@anuma/sdk 6.15.0 → 6.15.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/expo/{chunk-3V3BBJLH.mjs → chunk-4Z2X4UYQ.mjs} +7 -1
- package/dist/expo/{chunk-DIUQLXEH.mjs → chunk-A2G6TRUK.mjs} +1 -1
- package/dist/expo/{chunk-LUSKQQDD.mjs → chunk-JXN7LD6B.mjs} +41 -17
- package/dist/{react/consolidate-Y2XWEZRQ.mjs → expo/consolidate-ZM5JNULQ.mjs} +2 -2
- package/dist/expo/index.cjs +179 -104
- package/dist/expo/index.mjs +143 -92
- package/dist/expo/{recall-GKYVPD2B.mjs → recall-TGRI5MN4.mjs} +2 -2
- package/dist/react/{chunk-3V3BBJLH.mjs → chunk-4Z2X4UYQ.mjs} +7 -1
- package/dist/react/{chunk-2GNOTRG4.mjs → chunk-7X7BNMGS.mjs} +1 -1
- package/dist/react/{chunk-PDKKPAXP.mjs → chunk-TVPCH7ZZ.mjs} +45 -21
- package/dist/{expo/consolidate-GTMXZZ4C.mjs → react/consolidate-7NMKF7UC.mjs} +2 -2
- package/dist/react/index.cjs +183 -108
- package/dist/react/index.mjs +143 -92
- package/dist/react/{recall-5HNAFHLL.mjs → recall-OKNLU335.mjs} +2 -2
- package/dist/server/{chunk-JPLFOSB2.mjs → chunk-4LPSEROP.mjs} +1 -1
- package/dist/server/{chunk-H4G3DLDJ.mjs → chunk-BSCEZOIW.mjs} +7 -1
- package/dist/server/{chunk-2QFK4L7Y.mjs → chunk-K7H7ICPK.mjs} +21 -21
- package/dist/server/{consolidate-CMMDTZ37.mjs → consolidate-MSAXASHL.mjs} +2 -2
- package/dist/server/index.cjs +136 -93
- package/dist/server/index.mjs +118 -77
- package/dist/server/{recall-EODNEKIA.mjs → recall-YXJATOSD.mjs} +2 -2
- package/package.json +1 -1
package/dist/server/index.cjs
CHANGED
|
@@ -16830,14 +16830,14 @@ function resolveChunkText(content, chunk, chunksInRow) {
|
|
|
16830
16830
|
if (covered !== content.length) return content;
|
|
16831
16831
|
return content.slice(start, end);
|
|
16832
16832
|
}
|
|
16833
|
-
async function
|
|
16834
|
-
const
|
|
16835
|
-
if (!
|
|
16836
|
-
if (walletAddress && isEncrypted(
|
|
16837
|
-
return await decryptJsonField(
|
|
16833
|
+
async function readRawJsonField(raw, column, walletAddress) {
|
|
16834
|
+
const value = raw[column];
|
|
16835
|
+
if (!value) return void 0;
|
|
16836
|
+
if (walletAddress && isEncrypted(value)) {
|
|
16837
|
+
return await decryptJsonField(value, walletAddress);
|
|
16838
16838
|
}
|
|
16839
16839
|
try {
|
|
16840
|
-
return JSON.parse(
|
|
16840
|
+
return JSON.parse(value);
|
|
16841
16841
|
} catch {
|
|
16842
16842
|
return void 0;
|
|
16843
16843
|
}
|
|
@@ -16850,12 +16850,12 @@ async function searchMessagesOp(ctx, queryVector, options) {
|
|
|
16850
16850
|
activeConversations.map((c) => String(c._getRaw("conversation_id")))
|
|
16851
16851
|
);
|
|
16852
16852
|
const queryConditions = conversationId ? [import_watermelondb14.Q.where("conversation_id", conversationId)] : [];
|
|
16853
|
-
const messages = await ctx.messagesCollection.query(...queryConditions).
|
|
16853
|
+
const messages = await ctx.messagesCollection.query(...queryConditions).unsafeFetchRaw();
|
|
16854
16854
|
const candidates = [];
|
|
16855
16855
|
for (const message of messages) {
|
|
16856
|
-
const msgConvId = String(message.
|
|
16856
|
+
const msgConvId = String(message.conversation_id);
|
|
16857
16857
|
if (!activeConversationIds.has(msgConvId)) continue;
|
|
16858
|
-
const messageVector = await
|
|
16858
|
+
const messageVector = await readRawJsonField(message, "vector", ctx.walletAddress);
|
|
16859
16859
|
if (!messageVector || messageVector.length === 0) continue;
|
|
16860
16860
|
const similarity = cosineSimilarity(queryVector, messageVector);
|
|
16861
16861
|
if (similarity >= minSimilarity) {
|
|
@@ -16865,7 +16865,7 @@ async function searchMessagesOp(ctx, queryVector, options) {
|
|
|
16865
16865
|
const topK = candidates.sort((a, b) => b.similarity - a.similarity).slice(0, limit);
|
|
16866
16866
|
return Promise.all(
|
|
16867
16867
|
topK.map(async ({ message, similarity }) => {
|
|
16868
|
-
const stored = await
|
|
16868
|
+
const stored = await messageRawToStored(
|
|
16869
16869
|
message,
|
|
16870
16870
|
ctx.walletAddress,
|
|
16871
16871
|
ctx.signMessage,
|
|
@@ -16889,21 +16889,21 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
16889
16889
|
activeConversations.map((c) => String(c._getRaw("conversation_id")))
|
|
16890
16890
|
);
|
|
16891
16891
|
const queryConditions = conversationId ? [import_watermelondb14.Q.where("conversation_id", conversationId)] : [];
|
|
16892
|
-
const messages = await ctx.messagesCollection.query(...queryConditions).
|
|
16892
|
+
const messages = await ctx.messagesCollection.query(...queryConditions).unsafeFetchRaw();
|
|
16893
16893
|
const candidates = [];
|
|
16894
16894
|
let staleSkipped = 0;
|
|
16895
16895
|
let unreadableVectors = 0;
|
|
16896
16896
|
for (const message of messages) {
|
|
16897
|
-
const msgConvId = String(message.
|
|
16897
|
+
const msgConvId = String(message.conversation_id);
|
|
16898
16898
|
if (!activeConversationIds.has(msgConvId)) continue;
|
|
16899
16899
|
if (embeddingModel) {
|
|
16900
|
-
const storedModel = message.
|
|
16900
|
+
const storedModel = message.embedding_model;
|
|
16901
16901
|
if (storedModel !== null && storedModel !== void 0 && storedModel !== embeddingModel) {
|
|
16902
16902
|
staleSkipped++;
|
|
16903
16903
|
continue;
|
|
16904
16904
|
}
|
|
16905
16905
|
}
|
|
16906
|
-
const version = Number(message.
|
|
16906
|
+
const version = Number(message.updated_at) || 0;
|
|
16907
16907
|
const cached = chunkCache?.get(message.id);
|
|
16908
16908
|
if (cached && cached.version === version) {
|
|
16909
16909
|
if (cached.chunks.length > 0) {
|
|
@@ -16927,7 +16927,7 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
16927
16927
|
}
|
|
16928
16928
|
continue;
|
|
16929
16929
|
}
|
|
16930
|
-
const chunks = await
|
|
16930
|
+
const chunks = await readRawJsonField(message, "chunks", ctx.walletAddress);
|
|
16931
16931
|
if (chunks && chunks.length > 0) {
|
|
16932
16932
|
const vectors = chunks.map(
|
|
16933
16933
|
(chunk) => decodeChunkVector(chunk.vector, () => {
|
|
@@ -16948,7 +16948,7 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
16948
16948
|
}
|
|
16949
16949
|
}
|
|
16950
16950
|
} else {
|
|
16951
|
-
const messageVector = await
|
|
16951
|
+
const messageVector = await readRawJsonField(message, "vector", ctx.walletAddress);
|
|
16952
16952
|
if (!messageVector || messageVector.length === 0) continue;
|
|
16953
16953
|
const fallback = Float32Array.from(messageVector);
|
|
16954
16954
|
chunkCache?.set(message.id, { version, chunks: [], fallback });
|
|
@@ -16974,7 +16974,7 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
16974
16974
|
const storedById = new Map(
|
|
16975
16975
|
await Promise.all(
|
|
16976
16976
|
Array.from(uniqueMessages, async ([id, m]) => {
|
|
16977
|
-
const stored = await
|
|
16977
|
+
const stored = await messageRawToStored(
|
|
16978
16978
|
m,
|
|
16979
16979
|
ctx.walletAddress,
|
|
16980
16980
|
ctx.signMessage,
|
|
@@ -16992,8 +16992,8 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
16992
16992
|
await Promise.all(
|
|
16993
16993
|
Array.from(needsChunkText, async (id) => {
|
|
16994
16994
|
const m = uniqueMessages.get(id);
|
|
16995
|
-
const parsed = await
|
|
16996
|
-
const version = Number(m.
|
|
16995
|
+
const parsed = await readRawJsonField(m, "chunks", ctx.walletAddress);
|
|
16996
|
+
const version = Number(m.updated_at) || 0;
|
|
16997
16997
|
if (parsed) chunkStateByMsgId.set(id, { version, chunks: parsed });
|
|
16998
16998
|
})
|
|
16999
16999
|
);
|
|
@@ -20611,6 +20611,9 @@ function supportsResponseFormat(model, variant = "json_object") {
|
|
|
20611
20611
|
const allow = variant === "json_schema" ? RESPONSE_SCHEMA_OK : RESPONSE_FORMAT_OK;
|
|
20612
20612
|
return model.split("/").some((seg) => allow.has(seg));
|
|
20613
20613
|
}
|
|
20614
|
+
function requiresResponsesTransport(model) {
|
|
20615
|
+
return model.split("/").some((seg) => RESPONSES_ONLY_MODEL_PREFIXES.some((prefix) => seg.startsWith(prefix)));
|
|
20616
|
+
}
|
|
20614
20617
|
function responsesExtra(extra) {
|
|
20615
20618
|
if (!extra) return {};
|
|
20616
20619
|
const out = {};
|
|
@@ -20946,7 +20949,7 @@ function extractResponsesContent(body) {
|
|
|
20946
20949
|
const text12 = root.output.filter((item) => asRecord(item)?.type === "message").flatMap((item) => Array.isArray(item.content) ? item.content : []).map((part) => asRecord(part)?.text).filter((t) => typeof t === "string").join("");
|
|
20947
20950
|
return text12;
|
|
20948
20951
|
}
|
|
20949
|
-
var RESPONSE_FORMAT_OK, RESPONSE_SCHEMA_OK, JSON_CONTRACT_REMINDER, CHAT_TO_RESPONSES_FIELDS, FOREIGN_ENDPOINT_SUFFIX, RETRYABLE_HTTP;
|
|
20952
|
+
var RESPONSE_FORMAT_OK, RESPONSE_SCHEMA_OK, JSON_CONTRACT_REMINDER, RESPONSES_ONLY_MODEL_PREFIXES, CHAT_TO_RESPONSES_FIELDS, FOREIGN_ENDPOINT_SUFFIX, RETRYABLE_HTTP;
|
|
20950
20953
|
var init_portalLlm = __esm({
|
|
20951
20954
|
"src/lib/memory/portalLlm.ts"() {
|
|
20952
20955
|
"use strict";
|
|
@@ -20958,6 +20961,7 @@ var init_portalLlm = __esm({
|
|
|
20958
20961
|
RESPONSE_FORMAT_OK = /* @__PURE__ */ new Set(["openai", "inclusionai", "deepseek"]);
|
|
20959
20962
|
RESPONSE_SCHEMA_OK = /* @__PURE__ */ new Set(["openai"]);
|
|
20960
20963
|
JSON_CONTRACT_REMINDER = "Output ONLY the strict JSON object requested. No prose, no explanation, no markdown.";
|
|
20964
|
+
RESPONSES_ONLY_MODEL_PREFIXES = ["gpt-5.6"];
|
|
20961
20965
|
CHAT_TO_RESPONSES_FIELDS = {
|
|
20962
20966
|
max_completion_tokens: "max_output_tokens"
|
|
20963
20967
|
};
|
|
@@ -30733,6 +30737,9 @@ var DEFAULT_BASE_URL2 = BASE_URL;
|
|
|
30733
30737
|
var DEFAULT_MODEL4 = "anthropic/claude-sonnet-4-6";
|
|
30734
30738
|
var DEFAULT_MAX_TOKENS = 4096;
|
|
30735
30739
|
var REQUEST_TIMEOUT_MS = 6e4;
|
|
30740
|
+
var MIN_RETRY_BUDGET_MS = 2e3;
|
|
30741
|
+
var MIN_RESPONSES_OUTPUT_TOKENS = 2048;
|
|
30742
|
+
var SCHEMA_FALLBACK_SKIP_STATUSES = /* @__PURE__ */ new Set([401, 403, 404, 408, 409, 413, 425, 429]);
|
|
30736
30743
|
var DEFAULT_SYSTEM_PROMPT = `You are a personal assistant with access to the user's memory. Answer the user's question using the supplied memories as evidence.
|
|
30737
30744
|
|
|
30738
30745
|
Rules:
|
|
@@ -30764,14 +30771,9 @@ ${m.content}`).join("\n\n");
|
|
|
30764
30771
|
const baseUrl = options.baseUrl ?? DEFAULT_BASE_URL2;
|
|
30765
30772
|
const model = options.llmModel ?? DEFAULT_MODEL4;
|
|
30766
30773
|
const wantsStructured = !!options.responseSchema;
|
|
30767
|
-
const
|
|
30774
|
+
const useResponsesTransport = requiresResponsesTransport(model);
|
|
30775
|
+
const sendResponseFormat = wantsStructured && !useResponsesTransport && supportsResponseFormat(model, "json_schema");
|
|
30768
30776
|
const basePrompt = options.systemPrompt ?? DEFAULT_SYSTEM_PROMPT;
|
|
30769
|
-
const systemPrompt = wantsStructured && !sendResponseFormat ? `${basePrompt}
|
|
30770
|
-
|
|
30771
|
-
Respond with ONLY a single JSON object conforming to this JSON Schema, with no prose, comments, or code fences:
|
|
30772
|
-
${JSON.stringify(
|
|
30773
|
-
options.responseSchema
|
|
30774
|
-
)}` : basePrompt;
|
|
30775
30777
|
const userMessage = [
|
|
30776
30778
|
`Question:
|
|
30777
30779
|
${trimmed}`,
|
|
@@ -30781,85 +30783,121 @@ ${evidence}`
|
|
|
30781
30783
|
].join("\n\n");
|
|
30782
30784
|
const maxTokens = options.maxTokens ?? DEFAULT_MAX_TOKENS;
|
|
30783
30785
|
const fetchImpl = options.fetchFn ?? fetch;
|
|
30786
|
+
const buildBody = (useResponseFormat) => {
|
|
30787
|
+
const systemPrompt = wantsStructured && !useResponseFormat ? `${basePrompt}
|
|
30788
|
+
|
|
30789
|
+
Respond with ONLY a single JSON object conforming to this JSON Schema, with no prose, comments, or code fences:
|
|
30790
|
+
${JSON.stringify(
|
|
30791
|
+
options.responseSchema
|
|
30792
|
+
)}` : basePrompt;
|
|
30793
|
+
const messages = [
|
|
30794
|
+
{ role: "system", content: systemPrompt },
|
|
30795
|
+
{ role: "user", content: userMessage }
|
|
30796
|
+
];
|
|
30797
|
+
if (useResponsesTransport) {
|
|
30798
|
+
return JSON.stringify({
|
|
30799
|
+
model,
|
|
30800
|
+
// Same system+user pair under the Responses-API field names: `input`
|
|
30801
|
+
// for the turns, `max_output_tokens` for the cap. Sending the
|
|
30802
|
+
// chat-completions spelling here is silently ignored, which caps the
|
|
30803
|
+
// answer at the portal default.
|
|
30804
|
+
input: messages,
|
|
30805
|
+
max_output_tokens: Math.max(maxTokens, MIN_RESPONSES_OUTPUT_TOKENS)
|
|
30806
|
+
});
|
|
30807
|
+
}
|
|
30808
|
+
return JSON.stringify({
|
|
30809
|
+
model,
|
|
30810
|
+
// Modern OpenAI field; the portal reads only `max_completion_tokens`
|
|
30811
|
+
// (the deprecated `max_tokens` is silently ignored → falls back to the
|
|
30812
|
+
// portal's default output cap and truncates the answer).
|
|
30813
|
+
max_completion_tokens: maxTokens,
|
|
30814
|
+
messages,
|
|
30815
|
+
...useResponseFormat && {
|
|
30816
|
+
response_format: {
|
|
30817
|
+
type: "json_schema",
|
|
30818
|
+
json_schema: { name: "reflect_output", schema: options.responseSchema }
|
|
30819
|
+
}
|
|
30820
|
+
}
|
|
30821
|
+
});
|
|
30822
|
+
};
|
|
30784
30823
|
const log = getLogger();
|
|
30785
30824
|
const authHeaders = await resolvePortalAuthHeaders(options, "memory/reflect");
|
|
30786
30825
|
if (authHeaders === null) return baseResult;
|
|
30787
|
-
const controller = new AbortController();
|
|
30788
30826
|
const deadline = Date.now() + REQUEST_TIMEOUT_MS;
|
|
30789
30827
|
const remaining = () => Math.max(0, deadline - Date.now());
|
|
30790
|
-
const
|
|
30791
|
-
|
|
30792
|
-
|
|
30793
|
-
|
|
30794
|
-
|
|
30795
|
-
|
|
30796
|
-
|
|
30797
|
-
|
|
30798
|
-
|
|
30799
|
-
|
|
30800
|
-
|
|
30801
|
-
|
|
30802
|
-
|
|
30803
|
-
|
|
30804
|
-
|
|
30805
|
-
|
|
30806
|
-
|
|
30807
|
-
|
|
30808
|
-
|
|
30809
|
-
|
|
30810
|
-
|
|
30811
|
-
|
|
30812
|
-
|
|
30813
|
-
|
|
30814
|
-
|
|
30815
|
-
|
|
30816
|
-
}
|
|
30817
|
-
}
|
|
30818
|
-
}),
|
|
30819
|
-
signal: controller.signal
|
|
30820
|
-
});
|
|
30821
|
-
} catch (err) {
|
|
30828
|
+
const endpoint = useResponsesTransport ? "/api/v1/responses" : "/api/v1/chat/completions";
|
|
30829
|
+
const sendOnce = async (useResponseFormat) => {
|
|
30830
|
+
const controller = new AbortController();
|
|
30831
|
+
const timer = setTimeout(() => controller.abort(), remaining());
|
|
30832
|
+
let response;
|
|
30833
|
+
try {
|
|
30834
|
+
response = await fetchImpl(`${baseUrl}${endpoint}`, {
|
|
30835
|
+
method: "POST",
|
|
30836
|
+
// No task type unless the caller named one — an undeclared task adds no
|
|
30837
|
+
// header at all, which is what keeps user-facing reflect() unlabelled.
|
|
30838
|
+
headers: {
|
|
30839
|
+
...authHeaders,
|
|
30840
|
+
...taskTypeHeader(options.taskType),
|
|
30841
|
+
"Content-Type": "application/json"
|
|
30842
|
+
},
|
|
30843
|
+
body: buildBody(useResponseFormat),
|
|
30844
|
+
signal: controller.signal
|
|
30845
|
+
});
|
|
30846
|
+
} catch (err) {
|
|
30847
|
+
clearTimeout(timer);
|
|
30848
|
+
log.warn("[memory/reflect] portal request failed", {
|
|
30849
|
+
err: err instanceof Error ? err.message : String(err),
|
|
30850
|
+
baseUrl
|
|
30851
|
+
});
|
|
30852
|
+
return { kind: "error" };
|
|
30853
|
+
}
|
|
30822
30854
|
clearTimeout(timer);
|
|
30823
|
-
|
|
30824
|
-
|
|
30825
|
-
|
|
30855
|
+
if (!response.ok) {
|
|
30856
|
+
return { kind: "http", status: response.status, statusText: response.statusText };
|
|
30857
|
+
}
|
|
30858
|
+
const bodyTimer = setTimeout(() => controller.abort(), remaining());
|
|
30859
|
+
try {
|
|
30860
|
+
const body = await response.json();
|
|
30861
|
+
clearTimeout(bodyTimer);
|
|
30862
|
+
return { kind: "ok", body };
|
|
30863
|
+
} catch (err) {
|
|
30864
|
+
clearTimeout(bodyTimer);
|
|
30865
|
+
log.warn("[memory/reflect] failed to parse portal response body", {
|
|
30866
|
+
err: err instanceof Error ? err.message : String(err)
|
|
30867
|
+
});
|
|
30868
|
+
return { kind: "error" };
|
|
30869
|
+
}
|
|
30870
|
+
};
|
|
30871
|
+
let attempt = await sendOnce(sendResponseFormat);
|
|
30872
|
+
let schemaFallbackUsed = false;
|
|
30873
|
+
const budgetLeftMs = remaining();
|
|
30874
|
+
if (attempt.kind === "http" && sendResponseFormat && !SCHEMA_FALLBACK_SKIP_STATUSES.has(attempt.status) && budgetLeftMs >= MIN_RETRY_BUDGET_MS) {
|
|
30875
|
+
log.warn("[memory/reflect] response_format json_schema rejected; retrying schema-in-prompt", {
|
|
30876
|
+
status: attempt.status,
|
|
30877
|
+
statusText: attempt.statusText,
|
|
30878
|
+
model,
|
|
30879
|
+
taskType: options.taskType,
|
|
30880
|
+
budgetLeftMs
|
|
30826
30881
|
});
|
|
30827
|
-
|
|
30882
|
+
schemaFallbackUsed = true;
|
|
30883
|
+
attempt = await sendOnce(false);
|
|
30828
30884
|
}
|
|
30829
|
-
|
|
30830
|
-
if (
|
|
30885
|
+
if (attempt.kind === "error") return baseResult;
|
|
30886
|
+
if (attempt.kind === "http") {
|
|
30831
30887
|
log.warn("[memory/reflect] portal returned non-OK", {
|
|
30832
|
-
status:
|
|
30833
|
-
statusText:
|
|
30888
|
+
status: attempt.status,
|
|
30889
|
+
statusText: attempt.statusText,
|
|
30890
|
+
// Distinguishes "the fallback ran and still failed" from "never tried".
|
|
30891
|
+
schemaFallbackUsed
|
|
30834
30892
|
});
|
|
30835
30893
|
return baseResult;
|
|
30836
30894
|
}
|
|
30837
|
-
|
|
30838
|
-
let body;
|
|
30839
|
-
try {
|
|
30840
|
-
body = await response.json();
|
|
30841
|
-
} catch (err) {
|
|
30842
|
-
clearTimeout(bodyTimer);
|
|
30843
|
-
log.warn("[memory/reflect] failed to parse portal response body", {
|
|
30844
|
-
err: err instanceof Error ? err.message : String(err)
|
|
30845
|
-
});
|
|
30846
|
-
return baseResult;
|
|
30847
|
-
}
|
|
30848
|
-
clearTimeout(bodyTimer);
|
|
30849
|
-
return parseAnswer(body, baseResult, !!options.responseSchema);
|
|
30895
|
+
return parseAnswer(attempt.body, baseResult, !!options.responseSchema);
|
|
30850
30896
|
}
|
|
30851
30897
|
function parseAnswer(body, base, parseSchema) {
|
|
30852
30898
|
if (typeof body !== "object" || body === null) return base;
|
|
30853
30899
|
const obj = body;
|
|
30854
|
-
const
|
|
30855
|
-
let text12 = "";
|
|
30856
|
-
if (Array.isArray(choices) && choices.length > 0) {
|
|
30857
|
-
const message = choices[0].message;
|
|
30858
|
-
if (typeof message === "object" && message !== null) {
|
|
30859
|
-
const content = message.content;
|
|
30860
|
-
if (typeof content === "string") text12 = content;
|
|
30861
|
-
}
|
|
30862
|
-
}
|
|
30900
|
+
const text12 = extractCompletionContent(obj) ?? "";
|
|
30863
30901
|
const usage = obj.usage;
|
|
30864
30902
|
let structuredOutput;
|
|
30865
30903
|
if (parseSchema && text12) {
|
|
@@ -30871,14 +30909,19 @@ function parseAnswer(body, base, parseSchema) {
|
|
|
30871
30909
|
});
|
|
30872
30910
|
}
|
|
30873
30911
|
}
|
|
30912
|
+
const promptTokens = usage?.prompt_tokens ?? usage?.input_tokens ?? 0;
|
|
30913
|
+
const completionTokens = usage?.completion_tokens ?? usage?.output_tokens ?? 0;
|
|
30874
30914
|
return {
|
|
30875
30915
|
text: text12,
|
|
30876
30916
|
...structuredOutput !== void 0 && { structuredOutput },
|
|
30877
30917
|
basedOn: base.basedOn,
|
|
30878
30918
|
usage: {
|
|
30879
|
-
promptTokens
|
|
30880
|
-
completionTokens
|
|
30881
|
-
|
|
30919
|
+
promptTokens,
|
|
30920
|
+
completionTokens,
|
|
30921
|
+
// Derived when absent: the Responses API reports the two component counts
|
|
30922
|
+
// and does not always send a total, which would otherwise report zero
|
|
30923
|
+
// spend for a call that plainly cost something.
|
|
30924
|
+
totalTokens: usage?.total_tokens ?? promptTokens + completionTokens
|
|
30882
30925
|
}
|
|
30883
30926
|
};
|
|
30884
30927
|
}
|
package/dist/server/index.mjs
CHANGED
|
@@ -141,23 +141,25 @@ import {
|
|
|
141
141
|
updateVaultMemoryOp,
|
|
142
142
|
upsertMessageOp,
|
|
143
143
|
vaultMemoryToStored
|
|
144
|
-
} from "./chunk-
|
|
144
|
+
} from "./chunk-K7H7ICPK.mjs";
|
|
145
145
|
import {
|
|
146
146
|
createStreamingDeAnonymizer,
|
|
147
147
|
notifyConsolidationFallback,
|
|
148
148
|
resolvePiiRedactor
|
|
149
|
-
} from "./chunk-
|
|
149
|
+
} from "./chunk-4LPSEROP.mjs";
|
|
150
150
|
import {
|
|
151
151
|
INTERNAL_FLOW_MARKER,
|
|
152
152
|
callPortalJsonCompletion,
|
|
153
|
+
extractCompletionContent,
|
|
153
154
|
extractJsonCandidate,
|
|
154
155
|
getLogger,
|
|
156
|
+
requiresResponsesTransport,
|
|
155
157
|
resolvePortalAuthHeaders,
|
|
156
158
|
supportsResponseFormat,
|
|
157
159
|
taskTypeHeader,
|
|
158
160
|
validateEndpointOverride,
|
|
159
161
|
withInternalFlowMarker
|
|
160
|
-
} from "./chunk-
|
|
162
|
+
} from "./chunk-BSCEZOIW.mjs";
|
|
161
163
|
import {
|
|
162
164
|
BASE_URL,
|
|
163
165
|
__commonJS,
|
|
@@ -5700,7 +5702,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
5700
5702
|
content: m.content,
|
|
5701
5703
|
similarity: m.similarity
|
|
5702
5704
|
}));
|
|
5703
|
-
const { consolidateMemory: doConsolidate } = await import("./consolidate-
|
|
5705
|
+
const { consolidateMemory: doConsolidate } = await import("./consolidate-MSAXASHL.mjs");
|
|
5704
5706
|
const decision = await doConsolidate(trimmed, candidates, consolidateOptions);
|
|
5705
5707
|
if (decision.action === "create") return null;
|
|
5706
5708
|
if (decision.action === "supersede" && decision.content) {
|
|
@@ -6924,6 +6926,9 @@ var DEFAULT_BASE_URL = BASE_URL;
|
|
|
6924
6926
|
var DEFAULT_MODEL3 = "anthropic/claude-sonnet-4-6";
|
|
6925
6927
|
var DEFAULT_MAX_TOKENS = 4096;
|
|
6926
6928
|
var REQUEST_TIMEOUT_MS = 6e4;
|
|
6929
|
+
var MIN_RETRY_BUDGET_MS = 2e3;
|
|
6930
|
+
var MIN_RESPONSES_OUTPUT_TOKENS = 2048;
|
|
6931
|
+
var SCHEMA_FALLBACK_SKIP_STATUSES = /* @__PURE__ */ new Set([401, 403, 404, 408, 409, 413, 425, 429]);
|
|
6927
6932
|
var DEFAULT_SYSTEM_PROMPT = `You are a personal assistant with access to the user's memory. Answer the user's question using the supplied memories as evidence.
|
|
6928
6933
|
|
|
6929
6934
|
Rules:
|
|
@@ -6955,14 +6960,9 @@ ${m.content}`).join("\n\n");
|
|
|
6955
6960
|
const baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;
|
|
6956
6961
|
const model = options.llmModel ?? DEFAULT_MODEL3;
|
|
6957
6962
|
const wantsStructured = !!options.responseSchema;
|
|
6958
|
-
const
|
|
6963
|
+
const useResponsesTransport = requiresResponsesTransport(model);
|
|
6964
|
+
const sendResponseFormat = wantsStructured && !useResponsesTransport && supportsResponseFormat(model, "json_schema");
|
|
6959
6965
|
const basePrompt = options.systemPrompt ?? DEFAULT_SYSTEM_PROMPT;
|
|
6960
|
-
const systemPrompt = wantsStructured && !sendResponseFormat ? `${basePrompt}
|
|
6961
|
-
|
|
6962
|
-
Respond with ONLY a single JSON object conforming to this JSON Schema, with no prose, comments, or code fences:
|
|
6963
|
-
${JSON.stringify(
|
|
6964
|
-
options.responseSchema
|
|
6965
|
-
)}` : basePrompt;
|
|
6966
6966
|
const userMessage = [
|
|
6967
6967
|
`Question:
|
|
6968
6968
|
${trimmed}`,
|
|
@@ -6972,85 +6972,121 @@ ${evidence}`
|
|
|
6972
6972
|
].join("\n\n");
|
|
6973
6973
|
const maxTokens = options.maxTokens ?? DEFAULT_MAX_TOKENS;
|
|
6974
6974
|
const fetchImpl = options.fetchFn ?? fetch;
|
|
6975
|
+
const buildBody = (useResponseFormat) => {
|
|
6976
|
+
const systemPrompt = wantsStructured && !useResponseFormat ? `${basePrompt}
|
|
6977
|
+
|
|
6978
|
+
Respond with ONLY a single JSON object conforming to this JSON Schema, with no prose, comments, or code fences:
|
|
6979
|
+
${JSON.stringify(
|
|
6980
|
+
options.responseSchema
|
|
6981
|
+
)}` : basePrompt;
|
|
6982
|
+
const messages = [
|
|
6983
|
+
{ role: "system", content: systemPrompt },
|
|
6984
|
+
{ role: "user", content: userMessage }
|
|
6985
|
+
];
|
|
6986
|
+
if (useResponsesTransport) {
|
|
6987
|
+
return JSON.stringify({
|
|
6988
|
+
model,
|
|
6989
|
+
// Same system+user pair under the Responses-API field names: `input`
|
|
6990
|
+
// for the turns, `max_output_tokens` for the cap. Sending the
|
|
6991
|
+
// chat-completions spelling here is silently ignored, which caps the
|
|
6992
|
+
// answer at the portal default.
|
|
6993
|
+
input: messages,
|
|
6994
|
+
max_output_tokens: Math.max(maxTokens, MIN_RESPONSES_OUTPUT_TOKENS)
|
|
6995
|
+
});
|
|
6996
|
+
}
|
|
6997
|
+
return JSON.stringify({
|
|
6998
|
+
model,
|
|
6999
|
+
// Modern OpenAI field; the portal reads only `max_completion_tokens`
|
|
7000
|
+
// (the deprecated `max_tokens` is silently ignored → falls back to the
|
|
7001
|
+
// portal's default output cap and truncates the answer).
|
|
7002
|
+
max_completion_tokens: maxTokens,
|
|
7003
|
+
messages,
|
|
7004
|
+
...useResponseFormat && {
|
|
7005
|
+
response_format: {
|
|
7006
|
+
type: "json_schema",
|
|
7007
|
+
json_schema: { name: "reflect_output", schema: options.responseSchema }
|
|
7008
|
+
}
|
|
7009
|
+
}
|
|
7010
|
+
});
|
|
7011
|
+
};
|
|
6975
7012
|
const log = getLogger();
|
|
6976
7013
|
const authHeaders = await resolvePortalAuthHeaders(options, "memory/reflect");
|
|
6977
7014
|
if (authHeaders === null) return baseResult;
|
|
6978
|
-
const controller = new AbortController();
|
|
6979
7015
|
const deadline = Date.now() + REQUEST_TIMEOUT_MS;
|
|
6980
7016
|
const remaining = () => Math.max(0, deadline - Date.now());
|
|
6981
|
-
const
|
|
6982
|
-
|
|
6983
|
-
|
|
6984
|
-
|
|
6985
|
-
|
|
6986
|
-
|
|
6987
|
-
|
|
6988
|
-
|
|
6989
|
-
|
|
6990
|
-
|
|
6991
|
-
|
|
6992
|
-
|
|
6993
|
-
|
|
6994
|
-
|
|
6995
|
-
|
|
6996
|
-
|
|
6997
|
-
|
|
6998
|
-
|
|
6999
|
-
|
|
7000
|
-
|
|
7001
|
-
|
|
7002
|
-
|
|
7003
|
-
|
|
7004
|
-
|
|
7005
|
-
|
|
7006
|
-
|
|
7007
|
-
}
|
|
7008
|
-
}
|
|
7009
|
-
}),
|
|
7010
|
-
signal: controller.signal
|
|
7011
|
-
});
|
|
7012
|
-
} catch (err) {
|
|
7017
|
+
const endpoint = useResponsesTransport ? "/api/v1/responses" : "/api/v1/chat/completions";
|
|
7018
|
+
const sendOnce = async (useResponseFormat) => {
|
|
7019
|
+
const controller = new AbortController();
|
|
7020
|
+
const timer = setTimeout(() => controller.abort(), remaining());
|
|
7021
|
+
let response;
|
|
7022
|
+
try {
|
|
7023
|
+
response = await fetchImpl(`${baseUrl}${endpoint}`, {
|
|
7024
|
+
method: "POST",
|
|
7025
|
+
// No task type unless the caller named one — an undeclared task adds no
|
|
7026
|
+
// header at all, which is what keeps user-facing reflect() unlabelled.
|
|
7027
|
+
headers: {
|
|
7028
|
+
...authHeaders,
|
|
7029
|
+
...taskTypeHeader(options.taskType),
|
|
7030
|
+
"Content-Type": "application/json"
|
|
7031
|
+
},
|
|
7032
|
+
body: buildBody(useResponseFormat),
|
|
7033
|
+
signal: controller.signal
|
|
7034
|
+
});
|
|
7035
|
+
} catch (err) {
|
|
7036
|
+
clearTimeout(timer);
|
|
7037
|
+
log.warn("[memory/reflect] portal request failed", {
|
|
7038
|
+
err: err instanceof Error ? err.message : String(err),
|
|
7039
|
+
baseUrl
|
|
7040
|
+
});
|
|
7041
|
+
return { kind: "error" };
|
|
7042
|
+
}
|
|
7013
7043
|
clearTimeout(timer);
|
|
7014
|
-
|
|
7015
|
-
|
|
7016
|
-
|
|
7044
|
+
if (!response.ok) {
|
|
7045
|
+
return { kind: "http", status: response.status, statusText: response.statusText };
|
|
7046
|
+
}
|
|
7047
|
+
const bodyTimer = setTimeout(() => controller.abort(), remaining());
|
|
7048
|
+
try {
|
|
7049
|
+
const body = await response.json();
|
|
7050
|
+
clearTimeout(bodyTimer);
|
|
7051
|
+
return { kind: "ok", body };
|
|
7052
|
+
} catch (err) {
|
|
7053
|
+
clearTimeout(bodyTimer);
|
|
7054
|
+
log.warn("[memory/reflect] failed to parse portal response body", {
|
|
7055
|
+
err: err instanceof Error ? err.message : String(err)
|
|
7056
|
+
});
|
|
7057
|
+
return { kind: "error" };
|
|
7058
|
+
}
|
|
7059
|
+
};
|
|
7060
|
+
let attempt = await sendOnce(sendResponseFormat);
|
|
7061
|
+
let schemaFallbackUsed = false;
|
|
7062
|
+
const budgetLeftMs = remaining();
|
|
7063
|
+
if (attempt.kind === "http" && sendResponseFormat && !SCHEMA_FALLBACK_SKIP_STATUSES.has(attempt.status) && budgetLeftMs >= MIN_RETRY_BUDGET_MS) {
|
|
7064
|
+
log.warn("[memory/reflect] response_format json_schema rejected; retrying schema-in-prompt", {
|
|
7065
|
+
status: attempt.status,
|
|
7066
|
+
statusText: attempt.statusText,
|
|
7067
|
+
model,
|
|
7068
|
+
taskType: options.taskType,
|
|
7069
|
+
budgetLeftMs
|
|
7017
7070
|
});
|
|
7018
|
-
|
|
7071
|
+
schemaFallbackUsed = true;
|
|
7072
|
+
attempt = await sendOnce(false);
|
|
7019
7073
|
}
|
|
7020
|
-
|
|
7021
|
-
if (
|
|
7074
|
+
if (attempt.kind === "error") return baseResult;
|
|
7075
|
+
if (attempt.kind === "http") {
|
|
7022
7076
|
log.warn("[memory/reflect] portal returned non-OK", {
|
|
7023
|
-
status:
|
|
7024
|
-
statusText:
|
|
7077
|
+
status: attempt.status,
|
|
7078
|
+
statusText: attempt.statusText,
|
|
7079
|
+
// Distinguishes "the fallback ran and still failed" from "never tried".
|
|
7080
|
+
schemaFallbackUsed
|
|
7025
7081
|
});
|
|
7026
7082
|
return baseResult;
|
|
7027
7083
|
}
|
|
7028
|
-
|
|
7029
|
-
let body;
|
|
7030
|
-
try {
|
|
7031
|
-
body = await response.json();
|
|
7032
|
-
} catch (err) {
|
|
7033
|
-
clearTimeout(bodyTimer);
|
|
7034
|
-
log.warn("[memory/reflect] failed to parse portal response body", {
|
|
7035
|
-
err: err instanceof Error ? err.message : String(err)
|
|
7036
|
-
});
|
|
7037
|
-
return baseResult;
|
|
7038
|
-
}
|
|
7039
|
-
clearTimeout(bodyTimer);
|
|
7040
|
-
return parseAnswer(body, baseResult, !!options.responseSchema);
|
|
7084
|
+
return parseAnswer(attempt.body, baseResult, !!options.responseSchema);
|
|
7041
7085
|
}
|
|
7042
7086
|
function parseAnswer(body, base, parseSchema) {
|
|
7043
7087
|
if (typeof body !== "object" || body === null) return base;
|
|
7044
7088
|
const obj = body;
|
|
7045
|
-
const
|
|
7046
|
-
let text12 = "";
|
|
7047
|
-
if (Array.isArray(choices) && choices.length > 0) {
|
|
7048
|
-
const message = choices[0].message;
|
|
7049
|
-
if (typeof message === "object" && message !== null) {
|
|
7050
|
-
const content = message.content;
|
|
7051
|
-
if (typeof content === "string") text12 = content;
|
|
7052
|
-
}
|
|
7053
|
-
}
|
|
7089
|
+
const text12 = extractCompletionContent(obj) ?? "";
|
|
7054
7090
|
const usage = obj.usage;
|
|
7055
7091
|
let structuredOutput;
|
|
7056
7092
|
if (parseSchema && text12) {
|
|
@@ -7062,14 +7098,19 @@ function parseAnswer(body, base, parseSchema) {
|
|
|
7062
7098
|
});
|
|
7063
7099
|
}
|
|
7064
7100
|
}
|
|
7101
|
+
const promptTokens = usage?.prompt_tokens ?? usage?.input_tokens ?? 0;
|
|
7102
|
+
const completionTokens = usage?.completion_tokens ?? usage?.output_tokens ?? 0;
|
|
7065
7103
|
return {
|
|
7066
7104
|
text: text12,
|
|
7067
7105
|
...structuredOutput !== void 0 && { structuredOutput },
|
|
7068
7106
|
basedOn: base.basedOn,
|
|
7069
7107
|
usage: {
|
|
7070
|
-
promptTokens
|
|
7071
|
-
completionTokens
|
|
7072
|
-
|
|
7108
|
+
promptTokens,
|
|
7109
|
+
completionTokens,
|
|
7110
|
+
// Derived when absent: the Responses API reports the two component counts
|
|
7111
|
+
// and does not always send a total, which would otherwise report zero
|
|
7112
|
+
// spend for a call that plainly cost something.
|
|
7113
|
+
totalTokens: usage?.total_tokens ?? promptTokens + completionTokens
|
|
7073
7114
|
}
|
|
7074
7115
|
};
|
|
7075
7116
|
}
|