@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
|
@@ -12,11 +12,16 @@
|
|
|
12
12
|
* - Expose synthesized tools: channel_list, channel_open, channel_close, channel_publish
|
|
13
13
|
* - Build channel context for beforeInference params
|
|
14
14
|
*/
|
|
15
|
-
import {
|
|
15
|
+
import { convertBlock } from './convert-block.js';
|
|
16
|
+
import { ensureStateRegistered } from '../module-registry.js';
|
|
16
17
|
import { expandCoreTags } from './tags.js';
|
|
17
|
-
import { EmptyContentError, validateCoalescedContent } from './push-coalescer.js';
|
|
18
|
-
import {
|
|
18
|
+
import { coalesceRejectionReason, EmptyContentError, validateCoalescedContent } from './push-coalescer.js';
|
|
19
|
+
import { isVisiblyEmptyConversion } from './visible-content.js';
|
|
20
|
+
import { logDetail, logValue } from './log-value.js';
|
|
21
|
+
import { RefusalLines } from './refusal-lines.js';
|
|
19
22
|
import { CapabilityGrant } from './capability-grant.js';
|
|
23
|
+
import { McplRequestError } from './server-connection.js';
|
|
24
|
+
import { readSkipReplyWake } from './skip-reply-wake.js';
|
|
20
25
|
// ============================================================================
|
|
21
26
|
// Typing indicator interval (Discord typing lasts ~10s, so 7s keeps it alive)
|
|
22
27
|
// ============================================================================
|
|
@@ -81,68 +86,6 @@ function shallowEqualRecord(a, b) {
|
|
|
81
86
|
return true;
|
|
82
87
|
}
|
|
83
88
|
// ============================================================================
|
|
84
|
-
// Content Conversion: McplContentBlock → membrane ContentBlock
|
|
85
|
-
// ============================================================================
|
|
86
|
-
/**
|
|
87
|
-
* Convert a single MCPL wire-format content block to a membrane ContentBlock.
|
|
88
|
-
*/
|
|
89
|
-
function convertBlock(block) {
|
|
90
|
-
switch (block.type) {
|
|
91
|
-
case 'text':
|
|
92
|
-
return { type: 'text', text: block.text };
|
|
93
|
-
case 'image':
|
|
94
|
-
if (isInlineContradiction(block)) {
|
|
95
|
-
// RFC-005 vector 2: inline data claiming bulk disposition — fail
|
|
96
|
-
// closed, withhold the data (checked BEFORE the data branch).
|
|
97
|
-
return { type: 'text', text: INLINE_WITHHELD_TEXT };
|
|
98
|
-
}
|
|
99
|
-
if (block.uri && block.disposition) {
|
|
100
|
-
// RFC-005 uri-form media with a disposition claim: stub, do not
|
|
101
|
-
// hand the URI to the provider or inline it.
|
|
102
|
-
return { type: 'text', text: referenceStubOrNull(block, 'attachment on channel message') ?? '[reference]' };
|
|
103
|
-
}
|
|
104
|
-
if (block.data && block.mimeType) {
|
|
105
|
-
return {
|
|
106
|
-
type: 'image',
|
|
107
|
-
source: { type: 'base64', data: block.data, mediaType: block.mimeType },
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
if (block.uri) {
|
|
111
|
-
return {
|
|
112
|
-
type: 'image',
|
|
113
|
-
source: { type: 'url', url: block.uri },
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
return { type: 'text', text: '[Image: no data]' };
|
|
117
|
-
case 'audio':
|
|
118
|
-
if (isInlineContradiction(block)) {
|
|
119
|
-
// RFC-005 vector 2: inline data claiming bulk disposition — fail
|
|
120
|
-
// closed, withhold the data (checked BEFORE the data branch).
|
|
121
|
-
return { type: 'text', text: INLINE_WITHHELD_TEXT };
|
|
122
|
-
}
|
|
123
|
-
if (block.uri && block.disposition) {
|
|
124
|
-
// RFC-005 uri-form media with a disposition claim: stub, do not
|
|
125
|
-
// hand the URI to the provider or inline it.
|
|
126
|
-
return { type: 'text', text: referenceStubOrNull(block, 'attachment on channel message') ?? '[reference]' };
|
|
127
|
-
}
|
|
128
|
-
if (block.data && block.mimeType) {
|
|
129
|
-
return {
|
|
130
|
-
type: 'audio',
|
|
131
|
-
source: { type: 'base64', data: block.data, mediaType: block.mimeType },
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
return { type: 'text', text: '[Audio: no data]' };
|
|
135
|
-
case 'resource':
|
|
136
|
-
// RFC-005: reference blocks become bounded stubs — never raw URIs
|
|
137
|
-
// (a signed URL is a bearer credential that looks like a location).
|
|
138
|
-
return { type: 'text', text: referenceStubOrNull(block, 'attachment on channel message') ?? '[reference]' };
|
|
139
|
-
default:
|
|
140
|
-
// Unknown wire block types previously fell off the exhaustive switch
|
|
141
|
-
// and propagated `undefined` into ContentBlock[]. Fail visibly.
|
|
142
|
-
return { type: 'text', text: `[unrecognized content block: ${block.type ?? 'untyped'}]` };
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
// ============================================================================
|
|
146
89
|
// Channel Tool Definitions
|
|
147
90
|
// ============================================================================
|
|
148
91
|
const CHANNEL_TOOL_DEFINITIONS = [
|
|
@@ -153,9 +96,8 @@ const CHANNEL_TOOL_DEFINITIONS = [
|
|
|
153
96
|
},
|
|
154
97
|
{
|
|
155
98
|
name: 'channel_open',
|
|
156
|
-
description: 'Open a channel
|
|
157
|
-
'
|
|
158
|
-
'history preceding the message that invited you into the channel.',
|
|
99
|
+
description: 'Open a channel. What an open channel delivers to you depends on its MCPL server. ' +
|
|
100
|
+
'Optionally request history preceding the message that invited you into the channel.',
|
|
159
101
|
inputSchema: {
|
|
160
102
|
type: 'object',
|
|
161
103
|
properties: {
|
|
@@ -194,7 +136,8 @@ const CHANNEL_TOOL_DEFINITIONS = [
|
|
|
194
136
|
},
|
|
195
137
|
{
|
|
196
138
|
name: 'channel_close',
|
|
197
|
-
description: 'Close a channel
|
|
139
|
+
description: 'Close a channel. Messages that address you still reach you; what else stops reaching you ' +
|
|
140
|
+
'depends on its server.',
|
|
198
141
|
inputSchema: {
|
|
199
142
|
type: 'object',
|
|
200
143
|
properties: {
|
|
@@ -268,14 +211,90 @@ const CHANNEL_TOOL_DEFINITIONS = [
|
|
|
268
211
|
wake_in_seconds: {
|
|
269
212
|
type: 'number',
|
|
270
213
|
description: 'Optional self-wake: if nothing else wakes you first, you wake again after this ' +
|
|
271
|
-
'many seconds
|
|
272
|
-
'wake before then cancels it. Omit to stay idle until the
|
|
214
|
+
'many seconds, from 1 to 3600; a larger number waits 3600 (1 = go again almost ' +
|
|
215
|
+
'immediately). Any other wake before then cancels it. Omit to stay idle until the ' +
|
|
216
|
+
'next external wake.',
|
|
273
217
|
},
|
|
274
218
|
},
|
|
275
219
|
required: [],
|
|
276
220
|
},
|
|
277
221
|
},
|
|
278
222
|
];
|
|
223
|
+
// ============================================================================
|
|
224
|
+
// Constructor Options
|
|
225
|
+
// ============================================================================
|
|
226
|
+
/** Bound connector values for notices, logs and an outcome's reason. A
|
|
227
|
+
* PublishOutcome keeps the connector's structured data (`detail`) whole. */
|
|
228
|
+
export function connectorText(value) {
|
|
229
|
+
let text;
|
|
230
|
+
try {
|
|
231
|
+
text = typeof value === 'string' ? value : JSON.stringify(value) ?? String(value);
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
return '[unserializable connector value]';
|
|
235
|
+
}
|
|
236
|
+
const limit = 2000;
|
|
237
|
+
const suffix = '… [truncated]';
|
|
238
|
+
return text.length > limit ? text.slice(0, limit - suffix.length) + suffix : text;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* What a channels/publish request that threw establishes. Only a request
|
|
242
|
+
* that never left the host proves nothing was posted. An error response may
|
|
243
|
+
* follow a partial post (a multi-part send whose later part failed), so it
|
|
244
|
+
* is unknown, with the connector's own words, bounded, and its data kept for
|
|
245
|
+
* the resident to judge. The publish executor and channel_publish both read
|
|
246
|
+
* a failed request this way.
|
|
247
|
+
*/
|
|
248
|
+
function publishErrorOutcome(err, destination, at) {
|
|
249
|
+
const message = connectorText(err instanceof Error ? err.message : String(err));
|
|
250
|
+
const notSent = err instanceof McplRequestError && err.outcome === 'not-sent';
|
|
251
|
+
const detail = err instanceof McplRequestError ? err.data : undefined;
|
|
252
|
+
return {
|
|
253
|
+
status: notSent ? 'failed' : 'unknown',
|
|
254
|
+
destination,
|
|
255
|
+
reason: notSent ? message : `${message} (delivery uncertain)`,
|
|
256
|
+
...(detail !== undefined ? { detail } : {}),
|
|
257
|
+
at,
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* What a channels/publish answer establishes. A final publish is a request,
|
|
262
|
+
* so success requires an explicit receipt; a missing or malformed one leaves
|
|
263
|
+
* delivery uncertain (anima-research/agent-framework#163's rule).
|
|
264
|
+
* `delivered: false` proves nothing went out only when the receipt names no
|
|
265
|
+
* message at all: a message id beside it, valid or malformed, contradicts it,
|
|
266
|
+
* since something may have been posted. The publish executor and
|
|
267
|
+
* channel_publish both read an answer this way.
|
|
268
|
+
*/
|
|
269
|
+
function publishReceiptOutcome(result, destination, at) {
|
|
270
|
+
const receipt = (result ?? {});
|
|
271
|
+
const messageId = typeof receipt.messageId === 'string' && receipt.messageId ? receipt.messageId : undefined;
|
|
272
|
+
if (receipt.delivered === true) {
|
|
273
|
+
return { status: 'delivered', destination, ...(messageId ? { messageId } : {}), at };
|
|
274
|
+
}
|
|
275
|
+
if (receipt.delivered === false) {
|
|
276
|
+
if (receipt.messageId === undefined || receipt.messageId === null) {
|
|
277
|
+
return { status: 'failed', destination, reason: `server "${destination.serverId}" reported delivered:false`, at };
|
|
278
|
+
}
|
|
279
|
+
return {
|
|
280
|
+
status: 'unknown',
|
|
281
|
+
destination,
|
|
282
|
+
...(messageId ? { messageId } : {}),
|
|
283
|
+
reason: messageId
|
|
284
|
+
? `server "${destination.serverId}" reported delivered:false but named posted message ${connectorText(messageId)} (delivery uncertain)`
|
|
285
|
+
: `server "${destination.serverId}" reported delivered:false beside a malformed message id ` +
|
|
286
|
+
`${connectorText(receipt.messageId)} (contradictory receipt; delivery uncertain)`,
|
|
287
|
+
at,
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
return {
|
|
291
|
+
status: 'unknown',
|
|
292
|
+
destination,
|
|
293
|
+
...(messageId ? { messageId } : {}),
|
|
294
|
+
reason: `server "${destination.serverId}" returned no valid delivery receipt (delivery uncertain)`,
|
|
295
|
+
at,
|
|
296
|
+
};
|
|
297
|
+
}
|
|
279
298
|
/** The machine decision sources a module-origin channel_close may record.
|
|
280
299
|
* Closed on purpose: honest provenance means a small, auditable vocabulary,
|
|
281
300
|
* not arbitrary self-description. */
|
|
@@ -294,6 +313,9 @@ export class ChannelRegistry {
|
|
|
294
313
|
store;
|
|
295
314
|
/** Registered channels, keyed by `{serverId}:{channelId}`. */
|
|
296
315
|
channels = new Map();
|
|
316
|
+
/** Holds back repeats of the line for a message refused because its
|
|
317
|
+
* channel isn't registered (RefusalLines). */
|
|
318
|
+
unknownChannelLines = new RefusalLines();
|
|
297
319
|
/**
|
|
298
320
|
* Most-recently-known label per channelId, replayed from
|
|
299
321
|
* `CHANNEL_LABEL_HISTORY_LOG_ID` (last sighting wins) and kept current by
|
|
@@ -357,8 +379,22 @@ export class ChannelRegistry {
|
|
|
357
379
|
legacyPolicies = new Map();
|
|
358
380
|
migratedLegacyPolicies = new Set();
|
|
359
381
|
handleCoalescedIncoming;
|
|
382
|
+
acceptInbound;
|
|
383
|
+
channelTools;
|
|
360
384
|
constructor(serverRegistry, featureSetManager, pushEventFn, emitTraceFn, options) {
|
|
361
385
|
this.handleCoalescedIncoming = options?.handleCoalescedIncoming;
|
|
386
|
+
this.acceptInbound = options?.acceptInbound;
|
|
387
|
+
this.channelTools = CHANNEL_TOOL_DEFINITIONS.map((tool) => {
|
|
388
|
+
if (tool.name !== 'skip_reply' || options?.eventGatePresent === true)
|
|
389
|
+
return tool;
|
|
390
|
+
const schema = tool.inputSchema;
|
|
391
|
+
const { wake_in_seconds: _wake, ...properties } = schema.properties;
|
|
392
|
+
return {
|
|
393
|
+
...tool,
|
|
394
|
+
description: tool.description.replace(' To end this turn but come back on your own shortly, set wake_in_seconds.', ''),
|
|
395
|
+
inputSchema: { ...schema, properties },
|
|
396
|
+
};
|
|
397
|
+
});
|
|
362
398
|
this.serverRegistry = serverRegistry;
|
|
363
399
|
this.featureSetManager = featureSetManager;
|
|
364
400
|
this.pushEventFn = pushEventFn;
|
|
@@ -512,6 +548,37 @@ export class ChannelRegistry {
|
|
|
512
548
|
updated: params.updated?.map((c) => c.id) ?? [],
|
|
513
549
|
});
|
|
514
550
|
}
|
|
551
|
+
/**
|
|
552
|
+
* A coalesced message the host refused. Until now the host said nothing, so
|
|
553
|
+
* a dropped message (agent-framework#266: every Discord message with a
|
|
554
|
+
* screenshot) left no trace where operators look. The sender gets the
|
|
555
|
+
* per-message result this lane gives: `coalesce_invalid` for a malformed
|
|
556
|
+
* item, or the thrown error's message for anything else. `answered` is the
|
|
557
|
+
* code that result stands for (-32602 for `coalesce_invalid`), and the
|
|
558
|
+
* reason follows it (coalesceRejectionReason): `coalesce-failed` when the
|
|
559
|
+
* host itself failed, `coalesce-invalid` when the sender's item was
|
|
560
|
+
* refused, with the failing `field` and the error's message as `detail`.
|
|
561
|
+
* The line prints the ids the sender sent, whatever their type; the trace
|
|
562
|
+
* carries them when they are strings.
|
|
563
|
+
*/
|
|
564
|
+
traceCoalesceRejection(serverId, message, error, answered) {
|
|
565
|
+
const reason = coalesceRejectionReason(answered);
|
|
566
|
+
const field = typeof error.field === 'string' && error.field ? error.field : undefined;
|
|
567
|
+
const channelId = typeof message?.channelId === 'string' ? message.channelId : '';
|
|
568
|
+
const messageId = typeof message?.messageId === 'string' && message.messageId ? message.messageId : undefined;
|
|
569
|
+
console.error(`[channel-incoming-rejected] server=${serverId} channel=${logValue(message?.channelId ?? '')} ` +
|
|
570
|
+
`messageId=${logValue(message?.messageId ?? '')} ` +
|
|
571
|
+
`reason=${reason}${field ? ` field=${logValue(field)}` : ''}: ${logDetail(error.message)}`);
|
|
572
|
+
this.emitTraceFn({
|
|
573
|
+
type: 'mcpl:channel-incoming-rejected',
|
|
574
|
+
serverId,
|
|
575
|
+
channelId,
|
|
576
|
+
...(messageId ? { messageId } : {}),
|
|
577
|
+
reason,
|
|
578
|
+
...(field ? { field } : {}),
|
|
579
|
+
detail: error.message,
|
|
580
|
+
});
|
|
581
|
+
}
|
|
515
582
|
/**
|
|
516
583
|
* Handle `channels/incoming` from a server.
|
|
517
584
|
*
|
|
@@ -523,10 +590,20 @@ export class ChannelRegistry {
|
|
|
523
590
|
for (const message of params.messages) {
|
|
524
591
|
if (!message || typeof message.channelId !== 'string' || !message.channelId
|
|
525
592
|
|| typeof message.messageId !== 'string' || !message.messageId) {
|
|
593
|
+
// The same gate as admission below: with no coalescer wired, a
|
|
594
|
+
// message carrying `coalesce` is handled uncoalesced, and refused as
|
|
595
|
+
// any uncoalesced message without an identity is.
|
|
596
|
+
const coalescedItem = message?.coalesce !== undefined && !!this.handleCoalescedIncoming;
|
|
597
|
+
if (coalescedItem) {
|
|
598
|
+
this.traceCoalesceRejection(serverId, message, {
|
|
599
|
+
field: typeof message.channelId !== 'string' || !message.channelId ? 'channelId' : 'messageId',
|
|
600
|
+
message: 'a coalesced message needs a channelId and a messageId',
|
|
601
|
+
}, -32602);
|
|
602
|
+
}
|
|
526
603
|
results.push({
|
|
527
604
|
messageId: typeof message?.messageId === 'string' ? message.messageId : '',
|
|
528
605
|
accepted: false,
|
|
529
|
-
reason:
|
|
606
|
+
reason: coalescedItem ? 'coalesce_invalid' : 'invalid channel/message identity',
|
|
530
607
|
});
|
|
531
608
|
continue;
|
|
532
609
|
}
|
|
@@ -557,11 +634,22 @@ export class ChannelRegistry {
|
|
|
557
634
|
// routable entry rather than an open self-attested one.
|
|
558
635
|
const incomingKey = `${serverId}:${message.channelId}`;
|
|
559
636
|
if (!this.channels.has(incomingKey)) {
|
|
637
|
+
// Loud, coalesced or not, like every other refusal of a message, but
|
|
638
|
+
// at most once a minute per channel (RefusalLines): a server that
|
|
639
|
+
// never registered a busy channel would otherwise print a line for
|
|
640
|
+
// every message in it. Every refusal is traced.
|
|
641
|
+
const held = this.unknownChannelLines.admit(serverId, message.channelId);
|
|
642
|
+
if (held !== null) {
|
|
643
|
+
console.error(`[channel-incoming-rejected] server=${serverId} channel=${logValue(message.channelId)} ` +
|
|
644
|
+
`messageId=${logValue(message.messageId)} reason=unknown-channel ` +
|
|
645
|
+
`(not registered, §14.5${held ? `; ${held} more since the last line` : ''})`);
|
|
646
|
+
}
|
|
560
647
|
this.emitTraceFn({
|
|
561
648
|
type: 'mcpl:channel-incoming-rejected',
|
|
562
649
|
serverId,
|
|
563
650
|
channelId: message.channelId,
|
|
564
|
-
|
|
651
|
+
messageId: message.messageId,
|
|
652
|
+
reason: 'unknown-channel',
|
|
565
653
|
});
|
|
566
654
|
results.push({
|
|
567
655
|
messageId: message.messageId,
|
|
@@ -578,7 +666,7 @@ export class ChannelRegistry {
|
|
|
578
666
|
// shows the model nothing would wake it with no visible cause.
|
|
579
667
|
const emptyAllowed = coalesced && message.coalesce?.retract === true;
|
|
580
668
|
const rejectEmpty = () => {
|
|
581
|
-
console.error(`[channel-incoming-rejected] server=${serverId} channel=${message.channelId} messageId=${message.messageId} reason=empty-content`);
|
|
669
|
+
console.error(`[channel-incoming-rejected] server=${serverId} channel=${logValue(message.channelId)} messageId=${logValue(message.messageId)} reason=empty-content`);
|
|
582
670
|
this.emitTraceFn({
|
|
583
671
|
type: 'mcpl:channel-incoming-rejected',
|
|
584
672
|
serverId,
|
|
@@ -592,20 +680,23 @@ export class ChannelRegistry {
|
|
|
592
680
|
// RFC-006 §13: malformed content on a coalesced item is that item's
|
|
593
681
|
// failure, not the batch's — check the shape before converting.
|
|
594
682
|
try {
|
|
595
|
-
validateCoalescedContent(message.content,
|
|
683
|
+
validateCoalescedContent(message.content, { allowEmpty: emptyAllowed });
|
|
596
684
|
}
|
|
597
685
|
catch (error) {
|
|
598
686
|
if (error instanceof EmptyContentError)
|
|
599
687
|
rejectEmpty();
|
|
600
|
-
else
|
|
688
|
+
else {
|
|
689
|
+
// Answered coalesce_invalid whatever the error's code: -32602.
|
|
690
|
+
this.traceCoalesceRejection(serverId, message, error, -32602);
|
|
601
691
|
results.push({ messageId: message.messageId, accepted: false, reason: 'coalesce_invalid' });
|
|
692
|
+
}
|
|
602
693
|
continue;
|
|
603
694
|
}
|
|
604
695
|
}
|
|
605
696
|
if (message.tags)
|
|
606
697
|
message.tags = expandCoreTags(message.tags);
|
|
607
|
-
const convertedContent = message.content.map(convertBlock);
|
|
608
|
-
if (!emptyAllowed &&
|
|
698
|
+
const convertedContent = message.content.map((block) => convertBlock(block, 'attachment on channel message', serverId));
|
|
699
|
+
if (!emptyAllowed && isVisiblyEmptyConversion(message.content, convertedContent)) {
|
|
609
700
|
rejectEmpty();
|
|
610
701
|
continue;
|
|
611
702
|
}
|
|
@@ -630,7 +721,10 @@ export class ChannelRegistry {
|
|
|
630
721
|
// Determine whether to trigger inference
|
|
631
722
|
let triggerInference = true;
|
|
632
723
|
if (this.shouldTriggerInference) {
|
|
633
|
-
|
|
724
|
+
// The text the agent's context gets, as the push lane's filter reads
|
|
725
|
+
// it: the converted text blocks, a placeholder or reference stub
|
|
726
|
+
// among them, NON_STRING_TEXT_PLACEHOLDER included.
|
|
727
|
+
const textContent = convertedContent
|
|
634
728
|
.filter((b) => b.type === 'text')
|
|
635
729
|
.map((b) => b.text)
|
|
636
730
|
.join('\n');
|
|
@@ -658,6 +752,7 @@ export class ChannelRegistry {
|
|
|
658
752
|
metadata: message.metadata,
|
|
659
753
|
...(message.tags ? { tags: message.tags } : {}),
|
|
660
754
|
triggerInference,
|
|
755
|
+
acceptedAt: Date.now(),
|
|
661
756
|
};
|
|
662
757
|
if (coalesced) {
|
|
663
758
|
// RFC-006 §14.3: a coalesced message is admitted like any other and
|
|
@@ -672,6 +767,9 @@ export class ChannelRegistry {
|
|
|
672
767
|
}
|
|
673
768
|
catch (error) {
|
|
674
769
|
const err = error;
|
|
770
|
+
// -32602 is answered coalesce_invalid; anything else as its message,
|
|
771
|
+
// a plain Error standing for an internal error (-32603).
|
|
772
|
+
this.traceCoalesceRejection(serverId, message, err, typeof err.code === 'number' ? err.code : -32603);
|
|
675
773
|
results.push({
|
|
676
774
|
messageId: message.messageId,
|
|
677
775
|
accepted: false,
|
|
@@ -680,6 +778,12 @@ export class ChannelRegistry {
|
|
|
680
778
|
}
|
|
681
779
|
continue;
|
|
682
780
|
}
|
|
781
|
+
// The source envelope is frozen here, at admission, before the message
|
|
782
|
+
// is queued or acknowledged: a rename or rebind while it waits in the
|
|
783
|
+
// queue cannot change where it says it came from.
|
|
784
|
+
const inboundSource = this.acceptInbound?.(event);
|
|
785
|
+
if (inboundSource)
|
|
786
|
+
event.inboundSource = inboundSource;
|
|
683
787
|
// Push to the processing queue
|
|
684
788
|
// Cast through unknown because McplChannelIncomingEvent matches the
|
|
685
789
|
// CustomEvent `${string}:${string}` type pattern but lacks an index signature.
|
|
@@ -722,27 +826,19 @@ export class ChannelRegistry {
|
|
|
722
826
|
// time a message reveals it (labels must show people, not ids).
|
|
723
827
|
if (existing.descriptor.metadata?.lazyRegistered &&
|
|
724
828
|
label && existing.descriptor.label === channelId) {
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
}
|
|
829
|
+
const metadata = extraMetadata
|
|
830
|
+
? { ...existing.descriptor.metadata, ...extraMetadata }
|
|
831
|
+
: existing.descriptor.metadata;
|
|
729
832
|
// The channel now has a real label, not just the bare id — durable.
|
|
730
|
-
|
|
833
|
+
// Recorded before the live descriptor takes it, since this branch's
|
|
834
|
+
// guard reads the descriptor: an append that throws leaves the
|
|
835
|
+
// placeholder, so the next push tries again.
|
|
836
|
+
this.appendLabelSighting(existing.descriptor.id, label, extractDmMeta(metadata));
|
|
837
|
+
existing.descriptor.label = label;
|
|
838
|
+
existing.descriptor.metadata = metadata;
|
|
731
839
|
}
|
|
732
840
|
return;
|
|
733
841
|
}
|
|
734
|
-
const key = `${serverId}:${channelId}`;
|
|
735
|
-
this.channels.set(key, {
|
|
736
|
-
serverId,
|
|
737
|
-
descriptor: {
|
|
738
|
-
id: channelId,
|
|
739
|
-
type: serverId,
|
|
740
|
-
label: label ?? channelId,
|
|
741
|
-
direction: 'bidirectional',
|
|
742
|
-
metadata: { lazyRegistered: true, ...(extraMetadata ?? {}) },
|
|
743
|
-
},
|
|
744
|
-
open: false,
|
|
745
|
-
});
|
|
746
842
|
// Only persist a REAL label durably. Falling back to the bare
|
|
747
843
|
// channelId as a placeholder (no server-supplied label at all — e.g. a
|
|
748
844
|
// Discord DM push missing both channelName and an author name,
|
|
@@ -752,11 +848,24 @@ export class ChannelRegistry {
|
|
|
752
848
|
// label-less post-restart event takes — recording the placeholder here
|
|
753
849
|
// would clobber the good label initializeLabelHistoryStore() just
|
|
754
850
|
// replayed, defeating the entire point of the durable log. The live
|
|
755
|
-
// descriptor
|
|
851
|
+
// descriptor below still carries the placeholder for in-process
|
|
756
852
|
// routing; only the durable write is skipped when there's no real
|
|
757
|
-
// label to record.
|
|
853
|
+
// label to record. A real label is recorded before the entry exists:
|
|
854
|
+
// an append that throws registers nothing, so the next push tries again.
|
|
758
855
|
if (label)
|
|
759
856
|
this.appendLabelSighting(channelId, label, extractDmMeta(extraMetadata));
|
|
857
|
+
const key = `${serverId}:${channelId}`;
|
|
858
|
+
this.channels.set(key, {
|
|
859
|
+
serverId,
|
|
860
|
+
descriptor: {
|
|
861
|
+
id: channelId,
|
|
862
|
+
type: serverId,
|
|
863
|
+
label: label ?? channelId,
|
|
864
|
+
direction: 'bidirectional',
|
|
865
|
+
metadata: { lazyRegistered: true, ...(extraMetadata ?? {}) },
|
|
866
|
+
},
|
|
867
|
+
open: false,
|
|
868
|
+
});
|
|
760
869
|
this.emitTraceFn({
|
|
761
870
|
type: 'mcpl:channel-lazy-registered',
|
|
762
871
|
serverId,
|
|
@@ -879,6 +988,12 @@ export class ChannelRegistry {
|
|
|
879
988
|
getDescriptor(channelId) {
|
|
880
989
|
return this.findChannelEntry(channelId)?.descriptor;
|
|
881
990
|
}
|
|
991
|
+
/** The registered label of `channelId` on exactly `serverId` (no
|
|
992
|
+
* cross-server first match), or undefined when it has none. */
|
|
993
|
+
getChannelLabel(serverId, channelId) {
|
|
994
|
+
const label = this.channels.get(`${serverId}:${channelId}`)?.descriptor.label;
|
|
995
|
+
return typeof label === 'string' && label.length > 0 ? label : undefined;
|
|
996
|
+
}
|
|
882
997
|
isChannelOpen(channelId) {
|
|
883
998
|
return this.findChannelEntry(channelId)?.open === true;
|
|
884
999
|
}
|
|
@@ -904,7 +1019,7 @@ export class ChannelRegistry {
|
|
|
904
1019
|
* Get synthesized tool definitions for channel operations.
|
|
905
1020
|
*/
|
|
906
1021
|
getChannelTools() {
|
|
907
|
-
return
|
|
1022
|
+
return this.channelTools;
|
|
908
1023
|
}
|
|
909
1024
|
/**
|
|
910
1025
|
* Handle a call to one of the synthesized channel tools.
|
|
@@ -952,8 +1067,9 @@ export class ChannelRegistry {
|
|
|
952
1067
|
const openChannels = this.getOpenChannels();
|
|
953
1068
|
// Resolve the outbound locus the SAME way routeSpeech does, so the agent is
|
|
954
1069
|
// told the channel its speech will actually land in: a conversation fork's
|
|
955
|
-
// home channel, else this turn's
|
|
956
|
-
//
|
|
1070
|
+
// home channel, else this turn's channel (single trunk agent — item-3
|
|
1071
|
+
// redux: its locus, else its triggering channel), else the global default
|
|
1072
|
+
// (heartbeats). Without this, a fork
|
|
957
1073
|
// was advertised the global locus but published somewhere else; and a trunk
|
|
958
1074
|
// agent was told the wrong channel under concurrency.
|
|
959
1075
|
const home = agentName ? this.homeChannelResolver?.(agentName) : undefined;
|
|
@@ -1032,14 +1148,7 @@ export class ChannelRegistry {
|
|
|
1032
1148
|
initializeLifecycleStore() {
|
|
1033
1149
|
if (!this.store)
|
|
1034
1150
|
return;
|
|
1035
|
-
|
|
1036
|
-
this.store.registerState({ id: CHANNEL_LIFECYCLE_LOG_ID, strategy: 'append_log' });
|
|
1037
|
-
}
|
|
1038
|
-
catch (error) {
|
|
1039
|
-
if (!(error instanceof Error) || !error.message.includes('State already exists')) {
|
|
1040
|
-
throw error;
|
|
1041
|
-
}
|
|
1042
|
-
}
|
|
1151
|
+
ensureStateRegistered(this.store, { id: CHANNEL_LIFECYCLE_LOG_ID, strategy: 'append_log' });
|
|
1043
1152
|
const raw = this.store.getStateJson(CHANNEL_LIFECYCLE_LOG_ID);
|
|
1044
1153
|
if (!Array.isArray(raw))
|
|
1045
1154
|
return;
|
|
@@ -1077,6 +1186,15 @@ export class ChannelRegistry {
|
|
|
1077
1186
|
}
|
|
1078
1187
|
}
|
|
1079
1188
|
}
|
|
1189
|
+
/**
|
|
1190
|
+
* Each writer appends its record here before it changes memory for it, so
|
|
1191
|
+
* an append that throws, as on a full disk, fails the operation with that
|
|
1192
|
+
* change unmade, and memory and the log still agree. A retry then records
|
|
1193
|
+
* the change rather than finding it in memory already, where
|
|
1194
|
+
* setDesiredState's same-state return would record nothing, and a restart
|
|
1195
|
+
* replays what memory held. appendLabelSighting keeps the same order for
|
|
1196
|
+
* the label history.
|
|
1197
|
+
*/
|
|
1080
1198
|
appendLifecycleEvent(event) {
|
|
1081
1199
|
this.store?.appendToStateJson(CHANNEL_LIFECYCLE_LOG_ID, event);
|
|
1082
1200
|
}
|
|
@@ -1093,14 +1211,7 @@ export class ChannelRegistry {
|
|
|
1093
1211
|
initializeLabelHistoryStore() {
|
|
1094
1212
|
if (!this.store)
|
|
1095
1213
|
return;
|
|
1096
|
-
|
|
1097
|
-
this.store.registerState({ id: CHANNEL_LABEL_HISTORY_LOG_ID, strategy: 'append_log' });
|
|
1098
|
-
}
|
|
1099
|
-
catch (error) {
|
|
1100
|
-
if (!(error instanceof Error) || !error.message.includes('State already exists')) {
|
|
1101
|
-
throw error;
|
|
1102
|
-
}
|
|
1103
|
-
}
|
|
1214
|
+
ensureStateRegistered(this.store, { id: CHANNEL_LABEL_HISTORY_LOG_ID, strategy: 'append_log' });
|
|
1104
1215
|
const raw = this.store.getStateJson(CHANNEL_LABEL_HISTORY_LOG_ID);
|
|
1105
1216
|
if (!Array.isArray(raw))
|
|
1106
1217
|
return;
|
|
@@ -1180,6 +1291,16 @@ export class ChannelRegistry {
|
|
|
1180
1291
|
const isDmUnchanged = isDm === undefined || this.dmClassified.get(channelId) === true;
|
|
1181
1292
|
if (labelUnchanged && recipientIdUnchanged && recipientNameUnchanged && isDmUnchanged)
|
|
1182
1293
|
return;
|
|
1294
|
+
// The log first, as for lifecycle events: an append that throws leaves
|
|
1295
|
+
// the history in memory as it was, so the next sighting records it.
|
|
1296
|
+
this.store?.appendToStateJson(CHANNEL_LABEL_HISTORY_LOG_ID, {
|
|
1297
|
+
channelId,
|
|
1298
|
+
label,
|
|
1299
|
+
ts: Date.now(),
|
|
1300
|
+
...(recipientId ? { recipientId } : {}),
|
|
1301
|
+
...(recipientName ? { recipientName } : {}),
|
|
1302
|
+
...(isDm ? { isDm } : {}),
|
|
1303
|
+
});
|
|
1183
1304
|
this.labelHistory.set(channelId, label);
|
|
1184
1305
|
let seen = this.allLabelsSeen.get(channelId);
|
|
1185
1306
|
if (!seen) {
|
|
@@ -1193,14 +1314,6 @@ export class ChannelRegistry {
|
|
|
1193
1314
|
this.dmRecipientNames.set(channelId, recipientName);
|
|
1194
1315
|
if (isDm)
|
|
1195
1316
|
this.dmClassified.set(channelId, true);
|
|
1196
|
-
this.store?.appendToStateJson(CHANNEL_LABEL_HISTORY_LOG_ID, {
|
|
1197
|
-
channelId,
|
|
1198
|
-
label,
|
|
1199
|
-
ts: Date.now(),
|
|
1200
|
-
...(recipientId ? { recipientId } : {}),
|
|
1201
|
-
...(recipientName ? { recipientName } : {}),
|
|
1202
|
-
...(isDm ? { isDm } : {}),
|
|
1203
|
-
});
|
|
1204
1317
|
}
|
|
1205
1318
|
/**
|
|
1206
1319
|
* Look up a label spec against label *history* rather than the live
|
|
@@ -1418,7 +1531,6 @@ export class ChannelRegistry {
|
|
|
1418
1531
|
const key = this.lifecycleKey(serverId, channelId);
|
|
1419
1532
|
if (this.desiredStates.get(key)?.state === desired)
|
|
1420
1533
|
return;
|
|
1421
|
-
this.desiredStates.set(key, { state: desired, source });
|
|
1422
1534
|
this.appendLifecycleEvent({
|
|
1423
1535
|
kind: 'desired-state',
|
|
1424
1536
|
serverId,
|
|
@@ -1427,6 +1539,7 @@ export class ChannelRegistry {
|
|
|
1427
1539
|
source,
|
|
1428
1540
|
timestamp: new Date().toISOString(),
|
|
1429
1541
|
});
|
|
1542
|
+
this.desiredStates.set(key, { state: desired, source });
|
|
1430
1543
|
}
|
|
1431
1544
|
// ==========================================================================
|
|
1432
1545
|
// Tune-out state (issue #77) — durable in the lifecycle log
|
|
@@ -1439,12 +1552,6 @@ export class ChannelRegistry {
|
|
|
1439
1552
|
*/
|
|
1440
1553
|
enterTuneOut(serverId, channelId, params, source) {
|
|
1441
1554
|
const key = this.lifecycleKey(serverId, channelId);
|
|
1442
|
-
this.desiredStates.set(key, {
|
|
1443
|
-
state: 'tuned-out',
|
|
1444
|
-
source,
|
|
1445
|
-
tuneOut: params,
|
|
1446
|
-
wakeCount: 0,
|
|
1447
|
-
});
|
|
1448
1555
|
this.appendLifecycleEvent({
|
|
1449
1556
|
kind: 'desired-state',
|
|
1450
1557
|
serverId,
|
|
@@ -1454,6 +1561,12 @@ export class ChannelRegistry {
|
|
|
1454
1561
|
source,
|
|
1455
1562
|
timestamp: new Date().toISOString(),
|
|
1456
1563
|
});
|
|
1564
|
+
this.desiredStates.set(key, {
|
|
1565
|
+
state: 'tuned-out',
|
|
1566
|
+
source,
|
|
1567
|
+
tuneOut: params,
|
|
1568
|
+
wakeCount: 0,
|
|
1569
|
+
});
|
|
1457
1570
|
}
|
|
1458
1571
|
/**
|
|
1459
1572
|
* End the active tune-out, returning the channel to `nextState`.
|
|
@@ -1467,7 +1580,6 @@ export class ChannelRegistry {
|
|
|
1467
1580
|
if (current?.state !== 'tuned-out' || !current.tuneOut)
|
|
1468
1581
|
return null;
|
|
1469
1582
|
const ended = { params: current.tuneOut, wakeCount: current.wakeCount ?? 0 };
|
|
1470
|
-
this.desiredStates.set(key, { state: nextState, source });
|
|
1471
1583
|
this.appendLifecycleEvent({
|
|
1472
1584
|
kind: 'desired-state',
|
|
1473
1585
|
serverId,
|
|
@@ -1476,6 +1588,7 @@ export class ChannelRegistry {
|
|
|
1476
1588
|
source,
|
|
1477
1589
|
timestamp: new Date().toISOString(),
|
|
1478
1590
|
});
|
|
1591
|
+
this.desiredStates.set(key, { state: nextState, source });
|
|
1479
1592
|
return ended;
|
|
1480
1593
|
}
|
|
1481
1594
|
/**
|
|
@@ -1490,16 +1603,17 @@ export class ChannelRegistry {
|
|
|
1490
1603
|
const current = this.desiredStates.get(key);
|
|
1491
1604
|
if (current?.state !== 'tuned-out' || !current.tuneOut)
|
|
1492
1605
|
return null;
|
|
1493
|
-
|
|
1606
|
+
const wakeCount = (current.wakeCount ?? 0) + 1;
|
|
1494
1607
|
this.appendLifecycleEvent({
|
|
1495
1608
|
kind: 'tune-out-wake',
|
|
1496
1609
|
serverId,
|
|
1497
1610
|
channelId,
|
|
1498
1611
|
epochId: current.tuneOut.epochId,
|
|
1499
|
-
wakeCount
|
|
1612
|
+
wakeCount,
|
|
1500
1613
|
timestamp: new Date().toISOString(),
|
|
1501
1614
|
});
|
|
1502
|
-
|
|
1615
|
+
current.wakeCount = wakeCount;
|
|
1616
|
+
return { params: current.tuneOut, wakeCount };
|
|
1503
1617
|
}
|
|
1504
1618
|
/** Active tune-out params + wake count for a channel, or null. */
|
|
1505
1619
|
getTuneOutState(serverId, channelId) {
|
|
@@ -1523,19 +1637,13 @@ export class ChannelRegistry {
|
|
|
1523
1637
|
readCoordinatorState(stateId) {
|
|
1524
1638
|
if (!this.store)
|
|
1525
1639
|
return null;
|
|
1526
|
-
|
|
1527
|
-
this.store.registerState({ id: stateId, strategy: 'snapshot' });
|
|
1528
|
-
}
|
|
1529
|
-
catch { /* already registered */ }
|
|
1640
|
+
ensureStateRegistered(this.store, { id: stateId, strategy: 'snapshot' });
|
|
1530
1641
|
return this.store.getStateJson(stateId);
|
|
1531
1642
|
}
|
|
1532
1643
|
writeCoordinatorState(stateId, value) {
|
|
1533
1644
|
if (!this.store)
|
|
1534
1645
|
return;
|
|
1535
|
-
|
|
1536
|
-
this.store.registerState({ id: stateId, strategy: 'snapshot' });
|
|
1537
|
-
}
|
|
1538
|
-
catch { /* already registered */ }
|
|
1646
|
+
ensureStateRegistered(this.store, { id: stateId, strategy: 'snapshot' });
|
|
1539
1647
|
this.store.setStateJson(stateId, value);
|
|
1540
1648
|
}
|
|
1541
1649
|
/**
|
|
@@ -1566,13 +1674,13 @@ export class ChannelRegistry {
|
|
|
1566
1674
|
: 'closed';
|
|
1567
1675
|
this.setDesiredState(serverId, channel.id, desired, 'legacy-recipe-migration');
|
|
1568
1676
|
}
|
|
1569
|
-
this.migratedLegacyPolicies.add(serverId);
|
|
1570
1677
|
this.appendLifecycleEvent({
|
|
1571
1678
|
kind: 'legacy-policy-migrated',
|
|
1572
1679
|
serverId,
|
|
1573
1680
|
source: Array.isArray(policy) ? 'allow-list' : policy,
|
|
1574
1681
|
timestamp: new Date().toISOString(),
|
|
1575
1682
|
});
|
|
1683
|
+
this.migratedLegacyPolicies.add(serverId);
|
|
1576
1684
|
}
|
|
1577
1685
|
/**
|
|
1578
1686
|
* True when the server's recipe subscription policy wants this channel
|
|
@@ -1688,9 +1796,9 @@ export class ChannelRegistry {
|
|
|
1688
1796
|
});
|
|
1689
1797
|
}
|
|
1690
1798
|
}
|
|
1691
|
-
// Announce policy admissions to the agent —
|
|
1692
|
-
//
|
|
1693
|
-
//
|
|
1799
|
+
// Announce policy admissions to the agent — no channel may open without
|
|
1800
|
+
// them being told, and told how to opt out (channel_close; their
|
|
1801
|
+
// decision outranks policy).
|
|
1694
1802
|
if (policyOpened.length > 0) {
|
|
1695
1803
|
try {
|
|
1696
1804
|
this.onChannelAutoOpened?.({
|
|
@@ -2048,11 +2156,13 @@ export class ChannelRegistry {
|
|
|
2048
2156
|
// A tuned-out channel is transport-open but attention-diverted; a plain
|
|
2049
2157
|
// open would silently discard the epoch (and its pending backlog dump).
|
|
2050
2158
|
// Cancelling is the tune-out coordinator's flow, reached via its own
|
|
2051
|
-
// tool — refuse with the pointer rather than eat the state.
|
|
2159
|
+
// tool — refuse with the pointer rather than eat the state. As an error
|
|
2160
|
+
// result, the agent reads the pointer itself; `data` names the refusal
|
|
2161
|
+
// for an in-process caller.
|
|
2052
2162
|
if (this.getDesiredState(entry.serverId, input.channelId) === 'tuned-out') {
|
|
2053
2163
|
return {
|
|
2054
2164
|
success: false,
|
|
2055
|
-
isError:
|
|
2165
|
+
isError: true,
|
|
2056
2166
|
error: `Channel ${input.channelId} is tuned out. Cancel the tune-out ` +
|
|
2057
2167
|
`(tune_out with mode: 'cancel') to resume normal attention — ` +
|
|
2058
2168
|
`cancelling delivers the diverted backlog.`,
|
|
@@ -2189,7 +2299,7 @@ export class ChannelRegistry {
|
|
|
2189
2299
|
if (entry.open || this.getDesiredState(entry.serverId, input.channelId) === 'open') {
|
|
2190
2300
|
return {
|
|
2191
2301
|
success: false,
|
|
2192
|
-
error: `Channel is already open: ${input.channelId}. Use channel_close to
|
|
2302
|
+
error: `Channel is already open: ${input.channelId}. Use channel_close to close it.`,
|
|
2193
2303
|
isError: true,
|
|
2194
2304
|
};
|
|
2195
2305
|
}
|
|
@@ -2295,12 +2405,13 @@ export class ChannelRegistry {
|
|
|
2295
2405
|
*/
|
|
2296
2406
|
handleToolSkipReply(input) {
|
|
2297
2407
|
// The self-wake itself is armed by the framework (which owns the
|
|
2298
|
-
// EventGate) BEFORE
|
|
2299
|
-
//
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2408
|
+
// EventGate) BEFORE its dispatch reaches this handler, from the same
|
|
2409
|
+
// reading, and the framework refuses a wake the host can't set before
|
|
2410
|
+
// dispatching. A caller of this registry's handleChannelToolCall
|
|
2411
|
+
// (AgentFramework.channels) goes past both, so its note names a wake
|
|
2412
|
+
// nothing armed.
|
|
2413
|
+
const wake = readSkipReplyWake(input);
|
|
2414
|
+
const selfWake = wake.kind === 'wake' ? wake.seconds : undefined;
|
|
2304
2415
|
return {
|
|
2305
2416
|
success: true,
|
|
2306
2417
|
// The note says "ended the turn" — make it TRUE. Without endTurn the
|
|
@@ -2386,7 +2497,158 @@ export class ChannelRegistry {
|
|
|
2386
2497
|
const home = this.homeChannelResolver?.(conversationId);
|
|
2387
2498
|
return home ?? this.activeChannelResolver?.(conversationId) ?? this.defaultPublishChannel ?? null;
|
|
2388
2499
|
}
|
|
2389
|
-
|
|
2500
|
+
/**
|
|
2501
|
+
* Resolve a publish target to exactly one registered channel: `serverId`
|
|
2502
|
+
* plus `channelId` when the caller has the server, otherwise a channel id
|
|
2503
|
+
* registered by exactly one server. A shared id is refused, never resolved
|
|
2504
|
+
* to whichever server registered it first.
|
|
2505
|
+
*/
|
|
2506
|
+
resolveDestination(target) {
|
|
2507
|
+
const entry = this.findExactEntry(target);
|
|
2508
|
+
if ('error' in entry)
|
|
2509
|
+
return entry;
|
|
2510
|
+
return {
|
|
2511
|
+
destination: {
|
|
2512
|
+
serverId: entry.entry.serverId,
|
|
2513
|
+
channelId: entry.entry.descriptor.id,
|
|
2514
|
+
...(entry.entry.descriptor.label ? { label: entry.entry.descriptor.label } : {}),
|
|
2515
|
+
},
|
|
2516
|
+
};
|
|
2517
|
+
}
|
|
2518
|
+
findExactEntry(target) {
|
|
2519
|
+
// A supplied selector is checked, never read as omission: an empty or
|
|
2520
|
+
// non-string serverId would otherwise widen to "any server".
|
|
2521
|
+
if (typeof target.channelId !== 'string' || !target.channelId) {
|
|
2522
|
+
return { error: 'the destination names no channel id' };
|
|
2523
|
+
}
|
|
2524
|
+
if (target.serverId !== undefined && (typeof target.serverId !== 'string' || !target.serverId)) {
|
|
2525
|
+
return { error: 'serverId must name a server (omit it to resolve the channel id alone)' };
|
|
2526
|
+
}
|
|
2527
|
+
const matches = [...this.channels.values()].filter((e) => e.descriptor.id === target.channelId && (!target.serverId || e.serverId === target.serverId));
|
|
2528
|
+
if (matches.length === 0) {
|
|
2529
|
+
return {
|
|
2530
|
+
error: target.serverId
|
|
2531
|
+
? `no registered channel "${target.channelId}" on server "${target.serverId}"`
|
|
2532
|
+
: `no registered channel "${target.channelId}"`,
|
|
2533
|
+
};
|
|
2534
|
+
}
|
|
2535
|
+
if (matches.length > 1) {
|
|
2536
|
+
return {
|
|
2537
|
+
error: `channel id "${target.channelId}" is registered by more than one MCPL server; the destination must name its server`,
|
|
2538
|
+
};
|
|
2539
|
+
}
|
|
2540
|
+
return { entry: matches[0] };
|
|
2541
|
+
}
|
|
2542
|
+
/**
|
|
2543
|
+
* Publish `text` to one registered channel and report what the attempt
|
|
2544
|
+
* established (PublishOutcome). The delivery executor behind plain speech
|
|
2545
|
+
* (deliverSpeech / routeSpeech) and resident resends of held drafts.
|
|
2546
|
+
* channel_publish (and publishForAgent, which shares its handler) resolves
|
|
2547
|
+
* and sends on its own path, and reads its answer through the same
|
|
2548
|
+
* publishReceiptOutcome and publishErrorOutcome.
|
|
2549
|
+
*
|
|
2550
|
+
* Resolution is exact (resolveDestination): `serverId` plus `channelId`
|
|
2551
|
+
* when the caller has the server, otherwise the channel id must be
|
|
2552
|
+
* registered by exactly one server (a shared id is refused, never routed
|
|
2553
|
+
* through whichever server came first). An omitted `serverId` means "not
|
|
2554
|
+
* in use"; a supplied one must be a non-empty server id, and an empty or
|
|
2555
|
+
* non-string selector is refused rather than read as omission. It is not
|
|
2556
|
+
* possible to send into a closed channel: a closed but registered
|
|
2557
|
+
* destination is opened first (`openSource` names why), once its server
|
|
2558
|
+
* and that server's channels.publish grant are known to take the send, so
|
|
2559
|
+
* a refused send opens nothing; and a failed open sends nothing.
|
|
2560
|
+
*
|
|
2561
|
+
* Only the connector's `delivered: true` confirms a post. `failed` means
|
|
2562
|
+
* nothing was posted: the attempt stopped before the request was written,
|
|
2563
|
+
* or the connector answered `delivered: false` and named no message (no
|
|
2564
|
+
* `messageId`, or null). Everything else is `unknown`: once the request
|
|
2565
|
+
* has been handed to the transport, an error response, a timeout, a lost
|
|
2566
|
+
* connection, or a missing, malformed or contradictory receipt (such as
|
|
2567
|
+
* `delivered: false` beside a message id, valid or not) means the post may
|
|
2568
|
+
* or may not exist, and the caller must not treat it as safe to retry
|
|
2569
|
+
* blindly.
|
|
2570
|
+
*/
|
|
2571
|
+
async publish(conversationId, text, target, openSource = 'opened-by-delivery') {
|
|
2572
|
+
const at = () => Date.now();
|
|
2573
|
+
const found = this.findExactEntry(target);
|
|
2574
|
+
if ('error' in found)
|
|
2575
|
+
return { status: 'failed', reason: found.error, at: at() };
|
|
2576
|
+
const entry = found.entry;
|
|
2577
|
+
const destination = {
|
|
2578
|
+
serverId: entry.serverId,
|
|
2579
|
+
channelId: entry.descriptor.id,
|
|
2580
|
+
...(entry.descriptor.label ? { label: entry.descriptor.label } : {}),
|
|
2581
|
+
};
|
|
2582
|
+
// A send that would be refused is refused before anything opens: a
|
|
2583
|
+
// closed channel opens only for words that can go out.
|
|
2584
|
+
const server = this.serverRegistry.getServer(entry.serverId);
|
|
2585
|
+
if (!server) {
|
|
2586
|
+
return { status: 'failed', destination, reason: `server "${entry.serverId}" not found`, at: at() };
|
|
2587
|
+
}
|
|
2588
|
+
// §14.1: channels/publish requires channels.publish in the grant. The
|
|
2589
|
+
// host not sending is the enforcement.
|
|
2590
|
+
if (!CapabilityGrant.of(server).has('channels.publish')) {
|
|
2591
|
+
return {
|
|
2592
|
+
status: 'failed',
|
|
2593
|
+
destination,
|
|
2594
|
+
reason: `channels.publish not in "${entry.serverId}"'s effective grant (§14.1)`,
|
|
2595
|
+
at: at(),
|
|
2596
|
+
};
|
|
2597
|
+
}
|
|
2598
|
+
if (!entry.open) {
|
|
2599
|
+
try {
|
|
2600
|
+
await this.openChannelNow(entry, openSource);
|
|
2601
|
+
if (target.routed) {
|
|
2602
|
+
console.error(`[routeSpeech] ${conversationId}: locus ${logValue(entry.descriptor.id)} was closed — opened by delivery (speech implies engagement)`);
|
|
2603
|
+
}
|
|
2604
|
+
this.emitTraceFn({
|
|
2605
|
+
type: 'mcpl:channel-opened-by-send',
|
|
2606
|
+
serverId: entry.serverId,
|
|
2607
|
+
channelId: entry.descriptor.id,
|
|
2608
|
+
});
|
|
2609
|
+
if (openSource === 'opened-by-delivery') {
|
|
2610
|
+
try {
|
|
2611
|
+
this.onChannelAutoOpened?.({
|
|
2612
|
+
conversationId,
|
|
2613
|
+
serverId: entry.serverId,
|
|
2614
|
+
source: 'opened-by-delivery',
|
|
2615
|
+
channels: [{ channelId: entry.descriptor.id, label: entry.descriptor.label }],
|
|
2616
|
+
});
|
|
2617
|
+
}
|
|
2618
|
+
catch (err) {
|
|
2619
|
+
console.error('onChannelAutoOpened (delivery) failed:', err);
|
|
2620
|
+
}
|
|
2621
|
+
}
|
|
2622
|
+
}
|
|
2623
|
+
catch (err) {
|
|
2624
|
+
return {
|
|
2625
|
+
status: 'failed',
|
|
2626
|
+
destination,
|
|
2627
|
+
reason: `channel is closed and open failed: ${connectorText(err instanceof Error ? err.message : String(err))}`,
|
|
2628
|
+
at: at(),
|
|
2629
|
+
};
|
|
2630
|
+
}
|
|
2631
|
+
}
|
|
2632
|
+
let result;
|
|
2633
|
+
try {
|
|
2634
|
+
result = await server.sendChannelsPublish({
|
|
2635
|
+
conversationId,
|
|
2636
|
+
channelId: entry.descriptor.id,
|
|
2637
|
+
content: [{ type: 'text', text }],
|
|
2638
|
+
});
|
|
2639
|
+
}
|
|
2640
|
+
catch (err) {
|
|
2641
|
+
return publishErrorOutcome(err, destination, at());
|
|
2642
|
+
}
|
|
2643
|
+
return publishReceiptOutcome(result, destination, at());
|
|
2644
|
+
}
|
|
2645
|
+
/**
|
|
2646
|
+
* Plain speech for one turn segment: publish `text` to the turn's frozen
|
|
2647
|
+
* locus and report the PublishOutcome. A failure (or an uncertain outcome)
|
|
2648
|
+
* is surfaced as a trace and through onRouteFailure, so the agent learns
|
|
2649
|
+
* its words did not (or may not have) reached anyone.
|
|
2650
|
+
*/
|
|
2651
|
+
async deliverSpeech(conversationId, text,
|
|
2390
2652
|
/** The turn's FROZEN locus, snapshotted once by the caller (resolveLocus
|
|
2391
2653
|
* at turn start) and passed to every segment of the turn. Mandatory:
|
|
2392
2654
|
* there is deliberately no live-resolution fallback here — a late
|
|
@@ -2394,110 +2656,75 @@ export class ChannelRegistry {
|
|
|
2394
2656
|
* stale global default and land the reply in the wrong channel (item-3,
|
|
2395
2657
|
* PR #32, and the 2026-07-22 Sol DM misroute). Explicit `null` means
|
|
2396
2658
|
* "this turn is pinned to no locus": fail loudly rather than guess. */
|
|
2397
|
-
locusChannelId
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2659
|
+
locusChannelId,
|
|
2660
|
+
/** `heldOnFailure`: the caller holds a `failed` delivery's words as a
|
|
2661
|
+
* draft with its own notice, so no failure marker is written for it.
|
|
2662
|
+
* An `unknown` outcome still gets its marker. */
|
|
2663
|
+
opts) {
|
|
2664
|
+
const fail = (channelId, reason, outcome) => {
|
|
2665
|
+
const status = outcome.status === 'unknown' ? 'unknown' : 'failed';
|
|
2666
|
+
const detail = outcome.detail !== undefined ? connectorText(outcome.detail) : undefined;
|
|
2667
|
+
const detailText = detail !== undefined ? `; connector detail: ${detail}` : '';
|
|
2668
|
+
console.error(`[routeSpeech] ${conversationId}: ${reason}${detailText} — speech ${status === 'unknown' ? 'delivery NOT confirmed' : 'NOT routed'} (${text.length} chars stay in chronicle)`);
|
|
2403
2669
|
this.emitTraceFn({
|
|
2404
2670
|
type: 'mcpl:speech-route-failed',
|
|
2405
2671
|
conversationId,
|
|
2406
2672
|
channelId: channelId ?? '',
|
|
2407
2673
|
reason,
|
|
2408
2674
|
textLen: text.length,
|
|
2675
|
+
outcome: status,
|
|
2676
|
+
...(detail !== undefined ? { detail } : {}),
|
|
2409
2677
|
});
|
|
2410
|
-
|
|
2411
|
-
|
|
2678
|
+
if (status === 'unknown' || !opts?.heldOnFailure) {
|
|
2679
|
+
this.onRouteFailure?.({ conversationId, channelId, reason, textLen: text.length, outcome: status, ...(detail !== undefined ? { detail } : {}) });
|
|
2680
|
+
}
|
|
2681
|
+
return outcome;
|
|
2412
2682
|
};
|
|
2413
2683
|
// Runtime backstop for JS callers the compiler can't see: an omitted
|
|
2414
2684
|
// locus is a routing bug at the call site, never something to paper over
|
|
2415
2685
|
// with a live re-resolution.
|
|
2416
2686
|
if (locusChannelId === undefined) {
|
|
2417
|
-
|
|
2687
|
+
const reason = 'caller passed no locus (routing bug: every speech path must snapshot the turn locus)';
|
|
2688
|
+
return fail(null, reason, { status: 'failed', reason, at: Date.now() });
|
|
2418
2689
|
}
|
|
2419
|
-
|
|
2420
|
-
if (!channelId) {
|
|
2690
|
+
if (!locusChannelId) {
|
|
2421
2691
|
// The turn froze with no locus (no home, no triggering channel, no
|
|
2422
2692
|
// global inbound ever seen) — the agent was told its prose stays in
|
|
2423
2693
|
// the archive; honor that.
|
|
2424
|
-
|
|
2694
|
+
const reason = 'turn has no locus (no home/trigger channel; nothing to deliver into)';
|
|
2695
|
+
return fail(null, reason, { status: 'failed', reason, at: Date.now() });
|
|
2425
2696
|
}
|
|
2426
|
-
const
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
// INVARIANT: it is not possible to send into a closed channel. Speech
|
|
2431
|
-
// routed into a closed-but-registered locus (the canonical case: a DM
|
|
2432
|
-
// that woke the agent — DMs register closed) OPENS the channel first,
|
|
2433
|
-
// so typing indicators, reaction machinery, and inbound forwarding come
|
|
2434
|
-
// alive with the reply. If the open fails, the speech does NOT go out:
|
|
2435
|
-
// a half-alive delivery is worse than a loud marker.
|
|
2436
|
-
if (!entry.open) {
|
|
2437
|
-
try {
|
|
2438
|
-
await this.openChannelNow(entry, 'opened-by-delivery');
|
|
2439
|
-
console.error(`[routeSpeech] ${conversationId}: locus ${channelId} was closed — opened by delivery (speech implies engagement)`);
|
|
2440
|
-
this.emitTraceFn({
|
|
2441
|
-
type: 'mcpl:channel-opened-by-send',
|
|
2442
|
-
serverId: entry.serverId,
|
|
2443
|
-
channelId,
|
|
2444
|
-
});
|
|
2445
|
-
try {
|
|
2446
|
-
this.onChannelAutoOpened?.({
|
|
2447
|
-
conversationId,
|
|
2448
|
-
serverId: entry.serverId,
|
|
2449
|
-
source: 'opened-by-delivery',
|
|
2450
|
-
channels: [{ channelId, label: entry.descriptor.label }],
|
|
2451
|
-
});
|
|
2452
|
-
}
|
|
2453
|
-
catch (err) {
|
|
2454
|
-
console.error('onChannelAutoOpened (delivery) failed:', err);
|
|
2455
|
-
}
|
|
2456
|
-
}
|
|
2457
|
-
catch (err) {
|
|
2458
|
-
return fail(channelId, `locus channel is closed and open failed: ${err.message}`);
|
|
2459
|
-
}
|
|
2697
|
+
const outcome = await this.publish(conversationId, text, { channelId: locusChannelId, routed: true });
|
|
2698
|
+
const channelId = outcome.destination?.channelId ?? locusChannelId;
|
|
2699
|
+
if (outcome.status !== 'delivered') {
|
|
2700
|
+
return fail(channelId, outcome.reason ?? 'delivery not confirmed', outcome);
|
|
2460
2701
|
}
|
|
2461
|
-
|
|
2462
|
-
if (!server) {
|
|
2463
|
-
return fail(channelId, `server "${entry.serverId}" not found`);
|
|
2464
|
-
}
|
|
2465
|
-
// §14.1: channels/publish requires channels.publish in the grant. The
|
|
2466
|
-
// host not sending is the enforcement — a send to an ungranted server
|
|
2467
|
-
// would have it act on authority it was never told it has.
|
|
2468
|
-
if (!CapabilityGrant.of(server).has('channels.publish')) {
|
|
2469
|
-
return fail(channelId, `channels.publish not in "${entry.serverId}"'s effective grant (§14.1)`);
|
|
2470
|
-
}
|
|
2471
|
-
const publishParams = {
|
|
2472
|
-
conversationId,
|
|
2473
|
-
channelId,
|
|
2474
|
-
content: [{ type: 'text', text }],
|
|
2475
|
-
};
|
|
2476
|
-
const result = await server.sendChannelsPublish(publishParams);
|
|
2477
|
-
const delivered = result?.delivered ?? true;
|
|
2478
|
-
// Surface the posted message's id (ChannelsPublishResult.messageId) so
|
|
2479
|
-
// trace consumers can act on the just-posted message — e.g. a TTS-relay
|
|
2480
|
-
// tap editing it down to the words actually voiced on interruption.
|
|
2481
|
-
// Previously this was silently dropped here.
|
|
2482
|
-
const messageId = result?.messageId;
|
|
2483
|
-
// The server accepted the publish RPC but reported the message was not
|
|
2484
|
-
// actually delivered (e.g. missing Send Messages permission). Previously
|
|
2485
|
-
// this returned `{ delivered: true }`, masking the failure. Surface it.
|
|
2486
|
-
if (delivered === false) {
|
|
2487
|
-
return fail(channelId, `server "${entry.serverId}" reported delivered:false for "${channelId}"`);
|
|
2488
|
-
}
|
|
2489
|
-
console.error(`[routeSpeech] ${conversationId}: routed ${text.length} chars -> ${channelId} (server=${entry.serverId}, delivered=${delivered})`);
|
|
2702
|
+
console.error(`[routeSpeech] ${conversationId}: routed ${text.length} chars -> ${logValue(channelId)} (server=${outcome.destination.serverId}, delivered=true)`);
|
|
2490
2703
|
this.emitTraceFn({
|
|
2491
2704
|
type: 'mcpl:speech-routed',
|
|
2492
2705
|
conversationId,
|
|
2493
|
-
serverId:
|
|
2706
|
+
serverId: outcome.destination.serverId,
|
|
2494
2707
|
channelId,
|
|
2495
|
-
delivered,
|
|
2708
|
+
delivered: true,
|
|
2496
2709
|
textLen: text.length,
|
|
2497
2710
|
text,
|
|
2498
|
-
|
|
2711
|
+
// Surface the posted message's id (ChannelsPublishResult.messageId) so
|
|
2712
|
+
// trace consumers can act on the just-posted message — e.g. a TTS-relay
|
|
2713
|
+
// tap editing it down to the words actually voiced on interruption.
|
|
2714
|
+
...(outcome.messageId !== undefined ? { messageId: outcome.messageId } : {}),
|
|
2499
2715
|
});
|
|
2500
|
-
return
|
|
2716
|
+
return outcome;
|
|
2717
|
+
}
|
|
2718
|
+
/** deliverSpeech, reduced to the confirmed delivery (null when there was none). */
|
|
2719
|
+
async routeSpeech(conversationId, text, locusChannelId) {
|
|
2720
|
+
const outcome = await this.deliverSpeech(conversationId, text, locusChannelId);
|
|
2721
|
+
if (outcome.status !== 'delivered')
|
|
2722
|
+
return null;
|
|
2723
|
+
return {
|
|
2724
|
+
delivered: true,
|
|
2725
|
+
channelId: outcome.destination.channelId,
|
|
2726
|
+
...(outcome.messageId !== undefined ? { messageId: outcome.messageId } : {}),
|
|
2727
|
+
};
|
|
2501
2728
|
}
|
|
2502
2729
|
async handleToolPublish(input) {
|
|
2503
2730
|
// Resolve content: accept both `content` and `text` (backward compat)
|
|
@@ -2534,32 +2761,46 @@ export class ChannelRegistry {
|
|
|
2534
2761
|
isError: true,
|
|
2535
2762
|
};
|
|
2536
2763
|
}
|
|
2537
|
-
|
|
2538
|
-
if (!CapabilityGrant.of(server).has('channels.publish')) {
|
|
2539
|
-
return {
|
|
2540
|
-
success: false,
|
|
2541
|
-
error: `channels.publish not in "${server.id}"'s effective grant (§14.1)`,
|
|
2542
|
-
isError: true,
|
|
2543
|
-
};
|
|
2544
|
-
}
|
|
2545
|
-
const publishParams = {
|
|
2546
|
-
conversationId: '', // Framework will fill this when wired
|
|
2547
|
-
channelId,
|
|
2548
|
-
content: [{ type: 'text', text: messageText }],
|
|
2549
|
-
};
|
|
2550
|
-
const result = await server.sendChannelsPublish(publishParams);
|
|
2551
|
-
return {
|
|
2552
|
-
success: true,
|
|
2553
|
-
data: result ?? { delivered: true },
|
|
2554
|
-
};
|
|
2555
|
-
}
|
|
2556
|
-
catch (err) {
|
|
2764
|
+
if (!CapabilityGrant.of(server).has('channels.publish')) {
|
|
2557
2765
|
return {
|
|
2558
2766
|
success: false,
|
|
2559
|
-
error: `
|
|
2767
|
+
error: `channels.publish not in "${server.id}"'s effective grant (§14.1)`,
|
|
2560
2768
|
isError: true,
|
|
2561
2769
|
};
|
|
2562
2770
|
}
|
|
2771
|
+
const publishParams = {
|
|
2772
|
+
conversationId: '', // Framework will fill this when wired
|
|
2773
|
+
channelId,
|
|
2774
|
+
content: [{ type: 'text', text: messageText }],
|
|
2775
|
+
};
|
|
2776
|
+
const destination = {
|
|
2777
|
+
serverId: entry.serverId,
|
|
2778
|
+
channelId: entry.descriptor.id,
|
|
2779
|
+
...(entry.descriptor.label ? { label: entry.descriptor.label } : {}),
|
|
2780
|
+
};
|
|
2781
|
+
// The answer counts by the same rule as plain speech's: only the
|
|
2782
|
+
// connector's delivered:true confirms a post.
|
|
2783
|
+
let result;
|
|
2784
|
+
let outcome;
|
|
2785
|
+
try {
|
|
2786
|
+
result = await server.sendChannelsPublish(publishParams);
|
|
2787
|
+
outcome = publishReceiptOutcome(result, destination, Date.now());
|
|
2788
|
+
}
|
|
2789
|
+
catch (err) {
|
|
2790
|
+
outcome = publishErrorOutcome(err, destination, Date.now());
|
|
2791
|
+
}
|
|
2792
|
+
if (outcome.status === 'delivered')
|
|
2793
|
+
return { success: true, data: result };
|
|
2794
|
+
// The connector's data may say what a multi-part send already posted.
|
|
2795
|
+
const detail = outcome.status === 'unknown' && outcome.detail !== undefined ? ` Connector detail: ${connectorText(outcome.detail)}` : '';
|
|
2796
|
+
return {
|
|
2797
|
+
success: false,
|
|
2798
|
+
error: (outcome.status === 'failed'
|
|
2799
|
+
? `Publish to ${channelId} failed: ${outcome.reason}. Nothing was posted.`
|
|
2800
|
+
: `Publish to ${channelId} wasn't confirmed: ${outcome.reason}. ` +
|
|
2801
|
+
'It may or may not have been posted, so sending it again could post it twice.') + detail,
|
|
2802
|
+
isError: true,
|
|
2803
|
+
};
|
|
2563
2804
|
}
|
|
2564
2805
|
}
|
|
2565
2806
|
//# sourceMappingURL=channel-registry.js.map
|