@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.
Files changed (49) hide show
  1. package/dist/chat/chat-streaming.types.d.ts +3 -1
  2. package/dist/chat/chat-streaming.types.d.ts.map +1 -1
  3. package/dist/chat/chat-streaming.types.js.map +1 -1
  4. package/dist/chat/chat.agent.d.ts +1 -1
  5. package/dist/chat/chat.agent.d.ts.map +1 -1
  6. package/dist/chat/chat.agent.js.map +1 -1
  7. package/dist/index.d.ts +3 -0
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +3 -0
  10. package/dist/index.js.map +1 -1
  11. package/dist/negotiation/negotiation.agent.d.ts +21 -0
  12. package/dist/negotiation/negotiation.agent.d.ts.map +1 -1
  13. package/dist/negotiation/negotiation.agent.js +79 -11
  14. package/dist/negotiation/negotiation.agent.js.map +1 -1
  15. package/dist/negotiation/negotiation.graph.d.ts +55 -24
  16. package/dist/negotiation/negotiation.graph.d.ts.map +1 -1
  17. package/dist/negotiation/negotiation.graph.js +106 -27
  18. package/dist/negotiation/negotiation.graph.js.map +1 -1
  19. package/dist/negotiation/negotiation.protocol.d.ts +287 -0
  20. package/dist/negotiation/negotiation.protocol.d.ts.map +1 -0
  21. package/dist/negotiation/negotiation.protocol.js +152 -0
  22. package/dist/negotiation/negotiation.protocol.js.map +1 -0
  23. package/dist/negotiation/negotiation.state.d.ts +34 -9
  24. package/dist/negotiation/negotiation.state.d.ts.map +1 -1
  25. package/dist/negotiation/negotiation.state.js +28 -4
  26. package/dist/negotiation/negotiation.state.js.map +1 -1
  27. package/dist/negotiation/negotiation.tools.d.ts.map +1 -1
  28. package/dist/negotiation/negotiation.tools.js +86 -31
  29. package/dist/negotiation/negotiation.tools.js.map +1 -1
  30. package/dist/opportunity/opportunity.graph.d.ts.map +1 -1
  31. package/dist/opportunity/opportunity.graph.js +9 -0
  32. package/dist/opportunity/opportunity.graph.js.map +1 -1
  33. package/dist/opportunity/question.prompt.d.ts +1 -1
  34. package/dist/opportunity/question.prompt.d.ts.map +1 -1
  35. package/dist/opportunity/question.prompt.js.map +1 -1
  36. package/dist/shared/interfaces/agent-dispatcher.interface.d.ts +6 -0
  37. package/dist/shared/interfaces/agent-dispatcher.interface.d.ts.map +1 -1
  38. package/dist/shared/interfaces/agent-dispatcher.interface.js.map +1 -1
  39. package/dist/shared/interfaces/database.interface.d.ts +17 -0
  40. package/dist/shared/interfaces/database.interface.d.ts.map +1 -1
  41. package/dist/shared/interfaces/database.interface.js.map +1 -1
  42. package/dist/shared/schemas/discovery-question.schema.d.ts +8 -8
  43. package/dist/shared/schemas/discovery-question.schema.js +1 -1
  44. package/dist/shared/schemas/discovery-question.schema.js.map +1 -1
  45. package/dist/shared/schemas/negotiation-state.schema.d.ts +19 -3
  46. package/dist/shared/schemas/negotiation-state.schema.d.ts.map +1 -1
  47. package/dist/shared/schemas/negotiation-state.schema.js +15 -1
  48. package/dist/shared/schemas/negotiation-state.schema.js.map +1 -1
  49. 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":"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"}
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
- let isLocked = false;
44
- if (state.opportunityId) {
45
- const priorTask = await database.getNegotiationTaskForOpportunity(state.opportunityId);
46
- if (priorTask) {
47
- const activeStates = ['submitted', 'working', 'input_required', 'waiting_for_agent', 'claimed'];
48
- const isFresh = (Date.now() - new Date(priorTask.updatedAt).getTime()) < 5 * 60 * 1000;
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 be "propose" (unless continuing a prior conversation)
200
- if (state.turnCount === 0 && !state.isContinuation && turn.action !== "propose") {
201
- turnLog.warn("Agent returned unexpected action on turn 0, forcing to propose", { action: turn.action });
202
- turn.action = "propose";
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: "reject",
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
- if (state.lastTurn.action === "accept")
262
- return "finalize";
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 !== "accept" && lastTurn?.action !== "reject";
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 === 'reject'
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
- : lastTurn?.action === "reject"
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 !== 'reject' && state.turnCount > 0 && state.opportunityId && questionerEnqueue) {
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
  });