@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
|
@@ -9,14 +9,45 @@
|
|
|
9
9
|
* stdio and WebSocket behave identically above the transport seam.
|
|
10
10
|
*/
|
|
11
11
|
import { EventEmitter } from 'node:events';
|
|
12
|
-
import { openTransport } from './transport.js';
|
|
12
|
+
import { openTransport, STDERR_END_WAIT_MS } from './transport.js';
|
|
13
13
|
import { maskNegotiatedCapabilities } from './capability-mask.js';
|
|
14
14
|
import { CapabilityGrant, expandAdvertisementShorthand } from './capability-grant.js';
|
|
15
|
-
import { CAPABILITY_DISABLED } from './errors.js';
|
|
15
|
+
import { CAPABILITY_DISABLED, boundedForLog, describeCause } from './errors.js';
|
|
16
|
+
import { logDetail, logValue } from './log-value.js';
|
|
16
17
|
import { McplMethod } from './types.js';
|
|
17
18
|
/** Timeout for the initialize handshake in milliseconds.
|
|
18
19
|
* Spring Boot + JDA servers can take 5-10s to boot, so 30s is safe. */
|
|
19
20
|
const INITIALIZE_TIMEOUT_MS = 30_000;
|
|
21
|
+
/** A failed connect's `stderrTail`, the last of the server's stderr that its
|
|
22
|
+
* handshake's error keeps, when there is one. */
|
|
23
|
+
export function stderrTailOf(error) {
|
|
24
|
+
const tail = error?.stderrTail;
|
|
25
|
+
return typeof tail === 'string' && tail !== '' ? tail : undefined;
|
|
26
|
+
}
|
|
27
|
+
/** For the host's own log line about a failed connect: the server's stderr
|
|
28
|
+
* that the error keeps as `stderrTail`, one marked line per line of it,
|
|
29
|
+
* each through log-value, since it's the server's text. '' when there's
|
|
30
|
+
* none. */
|
|
31
|
+
export function withStderr(error) {
|
|
32
|
+
const tail = stderrTailOf(error);
|
|
33
|
+
if (tail === undefined)
|
|
34
|
+
return '';
|
|
35
|
+
return '. The last of its stderr:' + tail.split('\n').map((line) => `\n stderr: ${logDetail(line)}`).join('');
|
|
36
|
+
}
|
|
37
|
+
/** A transport close's reason, as an error message gives it: the transport's
|
|
38
|
+
* own words. A WebSocket peer's close reason is the server's text
|
|
39
|
+
* (`reasonFromPeer`), so an error gives the words the transport uses for a
|
|
40
|
+
* close without one, as `mcpl:server-closed` leaves that text out. A
|
|
41
|
+
* WebSocket close's code, a number, says what the server meant (4001: a
|
|
42
|
+
* refused credential), with or without a reason, so each error gives it too:
|
|
43
|
+
* a pending request's error has `code=`, and the handshake's adds it for any
|
|
44
|
+
* WebSocket close, since a close before the handshake completes reaches no
|
|
45
|
+
* 'close' event. A stdio child's exit reads as before. */
|
|
46
|
+
function closeReasonText(info) {
|
|
47
|
+
if (info.reasonFromPeer)
|
|
48
|
+
return 'websocket closed';
|
|
49
|
+
return info.reason ?? 'unknown';
|
|
50
|
+
}
|
|
20
51
|
/** Default per-request timeout in milliseconds (see McplServerConfig.requestTimeoutMs).
|
|
21
52
|
* A live-but-wedged server (accepts requests, never answers, never closes its
|
|
22
53
|
* transport) would otherwise freeze the awaiting agent turn forever — no
|
|
@@ -25,6 +56,39 @@ const INITIALIZE_TIMEOUT_MS = 30_000;
|
|
|
25
56
|
const DEFAULT_REQUEST_TIMEOUT_MS = 60_000;
|
|
26
57
|
/** MCP protocol version used in the initialize handshake. */
|
|
27
58
|
const MCP_PROTOCOL_VERSION = '2024-11-05';
|
|
59
|
+
/**
|
|
60
|
+
* Why a request to an MCPL server produced no result, as far as the host can
|
|
61
|
+
* know it. Messages are unchanged from plain errors; the `outcome` makes the
|
|
62
|
+
* difference between "never left the host" and "left, and no answer came
|
|
63
|
+
* back" a fact a caller can act on instead of a string to match:
|
|
64
|
+
* - `not-sent`: the request was refused before anything was written (the
|
|
65
|
+
* connection was already closed);
|
|
66
|
+
* - `error-response`: the server answered with a JSON-RPC error (it may have
|
|
67
|
+
* acted before failing; the error alone does not say);
|
|
68
|
+
* - `no-response`: the request was handed to the transport and no answer
|
|
69
|
+
* came back (timeout, or the connection closed while awaiting). It does
|
|
70
|
+
* not prove the request reached the server — the transport can decline or
|
|
71
|
+
* drop a write — only that the host can no longer say it didn't.
|
|
72
|
+
*/
|
|
73
|
+
export class McplRequestError extends Error {
|
|
74
|
+
outcome;
|
|
75
|
+
data;
|
|
76
|
+
constructor(message, outcome,
|
|
77
|
+
/** The JSON-RPC error's `data`, verbatim, when the server supplied one
|
|
78
|
+
* (e.g. which parts of a multi-part send were posted). */
|
|
79
|
+
data) {
|
|
80
|
+
super(message);
|
|
81
|
+
this.outcome = outcome;
|
|
82
|
+
this.data = data;
|
|
83
|
+
this.name = 'McplRequestError';
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/** A request's method for a log line, whatever the server sent there. */
|
|
87
|
+
function describeMethod(method) {
|
|
88
|
+
return typeof method === 'string'
|
|
89
|
+
? `method ${logValue(method)}`
|
|
90
|
+
: `a method of type ${method === null ? 'null' : typeof method}`;
|
|
91
|
+
}
|
|
28
92
|
/**
|
|
29
93
|
* McplServerConnection manages a single JSON-RPC 2.0 connection to an
|
|
30
94
|
* MCPL server over stdio. Use the static `connect()` factory to create
|
|
@@ -39,8 +103,13 @@ const MCP_PROTOCOL_VERSION = '2024-11-05';
|
|
|
39
103
|
* - `'channels-incoming'` — Server sent `channels/incoming`
|
|
40
104
|
* - `'error'` — Connection-level error
|
|
41
105
|
* - `'close'` — Connection closed: `(code, signal, info: McplConnectionCloseInfo)`
|
|
42
|
-
* - `'connect-failed'` — Initial connect failed; background retry scheduled
|
|
43
|
-
*
|
|
106
|
+
* - `'connect-failed'` — Initial connect failed; background retry scheduled:
|
|
107
|
+
* `{ error, stderrTail?, attempt }`
|
|
108
|
+
* - `'reconnect-failed'` — A background reconnect attempt failed; next retry scheduled:
|
|
109
|
+
* `{ error, stderrTail?, attempt }`. `stderrTail` is the last of the
|
|
110
|
+
* server's stderr when its handshake failed by its transport closing, a
|
|
111
|
+
* transport error or its timeout and it had written any; `error` never
|
|
112
|
+
* carries it.
|
|
44
113
|
* - `'reconnect'` — Background reconnect succeeded
|
|
45
114
|
*/
|
|
46
115
|
export class McplServerConnection extends EventEmitter {
|
|
@@ -142,6 +211,9 @@ export class McplServerConnection extends EventEmitter {
|
|
|
142
211
|
reconnectPromise = null;
|
|
143
212
|
/** Per-request timeout in ms (0 disables). See McplServerConfig.requestTimeoutMs. */
|
|
144
213
|
requestTimeoutMs = DEFAULT_REQUEST_TIMEOUT_MS;
|
|
214
|
+
/** The deadline a channels/publish or channels/open request keeps when
|
|
215
|
+
* requestTimeoutMs is 0 (see sendChannelsPublish). */
|
|
216
|
+
publishDeadlineMs = DEFAULT_REQUEST_TIMEOUT_MS;
|
|
145
217
|
// Event buffering: control-plane traffic can be released independently from
|
|
146
218
|
// inference-bearing data-plane traffic. This lets a server finish its own
|
|
147
219
|
// registration (and answer host tools/call requests) while startup/reconnect
|
|
@@ -149,15 +221,24 @@ export class McplServerConnection extends EventEmitter {
|
|
|
149
221
|
controlPlaneReady = false;
|
|
150
222
|
dataPlaneReady = false;
|
|
151
223
|
bufferedEvents = [];
|
|
152
|
-
/**
|
|
153
|
-
*
|
|
154
|
-
|
|
224
|
+
/** How many of bufferedEvents are server→host requests, each holding a
|
|
225
|
+
* responder its server waits on. Every change to bufferedEvents keeps it. */
|
|
226
|
+
heldRequests = 0;
|
|
227
|
+
/** Cap on held notifications (responder-less events) during a plane pause
|
|
228
|
+
* (issue #122), counted apart from requests: past it, the oldest held
|
|
229
|
+
* notification is dropped. */
|
|
230
|
+
static MAX_HELD_NOTIFICATIONS = 1000;
|
|
231
|
+
/** Budget of held requests during a plane pause (#387), counted apart from
|
|
232
|
+
* notifications: past it, a request is refused at once, never dropped. It
|
|
233
|
+
* bounds a server that pipelines requests without waiting for answers. A
|
|
234
|
+
* server that doesn't send a refused request again loses it (discord-mcpl
|
|
235
|
+
* doesn't), so the budget sits far above the notifications' cap, to leave
|
|
236
|
+
* a busy server's long pause room. */
|
|
237
|
+
static MAX_HELD_REQUESTS = 10_000;
|
|
155
238
|
droppedBufferedEvents = 0;
|
|
156
|
-
/**
|
|
157
|
-
*
|
|
158
|
-
|
|
159
|
-
* NEW arrivals during a pause, not churn from control-plane flushes). */
|
|
160
|
-
flushDepth = 0;
|
|
239
|
+
/** Requests refused at the budget since the planes last opened (ready()),
|
|
240
|
+
* so each pause's first refusal is logged. */
|
|
241
|
+
refusedHeldRequests = 0;
|
|
161
242
|
// Reconnect state (adapted from Anarchid/agent-framework@mcpl-module-proto)
|
|
162
243
|
config = null;
|
|
163
244
|
hostCapabilities = null;
|
|
@@ -173,6 +254,12 @@ export class McplServerConnection extends EventEmitter {
|
|
|
173
254
|
get willReconnect() {
|
|
174
255
|
return this.reconnectEnabled;
|
|
175
256
|
}
|
|
257
|
+
/** Closed with no reconnect to come: after close(), whether or not its
|
|
258
|
+
* transport close succeeded, or a drop with reconnect off. A connection
|
|
259
|
+
* between retries keeps reconnectEnabled, so it isn't closed for good. */
|
|
260
|
+
get closedForGood() {
|
|
261
|
+
return this.closed && !this.reconnectEnabled;
|
|
262
|
+
}
|
|
176
263
|
/**
|
|
177
264
|
* Private constructor. Use `McplServerConnection.connect()` instead.
|
|
178
265
|
*/
|
|
@@ -193,52 +280,60 @@ export class McplServerConnection extends EventEmitter {
|
|
|
193
280
|
* Mark the connection as ready — flushes any events that arrived between
|
|
194
281
|
* construction (when setupMessageRouting starts emitting) and now (when
|
|
195
282
|
* the caller has attached listeners via wireMcplEvents).
|
|
283
|
+
*
|
|
284
|
+
* Does nothing once the connection is closed for good. Its policy was reset
|
|
285
|
+
* when it closed, so what it held that needs a grant would be refused, and a
|
|
286
|
+
* closed connection sends no response, so nothing it held could be answered.
|
|
287
|
+
* Only what needs no grant would pass, to listeners of a server that won't
|
|
288
|
+
* be served again. A connection between retries isn't closed for good: what
|
|
289
|
+
* it held, such as a reconnect stub's connect-failed, still reaches its
|
|
290
|
+
* listeners.
|
|
196
291
|
*/
|
|
197
292
|
ready() {
|
|
293
|
+
if (this.closedForGood)
|
|
294
|
+
return;
|
|
198
295
|
this.controlPlaneReady = true;
|
|
199
296
|
this.dataPlaneReady = true;
|
|
200
297
|
const pending = this.bufferedEvents;
|
|
201
298
|
this.bufferedEvents = [];
|
|
299
|
+
// The cap's drops are counted per pause: this flush ends one, so its line
|
|
300
|
+
// reports that pause's drops, and the next pause counts (and logs) its own.
|
|
301
|
+
const dropped = this.droppedBufferedEvents;
|
|
302
|
+
this.droppedBufferedEvents = 0;
|
|
303
|
+
this.heldRequests = 0;
|
|
304
|
+
this.refusedHeldRequests = 0;
|
|
202
305
|
if (pending.length > 200) {
|
|
203
306
|
console.error(`[mcpl] ${this.id}: flushing ${pending.length} buffered event(s) synchronously ` +
|
|
204
|
-
`(long pause backlog${
|
|
307
|
+
`(long pause backlog${dropped > 0 ? `; ${dropped} dropped at cap` : ''})`);
|
|
205
308
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
// snapshot is being flushed; later data items must observe that pause.
|
|
212
|
-
this.emit(event, ...args);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
finally {
|
|
216
|
-
this.flushDepth--;
|
|
309
|
+
for (const { event, args } of pending) {
|
|
310
|
+
// Re-enter the gate for every buffered item. A control handler (notably
|
|
311
|
+
// tools/list_changed) may install a newer data-plane barrier while this
|
|
312
|
+
// snapshot is being flushed; later data items must observe that pause.
|
|
313
|
+
this.dispatchInboundEvent(event, ...args);
|
|
217
314
|
}
|
|
218
315
|
}
|
|
219
316
|
/**
|
|
220
317
|
* Release only server-establishment and lifecycle/control traffic. Responses
|
|
221
318
|
* to host requests are never event-buffered, so tools/list and tools/call
|
|
222
319
|
* responses remain live as well. Inference-bearing requests stay queued in
|
|
223
|
-
* their original relative order until {@link ready} is called.
|
|
320
|
+
* their original relative order until {@link ready} is called. Like
|
|
321
|
+
* {@link ready}, it does nothing once the connection is closed for good.
|
|
224
322
|
*/
|
|
225
323
|
readyControlPlane() {
|
|
324
|
+
if (this.closedForGood)
|
|
325
|
+
return;
|
|
226
326
|
this.controlPlaneReady = true;
|
|
227
327
|
const pending = this.bufferedEvents;
|
|
228
328
|
this.bufferedEvents = [];
|
|
229
|
-
this.
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
this.emit(item.event, ...item.args);
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
finally {
|
|
241
|
-
this.flushDepth--;
|
|
329
|
+
this.heldRequests = 0;
|
|
330
|
+
for (const item of pending) {
|
|
331
|
+
// Re-enter the ADMISSION gate (this.emit), never super.emit: control
|
|
332
|
+
// events include channels-register/changed, which are grant-gated —
|
|
333
|
+
// the old direct flush bypassed positive-grant enforcement entirely
|
|
334
|
+
// (PR #79 review blocker 3). Data-plane items re-buffer in order via
|
|
335
|
+
// the same call, since dataPlaneReady is still false.
|
|
336
|
+
this.dispatchInboundEvent(item.event, ...item.args);
|
|
242
337
|
}
|
|
243
338
|
}
|
|
244
339
|
/**
|
|
@@ -291,41 +386,74 @@ export class McplServerConnection extends EventEmitter {
|
|
|
291
386
|
responder.respondError(CAPABILITY_DISABLED, `${name} rejected: capability "${requiredCap}" ${phase}`, { capability: requiredCap });
|
|
292
387
|
}
|
|
293
388
|
else {
|
|
294
|
-
console.error(`[mcpl] ${this.id}: discarded ${name} — "${requiredCap}" ${phase}`);
|
|
389
|
+
console.error(`[mcpl] ${this.id}: discarded ${logValue(name)} — "${requiredCap}" ${phase}`);
|
|
295
390
|
}
|
|
296
391
|
return true;
|
|
297
392
|
}
|
|
393
|
+
// §6.6: a request that will never be answered MUST get an error. A
|
|
394
|
+
// request whose event nothing on this host listens for would never be.
|
|
395
|
+
const request = args[1];
|
|
396
|
+
if (typeof request?.respondError === 'function' && this.listenerCount(event) === 0) {
|
|
397
|
+
request.respondError(-32601, 'Method not found');
|
|
398
|
+
console.error(`[mcpl] ${this.id}: answered -32601 to ${logValue(name)}, which nothing on this host handles`);
|
|
399
|
+
return true;
|
|
400
|
+
}
|
|
401
|
+
// mcpl/manifestChanged (§17.3) and tools/list_changed are notifications.
|
|
402
|
+
// Sent as a request, either is answered with an empty result as it's
|
|
403
|
+
// admitted, and passed on as the notification is, with no responder:
|
|
404
|
+
// the host acts on it the same way, so the answer doesn't depend on what
|
|
405
|
+
// the refresh does, and it's written before any request the refresh
|
|
406
|
+
// sends. This is where live routing and buffer flushes meet, so a request
|
|
407
|
+
// held while its plane is closed is answered only when it's let through,
|
|
408
|
+
// never by a startup that fails first.
|
|
409
|
+
if ((name === 'manifest-changed' || name === 'tools-list-changed') && typeof request?.respond === 'function') {
|
|
410
|
+
request.respond({});
|
|
411
|
+
return super.emit(event, args[0]);
|
|
412
|
+
}
|
|
298
413
|
return super.emit(event, ...args);
|
|
299
414
|
}
|
|
300
|
-
//
|
|
301
|
-
//
|
|
302
|
-
//
|
|
303
|
-
// holds a
|
|
304
|
-
//
|
|
305
|
-
//
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
415
|
+
// Held until the plane opens. A long pause (a quiesce, say) on a busy or a
|
|
416
|
+
// runaway server would otherwise grow this array without bound, so
|
|
417
|
+
// requests and notifications each have a bound, counted apart. A request
|
|
418
|
+
// holds a responder its server waits on, and dropping it would strand that
|
|
419
|
+
// call, so past MAX_HELD_REQUESTS (#387) it's refused at once with -32000,
|
|
420
|
+
// the code of the host's other transient refusals, and its server can send
|
|
421
|
+
// it again. A notification has no one to tell, so past
|
|
422
|
+
// MAX_HELD_NOTIFICATIONS (issue #122) the oldest held notification is
|
|
423
|
+
// dropped to make room. A flush takes the whole buffer and zeroes its
|
|
424
|
+
// count, so what it holds again was admitted within these bounds and
|
|
425
|
+
// stays within them.
|
|
426
|
+
const responder = args[1];
|
|
427
|
+
const isRequest = McplServerConnection.hasResponder({ args });
|
|
428
|
+
if (isRequest && this.heldRequests >= McplServerConnection.MAX_HELD_REQUESTS) {
|
|
429
|
+
this.refusedHeldRequests++;
|
|
430
|
+
if (this.refusedHeldRequests % 100 === 1) {
|
|
431
|
+
console.error(`[mcpl] ${this.id}: held-request budget (${McplServerConnection.MAX_HELD_REQUESTS}) — ` +
|
|
432
|
+
`refused ${this.refusedHeldRequests} request(s) with -32000 while the plane is paused`);
|
|
433
|
+
}
|
|
434
|
+
responder?.respondError?.(-32000, `the host is busy: ${McplServerConnection.MAX_HELD_REQUESTS} of this server's requests are already waiting; send this one again later`);
|
|
435
|
+
return true;
|
|
436
|
+
}
|
|
437
|
+
if (!isRequest && this.bufferedEvents.length - this.heldRequests >= McplServerConnection.MAX_HELD_NOTIFICATIONS) {
|
|
438
|
+
this.droppedBufferedEvents++;
|
|
439
|
+
if (this.droppedBufferedEvents % 100 === 1) {
|
|
440
|
+
console.error(`[mcpl] ${this.id}: buffered-event cap (${McplServerConnection.MAX_HELD_NOTIFICATIONS}) — ` +
|
|
441
|
+
`dropped ${this.droppedBufferedEvents} responder-less event(s) while the plane is paused`);
|
|
324
442
|
}
|
|
443
|
+
const oldest = this.bufferedEvents.findIndex((item) => !McplServerConnection.hasResponder(item));
|
|
444
|
+
if (oldest >= 0)
|
|
445
|
+
this.bufferedEvents.splice(oldest, 1);
|
|
325
446
|
}
|
|
326
447
|
this.bufferedEvents.push({ event: name, args });
|
|
448
|
+
if (isRequest)
|
|
449
|
+
this.heldRequests++;
|
|
327
450
|
return true;
|
|
328
451
|
}
|
|
452
|
+
/** A buffered server→host request: it carries a responder its server waits on. */
|
|
453
|
+
static hasResponder(item) {
|
|
454
|
+
const responder = item.args[1];
|
|
455
|
+
return typeof responder?.respond === 'function';
|
|
456
|
+
}
|
|
329
457
|
/** Event-name form of METHOD_TO_REQUIRED_CAPABILITY, for admission-time
|
|
330
458
|
* enforcement in emit(). */
|
|
331
459
|
static EVENT_TO_REQUIRED_CAPABILITY = {
|
|
@@ -383,8 +511,9 @@ export class McplServerConnection extends EventEmitter {
|
|
|
383
511
|
connection.mcpToolsAdvertised = mcpToolsAdvertised;
|
|
384
512
|
connection.allowHostCommands = config.allowHostCommands === true;
|
|
385
513
|
connection.requestTimeoutMs = config.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
386
|
-
// Store config for reconnection
|
|
387
|
-
|
|
514
|
+
// Store config for reconnection. Only `true` turns reconnect on, as at
|
|
515
|
+
// every other reader of it.
|
|
516
|
+
if (config.reconnect === true) {
|
|
388
517
|
connection.config = config;
|
|
389
518
|
connection.hostCapabilities = hostCapabilities;
|
|
390
519
|
connection.reconnectEnabled = true;
|
|
@@ -402,6 +531,15 @@ export class McplServerConnection extends EventEmitter {
|
|
|
402
531
|
*/
|
|
403
532
|
static async handshake(config, hostCapabilities) {
|
|
404
533
|
const transport = await openTransport(config);
|
|
534
|
+
// Once the handshake stops listening for 'error', this logs what the
|
|
535
|
+
// transport reports, until the handshake hands the transport on, or for
|
|
536
|
+
// good if the handshake fails. EventEmitter throws an 'error' that has no
|
|
537
|
+
// listener, and from an I/O callback nothing catches it. A malformed
|
|
538
|
+
// WebSocket frame that arrives with the initialize response, or while a
|
|
539
|
+
// failed handshake's close() runs, is such an error.
|
|
540
|
+
const logAfterSettled = (err) => {
|
|
541
|
+
console.error(`[mcpl] ${config.id}: transport error after the handshake settled: ${err.message}`);
|
|
542
|
+
};
|
|
405
543
|
try {
|
|
406
544
|
const initId = 0; // use id=0 for the handshake
|
|
407
545
|
const initRequest = {
|
|
@@ -417,10 +555,20 @@ export class McplServerConnection extends EventEmitter {
|
|
|
417
555
|
// Await the initialize response, racing an early transport close/error and
|
|
418
556
|
// a timeout. All three paths clean up their listeners.
|
|
419
557
|
const { mcpl: rawCapabilities, mcpToolsAdvertised } = await new Promise((resolve, reject) => {
|
|
558
|
+
// When the transport fails, the end of the server's stderr often says
|
|
559
|
+
// why, such as a missing token or a crash at startup. It goes on the
|
|
560
|
+
// error as `stderrTail`, never into the message: an error's message
|
|
561
|
+
// travels to traces and tool results, and a server's stderr is its
|
|
562
|
+
// own text, which can hold a credential.
|
|
563
|
+
const failed = (failure) => {
|
|
564
|
+
const tail = transport.stderrTail.trimEnd();
|
|
565
|
+
return Object.assign(new Error(failure), tail ? { stderrTail: tail } : {});
|
|
566
|
+
};
|
|
420
567
|
const cleanup = () => {
|
|
421
568
|
transport.off('line', onLine);
|
|
422
569
|
transport.off('close', onClose);
|
|
423
570
|
transport.off('error', onError);
|
|
571
|
+
transport.on('error', logAfterSettled);
|
|
424
572
|
clearTimeout(timer);
|
|
425
573
|
};
|
|
426
574
|
const onLine = (line) => {
|
|
@@ -431,11 +579,32 @@ export class McplServerConnection extends EventEmitter {
|
|
|
431
579
|
catch {
|
|
432
580
|
return; // Ignore non-JSON lines (e.g. logback output from Java servers)
|
|
433
581
|
}
|
|
582
|
+
if (msg === null || typeof msg !== 'object' || Array.isArray(msg))
|
|
583
|
+
return;
|
|
584
|
+
// A request or a notification from the server is never the
|
|
585
|
+
// initialize response, whatever its id: a server's own ids can start
|
|
586
|
+
// at 0, this handshake's. MCP lets a server ping before
|
|
587
|
+
// initialization completes, and the ping gets its empty result, as
|
|
588
|
+
// on a connected transport. Anything else it sends now is ignored.
|
|
589
|
+
if ('method' in msg) {
|
|
590
|
+
const request = msg;
|
|
591
|
+
if (request.method === 'ping' && request.id != null) {
|
|
592
|
+
transport.writeLine(JSON.stringify({ jsonrpc: '2.0', id: request.id, result: {} }));
|
|
593
|
+
}
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
434
596
|
if (msg.id !== initId)
|
|
435
597
|
return;
|
|
436
598
|
cleanup();
|
|
437
599
|
if (msg.error) {
|
|
438
|
-
|
|
600
|
+
// describeCause rather than the template's own conversion: the
|
|
601
|
+
// server's `message` can be any JSON value, and one that has no
|
|
602
|
+
// primitive form, such as {"toString":1}, would throw out of this
|
|
603
|
+
// listener after cleanup() has cleared the timeout: an uncaught
|
|
604
|
+
// exception, which ends a host that doesn't catch them, and a
|
|
605
|
+
// handshake left to wait forever. It's the server's text in an
|
|
606
|
+
// error's message, so it's bounded as errors.ts says.
|
|
607
|
+
reject(new Error(`MCPL server "${config.id}" initialize error: ${boundedForLog(describeCause(msg.error.message))}`));
|
|
439
608
|
return;
|
|
440
609
|
}
|
|
441
610
|
const result = msg.result;
|
|
@@ -451,15 +620,22 @@ export class McplServerConnection extends EventEmitter {
|
|
|
451
620
|
};
|
|
452
621
|
const onClose = (info) => {
|
|
453
622
|
cleanup();
|
|
454
|
-
|
|
623
|
+
const code = transport.kind === 'websocket' && typeof info.code === 'number' ? `, code ${info.code}` : '';
|
|
624
|
+
const failure = `MCPL server "${config.id}" transport closed before handshake completed (${closeReasonText(info)}${code})`;
|
|
625
|
+
// The close comes at a stdio child's exit, which Node can emit before
|
|
626
|
+
// it has read the last of the child's stderr, or when the host closes
|
|
627
|
+
// the transport, which then ends the child. The tail is taken once
|
|
628
|
+
// stderr has ended, waiting at most STDERR_END_WAIT_MS. A WebSocket
|
|
629
|
+
// transport has no stderr to wait for.
|
|
630
|
+
void transport.stderrEnded(STDERR_END_WAIT_MS).then(() => reject(failed(failure)));
|
|
455
631
|
};
|
|
456
632
|
const onError = (err) => {
|
|
457
633
|
cleanup();
|
|
458
|
-
reject(
|
|
634
|
+
reject(failed(`MCPL server "${config.id}" transport error during handshake: ${err.message}`));
|
|
459
635
|
};
|
|
460
636
|
const timer = setTimeout(() => {
|
|
461
637
|
cleanup();
|
|
462
|
-
reject(
|
|
638
|
+
reject(failed(`MCPL server "${config.id}" initialize handshake timed out`));
|
|
463
639
|
}, INITIALIZE_TIMEOUT_MS);
|
|
464
640
|
transport.on('line', onLine);
|
|
465
641
|
transport.on('close', onClose);
|
|
@@ -478,8 +654,12 @@ export class McplServerConnection extends EventEmitter {
|
|
|
478
654
|
// had never been advertised (hooks, streaming, queries all read this).
|
|
479
655
|
const { capabilities: scoped, dropped } = maskNegotiatedCapabilities(capabilities, config);
|
|
480
656
|
if (dropped.length > 0) {
|
|
481
|
-
console.error(`MCPL server "${config.id}" capabilities masked by host config: ${dropped.join(', ')}`);
|
|
657
|
+
console.error(`MCPL server "${config.id}" capabilities masked by host config: ${dropped.map(logValue).join(', ')}`);
|
|
482
658
|
}
|
|
659
|
+
// The caller wires the transport, or keeps it for close() with a
|
|
660
|
+
// listener of its own, in the continuation of this return, before any
|
|
661
|
+
// I/O callback can emit.
|
|
662
|
+
transport.off('error', logAfterSettled);
|
|
483
663
|
return { transport, capabilities: scoped, droppedCapabilities: new Set(dropped), mcpToolsAdvertised };
|
|
484
664
|
}
|
|
485
665
|
catch (err) {
|
|
@@ -499,16 +679,17 @@ export class McplServerConnection extends EventEmitter {
|
|
|
499
679
|
return await McplServerConnection.connect(config, hostCapabilities);
|
|
500
680
|
}
|
|
501
681
|
catch (error) {
|
|
502
|
-
if (
|
|
682
|
+
if (config.reconnect !== true) {
|
|
503
683
|
throw error;
|
|
504
684
|
}
|
|
505
685
|
// Non-blocking start: create a disconnected stub that will reconnect in background
|
|
506
|
-
console.error(`MCPL server "${config.id}" initial connect failed, will retry
|
|
686
|
+
console.error(`MCPL server "${config.id}" initial connect failed, will retry: ${error.message}${withStderr(error)}`);
|
|
507
687
|
const stub = McplServerConnection.createDisconnectedStub(config, hostCapabilities);
|
|
508
688
|
// Surface the initial failure. The event is buffered by the emit()
|
|
509
689
|
// override until the host wires listeners and calls ready(), so it is
|
|
510
690
|
// not lost in the window before wireMcplEvents runs.
|
|
511
|
-
|
|
691
|
+
const stderrTail = stderrTailOf(error);
|
|
692
|
+
stub.emit('connect-failed', { error: error.message, ...(stderrTail ? { stderrTail } : {}), attempt: 0 });
|
|
512
693
|
return stub;
|
|
513
694
|
}
|
|
514
695
|
}
|
|
@@ -587,9 +768,13 @@ export class McplServerConnection extends EventEmitter {
|
|
|
587
768
|
sendStateRollback(params) {
|
|
588
769
|
return this.sendRequest(McplMethod.StateRollback, params);
|
|
589
770
|
}
|
|
590
|
-
/** Send `channels/open` request and await result.
|
|
771
|
+
/** Send `channels/open` request and await result. It keeps a deadline as
|
|
772
|
+
* channels/publish does: a delivery opens a closed channel before it
|
|
773
|
+
* publishes, so an open that is never answered would hold the delivery,
|
|
774
|
+
* and the turn that waits for it, for good. */
|
|
591
775
|
sendChannelsOpen(params) {
|
|
592
|
-
|
|
776
|
+
const timeoutMs = this.requestTimeoutMs > 0 ? this.requestTimeoutMs : this.publishDeadlineMs;
|
|
777
|
+
return this.sendRequest(McplMethod.ChannelsOpen, params, { timeoutMs });
|
|
593
778
|
}
|
|
594
779
|
/** Send `channels/close` request and await result. */
|
|
595
780
|
sendChannelsClose(params) {
|
|
@@ -607,13 +792,20 @@ export class McplServerConnection extends EventEmitter {
|
|
|
607
792
|
* Send `channels/publish`.
|
|
608
793
|
* May be sent as a request (if an ACK is desired) or notification.
|
|
609
794
|
* When `params.stream` is true, sends as a notification (no ACK).
|
|
795
|
+
*
|
|
796
|
+
* A request always has a deadline: the server's requestTimeoutMs, or
|
|
797
|
+
* publishDeadlineMs when that is 0 (disabled). A publish is a side effect
|
|
798
|
+
* whose outcome the resident is told and a held draft's attempt records,
|
|
799
|
+
* so one that is never answered would hold both open for good. Its expiry
|
|
800
|
+
* is a no-response, which the caller reads as unknown.
|
|
610
801
|
*/
|
|
611
802
|
sendChannelsPublish(params) {
|
|
612
803
|
if (params.stream) {
|
|
613
804
|
this.sendNotification(McplMethod.ChannelsPublish, params);
|
|
614
805
|
return Promise.resolve();
|
|
615
806
|
}
|
|
616
|
-
|
|
807
|
+
const timeoutMs = this.requestTimeoutMs > 0 ? this.requestTimeoutMs : this.publishDeadlineMs;
|
|
808
|
+
return this.sendRequest(McplMethod.ChannelsPublish, params, { timeoutMs });
|
|
617
809
|
}
|
|
618
810
|
/** Send `channels/outgoing/chunk` notification. */
|
|
619
811
|
sendChannelsOutgoingChunk(params) {
|
|
@@ -689,7 +881,7 @@ export class McplServerConnection extends EventEmitter {
|
|
|
689
881
|
for (const [id, pending] of this.pendingRequests) {
|
|
690
882
|
if (pending.timer)
|
|
691
883
|
clearTimeout(pending.timer);
|
|
692
|
-
pending.reject(new
|
|
884
|
+
pending.reject(new McplRequestError(`Connection to MCPL server "${this.id}" closed while awaiting response for ${pending.method} (id=${id})`, 'no-response'));
|
|
693
885
|
}
|
|
694
886
|
this.pendingRequests.clear();
|
|
695
887
|
this.orphanedRequests.clear();
|
|
@@ -699,7 +891,8 @@ export class McplServerConnection extends EventEmitter {
|
|
|
699
891
|
const attempt = Promise.resolve().then(async () => {
|
|
700
892
|
// An already opened handshake owns a transport too. It hands that
|
|
701
893
|
// transport back without admission once reconnect has been disabled.
|
|
702
|
-
//
|
|
894
|
+
// Only the registry's closeAll bounds its caller's wait for this; retry
|
|
895
|
+
// reuses this real close attempt.
|
|
703
896
|
if (this.reconnectPromise)
|
|
704
897
|
await this.reconnectPromise;
|
|
705
898
|
if (this.transport)
|
|
@@ -797,6 +990,13 @@ export class McplServerConnection extends EventEmitter {
|
|
|
797
990
|
// The prior transport was disconnected before this retry began. Keep
|
|
798
991
|
// the fresh, unadmitted transport owned by close(), including on a
|
|
799
992
|
// failed transport cleanup, instead of reviving a stopped connection.
|
|
993
|
+
// It isn't wired, and the handshake has removed its own listeners, so
|
|
994
|
+
// an error it reports from here on, such as a malformed frame from a
|
|
995
|
+
// WebSocket server while close() closes it, is logged here rather than
|
|
996
|
+
// thrown where nothing catches it.
|
|
997
|
+
transport.on('error', (err) => {
|
|
998
|
+
console.error(`[mcpl] ${this.id}: a transport kept for close() reported an error: ${err.message}`);
|
|
999
|
+
});
|
|
800
1000
|
this.transport = transport;
|
|
801
1001
|
return;
|
|
802
1002
|
}
|
|
@@ -820,9 +1020,10 @@ export class McplServerConnection extends EventEmitter {
|
|
|
820
1020
|
this.emit('reconnect', { attempts: attempt });
|
|
821
1021
|
}
|
|
822
1022
|
catch (error) {
|
|
823
|
-
console.error(`MCPL server "${this.id}" reconnect failed
|
|
1023
|
+
console.error(`MCPL server "${this.id}" reconnect failed: ${error.message}${withStderr(error)}`);
|
|
824
1024
|
this.reconnectAttempts = attempt + 1;
|
|
825
|
-
|
|
1025
|
+
const stderrTail = stderrTailOf(error);
|
|
1026
|
+
this.emit('reconnect-failed', { error: error.message, ...(stderrTail ? { stderrTail } : {}), attempt });
|
|
826
1027
|
this.scheduleReconnect();
|
|
827
1028
|
}
|
|
828
1029
|
}
|
|
@@ -842,7 +1043,7 @@ export class McplServerConnection extends EventEmitter {
|
|
|
842
1043
|
*/
|
|
843
1044
|
sendRequest(method, params, options = {}) {
|
|
844
1045
|
if (this.closed) {
|
|
845
|
-
return Promise.reject(new
|
|
1046
|
+
return Promise.reject(new McplRequestError(`Cannot send request: connection to "${this.id}" is closed`, 'not-sent'));
|
|
846
1047
|
}
|
|
847
1048
|
const id = this.nextRequestId++;
|
|
848
1049
|
const request = {
|
|
@@ -858,22 +1059,44 @@ export class McplServerConnection extends EventEmitter {
|
|
|
858
1059
|
pending.timer = setTimeout(() => {
|
|
859
1060
|
this.pendingRequests.delete(id);
|
|
860
1061
|
if (options.surfaceOrphanedResponse) {
|
|
861
|
-
this.orphanedRequests.set(id, {
|
|
1062
|
+
this.orphanedRequests.set(id, {
|
|
1063
|
+
method,
|
|
1064
|
+
...(method === 'push/render'
|
|
1065
|
+
? {
|
|
1066
|
+
renderParams: {
|
|
1067
|
+
featureSet: params.featureSet,
|
|
1068
|
+
key: params.key,
|
|
1069
|
+
eventId: params.eventId,
|
|
1070
|
+
...(typeof params.channelId === 'string' ? { channelId: params.channelId } : {}),
|
|
1071
|
+
},
|
|
1072
|
+
}
|
|
1073
|
+
: {}),
|
|
1074
|
+
});
|
|
862
1075
|
if (this.orphanedRequests.size > 4096)
|
|
863
1076
|
this.orphanedRequests.delete(this.orphanedRequests.keys().next().value);
|
|
864
1077
|
}
|
|
865
|
-
reject(new
|
|
1078
|
+
reject(new McplRequestError(`MCPL server "${this.id}" did not respond to ${method} (id=${id}) ` +
|
|
866
1079
|
`within ${timeoutMs}ms — the server may be hung. The response ` +
|
|
867
1080
|
`outcome is unknown: the request was abandoned locally but was not ` +
|
|
868
1081
|
`cancelled, so the tool may still have completed server-side; verify ` +
|
|
869
1082
|
`state before retrying; a blind retry of a stateful/side-effecting ` +
|
|
870
|
-
`tool may duplicate it
|
|
1083
|
+
`tool may duplicate it.`, 'no-response'));
|
|
871
1084
|
}, timeoutMs);
|
|
872
1085
|
// Don't hold the event loop open for the watchdog alone.
|
|
873
1086
|
pending.timer.unref?.();
|
|
874
1087
|
}
|
|
875
1088
|
this.pendingRequests.set(id, pending);
|
|
876
|
-
|
|
1089
|
+
try {
|
|
1090
|
+
this.transport.writeLine(JSON.stringify(request));
|
|
1091
|
+
}
|
|
1092
|
+
catch (err) {
|
|
1093
|
+
// A synchronous write rejection sent no request. Remove its pending
|
|
1094
|
+
// state and watchdog before reporting that it is safe to retry.
|
|
1095
|
+
this.pendingRequests.delete(id);
|
|
1096
|
+
if (pending.timer)
|
|
1097
|
+
clearTimeout(pending.timer);
|
|
1098
|
+
reject(new McplRequestError(`Cannot send ${method} to MCPL server "${this.id}": ${err instanceof Error ? err.message : String(err)}`, 'not-sent'));
|
|
1099
|
+
}
|
|
877
1100
|
});
|
|
878
1101
|
}
|
|
879
1102
|
/**
|
|
@@ -957,7 +1180,9 @@ export class McplServerConnection extends EventEmitter {
|
|
|
957
1180
|
this.setupLifecycle(transport);
|
|
958
1181
|
// Surface transport diagnostics (stdio child stderr) as 'stderr' events,
|
|
959
1182
|
// preserving the `{ line }` payload existing consumers expect.
|
|
960
|
-
|
|
1183
|
+
// Through the same containment boundary as every inbound event, so a
|
|
1184
|
+
// stderr listener that throws is reported, not thrown into the transport.
|
|
1185
|
+
transport.on('stderr', (line) => this.dispatchInboundEvent('stderr', { line }));
|
|
961
1186
|
}
|
|
962
1187
|
/**
|
|
963
1188
|
* Wire up the transport's line stream to route incoming JSON-RPC messages.
|
|
@@ -972,57 +1197,142 @@ export class McplServerConnection extends EventEmitter {
|
|
|
972
1197
|
// Ignore non-JSON lines
|
|
973
1198
|
return;
|
|
974
1199
|
}
|
|
975
|
-
//
|
|
976
|
-
|
|
977
|
-
|
|
1200
|
+
// JSON-RPC messages must be objects. Ignore unrelated stdout/log values
|
|
1201
|
+
// before property access, just as malformed JSON lines are ignored.
|
|
1202
|
+
if (msg === null || typeof msg !== 'object' || Array.isArray(msg))
|
|
978
1203
|
return;
|
|
1204
|
+
try {
|
|
1205
|
+
this.dispatchMessage(msg);
|
|
979
1206
|
}
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
// featureSets/changed is REMOVED in 0.5.0 (§6.7 — it carried a
|
|
987
|
-
// server-authored change payload, the self-attestation defect; the
|
|
988
|
-
// need is met by §17's host-diffed manifest fetch). It was still
|
|
989
|
-
// routed, control-plane classified, and mutating declarations — a
|
|
990
|
-
// live ungated self-attestation path (PR #79 review blocker 4).
|
|
991
|
-
if (request.method === McplMethod.FeatureSetsChanged) {
|
|
992
|
-
if (request.id != null) {
|
|
993
|
-
this.sendErrorResponse(request.id, -32601, 'featureSets/changed removed in MCPL 0.5.0 (superseded by mcpl/manifestChanged, SPEC §17)');
|
|
994
|
-
}
|
|
995
|
-
else {
|
|
996
|
-
console.error(`[mcpl] ${this.id}: discarded featureSets/changed — removed in 0.5.0 (§6.7/§17)`);
|
|
997
|
-
}
|
|
998
|
-
return;
|
|
1207
|
+
catch (error) {
|
|
1208
|
+
const request = msg;
|
|
1209
|
+
this.reportInboundFailure(error, {
|
|
1210
|
+
...(typeof request.method === 'string' ? { event: request.method } : {}),
|
|
1211
|
+
...(typeof request.id === 'string' || typeof request.id === 'number' ? { requestId: request.id } : {}),
|
|
1212
|
+
});
|
|
999
1213
|
}
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1214
|
+
});
|
|
1215
|
+
}
|
|
1216
|
+
/** Contain synchronous dispatch failures; async RPC handlers own their promises. */
|
|
1217
|
+
dispatchMessage(msg) {
|
|
1218
|
+
// Is this a response to one of our outbound requests?
|
|
1219
|
+
if ('id' in msg && msg.id != null && !('method' in msg)) {
|
|
1220
|
+
this.handleResponse(msg);
|
|
1221
|
+
return;
|
|
1222
|
+
}
|
|
1223
|
+
// It is an inbound request or notification from the server
|
|
1224
|
+
const request = msg;
|
|
1225
|
+
// MCP's ping, which either side may send: its receiver answers promptly
|
|
1226
|
+
// with an empty result. It's answered as it arrives, before admission and
|
|
1227
|
+
// buffering, since it asks only whether the connection is alive, and a
|
|
1228
|
+
// paused plane mustn't hold that answer. A ping sent as a notification
|
|
1229
|
+
// has nothing to answer. The handshake answers one too.
|
|
1230
|
+
if (request.method === 'ping') {
|
|
1231
|
+
if (request.id != null)
|
|
1232
|
+
this.sendResponse(request.id, {});
|
|
1233
|
+
return;
|
|
1234
|
+
}
|
|
1235
|
+
const eventName = typeof request.method === 'string' && Object.hasOwn(McplServerConnection.METHOD_TO_EVENT, request.method)
|
|
1236
|
+
? McplServerConnection.METHOD_TO_EVENT[request.method] : undefined;
|
|
1237
|
+
// §7 is removed in 0.5.0: scope/elevate is no longer a method. Answer
|
|
1238
|
+
// rather than hang (§6.6 — a method that will never be answered MUST
|
|
1239
|
+
// return an error).
|
|
1240
|
+
// featureSets/changed is REMOVED in 0.5.0 (§6.7 — it carried a
|
|
1241
|
+
// server-authored change payload, the self-attestation defect; the
|
|
1242
|
+
// need is met by §17's host-diffed manifest fetch). It was still
|
|
1243
|
+
// routed, control-plane classified, and mutating declarations — a
|
|
1244
|
+
// live ungated self-attestation path (PR #79 review blocker 4).
|
|
1245
|
+
if (request.method === McplMethod.FeatureSetsChanged) {
|
|
1246
|
+
if (request.id != null) {
|
|
1247
|
+
this.sendErrorResponse(request.id, -32601, 'featureSets/changed removed in MCPL 0.5.0 (superseded by mcpl/manifestChanged, SPEC §17)');
|
|
1005
1248
|
}
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
// and staged-buffer flushes share. See the comment there for why
|
|
1009
|
-
// rejecting here, at line receipt, was wrong for staged connections.
|
|
1010
|
-
if (eventName) {
|
|
1011
|
-
// Emit the typed event with params and (for requests) a respond callback
|
|
1012
|
-
if (request.id != null) {
|
|
1013
|
-
// Server expects a response — provide a respond helper
|
|
1014
|
-
this.emit(eventName, request.params, {
|
|
1015
|
-
id: request.id,
|
|
1016
|
-
respond: (result) => this.sendResponse(request.id, result),
|
|
1017
|
-
respondError: (code, message, data) => this.sendErrorResponse(request.id, code, message, data),
|
|
1018
|
-
});
|
|
1019
|
-
}
|
|
1020
|
-
else {
|
|
1021
|
-
// Notification — no response expected
|
|
1022
|
-
this.emit(eventName, request.params);
|
|
1023
|
-
}
|
|
1249
|
+
else {
|
|
1250
|
+
console.error(`[mcpl] ${this.id}: discarded featureSets/changed — removed in 0.5.0 (§6.7/§17)`);
|
|
1024
1251
|
}
|
|
1025
|
-
|
|
1252
|
+
return;
|
|
1253
|
+
}
|
|
1254
|
+
if (request.method === McplMethod.ScopeElevate) {
|
|
1255
|
+
if (request.id != null) {
|
|
1256
|
+
this.sendErrorResponse(request.id, -32601, 'scope/elevate removed in MCPL 0.5.0 (SPEC §7)');
|
|
1257
|
+
}
|
|
1258
|
+
return;
|
|
1259
|
+
}
|
|
1260
|
+
// Positive-grant enforcement (§5.4, §14.1) happens at ADMISSION, in
|
|
1261
|
+
// the emit() override below — the one choke-point that live routing
|
|
1262
|
+
// and staged-buffer flushes share. See the comment there for why
|
|
1263
|
+
// rejecting here, at line receipt, was wrong for staged connections.
|
|
1264
|
+
if (!eventName) {
|
|
1265
|
+
// §6.6: a request that will never be answered MUST get an error, so a
|
|
1266
|
+
// request (it has an id) whose method isn't a string, or isn't one this
|
|
1267
|
+
// host handles, is answered -32601. A notification nobody handles is
|
|
1268
|
+
// ignored, as JSON-RPC asks.
|
|
1269
|
+
if (request.id != null) {
|
|
1270
|
+
this.sendErrorResponse(request.id, -32601, 'Method not found');
|
|
1271
|
+
console.error(`[mcpl] ${this.id}: answered -32601 to a request for ${describeMethod(request.method)}, which this host doesn't handle`);
|
|
1272
|
+
}
|
|
1273
|
+
return;
|
|
1274
|
+
}
|
|
1275
|
+
// Emit the typed event with params and (for requests) a respond callback
|
|
1276
|
+
if (request.id != null) {
|
|
1277
|
+
// Server expects a response — provide a respond helper
|
|
1278
|
+
this.dispatchInboundEvent(eventName, request.params, {
|
|
1279
|
+
id: request.id,
|
|
1280
|
+
respond: (result) => this.sendResponse(request.id, result),
|
|
1281
|
+
respondError: (code, message, data) => this.sendErrorResponse(request.id, code, message, data),
|
|
1282
|
+
});
|
|
1283
|
+
}
|
|
1284
|
+
else {
|
|
1285
|
+
// Notification — no response expected
|
|
1286
|
+
this.dispatchInboundEvent(eventName, request.params);
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
/** Live delivery and delayed plane flushes share the same containment boundary. */
|
|
1290
|
+
dispatchInboundEvent(event, ...args) {
|
|
1291
|
+
try {
|
|
1292
|
+
this.emit(event, ...args);
|
|
1293
|
+
}
|
|
1294
|
+
catch (error) {
|
|
1295
|
+
const requestId = args[1]?.id;
|
|
1296
|
+
this.reportInboundFailure(error, {
|
|
1297
|
+
event,
|
|
1298
|
+
...(typeof requestId === 'string' || typeof requestId === 'number' ? { requestId } : {}),
|
|
1299
|
+
});
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
/** Report a failure the containment boundary caught, naming the event (or
|
|
1303
|
+
* method) and request it was dispatching, and what failed. The message is
|
|
1304
|
+
* what the framework's 'error' listener traces. */
|
|
1305
|
+
reportInboundFailure(cause, context = {}) {
|
|
1306
|
+
const where = (show) => (context.event === undefined ? '' : ` for ${show(context.event)}`) +
|
|
1307
|
+
(context.requestId === undefined ? '' : ` (request ${show(String(context.requestId))})`);
|
|
1308
|
+
// The error's message is what the 'error' listener traces, as text a
|
|
1309
|
+
// reader parses, so it is bounded rather than escaped (boundedForLog);
|
|
1310
|
+
// the log line prints the same through log-value.
|
|
1311
|
+
const error = new Error(`MCPL server "${this.id}" inbound dispatch failed${where(boundedForLog)}: ${boundedForLog(describeCause(cause))}`, { cause });
|
|
1312
|
+
console.error(`[mcpl] ${this.id}: inbound dispatch failed${where(logValue)}: ${logDetail(describeCause(cause))}`);
|
|
1313
|
+
this.emitToErrorListeners(error);
|
|
1314
|
+
}
|
|
1315
|
+
/**
|
|
1316
|
+
* Give an error to the connection's 'error' listeners, and say whether it
|
|
1317
|
+
* has any. EventEmitter throws an 'error' that nothing listens for, and
|
|
1318
|
+
* from a transport's callback, where these errors arise, nothing catches
|
|
1319
|
+
* that throw, so it ends the process. A bare connection has no listener:
|
|
1320
|
+
* the class is exported, and a probe, a playtest or a harness often attaches
|
|
1321
|
+
* none. So with no listener, the error is the caller's to log, unless it
|
|
1322
|
+
* already has. A listener that throws is caught and logged, with the error
|
|
1323
|
+
* it was handling.
|
|
1324
|
+
*/
|
|
1325
|
+
emitToErrorListeners(error) {
|
|
1326
|
+
if (this.listenerCount('error') === 0)
|
|
1327
|
+
return false;
|
|
1328
|
+
try {
|
|
1329
|
+
this.emit('error', error);
|
|
1330
|
+
}
|
|
1331
|
+
catch (listenerError) {
|
|
1332
|
+
console.error(`[mcpl] ${this.id}: an 'error' listener failed: ${logDetail(describeCause(listenerError))}` +
|
|
1333
|
+
`, handling ${logDetail(error.message)}`);
|
|
1334
|
+
}
|
|
1335
|
+
return true;
|
|
1026
1336
|
}
|
|
1027
1337
|
/**
|
|
1028
1338
|
* Handle a JSON-RPC response by resolving/rejecting the corresponding pending request.
|
|
@@ -1038,10 +1348,17 @@ export class McplServerConnection extends EventEmitter {
|
|
|
1038
1348
|
// re-inject either result because the original dispatch context is gone.
|
|
1039
1349
|
const orphaned = this.orphanedRequests.get(response.id);
|
|
1040
1350
|
this.orphanedRequests.delete(response.id);
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1351
|
+
// A push/render answered after its timeout (RFC-006 §5.3) is reported
|
|
1352
|
+
// with the render's featureSet, key, eventId and, for a channel-scoped
|
|
1353
|
+
// subject, channelId, kept from its request when the timeout fired, so
|
|
1354
|
+
// its discarded answer can be recorded beside its batch's other
|
|
1355
|
+
// coalescing records (§11). It is only reported: the fallback the
|
|
1356
|
+
// timeout materialized stands (§5.4 rule 3). A late JSON-RPC error is
|
|
1357
|
+
// passed on as `error`, so its record can be told from a late result's,
|
|
1358
|
+
// and so is one beside a result, which JSON-RPC forbids: the live path
|
|
1359
|
+
// rejects such an answer as an error.
|
|
1360
|
+
const render = orphaned?.renderParams ?? {};
|
|
1361
|
+
const failure = response.error ? { error: { code: response.error.code, message: response.error.message } } : {};
|
|
1045
1362
|
const result = response.result;
|
|
1046
1363
|
if (result && typeof result === 'object') {
|
|
1047
1364
|
const r = result;
|
|
@@ -1051,6 +1368,8 @@ export class McplServerConnection extends EventEmitter {
|
|
|
1051
1368
|
method: orphaned?.method,
|
|
1052
1369
|
hadState: r.state !== undefined,
|
|
1053
1370
|
hadCheckpoint: r.checkpoint !== undefined,
|
|
1371
|
+
...render,
|
|
1372
|
+
...failure,
|
|
1054
1373
|
});
|
|
1055
1374
|
}
|
|
1056
1375
|
}
|
|
@@ -1060,6 +1379,8 @@ export class McplServerConnection extends EventEmitter {
|
|
|
1060
1379
|
method: orphaned.method,
|
|
1061
1380
|
hadState: false,
|
|
1062
1381
|
hadCheckpoint: false,
|
|
1382
|
+
...render,
|
|
1383
|
+
...failure,
|
|
1063
1384
|
});
|
|
1064
1385
|
}
|
|
1065
1386
|
return; // Orphaned response — ignore
|
|
@@ -1068,7 +1389,14 @@ export class McplServerConnection extends EventEmitter {
|
|
|
1068
1389
|
if (pending.timer)
|
|
1069
1390
|
clearTimeout(pending.timer);
|
|
1070
1391
|
if (response.error) {
|
|
1071
|
-
|
|
1392
|
+
// describeCause rather than the template's own conversion, as for an
|
|
1393
|
+
// initialize error: the server's code and message can be any JSON
|
|
1394
|
+
// value, and one with no primitive form, such as {"toString":1}, would
|
|
1395
|
+
// throw here, after the request has left pendingRequests and its timer
|
|
1396
|
+
// is cleared, so it would never settle. Both are the server's text, a
|
|
1397
|
+
// code as much as a message, since a server can send a string, so both
|
|
1398
|
+
// are bounded as errors.ts says.
|
|
1399
|
+
pending.reject(new McplRequestError(`MCPL server "${this.id}" returned error for ${pending.method}: [${boundedForLog(describeCause(response.error.code))}] ${boundedForLog(describeCause(response.error.message))}`, 'error-response', response.error.data));
|
|
1072
1400
|
}
|
|
1073
1401
|
else {
|
|
1074
1402
|
pending.resolve(response.result);
|
|
@@ -1107,7 +1435,9 @@ export class McplServerConnection extends EventEmitter {
|
|
|
1107
1435
|
setupLifecycle(transport) {
|
|
1108
1436
|
this.hostCloseRequested = false;
|
|
1109
1437
|
transport.on('error', (err) => {
|
|
1110
|
-
|
|
1438
|
+
const error = new Error(`MCPL server "${this.id}" transport error: ${err.message}`);
|
|
1439
|
+
if (!this.emitToErrorListeners(error))
|
|
1440
|
+
console.error(`[mcpl] ${this.id}: transport error: ${logDetail(err.message)}`);
|
|
1111
1441
|
});
|
|
1112
1442
|
transport.on('close', (info) => {
|
|
1113
1443
|
if (!this.closed) {
|
|
@@ -1117,7 +1447,7 @@ export class McplServerConnection extends EventEmitter {
|
|
|
1117
1447
|
for (const [id, pending] of this.pendingRequests) {
|
|
1118
1448
|
if (pending.timer)
|
|
1119
1449
|
clearTimeout(pending.timer);
|
|
1120
|
-
pending.reject(new
|
|
1450
|
+
pending.reject(new McplRequestError(`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})`, 'no-response'));
|
|
1121
1451
|
}
|
|
1122
1452
|
this.pendingRequests.clear();
|
|
1123
1453
|
this.orphanedRequests.clear();
|
|
@@ -1132,6 +1462,7 @@ export class McplServerConnection extends EventEmitter {
|
|
|
1132
1462
|
code: info.code ?? null,
|
|
1133
1463
|
signal: info.signal ?? null,
|
|
1134
1464
|
reason: info.reason ?? (byHost ? 'closed by host' : undefined),
|
|
1465
|
+
...(info.reasonFromPeer ? { reasonFromPeer: true } : {}),
|
|
1135
1466
|
byHost,
|
|
1136
1467
|
};
|
|
1137
1468
|
this.emit('close', closeInfo.code, closeInfo.signal, closeInfo);
|