@anuma/sdk 3.11.6 → 3.12.1
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-Y7XT2VNQ.mjs → chunk-WV7C7VHF.mjs} +19 -1
- package/dist/expo/{consolidate-HYIEFPFA.mjs → consolidate-AURTG64H.mjs} +4 -12
- package/dist/expo/index.cjs +74 -19
- package/dist/expo/index.d.mts +68 -5
- package/dist/expo/index.d.ts +68 -5
- package/dist/expo/index.mjs +55 -11
- package/dist/react/{chunk-TP6CJZ25.mjs → chunk-3NPDZZGO.mjs} +19 -1
- package/dist/react/{consolidate-DOY3ZWTE.mjs → consolidate-R6FH7XMV.mjs} +4 -12
- package/dist/react/index.cjs +74 -19
- package/dist/react/index.d.mts +28 -5
- package/dist/react/index.d.ts +28 -5
- package/dist/react/index.mjs +55 -11
- package/dist/server/{chunk-PXN5Q3MD.mjs → chunk-RT75PNSJ.mjs} +19 -1
- package/dist/server/{consolidate-JMGL3MXG.mjs → consolidate-4VEAS3YN.mjs} +4 -12
- package/dist/server/index.cjs +74 -19
- package/dist/server/index.d.mts +69 -6
- package/dist/server/index.d.ts +69 -6
- package/dist/server/index.mjs +55 -11
- package/package.json +1 -1
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getLogger
|
|
3
|
+
} from "./chunk-ILAWDQDE.mjs";
|
|
4
|
+
|
|
1
5
|
// src/lib/pii/patterns.ts
|
|
2
6
|
function luhnCheck(digits) {
|
|
3
7
|
let sum = 0;
|
|
@@ -637,10 +641,24 @@ function createStreamingDeAnonymizer(redactor, emit) {
|
|
|
637
641
|
};
|
|
638
642
|
}
|
|
639
643
|
|
|
644
|
+
// src/lib/memory/consolidationFallback.ts
|
|
645
|
+
function notifyConsolidationFallback(reason, onFallback, detail) {
|
|
646
|
+
if (detail !== void 0) {
|
|
647
|
+
getLogger().warn(`memory/consolidate: degraded to create (${reason})`, detail);
|
|
648
|
+
} else {
|
|
649
|
+
getLogger().warn(`memory/consolidate: degraded to create (${reason})`);
|
|
650
|
+
}
|
|
651
|
+
try {
|
|
652
|
+
onFallback?.(reason);
|
|
653
|
+
} catch {
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
|
|
640
657
|
export {
|
|
641
658
|
PII_PATTERNS,
|
|
642
659
|
PiiRedactor,
|
|
643
660
|
isPiiRedactor,
|
|
644
661
|
resolvePiiRedactor,
|
|
645
|
-
createStreamingDeAnonymizer
|
|
662
|
+
createStreamingDeAnonymizer,
|
|
663
|
+
notifyConsolidationFallback
|
|
646
664
|
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
|
+
notifyConsolidationFallback,
|
|
2
3
|
resolvePiiRedactor
|
|
3
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-WV7C7VHF.mjs";
|
|
4
5
|
import {
|
|
5
|
-
callPortalJsonCompletion
|
|
6
|
-
getLogger
|
|
6
|
+
callPortalJsonCompletion
|
|
7
7
|
} from "./chunk-ILAWDQDE.mjs";
|
|
8
8
|
import "./chunk-GYKJOWEO.mjs";
|
|
9
9
|
|
|
@@ -102,15 +102,7 @@ ${candidateText}`;
|
|
|
102
102
|
return result;
|
|
103
103
|
}
|
|
104
104
|
function degrade(reason, fallback, options, detail) {
|
|
105
|
-
|
|
106
|
-
getLogger().warn(`memory/consolidate: degraded to create (${reason})`, detail);
|
|
107
|
-
} else {
|
|
108
|
-
getLogger().warn(`memory/consolidate: degraded to create (${reason})`);
|
|
109
|
-
}
|
|
110
|
-
try {
|
|
111
|
-
options.onFallback?.(reason);
|
|
112
|
-
} catch {
|
|
113
|
-
}
|
|
105
|
+
notifyConsolidationFallback(reason, options.onFallback, detail);
|
|
114
106
|
return { ...fallback, fallbackReason: reason };
|
|
115
107
|
}
|
|
116
108
|
function validate(parsed, newContent, validIds) {
|
package/dist/expo/index.cjs
CHANGED
|
@@ -8170,6 +8170,25 @@ var init_searchTool = __esm({
|
|
|
8170
8170
|
}
|
|
8171
8171
|
});
|
|
8172
8172
|
|
|
8173
|
+
// src/lib/memory/consolidationFallback.ts
|
|
8174
|
+
function notifyConsolidationFallback(reason, onFallback, detail) {
|
|
8175
|
+
if (detail !== void 0) {
|
|
8176
|
+
getLogger().warn(`memory/consolidate: degraded to create (${reason})`, detail);
|
|
8177
|
+
} else {
|
|
8178
|
+
getLogger().warn(`memory/consolidate: degraded to create (${reason})`);
|
|
8179
|
+
}
|
|
8180
|
+
try {
|
|
8181
|
+
onFallback?.(reason);
|
|
8182
|
+
} catch {
|
|
8183
|
+
}
|
|
8184
|
+
}
|
|
8185
|
+
var init_consolidationFallback = __esm({
|
|
8186
|
+
"src/lib/memory/consolidationFallback.ts"() {
|
|
8187
|
+
"use strict";
|
|
8188
|
+
init_logger();
|
|
8189
|
+
}
|
|
8190
|
+
});
|
|
8191
|
+
|
|
8173
8192
|
// src/lib/memory/consolidate.ts
|
|
8174
8193
|
var consolidate_exports = {};
|
|
8175
8194
|
__export(consolidate_exports, {
|
|
@@ -8234,15 +8253,7 @@ ${candidateText}`;
|
|
|
8234
8253
|
return result;
|
|
8235
8254
|
}
|
|
8236
8255
|
function degrade(reason, fallback, options, detail) {
|
|
8237
|
-
|
|
8238
|
-
getLogger().warn(`memory/consolidate: degraded to create (${reason})`, detail);
|
|
8239
|
-
} else {
|
|
8240
|
-
getLogger().warn(`memory/consolidate: degraded to create (${reason})`);
|
|
8241
|
-
}
|
|
8242
|
-
try {
|
|
8243
|
-
options.onFallback?.(reason);
|
|
8244
|
-
} catch {
|
|
8245
|
-
}
|
|
8256
|
+
notifyConsolidationFallback(reason, options.onFallback, detail);
|
|
8246
8257
|
return { ...fallback, fallbackReason: reason };
|
|
8247
8258
|
}
|
|
8248
8259
|
function validate2(parsed, newContent, validIds) {
|
|
@@ -8282,8 +8293,8 @@ var DEFAULT_CONSOLIDATION_MODEL, DEFAULT_CONSOLIDATE_ATTEMPTS, DEFAULT_CONSOLIDA
|
|
|
8282
8293
|
var init_consolidate = __esm({
|
|
8283
8294
|
"src/lib/memory/consolidate.ts"() {
|
|
8284
8295
|
"use strict";
|
|
8285
|
-
init_logger();
|
|
8286
8296
|
init_redactor();
|
|
8297
|
+
init_consolidationFallback();
|
|
8287
8298
|
init_portalLlm();
|
|
8288
8299
|
DEFAULT_CONSOLIDATION_MODEL = "inclusionai/ling-2.6-flash";
|
|
8289
8300
|
DEFAULT_CONSOLIDATE_ATTEMPTS = 3;
|
|
@@ -11786,13 +11797,18 @@ Executing tool: ${toolInfo}
|
|
|
11786
11797
|
}
|
|
11787
11798
|
const truncatedToNothing = (acc) => acc.finishReason === "length" && acc.toolCalls.size === 0 && acc.content.trim() === "";
|
|
11788
11799
|
const TRUNCATION_ERROR = "Model response was truncated at the output-token limit before it produced any usable content or tool call. Retry with a higher `maxOutputTokens`, or prompt for fewer/smaller tool calls per turn.";
|
|
11800
|
+
const terminalStateOf = (acc) => ({
|
|
11801
|
+
...acc.finishReason !== void 0 && { finishReason: acc.finishReason },
|
|
11802
|
+
finalToolCallCount: acc.toolCalls.size
|
|
11803
|
+
});
|
|
11789
11804
|
if (toolIteration > 0) {
|
|
11790
11805
|
if (truncatedToNothing(currentAccumulator)) {
|
|
11791
11806
|
await fireRunError({ error: TRUNCATION_ERROR, stage: "model" });
|
|
11792
11807
|
return {
|
|
11793
11808
|
data: buildResponseFinal(currentAccumulator),
|
|
11794
11809
|
error: TRUNCATION_ERROR,
|
|
11795
|
-
toolsChecksum: currentAccumulator.toolsChecksum
|
|
11810
|
+
toolsChecksum: currentAccumulator.toolsChecksum,
|
|
11811
|
+
terminalState: terminalStateOf(currentAccumulator)
|
|
11796
11812
|
};
|
|
11797
11813
|
}
|
|
11798
11814
|
const finalResponse = buildResponseFinal(currentAccumulator);
|
|
@@ -11805,7 +11821,8 @@ Executing tool: ${toolInfo}
|
|
|
11805
11821
|
data: finalResponse,
|
|
11806
11822
|
error: null,
|
|
11807
11823
|
toolsChecksum: currentAccumulator.toolsChecksum,
|
|
11808
|
-
autoExecutedToolResults: accumulatedToolResults
|
|
11824
|
+
autoExecutedToolResults: accumulatedToolResults,
|
|
11825
|
+
terminalState: terminalStateOf(currentAccumulator)
|
|
11809
11826
|
};
|
|
11810
11827
|
}
|
|
11811
11828
|
if (truncatedToNothing(accumulator)) {
|
|
@@ -11813,7 +11830,8 @@ Executing tool: ${toolInfo}
|
|
|
11813
11830
|
return {
|
|
11814
11831
|
data: response,
|
|
11815
11832
|
error: TRUNCATION_ERROR,
|
|
11816
|
-
toolsChecksum: accumulator.toolsChecksum
|
|
11833
|
+
toolsChecksum: accumulator.toolsChecksum,
|
|
11834
|
+
terminalState: terminalStateOf(accumulator)
|
|
11817
11835
|
};
|
|
11818
11836
|
}
|
|
11819
11837
|
if (onFinish) onFinish(response);
|
|
@@ -11824,7 +11842,8 @@ Executing tool: ${toolInfo}
|
|
|
11824
11842
|
return {
|
|
11825
11843
|
data: response,
|
|
11826
11844
|
error: null,
|
|
11827
|
-
toolsChecksum: accumulator.toolsChecksum
|
|
11845
|
+
toolsChecksum: accumulator.toolsChecksum,
|
|
11846
|
+
terminalState: terminalStateOf(accumulator)
|
|
11828
11847
|
};
|
|
11829
11848
|
} catch (err) {
|
|
11830
11849
|
if (isAbortError(err)) {
|
|
@@ -14840,6 +14859,7 @@ init_constants();
|
|
|
14840
14859
|
init_embeddings();
|
|
14841
14860
|
init_vector();
|
|
14842
14861
|
init_searchTool();
|
|
14862
|
+
init_consolidationFallback();
|
|
14843
14863
|
var DEFAULT_AUTO_MERGE_THRESHOLD = 0.8;
|
|
14844
14864
|
var DEFAULT_SCOPE = "private";
|
|
14845
14865
|
var DEFAULT_CONSOLIDATE_THRESHOLD = 0.55;
|
|
@@ -15019,6 +15039,11 @@ async function retain(content, ctx, options = {}) {
|
|
|
15019
15039
|
proofCount: 1
|
|
15020
15040
|
};
|
|
15021
15041
|
}
|
|
15042
|
+
notifyConsolidationFallback(
|
|
15043
|
+
"target_vanished",
|
|
15044
|
+
options.consolidateOptions?.onFallback,
|
|
15045
|
+
`supersede: primary target ${primaryTargetId} retired or deleted inside the atomic write`
|
|
15046
|
+
);
|
|
15022
15047
|
}
|
|
15023
15048
|
const created = await createVaultMemoryOp(ctx.vaultCtx, createOpts);
|
|
15024
15049
|
ctx.vaultCache.set(created.uniqueId, Float32Array.from(embedding));
|
|
@@ -15070,6 +15095,10 @@ function pickFactTypeUpdate(existing, incoming) {
|
|
|
15070
15095
|
function resurrectFields(existing) {
|
|
15071
15096
|
return typeof existing.archivedAt === "number" ? { restore: true } : { preserveUpdatedAt: true };
|
|
15072
15097
|
}
|
|
15098
|
+
function abandonToRace(options, detail) {
|
|
15099
|
+
notifyConsolidationFallback("target_vanished", options.consolidateOptions?.onFallback, detail);
|
|
15100
|
+
return null;
|
|
15101
|
+
}
|
|
15073
15102
|
async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
15074
15103
|
const consolidateOptions = options.consolidateOptions;
|
|
15075
15104
|
if (!consolidateOptions) return null;
|
|
@@ -15102,12 +15131,22 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
15102
15131
|
const existing = await getVaultMemoryOp(ctx.vaultCtx, id);
|
|
15103
15132
|
if (existing && !existing.supersededBy) valid.push(id);
|
|
15104
15133
|
}
|
|
15105
|
-
if (valid.length === 0)
|
|
15134
|
+
if (valid.length === 0) {
|
|
15135
|
+
return abandonToRace(
|
|
15136
|
+
options,
|
|
15137
|
+
`supersede: all ${requestedIds.length} target(s) deleted or already superseded`
|
|
15138
|
+
);
|
|
15139
|
+
}
|
|
15106
15140
|
return { supersede: valid, content: decision.content };
|
|
15107
15141
|
}
|
|
15108
15142
|
if (decision.action === "noop" && decision.targetId) {
|
|
15109
15143
|
const existing = await getVaultMemoryOp(ctx.vaultCtx, decision.targetId);
|
|
15110
|
-
if (!existing || existing.supersededBy)
|
|
15144
|
+
if (!existing || existing.supersededBy) {
|
|
15145
|
+
return abandonToRace(
|
|
15146
|
+
options,
|
|
15147
|
+
`noop: target ${decision.targetId} ${existing ? "superseded" : "deleted"} before the write`
|
|
15148
|
+
);
|
|
15149
|
+
}
|
|
15111
15150
|
const mergedSourceIds = unionStrings(
|
|
15112
15151
|
existing.sourceChunkIds ?? [],
|
|
15113
15152
|
options.sourceChunkIds ?? []
|
|
@@ -15132,7 +15171,10 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
15132
15171
|
});
|
|
15133
15172
|
if (!updated) {
|
|
15134
15173
|
await assertMergeTargetGoneOrThrow(ctx, decision.targetId);
|
|
15135
|
-
return
|
|
15174
|
+
return abandonToRace(
|
|
15175
|
+
options,
|
|
15176
|
+
`noop: target ${decision.targetId} deleted mid-write (proof-count bump lost)`
|
|
15177
|
+
);
|
|
15136
15178
|
}
|
|
15137
15179
|
return {
|
|
15138
15180
|
done: {
|
|
@@ -15145,7 +15187,12 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
15145
15187
|
}
|
|
15146
15188
|
if (decision.action === "update" && decision.targetId && decision.content) {
|
|
15147
15189
|
const existing = await getVaultMemoryOp(ctx.vaultCtx, decision.targetId);
|
|
15148
|
-
if (!existing || existing.supersededBy)
|
|
15190
|
+
if (!existing || existing.supersededBy) {
|
|
15191
|
+
return abandonToRace(
|
|
15192
|
+
options,
|
|
15193
|
+
`update: target ${decision.targetId} ${existing ? "superseded" : "deleted"} before the write`
|
|
15194
|
+
);
|
|
15195
|
+
}
|
|
15149
15196
|
const mergedSourceIds = unionStrings(
|
|
15150
15197
|
existing.sourceChunkIds ?? [],
|
|
15151
15198
|
options.sourceChunkIds ?? []
|
|
@@ -15176,7 +15223,10 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
15176
15223
|
});
|
|
15177
15224
|
if (!updated) {
|
|
15178
15225
|
await assertMergeTargetGoneOrThrow(ctx, decision.targetId);
|
|
15179
|
-
return
|
|
15226
|
+
return abandonToRace(
|
|
15227
|
+
options,
|
|
15228
|
+
`update: target ${decision.targetId} deleted mid-write (consolidated rewrite lost)`
|
|
15229
|
+
);
|
|
15180
15230
|
}
|
|
15181
15231
|
ctx.vaultCache.set(decision.targetId, Float32Array.from(newEmbedding));
|
|
15182
15232
|
return {
|
|
@@ -15188,6 +15238,11 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
15188
15238
|
}
|
|
15189
15239
|
};
|
|
15190
15240
|
}
|
|
15241
|
+
notifyConsolidationFallback(
|
|
15242
|
+
"invalid_response",
|
|
15243
|
+
options.consolidateOptions?.onFallback,
|
|
15244
|
+
`unapplicable ${decision.action} decision reached the applier \u2014 validate() should have rejected it`
|
|
15245
|
+
);
|
|
15191
15246
|
return null;
|
|
15192
15247
|
}
|
|
15193
15248
|
async function assertMergeTargetGoneOrThrow(ctx, targetId) {
|
package/dist/expo/index.d.mts
CHANGED
|
@@ -2429,6 +2429,32 @@ type StepFinishEvent = {
|
|
|
2429
2429
|
outputTokens?: number;
|
|
2430
2430
|
};
|
|
2431
2431
|
};
|
|
2432
|
+
/**
|
|
2433
|
+
* Terminal state of the LAST model response in the turn, normalized to the
|
|
2434
|
+
* completions vocabulary (`"stop"` | `"length"` | `"tool_calls"` | provider-
|
|
2435
|
+
* specific values). `undefined` when the stream carried no finish reason at all.
|
|
2436
|
+
*
|
|
2437
|
+
* Exposed because neither response shape reliably carries it out to a caller.
|
|
2438
|
+
* The Responses API shape has no field for it — `LlmapiResponseResponse` declares
|
|
2439
|
+
* neither `status` nor `incomplete_details` — so `buildFinalResponse` cannot
|
|
2440
|
+
* surface truncation there even though the loop detected it (`responses.ts`
|
|
2441
|
+
* normalizes it onto the accumulator). Completions does expose
|
|
2442
|
+
* `choices[0].finish_reason`, but omits `tool_calls` entirely when there are
|
|
2443
|
+
* none, so a caller sniffing the response cannot tell "no tool calls" from
|
|
2444
|
+
* "field absent".
|
|
2445
|
+
*
|
|
2446
|
+
* The loop already knows both, unambiguously and identically for either API.
|
|
2447
|
+
* Reporting them here means callers and test harnesses stop reverse-engineering
|
|
2448
|
+
* them from a response shape that cannot answer. See anuma-ai/sdk#805.
|
|
2449
|
+
*/
|
|
2450
|
+
type RunTerminalState = {
|
|
2451
|
+
/** Normalized finish reason of the final response. `"length"` means the output
|
|
2452
|
+
* ceiling cut it off; anything else means the model stopped on its own. */
|
|
2453
|
+
finishReason?: string;
|
|
2454
|
+
/** Tool calls the final response carried. `0` is meaningful — combined with
|
|
2455
|
+
* empty content it identifies a turn that ended having produced nothing. */
|
|
2456
|
+
finalToolCallCount: number;
|
|
2457
|
+
};
|
|
2432
2458
|
type RunToolLoopResult = {
|
|
2433
2459
|
data: ApiResponse;
|
|
2434
2460
|
error: null;
|
|
@@ -2436,6 +2462,8 @@ type RunToolLoopResult = {
|
|
|
2436
2462
|
toolsChecksum?: string;
|
|
2437
2463
|
/** Results from tools that were auto-executed by the SDK */
|
|
2438
2464
|
autoExecutedToolResults?: AutoExecutedToolResult[];
|
|
2465
|
+
/** Terminal state of the final model response. See {@link RunTerminalState}. */
|
|
2466
|
+
terminalState?: RunTerminalState;
|
|
2439
2467
|
} | {
|
|
2440
2468
|
data: ApiResponse | null;
|
|
2441
2469
|
error: string;
|
|
@@ -2447,6 +2475,18 @@ type RunToolLoopResult = {
|
|
|
2447
2475
|
detached?: true;
|
|
2448
2476
|
/** Non-null only when `resumable` was true AND an inference id was captured before detach. */
|
|
2449
2477
|
resume?: StreamResumeHandle | null;
|
|
2478
|
+
/**
|
|
2479
|
+
* Terminal state of the final model response, when the failure is one the
|
|
2480
|
+
* loop diagnosed FROM that response — today, the truncated-to-nothing
|
|
2481
|
+
* error. See {@link RunTerminalState}.
|
|
2482
|
+
*
|
|
2483
|
+
* Absent on failures that never got a terminal response to read (transport
|
|
2484
|
+
* errors, detach, an SSE failure mid-stream), which is why it stays
|
|
2485
|
+
* optional here. Present on the truncation error specifically because that
|
|
2486
|
+
* is where it is most diagnostic: a caller can branch on
|
|
2487
|
+
* `finishReason === "length"` instead of matching the error string.
|
|
2488
|
+
*/
|
|
2489
|
+
terminalState?: RunTerminalState;
|
|
2450
2490
|
};
|
|
2451
2491
|
/** Capability header: tells the portal this client can resume a detached stream. Pinned with zeta-chain/ai-portal#1139. */
|
|
2452
2492
|
declare const STREAM_RESUMABLE_HEADER = "X-Stream-Resumable";
|
|
@@ -5282,8 +5322,26 @@ interface RecallDiagnostics {
|
|
|
5282
5322
|
}
|
|
5283
5323
|
type RetainAction = "create" | "merge" | "update" | "skip" | "suppressed" | "supersede";
|
|
5284
5324
|
type RetainSource = "manual" | "auto-extracted" | "capsule";
|
|
5285
|
-
/**
|
|
5286
|
-
|
|
5325
|
+
/**
|
|
5326
|
+
* Why a retain fell back to "create" instead of applying a consolidation
|
|
5327
|
+
* decision. Each value names a DIFFERENT thing to go fix, which is the point of
|
|
5328
|
+
* keeping them apart:
|
|
5329
|
+
*
|
|
5330
|
+
* - `llm_error` — the consolidation call never produced a response (network,
|
|
5331
|
+
* timeout, 5xx, 429, empty completion, or missing credentials). Look at the
|
|
5332
|
+
* portal and the auth config.
|
|
5333
|
+
* - `invalid_response` — the model answered, but with something unusable: an
|
|
5334
|
+
* unknown action, a targetId that was not in the candidate set, an `update` or
|
|
5335
|
+
* `supersede` with empty content, a `noop` with no target. Look at the prompt
|
|
5336
|
+
* and the model.
|
|
5337
|
+
* - `target_vanished` — the model returned a decision that was valid when it was
|
|
5338
|
+
* made, and the row it named was deleted or superseded by a concurrent writer
|
|
5339
|
+
* before the write landed. Nothing is broken in the consolidator; a sustained
|
|
5340
|
+
* rate points at write contention (for example an auto-extraction worker and a
|
|
5341
|
+
* manual write racing over the same vault), which quietly costs you the
|
|
5342
|
+
* dedup that decision would have performed.
|
|
5343
|
+
*/
|
|
5344
|
+
type ConsolidationFallbackReason = "llm_error" | "invalid_response" | "target_vanished";
|
|
5287
5345
|
interface RetainOptions {
|
|
5288
5346
|
source?: RetainSource;
|
|
5289
5347
|
sourceChunkIds?: string[];
|
|
@@ -5299,7 +5357,8 @@ interface RetainOptions {
|
|
|
5299
5357
|
* Returns `action: 'suppressed'` with the matched `tombstoneId`.
|
|
5300
5358
|
*/
|
|
5301
5359
|
respectTombstones?: boolean;
|
|
5302
|
-
/** Cosine similarity threshold for auto-merge. Default: 0.
|
|
5360
|
+
/** Cosine similarity threshold for auto-merge. Default: 0.8
|
|
5361
|
+
* (`DEFAULT_AUTO_MERGE_THRESHOLD` in retain.ts — the source of truth). */
|
|
5303
5362
|
autoMergeThreshold?: number;
|
|
5304
5363
|
/**
|
|
5305
5364
|
* When provided, runs an LLM-based consolidation pass against the top-K
|
|
@@ -5327,9 +5386,13 @@ interface RetainOptions {
|
|
|
5327
5386
|
*/
|
|
5328
5387
|
piiRedaction?: boolean | PiiRedactor;
|
|
5329
5388
|
};
|
|
5330
|
-
/** Cosine similarity floor for the consolidator candidate set. Default: 0.
|
|
5389
|
+
/** Cosine similarity floor for the consolidator candidate set. Default: 0.55
|
|
5390
|
+
* (`DEFAULT_CONSOLIDATE_THRESHOLD` in retain.ts — the source of truth). */
|
|
5331
5391
|
consolidateThreshold?: number;
|
|
5332
|
-
/** Top-K consolidation candidates to feed the LLM. Default:
|
|
5392
|
+
/** Top-K consolidation candidates to feed the LLM. Default: 20
|
|
5393
|
+
* (`DEFAULT_CONSOLIDATE_TOP_K` in retain.ts — the source of truth). Widened
|
|
5394
|
+
* from 5 so a value change can find and retire ALL stale duplicates of the
|
|
5395
|
+
* old value in one pass, not just the nearest few. */
|
|
5333
5396
|
consolidateTopK?: number;
|
|
5334
5397
|
/**
|
|
5335
5398
|
* W6 temporal lane — when the event in this fact occurred. Persisted to
|
package/dist/expo/index.d.ts
CHANGED
|
@@ -2429,6 +2429,32 @@ type StepFinishEvent = {
|
|
|
2429
2429
|
outputTokens?: number;
|
|
2430
2430
|
};
|
|
2431
2431
|
};
|
|
2432
|
+
/**
|
|
2433
|
+
* Terminal state of the LAST model response in the turn, normalized to the
|
|
2434
|
+
* completions vocabulary (`"stop"` | `"length"` | `"tool_calls"` | provider-
|
|
2435
|
+
* specific values). `undefined` when the stream carried no finish reason at all.
|
|
2436
|
+
*
|
|
2437
|
+
* Exposed because neither response shape reliably carries it out to a caller.
|
|
2438
|
+
* The Responses API shape has no field for it — `LlmapiResponseResponse` declares
|
|
2439
|
+
* neither `status` nor `incomplete_details` — so `buildFinalResponse` cannot
|
|
2440
|
+
* surface truncation there even though the loop detected it (`responses.ts`
|
|
2441
|
+
* normalizes it onto the accumulator). Completions does expose
|
|
2442
|
+
* `choices[0].finish_reason`, but omits `tool_calls` entirely when there are
|
|
2443
|
+
* none, so a caller sniffing the response cannot tell "no tool calls" from
|
|
2444
|
+
* "field absent".
|
|
2445
|
+
*
|
|
2446
|
+
* The loop already knows both, unambiguously and identically for either API.
|
|
2447
|
+
* Reporting them here means callers and test harnesses stop reverse-engineering
|
|
2448
|
+
* them from a response shape that cannot answer. See anuma-ai/sdk#805.
|
|
2449
|
+
*/
|
|
2450
|
+
type RunTerminalState = {
|
|
2451
|
+
/** Normalized finish reason of the final response. `"length"` means the output
|
|
2452
|
+
* ceiling cut it off; anything else means the model stopped on its own. */
|
|
2453
|
+
finishReason?: string;
|
|
2454
|
+
/** Tool calls the final response carried. `0` is meaningful — combined with
|
|
2455
|
+
* empty content it identifies a turn that ended having produced nothing. */
|
|
2456
|
+
finalToolCallCount: number;
|
|
2457
|
+
};
|
|
2432
2458
|
type RunToolLoopResult = {
|
|
2433
2459
|
data: ApiResponse;
|
|
2434
2460
|
error: null;
|
|
@@ -2436,6 +2462,8 @@ type RunToolLoopResult = {
|
|
|
2436
2462
|
toolsChecksum?: string;
|
|
2437
2463
|
/** Results from tools that were auto-executed by the SDK */
|
|
2438
2464
|
autoExecutedToolResults?: AutoExecutedToolResult[];
|
|
2465
|
+
/** Terminal state of the final model response. See {@link RunTerminalState}. */
|
|
2466
|
+
terminalState?: RunTerminalState;
|
|
2439
2467
|
} | {
|
|
2440
2468
|
data: ApiResponse | null;
|
|
2441
2469
|
error: string;
|
|
@@ -2447,6 +2475,18 @@ type RunToolLoopResult = {
|
|
|
2447
2475
|
detached?: true;
|
|
2448
2476
|
/** Non-null only when `resumable` was true AND an inference id was captured before detach. */
|
|
2449
2477
|
resume?: StreamResumeHandle | null;
|
|
2478
|
+
/**
|
|
2479
|
+
* Terminal state of the final model response, when the failure is one the
|
|
2480
|
+
* loop diagnosed FROM that response — today, the truncated-to-nothing
|
|
2481
|
+
* error. See {@link RunTerminalState}.
|
|
2482
|
+
*
|
|
2483
|
+
* Absent on failures that never got a terminal response to read (transport
|
|
2484
|
+
* errors, detach, an SSE failure mid-stream), which is why it stays
|
|
2485
|
+
* optional here. Present on the truncation error specifically because that
|
|
2486
|
+
* is where it is most diagnostic: a caller can branch on
|
|
2487
|
+
* `finishReason === "length"` instead of matching the error string.
|
|
2488
|
+
*/
|
|
2489
|
+
terminalState?: RunTerminalState;
|
|
2450
2490
|
};
|
|
2451
2491
|
/** Capability header: tells the portal this client can resume a detached stream. Pinned with zeta-chain/ai-portal#1139. */
|
|
2452
2492
|
declare const STREAM_RESUMABLE_HEADER = "X-Stream-Resumable";
|
|
@@ -5282,8 +5322,26 @@ interface RecallDiagnostics {
|
|
|
5282
5322
|
}
|
|
5283
5323
|
type RetainAction = "create" | "merge" | "update" | "skip" | "suppressed" | "supersede";
|
|
5284
5324
|
type RetainSource = "manual" | "auto-extracted" | "capsule";
|
|
5285
|
-
/**
|
|
5286
|
-
|
|
5325
|
+
/**
|
|
5326
|
+
* Why a retain fell back to "create" instead of applying a consolidation
|
|
5327
|
+
* decision. Each value names a DIFFERENT thing to go fix, which is the point of
|
|
5328
|
+
* keeping them apart:
|
|
5329
|
+
*
|
|
5330
|
+
* - `llm_error` — the consolidation call never produced a response (network,
|
|
5331
|
+
* timeout, 5xx, 429, empty completion, or missing credentials). Look at the
|
|
5332
|
+
* portal and the auth config.
|
|
5333
|
+
* - `invalid_response` — the model answered, but with something unusable: an
|
|
5334
|
+
* unknown action, a targetId that was not in the candidate set, an `update` or
|
|
5335
|
+
* `supersede` with empty content, a `noop` with no target. Look at the prompt
|
|
5336
|
+
* and the model.
|
|
5337
|
+
* - `target_vanished` — the model returned a decision that was valid when it was
|
|
5338
|
+
* made, and the row it named was deleted or superseded by a concurrent writer
|
|
5339
|
+
* before the write landed. Nothing is broken in the consolidator; a sustained
|
|
5340
|
+
* rate points at write contention (for example an auto-extraction worker and a
|
|
5341
|
+
* manual write racing over the same vault), which quietly costs you the
|
|
5342
|
+
* dedup that decision would have performed.
|
|
5343
|
+
*/
|
|
5344
|
+
type ConsolidationFallbackReason = "llm_error" | "invalid_response" | "target_vanished";
|
|
5287
5345
|
interface RetainOptions {
|
|
5288
5346
|
source?: RetainSource;
|
|
5289
5347
|
sourceChunkIds?: string[];
|
|
@@ -5299,7 +5357,8 @@ interface RetainOptions {
|
|
|
5299
5357
|
* Returns `action: 'suppressed'` with the matched `tombstoneId`.
|
|
5300
5358
|
*/
|
|
5301
5359
|
respectTombstones?: boolean;
|
|
5302
|
-
/** Cosine similarity threshold for auto-merge. Default: 0.
|
|
5360
|
+
/** Cosine similarity threshold for auto-merge. Default: 0.8
|
|
5361
|
+
* (`DEFAULT_AUTO_MERGE_THRESHOLD` in retain.ts — the source of truth). */
|
|
5303
5362
|
autoMergeThreshold?: number;
|
|
5304
5363
|
/**
|
|
5305
5364
|
* When provided, runs an LLM-based consolidation pass against the top-K
|
|
@@ -5327,9 +5386,13 @@ interface RetainOptions {
|
|
|
5327
5386
|
*/
|
|
5328
5387
|
piiRedaction?: boolean | PiiRedactor;
|
|
5329
5388
|
};
|
|
5330
|
-
/** Cosine similarity floor for the consolidator candidate set. Default: 0.
|
|
5389
|
+
/** Cosine similarity floor for the consolidator candidate set. Default: 0.55
|
|
5390
|
+
* (`DEFAULT_CONSOLIDATE_THRESHOLD` in retain.ts — the source of truth). */
|
|
5331
5391
|
consolidateThreshold?: number;
|
|
5332
|
-
/** Top-K consolidation candidates to feed the LLM. Default:
|
|
5392
|
+
/** Top-K consolidation candidates to feed the LLM. Default: 20
|
|
5393
|
+
* (`DEFAULT_CONSOLIDATE_TOP_K` in retain.ts — the source of truth). Widened
|
|
5394
|
+
* from 5 so a value change can find and retire ALL stale duplicates of the
|
|
5395
|
+
* old value in one pass, not just the nearest few. */
|
|
5333
5396
|
consolidateTopK?: number;
|
|
5334
5397
|
/**
|
|
5335
5398
|
* W6 temporal lane — when the event in this fact occurred. Persisted to
|
package/dist/expo/index.mjs
CHANGED
|
@@ -120,8 +120,9 @@ import {
|
|
|
120
120
|
PiiRedactor,
|
|
121
121
|
createStreamingDeAnonymizer,
|
|
122
122
|
isPiiRedactor,
|
|
123
|
+
notifyConsolidationFallback,
|
|
123
124
|
resolvePiiRedactor
|
|
124
|
-
} from "./chunk-
|
|
125
|
+
} from "./chunk-WV7C7VHF.mjs";
|
|
125
126
|
import {
|
|
126
127
|
callPortalJsonCompletion,
|
|
127
128
|
consoleLogger,
|
|
@@ -3389,13 +3390,18 @@ Executing tool: ${toolInfo}
|
|
|
3389
3390
|
}
|
|
3390
3391
|
const truncatedToNothing = (acc) => acc.finishReason === "length" && acc.toolCalls.size === 0 && acc.content.trim() === "";
|
|
3391
3392
|
const TRUNCATION_ERROR = "Model response was truncated at the output-token limit before it produced any usable content or tool call. Retry with a higher `maxOutputTokens`, or prompt for fewer/smaller tool calls per turn.";
|
|
3393
|
+
const terminalStateOf = (acc) => ({
|
|
3394
|
+
...acc.finishReason !== void 0 && { finishReason: acc.finishReason },
|
|
3395
|
+
finalToolCallCount: acc.toolCalls.size
|
|
3396
|
+
});
|
|
3392
3397
|
if (toolIteration > 0) {
|
|
3393
3398
|
if (truncatedToNothing(currentAccumulator)) {
|
|
3394
3399
|
await fireRunError({ error: TRUNCATION_ERROR, stage: "model" });
|
|
3395
3400
|
return {
|
|
3396
3401
|
data: buildResponseFinal(currentAccumulator),
|
|
3397
3402
|
error: TRUNCATION_ERROR,
|
|
3398
|
-
toolsChecksum: currentAccumulator.toolsChecksum
|
|
3403
|
+
toolsChecksum: currentAccumulator.toolsChecksum,
|
|
3404
|
+
terminalState: terminalStateOf(currentAccumulator)
|
|
3399
3405
|
};
|
|
3400
3406
|
}
|
|
3401
3407
|
const finalResponse = buildResponseFinal(currentAccumulator);
|
|
@@ -3408,7 +3414,8 @@ Executing tool: ${toolInfo}
|
|
|
3408
3414
|
data: finalResponse,
|
|
3409
3415
|
error: null,
|
|
3410
3416
|
toolsChecksum: currentAccumulator.toolsChecksum,
|
|
3411
|
-
autoExecutedToolResults: accumulatedToolResults
|
|
3417
|
+
autoExecutedToolResults: accumulatedToolResults,
|
|
3418
|
+
terminalState: terminalStateOf(currentAccumulator)
|
|
3412
3419
|
};
|
|
3413
3420
|
}
|
|
3414
3421
|
if (truncatedToNothing(accumulator)) {
|
|
@@ -3416,7 +3423,8 @@ Executing tool: ${toolInfo}
|
|
|
3416
3423
|
return {
|
|
3417
3424
|
data: response,
|
|
3418
3425
|
error: TRUNCATION_ERROR,
|
|
3419
|
-
toolsChecksum: accumulator.toolsChecksum
|
|
3426
|
+
toolsChecksum: accumulator.toolsChecksum,
|
|
3427
|
+
terminalState: terminalStateOf(accumulator)
|
|
3420
3428
|
};
|
|
3421
3429
|
}
|
|
3422
3430
|
if (onFinish) onFinish(response);
|
|
@@ -3427,7 +3435,8 @@ Executing tool: ${toolInfo}
|
|
|
3427
3435
|
return {
|
|
3428
3436
|
data: response,
|
|
3429
3437
|
error: null,
|
|
3430
|
-
toolsChecksum: accumulator.toolsChecksum
|
|
3438
|
+
toolsChecksum: accumulator.toolsChecksum,
|
|
3439
|
+
terminalState: terminalStateOf(accumulator)
|
|
3431
3440
|
};
|
|
3432
3441
|
} catch (err) {
|
|
3433
3442
|
if (isAbortError(err)) {
|
|
@@ -6575,6 +6584,11 @@ async function retain(content, ctx, options = {}) {
|
|
|
6575
6584
|
proofCount: 1
|
|
6576
6585
|
};
|
|
6577
6586
|
}
|
|
6587
|
+
notifyConsolidationFallback(
|
|
6588
|
+
"target_vanished",
|
|
6589
|
+
options.consolidateOptions?.onFallback,
|
|
6590
|
+
`supersede: primary target ${primaryTargetId} retired or deleted inside the atomic write`
|
|
6591
|
+
);
|
|
6578
6592
|
}
|
|
6579
6593
|
const created = await createVaultMemoryOp(ctx.vaultCtx, createOpts);
|
|
6580
6594
|
ctx.vaultCache.set(created.uniqueId, Float32Array.from(embedding));
|
|
@@ -6626,6 +6640,10 @@ function pickFactTypeUpdate(existing, incoming) {
|
|
|
6626
6640
|
function resurrectFields(existing) {
|
|
6627
6641
|
return typeof existing.archivedAt === "number" ? { restore: true } : { preserveUpdatedAt: true };
|
|
6628
6642
|
}
|
|
6643
|
+
function abandonToRace(options, detail) {
|
|
6644
|
+
notifyConsolidationFallback("target_vanished", options.consolidateOptions?.onFallback, detail);
|
|
6645
|
+
return null;
|
|
6646
|
+
}
|
|
6629
6647
|
async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
6630
6648
|
const consolidateOptions = options.consolidateOptions;
|
|
6631
6649
|
if (!consolidateOptions) return null;
|
|
@@ -6647,7 +6665,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
6647
6665
|
content: m.content,
|
|
6648
6666
|
similarity: m.similarity
|
|
6649
6667
|
}));
|
|
6650
|
-
const { consolidateMemory: doConsolidate } = await import("./consolidate-
|
|
6668
|
+
const { consolidateMemory: doConsolidate } = await import("./consolidate-AURTG64H.mjs");
|
|
6651
6669
|
const decision = await doConsolidate(trimmed, candidates, consolidateOptions);
|
|
6652
6670
|
if (decision.action === "create") return null;
|
|
6653
6671
|
if (decision.action === "supersede" && decision.content) {
|
|
@@ -6658,12 +6676,22 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
6658
6676
|
const existing = await getVaultMemoryOp(ctx.vaultCtx, id);
|
|
6659
6677
|
if (existing && !existing.supersededBy) valid.push(id);
|
|
6660
6678
|
}
|
|
6661
|
-
if (valid.length === 0)
|
|
6679
|
+
if (valid.length === 0) {
|
|
6680
|
+
return abandonToRace(
|
|
6681
|
+
options,
|
|
6682
|
+
`supersede: all ${requestedIds.length} target(s) deleted or already superseded`
|
|
6683
|
+
);
|
|
6684
|
+
}
|
|
6662
6685
|
return { supersede: valid, content: decision.content };
|
|
6663
6686
|
}
|
|
6664
6687
|
if (decision.action === "noop" && decision.targetId) {
|
|
6665
6688
|
const existing = await getVaultMemoryOp(ctx.vaultCtx, decision.targetId);
|
|
6666
|
-
if (!existing || existing.supersededBy)
|
|
6689
|
+
if (!existing || existing.supersededBy) {
|
|
6690
|
+
return abandonToRace(
|
|
6691
|
+
options,
|
|
6692
|
+
`noop: target ${decision.targetId} ${existing ? "superseded" : "deleted"} before the write`
|
|
6693
|
+
);
|
|
6694
|
+
}
|
|
6667
6695
|
const mergedSourceIds = unionStrings(
|
|
6668
6696
|
existing.sourceChunkIds ?? [],
|
|
6669
6697
|
options.sourceChunkIds ?? []
|
|
@@ -6688,7 +6716,10 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
6688
6716
|
});
|
|
6689
6717
|
if (!updated) {
|
|
6690
6718
|
await assertMergeTargetGoneOrThrow(ctx, decision.targetId);
|
|
6691
|
-
return
|
|
6719
|
+
return abandonToRace(
|
|
6720
|
+
options,
|
|
6721
|
+
`noop: target ${decision.targetId} deleted mid-write (proof-count bump lost)`
|
|
6722
|
+
);
|
|
6692
6723
|
}
|
|
6693
6724
|
return {
|
|
6694
6725
|
done: {
|
|
@@ -6701,7 +6732,12 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
6701
6732
|
}
|
|
6702
6733
|
if (decision.action === "update" && decision.targetId && decision.content) {
|
|
6703
6734
|
const existing = await getVaultMemoryOp(ctx.vaultCtx, decision.targetId);
|
|
6704
|
-
if (!existing || existing.supersededBy)
|
|
6735
|
+
if (!existing || existing.supersededBy) {
|
|
6736
|
+
return abandonToRace(
|
|
6737
|
+
options,
|
|
6738
|
+
`update: target ${decision.targetId} ${existing ? "superseded" : "deleted"} before the write`
|
|
6739
|
+
);
|
|
6740
|
+
}
|
|
6705
6741
|
const mergedSourceIds = unionStrings(
|
|
6706
6742
|
existing.sourceChunkIds ?? [],
|
|
6707
6743
|
options.sourceChunkIds ?? []
|
|
@@ -6732,7 +6768,10 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
6732
6768
|
});
|
|
6733
6769
|
if (!updated) {
|
|
6734
6770
|
await assertMergeTargetGoneOrThrow(ctx, decision.targetId);
|
|
6735
|
-
return
|
|
6771
|
+
return abandonToRace(
|
|
6772
|
+
options,
|
|
6773
|
+
`update: target ${decision.targetId} deleted mid-write (consolidated rewrite lost)`
|
|
6774
|
+
);
|
|
6736
6775
|
}
|
|
6737
6776
|
ctx.vaultCache.set(decision.targetId, Float32Array.from(newEmbedding));
|
|
6738
6777
|
return {
|
|
@@ -6744,6 +6783,11 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
6744
6783
|
}
|
|
6745
6784
|
};
|
|
6746
6785
|
}
|
|
6786
|
+
notifyConsolidationFallback(
|
|
6787
|
+
"invalid_response",
|
|
6788
|
+
options.consolidateOptions?.onFallback,
|
|
6789
|
+
`unapplicable ${decision.action} decision reached the applier \u2014 validate() should have rejected it`
|
|
6790
|
+
);
|
|
6747
6791
|
return null;
|
|
6748
6792
|
}
|
|
6749
6793
|
async function assertMergeTargetGoneOrThrow(ctx, targetId) {
|