@indexnetwork/protocol 21.0.0-rc.489.1 → 21.0.0-rc.490.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -0
- package/dist/negotiations/negotiation.agent.d.ts +13 -0
- package/dist/negotiations/negotiation.agent.js +53 -3
- package/dist/negotiations/negotiation.client-dm.d.ts +50 -0
- package/dist/negotiations/negotiation.client-dm.js +66 -0
- package/dist/negotiations/negotiation.graph.d.ts +110 -1
- package/dist/negotiations/negotiation.graph.js +2 -1
- package/dist/negotiations/negotiation.graph.shared.d.ts +17 -0
- package/dist/negotiations/negotiation.graph.shared.js +23 -0
- package/dist/negotiations/negotiation.graph.turn.d.ts +27 -0
- package/dist/negotiations/negotiation.graph.turn.js +64 -2
- package/dist/negotiations/negotiation.module.d.ts +2 -1
- package/dist/negotiations/negotiation.module.js +1 -1
- package/dist/negotiations/negotiation.protocol.d.ts +498 -0
- package/dist/negotiations/negotiation.question-safety.d.ts +28 -0
- package/dist/negotiations/negotiation.question-safety.js +65 -0
- package/dist/negotiations/negotiation.state.d.ts +110 -0
- package/dist/questions/question.schema.d.ts +13 -31
- package/dist/questions/question.schema.js +9 -15
- package/dist/shared/schemas/negotiation-state.schema.d.ts +182 -3
- package/dist/shared/schemas/negotiation-state.schema.js +23 -3
- package/dist/shared/schemas/structured-question.schema.d.ts +66 -0
- package/dist/shared/schemas/structured-question.schema.js +31 -0
- package/package.json +1 -1
|
@@ -36,6 +36,71 @@ export function isSafeNegotiationQuestionText(value, options) {
|
|
|
36
36
|
}
|
|
37
37
|
return true;
|
|
38
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Instruction-shaped text that must never survive into a rendered question.
|
|
41
|
+
*
|
|
42
|
+
* Applies ONLY to `isSafeAuthoredNegotiationQuestion` — deliberately not added
|
|
43
|
+
* to `isSafeNegotiationQuestionText`, which guards a live path whose verdicts
|
|
44
|
+
* must not move. The exposure is specific to the authored question: the client
|
|
45
|
+
* reads these strings verbatim on a card, and whatever they select comes BACK
|
|
46
|
+
* into the negotiator's prompt as a user answer. An option labelled "ignore
|
|
47
|
+
* previous instructions" is therefore a round-trip injection with a human
|
|
48
|
+
* clicking the button.
|
|
49
|
+
*
|
|
50
|
+
* Two families. Override phrasings ("ignore the above", "you are now a…"), and
|
|
51
|
+
* forged structure: role headers and the `--- section ---` delimiter this
|
|
52
|
+
* codebase actually uses to fence prompt sections (see
|
|
53
|
+
* `renderNegotiatorClientDmSection`), which is what a forged block would have
|
|
54
|
+
* to imitate to be read as one.
|
|
55
|
+
*/
|
|
56
|
+
const PROMPT_INJECTION_PATTERN = /\b(?:ignore|disregard|forget|override|bypass)\b[^.!?\n]{0,40}\b(?:instructions?|prompts?|rules?|directives?|guidelines?|everything\s+above|the\s+above|all\s+of\s+the\s+above)\b|\byou\s+are\s+now\s+(?:an?|the)\b|\bnew\s+instructions?\s*:|^\s*(?:#{1,6}\s*|\*{2}\s*)?(?:system|assistant|developer|human)\s*:|<\|[^|>]{0,40}\|>|\[\/?(?:INST|SYS)\]|^\s*-{3,}[^\n]*-{3,}\s*$/im;
|
|
57
|
+
/**
|
|
58
|
+
* Whole-question gate for a question the NEGOTIATOR authored.
|
|
59
|
+
*
|
|
60
|
+
* The pre-A2H `disclosureSubject` never reached the client as written — the
|
|
61
|
+
* server templated the copy around it. An authored `StructuredQuestion` is
|
|
62
|
+
* rendered verbatim, so every visible field needs the same gate the subject
|
|
63
|
+
* got, and it needs it with the identifiers in hand.
|
|
64
|
+
*
|
|
65
|
+
* That is the capability the api-side `isSafeNegotiationQuestionPayload` lacks
|
|
66
|
+
* and cannot gain: at the DB boundary it holds only generic patterns, so it
|
|
67
|
+
* cannot tell that a perfectly well-formed question is naming THIS counterparty
|
|
68
|
+
* or paraphrasing THIS seed assessment. The turn node has both, which is why
|
|
69
|
+
* this runs here and not there.
|
|
70
|
+
*
|
|
71
|
+
* Fail-closed and non-rewriting, like every guard in this file: a caller that
|
|
72
|
+
* gets `false` drops the question and keeps the enum-only path, rather than
|
|
73
|
+
* shipping a repaired one.
|
|
74
|
+
*
|
|
75
|
+
* @param options.forbiddenIdentifiers Names that must not appear as words —
|
|
76
|
+
* the counterparty's, at the call site.
|
|
77
|
+
* @param options.forbiddenSourceText Private inputs that must not be echoed —
|
|
78
|
+
* the seed assessment's reasoning, at the call site.
|
|
79
|
+
*/
|
|
80
|
+
export function isSafeAuthoredNegotiationQuestion(question, options) {
|
|
81
|
+
if (!question || typeof question !== 'object')
|
|
82
|
+
return false;
|
|
83
|
+
// Re-checked rather than trusted from the schema: this gate also runs on
|
|
84
|
+
// turns that arrive from an external agent, and a rendered card with one
|
|
85
|
+
// option (or fifteen) is a broken card regardless of how it validated.
|
|
86
|
+
const questionOptions = question.options;
|
|
87
|
+
if (!Array.isArray(questionOptions) || questionOptions.length < 2 || questionOptions.length > 4)
|
|
88
|
+
return false;
|
|
89
|
+
const fields = [
|
|
90
|
+
question.title,
|
|
91
|
+
question.prompt,
|
|
92
|
+
...questionOptions.flatMap((option) => [option?.label, option?.description]),
|
|
93
|
+
];
|
|
94
|
+
for (const field of fields) {
|
|
95
|
+
if (typeof field !== 'string')
|
|
96
|
+
return false;
|
|
97
|
+
if (!isSafeNegotiationQuestionText(field, options))
|
|
98
|
+
return false;
|
|
99
|
+
if (PROMPT_INJECTION_PATTERN.test(field))
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
39
104
|
/** Validate the only structured fields allowed to enter the inflight Questioner prompt. */
|
|
40
105
|
export function validateInflightAskUserFields(input) {
|
|
41
106
|
const disclosureSubject = input.disclosureSubject?.trim();
|
|
@@ -40,10 +40,75 @@ export declare const NegotiationTurnSchema: z.ZodObject<{
|
|
|
40
40
|
/** Present when action is `ask_user` (v2, P3.2). */
|
|
41
41
|
askUser: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
42
42
|
reason: z.ZodEnum<["unresolved_owner_constraint", "consequential_disclosure_permission", "repeated_non_convergence", "insufficient_commitment_authority"]>;
|
|
43
|
+
question: z.ZodEffects<z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
44
|
+
title: z.ZodString;
|
|
45
|
+
prompt: z.ZodString;
|
|
46
|
+
options: z.ZodArray<z.ZodObject<{
|
|
47
|
+
label: z.ZodString;
|
|
48
|
+
description: z.ZodString;
|
|
49
|
+
}, "strip", z.ZodTypeAny, {
|
|
50
|
+
label: string;
|
|
51
|
+
description: string;
|
|
52
|
+
}, {
|
|
53
|
+
label: string;
|
|
54
|
+
description: string;
|
|
55
|
+
}>, "many">;
|
|
56
|
+
multiSelect: z.ZodBoolean;
|
|
57
|
+
}, "strip", z.ZodTypeAny, {
|
|
58
|
+
prompt: string;
|
|
59
|
+
options: {
|
|
60
|
+
label: string;
|
|
61
|
+
description: string;
|
|
62
|
+
}[];
|
|
63
|
+
title: string;
|
|
64
|
+
multiSelect: boolean;
|
|
65
|
+
}, {
|
|
66
|
+
prompt: string;
|
|
67
|
+
options: {
|
|
68
|
+
label: string;
|
|
69
|
+
description: string;
|
|
70
|
+
}[];
|
|
71
|
+
title: string;
|
|
72
|
+
multiSelect: boolean;
|
|
73
|
+
}>>>, {
|
|
74
|
+
prompt: string;
|
|
75
|
+
options: {
|
|
76
|
+
label: string;
|
|
77
|
+
description: string;
|
|
78
|
+
}[];
|
|
79
|
+
title: string;
|
|
80
|
+
multiSelect: boolean;
|
|
81
|
+
} | undefined, {
|
|
82
|
+
prompt: string;
|
|
83
|
+
options: {
|
|
84
|
+
label: string;
|
|
85
|
+
description: string;
|
|
86
|
+
}[];
|
|
87
|
+
title: string;
|
|
88
|
+
multiSelect: boolean;
|
|
89
|
+
} | null | undefined>;
|
|
43
90
|
}, "strict", z.ZodTypeAny, {
|
|
44
91
|
reason: "unresolved_owner_constraint" | "consequential_disclosure_permission" | "repeated_non_convergence" | "insufficient_commitment_authority";
|
|
92
|
+
question?: {
|
|
93
|
+
prompt: string;
|
|
94
|
+
options: {
|
|
95
|
+
label: string;
|
|
96
|
+
description: string;
|
|
97
|
+
}[];
|
|
98
|
+
title: string;
|
|
99
|
+
multiSelect: boolean;
|
|
100
|
+
} | undefined;
|
|
45
101
|
}, {
|
|
46
102
|
reason: "unresolved_owner_constraint" | "consequential_disclosure_permission" | "repeated_non_convergence" | "insufficient_commitment_authority";
|
|
103
|
+
question?: {
|
|
104
|
+
prompt: string;
|
|
105
|
+
options: {
|
|
106
|
+
label: string;
|
|
107
|
+
description: string;
|
|
108
|
+
}[];
|
|
109
|
+
title: string;
|
|
110
|
+
multiSelect: boolean;
|
|
111
|
+
} | null | undefined;
|
|
47
112
|
}>>>;
|
|
48
113
|
}, "strip", z.ZodTypeAny, {
|
|
49
114
|
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline" | "ask_user";
|
|
@@ -57,6 +122,15 @@ export declare const NegotiationTurnSchema: z.ZodObject<{
|
|
|
57
122
|
message?: string | null | undefined;
|
|
58
123
|
askUser?: {
|
|
59
124
|
reason: "unresolved_owner_constraint" | "consequential_disclosure_permission" | "repeated_non_convergence" | "insufficient_commitment_authority";
|
|
125
|
+
question?: {
|
|
126
|
+
prompt: string;
|
|
127
|
+
options: {
|
|
128
|
+
label: string;
|
|
129
|
+
description: string;
|
|
130
|
+
}[];
|
|
131
|
+
title: string;
|
|
132
|
+
multiSelect: boolean;
|
|
133
|
+
} | undefined;
|
|
60
134
|
} | null | undefined;
|
|
61
135
|
}, {
|
|
62
136
|
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline" | "ask_user";
|
|
@@ -70,6 +144,15 @@ export declare const NegotiationTurnSchema: z.ZodObject<{
|
|
|
70
144
|
message?: string | null | undefined;
|
|
71
145
|
askUser?: {
|
|
72
146
|
reason: "unresolved_owner_constraint" | "consequential_disclosure_permission" | "repeated_non_convergence" | "insufficient_commitment_authority";
|
|
147
|
+
question?: {
|
|
148
|
+
prompt: string;
|
|
149
|
+
options: {
|
|
150
|
+
label: string;
|
|
151
|
+
description: string;
|
|
152
|
+
}[];
|
|
153
|
+
title: string;
|
|
154
|
+
multiSelect: boolean;
|
|
155
|
+
} | null | undefined;
|
|
73
156
|
} | null | undefined;
|
|
74
157
|
}>;
|
|
75
158
|
/** Restricted v1 turn schema for the system agent (no question action). */
|
|
@@ -414,6 +497,15 @@ export declare const NegotiationGraphState: import("@langchain/langgraph").Annot
|
|
|
414
497
|
message?: string | null | undefined;
|
|
415
498
|
askUser?: {
|
|
416
499
|
reason: "unresolved_owner_constraint" | "consequential_disclosure_permission" | "repeated_non_convergence" | "insufficient_commitment_authority";
|
|
500
|
+
question?: {
|
|
501
|
+
prompt: string;
|
|
502
|
+
options: {
|
|
503
|
+
label: string;
|
|
504
|
+
description: string;
|
|
505
|
+
}[];
|
|
506
|
+
title: string;
|
|
507
|
+
multiSelect: boolean;
|
|
508
|
+
} | undefined;
|
|
417
509
|
} | null | undefined;
|
|
418
510
|
} | null, {
|
|
419
511
|
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline" | "ask_user";
|
|
@@ -427,6 +519,15 @@ export declare const NegotiationGraphState: import("@langchain/langgraph").Annot
|
|
|
427
519
|
message?: string | null | undefined;
|
|
428
520
|
askUser?: {
|
|
429
521
|
reason: "unresolved_owner_constraint" | "consequential_disclosure_permission" | "repeated_non_convergence" | "insufficient_commitment_authority";
|
|
522
|
+
question?: {
|
|
523
|
+
prompt: string;
|
|
524
|
+
options: {
|
|
525
|
+
label: string;
|
|
526
|
+
description: string;
|
|
527
|
+
}[];
|
|
528
|
+
title: string;
|
|
529
|
+
multiSelect: boolean;
|
|
530
|
+
} | undefined;
|
|
430
531
|
} | null | undefined;
|
|
431
532
|
} | import("@langchain/langgraph").OverwriteValue<{
|
|
432
533
|
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline" | "ask_user";
|
|
@@ -440,6 +541,15 @@ export declare const NegotiationGraphState: import("@langchain/langgraph").Annot
|
|
|
440
541
|
message?: string | null | undefined;
|
|
441
542
|
askUser?: {
|
|
442
543
|
reason: "unresolved_owner_constraint" | "consequential_disclosure_permission" | "repeated_non_convergence" | "insufficient_commitment_authority";
|
|
544
|
+
question?: {
|
|
545
|
+
prompt: string;
|
|
546
|
+
options: {
|
|
547
|
+
label: string;
|
|
548
|
+
description: string;
|
|
549
|
+
}[];
|
|
550
|
+
title: string;
|
|
551
|
+
multiSelect: boolean;
|
|
552
|
+
} | undefined;
|
|
443
553
|
} | null | undefined;
|
|
444
554
|
} | null> | null, unknown>;
|
|
445
555
|
/**
|
|
@@ -7,29 +7,21 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { z } from "zod";
|
|
9
9
|
import { UnderspecificationTypeSchema, type UnderspecificationType } from "../shared/schemas/underspecification.schema.js";
|
|
10
|
+
import { QuestionOptionSchema, StructuredQuestionSchema, type QuestionOption } from "../shared/schemas/structured-question.schema.js";
|
|
10
11
|
export { UnderspecificationTypeSchema };
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}, {
|
|
20
|
-
label: string;
|
|
21
|
-
description: string;
|
|
22
|
-
}>;
|
|
12
|
+
/**
|
|
13
|
+
* The renderer-facing quartet (title/prompt/options/multiSelect) lives in
|
|
14
|
+
* `shared/schemas/structured-question.schema.ts` so the negotiator can author a
|
|
15
|
+
* question without `shared/` importing this capability. Re-exported here so
|
|
16
|
+
* `questions/question.schema.js` stays the import site every caller already uses.
|
|
17
|
+
*/
|
|
18
|
+
export { QuestionOptionSchema, StructuredQuestionSchema };
|
|
19
|
+
export type { StructuredQuestion } from "../shared/schemas/structured-question.schema.js";
|
|
23
20
|
export declare const QuestionSchema: z.ZodObject<{
|
|
24
|
-
/** ≤12 chars. Noun of the decision domain — e.g. "Stage", "Timing", "Role". */
|
|
25
21
|
title: z.ZodString;
|
|
26
|
-
/** ≤2 sentences, ≤400 chars. Ends in a question mark. */
|
|
27
22
|
prompt: z.ZodString;
|
|
28
|
-
/** 2–4 options. No explicit "Other" — clients provide that automatically. */
|
|
29
23
|
options: z.ZodArray<z.ZodObject<{
|
|
30
|
-
/** Display text. Suffix " (Recommended)" on the safest path; list it first. */
|
|
31
24
|
label: z.ZodString;
|
|
32
|
-
/** Explains the consequence of choosing this option, not just its definition. */
|
|
33
25
|
description: z.ZodString;
|
|
34
26
|
}, "strip", z.ZodTypeAny, {
|
|
35
27
|
label: string;
|
|
@@ -38,8 +30,8 @@ export declare const QuestionSchema: z.ZodObject<{
|
|
|
38
30
|
label: string;
|
|
39
31
|
description: string;
|
|
40
32
|
}>, "many">;
|
|
41
|
-
/** True when options are not mutually exclusive (priorities, bundles). */
|
|
42
33
|
multiSelect: z.ZodBoolean;
|
|
34
|
+
} & {
|
|
43
35
|
/**
|
|
44
36
|
* Optional provenance line rendered as a muted chip above the prompt
|
|
45
37
|
* (e.g. "based on 18 people matching this intent"). Aggregate counts only —
|
|
@@ -77,15 +69,10 @@ export declare const QuestionSchema: z.ZodObject<{
|
|
|
77
69
|
}>;
|
|
78
70
|
export declare const QuestionStrategySchema: z.ZodEnum<["refine_intent", "surface_missing_detail", "open_adjacent_thread", "reflective_summary", "surface_emergent_knowledge"]>;
|
|
79
71
|
export declare const QuestionWithStrategySchema: z.ZodObject<{
|
|
80
|
-
/** ≤12 chars. Noun of the decision domain — e.g. "Stage", "Timing", "Role". */
|
|
81
72
|
title: z.ZodString;
|
|
82
|
-
/** ≤2 sentences, ≤400 chars. Ends in a question mark. */
|
|
83
73
|
prompt: z.ZodString;
|
|
84
|
-
/** 2–4 options. No explicit "Other" — clients provide that automatically. */
|
|
85
74
|
options: z.ZodArray<z.ZodObject<{
|
|
86
|
-
/** Display text. Suffix " (Recommended)" on the safest path; list it first. */
|
|
87
75
|
label: z.ZodString;
|
|
88
|
-
/** Explains the consequence of choosing this option, not just its definition. */
|
|
89
76
|
description: z.ZodString;
|
|
90
77
|
}, "strip", z.ZodTypeAny, {
|
|
91
78
|
label: string;
|
|
@@ -94,8 +81,8 @@ export declare const QuestionWithStrategySchema: z.ZodObject<{
|
|
|
94
81
|
label: string;
|
|
95
82
|
description: string;
|
|
96
83
|
}>, "many">;
|
|
97
|
-
/** True when options are not mutually exclusive (priorities, bundles). */
|
|
98
84
|
multiSelect: z.ZodBoolean;
|
|
85
|
+
} & {
|
|
99
86
|
/**
|
|
100
87
|
* Optional provenance line rendered as a muted chip above the prompt
|
|
101
88
|
* (e.g. "based on 18 people matching this intent"). Aggregate counts only —
|
|
@@ -141,15 +128,10 @@ export declare const QuestionWithStrategySchema: z.ZodObject<{
|
|
|
141
128
|
}>;
|
|
142
129
|
export declare const QuestionGeneratorResponseSchema: z.ZodObject<{
|
|
143
130
|
questions: z.ZodArray<z.ZodObject<{
|
|
144
|
-
/** ≤12 chars. Noun of the decision domain — e.g. "Stage", "Timing", "Role". */
|
|
145
131
|
title: z.ZodString;
|
|
146
|
-
/** ≤2 sentences, ≤400 chars. Ends in a question mark. */
|
|
147
132
|
prompt: z.ZodString;
|
|
148
|
-
/** 2–4 options. No explicit "Other" — clients provide that automatically. */
|
|
149
133
|
options: z.ZodArray<z.ZodObject<{
|
|
150
|
-
/** Display text. Suffix " (Recommended)" on the safest path; list it first. */
|
|
151
134
|
label: z.ZodString;
|
|
152
|
-
/** Explains the consequence of choosing this option, not just its definition. */
|
|
153
135
|
description: z.ZodString;
|
|
154
136
|
}, "strip", z.ZodTypeAny, {
|
|
155
137
|
label: string;
|
|
@@ -158,8 +140,8 @@ export declare const QuestionGeneratorResponseSchema: z.ZodObject<{
|
|
|
158
140
|
label: string;
|
|
159
141
|
description: string;
|
|
160
142
|
}>, "many">;
|
|
161
|
-
/** True when options are not mutually exclusive (priorities, bundles). */
|
|
162
143
|
multiSelect: z.ZodBoolean;
|
|
144
|
+
} & {
|
|
163
145
|
/**
|
|
164
146
|
* Optional provenance line rendered as a muted chip above the prompt
|
|
165
147
|
* (e.g. "based on 18 people matching this intent"). Aggregate counts only —
|
|
@@ -230,7 +212,7 @@ export declare const QuestionGeneratorResponseSchema: z.ZodObject<{
|
|
|
230
212
|
evidence?: string | null | undefined;
|
|
231
213
|
}[];
|
|
232
214
|
}>;
|
|
233
|
-
export type QuestionOption
|
|
215
|
+
export type { QuestionOption };
|
|
234
216
|
export type Question = z.infer<typeof QuestionSchema>;
|
|
235
217
|
export type { UnderspecificationType };
|
|
236
218
|
export type QuestionStrategy = z.infer<typeof QuestionStrategySchema>;
|
|
@@ -7,22 +7,16 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { z } from "zod";
|
|
9
9
|
import { UnderspecificationTypeSchema } from "../shared/schemas/underspecification.schema.js";
|
|
10
|
+
import { QuestionOptionSchema, StructuredQuestionSchema } from "../shared/schemas/structured-question.schema.js";
|
|
10
11
|
export { UnderspecificationTypeSchema };
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
export
|
|
18
|
-
|
|
19
|
-
title: z.string().min(1).max(12),
|
|
20
|
-
/** ≤2 sentences, ≤400 chars. Ends in a question mark. */
|
|
21
|
-
prompt: z.string().min(1).max(400),
|
|
22
|
-
/** 2–4 options. No explicit "Other" — clients provide that automatically. */
|
|
23
|
-
options: z.array(QuestionOptionSchema).min(2).max(4),
|
|
24
|
-
/** True when options are not mutually exclusive (priorities, bundles). */
|
|
25
|
-
multiSelect: z.boolean(),
|
|
12
|
+
/**
|
|
13
|
+
* The renderer-facing quartet (title/prompt/options/multiSelect) lives in
|
|
14
|
+
* `shared/schemas/structured-question.schema.ts` so the negotiator can author a
|
|
15
|
+
* question without `shared/` importing this capability. Re-exported here so
|
|
16
|
+
* `questions/question.schema.js` stays the import site every caller already uses.
|
|
17
|
+
*/
|
|
18
|
+
export { QuestionOptionSchema, StructuredQuestionSchema };
|
|
19
|
+
export const QuestionSchema = StructuredQuestionSchema.extend({
|
|
26
20
|
/**
|
|
27
21
|
* Optional provenance line rendered as a muted chip above the prompt
|
|
28
22
|
* (e.g. "based on 18 people matching this intent"). Aggregate counts only —
|
|
@@ -25,16 +25,99 @@ export declare const NEGOTIATION_CONSULTATION_REASONS: readonly ["unresolved_own
|
|
|
25
25
|
export declare const NegotiationConsultationReasonSchema: z.ZodEnum<["unresolved_owner_constraint", "consequential_disclosure_permission", "repeated_non_convergence", "insufficient_commitment_authority"]>;
|
|
26
26
|
export type NegotiationConsultationReason = z.infer<typeof NegotiationConsultationReasonSchema>;
|
|
27
27
|
/**
|
|
28
|
-
* Payload for a v2 `ask_user` action.
|
|
29
|
-
*
|
|
30
|
-
*
|
|
28
|
+
* Payload for a v2 `ask_user` action.
|
|
29
|
+
*
|
|
30
|
+
* `reason` stays the closed enum it has always been: it is admission metadata
|
|
31
|
+
* for the deterministic consultation policy, not copy. `question` is the
|
|
32
|
+
* channel through which the user's own personal agent — the only thing that
|
|
33
|
+
* should be writing questions — hands over the question it authored from the
|
|
34
|
+
* negotiation it is actually having. Free-form keys beyond these two are still
|
|
35
|
+
* rejected by `.strict()`.
|
|
31
36
|
*/
|
|
32
37
|
export declare const AskUserPayloadSchema: z.ZodObject<{
|
|
33
38
|
reason: z.ZodEnum<["unresolved_owner_constraint", "consequential_disclosure_permission", "repeated_non_convergence", "insufficient_commitment_authority"]>;
|
|
39
|
+
/**
|
|
40
|
+
* The question the negotiating agent wrote, in the structured shape the UI
|
|
41
|
+
* already renders. Optional: v1 turns, external agents, and the existing
|
|
42
|
+
* enum-only path must all keep validating, so a payload of `{ reason }`
|
|
43
|
+
* alone stays byte-identical in and out.
|
|
44
|
+
*
|
|
45
|
+
* Declared `.nullable().optional()` (not bare `.optional()`) so the enclosing
|
|
46
|
+
* turn schemas survive OpenAI/OpenRouter strict structured-output conversion,
|
|
47
|
+
* which rejects optional-without-nullable fields — the same constraint
|
|
48
|
+
* documented on `QuestionSchema.evidence`. The `.transform()` normalizes an
|
|
49
|
+
* LLM-returned `null` back to `undefined`, so a null is never persisted and
|
|
50
|
+
* `null` and omitted read as absent identically downstream.
|
|
51
|
+
*/
|
|
52
|
+
question: z.ZodEffects<z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
53
|
+
title: z.ZodString;
|
|
54
|
+
prompt: z.ZodString;
|
|
55
|
+
options: z.ZodArray<z.ZodObject<{
|
|
56
|
+
label: z.ZodString;
|
|
57
|
+
description: z.ZodString;
|
|
58
|
+
}, "strip", z.ZodTypeAny, {
|
|
59
|
+
label: string;
|
|
60
|
+
description: string;
|
|
61
|
+
}, {
|
|
62
|
+
label: string;
|
|
63
|
+
description: string;
|
|
64
|
+
}>, "many">;
|
|
65
|
+
multiSelect: z.ZodBoolean;
|
|
66
|
+
}, "strip", z.ZodTypeAny, {
|
|
67
|
+
prompt: string;
|
|
68
|
+
options: {
|
|
69
|
+
label: string;
|
|
70
|
+
description: string;
|
|
71
|
+
}[];
|
|
72
|
+
title: string;
|
|
73
|
+
multiSelect: boolean;
|
|
74
|
+
}, {
|
|
75
|
+
prompt: string;
|
|
76
|
+
options: {
|
|
77
|
+
label: string;
|
|
78
|
+
description: string;
|
|
79
|
+
}[];
|
|
80
|
+
title: string;
|
|
81
|
+
multiSelect: boolean;
|
|
82
|
+
}>>>, {
|
|
83
|
+
prompt: string;
|
|
84
|
+
options: {
|
|
85
|
+
label: string;
|
|
86
|
+
description: string;
|
|
87
|
+
}[];
|
|
88
|
+
title: string;
|
|
89
|
+
multiSelect: boolean;
|
|
90
|
+
} | undefined, {
|
|
91
|
+
prompt: string;
|
|
92
|
+
options: {
|
|
93
|
+
label: string;
|
|
94
|
+
description: string;
|
|
95
|
+
}[];
|
|
96
|
+
title: string;
|
|
97
|
+
multiSelect: boolean;
|
|
98
|
+
} | null | undefined>;
|
|
34
99
|
}, "strict", z.ZodTypeAny, {
|
|
35
100
|
reason: "unresolved_owner_constraint" | "consequential_disclosure_permission" | "repeated_non_convergence" | "insufficient_commitment_authority";
|
|
101
|
+
question?: {
|
|
102
|
+
prompt: string;
|
|
103
|
+
options: {
|
|
104
|
+
label: string;
|
|
105
|
+
description: string;
|
|
106
|
+
}[];
|
|
107
|
+
title: string;
|
|
108
|
+
multiSelect: boolean;
|
|
109
|
+
} | undefined;
|
|
36
110
|
}, {
|
|
37
111
|
reason: "unresolved_owner_constraint" | "consequential_disclosure_permission" | "repeated_non_convergence" | "insufficient_commitment_authority";
|
|
112
|
+
question?: {
|
|
113
|
+
prompt: string;
|
|
114
|
+
options: {
|
|
115
|
+
label: string;
|
|
116
|
+
description: string;
|
|
117
|
+
}[];
|
|
118
|
+
title: string;
|
|
119
|
+
multiSelect: boolean;
|
|
120
|
+
} | null | undefined;
|
|
38
121
|
}>;
|
|
39
122
|
export type AskUserPayload = z.infer<typeof AskUserPayloadSchema>;
|
|
40
123
|
export declare const NegotiationTurnSchema: z.ZodObject<{
|
|
@@ -68,10 +151,88 @@ export declare const NegotiationTurnSchema: z.ZodObject<{
|
|
|
68
151
|
/** Present when action is `ask_user` (v2, P3.2). */
|
|
69
152
|
askUser: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
70
153
|
reason: z.ZodEnum<["unresolved_owner_constraint", "consequential_disclosure_permission", "repeated_non_convergence", "insufficient_commitment_authority"]>;
|
|
154
|
+
/**
|
|
155
|
+
* The question the negotiating agent wrote, in the structured shape the UI
|
|
156
|
+
* already renders. Optional: v1 turns, external agents, and the existing
|
|
157
|
+
* enum-only path must all keep validating, so a payload of `{ reason }`
|
|
158
|
+
* alone stays byte-identical in and out.
|
|
159
|
+
*
|
|
160
|
+
* Declared `.nullable().optional()` (not bare `.optional()`) so the enclosing
|
|
161
|
+
* turn schemas survive OpenAI/OpenRouter strict structured-output conversion,
|
|
162
|
+
* which rejects optional-without-nullable fields — the same constraint
|
|
163
|
+
* documented on `QuestionSchema.evidence`. The `.transform()` normalizes an
|
|
164
|
+
* LLM-returned `null` back to `undefined`, so a null is never persisted and
|
|
165
|
+
* `null` and omitted read as absent identically downstream.
|
|
166
|
+
*/
|
|
167
|
+
question: z.ZodEffects<z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
168
|
+
title: z.ZodString;
|
|
169
|
+
prompt: z.ZodString;
|
|
170
|
+
options: z.ZodArray<z.ZodObject<{
|
|
171
|
+
label: z.ZodString;
|
|
172
|
+
description: z.ZodString;
|
|
173
|
+
}, "strip", z.ZodTypeAny, {
|
|
174
|
+
label: string;
|
|
175
|
+
description: string;
|
|
176
|
+
}, {
|
|
177
|
+
label: string;
|
|
178
|
+
description: string;
|
|
179
|
+
}>, "many">;
|
|
180
|
+
multiSelect: z.ZodBoolean;
|
|
181
|
+
}, "strip", z.ZodTypeAny, {
|
|
182
|
+
prompt: string;
|
|
183
|
+
options: {
|
|
184
|
+
label: string;
|
|
185
|
+
description: string;
|
|
186
|
+
}[];
|
|
187
|
+
title: string;
|
|
188
|
+
multiSelect: boolean;
|
|
189
|
+
}, {
|
|
190
|
+
prompt: string;
|
|
191
|
+
options: {
|
|
192
|
+
label: string;
|
|
193
|
+
description: string;
|
|
194
|
+
}[];
|
|
195
|
+
title: string;
|
|
196
|
+
multiSelect: boolean;
|
|
197
|
+
}>>>, {
|
|
198
|
+
prompt: string;
|
|
199
|
+
options: {
|
|
200
|
+
label: string;
|
|
201
|
+
description: string;
|
|
202
|
+
}[];
|
|
203
|
+
title: string;
|
|
204
|
+
multiSelect: boolean;
|
|
205
|
+
} | undefined, {
|
|
206
|
+
prompt: string;
|
|
207
|
+
options: {
|
|
208
|
+
label: string;
|
|
209
|
+
description: string;
|
|
210
|
+
}[];
|
|
211
|
+
title: string;
|
|
212
|
+
multiSelect: boolean;
|
|
213
|
+
} | null | undefined>;
|
|
71
214
|
}, "strict", z.ZodTypeAny, {
|
|
72
215
|
reason: "unresolved_owner_constraint" | "consequential_disclosure_permission" | "repeated_non_convergence" | "insufficient_commitment_authority";
|
|
216
|
+
question?: {
|
|
217
|
+
prompt: string;
|
|
218
|
+
options: {
|
|
219
|
+
label: string;
|
|
220
|
+
description: string;
|
|
221
|
+
}[];
|
|
222
|
+
title: string;
|
|
223
|
+
multiSelect: boolean;
|
|
224
|
+
} | undefined;
|
|
73
225
|
}, {
|
|
74
226
|
reason: "unresolved_owner_constraint" | "consequential_disclosure_permission" | "repeated_non_convergence" | "insufficient_commitment_authority";
|
|
227
|
+
question?: {
|
|
228
|
+
prompt: string;
|
|
229
|
+
options: {
|
|
230
|
+
label: string;
|
|
231
|
+
description: string;
|
|
232
|
+
}[];
|
|
233
|
+
title: string;
|
|
234
|
+
multiSelect: boolean;
|
|
235
|
+
} | null | undefined;
|
|
75
236
|
}>>>;
|
|
76
237
|
}, "strip", z.ZodTypeAny, {
|
|
77
238
|
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline" | "ask_user";
|
|
@@ -85,6 +246,15 @@ export declare const NegotiationTurnSchema: z.ZodObject<{
|
|
|
85
246
|
message?: string | null | undefined;
|
|
86
247
|
askUser?: {
|
|
87
248
|
reason: "unresolved_owner_constraint" | "consequential_disclosure_permission" | "repeated_non_convergence" | "insufficient_commitment_authority";
|
|
249
|
+
question?: {
|
|
250
|
+
prompt: string;
|
|
251
|
+
options: {
|
|
252
|
+
label: string;
|
|
253
|
+
description: string;
|
|
254
|
+
}[];
|
|
255
|
+
title: string;
|
|
256
|
+
multiSelect: boolean;
|
|
257
|
+
} | undefined;
|
|
88
258
|
} | null | undefined;
|
|
89
259
|
}, {
|
|
90
260
|
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline" | "ask_user";
|
|
@@ -98,6 +268,15 @@ export declare const NegotiationTurnSchema: z.ZodObject<{
|
|
|
98
268
|
message?: string | null | undefined;
|
|
99
269
|
askUser?: {
|
|
100
270
|
reason: "unresolved_owner_constraint" | "consequential_disclosure_permission" | "repeated_non_convergence" | "insufficient_commitment_authority";
|
|
271
|
+
question?: {
|
|
272
|
+
prompt: string;
|
|
273
|
+
options: {
|
|
274
|
+
label: string;
|
|
275
|
+
description: string;
|
|
276
|
+
}[];
|
|
277
|
+
title: string;
|
|
278
|
+
multiSelect: boolean;
|
|
279
|
+
} | null | undefined;
|
|
101
280
|
} | null | undefined;
|
|
102
281
|
}>;
|
|
103
282
|
export type NegotiationTurn = z.infer<typeof NegotiationTurnSchema>;
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* LangGraph Annotation.Root stays in the domain file.
|
|
5
5
|
*/
|
|
6
6
|
import { z } from "zod";
|
|
7
|
+
import { StructuredQuestionSchema } from "./structured-question.schema.js";
|
|
7
8
|
// ─── Zod schemas (available for runtime validation) ───────────────────────────
|
|
8
9
|
/**
|
|
9
10
|
* Union of every negotiation turn action across protocol versions.
|
|
@@ -29,12 +30,31 @@ export const NEGOTIATION_CONSULTATION_REASONS = [
|
|
|
29
30
|
];
|
|
30
31
|
export const NegotiationConsultationReasonSchema = z.enum(NEGOTIATION_CONSULTATION_REASONS);
|
|
31
32
|
/**
|
|
32
|
-
* Payload for a v2 `ask_user` action.
|
|
33
|
-
*
|
|
34
|
-
*
|
|
33
|
+
* Payload for a v2 `ask_user` action.
|
|
34
|
+
*
|
|
35
|
+
* `reason` stays the closed enum it has always been: it is admission metadata
|
|
36
|
+
* for the deterministic consultation policy, not copy. `question` is the
|
|
37
|
+
* channel through which the user's own personal agent — the only thing that
|
|
38
|
+
* should be writing questions — hands over the question it authored from the
|
|
39
|
+
* negotiation it is actually having. Free-form keys beyond these two are still
|
|
40
|
+
* rejected by `.strict()`.
|
|
35
41
|
*/
|
|
36
42
|
export const AskUserPayloadSchema = z.object({
|
|
37
43
|
reason: NegotiationConsultationReasonSchema,
|
|
44
|
+
/**
|
|
45
|
+
* The question the negotiating agent wrote, in the structured shape the UI
|
|
46
|
+
* already renders. Optional: v1 turns, external agents, and the existing
|
|
47
|
+
* enum-only path must all keep validating, so a payload of `{ reason }`
|
|
48
|
+
* alone stays byte-identical in and out.
|
|
49
|
+
*
|
|
50
|
+
* Declared `.nullable().optional()` (not bare `.optional()`) so the enclosing
|
|
51
|
+
* turn schemas survive OpenAI/OpenRouter strict structured-output conversion,
|
|
52
|
+
* which rejects optional-without-nullable fields — the same constraint
|
|
53
|
+
* documented on `QuestionSchema.evidence`. The `.transform()` normalizes an
|
|
54
|
+
* LLM-returned `null` back to `undefined`, so a null is never persisted and
|
|
55
|
+
* `null` and omitted read as absent identically downstream.
|
|
56
|
+
*/
|
|
57
|
+
question: StructuredQuestionSchema.nullable().optional().transform((value) => value ?? undefined),
|
|
38
58
|
}).strict();
|
|
39
59
|
export const NegotiationTurnSchema = z.object({
|
|
40
60
|
action: z.enum(NEGOTIATION_ACTIONS),
|