mixdog 1.2.5 → 1.2.6
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/package.json +1 -1
- package/scripts/lib/gate-scheduler.mjs +2 -2
- 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 +2 -3
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +10 -0
- package/src/defaults/skills/browser-use/SKILL.md +2 -1
- package/src/defaults/skills/computer-use/SKILL.md +3 -1
- package/src/defaults/skills/visualize/SKILL.md +3 -2
- package/src/lib/rules-builder.cjs +1 -1
- 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 +3 -1
- package/src/rules/lead/LEAD.md +4 -3
- package/src/rules/shared/10-tool-workflow.md +2 -1
- package/src/rules/shared/60-verification.md +4 -5
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -1
- package/src/runtime/agent/orchestrator/config.mjs +6 -0
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +1 -1
- package/src/runtime/agent/orchestrator/internal-agents.mjs +10 -0
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +53 -60
- package/src/runtime/agent/orchestrator/mcp/client.mjs +7 -4
- package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +2 -3
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +40 -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 +1 -2
- 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/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-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-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 +2 -3
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +3 -8
- package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +15 -3
- 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/lifecycle-scan.mjs +9 -0
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +39 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +9 -19
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +2 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +13 -5
- 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/runtime-liveness.mjs +23 -1
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +81 -34
- package/src/runtime/agent/orchestrator/session/manager.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/request-fork.mjs +47 -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-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 +306 -0
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +70 -21
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +46 -30
- 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/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-task-output.mjs +165 -39
- package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +25 -13
- 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 +119 -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 +40 -2
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +2 -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 +2 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +35 -4
- 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/memory/lib/embedding-tokenizer.mjs +32 -18
- package/src/runtime/memory/lib/runtime-fetcher.mjs +1 -1
- package/src/runtime/memory/lib/tool-call-handler.mjs +7 -5
- 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/atomic-file.mjs +22 -13
- 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 +0 -10
- 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/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/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/run-child.mjs +84 -0
- 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/tool-output-limit.mjs +4 -2
- package/src/runtime/shared/tool-output-marker.mjs +58 -0
- package/src/runtime/shared/user-data-guard.mjs +28 -9
- 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/lifecycle/session-switch/context-switch.mjs +4 -3
- package/src/session-runtime/lifecycle/session-switch/resume.mjs +7 -4
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +3 -3
- package/src/session-runtime/lifecycle/shared.mjs +19 -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/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/services/agent-tool/close-flow.mjs +2 -1
- 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-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/provider-admin.mjs +92 -20
- 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/turn/session-ops.mjs +2 -2
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
- package/src/session-runtime/usage-stats-api.mjs +6 -1
- package/src/standalone/channel-transport/http-routes.mjs +10 -9
- package/src/standalone/daemon-desktop-runtime.mjs +20 -7
- package/src/standalone/daemon-owner.mjs +117 -25
- package/src/standalone/daemon.mjs +43 -13
- package/src/standalone/session-call-cache.mjs +6 -0
- package/src/standalone/session-protocol.mjs +1 -1
- package/src/standalone/session-service/retention/busy.mjs +7 -2
- 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/dist/index.mjs +385 -104
- package/src/tui/session/notice-text.mjs +0 -1
- package/src/tui/session/session-api/intake/submission.mjs +7 -13
- package/src/tui/session/session-api/integrations.mjs +1 -5
- package/src/tui/session/session-flow/drain.mjs +8 -0
- package/src/tui/session/session-flow/steering.mjs +46 -0
- package/src/tui/session/session-flow.mjs +2 -0
- package/src/tui/session/turn-stream.mjs +33 -0
- package/src/tui/session/turn.mjs +30 -3
- 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
|
@@ -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);
|
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.1.
|
|
2
|
+
"version": "0.1.33",
|
|
3
3
|
"_comment": "Synced from immutable graph-v release assets.",
|
|
4
4
|
"assets": {
|
|
5
5
|
"darwin-arm64": {
|
|
6
|
-
"url": "https://github.com/tribgames/mixdog/releases/download/graph-v0.1.
|
|
7
|
-
"sha256": "
|
|
6
|
+
"url": "https://github.com/tribgames/mixdog/releases/download/graph-v0.1.33/mixdog-graph-darwin-arm64",
|
|
7
|
+
"sha256": "8637d61493eddca3eee80620a64e737f12eead44ea899ad19a18966a3843ff3a"
|
|
8
8
|
},
|
|
9
9
|
"darwin-x64": {
|
|
10
|
-
"url": "https://github.com/tribgames/mixdog/releases/download/graph-v0.1.
|
|
11
|
-
"sha256": "
|
|
10
|
+
"url": "https://github.com/tribgames/mixdog/releases/download/graph-v0.1.33/mixdog-graph-darwin-x64",
|
|
11
|
+
"sha256": "49ce311687c3df7e7080ecb7694219c9b51bbbb272864aa43d2102a8baa83550"
|
|
12
12
|
},
|
|
13
13
|
"linux-arm64": {
|
|
14
|
-
"url": "https://github.com/tribgames/mixdog/releases/download/graph-v0.1.
|
|
15
|
-
"sha256": "
|
|
14
|
+
"url": "https://github.com/tribgames/mixdog/releases/download/graph-v0.1.33/mixdog-graph-linux-arm64",
|
|
15
|
+
"sha256": "2e2a4ea6dccc5b33f583040b0ee6e8d47f93a1e879eb17343acd0b2f9838696f"
|
|
16
16
|
},
|
|
17
17
|
"linux-x64": {
|
|
18
|
-
"url": "https://github.com/tribgames/mixdog/releases/download/graph-v0.1.
|
|
19
|
-
"sha256": "
|
|
18
|
+
"url": "https://github.com/tribgames/mixdog/releases/download/graph-v0.1.33/mixdog-graph-linux-x64",
|
|
19
|
+
"sha256": "2cd1caa7f39e183d6fb6f7764f49e9a0643863d137c2bfb5f40bb7ac616c8d73"
|
|
20
20
|
},
|
|
21
21
|
"win32-arm64": {
|
|
22
|
-
"url": "https://github.com/tribgames/mixdog/releases/download/graph-v0.1.
|
|
23
|
-
"sha256": "
|
|
22
|
+
"url": "https://github.com/tribgames/mixdog/releases/download/graph-v0.1.33/mixdog-graph-win32-arm64.exe",
|
|
23
|
+
"sha256": "592dfa7e95e1e91424c7467e74f35d09758de502be403b7d229444b435600392"
|
|
24
24
|
},
|
|
25
25
|
"win32-x64": {
|
|
26
|
-
"url": "https://github.com/tribgames/mixdog/releases/download/graph-v0.1.
|
|
27
|
-
"sha256": "
|
|
26
|
+
"url": "https://github.com/tribgames/mixdog/releases/download/graph-v0.1.33/mixdog-graph-win32-x64.exe",
|
|
27
|
+
"sha256": "0ed17859a39f0160421865f3a3486ce53957b836ee164d606434519b85b90830"
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
}
|
|
@@ -27,14 +27,14 @@ export function unregisterOwnedShellTree(jobId, entry) {
|
|
|
27
27
|
if (ownedTrees.get(key) === entry) ownedTrees.delete(key);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
export function
|
|
34
|
-
const owner = String(ownerSessionId
|
|
30
|
+
/** Prepare the kill of every registered tree — of one owner, or of all when
|
|
31
|
+
* `ownerSessionId` is null (runtime shutdown) — and unregister them. Returns
|
|
32
|
+
* the snapshots still pending (empty when all were complete). */
|
|
33
|
+
export function prepareOwnedShellTreeKills(ownerSessionId = null) {
|
|
34
|
+
const owner = ownerSessionId == null ? null : String(ownerSessionId).trim();
|
|
35
35
|
const pending = [];
|
|
36
36
|
for (const [jobId, entry] of [...ownedTrees]) {
|
|
37
|
-
if (String(entry.ownerSessionId || '') !== owner) continue;
|
|
37
|
+
if (owner !== null && String(entry.ownerSessionId || '') !== owner) continue;
|
|
38
38
|
let ready;
|
|
39
39
|
try {
|
|
40
40
|
ready = entry.prepareKill();
|
|
@@ -44,6 +44,15 @@ export function cancelOwnedShellTrees(ownerSessionId) {
|
|
|
44
44
|
if (ready !== true) pending.push(Promise.resolve(ready).catch(() => false));
|
|
45
45
|
unregisterOwnedShellTree(jobId, entry);
|
|
46
46
|
}
|
|
47
|
+
return pending;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Cancel every shell tree of one owner session. Synchronous (the native
|
|
51
|
+
* cancel's own result) when every snapshot is already complete; otherwise a
|
|
52
|
+
* promise that sends the cancel once the snapshots land or the bound passes. */
|
|
53
|
+
export function cancelOwnedShellTrees(ownerSessionId) {
|
|
54
|
+
const owner = String(ownerSessionId || '').trim();
|
|
55
|
+
const pending = prepareOwnedShellTreeKills(owner);
|
|
47
56
|
if (pending.length === 0) return cancelNativeTasks({ ownerSessionId: owner });
|
|
48
57
|
let result = null;
|
|
49
58
|
const send = () => {
|
|
@@ -32,6 +32,9 @@ export const TERMINATION_RECHECK_MS = 5_000;
|
|
|
32
32
|
// read is not abandoned — a snapshot that lands later is still absorbed.
|
|
33
33
|
export const PROCESS_TABLE_READ_BOUND_MS = 2_000;
|
|
34
34
|
|
|
35
|
+
// Kill-and-observe rounds of a survivor kill before it reports what is left.
|
|
36
|
+
const KILL_ROUNDS = 3;
|
|
37
|
+
|
|
35
38
|
/** Resolve `promise`'s value, or `onTimeout` once `ms` elapse first. The
|
|
36
39
|
* bound's timer is cleared whichever side wins. */
|
|
37
40
|
export function withinBound(promise, ms, onTimeout) {
|
|
@@ -169,13 +172,30 @@ export function createProcessTreeTracker({ pid, members = [], exitObserved = fal
|
|
|
169
172
|
};
|
|
170
173
|
}
|
|
171
174
|
|
|
175
|
+
/** Terminate every identity the last observation found alive (console hosts
|
|
176
|
+
* excepted: they are witnesses, never workers). These are processes of a tree
|
|
177
|
+
* that was KILLED — they escaped its process group (setsid, job control, a
|
|
178
|
+
* double fork that kept its parent link) or outlived the root on Windows —
|
|
179
|
+
* so the kill is not finished while they run. Windows: taskkill /T /F;
|
|
180
|
+
* POSIX: SIGTERM, then SIGKILL after a short grace. */
|
|
181
|
+
function sweepLiveIdentities(tracker) {
|
|
182
|
+
const targets = tracker.live
|
|
183
|
+
.filter((entry) => entry.token != null && !CONSOLE_HOST.test(entry.name))
|
|
184
|
+
.map((entry) => entry.pid);
|
|
185
|
+
return targets.length > 0 ? killProcessTrees(targets) : Promise.resolve();
|
|
186
|
+
}
|
|
187
|
+
|
|
172
188
|
/** One observation loop: observe now, then every `intervalMs` until the tree
|
|
173
189
|
* is confirmed gone, then run `onTerminated` once. 'running', 'unknown', a
|
|
174
190
|
* failed or unanswered (by the next cadence tick) observation and a failing
|
|
175
191
|
* `onTerminated` all re-check on the same cadence; the first pass that is not
|
|
176
192
|
* 'gone' calls `onUnconfirmed` once. The returned stop() clears the pending
|
|
177
193
|
* timer; nothing else (listener, timer) outlives the loop. Nothing in it ever
|
|
178
|
-
* releases on time alone.
|
|
194
|
+
* releases on time alone.
|
|
195
|
+
*
|
|
196
|
+
* `sweep` (a killed tree): a pass that finds captured identities alive
|
|
197
|
+
* terminates them and observes again in the same pass, so a cancellation
|
|
198
|
+
* ends with the tree gone instead of a held folder over live processes. */
|
|
179
199
|
export function watchTermination({
|
|
180
200
|
tracker,
|
|
181
201
|
rootExited = () => true,
|
|
@@ -183,6 +203,7 @@ export function watchTermination({
|
|
|
183
203
|
onUnconfirmed = null,
|
|
184
204
|
releaseRequested = null,
|
|
185
205
|
intervalMs = TERMINATION_RECHECK_MS,
|
|
206
|
+
sweep = false,
|
|
186
207
|
}) {
|
|
187
208
|
let timer = null;
|
|
188
209
|
let stopped = false;
|
|
@@ -206,6 +227,17 @@ export function watchTermination({
|
|
|
206
227
|
observation.catch(() => {});
|
|
207
228
|
// A pass that has not answered by the next cadence tick is unknown.
|
|
208
229
|
state = await withinBound(observation, intervalMs, 'unknown');
|
|
230
|
+
if (state === 'running' && sweep && !stopped) {
|
|
231
|
+
await withinBound(
|
|
232
|
+
sweepLiveIdentities(tracker).catch(() => {}),
|
|
233
|
+
intervalMs,
|
|
234
|
+
null
|
|
235
|
+
);
|
|
236
|
+
await observation.catch(() => {});
|
|
237
|
+
observation = tracker.observe({ rootExited: rootExited() });
|
|
238
|
+
observation.catch(() => {});
|
|
239
|
+
state = await withinBound(observation, intervalMs, 'unknown');
|
|
240
|
+
}
|
|
209
241
|
} catch {
|
|
210
242
|
state = 'unknown';
|
|
211
243
|
}
|
|
@@ -365,7 +397,13 @@ export async function killShellDescendants(handle) {
|
|
|
365
397
|
.map((entry) => entry.pid);
|
|
366
398
|
await killProcessTrees(targets).catch(() => {});
|
|
367
399
|
const tracker = trackerFor(handle);
|
|
368
|
-
|
|
400
|
+
let state = await tracker.observe({ rootExited: true });
|
|
401
|
+
// What the first kill missed (a child forked meanwhile, a slow exit) is
|
|
402
|
+
// found by the re-observation itself and killed in the next round.
|
|
403
|
+
for (let round = 1; state === 'running' && round < KILL_ROUNDS; round += 1) {
|
|
404
|
+
await sweepLiveIdentities(tracker).catch(() => {});
|
|
405
|
+
state = await tracker.observe({ rootExited: true });
|
|
406
|
+
}
|
|
369
407
|
return { terminated: state === 'gone', survivors: tracker.live.map((entry) => entry.pid) };
|
|
370
408
|
} catch {
|
|
371
409
|
return { terminated: false, survivors: [...handle.watchPids] };
|
|
@@ -75,8 +75,8 @@ export function killAfterFailedPromotion(run, reason, promotionFailure) {
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
/**
|
|
78
|
-
* The promoted job leaves foreground admission: its lease is RELEASED
|
|
79
|
-
*
|
|
78
|
+
* The promoted job leaves foreground admission: its lease is RELEASED. A
|
|
79
|
+
* long-lived server must never
|
|
80
80
|
* hold a foreground slot for its whole life; background jobs are not counted
|
|
81
81
|
* against any cap (session/runtime close stops them via shutdownShellJobs).
|
|
82
82
|
*/
|
|
@@ -13,7 +13,18 @@ import {
|
|
|
13
13
|
} from '../shell-run-state.mjs';
|
|
14
14
|
|
|
15
15
|
const BACKGROUND_GUIDANCE =
|
|
16
|
-
'
|
|
16
|
+
'Its result is delivered automatically when it finishes; use task wait only if you need it now.';
|
|
17
|
+
|
|
18
|
+
function backgroundVerb(reason, secs) {
|
|
19
|
+
if (reason === 'timeout') return `moved to background at timeout after ${secs}s`;
|
|
20
|
+
if (reason === 'input') return `moved to background on new user input after ${secs}s`;
|
|
21
|
+
if (reason === 'notification') {
|
|
22
|
+
return `moved to background after ${secs}s because a notification arrived (delivered to you now)`;
|
|
23
|
+
}
|
|
24
|
+
if (reason === 'interrupt') return `moved to background on interrupt after ${secs}s`;
|
|
25
|
+
if (reason === 'background') return 'started in the background';
|
|
26
|
+
return `moved to background after the ${secs}s hold`;
|
|
27
|
+
}
|
|
17
28
|
|
|
18
29
|
export function promotedSpillPaths(taskOutput) {
|
|
19
30
|
return {
|
|
@@ -89,8 +100,7 @@ export function resolveBackgrounded(run, { jobId, reason, remainingBackgroundTim
|
|
|
89
100
|
// frame alive and could later kill an unrelated, already-returned job.
|
|
90
101
|
detachAbortHandler(run);
|
|
91
102
|
const secs = Math.max(0, Math.round(elapsedSinceStart(run) / 1000));
|
|
92
|
-
const verb =
|
|
93
|
-
reason === 'timeout' ? `moved to background at timeout after ${secs}s` : `auto-backgrounded after ${secs}s`;
|
|
103
|
+
const verb = backgroundVerb(reason, secs);
|
|
94
104
|
run.resolveResult(
|
|
95
105
|
new ExecResult({
|
|
96
106
|
...capturedFields(run, capture),
|
|
@@ -56,6 +56,8 @@ export function releaseAdmissionOnConfirmedTermination(run, { markNow = true } =
|
|
|
56
56
|
run.stopTerminationWatch = watchTermination({
|
|
57
57
|
tracker: run.terminationTracker,
|
|
58
58
|
rootExited: () => child.exitCode != null || child.signalCode != null,
|
|
59
|
+
// A killed run is not over while processes it started still run.
|
|
60
|
+
sweep: run.killed === true,
|
|
59
61
|
onTerminated: release,
|
|
60
62
|
onUnconfirmed: markNow ? null : () => keepTerminationUnconfirmedRecord(run),
|
|
61
63
|
releaseRequested: () => takeReleaseRequest(run.foregroundRecordId),
|
|
@@ -30,7 +30,9 @@ export function registerForegroundOwnedTree(run, ownerSessionId) {
|
|
|
30
30
|
run.killed = true;
|
|
31
31
|
run.ownerCancelled = true;
|
|
32
32
|
run.killCause = run.killCause || 'session-close';
|
|
33
|
-
|
|
33
|
+
// Always a fresh read: an earlier one predates what the run started
|
|
34
|
+
// since. Pending, the kill is sent at the snapshot bound regardless.
|
|
35
|
+
return capturePreKill(run);
|
|
34
36
|
},
|
|
35
37
|
};
|
|
36
38
|
registerOwnedShellTree(run.foregroundRecordId, run.ownedTree);
|
|
@@ -829,7 +829,7 @@ function unifiedUpdateHunks(sourceLines, section, displayPath, { fuzzy, rejectPa
|
|
|
829
829
|
const loc = resolveV4AHunkPosition(sourceLines, hunk, nextSearchLine, { fuzzy });
|
|
830
830
|
if (loc.skip) continue;
|
|
831
831
|
if (loc.error) {
|
|
832
|
-
const msg = `${loc.error.replace(/^V4A hunk /, `V4A hunk ${section.path}: `)}`;
|
|
832
|
+
const msg = `${loc.error.replace(/^V4A hunk /, () => `V4A hunk ${section.path}: `)}`;
|
|
833
833
|
if (rejectPartial) throw new Error(msg);
|
|
834
834
|
if (rejectedHunks) rejectedHunks.push({ file: section.path, hunk, reason: msg });
|
|
835
835
|
continue;
|