@indexnetwork/protocol 4.4.1-rc.320.1 → 4.5.0-rc.322.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/chat/chat.interrupt.classifier.d.ts.map +1 -1
- package/dist/chat/chat.interrupt.classifier.js +2 -2
- package/dist/chat/chat.interrupt.classifier.js.map +1 -1
- package/dist/chat/chat.suggester.d.ts.map +1 -1
- package/dist/chat/chat.suggester.js +2 -3
- package/dist/chat/chat.suggester.js.map +1 -1
- package/dist/chat/chat.summarizer.d.ts.map +1 -1
- package/dist/chat/chat.summarizer.js +11 -3
- package/dist/chat/chat.summarizer.js.map +1 -1
- package/dist/chat/chat.title.generator.d.ts.map +1 -1
- package/dist/chat/chat.title.generator.js +2 -2
- package/dist/chat/chat.title.generator.js.map +1 -1
- package/dist/contact/contact.inviter.d.ts.map +1 -1
- package/dist/contact/contact.inviter.js +2 -3
- package/dist/contact/contact.inviter.js.map +1 -1
- package/dist/context/context.generator.d.ts.map +1 -1
- package/dist/context/context.generator.js +2 -2
- package/dist/context/context.generator.js.map +1 -1
- package/dist/enrichment/enrichment.generator.d.ts +1 -1
- package/dist/enrichment/enrichment.generator.d.ts.map +1 -1
- package/dist/enrichment/enrichment.generator.js +3 -4
- package/dist/enrichment/enrichment.generator.js.map +1 -1
- package/dist/intent/intent.clarifier.d.ts.map +1 -1
- package/dist/intent/intent.clarifier.js +4 -5
- package/dist/intent/intent.clarifier.js.map +1 -1
- package/dist/intent/intent.indexer.d.ts.map +1 -1
- package/dist/intent/intent.indexer.js +2 -3
- package/dist/intent/intent.indexer.js.map +1 -1
- package/dist/intent/intent.inferrer.d.ts.map +1 -1
- package/dist/intent/intent.inferrer.js +2 -3
- package/dist/intent/intent.inferrer.js.map +1 -1
- package/dist/intent/intent.reconciler.d.ts.map +1 -1
- package/dist/intent/intent.reconciler.js +2 -3
- package/dist/intent/intent.reconciler.js.map +1 -1
- package/dist/intent/intent.verifier.d.ts.map +1 -1
- package/dist/intent/intent.verifier.js +2 -3
- package/dist/intent/intent.verifier.js.map +1 -1
- package/dist/negotiation/insight.generator.d.ts.map +1 -1
- package/dist/negotiation/insight.generator.js +2 -2
- package/dist/negotiation/insight.generator.js.map +1 -1
- package/dist/negotiation/negotiation.agent.js +2 -2
- package/dist/negotiation/negotiation.agent.js.map +1 -1
- package/dist/negotiation/negotiation.summarizer.d.ts +11 -0
- package/dist/negotiation/negotiation.summarizer.d.ts.map +1 -1
- package/dist/negotiation/negotiation.summarizer.js +13 -3
- package/dist/negotiation/negotiation.summarizer.js.map +1 -1
- package/dist/network/network.recommender.d.ts.map +1 -1
- package/dist/network/network.recommender.js +2 -3
- package/dist/network/network.recommender.js.map +1 -1
- package/dist/opportunity/feed/feed.categorizer.d.ts.map +1 -1
- package/dist/opportunity/feed/feed.categorizer.js +2 -3
- package/dist/opportunity/feed/feed.categorizer.js.map +1 -1
- package/dist/opportunity/opportunity.evaluator.d.ts.map +1 -1
- package/dist/opportunity/opportunity.evaluator.js +3 -4
- package/dist/opportunity/opportunity.evaluator.js.map +1 -1
- package/dist/opportunity/opportunity.presenter.d.ts.map +1 -1
- package/dist/opportunity/opportunity.presenter.js +3 -4
- package/dist/opportunity/opportunity.presenter.js.map +1 -1
- package/dist/opportunity/question.generator.d.ts.map +1 -1
- package/dist/opportunity/question.generator.js +17 -3
- package/dist/opportunity/question.generator.js.map +1 -1
- package/dist/premise/premise.analyzer.d.ts.map +1 -1
- package/dist/premise/premise.analyzer.js +2 -3
- package/dist/premise/premise.analyzer.js.map +1 -1
- package/dist/premise/premise.decomposer.d.ts.map +1 -1
- package/dist/premise/premise.decomposer.js +2 -3
- package/dist/premise/premise.decomposer.js.map +1 -1
- package/dist/premise/premise.indexer.d.ts.map +1 -1
- package/dist/premise/premise.indexer.js +2 -3
- package/dist/premise/premise.indexer.js.map +1 -1
- package/dist/questioner/questioner.agent.d.ts +2 -2
- package/dist/questioner/questioner.agent.d.ts.map +1 -1
- package/dist/questioner/questioner.agent.js +12 -4
- package/dist/questioner/questioner.agent.js.map +1 -1
- package/dist/shared/agent/model.config.d.ts +41 -2
- package/dist/shared/agent/model.config.d.ts.map +1 -1
- package/dist/shared/agent/model.config.js +98 -1
- package/dist/shared/agent/model.config.js.map +1 -1
- package/dist/shared/hyde/hyde.generator.d.ts.map +1 -1
- package/dist/shared/hyde/hyde.generator.js +2 -3
- package/dist/shared/hyde/hyde.generator.js.map +1 -1
- package/dist/shared/hyde/lens.inferrer.d.ts.map +1 -1
- package/dist/shared/hyde/lens.inferrer.js +2 -3
- package/dist/shared/hyde/lens.inferrer.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat.interrupt.classifier.d.ts","sourceRoot":"/","sources":["chat/chat.interrupt.classifier.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"chat.interrupt.classifier.d.ts","sourceRoot":"/","sources":["chat/chat.interrupt.classifier.ts"],"names":[],"mappings":"AAiBA,MAAM,WAAW,sBAAsB;IACrC,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,qBAAa,uBAAuB;IAClC,OAAO,CAAC,KAAK,CAA0C;;IAMvD;;;;;OAKG;IAEG,QAAQ,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,OAAO,GAAG,OAAO,CAAC;CAuB1E"}
|
|
@@ -10,7 +10,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
10
10
|
import { HumanMessage, SystemMessage } from "@langchain/core/messages";
|
|
11
11
|
import { log } from "../shared/observability/log.js";
|
|
12
12
|
import { Timed } from "../shared/observability/performance.js";
|
|
13
|
-
import {
|
|
13
|
+
import { createResilientModel } from "../shared/agent/model.config.js";
|
|
14
14
|
import { invokeWithAbortSignal } from "../shared/agent/model-signal.js";
|
|
15
15
|
const logger = log.lib.from("ChatInterruptClassifier");
|
|
16
16
|
const SYSTEM_PROMPT = `You decide whether a new user message sent during an active AI process should STEER or QUEUE.
|
|
@@ -27,7 +27,7 @@ Rules:
|
|
|
27
27
|
*/
|
|
28
28
|
export class ChatInterruptClassifier {
|
|
29
29
|
constructor() {
|
|
30
|
-
this.model =
|
|
30
|
+
this.model = createResilientModel("interruptClassifier");
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
33
|
* Classify a mid-stream interrupt as steer or queue.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat.interrupt.classifier.js","sourceRoot":"/","sources":["chat/chat.interrupt.classifier.ts"],"names":[],"mappings":";;;;;;;;;
|
|
1
|
+
{"version":3,"file":"chat.interrupt.classifier.js","sourceRoot":"/","sources":["chat/chat.interrupt.classifier.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEvE,OAAO,EAAE,GAAG,EAAE,MAAM,gCAAgC,CAAC;AACrD,OAAO,EAAE,KAAK,EAAE,MAAM,wCAAwC,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAExE,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;AAEvD,MAAM,aAAa,GAAG;;;;;;oCAMc,CAAC;AAYrC;;;;GAIG;AACH,MAAM,OAAO,uBAAuB;IAGlC;QACE,IAAI,CAAC,KAAK,GAAG,oBAAoB,CAAC,qBAAqB,CAAC,CAAC;IAC3D,CAAC;IAED;;;;;OAKG;IAEG,AAAN,KAAK,CAAC,QAAQ,CAAC,KAA6B;QAC1C,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC;QAEtC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,qBAAqB,CAAC,IAAI,CAAC,KAAK,EAAE;gBACvD,IAAI,aAAa,CAAC,aAAa,CAAC;gBAChC,IAAI,YAAY,CACd,2BAA2B,UAAU,IAAI,MAAM,0BAA0B,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,gBAAgB,CAC/G;aACF,CAAC,CAAC;YAEH,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;YAEjE,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;gBAAE,OAAO,OAAO,CAAC;YAC7C,yDAAyD;YACzD,OAAO,OAAO,CAAC;QACjB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,+EAA+E,EAAE;gBAC3F,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;aAC9D,CAAC,CAAC;YACH,OAAO,OAAO,CAAC;QACjB,CAAC;IACH,CAAC;CACF;AAvBO;IADL,KAAK,EAAE;;;;uDAuBP","sourcesContent":["import { HumanMessage, SystemMessage } from \"@langchain/core/messages\";\n\nimport { log } from \"../shared/observability/log.js\";\nimport { Timed } from \"../shared/observability/performance.js\";\nimport { createResilientModel } from \"../shared/agent/model.config.js\";\nimport { invokeWithAbortSignal } from \"../shared/agent/model-signal.js\";\n\nconst logger = log.lib.from(\"ChatInterruptClassifier\");\n\nconst SYSTEM_PROMPT = `You decide whether a new user message sent during an active AI process should STEER or QUEUE.\n\nRules:\n- Reply with ONLY one word: steer or queue (lowercase).\n- STEER: the message redirects, corrects, stops, contradicts, or changes what the AI is doing. Keywords: \"wait\", \"stop\", \"actually\", \"ignore that\", \"instead\", \"no\", \"cancel\".\n- QUEUE: the message adds context, asks a follow-up, or complements what the AI is doing. Keywords: \"also\", \"and\", \"when done\", \"additionally\", \"plus\".\n- When ambiguous, default to steer.`;\n\nexport interface ClassifyInterruptInput {\n /** The new user message sent while the agent is running. */\n message: string;\n /**\n * Current agent activity summary derived from the last few SSE trace event names\n * (e.g. \"tool_start: discover_opportunities, graph_start: opportunity\").\n */\n agentState: string;\n}\n\n/**\n * Binary classifier that decides whether a mid-stream user message should steer\n * (interrupt the current run) or queue (buffer until the run completes).\n * Uses a low-temperature, minimal-token model for sub-1 s latency.\n */\nexport class ChatInterruptClassifier {\n private model: ReturnType<typeof createResilientModel>;\n\n constructor() {\n this.model = createResilientModel(\"interruptClassifier\");\n }\n\n /**\n * Classify a mid-stream interrupt as steer or queue.\n *\n * @param input - The new message and current agent state context\n * @returns \"steer\" to interrupt the current run; \"queue\" to buffer\n */\n @Timed()\n async classify(input: ClassifyInterruptInput): Promise<\"steer\" | \"queue\"> {\n const { message, agentState } = input;\n\n try {\n const response = await invokeWithAbortSignal(this.model, [\n new SystemMessage(SYSTEM_PROMPT),\n new HumanMessage(\n `Current agent activity: ${agentState || \"idle\"}\\n\\nNew user message: \"${message.slice(0, 500)}\"\\n\\nDecision:`,\n ),\n ]);\n\n const text = String(response.content ?? \"\").trim().toLowerCase();\n\n if (text.startsWith(\"queue\")) return \"queue\";\n // Default to steer on any ambiguity or unexpected output\n return \"steer\";\n } catch (error) {\n logger.warn(\"[ChatInterruptClassifier.classify] Classification failed, defaulting to steer\", {\n error: error instanceof Error ? error.message : String(error),\n });\n return \"steer\";\n }\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat.suggester.d.ts","sourceRoot":"/","sources":["chat/chat.suggester.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"chat.suggester.d.ts","sourceRoot":"/","sources":["chat/chat.suggester.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAkChE,MAAM,WAAW,wBAAwB;IACvC,+DAA+D;IAC/D,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjE,6DAA6D;IAC7D,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,KAAK,CAA2C;;IAMxD;;;OAGG;IAEG,QAAQ,CAAC,KAAK,EAAE,wBAAwB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;CAsC3E"}
|
|
@@ -11,7 +11,7 @@ import { HumanMessage, SystemMessage } from "@langchain/core/messages";
|
|
|
11
11
|
import { z } from "zod";
|
|
12
12
|
import { protocolLogger } from "../shared/observability/protocol.logger.js";
|
|
13
13
|
import { Timed } from "../shared/observability/performance.js";
|
|
14
|
-
import {
|
|
14
|
+
import { createStructuredModel } from "../shared/agent/model.config.js";
|
|
15
15
|
import { invokeWithAbortSignal } from "../shared/agent/model-signal.js";
|
|
16
16
|
const logger = protocolLogger("SuggestionGenerator");
|
|
17
17
|
const suggestionItemSchema = z.object({
|
|
@@ -43,8 +43,7 @@ Rules:
|
|
|
43
43
|
*/
|
|
44
44
|
export class SuggestionGenerator {
|
|
45
45
|
constructor() {
|
|
46
|
-
|
|
47
|
-
this.model = llm.withStructuredOutput(suggestionsSchema, { name: "chat_suggestions" });
|
|
46
|
+
this.model = createStructuredModel("suggestionGenerator", suggestionsSchema, { name: "chat_suggestions" });
|
|
48
47
|
}
|
|
49
48
|
/**
|
|
50
49
|
* Generate follow-up suggestions from the last exchange.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat.suggester.js","sourceRoot":"/","sources":["chat/chat.suggester.ts"],"names":[],"mappings":";;;;;;;;;
|
|
1
|
+
{"version":3,"file":"chat.suggester.js","sourceRoot":"/","sources":["chat/chat.suggester.ts"],"names":[],"mappings":"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","sourcesContent":["import { HumanMessage, SystemMessage } from \"@langchain/core/messages\";\nimport { z } from \"zod\";\nimport type { ChatSuggestion } from \"./chat-streaming.types.js\";\nimport { protocolLogger } from \"../shared/observability/protocol.logger.js\";\nimport { Timed } from \"../shared/observability/performance.js\";\nimport { createStructuredModel } from \"../shared/agent/model.config.js\";\nimport { invokeWithAbortSignal } from \"../shared/agent/model-signal.js\";\n\nconst logger = protocolLogger(\"SuggestionGenerator\");\n\nconst suggestionItemSchema = z.object({\n label: z.string().describe(\"Short label for the chip (2-5 words)\"),\n type: z.enum([\"direct\", \"prompt\"]).describe(\"direct = auto-submit message; prompt = prefill input\"),\n followupText: z.string().nullable().describe(\"For type=direct: full message to send when clicked; null for prompt type\"),\n prefill: z.string().nullable().describe(\"For type=prompt: text to prefill the input; null for direct type\"),\n});\n\nconst suggestionsSchema = z.object({\n suggestions: z\n .array(suggestionItemSchema)\n .min(1)\n .max(6)\n .describe(\"3-5 follow-up suggestions based on the conversation\"),\n});\n\nconst SYSTEM_PROMPT = `You generate follow-up suggestions for a chat user based on their conversation.\n\nRules:\n- Return 3-5 suggestions. Mix of \"direct\" (one-click send) and \"prompt\" (prefill for user to edit).\n- Labels must be short: 2-5 words (e.g. \"Find collaborators\", \"Add more details\").\n- For type=direct: provide followupText as the exact message to send (complete sentence).\n- For type=prompt: provide prefill as the start of a sentence the user can complete (e.g. \"I need help with \").\n- Suggestions must be relevant to the last exchange and natural next steps.\n- Do not repeat what the user or assistant just said; suggest logical follow-ups.\n- Voice: Calm, direct; no hype or networking clichés. Prefer words like opportunity, overlap, signal, pattern, relevant. Avoid: search, leverage, networking, match, optimize, scale.`;\n\nexport interface SuggestionGeneratorInput {\n /** Last few messages (user and assistant) to derive context */\n messages: Array<{ role: \"user\" | \"assistant\"; content: string }>;\n /** Optional index/community context to tailor suggestions */\n indexContext?: string;\n}\n\n/**\n * Lightweight generator for context-aware chat follow-up suggestions.\n * Uses a fast model and structured output to return 3-5 suggestions per call.\n */\nexport class SuggestionGenerator {\n private model: ReturnType<typeof createStructuredModel>;\n\n constructor() {\n this.model = createStructuredModel(\"suggestionGenerator\", suggestionsSchema, { name: \"chat_suggestions\" });\n }\n\n /**\n * Generate follow-up suggestions from the last exchange.\n * Returns empty array on failure (graceful degradation).\n */\n @Timed()\n async generate(input: SuggestionGeneratorInput): Promise<ChatSuggestion[]> {\n const { messages, indexContext } = input;\n if (messages.length === 0) return [];\n\n const excerpt = messages\n .slice(-6)\n .map((m) => `${m.role === \"user\" ? \"User\" : \"Assistant\"}: ${m.content.slice(0, 300)}`)\n .join(\"\\n\\n\");\n\n const userContent = indexContext\n ? `Conversation (community context: ${indexContext}):\\n\\n${excerpt}\\n\\nGenerate 3-5 follow-up suggestions.`\n : `Conversation:\\n\\n${excerpt}\\n\\nGenerate 3-5 follow-up suggestions.`;\n\n try {\n const result = await invokeWithAbortSignal(this.model, [\n new SystemMessage(SYSTEM_PROMPT),\n new HumanMessage(userContent),\n ]);\n const parsed = suggestionsSchema.safeParse(result);\n if (!parsed.success) {\n logger.warn(\"[SuggestionGenerator] Parse failed\", { error: parsed.error.message });\n return [];\n }\n const out: ChatSuggestion[] = parsed.data.suggestions.map((s) => ({\n label: s.label,\n type: s.type,\n ...(s.type === \"direct\" && s.followupText != null && { followupText: s.followupText }),\n ...(s.type === \"prompt\" && s.prefill != null && { prefill: s.prefill }),\n }));\n logger.verbose(\"[SuggestionGenerator] Generated\", { count: out.length });\n return out;\n } catch (error) {\n logger.warn(\"[SuggestionGenerator] Failed\", {\n error: error instanceof Error ? error.message : String(error),\n });\n return [];\n }\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat.summarizer.d.ts","sourceRoot":"/","sources":["chat/chat.summarizer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"chat.summarizer.d.ts","sourceRoot":"/","sources":["chat/chat.summarizer.ts"],"names":[],"mappings":"AAWA,OAAO,EAA2B,KAAK,iBAAiB,EAAE,MAAM,0CAA0C,CAAC;AAwB3G,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,cAAc,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACzC,WAAW,EAAE,qBAAqB,EAAE,CAAC;CACtC;AAED,6CAA6C;AAC7C,qBAAa,cAAc;IACzB,OAAO,CAAC,KAAK,CAA2C;;IAQxD;;;;OAIG;IAEG,SAAS,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;CAyC/E"}
|
|
@@ -7,9 +7,18 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
8
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
9
|
};
|
|
10
|
+
/**
|
|
11
|
+
* ChatSummarizer — rolling, incremental digest of a chat session. Takes the
|
|
12
|
+
* previous persisted digest (if any) plus messages added since, returns a
|
|
13
|
+
* structured ChatContextDigest. Pure: no DB, no events. Persistence is the
|
|
14
|
+
* caller's responsibility (see backend ChatSummaryService).
|
|
15
|
+
*
|
|
16
|
+
* The model is instructed to drop entries in the previous digest that newer
|
|
17
|
+
* messages override, keeping the digest bounded as the session grows.
|
|
18
|
+
*/
|
|
10
19
|
import { HumanMessage, SystemMessage } from "@langchain/core/messages";
|
|
11
20
|
import { ChatContextDigestSchema } from "../shared/schemas/chat-context.schema.js";
|
|
12
|
-
import {
|
|
21
|
+
import { createStructuredModel } from "../shared/agent/model.config.js";
|
|
13
22
|
import { invokeWithAbortSignal } from "../shared/agent/model-signal.js";
|
|
14
23
|
import { protocolLogger } from "../shared/observability/protocol.logger.js";
|
|
15
24
|
import { Timed } from "../shared/observability/performance.js";
|
|
@@ -31,8 +40,7 @@ Rules:
|
|
|
31
40
|
/** Pure LLM summarizer; no DB, no events. */
|
|
32
41
|
export class ChatSummarizer {
|
|
33
42
|
constructor() {
|
|
34
|
-
|
|
35
|
-
this.model = llm.withStructuredOutput(ChatContextDigestSchema, {
|
|
43
|
+
this.model = createStructuredModel("chatContextSummarizer", ChatContextDigestSchema, {
|
|
36
44
|
name: "chat_context_digest",
|
|
37
45
|
});
|
|
38
46
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat.summarizer.js","sourceRoot":"/","sources":["chat/chat.summarizer.ts"],"names":[],"mappings":";;;;;;;;;
|
|
1
|
+
{"version":3,"file":"chat.summarizer.js","sourceRoot":"/","sources":["chat/chat.summarizer.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * ChatSummarizer — rolling, incremental digest of a chat session. Takes the\n * previous persisted digest (if any) plus messages added since, returns a\n * structured ChatContextDigest. Pure: no DB, no events. Persistence is the\n * caller's responsibility (see backend ChatSummaryService).\n *\n * The model is instructed to drop entries in the previous digest that newer\n * messages override, keeping the digest bounded as the session grows.\n */\nimport { HumanMessage, SystemMessage } from \"@langchain/core/messages\";\n\nimport { ChatContextDigestSchema, type ChatContextDigest } from \"../shared/schemas/chat-context.schema.js\";\nimport { createStructuredModel } from \"../shared/agent/model.config.js\";\nimport { invokeWithAbortSignal } from \"../shared/agent/model-signal.js\";\nimport { protocolLogger } from \"../shared/observability/protocol.logger.js\";\nimport { Timed } from \"../shared/observability/performance.js\";\n\nconst logger = protocolLogger(\"ChatSummarizer\");\n\nconst MESSAGE_CONTENT_CAP = 240;\n\nconst SYSTEM_PROMPT = `You distill chat sessions into a compact structured digest used to keep an assistant from asking obvious questions.\n\nOutput four arrays:\n- statedFacts: facts the user volunteered (stage, location, role, timing, scope, budget, …).\n- openQuestions: questions the assistant asked that the user has not yet answered.\n- rejectionReasons: pushback the user gave on prior assistant proposals (e.g. \"none of these fit — all US-based\").\n- surfacedFindings: facts the assistant has already shared with the user from prior negotiation results.\n\nRules:\n- Drop entries from the previous digest that newer messages override or contradict.\n- Keep each entry short (≤140 chars), specific, and standalone.\n- Bound the digest: at most 20 statedFacts, 10 openQuestions, 10 rejectionReasons, 20 surfacedFindings. Drop the least relevant when over.\n- Never invent facts. If the digest is empty for a category, output an empty array.`;\n\nexport interface ChatSummarizerMessage {\n role: \"user\" | \"assistant\";\n content: string;\n}\n\nexport interface ChatSummarizerInput {\n previousDigest: ChatContextDigest | null;\n newMessages: ChatSummarizerMessage[];\n}\n\n/** Pure LLM summarizer; no DB, no events. */\nexport class ChatSummarizer {\n private model: ReturnType<typeof createStructuredModel>;\n\n constructor() {\n this.model = createStructuredModel(\"chatContextSummarizer\", ChatContextDigestSchema, {\n name: \"chat_context_digest\",\n });\n }\n\n /**\n * Summarize a chat session into a bounded structured digest.\n * @param input - Previous digest (or null) and any messages added since.\n * @returns Updated digest, or null on LLM failure / first-time empty input.\n */\n @Timed()\n async summarize(input: ChatSummarizerInput): Promise<ChatContextDigest | null> {\n if (input.newMessages.length === 0) {\n return input.previousDigest;\n }\n\n const truncated = input.newMessages.map((m) => ({\n role: m.role,\n content: m.content.length > MESSAGE_CONTENT_CAP\n ? m.content.slice(0, MESSAGE_CONTENT_CAP)\n : m.content,\n }));\n\n const user = [\n input.previousDigest\n ? `Previous digest:\\n${JSON.stringify(input.previousDigest, null, 2)}`\n : \"Previous digest: (none — this is the first summarization for this session)\",\n \"\",\n \"New messages (since previous digest):\",\n ...truncated.map((m) => ` [${m.role}] ${m.content}`),\n \"\",\n \"Produce the updated digest now.\",\n ].join(\"\\n\");\n\n try {\n const response = await invokeWithAbortSignal(this.model, [\n new SystemMessage(SYSTEM_PROMPT),\n new HumanMessage(user),\n ]);\n const parsed = ChatContextDigestSchema.safeParse(response);\n if (!parsed.success) {\n logger.warn(\"ChatSummarizer parse failed\", { error: parsed.error.message });\n return null;\n }\n return parsed.data;\n } catch (err) {\n logger.warn(\"ChatSummarizer LLM call failed\", {\n error: err instanceof Error ? err.message : String(err),\n });\n return null;\n }\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat.title.generator.d.ts","sourceRoot":"/","sources":["chat/chat.title.generator.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"chat.title.generator.d.ts","sourceRoot":"/","sources":["chat/chat.title.generator.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpD;AAED;;;GAGG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,KAAK,CAA0C;;IAMvD;;;OAGG;IAEG,MAAM,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC;CA0B1D"}
|
|
@@ -10,7 +10,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
10
10
|
import { HumanMessage, SystemMessage } from "@langchain/core/messages";
|
|
11
11
|
import { log } from "../shared/observability/log.js";
|
|
12
12
|
import { Timed } from "../shared/observability/performance.js";
|
|
13
|
-
import {
|
|
13
|
+
import { createResilientModel } from "../shared/agent/model.config.js";
|
|
14
14
|
import { invokeWithAbortSignal } from "../shared/agent/model-signal.js";
|
|
15
15
|
const logger = log.lib.from("ChatTitleGenerator");
|
|
16
16
|
const SYSTEM_PROMPT = `You suggest a very short title for a chat conversation.
|
|
@@ -26,7 +26,7 @@ Rules:
|
|
|
26
26
|
*/
|
|
27
27
|
export class ChatTitleGenerator {
|
|
28
28
|
constructor() {
|
|
29
|
-
this.model =
|
|
29
|
+
this.model = createResilientModel("chatTitleGenerator");
|
|
30
30
|
}
|
|
31
31
|
/**
|
|
32
32
|
* Suggests a title from the conversation excerpt.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat.title.generator.js","sourceRoot":"/","sources":["chat/chat.title.generator.ts"],"names":[],"mappings":";;;;;;;;;
|
|
1
|
+
{"version":3,"file":"chat.title.generator.js","sourceRoot":"/","sources":["chat/chat.title.generator.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEvE,OAAO,EAAE,GAAG,EAAE,MAAM,gCAAgC,CAAC;AACrD,OAAO,EAAE,KAAK,EAAE,MAAM,wCAAwC,CAAC;AAE/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAExE,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;AAElD,MAAM,aAAa,GAAG;;;;;;+DAMyC,CAAC;AAMhE;;;GAGG;AACH,MAAM,OAAO,kBAAkB;IAG7B;QACE,IAAI,CAAC,KAAK,GAAG,oBAAoB,CAAC,oBAAoB,CAAC,CAAC;IAC1D,CAAC;IAED;;;OAGG;IAEG,AAAN,KAAK,CAAC,MAAM,CAAC,KAA0B;QACrC,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;QAC3B,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,UAAU,CAAC;QAE7C,MAAM,OAAO,GAAG,QAAQ;aACrB,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;aACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;aACrF,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,qBAAqB,CAAC,IAAI,CAAC,KAAK,EAAE;gBACvD,IAAI,aAAa,CAAC,aAAa,CAAC;gBAChC,IAAI,YAAY,CAAC,kBAAkB,OAAO,sBAAsB,CAAC;aAClE,CAAC,CAAC;YAEH,MAAM,IAAI,GAAG,OAAO,QAAQ,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YAC7G,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,UAAU,CAAC;YACrD,MAAM,CAAC,OAAO,CAAC,6CAA6C,EAAE,EAAE,WAAW,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;YAC7F,OAAO,KAAK,CAAC;QACf,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,sDAAsD,EAAE;gBAClE,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;aAC9D,CAAC,CAAC;YACH,OAAO,UAAU,CAAC;QACpB,CAAC;IACH,CAAC;CACF;AA1BO;IADL,KAAK,EAAE;;;;gDA0BP","sourcesContent":["import { HumanMessage, SystemMessage } from \"@langchain/core/messages\";\n\nimport { log } from \"../shared/observability/log.js\";\nimport { Timed } from \"../shared/observability/performance.js\";\n\nimport { createResilientModel } from \"../shared/agent/model.config.js\";\nimport { invokeWithAbortSignal } from \"../shared/agent/model-signal.js\";\n\nconst logger = log.lib.from(\"ChatTitleGenerator\");\n\nconst SYSTEM_PROMPT = `You suggest a very short title for a chat conversation.\n\nRules:\n- Reply with ONLY the title, no quotes or punctuation.\n- Maximum 6 words.\n- If the conversation is just greetings (hi, hello, hey, thanks) or has no clear topic yet, reply with exactly: New chat\n- Otherwise summarize the main topic or intent in a few words.`;\n\nexport interface TitleGeneratorInput {\n messages: Array<{ role: string; content: string }>;\n}\n\n/**\n * Generates a short, descriptive title for a chat session using the first exchange.\n * Only meaningful when there is at least one user message and one assistant message.\n */\nexport class ChatTitleGenerator {\n private model: ReturnType<typeof createResilientModel>;\n\n constructor() {\n this.model = createResilientModel(\"chatTitleGenerator\");\n }\n\n /**\n * Suggests a title from the conversation excerpt.\n * Call only when there is at least one user and one assistant message.\n */\n @Timed()\n async invoke(input: TitleGeneratorInput): Promise<string> {\n const { messages } = input;\n if (messages.length === 0) return \"New chat\";\n\n const excerpt = messages\n .slice(0, 6)\n .map((m) => `${m.role === \"user\" ? \"User\" : \"Assistant\"}: ${m.content.slice(0, 200)}`)\n .join(\"\\n\");\n\n try {\n const response = await invokeWithAbortSignal(this.model, [\n new SystemMessage(SYSTEM_PROMPT),\n new HumanMessage(`Conversation:\\n${excerpt}\\n\\nSuggested title:`),\n ]);\n\n const text = typeof response.content === \"string\" ? response.content : String(response.content ?? \"\").trim();\n const title = text.slice(0, 80).trim() || \"New chat\";\n logger.verbose(\"[ChatTitleGenerator.invoke] Title generated\", { titleLength: title.length });\n return title;\n } catch (error) {\n logger.warn(\"[ChatTitleGenerator.invoke] Failed to generate title\", {\n error: error instanceof Error ? error.message : String(error),\n });\n return \"New chat\";\n }\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contact.inviter.d.ts","sourceRoot":"/","sources":["contact/contact.inviter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"contact.inviter.d.ts","sourceRoot":"/","sources":["contact/contact.inviter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,QAAA,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;EAOrB,CAAC;AAEH,QAAA,MAAM,kBAAkB;;;;;;EAEtB,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC5D,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAgB9D;;;;GAIG;AACH,wBAAsB,qBAAqB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAkBrF"}
|
|
@@ -7,8 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { HumanMessage, SystemMessage } from "@langchain/core/messages";
|
|
9
9
|
import { z } from "zod";
|
|
10
|
-
import {
|
|
11
|
-
const model = createModel("inviteGenerator");
|
|
10
|
+
import { createStructuredModel } from "../shared/agent/model.config.js";
|
|
12
11
|
const InviteInputSchema = z.object({
|
|
13
12
|
recipientName: z.string(),
|
|
14
13
|
senderName: z.string(),
|
|
@@ -40,7 +39,7 @@ Do NOT use placeholder brackets like [Name]. Use the actual names provided.`;
|
|
|
40
39
|
*/
|
|
41
40
|
export async function generateInviteMessage(input) {
|
|
42
41
|
const validated = InviteInputSchema.parse(input);
|
|
43
|
-
const structuredModel =
|
|
42
|
+
const structuredModel = createStructuredModel("inviteGenerator", InviteOutputSchema);
|
|
44
43
|
const userPrompt = `Generate an invite message with this context:
|
|
45
44
|
- Sender: ${validated.senderName}
|
|
46
45
|
- Recipient: ${validated.recipientName}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contact.inviter.js","sourceRoot":"/","sources":["contact/contact.inviter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACvE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"contact.inviter.js","sourceRoot":"/","sources":["contact/contact.inviter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACvE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAExE,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE;IACzB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;IACtB,yBAAyB,EAAE,CAAC,CAAC,MAAM,EAAE;IACrC,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAClC,gBAAgB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IACrC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACpC,CAAC,CAAC;AAEH,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iDAAiD,CAAC;CAChF,CAAC,CAAC;AAKH,MAAM,aAAa,GAAG;;;;;;;;;;;;4EAYsD,CAAC;AAE7E;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,KAAkB;IAC5D,MAAM,SAAS,GAAG,iBAAiB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAEjD,MAAM,eAAe,GAAG,qBAAqB,CAAC,iBAAiB,EAAE,kBAAkB,CAAC,CAAC;IAErF,MAAM,UAAU,GAAG;YACT,SAAS,CAAC,UAAU;eACjB,SAAS,CAAC,aAAa;sBAChB,SAAS,CAAC,yBAAyB;wBACjC,SAAS,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,eAAe;2BAClD,SAAS,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,eAAe,GAAG,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,oBAAoB,SAAS,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IAEjK,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,MAAM,CAAC;QAC1C,IAAI,aAAa,CAAC,aAAa,CAAC;QAChC,IAAI,YAAY,CAAC,UAAU,CAAC;KAC7B,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["/**\n * Invite Generator Agent\n *\n * Generates contextual, editable invite messages for ghost users.\n * Produces warm, concise messages (~3-5 sentences) referencing why two\n * users were matched, with optional referrer mention.\n */\n\nimport { HumanMessage, SystemMessage } from \"@langchain/core/messages\";\nimport { z } from \"zod\";\n\nimport { createStructuredModel } from \"../shared/agent/model.config.js\";\n\nconst InviteInputSchema = z.object({\n recipientName: z.string(),\n senderName: z.string(),\n opportunityInterpretation: z.string(),\n senderIntents: z.array(z.string()),\n recipientIntents: z.array(z.string()),\n referrerName: z.string().optional(),\n});\n\nconst InviteOutputSchema = z.object({\n message: z.string().describe(\"The invite message text, ready to edit and send\"),\n});\n\nexport type InviteInput = z.infer<typeof InviteInputSchema>;\nexport type InviteOutput = z.infer<typeof InviteOutputSchema>;\n\nconst SYSTEM_PROMPT = `You generate brief, casual invite messages for a discovery platform called Index.\n\nThe sender wants to reach out to someone they were matched with. Write a short, human message (2-3 sentences max) that:\n- Sounds like a real person texting, not a LinkedIn outreach or AI email\n- References one concrete, specific detail from the opportunity context — something actual, like a specific project, technology, or goal they share. Not \"we have similar interests\" or \"I noticed we're both in this space\" — name the actual thing.\n- If a referrer is provided, casually drops that they were introduced\n- Ends naturally — no formal CTAs, no \"Would you be open to...\" closings\n\nTone: casual, direct, human. Think how you'd actually message someone you just got introduced to.\nDo NOT use a generic opener like \"Hi [Name], I'm [Sender].\" Just get to the point.\nDo NOT summarize the person's background. Pick one real, specific overlap from the context and mention it.\nDo NOT include a subject line. This is a chat message.\nDo NOT use placeholder brackets like [Name]. Use the actual names provided.`;\n\n/**\n * Generates a contextual invite message for a ghost user.\n * @param input - Context about sender, recipient, and opportunity\n * @returns Generated invite message text\n */\nexport async function generateInviteMessage(input: InviteInput): Promise<InviteOutput> {\n const validated = InviteInputSchema.parse(input);\n\n const structuredModel = createStructuredModel(\"inviteGenerator\", InviteOutputSchema);\n\n const userPrompt = `Generate an invite message with this context:\n- Sender: ${validated.senderName}\n- Recipient: ${validated.recipientName}\n- Why they matched: ${validated.opportunityInterpretation}\n- Sender's interests: ${validated.senderIntents.join(', ') || 'Not specified'}\n- Recipient's interests: ${validated.recipientIntents.join(', ') || 'Not specified'}${validated.referrerName ? `\\n- Referred by: ${validated.referrerName}` : ''}`;\n\n const result = await structuredModel.invoke([\n new SystemMessage(SYSTEM_PROMPT),\n new HumanMessage(userPrompt),\n ]);\n\n return result;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.generator.d.ts","sourceRoot":"/","sources":["context/context.generator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4CAA4C,CAAC;AAErF,2EAA2E;AAC3E,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,yEAAyE;AACzE,MAAM,WAAW,uBAAuB;IACtC,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,OAAO,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;IAC1D,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,yEAAyE;AACzE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACnC;AAED,gFAAgF;AAChF,MAAM,WAAW,6BAA6B;IAC5C,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,OAAO,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;IAC1D,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,6DAA6D;AAC7D,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAUD;;;GAGG;AACH,qBAAa,oBAAoB;IAGnB,OAAO,CAAC,kBAAkB;IAFtC,OAAO,CAAC,KAAK,
|
|
1
|
+
{"version":3,"file":"context.generator.d.ts","sourceRoot":"/","sources":["context/context.generator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4CAA4C,CAAC;AAErF,2EAA2E;AAC3E,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,yEAAyE;AACzE,MAAM,WAAW,uBAAuB;IACtC,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,OAAO,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;IAC1D,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,yEAAyE;AACzE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACnC;AAED,gFAAgF;AAChF,MAAM,WAAW,6BAA6B;IAC5C,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,OAAO,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;IAC1D,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,6DAA6D;AAC7D,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAUD;;;GAGG;AACH,qBAAa,oBAAoB;IAGnB,OAAO,CAAC,kBAAkB;IAFtC,OAAO,CAAC,KAAK,CAAgD;gBAEzC,kBAAkB,EAAE,kBAAkB;IAE1D;;;;;OAKG;IACG,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAiB5E;;;;;OAKG;IACG,mBAAmB,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAiBrF;;;;;;;OAOG;IACG,uBAAuB,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAgBpF;;;;;OAKG;IACG,yBAAyB,CAAC,KAAK,EAAE,6BAA6B,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAgBjG,4DAA4D;IAC5D,OAAO,CAAC,WAAW;IAMnB,yDAAyD;IACzD,OAAO,CAAC,oBAAoB;IAM5B,8DAA8D;IAC9D,OAAO,CAAC,cAAc;IAatB,iEAAiE;YACnD,KAAK;CAIpB"}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* Returns { text, embedding } for storage.
|
|
12
12
|
*/
|
|
13
13
|
import { HumanMessage, SystemMessage } from "@langchain/core/messages";
|
|
14
|
-
import {
|
|
14
|
+
import { createResilientModel } from "../shared/agent/model.config.js";
|
|
15
15
|
import { getAbortSignalConfig, invokeWithAbortSignal } from "../shared/agent/model-signal.js";
|
|
16
16
|
const COLD_START_SYSTEM_PROMPT = `You synthesize user context paragraphs for community matching. Given a list of premises (atomic facts about a person) and a network description, write a focused paragraph (3-6 sentences) that captures who this person is through the lens of that network's purpose. Highlight what is most relevant to the network. Write in third person. Be specific and concrete, not generic.`;
|
|
17
17
|
const INCREMENTAL_SYSTEM_PROMPT = `You maintain user context paragraphs for community matching. You will receive the current context paragraph, a change that occurred, and the network description. Update the context paragraph to reflect the change while preserving all other information. Keep the same style: 3-6 sentences, third person, specific and concrete. For retractions/expirations, remove the relevant information. For additions/updates, integrate the new information naturally.`;
|
|
@@ -24,7 +24,7 @@ const GLOBAL_INCREMENTAL_SYSTEM_PROMPT = `You maintain a person's global identit
|
|
|
24
24
|
export class UserContextGenerator {
|
|
25
25
|
constructor(embeddingGenerator) {
|
|
26
26
|
this.embeddingGenerator = embeddingGenerator;
|
|
27
|
-
this.model =
|
|
27
|
+
this.model = createResilientModel('userContextGenerator');
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
30
30
|
* Generate a context paragraph from the full set of premises (cold-start).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.generator.js","sourceRoot":"/","sources":["context/context.generator.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * User Context Generator\n *\n * Synthesizes context paragraphs from user premises for storage in the\n * user_contexts table. Two scopes:\n * - network-scoped: who the person is through the lens of a given network\n * - global (networkId = null): a cohesive, network-agnostic identity paragraph\n * that replaces the legacy synthesized user_profile projection.\n * Each scope supports cold-start (all premises at once) and incremental\n * (single premise change applied to an existing context).\n * Returns { text, embedding } for storage.\n */\n\nimport { HumanMessage, SystemMessage } from \"@langchain/core/messages\";\n\nimport { createModel } from \"../shared/agent/model.config.js\";\nimport { getAbortSignalConfig, invokeWithAbortSignal } from \"../shared/agent/model-signal.js\";\nimport type { EmbeddingGenerator } from \"../shared/interfaces/embedder.interface.js\";\n\n/** Input for cold-start context generation from a full set of premises. */\nexport interface UserContextInput {\n premises: Array<{ text: string }>;\n networkPrompt: string | null;\n networkTitle: string;\n}\n\n/** Input for incremental context update from a single premise change. */\nexport interface IncrementalContextInput {\n currentContext: string;\n changeType: 'added' | 'updated' | 'retracted' | 'expired';\n premiseText: string;\n previousPremiseText?: string;\n networkPrompt: string | null;\n networkTitle: string;\n}\n\n/** Input for cold-start global (network-agnostic) context generation. */\nexport interface GlobalContextInput {\n premises: Array<{ text: string }>;\n}\n\n/** Input for incremental global context update from a single premise change. */\nexport interface GlobalIncrementalContextInput {\n currentContext: string;\n changeType: 'added' | 'updated' | 'retracted' | 'expired';\n premiseText: string;\n previousPremiseText?: string;\n}\n\n/** Generated context paragraph with its embedding vector. */\nexport interface UserContextResult {\n text: string;\n embedding: number[];\n}\n\nconst COLD_START_SYSTEM_PROMPT = `You synthesize user context paragraphs for community matching. Given a list of premises (atomic facts about a person) and a network description, write a focused paragraph (3-6 sentences) that captures who this person is through the lens of that network's purpose. Highlight what is most relevant to the network. Write in third person. Be specific and concrete, not generic.`;\n\nconst INCREMENTAL_SYSTEM_PROMPT = `You maintain user context paragraphs for community matching. You will receive the current context paragraph, a change that occurred, and the network description. Update the context paragraph to reflect the change while preserving all other information. Keep the same style: 3-6 sentences, third person, specific and concrete. For retractions/expirations, remove the relevant information. For additions/updates, integrate the new information naturally.`;\n\nconst GLOBAL_COLD_START_SYSTEM_PROMPT = `You synthesize a person's global identity profile from premises (atomic facts about them). Write a cohesive paragraph (4-8 sentences) capturing who this person is overall — their identity, work, expertise, and interests — independent of any single community or network. This is their canonical self-description, not lensed toward any particular purpose. Write in third person. Be specific and concrete, not generic. Do not invent facts beyond the premises.`;\n\nconst GLOBAL_INCREMENTAL_SYSTEM_PROMPT = `You maintain a person's global identity profile. You will receive the current profile paragraph and a change that occurred. Update the paragraph to reflect the change while preserving all other information. Keep the same style: 4-8 sentences, third person, specific and concrete, network-agnostic. For retractions/expirations, remove the relevant information. For additions/updates, integrate the new information naturally.`;\n\n/**\n * Generates network-scoped context paragraphs from user premises.\n * Uses LLM synthesis to produce focused context and an embedding vector.\n */\nexport class UserContextGenerator {\n private model = createModel('userContextGenerator');\n\n constructor(private embeddingGenerator: EmbeddingGenerator) {}\n\n /**\n * Generate a context paragraph from the full set of premises (cold-start).\n *\n * @param input - Premises, network prompt, and network title\n * @returns Synthesized context text with embedding vector\n */\n async generateColdStart(input: UserContextInput): Promise<UserContextResult> {\n const premiseBlock = input.premises.map(p => `- ${p.text}`).join('\\n');\n const networkContext = this.formatNetworkContext(input.networkPrompt, input.networkTitle);\n\n const response = await invokeWithAbortSignal(this.model, [\n new SystemMessage(COLD_START_SYSTEM_PROMPT),\n new HumanMessage(\n `${networkContext}\\n\\nPremises:\\n${premiseBlock}\\n\\nWrite a focused context paragraph for this person in this network.`,\n ),\n ]);\n\n const text = this.extractText(response.content);\n\n const embedding = await this.embed(text);\n return { text, embedding };\n }\n\n /**\n * Update an existing context paragraph after a single premise change.\n *\n * @param input - Current context, change details, network metadata\n * @returns Updated context text with embedding vector\n */\n async generateIncremental(input: IncrementalContextInput): Promise<UserContextResult> {\n const networkContext = this.formatNetworkContext(input.networkPrompt, input.networkTitle);\n const changeDescription = this.describeChange(input);\n\n const response = await invokeWithAbortSignal(this.model, [\n new SystemMessage(INCREMENTAL_SYSTEM_PROMPT),\n new HumanMessage(\n `${networkContext}\\n\\nCurrent context:\\n${input.currentContext}\\n\\nChange:\\n${changeDescription}\\n\\nWrite the updated context paragraph.`,\n ),\n ]);\n\n const text = this.extractText(response.content);\n\n const embedding = await this.embed(text);\n return { text, embedding };\n }\n\n /**\n * Generate a global (network-agnostic) identity paragraph from the full set\n * of premises (cold-start). This is the profile-replacing projection stored\n * as the user's global user_context row (networkId = null).\n *\n * @param input - The user's active premises\n * @returns Synthesized global identity text with embedding vector\n */\n async generateGlobalColdStart(input: GlobalContextInput): Promise<UserContextResult> {\n const premiseBlock = input.premises.map(p => `- ${p.text}`).join('\\n');\n\n const response = await invokeWithAbortSignal(this.model, [\n new SystemMessage(GLOBAL_COLD_START_SYSTEM_PROMPT),\n new HumanMessage(\n `Premises:\\n${premiseBlock}\\n\\nWrite a cohesive global identity paragraph for this person.`,\n ),\n ]);\n\n const text = this.extractText(response.content);\n\n const embedding = await this.embed(text);\n return { text, embedding };\n }\n\n /**\n * Update the global identity paragraph after a single premise change.\n *\n * @param input - Current global context and change details\n * @returns Updated global identity text with embedding vector\n */\n async generateGlobalIncremental(input: GlobalIncrementalContextInput): Promise<UserContextResult> {\n const changeDescription = this.describeChange(input);\n\n const response = await invokeWithAbortSignal(this.model, [\n new SystemMessage(GLOBAL_INCREMENTAL_SYSTEM_PROMPT),\n new HumanMessage(\n `Current profile:\\n${input.currentContext}\\n\\nChange:\\n${changeDescription}\\n\\nWrite the updated global identity paragraph.`,\n ),\n ]);\n\n const text = this.extractText(response.content);\n\n const embedding = await this.embed(text);\n return { text, embedding };\n }\n\n /** Normalize an LLM message content into a plain string. */\n private extractText(content: unknown): string {\n return typeof content === 'string'\n ? content\n : String(content ?? '').trim();\n }\n\n /** Format the network context header for LLM prompts. */\n private formatNetworkContext(prompt: string | null, title: string): string {\n return prompt\n ? `Network \"${title}\": ${prompt}`\n : `Network: ${title}`;\n }\n\n /** Describe the premise change for the incremental prompt. */\n private describeChange(input: IncrementalContextInput | GlobalIncrementalContextInput): string {\n switch (input.changeType) {\n case 'added':\n return `A new fact was learned about this person:\\n\"${input.premiseText}\"`;\n case 'updated':\n return `A fact was updated.\\nOld: \"${input.previousPremiseText}\"\\nNew: \"${input.premiseText}\"`;\n case 'retracted':\n return `A fact was retracted (no longer true):\\n\"${input.premiseText}\"`;\n case 'expired':\n return `A fact has expired (time-bound, no longer current):\\n\"${input.premiseText}\"`;\n }\n }\n\n /** Generate embedding from text, normalizing the return type. */\n private async embed(text: string): Promise<number[]> {\n const result = await this.embeddingGenerator.generate(text, undefined, getAbortSignalConfig());\n return Array.isArray(result[0]) ? result[0] as number[] : result as number[];\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"context.generator.js","sourceRoot":"/","sources":["context/context.generator.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * User Context Generator\n *\n * Synthesizes context paragraphs from user premises for storage in the\n * user_contexts table. Two scopes:\n * - network-scoped: who the person is through the lens of a given network\n * - global (networkId = null): a cohesive, network-agnostic identity paragraph\n * that replaces the legacy synthesized user_profile projection.\n * Each scope supports cold-start (all premises at once) and incremental\n * (single premise change applied to an existing context).\n * Returns { text, embedding } for storage.\n */\n\nimport { HumanMessage, SystemMessage } from \"@langchain/core/messages\";\n\nimport { createResilientModel } from \"../shared/agent/model.config.js\";\nimport { getAbortSignalConfig, invokeWithAbortSignal } from \"../shared/agent/model-signal.js\";\nimport type { EmbeddingGenerator } from \"../shared/interfaces/embedder.interface.js\";\n\n/** Input for cold-start context generation from a full set of premises. */\nexport interface UserContextInput {\n premises: Array<{ text: string }>;\n networkPrompt: string | null;\n networkTitle: string;\n}\n\n/** Input for incremental context update from a single premise change. */\nexport interface IncrementalContextInput {\n currentContext: string;\n changeType: 'added' | 'updated' | 'retracted' | 'expired';\n premiseText: string;\n previousPremiseText?: string;\n networkPrompt: string | null;\n networkTitle: string;\n}\n\n/** Input for cold-start global (network-agnostic) context generation. */\nexport interface GlobalContextInput {\n premises: Array<{ text: string }>;\n}\n\n/** Input for incremental global context update from a single premise change. */\nexport interface GlobalIncrementalContextInput {\n currentContext: string;\n changeType: 'added' | 'updated' | 'retracted' | 'expired';\n premiseText: string;\n previousPremiseText?: string;\n}\n\n/** Generated context paragraph with its embedding vector. */\nexport interface UserContextResult {\n text: string;\n embedding: number[];\n}\n\nconst COLD_START_SYSTEM_PROMPT = `You synthesize user context paragraphs for community matching. Given a list of premises (atomic facts about a person) and a network description, write a focused paragraph (3-6 sentences) that captures who this person is through the lens of that network's purpose. Highlight what is most relevant to the network. Write in third person. Be specific and concrete, not generic.`;\n\nconst INCREMENTAL_SYSTEM_PROMPT = `You maintain user context paragraphs for community matching. You will receive the current context paragraph, a change that occurred, and the network description. Update the context paragraph to reflect the change while preserving all other information. Keep the same style: 3-6 sentences, third person, specific and concrete. For retractions/expirations, remove the relevant information. For additions/updates, integrate the new information naturally.`;\n\nconst GLOBAL_COLD_START_SYSTEM_PROMPT = `You synthesize a person's global identity profile from premises (atomic facts about them). Write a cohesive paragraph (4-8 sentences) capturing who this person is overall — their identity, work, expertise, and interests — independent of any single community or network. This is their canonical self-description, not lensed toward any particular purpose. Write in third person. Be specific and concrete, not generic. Do not invent facts beyond the premises.`;\n\nconst GLOBAL_INCREMENTAL_SYSTEM_PROMPT = `You maintain a person's global identity profile. You will receive the current profile paragraph and a change that occurred. Update the paragraph to reflect the change while preserving all other information. Keep the same style: 4-8 sentences, third person, specific and concrete, network-agnostic. For retractions/expirations, remove the relevant information. For additions/updates, integrate the new information naturally.`;\n\n/**\n * Generates network-scoped context paragraphs from user premises.\n * Uses LLM synthesis to produce focused context and an embedding vector.\n */\nexport class UserContextGenerator {\n private model = createResilientModel('userContextGenerator');\n\n constructor(private embeddingGenerator: EmbeddingGenerator) {}\n\n /**\n * Generate a context paragraph from the full set of premises (cold-start).\n *\n * @param input - Premises, network prompt, and network title\n * @returns Synthesized context text with embedding vector\n */\n async generateColdStart(input: UserContextInput): Promise<UserContextResult> {\n const premiseBlock = input.premises.map(p => `- ${p.text}`).join('\\n');\n const networkContext = this.formatNetworkContext(input.networkPrompt, input.networkTitle);\n\n const response = await invokeWithAbortSignal(this.model, [\n new SystemMessage(COLD_START_SYSTEM_PROMPT),\n new HumanMessage(\n `${networkContext}\\n\\nPremises:\\n${premiseBlock}\\n\\nWrite a focused context paragraph for this person in this network.`,\n ),\n ]);\n\n const text = this.extractText(response.content);\n\n const embedding = await this.embed(text);\n return { text, embedding };\n }\n\n /**\n * Update an existing context paragraph after a single premise change.\n *\n * @param input - Current context, change details, network metadata\n * @returns Updated context text with embedding vector\n */\n async generateIncremental(input: IncrementalContextInput): Promise<UserContextResult> {\n const networkContext = this.formatNetworkContext(input.networkPrompt, input.networkTitle);\n const changeDescription = this.describeChange(input);\n\n const response = await invokeWithAbortSignal(this.model, [\n new SystemMessage(INCREMENTAL_SYSTEM_PROMPT),\n new HumanMessage(\n `${networkContext}\\n\\nCurrent context:\\n${input.currentContext}\\n\\nChange:\\n${changeDescription}\\n\\nWrite the updated context paragraph.`,\n ),\n ]);\n\n const text = this.extractText(response.content);\n\n const embedding = await this.embed(text);\n return { text, embedding };\n }\n\n /**\n * Generate a global (network-agnostic) identity paragraph from the full set\n * of premises (cold-start). This is the profile-replacing projection stored\n * as the user's global user_context row (networkId = null).\n *\n * @param input - The user's active premises\n * @returns Synthesized global identity text with embedding vector\n */\n async generateGlobalColdStart(input: GlobalContextInput): Promise<UserContextResult> {\n const premiseBlock = input.premises.map(p => `- ${p.text}`).join('\\n');\n\n const response = await invokeWithAbortSignal(this.model, [\n new SystemMessage(GLOBAL_COLD_START_SYSTEM_PROMPT),\n new HumanMessage(\n `Premises:\\n${premiseBlock}\\n\\nWrite a cohesive global identity paragraph for this person.`,\n ),\n ]);\n\n const text = this.extractText(response.content);\n\n const embedding = await this.embed(text);\n return { text, embedding };\n }\n\n /**\n * Update the global identity paragraph after a single premise change.\n *\n * @param input - Current global context and change details\n * @returns Updated global identity text with embedding vector\n */\n async generateGlobalIncremental(input: GlobalIncrementalContextInput): Promise<UserContextResult> {\n const changeDescription = this.describeChange(input);\n\n const response = await invokeWithAbortSignal(this.model, [\n new SystemMessage(GLOBAL_INCREMENTAL_SYSTEM_PROMPT),\n new HumanMessage(\n `Current profile:\\n${input.currentContext}\\n\\nChange:\\n${changeDescription}\\n\\nWrite the updated global identity paragraph.`,\n ),\n ]);\n\n const text = this.extractText(response.content);\n\n const embedding = await this.embed(text);\n return { text, embedding };\n }\n\n /** Normalize an LLM message content into a plain string. */\n private extractText(content: unknown): string {\n return typeof content === 'string'\n ? content\n : String(content ?? '').trim();\n }\n\n /** Format the network context header for LLM prompts. */\n private formatNetworkContext(prompt: string | null, title: string): string {\n return prompt\n ? `Network \"${title}\": ${prompt}`\n : `Network: ${title}`;\n }\n\n /** Describe the premise change for the incremental prompt. */\n private describeChange(input: IncrementalContextInput | GlobalIncrementalContextInput): string {\n switch (input.changeType) {\n case 'added':\n return `A new fact was learned about this person:\\n\"${input.premiseText}\"`;\n case 'updated':\n return `A fact was updated.\\nOld: \"${input.previousPremiseText}\"\\nNew: \"${input.premiseText}\"`;\n case 'retracted':\n return `A fact was retracted (no longer true):\\n\"${input.premiseText}\"`;\n case 'expired':\n return `A fact has expired (time-bound, no longer current):\\n\"${input.premiseText}\"`;\n }\n }\n\n /** Generate embedding from text, normalizing the return type. */\n private async embed(text: string): Promise<number[]> {\n const result = await this.embeddingGenerator.generate(text, undefined, getAbortSignalConfig());\n return Array.isArray(result[0]) ? result[0] as number[] : result as number[];\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"enrichment.generator.d.ts","sourceRoot":"/","sources":["enrichment/enrichment.generator.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAkB3B,QAAA,MAAM,cAAc;;;;;;;;;;;;;iBAalB,CAAC;AAEH,KAAK,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAC9C,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5D,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"enrichment.generator.d.ts","sourceRoot":"/","sources":["enrichment/enrichment.generator.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAkB3B,QAAA,MAAM,cAAc;;;;;;;;;;;;;iBAalB,CAAC;AAEH,KAAK,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAC9C,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5D,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,MAAM,CAAC,WAAW,CAAuD;IACjF,OAAO,CAAC,KAAK,CAAkF;;IAQ/F,OAAO,CAAC,QAAQ;IAeH,MAAM,CAAC,KAAK,EAAE,MAAM;;;;;;;;;;;;;;;;;WAgBnB,MAAM;;;;;;;;;;;;;;;;;;;;;;;CAerB"}
|
|
@@ -12,7 +12,7 @@ import { tool } from "@langchain/core/tools";
|
|
|
12
12
|
import { z } from "zod/v4";
|
|
13
13
|
import { protocolLogger } from "../shared/observability/protocol.logger.js";
|
|
14
14
|
import { Timed } from "../shared/observability/performance.js";
|
|
15
|
-
import {
|
|
15
|
+
import { createStructuredModel } from "../shared/agent/model.config.js";
|
|
16
16
|
import { invokeWithAbortSignal } from "../shared/agent/model-signal.js";
|
|
17
17
|
const logger = protocolLogger("EnrichmentGenerator");
|
|
18
18
|
const systemPrompt = `
|
|
@@ -40,10 +40,9 @@ const responseFormat = z.object({
|
|
|
40
40
|
});
|
|
41
41
|
export class EnrichmentGenerator {
|
|
42
42
|
constructor() {
|
|
43
|
-
|
|
44
|
-
this.model = baseModel.withStructuredOutput(responseFormat, {
|
|
43
|
+
this.model = EnrichmentGenerator.sharedModel ?? (EnrichmentGenerator.sharedModel = createStructuredModel("profileGenerator", responseFormat, {
|
|
45
44
|
name: "profile_generator"
|
|
46
|
-
});
|
|
45
|
+
}));
|
|
47
46
|
}
|
|
48
47
|
toString(profile) {
|
|
49
48
|
return [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"enrichment.generator.js","sourceRoot":"/","sources":["enrichment/enrichment.generator.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACvE,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAC3B,OAAO,EAAE,cAAc,EAAE,MAAM,4CAA4C,CAAC;AAC5E,OAAO,EAAE,KAAK,EAAE,MAAM,wCAAwC,CAAC;AAC/D,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"enrichment.generator.js","sourceRoot":"/","sources":["enrichment/enrichment.generator.ts"],"names":[],"mappings":"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","sourcesContent":["import { HumanMessage, SystemMessage } from \"@langchain/core/messages\";\nimport { tool } from \"@langchain/core/tools\";\nimport { z } from \"zod/v4\";\nimport { protocolLogger } from \"../shared/observability/protocol.logger.js\";\nimport { Timed } from \"../shared/observability/performance.js\";\nimport { createStructuredModel } from \"../shared/agent/model.config.js\";\nimport { invokeWithAbortSignal } from \"../shared/agent/model-signal.js\";\n\nconst logger = protocolLogger(\"EnrichmentGenerator\");\n\nconst systemPrompt = `\n You are an expert profiler. Your task is to synthesize a structured User Profile from raw data or user requests.\n\n When given EXISTING PROFILE + USER REQUEST: Apply the request to the existing profile. Add, update, or remove skills and interests as the user asks. Preserve everything else. Output the full updated profile.\n\n When given raw data only: Infer name, bio, location, narrative.context, and extract skills and interests.\n\n PRIVACY: identity.bio and narrative.context are public-facing. Never include email addresses, phone numbers, physical addresses, government IDs, or other contact identifiers — even if they appear in the raw data. Describe the person professionally; do not embed ways to contact them.\n`;\n\nconst responseFormat = z.object({\n identity: z.object({\n name: z.string().describe(\"The user's full name\"),\n bio: z.string().describe(\"Professional summary (2-3 sentences) only; no email, phone, physical address, government ID, or other contact identifiers\"),\n location: z.string().describe(\"Inferred location (City, Country) or 'Remote'\"),\n }),\n narrative: z.object({\n context: z.string().describe(\"Rich narrative without email, phone, physical address, government ID, or other contact identifiers\"),\n }),\n attributes: z.object({\n interests: z.array(z.string()).describe(\"Inferred or explicit interests\"),\n skills: z.array(z.string()).describe(\"Professional skills\"),\n }),\n});\n\ntype Profile = z.infer<typeof responseFormat>;\nexport type GeneratedProfile = Profile & { userId: string };\n\nexport class EnrichmentGenerator {\n private static sharedModel: ReturnType<typeof createStructuredModel> | undefined;\n private model: { invoke(input: unknown, config?: { signal?: AbortSignal }): Promise<unknown> };\n\n constructor() {\n this.model = EnrichmentGenerator.sharedModel ??= createStructuredModel(\"profileGenerator\", responseFormat, {\n name: \"profile_generator\"\n });\n }\n\n private toString(profile: Profile): string {\n return [\n '# Identity',\n '## Name', profile.identity.name,\n '## Bio', profile.identity.bio,\n '## Location', profile.identity.location,\n '# Narrative',\n '## Context', profile.narrative.context,\n '# Attributes',\n '## Interests', profile.attributes.interests.join(', '),\n '## Skills', profile.attributes.skills.join(', ')\n ].join('\\n');\n }\n\n @Timed()\n public async invoke(input: string) {\n logger.verbose(\"Received input\", { inputLength: input?.length });\n const messages = [\n new SystemMessage(systemPrompt),\n new HumanMessage(`Here is the raw data:\\n${input}`)\n ];\n const result = await invokeWithAbortSignal(this.model, messages);\n const output = responseFormat.parse(result);\n const textToEmbed = this.toString(output);\n logger.verbose(\"Generated profile\", {\n skillsCount: output.attributes.skills.length,\n interestsCount: output.attributes.interests.length\n });\n return { output, textToEmbed };\n }\n\n public static asTool() {\n return tool(\n async (args: { input: string }) => {\n const profileGenerator = new EnrichmentGenerator();\n return await profileGenerator.invoke(args.input);\n },\n {\n name: 'profileGenerator',\n description: 'Profile Generator',\n schema: z.object({\n input: z.string().describe('Raw data scraped from the web (via Parallel.ai)'),\n })\n }\n );\n }\n}"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intent.clarifier.d.ts","sourceRoot":"/","sources":["intent/intent.clarifier.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"intent.clarifier.d.ts","sourceRoot":"/","sources":["intent/intent.clarifier.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAYxB,QAAA,MAAM,mBAAmB;;;;;;;;;;;;;;;EAKvB,CAAC;AASH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AA4CxE,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA2B;IACjD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA2B;IAC3D,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAA2B;;IAgBnE,oFAAoF;IACpF,OAAO,CAAC,WAAW;IAkBN,MAAM,CACjB,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,EACtB,oBAAoB,EAAE,MAAM,GAC3B,OAAO,CAAC,qBAAqB,CAAC;YAkCnB,kBAAkB;YAoBlB,0BAA0B;CA2BzC"}
|
|
@@ -11,7 +11,7 @@ import { HumanMessage, SystemMessage } from "@langchain/core/messages";
|
|
|
11
11
|
import { z } from "zod";
|
|
12
12
|
import { protocolLogger } from "../shared/observability/protocol.logger.js";
|
|
13
13
|
import { Timed } from "../shared/observability/performance.js";
|
|
14
|
-
import {
|
|
14
|
+
import { createStructuredModel } from "../shared/agent/model.config.js";
|
|
15
15
|
import { invokeWithAbortSignal } from "../shared/agent/model-signal.js";
|
|
16
16
|
const logger = protocolLogger("IntentClarifier");
|
|
17
17
|
const clarificationSchema = z.object({
|
|
@@ -68,14 +68,13 @@ Rules:
|
|
|
68
68
|
`;
|
|
69
69
|
export class IntentClarifier {
|
|
70
70
|
constructor() {
|
|
71
|
-
|
|
72
|
-
this.model = baseModel.withStructuredOutput(clarificationSchema, {
|
|
71
|
+
this.model = createStructuredModel("intentClarifier", clarificationSchema, {
|
|
73
72
|
name: "intent_clarifier",
|
|
74
73
|
});
|
|
75
|
-
this.suggestionModel =
|
|
74
|
+
this.suggestionModel = createStructuredModel("intentClarifier", suggestionSchema, {
|
|
76
75
|
name: "intent_clarifier_suggestion",
|
|
77
76
|
});
|
|
78
|
-
this.clarificationDraftModel =
|
|
77
|
+
this.clarificationDraftModel = createStructuredModel("intentClarifier", clarificationDraftSchema, { name: "intent_clarifier_message" });
|
|
79
78
|
}
|
|
80
79
|
/** Build the shared user prompt with intent, profile, and active-intent context. */
|
|
81
80
|
buildPrompt(description, profileContext, activeIntentsContext) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intent.clarifier.js","sourceRoot":"/","sources":["intent/intent.clarifier.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ChatOpenAI } from \"@langchain/openai\";\nimport { HumanMessage, SystemMessage } from \"@langchain/core/messages\";\nimport { z } from \"zod\";\n\nimport { protocolLogger } from \"../shared/observability/protocol.logger.js\";\nimport { Timed } from \"../shared/observability/performance.js\";\n\nimport { createModel } from \"../shared/agent/model.config.js\";\nimport { invokeWithAbortSignal } from \"../shared/agent/model-signal.js\";\n\nconst logger = protocolLogger(\"IntentClarifier\");\n\ntype ClarifierStructuredModel = ReturnType<ChatOpenAI[\"withStructuredOutput\"]>;\n\nconst clarificationSchema = z.object({\n needsClarification: z.boolean(),\n reason: z.string(),\n suggestedDescription: z.string().nullable(),\n clarificationMessage: z.string().nullable(),\n});\nconst suggestionSchema = z.object({\n suggestedDescription: z.string(),\n});\nconst clarificationDraftSchema = z.object({\n suggestedDescription: z.string(),\n clarificationMessage: z.string(),\n});\n\nexport type IntentClarifierOutput = z.infer<typeof clarificationSchema>;\n\nconst systemPrompt = `\nYou evaluate whether an intent is specific enough to persist without asking the user to confirm a refinement.\n\nOnly set needsClarification=true when the intent is truly vague — e.g. a single generic phrase with no role, domain, location, or other concrete criteria (like \"find a job\", \"I need help\", \"looking for something\").\n\nDo NOT ask for clarification when the user has already given:\n- A role or type (e.g. \"UX designer\", \"technical co-founder\", \"engineer\")\n- A domain or industry (e.g. \"in AI\", \"climate tech\", \"fintech\")\n- A location or format (e.g. \"remote\", \"Berlin\", \"full-time\")\n- Any other concrete detail that makes the intent actionable\n\nDefault to needsClarification=false when in doubt. Only clarify when the intent is so broad that persisting it as-is would be unhelpful (e.g. literally \"a job\" or \"something\" with no other signal).\n\nRules when needsClarification=true:\n- User Profile is the primary source for suggestedDescription; Active Intents are secondary.\n- You MUST provide a concrete suggestedDescription and short clarificationMessage.\n- Do not include JSON in clarificationMessage.\n`;\n\nconst suggestionPrompt = `\nYou generate one concrete, specific intent rewrite.\n\nRules:\n- Output only a concise intent sentence in suggestedDescription.\n- Use profile as primary source of personalization.\n- Use active intents as secondary context for consistency.\n- Keep user intent meaning, but make it actionable and specific.\n- Never return an empty suggestion.\n`;\n\nconst clarificationDraftPrompt = `\nYou draft a concise clarification response for a vague intent.\n\nRules:\n- Return both:\n 1) suggestedDescription (specific rewritten intent)\n 2) clarificationMessage (single short message to the user)\n- clarificationMessage must include the suggestion naturally and ask for confirmation.\n- Use this shape: ` + \"`Did you mean: \\\"<suggestedDescription>\\\"?`\" + ` followed by a brief confirmation instruction.\n- Keep it short. No bullet lists. No JSON.\n`;\n\nexport class IntentClarifier {\n private readonly model: ClarifierStructuredModel;\n private readonly suggestionModel: ClarifierStructuredModel;\n private readonly clarificationDraftModel: ClarifierStructuredModel;\n\n constructor() {\n const baseModel = createModel(\"intentClarifier\");\n this.model = baseModel.withStructuredOutput(clarificationSchema, {\n name: \"intent_clarifier\",\n });\n this.suggestionModel = baseModel.withStructuredOutput(suggestionSchema, {\n name: \"intent_clarifier_suggestion\",\n });\n this.clarificationDraftModel = baseModel.withStructuredOutput(\n clarificationDraftSchema,\n { name: \"intent_clarifier_message\" }\n );\n }\n\n /** Build the shared user prompt with intent, profile, and active-intent context. */\n private buildPrompt(\n description: string,\n profileContext: string,\n activeIntentsContext: string\n ): string {\n return `\n# User Input Intent\n${description}\n\n# User Profile\n${profileContext || \"none\"}\n\n# Active Intents\n${activeIntentsContext || \"none\"}\n`;\n }\n\n @Timed()\n public async invoke(\n description: string,\n profileContext: string,\n activeIntentsContext: string\n ): Promise<IntentClarifierOutput> {\n try {\n const prompt = this.buildPrompt(description, profileContext, activeIntentsContext);\n\n const result = await invokeWithAbortSignal(this.model, [\n new SystemMessage(systemPrompt),\n new HumanMessage(prompt),\n ]);\n const parsed = clarificationSchema.parse(result);\n\n if (parsed.needsClarification) {\n // Always prefer a dedicated rewrite pass for vague inputs so we avoid generic follow-up text.\n const draft = await this.generateClarificationDraft(description, profileContext, activeIntentsContext);\n if (draft) {\n return {\n ...parsed,\n suggestedDescription: draft.suggestedDescription,\n clarificationMessage: draft.clarificationMessage,\n };\n }\n }\n\n return parsed;\n } catch (error) {\n logger.warn(\"invoke: clarification failed\", { error });\n return {\n needsClarification: false,\n reason: \"fallback_on_model_error\",\n suggestedDescription: null,\n clarificationMessage: null,\n };\n }\n }\n\n private async generateSuggestion(\n description: string,\n profileContext: string,\n activeIntentsContext: string\n ): Promise<string | null> {\n try {\n const prompt = this.buildPrompt(description, profileContext, activeIntentsContext);\n const output = await invokeWithAbortSignal(this.suggestionModel, [\n new SystemMessage(suggestionPrompt),\n new HumanMessage(prompt),\n ]);\n const parsed = suggestionSchema.parse(output);\n const suggestion = parsed.suggestedDescription.trim();\n return suggestion.length > 0 ? suggestion : null;\n } catch (error) {\n logger.warn(\"generateSuggestion: failed\", { error });\n return null;\n }\n }\n\n private async generateClarificationDraft(\n description: string,\n profileContext: string,\n activeIntentsContext: string\n ): Promise<{ suggestedDescription: string; clarificationMessage: string } | null> {\n try {\n const prompt = this.buildPrompt(description, profileContext, activeIntentsContext);\n const output = await invokeWithAbortSignal(this.clarificationDraftModel, [\n new SystemMessage(clarificationDraftPrompt),\n new HumanMessage(prompt),\n ]);\n const parsed = clarificationDraftSchema.parse(output);\n const suggestedDescription = parsed.suggestedDescription.trim();\n const clarificationMessage = parsed.clarificationMessage.trim();\n if (!suggestedDescription || !clarificationMessage) return null;\n return { suggestedDescription, clarificationMessage };\n } catch (error) {\n logger.warn(\"generateClarificationDraft: failed\", { error });\n const suggestion = await this.generateSuggestion(description, profileContext, activeIntentsContext);\n if (!suggestion) return null;\n const clarificationMessage = `Do you mean: ${suggestion}?`;\n return {\n suggestedDescription: suggestion,\n clarificationMessage,\n };\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"intent.clarifier.js","sourceRoot":"/","sources":["intent/intent.clarifier.ts"],"names":[],"mappings":"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","sourcesContent":["import { HumanMessage, SystemMessage } from \"@langchain/core/messages\";\nimport { z } from \"zod\";\n\nimport { protocolLogger } from \"../shared/observability/protocol.logger.js\";\nimport { Timed } from \"../shared/observability/performance.js\";\n\nimport { createStructuredModel } from \"../shared/agent/model.config.js\";\nimport { invokeWithAbortSignal } from \"../shared/agent/model-signal.js\";\n\nconst logger = protocolLogger(\"IntentClarifier\");\n\ntype ClarifierStructuredModel = ReturnType<typeof createStructuredModel>;\n\nconst clarificationSchema = z.object({\n needsClarification: z.boolean(),\n reason: z.string(),\n suggestedDescription: z.string().nullable(),\n clarificationMessage: z.string().nullable(),\n});\nconst suggestionSchema = z.object({\n suggestedDescription: z.string(),\n});\nconst clarificationDraftSchema = z.object({\n suggestedDescription: z.string(),\n clarificationMessage: z.string(),\n});\n\nexport type IntentClarifierOutput = z.infer<typeof clarificationSchema>;\n\nconst systemPrompt = `\nYou evaluate whether an intent is specific enough to persist without asking the user to confirm a refinement.\n\nOnly set needsClarification=true when the intent is truly vague — e.g. a single generic phrase with no role, domain, location, or other concrete criteria (like \"find a job\", \"I need help\", \"looking for something\").\n\nDo NOT ask for clarification when the user has already given:\n- A role or type (e.g. \"UX designer\", \"technical co-founder\", \"engineer\")\n- A domain or industry (e.g. \"in AI\", \"climate tech\", \"fintech\")\n- A location or format (e.g. \"remote\", \"Berlin\", \"full-time\")\n- Any other concrete detail that makes the intent actionable\n\nDefault to needsClarification=false when in doubt. Only clarify when the intent is so broad that persisting it as-is would be unhelpful (e.g. literally \"a job\" or \"something\" with no other signal).\n\nRules when needsClarification=true:\n- User Profile is the primary source for suggestedDescription; Active Intents are secondary.\n- You MUST provide a concrete suggestedDescription and short clarificationMessage.\n- Do not include JSON in clarificationMessage.\n`;\n\nconst suggestionPrompt = `\nYou generate one concrete, specific intent rewrite.\n\nRules:\n- Output only a concise intent sentence in suggestedDescription.\n- Use profile as primary source of personalization.\n- Use active intents as secondary context for consistency.\n- Keep user intent meaning, but make it actionable and specific.\n- Never return an empty suggestion.\n`;\n\nconst clarificationDraftPrompt = `\nYou draft a concise clarification response for a vague intent.\n\nRules:\n- Return both:\n 1) suggestedDescription (specific rewritten intent)\n 2) clarificationMessage (single short message to the user)\n- clarificationMessage must include the suggestion naturally and ask for confirmation.\n- Use this shape: ` + \"`Did you mean: \\\"<suggestedDescription>\\\"?`\" + ` followed by a brief confirmation instruction.\n- Keep it short. No bullet lists. No JSON.\n`;\n\nexport class IntentClarifier {\n private readonly model: ClarifierStructuredModel;\n private readonly suggestionModel: ClarifierStructuredModel;\n private readonly clarificationDraftModel: ClarifierStructuredModel;\n\n constructor() {\n this.model = createStructuredModel(\"intentClarifier\", clarificationSchema, {\n name: \"intent_clarifier\",\n });\n this.suggestionModel = createStructuredModel(\"intentClarifier\", suggestionSchema, {\n name: \"intent_clarifier_suggestion\",\n });\n this.clarificationDraftModel = createStructuredModel(\n \"intentClarifier\",\n clarificationDraftSchema,\n { name: \"intent_clarifier_message\" }\n );\n }\n\n /** Build the shared user prompt with intent, profile, and active-intent context. */\n private buildPrompt(\n description: string,\n profileContext: string,\n activeIntentsContext: string\n ): string {\n return `\n# User Input Intent\n${description}\n\n# User Profile\n${profileContext || \"none\"}\n\n# Active Intents\n${activeIntentsContext || \"none\"}\n`;\n }\n\n @Timed()\n public async invoke(\n description: string,\n profileContext: string,\n activeIntentsContext: string\n ): Promise<IntentClarifierOutput> {\n try {\n const prompt = this.buildPrompt(description, profileContext, activeIntentsContext);\n\n const result = await invokeWithAbortSignal(this.model, [\n new SystemMessage(systemPrompt),\n new HumanMessage(prompt),\n ]);\n const parsed = clarificationSchema.parse(result);\n\n if (parsed.needsClarification) {\n // Always prefer a dedicated rewrite pass for vague inputs so we avoid generic follow-up text.\n const draft = await this.generateClarificationDraft(description, profileContext, activeIntentsContext);\n if (draft) {\n return {\n ...parsed,\n suggestedDescription: draft.suggestedDescription,\n clarificationMessage: draft.clarificationMessage,\n };\n }\n }\n\n return parsed;\n } catch (error) {\n logger.warn(\"invoke: clarification failed\", { error });\n return {\n needsClarification: false,\n reason: \"fallback_on_model_error\",\n suggestedDescription: null,\n clarificationMessage: null,\n };\n }\n }\n\n private async generateSuggestion(\n description: string,\n profileContext: string,\n activeIntentsContext: string\n ): Promise<string | null> {\n try {\n const prompt = this.buildPrompt(description, profileContext, activeIntentsContext);\n const output = await invokeWithAbortSignal(this.suggestionModel, [\n new SystemMessage(suggestionPrompt),\n new HumanMessage(prompt),\n ]);\n const parsed = suggestionSchema.parse(output);\n const suggestion = parsed.suggestedDescription.trim();\n return suggestion.length > 0 ? suggestion : null;\n } catch (error) {\n logger.warn(\"generateSuggestion: failed\", { error });\n return null;\n }\n }\n\n private async generateClarificationDraft(\n description: string,\n profileContext: string,\n activeIntentsContext: string\n ): Promise<{ suggestedDescription: string; clarificationMessage: string } | null> {\n try {\n const prompt = this.buildPrompt(description, profileContext, activeIntentsContext);\n const output = await invokeWithAbortSignal(this.clarificationDraftModel, [\n new SystemMessage(clarificationDraftPrompt),\n new HumanMessage(prompt),\n ]);\n const parsed = clarificationDraftSchema.parse(output);\n const suggestedDescription = parsed.suggestedDescription.trim();\n const clarificationMessage = parsed.clarificationMessage.trim();\n if (!suggestedDescription || !clarificationMessage) return null;\n return { suggestedDescription, clarificationMessage };\n } catch (error) {\n logger.warn(\"generateClarificationDraft: failed\", { error });\n const suggestion = await this.generateSuggestion(description, profileContext, activeIntentsContext);\n if (!suggestion) return null;\n const clarificationMessage = `Do you mean: ${suggestion}?`;\n return {\n suggestedDescription: suggestion,\n clarificationMessage,\n };\n }\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intent.indexer.d.ts","sourceRoot":"/","sources":["intent/intent.indexer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"intent.indexer.d.ts","sourceRoot":"/","sources":["intent/intent.indexer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAUxB,eAAO,MAAM,yBAAyB;;;;;;;;;;;;EAIpC,CAAC;AAEH;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAyD5E,qBAAa,aAAa;IACxB,OAAO,CAAC,KAAK,CAA2C;;IAQxD;;;OAGG;IACH,OAAO,CAAC,QAAQ;IAQhB;;;;;;;;;OASG;IAEU,MAAM,CACjB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,EAC1B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,GAC7B,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;IAuCtC;;;OAGG;IAEU,QAAQ,CACnB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,EAC1B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,GAC7B,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;IAItC;;;OAGG;WACW,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgCrB"}
|