@indexnetwork/protocol 21.1.0-rc.493.1 → 22.0.0-rc.494.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 (60) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/chat/chat-streaming.types.d.ts +2 -23
  3. package/dist/chat/chat-streaming.types.js +0 -3
  4. package/dist/chat/chat.agent.d.ts +0 -5
  5. package/dist/chat/chat.streamer.js +3 -6
  6. package/dist/chat/negotiator.persona.d.ts +1 -1
  7. package/dist/chat/negotiator.persona.js +0 -7
  8. package/dist/chat/negotiator.prompt.js +10 -12
  9. package/dist/chat/onboarding.persona.d.ts +1 -1
  10. package/dist/chat/onboarding.persona.js +0 -1
  11. package/dist/chat/onboarding.prompt.js +2 -2
  12. package/dist/chat/signal.persona.d.ts +1 -1
  13. package/dist/chat/signal.persona.js +1 -2
  14. package/dist/chat/signal.prompt.d.ts +6 -5
  15. package/dist/chat/signal.prompt.js +17 -37
  16. package/dist/index.d.ts +2 -6
  17. package/dist/index.js +1 -3
  18. package/dist/intents/graph/intent.graph.d.ts +1 -2
  19. package/dist/intents/graph/intent.graph.execute.js +0 -15
  20. package/dist/intents/graph/intent.graph.js +1 -2
  21. package/dist/intents/graph/intent.graph.shared.d.ts +0 -2
  22. package/dist/intents/intent.module.d.ts +0 -3
  23. package/dist/intents/intent.module.js +2 -2
  24. package/dist/mcp/mcp.authorization-policy.d.ts +2 -2
  25. package/dist/mcp/mcp.authorization-policy.js +0 -24
  26. package/dist/opportunities/opportunity.graph.d.ts +1 -1
  27. package/dist/opportunities/opportunity.tools.cards.d.ts +0 -13
  28. package/dist/opportunities/opportunity.tools.cards.js +0 -22
  29. package/dist/opportunities/opportunity.tools.js +4 -65
  30. package/dist/opportunities/opportunity.tools.port.d.ts +1 -1
  31. package/dist/questions/question.env.d.ts +5 -35
  32. package/dist/questions/question.env.js +5 -70
  33. package/dist/questions/question.input.d.ts +36 -145
  34. package/dist/questions/question.input.js +1 -56
  35. package/dist/questions/question.module.d.ts +10 -22
  36. package/dist/questions/question.module.js +9 -19
  37. package/dist/shared/agent/activity-projection.d.ts +2 -2
  38. package/dist/shared/agent/tool.factory.js +3 -15
  39. package/dist/shared/agent/tool.helpers.d.ts +0 -73
  40. package/dist/shared/agent/tool.registry.js +0 -2
  41. package/dist/shared/agent/tool.runtime.d.ts +1 -1
  42. package/dist/shared/agent/tool.runtime.js +3 -14
  43. package/dist/shared/observability/request-context.d.ts +0 -5
  44. package/package.json +1 -1
  45. package/dist/opportunities/opportunity.pending-questions.d.ts +0 -33
  46. package/dist/opportunities/opportunity.pending-questions.js +0 -42
  47. package/dist/questions/question.agent.d.ts +0 -28
  48. package/dist/questions/question.agent.js +0 -136
  49. package/dist/questions/question.ask.tool.d.ts +0 -12
  50. package/dist/questions/question.ask.tool.js +0 -297
  51. package/dist/questions/question.persistence.port.d.ts +0 -84
  52. package/dist/questions/question.persistence.port.js +0 -1
  53. package/dist/questions/question.presets.d.ts +0 -21
  54. package/dist/questions/question.presets.js +0 -388
  55. package/dist/questions/question.tools.d.ts +0 -15
  56. package/dist/questions/question.tools.js +0 -216
  57. package/dist/questions/question.tools.port.d.ts +0 -12
  58. package/dist/questions/question.tools.port.js +0 -1
  59. package/dist/shared/schemas/pending-question.schema.d.ts +0 -28
  60. package/dist/shared/schemas/pending-question.schema.js +0 -1
@@ -733,7 +733,7 @@ export declare class OpportunityGraphFactory {
733
733
  seedAssessmentScore?: number | undefined;
734
734
  }[]> | undefined;
735
735
  discoverySummary?: import("../shared/schemas/discovery-question.schema.js").DiscoverySummary | import("@langchain/langgraph").OverwriteValue<import("../shared/schemas/discovery-question.schema.js").DiscoverySummary | null> | null | undefined;
