@animalabs/agent-framework 0.22.2 → 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 +3 -1
- package/dist/src/agent.d.ts +77 -12
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +136 -40
- package/dist/src/agent.js.map +1 -1
- package/dist/src/api/mcp-server-core.js +1 -1
- package/dist/src/api/mcp-server-core.js.map +1 -1
- package/dist/src/api/server.d.ts.map +1 -1
- package/dist/src/api/server.js +5 -1
- package/dist/src/api/server.js.map +1 -1
- package/dist/src/api/types.d.ts +1 -1
- 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 +828 -88
- package/dist/src/framework.d.ts.map +1 -1
- package/dist/src/framework.js +5011 -1326
- 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/index.d.ts +4 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcpl/channel-registry.d.ts +144 -6
- package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
- package/dist/src/mcpl/channel-registry.js +424 -263
- 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/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/push-coalescer.d.ts +33 -11
- package/dist/src/mcpl/push-coalescer.d.ts.map +1 -1
- package/dist/src/mcpl/push-coalescer.js +52 -20
- package/dist/src/mcpl/push-coalescer.js.map +1 -1
- package/dist/src/mcpl/push-handler.d.ts +16 -9
- package/dist/src/mcpl/push-handler.d.ts.map +1 -1
- package/dist/src/mcpl/push-handler.js +18 -83
- 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 +47 -12
- 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/server-connection.d.ts +89 -10
- package/dist/src/mcpl/server-connection.d.ts.map +1 -1
- package/dist/src/mcpl/server-connection.js +405 -129
- 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/transport.d.ts +51 -2
- package/dist/src/mcpl/transport.d.ts.map +1 -1
- package/dist/src/mcpl/transport.js +114 -20
- package/dist/src/mcpl/transport.js.map +1 -1
- package/dist/src/mcpl/types.d.ts +14 -3
- 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.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 +379 -143
- 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/disk-agreement.d.ts +32 -2
- package/dist/src/modules/workspace/disk-agreement.d.ts.map +1 -1
- package/dist/src/modules/workspace/disk-agreement.js +30 -2
- 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 +119 -23
- package/dist/src/modules/workspace/index.d.ts.map +1 -1
- package/dist/src/modules/workspace/index.js +793 -247
- package/dist/src/modules/workspace/index.js.map +1 -1
- package/dist/src/modules/workspace/observe.d.ts +75 -8
- package/dist/src/modules/workspace/observe.d.ts.map +1 -1
- package/dist/src/modules/workspace/observe.js +174 -14
- package/dist/src/modules/workspace/observe.js.map +1 -1
- package/dist/src/modules/workspace/reconcile.d.ts +58 -7
- package/dist/src/modules/workspace/reconcile.d.ts.map +1 -1
- package/dist/src/modules/workspace/reconcile.js +521 -56
- package/dist/src/modules/workspace/reconcile.js.map +1 -1
- package/dist/src/modules/workspace/types.d.ts +18 -4
- 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/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/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 +3 -1
- package/dist/src/recovery/offline-branch.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/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/types/agent.d.ts +17 -5
- 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 +21 -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 +23 -4
- package/dist/src/types/module.d.ts.map +1 -1
- package/dist/src/types/trace.d.ts +95 -6
- 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 +3 -4
- package/src/agent.ts +162 -40
- package/src/api/mcp-server-core.ts +1 -1
- package/src/api/server.ts +4 -1
- package/src/api/types.ts +1 -1
- 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 +5352 -1388
- package/src/gate/event-gate.ts +28 -3
- package/src/index.ts +11 -2
- package/src/mcpl/channel-registry.ts +517 -286
- 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/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/push-coalescer.ts +60 -24
- package/src/mcpl/push-handler.ts +20 -90
- package/src/mcpl/reference-fetcher.ts +71 -26
- package/src/mcpl/references.ts +81 -22
- package/src/mcpl/server-connection.ts +427 -132
- package/src/mcpl/server-registry.ts +15 -4
- package/src/mcpl/skip-reply-wake.ts +73 -0
- package/src/mcpl/transport.ts +120 -18
- package/src/mcpl/types.ts +14 -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 +391 -158
- 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 +51 -3
- package/src/modules/workspace/effects.ts +279 -35
- package/src/modules/workspace/index.ts +810 -260
- package/src/modules/workspace/observe.ts +194 -20
- package/src/modules/workspace/reconcile.ts +619 -64
- package/src/modules/workspace/types.ts +18 -4
- 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 +4 -1
- package/src/safe-slice.ts +9 -1
- 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 +17 -7
- package/src/types/events.ts +17 -0
- package/src/types/framework.ts +21 -5
- package/src/types/inference-log.ts +1 -1
- package/src/types/module.ts +24 -4
- package/src/types/trace.ts +101 -6
- 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 -1598
- 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 -621
- 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 -371
- 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/discord-typing-keepalive.test.d.ts +0 -2
- package/dist/test/discord-typing-keepalive.test.d.ts.map +0 -1
- package/dist/test/discord-typing-keepalive.test.js +0 -77
- package/dist/test/discord-typing-keepalive.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 -1715
- 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 -74
- package/dist/test/helpers/coalescing-fixture.d.ts.map +0 -1
- package/dist/test/helpers/coalescing-fixture.js +0 -152
- 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/hide-then-turn.test.d.ts +0 -2
- package/dist/test/hide-then-turn.test.d.ts.map +0 -1
- package/dist/test/hide-then-turn.test.js +0 -101
- package/dist/test/hide-then-turn.test.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 -988
- 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 -387
- 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 -1202
- 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 -1827
- package/dist/test/maintenance-timer.test.js.map +0 -1
- package/dist/test/mcp-server-bin.test.d.ts +0 -2
- package/dist/test/mcp-server-bin.test.d.ts.map +0 -1
- package/dist/test/mcp-server-bin.test.js +0 -142
- package/dist/test/mcp-server-bin.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-coalesced-content-parity.test.d.ts +0 -2
- package/dist/test/mcpl-coalesced-content-parity.test.d.ts.map +0 -1
- package/dist/test/mcpl-coalesced-content-parity.test.js +0 -532
- package/dist/test/mcpl-coalesced-content-parity.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 -238
- 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-rejection-log-lines.test.d.ts +0 -2
- package/dist/test/mcpl-rejection-log-lines.test.d.ts.map +0 -1
- package/dist/test/mcpl-rejection-log-lines.test.js +0 -349
- package/dist/test/mcpl-rejection-log-lines.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-stderr-tail.test.d.ts +0 -2
- package/dist/test/mcpl-stderr-tail.test.d.ts.map +0 -1
- package/dist/test/mcpl-stderr-tail.test.js +0 -210
- package/dist/test/mcpl-stderr-tail.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-transport-close.test.d.ts +0 -2
- package/dist/test/mcpl-transport-close.test.d.ts.map +0 -1
- package/dist/test/mcpl-transport-close.test.js +0 -373
- package/dist/test/mcpl-transport-close.test.js.map +0 -1
- package/dist/test/mcpl-transport-spawn.test.d.ts +0 -2
- package/dist/test/mcpl-transport-spawn.test.d.ts.map +0 -1
- package/dist/test/mcpl-transport-spawn.test.js +0 -58
- package/dist/test/mcpl-transport-spawn.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 -259
- 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 -570
- 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 -595
- 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 -198
- package/dist/test/overbudget-drain-breaker.test.js.map +0 -1
- package/dist/test/pack-installs-alone.test.d.ts +0 -2
- package/dist/test/pack-installs-alone.test.d.ts.map +0 -1
- package/dist/test/pack-installs-alone.test.js +0 -284
- package/dist/test/pack-installs-alone.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 -16
- package/dist/test/physical-window-restart.test.d.ts.map +0 -1
- package/dist/test/physical-window-restart.test.js +0 -487
- 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 -1649
- 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 -2259
- 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 -226
- 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 -117
- 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-bump.test.d.ts +0 -2
- package/dist/test/release-bump.test.d.ts.map +0 -1
- package/dist/test/release-bump.test.js +0 -248
- package/dist/test/release-bump.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/release-holds.test.d.ts +0 -2
- package/dist/test/release-holds.test.d.ts.map +0 -1
- package/dist/test/release-holds.test.js +0 -456
- package/dist/test/release-holds.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-host-operations.test.d.ts +0 -20
- package/dist/test/stop-with-host-operations.test.d.ts.map +0 -1
- package/dist/test/stop-with-host-operations.test.js +0 -1174
- package/dist/test/stop-with-host-operations.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 -784
- 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 -3729
- 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 -652
- 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/unsent-compiles.test.d.ts +0 -2
- package/dist/test/unsent-compiles.test.d.ts.map +0 -1
- package/dist/test/unsent-compiles.test.js +0 -139
- package/dist/test/unsent-compiles.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 -4094
- 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
|
@@ -14,8 +14,9 @@
|
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
import type { ContentBlock } from '@animalabs/membrane';
|
|
17
|
-
import {
|
|
17
|
+
import { convertBlock } from './convert-block.js';
|
|
18
18
|
import type { JsStore } from '@animalabs/chronicle';
|
|
19
|
+
import { ensureStateRegistered } from '../module-registry.js';
|
|
19
20
|
|
|
20
21
|
import type {
|
|
21
22
|
ChannelDescriptor,
|
|
@@ -30,7 +31,6 @@ import type {
|
|
|
30
31
|
ChannelsPublishParams,
|
|
31
32
|
ChannelsOpenResult,
|
|
32
33
|
ChannelHistoryRequest,
|
|
33
|
-
McplContentBlock,
|
|
34
34
|
} from './types.js';
|
|
35
35
|
|
|
36
36
|
import type { McplServerRegistry } from './server-registry.js';
|
|
@@ -38,10 +38,13 @@ import type { FeatureSetManager } from './feature-set-manager.js';
|
|
|
38
38
|
import type { ToolDefinition, ToolResult, ProcessEvent } from '../types/index.js';
|
|
39
39
|
import { expandCoreTags } from './tags.js';
|
|
40
40
|
import { coalesceRejectionReason, EmptyContentError, validateCoalescedContent } from './push-coalescer.js';
|
|
41
|
-
import {
|
|
41
|
+
import { isVisiblyEmptyConversion } from './visible-content.js';
|
|
42
42
|
import { logDetail, logValue } from './log-value.js';
|
|
43
43
|
import { RefusalLines } from './refusal-lines.js';
|
|
44
44
|
import { CapabilityGrant } from './capability-grant.js';
|
|
45
|
+
import type { InboundSource } from './inbound-source.js';
|
|
46
|
+
import { McplRequestError } from './server-connection.js';
|
|
47
|
+
import { readSkipReplyWake } from './skip-reply-wake.js';
|
|
45
48
|
|
|
46
49
|
// ============================================================================
|
|
47
50
|
// Typing indicator interval (Discord typing lasts ~10s, so 7s keeps it alive)
|
|
@@ -239,88 +242,10 @@ interface McplChannelIncomingEvent {
|
|
|
239
242
|
tags?: string[];
|
|
240
243
|
triggerInference?: boolean;
|
|
241
244
|
targetAgents?: string[];
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
// ============================================================================
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* Convert a single MCPL wire-format content block to a membrane ContentBlock.
|
|
250
|
-
*/
|
|
251
|
-
function convertBlock(block: McplContentBlock): ContentBlock {
|
|
252
|
-
switch (block.type) {
|
|
253
|
-
case 'text':
|
|
254
|
-
// Text that isn't a string is no text, as the request sanitizer and
|
|
255
|
-
// the visible-content check already read it.
|
|
256
|
-
return { type: 'text', text: typeof block.text === 'string' ? block.text : '' };
|
|
257
|
-
|
|
258
|
-
case 'image':
|
|
259
|
-
if (isInlineContradiction(block)) {
|
|
260
|
-
// RFC-005 vector 2: inline data claiming bulk disposition — fail
|
|
261
|
-
// closed, withhold the data (checked BEFORE the data branch).
|
|
262
|
-
return { type: 'text', text: INLINE_WITHHELD_TEXT };
|
|
263
|
-
}
|
|
264
|
-
if (isFilledString(block.uri) && block.disposition) {
|
|
265
|
-
// RFC-005 uri-form media with a disposition claim: stub, do not
|
|
266
|
-
// hand the URI to the provider or inline it.
|
|
267
|
-
return { type: 'text', text: referenceStubOrNull(block, 'attachment on channel message') ?? '[reference]' };
|
|
268
|
-
}
|
|
269
|
-
if (isFilledString(block.data) && isFilledString(block.mimeType)) {
|
|
270
|
-
return {
|
|
271
|
-
type: 'image',
|
|
272
|
-
source: { type: 'base64', data: block.data, mediaType: block.mimeType },
|
|
273
|
-
} as ContentBlock;
|
|
274
|
-
}
|
|
275
|
-
if (isFilledString(block.uri)) {
|
|
276
|
-
return {
|
|
277
|
-
type: 'image',
|
|
278
|
-
source: { type: 'url', url: block.uri },
|
|
279
|
-
} as ContentBlock;
|
|
280
|
-
}
|
|
281
|
-
return { type: 'text', text: isFilledString(block.data) ? '[Image: no media type]' : '[Image: no data]' };
|
|
282
|
-
|
|
283
|
-
case 'audio':
|
|
284
|
-
if (isInlineContradiction(block)) {
|
|
285
|
-
// RFC-005 vector 2: inline data claiming bulk disposition — fail
|
|
286
|
-
// closed, withhold the data (checked BEFORE the data branch).
|
|
287
|
-
return { type: 'text', text: INLINE_WITHHELD_TEXT };
|
|
288
|
-
}
|
|
289
|
-
if (isFilledString(block.uri) && block.disposition) {
|
|
290
|
-
// RFC-005 uri-form media with a disposition claim: stub, do not
|
|
291
|
-
// hand the URI to the provider or inline it.
|
|
292
|
-
return { type: 'text', text: referenceStubOrNull(block, 'attachment on channel message') ?? '[reference]' };
|
|
293
|
-
}
|
|
294
|
-
if (isFilledString(block.data) && isFilledString(block.mimeType)) {
|
|
295
|
-
return {
|
|
296
|
-
type: 'audio',
|
|
297
|
-
source: { type: 'base64', data: block.data, mediaType: block.mimeType },
|
|
298
|
-
} as ContentBlock;
|
|
299
|
-
}
|
|
300
|
-
return { type: 'text', text: isFilledString(block.data) ? '[Audio: no media type]' : '[Audio: no data]' };
|
|
301
|
-
|
|
302
|
-
case 'resource':
|
|
303
|
-
// RFC-005: reference blocks become bounded stubs — never raw URIs
|
|
304
|
-
// (a signed URL is a bearer credential that looks like a location).
|
|
305
|
-
return { type: 'text', text: referenceStubOrNull(block, 'attachment on channel message') ?? '[reference]' };
|
|
306
|
-
|
|
307
|
-
default: {
|
|
308
|
-
// Unknown wire block types previously fell off the exhaustive switch
|
|
309
|
-
// and propagated `undefined` into ContentBlock[]. Fail visibly. A type
|
|
310
|
-
// that isn't a string is no type, and is never converted to one: an
|
|
311
|
-
// object can throw when it is.
|
|
312
|
-
const type: unknown = (block as { type?: unknown }).type;
|
|
313
|
-
return { type: 'text', text: `[unrecognized content block: ${typeof type === 'string' ? type : 'untyped'}]` };
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
/** A string with something in it: the only data, mimeType or uri a block's
|
|
319
|
-
* source is built from, and the only uri that makes it a reference. Anything
|
|
320
|
-
* else a sender puts there leaves the block without it, so conversion never
|
|
321
|
-
* throws and never copies a non-string. */
|
|
322
|
-
function isFilledString(value: unknown): value is string {
|
|
323
|
-
return typeof value === 'string' && value !== '';
|
|
245
|
+
/** Host acceptance time (epoch ms), stamped where the message is admitted. */
|
|
246
|
+
acceptedAt?: number;
|
|
247
|
+
/** Source envelope frozen at admission (mcpl/inbound-source.ts). */
|
|
248
|
+
inboundSource?: InboundSource;
|
|
324
249
|
}
|
|
325
250
|
|
|
326
251
|
// ============================================================================
|
|
@@ -336,9 +261,8 @@ const CHANNEL_TOOL_DEFINITIONS: ToolDefinition[] = [
|
|
|
336
261
|
{
|
|
337
262
|
name: 'channel_open',
|
|
338
263
|
description:
|
|
339
|
-
'Open a channel
|
|
340
|
-
'
|
|
341
|
-
'history preceding the message that invited you into the channel.',
|
|
264
|
+
'Open a channel. What an open channel delivers to you depends on its MCPL server. ' +
|
|
265
|
+
'Optionally request history preceding the message that invited you into the channel.',
|
|
342
266
|
inputSchema: {
|
|
343
267
|
type: 'object' as const,
|
|
344
268
|
properties: {
|
|
@@ -378,7 +302,9 @@ const CHANNEL_TOOL_DEFINITIONS: ToolDefinition[] = [
|
|
|
378
302
|
},
|
|
379
303
|
{
|
|
380
304
|
name: 'channel_close',
|
|
381
|
-
description:
|
|
305
|
+
description:
|
|
306
|
+
'Close a channel. Messages that address you still reach you; what else stops reaching you ' +
|
|
307
|
+
'depends on its server.',
|
|
382
308
|
inputSchema: {
|
|
383
309
|
type: 'object' as const,
|
|
384
310
|
properties: {
|
|
@@ -457,8 +383,9 @@ const CHANNEL_TOOL_DEFINITIONS: ToolDefinition[] = [
|
|
|
457
383
|
type: 'number',
|
|
458
384
|
description:
|
|
459
385
|
'Optional self-wake: if nothing else wakes you first, you wake again after this ' +
|
|
460
|
-
'many seconds
|
|
461
|
-
'wake before then cancels it. Omit to stay idle until the
|
|
386
|
+
'many seconds, from 1 to 3600; a larger number waits 3600 (1 = go again almost ' +
|
|
387
|
+
'immediately). Any other wake before then cancels it. Omit to stay idle until the ' +
|
|
388
|
+
'next external wake.',
|
|
462
389
|
},
|
|
463
390
|
},
|
|
464
391
|
required: [],
|
|
@@ -470,7 +397,125 @@ const CHANNEL_TOOL_DEFINITIONS: ToolDefinition[] = [
|
|
|
470
397
|
// Constructor Options
|
|
471
398
|
// ============================================================================
|
|
472
399
|
|
|
400
|
+
/** Bound connector values for notices, logs and an outcome's reason. A
|
|
401
|
+
* PublishOutcome keeps the connector's structured data (`detail`) whole. */
|
|
402
|
+
export function connectorText(value: unknown): string {
|
|
403
|
+
let text: string;
|
|
404
|
+
try {
|
|
405
|
+
text = typeof value === 'string' ? value : JSON.stringify(value) ?? String(value);
|
|
406
|
+
} catch {
|
|
407
|
+
return '[unserializable connector value]';
|
|
408
|
+
}
|
|
409
|
+
const limit = 2000;
|
|
410
|
+
const suffix = '… [truncated]';
|
|
411
|
+
return text.length > limit ? text.slice(0, limit - suffix.length) + suffix : text;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/** Where a publish was resolved to go — named by the registry, never by
|
|
415
|
+
* the caller's spelling. */
|
|
416
|
+
export interface PublishDestination {
|
|
417
|
+
serverId: string;
|
|
418
|
+
channelId: string;
|
|
419
|
+
/** The channel's registered label when the attempt was made. */
|
|
420
|
+
label?: string;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* What one channels/publish attempt established (ChannelRegistry.publish).
|
|
425
|
+
* - `delivered`: the connector returned `delivered: true`. A historical
|
|
426
|
+
* receipt (confirmed at `at`, to `destination`, message `messageId` when
|
|
427
|
+
* the connector named one), not a claim the message still exists.
|
|
428
|
+
* - `failed`: nothing was posted: the request never left the host
|
|
429
|
+
* (unresolvable or shared channel id, missing grant, failed open, closed
|
|
430
|
+
* connection), or the connector answered `delivered: false` and named no
|
|
431
|
+
* message.
|
|
432
|
+
* - `unknown`: the request was dispatched and no valid receipt came back (an
|
|
433
|
+
* error response, a timeout, a lost connection, or a missing, malformed or
|
|
434
|
+
* contradictory receipt, such as `delivered: false` beside a message id).
|
|
435
|
+
* It may or may not have been posted.
|
|
436
|
+
*/
|
|
437
|
+
export interface PublishOutcome {
|
|
438
|
+
status: 'delivered' | 'failed' | 'unknown';
|
|
439
|
+
/** Absent only when no destination could be resolved. */
|
|
440
|
+
destination?: PublishDestination;
|
|
441
|
+
messageId?: string;
|
|
442
|
+
/** Why it failed, or why its outcome is unknown — for a connector error,
|
|
443
|
+
* its message, bounded (which may say what was already posted). */
|
|
444
|
+
reason?: string;
|
|
445
|
+
/** The connector error's structured `data`, verbatim, when it sent one. */
|
|
446
|
+
detail?: unknown;
|
|
447
|
+
/** When the outcome was established (epoch ms). */
|
|
448
|
+
at: number;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* What a channels/publish request that threw establishes. Only a request
|
|
453
|
+
* that never left the host proves nothing was posted. An error response may
|
|
454
|
+
* follow a partial post (a multi-part send whose later part failed), so it
|
|
455
|
+
* is unknown, with the connector's own words, bounded, and its data kept for
|
|
456
|
+
* the resident to judge. The publish executor and channel_publish both read
|
|
457
|
+
* a failed request this way.
|
|
458
|
+
*/
|
|
459
|
+
function publishErrorOutcome(err: unknown, destination: PublishDestination, at: number): PublishOutcome {
|
|
460
|
+
const message = connectorText(err instanceof Error ? err.message : String(err));
|
|
461
|
+
const notSent = err instanceof McplRequestError && err.outcome === 'not-sent';
|
|
462
|
+
const detail = err instanceof McplRequestError ? err.data : undefined;
|
|
463
|
+
return {
|
|
464
|
+
status: notSent ? 'failed' : 'unknown',
|
|
465
|
+
destination,
|
|
466
|
+
reason: notSent ? message : `${message} (delivery uncertain)`,
|
|
467
|
+
...(detail !== undefined ? { detail } : {}),
|
|
468
|
+
at,
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* What a channels/publish answer establishes. A final publish is a request,
|
|
474
|
+
* so success requires an explicit receipt; a missing or malformed one leaves
|
|
475
|
+
* delivery uncertain (anima-research/agent-framework#163's rule).
|
|
476
|
+
* `delivered: false` proves nothing went out only when the receipt names no
|
|
477
|
+
* message at all: a message id beside it, valid or malformed, contradicts it,
|
|
478
|
+
* since something may have been posted. The publish executor and
|
|
479
|
+
* channel_publish both read an answer this way.
|
|
480
|
+
*/
|
|
481
|
+
function publishReceiptOutcome(result: unknown, destination: PublishDestination, at: number): PublishOutcome {
|
|
482
|
+
const receipt = (result ?? {}) as { delivered?: unknown; messageId?: unknown };
|
|
483
|
+
const messageId = typeof receipt.messageId === 'string' && receipt.messageId ? receipt.messageId : undefined;
|
|
484
|
+
if (receipt.delivered === true) {
|
|
485
|
+
return { status: 'delivered', destination, ...(messageId ? { messageId } : {}), at };
|
|
486
|
+
}
|
|
487
|
+
if (receipt.delivered === false) {
|
|
488
|
+
if (receipt.messageId === undefined || receipt.messageId === null) {
|
|
489
|
+
return { status: 'failed', destination, reason: `server "${destination.serverId}" reported delivered:false`, at };
|
|
490
|
+
}
|
|
491
|
+
return {
|
|
492
|
+
status: 'unknown',
|
|
493
|
+
destination,
|
|
494
|
+
...(messageId ? { messageId } : {}),
|
|
495
|
+
reason: messageId
|
|
496
|
+
? `server "${destination.serverId}" reported delivered:false but named posted message ${connectorText(messageId)} (delivery uncertain)`
|
|
497
|
+
: `server "${destination.serverId}" reported delivered:false beside a malformed message id ` +
|
|
498
|
+
`${connectorText(receipt.messageId)} (contradictory receipt; delivery uncertain)`,
|
|
499
|
+
at,
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
return {
|
|
503
|
+
status: 'unknown',
|
|
504
|
+
destination,
|
|
505
|
+
...(messageId ? { messageId } : {}),
|
|
506
|
+
reason: `server "${destination.serverId}" returned no valid delivery receipt (delivery uncertain)`,
|
|
507
|
+
at,
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
|
|
473
511
|
interface ChannelRegistryOptions {
|
|
512
|
+
/**
|
|
513
|
+
* An ordinary (uncoalesced) `channels/incoming` message has just been
|
|
514
|
+
* admitted, before it is queued or acknowledged: return its source
|
|
515
|
+
* envelope, frozen now (mcpl/inbound-source.ts). The framework observes the
|
|
516
|
+
* acceptance here; coalesced work is stamped and observed by its own path.
|
|
517
|
+
*/
|
|
518
|
+
acceptInbound?: (event: McplChannelIncomingEvent) => InboundSource | undefined;
|
|
474
519
|
/**
|
|
475
520
|
* RFC-006: an admitted `channels/incoming` message carrying `coalesce`, with
|
|
476
521
|
* the event the ordinary path would have queued. The handler decides
|
|
@@ -499,15 +544,21 @@ interface ChannelRegistryOptions {
|
|
|
499
544
|
channelId: string | null;
|
|
500
545
|
reason: string;
|
|
501
546
|
textLen: number;
|
|
547
|
+
/** `failed`: nothing was posted; `unknown`: the request was dispatched
|
|
548
|
+
* and no valid receipt came back, so it may or may not have been. */
|
|
549
|
+
outcome?: 'failed' | 'unknown';
|
|
550
|
+
/** Bounded display of the connector's structured error data, when present. */
|
|
551
|
+
detail?: string;
|
|
502
552
|
}) => void;
|
|
503
553
|
/**
|
|
504
554
|
* Called when channels were opened WITHOUT the agent asking (subscription
|
|
505
555
|
* policy admitting a newly discovered channel, or delivery into a closed
|
|
506
556
|
* locus). The host wires this to drop a durable notice into the agent's
|
|
507
|
-
* window — the agent must always learn that
|
|
508
|
-
*
|
|
509
|
-
*
|
|
510
|
-
* durable, so reboots do not
|
|
557
|
+
* window — the agent must always learn that the channel opened, and that
|
|
558
|
+
* `channel_close` opts out (their decision outranks policy). What an open
|
|
559
|
+
* channel delivers is the server's to say (#406). Fires ONCE per channel
|
|
560
|
+
* ever: the desired-state decision is durable, so reboots do not
|
|
561
|
+
* re-announce. Must not trigger inference.
|
|
511
562
|
*/
|
|
512
563
|
onChannelAutoOpened?: (info: {
|
|
513
564
|
/** Agent whose action caused the open (delivery); absent for policy opens. */
|
|
@@ -543,6 +594,8 @@ interface ChannelRegistryOptions {
|
|
|
543
594
|
* `defaultPublishChannel`.
|
|
544
595
|
*/
|
|
545
596
|
activeChannelResolver?: (agentName: string) => string | undefined;
|
|
597
|
+
/** Whether this framework has EventGate and can honor skip_reply self-wakes. */
|
|
598
|
+
eventGatePresent?: boolean;
|
|
546
599
|
}
|
|
547
600
|
|
|
548
601
|
// ============================================================================
|
|
@@ -576,12 +629,7 @@ export class ChannelRegistry {
|
|
|
576
629
|
op?: 'start' | 'stop',
|
|
577
630
|
) => void;
|
|
578
631
|
private shouldTriggerInference?: (content: string, metadata: Record<string, unknown>) => boolean;
|
|
579
|
-
private onRouteFailure?:
|
|
580
|
-
conversationId: string;
|
|
581
|
-
channelId: string | null;
|
|
582
|
-
reason: string;
|
|
583
|
-
textLen: number;
|
|
584
|
-
}) => void;
|
|
632
|
+
private onRouteFailure?: ChannelRegistryOptions['onRouteFailure'];
|
|
585
633
|
private onChannelAutoOpened?: (info: {
|
|
586
634
|
conversationId?: string;
|
|
587
635
|
serverId: string;
|
|
@@ -680,6 +728,8 @@ export class ChannelRegistry {
|
|
|
680
728
|
private legacyPolicies = new Map<string, 'auto' | 'manual' | string[]>();
|
|
681
729
|
private migratedLegacyPolicies = new Set<string>();
|
|
682
730
|
private handleCoalescedIncoming?: ChannelRegistryOptions['handleCoalescedIncoming'];
|
|
731
|
+
private acceptInbound?: ChannelRegistryOptions['acceptInbound'];
|
|
732
|
+
private channelTools: ToolDefinition[];
|
|
683
733
|
|
|
684
734
|
constructor(
|
|
685
735
|
serverRegistry: McplServerRegistry,
|
|
@@ -696,6 +746,24 @@ export class ChannelRegistry {
|
|
|
696
746
|
},
|
|
697
747
|
) {
|
|
698
748
|
this.handleCoalescedIncoming = options?.handleCoalescedIncoming;
|
|
749
|
+
this.acceptInbound = options?.acceptInbound;
|
|
750
|
+
this.channelTools = CHANNEL_TOOL_DEFINITIONS.map((tool) => {
|
|
751
|
+
if (tool.name !== 'skip_reply' || options?.eventGatePresent === true) return tool;
|
|
752
|
+
const schema = tool.inputSchema as {
|
|
753
|
+
type: 'object';
|
|
754
|
+
properties: NonNullable<ToolDefinition['inputSchema']['properties']>;
|
|
755
|
+
required?: string[];
|
|
756
|
+
};
|
|
757
|
+
const { wake_in_seconds: _wake, ...properties } = schema.properties;
|
|
758
|
+
return {
|
|
759
|
+
...tool,
|
|
760
|
+
description: tool.description.replace(
|
|
761
|
+
' To end this turn but come back on your own shortly, set wake_in_seconds.',
|
|
762
|
+
'',
|
|
763
|
+
),
|
|
764
|
+
inputSchema: { ...schema, properties },
|
|
765
|
+
};
|
|
766
|
+
});
|
|
699
767
|
this.serverRegistry = serverRegistry;
|
|
700
768
|
this.featureSetManager = featureSetManager;
|
|
701
769
|
this.pushEventFn = pushEventFn;
|
|
@@ -1031,8 +1099,8 @@ export class ChannelRegistry {
|
|
|
1031
1099
|
}
|
|
1032
1100
|
}
|
|
1033
1101
|
if (message.tags) message.tags = expandCoreTags(message.tags);
|
|
1034
|
-
const convertedContent: ContentBlock[] = message.content.map(convertBlock);
|
|
1035
|
-
if (!emptyAllowed &&
|
|
1102
|
+
const convertedContent: ContentBlock[] = message.content.map((block) => convertBlock(block, 'attachment on channel message', serverId));
|
|
1103
|
+
if (!emptyAllowed && isVisiblyEmptyConversion(message.content, convertedContent)) {
|
|
1036
1104
|
rejectEmpty();
|
|
1037
1105
|
continue;
|
|
1038
1106
|
}
|
|
@@ -1060,7 +1128,7 @@ export class ChannelRegistry {
|
|
|
1060
1128
|
if (this.shouldTriggerInference) {
|
|
1061
1129
|
// The text the agent's context gets, as the push lane's filter reads
|
|
1062
1130
|
// it: the converted text blocks, a placeholder or reference stub
|
|
1063
|
-
// among them,
|
|
1131
|
+
// among them, NON_STRING_TEXT_PLACEHOLDER included.
|
|
1064
1132
|
const textContent = convertedContent
|
|
1065
1133
|
.filter((b): b is ContentBlock & { type: 'text' } => b.type === 'text')
|
|
1066
1134
|
.map((b) => b.text)
|
|
@@ -1093,6 +1161,7 @@ export class ChannelRegistry {
|
|
|
1093
1161
|
metadata: message.metadata,
|
|
1094
1162
|
...(message.tags ? { tags: message.tags } : {}),
|
|
1095
1163
|
triggerInference,
|
|
1164
|
+
acceptedAt: Date.now(),
|
|
1096
1165
|
};
|
|
1097
1166
|
|
|
1098
1167
|
if (coalesced) {
|
|
@@ -1118,6 +1187,12 @@ export class ChannelRegistry {
|
|
|
1118
1187
|
continue;
|
|
1119
1188
|
}
|
|
1120
1189
|
|
|
1190
|
+
// The source envelope is frozen here, at admission, before the message
|
|
1191
|
+
// is queued or acknowledged: a rename or rebind while it waits in the
|
|
1192
|
+
// queue cannot change where it says it came from.
|
|
1193
|
+
const inboundSource = this.acceptInbound?.(event);
|
|
1194
|
+
if (inboundSource) event.inboundSource = inboundSource;
|
|
1195
|
+
|
|
1121
1196
|
// Push to the processing queue
|
|
1122
1197
|
// Cast through unknown because McplChannelIncomingEvent matches the
|
|
1123
1198
|
// CustomEvent `${string}:${string}` type pattern but lacks an index signature.
|
|
@@ -1171,20 +1246,34 @@ export class ChannelRegistry {
|
|
|
1171
1246
|
(existing.descriptor.metadata as { lazyRegistered?: boolean } | undefined)?.lazyRegistered &&
|
|
1172
1247
|
label && existing.descriptor.label === channelId
|
|
1173
1248
|
) {
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
}
|
|
1249
|
+
const metadata = extraMetadata
|
|
1250
|
+
? { ...existing.descriptor.metadata, ...extraMetadata }
|
|
1251
|
+
: existing.descriptor.metadata;
|
|
1178
1252
|
// The channel now has a real label, not just the bare id — durable.
|
|
1179
|
-
this
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1253
|
+
// Recorded before the live descriptor takes it, since this branch's
|
|
1254
|
+
// guard reads the descriptor: an append that throws leaves the
|
|
1255
|
+
// placeholder, so the next push tries again.
|
|
1256
|
+
this.appendLabelSighting(existing.descriptor.id, label, extractDmMeta(metadata));
|
|
1257
|
+
existing.descriptor.label = label;
|
|
1258
|
+
existing.descriptor.metadata = metadata;
|
|
1184
1259
|
}
|
|
1185
1260
|
return;
|
|
1186
1261
|
}
|
|
1187
1262
|
|
|
1263
|
+
// Only persist a REAL label durably. Falling back to the bare
|
|
1264
|
+
// channelId as a placeholder (no server-supplied label at all — e.g. a
|
|
1265
|
+
// Discord DM push missing both channelName and an author name,
|
|
1266
|
+
// framework.ts's derivePushEventChannel) must never overwrite a real
|
|
1267
|
+
// label already on file from a previous boot: after a restart the live
|
|
1268
|
+
// `channels` map starts empty, so THIS is the very branch a
|
|
1269
|
+
// label-less post-restart event takes — recording the placeholder here
|
|
1270
|
+
// would clobber the good label initializeLabelHistoryStore() just
|
|
1271
|
+
// replayed, defeating the entire point of the durable log. The live
|
|
1272
|
+
// descriptor below still carries the placeholder for in-process
|
|
1273
|
+
// routing; only the durable write is skipped when there's no real
|
|
1274
|
+
// label to record. A real label is recorded before the entry exists:
|
|
1275
|
+
// an append that throws registers nothing, so the next push tries again.
|
|
1276
|
+
if (label) this.appendLabelSighting(channelId, label, extractDmMeta(extraMetadata));
|
|
1188
1277
|
const key = `${serverId}:${channelId}`;
|
|
1189
1278
|
this.channels.set(key, {
|
|
1190
1279
|
serverId,
|
|
@@ -1197,19 +1286,6 @@ export class ChannelRegistry {
|
|
|
1197
1286
|
},
|
|
1198
1287
|
open: false,
|
|
1199
1288
|
});
|
|
1200
|
-
// Only persist a REAL label durably. Falling back to the bare
|
|
1201
|
-
// channelId as a placeholder (no server-supplied label at all — e.g. a
|
|
1202
|
-
// Discord DM push missing both channelName and an author name,
|
|
1203
|
-
// framework.ts's derivePushEventChannel) must never overwrite a real
|
|
1204
|
-
// label already on file from a previous boot: after a restart the live
|
|
1205
|
-
// `channels` map starts empty, so THIS is the very branch a
|
|
1206
|
-
// label-less post-restart event takes — recording the placeholder here
|
|
1207
|
-
// would clobber the good label initializeLabelHistoryStore() just
|
|
1208
|
-
// replayed, defeating the entire point of the durable log. The live
|
|
1209
|
-
// descriptor above still carries the placeholder for in-process
|
|
1210
|
-
// routing; only the durable write is skipped when there's no real
|
|
1211
|
-
// label to record.
|
|
1212
|
-
if (label) this.appendLabelSighting(channelId, label, extractDmMeta(extraMetadata));
|
|
1213
1289
|
this.emitTraceFn({
|
|
1214
1290
|
type: 'mcpl:channel-lazy-registered',
|
|
1215
1291
|
serverId,
|
|
@@ -1344,6 +1420,13 @@ export class ChannelRegistry {
|
|
|
1344
1420
|
return this.findChannelEntry(channelId)?.descriptor;
|
|
1345
1421
|
}
|
|
1346
1422
|
|
|
1423
|
+
/** The registered label of `channelId` on exactly `serverId` (no
|
|
1424
|
+
* cross-server first match), or undefined when it has none. */
|
|
1425
|
+
getChannelLabel(serverId: string, channelId: string): string | undefined {
|
|
1426
|
+
const label = this.channels.get(`${serverId}:${channelId}`)?.descriptor.label;
|
|
1427
|
+
return typeof label === 'string' && label.length > 0 ? label : undefined;
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1347
1430
|
isChannelOpen(channelId: string): boolean {
|
|
1348
1431
|
return this.findChannelEntry(channelId)?.open === true;
|
|
1349
1432
|
}
|
|
@@ -1373,7 +1456,7 @@ export class ChannelRegistry {
|
|
|
1373
1456
|
* Get synthesized tool definitions for channel operations.
|
|
1374
1457
|
*/
|
|
1375
1458
|
getChannelTools(): ToolDefinition[] {
|
|
1376
|
-
return
|
|
1459
|
+
return this.channelTools;
|
|
1377
1460
|
}
|
|
1378
1461
|
|
|
1379
1462
|
/**
|
|
@@ -1434,7 +1517,7 @@ export class ChannelRegistry {
|
|
|
1434
1517
|
return this.handleToolJournal(input as { content?: string });
|
|
1435
1518
|
|
|
1436
1519
|
case 'skip_reply':
|
|
1437
|
-
return this.handleToolSkipReply(input as { reason?: string; wake_in_seconds?:
|
|
1520
|
+
return this.handleToolSkipReply(input as { reason?: string; wake_in_seconds?: unknown });
|
|
1438
1521
|
|
|
1439
1522
|
default:
|
|
1440
1523
|
return { success: false, error: `Unknown channel tool: ${toolName}`, isError: true };
|
|
@@ -1549,13 +1632,7 @@ export class ChannelRegistry {
|
|
|
1549
1632
|
private initializeLifecycleStore(): void {
|
|
1550
1633
|
if (!this.store) return;
|
|
1551
1634
|
|
|
1552
|
-
|
|
1553
|
-
this.store.registerState({ id: CHANNEL_LIFECYCLE_LOG_ID, strategy: 'append_log' });
|
|
1554
|
-
} catch (error) {
|
|
1555
|
-
if (!(error instanceof Error) || !error.message.includes('State already exists')) {
|
|
1556
|
-
throw error;
|
|
1557
|
-
}
|
|
1558
|
-
}
|
|
1635
|
+
ensureStateRegistered(this.store, { id: CHANNEL_LIFECYCLE_LOG_ID, strategy: 'append_log' });
|
|
1559
1636
|
|
|
1560
1637
|
const raw = this.store.getStateJson(CHANNEL_LIFECYCLE_LOG_ID);
|
|
1561
1638
|
if (!Array.isArray(raw)) return;
|
|
@@ -1598,6 +1675,15 @@ export class ChannelRegistry {
|
|
|
1598
1675
|
}
|
|
1599
1676
|
}
|
|
1600
1677
|
|
|
1678
|
+
/**
|
|
1679
|
+
* Each writer appends its record here before it changes memory for it, so
|
|
1680
|
+
* an append that throws, as on a full disk, fails the operation with that
|
|
1681
|
+
* change unmade, and memory and the log still agree. A retry then records
|
|
1682
|
+
* the change rather than finding it in memory already, where
|
|
1683
|
+
* setDesiredState's same-state return would record nothing, and a restart
|
|
1684
|
+
* replays what memory held. appendLabelSighting keeps the same order for
|
|
1685
|
+
* the label history.
|
|
1686
|
+
*/
|
|
1601
1687
|
private appendLifecycleEvent(event: ChannelLifecycleEvent): void {
|
|
1602
1688
|
this.store?.appendToStateJson(CHANNEL_LIFECYCLE_LOG_ID, event);
|
|
1603
1689
|
}
|
|
@@ -1616,13 +1702,7 @@ export class ChannelRegistry {
|
|
|
1616
1702
|
private initializeLabelHistoryStore(): void {
|
|
1617
1703
|
if (!this.store) return;
|
|
1618
1704
|
|
|
1619
|
-
|
|
1620
|
-
this.store.registerState({ id: CHANNEL_LABEL_HISTORY_LOG_ID, strategy: 'append_log' });
|
|
1621
|
-
} catch (error) {
|
|
1622
|
-
if (!(error instanceof Error) || !error.message.includes('State already exists')) {
|
|
1623
|
-
throw error;
|
|
1624
|
-
}
|
|
1625
|
-
}
|
|
1705
|
+
ensureStateRegistered(this.store, { id: CHANNEL_LABEL_HISTORY_LOG_ID, strategy: 'append_log' });
|
|
1626
1706
|
|
|
1627
1707
|
const raw = this.store.getStateJson(CHANNEL_LABEL_HISTORY_LOG_ID);
|
|
1628
1708
|
if (!Array.isArray(raw)) return;
|
|
@@ -1703,6 +1783,16 @@ export class ChannelRegistry {
|
|
|
1703
1783
|
const recipientNameUnchanged = recipientName === undefined || recipientName === this.dmRecipientNames.get(channelId);
|
|
1704
1784
|
const isDmUnchanged = isDm === undefined || this.dmClassified.get(channelId) === true;
|
|
1705
1785
|
if (labelUnchanged && recipientIdUnchanged && recipientNameUnchanged && isDmUnchanged) return;
|
|
1786
|
+
// The log first, as for lifecycle events: an append that throws leaves
|
|
1787
|
+
// the history in memory as it was, so the next sighting records it.
|
|
1788
|
+
this.store?.appendToStateJson(CHANNEL_LABEL_HISTORY_LOG_ID, {
|
|
1789
|
+
channelId,
|
|
1790
|
+
label,
|
|
1791
|
+
ts: Date.now(),
|
|
1792
|
+
...(recipientId ? { recipientId } : {}),
|
|
1793
|
+
...(recipientName ? { recipientName } : {}),
|
|
1794
|
+
...(isDm ? { isDm } : {}),
|
|
1795
|
+
} satisfies ChannelLabelSightingEvent);
|
|
1706
1796
|
this.labelHistory.set(channelId, label);
|
|
1707
1797
|
let seen = this.allLabelsSeen.get(channelId);
|
|
1708
1798
|
if (!seen) {
|
|
@@ -1713,14 +1803,6 @@ export class ChannelRegistry {
|
|
|
1713
1803
|
if (recipientId) this.dmRecipientIds.set(channelId, recipientId);
|
|
1714
1804
|
if (recipientName) this.dmRecipientNames.set(channelId, recipientName);
|
|
1715
1805
|
if (isDm) this.dmClassified.set(channelId, true);
|
|
1716
|
-
this.store?.appendToStateJson(CHANNEL_LABEL_HISTORY_LOG_ID, {
|
|
1717
|
-
channelId,
|
|
1718
|
-
label,
|
|
1719
|
-
ts: Date.now(),
|
|
1720
|
-
...(recipientId ? { recipientId } : {}),
|
|
1721
|
-
...(recipientName ? { recipientName } : {}),
|
|
1722
|
-
...(isDm ? { isDm } : {}),
|
|
1723
|
-
} satisfies ChannelLabelSightingEvent);
|
|
1724
1806
|
}
|
|
1725
1807
|
|
|
1726
1808
|
/**
|
|
@@ -1945,7 +2027,6 @@ export class ChannelRegistry {
|
|
|
1945
2027
|
): void {
|
|
1946
2028
|
const key = this.lifecycleKey(serverId, channelId);
|
|
1947
2029
|
if (this.desiredStates.get(key)?.state === desired) return;
|
|
1948
|
-
this.desiredStates.set(key, { state: desired, source });
|
|
1949
2030
|
this.appendLifecycleEvent({
|
|
1950
2031
|
kind: 'desired-state',
|
|
1951
2032
|
serverId,
|
|
@@ -1954,6 +2035,7 @@ export class ChannelRegistry {
|
|
|
1954
2035
|
source,
|
|
1955
2036
|
timestamp: new Date().toISOString(),
|
|
1956
2037
|
});
|
|
2038
|
+
this.desiredStates.set(key, { state: desired, source });
|
|
1957
2039
|
}
|
|
1958
2040
|
|
|
1959
2041
|
// ==========================================================================
|
|
@@ -1973,12 +2055,6 @@ export class ChannelRegistry {
|
|
|
1973
2055
|
source: string,
|
|
1974
2056
|
): void {
|
|
1975
2057
|
const key = this.lifecycleKey(serverId, channelId);
|
|
1976
|
-
this.desiredStates.set(key, {
|
|
1977
|
-
state: 'tuned-out',
|
|
1978
|
-
source,
|
|
1979
|
-
tuneOut: params,
|
|
1980
|
-
wakeCount: 0,
|
|
1981
|
-
});
|
|
1982
2058
|
this.appendLifecycleEvent({
|
|
1983
2059
|
kind: 'desired-state',
|
|
1984
2060
|
serverId,
|
|
@@ -1988,6 +2064,12 @@ export class ChannelRegistry {
|
|
|
1988
2064
|
source,
|
|
1989
2065
|
timestamp: new Date().toISOString(),
|
|
1990
2066
|
});
|
|
2067
|
+
this.desiredStates.set(key, {
|
|
2068
|
+
state: 'tuned-out',
|
|
2069
|
+
source,
|
|
2070
|
+
tuneOut: params,
|
|
2071
|
+
wakeCount: 0,
|
|
2072
|
+
});
|
|
1991
2073
|
}
|
|
1992
2074
|
|
|
1993
2075
|
/**
|
|
@@ -2006,7 +2088,6 @@ export class ChannelRegistry {
|
|
|
2006
2088
|
const current = this.desiredStates.get(key);
|
|
2007
2089
|
if (current?.state !== 'tuned-out' || !current.tuneOut) return null;
|
|
2008
2090
|
const ended = { params: current.tuneOut, wakeCount: current.wakeCount ?? 0 };
|
|
2009
|
-
this.desiredStates.set(key, { state: nextState, source });
|
|
2010
2091
|
this.appendLifecycleEvent({
|
|
2011
2092
|
kind: 'desired-state',
|
|
2012
2093
|
serverId,
|
|
@@ -2015,6 +2096,7 @@ export class ChannelRegistry {
|
|
|
2015
2096
|
source,
|
|
2016
2097
|
timestamp: new Date().toISOString(),
|
|
2017
2098
|
});
|
|
2099
|
+
this.desiredStates.set(key, { state: nextState, source });
|
|
2018
2100
|
return ended;
|
|
2019
2101
|
}
|
|
2020
2102
|
|
|
@@ -2032,16 +2114,17 @@ export class ChannelRegistry {
|
|
|
2032
2114
|
const key = this.lifecycleKey(serverId, channelId);
|
|
2033
2115
|
const current = this.desiredStates.get(key);
|
|
2034
2116
|
if (current?.state !== 'tuned-out' || !current.tuneOut) return null;
|
|
2035
|
-
|
|
2117
|
+
const wakeCount = (current.wakeCount ?? 0) + 1;
|
|
2036
2118
|
this.appendLifecycleEvent({
|
|
2037
2119
|
kind: 'tune-out-wake',
|
|
2038
2120
|
serverId,
|
|
2039
2121
|
channelId,
|
|
2040
2122
|
epochId: current.tuneOut.epochId,
|
|
2041
|
-
wakeCount
|
|
2123
|
+
wakeCount,
|
|
2042
2124
|
timestamp: new Date().toISOString(),
|
|
2043
2125
|
});
|
|
2044
|
-
|
|
2126
|
+
current.wakeCount = wakeCount;
|
|
2127
|
+
return { params: current.tuneOut, wakeCount };
|
|
2045
2128
|
}
|
|
2046
2129
|
|
|
2047
2130
|
/** Active tune-out params + wake count for a channel, or null. */
|
|
@@ -2069,17 +2152,13 @@ export class ChannelRegistry {
|
|
|
2069
2152
|
*/
|
|
2070
2153
|
readCoordinatorState(stateId: string): unknown {
|
|
2071
2154
|
if (!this.store) return null;
|
|
2072
|
-
|
|
2073
|
-
this.store.registerState({ id: stateId, strategy: 'snapshot' });
|
|
2074
|
-
} catch { /* already registered */ }
|
|
2155
|
+
ensureStateRegistered(this.store, { id: stateId, strategy: 'snapshot' });
|
|
2075
2156
|
return this.store.getStateJson(stateId);
|
|
2076
2157
|
}
|
|
2077
2158
|
|
|
2078
2159
|
writeCoordinatorState(stateId: string, value: unknown): void {
|
|
2079
2160
|
if (!this.store) return;
|
|
2080
|
-
|
|
2081
|
-
this.store.registerState({ id: stateId, strategy: 'snapshot' });
|
|
2082
|
-
} catch { /* already registered */ }
|
|
2161
|
+
ensureStateRegistered(this.store, { id: stateId, strategy: 'snapshot' });
|
|
2083
2162
|
this.store.setStateJson(stateId, value);
|
|
2084
2163
|
}
|
|
2085
2164
|
|
|
@@ -2116,13 +2195,13 @@ export class ChannelRegistry {
|
|
|
2116
2195
|
this.setDesiredState(serverId, channel.id, desired, 'legacy-recipe-migration');
|
|
2117
2196
|
}
|
|
2118
2197
|
|
|
2119
|
-
this.migratedLegacyPolicies.add(serverId);
|
|
2120
2198
|
this.appendLifecycleEvent({
|
|
2121
2199
|
kind: 'legacy-policy-migrated',
|
|
2122
2200
|
serverId,
|
|
2123
2201
|
source: Array.isArray(policy) ? 'allow-list' : policy,
|
|
2124
2202
|
timestamp: new Date().toISOString(),
|
|
2125
2203
|
});
|
|
2204
|
+
this.migratedLegacyPolicies.add(serverId);
|
|
2126
2205
|
}
|
|
2127
2206
|
|
|
2128
2207
|
/**
|
|
@@ -2251,9 +2330,9 @@ export class ChannelRegistry {
|
|
|
2251
2330
|
}
|
|
2252
2331
|
}
|
|
2253
2332
|
|
|
2254
|
-
// Announce policy admissions to the agent —
|
|
2255
|
-
//
|
|
2256
|
-
//
|
|
2333
|
+
// Announce policy admissions to the agent — no channel may open without
|
|
2334
|
+
// them being told, and told how to opt out (channel_close; their
|
|
2335
|
+
// decision outranks policy).
|
|
2257
2336
|
if (policyOpened.length > 0) {
|
|
2258
2337
|
try {
|
|
2259
2338
|
this.onChannelAutoOpened?.({
|
|
@@ -2670,11 +2749,13 @@ export class ChannelRegistry {
|
|
|
2670
2749
|
// A tuned-out channel is transport-open but attention-diverted; a plain
|
|
2671
2750
|
// open would silently discard the epoch (and its pending backlog dump).
|
|
2672
2751
|
// Cancelling is the tune-out coordinator's flow, reached via its own
|
|
2673
|
-
// tool — refuse with the pointer rather than eat the state.
|
|
2752
|
+
// tool — refuse with the pointer rather than eat the state. As an error
|
|
2753
|
+
// result, the agent reads the pointer itself; `data` names the refusal
|
|
2754
|
+
// for an in-process caller.
|
|
2674
2755
|
if (this.getDesiredState(entry.serverId, input.channelId) === 'tuned-out') {
|
|
2675
2756
|
return {
|
|
2676
2757
|
success: false,
|
|
2677
|
-
isError:
|
|
2758
|
+
isError: true,
|
|
2678
2759
|
error:
|
|
2679
2760
|
`Channel ${input.channelId} is tuned out. Cancel the tune-out ` +
|
|
2680
2761
|
`(tune_out with mode: 'cancel') to resume normal attention — ` +
|
|
@@ -2845,7 +2926,7 @@ export class ChannelRegistry {
|
|
|
2845
2926
|
if (entry.open || this.getDesiredState(entry.serverId, input.channelId) === 'open') {
|
|
2846
2927
|
return {
|
|
2847
2928
|
success: false,
|
|
2848
|
-
error: `Channel is already open: ${input.channelId}. Use channel_close to
|
|
2929
|
+
error: `Channel is already open: ${input.channelId}. Use channel_close to close it.`,
|
|
2849
2930
|
isError: true,
|
|
2850
2931
|
};
|
|
2851
2932
|
}
|
|
@@ -2953,14 +3034,15 @@ export class ChannelRegistry {
|
|
|
2953
3034
|
* tool, so any trailing prose this turn is NOT posted. Replaces the old
|
|
2954
3035
|
* overloaded use of `think` for staying silent.
|
|
2955
3036
|
*/
|
|
2956
|
-
private handleToolSkipReply(input: { reason?: string; wake_in_seconds?:
|
|
3037
|
+
private handleToolSkipReply(input: { reason?: string; wake_in_seconds?: unknown }): ToolResult {
|
|
2957
3038
|
// The self-wake itself is armed by the framework (which owns the
|
|
2958
|
-
// EventGate) BEFORE
|
|
2959
|
-
//
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
3039
|
+
// EventGate) BEFORE its dispatch reaches this handler, from the same
|
|
3040
|
+
// reading, and the framework refuses a wake the host can't set before
|
|
3041
|
+
// dispatching. A caller of this registry's handleChannelToolCall
|
|
3042
|
+
// (AgentFramework.channels) goes past both, so its note names a wake
|
|
3043
|
+
// nothing armed.
|
|
3044
|
+
const wake = readSkipReplyWake(input);
|
|
3045
|
+
const selfWake = wake.kind === 'wake' ? wake.seconds : undefined;
|
|
2964
3046
|
return {
|
|
2965
3047
|
success: true,
|
|
2966
3048
|
// The note says "ended the turn" — make it TRUE. Without endTurn the
|
|
@@ -3056,7 +3138,179 @@ export class ChannelRegistry {
|
|
|
3056
3138
|
return home ?? this.activeChannelResolver?.(conversationId) ?? this.defaultPublishChannel ?? null;
|
|
3057
3139
|
}
|
|
3058
3140
|
|
|
3059
|
-
|
|
3141
|
+
/**
|
|
3142
|
+
* Resolve a publish target to exactly one registered channel: `serverId`
|
|
3143
|
+
* plus `channelId` when the caller has the server, otherwise a channel id
|
|
3144
|
+
* registered by exactly one server. A shared id is refused, never resolved
|
|
3145
|
+
* to whichever server registered it first.
|
|
3146
|
+
*/
|
|
3147
|
+
resolveDestination(
|
|
3148
|
+
target: { serverId?: string; channelId: string },
|
|
3149
|
+
): { destination: PublishDestination } | { error: string } {
|
|
3150
|
+
const entry = this.findExactEntry(target);
|
|
3151
|
+
if ('error' in entry) return entry;
|
|
3152
|
+
return {
|
|
3153
|
+
destination: {
|
|
3154
|
+
serverId: entry.entry.serverId,
|
|
3155
|
+
channelId: entry.entry.descriptor.id,
|
|
3156
|
+
...(entry.entry.descriptor.label ? { label: entry.entry.descriptor.label } : {}),
|
|
3157
|
+
},
|
|
3158
|
+
};
|
|
3159
|
+
}
|
|
3160
|
+
|
|
3161
|
+
private findExactEntry(
|
|
3162
|
+
target: { serverId?: string; channelId: string },
|
|
3163
|
+
): { entry: ChannelEntry } | { error: string } {
|
|
3164
|
+
// A supplied selector is checked, never read as omission: an empty or
|
|
3165
|
+
// non-string serverId would otherwise widen to "any server".
|
|
3166
|
+
if (typeof target.channelId !== 'string' || !target.channelId) {
|
|
3167
|
+
return { error: 'the destination names no channel id' };
|
|
3168
|
+
}
|
|
3169
|
+
if (target.serverId !== undefined && (typeof target.serverId !== 'string' || !target.serverId)) {
|
|
3170
|
+
return { error: 'serverId must name a server (omit it to resolve the channel id alone)' };
|
|
3171
|
+
}
|
|
3172
|
+
const matches = [...this.channels.values()].filter(
|
|
3173
|
+
(e) => e.descriptor.id === target.channelId && (!target.serverId || e.serverId === target.serverId),
|
|
3174
|
+
);
|
|
3175
|
+
if (matches.length === 0) {
|
|
3176
|
+
return {
|
|
3177
|
+
error: target.serverId
|
|
3178
|
+
? `no registered channel "${target.channelId}" on server "${target.serverId}"`
|
|
3179
|
+
: `no registered channel "${target.channelId}"`,
|
|
3180
|
+
};
|
|
3181
|
+
}
|
|
3182
|
+
if (matches.length > 1) {
|
|
3183
|
+
return {
|
|
3184
|
+
error: `channel id "${target.channelId}" is registered by more than one MCPL server; the destination must name its server`,
|
|
3185
|
+
};
|
|
3186
|
+
}
|
|
3187
|
+
return { entry: matches[0]! };
|
|
3188
|
+
}
|
|
3189
|
+
|
|
3190
|
+
/**
|
|
3191
|
+
* Publish `text` to one registered channel and report what the attempt
|
|
3192
|
+
* established (PublishOutcome). The delivery executor behind plain speech
|
|
3193
|
+
* (deliverSpeech / routeSpeech) and resident resends of held drafts.
|
|
3194
|
+
* channel_publish (and publishForAgent, which shares its handler) resolves
|
|
3195
|
+
* and sends on its own path, and reads its answer through the same
|
|
3196
|
+
* publishReceiptOutcome and publishErrorOutcome.
|
|
3197
|
+
*
|
|
3198
|
+
* Resolution is exact (resolveDestination): `serverId` plus `channelId`
|
|
3199
|
+
* when the caller has the server, otherwise the channel id must be
|
|
3200
|
+
* registered by exactly one server (a shared id is refused, never routed
|
|
3201
|
+
* through whichever server came first). An omitted `serverId` means "not
|
|
3202
|
+
* in use"; a supplied one must be a non-empty server id, and an empty or
|
|
3203
|
+
* non-string selector is refused rather than read as omission. It is not
|
|
3204
|
+
* possible to send into a closed channel: a closed but registered
|
|
3205
|
+
* destination is opened first (`openSource` names why), once its server
|
|
3206
|
+
* and that server's channels.publish grant are known to take the send, so
|
|
3207
|
+
* a refused send opens nothing; and a failed open sends nothing.
|
|
3208
|
+
*
|
|
3209
|
+
* Only the connector's `delivered: true` confirms a post. `failed` means
|
|
3210
|
+
* nothing was posted: the attempt stopped before the request was written,
|
|
3211
|
+
* or the connector answered `delivered: false` and named no message (no
|
|
3212
|
+
* `messageId`, or null). Everything else is `unknown`: once the request
|
|
3213
|
+
* has been handed to the transport, an error response, a timeout, a lost
|
|
3214
|
+
* connection, or a missing, malformed or contradictory receipt (such as
|
|
3215
|
+
* `delivered: false` beside a message id, valid or not) means the post may
|
|
3216
|
+
* or may not exist, and the caller must not treat it as safe to retry
|
|
3217
|
+
* blindly.
|
|
3218
|
+
*/
|
|
3219
|
+
async publish(
|
|
3220
|
+
conversationId: string,
|
|
3221
|
+
text: string,
|
|
3222
|
+
target: {
|
|
3223
|
+
serverId?: string;
|
|
3224
|
+
channelId: string;
|
|
3225
|
+
/** Set by speech routing (deliverSpeech): opening a closed channel
|
|
3226
|
+
* for this publish is logged under `[routeSpeech]`, with speech
|
|
3227
|
+
* routing's other lines. */
|
|
3228
|
+
routed?: boolean;
|
|
3229
|
+
},
|
|
3230
|
+
openSource: 'opened-by-delivery' | 'opened-by-reply' = 'opened-by-delivery',
|
|
3231
|
+
): Promise<PublishOutcome> {
|
|
3232
|
+
const at = (): number => Date.now();
|
|
3233
|
+
const found = this.findExactEntry(target);
|
|
3234
|
+
if ('error' in found) return { status: 'failed', reason: found.error, at: at() };
|
|
3235
|
+
const entry = found.entry;
|
|
3236
|
+
const destination: PublishDestination = {
|
|
3237
|
+
serverId: entry.serverId,
|
|
3238
|
+
channelId: entry.descriptor.id,
|
|
3239
|
+
...(entry.descriptor.label ? { label: entry.descriptor.label } : {}),
|
|
3240
|
+
};
|
|
3241
|
+
|
|
3242
|
+
// A send that would be refused is refused before anything opens: a
|
|
3243
|
+
// closed channel opens only for words that can go out.
|
|
3244
|
+
const server = this.serverRegistry.getServer(entry.serverId);
|
|
3245
|
+
if (!server) {
|
|
3246
|
+
return { status: 'failed', destination, reason: `server "${entry.serverId}" not found`, at: at() };
|
|
3247
|
+
}
|
|
3248
|
+
// §14.1: channels/publish requires channels.publish in the grant. The
|
|
3249
|
+
// host not sending is the enforcement.
|
|
3250
|
+
if (!CapabilityGrant.of(server).has('channels.publish')) {
|
|
3251
|
+
return {
|
|
3252
|
+
status: 'failed',
|
|
3253
|
+
destination,
|
|
3254
|
+
reason: `channels.publish not in "${entry.serverId}"'s effective grant (§14.1)`,
|
|
3255
|
+
at: at(),
|
|
3256
|
+
};
|
|
3257
|
+
}
|
|
3258
|
+
|
|
3259
|
+
if (!entry.open) {
|
|
3260
|
+
try {
|
|
3261
|
+
await this.openChannelNow(entry, openSource);
|
|
3262
|
+
if (target.routed) {
|
|
3263
|
+
console.error(
|
|
3264
|
+
`[routeSpeech] ${conversationId}: locus ${logValue(entry.descriptor.id)} was closed — opened by delivery (speech implies engagement)`,
|
|
3265
|
+
);
|
|
3266
|
+
}
|
|
3267
|
+
this.emitTraceFn({
|
|
3268
|
+
type: 'mcpl:channel-opened-by-send',
|
|
3269
|
+
serverId: entry.serverId,
|
|
3270
|
+
channelId: entry.descriptor.id,
|
|
3271
|
+
});
|
|
3272
|
+
if (openSource === 'opened-by-delivery') {
|
|
3273
|
+
try {
|
|
3274
|
+
this.onChannelAutoOpened?.({
|
|
3275
|
+
conversationId,
|
|
3276
|
+
serverId: entry.serverId,
|
|
3277
|
+
source: 'opened-by-delivery',
|
|
3278
|
+
channels: [{ channelId: entry.descriptor.id, label: entry.descriptor.label }],
|
|
3279
|
+
});
|
|
3280
|
+
} catch (err) {
|
|
3281
|
+
console.error('onChannelAutoOpened (delivery) failed:', err);
|
|
3282
|
+
}
|
|
3283
|
+
}
|
|
3284
|
+
} catch (err) {
|
|
3285
|
+
return {
|
|
3286
|
+
status: 'failed',
|
|
3287
|
+
destination,
|
|
3288
|
+
reason: `channel is closed and open failed: ${connectorText(err instanceof Error ? err.message : String(err))}`,
|
|
3289
|
+
at: at(),
|
|
3290
|
+
};
|
|
3291
|
+
}
|
|
3292
|
+
}
|
|
3293
|
+
|
|
3294
|
+
let result: unknown;
|
|
3295
|
+
try {
|
|
3296
|
+
result = await server.sendChannelsPublish({
|
|
3297
|
+
conversationId,
|
|
3298
|
+
channelId: entry.descriptor.id,
|
|
3299
|
+
content: [{ type: 'text', text }],
|
|
3300
|
+
});
|
|
3301
|
+
} catch (err) {
|
|
3302
|
+
return publishErrorOutcome(err, destination, at());
|
|
3303
|
+
}
|
|
3304
|
+
return publishReceiptOutcome(result, destination, at());
|
|
3305
|
+
}
|
|
3306
|
+
|
|
3307
|
+
/**
|
|
3308
|
+
* Plain speech for one turn segment: publish `text` to the turn's frozen
|
|
3309
|
+
* locus and report the PublishOutcome. A failure (or an uncertain outcome)
|
|
3310
|
+
* is surfaced as a trace and through onRouteFailure, so the agent learns
|
|
3311
|
+
* its words did not (or may not have) reached anyone.
|
|
3312
|
+
*/
|
|
3313
|
+
async deliverSpeech(
|
|
3060
3314
|
conversationId: string,
|
|
3061
3315
|
text: string,
|
|
3062
3316
|
/** The turn's FROZEN locus, snapshotted once by the caller (resolveLocus
|
|
@@ -3067,118 +3321,82 @@ export class ChannelRegistry {
|
|
|
3067
3321
|
* PR #32, and the 2026-07-22 Sol DM misroute). Explicit `null` means
|
|
3068
3322
|
* "this turn is pinned to no locus": fail loudly rather than guess. */
|
|
3069
3323
|
locusChannelId: string | null,
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3324
|
+
/** `heldOnFailure`: the caller holds a `failed` delivery's words as a
|
|
3325
|
+
* draft with its own notice, so no failure marker is written for it.
|
|
3326
|
+
* An `unknown` outcome still gets its marker. */
|
|
3327
|
+
opts?: { heldOnFailure?: boolean },
|
|
3328
|
+
): Promise<PublishOutcome> {
|
|
3329
|
+
const fail = (channelId: string | null, reason: string, outcome: PublishOutcome): PublishOutcome => {
|
|
3330
|
+
const status = outcome.status === 'unknown' ? 'unknown' : 'failed';
|
|
3331
|
+
const detail = outcome.detail !== undefined ? connectorText(outcome.detail) : undefined;
|
|
3332
|
+
const detailText = detail !== undefined ? `; connector detail: ${detail}` : '';
|
|
3333
|
+
console.error(`[routeSpeech] ${conversationId}: ${reason}${detailText} — speech ${status === 'unknown' ? 'delivery NOT confirmed' : 'NOT routed'} (${text.length} chars stay in chronicle)`);
|
|
3076
3334
|
this.emitTraceFn({
|
|
3077
3335
|
type: 'mcpl:speech-route-failed',
|
|
3078
3336
|
conversationId,
|
|
3079
3337
|
channelId: channelId ?? '',
|
|
3080
3338
|
reason,
|
|
3081
3339
|
textLen: text.length,
|
|
3340
|
+
outcome: status,
|
|
3341
|
+
...(detail !== undefined ? { detail } : {}),
|
|
3082
3342
|
});
|
|
3083
|
-
|
|
3084
|
-
|
|
3343
|
+
if (status === 'unknown' || !opts?.heldOnFailure) {
|
|
3344
|
+
this.onRouteFailure?.({ conversationId, channelId, reason, textLen: text.length, outcome: status, ...(detail !== undefined ? { detail } : {}) });
|
|
3345
|
+
}
|
|
3346
|
+
return outcome;
|
|
3085
3347
|
};
|
|
3086
3348
|
|
|
3087
3349
|
// Runtime backstop for JS callers the compiler can't see: an omitted
|
|
3088
3350
|
// locus is a routing bug at the call site, never something to paper over
|
|
3089
3351
|
// with a live re-resolution.
|
|
3090
3352
|
if (locusChannelId === undefined) {
|
|
3091
|
-
|
|
3353
|
+
const reason = 'caller passed no locus (routing bug: every speech path must snapshot the turn locus)';
|
|
3354
|
+
return fail(null, reason, { status: 'failed', reason, at: Date.now() });
|
|
3092
3355
|
}
|
|
3093
|
-
|
|
3094
|
-
if (!channelId) {
|
|
3356
|
+
if (!locusChannelId) {
|
|
3095
3357
|
// The turn froze with no locus (no home, no triggering channel, no
|
|
3096
3358
|
// global inbound ever seen) — the agent was told its prose stays in
|
|
3097
3359
|
// the archive; honor that.
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
const entry = this.findChannelEntry(channelId);
|
|
3102
|
-
if (!entry) {
|
|
3103
|
-
return fail(channelId, `no registered channel for locus "${channelId}"`);
|
|
3104
|
-
}
|
|
3105
|
-
|
|
3106
|
-
// INVARIANT: it is not possible to send into a closed channel. Speech
|
|
3107
|
-
// routed into a closed-but-registered locus (the canonical case: a DM
|
|
3108
|
-
// that woke the agent — DMs register closed) OPENS the channel first,
|
|
3109
|
-
// so typing indicators, reaction machinery, and inbound forwarding come
|
|
3110
|
-
// alive with the reply. If the open fails, the speech does NOT go out:
|
|
3111
|
-
// a half-alive delivery is worse than a loud marker.
|
|
3112
|
-
if (!entry.open) {
|
|
3113
|
-
try {
|
|
3114
|
-
await this.openChannelNow(entry, 'opened-by-delivery');
|
|
3115
|
-
console.error(
|
|
3116
|
-
`[routeSpeech] ${conversationId}: locus ${logValue(channelId)} was closed — opened by delivery (speech implies engagement)`,
|
|
3117
|
-
);
|
|
3118
|
-
this.emitTraceFn({
|
|
3119
|
-
type: 'mcpl:channel-opened-by-send',
|
|
3120
|
-
serverId: entry.serverId,
|
|
3121
|
-
channelId,
|
|
3122
|
-
});
|
|
3123
|
-
try {
|
|
3124
|
-
this.onChannelAutoOpened?.({
|
|
3125
|
-
conversationId,
|
|
3126
|
-
serverId: entry.serverId,
|
|
3127
|
-
source: 'opened-by-delivery',
|
|
3128
|
-
channels: [{ channelId, label: entry.descriptor.label }],
|
|
3129
|
-
});
|
|
3130
|
-
} catch (err) {
|
|
3131
|
-
console.error('onChannelAutoOpened (delivery) failed:', err);
|
|
3132
|
-
}
|
|
3133
|
-
} catch (err) {
|
|
3134
|
-
return fail(channelId, `locus channel is closed and open failed: ${(err as Error).message}`);
|
|
3135
|
-
}
|
|
3360
|
+
const reason = 'turn has no locus (no home/trigger channel; nothing to deliver into)';
|
|
3361
|
+
return fail(null, reason, { status: 'failed', reason, at: Date.now() });
|
|
3136
3362
|
}
|
|
3137
3363
|
|
|
3138
|
-
const
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
// §14.1: channels/publish requires channels.publish in the grant. The
|
|
3143
|
-
// host not sending is the enforcement — a send to an ungranted server
|
|
3144
|
-
// would have it act on authority it was never told it has.
|
|
3145
|
-
if (!CapabilityGrant.of(server).has('channels.publish')) {
|
|
3146
|
-
return fail(channelId, `channels.publish not in "${entry.serverId}"'s effective grant (§14.1)`);
|
|
3364
|
+
const outcome = await this.publish(conversationId, text, { channelId: locusChannelId, routed: true });
|
|
3365
|
+
const channelId = outcome.destination?.channelId ?? locusChannelId;
|
|
3366
|
+
if (outcome.status !== 'delivered') {
|
|
3367
|
+
return fail(channelId, outcome.reason ?? 'delivery not confirmed', outcome);
|
|
3147
3368
|
}
|
|
3148
3369
|
|
|
3149
|
-
|
|
3150
|
-
conversationId,
|
|
3151
|
-
channelId,
|
|
3152
|
-
content: [{ type: 'text', text }],
|
|
3153
|
-
};
|
|
3154
|
-
const result = await server.sendChannelsPublish(publishParams);
|
|
3155
|
-
const delivered = (result as { delivered?: boolean } | undefined)?.delivered ?? true;
|
|
3156
|
-
// Surface the posted message's id (ChannelsPublishResult.messageId) so
|
|
3157
|
-
// trace consumers can act on the just-posted message — e.g. a TTS-relay
|
|
3158
|
-
// tap editing it down to the words actually voiced on interruption.
|
|
3159
|
-
// Previously this was silently dropped here.
|
|
3160
|
-
const messageId = (result as { messageId?: string } | undefined)?.messageId;
|
|
3161
|
-
|
|
3162
|
-
// The server accepted the publish RPC but reported the message was not
|
|
3163
|
-
// actually delivered (e.g. missing Send Messages permission). Previously
|
|
3164
|
-
// this returned `{ delivered: true }`, masking the failure. Surface it.
|
|
3165
|
-
if (delivered === false) {
|
|
3166
|
-
return fail(channelId, `server "${entry.serverId}" reported delivered:false for "${channelId}"`);
|
|
3167
|
-
}
|
|
3168
|
-
|
|
3169
|
-
console.error(`[routeSpeech] ${conversationId}: routed ${text.length} chars -> ${logValue(channelId)} (server=${entry.serverId}, delivered=${delivered})`);
|
|
3370
|
+
console.error(`[routeSpeech] ${conversationId}: routed ${text.length} chars -> ${logValue(channelId)} (server=${outcome.destination!.serverId}, delivered=true)`);
|
|
3170
3371
|
this.emitTraceFn({
|
|
3171
3372
|
type: 'mcpl:speech-routed',
|
|
3172
3373
|
conversationId,
|
|
3173
|
-
serverId:
|
|
3374
|
+
serverId: outcome.destination!.serverId,
|
|
3174
3375
|
channelId,
|
|
3175
|
-
delivered,
|
|
3376
|
+
delivered: true,
|
|
3176
3377
|
textLen: text.length,
|
|
3177
3378
|
text,
|
|
3178
|
-
|
|
3379
|
+
// Surface the posted message's id (ChannelsPublishResult.messageId) so
|
|
3380
|
+
// trace consumers can act on the just-posted message — e.g. a TTS-relay
|
|
3381
|
+
// tap editing it down to the words actually voiced on interruption.
|
|
3382
|
+
...(outcome.messageId !== undefined ? { messageId: outcome.messageId } : {}),
|
|
3179
3383
|
});
|
|
3384
|
+
return outcome;
|
|
3385
|
+
}
|
|
3180
3386
|
|
|
3181
|
-
|
|
3387
|
+
/** deliverSpeech, reduced to the confirmed delivery (null when there was none). */
|
|
3388
|
+
async routeSpeech(
|
|
3389
|
+
conversationId: string,
|
|
3390
|
+
text: string,
|
|
3391
|
+
locusChannelId: string | null,
|
|
3392
|
+
): Promise<{ delivered: boolean; channelId: string; messageId?: string } | null> {
|
|
3393
|
+
const outcome = await this.deliverSpeech(conversationId, text, locusChannelId);
|
|
3394
|
+
if (outcome.status !== 'delivered') return null;
|
|
3395
|
+
return {
|
|
3396
|
+
delivered: true,
|
|
3397
|
+
channelId: outcome.destination!.channelId,
|
|
3398
|
+
...(outcome.messageId !== undefined ? { messageId: outcome.messageId } : {}),
|
|
3399
|
+
};
|
|
3182
3400
|
}
|
|
3183
3401
|
|
|
3184
3402
|
private async handleToolPublish(input: { channelId?: string; content?: string; text?: string }): Promise<ToolResult> {
|
|
@@ -3220,31 +3438,44 @@ export class ChannelRegistry {
|
|
|
3220
3438
|
};
|
|
3221
3439
|
}
|
|
3222
3440
|
|
|
3223
|
-
|
|
3224
|
-
if (!CapabilityGrant.of(server).has('channels.publish')) {
|
|
3225
|
-
return {
|
|
3226
|
-
success: false,
|
|
3227
|
-
error: `channels.publish not in "${server.id}"'s effective grant (§14.1)`,
|
|
3228
|
-
isError: true,
|
|
3229
|
-
};
|
|
3230
|
-
}
|
|
3231
|
-
const publishParams: ChannelsPublishParams = {
|
|
3232
|
-
conversationId: '', // Framework will fill this when wired
|
|
3233
|
-
channelId,
|
|
3234
|
-
content: [{ type: 'text', text: messageText }],
|
|
3235
|
-
};
|
|
3236
|
-
|
|
3237
|
-
const result = await server.sendChannelsPublish(publishParams);
|
|
3238
|
-
return {
|
|
3239
|
-
success: true,
|
|
3240
|
-
data: result ?? { delivered: true },
|
|
3241
|
-
};
|
|
3242
|
-
} catch (err) {
|
|
3441
|
+
if (!CapabilityGrant.of(server).has('channels.publish')) {
|
|
3243
3442
|
return {
|
|
3244
3443
|
success: false,
|
|
3245
|
-
error: `
|
|
3444
|
+
error: `channels.publish not in "${server.id}"'s effective grant (§14.1)`,
|
|
3246
3445
|
isError: true,
|
|
3247
3446
|
};
|
|
3248
3447
|
}
|
|
3448
|
+
const publishParams: ChannelsPublishParams = {
|
|
3449
|
+
conversationId: '', // Framework will fill this when wired
|
|
3450
|
+
channelId,
|
|
3451
|
+
content: [{ type: 'text', text: messageText }],
|
|
3452
|
+
};
|
|
3453
|
+
const destination: PublishDestination = {
|
|
3454
|
+
serverId: entry.serverId,
|
|
3455
|
+
channelId: entry.descriptor.id,
|
|
3456
|
+
...(entry.descriptor.label ? { label: entry.descriptor.label } : {}),
|
|
3457
|
+
};
|
|
3458
|
+
|
|
3459
|
+
// The answer counts by the same rule as plain speech's: only the
|
|
3460
|
+
// connector's delivered:true confirms a post.
|
|
3461
|
+
let result: unknown;
|
|
3462
|
+
let outcome: PublishOutcome;
|
|
3463
|
+
try {
|
|
3464
|
+
result = await server.sendChannelsPublish(publishParams);
|
|
3465
|
+
outcome = publishReceiptOutcome(result, destination, Date.now());
|
|
3466
|
+
} catch (err) {
|
|
3467
|
+
outcome = publishErrorOutcome(err, destination, Date.now());
|
|
3468
|
+
}
|
|
3469
|
+
if (outcome.status === 'delivered') return { success: true, data: result };
|
|
3470
|
+
// The connector's data may say what a multi-part send already posted.
|
|
3471
|
+
const detail = outcome.status === 'unknown' && outcome.detail !== undefined ? ` Connector detail: ${connectorText(outcome.detail)}` : '';
|
|
3472
|
+
return {
|
|
3473
|
+
success: false,
|
|
3474
|
+
error: (outcome.status === 'failed'
|
|
3475
|
+
? `Publish to ${channelId} failed: ${outcome.reason}. Nothing was posted.`
|
|
3476
|
+
: `Publish to ${channelId} wasn't confirmed: ${outcome.reason}. ` +
|
|
3477
|
+
'It may or may not have been posted, so sending it again could post it twice.') + detail,
|
|
3478
|
+
isError: true,
|
|
3479
|
+
};
|
|
3249
3480
|
}
|
|
3250
3481
|
}
|