@indexnetwork/protocol 4.3.7-rc.317.1 → 4.4.0-rc.318.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.
Files changed (47) hide show
  1. package/dist/chat/chat-streaming.types.d.ts +29 -2
  2. package/dist/chat/chat-streaming.types.d.ts.map +1 -1
  3. package/dist/chat/chat-streaming.types.js +3 -0
  4. package/dist/chat/chat-streaming.types.js.map +1 -1
  5. package/dist/chat/chat.agent.d.ts +15 -0
  6. package/dist/chat/chat.agent.d.ts.map +1 -1
  7. package/dist/chat/chat.agent.js.map +1 -1
  8. package/dist/chat/chat.prompt.d.ts.map +1 -1
  9. package/dist/chat/chat.prompt.js +3 -0
  10. package/dist/chat/chat.prompt.js.map +1 -1
  11. package/dist/chat/chat.streamer.d.ts.map +1 -1
  12. package/dist/chat/chat.streamer.js +9 -1
  13. package/dist/chat/chat.streamer.js.map +1 -1
  14. package/dist/index.d.ts +2 -2
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js.map +1 -1
  17. package/dist/questioner/questioner.ask.tool.d.ts +14 -0
  18. package/dist/questioner/questioner.ask.tool.d.ts.map +1 -0
  19. package/dist/questioner/questioner.ask.tool.js +309 -0
  20. package/dist/questioner/questioner.ask.tool.js.map +1 -0
  21. package/dist/questioner/questioner.presets.d.ts.map +1 -1
  22. package/dist/questioner/questioner.presets.js +73 -0
  23. package/dist/questioner/questioner.presets.js.map +1 -1
  24. package/dist/questioner/questioner.types.d.ts +21 -1
  25. package/dist/questioner/questioner.types.d.ts.map +1 -1
  26. package/dist/questioner/questioner.types.js.map +1 -1
  27. package/dist/shared/agent/tool.factory.d.ts.map +1 -1
  28. package/dist/shared/agent/tool.factory.js +10 -0
  29. package/dist/shared/agent/tool.factory.js.map +1 -1
  30. package/dist/shared/agent/tool.helpers.d.ts +19 -1
  31. package/dist/shared/agent/tool.helpers.d.ts.map +1 -1
  32. package/dist/shared/agent/tool.helpers.js.map +1 -1
  33. package/dist/shared/agent/tool.runtime.d.ts +1 -1
  34. package/dist/shared/agent/tool.runtime.d.ts.map +1 -1
  35. package/dist/shared/agent/tool.runtime.js +14 -3
  36. package/dist/shared/agent/tool.runtime.js.map +1 -1
  37. package/dist/shared/interfaces/questioner.interface.d.ts +26 -0
  38. package/dist/shared/interfaces/questioner.interface.d.ts.map +1 -1
  39. package/dist/shared/interfaces/questioner.interface.js.map +1 -1
  40. package/dist/shared/observability/request-context.d.ts +15 -0
  41. package/dist/shared/observability/request-context.d.ts.map +1 -1
  42. package/dist/shared/observability/request-context.js.map +1 -1
  43. package/dist/shared/schemas/question.schema.d.ts +4 -4
  44. package/dist/shared/schemas/question.schema.d.ts.map +1 -1
  45. package/dist/shared/schemas/question.schema.js +2 -0
  46. package/dist/shared/schemas/question.schema.js.map +1 -1
  47. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"tool.runtime.js","sourceRoot":"/","sources":["shared/agent/tool.runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import { timed } from \"../observability/performance.js\";\nimport type { TraceEmitter } from \"../observability/request-context.js\";\nimport { requestContext } from \"../observability/request-context.js\";\n\nimport type { RawToolDefinition, ResolvedToolContext } from \"./tool.helpers.js\";\n\nexport type ToolTimeoutClass = \"fast\" | \"bounded_slow\" | \"async_candidate\";\nexport type ToolRuntimeErrorCode = \"TOOL_TIMEOUT\" | \"TOOL_CANCELLED\" | \"TOOL_OUTPUT_TOO_LARGE\";\n\nexport interface ToolTimeoutPolicy {\n class: ToolTimeoutClass;\n timeoutMs: number;\n maxOutputBytes: number;\n}\n\nexport interface ToolInvocationRuntimeInput {\n toolName: string;\n tool: Pick<RawToolDefinition, \"handler\">;\n context: ResolvedToolContext;\n query: unknown;\n signal?: AbortSignal;\n traceEmitter?: TraceEmitter;\n timeoutMs?: number;\n maxOutputBytes?: number;\n}\n\nconst FAST_TIMEOUT_MS = 10_000;\nconst BOUNDED_SLOW_TIMEOUT_MS = 45_000;\nconst ASYNC_CANDIDATE_TIMEOUT_MS = 50_000;\nconst DEFAULT_MAX_OUTPUT_BYTES = 1_000_000;\n\nconst FAST_TOOLS = new Set([\n \"record_onboarding_privacy_consent\",\n \"create_intent_index\",\n \"delete_intent_index\",\n \"search_intents\",\n \"read_networks\",\n \"update_network\",\n \"create_network\",\n \"delete_network\",\n \"create_network_membership\",\n \"delete_network_membership\",\n \"confirm_opportunity_delivery\",\n \"read_docs\",\n \"get_discovery_run\",\n \"cancel_discovery_run\",\n \"get_profile_run\",\n \"cancel_profile_run\",\n \"remove_contact\",\n \"register_agent\",\n \"list_agents\",\n \"update_agent\",\n \"delete_agent\",\n \"grant_agent_permission\",\n \"revoke_agent_permission\",\n \"retract_premise\",\n]);\n\nconst ASYNC_CANDIDATE_TOOLS = new Set([\n // Canonical *_user_context names (IND-371)\n \"read_user_contexts\",\n \"preview_user_context\",\n \"create_user_context\",\n \"update_user_context\",\n // Deprecated *_user_profile aliases (kept until IND-373 retires them)\n \"read_user_profiles\",\n \"preview_user_profile\",\n \"create_user_profile\",\n \"update_user_profile\",\n \"create_intent\",\n \"update_intent\",\n \"discover_opportunities\",\n \"scrape_url\",\n \"import_gmail_contacts\",\n \"import_contacts\",\n \"respond_to_negotiation\",\n \"create_premise\",\n \"update_premise\",\n]);\n\nfunction parsePositiveIntEnv(name: string, fallback: number): number {\n const raw = process.env[name];\n if (!raw) return fallback;\n const parsed = Number.parseInt(raw, 10);\n return Number.isFinite(parsed) && parsed > 0 && parsed <= Number.MAX_SAFE_INTEGER\n ? parsed\n : fallback;\n}\n\nfunction toolNameEnv(toolName: string): string {\n return `MCP_TOOL_TIMEOUT_${toolName.toUpperCase().replace(/[^A-Z0-9]+/g, \"_\")}_MS`;\n}\n\nfunction toolNameOutputEnv(toolName: string): string {\n return `MCP_TOOL_MAX_OUTPUT_${toolName.toUpperCase().replace(/[^A-Z0-9]+/g, \"_\")}_BYTES`;\n}\n\nexport function getToolTimeoutPolicy(toolName: string): ToolTimeoutPolicy {\n const classification: ToolTimeoutClass = FAST_TOOLS.has(toolName)\n ? \"fast\"\n : ASYNC_CANDIDATE_TOOLS.has(toolName)\n ? \"async_candidate\"\n : \"bounded_slow\";\n\n let classDefault: number;\n switch (classification) {\n case \"fast\":\n classDefault = parsePositiveIntEnv(\"MCP_TOOL_TIMEOUT_FAST_MS\", FAST_TIMEOUT_MS);\n break;\n case \"async_candidate\":\n classDefault = parsePositiveIntEnv(\"MCP_TOOL_TIMEOUT_ASYNC_CANDIDATE_MS\", ASYNC_CANDIDATE_TIMEOUT_MS);\n break;\n default:\n classDefault = parsePositiveIntEnv(\"MCP_TOOL_TIMEOUT_BOUNDED_SLOW_MS\", BOUNDED_SLOW_TIMEOUT_MS);\n }\n\n const defaultMaxOutputBytes = parsePositiveIntEnv(\"MCP_TOOL_MAX_OUTPUT_BYTES\", DEFAULT_MAX_OUTPUT_BYTES);\n\n return {\n class: classification,\n timeoutMs: parsePositiveIntEnv(toolNameEnv(toolName), classDefault),\n maxOutputBytes: parsePositiveIntEnv(toolNameOutputEnv(toolName), defaultMaxOutputBytes),\n };\n}\n\nexport class ToolRuntimeError extends Error {\n constructor(\n public readonly code: ToolRuntimeErrorCode,\n message: string,\n public readonly toolName: string,\n public readonly policy: ToolTimeoutPolicy,\n ) {\n super(message);\n this.name = \"ToolRuntimeError\";\n }\n}\n\n/** Builds the typed timeout/cancellation error shared by the abort race and catch paths. */\nfunction makeAbortError(timedOut: boolean, toolName: string, policy: ToolTimeoutPolicy): ToolRuntimeError {\n const code: ToolRuntimeErrorCode = timedOut ? \"TOOL_TIMEOUT\" : \"TOOL_CANCELLED\";\n return new ToolRuntimeError(\n code,\n code === \"TOOL_TIMEOUT\"\n ? `Tool ${toolName} timed out after ${policy.timeoutMs}ms.`\n : `Tool ${toolName} was cancelled before it completed.`,\n toolName,\n policy,\n );\n}\n\nfunction combineSignals(signals: Array<AbortSignal | undefined>): {\n signal: AbortSignal;\n abort: (reason?: unknown) => void;\n cleanup: () => void;\n} {\n const controller = new AbortController();\n const listeners: Array<() => void> = [];\n\n for (const source of signals) {\n if (!source) continue;\n if (source.aborted) {\n controller.abort(source.reason);\n break;\n }\n const onAbort = () => {\n if (!controller.signal.aborted) controller.abort(source.reason);\n };\n source.addEventListener(\"abort\", onAbort, { once: true });\n listeners.push(() => source.removeEventListener(\"abort\", onAbort));\n }\n\n return {\n signal: controller.signal,\n abort: (reason?: unknown) => {\n if (!controller.signal.aborted) controller.abort(reason);\n },\n cleanup: () => {\n for (const cleanup of listeners) cleanup();\n },\n };\n}\n\nexport async function invokeToolRuntime(input: ToolInvocationRuntimeInput): Promise<string> {\n return timed(`ToolRuntime.${input.toolName}`, () => invokeToolRuntimeInner(input));\n}\n\nasync function invokeToolRuntimeInner(input: ToolInvocationRuntimeInput): Promise<string> {\n const basePolicy = getToolTimeoutPolicy(input.toolName);\n const policy = {\n ...basePolicy,\n ...(input.timeoutMs !== undefined ? { timeoutMs: input.timeoutMs } : {}),\n ...(input.maxOutputBytes !== undefined ? { maxOutputBytes: input.maxOutputBytes } : {}),\n };\n const inherited = requestContext.getStore();\n const combined = combineSignals([input.signal, inherited?.abortSignal]);\n let timedOut = false;\n const timer = setTimeout(() => {\n timedOut = true;\n combined.abort(new Error(`Tool ${input.toolName} timed out after ${policy.timeoutMs}ms`));\n }, policy.timeoutMs);\n\n let removeAbortListener = () => {};\n const abortPromise = new Promise<never>((_, reject) => {\n const onAbort = () => {\n reject(makeAbortError(timedOut, input.toolName, policy));\n };\n combined.signal.addEventListener(\"abort\", onAbort, { once: true });\n removeAbortListener = () => combined.signal.removeEventListener(\"abort\", onAbort);\n });\n\n try {\n const run = () => input.tool.handler({ context: input.context, query: input.query });\n const toolPromise = requestContext.run(\n {\n ...inherited,\n abortSignal: combined.signal,\n traceEmitter: input.traceEmitter ?? inherited?.traceEmitter,\n },\n run,\n );\n const result = await Promise.race([toolPromise, abortPromise]);\n const outputBytes = new TextEncoder().encode(result).byteLength;\n if (outputBytes > policy.maxOutputBytes) {\n throw new ToolRuntimeError(\n \"TOOL_OUTPUT_TOO_LARGE\",\n `Tool ${input.toolName} returned ${outputBytes} bytes, exceeding the ${policy.maxOutputBytes} byte limit.`,\n input.toolName,\n policy,\n );\n }\n return result;\n } catch (err) {\n if (err instanceof ToolRuntimeError) throw err;\n if (combined.signal.aborted) {\n throw makeAbortError(timedOut, input.toolName, policy);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n removeAbortListener();\n combined.cleanup();\n }\n}\n\nexport function toolRuntimeErrorToResult(err: unknown): string | null {\n if (!(err instanceof ToolRuntimeError)) return null;\n return JSON.stringify({\n success: false,\n code: err.code,\n error: err.message,\n data: {\n tool: err.toolName,\n timeoutClass: err.policy.class,\n timeoutMs: err.policy.timeoutMs,\n maxOutputBytes: err.policy.maxOutputBytes,\n },\n });\n}\n"]}
