@indexnetwork/protocol 8.6.1-rc.429.1 → 8.7.0-rc.430.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.
|
@@ -15,5 +15,5 @@ export type { IntentIndexerOutput } from "../signals/application/intent.indexer.
|
|
|
15
15
|
export { createIntentTools } from "../signals/application/intent.tools.js";
|
|
16
16
|
export type { IntentToolDeps } from "./signals.tools.port.js";
|
|
17
17
|
export { SignalIntakePackGenerator, normalizeIntakePack, type IntakePack, type IntakePackInput, type IntakePackQuestion, type IntakePackQuestionOption, } from "../signals/application/intake.pack.generator.js";
|
|
18
|
-
export { SignalIntakeOrchestrator, answerLabel, FALLBACK_WHO_QUESTION, FALLBACK_BRING_QUESTION, type IntakeAnswer, type SynthesisInput, type SynthesisResult, } from "../signals/application/intake.orchestrator.js";
|
|
18
|
+
export { SignalIntakeOrchestrator, answerLabel, FALLBACK_WHO_QUESTION, FALLBACK_BRING_QUESTION, type IntakeAnswer, type IntakeRound, type FollowUpPlan, type FollowUpPlanInput, type SynthesisInput, type SynthesisResult, } from "../signals/application/intake.orchestrator.js";
|
|
19
19
|
export { normalizeIntentDescription } from "../signals/domain/intent.proposal.js";
|
package/dist/index.d.ts
CHANGED
|
@@ -69,7 +69,7 @@ export type { IntentIndexerOutput } from "./capabilities/signals.facade.js";
|
|
|
69
69
|
export { SignalIntakePackGenerator, normalizeIntakePack } from "./capabilities/signals.facade.js";
|
|
70
70
|
export type { IntakePack, IntakePackInput, IntakePackQuestion, IntakePackQuestionOption, } from "./capabilities/signals.facade.js";
|
|
71
71
|
export { SignalIntakeOrchestrator, answerLabel, FALLBACK_WHO_QUESTION, FALLBACK_BRING_QUESTION, } from "./capabilities/signals.facade.js";
|
|
72
|
-
export type { IntakeAnswer, SynthesisInput, SynthesisResult, } from "./capabilities/signals.facade.js";
|
|
72
|
+
export type { IntakeAnswer, IntakeRound, FollowUpPlan, FollowUpPlanInput, SynthesisInput, SynthesisResult, } from "./capabilities/signals.facade.js";
|
|
73
73
|
export { normalizeIntentDescription } from "./capabilities/signals.facade.js";
|
|
74
74
|
export { LensInferrer } from "./capabilities/participant-context.facade.js";
|
|
75
75
|
export { NegotiationInsightsGenerator } from "./capabilities/negotiation.facade.js";
|
|
@@ -18,4 +18,4 @@ export { IntentReconciler, type IntentReconcilerOutput, type NormalizedIntentAct
|
|
|
18
18
|
export { IntentIndexer, IntentIndexerOutputSchema, type IntentIndexerOutput } from "./intent.indexer.js";
|
|
19
19
|
export { createIntentTools, describeIntentUpdateFailure } from "./intent.tools.js";
|
|
20
20
|
export { SignalIntakePackGenerator, normalizeIntakePack, type IntakePack, type IntakePackInput, type IntakePackQuestion, type IntakePackQuestionOption, } from "./intake.pack.generator.js";
|
|
21
|
-
export { SignalIntakeOrchestrator, answerLabel, FALLBACK_WHO_QUESTION, FALLBACK_BRING_QUESTION, type IntakeAnswer, type SynthesisInput, type SynthesisResult, } from "./intake.orchestrator.js";
|
|
21
|
+
export { SignalIntakeOrchestrator, answerLabel, FALLBACK_WHO_QUESTION, FALLBACK_BRING_QUESTION, type IntakeAnswer, type IntakeRound, type FollowUpPlan, type FollowUpPlanInput, type SynthesisInput, type SynthesisResult, } from "./intake.orchestrator.js";
|
|
@@ -8,18 +8,23 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import type { BaseLanguageModelInput } from "@langchain/core/language_models/base";
|
|
10
10
|
import type { Runnable } from "@langchain/core/runnables";
|
|
11
|
+
import { z } from "zod";
|
|
11
12
|
import { type IntakePackQuestion } from "./intake.pack.generator.js";
|
|
12
13
|
/** One answered intake round. */
|
|
13
14
|
export interface IntakeAnswer {
|
|
14
15
|
selectedOptions: string[];
|
|
15
16
|
freeText?: string;
|
|
16
17
|
}
|
|
18
|
+
/** One answered intake round, in order (round 1 first). */
|
|
19
|
+
export interface IntakeRound {
|
|
20
|
+
prompt: string;
|
|
21
|
+
answer: IntakeAnswer;
|
|
22
|
+
}
|
|
17
23
|
/** Everything synthesis needs to write the signal. */
|
|
18
24
|
export interface SynthesisInput {
|
|
19
25
|
brief: string;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
/** Free-text place/community constraint from round 3. */
|
|
26
|
+
rounds: IntakeRound[];
|
|
27
|
+
/** Free-text place/community constraint from the where round. */
|
|
23
28
|
whereText?: string;
|
|
24
29
|
/**
|
|
25
30
|
* Free-text correction the user typed against a draft they already saw.
|
|
@@ -28,12 +33,83 @@ export interface SynthesisInput {
|
|
|
28
33
|
*/
|
|
29
34
|
feedback?: string;
|
|
30
35
|
}
|
|
36
|
+
/** Planning input for one follow-up generation call. */
|
|
37
|
+
export interface FollowUpPlanInput {
|
|
38
|
+
brief: string;
|
|
39
|
+
/** Answered rounds in order (round 1 first). */
|
|
40
|
+
rounds: IntakeRound[];
|
|
41
|
+
/** Hard cap on questions returned by THIS call. */
|
|
42
|
+
maxFollowUps: number;
|
|
43
|
+
/** Locked interview plan on continuation calls; echoed unchanged. */
|
|
44
|
+
plannedFollowUpCount?: number;
|
|
45
|
+
}
|
|
46
|
+
/** The model's follow-up batch plus its total follow-up plan. */
|
|
47
|
+
export interface FollowUpPlan {
|
|
48
|
+
questions: IntakePackQuestion[];
|
|
49
|
+
plannedFollowUpCount: number;
|
|
50
|
+
}
|
|
31
51
|
/** Synthesized signal text plus its summary fields. */
|
|
32
52
|
export interface SynthesisResult {
|
|
33
53
|
description: string;
|
|
34
54
|
lookingFor: string;
|
|
35
55
|
youBring: string;
|
|
36
56
|
}
|
|
57
|
+
declare const followUpPlanSchema: z.ZodObject<{
|
|
58
|
+
questions: z.ZodArray<z.ZodObject<{
|
|
59
|
+
title: z.ZodString;
|
|
60
|
+
prompt: z.ZodString;
|
|
61
|
+
options: z.ZodArray<z.ZodObject<{
|
|
62
|
+
label: z.ZodString;
|
|
63
|
+
description: z.ZodString;
|
|
64
|
+
}, "strip", z.ZodTypeAny, {
|
|
65
|
+
label: string;
|
|
66
|
+
description: string;
|
|
67
|
+
}, {
|
|
68
|
+
label: string;
|
|
69
|
+
description: string;
|
|
70
|
+
}>, "many">;
|
|
71
|
+
multiSelect: z.ZodBoolean;
|
|
72
|
+
}, "strip", z.ZodTypeAny, {
|
|
73
|
+
prompt: string;
|
|
74
|
+
options: {
|
|
75
|
+
label: string;
|
|
76
|
+
description: string;
|
|
77
|
+
}[];
|
|
78
|
+
title: string;
|
|
79
|
+
multiSelect: boolean;
|
|
80
|
+
}, {
|
|
81
|
+
prompt: string;
|
|
82
|
+
options: {
|
|
83
|
+
label: string;
|
|
84
|
+
description: string;
|
|
85
|
+
}[];
|
|
86
|
+
title: string;
|
|
87
|
+
multiSelect: boolean;
|
|
88
|
+
}>, "many">;
|
|
89
|
+
plannedFollowUpCount: z.ZodNumber;
|
|
90
|
+
}, "strip", z.ZodTypeAny, {
|
|
91
|
+
questions: {
|
|
92
|
+
prompt: string;
|
|
93
|
+
options: {
|
|
94
|
+
label: string;
|
|
95
|
+
description: string;
|
|
96
|
+
}[];
|
|
97
|
+
title: string;
|
|
98
|
+
multiSelect: boolean;
|
|
99
|
+
}[];
|
|
100
|
+
plannedFollowUpCount: number;
|
|
101
|
+
}, {
|
|
102
|
+
questions: {
|
|
103
|
+
prompt: string;
|
|
104
|
+
options: {
|
|
105
|
+
label: string;
|
|
106
|
+
description: string;
|
|
107
|
+
}[];
|
|
108
|
+
title: string;
|
|
109
|
+
multiSelect: boolean;
|
|
110
|
+
}[];
|
|
111
|
+
plannedFollowUpCount: number;
|
|
112
|
+
}>;
|
|
37
113
|
/** Static round-1 question used only when pack generation fails outright. */
|
|
38
114
|
export declare const FALLBACK_WHO_QUESTION: IntakePackQuestion;
|
|
39
115
|
/** Static round-2 question used when live generation fails. */
|
|
@@ -45,34 +121,33 @@ export declare const FALLBACK_BRING_QUESTION: IntakePackQuestion;
|
|
|
45
121
|
* @returns Comma-joined non-empty parts
|
|
46
122
|
*/
|
|
47
123
|
export declare function answerLabel(answer: IntakeAnswer): string;
|
|
48
|
-
/** Runs the two live stages of the fast intake funnel. */
|
|
124
|
+
/** Runs the two live stages of the fast intake funnel: follow-up planning and synthesis. */
|
|
49
125
|
export declare class SignalIntakeOrchestrator {
|
|
50
|
-
private readonly
|
|
126
|
+
private readonly plannerModel;
|
|
51
127
|
private readonly synthesisModel;
|
|
52
128
|
/**
|
|
53
129
|
* @param models - Optional injected structured models. Tests pass stubs.
|
|
54
130
|
*/
|
|
55
131
|
constructor(models?: {
|
|
56
|
-
|
|
132
|
+
planner?: Runnable<BaseLanguageModelInput, z.infer<typeof followUpPlanSchema>>;
|
|
57
133
|
synthesis?: Runnable<BaseLanguageModelInput, SynthesisResult>;
|
|
58
134
|
});
|
|
59
135
|
/**
|
|
60
|
-
*
|
|
136
|
+
* Plan and write follow-up questions from the brief and answered rounds.
|
|
61
137
|
*
|
|
62
|
-
* @param input - Brief
|
|
63
|
-
* @returns
|
|
138
|
+
* @param input - Brief, answered rounds, per-call cap, and any locked plan
|
|
139
|
+
* @returns Up to `maxFollowUps` renderable questions plus the total plan;
|
|
140
|
+
* the static fallback question with count 1 when generation fails
|
|
64
141
|
*/
|
|
65
|
-
|
|
66
|
-
brief: string;
|
|
67
|
-
whoAnswer: IntakeAnswer;
|
|
68
|
-
}): Promise<IntakePackQuestion>;
|
|
142
|
+
generateFollowUps(input: FollowUpPlanInput): Promise<FollowUpPlan>;
|
|
69
143
|
/**
|
|
70
|
-
* Write the signal from
|
|
144
|
+
* Write the signal from every answered round, any where-constraint, and any
|
|
71
145
|
* revision feedback.
|
|
72
146
|
*
|
|
73
|
-
* @param input - Brief,
|
|
147
|
+
* @param input - Brief, ordered rounds, optional where constraint, optional feedback
|
|
74
148
|
* @returns Description plus card summary fields
|
|
75
149
|
* @throws Propagates model failure so the caller can mark the run failed
|
|
76
150
|
*/
|
|
77
151
|
synthesize(input: SynthesisInput): Promise<SynthesisResult>;
|
|
78
152
|
}
|
|
153
|
+
export {};
|
|
@@ -16,6 +16,10 @@ const questionSchema = z.object({
|
|
|
16
16
|
options: z.array(z.object({ label: z.string().min(1), description: z.string() })),
|
|
17
17
|
multiSelect: z.boolean(),
|
|
18
18
|
});
|
|
19
|
+
const followUpPlanSchema = z.object({
|
|
20
|
+
questions: z.array(questionSchema),
|
|
21
|
+
plannedFollowUpCount: z.number().int().min(0),
|
|
22
|
+
});
|
|
19
23
|
const synthesisSchema = z.object({
|
|
20
24
|
description: z.string().min(1),
|
|
21
25
|
lookingFor: z.string().min(1),
|
|
@@ -45,13 +49,18 @@ export const FALLBACK_BRING_QUESTION = {
|
|
|
45
49
|
],
|
|
46
50
|
multiSelect: false,
|
|
47
51
|
};
|
|
48
|
-
const
|
|
52
|
+
const PLAN_SYSTEM_PROMPT = `You plan and write follow-up intake questions for a networking product.
|
|
49
53
|
|
|
50
|
-
Given a brief about the person and
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
Given a brief about the person and the intake rounds they already answered, decide
|
|
55
|
+
how many further questions (up to the stated maximum) would make their signal
|
|
56
|
+
specific enough to match on, and write them. Each question is one concise prompt
|
|
57
|
+
with 3-4 concrete options grounded in the brief and the previous answers; each
|
|
58
|
+
option has a short label and a one-line description. Set multiSelect true only
|
|
59
|
+
when several options can genuinely apply together. Never re-ask a dimension that
|
|
60
|
+
is already answered; skip a dimension the brief already covers. Never expose raw
|
|
61
|
+
JSON, IDs, or internal vocabulary. plannedFollowUpCount is the TOTAL number of
|
|
62
|
+
follow-up questions the interview should contain, including any returned now;
|
|
63
|
+
when the input already fixes it, echo that value unchanged.`;
|
|
55
64
|
const SYNTHESIS_SYSTEM_PROMPT = `You write one clear signal for a networking product.
|
|
56
65
|
|
|
57
66
|
Combine the brief and the person's answers into a specific description of who they
|
|
@@ -70,44 +79,74 @@ community constraint. Never invent facts beyond the brief and the answers.`;
|
|
|
70
79
|
export function answerLabel(answer) {
|
|
71
80
|
return [...answer.selectedOptions, answer.freeText?.trim() ?? ""].filter(Boolean).join(", ");
|
|
72
81
|
}
|
|
73
|
-
/** Runs the two live stages of the fast intake funnel. */
|
|
82
|
+
/** Runs the two live stages of the fast intake funnel: follow-up planning and synthesis. */
|
|
74
83
|
export class SignalIntakeOrchestrator {
|
|
75
84
|
/**
|
|
76
85
|
* @param models - Optional injected structured models. Tests pass stubs.
|
|
77
86
|
*/
|
|
78
87
|
constructor(models) {
|
|
79
|
-
this.
|
|
80
|
-
?? createStructuredModel("signalIntakePack",
|
|
88
|
+
this.plannerModel = models?.planner
|
|
89
|
+
?? createStructuredModel("signalIntakePack", followUpPlanSchema);
|
|
81
90
|
this.synthesisModel = models?.synthesis
|
|
82
91
|
?? createStructuredModel("signalIntakePack", synthesisSchema);
|
|
83
92
|
}
|
|
84
93
|
/**
|
|
85
|
-
*
|
|
94
|
+
* Plan and write follow-up questions from the brief and answered rounds.
|
|
86
95
|
*
|
|
87
|
-
* @param input - Brief
|
|
88
|
-
* @returns
|
|
96
|
+
* @param input - Brief, answered rounds, per-call cap, and any locked plan
|
|
97
|
+
* @returns Up to `maxFollowUps` renderable questions plus the total plan;
|
|
98
|
+
* the static fallback question with count 1 when generation fails
|
|
89
99
|
*/
|
|
90
|
-
async
|
|
100
|
+
async generateFollowUps(input) {
|
|
101
|
+
const roundsText = input.rounds
|
|
102
|
+
.map((round, index) => `Round ${index + 1} — Q: ${round.prompt}\nA: ${answerLabel(round.answer)}`)
|
|
103
|
+
.join("\n\n");
|
|
104
|
+
const lockedLine = input.plannedFollowUpCount !== undefined
|
|
105
|
+
? `\n\nThe interview plan is fixed at ${input.plannedFollowUpCount} follow-up question(s) in total; ${input.rounds.length - 1} already asked. Echo that count unchanged.`
|
|
106
|
+
: "";
|
|
91
107
|
try {
|
|
92
|
-
const raw = await this.
|
|
93
|
-
new SystemMessage(
|
|
94
|
-
new HumanMessage(`Brief:\n${input.brief}\n\
|
|
108
|
+
const raw = await this.plannerModel.invoke([
|
|
109
|
+
new SystemMessage(PLAN_SYSTEM_PROMPT),
|
|
110
|
+
new HumanMessage(`Brief:\n${input.brief}\n\n${roundsText}\n\nWrite up to ${input.maxFollowUps} follow-up question(s).${lockedLine}`),
|
|
95
111
|
]);
|
|
96
|
-
|
|
112
|
+
const questions = raw.questions
|
|
113
|
+
.slice(0, input.maxFollowUps)
|
|
114
|
+
.map((q) => normalizeIntakePack({ brief: input.brief, question: q }).question);
|
|
115
|
+
// Backstop: while budget remains, a successful empty plan must not
|
|
116
|
+
// silently shrink the interview; serve the static fallback instead.
|
|
117
|
+
if (questions.length === 0 && input.maxFollowUps > 0) {
|
|
118
|
+
return {
|
|
119
|
+
questions: [FALLBACK_BRING_QUESTION],
|
|
120
|
+
plannedFollowUpCount: input.plannedFollowUpCount ?? 1,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
questions,
|
|
125
|
+
plannedFollowUpCount: input.plannedFollowUpCount
|
|
126
|
+
?? Math.max(raw.plannedFollowUpCount, questions.length),
|
|
127
|
+
};
|
|
97
128
|
}
|
|
98
129
|
catch {
|
|
99
|
-
|
|
130
|
+
if (input.maxFollowUps <= 0)
|
|
131
|
+
return { questions: [], plannedFollowUpCount: 0 };
|
|
132
|
+
return {
|
|
133
|
+
questions: [FALLBACK_BRING_QUESTION],
|
|
134
|
+
plannedFollowUpCount: input.plannedFollowUpCount ?? 1,
|
|
135
|
+
};
|
|
100
136
|
}
|
|
101
137
|
}
|
|
102
138
|
/**
|
|
103
|
-
* Write the signal from
|
|
139
|
+
* Write the signal from every answered round, any where-constraint, and any
|
|
104
140
|
* revision feedback.
|
|
105
141
|
*
|
|
106
|
-
* @param input - Brief,
|
|
142
|
+
* @param input - Brief, ordered rounds, optional where constraint, optional feedback
|
|
107
143
|
* @returns Description plus card summary fields
|
|
108
144
|
* @throws Propagates model failure so the caller can mark the run failed
|
|
109
145
|
*/
|
|
110
146
|
async synthesize(input) {
|
|
147
|
+
const roundsText = input.rounds
|
|
148
|
+
.map((round) => `Q: ${round.prompt}\nA: ${answerLabel(round.answer)}`)
|
|
149
|
+
.join("\n\n");
|
|
111
150
|
const whereLine = input.whereText?.trim()
|
|
112
151
|
? `\n\nWhere constraint: ${input.whereText.trim()}`
|
|
113
152
|
: "";
|
|
@@ -116,7 +155,7 @@ export class SignalIntakeOrchestrator {
|
|
|
116
155
|
: "";
|
|
117
156
|
const result = await this.synthesisModel.invoke([
|
|
118
157
|
new SystemMessage(SYNTHESIS_SYSTEM_PROMPT),
|
|
119
|
-
new HumanMessage(`Brief:\n${input.brief}\n\
|
|
158
|
+
new HumanMessage(`Brief:\n${input.brief}\n\n${roundsText}${whereLine}${feedbackLine}\n\nWrite the signal.`),
|
|
120
159
|
]);
|
|
121
160
|
return {
|
|
122
161
|
description: result.description.trim(),
|