@anuma/sdk 3.13.2 → 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/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/{consolidate-AURTG64H.mjs → consolidate-KASO7JDS.mjs} +7 -5
- package/dist/expo/index.cjs +19 -7
- package/dist/expo/index.d.mts +14 -4
- package/dist/expo/index.d.ts +14 -4
- package/dist/expo/index.mjs +13 -3
- package/dist/react/{chunk-XXCZVG4Z.mjs → chunk-BAJL46NX.mjs} +1 -1
- package/dist/react/{consolidate-R6FH7XMV.mjs → consolidate-IFIKT25Z.mjs} +7 -5
- package/dist/react/index.cjs +19 -7
- package/dist/react/index.d.mts +14 -4
- package/dist/react/index.d.ts +14 -4
- package/dist/react/index.mjs +14 -4
- package/dist/react/{recall-KTJCUAXN.mjs → recall-R3VX2UST.mjs} +1 -1
- package/dist/server/{consolidate-4VEAS3YN.mjs → consolidate-GRMEDWKK.mjs} +7 -5
- package/dist/server/index.cjs +19 -7
- package/dist/server/index.d.mts +14 -4
- package/dist/server/index.d.ts +14 -4
- package/dist/server/index.mjs +13 -3
- package/package.json +2 -2
|
@@ -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
|
@@ -8847,19 +8847,21 @@ A "memory" is a self-contained natural-language fact about the user. Multiple me
|
|
|
8847
8847
|
Decide one of four actions:
|
|
8848
8848
|
|
|
8849
8849
|
- "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.
|
|
8850
|
+
- "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".
|
|
8851
|
+
- "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.
|
|
8852
|
+
- "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
8853
|
|
|
8854
8854
|
RULES (carry these strictly):
|
|
8855
8855
|
|
|
8856
8856
|
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.
|
|
8857
|
+
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
8858
|
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
8859
|
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
8860
|
4. EVENTS vs STANDING STATE.
|
|
8860
8861
|
- 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.
|
|
8862
|
+
- 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.
|
|
8863
|
+
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.
|
|
8864
|
+
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
8865
|
|
|
8864
8866
|
OUTPUT \u2014 strict JSON, no prose:
|
|
8865
8867
|
{
|
|
@@ -18265,7 +18267,8 @@ function configMatches(a, b) {
|
|
|
18265
18267
|
return a.redacted === b.redacted && a.facetsSignature === b.facetsSignature && (a.reviewedMemoryIdsSignature ?? "") === b.reviewedMemoryIdsSignature && a.scopes.length === b.scopes.length && a.scopes.every((s, i) => s === b.scopes[i]);
|
|
18266
18268
|
}
|
|
18267
18269
|
function reviewedMemoryIdsSignature(ids) {
|
|
18268
|
-
if (ids === void 0
|
|
18270
|
+
if (ids === void 0) return "";
|
|
18271
|
+
if (ids.length === 0) return "\0gated-empty";
|
|
18269
18272
|
return [...new Set(ids)].sort().join("\n");
|
|
18270
18273
|
}
|
|
18271
18274
|
function facetsSignature(facets) {
|
|
@@ -18375,7 +18378,16 @@ async function synthesizeFacet(facet, ctx, options, prior) {
|
|
|
18375
18378
|
const factTypeWeights = { ...DEFAULT_PROFILE_FACT_TYPE_WEIGHTS, ...options.factTypeWeights };
|
|
18376
18379
|
const proofCountAlpha = options.proofCountAlpha ?? DEFAULT_PROFILE_PROOF_ALPHA;
|
|
18377
18380
|
const reviewed = options.reviewedMemoryIds;
|
|
18378
|
-
const hasReviewGate = reviewed !== void 0
|
|
18381
|
+
const hasReviewGate = reviewed !== void 0;
|
|
18382
|
+
if (hasReviewGate && reviewed.length === 0) {
|
|
18383
|
+
return {
|
|
18384
|
+
key: facet.key,
|
|
18385
|
+
label: facet.label,
|
|
18386
|
+
text: "",
|
|
18387
|
+
sourceMemoryIds: [],
|
|
18388
|
+
generatedAt: Date.now()
|
|
18389
|
+
};
|
|
18390
|
+
}
|
|
18379
18391
|
const recalled = await recall(facet.query, ctx, {
|
|
18380
18392
|
scopes,
|
|
18381
18393
|
limit: hasReviewGate ? RECALL_MAX_LIMIT : limit,
|
package/dist/react/index.d.mts
CHANGED
|
@@ -8949,10 +8949,20 @@ interface SynthesizeProfileOptions extends PortalLlmAuth {
|
|
|
8949
8949
|
*/
|
|
8950
8950
|
proofCountAlpha?: number;
|
|
8951
8951
|
/**
|
|
8952
|
-
*
|
|
8953
|
-
* before the LLM runs
|
|
8954
|
-
*
|
|
8955
|
-
* no
|
|
8952
|
+
* Publish-review gate: when SUPPLIED, each facet's recalled evidence is
|
|
8953
|
+
* intersected with this id set before the LLM runs, so synthesis can only draw
|
|
8954
|
+
* on memories the user approved for publication. Empty intersection → empty
|
|
8955
|
+
* section (legitimate no-evidence), not a stale fallback.
|
|
8956
|
+
*
|
|
8957
|
+
* Pass the user's published set (e.g. `getAllVaultMemoriesOp(ctx, { visibility:
|
|
8958
|
+
* ["public"] })`) to keep a published profile derivable only from published
|
|
8959
|
+
* memories — People Nearby's two-tier model treats `private` memories as never
|
|
8960
|
+
* leaving the device, and a summary derived from them is a derivative that does.
|
|
8961
|
+
*
|
|
8962
|
+
* `[]` means "nothing approved" and gates everything OUT (no recall, no LLM
|
|
8963
|
+
* call, empty sections). **Omitting the field is the only way to run ungated**
|
|
8964
|
+
* — that asymmetry is deliberate, so a caller computing a published set can
|
|
8965
|
+
* never accidentally disable the gate by finding it empty.
|
|
8956
8966
|
*/
|
|
8957
8967
|
reviewedMemoryIds?: readonly string[];
|
|
8958
8968
|
}
|
package/dist/react/index.d.ts
CHANGED
|
@@ -8949,10 +8949,20 @@ interface SynthesizeProfileOptions extends PortalLlmAuth {
|
|
|
8949
8949
|
*/
|
|
8950
8950
|
proofCountAlpha?: number;
|
|
8951
8951
|
/**
|
|
8952
|
-
*
|
|
8953
|
-
* before the LLM runs
|
|
8954
|
-
*
|
|
8955
|
-
* no
|
|
8952
|
+
* Publish-review gate: when SUPPLIED, each facet's recalled evidence is
|
|
8953
|
+
* intersected with this id set before the LLM runs, so synthesis can only draw
|
|
8954
|
+
* on memories the user approved for publication. Empty intersection → empty
|
|
8955
|
+
* section (legitimate no-evidence), not a stale fallback.
|
|
8956
|
+
*
|
|
8957
|
+
* Pass the user's published set (e.g. `getAllVaultMemoriesOp(ctx, { visibility:
|
|
8958
|
+
* ["public"] })`) to keep a published profile derivable only from published
|
|
8959
|
+
* memories — People Nearby's two-tier model treats `private` memories as never
|
|
8960
|
+
* leaving the device, and a summary derived from them is a derivative that does.
|
|
8961
|
+
*
|
|
8962
|
+
* `[]` means "nothing approved" and gates everything OUT (no recall, no LLM
|
|
8963
|
+
* call, empty sections). **Omitting the field is the only way to run ungated**
|
|
8964
|
+
* — that asymmetry is deliberate, so a caller computing a published set can
|
|
8965
|
+
* never accidentally disable the gate by finding it empty.
|
|
8956
8966
|
*/
|
|
8957
8967
|
reviewedMemoryIds?: readonly string[];
|
|
8958
8968
|
}
|
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-BAJL46NX.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) {
|
|
@@ -9036,7 +9036,8 @@ function configMatches(a, b) {
|
|
|
9036
9036
|
return a.redacted === b.redacted && a.facetsSignature === b.facetsSignature && (a.reviewedMemoryIdsSignature ?? "") === b.reviewedMemoryIdsSignature && a.scopes.length === b.scopes.length && a.scopes.every((s, i) => s === b.scopes[i]);
|
|
9037
9037
|
}
|
|
9038
9038
|
function reviewedMemoryIdsSignature(ids) {
|
|
9039
|
-
if (ids === void 0
|
|
9039
|
+
if (ids === void 0) return "";
|
|
9040
|
+
if (ids.length === 0) return "\0gated-empty";
|
|
9040
9041
|
return [...new Set(ids)].sort().join("\n");
|
|
9041
9042
|
}
|
|
9042
9043
|
function facetsSignature(facets) {
|
|
@@ -9146,7 +9147,16 @@ async function synthesizeFacet(facet, ctx, options, prior) {
|
|
|
9146
9147
|
const factTypeWeights = { ...DEFAULT_PROFILE_FACT_TYPE_WEIGHTS, ...options.factTypeWeights };
|
|
9147
9148
|
const proofCountAlpha = options.proofCountAlpha ?? DEFAULT_PROFILE_PROOF_ALPHA;
|
|
9148
9149
|
const reviewed = options.reviewedMemoryIds;
|
|
9149
|
-
const hasReviewGate = reviewed !== void 0
|
|
9150
|
+
const hasReviewGate = reviewed !== void 0;
|
|
9151
|
+
if (hasReviewGate && reviewed.length === 0) {
|
|
9152
|
+
return {
|
|
9153
|
+
key: facet.key,
|
|
9154
|
+
label: facet.label,
|
|
9155
|
+
text: "",
|
|
9156
|
+
sourceMemoryIds: [],
|
|
9157
|
+
generatedAt: Date.now()
|
|
9158
|
+
};
|
|
9159
|
+
}
|
|
9150
9160
|
const recalled = await recall(facet.query, ctx, {
|
|
9151
9161
|
scopes,
|
|
9152
9162
|
limit: hasReviewGate ? RECALL_MAX_LIMIT : limit,
|
|
@@ -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/server/index.cjs
CHANGED
|
@@ -23361,19 +23361,21 @@ A "memory" is a self-contained natural-language fact about the user. Multiple me
|
|
|
23361
23361
|
Decide one of four actions:
|
|
23362
23362
|
|
|
23363
23363
|
- "create": the new memory describes a distinct fact not covered by any existing memory. Write it as new.
|
|
23364
|
-
- "update": the new memory describes the SAME FACET as exactly one existing memory
|
|
23365
|
-
- "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.
|
|
23366
|
-
- "noop": the new memory is already fully captured by an existing memory \u2014 same facet, no new information. Skip the write.
|
|
23364
|
+
- "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".
|
|
23365
|
+
- "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.
|
|
23366
|
+
- "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.
|
|
23367
23367
|
|
|
23368
23368
|
RULES (carry these strictly):
|
|
23369
23369
|
|
|
23370
23370
|
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.
|
|
23371
|
+
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.
|
|
23371
23372
|
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.
|
|
23372
23373
|
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.
|
|
23373
23374
|
4. EVENTS vs STANDING STATE.
|
|
23374
23375
|
- 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.
|
|
23375
|
-
- A STANDING ATTRIBUTE (an ongoing state: where
|
|
23376
|
-
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.
|
|
23376
|
+
- 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.
|
|
23377
|
+
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.
|
|
23378
|
+
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.
|
|
23377
23379
|
|
|
23378
23380
|
OUTPUT \u2014 strict JSON, no prose:
|
|
23379
23381
|
{
|
|
@@ -29956,7 +29958,8 @@ function configMatches(a, b) {
|
|
|
29956
29958
|
return a.redacted === b.redacted && a.facetsSignature === b.facetsSignature && (a.reviewedMemoryIdsSignature ?? "") === b.reviewedMemoryIdsSignature && a.scopes.length === b.scopes.length && a.scopes.every((s, i) => s === b.scopes[i]);
|
|
29957
29959
|
}
|
|
29958
29960
|
function reviewedMemoryIdsSignature(ids) {
|
|
29959
|
-
if (ids === void 0
|
|
29961
|
+
if (ids === void 0) return "";
|
|
29962
|
+
if (ids.length === 0) return "\0gated-empty";
|
|
29960
29963
|
return [...new Set(ids)].sort().join("\n");
|
|
29961
29964
|
}
|
|
29962
29965
|
function facetsSignature(facets) {
|
|
@@ -30066,7 +30069,16 @@ async function synthesizeFacet(facet, ctx, options, prior) {
|
|
|
30066
30069
|
const factTypeWeights = { ...DEFAULT_PROFILE_FACT_TYPE_WEIGHTS, ...options.factTypeWeights };
|
|
30067
30070
|
const proofCountAlpha = options.proofCountAlpha ?? DEFAULT_PROFILE_PROOF_ALPHA;
|
|
30068
30071
|
const reviewed = options.reviewedMemoryIds;
|
|
30069
|
-
const hasReviewGate = reviewed !== void 0
|
|
30072
|
+
const hasReviewGate = reviewed !== void 0;
|
|
30073
|
+
if (hasReviewGate && reviewed.length === 0) {
|
|
30074
|
+
return {
|
|
30075
|
+
key: facet.key,
|
|
30076
|
+
label: facet.label,
|
|
30077
|
+
text: "",
|
|
30078
|
+
sourceMemoryIds: [],
|
|
30079
|
+
generatedAt: Date.now()
|
|
30080
|
+
};
|
|
30081
|
+
}
|
|
30070
30082
|
const recalled = await recall(facet.query, ctx, {
|
|
30071
30083
|
scopes,
|
|
30072
30084
|
limit: hasReviewGate ? RECALL_MAX_LIMIT : limit,
|
package/dist/server/index.d.mts
CHANGED
|
@@ -8356,10 +8356,20 @@ interface SynthesizeProfileOptions extends PortalLlmAuth {
|
|
|
8356
8356
|
*/
|
|
8357
8357
|
proofCountAlpha?: number;
|
|
8358
8358
|
/**
|
|
8359
|
-
*
|
|
8360
|
-
* before the LLM runs
|
|
8361
|
-
*
|
|
8362
|
-
* no
|
|
8359
|
+
* Publish-review gate: when SUPPLIED, each facet's recalled evidence is
|
|
8360
|
+
* intersected with this id set before the LLM runs, so synthesis can only draw
|
|
8361
|
+
* on memories the user approved for publication. Empty intersection → empty
|
|
8362
|
+
* section (legitimate no-evidence), not a stale fallback.
|
|
8363
|
+
*
|
|
8364
|
+
* Pass the user's published set (e.g. `getAllVaultMemoriesOp(ctx, { visibility:
|
|
8365
|
+
* ["public"] })`) to keep a published profile derivable only from published
|
|
8366
|
+
* memories — People Nearby's two-tier model treats `private` memories as never
|
|
8367
|
+
* leaving the device, and a summary derived from them is a derivative that does.
|
|
8368
|
+
*
|
|
8369
|
+
* `[]` means "nothing approved" and gates everything OUT (no recall, no LLM
|
|
8370
|
+
* call, empty sections). **Omitting the field is the only way to run ungated**
|
|
8371
|
+
* — that asymmetry is deliberate, so a caller computing a published set can
|
|
8372
|
+
* never accidentally disable the gate by finding it empty.
|
|
8363
8373
|
*/
|
|
8364
8374
|
reviewedMemoryIds?: readonly string[];
|
|
8365
8375
|
}
|
package/dist/server/index.d.ts
CHANGED
|
@@ -8356,10 +8356,20 @@ interface SynthesizeProfileOptions extends PortalLlmAuth {
|
|
|
8356
8356
|
*/
|
|
8357
8357
|
proofCountAlpha?: number;
|
|
8358
8358
|
/**
|
|
8359
|
-
*
|
|
8360
|
-
* before the LLM runs
|
|
8361
|
-
*
|
|
8362
|
-
* no
|
|
8359
|
+
* Publish-review gate: when SUPPLIED, each facet's recalled evidence is
|
|
8360
|
+
* intersected with this id set before the LLM runs, so synthesis can only draw
|
|
8361
|
+
* on memories the user approved for publication. Empty intersection → empty
|
|
8362
|
+
* section (legitimate no-evidence), not a stale fallback.
|
|
8363
|
+
*
|
|
8364
|
+
* Pass the user's published set (e.g. `getAllVaultMemoriesOp(ctx, { visibility:
|
|
8365
|
+
* ["public"] })`) to keep a published profile derivable only from published
|
|
8366
|
+
* memories — People Nearby's two-tier model treats `private` memories as never
|
|
8367
|
+
* leaving the device, and a summary derived from them is a derivative that does.
|
|
8368
|
+
*
|
|
8369
|
+
* `[]` means "nothing approved" and gates everything OUT (no recall, no LLM
|
|
8370
|
+
* call, empty sections). **Omitting the field is the only way to run ungated**
|
|
8371
|
+
* — that asymmetry is deliberate, so a caller computing a published set can
|
|
8372
|
+
* never accidentally disable the gate by finding it empty.
|
|
8363
8373
|
*/
|
|
8364
8374
|
reviewedMemoryIds?: readonly string[];
|
|
8365
8375
|
}
|
package/dist/server/index.mjs
CHANGED
|
@@ -5445,7 +5445,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
5445
5445
|
content: m.content,
|
|
5446
5446
|
similarity: m.similarity
|
|
5447
5447
|
}));
|
|
5448
|
-
const { consolidateMemory: doConsolidate } = await import("./consolidate-
|
|
5448
|
+
const { consolidateMemory: doConsolidate } = await import("./consolidate-GRMEDWKK.mjs");
|
|
5449
5449
|
const decision = await doConsolidate(trimmed, candidates, consolidateOptions);
|
|
5450
5450
|
if (decision.action === "create") return null;
|
|
5451
5451
|
if (decision.action === "supersede" && decision.content) {
|
|
@@ -6991,7 +6991,8 @@ function configMatches(a, b) {
|
|
|
6991
6991
|
return a.redacted === b.redacted && a.facetsSignature === b.facetsSignature && (a.reviewedMemoryIdsSignature ?? "") === b.reviewedMemoryIdsSignature && a.scopes.length === b.scopes.length && a.scopes.every((s, i) => s === b.scopes[i]);
|
|
6992
6992
|
}
|
|
6993
6993
|
function reviewedMemoryIdsSignature(ids) {
|
|
6994
|
-
if (ids === void 0
|
|
6994
|
+
if (ids === void 0) return "";
|
|
6995
|
+
if (ids.length === 0) return "\0gated-empty";
|
|
6995
6996
|
return [...new Set(ids)].sort().join("\n");
|
|
6996
6997
|
}
|
|
6997
6998
|
function facetsSignature(facets) {
|
|
@@ -7101,7 +7102,16 @@ async function synthesizeFacet(facet, ctx, options, prior) {
|
|
|
7101
7102
|
const factTypeWeights = { ...DEFAULT_PROFILE_FACT_TYPE_WEIGHTS, ...options.factTypeWeights };
|
|
7102
7103
|
const proofCountAlpha = options.proofCountAlpha ?? DEFAULT_PROFILE_PROOF_ALPHA;
|
|
7103
7104
|
const reviewed = options.reviewedMemoryIds;
|
|
7104
|
-
const hasReviewGate = reviewed !== void 0
|
|
7105
|
+
const hasReviewGate = reviewed !== void 0;
|
|
7106
|
+
if (hasReviewGate && reviewed.length === 0) {
|
|
7107
|
+
return {
|
|
7108
|
+
key: facet.key,
|
|
7109
|
+
label: facet.label,
|
|
7110
|
+
text: "",
|
|
7111
|
+
sourceMemoryIds: [],
|
|
7112
|
+
generatedAt: Date.now()
|
|
7113
|
+
};
|
|
7114
|
+
}
|
|
7105
7115
|
const recalled = await recall(facet.query, ctx, {
|
|
7106
7116
|
scopes,
|
|
7107
7117
|
limit: hasReviewGate ? RECALL_MAX_LIMIT : limit,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@anuma/sdk",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -159,7 +159,7 @@
|
|
|
159
159
|
"homepage": "https://github.com/anuma-ai/sdk#readme",
|
|
160
160
|
"packageManager": "pnpm@10.23.0",
|
|
161
161
|
"dependencies": {
|
|
162
|
-
"@anuma/portal": "1.0.0-next.
|
|
162
|
+
"@anuma/portal": "1.0.0-next.20260728181242",
|
|
163
163
|
"@babel/parser": "^7.29.2",
|
|
164
164
|
"@babel/types": "^7.29.0",
|
|
165
165
|
"ai": "6.0.202",
|