@animalabs/agent-framework 0.22.2 → 0.23.0
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 +108 -4
- package/dist/src/agent.d.ts +108 -17
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +207 -67
- 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/index.d.ts +1 -1
- package/dist/src/code-execution/index.d.ts.map +1 -1
- package/dist/src/code-execution/index.js.map +1 -1
- package/dist/src/code-execution/py-runner.d.ts +50 -7
- package/dist/src/code-execution/py-runner.d.ts.map +1 -1
- package/dist/src/code-execution/py-runner.js +258 -90
- package/dist/src/code-execution/py-runner.js.map +1 -1
- package/dist/src/code-execution/runtime-py.d.ts +3 -2
- package/dist/src/code-execution/runtime-py.d.ts.map +1 -1
- package/dist/src/code-execution/runtime-py.js +94 -8
- package/dist/src/code-execution/runtime-py.js.map +1 -1
- package/dist/src/code-execution/tool-definition.d.ts +17 -1
- package/dist/src/code-execution/tool-definition.d.ts.map +1 -1
- package/dist/src/code-execution/tool-definition.js +72 -6
- 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 +56 -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 +1529 -165
- package/dist/src/framework.d.ts.map +1 -1
- package/dist/src/framework.js +8264 -1939
- 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 +36 -5
- package/dist/src/gate/event-gate.js.map +1 -1
- package/dist/src/held-writes.d.ts +16 -0
- package/dist/src/held-writes.d.ts.map +1 -0
- package/dist/src/held-writes.js +56 -0
- package/dist/src/held-writes.js.map +1 -0
- package/dist/src/index.d.ts +10 -4
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +11 -5
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcpl/capability-grant.d.ts +4 -0
- package/dist/src/mcpl/capability-grant.d.ts.map +1 -1
- package/dist/src/mcpl/capability-grant.js +1 -1
- package/dist/src/mcpl/capability-grant.js.map +1 -1
- package/dist/src/mcpl/channel-registry.d.ts +233 -18
- package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
- package/dist/src/mcpl/channel-registry.js +975 -386
- 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 +88 -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 +7 -1
- package/dist/src/mcpl/index.d.ts.map +1 -1
- package/dist/src/mcpl/index.js +5 -1
- package/dist/src/mcpl/index.js.map +1 -1
- package/dist/src/mcpl/inference-router.d.ts +19 -13
- package/dist/src/mcpl/inference-router.d.ts.map +1 -1
- package/dist/src/mcpl/inference-router.js +155 -87
- package/dist/src/mcpl/inference-router.js.map +1 -1
- package/dist/src/mcpl/log-value.d.ts +7 -0
- package/dist/src/mcpl/log-value.d.ts.map +1 -1
- package/dist/src/mcpl/log-value.js +9 -0
- package/dist/src/mcpl/log-value.js.map +1 -1
- package/dist/src/mcpl/modern-connection.d.ts +227 -0
- package/dist/src/mcpl/modern-connection.d.ts.map +1 -0
- package/dist/src/mcpl/modern-connection.js +1088 -0
- package/dist/src/mcpl/modern-connection.js.map +1 -0
- package/dist/src/mcpl/prefix-rule.d.ts +18 -0
- package/dist/src/mcpl/prefix-rule.d.ts.map +1 -0
- package/dist/src/mcpl/prefix-rule.js +25 -0
- package/dist/src/mcpl/prefix-rule.js.map +1 -0
- package/dist/src/mcpl/protocol-family.d.ts +179 -0
- package/dist/src/mcpl/protocol-family.d.ts.map +1 -0
- package/dist/src/mcpl/protocol-family.js +697 -0
- package/dist/src/mcpl/protocol-family.js.map +1 -0
- package/dist/src/mcpl/push-coalescer.d.ts +58 -17
- package/dist/src/mcpl/push-coalescer.d.ts.map +1 -1
- package/dist/src/mcpl/push-coalescer.js +93 -32
- 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 +76 -13
- package/dist/src/mcpl/reference-fetcher.d.ts.map +1 -1
- package/dist/src/mcpl/reference-fetcher.js +275 -66
- package/dist/src/mcpl/reference-fetcher.js.map +1 -1
- package/dist/src/mcpl/references.d.ts +98 -18
- package/dist/src/mcpl/references.d.ts.map +1 -1
- package/dist/src/mcpl/references.js +170 -32
- package/dist/src/mcpl/references.js.map +1 -1
- package/dist/src/mcpl/server-connection.d.ts +406 -31
- package/dist/src/mcpl/server-connection.d.ts.map +1 -1
- package/dist/src/mcpl/server-connection.js +1331 -272
- package/dist/src/mcpl/server-connection.js.map +1 -1
- package/dist/src/mcpl/server-registry.d.ts +35 -6
- package/dist/src/mcpl/server-registry.d.ts.map +1 -1
- package/dist/src/mcpl/server-registry.js +63 -13
- package/dist/src/mcpl/server-registry.js.map +1 -1
- package/dist/src/mcpl/skip-reply-wake.d.ts +36 -0
- package/dist/src/mcpl/skip-reply-wake.d.ts.map +1 -0
- package/dist/src/mcpl/skip-reply-wake.js +55 -0
- package/dist/src/mcpl/skip-reply-wake.js.map +1 -0
- package/dist/src/mcpl/tool-result-normalize.d.ts +54 -0
- package/dist/src/mcpl/tool-result-normalize.d.ts.map +1 -0
- package/dist/src/mcpl/tool-result-normalize.js +232 -0
- package/dist/src/mcpl/tool-result-normalize.js.map +1 -0
- package/dist/src/mcpl/transport.d.ts +104 -12
- package/dist/src/mcpl/transport.d.ts.map +1 -1
- package/dist/src/mcpl/transport.js +315 -85
- package/dist/src/mcpl/transport.js.map +1 -1
- package/dist/src/mcpl/types.d.ts +76 -19
- 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 +16 -0
- package/dist/src/mcpl/visible-content.d.ts.map +1 -1
- package/dist/src/mcpl/visible-content.js +26 -0
- package/dist/src/mcpl/visible-content.js.map +1 -1
- package/dist/src/module-registry.d.ts +34 -6
- package/dist/src/module-registry.d.ts.map +1 -1
- package/dist/src/module-registry.js +119 -31
- package/dist/src/module-registry.js.map +1 -1
- package/dist/src/modules/api/index.d.ts +1 -1
- package/dist/src/modules/api/index.d.ts.map +1 -1
- package/dist/src/modules/api/index.js +3 -2
- package/dist/src/modules/api/index.js.map +1 -1
- package/dist/src/modules/discord/discord-js-client.d.ts +43 -2
- package/dist/src/modules/discord/discord-js-client.d.ts.map +1 -1
- package/dist/src/modules/discord/discord-js-client.js +286 -67
- package/dist/src/modules/discord/discord-js-client.js.map +1 -1
- package/dist/src/modules/discord/index.d.ts +53 -5
- package/dist/src/modules/discord/index.d.ts.map +1 -1
- package/dist/src/modules/discord/index.js +712 -186
- package/dist/src/modules/discord/index.js.map +1 -1
- package/dist/src/modules/discord/refusal.d.ts +14 -0
- package/dist/src/modules/discord/refusal.d.ts.map +1 -0
- package/dist/src/modules/discord/refusal.js +14 -0
- package/dist/src/modules/discord/refusal.js.map +1 -0
- package/dist/src/modules/discord/types.d.ts +27 -4
- 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 +8 -3
- 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/index.d.ts +1 -1
- package/dist/src/modules/index.d.ts.map +1 -1
- package/dist/src/modules/index.js +1 -1
- package/dist/src/modules/index.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 +57 -4
- package/dist/src/modules/workspace/disk-agreement.d.ts.map +1 -1
- package/dist/src/modules/workspace/disk-agreement.js +75 -7
- package/dist/src/modules/workspace/disk-agreement.js.map +1 -1
- package/dist/src/modules/workspace/effects.d.ts +66 -7
- package/dist/src/modules/workspace/effects.d.ts.map +1 -1
- package/dist/src/modules/workspace/effects.js +303 -46
- package/dist/src/modules/workspace/effects.js.map +1 -1
- package/dist/src/modules/workspace/index.d.ts +313 -45
- package/dist/src/modules/workspace/index.d.ts.map +1 -1
- package/dist/src/modules/workspace/index.js +1404 -304
- package/dist/src/modules/workspace/index.js.map +1 -1
- package/dist/src/modules/workspace/observe.d.ts +315 -16
- package/dist/src/modules/workspace/observe.d.ts.map +1 -1
- package/dist/src/modules/workspace/observe.js +727 -37
- 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 +28 -5
- 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 +49 -2
- package/dist/src/modules/workspace/watcher.d.ts.map +1 -1
- package/dist/src/modules/workspace/watcher.js +158 -29
- 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/silent-heartbeat.d.ts +112 -39
- package/dist/src/silent-heartbeat.d.ts.map +1 -1
- package/dist/src/silent-heartbeat.js +100 -29
- package/dist/src/silent-heartbeat.js.map +1 -1
- package/dist/src/tool-args.d.ts +40 -0
- package/dist/src/tool-args.d.ts.map +1 -0
- package/dist/src/tool-args.js +207 -0
- package/dist/src/tool-args.js.map +1 -0
- 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 +266 -62
- 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 +44 -22
- package/dist/src/types/agent.d.ts.map +1 -1
- package/dist/src/types/events.d.ts +25 -0
- package/dist/src/types/events.d.ts.map +1 -1
- package/dist/src/types/framework.d.ts +38 -7
- 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 +77 -14
- package/dist/src/types/module.d.ts.map +1 -1
- package/dist/src/types/trace.d.ts +97 -8
- 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 +5 -4
- package/src/agent.ts +257 -72
- 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/index.ts +1 -0
- package/src/code-execution/py-runner.ts +304 -93
- package/src/code-execution/runtime-py.ts +94 -8
- package/src/code-execution/tool-definition.ts +85 -7
- package/src/config-checks.ts +50 -0
- package/src/deadline-timer.ts +44 -0
- package/src/error-message.ts +48 -0
- package/src/framework.ts +8625 -1984
- package/src/gate/event-gate.ts +38 -5
- package/src/held-writes.ts +59 -0
- package/src/index.ts +29 -5
- package/src/mcpl/capability-grant.ts +1 -1
- package/src/mcpl/channel-registry.ts +1095 -411
- package/src/mcpl/checkpoint-manager.ts +104 -29
- package/src/mcpl/conversation-router.ts +28 -8
- package/src/mcpl/convert-block.ts +105 -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 +23 -1
- package/src/mcpl/inference-router.ts +179 -103
- package/src/mcpl/log-value.ts +10 -0
- package/src/mcpl/modern-connection.ts +1182 -0
- package/src/mcpl/prefix-rule.ts +32 -0
- package/src/mcpl/protocol-family.ts +691 -0
- package/src/mcpl/push-coalescer.ts +110 -36
- package/src/mcpl/push-handler.ts +20 -90
- package/src/mcpl/reference-fetcher.ts +318 -67
- package/src/mcpl/references.ts +183 -34
- package/src/mcpl/server-connection.ts +1404 -280
- package/src/mcpl/server-registry.ts +63 -14
- package/src/mcpl/skip-reply-wake.ts +73 -0
- package/src/mcpl/tool-result-normalize.ts +294 -0
- package/src/mcpl/transport.ts +320 -76
- package/src/mcpl/types.ts +77 -19
- package/src/mcpl/visible-content.ts +28 -0
- package/src/module-registry.ts +126 -36
- package/src/modules/api/index.ts +3 -2
- package/src/modules/discord/discord-js-client.ts +306 -74
- package/src/modules/discord/index.ts +737 -201
- package/src/modules/discord/refusal.ts +13 -0
- package/src/modules/discord/types.ts +27 -6
- package/src/modules/health/index.ts +8 -3
- package/src/modules/history/index.ts +410 -120
- package/src/modules/history/semantic.ts +189 -32
- package/src/modules/index.ts +1 -1
- package/src/modules/unknown-tool.ts +16 -0
- package/src/modules/workspace/disk-agreement.ts +97 -8
- package/src/modules/workspace/effects.ts +291 -36
- package/src/modules/workspace/index.ts +1469 -321
- package/src/modules/workspace/observe.ts +784 -41
- package/src/modules/workspace/reconcile.ts +619 -64
- package/src/modules/workspace/types.ts +28 -5
- package/src/modules/workspace/watcher.ts +154 -30
- 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/silent-heartbeat.ts +184 -59
- package/src/tool-args.ts +213 -0
- package/src/tool-image-ledger.ts +153 -34
- package/src/tool-presentation.ts +233 -42
- 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 +44 -24
- package/src/types/events.ts +25 -0
- package/src/types/framework.ts +38 -7
- package/src/types/inference-log.ts +1 -1
- package/src/types/module.ts +79 -14
- package/src/types/trace.ts +103 -8
- 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-image-ledger.ts
CHANGED
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
*/
|
|
28
28
|
|
|
29
29
|
import { createHash, randomBytes } from 'node:crypto';
|
|
30
|
+
import { REFERENCE_STUB_MAX_CHARS, referenceTypeLabel } from './mcpl/references.js';
|
|
30
31
|
import { safeSlice } from './safe-slice.js';
|
|
31
32
|
|
|
32
33
|
export interface RetainedToolImage {
|
|
@@ -189,8 +190,9 @@ function mintLedgerNonce(): string {
|
|
|
189
190
|
/** Grammar of a ref this module mints: `img_<ledger nonce>_<sequence>`. */
|
|
190
191
|
export const TOOL_IMAGE_REF_RE = /^img_[0-9a-z]+_\d+$/;
|
|
191
192
|
|
|
192
|
-
/** RFC 6838 type/subtype token characters (lowercased)
|
|
193
|
-
|
|
193
|
+
/** RFC 6838 type/subtype token characters (lowercased), each name at most
|
|
194
|
+
* 127 characters (its section 4.2); no parameters. */
|
|
195
|
+
const MEDIA_TYPE_ESSENCE_RE = /^[a-z0-9!#$&^_.+-]{1,127}\/[a-z0-9!#$&^_.+-]{1,127}$/;
|
|
194
196
|
export const FALLBACK_MEDIA_TYPE = 'application/octet-stream';
|
|
195
197
|
|
|
196
198
|
/**
|
|
@@ -228,21 +230,32 @@ export type ParsedImagePlaceholder =
|
|
|
228
230
|
/** The placeholder exactly as it appears in the text. */
|
|
229
231
|
text: string;
|
|
230
232
|
}
|
|
231
|
-
/** An RFC-005 reference stub whose
|
|
233
|
+
/** An RFC-005 reference stub whose text shows an image type — bytes live
|
|
232
234
|
* behind fetch_reference, never in this ledger. Occupies a slot so the
|
|
233
235
|
* index cannot slide past it. */
|
|
234
236
|
| {
|
|
235
237
|
kind: 'reference';
|
|
236
238
|
refId: string;
|
|
237
|
-
/**
|
|
238
|
-
|
|
239
|
+
/** The image type the stub shows, as a stub shows a type (sanitized and
|
|
240
|
+
* bounded), lowercased: the first `image/` token in its text, which can
|
|
241
|
+
* come from its name. */
|
|
242
|
+
mediaType: string;
|
|
239
243
|
offset: number;
|
|
240
244
|
/** The stub line exactly as it appears in the text. */
|
|
241
245
|
text: string;
|
|
242
246
|
};
|
|
243
247
|
|
|
244
|
-
|
|
245
|
-
|
|
248
|
+
/**
|
|
249
|
+
* `[image: image/png, ~691KB, ref img_k7x3q2_7]`. Each part is bounded by
|
|
250
|
+
* what formatToolImagePlaceholder writes, so text shaped like a placeholder
|
|
251
|
+
* but longer is no slot: a type and a subtype name at RFC 6838's 127
|
|
252
|
+
* characters each (normalizeMediaType writes none longer), and a size's
|
|
253
|
+
* number, a ledger nonce and a sequence at 16 characters each, a safe
|
|
254
|
+
* integer's digits.
|
|
255
|
+
*/
|
|
256
|
+
const PLACEHOLDER_RE = /\[image: ([a-z0-9!#$&^_.+-]{1,127}\/[a-z0-9!#$&^_.+-]{1,127}), (~?[\d.]{1,16}(?:B|KB|MB))(?:, ref (img_[0-9a-z]{1,16}_\d{1,16}))?\]/g;
|
|
257
|
+
/** `[ref_1_ab3d] cam.png — image/png, 1.2MB claimed — from tool result — …`
|
|
258
|
+
* (one line, at most REFERENCE_STUB_MAX_CHARS long: see parseImagePlaceholders). */
|
|
246
259
|
const REFERENCE_STUB_RE = /^\[(ref_[0-9a-z]+_[0-9a-z]+)\] ([^\n]*)$/gm;
|
|
247
260
|
const IMAGE_MIME_RE = /\bimage\/[a-z0-9!#$&^_.+-]+/i;
|
|
248
261
|
|
|
@@ -252,6 +265,13 @@ const IMAGE_MIME_RE = /\bimage\/[a-z0-9!#$&^_.+-]+/i;
|
|
|
252
265
|
* untrusted — a tool result can quote someone else's placeholder verbatim —
|
|
253
266
|
* so the caller MUST cross-check a resolved ref's provenance against the
|
|
254
267
|
* tool_result block it was found in before handing out bytes.
|
|
268
|
+
*
|
|
269
|
+
* Decided from the text alone, so a stored result counts the same however
|
|
270
|
+
* long ago it was written, across restarts and registry evictions. A
|
|
271
|
+
* reference stub is a slot when its text shows an image type, and a
|
|
272
|
+
* non-image reference is no slot. A line shaped like a stub but longer than
|
|
273
|
+
* buildReferenceStub writes (REFERENCE_STUB_MAX_CHARS) is quoted text and no
|
|
274
|
+
* slot either, so a slot's text is bounded wherever it is kept.
|
|
255
275
|
*/
|
|
256
276
|
export function parseImagePlaceholders(text: string): ParsedImagePlaceholder[] {
|
|
257
277
|
const out: ParsedImagePlaceholder[] = [];
|
|
@@ -259,43 +279,142 @@ export function parseImagePlaceholders(text: string): ParsedImagePlaceholder[] {
|
|
|
259
279
|
out.push({ kind: 'inline', mediaType: m[1]!, sizeLabel: m[2]!, ref: m[3] ?? null, offset: m.index ?? 0, text: m[0] });
|
|
260
280
|
}
|
|
261
281
|
for (const m of text.matchAll(REFERENCE_STUB_RE)) {
|
|
262
|
-
|
|
263
|
-
|
|
282
|
+
if (m[0].length > REFERENCE_STUB_MAX_CHARS) continue;
|
|
283
|
+
const shown = m[2]!.match(IMAGE_MIME_RE);
|
|
284
|
+
if (!shown) continue;
|
|
285
|
+
out.push({ kind: 'reference', refId: m[1]!, mediaType: referenceTypeLabel(shown[0]).toLowerCase(), offset: m.index ?? 0, text: m[0] });
|
|
264
286
|
}
|
|
265
287
|
out.sort((a, b) => a.offset - b.offset);
|
|
266
288
|
return out;
|
|
267
289
|
}
|
|
268
290
|
|
|
269
291
|
/**
|
|
270
|
-
*
|
|
271
|
-
*
|
|
272
|
-
*
|
|
273
|
-
*
|
|
274
|
-
*
|
|
275
|
-
*
|
|
276
|
-
*
|
|
277
|
-
*
|
|
278
|
-
*
|
|
279
|
-
*
|
|
292
|
+
* The most image slots a stored copy keeps past its cut: a bound on what it
|
|
293
|
+
* carries there, set at the ledger's entry limit, the most images it holds
|
|
294
|
+
* bytes for. Serializing a result retains its images in order before their
|
|
295
|
+
* placeholders are written, and every agent's ledger is built with the
|
|
296
|
+
* defaults, so once a result is stored a save can reach bytes for at most
|
|
297
|
+
* its newest DEFAULT_TOOL_IMAGE_LEDGER_MAX_ENTRIES images, fewer when the
|
|
298
|
+
* ledger's limit on held characters binds first, and an inline image older
|
|
299
|
+
* than those can only fail. Image stubs and quoted placeholders count toward
|
|
300
|
+
* the bound too, so where they follow a result's images past the cut, the
|
|
301
|
+
* newest slots kept can leave out an image whose bytes the ledger still
|
|
302
|
+
* holds.
|
|
303
|
+
*/
|
|
304
|
+
export const MAX_KEPT_IMAGE_SLOTS = DEFAULT_TOOL_IMAGE_LEDGER_MAX_ENTRIES;
|
|
305
|
+
|
|
306
|
+
/** The ranges `[start, end)` of a tool result's text that its live copy
|
|
307
|
+
* showed beside its images: each text block up to where the live copy cut it
|
|
308
|
+
* at the inline cap (toolResultCutAt), and every other block whole. They
|
|
309
|
+
* come in text order and never overlap, as the blocks do, and
|
|
310
|
+
* cutStoredToolResult relies on that. */
|
|
311
|
+
export type ShownRanges = ReadonlyArray<readonly [number, number]>;
|
|
312
|
+
|
|
313
|
+
/** A tool result's stored copy, cut at its inline cap. */
|
|
314
|
+
export interface StoredCut {
|
|
315
|
+
/** The text before the cut. */
|
|
316
|
+
head: string;
|
|
317
|
+
/** The image slots past the cut that the stored copy re-appends after its
|
|
318
|
+
* truncation notice, in text order: the newest MAX_KEPT_IMAGE_SLOTS of
|
|
319
|
+
* those the live copy showed. */
|
|
320
|
+
kept: string[];
|
|
321
|
+
/** How many image slots past the cut the live copy showed. */
|
|
322
|
+
fell: number;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Where a tool result's text longer than `cap` is cut: by its stored copy
|
|
327
|
+
* (cutStoredToolResult), by history's own truncation (truncateForHistory),
|
|
328
|
+
* and by its live copy, for each text block beside an image
|
|
329
|
+
* (tryNativeToolResultContent, framework.ts), so the stored copy and the live
|
|
330
|
+
* copy cut alike. The text's length when it isn't longer than `cap`.
|
|
331
|
+
*
|
|
332
|
+
* The cut is made at the cap, or before it when the cap would split a
|
|
333
|
+
* surrogate pair (safeSlice's rule), and that is where the moves back are
|
|
334
|
+
* measured from. It moves back to the start of a placeholder it would split,
|
|
335
|
+
* and then to the start of a stub-shaped line it would split when at most
|
|
336
|
+
* REFERENCE_STUB_MAX_CHARS of the line lie before it, since that part could
|
|
337
|
+
* still read as a slot. So no slot straddles the cut, and the text before it
|
|
338
|
+
* never ends in part of one. A longer part, which can't parse as a slot,
|
|
339
|
+
* stays before the cut. Each move back lands on a `[`, so it splits no pair.
|
|
280
340
|
*/
|
|
281
|
-
export function
|
|
282
|
-
|
|
283
|
-
let cutAt = cap;
|
|
284
|
-
|
|
285
|
-
|
|
341
|
+
export function toolResultCutAt(text: string, cap: number): number {
|
|
342
|
+
if (text.length <= cap) return text.length;
|
|
343
|
+
let cutAt = safeSlice(text, 0, cap).length;
|
|
344
|
+
// Neither grammar crosses a newline, so only the line holding the cut can
|
|
345
|
+
// be split; it is read whole, as the parser reads it.
|
|
346
|
+
const lineStart = text.lastIndexOf('\n', cutAt - 1) + 1;
|
|
347
|
+
const newline = text.indexOf('\n', cutAt);
|
|
348
|
+
const line = text.slice(lineStart, newline === -1 ? text.length : newline);
|
|
349
|
+
for (const m of line.matchAll(PLACEHOLDER_RE)) {
|
|
350
|
+
const start = lineStart + (m.index ?? 0);
|
|
351
|
+
if (start < cutAt && start + m[0].length > cutAt) cutAt = start;
|
|
286
352
|
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
}
|
|
353
|
+
for (const m of line.matchAll(REFERENCE_STUB_RE)) {
|
|
354
|
+
const start = lineStart + (m.index ?? 0);
|
|
355
|
+
if (start < cutAt && start + m[0].length > cutAt && cutAt - start <= REFERENCE_STUB_MAX_CHARS) cutAt = start;
|
|
356
|
+
}
|
|
357
|
+
return cutAt;
|
|
291
358
|
}
|
|
292
359
|
|
|
293
|
-
/**
|
|
294
|
-
*
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
360
|
+
/**
|
|
361
|
+
* Cut a tool result's text at its inline `cap` as its stored copy keeps it
|
|
362
|
+
* (toolResultCutAt): the stored copy keeps what the live copy showed. A text
|
|
363
|
+
* within the cap is all head, with nothing kept after it.
|
|
364
|
+
*
|
|
365
|
+
* `shown` is what the live copy showed beside the stored text: null when the
|
|
366
|
+
* live copy was the text itself, as for every result that carried no inline
|
|
367
|
+
* image. Then what the cut keeps is exactly what the resident saw, and
|
|
368
|
+
* nothing past it is kept (#403). A result that carried an inline image went
|
|
369
|
+
* to the model as native blocks (tryNativeToolResultContent, framework.ts),
|
|
370
|
+
* every image whatever the text's length, so its stored text is the only
|
|
371
|
+
* place save_recent_image's inventory finds them, and a slot dropped by the
|
|
372
|
+
* cut would be an image the resident saw that the index slides past (#104).
|
|
373
|
+
* The image slots past the cut that lie wholly within what the live copy
|
|
374
|
+
* showed are kept, the newest MAX_KEPT_IMAGE_SLOTS of them, since the
|
|
375
|
+
* inventory counts from the end.
|
|
376
|
+
*/
|
|
377
|
+
export function cutStoredToolResult(text: string, cap: number, shown: ShownRanges | null): StoredCut {
|
|
378
|
+
const cutAt = toolResultCutAt(text, cap);
|
|
379
|
+
const head = text.slice(0, cutAt);
|
|
380
|
+
if (shown === null) return { head, kept: [], fell: 0 };
|
|
381
|
+
// The slots and the ranges both come in text order, so one pass walks
|
|
382
|
+
// them together: a range that ends where a slot starts, or before, holds
|
|
383
|
+
// no later slot either.
|
|
384
|
+
const past: ParsedImagePlaceholder[] = [];
|
|
385
|
+
let r = 0;
|
|
386
|
+
for (const slot of parseImagePlaceholders(text)) {
|
|
387
|
+
if (slot.offset < cutAt) continue;
|
|
388
|
+
while (r < shown.length && shown[r]![1] <= slot.offset) r++;
|
|
389
|
+
const range = shown[r];
|
|
390
|
+
if (range && slot.offset >= range[0] && slot.offset + slot.text.length <= range[1]) past.push(slot);
|
|
391
|
+
}
|
|
392
|
+
return { head, kept: past.slice(-MAX_KEPT_IMAGE_SLOTS).map((slot) => slot.text), fell: past.length };
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/** What a stored copy re-appends after its truncation notice: the kept
|
|
396
|
+
* slots, each on its own line so a reference stub stays parseable, under a
|
|
397
|
+
* note saying how many fell past the cut, and how many of those were left
|
|
398
|
+
* out and aren't counted. Empty when none fell past the cut. */
|
|
399
|
+
export function formatKeptImageSlots(cut: StoredCut): string {
|
|
400
|
+
if (cut.fell === 0) return '';
|
|
401
|
+
const leftOut = cut.fell - cut.kept.length;
|
|
402
|
+
const note = leftOut === 0
|
|
403
|
+
? `${cut.fell} image slot(s) fell past the cut; kept here in order so save_recent_image still counts them:`
|
|
404
|
+
: `${cut.fell} image slot(s) fell past the cut. The last ${cut.kept.length} are kept here in order so `
|
|
405
|
+
+ `save_recent_image still counts them; the ${leftOut} before them are left out, and it doesn't count them:`;
|
|
406
|
+
return `\n[${note}]\n${cut.kept.join('\n')}`;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* The image slots a tool result's stored copy holds: its text's, or, when the
|
|
411
|
+
* text is longer than `cap`, those the cut keeps, in head and after the
|
|
412
|
+
* notice (cutStoredToolResult). The notice itself holds none. For counting a
|
|
413
|
+
* result before its stored copy is written, as it will count after.
|
|
414
|
+
*/
|
|
415
|
+
export function storedImageSlots(text: string, cap: number, shown: ShownRanges | null): ParsedImagePlaceholder[] {
|
|
416
|
+
const cut = cutStoredToolResult(text, cap, shown);
|
|
417
|
+
return parseImagePlaceholders(cut.head + formatKeptImageSlots(cut));
|
|
299
418
|
}
|
|
300
419
|
|
|
301
420
|
export function sha256Hex(bytes: Buffer): string {
|
package/src/tool-presentation.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { createHash, randomUUID } from 'node:crypto';
|
|
2
|
-
import { fchmodSync, closeSync, fstatSync, lstatSync, openSync, readSync, renameSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { constants, 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,145 @@ 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
|
+
/**
|
|
28
|
+
* Opened with each read of a presentation file, as observe.ts opens workspace
|
|
29
|
+
* files: a FIFO at the operator's path opens at once and fails the regular-file
|
|
30
|
+
* check, where a blocking open would hold the whole process (it's synchronous)
|
|
31
|
+
* until something opened the FIFO for writing.
|
|
32
|
+
*/
|
|
33
|
+
const NONBLOCK = typeof constants.O_NONBLOCK === 'number' ? constants.O_NONBLOCK : 0;
|
|
34
|
+
const MAX_DESCRIPTION_CHARS = 32768;
|
|
25
35
|
const protectedNames = new Set(['set_tool_visibility', 'set_tool_description', 'workspace--read']);
|
|
26
36
|
export const isPresentationTool = (name: string): boolean => name === 'set_tool_visibility' || name === 'set_tool_description';
|
|
27
37
|
const hash = (value: string): string => createHash('sha256').update(value).digest('hex');
|
|
28
38
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
39
|
+
/**
|
|
40
|
+
* A presentation or defaults file this host can't use. Each problem is a
|
|
41
|
+
* clause about the file, such as `the entry for "x" has "visible": "no",
|
|
42
|
+
* which must be true or false`; whoever reports it names the file and says
|
|
43
|
+
* what follows from it.
|
|
44
|
+
*/
|
|
45
|
+
class PresentationFileError extends Error {
|
|
46
|
+
constructor(problems: string[]) {
|
|
47
|
+
const more = problems.length - 10;
|
|
48
|
+
super((more > 0 ? [...problems.slice(0, 10), `${more} more problem${more === 1 ? '' : 's'}`] : problems).join('; '));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** An edit refused, in words for the agent: its message is the whole result. */
|
|
53
|
+
class PresentationRefusal extends Error {}
|
|
54
|
+
|
|
55
|
+
const count = (n: number): string => n.toLocaleString('en-US');
|
|
56
|
+
|
|
57
|
+
/** 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. */
|
|
58
|
+
const characters = (text: string): number => [...text].length;
|
|
59
|
+
|
|
60
|
+
/** A text's first `n` characters, never splitting a code point. */
|
|
61
|
+
const firstCharacters = (text: string, n: number): string => [...text].slice(0, n).join('');
|
|
62
|
+
|
|
63
|
+
/** 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. */
|
|
64
|
+
function quoted(name: string): string {
|
|
65
|
+
return characters(name) <= 60 ? JSON.stringify(name) : `${JSON.stringify(firstCharacters(name, 57))}... (${count(characters(name))} characters)`;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** 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. */
|
|
69
|
+
const problemText = (error: unknown): string => error instanceof PresentationFileError ? error.message : boundedErrorMessage(error);
|
|
70
|
+
|
|
71
|
+
/** A value as a message quotes it: short JSON for a scalar, the kind of anything bigger. */
|
|
72
|
+
function shown(value: unknown): string {
|
|
73
|
+
if (Array.isArray(value)) return 'an array';
|
|
74
|
+
if (value !== null && typeof value === 'object') return 'an object';
|
|
75
|
+
const json = JSON.stringify(value) ?? String(value);
|
|
76
|
+
return characters(json) > 40 ? `${firstCharacters(json, 37)}...` : json;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** 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. */
|
|
80
|
+
function quotedList(names: string[], conjunction: 'and' | 'or' = 'and', quote: (name: string) => string = quoted): string {
|
|
81
|
+
const each = names.slice(0, 10).map((name) => quote(name));
|
|
82
|
+
if (names.length > 10) return `${each.join(', ')} ${conjunction} ${count(names.length - 10)} more`;
|
|
83
|
+
return each.length > 1 ? `${each.slice(0, -1).join(', ')} ${conjunction} ${each[each.length - 1]}` : each.join('');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Every problem that keeps a document from being used, each by where it is;
|
|
88
|
+
* none for a usable one. A defaults file (`descriptionsOnly`) may set
|
|
89
|
+
* descriptions only, since visibility is the resident's to choose.
|
|
90
|
+
*/
|
|
91
|
+
function documentProblems(doc: unknown, descriptionsOnly: boolean): string[] {
|
|
92
|
+
if (!doc || typeof doc !== 'object' || Array.isArray(doc)) return [`its top level is ${shown(doc)}, not an object like {"version":1,"tools":{}}`];
|
|
93
|
+
const top = doc as Record<string, unknown>;
|
|
94
|
+
const problems: string[] = [];
|
|
95
|
+
if (top.version !== 1) problems.push(`"version" must be 1, and ${Object.hasOwn(top, 'version') ? `it is ${shown(top.version)}` : "it's missing"}`);
|
|
96
|
+
const extra = Object.keys(top).filter((key) => key !== 'version' && key !== 'tools');
|
|
97
|
+
if (extra.length) problems.push(`only "version" and "tools" belong at the top level, not ${quotedList(extra)}`);
|
|
98
|
+
const tools = top.tools;
|
|
99
|
+
if (!tools || typeof tools !== 'object' || Array.isArray(tools)) {
|
|
100
|
+
problems.push(`"tools" must be an object of tool names, and ${Object.hasOwn(top, 'tools') ? `it is ${shown(tools)}` : "it's missing"}`);
|
|
101
|
+
return problems;
|
|
102
|
+
}
|
|
103
|
+
const setsVisibility: string[] = [];
|
|
104
|
+
for (const [name, value] of Object.entries(tools)) {
|
|
105
|
+
if (!name) { problems.push('"tools" has an entry with an empty name'); continue; }
|
|
106
|
+
const entry = `the entry for ${quoted(name)}`;
|
|
107
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) { problems.push(`${entry} is ${shown(value)}, not an object such as {"visible":false}`); continue; }
|
|
35
108
|
const item = value as Record<string, unknown>;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
109
|
+
const unknown = Object.keys(item).filter((key) => key !== 'description' && key !== 'visible');
|
|
110
|
+
if (unknown.length) problems.push(`${entry} has ${quotedList(unknown)}, and an entry may have only ${descriptionsOnly ? '"description"' : '"description" and "visible"'}`);
|
|
111
|
+
if (Object.hasOwn(item, 'description')) {
|
|
112
|
+
if (typeof item.description !== 'string') problems.push(`${entry} has a "description" that is ${shown(item.description)}, not a string`);
|
|
113
|
+
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`);
|
|
114
|
+
}
|
|
115
|
+
if (!Object.hasOwn(item, 'visible')) continue;
|
|
116
|
+
if (descriptionsOnly) setsVisibility.push(name);
|
|
117
|
+
else if (typeof item.visible !== 'boolean') problems.push(`${entry} has "visible": ${shown(item.visible)}, which must be true or false`);
|
|
118
|
+
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
119
|
}
|
|
41
|
-
|
|
120
|
+
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`);
|
|
121
|
+
return problems;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function parseDocument(raw: string, descriptionsOnly: boolean): PresentationDocument {
|
|
125
|
+
let doc: unknown;
|
|
126
|
+
try { doc = JSON.parse(raw); }
|
|
127
|
+
catch (error) { throw new PresentationFileError([`it isn't valid JSON: ${errorMessage(error)}`]); }
|
|
128
|
+
const problems = documentProblems(doc, descriptionsOnly);
|
|
129
|
+
if (problems.length) throw new PresentationFileError(problems);
|
|
130
|
+
return doc as PresentationDocument;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** A resident's presentation document, or an error naming every problem that keeps it from being used. */
|
|
134
|
+
export function parsePresentation(raw: string): PresentationDocument {
|
|
135
|
+
return parseDocument(raw, false);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* What an agent is told when an edit fails. Every throw in `edit()` comes
|
|
140
|
+
* before its rename, and the cleanup after it never throws, so nothing was
|
|
141
|
+
* changed: a refusal says so in its own words, a file this host can't use is
|
|
142
|
+
* the host's to repair, and anything else is reported as the error it is.
|
|
143
|
+
*/
|
|
144
|
+
function editFailure(error: unknown): string {
|
|
145
|
+
if (error instanceof PresentationRefusal) return error.message;
|
|
146
|
+
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.`;
|
|
147
|
+
const code = (error as NodeJS.ErrnoException | null)?.code;
|
|
148
|
+
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.`;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** Whether a path is a symbolic link, so an open that found nothing can tell a dangling link from no file. */
|
|
152
|
+
function isLink(path: string): boolean {
|
|
153
|
+
try { return lstatSync(path).isSymbolicLink(); } catch { return false; }
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** Runs one step of an edit's cleanup, which must not throw: it returns what the step threw, if it did. */
|
|
157
|
+
function tidy(step: () => void): { error: unknown } | undefined {
|
|
158
|
+
try { step(); return undefined; } catch (error) { return { error }; }
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** What an edit says when its lock couldn't be removed afterwards, since every later edit will meet that lock. */
|
|
162
|
+
function lockLeftBehind(error: unknown): string {
|
|
163
|
+
const code = (error as NodeJS.ErrnoException | undefined)?.code;
|
|
164
|
+
return `This edit couldn't remove its lock afterwards, the presentation file's name with .lock added${typeof code === 'string' ? ` (${code})` : ''}. `
|
|
165
|
+
+ '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
166
|
}
|
|
43
167
|
|
|
44
168
|
export function presentationTools(path: string): ToolDefinition[] {
|
|
@@ -56,44 +180,51 @@ export class ToolPresentation {
|
|
|
56
180
|
constructor(readonly config: ToolPresentationConfig) {}
|
|
57
181
|
private read(path = this.config.path, allowMissing = true): string {
|
|
58
182
|
let fd: number;
|
|
59
|
-
try { fd = openSync(path,
|
|
60
|
-
catch (error) {
|
|
183
|
+
try { fd = openSync(path, constants.O_RDONLY | NONBLOCK); }
|
|
184
|
+
catch (error) {
|
|
185
|
+
const code = (error as NodeJS.ErrnoException).code;
|
|
186
|
+
if (code === 'ENOENT') {
|
|
187
|
+
if (isLink(path)) throw new PresentationFileError(["it's a symbolic link to a file that doesn't exist"]);
|
|
188
|
+
if (allowMissing) return '{"version":1,"tools":{}}';
|
|
189
|
+
throw new PresentationFileError(["it doesn't exist"]);
|
|
190
|
+
}
|
|
191
|
+
throw new PresentationFileError([`it couldn't be opened: ${code ?? boundedErrorMessage(error)}`]);
|
|
192
|
+
}
|
|
61
193
|
try {
|
|
62
194
|
const stat = fstatSync(fd);
|
|
63
|
-
if (!stat.isFile()
|
|
195
|
+
if (!stat.isFile()) throw new PresentationFileError(["it isn't a regular file"]);
|
|
196
|
+
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
197
|
const data = Buffer.alloc(MAX_BYTES + 1);
|
|
65
|
-
let size = 0,
|
|
66
|
-
while (size < data.length && (
|
|
67
|
-
if (size > MAX_BYTES) throw new
|
|
198
|
+
let size = 0, bytesRead = 0;
|
|
199
|
+
while (size < data.length && (bytesRead = readSync(fd, data, size, data.length - size, null)) > 0) size += bytesRead;
|
|
200
|
+
if (size > MAX_BYTES) throw new PresentationFileError([`it grew past ${count(MAX_BYTES)} bytes (256 KiB) while it was being read`]);
|
|
68
201
|
return data.subarray(0,size).toString('utf8');
|
|
69
202
|
} finally { closeSync(fd); }
|
|
70
203
|
}
|
|
71
204
|
resolve(tools: ToolDefinition[], sources: ReadonlyMap<string, string> = new Map()): PresentationSnapshot {
|
|
72
205
|
let raw = '', doc: PresentationDocument = {version:1,tools:{}}, diagnostics: string[] = [];
|
|
73
206
|
try { raw = this.read(); doc = parsePresentation(raw); }
|
|
74
|
-
catch (error) { diagnostics.push(`
|
|
207
|
+
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
208
|
const defaults = new Map<string, {description: string; path: string}>();
|
|
76
209
|
const configuredSources = new Set<string>();
|
|
77
210
|
for (const profile of this.config.defaults ?? []) {
|
|
78
211
|
if (configuredSources.has(profile.source)) {
|
|
79
|
-
diagnostics.push(`
|
|
212
|
+
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
213
|
}
|
|
81
214
|
configuredSources.add(profile.source);
|
|
82
215
|
// Absent components contribute neither tools nor missing-file errors.
|
|
83
216
|
if (!tools.some(t => (sources.get(t.name) ?? 'Unattributed') === profile.source)) continue;
|
|
84
217
|
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');
|
|
218
|
+
const profileDoc = parseDocument(this.read(profile.path, false), true);
|
|
88
219
|
for (const tool of tools) {
|
|
89
220
|
if ((sources.get(tool.name) ?? 'Unattributed') !== profile.source) continue;
|
|
90
221
|
const item = Object.hasOwn(profileDoc.tools, tool.name) ? profileDoc.tools[tool.name] : undefined;
|
|
91
222
|
if (item?.description !== undefined) defaults.set(tool.name, {description:item.description,path:profile.path});
|
|
92
223
|
}
|
|
93
|
-
} catch (error) { diagnostics.push(`
|
|
224
|
+
} 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
225
|
}
|
|
95
226
|
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}`);
|
|
227
|
+
for (const name of Object.keys(doc.tools)) if (!names.has(name)) diagnostics.push(`Not currently available: ${quoted(name)}`);
|
|
97
228
|
const entries = tools.map(tool => {
|
|
98
229
|
const override = Object.hasOwn(doc.tools, tool.name) ? doc.tools[tool.name] : undefined;
|
|
99
230
|
// Always retain a usable discovery signpost, even when its wording is overridden.
|
|
@@ -111,39 +242,98 @@ export class ToolPresentation {
|
|
|
111
242
|
edit(tool: string, input: unknown, available: ToolDefinition[]): ToolResult {
|
|
112
243
|
const lock = this.config.path + '.lock';
|
|
113
244
|
let fd: number | undefined, tempFd: number | undefined, temp: string | undefined;
|
|
245
|
+
let result: ToolResult, lockLeft: { error: unknown } | undefined;
|
|
114
246
|
try {
|
|
115
|
-
if (!isPresentationTool(tool)) throw new Error('
|
|
116
|
-
const value = input as Record<string, unknown>;
|
|
247
|
+
if (!isPresentationTool(tool)) throw new Error(`${tool} isn't a tool presentation editing tool`);
|
|
117
248
|
const field = tool === 'set_tool_visibility' ? 'visible' : 'description';
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
249
|
+
const name = this.editedName(tool, field, input, available);
|
|
250
|
+
const value = input as Record<string, unknown>;
|
|
251
|
+
try { fd = openSync(lock, 'wx', 0o600); }
|
|
252
|
+
catch (error) {
|
|
253
|
+
if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error;
|
|
254
|
+
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.");
|
|
255
|
+
}
|
|
123
256
|
let mode = 0o600;
|
|
124
|
-
try {
|
|
257
|
+
try {
|
|
258
|
+
const stat = lstatSync(this.config.path);
|
|
259
|
+
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.");
|
|
260
|
+
mode = stat.mode & 0o777;
|
|
261
|
+
}
|
|
125
262
|
catch (error) { if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error; }
|
|
126
263
|
const before = this.read(), doc = parsePresentation(before);
|
|
127
|
-
const old = Object.hasOwn(doc.tools,
|
|
264
|
+
const old = Object.hasOwn(doc.tools,name) ? doc.tools[name] : {};
|
|
128
265
|
const updated = {...old};
|
|
129
266
|
if (field === 'description' && value.description === null) delete updated.description;
|
|
130
267
|
else Object.assign(updated,{[field]:value[field]});
|
|
131
|
-
Object.defineProperty(doc.tools,
|
|
268
|
+
Object.defineProperty(doc.tools,name,{value:updated,enumerable:true,writable:true,configurable:true});
|
|
132
269
|
const next = JSON.stringify(doc,null,2)+'\n';
|
|
270
|
+
// editedName has checked what this adds, so this can't fail on the agent's input;
|
|
271
|
+
// it keeps a gap in those checks from writing a file the host would then ignore.
|
|
133
272
|
parsePresentation(next);
|
|
134
|
-
|
|
273
|
+
const size = Buffer.byteLength(next);
|
|
274
|
+
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). `
|
|
275
|
+
+ (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.')
|
|
276
|
+
+ ' Entries for tools no longer available to you can be removed only by whoever runs this host.');
|
|
135
277
|
temp = this.config.path + '.' + randomUUID() + '.tmp';
|
|
136
278
|
tempFd = openSync(temp,'wx',0o600);
|
|
137
279
|
writeFileSync(tempFd,next);
|
|
138
280
|
fchmodSync(tempFd,mode); // preserve permissions on the opened inode, never a replacement path
|
|
139
|
-
if (this.read() !== before) throw new
|
|
281
|
+
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
282
|
const opened = fstatSync(tempFd), named = lstatSync(temp);
|
|
141
283
|
if (!named.isFile() || named.dev !== opened.dev || named.ino !== opened.ino)
|
|
142
|
-
throw new
|
|
284
|
+
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
285
|
renameSync(temp,this.config.path); temp=undefined;
|
|
144
|
-
|
|
145
|
-
} catch (error) {
|
|
146
|
-
finally {
|
|
286
|
+
result = {success:true,data:{name,[field]:value[field],effective:'next newly compiled request',catalogue:this.config.cataloguePath}};
|
|
287
|
+
} catch (error) { result = {success:false,isError:true,error:editFailure(error)}; }
|
|
288
|
+
finally {
|
|
289
|
+
// After the rename the edit's result must stand, so no cleanup step may throw.
|
|
290
|
+
const tempFdToClose = tempFd, tempToRemove = temp, lockFd = fd;
|
|
291
|
+
if (tempFdToClose !== undefined) tidy(() => closeSync(tempFdToClose));
|
|
292
|
+
if (tempToRemove) tidy(() => unlinkSync(tempToRemove));
|
|
293
|
+
if (lockFd !== undefined) {
|
|
294
|
+
tidy(() => closeSync(lockFd));
|
|
295
|
+
lockLeft = tidy(() => unlinkSync(lock));
|
|
296
|
+
// A lock already gone was removed by something else, so none is left.
|
|
297
|
+
if ((lockLeft?.error as NodeJS.ErrnoException | undefined)?.code === 'ENOENT') lockLeft = undefined;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
if (!lockLeft) return result;
|
|
301
|
+
return result.success
|
|
302
|
+
? {...result,data:{...(result.data as Record<string, unknown>),note:lockLeftBehind(lockLeft.error)}}
|
|
303
|
+
: {...result,error:`${result.error} ${lockLeftBehind(lockLeft.error)}`};
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* The name of the tool an edit is for, once the agent's arguments hold up;
|
|
307
|
+
* otherwise a refusal naming every problem with them and the call to make.
|
|
308
|
+
* The limits a file would refuse (a description's length, the tools that
|
|
309
|
+
* can't be hidden) are checked here too, so they read as the agent's input
|
|
310
|
+
* rather than as a problem with the file.
|
|
311
|
+
*/
|
|
312
|
+
private editedName(tool: string, field: 'visible' | 'description', input: unknown, available: ToolDefinition[]): string {
|
|
313
|
+
const usage = field === 'visible'
|
|
314
|
+
? `set_tool_visibility takes {"name": a tool's exact name, "visible": true or false}.`
|
|
315
|
+
: `set_tool_description takes {"name": a tool's exact name, "description": the new text, or null to restore the default}.`;
|
|
316
|
+
if (!input || typeof input !== 'object' || Array.isArray(input)) throw new PresentationRefusal(`Nothing was changed: the arguments were ${shown(input)}, not an object. ${usage}`);
|
|
317
|
+
const args = input as Record<string, unknown>, problems: string[] = [];
|
|
318
|
+
if (!Object.hasOwn(args, 'name')) problems.push('"name" is missing');
|
|
319
|
+
else if (typeof args.name !== 'string') problems.push(`"name" is ${shown(args.name)}, not a string`);
|
|
320
|
+
if (!Object.hasOwn(args, field)) problems.push(`"${field}" is missing`);
|
|
321
|
+
else if (field === 'visible' ? typeof args.visible !== 'boolean' : args.description !== null && typeof args.description !== 'string')
|
|
322
|
+
problems.push(`"${field}" is ${shown(args[field])}, not ${field === 'visible' ? 'true or false' : 'a string or null'}`);
|
|
323
|
+
const extra = Object.keys(args).filter((key) => key !== 'name' && key !== field);
|
|
324
|
+
if (extra.length) problems.push(`${quotedList(extra)} ${extra.length > 1 ? "aren't arguments" : "isn't an argument"} of ${tool}`);
|
|
325
|
+
if (problems.length) throw new PresentationRefusal(`Nothing was changed: ${problems.join('; ')}. ${usage}`);
|
|
326
|
+
const name = args.name as string;
|
|
327
|
+
if (!available.some((t) => t.name === name)) {
|
|
328
|
+
const near = closestNames(name, available.map((t) => t.name));
|
|
329
|
+
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)}?` : ''}`
|
|
330
|
+
+ ` 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.`);
|
|
331
|
+
}
|
|
332
|
+
if (field === 'description' && typeof args.description === 'string' && characters(args.description) > MAX_DESCRIPTION_CHARS)
|
|
333
|
+
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.`);
|
|
334
|
+
if (field === 'visible' && args.visible === false && protectedNames.has(name))
|
|
335
|
+
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.`);
|
|
336
|
+
return name;
|
|
147
337
|
}
|
|
148
338
|
}
|
|
149
339
|
export function renderCatalogue(snapshot: PresentationSnapshot): string {
|
|
@@ -164,7 +354,8 @@ export function renderCatalogue(snapshot: PresentationSnapshot): string {
|
|
|
164
354
|
`Read details: workspace--read {"path":${JSON.stringify(snapshot.cataloguePath)},"offset":LINE,"limit":LINES}.`,
|
|
165
355
|
'Line references below belong to this revision; reread the index after changes.', '',
|
|
166
356
|
];
|
|
167
|
-
|
|
357
|
+
// One line each: a quoted parse error can hold the file's own line breaks.
|
|
358
|
+
for (const diagnostic of snapshot.diagnostics) lines.push('Diagnostic: '+diagnostic.replace(/\r\n|\r|\n/g, '\\n'));
|
|
168
359
|
lines.push('## Index by source', '');
|
|
169
360
|
const index = new Map<string, number>();
|
|
170
361
|
for (const [source, entries] of groups) {
|