@indexnetwork/protocol 6.14.0-rc.406.1 → 8.0.1-rc.417.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 +307 -0
- package/IMPLEMENTATION.md +7 -4
- package/dist/capabilities/opportunities.facade.d.ts +4 -0
- package/dist/capabilities/opportunities.facade.js +4 -0
- package/dist/capabilities/signals.tools.port.d.ts +1 -1
- package/dist/chat/chat-streaming.types.d.ts +4 -5
- package/dist/chat/chat.agent.d.ts +0 -19
- package/dist/chat/chat.agent.js +1 -70
- package/dist/chat/chat.persona.d.ts +0 -6
- package/dist/chat/chat.persona.js +0 -1
- package/dist/chat/chat.prompt.js +10 -10
- package/dist/chat/chat.prompt.modules.js +0 -104
- package/dist/chat/chat.tools.js +11 -7
- package/dist/chat/negotiator.persona.js +0 -1
- package/dist/chat/onboarding.persona.js +0 -1
- package/dist/chat/reporter.persona.d.ts +1 -1
- package/dist/chat/reporter.persona.js +1 -2
- package/dist/chat/reporter.prompt.js +5 -5
- package/dist/chat/signal.persona.js +0 -1
- package/dist/communities/application/network.tools.js +48 -27
- package/dist/contacts/application/contact.tools.js +9 -9
- package/dist/index.d.ts +9 -2
- package/dist/index.js +5 -0
- package/dist/maintenance/maintenance.graph.js +7 -0
- package/dist/mcp/mcp.authorization-policy.d.ts +250 -0
- package/dist/mcp/mcp.authorization-policy.js +522 -0
- package/dist/mcp/mcp.server.d.ts +6 -29
- package/dist/mcp/mcp.server.js +202 -228
- package/dist/negotiation/application/negotiation.agent.js +29 -5
- package/dist/negotiation/application/negotiation.graph.d.ts +2 -5
- package/dist/negotiation/application/negotiation.graph.js +53 -23
- package/dist/negotiation/domain/index.d.ts +3 -0
- package/dist/negotiation/domain/index.js +3 -0
- package/dist/negotiation/domain/negotiation.deadlock.d.ts +7 -1
- package/dist/negotiation/domain/negotiation.deadlock.js +48 -1
- package/dist/negotiation/domain/negotiation.stance.contracts.d.ts +85 -0
- package/dist/negotiation/domain/negotiation.stance.contracts.js +140 -0
- package/dist/negotiation/domain/negotiation.state.d.ts +2 -3
- package/dist/negotiation/domain/negotiation.state.js +2 -3
- package/dist/negotiation/public/index.d.ts +2 -0
- package/dist/negotiation/public/index.js +2 -0
- package/dist/opportunity/application/index.d.ts +0 -3
- package/dist/opportunity/application/index.js +0 -3
- package/dist/opportunity/application/opportunity.graph.d.ts +0 -43
- package/dist/opportunity/application/opportunity.graph.js +7 -113
- package/dist/opportunity/application/opportunity.introducer-feature.d.ts +2 -0
- package/dist/opportunity/application/opportunity.introducer-feature.js +4 -0
- package/dist/opportunity/application/opportunity.owner-approval.d.ts +118 -0
- package/dist/opportunity/application/opportunity.owner-approval.js +34 -0
- package/dist/opportunity/application/opportunity.owner-provenance.d.ts +6 -0
- package/dist/opportunity/application/opportunity.owner-provenance.js +28 -0
- package/dist/opportunity/application/opportunity.tools.d.ts +3 -3
- package/dist/opportunity/application/opportunity.tools.js +77 -870
- package/dist/opportunity/discriminator/discriminator.shadow.js +17 -10
- package/dist/opportunity/discriminator/discriminator.types.d.ts +2 -0
- package/dist/opportunity/domain/index.d.ts +0 -2
- package/dist/opportunity/domain/index.js +0 -2
- package/dist/opportunity/domain/opportunity.state.d.ts +2 -70
- package/dist/opportunity/domain/opportunity.state.js +2 -55
- package/dist/opportunity/opportunity.owner-approval.d.ts +5 -0
- package/dist/opportunity/opportunity.owner-approval.js +5 -0
- package/dist/opportunity/ports/opportunity.tools.port.d.ts +12 -1
- package/dist/opportunity/public/index.d.ts +3 -3
- package/dist/opportunity/public/index.js +2 -1
- package/dist/participant-agents/application/agent.tools.d.ts +1 -1
- package/dist/participant-agents/application/agent.tools.js +44 -6
- package/dist/participant-agents/application/index.d.ts +5 -3
- package/dist/participant-agents/application/index.js +5 -3
- package/dist/questions/application/question.tools.js +31 -2
- package/dist/runtime/foreground/composition/tool.factory.d.ts +2 -1
- package/dist/runtime/foreground/composition/tool.factory.js +10 -2
- package/dist/runtime/foreground/composition/tool.registry.d.ts +16 -2
- package/dist/runtime/foreground/composition/tool.registry.js +41 -38
- package/dist/shared/agent/activity-projection.d.ts +271 -0
- package/dist/shared/agent/activity-projection.js +248 -0
- package/dist/shared/agent/canonical-guidance.d.ts +30 -0
- package/dist/shared/agent/canonical-guidance.js +249 -0
- package/dist/shared/agent/tool.helpers.d.ts +13 -17
- package/dist/shared/agent/tool.runtime.js +1 -3
- package/dist/shared/agent/utility.tools.d.ts +11 -1
- package/dist/shared/agent/utility.tools.js +126 -90
- package/dist/shared/interfaces/auth.interface.d.ts +2 -8
- package/dist/shared/interfaces/chat-session.interface.js +5 -0
- package/dist/shared/interfaces/database.interface.d.ts +12 -5
- package/dist/shared/observability/request-context.d.ts +4 -40
- package/dist/shared/schemas/mcp-auth.schema.d.ts +87 -15
- package/dist/shared/schemas/mcp-auth.schema.js +49 -1
- package/dist/signals/application/intent.graph.js +4 -15
- package/dist/signals/application/intent.tools.js +34 -14
- package/dist/signals/domain/intent.proposal.d.ts +35 -0
- package/dist/signals/domain/intent.proposal.js +12 -0
- package/package.json +10 -9
- package/dist/opportunity/application/opportunity.discover.d.ts +0 -215
- package/dist/opportunity/application/opportunity.discover.js +0 -793
- package/dist/opportunity/application/opportunity.discovery-continuation-finalization.d.ts +0 -34
- package/dist/opportunity/application/opportunity.discovery-continuation-finalization.js +0 -74
- package/dist/opportunity/application/opportunity.discovery-mcp-lifecycle-finalization.d.ts +0 -44
- package/dist/opportunity/application/opportunity.discovery-mcp-lifecycle-finalization.js +0 -92
- package/dist/opportunity/domain/opportunity.discovery-run-coalescing.d.ts +0 -33
- package/dist/opportunity/domain/opportunity.discovery-run-coalescing.js +0 -33
- package/dist/opportunity/domain/opportunity.discovery.contracts.d.ts +0 -45
- package/dist/opportunity/domain/opportunity.discovery.contracts.js +0 -1
- package/dist/opportunity/opportunity.discover.d.ts +0 -5
- package/dist/opportunity/opportunity.discover.js +0 -5
- package/dist/opportunity/opportunity.discovery-continuation-finalization.d.ts +0 -5
- package/dist/opportunity/opportunity.discovery-continuation-finalization.js +0 -5
- package/dist/opportunity/opportunity.discovery-mcp-lifecycle-finalization.d.ts +0 -5
- package/dist/opportunity/opportunity.discovery-mcp-lifecycle-finalization.js +0 -5
- package/dist/opportunity/opportunity.discovery-run-coalescing.d.ts +0 -5
- package/dist/opportunity/opportunity.discovery-run-coalescing.js +0 -5
- package/dist/opportunity/opportunity.discovery.contracts.d.ts +0 -5
- package/dist/opportunity/opportunity.discovery.contracts.js +0 -5
- package/dist/shared/interfaces/discovery-run.interface.d.ts +0 -70
- package/dist/shared/interfaces/discovery-run.interface.js +0 -1
|
@@ -6,10 +6,8 @@
|
|
|
6
6
|
import { protocolLogger } from "../../shared/observability/protocol.logger.js";
|
|
7
7
|
import { computeNovelty, scoreDiscriminator } from "./discriminator.scorer.js";
|
|
8
8
|
const logger = protocolLogger("PoolDiscriminatorShadow");
|
|
9
|
-
/** Max
|
|
9
|
+
/** Max ordinary current-intent/premise text references compared for novelty. */
|
|
10
10
|
const MAX_REFERENCE_TEXTS = 24;
|
|
11
|
-
const MAX_PRIOR_REFERENCE_TEXTS = 24;
|
|
12
|
-
const MAX_REFERENCE_EMBEDDINGS = 24;
|
|
13
11
|
/** Text embedded per discriminator for the novelty comparison. */
|
|
14
12
|
function discriminatorEmbeddingText(d) {
|
|
15
13
|
return `${d.label} — ${d.questionSeed}`;
|
|
@@ -31,17 +29,16 @@ export async function runPoolDiscriminatorShadow(input) {
|
|
|
31
29
|
.slice(0, MAX_REFERENCE_TEXTS);
|
|
32
30
|
const priorReferenceTexts = (input.priorReferenceTexts ?? [])
|
|
33
31
|
.map((text) => text.trim())
|
|
34
|
-
.filter((text) => text.length > 0)
|
|
35
|
-
.slice(0, MAX_PRIOR_REFERENCE_TEXTS);
|
|
32
|
+
.filter((text) => text.length > 0);
|
|
36
33
|
const priorReferenceEmbeddings = (input.priorReferenceEmbeddings ?? [])
|
|
37
|
-
.filter((embedding) => embedding.length > 0)
|
|
38
|
-
|
|
34
|
+
.filter((embedding) => embedding.length > 0);
|
|
35
|
+
const hasPriorReferenceHistory = priorReferenceTexts.length > 0 || priorReferenceEmbeddings.length > 0;
|
|
39
36
|
let novelties = mined.map(() => 1);
|
|
40
37
|
let discriminatorEmbeddings = null;
|
|
38
|
+
let priorReferenceComparisonUnavailable = false;
|
|
41
39
|
const shouldEmbed = input.retainEmbeddings
|
|
42
40
|
|| references.length > 0
|
|
43
|
-
||
|
|
44
|
-
|| priorReferenceEmbeddings.length > 0;
|
|
41
|
+
|| hasPriorReferenceHistory;
|
|
45
42
|
if (shouldEmbed) {
|
|
46
43
|
try {
|
|
47
44
|
const texts = [
|
|
@@ -53,6 +50,11 @@ export async function runPoolDiscriminatorShadow(input) {
|
|
|
53
50
|
if (embeddings.length !== texts.length || embeddings.some((embedding) => !Array.isArray(embedding) || embedding.length === 0)) {
|
|
54
51
|
throw new Error("Embedding provider returned an invalid batch");
|
|
55
52
|
}
|
|
53
|
+
const comparisonEmbeddings = [...embeddings, ...priorReferenceEmbeddings];
|
|
54
|
+
const dimension = comparisonEmbeddings[0]?.length;
|
|
55
|
+
if (dimension !== undefined && comparisonEmbeddings.some((embedding) => embedding.length !== dimension)) {
|
|
56
|
+
throw new Error("Embedding comparison batch contains incompatible vector dimensions");
|
|
57
|
+
}
|
|
56
58
|
discriminatorEmbeddings = embeddings.slice(0, mined.length);
|
|
57
59
|
const referenceEmbeddings = [
|
|
58
60
|
...priorReferenceEmbeddings,
|
|
@@ -64,6 +66,7 @@ export async function runPoolDiscriminatorShadow(input) {
|
|
|
64
66
|
logger.warn("Novelty embedding failed; defaulting novelty to 1", {
|
|
65
67
|
error: err instanceof Error ? err.message : String(err),
|
|
66
68
|
});
|
|
69
|
+
priorReferenceComparisonUnavailable = hasPriorReferenceHistory;
|
|
67
70
|
}
|
|
68
71
|
}
|
|
69
72
|
const discriminators = mined
|
|
@@ -79,5 +82,9 @@ export async function runPoolDiscriminatorShadow(input) {
|
|
|
79
82
|
: scored;
|
|
80
83
|
})
|
|
81
84
|
.sort((a, b) => b.voi - a.voi);
|
|
82
|
-
return {
|
|
85
|
+
return {
|
|
86
|
+
poolSize: candidates.length,
|
|
87
|
+
discriminators,
|
|
88
|
+
...(priorReferenceComparisonUnavailable ? { priorReferenceComparisonUnavailable: true } : {}),
|
|
89
|
+
};
|
|
83
90
|
}
|
|
@@ -88,4 +88,6 @@ export interface DiscriminatorShadowResult {
|
|
|
88
88
|
poolSize: number;
|
|
89
89
|
/** Scored discriminators, sorted by VoI descending. */
|
|
90
90
|
discriminators: ScoredDiscriminator[];
|
|
91
|
+
/** Historical-axis comparison could not be completed due to invalid embeddings. */
|
|
92
|
+
priorReferenceComparisonUnavailable?: boolean;
|
|
91
93
|
}
|
|
@@ -25,7 +25,6 @@
|
|
|
25
25
|
* IND-551: canonical domain layer for the opportunities capability.
|
|
26
26
|
*/
|
|
27
27
|
export * from "./opportunity.state.js";
|
|
28
|
-
export * from "./opportunity.discovery.contracts.js";
|
|
29
28
|
export * from "./opportunity.labels.js";
|
|
30
29
|
export * from "./opportunity.utils.js";
|
|
31
30
|
export * from "./opportunity.actor.js";
|
|
@@ -34,7 +33,6 @@ export * from "./opportunity.claim-safety.js";
|
|
|
34
33
|
export * from "./opportunity.presentation.js";
|
|
35
34
|
export * from "./opportunity.safe-presentation.js";
|
|
36
35
|
export * from "./opportunity.presentation-cache.js";
|
|
37
|
-
export * from "./opportunity.discovery-run-coalescing.js";
|
|
38
36
|
export * from "./negotiation-summary.builder.js";
|
|
39
37
|
export * from "./discovery-question.helper.js";
|
|
40
38
|
export type { PoolCandidate, DiscriminatorMiningInput, MinedDiscriminator, ScoredDiscriminator, VerifiedAssignment, DiscriminatorShadowResult, } from "../discriminator/discriminator.types.js";
|
|
@@ -26,7 +26,6 @@
|
|
|
26
26
|
*/
|
|
27
27
|
// ── Flat domain files ─────────────────────────────────────────────────────────
|
|
28
28
|
export * from "./opportunity.state.js";
|
|
29
|
-
export * from "./opportunity.discovery.contracts.js";
|
|
30
29
|
export * from "./opportunity.labels.js";
|
|
31
30
|
export * from "./opportunity.utils.js";
|
|
32
31
|
export * from "./opportunity.actor.js";
|
|
@@ -35,7 +34,6 @@ export * from "./opportunity.claim-safety.js";
|
|
|
35
34
|
export * from "./opportunity.presentation.js";
|
|
36
35
|
export * from "./opportunity.safe-presentation.js";
|
|
37
36
|
export * from "./opportunity.presentation-cache.js";
|
|
38
|
-
export * from "./opportunity.discovery-run-coalescing.js";
|
|
39
37
|
export * from "./negotiation-summary.builder.js";
|
|
40
38
|
export * from "./discovery-question.helper.js";
|
|
41
39
|
export { poolQuestionsMiningMode, poolQuestionsMode, poolQuestionsPushMode, poolQuestionsStampNewborn, POOL_DISCRIMINATOR_MIN_POOL_SIZE, POOL_DISCRIMINATOR_MAX_CANDIDATES, POOL_DISCRIMINATOR_MAX_PUBLIC_CONTEXT_CHARS, POOL_QUESTION_MIN_VOI, POOL_QUESTION_MAX_PENDING_PER_INTENT, poolQuestionsRanking, POOL_RERUN_DEBOUNCE_MS, poolQuestionsVisitTrigger, POOL_VISIT_MINING_DEBOUNCE_MS, } from "../discriminator/discriminator.env.js";
|
|
@@ -108,40 +108,6 @@ export interface OpportunityPersistenceOutcome {
|
|
|
108
108
|
crossTriggerAllowedCount: number;
|
|
109
109
|
finalAtomicConflictCount: number;
|
|
110
110
|
}
|
|
111
|
-
/**
|
|
112
|
-
* Which flow triggered this graph invocation. Determines initial persist status,
|
|
113
|
-
* park-window timeout, streaming behavior, and whether AbortSignal is honored.
|
|
114
|
-
*
|
|
115
|
-
* - 'ambient' (default): queue-driven. Persists at the trigger default of
|
|
116
|
-
* `pending` unless `options.initialStatus` overrides (the queue worker
|
|
117
|
-
* passes `'latent'`, chat-bound ambient discovery passes `'draft'`). 5-min
|
|
118
|
-
* park window, no streaming, ignores abort.
|
|
119
|
-
* - 'orchestrator': chat-driven. Persists at the trigger default of
|
|
120
|
-
* `negotiating` unless `options.initialStatus` overrides. 60s park window,
|
|
121
|
-
* streams `opportunity_draft_ready` events, honors abort.
|
|
122
|
-
*
|
|
123
|
-
* See {@link resolveInitialStatus} for the exact fallback used when
|
|
124
|
-
* `options.initialStatus` is undefined.
|
|
125
|
-
*/
|
|
126
|
-
export type OpportunityTrigger = 'ambient' | 'orchestrator';
|
|
127
|
-
/**
|
|
128
|
-
* Resolves the initial status for opportunities created in the persist node.
|
|
129
|
-
*
|
|
130
|
-
* Explicit `options.initialStatus` always wins (callers like the chat tool or
|
|
131
|
-
* maintenance scripts override per-call). When the caller leaves it
|
|
132
|
-
* undefined, the trigger drives the default:
|
|
133
|
-
* - 'orchestrator' → 'negotiating' (chat-driven; negotiations run before the
|
|
134
|
-
* user sees a draft card).
|
|
135
|
-
* - 'ambient' (or any other trigger) → 'pending' (long-standing default for
|
|
136
|
-
* queue- and intent-driven discovery).
|
|
137
|
-
*
|
|
138
|
-
* Lives here rather than in opportunity.graph.ts so unit tests can exercise
|
|
139
|
-
* it without pulling in the full graph (and the evaluator's LLM requirements).
|
|
140
|
-
*
|
|
141
|
-
* @param trigger - The graph invocation's trigger
|
|
142
|
-
* @param explicit - Caller-supplied initial status from options.initialStatus
|
|
143
|
-
*/
|
|
144
|
-
export declare function resolveInitialStatus(trigger: OpportunityTrigger, explicit: OpportunityStatus | undefined): OpportunityStatus;
|
|
145
111
|
/**
|
|
146
112
|
* Options passed to the graph
|
|
147
113
|
*/
|
|
@@ -194,37 +160,6 @@ export declare const OpportunityGraphState: import("@langchain/langgraph").Annot
|
|
|
194
160
|
/** Optional: discover on behalf of this user (introducer flow). When set, prep/eval use this user's profile/intents; userId becomes the introducer. */
|
|
195
161
|
onBehalfOfUserId: import("@langchain/langgraph").BaseChannel<Id<"users"> | undefined, Id<"users"> | import("@langchain/langgraph").OverwriteValue<Id<"users"> | undefined> | undefined, unknown>;
|
|
196
162
|
options: import("@langchain/langgraph").BaseChannel<OpportunityGraphOptions, OpportunityGraphOptions | import("@langchain/langgraph").OverwriteValue<OpportunityGraphOptions>, unknown>;
|
|
197
|
-
/**
|
|
198
|
-
* Which flow triggered this graph invocation. See {@link OpportunityTrigger}
|
|
199
|
-
* for the exact branch behavior and {@link resolveInitialStatus} for the
|
|
200
|
-
* persist default when `options.initialStatus` is unset.
|
|
201
|
-
*
|
|
202
|
-
* - 'ambient' (default): queue-driven, persist default `pending`, 5-min
|
|
203
|
-
* park window, no streaming, ignores abort.
|
|
204
|
-
* - 'orchestrator': chat-driven, persist default `negotiating`, 60s park
|
|
205
|
-
* window, streams `opportunity_draft_ready` events, honors abort.
|
|
206
|
-
*/
|
|
207
|
-
trigger: import("@langchain/langgraph").BaseChannel<OpportunityTrigger, OpportunityTrigger | import("@langchain/langgraph").OverwriteValue<OpportunityTrigger>, unknown>;
|
|
208
|
-
/**
|
|
209
|
-
* Accepted opportunities the persist node discovered between the discoverer
|
|
210
|
-
* and a candidate actor (same pair, status='accepted'). The orchestrator
|
|
211
|
-
* branch populates this so the discover_opportunities tool (Task 7) can tell
|
|
212
|
-
* the LLM "these pairs are already connected, surface the existing chat
|
|
213
|
-
* rather than creating a new draft". Always empty for the ambient trigger.
|
|
214
|
-
*
|
|
215
|
-
* Left intentionally minimal — conversationId/URL resolution happens at
|
|
216
|
-
* Start Chat time (Task 8), not here.
|
|
217
|
-
*/
|
|
218
|
-
dedupAlreadyAccepted: import("@langchain/langgraph").BaseChannel<{
|
|
219
|
-
opportunityId: string;
|
|
220
|
-
counterpartyUserId: string;
|
|
221
|
-
}[], {
|
|
222
|
-
opportunityId: string;
|
|
223
|
-
counterpartyUserId: string;
|
|
224
|
-
}[] | import("@langchain/langgraph").OverwriteValue<{
|
|
225
|
-
opportunityId: string;
|
|
226
|
-
counterpartyUserId: string;
|
|
227
|
-
}[]>, unknown>;
|
|
228
163
|
/**
|
|
229
164
|
* Operation mode controls graph flow:
|
|
230
165
|
* - 'create': Existing discover pipeline (Prep → Scope → Discovery → Evaluation → Ranking → Persist)
|
|
@@ -441,11 +376,8 @@ export declare const OpportunityGraphState: import("@langchain/langgraph").Annot
|
|
|
441
376
|
/**
|
|
442
377
|
* Per-candidate negotiation records captured by `negotiateNode`. Populated
|
|
443
378
|
* regardless of accept/reject so the question generator sees a complete
|
|
444
|
-
* picture.
|
|
445
|
-
* negotiate
|
|
446
|
-
* orchestrator streaming side-effects (opportunity_draft_ready emission)
|
|
447
|
-
* are trigger-gated. Empty when the negotiate node was skipped (no
|
|
448
|
-
* opportunities to negotiate).
|
|
379
|
+
* picture. Empty when the negotiate node was skipped (no opportunities to
|
|
380
|
+
* negotiate).
|
|
449
381
|
*/
|
|
450
382
|
discoveryNegotiations: import("@langchain/langgraph").BaseChannel<{
|
|
451
383
|
counterpartyHint: string;
|
|
@@ -1,26 +1,4 @@
|
|
|
1
1
|
import { Annotation } from "@langchain/langgraph";
|
|
2
|
-
/**
|
|
3
|
-
* Resolves the initial status for opportunities created in the persist node.
|
|
4
|
-
*
|
|
5
|
-
* Explicit `options.initialStatus` always wins (callers like the chat tool or
|
|
6
|
-
* maintenance scripts override per-call). When the caller leaves it
|
|
7
|
-
* undefined, the trigger drives the default:
|
|
8
|
-
* - 'orchestrator' → 'negotiating' (chat-driven; negotiations run before the
|
|
9
|
-
* user sees a draft card).
|
|
10
|
-
* - 'ambient' (or any other trigger) → 'pending' (long-standing default for
|
|
11
|
-
* queue- and intent-driven discovery).
|
|
12
|
-
*
|
|
13
|
-
* Lives here rather than in opportunity.graph.ts so unit tests can exercise
|
|
14
|
-
* it without pulling in the full graph (and the evaluator's LLM requirements).
|
|
15
|
-
*
|
|
16
|
-
* @param trigger - The graph invocation's trigger
|
|
17
|
-
* @param explicit - Caller-supplied initial status from options.initialStatus
|
|
18
|
-
*/
|
|
19
|
-
export function resolveInitialStatus(trigger, explicit) {
|
|
20
|
-
if (explicit !== undefined)
|
|
21
|
-
return explicit;
|
|
22
|
-
return trigger === 'orchestrator' ? 'negotiating' : 'pending';
|
|
23
|
-
}
|
|
24
2
|
/**
|
|
25
3
|
* Opportunity Graph State Annotation
|
|
26
4
|
*/
|
|
@@ -68,34 +46,6 @@ export const OpportunityGraphState = Annotation.Root({
|
|
|
68
46
|
reducer: (curr, next) => next ?? curr,
|
|
69
47
|
default: () => ({}),
|
|
70
48
|
}),
|
|
71
|
-
/**
|
|
72
|
-
* Which flow triggered this graph invocation. See {@link OpportunityTrigger}
|
|
73
|
-
* for the exact branch behavior and {@link resolveInitialStatus} for the
|
|
74
|
-
* persist default when `options.initialStatus` is unset.
|
|
75
|
-
*
|
|
76
|
-
* - 'ambient' (default): queue-driven, persist default `pending`, 5-min
|
|
77
|
-
* park window, no streaming, ignores abort.
|
|
78
|
-
* - 'orchestrator': chat-driven, persist default `negotiating`, 60s park
|
|
79
|
-
* window, streams `opportunity_draft_ready` events, honors abort.
|
|
80
|
-
*/
|
|
81
|
-
trigger: Annotation({
|
|
82
|
-
reducer: (curr, next) => next ?? curr,
|
|
83
|
-
default: () => 'ambient',
|
|
84
|
-
}),
|
|
85
|
-
/**
|
|
86
|
-
* Accepted opportunities the persist node discovered between the discoverer
|
|
87
|
-
* and a candidate actor (same pair, status='accepted'). The orchestrator
|
|
88
|
-
* branch populates this so the discover_opportunities tool (Task 7) can tell
|
|
89
|
-
* the LLM "these pairs are already connected, surface the existing chat
|
|
90
|
-
* rather than creating a new draft". Always empty for the ambient trigger.
|
|
91
|
-
*
|
|
92
|
-
* Left intentionally minimal — conversationId/URL resolution happens at
|
|
93
|
-
* Start Chat time (Task 8), not here.
|
|
94
|
-
*/
|
|
95
|
-
dedupAlreadyAccepted: Annotation({
|
|
96
|
-
reducer: (curr, next) => next ?? curr,
|
|
97
|
-
default: () => [],
|
|
98
|
-
}),
|
|
99
49
|
/**
|
|
100
50
|
* Operation mode controls graph flow:
|
|
101
51
|
* - 'create': Existing discover pipeline (Prep → Scope → Discovery → Evaluation → Ranking → Persist)
|
|
@@ -291,11 +241,8 @@ export const OpportunityGraphState = Annotation.Root({
|
|
|
291
241
|
/**
|
|
292
242
|
* Per-candidate negotiation records captured by `negotiateNode`. Populated
|
|
293
243
|
* regardless of accept/reject so the question generator sees a complete
|
|
294
|
-
* picture.
|
|
295
|
-
* negotiate
|
|
296
|
-
* orchestrator streaming side-effects (opportunity_draft_ready emission)
|
|
297
|
-
* are trigger-gated. Empty when the negotiate node was skipped (no
|
|
298
|
-
* opportunities to negotiate).
|
|
244
|
+
* picture. Empty when the negotiate node was skipped (no opportunities to
|
|
245
|
+
* negotiate).
|
|
299
246
|
*/
|
|
300
247
|
discoveryNegotiations: Annotation({
|
|
301
248
|
reducer: (curr, next) => [...curr, ...(next || [])],
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import type { ToolRegistryCompositionDeps } from "../../shared/agent/tool.helpers.js";
|
|
2
|
+
import type { OpportunityOwnerApprovalAuthority } from "../application/opportunity.owner-approval.js";
|
|
3
|
+
/**
|
|
4
|
+
* IND-593 host authority consumed only by the opportunity mutation boundary.
|
|
5
|
+
*
|
|
6
|
+
* This stays capability-local rather than extending the shared registry shape:
|
|
7
|
+
* the shared helper participates in the negotiation/question architecture
|
|
8
|
+
* cycle, while owner approval belongs to the opportunity composition seam.
|
|
9
|
+
*/
|
|
10
|
+
export interface OpportunityOwnerApprovalDeps {
|
|
11
|
+
opportunityOwnerApproval?: OpportunityOwnerApprovalAuthority;
|
|
12
|
+
}
|
|
2
13
|
/** Host capabilities consumed by opportunity discovery, delivery, and presentation tools. */
|
|
3
|
-
export type OpportunityToolDeps = Pick<ToolRegistryCompositionDeps, "database" | "userDb" | "systemDb" | "cache" | "chatSummary" | "
|
|
14
|
+
export type OpportunityToolDeps = Pick<ToolRegistryCompositionDeps, "database" | "userDb" | "systemDb" | "cache" | "chatSummary" | "opportunityPresentation" | "questionGenerator" | "questionerEnqueue" | "findPendingQuestions" | "negotiationSummary" | "negotiationDatabase" | "deliveryLedger" | "mintConnectLink" | "frontendUrl" | "stampNewbornOpportunities" | "reportToolError"> & OpportunityOwnerApprovalDeps & {
|
|
4
15
|
graphs: Pick<ToolRegistryCompositionDeps["graphs"], "index" | "networkMembership" | "opportunity">;
|
|
5
16
|
};
|
|
@@ -7,9 +7,8 @@
|
|
|
7
7
|
*
|
|
8
8
|
* IND-551: canonical public surface for the opportunities capability.
|
|
9
9
|
*/
|
|
10
|
-
export { OpportunityGraphState,
|
|
11
|
-
export type { SourceProfileData, IndexedIntent, TargetNetwork, CandidateMatch, EvaluatedCandidate, EvaluatedOpportunityActor, EvaluatedOpportunity, OpportunityPersistenceOutcome,
|
|
12
|
-
export type { DiscoverDebugStep, DiscoveryResultContract, } from "../domain/opportunity.discovery.contracts.js";
|
|
10
|
+
export { OpportunityGraphState, } from "../domain/opportunity.state.js";
|
|
11
|
+
export type { SourceProfileData, IndexedIntent, TargetNetwork, CandidateMatch, EvaluatedCandidate, EvaluatedOpportunityActor, EvaluatedOpportunity, OpportunityPersistenceOutcome, OpportunityGraphOptions, } from "../domain/opportunity.state.js";
|
|
13
12
|
export { MINIMAL_MAIN_TEXT_MAX_CHARS, PRIMARY_ACTION_LABEL_INTRODUCER, PRIMARY_ACTION_LABEL_DEFAULT, SECONDARY_ACTION_LABEL, getPrimaryActionLabel, } from "../domain/opportunity.labels.js";
|
|
14
13
|
export { deriveRolesFromCorpus, validateOpportunityActors, canUserSeeOpportunity, isActionableForViewer, classifyOpportunity, selectByComposition, deduplicateByPerson, selectDigestCandidates, FEED_SOFT_TARGETS, DIGEST_REDELIVERY_COOLDOWN_DAYS, } from "../domain/opportunity.utils.js";
|
|
15
14
|
export type { OpportunityActorRole, DerivedRoles, FeedCategory, DigestDeliveredRow, } from "../domain/opportunity.utils.js";
|
|
@@ -35,6 +34,7 @@ export type { OutcomeLabel, OutcomeExample, OutcomeShadowResult, } from "../outc
|
|
|
35
34
|
export { isOutcomeQuestionsActivated, OUTCOME_MIN_INDEPENDENT_EXAMPLES, OUTCOME_MAX_CANDIDATES, OUTCOME_MAX_PUBLIC_CONTEXT_CHARS, } from "../outcome/outcome.env.js";
|
|
36
35
|
export { computeFeedHealth } from "../feed/feed.health.js";
|
|
37
36
|
export type { FeedHealthInput } from "../feed/feed.health.js";
|
|
37
|
+
export { isIntroducerDiscoveryEnabled } from "../application/opportunity.introducer-feature.js";
|
|
38
38
|
export { OpportunityGraphFactory } from "../application/opportunity.graph.js";
|
|
39
39
|
export type { StampNewbornOpportunitiesFn, StampNewbornOpportunitiesInput, } from "../application/opportunity.newborn-stamping.js";
|
|
40
40
|
export { OpportunityEvaluator } from "../application/opportunity.evaluator.js";
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
// ── Domain exports ────────────────────────────────────────────────────────────
|
|
11
11
|
export {
|
|
12
12
|
// state
|
|
13
|
-
OpportunityGraphState,
|
|
13
|
+
OpportunityGraphState, } from "../domain/opportunity.state.js";
|
|
14
14
|
export { MINIMAL_MAIN_TEXT_MAX_CHARS, PRIMARY_ACTION_LABEL_INTRODUCER, PRIMARY_ACTION_LABEL_DEFAULT, SECONDARY_ACTION_LABEL, getPrimaryActionLabel, } from "../domain/opportunity.labels.js";
|
|
15
15
|
export { deriveRolesFromCorpus, validateOpportunityActors, canUserSeeOpportunity, isActionableForViewer, classifyOpportunity, selectByComposition, deduplicateByPerson, selectDigestCandidates, FEED_SOFT_TARGETS, DIGEST_REDELIVERY_COOLDOWN_DAYS, } from "../domain/opportunity.utils.js";
|
|
16
16
|
export { normalizeOpportunityActorIntent, resolveOpportunityActorIntent, normalizeOpportunityActors, normalizeCreateOpportunityActorIntents, } from "../domain/opportunity.actor.js";
|
|
@@ -29,6 +29,7 @@ export { isOutcomeQuestionsActivated, OUTCOME_MIN_INDEPENDENT_EXAMPLES, OUTCOME_
|
|
|
29
29
|
// feed domain
|
|
30
30
|
export { computeFeedHealth } from "../feed/feed.health.js";
|
|
31
31
|
// ── Application exports ───────────────────────────────────────────────────────
|
|
32
|
+
export { isIntroducerDiscoveryEnabled } from "../application/opportunity.introducer-feature.js";
|
|
32
33
|
export { OpportunityGraphFactory } from "../application/opportunity.graph.js";
|
|
33
34
|
export { OpportunityEvaluator } from "../application/opportunity.evaluator.js";
|
|
34
35
|
export { OpportunityPresenter, gatherPresenterContext, } from "../application/opportunity.presenter.js";
|
|
@@ -13,4 +13,4 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import type { DefineTool } from '../../shared/agent/tool.helpers.js';
|
|
15
15
|
import type { AgentToolDeps } from '../ports/index.js';
|
|
16
|
-
export declare function createAgentTools(defineTool: DefineTool, deps: AgentToolDeps): never[] | readonly [any, any, any, any, any, any];
|
|
16
|
+
export declare function createAgentTools(defineTool: DefineTool, deps: AgentToolDeps): never[] | readonly [any, any, any, any, any, any, any];
|
|
@@ -16,13 +16,19 @@ import { error, success } from '../../shared/agent/tool.helpers.js';
|
|
|
16
16
|
import { protocolLogger } from '../../shared/observability/protocol.logger.js';
|
|
17
17
|
const logger = protocolLogger('ChatTools:Agent');
|
|
18
18
|
const AGENT_ACTIONS = [
|
|
19
|
-
'manage:
|
|
19
|
+
'manage:identity',
|
|
20
|
+
'manage:premises',
|
|
20
21
|
'manage:intents',
|
|
21
22
|
'manage:networks',
|
|
22
|
-
'manage:contacts',
|
|
23
23
|
'manage:opportunities',
|
|
24
24
|
'manage:negotiations',
|
|
25
25
|
];
|
|
26
|
+
/**
|
|
27
|
+
* Canonical permission-action enum for the public tool INPUT schemas. Retired
|
|
28
|
+
* `manage:profile` / `manage:contacts` strings are rejected at the schema seam
|
|
29
|
+
* (defense-in-depth: the handler still re-validates via {@link isValidAction}).
|
|
30
|
+
*/
|
|
31
|
+
const AgentPermissionActionSchema = z.enum(AGENT_ACTIONS);
|
|
26
32
|
function invalidActionMessage(action) {
|
|
27
33
|
return `Invalid action: ${action}. Valid actions: ${AGENT_ACTIONS.join(', ')}`;
|
|
28
34
|
}
|
|
@@ -44,7 +50,11 @@ function ensureAgentScopedAccess(context, requestedAgentId) {
|
|
|
44
50
|
function sanitizeAgentForOutput(agent) {
|
|
45
51
|
return {
|
|
46
52
|
...agent,
|
|
47
|
-
|
|
53
|
+
// Transport config carries private connection material (endpoint secrets,
|
|
54
|
+
// auth headers/tokens). It is never projected to ANY MCP caller — including
|
|
55
|
+
// the agent reading its own record via read_own_agent (IND-599). Channel,
|
|
56
|
+
// priority, and health metadata remain visible; config is fully redacted.
|
|
57
|
+
transports: agent.transports?.map((transport) => ({ ...transport, config: {} })),
|
|
48
58
|
};
|
|
49
59
|
}
|
|
50
60
|
function sanitizeAgentName(name) {
|
|
@@ -66,7 +76,7 @@ export function createAgentTools(defineTool, deps) {
|
|
|
66
76
|
querySchema: z.object({
|
|
67
77
|
name: z.string().min(1).describe('Display name for the agent.'),
|
|
68
78
|
description: z.string().optional().describe('What the agent does.'),
|
|
69
|
-
permissions: z.array(
|
|
79
|
+
permissions: z.array(AgentPermissionActionSchema).optional().describe('Optional initial permission actions to grant. Valid values: manage:identity, manage:premises, manage:intents, manage:networks, manage:opportunities, manage:negotiations.'),
|
|
70
80
|
}),
|
|
71
81
|
handler: async ({ context, query }) => {
|
|
72
82
|
if (context.agentId) {
|
|
@@ -121,6 +131,33 @@ export function createAgentTools(defineTool, deps) {
|
|
|
121
131
|
}
|
|
122
132
|
},
|
|
123
133
|
});
|
|
134
|
+
const readOwnAgent = defineTool({
|
|
135
|
+
name: 'read_own_agent',
|
|
136
|
+
description: "Read the calling agent's own registration record \u2014 its identity, " +
|
|
137
|
+
'transports, and granted permissions. Returns only the authenticated ' +
|
|
138
|
+
'agent\u2019s own record; no other agent can be named or targeted. Use this ' +
|
|
139
|
+
'when an agent needs to inspect its own configuration.',
|
|
140
|
+
querySchema: z.object({}),
|
|
141
|
+
handler: async ({ context }) => {
|
|
142
|
+
// Defense-in-depth: the capability policy only admits registered active
|
|
143
|
+
// agent principals here, but never trust the caller — require an agent
|
|
144
|
+
// context and resolve strictly the caller's OWN record (no target input).
|
|
145
|
+
if (!context.agentId) {
|
|
146
|
+
return error('read_own_agent is only available to a registered agent principal.');
|
|
147
|
+
}
|
|
148
|
+
try {
|
|
149
|
+
const agent = await agentDb.getAgentWithRelations(context.agentId);
|
|
150
|
+
if (!agent || agent.ownerId !== context.userId) {
|
|
151
|
+
return error('Agent not found');
|
|
152
|
+
}
|
|
153
|
+
return success({ agent: sanitizeAgentForOutput(agent) });
|
|
154
|
+
}
|
|
155
|
+
catch (err) {
|
|
156
|
+
logger.error('Failed to read own agent', { err });
|
|
157
|
+
return error('Failed to read agent. Please try again.');
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
});
|
|
124
161
|
const listAgents = defineTool({
|
|
125
162
|
name: 'list_agents',
|
|
126
163
|
description: 'List all agents the current user owns or has authorized.',
|
|
@@ -228,10 +265,10 @@ export function createAgentTools(defineTool, deps) {
|
|
|
228
265
|
const grantAgentPermission = defineTool({
|
|
229
266
|
name: 'grant_agent_permission',
|
|
230
267
|
description: 'Grant one or more permissions to an agent for the current user. ' +
|
|
231
|
-
'Valid actions: manage:
|
|
268
|
+
'Valid actions: manage:identity, manage:premises, manage:intents, manage:networks, manage:opportunities, manage:negotiations.',
|
|
232
269
|
querySchema: z.object({
|
|
233
270
|
agent_id: z.string().min(1).describe('The agent ID to grant permissions to.'),
|
|
234
|
-
actions: z.array(
|
|
271
|
+
actions: z.array(AgentPermissionActionSchema).min(1).describe('Permission actions to grant. Valid values: manage:identity, manage:premises, manage:intents, manage:networks, manage:opportunities, manage:negotiations.'),
|
|
235
272
|
scope: z.enum(['global', 'node', 'network']).optional().describe('Optional permission scope.'),
|
|
236
273
|
scope_id: z.string().optional().describe('Scope target ID for node/network scopes.'),
|
|
237
274
|
}),
|
|
@@ -303,6 +340,7 @@ export function createAgentTools(defineTool, deps) {
|
|
|
303
340
|
},
|
|
304
341
|
});
|
|
305
342
|
return [
|
|
343
|
+
readOwnAgent,
|
|
306
344
|
registerAgent,
|
|
307
345
|
listAgents,
|
|
308
346
|
updateAgent,
|
|
@@ -6,9 +6,11 @@
|
|
|
6
6
|
*
|
|
7
7
|
* ## Foreground adapters (participant-directed, authenticated)
|
|
8
8
|
*
|
|
9
|
-
* - {@link createAgentTools} — `
|
|
10
|
-
* `
|
|
11
|
-
* tools for the authenticated registration
|
|
9
|
+
* - {@link createAgentTools} — `read_own_agent`, `register_agent`,
|
|
10
|
+
* `list_agents`, `update_agent`, `delete_agent`, `grant_agent_permission`,
|
|
11
|
+
* `revoke_agent_permission` MCP tools for the authenticated registration
|
|
12
|
+
* and permission management path (IND-599: `read_own_agent` is the
|
|
13
|
+
* agent-principal self-read; the rest are human owner/admin actions).
|
|
12
14
|
*
|
|
13
15
|
* ## Boundary
|
|
14
16
|
*
|
|
@@ -6,9 +6,11 @@
|
|
|
6
6
|
*
|
|
7
7
|
* ## Foreground adapters (participant-directed, authenticated)
|
|
8
8
|
*
|
|
9
|
-
* - {@link createAgentTools} — `
|
|
10
|
-
* `
|
|
11
|
-
* tools for the authenticated registration
|
|
9
|
+
* - {@link createAgentTools} — `read_own_agent`, `register_agent`,
|
|
10
|
+
* `list_agents`, `update_agent`, `delete_agent`, `grant_agent_permission`,
|
|
11
|
+
* `revoke_agent_permission` MCP tools for the authenticated registration
|
|
12
|
+
* and permission management path (IND-599: `read_own_agent` is the
|
|
13
|
+
* agent-principal self-read; the rest are human owner/admin actions).
|
|
12
14
|
*
|
|
13
15
|
* ## Boundary
|
|
14
16
|
*
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
import { z } from "zod";
|
|
17
17
|
import { error, success } from "../../shared/agent/tool.helpers.js";
|
|
18
18
|
import { focusedIntentId, focusedNetworkId, focusedNetworkLabel } from "../../shared/agent/tool.scope.js";
|
|
19
|
+
import { callerMayAccessQuestionMode } from "../../shared/agent/activity-projection.js";
|
|
19
20
|
/**
|
|
20
21
|
* Detection modes whose questions derive solely from the caller's own data
|
|
21
22
|
* (profile gaps, own intents, own discovery sessions). Negotiation-mode
|
|
@@ -27,6 +28,23 @@ const SELF_OWNED_MODES = ["enrichment", "intent", "discovery"];
|
|
|
27
28
|
function isVisibleInScopedNetwork(question, userId, networkId) {
|
|
28
29
|
return question.actors?.some((actor) => actor.userId === userId && actor.networkId === networkId) === true;
|
|
29
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Exact affected-domain permission gate for a single question mode.
|
|
33
|
+
*
|
|
34
|
+
* The canonical MCP matrix admits both question tools with a UNION of domain
|
|
35
|
+
* actions (so any question-holding agent can reach the handler), but exact
|
|
36
|
+
* inheritance must be enforced here: a global `manage:intents` agent must not
|
|
37
|
+
* read or answer a `negotiation` question. Reuses the shared
|
|
38
|
+
* `callerMayAccessQuestionMode` mapping so this matches the read_activity_summary
|
|
39
|
+
* projection. A caller context without an `mcpCaller` (REST/chat surfaces) is
|
|
40
|
+
* owner-trusted and passes; MCP humans own their data and also pass.
|
|
41
|
+
*/
|
|
42
|
+
function callerMayAccessQuestion(context, mode) {
|
|
43
|
+
const caller = context.mcpCaller;
|
|
44
|
+
if (!caller)
|
|
45
|
+
return true;
|
|
46
|
+
return callerMayAccessQuestionMode(caller, mode);
|
|
47
|
+
}
|
|
30
48
|
function stripInternalQuestionFields(question) {
|
|
31
49
|
const { actors: _actors, purpose: _purpose, ...publicQuestion } = question;
|
|
32
50
|
return publicQuestion;
|
|
@@ -80,10 +98,14 @@ export function createQuestionerTools(defineTool, deps) {
|
|
|
80
98
|
...(isIntentScoped ? { scopeType: 'intent', scopeId: scopedIntentId } : {}),
|
|
81
99
|
limit,
|
|
82
100
|
});
|
|
101
|
+
// Exact affected-domain permission projection: an agent sees only the
|
|
102
|
+
// question modes backed by one of its permissions (a global intents-only
|
|
103
|
+
// agent never sees negotiation questions). The owning human passes.
|
|
104
|
+
const permitted = fetched.filter((q) => callerMayAccessQuestion(context, q.mode));
|
|
83
105
|
const visible = isNetworkScoped
|
|
84
|
-
?
|
|
106
|
+
? permitted.filter((q) => SELF_OWNED_MODES.includes(q.mode) &&
|
|
85
107
|
isVisibleInScopedNetwork(q, context.userId, scopedNetworkId))
|
|
86
|
-
:
|
|
108
|
+
: permitted;
|
|
87
109
|
const limited = visible.slice(0, limit).map(stripInternalQuestionFields);
|
|
88
110
|
if (isIntentScoped) {
|
|
89
111
|
return success({
|
|
@@ -163,6 +185,13 @@ export function createQuestionerTools(defineTool, deps) {
|
|
|
163
185
|
if (!target) {
|
|
164
186
|
return error("Question not found among the client's pending questions — it may already be answered or dismissed. Re-check with read_pending_questions.");
|
|
165
187
|
}
|
|
188
|
+
// Enforce exact affected-domain inheritance on the resolved target BEFORE
|
|
189
|
+
// any write: the union admission that let this tool run does not grant
|
|
190
|
+
// cross-domain answering (e.g. a manage:intents agent cannot answer a
|
|
191
|
+
// negotiation question). Fail closed with nothing persisted.
|
|
192
|
+
if (!callerMayAccessQuestion(context, target.mode)) {
|
|
193
|
+
return error("You are not authorized to answer this question — it belongs to a domain your agent key does not manage.");
|
|
194
|
+
}
|
|
166
195
|
const answered = await deps.answerPendingQuestion(context.userId, query.questionId, {
|
|
167
196
|
selectedOptions,
|
|
168
197
|
...(freeText ? { freeText } : {}),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type ToolContext, type ResolvedToolContext } from "../../../shared/agent/tool.helpers.js";
|
|
2
|
+
import type { OpportunityOwnerApprovalDeps } from "../../../opportunity/ports/opportunity.tools.port.js";
|
|
2
3
|
export type { ToolContext, ResolvedToolContext, ProtocolDeps } from "../../../shared/agent/tool.helpers.js";
|
|
3
4
|
export type { ToolDeps } from "../../../shared/agent/tool.helpers.js";
|
|
4
5
|
/**
|
|
@@ -9,7 +10,7 @@ export type { ToolDeps } from "../../../shared/agent/tool.helpers.js";
|
|
|
9
10
|
* All external dependencies (cache, integration, queue, etc.) are provided
|
|
10
11
|
* via the `deps` parameter — the protocol lib never imports concrete adapters.
|
|
11
12
|
*/
|
|
12
|
-
export declare function createChatTools(deps: ToolContext, preResolvedContext?: ResolvedToolContext): Promise<any[]>;
|
|
13
|
+
export declare function createChatTools(deps: ToolContext & OpportunityOwnerApprovalDeps, preResolvedContext?: ResolvedToolContext): Promise<any[]>;
|
|
13
14
|
/**
|
|
14
15
|
* Type for the tools array returned by createChatTools.
|
|
15
16
|
*/
|
|
@@ -24,6 +24,7 @@ import { createAgentTools } from "../../../capabilities/participant-agents.tools
|
|
|
24
24
|
import { createNegotiationTools } from "../../../capabilities/negotiation.facade.js";
|
|
25
25
|
import { createPremiseTools } from "../../../premise/premise.tools.js";
|
|
26
26
|
import { createQuestionerTools, createAskUserQuestionTools } from "../../../capabilities/questions.facade.js";
|
|
27
|
+
import { bindOwnerApprovalProvenance } from "../../../opportunity/application/opportunity.owner-provenance.js";
|
|
27
28
|
const logger = protocolLogger("ChatTools");
|
|
28
29
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
29
30
|
// TOOL FACTORY
|
|
@@ -57,6 +58,13 @@ export async function createChatTools(deps, preResolvedContext) {
|
|
|
57
58
|
resolvedContext.scopeType = explicitScope.scopeType;
|
|
58
59
|
resolvedContext.scopeId = explicitScope.scopeId;
|
|
59
60
|
}
|
|
61
|
+
// This factory is an orchestrated chat surface, never a direct owner request.
|
|
62
|
+
// Bind that fact at composition time rather than inferring it from a session
|
|
63
|
+
// id or a caller-controlled tool argument inside the opportunity handler.
|
|
64
|
+
bindOwnerApprovalProvenance(resolvedContext, {
|
|
65
|
+
surface: 'chat',
|
|
66
|
+
sessionAuthenticated: false,
|
|
67
|
+
});
|
|
60
68
|
const allowedNetworkIds = deriveAllowedNetworkIds({
|
|
61
69
|
memberships: resolvedContext.userNetworks,
|
|
62
70
|
...(resolvedContext.scopeType && resolvedContext.scopeId
|
|
@@ -155,8 +163,7 @@ export async function createChatTools(deps, preResolvedContext) {
|
|
|
155
163
|
agentDispatcher: deps.agentDispatcher,
|
|
156
164
|
stampNewbornOpportunities: deps.stampNewbornOpportunities,
|
|
157
165
|
deliveryLedger: deps.deliveryLedger,
|
|
158
|
-
|
|
159
|
-
discoveryRunQueue: deps.discoveryRunQueue,
|
|
166
|
+
...(deps.opportunityOwnerApproval && { opportunityOwnerApproval: deps.opportunityOwnerApproval }),
|
|
160
167
|
enrichmentRuns: deps.enrichmentRuns,
|
|
161
168
|
enrichmentRunQueue: deps.enrichmentRunQueue,
|
|
162
169
|
mintConnectToken: deps.mintConnectToken,
|
|
@@ -172,6 +179,7 @@ export async function createChatTools(deps, preResolvedContext) {
|
|
|
172
179
|
...(deps.chatQuestions && { chatQuestions: deps.chatQuestions }),
|
|
173
180
|
...(deps.chatSession && { chatSession: deps.chatSession }),
|
|
174
181
|
...(deps.getUserContextText && { getUserContextText: deps.getUserContextText }),
|
|
182
|
+
...(deps.intentProposalStore && { intentProposalStore: deps.intentProposalStore }),
|
|
175
183
|
graphs: {
|
|
176
184
|
profile: profileGraph,
|
|
177
185
|
intent: intentGraph,
|
|
@@ -1,11 +1,25 @@
|
|
|
1
1
|
import type { ToolDeps, ToolRegistry } from '../../../shared/agent/tool.helpers.js';
|
|
2
|
+
import type { ToolSurface } from '../../../shared/agent/utility.tools.js';
|
|
3
|
+
import type { OpportunityOwnerApprovalDeps } from '../../../opportunity/ports/opportunity.tools.port.js';
|
|
4
|
+
export interface CreateToolRegistryOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Tool-surface profile. The default `'rest'` profile (direct HTTP Tool API)
|
|
7
|
+
* exposes the full tool set — contact/Gmail tools, `scrape_url`, and the
|
|
8
|
+
* deprecated profile/profile-run compatibility aliases. The restricted
|
|
9
|
+
* `'mcp'` profile omits exactly those surfaces (IND-596/597/598); their
|
|
10
|
+
* non-MCP implementations remain intact for REST and chat.
|
|
11
|
+
*/
|
|
12
|
+
surface?: ToolSurface;
|
|
13
|
+
}
|
|
2
14
|
/**
|
|
3
15
|
* Creates a tool registry containing all tool handlers indexed by name.
|
|
4
16
|
* Handlers are raw async functions (not LangChain tool() wrappers) that
|
|
5
17
|
* accept { context, query } and return a JSON string.
|
|
6
18
|
*
|
|
7
19
|
* @param deps - Shared tool dependencies (graphs, database, embedder, etc.)
|
|
8
|
-
* @param
|
|
20
|
+
* @param options - Surface profile selecting the MCP-restricted or full REST set.
|
|
9
21
|
* @returns Map of tool name to raw tool definition.
|
|
10
22
|
*/
|
|
11
|
-
|
|
23
|
+
/** Complete registry composition with the opportunity-local owner-proof port. */
|
|
24
|
+
export type ToolRegistryDeps = ToolDeps & OpportunityOwnerApprovalDeps;
|
|
25
|
+
export declare function createToolRegistry(deps: ToolRegistryDeps, options?: CreateToolRegistryOptions): ToolRegistry;
|