@indexnetwork/protocol 3.8.0-rc.283.1 → 3.9.0-rc.284.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.
@@ -2,35 +2,43 @@ import { z } from "zod";
2
2
  declare const premiseItemSchema: z.ZodObject<{
3
3
  text: z.ZodString;
4
4
  tier: z.ZodEnum<["assertive", "contextual"]>;
5
+ validityDays: z.ZodNullable<z.ZodNumber>;
5
6
  }, "strip", z.ZodTypeAny, {
6
7
  text: string;
7
8
  tier: "assertive" | "contextual";
9
+ validityDays: number | null;
8
10
  }, {
9
11
  text: string;
10
12
  tier: "assertive" | "contextual";
13
+ validityDays: number | null;
11
14
  }>;
12
15
  declare const responseFormat: z.ZodObject<{
13
16
  reasoning: z.ZodString;
14
17
  premises: z.ZodArray<z.ZodObject<{
15
18
  text: z.ZodString;
16
19
  tier: z.ZodEnum<["assertive", "contextual"]>;
20
+ validityDays: z.ZodNullable<z.ZodNumber>;
17
21
  }, "strip", z.ZodTypeAny, {
18
22
  text: string;
19
23
  tier: "assertive" | "contextual";
24
+ validityDays: number | null;
20
25
  }, {
21
26
  text: string;
22
27
  tier: "assertive" | "contextual";
28
+ validityDays: number | null;
23
29
  }>, "many">;
24
30
  }, "strip", z.ZodTypeAny, {
25
31
  premises: {
26
32
  text: string;
27
33
  tier: "assertive" | "contextual";
34
+ validityDays: number | null;
28
35
  }[];
29
36
  reasoning: string;
30
37
  }, {
31
38
  premises: {
32
39
  text: string;
33
40
  tier: "assertive" | "contextual";
41
+ validityDays: number | null;
34
42
  }[];
35
43
  reasoning: string;
36
44
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"premise.decomposer.d.ts","sourceRoot":"/","sources":["premise/premise.decomposer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAmExB,QAAA,MAAM,iBAAiB;;;;;;;;;EAKrB,CAAC;AAEH,QAAA,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;EAOlB,CAAC;AAEH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AACrE,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAElE;;;GAGG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,KAAK,CAAqE;;IAUrE,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC;CAgBrE"}
1
+ {"version":3,"file":"premise.decomposer.d.ts","sourceRoot":"/","sources":["premise/premise.decomposer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA8ExB,QAAA,MAAM,iBAAiB;;;;;;;;;;;;EAQrB,CAAC;AAEH,QAAA,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAOlB,CAAC;AAEH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AACrE,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAElE;;;GAGG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,KAAK,CAAqE;;IAUrE,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC;CAgBrE"}
@@ -43,12 +43,23 @@ DECOMPOSITION RULES
43
43
  1. Extract every distinct factual claim about the person
44
44
  2. Convert third-person ("She works at...") to first-person ("I work at...")
45
45
  3. Separate compound statements: "I know Python and Rust" → two premises
46
- 4. Classify each premise:
47
- - \`assertive\` — stable identity facts (role, skills, education, location)
46
+ 4. Capture the FULL breadth of self-description, not just job/title. In particular,
47
+ do not drop:
48
+ - **Skills & expertise** ("I specialize in distributed systems", "I know Rust")
49
+ - **Interests & focus areas** ("I am interested in AI safety", "I care about climate")
50
+ - **Background/narrative context** (education, prior roles, domains, affiliations)
51
+ These map to what a profile would store as interests/skills/context — every such
52
+ fact must surface as its own premise so nothing is lost.
53
+ 5. Classify each premise:
54
+ - \`assertive\` — stable identity facts (role, skills, interests, education, location)
48
55
  - \`contextual\` — temporal/situational (current projects, events, fundraising status)
49
- 5. Skip vague or uninformative statements ("I like stuff", "I'm a person")
50
- 6. Skip desires, requests, or intents ("I'm looking for...", "I want to...") those are intents, not premises
51
- 7. If the input contains NO extractable premises (e.g. just "Yes" or "Hello"), return an empty array
56
+ 6. For \`contextual\` premises, estimate \`validityDays\` how many days the fact is
57
+ likely to remain true from now (e.g. "speaking next week" ~7, "raising a Series A"
58
+ ~120, "currently building X" ~180). Use null for \`assertive\` premises, which
59
+ have no natural expiry.
60
+ 7. Skip vague or uninformative statements ("I like stuff", "I'm a person")
61
+ 8. Skip desires, requests, or intents ("I'm looking for...", "I want to...") — those are intents, not premises
62
+ 9. If the input contains NO extractable premises (e.g. just "Yes" or "Hello"), return an empty array
52
63
 
53
64
  ═══════════════════════════════════════════════════
54
65
  EXAMPLES
@@ -56,18 +67,18 @@ EXAMPLES
56
67
 
57
68
  Input: "I'm a climate tech founder based in Berlin. I have a PhD in renewable energy systems and I'm currently raising Series A."
58
69
  Output:
59
- 1. "I am a climate tech founder" (assertive)
60
- 2. "I am based in Berlin" (assertive)
61
- 3. "I hold a PhD in renewable energy systems" (assertive)
62
- 4. "I am currently raising Series A" (contextual)
70
+ 1. "I am a climate tech founder" (assertive, validityDays: null)
71
+ 2. "I am based in Berlin" (assertive, validityDays: null)
72
+ 3. "I hold a PhD in renewable energy systems" (assertive, validityDays: null)
73
+ 4. "I am currently raising Series A" (contextual, validityDays: 120)
63
74
 
64
75
  Input: "John Doe is a senior ML engineer at Meta in Menlo Park. He has 8 years of experience in NLP and computer vision."
65
76
  Output:
66
- 1. "I am a senior ML engineer" (assertive)
67
- 2. "I work at Meta" (assertive)
68
- 3. "I am based in Menlo Park" (assertive)
69
- 4. "I have 8 years of experience in NLP" (assertive)
70
- 5. "I have experience in computer vision" (assertive)
77
+ 1. "I am a senior ML engineer" (assertive, validityDays: null)
78
+ 2. "I work at Meta" (assertive, validityDays: null)
79
+ 3. "I am based in Menlo Park" (assertive, validityDays: null)
80
+ 4. "I have 8 years of experience in NLP" (assertive, validityDays: null)
81
+ 5. "I have experience in computer vision" (assertive, validityDays: null)
71
82
 
72
83
  Input: "Yes, create my profile"
73
84
  Output: [] (empty — no premises)
@@ -75,6 +86,7 @@ Output: [] (empty — no premises)
75
86
  const premiseItemSchema = z.object({
76
87
  text: z.string().describe("The premise text in first person (e.g. 'I am a software engineer at Google')"),
77
88
  tier: z.enum(["assertive", "contextual"]).describe("assertive = stable identity fact; contextual = temporal/situational"),
89
+ validityDays: z.number().int().positive().nullable().describe("For contextual premises: estimated days the fact remains true from now (its validity window). null for assertive premises, which do not expire."),
78
90
  });
79
91
  const responseFormat = z.object({
80
92
  reasoning: z.string().describe("Brief analysis of what factual claims can be extracted from the input"),
@@ -1 +1 @@
1
- {"version":3,"file":"premise.decomposer.js","sourceRoot":"/","sources":["premise/premise.decomposer.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACvE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,4CAA4C,CAAC;AAC5E,OAAO,EAAE,KAAK,EAAE,MAAM,wCAAwC,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAExE,MAAM,MAAM,GAAG,cAAc,CAAC,mBAAmB,CAAC,CAAC;AAEnD,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyDpB,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8EAA8E,CAAC;IACzG,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC,CAAC,QAAQ,CAChD,qEAAqE,CACtE;CACF,CAAC,CAAC;AAEH,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAC5B,uEAAuE,CACxE;IACD,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,QAAQ,CAC3C,iFAAiF,CAClF;CACF,CAAC,CAAC;AAKH;;;GAGG;AACH,MAAM,OAAO,iBAAiB;IAG5B;QACE,MAAM,KAAK,GAAG,WAAW,CAAC,mBAAmB,CAAC,CAAC;QAC/C,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,oBAAoB,CAAC,cAAc,EAAE;YACtD,IAAI,EAAE,oBAAoB;SAC3B,CAAC,CAAC;IACL,CAAC;IAGY,AAAN,KAAK,CAAC,MAAM,CAAC,KAAa;QAC/B,MAAM,CAAC,OAAO,CAAC,iDAAiD,KAAK,CAAC,MAAM,SAAS,CAAC,CAAC;QAEvF,MAAM,MAAM,GAAG,6DAA6D,KAAK,EAAE,CAAC;QAEpF,MAAM,QAAQ,GAAG;YACf,IAAI,aAAa,CAAC,YAAY,CAAC;YAC/B,IAAI,YAAY,CAAC,MAAM,CAAC;SACzB,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QACjE,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAE5C,MAAM,CAAC,OAAO,CAAC,wCAAwC,MAAM,CAAC,QAAQ,CAAC,MAAM,aAAa,CAAC,CAAC;QAC5F,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AAhBc;IADZ,KAAK,EAAE;;;;+CAgBP","sourcesContent":["import { HumanMessage, SystemMessage } from \"@langchain/core/messages\";\nimport { z } from \"zod\";\nimport { protocolLogger } from \"../shared/observability/protocol.logger.js\";\nimport { Timed } from \"../shared/observability/performance.js\";\nimport { createModel } from \"../shared/agent/model.config.js\";\nimport { invokeWithAbortSignal } from \"../shared/agent/model-signal.js\";\n\nconst logger = protocolLogger(\"PremiseDecomposer\");\n\nconst systemPrompt = `\nYou are the Premise Decomposer for the Index Network — an intent-driven discovery protocol.\n\nYour job: decompose free-text input about a person into individual, atomic premises.\n\nA premise is a single self-descriptive proposition — a fact someone asserts about themselves.\nEach premise should be:\n1. **Atomic** — one fact per premise, not compound statements\n2. **First-person** — phrased as \"I am...\", \"I work at...\", \"I specialize in...\"\n3. **Self-descriptive** — about the person's identity, role, skills, interests, location, or context\n4. **Non-redundant** — do not repeat the same information in multiple premises\n\n═══════════════════════════════════════════════════\nINPUT TYPES\n═══════════════════════════════════════════════════\n\nYou may receive:\n- **Chat messages**: \"I'm a software engineer at Google, based in SF. I'm interested in AI safety.\"\n- **Bio text**: A paragraph describing someone's background\n- **Scraped content**: LinkedIn/GitHub/Twitter data about someone\n- **Mixed input**: Name, location, and free-text combined\n\n═══════════════════════════════════════════════════\nDECOMPOSITION RULES\n═══════════════════════════════════════════════════\n\n1. Extract every distinct factual claim about the person\n2. Convert third-person (\"She works at...\") to first-person (\"I work at...\")\n3. Separate compound statements: \"I know Python and Rust\" → two premises\n4. Classify each premise:\n - \\`assertive\\` — stable identity facts (role, skills, education, location)\n - \\`contextual\\` — temporal/situational (current projects, events, fundraising status)\n5. Skip vague or uninformative statements (\"I like stuff\", \"I'm a person\")\n6. Skip desires, requests, or intents (\"I'm looking for...\", \"I want to...\") — those are intents, not premises\n7. If the input contains NO extractable premises (e.g. just \"Yes\" or \"Hello\"), return an empty array\n\n═══════════════════════════════════════════════════\nEXAMPLES\n═══════════════════════════════════════════════════\n\nInput: \"I'm a climate tech founder based in Berlin. I have a PhD in renewable energy systems and I'm currently raising Series A.\"\nOutput:\n 1. \"I am a climate tech founder\" (assertive)\n 2. \"I am based in Berlin\" (assertive)\n 3. \"I hold a PhD in renewable energy systems\" (assertive)\n 4. \"I am currently raising Series A\" (contextual)\n\nInput: \"John Doe is a senior ML engineer at Meta in Menlo Park. He has 8 years of experience in NLP and computer vision.\"\nOutput:\n 1. \"I am a senior ML engineer\" (assertive)\n 2. \"I work at Meta\" (assertive)\n 3. \"I am based in Menlo Park\" (assertive)\n 4. \"I have 8 years of experience in NLP\" (assertive)\n 5. \"I have experience in computer vision\" (assertive)\n\nInput: \"Yes, create my profile\"\nOutput: [] (empty — no premises)\n`;\n\nconst premiseItemSchema = z.object({\n text: z.string().describe(\"The premise text in first person (e.g. 'I am a software engineer at Google')\"),\n tier: z.enum([\"assertive\", \"contextual\"]).describe(\n \"assertive = stable identity fact; contextual = temporal/situational\"\n ),\n});\n\nconst responseFormat = z.object({\n reasoning: z.string().describe(\n \"Brief analysis of what factual claims can be extracted from the input\"\n ),\n premises: z.array(premiseItemSchema).describe(\n \"Array of extracted premises. Empty if input contains no self-descriptive facts.\"\n ),\n});\n\nexport type PremiseDecomposerOutput = z.infer<typeof responseFormat>;\nexport type DecomposedPremise = z.infer<typeof premiseItemSchema>;\n\n/**\n * Decomposes free-text input (chat messages, bios, scraped content) into\n * individual atomic premises suitable for the premise graph.\n */\nexport class PremiseDecomposer {\n private model: ReturnType<ReturnType<typeof createModel>[\"withStructuredOutput\"]>;\n\n constructor() {\n const model = createModel(\"premiseDecomposer\");\n this.model = model.withStructuredOutput(responseFormat, {\n name: \"premise_decomposer\",\n });\n }\n\n @Timed()\n public async invoke(input: string): Promise<PremiseDecomposerOutput> {\n logger.verbose(`[PremiseDecomposer.invoke] Decomposing input (${input.length} chars)`);\n\n const prompt = `Decompose the following text into individual premises:\\n\\n${input}`;\n\n const messages = [\n new SystemMessage(systemPrompt),\n new HumanMessage(prompt),\n ];\n\n const result = await invokeWithAbortSignal(this.model, messages);\n const output = responseFormat.parse(result);\n\n logger.verbose(`[PremiseDecomposer.invoke] Extracted ${output.premises.length} premise(s)`);\n return output;\n }\n}\n"]}
1
+ {"version":3,"file":"premise.decomposer.js","sourceRoot":"/","sources":["premise/premise.decomposer.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACvE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,4CAA4C,CAAC;AAC5E,OAAO,EAAE,KAAK,EAAE,MAAM,wCAAwC,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAExE,MAAM,MAAM,GAAG,cAAc,CAAC,mBAAmB,CAAC,CAAC;AAEnD,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoEpB,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8EAA8E,CAAC;IACzG,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC,CAAC,QAAQ,CAChD,qEAAqE,CACtE;IACD,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAC3D,iJAAiJ,CAClJ;CACF,CAAC,CAAC;AAEH,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAC5B,uEAAuE,CACxE;IACD,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,QAAQ,CAC3C,iFAAiF,CAClF;CACF,CAAC,CAAC;AAKH;;;GAGG;AACH,MAAM,OAAO,iBAAiB;IAG5B;QACE,MAAM,KAAK,GAAG,WAAW,CAAC,mBAAmB,CAAC,CAAC;QAC/C,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,oBAAoB,CAAC,cAAc,EAAE;YACtD,IAAI,EAAE,oBAAoB;SAC3B,CAAC,CAAC;IACL,CAAC;IAGY,AAAN,KAAK,CAAC,MAAM,CAAC,KAAa;QAC/B,MAAM,CAAC,OAAO,CAAC,iDAAiD,KAAK,CAAC,MAAM,SAAS,CAAC,CAAC;QAEvF,MAAM,MAAM,GAAG,6DAA6D,KAAK,EAAE,CAAC;QAEpF,MAAM,QAAQ,GAAG;YACf,IAAI,aAAa,CAAC,YAAY,CAAC;YAC/B,IAAI,YAAY,CAAC,MAAM,CAAC;SACzB,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QACjE,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAE5C,MAAM,CAAC,OAAO,CAAC,wCAAwC,MAAM,CAAC,QAAQ,CAAC,MAAM,aAAa,CAAC,CAAC;QAC5F,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AAhBc;IADZ,KAAK,EAAE;;;;+CAgBP","sourcesContent":["import { HumanMessage, SystemMessage } from \"@langchain/core/messages\";\nimport { z } from \"zod\";\nimport { protocolLogger } from \"../shared/observability/protocol.logger.js\";\nimport { Timed } from \"../shared/observability/performance.js\";\nimport { createModel } from \"../shared/agent/model.config.js\";\nimport { invokeWithAbortSignal } from \"../shared/agent/model-signal.js\";\n\nconst logger = protocolLogger(\"PremiseDecomposer\");\n\nconst systemPrompt = `\nYou are the Premise Decomposer for the Index Network — an intent-driven discovery protocol.\n\nYour job: decompose free-text input about a person into individual, atomic premises.\n\nA premise is a single self-descriptive proposition — a fact someone asserts about themselves.\nEach premise should be:\n1. **Atomic** — one fact per premise, not compound statements\n2. **First-person** — phrased as \"I am...\", \"I work at...\", \"I specialize in...\"\n3. **Self-descriptive** — about the person's identity, role, skills, interests, location, or context\n4. **Non-redundant** — do not repeat the same information in multiple premises\n\n═══════════════════════════════════════════════════\nINPUT TYPES\n═══════════════════════════════════════════════════\n\nYou may receive:\n- **Chat messages**: \"I'm a software engineer at Google, based in SF. I'm interested in AI safety.\"\n- **Bio text**: A paragraph describing someone's background\n- **Scraped content**: LinkedIn/GitHub/Twitter data about someone\n- **Mixed input**: Name, location, and free-text combined\n\n═══════════════════════════════════════════════════\nDECOMPOSITION RULES\n═══════════════════════════════════════════════════\n\n1. Extract every distinct factual claim about the person\n2. Convert third-person (\"She works at...\") to first-person (\"I work at...\")\n3. Separate compound statements: \"I know Python and Rust\" → two premises\n4. Capture the FULL breadth of self-description, not just job/title. In particular,\n do not drop:\n - **Skills & expertise** (\"I specialize in distributed systems\", \"I know Rust\")\n - **Interests & focus areas** (\"I am interested in AI safety\", \"I care about climate\")\n - **Background/narrative context** (education, prior roles, domains, affiliations)\n These map to what a profile would store as interests/skills/context — every such\n fact must surface as its own premise so nothing is lost.\n5. Classify each premise:\n - \\`assertive\\` — stable identity facts (role, skills, interests, education, location)\n - \\`contextual\\` — temporal/situational (current projects, events, fundraising status)\n6. For \\`contextual\\` premises, estimate \\`validityDays\\` — how many days the fact is\n likely to remain true from now (e.g. \"speaking next week\" → ~7, \"raising a Series A\"\n → ~120, \"currently building X\" → ~180). Use null for \\`assertive\\` premises, which\n have no natural expiry.\n7. Skip vague or uninformative statements (\"I like stuff\", \"I'm a person\")\n8. Skip desires, requests, or intents (\"I'm looking for...\", \"I want to...\") — those are intents, not premises\n9. If the input contains NO extractable premises (e.g. just \"Yes\" or \"Hello\"), return an empty array\n\n═══════════════════════════════════════════════════\nEXAMPLES\n═══════════════════════════════════════════════════\n\nInput: \"I'm a climate tech founder based in Berlin. I have a PhD in renewable energy systems and I'm currently raising Series A.\"\nOutput:\n 1. \"I am a climate tech founder\" (assertive, validityDays: null)\n 2. \"I am based in Berlin\" (assertive, validityDays: null)\n 3. \"I hold a PhD in renewable energy systems\" (assertive, validityDays: null)\n 4. \"I am currently raising Series A\" (contextual, validityDays: 120)\n\nInput: \"John Doe is a senior ML engineer at Meta in Menlo Park. He has 8 years of experience in NLP and computer vision.\"\nOutput:\n 1. \"I am a senior ML engineer\" (assertive, validityDays: null)\n 2. \"I work at Meta\" (assertive, validityDays: null)\n 3. \"I am based in Menlo Park\" (assertive, validityDays: null)\n 4. \"I have 8 years of experience in NLP\" (assertive, validityDays: null)\n 5. \"I have experience in computer vision\" (assertive, validityDays: null)\n\nInput: \"Yes, create my profile\"\nOutput: [] (empty — no premises)\n`;\n\nconst premiseItemSchema = z.object({\n text: z.string().describe(\"The premise text in first person (e.g. 'I am a software engineer at Google')\"),\n tier: z.enum([\"assertive\", \"contextual\"]).describe(\n \"assertive = stable identity fact; contextual = temporal/situational\"\n ),\n validityDays: z.number().int().positive().nullable().describe(\n \"For contextual premises: estimated days the fact remains true from now (its validity window). null for assertive premises, which do not expire.\"\n ),\n});\n\nconst responseFormat = z.object({\n reasoning: z.string().describe(\n \"Brief analysis of what factual claims can be extracted from the input\"\n ),\n premises: z.array(premiseItemSchema).describe(\n \"Array of extracted premises. Empty if input contains no self-descriptive facts.\"\n ),\n});\n\nexport type PremiseDecomposerOutput = z.infer<typeof responseFormat>;\nexport type DecomposedPremise = z.infer<typeof premiseItemSchema>;\n\n/**\n * Decomposes free-text input (chat messages, bios, scraped content) into\n * individual atomic premises suitable for the premise graph.\n */\nexport class PremiseDecomposer {\n private model: ReturnType<ReturnType<typeof createModel>[\"withStructuredOutput\"]>;\n\n constructor() {\n const model = createModel(\"premiseDecomposer\");\n this.model = model.withStructuredOutput(responseFormat, {\n name: \"premise_decomposer\",\n });\n }\n\n @Timed()\n public async invoke(input: string): Promise<PremiseDecomposerOutput> {\n logger.verbose(`[PremiseDecomposer.invoke] Decomposing input (${input.length} chars)`);\n\n const prompt = `Decompose the following text into individual premises:\\n\\n${input}`;\n\n const messages = [\n new SystemMessage(systemPrompt),\n new HumanMessage(prompt),\n ];\n\n const result = await invokeWithAbortSignal(this.model, messages);\n const output = responseFormat.parse(result);\n\n logger.verbose(`[PremiseDecomposer.invoke] Extracted ${output.premises.length} premise(s)`);\n return output;\n }\n}\n"]}
@@ -31,6 +31,11 @@ export declare class PremiseGraphFactory {
31
31
  analysis: PremiseAnalysis | undefined;
32
32
  embedding: number[] | undefined;
33
33
  premise: import("../shared/interfaces/database.interface.js").PremiseRecord | undefined;
34
+ duplicateOf: {
35
+ premiseId: string;
36
+ assertionText: string;
37
+ similarity: number;
38
+ } | undefined;
34
39
  networkAssignments: {
35
40
  networkId: string;
36
41
  relevancyScore: number;
@@ -58,6 +63,15 @@ export declare class PremiseGraphFactory {
58
63
  analysis?: PremiseAnalysis | import("@langchain/langgraph").OverwriteValue<PremiseAnalysis | undefined> | undefined;
59
64
  embedding?: number[] | import("@langchain/langgraph").OverwriteValue<number[] | undefined> | undefined;
60
65
  premise?: import("../shared/interfaces/database.interface.js").PremiseRecord | import("@langchain/langgraph").OverwriteValue<import("../shared/interfaces/database.interface.js").PremiseRecord | undefined> | undefined;
66
+ duplicateOf?: {
67
+ premiseId: string;
68
+ assertionText: string;
69
+ similarity: number;
70
+ } | import("@langchain/langgraph").OverwriteValue<{
71
+ premiseId: string;
72
+ assertionText: string;
73
+ similarity: number;
74
+ } | undefined> | undefined;
61
75
  networkAssignments?: {
62
76
  networkId: string;
63
77
  relevancyScore: number;
@@ -76,7 +90,7 @@ export declare class PremiseGraphFactory {
76
90
  message?: string;
77
91
  } | undefined> | undefined;
78
92
  agentTimings?: DebugMetaAgent[] | import("@langchain/langgraph").OverwriteValue<DebugMetaAgent[]> | undefined;
79
- }, "index" | "query" | "__start__" | "persist" | "embed" | "analyze", {
93
+ }, "index" | "query" | "__start__" | "persist" | "embed" | "analyze" | "dedupe", {
80
94
  userId: {
81
95
  (annotation: import("@langchain/langgraph").SingleReducer<string, string>): import("@langchain/langgraph").BaseChannel<string, string | import("@langchain/langgraph").OverwriteValue<string>, unknown>;
82
96
  (): import("@langchain/langgraph").LastValue<string>;
@@ -96,6 +110,19 @@ export declare class PremiseGraphFactory {
96
110
  analysis: import("@langchain/langgraph").BaseChannel<PremiseAnalysis | undefined, PremiseAnalysis | import("@langchain/langgraph").OverwriteValue<PremiseAnalysis | undefined> | undefined, unknown>;
97
111
  embedding: import("@langchain/langgraph").BaseChannel<number[] | undefined, number[] | import("@langchain/langgraph").OverwriteValue<number[] | undefined> | undefined, unknown>;
98
112
  premise: import("@langchain/langgraph").BaseChannel<import("../shared/interfaces/database.interface.js").PremiseRecord | undefined, import("../shared/interfaces/database.interface.js").PremiseRecord | import("@langchain/langgraph").OverwriteValue<import("../shared/interfaces/database.interface.js").PremiseRecord | undefined> | undefined, unknown>;
113
+ duplicateOf: import("@langchain/langgraph").BaseChannel<{
114
+ premiseId: string;
115
+ assertionText: string;
116
+ similarity: number;
117
+ } | undefined, {
118
+ premiseId: string;
119
+ assertionText: string;
120
+ similarity: number;
121
+ } | import("@langchain/langgraph").OverwriteValue<{
122
+ premiseId: string;
123
+ assertionText: string;
124
+ similarity: number;
125
+ } | undefined> | undefined, unknown>;
99
126
  networkAssignments: import("@langchain/langgraph").BaseChannel<{
100
127
  networkId: string;
101
128
  relevancyScore: number;
@@ -141,6 +168,19 @@ export declare class PremiseGraphFactory {
141
168
  analysis: import("@langchain/langgraph").BaseChannel<PremiseAnalysis | undefined, PremiseAnalysis | import("@langchain/langgraph").OverwriteValue<PremiseAnalysis | undefined> | undefined, unknown>;
142
169
  embedding: import("@langchain/langgraph").BaseChannel<number[] | undefined, number[] | import("@langchain/langgraph").OverwriteValue<number[] | undefined> | undefined, unknown>;
143
170
  premise: import("@langchain/langgraph").BaseChannel<import("../shared/interfaces/database.interface.js").PremiseRecord | undefined, import("../shared/interfaces/database.interface.js").PremiseRecord | import("@langchain/langgraph").OverwriteValue<import("../shared/interfaces/database.interface.js").PremiseRecord | undefined> | undefined, unknown>;
171
+ duplicateOf: import("@langchain/langgraph").BaseChannel<{
172
+ premiseId: string;
173
+ assertionText: string;
174
+ similarity: number;
175
+ } | undefined, {
176
+ premiseId: string;
177
+ assertionText: string;
178
+ similarity: number;
179
+ } | import("@langchain/langgraph").OverwriteValue<{
180
+ premiseId: string;
181
+ assertionText: string;
182
+ similarity: number;
183
+ } | undefined> | undefined, unknown>;
144
184
  networkAssignments: import("@langchain/langgraph").BaseChannel<{
145
185
  networkId: string;
146
186
  relevancyScore: number;
@@ -192,6 +232,15 @@ export declare class PremiseGraphFactory {
192
232
  embedding: number[];
193
233
  error?: undefined;
194
234
  };
235
+ dedupe: {
236
+ duplicateOf?: undefined;
237
+ } | {
238
+ duplicateOf: {
239
+ premiseId: string;
240
+ assertionText: string;
241
+ similarity: number;
242
+ };
243
+ };
195
244
  persist: {
196
245
  error?: undefined;
197
246
  premise?: undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"premise.graph.d.ts","sourceRoot":"/","sources":["premise/premise.graph.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAItD,OAAO,KAAK,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,4CAA4C,CAAC;AACxG,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4CAA4C,CAAC;AAG3E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAItE;;GAEG;AACH,qBAAa,mBAAmB;IAE5B,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,cAAc;gBAFd,QAAQ,EAAE,oBAAoB,EAC9B,QAAQ,EAAE,QAAQ,EAClB,cAAc,GAAE,cAAqC;IAG/D;;;;OAIG;IACI,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BA6H0B,MAAM;gCAAkB,MAAM;;;;;CAuF3E"}
1
+ {"version":3,"file":"premise.graph.d.ts","sourceRoot":"/","sources":["premise/premise.graph.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAItD,OAAO,KAAK,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,4CAA4C,CAAC;AACxG,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4CAA4C,CAAC;AAG3E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AA6BtE;;GAEG;AACH,qBAAa,mBAAmB;IAE5B,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,cAAc;gBAFd,QAAQ,EAAE,oBAAoB,EAC9B,QAAQ,EAAE,QAAQ,EAClB,cAAc,GAAE,cAAqC;IAG/D;;;;OAIG;IACI,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BAgK0B,MAAM;gCAAkB,MAAM;;;;;CA6F3E"}
@@ -7,6 +7,31 @@ import { getAbortSignalConfig } from "../shared/agent/model-signal.js";
7
7
  import { protocolLogger } from "../shared/observability/protocol.logger.js";
8
8
  import { timed } from "../shared/observability/performance.js";
9
9
  const logger = protocolLogger("PremiseGraphFactory");
10
+ /**
11
+ * Minimum cosine similarity (0-1) at which a freshly-decomposed premise is treated
12
+ * as a near-duplicate of an existing ACTIVE premise for the same user and skipped
13
+ * on create. Tuned high so genuine paraphrases collapse while distinct facts (e.g.
14
+ * "I work at Google" vs "I worked at Google") still persist. Override with
15
+ * PREMISE_DEDUP_SIMILARITY.
16
+ */
17
+ const DEDUP_SIMILARITY_THRESHOLD = (() => {
18
+ const raw = Number(process.env.PREMISE_DEDUP_SIMILARITY);
19
+ return Number.isFinite(raw) && raw > 0 && raw <= 1 ? raw : 0.93;
20
+ })();
21
+ /**
22
+ * Derive a premise provenance confidence (0-1) from the analyzer's felicity scores.
23
+ * Averages authority, sincerity, and clarity — the dimensions that speak to how
24
+ * trustworthy the self-assertion is. Falls back to 1.0 when no analysis is present.
25
+ */
26
+ function deriveProvenanceConfidence(analysis) {
27
+ if (!analysis)
28
+ return 1.0;
29
+ const { felicityAuthority, felicitySincerity, felicityClarity } = analysis;
30
+ const mean = (felicityAuthority + felicitySincerity + felicityClarity) / 3;
31
+ if (!Number.isFinite(mean))
32
+ return 1.0;
33
+ return Math.min(1, Math.max(0, mean));
34
+ }
10
35
  /**
11
36
  * Graph factory for premise lifecycle: create, update, and query modes.
12
37
  */
@@ -71,6 +96,35 @@ export class PremiseGraphFactory {
71
96
  return { embedding };
72
97
  });
73
98
  };
99
+ // ─────────────────────────────────────────────────────────
100
+ // NODE: Dedupe (create mode only)
101
+ // Skips persisting a near-duplicate of an existing ACTIVE premise for the same
102
+ // user. Re-running similar input (e.g. repeated enrichment) therefore does not
103
+ // accumulate near-identical premises. No-op for update mode, when no embedding
104
+ // is available, or when the adapter does not implement findSimilarActivePremise.
105
+ // ─────────────────────────────────────────────────────────
106
+ const dedupeNode = async (state) => {
107
+ return timed("PremiseGraph.dedupe", async () => {
108
+ if (state.error)
109
+ return {};
110
+ if (state.operationMode === 'update')
111
+ return {};
112
+ if (!state.embedding || state.embedding.length === 0)
113
+ return {};
114
+ if (typeof this.database.findSimilarActivePremise !== 'function')
115
+ return {};
116
+ const match = await this.database.findSimilarActivePremise({
117
+ userId: state.userId,
118
+ embedding: state.embedding,
119
+ threshold: DEDUP_SIMILARITY_THRESHOLD,
120
+ });
121
+ if (match) {
122
+ logger.verbose(`[PremiseGraph.dedupe] Skipping near-duplicate (similarity=${match.similarity.toFixed(3)} >= ${DEDUP_SIMILARITY_THRESHOLD}) of premise ${match.premiseId}`);
123
+ return { duplicateOf: match };
124
+ }
125
+ return {};
126
+ });
127
+ };
74
128
  const persistNode = async (state) => {
75
129
  return timed("PremiseGraph.persist", async () => {
76
130
  if (state.error)
@@ -96,6 +150,11 @@ export class PremiseGraphFactory {
96
150
  return { premise: updated };
97
151
  }
98
152
  logger.verbose(`[PremiseGraph.persist] Creating new premise for user ${state.userId}`);
153
+ // Provenance confidence: prefer an explicit caller-supplied value; otherwise
154
+ // derive it from the analyzer's felicity scores (how authoritative, sincere,
155
+ // and clear the assertion is) rather than a blanket 1.0, so the stored
156
+ // provenance reflects per-premise signal quality.
157
+ const derivedConfidence = deriveProvenanceConfidence(state.analysis);
99
158
  const premise = await this.database.createPremise({
100
159
  userId: state.userId,
101
160
  assertion: {
@@ -105,7 +164,7 @@ export class PremiseGraphFactory {
105
164
  provenance: {
106
165
  source: state.provenanceSource ?? 'explicit',
107
166
  sourceId: state.provenanceSourceId,
108
- confidence: state.provenanceConfidence ?? 1.0,
167
+ confidence: state.provenanceConfidence ?? derivedConfidence,
109
168
  timestamp: new Date().toISOString(),
110
169
  },
111
170
  analysis: state.analysis ?? undefined,
@@ -193,6 +252,7 @@ export class PremiseGraphFactory {
193
252
  .addNode("query", queryNode)
194
253
  .addNode("analyze", analyzeNode)
195
254
  .addNode("embed", embedNode)
255
+ .addNode("dedupe", dedupeNode)
196
256
  .addNode("persist", persistNode)
197
257
  .addNode("index", indexNode)
198
258
  .addConditionalEdges(START, routeByMode, {
@@ -202,7 +262,12 @@ export class PremiseGraphFactory {
202
262
  })
203
263
  .addEdge("query", END)
204
264
  .addEdge("analyze", "embed")
205
- .addEdge("embed", "persist")
265
+ .addEdge("embed", "dedupe")
266
+ // A near-duplicate short-circuits straight to END (no persist, no index).
267
+ .addConditionalEdges("dedupe", (state) => (state.duplicateOf ? "end" : "persist"), {
268
+ persist: "persist",
269
+ end: END,
270
+ })
206
271
  .addEdge("persist", "index")
207
272
  .addEdge("index", END);
208
273
  return graph.compile();
@@ -1 +1 @@
1
- {"version":3,"file":"premise.graph.js","sourceRoot":"/","sources":["premise/premise.graph.ts"],"names":[],"mappings":"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","sourcesContent":["import { StateGraph, START, END } from \"@langchain/langgraph\";\n\nimport { PremiseGraphState } from \"./premise.state.js\";\nimport { PremiseAnalyzer } from \"./premise.analyzer.js\";\nimport { PremiseIndexer } from \"./premise.indexer.js\";\n\nimport { buildNetworkAssignmentDecision, resolveAssignmentNetworkScope } from \"../shared/assignment/network-assignment.policy.js\";\nimport { getAbortSignalConfig } from \"../shared/agent/model-signal.js\";\nimport type { PremiseGraphDatabase, PremiseAnalysis } from \"../shared/interfaces/database.interface.js\";\nimport type { Embedder } from \"../shared/interfaces/embedder.interface.js\";\nimport { protocolLogger } from \"../shared/observability/protocol.logger.js\";\nimport { timed } from \"../shared/observability/performance.js\";\nimport type { DebugMetaAgent } from \"../chat/chat-streaming.types.js\";\n\nconst logger = protocolLogger(\"PremiseGraphFactory\");\n\n/**\n * Graph factory for premise lifecycle: create, update, and query modes.\n */\nexport class PremiseGraphFactory {\n constructor(\n private database: PremiseGraphDatabase,\n private embedder: Embedder,\n private premiseIndexer: PremiseIndexer = new PremiseIndexer(),\n ) {}\n\n /**\n * Compiles and returns the premise lifecycle graph.\n *\n * @returns A compiled LangGraph graph handling create, update, and query modes.\n */\n public createGraph() {\n const analyzer = new PremiseAnalyzer();\n const indexer = this.premiseIndexer;\n\n const queryNode = async (state: typeof PremiseGraphState.State) => {\n return timed(\"PremiseGraph.query\", async () => {\n logger.verbose(`[PremiseGraph.query] Fetching premises for user ${state.userId}`);\n const premises = await this.database.getPremisesForUser(state.userId, 'ACTIVE');\n return {\n readResult: {\n premises,\n count: premises.length,\n },\n };\n });\n };\n\n const analyzeNode = async (state: typeof PremiseGraphState.State) => {\n return timed(\"PremiseGraph.analyze\", async () => {\n if (!state.assertionText) {\n return { error: \"assertionText is required for create/update mode\" };\n }\n\n logger.verbose(`[PremiseGraph.analyze] Analyzing: \"${state.assertionText.substring(0, 50)}...\"`);\n\n const start = Date.now();\n const result = await analyzer.invoke(state.assertionText);\n const timing: DebugMetaAgent = {\n name: \"premise-analyzer\",\n durationMs: Date.now() - start,\n };\n\n const analysis: PremiseAnalysis = {\n speechActType: result.speechActType,\n felicityAuthority: result.felicityAuthority,\n felicitySincerity: result.felicitySincerity,\n felicityClarity: result.felicityClarity,\n semanticEntropy: result.semanticEntropy,\n };\n\n return { analysis, agentTimings: [timing] };\n });\n };\n\n const embedNode = async (state: typeof PremiseGraphState.State) => {\n return timed(\"PremiseGraph.embed\", async () => {\n if (state.error) return {};\n\n if (!state.assertionText) {\n return { error: \"assertionText is required for embedding\" };\n }\n\n logger.verbose(`[PremiseGraph.embed] Generating embedding for premise`);\n\n // Embedder.generate returns number[] | number[][], cast for single string input\n const embedding = await this.embedder.generate(state.assertionText, undefined, getAbortSignalConfig()) as number[];\n return { embedding };\n });\n };\n\n const persistNode = async (state: typeof PremiseGraphState.State) => {\n return timed(\"PremiseGraph.persist\", async () => {\n if (state.error) return {};\n\n if (state.operationMode === 'update' && !state.targetPremiseId) {\n return { error: \"targetPremiseId is required for update mode\" };\n }\n\n if (state.operationMode === 'update' && state.targetPremiseId) {\n logger.verbose(`[PremiseGraph.persist] Updating premise ${state.targetPremiseId}`);\n\n const updated = await this.database.updatePremise(state.targetPremiseId, {\n assertion: {\n text: state.assertionText!,\n tier: state.tier,\n },\n analysis: state.analysis ?? undefined,\n validity: {\n validFrom: state.validFrom,\n validUntil: state.validUntil,\n volatile: state.volatile,\n },\n embedding: state.embedding,\n });\n return { premise: updated };\n }\n\n logger.verbose(`[PremiseGraph.persist] Creating new premise for user ${state.userId}`);\n\n const premise = await this.database.createPremise({\n userId: state.userId,\n assertion: {\n text: state.assertionText!,\n tier: state.tier,\n },\n provenance: {\n source: state.provenanceSource ?? 'explicit',\n sourceId: state.provenanceSourceId,\n confidence: state.provenanceConfidence ?? 1.0,\n timestamp: new Date().toISOString(),\n },\n analysis: state.analysis ?? undefined,\n validity: {\n validFrom: state.validFrom,\n validUntil: state.validUntil,\n volatile: state.volatile,\n },\n embedding: state.embedding,\n });\n return { premise };\n });\n };\n\n const indexNode = async (state: typeof PremiseGraphState.State) => {\n return timed(\"PremiseGraph.index\", async () => {\n if (!state.premise) return {};\n\n logger.verbose(`[PremiseGraph.index] Scoring premise against user networks`);\n\n const membershipNetworkIds = await this.database.getAssignmentNetworkIdsForUser(state.userId);\n const indexIds = resolveAssignmentNetworkScope({\n memberships: membershipNetworkIds,\n networkScopeId: state.networkScopeId,\n });\n const scope = state.networkScopeId ? \"network\" : \"global\";\n const assignments: Array<{ networkId: string; relevancyScore: number }> = [];\n const agentTimings: DebugMetaAgent[] = [];\n\n for (const networkId of indexIds) {\n try {\n const assignmentContext = await this.database.getNetworkAssignmentContext(networkId, state.userId);\n if (!assignmentContext) continue;\n const indexPrompt = assignmentContext.indexPrompt;\n const memberPrompt = assignmentContext.memberPrompt;\n const hasPrompts = !!indexPrompt?.trim() || !!memberPrompt?.trim();\n let rawScores: { indexScore?: number; memberScore?: number } | undefined;\n let reason: string | undefined;\n\n if (hasPrompts) {\n const start = Date.now();\n const result = await indexer.invoke({\n premiseText: state.assertionText!,\n indexPrompt: indexPrompt ?? \"\",\n memberPrompt: memberPrompt ?? undefined,\n });\n const timing: DebugMetaAgent = {\n name: \"premise-indexer\",\n durationMs: Date.now() - start,\n };\n rawScores = { indexScore: result.indexScore, memberScore: result.memberScore };\n reason = result.reasoning;\n agentTimings.push(timing);\n }\n\n const decision = buildNetworkAssignmentDecision({\n resourceType: \"premise\",\n mode: \"automatic\",\n scope,\n indexPrompt,\n memberPrompt,\n rawScores,\n evaluator: \"premise-indexer\",\n source: \"premise-graph\",\n reason,\n createdAt: new Date().toISOString(),\n });\n\n if (decision.assigned) {\n await this.database.assignPremiseToNetwork(\n state.premise.id,\n networkId,\n decision.finalScore,\n decision.metadata,\n );\n assignments.push({ networkId, relevancyScore: decision.finalScore });\n }\n } catch (err) {\n logger.verbose(`[PremiseGraph.index] Failed to score network ${networkId}, skipping: ${err}`);\n }\n }\n\n logger.verbose(`[PremiseGraph.index] Assigned to ${assignments.length} networks`);\n\n return { networkAssignments: assignments, agentTimings };\n });\n };\n\n const routeByMode = (state: typeof PremiseGraphState.State) => {\n if (state.error) return \"end\";\n if (state.operationMode === 'query') return \"query\";\n return \"analyze\";\n };\n\n const graph = new StateGraph(PremiseGraphState)\n .addNode(\"query\", queryNode)\n .addNode(\"analyze\", analyzeNode)\n .addNode(\"embed\", embedNode)\n .addNode(\"persist\", persistNode)\n .addNode(\"index\", indexNode)\n .addConditionalEdges(START, routeByMode, {\n query: \"query\",\n analyze: \"analyze\",\n end: END,\n })\n .addEdge(\"query\", END)\n .addEdge(\"analyze\", \"embed\")\n .addEdge(\"embed\", \"persist\")\n .addEdge(\"persist\", \"index\")\n .addEdge(\"index\", END);\n\n return graph.compile();\n }\n}\n"]}
1
+ {"version":3,"file":"premise.graph.js","sourceRoot":"/","sources":["premise/premise.graph.ts"],"names":[],"mappings":"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","sourcesContent":["import { StateGraph, START, END } from \"@langchain/langgraph\";\n\nimport { PremiseGraphState } from \"./premise.state.js\";\nimport { PremiseAnalyzer } from \"./premise.analyzer.js\";\nimport { PremiseIndexer } from \"./premise.indexer.js\";\n\nimport { buildNetworkAssignmentDecision, resolveAssignmentNetworkScope } from \"../shared/assignment/network-assignment.policy.js\";\nimport { getAbortSignalConfig } from \"../shared/agent/model-signal.js\";\nimport type { PremiseGraphDatabase, PremiseAnalysis } from \"../shared/interfaces/database.interface.js\";\nimport type { Embedder } from \"../shared/interfaces/embedder.interface.js\";\nimport { protocolLogger } from \"../shared/observability/protocol.logger.js\";\nimport { timed } from \"../shared/observability/performance.js\";\nimport type { DebugMetaAgent } from \"../chat/chat-streaming.types.js\";\n\nconst logger = protocolLogger(\"PremiseGraphFactory\");\n\n/**\n * Minimum cosine similarity (0-1) at which a freshly-decomposed premise is treated\n * as a near-duplicate of an existing ACTIVE premise for the same user and skipped\n * on create. Tuned high so genuine paraphrases collapse while distinct facts (e.g.\n * \"I work at Google\" vs \"I worked at Google\") still persist. Override with\n * PREMISE_DEDUP_SIMILARITY.\n */\nconst DEDUP_SIMILARITY_THRESHOLD = (() => {\n const raw = Number(process.env.PREMISE_DEDUP_SIMILARITY);\n return Number.isFinite(raw) && raw > 0 && raw <= 1 ? raw : 0.93;\n})();\n\n/**\n * Derive a premise provenance confidence (0-1) from the analyzer's felicity scores.\n * Averages authority, sincerity, and clarity — the dimensions that speak to how\n * trustworthy the self-assertion is. Falls back to 1.0 when no analysis is present.\n */\nfunction deriveProvenanceConfidence(analysis: PremiseAnalysis | undefined): number {\n if (!analysis) return 1.0;\n const { felicityAuthority, felicitySincerity, felicityClarity } = analysis;\n const mean = (felicityAuthority + felicitySincerity + felicityClarity) / 3;\n if (!Number.isFinite(mean)) return 1.0;\n return Math.min(1, Math.max(0, mean));\n}\n\n/**\n * Graph factory for premise lifecycle: create, update, and query modes.\n */\nexport class PremiseGraphFactory {\n constructor(\n private database: PremiseGraphDatabase,\n private embedder: Embedder,\n private premiseIndexer: PremiseIndexer = new PremiseIndexer(),\n ) {}\n\n /**\n * Compiles and returns the premise lifecycle graph.\n *\n * @returns A compiled LangGraph graph handling create, update, and query modes.\n */\n public createGraph() {\n const analyzer = new PremiseAnalyzer();\n const indexer = this.premiseIndexer;\n\n const queryNode = async (state: typeof PremiseGraphState.State) => {\n return timed(\"PremiseGraph.query\", async () => {\n logger.verbose(`[PremiseGraph.query] Fetching premises for user ${state.userId}`);\n const premises = await this.database.getPremisesForUser(state.userId, 'ACTIVE');\n return {\n readResult: {\n premises,\n count: premises.length,\n },\n };\n });\n };\n\n const analyzeNode = async (state: typeof PremiseGraphState.State) => {\n return timed(\"PremiseGraph.analyze\", async () => {\n if (!state.assertionText) {\n return { error: \"assertionText is required for create/update mode\" };\n }\n\n logger.verbose(`[PremiseGraph.analyze] Analyzing: \"${state.assertionText.substring(0, 50)}...\"`);\n\n const start = Date.now();\n const result = await analyzer.invoke(state.assertionText);\n const timing: DebugMetaAgent = {\n name: \"premise-analyzer\",\n durationMs: Date.now() - start,\n };\n\n const analysis: PremiseAnalysis = {\n speechActType: result.speechActType,\n felicityAuthority: result.felicityAuthority,\n felicitySincerity: result.felicitySincerity,\n felicityClarity: result.felicityClarity,\n semanticEntropy: result.semanticEntropy,\n };\n\n return { analysis, agentTimings: [timing] };\n });\n };\n\n const embedNode = async (state: typeof PremiseGraphState.State) => {\n return timed(\"PremiseGraph.embed\", async () => {\n if (state.error) return {};\n\n if (!state.assertionText) {\n return { error: \"assertionText is required for embedding\" };\n }\n\n logger.verbose(`[PremiseGraph.embed] Generating embedding for premise`);\n\n // Embedder.generate returns number[] | number[][], cast for single string input\n const embedding = await this.embedder.generate(state.assertionText, undefined, getAbortSignalConfig()) as number[];\n return { embedding };\n });\n };\n\n // ─────────────────────────────────────────────────────────\n // NODE: Dedupe (create mode only)\n // Skips persisting a near-duplicate of an existing ACTIVE premise for the same\n // user. Re-running similar input (e.g. repeated enrichment) therefore does not\n // accumulate near-identical premises. No-op for update mode, when no embedding\n // is available, or when the adapter does not implement findSimilarActivePremise.\n // ─────────────────────────────────────────────────────────\n const dedupeNode = async (state: typeof PremiseGraphState.State) => {\n return timed(\"PremiseGraph.dedupe\", async () => {\n if (state.error) return {};\n if (state.operationMode === 'update') return {};\n if (!state.embedding || state.embedding.length === 0) return {};\n if (typeof this.database.findSimilarActivePremise !== 'function') return {};\n\n const match = await this.database.findSimilarActivePremise({\n userId: state.userId,\n embedding: state.embedding,\n threshold: DEDUP_SIMILARITY_THRESHOLD,\n });\n\n if (match) {\n logger.verbose(\n `[PremiseGraph.dedupe] Skipping near-duplicate (similarity=${match.similarity.toFixed(3)} >= ${DEDUP_SIMILARITY_THRESHOLD}) of premise ${match.premiseId}`,\n );\n return { duplicateOf: match };\n }\n return {};\n });\n };\n\n const persistNode = async (state: typeof PremiseGraphState.State) => {\n return timed(\"PremiseGraph.persist\", async () => {\n if (state.error) return {};\n\n if (state.operationMode === 'update' && !state.targetPremiseId) {\n return { error: \"targetPremiseId is required for update mode\" };\n }\n\n if (state.operationMode === 'update' && state.targetPremiseId) {\n logger.verbose(`[PremiseGraph.persist] Updating premise ${state.targetPremiseId}`);\n\n const updated = await this.database.updatePremise(state.targetPremiseId, {\n assertion: {\n text: state.assertionText!,\n tier: state.tier,\n },\n analysis: state.analysis ?? undefined,\n validity: {\n validFrom: state.validFrom,\n validUntil: state.validUntil,\n volatile: state.volatile,\n },\n embedding: state.embedding,\n });\n return { premise: updated };\n }\n\n logger.verbose(`[PremiseGraph.persist] Creating new premise for user ${state.userId}`);\n\n // Provenance confidence: prefer an explicit caller-supplied value; otherwise\n // derive it from the analyzer's felicity scores (how authoritative, sincere,\n // and clear the assertion is) rather than a blanket 1.0, so the stored\n // provenance reflects per-premise signal quality.\n const derivedConfidence = deriveProvenanceConfidence(state.analysis);\n const premise = await this.database.createPremise({\n userId: state.userId,\n assertion: {\n text: state.assertionText!,\n tier: state.tier,\n },\n provenance: {\n source: state.provenanceSource ?? 'explicit',\n sourceId: state.provenanceSourceId,\n confidence: state.provenanceConfidence ?? derivedConfidence,\n timestamp: new Date().toISOString(),\n },\n analysis: state.analysis ?? undefined,\n validity: {\n validFrom: state.validFrom,\n validUntil: state.validUntil,\n volatile: state.volatile,\n },\n embedding: state.embedding,\n });\n return { premise };\n });\n };\n\n const indexNode = async (state: typeof PremiseGraphState.State) => {\n return timed(\"PremiseGraph.index\", async () => {\n if (!state.premise) return {};\n\n logger.verbose(`[PremiseGraph.index] Scoring premise against user networks`);\n\n const membershipNetworkIds = await this.database.getAssignmentNetworkIdsForUser(state.userId);\n const indexIds = resolveAssignmentNetworkScope({\n memberships: membershipNetworkIds,\n networkScopeId: state.networkScopeId,\n });\n const scope = state.networkScopeId ? \"network\" : \"global\";\n const assignments: Array<{ networkId: string; relevancyScore: number }> = [];\n const agentTimings: DebugMetaAgent[] = [];\n\n for (const networkId of indexIds) {\n try {\n const assignmentContext = await this.database.getNetworkAssignmentContext(networkId, state.userId);\n if (!assignmentContext) continue;\n const indexPrompt = assignmentContext.indexPrompt;\n const memberPrompt = assignmentContext.memberPrompt;\n const hasPrompts = !!indexPrompt?.trim() || !!memberPrompt?.trim();\n let rawScores: { indexScore?: number; memberScore?: number } | undefined;\n let reason: string | undefined;\n\n if (hasPrompts) {\n const start = Date.now();\n const result = await indexer.invoke({\n premiseText: state.assertionText!,\n indexPrompt: indexPrompt ?? \"\",\n memberPrompt: memberPrompt ?? undefined,\n });\n const timing: DebugMetaAgent = {\n name: \"premise-indexer\",\n durationMs: Date.now() - start,\n };\n rawScores = { indexScore: result.indexScore, memberScore: result.memberScore };\n reason = result.reasoning;\n agentTimings.push(timing);\n }\n\n const decision = buildNetworkAssignmentDecision({\n resourceType: \"premise\",\n mode: \"automatic\",\n scope,\n indexPrompt,\n memberPrompt,\n rawScores,\n evaluator: \"premise-indexer\",\n source: \"premise-graph\",\n reason,\n createdAt: new Date().toISOString(),\n });\n\n if (decision.assigned) {\n await this.database.assignPremiseToNetwork(\n state.premise.id,\n networkId,\n decision.finalScore,\n decision.metadata,\n );\n assignments.push({ networkId, relevancyScore: decision.finalScore });\n }\n } catch (err) {\n logger.verbose(`[PremiseGraph.index] Failed to score network ${networkId}, skipping: ${err}`);\n }\n }\n\n logger.verbose(`[PremiseGraph.index] Assigned to ${assignments.length} networks`);\n\n return { networkAssignments: assignments, agentTimings };\n });\n };\n\n const routeByMode = (state: typeof PremiseGraphState.State) => {\n if (state.error) return \"end\";\n if (state.operationMode === 'query') return \"query\";\n return \"analyze\";\n };\n\n const graph = new StateGraph(PremiseGraphState)\n .addNode(\"query\", queryNode)\n .addNode(\"analyze\", analyzeNode)\n .addNode(\"embed\", embedNode)\n .addNode(\"dedupe\", dedupeNode)\n .addNode(\"persist\", persistNode)\n .addNode(\"index\", indexNode)\n .addConditionalEdges(START, routeByMode, {\n query: \"query\",\n analyze: \"analyze\",\n end: END,\n })\n .addEdge(\"query\", END)\n .addEdge(\"analyze\", \"embed\")\n .addEdge(\"embed\", \"dedupe\")\n // A near-duplicate short-circuits straight to END (no persist, no index).\n .addConditionalEdges(\"dedupe\", (state: typeof PremiseGraphState.State) => (state.duplicateOf ? \"end\" : \"persist\"), {\n persist: \"persist\",\n end: END,\n })\n .addEdge(\"persist\", \"index\")\n .addEdge(\"index\", END);\n\n return graph.compile();\n }\n}\n"]}
@@ -20,6 +20,19 @@ export declare const PremiseGraphState: import("@langchain/langgraph").Annotatio
20
20
  analysis: import("@langchain/langgraph").BaseChannel<PremiseAnalysis | undefined, PremiseAnalysis | import("@langchain/langgraph").OverwriteValue<PremiseAnalysis | undefined> | undefined, unknown>;
21
21
  embedding: import("@langchain/langgraph").BaseChannel<number[] | undefined, number[] | import("@langchain/langgraph").OverwriteValue<number[] | undefined> | undefined, unknown>;
22
22
  premise: import("@langchain/langgraph").BaseChannel<PremiseRecord | undefined, PremiseRecord | import("@langchain/langgraph").OverwriteValue<PremiseRecord | undefined> | undefined, unknown>;
23
+ duplicateOf: import("@langchain/langgraph").BaseChannel<{
24
+ premiseId: string;
25
+ assertionText: string;
26
+ similarity: number;
27
+ } | undefined, {
28
+ premiseId: string;
29
+ assertionText: string;
30
+ similarity: number;
31
+ } | import("@langchain/langgraph").OverwriteValue<{
32
+ premiseId: string;
33
+ assertionText: string;
34
+ similarity: number;
35
+ } | undefined> | undefined, unknown>;
23
36
  networkAssignments: import("@langchain/langgraph").BaseChannel<{
24
37
  networkId: string;
25
38
  relevancyScore: number;
@@ -1 +1 @@
1
- {"version":3,"file":"premise.state.d.ts","sourceRoot":"/","sources":["premise/premise.state.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAqB,aAAa,EAAE,MAAM,4CAA4C,CAAC;AACpH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEtE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;mBAyEsB,MAAM;wBAAkB,MAAM;;mBAA9B,MAAM;wBAAkB,MAAM;;mBAA9B,MAAM;wBAAkB,MAAM;;;;kBAWpE,aAAa,EAAE;eAClB,MAAM;kBACH,MAAM;;kBAFN,aAAa,EAAE;eAClB,MAAM;kBACH,MAAM;;kBAFN,aAAa,EAAE;eAClB,MAAM;kBACH,MAAM;;;EAUlB,CAAC"}
1
+ {"version":3,"file":"premise.state.d.ts","sourceRoot":"/","sources":["premise/premise.state.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAqB,aAAa,EAAE,MAAM,4CAA4C,CAAC;AACpH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEtE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;mBA4ES,MAAM;uBAAiB,MAAM;oBAAc,MAAM;;mBAAjD,MAAM;uBAAiB,MAAM;oBAAc,MAAM;;mBAAjD,MAAM;uBAAiB,MAAM;oBAAc,MAAM;;;mBAKpC,MAAM;wBAAkB,MAAM;;mBAA9B,MAAM;wBAAkB,MAAM;;mBAA9B,MAAM;wBAAkB,MAAM;;;;kBAWpE,aAAa,EAAE;eAClB,MAAM;kBACH,MAAM;;kBAFN,aAAa,EAAE;eAClB,MAAM;kBACH,MAAM;;kBAFN,aAAa,EAAE;eAClB,MAAM;kBACH,MAAM;;;EAUlB,CAAC"}
@@ -57,6 +57,13 @@ export const PremiseGraphState = Annotation.Root({
57
57
  reducer: (curr, next) => next,
58
58
  default: () => undefined,
59
59
  }),
60
+ // Set by the dedupe node when a near-duplicate ACTIVE premise already exists for
61
+ // the user (create mode only). When present, persist/index are skipped — the
62
+ // candidate is treated as already represented by `duplicateOf`.
63
+ duplicateOf: Annotation({
64
+ reducer: (curr, next) => next,
65
+ default: () => undefined,
66
+ }),
60
67
  networkAssignments: Annotation({
61
68
  reducer: (curr, next) => next,
62
69
  default: () => [],
@@ -1 +1 @@
1
- {"version":3,"file":"premise.state.js","sourceRoot":"/","sources":["premise/premise.state.ts"],"names":[],"mappings":"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","sourcesContent":["import { Annotation } from \"@langchain/langgraph\";\nimport type { PremiseAnalysis, PremiseProvenance, PremiseRecord } from \"../shared/interfaces/database.interface.js\";\nimport type { DebugMetaAgent } from '../chat/chat-streaming.types.js';\n\nexport const PremiseGraphState = Annotation.Root({\n userId: Annotation<string>,\n\n assertionText: Annotation<string | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n tier: Annotation<'assertive' | 'contextual'>({\n reducer: (curr, next) => next ?? curr,\n default: () => 'assertive',\n }),\n\n validFrom: Annotation<string | undefined>({\n reducer: (curr, next) => next,\n default: () => undefined,\n }),\n\n validUntil: Annotation<string | undefined>({\n reducer: (curr, next) => next,\n default: () => undefined,\n }),\n\n volatile: Annotation<boolean>({\n reducer: (curr, next) => next ?? curr,\n default: () => false,\n }),\n\n provenanceSource: Annotation<PremiseProvenance['source'] | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n provenanceSourceId: Annotation<string | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n provenanceConfidence: Annotation<number | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n operationMode: Annotation<'create' | 'update' | 'query'>({\n reducer: (curr, next) => next ?? curr,\n default: () => 'create',\n }),\n\n networkScopeId: Annotation<string | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n targetPremiseId: Annotation<string | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n analysis: Annotation<PremiseAnalysis | undefined>({\n reducer: (curr, next) => next,\n default: () => undefined,\n }),\n\n embedding: Annotation<number[] | undefined>({\n reducer: (curr, next) => next,\n default: () => undefined,\n }),\n\n premise: Annotation<PremiseRecord | undefined>({\n reducer: (curr, next) => next,\n default: () => undefined,\n }),\n\n networkAssignments: Annotation<Array<{ networkId: string; relevancyScore: number }>>({\n reducer: (curr, next) => next,\n default: () => [],\n }),\n\n error: Annotation<string | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n readResult: Annotation<{\n premises: PremiseRecord[];\n count: number;\n message?: string;\n } | undefined>({\n reducer: (curr, next) => next,\n default: () => undefined,\n }),\n\n agentTimings: Annotation<DebugMetaAgent[]>({\n reducer: (acc, val) => [...acc, ...val],\n default: () => [],\n }),\n});\n"]}
1
+ {"version":3,"file":"premise.state.js","sourceRoot":"/","sources":["premise/premise.state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAIlD,MAAM,CAAC,MAAM,iBAAiB,GAAG,UAAU,CAAC,IAAI,CAAC;IAC/C,MAAM,EAAE,CAAA,UAAkB,CAAA;IAE1B,aAAa,EAAE,UAAU,CAAqB;QAC5C,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;KACzB,CAAC;IAEF,IAAI,EAAE,UAAU,CAA6B;QAC3C,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,WAAW;KAC3B,CAAC;IAEF,SAAS,EAAE,UAAU,CAAqB;QACxC,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI;QAC7B,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;KACzB,CAAC;IAEF,UAAU,EAAE,UAAU,CAAqB;QACzC,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI;QAC7B,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;KACzB,CAAC;IAEF,QAAQ,EAAE,UAAU,CAAU;QAC5B,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK;KACrB,CAAC;IAEF,gBAAgB,EAAE,UAAU,CAA0C;QACpE,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;KACzB,CAAC;IAEF,kBAAkB,EAAE,UAAU,CAAqB;QACjD,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;KACzB,CAAC;IAEF,oBAAoB,EAAE,UAAU,CAAqB;QACnD,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;KACzB,CAAC;IAEF,aAAa,EAAE,UAAU,CAAgC;QACvD,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ;KACxB,CAAC;IAEF,cAAc,EAAE,UAAU,CAAqB;QAC7C,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;KACzB,CAAC;IAEF,eAAe,EAAE,UAAU,CAAqB;QAC9C,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;KACzB,CAAC;IAEF,QAAQ,EAAE,UAAU,CAA8B;QAChD,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI;QAC7B,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;KACzB,CAAC;IAEF,SAAS,EAAE,UAAU,CAAuB;QAC1C,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI;QAC7B,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;KACzB,CAAC;IAEF,OAAO,EAAE,UAAU,CAA4B;QAC7C,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI;QAC7B,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;KACzB,CAAC;IAEF,iFAAiF;IACjF,6EAA6E;IAC7E,gEAAgE;IAChE,WAAW,EAAE,UAAU,CAA+E;QACpG,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI;QAC7B,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;KACzB,CAAC;IAEF,kBAAkB,EAAE,UAAU,CAAuD;QACnF,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI;QAC7B,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE;KAClB,CAAC;IAEF,KAAK,EAAE,UAAU,CAAqB;QACpC,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI;QACrC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;KACzB,CAAC;IAEF,UAAU,EAAE,UAAU,CAIP;QACb,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI;QAC7B,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;KACzB,CAAC;IAEF,YAAY,EAAE,UAAU,CAAmB;QACzC,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,GAAG,CAAC;QACvC,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE;KAClB,CAAC;CACH,CAAC,CAAC","sourcesContent":["import { Annotation } from \"@langchain/langgraph\";\nimport type { PremiseAnalysis, PremiseProvenance, PremiseRecord } from \"../shared/interfaces/database.interface.js\";\nimport type { DebugMetaAgent } from '../chat/chat-streaming.types.js';\n\nexport const PremiseGraphState = Annotation.Root({\n userId: Annotation<string>,\n\n assertionText: Annotation<string | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n tier: Annotation<'assertive' | 'contextual'>({\n reducer: (curr, next) => next ?? curr,\n default: () => 'assertive',\n }),\n\n validFrom: Annotation<string | undefined>({\n reducer: (curr, next) => next,\n default: () => undefined,\n }),\n\n validUntil: Annotation<string | undefined>({\n reducer: (curr, next) => next,\n default: () => undefined,\n }),\n\n volatile: Annotation<boolean>({\n reducer: (curr, next) => next ?? curr,\n default: () => false,\n }),\n\n provenanceSource: Annotation<PremiseProvenance['source'] | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n provenanceSourceId: Annotation<string | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n provenanceConfidence: Annotation<number | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n operationMode: Annotation<'create' | 'update' | 'query'>({\n reducer: (curr, next) => next ?? curr,\n default: () => 'create',\n }),\n\n networkScopeId: Annotation<string | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n targetPremiseId: Annotation<string | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n analysis: Annotation<PremiseAnalysis | undefined>({\n reducer: (curr, next) => next,\n default: () => undefined,\n }),\n\n embedding: Annotation<number[] | undefined>({\n reducer: (curr, next) => next,\n default: () => undefined,\n }),\n\n premise: Annotation<PremiseRecord | undefined>({\n reducer: (curr, next) => next,\n default: () => undefined,\n }),\n\n // Set by the dedupe node when a near-duplicate ACTIVE premise already exists for\n // the user (create mode only). When present, persist/index are skipped — the\n // candidate is treated as already represented by `duplicateOf`.\n duplicateOf: Annotation<{ premiseId: string; assertionText: string; similarity: number } | undefined>({\n reducer: (curr, next) => next,\n default: () => undefined,\n }),\n\n networkAssignments: Annotation<Array<{ networkId: string; relevancyScore: number }>>({\n reducer: (curr, next) => next,\n default: () => [],\n }),\n\n error: Annotation<string | undefined>({\n reducer: (curr, next) => next ?? curr,\n default: () => undefined,\n }),\n\n readResult: Annotation<{\n premises: PremiseRecord[];\n count: number;\n message?: string;\n } | undefined>({\n reducer: (curr, next) => next,\n default: () => undefined,\n }),\n\n agentTimings: Annotation<DebugMetaAgent[]>({\n reducer: (acc, val) => [...acc, ...val],\n default: () => [],\n }),\n});\n"]}
@@ -14,12 +14,22 @@ export interface CompiledPremiseGraph {
14
14
  assertionText: string;
15
15
  tier: 'assertive' | 'contextual';
16
16
  operationMode: 'create';
17
+ /** Volatile premises auto-retract once their validity window lapses. */
18
+ volatile?: boolean;
19
+ /** ISO timestamp after which a contextual premise is no longer valid. */
20
+ validUntil?: string;
17
21
  provenanceSource?: PremiseProvenance['source'];
18
22
  provenanceSourceId?: string;
19
23
  }): Promise<{
20
24
  premise?: {
21
25
  id: string;
22
26
  } | undefined;
27
+ /** Set when the create was skipped because a near-duplicate already exists. */
28
+ duplicateOf?: {
29
+ premiseId: string;
30
+ assertionText: string;
31
+ similarity: number;
32
+ } | undefined;
23
33
  error?: string | undefined;
24
34
  }>;
25
35
  }
@@ -1 +1 @@
1
- {"version":3,"file":"profile.graph.d.ts","sourceRoot":"/","sources":["profile/profile.graph.ts"],"names":[],"mappings":"AAEA,OAAO,EAAoB,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAiB,iBAAiB,EAAE,MAAM,4CAA4C,CAAC;AACpH,OAAO,EAAE,OAAO,EAAE,MAAM,2CAA2C,CAAC;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8CAA8C,CAAC;AAIpF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAG7E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAItE;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,MAAM,CAAC,KAAK,EAAE;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,aAAa,EAAE,MAAM,CAAC;QACtB,IAAI,EAAE,WAAW,GAAG,YAAY,CAAC;QACjC,aAAa,EAAE,QAAQ,CAAC;QACxB,gBAAgB,CAAC,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QAC/C,kBAAkB,CAAC,EAAE,MAAM,CAAC;KAC7B,GAAG,OAAO,CAAC;QACV,OAAO,CAAC,EAAE;YAAE,EAAE,EAAE,MAAM,CAAA;SAAE,GAAG,SAAS,CAAC;QACrC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KAC5B,CAAC,CAAC;CACJ;AA+BD;;;;;;;;;;;;;;GAcG;AACH,qBAAa,mBAAmB;IAE5B,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,QAAQ,CAAC;IACjB,OAAO,CAAC,iBAAiB,CAAC;IAC1B,OAAO,CAAC,YAAY,CAAC;gBAJb,QAAQ,EAAE,oBAAoB,EAC9B,OAAO,EAAE,OAAO,EAChB,QAAQ,CAAC,EAAE,eAAe,YAAA,EAC1B,iBAAiB,CAAC,EAAE,mBAAmB,YAAA,EACvC,YAAY,CAAC,EAAE,oBAAoB,YAAA;IAGtC,WAAW;;;;;;;;;;;;;;;;;;;;;;;kBAWV,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAAD,CAAC;;;;;;;;;;;kBAAD,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAAD,CAAC;;;;;;;;;;;kBAAD,CAAC;;;;;;;;;;;kBAAD,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAAD,CAAC;;;;;;;;;;;kBAAD,CAAC;;;;;;;;;;;kBAAD,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAg4BV"}
1
+ {"version":3,"file":"profile.graph.d.ts","sourceRoot":"/","sources":["profile/profile.graph.ts"],"names":[],"mappings":"AAEA,OAAO,EAAoB,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAiB,iBAAiB,EAAE,MAAM,4CAA4C,CAAC;AACpH,OAAO,EAAE,OAAO,EAAE,MAAM,2CAA2C,CAAC;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8CAA8C,CAAC;AAIpF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAG7E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAItE;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,MAAM,CAAC,KAAK,EAAE;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,aAAa,EAAE,MAAM,CAAC;QACtB,IAAI,EAAE,WAAW,GAAG,YAAY,CAAC;QACjC,aAAa,EAAE,QAAQ,CAAC;QACxB,wEAAwE;QACxE,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,yEAAyE;QACzE,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,gBAAgB,CAAC,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QAC/C,kBAAkB,CAAC,EAAE,MAAM,CAAC;KAC7B,GAAG,OAAO,CAAC;QACV,OAAO,CAAC,EAAE;YAAE,EAAE,EAAE,MAAM,CAAA;SAAE,GAAG,SAAS,CAAC;QACrC,+EAA+E;QAC/E,WAAW,CAAC,EAAE;YAAE,SAAS,EAAE,MAAM,CAAC;YAAC,aAAa,EAAE,MAAM,CAAC;YAAC,UAAU,EAAE,MAAM,CAAA;SAAE,GAAG,SAAS,CAAC;QAC3F,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KAC5B,CAAC,CAAC;CACJ;AA+BD;;;;;;;;;;;;;;GAcG;AACH,qBAAa,mBAAmB;IAE5B,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,QAAQ,CAAC;IACjB,OAAO,CAAC,iBAAiB,CAAC;IAC1B,OAAO,CAAC,YAAY,CAAC;gBAJb,QAAQ,EAAE,oBAAoB,EAC9B,OAAO,EAAE,OAAO,EAChB,QAAQ,CAAC,EAAE,eAAe,YAAA,EAC1B,iBAAiB,CAAC,EAAE,mBAAmB,YAAA,EACvC,YAAY,CAAC,EAAE,oBAAoB,YAAA;IAGtC,WAAW;;;;;;;;;;;;;;;;;;;;;;;kBAIX,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAAD,CAAC;;;;;;;;;;;kBAAD,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAAD,CAAC;;;;;;;;;;;kBAAD,CAAC;;;;;;;;;;;kBAAD,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAAD,CAAC;;;;;;;;;;;kBAAD,CAAC;;;;;;;;;;;kBAAD,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAm5BT"}
@@ -685,13 +685,22 @@ export class ProfileGraphFactory {
685
685
  userId: state.userId,
686
686
  });
687
687
  let created = 0;
688
+ let skippedDuplicates = 0;
688
689
  for (const p of result.premises) {
689
690
  try {
691
+ // Contextual premises carry an LLM-inferred validity window and are
692
+ // volatile (auto-retract on expiry); assertive premises do not expire.
693
+ const isContextual = p.tier === 'contextual';
694
+ const validUntil = isContextual && p.validityDays
695
+ ? new Date(Date.now() + p.validityDays * 24 * 60 * 60 * 1000).toISOString()
696
+ : undefined;
690
697
  const premiseResult = await invokeWithAbortSignal(this.premiseGraph, {
691
698
  userId: state.userId,
692
699
  assertionText: p.text,
693
700
  tier: p.tier,
694
701
  operationMode: 'create',
702
+ volatile: isContextual,
703
+ ...(validUntil ? { validUntil } : {}),
695
704
  ...(state.activeSocialIds?.length
696
705
  ? { provenanceSource: 'integration', provenanceSourceId: state.activeSocialIds[0] }
697
706
  : {}),
@@ -699,6 +708,9 @@ export class ProfileGraphFactory {
699
708
  if (premiseResult.premise) {
700
709
  created++;
701
710
  }
711
+ else if (premiseResult.duplicateOf) {
712
+ skippedDuplicates++;
713
+ }
702
714
  else if (premiseResult.error) {
703
715
  logger.warn("Premise creation failed", {
704
716
  text: p.text.substring(0, 60),
@@ -713,7 +725,7 @@ export class ProfileGraphFactory {
713
725
  });
714
726
  }
715
727
  }
716
- logger.verbose(`Created ${created}/${result.premises.length} premise(s)`, {
728
+ logger.verbose(`Created ${created}/${result.premises.length} premise(s) (${skippedDuplicates} skipped as near-duplicates)`, {
717
729
  userId: state.userId,
718
730
  });
719
731
  // Route to aggregate mode to rebuild the profile from all active premises