@animalabs/agent-framework 0.22.2 → 0.22.4
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 +143 -41
- 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/thinking-token-stamp.d.ts +12 -0
- package/dist/src/thinking-token-stamp.d.ts.map +1 -1
- package/dist/src/thinking-token-stamp.js +34 -3
- package/dist/src/thinking-token-stamp.js.map +1 -1
- package/dist/src/tool-image-ledger.d.ts +87 -19
- package/dist/src/tool-image-ledger.d.ts.map +1 -1
- package/dist/src/tool-image-ledger.js +135 -32
- package/dist/src/tool-image-ledger.js.map +1 -1
- package/dist/src/tool-presentation.d.ts +9 -0
- package/dist/src/tool-presentation.d.ts.map +1 -1
- package/dist/src/tool-presentation.js +257 -60
- package/dist/src/tool-presentation.js.map +1 -1
- package/dist/src/tool-result-guard.d.ts.map +1 -1
- package/dist/src/tool-result-guard.js +7 -10
- package/dist/src/tool-result-guard.js.map +1 -1
- package/dist/src/tool-result-history.d.ts +32 -3
- package/dist/src/tool-result-history.d.ts.map +1 -1
- package/dist/src/tool-result-history.js +106 -19
- package/dist/src/tool-result-history.js.map +1 -1
- package/dist/src/tune-out/coordinator.d.ts +25 -1
- package/dist/src/tune-out/coordinator.d.ts.map +1 -1
- package/dist/src/tune-out/coordinator.js +260 -65
- package/dist/src/tune-out/coordinator.js.map +1 -1
- package/dist/src/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 +6 -4
- package/src/agent.ts +169 -41
- 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/thinking-token-stamp.ts +34 -3
- 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
package/src/tool-presentation.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { createHash, randomUUID } from 'node:crypto';
|
|
2
2
|
import { fchmodSync, closeSync, fstatSync, lstatSync, openSync, readSync, renameSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { closestNames } from './closest-names.js';
|
|
4
|
+
import { boundedErrorMessage, errorMessage } from './error-message.js';
|
|
3
5
|
import type { ToolDefinition, ToolResult } from './types/events.js';
|
|
4
6
|
|
|
5
7
|
export interface ToolPresentationConfig {
|
|
@@ -22,23 +24,138 @@ export interface PresentationSnapshot {
|
|
|
22
24
|
entries: { name: string; source: string; visible: boolean; originalDescription: string; description: string; descriptionSource?: string; inputSchema: ToolDefinition['inputSchema'] }[];
|
|
23
25
|
}
|
|
24
26
|
const MAX_BYTES = 256 * 1024;
|
|
27
|
+
const MAX_DESCRIPTION_CHARS = 32768;
|
|
25
28
|
const protectedNames = new Set(['set_tool_visibility', 'set_tool_description', 'workspace--read']);
|
|
26
29
|
export const isPresentationTool = (name: string): boolean => name === 'set_tool_visibility' || name === 'set_tool_description';
|
|
27
30
|
const hash = (value: string): string => createHash('sha256').update(value).digest('hex');
|
|
28
31
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
/**
|
|
33
|
+
* A presentation or defaults file this host can't use. Each problem is a
|
|
34
|
+
* clause about the file, such as `the entry for "x" has "visible": "no",
|
|
35
|
+
* which must be true or false`; whoever reports it names the file and says
|
|
36
|
+
* what follows from it.
|
|
37
|
+
*/
|
|
38
|
+
class PresentationFileError extends Error {
|
|
39
|
+
constructor(problems: string[]) {
|
|
40
|
+
const more = problems.length - 10;
|
|
41
|
+
super((more > 0 ? [...problems.slice(0, 10), `${more} more problem${more === 1 ? '' : 's'}`] : problems).join('; '));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** An edit refused, in words for the agent: its message is the whole result. */
|
|
46
|
+
class PresentationRefusal extends Error {}
|
|
47
|
+
|
|
48
|
+
const count = (n: number): string => n.toLocaleString('en-US');
|
|
49
|
+
|
|
50
|
+
/** A text's length in code points, so a character outside the Basic Multilingual Plane, such as 😀, counts once where UTF-16 counts it twice. */
|
|
51
|
+
const characters = (text: string): number => [...text].length;
|
|
52
|
+
|
|
53
|
+
/** A text's first `n` characters, never splitting a code point. */
|
|
54
|
+
const firstCharacters = (text: string, n: number): string => [...text].slice(0, n).join('');
|
|
55
|
+
|
|
56
|
+
/** A name as a message quotes it: whole up to 60 characters, and past that cut, with its length, since a file can hold a key of any size. */
|
|
57
|
+
function quoted(name: string): string {
|
|
58
|
+
return characters(name) <= 60 ? JSON.stringify(name) : `${JSON.stringify(firstCharacters(name, 57))}... (${count(characters(name))} characters)`;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** A file's problem as a message quotes it: its own clauses whole, and anything else bounded, since nobody wrote that text for its reader. */
|
|
62
|
+
const problemText = (error: unknown): string => error instanceof PresentationFileError ? error.message : boundedErrorMessage(error);
|
|
63
|
+
|
|
64
|
+
/** A value as a message quotes it: short JSON for a scalar, the kind of anything bigger. */
|
|
65
|
+
function shown(value: unknown): string {
|
|
66
|
+
if (Array.isArray(value)) return 'an array';
|
|
67
|
+
if (value !== null && typeof value === 'object') return 'an object';
|
|
68
|
+
const json = JSON.stringify(value) ?? String(value);
|
|
69
|
+
return characters(json) > 40 ? `${firstCharacters(json, 37)}...` : json;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Names quoted and joined: "a", "a" and "b", "a", "b" and "c"; past ten, the first ten and how many more, since a file can hold any number of keys. Each is quoted by `quote`: quoted() by default, which cuts a file's long keys, or JSON.stringify for names the agent should copy whole. */
|
|
73
|
+
function quotedList(names: string[], conjunction: 'and' | 'or' = 'and', quote: (name: string) => string = quoted): string {
|
|
74
|
+
const each = names.slice(0, 10).map((name) => quote(name));
|
|
75
|
+
if (names.length > 10) return `${each.join(', ')} ${conjunction} ${count(names.length - 10)} more`;
|
|
76
|
+
return each.length > 1 ? `${each.slice(0, -1).join(', ')} ${conjunction} ${each[each.length - 1]}` : each.join('');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Every problem that keeps a document from being used, each by where it is;
|
|
81
|
+
* none for a usable one. A defaults file (`descriptionsOnly`) may set
|
|
82
|
+
* descriptions only, since visibility is the resident's to choose.
|
|
83
|
+
*/
|
|
84
|
+
function documentProblems(doc: unknown, descriptionsOnly: boolean): string[] {
|
|
85
|
+
if (!doc || typeof doc !== 'object' || Array.isArray(doc)) return [`its top level is ${shown(doc)}, not an object like {"version":1,"tools":{}}`];
|
|
86
|
+
const top = doc as Record<string, unknown>;
|
|
87
|
+
const problems: string[] = [];
|
|
88
|
+
if (top.version !== 1) problems.push(`"version" must be 1, and ${Object.hasOwn(top, 'version') ? `it is ${shown(top.version)}` : "it's missing"}`);
|
|
89
|
+
const extra = Object.keys(top).filter((key) => key !== 'version' && key !== 'tools');
|
|
90
|
+
if (extra.length) problems.push(`only "version" and "tools" belong at the top level, not ${quotedList(extra)}`);
|
|
91
|
+
const tools = top.tools;
|
|
92
|
+
if (!tools || typeof tools !== 'object' || Array.isArray(tools)) {
|
|
93
|
+
problems.push(`"tools" must be an object of tool names, and ${Object.hasOwn(top, 'tools') ? `it is ${shown(tools)}` : "it's missing"}`);
|
|
94
|
+
return problems;
|
|
95
|
+
}
|
|
96
|
+
const setsVisibility: string[] = [];
|
|
97
|
+
for (const [name, value] of Object.entries(tools)) {
|
|
98
|
+
if (!name) { problems.push('"tools" has an entry with an empty name'); continue; }
|
|
99
|
+
const entry = `the entry for ${quoted(name)}`;
|
|
100
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) { problems.push(`${entry} is ${shown(value)}, not an object such as {"visible":false}`); continue; }
|
|
35
101
|
const item = value as Record<string, unknown>;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
102
|
+
const unknown = Object.keys(item).filter((key) => key !== 'description' && key !== 'visible');
|
|
103
|
+
if (unknown.length) problems.push(`${entry} has ${quotedList(unknown)}, and an entry may have only ${descriptionsOnly ? '"description"' : '"description" and "visible"'}`);
|
|
104
|
+
if (Object.hasOwn(item, 'description')) {
|
|
105
|
+
if (typeof item.description !== 'string') problems.push(`${entry} has a "description" that is ${shown(item.description)}, not a string`);
|
|
106
|
+
else if (characters(item.description) > MAX_DESCRIPTION_CHARS) problems.push(`${entry} has a "description" of ${count(characters(item.description))} characters, over the ${count(MAX_DESCRIPTION_CHARS)} allowed`);
|
|
107
|
+
}
|
|
108
|
+
if (!Object.hasOwn(item, 'visible')) continue;
|
|
109
|
+
if (descriptionsOnly) setsVisibility.push(name);
|
|
110
|
+
else if (typeof item.visible !== 'boolean') problems.push(`${entry} has "visible": ${shown(item.visible)}, which must be true or false`);
|
|
111
|
+
else if (!item.visible && protectedNames.has(name)) problems.push(`${entry} hides it, which isn't allowed, since workspace--read, set_tool_visibility and set_tool_description are how the catalogue is read and how these settings are undone`);
|
|
40
112
|
}
|
|
41
|
-
|
|
113
|
+
if (setsVisibility.length) problems.push(`it sets "visible" for ${quotedList(setsVisibility)}, and a defaults file may set only descriptions, since visibility is yours to choose`);
|
|
114
|
+
return problems;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function parseDocument(raw: string, descriptionsOnly: boolean): PresentationDocument {
|
|
118
|
+
let doc: unknown;
|
|
119
|
+
try { doc = JSON.parse(raw); }
|
|
120
|
+
catch (error) { throw new PresentationFileError([`it isn't valid JSON: ${errorMessage(error)}`]); }
|
|
121
|
+
const problems = documentProblems(doc, descriptionsOnly);
|
|
122
|
+
if (problems.length) throw new PresentationFileError(problems);
|
|
123
|
+
return doc as PresentationDocument;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** A resident's presentation document, or an error naming every problem that keeps it from being used. */
|
|
127
|
+
export function parsePresentation(raw: string): PresentationDocument {
|
|
128
|
+
return parseDocument(raw, false);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* What an agent is told when an edit fails. Every throw in `edit()` comes
|
|
133
|
+
* before its rename, and the cleanup after it never throws, so nothing was
|
|
134
|
+
* changed: a refusal says so in its own words, a file this host can't use is
|
|
135
|
+
* the host's to repair, and anything else is reported as the error it is.
|
|
136
|
+
*/
|
|
137
|
+
function editFailure(error: unknown): string {
|
|
138
|
+
if (error instanceof PresentationRefusal) return error.message;
|
|
139
|
+
if (error instanceof PresentationFileError) return `Nothing was changed: your tool presentation file can't be used (${error.message}), and these tools won't write over it until it's repaired. Ask whoever runs this host to repair it.`;
|
|
140
|
+
const code = (error as NodeJS.ErrnoException | null)?.code;
|
|
141
|
+
return `Nothing was changed: the edit failed (${typeof code === 'string' ? code : boundedErrorMessage(error)}). Ask whoever runs this host to check your tool presentation file and its directory.`;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/** Whether a path is a symbolic link, so an open that found nothing can tell a dangling link from no file. */
|
|
145
|
+
function isLink(path: string): boolean {
|
|
146
|
+
try { return lstatSync(path).isSymbolicLink(); } catch { return false; }
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** Runs one step of an edit's cleanup, which must not throw: it returns what the step threw, if it did. */
|
|
150
|
+
function tidy(step: () => void): { error: unknown } | undefined {
|
|
151
|
+
try { step(); return undefined; } catch (error) { return { error }; }
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** What an edit says when its lock couldn't be removed afterwards, since every later edit will meet that lock. */
|
|
155
|
+
function lockLeftBehind(error: unknown): string {
|
|
156
|
+
const code = (error as NodeJS.ErrnoException | undefined)?.code;
|
|
157
|
+
return `This edit couldn't remove its lock afterwards, the presentation file's name with .lock added${typeof code === 'string' ? ` (${code})` : ''}. `
|
|
158
|
+
+ 'Until whoever runs this host removes it, set_tool_visibility and set_tool_description will be refused, saying an edit left its lock behind.';
|
|
42
159
|
}
|
|
43
160
|
|
|
44
161
|
export function presentationTools(path: string): ToolDefinition[] {
|
|
@@ -57,43 +174,50 @@ export class ToolPresentation {
|
|
|
57
174
|
private read(path = this.config.path, allowMissing = true): string {
|
|
58
175
|
let fd: number;
|
|
59
176
|
try { fd = openSync(path, 'r'); }
|
|
60
|
-
catch (error) {
|
|
177
|
+
catch (error) {
|
|
178
|
+
const code = (error as NodeJS.ErrnoException).code;
|
|
179
|
+
if (code === 'ENOENT') {
|
|
180
|
+
if (isLink(path)) throw new PresentationFileError(["it's a symbolic link to a file that doesn't exist"]);
|
|
181
|
+
if (allowMissing) return '{"version":1,"tools":{}}';
|
|
182
|
+
throw new PresentationFileError(["it doesn't exist"]);
|
|
183
|
+
}
|
|
184
|
+
throw new PresentationFileError([`it couldn't be opened: ${code ?? boundedErrorMessage(error)}`]);
|
|
185
|
+
}
|
|
61
186
|
try {
|
|
62
187
|
const stat = fstatSync(fd);
|
|
63
|
-
if (!stat.isFile()
|
|
188
|
+
if (!stat.isFile()) throw new PresentationFileError(["it isn't a regular file"]);
|
|
189
|
+
if (stat.size > MAX_BYTES) throw new PresentationFileError([`it's ${count(stat.size)} bytes, over the ${count(MAX_BYTES)} (256 KiB) this host reads`]);
|
|
64
190
|
const data = Buffer.alloc(MAX_BYTES + 1);
|
|
65
|
-
let size = 0,
|
|
66
|
-
while (size < data.length && (
|
|
67
|
-
if (size > MAX_BYTES) throw new
|
|
191
|
+
let size = 0, bytesRead = 0;
|
|
192
|
+
while (size < data.length && (bytesRead = readSync(fd, data, size, data.length - size, null)) > 0) size += bytesRead;
|
|
193
|
+
if (size > MAX_BYTES) throw new PresentationFileError([`it grew past ${count(MAX_BYTES)} bytes (256 KiB) while it was being read`]);
|
|
68
194
|
return data.subarray(0,size).toString('utf8');
|
|
69
195
|
} finally { closeSync(fd); }
|
|
70
196
|
}
|
|
71
197
|
resolve(tools: ToolDefinition[], sources: ReadonlyMap<string, string> = new Map()): PresentationSnapshot {
|
|
72
198
|
let raw = '', doc: PresentationDocument = {version:1,tools:{}}, diagnostics: string[] = [];
|
|
73
199
|
try { raw = this.read(); doc = parsePresentation(raw); }
|
|
74
|
-
catch (error) { diagnostics.push(`
|
|
200
|
+
catch (error) { diagnostics.push(`Your tool presentation file can't be used (${problemText(error)}), so none of its settings apply: every tool is visible and shows its configured default description, or its installed one where none is configured. set_tool_visibility and set_tool_description won't change the file until it's repaired; ask whoever runs this host to repair it.`); }
|
|
75
201
|
const defaults = new Map<string, {description: string; path: string}>();
|
|
76
202
|
const configuredSources = new Set<string>();
|
|
77
203
|
for (const profile of this.config.defaults ?? []) {
|
|
78
204
|
if (configuredSources.has(profile.source)) {
|
|
79
|
-
diagnostics.push(`
|
|
205
|
+
diagnostics.push(`The description defaults for ${JSON.stringify(profile.source)} are configured twice; only the first is read, and the other is ignored. Ask whoever runs this host to remove the duplicate.`); continue;
|
|
80
206
|
}
|
|
81
207
|
configuredSources.add(profile.source);
|
|
82
208
|
// Absent components contribute neither tools nor missing-file errors.
|
|
83
209
|
if (!tools.some(t => (sources.get(t.name) ?? 'Unattributed') === profile.source)) continue;
|
|
84
210
|
try {
|
|
85
|
-
const profileDoc =
|
|
86
|
-
if (Object.values(profileDoc.tools).some(item => Object.keys(item).some(k => k !== 'description')))
|
|
87
|
-
throw new Error('Component defaults may contain descriptions only; visibility belongs to the resident');
|
|
211
|
+
const profileDoc = parseDocument(this.read(profile.path, false), true);
|
|
88
212
|
for (const tool of tools) {
|
|
89
213
|
if ((sources.get(tool.name) ?? 'Unattributed') !== profile.source) continue;
|
|
90
214
|
const item = Object.hasOwn(profileDoc.tools, tool.name) ? profileDoc.tools[tool.name] : undefined;
|
|
91
215
|
if (item?.description !== undefined) defaults.set(tool.name, {description:item.description,path:profile.path});
|
|
92
216
|
}
|
|
93
|
-
} catch (error) { diagnostics.push(`
|
|
217
|
+
} catch (error) { diagnostics.push(`The description defaults for ${JSON.stringify(profile.source)} can't be used (${problemText(error)}), so its tools show their installed descriptions, or yours where you set one. Ask whoever runs this host to fix that defaults file.`); }
|
|
94
218
|
}
|
|
95
219
|
const names = new Set(tools.map(t => t.name));
|
|
96
|
-
for (const name of Object.keys(doc.tools)) if (!names.has(name)) diagnostics.push(`Not currently available: ${name}`);
|
|
220
|
+
for (const name of Object.keys(doc.tools)) if (!names.has(name)) diagnostics.push(`Not currently available: ${quoted(name)}`);
|
|
97
221
|
const entries = tools.map(tool => {
|
|
98
222
|
const override = Object.hasOwn(doc.tools, tool.name) ? doc.tools[tool.name] : undefined;
|
|
99
223
|
// Always retain a usable discovery signpost, even when its wording is overridden.
|
|
@@ -111,39 +235,98 @@ export class ToolPresentation {
|
|
|
111
235
|
edit(tool: string, input: unknown, available: ToolDefinition[]): ToolResult {
|
|
112
236
|
const lock = this.config.path + '.lock';
|
|
113
237
|
let fd: number | undefined, tempFd: number | undefined, temp: string | undefined;
|
|
238
|
+
let result: ToolResult, lockLeft: { error: unknown } | undefined;
|
|
114
239
|
try {
|
|
115
|
-
if (!isPresentationTool(tool)) throw new Error('
|
|
116
|
-
const value = input as Record<string, unknown>;
|
|
240
|
+
if (!isPresentationTool(tool)) throw new Error(`${tool} isn't a tool presentation editing tool`);
|
|
117
241
|
const field = tool === 'set_tool_visibility' ? 'visible' : 'description';
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
242
|
+
const name = this.editedName(tool, field, input, available);
|
|
243
|
+
const value = input as Record<string, unknown>;
|
|
244
|
+
try { fd = openSync(lock, 'wx', 0o600); }
|
|
245
|
+
catch (error) {
|
|
246
|
+
if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error;
|
|
247
|
+
throw new PresentationRefusal("Nothing was changed: an earlier edit of your tool presentation file left its lock behind, or another edit is in progress. Call this again in a few seconds. If it fails the same way, ask whoever runs this host to remove the stale lock, the presentation file's name with .lock added, once nothing is editing the file.");
|
|
248
|
+
}
|
|
123
249
|
let mode = 0o600;
|
|
124
|
-
try {
|
|
250
|
+
try {
|
|
251
|
+
const stat = lstatSync(this.config.path);
|
|
252
|
+
if (stat.isSymbolicLink()) throw new PresentationRefusal("Nothing was changed: your tool presentation file is a symbolic link, and these tools don't write through links. Ask whoever runs this host to make the change in the file it points to, or to replace the link with that file.");
|
|
253
|
+
mode = stat.mode & 0o777;
|
|
254
|
+
}
|
|
125
255
|
catch (error) { if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error; }
|
|
126
256
|
const before = this.read(), doc = parsePresentation(before);
|
|
127
|
-
const old = Object.hasOwn(doc.tools,
|
|
257
|
+
const old = Object.hasOwn(doc.tools,name) ? doc.tools[name] : {};
|
|
128
258
|
const updated = {...old};
|
|
129
259
|
if (field === 'description' && value.description === null) delete updated.description;
|
|
130
260
|
else Object.assign(updated,{[field]:value[field]});
|
|
131
|
-
Object.defineProperty(doc.tools,
|
|
261
|
+
Object.defineProperty(doc.tools,name,{value:updated,enumerable:true,writable:true,configurable:true});
|
|
132
262
|
const next = JSON.stringify(doc,null,2)+'\n';
|
|
263
|
+
// editedName has checked what this adds, so this can't fail on the agent's input;
|
|
264
|
+
// it keeps a gap in those checks from writing a file the host would then ignore.
|
|
133
265
|
parsePresentation(next);
|
|
134
|
-
|
|
266
|
+
const size = Buffer.byteLength(next);
|
|
267
|
+
if (size>MAX_BYTES) throw new PresentationRefusal(`Nothing was changed: with this change your tool presentation file would be ${count(size)} bytes, ${count(size - MAX_BYTES)} over its limit of ${count(MAX_BYTES)} (256 KiB). `
|
|
268
|
+
+ (field === 'description' ? 'Use a shorter description, or make room by restoring descriptions you no longer need with "description": null.' : 'Make room by restoring descriptions you no longer need with set_tool_description and "description": null.')
|
|
269
|
+
+ ' Entries for tools no longer available to you can be removed only by whoever runs this host.');
|
|
135
270
|
temp = this.config.path + '.' + randomUUID() + '.tmp';
|
|
136
271
|
tempFd = openSync(temp,'wx',0o600);
|
|
137
272
|
writeFileSync(tempFd,next);
|
|
138
273
|
fchmodSync(tempFd,mode); // preserve permissions on the opened inode, never a replacement path
|
|
139
|
-
if (this.read() !== before) throw new
|
|
274
|
+
if (this.read() !== before) throw new PresentationRefusal('Nothing was changed: your tool presentation file changed while this edit was being made. Call this again; it applies to the file as it is now.');
|
|
140
275
|
const opened = fstatSync(tempFd), named = lstatSync(temp);
|
|
141
276
|
if (!named.isFile() || named.dev !== opened.dev || named.ino !== opened.ino)
|
|
142
|
-
throw new
|
|
277
|
+
throw new PresentationRefusal('Nothing was changed: the temporary copy this edit was writing was replaced while it was written. Call this again; if it fails the same way, ask whoever runs this host to check what else writes beside your tool presentation file.');
|
|
143
278
|
renameSync(temp,this.config.path); temp=undefined;
|
|
144
|
-
|
|
145
|
-
} catch (error) {
|
|
146
|
-
finally {
|
|
279
|
+
result = {success:true,data:{name,[field]:value[field],effective:'next newly compiled request',catalogue:this.config.cataloguePath}};
|
|
280
|
+
} catch (error) { result = {success:false,isError:true,error:editFailure(error)}; }
|
|
281
|
+
finally {
|
|
282
|
+
// After the rename the edit's result must stand, so no cleanup step may throw.
|
|
283
|
+
const tempFdToClose = tempFd, tempToRemove = temp, lockFd = fd;
|
|
284
|
+
if (tempFdToClose !== undefined) tidy(() => closeSync(tempFdToClose));
|
|
285
|
+
if (tempToRemove) tidy(() => unlinkSync(tempToRemove));
|
|
286
|
+
if (lockFd !== undefined) {
|
|
287
|
+
tidy(() => closeSync(lockFd));
|
|
288
|
+
lockLeft = tidy(() => unlinkSync(lock));
|
|
289
|
+
// A lock already gone was removed by something else, so none is left.
|
|
290
|
+
if ((lockLeft?.error as NodeJS.ErrnoException | undefined)?.code === 'ENOENT') lockLeft = undefined;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
if (!lockLeft) return result;
|
|
294
|
+
return result.success
|
|
295
|
+
? {...result,data:{...(result.data as Record<string, unknown>),note:lockLeftBehind(lockLeft.error)}}
|
|
296
|
+
: {...result,error:`${result.error} ${lockLeftBehind(lockLeft.error)}`};
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* The name of the tool an edit is for, once the agent's arguments hold up;
|
|
300
|
+
* otherwise a refusal naming every problem with them and the call to make.
|
|
301
|
+
* The limits a file would refuse (a description's length, the tools that
|
|
302
|
+
* can't be hidden) are checked here too, so they read as the agent's input
|
|
303
|
+
* rather than as a problem with the file.
|
|
304
|
+
*/
|
|
305
|
+
private editedName(tool: string, field: 'visible' | 'description', input: unknown, available: ToolDefinition[]): string {
|
|
306
|
+
const usage = field === 'visible'
|
|
307
|
+
? `set_tool_visibility takes {"name": a tool's exact name, "visible": true or false}.`
|
|
308
|
+
: `set_tool_description takes {"name": a tool's exact name, "description": the new text, or null to restore the default}.`;
|
|
309
|
+
if (!input || typeof input !== 'object' || Array.isArray(input)) throw new PresentationRefusal(`Nothing was changed: the arguments were ${shown(input)}, not an object. ${usage}`);
|
|
310
|
+
const args = input as Record<string, unknown>, problems: string[] = [];
|
|
311
|
+
if (!Object.hasOwn(args, 'name')) problems.push('"name" is missing');
|
|
312
|
+
else if (typeof args.name !== 'string') problems.push(`"name" is ${shown(args.name)}, not a string`);
|
|
313
|
+
if (!Object.hasOwn(args, field)) problems.push(`"${field}" is missing`);
|
|
314
|
+
else if (field === 'visible' ? typeof args.visible !== 'boolean' : args.description !== null && typeof args.description !== 'string')
|
|
315
|
+
problems.push(`"${field}" is ${shown(args[field])}, not ${field === 'visible' ? 'true or false' : 'a string or null'}`);
|
|
316
|
+
const extra = Object.keys(args).filter((key) => key !== 'name' && key !== field);
|
|
317
|
+
if (extra.length) problems.push(`${quotedList(extra)} ${extra.length > 1 ? "aren't arguments" : "isn't an argument"} of ${tool}`);
|
|
318
|
+
if (problems.length) throw new PresentationRefusal(`Nothing was changed: ${problems.join('; ')}. ${usage}`);
|
|
319
|
+
const name = args.name as string;
|
|
320
|
+
if (!available.some((t) => t.name === name)) {
|
|
321
|
+
const near = closestNames(name, available.map((t) => t.name));
|
|
322
|
+
throw new PresentationRefusal(`Nothing was changed: no tool named ${quoted(name)} is available to you.${near.length ? ` Did you mean ${quotedList(near, 'or', JSON.stringify)}?` : ''}`
|
|
323
|
+
+ ` Copy the exact name from your tool catalogue's index, workspace--read {"path":${JSON.stringify(this.config.cataloguePath)},"limit":140}, reading on with "offset" if the index runs past that.`);
|
|
324
|
+
}
|
|
325
|
+
if (field === 'description' && typeof args.description === 'string' && characters(args.description) > MAX_DESCRIPTION_CHARS)
|
|
326
|
+
throw new PresentationRefusal(`Nothing was changed: the description is ${count(characters(args.description))} characters, over the ${count(MAX_DESCRIPTION_CHARS)} allowed. Shorten it and call set_tool_description again.`);
|
|
327
|
+
if (field === 'visible' && args.visible === false && protectedNames.has(name))
|
|
328
|
+
throw new PresentationRefusal(`Nothing was changed: ${name} can't be hidden, since workspace--read, set_tool_visibility and set_tool_description are how you read the catalogue and undo these changes. Calling this again won't change that.`);
|
|
329
|
+
return name;
|
|
147
330
|
}
|
|
148
331
|
}
|
|
149
332
|
export function renderCatalogue(snapshot: PresentationSnapshot): string {
|
|
@@ -164,7 +347,8 @@ export function renderCatalogue(snapshot: PresentationSnapshot): string {
|
|
|
164
347
|
`Read details: workspace--read {"path":${JSON.stringify(snapshot.cataloguePath)},"offset":LINE,"limit":LINES}.`,
|
|
165
348
|
'Line references below belong to this revision; reread the index after changes.', '',
|
|
166
349
|
];
|
|
167
|
-
|
|
350
|
+
// One line each: a quoted parse error can hold the file's own line breaks.
|
|
351
|
+
for (const diagnostic of snapshot.diagnostics) lines.push('Diagnostic: '+diagnostic.replace(/\r\n|\r|\n/g, '\\n'));
|
|
168
352
|
lines.push('## Index by source', '');
|
|
169
353
|
const index = new Map<string, number>();
|
|
170
354
|
for (const [source, entries] of groups) {
|
package/src/tool-result-guard.ts
CHANGED
|
@@ -3,8 +3,8 @@ import { isDeepStrictEqual } from 'node:util';
|
|
|
3
3
|
import type { ContextManager, MessageId, MessageMetadata } from '@animalabs/context-manager';
|
|
4
4
|
import type { ContentBlock, NormalizedMessage, ToolResult } from '@animalabs/membrane';
|
|
5
5
|
import type { CompletedToolCall } from './types/index.js';
|
|
6
|
-
import {
|
|
7
|
-
import { toolResultDataToHistoryString } from './tool-result-history.js';
|
|
6
|
+
import { ensureStateRegistered } from './module-registry.js';
|
|
7
|
+
import { rfc005TextOf, toolResultDataToHistoryString } from './tool-result-history.js';
|
|
8
8
|
import { safeSlice } from './safe-slice.js';
|
|
9
9
|
|
|
10
10
|
export const TOOL_RESULT_GUARD_NOTICE = 'Tool result withheld by the guard. The tool has already executed.';
|
|
@@ -101,7 +101,10 @@ export function keptWhenWithheld(result: CompletedToolCall['result'], maxChars:
|
|
|
101
101
|
const fields = data as Record<string, unknown>;
|
|
102
102
|
const kept = Object.fromEntries(keys.filter((key) => Object.hasOwn(fields, key)).map((key) => [key, fields[key]]));
|
|
103
103
|
if (Object.keys(kept).length === 0) return undefined;
|
|
104
|
-
|
|
104
|
+
// Data that RFC-005 shows as text, such as a reference's stub, keeps that
|
|
105
|
+
// text: picked out of it, a kept uri would lose the type that makes it a
|
|
106
|
+
// reference, and be written out of the stub that hides it.
|
|
107
|
+
const whole = rfc005TextOf(fields) ?? toolResultDataToHistoryString(kept);
|
|
105
108
|
if (!maxChars || whole.length <= maxChars) return whole;
|
|
106
109
|
// Never half a surrogate pair: the stub goes to the provider as text, so
|
|
107
110
|
// the cut can be one character short of the cap.
|
|
@@ -295,11 +298,7 @@ export class ToolResultGuard {
|
|
|
295
298
|
private write(record: Record<string, unknown>): void {
|
|
296
299
|
const store = this.cm.getStore();
|
|
297
300
|
if (!this.registered) {
|
|
298
|
-
|
|
299
|
-
store.registerState({ id: TOOL_RESULT_GUARD_AUDIT_STATE, strategy: 'append_log' });
|
|
300
|
-
} catch (error) {
|
|
301
|
-
if (!isStateExistsError(error)) throw error;
|
|
302
|
-
}
|
|
301
|
+
ensureStateRegistered(store, { id: TOOL_RESULT_GUARD_AUDIT_STATE, strategy: 'append_log' });
|
|
303
302
|
this.registered = true;
|
|
304
303
|
}
|
|
305
304
|
store.appendToStateJson(TOOL_RESULT_GUARD_AUDIT_STATE, record);
|
|
@@ -11,11 +11,24 @@
|
|
|
11
11
|
*
|
|
12
12
|
* For MCP-shaped content arrays, this helper keeps text blocks verbatim and
|
|
13
13
|
* replaces image blocks with a short `[image: mimeType, ~NKB]` placeholder.
|
|
14
|
-
* For anything else it falls back to JSON
|
|
14
|
+
* For anything else it falls back to JSON, written by RFC-005's rules at
|
|
15
|
+
* every depth (historyJson): a reference is shown as its stub wherever it
|
|
16
|
+
* sits in the data, so its uri never reaches history, and inline data that
|
|
17
|
+
* claims a uri or a disposition is withheld.
|
|
15
18
|
*/
|
|
16
19
|
|
|
17
20
|
import { INLINE_WITHHELD_TEXT, isInlineContradiction, referenceStubOrNull } from './mcpl/references.js';
|
|
18
|
-
import {
|
|
21
|
+
import { NON_STRING_TEXT_PLACEHOLDER } from './mcpl/visible-content.js';
|
|
22
|
+
import { formatToolImagePlaceholder, toolResultCutAt } from './tool-image-ledger.js';
|
|
23
|
+
|
|
24
|
+
/** Where one block of a content array sits in its history text, and what
|
|
25
|
+
* kind of block it was: text, an inline image (its placeholder), an RFC-005
|
|
26
|
+
* reference (its stub), or inline data withheld for a contradiction. */
|
|
27
|
+
export interface HistoryBlockSpan {
|
|
28
|
+
kind: 'text' | 'image' | 'reference' | 'withheld';
|
|
29
|
+
start: number;
|
|
30
|
+
end: number;
|
|
31
|
+
}
|
|
19
32
|
|
|
20
33
|
export interface HistorySerializeOptions {
|
|
21
34
|
/**
|
|
@@ -25,6 +38,13 @@ export interface HistorySerializeOptions {
|
|
|
25
38
|
* handle in history; null leaves the legacy ref-less form.
|
|
26
39
|
*/
|
|
27
40
|
imageRef?: (blockIndex: number, image: { data: string; mimeType: string }) => string | null;
|
|
41
|
+
/**
|
|
42
|
+
* Called once a content array has been serialized block by block, rather
|
|
43
|
+
* than given up on for the fallback, with where each block sits in the
|
|
44
|
+
* joined text, before any cut at `maxChars`. The framework reads from it
|
|
45
|
+
* what a result's live copy showed (#403).
|
|
46
|
+
*/
|
|
47
|
+
onBlocks?: (spans: HistoryBlockSpan[]) => void;
|
|
28
48
|
}
|
|
29
49
|
|
|
30
50
|
/**
|
|
@@ -54,7 +74,7 @@ export function toolResultDataToHistoryString(
|
|
|
54
74
|
const fromArray = tryHistoryStringFromContentArray(data, options);
|
|
55
75
|
// JSON leaves out undefined, a function and a symbol: a result with no data
|
|
56
76
|
// is stored as no text, as an empty content array is.
|
|
57
|
-
const str = fromArray ?? (
|
|
77
|
+
const str = fromArray ?? historyJson(data) ?? '';
|
|
58
78
|
return maxChars ? truncateForHistory(str, maxChars) : str;
|
|
59
79
|
}
|
|
60
80
|
|
|
@@ -80,52 +100,136 @@ export function nonErrorResultText(
|
|
|
80
100
|
return toolResultDataToHistoryString(data, maxChars, options);
|
|
81
101
|
}
|
|
82
102
|
|
|
83
|
-
/** Bounded copy of an arbitrary string with the standard truncation notice
|
|
84
|
-
*
|
|
103
|
+
/** Bounded copy of an arbitrary string with the standard truncation notice,
|
|
104
|
+
* cut at the cap as a tool result's stored copy is (toolResultCutAt), so it
|
|
105
|
+
* never ends in part of a slot. Each of its callers' readers sees this
|
|
106
|
+
* very text, never the images behind a placeholder, so nothing past the cut
|
|
107
|
+
* is kept for save_recent_image's index (#403). The framework stores a tool
|
|
108
|
+
* result with spillOrTruncate, which keeps the slots past its cut that the
|
|
109
|
+
* result's live copy showed. */
|
|
85
110
|
export function truncateForHistory(str: string, maxChars: number): string {
|
|
86
111
|
if (str.length <= maxChars) return str;
|
|
87
|
-
|
|
88
|
-
return head
|
|
89
|
-
+ '\n\n[truncated — original was ' + str.length + ' chars]'
|
|
90
|
-
+ formatPreservedImageSlots(tail);
|
|
112
|
+
return str.slice(0, toolResultCutAt(str, maxChars)) + '\n\n[truncated — original was ' + str.length + ' chars]';
|
|
91
113
|
}
|
|
92
114
|
|
|
93
115
|
/**
|
|
94
116
|
* If `data` is an MCP content array whose every block has a shape we
|
|
95
117
|
* recognize, return a history-safe string (images → placeholders). Otherwise
|
|
96
|
-
* return `null` to defer to the
|
|
118
|
+
* return `null` to defer to the fallback, historyJson, which shows a
|
|
119
|
+
* reference anywhere in the data as its stub.
|
|
97
120
|
*/
|
|
98
121
|
function tryHistoryStringFromContentArray(data: unknown, options?: HistorySerializeOptions): string | null {
|
|
99
122
|
if (!Array.isArray(data)) return null;
|
|
100
|
-
const parts:
|
|
123
|
+
const parts: Array<{ kind: HistoryBlockSpan['kind']; text: string }> = [];
|
|
101
124
|
for (const [blockIndex, raw] of data.entries()) {
|
|
102
125
|
if (!raw || typeof raw !== 'object') return null;
|
|
103
126
|
const b = raw as { type?: unknown; text?: unknown; data?: unknown; mimeType?: unknown };
|
|
104
|
-
if (b.type === 'text'
|
|
105
|
-
|
|
127
|
+
if (b.type === 'text') {
|
|
128
|
+
// A text that isn't a string shows as the converters' placeholder,
|
|
129
|
+
// rather than sending the whole array to the JSON fallback.
|
|
130
|
+
parts.push({ kind: 'text', text: typeof b.text === 'string' ? b.text : NON_STRING_TEXT_PLACEHOLDER });
|
|
106
131
|
} else if (isInlineContradiction(b)) {
|
|
107
132
|
// RFC-005 vector 2: checked before the data branch so inline data
|
|
108
133
|
// claiming bulk disposition is withheld, not rendered.
|
|
109
|
-
parts.push(INLINE_WITHHELD_TEXT);
|
|
134
|
+
parts.push({ kind: 'withheld', text: INLINE_WITHHELD_TEXT });
|
|
110
135
|
} else if (b.type === 'image' && typeof b.data === 'string' && typeof b.mimeType === 'string') {
|
|
111
136
|
// Decoded byte estimate from base64 length (3/4 ratio, rounded).
|
|
112
137
|
const approxBytes = Math.floor(b.data.length * 3 / 4);
|
|
113
138
|
const ref = options?.imageRef?.(blockIndex, { data: b.data, mimeType: b.mimeType }) ?? null;
|
|
114
|
-
parts.push(formatToolImagePlaceholder(b.mimeType, formatSize(approxBytes), ref));
|
|
139
|
+
parts.push({ kind: 'image', text: formatToolImagePlaceholder(b.mimeType, formatSize(approxBytes), ref) });
|
|
115
140
|
} else if (b.type === 'resource' || ((b.type === 'image' || b.type === 'audio') && typeof (b as { uri?: unknown }).uri === 'string')) {
|
|
116
141
|
// RFC-005 reference block: a bounded stub, never the raw block JSON
|
|
117
142
|
// (which used to inline the URI — and the whole array — into history).
|
|
118
|
-
//
|
|
119
|
-
// inventory (a failing one — bytes live behind
|
|
120
|
-
// the index never slides past an image the
|
|
143
|
+
// A stub that shows an image type occupies a slot in
|
|
144
|
+
// save_recent_image's inventory (a failing one — bytes live behind
|
|
145
|
+
// fetch_reference), so the index never slides past an image the
|
|
146
|
+
// resident saw.
|
|
121
147
|
const stub = referenceStubOrNull(b, 'from tool result');
|
|
122
148
|
if (stub === null) return null;
|
|
123
|
-
parts.push(stub);
|
|
149
|
+
parts.push({ kind: 'reference', text: stub });
|
|
124
150
|
} else {
|
|
125
151
|
return null;
|
|
126
152
|
}
|
|
127
153
|
}
|
|
128
|
-
|
|
154
|
+
if (options?.onBlocks) {
|
|
155
|
+
const spans: HistoryBlockSpan[] = [];
|
|
156
|
+
let start = 0;
|
|
157
|
+
for (const part of parts) {
|
|
158
|
+
spans.push({ kind: part.kind, start, end: start + part.text.length });
|
|
159
|
+
start += part.text.length + 1; // the newline that joins them
|
|
160
|
+
}
|
|
161
|
+
options.onBlocks(spans);
|
|
162
|
+
}
|
|
163
|
+
return parts.map((part) => part.text).join('\n');
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Whether RFC-005 governs a value of a tool result's data, wherever it sits.
|
|
168
|
+
* A reference is a `resource` with a uri, at its top level or under
|
|
169
|
+
* `resource` (where MCP embeds a resource's uri), or an `image` or `audio`
|
|
170
|
+
* given by uri; inline data is an `image` or `audio` whose data is a string.
|
|
171
|
+
* A uri that is null, absent or empty counts as none, and data that isn't a
|
|
172
|
+
* string isn't inline data, so a record that only shares one of those type
|
|
173
|
+
* names is data. A uri of any other value, string or not, counts, so a
|
|
174
|
+
* credential fails closed.
|
|
175
|
+
*/
|
|
176
|
+
function governedByRfc005(b: Record<string, unknown>): boolean {
|
|
177
|
+
if (b.type === 'resource') return hasUri(b.uri) || (isPlainRecord(b.resource) && hasUri(b.resource.uri));
|
|
178
|
+
if (b.type === 'image' || b.type === 'audio') return typeof b.data === 'string' || hasUri(b.uri);
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function hasUri(value: unknown): boolean {
|
|
183
|
+
return value !== undefined && value !== null && value !== '';
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function isPlainRecord(value: unknown): value is Record<string, unknown> {
|
|
187
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* A value of a tool result's data as history shows it, by RFC-005's rules,
|
|
192
|
+
* wherever it sits in the data. A value RFC-005 governs (governedByRfc005) is
|
|
193
|
+
* shown as the reference lanes show it: a reference as its stub, an invalid
|
|
194
|
+
* one (such as a uri that isn't a string, or MCP's embedded resource, whose
|
|
195
|
+
* uri isn't at its top level) as an unrecognized-block line, and inline data
|
|
196
|
+
* that also claims a uri or a disposition as withheld, so no uri is ever
|
|
197
|
+
* shown. Inline data that claims neither is itself, as is any other value:
|
|
198
|
+
* a block of another type keeps its fields, a `resource_link`'s uri among
|
|
199
|
+
* them, since RFC-005 governs references.
|
|
200
|
+
*/
|
|
201
|
+
function shownInHistory(value: unknown): unknown {
|
|
202
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return value;
|
|
203
|
+
const b = value as Record<string, unknown>;
|
|
204
|
+
if (!governedByRfc005(b)) return value;
|
|
205
|
+
if ((b.type === 'image' || b.type === 'audio') && typeof b.data === 'string') {
|
|
206
|
+
// JSON writes every field, so here inline data beside a uri of any value
|
|
207
|
+
// is withheld, not only beside a string one as in the lanes, which show
|
|
208
|
+
// no uri: an object can carry a credential. An empty uri carries none.
|
|
209
|
+
return hasUri(b.uri) || b.disposition !== undefined ? INLINE_WITHHELD_TEXT : value;
|
|
210
|
+
}
|
|
211
|
+
return referenceStubOrNull(b, 'from tool result') ?? value;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* The text RFC-005 shows a value of a tool result's data as, when it shows it
|
|
216
|
+
* as text rather than as its fields: a reference's stub, an invalid one's
|
|
217
|
+
* unrecognized-block line, or inline data withheld. Null for any other value.
|
|
218
|
+
*/
|
|
219
|
+
export function rfc005TextOf(value: unknown): string | null {
|
|
220
|
+
const shown = shownInHistory(value);
|
|
221
|
+
return shown !== value && typeof shown === 'string' ? shown : null;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* JSON of a tool result's data with each value in it shown as history shows
|
|
226
|
+
* it (shownInHistory), at any depth. Data that is itself shown as text, such
|
|
227
|
+
* as a bare reference, is that text.
|
|
228
|
+
*/
|
|
229
|
+
function historyJson(data: unknown): string | undefined {
|
|
230
|
+
const root = shownInHistory(data);
|
|
231
|
+
if (root !== data && typeof root === 'string') return root;
|
|
232
|
+
return JSON.stringify(data, (_key, value: unknown) => shownInHistory(value)) as string | undefined;
|
|
129
233
|
}
|
|
130
234
|
|
|
131
235
|
function formatSize(bytes: number): string {
|