@anuma/sdk 6.29.2 → 6.30.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/index.cjs +89 -32
- package/dist/expo/index.d.mts +4 -0
- package/dist/expo/index.d.ts +4 -0
- package/dist/expo/index.mjs +89 -32
- package/dist/memory/context.cjs +8 -2
- package/dist/memory/context.d.mts +3 -0
- package/dist/memory/context.d.ts +3 -0
- package/dist/memory/context.mjs +8 -2
- package/dist/react/index.cjs +91 -33
- package/dist/react/index.d.mts +4 -0
- package/dist/react/index.d.ts +4 -0
- package/dist/react/index.mjs +91 -33
- package/dist/server/index.cjs +116 -32
- package/dist/server/index.d.mts +3 -0
- package/dist/server/index.d.ts +3 -0
- package/dist/server/index.mjs +116 -32
- package/dist/tools/index.cjs +2 -1
- package/dist/tools/index.mjs +2 -1
- package/package.json +1 -1
package/dist/server/index.cjs
CHANGED
|
@@ -22386,6 +22386,33 @@ async function getAllVaultMemoriesOp(ctx, options) {
|
|
|
22386
22386
|
(raw) => vaultMemoryRawToStored(raw, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
|
|
22387
22387
|
);
|
|
22388
22388
|
}
|
|
22389
|
+
function vaultMemoryRawToRankable(raw) {
|
|
22390
|
+
return {
|
|
22391
|
+
uniqueId: raw.id,
|
|
22392
|
+
// @text coerces NULL→"" on the Model path; unsafeFetchRaw returns raw NULL, so guard.
|
|
22393
|
+
scope: raw.scope ?? "",
|
|
22394
|
+
folderId: raw.folder_id ?? null,
|
|
22395
|
+
embedding: raw.embedding ?? null,
|
|
22396
|
+
embeddingModel: raw.embedding_model ?? null,
|
|
22397
|
+
createdAt: new Date(raw.created_at),
|
|
22398
|
+
updatedAt: new Date(raw.updated_at),
|
|
22399
|
+
// Same mapping as vaultMemoryRawToStoredRaw. A consolidation rewrite moves
|
|
22400
|
+
// ONLY this column (preserveUpdatedAt pins updated_at), so a change-since
|
|
22401
|
+
// check that reads this projection needs it — see the type doc.
|
|
22402
|
+
lastObservedAt: raw.last_observed_at ?? null
|
|
22403
|
+
};
|
|
22404
|
+
}
|
|
22405
|
+
async function getVaultRankingProjectionsOp(ctx, options) {
|
|
22406
|
+
const conditions = [
|
|
22407
|
+
...baseVaultConditions(ctx, options),
|
|
22408
|
+
...options?.scopes?.length ? [import_watermelondb18.Q.where("scope", import_watermelondb18.Q.oneOf(options.scopes))] : [],
|
|
22409
|
+
...options?.folderId !== void 0 ? [import_watermelondb18.Q.where("folder_id", options.folderId)] : [],
|
|
22410
|
+
import_watermelondb18.Q.sortBy(options?.since ? "updated_at" : "created_at", import_watermelondb18.Q.desc),
|
|
22411
|
+
...options?.limit !== null && options?.limit !== void 0 && options.limit > 0 ? [import_watermelondb18.Q.take(options.limit)] : []
|
|
22412
|
+
];
|
|
22413
|
+
const results = await ctx.vaultMemoryCollection.query(...conditions).unsafeFetchRaw();
|
|
22414
|
+
return results.map(vaultMemoryRawToRankable);
|
|
22415
|
+
}
|
|
22389
22416
|
function baseVaultSql(ctx, options) {
|
|
22390
22417
|
const clauses = [
|
|
22391
22418
|
'"is_deleted" = 0',
|
|
@@ -30795,6 +30822,11 @@ function formatEventTime(start, end, kind) {
|
|
|
30795
30822
|
if (kind === "ongoing") return `, event: since ${startDate}`;
|
|
30796
30823
|
return `, event: ${startDate}`;
|
|
30797
30824
|
}
|
|
30825
|
+
function formatSavedTime(createdAt) {
|
|
30826
|
+
const ms = createdAt?.getTime();
|
|
30827
|
+
if (ms === void 0 || !Number.isFinite(ms) || ms <= 0) return "";
|
|
30828
|
+
return `, saved: ${new Date(ms).toISOString().slice(0, 10)}`;
|
|
30829
|
+
}
|
|
30798
30830
|
function generateFenceNonce() {
|
|
30799
30831
|
const bytes = new Uint8Array(9);
|
|
30800
30832
|
crypto.getRandomValues(bytes);
|
|
@@ -30813,8 +30845,9 @@ function formatRecallResult(memories) {
|
|
|
30813
30845
|
const lines = memories.map((m, i) => {
|
|
30814
30846
|
let body;
|
|
30815
30847
|
if (m.kind === "fact") {
|
|
30848
|
+
const savedSuffix = formatSavedTime(m.createdAt);
|
|
30816
30849
|
const eventSuffix = formatEventTime(m.eventTimeStart, m.eventTimeEnd, m.eventTimeKind);
|
|
30817
|
-
body = `[${i + 1}] fact (id: ${m.id}${eventSuffix})
|
|
30850
|
+
body = `[${i + 1}] fact (id: ${m.id}${savedSuffix}${eventSuffix})
|
|
30818
30851
|
${m.content}`;
|
|
30819
30852
|
} else {
|
|
30820
30853
|
const date10 = m.createdAt.toISOString().slice(0, 10);
|
|
@@ -30864,6 +30897,40 @@ function isDumpQuery(query) {
|
|
|
30864
30897
|
if (EVERYTHING_YOU_KNOW_RE.test(q)) return true;
|
|
30865
30898
|
return false;
|
|
30866
30899
|
}
|
|
30900
|
+
async function listRecentFacts(ctx, limit, toolOptions) {
|
|
30901
|
+
const vaultCtx = ctx.vaultCtx;
|
|
30902
|
+
if (!vaultCtx) return [];
|
|
30903
|
+
const ordered = await getVaultRankingProjectionsOp(vaultCtx, {
|
|
30904
|
+
...toolOptions?.scopes && { scopes: toolOptions.scopes },
|
|
30905
|
+
...toolOptions?.memoryIds !== void 0 && { memoryIds: toolOptions.memoryIds },
|
|
30906
|
+
...toolOptions?.folderId !== void 0 && { folderId: toolOptions.folderId }
|
|
30907
|
+
});
|
|
30908
|
+
const readable = [];
|
|
30909
|
+
for (let i = 0; i < ordered.length && readable.length < limit; i += limit) {
|
|
30910
|
+
const batch = ordered.slice(i, i + limit).map((p) => p.uniqueId);
|
|
30911
|
+
const byId = new Map(
|
|
30912
|
+
(await getVaultMemoriesByIdsOp(vaultCtx, batch)).map((m) => [m.uniqueId, m])
|
|
30913
|
+
);
|
|
30914
|
+
for (const id of batch) {
|
|
30915
|
+
const m = byId.get(id);
|
|
30916
|
+
if (m && !isEncrypted(m.content)) readable.push(m);
|
|
30917
|
+
if (readable.length >= limit) break;
|
|
30918
|
+
}
|
|
30919
|
+
}
|
|
30920
|
+
return readable.map((m) => ({
|
|
30921
|
+
id: m.uniqueId,
|
|
30922
|
+
kind: "fact",
|
|
30923
|
+
content: m.content,
|
|
30924
|
+
score: 0,
|
|
30925
|
+
folderId: m.folderId,
|
|
30926
|
+
eventTimeStart: m.eventTimeStart,
|
|
30927
|
+
eventTimeEnd: m.eventTimeEnd,
|
|
30928
|
+
eventTimeKind: m.eventTimeKind,
|
|
30929
|
+
factType: m.factType,
|
|
30930
|
+
createdAt: m.createdAt,
|
|
30931
|
+
updatedAt: m.updatedAt
|
|
30932
|
+
}));
|
|
30933
|
+
}
|
|
30867
30934
|
function createRecallTool(ctx, toolOptions, callbacks) {
|
|
30868
30935
|
const defaultTypes = toolOptions?.types ?? ["fact", "chunk"];
|
|
30869
30936
|
const defaultLimit = toolOptions?.limit ?? DEFAULT_LIMIT2;
|
|
@@ -30876,7 +30943,7 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
30876
30943
|
type: "function",
|
|
30877
30944
|
function: {
|
|
30878
30945
|
name: RECALL_TOOL_NAME,
|
|
30879
|
-
description:
|
|
30946
|
+
description: 'Search the user\'s memory across stored facts/preferences and past conversation excerpts. Returns a unified ranked list \u2014 facts carry an `id` you can reference and the date they were saved; conversation excerpts carry a date and role. Use this whenever the user\'s question may relate to anything previously discussed or saved (preferences, prior decisions, past topics). Phrase the query naturally. For multi-faceted / overview questions ("tell me about the user", "what\'s my tech stack"), prefer several targeted searches \u2014 one facet each (e.g. name, work, hobbies) \u2014 over a single broad query; fuse the results yourself. For "what did I save recently / latest memories" questions, set `sort` to "recent" to get the newest saved facts, newest first, instead of a relevance search.',
|
|
30880
30947
|
arguments: {
|
|
30881
30948
|
type: "object",
|
|
30882
30949
|
properties: {
|
|
@@ -30887,6 +30954,11 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
30887
30954
|
limit: {
|
|
30888
30955
|
type: "integer",
|
|
30889
30956
|
description: `Max number of results. Default: ${defaultLimit}.`
|
|
30957
|
+
},
|
|
30958
|
+
sort: {
|
|
30959
|
+
type: "string",
|
|
30960
|
+
enum: ["relevance", "recent"],
|
|
30961
|
+
description: `"relevance" (default) ranks by match to the query. "recent" returns the newest saved facts, newest first, and ignores the query's topic.`
|
|
30890
30962
|
}
|
|
30891
30963
|
},
|
|
30892
30964
|
required: ["query"]
|
|
@@ -30931,35 +31003,41 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
30931
31003
|
let surfaced = 0;
|
|
30932
31004
|
try {
|
|
30933
31005
|
let recallDegraded = [];
|
|
30934
|
-
|
|
30935
|
-
|
|
30936
|
-
|
|
30937
|
-
|
|
30938
|
-
|
|
31006
|
+
const wantsRecent = args.sort === "recent" && defaultTypes.includes("fact") && ctx.vaultCtx !== void 0;
|
|
31007
|
+
let result;
|
|
31008
|
+
if (wantsRecent) {
|
|
31009
|
+
result = { memories: await listRecentFacts(ctx, effectiveLimit, toolOptions) };
|
|
31010
|
+
} else {
|
|
31011
|
+
let subQueries;
|
|
31012
|
+
if (defaultBudget === "high" && toolOptions?.decomposeOptions) {
|
|
31013
|
+
const decomp = await decomposeQuery(query, toolOptions.decomposeOptions);
|
|
31014
|
+
if (decomp.mode === "composite" && decomp.subQueries.length >= 2) {
|
|
31015
|
+
subQueries = decomp.subQueries;
|
|
31016
|
+
}
|
|
30939
31017
|
}
|
|
31018
|
+
const recallOpts = {
|
|
31019
|
+
onDiagnostics: (d) => {
|
|
31020
|
+
recallDegraded = d.degraded;
|
|
31021
|
+
},
|
|
31022
|
+
types: defaultTypes,
|
|
31023
|
+
limit: effectiveLimit,
|
|
31024
|
+
budget: defaultBudget,
|
|
31025
|
+
...toolOptions?.minScore !== void 0 && { minScore: toolOptions.minScore },
|
|
31026
|
+
...toolOptions?.scopes && { scopes: toolOptions.scopes },
|
|
31027
|
+
...toolOptions?.memoryIds !== void 0 && { memoryIds: toolOptions.memoryIds },
|
|
31028
|
+
...toolOptions?.folderId !== void 0 && { folderId: toolOptions.folderId },
|
|
31029
|
+
...toolOptions?.excludeConversationId && {
|
|
31030
|
+
excludeConversationId: toolOptions.excludeConversationId
|
|
31031
|
+
},
|
|
31032
|
+
// Do NOT forward decomposeOptions into recall() — rewrite already
|
|
31033
|
+
// ran above, and forwarding would falsely trip `decompose-moved`
|
|
31034
|
+
// on every specific-mode high-budget call. graphRefine auth can
|
|
31035
|
+
// be threaded later when the tool opts into that path.
|
|
31036
|
+
...toolOptions?.now !== void 0 && { now: toolOptions.now },
|
|
31037
|
+
...subQueries && { subQueries }
|
|
31038
|
+
};
|
|
31039
|
+
result = await recall(query, ctx, recallOpts);
|
|
30940
31040
|
}
|
|
30941
|
-
const recallOpts = {
|
|
30942
|
-
onDiagnostics: (d) => {
|
|
30943
|
-
recallDegraded = d.degraded;
|
|
30944
|
-
},
|
|
30945
|
-
types: defaultTypes,
|
|
30946
|
-
limit: effectiveLimit,
|
|
30947
|
-
budget: defaultBudget,
|
|
30948
|
-
...toolOptions?.minScore !== void 0 && { minScore: toolOptions.minScore },
|
|
30949
|
-
...toolOptions?.scopes && { scopes: toolOptions.scopes },
|
|
30950
|
-
...toolOptions?.memoryIds !== void 0 && { memoryIds: toolOptions.memoryIds },
|
|
30951
|
-
...toolOptions?.folderId !== void 0 && { folderId: toolOptions.folderId },
|
|
30952
|
-
...toolOptions?.excludeConversationId && {
|
|
30953
|
-
excludeConversationId: toolOptions.excludeConversationId
|
|
30954
|
-
},
|
|
30955
|
-
// Do NOT forward decomposeOptions into recall() — rewrite already
|
|
30956
|
-
// ran above, and forwarding would falsely trip `decompose-moved`
|
|
30957
|
-
// on every specific-mode high-budget call. graphRefine auth can
|
|
30958
|
-
// be threaded later when the tool opts into that path.
|
|
30959
|
-
...toolOptions?.now !== void 0 && { now: toolOptions.now },
|
|
30960
|
-
...subQueries && { subQueries }
|
|
30961
|
-
};
|
|
30962
|
-
const result = await recall(query, ctx, recallOpts);
|
|
30963
31041
|
if (callbacks?.onChunksRetrieved) {
|
|
30964
31042
|
const convIds = Array.from(
|
|
30965
31043
|
new Set(
|
|
@@ -30972,7 +31050,7 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
30972
31050
|
const facts = result.memories.filter((m) => m.kind === "fact").map((m) => ({ id: m.id, score: m.score }));
|
|
30973
31051
|
if (facts.length > 0) {
|
|
30974
31052
|
callbacks.onFactsRetrieved?.(facts.map((f) => f.id));
|
|
30975
|
-
callbacks.onFactsRanked?.(facts);
|
|
31053
|
+
if (!wantsRecent) callbacks.onFactsRanked?.(facts);
|
|
30976
31054
|
}
|
|
30977
31055
|
}
|
|
30978
31056
|
surfaced = result.memories.length;
|
|
@@ -32153,6 +32231,10 @@ function createMessageSourceResolver(ctx) {
|
|
|
32153
32231
|
}
|
|
32154
32232
|
|
|
32155
32233
|
// src/lib/memory/context.ts
|
|
32234
|
+
function savedAt(createdAt) {
|
|
32235
|
+
const ms = createdAt?.getTime();
|
|
32236
|
+
return ms !== void 0 && Number.isFinite(ms) && ms > 0 ? { createdAt } : {};
|
|
32237
|
+
}
|
|
32156
32238
|
function shouldRecallMemory(query) {
|
|
32157
32239
|
const normalized = query.trim().toLowerCase().replace(/[.!?。!?¡¿]+$/u, "").replace(/^[¡¿]+/u, "");
|
|
32158
32240
|
return normalized.length > 0 && !/^(hi|hi there|hello|hey|yes|no|yep|nope|sure|k|ok|okay|thanks|thank you|thank you very much|thanks a lot|cool|great|got it|sounds good|hola|buenos días|buenas|sí|si|gracias|muchas gracias|vale|bonjour|salut|oui|non|merci|merci beaucoup|d'accord|hallo|guten tag|ja|nein|danke|danke schön|alles klar|olá|obrigado|obrigada|ciao|grazie|sì|你好|谢谢|好的|こんにちは|ありがとう|안녕하세요|감사합니다)$/u.test(
|
|
@@ -32190,7 +32272,8 @@ async function assembleMemoryContext(options) {
|
|
|
32190
32272
|
content: m.content,
|
|
32191
32273
|
score,
|
|
32192
32274
|
lane,
|
|
32193
|
-
sourceIds: m.sourceChunkIds ?? []
|
|
32275
|
+
sourceIds: m.sourceChunkIds ?? [],
|
|
32276
|
+
...savedAt(m.createdAt)
|
|
32194
32277
|
});
|
|
32195
32278
|
const empty = {
|
|
32196
32279
|
memories: [],
|
|
@@ -32255,7 +32338,8 @@ async function assembleMemoryContext(options) {
|
|
|
32255
32338
|
score: m.score,
|
|
32256
32339
|
lane,
|
|
32257
32340
|
...lane === "fact" && { recalled: true },
|
|
32258
|
-
sourceIds: m.sourceChunkIds ?? (m.messageId ? [m.messageId] : [])
|
|
32341
|
+
sourceIds: m.sourceChunkIds ?? (m.messageId ? [m.messageId] : []),
|
|
32342
|
+
...savedAt(m.createdAt)
|
|
32259
32343
|
}));
|
|
32260
32344
|
const recalledFacts = toItems(facts, "fact");
|
|
32261
32345
|
const recalledScores = /* @__PURE__ */ new Map();
|
package/dist/server/index.d.mts
CHANGED
|
@@ -10200,6 +10200,9 @@ interface MemoryContextItem {
|
|
|
10200
10200
|
sourceIds: string[];
|
|
10201
10201
|
/** Ranked fact evidence, retained when profile deduplication wins placement. */
|
|
10202
10202
|
recalled?: boolean;
|
|
10203
|
+
/** When the memory was written — lets the prompt show a saved date so the
|
|
10204
|
+
* model can answer "what did I save recently". */
|
|
10205
|
+
createdAt?: Date;
|
|
10203
10206
|
}
|
|
10204
10207
|
interface MemoryContextOptions {
|
|
10205
10208
|
query: string;
|
package/dist/server/index.d.ts
CHANGED
|
@@ -10200,6 +10200,9 @@ interface MemoryContextItem {
|
|
|
10200
10200
|
sourceIds: string[];
|
|
10201
10201
|
/** Ranked fact evidence, retained when profile deduplication wins placement. */
|
|
10202
10202
|
recalled?: boolean;
|
|
10203
|
+
/** When the memory was written — lets the prompt show a saved date so the
|
|
10204
|
+
* model can answer "what did I save recently". */
|
|
10205
|
+
createdAt?: Date;
|
|
10203
10206
|
}
|
|
10204
10207
|
interface MemoryContextOptions {
|
|
10205
10208
|
query: string;
|
package/dist/server/index.mjs
CHANGED
|
@@ -20701,6 +20701,33 @@ async function getAllVaultMemoriesOp(ctx, options) {
|
|
|
20701
20701
|
(raw) => vaultMemoryRawToStored(raw, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
|
|
20702
20702
|
);
|
|
20703
20703
|
}
|
|
20704
|
+
function vaultMemoryRawToRankable(raw) {
|
|
20705
|
+
return {
|
|
20706
|
+
uniqueId: raw.id,
|
|
20707
|
+
// @text coerces NULL→"" on the Model path; unsafeFetchRaw returns raw NULL, so guard.
|
|
20708
|
+
scope: raw.scope ?? "",
|
|
20709
|
+
folderId: raw.folder_id ?? null,
|
|
20710
|
+
embedding: raw.embedding ?? null,
|
|
20711
|
+
embeddingModel: raw.embedding_model ?? null,
|
|
20712
|
+
createdAt: new Date(raw.created_at),
|
|
20713
|
+
updatedAt: new Date(raw.updated_at),
|
|
20714
|
+
// Same mapping as vaultMemoryRawToStoredRaw. A consolidation rewrite moves
|
|
20715
|
+
// ONLY this column (preserveUpdatedAt pins updated_at), so a change-since
|
|
20716
|
+
// check that reads this projection needs it — see the type doc.
|
|
20717
|
+
lastObservedAt: raw.last_observed_at ?? null
|
|
20718
|
+
};
|
|
20719
|
+
}
|
|
20720
|
+
async function getVaultRankingProjectionsOp(ctx, options) {
|
|
20721
|
+
const conditions = [
|
|
20722
|
+
...baseVaultConditions(ctx, options),
|
|
20723
|
+
...options?.scopes?.length ? [import_watermelondb18.Q.where("scope", import_watermelondb18.Q.oneOf(options.scopes))] : [],
|
|
20724
|
+
...options?.folderId !== void 0 ? [import_watermelondb18.Q.where("folder_id", options.folderId)] : [],
|
|
20725
|
+
import_watermelondb18.Q.sortBy(options?.since ? "updated_at" : "created_at", import_watermelondb18.Q.desc),
|
|
20726
|
+
...options?.limit !== null && options?.limit !== void 0 && options.limit > 0 ? [import_watermelondb18.Q.take(options.limit)] : []
|
|
20727
|
+
];
|
|
20728
|
+
const results = await ctx.vaultMemoryCollection.query(...conditions).unsafeFetchRaw();
|
|
20729
|
+
return results.map(vaultMemoryRawToRankable);
|
|
20730
|
+
}
|
|
20704
20731
|
function baseVaultSql(ctx, options) {
|
|
20705
20732
|
const clauses = [
|
|
20706
20733
|
'"is_deleted" = 0',
|
|
@@ -29072,6 +29099,11 @@ function formatEventTime(start, end, kind) {
|
|
|
29072
29099
|
if (kind === "ongoing") return `, event: since ${startDate}`;
|
|
29073
29100
|
return `, event: ${startDate}`;
|
|
29074
29101
|
}
|
|
29102
|
+
function formatSavedTime(createdAt) {
|
|
29103
|
+
const ms = createdAt?.getTime();
|
|
29104
|
+
if (ms === void 0 || !Number.isFinite(ms) || ms <= 0) return "";
|
|
29105
|
+
return `, saved: ${new Date(ms).toISOString().slice(0, 10)}`;
|
|
29106
|
+
}
|
|
29075
29107
|
function generateFenceNonce() {
|
|
29076
29108
|
const bytes = new Uint8Array(9);
|
|
29077
29109
|
crypto.getRandomValues(bytes);
|
|
@@ -29090,8 +29122,9 @@ function formatRecallResult(memories) {
|
|
|
29090
29122
|
const lines = memories.map((m, i) => {
|
|
29091
29123
|
let body;
|
|
29092
29124
|
if (m.kind === "fact") {
|
|
29125
|
+
const savedSuffix = formatSavedTime(m.createdAt);
|
|
29093
29126
|
const eventSuffix = formatEventTime(m.eventTimeStart, m.eventTimeEnd, m.eventTimeKind);
|
|
29094
|
-
body = `[${i + 1}] fact (id: ${m.id}${eventSuffix})
|
|
29127
|
+
body = `[${i + 1}] fact (id: ${m.id}${savedSuffix}${eventSuffix})
|
|
29095
29128
|
${m.content}`;
|
|
29096
29129
|
} else {
|
|
29097
29130
|
const date10 = m.createdAt.toISOString().slice(0, 10);
|
|
@@ -29141,6 +29174,40 @@ function isDumpQuery(query) {
|
|
|
29141
29174
|
if (EVERYTHING_YOU_KNOW_RE.test(q)) return true;
|
|
29142
29175
|
return false;
|
|
29143
29176
|
}
|
|
29177
|
+
async function listRecentFacts(ctx, limit, toolOptions) {
|
|
29178
|
+
const vaultCtx = ctx.vaultCtx;
|
|
29179
|
+
if (!vaultCtx) return [];
|
|
29180
|
+
const ordered = await getVaultRankingProjectionsOp(vaultCtx, {
|
|
29181
|
+
...toolOptions?.scopes && { scopes: toolOptions.scopes },
|
|
29182
|
+
...toolOptions?.memoryIds !== void 0 && { memoryIds: toolOptions.memoryIds },
|
|
29183
|
+
...toolOptions?.folderId !== void 0 && { folderId: toolOptions.folderId }
|
|
29184
|
+
});
|
|
29185
|
+
const readable = [];
|
|
29186
|
+
for (let i = 0; i < ordered.length && readable.length < limit; i += limit) {
|
|
29187
|
+
const batch = ordered.slice(i, i + limit).map((p) => p.uniqueId);
|
|
29188
|
+
const byId = new Map(
|
|
29189
|
+
(await getVaultMemoriesByIdsOp(vaultCtx, batch)).map((m) => [m.uniqueId, m])
|
|
29190
|
+
);
|
|
29191
|
+
for (const id of batch) {
|
|
29192
|
+
const m = byId.get(id);
|
|
29193
|
+
if (m && !isEncrypted(m.content)) readable.push(m);
|
|
29194
|
+
if (readable.length >= limit) break;
|
|
29195
|
+
}
|
|
29196
|
+
}
|
|
29197
|
+
return readable.map((m) => ({
|
|
29198
|
+
id: m.uniqueId,
|
|
29199
|
+
kind: "fact",
|
|
29200
|
+
content: m.content,
|
|
29201
|
+
score: 0,
|
|
29202
|
+
folderId: m.folderId,
|
|
29203
|
+
eventTimeStart: m.eventTimeStart,
|
|
29204
|
+
eventTimeEnd: m.eventTimeEnd,
|
|
29205
|
+
eventTimeKind: m.eventTimeKind,
|
|
29206
|
+
factType: m.factType,
|
|
29207
|
+
createdAt: m.createdAt,
|
|
29208
|
+
updatedAt: m.updatedAt
|
|
29209
|
+
}));
|
|
29210
|
+
}
|
|
29144
29211
|
function createRecallTool(ctx, toolOptions, callbacks) {
|
|
29145
29212
|
const defaultTypes = toolOptions?.types ?? ["fact", "chunk"];
|
|
29146
29213
|
const defaultLimit = toolOptions?.limit ?? DEFAULT_LIMIT2;
|
|
@@ -29153,7 +29220,7 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
29153
29220
|
type: "function",
|
|
29154
29221
|
function: {
|
|
29155
29222
|
name: RECALL_TOOL_NAME,
|
|
29156
|
-
description:
|
|
29223
|
+
description: 'Search the user\'s memory across stored facts/preferences and past conversation excerpts. Returns a unified ranked list \u2014 facts carry an `id` you can reference and the date they were saved; conversation excerpts carry a date and role. Use this whenever the user\'s question may relate to anything previously discussed or saved (preferences, prior decisions, past topics). Phrase the query naturally. For multi-faceted / overview questions ("tell me about the user", "what\'s my tech stack"), prefer several targeted searches \u2014 one facet each (e.g. name, work, hobbies) \u2014 over a single broad query; fuse the results yourself. For "what did I save recently / latest memories" questions, set `sort` to "recent" to get the newest saved facts, newest first, instead of a relevance search.',
|
|
29157
29224
|
arguments: {
|
|
29158
29225
|
type: "object",
|
|
29159
29226
|
properties: {
|
|
@@ -29164,6 +29231,11 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
29164
29231
|
limit: {
|
|
29165
29232
|
type: "integer",
|
|
29166
29233
|
description: `Max number of results. Default: ${defaultLimit}.`
|
|
29234
|
+
},
|
|
29235
|
+
sort: {
|
|
29236
|
+
type: "string",
|
|
29237
|
+
enum: ["relevance", "recent"],
|
|
29238
|
+
description: `"relevance" (default) ranks by match to the query. "recent" returns the newest saved facts, newest first, and ignores the query's topic.`
|
|
29167
29239
|
}
|
|
29168
29240
|
},
|
|
29169
29241
|
required: ["query"]
|
|
@@ -29208,35 +29280,41 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
29208
29280
|
let surfaced = 0;
|
|
29209
29281
|
try {
|
|
29210
29282
|
let recallDegraded = [];
|
|
29211
|
-
|
|
29212
|
-
|
|
29213
|
-
|
|
29214
|
-
|
|
29215
|
-
|
|
29283
|
+
const wantsRecent = args.sort === "recent" && defaultTypes.includes("fact") && ctx.vaultCtx !== void 0;
|
|
29284
|
+
let result;
|
|
29285
|
+
if (wantsRecent) {
|
|
29286
|
+
result = { memories: await listRecentFacts(ctx, effectiveLimit, toolOptions) };
|
|
29287
|
+
} else {
|
|
29288
|
+
let subQueries;
|
|
29289
|
+
if (defaultBudget === "high" && toolOptions?.decomposeOptions) {
|
|
29290
|
+
const decomp = await decomposeQuery(query, toolOptions.decomposeOptions);
|
|
29291
|
+
if (decomp.mode === "composite" && decomp.subQueries.length >= 2) {
|
|
29292
|
+
subQueries = decomp.subQueries;
|
|
29293
|
+
}
|
|
29216
29294
|
}
|
|
29295
|
+
const recallOpts = {
|
|
29296
|
+
onDiagnostics: (d) => {
|
|
29297
|
+
recallDegraded = d.degraded;
|
|
29298
|
+
},
|
|
29299
|
+
types: defaultTypes,
|
|
29300
|
+
limit: effectiveLimit,
|
|
29301
|
+
budget: defaultBudget,
|
|
29302
|
+
...toolOptions?.minScore !== void 0 && { minScore: toolOptions.minScore },
|
|
29303
|
+
...toolOptions?.scopes && { scopes: toolOptions.scopes },
|
|
29304
|
+
...toolOptions?.memoryIds !== void 0 && { memoryIds: toolOptions.memoryIds },
|
|
29305
|
+
...toolOptions?.folderId !== void 0 && { folderId: toolOptions.folderId },
|
|
29306
|
+
...toolOptions?.excludeConversationId && {
|
|
29307
|
+
excludeConversationId: toolOptions.excludeConversationId
|
|
29308
|
+
},
|
|
29309
|
+
// Do NOT forward decomposeOptions into recall() — rewrite already
|
|
29310
|
+
// ran above, and forwarding would falsely trip `decompose-moved`
|
|
29311
|
+
// on every specific-mode high-budget call. graphRefine auth can
|
|
29312
|
+
// be threaded later when the tool opts into that path.
|
|
29313
|
+
...toolOptions?.now !== void 0 && { now: toolOptions.now },
|
|
29314
|
+
...subQueries && { subQueries }
|
|
29315
|
+
};
|
|
29316
|
+
result = await recall(query, ctx, recallOpts);
|
|
29217
29317
|
}
|
|
29218
|
-
const recallOpts = {
|
|
29219
|
-
onDiagnostics: (d) => {
|
|
29220
|
-
recallDegraded = d.degraded;
|
|
29221
|
-
},
|
|
29222
|
-
types: defaultTypes,
|
|
29223
|
-
limit: effectiveLimit,
|
|
29224
|
-
budget: defaultBudget,
|
|
29225
|
-
...toolOptions?.minScore !== void 0 && { minScore: toolOptions.minScore },
|
|
29226
|
-
...toolOptions?.scopes && { scopes: toolOptions.scopes },
|
|
29227
|
-
...toolOptions?.memoryIds !== void 0 && { memoryIds: toolOptions.memoryIds },
|
|
29228
|
-
...toolOptions?.folderId !== void 0 && { folderId: toolOptions.folderId },
|
|
29229
|
-
...toolOptions?.excludeConversationId && {
|
|
29230
|
-
excludeConversationId: toolOptions.excludeConversationId
|
|
29231
|
-
},
|
|
29232
|
-
// Do NOT forward decomposeOptions into recall() — rewrite already
|
|
29233
|
-
// ran above, and forwarding would falsely trip `decompose-moved`
|
|
29234
|
-
// on every specific-mode high-budget call. graphRefine auth can
|
|
29235
|
-
// be threaded later when the tool opts into that path.
|
|
29236
|
-
...toolOptions?.now !== void 0 && { now: toolOptions.now },
|
|
29237
|
-
...subQueries && { subQueries }
|
|
29238
|
-
};
|
|
29239
|
-
const result = await recall(query, ctx, recallOpts);
|
|
29240
29318
|
if (callbacks?.onChunksRetrieved) {
|
|
29241
29319
|
const convIds = Array.from(
|
|
29242
29320
|
new Set(
|
|
@@ -29249,7 +29327,7 @@ function createRecallTool(ctx, toolOptions, callbacks) {
|
|
|
29249
29327
|
const facts = result.memories.filter((m) => m.kind === "fact").map((m) => ({ id: m.id, score: m.score }));
|
|
29250
29328
|
if (facts.length > 0) {
|
|
29251
29329
|
callbacks.onFactsRetrieved?.(facts.map((f) => f.id));
|
|
29252
|
-
callbacks.onFactsRanked?.(facts);
|
|
29330
|
+
if (!wantsRecent) callbacks.onFactsRanked?.(facts);
|
|
29253
29331
|
}
|
|
29254
29332
|
}
|
|
29255
29333
|
surfaced = result.memories.length;
|
|
@@ -30418,6 +30496,10 @@ function createMessageSourceResolver(ctx) {
|
|
|
30418
30496
|
}
|
|
30419
30497
|
|
|
30420
30498
|
// src/lib/memory/context.ts
|
|
30499
|
+
function savedAt(createdAt) {
|
|
30500
|
+
const ms = createdAt?.getTime();
|
|
30501
|
+
return ms !== void 0 && Number.isFinite(ms) && ms > 0 ? { createdAt } : {};
|
|
30502
|
+
}
|
|
30421
30503
|
function shouldRecallMemory(query) {
|
|
30422
30504
|
const normalized = query.trim().toLowerCase().replace(/[.!?。!?¡¿]+$/u, "").replace(/^[¡¿]+/u, "");
|
|
30423
30505
|
return normalized.length > 0 && !/^(hi|hi there|hello|hey|yes|no|yep|nope|sure|k|ok|okay|thanks|thank you|thank you very much|thanks a lot|cool|great|got it|sounds good|hola|buenos días|buenas|sí|si|gracias|muchas gracias|vale|bonjour|salut|oui|non|merci|merci beaucoup|d'accord|hallo|guten tag|ja|nein|danke|danke schön|alles klar|olá|obrigado|obrigada|ciao|grazie|sì|你好|谢谢|好的|こんにちは|ありがとう|안녕하세요|감사합니다)$/u.test(
|
|
@@ -30455,7 +30537,8 @@ async function assembleMemoryContext(options) {
|
|
|
30455
30537
|
content: m.content,
|
|
30456
30538
|
score,
|
|
30457
30539
|
lane,
|
|
30458
|
-
sourceIds: m.sourceChunkIds ?? []
|
|
30540
|
+
sourceIds: m.sourceChunkIds ?? [],
|
|
30541
|
+
...savedAt(m.createdAt)
|
|
30459
30542
|
});
|
|
30460
30543
|
const empty = {
|
|
30461
30544
|
memories: [],
|
|
@@ -30520,7 +30603,8 @@ async function assembleMemoryContext(options) {
|
|
|
30520
30603
|
score: m.score,
|
|
30521
30604
|
lane,
|
|
30522
30605
|
...lane === "fact" && { recalled: true },
|
|
30523
|
-
sourceIds: m.sourceChunkIds ?? (m.messageId ? [m.messageId] : [])
|
|
30606
|
+
sourceIds: m.sourceChunkIds ?? (m.messageId ? [m.messageId] : []),
|
|
30607
|
+
...savedAt(m.createdAt)
|
|
30524
30608
|
}));
|
|
30525
30609
|
const recalledFacts = toItems(facts, "fact");
|
|
30526
30610
|
const recalledScores = /* @__PURE__ */ new Map();
|
package/dist/tools/index.cjs
CHANGED
|
@@ -6985,7 +6985,8 @@ var DEFAULT_COLORS = {
|
|
|
6985
6985
|
textPrimary: "#ffffff",
|
|
6986
6986
|
textSecondary: "#ffffff",
|
|
6987
6987
|
textMuted: "#9a9592",
|
|
6988
|
-
|
|
6988
|
+
// White on the dark default deck — the brand orange is retired (#8419).
|
|
6989
|
+
accent: "#ffffff",
|
|
6989
6990
|
card: "#1a1a21",
|
|
6990
6991
|
border: "#434242"
|
|
6991
6992
|
};
|
package/dist/tools/index.mjs
CHANGED
|
@@ -6829,7 +6829,8 @@ var DEFAULT_COLORS = {
|
|
|
6829
6829
|
textPrimary: "#ffffff",
|
|
6830
6830
|
textSecondary: "#ffffff",
|
|
6831
6831
|
textMuted: "#9a9592",
|
|
6832
|
-
|
|
6832
|
+
// White on the dark default deck — the brand orange is retired (#8419).
|
|
6833
|
+
accent: "#ffffff",
|
|
6833
6834
|
card: "#1a1a21",
|
|
6834
6835
|
border: "#434242"
|
|
6835
6836
|
};
|