@anuma/sdk 6.3.0 → 6.4.0
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/index.cjs +193 -4
- package/dist/expo/index.d.mts +73 -0
- package/dist/expo/index.d.ts +73 -0
- package/dist/expo/index.mjs +193 -4
- package/dist/react/index.cjs +144 -30
- package/dist/react/index.d.mts +65 -0
- package/dist/react/index.d.ts +65 -0
- package/dist/react/index.mjs +144 -30
- package/dist/server/index.cjs +3 -0
- package/dist/server/index.d.mts +25 -0
- package/dist/server/index.d.ts +25 -0
- package/dist/server/index.mjs +3 -0
- package/package.json +1 -1
package/dist/expo/index.cjs
CHANGED
|
@@ -14092,6 +14092,153 @@ async function cleanupConversationSummary(database, conversationId) {
|
|
|
14092
14092
|
}
|
|
14093
14093
|
}
|
|
14094
14094
|
|
|
14095
|
+
// src/lib/chat/toolResultMessage.ts
|
|
14096
|
+
var HEADER = "[Tool Execution Results]\n\n";
|
|
14097
|
+
var FOOTER = "\n\nBased on these results, continue with the task.";
|
|
14098
|
+
var ENTRY_SEPARATOR = "\n\n";
|
|
14099
|
+
var TOOL_RESULT_FOOTER_LINE = FOOTER.trim();
|
|
14100
|
+
var MAX_PERSISTED_TOOL_RESULT_CHARS = 1e5;
|
|
14101
|
+
function buildToolResultContent(results) {
|
|
14102
|
+
const entries = results.map((r) => `Tool "${r.name}" returned: ${JSON.stringify(r.result)}`);
|
|
14103
|
+
const framing = HEADER.length + FOOTER.length + ENTRY_SEPARATOR.length * Math.max(0, entries.length - 1);
|
|
14104
|
+
const summary = capEntries(entries, MAX_PERSISTED_TOOL_RESULT_CHARS - framing).join(
|
|
14105
|
+
ENTRY_SEPARATOR
|
|
14106
|
+
);
|
|
14107
|
+
return `${HEADER}${summary}${FOOTER}`;
|
|
14108
|
+
}
|
|
14109
|
+
function capToolResultEntries(entries, budget) {
|
|
14110
|
+
return capEntries(entries, budget);
|
|
14111
|
+
}
|
|
14112
|
+
function capEntries(entries, budget) {
|
|
14113
|
+
const smallestFirst = entries.map((_, index) => index).sort((a, b) => entries[a].length - entries[b].length);
|
|
14114
|
+
const capped = [...entries];
|
|
14115
|
+
let remaining = budget;
|
|
14116
|
+
let unassigned = entries.length;
|
|
14117
|
+
for (const index of smallestFirst) {
|
|
14118
|
+
capped[index] = truncateEntry(entries[index], Math.floor(remaining / unassigned));
|
|
14119
|
+
remaining -= capped[index].length;
|
|
14120
|
+
unassigned--;
|
|
14121
|
+
}
|
|
14122
|
+
return capped;
|
|
14123
|
+
}
|
|
14124
|
+
function truncateEntry(entry, allowance) {
|
|
14125
|
+
if (entry.length <= allowance) return entry;
|
|
14126
|
+
const keep = allowance - truncationMarker(entry.length).length;
|
|
14127
|
+
if (keep <= 0) return entry.slice(0, Math.max(0, allowance));
|
|
14128
|
+
return `${entry.slice(0, keep)}${truncationMarker(entry.length - keep)}`;
|
|
14129
|
+
}
|
|
14130
|
+
function truncationMarker(omitted) {
|
|
14131
|
+
return `
|
|
14132
|
+
|
|
14133
|
+
... (tool output truncated, ${omitted} characters omitted)`;
|
|
14134
|
+
}
|
|
14135
|
+
|
|
14136
|
+
// src/lib/chat/toolResults.ts
|
|
14137
|
+
var TOOL_RESULTS_PREFIX = "[Tool Execution Results]";
|
|
14138
|
+
var DISPLAY_CARD_PLACEHOLDER = "[displayed a card to the user with the tool result]";
|
|
14139
|
+
var TOOL_LINE = /^Tool "([^"]+)" returned: (.*)$/;
|
|
14140
|
+
var TOOL_RESULT_ORIGIN = "tool_result";
|
|
14141
|
+
function isToolResultsRow(row) {
|
|
14142
|
+
if (row.origin === TOOL_RESULT_ORIGIN) return true;
|
|
14143
|
+
if (typeof row.origin === "string") return false;
|
|
14144
|
+
if (row.role !== "user" || !row.content.startsWith(TOOL_RESULTS_PREFIX)) return false;
|
|
14145
|
+
return parseToolResultSegments(row.content).length > 0;
|
|
14146
|
+
}
|
|
14147
|
+
function parseToolResultSegments(content) {
|
|
14148
|
+
const segments = [];
|
|
14149
|
+
for (const raw of content.split("\n")) {
|
|
14150
|
+
const line = raw.trim();
|
|
14151
|
+
const match = TOOL_LINE.exec(line);
|
|
14152
|
+
if (match) {
|
|
14153
|
+
segments.push({ name: match[1], line });
|
|
14154
|
+
continue;
|
|
14155
|
+
}
|
|
14156
|
+
const current = segments[segments.length - 1];
|
|
14157
|
+
if (!current || line === "" || line === TOOL_RESULT_FOOTER_LINE) continue;
|
|
14158
|
+
if (line === TOOL_RESULTS_PREFIX) continue;
|
|
14159
|
+
current.line = `${current.line}
|
|
14160
|
+
${line}`;
|
|
14161
|
+
}
|
|
14162
|
+
return segments;
|
|
14163
|
+
}
|
|
14164
|
+
function prepareToolResultsForReplay(rows, options) {
|
|
14165
|
+
if (options.fold) {
|
|
14166
|
+
return foldToolResultsRows(rows, {
|
|
14167
|
+
exclude: options.exclude,
|
|
14168
|
+
placeholder: options.placeholder
|
|
14169
|
+
});
|
|
14170
|
+
}
|
|
14171
|
+
return rows.filter((row) => !isToolResultsRow(row));
|
|
14172
|
+
}
|
|
14173
|
+
function foldToolResultsRows(rows, options) {
|
|
14174
|
+
const exclude = new Set(options?.exclude ?? []);
|
|
14175
|
+
const out = [];
|
|
14176
|
+
const pending = [];
|
|
14177
|
+
const assistantIndexById = /* @__PURE__ */ new Map();
|
|
14178
|
+
for (const row of rows) {
|
|
14179
|
+
if (isToolResultsRow(row)) {
|
|
14180
|
+
pending.push({ row, insertionPoint: out.length });
|
|
14181
|
+
continue;
|
|
14182
|
+
}
|
|
14183
|
+
out.push(row);
|
|
14184
|
+
if (row.role === "assistant" && row.uniqueId) {
|
|
14185
|
+
assistantIndexById.set(row.uniqueId, out.length - 1);
|
|
14186
|
+
}
|
|
14187
|
+
}
|
|
14188
|
+
const byTarget = /* @__PURE__ */ new Map();
|
|
14189
|
+
for (const { row, insertionPoint } of pending) {
|
|
14190
|
+
const target = resolveFoldTarget(out, row, insertionPoint, assistantIndexById);
|
|
14191
|
+
if (target === void 0) continue;
|
|
14192
|
+
const group = byTarget.get(target);
|
|
14193
|
+
if (group) group.push(row);
|
|
14194
|
+
else byTarget.set(target, [row]);
|
|
14195
|
+
}
|
|
14196
|
+
for (const [target, groupedRows] of byTarget) {
|
|
14197
|
+
const assistant = out[target];
|
|
14198
|
+
const kept = groupedRows.flatMap((row) => parseToolResultSegments(row.content)).filter((segment) => !exclude.has(segment.name));
|
|
14199
|
+
if (kept.length > 0) {
|
|
14200
|
+
out[target] = { ...assistant, content: appendToolResults(assistant.content, kept) };
|
|
14201
|
+
} else if (!assistant.content.trim() && options?.placeholder) {
|
|
14202
|
+
out[target] = { ...assistant, content: options.placeholder };
|
|
14203
|
+
}
|
|
14204
|
+
}
|
|
14205
|
+
return out;
|
|
14206
|
+
}
|
|
14207
|
+
function resolveFoldTarget(out, row, insertionPoint, assistantIndexById) {
|
|
14208
|
+
const linked = row.parentMessageId ? assistantIndexById.get(row.parentMessageId) : void 0;
|
|
14209
|
+
if (linked !== void 0) return linked;
|
|
14210
|
+
let previous;
|
|
14211
|
+
for (let i = insertionPoint - 1; i >= 0; i--) {
|
|
14212
|
+
if (out[i].role === "assistant") {
|
|
14213
|
+
previous = i;
|
|
14214
|
+
break;
|
|
14215
|
+
}
|
|
14216
|
+
}
|
|
14217
|
+
let next;
|
|
14218
|
+
for (let i = insertionPoint; i < out.length; i++) {
|
|
14219
|
+
if (out[i].role === "assistant") {
|
|
14220
|
+
next = i;
|
|
14221
|
+
break;
|
|
14222
|
+
}
|
|
14223
|
+
}
|
|
14224
|
+
if (previous === void 0) return next;
|
|
14225
|
+
if (next === void 0) return previous;
|
|
14226
|
+
return next - insertionPoint < insertionPoint - previous ? next : previous;
|
|
14227
|
+
}
|
|
14228
|
+
var MAX_FOLDED_APPENDIX_CHARS = 2e4;
|
|
14229
|
+
function appendToolResults(assistantContent, kept) {
|
|
14230
|
+
const framing = TOOL_RESULTS_PREFIX.length + 1 + (kept.length - 1);
|
|
14231
|
+
const capped = capToolResultEntries(
|
|
14232
|
+
kept.map((segment) => segment.line),
|
|
14233
|
+
MAX_FOLDED_APPENDIX_CHARS - framing
|
|
14234
|
+
);
|
|
14235
|
+
const appendix = `${TOOL_RESULTS_PREFIX}
|
|
14236
|
+
${capped.join("\n")}`;
|
|
14237
|
+
return assistantContent.trim() ? `${assistantContent}
|
|
14238
|
+
|
|
14239
|
+
${appendix}` : appendix;
|
|
14240
|
+
}
|
|
14241
|
+
|
|
14095
14242
|
// src/lib/db/chat/lazyDecrypt.ts
|
|
14096
14243
|
init_useEncryption();
|
|
14097
14244
|
init_encryption_utils();
|
|
@@ -16207,6 +16354,9 @@ async function extractFacts(messages, options) {
|
|
|
16207
16354
|
...options.apiKey !== void 0 && { apiKey: options.apiKey },
|
|
16208
16355
|
...options.getToken !== void 0 && { getToken: options.getToken },
|
|
16209
16356
|
...options.baseUrl !== void 0 && { baseUrl: options.baseUrl },
|
|
16357
|
+
...options.endpointOverride !== void 0 && {
|
|
16358
|
+
endpointOverride: options.endpointOverride
|
|
16359
|
+
},
|
|
16210
16360
|
model: options.model ?? DEFAULT_EXTRACTION_MODEL,
|
|
16211
16361
|
systemPrompt: SYSTEM_PROMPT4,
|
|
16212
16362
|
userMessage: `Today's date is ${today}. Resolve any relative dates ("yesterday", "next week") against it.
|
|
@@ -19746,11 +19896,17 @@ function useChatStorage(options) {
|
|
|
19746
19896
|
onPiiRedacted,
|
|
19747
19897
|
nerDetector,
|
|
19748
19898
|
onServerToolCall,
|
|
19749
|
-
onToolCallArgumentsDelta
|
|
19899
|
+
onToolCallArgumentsDelta,
|
|
19900
|
+
toolResultsHistoryExclude,
|
|
19901
|
+
foldToolResultsInHistory
|
|
19750
19902
|
} = options;
|
|
19751
19903
|
const [currentConversationId, setCurrentConversationId] = (0, import_react4.useState)(
|
|
19752
19904
|
initialConversationId || null
|
|
19753
19905
|
);
|
|
19906
|
+
const toolResultsHistoryExcludeRef = (0, import_react4.useRef)(toolResultsHistoryExclude);
|
|
19907
|
+
toolResultsHistoryExcludeRef.current = toolResultsHistoryExclude;
|
|
19908
|
+
const foldToolResultsInHistoryRef = (0, import_react4.useRef)(foldToolResultsInHistory);
|
|
19909
|
+
foldToolResultsInHistoryRef.current = foldToolResultsInHistory;
|
|
19754
19910
|
const nerDetectorRef = (0, import_react4.useRef)(nerDetector);
|
|
19755
19911
|
nerDetectorRef.current = nerDetector;
|
|
19756
19912
|
const resolvedPiiRedaction = (0, import_react4.useMemo)(
|
|
@@ -20618,7 +20774,13 @@ function useChatStorage(options) {
|
|
|
20618
20774
|
}
|
|
20619
20775
|
if (includeHistory) {
|
|
20620
20776
|
const validMessages = storedMessages.filter((msg) => !msg.error);
|
|
20621
|
-
const
|
|
20777
|
+
const replayableMessages = prepareToolResultsForReplay(validMessages, {
|
|
20778
|
+
fold: foldToolResultsInHistoryRef.current === true,
|
|
20779
|
+
exclude: toolResultsHistoryExcludeRef.current,
|
|
20780
|
+
placeholder: DISPLAY_CARD_PLACEHOLDER
|
|
20781
|
+
});
|
|
20782
|
+
const limitedMessages = replayableMessages.slice(-maxHistoryMessages);
|
|
20783
|
+
const foldedHistory = limitedMessages;
|
|
20622
20784
|
if (summarizeHistory && !getTokenRef.current) {
|
|
20623
20785
|
getLogger().warn(
|
|
20624
20786
|
"[summarize] summarizeHistory is enabled but getToken is not provided \u2014 summarization will be skipped"
|
|
@@ -20628,7 +20790,7 @@ function useChatStorage(options) {
|
|
|
20628
20790
|
const { messagesToConvert, summarySystemMessage } = await maybeSummarizeHistory({
|
|
20629
20791
|
database,
|
|
20630
20792
|
conversationId: convId,
|
|
20631
|
-
messages:
|
|
20793
|
+
messages: foldedHistory,
|
|
20632
20794
|
summarizeHistory,
|
|
20633
20795
|
summaryTokenThreshold,
|
|
20634
20796
|
summaryMinWindowMessages,
|
|
@@ -20998,6 +21160,7 @@ function useChatStorage(options) {
|
|
|
20998
21160
|
uniqueId: effectiveAssistantUniqueId
|
|
20999
21161
|
};
|
|
21000
21162
|
let storedAssistantMessage;
|
|
21163
|
+
let assistantMsgQueueId;
|
|
21001
21164
|
try {
|
|
21002
21165
|
const assistantMsgResult = await writeOrQueue(
|
|
21003
21166
|
"createMessage",
|
|
@@ -21007,6 +21170,7 @@ function useChatStorage(options) {
|
|
|
21007
21170
|
userMsgQueueId ? [userMsgQueueId] : []
|
|
21008
21171
|
);
|
|
21009
21172
|
storedAssistantMessage = assistantMsgResult.result;
|
|
21173
|
+
assistantMsgQueueId = assistantMsgResult.queueId;
|
|
21010
21174
|
if (!assistantMsgResult.queued) {
|
|
21011
21175
|
void embedMessageAsync(storedAssistantMessage, maskForCall);
|
|
21012
21176
|
}
|
|
@@ -21017,6 +21181,29 @@ function useChatStorage(options) {
|
|
|
21017
21181
|
userMessage: storedUserMessage
|
|
21018
21182
|
};
|
|
21019
21183
|
}
|
|
21184
|
+
const autoToolResults = result.autoExecutedToolResults;
|
|
21185
|
+
let storedToolResultsMessage;
|
|
21186
|
+
if (autoToolResults && autoToolResults.length > 0) {
|
|
21187
|
+
const toolResultsOpts = {
|
|
21188
|
+
conversationId: convId,
|
|
21189
|
+
role: "user",
|
|
21190
|
+
content: buildToolResultContent(autoToolResults),
|
|
21191
|
+
model: "",
|
|
21192
|
+
parentMessageId: storedAssistantMessage.uniqueId,
|
|
21193
|
+
origin: TOOL_RESULT_ORIGIN
|
|
21194
|
+
};
|
|
21195
|
+
try {
|
|
21196
|
+
const toolResultsWrite = await writeOrQueue(
|
|
21197
|
+
"createMessage",
|
|
21198
|
+
toolResultsOpts,
|
|
21199
|
+
() => createMessageOp(storageCtx, toolResultsOpts),
|
|
21200
|
+
() => makeSyntheticStoredMessage(toolResultsOpts),
|
|
21201
|
+
assistantMsgQueueId ? [assistantMsgQueueId] : []
|
|
21202
|
+
);
|
|
21203
|
+
storedToolResultsMessage = toolResultsWrite.result;
|
|
21204
|
+
} catch {
|
|
21205
|
+
}
|
|
21206
|
+
}
|
|
21020
21207
|
const refreshGetToken = getTokenRef.current;
|
|
21021
21208
|
if (refreshGetToken) {
|
|
21022
21209
|
Promise.resolve().then(() => shouldRefreshTools(getToolsChecksum(responseData), serverToolsConfig?.cache)).then((refresh) => {
|
|
@@ -21036,7 +21223,9 @@ function useChatStorage(options) {
|
|
|
21036
21223
|
data: responseData,
|
|
21037
21224
|
error: null,
|
|
21038
21225
|
userMessage: storedUserMessage,
|
|
21039
|
-
assistantMessage: storedAssistantMessage
|
|
21226
|
+
assistantMessage: storedAssistantMessage,
|
|
21227
|
+
autoExecutedToolResults: autoToolResults,
|
|
21228
|
+
toolResultsMessage: storedToolResultsMessage
|
|
21040
21229
|
};
|
|
21041
21230
|
},
|
|
21042
21231
|
[
|
package/dist/expo/index.d.mts
CHANGED
|
@@ -3777,6 +3777,40 @@ interface BaseUseChatStorageOptions {
|
|
|
3777
3777
|
* Defaults to the hardcoded MCP_R2_DOMAIN from clientConfig.
|
|
3778
3778
|
*/
|
|
3779
3779
|
mcpR2Domain?: string;
|
|
3780
|
+
/**
|
|
3781
|
+
* Tool names whose persisted results must never be replayed to the model.
|
|
3782
|
+
*
|
|
3783
|
+
* A turn's auto-executed tool results are stored as a synthetic
|
|
3784
|
+
* `[Tool Execution Results]` row and, on a replayed send, folded back onto the
|
|
3785
|
+
* assistant turn they belong to — that is what lets a follow-up question about a
|
|
3786
|
+
* tool's output work after a reload. Name a tool here when its payload exists for
|
|
3787
|
+
* the RENDERER rather than the model: a display card can carry data the model was
|
|
3788
|
+
* deliberately never given (People Nearby's card holds third parties' snapped
|
|
3789
|
+
* coordinates, which the search result strips), and replaying it would hand that
|
|
3790
|
+
* data straight back.
|
|
3791
|
+
*
|
|
3792
|
+
* Hook-level rather than per-send on purpose: an exclusion that has to be
|
|
3793
|
+
* remembered at every call site is one bad send away from leaking.
|
|
3794
|
+
*/
|
|
3795
|
+
toolResultsHistoryExclude?: string[];
|
|
3796
|
+
/**
|
|
3797
|
+
* Fold persisted `[Tool Execution Results]` rows onto the assistant turn that produced them
|
|
3798
|
+
* when replaying stored history, instead of dropping them.
|
|
3799
|
+
*
|
|
3800
|
+
* **Defaults to `false`, and that default is deliberate.** Folding is the better behaviour —
|
|
3801
|
+
* it is what lets a follow-up about a tool's output work after a reload — but it moves the
|
|
3802
|
+
* payload from a `role: "user"` row onto an `assistant` row. Any consumer that scrubs these
|
|
3803
|
+
* rows by checking `role === "user"` plus the content prefix (which is how both apps did it
|
|
3804
|
+
* before this option existed) stops catching them the moment folding turns on, and starts
|
|
3805
|
+
* replaying whatever the row held. Opting in is therefore a statement that the caller has
|
|
3806
|
+
* checked its own filters and set {@link toolResultsHistoryExclude} for any payload that must
|
|
3807
|
+
* not reach the model.
|
|
3808
|
+
*
|
|
3809
|
+
* With it off, rows are dropped from the replayed history rather than sent verbatim. Verbatim
|
|
3810
|
+
* would put two consecutive `user` turns on the wire, and the model answers the previous turn
|
|
3811
|
+
* instead of the new prompt.
|
|
3812
|
+
*/
|
|
3813
|
+
foldToolResultsInHistory?: boolean;
|
|
3780
3814
|
/**
|
|
3781
3815
|
* Pre-processors run after the last user message is received but before
|
|
3782
3816
|
* the first LLM request. Each receives the prompt text and a shared
|
|
@@ -4126,6 +4160,20 @@ interface BaseSendMessageSuccessResult {
|
|
|
4126
4160
|
error: null;
|
|
4127
4161
|
userMessage: StoredMessage;
|
|
4128
4162
|
assistantMessage: StoredMessage;
|
|
4163
|
+
/** Results from tools the SDK auto-executed this turn (e.g. display tools). */
|
|
4164
|
+
autoExecutedToolResults?: {
|
|
4165
|
+
name: string;
|
|
4166
|
+
result: unknown;
|
|
4167
|
+
}[];
|
|
4168
|
+
/**
|
|
4169
|
+
* The synthetic `[Tool Execution Results]` row those results were persisted as.
|
|
4170
|
+
*
|
|
4171
|
+
* Returned so a caller can key its transient overlay on the id the SDK actually wrote instead of
|
|
4172
|
+
* deriving one and hoping the two agree — that guesswork is what mobile's per-card persist
|
|
4173
|
+
* workarounds existed to do (#5519). Absent when the turn executed no tools, or when the row write
|
|
4174
|
+
* failed (non-fatal: the assistant reply is already stored).
|
|
4175
|
+
*/
|
|
4176
|
+
toolResultsMessage?: StoredMessage;
|
|
4129
4177
|
}
|
|
4130
4178
|
interface BaseSendMessageSkippedResult {
|
|
4131
4179
|
data: ApiResponse;
|
|
@@ -5820,6 +5868,31 @@ interface QuarantinedMemoryInfo {
|
|
|
5820
5868
|
interface ExtractFactsOptions extends PortalLlmAuth {
|
|
5821
5869
|
baseUrl?: string;
|
|
5822
5870
|
model?: string;
|
|
5871
|
+
/**
|
|
5872
|
+
* Optional per-call request path override, forwarded to
|
|
5873
|
+
* {@link callPortalJsonCompletion}. When set, the extraction call POSTs to
|
|
5874
|
+
* `baseUrl + endpointOverride` instead of the default
|
|
5875
|
+
* `/api/v1/chat/completions` — path only, body unchanged. Lets callers route
|
|
5876
|
+
* this internal-utility pass to a dedicated endpoint. Invalid values throw at
|
|
5877
|
+
* call time (see {@link validateEndpointOverride}).
|
|
5878
|
+
*
|
|
5879
|
+
* Why this exists (anuma-ai/ai-memoryless-client#5536): auto-extraction is the
|
|
5880
|
+
* highest-volume first-party background call in the product — one per
|
|
5881
|
+
* extracting turn, on every platform — and it carries no flow fingerprint, so
|
|
5882
|
+
* the portal's freeloader detector classifies it as scripted abuse. In reject
|
|
5883
|
+
* mode that 403s every basic-tier extraction, which surfaces here as
|
|
5884
|
+
* `onExhaustedEmpty` → `empty-after-retry` and leaves free-tier vaults empty.
|
|
5885
|
+
* {@link TopicExtractOptions.endpointOverride} already exists for the same
|
|
5886
|
+
* reason on the topic pass; this is the fact pass catching up.
|
|
5887
|
+
*
|
|
5888
|
+
* IMPORTANT — the utility endpoint clamps to a PRICE CEILING and never
|
|
5889
|
+
* rejects, so pointing this at `/api/v1/utility/chat/completions` while the
|
|
5890
|
+
* portal's ceiling prices below {@link DEFAULT_EXTRACTION_MODEL} silently
|
|
5891
|
+
* rewrites the model instead of 403-ing. That trades a visible failure for an
|
|
5892
|
+
* invisible quality regression: raise `PORTAL_UTILITY_CEILING_MODEL` to at
|
|
5893
|
+
* least the extraction model's rate BEFORE setting this in a client.
|
|
5894
|
+
*/
|
|
5895
|
+
endpointOverride?: string;
|
|
5823
5896
|
/** Override the global fetch implementation (useful for tests). */
|
|
5824
5897
|
fetchFn?: typeof fetch;
|
|
5825
5898
|
/**
|
package/dist/expo/index.d.ts
CHANGED
|
@@ -3777,6 +3777,40 @@ interface BaseUseChatStorageOptions {
|
|
|
3777
3777
|
* Defaults to the hardcoded MCP_R2_DOMAIN from clientConfig.
|
|
3778
3778
|
*/
|
|
3779
3779
|
mcpR2Domain?: string;
|
|
3780
|
+
/**
|
|
3781
|
+
* Tool names whose persisted results must never be replayed to the model.
|
|
3782
|
+
*
|
|
3783
|
+
* A turn's auto-executed tool results are stored as a synthetic
|
|
3784
|
+
* `[Tool Execution Results]` row and, on a replayed send, folded back onto the
|
|
3785
|
+
* assistant turn they belong to — that is what lets a follow-up question about a
|
|
3786
|
+
* tool's output work after a reload. Name a tool here when its payload exists for
|
|
3787
|
+
* the RENDERER rather than the model: a display card can carry data the model was
|
|
3788
|
+
* deliberately never given (People Nearby's card holds third parties' snapped
|
|
3789
|
+
* coordinates, which the search result strips), and replaying it would hand that
|
|
3790
|
+
* data straight back.
|
|
3791
|
+
*
|
|
3792
|
+
* Hook-level rather than per-send on purpose: an exclusion that has to be
|
|
3793
|
+
* remembered at every call site is one bad send away from leaking.
|
|
3794
|
+
*/
|
|
3795
|
+
toolResultsHistoryExclude?: string[];
|
|
3796
|
+
/**
|
|
3797
|
+
* Fold persisted `[Tool Execution Results]` rows onto the assistant turn that produced them
|
|
3798
|
+
* when replaying stored history, instead of dropping them.
|
|
3799
|
+
*
|
|
3800
|
+
* **Defaults to `false`, and that default is deliberate.** Folding is the better behaviour —
|
|
3801
|
+
* it is what lets a follow-up about a tool's output work after a reload — but it moves the
|
|
3802
|
+
* payload from a `role: "user"` row onto an `assistant` row. Any consumer that scrubs these
|
|
3803
|
+
* rows by checking `role === "user"` plus the content prefix (which is how both apps did it
|
|
3804
|
+
* before this option existed) stops catching them the moment folding turns on, and starts
|
|
3805
|
+
* replaying whatever the row held. Opting in is therefore a statement that the caller has
|
|
3806
|
+
* checked its own filters and set {@link toolResultsHistoryExclude} for any payload that must
|
|
3807
|
+
* not reach the model.
|
|
3808
|
+
*
|
|
3809
|
+
* With it off, rows are dropped from the replayed history rather than sent verbatim. Verbatim
|
|
3810
|
+
* would put two consecutive `user` turns on the wire, and the model answers the previous turn
|
|
3811
|
+
* instead of the new prompt.
|
|
3812
|
+
*/
|
|
3813
|
+
foldToolResultsInHistory?: boolean;
|
|
3780
3814
|
/**
|
|
3781
3815
|
* Pre-processors run after the last user message is received but before
|
|
3782
3816
|
* the first LLM request. Each receives the prompt text and a shared
|
|
@@ -4126,6 +4160,20 @@ interface BaseSendMessageSuccessResult {
|
|
|
4126
4160
|
error: null;
|
|
4127
4161
|
userMessage: StoredMessage;
|
|
4128
4162
|
assistantMessage: StoredMessage;
|
|
4163
|
+
/** Results from tools the SDK auto-executed this turn (e.g. display tools). */
|
|
4164
|
+
autoExecutedToolResults?: {
|
|
4165
|
+
name: string;
|
|
4166
|
+
result: unknown;
|
|
4167
|
+
}[];
|
|
4168
|
+
/**
|
|
4169
|
+
* The synthetic `[Tool Execution Results]` row those results were persisted as.
|
|
4170
|
+
*
|
|
4171
|
+
* Returned so a caller can key its transient overlay on the id the SDK actually wrote instead of
|
|
4172
|
+
* deriving one and hoping the two agree — that guesswork is what mobile's per-card persist
|
|
4173
|
+
* workarounds existed to do (#5519). Absent when the turn executed no tools, or when the row write
|
|
4174
|
+
* failed (non-fatal: the assistant reply is already stored).
|
|
4175
|
+
*/
|
|
4176
|
+
toolResultsMessage?: StoredMessage;
|
|
4129
4177
|
}
|
|
4130
4178
|
interface BaseSendMessageSkippedResult {
|
|
4131
4179
|
data: ApiResponse;
|
|
@@ -5820,6 +5868,31 @@ interface QuarantinedMemoryInfo {
|
|
|
5820
5868
|
interface ExtractFactsOptions extends PortalLlmAuth {
|
|
5821
5869
|
baseUrl?: string;
|
|
5822
5870
|
model?: string;
|
|
5871
|
+
/**
|
|
5872
|
+
* Optional per-call request path override, forwarded to
|
|
5873
|
+
* {@link callPortalJsonCompletion}. When set, the extraction call POSTs to
|
|
5874
|
+
* `baseUrl + endpointOverride` instead of the default
|
|
5875
|
+
* `/api/v1/chat/completions` — path only, body unchanged. Lets callers route
|
|
5876
|
+
* this internal-utility pass to a dedicated endpoint. Invalid values throw at
|
|
5877
|
+
* call time (see {@link validateEndpointOverride}).
|
|
5878
|
+
*
|
|
5879
|
+
* Why this exists (anuma-ai/ai-memoryless-client#5536): auto-extraction is the
|
|
5880
|
+
* highest-volume first-party background call in the product — one per
|
|
5881
|
+
* extracting turn, on every platform — and it carries no flow fingerprint, so
|
|
5882
|
+
* the portal's freeloader detector classifies it as scripted abuse. In reject
|
|
5883
|
+
* mode that 403s every basic-tier extraction, which surfaces here as
|
|
5884
|
+
* `onExhaustedEmpty` → `empty-after-retry` and leaves free-tier vaults empty.
|
|
5885
|
+
* {@link TopicExtractOptions.endpointOverride} already exists for the same
|
|
5886
|
+
* reason on the topic pass; this is the fact pass catching up.
|
|
5887
|
+
*
|
|
5888
|
+
* IMPORTANT — the utility endpoint clamps to a PRICE CEILING and never
|
|
5889
|
+
* rejects, so pointing this at `/api/v1/utility/chat/completions` while the
|
|
5890
|
+
* portal's ceiling prices below {@link DEFAULT_EXTRACTION_MODEL} silently
|
|
5891
|
+
* rewrites the model instead of 403-ing. That trades a visible failure for an
|
|
5892
|
+
* invisible quality regression: raise `PORTAL_UTILITY_CEILING_MODEL` to at
|
|
5893
|
+
* least the extraction model's rate BEFORE setting this in a client.
|
|
5894
|
+
*/
|
|
5895
|
+
endpointOverride?: string;
|
|
5823
5896
|
/** Override the global fetch implementation (useful for tests). */
|
|
5824
5897
|
fetchFn?: typeof fetch;
|
|
5825
5898
|
/**
|