mixdog 1.3.5 → 1.4.1
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/NOTICE.md +2 -2
- package/README.md +2 -2
- package/package.json +2 -11
- package/scripts/check-voice-runtime-inputs.mjs +25 -0
- package/scripts/daemon-stub.mjs +1 -1
- package/scripts/gate-local.mjs +16 -5
- package/scripts/latest-guard.mjs +21 -9
- package/scripts/lib/isolated-test-env.mjs +10 -5
- package/scripts/lib/run-node-tests.mjs +37 -37
- package/scripts/lib/scoped-temp.d.mts +16 -0
- package/scripts/lib/scoped-temp.mjs +123 -0
- package/scripts/lib/stale-temp.mjs +44 -0
- package/scripts/native-release-status.mjs +2 -2
- package/scripts/post-release-check.mjs +1 -6
- package/scripts/pptx-kit-index.mjs +17 -4
- package/scripts/recall-history-cases.json +1 -1
- package/scripts/suite-health.mjs +20 -2
- package/scripts/test-data-dir.mjs +10 -7
- package/scripts/test.mjs +7 -11
- package/src/agents/reviewer/AGENT.md +7 -11
- package/src/agents/reviewer/agent.json +1 -1
- package/src/app.mjs +4 -0
- package/src/defaults/shipped-history.json +22 -1
- package/src/defaults/skills/browser-use/SKILL.md +62 -12
- package/src/defaults/skills/code-tidy/SKILL.md +142 -270
- package/src/defaults/skills/code-tidy/references/agent-cleanup.md +4 -4
- package/src/defaults/skills/code-tidy/references/cleanup-report.md +31 -76
- package/src/defaults/skills/code-tidy/references/dead-code.md +6 -12
- package/src/defaults/skills/computer-use/SKILL.md +35 -9
- package/src/defaults/skills/setup/SKILL.md +22 -0
- package/src/defaults/skills/setup/references/actions.md +39 -5
- package/src/defaults/skills/setup/references/surfaces.md +11 -2
- package/src/defaults/skills/visualize/SKILL.md +2 -1
- package/src/lib/rules-builder.cjs +39 -20
- package/src/output-styles/common.md +2 -2
- package/src/output-styles/simple.md +1 -1
- package/src/rules/agent/AGENT.md +11 -10
- package/src/rules/lead/LEAD.md +23 -20
- package/src/rules/shared/05-tool-calls.md +5 -6
- package/src/rules/shared/10-tool-workflow.md +4 -0
- package/src/rules/shared/45-destructive.md +0 -2
- package/src/rules/shared/50-execution.md +2 -0
- package/src/rules/shared/60-verification.md +7 -5
- package/src/rules/shared/70-delivery.md +7 -9
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +29 -6
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -3
- package/src/runtime/agent/orchestrator/agent-runtime/title-completion.mjs +3 -1
- package/src/runtime/agent/orchestrator/agent-trace-format.mjs +3 -1
- package/src/runtime/agent/orchestrator/cache-break-trace.mjs +2 -0
- package/src/runtime/agent/orchestrator/config.mjs +17 -1
- package/src/runtime/agent/orchestrator/context/collect.mjs +3 -0
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +73 -68
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +57 -2
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +3 -3
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +176 -72
- package/src/runtime/agent/orchestrator/mcp/client.mjs +19 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +192 -133
- package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +42 -6
- package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +7 -3
- package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +8 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-cache-warm.mjs +165 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +6 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +14 -14
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/initial-status.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +159 -69
- package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +25 -3
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +70 -33
- package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +135 -87
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +123 -102
- package/src/runtime/agent/orchestrator/providers/cache-warm-admission.mjs +90 -0
- package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +1 -10
- package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +25 -9
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +25 -13
- package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/devin.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +210 -20
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-prefix-trace.mjs +76 -11
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +45 -6
- package/src/runtime/agent/orchestrator/providers/lib/first-output-window.mjs +58 -0
- package/src/runtime/agent/orchestrator/providers/lib/listen-on.mjs +14 -0
- package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +17 -3
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +52 -10
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-login.mjs +1 -10
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +8 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/npm-cli-version.mjs +11 -3
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +14 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +4 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +5 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +16 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +13 -3
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +13 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +81 -42
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +8 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +136 -5
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +10 -9
- package/src/runtime/agent/orchestrator/providers/openai-ws-send/send-context.mjs +22 -3
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +43 -5
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/handshake-failure.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/stream-failure.mjs +6 -3
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +20 -12
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +48 -22
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +65 -1
- package/src/runtime/agent/orchestrator/providers/quota-reading.mjs +38 -12
- package/src/runtime/agent/orchestrator/providers/registry.mjs +38 -0
- package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +39 -7
- package/src/runtime/agent/orchestrator/providers/statusline-route-meta.mjs +6 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +49 -16
- package/src/runtime/agent/orchestrator/runtime-core/compaction-config-keys.mjs +62 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +37 -16
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +100 -23
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +7 -6
- package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +9 -3
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +19 -4
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +125 -30
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +3 -1
- package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +5 -2
- package/src/runtime/agent/orchestrator/session/cache/scoped-cache.mjs +1 -3
- package/src/runtime/agent/orchestrator/session/cache-warm.mjs +798 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -8
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +23 -0
- package/src/runtime/agent/orchestrator/session/compact/observation-supersession.mjs +103 -23
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +280 -45
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +475 -58
- package/src/runtime/agent/orchestrator/session/compaction-archive.mjs +42 -17
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +13 -1
- package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +163 -22
- package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +132 -17
- package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +38 -7
- package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +90 -22
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +11 -5
- package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +0 -2
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -4
- package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +51 -25
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +37 -3
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +13 -5
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +31 -3
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +20 -3
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/after-hook.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +5 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +16 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +16 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +49 -21
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -10
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +12 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +12 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +19 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +133 -90
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +31 -4
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +30 -18
- package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +24 -14
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +11 -2
- package/src/runtime/agent/orchestrator/session/manager/provider-replay.mjs +13 -0
- package/src/runtime/agent/orchestrator/session/manager/route-fallback-chain.mjs +130 -0
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +27 -9
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +81 -8
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +27 -8
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +12 -5
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +9 -4
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +102 -15
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +21 -5
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +9 -0
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +24 -9
- package/src/runtime/agent/orchestrator/session/prompt-cache-idle-gaps.mjs +113 -0
- package/src/runtime/agent/orchestrator/session/prompt-cache-touch-store.mjs +150 -0
- package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +154 -0
- package/src/runtime/agent/orchestrator/session/routine-result.mjs +36 -9
- package/src/runtime/agent/orchestrator/session/sensitive-projection.mjs +100 -0
- package/src/runtime/agent/orchestrator/session/sensitive-values.mjs +257 -0
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +20 -7
- package/src/runtime/agent/orchestrator/session/side-question.mjs +18 -0
- package/src/runtime/agent/orchestrator/session/skill-update-notice.mjs +60 -0
- package/src/runtime/agent/orchestrator/session/store/live-state.mjs +6 -3
- package/src/runtime/agent/orchestrator/session/store/save-delta.mjs +9 -5
- package/src/runtime/agent/orchestrator/session/store/serialize.mjs +9 -8
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +7 -0
- package/src/runtime/agent/orchestrator/session/store/session-persistence-events.mjs +29 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +8 -6
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +16 -2
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +81 -22
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +92 -3
- package/src/runtime/agent/orchestrator/session/stored-attachment-history.mjs +32 -0
- package/src/runtime/agent/orchestrator/session/thinking-binding.mjs +108 -0
- package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +79 -3
- package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-status.mjs +9 -7
- package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-text.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/turn-failure.mjs +5 -1
- package/src/runtime/agent/orchestrator/stall-policy.mjs +23 -0
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +5 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +12 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +240 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/shell-cwd.mjs +38 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +31 -6
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +110 -26
- package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +31 -5
- package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +22 -8
- package/src/runtime/agent/orchestrator/tools/builtin/lib/scoped-search-flight.mjs +9 -5
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-stream.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +6 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-dispatch.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-publication.mjs +23 -12
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-snapshot.mjs +6 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +1 -8
- package/src/runtime/agent/orchestrator/tools/builtin/shell-runtime.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/federation.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
- package/src/runtime/agent/orchestrator/tools/lib/isolated-test-env.mjs +4 -3
- package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +26 -4
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +36 -13
- package/src/runtime/browser-bridge/action-schema.mjs +13 -2
- package/src/runtime/browser-bridge/client.mjs +73 -8
- package/src/runtime/browser-bridge/input-fields.mjs +8 -9
- package/src/runtime/browser-bridge/mail-links.mjs +107 -0
- package/src/runtime/browser-bridge/tool-defs.mjs +1 -1
- package/src/runtime/channels/lib/config.mjs +6 -61
- package/src/runtime/channels/lib/crash-log.mjs +1 -1
- package/src/runtime/channels/lib/event-pipeline.mjs +4 -19
- package/src/runtime/channels/lib/event-queue.mjs +3 -18
- package/src/runtime/channels/lib/owned-runtime/automation-services.mjs +2 -2
- package/src/runtime/channels/lib/owned-runtime/automation-start.mjs +3 -4
- package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +4 -59
- package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +33 -115
- package/src/runtime/channels/lib/owned-runtime/owned-stop.mjs +5 -22
- package/src/runtime/channels/lib/owned-runtime/state.mjs +2 -8
- package/src/runtime/channels/lib/owned-runtime.mjs +6 -23
- package/src/runtime/channels/lib/parent-bridge.mjs +2 -2
- package/src/runtime/channels/lib/runtime-paths.mjs +4 -43
- package/src/runtime/channels/lib/scheduler.mjs +33 -147
- package/src/runtime/channels/lib/schedules-db.mjs +34 -11
- package/src/runtime/channels/lib/status-snapshot.mjs +1 -1
- package/src/runtime/channels/lib/tool-dispatch.mjs +1 -2
- package/src/runtime/channels/lib/webhook/signature.mjs +4 -1
- package/src/runtime/channels/lib/webhooks-db.mjs +5 -9
- package/src/runtime/channels/lib/whisper-port.mjs +10 -1
- package/src/runtime/channels/lib/worker-bootstrap.mjs +0 -1
- package/src/runtime/channels/lib/worker-ipc.mjs +0 -1
- package/src/runtime/channels/lib/worker-main.mjs +10 -34
- package/src/runtime/computer-bridge/action-schema.mjs +42 -1
- package/src/runtime/computer-bridge/actions.mjs +9 -1
- package/src/runtime/computer-bridge/client.mjs +180 -8
- package/src/runtime/computer-bridge/core-actions.mjs +2 -2
- package/src/runtime/computer-bridge/error-recovery.mjs +28 -2
- package/src/runtime/computer-bridge/linux-action-capabilities.mjs +24 -5
- package/src/runtime/computer-bridge/linux-readiness.d.mts +7 -2
- package/src/runtime/computer-bridge/linux-readiness.mjs +65 -23
- package/src/runtime/computer-bridge/pending-continuation.mjs +1 -1
- package/src/runtime/connectors/connector-accounts-mcp.mjs +230 -0
- package/src/runtime/connectors/gmail-app-password.mjs +172 -39
- package/src/runtime/connectors/google-mcp.mjs +10 -12
- package/src/runtime/local-provider/server-process.mjs +2 -1
- package/src/runtime/media/adapters/gemini-video.mjs +4 -1
- package/src/runtime/media/adapters/xai-media.mjs +2 -1
- package/src/runtime/memory/lib/embedding-worker.mjs +6 -3
- package/src/runtime/memory/lib/memory-action-handlers/cycle-backfill-action.mjs +1 -7
- package/src/runtime/memory/lib/memory-chunk-quality.mjs +1 -6
- package/src/runtime/memory/lib/pg/adapter.mjs +77 -70
- package/src/runtime/memory/lib/pg/supervisor.mjs +24 -12
- package/src/runtime/memory/lib/runtime-fetcher.mjs +23 -5
- package/src/runtime/office/authoring/pdf-author-action.mjs +1 -6
- package/src/runtime/office/design/design-art-direction.mjs +29 -27
- package/src/runtime/office/pdf/pdf-writer.mjs +6 -1
- package/src/runtime/office/portable/portable-snapshot-docx.mjs +7 -1
- package/src/runtime/office/portable/portable-snapshot-shared.mjs +6 -1
- package/src/runtime/office/quality/assurance-rendered.mjs +9 -2
- package/src/runtime/office/quality/assurance-structure-docx.mjs +3 -1
- package/src/runtime/office/quality/design-review.mjs +1 -5
- package/src/runtime/office/quality/document-brief.mjs +1 -5
- package/src/runtime/office/quality/forced-break-pages.mjs +9 -6
- package/src/runtime/office/quality/quality-pipeline.mjs +1 -1
- package/src/runtime/session-search/session-search-db.mjs +73 -9
- package/src/runtime/session-search/session-search-ingest.mjs +110 -20
- package/src/runtime/shared/abort-race.mjs +89 -0
- package/src/runtime/shared/agent-avatar.d.mts +0 -1
- package/src/runtime/shared/agent-kind.mjs +4 -3
- package/src/runtime/shared/bot-owned-work.mjs +56 -0
- package/src/runtime/shared/bounded-download.mjs +8 -3
- package/src/runtime/shared/config.mjs +2 -13
- package/src/runtime/shared/connector-accounts.mjs +20 -10
- package/src/runtime/shared/connector-catalog.d.mts +29 -0
- package/src/runtime/shared/connector-catalog.mjs +150 -0
- package/src/runtime/shared/connector-triggers.mjs +22 -19
- package/src/runtime/shared/defaults-separation.mjs +2 -17
- package/src/runtime/shared/delegated-approval-host.mjs +103 -11
- package/src/runtime/shared/err-text.mjs +24 -15
- package/src/runtime/shared/fetch-safe-listen.d.mts +16 -0
- package/src/runtime/shared/fetch-safe-listen.mjs +50 -0
- package/src/runtime/shared/file-permissions.d.mts +0 -8
- package/src/runtime/shared/file-permissions.mjs +0 -11
- package/src/runtime/shared/git-direct.test-support.mjs +19 -0
- package/src/runtime/shared/handoff-artifacts.d.mts +2 -1
- package/src/runtime/shared/handoff-artifacts.mjs +18 -8
- package/src/runtime/shared/heartbeat-interval.d.mts +4 -0
- package/src/runtime/shared/heartbeat-interval.mjs +19 -0
- package/src/runtime/shared/idle-auto-clear-gate.mjs +126 -0
- package/src/runtime/shared/llm/cost.mjs +5 -1
- package/src/runtime/shared/llm/usage-rollup.mjs +1 -1
- package/src/runtime/shared/loopback-listener.mjs +25 -2
- package/src/runtime/shared/mixy-presence.mjs +22 -0
- package/src/runtime/shared/model-route-chain.d.mts +7 -2
- package/src/runtime/shared/model-route-chain.mjs +22 -4
- package/src/runtime/shared/open-url.mjs +10 -0
- package/src/runtime/shared/orchestration.d.mts +2 -0
- package/src/runtime/shared/pg-schema-db.mjs +27 -16
- package/src/runtime/shared/profile-config.cjs +1 -1
- package/src/runtime/shared/prompt-origin.d.mts +4 -0
- package/src/runtime/shared/prompt-origin.mjs +21 -0
- package/src/runtime/shared/provider-accounts.mjs +7 -1
- package/src/runtime/shared/provider-display-name.mjs +29 -0
- package/src/runtime/shared/provider-timeout-phase.mjs +2 -0
- package/src/runtime/shared/routine-trigger.d.mts +2 -0
- package/src/runtime/shared/routine-trigger.mjs +10 -0
- package/src/runtime/shared/sensitive-path-rules.d.mts +2 -10
- package/src/runtime/shared/sensitive-path-rules.mjs +19 -41
- package/src/runtime/shared/session-activity-signal.mjs +48 -1
- package/src/runtime/shared/session-scratch.mjs +37 -0
- package/src/runtime/shared/session-sidebar-host.d.mts +1 -1
- package/src/runtime/shared/session-sidebar-host.mjs +7 -3
- package/src/runtime/shared/session-turn-prelude.mjs +18 -0
- package/src/runtime/shared/tool-card-model/agent-surface.mjs +1 -3
- package/src/runtime/shared/tool-card-model/card-status.mjs +15 -2
- package/src/runtime/shared/tool-result-summary.mjs +2 -15
- package/src/runtime/shared/tool-surface.mjs +3 -0
- package/src/runtime/shared/tool-work-units.mjs +2 -0
- package/src/runtime/shared/turn-snapshot-store.mjs +13 -6
- package/src/runtime/shared/worktrees/contract.mjs +4 -1
- package/src/runtime/shared/worktrees/git.mjs +15 -0
- package/src/runtime/shared/worktrees/manager.mjs +87 -38
- package/src/runtime/shared/worktrees/test-support.mjs +14 -13
- package/src/runtime/terminal-bridge/client.mjs +10 -1
- package/src/runtime/visualize-bridge/client.mjs +29 -8
- package/src/runtime/visualize-bridge/tool-defs.mjs +22 -8
- package/src/runtime/visualize-bridge/tool-meta.d.mts +5 -0
- package/src/runtime/visualize-bridge/tool-meta.mjs +22 -0
- package/src/runtime/web-search/lib/fetch-pipeline.mjs +2 -2
- package/src/session-runtime/agent-home-delivery.mjs +489 -185
- package/src/session-runtime/agent-task-sessions.mjs +467 -229
- package/src/session-runtime/agent-tool-routing.mjs +8 -41
- package/src/session-runtime/boot/apis.mjs +9 -0
- package/src/session-runtime/boot/infrastructure.mjs +4 -0
- package/src/session-runtime/boot/providers.mjs +3 -0
- package/src/session-runtime/boot/tools.mjs +11 -2
- package/src/session-runtime/bot-status.mjs +12 -6
- package/src/session-runtime/bot-target.mjs +38 -0
- package/src/session-runtime/channel-config-api.mjs +6 -1
- package/src/session-runtime/config-lifecycle.mjs +6 -0
- package/src/session-runtime/connector-merge-migration.mjs +305 -0
- package/src/session-runtime/conversation-import/codex-titles.mjs +88 -0
- package/src/session-runtime/conversation-import/discovery.mjs +271 -25
- package/src/session-runtime/conversation-import/service.mjs +26 -5
- package/src/session-runtime/handoff-attachments.mjs +82 -31
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +144 -41
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -0
- package/src/session-runtime/internal-tool-executor/reaction-tool.mjs +4 -1
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +8 -2
- package/src/session-runtime/lifecycle/cold-heir.mjs +11 -6
- package/src/session-runtime/lifecycle/inheritance.mjs +16 -3
- package/src/session-runtime/lifecycle/session-catalog.mjs +12 -2
- package/src/session-runtime/lifecycle/teardown/runtime-stops.mjs +50 -4
- package/src/session-runtime/lifecycle/teardown.mjs +23 -5
- package/src/session-runtime/mcp-glue/server-catalog.mjs +55 -3
- package/src/session-runtime/mcp-oauth-login.mjs +5 -3
- package/src/session-runtime/mixy-heartbeat.mjs +153 -33
- package/src/session-runtime/model-route/set-route.mjs +11 -2
- package/src/session-runtime/notification-bus.mjs +31 -117
- package/src/session-runtime/notification-completion-queue.mjs +54 -0
- package/src/session-runtime/notification-listeners.mjs +76 -0
- package/src/session-runtime/owned-automation-run.mjs +2 -1
- package/src/session-runtime/prewarm/channel-start.mjs +3 -7
- package/src/session-runtime/provider-catalog-cache.mjs +82 -36
- package/src/session-runtime/provider-models/catalog-load.mjs +23 -6
- package/src/session-runtime/provider-models.mjs +4 -2
- package/src/session-runtime/resource-mcp-api.mjs +143 -224
- package/src/session-runtime/resource-mcp-connector-accounts.mjs +163 -0
- package/src/session-runtime/resource-mcp-oauth-api.mjs +217 -0
- package/src/session-runtime/resource-mcp-secrets.mjs +82 -0
- package/src/session-runtime/resource-mcp-servers.mjs +78 -0
- package/src/session-runtime/resource-mcp-store.mjs +49 -0
- package/src/session-runtime/resource-recall-api.mjs +6 -1
- package/src/session-runtime/routine-owner.mjs +40 -9
- package/src/session-runtime/runtime-feature-gates.mjs +5 -1
- package/src/session-runtime/services/agent-tool/close-flow.mjs +3 -0
- package/src/session-runtime/services/agent-tool/execute.mjs +14 -9
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +20 -4
- package/src/session-runtime/services/agent-tool/model-select.mjs +48 -7
- package/src/session-runtime/services/agent-tool/render.mjs +71 -17
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +13 -4
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +1 -0
- package/src/session-runtime/services/agent-tool/tool-def.mjs +9 -9
- package/src/session-runtime/services/agent-tool/worker-index/awaiting-user-sync.mjs +51 -0
- package/src/session-runtime/services/agent-tool/worker-index/disposal.mjs +55 -0
- package/src/session-runtime/services/agent-tool/worker-index/released-store.mjs +123 -0
- package/src/session-runtime/services/agent-tool/worker-index/restart-settlement.mjs +112 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-reads.mjs +36 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +17 -4
- package/src/session-runtime/services/agent-tool/worker-index/row-writes.mjs +58 -0
- package/src/session-runtime/services/agent-tool/worker-index.mjs +41 -241
- package/src/session-runtime/services/agent-tool/worker-rows.mjs +3 -0
- package/src/session-runtime/services/channel-admin.mjs +7 -13
- package/src/session-runtime/services/channel-session-router.mjs +4 -2
- package/src/session-runtime/services/provider-admin.mjs +2 -1
- package/src/session-runtime/services/seeds.mjs +0 -28
- package/src/session-runtime/session-compaction-sync.mjs +27 -0
- package/src/session-runtime/session-create/session-options.mjs +1 -0
- package/src/session-runtime/settings-builtin-tools-api.mjs +11 -0
- package/src/session-runtime/settings-compaction-api.mjs +2 -40
- package/src/session-runtime/settings-system-api.mjs +13 -1
- package/src/session-runtime/setup-tool/agent-settings-actions.mjs +65 -0
- package/src/session-runtime/setup-tool/executor.mjs +145 -22
- package/src/session-runtime/setup-tool/extended-actions.mjs +8 -3
- package/src/session-runtime/setup-tool/session-route-actions.mjs +152 -0
- package/src/session-runtime/setup-tool/settings-contract.mjs +4 -3
- package/src/session-runtime/setup-tool/tool-defs.mjs +64 -5
- package/src/session-runtime/tool-policy/agent-profile-fold.mjs +17 -13
- package/src/session-runtime/tool-policy/policy-stage.mjs +17 -2
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +5 -1
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +15 -4
- package/src/session-runtime/workflow-agents-api/onboarding.mjs +3 -3
- package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +4 -0
- package/src/session-runtime/workspace/transitions.mjs +25 -0
- package/src/session-runtime/workspace/worktree-tool.mjs +26 -9
- package/src/standalone/channel-transport/client-registry/client-records.mjs +65 -0
- package/src/standalone/channel-transport/client-registry/client-registration.mjs +118 -0
- package/src/standalone/channel-transport/client-registry.mjs +24 -163
- package/src/standalone/channel-transport.mjs +1 -1
- package/src/standalone/daemon-channels-loader.mjs +10 -8
- package/src/standalone/daemon-session-control/list-page.mjs +72 -0
- package/src/standalone/daemon-session-control/request.mjs +51 -0
- package/src/standalone/daemon-session-control/room-host.mjs +57 -0
- package/src/standalone/daemon-session-control/route-control.mjs +48 -0
- package/src/standalone/daemon-session-control/send-turn.mjs +60 -0
- package/src/standalone/daemon-session-control/worktree-control.mjs +40 -0
- package/src/standalone/daemon-session-control.mjs +142 -190
- package/src/standalone/daemon.mjs +26 -3
- package/src/standalone/session-client.mjs +7 -3
- package/src/standalone/session-protocol.mjs +5 -0
- package/src/standalone/session-service/agent-tree/agent-child.mjs +1 -0
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +16 -12
- package/src/standalone/session-service/quota-resume.mjs +3 -0
- package/src/standalone/session-service/retention/busy.mjs +65 -1
- package/src/standalone/session-service/session-calls/session-action.mjs +30 -2
- package/src/standalone/session-service/session-calls/session-views.mjs +8 -0
- package/src/standalone/session-tool-output.mjs +15 -7
- package/src/standalone/session-transport/client-registry/client-grace.mjs +12 -9
- package/src/tui/app/app-view/floating-panel.jsx +7 -4
- package/src/tui/app/model-options.mjs +3 -28
- package/src/tui/app/model-picker/route-selection/fast-parameters.mjs +1 -3
- package/src/tui/app/model-picker/route-selection.mjs +5 -6
- package/src/tui/app/provider-setup/oauth-actions.mjs +38 -20
- package/src/tui/app/provider-setup/provider-items.mjs +8 -2
- package/src/tui/app/provider-setup-picker.mjs +9 -5
- package/src/tui/components/QuestionPanel.jsx +13 -4
- package/src/tui/dist/index.mjs +133 -92
- package/src/tui/session/agent-job-feed/model-notification.mjs +3 -0
- package/src/tui/session/initial-state.mjs +3 -0
- package/src/tui/session/notice-surface.mjs +7 -1
- package/src/tui/session/queue-helpers.mjs +3 -42
- package/src/tui/session/session-api/routes-agent-definitions.mjs +14 -2
- package/src/tui/session/session-api/routes-write.mjs +5 -1
- package/src/tui/session/session-api/routes.mjs +1 -0
- package/src/tui/session/session-api/settings.mjs +17 -1
- package/src/tui/session/session-flow/auto-clear.mjs +4 -33
- package/src/tui/session/session-flow/drain-closed-queue.mjs +38 -0
- package/src/tui/session/session-flow/drain-enqueue.mjs +86 -0
- package/src/tui/session/session-flow/drain-retry.mjs +35 -0
- package/src/tui/session/session-flow/drain.mjs +118 -149
- package/src/tui/session/session-flow/queue/entry-shape.mjs +5 -0
- package/src/tui/session/session-flow/queue/take-entries.mjs +16 -2
- package/src/tui/session/tool-approval-delegation.mjs +64 -0
- package/src/tui/session/tool-approval-request.mjs +39 -0
- package/src/tui/session/tool-approval-settle.mjs +62 -0
- package/src/tui/session/tool-approval.mjs +69 -115
- package/src/tui/session/tui-steering-persist.mjs +8 -1
- package/src/tui/session/turn-stream.mjs +19 -2
- package/src/tui/session/turn.mjs +1 -0
- package/src/ui/statusline-agents.mjs +1 -3
- package/src/vendor/statusline/bin/statusline-route.mjs +1 -219
- package/src/vendor/statusline/src/gateway/route-meta.mjs +35 -13
- package/scripts/code-graph-description-contract.mjs +0 -188
- package/src/runtime/channels/lib/owned-runtime/ownership-refresh.mjs +0 -36
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
// Runtime guards against shell-tool misuse, run in the shell tool's validation
|
|
2
|
+
// step before hooks, approvals and execution (tool-exec.mjs) and again, once,
|
|
3
|
+
// for callers that reach executeBashTool without that step:
|
|
4
|
+
// 1. a leading whole-second sleep of 2 s or more is rejected (a wait belongs
|
|
5
|
+
// to background + task wait);
|
|
6
|
+
// 2. a plain leading `cd <dir>` moves into the `cwd` argument;
|
|
7
|
+
// 3. a shell file read (cat/Get-Content/grep/ls …) gets a pointer to the
|
|
8
|
+
// read / grep / list tools — a note now, a rejection when the mode flips.
|
|
9
|
+
import { shellSplitPipelineSegments, shellSplitSegments, shellTokenize } from '../shell-analysis.mjs';
|
|
10
|
+
import { resolveShellFor } from '../shell-runtime.mjs';
|
|
11
|
+
import { formatShellToolFailure } from './result-format.mjs';
|
|
12
|
+
|
|
13
|
+
/** `warn` runs the read with a note; `reject` returns the block without running. */
|
|
14
|
+
export const SHELL_FILE_READ_MODE = 'warn';
|
|
15
|
+
export const SHELL_FILE_READ_NOTE = 'Note: use the read / grep / list tools for files instead of the shell.';
|
|
16
|
+
const SHELL_FILE_READ_BLOCK =
|
|
17
|
+
'Blocked: use read / grep / list for files instead of the shell (read takes offset/limit for a window of a large file).';
|
|
18
|
+
|
|
19
|
+
const isPlainObject = (value) => value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
20
|
+
|
|
21
|
+
// ── 1. leading sleep ─────────────────────────────────────────────────────────
|
|
22
|
+
|
|
23
|
+
// Sub-2-second pacing stays allowed: only a bare whole-second sleep of 2 or
|
|
24
|
+
// more is refused. Float seconds, `-Milliseconds`, unit suffixes, pipelines,
|
|
25
|
+
// subshells and later statements are not matched.
|
|
26
|
+
const LEADING_SLEEP_MIN_SECONDS = 2;
|
|
27
|
+
// The first statement ends the command or is followed by `;`, `&&` or a newline.
|
|
28
|
+
const STATEMENT_END = String.raw`(?=\s*(?:$|;|&&|\r?\n))`;
|
|
29
|
+
// The argument stays on the command's line: a number on the next line is its own statement.
|
|
30
|
+
// PowerShell takes any prefix of `-Seconds` (`-s`, `-sec`, …) as the seconds parameter.
|
|
31
|
+
const POSIX_SLEEP_RE = new RegExp(String.raw`^\s*sleep[ \t]+(\d+)${STATEMENT_END}`);
|
|
32
|
+
const POWERSHELL_SLEEP_RE = new RegExp(
|
|
33
|
+
String.raw`^\s*(?:start-sleep|sleep)[ \t]+(?:-s(?:e(?:c(?:o(?:n(?:d(?:s)?)?)?)?)?)?[ \t:]+)?(\d+)${STATEMENT_END}`,
|
|
34
|
+
'i'
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
/** Whole seconds of the sleep the command starts with, or null when it does not start with one. */
|
|
38
|
+
function leadingSleepSeconds(command, shellType) {
|
|
39
|
+
const match = (shellType === 'powershell' ? POWERSHELL_SLEEP_RE : POSIX_SLEEP_RE).exec(String(command ?? ''));
|
|
40
|
+
return match ? Number(match[1]) : null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function leadingSleepFailure(command, shellType) {
|
|
44
|
+
const seconds = leadingSleepSeconds(command, shellType);
|
|
45
|
+
if (seconds === null || seconds < LEADING_SLEEP_MIN_SECONDS) return null;
|
|
46
|
+
return formatShellToolFailure(
|
|
47
|
+
`Blocked: the leading sleep of ${seconds} s was not run. For a long-running command use background:true; its completion arrives automatically. To wait for a specific task when the result is needed now, use task wait — do not poll in a sleep loop. A deliberate delay under ${LEADING_SLEEP_MIN_SECONDS} seconds is allowed.`
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// ── 2. leading cd → cwd ──────────────────────────────────────────────────────
|
|
52
|
+
|
|
53
|
+
// One plain path token: quoted (no variable or escape characters) or unquoted
|
|
54
|
+
// (no shell metacharacters, glob characters included), then `;` or `&&` and a remainder.
|
|
55
|
+
const CD_RE =
|
|
56
|
+
/^\s*(?:cd|set-location)\s+(?:-path\s+)?(?:"([^"$`]+)"|'([^'$`]+)'|([^\s;&|<>"'`$(){}*?[,@%#!]+))\s*(?:;|&&)\s*(\S[\s\S]*)$/i;
|
|
57
|
+
// `Set-Location -Path` expands wildcards even in a quoted path; a POSIX shell
|
|
58
|
+
// keeps a quoted glob literal, so only PowerShell leaves those unrewritten.
|
|
59
|
+
const POWERSHELL_WILDCARD_RE = /[*?[]/;
|
|
60
|
+
const CD_LIKE_RE = /^(?:cd|set-location|pushd|popd)(?:\s|;|&|$)/i;
|
|
61
|
+
|
|
62
|
+
/** `{ dir, rest }` for a command that starts with a plain `cd <dir>` and more, else null. */
|
|
63
|
+
function splitLeadingCd(command, shellType) {
|
|
64
|
+
const match = CD_RE.exec(String(command ?? ''));
|
|
65
|
+
if (!match) return null;
|
|
66
|
+
const dir = match[1] ?? match[2] ?? match[3];
|
|
67
|
+
const rest = match[4];
|
|
68
|
+
if (CD_LIKE_RE.test(rest)) return null;
|
|
69
|
+
if (dir.trim() === '' || dir.startsWith('-')) return null;
|
|
70
|
+
if (shellType === 'powershell' && POWERSHELL_WILDCARD_RE.test(dir)) return null;
|
|
71
|
+
// `~user` is another account's home in a shell, not a folder named so; a
|
|
72
|
+
// quoted `~` is a literal directory name, only an unquoted one is home.
|
|
73
|
+
if (dir.startsWith('~') && (match[3] === undefined || !/^~(?:[\\/]|$)/.test(dir))) return null;
|
|
74
|
+
// A POSIX backslash escapes; only single quotes keep it literal.
|
|
75
|
+
if (shellType !== 'powershell' && match[2] === undefined && dir.includes('\\')) return null;
|
|
76
|
+
return { dir, rest };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// ── 3. shell file reads ──────────────────────────────────────────────────────
|
|
80
|
+
|
|
81
|
+
const POWERSHELL_READERS = {
|
|
82
|
+
'get-content': 'read',
|
|
83
|
+
gc: 'read',
|
|
84
|
+
cat: 'read',
|
|
85
|
+
type: 'read',
|
|
86
|
+
'select-string': 'grep',
|
|
87
|
+
sls: 'grep',
|
|
88
|
+
'get-childitem': 'list',
|
|
89
|
+
gci: 'list',
|
|
90
|
+
ls: 'list',
|
|
91
|
+
dir: 'list',
|
|
92
|
+
rg: 'grep',
|
|
93
|
+
};
|
|
94
|
+
const POSIX_READERS = {
|
|
95
|
+
cat: 'read',
|
|
96
|
+
head: 'read',
|
|
97
|
+
tail: 'read',
|
|
98
|
+
less: 'read',
|
|
99
|
+
grep: 'grep',
|
|
100
|
+
rg: 'grep',
|
|
101
|
+
ls: 'list',
|
|
102
|
+
find: 'list',
|
|
103
|
+
};
|
|
104
|
+
// Flags whose next token is a path or pattern operand, and flags whose next
|
|
105
|
+
// token is a plain value; both are read off the operand count.
|
|
106
|
+
const OPERAND_FLAGS = new Set(['-path', '-literalpath', '-pattern', '-e', '--regexp', '-f', '--file']);
|
|
107
|
+
const VALUE_FLAGS = new Set(['-encoding', '-filter', '-include', '-exclude', '-g', '--glob', '-t', '--type']);
|
|
108
|
+
// A later pipeline stage that only shapes text; anything else is a program
|
|
109
|
+
// the first stage feeds.
|
|
110
|
+
const TEXT_FILTERS = new Set([
|
|
111
|
+
'select-object',
|
|
112
|
+
'select',
|
|
113
|
+
'select-string',
|
|
114
|
+
'sls',
|
|
115
|
+
'where-object',
|
|
116
|
+
'sort-object',
|
|
117
|
+
'sort',
|
|
118
|
+
'measure-object',
|
|
119
|
+
'format-table',
|
|
120
|
+
'format-list',
|
|
121
|
+
'ft',
|
|
122
|
+
'fl',
|
|
123
|
+
'out-string',
|
|
124
|
+
'out-host',
|
|
125
|
+
'head',
|
|
126
|
+
'tail',
|
|
127
|
+
'grep',
|
|
128
|
+
'egrep',
|
|
129
|
+
'rg',
|
|
130
|
+
'wc',
|
|
131
|
+
'uniq',
|
|
132
|
+
'cut',
|
|
133
|
+
'findstr',
|
|
134
|
+
]);
|
|
135
|
+
const FIND_WRITERS = new Set(['-exec', '-execdir', '-ok', '-okdir', '-delete', '-fprint', '-fprintf', '-fls']);
|
|
136
|
+
const BENIGN_REDIRECT_TARGET = /^(?:&\d|\$null|\/dev\/null|nul)$/i;
|
|
137
|
+
|
|
138
|
+
const commandName = (token) =>
|
|
139
|
+
String(token ?? '')
|
|
140
|
+
.toLowerCase()
|
|
141
|
+
.replace(/^.*[\\/]/, '')
|
|
142
|
+
.replace(/\.exe$/, '');
|
|
143
|
+
|
|
144
|
+
// The path/pattern operands of a stage, or null when it writes a file.
|
|
145
|
+
function stageOperands(args) {
|
|
146
|
+
const operands = [];
|
|
147
|
+
for (let i = 0; i < args.length; i++) {
|
|
148
|
+
const token = args[i];
|
|
149
|
+
if (token === '>' || token === '>>') {
|
|
150
|
+
if (!BENIGN_REDIRECT_TARGET.test(args[i + 1] ?? '')) return null;
|
|
151
|
+
i++;
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
const flag = token.toLowerCase();
|
|
155
|
+
if (flag.startsWith('-') && flag.length > 1) {
|
|
156
|
+
if (OPERAND_FLAGS.has(flag) && i + 1 < args.length) operands.push(args[++i]);
|
|
157
|
+
else if (VALUE_FLAGS.has(flag)) i++;
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
// A bare count (`head -n 5`, `tail -n +5`) is a flag value, not an operand.
|
|
161
|
+
if (!/^[+-]?\d+$/.test(token)) operands.push(token);
|
|
162
|
+
}
|
|
163
|
+
return operands;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* `{ tool, command }` when the command's first statement starts with a
|
|
168
|
+
* read-only file command on a path — the tool that does that job — else null.
|
|
169
|
+
* A pipeline whose later stage is a program, a write, and a first stage that
|
|
170
|
+
* reads piped input are not file reads.
|
|
171
|
+
*/
|
|
172
|
+
function detectShellFileRead(command, shellType) {
|
|
173
|
+
const first = shellSplitSegments(String(command ?? ''))[0];
|
|
174
|
+
if (!first) return null;
|
|
175
|
+
const stages = shellSplitPipelineSegments(first);
|
|
176
|
+
const tokens = shellTokenize(stages[0] ?? '');
|
|
177
|
+
if (!tokens || tokens.length === 0) return null;
|
|
178
|
+
const name = commandName(tokens[0]);
|
|
179
|
+
const tool = (shellType === 'powershell' ? POWERSHELL_READERS : POSIX_READERS)[name];
|
|
180
|
+
if (!tool) return null;
|
|
181
|
+
for (const stage of stages.slice(1)) {
|
|
182
|
+
if (!TEXT_FILTERS.has(commandName(stage.trim().split(/\s+/)[0]))) return null;
|
|
183
|
+
}
|
|
184
|
+
const args = tokens.slice(1);
|
|
185
|
+
if (name === 'find') {
|
|
186
|
+
const lowered = args.map((token) => token.toLowerCase());
|
|
187
|
+
const matchesNames = lowered.some((token) => ['-name', '-iname', '-path', '-regex'].includes(token));
|
|
188
|
+
return matchesNames && !lowered.some((token) => FIND_WRITERS.has(token)) ? { tool, command: name } : null;
|
|
189
|
+
}
|
|
190
|
+
const operands = stageOperands(args);
|
|
191
|
+
if (!operands) return null;
|
|
192
|
+
// A search names its pattern and then the path it reads; with one operand it reads piped input.
|
|
193
|
+
const minOperands = tool === 'grep' ? 2 : 1;
|
|
194
|
+
return operands.length >= minOperands ? { tool, command: name } : null;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// ── the guard ────────────────────────────────────────────────────────────────
|
|
198
|
+
|
|
199
|
+
/** The syntax family of the shell a call asks for (`args.shell`, as foreign adapters set it), else the default shell's. */
|
|
200
|
+
export function requestedShellType(args) {
|
|
201
|
+
const requested = typeof args?.shell === 'string' && args.shell ? resolveShellFor(args.shell) : null;
|
|
202
|
+
return (requested ?? resolveShellFor('default'))?.shellType;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function recordFileRead(telemetry, entry) {
|
|
206
|
+
if (!telemetry || typeof telemetry !== 'object') return;
|
|
207
|
+
if (!Array.isArray(telemetry.shellMisuse)) telemetry.shellMisuse = [];
|
|
208
|
+
telemetry.shellMisuse.push({ kind: 'file-read', ...entry });
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Apply the three guards to a shell call.
|
|
213
|
+
* @returns {{ failure: string } | { args: object, notes: string[] }} the
|
|
214
|
+
* rejection, or the call to run (a leading `cd` moved into `cwd`) with the
|
|
215
|
+
* lines to add to its result.
|
|
216
|
+
*/
|
|
217
|
+
export function guardShellCall(
|
|
218
|
+
args,
|
|
219
|
+
{ shellType, fileReadMode = SHELL_FILE_READ_MODE, agent = null, sessionId = null, telemetry = null } = {}
|
|
220
|
+
) {
|
|
221
|
+
if (!isPlainObject(args) || typeof args.command !== 'string') return { args, notes: [] };
|
|
222
|
+
const notes = [];
|
|
223
|
+
let guarded = args;
|
|
224
|
+
const moved = args.cwd == null ? splitLeadingCd(args.command, shellType) : null;
|
|
225
|
+
if (moved) {
|
|
226
|
+
guarded = { ...args, command: moved.rest, cwd: moved.dir };
|
|
227
|
+
notes.push(`Moved \`cd ${moved.dir}\` into cwd.`);
|
|
228
|
+
}
|
|
229
|
+
if (args.background !== true) {
|
|
230
|
+
const sleepFailure = leadingSleepFailure(guarded.command, shellType);
|
|
231
|
+
if (sleepFailure) return { failure: sleepFailure };
|
|
232
|
+
}
|
|
233
|
+
const read = detectShellFileRead(guarded.command, shellType);
|
|
234
|
+
if (read) {
|
|
235
|
+
recordFileRead(telemetry, { mode: fileReadMode, tool: read.tool, command: read.command, agent, sessionId });
|
|
236
|
+
if (fileReadMode === 'reject') return { failure: formatShellToolFailure(SHELL_FILE_READ_BLOCK) };
|
|
237
|
+
notes.push(SHELL_FILE_READ_NOTE);
|
|
238
|
+
}
|
|
239
|
+
return { args: guarded, notes };
|
|
240
|
+
}
|
|
@@ -118,7 +118,7 @@ const _PS_UNIX_EQUIVALENTS = {
|
|
|
118
118
|
head: 'Select-Object -First N',
|
|
119
119
|
tail: 'Select-Object -Last N',
|
|
120
120
|
wc: 'Measure-Object -Line',
|
|
121
|
-
grep: '
|
|
121
|
+
grep: 'the grep tool',
|
|
122
122
|
sed: 'the edit tool',
|
|
123
123
|
awk: 'ForEach-Object / the edit tool',
|
|
124
124
|
pgrep: 'Get-Process -Name <name>',
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// The shell tool's optional `cwd` argument: where one command runs. Omitted,
|
|
2
|
+
// the command runs in the session cwd; a relative value resolves against it.
|
|
3
|
+
import { stat } from 'node:fs/promises';
|
|
4
|
+
import { homedir } from 'node:os';
|
|
5
|
+
import { resolve } from 'node:path';
|
|
6
|
+
|
|
7
|
+
// `~`, `~/x` (and `~\x` on Windows) name the user's home folder.
|
|
8
|
+
function expandHome(path) {
|
|
9
|
+
if (path === '~') return homedir();
|
|
10
|
+
if (path.startsWith('~/') || (process.platform === 'win32' && path.startsWith('~\\'))) {
|
|
11
|
+
return resolve(homedir(), path.slice(2));
|
|
12
|
+
}
|
|
13
|
+
return path;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** The directory a shell call runs in: its `cwd` argument resolved against the session cwd. */
|
|
17
|
+
export function effectiveShellCwd(args, sessionCwd) {
|
|
18
|
+
const requested = args?.cwd;
|
|
19
|
+
// Trim only decides blank; a name with edge spaces is used as given.
|
|
20
|
+
if (typeof requested !== 'string' || requested.trim() === '') return sessionCwd;
|
|
21
|
+
return resolve(sessionCwd || process.cwd(), expandHome(requested));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** The cwd hooks and approvals see for a tool call: the effective one for shell, the session cwd otherwise. */
|
|
25
|
+
export function effectiveToolCwd(toolName, args, sessionCwd) {
|
|
26
|
+
return toolName === 'shell' ? effectiveShellCwd(args, sessionCwd) : sessionCwd;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** An error naming the path when `dir` is not an existing directory, else null. */
|
|
30
|
+
export async function shellCwdError(dir) {
|
|
31
|
+
let info;
|
|
32
|
+
try {
|
|
33
|
+
info = await stat(dir);
|
|
34
|
+
} catch {
|
|
35
|
+
return `shell cwd "${dir}" does not exist`;
|
|
36
|
+
}
|
|
37
|
+
return info.isDirectory() ? null : `shell cwd "${dir}" is not a directory`;
|
|
38
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { applySessionScratchEnv } from '../../../../../shared/session-scratch.mjs';
|
|
1
2
|
import { withSkillLauncherPath } from '../../../../../shared/skill-script-runtime.mjs';
|
|
2
3
|
import {
|
|
3
4
|
applyShellEgressPolicy,
|
|
@@ -6,7 +7,8 @@ import {
|
|
|
6
7
|
scrubRuntimeRootVars,
|
|
7
8
|
} from '../../env-scrub.mjs';
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
// `sessionId` points TEMP/TMP/TMPDIR at that session's scratch directory.
|
|
11
|
+
export function buildShellSpawnEnv(cwd, baseEnv = process.env, sessionId = null) {
|
|
10
12
|
const spawnEnv = {
|
|
11
13
|
...baseEnv,
|
|
12
14
|
LANG: 'C.UTF-8',
|
|
@@ -24,5 +26,5 @@ export function buildShellSpawnEnv(cwd, baseEnv = process.env) {
|
|
|
24
26
|
// `mixdog-skill-node` (a skill's ${MIXDOG_SKILL_NODE}) resolves in every
|
|
25
27
|
// model shell; only this env gets the entry, never the daemon's own.
|
|
26
28
|
withSkillLauncherPath(spawnEnv);
|
|
27
|
-
return spawnEnv;
|
|
29
|
+
return applySessionScratchEnv(spawnEnv, sessionId);
|
|
28
30
|
}
|
|
@@ -25,6 +25,8 @@ import { planShellDeadlines } from './bash-tool/deadline-plan.mjs';
|
|
|
25
25
|
import { planShellInvocation } from './bash-tool/invocation-plan.mjs';
|
|
26
26
|
import { renderBackgroundedResult } from './bash-tool/backgrounded-result.mjs';
|
|
27
27
|
import { renderCompletedResult } from './bash-tool/completed-result.mjs';
|
|
28
|
+
import { effectiveShellCwd, shellCwdError } from './bash-tool/shell-cwd.mjs';
|
|
29
|
+
import { guardShellCall, requestedShellType } from './bash-tool/misuse-guard.mjs';
|
|
28
30
|
|
|
29
31
|
export {
|
|
30
32
|
SURVIVING_DESCENDANTS_WARNING,
|
|
@@ -64,9 +66,26 @@ function settleMutationCaches(shellEffects, backgroundJobId, runSettled = null)
|
|
|
64
66
|
}
|
|
65
67
|
|
|
66
68
|
export async function executeBashTool(args, workDir, options = {}) {
|
|
67
|
-
//
|
|
68
|
-
//
|
|
69
|
-
const
|
|
69
|
+
// The tool-exec layer already guarded the call before its hooks ran and left
|
|
70
|
+
// its notes; a direct caller is guarded here.
|
|
71
|
+
const guarded = Array.isArray(options?.shellGuardNotes)
|
|
72
|
+
? { args, notes: options.shellGuardNotes }
|
|
73
|
+
: guardShellCall(args, {
|
|
74
|
+
shellType: requestedShellType(args),
|
|
75
|
+
agent: options?.agent,
|
|
76
|
+
sessionId: options?.sessionId,
|
|
77
|
+
telemetry: options?.resultTelemetry,
|
|
78
|
+
});
|
|
79
|
+
if (guarded.failure) return guarded.failure;
|
|
80
|
+
args = guarded.args;
|
|
81
|
+
const guardNotes = guarded.notes;
|
|
82
|
+
// A call starts from the current Project root unless it names a `cwd`. A
|
|
83
|
+
// command-local `cd` never creates a second session cwd authority beside it.
|
|
84
|
+
const bashWorkDir = effectiveShellCwd(args, workDir);
|
|
85
|
+
if (bashWorkDir !== workDir) {
|
|
86
|
+
const cwdError = await shellCwdError(bashWorkDir);
|
|
87
|
+
if (cwdError) return formatShellToolFailure(cwdError);
|
|
88
|
+
}
|
|
70
89
|
// Approval comes from the runtime's options, never from model-supplied args.
|
|
71
90
|
const elevationApproved = options?.elevationApproved === true;
|
|
72
91
|
const prepared = prepareShellCommand(args, { elevationApproved });
|
|
@@ -97,7 +116,12 @@ export async function executeBashTool(args, workDir, options = {}) {
|
|
|
97
116
|
// A queued run, or a foreground tree that may outlive its result, settles later.
|
|
98
117
|
let runSettled = null;
|
|
99
118
|
try {
|
|
100
|
-
const invocation = await planShellInvocation({
|
|
119
|
+
const invocation = await planShellInvocation({
|
|
120
|
+
command,
|
|
121
|
+
resolvedSpec,
|
|
122
|
+
cwd: bashWorkDir,
|
|
123
|
+
sessionId: options?.callerSessionId || options?.sessionId || null,
|
|
124
|
+
});
|
|
101
125
|
if (invocation.failure) return invocation.failure;
|
|
102
126
|
combinedAbort = combineAbortSignals(await sessionAbortSignal(options?.sessionId), options?.abortSignal || null);
|
|
103
127
|
const startedAtMs = Date.now();
|
|
@@ -106,6 +130,7 @@ export async function executeBashTool(args, workDir, options = {}) {
|
|
|
106
130
|
shellArg: invocation.execShellArg,
|
|
107
131
|
shellArgs: invocation.execShellArgs,
|
|
108
132
|
command: invocation.wrappedCommand,
|
|
133
|
+
displayCommand: command,
|
|
109
134
|
execScript: invocation.execScript,
|
|
110
135
|
directArgv: invocation.directArgv,
|
|
111
136
|
elevationApproved,
|
|
@@ -147,12 +172,12 @@ export async function executeBashTool(args, workDir, options = {}) {
|
|
|
147
172
|
stdout,
|
|
148
173
|
stderr,
|
|
149
174
|
};
|
|
150
|
-
if (backgrounded) return renderBackgroundedResult(rendering);
|
|
175
|
+
if (backgrounded) return renderBackgroundedResult({ ...rendering, notes: guardNotes.join('\n') });
|
|
151
176
|
return renderCompletedResult({
|
|
152
177
|
...rendering,
|
|
153
178
|
analysisCommand,
|
|
154
179
|
timeout: deadlines.timeout,
|
|
155
|
-
rewriteNote: [wmicRewrite?.note, bashismRewrite?.note].filter(Boolean).join('\n'),
|
|
180
|
+
rewriteNote: [wmicRewrite?.note, bashismRewrite?.note, ...guardNotes].filter(Boolean).join('\n'),
|
|
156
181
|
});
|
|
157
182
|
} finally {
|
|
158
183
|
inputWake?.dispose();
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// behavior, argument shapes, and the usage boundaries that only apply to that
|
|
6
6
|
// tool; cross-tool policy lives in rules/shared/*.md.
|
|
7
7
|
// Platform-specific command syntax belongs next to the command argument.
|
|
8
|
-
import { GIT_TOOL_DEF } from './git-command-tool.mjs';
|
|
8
|
+
import { GIT_AGENT_TOOL_DEF, GIT_TOOL_DEF } from './git-command-tool.mjs';
|
|
9
9
|
import { PUBLIC_PATH_BATCH_LIMIT, PUBLIC_READ_WINDOW_MAX } from './arg-guard.mjs';
|
|
10
10
|
import { GITHUB_TOOL_DEF } from '../../../../github/tool.mjs';
|
|
11
11
|
import { envFlag } from '../../../../shared/env.mjs';
|
|
@@ -27,13 +27,71 @@ export const TASK_WAIT_TIMEOUT_DEFAULT_MS = TASK_WAIT_DEFAULT_MS;
|
|
|
27
27
|
export const TASK_WAIT_TIMEOUT_MIN_MS = TASK_WAIT_MIN_MS;
|
|
28
28
|
export const TASK_WAIT_TIMEOUT_MAX_MS = TASK_WAIT_MAX_MS;
|
|
29
29
|
const _holdS = budgetSeconds(SHELL_HOLD_DEFAULT_MS);
|
|
30
|
-
const _shellSyntaxCheat =
|
|
31
|
-
process.platform === 'win32'
|
|
32
|
-
? " PowerShell: ; between independent commands, if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } between dependent ones; no heredoc, </dev/null or | head/tail/wc (Select-Object -First/-Last); multiline python/node via @'…'@ | python - (node -); 2>$null; /c/→C:\\; $PID is reserved."
|
|
33
|
-
: ' Bash: chain dependent commands with &&; multiline input via a quoted heredoc delimiter, not extra quoting/escape layers.';
|
|
34
30
|
// Process-stable switch used to describe foreground-only execution accurately.
|
|
35
31
|
const _shellBackgroundDisabled = envFlag('MIXDOG_SHELL_DISABLE_BACKGROUND_TASKS');
|
|
36
32
|
|
|
33
|
+
// Shell kinds the description is written for: 'powershell' or 'posix' (bash,
|
|
34
|
+
// zsh, sh, Git Bash, WSL), the `shellType` of the runtime's resolved shell.
|
|
35
|
+
// BUILTIN_TOOLS is static, so it carries the platform's default kind; a
|
|
36
|
+
// session whose configured system shell is the other kind gets the matching
|
|
37
|
+
// text through bindShellKind where the session tool schema is assembled.
|
|
38
|
+
const _defaultShellKind = process.platform === 'win32' ? 'powershell' : 'posix';
|
|
39
|
+
|
|
40
|
+
// The kind's banned commands → replacement tool. `edit/apply_patch` is
|
|
41
|
+
// rewritten per model by the edit-dialect surface filter.
|
|
42
|
+
export function buildShellRoutingRules(kind = _defaultShellKind) {
|
|
43
|
+
const pairs =
|
|
44
|
+
kind === 'powershell'
|
|
45
|
+
? 'Get-Content/gc/cat/type→read; Get-ChildItem/dir/ls→list/glob/find; Select-String/findstr→grep; Set-Content/Add-Content/Out-File/`>`→edit/apply_patch'
|
|
46
|
+
: 'cat/head/tail/less→read; ls/tree→list; find→glob/find; grep/rg/ag→grep; file authoring via sed/awk/echo >/tee/heredoc→edit/apply_patch';
|
|
47
|
+
return `Never use shell commands/scripts for work other tools cover: ${pairs}; git→git (-C <dir> for other folders); code structure→code_graph.`;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function buildShellDescription(kind) {
|
|
51
|
+
const run = _shellBackgroundDisabled
|
|
52
|
+
? 'Commands run in the foreground until completion.'
|
|
53
|
+
: `Holds ${_holdS}s; then, or on input/task notification, backgrounds with task_id (command keeps running). Completion is automatic; never poll, and never sleep/poll-loop inside the shell (background:true or wait_ms instead; for an external job, background a command that exits when it ends). Result needed now: task wait. Independent long runs: background:true; cancel when done.`;
|
|
54
|
+
return `Run programs, builds, tests and computation. ${buildShellRoutingRules(kind)} ${run}`;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function buildShellCommandDescription(kind) {
|
|
58
|
+
const cheat =
|
|
59
|
+
kind === 'powershell'
|
|
60
|
+
? " PowerShell: ; between independent commands, if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } between dependent ones; no Bash heredocs or </dev/null; Select-Object shapes program output, not file reads; multiline python/node via @'…'@ | python - (node -); 2>$null; /c/→C:\\; $PID is reserved."
|
|
61
|
+
: ' Bash: chain dependent commands with &&; multiline input via a quoted heredoc delimiter, not extra quoting/escape layers.';
|
|
62
|
+
return `Command.${cheat}`;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// One bound copy per (tool, kind), so a session's shell tool keeps its identity
|
|
66
|
+
// and bytes from turn to turn.
|
|
67
|
+
const _boundShellTools = new WeakMap();
|
|
68
|
+
|
|
69
|
+
/** The shell tool with the text of `kind`, when that differs from the static default. */
|
|
70
|
+
export function bindShellKind(tool, kind) {
|
|
71
|
+
if (tool?.name !== 'shell' || kind === _defaultShellKind || (kind !== 'powershell' && kind !== 'posix')) return tool;
|
|
72
|
+
const cached = _boundShellTools.get(tool)?.get(kind);
|
|
73
|
+
if (cached) return cached;
|
|
74
|
+
const properties = tool.inputSchema?.properties || {};
|
|
75
|
+
const bound = {
|
|
76
|
+
...tool,
|
|
77
|
+
description: buildShellDescription(kind),
|
|
78
|
+
inputSchema: {
|
|
79
|
+
...tool.inputSchema,
|
|
80
|
+
properties: {
|
|
81
|
+
...properties,
|
|
82
|
+
command: { ...properties.command, description: buildShellCommandDescription(kind) },
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
if (!_boundShellTools.has(tool)) _boundShellTools.set(tool, new Map());
|
|
87
|
+
_boundShellTools.get(tool).set(kind, bound);
|
|
88
|
+
return bound;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function taskTimeoutDescription(defaultMs) {
|
|
92
|
+
return `Wait ceiling in ms; else current output at the ceiling. Default ${defaultMs}; clamped to ${TASK_WAIT_TIMEOUT_MIN_MS}-${TASK_WAIT_TIMEOUT_MAX_MS}.`;
|
|
93
|
+
}
|
|
94
|
+
|
|
37
95
|
export const BUILTIN_TOOLS = [
|
|
38
96
|
{
|
|
39
97
|
name: 'read',
|
|
@@ -47,7 +105,7 @@ export const BUILTIN_TOOLS = [
|
|
|
47
105
|
compressible: false,
|
|
48
106
|
},
|
|
49
107
|
description:
|
|
50
|
-
"Read file windows or images. One call per read stage: {file_path, offset, limit} entries for every located site
|
|
108
|
+
"Read file windows or images. One call per read stage: {file_path, offset, limit} entries for every located site, never a whole large file. Content in context is never read again. Missing paths are reported, never replaced. Directories: list. Binaries: bounded hex. Rows carry no line numbers; `[lines a-b]` gives each block's range. Never count rows: before writing a line number, copy it from grep, code_graph or git diff output; otherwise cite path and symbol.",
|
|
51
109
|
inputSchema: {
|
|
52
110
|
type: 'object',
|
|
53
111
|
properties: {
|
|
@@ -75,8 +133,7 @@ export const BUILTIN_TOOLS = [
|
|
|
75
133
|
},
|
|
76
134
|
},
|
|
77
135
|
],
|
|
78
|
-
description:
|
|
79
|
-
'Path(s) or {file_path, offset, limit} entries; overlapping windows of one file merge. A glob fans out to ≤10 newest files, 25 lines each.',
|
|
136
|
+
description: 'Overlapping windows of one file merge. A glob fans out to ≤10 newest files.',
|
|
80
137
|
},
|
|
81
138
|
offset: {
|
|
82
139
|
type: 'integer',
|
|
@@ -113,14 +170,11 @@ export const BUILTIN_TOOLS = [
|
|
|
113
170
|
compressibleLossless: true,
|
|
114
171
|
},
|
|
115
172
|
description:
|
|
116
|
-
'Replace exact text in one file. old_string must match once unless replace_all is true. Every non-overlapping edit of the stage in one response, using existing text, not text another edit creates; many files → one edit per file
|
|
173
|
+
'Replace exact text in one file. old_string must match once unless replace_all is true. Every non-overlapping edit of the stage in one response, using existing text, not text another edit creates; many files → one edit per file. Widened replacements keep intervening lines verbatim.',
|
|
117
174
|
inputSchema: {
|
|
118
175
|
type: 'object',
|
|
119
176
|
properties: {
|
|
120
|
-
file_path: {
|
|
121
|
-
type: 'string',
|
|
122
|
-
description: 'Path to the file to modify.',
|
|
123
|
-
},
|
|
177
|
+
file_path: { type: 'string' },
|
|
124
178
|
old_string: {
|
|
125
179
|
type: 'string',
|
|
126
180
|
description:
|
|
@@ -133,7 +187,7 @@ export const BUILTIN_TOOLS = [
|
|
|
133
187
|
replace_all: {
|
|
134
188
|
type: 'boolean',
|
|
135
189
|
default: false,
|
|
136
|
-
description: 'Replace all occurrences of old_string
|
|
190
|
+
description: 'Replace all occurrences of old_string.',
|
|
137
191
|
},
|
|
138
192
|
},
|
|
139
193
|
required: ['file_path', 'old_string', 'new_string'],
|
|
@@ -151,11 +205,15 @@ export const BUILTIN_TOOLS = [
|
|
|
151
205
|
openWorldHint: true,
|
|
152
206
|
compressible: true,
|
|
153
207
|
},
|
|
154
|
-
description:
|
|
208
|
+
description: buildShellDescription(_defaultShellKind),
|
|
155
209
|
inputSchema: {
|
|
156
210
|
type: 'object',
|
|
157
211
|
properties: {
|
|
158
|
-
command: { type: 'string', description:
|
|
212
|
+
command: { type: 'string', description: buildShellCommandDescription(_defaultShellKind) },
|
|
213
|
+
cwd: {
|
|
214
|
+
type: 'string',
|
|
215
|
+
description: 'Working directory; default the Project. Use it instead of cd/Set-Location.',
|
|
216
|
+
},
|
|
159
217
|
timeout_ms: {
|
|
160
218
|
type: 'integer',
|
|
161
219
|
minimum: 0,
|
|
@@ -165,7 +223,7 @@ export const BUILTIN_TOOLS = [
|
|
|
165
223
|
type: 'integer',
|
|
166
224
|
minimum: SHELL_HOLD_MIN_MS,
|
|
167
225
|
maximum: SHELL_HOLD_MAX_MS,
|
|
168
|
-
description: `Hold in ms before a still-running command moves to the background (default ${SHELL_HOLD_DEFAULT_MS}). Usually omit.`,
|
|
226
|
+
description: `Hold in ms before a still-running command moves to the background (default ${SHELL_HOLD_DEFAULT_MS}). Usually omit; for a long finite command needed next, set up to ${SHELL_HOLD_MAX_MS}.`,
|
|
169
227
|
},
|
|
170
228
|
background: {
|
|
171
229
|
type: 'boolean',
|
|
@@ -196,7 +254,7 @@ export const BUILTIN_TOOLS = [
|
|
|
196
254
|
openWorldHint: false,
|
|
197
255
|
},
|
|
198
256
|
description:
|
|
199
|
-
'Manage shell tasks. Completion is delivered automatically; wait only when you need the result now, never poll with read. wait returns when the task finishes, or when new user input or any task notification arrives (the task keeps running). read/wait return new output, prioritizing the tail on completion.
|
|
257
|
+
'Manage shell tasks. Completion is delivered automatically; wait only when you need the result now, never poll with read. wait returns when the task finishes, or when new user input or any task notification arrives (the task keeps running). read/wait return new output, prioritizing the tail on completion. Use read on the log path for omitted content.',
|
|
200
258
|
inputSchema: {
|
|
201
259
|
type: 'object',
|
|
202
260
|
properties: {
|
|
@@ -209,13 +267,13 @@ export const BUILTIN_TOOLS = [
|
|
|
209
267
|
timeout_ms: {
|
|
210
268
|
type: 'integer',
|
|
211
269
|
minimum: 0,
|
|
212
|
-
description:
|
|
270
|
+
description: taskTimeoutDescription(TASK_WAIT_TIMEOUT_DEFAULT_MS),
|
|
213
271
|
},
|
|
214
272
|
output: {
|
|
215
273
|
type: 'string',
|
|
216
274
|
enum: ['new', 'tail'],
|
|
217
275
|
description:
|
|
218
|
-
'read/wait only. Default new; tail
|
|
276
|
+
'read/wait only. Default new; tail re-reads recent output without advancing the cursor, after an interruption or context loss. Up to 8 KiB per stream while running, 12 KiB on completion or replay; original logs are preserved.',
|
|
219
277
|
},
|
|
220
278
|
},
|
|
221
279
|
required: ['action'],
|
|
@@ -266,7 +324,7 @@ export const BUILTIN_TOOLS = [
|
|
|
266
324
|
description:
|
|
267
325
|
'Requested results; default 250; 0 unlimited. Context output caps at 40 blocks; continue via the returned offset.',
|
|
268
326
|
},
|
|
269
|
-
offset: { type: 'integer', minimum: 0
|
|
327
|
+
offset: { type: 'integer', minimum: 0 },
|
|
270
328
|
context: {
|
|
271
329
|
type: 'integer',
|
|
272
330
|
minimum: 0,
|
|
@@ -298,7 +356,7 @@ export const BUILTIN_TOOLS = [
|
|
|
298
356
|
compressible: true,
|
|
299
357
|
},
|
|
300
358
|
description:
|
|
301
|
-
'Wildcard file-path lookup under a known directory; directories never match.
|
|
359
|
+
'Wildcard file-path lookup under a known directory; directories never match. No preliminary listing. Unknown base: find first with a known path fragment.',
|
|
302
360
|
inputSchema: {
|
|
303
361
|
type: 'object',
|
|
304
362
|
properties: {
|
|
@@ -316,7 +374,7 @@ export const BUILTIN_TOOLS = [
|
|
|
316
374
|
description: 'mtime default (newest first); natural = raw walk order, cheaper on huge trees.',
|
|
317
375
|
},
|
|
318
376
|
limit: { type: 'integer', minimum: 0, description: 'Max entries; default 100; 0 unlimited.' },
|
|
319
|
-
offset: { type: 'integer', minimum: 0
|
|
377
|
+
offset: { type: 'integer', minimum: 0 },
|
|
320
378
|
include_noise: {
|
|
321
379
|
type: 'boolean',
|
|
322
380
|
description: 'Also search gitignored trees.',
|
|
@@ -346,7 +404,7 @@ export const BUILTIN_TOOLS = [
|
|
|
346
404
|
type: 'string',
|
|
347
405
|
minLength: 1,
|
|
348
406
|
pattern: '\\S',
|
|
349
|
-
description: '
|
|
407
|
+
description: 'Filename/path fragment; space-separated fragments AND-match within one path.',
|
|
350
408
|
},
|
|
351
409
|
path: { type: 'string', description: 'Base directory; omit for the current Project.' },
|
|
352
410
|
limit: { type: 'integer', minimum: 0, description: 'Max paths; default 25; 0 unlimited.' },
|
|
@@ -387,10 +445,36 @@ export const BUILTIN_TOOLS = [
|
|
|
387
445
|
maximum: 100,
|
|
388
446
|
description: 'Max entries; default 100; 0 = no page cap (absolute cap still applies).',
|
|
389
447
|
},
|
|
390
|
-
offset: { type: 'integer', minimum: 0
|
|
448
|
+
offset: { type: 'integer', minimum: 0 },
|
|
391
449
|
},
|
|
392
|
-
required: [],
|
|
393
450
|
additionalProperties: false,
|
|
394
451
|
},
|
|
395
452
|
},
|
|
396
453
|
];
|
|
454
|
+
|
|
455
|
+
// What a delegated agent's session sees of the tools whose text differs from
|
|
456
|
+
// the Lead's: git (worktree operations are Lead-only) and task (the agent wait
|
|
457
|
+
// default). Keyed by the shared definition, so a rebuilt list binds once.
|
|
458
|
+
const _taskTool = BUILTIN_TOOLS.find((tool) => tool.name === 'task');
|
|
459
|
+
const _agentTaskTool = {
|
|
460
|
+
..._taskTool,
|
|
461
|
+
inputSchema: {
|
|
462
|
+
..._taskTool.inputSchema,
|
|
463
|
+
properties: {
|
|
464
|
+
..._taskTool.inputSchema.properties,
|
|
465
|
+
timeout_ms: {
|
|
466
|
+
..._taskTool.inputSchema.properties.timeout_ms,
|
|
467
|
+
description: taskTimeoutDescription(AGENT_TASK_WAIT_DEFAULT_MS),
|
|
468
|
+
},
|
|
469
|
+
},
|
|
470
|
+
},
|
|
471
|
+
};
|
|
472
|
+
const _agentToolVariants = new Map([
|
|
473
|
+
[GIT_TOOL_DEF, GIT_AGENT_TOOL_DEF],
|
|
474
|
+
[_taskTool, _agentTaskTool],
|
|
475
|
+
]);
|
|
476
|
+
|
|
477
|
+
/** The agent-session variant of `tool`, or `tool` itself when it has none. */
|
|
478
|
+
export function bindAgentOwner(tool) {
|
|
479
|
+
return _agentToolVariants.get(tool) ?? tool;
|
|
480
|
+
}
|
|
@@ -324,7 +324,13 @@ export function rawContentCacheSet(fullPath, stat, rawBuf, now = Date.now()) {
|
|
|
324
324
|
if (!canPublishReadCache(fullPath)) return;
|
|
325
325
|
if (!fullPath || !Buffer.isBuffer(rawBuf)) return;
|
|
326
326
|
const version = fileVersion(stat);
|
|
327
|
-
if (
|
|
327
|
+
if (
|
|
328
|
+
!version ||
|
|
329
|
+
!canCacheReadFile(version) ||
|
|
330
|
+
rawBuf.length !== version.size ||
|
|
331
|
+
rawBuf.length > RAW_CONTENT_CACHE_MAX_BYTES
|
|
332
|
+
)
|
|
333
|
+
return;
|
|
328
334
|
const key = canonicalCachePath(fullPath);
|
|
329
335
|
rawContentCacheDelete(key);
|
|
330
336
|
RAW_CONTENT_CACHE.set(key, {
|