1
+ {"version":3,"file":"tool.runtime.js","sourceRoot":"/","sources":["shared/agent/tool.runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import { timed } from \"../observability/performance.js\";\nimport type { TraceEmitter } from \"../observability/request-context.js\";\nimport { requestContext } from \"../observability/request-context.js\";\n\nimport type { RawToolDefinition, ResolvedToolContext } from \"./tool.helpers.js\";\n\nexport type ToolTimeoutClass = \"fast\" | \"bounded_slow\" | \"async_candidate\" | \"interactive\";\nexport type ToolRuntimeErrorCode = \"TOOL_TIMEOUT\" | \"TOOL_CANCELLED\" | \"TOOL_OUTPUT_TOO_LARGE\";\n\nexport interface ToolTimeoutPolicy {\n class: ToolTimeoutClass;\n timeoutMs: number;\n maxOutputBytes: number;\n}\n\nexport interface ToolInvocationRuntimeInput {\n toolName: string;\n tool: Pick<RawToolDefinition, \"handler\">;\n context: ResolvedToolContext;\n query: unknown;\n signal?: AbortSignal;\n traceEmitter?: TraceEmitter;\n timeoutMs?: number;\n maxOutputBytes?: number;\n}\n\nconst FAST_TIMEOUT_MS = 10_000;\nconst BOUNDED_SLOW_TIMEOUT_MS = 45_000;\nconst ASYNC_CANDIDATE_TIMEOUT_MS = 50_000;\n// Interactive tools deliberately block on human input (ask_user_question).\n// Must exceed the tool's own internal wait budget (CHAT_QUESTION_WAIT_TIMEOUT_MS,\n// default 4 min) so the tool returns a graceful timeout result instead of\n// being killed by the runtime.\nconst INTERACTIVE_TIMEOUT_MS = 300_000;\nconst DEFAULT_MAX_OUTPUT_BYTES = 1_000_000;\n\nconst FAST_TOOLS = new Set([\n \"record_onboarding_privacy_consent\",\n \"create_intent_index\",\n \"delete_intent_index\",\n \"search_intents\",\n \"read_networks\",\n \"update_network\",\n \"create_network\",\n \"delete_network\",\n \"create_network_membership\",\n \"delete_network_membership\",\n \"confirm_opportunity_delivery\",\n \"read_docs\",\n \"get_discovery_run\",\n \"cancel_discovery_run\",\n \"get_profile_run\",\n \"cancel_profile_run\",\n \"remove_contact\",\n \"register_agent\",\n \"list_agents\",\n \"update_agent\",\n \"delete_agent\",\n \"grant_agent_permission\",\n \"revoke_agent_permission\",\n \"retract_premise\",\n]);\n\nconst INTERACTIVE_TOOLS = new Set([\"ask_user_question\"]);\n\nconst ASYNC_CANDIDATE_TOOLS = new Set([\n // Canonical *_user_context names (IND-371)\n \"read_user_contexts\",\n \"preview_user_context\",\n \"create_user_context\",\n \"update_user_context\",\n // Deprecated *_user_profile aliases (kept until IND-373 retires them)\n \"read_user_profiles\",\n \"preview_user_profile\",\n \"create_user_profile\",\n \"update_user_profile\",\n \"create_intent\",\n \"update_intent\",\n \"discover_opportunities\",\n \"scrape_url\",\n \"import_gmail_contacts\",\n \"import_contacts\",\n \"respond_to_negotiation\",\n \"create_premise\",\n \"update_premise\",\n]);\n\nfunction parsePositiveIntEnv(name: string, fallback: number): number {\n const raw = process.env[name];\n if (!raw) return fallback;\n const parsed = Number.parseInt(raw, 10);\n return Number.isFinite(parsed) && parsed > 0 && parsed <= Number.MAX_SAFE_INTEGER\n ? parsed\n : fallback;\n}\n\nfunction toolNameEnv(toolName: string): string {\n return `MCP_TOOL_TIMEOUT_${toolName.toUpperCase().replace(/[^A-Z0-9]+/g, \"_\")}_MS`;\n}\n\nfunction toolNameOutputEnv(toolName: string): string {\n return `MCP_TOOL_MAX_OUTPUT_${toolName.toUpperCase().replace(/[^A-Z0-9]+/g, \"_\")}_BYTES`;\n}\n\nexport function getToolTimeoutPolicy(toolName: string): ToolTimeoutPolicy {\n const classification: ToolTimeoutClass = FAST_TOOLS.has(toolName)\n ? \"fast\"\n : INTERACTIVE_TOOLS.has(toolName)\n ? \"interactive\"\n : ASYNC_CANDIDATE_TOOLS.has(toolName)\n ? \"async_candidate\"\n : \"bounded_slow\";\n\n let classDefault: number;\n switch (classification) {\n case \"fast\":\n classDefault = parsePositiveIntEnv(\"MCP_TOOL_TIMEOUT_FAST_MS\", FAST_TIMEOUT_MS);\n break;\n case \"interactive\":\n classDefault = parsePositiveIntEnv(\"MCP_TOOL_TIMEOUT_INTERACTIVE_MS\", INTERACTIVE_TIMEOUT_MS);\n break;\n case \"async_candidate\":\n classDefault = parsePositiveIntEnv(\"MCP_TOOL_TIMEOUT_ASYNC_CANDIDATE_MS\", ASYNC_CANDIDATE_TIMEOUT_MS);\n break;\n default:\n classDefault = parsePositiveIntEnv(\"MCP_TOOL_TIMEOUT_BOUNDED_SLOW_MS\", BOUNDED_SLOW_TIMEOUT_MS);\n }\n\n const defaultMaxOutputBytes = parsePositiveIntEnv(\"MCP_TOOL_MAX_OUTPUT_BYTES\", DEFAULT_MAX_OUTPUT_BYTES);\n\n return {\n class: classification,\n timeoutMs: parsePositiveIntEnv(toolNameEnv(toolName), classDefault),\n maxOutputBytes: parsePositiveIntEnv(toolNameOutputEnv(toolName), defaultMaxOutputBytes),\n };\n}\n\nexport class ToolRuntimeError extends Error {\n constructor(\n public readonly code: ToolRuntimeErrorCode,\n message: string,\n public readonly toolName: string,\n public readonly policy: ToolTimeoutPolicy,\n ) {\n super(message);\n this.name = \"ToolRuntimeError\";\n }\n}\n\n/** Builds the typed timeout/cancellation error shared by the abort race and catch paths. */\nfunction makeAbortError(timedOut: boolean, toolName: string, policy: ToolTimeoutPolicy): ToolRuntimeError {\n const code: ToolRuntimeErrorCode = timedOut ? \"TOOL_TIMEOUT\" : \"TOOL_CANCELLED\";\n return new ToolRuntimeError(\n code,\n code === \"TOOL_TIMEOUT\"\n ? `Tool ${toolName} timed out after ${policy.timeoutMs}ms.`\n : `Tool ${toolName} was cancelled before it completed.`,\n toolName,\n policy,\n );\n}\n\nfunction combineSignals(signals: Array<AbortSignal | undefined>): {\n signal: AbortSignal;\n abort: (reason?: unknown) => void;\n cleanup: () => void;\n} {\n const controller = new AbortController();\n const listeners: Array<() => void> = [];\n\n for (const source of signals) {\n if (!source) continue;\n if (source.aborted) {\n controller.abort(source.reason);\n break;\n }\n const onAbort = () => {\n if (!controller.signal.aborted) controller.abort(source.reason);\n };\n source.addEventListener(\"abort\", onAbort, { once: true });\n listeners.push(() => source.removeEventListener(\"abort\", onAbort));\n }\n\n return {\n signal: controller.signal,\n abort: (reason?: unknown) => {\n if (!controller.signal.aborted) controller.abort(reason);\n },\n cleanup: () => {\n for (const cleanup of listeners) cleanup();\n },\n };\n}\n\nexport async function invokeToolRuntime(input: ToolInvocationRuntimeInput): Promise<string> {\n return timed(`ToolRuntime.${input.toolName}`, () => invokeToolRuntimeInner(input));\n}\n\nasync function invokeToolRuntimeInner(input: ToolInvocationRuntimeInput): Promise<string> {\n const basePolicy = getToolTimeoutPolicy(input.toolName);\n const policy = {\n ...basePolicy,\n ...(input.timeoutMs !== undefined ? { timeoutMs: input.timeoutMs } : {}),\n ...(input.maxOutputBytes !== undefined ? { maxOutputBytes: input.maxOutputBytes } : {}),\n };\n const inherited = requestContext.getStore();\n const combined = combineSignals([input.signal, inherited?.abortSignal]);\n let timedOut = false;\n const timer = setTimeout(() => {\n timedOut = true;\n combined.abort(new Error(`Tool ${input.toolName} timed out after ${policy.timeoutMs}ms`));\n }, policy.timeoutMs);\n\n let removeAbortListener = () => {};\n const abortPromise = new Promise<never>((_, reject) => {\n const onAbort = () => {\n reject(makeAbortError(timedOut, input.toolName, policy));\n };\n combined.signal.addEventListener(\"abort\", onAbort, { once: true });\n removeAbortListener = () => combined.signal.removeEventListener(\"abort\", onAbort);\n });\n\n try {\n const run = () => input.tool.handler({ context: input.context, query: input.query });\n const toolPromise = requestContext.run(\n {\n ...inherited,\n abortSignal: combined.signal,\n traceEmitter: input.traceEmitter ?? inherited?.traceEmitter,\n },\n run,\n );\n const result = await Promise.race([toolPromise, abortPromise]);\n const outputBytes = new TextEncoder().encode(result).byteLength;\n if (outputBytes > policy.maxOutputBytes) {\n throw new ToolRuntimeError(\n \"TOOL_OUTPUT_TOO_LARGE\",\n `Tool ${input.toolName} returned ${outputBytes} bytes, exceeding the ${policy.maxOutputBytes} byte limit.`,\n input.toolName,\n policy,\n );\n }\n return result;\n } catch (err) {\n if (err instanceof ToolRuntimeError) throw err;\n if (combined.signal.aborted) {\n throw makeAbortError(timedOut, input.toolName, policy);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n removeAbortListener();\n combined.cleanup();\n }\n}\n\nexport function toolRuntimeErrorToResult(err: unknown): string | null {\n if (!(err instanceof ToolRuntimeError)) return null;\n return JSON.stringify({\n success: false,\n code: err.code,\n error: err.message,\n data: {\n tool: err.toolName,\n timeoutClass: err.policy.class,\n timeoutMs: err.policy.timeoutMs,\n maxOutputBytes: err.policy.maxOutputBytes,\n },\n });\n}\n"]}
@@ -32,6 +32,32 @@ export interface QuestionFilters {
32
32
  scopeType?: 'intent';
33
33
  scopeId?: string;
34
34
  }
