@indexnetwork/protocol 4.5.0-rc.331.1 → 4.5.0-rc.333.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/chat/chat-streaming.types.d.ts +3 -1
- package/dist/chat/chat-streaming.types.d.ts.map +1 -1
- package/dist/chat/chat-streaming.types.js.map +1 -1
- package/dist/chat/chat.agent.d.ts +1 -1
- package/dist/chat/chat.agent.d.ts.map +1 -1
- package/dist/chat/chat.agent.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/negotiation/negotiation.agent.d.ts +21 -0
- package/dist/negotiation/negotiation.agent.d.ts.map +1 -1
- package/dist/negotiation/negotiation.agent.js +79 -11
- package/dist/negotiation/negotiation.agent.js.map +1 -1
- package/dist/negotiation/negotiation.graph.d.ts +55 -24
- package/dist/negotiation/negotiation.graph.d.ts.map +1 -1
- package/dist/negotiation/negotiation.graph.js +106 -27
- package/dist/negotiation/negotiation.graph.js.map +1 -1
- package/dist/negotiation/negotiation.protocol.d.ts +287 -0
- package/dist/negotiation/negotiation.protocol.d.ts.map +1 -0
- package/dist/negotiation/negotiation.protocol.js +152 -0
- package/dist/negotiation/negotiation.protocol.js.map +1 -0
- package/dist/negotiation/negotiation.state.d.ts +34 -9
- package/dist/negotiation/negotiation.state.d.ts.map +1 -1
- package/dist/negotiation/negotiation.state.js +28 -4
- package/dist/negotiation/negotiation.state.js.map +1 -1
- package/dist/negotiation/negotiation.tools.d.ts.map +1 -1
- package/dist/negotiation/negotiation.tools.js +86 -31
- package/dist/negotiation/negotiation.tools.js.map +1 -1
- package/dist/opportunity/opportunity.graph.d.ts.map +1 -1
- package/dist/opportunity/opportunity.graph.js +9 -0
- package/dist/opportunity/opportunity.graph.js.map +1 -1
- package/dist/opportunity/question.prompt.d.ts +1 -1
- package/dist/opportunity/question.prompt.d.ts.map +1 -1
- package/dist/opportunity/question.prompt.js.map +1 -1
- package/dist/shared/interfaces/agent-dispatcher.interface.d.ts +6 -0
- package/dist/shared/interfaces/agent-dispatcher.interface.d.ts.map +1 -1
- package/dist/shared/interfaces/agent-dispatcher.interface.js.map +1 -1
- package/dist/shared/interfaces/database.interface.d.ts +17 -0
- package/dist/shared/interfaces/database.interface.d.ts.map +1 -1
- package/dist/shared/interfaces/database.interface.js.map +1 -1
- package/dist/shared/schemas/discovery-question.schema.d.ts +8 -8
- package/dist/shared/schemas/discovery-question.schema.js +1 -1
- package/dist/shared/schemas/discovery-question.schema.js.map +1 -1
- package/dist/shared/schemas/negotiation-state.schema.d.ts +19 -3
- package/dist/shared/schemas/negotiation-state.schema.d.ts.map +1 -1
- package/dist/shared/schemas/negotiation-state.schema.js +15 -1
- package/dist/shared/schemas/negotiation-state.schema.js.map +1 -1
- package/package.json +1 -1
|
@@ -3,6 +3,7 @@ import type { NegotiationGraphDatabase } from "../shared/interfaces/database.int
|
|
|
3
3
|
import type { NegotiationTimeoutQueue } from "../shared/interfaces/negotiation-events.interface.js";
|
|
4
4
|
import type { AgentDispatcher } from "../shared/interfaces/agent-dispatcher.interface.js";
|
|
5
5
|
import { type NegotiationTurn, type NegotiationOutcome, type UserNegotiationContext, type SeedAssessment, type NegotiationGraphLike } from "./negotiation.state.js";
|
|
6
|
+
import type { NegotiationProtocolVersion } from "../shared/schemas/negotiation-state.schema.js";
|
|
6
7
|
import type { QuestionerEnqueueFn } from "../questioner/questioner.types.js";
|
|
7
8
|
/**
|
|
8
9
|
* Factory for the bilateral negotiation LangGraph state machine.
|
|
@@ -22,7 +23,9 @@ export declare class NegotiationGraphFactory {
|
|
|
22
23
|
prompt: string;
|
|
23
24
|
};
|
|
24
25
|
seedAssessment: SeedAssessment;
|
|
26
|
+
initiatorUserId: string | undefined;
|
|
25
27
|
discoveryQuery: string | undefined;
|
|
28
|
+
protocolVersion: NegotiationProtocolVersion;
|
|
26
29
|
isContinuation: boolean;
|
|
27
30
|
opportunityId: string;
|
|
28
31
|
conversationId: string;
|
|
@@ -33,7 +36,7 @@ export declare class NegotiationGraphFactory {
|
|
|
33
36
|
timeoutMs: number;
|
|
34
37
|
currentSpeaker: "source" | "candidate";
|
|
35
38
|
lastTurn: {
|
|
36
|
-
action: "propose" | "accept" | "reject" | "counter" | "question";
|
|
39
|
+
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline";
|
|
37
40
|
assessment: {
|
|
38
41
|
reasoning: string;
|
|
39
42
|
suggestedRoles: {
|
|
@@ -68,7 +71,9 @@ export declare class NegotiationGraphFactory {
|
|
|
68
71
|
prompt: string;
|
|
69
72
|
}> | undefined;
|
|
70
73
|
seedAssessment?: SeedAssessment | import("@langchain/langgraph").OverwriteValue<SeedAssessment> | undefined;
|
|
74
|
+
initiatorUserId?: string | import("@langchain/langgraph").OverwriteValue<string | undefined> | undefined;
|
|
71
75
|
discoveryQuery?: string | import("@langchain/langgraph").OverwriteValue<string | undefined> | undefined;
|
|
76
|
+
protocolVersion?: NegotiationProtocolVersion | import("@langchain/langgraph").OverwriteValue<NegotiationProtocolVersion> | undefined;
|
|
72
77
|
isContinuation?: boolean | import("@langchain/langgraph").OverwriteValue<boolean> | undefined;
|
|
73
78
|
opportunityId?: string | import("@langchain/langgraph").OverwriteValue<string> | undefined;
|
|
74
79
|
conversationId?: string | import("@langchain/langgraph").OverwriteValue<string> | undefined;
|
|
@@ -79,7 +84,7 @@ export declare class NegotiationGraphFactory {
|
|
|
79
84
|
timeoutMs?: number | import("@langchain/langgraph").OverwriteValue<number> | undefined;
|
|
80
85
|
currentSpeaker?: "source" | "candidate" | import("@langchain/langgraph").OverwriteValue<"source" | "candidate"> | undefined;
|
|
81
86
|
lastTurn?: {
|
|
82
|
-
action: "propose" | "accept" | "reject" | "counter" | "question";
|
|
87
|
+
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline";
|
|
83
88
|
assessment: {
|
|
84
89
|
reasoning: string;
|
|
85
90
|
suggestedRoles: {
|
|
@@ -89,7 +94,7 @@ export declare class NegotiationGraphFactory {
|
|
|
89
94
|
};
|
|
90
95
|
message?: string | null | undefined;
|
|
91
96
|
} | import("@langchain/langgraph").OverwriteValue<{
|
|
92
|
-
action: "propose" | "accept" | "reject" | "counter" | "question";
|
|
97
|
+
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline";
|
|
93
98
|
assessment: {
|
|
94
99
|
reasoning: string;
|
|
95
100
|
suggestedRoles: {
|
|
@@ -136,7 +141,9 @@ export declare class NegotiationGraphFactory {
|
|
|
136
141
|
prompt: string;
|
|
137
142
|
}>, unknown>;
|
|
138
143
|
seedAssessment: import("@langchain/langgraph").BaseChannel<SeedAssessment, SeedAssessment | import("@langchain/langgraph").OverwriteValue<SeedAssessment>, unknown>;
|
|
144
|
+
initiatorUserId: import("@langchain/langgraph").BaseChannel<string | undefined, string | import("@langchain/langgraph").OverwriteValue<string | undefined> | undefined, unknown>;
|
|
139
145
|
discoveryQuery: import("@langchain/langgraph").BaseChannel<string | undefined, string | import("@langchain/langgraph").OverwriteValue<string | undefined> | undefined, unknown>;
|
|
146
|
+
protocolVersion: import("@langchain/langgraph").BaseChannel<NegotiationProtocolVersion, NegotiationProtocolVersion | import("@langchain/langgraph").OverwriteValue<NegotiationProtocolVersion>, unknown>;
|
|
140
147
|
isContinuation: import("@langchain/langgraph").BaseChannel<boolean, boolean | import("@langchain/langgraph").OverwriteValue<boolean>, unknown>;
|
|
141
148
|
opportunityId: import("@langchain/langgraph").BaseChannel<string, string | import("@langchain/langgraph").OverwriteValue<string>, unknown>;
|
|
142
149
|
conversationId: import("@langchain/langgraph").BaseChannel<string, string | import("@langchain/langgraph").OverwriteValue<string>, unknown>;
|
|
@@ -147,7 +154,7 @@ export declare class NegotiationGraphFactory {
|
|
|
147
154
|
timeoutMs: import("@langchain/langgraph").BaseChannel<number, number | import("@langchain/langgraph").OverwriteValue<number>, unknown>;
|
|
148
155
|
currentSpeaker: import("@langchain/langgraph").BaseChannel<"source" | "candidate", "source" | "candidate" | import("@langchain/langgraph").OverwriteValue<"source" | "candidate">, unknown>;
|
|
149
156
|
lastTurn: import("@langchain/langgraph").BaseChannel<{
|
|
150
|
-
action: "propose" | "accept" | "reject" | "counter" | "question";
|
|
157
|
+
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline";
|
|
151
158
|
assessment: {
|
|
152
159
|
reasoning: string;
|
|
153
160
|
suggestedRoles: {
|
|
@@ -157,7 +164,7 @@ export declare class NegotiationGraphFactory {
|
|
|
157
164
|
};
|
|
158
165
|
message?: string | null | undefined;
|
|
159
166
|
} | null, {
|
|
160
|
-
action: "propose" | "accept" | "reject" | "counter" | "question";
|
|
167
|
+
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline";
|
|
161
168
|
assessment: {
|
|
162
169
|
reasoning: string;
|
|
163
170
|
suggestedRoles: {
|
|
@@ -167,7 +174,7 @@ export declare class NegotiationGraphFactory {
|
|
|
167
174
|
};
|
|
168
175
|
message?: string | null | undefined;
|
|
169
176
|
} | import("@langchain/langgraph").OverwriteValue<{
|
|
170
|
-
action: "propose" | "accept" | "reject" | "counter" | "question";
|
|
177
|
+
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline";
|
|
171
178
|
assessment: {
|
|
172
179
|
reasoning: string;
|
|
173
180
|
suggestedRoles: {
|
|
@@ -223,7 +230,9 @@ export declare class NegotiationGraphFactory {
|
|
|
223
230
|
prompt: string;
|
|
224
231
|
}>, unknown>;
|
|
225
232
|
seedAssessment: import("@langchain/langgraph").BaseChannel<SeedAssessment, SeedAssessment | import("@langchain/langgraph").OverwriteValue<SeedAssessment>, unknown>;
|
|
233
|
+
initiatorUserId: import("@langchain/langgraph").BaseChannel<string | undefined, string | import("@langchain/langgraph").OverwriteValue<string | undefined> | undefined, unknown>;
|
|
226
234
|
discoveryQuery: import("@langchain/langgraph").BaseChannel<string | undefined, string | import("@langchain/langgraph").OverwriteValue<string | undefined> | undefined, unknown>;
|
|
235
|
+
protocolVersion: import("@langchain/langgraph").BaseChannel<NegotiationProtocolVersion, NegotiationProtocolVersion | import("@langchain/langgraph").OverwriteValue<NegotiationProtocolVersion>, unknown>;
|
|
227
236
|
isContinuation: import("@langchain/langgraph").BaseChannel<boolean, boolean | import("@langchain/langgraph").OverwriteValue<boolean>, unknown>;
|
|
228
237
|
opportunityId: import("@langchain/langgraph").BaseChannel<string, string | import("@langchain/langgraph").OverwriteValue<string>, unknown>;
|
|
229
238
|
conversationId: import("@langchain/langgraph").BaseChannel<string, string | import("@langchain/langgraph").OverwriteValue<string>, unknown>;
|
|
@@ -234,7 +243,7 @@ export declare class NegotiationGraphFactory {
|
|
|
234
243
|
timeoutMs: import("@langchain/langgraph").BaseChannel<number, number | import("@langchain/langgraph").OverwriteValue<number>, unknown>;
|
|
235
244
|
currentSpeaker: import("@langchain/langgraph").BaseChannel<"source" | "candidate", "source" | "candidate" | import("@langchain/langgraph").OverwriteValue<"source" | "candidate">, unknown>;
|
|
236
245
|
lastTurn: import("@langchain/langgraph").BaseChannel<{
|
|
237
|
-
action: "propose" | "accept" | "reject" | "counter" | "question";
|
|
246
|
+
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline";
|
|
238
247
|
assessment: {
|
|
239
248
|
reasoning: string;
|
|
240
249
|
suggestedRoles: {
|
|
@@ -244,7 +253,7 @@ export declare class NegotiationGraphFactory {
|
|
|
244
253
|
};
|
|
245
254
|
message?: string | null | undefined;
|
|
246
255
|
} | null, {
|
|
247
|
-
action: "propose" | "accept" | "reject" | "counter" | "question";
|
|
256
|
+
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline";
|
|
248
257
|
assessment: {
|
|
249
258
|
reasoning: string;
|
|
250
259
|
suggestedRoles: {
|
|
@@ -254,7 +263,7 @@ export declare class NegotiationGraphFactory {
|
|
|
254
263
|
};
|
|
255
264
|
message?: string | null | undefined;
|
|
256
265
|
} | import("@langchain/langgraph").OverwriteValue<{
|
|
257
|
-
action: "propose" | "accept" | "reject" | "counter" | "question";
|
|
266
|
+
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline";
|
|
258
267
|
assessment: {
|
|
259
268
|
reasoning: string;
|
|
260
269
|
suggestedRoles: {
|
|
@@ -314,6 +323,8 @@ export declare class NegotiationGraphFactory {
|
|
|
314
323
|
turnCount: number;
|
|
315
324
|
maxTurns: number;
|
|
316
325
|
isContinuation: boolean;
|
|
326
|
+
initiatorUserId: string;
|
|
327
|
+
protocolVersion: NegotiationProtocolVersion;
|
|
317
328
|
priorTurnCount: number;
|
|
318
329
|
error?: undefined;
|
|
319
330
|
};
|
|
@@ -331,7 +342,9 @@ export declare class NegotiationGraphFactory {
|
|
|
331
342
|
prompt: string;
|
|
332
343
|
}>, unknown>;
|
|
333
344
|
seedAssessment: import("@langchain/langgraph").BaseChannel<SeedAssessment, SeedAssessment | import("@langchain/langgraph").OverwriteValue<SeedAssessment>, unknown>;
|
|
345
|
+
initiatorUserId: import("@langchain/langgraph").BaseChannel<string | undefined, string | import("@langchain/langgraph").OverwriteValue<string | undefined> | undefined, unknown>;
|
|
334
346
|
discoveryQuery: import("@langchain/langgraph").BaseChannel<string | undefined, string | import("@langchain/langgraph").OverwriteValue<string | undefined> | undefined, unknown>;
|
|
347
|
+
protocolVersion: import("@langchain/langgraph").BaseChannel<NegotiationProtocolVersion, NegotiationProtocolVersion | import("@langchain/langgraph").OverwriteValue<NegotiationProtocolVersion>, unknown>;
|
|
335
348
|
isContinuation: import("@langchain/langgraph").BaseChannel<boolean, boolean | import("@langchain/langgraph").OverwriteValue<boolean>, unknown>;
|
|
336
349
|
opportunityId: import("@langchain/langgraph").BaseChannel<string, string | import("@langchain/langgraph").OverwriteValue<string>, unknown>;
|
|
337
350
|
conversationId: import("@langchain/langgraph").BaseChannel<string, string | import("@langchain/langgraph").OverwriteValue<string>, unknown>;
|
|
@@ -342,7 +355,7 @@ export declare class NegotiationGraphFactory {
|
|
|
342
355
|
timeoutMs: import("@langchain/langgraph").BaseChannel<number, number | import("@langchain/langgraph").OverwriteValue<number>, unknown>;
|
|
343
356
|
currentSpeaker: import("@langchain/langgraph").BaseChannel<"source" | "candidate", "source" | "candidate" | import("@langchain/langgraph").OverwriteValue<"source" | "candidate">, unknown>;
|
|
344
357
|
lastTurn: import("@langchain/langgraph").BaseChannel<{
|
|
345
|
-
action: "propose" | "accept" | "reject" | "counter" | "question";
|
|
358
|
+
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline";
|
|
346
359
|
assessment: {
|
|
347
360
|
reasoning: string;
|
|
348
361
|
suggestedRoles: {
|
|
@@ -352,7 +365,7 @@ export declare class NegotiationGraphFactory {
|
|
|
352
365
|
};
|
|
353
366
|
message?: string | null | undefined;
|
|
354
367
|
} | null, {
|
|
355
|
-
action: "propose" | "accept" | "reject" | "counter" | "question";
|
|
368
|
+
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline";
|
|
356
369
|
assessment: {
|
|
357
370
|
reasoning: string;
|
|
358
371
|
suggestedRoles: {
|
|
@@ -362,7 +375,7 @@ export declare class NegotiationGraphFactory {
|
|
|
362
375
|
};
|
|
363
376
|
message?: string | null | undefined;
|
|
364
377
|
} | import("@langchain/langgraph").OverwriteValue<{
|
|
365
|
-
action: "propose" | "accept" | "reject" | "counter" | "question";
|
|
378
|
+
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline";
|
|
366
379
|
assessment: {
|
|
367
380
|
reasoning: string;
|
|
368
381
|
suggestedRoles: {
|
|
@@ -477,6 +490,12 @@ export declare function negotiateCandidates(negotiationGraph: NegotiationGraphLi
|
|
|
477
490
|
timeoutMs?: number;
|
|
478
491
|
onCandidateResolved?: OnNegotiationResolved;
|
|
479
492
|
trigger?: "orchestrator" | "ambient";
|
|
493
|
+
/**
|
|
494
|
+
* Initiator seat for every candidate session in this fan-out (v2 stamp).
|
|
495
|
+
* Passed through to the negotiation graph, which may still override it by
|
|
496
|
+
* inheriting from a prior task on the same opportunity/conversation.
|
|
497
|
+
*/
|
|
498
|
+
initiatorUserId?: string;
|
|
480
499
|
}): Promise<NegotiationResult[]>;
|
|
481
500
|
/**
|
|
482
501
|
* Creates a negotiation graph with the provided dependencies.
|
|
@@ -493,7 +512,9 @@ export declare function createDefaultNegotiationGraph(deps: {
|
|
|
493
512
|
prompt: string;
|
|
494
513
|
};
|
|
495
514
|
seedAssessment: SeedAssessment;
|
|
515
|
+
initiatorUserId: string | undefined;
|
|
496
516
|
discoveryQuery: string | undefined;
|
|
517
|
+
protocolVersion: NegotiationProtocolVersion;
|
|
497
518
|
isContinuation: boolean;
|
|
498
519
|
opportunityId: string;
|
|
499
520
|
conversationId: string;
|
|
@@ -504,7 +525,7 @@ export declare function createDefaultNegotiationGraph(deps: {
|
|
|
504
525
|
timeoutMs: number;
|
|
505
526
|
currentSpeaker: "source" | "candidate";
|
|
506
527
|
lastTurn: {
|
|
507
|
-
action: "propose" | "accept" | "reject" | "counter" | "question";
|
|
528
|
+
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline";
|
|
508
529
|
assessment: {
|
|
509
530
|
reasoning: string;
|
|
510
531
|
suggestedRoles: {
|
|
@@ -539,7 +560,9 @@ export declare function createDefaultNegotiationGraph(deps: {
|
|
|
539
560
|
prompt: string;
|
|
540
561
|
}> | undefined;
|
|
541
562
|
seedAssessment?: SeedAssessment | import("@langchain/langgraph").OverwriteValue<SeedAssessment> | undefined;
|
|
563
|
+
initiatorUserId?: string | import("@langchain/langgraph").OverwriteValue<string | undefined> | undefined;
|
|
542
564
|
discoveryQuery?: string | import("@langchain/langgraph").OverwriteValue<string | undefined> | undefined;
|
|
565
|
+
protocolVersion?: NegotiationProtocolVersion | import("@langchain/langgraph").OverwriteValue<NegotiationProtocolVersion> | undefined;
|
|
543
566
|
isContinuation?: boolean | import("@langchain/langgraph").OverwriteValue<boolean> | undefined;
|
|
544
567
|
opportunityId?: string | import("@langchain/langgraph").OverwriteValue<string> | undefined;
|
|
545
568
|
conversationId?: string | import("@langchain/langgraph").OverwriteValue<string> | undefined;
|
|
@@ -550,7 +573,7 @@ export declare function createDefaultNegotiationGraph(deps: {
|
|
|
550
573
|
timeoutMs?: number | import("@langchain/langgraph").OverwriteValue<number> | undefined;
|
|
551
574
|
currentSpeaker?: "source" | "candidate" | import("@langchain/langgraph").OverwriteValue<"source" | "candidate"> | undefined;
|
|
552
575
|
lastTurn?: {
|
|
553
|
-
action: "propose" | "accept" | "reject" | "counter" | "question";
|
|
576
|
+
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline";
|
|
554
577
|
assessment: {
|
|
555
578
|
reasoning: string;
|
|
556
579
|
suggestedRoles: {
|
|
@@ -560,7 +583,7 @@ export declare function createDefaultNegotiationGraph(deps: {
|
|
|
560
583
|
};
|
|
561
584
|
message?: string | null | undefined;
|
|
562
585
|
} | import("@langchain/langgraph").OverwriteValue<{
|
|
563
|
-
action: "propose" | "accept" | "reject" | "counter" | "question";
|
|
586
|
+
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline";
|
|
564
587
|
assessment: {
|
|
565
588
|
reasoning: string;
|
|
566
589
|
suggestedRoles: {
|
|
@@ -607,7 +630,9 @@ export declare function createDefaultNegotiationGraph(deps: {
|
|
|
607
630
|
prompt: string;
|
|
608
631
|
}>, unknown>;
|
|
609
632
|
seedAssessment: import("@langchain/langgraph").BaseChannel<SeedAssessment, SeedAssessment | import("@langchain/langgraph").OverwriteValue<SeedAssessment>, unknown>;
|
|
633
|
+
initiatorUserId: import("@langchain/langgraph").BaseChannel<string | undefined, string | import("@langchain/langgraph").OverwriteValue<string | undefined> | undefined, unknown>;
|
|
610
634
|
discoveryQuery: import("@langchain/langgraph").BaseChannel<string | undefined, string | import("@langchain/langgraph").OverwriteValue<string | undefined> | undefined, unknown>;
|
|
635
|
+
protocolVersion: import("@langchain/langgraph").BaseChannel<NegotiationProtocolVersion, NegotiationProtocolVersion | import("@langchain/langgraph").OverwriteValue<NegotiationProtocolVersion>, unknown>;
|
|
611
636
|
isContinuation: import("@langchain/langgraph").BaseChannel<boolean, boolean | import("@langchain/langgraph").OverwriteValue<boolean>, unknown>;
|
|
612
637
|
opportunityId: import("@langchain/langgraph").BaseChannel<string, string | import("@langchain/langgraph").OverwriteValue<string>, unknown>;
|
|
613
638
|
conversationId: import("@langchain/langgraph").BaseChannel<string, string | import("@langchain/langgraph").OverwriteValue<string>, unknown>;
|
|
@@ -618,7 +643,7 @@ export declare function createDefaultNegotiationGraph(deps: {
|
|
|
618
643
|
timeoutMs: import("@langchain/langgraph").BaseChannel<number, number | import("@langchain/langgraph").OverwriteValue<number>, unknown>;
|
|
619
644
|
currentSpeaker: import("@langchain/langgraph").BaseChannel<"source" | "candidate", "source" | "candidate" | import("@langchain/langgraph").OverwriteValue<"source" | "candidate">, unknown>;
|
|
620
645
|
lastTurn: import("@langchain/langgraph").BaseChannel<{
|
|
621
|
-
action: "propose" | "accept" | "reject" | "counter" | "question";
|
|
646
|
+
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline";
|
|
622
647
|
assessment: {
|
|
623
648
|
reasoning: string;
|
|
624
649
|
suggestedRoles: {
|
|
@@ -628,7 +653,7 @@ export declare function createDefaultNegotiationGraph(deps: {
|
|
|
628
653
|
};
|
|
629
654
|
message?: string | null | undefined;
|
|
630
655
|
} | null, {
|
|
631
|
-
action: "propose" | "accept" | "reject" | "counter" | "question";
|
|
656
|
+
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline";
|
|
632
657
|
assessment: {
|
|
633
658
|
reasoning: string;
|
|
634
659
|
suggestedRoles: {
|
|
@@ -638,7 +663,7 @@ export declare function createDefaultNegotiationGraph(deps: {
|
|
|
638
663
|
};
|
|
639
664
|
message?: string | null | undefined;
|
|
640
665
|
} | import("@langchain/langgraph").OverwriteValue<{
|
|
641
|
-
action: "propose" | "accept" | "reject" | "counter" | "question";
|
|
666
|
+
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline";
|
|
642
667
|
assessment: {
|
|
643
668
|
reasoning: string;
|
|
644
669
|
suggestedRoles: {
|
|
@@ -694,7 +719,9 @@ export declare function createDefaultNegotiationGraph(deps: {
|
|
|
694
719
|
prompt: string;
|
|
695
720
|
}>, unknown>;
|
|
696
721
|
seedAssessment: import("@langchain/langgraph").BaseChannel<SeedAssessment, SeedAssessment | import("@langchain/langgraph").OverwriteValue<SeedAssessment>, unknown>;
|
|
722
|
+
initiatorUserId: import("@langchain/langgraph").BaseChannel<string | undefined, string | import("@langchain/langgraph").OverwriteValue<string | undefined> | undefined, unknown>;
|
|
697
723
|
discoveryQuery: import("@langchain/langgraph").BaseChannel<string | undefined, string | import("@langchain/langgraph").OverwriteValue<string | undefined> | undefined, unknown>;
|
|
724
|
+
protocolVersion: import("@langchain/langgraph").BaseChannel<NegotiationProtocolVersion, NegotiationProtocolVersion | import("@langchain/langgraph").OverwriteValue<NegotiationProtocolVersion>, unknown>;
|
|
698
725
|
isContinuation: import("@langchain/langgraph").BaseChannel<boolean, boolean | import("@langchain/langgraph").OverwriteValue<boolean>, unknown>;
|
|
699
726
|
opportunityId: import("@langchain/langgraph").BaseChannel<string, string | import("@langchain/langgraph").OverwriteValue<string>, unknown>;
|
|
700
727
|
conversationId: import("@langchain/langgraph").BaseChannel<string, string | import("@langchain/langgraph").OverwriteValue<string>, unknown>;
|
|
@@ -705,7 +732,7 @@ export declare function createDefaultNegotiationGraph(deps: {
|
|
|
705
732
|
timeoutMs: import("@langchain/langgraph").BaseChannel<number, number | import("@langchain/langgraph").OverwriteValue<number>, unknown>;
|
|
706
733
|
currentSpeaker: import("@langchain/langgraph").BaseChannel<"source" | "candidate", "source" | "candidate" | import("@langchain/langgraph").OverwriteValue<"source" | "candidate">, unknown>;
|
|
707
734
|
lastTurn: import("@langchain/langgraph").BaseChannel<{
|
|
708
|
-
action: "propose" | "accept" | "reject" | "counter" | "question";
|
|
735
|
+
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline";
|
|
709
736
|
assessment: {
|
|
710
737
|
reasoning: string;
|
|
711
738
|
suggestedRoles: {
|
|
@@ -715,7 +742,7 @@ export declare function createDefaultNegotiationGraph(deps: {
|
|
|
715
742
|
};
|
|
716
743
|
message?: string | null | undefined;
|
|
717
744
|
} | null, {
|
|
718
|
-
action: "propose" | "accept" | "reject" | "counter" | "question";
|
|
745
|
+
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline";
|
|
719
746
|
assessment: {
|
|
720
747
|
reasoning: string;
|
|
721
748
|
suggestedRoles: {
|
|
@@ -725,7 +752,7 @@ export declare function createDefaultNegotiationGraph(deps: {
|
|
|
725
752
|
};
|
|
726
753
|
message?: string | null | undefined;
|
|
727
754
|
} | import("@langchain/langgraph").OverwriteValue<{
|
|
728
|
-
action: "propose" | "accept" | "reject" | "counter" | "question";
|
|
755
|
+
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline";
|
|
729
756
|
assessment: {
|
|
730
757
|
reasoning: string;
|
|
731
758
|
suggestedRoles: {
|
|
@@ -785,6 +812,8 @@ export declare function createDefaultNegotiationGraph(deps: {
|
|
|
785
812
|
turnCount: number;
|
|
786
813
|
maxTurns: number;
|
|
787
814
|
isContinuation: boolean;
|
|
815
|
+
initiatorUserId: string;
|
|
816
|
+
protocolVersion: NegotiationProtocolVersion;
|
|
788
817
|
priorTurnCount: number;
|
|
789
818
|
error?: undefined;
|
|
790
819
|
};
|
|
@@ -802,7 +831,9 @@ export declare function createDefaultNegotiationGraph(deps: {
|
|
|
802
831
|
prompt: string;
|
|
803
832
|
}>, unknown>;
|
|
804
833
|
seedAssessment: import("@langchain/langgraph").BaseChannel<SeedAssessment, SeedAssessment | import("@langchain/langgraph").OverwriteValue<SeedAssessment>, unknown>;
|
|
834
|
+
initiatorUserId: import("@langchain/langgraph").BaseChannel<string | undefined, string | import("@langchain/langgraph").OverwriteValue<string | undefined> | undefined, unknown>;
|
|
805
835
|
discoveryQuery: import("@langchain/langgraph").BaseChannel<string | undefined, string | import("@langchain/langgraph").OverwriteValue<string | undefined> | undefined, unknown>;
|
|
836
|
+
protocolVersion: import("@langchain/langgraph").BaseChannel<NegotiationProtocolVersion, NegotiationProtocolVersion | import("@langchain/langgraph").OverwriteValue<NegotiationProtocolVersion>, unknown>;
|
|
806
837
|
isContinuation: import("@langchain/langgraph").BaseChannel<boolean, boolean | import("@langchain/langgraph").OverwriteValue<boolean>, unknown>;
|
|
807
838
|
opportunityId: import("@langchain/langgraph").BaseChannel<string, string | import("@langchain/langgraph").OverwriteValue<string>, unknown>;
|
|
808
839
|
conversationId: import("@langchain/langgraph").BaseChannel<string, string | import("@langchain/langgraph").OverwriteValue<string>, unknown>;
|
|
@@ -813,7 +844,7 @@ export declare function createDefaultNegotiationGraph(deps: {
|
|
|
813
844
|
timeoutMs: import("@langchain/langgraph").BaseChannel<number, number | import("@langchain/langgraph").OverwriteValue<number>, unknown>;
|
|
814
845
|
currentSpeaker: import("@langchain/langgraph").BaseChannel<"source" | "candidate", "source" | "candidate" | import("@langchain/langgraph").OverwriteValue<"source" | "candidate">, unknown>;
|
|
815
846
|
lastTurn: import("@langchain/langgraph").BaseChannel<{
|
|
816
|
-
action: "propose" | "accept" | "reject" | "counter" | "question";
|
|
847
|
+
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline";
|
|
817
848
|
assessment: {
|
|
818
849
|
reasoning: string;
|
|
819
850
|
suggestedRoles: {
|
|
@@ -823,7 +854,7 @@ export declare function createDefaultNegotiationGraph(deps: {
|
|
|
823
854
|
};
|
|
824
855
|
message?: string | null | undefined;
|
|
825
856
|
} | null, {
|
|
826
|
-
action: "propose" | "accept" | "reject" | "counter" | "question";
|
|
857
|
+
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline";
|
|
827
858
|
assessment: {
|
|
828
859
|
reasoning: string;
|
|
829
860
|
suggestedRoles: {
|
|
@@ -833,7 +864,7 @@ export declare function createDefaultNegotiationGraph(deps: {
|
|
|
833
864
|
};
|
|
834
865
|
message?: string | null | undefined;
|
|
835
866
|
} | import("@langchain/langgraph").OverwriteValue<{
|
|
836
|
-
action: "propose" | "accept" | "reject" | "counter" | "question";
|
|
867
|
+
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline";
|
|
837
868
|
assessment: {
|
|
838
869
|
reasoning: string;
|
|
839
870
|
suggestedRoles: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"negotiation.graph.d.ts","sourceRoot":"/","sources":["negotiation/negotiation.graph.ts"],"names":[],"mappings":"AAGA,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,4CAA4C,CAAC;AAC/F,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,4CAA4C,CAAC;AAC3F,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sDAAsD,CAAC;AACpG,OAAO,KAAK,EAAE,eAAe,EAA0B,MAAM,oDAAoD,CAAC;AAClH,OAAO,EAAyB,KAAK,eAAe,EAAE,KAAK,kBAAkB,EAAE,KAAK,sBAAsB,EAAE,KAAK,cAAc,EAAE,KAAK,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAG3L,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAkB7E;;;GAGG;AACH,qBAAa,uBAAuB;IAEhC,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,YAAY,CAAC;IACrB,OAAO,CAAC,iBAAiB,CAAC;gBAHlB,QAAQ,EAAE,wBAAwB,EAClC,UAAU,EAAE,eAAe,EAC3B,YAAY,CAAC,EAAE,uBAAuB,YAAA,EACtC,iBAAiB,CAAC,EAAE,mBAAmB,YAAA;IAGjD,WAAW
|
|
1
|
+
{"version":3,"file":"negotiation.graph.d.ts","sourceRoot":"/","sources":["negotiation/negotiation.graph.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ import { invokeWithAbortSignal } from "../shared/agent/model-signal.js";
|
|
|
3
3
|
import { requestContext } from "../shared/observability/request-context.js";
|
|
4
4
|
import { NegotiationGraphState } from "./negotiation.state.js";
|
|
5
5
|
import { IndexNegotiator } from "./negotiation.agent.js";
|
|
6
|
+
import { allowedActionsFor, configuredProtocolVersion, fallbackActionFor, isRejectLikeAction, isTerminalAction, readProtocolVersion, rejectActionFor } from "./negotiation.protocol.js";
|
|
6
7
|
import { protocolLogger } from "../shared/observability/protocol.logger.js";
|
|
7
8
|
const logger = protocolLogger("NegotiationGraph");
|
|
8
9
|
const initLog = protocolLogger("NegotiationGraph:Init");
|
|
@@ -40,17 +41,12 @@ export class NegotiationGraphFactory {
|
|
|
40
41
|
const conversation = await database.getOrCreateDM(agentIdA, agentIdB, 'agent');
|
|
41
42
|
// --- Lock gate: check for an active task on this conversation ---
|
|
42
43
|
const priorMessages = await database.getMessagesForConversation(conversation.id);
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
if (activeStates.includes(priorTask.state) && isFresh) {
|
|
50
|
-
isLocked = true;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
44
|
+
const activeStates = ['submitted', 'working', 'input_required', 'waiting_for_agent', 'claimed'];
|
|
45
|
+
const isActiveAndFresh = (t) => activeStates.includes(t.state) && (Date.now() - new Date(t.updatedAt).getTime()) < 5 * 60 * 1000;
|
|
46
|
+
const priorTask = state.opportunityId
|
|
47
|
+
? await database.getNegotiationTaskForOpportunity(state.opportunityId)
|
|
48
|
+
: null;
|
|
49
|
+
const isLocked = !!priorTask && isActiveAndFresh(priorTask);
|
|
54
50
|
if (isLocked) {
|
|
55
51
|
initLog.info('Conversation locked by active task, returning busy', {
|
|
56
52
|
conversationId: conversation.id,
|
|
@@ -78,9 +74,62 @@ export class NegotiationGraphFactory {
|
|
|
78
74
|
if (maxTurns == null) {
|
|
79
75
|
maxTurns = (sourceHasAgent && candidateHasAgent) ? 0 : ambientMax;
|
|
80
76
|
}
|
|
77
|
+
// --- Initiator seat resolution (v2: rigid per match, stamped at discovery) ---
|
|
78
|
+
// 1. Continuations inherit from the prior task for the same opportunity —
|
|
79
|
+
// never re-derive, so the seat cannot flip between sessions.
|
|
80
|
+
// 2. Conversation-scoped tie-break: if another negotiation on this DM is
|
|
81
|
+
// active and fresh (symmetric concurrent start under a different
|
|
82
|
+
// opportunityId — the opportunity-scoped lock above cannot see it),
|
|
83
|
+
// the first created task keeps the seat; this run inherits its stamp.
|
|
84
|
+
// 3. Otherwise: explicit stamp from the caller, falling back to the
|
|
85
|
+
// session's sourceUser (pre-stamp heuristic behavior, unchanged).
|
|
86
|
+
const readInitiator = (metadata) => {
|
|
87
|
+
const v = metadata?.initiatorUserId;
|
|
88
|
+
return typeof v === 'string' && v.length > 0 ? v : null;
|
|
89
|
+
};
|
|
90
|
+
let initiatorUserId = readInitiator(priorTask?.metadata) ?? state.initiatorUserId ?? state.sourceUser.id;
|
|
91
|
+
// Conversation-scoped prior task: reused for both the initiator tie-break
|
|
92
|
+
// (only when active+fresh) and protocol-version inheritance (any prior
|
|
93
|
+
// task on the conversation pins the version).
|
|
94
|
+
const convTask = (!readInitiator(priorTask?.metadata) || !readProtocolVersion(priorTask?.metadata))
|
|
95
|
+
? await database.getLatestNegotiationTaskForConversation?.(conversation.id).catch(() => null)
|
|
96
|
+
: null;
|
|
97
|
+
if (!readInitiator(priorTask?.metadata)) {
|
|
98
|
+
if (convTask && convTask.id !== priorTask?.id && isActiveAndFresh(convTask)) {
|
|
99
|
+
const convInitiator = readInitiator(convTask.metadata);
|
|
100
|
+
if (convInitiator) {
|
|
101
|
+
initLog.info('Conversation-scoped tie-break: inheriting initiator seat from concurrent task', {
|
|
102
|
+
conversationId: conversation.id,
|
|
103
|
+
winningTaskId: convTask.id,
|
|
104
|
+
initiatorUserId: convInitiator,
|
|
105
|
+
});
|
|
106
|
+
initiatorUserId = convInitiator;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// --- Protocol version: inherited, never re-stamped ---
|
|
111
|
+
// Every session (including continuations) creates a new task row, so a
|
|
112
|
+
// naïve "stamp from env at init" would flip a v1 conversation to v2
|
|
113
|
+
// mid-flight. Rule: any prior negotiation task on this conversation pins
|
|
114
|
+
// the version (absent field on a genuine prior = pre-v2 task = v1);
|
|
115
|
+
// prior turns without a readable task also grandfather to v1; only
|
|
116
|
+
// genuinely fresh negotiations stamp from NEGOTIATION_PROTOCOL_VERSION.
|
|
117
|
+
let protocolVersion;
|
|
118
|
+
const priorVersionSource = priorTask ?? convTask;
|
|
119
|
+
if (priorVersionSource) {
|
|
120
|
+
protocolVersion = readProtocolVersion(priorVersionSource.metadata) ?? 'v1';
|
|
121
|
+
}
|
|
122
|
+
else if (isContinuation) {
|
|
123
|
+
protocolVersion = 'v1';
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
protocolVersion = configuredProtocolVersion();
|
|
127
|
+
}
|
|
81
128
|
const task = await database.createTask(conversation.id, {
|
|
82
129
|
type: 'negotiation',
|
|
83
130
|
sourceUserId: state.sourceUser.id,
|
|
131
|
+
initiatorUserId,
|
|
132
|
+
protocolVersion,
|
|
84
133
|
candidateUserId: state.candidateUser.id,
|
|
85
134
|
networkId: state.indexContext.networkId,
|
|
86
135
|
...(state.opportunityId && { opportunityId: state.opportunityId }),
|
|
@@ -115,6 +164,8 @@ export class NegotiationGraphFactory {
|
|
|
115
164
|
turnCount: 0,
|
|
116
165
|
maxTurns,
|
|
117
166
|
isContinuation,
|
|
167
|
+
initiatorUserId,
|
|
168
|
+
protocolVersion,
|
|
118
169
|
priorTurnCount: priorTurns.length,
|
|
119
170
|
...(userAnswers.length > 0 && { userAnswers }),
|
|
120
171
|
...(seedMessages.length > 0 && { messages: seedMessages }),
|
|
@@ -141,6 +192,13 @@ export class NegotiationGraphFactory {
|
|
|
141
192
|
// Determine if this is the system agent's final allowed turn
|
|
142
193
|
const maxTurns = state.maxTurns ?? 0;
|
|
143
194
|
const isFinalTurn = maxTurns > 0 && (state.turnCount + 1) >= maxTurns;
|
|
195
|
+
// Seat attribution keys on initiatorUserId (rigid v2 stamp), never on
|
|
196
|
+
// parity or source/candidate position — under the conversation-scoped
|
|
197
|
+
// tie-break this run's source may hold the counterparty seat.
|
|
198
|
+
const version = state.protocolVersion ?? 'v1';
|
|
199
|
+
const seat = ownUser.id === (state.initiatorUserId ?? state.sourceUser.id)
|
|
200
|
+
? 'initiator'
|
|
201
|
+
: 'counterparty';
|
|
144
202
|
const payload = {
|
|
145
203
|
negotiationId: state.taskId,
|
|
146
204
|
ownUser,
|
|
@@ -150,14 +208,25 @@ export class NegotiationGraphFactory {
|
|
|
150
208
|
history,
|
|
151
209
|
isFinalTurn,
|
|
152
210
|
isDiscoverer: isSource,
|
|
211
|
+
seat,
|
|
212
|
+
protocolVersion: version,
|
|
213
|
+
allowedActions: [...allowedActionsFor(version, seat, isFinalTurn)],
|
|
153
214
|
...(state.discoveryQuery && isSource && { discoveryQuery: state.discoveryQuery }),
|
|
154
215
|
};
|
|
155
216
|
const scope = { action: 'manage:negotiations', scopeType: 'network', scopeId: state.indexContext.networkId };
|
|
156
217
|
const dispatchResult = await dispatcher.dispatch(ownUser.id, scope, payload, { timeoutMs: state.timeoutMs });
|
|
157
218
|
let turn;
|
|
158
219
|
if (dispatchResult.handled) {
|
|
159
|
-
// Personal agent responded
|
|
220
|
+
// Personal agent responded. Under v2, coerce out-of-seat actions to
|
|
221
|
+
// the conservative fallback — the polling/respond surfaces reject
|
|
222
|
+
// these with a 400, but locally-dispatched turns land here directly.
|
|
160
223
|
turn = dispatchResult.turn;
|
|
224
|
+
if (version === 'v2' && !allowedActionsFor(version, seat, isFinalTurn).includes(turn.action)) {
|
|
225
|
+
turnLog.warn('Personal agent returned out-of-seat action, coercing to conservative fallback', {
|
|
226
|
+
action: turn.action, seat, isFinalTurn,
|
|
227
|
+
});
|
|
228
|
+
turn = { ...turn, action: fallbackActionFor(version, seat, isFinalTurn) };
|
|
229
|
+
}
|
|
161
230
|
}
|
|
162
231
|
else if (dispatchResult.reason === 'waiting') {
|
|
163
232
|
// Long timeout — graph suspends. Persist the full turn context so the
|
|
@@ -190,16 +259,24 @@ export class NegotiationGraphFactory {
|
|
|
190
259
|
history,
|
|
191
260
|
isFinalTurn,
|
|
192
261
|
isDiscoverer: isSource,
|
|
262
|
+
seat,
|
|
263
|
+
protocolVersion: version,
|
|
193
264
|
...(state.discoveryQuery && isSource && { discoveryQuery: state.discoveryQuery }),
|
|
194
265
|
isContinuation: state.isContinuation,
|
|
195
266
|
...(state.userAnswers.length > 0 && { userAnswers: state.userAnswers }),
|
|
196
267
|
});
|
|
197
268
|
}
|
|
198
269
|
traceEmitter?.({ type: "agent_end", name: agentName, durationMs: Date.now() - agentStart, summary: `${turn.action}` });
|
|
199
|
-
// First turn must
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
270
|
+
// First turn must open the negotiation (unless continuing a prior
|
|
271
|
+
// conversation): v1 → "propose"; v2 initiator → "outreach". A v2 turn-0
|
|
272
|
+
// speaker holding the counterparty seat (tie-break inheritance) is left
|
|
273
|
+
// unforced — it is responding, not opening.
|
|
274
|
+
if (state.turnCount === 0 && !state.isContinuation) {
|
|
275
|
+
const openingAction = version === 'v2' ? 'outreach' : 'propose';
|
|
276
|
+
if ((version !== 'v2' || seat === 'initiator') && turn.action !== openingAction) {
|
|
277
|
+
turnLog.warn(`Agent returned unexpected action on turn 0, forcing to ${openingAction}`, { action: turn.action });
|
|
278
|
+
turn.action = openingAction;
|
|
279
|
+
}
|
|
203
280
|
}
|
|
204
281
|
const parts = [{ kind: "data", data: turn }];
|
|
205
282
|
const message = await database.createMessage({
|
|
@@ -241,9 +318,12 @@ export class NegotiationGraphFactory {
|
|
|
241
318
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
242
319
|
turnLog.error("Agent invocation failed", { error: errMsg, stack: err instanceof Error ? err.stack : undefined, turnCount: state.turnCount });
|
|
243
320
|
traceEmitter?.({ type: "agent_end", name: agentName, durationMs: Date.now() - agentStart, summary: `error: ${errMsg}` });
|
|
321
|
+
const errorSeat = (state.currentSpeaker === 'source' ? state.sourceUser.id : state.candidateUser.id) === (state.initiatorUserId ?? state.sourceUser.id)
|
|
322
|
+
? 'initiator'
|
|
323
|
+
: 'counterparty';
|
|
244
324
|
return {
|
|
245
325
|
lastTurn: {
|
|
246
|
-
action:
|
|
326
|
+
action: rejectActionFor(state.protocolVersion ?? 'v1', errorSeat),
|
|
247
327
|
assessment: { reasoning: `Agent error: ${errMsg}`, suggestedRoles: { ownUser: "peer", otherUser: "peer" } },
|
|
248
328
|
},
|
|
249
329
|
turnCount: state.turnCount + 1,
|
|
@@ -258,9 +338,8 @@ export class NegotiationGraphFactory {
|
|
|
258
338
|
return "finalize";
|
|
259
339
|
if (!state.lastTurn)
|
|
260
340
|
return "finalize";
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
if (state.lastTurn.action === "reject")
|
|
341
|
+
// Terminal actions: accept (v1+v2), reject (v1), withdraw/decline (v2)
|
|
342
|
+
if (isTerminalAction(state.lastTurn.action))
|
|
264
343
|
return "finalize";
|
|
265
344
|
// question routes same as counter — next turn
|
|
266
345
|
if ((state.maxTurns ?? 0) > 0 && state.turnCount >= state.maxTurns)
|
|
@@ -285,7 +364,7 @@ export class NegotiationGraphFactory {
|
|
|
285
364
|
const history = turnsFromMessages(state.messages);
|
|
286
365
|
const lastTurn = state.lastTurn;
|
|
287
366
|
const hasOpportunity = lastTurn?.action === "accept";
|
|
288
|
-
const atCap = (state.maxTurns ?? 0) > 0 && state.turnCount >= state.maxTurns && lastTurn?.action
|
|
367
|
+
const atCap = (state.maxTurns ?? 0) > 0 && state.turnCount >= state.maxTurns && !isTerminalAction(lastTurn?.action);
|
|
289
368
|
let agreedRoles = [];
|
|
290
369
|
if (hasOpportunity && history.length >= 2) {
|
|
291
370
|
const acceptTurn = history[history.length - 1];
|
|
@@ -326,7 +405,7 @@ export class NegotiationGraphFactory {
|
|
|
326
405
|
if (state.opportunityId) {
|
|
327
406
|
const nextStatus = lastTurn?.action === 'accept'
|
|
328
407
|
? 'pending'
|
|
329
|
-
: lastTurn?.action
|
|
408
|
+
: isRejectLikeAction(lastTurn?.action)
|
|
330
409
|
? 'rejected'
|
|
331
410
|
: 'stalled';
|
|
332
411
|
await database.updateOpportunityStatus(state.opportunityId, nextStatus).catch((err) => {
|
|
@@ -344,9 +423,7 @@ export class NegotiationGraphFactory {
|
|
|
344
423
|
? "turn_cap"
|
|
345
424
|
: state.error && /timeout/i.test(state.error)
|
|
346
425
|
? "timed_out"
|
|
347
|
-
:
|
|
348
|
-
? "rejected_stalled"
|
|
349
|
-
: "rejected_stalled";
|
|
426
|
+
: "rejected_stalled";
|
|
350
427
|
emitWide({
|
|
351
428
|
type: "negotiation_outcome",
|
|
352
429
|
opportunityId: state.opportunityId,
|
|
@@ -366,7 +443,7 @@ export class NegotiationGraphFactory {
|
|
|
366
443
|
}
|
|
367
444
|
// Enqueue question generation for stalled/capped negotiations (not accepted or explicitly rejected).
|
|
368
445
|
// Require turnCount > 0 so early init/turn errors don't enqueue with empty context.
|
|
369
|
-
if (!hasOpportunity && lastTurn?.action
|
|
446
|
+
if (!hasOpportunity && !isRejectLikeAction(lastTurn?.action) && state.turnCount > 0 && state.opportunityId && questionerEnqueue) {
|
|
370
447
|
const stallReason = atCap
|
|
371
448
|
? 'turn_cap'
|
|
372
449
|
: (state.error && /timeout/i.test(state.error))
|
|
@@ -414,7 +491,7 @@ export class NegotiationGraphFactory {
|
|
|
414
491
|
* @returns Only candidates that produced an opportunity
|
|
415
492
|
*/
|
|
416
493
|
export async function negotiateCandidates(negotiationGraph, sourceUser, candidates, indexContext, opts) {
|
|
417
|
-
const { maxTurns, traceEmitter, indexContextOverrides, timeoutMs, onCandidateResolved, trigger } = opts ?? {};
|
|
494
|
+
const { maxTurns, traceEmitter, indexContextOverrides, timeoutMs, onCandidateResolved, trigger, initiatorUserId } = opts ?? {};
|
|
418
495
|
// Local helper to emit events whose shape is wider than the declared
|
|
419
496
|
// `TraceEmitter` union (mirrors the cast used in chat.agent at the relay sink
|
|
420
497
|
// and inside turn/finalize nodes above).
|
|
@@ -429,6 +506,7 @@ export async function negotiateCandidates(negotiationGraph, sourceUser, candidat
|
|
|
429
506
|
negotiationConversationId: "", // filled in on session_end
|
|
430
507
|
sourceUserId: sourceUser.id,
|
|
431
508
|
candidateUserId: candidate.userId,
|
|
509
|
+
initiatorUserId: initiatorUserId ?? sourceUser.id,
|
|
432
510
|
...(candidateName && { candidateName }),
|
|
433
511
|
trigger: trigger ?? "ambient",
|
|
434
512
|
startedAt: start,
|
|
@@ -449,6 +527,7 @@ export async function negotiateCandidates(negotiationGraph, sourceUser, candidat
|
|
|
449
527
|
},
|
|
450
528
|
...(candidate.discoveryQuery && { discoveryQuery: candidate.discoveryQuery }),
|
|
451
529
|
...(candidate.opportunityId && { opportunityId: candidate.opportunityId }),
|
|
530
|
+
...(initiatorUserId && { initiatorUserId }),
|
|
452
531
|
...(maxTurns !== undefined && { maxTurns }),
|
|
453
532
|
...(timeoutMs !== undefined && { timeoutMs }),
|
|
454
533
|
});
|