736
- }, "scope" | "__start__" | "discovery" | "prep" | "evaluation" | "persist" | "negotiate" | "resolve" | "ranking", {
736
+ }, "scope" | "__start__" | "prep" | "discovery" | "evaluation" | "persist" | "negotiate" | "resolve" | "ranking", {
737
737
  userId: import("@langchain/langgraph").BaseChannel<import("./opportunity.graph.shared.js").Id<"users">, import("./opportunity.graph.shared.js").Id<"users"> | import("@langchain/langgraph").OverwriteValue<import("./opportunity.graph.shared.js").Id<"users">>, unknown>;
738
738
  searchQuery: import("@langchain/langgraph").BaseChannel<string | undefined, string | import("@langchain/langgraph").OverwriteValue<string | undefined> | undefined, unknown>;
739
739
  networkId: import("@langchain/langgraph").BaseChannel<import("./opportunity.graph.shared.js").Id<"networks"> | undefined, import("./opportunity.graph.shared.js").Id<"networks"> | import("@langchain/langgraph").OverwriteValue<import("./opportunity.graph.shared.js").Id<"networks"> | undefined> | undefined, unknown>;
@@ -8,7 +8,6 @@
8
8
  import { type OpportunityOwnerAction, type OpportunityOwnerApprovalVerdict } from "./opportunity.owner-approval.js";
9
9
  export declare function stripLeadingNarratorName(remark: string, narratorName: string): string;
10
10
  import type { Opportunity } from "../shared/interfaces/database.interface.js";
11
- import type { PendingQuestionSummary } from "../shared/schemas/pending-question.schema.js";
12
11
  export declare const logger: import("../shared/observability/log.js").LoggerWithSource;
13
12
  /**
14
13
  * Build the agent-facing profile link for a counterpart — always the Index web
@@ -72,18 +71,6 @@ export declare function attachOpportunityAppLink(card: Record<string, unknown> &
72
71
  }, opts: {
73
72
  frontendUrl: string | undefined;
74
73
  }): void;
75
- export interface PublicUptakeQuestion {
76
- id: string;
77
- title: string;
78
- prompt: string;
79
- options: Array<{
80
- label: string;
81
- description: string;
82
- }>;
83
- multiSelect: boolean;
84
- }
85
- export declare function publicUptakeQuestion(question: PendingQuestionSummary): PublicUptakeQuestion;
86
- export declare function uptakeAdvisory(opportunityId: string, questions: PublicUptakeQuestion[]): string;
87
74
  /**
88
75
  * IND-593: stable fail-closed denial for the owner-approval boundary. The
89
76
  * `missing` reason carries the fresh, server-derived interaction challenge the
@@ -111,28 +111,6 @@ export function attachOpportunityAppLink(card, opts) {
111
111
  if (appUrl)
112
112
  card.appUrl = appUrl;
113
113
  }
114
- export function publicUptakeQuestion(question) {
115
- return {
116
- id: question.id,
117
- title: question.title,
118
- prompt: question.prompt,
119
- options: question.options,
120
- multiSelect: question.multiSelect,
121
- };
122
- }
123
- export function uptakeAdvisory(opportunityId, questions) {
124
- return JSON.stringify({
125
- success: false,
126
- error: "Resolve the pending uptake questions or explicitly continue anyway.",
127
- advisory: {
128
- code: "unresolved_uptake_questions",
129
- advisoryOnly: true,
130
- opportunityId,
131
- questions,
132
- acknowledgedUptakeQuestionIds: questions.map((question) => question.id),
133
- },
134
- });
135
- }
136
114
  /**
137
115
  * IND-593: stable fail-closed denial for the owner-approval boundary. The
138
116
  * `missing` reason carries the fresh, server-derived interaction challenge the
@@ -10,14 +10,13 @@ import { requestContext } from "../shared/observability/request-context.js";
10
10
  import { success, error, UUID_REGEX } from "../shared/agent/tool.helpers.js";
11
11
  import { focusedIntentId, focusedNetworkId } from "../shared/agent/tool.scope.js";
12
12
  import { OpportunityPresenter, gatherPresenterContext } from "./opportunity.presentation.js";
13
- import { isUptakeGuardEnabled } from "../questions/question.module.js";
14
13
  import { admitOpportunityUpdate } from "./opportunity.update-admission.js";
15
14
  import { opportunityOwnerActionForStatus } from "./opportunity.owner-approval.js";
16
15
  import { ownerApprovalProvenanceFor } from "./opportunity.owner-provenance.js";
17
16
  export { buildOpportunityPresentation } from "./opportunity.presentation.js";
18
17
  import { sendOpportunity, updateOpportunityStatus } from "./opportunity.graph.modes.js";
19
18
  import { createListOpportunitiesTool } from "./opportunity.tools.list.js";
20
- import { confirmDeliveryError, logger, ownerApprovalDenial, publicUptakeQuestion, uptakeAdvisory } from "./opportunity.tools.cards.js";
19
+ import { confirmDeliveryError, logger, ownerApprovalDenial } from "./opportunity.tools.cards.js";
21
20
  export { attachOpportunityAppLink, attachProfileLink, buildMinimalOpportunityCard, buildNegotiationUrl, buildOpportunityAppUrl, buildProfileUrl } from "./opportunity.tools.cards.js";
22
21
  export function createOpportunityTools(defineTool, deps) {
23
22
  const { database, userDb, systemDb, graphs, cache } = deps;
@@ -36,13 +35,12 @@ export function createOpportunityTools(defineTool, deps) {
36
35
  "- `rejected`: Decline a received opportunity.\n" +
37
36
  "- `expired`: Mark as expired (typically done by the system after timeout).\n\n" +
38
37
  "**When to use:** After list_opportunities returns persisted opportunity cards. " +
39
- "The user clicks 'Send' (pending), 'Accept', or 'Reject' on the card, and the agent calls this tool. " +
40
- "An accepted transition may first return a non-success uptake advisory with preparatory questions. Surface those questions, then retry with all returned question ids in acknowledgedUptakeQuestionIds; acknowledgement confirms presentation, not an answer.\n\n" +
38
+ "The user clicks 'Send' (pending), 'Accept', or 'Reject' on the card, and the agent calls this tool.\n\n" +
41
39
  "**Owner approval (agents):** Agent-driven send/accept/reject transitions require an explicit owner-issued approval proof. " +
42
40
  "Call without ownerApprovalProof first: the denial returns an approval challenge (interactionId, expiresAt) bound to the exact opportunity, action, owner, and agent. " +
43
41
  "Relay that challenge to the owner for explicit approval, then retry once with the issued ownerApprovalProof. " +
44
- "Proofs are single-use and expire; acknowledgedUptakeQuestionIds, negotiation approvals, and advisory values are never substitutes.\n\n" +
45
- "**Returns:** Confirmation with the new status and notification details (who was notified), or a structured uptake advisory without mutation.",
42
+ "Proofs are single-use and expire; negotiation approvals and advisory values are never substitutes.\n\n" +
43
+ "**Returns:** Confirmation with the new status and notification details (who was notified).",
46
44
  querySchema: z.object({
47
45
  opportunityId: z
48
46
  .string()
@@ -58,10 +56,6 @@ export function createOpportunityTools(defineTool, deps) {
58
56
  .describe("Opaque owner-issued approval proof for this exact transition (agents only). Obtained after the owner " +
59
57
  "explicitly approves the interaction challenge returned by a proof-less call. The opportunity, action, " +
60
58
  "owner, agent, and interaction binding is always derived server-side; only this token is presented."),
61
- acknowledgedUptakeQuestionIds: z
62
- .array(z.string().min(1))
63
- .optional()
64
- .describe("On an acknowledged retry after an uptake advisory, include every question id returned by that advisory."),
65
59
  scopeType: z
66
60
  .enum(['intent'])
67
61
  .optional()
@@ -137,61 +131,6 @@ export function createOpportunityTools(defineTool, deps) {
137
131
  if (verdict.kind === 'denied')
138
132
  return ownerApprovalDenial(opportunityId, ownerAction, verdict);
139
133
  }
140
- // The caller actor's own network is the exact question lookup boundary,
141
- // even for an otherwise unscoped request. A focused network may only be
142
- // equal to this after the guard above.
143
- // Unscoped callers query all of their exact opportunity questions; a
144
- // network-scoped caller is clamped to the bound network. Selecting the
145
- // first duplicate actor row would miss a valid question on another
146
- // shared network.
147
- const uptakeNetworkId = scopedNetworkId;
148
- // Soft uptake interlock: only acceptance is advisory-gated. All existing
149
- // actor/scope/privacy guards run first so the question lookup cannot be
150
- // used to probe opportunities or networks the caller cannot access.
151
- if (query.status === "accepted" && isUptakeGuardEnabled() && deps.findPendingQuestions) {
152
- try {
153
- const pending = await deps.findPendingQuestions(context.userId, {
154
- sourceType: "opportunity",
155
- sourceId: opportunityId,
156
- modes: ["negotiation"],
157
- purpose: "uptake",
158
- ...(uptakeNetworkId ? { networkId: uptakeNetworkId } : {}),
159
- });
160
- // Defense in depth if a host overlooks one or more filters. Actor
161
- // internals are checked here and never serialized into the advisory.
162
- const exactPending = pending.filter((question) => {
163
- if (question.sourceType !== "opportunity" ||
164
- question.sourceId !== opportunityId ||
165
- question.mode !== "negotiation" ||
166
- question.purpose !== "uptake") {
167
- return false;
168
- }
169
- if (!question.actors?.some((actor) => actor.userId === context.userId))
170
- return false;
171
- if (uptakeNetworkId && !question.actors.some((actor) => actor.userId === context.userId && actor.networkId === uptakeNetworkId)) {
172
- return false;
173
- }
174
- return true;
175
- });
176
- const acknowledged = new Set(query.acknowledgedUptakeQuestionIds ?? []);
177
- if (exactPending.some((question) => !acknowledged.has(question.id))) {
178
- return uptakeAdvisory(opportunityId, exactPending.map(publicUptakeQuestion));
179
- }
180
- }
181
- catch (err) {
182
- logger.warn("update_opportunity: uptake question lookup failed open", {
183
- opportunityId,
184
- userId: context.userId,
185
- error: err instanceof Error ? err.message : String(err),
186
- });
187
- deps.reportToolError?.(err, {
188
- subsystem: "opportunity",
189
- operation: "opportunity.uptake_lookup",
190
- toolName: "update_opportunity",
191
- userId: context.userId,
192
- });
193
- }
194
- }
195
134
  const isSend = query.status === "pending";
196
135
  const _updateGraphStart = Date.now();
197
136
  const _updateTraceEmitter = requestContext.getStore()?.traceEmitter;
@@ -11,6 +11,6 @@ export interface OpportunityOwnerApprovalDeps {
11
11
  opportunityOwnerApproval?: OpportunityOwnerApprovalAuthority;
12
12
  }
13
13
  /** Host capabilities consumed by opportunity discovery, delivery, and presentation tools. */
14
- export type OpportunityToolDeps = Pick<ToolRegistryCompositionDeps, "database" | "userDb" | "systemDb" | "cache" | "chatSummary" | "opportunityPresentation" | "questionerEnqueue" | "findPendingQuestions" | "negotiationSummary" | "negotiationDatabase" | "deliveryLedger" | "frontendUrl" | "stampNewbornOpportunities" | "reportToolError" | "opportunityOperations"> & OpportunityOwnerApprovalDeps & {
14
+ export type OpportunityToolDeps = Pick<ToolRegistryCompositionDeps, "database" | "userDb" | "systemDb" | "cache" | "chatSummary" | "opportunityPresentation" | "questionerEnqueue" | "negotiationSummary" | "negotiationDatabase" | "deliveryLedger" | "frontendUrl" | "stampNewbornOpportunities" | "reportToolError" | "opportunityOperations"> & OpportunityOwnerApprovalDeps & {
15
15
  graphs: Pick<ToolRegistryCompositionDeps["graphs"], "index" | "networkMembership" | "opportunity">;
16
16
  };
@@ -1,26 +1,11 @@
1
1
  /**
2
- * questions/question.env — centralized question-generation env accessors.
2
+ * questions/question.env — leftover question env constants.
3
3
  *
4
- * Naming scheme (one prefix, hierarchical):
5
- *
6
- * QUESTIONER_ENABLED master switch — QuestionerQueue worker +
7
- * enqueue closures at every composition site.
8
- * QUESTIONER_UPTAKE_ENABLED per-surface switch — advisory pre-accept uptake
9
- * interlock. Requires the master switch.
10
- * QUESTIONER_UPTAKE_AUTHORITY_THRESHOLD
11
- * authority threshold (0-100, default 70).
12
- * QUESTIONER_CHAT_WAIT_TIMEOUT_MS how long the blocking ask_user_question chat
13
- * tool waits for an inline answer (default 4 min).
14
- * QUESTIONER_INTENT_DAILY_CAP refinement questions one intent may generate
15
- * per rolling 24h, recovery + pool combined
16
- * (default 2; 0 disables refinement).
17
- *
18
- * All reads go through this module — do not read these variables via
19
- * `process.env` elsewhere. Values are read on every call (no caching) so tests
20
- * and long-lived processes observe changes.
4
+ * The QUESTIONER_* runtime flags are retired with the card generators
5
+ * (conversational-questions plan); park-path routing is always on. What
6
+ * remains are the historical budget constants still referenced by the
7
+ * questions-table adapter until its surface drops.
21
8
  */
22
- export declare const CHAT_QUESTION_WAIT_TIMEOUT_MS_DEFAULT = 240000;
23
- export declare const UPTAKE_AUTHORITY_THRESHOLD_DEFAULT = 70;
24
9
  /**
25
10
  * Refinement questions a single intent may generate per rolling window.
26
11
  *
@@ -40,18 +25,3 @@ export declare const INTENT_QUESTION_DAILY_CAP_DEFAULT = 2;
40
25
  * have granted the second burst a full fresh allowance.
41
26
  */
42
27
  export declare const INTENT_QUESTION_DAILY_WINDOW_HOURS = 24;
43
- /** Master switch: is any background question generation enabled? */
44
- export declare function isQuestionerEnabled(): boolean;
45
- /** Advisory uptake interlock. Flag-off by default and subordinate to the master switch. */
46
- export declare function isUptakeGuardEnabled(): boolean;
47
- /** Authority threshold below which hosts may generate uptake questions. */
48
- export declare function uptakeAuthorityThreshold(): number;
49
- /** Wait budget for the blocking ask_user_question chat tool. */
50
- export declare function chatQuestionWaitTimeoutMs(): number;
51
- /**
52
- * Per-intent refinement budget over {@link INTENT_QUESTION_DAILY_WINDOW_HOURS}.
53
- *
54
- * Zero is a meaningful setting — it disables background refinement entirely
55
- * without touching the master switch — so this does not reuse `positiveIntEnv`.
56
- */
57
- export declare function intentQuestionDailyCap(): number;
@@ -1,26 +1,11 @@
1
1
  /**
2
- * questions/question.env — centralized question-generation env accessors.
2
+ * questions/question.env — leftover question env constants.
3
3
  *
4
- * Naming scheme (one prefix, hierarchical):
5
- *
6
- * QUESTIONER_ENABLED master switch — QuestionerQueue worker +
7
- * enqueue closures at every composition site.
8
- * QUESTIONER_UPTAKE_ENABLED per-surface switch — advisory pre-accept uptake
9
- * interlock. Requires the master switch.
10
- * QUESTIONER_UPTAKE_AUTHORITY_THRESHOLD
11
- * authority threshold (0-100, default 70).
12
- * QUESTIONER_CHAT_WAIT_TIMEOUT_MS how long the blocking ask_user_question chat
13
- * tool waits for an inline answer (default 4 min).
14
- * QUESTIONER_INTENT_DAILY_CAP refinement questions one intent may generate
15
- * per rolling 24h, recovery + pool combined
16
- * (default 2; 0 disables refinement).
17
- *
18
- * All reads go through this module — do not read these variables via
19
- * `process.env` elsewhere. Values are read on every call (no caching) so tests
20
- * and long-lived processes observe changes.
4
+ * The QUESTIONER_* runtime flags are retired with the card generators
5
+ * (conversational-questions plan); park-path routing is always on. What
6
+ * remains are the historical budget constants still referenced by the
7
+ * questions-table adapter until its surface drops.
21
8
  */
22
- export const CHAT_QUESTION_WAIT_TIMEOUT_MS_DEFAULT = 240000;
23
- export const UPTAKE_AUTHORITY_THRESHOLD_DEFAULT = 70;
24
9
  /**
25
10
  * Refinement questions a single intent may generate per rolling window.
26
11
  *
@@ -40,53 +25,3 @@ export const INTENT_QUESTION_DAILY_CAP_DEFAULT = 2;
40
25
  * have granted the second burst a full fresh allowance.
41
26
  */
42
27
  export const INTENT_QUESTION_DAILY_WINDOW_HOURS = 24;
43
- /**
44
- * Parse a positive integer env var, clamped to the safe-integer range so a
45
- * malformed env value cannot crash `AbortSignal.timeout` (which throws on
46
- * values outside `[0, MAX_SAFE_INTEGER]`).
47
- */
48
- function positiveIntEnv(name, fallback) {
49
- const raw = process.env[name];
50
- if (!raw)
51
- return fallback;
52
- const parsed = Number.parseInt(raw, 10);
53
- if (!Number.isFinite(parsed) || parsed <= 0 || parsed > Number.MAX_SAFE_INTEGER)
54
- return fallback;
55
- return parsed;
56
- }
57
- /** Master switch: is any background question generation enabled? */
58
- export function isQuestionerEnabled() {
59
- return process.env.QUESTIONER_ENABLED === "true";
60
- }
61
- /** Advisory uptake interlock. Flag-off by default and subordinate to the master switch. */
62
- export function isUptakeGuardEnabled() {
63
- return isQuestionerEnabled() && process.env.QUESTIONER_UPTAKE_ENABLED === "true";
64
- }
65
- /** Authority threshold below which hosts may generate uptake questions. */
66
- export function uptakeAuthorityThreshold() {
67
- const raw = process.env.QUESTIONER_UPTAKE_AUTHORITY_THRESHOLD;
68
- if (!raw?.trim())
69
- return UPTAKE_AUTHORITY_THRESHOLD_DEFAULT;
70
- if (!/^-?\d+$/.test(raw.trim()))
71
- return UPTAKE_AUTHORITY_THRESHOLD_DEFAULT;
72
- const parsed = Number.parseInt(raw, 10);
73
- return Math.min(100, Math.max(0, parsed));
74
- }
75
- /** Wait budget for the blocking ask_user_question chat tool. */
76
- export function chatQuestionWaitTimeoutMs() {
77
- return positiveIntEnv("QUESTIONER_CHAT_WAIT_TIMEOUT_MS", CHAT_QUESTION_WAIT_TIMEOUT_MS_DEFAULT);
78
- }
79
- /**
80
- * Per-intent refinement budget over {@link INTENT_QUESTION_DAILY_WINDOW_HOURS}.
81
- *
82
- * Zero is a meaningful setting — it disables background refinement entirely
83
- * without touching the master switch — so this does not reuse `positiveIntEnv`.
84
- */
85
- export function intentQuestionDailyCap() {
86
- const raw = process.env.QUESTIONER_INTENT_DAILY_CAP;
87
- if (!raw?.trim())
88
- return INTENT_QUESTION_DAILY_CAP_DEFAULT;
89
- if (!/^\d+$/.test(raw.trim()))
90
- return INTENT_QUESTION_DAILY_CAP_DEFAULT;
91
- return Number.parseInt(raw, 10);
92
- }
@@ -1,37 +1,20 @@
1
1
  /**
2
- * questions/question.input — QuestionerAgent input envelope.
2
+ * questions/question.input — park-path question payloads.
3
3
  *
4
- * Defines per-mode context types (IntentContext, NegotiationContext, …),
5
- * the discriminated QuestionerInput union, and the runtime validation guard
6
- * `isValidQuestionerInputContract`.
7
- *
8
- * Lives in the application layer (not domain) because `isValidQuestionerInputContract`
9
- * consumes the negotiation question-safety port
10
- * (`capabilities/negotiation.questions.facade`) to enforce privacy invariants
11
- * on counterparty hints and indexContext labels.
12
- *
13
- * Foreground and ambient adapter entry points inject a `QuestionerEnqueueFn`
14
- * (defined here as a port alias) to schedule async generation without
15
- * importing the queue implementation.
4
+ * The QuestionerAgent and its per-mode generation envelope are retired
5
+ * (conversational-questions plan, "Retirements"). What survives is the
6
+ * payload the negotiation graph hands the composition root when a
7
+ * negotiation parks needing its client's input: the two park families
8
+ * (`negotiation_inflight`/`inflight_consultation` mid-flight consults and
9
+ * `negotiation`/`stalled_followup` post-stall parks). The composition root
10
+ * routes them to the question-message regeneration queue keyed on the parked
11
+ * side's `(recipientUserId, recipientIntentId)`; the parked negotiation is
12
+ * the durable record and the DM message is its rendering.
16
13
  */
17
14
  import type { ToolScopeType } from "../shared/agent/tool.scope.js";
18
- import type { NegotiationQuestionCandidate, QuestionMode, QuestionPoolDiscriminator } from "./question.schema.js";
15
+ import type { NegotiationQuestionCandidate } from "./question.schema.js";
19
16
  import type { NegotiationConsultationReason } from "../negotiations/negotiation.module.js";
20
- /** Intent context — data needed to generate questions about an intent. */
21
- export interface IntentContext {
22
- intentId: string;
23
- payload: string;
24
- summary?: string;
25
- /** The user's global user_context paragraph (profile-replacing identity text). */
26
- userContext?: string;
27
- }
28
- /** Recovery-only intent context after a successful discovery completion. */
29
- export interface RecoveryIntentContext extends IntentContext {
30
- purpose: "recovery";
31
- /** Privacy-safe aggregate signal; raw negotiation evidence is never provided. */
32
- rejectedNegotiationCount?: number;
33
- }
34
- /** Shared context fields for negotiation-mode questions. */
17
+ /** Shared context fields for negotiation park payloads. */
35
18
  interface NegotiationContextBase {
36
19
  negotiationId: string;
37
20
  /** Privacy-reviewed generic description; never raw counterparty identity/profile. */
@@ -48,20 +31,10 @@ export interface PostStallNegotiationContext extends NegotiationContextBase {
48
31
  /** The recipient's own exact opportunity-bound signal, never evaluator reasoning. */
49
32
  recipientIntent: string;
50
33
  }
51
- /** Pre-accept uptake context targeting a counterparty's preparatory conditions. */
52
- export interface UptakeNegotiationContext extends NegotiationContextBase {
53
- purpose: "uptake";
54
- /** Plain-language activity or commitment whose feasibility needs clarification. */
55
- proposedActivity: string;
56
- }
57
- /** Negotiation context discriminated by internal question purpose. */
58
- export type NegotiationContext = PostStallNegotiationContext | UptakeNegotiationContext;
59
34
  /**
60
35
  * Negotiation-inflight context — a negotiator mid-negotiation wants to ask its
61
- * OWN client a question before continuing (the `ask_user` action, P3.2). The
62
- * negotiator supplies only a closed category; the QuestionerAgent receives
63
- * server-owned fixed copy and never agent-authored instruction text.
64
- * Distinct from {@link NegotiationContext}, which covers post-stall questions.
36
+ * OWN client a question before continuing (the `ask_user` action, P3.2).
37
+ * The negotiator supplies only a closed category.
65
38
  */
66
39
  export interface NegotiationInflightContext {
67
40
  negotiationId: string;
@@ -69,108 +42,47 @@ export interface NegotiationInflightContext {
69
42
  counterpartyHint: string;
70
43
  /** Community / index context the negotiation runs in. */
71
44
  indexContext: string;
72
- /** Closed server-owned category selecting fixed Questioner copy. */
45
+ /** Closed server-owned category selecting the consultation reason. */
73
46
  consultationPolicyReason: NegotiationConsultationReason;
74
47
  /** The user's global user_context paragraph (profile-replacing identity text). */
75
48
  userContext?: string;
76
49
  }
77
50
  /**
78
- * Chat context — data for orchestrator-initiated mid-conversation questions
79
- * (the `ask_user_question` tool). The orchestrator states what it needs to
80
- * learn; the QuestionerAgent turns that into polished structured questions,
81
- * grounded in the recent conversation and the user's identity context.
82
- */
83
- export interface ChatContext {
84
- /** What the orchestrator needs to learn and why (authored by the chat model). */
85
- purpose: string;
86
- /** Draft questions proposed by the orchestrator. The agent refines these. */
87
- draftQuestions?: Array<{
88
- prompt: string;
89
- options?: string[];
90
- multiSelect?: boolean;
91
- }>;
92
- /** Recent conversation excerpt for grounding (most recent messages last). */
93
- conversationExcerpt?: string;
94
- /** The user's global user_context paragraph (profile-replacing identity text). */
95
- userContext?: string;
96
- }
97
- /**
98
- * Pool-discovery context — mined discriminators from a discovery-run pool
99
- * (IND-418). No generator LLM runs for this mode: the QuestionerQueue
100
- * synthesizes the question deterministically from the top discriminator and
101
- * stashes the rest as interview-mode alternates.
102
- */
103
- export interface PoolDiscoveryContext {
104
- intentId: string;
105
- /** Truncated intent payload (+ summary) display snippet. */
106
- intentText: string;
107
- /** Stable hash of the full normalized payload + summary used for freshness. */
108
- intentFingerprint?: string;
109
- poolSize: number;
110
- /** Exact bounded candidate opportunity IDs supplied to synthesis. */
111
- opportunityIds: string[];
112
- /** Discovery run that produced the pool. */
113
- runId?: string;
114
- /** Eligible discriminators, VoI-descending (asked + chain alternates). */
115
- discriminators: QuestionPoolDiscriminator[];
116
- /** ISO-8601 timestamp of the mining pass. */
117
- minedAt: string;
118
- }
119
- /** Discriminated union: mode selects the context shape. */
120
- export type QuestionerContext = IntentContext | RecoveryIntentContext | NegotiationContext | NegotiationInflightContext | ChatContext | PoolDiscoveryContext;
121
- /**
122
- * Payload shape accepted by the questionerEnqueue callback. Covers all
123
- * question modes — the composition root bridges this to the concrete
124
- * QuestionerQueue.
51
+ * Payload shape accepted by the questionerEnqueue callback: exactly the two
52
+ * park families. The composition root bridges this to the question-message
53
+ * regeneration queue.
125
54
  */
126
55
  export type QuestionerEnqueuePayload = QuestionerInput;
127
56
  /**
128
- * Callback signature for async question generation enqueue.
57
+ * Callback signature for the park-path enqueue.
129
58
  *
130
- * Ambient adapter port: recovery, pool, uptake, inflight, and push generation
131
- * each inject this callback from the composition root; they never import the
132
- * queue implementation directly.
59
+ * Ambient adapter port: the negotiation graph and the external-consultation
60
+ * pause path inject this callback from the composition root; they never
61
+ * import the queue implementation directly.
133
62
  */
134
63
  export type QuestionerEnqueueFn = (input: QuestionerEnqueuePayload) => Promise<void>;
135
- /** Top-level input envelope for QuestionerAgent.invoke(). */
64
+ /** Shared envelope fields for both park families. */
136
65
  interface QuestionerInputBase {
137
- /** Selects the preset (system prompt + builder). */
138
- mode: QuestionMode;
139
- /** User the questions are generated for. */
66
+ /** User whose input is required (the parked side). */
140
67
  userId: string;
141
- /** Entity type that triggered this (e.g. "opportunity", "intent", "profile"). */
68
+ /** Entity type that triggered this (always "opportunity" for park payloads). */
142
69
  sourceType: string;
143
70
  /** ID of the triggering entity. */
144
71
  sourceId: string;
145
- /** Scoped question context. Network scopes persist as QuestionActor.networkId. */
72
+ /** Scoped context carried through from the triggering surface. */
146
73
  scopeType?: ToolScopeType;
147
- /** Scoped question id. When scopeType is `network`, this is the actor networkId. */
74
+ /** Scoped id. When scopeType is `network`, this is the network id. */
148
75
  scopeId?: string;
149
- /**
150
- * Intent that triggered the run that generated these questions. Persisted as
151
- * `detection.triggeredBy` so intent-scoped surfaces (e.g. the intent page)
152
- * can find them. Independent of `scopeType`/`scopeId`, which may carry a
153
- * network scope at the same time.
154
- */
76
+ /** Intent that triggered the run, when the producer knows it. */
155
77
  triggeredByIntentId?: string;
156
- /** Conversation ID — set when the question originates from a chat session. Persisted on the question row for frontend filtering. */
157
- conversationId?: string;
158
- /** Assistant message ID — set when we know which message triggered the question. Stored in detection.messageId for inline anchoring. */
159
- messageId?: string;
160
78
  /**
161
- * Candidate exact binding for negotiation-family jobs. The API/DB must
162
- * authoritatively re-resolve it before generation and again before insert.
79
+ * Candidate exact binding. `recipientUserId`/`recipientIntentId` name the
80
+ * parked side — the user whose input is required and the signal whose DM
81
+ * carries the question-message.
163
82
  */
164
- negotiation?: NegotiationQuestionCandidate;
165
- }
166
- /** Non-negotiation modes cannot smuggle negotiation purpose/provenance. */
167
- interface StandardQuestionerInput extends QuestionerInputBase {
168
- mode: Exclude<QuestionMode, "negotiation" | "negotiation_inflight">;
169
- purpose?: never;
170
- negotiation?: never;
171
- context: Exclude<QuestionerContext, NegotiationContext | NegotiationInflightContext | RecoveryIntentContext>;
83
+ negotiation: NegotiationQuestionCandidate;
172
84
  }
173
- /** Ordinary post-stall generation is task-backed and uses only the ordinary preset. */
85
+ /** Post-stall park payload, task-backed. */
174
86
  export interface PostStallQuestionerInput extends QuestionerInputBase {
175
87
  mode: "negotiation";
176
88
  purpose: "stalled_followup";
@@ -180,7 +92,7 @@ export interface PostStallQuestionerInput extends QuestionerInputBase {
180
92
  };
181
93
  context: PostStallNegotiationContext;
182
94
  }
183
- /** Mid-negotiation consultation is task-backed and uses only structured ask_user fields. */
95
+ /** Mid-negotiation consultation park payload, task-backed. */
184
96
  export interface InflightQuestionerInput extends QuestionerInputBase {
185
97
  mode: "negotiation_inflight";
186
98
  purpose: "inflight_consultation";
@@ -190,27 +102,6 @@ export interface InflightQuestionerInput extends QuestionerInputBase {
190
102
  };
191
103
  context: NegotiationInflightContext;
192
104
  }
193
- /** Negotiation-mode uptake generation input. */
194
- export interface UptakeQuestionerInput extends QuestionerInputBase {
195
- mode: "negotiation";
196
- purpose: "uptake";
197
- negotiation: NegotiationQuestionCandidate & {
198
- purpose: "uptake";
199
- taskId?: undefined;
200
- };
201
- context: UptakeNegotiationContext;
202
- }
203
- /** Intent-mode post-discovery recovery generation input. */
204
- export interface RecoveryQuestionerInput extends QuestionerInputBase {
205
- mode: "intent";
206
- purpose: "recovery";
207
- sourceType: "intent";
208
- triggeredByIntentId: string;
209
- negotiation?: never;
210
- context: RecoveryIntentContext;
211
- }
212
- /** Top-level input discriminated by both mode and internal purpose. */
213
- export type QuestionerInput = StandardQuestionerInput | PostStallQuestionerInput | InflightQuestionerInput | UptakeQuestionerInput | RecoveryQuestionerInput;
214
- /** Runtime mirror of the mode/purpose/context discriminant used at queue boundaries. */
215
- export declare function isValidQuestionerInputContract(input: QuestionerInput): boolean;
105
+ /** Park-path payload union, discriminated by mode + internal purpose. */
106
+ export type QuestionerInput = PostStallQuestionerInput | InflightQuestionerInput;
216
107
  export {};
@@ -1,56 +1 @@
1
- import { NEGOTIATION_QUESTION_GENERIC_COUNTERPARTY, NEGOTIATION_QUESTION_GENERIC_NETWORK, NEGOTIATION_QUESTION_GENERIC_UPTAKE_ACTIVITY } from "../negotiations/negotiation.module.js";
2
- /** Runtime mirror of the mode/purpose/context discriminant used at queue boundaries. */
3
- export function isValidQuestionerInputContract(input) {
4
- if (input.purpose === 'recovery') {
5
- const context = input.context;
6
- return input.mode === 'intent'
7
- && input.sourceType === 'intent'
8
- && input.triggeredByIntentId === input.sourceId
9
- && input.negotiation === undefined
10
- && context.purpose === 'recovery'
11
- && context.intentId === input.sourceId;
12
- }
13
- if (input.mode !== 'negotiation' && input.mode !== 'negotiation_inflight') {
14
- return input.purpose === undefined && input.negotiation === undefined;
15
- }
16
- if (input.sourceType !== 'opportunity'
17
- || !input.negotiation
18
- || input.negotiation.opportunityId !== input.sourceId
19
- || input.negotiation.recipientUserId !== input.userId
20
- || input.negotiation.purpose !== input.purpose)
21
- return false;
22
- const context = input.context;
23
- if (context.counterpartyHint !== NEGOTIATION_QUESTION_GENERIC_COUNTERPARTY
24
- || context.indexContext !== NEGOTIATION_QUESTION_GENERIC_NETWORK)
25
- return false;
26
- if (input.mode === 'negotiation_inflight') {
27
- return input.purpose === 'inflight_consultation'
28
- && typeof input.negotiation.taskId === 'string'
29
- && input.negotiation.taskId.length > 0
30
- && context.negotiationId === input.negotiation.taskId
31
- && (context.consultationPolicyReason === 'unresolved_owner_constraint'
32
- || context.consultationPolicyReason === 'consequential_disclosure_permission'
33
- || context.consultationPolicyReason === 'repeated_non_convergence'
34
- || context.consultationPolicyReason === 'insufficient_commitment_authority');
35
- }
36
- if (input.purpose === 'uptake') {
37
- return input.negotiation.taskId === undefined
38
- && typeof input.negotiation.counterpartyUserId === 'string'
39
- && input.negotiation.counterpartyUserId.length > 0
40
- && typeof input.negotiation.counterpartyIntentId === 'string'
41
- && input.negotiation.counterpartyIntentId.length > 0
42
- && typeof input.negotiation.counterpartyFelicityAuthority === 'number'
43
- && Number.isFinite(input.negotiation.counterpartyFelicityAuthority)
44
- && context.negotiationId === input.sourceId
45
- && context.purpose === 'uptake'
46
- && context.proposedActivity === NEGOTIATION_QUESTION_GENERIC_UPTAKE_ACTIVITY;
47
- }
48
- return input.purpose === 'stalled_followup'
49
- && typeof input.negotiation.taskId === 'string'
50
- && input.negotiation.taskId.length > 0
51
- && context.negotiationId === input.negotiation.taskId
52
- && context.purpose === undefined
53
- && (context.outcomeReason === 'turn_cap' || context.outcomeReason === 'timeout' || context.outcomeReason === 'stalled')
54
- && typeof context.recipientIntent === 'string'
55
- && context.recipientIntent.trim().length > 0;
56
- }
1
+ export {};