@namzu/sdk 46.0.0 → 48.1.0
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 +351 -8
- package/README.md +7 -8
- package/dist/advisory/history.d.ts.map +1 -1
- package/dist/advisory/history.js +21 -1
- package/dist/advisory/history.js.map +1 -1
- package/dist/advisory/index.d.ts +1 -1
- package/dist/advisory/index.d.ts.map +1 -1
- package/dist/advisory/index.js +1 -1
- package/dist/advisory/index.js.map +1 -1
- package/dist/advisory/registry.d.ts +17 -0
- package/dist/advisory/registry.d.ts.map +1 -1
- package/dist/advisory/registry.js +26 -0
- package/dist/advisory/registry.js.map +1 -1
- package/dist/agents/PipelineAgent.d.ts +2 -46
- package/dist/agents/PipelineAgent.d.ts.map +1 -1
- package/dist/agents/PipelineAgent.js +2 -242
- package/dist/agents/PipelineAgent.js.map +1 -1
- package/dist/agents/QueryAgent.d.ts +21 -0
- package/dist/agents/QueryAgent.d.ts.map +1 -0
- package/dist/agents/QueryAgent.js +214 -0
- package/dist/agents/QueryAgent.js.map +1 -0
- package/dist/agents/ReactiveAgent.d.ts +4 -16
- package/dist/agents/ReactiveAgent.d.ts.map +1 -1
- package/dist/agents/ReactiveAgent.js +4 -183
- package/dist/agents/ReactiveAgent.js.map +1 -1
- package/dist/agents/RouterAgent.d.ts +2 -20
- package/dist/agents/RouterAgent.d.ts.map +1 -1
- package/dist/agents/RouterAgent.js +2 -266
- package/dist/agents/RouterAgent.js.map +1 -1
- package/dist/agents/SupervisorAgent.d.ts +3 -43
- package/dist/agents/SupervisorAgent.d.ts.map +1 -1
- package/dist/agents/SupervisorAgent.js +3 -418
- package/dist/agents/SupervisorAgent.js.map +1 -1
- package/dist/agents/defineAgent.d.ts +2 -1
- package/dist/agents/defineAgent.d.ts.map +1 -1
- package/dist/agents/defineAgent.js +6 -1
- package/dist/agents/defineAgent.js.map +1 -1
- package/dist/agents/examples/PipelineAgent.d.ts +46 -0
- package/dist/agents/examples/PipelineAgent.d.ts.map +1 -0
- package/dist/agents/examples/PipelineAgent.js +242 -0
- package/dist/agents/examples/PipelineAgent.js.map +1 -0
- package/dist/agents/examples/RouterAgent.d.ts +22 -0
- package/dist/agents/examples/RouterAgent.d.ts.map +1 -0
- package/dist/agents/examples/RouterAgent.js +268 -0
- package/dist/agents/examples/RouterAgent.js.map +1 -0
- package/dist/agents/examples/SupervisorAgent.d.ts +45 -0
- package/dist/agents/examples/SupervisorAgent.d.ts.map +1 -0
- package/dist/agents/examples/SupervisorAgent.js +406 -0
- package/dist/agents/examples/SupervisorAgent.js.map +1 -0
- package/dist/agents/explore.d.ts +6 -3
- package/dist/agents/explore.d.ts.map +1 -1
- package/dist/agents/explore.js +6 -3
- package/dist/agents/explore.js.map +1 -1
- package/dist/agents/forward-options.d.ts +11 -0
- package/dist/agents/forward-options.d.ts.map +1 -0
- package/dist/agents/forward-options.js +15 -0
- package/dist/agents/forward-options.js.map +1 -0
- package/dist/agents/index.d.ts +1 -0
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +2 -0
- package/dist/agents/index.js.map +1 -1
- package/dist/agents/runAgent.d.ts +19 -8
- package/dist/agents/runAgent.d.ts.map +1 -1
- package/dist/agents/runAgent.js +99 -29
- package/dist/agents/runAgent.js.map +1 -1
- package/dist/authorization/command-line.d.ts +2 -0
- package/dist/authorization/command-line.d.ts.map +1 -1
- package/dist/authorization/command-line.js +2 -2
- package/dist/authorization/command-line.js.map +1 -1
- package/dist/authorization/gate.d.ts +8 -0
- package/dist/authorization/gate.d.ts.map +1 -1
- package/dist/authorization/gate.js +12 -1
- package/dist/authorization/gate.js.map +1 -1
- package/dist/authorization/program.d.ts +151 -0
- package/dist/authorization/program.d.ts.map +1 -0
- package/dist/authorization/program.js +713 -0
- package/dist/authorization/program.js.map +1 -0
- package/dist/authorization/reexec-wrapper.d.ts +106 -0
- package/dist/authorization/reexec-wrapper.d.ts.map +1 -0
- package/dist/authorization/reexec-wrapper.js +532 -0
- package/dist/authorization/reexec-wrapper.js.map +1 -0
- package/dist/authorization/rules.d.ts +9 -0
- package/dist/authorization/rules.d.ts.map +1 -1
- package/dist/authorization/rules.js +8 -1
- package/dist/authorization/rules.js.map +1 -1
- package/dist/authorization/shell-lexer.d.ts +19 -4
- package/dist/authorization/shell-lexer.d.ts.map +1 -1
- package/dist/authorization/shell-lexer.js +91 -65
- package/dist/authorization/shell-lexer.js.map +1 -1
- package/dist/bridge/sse/mapper.d.ts.map +1 -1
- package/dist/bridge/sse/mapper.js +6 -0
- package/dist/bridge/sse/mapper.js.map +1 -1
- package/dist/capabilities/index.d.ts +54 -0
- package/dist/capabilities/index.d.ts.map +1 -0
- package/dist/capabilities/index.js +92 -0
- package/dist/capabilities/index.js.map +1 -0
- package/dist/config/registry.d.ts +2 -1
- package/dist/config/registry.d.ts.map +1 -1
- package/dist/config/registry.js +3 -2
- package/dist/config/registry.js.map +1 -1
- package/dist/connector/index.d.ts +4 -4
- package/dist/connector/index.d.ts.map +1 -1
- package/dist/connector/index.js +3 -3
- package/dist/connector/index.js.map +1 -1
- package/dist/connector/mcp/adapter.d.ts +16 -1
- package/dist/connector/mcp/adapter.d.ts.map +1 -1
- package/dist/connector/mcp/adapter.js +71 -4
- package/dist/connector/mcp/adapter.js.map +1 -1
- package/dist/connector/mcp/client.d.ts +32 -4
- package/dist/connector/mcp/client.d.ts.map +1 -1
- package/dist/connector/mcp/client.js +383 -5
- package/dist/connector/mcp/client.js.map +1 -1
- package/dist/connector/mcp/discovery.d.ts +24 -1
- package/dist/connector/mcp/discovery.d.ts.map +1 -1
- package/dist/connector/mcp/discovery.js +44 -0
- package/dist/connector/mcp/discovery.js.map +1 -1
- package/dist/connector/mcp/era.d.ts.map +1 -1
- package/dist/connector/mcp/era.js +7 -0
- package/dist/connector/mcp/era.js.map +1 -1
- package/dist/connector/mcp/index.d.ts +2 -0
- package/dist/connector/mcp/index.d.ts.map +1 -1
- package/dist/connector/mcp/index.js +11 -0
- package/dist/connector/mcp/index.js.map +1 -1
- package/dist/connector/mcp/mcp-toolset.d.ts +133 -0
- package/dist/connector/mcp/mcp-toolset.d.ts.map +1 -0
- package/dist/connector/mcp/mcp-toolset.js +399 -0
- package/dist/connector/mcp/mcp-toolset.js.map +1 -0
- package/dist/connector/mcp/streamable-http.d.ts +15 -0
- package/dist/connector/mcp/streamable-http.d.ts.map +1 -1
- package/dist/connector/mcp/streamable-http.js +281 -6
- package/dist/connector/mcp/streamable-http.js.map +1 -1
- package/dist/connector/tools/index.d.ts +2 -2
- package/dist/connector/tools/index.d.ts.map +1 -1
- package/dist/connector/tools/index.js +1 -1
- package/dist/connector/tools/index.js.map +1 -1
- package/dist/connector/tools/router.d.ts +15 -13
- package/dist/connector/tools/router.d.ts.map +1 -1
- package/dist/connector/tools/router.js +30 -51
- package/dist/connector/tools/router.js.map +1 -1
- package/dist/contracts/a2a.d.ts +2 -2
- package/dist/directory/derive-supervisor.d.ts +2 -2
- package/dist/directory/derive-supervisor.d.ts.map +1 -1
- package/dist/directory/derive-supervisor.js +6 -7
- package/dist/directory/derive-supervisor.js.map +1 -1
- package/dist/directory/derive.d.ts.map +1 -1
- package/dist/directory/derive.js +5 -5
- package/dist/directory/derive.js.map +1 -1
- package/dist/execution/code-runtime/types.d.ts +2 -2
- package/dist/execution/code-runtime/types.js +1 -1
- package/dist/invariants/index.d.ts +2 -1
- package/dist/invariants/index.d.ts.map +1 -1
- package/dist/invariants/index.js +3 -2
- package/dist/invariants/index.js.map +1 -1
- package/dist/manager/agent/lifecycle.d.ts +1 -0
- package/dist/manager/agent/lifecycle.d.ts.map +1 -1
- package/dist/manager/agent/lifecycle.js +146 -18
- package/dist/manager/agent/lifecycle.js.map +1 -1
- package/dist/manager/connector/environment.d.ts +6 -0
- package/dist/manager/connector/environment.d.ts.map +1 -1
- package/dist/manager/connector/environment.js +11 -4
- package/dist/manager/connector/environment.js.map +1 -1
- package/dist/manager/connector/index.d.ts +2 -2
- package/dist/manager/connector/index.d.ts.map +1 -1
- package/dist/manager/connector/index.js +2 -2
- package/dist/manager/connector/index.js.map +1 -1
- package/dist/manager/connector/tenant.d.ts +6 -0
- package/dist/manager/connector/tenant.d.ts.map +1 -1
- package/dist/manager/connector/tenant.js +11 -4
- package/dist/manager/connector/tenant.js.map +1 -1
- package/dist/manager/index.d.ts +2 -2
- package/dist/manager/index.d.ts.map +1 -1
- package/dist/manager/index.js +2 -2
- package/dist/manager/index.js.map +1 -1
- package/dist/manager/resident/initiative.d.ts +6 -6
- package/dist/manager/resident/learning-observation.d.ts +4 -4
- package/dist/manager/resident/learning.d.ts +36 -36
- package/dist/manager/resident/outbox.d.ts +4 -4
- package/dist/manager/session/attribution.d.ts +22 -0
- package/dist/manager/session/attribution.d.ts.map +1 -0
- package/dist/manager/session/attribution.js +64 -0
- package/dist/manager/session/attribution.js.map +1 -0
- package/dist/manager/session/turn-recorder.d.ts +14 -0
- package/dist/manager/session/turn-recorder.d.ts.map +1 -1
- package/dist/manager/session/turn-recorder.js +208 -55
- package/dist/manager/session/turn-recorder.js.map +1 -1
- package/dist/peers/address.d.ts +36 -0
- package/dist/peers/address.d.ts.map +1 -0
- package/dist/peers/address.js +52 -0
- package/dist/peers/address.js.map +1 -0
- package/dist/peers/client.d.ts +47 -0
- package/dist/peers/client.d.ts.map +1 -0
- package/dist/peers/client.js +132 -0
- package/dist/peers/client.js.map +1 -0
- package/dist/peers/dir.d.ts +88 -0
- package/dist/peers/dir.d.ts.map +1 -0
- package/dist/peers/dir.js +139 -0
- package/dist/peers/dir.js.map +1 -0
- package/dist/peers/endpoint.d.ts +144 -0
- package/dist/peers/endpoint.d.ts.map +1 -0
- package/dist/peers/endpoint.js +420 -0
- package/dist/peers/endpoint.js.map +1 -0
- package/dist/peers/envelope.d.ts +42 -0
- package/dist/peers/envelope.d.ts.map +1 -0
- package/dist/peers/envelope.js +110 -0
- package/dist/peers/envelope.js.map +1 -0
- package/dist/peers/index.d.ts +30 -0
- package/dist/peers/index.d.ts.map +1 -0
- package/dist/peers/index.js +22 -0
- package/dist/peers/index.js.map +1 -0
- package/dist/peers/protocol.d.ts +645 -0
- package/dist/peers/protocol.d.ts.map +1 -0
- package/dist/peers/protocol.js +151 -0
- package/dist/peers/protocol.js.map +1 -0
- package/dist/peers/record.d.ts +71 -0
- package/dist/peers/record.d.ts.map +1 -0
- package/dist/peers/record.js +45 -0
- package/dist/peers/record.js.map +1 -0
- package/dist/peers/registry.d.ts +54 -0
- package/dist/peers/registry.d.ts.map +1 -0
- package/dist/peers/registry.js +213 -0
- package/dist/peers/registry.js.map +1 -0
- package/dist/plugin/define.d.ts +24 -0
- package/dist/plugin/define.d.ts.map +1 -0
- package/dist/plugin/define.js +42 -0
- package/dist/plugin/define.js.map +1 -0
- package/dist/plugin/index.d.ts +2 -0
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +1 -0
- package/dist/plugin/index.js.map +1 -1
- package/dist/plugin/lifecycle.d.ts +27 -3
- package/dist/plugin/lifecycle.d.ts.map +1 -1
- package/dist/plugin/lifecycle.js +242 -92
- package/dist/plugin/lifecycle.js.map +1 -1
- package/dist/plugin/resolver.d.ts +2 -2
- package/dist/plugin/resolver.d.ts.map +1 -1
- package/dist/plugin/resolver.js.map +1 -1
- package/dist/plugin/shell-hook.d.ts.map +1 -1
- package/dist/plugin/shell-hook.js +17 -3
- package/dist/plugin/shell-hook.js.map +1 -1
- package/dist/probe/errors.d.ts +2 -1
- package/dist/probe/errors.d.ts.map +1 -1
- package/dist/probe/errors.js +3 -2
- package/dist/probe/errors.js.map +1 -1
- package/dist/prompt/coding-agent-doctrine.d.ts +18 -7
- package/dist/prompt/coding-agent-doctrine.d.ts.map +1 -1
- package/dist/prompt/coding-agent-doctrine.js +11 -6
- package/dist/prompt/coding-agent-doctrine.js.map +1 -1
- package/dist/prompt/contributions.d.ts +4 -1
- package/dist/prompt/contributions.d.ts.map +1 -1
- package/dist/prompt/contributions.js +7 -2
- package/dist/prompt/contributions.js.map +1 -1
- package/dist/prompt/index.d.ts +1 -1
- package/dist/prompt/index.d.ts.map +1 -1
- package/dist/prompt/index.js +1 -1
- package/dist/prompt/index.js.map +1 -1
- package/dist/provider/collect-chat-completion.d.ts +6 -1
- package/dist/provider/collect-chat-completion.d.ts.map +1 -1
- package/dist/provider/collect-chat-completion.js +88 -10
- package/dist/provider/collect-chat-completion.js.map +1 -1
- package/dist/provider/mock.d.ts.map +1 -1
- package/dist/provider/mock.js +23 -6
- package/dist/provider/mock.js.map +1 -1
- package/dist/provider/registry.d.ts +2 -1
- package/dist/provider/registry.d.ts.map +1 -1
- package/dist/provider/registry.js +3 -2
- package/dist/provider/registry.js.map +1 -1
- package/dist/provider/tool-call-framing.d.ts +164 -0
- package/dist/provider/tool-call-framing.d.ts.map +1 -0
- package/dist/provider/tool-call-framing.js +163 -0
- package/dist/provider/tool-call-framing.js.map +1 -0
- package/dist/public-runtime.d.ts +24 -11
- package/dist/public-runtime.d.ts.map +1 -1
- package/dist/public-runtime.js +45 -9
- package/dist/public-runtime.js.map +1 -1
- package/dist/public-tools.d.ts +6 -4
- package/dist/public-tools.d.ts.map +1 -1
- package/dist/public-tools.js +8 -3
- package/dist/public-tools.js.map +1 -1
- package/dist/public-types.d.ts +13 -2
- package/dist/public-types.d.ts.map +1 -1
- package/dist/read-model/registry.d.ts +2 -1
- package/dist/read-model/registry.d.ts.map +1 -1
- package/dist/read-model/registry.js +3 -2
- package/dist/read-model/registry.js.map +1 -1
- package/dist/registry/ManagedRegistry.d.ts +30 -0
- package/dist/registry/ManagedRegistry.d.ts.map +1 -1
- package/dist/registry/ManagedRegistry.js +45 -6
- package/dist/registry/ManagedRegistry.js.map +1 -1
- package/dist/registry/collision.d.ts +57 -0
- package/dist/registry/collision.d.ts.map +1 -0
- package/dist/registry/collision.js +41 -0
- package/dist/registry/collision.js.map +1 -0
- package/dist/registry/command/index.d.ts +5 -3
- package/dist/registry/command/index.d.ts.map +1 -1
- package/dist/registry/command/index.js +6 -4
- package/dist/registry/command/index.js.map +1 -1
- package/dist/registry/index.d.ts +3 -4
- package/dist/registry/index.d.ts.map +1 -1
- package/dist/registry/index.js +2 -2
- package/dist/registry/index.js.map +1 -1
- package/dist/registry/plugin/index.d.ts.map +1 -1
- package/dist/registry/plugin/index.js +14 -1
- package/dist/registry/plugin/index.js.map +1 -1
- package/dist/registry/tool/callable.d.ts +7 -7
- package/dist/registry/tool/callable.d.ts.map +1 -1
- package/dist/registry/tool/callable.js +6 -7
- package/dist/registry/tool/callable.js.map +1 -1
- package/dist/registry/tool/execute.d.ts +14 -77
- package/dist/registry/tool/execute.d.ts.map +1 -1
- package/dist/registry/tool/execute.js +15 -727
- package/dist/registry/tool/execute.js.map +1 -1
- package/dist/registry/tool/portable.d.ts +25 -0
- package/dist/registry/tool/portable.d.ts.map +1 -1
- package/dist/registry/tool/portable.js +50 -0
- package/dist/registry/tool/portable.js.map +1 -1
- package/dist/registry/tool/presentation.d.ts +6 -5
- package/dist/registry/tool/presentation.d.ts.map +1 -1
- package/dist/registry/tool/presentation.js +3 -3
- package/dist/registry/tool/presentation.js.map +1 -1
- package/dist/runtime/bidi/session.d.ts +5 -4
- package/dist/runtime/bidi/session.d.ts.map +1 -1
- package/dist/runtime/bidi/session.js +18 -1
- package/dist/runtime/bidi/session.js.map +1 -1
- package/dist/runtime/query/executor/tool-call-admission.d.ts +45 -2
- package/dist/runtime/query/executor/tool-call-admission.d.ts.map +1 -1
- package/dist/runtime/query/executor/tool-call-admission.js +189 -5
- package/dist/runtime/query/executor/tool-call-admission.js.map +1 -1
- package/dist/runtime/query/executor.d.ts +33 -3
- package/dist/runtime/query/executor.d.ts.map +1 -1
- package/dist/runtime/query/executor.js +86 -10
- package/dist/runtime/query/executor.js.map +1 -1
- package/dist/runtime/query/file-evidence-replay.d.ts +1 -1
- package/dist/runtime/query/file-evidence-replay.d.ts.map +1 -1
- package/dist/runtime/query/file-evidence-replay.js +8 -7
- package/dist/runtime/query/file-evidence-replay.js.map +1 -1
- package/dist/runtime/query/fork/prepare.d.ts +4 -1
- package/dist/runtime/query/fork/prepare.d.ts.map +1 -1
- package/dist/runtime/query/fork/prepare.js +4 -0
- package/dist/runtime/query/fork/prepare.js.map +1 -1
- package/dist/runtime/query/guardrail-presets.d.ts +4 -3
- package/dist/runtime/query/guardrail-presets.d.ts.map +1 -1
- package/dist/runtime/query/guardrail-presets.js +4 -3
- package/dist/runtime/query/guardrail-presets.js.map +1 -1
- package/dist/runtime/query/index.d.ts +23 -10
- package/dist/runtime/query/index.d.ts.map +1 -1
- package/dist/runtime/query/index.js +149 -70
- package/dist/runtime/query/index.js.map +1 -1
- package/dist/runtime/query/iteration/index.d.ts.map +1 -1
- package/dist/runtime/query/iteration/index.js +8 -1
- package/dist/runtime/query/iteration/index.js.map +1 -1
- package/dist/runtime/query/iteration/phases/compaction.js +1 -1
- package/dist/runtime/query/iteration/phases/compaction.js.map +1 -1
- package/dist/runtime/query/iteration/phases/context.d.ts +2 -2
- package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/tool-review.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/tool-review.js +55 -2
- package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
- package/dist/runtime/query/iteration/stream-turn.d.ts.map +1 -1
- package/dist/runtime/query/iteration/stream-turn.js +342 -116
- package/dist/runtime/query/iteration/stream-turn.js.map +1 -1
- package/dist/runtime/query/iteration/tool-input.d.ts +79 -0
- package/dist/runtime/query/iteration/tool-input.d.ts.map +1 -0
- package/dist/runtime/query/iteration/tool-input.js +291 -0
- package/dist/runtime/query/iteration/tool-input.js.map +1 -0
- package/dist/runtime/query/observation-context.d.ts +2 -2
- package/dist/runtime/query/observation-context.d.ts.map +1 -1
- package/dist/runtime/query/observation-context.js.map +1 -1
- package/dist/runtime/query/prelude-lease.d.ts +18 -0
- package/dist/runtime/query/prelude-lease.d.ts.map +1 -0
- package/dist/runtime/query/prelude-lease.js +121 -0
- package/dist/runtime/query/prelude-lease.js.map +1 -0
- package/dist/runtime/query/prepare-turn.d.ts.map +1 -1
- package/dist/runtime/query/prepare-turn.js +386 -187
- package/dist/runtime/query/prepare-turn.js.map +1 -1
- package/dist/runtime/query/prompt-cache.d.ts +2 -2
- package/dist/runtime/query/prompt-cache.d.ts.map +1 -1
- package/dist/runtime/query/prompt.d.ts +2 -2
- package/dist/runtime/query/prompt.d.ts.map +1 -1
- package/dist/runtime/query/prompt.js +1 -1
- package/dist/runtime/query/prompt.js.map +1 -1
- package/dist/runtime/query/resume-session.d.ts.map +1 -1
- package/dist/runtime/query/resume-session.js +37 -2
- package/dist/runtime/query/resume-session.js.map +1 -1
- package/dist/runtime/query/review-policy.d.ts +22 -3
- package/dist/runtime/query/review-policy.d.ts.map +1 -1
- package/dist/runtime/query/review-policy.js +84 -6
- package/dist/runtime/query/review-policy.js.map +1 -1
- package/dist/runtime/query/tooling.d.ts +3 -2
- package/dist/runtime/query/tooling.d.ts.map +1 -1
- package/dist/runtime/query/tooling.js.map +1 -1
- package/dist/runtime/query/turn-state.d.ts.map +1 -1
- package/dist/runtime/query/turn-state.js +5 -0
- package/dist/runtime/query/turn-state.js.map +1 -1
- package/dist/runtime/system-events.d.ts +112 -0
- package/dist/runtime/system-events.d.ts.map +1 -0
- package/dist/runtime/system-events.js +183 -0
- package/dist/runtime/system-events.js.map +1 -0
- package/dist/scheduler/delegating.d.ts +2 -1
- package/dist/scheduler/delegating.d.ts.map +1 -1
- package/dist/scheduler/delegating.js +3 -2
- package/dist/scheduler/delegating.js.map +1 -1
- package/dist/scheduler/local.d.ts.map +1 -1
- package/dist/scheduler/local.js +2 -0
- package/dist/scheduler/local.js.map +1 -1
- package/dist/session/retention/archive.js +1 -1
- package/dist/session/retention/archive.js.map +1 -1
- package/dist/skills/index.d.ts +1 -1
- package/dist/skills/index.d.ts.map +1 -1
- package/dist/skills/index.js +1 -1
- package/dist/skills/index.js.map +1 -1
- package/dist/skills/registry.d.ts +12 -0
- package/dist/skills/registry.d.ts.map +1 -1
- package/dist/skills/registry.js +19 -0
- package/dist/skills/registry.js.map +1 -1
- package/dist/store/evidence/index-page.d.ts +2 -2
- package/dist/store/session/disk.d.ts.map +1 -1
- package/dist/store/session/disk.js +2 -0
- package/dist/store/session/disk.js.map +1 -1
- package/dist/store/session-log/conformance.d.ts +1 -1
- package/dist/store/session-log/conformance.d.ts.map +1 -1
- package/dist/store/session-log/conformance.js +49 -8
- package/dist/store/session-log/conformance.js.map +1 -1
- package/dist/store/session-log/core.d.ts +8 -3
- package/dist/store/session-log/core.d.ts.map +1 -1
- package/dist/store/session-log/core.js +2 -1
- package/dist/store/session-log/core.js.map +1 -1
- package/dist/store/session-log/fold.d.ts +12 -0
- package/dist/store/session-log/fold.d.ts.map +1 -1
- package/dist/store/session-log/fold.js +57 -7
- package/dist/store/session-log/fold.js.map +1 -1
- package/dist/store/session-log/index.d.ts +2 -2
- package/dist/store/session-log/index.d.ts.map +1 -1
- package/dist/store/session-log/index.js +1 -1
- package/dist/store/session-log/index.js.map +1 -1
- package/dist/test-support/toolset.d.ts +19 -0
- package/dist/test-support/toolset.d.ts.map +1 -0
- package/dist/test-support/toolset.js +20 -0
- package/dist/test-support/toolset.js.map +1 -0
- package/dist/tools/builtins/bash.d.ts +29 -0
- package/dist/tools/builtins/bash.d.ts.map +1 -1
- package/dist/tools/builtins/bash.js +19 -9
- package/dist/tools/builtins/bash.js.map +1 -1
- package/dist/tools/builtins/browser-url.d.ts +1 -1
- package/dist/tools/builtins/browser-url.js +1 -1
- package/dist/tools/builtins/browser.d.ts +6 -6
- package/dist/tools/builtins/browser.js +2 -2
- package/dist/tools/builtins/browser.js.map +1 -1
- package/dist/tools/builtins/computer-use.d.ts.map +1 -1
- package/dist/tools/builtins/computer-use.js +19 -11
- package/dist/tools/builtins/computer-use.js.map +1 -1
- package/dist/tools/builtins/edit.d.ts.map +1 -1
- package/dist/tools/builtins/edit.js +9 -1
- package/dist/tools/builtins/edit.js.map +1 -1
- package/dist/tools/builtins/json-string-hint.d.ts +15 -0
- package/dist/tools/builtins/json-string-hint.d.ts.map +1 -0
- package/dist/tools/builtins/json-string-hint.js +17 -0
- package/dist/tools/builtins/json-string-hint.js.map +1 -0
- package/dist/tools/builtins/search-tools.d.ts.map +1 -1
- package/dist/tools/builtins/search-tools.js +7 -15
- package/dist/tools/builtins/search-tools.js.map +1 -1
- package/dist/tools/builtins/write-file.d.ts.map +1 -1
- package/dist/tools/builtins/write-file.js +11 -0
- package/dist/tools/builtins/write-file.js.map +1 -1
- package/dist/tools/command-shell.d.ts +10 -0
- package/dist/tools/command-shell.d.ts.map +1 -1
- package/dist/tools/command-shell.js +45 -1
- package/dist/tools/command-shell.js.map +1 -1
- package/dist/tools/coordinator/agent.d.ts.map +1 -1
- package/dist/tools/coordinator/agent.js +5 -0
- package/dist/tools/coordinator/agent.js.map +1 -1
- package/dist/tools/coordinator/ask-user-question.d.ts.map +1 -1
- package/dist/tools/coordinator/ask-user-question.js +26 -13
- package/dist/tools/coordinator/ask-user-question.js.map +1 -1
- package/dist/tools/coordinator/index.d.ts.map +1 -1
- package/dist/tools/coordinator/index.js +5 -0
- package/dist/tools/coordinator/index.js.map +1 -1
- package/dist/tools/coordinator/question-options.d.ts +78 -0
- package/dist/tools/coordinator/question-options.d.ts.map +1 -0
- package/dist/tools/coordinator/question-options.js +153 -0
- package/dist/tools/coordinator/question-options.js.map +1 -0
- package/dist/tools/defineTool.d.ts +10 -0
- package/dist/tools/defineTool.d.ts.map +1 -1
- package/dist/tools/defineTool.js +17 -0
- package/dist/tools/defineTool.js.map +1 -1
- package/dist/tools/memory/search.d.ts.map +1 -1
- package/dist/tools/memory/search.js +4 -1
- package/dist/tools/memory/search.js.map +1 -1
- package/dist/tools/memory/update.d.ts.map +1 -1
- package/dist/tools/memory/update.js +8 -5
- package/dist/tools/memory/update.js.map +1 -1
- package/dist/tools/render-nonce.d.ts +47 -0
- package/dist/tools/render-nonce.d.ts.map +1 -0
- package/dist/tools/render-nonce.js +63 -0
- package/dist/tools/render-nonce.js.map +1 -0
- package/dist/tools/roster.d.ts +46 -19
- package/dist/tools/roster.d.ts.map +1 -1
- package/dist/tools/roster.js +63 -33
- package/dist/tools/roster.js.map +1 -1
- package/dist/tools/schedules/schedule-tool.d.ts.map +1 -1
- package/dist/tools/schedules/schedule-tool.js +94 -14
- package/dist/tools/schedules/schedule-tool.js.map +1 -1
- package/dist/tools/schedules/types.d.ts +52 -6
- package/dist/tools/schedules/types.d.ts.map +1 -1
- package/dist/tools/trusted-read-only.d.ts +9 -5
- package/dist/tools/trusted-read-only.d.ts.map +1 -1
- package/dist/tools/trusted-read-only.js +14 -10
- package/dist/tools/trusted-read-only.js.map +1 -1
- package/dist/tools/untrusted-envelope.d.ts +67 -28
- package/dist/tools/untrusted-envelope.d.ts.map +1 -1
- package/dist/tools/untrusted-envelope.js +108 -59
- package/dist/tools/untrusted-envelope.js.map +1 -1
- package/dist/toolsets/combine.d.ts +44 -0
- package/dist/toolsets/combine.d.ts.map +1 -0
- package/dist/toolsets/combine.js +153 -0
- package/dist/toolsets/combine.js.map +1 -0
- package/dist/toolsets/manager.d.ts +201 -0
- package/dist/toolsets/manager.d.ts.map +1 -0
- package/dist/toolsets/manager.js +837 -0
- package/dist/toolsets/manager.js.map +1 -0
- package/dist/toolsets/source-glob.d.ts +15 -0
- package/dist/toolsets/source-glob.d.ts.map +1 -0
- package/dist/toolsets/source-glob.js +23 -0
- package/dist/toolsets/source-glob.js.map +1 -0
- package/dist/toolsets/toolset.d.ts +20 -0
- package/dist/toolsets/toolset.d.ts.map +1 -0
- package/dist/toolsets/toolset.js +28 -0
- package/dist/toolsets/toolset.js.map +1 -0
- package/dist/toolsets/types.d.ts +128 -0
- package/dist/toolsets/types.d.ts.map +1 -0
- package/dist/toolsets/types.js +33 -0
- package/dist/toolsets/types.js.map +1 -0
- package/dist/toolsets/wrappers.d.ts +59 -0
- package/dist/toolsets/wrappers.d.ts.map +1 -0
- package/dist/toolsets/wrappers.js +165 -0
- package/dist/toolsets/wrappers.js.map +1 -0
- package/dist/types/agent/base.d.ts +27 -16
- package/dist/types/agent/base.d.ts.map +1 -1
- package/dist/types/agent/index.d.ts +1 -0
- package/dist/types/agent/index.d.ts.map +1 -1
- package/dist/types/agent/index.js +1 -0
- package/dist/types/agent/index.js.map +1 -1
- package/dist/types/agent/pipeline.d.ts +2 -0
- package/dist/types/agent/pipeline.d.ts.map +1 -1
- package/dist/types/agent/query.d.ts +117 -0
- package/dist/types/agent/query.d.ts.map +1 -0
- package/dist/types/agent/query.js +2 -0
- package/dist/types/agent/query.js.map +1 -0
- package/dist/types/agent/reactive.d.ts +2 -129
- package/dist/types/agent/reactive.d.ts.map +1 -1
- package/dist/types/agent/router.d.ts +2 -0
- package/dist/types/agent/router.d.ts.map +1 -1
- package/dist/types/agent/scheduler.d.ts +6 -1
- package/dist/types/agent/scheduler.d.ts.map +1 -1
- package/dist/types/agent/supervisor.d.ts +5 -2
- package/dist/types/agent/supervisor.d.ts.map +1 -1
- package/dist/types/agent/task.d.ts +19 -1
- package/dist/types/agent/task.d.ts.map +1 -1
- package/dist/types/agent/task.js.map +1 -1
- package/dist/types/authorization/index.d.ts +49 -12
- package/dist/types/authorization/index.d.ts.map +1 -1
- package/dist/types/authorization/index.js +6 -0
- package/dist/types/authorization/index.js.map +1 -1
- package/dist/types/connector/mcp.d.ts +45 -0
- package/dist/types/connector/mcp.d.ts.map +1 -1
- package/dist/types/errors/index.d.ts +15 -0
- package/dist/types/errors/index.d.ts.map +1 -1
- package/dist/types/errors/index.js.map +1 -1
- package/dist/types/hitl/index.d.ts +57 -0
- package/dist/types/hitl/index.d.ts.map +1 -1
- package/dist/types/hitl/index.js.map +1 -1
- package/dist/types/message/index.d.ts +130 -9
- package/dist/types/message/index.d.ts.map +1 -1
- package/dist/types/message/index.js +4 -1
- package/dist/types/message/index.js.map +1 -1
- package/dist/types/plugin/index.d.ts +22 -4
- package/dist/types/plugin/index.d.ts.map +1 -1
- package/dist/types/plugin/index.js +1 -0
- package/dist/types/plugin/index.js.map +1 -1
- package/dist/types/provider/chat.d.ts +5 -0
- package/dist/types/provider/chat.d.ts.map +1 -1
- package/dist/types/provider/config.d.ts +8 -3
- package/dist/types/provider/config.d.ts.map +1 -1
- package/dist/types/provider/stream.d.ts +39 -0
- package/dist/types/provider/stream.d.ts.map +1 -1
- package/dist/types/sandbox/index.d.ts +1 -1
- package/dist/types/session/events.d.ts +14 -3
- package/dist/types/session/events.d.ts.map +1 -1
- package/dist/types/session/events.js.map +1 -1
- package/dist/types/session/sub-session.d.ts +2 -0
- package/dist/types/session/sub-session.d.ts.map +1 -1
- package/dist/types/tool/index.d.ts +152 -91
- package/dist/types/tool/index.d.ts.map +1 -1
- package/dist/types/tool/index.js.map +1 -1
- package/dist/types/toolset/index.d.ts +10 -40
- package/dist/types/toolset/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/advisory/history.ts +27 -2
- package/src/advisory/index.ts +1 -1
- package/src/advisory/registry.ts +33 -0
- package/src/agents/AGENTS.md +14 -7
- package/src/agents/PipelineAgent.ts +2 -303
- package/src/agents/QueryAgent.ts +269 -0
- package/src/agents/ReactiveAgent.ts +6 -216
- package/src/agents/RouterAgent.ts +2 -337
- package/src/agents/SupervisorAgent.ts +3 -476
- package/src/agents/defineAgent.ts +13 -2
- package/src/agents/examples/PipelineAgent.ts +302 -0
- package/src/agents/examples/RouterAgent.ts +338 -0
- package/src/agents/examples/SupervisorAgent.ts +472 -0
- package/src/agents/explore.ts +6 -3
- package/src/agents/forward-options.ts +37 -0
- package/src/agents/index.ts +2 -0
- package/src/agents/runAgent.ts +144 -37
- package/src/authorization/command-line.ts +2 -2
- package/src/authorization/gate.ts +21 -1
- package/src/authorization/program.ts +773 -0
- package/src/authorization/reexec-wrapper.ts +589 -0
- package/src/authorization/rules.ts +18 -1
- package/src/authorization/shell-lexer.ts +104 -59
- package/src/bridge/sse/mapper.ts +6 -0
- package/src/capabilities/index.ts +157 -0
- package/src/config/registry.ts +4 -1
- package/src/connector/index.ts +9 -2
- package/src/connector/mcp/adapter.ts +73 -3
- package/src/connector/mcp/client.ts +425 -6
- package/src/connector/mcp/discovery.ts +60 -0
- package/src/connector/mcp/era.ts +7 -0
- package/src/connector/mcp/index.ts +13 -0
- package/src/connector/mcp/mcp-toolset.ts +515 -0
- package/src/connector/mcp/streamable-http.ts +302 -5
- package/src/connector/tools/index.ts +2 -2
- package/src/connector/tools/router.ts +35 -58
- package/src/directory/derive-supervisor.ts +12 -8
- package/src/directory/derive.ts +8 -5
- package/src/execution/code-runtime/types.ts +2 -2
- package/src/invariants/index.ts +4 -1
- package/src/manager/agent/lifecycle.ts +167 -19
- package/src/manager/connector/environment.ts +17 -4
- package/src/manager/connector/index.ts +2 -2
- package/src/manager/connector/tenant.ts +17 -4
- package/src/manager/index.ts +2 -2
- package/src/manager/session/attribution.ts +79 -0
- package/src/manager/session/turn-recorder.ts +211 -55
- package/src/peers/address.ts +58 -0
- package/src/peers/client.ts +202 -0
- package/src/peers/dir.ts +176 -0
- package/src/peers/endpoint.ts +564 -0
- package/src/peers/envelope.ts +121 -0
- package/src/peers/index.ts +96 -0
- package/src/peers/protocol.ts +196 -0
- package/src/peers/record.ts +56 -0
- package/src/peers/registry.ts +241 -0
- package/src/plugin/define.ts +68 -0
- package/src/plugin/index.ts +2 -0
- package/src/plugin/lifecycle.ts +286 -106
- package/src/plugin/resolver.ts +6 -3
- package/src/plugin/shell-hook.ts +21 -5
- package/src/probe/errors.ts +4 -1
- package/src/prompt/coding-agent-doctrine.ts +22 -10
- package/src/prompt/contributions.ts +12 -2
- package/src/prompt/index.ts +1 -0
- package/src/provider/collect-chat-completion.ts +96 -11
- package/src/provider/mock.ts +24 -6
- package/src/provider/registry.ts +4 -1
- package/src/provider/tool-call-framing.ts +226 -0
- package/src/public-runtime.ts +136 -7
- package/src/public-tools.ts +24 -4
- package/src/public-types.ts +60 -6
- package/src/read-model/registry.ts +7 -2
- package/src/registry/ManagedRegistry.ts +57 -6
- package/src/registry/collision.ts +64 -0
- package/src/registry/command/index.ts +7 -3
- package/src/registry/index.ts +3 -9
- package/src/registry/plugin/index.ts +14 -1
- package/src/registry/tool/callable.ts +8 -9
- package/src/registry/tool/execute.ts +16 -846
- package/src/registry/tool/portable.ts +59 -0
- package/src/registry/tool/presentation.ts +6 -5
- package/src/runtime/bidi/session.ts +24 -5
- package/src/runtime/query/executor/tool-call-admission.ts +228 -6
- package/src/runtime/query/executor.ts +110 -12
- package/src/runtime/query/file-evidence-replay.ts +8 -7
- package/src/runtime/query/fork/prepare.ts +6 -1
- package/src/runtime/query/guardrail-presets.ts +4 -3
- package/src/runtime/query/index.ts +199 -101
- package/src/runtime/query/iteration/index.ts +13 -3
- package/src/runtime/query/iteration/phases/compaction.ts +1 -1
- package/src/runtime/query/iteration/phases/context.ts +2 -2
- package/src/runtime/query/iteration/phases/tool-review.ts +59 -2
- package/src/runtime/query/iteration/stream-turn.ts +390 -136
- package/src/runtime/query/iteration/tool-input.ts +284 -0
- package/src/runtime/query/observation-context.ts +2 -2
- package/src/runtime/query/prelude-lease.ts +132 -0
- package/src/runtime/query/prepare-turn.ts +477 -198
- package/src/runtime/query/prompt-cache.ts +2 -2
- package/src/runtime/query/prompt.ts +4 -4
- package/src/runtime/query/resume-session.ts +42 -3
- package/src/runtime/query/review-policy.ts +87 -9
- package/src/runtime/query/tooling.ts +3 -6
- package/src/runtime/query/turn-state.ts +4 -0
- package/src/runtime/system-events.ts +246 -0
- package/src/scheduler/delegating.ts +7 -2
- package/src/scheduler/local.ts +2 -0
- package/src/session/retention/archive.ts +1 -1
- package/src/skills/index.ts +1 -1
- package/src/skills/registry.ts +25 -0
- package/src/store/session/disk.ts +3 -0
- package/src/store/session-log/conformance.ts +51 -8
- package/src/store/session-log/core.ts +10 -4
- package/src/store/session-log/fold.ts +33 -7
- package/src/store/session-log/index.ts +2 -0
- package/src/test-support/toolset.ts +23 -0
- package/src/tools/builtins/bash.ts +27 -10
- package/src/tools/builtins/browser-url.ts +1 -1
- package/src/tools/builtins/browser.ts +2 -2
- package/src/tools/builtins/computer-use.ts +21 -11
- package/src/tools/builtins/edit.ts +12 -2
- package/src/tools/builtins/json-string-hint.ts +16 -0
- package/src/tools/builtins/search-tools.ts +7 -20
- package/src/tools/builtins/write-file.ts +12 -0
- package/src/tools/command-shell.ts +46 -1
- package/src/tools/coordinator/agent.ts +6 -0
- package/src/tools/coordinator/ask-user-question.ts +29 -15
- package/src/tools/coordinator/index.ts +6 -0
- package/src/tools/coordinator/question-options.ts +195 -0
- package/src/tools/defineTool.ts +28 -0
- package/src/tools/memory/search.ts +4 -1
- package/src/tools/memory/update.ts +8 -5
- package/src/tools/render-nonce.ts +69 -0
- package/src/tools/roster.ts +84 -33
- package/src/tools/schedules/schedule-tool.ts +107 -14
- package/src/tools/schedules/types.ts +52 -6
- package/src/tools/trusted-read-only.ts +19 -10
- package/src/tools/untrusted-envelope.ts +121 -57
- package/src/toolsets/combine.ts +181 -0
- package/src/toolsets/manager.ts +996 -0
- package/src/toolsets/source-glob.ts +22 -0
- package/src/toolsets/toolset.ts +31 -0
- package/src/toolsets/types.ts +154 -0
- package/src/toolsets/wrappers.ts +191 -0
- package/src/types/agent/base.ts +29 -16
- package/src/types/agent/index.ts +1 -0
- package/src/types/agent/pipeline.ts +2 -0
- package/src/types/agent/query.ts +129 -0
- package/src/types/agent/reactive.ts +5 -142
- package/src/types/agent/router.ts +2 -0
- package/src/types/agent/scheduler.ts +6 -1
- package/src/types/agent/supervisor.ts +5 -2
- package/src/types/agent/task.ts +21 -1
- package/src/types/authorization/index.ts +12 -0
- package/src/types/connector/mcp.ts +46 -0
- package/src/types/errors/index.ts +15 -0
- package/src/types/hitl/index.ts +57 -0
- package/src/types/message/index.ts +135 -7
- package/src/types/plugin/index.ts +44 -21
- package/src/types/provider/chat.ts +5 -0
- package/src/types/provider/config.ts +8 -3
- package/src/types/provider/stream.ts +39 -0
- package/src/types/sandbox/index.ts +1 -1
- package/src/types/session/events.ts +14 -3
- package/src/types/session/sub-session.ts +2 -0
- package/src/types/tool/index.ts +154 -105
- package/src/types/toolset/index.ts +10 -47
- package/dist/registry/toolset/catalog.d.ts +0 -42
- package/dist/registry/toolset/catalog.d.ts.map +0 -1
- package/dist/registry/toolset/catalog.js +0 -234
- package/dist/registry/toolset/catalog.js.map +0 -1
- package/src/registry/toolset/catalog.ts +0 -308
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto'
|
|
2
|
+
|
|
1
3
|
import type {
|
|
2
4
|
MCPClientConfig,
|
|
3
5
|
MCPClientState,
|
|
@@ -9,6 +11,7 @@ import type {
|
|
|
9
11
|
MCPInitializeResult,
|
|
10
12
|
MCPJsonRpcMessage,
|
|
11
13
|
MCPLifecycleEvent,
|
|
14
|
+
MCPProgressUpdate,
|
|
12
15
|
MCPPromptDefinition,
|
|
13
16
|
MCPPromptMessage,
|
|
14
17
|
MCPRequestOptions,
|
|
@@ -48,7 +51,7 @@ import {
|
|
|
48
51
|
} from './errors.js'
|
|
49
52
|
import { HttpSseTransport } from './http-sse.js'
|
|
50
53
|
import { StdioTransport } from './stdio.js'
|
|
51
|
-
import { StreamableHttpTransport } from './streamable-http.js'
|
|
54
|
+
import { MCPSubscriptionResponseError, StreamableHttpTransport } from './streamable-http.js'
|
|
52
55
|
import { type McpParamHeaderBinding, validateMcpHeaderAnnotations } from './x-mcp-header.js'
|
|
53
56
|
|
|
54
57
|
import {
|
|
@@ -70,9 +73,104 @@ const MAX_LIST_PAGES = 100
|
|
|
70
73
|
|
|
71
74
|
/** A cancellation notification must never become the next unbounded wait. */
|
|
72
75
|
const CANCEL_NOTIFICATION_TIMEOUT_MS = 1_000
|
|
76
|
+
const MAX_PROGRESS_MESSAGE_BYTES = 512
|
|
77
|
+
const ANSI_CSI_PATTERN = new RegExp(`${String.fromCharCode(27)}\\[[0-?]*[ -/]*[@-~]`, 'g')
|
|
78
|
+
const SUBSCRIPTION_ID_META_KEY = 'io.modelcontextprotocol/subscriptionId'
|
|
79
|
+
const SUBSCRIPTION_RETRY_MAX_MS = 30_000
|
|
80
|
+
/** Auth may refresh; timeouts, conflicts and rate limits can clear without reconnecting. */
|
|
81
|
+
const RETRYABLE_SUBSCRIPTION_CLIENT_STATUSES = new Set([401, 403, 408, 409, 425, 429])
|
|
82
|
+
|
|
83
|
+
type ListChangeFilter = {
|
|
84
|
+
toolsListChanged?: true
|
|
85
|
+
promptsListChanged?: true
|
|
86
|
+
resourcesListChanged?: true
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
interface ModernSubscription {
|
|
90
|
+
readonly id: number
|
|
91
|
+
readonly requested: ListChangeFilter
|
|
92
|
+
readonly controller: AbortController
|
|
93
|
+
readonly ackTimer: ReturnType<typeof setTimeout>
|
|
94
|
+
acknowledged?: ListChangeFilter
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const SUBSCRIPTION_NOTIFICATIONS = {
|
|
98
|
+
'notifications/tools/list_changed': 'toolsListChanged',
|
|
99
|
+
'notifications/prompts/list_changed': 'promptsListChanged',
|
|
100
|
+
'notifications/resources/list_changed': 'resourcesListChanged',
|
|
101
|
+
} as const
|
|
102
|
+
|
|
103
|
+
function subscriptionFilter(capabilities: MCPServerCapabilities | undefined): ListChangeFilter {
|
|
104
|
+
return {
|
|
105
|
+
...(capabilities?.tools?.listChanged === true ? { toolsListChanged: true as const } : {}),
|
|
106
|
+
...(capabilities?.prompts?.listChanged === true ? { promptsListChanged: true as const } : {}),
|
|
107
|
+
...(capabilities?.resources?.listChanged === true
|
|
108
|
+
? { resourcesListChanged: true as const }
|
|
109
|
+
: {}),
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function acknowledgedFilter(
|
|
114
|
+
value: unknown,
|
|
115
|
+
requested: ListChangeFilter,
|
|
116
|
+
): ListChangeFilter | undefined {
|
|
117
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return undefined
|
|
118
|
+
const record = value as Record<string, unknown>
|
|
119
|
+
const acknowledged: ListChangeFilter = {}
|
|
120
|
+
for (const [key, entry] of Object.entries(record)) {
|
|
121
|
+
if (!Object.hasOwn(requested, key) || (entry !== true && entry !== false)) return undefined
|
|
122
|
+
if (entry === true) (acknowledged as Record<string, true>)[key] = true
|
|
123
|
+
}
|
|
124
|
+
return acknowledged
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** A rejected listen request with the same inputs cannot heal by repeating it. */
|
|
128
|
+
function isPermanentSubscriptionFailure(error: unknown, requestId: number): boolean {
|
|
129
|
+
if (!(error instanceof MCPHttpStatusError || error instanceof MCPSubscriptionResponseError))
|
|
130
|
+
return false
|
|
131
|
+
try {
|
|
132
|
+
const reply = JSON.parse(error.bodyText) as MCPJsonRpcMessage
|
|
133
|
+
if (
|
|
134
|
+
reply?.jsonrpc === '2.0' &&
|
|
135
|
+
reply.id === requestId &&
|
|
136
|
+
reply.method === undefined &&
|
|
137
|
+
reply.error?.code === JSON_RPC_METHOD_NOT_FOUND
|
|
138
|
+
) {
|
|
139
|
+
return true
|
|
140
|
+
}
|
|
141
|
+
} catch {
|
|
142
|
+
// Only a failed HTTP status can determine policy without a JSON-RPC reply.
|
|
143
|
+
}
|
|
144
|
+
return (
|
|
145
|
+
error instanceof MCPHttpStatusError &&
|
|
146
|
+
error.status >= 400 &&
|
|
147
|
+
error.status < 500 &&
|
|
148
|
+
!RETRYABLE_SUBSCRIPTION_CLIENT_STATUSES.has(error.status)
|
|
149
|
+
)
|
|
150
|
+
}
|
|
73
151
|
|
|
74
152
|
const NAMZU_CLIENT_INFO = { name: 'namzu-sdk', version: VERSION }
|
|
75
153
|
|
|
154
|
+
/** Keep server-authored status text safe and small before it reaches a host UI. */
|
|
155
|
+
function progressMessage(value: unknown): string | undefined {
|
|
156
|
+
if (typeof value !== 'string') return undefined
|
|
157
|
+
const plain = value
|
|
158
|
+
.slice(0, MAX_PROGRESS_MESSAGE_BYTES * 4)
|
|
159
|
+
.replace(ANSI_CSI_PATTERN, '')
|
|
160
|
+
.replace(/[\p{Cc}\p{Cf}\p{Cs}]/gu, ' ')
|
|
161
|
+
.trim()
|
|
162
|
+
if (!plain) return undefined
|
|
163
|
+
let bounded = ''
|
|
164
|
+
let bytes = 0
|
|
165
|
+
for (const character of plain) {
|
|
166
|
+
const length = Buffer.byteLength(character, 'utf8')
|
|
167
|
+
if (bytes + length > MAX_PROGRESS_MESSAGE_BYTES) break
|
|
168
|
+
bounded += character
|
|
169
|
+
bytes += length
|
|
170
|
+
}
|
|
171
|
+
return bounded
|
|
172
|
+
}
|
|
173
|
+
|
|
76
174
|
/**
|
|
77
175
|
* The three header names the protocol owns, lower-cased for matching.
|
|
78
176
|
*
|
|
@@ -119,6 +217,7 @@ export class MCPClient {
|
|
|
119
217
|
private status: MCPConnectionStatus = 'disconnected'
|
|
120
218
|
private serverInfo?: { name: string; version?: string }
|
|
121
219
|
private serverCapabilities?: MCPServerCapabilities
|
|
220
|
+
private serverInstructions?: string
|
|
122
221
|
private era?: McpEra
|
|
123
222
|
private connectedAt?: number
|
|
124
223
|
private error?: string
|
|
@@ -131,9 +230,16 @@ export class MCPClient {
|
|
|
131
230
|
}
|
|
132
231
|
>()
|
|
133
232
|
private nextRequestId = 1
|
|
233
|
+
private progressRequests = new Map<
|
|
234
|
+
string,
|
|
235
|
+
{ onProgress: (update: MCPProgressUpdate) => void; lastProgress?: number }
|
|
236
|
+
>()
|
|
134
237
|
private notificationHandlers: Array<(method: string, params?: Record<string, unknown>) => void> =
|
|
135
238
|
[]
|
|
136
239
|
private lifecycleListeners: MCPEventListener[] = []
|
|
240
|
+
private modernSubscription?: ModernSubscription
|
|
241
|
+
private subscriptionRestartTimer?: ReturnType<typeof setTimeout>
|
|
242
|
+
private subscriptionFailures = 0
|
|
137
243
|
/** Best-effort protocol cancellations still belong to this connection generation. */
|
|
138
244
|
private cancellationControllers = new Set<AbortController>()
|
|
139
245
|
private log: Logger
|
|
@@ -187,6 +293,7 @@ export class MCPClient {
|
|
|
187
293
|
throw new Error(`MCPClient already connected to "${this.config.serverName}"`)
|
|
188
294
|
}
|
|
189
295
|
|
|
296
|
+
this.stopModernSubscription(false)
|
|
190
297
|
this.status = 'connecting'
|
|
191
298
|
// Tool schemas belong to a listing, and a listing belongs to a
|
|
192
299
|
// connection. Carrying bindings across a reconnect would mirror the
|
|
@@ -202,6 +309,7 @@ export class MCPClient {
|
|
|
202
309
|
try {
|
|
203
310
|
this.transport.onMessage((msg) => this.handleMessage(msg))
|
|
204
311
|
this.transport.onClose(() => {
|
|
312
|
+
this.stopModernSubscription(false)
|
|
205
313
|
this.status = 'disconnected'
|
|
206
314
|
this.abortCancellations(new Error('MCP transport closed'))
|
|
207
315
|
this.log.info('MCP transport closed')
|
|
@@ -209,6 +317,7 @@ export class MCPClient {
|
|
|
209
317
|
this.rejectAllPending(`MCP transport to "${this.config.serverName}" closed`)
|
|
210
318
|
})
|
|
211
319
|
this.transport.onError((err) => {
|
|
320
|
+
this.stopModernSubscription(false)
|
|
212
321
|
this.status = 'error'
|
|
213
322
|
this.abortCancellations(err)
|
|
214
323
|
this.error = err.message
|
|
@@ -312,6 +421,7 @@ export class MCPClient {
|
|
|
312
421
|
|
|
313
422
|
this.serverInfo = result.serverInfo
|
|
314
423
|
this.serverCapabilities = result.capabilities
|
|
424
|
+
this.serverInstructions = result.instructions
|
|
315
425
|
|
|
316
426
|
await this.notify('notifications/initialized', {})
|
|
317
427
|
|
|
@@ -486,6 +596,7 @@ export class MCPClient {
|
|
|
486
596
|
const result = this.modernInitializeResult(era.version, resolution.discover)
|
|
487
597
|
this.serverInfo = result.serverInfo
|
|
488
598
|
this.serverCapabilities = result.capabilities
|
|
599
|
+
this.serverInstructions = result.instructions
|
|
489
600
|
|
|
490
601
|
this.status = 'connected'
|
|
491
602
|
this.connectedAt = Date.now()
|
|
@@ -498,6 +609,7 @@ export class MCPClient {
|
|
|
498
609
|
[NAMZU.SERVER_NAME]: result.serverInfo.name,
|
|
499
610
|
}
|
|
500
611
|
this.log.info('Connected to MCP server', connectedAttributes)
|
|
612
|
+
this.startModernSubscription()
|
|
501
613
|
return result
|
|
502
614
|
}
|
|
503
615
|
|
|
@@ -509,6 +621,9 @@ export class MCPClient {
|
|
|
509
621
|
* not name itself is reported under the name the operator gave it.
|
|
510
622
|
* Inventing a placeholder like "unknown" would put a word in the
|
|
511
623
|
* server's mouth in the one field a person reads to identify it.
|
|
624
|
+
*
|
|
625
|
+
* `instructions` is left unset: the modern era has no `initialize`
|
|
626
|
+
* round trip, so there is nothing in a `DiscoverResult` to carry it.
|
|
512
627
|
*/
|
|
513
628
|
private modernInitializeResult(
|
|
514
629
|
version: McpModernVersion,
|
|
@@ -521,8 +636,151 @@ export class MCPClient {
|
|
|
521
636
|
}
|
|
522
637
|
}
|
|
523
638
|
|
|
639
|
+
/** Subscribe only to change kinds the modern server actually advertised. */
|
|
640
|
+
private startModernSubscription(): void {
|
|
641
|
+
if (this.status !== 'connected' || this.era?.kind !== 'modern' || this.modernSubscription) {
|
|
642
|
+
return
|
|
643
|
+
}
|
|
644
|
+
const requested = subscriptionFilter(this.serverCapabilities)
|
|
645
|
+
if (Object.keys(requested).length === 0) return
|
|
646
|
+
const id = this.nextRequestId++
|
|
647
|
+
const controller = new AbortController()
|
|
648
|
+
const envelope = buildEnvelope({
|
|
649
|
+
era: this.era,
|
|
650
|
+
method: 'subscriptions/listen',
|
|
651
|
+
params: { notifications: requested },
|
|
652
|
+
clientInfo: this.config.clientInfo ?? NAMZU_CLIENT_INFO,
|
|
653
|
+
capabilities: this.config.capabilities ?? {},
|
|
654
|
+
})
|
|
655
|
+
const subscription: ModernSubscription = {
|
|
656
|
+
id,
|
|
657
|
+
requested,
|
|
658
|
+
controller,
|
|
659
|
+
ackTimer: setTimeout(() => {
|
|
660
|
+
this.finishModernSubscription(subscription, 'acknowledgment timed out', true)
|
|
661
|
+
}, this.requestTimeoutMs),
|
|
662
|
+
}
|
|
663
|
+
subscription.ackTimer.unref?.()
|
|
664
|
+
this.modernSubscription = subscription
|
|
665
|
+
const message: MCPJsonRpcMessage = {
|
|
666
|
+
jsonrpc: '2.0',
|
|
667
|
+
id,
|
|
668
|
+
method: 'subscriptions/listen',
|
|
669
|
+
params: envelope.params,
|
|
670
|
+
}
|
|
671
|
+
try {
|
|
672
|
+
const options = {
|
|
673
|
+
signal: controller.signal,
|
|
674
|
+
...this.eraHeaderOptions(envelope.headers),
|
|
675
|
+
}
|
|
676
|
+
const transport = this.transport
|
|
677
|
+
const streaming = transport instanceof StreamableHttpTransport
|
|
678
|
+
const sending =
|
|
679
|
+
transport instanceof StreamableHttpTransport
|
|
680
|
+
? transport.sendSubscription(message, options, (frame) => {
|
|
681
|
+
if (this.modernSubscription !== subscription) return
|
|
682
|
+
// This callback belongs to the listen POST alone, so its first
|
|
683
|
+
// JSON-RPC frame must be this request's acknowledgment.
|
|
684
|
+
if (!subscription.acknowledged) {
|
|
685
|
+
const meta = frame.params?._meta
|
|
686
|
+
const frameId =
|
|
687
|
+
meta && typeof meta === 'object' && !Array.isArray(meta)
|
|
688
|
+
? (meta as Record<string, unknown>)[SUBSCRIPTION_ID_META_KEY]
|
|
689
|
+
: undefined
|
|
690
|
+
if (frame.method !== 'notifications/subscriptions/acknowledged' || frameId !== id) {
|
|
691
|
+
// A final JSON-RPC result is a valid graceful or error close.
|
|
692
|
+
if (frame.id === id) this.handleMessage(frame)
|
|
693
|
+
else
|
|
694
|
+
this.finishModernSubscription(
|
|
695
|
+
subscription,
|
|
696
|
+
'first stream message was not its acknowledgment',
|
|
697
|
+
true,
|
|
698
|
+
)
|
|
699
|
+
return
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
this.handleMessage(frame)
|
|
703
|
+
})
|
|
704
|
+
: transport.send(message, options)
|
|
705
|
+
void sending.then(
|
|
706
|
+
() => {
|
|
707
|
+
// stdio's send only writes the request. Its eventual result
|
|
708
|
+
// arrives through handleMessage, whereas HTTP's send owns the
|
|
709
|
+
// response stream and settling means it closed.
|
|
710
|
+
if (streaming) this.finishModernSubscription(subscription, 'stream ended', false)
|
|
711
|
+
},
|
|
712
|
+
(err: unknown) => {
|
|
713
|
+
if (!controller.signal.aborted) {
|
|
714
|
+
this.failModernSubscription(subscription, err)
|
|
715
|
+
}
|
|
716
|
+
},
|
|
717
|
+
)
|
|
718
|
+
} catch (err) {
|
|
719
|
+
this.failModernSubscription(subscription, err)
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
private failModernSubscription(subscription: ModernSubscription, error: unknown): void {
|
|
724
|
+
if (this.modernSubscription !== subscription) return
|
|
725
|
+
const retry = !isPermanentSubscriptionFailure(error, subscription.id)
|
|
726
|
+
if (!retry) {
|
|
727
|
+
this.log.warn('Modern MCP subscription rejected; live updates stopped until reconnection', {
|
|
728
|
+
'namzu.connector.server': this.config.serverName,
|
|
729
|
+
'namzu.connector.reason': toErrorMessage(error),
|
|
730
|
+
})
|
|
731
|
+
}
|
|
732
|
+
this.finishModernSubscription(subscription, toErrorMessage(error), true, retry)
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
/** Stop one subscription, and retry with a bounded delay while connected. */
|
|
736
|
+
private finishModernSubscription(
|
|
737
|
+
subscription: ModernSubscription,
|
|
738
|
+
reason: string,
|
|
739
|
+
cancelPeer: boolean,
|
|
740
|
+
retry = true,
|
|
741
|
+
): void {
|
|
742
|
+
if (this.modernSubscription !== subscription) return
|
|
743
|
+
this.modernSubscription = undefined
|
|
744
|
+
clearTimeout(subscription.ackTimer)
|
|
745
|
+
subscription.controller.abort(new Error(`MCP subscription ${reason}`))
|
|
746
|
+
if (cancelPeer && !(this.transport instanceof StreamableHttpTransport) && this.isConnected()) {
|
|
747
|
+
this.sendCancellation(subscription.id, `Subscription ${reason}`)
|
|
748
|
+
}
|
|
749
|
+
if (!retry || this.status !== 'connected' || this.era?.kind !== 'modern') return
|
|
750
|
+
this.subscriptionFailures++
|
|
751
|
+
const delay = Math.min(
|
|
752
|
+
1_000 * 2 ** Math.min(this.subscriptionFailures - 1, 5),
|
|
753
|
+
SUBSCRIPTION_RETRY_MAX_MS,
|
|
754
|
+
)
|
|
755
|
+
this.log.warn('Modern MCP subscription ended; retrying', {
|
|
756
|
+
'namzu.connector.server': this.config.serverName,
|
|
757
|
+
'namzu.connector.reason': reason,
|
|
758
|
+
'namzu.connector.retry_ms': delay,
|
|
759
|
+
})
|
|
760
|
+
this.subscriptionRestartTimer = setTimeout(() => {
|
|
761
|
+
this.subscriptionRestartTimer = undefined
|
|
762
|
+
this.startModernSubscription()
|
|
763
|
+
}, delay)
|
|
764
|
+
this.subscriptionRestartTimer.unref?.()
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
private stopModernSubscription(cancelPeer: boolean): void {
|
|
768
|
+
if (this.subscriptionRestartTimer) clearTimeout(this.subscriptionRestartTimer)
|
|
769
|
+
this.subscriptionRestartTimer = undefined
|
|
770
|
+
const subscription = this.modernSubscription
|
|
771
|
+
this.modernSubscription = undefined
|
|
772
|
+
this.subscriptionFailures = 0
|
|
773
|
+
if (!subscription) return
|
|
774
|
+
clearTimeout(subscription.ackTimer)
|
|
775
|
+
subscription.controller.abort(new Error('MCP connection closed'))
|
|
776
|
+
if (cancelPeer && !(this.transport instanceof StreamableHttpTransport) && this.isConnected()) {
|
|
777
|
+
this.sendCancellation(subscription.id, 'Subscription closed')
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
|
|
524
781
|
async disconnect(): Promise<void> {
|
|
525
782
|
const reason = new Error('MCPClient disconnecting')
|
|
783
|
+
this.stopModernSubscription(true)
|
|
526
784
|
this.abortCancellations(reason)
|
|
527
785
|
const alreadyDisconnected = this.status === 'disconnected'
|
|
528
786
|
|
|
@@ -558,6 +816,7 @@ export class MCPClient {
|
|
|
558
816
|
status: this.status,
|
|
559
817
|
serverInfo: this.serverInfo,
|
|
560
818
|
serverCapabilities: this.serverCapabilities,
|
|
819
|
+
serverInstructions: this.serverInstructions,
|
|
561
820
|
connectedAt: this.connectedAt,
|
|
562
821
|
error: this.error,
|
|
563
822
|
}
|
|
@@ -837,8 +1096,33 @@ export class MCPClient {
|
|
|
837
1096
|
}
|
|
838
1097
|
}
|
|
839
1098
|
|
|
840
|
-
|
|
1099
|
+
/**
|
|
1100
|
+
* Returns an unsubscribe, mirroring {@link onLifecycle} below — a listener
|
|
1101
|
+
* that cannot be removed keeps whatever it closes over (a discovery
|
|
1102
|
+
* object, a logger, a caller's own state) referenced by this client for
|
|
1103
|
+
* as long as the client lives, even after the listener's own owner is
|
|
1104
|
+
* done with it.
|
|
1105
|
+
*/
|
|
1106
|
+
onNotification(handler: (method: string, params?: Record<string, unknown>) => void): () => void {
|
|
841
1107
|
this.notificationHandlers.push(handler)
|
|
1108
|
+
// A list may have changed between the first fetch and the subscription
|
|
1109
|
+
// acknowledgment. Reconcile when a listener joins an already-acknowledged
|
|
1110
|
+
// stream, as well as when a stream is acknowledged with listeners present.
|
|
1111
|
+
const subscription = this.modernSubscription
|
|
1112
|
+
if (subscription?.acknowledged) {
|
|
1113
|
+
queueMicrotask(() => {
|
|
1114
|
+
if (
|
|
1115
|
+
this.modernSubscription === subscription &&
|
|
1116
|
+
this.notificationHandlers.includes(handler)
|
|
1117
|
+
) {
|
|
1118
|
+
this.reconcileSubscription(subscription, handler)
|
|
1119
|
+
}
|
|
1120
|
+
})
|
|
1121
|
+
}
|
|
1122
|
+
return () => {
|
|
1123
|
+
const index = this.notificationHandlers.indexOf(handler)
|
|
1124
|
+
if (index >= 0) this.notificationHandlers.splice(index, 1)
|
|
1125
|
+
}
|
|
842
1126
|
}
|
|
843
1127
|
|
|
844
1128
|
/**
|
|
@@ -851,9 +1135,7 @@ export class MCPClient {
|
|
|
851
1135
|
* this adds no state, it just says out loud what the client already
|
|
852
1136
|
* knew.
|
|
853
1137
|
*
|
|
854
|
-
* Returns an unsubscribe
|
|
855
|
-
* bug this avoids repeating: a listener that cannot be removed keeps a
|
|
856
|
-
* disposed host object alive for as long as the client lives.
|
|
1138
|
+
* Returns an unsubscribe, the same shape `onNotification` above returns.
|
|
857
1139
|
*/
|
|
858
1140
|
onLifecycle(listener: MCPEventListener): () => void {
|
|
859
1141
|
this.lifecycleListeners.push(listener)
|
|
@@ -914,10 +1196,21 @@ export class MCPClient {
|
|
|
914
1196
|
// Refuse before allocating an id or asking the transport to do work.
|
|
915
1197
|
options?.signal?.throwIfAborted()
|
|
916
1198
|
const id = this.nextRequestId++
|
|
1199
|
+
const progressToken = method === 'tools/call' && options?.onProgress ? randomUUID() : undefined
|
|
1200
|
+
const requestParams =
|
|
1201
|
+
progressToken === undefined
|
|
1202
|
+
? params
|
|
1203
|
+
: {
|
|
1204
|
+
...params,
|
|
1205
|
+
_meta: {
|
|
1206
|
+
...(params._meta as Record<string, unknown> | undefined),
|
|
1207
|
+
progressToken,
|
|
1208
|
+
},
|
|
1209
|
+
}
|
|
917
1210
|
const envelope = buildEnvelope({
|
|
918
1211
|
era: this.era,
|
|
919
1212
|
method,
|
|
920
|
-
params,
|
|
1213
|
+
params: requestParams,
|
|
921
1214
|
clientInfo: this.config.clientInfo ?? NAMZU_CLIENT_INFO,
|
|
922
1215
|
capabilities: this.config.capabilities ?? {},
|
|
923
1216
|
...this.paramHeaderBindings(method, params),
|
|
@@ -951,6 +1244,7 @@ export class MCPClient {
|
|
|
951
1244
|
clearTimeout(timer)
|
|
952
1245
|
options?.signal?.removeEventListener('abort', onCallerAbort)
|
|
953
1246
|
if (this.pendingRequests.get(id) === entry) this.pendingRequests.delete(id)
|
|
1247
|
+
if (progressToken !== undefined) this.progressRequests.delete(progressToken)
|
|
954
1248
|
}
|
|
955
1249
|
const settle = (terminal: Terminal, value: unknown): boolean => {
|
|
956
1250
|
if (settled) return false
|
|
@@ -998,6 +1292,9 @@ export class MCPClient {
|
|
|
998
1292
|
}
|
|
999
1293
|
|
|
1000
1294
|
this.pendingRequests.set(id, entry)
|
|
1295
|
+
if (progressToken !== undefined && options?.onProgress) {
|
|
1296
|
+
this.progressRequests.set(progressToken, { onProgress: options.onProgress })
|
|
1297
|
+
}
|
|
1001
1298
|
const timer = setTimeout(() => {
|
|
1002
1299
|
const error = new Error(
|
|
1003
1300
|
`MCP request "${method}" to "${this.config.serverName}" timed out after ${this.requestTimeoutMs}ms`,
|
|
@@ -1238,6 +1535,10 @@ export class MCPClient {
|
|
|
1238
1535
|
}
|
|
1239
1536
|
|
|
1240
1537
|
private handleMessage(message: MCPJsonRpcMessage): void {
|
|
1538
|
+
if (message.method === 'notifications/progress' && message.id === undefined) {
|
|
1539
|
+
this.handleProgressNotification(message.params)
|
|
1540
|
+
}
|
|
1541
|
+
if (this.handleModernSubscriptionMessage(message)) return
|
|
1241
1542
|
if (message.id !== undefined) {
|
|
1242
1543
|
const pending = this.pendingRequests.get(message.id)
|
|
1243
1544
|
if (pending) {
|
|
@@ -1285,6 +1586,124 @@ export class MCPClient {
|
|
|
1285
1586
|
}
|
|
1286
1587
|
}
|
|
1287
1588
|
|
|
1589
|
+
private handleProgressNotification(params: Record<string, unknown> | undefined): void {
|
|
1590
|
+
const token = params?.progressToken
|
|
1591
|
+
if (typeof token !== 'string') return
|
|
1592
|
+
const pending = this.progressRequests.get(token)
|
|
1593
|
+
if (!pending) return
|
|
1594
|
+
const progress = params?.progress
|
|
1595
|
+
if (typeof progress !== 'number' || !Number.isFinite(progress) || progress < 0) return
|
|
1596
|
+
if (pending.lastProgress !== undefined && progress <= pending.lastProgress) return
|
|
1597
|
+
pending.lastProgress = progress
|
|
1598
|
+
const total = params?.total
|
|
1599
|
+
const message = progressMessage(params?.message)
|
|
1600
|
+
const update: MCPProgressUpdate = {
|
|
1601
|
+
progress,
|
|
1602
|
+
...(typeof total === 'number' && Number.isFinite(total) && total > 0 ? { total } : {}),
|
|
1603
|
+
...(message === undefined ? {} : { message }),
|
|
1604
|
+
}
|
|
1605
|
+
try {
|
|
1606
|
+
pending.onProgress(update)
|
|
1607
|
+
} catch (error) {
|
|
1608
|
+
this.log.warn('MCP progress listener threw', {
|
|
1609
|
+
'exception.message': toErrorMessage(error),
|
|
1610
|
+
})
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
|
|
1614
|
+
/**
|
|
1615
|
+
* The modern subscription stream is authority-scoped by its request ID.
|
|
1616
|
+
* A bare or wrong-ID list_changed notification must not refresh a live
|
|
1617
|
+
* toolset, and no event may precede its acknowledgment.
|
|
1618
|
+
*/
|
|
1619
|
+
private handleModernSubscriptionMessage(message: MCPJsonRpcMessage): boolean {
|
|
1620
|
+
if (this.era?.kind !== 'modern') return false
|
|
1621
|
+
const subscription = this.modernSubscription
|
|
1622
|
+
if (subscription && message.id === subscription.id) {
|
|
1623
|
+
if (message.error?.code === JSON_RPC_METHOD_NOT_FOUND) {
|
|
1624
|
+
this.log.warn('Modern MCP subscription rejected; live updates stopped until reconnection', {
|
|
1625
|
+
'namzu.connector.server': this.config.serverName,
|
|
1626
|
+
'namzu.connector.reason': `MCP error ${message.error.code}: ${message.error.message}`,
|
|
1627
|
+
})
|
|
1628
|
+
}
|
|
1629
|
+
this.finishModernSubscription(
|
|
1630
|
+
subscription,
|
|
1631
|
+
message.error
|
|
1632
|
+
? `server rejected subscription: ${message.error.message}`
|
|
1633
|
+
: 'server closed stream',
|
|
1634
|
+
false,
|
|
1635
|
+
message.error?.code !== JSON_RPC_METHOD_NOT_FOUND && message.error !== undefined,
|
|
1636
|
+
)
|
|
1637
|
+
return true
|
|
1638
|
+
}
|
|
1639
|
+
const method = message.method
|
|
1640
|
+
if (!method) return false
|
|
1641
|
+
const isAck = method === 'notifications/subscriptions/acknowledged'
|
|
1642
|
+
const kind = Object.hasOwn(SUBSCRIPTION_NOTIFICATIONS, method)
|
|
1643
|
+
? SUBSCRIPTION_NOTIFICATIONS[method as keyof typeof SUBSCRIPTION_NOTIFICATIONS]
|
|
1644
|
+
: undefined
|
|
1645
|
+
const isSubscribedEvent =
|
|
1646
|
+
isAck || kind !== undefined || method === 'notifications/resources/updated'
|
|
1647
|
+
if (!isSubscribedEvent) return false
|
|
1648
|
+
const meta = message.params?._meta
|
|
1649
|
+
const id =
|
|
1650
|
+
meta && typeof meta === 'object' && !Array.isArray(meta)
|
|
1651
|
+
? (meta as Record<string, unknown>)[SUBSCRIPTION_ID_META_KEY]
|
|
1652
|
+
: undefined
|
|
1653
|
+
if (!subscription || id !== subscription.id || message.id !== undefined) {
|
|
1654
|
+
this.log.warn('Ignoring MCP subscription notification without the active subscription ID', {
|
|
1655
|
+
'namzu.connector.server': this.config.serverName,
|
|
1656
|
+
'namzu.connector.method': method,
|
|
1657
|
+
})
|
|
1658
|
+
return true
|
|
1659
|
+
}
|
|
1660
|
+
if (isAck) {
|
|
1661
|
+
if (subscription.acknowledged) {
|
|
1662
|
+
this.finishModernSubscription(subscription, 'duplicate acknowledgment', true)
|
|
1663
|
+
return true
|
|
1664
|
+
}
|
|
1665
|
+
const acknowledged = acknowledgedFilter(message.params?.notifications, subscription.requested)
|
|
1666
|
+
if (!acknowledged) {
|
|
1667
|
+
this.finishModernSubscription(subscription, 'invalid acknowledgment filter', true)
|
|
1668
|
+
return true
|
|
1669
|
+
}
|
|
1670
|
+
subscription.acknowledged = acknowledged
|
|
1671
|
+
clearTimeout(subscription.ackTimer)
|
|
1672
|
+
for (const handler of [...this.notificationHandlers]) {
|
|
1673
|
+
this.reconcileSubscription(subscription, handler)
|
|
1674
|
+
}
|
|
1675
|
+
return true
|
|
1676
|
+
}
|
|
1677
|
+
if (!subscription.acknowledged) {
|
|
1678
|
+
this.finishModernSubscription(
|
|
1679
|
+
subscription,
|
|
1680
|
+
'notification arrived before acknowledgment',
|
|
1681
|
+
true,
|
|
1682
|
+
)
|
|
1683
|
+
return true
|
|
1684
|
+
}
|
|
1685
|
+
if (!kind || subscription.acknowledged[kind] !== true) {
|
|
1686
|
+
this.log.warn('Ignoring unrequested MCP subscription notification', {
|
|
1687
|
+
'namzu.connector.server': this.config.serverName,
|
|
1688
|
+
'namzu.connector.method': method,
|
|
1689
|
+
})
|
|
1690
|
+
return true
|
|
1691
|
+
}
|
|
1692
|
+
for (const handler of [...this.notificationHandlers]) handler(method, message.params)
|
|
1693
|
+
return true
|
|
1694
|
+
}
|
|
1695
|
+
|
|
1696
|
+
/** Re-list once when a subscription becomes live; it may have missed a change while opening. */
|
|
1697
|
+
private reconcileSubscription(
|
|
1698
|
+
subscription: ModernSubscription,
|
|
1699
|
+
handler: (method: string, params?: Record<string, unknown>) => void,
|
|
1700
|
+
): void {
|
|
1701
|
+
if (this.modernSubscription !== subscription) return
|
|
1702
|
+
for (const [method, kind] of Object.entries(SUBSCRIPTION_NOTIFICATIONS)) {
|
|
1703
|
+
if (subscription.acknowledged?.[kind as keyof ListChangeFilter]) handler(method)
|
|
1704
|
+
}
|
|
1705
|
+
}
|
|
1706
|
+
|
|
1288
1707
|
private requireConnected(): void {
|
|
1289
1708
|
if (this.status !== 'connected') {
|
|
1290
1709
|
throw new Error(
|
|
@@ -2,6 +2,8 @@ import { NAMZU } from '../../constants/telemetry/index.js'
|
|
|
2
2
|
import type {
|
|
3
3
|
MCPDiscoveredTool,
|
|
4
4
|
MCPPromptDefinition,
|
|
5
|
+
MCPRequestOptions,
|
|
6
|
+
MCPResource,
|
|
5
7
|
MCPToolDefinition,
|
|
6
8
|
} from '../../types/connector/index.js'
|
|
7
9
|
import type { ToolDefinition } from '../../types/tool/index.js'
|
|
@@ -38,6 +40,13 @@ export interface MCPToolDiscoveryOptions {
|
|
|
38
40
|
* knows which it is looking at.
|
|
39
41
|
*/
|
|
40
42
|
readonly onDrift?: (event: { serverName: string; clientId: string; drift: MCPToolDrift }) => void
|
|
43
|
+
/** The current policy refusals after each listing, including an empty list when they clear. */
|
|
44
|
+
readonly onRefused?: (event: {
|
|
45
|
+
serverName: string
|
|
46
|
+
clientId: string
|
|
47
|
+
kind: 'tools' | 'prompts' | 'resources'
|
|
48
|
+
refused: readonly { name: string; reason: 'not_allowed' | 'denied' }[]
|
|
49
|
+
}) => void
|
|
41
50
|
readonly logger?: Logger
|
|
42
51
|
}
|
|
43
52
|
|
|
@@ -120,6 +129,12 @@ export class MCPToolDiscovery {
|
|
|
120
129
|
// having agreed to it.
|
|
121
130
|
const policy = this.options.policies?.[state.serverName] ?? this.options.policies?.['*']
|
|
122
131
|
const { admitted, refused } = applyToolPolicy(advertised, policy)
|
|
132
|
+
this.options.onRefused?.({
|
|
133
|
+
serverName: state.serverName,
|
|
134
|
+
clientId: client.id,
|
|
135
|
+
kind: 'tools',
|
|
136
|
+
refused,
|
|
137
|
+
})
|
|
123
138
|
|
|
124
139
|
if (refused.length > 0) {
|
|
125
140
|
this.log.warn('MCP tools refused by policy', {
|
|
@@ -168,6 +183,12 @@ export class MCPToolDiscovery {
|
|
|
168
183
|
|
|
169
184
|
const policy = this.options.policies?.[state.serverName] ?? this.options.policies?.['*']
|
|
170
185
|
const { admitted, refused } = applyNamePolicy(advertised, policy)
|
|
186
|
+
this.options.onRefused?.({
|
|
187
|
+
serverName: state.serverName,
|
|
188
|
+
clientId: client.id,
|
|
189
|
+
kind: 'prompts',
|
|
190
|
+
refused,
|
|
191
|
+
})
|
|
171
192
|
|
|
172
193
|
if (refused.length > 0) {
|
|
173
194
|
this.log.warn('MCP prompts refused by policy', {
|
|
@@ -180,6 +201,45 @@ export class MCPToolDiscovery {
|
|
|
180
201
|
return admitted
|
|
181
202
|
}
|
|
182
203
|
|
|
204
|
+
/**
|
|
205
|
+
* The resources a server publishes, through the same admission gate its
|
|
206
|
+
* tools and prompts go through.
|
|
207
|
+
*
|
|
208
|
+
* A server publishing a resource is the same trust question as one
|
|
209
|
+
* publishing a tool or a prompt: the remote side must not decide what
|
|
210
|
+
* enters the agent's registry. Policy is matched on the resource's own
|
|
211
|
+
* `name`, as the server reports it — before this call existed,
|
|
212
|
+
* `mcpToolset` read `client.listResources()` directly and admitted every
|
|
213
|
+
* URI the server returned, so `deny`/`allow` governed tools and prompts
|
|
214
|
+
* but not the one other surface a server can contribute by name.
|
|
215
|
+
*/
|
|
216
|
+
async discoverResourcesFrom(
|
|
217
|
+
client: MCPClient,
|
|
218
|
+
options?: MCPRequestOptions,
|
|
219
|
+
): Promise<MCPResource[]> {
|
|
220
|
+
const state = client.getState()
|
|
221
|
+
const advertised = await client.listResources(options)
|
|
222
|
+
|
|
223
|
+
const policy = this.options.policies?.[state.serverName] ?? this.options.policies?.['*']
|
|
224
|
+
const { admitted, refused } = applyNamePolicy(advertised, policy)
|
|
225
|
+
this.options.onRefused?.({
|
|
226
|
+
serverName: state.serverName,
|
|
227
|
+
clientId: client.id,
|
|
228
|
+
kind: 'resources',
|
|
229
|
+
refused,
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
if (refused.length > 0) {
|
|
233
|
+
this.log.warn('MCP resources refused by policy', {
|
|
234
|
+
[NAMZU.SERVER_NAME]: state.serverName,
|
|
235
|
+
'namzu.mcp.client_id': client.id,
|
|
236
|
+
'namzu.connector.refused': refused.map((r) => `${r.name} (${r.reason})`),
|
|
237
|
+
})
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return admitted
|
|
241
|
+
}
|
|
242
|
+
|
|
183
243
|
async toToolDefinitions(): Promise<ToolDefinition[]> {
|
|
184
244
|
const discovered = await this.discoverAll()
|
|
185
245
|
return discovered.map((d) => {
|
package/src/connector/mcp/era.ts
CHANGED
|
@@ -326,6 +326,13 @@ function classifyAnswer(
|
|
|
326
326
|
}
|
|
327
327
|
|
|
328
328
|
if (error instanceof MCPHttpStatusError) {
|
|
329
|
+
// Authentication and authorization failures say nothing about the
|
|
330
|
+
// peer's protocol era. Retrying them as a legacy initialize request
|
|
331
|
+
// only hides the actual refusal and sends another request with the
|
|
332
|
+
// same unusable credentials.
|
|
333
|
+
if (error.status === 401 || error.status === 403) {
|
|
334
|
+
return { kind: 'refuse', error }
|
|
335
|
+
}
|
|
329
336
|
const verdict = classifyModernHttpFailure(error.status, error.bodyText)
|
|
330
337
|
if (verdict.kind === 'legacy') return { kind: 'legacy' }
|
|
331
338
|
if (isUnsupportedProtocolVersionError(verdict.error)) {
|