@anuma/sdk 6.10.0 → 6.12.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/{chunk-4M56MKBV.mjs → chunk-732ZLOLA.mjs} +89 -32
- package/dist/expo/index.cjs +112 -38
- package/dist/expo/index.d.mts +109 -0
- package/dist/expo/index.d.ts +109 -0
- package/dist/expo/index.mjs +34 -18
- package/dist/expo/{recall-WIB7RQQZ.mjs → recall-PIATJ336.mjs} +1 -1
- package/dist/index.d.mts +15 -1
- package/dist/index.d.ts +15 -1
- package/dist/react/{chunk-EJ65X4GI.mjs → chunk-6IBFFWCE.mjs} +89 -32
- package/dist/react/index.cjs +112 -38
- package/dist/react/index.d.mts +109 -0
- package/dist/react/index.d.ts +109 -0
- package/dist/react/index.mjs +34 -18
- package/dist/react/{recall-FWILZSFH.mjs → recall-QUWN7DJ7.mjs} +1 -1
- package/dist/server/{chunk-I56324FR.mjs → chunk-7YTEE6JT.mjs} +89 -32
- package/dist/server/index.cjs +112 -38
- package/dist/server/index.d.mts +109 -0
- package/dist/server/index.d.ts +109 -0
- package/dist/server/index.mjs +34 -18
- package/dist/server/{recall-T7CNXTQ3.mjs → recall-HOVWMT4Q.mjs} +1 -1
- package/package.json +1 -1
package/dist/server/index.cjs
CHANGED
|
@@ -20236,9 +20236,9 @@ function recencyMultiplier(updatedAt, opts = {}) {
|
|
|
20236
20236
|
const updatedMs = updatedAt.getTime();
|
|
20237
20237
|
if (!Number.isFinite(updatedMs)) return noDate;
|
|
20238
20238
|
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
20239
|
-
const
|
|
20240
|
-
if (!Number.isFinite(
|
|
20241
|
-
const ageDays2 = Math.max(0, (
|
|
20239
|
+
const nowMs3 = now.getTime();
|
|
20240
|
+
if (!Number.isFinite(nowMs3)) return noDate;
|
|
20241
|
+
const ageDays2 = Math.max(0, (nowMs3 - updatedMs) / DAY_MS2);
|
|
20242
20242
|
const perYearDecay = opts.perYearDecay ?? DEFAULT_PER_YEAR_DECAY;
|
|
20243
20243
|
const floor = opts.floor ?? DEFAULT_FLOOR;
|
|
20244
20244
|
const decay = perYearDecay * (ageDays2 / 365);
|
|
@@ -20915,6 +20915,9 @@ async function decomposeQuery(query, options) {
|
|
|
20915
20915
|
...options.baseUrl !== void 0 && { baseUrl: options.baseUrl },
|
|
20916
20916
|
model: options.model ?? DEFAULT_MODEL,
|
|
20917
20917
|
systemPrompt: SYSTEM_PROMPT,
|
|
20918
|
+
// The query itself rides the user turn below, so SYSTEM_PROMPT is the whole
|
|
20919
|
+
// fixed instruction — which is what lets the portal own it outright.
|
|
20920
|
+
taskType: "memory_decompose",
|
|
20918
20921
|
// Wrap the bare query in a task framing so the model treats it as
|
|
20919
20922
|
// input to classify, not as a question to answer conversationally.
|
|
20920
20923
|
// Bare-query inputs caused Anthropic models to respond with prose
|
|
@@ -21220,24 +21223,19 @@ function createLlmNeighborRefiner(options) {
|
|
|
21220
21223
|
async refine(query, candidates, limit) {
|
|
21221
21224
|
if (candidates.length === 0) return [];
|
|
21222
21225
|
const numbered = candidates.map((name, i) => `[${i + 1}] ${name}`).join("\n");
|
|
21223
|
-
const systemPrompt = `You help a memory-retrieval system decide which related topics to explore.
|
|
21224
|
-
|
|
21225
|
-
Given a user's question and a numbered list of candidate topics/entities linked to memories found so far, pick the ones most likely to lead to memories that help ANSWER the question. Choose at most ${limit}. Prefer topics semantically related to the question; ignore incidental ones.
|
|
21226
|
-
|
|
21227
|
-
Output strict JSON, no prose: { "expand": [<entity names to expand, verbatim from the list>] }`;
|
|
21228
21226
|
const parsed = await callPortalJsonCompletion({
|
|
21229
21227
|
...options.apiKey !== void 0 && { apiKey: options.apiKey },
|
|
21230
21228
|
...options.getToken !== void 0 && { getToken: options.getToken },
|
|
21231
21229
|
...options.baseUrl !== void 0 && { baseUrl: options.baseUrl },
|
|
21232
21230
|
taskType: "memory_graph",
|
|
21233
21231
|
model: options.model ?? DEFAULT_REFINER_MODEL,
|
|
21234
|
-
systemPrompt,
|
|
21232
|
+
systemPrompt: REFINER_SYSTEM_PROMPT,
|
|
21235
21233
|
userMessage: `Question: ${query}
|
|
21236
21234
|
|
|
21237
21235
|
Candidate topics:
|
|
21238
21236
|
${numbered}
|
|
21239
21237
|
|
|
21240
|
-
Which should be expanded
|
|
21238
|
+
Which should be expanded? Choose at most ${limit}.`,
|
|
21241
21239
|
tag: "memory/graph-refine",
|
|
21242
21240
|
maxAttempts: options.maxAttempts ?? DEFAULT_REFINER_ATTEMPTS,
|
|
21243
21241
|
totalTimeoutMs: options.totalTimeoutMs ?? DEFAULT_REFINER_TOTAL_TIMEOUT_MS,
|
|
@@ -21258,7 +21256,7 @@ Which should be expanded?`,
|
|
|
21258
21256
|
}
|
|
21259
21257
|
};
|
|
21260
21258
|
}
|
|
21261
|
-
var MAX_HOPS, ENTITY_FANOUT, MIN_REFINER_CANDIDATES, MAX_REFINER_CANDIDATES, NODE_BUDGET, VAULT_SIZE_HOP_CAP, DEFAULT_REFINER_MODEL, DEFAULT_REFINER_ATTEMPTS, DEFAULT_REFINER_TOTAL_TIMEOUT_MS;
|
|
21259
|
+
var MAX_HOPS, ENTITY_FANOUT, MIN_REFINER_CANDIDATES, MAX_REFINER_CANDIDATES, NODE_BUDGET, VAULT_SIZE_HOP_CAP, DEFAULT_REFINER_MODEL, DEFAULT_REFINER_ATTEMPTS, DEFAULT_REFINER_TOTAL_TIMEOUT_MS, REFINER_SYSTEM_PROMPT;
|
|
21262
21260
|
var init_graphTraversal = __esm({
|
|
21263
21261
|
"src/lib/memory/graphTraversal.ts"() {
|
|
21264
21262
|
"use strict";
|
|
@@ -21277,6 +21275,11 @@ var init_graphTraversal = __esm({
|
|
|
21277
21275
|
DEFAULT_REFINER_MODEL = "inclusionai/ling-2.6-flash";
|
|
21278
21276
|
DEFAULT_REFINER_ATTEMPTS = 1;
|
|
21279
21277
|
DEFAULT_REFINER_TOTAL_TIMEOUT_MS = 8e3;
|
|
21278
|
+
REFINER_SYSTEM_PROMPT = `You help a memory-retrieval system decide which related topics to explore.
|
|
21279
|
+
|
|
21280
|
+
Given a user's question and a numbered list of candidate topics/entities linked to memories found so far, pick the ones most likely to lead to memories that help ANSWER the question. Never return more than the maximum the user turn asks for. Prefer topics semantically related to the question; ignore incidental ones.
|
|
21281
|
+
|
|
21282
|
+
Output strict JSON, no prose: { "expand": [<entity names to expand, verbatim from the list>] }`;
|
|
21280
21283
|
}
|
|
21281
21284
|
});
|
|
21282
21285
|
|
|
@@ -21576,6 +21579,9 @@ async function recall(query, ctx, options = {}) {
|
|
|
21576
21579
|
const chunkResults = [];
|
|
21577
21580
|
let vaultSize;
|
|
21578
21581
|
let didRerank = false;
|
|
21582
|
+
let rerankMs = 0;
|
|
21583
|
+
let queryEmbedMs = 0;
|
|
21584
|
+
let vaultRowsEmbedded;
|
|
21579
21585
|
let hadV2Head = false;
|
|
21580
21586
|
let embeddingsUnavailable = false;
|
|
21581
21587
|
let chunkEmbedFailed = false;
|
|
@@ -21600,12 +21606,15 @@ async function recall(query, ctx, options = {}) {
|
|
|
21600
21606
|
...vaultSize !== void 0 && { vaultSize },
|
|
21601
21607
|
...decryptLastRan !== void 0 && { decryptLast: decryptLastRan },
|
|
21602
21608
|
...vaultRowsDecrypted !== void 0 && { vaultRowsDecrypted },
|
|
21609
|
+
...vaultRowsEmbedded !== void 0 && { vaultRowsEmbedded },
|
|
21603
21610
|
factCount: factResults.length,
|
|
21604
21611
|
chunkCount: chunkResults.length,
|
|
21605
21612
|
timings: {
|
|
21606
21613
|
total: nowMs() - t0,
|
|
21607
21614
|
prep: prepMs,
|
|
21608
21615
|
factLane: factLaneMs,
|
|
21616
|
+
rerank: rerankMs,
|
|
21617
|
+
queryEmbed: queryEmbedMs,
|
|
21609
21618
|
chunkLane: chunkLaneMs,
|
|
21610
21619
|
fuse: fuseMs
|
|
21611
21620
|
},
|
|
@@ -21669,6 +21678,9 @@ async function recall(query, ctx, options = {}) {
|
|
|
21669
21678
|
results,
|
|
21670
21679
|
vaultSize: size,
|
|
21671
21680
|
reranked,
|
|
21681
|
+
rerankMs: factRerankMs,
|
|
21682
|
+
queryEmbedMs: factQueryEmbedMs,
|
|
21683
|
+
rowsEmbedded: factRowsEmbedded,
|
|
21672
21684
|
hadV2Head: v2Head,
|
|
21673
21685
|
embeddingsUnavailable: factEmbeddingsUnavailable,
|
|
21674
21686
|
rankedOnCosine: factRankedOnCosine,
|
|
@@ -21727,6 +21739,9 @@ async function recall(query, ctx, options = {}) {
|
|
|
21727
21739
|
);
|
|
21728
21740
|
vaultSize = size;
|
|
21729
21741
|
didRerank = reranked;
|
|
21742
|
+
rerankMs = factRerankMs;
|
|
21743
|
+
queryEmbedMs = factQueryEmbedMs;
|
|
21744
|
+
vaultRowsEmbedded = factRowsEmbedded;
|
|
21730
21745
|
hadV2Head = v2Head;
|
|
21731
21746
|
if (factEmbeddingsUnavailable) embeddingsUnavailable = true;
|
|
21732
21747
|
factLaneRankedOnCosine = factRankedOnCosine;
|
|
@@ -22191,6 +22206,7 @@ async function rankFusedVaultMemoriesAsync(query, queryEmbedding, items, options
|
|
|
22191
22206
|
const rerankTopN = options.rerankTopN ?? 30;
|
|
22192
22207
|
const ceWeight = options.ceWeight ?? 0.1;
|
|
22193
22208
|
const headSlice = v2Ranked.slice(0, rerankTopN);
|
|
22209
|
+
const ceStart = nowMs2();
|
|
22194
22210
|
try {
|
|
22195
22211
|
const reranked = await rerankPairs(
|
|
22196
22212
|
query,
|
|
@@ -22218,6 +22234,8 @@ async function rankFusedVaultMemoriesAsync(query, queryEmbedding, items, options
|
|
|
22218
22234
|
getLogger().warn("[memory/search] cross-encoder rerank failed; using V2 ranking", err);
|
|
22219
22235
|
}
|
|
22220
22236
|
combined = v2Ranked;
|
|
22237
|
+
} finally {
|
|
22238
|
+
if (options.rerankStats) options.rerankStats.ms += nowMs2() - ceStart;
|
|
22221
22239
|
}
|
|
22222
22240
|
} else {
|
|
22223
22241
|
combined = v2Ranked;
|
|
@@ -22384,6 +22402,7 @@ async function rankComposite(originalQuery, originalQueryEmbedding, subQueries,
|
|
|
22384
22402
|
const ceWeight = options.ceWeight ?? 0.1;
|
|
22385
22403
|
const headSlice = combined.slice(0, rerankTopN);
|
|
22386
22404
|
const tailSlice = combined.slice(rerankTopN);
|
|
22405
|
+
const ceStart = nowMs2();
|
|
22387
22406
|
try {
|
|
22388
22407
|
const reranked = await rerankPairs(
|
|
22389
22408
|
originalQuery,
|
|
@@ -22411,6 +22430,8 @@ async function rankComposite(originalQuery, originalQueryEmbedding, subQueries,
|
|
|
22411
22430
|
err
|
|
22412
22431
|
);
|
|
22413
22432
|
}
|
|
22433
|
+
} finally {
|
|
22434
|
+
if (options.rerankStats) options.rerankStats.ms += nowMs2() - ceStart;
|
|
22414
22435
|
}
|
|
22415
22436
|
}
|
|
22416
22437
|
if (options?.mmr) {
|
|
@@ -22537,11 +22558,13 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
|
|
|
22537
22558
|
rowsDecrypted: 0
|
|
22538
22559
|
};
|
|
22539
22560
|
}
|
|
22561
|
+
const queryEmbedStart = nowMs2();
|
|
22540
22562
|
const queryEmbedding = await embedQueryOrDegrade(
|
|
22541
22563
|
query,
|
|
22542
22564
|
embeddingOptions,
|
|
22543
22565
|
opts.onEmbeddingDegraded
|
|
22544
22566
|
);
|
|
22567
|
+
if (opts.embedStats) opts.embedStats.queryMs += nowMs2() - queryEmbedStart;
|
|
22545
22568
|
const embeddingsDegraded = queryEmbedding.length === 0;
|
|
22546
22569
|
const currentModel = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
22547
22570
|
const vectored = [];
|
|
@@ -22594,6 +22617,7 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
|
|
|
22594
22617
|
const laneRows = laneFetched.filter((m) => !isEncrypted(m.content));
|
|
22595
22618
|
if (laneRows.length > 0) {
|
|
22596
22619
|
let laneVecs;
|
|
22620
|
+
if (opts.embedStats) opts.embedStats.rowsEmbedded += laneRows.length;
|
|
22597
22621
|
try {
|
|
22598
22622
|
laneVecs = await generateEmbeddings(
|
|
22599
22623
|
laneRows.map((m) => m.content),
|
|
@@ -22672,6 +22696,10 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
|
|
|
22672
22696
|
async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache, searchOptions) {
|
|
22673
22697
|
if (!query || typeof query !== "string") {
|
|
22674
22698
|
return {
|
|
22699
|
+
// Nothing was read and nothing was embedded — the short-circuit fires
|
|
22700
|
+
// before either.
|
|
22701
|
+
queryEmbedMs: 0,
|
|
22702
|
+
rowsEmbedded: 0,
|
|
22675
22703
|
memories: [],
|
|
22676
22704
|
embeddedItems: [],
|
|
22677
22705
|
queryEmbedding: [],
|
|
@@ -22704,6 +22732,7 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
|
|
|
22704
22732
|
embeddingsUnavailable = true;
|
|
22705
22733
|
embeddingFailure = true;
|
|
22706
22734
|
};
|
|
22735
|
+
const embedStats = { queryMs: 0, rowsEmbedded: 0 };
|
|
22707
22736
|
if (searchOptions?.decryptLast) {
|
|
22708
22737
|
const forceIncludeIds = [
|
|
22709
22738
|
...searchOptions.entityRanking ?? [],
|
|
@@ -22715,7 +22744,8 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
|
|
|
22715
22744
|
admitFloor: ADMIT_FLOOR,
|
|
22716
22745
|
unembeddedCap: UNEMBEDDED_CAP,
|
|
22717
22746
|
...forceIncludeIds.length > 0 && { forceIncludeIds },
|
|
22718
|
-
onEmbeddingDegraded
|
|
22747
|
+
onEmbeddingDegraded,
|
|
22748
|
+
embedStats
|
|
22719
22749
|
});
|
|
22720
22750
|
if (corpus.vaultSize === 0) {
|
|
22721
22751
|
return {
|
|
@@ -22726,7 +22756,9 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
|
|
|
22726
22756
|
embeddingsUnavailable: false,
|
|
22727
22757
|
embeddingFailure: false,
|
|
22728
22758
|
decryptLast: true,
|
|
22729
|
-
rowsDecrypted: corpus.rowsDecrypted
|
|
22759
|
+
rowsDecrypted: corpus.rowsDecrypted,
|
|
22760
|
+
queryEmbedMs: embedStats.queryMs,
|
|
22761
|
+
rowsEmbedded: embedStats.rowsEmbedded
|
|
22730
22762
|
};
|
|
22731
22763
|
}
|
|
22732
22764
|
({ memories, embeddedItems, queryEmbedding, vaultSize } = corpus);
|
|
@@ -22743,7 +22775,9 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
|
|
|
22743
22775
|
decryptLast: true,
|
|
22744
22776
|
// Rows WERE decrypt-attempted even though none came back readable — that
|
|
22745
22777
|
// is the whole point of reporting attempts rather than successes.
|
|
22746
|
-
rowsDecrypted: corpus.rowsDecrypted
|
|
22778
|
+
rowsDecrypted: corpus.rowsDecrypted,
|
|
22779
|
+
queryEmbedMs: embedStats.queryMs,
|
|
22780
|
+
rowsEmbedded: embedStats.rowsEmbedded
|
|
22747
22781
|
};
|
|
22748
22782
|
}
|
|
22749
22783
|
} else {
|
|
@@ -22768,10 +22802,14 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
|
|
|
22768
22802
|
embeddingsUnavailable: false,
|
|
22769
22803
|
embeddingFailure: false,
|
|
22770
22804
|
decryptLast: false,
|
|
22771
|
-
rowsDecrypted: loaded.length
|
|
22805
|
+
rowsDecrypted: loaded.length,
|
|
22806
|
+
queryEmbedMs: embedStats.queryMs,
|
|
22807
|
+
rowsEmbedded: embedStats.rowsEmbedded
|
|
22772
22808
|
};
|
|
22773
22809
|
}
|
|
22810
|
+
const legacyEmbedStart = nowMs2();
|
|
22774
22811
|
queryEmbedding = await embedQueryOrDegrade(query, embeddingOptions, onEmbeddingDegraded);
|
|
22812
|
+
embedStats.queryMs += nowMs2() - legacyEmbedStart;
|
|
22775
22813
|
const currentModel = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
22776
22814
|
const uncachedTexts = [];
|
|
22777
22815
|
const uncachedIndices = [];
|
|
@@ -22805,6 +22843,7 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
|
|
|
22805
22843
|
}
|
|
22806
22844
|
if (uncachedTexts.length > 0) {
|
|
22807
22845
|
let newEmbeddings;
|
|
22846
|
+
embedStats.rowsEmbedded += uncachedTexts.length;
|
|
22808
22847
|
try {
|
|
22809
22848
|
newEmbeddings = await generateEmbeddings(uncachedTexts, embeddingOptions);
|
|
22810
22849
|
} catch (err) {
|
|
@@ -22848,6 +22887,8 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
|
|
|
22848
22887
|
embeddingsUnavailable = true;
|
|
22849
22888
|
}
|
|
22850
22889
|
return {
|
|
22890
|
+
queryEmbedMs: embedStats.queryMs,
|
|
22891
|
+
rowsEmbedded: embedStats.rowsEmbedded,
|
|
22851
22892
|
memories,
|
|
22852
22893
|
embeddedItems,
|
|
22853
22894
|
queryEmbedding,
|
|
@@ -22898,11 +22939,15 @@ async function rankPreparedVaultCandidates(query, prepared, embeddingOptions, se
|
|
|
22898
22939
|
results: results2,
|
|
22899
22940
|
vaultSize: out.vaultSize,
|
|
22900
22941
|
reranked: out.reranked ?? false,
|
|
22942
|
+
// Read straight off the shared stats object rather than being passed in at
|
|
22943
|
+
// each call site: every return in this function funnels through here, so a
|
|
22944
|
+
// path added later reports the CE bill without having to remember to.
|
|
22945
|
+
rerankMs: rerankStats.ms,
|
|
22901
22946
|
hadV2Head: out.hadV2Head ?? false,
|
|
22902
22947
|
embeddingsUnavailable
|
|
22903
22948
|
};
|
|
22904
22949
|
};
|
|
22905
|
-
const rerankStats = { applied: false };
|
|
22950
|
+
const rerankStats = { applied: false, ms: 0 };
|
|
22906
22951
|
const useFusion = searchOptions?.useFusion ?? true;
|
|
22907
22952
|
const tuning = {
|
|
22908
22953
|
...searchOptions?.recencyAlpha !== void 0 && { recencyAlpha: searchOptions.recencyAlpha },
|
|
@@ -23021,13 +23066,16 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
23021
23066
|
results: [],
|
|
23022
23067
|
vaultSize: 0,
|
|
23023
23068
|
reranked: false,
|
|
23069
|
+
rerankMs: 0,
|
|
23024
23070
|
hadV2Head: false,
|
|
23025
23071
|
embeddingsUnavailable: false,
|
|
23026
23072
|
rankedOnCosine: false,
|
|
23027
23073
|
// No storage read happened, so nothing was decrypted; report the path the
|
|
23028
23074
|
// caller asked for so this turn is still attributable.
|
|
23029
23075
|
decryptLast: !!searchOptions?.decryptLast,
|
|
23030
|
-
rowsDecrypted: 0
|
|
23076
|
+
rowsDecrypted: 0,
|
|
23077
|
+
queryEmbedMs: 0,
|
|
23078
|
+
rowsEmbedded: 0
|
|
23031
23079
|
};
|
|
23032
23080
|
}
|
|
23033
23081
|
if (searchOptions?.decompose === "llm" && normalizeSubQueries(searchOptions.subQueries).length < 2 && !warnedProgrammaticDecomposeIgnored) {
|
|
@@ -23048,11 +23096,14 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
23048
23096
|
results: [],
|
|
23049
23097
|
vaultSize: 0,
|
|
23050
23098
|
reranked: false,
|
|
23099
|
+
rerankMs: 0,
|
|
23051
23100
|
hadV2Head: false,
|
|
23052
23101
|
embeddingsUnavailable: prepared.embeddingsUnavailable,
|
|
23053
23102
|
rankedOnCosine: false,
|
|
23054
23103
|
decryptLast: prepared.decryptLast,
|
|
23055
|
-
rowsDecrypted: prepared.rowsDecrypted
|
|
23104
|
+
rowsDecrypted: prepared.rowsDecrypted,
|
|
23105
|
+
queryEmbedMs: prepared.queryEmbedMs,
|
|
23106
|
+
rowsEmbedded: prepared.rowsEmbedded
|
|
23056
23107
|
};
|
|
23057
23108
|
}
|
|
23058
23109
|
if (prepared.memories.length === 0) {
|
|
@@ -23060,11 +23111,14 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
23060
23111
|
results: [],
|
|
23061
23112
|
vaultSize: prepared.vaultSize,
|
|
23062
23113
|
reranked: false,
|
|
23114
|
+
rerankMs: 0,
|
|
23063
23115
|
hadV2Head: false,
|
|
23064
23116
|
embeddingsUnavailable: prepared.embeddingsUnavailable,
|
|
23065
23117
|
rankedOnCosine: false,
|
|
23066
23118
|
decryptLast: prepared.decryptLast,
|
|
23067
|
-
rowsDecrypted: prepared.rowsDecrypted
|
|
23119
|
+
rowsDecrypted: prepared.rowsDecrypted,
|
|
23120
|
+
queryEmbedMs: prepared.queryEmbedMs,
|
|
23121
|
+
rowsEmbedded: prepared.rowsEmbedded
|
|
23068
23122
|
};
|
|
23069
23123
|
}
|
|
23070
23124
|
const ranked = await rankPreparedVaultCandidates(
|
|
@@ -23077,7 +23131,9 @@ async function searchVaultMemoriesWithSize(query, vaultCtx, embeddingOptions, ca
|
|
|
23077
23131
|
...ranked,
|
|
23078
23132
|
rankedOnCosine: !ranked.embeddingsUnavailable,
|
|
23079
23133
|
decryptLast: prepared.decryptLast,
|
|
23080
|
-
rowsDecrypted: prepared.rowsDecrypted
|
|
23134
|
+
rowsDecrypted: prepared.rowsDecrypted,
|
|
23135
|
+
queryEmbedMs: prepared.queryEmbedMs,
|
|
23136
|
+
rowsEmbedded: prepared.rowsEmbedded
|
|
23081
23137
|
};
|
|
23082
23138
|
}
|
|
23083
23139
|
async function searchVaultMemories(query, vaultCtx, embeddingOptions, cache, searchOptions) {
|
|
@@ -23227,7 +23283,7 @@ ${formatted}`;
|
|
|
23227
23283
|
}
|
|
23228
23284
|
};
|
|
23229
23285
|
}
|
|
23230
|
-
var warnedProgrammaticDecomposeIgnored, SUPERSESSION_SIMILARITY_THRESHOLD, SUPERSESSION_MIN_AGE_GAP_MS, SUPERSESSION_BOOST_FACTOR, SUPERSESSION_MAX_WINDOW, EMBEDDINGS_DEGRADED_EMPTY_NO_LEXICAL;
|
|
23286
|
+
var nowMs2, warnedProgrammaticDecomposeIgnored, SUPERSESSION_SIMILARITY_THRESHOLD, SUPERSESSION_MIN_AGE_GAP_MS, SUPERSESSION_BOOST_FACTOR, SUPERSESSION_MAX_WINDOW, EMBEDDINGS_DEGRADED_EMPTY_NO_LEXICAL;
|
|
23231
23287
|
var init_searchTool = __esm({
|
|
23232
23288
|
"src/lib/memoryVault/searchTool.ts"() {
|
|
23233
23289
|
"use strict";
|
|
@@ -23245,6 +23301,7 @@ var init_searchTool = __esm({
|
|
|
23245
23301
|
init_bm25();
|
|
23246
23302
|
init_decomposeQuery();
|
|
23247
23303
|
init_lruCache();
|
|
23304
|
+
nowMs2 = () => typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
23248
23305
|
warnedProgrammaticDecomposeIgnored = false;
|
|
23249
23306
|
SUPERSESSION_SIMILARITY_THRESHOLD = 0.7;
|
|
23250
23307
|
SUPERSESSION_MIN_AGE_GAP_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
@@ -30602,6 +30659,7 @@ ${TRUNCATION_NOTICE}` : formatted;
|
|
|
30602
30659
|
// src/lib/memory/reflect.ts
|
|
30603
30660
|
init_clientConfig();
|
|
30604
30661
|
init_logger();
|
|
30662
|
+
init_taskType();
|
|
30605
30663
|
init_portalLlm();
|
|
30606
30664
|
init_recall();
|
|
30607
30665
|
var DEFAULT_BASE_URL2 = BASE_URL;
|
|
@@ -30647,11 +30705,13 @@ Respond with ONLY a single JSON object conforming to this JSON Schema, with no p
|
|
|
30647
30705
|
${JSON.stringify(
|
|
30648
30706
|
options.responseSchema
|
|
30649
30707
|
)}` : basePrompt;
|
|
30650
|
-
const userMessage =
|
|
30651
|
-
|
|
30652
|
-
|
|
30653
|
-
|
|
30654
|
-
|
|
30708
|
+
const userMessage = [
|
|
30709
|
+
`Question:
|
|
30710
|
+
${trimmed}`,
|
|
30711
|
+
...options.userInstructions ? [options.userInstructions] : [],
|
|
30712
|
+
`Memories (use only these as evidence):
|
|
30713
|
+
${evidence}`
|
|
30714
|
+
].join("\n\n");
|
|
30655
30715
|
const maxTokens = options.maxTokens ?? DEFAULT_MAX_TOKENS;
|
|
30656
30716
|
const fetchImpl = options.fetchFn ?? fetch;
|
|
30657
30717
|
const log = getLogger();
|
|
@@ -30665,7 +30725,13 @@ ${evidence}`;
|
|
|
30665
30725
|
try {
|
|
30666
30726
|
response = await fetchImpl(`${baseUrl}/api/v1/chat/completions`, {
|
|
30667
30727
|
method: "POST",
|
|
30668
|
-
|
|
30728
|
+
// No task type unless the caller named one — an undeclared task adds no
|
|
30729
|
+
// header at all, which is what keeps user-facing reflect() unlabelled.
|
|
30730
|
+
headers: {
|
|
30731
|
+
...authHeaders,
|
|
30732
|
+
...taskTypeHeader(options.taskType),
|
|
30733
|
+
"Content-Type": "application/json"
|
|
30734
|
+
},
|
|
30669
30735
|
body: JSON.stringify({
|
|
30670
30736
|
model,
|
|
30671
30737
|
// Modern OpenAI field; the portal reads only `max_completion_tokens`
|
|
@@ -31117,10 +31183,15 @@ async function synthesizeFacet(facet, ctx, options, prior) {
|
|
|
31117
31183
|
limit,
|
|
31118
31184
|
types: ["fact"],
|
|
31119
31185
|
maxTokens: DEFAULT_FACET_MAX_TOKENS,
|
|
31120
|
-
// Profile-facet synthesis is a background op, so it marks its own prompt
|
|
31121
|
-
// reflect() itself must
|
|
31122
|
-
// and that traffic is chat, not an internal flow. See
|
|
31123
|
-
|
|
31186
|
+
// Profile-facet synthesis is a background op, so it marks its own prompt AND
|
|
31187
|
+
// names its own task. reflect() itself must do neither — it also serves the
|
|
31188
|
+
// user's own questions, and that traffic is chat, not an internal flow. See
|
|
31189
|
+
// ../internalFlowMarker and ReflectOptions.taskType.
|
|
31190
|
+
taskType: "memory_profile_synth",
|
|
31191
|
+
systemPrompt: withInternalFlowMarker(FACET_SYSTEM_PROMPT),
|
|
31192
|
+
// The facet's label/guidance/response-fields, on the user turn — what keeps
|
|
31193
|
+
// the system half fixed and therefore server-ownable.
|
|
31194
|
+
userInstructions: buildFacetUserInstructions(facet),
|
|
31124
31195
|
responseSchema: facetResponseSchema(facet.key),
|
|
31125
31196
|
memories
|
|
31126
31197
|
});
|
|
@@ -31178,19 +31249,22 @@ function fallbackSection(facet, prior) {
|
|
|
31178
31249
|
stale: true
|
|
31179
31250
|
};
|
|
31180
31251
|
}
|
|
31181
|
-
|
|
31182
|
-
const structuredField = FACET_STRUCTURED_RESPONSE_HINT[facet.key] ?? "";
|
|
31183
|
-
return `You are writing the "${facet.label}" section of a person's shareable profile, using their private memories (supplied as evidence) as the only source of truth.
|
|
31184
|
-
|
|
31185
|
-
Task for this section:
|
|
31186
|
-
${facet.guidance}
|
|
31252
|
+
var FACET_SYSTEM_PROMPT = `You are writing one section of a person's shareable profile, using their private memories (supplied as evidence) as the only source of truth. The user turn names the section, states the task for it, and gives the exact JSON shape to respond in.
|
|
31187
31253
|
|
|
31188
31254
|
Rules:
|
|
31189
31255
|
- Ground every claim in the supplied memories \u2014 never invent, infer beyond, or embellish what they support.
|
|
31190
31256
|
- If the memories don't cover this section, return an empty summary with hasEvidence=false. Do not pad or guess.
|
|
31191
31257
|
- Write in third person about the person, in a natural voice suitable for a public profile (no "I"/"you", no name repetition).
|
|
31192
31258
|
- Be concise and specific; no preamble, hedging, or meta-commentary.
|
|
31193
|
-
- Respond as JSON
|
|
31259
|
+
- Respond as JSON in exactly the shape the user turn states, with no extra fields.`;
|
|
31260
|
+
function buildFacetUserInstructions(facet) {
|
|
31261
|
+
const structuredField = FACET_STRUCTURED_RESPONSE_HINT[facet.key] ?? "";
|
|
31262
|
+
return `Section: "${facet.label}"
|
|
31263
|
+
|
|
31264
|
+
Task for this section:
|
|
31265
|
+
${facet.guidance}
|
|
31266
|
+
|
|
31267
|
+
Respond as JSON: { "summary": <the section text, or "">, "hasEvidence": <true|false>${structuredField} }.`;
|
|
31194
31268
|
}
|
|
31195
31269
|
function extractFacetText(structured) {
|
|
31196
31270
|
if (structured && typeof structured === "object") {
|
package/dist/server/index.d.mts
CHANGED
|
@@ -4698,6 +4698,51 @@ interface EntityOperationsContext {
|
|
|
4698
4698
|
allowUnscopedRows?: boolean;
|
|
4699
4699
|
}
|
|
4700
4700
|
|
|
4701
|
+
/**
|
|
4702
|
+
* Class-B task types — the vocabulary of the `X-Anuma-Task-Type` header.
|
|
4703
|
+
*
|
|
4704
|
+
* A Class-B flow has ONE fixed purpose and no conversation: extract memories
|
|
4705
|
+
* from a snippet, pick a topic, consolidate duplicates, classify a query. Today
|
|
4706
|
+
* each of those builds its own system prompt on the client and sends it as a
|
|
4707
|
+
* `role:system` message, which makes the prompt a suggestion rather than a
|
|
4708
|
+
* contract — a caller can reword it into "you are a general assistant" and get
|
|
4709
|
+
* general chat at internal-endpoint prices.
|
|
4710
|
+
*
|
|
4711
|
+
* The fix is that the SERVER owns the text and the client only names the task.
|
|
4712
|
+
* This header is the name. The portal allowlists it against its own copy of this
|
|
4713
|
+
* enum (ai-portal `internal/systemprompt/tasks.go`) and DROPS anything it does
|
|
4714
|
+
* not recognise, so an unknown value degrades to "no task declared" rather than
|
|
4715
|
+
* failing the request.
|
|
4716
|
+
*
|
|
4717
|
+
* ⚠ These string values are a wire contract with ai-portal. Adding one here
|
|
4718
|
+
* before the portal knows it is harmless (it is dropped); renaming or removing
|
|
4719
|
+
* one silently stops that flow being counted. Keep them in step with
|
|
4720
|
+
* `AllTaskTypes` on the portal side, and see ai-portal
|
|
4721
|
+
* `docs/BACKEND_OWNED_TASK_PROMPTS.md` for the rollout.
|
|
4722
|
+
*
|
|
4723
|
+
* ⚠ RELEASE ORDER. This union is a PUBLIC type, so a split is breaking in both
|
|
4724
|
+
* directions and has to be sequenced:
|
|
4725
|
+
*
|
|
4726
|
+
* 1. merge + publish this package;
|
|
4727
|
+
* 2. bump `@anuma/sdk` in the consumer and switch its call sites to the new
|
|
4728
|
+
* names in the same commit.
|
|
4729
|
+
*
|
|
4730
|
+
* A consumer on the OLD version cannot compile the new names, and a consumer on
|
|
4731
|
+
* the NEW version cannot compile the retired ones (`app_inspiration` is gone
|
|
4732
|
+
* here, replaced by the three `app_inspiration_*` names). Both halves of that
|
|
4733
|
+
* are type-only — the wire itself always degrades safely, because the portal
|
|
4734
|
+
* drops any value it does not recognise. Concretely: ai-memoryless-client#5782
|
|
4735
|
+
* is blocked on this publish for exactly that reason.
|
|
4736
|
+
*
|
|
4737
|
+
* Deliberately ABSENT: agent personas, `reflect()` when it answers the user, and
|
|
4738
|
+
* the app-idea chat. Those carry an open conversation with the user, so a fixed
|
|
4739
|
+
* server-owned prompt would be wrong rather than merely premature — the same
|
|
4740
|
+
* boundary {@link INTERNAL_FLOW_MARKER} draws.
|
|
4741
|
+
*
|
|
4742
|
+
* @public
|
|
4743
|
+
*/
|
|
4744
|
+
type TaskType = "title" | "commit_message" | "memory_extract" | "memory_dedup" | "memory_decay" | "memory_injection_check" | "memory_verify_support" | "memory_autosort" | "memory_topic" | "memory_consolidate" | "memory_decompose" | "memory_profile_synth" | "memory_graph" | "folder_context" | "selection_memory" | "summarize" | "style_analysis" | "classify_search" | "app_inspiration_generate" | "app_inspiration_trends" | "app_inspiration_remix" | "spotlight_image" | "slide_image" | "slide_video" | "slide_music" | "slide_sfx" | "media_video" | "media_audio" | "media_bg_removal" | "media_image_preset" | "tool_app_builder" | "tool_document_builder" | "tool_slides" | "tool_slides_image_gen" | "connector_guidance" | "cf_task" | "xbot_intent" | "xbot_council" | "scheduled_task";
|
|
4745
|
+
|
|
4701
4746
|
/**
|
|
4702
4747
|
* Shared portal LLM call for the memory pipeline.
|
|
4703
4748
|
*
|
|
@@ -5641,6 +5686,17 @@ interface RecallDiagnostics {
|
|
|
5641
5686
|
* never the cost.
|
|
5642
5687
|
*/
|
|
5643
5688
|
vaultRowsDecrypted?: number;
|
|
5689
|
+
/**
|
|
5690
|
+
* Rows the fact lane had to re-embed through the portal because their stored
|
|
5691
|
+
* vector was unusable — stale `embedding_model`, wrong dimension, or
|
|
5692
|
+
* unparseable. Absent when the fact lane didn't run.
|
|
5693
|
+
*
|
|
5694
|
+
* Expected to be 0 on a healthy vault: rows are embedded at write time and the
|
|
5695
|
+
* re-embed writes the current model back, so a persistently non-zero value
|
|
5696
|
+
* means the writeback is not sticking and every turn is paying for it. On the
|
|
5697
|
+
* LEGACY read path this batch is uncapped, so it can be the whole vault.
|
|
5698
|
+
*/
|
|
5699
|
+
vaultRowsEmbedded?: number;
|
|
5644
5700
|
/** Facts the fact lane returned (post-dedupe, pre-fusion). */
|
|
5645
5701
|
factCount: number;
|
|
5646
5702
|
/** Chunks the chunk lane returned (post-dedupe, pre-fusion). */
|
|
@@ -5653,6 +5709,37 @@ interface RecallDiagnostics {
|
|
|
5653
5709
|
prep: number;
|
|
5654
5710
|
/** Vault fact-lane search (`searchVaultMemoriesWithSize`). */
|
|
5655
5711
|
factLane: number;
|
|
5712
|
+
/**
|
|
5713
|
+
* The cross-encoder's share of {@link factLane} — wall-clock spent inside
|
|
5714
|
+
* `rerankPairs`. Billed even when the CE threw partway through, because a
|
|
5715
|
+
* rerank that burned three seconds and then failed still cost them.
|
|
5716
|
+
*
|
|
5717
|
+
* A SUBSET of `factLane`, not a sibling: read `factLane - rerank` for
|
|
5718
|
+
* everything else the lane did (query embed, vault read, fused ranking).
|
|
5719
|
+
* 0 when the CE did not run; `reranked` is what distinguishes that from a
|
|
5720
|
+
* rerank that cost nothing.
|
|
5721
|
+
*
|
|
5722
|
+
* Exists because #845 spent three rounds arguing about which stage inside
|
|
5723
|
+
* the fact lane dominated — whole-vault read, then admission window, then
|
|
5724
|
+
* the CE — with one aggregate number for all of them. Every hypothesis was
|
|
5725
|
+
* an inference; this makes the question a query.
|
|
5726
|
+
*/
|
|
5727
|
+
rerank: number;
|
|
5728
|
+
/**
|
|
5729
|
+
* The query embed's share of {@link factLane} — one portal round trip.
|
|
5730
|
+
*
|
|
5731
|
+
* Also a SUBSET of `factLane`. Together with `rerank` this makes the lane
|
|
5732
|
+
* decomposable: `factLane - queryEmbed - rerank` is the local work (vault
|
|
5733
|
+
* read, decrypt, BM25/cosine fusion), and each of the three implies a
|
|
5734
|
+
* completely different fix.
|
|
5735
|
+
*
|
|
5736
|
+
* 0 when the lane returned before embedding, which includes every empty
|
|
5737
|
+
* vault — `prepareVaultCandidates` short-circuits first. That is why the
|
|
5738
|
+
* fast `vault_size = 0` population never established a baseline for this
|
|
5739
|
+
* cost, and why the ~850ms floor on the smallest NON-empty vaults had no
|
|
5740
|
+
* attributable owner.
|
|
5741
|
+
*/
|
|
5742
|
+
queryEmbed: number;
|
|
5656
5743
|
/** Chunk-lane search (`searchChunksOp`). */
|
|
5657
5744
|
chunkLane: number;
|
|
5658
5745
|
/** Cross-lane RRF fusion + provenance dedup after both lanes. */
|
|
@@ -8757,6 +8844,28 @@ interface ReflectOptions extends RecallOptions, PortalLlmAuth {
|
|
|
8757
8844
|
maxTokens?: number;
|
|
8758
8845
|
/** Override the grounding system prompt. */
|
|
8759
8846
|
systemPrompt?: string;
|
|
8847
|
+
/**
|
|
8848
|
+
* Extra caller instruction to carry on the USER turn, between the question and
|
|
8849
|
+
* the evidence block (see the `userMessage` assembly below). This is the slot a
|
|
8850
|
+
* background caller uses to keep its per-request data OUT of the system message
|
|
8851
|
+
* without colliding with the numbered evidence list — profile-facet synthesis
|
|
8852
|
+
* puts its section label, guidance and response-field hint here so its system
|
|
8853
|
+
* half can stay fixed and server-ownable.
|
|
8854
|
+
*/
|
|
8855
|
+
userInstructions?: string;
|
|
8856
|
+
/**
|
|
8857
|
+
* Class-B task name for the `X-Anuma-Task-Type` header, or nothing.
|
|
8858
|
+
*
|
|
8859
|
+
* Deliberately OPTIONAL and unset by default. reflect() also answers the user's
|
|
8860
|
+
* OWN question, and that traffic is chat, not an internal flow — declaring a
|
|
8861
|
+
* task type unconditionally here would put an internal-flow name on real
|
|
8862
|
+
* conversation, which is the same boundary `INTERNAL_FLOW_MARKER` draws
|
|
8863
|
+
* (reflect is deliberately unmarked; its background caller marks its own
|
|
8864
|
+
* prompt — see ../internalFlowMarker.ts). So the name is per call: only a
|
|
8865
|
+
* caller with ONE fixed purpose passes
|
|
8866
|
+
* one, and today that is profile-facet synthesis (`memory_profile_synth`).
|
|
8867
|
+
*/
|
|
8868
|
+
taskType?: TaskType;
|
|
8760
8869
|
/** Endpoint for the answer LLM. */
|
|
8761
8870
|
baseUrl?: string;
|
|
8762
8871
|
/** Override fetch (for tests). */
|