@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
|
@@ -70,6 +70,10 @@ function supportsResponseFormat(model, variant = "json_object") {
|
|
|
70
70
|
const allow = variant === "json_schema" ? RESPONSE_SCHEMA_OK : RESPONSE_FORMAT_OK;
|
|
71
71
|
return model.split("/").some((seg) => allow.has(seg));
|
|
72
72
|
}
|
|
73
|
+
var RESPONSES_ONLY_MODEL_PREFIXES = ["gpt-5.6"];
|
|
74
|
+
function requiresResponsesTransport(model) {
|
|
75
|
+
return model.split("/").some((seg) => RESPONSES_ONLY_MODEL_PREFIXES.some((prefix) => seg.startsWith(prefix)));
|
|
76
|
+
}
|
|
73
77
|
var CHAT_TO_RESPONSES_FIELDS = {
|
|
74
78
|
max_completion_tokens: "max_output_tokens"
|
|
75
79
|
};
|
|
@@ -424,7 +428,9 @@ export {
|
|
|
424
428
|
withInternalFlowMarker,
|
|
425
429
|
taskTypeHeader,
|
|
426
430
|
supportsResponseFormat,
|
|
431
|
+
requiresResponsesTransport,
|
|
427
432
|
resolvePortalAuthHeaders,
|
|
428
433
|
callPortalJsonCompletion,
|
|
429
|
-
extractJsonCandidate
|
|
434
|
+
extractJsonCandidate,
|
|
435
|
+
extractCompletionContent
|
|
430
436
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
callPortalJsonCompletion,
|
|
3
3
|
getLogger
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-4Z2X4UYQ.mjs";
|
|
5
5
|
import {
|
|
6
6
|
BASE_URL,
|
|
7
7
|
createClientConfig
|
|
@@ -1680,6 +1680,29 @@ async function getMessageSkeletonsOp(ctx, convId) {
|
|
|
1680
1680
|
}
|
|
1681
1681
|
return skeletons;
|
|
1682
1682
|
}
|
|
1683
|
+
async function getToolCallEventIdsOp(ctx, convId) {
|
|
1684
|
+
const results = await ctx.messagesCollection.query(Q.where("conversation_id", convId)).unsafeFetchRaw();
|
|
1685
|
+
const ids = /* @__PURE__ */ new Set();
|
|
1686
|
+
for (const raw of results) {
|
|
1687
|
+
const value = raw.tool_call_events;
|
|
1688
|
+
if (!value) continue;
|
|
1689
|
+
let events;
|
|
1690
|
+
if (typeof value === "string") {
|
|
1691
|
+
try {
|
|
1692
|
+
events = JSON.parse(value);
|
|
1693
|
+
} catch {
|
|
1694
|
+
continue;
|
|
1695
|
+
}
|
|
1696
|
+
} else if (Array.isArray(value)) {
|
|
1697
|
+
events = value;
|
|
1698
|
+
}
|
|
1699
|
+
if (!Array.isArray(events)) continue;
|
|
1700
|
+
for (const evt of events) {
|
|
1701
|
+
if (evt && evt.id) ids.add(evt.id);
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
return ids;
|
|
1705
|
+
}
|
|
1683
1706
|
async function clearMessagesOp(ctx, convId) {
|
|
1684
1707
|
const messages = await ctx.messagesCollection.query(Q.where("conversation_id", convId)).fetch();
|
|
1685
1708
|
await ctx.database.write(async () => {
|
|
@@ -1918,14 +1941,14 @@ function resolveChunkText(content, chunk, chunksInRow) {
|
|
|
1918
1941
|
if (covered !== content.length) return content;
|
|
1919
1942
|
return content.slice(start, end);
|
|
1920
1943
|
}
|
|
1921
|
-
async function
|
|
1922
|
-
const
|
|
1923
|
-
if (!
|
|
1924
|
-
if (walletAddress && isEncrypted(
|
|
1925
|
-
return await decryptJsonField(
|
|
1944
|
+
async function readRawJsonField(raw, column, walletAddress) {
|
|
1945
|
+
const value = raw[column];
|
|
1946
|
+
if (!value) return void 0;
|
|
1947
|
+
if (walletAddress && isEncrypted(value)) {
|
|
1948
|
+
return await decryptJsonField(value, walletAddress);
|
|
1926
1949
|
}
|
|
1927
1950
|
try {
|
|
1928
|
-
return JSON.parse(
|
|
1951
|
+
return JSON.parse(value);
|
|
1929
1952
|
} catch {
|
|
1930
1953
|
return void 0;
|
|
1931
1954
|
}
|
|
@@ -1944,21 +1967,21 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
1944
1967
|
activeConversations.map((c) => String(c._getRaw("conversation_id")))
|
|
1945
1968
|
);
|
|
1946
1969
|
const queryConditions = conversationId ? [Q.where("conversation_id", conversationId)] : [];
|
|
1947
|
-
const messages = await ctx.messagesCollection.query(...queryConditions).
|
|
1970
|
+
const messages = await ctx.messagesCollection.query(...queryConditions).unsafeFetchRaw();
|
|
1948
1971
|
const candidates = [];
|
|
1949
1972
|
let staleSkipped = 0;
|
|
1950
1973
|
let unreadableVectors = 0;
|
|
1951
1974
|
for (const message of messages) {
|
|
1952
|
-
const msgConvId = String(message.
|
|
1975
|
+
const msgConvId = String(message.conversation_id);
|
|
1953
1976
|
if (!activeConversationIds.has(msgConvId)) continue;
|
|
1954
1977
|
if (embeddingModel) {
|
|
1955
|
-
const storedModel = message.
|
|
1978
|
+
const storedModel = message.embedding_model;
|
|
1956
1979
|
if (storedModel !== null && storedModel !== void 0 && storedModel !== embeddingModel) {
|
|
1957
1980
|
staleSkipped++;
|
|
1958
1981
|
continue;
|
|
1959
1982
|
}
|
|
1960
1983
|
}
|
|
1961
|
-
const version = Number(message.
|
|
1984
|
+
const version = Number(message.updated_at) || 0;
|
|
1962
1985
|
const cached = chunkCache?.get(message.id);
|
|
1963
1986
|
if (cached && cached.version === version) {
|
|
1964
1987
|
if (cached.chunks.length > 0) {
|
|
@@ -1982,7 +2005,7 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
1982
2005
|
}
|
|
1983
2006
|
continue;
|
|
1984
2007
|
}
|
|
1985
|
-
const chunks = await
|
|
2008
|
+
const chunks = await readRawJsonField(message, "chunks", ctx.walletAddress);
|
|
1986
2009
|
if (chunks && chunks.length > 0) {
|
|
1987
2010
|
const vectors = chunks.map(
|
|
1988
2011
|
(chunk) => decodeChunkVector(chunk.vector, () => {
|
|
@@ -2003,7 +2026,7 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
2003
2026
|
}
|
|
2004
2027
|
}
|
|
2005
2028
|
} else {
|
|
2006
|
-
const messageVector = await
|
|
2029
|
+
const messageVector = await readRawJsonField(message, "vector", ctx.walletAddress);
|
|
2007
2030
|
if (!messageVector || messageVector.length === 0) continue;
|
|
2008
2031
|
const fallback = Float32Array.from(messageVector);
|
|
2009
2032
|
chunkCache?.set(message.id, { version, chunks: [], fallback });
|
|
@@ -2029,7 +2052,7 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
2029
2052
|
const storedById = new Map(
|
|
2030
2053
|
await Promise.all(
|
|
2031
2054
|
Array.from(uniqueMessages, async ([id, m]) => {
|
|
2032
|
-
const stored = await
|
|
2055
|
+
const stored = await messageRawToStored(
|
|
2033
2056
|
m,
|
|
2034
2057
|
ctx.walletAddress,
|
|
2035
2058
|
ctx.signMessage,
|
|
@@ -2047,8 +2070,8 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
2047
2070
|
await Promise.all(
|
|
2048
2071
|
Array.from(needsChunkText, async (id) => {
|
|
2049
2072
|
const m = uniqueMessages.get(id);
|
|
2050
|
-
const parsed = await
|
|
2051
|
-
const version = Number(m.
|
|
2073
|
+
const parsed = await readRawJsonField(m, "chunks", ctx.walletAddress);
|
|
2074
|
+
const version = Number(m.updated_at) || 0;
|
|
2052
2075
|
if (parsed) chunkStateByMsgId.set(id, { version, chunks: parsed });
|
|
2053
2076
|
})
|
|
2054
2077
|
);
|
|
@@ -6885,7 +6908,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
6885
6908
|
subQueries = decomp.subQueries;
|
|
6886
6909
|
}
|
|
6887
6910
|
}
|
|
6888
|
-
const { recall: recall2 } = await import("./recall-
|
|
6911
|
+
const { recall: recall2 } = await import("./recall-TGRI5MN4.mjs");
|
|
6889
6912
|
let recallDegraded = [];
|
|
6890
6913
|
const result = await recall2(
|
|
6891
6914
|
query,
|
|
@@ -7889,6 +7912,7 @@ export {
|
|
|
7889
7912
|
getMessageCountOp,
|
|
7890
7913
|
getMessagesPageOp,
|
|
7891
7914
|
getMessageSkeletonsOp,
|
|
7915
|
+
getToolCallEventIdsOp,
|
|
7892
7916
|
clearMessagesOp,
|
|
7893
7917
|
createMessageOp,
|
|
7894
7918
|
upsertMessageOp,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
notifyConsolidationFallback,
|
|
3
3
|
resolvePiiRedactor
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-A2G6TRUK.mjs";
|
|
5
5
|
import {
|
|
6
6
|
callPortalJsonCompletion
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-4Z2X4UYQ.mjs";
|
|
8
8
|
import "./chunk-GYKJOWEO.mjs";
|
|
9
9
|
|
|
10
10
|
// src/lib/memory/consolidate.ts
|
package/dist/expo/index.cjs
CHANGED
|
@@ -1963,6 +1963,29 @@ async function getMessageSkeletonsOp(ctx, convId) {
|
|
|
1963
1963
|
}
|
|
1964
1964
|
return skeletons;
|
|
1965
1965
|
}
|
|
1966
|
+
async function getToolCallEventIdsOp(ctx, convId) {
|
|
1967
|
+
const results = await ctx.messagesCollection.query(import_watermelondb.Q.where("conversation_id", convId)).unsafeFetchRaw();
|
|
1968
|
+
const ids = /* @__PURE__ */ new Set();
|
|
1969
|
+
for (const raw of results) {
|
|
1970
|
+
const value = raw.tool_call_events;
|
|
1971
|
+
if (!value) continue;
|
|
1972
|
+
let events;
|
|
1973
|
+
if (typeof value === "string") {
|
|
1974
|
+
try {
|
|
1975
|
+
events = JSON.parse(value);
|
|
1976
|
+
} catch {
|
|
1977
|
+
continue;
|
|
1978
|
+
}
|
|
1979
|
+
} else if (Array.isArray(value)) {
|
|
1980
|
+
events = value;
|
|
1981
|
+
}
|
|
1982
|
+
if (!Array.isArray(events)) continue;
|
|
1983
|
+
for (const evt of events) {
|
|
1984
|
+
if (evt && evt.id) ids.add(evt.id);
|
|
1985
|
+
}
|
|
1986
|
+
}
|
|
1987
|
+
return ids;
|
|
1988
|
+
}
|
|
1966
1989
|
async function clearMessagesOp(ctx, convId) {
|
|
1967
1990
|
const messages = await ctx.messagesCollection.query(import_watermelondb.Q.where("conversation_id", convId)).fetch();
|
|
1968
1991
|
await ctx.database.write(async () => {
|
|
@@ -2201,14 +2224,14 @@ function resolveChunkText(content, chunk, chunksInRow) {
|
|
|
2201
2224
|
if (covered !== content.length) return content;
|
|
2202
2225
|
return content.slice(start, end);
|
|
2203
2226
|
}
|
|
2204
|
-
async function
|
|
2205
|
-
const
|
|
2206
|
-
if (!
|
|
2207
|
-
if (walletAddress && isEncrypted(
|
|
2208
|
-
return await decryptJsonField(
|
|
2227
|
+
async function readRawJsonField(raw, column, walletAddress) {
|
|
2228
|
+
const value = raw[column];
|
|
2229
|
+
if (!value) return void 0;
|
|
2230
|
+
if (walletAddress && isEncrypted(value)) {
|
|
2231
|
+
return await decryptJsonField(value, walletAddress);
|
|
2209
2232
|
}
|
|
2210
2233
|
try {
|
|
2211
|
-
return JSON.parse(
|
|
2234
|
+
return JSON.parse(value);
|
|
2212
2235
|
} catch {
|
|
2213
2236
|
return void 0;
|
|
2214
2237
|
}
|
|
@@ -2227,21 +2250,21 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
2227
2250
|
activeConversations.map((c) => String(c._getRaw("conversation_id")))
|
|
2228
2251
|
);
|
|
2229
2252
|
const queryConditions = conversationId ? [import_watermelondb.Q.where("conversation_id", conversationId)] : [];
|
|
2230
|
-
const messages = await ctx.messagesCollection.query(...queryConditions).
|
|
2253
|
+
const messages = await ctx.messagesCollection.query(...queryConditions).unsafeFetchRaw();
|
|
2231
2254
|
const candidates = [];
|
|
2232
2255
|
let staleSkipped = 0;
|
|
2233
2256
|
let unreadableVectors = 0;
|
|
2234
2257
|
for (const message of messages) {
|
|
2235
|
-
const msgConvId = String(message.
|
|
2258
|
+
const msgConvId = String(message.conversation_id);
|
|
2236
2259
|
if (!activeConversationIds.has(msgConvId)) continue;
|
|
2237
2260
|
if (embeddingModel) {
|
|
2238
|
-
const storedModel = message.
|
|
2261
|
+
const storedModel = message.embedding_model;
|
|
2239
2262
|
if (storedModel !== null && storedModel !== void 0 && storedModel !== embeddingModel) {
|
|
2240
2263
|
staleSkipped++;
|
|
2241
2264
|
continue;
|
|
2242
2265
|
}
|
|
2243
2266
|
}
|
|
2244
|
-
const version = Number(message.
|
|
2267
|
+
const version = Number(message.updated_at) || 0;
|
|
2245
2268
|
const cached = chunkCache?.get(message.id);
|
|
2246
2269
|
if (cached && cached.version === version) {
|
|
2247
2270
|
if (cached.chunks.length > 0) {
|
|
@@ -2265,7 +2288,7 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
2265
2288
|
}
|
|
2266
2289
|
continue;
|
|
2267
2290
|
}
|
|
2268
|
-
const chunks = await
|
|
2291
|
+
const chunks = await readRawJsonField(message, "chunks", ctx.walletAddress);
|
|
2269
2292
|
if (chunks && chunks.length > 0) {
|
|
2270
2293
|
const vectors = chunks.map(
|
|
2271
2294
|
(chunk) => decodeChunkVector(chunk.vector, () => {
|
|
@@ -2286,7 +2309,7 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
2286
2309
|
}
|
|
2287
2310
|
}
|
|
2288
2311
|
} else {
|
|
2289
|
-
const messageVector = await
|
|
2312
|
+
const messageVector = await readRawJsonField(message, "vector", ctx.walletAddress);
|
|
2290
2313
|
if (!messageVector || messageVector.length === 0) continue;
|
|
2291
2314
|
const fallback = Float32Array.from(messageVector);
|
|
2292
2315
|
chunkCache?.set(message.id, { version, chunks: [], fallback });
|
|
@@ -2312,7 +2335,7 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
2312
2335
|
const storedById = new Map(
|
|
2313
2336
|
await Promise.all(
|
|
2314
2337
|
Array.from(uniqueMessages, async ([id, m]) => {
|
|
2315
|
-
const stored = await
|
|
2338
|
+
const stored = await messageRawToStored(
|
|
2316
2339
|
m,
|
|
2317
2340
|
ctx.walletAddress,
|
|
2318
2341
|
ctx.signMessage,
|
|
@@ -2330,8 +2353,8 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
2330
2353
|
await Promise.all(
|
|
2331
2354
|
Array.from(needsChunkText, async (id) => {
|
|
2332
2355
|
const m = uniqueMessages.get(id);
|
|
2333
|
-
const parsed = await
|
|
2334
|
-
const version = Number(m.
|
|
2356
|
+
const parsed = await readRawJsonField(m, "chunks", ctx.walletAddress);
|
|
2357
|
+
const version = Number(m.updated_at) || 0;
|
|
2335
2358
|
if (parsed) chunkStateByMsgId.set(id, { version, chunks: parsed });
|
|
2336
2359
|
})
|
|
2337
2360
|
);
|
|
@@ -6145,6 +6168,9 @@ function supportsResponseFormat(model, variant = "json_object") {
|
|
|
6145
6168
|
const allow = variant === "json_schema" ? RESPONSE_SCHEMA_OK : RESPONSE_FORMAT_OK;
|
|
6146
6169
|
return model.split("/").some((seg) => allow.has(seg));
|
|
6147
6170
|
}
|
|
6171
|
+
function requiresResponsesTransport(model) {
|
|
6172
|
+
return model.split("/").some((seg) => RESPONSES_ONLY_MODEL_PREFIXES.some((prefix) => seg.startsWith(prefix)));
|
|
6173
|
+
}
|
|
6148
6174
|
function responsesExtra(extra) {
|
|
6149
6175
|
if (!extra) return {};
|
|
6150
6176
|
const out = {};
|
|
@@ -6480,7 +6506,7 @@ function extractResponsesContent(body) {
|
|
|
6480
6506
|
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("");
|
|
6481
6507
|
return text12;
|
|
6482
6508
|
}
|
|
6483
|
-
var RESPONSE_FORMAT_OK, RESPONSE_SCHEMA_OK, JSON_CONTRACT_REMINDER, CHAT_TO_RESPONSES_FIELDS, FOREIGN_ENDPOINT_SUFFIX, RETRYABLE_HTTP;
|
|
6509
|
+
var RESPONSE_FORMAT_OK, RESPONSE_SCHEMA_OK, JSON_CONTRACT_REMINDER, RESPONSES_ONLY_MODEL_PREFIXES, CHAT_TO_RESPONSES_FIELDS, FOREIGN_ENDPOINT_SUFFIX, RETRYABLE_HTTP;
|
|
6484
6510
|
var init_portalLlm = __esm({
|
|
6485
6511
|
"src/lib/memory/portalLlm.ts"() {
|
|
6486
6512
|
"use strict";
|
|
@@ -6492,6 +6518,7 @@ var init_portalLlm = __esm({
|
|
|
6492
6518
|
RESPONSE_FORMAT_OK = /* @__PURE__ */ new Set(["openai", "inclusionai", "deepseek"]);
|
|
6493
6519
|
RESPONSE_SCHEMA_OK = /* @__PURE__ */ new Set(["openai"]);
|
|
6494
6520
|
JSON_CONTRACT_REMINDER = "Output ONLY the strict JSON object requested. No prose, no explanation, no markdown.";
|
|
6521
|
+
RESPONSES_ONLY_MODEL_PREFIXES = ["gpt-5.6"];
|
|
6495
6522
|
CHAT_TO_RESPONSES_FIELDS = {
|
|
6496
6523
|
max_completion_tokens: "max_output_tokens"
|
|
6497
6524
|
};
|
|
@@ -17817,6 +17844,9 @@ var DEFAULT_BASE_URL2 = BASE_URL;
|
|
|
17817
17844
|
var DEFAULT_MODEL4 = "anthropic/claude-sonnet-4-6";
|
|
17818
17845
|
var DEFAULT_MAX_TOKENS = 4096;
|
|
17819
17846
|
var REQUEST_TIMEOUT_MS = 6e4;
|
|
17847
|
+
var MIN_RETRY_BUDGET_MS = 2e3;
|
|
17848
|
+
var MIN_RESPONSES_OUTPUT_TOKENS = 2048;
|
|
17849
|
+
var SCHEMA_FALLBACK_SKIP_STATUSES = /* @__PURE__ */ new Set([401, 403, 404, 408, 409, 413, 425, 429]);
|
|
17820
17850
|
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.
|
|
17821
17851
|
|
|
17822
17852
|
Rules:
|
|
@@ -17848,14 +17878,9 @@ ${m.content}`).join("\n\n");
|
|
|
17848
17878
|
const baseUrl = options.baseUrl ?? DEFAULT_BASE_URL2;
|
|
17849
17879
|
const model = options.llmModel ?? DEFAULT_MODEL4;
|
|
17850
17880
|
const wantsStructured = !!options.responseSchema;
|
|
17851
|
-
const
|
|
17881
|
+
const useResponsesTransport = requiresResponsesTransport(model);
|
|
17882
|
+
const sendResponseFormat = wantsStructured && !useResponsesTransport && supportsResponseFormat(model, "json_schema");
|
|
17852
17883
|
const basePrompt = options.systemPrompt ?? DEFAULT_SYSTEM_PROMPT;
|
|
17853
|
-
const systemPrompt = wantsStructured && !sendResponseFormat ? `${basePrompt}
|
|
17854
|
-
|
|
17855
|
-
Respond with ONLY a single JSON object conforming to this JSON Schema, with no prose, comments, or code fences:
|
|
17856
|
-
${JSON.stringify(
|
|
17857
|
-
options.responseSchema
|
|
17858
|
-
)}` : basePrompt;
|
|
17859
17884
|
const userMessage = [
|
|
17860
17885
|
`Question:
|
|
17861
17886
|
${trimmed}`,
|
|
@@ -17865,85 +17890,121 @@ ${evidence}`
|
|
|
17865
17890
|
].join("\n\n");
|
|
17866
17891
|
const maxTokens = options.maxTokens ?? DEFAULT_MAX_TOKENS;
|
|
17867
17892
|
const fetchImpl = options.fetchFn ?? fetch;
|
|
17893
|
+
const buildBody = (useResponseFormat) => {
|
|
17894
|
+
const systemPrompt = wantsStructured && !useResponseFormat ? `${basePrompt}
|
|
17895
|
+
|
|
17896
|
+
Respond with ONLY a single JSON object conforming to this JSON Schema, with no prose, comments, or code fences:
|
|
17897
|
+
${JSON.stringify(
|
|
17898
|
+
options.responseSchema
|
|
17899
|
+
)}` : basePrompt;
|
|
17900
|
+
const messages = [
|
|
17901
|
+
{ role: "system", content: systemPrompt },
|
|
17902
|
+
{ role: "user", content: userMessage }
|
|
17903
|
+
];
|
|
17904
|
+
if (useResponsesTransport) {
|
|
17905
|
+
return JSON.stringify({
|
|
17906
|
+
model,
|
|
17907
|
+
// Same system+user pair under the Responses-API field names: `input`
|
|
17908
|
+
// for the turns, `max_output_tokens` for the cap. Sending the
|
|
17909
|
+
// chat-completions spelling here is silently ignored, which caps the
|
|
17910
|
+
// answer at the portal default.
|
|
17911
|
+
input: messages,
|
|
17912
|
+
max_output_tokens: Math.max(maxTokens, MIN_RESPONSES_OUTPUT_TOKENS)
|
|
17913
|
+
});
|
|
17914
|
+
}
|
|
17915
|
+
return JSON.stringify({
|
|
17916
|
+
model,
|
|
17917
|
+
// Modern OpenAI field; the portal reads only `max_completion_tokens`
|
|
17918
|
+
// (the deprecated `max_tokens` is silently ignored → falls back to the
|
|
17919
|
+
// portal's default output cap and truncates the answer).
|
|
17920
|
+
max_completion_tokens: maxTokens,
|
|
17921
|
+
messages,
|
|
17922
|
+
...useResponseFormat && {
|
|
17923
|
+
response_format: {
|
|
17924
|
+
type: "json_schema",
|
|
17925
|
+
json_schema: { name: "reflect_output", schema: options.responseSchema }
|
|
17926
|
+
}
|
|
17927
|
+
}
|
|
17928
|
+
});
|
|
17929
|
+
};
|
|
17868
17930
|
const log = getLogger();
|
|
17869
17931
|
const authHeaders = await resolvePortalAuthHeaders(options, "memory/reflect");
|
|
17870
17932
|
if (authHeaders === null) return baseResult;
|
|
17871
|
-
const controller = new AbortController();
|
|
17872
17933
|
const deadline = Date.now() + REQUEST_TIMEOUT_MS;
|
|
17873
17934
|
const remaining = () => Math.max(0, deadline - Date.now());
|
|
17874
|
-
const
|
|
17875
|
-
|
|
17876
|
-
|
|
17877
|
-
|
|
17878
|
-
|
|
17879
|
-
|
|
17880
|
-
|
|
17881
|
-
|
|
17882
|
-
|
|
17883
|
-
|
|
17884
|
-
|
|
17885
|
-
|
|
17886
|
-
|
|
17887
|
-
|
|
17888
|
-
|
|
17889
|
-
|
|
17890
|
-
|
|
17891
|
-
|
|
17892
|
-
|
|
17893
|
-
|
|
17894
|
-
|
|
17895
|
-
|
|
17896
|
-
|
|
17897
|
-
|
|
17898
|
-
|
|
17899
|
-
|
|
17900
|
-
}
|
|
17901
|
-
}
|
|
17902
|
-
}),
|
|
17903
|
-
signal: controller.signal
|
|
17904
|
-
});
|
|
17905
|
-
} catch (err) {
|
|
17935
|
+
const endpoint = useResponsesTransport ? "/api/v1/responses" : "/api/v1/chat/completions";
|
|
17936
|
+
const sendOnce = async (useResponseFormat) => {
|
|
17937
|
+
const controller = new AbortController();
|
|
17938
|
+
const timer = setTimeout(() => controller.abort(), remaining());
|
|
17939
|
+
let response;
|
|
17940
|
+
try {
|
|
17941
|
+
response = await fetchImpl(`${baseUrl}${endpoint}`, {
|
|
17942
|
+
method: "POST",
|
|
17943
|
+
// No task type unless the caller named one — an undeclared task adds no
|
|
17944
|
+
// header at all, which is what keeps user-facing reflect() unlabelled.
|
|
17945
|
+
headers: {
|
|
17946
|
+
...authHeaders,
|
|
17947
|
+
...taskTypeHeader(options.taskType),
|
|
17948
|
+
"Content-Type": "application/json"
|
|
17949
|
+
},
|
|
17950
|
+
body: buildBody(useResponseFormat),
|
|
17951
|
+
signal: controller.signal
|
|
17952
|
+
});
|
|
17953
|
+
} catch (err) {
|
|
17954
|
+
clearTimeout(timer);
|
|
17955
|
+
log.warn("[memory/reflect] portal request failed", {
|
|
17956
|
+
err: err instanceof Error ? err.message : String(err),
|
|
17957
|
+
baseUrl
|
|
17958
|
+
});
|
|
17959
|
+
return { kind: "error" };
|
|
17960
|
+
}
|
|
17906
17961
|
clearTimeout(timer);
|
|
17907
|
-
|
|
17908
|
-
|
|
17909
|
-
|
|
17962
|
+
if (!response.ok) {
|
|
17963
|
+
return { kind: "http", status: response.status, statusText: response.statusText };
|
|
17964
|
+
}
|
|
17965
|
+
const bodyTimer = setTimeout(() => controller.abort(), remaining());
|
|
17966
|
+
try {
|
|
17967
|
+
const body = await response.json();
|
|
17968
|
+
clearTimeout(bodyTimer);
|
|
17969
|
+
return { kind: "ok", body };
|
|
17970
|
+
} catch (err) {
|
|
17971
|
+
clearTimeout(bodyTimer);
|
|
17972
|
+
log.warn("[memory/reflect] failed to parse portal response body", {
|
|
17973
|
+
err: err instanceof Error ? err.message : String(err)
|
|
17974
|
+
});
|
|
17975
|
+
return { kind: "error" };
|
|
17976
|
+
}
|
|
17977
|
+
};
|
|
17978
|
+
let attempt = await sendOnce(sendResponseFormat);
|
|
17979
|
+
let schemaFallbackUsed = false;
|
|
17980
|
+
const budgetLeftMs = remaining();
|
|
17981
|
+
if (attempt.kind === "http" && sendResponseFormat && !SCHEMA_FALLBACK_SKIP_STATUSES.has(attempt.status) && budgetLeftMs >= MIN_RETRY_BUDGET_MS) {
|
|
17982
|
+
log.warn("[memory/reflect] response_format json_schema rejected; retrying schema-in-prompt", {
|
|
17983
|
+
status: attempt.status,
|
|
17984
|
+
statusText: attempt.statusText,
|
|
17985
|
+
model,
|
|
17986
|
+
taskType: options.taskType,
|
|
17987
|
+
budgetLeftMs
|
|
17910
17988
|
});
|
|
17911
|
-
|
|
17989
|
+
schemaFallbackUsed = true;
|
|
17990
|
+
attempt = await sendOnce(false);
|
|
17912
17991
|
}
|
|
17913
|
-
|
|
17914
|
-
if (
|
|
17992
|
+
if (attempt.kind === "error") return baseResult;
|
|
17993
|
+
if (attempt.kind === "http") {
|
|
17915
17994
|
log.warn("[memory/reflect] portal returned non-OK", {
|
|
17916
|
-
status:
|
|
17917
|
-
statusText:
|
|
17918
|
-
|
|
17919
|
-
|
|
17920
|
-
}
|
|
17921
|
-
const bodyTimer = setTimeout(() => controller.abort(), remaining());
|
|
17922
|
-
let body;
|
|
17923
|
-
try {
|
|
17924
|
-
body = await response.json();
|
|
17925
|
-
} catch (err) {
|
|
17926
|
-
clearTimeout(bodyTimer);
|
|
17927
|
-
log.warn("[memory/reflect] failed to parse portal response body", {
|
|
17928
|
-
err: err instanceof Error ? err.message : String(err)
|
|
17995
|
+
status: attempt.status,
|
|
17996
|
+
statusText: attempt.statusText,
|
|
17997
|
+
// Distinguishes "the fallback ran and still failed" from "never tried".
|
|
17998
|
+
schemaFallbackUsed
|
|
17929
17999
|
});
|
|
17930
18000
|
return baseResult;
|
|
17931
18001
|
}
|
|
17932
|
-
|
|
17933
|
-
return parseAnswer(body, baseResult, !!options.responseSchema);
|
|
18002
|
+
return parseAnswer(attempt.body, baseResult, !!options.responseSchema);
|
|
17934
18003
|
}
|
|
17935
18004
|
function parseAnswer(body, base, parseSchema) {
|
|
17936
18005
|
if (typeof body !== "object" || body === null) return base;
|
|
17937
18006
|
const obj = body;
|
|
17938
|
-
const
|
|
17939
|
-
let text12 = "";
|
|
17940
|
-
if (Array.isArray(choices) && choices.length > 0) {
|
|
17941
|
-
const message = choices[0].message;
|
|
17942
|
-
if (typeof message === "object" && message !== null) {
|
|
17943
|
-
const content = message.content;
|
|
17944
|
-
if (typeof content === "string") text12 = content;
|
|
17945
|
-
}
|
|
17946
|
-
}
|
|
18007
|
+
const text12 = extractCompletionContent(obj) ?? "";
|
|
17947
18008
|
const usage = obj.usage;
|
|
17948
18009
|
let structuredOutput;
|
|
17949
18010
|
if (parseSchema && text12) {
|
|
@@ -17955,14 +18016,19 @@ function parseAnswer(body, base, parseSchema) {
|
|
|
17955
18016
|
});
|
|
17956
18017
|
}
|
|
17957
18018
|
}
|
|
18019
|
+
const promptTokens = usage?.prompt_tokens ?? usage?.input_tokens ?? 0;
|
|
18020
|
+
const completionTokens = usage?.completion_tokens ?? usage?.output_tokens ?? 0;
|
|
17958
18021
|
return {
|
|
17959
18022
|
text: text12,
|
|
17960
18023
|
...structuredOutput !== void 0 && { structuredOutput },
|
|
17961
18024
|
basedOn: base.basedOn,
|
|
17962
18025
|
usage: {
|
|
17963
|
-
promptTokens
|
|
17964
|
-
completionTokens
|
|
17965
|
-
|
|
18026
|
+
promptTokens,
|
|
18027
|
+
completionTokens,
|
|
18028
|
+
// Derived when absent: the Responses API reports the two component counts
|
|
18029
|
+
// and does not always send a total, which would otherwise report zero
|
|
18030
|
+
// spend for a call that plainly cost something.
|
|
18031
|
+
totalTokens: usage?.total_tokens ?? promptTokens + completionTokens
|
|
17966
18032
|
}
|
|
17967
18033
|
};
|
|
17968
18034
|
}
|
|
@@ -21285,22 +21351,31 @@ function useChatStorage(options) {
|
|
|
21285
21351
|
const serverToolsPromise = getTokenRef.current && !(Array.isArray(serverToolsFilter) && serverToolsFilter.length === 0) ? fetchServerToolsSettled(getTokenRef.current) : null;
|
|
21286
21352
|
const userMessageEmbeddingPromise = getTokenRef.current && contentForStorage.length >= MIN_CONTENT_LENGTH_FOR_TOOLS && (isServerToolsFunction && !(serverToolsConfig?.deferLoading?.enabled && effectiveApiType === "responses") || !!clientTools?.length) ? embedForToolsSettled(getTokenRef.current) : null;
|
|
21287
21353
|
let messagesToSend;
|
|
21288
|
-
const
|
|
21289
|
-
const knownToolCallEventIds = /* @__PURE__ */ new Set();
|
|
21290
|
-
for (const msg of storedMessages) {
|
|
21291
|
-
if (msg.toolCallEvents) {
|
|
21292
|
-
for (const evt of msg.toolCallEvents) {
|
|
21293
|
-
if (evt.id) knownToolCallEventIds.add(evt.id);
|
|
21294
|
-
}
|
|
21295
|
-
}
|
|
21296
|
-
}
|
|
21354
|
+
const knownToolCallEventIds = await getToolCallEventIdsOp(storageCtx, convId);
|
|
21297
21355
|
if (includeHistory) {
|
|
21298
|
-
|
|
21299
|
-
|
|
21300
|
-
|
|
21301
|
-
|
|
21302
|
-
|
|
21303
|
-
|
|
21356
|
+
let tail = [];
|
|
21357
|
+
let replayableMessages = [];
|
|
21358
|
+
let beforeMessageId;
|
|
21359
|
+
let boundaryExcludeUniqueIds;
|
|
21360
|
+
for (; ; ) {
|
|
21361
|
+
const page = await getMessagesPageOp(storageCtx, convId, {
|
|
21362
|
+
limit: maxHistoryMessages,
|
|
21363
|
+
beforeMessageId,
|
|
21364
|
+
boundaryExcludeUniqueIds
|
|
21365
|
+
});
|
|
21366
|
+
if (page.length === 0) break;
|
|
21367
|
+
tail = [...page, ...tail];
|
|
21368
|
+
const validMessages = tail.filter((msg) => !msg.error);
|
|
21369
|
+
replayableMessages = prepareToolResultsForReplay(validMessages, {
|
|
21370
|
+
fold: foldToolResultsInHistoryRef.current === true,
|
|
21371
|
+
exclude: toolResultsHistoryExcludeRef.current,
|
|
21372
|
+
placeholder: DISPLAY_CARD_PLACEHOLDER
|
|
21373
|
+
});
|
|
21374
|
+
if (replayableMessages.length >= maxHistoryMessages) break;
|
|
21375
|
+
if (page.length < maxHistoryMessages) break;
|
|
21376
|
+
beforeMessageId = page[0].messageId;
|
|
21377
|
+
boundaryExcludeUniqueIds = tail.filter((msg) => msg.messageId === beforeMessageId).map((msg) => msg.uniqueId);
|
|
21378
|
+
}
|
|
21304
21379
|
const limitedMessages = replayableMessages.slice(-maxHistoryMessages);
|
|
21305
21380
|
const foldedHistory = limitedMessages;
|
|
21306
21381
|
if (summarizeHistory && !getTokenRef.current) {
|