mixdog 1.2.5 → 1.3.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/LICENSES/simple-icons-CC0-1.0.txt +30 -0
- package/NOTICE.md +19 -0
- package/package.json +4 -1
- package/scripts/check-model-recommendations.mjs +89 -0
- package/scripts/gate-local.mjs +7 -0
- package/scripts/lib/gate-scheduler.mjs +2 -2
- package/scripts/lib/isolated-test-env.mjs +16 -0
- package/scripts/lib/run-node-tests.mjs +5 -14
- package/scripts/provider-pingpong-live.mjs +9 -9
- package/src/agents/advisor/AGENT.md +4 -4
- package/src/agents/advisor/agent.json +1 -1
- package/src/agents/reviewer/AGENT.md +5 -4
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +17 -0
- package/src/defaults/skills/browser-use/SKILL.md +7 -1
- package/src/defaults/skills/computer-use/SKILL.md +3 -1
- package/src/defaults/skills/memory-management/SKILL.md +4 -1
- package/src/defaults/skills/setup/references/actions.md +11 -4
- package/src/defaults/skills/setup-guide/SKILL.md +175 -0
- package/src/defaults/skills/setup-guide/model-recommendations.json +333 -0
- package/src/defaults/skills/visualize/SKILL.md +3 -2
- package/src/lib/rules-builder.cjs +56 -7
- package/src/output-styles/common.md +22 -6
- package/src/output-styles/detailed.md +7 -5
- package/src/output-styles/minimal.md +7 -3
- package/src/output-styles/simple.md +2 -3
- package/src/rules/agent/AGENT.md +7 -1
- package/src/rules/agent-mode/AGENT_MODE.md +24 -0
- package/src/rules/agent-mode/MIXY.md +21 -0
- package/src/rules/agent-mode/ROUTINE.md +6 -0
- package/src/rules/lead/LEAD.md +9 -4
- package/src/rules/shared/10-tool-workflow.md +2 -1
- package/src/rules/shared/60-verification.md +4 -5
- package/src/rules/shared/70-delivery.md +3 -0
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -1
- package/src/runtime/agent/orchestrator/agent-runtime/room-supervisor-completion.mjs +86 -0
- package/src/runtime/agent/orchestrator/config.mjs +6 -0
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +77 -14
- package/src/runtime/agent/orchestrator/context/role-instructions.mjs +182 -13
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +5 -3
- package/src/runtime/agent/orchestrator/internal-agents.mjs +10 -0
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +215 -0
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +58 -64
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +10 -1
- package/src/runtime/agent/orchestrator/mcp/client.mjs +122 -15
- package/src/runtime/agent/orchestrator/mcp/oauth-account.mjs +97 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +2 -3
- package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +49 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +59 -9
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +32 -7
- package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +45 -6
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +195 -6
- package/src/runtime/agent/orchestrator/mcp/server-connectors.mjs +17 -0
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +41 -19
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +11 -5
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/catalog-deadline.mjs +163 -0
- package/src/runtime/agent/orchestrator/providers/catalog-failures.mjs +34 -0
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +38 -14
- package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +100 -26
- package/src/runtime/agent/orchestrator/providers/lib/send-callbacks.mjs +24 -0
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +13 -0
- package/src/runtime/agent/orchestrator/providers/oauth-usage.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 +4 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +49 -4
- package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +0 -7
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +17 -12
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +5 -1
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +11 -2
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +45 -16
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +10 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-connect.mjs +196 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +74 -9
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +14 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth-login.mjs +194 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth-tokens.mjs +353 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +293 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-usage.mjs +33 -100
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +23 -14
- package/src/runtime/agent/orchestrator/providers/registry.mjs +41 -27
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +98 -4
- package/src/runtime/agent/orchestrator/runtime-core/context-status-shape.mjs +4 -0
- package/src/runtime/agent/orchestrator/runtime-core/extension-scopes.mjs +6 -4
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +15 -8
- package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +1 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +12 -6
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +32 -5
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +10 -4
- package/src/runtime/agent/orchestrator/runtime-core/workflow/agents.mjs +4 -1
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +50 -20
- package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/agent-home.d.mts +4 -0
- package/src/runtime/agent/orchestrator/session/agent-home.mjs +33 -0
- package/src/runtime/agent/orchestrator/session/agent-mode.mjs +62 -0
- package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +15 -3
- package/src/runtime/agent/orchestrator/session/agent-room-supervisor.d.mts +31 -0
- package/src/runtime/agent/orchestrator/session/agent-room-supervisor.mjs +241 -0
- package/src/runtime/agent/orchestrator/session/agent-room.d.mts +162 -0
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +641 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +7 -1
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +74 -13
- package/src/runtime/agent/orchestrator/session/compact/forked-summary.mjs +102 -0
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +8 -2
- package/src/runtime/agent/orchestrator/session/compact/summary.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +165 -0
- package/src/runtime/agent/orchestrator/session/human-gate/held-message.mjs +95 -0
- package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +221 -0
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +195 -0
- package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +167 -0
- package/src/runtime/agent/orchestrator/session/lifecycle-scan.mjs +9 -0
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +39 -2
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +16 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +82 -33
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +11 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +5 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +13 -3
- package/src/runtime/agent/orchestrator/session/loop/usage.mjs +7 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +6 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +13 -5
- package/src/runtime/agent/orchestrator/session/manager/pending-lifecycle-epoch.mjs +0 -8
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +10 -7
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +62 -22
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +44 -16
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +22 -5
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +23 -1
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +81 -34
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +39 -4
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +27 -5
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +55 -8
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/manager/workflow-switch-notice.mjs +58 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/mixy-name.mjs +24 -0
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +32 -5
- package/src/runtime/agent/orchestrator/session/request-fork.mjs +47 -0
- package/src/runtime/agent/orchestrator/session/routine-result.d.mts +70 -0
- package/src/runtime/agent/orchestrator/session/routine-result.mjs +277 -0
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +16 -1
- package/src/runtime/agent/orchestrator/session/side-question.mjs +5 -43
- package/src/runtime/agent/orchestrator/session/store/fs-probe.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +73 -6
- package/src/runtime/agent/orchestrator/session/store/load-session.mjs +40 -0
- package/src/runtime/agent/orchestrator/session/store/save-fault.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/store/session-paths.mjs +12 -0
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-header.mjs +36 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +258 -43
- package/src/runtime/agent/orchestrator/session/store-record-strict-scan.mjs +325 -0
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +84 -21
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +44 -12
- package/src/runtime/agent/orchestrator/session/store-summary-last-message.mjs +46 -0
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +46 -30
- package/src/runtime/agent/orchestrator/session/store-summary-visibility.mjs +0 -4
- package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +144 -45
- package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +32 -13
- package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +364 -38
- package/src/runtime/agent/orchestrator/session/store.mjs +9 -2
- package/src/runtime/agent/orchestrator/session/task-wait-control.mjs +43 -12
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +23 -6
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +44 -1
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +12 -6
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +13 -7
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/bashism-rewrite.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/benign-exit.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +40 -7
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/deadline-plan.mjs +37 -34
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/inline-hoist.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +0 -4
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +6 -0
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +29 -27
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/find-files-tool.mjs +28 -11
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-policy.mjs +12 -3
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +203 -101
- package/src/runtime/agent/orchestrator/tools/builtin/git-repo-rw-lock.mjs +90 -41
- package/src/runtime/agent/orchestrator/tools/builtin/lib/list-helpers.mjs +17 -1
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-delivery.mjs +199 -0
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +12 -0
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-task-output.mjs +165 -39
- package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +25 -13
- package/src/runtime/agent/orchestrator/tools/builtin/native-search-client.mjs +113 -5
- package/src/runtime/agent/orchestrator/tools/builtin/read-batch.mjs +7 -6
- package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +19 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-line-collector.mjs +5 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-render.mjs +25 -7
- package/src/runtime/agent/orchestrator/tools/builtin/read-special-files.mjs +2 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-render.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/builtin/search-glob-tool.mjs +12 -5
- package/src/runtime/agent/orchestrator/tools/builtin/search-grep-tool.mjs +61 -22
- package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +32 -8
- package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +193 -19
- package/src/runtime/agent/orchestrator/tools/builtin/shell-direct-exe.mjs +57 -7
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +123 -32
- package/src/runtime/agent/orchestrator/tools/builtin/shell-lossless-compact.mjs +26 -1
- package/src/runtime/agent/orchestrator/tools/builtin/shell-output.mjs +13 -28
- package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +90 -11
- package/src/runtime/agent/orchestrator/tools/builtin/wait-budgets.mjs +23 -0
- package/src/runtime/agent/orchestrator/tools/builtin.mjs +54 -10
- package/src/runtime/agent/orchestrator/tools/code-graph/build.mjs +22 -28
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +11 -7
- package/src/runtime/agent/orchestrator/tools/destructive-warning.mjs +126 -9
- package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
- package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +15 -6
- package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +64 -2
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +10 -2
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promotion-results.mjs +13 -3
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +8 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +6 -1
- package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +104 -55
- package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +7 -2
- package/src/runtime/agent/orchestrator/tools/shell-powershell.mjs +39 -23
- package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
- package/src/runtime/attachments/office-extract.mjs +11 -9
- package/src/runtime/browser-bridge/client.mjs +24 -0
- package/src/runtime/channels/lib/scheduler.mjs +40 -12
- package/src/runtime/channels/lib/schedules-db.mjs +71 -12
- package/src/runtime/channels/lib/webhook/session-dispatch.mjs +36 -16
- package/src/runtime/channels/lib/webhook.mjs +0 -1
- package/src/runtime/channels/lib/webhooks-db.mjs +100 -10
- package/src/runtime/channels/lib/worker-main.mjs +17 -20
- package/src/runtime/computer-bridge/client.mjs +28 -1
- package/src/runtime/connectors/gmail-app-password.mjs +690 -0
- package/src/runtime/connectors/google-mcp.mjs +446 -0
- package/src/runtime/memory/lib/core-memory-access.mjs +69 -0
- package/src/runtime/memory/lib/core-memory-file.mjs +16 -8
- package/src/runtime/memory/lib/core-memory-index.mjs +15 -9
- package/src/runtime/memory/lib/core-memory-management.mjs +10 -4
- package/src/runtime/memory/lib/core-memory-store.mjs +53 -30
- package/src/runtime/memory/lib/core-memory-uniqueness.mjs +10 -6
- package/src/runtime/memory/lib/embedding-tokenizer.mjs +32 -18
- package/src/runtime/memory/lib/http-router/session-routes.mjs +3 -2
- package/src/runtime/memory/lib/memory-action-handlers/core-actions.mjs +44 -14
- package/src/runtime/memory/lib/memory-schema/core-and-meta.mjs +11 -0
- package/src/runtime/memory/lib/memory.mjs +7 -1
- package/src/runtime/memory/lib/query-core-recall.mjs +9 -1
- package/src/runtime/memory/lib/query-hybrid-search.mjs +2 -0
- package/src/runtime/memory/lib/runtime-fetcher.mjs +1 -1
- package/src/runtime/memory/lib/tool-call-handler.mjs +9 -5
- package/src/runtime/memory/tool-defs.mjs +5 -0
- package/src/runtime/office/authoring/pptx-script-normalize.mjs +11 -8
- package/src/runtime/office/core/tabular.mjs +1 -1
- package/src/runtime/office/design/library/design-template-inspect.mjs +7 -4
- package/src/runtime/office/portable/docx-formatting.mjs +1 -1
- package/src/runtime/office/portable/docx-runs.mjs +1 -1
- package/src/runtime/office/portable/docx-tracked-edits.mjs +2 -2
- package/src/runtime/office/portable/portable-docx-edits.mjs +11 -10
- package/src/runtime/office/portable/portable-docx-operations.mjs +21 -17
- package/src/runtime/office/portable/portable-docx-parts.mjs +15 -9
- package/src/runtime/office/portable/portable-docx-styles.mjs +4 -1
- package/src/runtime/office/portable/portable-docx-xml.mjs +9 -9
- package/src/runtime/office/portable/portable-opc.mjs +27 -13
- package/src/runtime/office/portable/portable-pivot.mjs +3 -3
- package/src/runtime/office/portable/portable-pptx-chart.mjs +3 -3
- package/src/runtime/office/portable/portable-pptx-charts.mjs +24 -18
- package/src/runtime/office/portable/portable-pptx-core.mjs +5 -5
- package/src/runtime/office/portable/portable-pptx-deck.mjs +8 -4
- package/src/runtime/office/portable/portable-pptx-package.mjs +7 -4
- package/src/runtime/office/portable/portable-pptx-shapes.mjs +18 -9
- package/src/runtime/office/portable/portable-sheet-parts.mjs +9 -3
- package/src/runtime/office/portable/portable-sheet-xml.mjs +5 -5
- package/src/runtime/office/portable/portable-xlsx-charts.mjs +4 -1
- package/src/runtime/office/portable/portable-xlsx-drawings.mjs +10 -6
- package/src/runtime/office/portable/portable-xlsx-operations.mjs +8 -5
- package/src/runtime/office/portable/portable-xlsx-pivot-ops.mjs +1 -1
- package/src/runtime/office/portable/portable-xlsx-reference-shift.mjs +11 -7
- package/src/runtime/office/portable/portable-xlsx-sheet-edits.mjs +6 -3
- package/src/runtime/office/portable/portable-xml.mjs +1 -1
- package/src/runtime/shared/agent-avatar-sprites.mjs +445 -0
- package/src/runtime/shared/agent-avatar.d.mts +64 -0
- package/src/runtime/shared/agent-avatar.mjs +320 -0
- package/src/runtime/shared/agent-route-config.d.mts +3 -0
- package/src/runtime/shared/agent-route-config.mjs +16 -0
- package/src/runtime/shared/atomic-file.mjs +36 -14
- package/src/runtime/shared/background-tasks.mjs +60 -20
- package/src/runtime/shared/child-spawn-gate.mjs +26 -16
- package/src/runtime/shared/config.mjs +8 -11
- package/src/runtime/shared/connector-accounts.mjs +15 -0
- package/src/runtime/shared/connector-catalog.d.mts +52 -0
- package/src/runtime/shared/connector-catalog.mjs +230 -0
- package/src/runtime/shared/connector-triggers.d.mts +3 -0
- package/src/runtime/shared/connector-triggers.mjs +43 -0
- package/src/runtime/shared/file-lock.mjs +7 -1
- package/src/runtime/shared/file-permissions-worker.mjs +38 -0
- package/src/runtime/shared/file-permissions.d.mts +19 -4
- package/src/runtime/shared/file-permissions.mjs +310 -4
- package/src/runtime/shared/git-runner-worker.mjs +6 -78
- package/src/runtime/shared/google-oauth-client.mjs +24 -0
- package/src/runtime/shared/held-request-host.d.mts +12 -0
- package/src/runtime/shared/held-request-host.mjs +71 -0
- package/src/runtime/shared/llm/http-agent.mjs +7 -3
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +10 -0
- package/src/runtime/shared/llm/usage-accounting.mjs +2 -0
- package/src/runtime/shared/llm/usage-ledger-import.mjs +32 -3
- package/src/runtime/shared/llm/usage-ledger-rollup.mjs +12 -5
- package/src/runtime/shared/llm/usage-ledger-worker.mjs +1 -1
- package/src/runtime/shared/llm/usage-ledger.mjs +20 -5
- package/src/runtime/shared/memory-snapshot.mjs +5 -1
- package/src/runtime/shared/notify-trace.mjs +8 -1
- package/src/runtime/shared/plain-preview.d.mts +1 -0
- package/src/runtime/shared/plain-preview.mjs +28 -0
- package/src/runtime/shared/pristine-execution-contract.json +5 -1
- package/src/runtime/shared/process-runner-worker.mjs +7 -0
- package/src/runtime/shared/process-runner.mjs +38 -0
- package/src/runtime/shared/provider-accounts.mjs +2 -1
- package/src/runtime/shared/provider-api-key.mjs +0 -1
- package/src/runtime/shared/read-row-numbers.mjs +1 -1
- package/src/runtime/shared/resource-admission.mjs +60 -18
- package/src/runtime/shared/routine-limits.d.mts +11 -0
- package/src/runtime/shared/routine-limits.mjs +21 -0
- package/src/runtime/shared/routine-trigger.d.mts +10 -0
- package/src/runtime/shared/routine-trigger.mjs +44 -0
- package/src/runtime/shared/run-child.mjs +84 -0
- package/src/runtime/shared/schedule-model-ref.mjs +9 -10
- package/src/runtime/shared/session-activity-signal.mjs +23 -0
- package/src/runtime/shared/shell-output-summary.mjs +23 -0
- package/src/runtime/shared/singleton-owner.mjs +126 -42
- package/src/runtime/shared/slow-span.mjs +4 -12
- package/src/runtime/shared/statusline/statusline-segments.mjs +13 -1
- package/src/runtime/shared/tool-output-limit.mjs +4 -2
- package/src/runtime/shared/tool-output-marker.mjs +58 -0
- package/src/runtime/shared/transcript-metadata.mjs +10 -0
- package/src/runtime/shared/turn-changes.mjs +0 -8
- package/src/runtime/shared/usage-readout-totals.mjs +56 -0
- package/src/runtime/shared/user-data-guard.mjs +131 -34
- package/src/runtime/shared/worktrees/activity-gate.mjs +33 -8
- package/src/runtime/shared/worktrees/git-head.mjs +20 -2
- package/src/runtime/shared/worktrees/lock.mjs +3 -2
- package/src/runtime/terminal-bridge/tool-defs.mjs +1 -1
- package/src/runtime/tidy/runners/biome.mjs +3 -1
- package/src/runtime/tidy/shadow.mjs +2 -1
- package/src/runtime/web-search/index.mjs +5 -7
- package/src/runtime/web-search/lib/formatter.mjs +42 -6
- package/src/runtime/web-search/tool-defs.mjs +6 -1
- package/src/session-runtime/agent-home-delivery.mjs +459 -0
- package/src/session-runtime/agent-profile-changes.mjs +21 -0
- package/src/session-runtime/agent-room-delivery.mjs +92 -0
- package/src/session-runtime/agent-task-sessions.mjs +200 -0
- package/src/session-runtime/boot/apis.mjs +50 -18
- package/src/session-runtime/boot/facade.mjs +5 -8
- package/src/session-runtime/boot/infrastructure.mjs +28 -17
- package/src/session-runtime/boot/tools.mjs +3 -0
- package/src/session-runtime/channel-config-api.mjs +53 -5
- package/src/session-runtime/cwd-plugins/core-memory-context.mjs +36 -20
- package/src/session-runtime/cwd-plugins/plugin-status.mjs +6 -1
- package/src/session-runtime/held-requests.mjs +228 -0
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +121 -0
- package/src/session-runtime/internal-tool-executor/feature-tools.mjs +5 -1
- package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +31 -2
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +31 -2
- package/src/session-runtime/internal-tool-executor.mjs +2 -0
- package/src/session-runtime/lifecycle/session-catalog.mjs +9 -0
- package/src/session-runtime/lifecycle/session-switch/context-switch.mjs +4 -3
- package/src/session-runtime/lifecycle/session-switch/resume.mjs +11 -4
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +3 -3
- package/src/session-runtime/lifecycle/shared.mjs +25 -2
- package/src/session-runtime/lifecycle/teardown/session-close.mjs +2 -0
- package/src/session-runtime/lifecycle/teardown.mjs +5 -2
- package/src/session-runtime/lifecycle-api.mjs +3 -1
- package/src/session-runtime/mcp-glue/server-catalog.mjs +8 -0
- package/src/session-runtime/mcp-glue/server-input.mjs +3 -0
- package/src/session-runtime/mcp-oauth-login.mjs +112 -15
- package/src/session-runtime/model-route/set-route.mjs +14 -3
- package/src/session-runtime/owned-automation-run.mjs +229 -0
- package/src/session-runtime/provider-auth/login.mjs +10 -6
- package/src/session-runtime/provider-auth/setup.mjs +19 -2
- package/src/session-runtime/provider-catalog-cache.mjs +101 -25
- package/src/session-runtime/provider-models/catalog-load.mjs +14 -3
- package/src/session-runtime/provider-models/row-hydration.mjs +4 -0
- package/src/session-runtime/provider-models.mjs +76 -10
- package/src/session-runtime/provider-readiness.mjs +4 -0
- package/src/session-runtime/resource-api.mjs +5 -0
- package/src/session-runtime/resource-mcp-api.mjs +107 -13
- package/src/session-runtime/resource-skills-api.mjs +12 -0
- package/src/session-runtime/room-member-gate.mjs +48 -0
- package/src/session-runtime/routine-home-turn.mjs +156 -0
- package/src/session-runtime/routine-owner.mjs +48 -0
- package/src/session-runtime/schedule-session-run.mjs +30 -64
- package/src/session-runtime/services/agent-tool/close-flow.mjs +2 -1
- package/src/session-runtime/services/agent-tool/helpers.mjs +10 -0
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +10 -2
- package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +13 -4
- package/src/session-runtime/services/agent-tool/notify.mjs +15 -4
- package/src/session-runtime/services/agent-tool/restart-notify.mjs +134 -0
- package/src/session-runtime/services/agent-tool/send-flow.mjs +24 -1
- package/src/session-runtime/services/agent-tool/spawn-flow/deferred-spawn.mjs +2 -1
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +4 -3
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +19 -4
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +2 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +5 -1
- package/src/session-runtime/services/agent-tool/tag-registry/tag-lookup.mjs +8 -3
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +3 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +4 -0
- package/src/session-runtime/services/agent-tool/worker-index.mjs +44 -10
- package/src/session-runtime/services/agent-tool.mjs +20 -0
- package/src/session-runtime/services/channel-admin.mjs +93 -24
- package/src/session-runtime/services/memory-access.mjs +37 -0
- package/src/session-runtime/services/provider-admin.mjs +166 -59
- package/src/session-runtime/services/schedule-access.mjs +91 -0
- package/src/session-runtime/services/usage-dashboard-model.mjs +2 -2
- package/src/session-runtime/services/usage-dashboard.mjs +27 -69
- package/src/session-runtime/session-create/session-options.mjs +34 -7
- package/src/session-runtime/session-hooks.mjs +16 -8
- package/src/session-runtime/setup-tool/executor.mjs +68 -6
- package/src/session-runtime/setup-tool/extended-actions.mjs +72 -14
- package/src/session-runtime/setup-tool/settings-contract.mjs +8 -6
- package/src/session-runtime/setup-tool/tool-defs.mjs +8 -0
- package/src/session-runtime/skills-api.mjs +16 -1
- package/src/session-runtime/tool-policy-refresh.mjs +238 -29
- package/src/session-runtime/turn/session-ops.mjs +10 -3
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +11 -2
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +3 -0
- package/src/session-runtime/usage-stats-api.mjs +6 -1
- package/src/session-runtime/webhook-session-run.mjs +49 -67
- package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +239 -0
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +556 -22
- package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +11 -1
- package/src/session-runtime/workflow-agents-api.mjs +4 -1
- package/src/standalone/channel-transport/http-routes.mjs +10 -9
- package/src/standalone/daemon-agent-control.mjs +1 -8
- package/src/standalone/daemon-desktop-runtime.mjs +20 -7
- package/src/standalone/daemon-owner.mjs +117 -25
- package/src/standalone/daemon-session-control.mjs +11 -2
- package/src/standalone/daemon.mjs +61 -17
- package/src/standalone/session-call-cache.mjs +6 -0
- package/src/standalone/session-protocol.mjs +28 -1
- package/src/standalone/session-service/retention/busy.mjs +7 -2
- package/src/standalone/session-service/session-calls/session-turns.mjs +9 -0
- package/src/standalone/session-service.mjs +19 -0
- package/src/standalone/session-transport/routes.mjs +7 -6
- package/src/tui/app/model-options.mjs +39 -2
- package/src/tui/app/model-picker.mjs +16 -2
- package/src/tui/app/provider-setup-picker.mjs +1 -2
- package/src/tui/app/slash-commands.mjs +20 -0
- package/src/tui/dist/index.mjs +487 -128
- package/src/tui/session/context-state.mjs +6 -1
- package/src/tui/session/notice-surface.mjs +35 -4
- package/src/tui/session/notice-text.mjs +0 -1
- package/src/tui/session/queue-helpers.mjs +2 -1
- package/src/tui/session/session-api/extensions.mjs +4 -0
- package/src/tui/session/session-api/intake/submission.mjs +12 -13
- package/src/tui/session/session-api/integrations.mjs +9 -5
- package/src/tui/session/session-api/lifecycle/session-reset.mjs +13 -3
- package/src/tui/session/session-api/lifecycle.mjs +17 -1
- package/src/tui/session/session-api/routes.mjs +48 -3
- package/src/tui/session/session-flow/drain.mjs +20 -3
- package/src/tui/session/session-flow/queue/entry-shape.mjs +2 -1
- package/src/tui/session/session-flow/queue/take-entries.mjs +3 -2
- package/src/tui/session/session-flow/steering.mjs +104 -24
- package/src/tui/session/session-flow.mjs +2 -0
- package/src/tui/session/tool-approval.mjs +26 -5
- package/src/tui/session/transcript-intake.mjs +6 -2
- package/src/tui/session/transcript-spill.mjs +5 -1
- package/src/tui/session/tui-steering-persist.mjs +65 -42
- package/src/tui/session/turn-live-call.mjs +56 -0
- package/src/tui/session/turn-stream.mjs +33 -0
- package/src/tui/session/turn.mjs +50 -7
- package/src/ui/statusline.mjs +1 -6
- package/src/ui/streaming-markdown-heal.mjs +24 -7
- package/src/vendor/statusline/bin/statusline-route.mjs +0 -1
- package/src/vendor/statusline/src/gateway/route-meta.mjs +0 -1
- package/src/workflows/default/WORKFLOW.md +9 -13
- package/src/session-runtime/automation-agents.mjs +0 -94
- package/src/session-runtime/automation-workflow.mjs +0 -59
|
@@ -9,10 +9,13 @@ import {
|
|
|
9
9
|
shellJobPublicTaskResult,
|
|
10
10
|
shellJobTaskStatus,
|
|
11
11
|
waitForShellJob,
|
|
12
|
+
waitShellJobTerminated,
|
|
12
13
|
} from './shell-jobs.mjs';
|
|
14
|
+
import { beginSessionTaskWait } from '../../session/manager/runtime-liveness.mjs';
|
|
13
15
|
import { TASK_WAIT_TIMEOUT_DEFAULT_MS, TASK_WAIT_TIMEOUT_MAX_MS, TASK_WAIT_TIMEOUT_MIN_MS } from './builtin-tools.mjs';
|
|
16
|
+
import { AGENT_TASK_WAIT_DEFAULT_MS } from './wait-budgets.mjs';
|
|
14
17
|
import { getAbortSignalForSession } from '../../session/abort-lookup.mjs';
|
|
15
|
-
import { beginInterruptibleTaskWait } from '../../session/task-wait-control.mjs';
|
|
18
|
+
import { TASK_WAIT_WAKE_NOTIFICATION, beginInterruptibleTaskWait } from '../../session/task-wait-control.mjs';
|
|
16
19
|
import {
|
|
17
20
|
acknowledgeBackgroundTaskCompletion,
|
|
18
21
|
cancelBackgroundTask,
|
|
@@ -31,6 +34,18 @@ import { readShellTaskOutput } from './lib/shell-task-output.mjs';
|
|
|
31
34
|
// wait returns the moment the native task settles, so this only bounds a
|
|
32
35
|
// process that ignores the kill.
|
|
33
36
|
const TASK_CANCEL_CONFIRM_MS = 5_000;
|
|
37
|
+
// Ceiling for confirming that every process the task started is gone once its
|
|
38
|
+
// root exited: a sweep is a table read, the kill and a second read (each read
|
|
39
|
+
// ~1-2 s on Windows).
|
|
40
|
+
const TASK_CANCEL_TREE_CONFIRM_MS = 15_000;
|
|
41
|
+
|
|
42
|
+
function cancelPendingText(taskId) {
|
|
43
|
+
return [
|
|
44
|
+
'status: cancel-pending',
|
|
45
|
+
`task_id: ${taskId}`,
|
|
46
|
+
'the kill was sent and the command itself exited, but processes it started are still alive. They keep being terminated and stay tracked (the folder stays held) until they are gone; re-run task cancel or task read to check again.',
|
|
47
|
+
].join('\n');
|
|
48
|
+
}
|
|
34
49
|
|
|
35
50
|
function recoveredTaskMatches(record, options = {}) {
|
|
36
51
|
const context =
|
|
@@ -84,12 +99,22 @@ function renderTaskCancelSuccess(taskId, task) {
|
|
|
84
99
|
|
|
85
100
|
// Clamp lives next to the caller; the bounds themselves are published by the
|
|
86
101
|
// tool schema, so an out-of-range request is corrected rather than rejected.
|
|
87
|
-
function resolveTaskWaitTimeoutMs(value) {
|
|
102
|
+
function resolveTaskWaitTimeoutMs(value, defaultMs = TASK_WAIT_TIMEOUT_DEFAULT_MS) {
|
|
88
103
|
const raw = Number(value);
|
|
89
|
-
if (!Number.isFinite(raw) || raw <= 0) return
|
|
104
|
+
if (!Number.isFinite(raw) || raw <= 0) return defaultMs;
|
|
90
105
|
return Math.min(TASK_WAIT_TIMEOUT_MAX_MS, Math.max(TASK_WAIT_TIMEOUT_MIN_MS, Math.floor(raw)));
|
|
91
106
|
}
|
|
92
107
|
|
|
108
|
+
// Agents run on the 5 m prompt cache, so their default wakes before it lapses;
|
|
109
|
+
// the Lead keeps the 1 h cache and the longer default.
|
|
110
|
+
async function defaultTaskWaitMs(sessionId) {
|
|
111
|
+
if (!sessionId) return TASK_WAIT_TIMEOUT_DEFAULT_MS;
|
|
112
|
+
const { getSession } = await import('../../session/manager.mjs');
|
|
113
|
+
const session = getSession(String(sessionId));
|
|
114
|
+
const agentOwned = session?.owner === 'agent' || session?.visibility === 'agent-only';
|
|
115
|
+
return agentOwned ? AGENT_TASK_WAIT_DEFAULT_MS : TASK_WAIT_TIMEOUT_DEFAULT_MS;
|
|
116
|
+
}
|
|
117
|
+
|
|
93
118
|
// Read-only counts of this runtime's shell work owned by OTHER sessions.
|
|
94
119
|
// Admission is runtime-wide while task list/cancel are session-scoped, so
|
|
95
120
|
// without this those holders are invisible. Counts only: another session's
|
|
@@ -128,8 +153,15 @@ async function listTasks(options) {
|
|
|
128
153
|
return sections.join('\n');
|
|
129
154
|
}
|
|
130
155
|
|
|
131
|
-
//
|
|
132
|
-
//
|
|
156
|
+
// Ceiling hits per still-running task, so a wait that keeps timing out on the
|
|
157
|
+
// same job can suggest a different move. Keyed by the task object, so the count
|
|
158
|
+
// goes with the task however it settles or is removed.
|
|
159
|
+
const waitCeilingHits = new WeakMap();
|
|
160
|
+
|
|
161
|
+
// Blocks until the shell task settles, the timeout elapses, the turn is
|
|
162
|
+
// cancelled, or anything deliverable is queued for this session (user input,
|
|
163
|
+
// steering, or any task notification: an agent or another shell job
|
|
164
|
+
// finishing). Returns what cut the wait short.
|
|
133
165
|
async function waitForShellTask(task, taskId, args, options) {
|
|
134
166
|
// The turn's abort signal must cut the wait short; a cancelled turn
|
|
135
167
|
// cannot sit out the remaining ceiling.
|
|
@@ -140,9 +172,12 @@ async function waitForShellTask(task, taskId, args, options) {
|
|
|
140
172
|
turnSignal = null;
|
|
141
173
|
}
|
|
142
174
|
const waitControl = beginInterruptibleTaskWait(options?.sessionId, turnSignal);
|
|
175
|
+
const releaseWaitState = beginSessionTaskWait(options?.sessionId);
|
|
143
176
|
const waitSignal = waitControl.signal;
|
|
144
|
-
const waitTimeoutMs = resolveTaskWaitTimeoutMs(args.timeout_ms);
|
|
177
|
+
const waitTimeoutMs = resolveTaskWaitTimeoutMs(args.timeout_ms, await defaultTaskWaitMs(options?.sessionId));
|
|
145
178
|
let interruptedByUser = false;
|
|
179
|
+
let notified = false;
|
|
180
|
+
let notifiedTaskId = null;
|
|
146
181
|
try {
|
|
147
182
|
// A shell task whose descendants outlived the shell process has no
|
|
148
183
|
// native job to subscribe to — the process it belonged to is gone.
|
|
@@ -175,9 +210,12 @@ async function waitForShellTask(task, taskId, args, options) {
|
|
|
175
210
|
}
|
|
176
211
|
} finally {
|
|
177
212
|
interruptedByUser = waitControl.interruptedByUser;
|
|
213
|
+
notified = waitControl.wakeReason === TASK_WAIT_WAKE_NOTIFICATION;
|
|
214
|
+
notifiedTaskId = waitControl.wakeDetail;
|
|
178
215
|
waitControl.dispose();
|
|
216
|
+
releaseWaitState();
|
|
179
217
|
}
|
|
180
|
-
return interruptedByUser;
|
|
218
|
+
return { interruptedByUser, notified, notifiedTaskId };
|
|
181
219
|
}
|
|
182
220
|
|
|
183
221
|
// Outcome of a shell cancel: `outcome` is 'cancelled' only when the process is
|
|
@@ -208,6 +246,11 @@ async function cancelShellTaskOutcome(task, taskId, options) {
|
|
|
208
246
|
].join('\n'),
|
|
209
247
|
};
|
|
210
248
|
}
|
|
249
|
+
// The root exited; what it started outside its process group is swept
|
|
250
|
+
// by the job's termination watch. Cancelled means all of it is gone.
|
|
251
|
+
if (confirmed && !(await waitShellJobTerminated(taskId, TASK_CANCEL_TREE_CONFIRM_MS))) {
|
|
252
|
+
return { outcome: 'unconfirmed', text: cancelPendingText(taskId) };
|
|
253
|
+
}
|
|
211
254
|
if (!confirmed) {
|
|
212
255
|
// No terminal event and no observable task: absence of
|
|
213
256
|
// state is not proof of termination. Stop tracking it so it
|
|
@@ -228,6 +271,10 @@ async function cancelShellTaskOutcome(task, taskId, options) {
|
|
|
228
271
|
cancelBackgroundShellJobWatch(taskId);
|
|
229
272
|
clearShellJobNotifyCtx(taskId);
|
|
230
273
|
cancelBackgroundTask(taskId, 'cancelled by task control');
|
|
274
|
+
// A task whose own cancel hook kills (what a finished command left running)
|
|
275
|
+
// reports what that kill confirmed.
|
|
276
|
+
const hookKill = job ? null : await task.cancelOutcome;
|
|
277
|
+
if (hookKill && hookKill.terminated !== true) return { outcome: 'unconfirmed', text: cancelPendingText(taskId) };
|
|
231
278
|
return job || wasRunning
|
|
232
279
|
? {
|
|
233
280
|
outcome: 'cancelled',
|
|
@@ -323,27 +370,59 @@ export async function executeTaskTool(args, options = {}) {
|
|
|
323
370
|
|
|
324
371
|
if (action === 'read' || action === 'wait') {
|
|
325
372
|
let waitInterruptedByUser = false;
|
|
373
|
+
let waitNotified = false;
|
|
374
|
+
let notifiedTaskId = null;
|
|
326
375
|
if (action === 'wait') {
|
|
327
376
|
if (!isShellTask) return `Error: task wait is only available for shell tasks: ${taskId}`;
|
|
328
|
-
|
|
377
|
+
({
|
|
378
|
+
interruptedByUser: waitInterruptedByUser,
|
|
379
|
+
notified: waitNotified,
|
|
380
|
+
notifiedTaskId,
|
|
381
|
+
} = await waitForShellTask(task, taskId, args, options));
|
|
329
382
|
}
|
|
330
383
|
if (isShellTask) refreshShellTask(taskId, { includeRunning: true });
|
|
331
384
|
const latest = getBackgroundTask(taskId, { context: options }) || task;
|
|
385
|
+
// A finished task whose completion notice is still unconsumed returns that
|
|
386
|
+
// notice's output (the unseen remainder) once; everything else reads the
|
|
387
|
+
// cursor. A wait that leaves the job running carries the progress digest.
|
|
388
|
+
const pendingCompletionOutput =
|
|
389
|
+
isShellTask &&
|
|
390
|
+
latest.status !== 'running' &&
|
|
391
|
+
latest.completionAcknowledged !== true &&
|
|
392
|
+
args.output !== 'tail' &&
|
|
393
|
+
typeof latest.completionOutput === 'string'
|
|
394
|
+
? latest.completionOutput
|
|
395
|
+
: null;
|
|
332
396
|
const visible =
|
|
333
397
|
isShellTask && latest.result && typeof latest.result === 'object'
|
|
334
|
-
? {
|
|
398
|
+
? {
|
|
399
|
+
...latest,
|
|
400
|
+
resultText:
|
|
401
|
+
pendingCompletionOutput ??
|
|
402
|
+
readShellTaskOutput(latest, latest.result, {
|
|
403
|
+
output: args.output,
|
|
404
|
+
digest: action === 'wait' && latest.status === 'running',
|
|
405
|
+
}),
|
|
406
|
+
}
|
|
335
407
|
: latest;
|
|
336
408
|
let rendered = renderBackgroundTask(visible, { includeResult: true });
|
|
337
409
|
if (action === 'wait' && latest.status === 'running') {
|
|
338
410
|
if (waitInterruptedByUser) {
|
|
339
411
|
rendered +=
|
|
340
|
-
'\n\nWait
|
|
412
|
+
'\n\nWait ended by new user input; task still running in the background. Handle the new message first.';
|
|
413
|
+
} else if (waitNotified) {
|
|
414
|
+
const from = notifiedTaskId && notifiedTaskId !== taskId ? ` (task_id: ${notifiedTaskId})` : '';
|
|
415
|
+
rendered += `\n\nWait ended because a notification arrived${from}; it is delivered to you now. This task (${taskId}) is still running in the background.`;
|
|
341
416
|
} else {
|
|
417
|
+
const hits = (waitCeilingHits.get(latest) || 0) + 1;
|
|
418
|
+
waitCeilingHits.set(latest, hits);
|
|
342
419
|
// In-band report cue: the static "periodic reports" rule does not
|
|
343
420
|
// survive a long tool loop, so a ceiling-hit wait carries the
|
|
344
421
|
// protocol reminder itself.
|
|
345
422
|
rendered +=
|
|
346
|
-
|
|
423
|
+
hits > 1
|
|
424
|
+
? `\n\nWait ceiling reached again (${hits} times); task still running. Check whether it is progressing (task read output:tail, or the log file) and cancel it if it is stuck; otherwise continue other work — its result is delivered automatically.`
|
|
425
|
+
: '\n\nWait ceiling reached; task still running and its result is delivered automatically. If periodic reports were requested, write the user-facing report now; otherwise continue independent work or end the turn.';
|
|
347
426
|
}
|
|
348
427
|
}
|
|
349
428
|
if (acknowledgeBackgroundTaskCompletion(taskId, { context: options })) {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// The one place the shell hold and the task wait budgets are set. Every
|
|
2
|
+
// schema, clamp, description and result text reads them from here.
|
|
3
|
+
//
|
|
4
|
+
// Shell hold: how long a foreground command may hold the tool call before it
|
|
5
|
+
// moves to the background (it keeps running; completion is delivered
|
|
6
|
+
// automatically). New user input ends the hold early. `wait_ms` picks a
|
|
7
|
+
// different hold for one call, clamped to MIN..MAX.
|
|
8
|
+
export const SHELL_HOLD_DEFAULT_MS = 60_000;
|
|
9
|
+
export const SHELL_HOLD_MIN_MS = 1_000;
|
|
10
|
+
export const SHELL_HOLD_MAX_MS = 600_000;
|
|
11
|
+
|
|
12
|
+
// `task wait` ceiling. The wait returns the moment the task settles or new
|
|
13
|
+
// user input arrives, so the ceiling only bounds a still-running task. The
|
|
14
|
+
// floor stops a caller from turning wait into a busy poll. An agent's default
|
|
15
|
+
// stays under the 5 m prompt-cache TTL with room for the turn's own generation
|
|
16
|
+
// time, so a wait that runs to the ceiling wakes to a warm cache.
|
|
17
|
+
export const TASK_WAIT_DEFAULT_MS = 300_000;
|
|
18
|
+
export const AGENT_TASK_WAIT_DEFAULT_MS = 240_000;
|
|
19
|
+
export const TASK_WAIT_MIN_MS = 10_000;
|
|
20
|
+
export const TASK_WAIT_MAX_MS = 3_600_000;
|
|
21
|
+
|
|
22
|
+
/** Whole seconds for descriptions and result text. */
|
|
23
|
+
export const budgetSeconds = (ms) => Math.round(ms / 1000);
|
|
@@ -58,6 +58,7 @@ import {
|
|
|
58
58
|
GREP_OUTPUT_MAX_BYTES,
|
|
59
59
|
LOCATOR_OUTPUT_MAX_BYTES,
|
|
60
60
|
capLineOrientedToolOutput,
|
|
61
|
+
capMarker,
|
|
61
62
|
} from './builtin/tool-output-limit.mjs';
|
|
62
63
|
import {
|
|
63
64
|
isBlockedDevicePath,
|
|
@@ -340,6 +341,46 @@ function _locatorTargets(toolName, args) {
|
|
|
340
341
|
return [toolName === 'find' ? '' : '.'];
|
|
341
342
|
}
|
|
342
343
|
|
|
344
|
+
const _GREP_MATCH_ROW_RE = /^(?:\d+|.+?:\d+):/;
|
|
345
|
+
|
|
346
|
+
// Match rows the byte cap left visible, in the units grep's `offset` counts.
|
|
347
|
+
function _grepShownEntries(keptLines, mode) {
|
|
348
|
+
// A context block counts only when its header and every source line survived.
|
|
349
|
+
let blocks = 0;
|
|
350
|
+
let sawHeader = false;
|
|
351
|
+
keptLines.forEach((line, index) => {
|
|
352
|
+
const header = /^# .+:\d+ \[lines (\d+)-(\d+)\]$/.exec(line);
|
|
353
|
+
if (!header) return;
|
|
354
|
+
sawHeader = true;
|
|
355
|
+
if (index + Number(header[2]) - Number(header[1]) + 1 < keptLines.length) blocks += 1;
|
|
356
|
+
});
|
|
357
|
+
if (sawHeader) return blocks;
|
|
358
|
+
const rows = keptLines.filter((line) => line && !/^(?:#|--$|\[|\.\.\.|…|\()/.test(line));
|
|
359
|
+
return mode === 'content' ? rows.filter((line) => _GREP_MATCH_ROW_RE.test(line)).length : rows.length;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Byte-cap marker for grep: the continuation is the offset of the first match
|
|
363
|
+
// row not shown. A pattern/path fan-out has per-target offsets, so it gets
|
|
364
|
+
// narrowing advice instead of a misleading global offset.
|
|
365
|
+
function _grepBudgetFooter(args, keptLines, capBytes) {
|
|
366
|
+
const fanout = keptLines.some((line) => line.startsWith('# grep '));
|
|
367
|
+
const baseOffset =
|
|
368
|
+
Number.isFinite(Number(args?.offset)) && Number(args.offset) > 0 ? Math.floor(Number(args.offset)) : 0;
|
|
369
|
+
const shown = _grepShownEntries(keptLines, args?.mode);
|
|
370
|
+
// Every mode orders the whole result set before `offset` slices it (files
|
|
371
|
+
// and count pages are sorted first, then cut), so the rows kept here are a
|
|
372
|
+
// prefix of the offset order and offset resumes right after them.
|
|
373
|
+
let narrow = '';
|
|
374
|
+
if (fanout) narrow = 'run one pattern/path per call, or add path/glob/type to cut the match set';
|
|
375
|
+
else if (shown === 0) narrow = 'one match row exceeds the cap; read that file window or use a tighter pattern';
|
|
376
|
+
return capMarker({
|
|
377
|
+
limit: capBytes,
|
|
378
|
+
shown: `${shown} match row(s) shown`,
|
|
379
|
+
nextOffset: fanout || shown === 0 ? null : baseOffset + shown,
|
|
380
|
+
narrow,
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
|
|
343
384
|
function _locatorBudgetFooter(toolName, args, keptLines, capBytes) {
|
|
344
385
|
const targets = _locatorTargets(toolName, args);
|
|
345
386
|
const header = new RegExp(`^# ${toolName} (.+)$`);
|
|
@@ -358,17 +399,24 @@ function _locatorBudgetFooter(toolName, args, keptLines, capBytes) {
|
|
|
358
399
|
}
|
|
359
400
|
const target = targets[targetIndex] || targets[0] || '';
|
|
360
401
|
const remaining = targets.length - targetIndex - 1;
|
|
361
|
-
const
|
|
362
|
-
// Factual continuation only — no retry imperatives: the marker states
|
|
363
|
-
// what was cut, never instructs another call.
|
|
402
|
+
const limit = Number(capBytes) > 0 ? Number(capBytes) : LOCATOR_OUTPUT_MAX_BYTES;
|
|
364
403
|
const nextTarget =
|
|
365
404
|
remaining > 0 ? `; ${remaining} target(s) not shown, next=${JSON.stringify(targets[targetIndex + 1])}` : '';
|
|
366
405
|
if (toolName === 'find') {
|
|
367
|
-
|
|
406
|
+
// find has no offset: the rest of the ranked matches needs a tighter query.
|
|
407
|
+
return capMarker({
|
|
408
|
+
limit,
|
|
409
|
+
shown: `matches for query=${JSON.stringify(target)} cut${nextTarget}`,
|
|
410
|
+
narrow: 'use a more specific query or add path',
|
|
411
|
+
});
|
|
368
412
|
}
|
|
369
413
|
const baseOffset =
|
|
370
414
|
Number.isFinite(Number(args?.offset)) && Number(args.offset) > 0 ? Math.floor(Number(args.offset)) : 0;
|
|
371
|
-
return
|
|
415
|
+
return capMarker({
|
|
416
|
+
limit,
|
|
417
|
+
shown: `${visibleEntries} complete row(s) shown for path=${JSON.stringify(target)}${nextTarget}`,
|
|
418
|
+
nextOffset: baseOffset + visibleEntries,
|
|
419
|
+
});
|
|
372
420
|
}
|
|
373
421
|
|
|
374
422
|
export async function executeBuiltinTool(name, args, cwd, options = {}) {
|
|
@@ -489,11 +537,7 @@ function _budgetBuiltinOutput(toolName, args, result, options) {
|
|
|
489
537
|
const explicitCap = Number(options?.toolOutputMaxBytes) > 0 ? Math.trunc(Number(options.toolOutputMaxBytes)) : null;
|
|
490
538
|
if (toolName === 'grep') {
|
|
491
539
|
const grepCap = explicitCap ? Math.min(explicitCap, GREP_OUTPUT_MAX_BYTES) : GREP_OUTPUT_MAX_BYTES;
|
|
492
|
-
return capLineOrientedToolOutput(
|
|
493
|
-
result,
|
|
494
|
-
grepCap,
|
|
495
|
-
(kept) => `[grep output capped at ${grepCap} bytes; ${kept.length} line(s) shown, remainder omitted]`
|
|
496
|
-
);
|
|
540
|
+
return capLineOrientedToolOutput(result, grepCap, (kept) => _grepBudgetFooter(args, kept, grepCap));
|
|
497
541
|
}
|
|
498
542
|
if (_LOCATOR_BUDGET_TOOLS.has(toolName)) {
|
|
499
543
|
const locatorCap = explicitCap ? Math.min(explicitCap, LOCATOR_OUTPUT_MAX_BYTES) : LOCATOR_OUTPUT_MAX_BYTES;
|
|
@@ -172,9 +172,10 @@ async function _validateDiskCodeGraphHit({
|
|
|
172
172
|
return { graph, manifest, signature };
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
-
//
|
|
176
|
-
//
|
|
177
|
-
//
|
|
175
|
+
// Validates the disk graph under a read-only query slot; a miss releases it
|
|
176
|
+
// and spawnWorker queues for a build slot, so queries never wait behind
|
|
177
|
+
// builds. Keeping this seam dependency-injectable makes slot/abort behavior
|
|
178
|
+
// testable without spawning native processes or Worker threads.
|
|
178
179
|
export async function _runDiskCodeGraphFastPath({
|
|
179
180
|
graphCwd,
|
|
180
181
|
diskProbe,
|
|
@@ -182,36 +183,31 @@ export async function _runDiskCodeGraphFastPath({
|
|
|
182
183
|
signal = null,
|
|
183
184
|
loadDiskEntry,
|
|
184
185
|
consumeDirty = () => {},
|
|
185
|
-
|
|
186
|
-
// processes in the independent search lane.
|
|
187
|
-
acquireSlot = (signal) => acquireChildSpawnSlot(signal, 'code-graph'),
|
|
186
|
+
acquireSlot = (signal) => acquireChildSpawnSlot(signal, 'code-graph-query'),
|
|
188
187
|
validateDiskHit = _validateDiskCodeGraphHit,
|
|
189
188
|
spawnWorker,
|
|
190
189
|
maxFiles = CODE_GRAPH_MAX_FILES,
|
|
191
190
|
}) {
|
|
192
191
|
if (!diskProbe?.isFastPathEligible || diskProbe.maxFiles !== maxFiles) {
|
|
193
|
-
return spawnWorker(null, null
|
|
192
|
+
return spawnWorker(null, null);
|
|
194
193
|
}
|
|
195
194
|
const diskEntry = loadDiskEntry();
|
|
196
195
|
if (!_isCompatibleDiskCodeGraphEntry(diskEntry, maxFiles)) {
|
|
197
|
-
return spawnWorker(null, null
|
|
196
|
+
return spawnWorker(null, null);
|
|
198
197
|
}
|
|
199
198
|
consumeDirty();
|
|
200
199
|
const release = await acquireSlot(signal || null);
|
|
201
|
-
let
|
|
200
|
+
let hit;
|
|
202
201
|
try {
|
|
203
202
|
_throwIfAborted(signal);
|
|
204
|
-
|
|
205
|
-
_throwIfAborted(signal);
|
|
206
|
-
if (hit?.invalidated) throw codeGraphBuildInvalidatedError(hit.graph);
|
|
207
|
-
if (hit?.graph) return hit.graph;
|
|
208
|
-
_throwIfAborted(signal);
|
|
209
|
-
const workerPromise = spawnWorker(release, hit?.manifest || null, hit?.signature || null);
|
|
210
|
-
handedToWorker = true;
|
|
211
|
-
return workerPromise;
|
|
203
|
+
hit = await validateDiskHit({ graphCwd, diskEntry, genAtStart, signal });
|
|
212
204
|
} finally {
|
|
213
|
-
|
|
205
|
+
release();
|
|
214
206
|
}
|
|
207
|
+
_throwIfAborted(signal);
|
|
208
|
+
if (hit?.invalidated) throw codeGraphBuildInvalidatedError(hit.graph);
|
|
209
|
+
if (hit?.graph) return hit.graph;
|
|
210
|
+
return spawnWorker(hit?.manifest || null, hit?.signature || null);
|
|
215
211
|
}
|
|
216
212
|
|
|
217
213
|
function _prepareDiskCodeGraphFastPath({
|
|
@@ -306,8 +302,10 @@ export async function buildCodeGraphAsync(
|
|
|
306
302
|
const existing = _inflightAsyncBuilds.get(inflightKey);
|
|
307
303
|
if (existing) return raceAbort(existing, signal);
|
|
308
304
|
// Non-competing prewarm: the signature-validation manifest also needs a
|
|
309
|
-
//
|
|
310
|
-
if (bestEffort && !childSpawnHasSpareCapacity('code-graph'))
|
|
305
|
+
// query slot and a miss a build slot, so warmers skip before either queues.
|
|
306
|
+
if (bestEffort && !(childSpawnHasSpareCapacity('code-graph-query') && childSpawnHasSpareCapacity('code-graph'))) {
|
|
307
|
+
return null;
|
|
308
|
+
}
|
|
311
309
|
const promise = _retryCodeGraphBuildAfterInvalidation(
|
|
312
310
|
async () => {
|
|
313
311
|
const genAtStart = _getCodeGraphGen(graphCwd);
|
|
@@ -315,7 +313,7 @@ export async function buildCodeGraphAsync(
|
|
|
315
313
|
// bounded I/O. Do not run a manifest at all when no disk candidate exists:
|
|
316
314
|
// cold/dirty misses remain entirely on the existing Worker path.
|
|
317
315
|
if (scoped) {
|
|
318
|
-
return _spawnCodeGraphWorker(cwd, graphCwd, genAtStart, signal, null, null,
|
|
316
|
+
return _spawnCodeGraphWorker(cwd, graphCwd, genAtStart, signal, null, null, {
|
|
319
317
|
buildOptions: scopeOptions,
|
|
320
318
|
cacheResult: false,
|
|
321
319
|
});
|
|
@@ -330,8 +328,8 @@ export async function buildCodeGraphAsync(
|
|
|
330
328
|
signal,
|
|
331
329
|
loadDiskEntry: () => getDiskCodeGraphEntry(graphCwd),
|
|
332
330
|
consumeDirty: () => _consumeCodeGraphDirtyPaths(graphCwd),
|
|
333
|
-
spawnWorker: (
|
|
334
|
-
_spawnCodeGraphWorker(cwd, graphCwd, genAtStart, signal,
|
|
331
|
+
spawnWorker: (manifest, signature) =>
|
|
332
|
+
_spawnCodeGraphWorker(cwd, graphCwd, genAtStart, signal, manifest, signature),
|
|
335
333
|
}),
|
|
336
334
|
});
|
|
337
335
|
},
|
|
@@ -350,7 +348,6 @@ export function _spawnCodeGraphWorker(
|
|
|
350
348
|
graphCwd,
|
|
351
349
|
genAtStart,
|
|
352
350
|
signal,
|
|
353
|
-
preAcquiredRelease = null,
|
|
354
351
|
manifest = null,
|
|
355
352
|
signature = null,
|
|
356
353
|
{
|
|
@@ -416,10 +413,7 @@ export function _spawnCodeGraphWorker(
|
|
|
416
413
|
/* best-effort */
|
|
417
414
|
}
|
|
418
415
|
};
|
|
419
|
-
(
|
|
420
|
-
? Promise.resolve(preAcquiredRelease)
|
|
421
|
-
: acquireChildSpawnSlot(signal || null, 'code-graph')
|
|
422
|
-
).then((release) => {
|
|
416
|
+
acquireChildSpawnSlot(signal || null, 'code-graph').then((release) => {
|
|
423
417
|
_releaseSlot = release;
|
|
424
418
|
if (settled) {
|
|
425
419
|
release();
|
|
@@ -14,7 +14,7 @@ import { resolve as pathResolve, isAbsolute, relative as pathRelative, dirname a
|
|
|
14
14
|
import { normalizeInputPath } from '../builtin/path-utils.mjs';
|
|
15
15
|
import { markScopedCacheIncomplete, recordScopedCacheDependency } from '../../session/cache/scoped-cache-outcome.mjs';
|
|
16
16
|
import { CODE_GRAPH_TOOL_DEFS } from '../code-graph-tool-defs.mjs';
|
|
17
|
-
import { CODE_GRAPH_OUTPUT_MAX_BYTES, capLineOrientedToolOutput } from '../builtin/tool-output-limit.mjs';
|
|
17
|
+
import { CODE_GRAPH_OUTPUT_MAX_BYTES, capLineOrientedToolOutput, capMarker } from '../builtin/tool-output-limit.mjs';
|
|
18
18
|
import { _graphRel, _appendSameBasenameHint, _isExistingFile } from './source-access.mjs';
|
|
19
19
|
import {
|
|
20
20
|
_capGraphList,
|
|
@@ -375,7 +375,6 @@ async function executeCodeGraphToolRaw(name, rawArgs, cwd, signal = null, option
|
|
|
375
375
|
|
|
376
376
|
function _codeGraphBudgetFooter(args, keptLines) {
|
|
377
377
|
const rawMode = String(args?.mode || '').trim();
|
|
378
|
-
const capKb = Math.round(CODE_GRAPH_OUTPUT_MAX_BYTES / 1024);
|
|
379
378
|
const targets = collectGraphSymbolList(args);
|
|
380
379
|
const files = _collectGraphFileList(args);
|
|
381
380
|
const batchTargets = targets.length ? targets : files;
|
|
@@ -389,13 +388,18 @@ function _codeGraphBudgetFooter(args, keptLines) {
|
|
|
389
388
|
const index = batchTargets.indexOf(match[1]);
|
|
390
389
|
if (index >= 0) currentIndex = index;
|
|
391
390
|
}
|
|
392
|
-
return
|
|
391
|
+
return capMarker({
|
|
392
|
+
limit: CODE_GRAPH_OUTPUT_MAX_BYTES,
|
|
393
|
+
shown: `${label} from index ${currentIndex} not fully shown`,
|
|
394
|
+
narrow: `re-query ${label}=${JSON.stringify(batchTargets.slice(currentIndex))} separately`,
|
|
395
|
+
});
|
|
393
396
|
}
|
|
394
397
|
const target = batchTargets[0];
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
:
|
|
398
|
-
|
|
398
|
+
return capMarker({
|
|
399
|
+
limit: CODE_GRAPH_OUTPUT_MAX_BYTES,
|
|
400
|
+
shown: target ? `remainder for ${label.slice(0, -1)}=${JSON.stringify(target)} omitted` : 'remainder omitted',
|
|
401
|
+
narrow: 'add file/path scope, a narrower mode, or a smaller depth/limit',
|
|
402
|
+
});
|
|
399
403
|
}
|
|
400
404
|
|
|
401
405
|
export async function executeCodeGraphTool(name, args, cwd, signal = null, options = {}) {
|
|
@@ -9,12 +9,111 @@
|
|
|
9
9
|
import { SHELL_NAMES as _SHELL_NAMES, WRAPPER_NAMES as _WRAPPER_NAMES } from './shell-policy.mjs';
|
|
10
10
|
import { extractPowerShellCommandInner } from './shell-powershell.mjs';
|
|
11
11
|
|
|
12
|
+
// A `#` (or PowerShell `<#`) starts a comment only at the start of a word:
|
|
13
|
+
// line start, after whitespace, or after a command operator. Inside a word or
|
|
14
|
+
// URL (`a#b`, `http://x/#y`, `$#`, `${#v}`) it is an ordinary character.
|
|
15
|
+
function _isCommentStart(text, i) {
|
|
16
|
+
return i === 0 || /[\s;&|(]/.test(text[i - 1]);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const _PS_HERE_SQ = /@'[ \t]*\r?\n[\s\S]*?\r?\n'@/y;
|
|
20
|
+
const _PS_HERE_DQ = /@"[ \t]*\r?\n[\s\S]*?\r?\n"@/y;
|
|
21
|
+
const _HEREDOC_START = /<<-?\s*['"]?(\w+)['"]?/y;
|
|
22
|
+
|
|
23
|
+
function _closingQuote(text, from, quote, escapes) {
|
|
24
|
+
let j = from;
|
|
25
|
+
while (j < text.length && text[j] !== quote) j += escapes && text[j] === '\\' ? 2 : 1;
|
|
26
|
+
return j < text.length ? j : -1;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Single left-to-right scan so each construct is recognised by what the shell
|
|
30
|
+
// would see at that position (a `'` inside a comment, a `#` inside a word or a
|
|
31
|
+
// quote inside a here-string never mis-pair later delimiters). Any construct
|
|
32
|
+
// that cannot be closed (unterminated quote, `<#` without `#>`, heredoc without
|
|
33
|
+
// terminator) is left in the output verbatim, so uncertain text stays visible
|
|
34
|
+
// to the policy checks instead of being dropped.
|
|
12
35
|
export function stripQuotedAndHeredoc(s) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
36
|
+
const text = String(s || '');
|
|
37
|
+
const n = text.length;
|
|
38
|
+
const pendingHeredocs = [];
|
|
39
|
+
let out = '';
|
|
40
|
+
let i = 0;
|
|
41
|
+
while (i < n) {
|
|
42
|
+
const ch = text[i];
|
|
43
|
+
if (ch === '\\') {
|
|
44
|
+
out += text.slice(i, i + 2);
|
|
45
|
+
i += 2;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (ch === '@' && (text[i + 1] === "'" || text[i + 1] === '"')) {
|
|
49
|
+
const re = text[i + 1] === "'" ? _PS_HERE_SQ : _PS_HERE_DQ;
|
|
50
|
+
re.lastIndex = i;
|
|
51
|
+
const m = re.exec(text);
|
|
52
|
+
if (m) {
|
|
53
|
+
out += text[i + 1] === "'" ? "''" : '""';
|
|
54
|
+
i += m[0].length;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (ch === '<' && text[i + 1] === '<' && text[i - 1] !== '<') {
|
|
59
|
+
_HEREDOC_START.lastIndex = i;
|
|
60
|
+
const m = _HEREDOC_START.exec(text);
|
|
61
|
+
if (m && new RegExp(`\\n${m[1]}\\b`).test(text.slice(i + m[0].length))) {
|
|
62
|
+
// The rest of the opening line stays visible; the body is skipped at
|
|
63
|
+
// the next newline.
|
|
64
|
+
pendingHeredocs.push(m[1]);
|
|
65
|
+
out += '<<HEREDOC>>';
|
|
66
|
+
i += m[0].length;
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (ch === '<' && text[i + 1] === '#' && _isCommentStart(text, i)) {
|
|
71
|
+
const end = text.indexOf('#>', i + 2);
|
|
72
|
+
if (end >= 0) {
|
|
73
|
+
out += ' ';
|
|
74
|
+
i = end + 2;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (ch === '#' && _isCommentStart(text, i)) {
|
|
79
|
+
const nl = text.indexOf('\n', i);
|
|
80
|
+
i = nl < 0 ? n : nl;
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
if (ch === "'" || ch === '"' || (ch === '$' && text[i + 1] === "'")) {
|
|
84
|
+
const ansiC = ch === '$';
|
|
85
|
+
const quote = ansiC ? "'" : ch;
|
|
86
|
+
const open = ansiC ? i + 2 : i + 1;
|
|
87
|
+
const close = _closingQuote(text, open, quote, ch !== "'");
|
|
88
|
+
if (close >= 0) {
|
|
89
|
+
out += (ansiC ? '$' : '') + quote + quote;
|
|
90
|
+
i = close + 1;
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (ch === '\n' && pendingHeredocs.length) {
|
|
95
|
+
let at = i;
|
|
96
|
+
let found = true;
|
|
97
|
+
for (const delimiter of pendingHeredocs) {
|
|
98
|
+
const re = new RegExp(`\\n${delimiter}\\b`, 'g');
|
|
99
|
+
re.lastIndex = at;
|
|
100
|
+
const m = re.exec(text);
|
|
101
|
+
if (!m) {
|
|
102
|
+
found = false;
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
at = m.index + m[0].length;
|
|
106
|
+
}
|
|
107
|
+
pendingHeredocs.length = 0;
|
|
108
|
+
if (found) {
|
|
109
|
+
i = at;
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
out += ch;
|
|
114
|
+
i++;
|
|
115
|
+
}
|
|
116
|
+
return out;
|
|
18
117
|
}
|
|
19
118
|
|
|
20
119
|
// Heredoc bodies (shell-exec contexts route the body through scanning).
|
|
@@ -37,8 +136,11 @@ function _tokenize(s) {
|
|
|
37
136
|
if (c === "'") {
|
|
38
137
|
const e = src.indexOf("'", i + 1);
|
|
39
138
|
if (e === -1) {
|
|
40
|
-
|
|
41
|
-
|
|
139
|
+
// Unterminated: an apostrophe inside a PowerShell word is literal, so
|
|
140
|
+
// keep tokenizing instead of swallowing the rest of the command.
|
|
141
|
+
cur += c;
|
|
142
|
+
i++;
|
|
143
|
+
continue;
|
|
42
144
|
}
|
|
43
145
|
cur += src.slice(i, e + 1);
|
|
44
146
|
i = e + 1;
|
|
@@ -55,8 +157,9 @@ function _tokenize(s) {
|
|
|
55
157
|
j++;
|
|
56
158
|
}
|
|
57
159
|
if (j >= src.length) {
|
|
58
|
-
cur +=
|
|
59
|
-
|
|
160
|
+
cur += c;
|
|
161
|
+
i++;
|
|
162
|
+
continue;
|
|
60
163
|
}
|
|
61
164
|
cur += src.slice(i, j + 1);
|
|
62
165
|
i = j + 1;
|
|
@@ -67,6 +170,20 @@ function _tokenize(s) {
|
|
|
67
170
|
i += 2;
|
|
68
171
|
continue;
|
|
69
172
|
}
|
|
173
|
+
// `cur` is empty exactly at a word start (after whitespace or an operator),
|
|
174
|
+
// the only place `#` / PowerShell `<#` begins a comment.
|
|
175
|
+
if (!cur && c === '#') {
|
|
176
|
+
const nl = src.indexOf('\n', i);
|
|
177
|
+
i = nl < 0 ? src.length : nl;
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
if (!cur && c === '<' && src[i + 1] === '#') {
|
|
181
|
+
const end = src.indexOf('#>', i + 2);
|
|
182
|
+
if (end >= 0) {
|
|
183
|
+
i = end + 2;
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
70
187
|
if (c === ' ' || c === '\t') {
|
|
71
188
|
if (cur) {
|
|
72
189
|
t.push(cur);
|