@anuma/sdk 2.4.2 → 2.6.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-UOUJUZM4.mjs → chunk-TCRDSUC6.mjs} +107 -5
- package/dist/expo/{consolidate-HEMQGOUD.mjs → consolidate-3QQPUWD6.mjs} +15 -9
- package/dist/expo/index.cjs +264 -70
- package/dist/expo/index.d.mts +77 -17
- package/dist/expo/index.d.ts +77 -17
- package/dist/expo/index.mjs +148 -58
- package/dist/{react/recall-G3CS444F.mjs → expo/recall-FQU3NUTL.mjs} +1 -1
- package/dist/react/{chunk-IYDQBFS2.mjs → chunk-ZXS3KOY4.mjs} +111 -6
- package/dist/react/{consolidate-IJH7LD2T.mjs → consolidate-3MXZV3G7.mjs} +15 -9
- package/dist/react/index.cjs +268 -71
- package/dist/react/index.d.mts +85 -20
- package/dist/react/index.d.ts +85 -20
- package/dist/react/index.mjs +148 -58
- package/dist/{expo/recall-HI7VO3VM.mjs → react/recall-PV7L3SN3.mjs} +1 -1
- package/dist/server/{chunk-3MLG7SUH.mjs → chunk-Z6II54I7.mjs} +107 -5
- package/dist/server/{consolidate-TDT4HRHG.mjs → consolidate-CN2GQV4D.mjs} +15 -9
- package/dist/server/index.cjs +264 -70
- package/dist/server/index.d.mts +77 -17
- package/dist/server/index.d.ts +77 -17
- package/dist/server/index.mjs +148 -58
- package/dist/server/{recall-MJHGXMHZ.mjs → recall-CQT24XLH.mjs} +1 -1
- package/package.json +1 -1
package/dist/server/index.cjs
CHANGED
|
@@ -16864,6 +16864,7 @@ function isOwnedByCtxUser(ctx, record) {
|
|
|
16864
16864
|
function baseVaultConditions(ctx, options) {
|
|
16865
16865
|
return [
|
|
16866
16866
|
...options?.includeDeleted ? [] : [import_watermelondb17.Q.where("is_deleted", false)],
|
|
16867
|
+
...options?.includeSuperseded ? [] : [import_watermelondb17.Q.where("superseded_by", null)],
|
|
16867
16868
|
...ctx.userId !== void 0 ? [import_watermelondb17.Q.where("user_id", ctx.userId)] : [],
|
|
16868
16869
|
...options?.since ? [import_watermelondb17.Q.where("updated_at", import_watermelondb17.Q.gt(options.since.getTime()))] : []
|
|
16869
16870
|
];
|
|
@@ -16904,6 +16905,9 @@ function vaultMemoryToStoredRaw(memory) {
|
|
|
16904
16905
|
eventTimeKind: memory.eventTimeKind ?? null,
|
|
16905
16906
|
topicsUserManaged: memory.topicsUserManaged ?? false,
|
|
16906
16907
|
topicsExtractedAt: memory.topicsExtractedAt ?? null,
|
|
16908
|
+
topicsExtractedVersion: memory.topicsExtractedVersion ?? null,
|
|
16909
|
+
supersededBy: memory.supersededBy ?? null,
|
|
16910
|
+
supersededAt: memory.supersededAt ?? null,
|
|
16907
16911
|
createdAt: memory.createdAt,
|
|
16908
16912
|
updatedAt: memory.updatedAt,
|
|
16909
16913
|
isDeleted: memory.isDeleted
|
|
@@ -16949,6 +16953,59 @@ async function createVaultMemoryOp(ctx, opts) {
|
|
|
16949
16953
|
});
|
|
16950
16954
|
return vaultMemoryToStored(created, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
16951
16955
|
}
|
|
16956
|
+
async function createSupersedingMemoryOp(ctx, opts, targetId) {
|
|
16957
|
+
if (!targetId) return { created: null, retired: false };
|
|
16958
|
+
const scope = opts.scope ?? "private";
|
|
16959
|
+
const encryptedContent = ctx.walletAddress && ctx.signMessage ? await encryptVaultMemoryContent(
|
|
16960
|
+
opts.content,
|
|
16961
|
+
ctx.walletAddress,
|
|
16962
|
+
ctx.signMessage,
|
|
16963
|
+
ctx.embeddedWalletSigner
|
|
16964
|
+
) : opts.content;
|
|
16965
|
+
let createdRecord = null;
|
|
16966
|
+
await ctx.database.write(async () => {
|
|
16967
|
+
let target;
|
|
16968
|
+
try {
|
|
16969
|
+
target = await ctx.vaultMemoryCollection.find(targetId);
|
|
16970
|
+
} catch {
|
|
16971
|
+
return;
|
|
16972
|
+
}
|
|
16973
|
+
if (target.isDeleted || target.supersededBy || !isOwnedByCtxUser(ctx, target)) return;
|
|
16974
|
+
createdRecord = await ctx.vaultMemoryCollection.create((record) => {
|
|
16975
|
+
record._setRaw("content", encryptedContent);
|
|
16976
|
+
record._setRaw("scope", scope);
|
|
16977
|
+
record._setRaw("folder_id", opts.folderId ?? null);
|
|
16978
|
+
record._setRaw("user_id", ctx.userId ?? null);
|
|
16979
|
+
record._setRaw("is_deleted", false);
|
|
16980
|
+
if (opts.embedding !== void 0) {
|
|
16981
|
+
record._setRaw("embedding", opts.embedding);
|
|
16982
|
+
record._setRaw("embedding_model", opts.embeddingModel ?? null);
|
|
16983
|
+
}
|
|
16984
|
+
if (opts.sourceChunkIds !== void 0) {
|
|
16985
|
+
record._setRaw("source_chunk_ids", JSON.stringify(opts.sourceChunkIds));
|
|
16986
|
+
}
|
|
16987
|
+
record._setRaw("proof_count", opts.proofCount ?? 1);
|
|
16988
|
+
record._setRaw("source", opts.source ?? "manual");
|
|
16989
|
+
if (opts.eventTime) {
|
|
16990
|
+
record._setRaw("event_time_start", opts.eventTime.start ?? null);
|
|
16991
|
+
record._setRaw("event_time_end", opts.eventTime.end ?? null);
|
|
16992
|
+
record._setRaw("event_time_kind", opts.eventTime.kind ?? null);
|
|
16993
|
+
}
|
|
16994
|
+
});
|
|
16995
|
+
await target.update((r) => {
|
|
16996
|
+
r._setRaw("superseded_by", createdRecord.id);
|
|
16997
|
+
r._setRaw("superseded_at", Date.now());
|
|
16998
|
+
});
|
|
16999
|
+
});
|
|
17000
|
+
if (!createdRecord) return { created: null, retired: false };
|
|
17001
|
+
const created = await vaultMemoryToStored(
|
|
17002
|
+
createdRecord,
|
|
17003
|
+
ctx.walletAddress,
|
|
17004
|
+
ctx.signMessage,
|
|
17005
|
+
ctx.embeddedWalletSigner
|
|
17006
|
+
);
|
|
17007
|
+
return { created, retired: true };
|
|
17008
|
+
}
|
|
16952
17009
|
async function getMemoriesByEventTimeOp(ctx, windowStart, windowEnd) {
|
|
16953
17010
|
const records = await ctx.vaultMemoryCollection.query(
|
|
16954
17011
|
...baseVaultConditions(ctx),
|
|
@@ -17088,6 +17145,9 @@ function vaultMemoryRawToStoredRaw(raw) {
|
|
|
17088
17145
|
// SQLite stores booleans as 0/1, LokiJS as true/false — coerce both.
|
|
17089
17146
|
topicsUserManaged: raw.topics_user_managed === true || raw.topics_user_managed === 1,
|
|
17090
17147
|
topicsExtractedAt: raw.topics_extracted_at ?? null,
|
|
17148
|
+
topicsExtractedVersion: raw.topics_extracted_version ?? null,
|
|
17149
|
+
supersededBy: raw.superseded_by ?? null,
|
|
17150
|
+
supersededAt: raw.superseded_at ?? null,
|
|
17091
17151
|
createdAt: new Date(raw.created_at),
|
|
17092
17152
|
updatedAt: new Date(raw.updated_at),
|
|
17093
17153
|
isDeleted: raw.is_deleted === true || raw.is_deleted === 1
|
|
@@ -17129,7 +17189,7 @@ async function getAllVaultMemoryContentsOp(ctx, options) {
|
|
|
17129
17189
|
async function updateVaultMemoryOp(ctx, id, opts) {
|
|
17130
17190
|
try {
|
|
17131
17191
|
const probe = await ctx.vaultMemoryCollection.find(id);
|
|
17132
|
-
if (probe.isDeleted || !isOwnedByCtxUser(ctx, probe)) return null;
|
|
17192
|
+
if (probe.isDeleted || probe.supersededBy || !isOwnedByCtxUser(ctx, probe)) return null;
|
|
17133
17193
|
const encryptedContent = ctx.walletAddress && ctx.signMessage ? await encryptVaultMemoryContent(
|
|
17134
17194
|
opts.content,
|
|
17135
17195
|
ctx.walletAddress,
|
|
@@ -17140,7 +17200,7 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
17140
17200
|
const record = probe;
|
|
17141
17201
|
const originalUpdatedAt = record.updatedAt.getTime();
|
|
17142
17202
|
await ctx.database.write(async () => {
|
|
17143
|
-
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) {
|
|
17203
|
+
if (record.isDeleted || record.supersededBy || !isOwnedByCtxUser(ctx, record)) {
|
|
17144
17204
|
stale = true;
|
|
17145
17205
|
return;
|
|
17146
17206
|
}
|
|
@@ -17218,6 +17278,40 @@ async function deleteVaultMemoryOp(ctx, id) {
|
|
|
17218
17278
|
return false;
|
|
17219
17279
|
}
|
|
17220
17280
|
}
|
|
17281
|
+
async function supersedeVaultMemoryOp(ctx, id, supersededById) {
|
|
17282
|
+
if (id === supersededById) return false;
|
|
17283
|
+
try {
|
|
17284
|
+
const record = await ctx.vaultMemoryCollection.find(id);
|
|
17285
|
+
if (record.isDeleted || record.supersededBy || !isOwnedByCtxUser(ctx, record)) return false;
|
|
17286
|
+
let successor;
|
|
17287
|
+
try {
|
|
17288
|
+
successor = await ctx.vaultMemoryCollection.find(supersededById);
|
|
17289
|
+
} catch {
|
|
17290
|
+
return false;
|
|
17291
|
+
}
|
|
17292
|
+
if (successor.isDeleted || successor.supersededBy || !isOwnedByCtxUser(ctx, successor)) {
|
|
17293
|
+
return false;
|
|
17294
|
+
}
|
|
17295
|
+
let stale = false;
|
|
17296
|
+
await ctx.database.write(async () => {
|
|
17297
|
+
if (record.isDeleted || record.supersededBy || !isOwnedByCtxUser(ctx, record)) {
|
|
17298
|
+
stale = true;
|
|
17299
|
+
return;
|
|
17300
|
+
}
|
|
17301
|
+
if (successor.isDeleted || successor.supersededBy || !isOwnedByCtxUser(ctx, successor)) {
|
|
17302
|
+
stale = true;
|
|
17303
|
+
return;
|
|
17304
|
+
}
|
|
17305
|
+
await record.update((r) => {
|
|
17306
|
+
r._setRaw("superseded_by", supersededById);
|
|
17307
|
+
r._setRaw("superseded_at", Date.now());
|
|
17308
|
+
});
|
|
17309
|
+
});
|
|
17310
|
+
return !stale;
|
|
17311
|
+
} catch {
|
|
17312
|
+
return false;
|
|
17313
|
+
}
|
|
17314
|
+
}
|
|
17221
17315
|
async function getUnfiledVaultMemoriesOp(ctx) {
|
|
17222
17316
|
const conditions = [
|
|
17223
17317
|
import_watermelondb17.Q.where("folder_id", null),
|
|
@@ -17248,7 +17342,10 @@ async function getMemoriesNeedingTopicExtractionOp(ctx, options) {
|
|
|
17248
17342
|
for (const raw of rows) {
|
|
17249
17343
|
const stamp = raw.topics_extracted_at ?? null;
|
|
17250
17344
|
if (stamp !== null) {
|
|
17251
|
-
|
|
17345
|
+
const version = raw.topics_extracted_version ?? 0;
|
|
17346
|
+
if (raw.updated_at > stamp || version < TOPICS_EXTRACTION_VERSION) {
|
|
17347
|
+
stampedPending.push(raw);
|
|
17348
|
+
}
|
|
17252
17349
|
} else {
|
|
17253
17350
|
unstamped.push(raw);
|
|
17254
17351
|
}
|
|
@@ -17278,7 +17375,7 @@ async function getMemoriesNeedingTopicExtractionOp(ctx, options) {
|
|
|
17278
17375
|
);
|
|
17279
17376
|
return { pending, linkedUnstamped };
|
|
17280
17377
|
}
|
|
17281
|
-
async function stampTopicsExtractedAtOp(ctx, memoryIds, extractedAt) {
|
|
17378
|
+
async function stampTopicsExtractedAtOp(ctx, memoryIds, extractedAt, version = TOPICS_EXTRACTION_VERSION) {
|
|
17282
17379
|
if (memoryIds.length === 0) return [];
|
|
17283
17380
|
const uniqueIds = Array.from(new Set(memoryIds));
|
|
17284
17381
|
const CHUNK = 500;
|
|
@@ -17301,6 +17398,7 @@ async function stampTopicsExtractedAtOp(ctx, memoryIds, extractedAt) {
|
|
|
17301
17398
|
prepared.push(
|
|
17302
17399
|
record.prepareUpdate((r) => {
|
|
17303
17400
|
r._setRaw("topics_extracted_at", extractedAt);
|
|
17401
|
+
r._setRaw("topics_extracted_version", version);
|
|
17304
17402
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
17305
17403
|
})
|
|
17306
17404
|
);
|
|
@@ -17353,13 +17451,14 @@ async function updateVaultMemoryEmbeddingOp(ctx, id, embedding, embeddingModel)
|
|
|
17353
17451
|
return false;
|
|
17354
17452
|
}
|
|
17355
17453
|
}
|
|
17356
|
-
var import_watermelondb17;
|
|
17454
|
+
var import_watermelondb17, TOPICS_EXTRACTION_VERSION;
|
|
17357
17455
|
var init_operations3 = __esm({
|
|
17358
17456
|
"src/lib/db/memoryVault/operations.ts"() {
|
|
17359
17457
|
"use strict";
|
|
17360
17458
|
import_watermelondb17 = __toESM(require_watermelondb());
|
|
17361
17459
|
init_operations2();
|
|
17362
17460
|
init_encryption2();
|
|
17461
|
+
TOPICS_EXTRACTION_VERSION = 1;
|
|
17363
17462
|
}
|
|
17364
17463
|
});
|
|
17365
17464
|
|
|
@@ -21688,7 +21787,9 @@ function validate2(parsed, newContent, validIds) {
|
|
|
21688
21787
|
if (typeof parsed !== "object" || parsed === null) return null;
|
|
21689
21788
|
const obj = parsed;
|
|
21690
21789
|
const action = obj.action;
|
|
21691
|
-
if (action !== "create" && action !== "update" && action !== "noop")
|
|
21790
|
+
if (action !== "create" && action !== "update" && action !== "noop" && action !== "supersede") {
|
|
21791
|
+
return null;
|
|
21792
|
+
}
|
|
21692
21793
|
if (action === "create") {
|
|
21693
21794
|
const c2 = typeof obj.content === "string" ? obj.content.trim() : "";
|
|
21694
21795
|
return { action: "create", content: c2.length > 0 ? c2 : newContent };
|
|
@@ -21700,7 +21801,7 @@ function validate2(parsed, newContent, validIds) {
|
|
|
21700
21801
|
}
|
|
21701
21802
|
const c = typeof obj.content === "string" ? obj.content.trim() : "";
|
|
21702
21803
|
if (c.length === 0) return null;
|
|
21703
|
-
return { action
|
|
21804
|
+
return { action, targetId, content: c };
|
|
21704
21805
|
}
|
|
21705
21806
|
var DEFAULT_MODEL2, DEFAULT_CONSOLIDATE_ATTEMPTS, DEFAULT_CONSOLIDATE_TOTAL_TIMEOUT_MS, SYSTEM_PROMPT2;
|
|
21706
21807
|
var init_consolidate = __esm({
|
|
@@ -21716,10 +21817,11 @@ var init_consolidate = __esm({
|
|
|
21716
21817
|
|
|
21717
21818
|
A "memory" is a self-contained natural-language fact about the user. Multiple memories about the same EXACT FACET (the same dimension of the same subject) should never coexist \u2014 they should be merged into one. Different facets on the same subject (e.g. user's dog's name vs user's dog's age) are SEPARATE memories.
|
|
21718
21819
|
|
|
21719
|
-
Decide one of
|
|
21820
|
+
Decide one of four actions:
|
|
21720
21821
|
|
|
21721
21822
|
- "create": the new memory describes a distinct fact not covered by any existing memory. Write it as new.
|
|
21722
|
-
- "update": the new memory describes the SAME FACET as exactly one existing memory
|
|
21823
|
+
- "update": the new memory describes the SAME FACET as exactly one existing memory and is COMPATIBLE with it \u2014 it adds detail, fixes an incomplete value, or rephrases the same still-true fact. Return targetId of that existing memory + the consolidated content (richest version of the two).
|
|
21824
|
+
- "supersede": the new memory REPLACES a standing fact whose value has CHANGED and is now INCOMPATIBLE with an existing memory \u2014 the old fact was true before but is false now (a state change). Return targetId of the STALE existing memory to retire + content = the NEW fact. The old memory is kept as history, not overwritten or deleted; do not re-state it.
|
|
21723
21825
|
- "noop": the new memory is already fully captured by an existing memory \u2014 same facet, no new information. Skip the write.
|
|
21724
21826
|
|
|
21725
21827
|
RULES (carry these strictly):
|
|
@@ -21727,18 +21829,21 @@ RULES (carry these strictly):
|
|
|
21727
21829
|
1. ONE OBSERVATION PER DISTINCT FACET. If the new memory is about "user's aunt's twins" and an existing memory is also about "user's aunt's twins", they are the same facet \u2192 update, never create.
|
|
21728
21830
|
2. MATCH BY FACET, NOT TOPIC. Two memories both mentioning "Zara" is not enough to merge \u2014 only merge if they describe the same property (e.g. both about "user's pending Zara boot exchange"). Two memories about Zara on different topics (e.g. "user shops at Zara" + "user returned a sweater to Zara last week") are separate facets.
|
|
21729
21831
|
3. NO COMPUTATION. Do not sum counts, decrement quantities, or derive new facts from existing ones. If the new memory says "user spent $200 today" and an existing memory says "user spent $150 yesterday", these are TWO SEPARATE EVENTS \u2014 create.
|
|
21730
|
-
4.
|
|
21731
|
-
|
|
21832
|
+
4. EVENTS vs STANDING STATE.
|
|
21833
|
+
- Distinct EVENTS (episodic \u2014 something that happened on a date) are separate memories, even if the same activity: "user went to gym Monday" vs "user went to gym Friday" \u2192 create; keep both.
|
|
21834
|
+
- A STANDING ATTRIBUTE (an ongoing state: where the user lives/works, relationship status, current role) has ONE current value. When the new memory changes that value ("Lives in Portland" \u2192 "Lives in San Francisco"; "Works at Google" \u2192 "Works at Riverbend"; "Engaged" \u2192 "Broke up"), the old value is no longer true \u2192 supersede (retire the old, record the new). Do NOT create (that leaves a stale contradiction) and do NOT update (that erases the history that the old value was once true).
|
|
21835
|
+
5. When in doubt between create and update, choose create \u2014 EXCEPT when the new memory directly contradicts the current value of a standing attribute in an existing memory; then choose supersede. Over-merging loses information; a live contradiction is worse than either.
|
|
21732
21836
|
|
|
21733
21837
|
OUTPUT \u2014 strict JSON, no prose:
|
|
21734
21838
|
{
|
|
21735
|
-
"action": "create" | "update" | "noop",
|
|
21736
|
-
"targetId": "<existing memory id
|
|
21737
|
-
"content": "<
|
|
21839
|
+
"action": "create" | "update" | "supersede" | "noop",
|
|
21840
|
+
"targetId": "<existing memory id \u2014 required for update/supersede/noop, omit for create>",
|
|
21841
|
+
"content": "<content \u2014 required for create/update/supersede, omit for noop>"
|
|
21738
21842
|
}
|
|
21739
21843
|
|
|
21740
21844
|
For "create": content is the new memory verbatim (or a slight refinement).
|
|
21741
21845
|
For "update": content is the merged richest-version, \u226480 words.
|
|
21846
|
+
For "supersede": content is the NEW fact only (\u226480 words); targetId is the stale memory being retired.
|
|
21742
21847
|
For "noop": no content (existing memory is already correct).`;
|
|
21743
21848
|
}
|
|
21744
21849
|
});
|
|
@@ -21789,6 +21894,7 @@ __export(index_exports, {
|
|
|
21789
21894
|
STREAM_RESUMABLE_HEADER: () => STREAM_RESUMABLE_HEADER,
|
|
21790
21895
|
StreamExpiredError: () => StreamExpiredError,
|
|
21791
21896
|
TOOL_CATALOG: () => TOOL_CATALOG,
|
|
21897
|
+
TOPICS_EXTRACTION_VERSION: () => TOPICS_EXTRACTION_VERSION,
|
|
21792
21898
|
TOPIC_EXTRACTION_BATCH_SIZE: () => TOPIC_EXTRACTION_BATCH_SIZE,
|
|
21793
21899
|
TextProcessor: () => TextProcessor,
|
|
21794
21900
|
UserPreference: () => UserPreference,
|
|
@@ -21975,6 +22081,7 @@ __export(index_exports, {
|
|
|
21975
22081
|
streamCancelPath: () => streamCancelPath,
|
|
21976
22082
|
streamReplayPath: () => streamReplayPath,
|
|
21977
22083
|
summaryToSystemMessage: () => summaryToSystemMessage,
|
|
22084
|
+
supersedeVaultMemoryOp: () => supersedeVaultMemoryOp,
|
|
21978
22085
|
toolSetSystemPrompts: () => toolSetSystemPrompts,
|
|
21979
22086
|
updateConversationProjectOp: () => updateConversationProjectOp,
|
|
21980
22087
|
updateConversationTitleOp: () => updateConversationTitleOp,
|
|
@@ -22329,6 +22436,15 @@ __decorateClass([
|
|
|
22329
22436
|
__decorateClass([
|
|
22330
22437
|
(0, import_decorators6.field)("topics_extracted_at")
|
|
22331
22438
|
], VaultMemory.prototype, "topicsExtractedAt", 2);
|
|
22439
|
+
__decorateClass([
|
|
22440
|
+
(0, import_decorators6.field)("superseded_by")
|
|
22441
|
+
], VaultMemory.prototype, "supersededBy", 2);
|
|
22442
|
+
__decorateClass([
|
|
22443
|
+
(0, import_decorators6.field)("superseded_at")
|
|
22444
|
+
], VaultMemory.prototype, "supersededAt", 2);
|
|
22445
|
+
__decorateClass([
|
|
22446
|
+
(0, import_decorators6.field)("topics_extracted_version")
|
|
22447
|
+
], VaultMemory.prototype, "topicsExtractedVersion", 2);
|
|
22332
22448
|
__decorateClass([
|
|
22333
22449
|
import_decorators6.readonly,
|
|
22334
22450
|
(0, import_decorators6.date)("created_at")
|
|
@@ -22476,7 +22592,7 @@ __decorateClass([
|
|
|
22476
22592
|
], VaultFolder.prototype, "context", 2);
|
|
22477
22593
|
|
|
22478
22594
|
// src/lib/db/schema.ts
|
|
22479
|
-
var SDK_SCHEMA_VERSION =
|
|
22595
|
+
var SDK_SCHEMA_VERSION = 38;
|
|
22480
22596
|
var sdkSchema = (0, import_watermelondb12.appSchema)({
|
|
22481
22597
|
version: SDK_SCHEMA_VERSION,
|
|
22482
22598
|
tables: [
|
|
@@ -22601,7 +22717,20 @@ var sdkSchema = (0, import_watermelondb12.appSchema)({
|
|
|
22601
22717
|
// Unix ms of the last LLM topic-extraction pass over this memory's
|
|
22602
22718
|
// content. Null = never extracted standalone (legacy rows with entity
|
|
22603
22719
|
// links are grandfathered — see getMemoriesNeedingTopicExtractionOp).
|
|
22604
|
-
{ name: "topics_extracted_at", type: "number", isOptional: true }
|
|
22720
|
+
{ name: "topics_extracted_at", type: "number", isOptional: true },
|
|
22721
|
+
// Write-time supersession (A2). When set, this fact was replaced by a
|
|
22722
|
+
// newer, incompatible-value fact (e.g. "Lives in Portland" superseded by
|
|
22723
|
+
// "Lives in SF"); `superseded_by` points at the newer memory's id and
|
|
22724
|
+
// `superseded_at` is the Unix ms it happened. Superseded rows stay in
|
|
22725
|
+
// the table (history / read-time fallback) but are excluded from recall
|
|
22726
|
+
// and dedup by default. Null = live (not superseded). Indexed so the
|
|
22727
|
+
// recall filter stays cheap.
|
|
22728
|
+
{ name: "superseded_by", type: "string", isOptional: true, isIndexed: true },
|
|
22729
|
+
{ name: "superseded_at", type: "number", isOptional: true },
|
|
22730
|
+
// The extraction-logic version this memory was last stamped under. Null
|
|
22731
|
+
// (pre-v38) is treated as version 0, so a bump of TOPICS_EXTRACTION_VERSION
|
|
22732
|
+
// re-extracts stale rows. See getMemoriesNeedingTopicExtractionOp.
|
|
22733
|
+
{ name: "topics_extracted_version", type: "number", isOptional: true }
|
|
22605
22734
|
]
|
|
22606
22735
|
}),
|
|
22607
22736
|
// Entity table — canonical names extracted from auto-extraction (W5).
|
|
@@ -23212,6 +23341,34 @@ var sdkMigrations = (0, import_migrations.schemaMigrations)({
|
|
|
23212
23341
|
columns: [{ name: "topics_extracted_at", type: "number", isOptional: true }]
|
|
23213
23342
|
})
|
|
23214
23343
|
]
|
|
23344
|
+
},
|
|
23345
|
+
// v36 -> v37: write-time supersession columns on memory_vault. Existing rows
|
|
23346
|
+
// keep both NULL (= live / not superseded), so no backfill — legacy
|
|
23347
|
+
// contradictory rows are handled by the read-time supersession fallback.
|
|
23348
|
+
{
|
|
23349
|
+
toVersion: 37,
|
|
23350
|
+
steps: [
|
|
23351
|
+
(0, import_migrations.addColumns)({
|
|
23352
|
+
table: "memory_vault",
|
|
23353
|
+
columns: [
|
|
23354
|
+
{ name: "superseded_by", type: "string", isOptional: true, isIndexed: true },
|
|
23355
|
+
{ name: "superseded_at", type: "number", isOptional: true }
|
|
23356
|
+
]
|
|
23357
|
+
})
|
|
23358
|
+
]
|
|
23359
|
+
},
|
|
23360
|
+
// v37 -> v38: topics_extracted_version on memory_vault. Existing rows keep it
|
|
23361
|
+
// NULL, read as version 0 by getMemoriesNeedingTopicExtractionOp — so the
|
|
23362
|
+
// first sweep after a TOPICS_EXTRACTION_VERSION bump re-extracts them (drained
|
|
23363
|
+
// across sweeps by the worker's limit). See topicExtract.ts.
|
|
23364
|
+
{
|
|
23365
|
+
toVersion: 38,
|
|
23366
|
+
steps: [
|
|
23367
|
+
(0, import_migrations.addColumns)({
|
|
23368
|
+
table: "memory_vault",
|
|
23369
|
+
columns: [{ name: "topics_extracted_version", type: "number", isOptional: true }]
|
|
23370
|
+
})
|
|
23371
|
+
]
|
|
23215
23372
|
}
|
|
23216
23373
|
]
|
|
23217
23374
|
});
|
|
@@ -25950,53 +26107,62 @@ async function retain(content, ctx, options = {}) {
|
|
|
25950
26107
|
const enableAutoMerge = options.enableAutoMerge ?? true;
|
|
25951
26108
|
const threshold = options.autoMergeThreshold ?? DEFAULT_AUTO_MERGE_THRESHOLD;
|
|
25952
26109
|
const resolvedScope = options.scope ?? DEFAULT_SCOPE;
|
|
26110
|
+
let supersedeTargetId;
|
|
26111
|
+
let supersedeContent;
|
|
25953
26112
|
if (enableAutoMerge) {
|
|
25954
26113
|
if (options.consolidateOptions) {
|
|
25955
|
-
const
|
|
25956
|
-
if (
|
|
25957
|
-
|
|
25958
|
-
|
|
25959
|
-
|
|
25960
|
-
|
|
25961
|
-
|
|
25962
|
-
|
|
25963
|
-
|
|
25964
|
-
|
|
25965
|
-
|
|
25966
|
-
|
|
25967
|
-
|
|
25968
|
-
|
|
25969
|
-
|
|
25970
|
-
|
|
25971
|
-
|
|
25972
|
-
|
|
25973
|
-
|
|
25974
|
-
|
|
25975
|
-
|
|
25976
|
-
|
|
25977
|
-
|
|
25978
|
-
);
|
|
25979
|
-
|
|
25980
|
-
|
|
25981
|
-
|
|
25982
|
-
|
|
25983
|
-
|
|
25984
|
-
|
|
25985
|
-
|
|
25986
|
-
|
|
25987
|
-
|
|
25988
|
-
|
|
25989
|
-
|
|
25990
|
-
|
|
25991
|
-
|
|
25992
|
-
|
|
25993
|
-
|
|
26114
|
+
const outcome = await tryConsolidate(trimmed, ctx, options);
|
|
26115
|
+
if (outcome) {
|
|
26116
|
+
if ("done" in outcome) return outcome.done;
|
|
26117
|
+
supersedeTargetId = outcome.supersede;
|
|
26118
|
+
supersedeContent = outcome.content;
|
|
26119
|
+
}
|
|
26120
|
+
}
|
|
26121
|
+
if (!supersedeTargetId) {
|
|
26122
|
+
const matches = await searchVaultMemories(
|
|
26123
|
+
trimmed,
|
|
26124
|
+
ctx.vaultCtx,
|
|
26125
|
+
ctx.embeddingOptions,
|
|
26126
|
+
ctx.vaultCache,
|
|
26127
|
+
{
|
|
26128
|
+
limit: 1,
|
|
26129
|
+
minSimilarity: threshold,
|
|
26130
|
+
useFusion: false,
|
|
26131
|
+
scopes: [resolvedScope],
|
|
26132
|
+
...options.folderId !== void 0 && { folderId: options.folderId }
|
|
26133
|
+
}
|
|
26134
|
+
);
|
|
26135
|
+
if (matches.length > 0) {
|
|
26136
|
+
const targetId = matches[0].uniqueId;
|
|
26137
|
+
const existing = await getVaultMemoryOp(ctx.vaultCtx, targetId);
|
|
26138
|
+
if (existing && !existing.supersededBy) {
|
|
26139
|
+
const mergedSourceIds = unionStrings(
|
|
26140
|
+
existing.sourceChunkIds ?? [],
|
|
26141
|
+
options.sourceChunkIds ?? []
|
|
26142
|
+
);
|
|
26143
|
+
const eventTimeUpdate = pickEventTimeUpdate(existing, options.eventTime);
|
|
26144
|
+
const updated = await updateVaultMemoryOp(ctx.vaultCtx, targetId, {
|
|
26145
|
+
content: existing.content,
|
|
26146
|
+
proofCountIncrement: 1,
|
|
26147
|
+
sourceChunkIds: mergedSourceIds,
|
|
26148
|
+
preserveUpdatedAt: true,
|
|
26149
|
+
...eventTimeUpdate && { eventTime: eventTimeUpdate }
|
|
26150
|
+
});
|
|
26151
|
+
if (updated) {
|
|
26152
|
+
return {
|
|
26153
|
+
action: "merge",
|
|
26154
|
+
memoryId: targetId,
|
|
26155
|
+
targetId,
|
|
26156
|
+
proofCount: updated.proofCount ?? (existing.proofCount ?? 1) + 1
|
|
26157
|
+
};
|
|
26158
|
+
}
|
|
26159
|
+
await assertMergeTargetGoneOrThrow(ctx, targetId);
|
|
25994
26160
|
}
|
|
25995
|
-
await assertMergeTargetGoneOrThrow(ctx, targetId);
|
|
25996
26161
|
}
|
|
25997
26162
|
}
|
|
25998
26163
|
}
|
|
25999
|
-
const
|
|
26164
|
+
const contentToWrite = supersedeContent ?? trimmed;
|
|
26165
|
+
const embedding = await generateEmbedding(contentToWrite, ctx.embeddingOptions);
|
|
26000
26166
|
const embeddingModel = ctx.embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
26001
26167
|
if (options.respectTombstones) {
|
|
26002
26168
|
const tombstoneId = await findTombstoneMatch(embedding, embeddingModel, resolvedScope, ctx, {
|
|
@@ -26007,8 +26173,8 @@ async function retain(content, ctx, options = {}) {
|
|
|
26007
26173
|
return { action: "suppressed", memoryId: tombstoneId, tombstoneId, proofCount: 0 };
|
|
26008
26174
|
}
|
|
26009
26175
|
}
|
|
26010
|
-
const
|
|
26011
|
-
content:
|
|
26176
|
+
const createOpts = {
|
|
26177
|
+
content: contentToWrite,
|
|
26012
26178
|
scope: resolvedScope,
|
|
26013
26179
|
...options.folderId !== void 0 && { folderId: options.folderId },
|
|
26014
26180
|
embedding: JSON.stringify(embedding),
|
|
@@ -26025,7 +26191,24 @@ async function retain(content, ctx, options = {}) {
|
|
|
26025
26191
|
kind: options.eventTime.kind
|
|
26026
26192
|
}
|
|
26027
26193
|
}
|
|
26028
|
-
}
|
|
26194
|
+
};
|
|
26195
|
+
if (supersedeTargetId) {
|
|
26196
|
+
const { created: created2, retired } = await createSupersedingMemoryOp(
|
|
26197
|
+
ctx.vaultCtx,
|
|
26198
|
+
createOpts,
|
|
26199
|
+
supersedeTargetId
|
|
26200
|
+
);
|
|
26201
|
+
if (created2 && retired) {
|
|
26202
|
+
ctx.vaultCache.set(created2.uniqueId, Float32Array.from(embedding));
|
|
26203
|
+
return {
|
|
26204
|
+
action: "supersede",
|
|
26205
|
+
memoryId: created2.uniqueId,
|
|
26206
|
+
targetId: supersedeTargetId,
|
|
26207
|
+
proofCount: 1
|
|
26208
|
+
};
|
|
26209
|
+
}
|
|
26210
|
+
}
|
|
26211
|
+
const created = await createVaultMemoryOp(ctx.vaultCtx, createOpts);
|
|
26029
26212
|
ctx.vaultCache.set(created.uniqueId, Float32Array.from(embedding));
|
|
26030
26213
|
return {
|
|
26031
26214
|
action: "create",
|
|
@@ -26095,9 +26278,14 @@ async function tryConsolidate(trimmed, ctx, options) {
|
|
|
26095
26278
|
const { consolidateMemory: doConsolidate } = await Promise.resolve().then(() => (init_consolidate(), consolidate_exports));
|
|
26096
26279
|
const decision = await doConsolidate(trimmed, candidates, consolidateOptions);
|
|
26097
26280
|
if (decision.action === "create") return null;
|
|
26281
|
+
if (decision.action === "supersede" && decision.targetId && decision.content) {
|
|
26282
|
+
const existing = await getVaultMemoryOp(ctx.vaultCtx, decision.targetId);
|
|
26283
|
+
if (!existing || existing.supersededBy) return null;
|
|
26284
|
+
return { supersede: decision.targetId, content: decision.content };
|
|
26285
|
+
}
|
|
26098
26286
|
if (decision.action === "noop" && decision.targetId) {
|
|
26099
26287
|
const existing = await getVaultMemoryOp(ctx.vaultCtx, decision.targetId);
|
|
26100
|
-
if (!existing) return null;
|
|
26288
|
+
if (!existing || existing.supersededBy) return null;
|
|
26101
26289
|
const mergedSourceIds = unionStrings(
|
|
26102
26290
|
existing.sourceChunkIds ?? [],
|
|
26103
26291
|
options.sourceChunkIds ?? []
|
|
@@ -26115,15 +26303,17 @@ async function tryConsolidate(trimmed, ctx, options) {
|
|
|
26115
26303
|
return null;
|
|
26116
26304
|
}
|
|
26117
26305
|
return {
|
|
26118
|
-
|
|
26119
|
-
|
|
26120
|
-
|
|
26121
|
-
|
|
26306
|
+
done: {
|
|
26307
|
+
action: "merge",
|
|
26308
|
+
memoryId: decision.targetId,
|
|
26309
|
+
targetId: decision.targetId,
|
|
26310
|
+
proofCount: updated.proofCount ?? (existing.proofCount ?? 1) + 1
|
|
26311
|
+
}
|
|
26122
26312
|
};
|
|
26123
26313
|
}
|
|
26124
26314
|
if (decision.action === "update" && decision.targetId && decision.content) {
|
|
26125
26315
|
const existing = await getVaultMemoryOp(ctx.vaultCtx, decision.targetId);
|
|
26126
|
-
if (!existing) return null;
|
|
26316
|
+
if (!existing || existing.supersededBy) return null;
|
|
26127
26317
|
const mergedSourceIds = unionStrings(
|
|
26128
26318
|
existing.sourceChunkIds ?? [],
|
|
26129
26319
|
options.sourceChunkIds ?? []
|
|
@@ -26150,10 +26340,12 @@ async function tryConsolidate(trimmed, ctx, options) {
|
|
|
26150
26340
|
}
|
|
26151
26341
|
ctx.vaultCache.set(decision.targetId, Float32Array.from(newEmbedding));
|
|
26152
26342
|
return {
|
|
26153
|
-
|
|
26154
|
-
|
|
26155
|
-
|
|
26156
|
-
|
|
26343
|
+
done: {
|
|
26344
|
+
action: "update",
|
|
26345
|
+
memoryId: decision.targetId,
|
|
26346
|
+
targetId: decision.targetId,
|
|
26347
|
+
proofCount: updated.proofCount ?? (existing.proofCount ?? 1) + 1
|
|
26348
|
+
}
|
|
26157
26349
|
};
|
|
26158
26350
|
}
|
|
26159
26351
|
return null;
|
|
@@ -32702,6 +32894,7 @@ function buildSystemPrompt(ctx, options) {
|
|
|
32702
32894
|
STREAM_RESUMABLE_HEADER,
|
|
32703
32895
|
StreamExpiredError,
|
|
32704
32896
|
TOOL_CATALOG,
|
|
32897
|
+
TOPICS_EXTRACTION_VERSION,
|
|
32705
32898
|
TOPIC_EXTRACTION_BATCH_SIZE,
|
|
32706
32899
|
TextProcessor,
|
|
32707
32900
|
UserPreference,
|
|
@@ -32888,6 +33081,7 @@ function buildSystemPrompt(ctx, options) {
|
|
|
32888
33081
|
streamCancelPath,
|
|
32889
33082
|
streamReplayPath,
|
|
32890
33083
|
summaryToSystemMessage,
|
|
33084
|
+
supersedeVaultMemoryOp,
|
|
32891
33085
|
toolSetSystemPrompts,
|
|
32892
33086
|
updateConversationProjectOp,
|
|
32893
33087
|
updateConversationTitleOp,
|