@indexnetwork/protocol 14.3.2-rc.477.1 → 16.1.1-rc.478.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/CHANGELOG.md +107 -0
  2. package/IMPLEMENTATION.md +50 -52
  3. package/STABILITY.md +3 -3
  4. package/dist/chat/chat.agent.js +2 -2
  5. package/dist/chat/chat.graph.d.ts +41 -1
  6. package/dist/chat/chat.graph.js +108 -127
  7. package/dist/discovery/hyde.frame.d.ts +4 -4
  8. package/dist/discovery/hyde.graph.d.ts +71 -12
  9. package/dist/discovery/hyde.graph.js +337 -335
  10. package/dist/discovery/lens.inferrer.d.ts +6 -6
  11. package/dist/enrichment/enrichment.graph.d.ts +127 -9
  12. package/dist/enrichment/enrichment.graph.js +633 -655
  13. package/dist/enrichment/enrichment.state.d.ts +1 -1
  14. package/dist/enrichment/enrichment.tools.context-read.d.ts +10 -0
  15. package/dist/enrichment/enrichment.tools.context-read.js +353 -0
  16. package/dist/enrichment/enrichment.tools.context-write.d.ts +9 -0
  17. package/dist/enrichment/enrichment.tools.context-write.js +417 -0
  18. package/dist/enrichment/enrichment.tools.d.ts +11 -1
  19. package/dist/enrichment/enrichment.tools.helpers.d.ts +139 -0
  20. package/dist/enrichment/enrichment.tools.helpers.js +234 -0
  21. package/dist/enrichment/enrichment.tools.js +16 -975
  22. package/dist/index.d.ts +27 -48
  23. package/dist/index.js +17 -27
  24. package/dist/intents/application/intent.graph.d.ts +71 -67
  25. package/dist/intents/application/intent.graph.execute.d.ts +59 -0
  26. package/dist/intents/application/intent.graph.execute.js +301 -0
  27. package/dist/intents/application/intent.graph.infer.d.ts +44 -0
  28. package/dist/intents/application/intent.graph.infer.js +97 -0
  29. package/dist/intents/application/intent.graph.js +96 -888
  30. package/dist/intents/application/intent.graph.reconcile.d.ts +71 -0
  31. package/dist/intents/application/intent.graph.reconcile.js +274 -0
  32. package/dist/intents/application/intent.graph.shared.d.ts +70 -0
  33. package/dist/intents/application/intent.graph.shared.js +153 -0
  34. package/dist/intents/domain/intent.state.d.ts +1 -1
  35. package/dist/maintenance/maintenance.graph.d.ts +66 -3
  36. package/dist/maintenance/maintenance.graph.js +155 -156
  37. package/dist/mcp/mcp.authorization-policy.d.ts +24 -28
  38. package/dist/mcp/mcp.authorization-policy.js +14 -34
  39. package/dist/mcp/mcp.server.d.ts +3 -3
  40. package/dist/mcp/mcp.server.js +12 -16
  41. package/dist/negotiations/application/negotiation.candidates.d.ts +83 -0
  42. package/dist/negotiations/application/negotiation.candidates.js +162 -0
  43. package/dist/negotiations/application/negotiation.graph.d.ts +91 -157
  44. package/dist/negotiations/application/negotiation.graph.finalize.d.ts +5 -0
  45. package/dist/negotiations/application/negotiation.graph.finalize.js +280 -0
  46. package/dist/negotiations/application/negotiation.graph.init.d.ts +54 -0
  47. package/dist/negotiations/application/negotiation.graph.init.js +227 -0
  48. package/dist/negotiations/application/negotiation.graph.js +69 -1388
  49. package/dist/negotiations/application/negotiation.graph.screen.d.ts +23 -0
  50. package/dist/negotiations/application/negotiation.graph.screen.js +108 -0
  51. package/dist/negotiations/application/negotiation.graph.shared.d.ts +75 -0
  52. package/dist/negotiations/application/negotiation.graph.shared.js +125 -0
  53. package/dist/negotiations/application/negotiation.graph.turn.d.ts +105 -0
  54. package/dist/negotiations/application/negotiation.graph.turn.js +484 -0
  55. package/dist/negotiations/domain/negotiation.state.d.ts +1 -1
  56. package/dist/negotiations/domain/negotiation.state.js +0 -1
  57. package/dist/networks/application/indexer.graph.d.ts +165 -7
  58. package/dist/networks/application/indexer.graph.js +339 -388
  59. package/dist/networks/application/indexer.state.d.ts +1 -1
  60. package/dist/networks/application/membership.graph.d.ts +83 -5
  61. package/dist/networks/application/membership.graph.js +177 -207
  62. package/dist/networks/application/network.graph.d.ts +148 -5
  63. package/dist/networks/application/network.graph.js +249 -278
  64. package/dist/networks/domain/membership.state.d.ts +1 -1
  65. package/dist/networks/domain/network.state.d.ts +1 -1
  66. package/dist/opportunities/application/delivery-card.cache.d.ts +1 -1
  67. package/dist/opportunities/application/delivery-card.cache.js +2 -2
  68. package/dist/opportunities/application/index.d.ts +2 -2
  69. package/dist/opportunities/application/index.js +2 -2
  70. package/dist/opportunities/application/opportunity.evaluator.js +1 -1
  71. package/dist/opportunities/application/opportunity.graph.d.ts +686 -473
  72. package/dist/opportunities/application/opportunity.graph.discovery-strategies.d.ts +109 -0
  73. package/dist/opportunities/application/opportunity.graph.discovery-strategies.js +451 -0
  74. package/dist/opportunities/application/opportunity.graph.discovery.d.ts +69 -0
  75. package/dist/opportunities/application/opportunity.graph.discovery.js +397 -0
  76. package/dist/opportunities/application/opportunity.graph.evaluation.d.ts +82 -0
  77. package/dist/opportunities/application/opportunity.graph.evaluation.js +608 -0
  78. package/dist/opportunities/application/opportunity.graph.js +120 -3690
  79. package/dist/opportunities/application/opportunity.graph.modes.d.ts +538 -0
  80. package/dist/opportunities/application/opportunity.graph.modes.js +538 -0
  81. package/dist/opportunities/application/opportunity.graph.negotiate.d.ts +109 -0
  82. package/dist/opportunities/application/opportunity.graph.negotiate.js +392 -0
  83. package/dist/opportunities/application/opportunity.graph.persist-node.d.ts +93 -0
  84. package/dist/opportunities/application/opportunity.graph.persist-node.js +765 -0
  85. package/dist/opportunities/application/opportunity.graph.prep.d.ts +150 -0
  86. package/dist/opportunities/application/opportunity.graph.prep.js +381 -0
  87. package/dist/opportunities/application/opportunity.graph.shared.d.ts +173 -0
  88. package/dist/opportunities/application/opportunity.graph.shared.js +199 -0
  89. package/dist/opportunities/application/opportunity.presentation.d.ts +399 -0
  90. package/dist/opportunities/application/{opportunity.presenter.js → opportunity.presentation.js} +735 -9
  91. package/dist/opportunities/application/opportunity.tools.cards.d.ts +152 -0
  92. package/dist/opportunities/application/opportunity.tools.cards.js +235 -0
  93. package/dist/opportunities/application/opportunity.tools.d.ts +8 -114
  94. package/dist/opportunities/application/opportunity.tools.js +28 -711
  95. package/dist/opportunities/application/opportunity.tools.list.d.ts +10 -0
  96. package/dist/opportunities/application/opportunity.tools.list.js +493 -0
  97. package/dist/opportunities/domain/index.d.ts +3 -3
  98. package/dist/opportunities/domain/index.js +3 -3
  99. package/dist/opportunities/domain/opportunity.state.d.ts +19 -19
  100. package/dist/opportunities/index.d.ts +6 -6
  101. package/dist/opportunities/index.js +4 -4
  102. package/dist/opportunities/ports/opportunity.tools.port.d.ts +1 -1
  103. package/dist/opportunities/radar/radar.graph.d.ts +57 -13
  104. package/dist/opportunities/radar/radar.graph.js +470 -471
  105. package/dist/premises/premise.graph.d.ts +88 -20
  106. package/dist/premises/premise.graph.js +207 -218
  107. package/dist/questions/domain/question.schema.d.ts +40 -40
  108. package/dist/shared/agent/tool.helpers.d.ts +21 -0
  109. package/dist/shared/agent/tool.registry.d.ts +4 -3
  110. package/dist/shared/agent/tool.registry.js +1 -1
  111. package/dist/shared/interfaces/database.capabilities.d.ts +100 -0
  112. package/dist/shared/interfaces/database.capabilities.js +7 -0
  113. package/dist/shared/interfaces/database.entities.d.ts +533 -0
  114. package/dist/shared/interfaces/database.entities.js +10 -0
  115. package/dist/shared/interfaces/database.identity-queries.d.ts +294 -0
  116. package/dist/shared/interfaces/database.identity-queries.js +4 -0
  117. package/dist/shared/interfaces/database.interface.d.ts +15 -2277
  118. package/dist/shared/interfaces/database.interface.js +8 -0
  119. package/dist/shared/interfaces/database.member-queries.d.ts +228 -0
  120. package/dist/shared/interfaces/database.member-queries.js +4 -0
  121. package/dist/shared/interfaces/database.negotiation.d.ts +305 -0
  122. package/dist/shared/interfaces/database.negotiation.js +26 -0
  123. package/dist/shared/interfaces/database.network-queries.d.ts +277 -0
  124. package/dist/shared/interfaces/database.network-queries.js +4 -0
  125. package/dist/shared/interfaces/database.opportunity-queries.d.ts +285 -0
  126. package/dist/shared/interfaces/database.opportunity-queries.js +4 -0
  127. package/dist/shared/interfaces/database.port.d.ts +322 -0
  128. package/dist/shared/interfaces/database.port.js +29 -0
  129. package/dist/shared/schemas/discovery-question.schema.d.ts +14 -14
  130. package/dist/shared/schemas/negotiation-digest.schema.d.ts +2 -2
  131. package/package.json +2 -15
  132. package/dist/opportunities/application/opportunity.card-presentation.d.ts +0 -44
  133. package/dist/opportunities/application/opportunity.card-presentation.js +0 -93
  134. package/dist/opportunities/application/opportunity.presenter.d.ts +0 -156
  135. package/dist/opportunities/domain/opportunity.presentation-cache.d.ts +0 -5
  136. package/dist/opportunities/domain/opportunity.presentation-cache.js +0 -11
  137. package/dist/opportunities/domain/opportunity.presentation.d.ts +0 -76
  138. package/dist/opportunities/domain/opportunity.presentation.js +0 -516
  139. package/dist/opportunities/domain/opportunity.safe-presentation.d.ts +0 -104
  140. package/dist/opportunities/domain/opportunity.safe-presentation.js +0 -102
