@indexnetwork/protocol 12.1.0-rc.463.1 → 13.1.0-rc.465.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -0
- package/dist/capabilities/questions.facade.d.ts +2 -2
- package/dist/capabilities/questions.facade.js +1 -1
- package/dist/capabilities/questions.runtime.facade.d.ts +1 -1
- package/dist/capabilities/questions.runtime.facade.js +1 -1
- package/dist/chat/reporter.persona.js +1 -1
- package/dist/enrichment/enrichment.graph.d.ts +1 -3
- package/dist/enrichment/enrichment.graph.js +1 -2
- package/dist/index.d.ts +2 -2
- package/dist/negotiation/application/negotiation.graph.d.ts +5 -5
- package/dist/negotiation/domain/negotiation.state.d.ts +1 -1
- package/dist/opportunity/application/opportunity.graph.d.ts +23 -23
- package/dist/opportunity/domain/opportunity.state.d.ts +6 -6
- package/dist/opportunity/ports/opportunity.tools.port.d.ts +1 -1
- package/dist/questions/application/index.d.ts +2 -2
- package/dist/questions/application/index.js +1 -1
- package/dist/questions/application/question.env.d.ts +0 -30
- package/dist/questions/application/question.env.js +0 -38
- package/dist/questions/application/question.input.d.ts +2 -16
- package/dist/questions/application/question.presets.js +0 -66
- package/dist/questions/application/question.tools.js +3 -3
- package/dist/questions/domain/question.schema.d.ts +84 -68
- package/dist/questions/domain/question.schema.js +9 -3
- package/dist/questions/ports/index.d.ts +0 -2
- package/dist/questions/ports/index.js +0 -1
- package/dist/questions/public/index.d.ts +2 -2
- package/dist/questions/public/index.js +1 -1
- package/dist/runtime/foreground/composition/tool.factory.js +1 -2
- package/dist/shared/agent/activity-projection.d.ts +4 -4
- package/dist/shared/agent/activity-projection.js +6 -0
- package/dist/shared/agent/tool.helpers.d.ts +2 -8
- package/dist/shared/schemas/discovery-question.schema.d.ts +10 -28
- package/dist/shared/schemas/discovery-question.schema.js +2 -4
- package/dist/shared/schemas/negotiation-digest.schema.d.ts +5 -5
- package/package.json +1 -1
- package/dist/questions/application/question.discovery.prompt.d.ts +0 -8
- package/dist/questions/application/question.discovery.prompt.js +0 -181
- package/dist/questions/ports/question.generator.port.d.ts +0 -33
- package/dist/questions/ports/question.generator.port.js +0 -1
|
@@ -9,14 +9,6 @@
|
|
|
9
9
|
* interlock. Requires the master switch.
|
|
10
10
|
* QUESTIONER_UPTAKE_AUTHORITY_THRESHOLD
|
|
11
11
|
* authority threshold (0-100, default 70).
|
|
12
|
-
* QUESTIONER_DISCOVERY_ENABLED per-surface switch — decision questions during
|
|
13
|
-
* chat/MCP opportunity discovery. Only effective
|
|
14
|
-
* when the master switch is on (the discovery
|
|
15
|
-
* question step adds inline summarizer latency,
|
|
16
|
-
* so operators can turn it off independently).
|
|
17
|
-
* QUESTIONER_DISCOVERY_INPUT_MODE 'transcripts' | 'insights' generator input.
|
|
18
|
-
* QUESTIONER_DISCOVERY_TIMEOUT_MS per-call deadline for the discovery-questions
|
|
19
|
-
* LLM step (default 12s).
|
|
20
12
|
* QUESTIONER_CHAT_WAIT_TIMEOUT_MS how long the blocking ask_user_question chat
|
|
21
13
|
* tool waits for an inline answer (default 4 min).
|
|
22
14
|
*
|
|
@@ -27,15 +19,6 @@
|
|
|
27
19
|
* IND-547: canonical home — previously questioner/questioner.env.ts.
|
|
28
20
|
* Legacy path is a thin compatibility shim pointing here.
|
|
29
21
|
*/
|
|
30
|
-
/**
|
|
31
|
-
* Question-generator budget. Sized against Railway's ~60 s edge timeout:
|
|
32
|
-
* the discovery + evaluation + negotiate phases consume ~50 s on the slow
|
|
33
|
-
* path, leaving ~10 s of headroom for the tail. 12 s is the larger end of
|
|
34
|
-
* "fits"; the question step usually completes in 4-8 s, so most legitimate
|
|
35
|
-
* calls finish well inside. Aborted calls return `null` (no questions);
|
|
36
|
-
* the rest of the discovery payload still ships.
|
|
37
|
-
*/
|
|
38
|
-
export const DISCOVERY_QUESTIONS_TIMEOUT_MS_DEFAULT = 12000;
|
|
39
22
|
export const CHAT_QUESTION_WAIT_TIMEOUT_MS_DEFAULT = 240000;
|
|
40
23
|
export const UPTAKE_AUTHORITY_THRESHOLD_DEFAULT = 70;
|
|
41
24
|
/**
|
|
@@ -56,13 +39,6 @@ function positiveIntEnv(name, fallback) {
|
|
|
56
39
|
export function isQuestionerEnabled() {
|
|
57
40
|
return process.env.QUESTIONER_ENABLED === "true";
|
|
58
41
|
}
|
|
59
|
-
/**
|
|
60
|
-
* Per-surface switch: should chat/MCP opportunity discovery produce decision
|
|
61
|
-
* questions? Hierarchical — always false when the master switch is off.
|
|
62
|
-
*/
|
|
63
|
-
export function isDiscoveryQuestionsEnabled() {
|
|
64
|
-
return isQuestionerEnabled() && process.env.QUESTIONER_DISCOVERY_ENABLED === "true";
|
|
65
|
-
}
|
|
66
42
|
/** Advisory uptake interlock. Flag-off by default and subordinate to the master switch. */
|
|
67
43
|
export function isUptakeGuardEnabled() {
|
|
68
44
|
return isQuestionerEnabled() && process.env.QUESTIONER_UPTAKE_ENABLED === "true";
|
|
@@ -77,20 +53,6 @@ export function uptakeAuthorityThreshold() {
|
|
|
77
53
|
const parsed = Number.parseInt(raw, 10);
|
|
78
54
|
return Math.min(100, Math.max(0, parsed));
|
|
79
55
|
}
|
|
80
|
-
/**
|
|
81
|
-
* Input mode for the discovery question generator. Only `transcripts` is
|
|
82
|
-
* implemented; any other value falls back to `transcripts` (startup.env.ts
|
|
83
|
-
* warns on invalid values).
|
|
84
|
-
*/
|
|
85
|
-
export function discoveryQuestionsInputMode() {
|
|
86
|
-
return process.env.QUESTIONER_DISCOVERY_INPUT_MODE?.trim() === "insights"
|
|
87
|
-
? "insights"
|
|
88
|
-
: "transcripts";
|
|
89
|
-
}
|
|
90
|
-
/** Per-call deadline for the discovery-questions LLM step. */
|
|
91
|
-
export function discoveryQuestionsTimeoutMs() {
|
|
92
|
-
return positiveIntEnv("QUESTIONER_DISCOVERY_TIMEOUT_MS", DISCOVERY_QUESTIONS_TIMEOUT_MS_DEFAULT);
|
|
93
|
-
}
|
|
94
56
|
/** Wait budget for the blocking ask_user_question chat tool. */
|
|
95
57
|
export function chatQuestionWaitTimeoutMs() {
|
|
96
58
|
return positiveIntEnv("QUESTIONER_CHAT_WAIT_TIMEOUT_MS", CHAT_QUESTION_WAIT_TIMEOUT_MS_DEFAULT);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* questions/application/question.input — QuestionerAgent input envelope.
|
|
3
3
|
*
|
|
4
|
-
* Defines per-mode context types (
|
|
4
|
+
* Defines per-mode context types (IntentContext, NegotiationContext, …),
|
|
5
5
|
* the discriminated QuestionerInput union, and the runtime validation guard
|
|
6
6
|
* `isValidQuestionerInputContract`.
|
|
7
7
|
*
|
|
@@ -17,15 +17,9 @@
|
|
|
17
17
|
* IND-547: canonical home — previously questioner/questioner.types.ts.
|
|
18
18
|
* Legacy path is a thin compatibility shim pointing here.
|
|
19
19
|
*/
|
|
20
|
-
import type { DiscoveryQuestionInput } from "../../shared/schemas/discovery-question.schema.js";
|
|
21
20
|
import type { ToolScopeType } from "../../shared/agent/tool.scope.js";
|
|
22
21
|
import type { NegotiationQuestionCandidate, QuestionMode, QuestionPoolDiscriminator } from "../domain/question.schema.js";
|
|
23
22
|
import type { NegotiationConsultationReason } from "../../capabilities/negotiation.questions.facade.js";
|
|
24
|
-
/**
|
|
25
|
-
* Discovery context — wraps the existing DiscoveryQuestionInput wholesale.
|
|
26
|
-
* The discovery preset's buildPrompt delegates to `question.discovery.prompt.ts`.
|
|
27
|
-
*/
|
|
28
|
-
export type DiscoveryContext = DiscoveryQuestionInput;
|
|
29
23
|
/** Intent context — data needed to generate questions about an intent. */
|
|
30
24
|
export interface IntentContext {
|
|
31
25
|
intentId: string;
|
|
@@ -40,14 +34,6 @@ export interface RecoveryIntentContext extends IntentContext {
|
|
|
40
34
|
/** Privacy-safe aggregate signal; raw negotiation evidence is never provided. */
|
|
41
35
|
rejectedNegotiationCount?: number;
|
|
42
36
|
}
|
|
43
|
-
/** Profile context — data needed to generate questions to fill profile gaps. */
|
|
44
|
-
export interface ProfileContext {
|
|
45
|
-
/** The user's global user_context paragraph (profile-replacing identity text). */
|
|
46
|
-
userContext?: string;
|
|
47
|
-
gaps: string[];
|
|
48
|
-
/** Existing premise texts the user has already stated (e.g. "I live in Berlin"). */
|
|
49
|
-
existingPremises?: string[];
|
|
50
|
-
}
|
|
51
37
|
/** Shared context fields for negotiation-mode questions. */
|
|
52
38
|
interface NegotiationContextBase {
|
|
53
39
|
negotiationId: string;
|
|
@@ -134,7 +120,7 @@ export interface PoolDiscoveryContext {
|
|
|
134
120
|
minedAt: string;
|
|
135
121
|
}
|
|
136
122
|
/** Discriminated union: mode selects the context shape. */
|
|
137
|
-
export type QuestionerContext =
|
|
123
|
+
export type QuestionerContext = IntentContext | RecoveryIntentContext | NegotiationContext | NegotiationInflightContext | ChatContext | PoolDiscoveryContext;
|
|
138
124
|
/**
|
|
139
125
|
* Payload shape accepted by the questionerEnqueue callback. Covers all
|
|
140
126
|
* question modes — the composition root bridges this to the concrete
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { DISCOVERY_SYSTEM_PROMPT, buildDiscoveryQuestionPrompt } from "./question.discovery.prompt.js";
|
|
2
1
|
import { QUD_UNDERSPECIFICATION_RULES } from "./question.qud.js";
|
|
3
2
|
import { consultationPromptFor } from "../../capabilities/negotiation.questions.facade.js";
|
|
4
3
|
/**
|
|
@@ -121,63 +120,6 @@ function buildRecoveryIntentPrompt(ctx) {
|
|
|
121
120
|
"Return an empty `questions` array when no safe useful axis is missing.",
|
|
122
121
|
].join("\n");
|
|
123
122
|
}
|
|
124
|
-
// ─── Profile preset ─────────────────────────────────────────────────────────
|
|
125
|
-
const PROFILE_SYSTEM_PROMPT = `You sit between a human and a discovery protocol. The user has a profile that is incomplete. Your job: surface the minimum set of structured questions that fill the identified gaps — asking about location, skills, interests, current work, or goals — so the protocol can run better discovery on their behalf.
|
|
126
|
-
|
|
127
|
-
The user may already have premises — atomic self-descriptions they have stated. These cover specific profile domains. Do not ask about domains already addressed by existing premises. Focus only on gaps not covered by any premise.
|
|
128
|
-
|
|
129
|
-
You may pick from two strategies. Choose contextually; mix only when each question is genuinely distinct.
|
|
130
|
-
- surface_missing_detail: ask for one concrete missing piece of profile data (location, current role, skills, interests, goals, availability, …).
|
|
131
|
-
- refine_intent: ask the user to clarify or sharpen an existing profile signal so candidates can be ranked more accurately.
|
|
132
|
-
|
|
133
|
-
Ask a question only when ALL of these hold:
|
|
134
|
-
1. The answer is not already visible in the profile data shown.
|
|
135
|
-
2. The answer is not already covered by an existing premise listed below the profile.
|
|
136
|
-
3. The answer would meaningfully change which opportunities surface for this user.
|
|
137
|
-
4. The question targets a different profile domain from any other question in this batch.
|
|
138
|
-
|
|
139
|
-
Standalone prompt rule. Every generated \`prompt\` must be understandable outside the conversation where it was created. Naturally include the profile signal or gap being clarified in the question text itself, using concise plain language from the current profile, existing premises, or identified gaps. Do not rely on \`title\`, UI labels, hidden metadata, or surrounding digest/chat text to explain what the question is about.
|
|
140
|
-
- Bad: "What kind of role are you looking for?"
|
|
141
|
-
- Good: "To improve matches from your founder/operator profile, what kind of role are you looking for?"
|
|
142
|
-
|
|
143
|
-
${REFERENTIAL_CLOSURE_RULES}
|
|
144
|
-
|
|
145
|
-
Cardinality. Default one question. Add a second only when a DIFFERENT strategy genuinely complements the first and unblocks a clearly distinct decision. Never ask two questions of the same strategy unless their decision domains differ.
|
|
146
|
-
|
|
147
|
-
Option construction. Each option must represent a meaningfully different outcome. Suffix the safest or most common path with " (Recommended)" and list it first. The description states the CONSEQUENCE of choosing the option, not its definition. 2–4 options. Never add an "Other" option — clients provide a free-text fallback automatically.
|
|
148
|
-
|
|
149
|
-
Title rules. ≤12 chars. Noun of the profile domain. Examples: "Location", "Role", "Skills", "Goals", "Interests", "Availability", "Stage".
|
|
150
|
-
|
|
151
|
-
Anti-patterns — never do these.
|
|
152
|
-
- Don't ask about fields already filled in the profile.
|
|
153
|
-
- Don't ask about information already captured in an existing premise.
|
|
154
|
-
- Don't ask procedural confirmations ("Should I update your profile?").
|
|
155
|
-
- Don't ask vague introspective questions ("Who are you really?").
|
|
156
|
-
- Don't re-ask for facts visible anywhere in the profile data or premises shown.
|
|
157
|
-
|
|
158
|
-
Output. Return at most 2 entries in the "questions" array. Each entry must include a "strategy" field (one of the two values above). If the profile is already complete enough for discovery, return "questions": [].`;
|
|
159
|
-
function buildProfilePrompt(ctx) {
|
|
160
|
-
const profileBlock = buildUserContextBlock(ctx.userContext);
|
|
161
|
-
const premisesBlock = ctx.existingPremises && ctx.existingPremises.length > 0
|
|
162
|
-
? ctx.existingPremises.map((p, i) => `${i + 1}. ${p}`).join("\n")
|
|
163
|
-
: "(none)";
|
|
164
|
-
const gapsBlock = ctx.gaps.length > 0 ? ctx.gaps.join(", ") : "(none identified)";
|
|
165
|
-
return [
|
|
166
|
-
"## Current profile",
|
|
167
|
-
profileBlock,
|
|
168
|
-
"",
|
|
169
|
-
"## Existing premises",
|
|
170
|
-
premisesBlock,
|
|
171
|
-
"",
|
|
172
|
-
"## Identified gaps",
|
|
173
|
-
gapsBlock,
|
|
174
|
-
"",
|
|
175
|
-
"## Your task",
|
|
176
|
-
"Generate the minimum set of questions needed to fill the identified gaps.",
|
|
177
|
-
"Apply every rule from your system prompt before outputting.",
|
|
178
|
-
"Return an empty `questions` array if the profile is already complete enough.",
|
|
179
|
-
].join("\n");
|
|
180
|
-
}
|
|
181
123
|
// ─── Negotiation preset ──────────────────────────────────────────────────────
|
|
182
124
|
const NEGOTIATION_SYSTEM_PROMPT = `You sit between a human and a discovery protocol. You generate negotiation-mode questions for one of two purposes described in the user message.
|
|
183
125
|
|
|
@@ -397,18 +339,10 @@ function withQudMetadataRules(systemPrompt) {
|
|
|
397
339
|
return `${systemPrompt}\n\n${QUD_UNDERSPECIFICATION_RULES}`;
|
|
398
340
|
}
|
|
399
341
|
const presets = {
|
|
400
|
-
discovery: {
|
|
401
|
-
systemPrompt: withQudMetadataRules(DISCOVERY_SYSTEM_PROMPT),
|
|
402
|
-
buildPrompt: (context) => buildDiscoveryQuestionPrompt(context),
|
|
403
|
-
},
|
|
404
342
|
intent: {
|
|
405
343
|
systemPrompt: withQudMetadataRules(INTENT_SYSTEM_PROMPT),
|
|
406
344
|
buildPrompt: (context) => buildIntentPrompt(context),
|
|
407
345
|
},
|
|
408
|
-
enrichment: {
|
|
409
|
-
systemPrompt: withQudMetadataRules(PROFILE_SYSTEM_PROMPT),
|
|
410
|
-
buildPrompt: (context) => buildProfilePrompt(context),
|
|
411
|
-
},
|
|
412
346
|
negotiation: {
|
|
413
347
|
systemPrompt: withQudMetadataRules(NEGOTIATION_SYSTEM_PROMPT),
|
|
414
348
|
buildPrompt: (context) => buildNegotiationPrompt(context),
|
|
@@ -24,7 +24,7 @@ import { callerMayAccessQuestionMode } from "../../shared/agent/activity-project
|
|
|
24
24
|
* from opportunity metadata that can reference out-of-scope networks and
|
|
25
25
|
* other users' content (same leak class as the getOpportunitiesForUser fix).
|
|
26
26
|
*/
|
|
27
|
-
const SELF_OWNED_MODES = ["
|
|
27
|
+
const SELF_OWNED_MODES = ["intent"];
|
|
28
28
|
function isVisibleInScopedNetwork(question, userId, networkId) {
|
|
29
29
|
return question.actors?.some((actor) => actor.userId === userId && actor.networkId === networkId) === true;
|
|
30
30
|
}
|
|
@@ -65,11 +65,11 @@ export function createQuestionerTools(defineTool, deps) {
|
|
|
65
65
|
const readPendingQuestions = defineTool({
|
|
66
66
|
name: "read_pending_questions",
|
|
67
67
|
description: "Returns pending questions generated for the authenticated user across all modes " +
|
|
68
|
-
"(
|
|
68
|
+
"(intent, negotiation, chat, pool_discovery). These are questions generated by the " +
|
|
69
69
|
"system to help surface missing signals, refine intents, or capture engagement context.\n\n" +
|
|
70
70
|
"**Returns:** List of pending questions, each with `id`, `title`, `prompt`, `options`, " +
|
|
71
71
|
"`multiSelect`, `mode`, `sourceType`, `sourceId`, `createdAt`, and optional `expiresAt`. " +
|
|
72
|
-
"Network-scoped agents receive only
|
|
72
|
+
"Network-scoped agents receive only intent questions for the scoped network plus a " +
|
|
73
73
|
"`scopeRestriction` note.\n\n" +
|
|
74
74
|
"**Use:** Call with no arguments to get all pending questions, or pass `limit` to cap the " +
|
|
75
75
|
"count. For the daily brief the script calls with a small `limit` and renders the first " +
|