@indexnetwork/protocol 6.15.0-rc.407.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 +302 -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/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 +9 -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 +9 -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.tools.js +7 -8
- 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
package/CHANGELOG.md
CHANGED
|
@@ -12,10 +12,312 @@ See [STABILITY.md](./STABILITY.md) for the public-contract and tier definitions.
|
|
|
12
12
|
|
|
13
13
|
## [Unreleased]
|
|
14
14
|
|
|
15
|
+
### Added
|
|
16
|
+
- Configurable negotiator stance `NEGOTIATOR_STANCE` (IND-611; 7.11.0), shipped
|
|
17
|
+
dark. `advocate` (default) | `evaluator` | `skeptic`, resolved by the new
|
|
18
|
+
domain contract `configuredNegotiatorStance()`
|
|
19
|
+
(`negotiation/domain/negotiation.stance.contracts.ts`, mirroring
|
|
20
|
+
`configuredScreenMode()`); unset or unrecognized falls back to `advocate`.
|
|
21
|
+
`evaluator` adds an opportunity-cost value bar, asks the agent to assess
|
|
22
|
+
before advocating, and makes discovery-query satisfaction a precondition for
|
|
23
|
+
continuing to evaluate rather than a mandate to connect; `skeptic` adds the
|
|
24
|
+
prior that most candidate matches are not worth making and resolves a
|
|
25
|
+
detected deadlock as a stalemate instead of by concessions.
|
|
26
|
+
**Prompt-only** — seat vocabularies (`allowedActionsFor`), turn schemas, and
|
|
27
|
+
graph routing (including the continuation-screen bypass) are identical under
|
|
28
|
+
all three stances. **`advocate` renders byte-identical prompts** to 7.10.1,
|
|
29
|
+
pinned by an external golden fixture in
|
|
30
|
+
`negotiation/tests/negotiation.stance.spec.ts`. New live eval harness
|
|
31
|
+
`bun run eval:stance` measures decline rate on low-value versus high-value
|
|
32
|
+
fixtures per stance.
|
|
33
|
+
|
|
34
|
+
### Fixed
|
|
35
|
+
- Stop force-rewriting an opening-move refusal (IND-611 prerequisite; 7.11.0):
|
|
36
|
+
`negotiation.graph.ts` ran the turn-0 opening force *before* the IND-564
|
|
37
|
+
opening-withdraw guard, so a v2 initiator that judged a match not worth making
|
|
38
|
+
had its `withdraw` rewritten to `outreach` while its reasoning survived —
|
|
39
|
+
sending the counterparty an outreach that argued against the match — and made
|
|
40
|
+
the guard below it dead code on turn 0. The guard now runs first: a turn-0
|
|
41
|
+
refusal stands and flows into the existing quiet `screened_out` outcome with
|
|
42
|
+
no message persisted, while a genuinely malformed turn-0 opening (e.g.
|
|
43
|
+
`counter`) is still coerced to the opening action.
|
|
44
|
+
- Attribute `outcome.reasoning` to whoever actually decided (IND-611; 7.11.1):
|
|
45
|
+
`screened_out` now has two routes — the screen node, and an opening-turn
|
|
46
|
+
refusal. The finalize node preferred `screenDecision.reasoning` for both,
|
|
47
|
+
which is wrong on the new route when the gate returned `reach_out`: the
|
|
48
|
+
outcome would carry the screen's argument *for* the match as the reason the
|
|
49
|
+
agent did *not* reach out (and IND-610 renders that string in the owner-only
|
|
50
|
+
gate-decision card). An opening-turn refusal now reports the withdrawing
|
|
51
|
+
turn's own reasoning; a genuine screen-node block is unchanged.
|
|
52
|
+
- Add canonical shared guidance source and unified MCP_INSTRUCTIONS/read_docs
|
|
53
|
+
(IND-602/603; 7.10.0): The single normative `CANONICAL_GUIDANCE_SUMMARY`
|
|
54
|
+
(1,555 chars, under the 4,500-char MCP context budget) covers Index Network
|
|
55
|
+
entity model (identity/context, premises, signals, communities/networks,
|
|
56
|
+
opportunities), negotiation semantics with the critical distinction
|
|
57
|
+
**"A2A acceptance is not owner approval"** (separate gates), H2A/A2A
|
|
58
|
+
workflows, and the boundary **"H2H (human-to-human) never exposed; escalation
|
|
59
|
+
to native surfaces (web, Telegram) is outside MCP scope."** Seven detailed
|
|
60
|
+
canonical topics (identity-context, premises, signals, communities-networks,
|
|
61
|
+
opportunities, negotiations, workflows) are published via read_docs on both
|
|
62
|
+
MCP and REST/chat surfaces. MCP surface read_docs serves canonical guidance
|
|
63
|
+
only; REST/chat retains legacy supplemental topics for backwards compatibility.
|
|
64
|
+
New internal shared constants (packages/protocol/src/shared/agent/canonical-guidance.ts):
|
|
65
|
+
`CANONICAL_GUIDANCE_SUMMARY`, `CANONICAL_GUIDANCE_TOPICS` (const array),
|
|
66
|
+
`CANONICAL_GUIDANCE_TOPICS_CONTENT` (record). Not public root protocol exports.
|
|
67
|
+
MCP_INSTRUCTIONS now delegates entity/lifecycle details to read_docs, dropping
|
|
68
|
+
verbose inline model. Published MCP guidance/read_docs contract now includes
|
|
69
|
+
canonical seven-topic structure and H2A/A2A/owner-approval semantics. No data,
|
|
70
|
+
migration, capability, permission, or runtime behavior changes.
|
|
71
|
+
|
|
72
|
+
- Add a host-injected MCP authorization-observability seam (IND-581; 7.8.0):
|
|
73
|
+
`McpAuthorizationObserver`, the secret-free `McpAuthorizationDenialEvent`, and
|
|
74
|
+
the central `buildMcpAuthorizationDenialEvent` constructor, plus an optional
|
|
75
|
+
fifth `authorizationObserver` parameter on `createMcpServer`. Every
|
|
76
|
+
`tools/call` capability denial (preliminary and resolved stages) emits one
|
|
77
|
+
structured event carrying ONLY the caller profile, tool name, decision
|
|
78
|
+
reason/reach, required permissions, and opaque `userId`/`agentId`/
|
|
79
|
+
`networkScopeId` — never a token, API key, bearer credential, raw header, or
|
|
80
|
+
tool-argument payload. The seam is fail-closed: an observer that throws is
|
|
81
|
+
swallowed and never alters the denial. Denials remain freshly resolved per
|
|
82
|
+
reconnect/session because the static tool-metadata cache holds
|
|
83
|
+
principal-independent registration data only; the per-principal decision is
|
|
84
|
+
recomputed on every fresh server resolution.
|
|
85
|
+
|
|
86
|
+
- Add the canonical `read_own_agent` MCP tool: a registered active agent's
|
|
87
|
+
self-read of its OWN sanitized registration record (IND-599; 7.7.0). The input
|
|
88
|
+
schema is empty — there is no target selector, so a caller can never name
|
|
89
|
+
another agent — and the handler resolves strictly the authenticated
|
|
90
|
+
`context.agentId` with an owner match, so a forged target argument is stripped
|
|
91
|
+
by the schema and never queried. The tool is classified `agent_admin` in the
|
|
92
|
+
canonical capability matrix and registered in the shared factory (`fast`
|
|
93
|
+
runtime class).
|
|
94
|
+
|
|
95
|
+
### Changed
|
|
96
|
+
- Pin the generic MCP conversation surface to H2A-only in the published
|
|
97
|
+
contract (IND-600; 7.9.0). This is a distinct public-contract release above
|
|
98
|
+
the integrated 7.8.0 floor (IND-581): the `list_conversations` /
|
|
99
|
+
`get_conversation` descriptions now state explicitly that they expose ONLY
|
|
100
|
+
the caller's H2A chats with the Index agent (orchestrator-persona sessions
|
|
101
|
+
with the system agent as a participant): human-to-human (H2H) DMs are NEVER
|
|
102
|
+
exposed through these tools — including via schema-valid forged `tools/call`
|
|
103
|
+
requests — and A2A negotiation conversations are reachable only through the
|
|
104
|
+
negotiation tools (`list_negotiations` / `get_negotiation` /
|
|
105
|
+
`respond_to_negotiation`), which retain their `manage:negotiations`
|
|
106
|
+
permission, exact-participation, and bound-network-scope checks. The public
|
|
107
|
+
`ChatSessionReader` port contract gains the same category rule: non-H2A
|
|
108
|
+
session IDs behave exactly like nonexistent ones. Runtime enforcement is
|
|
109
|
+
unchanged — the `human_only` capability classification still denies every
|
|
110
|
+
non-session principal before any context DB read, scoped-deps creation, or
|
|
111
|
+
chat-adapter work — so this is a published contract/description
|
|
112
|
+
clarification on public tools, hence the minor bump.
|
|
113
|
+
- Split the `agent_admin` capability family by principal kind (IND-599; 7.7.0).
|
|
114
|
+
Registered agent principals (global/network/delivery) may now see and call
|
|
115
|
+
ONLY `read_own_agent` on the admin surface — `list_agents` is no longer
|
|
116
|
+
visible or callable by an agent (previously it was the sole agent-visible
|
|
117
|
+
admin tool), and every admin mutation remains denied (`agent_admin_denied`).
|
|
118
|
+
Session/onboarding humans retain the full owned-agent administration surface
|
|
119
|
+
(`register_agent`, `list_agents`, `update_agent`, `delete_agent`,
|
|
120
|
+
`grant_agent_permission`, `revoke_agent_permission`) but are denied the
|
|
121
|
+
agent-only `read_own_agent` with the new dedicated decision reason
|
|
122
|
+
`human_read_own_agent_denied`. Enrollment-capable unregistered keys remain
|
|
123
|
+
single-purpose `register_agent`-only across the entire registry, and plain
|
|
124
|
+
unregistered keys remain fail-closed. The `agent_admin` decision is made
|
|
125
|
+
BEFORE the session-human blanket allow, and denials fire before any context
|
|
126
|
+
DB read or scoped-deps creation. Domain, informational (`read_docs`),
|
|
127
|
+
permission/network-scope, and delivery capabilities for registered agents are
|
|
128
|
+
unchanged. Behavior tightening on published MCP tools plus a new public tool
|
|
129
|
+
name, hence the minor bump.
|
|
130
|
+
- Redact private transport connection material from every agent record
|
|
131
|
+
projected by the participant-agent tools (IND-599; 7.7.0).
|
|
132
|
+
`sanitizeAgentForOutput` now empties each transport's `config` (endpoint
|
|
133
|
+
secrets, auth headers/tokens) while preserving the safe response shape
|
|
134
|
+
(id/channel/priority/active/failureCount and permissions), covering
|
|
135
|
+
`read_own_agent`, `register_agent`, `list_agents`, and `update_agent` outputs.
|
|
136
|
+
- Require explicit owner authorization for every owner-gated `update_opportunity`
|
|
137
|
+
transition (send/accept/reject) at a new protocol-owned authoritative boundary
|
|
138
|
+
(IND-593; 7.6.0). The `OpportunityOwnerApprovalAuthority` port is injected by
|
|
139
|
+
the host: registered MCP agents must present an owner-issued, fresh, atomically
|
|
140
|
+
single-use proof bound to the exact opportunity, action, owner principal, acting
|
|
141
|
+
agent, and server-derived interaction — missing/stale/generic/forged/wrong-binding/
|
|
142
|
+
replayed proofs fail closed with stable reasons BEFORE the mutation graph runs,
|
|
143
|
+
and a proof-less agent call returns a fresh interaction challenge. The optional
|
|
144
|
+
`ownerApprovalProof` field is added to the public `update_opportunity` schema.
|
|
145
|
+
Non-agent calls traverse the same boundary via host attestation of typed, trusted,
|
|
146
|
+
server-derived interaction/surface provenance (`OpportunityOwnerInteractionProvenance`):
|
|
147
|
+
only a genuine direct authenticated owner session (REST or MCP) attests; chat/CLI/
|
|
148
|
+
H2A/A2A/mediated surfaces and caller-supplied identity, binding, or provenance
|
|
149
|
+
fields can never mint or attest owner authority (`untrusted_provenance`). A2A
|
|
150
|
+
negotiation approvals, uptake acknowledgements, agent self-acknowledgement, and
|
|
151
|
+
server advisory/challenge values are explicitly non-substitutable. System `expired`
|
|
152
|
+
transitions remain ungated. Behavior tightening on a published MCP tool plus new
|
|
153
|
+
public port types, hence the minor bump. No data action, migration, or deployment
|
|
154
|
+
change ships with this entry.
|
|
155
|
+
|
|
156
|
+
## [7.5.0] — 2026-07-25
|
|
157
|
+
|
|
158
|
+
### Changed
|
|
159
|
+
- Partition async discovery-run ownership by the exact calling MCP principal, not
|
|
160
|
+
only by user (IND-592). `get_discovery_run` and `cancel_discovery_run` now
|
|
161
|
+
reject a run whose recorded principal (session-human vs a specific agent id)
|
|
162
|
+
differs from the caller's, even within the same user, returning the opaque
|
|
163
|
+
"Discovery run not found." and never attempting cancellation. `discover_opportunities`
|
|
164
|
+
MCP coalescing is likewise partitioned by principal, so an agent-initiated
|
|
165
|
+
request never coalesces onto — and is never handed — the owner's (or another
|
|
166
|
+
agent's) in-flight run id or its status/results. The store lookup remains
|
|
167
|
+
user-scoped; this is an additional in-handler/domain narrowing with no host
|
|
168
|
+
interface change. Behavior tightening on published MCP tools, hence the minor bump.
|
|
169
|
+
|
|
170
|
+
## [7.4.0] — 2026-07-25
|
|
171
|
+
|
|
172
|
+
### Changed
|
|
173
|
+
- Make the public participant-agent permission INPUT schemas canonical-only:
|
|
174
|
+
`register_agent.permissions` and `grant_agent_permission.actions` are now a
|
|
175
|
+
`z.enum` of the six canonical `manage:*` actions instead of `z.array(z.string())`.
|
|
176
|
+
Retired `manage:profile` / `manage:contacts` strings are rejected at the schema
|
|
177
|
+
seam (the handler's `isValidAction` check is retained as defense in depth). This
|
|
178
|
+
narrows the published tool input schemas exposed via `tools/list`, hence the
|
|
179
|
+
minor bump. No change to the temporary stored-row compatibility projection,
|
|
180
|
+
which still interprets residual legacy STORED rows.
|
|
181
|
+
|
|
182
|
+
## [7.3.0] — 2026-07-25
|
|
183
|
+
|
|
15
184
|
### Added
|
|
16
185
|
- Add the injected `IntentProposalStore` host boundary so web proposal cards are
|
|
17
186
|
emitted only after the normalized description, optional network scope, and
|
|
18
187
|
complete verifier output have been durably bound to their owner.
|
|
188
|
+
- Add `projectStoredPermissionActions` at the MCP capability-loading boundary:
|
|
189
|
+
temporary rolling-data compatibility that interprets residual **stored** legacy
|
|
190
|
+
grant rows during a mixed-version deploy (`manage:profile` →
|
|
191
|
+
`manage:identity` + `manage:premises`; `manage:contacts` → no capability;
|
|
192
|
+
owner/scope preserved; unknown actions fail closed). Not a public alias — legacy
|
|
193
|
+
names remain rejected as input and absent from `tools/list`/docs. Removed only
|
|
194
|
+
after the post-drain final sweep and compatibility gate (see the IND-609
|
|
195
|
+
rollout doc).
|
|
196
|
+
|
|
197
|
+
### Changed
|
|
198
|
+
- **MCP permission migration (IND-606/607).** Retire issuance of the legacy
|
|
199
|
+
`manage:profile` and `manage:contacts` grant actions in favor of
|
|
200
|
+
`manage:identity` and `manage:premises`. Issuers, defaults, validation, and the
|
|
201
|
+
capability policy emit/accept only the canonical action set; the durable data
|
|
202
|
+
migration (`services/api/drizzle/0109_migrate_agent_permission_actions.sql`)
|
|
203
|
+
converges existing grants (`manage:profile` → `manage:identity` + `manage:premises`;
|
|
204
|
+
`manage:contacts` removed). No public protocol type changes.
|
|
205
|
+
- **Exact question affected-domain inheritance (IND-608).** `read_pending_questions`
|
|
206
|
+
and `answer_pending_question` now enforce each question's exact affected-domain
|
|
207
|
+
permission at the handler, not merely the union that admits the tool. A global
|
|
208
|
+
`manage:intents` agent can no longer read or answer negotiation/enrichment/
|
|
209
|
+
discovery questions it does not manage; the owning human is unaffected.
|
|
210
|
+
- **Corrected `QUESTION_MODE_TO_DOMAIN` mapping.** `enrichment` now maps to the
|
|
211
|
+
`premises` domain (`manage:premises`), matching the enrichment answer pipeline
|
|
212
|
+
that runs the PremiseGraph lifecycle. Previously mapped to `identity`. This
|
|
213
|
+
changes the exported constant's `enrichment` value and the
|
|
214
|
+
`read_activity_summary` projection of enrichment question counts from the
|
|
215
|
+
identity domain to the premises domain — the deliberate public-constant change
|
|
216
|
+
motivating this minor bump from the 7.2.0 floor.
|
|
217
|
+
|
|
218
|
+
## [7.2.0] — 2026-07-25
|
|
219
|
+
|
|
220
|
+
### Added
|
|
221
|
+
- Add `read_activity_summary` as the single public name for grounded,
|
|
222
|
+
aggregate-only agent activity reporting (IND-605). The MCP capability matrix
|
|
223
|
+
admits any caller holding at least one activity-domain permission
|
|
224
|
+
(`manage:identity`/`manage:premises`/`manage:intents`/`manage:opportunities`/
|
|
225
|
+
`manage:negotiations`); the handler then passes the typed resolved MCP caller
|
|
226
|
+
context into one centralized permission projection, so global agents receive
|
|
227
|
+
only the domains their permissions authorize while session humans receive the
|
|
228
|
+
full owner view. Signal IDs/titles (`opportunitiesBySignal`) are exposed only
|
|
229
|
+
with `manage:intents`, and question counts are meta-network — never network
|
|
230
|
+
filtered — while each count inherits the permission of the domain the
|
|
231
|
+
question affects: the adapter groups pending/answered counts by question
|
|
232
|
+
mode and the projection releases only the affected-domain counts
|
|
233
|
+
(identity/premises/intents/opportunities/negotiations) the caller is
|
|
234
|
+
authorized for, with conversational `chat`-mode and unrecognized modes
|
|
235
|
+
human-owner-only. There is deliberately no any-of all-question count
|
|
236
|
+
shortcut. A network agent's network-bound aggregates (opportunity and
|
|
237
|
+
negotiation counts) are narrowed to its bound community inside the
|
|
238
|
+
query/adapter layer via the new optional `getAgentActivitySummary`
|
|
239
|
+
`networkId` input — never by transport-local JSON filtering. The response
|
|
240
|
+
never contains counterparty identities, chats, turns, transcripts, or
|
|
241
|
+
private content, and validates against the new strict
|
|
242
|
+
`ActivitySummaryResponseSchema`.
|
|
243
|
+
- Export the centralized activity-projection contract
|
|
244
|
+
(`READ_ACTIVITY_SUMMARY_TOOL_NAME`, `McpActivityCallerSchema`,
|
|
245
|
+
`ActivitySummaryDomainSchema`, `ActivitySummaryResponseSchema`,
|
|
246
|
+
`ActivityQuestionDomainSchema`, `ActivityQuestionCountsSchema`,
|
|
247
|
+
`QUESTION_MODE_TO_DOMAIN`, `resolveMcpActivityCaller`,
|
|
248
|
+
`resolveActivitySummaryDomains`, `activitySummaryNetworkId`,
|
|
249
|
+
`projectActivitySummary`, and their types) for host and capability
|
|
250
|
+
composition.
|
|
251
|
+
|
|
252
|
+
### Changed
|
|
253
|
+
- The internal reporter persona now consumes the canonical
|
|
254
|
+
`read_activity_summary` as the same tool (no persona-specific fork);
|
|
255
|
+
unrelated REST/chat behavior is unchanged.
|
|
256
|
+
- SemVer rationale: on MCP this release is purely additive —
|
|
257
|
+
`report_agent_activity` was already denied as `removed` since 7.0.0, so no
|
|
258
|
+
working MCP integration can break. The REST/chat tool rename retires a
|
|
259
|
+
same-cycle (7.0.0-era) surface with no alias by deliberate product decision,
|
|
260
|
+
so a minor bump records the change without a major. Recorded here for
|
|
261
|
+
integration-owner reconciliation.
|
|
262
|
+
|
|
263
|
+
### Removed
|
|
264
|
+
- `report_agent_activity` is retired on every surface with no hidden legacy
|
|
265
|
+
alias. It is no longer registered in either tool-registry profile and
|
|
266
|
+
carries no canonical access rule, so a forged MCP `tools/call` under the old
|
|
267
|
+
name is rejected as an unknown tool before any authorization, database, or
|
|
268
|
+
graph work. The `'removed'` access classification remains available in the
|
|
269
|
+
extension contract but no canonical tool uses it.
|
|
270
|
+
|
|
271
|
+
## [7.1.0] — 2026-07-25
|
|
272
|
+
|
|
273
|
+
### Changed
|
|
274
|
+
- Complete the MCP legacy-surface removal declared in 7.0.0 (IND-596/597/598).
|
|
275
|
+
`createToolRegistry` is now surface-aware: the default `'rest'` profile (direct
|
|
276
|
+
HTTP Tool API + chat) retains contact/Gmail-import tools, `scrape_url`, and the
|
|
277
|
+
deprecated `*_user_profile` / `*_profile_run` compatibility aliases, while the
|
|
278
|
+
restricted `'mcp'` profile omits all of them. The MCP server builds both its
|
|
279
|
+
`tools/list` metadata and its `tools/call` lookup from the `'mcp'` profile, so
|
|
280
|
+
the removed names are no longer registered on the MCP surface — a direct
|
|
281
|
+
`tools/call` for any of them now fails as an unknown tool before any work.
|
|
282
|
+
- MCP `read_docs` guidance is sanitized by the MCP surface profile (never by
|
|
283
|
+
`CONTACTS_ENABLED`) so it no longer advertises the removed contact/Gmail
|
|
284
|
+
workflows; REST/chat `read_docs` retains the full guidance.
|
|
285
|
+
- `CONTACTS_ENABLED` no longer shapes the MCP registry or its metadata cache key.
|
|
286
|
+
|
|
287
|
+
### Removed
|
|
288
|
+
- The `add_contact`, `import_contacts`, `import_gmail_contacts`, `list_contacts`,
|
|
289
|
+
`remove_contact`, `search_contacts`, `scrape_url`, `read_user_profiles`,
|
|
290
|
+
`create_user_profile`, `update_user_profile`, `confirm_user_profile`,
|
|
291
|
+
`preview_user_profile`, `get_profile_run`, and `cancel_profile_run` entries are
|
|
292
|
+
removed from the canonical MCP capability matrix; the tools are omitted from the
|
|
293
|
+
MCP registry rather than classified. Their non-MCP implementations (REST Tool
|
|
294
|
+
API, dedicated contact REST endpoints, chat agent, shared runtime
|
|
295
|
+
classifications) are unchanged.
|
|
296
|
+
|
|
297
|
+
## [7.0.0] — 2026-07-25
|
|
298
|
+
|
|
299
|
+
### Breaking
|
|
300
|
+
- MCP capability discovery is now principal-aware. `tools/list` advertises only
|
|
301
|
+
the tools available to the resolved human, onboarding, enrollment-key,
|
|
302
|
+
registered-agent, network-agent, or delivery-agent profile; `tools/call`
|
|
303
|
+
repeats the same authorization before scoped database and handler work.
|
|
304
|
+
- Replace the agent permission actions `manage:profile` and `manage:contacts`
|
|
305
|
+
with the canonical `manage:identity` and `manage:premises` actions. The full
|
|
306
|
+
MCP permission vocabulary is now `manage:identity`, `manage:premises`,
|
|
307
|
+
`manage:intents`, `manage:networks`, `manage:opportunities`, and
|
|
308
|
+
`manage:negotiations`.
|
|
309
|
+
- Contact tools, Gmail contact import, `scrape_url`, `report_agent_activity`,
|
|
310
|
+
and deprecated profile/profile-run aliases are explicitly unavailable
|
|
311
|
+
through MCP. Their non-MCP implementations remain intact.
|
|
312
|
+
- Agent-administration mutations are session-human-only. Enrollment keys may
|
|
313
|
+
call `register_agent` only when explicitly enrollment-capable; registered
|
|
314
|
+
agents may list only their own sanitized registration. Opportunity delivery
|
|
315
|
+
confirmation is exposed only to designated delivery agents.
|
|
316
|
+
|
|
317
|
+
### Added
|
|
318
|
+
- Export a runtime-validated canonical MCP tool access matrix, permission/reach
|
|
319
|
+
extension contracts, principal schemas, and reusable capability-policy
|
|
320
|
+
implementation for host and capability composition.
|
|
19
321
|
|
|
20
322
|
## [6.14.0] — 2026-07-25
|
|
21
323
|
|
package/IMPLEMENTATION.md
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
This guide covers the technical package surface for implementers embedding the canonical Index Network Protocol implementation. For the public protocol overview, see [README.md](./README.md).
|
|
4
4
|
|
|
5
|
-
The package implements LangGraph-based workflows for signal processing, opportunity discovery, negotiation, and chat — decoupled from any specific infrastructure via adapter injection.
|
|
6
5
|
|
|
7
6
|
## Stability & versioning
|
|
8
7
|
|
|
@@ -227,7 +226,12 @@ On every tool call the server:
|
|
|
227
226
|
|
|
228
227
|
1. Extracts the HTTP request from the MCP `ServerContext`.
|
|
229
228
|
2. Calls `authResolver.resolveIdentity(req)` to get `{ userId, agentId }`.
|
|
230
|
-
3. Gates access
|
|
229
|
+
3. Gates access through the canonical capability policy (`mcp/mcp.authorization-policy.ts`), decided per resolved principal BEFORE any context read or scoped-deps creation:
|
|
230
|
+
- **Enrollment-capable unregistered API keys** may see and call only `register_agent` — single-purpose across the entire registry.
|
|
231
|
+
- **Plain unregistered API keys** fail closed on every tool.
|
|
232
|
+
- **Registered active agents** retain their canonical permission- and network-scope-authorized domain tools, `read_docs`, and (for designated delivery agents) `confirm_opportunity_delivery`; within the agent-administration family (`MCP_AGENT_ADMIN_TOOLS`) they may see and call only `read_own_agent`, which returns the caller's own sanitized record and accepts no target.
|
|
233
|
+
- **Session humans** administer their owned agents (`register_agent`, `list_agents`, `update_agent`, `delete_agent`, `grant_agent_permission`, `revoke_agent_permission`) but are never offered the agent-only `read_own_agent`.
|
|
234
|
+
- Contact/Gmail-import tools, `scrape_url`, and the deprecated `*_user_profile`/`*_profile_run` aliases are not registered on the MCP surface at all (IND-596/597/598).
|
|
231
235
|
4. Builds per-request scoped databases via `scopedDepsFactory` and invokes the tool handler through the shared runtime.
|
|
232
236
|
|
|
233
237
|
### Runtime controls
|
|
@@ -240,9 +244,8 @@ MCP tools are bounded by `ToolInvocationRuntime`:
|
|
|
240
244
|
| `bounded_slow` | 45 s | `MCP_TOOL_TIMEOUT_BOUNDED_SLOW_MS` |
|
|
241
245
|
| `async_candidate` | 50 s | `MCP_TOOL_TIMEOUT_ASYNC_CANDIDATE_MS` |
|
|
242
246
|
|
|
243
|
-
Per-tool timeout overrides use `MCP_TOOL_TIMEOUT_<TOOL_NAME>_MS
|
|
247
|
+
Per-tool timeout overrides use `MCP_TOOL_TIMEOUT_<TOOL_NAME>_MS`. Tool outputs are capped by `MCP_TOOL_MAX_OUTPUT_BYTES` (default `1000000`) or `MCP_TOOL_MAX_OUTPUT_<TOOL_NAME>_BYTES`; inbound MCP request bodies are capped by the backend with `MCP_MAX_REQUEST_BYTES` (default `1000000`). Runtime failures return JSON text envelopes with stable `code` values: `TOOL_TIMEOUT`, `TOOL_CANCELLED`, or `TOOL_OUTPUT_TOO_LARGE`.
|
|
244
248
|
|
|
245
|
-
For MCP callers, `discover_opportunities` is async: it returns a `discoveryRunId` immediately, and clients poll `get_discovery_run` or request cancellation with `cancel_discovery_run`. Non-MCP chat/web paths stay synchronous.
|
|
246
249
|
|
|
247
250
|
### `MCP_INSTRUCTIONS`
|
|
248
251
|
|
|
@@ -39,9 +39,13 @@ export { canUserSeeOpportunity, isActionableForViewer, validateOpportunityActors
|
|
|
39
39
|
export { getPrimaryActionLabel } from "../opportunity/domain/opportunity.labels.js";
|
|
40
40
|
export { computeFeedHealth } from "../opportunity/feed/feed.health.js";
|
|
41
41
|
export type { FeedHealthInput } from "../opportunity/feed/feed.health.js";
|
|
42
|
+
export { isIntroducerDiscoveryEnabled } from "../opportunity/application/opportunity.introducer-feature.js";
|
|
42
43
|
export { selectContactsForDiscovery, shouldRunIntroducerDiscovery, runIntroducerDiscovery, MAX_CONTACTS_PER_CYCLE, MAX_CANDIDATES_PER_CONTACT, INTRODUCER_DISCOVERY_SOURCE } from "../opportunity/application/opportunity.introducer.js";
|
|
43
44
|
export type { IntroducerDiscoveryDatabase, IntroducerDiscoveryQueue, ContactWithIntents } from "../opportunity/application/opportunity.introducer.js";
|
|
44
45
|
export { persistOpportunities } from "../opportunity/application/opportunity.persist.js";
|
|
46
|
+
export { opportunityOwnerActionForStatus } from "../opportunity/application/opportunity.owner-approval.js";
|
|
47
|
+
export { bindOwnerApprovalProvenance } from "../opportunity/application/opportunity.owner-provenance.js";
|
|
48
|
+
export type { OpportunityOwnerAction, OpportunityOwnerApprovalAttestation, OpportunityOwnerApprovalAuthority, OpportunityOwnerApprovalBinding, OpportunityOwnerApprovalChallenge, OpportunityOwnerApprovalDenialReason, OpportunityOwnerApprovalVerdict, OpportunityOwnerInteractionProvenance, OpportunityOwnerInteractionSurface, } from "../opportunity/application/opportunity.owner-approval.js";
|
|
45
49
|
export { presentOpportunity, stripUuids, truncateAtBoundary } from "../opportunity/domain/opportunity.presentation.js";
|
|
46
50
|
export type { UserInfo } from "../opportunity/domain/opportunity.presentation.js";
|
|
47
51
|
export { stripUnsupportedOpportunityClaims as stripUnsupportedOpportunityClaimsText } from "../opportunity/domain/opportunity.claim-safety.js";
|
|
@@ -39,9 +39,13 @@ export { canUserSeeOpportunity, isActionableForViewer, validateOpportunityActors
|
|
|
39
39
|
export { getPrimaryActionLabel } from "../opportunity/domain/opportunity.labels.js";
|
|
40
40
|
export { computeFeedHealth } from "../opportunity/feed/feed.health.js";
|
|
41
41
|
// ── Introducer / ambient discovery ───────────────────────────────────────────
|
|
42
|
+
export { isIntroducerDiscoveryEnabled } from "../opportunity/application/opportunity.introducer-feature.js";
|
|
42
43
|
export { selectContactsForDiscovery, shouldRunIntroducerDiscovery, runIntroducerDiscovery, MAX_CONTACTS_PER_CYCLE, MAX_CANDIDATES_PER_CONTACT, INTRODUCER_DISCOVERY_SOURCE } from "../opportunity/application/opportunity.introducer.js";
|
|
43
44
|
// ── Persistence ───────────────────────────────────────────────────────────────
|
|
44
45
|
export { persistOpportunities } from "../opportunity/application/opportunity.persist.js";
|
|
46
|
+
// ── Owner-approval boundary (IND-593) ─────────────────────────────────
|
|
47
|
+
export { opportunityOwnerActionForStatus } from "../opportunity/application/opportunity.owner-approval.js";
|
|
48
|
+
export { bindOwnerApprovalProvenance } from "../opportunity/application/opportunity.owner-provenance.js";
|
|
45
49
|
// ── Presentation utilities ────────────────────────────────────────────────────
|
|
46
50
|
export { presentOpportunity, stripUuids, truncateAtBoundary } from "../opportunity/domain/opportunity.presentation.js";
|
|
47
51
|
export { stripUnsupportedOpportunityClaims as stripUnsupportedOpportunityClaimsText } from "../opportunity/domain/opportunity.claim-safety.js";
|
|
@@ -324,14 +324,14 @@ export interface DebugMetaLlm {
|
|
|
324
324
|
}>;
|
|
325
325
|
}
|
|
326
326
|
/**
|
|
327
|
-
* Negotiation sessions
|
|
327
|
+
* Negotiation sessions recorded during this turn.
|
|
328
328
|
*/
|
|
329
329
|
export interface DebugMetaOrchestratorNegotiations {
|
|
330
330
|
/** Opportunity IDs for which a negotiation_session_start was emitted. */
|
|
331
331
|
opportunityIds: string[];
|
|
332
332
|
}
|
|
333
333
|
/**
|
|
334
|
-
* Decision-question generation debug data
|
|
334
|
+
* Decision-question generation debug data.
|
|
335
335
|
*/
|
|
336
336
|
export interface DebugMetaDiscoveryQuestions {
|
|
337
337
|
inputMode: "transcripts" | "insights";
|
|
@@ -349,7 +349,7 @@ export interface DebugMetaEvent extends ChatStreamEventBase {
|
|
|
349
349
|
tools: DebugMetaToolCall[];
|
|
350
350
|
llm: DebugMetaLlm;
|
|
351
351
|
orchestratorNegotiations?: DebugMetaOrchestratorNegotiations;
|
|
352
|
-
/** Decision-question generation debug data
|
|
352
|
+
/** Decision-question generation debug data. */
|
|
353
353
|
discoveryQuestions?: DebugMetaDiscoveryQuestions;
|
|
354
354
|
}
|
|
355
355
|
/** Graph start event — emitted when a LangGraph sub-graph begins inside a tool. */
|
|
@@ -392,7 +392,7 @@ export interface AgentEndEvent extends ChatStreamEventBase {
|
|
|
392
392
|
/** Structured outcome summary, e.g. "5 of 12 passed" or "3 intents extracted". */
|
|
393
393
|
summary: string;
|
|
394
394
|
}
|
|
395
|
-
/**
|
|
395
|
+
/** Per-candidate negotiation wrapper emitted from `negotiateCandidates`. */
|
|
396
396
|
export interface NegotiationSessionStartEvent extends ChatStreamEventBase {
|
|
397
397
|
type: "negotiation_session_start";
|
|
398
398
|
opportunityId: string;
|
|
@@ -402,7 +402,6 @@ export interface NegotiationSessionStartEvent extends ChatStreamEventBase {
|
|
|
402
402
|
/** The user holding the initiating seat for this match (v2 stamp). */
|
|
403
403
|
initiatorUserId?: string;
|
|
404
404
|
candidateName?: string;
|
|
405
|
-
trigger: "orchestrator" | "ambient";
|
|
406
405
|
startedAt: number;
|
|
407
406
|
}
|
|
408
407
|
export interface NegotiationSessionEndEvent extends ChatStreamEventBase {
|
|
@@ -3,7 +3,6 @@ import type { ToolContext } from "../shared/agent/tool.factory.js";
|
|
|
3
3
|
import { type ChatPersonaConfig } from "./chat.persona.js";
|
|
4
4
|
import type { DebugMetaToolCall, DebugMetaLlm, DebugMetaOrchestratorNegotiations, DebugMetaDiscoveryQuestions } from "./chat-streaming.types.js";
|
|
5
5
|
import type { Question, QuestionStrategy } from "../shared/schemas/question.schema.js";
|
|
6
|
-
import type { Opportunity } from "../shared/interfaces/database.interface.js";
|
|
7
6
|
export { ITERATION_NUDGE } from "./chat.prompt.js";
|
|
8
7
|
/**
|
|
9
8
|
* Writer callback for streaming custom data out of the graph node.
|
|
@@ -22,8 +21,6 @@ export type StreamWriter = (data: unknown) => void;
|
|
|
22
21
|
* - `graph_end` — a LangGraph sub-graph completes
|
|
23
22
|
* - `agent_start` — an LLM agent begins inside a graph node
|
|
24
23
|
* - `agent_end` — an LLM agent completes
|
|
25
|
-
* - `opportunity_draft_ready` — an orchestrator-triggered negotiation finalized
|
|
26
|
-
* to `draft` and the card is ready to render inline
|
|
27
24
|
*/
|
|
28
25
|
export type AgentStreamEvent = {
|
|
29
26
|
type: "iteration_start";
|
|
@@ -83,16 +80,6 @@ export type AgentStreamEvent = {
|
|
|
83
80
|
name: string;
|
|
84
81
|
durationMs: number;
|
|
85
82
|
summary: string;
|
|
86
|
-
} | {
|
|
87
|
-
type: "opportunity_draft_ready";
|
|
88
|
-
opportunityId: string;
|
|
89
|
-
opportunity: Opportunity;
|
|
90
|
-
/** Viewer-centric summary derived from interpretation.reasoning via viewerCentricCardSummary. */
|
|
91
|
-
personalizedSummary?: string;
|
|
92
|
-
counterparty: {
|
|
93
|
-
userId: string;
|
|
94
|
-
name?: string;
|
|
95
|
-
};
|
|
96
83
|
} | {
|
|
97
84
|
type: "negotiation_session_start";
|
|
98
85
|
opportunityId: string;
|
|
@@ -100,7 +87,6 @@ export type AgentStreamEvent = {
|
|
|
100
87
|
sourceUserId: string;
|
|
101
88
|
candidateUserId: string;
|
|
102
89
|
candidateName?: string;
|
|
103
|
-
trigger: "orchestrator" | "ambient";
|
|
104
90
|
startedAt: number;
|
|
105
91
|
} | {
|
|
106
92
|
type: "negotiation_session_end";
|
|
@@ -255,11 +241,6 @@ export declare class ChatAgent {
|
|
|
255
241
|
* Execute tool calls, potentially in parallel.
|
|
256
242
|
*/
|
|
257
243
|
private executeToolCalls;
|
|
258
|
-
/**
|
|
259
|
-
* When discover_opportunities returned createIntentSuggested, call create_intent then discover_opportunities.
|
|
260
|
-
* Returns the new discover_opportunities result string or null if no callback / create_intent failed.
|
|
261
|
-
*/
|
|
262
|
-
private handleCreateIntentCallback;
|
|
263
244
|
/**
|
|
264
245
|
* Check whether any tool call produced valid opportunity blocks.
|
|
265
246
|
* Both `discover_opportunities` and `list_opportunities` can return
|
package/dist/chat/chat.agent.js
CHANGED
|
@@ -330,13 +330,6 @@ export class ChatAgent {
|
|
|
330
330
|
logger.verbose("Executing tool", { name: tc.name, args: tc.args });
|
|
331
331
|
let result = await tool.invoke(tc.args);
|
|
332
332
|
let resultStr = typeof result === "string" ? result : JSON.stringify(result);
|
|
333
|
-
if (tc.name === "discover_opportunities" && this.persona.loopBehaviors.createIntentCallback) {
|
|
334
|
-
const newResult = await this.handleCreateIntentCallback(resultStr, tc.args);
|
|
335
|
-
if (newResult !== null) {
|
|
336
|
-
resultStr = newResult;
|
|
337
|
-
result = newResult;
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
333
|
logger.debug("Tool response", { name: tc.name, result: resultStr });
|
|
341
334
|
logger.verbose("Tool completed", {
|
|
342
335
|
name: tc.name,
|
|
@@ -365,59 +358,13 @@ export class ChatAgent {
|
|
|
365
358
|
}));
|
|
366
359
|
return results;
|
|
367
360
|
}
|
|
368
|
-
/**
|
|
369
|
-
* When discover_opportunities returned createIntentSuggested, call create_intent then discover_opportunities.
|
|
370
|
-
* Returns the new discover_opportunities result string or null if no callback / create_intent failed.
|
|
371
|
-
*/
|
|
372
|
-
async handleCreateIntentCallback(resultStr, originalArgs) {
|
|
373
|
-
let parsed;
|
|
374
|
-
try {
|
|
375
|
-
parsed = JSON.parse(resultStr);
|
|
376
|
-
}
|
|
377
|
-
catch {
|
|
378
|
-
return null;
|
|
379
|
-
}
|
|
380
|
-
if (!parsed?.data?.createIntentSuggested ||
|
|
381
|
-
typeof parsed.data.suggestedIntentDescription !== "string") {
|
|
382
|
-
return null;
|
|
383
|
-
}
|
|
384
|
-
// Never auto-create intents during introducer flows — signals are personal
|
|
385
|
-
if (originalArgs.introTargetUserId) {
|
|
386
|
-
return null;
|
|
387
|
-
}
|
|
388
|
-
const createIntentTool = this.toolsByName.get("create_intent");
|
|
389
|
-
const discoverOpportunitiesTool = this.toolsByName.get("discover_opportunities");
|
|
390
|
-
if (!createIntentTool || !discoverOpportunitiesTool)
|
|
391
|
-
return null;
|
|
392
|
-
logger.verbose("Create-intent signal: auto-calling create_intent then discover_opportunities");
|
|
393
|
-
const createIntentResult = await createIntentTool.invoke({
|
|
394
|
-
description: parsed.data.suggestedIntentDescription,
|
|
395
|
-
networkId: originalArgs.networkId,
|
|
396
|
-
});
|
|
397
|
-
const createIntentStr = typeof createIntentResult === "string" ? createIntentResult : JSON.stringify(createIntentResult);
|
|
398
|
-
let createIntentParsed;
|
|
399
|
-
try {
|
|
400
|
-
createIntentParsed = JSON.parse(createIntentStr);
|
|
401
|
-
}
|
|
402
|
-
catch {
|
|
403
|
-
createIntentParsed = {};
|
|
404
|
-
}
|
|
405
|
-
if (createIntentParsed.success === false) {
|
|
406
|
-
logger.warn("Create-intent failed; not re-running discover_opportunities", {
|
|
407
|
-
error: createIntentParsed.error,
|
|
408
|
-
});
|
|
409
|
-
return null;
|
|
410
|
-
}
|
|
411
|
-
const newResult = await discoverOpportunitiesTool.invoke(originalArgs);
|
|
412
|
-
return typeof newResult === "string" ? newResult : JSON.stringify(newResult);
|
|
413
|
-
}
|
|
414
361
|
/**
|
|
415
362
|
* Check whether any tool call produced valid opportunity blocks.
|
|
416
363
|
* Both `discover_opportunities` and `list_opportunities` can return
|
|
417
364
|
* ```opportunity code blocks — either one counts as a valid source.
|
|
418
365
|
*/
|
|
419
366
|
static hasOpportunitySource(toolsUsed) {
|
|
420
|
-
return toolsUsed.some((t) =>
|
|
367
|
+
return toolsUsed.some((t) => t.name === "list_opportunities" &&
|
|
421
368
|
t.success &&
|
|
422
369
|
!t.resultSummary?.startsWith("Found 0") &&
|
|
423
370
|
!t.resultSummary?.startsWith("No matches") &&
|
|
@@ -441,15 +388,6 @@ export class ChatAgent {
|
|
|
441
388
|
return { type: "intent_proposal", tool: "create_intent", description: match[1] };
|
|
442
389
|
}
|
|
443
390
|
}
|
|
444
|
-
// Check for hallucinated opportunity blocks
|
|
445
|
-
if (text.includes("```opportunity") && !ChatAgent.hasOpportunitySource(toolsUsed)) {
|
|
446
|
-
// Use the user's original message as the search query — NOT fields from the
|
|
447
|
-
// hallucinated JSON. The model fabricates person names and reasoning that have
|
|
448
|
-
// nothing to do with the user's actual request, leading to wrong results and
|
|
449
|
-
// the model re-calling the tool with the correct query (doubling negotiation cost).
|
|
450
|
-
const description = userMessage?.trim() || "find connections";
|
|
451
|
-
return { type: "opportunity", tool: "discover_opportunities", description };
|
|
452
|
-
}
|
|
453
391
|
return null;
|
|
454
392
|
}
|
|
455
393
|
/**
|
|
@@ -501,13 +439,6 @@ export class ChatAgent {
|
|
|
501
439
|
*/
|
|
502
440
|
async normalizeToolResult(toolName, resultStr, toolArgs) {
|
|
503
441
|
let normalized = resultStr;
|
|
504
|
-
// Run create_intent callback for discover_opportunities results (orchestrator behavior)
|
|
505
|
-
if (toolName === "discover_opportunities" && this.persona.loopBehaviors.createIntentCallback) {
|
|
506
|
-
const callbackResult = await this.handleCreateIntentCallback(normalized, toolArgs);
|
|
507
|
-
if (callbackResult !== null) {
|
|
508
|
-
normalized = callbackResult;
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
442
|
let summary = "Done";
|
|
512
443
|
let debugSteps;
|
|
513
444
|
let graphTimings;
|
|
@@ -5,12 +5,6 @@ import type { IterationContext } from "./chat.prompt.modules.js";
|
|
|
5
5
|
* (not in the prompt or toolset). Each persona opts in explicitly.
|
|
6
6
|
*/
|
|
7
7
|
export interface ChatPersonaLoopBehaviors {
|
|
8
|
-
/**
|
|
9
|
-
* When `discover_opportunities` returns `createIntentSuggested`, auto-invoke
|
|
10
|
-
* `create_intent` and then re-run `discover_opportunities` with the original
|
|
11
|
-
* arguments.
|
|
12
|
-
*/
|
|
13
|
-
createIntentCallback: boolean;
|
|
14
8
|
/**
|
|
15
9
|
* Detect hallucinated ```opportunity / ```intent_proposal code blocks in model
|
|
16
10
|
* text, auto-invoke the corresponding tool, and strip unbacked blocks from the
|
|
@@ -19,7 +19,6 @@ export const ORCHESTRATOR_PERSONA = {
|
|
|
19
19
|
buildSystemContent: (ctx, iterCtx) => buildSystemContent(ctx, iterCtx),
|
|
20
20
|
createTools: (deps, preResolvedContext) => createChatTools(deps, preResolvedContext),
|
|
21
21
|
loopBehaviors: {
|
|
22
|
-
createIntentCallback: true,
|
|
23
22
|
hallucinationRecovery: true,
|
|
24
23
|
},
|
|
25
24
|
};
|