package/CHANGELOG.md CHANGED
@@ -20,6 +20,112 @@ went 6.7.1 → 8.0.2 with no 7.x in between because the whole 7.x line shipped a
20
20
  prereleases between the two promotions. To track every change, read `rc`; to
21
21
  pin a supported release, use `latest`.
22
22
 
23
+ ## 16.1.0 - 2026-08-17
24
+
25
+ ### Removed
26
+
27
+ - Remove the eval harnesses (`eval/`) and the 13 `eval:*` package scripts. No
28
+ public API change: `src/` never imported `eval/`, so the package build,
29
+ architecture gates and source tests are unaffected. The final state is
30
+ preserved in the `archive/eval-2026-08-16` tag; restore with
31
+ `git checkout archive/eval-2026-08-16 -- packages/protocol/eval`.
32
+
33
+ ## 16.0.0 - 2026-08-17
34
+
35
+ ### Removed
36
+
37
+ - **Breaking:** MCP no longer gates on web/CLI onboarding. Incomplete
38
+ onboarding does not restrict the MCP inventory, `onboarding_human` and
39
+ `onboarding_required` are gone, and `complete_onboarding` is omitted from
40
+ the MCP registry. `read_user_contexts` no longer returns
41
+ `onboardingComplete` on MCP. Web onboarding chat and the REST Tool API
42
+ keep the existing completion flow.
43
+
44
+ ## 15.0.0 - 2026-08-17
45
+
46
+ Public-surface prune. `src/index.ts` goes from 443 exported symbols across 164
47
+ export statements to 312 across 143. No implementation changed: every removed
48
+ symbol still exists and still works inside the package — it is simply no longer
49
+ re-exported from the barrel.
50
+
51
+ A symbol was kept whenever a retained export could not be *used* without it —
52
+ parameter and member types of exported functions, interfaces, and unions stay
53
+ public even with no direct importer, because an exported symbol whose members
54
+ cannot be named is not usable.
55
+
56
+ The removal set was derived by parsing every barrel export and resolving it
57
+ against every consumer reference in `services/`, `apps/`, `packages/*`,
58
+ `docs/`, `.claude/`, and the protocol's own `eval/` and `skills/` trees —
59
+ covering static named imports, `import type` queries, `import('...').Sym` type
60
+ positions, `await import()` destructuring, namespace aliases, and `mock.module`
61
+ shapes. A symbol was removed only when nothing outside the package imported it
62
+ from the package root.
63
+
64
+ ### Removed from the public API (BREAKING)
65
+
66
+ 131 symbols. None were deleted; all remain internal. The largest groups:
67
+
68
+ - **Capability tool factories** — `createChatTools`, `createAgentTools`,
69
+ `createIntentTools`, `createNetworkTools`, `createOpportunityTools`,
70
+ `createNegotiationTools`, `createQuestionerTools`,
71
+ `createAskUserQuestionTools`, `createContactTools`, `createIntegrationTools`,
72
+ `createPremiseTools`, and their `*ToolDeps` types. These are composed
73
+ internally by `createMcpServer` / `createToolRegistry`, which remain public.
74
+ `createEnrichmentTools` and `EnrichmentToolDeps` stay exported — the API
75
+ service calls them directly from its enrichment-run worker.
76
+ - **MCP authorization policy** — 27 symbols from `mcp/mcp.authorization-policy.ts`
77
+ (`MCP_AGENT_ADMIN_TOOLS`, `McpCapabilityPolicy`, `McpToolAccessRuleSchema`,
78
+ `defineMcpToolAccessRules`, the `Mcp*` policy types, …). Four stay public
79
+ because a host cannot type its own `createMcpServer` call without them:
80
+ `CANONICAL_MCP_CAPABILITY_POLICY_OPTIONS`, `McpCapabilityPolicyOptions` (the
81
+ fourth parameter), `McpAuthorizationObserver`, and
82
+ `McpAuthorizationDenialEvent` (the observer callback's only argument).
83
+ - **Activity projection** — 15 symbols from `shared/agent/activity-projection.ts`
84
+ (`projectActivitySummary`, `ActivitySummaryResponseSchema`,
85
+ `QUESTION_MODE_TO_DOMAIN`, `READ_ACTIVITY_SUMMARY_TOOL_NAME`, …).
86
+ - **Persona helpers** — the `filter*Tools` / `narrow*Tools` helpers, the
87
+ `*_TOOL_NAMES` constants, and the `SIGNAL_NEW_SIGNAL_KICKOFF` /
88
+ `ONBOARDING_PROFILE_KICKOFF` constants. The persona IDs, the prompt
89
+ constants, and `REPORTER_BRIEFING_KICKOFF` stay — `apps/web` imports the
90
+ latter.
91
+ - **Discovery env accessors** — `discoveryAllowedTypes`, `discoveryMinSimilarity`,
92
+ `discoveryProfileSource`, `discoveryIntentMatchingEnabled`,
93
+ `discoveryProfileMatchingEnabled`, the `validate*` helpers, and the
94
+ `DISCOVERY_*_DEFAULT` constants. `discoveryEvaluatorMinScore` stays: its one
95
+ importer is `services/api/src/cli/discovery-env-matrix.main.ts`. That CLI is
96
+ slated for removal with the eval harnesses, and this accessor should be
97
+ pruned in the same change. These back live Railway configuration and are
98
+ unchanged in behaviour; only the re-export is gone.
99
+ - **Signal-intake types** — `IntakePack`, `IntakePackInput`, `SynthesisInput`,
100
+ `SynthesisResult`, `FollowUpPlan`, `answerLabel`, `normalizeIntakePack`, …
101
+
102
+ Two of the removed symbols (`createAgentTools` and
103
+ `CANONICAL_MCP_TOOL_ACCESS_RULES`) are referenced by `services/api` tests
104
+ through deep source paths rather than the package root, so those tests are
105
+ unaffected by the barrel change.
106
+
107
+ ### Changed
108
+
109
+ - `IMPLEMENTATION.md` §1 no longer documents a `modelConfig` override on
110
+ `ToolDeps` — that field does not exist there. `modelConfig` lives on the
111
+ internal `ToolContext` / `ProtocolDeps` composition, which is not exported, so
112
+ the section now documents the environment variables as the supported
113
+ configuration path and states plainly that programmatic override is outside
114
+ the public contract.
115
+ - `IMPLEMENTATION.md` §3 now documents `createMcpServer` and
116
+ `createToolRegistry` + `invokeToolRuntime` as the supported tool entry points,
117
+ replacing the `createChatTools` walkthrough.
118
+ - `STABILITY.md` — the **Capability tools** tier now covers
119
+ `createEnrichmentTools` only; the **Public API** row names `createToolRegistry`
120
+ and corrects `ToolContext` to the actually-exported `ResolvedToolContext`.
121
+
122
+ ### Migration
123
+
124
+ Hosts composing tools by capability should call `createMcpServer` (full MCP
125
+ server, policy applied) or `createToolRegistry` (raw handler map, invoked via
126
+ `invokeToolRuntime`). Both take the same dependency object the individual
127
+ factories did.
128
+
23
129
  ## 14.3.2 - 2026-08-16
24
130
 
25
131
  No source change. The public contract in `src/index.ts` is untouched; only
@@ -419,6 +525,7 @@ No public API change: all 441 exported symbols are byte-identical to 13.2.0, and
419
525
  ## [Unreleased]
420
526
 
421
527
  ### Changed
528
+ - Behaviour-neutral internal refactor (16.1.1): split the six largest modules and hoist every graph node to a top-level function. The opportunity graph is now the discovery pipeline only — its eight non-pipeline modes (read, update, delete, send, negotiate_existing, approve_introduction, and the two introduction stages) are plain functions on `OpportunityGraphFactory` instead of `operationMode` conditional-edge routing. `database.interface.ts` becomes a barrel over entity, query-group, and capability-view modules; every `Pick<Database, ...>` resolves as before. The opportunity presentation cluster is one module. `opportunity.graph.ts` 4167 → 250 lines, `database.interface.ts` 2925 → 17, `negotiation.graph.ts` 1619 → 111, `opportunity.tools.ts` 1200 → 354, `enrichment.tools.ts` 1198 → 178, `intent.graph.ts` 1091 → 174. No public export, feature flag, or environment variable changed.
422
529
  - Move the opportunity-presentation review checklist into `src/opportunity/AGENTS.md` and repoint the `opportunity.safe-presentation.ts` and `discriminator.adjustments.ts` comments at it. Comment-only; no runtime change.
423
530
 
424
531
  ### Removed
package/IMPLEMENTATION.md CHANGED
@@ -10,7 +10,7 @@ supported entry point is the package root (`import { ... } from "@indexnetwork/p
10
10
  deep imports are not part of the contract. Every symbol is re-exported explicitly from
11
11
  `src/index.ts` and tagged with a stability tier:
12
12
 
13
- - **Stable** — interfaces, graph factories, agents, `createChatTools`, the
13
+ - **Stable** — interfaces, graph factories, agents, `createMcpServer`, the
14
14
  tool/runtime helpers, and shared schemas. Breaking changes require a major bump.
15
15
  - **Experimental** (`@experimental`) — advanced graph-state types and internal
16
16
  helpers; may change in a minor release.
@@ -35,27 +35,15 @@ npm install @indexnetwork/protocol
35
35
 
36
36
  The package reads `OPENROUTER_API_KEY` (required), `CHAT_MODEL`, and `CHAT_REASONING_EFFORT` from environment variables. No startup call is needed.
37
37
 
38
- To override the chat model or reasoning effort when using the built-in chat runtime (`ChatGraphFactory` / `ChatAgent`), pass `modelConfig` on `ToolContext`. `ChatAgent` reads these fields when the chat graph runs; the tools themselves do not consume `modelConfig`:
38
+ Environment variables are the supported way to configure models. `CHAT_MODEL` and `CHAT_REASONING_EFFORT` (`minimal | low | medium | high | xhigh`) drive the built-in chat runtime (`ChatGraphFactory` / `ChatAgent`); every other protocol agent evaluators, generators, miners reads `OPENROUTER_API_KEY` from the environment.
39
39
 
40
- ```typescript
41
- import { createChatTools } from "@indexnetwork/protocol";
42
-
43
- const tools = await createChatTools({
44
- // ... other deps ...
45
- modelConfig: {
46
- chatModel: "google/gemini-2.5-flash", // optional — has a default
47
- chatReasoningEffort: "low", // optional: minimal | low | medium | high | xhigh
48
- },
49
- });
50
- ```
51
-
52
- `apiKey` and `baseURL` can also be overridden this way. All other protocol agents (evaluators, generators, etc.) rely on `OPENROUTER_API_KEY` set in the environment regardless of `modelConfig`.
40
+ There is a per-instance `modelConfig` (chat model, reasoning effort, `apiKey`, `baseURL`) that `ChatAgent` reads off the resolved tool context, but it lives on the internal composition types (`ToolContext` / `ProtocolDeps`), not on `ToolDeps`, and those types are not exported. **Programmatic model override is therefore not part of the public contract in 15.0.0** — use the environment variables. If you need a typed override path, open an issue rather than reaching through a deep import.
53
41
 
54
42
  ### 2. Implement the adapters
55
43
 
56
44
  The package defines interfaces — your application provides the concrete implementations.
57
45
 
58
- **Required** (always needed by `createChatTools`):
46
+ **Required** (always needed by the tool registry):
59
47
 
60
48
  | Interface | Responsibility |
61
49
  |---|---|
@@ -90,50 +78,60 @@ All interfaces are exported from the package root — import them with `import t
90
78
 
91
79
  ### 3. Create tools
92
80
 
93
- Pass your adapter implementations to `createChatTools` to get a set of LangChain-compatible tools bound to a user session:
81
+ Two entry points are supported, both taking a single dependency object built
82
+ from the adapters above.
83
+
84
+ `createMcpServer` is the complete integration: it composes every capability's
85
+ tools internally, applies the authorization policy, and returns a ready MCP
86
+ server.
94
87
 
95
88
  ```typescript
96
- import { createChatTools } from "@indexnetwork/protocol";
89
+ import { createMcpServer, CANONICAL_MCP_CAPABILITY_POLICY_OPTIONS } from "@indexnetwork/protocol";
97
90
 
98
- const tools = await createChatTools({
99
- userId: "user-uuid",
91
+ const server = createMcpServer(
92
+ deps, // ToolDeps + the opportunity owner-approval port
93
+ authResolver, // McpAuthResolver
94
+ scopedDepsFactory, // ScopedDepsFactory — builds per-user scoped userDb/systemDb
95
+ CANONICAL_MCP_CAPABILITY_POLICY_OPTIONS,
96
+ authorizationObserver, // optional McpAuthorizationObserver
97
+ );
98
+ ```
99
+
100
+ `createToolRegistry` is the lower-level surface for hosts running their own
101
+ runtime. It returns a `Map` of tool name to `RawToolDefinition` — raw async
102
+ handlers taking `{ context, query }` — which you invoke through
103
+ `invokeToolRuntime`:
104
+
105
+ ```typescript
106
+ import { createToolRegistry, invokeToolRuntime, resolveChatContext } from "@indexnetwork/protocol";
100
107
 
101
- // ── Required adapters ──
102
- database, // ChatGraphCompositeDatabase
103
- embedder, // Embedder
104
- scraper, // Scraper
105
- cache, // Cache
106
- hydeCache, // HydeCache
107
- integration, // IntegrationAdapter
108
- intentQueue, // IntentGraphQueue
109
- contactService, // ContactServiceAdapter
110
- chatSession, // ChatSessionReader
111
- enricher, // ProfileEnricher
112
- negotiationDatabase, // NegotiationGraphDatabase
113
- integrationImporter, // bulk contact import
114
- createUserDatabase, // (db, userId) => UserDatabase
115
- createSystemDatabase, // (db, userId, indexScope, embedder?) => SystemDatabase
116
-
117
- // ── Optional scoping ──
118
- networkId: "optional-network-uuid", // scope tools to a specific index/network
119
- sessionId: "chat-session-id", // enables draft opportunities with conversation context
120
-
121
- // ── Optional capabilities (enable when the host supports them) ──
122
- agentDatabase, // AgentDatabase — agent registry
123
- agentDispatcher, // AgentDispatcher — routes negotiation turns to personal agents
124
- deliveryLedger, // DeliveryLedger — OpenClaw delivery commits
125
- enrichmentRuns, // EnrichmentRunStore (+ enrichmentRunQueue) — async MCP enrichment runs
126
- mintConnectLink, // short connect links for opportunity accepts
127
- modelConfig, // override chat model / reasoning effort (see above)
108
+ const registry = createToolRegistry(deps, { surface: "mcp" }); // omit `surface` for the full REST set
109
+
110
+ const context = await resolveChatContext({
111
+ database, // the ChatGraphCompositeDatabase reads listed above
112
+ userId: "user-uuid",
113
+ networkId, // optional — scopes tools to one network
114
+ sessionId, // optional — enables draft opportunities
128
115
  });
129
116
 
130
- // tools is an array of LangChain Tool objects ready to bind to an agent
117
+ const tool = registry.get("search_intents")!;
118
+ const result = await invokeToolRuntime({
119
+ toolName: tool.name,
120
+ tool,
121
+ context,
122
+ query: { /* validated against tool.schema */ },
123
+ });
131
124
  ```
132
125
 
133
- `createChatTools` accepts a single `ToolContext` object. The required adapters
134
- above are always needed; optional capabilities default to a degraded-but-
135
- functional mode when omitted (for example, without `agentDispatcher` the
136
- negotiation tools are not registered).
126
+ The dependency object carries the required adapters listed above; optional
127
+ capabilities default to a degraded-but-functional mode when omitted (for
128
+ example, without `agentDispatcher` the negotiation tools are not registered).
129
+
130
+ The per-capability tool factories behind these entry points
131
+ (`createChatTools`, `createIntentTools`, `createNegotiationTools`, …) are
132
+ package-internal as of 15.0.0 and are not part of the supported surface.
133
+ `createEnrichmentTools` remains exported for hosts that run enrichment on its
134
+ own worker, separately from the chat runtime.
137
135
 
138
136
  ## Graphs
139
137
 
package/STABILITY.md CHANGED
@@ -30,13 +30,13 @@ Covered by SemVer below. Breaking changes require a **major** bump.
30
30
 
31
31
  | Barrel section | What it is |
32
32
  |---|---|
33
- | **Public API** | `createChatTools`, model config helpers, tool/runtime helpers (`ToolContext`, `ToolDeps`, `invokeToolRuntime`, …), `requestContext`. |
33
+ | **Public API** | `createToolRegistry`, model config helpers, tool/runtime helpers (`ResolvedToolContext`, `ToolDeps`, `invokeToolRuntime`, …), `requestContext`. |
34
34
  | **Interfaces** | Every `*.interface.ts` port you implement to inject infrastructure (databases, embedder, cache, scraper, queues, integration, agent dispatcher, …). |
35
35
  | **Shared schemas** | Zod schemas + inferred types that cross the boundary (questions, identity, network-assignment, chat-context, …). |
36
36
  | **Graph factories** | `*GraphFactory` classes (`ChatGraphFactory`, `OpportunityGraphFactory`, `NegotiationGraphFactory`, …). |
37
37
  | **Agents** | Structured LLM agents (`UserContextGenerator`, `IndexNegotiator`, `OpportunityEvaluator`, …). |
38
- | **MCP** | `createMcpServer` and its supporting types. |
39
- | **Capability tools** | Named tool-factory entry points for Signals, Participant context, Communities, Opportunities, Negotiation, Questions, Participant agents, Contacts, and Integrations. |
38
+ | **MCP** | `createMcpServer` plus the types needed to call it: `ScopedDepsFactory`, `McpCapabilityPolicyOptions`, `CANONICAL_MCP_CAPABILITY_POLICY_OPTIONS`, `McpAuthorizationObserver`, `McpAuthorizationDenialEvent`. The rest of `mcp.authorization-policy.ts` is package-internal as of 15.0.0. |
39
+ | **Capability tools** | `createEnrichmentTools` only. The other per-capability tool factories became package-internal in 15.0.0 compose them through `createMcpServer` or `createToolRegistry`. |
40
40
 
41
41
  ### Experimental
42
42
 
@@ -327,8 +327,8 @@ export class ChatAgent {
327
327
  }
328
328
  try {
329
329
  logger.verbose("Executing tool", { name: tc.name, args: tc.args });
330
- let result = await tool.invoke(tc.args);
331
- let resultStr = typeof result === "string" ? result : JSON.stringify(result);
330
+ const result = await tool.invoke(tc.args);
331
+ const resultStr = typeof result === "string" ? result : JSON.stringify(result);
332
332
  logger.debug("Tool response", { name: tc.name, result: resultStr });
333
333
  logger.verbose("Tool completed", {
334
334
  name: tc.name,
@@ -1,5 +1,6 @@
1
- import { BaseCheckpointSaver } from "@langchain/langgraph";
1
+ import { BaseCheckpointSaver, type LangGraphRunnableConfig } from "@langchain/langgraph";
2
2
  import { BaseMessage } from "@langchain/core/messages";
3
+ import { ChatGraphState } from "./chat.state.js";
3
4
  import type { ChatPersonaConfig } from "./chat.persona.js";
4
5
  import type { ChatGraphCompositeDatabase } from "../shared/interfaces/database.interface.js";
5
6
  import type { Embedder } from "../shared/interfaces/embedder.interface.js";
@@ -21,6 +22,16 @@ import type { ProtocolDeps } from "../shared/agent/tool.helpers.js";
21
22
  * with a flexible, LLM-driven approach that can handle multi-step
22
23
  * reasoning and self-correction.
23
24
  */
25
+ /** The graph's channel state, as the agent loop sees it. */
26
+ export type ChatState = typeof ChatGraphState.State;
27
+ /** Everything the agent loop node reaches for. */
28
+ export interface ChatGraphNodeDeps {
29
+ database: ChatGraphCompositeDatabase;
30
+ embedder: Embedder;
31
+ scraper: Scraper;
32
+ protocolDeps: ProtocolDeps;
33
+ persona: ChatPersonaConfig;
34
+ }
24
35
  export declare class ChatGraphFactory {
25
36
  private database;
26
37
  private embedder;
@@ -382,3 +393,32 @@ export declare class ChatGraphFactory {
382
393
  */
383
394
  private buildGraph;
384
395
  }
396
+ /**
397
+ * The main agent loop node.
398
+ * Runs a ReAct-style agent that calls tools until it decides to respond.
399
+ *
400
+ * Uses `agent.streamRun()` + `config.writer` so that text tokens and
401
+ * tool-activity events are pushed into the graph's custom stream in
402
+ * real-time rather than batched at the end.
403
+ */
404
+ export declare function agentLoopNode(state: ChatState, config: LangGraphRunnableConfig, deps: ChatGraphNodeDeps): Promise<{
405
+ messages: BaseMessage<import("@langchain/core/messages").MessageStructure<import("@langchain/core/messages").MessageToolSet>, import("@langchain/core/messages").MessageType>[];
406
+ responseText: string;
407
+ iterationCount: number;
408
+ shouldContinue: boolean;
409
+ debugMeta: {
410
+ graph: string;
411
+ iterations: number;
412
+ tools: import("./chat-streaming.types.js").DebugMetaToolCall[];
413
+ llm: import("./chat-streaming.types.js").DebugMetaLlm;
414
+ orchestratorNegotiations?: import("./chat-streaming.types.js").DebugMetaOrchestratorNegotiations;
415
+ };
416
+ error?: undefined;
417
+ } | {
418
+ error: string;
419
+ responseText: string;
420
+ shouldContinue: boolean;
421
+ messages?: undefined;
422
+ iterationCount?: undefined;
423
+ debugMeta?: undefined;
424
+ }>;
@@ -19,24 +19,6 @@ function isRetriableError(err) {
19
19
  lower.includes("etimedout"));
20
20
  }
21
21
  const RETRY_DELAY_MS = 800;
22
- // ══════════════════════════════════════════════════════════════════════════════
23
- // CHAT GRAPH FACTORY (Agent Loop Architecture)
24
- // ══════════════════════════════════════════════════════════════════════════════
25
- /**
26
- * Factory class to build and compile the Chat Graph.
27
- *
28
- * Architecture: ReAct-Style Agent Loop
29
- *
30
- * The graph contains a single node that runs an agent loop:
31
- * 1. Agent receives messages (conversation + tool results)
32
- * 2. Agent decides: call tools OR respond to user
33
- * 3. If tools called → execute → add results → loop back
34
- * 4. If response → exit loop → stream to user
35
- *
36
- * This replaces the previous 17-node conditional routing architecture
37
- * with a flexible, LLM-driven approach that can handle multi-step
38
- * reasoning and self-correction.
39
- */
40
22
  export class ChatGraphFactory {
41
23
  constructor(database, embedder, scraper, chatSession, protocolDeps,
42
24
  /** Persona driving this graph's agent loop. Required — there is no default. */
@@ -139,68 +121,107 @@ export class ChatGraphFactory {
139
121
  * @returns Uncompiled StateGraph
140
122
  */
141
123
  buildGraph() {
142
- const database = this.database;
143
- const embedder = this.embedder;
144
- const scraper = this.scraper;
145
- const protocolDeps = this.protocolDeps;
146
- const persona = this.persona;
124
+ const deps = {
125
+ database: this.database,
126
+ embedder: this.embedder,
127
+ scraper: this.scraper,
128
+ protocolDeps: this.protocolDeps,
129
+ persona: this.persona,
130
+ };
147
131
  // ─────────────────────────────────────────────────────────────────────────
148
- // AGENT LOOP NODE
132
+ // GRAPH ASSEMBLY
149
133
  // ─────────────────────────────────────────────────────────────────────────
150
- /**
151
- * The main agent loop node.
152
- * Runs a ReAct-style agent that calls tools until it decides to respond.
153
- *
154
- * Uses `agent.streamRun()` + `config.writer` so that text tokens and
155
- * tool-activity events are pushed into the graph's custom stream in
156
- * real-time rather than batched at the end.
157
- */
158
- const agentLoopNode = async (state, config) => {
159
- return timed("ChatGraph.agentLoop", async () => {
160
- logger.verbose("Agent loop starting", {
134
+ const workflow = new StateGraph(ChatGraphState)
135
+ .addNode("agent_loop", (state, config) => agentLoopNode(state, config, deps))
136
+ .addEdge(START, "agent_loop")
137
+ .addEdge("agent_loop", END);
138
+ logger.verbose("Graph built successfully (agent loop architecture)");
139
+ return workflow;
140
+ }
141
+ }
142
+ /**
143
+ * The main agent loop node.
144
+ * Runs a ReAct-style agent that calls tools until it decides to respond.
145
+ *
146
+ * Uses `agent.streamRun()` + `config.writer` so that text tokens and
147
+ * tool-activity events are pushed into the graph's custom stream in
148
+ * real-time rather than batched at the end.
149
+ */
150
+ export async function agentLoopNode(state, config, deps) {
151
+ return timed("ChatGraph.agentLoop", async () => {
152
+ logger.verbose("Agent loop starting", {
153
+ userId: state.userId,
154
+ messageCount: state.messages.length,
155
+ currentIteration: state.iterationCount
156
+ });
157
+ const runLoop = async () => {
158
+ const legacyNetworkId = state.networkId;
159
+ const scopeType = state.scopeType ?? (legacyNetworkId ? 'network' : undefined);
160
+ const scopeId = state.scopeId ?? legacyNetworkId;
161
+ const agent = await ChatAgent.create({
162
+ ...deps.protocolDeps,
163
+ userId: state.userId,
164
+ database: deps.database,
165
+ embedder: deps.embedder,
166
+ scraper: deps.scraper,
167
+ ...(legacyNetworkId ? { networkId: legacyNetworkId } : {}),
168
+ ...(scopeType && scopeId ? { scopeType, scopeId } : {}),
169
+ sessionId: state.sessionId,
170
+ }, deps.persona);
171
+ // Direct streaming writer - emit events immediately instead of buffering
172
+ const directWriter = (data) => {
173
+ try {
174
+ config.writer?.(data);
175
+ }
176
+ catch {
177
+ /* swallow if writer is gone */
178
+ }
179
+ };
180
+ // Get signal from configurable (passed by streamer via graph.stream() config)
181
+ const signal = config.configurable?.signal;
182
+ const result = await agent.streamRun(state.messages, directWriter, signal);
183
+ return result;
184
+ };
185
+ try {
186
+ const result = await runLoop();
187
+ logger.debug("Agent streamRun result", {
188
+ responseText: result.responseText,
189
+ iterationCount: result.iterationCount,
190
+ messageCount: result.messages.length,
191
+ });
192
+ logger.verbose("Agent loop complete", {
193
+ userId: state.userId,
194
+ iterations: result.iterationCount,
195
+ responseLength: result.responseText.length
196
+ });
197
+ return {
198
+ messages: result.messages,
199
+ responseText: result.responseText,
200
+ iterationCount: result.iterationCount,
201
+ shouldContinue: false,
202
+ debugMeta: result.debugMeta,
203
+ };
204
+ }
205
+ catch (error) {
206
+ if (isRetriableError(error)) {
207
+ const signal = config.configurable?.signal;
208
+ if (signal?.aborted) {
209
+ return {
210
+ error: "Request aborted",
211
+ responseText: "",
212
+ shouldContinue: false,
213
+ };
214
+ }
215
+ logger.warn("Agent loop failed with retriable error, retrying once", {
161
216
  userId: state.userId,
162
- messageCount: state.messages.length,
163
- currentIteration: state.iterationCount
217
+ error: error instanceof Error ? error.message : String(error)
164
218
  });
165
- const runLoop = async () => {
166
- const legacyNetworkId = state.networkId;
167
- const scopeType = state.scopeType ?? (legacyNetworkId ? 'network' : undefined);
168
- const scopeId = state.scopeId ?? legacyNetworkId;
169
- const agent = await ChatAgent.create({
170
- ...protocolDeps,
171
- userId: state.userId,
172
- database,
173
- embedder,
174
- scraper,
175
- ...(legacyNetworkId ? { networkId: legacyNetworkId } : {}),
176
- ...(scopeType && scopeId ? { scopeType, scopeId } : {}),
177
- sessionId: state.sessionId,
178
- }, persona);
179
- // Direct streaming writer - emit events immediately instead of buffering
180
- const directWriter = (data) => {
181
- try {
182
- config.writer?.(data);
183
- }
184
- catch {
185
- /* swallow if writer is gone */
186
- }
187
- };
188
- // Get signal from configurable (passed by streamer via graph.stream() config)
189
- const signal = config.configurable?.signal;
190
- const result = await agent.streamRun(state.messages, directWriter, signal);
191
- return result;
192
- };
219
+ await new Promise((r) => setTimeout(r, RETRY_DELAY_MS));
193
220
  try {
194
221
  const result = await runLoop();
195
- logger.debug("Agent streamRun result", {
196
- responseText: result.responseText,
197
- iterationCount: result.iterationCount,
198
- messageCount: result.messages.length,
199
- });
200
- logger.verbose("Agent loop complete", {
222
+ logger.verbose("Agent loop complete after retry", {
201
223
  userId: state.userId,
202
224
  iterations: result.iterationCount,
203
- responseLength: result.responseText.length
204
225
  });
205
226
  return {
206
227
  messages: result.messages,
@@ -210,67 +231,27 @@ export class ChatGraphFactory {
210
231
  debugMeta: result.debugMeta,
211
232
  };
212
233
  }
213
- catch (error) {
214
- if (isRetriableError(error)) {
215
- const signal = config.configurable?.signal;
216
- if (signal?.aborted) {
217
- return {
218
- error: "Request aborted",
219
- responseText: "",
220
- shouldContinue: false,
221
- };
222
- }
223
- logger.warn("Agent loop failed with retriable error, retrying once", {
224
- userId: state.userId,
225
- error: error instanceof Error ? error.message : String(error)
226
- });
227
- await new Promise((r) => setTimeout(r, RETRY_DELAY_MS));
228
- try {
229
- const result = await runLoop();
230
- logger.verbose("Agent loop complete after retry", {
231
- userId: state.userId,
232
- iterations: result.iterationCount,
233
- });
234
- return {
235
- messages: result.messages,
236
- responseText: result.responseText,
237
- iterationCount: result.iterationCount,
238
- shouldContinue: false,
239
- debugMeta: result.debugMeta,
240
- };
241
- }
242
- catch (retryError) {
243
- logger.error("Agent loop failed on retry", {
244
- userId: state.userId,
245
- error: retryError instanceof Error ? retryError.message : String(retryError)
246
- });
247
- return {
248
- error: retryError instanceof Error ? retryError.message : "Agent loop failed",
249
- responseText: "I apologize, but I encountered an issue processing your request. Please try again.",
250
- shouldContinue: false
251
- };
252
- }
253
- }
254
- logger.error("Agent loop failed", {
234
+ catch (retryError) {
235
+ logger.error("Agent loop failed on retry", {
255
236
  userId: state.userId,
256
- error: error instanceof Error ? error.message : String(error)
237
+ error: retryError instanceof Error ? retryError.message : String(retryError)
257
238
  });
258
239
  return {
259
- error: error instanceof Error ? error.message : "Agent loop failed",
240
+ error: retryError instanceof Error ? retryError.message : "Agent loop failed",
260
241
  responseText: "I apologize, but I encountered an issue processing your request. Please try again.",
261
242
  shouldContinue: false
262
243
  };
263
244
  }
245
+ }
246
+ logger.error("Agent loop failed", {
247
+ userId: state.userId,
248
+ error: error instanceof Error ? error.message : String(error)
264
249
  });
265
- };
266
- // ─────────────────────────────────────────────────────────────────────────
267
- // GRAPH ASSEMBLY
268
- // ─────────────────────────────────────────────────────────────────────────
269
- const workflow = new StateGraph(ChatGraphState)
270
- .addNode("agent_loop", agentLoopNode)
271
- .addEdge(START, "agent_loop")
272
- .addEdge("agent_loop", END);
273
- logger.verbose("Graph built successfully (agent loop architecture)");
274
- return workflow;
275
- }
250
+ return {
251
+ error: error instanceof Error ? error.message : "Agent loop failed",
252
+ responseText: "I apologize, but I encountered an issue processing your request. Please try again.",
253
+ shouldContinue: false
254
+ };
255
+ }
256
+ });
276
257
  }
@@ -78,11 +78,11 @@ export declare const HydeSourceFrameSchema: z.ZodObject<{
78
78
  evidence: z.ZodString;
79
79
  }, "strip", z.ZodTypeAny, {
80
80
  name: string;
81
- type: "location" | "organization" | "other" | "person" | "product" | "event";
81
+ type: "location" | "event" | "organization" | "other" | "person" | "product";
82
82
  evidence: string;
83
83
  }, {
84
84
  name: string;
85
- type: "location" | "organization" | "other" | "person" | "product" | "event";
85
+ type: "location" | "event" | "organization" | "other" | "person" | "product";
86
86
  evidence: string;
87
87
  }>, "many">;
88
88
  domainVocabulary: z.ZodArray<z.ZodObject<{
@@ -111,7 +111,7 @@ export declare const HydeSourceFrameSchema: z.ZodObject<{
111
111
  }[];
112
112
  namedEntities: {
113
113
  name: string;
114
- type: "location" | "organization" | "other" | "person" | "product" | "event";
114
+ type: "location" | "event" | "organization" | "other" | "person" | "product";
115
115
  evidence: string;
116
116
  }[];
117
117
  domainVocabulary: {
@@ -134,7 +134,7 @@ export declare const HydeSourceFrameSchema: z.ZodObject<{
134
134
  }[];
135
135
  namedEntities: {
136
136
  name: string;
137
- type: "location" | "organization" | "other" | "person" | "product" | "event";
137
+ type: "location" | "event" | "organization" | "other" | "person" | "product";
138
138
  evidence: string;
139
139
  }[];
140
140
  domainVocabulary: {