@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/react/index.cjs
CHANGED
|
@@ -4403,6 +4403,7 @@ function isOwnedByCtxUser(ctx, record) {
|
|
|
4403
4403
|
function baseVaultConditions(ctx, options) {
|
|
4404
4404
|
return [
|
|
4405
4405
|
...options?.includeDeleted ? [] : [import_watermelondb10.Q.where("is_deleted", false)],
|
|
4406
|
+
...options?.includeSuperseded ? [] : [import_watermelondb10.Q.where("superseded_by", null)],
|
|
4406
4407
|
...ctx.userId !== void 0 ? [import_watermelondb10.Q.where("user_id", ctx.userId)] : [],
|
|
4407
4408
|
...options?.since ? [import_watermelondb10.Q.where("updated_at", import_watermelondb10.Q.gt(options.since.getTime()))] : []
|
|
4408
4409
|
];
|
|
@@ -4443,6 +4444,9 @@ function vaultMemoryToStoredRaw(memory) {
|
|
|
4443
4444
|
eventTimeKind: memory.eventTimeKind ?? null,
|
|
4444
4445
|
topicsUserManaged: memory.topicsUserManaged ?? false,
|
|
4445
4446
|
topicsExtractedAt: memory.topicsExtractedAt ?? null,
|
|
4447
|
+
topicsExtractedVersion: memory.topicsExtractedVersion ?? null,
|
|
4448
|
+
supersededBy: memory.supersededBy ?? null,
|
|
4449
|
+
supersededAt: memory.supersededAt ?? null,
|
|
4446
4450
|
createdAt: memory.createdAt,
|
|
4447
4451
|
updatedAt: memory.updatedAt,
|
|
4448
4452
|
isDeleted: memory.isDeleted
|
|
@@ -4488,6 +4492,59 @@ async function createVaultMemoryOp(ctx, opts) {
|
|
|
4488
4492
|
});
|
|
4489
4493
|
return vaultMemoryToStored(created, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
4490
4494
|
}
|
|
4495
|
+
async function createSupersedingMemoryOp(ctx, opts, targetId) {
|
|
4496
|
+
if (!targetId) return { created: null, retired: false };
|
|
4497
|
+
const scope = opts.scope ?? "private";
|
|
4498
|
+
const encryptedContent = ctx.walletAddress && ctx.signMessage ? await encryptVaultMemoryContent(
|
|
4499
|
+
opts.content,
|
|
4500
|
+
ctx.walletAddress,
|
|
4501
|
+
ctx.signMessage,
|
|
4502
|
+
ctx.embeddedWalletSigner
|
|
4503
|
+
) : opts.content;
|
|
4504
|
+
let createdRecord = null;
|
|
4505
|
+
await ctx.database.write(async () => {
|
|
4506
|
+
let target;
|
|
4507
|
+
try {
|
|
4508
|
+
target = await ctx.vaultMemoryCollection.find(targetId);
|
|
4509
|
+
} catch {
|
|
4510
|
+
return;
|
|
4511
|
+
}
|
|
4512
|
+
if (target.isDeleted || target.supersededBy || !isOwnedByCtxUser(ctx, target)) return;
|
|
4513
|
+
createdRecord = await ctx.vaultMemoryCollection.create((record) => {
|
|
4514
|
+
record._setRaw("content", encryptedContent);
|
|
4515
|
+
record._setRaw("scope", scope);
|
|
4516
|
+
record._setRaw("folder_id", opts.folderId ?? null);
|
|
4517
|
+
record._setRaw("user_id", ctx.userId ?? null);
|
|
4518
|
+
record._setRaw("is_deleted", false);
|
|
4519
|
+
if (opts.embedding !== void 0) {
|
|
4520
|
+
record._setRaw("embedding", opts.embedding);
|
|
4521
|
+
record._setRaw("embedding_model", opts.embeddingModel ?? null);
|
|
4522
|
+
}
|
|
4523
|
+
if (opts.sourceChunkIds !== void 0) {
|
|
4524
|
+
record._setRaw("source_chunk_ids", JSON.stringify(opts.sourceChunkIds));
|
|
4525
|
+
}
|
|
4526
|
+
record._setRaw("proof_count", opts.proofCount ?? 1);
|
|
4527
|
+
record._setRaw("source", opts.source ?? "manual");
|
|
4528
|
+
if (opts.eventTime) {
|
|
4529
|
+
record._setRaw("event_time_start", opts.eventTime.start ?? null);
|
|
4530
|
+
record._setRaw("event_time_end", opts.eventTime.end ?? null);
|
|
4531
|
+
record._setRaw("event_time_kind", opts.eventTime.kind ?? null);
|
|
4532
|
+
}
|
|
4533
|
+
});
|
|
4534
|
+
await target.update((r) => {
|
|
4535
|
+
r._setRaw("superseded_by", createdRecord.id);
|
|
4536
|
+
r._setRaw("superseded_at", Date.now());
|
|
4537
|
+
});
|
|
4538
|
+
});
|
|
4539
|
+
if (!createdRecord) return { created: null, retired: false };
|
|
4540
|
+
const created = await vaultMemoryToStored(
|
|
4541
|
+
createdRecord,
|
|
4542
|
+
ctx.walletAddress,
|
|
4543
|
+
ctx.signMessage,
|
|
4544
|
+
ctx.embeddedWalletSigner
|
|
4545
|
+
);
|
|
4546
|
+
return { created, retired: true };
|
|
4547
|
+
}
|
|
4491
4548
|
async function getMemoriesByEventTimeOp(ctx, windowStart, windowEnd) {
|
|
4492
4549
|
const records = await ctx.vaultMemoryCollection.query(
|
|
4493
4550
|
...baseVaultConditions(ctx),
|
|
@@ -4627,6 +4684,9 @@ function vaultMemoryRawToStoredRaw(raw) {
|
|
|
4627
4684
|
// SQLite stores booleans as 0/1, LokiJS as true/false — coerce both.
|
|
4628
4685
|
topicsUserManaged: raw.topics_user_managed === true || raw.topics_user_managed === 1,
|
|
4629
4686
|
topicsExtractedAt: raw.topics_extracted_at ?? null,
|
|
4687
|
+
topicsExtractedVersion: raw.topics_extracted_version ?? null,
|
|
4688
|
+
supersededBy: raw.superseded_by ?? null,
|
|
4689
|
+
supersededAt: raw.superseded_at ?? null,
|
|
4630
4690
|
createdAt: new Date(raw.created_at),
|
|
4631
4691
|
updatedAt: new Date(raw.updated_at),
|
|
4632
4692
|
isDeleted: raw.is_deleted === true || raw.is_deleted === 1
|
|
@@ -4668,7 +4728,7 @@ async function getAllVaultMemoryContentsOp(ctx, options) {
|
|
|
4668
4728
|
async function updateVaultMemoryOp(ctx, id, opts) {
|
|
4669
4729
|
try {
|
|
4670
4730
|
const probe = await ctx.vaultMemoryCollection.find(id);
|
|
4671
|
-
if (probe.isDeleted || !isOwnedByCtxUser(ctx, probe)) return null;
|
|
4731
|
+
if (probe.isDeleted || probe.supersededBy || !isOwnedByCtxUser(ctx, probe)) return null;
|
|
4672
4732
|
const encryptedContent = ctx.walletAddress && ctx.signMessage ? await encryptVaultMemoryContent(
|
|
4673
4733
|
opts.content,
|
|
4674
4734
|
ctx.walletAddress,
|
|
@@ -4679,7 +4739,7 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
4679
4739
|
const record = probe;
|
|
4680
4740
|
const originalUpdatedAt = record.updatedAt.getTime();
|
|
4681
4741
|
await ctx.database.write(async () => {
|
|
4682
|
-
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) {
|
|
4742
|
+
if (record.isDeleted || record.supersededBy || !isOwnedByCtxUser(ctx, record)) {
|
|
4683
4743
|
stale = true;
|
|
4684
4744
|
return;
|
|
4685
4745
|
}
|
|
@@ -4779,7 +4839,10 @@ async function clearMemoryTopicsOverrideOp(ctx, memoryId) {
|
|
|
4779
4839
|
await ctx.database.write(async () => {
|
|
4780
4840
|
await record.update((r) => {
|
|
4781
4841
|
r._setRaw("topics_user_managed", false);
|
|
4782
|
-
r._setRaw("
|
|
4842
|
+
r._setRaw("topics_extracted_version", null);
|
|
4843
|
+
if (record.topicsExtractedAt === null) {
|
|
4844
|
+
r._setRaw("topics_extracted_at", originalUpdatedAt);
|
|
4845
|
+
}
|
|
4783
4846
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
4784
4847
|
});
|
|
4785
4848
|
});
|
|
@@ -4811,6 +4874,40 @@ async function deleteVaultMemoryOp(ctx, id) {
|
|
|
4811
4874
|
return false;
|
|
4812
4875
|
}
|
|
4813
4876
|
}
|
|
4877
|
+
async function supersedeVaultMemoryOp(ctx, id, supersededById) {
|
|
4878
|
+
if (id === supersededById) return false;
|
|
4879
|
+
try {
|
|
4880
|
+
const record = await ctx.vaultMemoryCollection.find(id);
|
|
4881
|
+
if (record.isDeleted || record.supersededBy || !isOwnedByCtxUser(ctx, record)) return false;
|
|
4882
|
+
let successor;
|
|
4883
|
+
try {
|
|
4884
|
+
successor = await ctx.vaultMemoryCollection.find(supersededById);
|
|
4885
|
+
} catch {
|
|
4886
|
+
return false;
|
|
4887
|
+
}
|
|
4888
|
+
if (successor.isDeleted || successor.supersededBy || !isOwnedByCtxUser(ctx, successor)) {
|
|
4889
|
+
return false;
|
|
4890
|
+
}
|
|
4891
|
+
let stale = false;
|
|
4892
|
+
await ctx.database.write(async () => {
|
|
4893
|
+
if (record.isDeleted || record.supersededBy || !isOwnedByCtxUser(ctx, record)) {
|
|
4894
|
+
stale = true;
|
|
4895
|
+
return;
|
|
4896
|
+
}
|
|
4897
|
+
if (successor.isDeleted || successor.supersededBy || !isOwnedByCtxUser(ctx, successor)) {
|
|
4898
|
+
stale = true;
|
|
4899
|
+
return;
|
|
4900
|
+
}
|
|
4901
|
+
await record.update((r) => {
|
|
4902
|
+
r._setRaw("superseded_by", supersededById);
|
|
4903
|
+
r._setRaw("superseded_at", Date.now());
|
|
4904
|
+
});
|
|
4905
|
+
});
|
|
4906
|
+
return !stale;
|
|
4907
|
+
} catch {
|
|
4908
|
+
return false;
|
|
4909
|
+
}
|
|
4910
|
+
}
|
|
4814
4911
|
async function getUnfiledVaultMemoriesOp(ctx) {
|
|
4815
4912
|
const conditions = [
|
|
4816
4913
|
import_watermelondb10.Q.where("folder_id", null),
|
|
@@ -4841,7 +4938,10 @@ async function getMemoriesNeedingTopicExtractionOp(ctx, options) {
|
|
|
4841
4938
|
for (const raw of rows) {
|
|
4842
4939
|
const stamp = raw.topics_extracted_at ?? null;
|
|
4843
4940
|
if (stamp !== null) {
|
|
4844
|
-
|
|
4941
|
+
const version = raw.topics_extracted_version ?? 0;
|
|
4942
|
+
if (raw.updated_at > stamp || version < TOPICS_EXTRACTION_VERSION) {
|
|
4943
|
+
stampedPending.push(raw);
|
|
4944
|
+
}
|
|
4845
4945
|
} else {
|
|
4846
4946
|
unstamped.push(raw);
|
|
4847
4947
|
}
|
|
@@ -4871,7 +4971,7 @@ async function getMemoriesNeedingTopicExtractionOp(ctx, options) {
|
|
|
4871
4971
|
);
|
|
4872
4972
|
return { pending, linkedUnstamped };
|
|
4873
4973
|
}
|
|
4874
|
-
async function stampTopicsExtractedAtOp(ctx, memoryIds, extractedAt) {
|
|
4974
|
+
async function stampTopicsExtractedAtOp(ctx, memoryIds, extractedAt, version = TOPICS_EXTRACTION_VERSION) {
|
|
4875
4975
|
if (memoryIds.length === 0) return [];
|
|
4876
4976
|
const uniqueIds = Array.from(new Set(memoryIds));
|
|
4877
4977
|
const CHUNK = 500;
|
|
@@ -4894,6 +4994,7 @@ async function stampTopicsExtractedAtOp(ctx, memoryIds, extractedAt) {
|
|
|
4894
4994
|
prepared.push(
|
|
4895
4995
|
record.prepareUpdate((r) => {
|
|
4896
4996
|
r._setRaw("topics_extracted_at", extractedAt);
|
|
4997
|
+
r._setRaw("topics_extracted_version", version);
|
|
4897
4998
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
4898
4999
|
})
|
|
4899
5000
|
);
|
|
@@ -4946,13 +5047,14 @@ async function updateVaultMemoryEmbeddingOp(ctx, id, embedding, embeddingModel)
|
|
|
4946
5047
|
return false;
|
|
4947
5048
|
}
|
|
4948
5049
|
}
|
|
4949
|
-
var import_watermelondb10;
|
|
5050
|
+
var import_watermelondb10, TOPICS_EXTRACTION_VERSION;
|
|
4950
5051
|
var init_operations3 = __esm({
|
|
4951
5052
|
"src/lib/db/memoryVault/operations.ts"() {
|
|
4952
5053
|
"use strict";
|
|
4953
5054
|
import_watermelondb10 = require("@nozbe/watermelondb");
|
|
4954
5055
|
init_operations2();
|
|
4955
5056
|
init_encryption2();
|
|
5057
|
+
TOPICS_EXTRACTION_VERSION = 1;
|
|
4956
5058
|
}
|
|
4957
5059
|
});
|
|
4958
5060
|
|
|
@@ -7228,7 +7330,9 @@ function validate2(parsed, newContent, validIds) {
|
|
|
7228
7330
|
if (typeof parsed !== "object" || parsed === null) return null;
|
|
7229
7331
|
const obj = parsed;
|
|
7230
7332
|
const action = obj.action;
|
|
7231
|
-
if (action !== "create" && action !== "update" && action !== "noop")
|
|
7333
|
+
if (action !== "create" && action !== "update" && action !== "noop" && action !== "supersede") {
|
|
7334
|
+
return null;
|
|
7335
|
+
}
|
|
7232
7336
|
if (action === "create") {
|
|
7233
7337
|
const c2 = typeof obj.content === "string" ? obj.content.trim() : "";
|
|
7234
7338
|
return { action: "create", content: c2.length > 0 ? c2 : newContent };
|
|
@@ -7240,7 +7344,7 @@ function validate2(parsed, newContent, validIds) {
|
|
|
7240
7344
|
}
|
|
7241
7345
|
const c = typeof obj.content === "string" ? obj.content.trim() : "";
|
|
7242
7346
|
if (c.length === 0) return null;
|
|
7243
|
-
return { action
|
|
7347
|
+
return { action, targetId, content: c };
|
|
7244
7348
|
}
|
|
7245
7349
|
var DEFAULT_MODEL2, DEFAULT_CONSOLIDATE_ATTEMPTS, DEFAULT_CONSOLIDATE_TOTAL_TIMEOUT_MS, SYSTEM_PROMPT2;
|
|
7246
7350
|
var init_consolidate = __esm({
|
|
@@ -7256,10 +7360,11 @@ var init_consolidate = __esm({
|
|
|
7256
7360
|
|
|
7257
7361
|
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.
|
|
7258
7362
|
|
|
7259
|
-
Decide one of
|
|
7363
|
+
Decide one of four actions:
|
|
7260
7364
|
|
|
7261
7365
|
- "create": the new memory describes a distinct fact not covered by any existing memory. Write it as new.
|
|
7262
|
-
- "update": the new memory describes the SAME FACET as exactly one existing memory
|
|
7366
|
+
- "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).
|
|
7367
|
+
- "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.
|
|
7263
7368
|
- "noop": the new memory is already fully captured by an existing memory \u2014 same facet, no new information. Skip the write.
|
|
7264
7369
|
|
|
7265
7370
|
RULES (carry these strictly):
|
|
@@ -7267,18 +7372,21 @@ RULES (carry these strictly):
|
|
|
7267
7372
|
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.
|
|
7268
7373
|
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.
|
|
7269
7374
|
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.
|
|
7270
|
-
4.
|
|
7271
|
-
|
|
7375
|
+
4. EVENTS vs STANDING STATE.
|
|
7376
|
+
- 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.
|
|
7377
|
+
- 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).
|
|
7378
|
+
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.
|
|
7272
7379
|
|
|
7273
7380
|
OUTPUT \u2014 strict JSON, no prose:
|
|
7274
7381
|
{
|
|
7275
|
-
"action": "create" | "update" | "noop",
|
|
7276
|
-
"targetId": "<existing memory id
|
|
7277
|
-
"content": "<
|
|
7382
|
+
"action": "create" | "update" | "supersede" | "noop",
|
|
7383
|
+
"targetId": "<existing memory id \u2014 required for update/supersede/noop, omit for create>",
|
|
7384
|
+
"content": "<content \u2014 required for create/update/supersede, omit for noop>"
|
|
7278
7385
|
}
|
|
7279
7386
|
|
|
7280
7387
|
For "create": content is the new memory verbatim (or a slight refinement).
|
|
7281
7388
|
For "update": content is the merged richest-version, \u226480 words.
|
|
7389
|
+
For "supersede": content is the NEW fact only (\u226480 words); targetId is the stale memory being retired.
|
|
7282
7390
|
For "noop": no content (existing memory is already correct).`;
|
|
7283
7391
|
}
|
|
7284
7392
|
});
|
|
@@ -7357,6 +7465,7 @@ __export(index_exports, {
|
|
|
7357
7465
|
StoredVaultMemoryModel: () => VaultMemory,
|
|
7358
7466
|
StreamExpiredError: () => StreamExpiredError,
|
|
7359
7467
|
THEME_ATTRS: () => THEME_ATTRS,
|
|
7468
|
+
TOPICS_EXTRACTION_VERSION: () => TOPICS_EXTRACTION_VERSION,
|
|
7360
7469
|
TOPIC_EXTRACTION_BATCH_SIZE: () => TOPIC_EXTRACTION_BATCH_SIZE,
|
|
7361
7470
|
TextProcessor: () => TextProcessor,
|
|
7362
7471
|
UIInteractionProvider: () => UIInteractionProvider,
|
|
@@ -7633,6 +7742,7 @@ __export(index_exports, {
|
|
|
7633
7742
|
storeNotionReturnUrl: () => storeNotionReturnUrl,
|
|
7634
7743
|
streamCancelPath: () => streamCancelPath,
|
|
7635
7744
|
streamReplayPath: () => streamReplayPath,
|
|
7745
|
+
supersedeVaultMemoryOp: () => supersedeVaultMemoryOp,
|
|
7636
7746
|
updateAttrs: () => updateAttrs,
|
|
7637
7747
|
updateConversationProjectOp: () => updateConversationProjectOp,
|
|
7638
7748
|
updateMediaMessageIdBatchOp: () => updateMediaMessageIdBatchOp,
|
|
@@ -14234,6 +14344,15 @@ __decorateClass([
|
|
|
14234
14344
|
__decorateClass([
|
|
14235
14345
|
(0, import_decorators3.field)("topics_extracted_at")
|
|
14236
14346
|
], VaultMemory.prototype, "topicsExtractedAt", 2);
|
|
14347
|
+
__decorateClass([
|
|
14348
|
+
(0, import_decorators3.field)("superseded_by")
|
|
14349
|
+
], VaultMemory.prototype, "supersededBy", 2);
|
|
14350
|
+
__decorateClass([
|
|
14351
|
+
(0, import_decorators3.field)("superseded_at")
|
|
14352
|
+
], VaultMemory.prototype, "supersededAt", 2);
|
|
14353
|
+
__decorateClass([
|
|
14354
|
+
(0, import_decorators3.field)("topics_extracted_version")
|
|
14355
|
+
], VaultMemory.prototype, "topicsExtractedVersion", 2);
|
|
14237
14356
|
__decorateClass([
|
|
14238
14357
|
import_decorators3.readonly,
|
|
14239
14358
|
(0, import_decorators3.date)("created_at")
|
|
@@ -14277,53 +14396,62 @@ async function retain(content, ctx, options = {}) {
|
|
|
14277
14396
|
const enableAutoMerge = options.enableAutoMerge ?? true;
|
|
14278
14397
|
const threshold = options.autoMergeThreshold ?? DEFAULT_AUTO_MERGE_THRESHOLD;
|
|
14279
14398
|
const resolvedScope = options.scope ?? DEFAULT_SCOPE;
|
|
14399
|
+
let supersedeTargetId;
|
|
14400
|
+
let supersedeContent;
|
|
14280
14401
|
if (enableAutoMerge) {
|
|
14281
14402
|
if (options.consolidateOptions) {
|
|
14282
|
-
const
|
|
14283
|
-
if (
|
|
14284
|
-
|
|
14285
|
-
|
|
14286
|
-
|
|
14287
|
-
|
|
14288
|
-
|
|
14289
|
-
|
|
14290
|
-
|
|
14291
|
-
|
|
14292
|
-
|
|
14293
|
-
|
|
14294
|
-
|
|
14295
|
-
|
|
14296
|
-
|
|
14297
|
-
|
|
14298
|
-
|
|
14299
|
-
|
|
14300
|
-
|
|
14301
|
-
|
|
14302
|
-
|
|
14303
|
-
|
|
14304
|
-
|
|
14305
|
-
);
|
|
14306
|
-
|
|
14307
|
-
|
|
14308
|
-
|
|
14309
|
-
|
|
14310
|
-
|
|
14311
|
-
|
|
14312
|
-
|
|
14313
|
-
|
|
14314
|
-
|
|
14315
|
-
|
|
14316
|
-
|
|
14317
|
-
|
|
14318
|
-
|
|
14319
|
-
|
|
14320
|
-
|
|
14403
|
+
const outcome = await tryConsolidate(trimmed, ctx, options);
|
|
14404
|
+
if (outcome) {
|
|
14405
|
+
if ("done" in outcome) return outcome.done;
|
|
14406
|
+
supersedeTargetId = outcome.supersede;
|
|
14407
|
+
supersedeContent = outcome.content;
|
|
14408
|
+
}
|
|
14409
|
+
}
|
|
14410
|
+
if (!supersedeTargetId) {
|
|
14411
|
+
const matches = await searchVaultMemories(
|
|
14412
|
+
trimmed,
|
|
14413
|
+
ctx.vaultCtx,
|
|
14414
|
+
ctx.embeddingOptions,
|
|
14415
|
+
ctx.vaultCache,
|
|
14416
|
+
{
|
|
14417
|
+
limit: 1,
|
|
14418
|
+
minSimilarity: threshold,
|
|
14419
|
+
useFusion: false,
|
|
14420
|
+
scopes: [resolvedScope],
|
|
14421
|
+
...options.folderId !== void 0 && { folderId: options.folderId }
|
|
14422
|
+
}
|
|
14423
|
+
);
|
|
14424
|
+
if (matches.length > 0) {
|
|
14425
|
+
const targetId = matches[0].uniqueId;
|
|
14426
|
+
const existing = await getVaultMemoryOp(ctx.vaultCtx, targetId);
|
|
14427
|
+
if (existing && !existing.supersededBy) {
|
|
14428
|
+
const mergedSourceIds = unionStrings(
|
|
14429
|
+
existing.sourceChunkIds ?? [],
|
|
14430
|
+
options.sourceChunkIds ?? []
|
|
14431
|
+
);
|
|
14432
|
+
const eventTimeUpdate = pickEventTimeUpdate(existing, options.eventTime);
|
|
14433
|
+
const updated = await updateVaultMemoryOp(ctx.vaultCtx, targetId, {
|
|
14434
|
+
content: existing.content,
|
|
14435
|
+
proofCountIncrement: 1,
|
|
14436
|
+
sourceChunkIds: mergedSourceIds,
|
|
14437
|
+
preserveUpdatedAt: true,
|
|
14438
|
+
...eventTimeUpdate && { eventTime: eventTimeUpdate }
|
|
14439
|
+
});
|
|
14440
|
+
if (updated) {
|
|
14441
|
+
return {
|
|
14442
|
+
action: "merge",
|
|
14443
|
+
memoryId: targetId,
|
|
14444
|
+
targetId,
|
|
14445
|
+
proofCount: updated.proofCount ?? (existing.proofCount ?? 1) + 1
|
|
14446
|
+
};
|
|
14447
|
+
}
|
|
14448
|
+
await assertMergeTargetGoneOrThrow(ctx, targetId);
|
|
14321
14449
|
}
|
|
14322
|
-
await assertMergeTargetGoneOrThrow(ctx, targetId);
|
|
14323
14450
|
}
|
|
14324
14451
|
}
|
|
14325
14452
|
}
|
|
14326
|
-
const
|
|
14453
|
+
const contentToWrite = supersedeContent ?? trimmed;
|
|
14454
|
+
const embedding = await generateEmbedding(contentToWrite, ctx.embeddingOptions);
|
|
14327
14455
|
const embeddingModel = ctx.embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
14328
14456
|
if (options.respectTombstones) {
|
|
14329
14457
|
const tombstoneId = await findTombstoneMatch(embedding, embeddingModel, resolvedScope, ctx, {
|
|
@@ -14334,8 +14462,8 @@ async function retain(content, ctx, options = {}) {
|
|
|
14334
14462
|
return { action: "suppressed", memoryId: tombstoneId, tombstoneId, proofCount: 0 };
|
|
14335
14463
|
}
|
|
14336
14464
|
}
|
|
14337
|
-
const
|
|
14338
|
-
content:
|
|
14465
|
+
const createOpts = {
|
|
14466
|
+
content: contentToWrite,
|
|
14339
14467
|
scope: resolvedScope,
|
|
14340
14468
|
...options.folderId !== void 0 && { folderId: options.folderId },
|
|
14341
14469
|
embedding: JSON.stringify(embedding),
|
|
@@ -14352,7 +14480,24 @@ async function retain(content, ctx, options = {}) {
|
|
|
14352
14480
|
kind: options.eventTime.kind
|
|
14353
14481
|
}
|
|
14354
14482
|
}
|
|
14355
|
-
}
|
|
14483
|
+
};
|
|
14484
|
+
if (supersedeTargetId) {
|
|
14485
|
+
const { created: created2, retired } = await createSupersedingMemoryOp(
|
|
14486
|
+
ctx.vaultCtx,
|
|
14487
|
+
createOpts,
|
|
14488
|
+
supersedeTargetId
|
|
14489
|
+
);
|
|
14490
|
+
if (created2 && retired) {
|
|
14491
|
+
ctx.vaultCache.set(created2.uniqueId, Float32Array.from(embedding));
|
|
14492
|
+
return {
|
|
14493
|
+
action: "supersede",
|
|
14494
|
+
memoryId: created2.uniqueId,
|
|
14495
|
+
targetId: supersedeTargetId,
|
|
14496
|
+
proofCount: 1
|
|
14497
|
+
};
|
|
14498
|
+
}
|
|
14499
|
+
}
|
|
14500
|
+
const created = await createVaultMemoryOp(ctx.vaultCtx, createOpts);
|
|
14356
14501
|
ctx.vaultCache.set(created.uniqueId, Float32Array.from(embedding));
|
|
14357
14502
|
return {
|
|
14358
14503
|
action: "create",
|
|
@@ -14422,9 +14567,14 @@ async function tryConsolidate(trimmed, ctx, options) {
|
|
|
14422
14567
|
const { consolidateMemory: doConsolidate } = await Promise.resolve().then(() => (init_consolidate(), consolidate_exports));
|
|
14423
14568
|
const decision = await doConsolidate(trimmed, candidates, consolidateOptions);
|
|
14424
14569
|
if (decision.action === "create") return null;
|
|
14570
|
+
if (decision.action === "supersede" && decision.targetId && decision.content) {
|
|
14571
|
+
const existing = await getVaultMemoryOp(ctx.vaultCtx, decision.targetId);
|
|
14572
|
+
if (!existing || existing.supersededBy) return null;
|
|
14573
|
+
return { supersede: decision.targetId, content: decision.content };
|
|
14574
|
+
}
|
|
14425
14575
|
if (decision.action === "noop" && decision.targetId) {
|
|
14426
14576
|
const existing = await getVaultMemoryOp(ctx.vaultCtx, decision.targetId);
|
|
14427
|
-
if (!existing) return null;
|
|
14577
|
+
if (!existing || existing.supersededBy) return null;
|
|
14428
14578
|
const mergedSourceIds = unionStrings(
|
|
14429
14579
|
existing.sourceChunkIds ?? [],
|
|
14430
14580
|
options.sourceChunkIds ?? []
|
|
@@ -14442,15 +14592,17 @@ async function tryConsolidate(trimmed, ctx, options) {
|
|
|
14442
14592
|
return null;
|
|
14443
14593
|
}
|
|
14444
14594
|
return {
|
|
14445
|
-
|
|
14446
|
-
|
|
14447
|
-
|
|
14448
|
-
|
|
14595
|
+
done: {
|
|
14596
|
+
action: "merge",
|
|
14597
|
+
memoryId: decision.targetId,
|
|
14598
|
+
targetId: decision.targetId,
|
|
14599
|
+
proofCount: updated.proofCount ?? (existing.proofCount ?? 1) + 1
|
|
14600
|
+
}
|
|
14449
14601
|
};
|
|
14450
14602
|
}
|
|
14451
14603
|
if (decision.action === "update" && decision.targetId && decision.content) {
|
|
14452
14604
|
const existing = await getVaultMemoryOp(ctx.vaultCtx, decision.targetId);
|
|
14453
|
-
if (!existing) return null;
|
|
14605
|
+
if (!existing || existing.supersededBy) return null;
|
|
14454
14606
|
const mergedSourceIds = unionStrings(
|
|
14455
14607
|
existing.sourceChunkIds ?? [],
|
|
14456
14608
|
options.sourceChunkIds ?? []
|
|
@@ -14477,10 +14629,12 @@ async function tryConsolidate(trimmed, ctx, options) {
|
|
|
14477
14629
|
}
|
|
14478
14630
|
ctx.vaultCache.set(decision.targetId, Float32Array.from(newEmbedding));
|
|
14479
14631
|
return {
|
|
14480
|
-
|
|
14481
|
-
|
|
14482
|
-
|
|
14483
|
-
|
|
14632
|
+
done: {
|
|
14633
|
+
action: "update",
|
|
14634
|
+
memoryId: decision.targetId,
|
|
14635
|
+
targetId: decision.targetId,
|
|
14636
|
+
proofCount: updated.proofCount ?? (existing.proofCount ?? 1) + 1
|
|
14637
|
+
}
|
|
14484
14638
|
};
|
|
14485
14639
|
}
|
|
14486
14640
|
return null;
|
|
@@ -19817,7 +19971,7 @@ __decorateClass([
|
|
|
19817
19971
|
], VaultFolder.prototype, "context", 2);
|
|
19818
19972
|
|
|
19819
19973
|
// src/lib/db/schema.ts
|
|
19820
|
-
var SDK_SCHEMA_VERSION =
|
|
19974
|
+
var SDK_SCHEMA_VERSION = 38;
|
|
19821
19975
|
var sdkSchema = (0, import_watermelondb20.appSchema)({
|
|
19822
19976
|
version: SDK_SCHEMA_VERSION,
|
|
19823
19977
|
tables: [
|
|
@@ -19942,7 +20096,20 @@ var sdkSchema = (0, import_watermelondb20.appSchema)({
|
|
|
19942
20096
|
// Unix ms of the last LLM topic-extraction pass over this memory's
|
|
19943
20097
|
// content. Null = never extracted standalone (legacy rows with entity
|
|
19944
20098
|
// links are grandfathered — see getMemoriesNeedingTopicExtractionOp).
|
|
19945
|
-
{ name: "topics_extracted_at", type: "number", isOptional: true }
|
|
20099
|
+
{ name: "topics_extracted_at", type: "number", isOptional: true },
|
|
20100
|
+
// Write-time supersession (A2). When set, this fact was replaced by a
|
|
20101
|
+
// newer, incompatible-value fact (e.g. "Lives in Portland" superseded by
|
|
20102
|
+
// "Lives in SF"); `superseded_by` points at the newer memory's id and
|
|
20103
|
+
// `superseded_at` is the Unix ms it happened. Superseded rows stay in
|
|
20104
|
+
// the table (history / read-time fallback) but are excluded from recall
|
|
20105
|
+
// and dedup by default. Null = live (not superseded). Indexed so the
|
|
20106
|
+
// recall filter stays cheap.
|
|
20107
|
+
{ name: "superseded_by", type: "string", isOptional: true, isIndexed: true },
|
|
20108
|
+
{ name: "superseded_at", type: "number", isOptional: true },
|
|
20109
|
+
// The extraction-logic version this memory was last stamped under. Null
|
|
20110
|
+
// (pre-v38) is treated as version 0, so a bump of TOPICS_EXTRACTION_VERSION
|
|
20111
|
+
// re-extracts stale rows. See getMemoriesNeedingTopicExtractionOp.
|
|
20112
|
+
{ name: "topics_extracted_version", type: "number", isOptional: true }
|
|
19946
20113
|
]
|
|
19947
20114
|
}),
|
|
19948
20115
|
// Entity table — canonical names extracted from auto-extraction (W5).
|
|
@@ -20553,6 +20720,34 @@ var sdkMigrations = (0, import_migrations2.schemaMigrations)({
|
|
|
20553
20720
|
columns: [{ name: "topics_extracted_at", type: "number", isOptional: true }]
|
|
20554
20721
|
})
|
|
20555
20722
|
]
|
|
20723
|
+
},
|
|
20724
|
+
// v36 -> v37: write-time supersession columns on memory_vault. Existing rows
|
|
20725
|
+
// keep both NULL (= live / not superseded), so no backfill — legacy
|
|
20726
|
+
// contradictory rows are handled by the read-time supersession fallback.
|
|
20727
|
+
{
|
|
20728
|
+
toVersion: 37,
|
|
20729
|
+
steps: [
|
|
20730
|
+
(0, import_migrations2.addColumns)({
|
|
20731
|
+
table: "memory_vault",
|
|
20732
|
+
columns: [
|
|
20733
|
+
{ name: "superseded_by", type: "string", isOptional: true, isIndexed: true },
|
|
20734
|
+
{ name: "superseded_at", type: "number", isOptional: true }
|
|
20735
|
+
]
|
|
20736
|
+
})
|
|
20737
|
+
]
|
|
20738
|
+
},
|
|
20739
|
+
// v37 -> v38: topics_extracted_version on memory_vault. Existing rows keep it
|
|
20740
|
+
// NULL, read as version 0 by getMemoriesNeedingTopicExtractionOp — so the
|
|
20741
|
+
// first sweep after a TOPICS_EXTRACTION_VERSION bump re-extracts them (drained
|
|
20742
|
+
// across sweeps by the worker's limit). See topicExtract.ts.
|
|
20743
|
+
{
|
|
20744
|
+
toVersion: 38,
|
|
20745
|
+
steps: [
|
|
20746
|
+
(0, import_migrations2.addColumns)({
|
|
20747
|
+
table: "memory_vault",
|
|
20748
|
+
columns: [{ name: "topics_extracted_version", type: "number", isOptional: true }]
|
|
20749
|
+
})
|
|
20750
|
+
]
|
|
20556
20751
|
}
|
|
20557
20752
|
]
|
|
20558
20753
|
});
|
|
@@ -30233,6 +30428,7 @@ function renderAnumaJsx(jsx3) {
|
|
|
30233
30428
|
StoredVaultMemoryModel,
|
|
30234
30429
|
StreamExpiredError,
|
|
30235
30430
|
THEME_ATTRS,
|
|
30431
|
+
TOPICS_EXTRACTION_VERSION,
|
|
30236
30432
|
TOPIC_EXTRACTION_BATCH_SIZE,
|
|
30237
30433
|
TextProcessor,
|
|
30238
30434
|
UIInteractionProvider,
|
|
@@ -30509,6 +30705,7 @@ function renderAnumaJsx(jsx3) {
|
|
|
30509
30705
|
storeNotionReturnUrl,
|
|
30510
30706
|
streamCancelPath,
|
|
30511
30707
|
streamReplayPath,
|
|
30708
|
+
supersedeVaultMemoryOp,
|
|
30512
30709
|
updateAttrs,
|
|
30513
30710
|
updateConversationProjectOp,
|
|
30514
30711
|
updateMediaMessageIdBatchOp,
|