@anuma/sdk 4.0.0 → 4.0.2
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/client/index.cjs +15 -2
- package/dist/client/index.d.mts +94 -1
- package/dist/client/index.d.ts +94 -1
- package/dist/client/index.mjs +12 -1
- package/dist/expo/{chunk-BOAKGY4R.mjs → chunk-VBO6KSNQ.mjs} +44 -4
- package/dist/expo/{consolidate-AURTG64H.mjs → consolidate-KASO7JDS.mjs} +7 -5
- package/dist/expo/index.cjs +50 -8
- package/dist/expo/index.d.mts +15 -3
- package/dist/expo/index.d.ts +15 -3
- package/dist/expo/index.mjs +2 -2
- package/dist/{react/recall-KTJCUAXN.mjs → expo/recall-OCQOA7M3.mjs} +1 -1
- package/dist/react/{chunk-XXCZVG4Z.mjs → chunk-BS7C4CUW.mjs} +38 -26
- package/dist/react/{consolidate-R6FH7XMV.mjs → consolidate-IFIKT25Z.mjs} +7 -5
- package/dist/react/index.cjs +44 -30
- package/dist/react/index.d.mts +26 -4
- package/dist/react/index.d.ts +26 -4
- package/dist/react/index.mjs +2 -2
- package/dist/{expo/recall-O65PGPIQ.mjs → react/recall-WXCZHXHZ.mjs} +1 -1
- package/dist/server/{chunk-WZE6ZVKE.mjs → chunk-WADHFDMA.mjs} +44 -4
- package/dist/server/{consolidate-4VEAS3YN.mjs → consolidate-GRMEDWKK.mjs} +7 -5
- package/dist/server/index.cjs +50 -8
- package/dist/server/index.d.mts +15 -3
- package/dist/server/index.d.ts +15 -3
- package/dist/server/index.mjs +2 -2
- package/dist/server/{recall-YZWIV6IH.mjs → recall-QTVT7HCZ.mjs} +1 -1
- package/package.json +2 -2
package/dist/expo/index.d.mts
CHANGED
|
@@ -6083,6 +6083,12 @@ declare function getUnfiledVaultMemoriesOp(ctx: VaultMemoryOperationsContext): P
|
|
|
6083
6083
|
* older version (including pre-v37 rows, read as version 0) is then re-extracted
|
|
6084
6084
|
* by the next sweep, so topic-quality improvements propagate across the existing
|
|
6085
6085
|
* vault. The worker's `limit` drains that re-extraction across sweeps.
|
|
6086
|
+
*
|
|
6087
|
+
* Bumping this is a WHOLE-VAULT re-extraction: the gate is unconditional across
|
|
6088
|
+
* every stamped row, and `stampTopicsExtractedAtOp` stamps this version on every
|
|
6089
|
+
* healthy row, so a bump sends each user's entire extracted vault back to the
|
|
6090
|
+
* LLM. Never reach for it to repair a subset — see the pre-v42-restore repair in
|
|
6091
|
+
* {@link getMemoriesNeedingTopicExtractionOp}, which targets the damaged rows.
|
|
6086
6092
|
*/
|
|
6087
6093
|
declare const TOPICS_EXTRACTION_VERSION = 3;
|
|
6088
6094
|
/**
|
|
@@ -6095,9 +6101,10 @@ interface MemoriesNeedingTopicExtraction {
|
|
|
6095
6101
|
* Memories to run LLM topic extraction on (decrypted): never-extracted rows
|
|
6096
6102
|
* with no entity links, plus stamped rows edited since their last pass
|
|
6097
6103
|
* (`updated_at` > `topics_extracted_at`) or extracted under an older
|
|
6098
|
-
* `topics_extracted_version` than {@link TOPICS_EXTRACTION_VERSION}
|
|
6099
|
-
*
|
|
6100
|
-
*
|
|
6104
|
+
* `topics_extracted_version` than {@link TOPICS_EXTRACTION_VERSION}, plus the
|
|
6105
|
+
* pre-v42-restore repair: a stamped row left with neither links nor a `topics`
|
|
6106
|
+
* record, which no no-LLM bucket can reach. Edited / stale-version rows come
|
|
6107
|
+
* first (they get priority under `limit`), each group newest-created first.
|
|
6101
6108
|
*/
|
|
6102
6109
|
pending: StoredVaultMemory[];
|
|
6103
6110
|
/**
|
|
@@ -6149,6 +6156,11 @@ interface MemoriesNeedingTopicExtraction {
|
|
|
6149
6156
|
* between the record and the index and never re-derive them. That's why the
|
|
6150
6157
|
* ownership filter lives in the partition below rather than in the query: a
|
|
6151
6158
|
* restored curated memory is exactly the row whose index must be rebuilt.
|
|
6159
|
+
*
|
|
6160
|
+
* NOT purely a read: a curated row with no `topics` record AND no usable link is
|
|
6161
|
+
* a contradiction only a pre-v42 restore produces, and this is the one place
|
|
6162
|
+
* that can see all three facts at once, so it clears the flag there (capped by
|
|
6163
|
+
* `limit`) before returning. See the branch for why that's safe.
|
|
6152
6164
|
*/
|
|
6153
6165
|
declare function getMemoriesNeedingTopicExtractionOp(ctx: VaultMemoryOperationsContext, options?: {
|
|
6154
6166
|
limit?: number;
|
package/dist/expo/index.d.ts
CHANGED
|
@@ -6083,6 +6083,12 @@ declare function getUnfiledVaultMemoriesOp(ctx: VaultMemoryOperationsContext): P
|
|
|
6083
6083
|
* older version (including pre-v37 rows, read as version 0) is then re-extracted
|
|
6084
6084
|
* by the next sweep, so topic-quality improvements propagate across the existing
|
|
6085
6085
|
* vault. The worker's `limit` drains that re-extraction across sweeps.
|
|
6086
|
+
*
|
|
6087
|
+
* Bumping this is a WHOLE-VAULT re-extraction: the gate is unconditional across
|
|
6088
|
+
* every stamped row, and `stampTopicsExtractedAtOp` stamps this version on every
|
|
6089
|
+
* healthy row, so a bump sends each user's entire extracted vault back to the
|
|
6090
|
+
* LLM. Never reach for it to repair a subset — see the pre-v42-restore repair in
|
|
6091
|
+
* {@link getMemoriesNeedingTopicExtractionOp}, which targets the damaged rows.
|
|
6086
6092
|
*/
|
|
6087
6093
|
declare const TOPICS_EXTRACTION_VERSION = 3;
|
|
6088
6094
|
/**
|
|
@@ -6095,9 +6101,10 @@ interface MemoriesNeedingTopicExtraction {
|
|
|
6095
6101
|
* Memories to run LLM topic extraction on (decrypted): never-extracted rows
|
|
6096
6102
|
* with no entity links, plus stamped rows edited since their last pass
|
|
6097
6103
|
* (`updated_at` > `topics_extracted_at`) or extracted under an older
|
|
6098
|
-
* `topics_extracted_version` than {@link TOPICS_EXTRACTION_VERSION}
|
|
6099
|
-
*
|
|
6100
|
-
*
|
|
6104
|
+
* `topics_extracted_version` than {@link TOPICS_EXTRACTION_VERSION}, plus the
|
|
6105
|
+
* pre-v42-restore repair: a stamped row left with neither links nor a `topics`
|
|
6106
|
+
* record, which no no-LLM bucket can reach. Edited / stale-version rows come
|
|
6107
|
+
* first (they get priority under `limit`), each group newest-created first.
|
|
6101
6108
|
*/
|
|
6102
6109
|
pending: StoredVaultMemory[];
|
|
6103
6110
|
/**
|
|
@@ -6149,6 +6156,11 @@ interface MemoriesNeedingTopicExtraction {
|
|
|
6149
6156
|
* between the record and the index and never re-derive them. That's why the
|
|
6150
6157
|
* ownership filter lives in the partition below rather than in the query: a
|
|
6151
6158
|
* restored curated memory is exactly the row whose index must be rebuilt.
|
|
6159
|
+
*
|
|
6160
|
+
* NOT purely a read: a curated row with no `topics` record AND no usable link is
|
|
6161
|
+
* a contradiction only a pre-v42 restore produces, and this is the one place
|
|
6162
|
+
* that can see all three facts at once, so it clears the flag there (capped by
|
|
6163
|
+
* `limit`) before returning. See the branch for why that's safe.
|
|
6152
6164
|
*/
|
|
6153
6165
|
declare function getMemoriesNeedingTopicExtractionOp(ctx: VaultMemoryOperationsContext, options?: {
|
|
6154
6166
|
limit?: number;
|
package/dist/expo/index.mjs
CHANGED
|
@@ -116,7 +116,7 @@ import {
|
|
|
116
116
|
upsertMessageOp,
|
|
117
117
|
useEncryption,
|
|
118
118
|
vaultMemoryToStored
|
|
119
|
-
} from "./chunk-
|
|
119
|
+
} from "./chunk-VBO6KSNQ.mjs";
|
|
120
120
|
import {
|
|
121
121
|
PII_PATTERNS,
|
|
122
122
|
PiiRedactor,
|
|
@@ -6673,7 +6673,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
6673
6673
|
content: m.content,
|
|
6674
6674
|
similarity: m.similarity
|
|
6675
6675
|
}));
|
|
6676
|
-
const { consolidateMemory: doConsolidate } = await import("./consolidate-
|
|
6676
|
+
const { consolidateMemory: doConsolidate } = await import("./consolidate-KASO7JDS.mjs");
|
|
6677
6677
|
const decision = await doConsolidate(trimmed, candidates, consolidateOptions);
|
|
6678
6678
|
if (decision.action === "create") return null;
|
|
6679
6679
|
if (decision.action === "supersede" && decision.content) {
|
|
@@ -2927,7 +2927,7 @@ async function setMemoryEntitiesOp(ctx, memoryId, entities) {
|
|
|
2927
2927
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return null;
|
|
2928
2928
|
let stale = false;
|
|
2929
2929
|
const originalUpdatedAt = record.updatedAt.getTime();
|
|
2930
|
-
await ctx.database.write(async () => {
|
|
2930
|
+
await ctx.database.write(async (writer) => {
|
|
2931
2931
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) {
|
|
2932
2932
|
stale = true;
|
|
2933
2933
|
return;
|
|
@@ -2936,30 +2936,23 @@ async function setMemoryEntitiesOp(ctx, memoryId, entities) {
|
|
|
2936
2936
|
r._setRaw("topics_user_managed", true);
|
|
2937
2937
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
2938
2938
|
});
|
|
2939
|
+
const linked = entities.length > 0 ? await writer.callWriter(
|
|
2940
|
+
() => linkMemoryEntitiesOp(entityCtx, memoryId, entities, { topicsSource: "user" })
|
|
2941
|
+
) : [];
|
|
2942
|
+
const keep = new Set(linked.map((e) => e.uniqueId));
|
|
2943
|
+
const existing = await entityCtx.memoryEntityCollection.query(Q3.where("memory_id", memoryId)).fetch();
|
|
2944
|
+
const staleLinks = existing.filter((l) => !keep.has(String(l.entityId)));
|
|
2945
|
+
if (staleLinks.length === 0 && entities.length > 0) return;
|
|
2946
|
+
const topicsOp = await prepareMemoryTopicsUpdate(entityCtx, memoryId, linked, entities, "user");
|
|
2947
|
+
await ctx.database.batch(
|
|
2948
|
+
...staleLinks.map((l) => l.prepareDestroyPermanently()),
|
|
2949
|
+
...topicsOp ? [topicsOp] : []
|
|
2950
|
+
);
|
|
2939
2951
|
});
|
|
2940
2952
|
if (stale) return null;
|
|
2941
|
-
const linked = entities.length > 0 ? await linkMemoryEntitiesOp(entityCtx, memoryId, entities, { topicsSource: "user" }) : [];
|
|
2942
|
-
const keep = new Set(linked.map((e) => e.uniqueId));
|
|
2943
|
-
const existing = await entityCtx.memoryEntityCollection.query(Q3.where("memory_id", memoryId)).fetch();
|
|
2944
|
-
const staleLinks = existing.filter((l) => !keep.has(String(l.entityId)));
|
|
2945
|
-
if (staleLinks.length > 0 || entities.length === 0) {
|
|
2946
|
-
await ctx.database.write(async () => {
|
|
2947
|
-
const topicsOp = await prepareMemoryTopicsUpdate(
|
|
2948
|
-
entityCtx,
|
|
2949
|
-
memoryId,
|
|
2950
|
-
linked,
|
|
2951
|
-
entities,
|
|
2952
|
-
"user"
|
|
2953
|
-
);
|
|
2954
|
-
await ctx.database.batch(
|
|
2955
|
-
...staleLinks.map((l) => l.prepareDestroyPermanently()),
|
|
2956
|
-
...topicsOp ? [topicsOp] : []
|
|
2957
|
-
);
|
|
2958
|
-
});
|
|
2959
|
-
}
|
|
2960
2953
|
return vaultMemoryToStored(record, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
2961
2954
|
}
|
|
2962
|
-
async function clearMemoryTopicsOverrideOp(ctx, memoryId) {
|
|
2955
|
+
async function clearMemoryTopicsOverrideOp(ctx, memoryId, options) {
|
|
2963
2956
|
let record;
|
|
2964
2957
|
try {
|
|
2965
2958
|
record = await ctx.vaultMemoryCollection.find(memoryId);
|
|
@@ -2968,7 +2961,10 @@ async function clearMemoryTopicsOverrideOp(ctx, memoryId) {
|
|
|
2968
2961
|
}
|
|
2969
2962
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return false;
|
|
2970
2963
|
const originalUpdatedAt = record.updatedAt.getTime();
|
|
2964
|
+
let cleared = false;
|
|
2971
2965
|
await ctx.database.write(async () => {
|
|
2966
|
+
if (options?.unlessTopicsRecorded && parseTopics(record.topics) !== null) return;
|
|
2967
|
+
cleared = true;
|
|
2972
2968
|
await record.update((r) => {
|
|
2973
2969
|
r._setRaw("topics_user_managed", false);
|
|
2974
2970
|
r._setRaw("topics_extracted_version", null);
|
|
@@ -2978,7 +2974,7 @@ async function clearMemoryTopicsOverrideOp(ctx, memoryId) {
|
|
|
2978
2974
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
2979
2975
|
});
|
|
2980
2976
|
});
|
|
2981
|
-
return
|
|
2977
|
+
return cleared;
|
|
2982
2978
|
}
|
|
2983
2979
|
async function setMemoryVisibilityOp(ctx, id, opts) {
|
|
2984
2980
|
let record;
|
|
@@ -3141,11 +3137,13 @@ async function getMemoriesNeedingTopicExtractionOp(ctx, options) {
|
|
|
3141
3137
|
entityCtx,
|
|
3142
3138
|
rows.map((r) => r.id)
|
|
3143
3139
|
);
|
|
3140
|
+
const cap = options?.limit !== void 0 && options.limit > 0 ? options.limit : void 0;
|
|
3144
3141
|
const pendingRaw = [];
|
|
3145
3142
|
const stampedPendingRaw = [];
|
|
3146
3143
|
const linkedUnstampedAll = [];
|
|
3147
3144
|
const topicsToRelinkAll = [];
|
|
3148
3145
|
const topicsBackfillAll = [];
|
|
3146
|
+
const emptyCurationToClear = [];
|
|
3149
3147
|
for (const raw of rows) {
|
|
3150
3148
|
const id = raw.id;
|
|
3151
3149
|
const topics = parseTopics(raw.topics);
|
|
@@ -3155,8 +3153,12 @@ async function getMemoriesNeedingTopicExtractionOp(ctx, options) {
|
|
|
3155
3153
|
continue;
|
|
3156
3154
|
}
|
|
3157
3155
|
if (raw.topics_user_managed) {
|
|
3158
|
-
if (topics
|
|
3159
|
-
|
|
3156
|
+
if (topics !== null || linked !== void 0) {
|
|
3157
|
+
if (topics === null) topicsBackfillAll.push(id);
|
|
3158
|
+
continue;
|
|
3159
|
+
}
|
|
3160
|
+
if (cap !== void 0 && emptyCurationToClear.length >= cap) continue;
|
|
3161
|
+
emptyCurationToClear.push(id);
|
|
3160
3162
|
}
|
|
3161
3163
|
const stamp = raw.topics_extracted_at ?? null;
|
|
3162
3164
|
let isPending = false;
|
|
@@ -3172,11 +3174,21 @@ async function getMemoriesNeedingTopicExtractionOp(ctx, options) {
|
|
|
3172
3174
|
pendingRaw.push(raw);
|
|
3173
3175
|
isPending = true;
|
|
3174
3176
|
}
|
|
3177
|
+
if (!isPending && linked === void 0 && topics === null) {
|
|
3178
|
+
pendingRaw.push(raw);
|
|
3179
|
+
isPending = true;
|
|
3180
|
+
}
|
|
3175
3181
|
if (!isPending && topics === null && linked !== void 0) {
|
|
3176
3182
|
topicsBackfillAll.push(id);
|
|
3177
3183
|
}
|
|
3178
3184
|
}
|
|
3179
|
-
const
|
|
3185
|
+
for (const id of emptyCurationToClear) {
|
|
3186
|
+
try {
|
|
3187
|
+
await clearMemoryTopicsOverrideOp(ctx, id, { unlessTopicsRecorded: true });
|
|
3188
|
+
} catch (err) {
|
|
3189
|
+
getLogger().warn("[memory/topics] repair clear failed", err);
|
|
3190
|
+
}
|
|
3191
|
+
}
|
|
3180
3192
|
const orderedPendingRaw = [...stampedPendingRaw, ...pendingRaw];
|
|
3181
3193
|
const limitedPendingRaw = cap !== void 0 ? orderedPendingRaw.slice(0, cap) : orderedPendingRaw;
|
|
3182
3194
|
const pending = await mapInBatches(
|
|
@@ -6430,7 +6442,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
6430
6442
|
legacy.map((r) => ({ id: r.uniqueId, content: r.content, score: r.similarity }))
|
|
6431
6443
|
);
|
|
6432
6444
|
}
|
|
6433
|
-
const { recall: recall2 } = await import("./recall-
|
|
6445
|
+
const { recall: recall2 } = await import("./recall-WXCZHXHZ.mjs");
|
|
6434
6446
|
let recallDegraded = [];
|
|
6435
6447
|
const result = await recall2(
|
|
6436
6448
|
query,
|
|
@@ -18,19 +18,21 @@ A "memory" is a self-contained natural-language fact about the user. Multiple me
|
|
|
18
18
|
Decide one of four actions:
|
|
19
19
|
|
|
20
20
|
- "create": the new memory describes a distinct fact not covered by any existing memory. Write it as new.
|
|
21
|
-
- "update": the new memory describes the SAME FACET as exactly one existing memory
|
|
22
|
-
- "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 "targetIds": an array of the ids of EVERY existing candidate that describes the SAME standing attribute now being changed \u2014 retire ALL stale duplicates of the old value, not just one (the candidate list may contain several paraphrases of the same old fact) + content = the NEW fact. The old memories are kept as history, not overwritten or deleted; do not re-state them.
|
|
23
|
-
- "noop": the new memory is already fully captured by an existing memory \u2014 same facet, no new information. Skip the write.
|
|
21
|
+
- "update": the new memory describes the SAME FACET of the SAME SUBJECT as exactly one existing memory, is COMPATIBLE with it, and ADDS INFORMATION \u2014 it adds detail or fills in an incomplete value. Return targetId of that existing memory + the consolidated content (richest version of the two). A pure rewording that adds nothing is NOT an update; it is "noop".
|
|
22
|
+
- "supersede": the new memory REPLACES a standing fact whose value has CHANGED and is now INCOMPATIBLE with an existing memory ABOUT THE SAME SUBJECT \u2014 the old fact was true before but is false now (a state change). Before choosing this, name the subject of the new memory and the subject of each candidate out loud to yourself; if they are different people, the old fact is still TRUE and superseding it would delete a correct memory \u2014 choose "create" instead. Return "targetIds": an array of the ids of EVERY existing candidate that describes the SAME standing attribute now being changed \u2014 retire ALL stale duplicates of the old value, not just one (the candidate list may contain several paraphrases of the same old fact) + content = the NEW fact. The old memories are kept as history, not overwritten or deleted; do not re-state them.
|
|
23
|
+
- "noop": the new memory is already fully captured by an existing memory \u2014 same facet of the same subject, no new information. This INCLUDES a restatement in different words ("has two kids" / "has two children"): if the existing memory already tells you everything the new one does, the answer is noop no matter how differently it is worded. Skip the write.
|
|
24
24
|
|
|
25
25
|
RULES (carry these strictly):
|
|
26
26
|
|
|
27
27
|
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.
|
|
28
|
+
1a. SAME SUBJECT REQUIRED \u2014 check this FIRST, before you look at the facet. The subject is WHO the fact is about: the user, or a specific person or thing in their life (a relative, their manager, their dog Biscuit). "update", "supersede" and "noop" all require the new memory and the existing one to be about the SAME subject. Two memories can share a facet and still have different subjects, and then they are simply two different facts: "User's daughter is allergic to peanuts" and "User is allergic to peanuts" are both about a peanut allergy, but one is about the DAUGHTER and one is about the USER \u2192 create, keep both. This holds for EVERY attribute, not just the one in this example \u2014 where someone lives, who they work for, what they own, how old they are. A possessive like "user's X" makes X the subject, not the user; strip it and ask "whose fact is this?" before comparing anything. Never retire the user's own value because a fact about somebody else resembles it \u2014 the user's fact is still true, and retiring it destroys it.
|
|
28
29
|
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.
|
|
29
30
|
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.
|
|
30
31
|
4. EVENTS vs STANDING STATE.
|
|
31
32
|
- 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.
|
|
32
|
-
- A STANDING ATTRIBUTE (an ongoing state: where
|
|
33
|
-
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.
|
|
33
|
+
- A STANDING ATTRIBUTE (an ongoing state: where someone lives/works, relationship status, current role) has ONE current value PER SUBJECT. When the new memory changes that value FOR THE SAME SUBJECT ("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). A different subject holding the same attribute is not a value change at all \u2192 create.
|
|
34
|
+
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 ABOUT THE SAME SUBJECT; then choose supersede. Two facts about different subjects never contradict each other, however similarly they read. Over-merging loses information; a live contradiction is worse than either.
|
|
35
|
+
6. When in doubt between update and noop, ask whether the existing memory ALONE already answers everything the new one would. If it does, choose noop \u2014 a write that changes only the wording costs a re-embed and makes an old fact look newly observed.
|
|
34
36
|
|
|
35
37
|
OUTPUT \u2014 strict JSON, no prose:
|
|
36
38
|
{
|
package/dist/react/index.cjs
CHANGED
|
@@ -5238,7 +5238,7 @@ async function setMemoryEntitiesOp(ctx, memoryId, entities) {
|
|
|
5238
5238
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return null;
|
|
5239
5239
|
let stale = false;
|
|
5240
5240
|
const originalUpdatedAt = record.updatedAt.getTime();
|
|
5241
|
-
await ctx.database.write(async () => {
|
|
5241
|
+
await ctx.database.write(async (writer) => {
|
|
5242
5242
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) {
|
|
5243
5243
|
stale = true;
|
|
5244
5244
|
return;
|
|
@@ -5247,30 +5247,23 @@ async function setMemoryEntitiesOp(ctx, memoryId, entities) {
|
|
|
5247
5247
|
r._setRaw("topics_user_managed", true);
|
|
5248
5248
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
5249
5249
|
});
|
|
5250
|
+
const linked = entities.length > 0 ? await writer.callWriter(
|
|
5251
|
+
() => linkMemoryEntitiesOp(entityCtx, memoryId, entities, { topicsSource: "user" })
|
|
5252
|
+
) : [];
|
|
5253
|
+
const keep = new Set(linked.map((e) => e.uniqueId));
|
|
5254
|
+
const existing = await entityCtx.memoryEntityCollection.query(import_watermelondb10.Q.where("memory_id", memoryId)).fetch();
|
|
5255
|
+
const staleLinks = existing.filter((l) => !keep.has(String(l.entityId)));
|
|
5256
|
+
if (staleLinks.length === 0 && entities.length > 0) return;
|
|
5257
|
+
const topicsOp = await prepareMemoryTopicsUpdate(entityCtx, memoryId, linked, entities, "user");
|
|
5258
|
+
await ctx.database.batch(
|
|
5259
|
+
...staleLinks.map((l) => l.prepareDestroyPermanently()),
|
|
5260
|
+
...topicsOp ? [topicsOp] : []
|
|
5261
|
+
);
|
|
5250
5262
|
});
|
|
5251
5263
|
if (stale) return null;
|
|
5252
|
-
const linked = entities.length > 0 ? await linkMemoryEntitiesOp(entityCtx, memoryId, entities, { topicsSource: "user" }) : [];
|
|
5253
|
-
const keep = new Set(linked.map((e) => e.uniqueId));
|
|
5254
|
-
const existing = await entityCtx.memoryEntityCollection.query(import_watermelondb10.Q.where("memory_id", memoryId)).fetch();
|
|
5255
|
-
const staleLinks = existing.filter((l) => !keep.has(String(l.entityId)));
|
|
5256
|
-
if (staleLinks.length > 0 || entities.length === 0) {
|
|
5257
|
-
await ctx.database.write(async () => {
|
|
5258
|
-
const topicsOp = await prepareMemoryTopicsUpdate(
|
|
5259
|
-
entityCtx,
|
|
5260
|
-
memoryId,
|
|
5261
|
-
linked,
|
|
5262
|
-
entities,
|
|
5263
|
-
"user"
|
|
5264
|
-
);
|
|
5265
|
-
await ctx.database.batch(
|
|
5266
|
-
...staleLinks.map((l) => l.prepareDestroyPermanently()),
|
|
5267
|
-
...topicsOp ? [topicsOp] : []
|
|
5268
|
-
);
|
|
5269
|
-
});
|
|
5270
|
-
}
|
|
5271
5264
|
return vaultMemoryToStored(record, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
5272
5265
|
}
|
|
5273
|
-
async function clearMemoryTopicsOverrideOp(ctx, memoryId) {
|
|
5266
|
+
async function clearMemoryTopicsOverrideOp(ctx, memoryId, options) {
|
|
5274
5267
|
let record;
|
|
5275
5268
|
try {
|
|
5276
5269
|
record = await ctx.vaultMemoryCollection.find(memoryId);
|
|
@@ -5279,7 +5272,10 @@ async function clearMemoryTopicsOverrideOp(ctx, memoryId) {
|
|
|
5279
5272
|
}
|
|
5280
5273
|
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return false;
|
|
5281
5274
|
const originalUpdatedAt = record.updatedAt.getTime();
|
|
5275
|
+
let cleared = false;
|
|
5282
5276
|
await ctx.database.write(async () => {
|
|
5277
|
+
if (options?.unlessTopicsRecorded && parseTopics(record.topics) !== null) return;
|
|
5278
|
+
cleared = true;
|
|
5283
5279
|
await record.update((r) => {
|
|
5284
5280
|
r._setRaw("topics_user_managed", false);
|
|
5285
5281
|
r._setRaw("topics_extracted_version", null);
|
|
@@ -5289,7 +5285,7 @@ async function clearMemoryTopicsOverrideOp(ctx, memoryId) {
|
|
|
5289
5285
|
r._setRaw("updated_at", originalUpdatedAt);
|
|
5290
5286
|
});
|
|
5291
5287
|
});
|
|
5292
|
-
return
|
|
5288
|
+
return cleared;
|
|
5293
5289
|
}
|
|
5294
5290
|
async function setMemoryVisibilityOp(ctx, id, opts) {
|
|
5295
5291
|
let record;
|
|
@@ -5451,11 +5447,13 @@ async function getMemoriesNeedingTopicExtractionOp(ctx, options) {
|
|
|
5451
5447
|
entityCtx,
|
|
5452
5448
|
rows.map((r) => r.id)
|
|
5453
5449
|
);
|
|
5450
|
+
const cap = options?.limit !== void 0 && options.limit > 0 ? options.limit : void 0;
|
|
5454
5451
|
const pendingRaw = [];
|
|
5455
5452
|
const stampedPendingRaw = [];
|
|
5456
5453
|
const linkedUnstampedAll = [];
|
|
5457
5454
|
const topicsToRelinkAll = [];
|
|
5458
5455
|
const topicsBackfillAll = [];
|
|
5456
|
+
const emptyCurationToClear = [];
|
|
5459
5457
|
for (const raw of rows) {
|
|
5460
5458
|
const id = raw.id;
|
|
5461
5459
|
const topics = parseTopics(raw.topics);
|
|
@@ -5465,8 +5463,12 @@ async function getMemoriesNeedingTopicExtractionOp(ctx, options) {
|
|
|
5465
5463
|
continue;
|
|
5466
5464
|
}
|
|
5467
5465
|
if (raw.topics_user_managed) {
|
|
5468
|
-
if (topics
|
|
5469
|
-
|
|
5466
|
+
if (topics !== null || linked !== void 0) {
|
|
5467
|
+
if (topics === null) topicsBackfillAll.push(id);
|
|
5468
|
+
continue;
|
|
5469
|
+
}
|
|
5470
|
+
if (cap !== void 0 && emptyCurationToClear.length >= cap) continue;
|
|
5471
|
+
emptyCurationToClear.push(id);
|
|
5470
5472
|
}
|
|
5471
5473
|
const stamp = raw.topics_extracted_at ?? null;
|
|
5472
5474
|
let isPending = false;
|
|
@@ -5482,11 +5484,21 @@ async function getMemoriesNeedingTopicExtractionOp(ctx, options) {
|
|
|
5482
5484
|
pendingRaw.push(raw);
|
|
5483
5485
|
isPending = true;
|
|
5484
5486
|
}
|
|
5487
|
+
if (!isPending && linked === void 0 && topics === null) {
|
|
5488
|
+
pendingRaw.push(raw);
|
|
5489
|
+
isPending = true;
|
|
5490
|
+
}
|
|
5485
5491
|
if (!isPending && topics === null && linked !== void 0) {
|
|
5486
5492
|
topicsBackfillAll.push(id);
|
|
5487
5493
|
}
|
|
5488
5494
|
}
|
|
5489
|
-
const
|
|
5495
|
+
for (const id of emptyCurationToClear) {
|
|
5496
|
+
try {
|
|
5497
|
+
await clearMemoryTopicsOverrideOp(ctx, id, { unlessTopicsRecorded: true });
|
|
5498
|
+
} catch (err) {
|
|
5499
|
+
getLogger().warn("[memory/topics] repair clear failed", err);
|
|
5500
|
+
}
|
|
5501
|
+
}
|
|
5490
5502
|
const orderedPendingRaw = [...stampedPendingRaw, ...pendingRaw];
|
|
5491
5503
|
const limitedPendingRaw = cap !== void 0 ? orderedPendingRaw.slice(0, cap) : orderedPendingRaw;
|
|
5492
5504
|
const pending = await mapInBatches(
|
|
@@ -8847,19 +8859,21 @@ A "memory" is a self-contained natural-language fact about the user. Multiple me
|
|
|
8847
8859
|
Decide one of four actions:
|
|
8848
8860
|
|
|
8849
8861
|
- "create": the new memory describes a distinct fact not covered by any existing memory. Write it as new.
|
|
8850
|
-
- "update": the new memory describes the SAME FACET as exactly one existing memory
|
|
8851
|
-
- "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 "targetIds": an array of the ids of EVERY existing candidate that describes the SAME standing attribute now being changed \u2014 retire ALL stale duplicates of the old value, not just one (the candidate list may contain several paraphrases of the same old fact) + content = the NEW fact. The old memories are kept as history, not overwritten or deleted; do not re-state them.
|
|
8852
|
-
- "noop": the new memory is already fully captured by an existing memory \u2014 same facet, no new information. Skip the write.
|
|
8862
|
+
- "update": the new memory describes the SAME FACET of the SAME SUBJECT as exactly one existing memory, is COMPATIBLE with it, and ADDS INFORMATION \u2014 it adds detail or fills in an incomplete value. Return targetId of that existing memory + the consolidated content (richest version of the two). A pure rewording that adds nothing is NOT an update; it is "noop".
|
|
8863
|
+
- "supersede": the new memory REPLACES a standing fact whose value has CHANGED and is now INCOMPATIBLE with an existing memory ABOUT THE SAME SUBJECT \u2014 the old fact was true before but is false now (a state change). Before choosing this, name the subject of the new memory and the subject of each candidate out loud to yourself; if they are different people, the old fact is still TRUE and superseding it would delete a correct memory \u2014 choose "create" instead. Return "targetIds": an array of the ids of EVERY existing candidate that describes the SAME standing attribute now being changed \u2014 retire ALL stale duplicates of the old value, not just one (the candidate list may contain several paraphrases of the same old fact) + content = the NEW fact. The old memories are kept as history, not overwritten or deleted; do not re-state them.
|
|
8864
|
+
- "noop": the new memory is already fully captured by an existing memory \u2014 same facet of the same subject, no new information. This INCLUDES a restatement in different words ("has two kids" / "has two children"): if the existing memory already tells you everything the new one does, the answer is noop no matter how differently it is worded. Skip the write.
|
|
8853
8865
|
|
|
8854
8866
|
RULES (carry these strictly):
|
|
8855
8867
|
|
|
8856
8868
|
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.
|
|
8869
|
+
1a. SAME SUBJECT REQUIRED \u2014 check this FIRST, before you look at the facet. The subject is WHO the fact is about: the user, or a specific person or thing in their life (a relative, their manager, their dog Biscuit). "update", "supersede" and "noop" all require the new memory and the existing one to be about the SAME subject. Two memories can share a facet and still have different subjects, and then they are simply two different facts: "User's daughter is allergic to peanuts" and "User is allergic to peanuts" are both about a peanut allergy, but one is about the DAUGHTER and one is about the USER \u2192 create, keep both. This holds for EVERY attribute, not just the one in this example \u2014 where someone lives, who they work for, what they own, how old they are. A possessive like "user's X" makes X the subject, not the user; strip it and ask "whose fact is this?" before comparing anything. Never retire the user's own value because a fact about somebody else resembles it \u2014 the user's fact is still true, and retiring it destroys it.
|
|
8857
8870
|
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.
|
|
8858
8871
|
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.
|
|
8859
8872
|
4. EVENTS vs STANDING STATE.
|
|
8860
8873
|
- 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.
|
|
8861
|
-
- A STANDING ATTRIBUTE (an ongoing state: where
|
|
8862
|
-
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.
|
|
8874
|
+
- A STANDING ATTRIBUTE (an ongoing state: where someone lives/works, relationship status, current role) has ONE current value PER SUBJECT. When the new memory changes that value FOR THE SAME SUBJECT ("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). A different subject holding the same attribute is not a value change at all \u2192 create.
|
|
8875
|
+
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 ABOUT THE SAME SUBJECT; then choose supersede. Two facts about different subjects never contradict each other, however similarly they read. Over-merging loses information; a live contradiction is worse than either.
|
|
8876
|
+
6. When in doubt between update and noop, ask whether the existing memory ALONE already answers everything the new one would. If it does, choose noop \u2014 a write that changes only the wording costs a re-embed and makes an old fact look newly observed.
|
|
8863
8877
|
|
|
8864
8878
|
OUTPUT \u2014 strict JSON, no prose:
|
|
8865
8879
|
{
|
package/dist/react/index.d.mts
CHANGED
|
@@ -7457,8 +7457,18 @@ declare function setMemoryEntitiesOp(ctx: VaultMemoryOperationsContext, memoryId
|
|
|
7457
7457
|
* see the schema note. This op's version-invalidation trick is the reason the
|
|
7458
7458
|
* earlier plan to exclude them from sync was dropped, and it's the last piece
|
|
7459
7459
|
* that has to move before they can go.
|
|
7460
|
+
*
|
|
7461
|
+
* `options.unlessTopicsRecorded` declines the reset when the row already has a
|
|
7462
|
+
* `topics` record, re-checked INSIDE the serialized writer. Only the repair path
|
|
7463
|
+
* in {@link getMemoriesNeedingTopicExtractionOp} passes it: that path clears the
|
|
7464
|
+
* flag off rows whose curation is provably empty, and a `setMemoryEntitiesOp`
|
|
7465
|
+
* committing in the gap would have written a real record the autotagger must not
|
|
7466
|
+
* be handed. The user-facing reset leaves it off — resetting a memory that HAS
|
|
7467
|
+
* curated topics is the whole point there.
|
|
7460
7468
|
*/
|
|
7461
|
-
declare function clearMemoryTopicsOverrideOp(ctx: VaultMemoryOperationsContext, memoryId: string
|
|
7469
|
+
declare function clearMemoryTopicsOverrideOp(ctx: VaultMemoryOperationsContext, memoryId: string, options?: {
|
|
7470
|
+
unlessTopicsRecorded?: boolean;
|
|
7471
|
+
}): Promise<boolean>;
|
|
7462
7472
|
/**
|
|
7463
7473
|
* Set a memory's People Nearby visibility (and optionally its twin opt-in).
|
|
7464
7474
|
*
|
|
@@ -7500,6 +7510,12 @@ declare function getUnfiledVaultMemoriesOp(ctx: VaultMemoryOperationsContext): P
|
|
|
7500
7510
|
* older version (including pre-v37 rows, read as version 0) is then re-extracted
|
|
7501
7511
|
* by the next sweep, so topic-quality improvements propagate across the existing
|
|
7502
7512
|
* vault. The worker's `limit` drains that re-extraction across sweeps.
|
|
7513
|
+
*
|
|
7514
|
+
* Bumping this is a WHOLE-VAULT re-extraction: the gate is unconditional across
|
|
7515
|
+
* every stamped row, and `stampTopicsExtractedAtOp` stamps this version on every
|
|
7516
|
+
* healthy row, so a bump sends each user's entire extracted vault back to the
|
|
7517
|
+
* LLM. Never reach for it to repair a subset — see the pre-v42-restore repair in
|
|
7518
|
+
* {@link getMemoriesNeedingTopicExtractionOp}, which targets the damaged rows.
|
|
7503
7519
|
*/
|
|
7504
7520
|
declare const TOPICS_EXTRACTION_VERSION = 3;
|
|
7505
7521
|
/**
|
|
@@ -7512,9 +7528,10 @@ interface MemoriesNeedingTopicExtraction {
|
|
|
7512
7528
|
* Memories to run LLM topic extraction on (decrypted): never-extracted rows
|
|
7513
7529
|
* with no entity links, plus stamped rows edited since their last pass
|
|
7514
7530
|
* (`updated_at` > `topics_extracted_at`) or extracted under an older
|
|
7515
|
-
* `topics_extracted_version` than {@link TOPICS_EXTRACTION_VERSION}
|
|
7516
|
-
*
|
|
7517
|
-
*
|
|
7531
|
+
* `topics_extracted_version` than {@link TOPICS_EXTRACTION_VERSION}, plus the
|
|
7532
|
+
* pre-v42-restore repair: a stamped row left with neither links nor a `topics`
|
|
7533
|
+
* record, which no no-LLM bucket can reach. Edited / stale-version rows come
|
|
7534
|
+
* first (they get priority under `limit`), each group newest-created first.
|
|
7518
7535
|
*/
|
|
7519
7536
|
pending: StoredVaultMemory[];
|
|
7520
7537
|
/**
|
|
@@ -7566,6 +7583,11 @@ interface MemoriesNeedingTopicExtraction {
|
|
|
7566
7583
|
* between the record and the index and never re-derive them. That's why the
|
|
7567
7584
|
* ownership filter lives in the partition below rather than in the query: a
|
|
7568
7585
|
* restored curated memory is exactly the row whose index must be rebuilt.
|
|
7586
|
+
*
|
|
7587
|
+
* NOT purely a read: a curated row with no `topics` record AND no usable link is
|
|
7588
|
+
* a contradiction only a pre-v42 restore produces, and this is the one place
|
|
7589
|
+
* that can see all three facts at once, so it clears the flag there (capped by
|
|
7590
|
+
* `limit`) before returning. See the branch for why that's safe.
|
|
7569
7591
|
*/
|
|
7570
7592
|
declare function getMemoriesNeedingTopicExtractionOp(ctx: VaultMemoryOperationsContext, options?: {
|
|
7571
7593
|
limit?: number;
|
package/dist/react/index.d.ts
CHANGED
|
@@ -7457,8 +7457,18 @@ declare function setMemoryEntitiesOp(ctx: VaultMemoryOperationsContext, memoryId
|
|
|
7457
7457
|
* see the schema note. This op's version-invalidation trick is the reason the
|
|
7458
7458
|
* earlier plan to exclude them from sync was dropped, and it's the last piece
|
|
7459
7459
|
* that has to move before they can go.
|
|
7460
|
+
*
|
|
7461
|
+
* `options.unlessTopicsRecorded` declines the reset when the row already has a
|
|
7462
|
+
* `topics` record, re-checked INSIDE the serialized writer. Only the repair path
|
|
7463
|
+
* in {@link getMemoriesNeedingTopicExtractionOp} passes it: that path clears the
|
|
7464
|
+
* flag off rows whose curation is provably empty, and a `setMemoryEntitiesOp`
|
|
7465
|
+
* committing in the gap would have written a real record the autotagger must not
|
|
7466
|
+
* be handed. The user-facing reset leaves it off — resetting a memory that HAS
|
|
7467
|
+
* curated topics is the whole point there.
|
|
7460
7468
|
*/
|
|
7461
|
-
declare function clearMemoryTopicsOverrideOp(ctx: VaultMemoryOperationsContext, memoryId: string
|
|
7469
|
+
declare function clearMemoryTopicsOverrideOp(ctx: VaultMemoryOperationsContext, memoryId: string, options?: {
|
|
7470
|
+
unlessTopicsRecorded?: boolean;
|
|
7471
|
+
}): Promise<boolean>;
|
|
7462
7472
|
/**
|
|
7463
7473
|
* Set a memory's People Nearby visibility (and optionally its twin opt-in).
|
|
7464
7474
|
*
|
|
@@ -7500,6 +7510,12 @@ declare function getUnfiledVaultMemoriesOp(ctx: VaultMemoryOperationsContext): P
|
|
|
7500
7510
|
* older version (including pre-v37 rows, read as version 0) is then re-extracted
|
|
7501
7511
|
* by the next sweep, so topic-quality improvements propagate across the existing
|
|
7502
7512
|
* vault. The worker's `limit` drains that re-extraction across sweeps.
|
|
7513
|
+
*
|
|
7514
|
+
* Bumping this is a WHOLE-VAULT re-extraction: the gate is unconditional across
|
|
7515
|
+
* every stamped row, and `stampTopicsExtractedAtOp` stamps this version on every
|
|
7516
|
+
* healthy row, so a bump sends each user's entire extracted vault back to the
|
|
7517
|
+
* LLM. Never reach for it to repair a subset — see the pre-v42-restore repair in
|
|
7518
|
+
* {@link getMemoriesNeedingTopicExtractionOp}, which targets the damaged rows.
|
|
7503
7519
|
*/
|
|
7504
7520
|
declare const TOPICS_EXTRACTION_VERSION = 3;
|
|
7505
7521
|
/**
|
|
@@ -7512,9 +7528,10 @@ interface MemoriesNeedingTopicExtraction {
|
|
|
7512
7528
|
* Memories to run LLM topic extraction on (decrypted): never-extracted rows
|
|
7513
7529
|
* with no entity links, plus stamped rows edited since their last pass
|
|
7514
7530
|
* (`updated_at` > `topics_extracted_at`) or extracted under an older
|
|
7515
|
-
* `topics_extracted_version` than {@link TOPICS_EXTRACTION_VERSION}
|
|
7516
|
-
*
|
|
7517
|
-
*
|
|
7531
|
+
* `topics_extracted_version` than {@link TOPICS_EXTRACTION_VERSION}, plus the
|
|
7532
|
+
* pre-v42-restore repair: a stamped row left with neither links nor a `topics`
|
|
7533
|
+
* record, which no no-LLM bucket can reach. Edited / stale-version rows come
|
|
7534
|
+
* first (they get priority under `limit`), each group newest-created first.
|
|
7518
7535
|
*/
|
|
7519
7536
|
pending: StoredVaultMemory[];
|
|
7520
7537
|
/**
|
|
@@ -7566,6 +7583,11 @@ interface MemoriesNeedingTopicExtraction {
|
|
|
7566
7583
|
* between the record and the index and never re-derive them. That's why the
|
|
7567
7584
|
* ownership filter lives in the partition below rather than in the query: a
|
|
7568
7585
|
* restored curated memory is exactly the row whose index must be rebuilt.
|
|
7586
|
+
*
|
|
7587
|
+
* NOT purely a read: a curated row with no `topics` record AND no usable link is
|
|
7588
|
+
* a contradiction only a pre-v42 restore produces, and this is the one place
|
|
7589
|
+
* that can see all three facts at once, so it clears the flag there (capped by
|
|
7590
|
+
* `limit`) before returning. See the branch for why that's safe.
|
|
7569
7591
|
*/
|
|
7570
7592
|
declare function getMemoriesNeedingTopicExtractionOp(ctx: VaultMemoryOperationsContext, options?: {
|
|
7571
7593
|
limit?: number;
|
package/dist/react/index.mjs
CHANGED
|
@@ -161,7 +161,7 @@ import {
|
|
|
161
161
|
updateVaultMemoryOp,
|
|
162
162
|
useEncryption,
|
|
163
163
|
vaultMemoryToStored
|
|
164
|
-
} from "./chunk-
|
|
164
|
+
} from "./chunk-BS7C4CUW.mjs";
|
|
165
165
|
import {
|
|
166
166
|
PiiRedactor,
|
|
167
167
|
createStreamingDeAnonymizer,
|
|
@@ -7490,7 +7490,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
7490
7490
|
content: m.content,
|
|
7491
7491
|
similarity: m.similarity
|
|
7492
7492
|
}));
|
|
7493
|
-
const { consolidateMemory: doConsolidate } = await import("./consolidate-
|
|
7493
|
+
const { consolidateMemory: doConsolidate } = await import("./consolidate-IFIKT25Z.mjs");
|
|
7494
7494
|
const decision = await doConsolidate(trimmed, candidates, consolidateOptions);
|
|
7495
7495
|
if (decision.action === "create") return null;
|
|
7496
7496
|
if (decision.action === "supersede" && decision.content) {
|