35
+ /**
36
+ * Resolution outcome for a single awaited chat question.
37
+ * `timeout` means the wait budget elapsed (or the run was aborted) before the
38
+ * user responded — the question stays `pending` in the database.
39
+ */
40
+ export interface ChatQuestionAnswerOutcome {
41
+ questionId: string;
42
+ status: "answered" | "dismissed" | "timeout";
43
+ answer?: QuestionAnswer;
44
+ }
45
+ /**
46
+ * Host bridge for the orchestrator's blocking `ask_user_question` tool.
47
+ * `persist` synchronously inserts chat-mode question rows; `awaitAnswers`
48
+ * blocks until every question resolves (answer/dismiss via the questions
49
+ * REST endpoints) or the wait times out / the run is aborted.
50
+ *
51
+ * Implementations live in the backend (in-memory per-question wait bus,
52
+ * single-instance semantics like the chat steer/queue interrupt emitter).
53
+ */
54
+ export interface ChatQuestionsHost {
55
+ persist(batch: PersistableQuestion[]): Promise<PersistedQuestion[]>;
56
+ awaitAnswers(questionIds: string[], opts?: {
57
+ timeoutMs?: number;
58
+ signal?: AbortSignal;
59
+ }): Promise<ChatQuestionAnswerOutcome[]>;
60
+ }
35
61
  export interface QuestionerDatabase {
36
62
  /** Persist a batch of generated questions (up to 3 per generation).
37
63
  * @returns The IDs of the inserted rows. */
@@ -1 +1 @@
1
- {"version":3,"file":"questioner.interface.d.ts","sourceRoot":"/","sources":["shared/interfaces/questioner.interface.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAEhJ,kFAAkF;AAClF,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,iBAAiB,CAAC;IAC7B,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,OAAO,EAAE,QAAQ,CAAC;IAClB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,8EAA8E;IAC9E,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,0FAA0F;AAC1F,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,iBAAiB,CAAC;IAC7B,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,OAAO,EAAE,QAAQ,CAAC;IAClB,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,WAAW,CAAC;IAC7C,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,4CAA4C;AAC5C,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0GAA0G;IAC1G,SAAS,CAAC,EAAE,QAAQ,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC;iDAC6C;IAC7C,OAAO,CAAC,SAAS,EAAE,mBAAmB,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAE7D,6EAA6E;IAC7E,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC;IAErF;;0FAEsF;IACtF,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAErF;;0FAEsF;IACtF,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC/D"}
1
+ {"version":3,"file":"questioner.interface.d.ts","sourceRoot":"/","sources":["shared/interfaces/questioner.interface.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAEhJ,kFAAkF;AAClF,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,iBAAiB,CAAC;IAC7B,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,OAAO,EAAE,QAAQ,CAAC;IAClB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,8EAA8E;IAC9E,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,0FAA0F;AAC1F,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,iBAAiB,CAAC;IAC7B,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,OAAO,EAAE,QAAQ,CAAC;IAClB,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,WAAW,CAAC;IAC7C,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,4CAA4C;AAC5C,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0GAA0G;IAC1G,SAAS,CAAC,EAAE,QAAQ,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,MAAM,WAAW,yBAAyB;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,UAAU,GAAG,WAAW,GAAG,SAAS,CAAC;IAC7C,MAAM,CAAC,EAAE,cAAc,CAAC;CACzB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,KAAK,EAAE,mBAAmB,EAAE,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC;IACpE,YAAY,CACV,WAAW,EAAE,MAAM,EAAE,EACrB,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAClD,OAAO,CAAC,yBAAyB,EAAE,CAAC,CAAC;CACzC;AAED,MAAM,WAAW,kBAAkB;IACjC;iDAC6C;IAC7C,OAAO,CAAC,SAAS,EAAE,mBAAmB,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAE7D,6EAA6E;IAC7E,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC;IAErF;;0FAEsF;IACtF,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAErF;;0FAEsF;IACtF,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC/D"}
@@ -1 +1 @@
1
- {"version":3,"file":"questioner.interface.js","sourceRoot":"/","sources":["shared/interfaces/questioner.interface.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Protocol-level persistence contract for structured questions generated by\n * the QuestionerAgent. Implementations live in the backend and are injected\n * into ProtocolDeps.\n */\nimport type { Question, QuestionMode, QuestionStrategy, QuestionDetection, QuestionActor, QuestionAnswer } from \"../schemas/question.schema.js\";\n\n/** Shape accepted by `persist()` — everything needed to insert a question row. */\nexport interface PersistableQuestion {\n detection: QuestionDetection;\n actors: QuestionActor[];\n payload: Question;\n strategy: QuestionStrategy;\n /** Conversation ID — set when the question originates from a chat session. */\n conversationId?: string;\n}\n\n/** Shape returned by `findPending()` — a persisted question with its DB id and status. */\nexport interface PersistedQuestion {\n id: string;\n detection: QuestionDetection;\n actors: QuestionActor[];\n payload: Question;\n status: \"pending\" | \"answered\" | \"dismissed\";\n answer: QuestionAnswer | null;\n createdAt: string;\n}\n\n/** Optional filters for `findPending()`. */\nexport interface QuestionFilters {\n mode?: QuestionMode;\n sourceType?: string;\n sourceId?: string;\n /** Optional selected-intent scope. When `scopeType === 'intent'`, `scopeId` is the selected intent id. */\n scopeType?: 'intent';\n scopeId?: string;\n}\n\nexport interface QuestionerDatabase {\n /** Persist a batch of generated questions (up to 3 per generation).\n * @returns The IDs of the inserted rows. */\n persist(questions: PersistableQuestion[]): Promise<string[]>;\n\n /** Find pending questions for a user, optionally filtered by mode/source. */\n findPending(userId: string, filters?: QuestionFilters): Promise<PersistedQuestion[]>;\n\n /** Record an answer for a question. Sets status to \"answered\".\n * Only succeeds if the user is an actor on a pending question.\n * @returns `true` if updated, `false` if not found, not pending, or unauthorized. */\n answer(questionId: string, userId: string, answer: QuestionAnswer): Promise<boolean>;\n\n /** Dismiss a question. Sets status to \"dismissed\".\n * Only succeeds if the user is an actor on a pending question.\n * @returns `true` if updated, `false` if not found, not pending, or unauthorized. */\n dismiss(questionId: string, userId: string): Promise<boolean>;\n}\n"]}
1
+ {"version":3,"file":"questioner.interface.js","sourceRoot":"/","sources":["shared/interfaces/questioner.interface.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Protocol-level persistence contract for structured questions generated by\n * the QuestionerAgent. Implementations live in the backend and are injected\n * into ProtocolDeps.\n */\nimport type { Question, QuestionMode, QuestionStrategy, QuestionDetection, QuestionActor, QuestionAnswer } from \"../schemas/question.schema.js\";\n\n/** Shape accepted by `persist()` — everything needed to insert a question row. */\nexport interface PersistableQuestion {\n detection: QuestionDetection;\n actors: QuestionActor[];\n payload: Question;\n strategy: QuestionStrategy;\n /** Conversation ID — set when the question originates from a chat session. */\n conversationId?: string;\n}\n\n/** Shape returned by `findPending()` — a persisted question with its DB id and status. */\nexport interface PersistedQuestion {\n id: string;\n detection: QuestionDetection;\n actors: QuestionActor[];\n payload: Question;\n status: \"pending\" | \"answered\" | \"dismissed\";\n answer: QuestionAnswer | null;\n createdAt: string;\n}\n\n/** Optional filters for `findPending()`. */\nexport interface QuestionFilters {\n mode?: QuestionMode;\n sourceType?: string;\n sourceId?: string;\n /** Optional selected-intent scope. When `scopeType === 'intent'`, `scopeId` is the selected intent id. */\n scopeType?: 'intent';\n scopeId?: string;\n}\n\n/**\n * Resolution outcome for a single awaited chat question.\n * `timeout` means the wait budget elapsed (or the run was aborted) before the\n * user responded — the question stays `pending` in the database.\n */\nexport interface ChatQuestionAnswerOutcome {\n questionId: string;\n status: \"answered\" | \"dismissed\" | \"timeout\";\n answer?: QuestionAnswer;\n}\n\n/**\n * Host bridge for the orchestrator's blocking `ask_user_question` tool.\n * `persist` synchronously inserts chat-mode question rows; `awaitAnswers`\n * blocks until every question resolves (answer/dismiss via the questions\n * REST endpoints) or the wait times out / the run is aborted.\n *\n * Implementations live in the backend (in-memory per-question wait bus,\n * single-instance semantics like the chat steer/queue interrupt emitter).\n */\nexport interface ChatQuestionsHost {\n persist(batch: PersistableQuestion[]): Promise<PersistedQuestion[]>;\n awaitAnswers(\n questionIds: string[],\n opts?: { timeoutMs?: number; signal?: AbortSignal },\n ): Promise<ChatQuestionAnswerOutcome[]>;\n}\n\nexport interface QuestionerDatabase {\n /** Persist a batch of generated questions (up to 3 per generation).\n * @returns The IDs of the inserted rows. */\n persist(questions: PersistableQuestion[]): Promise<string[]>;\n\n /** Find pending questions for a user, optionally filtered by mode/source. */\n findPending(userId: string, filters?: QuestionFilters): Promise<PersistedQuestion[]>;\n\n /** Record an answer for a question. Sets status to \"answered\".\n * Only succeeds if the user is an actor on a pending question.\n * @returns `true` if updated, `false` if not found, not pending, or unauthorized. */\n answer(questionId: string, userId: string, answer: QuestionAnswer): Promise<boolean>;\n\n /** Dismiss a question. Sets status to \"dismissed\".\n * Only succeeds if the user is an actor on a pending question.\n * @returns `true` if updated, `false` if not found, not pending, or unauthorized. */\n dismiss(questionId: string, userId: string): Promise<boolean>;\n}\n"]}
@@ -19,6 +19,21 @@ export type TraceEmitter = (event: {
19
19
  name: string;
20
20
  durationMs?: number;
21
21
  summary?: string;
22
+ } | {
23
+ type: "user_question";
24
+ questions: Array<{
25
+ id: string;
26
+ title: string;
27
+ prompt: string;
28
+ options: Array<{
29
+ label: string;
30
+ description: string;
31
+ }>;
32
+ multiSelect: boolean;
33
+ }>;
34
+ } | {
35
+ type: "status";
36
+ message: string;
22
37
  } | {
23
38
  type: "opportunity_draft_ready";
24
39
  opportunityId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"request-context.d.ts","sourceRoot":"/","sources":["shared/observability/request-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qCAAqC,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,YAAY,GAAG,CACzB,KAAK,EACD;IACE,IAAI,EAAE,aAAa,GAAG,WAAW,GAAG,aAAa,GAAG,WAAW,CAAC;IAChE,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GACD;IACE,IAAI,EAAE,yBAAyB,CAAC;IAChC,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,WAAW,CAAC;IACzB,oEAAoE;IACpE,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;;;OAMG;IACH,YAAY,EAAE;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;CACH,KACF,IAAI,CAAC;AAEV,UAAU,cAAc;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B;;;;;;;;;OASG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,mCAA0C,CAAC"}
1
+ {"version":3,"file":"request-context.d.ts","sourceRoot":"/","sources":["shared/observability/request-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qCAAqC,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,YAAY,GAAG,CACzB,KAAK,EACD;IACE,IAAI,EAAE,aAAa,GAAG,WAAW,GAAG,aAAa,GAAG,WAAW,CAAC;IAChE,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GACD;IAKE,IAAI,EAAE,eAAe,CAAC;IACtB,SAAS,EAAE,KAAK,CAAC;QACf,EAAE,EAAE,MAAM,CAAC;QACX,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,KAAK,CAAC;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QACvD,WAAW,EAAE,OAAO,CAAC;KACtB,CAAC,CAAC;CACJ,GACD;IAGE,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB,GACD;IACE,IAAI,EAAE,yBAAyB,CAAC;IAChC,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,WAAW,CAAC;IACzB,oEAAoE;IACpE,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;;;OAMG;IACH,YAAY,EAAE;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;CACH,KACF,IAAI,CAAC;AAEV,UAAU,cAAc;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B;;;;;;;;;OASG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,mCAA0C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"request-context.js","sourceRoot":"/","sources":["shared/observability/request-context.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AA4DhD;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,iBAAiB,EAAkB,CAAC","sourcesContent":["import type { Opportunity } from \"../interfaces/database.interface.js\";\nimport { AsyncLocalStorage } from \"async_hooks\";\n\n/**\n * Callback for streaming trace / domain events from deep inside graph nodes\n * back to the caller (typically chat.agent's stream pipeline).\n *\n * Carries two flavors of event:\n * - Trace events (`graph_start | graph_end | agent_start | agent_end`) — used\n * by the chat TRACE panel to visualize what the agent is doing.\n * - Domain events (`opportunity_draft_ready`) — emitted by the orchestrator\n * branch of OpportunityGraph.negotiateNode so the frontend can render each\n * accepted draft card progressively as its negotiation resolves.\n *\n * Kept as a single emitter rather than splitting into two to minimize plumbing\n * through AsyncLocalStorage; the chat.agent relay branches on event.type.\n */\nexport type TraceEmitter = (\n event:\n | {\n type: \"graph_start\" | \"graph_end\" | \"agent_start\" | \"agent_end\";\n name: string;\n durationMs?: number;\n summary?: string;\n }\n | {\n type: \"opportunity_draft_ready\";\n opportunityId: string;\n opportunity: Opportunity;\n /** Viewer-centric summary derived from interpretation.reasoning. */\n personalizedSummary?: string;\n /**\n * Minimal counterparty data for rendering the inline card without a\n * second-round-trip user lookup. Populated from the negotiation\n * candidate's profile; avatar is intentionally omitted (the card\n * falls back to initials) since UserNegotiationContext doesn't\n * carry avatars.\n */\n counterparty: {\n userId: string;\n name?: string;\n };\n },\n) => void;\n\ninterface RequestContext {\n originUrl?: string;\n traceEmitter?: TraceEmitter;\n /**\n * Signal for cooperative cancellation — propagates the caller's AbortSignal\n * into long-running graph nodes (e.g. orchestrator negotiation fan-out) so\n * they can stop emitting events when the chat session closes.\n *\n * The orchestrator branch checks this before persisting status flips or\n * pushing `opportunity_draft_ready` events. In-flight negotiations are not\n * forcibly cancelled — they finish or time out naturally via their park\n * window — but their results are suppressed once the signal trips.\n */\n abortSignal?: AbortSignal;\n}\n\n/**\n * AsyncLocalStorage for propagating request-scoped context through the protocol layer.\n * The host application is responsible for calling `requestContext.run()` to set the context.\n */\nexport const requestContext = new AsyncLocalStorage<RequestContext>();\n"]}
1
+ {"version":3,"file":"request-context.js","sourceRoot":"/","sources":["shared/observability/request-context.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAgFhD;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,iBAAiB,EAAkB,CAAC","sourcesContent":["import type { Opportunity } from \"../interfaces/database.interface.js\";\nimport { AsyncLocalStorage } from \"async_hooks\";\n\n/**\n * Callback for streaming trace / domain events from deep inside graph nodes\n * back to the caller (typically chat.agent's stream pipeline).\n *\n * Carries two flavors of event:\n * - Trace events (`graph_start | graph_end | agent_start | agent_end`) — used\n * by the chat TRACE panel to visualize what the agent is doing.\n * - Domain events (`opportunity_draft_ready`) — emitted by the orchestrator\n * branch of OpportunityGraph.negotiateNode so the frontend can render each\n * accepted draft card progressively as its negotiation resolves.\n *\n * Kept as a single emitter rather than splitting into two to minimize plumbing\n * through AsyncLocalStorage; the chat.agent relay branches on event.type.\n */\nexport type TraceEmitter = (\n event:\n | {\n type: \"graph_start\" | \"graph_end\" | \"agent_start\" | \"agent_end\";\n name: string;\n durationMs?: number;\n summary?: string;\n }\n | {\n // Emitted by the ask_user_question tool: structured questions were\n // persisted and the turn is now blocked awaiting the user's answer.\n // Carries persisted question ids so the frontend can answer them\n // through the questions REST endpoints while the stream is live.\n type: \"user_question\";\n questions: Array<{\n id: string;\n title: string;\n prompt: string;\n options: Array<{ label: string; description: string }>;\n multiSelect: boolean;\n }>;\n }\n | {\n // Lightweight keep-alive/status line. Used by long-blocking tools\n // (ask_user_question wait loop) so SSE transports do not idle out.\n type: \"status\";\n message: string;\n }\n | {\n type: \"opportunity_draft_ready\";\n opportunityId: string;\n opportunity: Opportunity;\n /** Viewer-centric summary derived from interpretation.reasoning. */\n personalizedSummary?: string;\n /**\n * Minimal counterparty data for rendering the inline card without a\n * second-round-trip user lookup. Populated from the negotiation\n * candidate's profile; avatar is intentionally omitted (the card\n * falls back to initials) since UserNegotiationContext doesn't\n * carry avatars.\n */\n counterparty: {\n userId: string;\n name?: string;\n };\n },\n) => void;\n\ninterface RequestContext {\n originUrl?: string;\n traceEmitter?: TraceEmitter;\n /**\n * Signal for cooperative cancellation — propagates the caller's AbortSignal\n * into long-running graph nodes (e.g. orchestrator negotiation fan-out) so\n * they can stop emitting events when the chat session closes.\n *\n * The orchestrator branch checks this before persisting status flips or\n * pushing `opportunity_draft_ready` events. In-flight negotiations are not\n * forcibly cancelled — they finish or time out naturally via their park\n * window — but their results are suppressed once the signal trips.\n */\n abortSignal?: AbortSignal;\n}\n\n/**\n * AsyncLocalStorage for propagating request-scoped context through the protocol layer.\n * The host application is responsible for calling `requestContext.run()` to set the context.\n */\nexport const requestContext = new AsyncLocalStorage<RequestContext>();\n"]}
@@ -179,10 +179,10 @@ export interface QuestionGenerationResult {
179
179
  questions: Question[];
180
180
  strategies: QuestionStrategy[];
181
181
  }
182
- export declare const QuestionModeSchema: z.ZodEnum<["discovery", "intent", "enrichment", "negotiation"]>;
182
+ export declare const QuestionModeSchema: z.ZodEnum<["discovery", "intent", "enrichment", "negotiation", "chat"]>;
183
183
  export declare const QuestionDetectionSchema: z.ZodObject<{
184
184
  /** Which preset mode generated this question. */
185
- mode: z.ZodEnum<["discovery", "intent", "enrichment", "negotiation"]>;
185
+ mode: z.ZodEnum<["discovery", "intent", "enrichment", "negotiation", "chat"]>;
186
186
  /** Entity type that triggered generation (e.g. "opportunity", "intent", "profile"). */
187
187
  sourceType: z.ZodString;
188
188
  /** ID of the triggering entity. */
@@ -194,14 +194,14 @@ export declare const QuestionDetectionSchema: z.ZodObject<{
194
194
  /** ID of the assistant message that triggered this question. Used by the frontend to anchor the question card inline. */
195
195
  messageId: z.ZodOptional<z.ZodString>;
196
196
  }, "strip", z.ZodTypeAny, {
197
- mode: "intent" | "enrichment" | "discovery" | "negotiation";
197
+ mode: "intent" | "chat" | "enrichment" | "discovery" | "negotiation";
198
198
  sourceType: string;
199
199
  sourceId: string;
200
200
  timestamp: string;
201
201
  triggeredBy?: string | undefined;
202
202
  messageId?: string | undefined;
203
203
  }, {
204
- mode: "intent" | "enrichment" | "discovery" | "negotiation";
204
+ mode: "intent" | "chat" | "enrichment" | "discovery" | "negotiation";
205
205
  sourceType: string;
206
206
  sourceId: string;
207
207
  timestamp: string;
@@ -1 +1 @@
1
- {"version":3,"file":"question.schema.d.ts","sourceRoot":"/","sources":["shared/schemas/question.schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,oBAAoB;IAC/B,+EAA+E;;IAE/E,iFAAiF;;;;;;;;EAEjF,CAAC;AAEH,eAAO,MAAM,cAAc;IACzB,+EAA+E;;IAE/E,yDAAyD;;IAEzD,6EAA6E;;QAX7E,+EAA+E;;QAE/E,iFAAiF;;;;;;;;;IAWjF,0EAA0E;;;;;;;;;;;;;;;;;;EAE1E,CAAC;AAEH,eAAO,MAAM,sBAAsB,oIAMjC,CAAC;AAEH,eAAO,MAAM,0BAA0B;IAlBrC,+EAA+E;;IAE/E,yDAAyD;;IAEzD,6EAA6E;;QAX7E,+EAA+E;;QAE/E,iFAAiF;;;;;;;;;IAWjF,0EAA0E;;;;;;;;;;;;;;;;;;;;;;EAc1E,CAAC;AAEH,eAAO,MAAM,+BAA+B;;QAtB1C,+EAA+E;;QAE/E,yDAAyD;;QAEzD,6EAA6E;;YAX7E,+EAA+E;;YAE/E,iFAAiF;;;;;;;;;QAWjF,0EAA0E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkB1E,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAClE,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AACtD,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AACtE,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAC9E,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAC;AAExF;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,UAAU,EAAE,gBAAgB,EAAE,CAAC;CAChC;AAID,eAAO,MAAM,kBAAkB,iEAK7B,CAAC;AAEH,eAAO,MAAM,uBAAuB;IAClC,iDAAiD;;IAEjD,uFAAuF;;IAEvF,mCAAmC;;IAEnC,kDAAkD;;IAElD,wCAAwC;;IAExC,yHAAyH;;;;;;;;;;;;;;;;EAEzH,CAAC;AAEH,eAAO,MAAM,mBAAmB;IAC9B,qCAAqC;;IAErC,gCAAgC;;IAEhC,iEAAiE;;;;;;;;;;EAEjE,CAAC;AAEH,eAAO,MAAM,oBAAoB;IAC/B,uCAAuC;;IAEvC,iEAAiE;;IAEjE,+BAA+B;;IAE/B,2DAA2D;;;;;;;;;;;;EAE3D,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAC9D,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AACxE,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAChE,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC"}
1
+ {"version":3,"file":"question.schema.d.ts","sourceRoot":"/","sources":["shared/schemas/question.schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,oBAAoB;IAC/B,+EAA+E;;IAE/E,iFAAiF;;;;;;;;EAEjF,CAAC;AAEH,eAAO,MAAM,cAAc;IACzB,+EAA+E;;IAE/E,yDAAyD;;IAEzD,6EAA6E;;QAX7E,+EAA+E;;QAE/E,iFAAiF;;;;;;;;;IAWjF,0EAA0E;;;;;;;;;;;;;;;;;;EAE1E,CAAC;AAEH,eAAO,MAAM,sBAAsB,oIAMjC,CAAC;AAEH,eAAO,MAAM,0BAA0B;IAlBrC,+EAA+E;;IAE/E,yDAAyD;;IAEzD,6EAA6E;;QAX7E,+EAA+E;;QAE/E,iFAAiF;;;;;;;;;IAWjF,0EAA0E;;;;;;;;;;;;;;;;;;;;;;EAc1E,CAAC;AAEH,eAAO,MAAM,+BAA+B;;QAtB1C,+EAA+E;;QAE/E,yDAAyD;;QAEzD,6EAA6E;;YAX7E,+EAA+E;;YAE/E,iFAAiF;;;;;;;;;QAWjF,0EAA0E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkB1E,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAClE,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AACtD,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AACtE,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAC9E,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAC;AAExF;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,UAAU,EAAE,gBAAgB,EAAE,CAAC;CAChC;AAID,eAAO,MAAM,kBAAkB,yEAO7B,CAAC;AAEH,eAAO,MAAM,uBAAuB;IAClC,iDAAiD;;IAEjD,uFAAuF;;IAEvF,mCAAmC;;IAEnC,kDAAkD;;IAElD,wCAAwC;;IAExC,yHAAyH;;;;;;;;;;;;;;;;EAEzH,CAAC;AAEH,eAAO,MAAM,mBAAmB;IAC9B,qCAAqC;;IAErC,gCAAgC;;IAEhC,iEAAiE;;;;;;;;;;EAEjE,CAAC;AAEH,eAAO,MAAM,oBAAoB;IAC/B,uCAAuC;;IAEvC,iEAAiE;;IAEjE,+BAA+B;;IAE/B,2DAA2D;;;;;;;;;;;;EAE3D,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAC9D,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AACxE,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAChE,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC"}
@@ -44,6 +44,8 @@ export const QuestionModeSchema = z.enum([
44
44
  "intent",
45
45
  "enrichment",
46
46
  "negotiation",
47
+ // Orchestrator-initiated mid-conversation questions (ask_user_question tool).
48
+ "chat",
47
49
  ]);
48
50
  export const QuestionDetectionSchema = z.object({
49
51
  /** Which preset mode generated this question. */
@@ -1 +1 @@
1
- {"version":3,"file":"question.schema.js","sourceRoot":"/","sources":["shared/schemas/question.schema.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Question — public structured shape consumed by frontend renderers and MCP\n * elicitation dispatch. Mirrors the brainstorming AskUserQuestion skill so a\n * Question can be rendered identically across surfaces.\n *\n * `QuestionWithStrategy` extends the public shape with an internal `strategy`\n * tag used by the generator's guardrails (dedup/diversity) and recorded in\n * `debugMeta`. The tag is stripped before the public payload leaves the\n * generator — users never see it.\n */\nimport { z } from \"zod\";\n\nexport const QuestionOptionSchema = z.object({\n /** Display text. Suffix \" (Recommended)\" on the safest path; list it first. */\n label: z.string().min(1).max(120),\n /** Explains the consequence of choosing this option, not just its definition. */\n description: z.string().min(1).max(280),\n});\n\nexport const QuestionSchema = z.object({\n /** ≤12 chars. Noun of the decision domain — e.g. \"Stage\", \"Timing\", \"Role\". */\n title: z.string().min(1).max(12),\n /** ≤2 sentences, ≤400 chars. Ends in a question mark. */\n prompt: z.string().min(1).max(400),\n /** 2–4 options. No explicit \"Other\" — clients provide that automatically. */\n options: z.array(QuestionOptionSchema).min(2).max(4),\n /** True when options are not mutually exclusive (priorities, bundles). */\n multiSelect: z.boolean(),\n});\n\nexport const QuestionStrategySchema = z.enum([\n \"refine_intent\",\n \"surface_missing_detail\",\n \"open_adjacent_thread\",\n \"reflective_summary\",\n \"surface_emergent_knowledge\",\n]);\n\nexport const QuestionWithStrategySchema = QuestionSchema.extend({\n strategy: QuestionStrategySchema,\n});\n\nexport const QuestionGeneratorResponseSchema = z.object({\n questions: z.array(QuestionWithStrategySchema).max(3),\n});\n\nexport type QuestionOption = z.infer<typeof QuestionOptionSchema>;\nexport type Question = z.infer<typeof QuestionSchema>;\nexport type QuestionStrategy = z.infer<typeof QuestionStrategySchema>;\nexport type QuestionWithStrategy = z.infer<typeof QuestionWithStrategySchema>;\nexport type QuestionGeneratorResponse = z.infer<typeof QuestionGeneratorResponseSchema>;\n\n/**\n * Internal generator output: public questions plus a parallel strategies\n * array for debug-only consumption. The generator emits this; callers\n * forward `questions` to renderers and `strategies` to `debugMeta` only.\n */\nexport interface QuestionGenerationResult {\n questions: Question[];\n strategies: QuestionStrategy[];\n}\n\n// ─── Persistence types (opportunity-style composable jsonb) ──────────────────\n\nexport const QuestionModeSchema = z.enum([\n \"discovery\",\n \"intent\",\n \"enrichment\",\n \"negotiation\",\n]);\n\nexport const QuestionDetectionSchema = z.object({\n /** Which preset mode generated this question. */\n mode: QuestionModeSchema,\n /** Entity type that triggered generation (e.g. \"opportunity\", \"intent\", \"profile\"). */\n sourceType: z.string().min(1),\n /** ID of the triggering entity. */\n sourceId: z.string().min(1),\n /** Optional intent ID that was the root cause. */\n triggeredBy: z.string().optional(),\n /** ISO-8601 timestamp of generation. */\n timestamp: z.string().min(1),\n /** ID of the assistant message that triggered this question. Used by the frontend to anchor the question card inline. */\n messageId: z.string().optional(),\n});\n\nexport const QuestionActorSchema = z.object({\n /** The user this question is for. */\n userId: z.string().min(1),\n /** Optional network context. */\n networkId: z.string().optional(),\n /** Actor's role in the question — currently always \"subject\". */\n role: z.literal(\"subject\"),\n});\n\nexport const QuestionAnswerSchema = z.object({\n /** Option labels the user selected. */\n selectedOptions: z.array(z.string()),\n /** Free-text input when the user chose \"Other\" or elaborated. */\n freeText: z.string().optional(),\n /** User ID of the answerer. */\n answeredBy: z.string().min(1),\n /** ISO-8601 timestamp of when the answer was submitted. */\n answeredAt: z.string().min(1),\n});\n\nexport type QuestionMode = z.infer<typeof QuestionModeSchema>;\nexport type QuestionDetection = z.infer<typeof QuestionDetectionSchema>;\nexport type QuestionActor = z.infer<typeof QuestionActorSchema>;\nexport type QuestionAnswer = z.infer<typeof QuestionAnswerSchema>;\n"]}
1
+ {"version":3,"file":"question.schema.js","sourceRoot":"/","sources":["shared/schemas/question.schema.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Question — public structured shape consumed by frontend renderers and MCP\n * elicitation dispatch. Mirrors the brainstorming AskUserQuestion skill so a\n * Question can be rendered identically across surfaces.\n *\n * `QuestionWithStrategy` extends the public shape with an internal `strategy`\n * tag used by the generator's guardrails (dedup/diversity) and recorded in\n * `debugMeta`. The tag is stripped before the public payload leaves the\n * generator — users never see it.\n */\nimport { z } from \"zod\";\n\nexport const QuestionOptionSchema = z.object({\n /** Display text. Suffix \" (Recommended)\" on the safest path; list it first. */\n label: z.string().min(1).max(120),\n /** Explains the consequence of choosing this option, not just its definition. */\n description: z.string().min(1).max(280),\n});\n\nexport const QuestionSchema = z.object({\n /** ≤12 chars. Noun of the decision domain — e.g. \"Stage\", \"Timing\", \"Role\". */\n title: z.string().min(1).max(12),\n /** ≤2 sentences, ≤400 chars. Ends in a question mark. */\n prompt: z.string().min(1).max(400),\n /** 2–4 options. No explicit \"Other\" — clients provide that automatically. */\n options: z.array(QuestionOptionSchema).min(2).max(4),\n /** True when options are not mutually exclusive (priorities, bundles). */\n multiSelect: z.boolean(),\n});\n\nexport const QuestionStrategySchema = z.enum([\n \"refine_intent\",\n \"surface_missing_detail\",\n \"open_adjacent_thread\",\n \"reflective_summary\",\n \"surface_emergent_knowledge\",\n]);\n\nexport const QuestionWithStrategySchema = QuestionSchema.extend({\n strategy: QuestionStrategySchema,\n});\n\nexport const QuestionGeneratorResponseSchema = z.object({\n questions: z.array(QuestionWithStrategySchema).max(3),\n});\n\nexport type QuestionOption = z.infer<typeof QuestionOptionSchema>;\nexport type Question = z.infer<typeof QuestionSchema>;\nexport type QuestionStrategy = z.infer<typeof QuestionStrategySchema>;\nexport type QuestionWithStrategy = z.infer<typeof QuestionWithStrategySchema>;\nexport type QuestionGeneratorResponse = z.infer<typeof QuestionGeneratorResponseSchema>;\n\n/**\n * Internal generator output: public questions plus a parallel strategies\n * array for debug-only consumption. The generator emits this; callers\n * forward `questions` to renderers and `strategies` to `debugMeta` only.\n */\nexport interface QuestionGenerationResult {\n questions: Question[];\n strategies: QuestionStrategy[];\n}\n\n// ─── Persistence types (opportunity-style composable jsonb) ──────────────────\n\nexport const QuestionModeSchema = z.enum([\n \"discovery\",\n \"intent\",\n \"enrichment\",\n \"negotiation\",\n // Orchestrator-initiated mid-conversation questions (ask_user_question tool).\n \"chat\",\n]);\n\nexport const QuestionDetectionSchema = z.object({\n /** Which preset mode generated this question. */\n mode: QuestionModeSchema,\n /** Entity type that triggered generation (e.g. \"opportunity\", \"intent\", \"profile\"). */\n sourceType: z.string().min(1),\n /** ID of the triggering entity. */\n sourceId: z.string().min(1),\n /** Optional intent ID that was the root cause. */\n triggeredBy: z.string().optional(),\n /** ISO-8601 timestamp of generation. */\n timestamp: z.string().min(1),\n /** ID of the assistant message that triggered this question. Used by the frontend to anchor the question card inline. */\n messageId: z.string().optional(),\n});\n\nexport const QuestionActorSchema = z.object({\n /** The user this question is for. */\n userId: z.string().min(1),\n /** Optional network context. */\n networkId: z.string().optional(),\n /** Actor's role in the question — currently always \"subject\". */\n role: z.literal(\"subject\"),\n});\n\nexport const QuestionAnswerSchema = z.object({\n /** Option labels the user selected. */\n selectedOptions: z.array(z.string()),\n /** Free-text input when the user chose \"Other\" or elaborated. */\n freeText: z.string().optional(),\n /** User ID of the answerer. */\n answeredBy: z.string().min(1),\n /** ISO-8601 timestamp of when the answer was submitted. */\n answeredAt: z.string().min(1),\n});\n\nexport type QuestionMode = z.infer<typeof QuestionModeSchema>;\nexport type QuestionDetection = z.infer<typeof QuestionDetectionSchema>;\nexport type QuestionActor = z.infer<typeof QuestionActorSchema>;\nexport type QuestionAnswer = z.infer<typeof QuestionAnswerSchema>;\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indexnetwork/protocol",
3
- "version": "4.3.7-rc.317.1",
3
+ "version": "4.4.0-rc.318.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",