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
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
} from './tool-execution-contract.mjs';
|
|
8
8
|
import { presentErrorText } from './err-text.mjs';
|
|
9
9
|
import { clean } from './clean.mjs';
|
|
10
|
+
import { emitSessionActivityChange } from './session-activity-signal.mjs';
|
|
10
11
|
import {
|
|
11
12
|
parseTaskNotification,
|
|
12
13
|
renderTaskCompletionEnvelope,
|
|
@@ -104,12 +105,17 @@ function hasScopeCriteria(scope) {
|
|
|
104
105
|
return Boolean(scope?.callerSessionId || scope?.routingSessionId || scope?.clientHostPid);
|
|
105
106
|
}
|
|
106
107
|
|
|
107
|
-
function
|
|
108
|
+
function taskSessionIdOf(task) {
|
|
109
|
+
return task.ownerSessionId || task.notifyContext?.callerSessionId || task.notifyContext?.routingSessionId || null;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// `scope` is normalizeTaskScope(options), normalized once per scan by the
|
|
113
|
+
// caller: a scan is O(tasks), and the daemon runs one per session per
|
|
114
|
+
// busy-count, so per-task normalization multiplied into seconds under load.
|
|
115
|
+
function taskMatchesScope(task, scope, { includeUnattributed = true } = {}) {
|
|
108
116
|
if (!task) return false;
|
|
109
|
-
const scope = normalizeTaskScope(options);
|
|
110
117
|
if (!hasScopeCriteria(scope)) return true;
|
|
111
|
-
const taskSessionId =
|
|
112
|
-
task.ownerSessionId || task.notifyContext?.callerSessionId || task.notifyContext?.routingSessionId || null;
|
|
118
|
+
const taskSessionId = taskSessionIdOf(task);
|
|
113
119
|
const taskClientHostPid = task.clientHostPid || task.notifyContext?.clientHostPid || null;
|
|
114
120
|
// Legacy/unattributed tasks remain visible so old async jobs are still recoverable.
|
|
115
121
|
if (!taskSessionId && !taskClientHostPid) return includeUnattributed;
|
|
@@ -127,11 +133,13 @@ function pruneTasks(options = {}) {
|
|
|
127
133
|
const { force = false, surface } = options;
|
|
128
134
|
const now = Date.now();
|
|
129
135
|
const wanted = clean(surface);
|
|
130
|
-
|
|
136
|
+
const scope = normalizeTaskScope(options);
|
|
137
|
+
// Deleting the entry being visited is safe during Map iteration.
|
|
138
|
+
for (const [taskId, task] of tasks) {
|
|
131
139
|
if (wanted && task.surface !== wanted) continue;
|
|
132
|
-
if (!taskMatchesScope(task, options)) continue;
|
|
133
140
|
const finishedAt = task.finishedAtMs || 0;
|
|
134
|
-
if (force
|
|
141
|
+
if (!force && !(finishedAt > 0 && now - finishedAt > TASK_TTL_MS)) continue;
|
|
142
|
+
if (taskMatchesScope(task, scope)) tasks.delete(taskId);
|
|
135
143
|
}
|
|
136
144
|
if (tasks.size <= MAX_TASKS) return;
|
|
137
145
|
const removable = [...tasks.values()]
|
|
@@ -197,6 +205,7 @@ export function registerBackgroundTask({
|
|
|
197
205
|
notifyOnCancel: notifyOnCancel === true,
|
|
198
206
|
};
|
|
199
207
|
tasks.set(id, task);
|
|
208
|
+
emitSessionActivityChange(task.ownerSessionId || '');
|
|
200
209
|
return task;
|
|
201
210
|
}
|
|
202
211
|
|
|
@@ -230,38 +239,64 @@ export function getBackgroundTask(taskId, options = {}) {
|
|
|
230
239
|
if (!task) return null;
|
|
231
240
|
const wanted = clean(options.surface);
|
|
232
241
|
if (wanted && task.surface !== wanted) return null;
|
|
233
|
-
if (!taskMatchesScope(task, options)) return null;
|
|
242
|
+
if (!taskMatchesScope(task, normalizeTaskScope(options))) return null;
|
|
234
243
|
return task;
|
|
235
244
|
}
|
|
236
245
|
|
|
246
|
+
function countsAsActive(task, wanted, awaitedOnly) {
|
|
247
|
+
return task.status === 'running' && !(awaitedOnly && task.detached === true) && (!wanted || task.surface === wanted);
|
|
248
|
+
}
|
|
249
|
+
|
|
237
250
|
/** Lifetime signal: a session-owned background task remains live
|
|
238
|
-
* work even while the interactive turn is idle and every view is detached.
|
|
251
|
+
* work even while the interactive turn is idle and every view is detached.
|
|
252
|
+
* `awaitedOnly` leaves out `detached` tasks: processes a finished command
|
|
253
|
+
* deliberately left running (an app or server it launched), which nothing is
|
|
254
|
+
* waiting on and which may outlive the session's work by days.
|
|
255
|
+
* A read: pruning only ever drops finished tasks, which never count here. */
|
|
239
256
|
export function hasActiveBackgroundTasks(options = {}) {
|
|
240
|
-
pruneTasks(options);
|
|
241
257
|
const wanted = clean(options.surface);
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
258
|
+
const awaitedOnly = options.awaitedOnly === true;
|
|
259
|
+
const scope = normalizeTaskScope(options);
|
|
260
|
+
for (const task of tasks.values()) {
|
|
261
|
+
if (countsAsActive(task, wanted, awaitedOnly) && taskMatchesScope(task, scope, { includeUnattributed: false })) {
|
|
262
|
+
return true;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/** Every owner session `hasActiveBackgroundTasks({ callerSessionId, surface,
|
|
269
|
+
* awaitedOnly })` answers true for, from ONE pass over the tasks: a caller
|
|
270
|
+
* asking for every session (busy counts, pool rows) scans once instead of
|
|
271
|
+
* once per session. */
|
|
272
|
+
export function activeBackgroundTaskSessionIds(options = {}) {
|
|
273
|
+
const wanted = clean(options.surface);
|
|
274
|
+
const awaitedOnly = options.awaitedOnly === true;
|
|
275
|
+
const ids = new Set();
|
|
276
|
+
for (const task of tasks.values()) {
|
|
277
|
+
if (!countsAsActive(task, wanted, awaitedOnly)) continue;
|
|
278
|
+
const sessionId = taskSessionIdOf(task);
|
|
279
|
+
if (sessionId) ids.add(sessionId);
|
|
280
|
+
}
|
|
281
|
+
return ids;
|
|
248
282
|
}
|
|
249
283
|
|
|
250
284
|
export function listBackgroundTasks(options = {}) {
|
|
251
285
|
const { surface } = options;
|
|
252
286
|
pruneTasks(options);
|
|
253
287
|
const wanted = clean(surface);
|
|
288
|
+
const scope = normalizeTaskScope(options);
|
|
254
289
|
return [...tasks.values()]
|
|
255
290
|
.filter((task) => !wanted || task.surface === wanted)
|
|
256
|
-
.filter((task) => taskMatchesScope(task,
|
|
291
|
+
.filter((task) => taskMatchesScope(task, scope))
|
|
257
292
|
.map((task) => taskSummary(task));
|
|
258
293
|
}
|
|
259
294
|
|
|
260
295
|
export function cleanupBackgroundTasks(options = {}) {
|
|
261
296
|
const wanted = clean(options.surface);
|
|
297
|
+
const scope = normalizeTaskScope(options);
|
|
262
298
|
const countForSurface = () =>
|
|
263
|
-
[...tasks.values()].filter((task) => (!wanted || task.surface === wanted) && taskMatchesScope(task,
|
|
264
|
-
.length;
|
|
299
|
+
[...tasks.values()].filter((task) => (!wanted || task.surface === wanted) && taskMatchesScope(task, scope)).length;
|
|
265
300
|
const before = countForSurface();
|
|
266
301
|
pruneTasks(options);
|
|
267
302
|
const after = countForSurface();
|
|
@@ -331,6 +366,7 @@ export function cancelBackgroundTasks(options = {}) {
|
|
|
331
366
|
const reason = clean(options.reason) || 'cancelled';
|
|
332
367
|
const wanted = clean(options.surface);
|
|
333
368
|
const executionSessionId = clean(options.executionSessionId);
|
|
369
|
+
const scope = normalizeTaskScope(options);
|
|
334
370
|
let cancelled = 0;
|
|
335
371
|
for (const task of [...tasks.values()]) {
|
|
336
372
|
if (wanted && task.surface !== wanted) continue;
|
|
@@ -341,7 +377,7 @@ export function cancelBackgroundTasks(options = {}) {
|
|
|
341
377
|
// Delegated work executes in its bound session; before binding it still
|
|
342
378
|
// belongs to the registering session. Notification ownership is separate.
|
|
343
379
|
if ((clean(task.meta?.sessionId) || task.ownerSessionId) !== executionSessionId) continue;
|
|
344
|
-
} else if (!taskMatchesScope(task,
|
|
380
|
+
} else if (!taskMatchesScope(task, scope, { includeUnattributed: false })) continue;
|
|
345
381
|
if (TERMINAL_STATUSES.has(task.status)) {
|
|
346
382
|
if (options.notify === false) silenceCancelledNotification(task);
|
|
347
383
|
continue;
|
|
@@ -413,6 +449,7 @@ export function completeBackgroundTask(
|
|
|
413
449
|
if (error != null) task.error = presentErrorText(error, { surface: task.surface });
|
|
414
450
|
if (resultType) task.resultType = resultType;
|
|
415
451
|
if (instruction) task.notificationInstruction = compactText(instruction, 1_000);
|
|
452
|
+
emitSessionActivityChange(task.ownerSessionId || '');
|
|
416
453
|
if (notify) {
|
|
417
454
|
task.meta = sanitizeTaskMeta(task.meta);
|
|
418
455
|
notifyTaskCompletion(task, instruction);
|
|
@@ -522,6 +559,9 @@ export function renderBackgroundTaskNotification(task) {
|
|
|
522
559
|
: resultTextForTask(task);
|
|
523
560
|
if (task.surface === 'shell') {
|
|
524
561
|
const parsed = parseTaskNotification(result);
|
|
562
|
+
// The completion envelope already carries the result (exit code,
|
|
563
|
+
// duration, output or its summary): deliver it as is.
|
|
564
|
+
if (parsed?.result) return result;
|
|
525
565
|
return renderShellCompletionNotice({
|
|
526
566
|
jobId: task.taskId,
|
|
527
567
|
status: task.status,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { availableParallelism } from 'node:os';
|
|
1
|
+
import { availableParallelism, totalmem } from 'node:os';
|
|
2
2
|
import { createOwnerFairGate } from './owner-fair-gate.mjs';
|
|
3
3
|
import { currentToolExecutionOwner } from './tool-execution-owner.mjs';
|
|
4
4
|
import { positiveInt } from './numbers.mjs';
|
|
@@ -9,8 +9,9 @@ import { positiveInt } from './numbers.mjs';
|
|
|
9
9
|
// singleton semaphore CAN bound the number of concurrent child processes (rg,
|
|
10
10
|
// mixdog-graph, …) across ALL agents/workers in this daemon.
|
|
11
11
|
//
|
|
12
|
-
// Default: Windows search
|
|
13
|
-
// code-graph
|
|
12
|
+
// Default: Windows search and code-graph-query scale 2..8 with CPU count;
|
|
13
|
+
// code-graph builds 1..4 with cores and memory. Other platforms bound search
|
|
14
|
+
// only. Windows measurements
|
|
14
15
|
// showed both extremes are poor: cap 1 creates multi-session queue latency,
|
|
15
16
|
// while unbounded multithreaded rg amplifies Defender/process-scan and disk
|
|
16
17
|
// contention. Separate lanes isolate short search from long graph builds.
|
|
@@ -28,7 +29,8 @@ function resolveDefaultChildSpawnLaneMaxInflight(
|
|
|
28
29
|
laneName,
|
|
29
30
|
env = process.env,
|
|
30
31
|
platform = process.platform,
|
|
31
|
-
parallelism = availableParallelism()
|
|
32
|
+
parallelism = availableParallelism(),
|
|
33
|
+
memoryBytes = totalmem()
|
|
32
34
|
) {
|
|
33
35
|
const lane = _laneName(laneName);
|
|
34
36
|
const laneOverride = positiveInt(env[`MIXDOG_CHILD_SPAWN_${_laneEnvKey(lane)}_MAX_INFLIGHT`]);
|
|
@@ -45,13 +47,19 @@ function resolveDefaultChildSpawnLaneMaxInflight(
|
|
|
45
47
|
// Slots are held only across the spawn itself, so a small cap smooths the
|
|
46
48
|
// AV convoy without limiting how many commands run concurrently.
|
|
47
49
|
if (lane === 'process-spawn') return Math.max(2, Math.min(4, Math.floor(cpus / 6) || 2));
|
|
48
|
-
//
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
// Graph builds (Worker thread + native walk/parse) hold a slot for seconds
|
|
51
|
+
// and are memory-heavy: one per 4 cores and per 4 GiB, 1..4. Builds of one
|
|
52
|
+
// repo are already single-flight (build.mjs); distinct repos are independent.
|
|
53
|
+
if (lane === 'code-graph') {
|
|
54
|
+
const memGb = Math.floor((Number(memoryBytes) || 0) / 1024 ** 3);
|
|
55
|
+
return Math.max(1, Math.min(4, Math.floor(cpus / 4), Math.floor(memGb / 4)));
|
|
56
|
+
}
|
|
57
|
+
if (lane !== 'search' && lane !== 'code-graph-query') return 1;
|
|
58
|
+
// Short read-only walks: rg, and the graph binary's `--manifest` that
|
|
59
|
+
// validates a cached graph. Multiple processes beat one under multi-session
|
|
60
|
+
// load, but each is itself threaded and Defender amplifies excess fan-out.
|
|
61
|
+
// Burst stress measured cap-4 starvation (find p50 15s at 8 concurrent
|
|
62
|
+
// sessions), so scale with cores and cap at eight: 4→2, 8→3, 12→4, 18→6, 24+→8.
|
|
55
63
|
return Math.max(2, Math.min(8, Math.ceil(cpus / 3)));
|
|
56
64
|
}
|
|
57
65
|
|
|
@@ -87,11 +95,13 @@ function _laneSetting(name, suffix, fallback) {
|
|
|
87
95
|
// ── Lanes ────────────────────────────────────────────────────────────────
|
|
88
96
|
// Independent optional limits and queues:
|
|
89
97
|
// 'search' — short-lived rg processes.
|
|
90
|
-
// 'code-graph' — long-lived graph workers
|
|
91
|
-
//
|
|
92
|
-
//
|
|
93
|
-
//
|
|
94
|
-
//
|
|
98
|
+
// 'code-graph' — long-lived graph build workers. A cold build can hold its
|
|
99
|
+
// slot for seconds-to-minutes; a single shared lane would let
|
|
100
|
+
// one build stall every rg spawn behind it. Separate lanes
|
|
101
|
+
// remove that starvation class while keeping each spawn
|
|
102
|
+
// family bounded.
|
|
103
|
+
// 'code-graph-query' — the short read-only manifest walk that validates
|
|
104
|
+
// a cached graph, so queries never wait behind builds.
|
|
95
105
|
function _makeLane(name) {
|
|
96
106
|
const limit = resolveDefaultChildSpawnLaneMaxInflight(name);
|
|
97
107
|
const queueMax = _laneSetting(name, 'MAX_QUEUE', 1024);
|
|
@@ -608,7 +608,6 @@ export function updateSectionAsync(section, updater) {
|
|
|
608
608
|
export const SECRET_ACCOUNTS = Object.freeze({
|
|
609
609
|
agentApiKey: (provider) => `agent.${provider}.apiKey`,
|
|
610
610
|
openaiUsageSessionKey: 'agent.openai.usageSessionKey',
|
|
611
|
-
opencodeGoConsoleKey: 'agent.opencode-go.consoleKey',
|
|
612
611
|
});
|
|
613
612
|
|
|
614
613
|
// ── Secret-aware getters ─────────────────────────────────────────────────────
|
|
@@ -639,15 +638,6 @@ export function getOpenAIUsageSessionKey() {
|
|
|
639
638
|
);
|
|
640
639
|
}
|
|
641
640
|
|
|
642
|
-
export function getOpenCodeGoConsoleKey() {
|
|
643
|
-
return (
|
|
644
|
-
process.env.OPENCODE_CONSOLE_API_KEY ||
|
|
645
|
-
process.env.OPENCODE_GO_CONSOLE_API_KEY ||
|
|
646
|
-
process.env.MIXDOG_OPENCODE_CONSOLE_API_KEY ||
|
|
647
|
-
_readSecret(SECRET_ACCOUNTS.opencodeGoConsoleKey)
|
|
648
|
-
);
|
|
649
|
-
}
|
|
650
|
-
|
|
651
641
|
/**
|
|
652
642
|
* Persist a secret to the OS keychain. Throws on failure.
|
|
653
643
|
* Never writes to mixdog-config.json.
|
|
@@ -24,7 +24,13 @@ import { createKeyedSerialQueue } from './keyed-serial-queue.mjs';
|
|
|
24
24
|
import { sleep, sleepSync } from './sleep.mjs';
|
|
25
25
|
|
|
26
26
|
const LOCK_WAIT_CODES = new Set(['EEXIST', 'EPERM', 'EACCES', 'EBUSY']);
|
|
27
|
-
|
|
27
|
+
// Cross-process waits must poll (in-process waiters already queue on
|
|
28
|
+
// lockQueue and wake on release). Each sleep is capped at 200 ms: longer
|
|
29
|
+
// sleeps overshoot a release by up to their full length, and the synchronous
|
|
30
|
+
// paths block the event loop for each sleep. The schedule keeps the earlier
|
|
31
|
+
// ~4.2 s total window for rename retries (Windows AV/indexer file holds).
|
|
32
|
+
const RETRY_MAX_MS = 200;
|
|
33
|
+
export const DEFAULT_BACKOFFS_MS = Object.freeze([25, 50, 100, ...Array(20).fill(RETRY_MAX_MS)]);
|
|
28
34
|
const configuredLockTimeoutMs = Number(process.env.MIXDOG_LOCK_TIMEOUT_MS);
|
|
29
35
|
const DEFAULT_LOCK_TIMEOUT_MS =
|
|
30
36
|
Number.isFinite(configuredLockTimeoutMs) && configuredLockTimeoutMs >= 0 ? configuredLockTimeoutMs : 2000;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Worker side of file-permissions.mjs's sync bridge: owner-only enforcement
|
|
2
|
+
// for synchronous callers, through this thread's own long-lived ACL helper.
|
|
3
|
+
// Every request is answered on the port, then the shared counter (slot 0) is
|
|
4
|
+
// bumped and notified so the blocked caller wakes; slot 1 marks this thread
|
|
5
|
+
// gone, slot 2 marks it ready.
|
|
6
|
+
import { workerData } from 'node:worker_threads';
|
|
7
|
+
import { enforceOwnerOnlyAclWin32Async, prewarmOwnerOnlyAclWin32 } from './file-permissions.mjs';
|
|
8
|
+
|
|
9
|
+
const { port, signal } = workerData;
|
|
10
|
+
|
|
11
|
+
function wake() {
|
|
12
|
+
Atomics.add(signal, 0, 1);
|
|
13
|
+
Atomics.notify(signal, 0);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
process.on('exit', () => {
|
|
17
|
+
Atomics.store(signal, 1, 1);
|
|
18
|
+
wake();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
port.on('message', async (request) => {
|
|
22
|
+
if (request?.warm === true) {
|
|
23
|
+
await prewarmOwnerOnlyAclWin32({ bridge: false });
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
let reply;
|
|
27
|
+
try {
|
|
28
|
+
await enforceOwnerOnlyAclWin32Async(request.path, { fresh: true });
|
|
29
|
+
reply = { id: request.id, ok: true };
|
|
30
|
+
} catch (error) {
|
|
31
|
+
reply = { id: request.id, ok: false, message: String(error?.message || error), code: error?.code ?? null };
|
|
32
|
+
}
|
|
33
|
+
port.postMessage(reply);
|
|
34
|
+
wake();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
Atomics.store(signal, 2, 1);
|
|
38
|
+
wake();
|
|
@@ -1,8 +1,23 @@
|
|
|
1
1
|
export function enforceOwnerOnlyAclWin32(targetPath: string, options?: { fresh?: boolean }): void;
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
/** Test hook: the live per-process ACL helper, or null. */
|
|
4
|
+
export function ownerOnlyAclHelperForTests(): import('node:child_process').ChildProcess | null;
|
|
5
|
+
|
|
6
|
+
/** Test/diagnostic hook: helper attachment, pending requests, starts in the restart window. */
|
|
7
|
+
export function ownerOnlyAclHelperStats(): {
|
|
8
|
+
alive: boolean;
|
|
9
|
+
pid: number | null;
|
|
10
|
+
pending: number;
|
|
11
|
+
recentStarts: number;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/** Non-fresh calls verify (and tighten) the real DACL on every call through a shared helper. */
|
|
15
|
+
export function enforceOwnerOnlyAclWin32Async(targetPath: string, options?: { fresh?: boolean }): Promise<void>;
|
|
7
16
|
|
|
8
17
|
export function enforceOwnerOnlyDirectoryWin32Async(targetPath: string): Promise<void>;
|
|
18
|
+
|
|
19
|
+
/** Test hook: synchronous calls skip the sync bridge and use the one-shot update. */
|
|
20
|
+
export function disableOwnerOnlyAclSyncBridgeForTests(): void;
|
|
21
|
+
|
|
22
|
+
/** Starts this thread's ACL helper and the sync bridge off any write path. Never rejects. */
|
|
23
|
+
export function prewarmOwnerOnlyAclWin32(options?: { bridge?: boolean }): Promise<void>;
|