@namzu/sdk 49.0.0 → 50.1.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/CHANGELOG.md +541 -0
- package/README.md +137 -125
- package/dist/agents/QueryAgent.d.ts.map +1 -1
- package/dist/agents/QueryAgent.js +1 -0
- package/dist/agents/QueryAgent.js.map +1 -1
- package/dist/agents/examples/SupervisorAgent.d.ts.map +1 -1
- package/dist/agents/examples/SupervisorAgent.js +1 -0
- package/dist/agents/examples/SupervisorAgent.js.map +1 -1
- package/dist/agents/runAgent.d.ts +2 -0
- package/dist/agents/runAgent.d.ts.map +1 -1
- package/dist/agents/runAgent.js +1 -0
- package/dist/agents/runAgent.js.map +1 -1
- package/dist/authorization/shell-lexer.d.ts.map +1 -1
- package/dist/authorization/shell-lexer.js +16 -1
- package/dist/authorization/shell-lexer.js.map +1 -1
- package/dist/bridge/acp/permission.d.ts +8 -2
- package/dist/bridge/acp/permission.d.ts.map +1 -1
- package/dist/bridge/acp/permission.js +1 -0
- package/dist/bridge/acp/permission.js.map +1 -1
- package/dist/bridge/acp/server.d.ts +25 -1
- package/dist/bridge/acp/server.d.ts.map +1 -1
- package/dist/bridge/acp/server.js +205 -21
- package/dist/bridge/acp/server.js.map +1 -1
- package/dist/bridge/acp/tasks.d.ts +5 -0
- package/dist/bridge/acp/tasks.d.ts.map +1 -0
- package/dist/bridge/acp/tasks.js +19 -0
- package/dist/bridge/acp/tasks.js.map +1 -0
- package/dist/bridge/acp/update.d.ts.map +1 -1
- package/dist/bridge/acp/update.js +148 -13
- package/dist/bridge/acp/update.js.map +1 -1
- package/dist/config/runtime.d.ts +31 -31
- package/dist/connector/mcp/adapter.d.ts.map +1 -1
- package/dist/connector/mcp/adapter.js +11 -4
- package/dist/connector/mcp/adapter.js.map +1 -1
- package/dist/connector/mcp/client.d.ts.map +1 -1
- package/dist/connector/mcp/client.js +6 -3
- package/dist/connector/mcp/client.js.map +1 -1
- package/dist/constants/acp/index.d.ts +3 -0
- package/dist/constants/acp/index.d.ts.map +1 -1
- package/dist/constants/acp/index.js +3 -0
- package/dist/constants/acp/index.js.map +1 -1
- package/dist/contracts/a2a.d.ts +80 -80
- package/dist/contracts/schemas.d.ts +2 -2
- package/dist/contracts/session/schemas.d.ts +10 -10
- package/dist/manager/agent/lifecycle.d.ts +11 -0
- package/dist/manager/agent/lifecycle.d.ts.map +1 -1
- package/dist/manager/agent/lifecycle.js +178 -3
- package/dist/manager/agent/lifecycle.js.map +1 -1
- package/dist/manager/plan/lifecycle.d.ts +7 -8
- package/dist/manager/plan/lifecycle.d.ts.map +1 -1
- package/dist/manager/plan/lifecycle.js +7 -8
- package/dist/manager/plan/lifecycle.js.map +1 -1
- package/dist/manager/resident/consumption.d.ts +8 -8
- package/dist/manager/resident/learning-cycle.d.ts +2 -2
- package/dist/manager/resident/learning-observation.d.ts +12 -12
- package/dist/manager/resident/learning.d.ts +82 -82
- package/dist/manager/resident/outbox.d.ts +8 -8
- package/dist/manager/resident/proposal.d.ts +2 -2
- package/dist/manager/resident/store.d.ts +10 -10
- package/dist/manager/session/attribution.d.ts +1 -0
- package/dist/manager/session/attribution.d.ts.map +1 -1
- package/dist/manager/session/attribution.js +9 -1
- package/dist/manager/session/attribution.js.map +1 -1
- package/dist/manager/session/streamed-message-identity.d.ts +6 -0
- package/dist/manager/session/streamed-message-identity.d.ts.map +1 -0
- package/dist/manager/session/streamed-message-identity.js +14 -0
- package/dist/manager/session/streamed-message-identity.js.map +1 -0
- package/dist/manager/session/turn-recorder.d.ts.map +1 -1
- package/dist/manager/session/turn-recorder.js +4 -3
- package/dist/manager/session/turn-recorder.js.map +1 -1
- package/dist/pals/activity/causality.d.ts +23 -0
- package/dist/pals/activity/causality.d.ts.map +1 -0
- package/dist/pals/activity/causality.js +205 -0
- package/dist/pals/activity/causality.js.map +1 -0
- package/dist/pals/activity/projection.d.ts +5 -0
- package/dist/pals/activity/projection.d.ts.map +1 -0
- package/dist/pals/activity/projection.js +79 -0
- package/dist/pals/activity/projection.js.map +1 -0
- package/dist/pals/activity/source.d.ts +16 -0
- package/dist/pals/activity/source.d.ts.map +1 -0
- package/dist/pals/activity/source.js +235 -0
- package/dist/pals/activity/source.js.map +1 -0
- package/dist/pals/activity/subscription-policy.d.ts +38 -0
- package/dist/pals/activity/subscription-policy.d.ts.map +1 -0
- package/dist/pals/activity/subscription-policy.js +183 -0
- package/dist/pals/activity/subscription-policy.js.map +1 -0
- package/dist/pals/activity/subscription-schema.d.ts +353 -0
- package/dist/pals/activity/subscription-schema.d.ts.map +1 -0
- package/dist/pals/activity/subscription-schema.js +24 -0
- package/dist/pals/activity/subscription-schema.js.map +1 -0
- package/dist/pals/activity/subscription-store.d.ts +25 -0
- package/dist/pals/activity/subscription-store.d.ts.map +1 -0
- package/dist/pals/activity/subscription-store.js +152 -0
- package/dist/pals/activity/subscription-store.js.map +1 -0
- package/dist/pals/activity/subscription-types.d.ts +42 -0
- package/dist/pals/activity/subscription-types.d.ts.map +1 -0
- package/dist/pals/activity/subscription-types.js +2 -0
- package/dist/pals/activity/subscription-types.js.map +1 -0
- package/dist/pals/activity/subscriptions.d.ts +32 -0
- package/dist/pals/activity/subscriptions.d.ts.map +1 -0
- package/dist/pals/activity/subscriptions.js +151 -0
- package/dist/pals/activity/subscriptions.js.map +1 -0
- package/dist/pals/activity/types.d.ts +77 -0
- package/dist/pals/activity/types.d.ts.map +1 -0
- package/dist/pals/activity/types.js +2 -0
- package/dist/pals/activity/types.js.map +1 -0
- package/dist/pals/channels/ingress.d.ts +9 -0
- package/dist/pals/channels/ingress.d.ts.map +1 -0
- package/dist/pals/channels/ingress.js +131 -0
- package/dist/pals/channels/ingress.js.map +1 -0
- package/dist/pals/channels/routes.d.ts +20 -0
- package/dist/pals/channels/routes.d.ts.map +1 -0
- package/dist/pals/channels/routes.js +111 -0
- package/dist/pals/channels/routes.js.map +1 -0
- package/dist/pals/channels/routing.d.ts +37 -0
- package/dist/pals/channels/routing.d.ts.map +1 -0
- package/dist/pals/channels/routing.js +150 -0
- package/dist/pals/channels/routing.js.map +1 -0
- package/dist/pals/channels/schema.d.ts +234 -0
- package/dist/pals/channels/schema.d.ts.map +1 -0
- package/dist/pals/channels/schema.js +94 -0
- package/dist/pals/channels/schema.js.map +1 -0
- package/dist/pals/channels/types.d.ts +115 -0
- package/dist/pals/channels/types.d.ts.map +1 -0
- package/dist/pals/channels/types.js +2 -0
- package/dist/pals/channels/types.js.map +1 -0
- package/dist/pals/communication/broker.d.ts +8 -0
- package/dist/pals/communication/broker.d.ts.map +1 -0
- package/dist/pals/communication/broker.js +121 -0
- package/dist/pals/communication/broker.js.map +1 -0
- package/dist/pals/communication/dispatch.d.ts +4 -0
- package/dist/pals/communication/dispatch.d.ts.map +1 -0
- package/dist/pals/communication/dispatch.js +57 -0
- package/dist/pals/communication/dispatch.js.map +1 -0
- package/dist/pals/communication/inbound.d.ts +9 -0
- package/dist/pals/communication/inbound.d.ts.map +1 -0
- package/dist/pals/communication/inbound.js +155 -0
- package/dist/pals/communication/inbound.js.map +1 -0
- package/dist/pals/communication/ingress-dispatch.d.ts +5 -0
- package/dist/pals/communication/ingress-dispatch.d.ts.map +1 -0
- package/dist/pals/communication/ingress-dispatch.js +51 -0
- package/dist/pals/communication/ingress-dispatch.js.map +1 -0
- package/dist/pals/communication/ingress-inbound.d.ts +9 -0
- package/dist/pals/communication/ingress-inbound.d.ts.map +1 -0
- package/dist/pals/communication/ingress-inbound.js +222 -0
- package/dist/pals/communication/ingress-inbound.js.map +1 -0
- package/dist/pals/communication/ingress-schema.d.ts +7829 -0
- package/dist/pals/communication/ingress-schema.d.ts.map +1 -0
- package/dist/pals/communication/ingress-schema.js +479 -0
- package/dist/pals/communication/ingress-schema.js.map +1 -0
- package/dist/pals/communication/ingress-types.d.ts +187 -0
- package/dist/pals/communication/ingress-types.d.ts.map +1 -0
- package/dist/pals/communication/ingress-types.js +73 -0
- package/dist/pals/communication/ingress-types.js.map +1 -0
- package/dist/pals/communication/operator.d.ts +75 -0
- package/dist/pals/communication/operator.d.ts.map +1 -0
- package/dist/pals/communication/operator.js +217 -0
- package/dist/pals/communication/operator.js.map +1 -0
- package/dist/pals/communication/policy.d.ts +41 -0
- package/dist/pals/communication/policy.d.ts.map +1 -0
- package/dist/pals/communication/policy.js +138 -0
- package/dist/pals/communication/policy.js.map +1 -0
- package/dist/pals/communication/schema.d.ts +2000 -0
- package/dist/pals/communication/schema.d.ts.map +1 -0
- package/dist/pals/communication/schema.js +170 -0
- package/dist/pals/communication/schema.js.map +1 -0
- package/dist/pals/communication/store.d.ts +61 -0
- package/dist/pals/communication/store.d.ts.map +1 -0
- package/dist/pals/communication/store.js +450 -0
- package/dist/pals/communication/store.js.map +1 -0
- package/dist/pals/communication/tools.d.ts +23 -0
- package/dist/pals/communication/tools.d.ts.map +1 -0
- package/dist/pals/communication/tools.js +107 -0
- package/dist/pals/communication/tools.js.map +1 -0
- package/dist/pals/communication/types.d.ts +168 -0
- package/dist/pals/communication/types.d.ts.map +1 -0
- package/dist/pals/communication/types.js +24 -0
- package/dist/pals/communication/types.js.map +1 -0
- package/dist/pals/communication/verify.d.ts +22 -0
- package/dist/pals/communication/verify.d.ts.map +1 -0
- package/dist/pals/communication/verify.js +142 -0
- package/dist/pals/communication/verify.js.map +1 -0
- package/dist/pals/lifecycle.d.ts +37 -0
- package/dist/pals/lifecycle.d.ts.map +1 -0
- package/dist/pals/lifecycle.js +22 -0
- package/dist/pals/lifecycle.js.map +1 -0
- package/dist/pals/prompt.d.ts +30 -0
- package/dist/pals/prompt.d.ts.map +1 -0
- package/dist/pals/prompt.js +65 -0
- package/dist/pals/prompt.js.map +1 -0
- package/dist/pals/reference-images.d.ts +44 -0
- package/dist/pals/reference-images.d.ts.map +1 -0
- package/dist/pals/reference-images.js +248 -0
- package/dist/pals/reference-images.js.map +1 -0
- package/dist/pals/runtime.d.ts +46 -0
- package/dist/pals/runtime.d.ts.map +1 -0
- package/dist/pals/runtime.js +624 -0
- package/dist/pals/runtime.js.map +1 -0
- package/dist/pals/store.d.ts +26 -0
- package/dist/pals/store.d.ts.map +1 -0
- package/dist/pals/store.js +334 -0
- package/dist/pals/store.js.map +1 -0
- package/dist/pals/types.d.ts +145 -0
- package/dist/pals/types.d.ts.map +1 -0
- package/dist/pals/types.js +2 -0
- package/dist/pals/types.js.map +1 -0
- package/dist/peers/envelope.js +1 -1
- package/dist/peers/envelope.js.map +1 -1
- package/dist/peers/protocol.d.ts +83 -83
- package/dist/peers/record.d.ts +10 -10
- package/dist/plugin/shell-hook.d.ts.map +1 -1
- package/dist/plugin/shell-hook.js +7 -2
- package/dist/plugin/shell-hook.js.map +1 -1
- package/dist/process/kill-tree.d.ts.map +1 -1
- package/dist/process/kill-tree.js +9 -1
- package/dist/process/kill-tree.js.map +1 -1
- package/dist/provider/errors.d.ts +19 -0
- package/dist/provider/errors.d.ts.map +1 -1
- package/dist/provider/errors.js +123 -2
- package/dist/provider/errors.js.map +1 -1
- package/dist/provider/strict-schema.d.ts +28 -0
- package/dist/provider/strict-schema.d.ts.map +1 -1
- package/dist/provider/strict-schema.js +86 -0
- package/dist/provider/strict-schema.js.map +1 -1
- package/dist/public-runtime.d.ts +42 -14
- package/dist/public-runtime.d.ts.map +1 -1
- package/dist/public-runtime.js +36 -8
- package/dist/public-runtime.js.map +1 -1
- package/dist/public-tools.d.ts +8 -3
- package/dist/public-tools.d.ts.map +1 -1
- package/dist/public-tools.js +8 -3
- package/dist/public-tools.js.map +1 -1
- package/dist/public-types.d.ts +27 -7
- package/dist/public-types.d.ts.map +1 -1
- package/dist/registry/tool/presentation.d.ts +1 -0
- package/dist/registry/tool/presentation.d.ts.map +1 -1
- package/dist/registry/tool/presentation.js +9 -7
- package/dist/registry/tool/presentation.js.map +1 -1
- package/dist/runtime/harness-session/index.d.ts +5 -0
- package/dist/runtime/harness-session/index.d.ts.map +1 -0
- package/dist/runtime/harness-session/index.js +928 -0
- package/dist/runtime/harness-session/index.js.map +1 -0
- package/dist/runtime/harness-session/journal.d.ts +37 -0
- package/dist/runtime/harness-session/journal.d.ts.map +1 -0
- package/dist/runtime/harness-session/journal.js +177 -0
- package/dist/runtime/harness-session/journal.js.map +1 -0
- package/dist/runtime/harness-session/saved-view.d.ts +8 -0
- package/dist/runtime/harness-session/saved-view.d.ts.map +1 -0
- package/dist/runtime/harness-session/saved-view.js +112 -0
- package/dist/runtime/harness-session/saved-view.js.map +1 -0
- package/dist/runtime/jobs/awaited-jobs.d.ts +2 -1
- package/dist/runtime/jobs/awaited-jobs.d.ts.map +1 -1
- package/dist/runtime/jobs/awaited-jobs.js +2 -1
- package/dist/runtime/jobs/awaited-jobs.js.map +1 -1
- package/dist/runtime/jobs/registry.d.ts +56 -1
- package/dist/runtime/jobs/registry.d.ts.map +1 -1
- package/dist/runtime/jobs/registry.js +351 -34
- package/dist/runtime/jobs/registry.js.map +1 -1
- package/dist/runtime/query/abandon-turn.d.ts +12 -1
- package/dist/runtime/query/abandon-turn.d.ts.map +1 -1
- package/dist/runtime/query/abandon-turn.js +3 -1
- package/dist/runtime/query/abandon-turn.js.map +1 -1
- package/dist/runtime/query/checkpoint.d.ts +4 -0
- package/dist/runtime/query/checkpoint.d.ts.map +1 -1
- package/dist/runtime/query/checkpoint.js +10 -0
- package/dist/runtime/query/checkpoint.js.map +1 -1
- package/dist/runtime/query/durable-inbound.d.ts +5 -0
- package/dist/runtime/query/durable-inbound.d.ts.map +1 -0
- package/dist/runtime/query/durable-inbound.js +89 -0
- package/dist/runtime/query/durable-inbound.js.map +1 -0
- package/dist/runtime/query/events.d.ts +4 -0
- package/dist/runtime/query/events.d.ts.map +1 -1
- package/dist/runtime/query/events.js +22 -5
- package/dist/runtime/query/events.js.map +1 -1
- package/dist/runtime/query/executor/tool-call-admission.d.ts +5 -1
- package/dist/runtime/query/executor/tool-call-admission.d.ts.map +1 -1
- package/dist/runtime/query/executor/tool-call-admission.js +85 -13
- package/dist/runtime/query/executor/tool-call-admission.js.map +1 -1
- package/dist/runtime/query/executor.d.ts +41 -18
- package/dist/runtime/query/executor.d.ts.map +1 -1
- package/dist/runtime/query/executor.js +227 -114
- package/dist/runtime/query/executor.js.map +1 -1
- package/dist/runtime/query/index.d.ts +3 -0
- package/dist/runtime/query/index.d.ts.map +1 -1
- package/dist/runtime/query/index.js +21 -4
- package/dist/runtime/query/index.js.map +1 -1
- package/dist/runtime/query/iteration/index.d.ts +18 -6
- package/dist/runtime/query/iteration/index.d.ts.map +1 -1
- package/dist/runtime/query/iteration/index.js +144 -67
- package/dist/runtime/query/iteration/index.js.map +1 -1
- package/dist/runtime/query/iteration/outstanding-work.d.ts +9 -5
- package/dist/runtime/query/iteration/outstanding-work.d.ts.map +1 -1
- package/dist/runtime/query/iteration/outstanding-work.js +61 -6
- package/dist/runtime/query/iteration/outstanding-work.js.map +1 -1
- package/dist/runtime/query/iteration/phases/context.d.ts +4 -0
- package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/context.js.map +1 -1
- package/dist/runtime/query/iteration/phases/tool-review.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/tool-review.js +99 -16
- package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
- package/dist/runtime/query/observation-context.d.ts +2 -2
- package/dist/runtime/query/observation-context.d.ts.map +1 -1
- package/dist/runtime/query/observation-context.js +20 -13
- package/dist/runtime/query/observation-context.js.map +1 -1
- package/dist/runtime/query/prepare-turn.js +2 -2
- package/dist/runtime/query/prepare-turn.js.map +1 -1
- package/dist/runtime/query/prompt-cache.d.ts +1 -0
- package/dist/runtime/query/prompt-cache.d.ts.map +1 -1
- package/dist/runtime/query/prompt-cache.js +2 -0
- package/dist/runtime/query/prompt-cache.js.map +1 -1
- package/dist/runtime/query/prompt.d.ts +2 -0
- package/dist/runtime/query/prompt.d.ts.map +1 -1
- package/dist/runtime/query/prompt.js +23 -1
- package/dist/runtime/query/prompt.js.map +1 -1
- package/dist/runtime/query/repeat-call.d.ts +12 -3
- package/dist/runtime/query/repeat-call.d.ts.map +1 -1
- package/dist/runtime/query/repeat-call.js +33 -10
- package/dist/runtime/query/repeat-call.js.map +1 -1
- package/dist/runtime/query/resume-pending.d.ts +5 -6
- package/dist/runtime/query/resume-pending.d.ts.map +1 -1
- package/dist/runtime/query/resume-pending.js +30 -3
- package/dist/runtime/query/resume-pending.js.map +1 -1
- package/dist/runtime/query/resume-session.js +1 -1
- package/dist/runtime/query/resume-session.js.map +1 -1
- package/dist/runtime/query/review-policy.d.ts +8 -1
- package/dist/runtime/query/review-policy.d.ts.map +1 -1
- package/dist/runtime/query/review-policy.js +6 -0
- package/dist/runtime/query/review-policy.js.map +1 -1
- package/dist/runtime/query/saved-presentation.d.ts +13 -0
- package/dist/runtime/query/saved-presentation.d.ts.map +1 -0
- package/dist/runtime/query/saved-presentation.js +63 -0
- package/dist/runtime/query/saved-presentation.js.map +1 -0
- package/dist/runtime/query/steering.d.ts +6 -9
- package/dist/runtime/query/steering.d.ts.map +1 -1
- package/dist/runtime/query/steering.js.map +1 -1
- package/dist/runtime/query/tool-executions.d.ts +7 -3
- package/dist/runtime/query/tool-executions.d.ts.map +1 -1
- package/dist/runtime/query/tool-executions.js +89 -9
- package/dist/runtime/query/tool-executions.js.map +1 -1
- package/dist/runtime/query/tooling.d.ts +3 -1
- package/dist/runtime/query/tooling.d.ts.map +1 -1
- package/dist/runtime/query/tooling.js +3 -0
- package/dist/runtime/query/tooling.js.map +1 -1
- package/dist/scheduler/completion-inbox.d.ts +25 -1
- package/dist/scheduler/completion-inbox.d.ts.map +1 -1
- package/dist/scheduler/completion-inbox.js +102 -8
- package/dist/scheduler/completion-inbox.js.map +1 -1
- package/dist/scheduler/delegating.d.ts.map +1 -1
- package/dist/scheduler/delegating.js +5 -0
- package/dist/scheduler/delegating.js.map +1 -1
- package/dist/scheduler/local.d.ts.map +1 -1
- package/dist/scheduler/local.js +2 -0
- package/dist/scheduler/local.js.map +1 -1
- package/dist/session/summary/materialize.d.ts +10 -6
- package/dist/session/summary/materialize.d.ts.map +1 -1
- package/dist/session/summary/materialize.js +41 -8
- package/dist/session/summary/materialize.js.map +1 -1
- package/dist/store/budget/ledger.d.ts +9 -0
- package/dist/store/budget/ledger.d.ts.map +1 -1
- package/dist/store/budget/ledger.js +58 -6
- package/dist/store/budget/ledger.js.map +1 -1
- package/dist/store/evidence/index-page.d.ts +12 -12
- package/dist/store/evidence/source-text.d.ts +4 -4
- package/dist/store/session/disk.d.ts +9 -4
- package/dist/store/session/disk.d.ts.map +1 -1
- package/dist/store/session/disk.js +57 -11
- package/dist/store/session/disk.js.map +1 -1
- package/dist/store/session/memory.d.ts +5 -3
- package/dist/store/session/memory.d.ts.map +1 -1
- package/dist/store/session/memory.js +24 -7
- package/dist/store/session/memory.js.map +1 -1
- package/dist/store/session-log/core.d.ts +26 -6
- package/dist/store/session-log/core.d.ts.map +1 -1
- package/dist/store/session-log/core.js +61 -8
- package/dist/store/session-log/core.js.map +1 -1
- package/dist/store/session-log/disk.d.ts +2 -2
- package/dist/store/session-log/disk.d.ts.map +1 -1
- package/dist/store/session-log/disk.js +1 -0
- package/dist/store/session-log/disk.js.map +1 -1
- package/dist/store/session-log/fold.d.ts +7 -0
- package/dist/store/session-log/fold.d.ts.map +1 -1
- package/dist/store/session-log/fold.js +21 -0
- package/dist/store/session-log/fold.js.map +1 -1
- package/dist/store/session-log/index.d.ts +5 -3
- package/dist/store/session-log/index.d.ts.map +1 -1
- package/dist/store/session-log/index.js +3 -1
- package/dist/store/session-log/index.js.map +1 -1
- package/dist/store/session-log/memory.d.ts +1 -1
- package/dist/store/session-log/memory.d.ts.map +1 -1
- package/dist/store/session-log/memory.js +1 -0
- package/dist/store/session-log/memory.js.map +1 -1
- package/dist/store/session-log/spill.d.ts +10 -3
- package/dist/store/session-log/spill.d.ts.map +1 -1
- package/dist/store/session-log/spill.js +70 -5
- package/dist/store/session-log/spill.js.map +1 -1
- package/dist/store/session-log/structured-result.d.ts +21 -0
- package/dist/store/session-log/structured-result.d.ts.map +1 -0
- package/dist/store/session-log/structured-result.js +67 -0
- package/dist/store/session-log/structured-result.js.map +1 -0
- package/dist/store/task/disk.d.ts +11 -0
- package/dist/store/task/disk.d.ts.map +1 -1
- package/dist/store/task/disk.js +41 -2
- package/dist/store/task/disk.js.map +1 -1
- package/dist/store/task/memory.d.ts.map +1 -1
- package/dist/store/task/memory.js +15 -3
- package/dist/store/task/memory.js.map +1 -1
- package/dist/tools/admit-facts.d.ts +13 -0
- package/dist/tools/admit-facts.d.ts.map +1 -0
- package/dist/tools/admit-facts.js +142 -0
- package/dist/tools/admit-facts.js.map +1 -0
- package/dist/tools/builtins/bash.d.ts +4 -1
- package/dist/tools/builtins/bash.d.ts.map +1 -1
- package/dist/tools/builtins/bash.js +108 -22
- package/dist/tools/builtins/bash.js.map +1 -1
- package/dist/tools/builtins/browser.d.ts +10 -10
- package/dist/tools/builtins/computer-use.d.ts +90 -90
- package/dist/tools/builtins/edit.d.ts +17 -0
- package/dist/tools/builtins/edit.d.ts.map +1 -1
- package/dist/tools/builtins/edit.js +46 -1
- package/dist/tools/builtins/edit.js.map +1 -1
- package/dist/tools/builtins/file-write-result.d.ts.map +1 -1
- package/dist/tools/builtins/file-write-result.js +13 -0
- package/dist/tools/builtins/file-write-result.js.map +1 -1
- package/dist/tools/builtins/glob.d.ts.map +1 -1
- package/dist/tools/builtins/glob.js +12 -0
- package/dist/tools/builtins/glob.js.map +1 -1
- package/dist/tools/builtins/grep.d.ts.map +1 -1
- package/dist/tools/builtins/grep.js +14 -0
- package/dist/tools/builtins/grep.js.map +1 -1
- package/dist/tools/builtins/index.d.ts +2 -0
- package/dist/tools/builtins/index.d.ts.map +1 -1
- package/dist/tools/builtins/index.js +1 -0
- package/dist/tools/builtins/index.js.map +1 -1
- package/dist/tools/builtins/job.d.ts.map +1 -1
- package/dist/tools/builtins/job.js +4 -1
- package/dist/tools/builtins/job.js.map +1 -1
- package/dist/tools/builtins/lsp.d.ts +2 -2
- package/dist/tools/builtins/read-file.d.ts.map +1 -1
- package/dist/tools/builtins/read-file.js +49 -0
- package/dist/tools/builtins/read-file.js.map +1 -1
- package/dist/tools/builtins/view-image.d.ts +24 -0
- package/dist/tools/builtins/view-image.d.ts.map +1 -0
- package/dist/tools/builtins/view-image.js +385 -0
- package/dist/tools/builtins/view-image.js.map +1 -0
- package/dist/tools/builtins/wait-for-job-bounds.d.ts +2 -0
- package/dist/tools/builtins/wait-for-job-bounds.d.ts.map +1 -1
- package/dist/tools/builtins/wait-for-job-bounds.js +1 -0
- package/dist/tools/builtins/wait-for-job-bounds.js.map +1 -1
- package/dist/tools/builtins/wait-for-job.d.ts +2 -0
- package/dist/tools/builtins/wait-for-job.d.ts.map +1 -1
- package/dist/tools/builtins/wait-for-job.js +104 -6
- package/dist/tools/builtins/wait-for-job.js.map +1 -1
- package/dist/tools/builtins/write-file.d.ts.map +1 -1
- package/dist/tools/builtins/write-file.js +1 -0
- package/dist/tools/builtins/write-file.js.map +1 -1
- package/dist/tools/command-shell.d.ts +37 -2
- package/dist/tools/command-shell.d.ts.map +1 -1
- package/dist/tools/command-shell.js +100 -3
- package/dist/tools/command-shell.js.map +1 -1
- package/dist/tools/coordinator/agent.d.ts +9 -19
- package/dist/tools/coordinator/agent.d.ts.map +1 -1
- package/dist/tools/coordinator/agent.js.map +1 -1
- package/dist/tools/coordinator/index.d.ts.map +1 -1
- package/dist/tools/coordinator/index.js +127 -67
- package/dist/tools/coordinator/index.js.map +1 -1
- package/dist/tools/coordinator/wait-with-idle-bound.d.ts +2 -0
- package/dist/tools/coordinator/wait-with-idle-bound.d.ts.map +1 -1
- package/dist/tools/coordinator/wait-with-idle-bound.js +1 -1
- package/dist/tools/coordinator/wait-with-idle-bound.js.map +1 -1
- package/dist/tools/defineTool.d.ts.map +1 -1
- package/dist/tools/defineTool.js +4 -0
- package/dist/tools/defineTool.js.map +1 -1
- package/dist/tools/failure-facts.d.ts +8 -0
- package/dist/tools/failure-facts.d.ts.map +1 -0
- package/dist/tools/failure-facts.js +24 -0
- package/dist/tools/failure-facts.js.map +1 -0
- package/dist/tools/host-output.d.ts +24 -0
- package/dist/tools/host-output.d.ts.map +1 -0
- package/dist/tools/host-output.js +117 -0
- package/dist/tools/host-output.js.map +1 -0
- package/dist/tools/oem-code-pages.d.ts +8 -0
- package/dist/tools/oem-code-pages.d.ts.map +1 -0
- package/dist/tools/oem-code-pages.js +23 -0
- package/dist/tools/oem-code-pages.js.map +1 -0
- package/dist/tools/schedules/schedule-tool.d.ts.map +1 -1
- package/dist/tools/schedules/schedule-tool.js +35 -6
- package/dist/tools/schedules/schedule-tool.js.map +1 -1
- package/dist/tools/schedules/types.d.ts +23 -3
- package/dist/tools/schedules/types.d.ts.map +1 -1
- package/dist/tools/task/list.d.ts.map +1 -1
- package/dist/tools/task/list.js +14 -6
- package/dist/tools/task/list.js.map +1 -1
- package/dist/tools/task/present.d.ts.map +1 -1
- package/dist/tools/task/present.js +26 -6
- package/dist/tools/task/present.js.map +1 -1
- package/dist/tools/task/update.d.ts.map +1 -1
- package/dist/tools/task/update.js +12 -5
- package/dist/tools/task/update.js.map +1 -1
- package/dist/tools/text-window.d.ts +19 -0
- package/dist/tools/text-window.d.ts.map +1 -0
- package/dist/tools/text-window.js +83 -0
- package/dist/tools/text-window.js.map +1 -0
- package/dist/toolsets/manager.d.ts +11 -0
- package/dist/toolsets/manager.d.ts.map +1 -1
- package/dist/toolsets/manager.js +45 -1
- package/dist/toolsets/manager.js.map +1 -1
- package/dist/types/acp/index.d.ts +137 -1
- package/dist/types/acp/index.d.ts.map +1 -1
- package/dist/types/agent/base.d.ts +3 -0
- package/dist/types/agent/base.d.ts.map +1 -1
- package/dist/types/agent/manager.d.ts +8 -23
- package/dist/types/agent/manager.d.ts.map +1 -1
- package/dist/types/agent/scheduler.d.ts +10 -1
- package/dist/types/agent/scheduler.d.ts.map +1 -1
- package/dist/types/agent/task.d.ts +4 -0
- package/dist/types/agent/task.d.ts.map +1 -1
- package/dist/types/authorization/index.d.ts +30 -30
- package/dist/types/connector/mcp.d.ts +7 -0
- package/dist/types/connector/mcp.d.ts.map +1 -1
- package/dist/types/errors/catalog.d.ts.map +1 -1
- package/dist/types/errors/catalog.js +4 -2
- package/dist/types/errors/catalog.js.map +1 -1
- package/dist/types/harness/schema.d.ts +354 -0
- package/dist/types/harness/schema.d.ts.map +1 -0
- package/dist/types/harness/schema.js +203 -0
- package/dist/types/harness/schema.js.map +1 -0
- package/dist/types/harness/session.d.ts +278 -0
- package/dist/types/harness/session.d.ts.map +1 -0
- package/dist/types/harness/session.js +2 -0
- package/dist/types/harness/session.js.map +1 -0
- package/dist/types/hitl/index.d.ts +12 -0
- package/dist/types/hitl/index.d.ts.map +1 -1
- package/dist/types/hitl/index.js.map +1 -1
- package/dist/types/job/index.d.ts +47 -0
- package/dist/types/job/index.d.ts.map +1 -0
- package/dist/types/job/index.js +2 -0
- package/dist/types/job/index.js.map +1 -0
- package/dist/types/message/inbound-delivery.d.ts +44 -0
- package/dist/types/message/inbound-delivery.d.ts.map +1 -0
- package/dist/types/message/inbound-delivery.js +14 -0
- package/dist/types/message/inbound-delivery.js.map +1 -0
- package/dist/types/message/index.d.ts +4 -1
- package/dist/types/message/index.d.ts.map +1 -1
- package/dist/types/message/index.js +5 -1
- package/dist/types/message/index.js.map +1 -1
- package/dist/types/plugin/index.d.ts +6 -6
- package/dist/types/sandbox/index.d.ts +39 -2
- package/dist/types/sandbox/index.d.ts.map +1 -1
- package/dist/types/sandbox/index.js.map +1 -1
- package/dist/types/session/checkpoint.d.ts +24 -17
- package/dist/types/session/checkpoint.d.ts.map +1 -1
- package/dist/types/session/checkpoint.js +1 -0
- package/dist/types/session/checkpoint.js.map +1 -1
- package/dist/types/session/events.d.ts +23 -1
- package/dist/types/session/events.d.ts.map +1 -1
- package/dist/types/session/events.js.map +1 -1
- package/dist/types/session/records.d.ts +1514 -565
- package/dist/types/session/records.d.ts.map +1 -1
- package/dist/types/session/records.js +89 -1
- package/dist/types/session/records.js.map +1 -1
- package/dist/types/session/step.d.ts +2 -0
- package/dist/types/session/step.d.ts.map +1 -1
- package/dist/types/session/step.js.map +1 -1
- package/dist/types/session/store.d.ts +19 -10
- package/dist/types/session/store.d.ts.map +1 -1
- package/dist/types/session/tool-execution.d.ts +6 -0
- package/dist/types/session/tool-execution.d.ts.map +1 -1
- package/dist/types/structured-output/index.d.ts +12 -2
- package/dist/types/structured-output/index.d.ts.map +1 -1
- package/dist/types/summary/ref.d.ts +3 -1
- package/dist/types/summary/ref.d.ts.map +1 -1
- package/dist/types/tool/index.d.ts +32 -4
- package/dist/types/tool/index.d.ts.map +1 -1
- package/dist/types/tool/index.js.map +1 -1
- package/dist/types/tool/presentation.d.ts +106 -0
- package/dist/types/tool/presentation.d.ts.map +1 -1
- package/dist/utils/json-snapshot.d.ts +6 -2
- package/dist/utils/json-snapshot.d.ts.map +1 -1
- package/dist/utils/json-snapshot.js +19 -9
- package/dist/utils/json-snapshot.js.map +1 -1
- package/dist/utils/structured-result-json.d.ts +5 -0
- package/dist/utils/structured-result-json.d.ts.map +1 -0
- package/dist/utils/structured-result-json.js +10 -0
- package/dist/utils/structured-result-json.js.map +1 -0
- package/package.json +1 -1
- package/src/agents/QueryAgent.ts +1 -0
- package/src/agents/examples/SupervisorAgent.ts +1 -0
- package/src/agents/runAgent.ts +3 -0
- package/src/authorization/shell-lexer.ts +16 -1
- package/src/bridge/acp/permission.ts +17 -3
- package/src/bridge/acp/server.ts +271 -25
- package/src/bridge/acp/tasks.ts +23 -0
- package/src/bridge/acp/update.ts +167 -13
- package/src/connector/mcp/adapter.ts +16 -4
- package/src/connector/mcp/client.ts +6 -2
- package/src/constants/acp/index.ts +4 -0
- package/src/manager/agent/lifecycle.ts +230 -3
- package/src/manager/plan/lifecycle.ts +11 -9
- package/src/manager/session/attribution.ts +12 -2
- package/src/manager/session/streamed-message-identity.ts +21 -0
- package/src/manager/session/turn-recorder.ts +4 -3
- package/src/pals/activity/causality.ts +261 -0
- package/src/pals/activity/projection.ts +89 -0
- package/src/pals/activity/source.ts +240 -0
- package/src/pals/activity/subscription-policy.ts +230 -0
- package/src/pals/activity/subscription-schema.ts +27 -0
- package/src/pals/activity/subscription-store.ts +172 -0
- package/src/pals/activity/subscription-types.ts +48 -0
- package/src/pals/activity/subscriptions.ts +209 -0
- package/src/pals/activity/types.ts +108 -0
- package/src/pals/channels/ingress.ts +153 -0
- package/src/pals/channels/routes.ts +118 -0
- package/src/pals/channels/routing.ts +197 -0
- package/src/pals/channels/schema.ts +108 -0
- package/src/pals/channels/types.ts +156 -0
- package/src/pals/communication/broker.ts +131 -0
- package/src/pals/communication/dispatch.ts +66 -0
- package/src/pals/communication/inbound.ts +193 -0
- package/src/pals/communication/ingress-dispatch.ts +63 -0
- package/src/pals/communication/ingress-inbound.ts +269 -0
- package/src/pals/communication/ingress-schema.ts +526 -0
- package/src/pals/communication/ingress-types.ts +336 -0
- package/src/pals/communication/operator.ts +315 -0
- package/src/pals/communication/policy.ts +174 -0
- package/src/pals/communication/schema.ts +173 -0
- package/src/pals/communication/store.ts +577 -0
- package/src/pals/communication/tools.ts +139 -0
- package/src/pals/communication/types.ts +227 -0
- package/src/pals/communication/verify.ts +220 -0
- package/src/pals/lifecycle.ts +54 -0
- package/src/pals/prompt.ts +101 -0
- package/src/pals/reference-images.ts +322 -0
- package/src/pals/runtime.ts +670 -0
- package/src/pals/store.ts +369 -0
- package/src/pals/types.ts +157 -0
- package/src/peers/envelope.ts +1 -1
- package/src/plugin/shell-hook.ts +8 -2
- package/src/process/kill-tree.ts +10 -1
- package/src/provider/errors.ts +135 -2
- package/src/provider/strict-schema.ts +90 -0
- package/src/public-runtime.ts +118 -12
- package/src/public-tools.ts +13 -1
- package/src/public-types.ts +69 -7
- package/src/registry/tool/presentation.ts +9 -4
- package/src/runtime/harness-session/index.ts +1125 -0
- package/src/runtime/harness-session/journal.ts +209 -0
- package/src/runtime/harness-session/saved-view.ts +122 -0
- package/src/runtime/jobs/awaited-jobs.ts +2 -1
- package/src/runtime/jobs/registry.ts +397 -41
- package/src/runtime/query/abandon-turn.ts +18 -2
- package/src/runtime/query/checkpoint.ts +11 -0
- package/src/runtime/query/durable-inbound.ts +101 -0
- package/src/runtime/query/events.ts +22 -5
- package/src/runtime/query/executor/tool-call-admission.ts +125 -32
- package/src/runtime/query/executor.ts +316 -130
- package/src/runtime/query/index.ts +24 -4
- package/src/runtime/query/iteration/index.ts +218 -104
- package/src/runtime/query/iteration/outstanding-work.ts +55 -7
- package/src/runtime/query/iteration/phases/context.ts +4 -0
- package/src/runtime/query/iteration/phases/tool-review.ts +118 -21
- package/src/runtime/query/observation-context.ts +22 -16
- package/src/runtime/query/prepare-turn.ts +2 -2
- package/src/runtime/query/prompt-cache.ts +3 -0
- package/src/runtime/query/prompt.ts +32 -1
- package/src/runtime/query/repeat-call.ts +40 -10
- package/src/runtime/query/resume-pending.ts +60 -7
- package/src/runtime/query/resume-session.ts +1 -1
- package/src/runtime/query/review-policy.ts +23 -2
- package/src/runtime/query/saved-presentation.ts +70 -0
- package/src/runtime/query/steering.ts +6 -9
- package/src/runtime/query/tool-executions.ts +108 -9
- package/src/runtime/query/tooling.ts +6 -1
- package/src/scheduler/completion-inbox.ts +108 -7
- package/src/scheduler/delegating.ts +5 -0
- package/src/scheduler/local.ts +2 -0
- package/src/session/summary/materialize.ts +51 -9
- package/src/store/budget/ledger.ts +60 -5
- package/src/store/session/disk.ts +77 -10
- package/src/store/session/memory.ts +32 -7
- package/src/store/session-log/core.ts +118 -11
- package/src/store/session-log/disk.ts +9 -2
- package/src/store/session-log/fold.ts +22 -0
- package/src/store/session-log/index.ts +5 -0
- package/src/store/session-log/memory.ts +2 -1
- package/src/store/session-log/spill.ts +89 -6
- package/src/store/session-log/structured-result.ts +96 -0
- package/src/store/task/disk.ts +46 -2
- package/src/store/task/memory.ts +13 -3
- package/src/tools/admit-facts.ts +145 -0
- package/src/tools/builtins/bash.ts +132 -24
- package/src/tools/builtins/edit.ts +54 -1
- package/src/tools/builtins/file-write-result.ts +14 -0
- package/src/tools/builtins/glob.ts +12 -0
- package/src/tools/builtins/grep.ts +14 -0
- package/src/tools/builtins/index.ts +2 -0
- package/src/tools/builtins/job.ts +4 -1
- package/src/tools/builtins/read-file.ts +57 -0
- package/src/tools/builtins/view-image.ts +409 -0
- package/src/tools/builtins/wait-for-job-bounds.ts +3 -0
- package/src/tools/builtins/wait-for-job.ts +141 -32
- package/src/tools/builtins/write-file.ts +4 -2
- package/src/tools/command-shell.ts +132 -5
- package/src/tools/coordinator/agent.ts +9 -19
- package/src/tools/coordinator/index.ts +150 -75
- package/src/tools/coordinator/wait-with-idle-bound.ts +3 -1
- package/src/tools/defineTool.ts +4 -0
- package/src/tools/failure-facts.ts +24 -0
- package/src/tools/host-output.ts +136 -0
- package/src/tools/oem-code-pages.ts +22 -0
- package/src/tools/schedules/schedule-tool.ts +38 -5
- package/src/tools/schedules/types.ts +23 -3
- package/src/tools/task/list.ts +15 -7
- package/src/tools/task/present.ts +37 -7
- package/src/tools/task/update.ts +12 -5
- package/src/tools/text-window.ts +87 -0
- package/src/toolsets/manager.ts +58 -1
- package/src/types/acp/index.ts +150 -4
- package/src/types/agent/base.ts +3 -0
- package/src/types/agent/manager.ts +8 -23
- package/src/types/agent/scheduler.ts +10 -1
- package/src/types/agent/task.ts +4 -0
- package/src/types/connector/mcp.ts +7 -0
- package/src/types/errors/catalog.ts +4 -2
- package/src/types/harness/schema.ts +203 -0
- package/src/types/harness/session.ts +306 -0
- package/src/types/hitl/index.ts +17 -1
- package/src/types/job/index.ts +42 -0
- package/src/types/message/inbound-delivery.ts +63 -0
- package/src/types/message/index.ts +8 -1
- package/src/types/sandbox/index.ts +46 -0
- package/src/types/session/checkpoint.ts +4 -1
- package/src/types/session/events.ts +23 -1
- package/src/types/session/records.ts +114 -2
- package/src/types/session/step.ts +2 -0
- package/src/types/session/store.ts +23 -9
- package/src/types/session/tool-execution.ts +6 -0
- package/src/types/structured-output/index.ts +13 -2
- package/src/types/summary/ref.ts +3 -1
- package/src/types/tool/index.ts +39 -5
- package/src/types/tool/presentation.ts +121 -0
- package/src/utils/json-snapshot.ts +26 -9
- package/src/utils/structured-result-json.ts +10 -0
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto'
|
|
2
|
+
import { open } from 'node:fs/promises'
|
|
3
|
+
import { inflateSync } from 'node:zlib'
|
|
4
|
+
import { z } from 'zod'
|
|
5
|
+
import { admitMcpImageBatch } from '../../connector/mcp/image-admission.js'
|
|
6
|
+
import type { ToolContext, ToolDefinition } from '../../types/tool/index.js'
|
|
7
|
+
import { defineTool } from '../defineTool.js'
|
|
8
|
+
import { resolveWithinAnyReal, toolRoots } from '../paths.js'
|
|
9
|
+
import { STANDARD_SCREENSHOT_LIMITS, fitPng, screenshotTargetSize } from './computer-use-image.js'
|
|
10
|
+
|
|
11
|
+
// 16 MiB becomes less than the runtime's 24 MiB encoded rich-content budget.
|
|
12
|
+
// Admission is per artifact; the runtime still budgets accumulated images.
|
|
13
|
+
const MAX_BYTES = 16 * 1024 * 1024
|
|
14
|
+
const READ_CHUNK_BYTES = 1024 * 1024
|
|
15
|
+
const MAX_EDGE = 16_384
|
|
16
|
+
const MAX_PIXELS = 16_000_000
|
|
17
|
+
const PNG_SIGNATURE = Buffer.from('89504e470d0a1a0a', 'hex')
|
|
18
|
+
const JPEG_FRAME_MARKERS = new Set([
|
|
19
|
+
0xc0, 0xc1, 0xc2, 0xc3, 0xc5, 0xc6, 0xc7, 0xc9, 0xca, 0xcb, 0xcd, 0xce, 0xcf,
|
|
20
|
+
])
|
|
21
|
+
|
|
22
|
+
const inputSchema = z.object({
|
|
23
|
+
path: z.string().min(1).describe("Path to a saved PNG, JPEG or WebP image in this turn's files"),
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
/** Host admission for a model which cannot receive image tool results. */
|
|
27
|
+
export interface ViewImageToolOptions {
|
|
28
|
+
readonly unavailableReason?: string
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
interface Raster {
|
|
32
|
+
readonly mediaType: 'image/png' | 'image/jpeg' | 'image/webp'
|
|
33
|
+
readonly width: number
|
|
34
|
+
readonly height: number
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async function readBounded(
|
|
38
|
+
read: (offset: number, length: number) => Promise<Buffer>,
|
|
39
|
+
signal: AbortSignal,
|
|
40
|
+
): Promise<Buffer> {
|
|
41
|
+
const chunks: Buffer[] = []
|
|
42
|
+
let offset = 0
|
|
43
|
+
for (;;) {
|
|
44
|
+
signal.throwIfAborted()
|
|
45
|
+
const length = Math.min(READ_CHUNK_BYTES, MAX_BYTES + 1 - offset)
|
|
46
|
+
const chunk = await read(offset, length)
|
|
47
|
+
signal.throwIfAborted()
|
|
48
|
+
if (chunk.length > length)
|
|
49
|
+
throw new Error('The file backend returned more bytes than the requested bounded range.')
|
|
50
|
+
offset += chunk.length
|
|
51
|
+
if (offset > MAX_BYTES)
|
|
52
|
+
throw new Error('Image exceeds the 16 MiB inspection limit. Export a smaller image.')
|
|
53
|
+
chunks.push(chunk)
|
|
54
|
+
if (chunk.length < length) return Buffer.concat(chunks, offset)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async function readArtifact(
|
|
59
|
+
path: string,
|
|
60
|
+
context: ToolContext,
|
|
61
|
+
): Promise<{ path: string; bytes: Buffer; sandboxed: boolean }> {
|
|
62
|
+
context.abortSignal.throwIfAborted()
|
|
63
|
+
if (context.sandbox) {
|
|
64
|
+
const bytes = await context.sandbox.readFile(path, {
|
|
65
|
+
offset: 0,
|
|
66
|
+
length: MAX_BYTES + 1,
|
|
67
|
+
signal: context.abortSignal,
|
|
68
|
+
})
|
|
69
|
+
context.abortSignal.throwIfAborted()
|
|
70
|
+
if (bytes.length > MAX_BYTES)
|
|
71
|
+
throw new Error('Image exceeds the 16 MiB inspection limit. Export a smaller image.')
|
|
72
|
+
return { path, bytes, sandboxed: true }
|
|
73
|
+
}
|
|
74
|
+
const resolved = await resolveWithinAnyReal(toolRoots(context), path)
|
|
75
|
+
const file = await open(resolved, 'r')
|
|
76
|
+
try {
|
|
77
|
+
const stat = await file.stat()
|
|
78
|
+
if (!stat.isFile()) throw new Error('Image inspection requires a regular file.')
|
|
79
|
+
if (stat.size > MAX_BYTES)
|
|
80
|
+
throw new Error('Image exceeds the 16 MiB inspection limit. Export a smaller image.')
|
|
81
|
+
const bytes = await readBounded(async (offset, length) => {
|
|
82
|
+
const buffer = Buffer.allocUnsafe(length)
|
|
83
|
+
const { bytesRead } = await file.read(buffer, 0, length, offset)
|
|
84
|
+
return buffer.subarray(0, bytesRead)
|
|
85
|
+
}, context.abortSignal)
|
|
86
|
+
return { path: resolved, bytes, sandboxed: false }
|
|
87
|
+
} finally {
|
|
88
|
+
await file.close()
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function malformed(): never {
|
|
93
|
+
throw new Error('Image is malformed or truncated. Export a complete static PNG, JPEG or WebP.')
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function jpegDimensions(bytes: Buffer): Pick<Raster, 'width' | 'height'> {
|
|
97
|
+
let offset = 2
|
|
98
|
+
let inScan = false
|
|
99
|
+
let frame: Pick<Raster, 'width' | 'height'> | undefined
|
|
100
|
+
while (offset < bytes.length) {
|
|
101
|
+
if (inScan && bytes[offset] !== 0xff) {
|
|
102
|
+
offset += 1
|
|
103
|
+
continue
|
|
104
|
+
}
|
|
105
|
+
if (bytes[offset] !== 0xff) malformed()
|
|
106
|
+
while (bytes[offset] === 0xff) offset += 1
|
|
107
|
+
const marker = bytes[offset]
|
|
108
|
+
if (marker === undefined) malformed()
|
|
109
|
+
offset += 1
|
|
110
|
+
if (inScan && (marker === 0 || (marker >= 0xd0 && marker <= 0xd7))) continue
|
|
111
|
+
inScan = false
|
|
112
|
+
if (marker === 0xd9) break
|
|
113
|
+
if (marker === 0xd8 || marker === 0x01 || (marker >= 0xd0 && marker <= 0xd7)) continue
|
|
114
|
+
if (offset + 2 > bytes.length) malformed()
|
|
115
|
+
const length = bytes.readUInt16BE(offset)
|
|
116
|
+
if (length < 2 || offset + length > bytes.length) malformed()
|
|
117
|
+
if (JPEG_FRAME_MARKERS.has(marker)) {
|
|
118
|
+
if (length < 8 || frame) malformed()
|
|
119
|
+
frame = {
|
|
120
|
+
width: bytes.readUInt16BE(offset + 5),
|
|
121
|
+
height: bytes.readUInt16BE(offset + 3),
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
offset += length
|
|
125
|
+
if (marker === 0xda) inScan = true
|
|
126
|
+
}
|
|
127
|
+
return frame ?? malformed()
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function webpDimensions(bytes: Buffer): Pick<Raster, 'width' | 'height'> {
|
|
131
|
+
let offset = 12
|
|
132
|
+
let dimensions: Pick<Raster, 'width' | 'height'> | undefined
|
|
133
|
+
while (offset + 8 <= bytes.length) {
|
|
134
|
+
const type = bytes.toString('ascii', offset, offset + 4)
|
|
135
|
+
const length = bytes.readUInt32LE(offset + 4)
|
|
136
|
+
const start = offset + 8
|
|
137
|
+
if (start + length > bytes.length) malformed()
|
|
138
|
+
let current: Pick<Raster, 'width' | 'height'> | undefined
|
|
139
|
+
if (type === 'ANIM' || type === 'ANMF')
|
|
140
|
+
throw new Error('Animated WebP is unsupported. Export the required frame as a static PNG.')
|
|
141
|
+
if (type === 'VP8X' && length >= 10) {
|
|
142
|
+
current = {
|
|
143
|
+
width: bytes.readUIntLE(start + 4, 3) + 1,
|
|
144
|
+
height: bytes.readUIntLE(start + 7, 3) + 1,
|
|
145
|
+
}
|
|
146
|
+
} else if (type === 'VP8L' && length >= 5 && bytes[start] === 0x2f) {
|
|
147
|
+
const packed = bytes.readUInt32LE(start + 1)
|
|
148
|
+
current = {
|
|
149
|
+
width: (packed & 0x3fff) + 1,
|
|
150
|
+
height: ((packed >>> 14) & 0x3fff) + 1,
|
|
151
|
+
}
|
|
152
|
+
} else if (type === 'VP8 ' && length >= 10) {
|
|
153
|
+
current = {
|
|
154
|
+
width: bytes.readUInt16LE(start + 6) & 0x3fff,
|
|
155
|
+
height: bytes.readUInt16LE(start + 8) & 0x3fff,
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
if (current) {
|
|
159
|
+
if (
|
|
160
|
+
dimensions &&
|
|
161
|
+
(dimensions.width !== current.width || dimensions.height !== current.height)
|
|
162
|
+
)
|
|
163
|
+
malformed()
|
|
164
|
+
dimensions = current
|
|
165
|
+
}
|
|
166
|
+
offset = start + length + (length & 1)
|
|
167
|
+
}
|
|
168
|
+
return dimensions ?? malformed()
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function describeRaster(bytes: Buffer): Raster {
|
|
172
|
+
let raster: Raster
|
|
173
|
+
if (bytes.subarray(0, 8).equals(PNG_SIGNATURE)) {
|
|
174
|
+
if (bytes.length < 33) malformed()
|
|
175
|
+
raster = {
|
|
176
|
+
mediaType: 'image/png',
|
|
177
|
+
width: bytes.readUInt32BE(16),
|
|
178
|
+
height: bytes.readUInt32BE(20),
|
|
179
|
+
}
|
|
180
|
+
} else if (bytes[0] === 0xff && bytes[1] === 0xd8) {
|
|
181
|
+
raster = { mediaType: 'image/jpeg', ...jpegDimensions(bytes) }
|
|
182
|
+
} else if (
|
|
183
|
+
bytes.toString('ascii', 0, 4) === 'RIFF' &&
|
|
184
|
+
bytes.toString('ascii', 8, 12) === 'WEBP'
|
|
185
|
+
) {
|
|
186
|
+
raster = { mediaType: 'image/webp', ...webpDimensions(bytes) }
|
|
187
|
+
} else {
|
|
188
|
+
throw new Error(
|
|
189
|
+
'Unsupported image bytes. Export a static PNG, JPEG or WebP; renaming the file does not convert it.',
|
|
190
|
+
)
|
|
191
|
+
}
|
|
192
|
+
if (
|
|
193
|
+
raster.width < 1 ||
|
|
194
|
+
raster.height < 1 ||
|
|
195
|
+
raster.width > MAX_EDGE ||
|
|
196
|
+
raster.height > MAX_EDGE ||
|
|
197
|
+
raster.width * raster.height > MAX_PIXELS
|
|
198
|
+
)
|
|
199
|
+
throw new Error(
|
|
200
|
+
'Image dimensions exceed the inspection limit (16,384 pixels per edge, 16 million pixels total). Export a smaller image.',
|
|
201
|
+
)
|
|
202
|
+
return raster
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/** Validate bounded pixel data without inflating ancillary metadata. */
|
|
206
|
+
async function validatedPng(bytes: Buffer, raster: Raster): Promise<Buffer> {
|
|
207
|
+
const depth = bytes[24] ?? 0
|
|
208
|
+
const colour = bytes[25] ?? -1
|
|
209
|
+
const channels = ({ 0: 1, 2: 3, 3: 1, 4: 2, 6: 4 } as Record<number, number>)[colour]
|
|
210
|
+
const allowedDepths = colour === 0 ? [1, 2, 4, 8, 16] : colour === 3 ? [1, 2, 4, 8] : [8, 16]
|
|
211
|
+
if (
|
|
212
|
+
!channels ||
|
|
213
|
+
!allowedDepths.includes(depth) ||
|
|
214
|
+
bytes[26] !== 0 ||
|
|
215
|
+
bytes[27] !== 0 ||
|
|
216
|
+
(bytes[28] !== 0 && bytes[28] !== 1)
|
|
217
|
+
)
|
|
218
|
+
malformed()
|
|
219
|
+
// fast-png's Adam7 reader lays out sub-byte pixels as whole bytes. Do not
|
|
220
|
+
// return a success observation whose unpacked pixels differ from the file.
|
|
221
|
+
if (bytes[28] === 1 && depth < 8)
|
|
222
|
+
throw new Error(
|
|
223
|
+
'Interlaced PNGs below 8 bits per sample are unsupported by this decoder. Export a non-interlaced or 8-bit PNG and inspect that file.',
|
|
224
|
+
)
|
|
225
|
+
const passes =
|
|
226
|
+
bytes[28] === 1
|
|
227
|
+
? [
|
|
228
|
+
[0, 0, 8, 8],
|
|
229
|
+
[4, 0, 8, 8],
|
|
230
|
+
[0, 4, 4, 8],
|
|
231
|
+
[2, 0, 4, 4],
|
|
232
|
+
[0, 2, 2, 4],
|
|
233
|
+
[1, 0, 2, 2],
|
|
234
|
+
[0, 1, 1, 2],
|
|
235
|
+
]
|
|
236
|
+
: [[0, 0, 1, 1]]
|
|
237
|
+
let expected = 0
|
|
238
|
+
for (const [x = 0, y = 0, dx = 1, dy = 1] of passes) {
|
|
239
|
+
const width = Math.max(0, Math.ceil((raster.width - x) / dx))
|
|
240
|
+
const height = Math.max(0, Math.ceil((raster.height - y) / dy))
|
|
241
|
+
if (width > 0 && height > 0)
|
|
242
|
+
expected += (Math.ceil((width * channels * depth) / 8) + 1) * height
|
|
243
|
+
}
|
|
244
|
+
const chunks: Buffer[] = [PNG_SIGNATURE]
|
|
245
|
+
const compressed: Buffer[] = []
|
|
246
|
+
let offset = 8
|
|
247
|
+
while (offset + 12 <= bytes.length) {
|
|
248
|
+
const length = bytes.readUInt32BE(offset)
|
|
249
|
+
const type = bytes.toString('ascii', offset + 4, offset + 8)
|
|
250
|
+
const end = offset + length + 12
|
|
251
|
+
if (end > bytes.length) malformed()
|
|
252
|
+
if (type === 'acTL' || type === 'fcTL' || type === 'fdAT')
|
|
253
|
+
throw new Error('Animated PNG is unsupported. Export the required frame as a static PNG.')
|
|
254
|
+
if (type === 'IDAT') compressed.push(bytes.subarray(offset + 8, end - 4))
|
|
255
|
+
if (['IHDR', 'PLTE', 'tRNS', 'IDAT', 'IEND'].includes(type))
|
|
256
|
+
chunks.push(bytes.subarray(offset, end))
|
|
257
|
+
else if (/^[A-Z]/.test(type)) throw new Error(`Unsupported critical PNG chunk: ${type}.`)
|
|
258
|
+
offset = end
|
|
259
|
+
}
|
|
260
|
+
// fast-png's inflater does not expose a byte ceiling. Check the complete
|
|
261
|
+
// compressed pixel stream with Node's ceiling before handing it the image.
|
|
262
|
+
try {
|
|
263
|
+
const inflated = inflateSync(Buffer.concat(compressed), {
|
|
264
|
+
maxOutputLength: expected,
|
|
265
|
+
})
|
|
266
|
+
if (inflated.length !== expected) malformed()
|
|
267
|
+
} catch {
|
|
268
|
+
malformed()
|
|
269
|
+
}
|
|
270
|
+
const canonical = Buffer.concat(chunks)
|
|
271
|
+
const { decode, encode, convertIndexedToRgb } = await import('fast-png')
|
|
272
|
+
try {
|
|
273
|
+
const decoded = decode(canonical, { checkCrc: true })
|
|
274
|
+
if (decoded.width !== raster.width || decoded.height !== raster.height) malformed()
|
|
275
|
+
// Decode indexed pixels too: a complete PLTE/IDAT container can still
|
|
276
|
+
// refer to a palette entry that does not exist.
|
|
277
|
+
if (decoded.palette) convertIndexedToRgb(decoded)
|
|
278
|
+
else if (decoded.depth < 8 || decoded.transparency) {
|
|
279
|
+
// Screenshot resizing assumes unpacked 8/16-bit samples and explicit
|
|
280
|
+
// alpha. Saved images can use packed greyscale or tRNS colour keys.
|
|
281
|
+
const rgba = new Uint8Array(raster.width * raster.height * 4)
|
|
282
|
+
const packedStride = Math.ceil((raster.width * decoded.depth) / 8)
|
|
283
|
+
const maxSample = 2 ** decoded.depth - 1
|
|
284
|
+
for (let y = 0; y < raster.height; y += 1) {
|
|
285
|
+
for (let x = 0; x < raster.width; x += 1) {
|
|
286
|
+
const i = y * raster.width + x
|
|
287
|
+
const packed = decoded.data[y * packedStride + Math.floor((x * decoded.depth) / 8)] ?? 0
|
|
288
|
+
const grey =
|
|
289
|
+
decoded.depth < 8
|
|
290
|
+
? (packed >>> (8 - decoded.depth - ((x * decoded.depth) % 8))) & maxSample
|
|
291
|
+
: (decoded.data[i * decoded.channels] ?? 0)
|
|
292
|
+
const r = grey
|
|
293
|
+
const g = decoded.channels >= 3 ? (decoded.data[i * decoded.channels + 1] ?? 0) : grey
|
|
294
|
+
const b = decoded.channels >= 3 ? (decoded.data[i * decoded.channels + 2] ?? 0) : grey
|
|
295
|
+
rgba[i * 4] = Math.round((r * 255) / maxSample)
|
|
296
|
+
rgba[i * 4 + 1] = Math.round((g * 255) / maxSample)
|
|
297
|
+
rgba[i * 4 + 2] = Math.round((b * 255) / maxSample)
|
|
298
|
+
const transparent =
|
|
299
|
+
decoded.transparency &&
|
|
300
|
+
r === decoded.transparency[0] &&
|
|
301
|
+
(decoded.channels === 1 ||
|
|
302
|
+
(g === decoded.transparency[1] && b === decoded.transparency[2]))
|
|
303
|
+
rgba[i * 4 + 3] = transparent ? 0 : 255
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return Buffer.from(
|
|
307
|
+
encode({ width: raster.width, height: raster.height, data: rgba, channels: 4, depth: 8 }),
|
|
308
|
+
)
|
|
309
|
+
}
|
|
310
|
+
} catch {
|
|
311
|
+
malformed()
|
|
312
|
+
}
|
|
313
|
+
return canonical
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Inspect an artifact without granting screen-coordinate authority. An image
|
|
318
|
+
* file can be a reference, render or export; it is never a computer_use frame.
|
|
319
|
+
*/
|
|
320
|
+
export function createViewImageTool(
|
|
321
|
+
options: ViewImageToolOptions = {},
|
|
322
|
+
): ToolDefinition<z.infer<typeof inputSchema>> {
|
|
323
|
+
const unavailableReason = options.unavailableReason
|
|
324
|
+
return defineTool({
|
|
325
|
+
name: 'view_image',
|
|
326
|
+
description: `Visually inspect a saved PNG, JPEG or WebP reference, render or exported image. Reads this turn's files and returns actual image pixels to the model, with source dimensions. PNGs are decoded and fitted; JPEG/WebP containers are checked and must already fit standard vision size. File pixels are not a live desktop screenshot and cannot authorize mouse coordinates.${unavailableReason ? ` Unavailable: ${unavailableReason} Do not retry; tell the user.` : ''}`,
|
|
327
|
+
inputSchema,
|
|
328
|
+
category: 'filesystem',
|
|
329
|
+
pathArgument: 'path',
|
|
330
|
+
permissions: ['file_read'],
|
|
331
|
+
readOnly: true,
|
|
332
|
+
destructive: false,
|
|
333
|
+
concurrencySafe: true,
|
|
334
|
+
presentCall: (input) => ({
|
|
335
|
+
kind: 'generic',
|
|
336
|
+
label: `Inspect ${input.path}`,
|
|
337
|
+
presentation: 'activity',
|
|
338
|
+
activity: 'exploration',
|
|
339
|
+
}),
|
|
340
|
+
async execute(input, context) {
|
|
341
|
+
if (unavailableReason) {
|
|
342
|
+
const message = `view_image unavailable: ${unavailableReason} No image was read or shown. Do not retry; tell the user.`
|
|
343
|
+
return { success: false, output: message, error: message }
|
|
344
|
+
}
|
|
345
|
+
const artifact = await readArtifact(input.path, context)
|
|
346
|
+
const source = describeRaster(artifact.bytes)
|
|
347
|
+
if (
|
|
348
|
+
!admitMcpImageBatch([
|
|
349
|
+
{
|
|
350
|
+
type: 'image',
|
|
351
|
+
mimeType: source.mediaType,
|
|
352
|
+
data: artifact.bytes.toString('base64'),
|
|
353
|
+
},
|
|
354
|
+
])
|
|
355
|
+
)
|
|
356
|
+
malformed()
|
|
357
|
+
context.abortSignal.throwIfAborted()
|
|
358
|
+
let image = {
|
|
359
|
+
data: artifact.bytes,
|
|
360
|
+
width: source.width,
|
|
361
|
+
height: source.height,
|
|
362
|
+
}
|
|
363
|
+
if (source.mediaType === 'image/png') {
|
|
364
|
+
const png = await validatedPng(artifact.bytes, source)
|
|
365
|
+
image = await fitPng(png, STANDARD_SCREENSHOT_LIMITS)
|
|
366
|
+
} else {
|
|
367
|
+
const target = screenshotTargetSize(source.width, source.height)
|
|
368
|
+
if (target.width !== source.width || target.height !== source.height)
|
|
369
|
+
throw new Error(
|
|
370
|
+
`This ${source.mediaType} image needs resizing. JPEG/WebP decoding and resizing are unavailable here; export a PNG (or a smaller JPEG/WebP) and inspect that file.`,
|
|
371
|
+
)
|
|
372
|
+
}
|
|
373
|
+
context.abortSignal.throwIfAborted()
|
|
374
|
+
const validation = source.mediaType === 'image/png' ? 'decoded' : 'container'
|
|
375
|
+
const output = `Image artifact: ${artifact.path} (${source.width}x${source.height}, ${source.mediaType}); shown at ${image.width}x${image.height}.`
|
|
376
|
+
return {
|
|
377
|
+
success: true,
|
|
378
|
+
output,
|
|
379
|
+
content: [
|
|
380
|
+
{
|
|
381
|
+
type: 'text',
|
|
382
|
+
text: `${output}\n${validation === 'container' ? 'The complete container and dimensions were validated; compressed JPEG/WebP pixels were not decoded by this tool. ' : ''}Inspect these pixels for visual evidence. This saved artifact is not a current computer_use screenshot; capture the application before GUI input.`,
|
|
383
|
+
},
|
|
384
|
+
{
|
|
385
|
+
type: 'image',
|
|
386
|
+
mediaType: source.mediaType,
|
|
387
|
+
data: image.data.toString('base64'),
|
|
388
|
+
},
|
|
389
|
+
],
|
|
390
|
+
data: {
|
|
391
|
+
path: artifact.path,
|
|
392
|
+
sandboxed: artifact.sandboxed,
|
|
393
|
+
artifact: true,
|
|
394
|
+
mediaType: source.mediaType,
|
|
395
|
+
sourceWidth: source.width,
|
|
396
|
+
sourceHeight: source.height,
|
|
397
|
+
width: image.width,
|
|
398
|
+
height: image.height,
|
|
399
|
+
sourceBytes: artifact.bytes.length,
|
|
400
|
+
sha256: createHash('sha256').update(artifact.bytes).digest('hex'),
|
|
401
|
+
validation,
|
|
402
|
+
},
|
|
403
|
+
}
|
|
404
|
+
},
|
|
405
|
+
})
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/** An optional artifact inspection tool; hosts must mount it explicitly. */
|
|
409
|
+
export const ViewImageTool = createViewImageTool()
|
|
@@ -52,6 +52,8 @@ export type JobWaitOutcome =
|
|
|
52
52
|
readonly kind: 'exited'
|
|
53
53
|
readonly status: string
|
|
54
54
|
readonly exitCode?: number
|
|
55
|
+
/** Why the command never started, when it could not. */
|
|
56
|
+
readonly error?: string
|
|
55
57
|
} & JobWaitProgress)
|
|
56
58
|
| ({
|
|
57
59
|
readonly kind: 'timeout'
|
|
@@ -142,6 +144,7 @@ export async function waitForJobWithBounds(
|
|
|
142
144
|
kind: 'exited',
|
|
143
145
|
status: job.status,
|
|
144
146
|
...(job.exitCode === undefined ? {} : { exitCode: job.exitCode }),
|
|
147
|
+
...(job.error === undefined ? {} : { error: job.error }),
|
|
145
148
|
output,
|
|
146
149
|
nextOffset: cursor,
|
|
147
150
|
droppedBytes,
|
|
@@ -33,40 +33,69 @@ const DEFAULT_IDLE_TIMEOUT_MS = readPositiveIntEnv('NAMZU_JOB_WAIT_IDLE_MS', 2 *
|
|
|
33
33
|
*/
|
|
34
34
|
const MAX_WAIT_MS = readPositiveIntEnv('NAMZU_JOB_WAIT_MAX_MS', 60 * 60 * 1000)
|
|
35
35
|
|
|
36
|
-
const inputSchema = z
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
36
|
+
const inputSchema = z
|
|
37
|
+
.object({
|
|
38
|
+
id: z.string().describe('The job id, as returned by bash with run_in_background.'),
|
|
39
|
+
output_contains: z
|
|
40
|
+
.string()
|
|
41
|
+
.min(1)
|
|
42
|
+
.max(4096)
|
|
43
|
+
.refine(
|
|
44
|
+
(value) =>
|
|
45
|
+
Buffer.byteLength(value) <= 4096 && Buffer.from(value).toString('utf8') === value,
|
|
46
|
+
'Use a non-empty UTF-8 literal of at most 4096 bytes.',
|
|
47
|
+
)
|
|
48
|
+
.optional()
|
|
49
|
+
.describe(
|
|
50
|
+
'Wait for this exact literal in output rather than for exit. This observes a marker; it does not prove service health or keep the turn open until the job exits.',
|
|
51
|
+
),
|
|
52
|
+
output_stream: z
|
|
53
|
+
.enum(['stdout', 'stderr', 'either'])
|
|
54
|
+
.optional()
|
|
55
|
+
.describe(
|
|
56
|
+
'Pipe to inspect with output_contains. Default either; stdout and stderr are never joined for a match.',
|
|
57
|
+
),
|
|
58
|
+
from_offset: z
|
|
59
|
+
.number()
|
|
60
|
+
.int()
|
|
61
|
+
.nonnegative()
|
|
62
|
+
.optional()
|
|
63
|
+
.describe('Resume after a previous wait: pass its next_offset to receive only new output.'),
|
|
64
|
+
timeout_ms: z
|
|
65
|
+
.number()
|
|
66
|
+
.int()
|
|
67
|
+
.positive()
|
|
68
|
+
.max(MAX_WAIT_MS)
|
|
69
|
+
.optional()
|
|
70
|
+
.describe(
|
|
71
|
+
`Give up after this long even if the job keeps producing output, in milliseconds. Default: ${DEFAULT_TIMEOUT_MS}, maximum: ${MAX_WAIT_MS}. The job is never stopped by this running out.`,
|
|
72
|
+
),
|
|
73
|
+
idle_timeout_ms: z
|
|
74
|
+
.number()
|
|
75
|
+
.int()
|
|
76
|
+
.positive()
|
|
77
|
+
.max(MAX_WAIT_MS)
|
|
78
|
+
.optional()
|
|
79
|
+
.describe(
|
|
80
|
+
`Give up if the job produces no new output for this long, in milliseconds. Default: ${DEFAULT_IDLE_TIMEOUT_MS}. Resets on every new byte of output, so a job that is still working is not cut off; only real silence ends the wait early.`,
|
|
81
|
+
),
|
|
82
|
+
})
|
|
83
|
+
.superRefine((input, ctx) => {
|
|
84
|
+
if (input.output_stream !== undefined && input.output_contains === undefined) {
|
|
85
|
+
ctx.addIssue({
|
|
86
|
+
code: 'custom',
|
|
87
|
+
path: ['output_stream'],
|
|
88
|
+
message: 'output_stream requires output_contains.',
|
|
89
|
+
})
|
|
90
|
+
}
|
|
91
|
+
})
|
|
63
92
|
|
|
64
93
|
type WaitForJobInput = z.infer<typeof inputSchema>
|
|
65
94
|
|
|
66
95
|
export const WaitForJobTool = defineTool({
|
|
67
96
|
name: 'wait_for_job',
|
|
68
97
|
description:
|
|
69
|
-
'
|
|
98
|
+
'Wait for an owned background job to exit, or set output_contains to observe an exact output marker while it stays running. Use one wait instead of polling job read. Output markers do not prove service health or completion and never express intent to wait until exit. A bounded wait returns output and next_offset without stopping the job; pass that cursor as from_offset to exclude earlier output.',
|
|
70
99
|
inputSchema,
|
|
71
100
|
category: 'shell',
|
|
72
101
|
permissions: ['shell_execute'],
|
|
@@ -88,7 +117,7 @@ export const WaitForJobTool = defineTool({
|
|
|
88
117
|
return {
|
|
89
118
|
kind: 'generic',
|
|
90
119
|
presentation: 'activity',
|
|
91
|
-
label:
|
|
120
|
+
label: `${input.output_contains === undefined ? 'Wait for background job' : 'Wait for job output'} · ${input.id ?? '(missing id)'}`,
|
|
92
121
|
}
|
|
93
122
|
},
|
|
94
123
|
|
|
@@ -112,6 +141,83 @@ export const WaitForJobTool = defineTool({
|
|
|
112
141
|
}
|
|
113
142
|
}
|
|
114
143
|
|
|
144
|
+
if (input.output_stream !== undefined && input.output_contains === undefined) {
|
|
145
|
+
return { success: false, output: '', error: 'output_stream requires output_contains.' }
|
|
146
|
+
}
|
|
147
|
+
if (input.output_contains !== undefined) {
|
|
148
|
+
if (!jobs.waitForOutput) {
|
|
149
|
+
return {
|
|
150
|
+
success: false,
|
|
151
|
+
output: '',
|
|
152
|
+
error:
|
|
153
|
+
'This host cannot observe output readiness. It must implement backgroundJobs.waitForOutput; no exit wait was started.',
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
try {
|
|
157
|
+
const outcome = await jobs.waitForOutput(input.id, {
|
|
158
|
+
literal: input.output_contains,
|
|
159
|
+
stream: input.output_stream ?? 'either',
|
|
160
|
+
timeoutMs: input.timeout_ms ?? DEFAULT_TIMEOUT_MS,
|
|
161
|
+
idleTimeoutMs: input.idle_timeout_ms ?? DEFAULT_IDLE_TIMEOUT_MS,
|
|
162
|
+
...(input.from_offset === undefined ? {} : { fromOffset: input.from_offset }),
|
|
163
|
+
signal: context.abortSignal,
|
|
164
|
+
})
|
|
165
|
+
const notices = [
|
|
166
|
+
...(outcome.droppedBytes > 0
|
|
167
|
+
? [`[${outcome.droppedBytes} bytes unavailable before the retained output]`]
|
|
168
|
+
: []),
|
|
169
|
+
...(outcome.unsearchedBytes > 0
|
|
170
|
+
? [
|
|
171
|
+
`[${outcome.unsearchedBytes} retained bytes could not be searched because the channel history cap discarded them]`,
|
|
172
|
+
]
|
|
173
|
+
: []),
|
|
174
|
+
...(outcome.omittedOutputBytes > 0
|
|
175
|
+
? [`[${outcome.omittedOutputBytes} earlier bytes omitted from this bounded result]`]
|
|
176
|
+
: []),
|
|
177
|
+
]
|
|
178
|
+
const status =
|
|
179
|
+
outcome.error !== undefined
|
|
180
|
+
? `failed to start: ${outcome.error}`
|
|
181
|
+
: outcome.exitCode === undefined
|
|
182
|
+
? outcome.status
|
|
183
|
+
: `${outcome.status} with code ${outcome.exitCode}`
|
|
184
|
+
const reason =
|
|
185
|
+
outcome.kind === 'matched'
|
|
186
|
+
? `Output marker observed on ${outcome.matchedStream}. This is output evidence, not a health check or completion claim.`
|
|
187
|
+
: outcome.kind === 'exited'
|
|
188
|
+
? 'Job exited before the marker was observed.'
|
|
189
|
+
: outcome.kind === 'stopped'
|
|
190
|
+
? 'Job stop was requested before the marker was observed; shutdown may still be completing.'
|
|
191
|
+
: outcome.kind === 'aborted'
|
|
192
|
+
? 'Output observation was cancelled; this wait did not stop the job.'
|
|
193
|
+
: `Output marker was not observed before the ${outcome.cause} timeout (${outcome.elapsedMs} ms); this wait did not stop the job.`
|
|
194
|
+
return {
|
|
195
|
+
success: outcome.kind !== 'aborted',
|
|
196
|
+
output: `${reason}\n\n${notices.length > 0 ? `${notices.join('\n')}\n` : ''}${outcome.output || '(no new output)'}\n\n[job ${input.id} is ${status}; next_offset ${outcome.nextOffset}]`,
|
|
197
|
+
data: {
|
|
198
|
+
jobId: input.id,
|
|
199
|
+
outcome: outcome.kind,
|
|
200
|
+
status: outcome.status,
|
|
201
|
+
nextOffset: outcome.nextOffset,
|
|
202
|
+
droppedBytes: outcome.droppedBytes,
|
|
203
|
+
unsearchedBytes: outcome.unsearchedBytes,
|
|
204
|
+
omittedOutputBytes: outcome.omittedOutputBytes,
|
|
205
|
+
...(outcome.kind === 'matched' ? { matchedStream: outcome.matchedStream } : {}),
|
|
206
|
+
...(outcome.kind === 'timeout' ? { timedOut: outcome.cause } : {}),
|
|
207
|
+
...(outcome.kind === 'aborted' ? { abandoned: true } : {}),
|
|
208
|
+
...(outcome.exitCode === undefined ? {} : { exitCode: outcome.exitCode }),
|
|
209
|
+
...(outcome.error === undefined ? {} : { error: outcome.error }),
|
|
210
|
+
},
|
|
211
|
+
}
|
|
212
|
+
} catch (err) {
|
|
213
|
+
return {
|
|
214
|
+
success: false,
|
|
215
|
+
output: '',
|
|
216
|
+
error: err instanceof Error ? err.message : String(err),
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
115
221
|
if (!jobs.waitForExit) {
|
|
116
222
|
return {
|
|
117
223
|
success: false,
|
|
@@ -178,9 +284,11 @@ export const WaitForJobTool = defineTool({
|
|
|
178
284
|
}
|
|
179
285
|
|
|
180
286
|
const status =
|
|
181
|
-
outcome.
|
|
182
|
-
? outcome.
|
|
183
|
-
:
|
|
287
|
+
outcome.error !== undefined
|
|
288
|
+
? `failed to start: ${outcome.error}`
|
|
289
|
+
: outcome.exitCode === undefined
|
|
290
|
+
? outcome.status
|
|
291
|
+
: `${outcome.status} with code ${outcome.exitCode}`
|
|
184
292
|
|
|
185
293
|
return {
|
|
186
294
|
success: true,
|
|
@@ -192,6 +300,7 @@ export const WaitForJobTool = defineTool({
|
|
|
192
300
|
droppedBytes: outcome.droppedBytes,
|
|
193
301
|
omittedOutputBytes: outcome.omittedOutputBytes,
|
|
194
302
|
...(outcome.exitCode === undefined ? {} : { exitCode: outcome.exitCode }),
|
|
303
|
+
...(outcome.error === undefined ? {} : { error: outcome.error }),
|
|
195
304
|
},
|
|
196
305
|
}
|
|
197
306
|
},
|
|
@@ -2,6 +2,7 @@ import { mkdir, readFile } from 'node:fs/promises'
|
|
|
2
2
|
import { dirname } from 'node:path'
|
|
3
3
|
import { z } from 'zod'
|
|
4
4
|
import type { ToolContext, ToolResult } from '../../types/tool/index.js'
|
|
5
|
+
import type { ToolFacts } from '../../types/tool/presentation.js'
|
|
5
6
|
import { defineTool } from '../defineTool.js'
|
|
6
7
|
import { resolveWithinAnyReal, toolRoots } from '../paths.js'
|
|
7
8
|
import { atomicWriteFile } from './atomic-write-file.js'
|
|
@@ -196,13 +197,14 @@ export const WriteFileTool = defineTool({
|
|
|
196
197
|
function enforceReadBeforeOverwrite(
|
|
197
198
|
context: ToolContext,
|
|
198
199
|
key: string,
|
|
199
|
-
): { success: false; output: ''; error: string } | null {
|
|
200
|
+
): { success: false; output: ''; error: string; facts?: ToolFacts } | null {
|
|
200
201
|
if (!context.fileReadTracker) return null
|
|
201
202
|
if (context.fileReadTracker.hasRead(key)) return null
|
|
202
203
|
return {
|
|
203
204
|
success: false,
|
|
204
205
|
output: '',
|
|
205
206
|
error: `${key} already exists. Use the \`read\` tool on it first in this conversation, then call \`write\` again — or prefer \`edit\` for a targeted change.`,
|
|
207
|
+
facts: { kind: 'failure', reason: 'already_exists', subject: key },
|
|
206
208
|
}
|
|
207
209
|
}
|
|
208
210
|
|
|
@@ -210,7 +212,7 @@ function enforceFreshOverwrite(
|
|
|
210
212
|
context: ToolContext,
|
|
211
213
|
key: string,
|
|
212
214
|
currentContent: string,
|
|
213
|
-
): { success: false; output: ''; error: string } | null {
|
|
215
|
+
): { success: false; output: ''; error: string; facts?: ToolFacts } | null {
|
|
214
216
|
const unread = enforceReadBeforeOverwrite(context, key)
|
|
215
217
|
if (unread) return unread
|
|
216
218
|
|