@indexnetwork/protocol 6.0.0-rc.375.1 → 6.2.0-rc.377.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.
@@ -4,6 +4,7 @@ import type { NegotiationTimeoutQueue } from "../shared/interfaces/negotiation-e
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
6
  import { type ScreenDecisionRecord } from "./negotiation.screen.js";
7
+ import { type DeadlockShiftRecord } from "./negotiation.deadlock.js";
7
8
  import type { NegotiationProtocolVersion } from "../shared/schemas/negotiation-state.schema.js";
8
9
  import type { QuestionerEnqueueFn } from "../questioner/questioner.types.js";
9
10
  import type { ReflectEnqueueFn } from "./negotiation.reflect.js";
@@ -32,6 +33,7 @@ export declare class NegotiationGraphFactory {
32
33
  discoveryQuery: string | undefined;
33
34
  protocolVersion: NegotiationProtocolVersion;
34
35
  screenDecision: ScreenDecisionRecord | null;
36
+ deadlockShift: DeadlockShiftRecord | null;
35
37
  memoryBySide: Partial<Record<"source" | "candidate", NegotiatorMemoryEntry[]>>;
36
38
  isContinuation: boolean;
37
39
  opportunityId: string;
@@ -86,6 +88,7 @@ export declare class NegotiationGraphFactory {
86
88
  discoveryQuery?: string | import("@langchain/langgraph").OverwriteValue<string | undefined> | undefined;
87
89
  protocolVersion?: NegotiationProtocolVersion | import("@langchain/langgraph").OverwriteValue<NegotiationProtocolVersion> | undefined;
88
90
  screenDecision?: ScreenDecisionRecord | import("@langchain/langgraph").OverwriteValue<ScreenDecisionRecord | null> | null | undefined;
91
+ deadlockShift?: DeadlockShiftRecord | import("@langchain/langgraph").OverwriteValue<DeadlockShiftRecord | null> | null | undefined;
89
92
  memoryBySide?: Partial<Record<"source" | "candidate", NegotiatorMemoryEntry[]>> | import("@langchain/langgraph").OverwriteValue<Partial<Record<"source" | "candidate", NegotiatorMemoryEntry[]>>> | undefined;
90
93
  isContinuation?: boolean | import("@langchain/langgraph").OverwriteValue<boolean> | undefined;
91
94
  opportunityId?: string | import("@langchain/langgraph").OverwriteValue<string> | undefined;
@@ -166,6 +169,7 @@ export declare class NegotiationGraphFactory {
166
169
  discoveryQuery: import("@langchain/langgraph").BaseChannel<string | undefined, string | import("@langchain/langgraph").OverwriteValue<string | undefined> | undefined, unknown>;
167
170
  protocolVersion: import("@langchain/langgraph").BaseChannel<NegotiationProtocolVersion, NegotiationProtocolVersion | import("@langchain/langgraph").OverwriteValue<NegotiationProtocolVersion>, unknown>;
168
171
  screenDecision: import("@langchain/langgraph").BaseChannel<ScreenDecisionRecord | null, ScreenDecisionRecord | import("@langchain/langgraph").OverwriteValue<ScreenDecisionRecord | null> | null, unknown>;
172
+ deadlockShift: import("@langchain/langgraph").BaseChannel<DeadlockShiftRecord | null, DeadlockShiftRecord | import("@langchain/langgraph").OverwriteValue<DeadlockShiftRecord | null> | null, unknown>;
169
173
  memoryBySide: import("@langchain/langgraph").BaseChannel<Partial<Record<"source" | "candidate", NegotiatorMemoryEntry[]>>, Partial<Record<"source" | "candidate", NegotiatorMemoryEntry[]>> | import("@langchain/langgraph").OverwriteValue<Partial<Record<"source" | "candidate", NegotiatorMemoryEntry[]>>>, unknown>;
170
174
  isContinuation: import("@langchain/langgraph").BaseChannel<boolean, boolean | import("@langchain/langgraph").OverwriteValue<boolean>, unknown>;
171
175
  opportunityId: import("@langchain/langgraph").BaseChannel<string, string | import("@langchain/langgraph").OverwriteValue<string>, unknown>;
@@ -269,6 +273,7 @@ export declare class NegotiationGraphFactory {
269
273
  discoveryQuery: import("@langchain/langgraph").BaseChannel<string | undefined, string | import("@langchain/langgraph").OverwriteValue<string | undefined> | undefined, unknown>;
270
274
  protocolVersion: import("@langchain/langgraph").BaseChannel<NegotiationProtocolVersion, NegotiationProtocolVersion | import("@langchain/langgraph").OverwriteValue<NegotiationProtocolVersion>, unknown>;
271
275
  screenDecision: import("@langchain/langgraph").BaseChannel<ScreenDecisionRecord | null, ScreenDecisionRecord | import("@langchain/langgraph").OverwriteValue<ScreenDecisionRecord | null> | null, unknown>;
276
+ deadlockShift: import("@langchain/langgraph").BaseChannel<DeadlockShiftRecord | null, DeadlockShiftRecord | import("@langchain/langgraph").OverwriteValue<DeadlockShiftRecord | null> | null, unknown>;
272
277
  memoryBySide: import("@langchain/langgraph").BaseChannel<Partial<Record<"source" | "candidate", NegotiatorMemoryEntry[]>>, Partial<Record<"source" | "candidate", NegotiatorMemoryEntry[]>> | import("@langchain/langgraph").OverwriteValue<Partial<Record<"source" | "candidate", NegotiatorMemoryEntry[]>>>, unknown>;
273
278
  isContinuation: import("@langchain/langgraph").BaseChannel<boolean, boolean | import("@langchain/langgraph").OverwriteValue<boolean>, unknown>;
274
279
  opportunityId: import("@langchain/langgraph").BaseChannel<string, string | import("@langchain/langgraph").OverwriteValue<string>, unknown>;
@@ -401,6 +406,7 @@ export declare class NegotiationGraphFactory {
401
406
  discoveryQuery: import("@langchain/langgraph").BaseChannel<string | undefined, string | import("@langchain/langgraph").OverwriteValue<string | undefined> | undefined, unknown>;
402
407
  protocolVersion: import("@langchain/langgraph").BaseChannel<NegotiationProtocolVersion, NegotiationProtocolVersion | import("@langchain/langgraph").OverwriteValue<NegotiationProtocolVersion>, unknown>;
403
408
  screenDecision: import("@langchain/langgraph").BaseChannel<ScreenDecisionRecord | null, ScreenDecisionRecord | import("@langchain/langgraph").OverwriteValue<ScreenDecisionRecord | null> | null, unknown>;
409
+ deadlockShift: import("@langchain/langgraph").BaseChannel<DeadlockShiftRecord | null, DeadlockShiftRecord | import("@langchain/langgraph").OverwriteValue<DeadlockShiftRecord | null> | null, unknown>;
404
410
  memoryBySide: import("@langchain/langgraph").BaseChannel<Partial<Record<"source" | "candidate", NegotiatorMemoryEntry[]>>, Partial<Record<"source" | "candidate", NegotiatorMemoryEntry[]>> | import("@langchain/langgraph").OverwriteValue<Partial<Record<"source" | "candidate", NegotiatorMemoryEntry[]>>>, unknown>;
405
411
  isContinuation: import("@langchain/langgraph").BaseChannel<boolean, boolean | import("@langchain/langgraph").OverwriteValue<boolean>, unknown>;
406
412
  opportunityId: import("@langchain/langgraph").BaseChannel<string, string | import("@langchain/langgraph").OverwriteValue<string>, unknown>;
@@ -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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"}
@@ -5,6 +5,7 @@ import { NegotiationGraphState } from "./negotiation.state.js";
5
5
  import { IndexNegotiator } from "./negotiation.agent.js";
6
6
  import { ASK_USER_LOCK_SLACK_MS, allowedActionsFor, askUserAnswerWindowMs, configuredAskUserEnabled, configuredProtocolVersion, fallbackActionFor, isRejectLikeAction, isTerminalAction, readProtocolVersion, rejectActionFor } from "./negotiation.protocol.js";
7
7
  import { NegotiationScreener, configuredScreenMode } from "./negotiation.screen.js";
8
+ import { assessDeadlock, configuredDeadlockShiftEnabled, configuredDeadlockThreshold } from "./negotiation.deadlock.js";
8
9
  import { protocolLogger } from "../shared/observability/protocol.logger.js";
9
10
  const logger = protocolLogger("NegotiationGraph");
10
11
  const initLog = protocolLogger("NegotiationGraph:Init");
@@ -416,6 +417,28 @@ export class NegotiationGraphFactory {
416
417
  && !!state.opportunityId
417
418
  && !(state.turnCount === 0 && !state.isContinuation)
418
419
  && !hasPriorAskUser(state.messages, ownUser.id);
420
+ // ─── Deadlock detection → persuasion→bargaining stance (IND-428) ──────
421
+ // Deterministic trailing-run inspection of the persisted history — no
422
+ // LLM in the decision. Gated on the strict default-off flag AND v2,
423
+ // checked alongside the protocol-version plumbing so v1 semantics stay
424
+ // untouched. Fail-open: any detection error means "no deadlock" and
425
+ // the legacy path proceeds byte-identically. The shift changes the
426
+ // system agent's drafting stance only — allowedActions, the dispatch
427
+ // payload, and all termination rules are untouched.
428
+ let deadlock = null;
429
+ if (version === 'v2' && configuredDeadlockShiftEnabled()) {
430
+ try {
431
+ deadlock = assessDeadlock(history, configuredDeadlockThreshold());
432
+ }
433
+ catch (err) {
434
+ turnLog.warn('Deadlock detection failed; proceeding without mode shift', {
435
+ taskId: state.taskId,
436
+ error: err instanceof Error ? err.message : String(err),
437
+ });
438
+ deadlock = null;
439
+ }
440
+ }
441
+ const bargainingMode = deadlock?.deadlocked === true;
419
442
  // P5.3: the speaker's own negotiator memory (cached per side across
420
443
  // turns). Injected into both the dispatch payload (the user's own
421
444
  // agent — scope-correct) and the system-agent prompt.
@@ -491,6 +514,7 @@ export class NegotiationGraphFactory {
491
514
  isContinuation: state.isContinuation,
492
515
  ...(state.userAnswers.length > 0 && { userAnswers: state.userAnswers }),
493
516
  ...(askUserAvailable && { canAskUser: true }),
517
+ ...(bargainingMode && { bargaining: { consecutiveNonConvergent: deadlock.consecutiveNonConvergent } }),
494
518
  ...(ownMemory.length > 0 && { memory: ownMemory }),
495
519
  });
496
520
  }
@@ -516,6 +540,47 @@ export class NegotiationGraphFactory {
516
540
  });
517
541
  turn = { ...turn, action: fallbackActionFor(version, seat, isFinalTurn) };
518
542
  }
543
+ // ─── Deadlock shift record (IND-428) ───────────────────────────────
544
+ // Applied-stance analytics: recorded once per session, on the first
545
+ // turn actually drafted in the bargaining stance (the system agent —
546
+ // externally dispatched turns never receive the stance). Internal
547
+ // metadata only: persisted to tasks.metadata.deadlockShift via the
548
+ // optional hook; negotiation API surfaces project specific fields and
549
+ // never return task metadata verbatim. Every step fails open.
550
+ const bargainingApplied = bargainingMode && !dispatchResult.handled;
551
+ let deadlockShiftRecord = null;
552
+ if (bargainingApplied && !state.deadlockShift) {
553
+ deadlockShiftRecord = {
554
+ reason: 'consecutive_non_convergent',
555
+ consecutiveNonConvergent: deadlock.consecutiveNonConvergent,
556
+ threshold: deadlock.threshold,
557
+ shiftedAtTurn: state.turnCount,
558
+ seat,
559
+ detectedAt: new Date().toISOString(),
560
+ };
561
+ await database.setTaskDeadlockShift?.(state.taskId, deadlockShiftRecord).catch((err) => {
562
+ turnLog.error('Failed to persist deadlock shift record', { taskId: state.taskId, error: err });
563
+ });
564
+ turnLog.info('negotiation_deadlock_shift', {
565
+ taskId: state.taskId,
566
+ opportunityId: state.opportunityId || undefined,
567
+ seat,
568
+ consecutiveNonConvergent: deadlockShiftRecord.consecutiveNonConvergent,
569
+ threshold: deadlockShiftRecord.threshold,
570
+ turnIndex: state.turnCount,
571
+ });
572
+ if (state.opportunityId) {
573
+ emitWide({
574
+ type: 'negotiation_deadlock_shift',
575
+ opportunityId: state.opportunityId,
576
+ negotiationConversationId: state.conversationId,
577
+ turnIndex: state.turnCount,
578
+ actor: isSource ? 'source' : 'candidate',
579
+ consecutiveNonConvergent: deadlockShiftRecord.consecutiveNonConvergent,
580
+ threshold: deadlockShiftRecord.threshold,
581
+ });
582
+ }
583
+ }
519
584
  const parts = [{ kind: "data", data: turn }];
520
585
  const message = await database.createMessage({
521
586
  conversationId: state.conversationId,
@@ -604,6 +669,7 @@ export class NegotiationGraphFactory {
604
669
  turnCount: state.turnCount + 1,
605
670
  lastTurn: turn,
606
671
  status: 'input_required',
672
+ ...(deadlockShiftRecord && { deadlockShift: deadlockShiftRecord }),
607
673
  };
608
674
  }
609
675
  await database.updateTaskState(state.taskId, "working");
@@ -633,6 +699,7 @@ export class NegotiationGraphFactory {
633
699
  currentSpeaker: (isSource ? "candidate" : "source"),
634
700
  lastTurn: turn,
635
701
  memoryBySide: { [ownSide]: ownMemory },
702
+ ...(deadlockShiftRecord && { deadlockShift: deadlockShiftRecord }),
636
703
  };
637
704
  }
638
705
  catch (err) {