@indexnetwork/protocol 14.3.2-rc.477.1 → 17.0.0-rc.479.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/CHANGELOG.md +141 -0
- package/IMPLEMENTATION.md +50 -52
- package/STABILITY.md +3 -3
- package/dist/chat/chat.agent.js +2 -3
- package/dist/chat/chat.graph.d.ts +41 -1
- package/dist/chat/chat.graph.js +108 -127
- package/dist/chat/negotiator.persona.d.ts +1 -1
- package/dist/chat/negotiator.persona.js +1 -4
- package/dist/chat/negotiator.prompt.js +1 -2
- package/dist/chat/onboarding.persona.js +0 -1
- package/dist/chat/reporter.persona.js +0 -1
- package/dist/chat/signal.persona.js +0 -1
- package/dist/contacts/application/contact.tools.d.ts +6 -9
- package/dist/contacts/application/contact.tools.js +11 -92
- package/dist/contacts/application/index.d.ts +2 -14
- package/dist/contacts/application/index.js +2 -13
- package/dist/contacts/domain/contact.types.d.ts +0 -23
- package/dist/contacts/domain/index.d.ts +2 -6
- package/dist/contacts/index.d.ts +1 -1
- package/dist/contacts/index.js +1 -1
- package/dist/contacts/ports/contact.repository.port.d.ts +5 -12
- package/dist/contacts/ports/contact.repository.port.js +4 -6
- package/dist/contacts/ports/contact.tools.port.d.ts +1 -3
- package/dist/contacts/ports/contact.tools.port.js +1 -2
- package/dist/contacts/ports/index.d.ts +1 -1
- package/dist/contacts/ports/index.js +1 -1
- package/dist/discovery/hyde.frame.d.ts +4 -4
- package/dist/discovery/hyde.graph.d.ts +71 -12
- package/dist/discovery/hyde.graph.js +337 -335
- package/dist/discovery/lens.inferrer.d.ts +6 -6
- package/dist/enrichment/enrichment.graph.d.ts +127 -9
- package/dist/enrichment/enrichment.graph.js +633 -655
- package/dist/enrichment/enrichment.state.d.ts +1 -1
- package/dist/enrichment/enrichment.tools.context-read.d.ts +10 -0
- package/dist/enrichment/enrichment.tools.context-read.js +353 -0
- package/dist/enrichment/enrichment.tools.context-write.d.ts +9 -0
- package/dist/enrichment/enrichment.tools.context-write.js +417 -0
- package/dist/enrichment/enrichment.tools.d.ts +11 -1
- package/dist/enrichment/enrichment.tools.helpers.d.ts +139 -0
- package/dist/enrichment/enrichment.tools.helpers.js +234 -0
- package/dist/enrichment/enrichment.tools.js +16 -975
- package/dist/index.d.ts +27 -50
- package/dist/index.js +17 -28
- package/dist/intents/application/intent.graph.d.ts +71 -67
- package/dist/intents/application/intent.graph.execute.d.ts +59 -0
- package/dist/intents/application/intent.graph.execute.js +301 -0
- package/dist/intents/application/intent.graph.infer.d.ts +44 -0
- package/dist/intents/application/intent.graph.infer.js +97 -0
- package/dist/intents/application/intent.graph.js +96 -888
- package/dist/intents/application/intent.graph.reconcile.d.ts +71 -0
- package/dist/intents/application/intent.graph.reconcile.js +274 -0
- package/dist/intents/application/intent.graph.shared.d.ts +70 -0
- package/dist/intents/application/intent.graph.shared.js +153 -0
- package/dist/intents/domain/intent.state.d.ts +1 -1
- package/dist/maintenance/maintenance.graph.d.ts +66 -3
- package/dist/maintenance/maintenance.graph.js +155 -156
- package/dist/mcp/mcp.authorization-policy.d.ts +24 -28
- package/dist/mcp/mcp.authorization-policy.js +14 -34
- package/dist/mcp/mcp.server.d.ts +3 -3
- package/dist/mcp/mcp.server.js +14 -20
- package/dist/negotiations/application/negotiation.candidates.d.ts +83 -0
- package/dist/negotiations/application/negotiation.candidates.js +162 -0
- package/dist/negotiations/application/negotiation.graph.d.ts +91 -157
- package/dist/negotiations/application/negotiation.graph.finalize.d.ts +5 -0
- package/dist/negotiations/application/negotiation.graph.finalize.js +280 -0
- package/dist/negotiations/application/negotiation.graph.init.d.ts +54 -0
- package/dist/negotiations/application/negotiation.graph.init.js +227 -0
- package/dist/negotiations/application/negotiation.graph.js +69 -1388
- package/dist/negotiations/application/negotiation.graph.screen.d.ts +23 -0
- package/dist/negotiations/application/negotiation.graph.screen.js +108 -0
- package/dist/negotiations/application/negotiation.graph.shared.d.ts +75 -0
- package/dist/negotiations/application/negotiation.graph.shared.js +125 -0
- package/dist/negotiations/application/negotiation.graph.turn.d.ts +105 -0
- package/dist/negotiations/application/negotiation.graph.turn.js +484 -0
- package/dist/negotiations/domain/negotiation.state.d.ts +1 -1
- package/dist/negotiations/domain/negotiation.state.js +0 -1
- package/dist/networks/application/indexer.graph.d.ts +165 -7
- package/dist/networks/application/indexer.graph.js +339 -388
- package/dist/networks/application/indexer.state.d.ts +1 -1
- package/dist/networks/application/membership.graph.d.ts +83 -5
- package/dist/networks/application/membership.graph.js +177 -207
- package/dist/networks/application/network.graph.d.ts +148 -5
- package/dist/networks/application/network.graph.js +249 -278
- package/dist/networks/domain/membership.state.d.ts +1 -1
- package/dist/networks/domain/network.state.d.ts +1 -1
- package/dist/opportunities/application/delivery-card.cache.d.ts +1 -1
- package/dist/opportunities/application/delivery-card.cache.js +2 -2
- package/dist/opportunities/application/index.d.ts +2 -2
- package/dist/opportunities/application/index.js +2 -2
- package/dist/opportunities/application/opportunity.evaluator.js +1 -1
- package/dist/opportunities/application/opportunity.graph.d.ts +686 -473
- package/dist/opportunities/application/opportunity.graph.discovery-strategies.d.ts +109 -0
- package/dist/opportunities/application/opportunity.graph.discovery-strategies.js +451 -0
- package/dist/opportunities/application/opportunity.graph.discovery.d.ts +69 -0
- package/dist/opportunities/application/opportunity.graph.discovery.js +397 -0
- package/dist/opportunities/application/opportunity.graph.evaluation.d.ts +82 -0
- package/dist/opportunities/application/opportunity.graph.evaluation.js +608 -0
- package/dist/opportunities/application/opportunity.graph.js +120 -3690
- package/dist/opportunities/application/opportunity.graph.modes.d.ts +538 -0
- package/dist/opportunities/application/opportunity.graph.modes.js +538 -0
- package/dist/opportunities/application/opportunity.graph.negotiate.d.ts +109 -0
- package/dist/opportunities/application/opportunity.graph.negotiate.js +392 -0
- package/dist/opportunities/application/opportunity.graph.persist-node.d.ts +93 -0
- package/dist/opportunities/application/opportunity.graph.persist-node.js +765 -0
- package/dist/opportunities/application/opportunity.graph.prep.d.ts +150 -0
- package/dist/opportunities/application/opportunity.graph.prep.js +381 -0
- package/dist/opportunities/application/opportunity.graph.shared.d.ts +173 -0
- package/dist/opportunities/application/opportunity.graph.shared.js +199 -0
- package/dist/opportunities/application/opportunity.presentation.d.ts +399 -0
- package/dist/opportunities/application/{opportunity.presenter.js → opportunity.presentation.js} +735 -9
- package/dist/opportunities/application/opportunity.tools.cards.d.ts +152 -0
- package/dist/opportunities/application/opportunity.tools.cards.js +235 -0
- package/dist/opportunities/application/opportunity.tools.d.ts +8 -114
- package/dist/opportunities/application/opportunity.tools.js +28 -711
- package/dist/opportunities/application/opportunity.tools.list.d.ts +10 -0
- package/dist/opportunities/application/opportunity.tools.list.js +493 -0
- package/dist/opportunities/domain/index.d.ts +3 -3
- package/dist/opportunities/domain/index.js +3 -3
- package/dist/opportunities/domain/opportunity.state.d.ts +19 -19
- package/dist/opportunities/index.d.ts +6 -6
- package/dist/opportunities/index.js +4 -4
- package/dist/opportunities/ports/opportunity.tools.port.d.ts +1 -1
- package/dist/opportunities/radar/radar.graph.d.ts +57 -13
- package/dist/opportunities/radar/radar.graph.js +470 -471
- package/dist/premises/premise.graph.d.ts +88 -20
- package/dist/premises/premise.graph.js +207 -218
- package/dist/questions/domain/question.schema.d.ts +40 -40
- package/dist/shared/agent/tool.factory.js +0 -8
- package/dist/shared/agent/tool.helpers.d.ts +21 -45
- package/dist/shared/agent/tool.helpers.js +1 -2
- package/dist/shared/agent/tool.registry.d.ts +4 -3
- package/dist/shared/agent/tool.registry.js +2 -4
- package/dist/shared/agent/tool.runtime.js +0 -2
- package/dist/shared/agent/utility.tools.js +9 -13
- package/dist/shared/interfaces/database.capabilities.d.ts +100 -0
- package/dist/shared/interfaces/database.capabilities.js +7 -0
- package/dist/shared/interfaces/database.entities.d.ts +533 -0
- package/dist/shared/interfaces/database.entities.js +10 -0
- package/dist/shared/interfaces/database.identity-queries.d.ts +294 -0
- package/dist/shared/interfaces/database.identity-queries.js +4 -0
- package/dist/shared/interfaces/database.interface.d.ts +15 -2277
- package/dist/shared/interfaces/database.interface.js +8 -0
- package/dist/shared/interfaces/database.member-queries.d.ts +221 -0
- package/dist/shared/interfaces/database.member-queries.js +4 -0
- package/dist/shared/interfaces/database.negotiation.d.ts +305 -0
- package/dist/shared/interfaces/database.negotiation.js +26 -0
- package/dist/shared/interfaces/database.network-queries.d.ts +277 -0
- package/dist/shared/interfaces/database.network-queries.js +4 -0
- package/dist/shared/interfaces/database.opportunity-queries.d.ts +285 -0
- package/dist/shared/interfaces/database.opportunity-queries.js +4 -0
- package/dist/shared/interfaces/database.port.d.ts +322 -0
- package/dist/shared/interfaces/database.port.js +29 -0
- package/dist/shared/schemas/discovery-question.schema.d.ts +14 -14
- package/dist/shared/schemas/negotiation-digest.schema.d.ts +2 -2
- package/package.json +2 -15
- package/dist/contacts/application/contact.inviter.d.ts +0 -49
- package/dist/contacts/application/contact.inviter.js +0 -64
- package/dist/integrations/application/index.d.ts +0 -14
- package/dist/integrations/application/index.js +0 -14
- package/dist/integrations/application/integration.tools.d.ts +0 -27
- package/dist/integrations/application/integration.tools.js +0 -98
- package/dist/integrations/domain/index.d.ts +0 -16
- package/dist/integrations/domain/index.js +0 -1
- package/dist/integrations/domain/integration.types.d.ts +0 -51
- package/dist/integrations/domain/integration.types.js +0 -9
- package/dist/integrations/index.d.ts +0 -10
- package/dist/integrations/index.js +0 -8
- package/dist/integrations/ports/index.d.ts +0 -25
- package/dist/integrations/ports/index.js +0 -23
- package/dist/integrations/ports/integration.adapter.port.d.ts +0 -62
- package/dist/integrations/ports/integration.adapter.port.js +0 -15
- package/dist/integrations/ports/integration.importer.port.d.ts +0 -31
- package/dist/integrations/ports/integration.importer.port.js +0 -15
- package/dist/integrations/ports/integration.tools.port.d.ts +0 -25
- package/dist/integrations/ports/integration.tools.port.js +0 -18
- package/dist/opportunities/application/opportunity.card-presentation.d.ts +0 -44
- package/dist/opportunities/application/opportunity.card-presentation.js +0 -93
- package/dist/opportunities/application/opportunity.presenter.d.ts +0 -156
- package/dist/opportunities/domain/opportunity.presentation-cache.d.ts +0 -5
- package/dist/opportunities/domain/opportunity.presentation-cache.js +0 -11
- package/dist/opportunities/domain/opportunity.presentation.d.ts +0 -76
- package/dist/opportunities/domain/opportunity.presentation.js +0 -516
- package/dist/opportunities/domain/opportunity.safe-presentation.d.ts +0 -104
- package/dist/opportunities/domain/opportunity.safe-presentation.js +0 -102
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Negotiation graph, stage 2: the outreach gate.
|
|
3
|
+
*/
|
|
4
|
+
import { type ScreenDecisionRecord } from "./negotiation.screen.js";
|
|
5
|
+
import type { NegotiationGraphDeps, NegotiationState } from "./negotiation.graph.shared.js";
|
|
6
|
+
/**
|
|
7
|
+
* Screen node (P2.1) — the outreach gate. Runs between init and the first
|
|
8
|
+
* turn on FRESH negotiations only (routing skips it on continuations and
|
|
9
|
+
* when NEGOTIATION_SCREEN_MODE=off). The reaching client's negotiator
|
|
10
|
+
* decides whether the match is worth its client's name; in shadow mode the
|
|
11
|
+
* decision is recorded (task metadata + trace event + log line) but never
|
|
12
|
+
* blocks — the negotiation always proceeds to the first turn. In enforce
|
|
13
|
+
* mode (P2.2) a `pass` routes straight to finalize: zero turns, zero
|
|
14
|
+
* counterparty involvement, outcome `reason: "screened_out"`, opportunity
|
|
15
|
+
* quietly `rejected` (init had already flipped it to `negotiating`).
|
|
16
|
+
* A failed screen still fails OPEN in every mode.
|
|
17
|
+
*/
|
|
18
|
+
export declare function screenNode(state: NegotiationState, deps: NegotiationGraphDeps): Promise<{
|
|
19
|
+
screenDecision: ScreenDecisionRecord;
|
|
20
|
+
memoryBySide: {
|
|
21
|
+
[x: string]: import("../index.js").NegotiatorMemoryEntry[];
|
|
22
|
+
};
|
|
23
|
+
}>;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Negotiation graph, stage 2: the outreach gate.
|
|
3
|
+
*/
|
|
4
|
+
import { requestContext } from "../../shared/observability/request-context.js";
|
|
5
|
+
import { configuredScreenMode } from "../domain/negotiation.screen.contracts.js";
|
|
6
|
+
import { buildAttributedDialogue, memoryQueryText, retrieveMemory, screenNodeLog, turnsFromMessages } from "./negotiation.graph.shared.js";
|
|
7
|
+
/**
|
|
8
|
+
* Screen node (P2.1) — the outreach gate. Runs between init and the first
|
|
9
|
+
* turn on FRESH negotiations only (routing skips it on continuations and
|
|
10
|
+
* when NEGOTIATION_SCREEN_MODE=off). The reaching client's negotiator
|
|
11
|
+
* decides whether the match is worth its client's name; in shadow mode the
|
|
12
|
+
* decision is recorded (task metadata + trace event + log line) but never
|
|
13
|
+
* blocks — the negotiation always proceeds to the first turn. In enforce
|
|
14
|
+
* mode (P2.2) a `pass` routes straight to finalize: zero turns, zero
|
|
15
|
+
* counterparty involvement, outcome `reason: "screened_out"`, opportunity
|
|
16
|
+
* quietly `rejected` (init had already flipped it to `negotiating`).
|
|
17
|
+
* A failed screen still fails OPEN in every mode.
|
|
18
|
+
*/
|
|
19
|
+
export async function screenNode(state, deps) {
|
|
20
|
+
const traceEmitter = requestContext.getStore()?.traceEmitter;
|
|
21
|
+
const emitWide = (event) => traceEmitter?.(event);
|
|
22
|
+
const mode = configuredScreenMode();
|
|
23
|
+
const start = Date.now();
|
|
24
|
+
// The client is the initiator seat's user — the side whose negotiator is
|
|
25
|
+
// reaching out. Fresh runs stamp initiatorUserId in init; fall back to
|
|
26
|
+
// sourceUser (what the stamp defaults to anyway).
|
|
27
|
+
const initiatorId = state.initiatorUserId ?? state.sourceUser.id;
|
|
28
|
+
const clientIsSource = initiatorId !== state.candidateUser.id;
|
|
29
|
+
const clientUser = clientIsSource ? state.sourceUser : state.candidateUser;
|
|
30
|
+
const counterpartyUser = clientIsSource ? state.candidateUser : state.sourceUser;
|
|
31
|
+
// P5.3: the client's own negotiator memory informs the outreach gate.
|
|
32
|
+
// Cached into state so the client's first turn reuses it.
|
|
33
|
+
const clientSide = clientIsSource ? "source" : "candidate";
|
|
34
|
+
const clientMemory = state.memoryBySide?.[clientSide]
|
|
35
|
+
?? (deps.memoryRetrieve
|
|
36
|
+
? await retrieveMemory(deps, clientUser.id, counterpartyUser.id, memoryQueryText(state, counterpartyUser), "screen")
|
|
37
|
+
: []);
|
|
38
|
+
let decision;
|
|
39
|
+
let failedOpen = false;
|
|
40
|
+
let screenError;
|
|
41
|
+
try {
|
|
42
|
+
const counterpartyContext = (await deps.database.getUserContext(counterpartyUser.id, null).catch(() => null))?.text ?? "";
|
|
43
|
+
const priorDialogueAttributed = buildAttributedDialogue(state);
|
|
44
|
+
decision = await deps.screener.invoke({
|
|
45
|
+
clientUser,
|
|
46
|
+
counterpartyUser,
|
|
47
|
+
...(counterpartyContext && { counterpartyContext }),
|
|
48
|
+
...(clientMemory.length > 0 && { memory: clientMemory }),
|
|
49
|
+
// discoveryQuery belongs to the discovery session's source user; only
|
|
50
|
+
// meaningful for the client when the client holds the source side.
|
|
51
|
+
...(clientIsSource && state.discoveryQuery && { discoveryQuery: state.discoveryQuery }),
|
|
52
|
+
seedAssessment: state.seedAssessment,
|
|
53
|
+
indexContext: state.indexContext,
|
|
54
|
+
isContinuation: state.isContinuation,
|
|
55
|
+
...(state.messages.length > 0 && { priorDialogue: turnsFromMessages(state.messages) }),
|
|
56
|
+
...(priorDialogueAttributed && { priorDialogueAttributed }),
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
// Fail open: a screen failure must never block a negotiation.
|
|
61
|
+
failedOpen = true;
|
|
62
|
+
screenError = err instanceof Error ? err.message : String(err);
|
|
63
|
+
screenNodeLog.warn("Screen failed; proceeding open (reach_out)", {
|
|
64
|
+
taskId: state.taskId,
|
|
65
|
+
opportunityId: state.opportunityId || undefined,
|
|
66
|
+
error: screenError,
|
|
67
|
+
});
|
|
68
|
+
decision = {
|
|
69
|
+
decision: "reach_out",
|
|
70
|
+
reasoning: `screen_error: ${screenError}`,
|
|
71
|
+
evidence: { counterpartyPremiseFit: "", intentAlignment: "" },
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
const durationMs = Date.now() - start;
|
|
75
|
+
const record = {
|
|
76
|
+
...decision,
|
|
77
|
+
mode,
|
|
78
|
+
...(failedOpen && { failedOpen, error: screenError }),
|
|
79
|
+
screenedAt: new Date().toISOString(),
|
|
80
|
+
durationMs,
|
|
81
|
+
};
|
|
82
|
+
await deps.database.setTaskScreenDecision?.(state.taskId, record, state.continuationExecution).catch((err) => {
|
|
83
|
+
screenNodeLog.error("Failed to persist screen decision", { taskId: state.taskId, error: err });
|
|
84
|
+
});
|
|
85
|
+
screenNodeLog.info("negotiation_screen", {
|
|
86
|
+
taskId: state.taskId,
|
|
87
|
+
opportunityId: state.opportunityId || undefined,
|
|
88
|
+
decision: decision.decision,
|
|
89
|
+
mode,
|
|
90
|
+
failedOpen,
|
|
91
|
+
durationMs,
|
|
92
|
+
});
|
|
93
|
+
if (state.opportunityId) {
|
|
94
|
+
emitWide({
|
|
95
|
+
type: "negotiation_screen",
|
|
96
|
+
opportunityId: state.opportunityId,
|
|
97
|
+
negotiationConversationId: state.conversationId,
|
|
98
|
+
decision: decision.decision,
|
|
99
|
+
reasoning: decision.reasoning,
|
|
100
|
+
mode,
|
|
101
|
+
failedOpen,
|
|
102
|
+
durationMs,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
// Routing happens on the conditional edge: shadow always proceeds to
|
|
106
|
+
// the first turn; enforce routes a (non-failed-open) pass to finalize.
|
|
107
|
+
return { screenDecision: record, memoryBySide: { [clientSide]: clientMemory } };
|
|
108
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared vocabulary for the negotiation graph's nodes.
|
|
3
|
+
*
|
|
4
|
+
* The nodes were closures inside `NegotiationGraphFactory.createGraph()`,
|
|
5
|
+
* capturing the injected database, dispatcher and queues. They are top-level
|
|
6
|
+
* functions now, each taking an explicit {@link NegotiationGraphDeps}; this
|
|
7
|
+
* module owns the bag itself and the helpers more than one node needs.
|
|
8
|
+
*/
|
|
9
|
+
import type { NegotiationGraphDatabase } from "../../shared/interfaces/database.interface.js";
|
|
10
|
+
import type { NegotiationTimeoutQueue } from "../../shared/interfaces/negotiation-events.interface.js";
|
|
11
|
+
import type { AgentDispatcher } from "../../shared/interfaces/agent-dispatcher.interface.js";
|
|
12
|
+
import { NegotiationGraphState, type NegotiationTurn, type UserNegotiationContext } from "../domain/negotiation.state.js";
|
|
13
|
+
import { IndexNegotiator } from "./negotiation.agent.js";
|
|
14
|
+
import { NegotiationScreener } from "./negotiation.screen.js";
|
|
15
|
+
import type { QuestionerEnqueueFn } from "../../questions/index.js";
|
|
16
|
+
import type { ReflectEnqueueFn } from "./negotiation.reflect.js";
|
|
17
|
+
import type { NegotiatorMemoryEntry, NegotiatorMemoryRetrieveFn, NegotiatorMemoryScope } from "../domain/negotiation.memory.js";
|
|
18
|
+
import { type AttributedPriorDialogue, type TaskAttribution } from '../negotiation.attribution.js';
|
|
19
|
+
/** The graph's channel state, as every node sees it. */
|
|
20
|
+
export type NegotiationState = typeof NegotiationGraphState.State;
|
|
21
|
+
/** Everything the negotiation nodes reach for. Composed once by the factory. */
|
|
22
|
+
export interface NegotiationGraphDeps {
|
|
23
|
+
database: NegotiationGraphDatabase;
|
|
24
|
+
dispatcher: AgentDispatcher;
|
|
25
|
+
timeoutQueue?: NegotiationTimeoutQueue;
|
|
26
|
+
questionerEnqueue?: QuestionerEnqueueFn;
|
|
27
|
+
reflectEnqueue?: ReflectEnqueueFn;
|
|
28
|
+
memoryRetrieve?: NegotiatorMemoryRetrieveFn;
|
|
29
|
+
/** In-process negotiator used when no personal agent answers. */
|
|
30
|
+
systemAgent: IndexNegotiator;
|
|
31
|
+
/** Outreach gate for fresh negotiations. */
|
|
32
|
+
screener: NegotiationScreener;
|
|
33
|
+
}
|
|
34
|
+
export declare const logger: import("../../shared/observability/log.js").LoggerWithSource;
|
|
35
|
+
export declare const initLog: import("../../shared/observability/log.js").LoggerWithSource;
|
|
36
|
+
export declare const screenNodeLog: import("../../shared/observability/log.js").LoggerWithSource;
|
|
37
|
+
export declare const turnLog: import("../../shared/observability/log.js").LoggerWithSource;
|
|
38
|
+
export declare const finalizeLog: import("../../shared/observability/log.js").LoggerWithSource;
|
|
39
|
+
export declare const negotiateCandidatesLog: import("../../shared/observability/log.js").LoggerWithSource;
|
|
40
|
+
/** Extracts the ordered NegotiationTurn list from A2A message data parts. */
|
|
41
|
+
export declare function turnsFromMessages(messages: Array<{
|
|
42
|
+
parts: unknown[];
|
|
43
|
+
}>): NegotiationTurn[];
|
|
44
|
+
/**
|
|
45
|
+
* Whether `userId`'s side has already spent its one `ask_user` client
|
|
46
|
+
* consultation in this conversation (P3.2 rationing: max one per negotiation
|
|
47
|
+
* per side, checked against the full message history so continuations count
|
|
48
|
+
* prior sessions' consultations too).
|
|
49
|
+
*/
|
|
50
|
+
export declare function hasPriorAskUser(messages: Array<{
|
|
51
|
+
senderId: string;
|
|
52
|
+
parts: unknown[];
|
|
53
|
+
}>, userId: string): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* P5.3 memory retrieval — never throws, never blocks a negotiation. The
|
|
56
|
+
* injected fn already resolves [] when NEGOTIATOR_MEMORY_INJECT is off;
|
|
57
|
+
* this wrapper adds the graph-side failure guard.
|
|
58
|
+
*/
|
|
59
|
+
export declare function retrieveMemory(deps: NegotiationGraphDeps, userId: string, counterpartyUserId: string, queryText: string, scope: NegotiatorMemoryScope): Promise<NegotiatorMemoryEntry[]>;
|
|
60
|
+
/** Similarity query text: seed reasoning + counterparty context. */
|
|
61
|
+
export declare function memoryQueryText(state: NegotiationState, counterparty: UserNegotiationContext): string;
|
|
62
|
+
/**
|
|
63
|
+
* IND-569: resolve a prior negotiation task's attribution metadata for the
|
|
64
|
+
* per-opportunity prior-dialogue labels. Never throws — any failure returns
|
|
65
|
+
* null so the turns degrade to the unattributed block instead of leaking
|
|
66
|
+
* into the current opportunity's context.
|
|
67
|
+
*/
|
|
68
|
+
export declare function resolveTaskAttribution(deps: NegotiationGraphDeps, taskId: string): Promise<TaskAttribution | null>;
|
|
69
|
+
/**
|
|
70
|
+
* IND-569: build the attributed prior dialogue passed to the screener and
|
|
71
|
+
* turn prompts. Combines the immutable seeded attribution (earlier + legacy
|
|
72
|
+
* unattributed blocks, resolved once in init) with this session's own turns
|
|
73
|
+
* (task-id-matched). Null when there is no seeded attribution.
|
|
74
|
+
*/
|
|
75
|
+
export declare function buildAttributedDialogue(state: NegotiationState): AttributedPriorDialogue | null;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared vocabulary for the negotiation graph's nodes.
|
|
3
|
+
*
|
|
4
|
+
* The nodes were closures inside `NegotiationGraphFactory.createGraph()`,
|
|
5
|
+
* capturing the injected database, dispatcher and queues. They are top-level
|
|
6
|
+
* functions now, each taking an explicit {@link NegotiationGraphDeps}; this
|
|
7
|
+
* module owns the bag itself and the helpers more than one node needs.
|
|
8
|
+
*/
|
|
9
|
+
import { protocolLogger } from "../../shared/observability/protocol.logger.js";
|
|
10
|
+
import { attributedDialogueIsEmpty, combineAttributedDialogue } from '../negotiation.attribution.js';
|
|
11
|
+
export const logger = protocolLogger("NegotiationGraph");
|
|
12
|
+
export const initLog = protocolLogger("NegotiationGraph:Init");
|
|
13
|
+
export const screenNodeLog = protocolLogger("NegotiationGraph:Screen");
|
|
14
|
+
export const turnLog = protocolLogger("NegotiationGraph:Turn");
|
|
15
|
+
export const finalizeLog = protocolLogger("NegotiationGraph:Finalize");
|
|
16
|
+
export const negotiateCandidatesLog = protocolLogger("NegotiationGraph:negotiateCandidates");
|
|
17
|
+
/** Extracts the ordered NegotiationTurn list from A2A message data parts. */
|
|
18
|
+
export function turnsFromMessages(messages) {
|
|
19
|
+
return messages
|
|
20
|
+
.map((m) => {
|
|
21
|
+
const dataPart = m.parts.find((p) => p.kind === "data");
|
|
22
|
+
return dataPart?.data;
|
|
23
|
+
})
|
|
24
|
+
.filter(Boolean);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Whether `userId`'s side has already spent its one `ask_user` client
|
|
28
|
+
* consultation in this conversation (P3.2 rationing: max one per negotiation
|
|
29
|
+
* per side, checked against the full message history so continuations count
|
|
30
|
+
* prior sessions' consultations too).
|
|
31
|
+
*/
|
|
32
|
+
export function hasPriorAskUser(messages, userId) {
|
|
33
|
+
const sender = `agent:${userId}`;
|
|
34
|
+
return messages.some((m) => {
|
|
35
|
+
if (m.senderId !== sender)
|
|
36
|
+
return false;
|
|
37
|
+
const dataPart = m.parts.find((p) => p.kind === "data");
|
|
38
|
+
return dataPart?.data?.action === "ask_user";
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* P5.3 memory retrieval — never throws, never blocks a negotiation. The
|
|
43
|
+
* injected fn already resolves [] when NEGOTIATOR_MEMORY_INJECT is off;
|
|
44
|
+
* this wrapper adds the graph-side failure guard.
|
|
45
|
+
*/
|
|
46
|
+
export async function retrieveMemory(deps, userId, counterpartyUserId, queryText, scope) {
|
|
47
|
+
if (!deps.memoryRetrieve)
|
|
48
|
+
return [];
|
|
49
|
+
try {
|
|
50
|
+
return await deps.memoryRetrieve({ userId, counterpartyUserId, queryText, scope });
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
logger.warn("Negotiator memory retrieval failed; proceeding without memory", {
|
|
54
|
+
userId,
|
|
55
|
+
scope,
|
|
56
|
+
error: err instanceof Error ? err.message : String(err),
|
|
57
|
+
});
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/** Similarity query text: seed reasoning + counterparty context. */
|
|
62
|
+
export function memoryQueryText(state, counterparty) {
|
|
63
|
+
return [
|
|
64
|
+
state.discoveryQuery ? `Search: ${state.discoveryQuery}` : "",
|
|
65
|
+
state.seedAssessment?.reasoning ?? "",
|
|
66
|
+
counterparty?.profile?.name ?? "",
|
|
67
|
+
counterparty?.profile?.bio ?? "",
|
|
68
|
+
(counterparty?.intents ?? []).slice(0, 5).map((i) => `${i.title}: ${i.description}`).join("\n"),
|
|
69
|
+
].filter(Boolean).join("\n");
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* IND-569: resolve a prior negotiation task's attribution metadata for the
|
|
73
|
+
* per-opportunity prior-dialogue labels. Never throws — any failure returns
|
|
74
|
+
* null so the turns degrade to the unattributed block instead of leaking
|
|
75
|
+
* into the current opportunity's context.
|
|
76
|
+
*/
|
|
77
|
+
export async function resolveTaskAttribution(deps, taskId) {
|
|
78
|
+
try {
|
|
79
|
+
const task = await deps.database.getTask(taskId);
|
|
80
|
+
if (!task)
|
|
81
|
+
return null;
|
|
82
|
+
const md = (task.metadata ?? {});
|
|
83
|
+
const opportunityId = typeof md.opportunityId === 'string' && md.opportunityId.length > 0 ? md.opportunityId : null;
|
|
84
|
+
const snapshots = Array.isArray(md.intentSnapshots) ? md.intentSnapshots : [];
|
|
85
|
+
const sourceIntentId = typeof md.sourceIntentId === 'string' ? md.sourceIntentId : null;
|
|
86
|
+
const snap = snapshots.find((s) => s && s.intentId === sourceIntentId) ?? snapshots[0];
|
|
87
|
+
const opportunityTitle = snap && typeof snap.title === 'string' && snap.title.trim().length > 0 ? snap.title : null;
|
|
88
|
+
let outcome = null;
|
|
89
|
+
try {
|
|
90
|
+
const artifacts = await deps.database.getArtifactsForTask(taskId);
|
|
91
|
+
const outArtifact = artifacts.find((a) => a.name === 'negotiation-outcome');
|
|
92
|
+
if (outArtifact) {
|
|
93
|
+
const firstPart = Array.isArray(outArtifact.parts) ? outArtifact.parts[0] : undefined;
|
|
94
|
+
const data = firstPart?.data;
|
|
95
|
+
if (data && typeof data.hasOpportunity === 'boolean') {
|
|
96
|
+
outcome = data.hasOpportunity ? 'accepted' : (data.reason === 'screened_out' ? 'not pursued' : 'declined');
|
|
97
|
+
}
|
|
98
|
+
else if (typeof outArtifact.metadata?.continuationOutcome === 'string') {
|
|
99
|
+
outcome = outArtifact.metadata.continuationOutcome;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
catch { /* outcome stays null; header degrades to "outcome unknown" */ }
|
|
104
|
+
const concludedAt = task.updatedAt instanceof Date
|
|
105
|
+
? task.updatedAt.toISOString()
|
|
106
|
+
: (task.updatedAt ? new Date(task.updatedAt).toISOString() : null);
|
|
107
|
+
return { opportunityId, opportunityTitle, outcome, concludedAt };
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* IND-569: build the attributed prior dialogue passed to the screener and
|
|
115
|
+
* turn prompts. Combines the immutable seeded attribution (earlier + legacy
|
|
116
|
+
* unattributed blocks, resolved once in init) with this session's own turns
|
|
117
|
+
* (task-id-matched). Null when there is no seeded attribution.
|
|
118
|
+
*/
|
|
119
|
+
export function buildAttributedDialogue(state) {
|
|
120
|
+
if (!state.isContinuation || !state.priorAttribution)
|
|
121
|
+
return null;
|
|
122
|
+
const currentSessionTurns = turnsFromMessages(state.messages.filter((m) => m.taskId === state.taskId));
|
|
123
|
+
const dialogue = combineAttributedDialogue(state.priorAttribution, currentSessionTurns);
|
|
124
|
+
return attributedDialogueIsEmpty(dialogue) ? null : dialogue;
|
|
125
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Negotiation graph, stage 3: one negotiator turn.
|
|
3
|
+
*/
|
|
4
|
+
import { type DeadlockShiftRecord } from "../domain/negotiation.deadlock.js";
|
|
5
|
+
import type { NegotiationGraphDeps, NegotiationState } from "./negotiation.graph.shared.js";
|
|
6
|
+
export declare function turnNode(state: NegotiationState, deps: NegotiationGraphDeps): Promise<{
|
|
7
|
+
status: "waiting_for_agent";
|
|
8
|
+
lastTurn?: undefined;
|
|
9
|
+
firstTurnScreenedOut?: undefined;
|
|
10
|
+
turnCount?: undefined;
|
|
11
|
+
error?: undefined;
|
|
12
|
+
} | {
|
|
13
|
+
lastTurn: {
|
|
14
|
+
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline" | "ask_user";
|
|
15
|
+
assessment: {
|
|
16
|
+
reasoning: string;
|
|
17
|
+
suggestedRoles: {
|
|
18
|
+
ownUser: "agent" | "patient" | "peer";
|
|
19
|
+
otherUser: "agent" | "patient" | "peer";
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
message?: string | null | undefined;
|
|
23
|
+
askUser?: {
|
|
24
|
+
reason: "unresolved_owner_constraint" | "consequential_disclosure_permission" | "repeated_non_convergence" | "insufficient_commitment_authority";
|
|
25
|
+
} | null | undefined;
|
|
26
|
+
};
|
|
27
|
+
firstTurnScreenedOut: boolean;
|
|
28
|
+
status?: undefined;
|
|
29
|
+
turnCount?: undefined;
|
|
30
|
+
error?: undefined;
|
|
31
|
+
} | {
|
|
32
|
+
deadlockShift?: DeadlockShiftRecord | undefined;
|
|
33
|
+
messages: {
|
|
34
|
+
id: string;
|
|
35
|
+
senderId: string;
|
|
36
|
+
role: "agent";
|
|
37
|
+
parts: unknown;
|
|
38
|
+
createdAt: Date;
|
|
39
|
+
}[];
|
|
40
|
+
turnCount: number;
|
|
41
|
+
lastTurn: {
|
|
42
|
+
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline" | "ask_user";
|
|
43
|
+
assessment: {
|
|
44
|
+
reasoning: string;
|
|
45
|
+
suggestedRoles: {
|
|
46
|
+
ownUser: "agent" | "patient" | "peer";
|
|
47
|
+
otherUser: "agent" | "patient" | "peer";
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
message?: string | null | undefined;
|
|
51
|
+
askUser?: {
|
|
52
|
+
reason: "unresolved_owner_constraint" | "consequential_disclosure_permission" | "repeated_non_convergence" | "insufficient_commitment_authority";
|
|
53
|
+
} | null | undefined;
|
|
54
|
+
};
|
|
55
|
+
status: "input_required";
|
|
56
|
+
firstTurnScreenedOut?: undefined;
|
|
57
|
+
error?: undefined;
|
|
58
|
+
} | {
|
|
59
|
+
deadlockShift?: DeadlockShiftRecord | undefined;
|
|
60
|
+
outreachOpened?: boolean | undefined;
|
|
61
|
+
messages: {
|
|
62
|
+
id: string;
|
|
63
|
+
senderId: string;
|
|
64
|
+
role: "agent";
|
|
65
|
+
parts: unknown;
|
|
66
|
+
createdAt: Date;
|
|
67
|
+
}[];
|
|
68
|
+
turnCount: number;
|
|
69
|
+
currentSpeaker: "source" | "candidate";
|
|
70
|
+
lastTurn: {
|
|
71
|
+
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline" | "ask_user";
|
|
72
|
+
assessment: {
|
|
73
|
+
reasoning: string;
|
|
74
|
+
suggestedRoles: {
|
|
75
|
+
ownUser: "agent" | "patient" | "peer";
|
|
76
|
+
otherUser: "agent" | "patient" | "peer";
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
message?: string | null | undefined;
|
|
80
|
+
askUser?: {
|
|
81
|
+
reason: "unresolved_owner_constraint" | "consequential_disclosure_permission" | "repeated_non_convergence" | "insufficient_commitment_authority";
|
|
82
|
+
} | null | undefined;
|
|
83
|
+
};
|
|
84
|
+
memoryBySide: {
|
|
85
|
+
[x: string]: import("../index.js").NegotiatorMemoryEntry[];
|
|
86
|
+
};
|
|
87
|
+
status?: undefined;
|
|
88
|
+
firstTurnScreenedOut?: undefined;
|
|
89
|
+
error?: undefined;
|
|
90
|
+
} | {
|
|
91
|
+
lastTurn: {
|
|
92
|
+
action: "propose" | "accept" | "reject" | "counter" | "question" | "outreach" | "withdraw" | "decline" | "ask_user";
|
|
93
|
+
assessment: {
|
|
94
|
+
reasoning: string;
|
|
95
|
+
suggestedRoles: {
|
|
96
|
+
ownUser: "peer";
|
|
97
|
+
otherUser: "peer";
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
turnCount: number;
|
|
102
|
+
error: string;
|
|
103
|
+
status?: undefined;
|
|
104
|
+
firstTurnScreenedOut?: undefined;
|
|
105
|
+
}>;
|