@animalabs/agent-framework 0.22.1 → 0.22.3
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/README.md +4 -2
- package/dist/src/agent.d.ts +266 -28
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +539 -104
- package/dist/src/agent.js.map +1 -1
- package/dist/src/api/mcp-server-core.d.ts +41 -0
- package/dist/src/api/mcp-server-core.d.ts.map +1 -0
- package/dist/src/api/mcp-server-core.js +593 -0
- package/dist/src/api/mcp-server-core.js.map +1 -0
- package/dist/src/api/mcp-server.d.ts +2 -36
- package/dist/src/api/mcp-server.d.ts.map +1 -1
- package/dist/src/api/mcp-server.js +15 -595
- package/dist/src/api/mcp-server.js.map +1 -1
- package/dist/src/api/server.d.ts +9 -1
- package/dist/src/api/server.d.ts.map +1 -1
- package/dist/src/api/server.js +55 -27
- package/dist/src/api/server.js.map +1 -1
- package/dist/src/api/types.d.ts +10 -2
- package/dist/src/api/types.d.ts.map +1 -1
- package/dist/src/branch-names.d.ts +14 -0
- package/dist/src/branch-names.d.ts.map +1 -0
- package/dist/src/branch-names.js +22 -0
- package/dist/src/branch-names.js.map +1 -0
- package/dist/src/closest-names.d.ts +28 -0
- package/dist/src/closest-names.d.ts.map +1 -0
- package/dist/src/closest-names.js +98 -0
- package/dist/src/closest-names.js.map +1 -0
- package/dist/src/code-execution/py-runner.d.ts +16 -5
- package/dist/src/code-execution/py-runner.d.ts.map +1 -1
- package/dist/src/code-execution/py-runner.js +186 -74
- package/dist/src/code-execution/py-runner.js.map +1 -1
- package/dist/src/code-execution/runtime-py.d.ts.map +1 -1
- package/dist/src/code-execution/runtime-py.js +49 -3
- package/dist/src/code-execution/runtime-py.js.map +1 -1
- package/dist/src/code-execution/tool-definition.d.ts +12 -1
- package/dist/src/code-execution/tool-definition.d.ts.map +1 -1
- package/dist/src/code-execution/tool-definition.js +21 -3
- package/dist/src/code-execution/tool-definition.js.map +1 -1
- package/dist/src/config-checks.d.ts +28 -0
- package/dist/src/config-checks.d.ts.map +1 -0
- package/dist/src/config-checks.js +52 -0
- package/dist/src/config-checks.js.map +1 -0
- package/dist/src/deadline-timer.d.ts +21 -0
- package/dist/src/deadline-timer.d.ts.map +1 -0
- package/dist/src/deadline-timer.js +43 -0
- package/dist/src/deadline-timer.js.map +1 -0
- package/dist/src/error-message.d.ts +30 -0
- package/dist/src/error-message.d.ts.map +1 -0
- package/dist/src/error-message.js +50 -0
- package/dist/src/error-message.js.map +1 -0
- package/dist/src/framework.d.ts +1212 -192
- package/dist/src/framework.d.ts.map +1 -1
- package/dist/src/framework.js +6686 -1835
- package/dist/src/framework.js.map +1 -1
- package/dist/src/gate/event-gate.d.ts +8 -0
- package/dist/src/gate/event-gate.d.ts.map +1 -1
- package/dist/src/gate/event-gate.js +27 -3
- package/dist/src/gate/event-gate.js.map +1 -1
- package/dist/src/gate/gate-script.d.ts.map +1 -1
- package/dist/src/gate/gate-script.js.map +1 -1
- package/dist/src/index.d.ts +5 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +5 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcpl/capability-grant.d.ts.map +1 -1
- package/dist/src/mcpl/channel-registry.d.ts +170 -13
- package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
- package/dist/src/mcpl/channel-registry.js +499 -258
- package/dist/src/mcpl/channel-registry.js.map +1 -1
- package/dist/src/mcpl/checkpoint-manager.d.ts +21 -1
- package/dist/src/mcpl/checkpoint-manager.d.ts.map +1 -1
- package/dist/src/mcpl/checkpoint-manager.js +91 -30
- package/dist/src/mcpl/checkpoint-manager.js.map +1 -1
- package/dist/src/mcpl/conversation-router.d.ts +19 -3
- package/dist/src/mcpl/conversation-router.d.ts.map +1 -1
- package/dist/src/mcpl/conversation-router.js +23 -8
- package/dist/src/mcpl/conversation-router.js.map +1 -1
- package/dist/src/mcpl/convert-block.d.ts +20 -0
- package/dist/src/mcpl/convert-block.d.ts.map +1 -0
- package/dist/src/mcpl/convert-block.js +89 -0
- package/dist/src/mcpl/convert-block.js.map +1 -0
- package/dist/src/mcpl/errors.d.ts +13 -0
- package/dist/src/mcpl/errors.d.ts.map +1 -1
- package/dist/src/mcpl/errors.js +28 -0
- package/dist/src/mcpl/errors.js.map +1 -1
- package/dist/src/mcpl/feature-set-manager.d.ts.map +1 -1
- package/dist/src/mcpl/feature-set-manager.js +4 -3
- package/dist/src/mcpl/feature-set-manager.js.map +1 -1
- package/dist/src/mcpl/hook-orchestrator.d.ts +23 -0
- package/dist/src/mcpl/hook-orchestrator.d.ts.map +1 -1
- package/dist/src/mcpl/hook-orchestrator.js +83 -72
- package/dist/src/mcpl/hook-orchestrator.js.map +1 -1
- package/dist/src/mcpl/inbound-source.d.ts +114 -0
- package/dist/src/mcpl/inbound-source.d.ts.map +1 -0
- package/dist/src/mcpl/inbound-source.js +83 -0
- package/dist/src/mcpl/inbound-source.js.map +1 -0
- package/dist/src/mcpl/index.d.ts +3 -1
- package/dist/src/mcpl/index.d.ts.map +1 -1
- package/dist/src/mcpl/index.js +3 -1
- package/dist/src/mcpl/index.js.map +1 -1
- package/dist/src/mcpl/inference-router.d.ts +15 -11
- package/dist/src/mcpl/inference-router.d.ts.map +1 -1
- package/dist/src/mcpl/inference-router.js +153 -84
- package/dist/src/mcpl/inference-router.js.map +1 -1
- package/dist/src/mcpl/log-value.d.ts +54 -0
- package/dist/src/mcpl/log-value.d.ts.map +1 -0
- package/dist/src/mcpl/log-value.js +109 -0
- package/dist/src/mcpl/log-value.js.map +1 -0
- package/dist/src/mcpl/prose-stream-router.d.ts +6 -6
- package/dist/src/mcpl/prose-stream-router.d.ts.map +1 -1
- package/dist/src/mcpl/prose-stream-router.js +4 -4
- package/dist/src/mcpl/prose-stream-router.js.map +1 -1
- package/dist/src/mcpl/push-coalescer.d.ts +64 -7
- package/dist/src/mcpl/push-coalescer.d.ts.map +1 -1
- package/dist/src/mcpl/push-coalescer.js +121 -24
- package/dist/src/mcpl/push-coalescer.js.map +1 -1
- package/dist/src/mcpl/push-handler.d.ts +38 -8
- package/dist/src/mcpl/push-handler.d.ts.map +1 -1
- package/dist/src/mcpl/push-handler.js +77 -78
- package/dist/src/mcpl/push-handler.js.map +1 -1
- package/dist/src/mcpl/reference-fetcher.d.ts +14 -2
- package/dist/src/mcpl/reference-fetcher.d.ts.map +1 -1
- package/dist/src/mcpl/reference-fetcher.js +72 -30
- package/dist/src/mcpl/reference-fetcher.js.map +1 -1
- package/dist/src/mcpl/references.d.ts +49 -14
- package/dist/src/mcpl/references.d.ts.map +1 -1
- package/dist/src/mcpl/references.js +74 -21
- package/dist/src/mcpl/references.js.map +1 -1
- package/dist/src/mcpl/refusal-lines.d.ts +37 -0
- package/dist/src/mcpl/refusal-lines.d.ts.map +1 -0
- package/dist/src/mcpl/refusal-lines.js +61 -0
- package/dist/src/mcpl/refusal-lines.js.map +1 -0
- package/dist/src/mcpl/scope-manager.d.ts.map +1 -1
- package/dist/src/mcpl/server-connection.d.ts +107 -12
- package/dist/src/mcpl/server-connection.d.ts.map +1 -1
- package/dist/src/mcpl/server-connection.js +470 -139
- package/dist/src/mcpl/server-connection.js.map +1 -1
- package/dist/src/mcpl/server-registry.d.ts +10 -1
- package/dist/src/mcpl/server-registry.d.ts.map +1 -1
- package/dist/src/mcpl/server-registry.js +14 -3
- package/dist/src/mcpl/server-registry.js.map +1 -1
- package/dist/src/mcpl/skip-reply-wake.d.ts +36 -0
- package/dist/src/mcpl/skip-reply-wake.d.ts.map +1 -0
- package/dist/src/mcpl/skip-reply-wake.js +55 -0
- package/dist/src/mcpl/skip-reply-wake.js.map +1 -0
- package/dist/src/mcpl/tool-classes.d.ts +1 -1
- package/dist/src/mcpl/tool-classes.d.ts.map +1 -1
- package/dist/src/mcpl/tool-classes.js +3 -2
- package/dist/src/mcpl/tool-classes.js.map +1 -1
- package/dist/src/mcpl/tool-lifecycle.d.ts.map +1 -1
- package/dist/src/mcpl/tool-lifecycle.js.map +1 -1
- package/dist/src/mcpl/transport.d.ts +74 -7
- package/dist/src/mcpl/transport.d.ts.map +1 -1
- package/dist/src/mcpl/transport.js +209 -22
- package/dist/src/mcpl/transport.js.map +1 -1
- package/dist/src/mcpl/types.d.ts +43 -28
- package/dist/src/mcpl/types.d.ts.map +1 -1
- package/dist/src/mcpl/types.js.map +1 -1
- package/dist/src/mcpl/visible-content.d.ts +15 -0
- package/dist/src/mcpl/visible-content.d.ts.map +1 -1
- package/dist/src/mcpl/visible-content.js +25 -0
- package/dist/src/mcpl/visible-content.js.map +1 -1
- package/dist/src/module-registry.d.ts +19 -1
- package/dist/src/module-registry.d.ts.map +1 -1
- package/dist/src/module-registry.js +54 -25
- package/dist/src/module-registry.js.map +1 -1
- package/dist/src/modules/api/index.d.ts.map +1 -1
- package/dist/src/modules/api/index.js +1 -1
- package/dist/src/modules/api/index.js.map +1 -1
- package/dist/src/modules/discord/discord-js-client.d.ts +1 -0
- package/dist/src/modules/discord/discord-js-client.d.ts.map +1 -1
- package/dist/src/modules/discord/discord-js-client.js +25 -9
- package/dist/src/modules/discord/discord-js-client.js.map +1 -1
- package/dist/src/modules/discord/index.d.ts +29 -3
- package/dist/src/modules/discord/index.d.ts.map +1 -1
- package/dist/src/modules/discord/index.js +383 -145
- package/dist/src/modules/discord/index.js.map +1 -1
- package/dist/src/modules/discord/types.d.ts +14 -1
- package/dist/src/modules/discord/types.d.ts.map +1 -1
- package/dist/src/modules/health/index.d.ts.map +1 -1
- package/dist/src/modules/health/index.js +2 -1
- package/dist/src/modules/health/index.js.map +1 -1
- package/dist/src/modules/history/index.d.ts +3 -1
- package/dist/src/modules/history/index.d.ts.map +1 -1
- package/dist/src/modules/history/index.js +359 -127
- package/dist/src/modules/history/index.js.map +1 -1
- package/dist/src/modules/history/semantic.d.ts +28 -1
- package/dist/src/modules/history/semantic.d.ts.map +1 -1
- package/dist/src/modules/history/semantic.js +177 -32
- package/dist/src/modules/history/semantic.js.map +1 -1
- package/dist/src/modules/unknown-tool.d.ts +10 -0
- package/dist/src/modules/unknown-tool.d.ts.map +1 -0
- package/dist/src/modules/unknown-tool.js +17 -0
- package/dist/src/modules/unknown-tool.js.map +1 -0
- package/dist/src/modules/workspace/branch-intent.d.ts.map +1 -1
- package/dist/src/modules/workspace/branch-intent.js.map +1 -1
- package/dist/src/modules/workspace/disk-agreement.d.ts +54 -6
- package/dist/src/modules/workspace/disk-agreement.d.ts.map +1 -1
- package/dist/src/modules/workspace/disk-agreement.js +93 -27
- package/dist/src/modules/workspace/disk-agreement.js.map +1 -1
- package/dist/src/modules/workspace/effects.d.ts +64 -6
- package/dist/src/modules/workspace/effects.d.ts.map +1 -1
- package/dist/src/modules/workspace/effects.js +291 -44
- package/dist/src/modules/workspace/effects.js.map +1 -1
- package/dist/src/modules/workspace/index.d.ts +127 -27
- package/dist/src/modules/workspace/index.d.ts.map +1 -1
- package/dist/src/modules/workspace/index.js +821 -248
- package/dist/src/modules/workspace/index.js.map +1 -1
- package/dist/src/modules/workspace/observe.d.ts +117 -15
- package/dist/src/modules/workspace/observe.d.ts.map +1 -1
- package/dist/src/modules/workspace/observe.js +436 -51
- package/dist/src/modules/workspace/observe.js.map +1 -1
- package/dist/src/modules/workspace/reconcile.d.ts +75 -8
- package/dist/src/modules/workspace/reconcile.d.ts.map +1 -1
- package/dist/src/modules/workspace/reconcile.js +576 -68
- package/dist/src/modules/workspace/reconcile.js.map +1 -1
- package/dist/src/modules/workspace/types.d.ts +42 -3
- package/dist/src/modules/workspace/types.d.ts.map +1 -1
- package/dist/src/modules/workspace/types.js.map +1 -1
- package/dist/src/modules/workspace/watcher.d.ts +7 -2
- package/dist/src/modules/workspace/watcher.d.ts.map +1 -1
- package/dist/src/modules/workspace/watcher.js +28 -4
- package/dist/src/modules/workspace/watcher.js.map +1 -1
- package/dist/src/operator-log.d.ts.map +1 -1
- package/dist/src/operator-log.js.map +1 -1
- package/dist/src/prose-drafts.d.ts +240 -0
- package/dist/src/prose-drafts.d.ts.map +1 -0
- package/dist/src/prose-drafts.js +362 -0
- package/dist/src/prose-drafts.js.map +1 -0
- package/dist/src/prose-segments.d.ts +21 -2
- package/dist/src/prose-segments.d.ts.map +1 -1
- package/dist/src/prose-segments.js +46 -9
- package/dist/src/prose-segments.js.map +1 -1
- package/dist/src/provider-waits.d.ts.map +1 -1
- package/dist/src/provider-waits.js.map +1 -1
- package/dist/src/queue.d.ts.map +1 -1
- package/dist/src/record-journal.d.ts.map +1 -1
- package/dist/src/record-journal.js.map +1 -1
- package/dist/src/recovery/discord-awareness-outbox.d.ts.map +1 -1
- package/dist/src/recovery/discord-awareness-outbox.js.map +1 -1
- package/dist/src/recovery/offline-branch.d.ts +1 -0
- package/dist/src/recovery/offline-branch.d.ts.map +1 -1
- package/dist/src/recovery/offline-branch.js +32 -25
- package/dist/src/recovery/offline-branch.js.map +1 -1
- package/dist/src/recovery/recover-cli.js.map +1 -1
- package/dist/src/runtime/liveness-watchdog.d.ts.map +1 -1
- package/dist/src/runtime/liveness-watchdog.js.map +1 -1
- package/dist/src/safe-slice.d.ts +5 -1
- package/dist/src/safe-slice.d.ts.map +1 -1
- package/dist/src/safe-slice.js +9 -1
- package/dist/src/safe-slice.js.map +1 -1
- package/dist/src/shutdown.d.ts.map +1 -1
- package/dist/src/shutdown.js.map +1 -1
- package/dist/src/stored-removal.d.ts +73 -0
- package/dist/src/stored-removal.d.ts.map +1 -0
- package/dist/src/stored-removal.js +100 -0
- package/dist/src/stored-removal.js.map +1 -0
- package/dist/src/thinking-token-stamp.js.map +1 -1
- package/dist/src/tool-image-ledger.d.ts +87 -19
- package/dist/src/tool-image-ledger.d.ts.map +1 -1
- package/dist/src/tool-image-ledger.js +135 -32
- package/dist/src/tool-image-ledger.js.map +1 -1
- package/dist/src/tool-presentation.d.ts +9 -0
- package/dist/src/tool-presentation.d.ts.map +1 -1
- package/dist/src/tool-presentation.js +257 -60
- package/dist/src/tool-presentation.js.map +1 -1
- package/dist/src/tool-result-guard.d.ts.map +1 -1
- package/dist/src/tool-result-guard.js +7 -10
- package/dist/src/tool-result-guard.js.map +1 -1
- package/dist/src/tool-result-history.d.ts +32 -3
- package/dist/src/tool-result-history.d.ts.map +1 -1
- package/dist/src/tool-result-history.js +106 -19
- package/dist/src/tool-result-history.js.map +1 -1
- package/dist/src/tune-out/coordinator.d.ts +25 -1
- package/dist/src/tune-out/coordinator.d.ts.map +1 -1
- package/dist/src/tune-out/coordinator.js +260 -65
- package/dist/src/tune-out/coordinator.js.map +1 -1
- package/dist/src/tune-out/tools.d.ts +1 -1
- package/dist/src/tune-out/tools.d.ts.map +1 -1
- package/dist/src/types/agent.d.ts +59 -11
- package/dist/src/types/agent.d.ts.map +1 -1
- package/dist/src/types/events.d.ts +17 -0
- package/dist/src/types/events.d.ts.map +1 -1
- package/dist/src/types/framework.d.ts +31 -5
- package/dist/src/types/framework.d.ts.map +1 -1
- package/dist/src/types/inference-log.d.ts +1 -1
- package/dist/src/types/inference-log.d.ts.map +1 -1
- package/dist/src/types/module.d.ts +30 -7
- package/dist/src/types/module.d.ts.map +1 -1
- package/dist/src/types/trace.d.ts +151 -11
- package/dist/src/types/trace.d.ts.map +1 -1
- package/dist/src/usage/usage-tracker.d.ts +5 -0
- package/dist/src/usage/usage-tracker.d.ts.map +1 -1
- package/dist/src/usage/usage-tracker.js +35 -8
- package/dist/src/usage/usage-tracker.js.map +1 -1
- package/package.json +10 -9
- package/src/agent.ts +572 -105
- package/src/api/mcp-server-core.ts +681 -0
- package/src/api/mcp-server.ts +16 -685
- package/src/api/server.ts +55 -30
- package/src/api/types.ts +10 -2
- package/src/branch-names.ts +19 -0
- package/src/closest-names.ts +94 -0
- package/src/code-execution/py-runner.ts +200 -76
- package/src/code-execution/runtime-py.ts +49 -3
- package/src/code-execution/tool-definition.ts +28 -4
- package/src/config-checks.ts +48 -0
- package/src/deadline-timer.ts +44 -0
- package/src/error-message.ts +48 -0
- package/src/framework.ts +7158 -1936
- package/src/gate/event-gate.ts +28 -3
- package/src/index.ts +12 -3
- package/src/mcpl/channel-registry.ts +615 -289
- package/src/mcpl/checkpoint-manager.ts +104 -29
- package/src/mcpl/conversation-router.ts +28 -8
- package/src/mcpl/convert-block.ts +97 -0
- package/src/mcpl/errors.ts +28 -0
- package/src/mcpl/feature-set-manager.ts +4 -3
- package/src/mcpl/hook-orchestrator.ts +84 -77
- package/src/mcpl/inbound-source.ts +156 -0
- package/src/mcpl/index.ts +10 -1
- package/src/mcpl/inference-router.ts +174 -99
- package/src/mcpl/log-value.ts +116 -0
- package/src/mcpl/prose-stream-router.ts +6 -6
- package/src/mcpl/push-coalescer.ts +124 -24
- package/src/mcpl/push-handler.ts +86 -84
- package/src/mcpl/reference-fetcher.ts +71 -26
- package/src/mcpl/references.ts +81 -22
- package/src/mcpl/refusal-lines.ts +59 -0
- package/src/mcpl/server-connection.ts +496 -142
- package/src/mcpl/server-registry.ts +15 -4
- package/src/mcpl/skip-reply-wake.ts +73 -0
- package/src/mcpl/tool-classes.ts +3 -2
- package/src/mcpl/transport.ts +219 -26
- package/src/mcpl/types.ts +18 -3
- package/src/mcpl/visible-content.ts +27 -0
- package/src/module-registry.ts +58 -23
- package/src/modules/api/index.ts +1 -1
- package/src/modules/discord/discord-js-client.ts +26 -10
- package/src/modules/discord/index.ts +395 -160
- package/src/modules/discord/types.ts +15 -2
- package/src/modules/health/index.ts +2 -1
- package/src/modules/history/index.ts +410 -120
- package/src/modules/history/semantic.ts +189 -32
- package/src/modules/unknown-tool.ts +16 -0
- package/src/modules/workspace/disk-agreement.ts +125 -21
- package/src/modules/workspace/effects.ts +279 -35
- package/src/modules/workspace/index.ts +841 -261
- package/src/modules/workspace/observe.ts +456 -56
- package/src/modules/workspace/reconcile.ts +688 -76
- package/src/modules/workspace/types.ts +41 -2
- package/src/modules/workspace/watcher.ts +27 -4
- package/src/prose-drafts.ts +481 -0
- package/src/prose-segments.ts +51 -8
- package/src/recovery/offline-branch.ts +36 -29
- package/src/safe-slice.ts +9 -1
- package/src/stored-removal.ts +126 -0
- package/src/tool-image-ledger.ts +153 -34
- package/src/tool-presentation.ts +224 -40
- package/src/tool-result-guard.ts +7 -8
- package/src/tool-result-history.ts +124 -20
- package/src/tune-out/coordinator.ts +259 -65
- package/src/types/agent.ts +59 -13
- package/src/types/events.ts +17 -0
- package/src/types/framework.ts +31 -5
- package/src/types/inference-log.ts +1 -1
- package/src/types/module.ts +31 -7
- package/src/types/trace.ts +158 -12
- package/src/usage/usage-tracker.ts +32 -8
- package/dist/test/activation-request-sanitize.test.d.ts +0 -2
- package/dist/test/activation-request-sanitize.test.d.ts.map +0 -1
- package/dist/test/activation-request-sanitize.test.js +0 -89
- package/dist/test/activation-request-sanitize.test.js.map +0 -1
- package/dist/test/agent-cache-ttl.test.d.ts +0 -2
- package/dist/test/agent-cache-ttl.test.d.ts.map +0 -1
- package/dist/test/agent-cache-ttl.test.js +0 -41
- package/dist/test/agent-cache-ttl.test.js.map +0 -1
- package/dist/test/agent-runtime-settings.test.d.ts +0 -2
- package/dist/test/agent-runtime-settings.test.d.ts.map +0 -1
- package/dist/test/agent-runtime-settings.test.js +0 -462
- package/dist/test/agent-runtime-settings.test.js.map +0 -1
- package/dist/test/api-admin-gate.test.d.ts +0 -2
- package/dist/test/api-admin-gate.test.d.ts.map +0 -1
- package/dist/test/api-admin-gate.test.js +0 -116
- package/dist/test/api-admin-gate.test.js.map +0 -1
- package/dist/test/assistant-persist-refusal.test.d.ts +0 -2
- package/dist/test/assistant-persist-refusal.test.d.ts.map +0 -1
- package/dist/test/assistant-persist-refusal.test.js +0 -63
- package/dist/test/assistant-persist-refusal.test.js.map +0 -1
- package/dist/test/batched-wake-locus.test.d.ts +0 -2
- package/dist/test/batched-wake-locus.test.d.ts.map +0 -1
- package/dist/test/batched-wake-locus.test.js +0 -166
- package/dist/test/batched-wake-locus.test.js.map +0 -1
- package/dist/test/busy-agent-scheduler.test.d.ts +0 -2
- package/dist/test/busy-agent-scheduler.test.d.ts.map +0 -1
- package/dist/test/busy-agent-scheduler.test.js +0 -92
- package/dist/test/busy-agent-scheduler.test.js.map +0 -1
- package/dist/test/channel-incoming-targeting.test.d.ts +0 -2
- package/dist/test/channel-incoming-targeting.test.d.ts.map +0 -1
- package/dist/test/channel-incoming-targeting.test.js +0 -81
- package/dist/test/channel-incoming-targeting.test.js.map +0 -1
- package/dist/test/channel-label-history.test.d.ts +0 -2
- package/dist/test/channel-label-history.test.d.ts.map +0 -1
- package/dist/test/channel-label-history.test.js +0 -424
- package/dist/test/channel-label-history.test.js.map +0 -1
- package/dist/test/channel-lifecycle-provenance.test.d.ts +0 -2
- package/dist/test/channel-lifecycle-provenance.test.d.ts.map +0 -1
- package/dist/test/channel-lifecycle-provenance.test.js +0 -47
- package/dist/test/channel-lifecycle-provenance.test.js.map +0 -1
- package/dist/test/channel-registry-routing.test.d.ts +0 -2
- package/dist/test/channel-registry-routing.test.d.ts.map +0 -1
- package/dist/test/channel-registry-routing.test.js +0 -446
- package/dist/test/channel-registry-routing.test.js.map +0 -1
- package/dist/test/channel-registry-typing.test.d.ts +0 -2
- package/dist/test/channel-registry-typing.test.d.ts.map +0 -1
- package/dist/test/channel-registry-typing.test.js +0 -91
- package/dist/test/channel-registry-typing.test.js.map +0 -1
- package/dist/test/channels-changed-respond-first.test.d.ts +0 -2
- package/dist/test/channels-changed-respond-first.test.d.ts.map +0 -1
- package/dist/test/channels-changed-respond-first.test.js +0 -74
- package/dist/test/channels-changed-respond-first.test.js.map +0 -1
- package/dist/test/checkpoint-attribution.test.d.ts +0 -2
- package/dist/test/checkpoint-attribution.test.d.ts.map +0 -1
- package/dist/test/checkpoint-attribution.test.js +0 -200
- package/dist/test/checkpoint-attribution.test.js.map +0 -1
- package/dist/test/code-execution.test.d.ts +0 -11
- package/dist/test/code-execution.test.d.ts.map +0 -1
- package/dist/test/code-execution.test.js +0 -1272
- package/dist/test/code-execution.test.js.map +0 -1
- package/dist/test/component-defaults.test.d.ts +0 -2
- package/dist/test/component-defaults.test.d.ts.map +0 -1
- package/dist/test/component-defaults.test.js +0 -54
- package/dist/test/component-defaults.test.js.map +0 -1
- package/dist/test/conversation-fork-injection-scoping.test.d.ts +0 -2
- package/dist/test/conversation-fork-injection-scoping.test.d.ts.map +0 -1
- package/dist/test/conversation-fork-injection-scoping.test.js +0 -200
- package/dist/test/conversation-fork-injection-scoping.test.js.map +0 -1
- package/dist/test/conversation-router.test.d.ts +0 -2
- package/dist/test/conversation-router.test.d.ts.map +0 -1
- package/dist/test/conversation-router.test.js +0 -174
- package/dist/test/conversation-router.test.js.map +0 -1
- package/dist/test/conversation-routing.test.d.ts +0 -7
- package/dist/test/conversation-routing.test.d.ts.map +0 -1
- package/dist/test/conversation-routing.test.js +0 -387
- package/dist/test/conversation-routing.test.js.map +0 -1
- package/dist/test/deferred-wake-integrity.test.d.ts +0 -29
- package/dist/test/deferred-wake-integrity.test.d.ts.map +0 -1
- package/dist/test/deferred-wake-integrity.test.js +0 -320
- package/dist/test/deferred-wake-integrity.test.js.map +0 -1
- package/dist/test/discord-awareness-outbox.test.d.ts +0 -2
- package/dist/test/discord-awareness-outbox.test.d.ts.map +0 -1
- package/dist/test/discord-awareness-outbox.test.js +0 -267
- package/dist/test/discord-awareness-outbox.test.js.map +0 -1
- package/dist/test/discord-history-delete-window.test.d.ts +0 -2
- package/dist/test/discord-history-delete-window.test.d.ts.map +0 -1
- package/dist/test/discord-history-delete-window.test.js +0 -81
- package/dist/test/discord-history-delete-window.test.js.map +0 -1
- package/dist/test/discord-history-sync.test.d.ts +0 -2
- package/dist/test/discord-history-sync.test.d.ts.map +0 -1
- package/dist/test/discord-history-sync.test.js +0 -56
- package/dist/test/discord-history-sync.test.js.map +0 -1
- package/dist/test/ephemeral-settle.test.d.ts +0 -2
- package/dist/test/ephemeral-settle.test.d.ts.map +0 -1
- package/dist/test/ephemeral-settle.test.js +0 -354
- package/dist/test/ephemeral-settle.test.js.map +0 -1
- package/dist/test/event-gate-passthrough.test.d.ts +0 -15
- package/dist/test/event-gate-passthrough.test.d.ts.map +0 -1
- package/dist/test/event-gate-passthrough.test.js +0 -289
- package/dist/test/event-gate-passthrough.test.js.map +0 -1
- package/dist/test/event-gate-policy-mutation.test.d.ts +0 -2
- package/dist/test/event-gate-policy-mutation.test.d.ts.map +0 -1
- package/dist/test/event-gate-policy-mutation.test.js +0 -137
- package/dist/test/event-gate-policy-mutation.test.js.map +0 -1
- package/dist/test/event-gate-rate-limit.test.d.ts +0 -2
- package/dist/test/event-gate-rate-limit.test.d.ts.map +0 -1
- package/dist/test/event-gate-rate-limit.test.js +0 -627
- package/dist/test/event-gate-rate-limit.test.js.map +0 -1
- package/dist/test/event-gate-script.test.d.ts +0 -2
- package/dist/test/event-gate-script.test.d.ts.map +0 -1
- package/dist/test/event-gate-script.test.js +0 -95
- package/dist/test/event-gate-script.test.js.map +0 -1
- package/dist/test/event-gate-selfwake.test.d.ts +0 -15
- package/dist/test/event-gate-selfwake.test.d.ts.map +0 -1
- package/dist/test/event-gate-selfwake.test.js +0 -125
- package/dist/test/event-gate-selfwake.test.js.map +0 -1
- package/dist/test/event-gate-tags.test.d.ts +0 -2
- package/dist/test/event-gate-tags.test.d.ts.map +0 -1
- package/dist/test/event-gate-tags.test.js +0 -76
- package/dist/test/event-gate-tags.test.js.map +0 -1
- package/dist/test/event-gate.test.d.ts +0 -2
- package/dist/test/event-gate.test.d.ts.map +0 -1
- package/dist/test/event-gate.test.js +0 -919
- package/dist/test/event-gate.test.js.map +0 -1
- package/dist/test/explicit-prose-routing.test.d.ts +0 -11
- package/dist/test/explicit-prose-routing.test.d.ts.map +0 -1
- package/dist/test/explicit-prose-routing.test.js +0 -1394
- package/dist/test/explicit-prose-routing.test.js.map +0 -1
- package/dist/test/framework.test.d.ts +0 -5
- package/dist/test/framework.test.d.ts.map +0 -1
- package/dist/test/framework.test.js +0 -1048
- package/dist/test/framework.test.js.map +0 -1
- package/dist/test/gather-context-timeout.test.d.ts +0 -2
- package/dist/test/gather-context-timeout.test.d.ts.map +0 -1
- package/dist/test/gather-context-timeout.test.js +0 -120
- package/dist/test/gather-context-timeout.test.js.map +0 -1
- package/dist/test/health-snapshot.test.d.ts +0 -2
- package/dist/test/health-snapshot.test.d.ts.map +0 -1
- package/dist/test/health-snapshot.test.js +0 -74
- package/dist/test/health-snapshot.test.js.map +0 -1
- package/dist/test/helpers/coalescing-fixture.d.ts +0 -72
- package/dist/test/helpers/coalescing-fixture.d.ts.map +0 -1
- package/dist/test/helpers/coalescing-fixture.js +0 -146
- package/dist/test/helpers/coalescing-fixture.js.map +0 -1
- package/dist/test/helpers/coalescing-kill-child.d.ts +0 -2
- package/dist/test/helpers/coalescing-kill-child.d.ts.map +0 -1
- package/dist/test/helpers/coalescing-kill-child.js +0 -24
- package/dist/test/helpers/coalescing-kill-child.js.map +0 -1
- package/dist/test/helpers/mock-membrane.d.ts +0 -53
- package/dist/test/helpers/mock-membrane.d.ts.map +0 -1
- package/dist/test/helpers/mock-membrane.js +0 -168
- package/dist/test/helpers/mock-membrane.js.map +0 -1
- package/dist/test/helpers/pytc-stop-rows.d.ts +0 -11
- package/dist/test/helpers/pytc-stop-rows.d.ts.map +0 -1
- package/dist/test/helpers/pytc-stop-rows.js +0 -143
- package/dist/test/helpers/pytc-stop-rows.js.map +0 -1
- package/dist/test/helpers/quiesce-crash-child.d.ts +0 -2
- package/dist/test/helpers/quiesce-crash-child.d.ts.map +0 -1
- package/dist/test/helpers/quiesce-crash-child.js +0 -156
- package/dist/test/helpers/quiesce-crash-child.js.map +0 -1
- package/dist/test/history-module-overview.test.d.ts +0 -2
- package/dist/test/history-module-overview.test.d.ts.map +0 -1
- package/dist/test/history-module-overview.test.js +0 -711
- package/dist/test/history-module-overview.test.js.map +0 -1
- package/dist/test/history-module-realstore.test.d.ts +0 -2
- package/dist/test/history-module-realstore.test.d.ts.map +0 -1
- package/dist/test/history-module-realstore.test.js +0 -363
- package/dist/test/history-module-realstore.test.js.map +0 -1
- package/dist/test/history-module-semantic.test.d.ts +0 -2
- package/dist/test/history-module-semantic.test.d.ts.map +0 -1
- package/dist/test/history-module-semantic.test.js +0 -213
- package/dist/test/history-module-semantic.test.js.map +0 -1
- package/dist/test/history-module-ux.test.d.ts +0 -2
- package/dist/test/history-module-ux.test.d.ts.map +0 -1
- package/dist/test/history-module-ux.test.js +0 -304
- package/dist/test/history-module-ux.test.js.map +0 -1
- package/dist/test/history-module.test.d.ts +0 -2
- package/dist/test/history-module.test.d.ts.map +0 -1
- package/dist/test/history-module.test.js +0 -619
- package/dist/test/history-module.test.js.map +0 -1
- package/dist/test/history-semantic-review-findings.test.d.ts +0 -2
- package/dist/test/history-semantic-review-findings.test.d.ts.map +0 -1
- package/dist/test/history-semantic-review-findings.test.js +0 -338
- package/dist/test/history-semantic-review-findings.test.js.map +0 -1
- package/dist/test/history-semantic-sync-converges.test.d.ts +0 -2
- package/dist/test/history-semantic-sync-converges.test.d.ts.map +0 -1
- package/dist/test/history-semantic-sync-converges.test.js +0 -109
- package/dist/test/history-semantic-sync-converges.test.js.map +0 -1
- package/dist/test/host-quiesce.test.d.ts +0 -2
- package/dist/test/host-quiesce.test.d.ts.map +0 -1
- package/dist/test/host-quiesce.test.js +0 -863
- package/dist/test/host-quiesce.test.js.map +0 -1
- package/dist/test/inference-exhaustion-rewind.test.d.ts +0 -2
- package/dist/test/inference-exhaustion-rewind.test.d.ts.map +0 -1
- package/dist/test/inference-exhaustion-rewind.test.js +0 -309
- package/dist/test/inference-exhaustion-rewind.test.js.map +0 -1
- package/dist/test/inference-failure-bounds.test.d.ts +0 -2
- package/dist/test/inference-failure-bounds.test.d.ts.map +0 -1
- package/dist/test/inference-failure-bounds.test.js +0 -1201
- package/dist/test/inference-failure-bounds.test.js.map +0 -1
- package/dist/test/inference-failure-observability.test.d.ts +0 -2
- package/dist/test/inference-failure-observability.test.d.ts.map +0 -1
- package/dist/test/inference-failure-observability.test.js +0 -84
- package/dist/test/inference-failure-observability.test.js.map +0 -1
- package/dist/test/journal-tool.test.d.ts +0 -2
- package/dist/test/journal-tool.test.d.ts.map +0 -1
- package/dist/test/journal-tool.test.js +0 -33
- package/dist/test/journal-tool.test.js.map +0 -1
- package/dist/test/kv-unified-open-flight-retry.test.d.ts +0 -2
- package/dist/test/kv-unified-open-flight-retry.test.d.ts.map +0 -1
- package/dist/test/kv-unified-open-flight-retry.test.js +0 -189
- package/dist/test/kv-unified-open-flight-retry.test.js.map +0 -1
- package/dist/test/kv-unified-wiring.test.d.ts +0 -2
- package/dist/test/kv-unified-wiring.test.d.ts.map +0 -1
- package/dist/test/kv-unified-wiring.test.js +0 -95
- package/dist/test/kv-unified-wiring.test.js.map +0 -1
- package/dist/test/late-events-after-stop.test.d.ts +0 -2
- package/dist/test/late-events-after-stop.test.d.ts.map +0 -1
- package/dist/test/late-events-after-stop.test.js +0 -122
- package/dist/test/late-events-after-stop.test.js.map +0 -1
- package/dist/test/liveness-watchdog.test.d.ts +0 -2
- package/dist/test/liveness-watchdog.test.d.ts.map +0 -1
- package/dist/test/liveness-watchdog.test.js +0 -94
- package/dist/test/liveness-watchdog.test.js.map +0 -1
- package/dist/test/machine-close-provenance.test.d.ts +0 -2
- package/dist/test/machine-close-provenance.test.d.ts.map +0 -1
- package/dist/test/machine-close-provenance.test.js +0 -116
- package/dist/test/machine-close-provenance.test.js.map +0 -1
- package/dist/test/maintenance-timer.test.d.ts +0 -2
- package/dist/test/maintenance-timer.test.d.ts.map +0 -1
- package/dist/test/maintenance-timer.test.js +0 -265
- package/dist/test/maintenance-timer.test.js.map +0 -1
- package/dist/test/mcpl-access-provider.test.d.ts +0 -2
- package/dist/test/mcpl-access-provider.test.d.ts.map +0 -1
- package/dist/test/mcpl-access-provider.test.js +0 -20
- package/dist/test/mcpl-access-provider.test.js.map +0 -1
- package/dist/test/mcpl-awareness-barrier.test.d.ts +0 -2
- package/dist/test/mcpl-awareness-barrier.test.d.ts.map +0 -1
- package/dist/test/mcpl-awareness-barrier.test.js +0 -769
- package/dist/test/mcpl-awareness-barrier.test.js.map +0 -1
- package/dist/test/mcpl-capability-grant.test.d.ts +0 -10
- package/dist/test/mcpl-capability-grant.test.d.ts.map +0 -1
- package/dist/test/mcpl-capability-grant.test.js +0 -111
- package/dist/test/mcpl-capability-grant.test.js.map +0 -1
- package/dist/test/mcpl-capability-scoping.test.d.ts +0 -2
- package/dist/test/mcpl-capability-scoping.test.d.ts.map +0 -1
- package/dist/test/mcpl-capability-scoping.test.js +0 -266
- package/dist/test/mcpl-capability-scoping.test.js.map +0 -1
- package/dist/test/mcpl-child-env.test.d.ts +0 -2
- package/dist/test/mcpl-child-env.test.d.ts.map +0 -1
- package/dist/test/mcpl-child-env.test.js +0 -158
- package/dist/test/mcpl-child-env.test.js.map +0 -1
- package/dist/test/mcpl-coalescing.test.d.ts +0 -2
- package/dist/test/mcpl-coalescing.test.d.ts.map +0 -1
- package/dist/test/mcpl-coalescing.test.js +0 -1125
- package/dist/test/mcpl-coalescing.test.js.map +0 -1
- package/dist/test/mcpl-config-diagnostics.test.d.ts +0 -2
- package/dist/test/mcpl-config-diagnostics.test.d.ts.map +0 -1
- package/dist/test/mcpl-config-diagnostics.test.js +0 -452
- package/dist/test/mcpl-config-diagnostics.test.js.map +0 -1
- package/dist/test/mcpl-empty-content.test.d.ts +0 -2
- package/dist/test/mcpl-empty-content.test.d.ts.map +0 -1
- package/dist/test/mcpl-empty-content.test.js +0 -368
- package/dist/test/mcpl-empty-content.test.js.map +0 -1
- package/dist/test/mcpl-gate-roundtrip.test.d.ts +0 -2
- package/dist/test/mcpl-gate-roundtrip.test.d.ts.map +0 -1
- package/dist/test/mcpl-gate-roundtrip.test.js +0 -285
- package/dist/test/mcpl-gate-roundtrip.test.js.map +0 -1
- package/dist/test/mcpl-list-status.test.d.ts +0 -2
- package/dist/test/mcpl-list-status.test.d.ts.map +0 -1
- package/dist/test/mcpl-list-status.test.js +0 -82
- package/dist/test/mcpl-list-status.test.js.map +0 -1
- package/dist/test/mcpl-manifest-changed.test.d.ts +0 -2
- package/dist/test/mcpl-manifest-changed.test.d.ts.map +0 -1
- package/dist/test/mcpl-manifest-changed.test.js +0 -178
- package/dist/test/mcpl-manifest-changed.test.js.map +0 -1
- package/dist/test/mcpl-push-convert.test.d.ts +0 -2
- package/dist/test/mcpl-push-convert.test.d.ts.map +0 -1
- package/dist/test/mcpl-push-convert.test.js +0 -42
- package/dist/test/mcpl-push-convert.test.js.map +0 -1
- package/dist/test/mcpl-reconnect-events.test.d.ts +0 -2
- package/dist/test/mcpl-reconnect-events.test.d.ts.map +0 -1
- package/dist/test/mcpl-reconnect-events.test.js +0 -144
- package/dist/test/mcpl-reconnect-events.test.js.map +0 -1
- package/dist/test/mcpl-reconnect-reregistration.test.d.ts +0 -2
- package/dist/test/mcpl-reconnect-reregistration.test.d.ts.map +0 -1
- package/dist/test/mcpl-reconnect-reregistration.test.js +0 -236
- package/dist/test/mcpl-reconnect-reregistration.test.js.map +0 -1
- package/dist/test/mcpl-reference-fetcher.test.d.ts +0 -2
- package/dist/test/mcpl-reference-fetcher.test.d.ts.map +0 -1
- package/dist/test/mcpl-reference-fetcher.test.js +0 -427
- package/dist/test/mcpl-reference-fetcher.test.js.map +0 -1
- package/dist/test/mcpl-reference-fields.test.d.ts +0 -2
- package/dist/test/mcpl-reference-fields.test.d.ts.map +0 -1
- package/dist/test/mcpl-reference-fields.test.js +0 -149
- package/dist/test/mcpl-reference-fields.test.js.map +0 -1
- package/dist/test/mcpl-request-timeout.test.d.ts +0 -2
- package/dist/test/mcpl-request-timeout.test.d.ts.map +0 -1
- package/dist/test/mcpl-request-timeout.test.js +0 -138
- package/dist/test/mcpl-request-timeout.test.js.map +0 -1
- package/dist/test/mcpl-runtime-lifecycle.test.d.ts +0 -7
- package/dist/test/mcpl-runtime-lifecycle.test.d.ts.map +0 -1
- package/dist/test/mcpl-runtime-lifecycle.test.js +0 -142
- package/dist/test/mcpl-runtime-lifecycle.test.js.map +0 -1
- package/dist/test/mcpl-tool-class-listing.test.d.ts +0 -2
- package/dist/test/mcpl-tool-class-listing.test.d.ts.map +0 -1
- package/dist/test/mcpl-tool-class-listing.test.js +0 -147
- package/dist/test/mcpl-tool-class-listing.test.js.map +0 -1
- package/dist/test/mcpl-tool-classes.test.d.ts +0 -7
- package/dist/test/mcpl-tool-classes.test.d.ts.map +0 -1
- package/dist/test/mcpl-tool-classes.test.js +0 -80
- package/dist/test/mcpl-tool-classes.test.js.map +0 -1
- package/dist/test/mcpl-tool-lifecycle-e2e.test.d.ts +0 -2
- package/dist/test/mcpl-tool-lifecycle-e2e.test.d.ts.map +0 -1
- package/dist/test/mcpl-tool-lifecycle-e2e.test.js +0 -237
- package/dist/test/mcpl-tool-lifecycle-e2e.test.js.map +0 -1
- package/dist/test/mcpl-tool-lifecycle-emitter.test.d.ts +0 -11
- package/dist/test/mcpl-tool-lifecycle-emitter.test.d.ts.map +0 -1
- package/dist/test/mcpl-tool-lifecycle-emitter.test.js +0 -412
- package/dist/test/mcpl-tool-lifecycle-emitter.test.js.map +0 -1
- package/dist/test/mcpl-tool-lifecycle-script.test.d.ts +0 -2
- package/dist/test/mcpl-tool-lifecycle-script.test.d.ts.map +0 -1
- package/dist/test/mcpl-tool-lifecycle-script.test.js +0 -288
- package/dist/test/mcpl-tool-lifecycle-script.test.js.map +0 -1
- package/dist/test/mcpl-tool-lifecycle.test.d.ts +0 -11
- package/dist/test/mcpl-tool-lifecycle.test.d.ts.map +0 -1
- package/dist/test/mcpl-tool-lifecycle.test.js +0 -270
- package/dist/test/mcpl-tool-lifecycle.test.js.map +0 -1
- package/dist/test/mcpl-ws-transport.test.d.ts +0 -2
- package/dist/test/mcpl-ws-transport.test.d.ts.map +0 -1
- package/dist/test/mcpl-ws-transport.test.js +0 -258
- package/dist/test/mcpl-ws-transport.test.js.map +0 -1
- package/dist/test/module-context-integration.test.d.ts +0 -18
- package/dist/test/module-context-integration.test.d.ts.map +0 -1
- package/dist/test/module-context-integration.test.js +0 -181
- package/dist/test/module-context-integration.test.js.map +0 -1
- package/dist/test/offline-recovery-branch.test.d.ts +0 -2
- package/dist/test/offline-recovery-branch.test.d.ts.map +0 -1
- package/dist/test/offline-recovery-branch.test.js +0 -226
- package/dist/test/offline-recovery-branch.test.js.map +0 -1
- package/dist/test/operator-surgery.test.d.ts +0 -2
- package/dist/test/operator-surgery.test.d.ts.map +0 -1
- package/dist/test/operator-surgery.test.js +0 -398
- package/dist/test/operator-surgery.test.js.map +0 -1
- package/dist/test/ops-alert.test.d.ts +0 -2
- package/dist/test/ops-alert.test.d.ts.map +0 -1
- package/dist/test/ops-alert.test.js +0 -153
- package/dist/test/ops-alert.test.js.map +0 -1
- package/dist/test/overbudget-drain-breaker.test.d.ts +0 -2
- package/dist/test/overbudget-drain-breaker.test.d.ts.map +0 -1
- package/dist/test/overbudget-drain-breaker.test.js +0 -197
- package/dist/test/overbudget-drain-breaker.test.js.map +0 -1
- package/dist/test/per-agent-delivery.test.d.ts +0 -2
- package/dist/test/per-agent-delivery.test.d.ts.map +0 -1
- package/dist/test/per-agent-delivery.test.js +0 -108
- package/dist/test/per-agent-delivery.test.js.map +0 -1
- package/dist/test/physical-window-restart.test.d.ts +0 -14
- package/dist/test/physical-window-restart.test.d.ts.map +0 -1
- package/dist/test/physical-window-restart.test.js +0 -222
- package/dist/test/physical-window-restart.test.js.map +0 -1
- package/dist/test/placed-reaction-baseline.test.d.ts +0 -2
- package/dist/test/placed-reaction-baseline.test.d.ts.map +0 -1
- package/dist/test/placed-reaction-baseline.test.js +0 -312
- package/dist/test/placed-reaction-baseline.test.js.map +0 -1
- package/dist/test/present-while-acting.test.d.ts +0 -19
- package/dist/test/present-while-acting.test.d.ts.map +0 -1
- package/dist/test/present-while-acting.test.js +0 -706
- package/dist/test/present-while-acting.test.js.map +0 -1
- package/dist/test/prose-segments.test.d.ts +0 -2
- package/dist/test/prose-segments.test.d.ts.map +0 -1
- package/dist/test/prose-segments.test.js +0 -52
- package/dist/test/prose-segments.test.js.map +0 -1
- package/dist/test/prose-stream-router.test.d.ts +0 -2
- package/dist/test/prose-stream-router.test.d.ts.map +0 -1
- package/dist/test/prose-stream-router.test.js +0 -171
- package/dist/test/prose-stream-router.test.js.map +0 -1
- package/dist/test/provider-acceleration-cooldown.test.d.ts +0 -2
- package/dist/test/provider-acceleration-cooldown.test.d.ts.map +0 -1
- package/dist/test/provider-acceleration-cooldown.test.js +0 -435
- package/dist/test/provider-acceleration-cooldown.test.js.map +0 -1
- package/dist/test/provider-waits.test.d.ts +0 -2
- package/dist/test/provider-waits.test.d.ts.map +0 -1
- package/dist/test/provider-waits.test.js +0 -2196
- package/dist/test/provider-waits.test.js.map +0 -1
- package/dist/test/puppet-tool-call.test.d.ts +0 -2
- package/dist/test/puppet-tool-call.test.d.ts.map +0 -1
- package/dist/test/puppet-tool-call.test.js +0 -224
- package/dist/test/puppet-tool-call.test.js.map +0 -1
- package/dist/test/puppet-turn-reservation.test.d.ts +0 -2
- package/dist/test/puppet-turn-reservation.test.d.ts.map +0 -1
- package/dist/test/puppet-turn-reservation.test.js +0 -139
- package/dist/test/puppet-turn-reservation.test.js.map +0 -1
- package/dist/test/reaction-baseline-platform.test.d.ts +0 -2
- package/dist/test/reaction-baseline-platform.test.d.ts.map +0 -1
- package/dist/test/reaction-baseline-platform.test.js +0 -124
- package/dist/test/reaction-baseline-platform.test.js.map +0 -1
- package/dist/test/record-journal.test.d.ts +0 -6
- package/dist/test/record-journal.test.d.ts.map +0 -1
- package/dist/test/record-journal.test.js +0 -269
- package/dist/test/record-journal.test.js.map +0 -1
- package/dist/test/refusal-reaction-baseline.test.d.ts +0 -2
- package/dist/test/refusal-reaction-baseline.test.d.ts.map +0 -1
- package/dist/test/refusal-reaction-baseline.test.js +0 -81
- package/dist/test/refusal-reaction-baseline.test.js.map +0 -1
- package/dist/test/refusal-rewind.test.d.ts +0 -2
- package/dist/test/refusal-rewind.test.d.ts.map +0 -1
- package/dist/test/refusal-rewind.test.js +0 -108
- package/dist/test/refusal-rewind.test.js.map +0 -1
- package/dist/test/refusal-single-call.test.d.ts +0 -2
- package/dist/test/refusal-single-call.test.d.ts.map +0 -1
- package/dist/test/refusal-single-call.test.js +0 -177
- package/dist/test/refusal-single-call.test.js.map +0 -1
- package/dist/test/release-changelog.test.d.ts +0 -2
- package/dist/test/release-changelog.test.d.ts.map +0 -1
- package/dist/test/release-changelog.test.js +0 -159
- package/dist/test/release-changelog.test.js.map +0 -1
- package/dist/test/same-round-think-policy.test.d.ts +0 -2
- package/dist/test/same-round-think-policy.test.d.ts.map +0 -1
- package/dist/test/same-round-think-policy.test.js +0 -853
- package/dist/test/same-round-think-policy.test.js.map +0 -1
- package/dist/test/save-recent-image.test.d.ts +0 -26
- package/dist/test/save-recent-image.test.d.ts.map +0 -1
- package/dist/test/save-recent-image.test.js +0 -974
- package/dist/test/save-recent-image.test.js.map +0 -1
- package/dist/test/shutdown-errors.test.d.ts +0 -2
- package/dist/test/shutdown-errors.test.d.ts.map +0 -1
- package/dist/test/shutdown-errors.test.js +0 -662
- package/dist/test/shutdown-errors.test.js.map +0 -1
- package/dist/test/silent-heartbeat-rows.test.d.ts +0 -2
- package/dist/test/silent-heartbeat-rows.test.d.ts.map +0 -1
- package/dist/test/silent-heartbeat-rows.test.js +0 -451
- package/dist/test/silent-heartbeat-rows.test.js.map +0 -1
- package/dist/test/silent-heartbeat.test.d.ts +0 -2
- package/dist/test/silent-heartbeat.test.d.ts.map +0 -1
- package/dist/test/silent-heartbeat.test.js +0 -165
- package/dist/test/silent-heartbeat.test.js.map +0 -1
- package/dist/test/state-scaling-e2e.test.d.ts +0 -22
- package/dist/test/state-scaling-e2e.test.d.ts.map +0 -1
- package/dist/test/state-scaling-e2e.test.js +0 -206
- package/dist/test/state-scaling-e2e.test.js.map +0 -1
- package/dist/test/state-scaling.test.d.ts +0 -12
- package/dist/test/state-scaling.test.d.ts.map +0 -1
- package/dist/test/state-scaling.test.js +0 -251
- package/dist/test/state-scaling.test.js.map +0 -1
- package/dist/test/stop-with-work-in-flight.test.d.ts +0 -23
- package/dist/test/stop-with-work-in-flight.test.d.ts.map +0 -1
- package/dist/test/stop-with-work-in-flight.test.js +0 -672
- package/dist/test/stop-with-work-in-flight.test.js.map +0 -1
- package/dist/test/surgery-marks-receipt.test.d.ts +0 -2
- package/dist/test/surgery-marks-receipt.test.d.ts.map +0 -1
- package/dist/test/surgery-marks-receipt.test.js +0 -540
- package/dist/test/surgery-marks-receipt.test.js.map +0 -1
- package/dist/test/thinking-token-stamp.test.d.ts +0 -12
- package/dist/test/thinking-token-stamp.test.d.ts.map +0 -1
- package/dist/test/thinking-token-stamp.test.js +0 -129
- package/dist/test/thinking-token-stamp.test.js.map +0 -1
- package/dist/test/timezone.test.d.ts +0 -2
- package/dist/test/timezone.test.d.ts.map +0 -1
- package/dist/test/timezone.test.js +0 -18
- package/dist/test/timezone.test.js.map +0 -1
- package/dist/test/tool-batch-hook.test.d.ts +0 -8
- package/dist/test/tool-batch-hook.test.d.ts.map +0 -1
- package/dist/test/tool-batch-hook.test.js +0 -275
- package/dist/test/tool-batch-hook.test.js.map +0 -1
- package/dist/test/tool-policy.test.d.ts +0 -2
- package/dist/test/tool-policy.test.d.ts.map +0 -1
- package/dist/test/tool-policy.test.js +0 -51
- package/dist/test/tool-policy.test.js.map +0 -1
- package/dist/test/tool-presentation.test.d.ts +0 -2
- package/dist/test/tool-presentation.test.d.ts.map +0 -1
- package/dist/test/tool-presentation.test.js +0 -268
- package/dist/test/tool-presentation.test.js.map +0 -1
- package/dist/test/tool-result-content.test.d.ts +0 -2
- package/dist/test/tool-result-content.test.d.ts.map +0 -1
- package/dist/test/tool-result-content.test.js +0 -37
- package/dist/test/tool-result-content.test.js.map +0 -1
- package/dist/test/tool-result-guard.test.d.ts +0 -2
- package/dist/test/tool-result-guard.test.d.ts.map +0 -1
- package/dist/test/tool-result-guard.test.js +0 -3607
- package/dist/test/tool-result-guard.test.js.map +0 -1
- package/dist/test/tool-result-history.test.d.ts +0 -7
- package/dist/test/tool-result-history.test.d.ts.map +0 -1
- package/dist/test/tool-result-history.test.js +0 -156
- package/dist/test/tool-result-history.test.js.map +0 -1
- package/dist/test/tool-result-spill.test.d.ts +0 -13
- package/dist/test/tool-result-spill.test.d.ts.map +0 -1
- package/dist/test/tool-result-spill.test.js +0 -586
- package/dist/test/tool-result-spill.test.js.map +0 -1
- package/dist/test/tool-wrapper-prose-guard-integration.test.d.ts +0 -2
- package/dist/test/tool-wrapper-prose-guard-integration.test.d.ts.map +0 -1
- package/dist/test/tool-wrapper-prose-guard-integration.test.js +0 -485
- package/dist/test/tool-wrapper-prose-guard-integration.test.js.map +0 -1
- package/dist/test/tool-wrapper-prose-guard.test.d.ts +0 -2
- package/dist/test/tool-wrapper-prose-guard.test.d.ts.map +0 -1
- package/dist/test/tool-wrapper-prose-guard.test.js +0 -34
- package/dist/test/tool-wrapper-prose-guard.test.js.map +0 -1
- package/dist/test/tools-observe-parser-conformance.test.d.ts +0 -2
- package/dist/test/tools-observe-parser-conformance.test.d.ts.map +0 -1
- package/dist/test/tools-observe-parser-conformance.test.js +0 -129
- package/dist/test/tools-observe-parser-conformance.test.js.map +0 -1
- package/dist/test/trunk-channel-routing.test.d.ts +0 -19
- package/dist/test/trunk-channel-routing.test.d.ts.map +0 -1
- package/dist/test/trunk-channel-routing.test.js +0 -329
- package/dist/test/trunk-channel-routing.test.js.map +0 -1
- package/dist/test/tune-out-e2e.test.d.ts +0 -2
- package/dist/test/tune-out-e2e.test.d.ts.map +0 -1
- package/dist/test/tune-out-e2e.test.js +0 -142
- package/dist/test/tune-out-e2e.test.js.map +0 -1
- package/dist/test/tune-out-gate-composition.test.d.ts +0 -2
- package/dist/test/tune-out-gate-composition.test.d.ts.map +0 -1
- package/dist/test/tune-out-gate-composition.test.js +0 -221
- package/dist/test/tune-out-gate-composition.test.js.map +0 -1
- package/dist/test/tune-out-lifecycle.test.d.ts +0 -2
- package/dist/test/tune-out-lifecycle.test.d.ts.map +0 -1
- package/dist/test/tune-out-lifecycle.test.js +0 -121
- package/dist/test/tune-out-lifecycle.test.js.map +0 -1
- package/dist/test/turn-trigger-provenance.test.d.ts +0 -2
- package/dist/test/turn-trigger-provenance.test.d.ts.map +0 -1
- package/dist/test/turn-trigger-provenance.test.js +0 -137
- package/dist/test/turn-trigger-provenance.test.js.map +0 -1
- package/dist/test/unconvertible-tool-result.test.d.ts +0 -2
- package/dist/test/unconvertible-tool-result.test.d.ts.map +0 -1
- package/dist/test/unconvertible-tool-result.test.js +0 -358
- package/dist/test/unconvertible-tool-result.test.js.map +0 -1
- package/dist/test/usage-accounting.test.d.ts +0 -2
- package/dist/test/usage-accounting.test.d.ts.map +0 -1
- package/dist/test/usage-accounting.test.js +0 -13
- package/dist/test/usage-accounting.test.js.map +0 -1
- package/dist/test/usage-tracker.test.d.ts +0 -2
- package/dist/test/usage-tracker.test.d.ts.map +0 -1
- package/dist/test/usage-tracker.test.js +0 -129
- package/dist/test/usage-tracker.test.js.map +0 -1
- package/dist/test/utils-surface.test.d.ts +0 -2
- package/dist/test/utils-surface.test.d.ts.map +0 -1
- package/dist/test/utils-surface.test.js +0 -145
- package/dist/test/utils-surface.test.js.map +0 -1
- package/dist/test/workspace-branch-continuation.test.d.ts +0 -15
- package/dist/test/workspace-branch-continuation.test.d.ts.map +0 -1
- package/dist/test/workspace-branch-continuation.test.js +0 -183
- package/dist/test/workspace-branch-continuation.test.js.map +0 -1
- package/dist/test/workspace-materialize-freshness.test.d.ts +0 -16
- package/dist/test/workspace-materialize-freshness.test.d.ts.map +0 -1
- package/dist/test/workspace-materialize-freshness.test.js +0 -252
- package/dist/test/workspace-materialize-freshness.test.js.map +0 -1
- package/dist/test/workspace-path-containment.test.d.ts +0 -19
- package/dist/test/workspace-path-containment.test.d.ts.map +0 -1
- package/dist/test/workspace-path-containment.test.js +0 -91
- package/dist/test/workspace-path-containment.test.js.map +0 -1
- package/dist/test/workspace-read-file-from-disk.test.d.ts +0 -17
- package/dist/test/workspace-read-file-from-disk.test.d.ts.map +0 -1
- package/dist/test/workspace-read-file-from-disk.test.js +0 -174
- package/dist/test/workspace-read-file-from-disk.test.js.map +0 -1
- package/dist/test/workspace-read-image.test.d.ts +0 -2
- package/dist/test/workspace-read-image.test.d.ts.map +0 -1
- package/dist/test/workspace-read-image.test.js +0 -597
- package/dist/test/workspace-read-image.test.js.map +0 -1
- package/dist/test/workspace-read-text.test.d.ts +0 -2
- package/dist/test/workspace-read-text.test.d.ts.map +0 -1
- package/dist/test/workspace-read-text.test.js +0 -101
- package/dist/test/workspace-read-text.test.js.map +0 -1
- package/dist/test/workspace-restore-order.test.d.ts +0 -16
- package/dist/test/workspace-restore-order.test.d.ts.map +0 -1
- package/dist/test/workspace-restore-order.test.js +0 -140
- package/dist/test/workspace-restore-order.test.js.map +0 -1
- package/dist/test/workspace-three-way.test.d.ts +0 -12
- package/dist/test/workspace-three-way.test.d.ts.map +0 -1
- package/dist/test/workspace-three-way.test.js +0 -3194
- package/dist/test/workspace-three-way.test.js.map +0 -1
- package/dist/test/workspace-watcher.test.d.ts +0 -2
- package/dist/test/workspace-watcher.test.d.ts.map +0 -1
- package/dist/test/workspace-watcher.test.js +0 -281
- package/dist/test/workspace-watcher.test.js.map +0 -1
- package/dist/test/xml-round-persist.test.d.ts +0 -19
- package/dist/test/xml-round-persist.test.d.ts.map +0 -1
- package/dist/test/xml-round-persist.test.js +0 -235
- package/dist/test/xml-round-persist.test.js.map +0 -1
- package/dist/tsconfig.tsbuildinfo +0 -1
|
@@ -11,10 +11,11 @@
|
|
|
11
11
|
|
|
12
12
|
import { EventEmitter } from 'node:events';
|
|
13
13
|
|
|
14
|
-
import { openTransport, type McplTransport, type TransportCloseInfo } from './transport.js';
|
|
14
|
+
import { openTransport, STDERR_END_WAIT_MS, type McplTransport, type TransportCloseInfo } from './transport.js';
|
|
15
15
|
import { maskNegotiatedCapabilities } from './capability-mask.js';
|
|
16
16
|
import { CapabilityGrant, expandAdvertisementShorthand } from './capability-grant.js';
|
|
17
|
-
import { CAPABILITY_DISABLED } from './errors.js';
|
|
17
|
+
import { CAPABILITY_DISABLED, boundedForLog, describeCause } from './errors.js';
|
|
18
|
+
import { logDetail, logValue } from './log-value.js';
|
|
18
19
|
|
|
19
20
|
import type {
|
|
20
21
|
McplServerConfig,
|
|
@@ -65,6 +66,9 @@ export interface McplConnectionCloseInfo {
|
|
|
65
66
|
signal: NodeJS.Signals | null;
|
|
66
67
|
/** WebSocket close reason, or a short description of the cause. */
|
|
67
68
|
reason?: string;
|
|
69
|
+
/** True when `reason` is the peer's own text, a WebSocket server's close
|
|
70
|
+
* reason, rather than the transport's or the host's words. */
|
|
71
|
+
reasonFromPeer?: boolean;
|
|
68
72
|
/** True when the host closed the link (`close()` / `reconnectAfterFailure()`),
|
|
69
73
|
* false when the transport dropped unexpectedly. */
|
|
70
74
|
byHost: boolean;
|
|
@@ -74,6 +78,37 @@ export interface McplConnectionCloseInfo {
|
|
|
74
78
|
* Spring Boot + JDA servers can take 5-10s to boot, so 30s is safe. */
|
|
75
79
|
const INITIALIZE_TIMEOUT_MS = 30_000;
|
|
76
80
|
|
|
81
|
+
/** A failed connect's `stderrTail`, the last of the server's stderr that its
|
|
82
|
+
* handshake's error keeps, when there is one. */
|
|
83
|
+
export function stderrTailOf(error: unknown): string | undefined {
|
|
84
|
+
const tail = (error as { stderrTail?: unknown } | null | undefined)?.stderrTail;
|
|
85
|
+
return typeof tail === 'string' && tail !== '' ? tail : undefined;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** For the host's own log line about a failed connect: the server's stderr
|
|
89
|
+
* that the error keeps as `stderrTail`, one marked line per line of it,
|
|
90
|
+
* each through log-value, since it's the server's text. '' when there's
|
|
91
|
+
* none. */
|
|
92
|
+
export function withStderr(error: unknown): string {
|
|
93
|
+
const tail = stderrTailOf(error);
|
|
94
|
+
if (tail === undefined) return '';
|
|
95
|
+
return '. The last of its stderr:' + tail.split('\n').map((line) => `\n stderr: ${logDetail(line)}`).join('');
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** A transport close's reason, as an error message gives it: the transport's
|
|
99
|
+
* own words. A WebSocket peer's close reason is the server's text
|
|
100
|
+
* (`reasonFromPeer`), so an error gives the words the transport uses for a
|
|
101
|
+
* close without one, as `mcpl:server-closed` leaves that text out. A
|
|
102
|
+
* WebSocket close's code, a number, says what the server meant (4001: a
|
|
103
|
+
* refused credential), with or without a reason, so each error gives it too:
|
|
104
|
+
* a pending request's error has `code=`, and the handshake's adds it for any
|
|
105
|
+
* WebSocket close, since a close before the handshake completes reaches no
|
|
106
|
+
* 'close' event. A stdio child's exit reads as before. */
|
|
107
|
+
function closeReasonText(info: TransportCloseInfo): string {
|
|
108
|
+
if (info.reasonFromPeer) return 'websocket closed';
|
|
109
|
+
return info.reason ?? 'unknown';
|
|
110
|
+
}
|
|
111
|
+
|
|
77
112
|
/** Default per-request timeout in milliseconds (see McplServerConfig.requestTimeoutMs).
|
|
78
113
|
* A live-but-wedged server (accepts requests, never answers, never closes its
|
|
79
114
|
* transport) would otherwise freeze the awaiting agent turn forever — no
|
|
@@ -84,6 +119,33 @@ const DEFAULT_REQUEST_TIMEOUT_MS = 60_000;
|
|
|
84
119
|
/** MCP protocol version used in the initialize handshake. */
|
|
85
120
|
const MCP_PROTOCOL_VERSION = '2024-11-05';
|
|
86
121
|
|
|
122
|
+
/**
|
|
123
|
+
* Why a request to an MCPL server produced no result, as far as the host can
|
|
124
|
+
* know it. Messages are unchanged from plain errors; the `outcome` makes the
|
|
125
|
+
* difference between "never left the host" and "left, and no answer came
|
|
126
|
+
* back" a fact a caller can act on instead of a string to match:
|
|
127
|
+
* - `not-sent`: the request was refused before anything was written (the
|
|
128
|
+
* connection was already closed);
|
|
129
|
+
* - `error-response`: the server answered with a JSON-RPC error (it may have
|
|
130
|
+
* acted before failing; the error alone does not say);
|
|
131
|
+
* - `no-response`: the request was handed to the transport and no answer
|
|
132
|
+
* came back (timeout, or the connection closed while awaiting). It does
|
|
133
|
+
* not prove the request reached the server — the transport can decline or
|
|
134
|
+
* drop a write — only that the host can no longer say it didn't.
|
|
135
|
+
*/
|
|
136
|
+
export class McplRequestError extends Error {
|
|
137
|
+
constructor(
|
|
138
|
+
message: string,
|
|
139
|
+
readonly outcome: 'not-sent' | 'error-response' | 'no-response',
|
|
140
|
+
/** The JSON-RPC error's `data`, verbatim, when the server supplied one
|
|
141
|
+
* (e.g. which parts of a multi-part send were posted). */
|
|
142
|
+
readonly data?: unknown,
|
|
143
|
+
) {
|
|
144
|
+
super(message);
|
|
145
|
+
this.name = 'McplRequestError';
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
87
149
|
/**
|
|
88
150
|
* Represents a pending JSON-RPC request awaiting a response.
|
|
89
151
|
*/
|
|
@@ -102,6 +164,13 @@ interface RequestOptions {
|
|
|
102
164
|
surfaceOrphanedResponse?: boolean;
|
|
103
165
|
}
|
|
104
166
|
|
|
167
|
+
/** A request's method for a log line, whatever the server sent there. */
|
|
168
|
+
function describeMethod(method: unknown): string {
|
|
169
|
+
return typeof method === 'string'
|
|
170
|
+
? `method ${logValue(method)}`
|
|
171
|
+
: `a method of type ${method === null ? 'null' : typeof method}`;
|
|
172
|
+
}
|
|
173
|
+
|
|
105
174
|
/**
|
|
106
175
|
* McplServerConnection manages a single JSON-RPC 2.0 connection to an
|
|
107
176
|
* MCPL server over stdio. Use the static `connect()` factory to create
|
|
@@ -116,8 +185,13 @@ interface RequestOptions {
|
|
|
116
185
|
* - `'channels-incoming'` — Server sent `channels/incoming`
|
|
117
186
|
* - `'error'` — Connection-level error
|
|
118
187
|
* - `'close'` — Connection closed: `(code, signal, info: McplConnectionCloseInfo)`
|
|
119
|
-
* - `'connect-failed'` — Initial connect failed; background retry scheduled
|
|
120
|
-
*
|
|
188
|
+
* - `'connect-failed'` — Initial connect failed; background retry scheduled:
|
|
189
|
+
* `{ error, stderrTail?, attempt }`
|
|
190
|
+
* - `'reconnect-failed'` — A background reconnect attempt failed; next retry scheduled:
|
|
191
|
+
* `{ error, stderrTail?, attempt }`. `stderrTail` is the last of the
|
|
192
|
+
* server's stderr when its handshake failed by its transport closing, a
|
|
193
|
+
* transport error or its timeout and it had written any; `error` never
|
|
194
|
+
* carries it.
|
|
121
195
|
* - `'reconnect'` — Background reconnect succeeded
|
|
122
196
|
*/
|
|
123
197
|
export class McplServerConnection extends EventEmitter {
|
|
@@ -229,7 +303,10 @@ export class McplServerConnection extends EventEmitter {
|
|
|
229
303
|
private pendingRequests = new Map<string | number, PendingRequest>();
|
|
230
304
|
/** Metadata retained after selected request deadlines so a late response is
|
|
231
305
|
* observable even though its original promise has already been rejected. */
|
|
232
|
-
private orphanedRequests = new Map<string | number, {
|
|
306
|
+
private orphanedRequests = new Map<string | number, {
|
|
307
|
+
method: string;
|
|
308
|
+
renderParams?: { featureSet: string; key: string; eventId: string; channelId?: string };
|
|
309
|
+
}>();
|
|
233
310
|
private closed = false;
|
|
234
311
|
/** Set by `reconnectAfterFailure()` before it closes a live transport, so
|
|
235
312
|
* the transport close handler reports that teardown as `byHost: true`. */
|
|
@@ -240,6 +317,9 @@ export class McplServerConnection extends EventEmitter {
|
|
|
240
317
|
|
|
241
318
|
/** Per-request timeout in ms (0 disables). See McplServerConfig.requestTimeoutMs. */
|
|
242
319
|
private requestTimeoutMs = DEFAULT_REQUEST_TIMEOUT_MS;
|
|
320
|
+
/** The deadline a channels/publish or channels/open request keeps when
|
|
321
|
+
* requestTimeoutMs is 0 (see sendChannelsPublish). */
|
|
322
|
+
private publishDeadlineMs = DEFAULT_REQUEST_TIMEOUT_MS;
|
|
243
323
|
|
|
244
324
|
// Event buffering: control-plane traffic can be released independently from
|
|
245
325
|
// inference-bearing data-plane traffic. This lets a server finish its own
|
|
@@ -248,15 +328,24 @@ export class McplServerConnection extends EventEmitter {
|
|
|
248
328
|
private controlPlaneReady = false;
|
|
249
329
|
private dataPlaneReady = false;
|
|
250
330
|
private bufferedEvents: Array<{ event: string; args: unknown[] }> = [];
|
|
251
|
-
/**
|
|
252
|
-
*
|
|
253
|
-
private
|
|
331
|
+
/** How many of bufferedEvents are server→host requests, each holding a
|
|
332
|
+
* responder its server waits on. Every change to bufferedEvents keeps it. */
|
|
333
|
+
private heldRequests = 0;
|
|
334
|
+
/** Cap on held notifications (responder-less events) during a plane pause
|
|
335
|
+
* (issue #122), counted apart from requests: past it, the oldest held
|
|
336
|
+
* notification is dropped. */
|
|
337
|
+
private static readonly MAX_HELD_NOTIFICATIONS = 1000;
|
|
338
|
+
/** Budget of held requests during a plane pause (#387), counted apart from
|
|
339
|
+
* notifications: past it, a request is refused at once, never dropped. It
|
|
340
|
+
* bounds a server that pipelines requests without waiting for answers. A
|
|
341
|
+
* server that doesn't send a refused request again loses it (discord-mcpl
|
|
342
|
+
* doesn't), so the budget sits far above the notifications' cap, to leave
|
|
343
|
+
* a busy server's long pause room. */
|
|
344
|
+
private static readonly MAX_HELD_REQUESTS = 10_000;
|
|
254
345
|
private droppedBufferedEvents = 0;
|
|
255
|
-
/**
|
|
256
|
-
*
|
|
257
|
-
|
|
258
|
-
* NEW arrivals during a pause, not churn from control-plane flushes). */
|
|
259
|
-
private flushDepth = 0;
|
|
346
|
+
/** Requests refused at the budget since the planes last opened (ready()),
|
|
347
|
+
* so each pause's first refusal is logged. */
|
|
348
|
+
private refusedHeldRequests = 0;
|
|
260
349
|
|
|
261
350
|
// Reconnect state (adapted from Anarchid/agent-framework@mcpl-module-proto)
|
|
262
351
|
private config: McplServerConfig | null = null;
|
|
@@ -275,6 +364,13 @@ export class McplServerConnection extends EventEmitter {
|
|
|
275
364
|
return this.reconnectEnabled;
|
|
276
365
|
}
|
|
277
366
|
|
|
367
|
+
/** Closed with no reconnect to come: after close(), whether or not its
|
|
368
|
+
* transport close succeeded, or a drop with reconnect off. A connection
|
|
369
|
+
* between retries keeps reconnectEnabled, so it isn't closed for good. */
|
|
370
|
+
private get closedForGood(): boolean {
|
|
371
|
+
return this.closed && !this.reconnectEnabled;
|
|
372
|
+
}
|
|
373
|
+
|
|
278
374
|
/**
|
|
279
375
|
* Private constructor. Use `McplServerConnection.connect()` instead.
|
|
280
376
|
*/
|
|
@@ -302,28 +398,38 @@ export class McplServerConnection extends EventEmitter {
|
|
|
302
398
|
* Mark the connection as ready — flushes any events that arrived between
|
|
303
399
|
* construction (when setupMessageRouting starts emitting) and now (when
|
|
304
400
|
* the caller has attached listeners via wireMcplEvents).
|
|
401
|
+
*
|
|
402
|
+
* Does nothing once the connection is closed for good. Its policy was reset
|
|
403
|
+
* when it closed, so what it held that needs a grant would be refused, and a
|
|
404
|
+
* closed connection sends no response, so nothing it held could be answered.
|
|
405
|
+
* Only what needs no grant would pass, to listeners of a server that won't
|
|
406
|
+
* be served again. A connection between retries isn't closed for good: what
|
|
407
|
+
* it held, such as a reconnect stub's connect-failed, still reaches its
|
|
408
|
+
* listeners.
|
|
305
409
|
*/
|
|
306
410
|
ready(): void {
|
|
411
|
+
if (this.closedForGood) return;
|
|
307
412
|
this.controlPlaneReady = true;
|
|
308
413
|
this.dataPlaneReady = true;
|
|
309
414
|
const pending = this.bufferedEvents;
|
|
310
415
|
this.bufferedEvents = [];
|
|
416
|
+
// The cap's drops are counted per pause: this flush ends one, so its line
|
|
417
|
+
// reports that pause's drops, and the next pause counts (and logs) its own.
|
|
418
|
+
const dropped = this.droppedBufferedEvents;
|
|
419
|
+
this.droppedBufferedEvents = 0;
|
|
420
|
+
this.heldRequests = 0;
|
|
421
|
+
this.refusedHeldRequests = 0;
|
|
311
422
|
if (pending.length > 200) {
|
|
312
423
|
console.error(
|
|
313
424
|
`[mcpl] ${this.id}: flushing ${pending.length} buffered event(s) synchronously ` +
|
|
314
|
-
`(long pause backlog${
|
|
425
|
+
`(long pause backlog${dropped > 0 ? `; ${dropped} dropped at cap` : ''})`,
|
|
315
426
|
);
|
|
316
427
|
}
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
// snapshot is being flushed; later data items must observe that pause.
|
|
323
|
-
this.emit(event, ...args);
|
|
324
|
-
}
|
|
325
|
-
} finally {
|
|
326
|
-
this.flushDepth--;
|
|
428
|
+
for (const { event, args } of pending) {
|
|
429
|
+
// Re-enter the gate for every buffered item. A control handler (notably
|
|
430
|
+
// tools/list_changed) may install a newer data-plane barrier while this
|
|
431
|
+
// snapshot is being flushed; later data items must observe that pause.
|
|
432
|
+
this.dispatchInboundEvent(event, ...args);
|
|
327
433
|
}
|
|
328
434
|
}
|
|
329
435
|
|
|
@@ -331,24 +437,22 @@ export class McplServerConnection extends EventEmitter {
|
|
|
331
437
|
* Release only server-establishment and lifecycle/control traffic. Responses
|
|
332
438
|
* to host requests are never event-buffered, so tools/list and tools/call
|
|
333
439
|
* responses remain live as well. Inference-bearing requests stay queued in
|
|
334
|
-
* their original relative order until {@link ready} is called.
|
|
440
|
+
* their original relative order until {@link ready} is called. Like
|
|
441
|
+
* {@link ready}, it does nothing once the connection is closed for good.
|
|
335
442
|
*/
|
|
336
443
|
readyControlPlane(): void {
|
|
444
|
+
if (this.closedForGood) return;
|
|
337
445
|
this.controlPlaneReady = true;
|
|
338
446
|
const pending = this.bufferedEvents;
|
|
339
447
|
this.bufferedEvents = [];
|
|
340
|
-
this.
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
this.emit(item.event, ...item.args);
|
|
349
|
-
}
|
|
350
|
-
} finally {
|
|
351
|
-
this.flushDepth--;
|
|
448
|
+
this.heldRequests = 0;
|
|
449
|
+
for (const item of pending) {
|
|
450
|
+
// Re-enter the ADMISSION gate (this.emit), never super.emit: control
|
|
451
|
+
// events include channels-register/changed, which are grant-gated —
|
|
452
|
+
// the old direct flush bypassed positive-grant enforcement entirely
|
|
453
|
+
// (PR #79 review blocker 3). Data-plane items re-buffer in order via
|
|
454
|
+
// the same call, since dataPlaneReady is still false.
|
|
455
|
+
this.dispatchInboundEvent(item.event, ...item.args);
|
|
352
456
|
}
|
|
353
457
|
}
|
|
354
458
|
|
|
@@ -403,44 +507,84 @@ export class McplServerConnection extends EventEmitter {
|
|
|
403
507
|
if (responder?.respondError) {
|
|
404
508
|
responder.respondError(CAPABILITY_DISABLED, `${name} rejected: capability "${requiredCap}" ${phase}`, { capability: requiredCap });
|
|
405
509
|
} else {
|
|
406
|
-
console.error(`[mcpl] ${this.id}: discarded ${name} — "${requiredCap}" ${phase}`);
|
|
510
|
+
console.error(`[mcpl] ${this.id}: discarded ${logValue(name)} — "${requiredCap}" ${phase}`);
|
|
407
511
|
}
|
|
408
512
|
return true;
|
|
409
513
|
}
|
|
514
|
+
// §6.6: a request that will never be answered MUST get an error. A
|
|
515
|
+
// request whose event nothing on this host listens for would never be.
|
|
516
|
+
const request = args[1] as {
|
|
517
|
+
respond?: (result: unknown) => void;
|
|
518
|
+
respondError?: (code: number, message: string, data?: unknown) => void;
|
|
519
|
+
} | undefined;
|
|
520
|
+
if (typeof request?.respondError === 'function' && this.listenerCount(event) === 0) {
|
|
521
|
+
request.respondError(-32601, 'Method not found');
|
|
522
|
+
console.error(`[mcpl] ${this.id}: answered -32601 to ${logValue(name)}, which nothing on this host handles`);
|
|
523
|
+
return true;
|
|
524
|
+
}
|
|
525
|
+
// mcpl/manifestChanged (§17.3) and tools/list_changed are notifications.
|
|
526
|
+
// Sent as a request, either is answered with an empty result as it's
|
|
527
|
+
// admitted, and passed on as the notification is, with no responder:
|
|
528
|
+
// the host acts on it the same way, so the answer doesn't depend on what
|
|
529
|
+
// the refresh does, and it's written before any request the refresh
|
|
530
|
+
// sends. This is where live routing and buffer flushes meet, so a request
|
|
531
|
+
// held while its plane is closed is answered only when it's let through,
|
|
532
|
+
// never by a startup that fails first.
|
|
533
|
+
if ((name === 'manifest-changed' || name === 'tools-list-changed') && typeof request?.respond === 'function') {
|
|
534
|
+
request.respond({});
|
|
535
|
+
return super.emit(event, args[0]);
|
|
536
|
+
}
|
|
410
537
|
return super.emit(event, ...args);
|
|
411
538
|
}
|
|
412
|
-
//
|
|
413
|
-
//
|
|
414
|
-
//
|
|
415
|
-
// holds a
|
|
416
|
-
//
|
|
417
|
-
//
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
)
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
if (dropIndex >= 0) {
|
|
433
|
-
this.bufferedEvents.splice(dropIndex, 1); // drop-oldest non-request
|
|
434
|
-
this.bufferedEvents.push({ event: name, args });
|
|
435
|
-
}
|
|
436
|
-
// else: buffer is all held requests — drop the incoming event instead.
|
|
437
|
-
return true;
|
|
539
|
+
// Held until the plane opens. A long pause (a quiesce, say) on a busy or a
|
|
540
|
+
// runaway server would otherwise grow this array without bound, so
|
|
541
|
+
// requests and notifications each have a bound, counted apart. A request
|
|
542
|
+
// holds a responder its server waits on, and dropping it would strand that
|
|
543
|
+
// call, so past MAX_HELD_REQUESTS (#387) it's refused at once with -32000,
|
|
544
|
+
// the code of the host's other transient refusals, and its server can send
|
|
545
|
+
// it again. A notification has no one to tell, so past
|
|
546
|
+
// MAX_HELD_NOTIFICATIONS (issue #122) the oldest held notification is
|
|
547
|
+
// dropped to make room. A flush takes the whole buffer and zeroes its
|
|
548
|
+
// count, so what it holds again was admitted within these bounds and
|
|
549
|
+
// stays within them.
|
|
550
|
+
const responder = args[1] as { respond?: unknown; respondError?: (code: number, message: string) => void } | undefined;
|
|
551
|
+
const isRequest = McplServerConnection.hasResponder({ args });
|
|
552
|
+
if (isRequest && this.heldRequests >= McplServerConnection.MAX_HELD_REQUESTS) {
|
|
553
|
+
this.refusedHeldRequests++;
|
|
554
|
+
if (this.refusedHeldRequests % 100 === 1) {
|
|
555
|
+
console.error(
|
|
556
|
+
`[mcpl] ${this.id}: held-request budget (${McplServerConnection.MAX_HELD_REQUESTS}) — ` +
|
|
557
|
+
`refused ${this.refusedHeldRequests} request(s) with -32000 while the plane is paused`,
|
|
558
|
+
);
|
|
438
559
|
}
|
|
560
|
+
responder?.respondError?.(
|
|
561
|
+
-32000,
|
|
562
|
+
`the host is busy: ${McplServerConnection.MAX_HELD_REQUESTS} of this server's requests are already waiting; send this one again later`,
|
|
563
|
+
);
|
|
564
|
+
return true;
|
|
565
|
+
}
|
|
566
|
+
if (!isRequest && this.bufferedEvents.length - this.heldRequests >= McplServerConnection.MAX_HELD_NOTIFICATIONS) {
|
|
567
|
+
this.droppedBufferedEvents++;
|
|
568
|
+
if (this.droppedBufferedEvents % 100 === 1) {
|
|
569
|
+
console.error(
|
|
570
|
+
`[mcpl] ${this.id}: buffered-event cap (${McplServerConnection.MAX_HELD_NOTIFICATIONS}) — ` +
|
|
571
|
+
`dropped ${this.droppedBufferedEvents} responder-less event(s) while the plane is paused`,
|
|
572
|
+
);
|
|
573
|
+
}
|
|
574
|
+
const oldest = this.bufferedEvents.findIndex((item) => !McplServerConnection.hasResponder(item));
|
|
575
|
+
if (oldest >= 0) this.bufferedEvents.splice(oldest, 1);
|
|
439
576
|
}
|
|
440
577
|
this.bufferedEvents.push({ event: name, args });
|
|
578
|
+
if (isRequest) this.heldRequests++;
|
|
441
579
|
return true;
|
|
442
580
|
}
|
|
443
581
|
|
|
582
|
+
/** A buffered server→host request: it carries a responder its server waits on. */
|
|
583
|
+
private static hasResponder(item: { args: unknown[] }): boolean {
|
|
584
|
+
const responder = item.args[1] as { respond?: unknown } | undefined;
|
|
585
|
+
return typeof responder?.respond === 'function';
|
|
586
|
+
}
|
|
587
|
+
|
|
444
588
|
/** Event-name form of METHOD_TO_REQUIRED_CAPABILITY, for admission-time
|
|
445
589
|
* enforcement in emit(). */
|
|
446
590
|
private static readonly EVENT_TO_REQUIRED_CAPABILITY: Record<string, string> = {
|
|
@@ -507,8 +651,9 @@ export class McplServerConnection extends EventEmitter {
|
|
|
507
651
|
connection.allowHostCommands = config.allowHostCommands === true;
|
|
508
652
|
connection.requestTimeoutMs = config.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
509
653
|
|
|
510
|
-
// Store config for reconnection
|
|
511
|
-
|
|
654
|
+
// Store config for reconnection. Only `true` turns reconnect on, as at
|
|
655
|
+
// every other reader of it.
|
|
656
|
+
if (config.reconnect === true) {
|
|
512
657
|
connection.config = config;
|
|
513
658
|
connection.hostCapabilities = hostCapabilities;
|
|
514
659
|
connection.reconnectEnabled = true;
|
|
@@ -531,6 +676,15 @@ export class McplServerConnection extends EventEmitter {
|
|
|
531
676
|
hostCapabilities: McplHostCapabilities,
|
|
532
677
|
): Promise<{ transport: McplTransport; capabilities: McplCapabilities | null; droppedCapabilities: ReadonlySet<string>; mcpToolsAdvertised: boolean }> {
|
|
533
678
|
const transport = await openTransport(config);
|
|
679
|
+
// Once the handshake stops listening for 'error', this logs what the
|
|
680
|
+
// transport reports, until the handshake hands the transport on, or for
|
|
681
|
+
// good if the handshake fails. EventEmitter throws an 'error' that has no
|
|
682
|
+
// listener, and from an I/O callback nothing catches it. A malformed
|
|
683
|
+
// WebSocket frame that arrives with the initialize response, or while a
|
|
684
|
+
// failed handshake's close() runs, is such an error.
|
|
685
|
+
const logAfterSettled = (err: Error) => {
|
|
686
|
+
console.error(`[mcpl] ${config.id}: transport error after the handshake settled: ${err.message}`);
|
|
687
|
+
};
|
|
534
688
|
|
|
535
689
|
try {
|
|
536
690
|
const initId = 0; // use id=0 for the handshake
|
|
@@ -548,10 +702,20 @@ export class McplServerConnection extends EventEmitter {
|
|
|
548
702
|
// Await the initialize response, racing an early transport close/error and
|
|
549
703
|
// a timeout. All three paths clean up their listeners.
|
|
550
704
|
const { mcpl: rawCapabilities, mcpToolsAdvertised } = await new Promise<{ mcpl: McplCapabilities | null; mcpToolsAdvertised: boolean }>((resolve, reject) => {
|
|
705
|
+
// When the transport fails, the end of the server's stderr often says
|
|
706
|
+
// why, such as a missing token or a crash at startup. It goes on the
|
|
707
|
+
// error as `stderrTail`, never into the message: an error's message
|
|
708
|
+
// travels to traces and tool results, and a server's stderr is its
|
|
709
|
+
// own text, which can hold a credential.
|
|
710
|
+
const failed = (failure: string): Error & { stderrTail?: string } => {
|
|
711
|
+
const tail = transport.stderrTail.trimEnd();
|
|
712
|
+
return Object.assign(new Error(failure), tail ? { stderrTail: tail } : {});
|
|
713
|
+
};
|
|
551
714
|
const cleanup = () => {
|
|
552
715
|
transport.off('line', onLine);
|
|
553
716
|
transport.off('close', onClose);
|
|
554
717
|
transport.off('error', onError);
|
|
718
|
+
transport.on('error', logAfterSettled);
|
|
555
719
|
clearTimeout(timer);
|
|
556
720
|
};
|
|
557
721
|
const onLine = (line: string) => {
|
|
@@ -561,10 +725,30 @@ export class McplServerConnection extends EventEmitter {
|
|
|
561
725
|
} catch {
|
|
562
726
|
return; // Ignore non-JSON lines (e.g. logback output from Java servers)
|
|
563
727
|
}
|
|
728
|
+
if (msg === null || typeof msg !== 'object' || Array.isArray(msg)) return;
|
|
729
|
+
// A request or a notification from the server is never the
|
|
730
|
+
// initialize response, whatever its id: a server's own ids can start
|
|
731
|
+
// at 0, this handshake's. MCP lets a server ping before
|
|
732
|
+
// initialization completes, and the ping gets its empty result, as
|
|
733
|
+
// on a connected transport. Anything else it sends now is ignored.
|
|
734
|
+
if ('method' in msg) {
|
|
735
|
+
const request = msg as unknown as JsonRpcRequest;
|
|
736
|
+
if (request.method === 'ping' && request.id != null) {
|
|
737
|
+
transport.writeLine(JSON.stringify({ jsonrpc: '2.0', id: request.id, result: {} }));
|
|
738
|
+
}
|
|
739
|
+
return;
|
|
740
|
+
}
|
|
564
741
|
if (msg.id !== initId) return;
|
|
565
742
|
cleanup();
|
|
566
743
|
if (msg.error) {
|
|
567
|
-
|
|
744
|
+
// describeCause rather than the template's own conversion: the
|
|
745
|
+
// server's `message` can be any JSON value, and one that has no
|
|
746
|
+
// primitive form, such as {"toString":1}, would throw out of this
|
|
747
|
+
// listener after cleanup() has cleared the timeout: an uncaught
|
|
748
|
+
// exception, which ends a host that doesn't catch them, and a
|
|
749
|
+
// handshake left to wait forever. It's the server's text in an
|
|
750
|
+
// error's message, so it's bounded as errors.ts says.
|
|
751
|
+
reject(new Error(`MCPL server "${config.id}" initialize error: ${boundedForLog(describeCause(msg.error.message))}`));
|
|
568
752
|
return;
|
|
569
753
|
}
|
|
570
754
|
const result = msg.result as Record<string, unknown> | undefined;
|
|
@@ -580,15 +764,22 @@ export class McplServerConnection extends EventEmitter {
|
|
|
580
764
|
};
|
|
581
765
|
const onClose = (info: TransportCloseInfo) => {
|
|
582
766
|
cleanup();
|
|
583
|
-
|
|
767
|
+
const code = transport.kind === 'websocket' && typeof info.code === 'number' ? `, code ${info.code}` : '';
|
|
768
|
+
const failure = `MCPL server "${config.id}" transport closed before handshake completed (${closeReasonText(info)}${code})`;
|
|
769
|
+
// The close comes at a stdio child's exit, which Node can emit before
|
|
770
|
+
// it has read the last of the child's stderr, or when the host closes
|
|
771
|
+
// the transport, which then ends the child. The tail is taken once
|
|
772
|
+
// stderr has ended, waiting at most STDERR_END_WAIT_MS. A WebSocket
|
|
773
|
+
// transport has no stderr to wait for.
|
|
774
|
+
void transport.stderrEnded(STDERR_END_WAIT_MS).then(() => reject(failed(failure)));
|
|
584
775
|
};
|
|
585
776
|
const onError = (err: Error) => {
|
|
586
777
|
cleanup();
|
|
587
|
-
reject(
|
|
778
|
+
reject(failed(`MCPL server "${config.id}" transport error during handshake: ${err.message}`));
|
|
588
779
|
};
|
|
589
780
|
const timer = setTimeout(() => {
|
|
590
781
|
cleanup();
|
|
591
|
-
reject(
|
|
782
|
+
reject(failed(`MCPL server "${config.id}" initialize handshake timed out`));
|
|
592
783
|
}, INITIALIZE_TIMEOUT_MS);
|
|
593
784
|
|
|
594
785
|
transport.on('line', onLine);
|
|
@@ -610,9 +801,13 @@ export class McplServerConnection extends EventEmitter {
|
|
|
610
801
|
// had never been advertised (hooks, streaming, queries all read this).
|
|
611
802
|
const { capabilities: scoped, dropped } = maskNegotiatedCapabilities(capabilities, config);
|
|
612
803
|
if (dropped.length > 0) {
|
|
613
|
-
console.error(`MCPL server "${config.id}" capabilities masked by host config: ${dropped.join(', ')}`);
|
|
804
|
+
console.error(`MCPL server "${config.id}" capabilities masked by host config: ${dropped.map(logValue).join(', ')}`);
|
|
614
805
|
}
|
|
615
806
|
|
|
807
|
+
// The caller wires the transport, or keeps it for close() with a
|
|
808
|
+
// listener of its own, in the continuation of this return, before any
|
|
809
|
+
// I/O callback can emit.
|
|
810
|
+
transport.off('error', logAfterSettled);
|
|
616
811
|
return { transport, capabilities: scoped, droppedCapabilities: new Set(dropped), mcpToolsAdvertised };
|
|
617
812
|
} catch (err) {
|
|
618
813
|
// Never leak the child / socket if the handshake fails.
|
|
@@ -634,17 +829,18 @@ export class McplServerConnection extends EventEmitter {
|
|
|
634
829
|
try {
|
|
635
830
|
return await McplServerConnection.connect(config, hostCapabilities);
|
|
636
831
|
} catch (error) {
|
|
637
|
-
if (
|
|
832
|
+
if (config.reconnect !== true) {
|
|
638
833
|
throw error;
|
|
639
834
|
}
|
|
640
835
|
|
|
641
836
|
// Non-blocking start: create a disconnected stub that will reconnect in background
|
|
642
|
-
console.error(`MCPL server "${config.id}" initial connect failed, will retry
|
|
837
|
+
console.error(`MCPL server "${config.id}" initial connect failed, will retry: ${(error as Error).message}${withStderr(error)}`);
|
|
643
838
|
const stub = McplServerConnection.createDisconnectedStub(config, hostCapabilities);
|
|
644
839
|
// Surface the initial failure. The event is buffered by the emit()
|
|
645
840
|
// override until the host wires listeners and calls ready(), so it is
|
|
646
841
|
// not lost in the window before wireMcplEvents runs.
|
|
647
|
-
|
|
842
|
+
const stderrTail = stderrTailOf(error);
|
|
843
|
+
stub.emit('connect-failed', { error: (error as Error).message, ...(stderrTail ? { stderrTail } : {}), attempt: 0 });
|
|
648
844
|
return stub;
|
|
649
845
|
}
|
|
650
846
|
}
|
|
@@ -748,9 +944,13 @@ export class McplServerConnection extends EventEmitter {
|
|
|
748
944
|
return this.sendRequest(McplMethod.StateRollback, params as unknown as Record<string, unknown>) as Promise<StateRollbackResult>;
|
|
749
945
|
}
|
|
750
946
|
|
|
751
|
-
/** Send `channels/open` request and await result.
|
|
947
|
+
/** Send `channels/open` request and await result. It keeps a deadline as
|
|
948
|
+
* channels/publish does: a delivery opens a closed channel before it
|
|
949
|
+
* publishes, so an open that is never answered would hold the delivery,
|
|
950
|
+
* and the turn that waits for it, for good. */
|
|
752
951
|
sendChannelsOpen(params: ChannelsOpenParams): Promise<ChannelsOpenResult> {
|
|
753
|
-
|
|
952
|
+
const timeoutMs = this.requestTimeoutMs > 0 ? this.requestTimeoutMs : this.publishDeadlineMs;
|
|
953
|
+
return this.sendRequest(McplMethod.ChannelsOpen, params as unknown as Record<string, unknown>, { timeoutMs }) as Promise<ChannelsOpenResult>;
|
|
754
954
|
}
|
|
755
955
|
|
|
756
956
|
/** Send `channels/close` request and await result. */
|
|
@@ -775,13 +975,20 @@ export class McplServerConnection extends EventEmitter {
|
|
|
775
975
|
* Send `channels/publish`.
|
|
776
976
|
* May be sent as a request (if an ACK is desired) or notification.
|
|
777
977
|
* When `params.stream` is true, sends as a notification (no ACK).
|
|
978
|
+
*
|
|
979
|
+
* A request always has a deadline: the server's requestTimeoutMs, or
|
|
980
|
+
* publishDeadlineMs when that is 0 (disabled). A publish is a side effect
|
|
981
|
+
* whose outcome the resident is told and a held draft's attempt records,
|
|
982
|
+
* so one that is never answered would hold both open for good. Its expiry
|
|
983
|
+
* is a no-response, which the caller reads as unknown.
|
|
778
984
|
*/
|
|
779
985
|
sendChannelsPublish(params: ChannelsPublishParams): Promise<ChannelsPublishResult | void> {
|
|
780
986
|
if (params.stream) {
|
|
781
987
|
this.sendNotification(McplMethod.ChannelsPublish, params as unknown as Record<string, unknown>);
|
|
782
988
|
return Promise.resolve();
|
|
783
989
|
}
|
|
784
|
-
|
|
990
|
+
const timeoutMs = this.requestTimeoutMs > 0 ? this.requestTimeoutMs : this.publishDeadlineMs;
|
|
991
|
+
return this.sendRequest(McplMethod.ChannelsPublish, params as unknown as Record<string, unknown>, { timeoutMs }) as Promise<ChannelsPublishResult>;
|
|
785
992
|
}
|
|
786
993
|
|
|
787
994
|
/** Send `channels/outgoing/chunk` notification. */
|
|
@@ -874,7 +1081,7 @@ export class McplServerConnection extends EventEmitter {
|
|
|
874
1081
|
// Reject all pending requests
|
|
875
1082
|
for (const [id, pending] of this.pendingRequests) {
|
|
876
1083
|
if (pending.timer) clearTimeout(pending.timer);
|
|
877
|
-
pending.reject(new
|
|
1084
|
+
pending.reject(new McplRequestError(`Connection to MCPL server "${this.id}" closed while awaiting response for ${pending.method} (id=${id})`, 'no-response'));
|
|
878
1085
|
}
|
|
879
1086
|
this.pendingRequests.clear();
|
|
880
1087
|
this.orphanedRequests.clear();
|
|
@@ -885,7 +1092,8 @@ export class McplServerConnection extends EventEmitter {
|
|
|
885
1092
|
const attempt = Promise.resolve().then(async () => {
|
|
886
1093
|
// An already opened handshake owns a transport too. It hands that
|
|
887
1094
|
// transport back without admission once reconnect has been disabled.
|
|
888
|
-
//
|
|
1095
|
+
// Only the registry's closeAll bounds its caller's wait for this; retry
|
|
1096
|
+
// reuses this real close attempt.
|
|
889
1097
|
if (this.reconnectPromise) await this.reconnectPromise;
|
|
890
1098
|
if (this.transport) await this.transport.close();
|
|
891
1099
|
this.closeIncomplete = false;
|
|
@@ -989,6 +1197,13 @@ export class McplServerConnection extends EventEmitter {
|
|
|
989
1197
|
// The prior transport was disconnected before this retry began. Keep
|
|
990
1198
|
// the fresh, unadmitted transport owned by close(), including on a
|
|
991
1199
|
// failed transport cleanup, instead of reviving a stopped connection.
|
|
1200
|
+
// It isn't wired, and the handshake has removed its own listeners, so
|
|
1201
|
+
// an error it reports from here on, such as a malformed frame from a
|
|
1202
|
+
// WebSocket server while close() closes it, is logged here rather than
|
|
1203
|
+
// thrown where nothing catches it.
|
|
1204
|
+
transport.on('error', (err: Error) => {
|
|
1205
|
+
console.error(`[mcpl] ${this.id}: a transport kept for close() reported an error: ${err.message}`);
|
|
1206
|
+
});
|
|
992
1207
|
this.transport = transport;
|
|
993
1208
|
return;
|
|
994
1209
|
}
|
|
@@ -1013,9 +1228,10 @@ export class McplServerConnection extends EventEmitter {
|
|
|
1013
1228
|
this.reconnectAttempts = 0;
|
|
1014
1229
|
this.emit('reconnect', { attempts: attempt });
|
|
1015
1230
|
} catch (error) {
|
|
1016
|
-
console.error(`MCPL server "${this.id}" reconnect failed
|
|
1231
|
+
console.error(`MCPL server "${this.id}" reconnect failed: ${(error as Error).message}${withStderr(error)}`);
|
|
1017
1232
|
this.reconnectAttempts = attempt + 1;
|
|
1018
|
-
|
|
1233
|
+
const stderrTail = stderrTailOf(error);
|
|
1234
|
+
this.emit('reconnect-failed', { error: (error as Error).message, ...(stderrTail ? { stderrTail } : {}), attempt });
|
|
1019
1235
|
this.scheduleReconnect();
|
|
1020
1236
|
}
|
|
1021
1237
|
}
|
|
@@ -1041,7 +1257,7 @@ export class McplServerConnection extends EventEmitter {
|
|
|
1041
1257
|
options: RequestOptions = {},
|
|
1042
1258
|
): Promise<unknown> {
|
|
1043
1259
|
if (this.closed) {
|
|
1044
|
-
return Promise.reject(new
|
|
1260
|
+
return Promise.reject(new McplRequestError(`Cannot send request: connection to "${this.id}" is closed`, 'not-sent'));
|
|
1045
1261
|
}
|
|
1046
1262
|
|
|
1047
1263
|
const id = this.nextRequestId++;
|
|
@@ -1059,23 +1275,47 @@ export class McplServerConnection extends EventEmitter {
|
|
|
1059
1275
|
pending.timer = setTimeout(() => {
|
|
1060
1276
|
this.pendingRequests.delete(id);
|
|
1061
1277
|
if (options.surfaceOrphanedResponse) {
|
|
1062
|
-
this.orphanedRequests.set(id, {
|
|
1278
|
+
this.orphanedRequests.set(id, {
|
|
1279
|
+
method,
|
|
1280
|
+
...(method === 'push/render'
|
|
1281
|
+
? {
|
|
1282
|
+
renderParams: {
|
|
1283
|
+
featureSet: params.featureSet as string,
|
|
1284
|
+
key: params.key as string,
|
|
1285
|
+
eventId: params.eventId as string,
|
|
1286
|
+
...(typeof params.channelId === 'string' ? { channelId: params.channelId } : {}),
|
|
1287
|
+
},
|
|
1288
|
+
}
|
|
1289
|
+
: {}),
|
|
1290
|
+
});
|
|
1063
1291
|
if (this.orphanedRequests.size > 4096) this.orphanedRequests.delete(this.orphanedRequests.keys().next().value!);
|
|
1064
1292
|
}
|
|
1065
|
-
reject(new
|
|
1293
|
+
reject(new McplRequestError(
|
|
1066
1294
|
`MCPL server "${this.id}" did not respond to ${method} (id=${id}) ` +
|
|
1067
1295
|
`within ${timeoutMs}ms — the server may be hung. The response ` +
|
|
1068
1296
|
`outcome is unknown: the request was abandoned locally but was not ` +
|
|
1069
1297
|
`cancelled, so the tool may still have completed server-side; verify ` +
|
|
1070
1298
|
`state before retrying; a blind retry of a stateful/side-effecting ` +
|
|
1071
1299
|
`tool may duplicate it.`,
|
|
1300
|
+
'no-response',
|
|
1072
1301
|
));
|
|
1073
1302
|
}, timeoutMs);
|
|
1074
1303
|
// Don't hold the event loop open for the watchdog alone.
|
|
1075
1304
|
pending.timer.unref?.();
|
|
1076
1305
|
}
|
|
1077
1306
|
this.pendingRequests.set(id, pending);
|
|
1078
|
-
|
|
1307
|
+
try {
|
|
1308
|
+
this.transport!.writeLine(JSON.stringify(request));
|
|
1309
|
+
} catch (err) {
|
|
1310
|
+
// A synchronous write rejection sent no request. Remove its pending
|
|
1311
|
+
// state and watchdog before reporting that it is safe to retry.
|
|
1312
|
+
this.pendingRequests.delete(id);
|
|
1313
|
+
if (pending.timer) clearTimeout(pending.timer);
|
|
1314
|
+
reject(new McplRequestError(
|
|
1315
|
+
`Cannot send ${method} to MCPL server "${this.id}": ${err instanceof Error ? err.message : String(err)}`,
|
|
1316
|
+
'not-sent',
|
|
1317
|
+
));
|
|
1318
|
+
}
|
|
1079
1319
|
});
|
|
1080
1320
|
}
|
|
1081
1321
|
|
|
@@ -1165,7 +1405,9 @@ export class McplServerConnection extends EventEmitter {
|
|
|
1165
1405
|
this.setupLifecycle(transport);
|
|
1166
1406
|
// Surface transport diagnostics (stdio child stderr) as 'stderr' events,
|
|
1167
1407
|
// preserving the `{ line }` payload existing consumers expect.
|
|
1168
|
-
|
|
1408
|
+
// Through the same containment boundary as every inbound event, so a
|
|
1409
|
+
// stderr listener that throws is reported, not thrown into the transport.
|
|
1410
|
+
transport.on('stderr', (line: string) => this.dispatchInboundEvent('stderr', { line }));
|
|
1169
1411
|
}
|
|
1170
1412
|
|
|
1171
1413
|
/**
|
|
@@ -1181,61 +1423,148 @@ export class McplServerConnection extends EventEmitter {
|
|
|
1181
1423
|
return;
|
|
1182
1424
|
}
|
|
1183
1425
|
|
|
1184
|
-
//
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1426
|
+
// JSON-RPC messages must be objects. Ignore unrelated stdout/log values
|
|
1427
|
+
// before property access, just as malformed JSON lines are ignored.
|
|
1428
|
+
if (msg === null || typeof msg !== 'object' || Array.isArray(msg)) return;
|
|
1429
|
+
try {
|
|
1430
|
+
this.dispatchMessage(msg);
|
|
1431
|
+
} catch (error) {
|
|
1432
|
+
const request = msg as { method?: unknown; id?: unknown };
|
|
1433
|
+
this.reportInboundFailure(error, {
|
|
1434
|
+
...(typeof request.method === 'string' ? { event: request.method } : {}),
|
|
1435
|
+
...(typeof request.id === 'string' || typeof request.id === 'number' ? { requestId: request.id } : {}),
|
|
1436
|
+
});
|
|
1188
1437
|
}
|
|
1438
|
+
});
|
|
1439
|
+
}
|
|
1189
1440
|
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1441
|
+
/** Contain synchronous dispatch failures; async RPC handlers own their promises. */
|
|
1442
|
+
private dispatchMessage(msg: JsonRpcRequest | JsonRpcResponse): void {
|
|
1443
|
+
// Is this a response to one of our outbound requests?
|
|
1444
|
+
if ('id' in msg && msg.id != null && !('method' in msg)) {
|
|
1445
|
+
this.handleResponse(msg as JsonRpcResponse);
|
|
1446
|
+
return;
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
// It is an inbound request or notification from the server
|
|
1450
|
+
const request = msg as JsonRpcRequest;
|
|
1451
|
+
|
|
1452
|
+
// MCP's ping, which either side may send: its receiver answers promptly
|
|
1453
|
+
// with an empty result. It's answered as it arrives, before admission and
|
|
1454
|
+
// buffering, since it asks only whether the connection is alive, and a
|
|
1455
|
+
// paused plane mustn't hold that answer. A ping sent as a notification
|
|
1456
|
+
// has nothing to answer. The handshake answers one too.
|
|
1457
|
+
if (request.method === 'ping') {
|
|
1458
|
+
if (request.id != null) this.sendResponse(request.id, {});
|
|
1459
|
+
return;
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
const eventName = typeof request.method === 'string' && Object.hasOwn(McplServerConnection.METHOD_TO_EVENT, request.method)
|
|
1463
|
+
? McplServerConnection.METHOD_TO_EVENT[request.method] : undefined;
|
|
1464
|
+
|
|
1465
|
+
// §7 is removed in 0.5.0: scope/elevate is no longer a method. Answer
|
|
1466
|
+
// rather than hang (§6.6 — a method that will never be answered MUST
|
|
1467
|
+
// return an error).
|
|
1468
|
+
// featureSets/changed is REMOVED in 0.5.0 (§6.7 — it carried a
|
|
1469
|
+
// server-authored change payload, the self-attestation defect; the
|
|
1470
|
+
// need is met by §17's host-diffed manifest fetch). It was still
|
|
1471
|
+
// routed, control-plane classified, and mutating declarations — a
|
|
1472
|
+
// live ungated self-attestation path (PR #79 review blocker 4).
|
|
1473
|
+
if (request.method === McplMethod.FeatureSetsChanged) {
|
|
1474
|
+
if (request.id != null) {
|
|
1475
|
+
this.sendErrorResponse(request.id, -32601, 'featureSets/changed removed in MCPL 0.5.0 (superseded by mcpl/manifestChanged, SPEC §17)');
|
|
1476
|
+
} else {
|
|
1477
|
+
console.error(`[mcpl] ${this.id}: discarded featureSets/changed — removed in 0.5.0 (§6.7/§17)`);
|
|
1209
1478
|
}
|
|
1479
|
+
return;
|
|
1480
|
+
}
|
|
1210
1481
|
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
}
|
|
1215
|
-
return;
|
|
1482
|
+
if (request.method === McplMethod.ScopeElevate) {
|
|
1483
|
+
if (request.id != null) {
|
|
1484
|
+
this.sendErrorResponse(request.id, -32601, 'scope/elevate removed in MCPL 0.5.0 (SPEC §7)');
|
|
1216
1485
|
}
|
|
1486
|
+
return;
|
|
1487
|
+
}
|
|
1217
1488
|
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
this.sendErrorResponse(request.id!, code, message, data),
|
|
1232
|
-
});
|
|
1233
|
-
} else {
|
|
1234
|
-
// Notification — no response expected
|
|
1235
|
-
this.emit(eventName, request.params);
|
|
1236
|
-
}
|
|
1489
|
+
// Positive-grant enforcement (§5.4, §14.1) happens at ADMISSION, in
|
|
1490
|
+
// the emit() override below — the one choke-point that live routing
|
|
1491
|
+
// and staged-buffer flushes share. See the comment there for why
|
|
1492
|
+
// rejecting here, at line receipt, was wrong for staged connections.
|
|
1493
|
+
|
|
1494
|
+
if (!eventName) {
|
|
1495
|
+
// §6.6: a request that will never be answered MUST get an error, so a
|
|
1496
|
+
// request (it has an id) whose method isn't a string, or isn't one this
|
|
1497
|
+
// host handles, is answered -32601. A notification nobody handles is
|
|
1498
|
+
// ignored, as JSON-RPC asks.
|
|
1499
|
+
if (request.id != null) {
|
|
1500
|
+
this.sendErrorResponse(request.id, -32601, 'Method not found');
|
|
1501
|
+
console.error(`[mcpl] ${this.id}: answered -32601 to a request for ${describeMethod(request.method)}, which this host doesn't handle`);
|
|
1237
1502
|
}
|
|
1238
|
-
|
|
1503
|
+
return;
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1506
|
+
// Emit the typed event with params and (for requests) a respond callback
|
|
1507
|
+
if (request.id != null) {
|
|
1508
|
+
// Server expects a response — provide a respond helper
|
|
1509
|
+
this.dispatchInboundEvent(eventName, request.params, {
|
|
1510
|
+
id: request.id,
|
|
1511
|
+
respond: (result: unknown) => this.sendResponse(request.id!, result),
|
|
1512
|
+
respondError: (code: number, message: string, data?: unknown) =>
|
|
1513
|
+
this.sendErrorResponse(request.id!, code, message, data),
|
|
1514
|
+
});
|
|
1515
|
+
} else {
|
|
1516
|
+
// Notification — no response expected
|
|
1517
|
+
this.dispatchInboundEvent(eventName, request.params);
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
|
|
1521
|
+
/** Live delivery and delayed plane flushes share the same containment boundary. */
|
|
1522
|
+
private dispatchInboundEvent(event: string, ...args: unknown[]): void {
|
|
1523
|
+
try {
|
|
1524
|
+
this.emit(event, ...args);
|
|
1525
|
+
} catch (error) {
|
|
1526
|
+
const requestId = (args[1] as { id?: unknown } | undefined)?.id;
|
|
1527
|
+
this.reportInboundFailure(error, {
|
|
1528
|
+
event,
|
|
1529
|
+
...(typeof requestId === 'string' || typeof requestId === 'number' ? { requestId } : {}),
|
|
1530
|
+
});
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
|
|
1534
|
+
/** Report a failure the containment boundary caught, naming the event (or
|
|
1535
|
+
* method) and request it was dispatching, and what failed. The message is
|
|
1536
|
+
* what the framework's 'error' listener traces. */
|
|
1537
|
+
private reportInboundFailure(cause: unknown, context: { event?: string; requestId?: string | number } = {}): void {
|
|
1538
|
+
const where = (show: (text: string) => string): string => (context.event === undefined ? '' : ` for ${show(context.event)}`) +
|
|
1539
|
+
(context.requestId === undefined ? '' : ` (request ${show(String(context.requestId))})`);
|
|
1540
|
+
// The error's message is what the 'error' listener traces, as text a
|
|
1541
|
+
// reader parses, so it is bounded rather than escaped (boundedForLog);
|
|
1542
|
+
// the log line prints the same through log-value.
|
|
1543
|
+
const error = new Error(`MCPL server "${this.id}" inbound dispatch failed${where(boundedForLog)}: ${boundedForLog(describeCause(cause))}`, { cause });
|
|
1544
|
+
console.error(`[mcpl] ${this.id}: inbound dispatch failed${where(logValue)}: ${logDetail(describeCause(cause))}`);
|
|
1545
|
+
this.emitToErrorListeners(error);
|
|
1546
|
+
}
|
|
1547
|
+
|
|
1548
|
+
/**
|
|
1549
|
+
* Give an error to the connection's 'error' listeners, and say whether it
|
|
1550
|
+
* has any. EventEmitter throws an 'error' that nothing listens for, and
|
|
1551
|
+
* from a transport's callback, where these errors arise, nothing catches
|
|
1552
|
+
* that throw, so it ends the process. A bare connection has no listener:
|
|
1553
|
+
* the class is exported, and a probe, a playtest or a harness often attaches
|
|
1554
|
+
* none. So with no listener, the error is the caller's to log, unless it
|
|
1555
|
+
* already has. A listener that throws is caught and logged, with the error
|
|
1556
|
+
* it was handling.
|
|
1557
|
+
*/
|
|
1558
|
+
private emitToErrorListeners(error: Error): boolean {
|
|
1559
|
+
if (this.listenerCount('error') === 0) return false;
|
|
1560
|
+
try { this.emit('error', error); }
|
|
1561
|
+
catch (listenerError) {
|
|
1562
|
+
console.error(
|
|
1563
|
+
`[mcpl] ${this.id}: an 'error' listener failed: ${logDetail(describeCause(listenerError))}` +
|
|
1564
|
+
`, handling ${logDetail(error.message)}`,
|
|
1565
|
+
);
|
|
1566
|
+
}
|
|
1567
|
+
return true;
|
|
1239
1568
|
}
|
|
1240
1569
|
|
|
1241
1570
|
/**
|
|
@@ -1252,10 +1581,17 @@ export class McplServerConnection extends EventEmitter {
|
|
|
1252
1581
|
// re-inject either result because the original dispatch context is gone.
|
|
1253
1582
|
const orphaned = this.orphanedRequests.get(response.id);
|
|
1254
1583
|
this.orphanedRequests.delete(response.id);
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1584
|
+
// A push/render answered after its timeout (RFC-006 §5.3) is reported
|
|
1585
|
+
// with the render's featureSet, key, eventId and, for a channel-scoped
|
|
1586
|
+
// subject, channelId, kept from its request when the timeout fired, so
|
|
1587
|
+
// its discarded answer can be recorded beside its batch's other
|
|
1588
|
+
// coalescing records (§11). It is only reported: the fallback the
|
|
1589
|
+
// timeout materialized stands (§5.4 rule 3). A late JSON-RPC error is
|
|
1590
|
+
// passed on as `error`, so its record can be told from a late result's,
|
|
1591
|
+
// and so is one beside a result, which JSON-RPC forbids: the live path
|
|
1592
|
+
// rejects such an answer as an error.
|
|
1593
|
+
const render = orphaned?.renderParams ?? {};
|
|
1594
|
+
const failure = response.error ? { error: { code: response.error.code, message: response.error.message } } : {};
|
|
1259
1595
|
const result = response.result;
|
|
1260
1596
|
if (result && typeof result === 'object') {
|
|
1261
1597
|
const r = result as { state?: unknown; checkpoint?: unknown };
|
|
@@ -1265,6 +1601,8 @@ export class McplServerConnection extends EventEmitter {
|
|
|
1265
1601
|
method: orphaned?.method,
|
|
1266
1602
|
hadState: r.state !== undefined,
|
|
1267
1603
|
hadCheckpoint: r.checkpoint !== undefined,
|
|
1604
|
+
...render,
|
|
1605
|
+
...failure,
|
|
1268
1606
|
});
|
|
1269
1607
|
}
|
|
1270
1608
|
} else if (orphaned) {
|
|
@@ -1273,6 +1611,8 @@ export class McplServerConnection extends EventEmitter {
|
|
|
1273
1611
|
method: orphaned.method,
|
|
1274
1612
|
hadState: false,
|
|
1275
1613
|
hadCheckpoint: false,
|
|
1614
|
+
...render,
|
|
1615
|
+
...failure,
|
|
1276
1616
|
});
|
|
1277
1617
|
}
|
|
1278
1618
|
return; // Orphaned response — ignore
|
|
@@ -1282,8 +1622,19 @@ export class McplServerConnection extends EventEmitter {
|
|
|
1282
1622
|
if (pending.timer) clearTimeout(pending.timer);
|
|
1283
1623
|
|
|
1284
1624
|
if (response.error) {
|
|
1625
|
+
// describeCause rather than the template's own conversion, as for an
|
|
1626
|
+
// initialize error: the server's code and message can be any JSON
|
|
1627
|
+
// value, and one with no primitive form, such as {"toString":1}, would
|
|
1628
|
+
// throw here, after the request has left pendingRequests and its timer
|
|
1629
|
+
// is cleared, so it would never settle. Both are the server's text, a
|
|
1630
|
+
// code as much as a message, since a server can send a string, so both
|
|
1631
|
+
// are bounded as errors.ts says.
|
|
1285
1632
|
pending.reject(
|
|
1286
|
-
new
|
|
1633
|
+
new McplRequestError(
|
|
1634
|
+
`MCPL server "${this.id}" returned error for ${pending.method}: [${boundedForLog(describeCause(response.error.code))}] ${boundedForLog(describeCause(response.error.message))}`,
|
|
1635
|
+
'error-response',
|
|
1636
|
+
(response.error as { data?: unknown }).data,
|
|
1637
|
+
),
|
|
1287
1638
|
);
|
|
1288
1639
|
} else {
|
|
1289
1640
|
pending.resolve(response.result);
|
|
@@ -1324,7 +1675,8 @@ export class McplServerConnection extends EventEmitter {
|
|
|
1324
1675
|
private setupLifecycle(transport: McplTransport): void {
|
|
1325
1676
|
this.hostCloseRequested = false;
|
|
1326
1677
|
transport.on('error', (err: Error) => {
|
|
1327
|
-
|
|
1678
|
+
const error = new Error(`MCPL server "${this.id}" transport error: ${err.message}`);
|
|
1679
|
+
if (!this.emitToErrorListeners(error)) console.error(`[mcpl] ${this.id}: transport error: ${logDetail(err.message)}`);
|
|
1328
1680
|
});
|
|
1329
1681
|
|
|
1330
1682
|
transport.on('close', (info: TransportCloseInfo) => {
|
|
@@ -1336,8 +1688,9 @@ export class McplServerConnection extends EventEmitter {
|
|
|
1336
1688
|
for (const [id, pending] of this.pendingRequests) {
|
|
1337
1689
|
if (pending.timer) clearTimeout(pending.timer);
|
|
1338
1690
|
pending.reject(
|
|
1339
|
-
new
|
|
1340
|
-
`MCPL server "${this.id}" disconnected unexpectedly (code=${info.code ?? 'n/a'}, signal=${info.signal ?? 'n/a'}, reason=${info
|
|
1691
|
+
new McplRequestError(
|
|
1692
|
+
`MCPL server "${this.id}" disconnected unexpectedly (code=${info.code ?? 'n/a'}, signal=${info.signal ?? 'n/a'}, reason=${closeReasonText(info)}) while awaiting ${pending.method} (id=${id})`,
|
|
1693
|
+
'no-response',
|
|
1341
1694
|
),
|
|
1342
1695
|
);
|
|
1343
1696
|
}
|
|
@@ -1355,6 +1708,7 @@ export class McplServerConnection extends EventEmitter {
|
|
|
1355
1708
|
code: info.code ?? null,
|
|
1356
1709
|
signal: info.signal ?? null,
|
|
1357
1710
|
reason: info.reason ?? (byHost ? 'closed by host' : undefined),
|
|
1711
|
+
...(info.reasonFromPeer ? { reasonFromPeer: true } : {}),
|
|
1358
1712
|
byHost,
|
|
1359
1713
|
};
|
|
1360
1714
|
this.emit('close', closeInfo.code, closeInfo.signal, closeInfo);
|