mixdog 1.4.1 → 1.4.3
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 +4 -3
- package/scripts/build-shipped-history.mjs +125 -33
- package/scripts/gate-local.mjs +220 -63
- package/scripts/graph-parity.mjs +8 -3
- package/scripts/lib/gate-scheduler.mjs +139 -32
- package/scripts/lib/gate-timing-reporter.mjs +16 -0
- package/scripts/lib/run-node-tests.mjs +71 -34
- package/scripts/lib/scoped-temp.mjs +1 -0
- package/scripts/lib/test-failure-records.mjs +14 -1
- package/scripts/lib/test-failure-summary.mjs +9 -4
- package/scripts/lib/test-spawn-ledger.mjs +43 -3
- package/scripts/post-release-check.mjs +26 -16
- package/scripts/pptx-kit-index.mjs +5 -6
- package/scripts/provider-pingpong-live.mjs +1 -1
- package/scripts/prune-embedding-runtime.mjs +3 -1
- package/scripts/release-paths.mjs +7 -1
- package/scripts/suite-health.mjs +110 -28
- package/scripts/test.mjs +9 -14
- package/src/agents/advisor/AGENT.md +4 -4
- package/src/agents/advisor/agent.json +1 -1
- package/src/agents/explore/AGENT.md +22 -0
- package/src/agents/explore/agent.json +6 -0
- package/src/cli.mjs +7 -0
- package/src/defaults/agents.json +7 -0
- package/src/defaults/shipped-history.json +38 -2
- package/src/defaults/skills/browser-use/SKILL.md +4 -1
- package/src/defaults/skills/code-tidy/SKILL.md +71 -102
- package/src/defaults/skills/code-tidy/references/agent-cleanup.md +66 -114
- package/src/defaults/skills/code-tidy/references/cleanup-report.md +19 -35
- package/src/defaults/skills/code-tidy/references/dead-code.md +3 -9
- package/src/defaults/skills/code-tidy/references/test-suite-slop.md +16 -27
- package/src/defaults/skills/computer-use/SKILL.md +12 -2
- package/src/defaults/skills/setup/SKILL.md +2 -2
- package/src/defaults/skills/setup/references/actions.md +28 -9
- package/src/defaults/skills/setup/references/surfaces.md +5 -2
- package/src/defaults/skills/setup-guide/SKILL.md +11 -3
- package/src/defaults/skills/setup-guide/model-recommendations.json +13 -0
- package/src/defaults/skills/skill-creator/SKILL.md +85 -190
- package/src/defaults/skills/skill-creator/references/design.md +70 -162
- package/src/defaults/skills/skill-creator/references/evaluation.md +33 -92
- package/src/defaults/skills/test-suite/SKILL.md +194 -0
- package/src/defaults/skills/test-suite/references/case-management.md +51 -0
- package/src/defaults/skills/test-suite/references/flaky-policy.md +39 -0
- package/src/defaults/skills/test-suite/references/reliability.md +49 -0
- package/src/defaults/skills/test-suite/references/suite-design.md +78 -0
- package/src/defaults/skills/test-suite/scripts/inventory.mjs +335 -0
- package/src/defaults/skills/visualize/SKILL.md +6 -2
- package/src/lib/instruction-text.cjs +36 -0
- package/src/lib/rules-builder.cjs +40 -50
- package/src/orchestration/balanced.md +23 -0
- package/src/orchestration/focused.md +22 -0
- package/src/orchestration/none.md +5 -0
- package/src/orchestration/swarm.md +24 -0
- package/src/rules/agent-mode/AGENT_MODE.md +3 -1
- package/src/rules/agent-mode/MIXY.md +2 -2
- package/src/rules/lead/LEAD.md +3 -3
- package/src/rules/shared/20-research.md +3 -6
- package/src/rules/shared/40-editing.md +1 -0
- package/src/rules/shared/60-verification.md +10 -9
- package/src/rules/shared/70-delivery.md +4 -3
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/abort-link.mjs +5 -1
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/session-prep.mjs +3 -3
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +10 -2
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +132 -21
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +13 -9
- package/src/runtime/agent/orchestrator/agent-runtime/heartbeat-completion.mjs +2 -2
- package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +4 -1
- package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +67 -0
- package/src/runtime/agent/orchestrator/agent-trace-format.mjs +1 -0
- package/src/runtime/agent/orchestrator/config.mjs +12 -7
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +7 -7
- package/src/runtime/agent/orchestrator/context/role-instructions.mjs +9 -30
- package/src/runtime/agent/orchestrator/internal-agents.mjs +3 -14
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +124 -12
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +204 -49
- package/src/runtime/agent/orchestrator/mcp/client-config.mjs +16 -7
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +157 -57
- package/src/runtime/agent/orchestrator/mcp/client.mjs +54 -23
- package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +1 -1
- package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +8 -2
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +83 -52
- package/src/runtime/agent/orchestrator/mcp/oauth-probe.mjs +1 -1
- package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +14 -0
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +43 -27
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +43 -8
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +30 -28
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +31 -21
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-stop.mjs +3 -3
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +40 -0
- package/src/runtime/agent/orchestrator/providers/custom-provider-keys.mjs +34 -0
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/devin-auth.mjs +14 -7
- package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +48 -31
- package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +0 -18
- package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +138 -6
- package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/model-cache.mjs +100 -33
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/oauth-secret-fields.fixtures.mjs +45 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +4 -6
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2784 -2872
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +5 -8
- package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +26 -28
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +288 -300
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/registry.mjs +33 -2
- package/src/runtime/agent/orchestrator/providers/vertex-ai-auth.mjs +622 -0
- package/src/runtime/agent/orchestrator/providers/vertex-ai-maas.mjs +185 -0
- package/src/runtime/agent/orchestrator/providers/vertex-ai-models.mjs +445 -0
- package/src/runtime/agent/orchestrator/providers/vertex-ai.mjs +576 -0
- package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +10 -30
- package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +32 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +0 -11
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +8 -0
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +17 -3
- package/src/runtime/agent/orchestrator/runtime-core/goal-control.mjs +47 -27
- package/src/runtime/agent/orchestrator/runtime-core/goal-deadlines.mjs +141 -10
- package/src/runtime/agent/orchestrator/runtime-core/goal-mutations.mjs +26 -63
- package/src/runtime/agent/orchestrator/runtime-core/goal-reminder.mjs +28 -3
- package/src/runtime/agent/orchestrator/runtime-core/goal-runtime.mjs +36 -11
- package/src/runtime/agent/orchestrator/runtime-core/goal-state.mjs +88 -56
- package/src/runtime/agent/orchestrator/runtime-core/goal-storage.mjs +4 -1
- package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +51 -32
- package/src/runtime/agent/orchestrator/runtime-core/goal-text.mjs +45 -145
- package/src/runtime/agent/orchestrator/runtime-core/goal-tool-defs.mjs +15 -98
- package/src/runtime/agent/orchestrator/runtime-core/goal-tool-exec.mjs +32 -99
- package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +23 -78
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +69 -47
- package/src/runtime/agent/orchestrator/runtime-core/todo-list.mjs +367 -0
- package/src/runtime/agent/orchestrator/runtime-core/todo-tool-defs.mjs +47 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-availability.mjs +155 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +12 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +119 -35
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +4 -1
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +15 -6
- package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +28 -22
- package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +30 -0
- package/src/runtime/agent/orchestrator/session/agent-room.d.mts +30 -5
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +171 -37
- package/src/runtime/agent/orchestrator/session/attachment-preflight.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/cache-warm.mjs +94 -10
- package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/compact/summary-route.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -12
- package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +4 -4
- package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +11 -6
- package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +6 -6
- package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +7 -3
- package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +11 -1
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -3
- package/src/runtime/agent/orchestrator/session/human-gate/held-message.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +37 -8
- package/src/runtime/agent/orchestrator/session/human-gate/run-policy.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/image-strip-recovery.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +11 -1
- package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +5 -3
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +8 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/todo-check.mjs +196 -0
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +116 -50
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +8 -1
- package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +5 -6
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +27 -3
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +18 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +23 -1
- package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +13 -8
- package/src/runtime/agent/orchestrator/session/loop/turn-report.mjs +35 -0
- package/src/runtime/agent/orchestrator/session/loop/usage.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +103 -50
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +9 -7
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +21 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-failure.mjs +27 -11
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-open.mjs +37 -34
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +25 -15
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +79 -24
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +12 -1
- package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/idle-cleanup.mjs +6 -1
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +9 -1
- package/src/runtime/agent/orchestrator/session/manager/pending-spool-path.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/manager/pending-spool-shard.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/prompt-settings.mjs +598 -0
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +20 -0
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +22 -14
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +12 -0
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +56 -14
- package/src/runtime/agent/orchestrator/session/manager/session-lock.mjs +31 -0
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +59 -20
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/session-scratch-environment.mjs +70 -0
- package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +0 -3
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +18 -4
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +8 -9
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +339 -88
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-recovery.mjs +135 -11
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +377 -104
- package/src/runtime/agent/orchestrator/session/manager/turn-durability.mjs +144 -0
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +48 -30
- package/src/runtime/agent/orchestrator/session/manager/turn-reap.mjs +125 -0
- package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/mixy-name.mjs +12 -6
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +8 -1
- package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/save-session-worker.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/store/canonical-reader.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/liveness-veto.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +23 -2
- package/src/runtime/agent/orchestrator/session/store/sweep/sub-agent-retention.mjs +3 -3
- package/src/runtime/agent/orchestrator/session/store/transcript-durability.mjs +88 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/store-summary-log.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +243 -38
- package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +163 -64
- package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +177 -8
- package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +142 -18
- package/src/runtime/agent/orchestrator/session/store.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/synthetic-user-envelope.mjs +7 -1
- package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +9 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/agent-envelope.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +2 -2
- package/src/runtime/agent/orchestrator/stall-policy.mjs +3 -5
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +4 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +21 -3
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/worktree-add-guard.mjs +77 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +0 -1
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +42 -28
- package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +30 -14
- package/src/runtime/agent/orchestrator/tools/builtin/lib/search-input-helpers.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +58 -20
- package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-fast-paths.mjs +0 -1
- package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +20 -15
- package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +0 -10
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +95 -20
- package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +59 -10
- package/src/runtime/agent/orchestrator/tools/builtin.mjs +1 -24
- package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary/child-kill.mjs +4 -3
- package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary.mjs +1 -2
- package/src/runtime/agent/orchestrator/tools/code-graph/modes/calls.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/modes/symbols.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +4 -5
- package/src/runtime/agent/orchestrator/tools/code-graph/symbol-index.mjs +3 -4
- package/src/runtime/agent/orchestrator/tools/code-graph.mjs +4 -22
- package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
- package/src/runtime/agent/orchestrator/tools/lib/native-spawn-client.mjs +99 -2
- package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +2 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +105 -15
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +49 -15
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +45 -27
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +35 -11
- package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +2 -0
- package/src/runtime/agent/orchestrator/tools/lib/wait-until-fixture.mjs +26 -0
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -6
- package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +0 -1
- package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
- package/src/runtime/attachments/attachment-reference.mjs +1 -1
- package/src/runtime/attachments/pdf-extract.mjs +1 -1
- package/src/runtime/attachments/store.d.mts +1 -0
- package/src/runtime/attachments/store.mjs +2 -2
- package/src/runtime/channels/lib/config-reload-watch.mjs +42 -0
- package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +29 -9
- package/src/runtime/channels/lib/scheduler.mjs +33 -0
- package/src/runtime/channels/lib/schedules-db.mjs +11 -4
- package/src/runtime/channels/lib/webhook/session-dispatch.mjs +4 -1
- package/src/runtime/channels/lib/webhooks-db.mjs +9 -3
- package/src/runtime/channels/lib/whisper-port.mjs +19 -10
- package/src/runtime/channels/lib/whisper-server.mjs +22 -13
- package/src/runtime/channels/lib/worker-main.mjs +9 -31
- package/src/runtime/computer-bridge/linux-readiness.mjs +10 -14
- package/src/runtime/connectors/connector-accounts-mcp.mjs +372 -103
- package/src/runtime/connectors/gmail-app-password.mjs +4 -4
- package/src/runtime/connectors/google-mcp.mjs +1 -1
- package/src/runtime/effort-judge/judge-client.mjs +2 -2
- package/src/runtime/effort-judge/judge-input.mjs +4 -4
- package/src/runtime/explore/explorer.mjs +88 -0
- package/src/runtime/explore/tool-defs.mjs +35 -0
- package/src/runtime/explore/tool.mjs +123 -0
- package/src/runtime/local-provider/hardware.mjs +1 -1
- package/src/runtime/media/adapters/codex-image.mjs +3 -3
- package/src/runtime/media/adapters/gemini-video.mjs +1 -1
- package/src/runtime/media/media-usage.mjs +1 -1
- package/src/runtime/media/store.mjs +1 -1
- package/src/runtime/memory/index.mjs +15 -1
- package/src/runtime/memory/lib/embedding-provider.mjs +4 -1
- package/src/runtime/memory/lib/embedding-reindex.mjs +27 -0
- package/src/runtime/memory/lib/embedding-worker.mjs +4 -0
- package/src/runtime/memory/lib/memory-embed.mjs +83 -14
- package/src/runtime/memory/lib/memory-process-lock.mjs +159 -36
- package/src/runtime/memory/lib/memory-text-utils.mjs +6 -1
- package/src/runtime/memory/lib/memory.mjs +17 -0
- package/src/runtime/memory/lib/pg/process.mjs +1 -1
- package/src/runtime/memory/lib/pg/supervisor.mjs +16 -96
- package/src/runtime/memory/lib/recall-hybrid/hybrid-sql.mjs +12 -3
- package/src/runtime/office/authoring/docx-html-runner.mjs +1 -1
- package/src/runtime/office/authoring/pptx-author-action.mjs +1 -1
- package/src/runtime/office/authoring/xlsx-html-build.mjs +1 -1
- package/src/runtime/office/authoring/xlsx-html-runner.mjs +1 -1
- package/src/runtime/office/capabilities.mjs +1 -1
- package/src/runtime/office/core/office-core.mjs +1 -1
- package/src/runtime/office/design/content-model.mjs +3 -3
- package/src/runtime/office/design/docx/design-docx/section.mjs +6 -6
- package/src/runtime/office/design/xlsx/design-xlsx-components.mjs +1 -1
- package/src/runtime/office/design/xlsx/design-xlsx.mjs +1 -1
- package/src/runtime/office/pdf/ocr-engine.mjs +1 -1
- package/src/runtime/office/pdf/pdf-writer.mjs +4 -4
- package/src/runtime/office/portable/portable-docx-operations.mjs +2 -2
- package/src/runtime/office/portable/portable-soffice.mjs +8 -6
- package/src/runtime/office/portable/xlsx-contract.mjs +1 -1
- package/src/runtime/office/quality/assurance-structure-docx.mjs +1 -1
- package/src/runtime/shared/agent-route-config.mjs +17 -2
- package/src/runtime/shared/atomic-file.d.mts +8 -0
- package/src/runtime/shared/atomic-file.mjs +103 -2
- package/src/runtime/shared/background-tasks.mjs +37 -10
- package/src/runtime/shared/background-wait.mjs +66 -0
- package/src/runtime/shared/child-guardian.mjs +17 -7
- package/src/runtime/shared/config.mjs +313 -16
- package/src/runtime/shared/connector-accounts.mjs +5 -5
- package/src/runtime/shared/connector-catalog.d.mts +14 -8
- package/src/runtime/shared/connector-catalog.mjs +70 -52
- package/src/runtime/shared/custom-provider-keys.mjs +20 -0
- package/src/runtime/shared/file-has-data.mjs +26 -2
- package/src/runtime/shared/file-lock.mjs +21 -18
- package/src/runtime/shared/git-launch.d.mts +9 -0
- package/src/runtime/shared/git-launch.mjs +213 -0
- package/src/runtime/shared/git-runner-worker.mjs +2 -1
- package/src/runtime/shared/git-runner.mjs +7 -2
- package/src/runtime/shared/idle-gc.mjs +30 -7
- package/src/runtime/shared/llm/cost.mjs +6 -1
- package/src/runtime/shared/llm/http-agent.mjs +316 -29
- package/src/runtime/shared/llm/model-catalog-projection.mjs +3 -2
- package/src/runtime/shared/llm/model-catalog.mjs +46 -6
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +3 -0
- package/src/runtime/shared/llm/system-proxy.mjs +453 -0
- package/src/runtime/shared/llm/usage-ledger-quota.mjs +31 -12
- package/src/runtime/shared/llm/usage-ledger-rollup.mjs +84 -8
- package/src/runtime/shared/llm/usage-ledger.mjs +3 -0
- package/src/runtime/shared/llm/usage-rollup.mjs +48 -0
- package/src/runtime/shared/maintenance-schedule.mjs +109 -0
- package/src/runtime/shared/process-runner.mjs +8 -4
- package/src/runtime/shared/provider-accounts.mjs +52 -2
- package/src/runtime/shared/routine-trigger.d.mts +13 -0
- package/src/runtime/shared/routine-trigger.mjs +34 -0
- package/src/runtime/shared/run-child.d.mts +2 -1
- package/src/runtime/shared/run-child.mjs +70 -18
- package/src/runtime/shared/session-scratch.mjs +14 -2
- package/src/runtime/shared/shipped-definitions.mjs +7 -1
- package/src/runtime/shared/staged-install-worker.mjs +5 -0
- package/src/runtime/shared/staged-update.mjs +47 -2
- package/src/runtime/shared/tool-card-model.golden.json +3 -12
- package/src/runtime/shared/tool-execution-contract.mjs +2 -0
- package/src/runtime/shared/tool-surface.mjs +110 -36
- package/src/runtime/shared/tool-work-units.mjs +35 -6
- package/src/runtime/shared/turn-snapshot.mjs +26 -4
- package/src/runtime/shared/turn-worktree-snapshot.mjs +409 -54
- package/src/runtime/shared/worker-requests.mjs +17 -3
- package/src/runtime/shared/worktrees/activity-gate.mjs +215 -318
- package/src/runtime/shared/worktrees/activity-ledger-worker.mjs +56 -0
- package/src/runtime/shared/worktrees/activity-ledger.mjs +391 -0
- package/src/runtime/shared/worktrees/branch-management.mjs +5 -3
- package/src/runtime/shared/worktrees/contract.mjs +16 -6
- package/src/runtime/shared/worktrees/dependencies.mjs +127 -89
- package/src/runtime/shared/worktrees/disk.mjs +79 -2
- package/src/runtime/shared/worktrees/git.mjs +97 -7
- package/src/runtime/shared/worktrees/include.mjs +6 -4
- package/src/runtime/shared/worktrees/maintenance.mjs +422 -30
- package/src/runtime/shared/worktrees/manager.mjs +962 -197
- package/src/runtime/shared/worktrees/settings.mjs +33 -7
- package/src/runtime/shared/worktrees/test-support.mjs +5 -1
- package/src/runtime/shared/worktrees/worker-snapshots.mjs +82 -0
- package/src/runtime/tidy/install.mjs +95 -15
- package/src/runtime/tidy/languages.mjs +17 -15
- package/src/runtime/tidy/process.mjs +9 -5
- package/src/runtime/tidy/resolve.mjs +19 -16
- package/src/runtime/tidy/runners/biome.mjs +3 -3
- package/src/runtime/tidy/tool.mjs +1 -1
- package/src/runtime/tidy/worktree.mjs +10 -6
- package/src/runtime/visualize-bridge/client.mjs +4 -1
- package/src/runtime/visualize-bridge/tool-defs.mjs +7 -2
- package/src/runtime/web-search/index.mjs +4 -23
- package/src/runtime/web-search/lib/web-tools.mjs +2 -2
- package/src/runtime/web-search/tool-defs.mjs +17 -26
- package/src/session-runtime/agent-profile-changes.mjs +55 -4
- package/src/session-runtime/agent-task-sessions.mjs +410 -353
- package/src/session-runtime/boot/apis.mjs +27 -4
- package/src/session-runtime/boot/begin.mjs +2 -0
- package/src/session-runtime/boot/config.mjs +10 -1
- package/src/session-runtime/boot/facade.mjs +1 -0
- package/src/session-runtime/boot/providers.mjs +70 -3
- package/src/session-runtime/boot/session.mjs +2 -0
- package/src/session-runtime/boot/tools.mjs +71 -25
- package/src/session-runtime/bot-status.mjs +103 -103
- package/src/session-runtime/channel-config-api.mjs +1 -0
- package/src/session-runtime/config-change-effects.mjs +179 -0
- package/src/session-runtime/config-lifecycle/config-writers.mjs +1 -0
- package/src/session-runtime/config-lifecycle.mjs +160 -24
- package/src/session-runtime/connector-merge-migration.mjs +18 -15
- package/src/session-runtime/conversation-import/discovery.mjs +245 -47
- package/src/session-runtime/conversation-import/service.mjs +12 -5
- package/src/session-runtime/goal-facade-api.mjs +49 -3
- package/src/session-runtime/handoff-attachments.mjs +1 -1
- package/src/session-runtime/held-requests.mjs +3 -1
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +3 -0
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -2
- package/src/session-runtime/internal-tool-executor/feature-tools.mjs +5 -11
- package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +8 -0
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +161 -120
- package/src/session-runtime/internal-tool-executor.mjs +12 -19
- package/src/session-runtime/lifecycle/cold-heir.mjs +7 -0
- package/src/session-runtime/lifecycle/memory-ingest.mjs +3 -3
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +53 -5
- package/src/session-runtime/lifecycle/session-switch.mjs +13 -2
- package/src/session-runtime/lifecycle/teardown/session-close.mjs +10 -5
- package/src/session-runtime/lifecycle/teardown.mjs +1 -1
- package/src/session-runtime/lifecycle-api.mjs +1 -0
- package/src/session-runtime/mcp-glue/server-catalog.mjs +27 -10
- package/src/session-runtime/mcp-glue/server-connection.mjs +34 -8
- package/src/session-runtime/mcp-glue/server-input.mjs +4 -1
- package/src/session-runtime/mixy-heartbeat.mjs +1 -1
- package/src/session-runtime/model-route/set-route.mjs +40 -7
- package/src/session-runtime/native-web-search/routes.mjs +3 -3
- package/src/session-runtime/provider-auth/login.mjs +2 -2
- package/src/session-runtime/provider-auth/refresh.mjs +6 -3
- package/src/session-runtime/provider-auth/setup.mjs +1 -1
- package/src/session-runtime/provider-readiness.mjs +53 -4
- package/src/session-runtime/resource-api.mjs +1 -1
- package/src/session-runtime/resource-extension-sync.mjs +4 -8
- package/src/session-runtime/resource-mcp-api.mjs +98 -35
- package/src/session-runtime/resource-mcp-connector-accounts.mjs +49 -32
- package/src/session-runtime/resource-mcp-secrets.mjs +27 -10
- package/src/session-runtime/resource-mcp-servers.mjs +5 -4
- package/src/session-runtime/resource-plugins-api.mjs +4 -0
- package/src/session-runtime/routine-executor.mjs +152 -0
- package/src/session-runtime/routine-home-turn.mjs +46 -5
- package/src/session-runtime/runtime-facade.mjs +5 -0
- package/src/session-runtime/runtime-feature-gates.mjs +2 -11
- package/src/session-runtime/schedule-session-run.mjs +1 -0
- package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +6 -1
- package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +7 -0
- package/src/session-runtime/services/agent-tool/send-flow.mjs +120 -8
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +12 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +5 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +8 -3
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +28 -7
- package/src/session-runtime/services/agent-tool.mjs +51 -1
- package/src/session-runtime/services/agent-watchdog-registry.mjs +32 -4
- package/src/session-runtime/services/channel-admin.mjs +18 -0
- package/src/session-runtime/services/channel-worker/daemon-spawn.mjs +2 -0
- package/src/session-runtime/services/daemon-candidate.mjs +4 -1
- package/src/session-runtime/services/hook-bus/command-handler.mjs +7 -11
- package/src/session-runtime/services/memory-runtime-proxy/daemon-spawn.mjs +4 -0
- package/src/session-runtime/services/plugin-admin.mjs +14 -6
- package/src/session-runtime/services/provider-admin.mjs +281 -10
- package/src/session-runtime/services/seeds.mjs +7 -0
- package/src/session-runtime/services/usage-stats-model.mjs +32 -11
- package/src/session-runtime/session-create/materialize.mjs +4 -2
- package/src/session-runtime/session-create/session-options.mjs +2 -0
- package/src/session-runtime/session-turn-api.mjs +2 -0
- package/src/session-runtime/settings-builtin-tools-api.mjs +5 -10
- package/src/session-runtime/settings-system-api.mjs +1 -1
- package/src/session-runtime/setup-tool/agent-settings-actions.mjs +13 -3
- package/src/session-runtime/setup-tool/connector-widen-approval.mjs +96 -0
- package/src/session-runtime/setup-tool/executor.mjs +14 -3
- package/src/session-runtime/setup-tool/extended-actions.mjs +2 -0
- package/src/session-runtime/setup-tool/settings-contract.mjs +28 -0
- package/src/session-runtime/setup-tool/tool-defs.mjs +28 -2
- package/src/session-runtime/tool-policy/agent-profile-fold.mjs +40 -43
- package/src/session-runtime/tool-policy/mode-switch.mjs +1 -1
- package/src/session-runtime/tool-policy/policy-stage.mjs +106 -8
- package/src/session-runtime/tool-policy/workflow-overlay.mjs +2 -1
- package/src/session-runtime/tool-policy-refresh.mjs +182 -5
- package/src/session-runtime/tool-surface.mjs +38 -1
- package/src/session-runtime/turn/agent-ops.mjs +33 -2
- package/src/session-runtime/turn/session-ops.mjs +2 -0
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +5 -0
- package/src/session-runtime/turn/turn-run.mjs +1 -1
- package/src/session-runtime/webhook-session-run.mjs +2 -0
- package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +46 -11
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +2 -0
- package/src/session-runtime/workflow-agents-api/instruction-files.mjs +165 -0
- package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +5 -4
- package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +2 -3
- package/src/session-runtime/workflow-agents-api.mjs +2 -0
- package/src/session-runtime/workspace/activity-guards.mjs +176 -0
- package/src/session-runtime/workspace/project-branches.mjs +1 -1
- package/src/session-runtime/workspace/session-view.mjs +149 -0
- package/src/session-runtime/workspace/side-checkouts.mjs +203 -0
- package/src/session-runtime/workspace/transition-runner.mjs +188 -0
- package/src/session-runtime/workspace/transitions.mjs +128 -1070
- package/src/session-runtime/workspace/workspace-merge.mjs +132 -0
- package/src/session-runtime/workspace/worktree-intents.mjs +242 -0
- package/src/session-runtime/workspace/worktree-maintenance.mjs +200 -0
- package/src/session-runtime/workspace/worktree-setup.mjs +97 -0
- package/src/session-runtime/workspace/worktree-tool.mjs +70 -54
- package/src/standalone/daemon-agent-control.mjs +25 -8
- package/src/standalone/daemon-desktop-runtime.mjs +8 -2
- package/src/standalone/daemon-lag-profiler.mjs +7 -7
- package/src/standalone/daemon-session-control.mjs +151 -136
- package/src/standalone/daemon.mjs +61 -2
- package/src/standalone/desktop-service-registry.mjs +9 -0
- package/src/standalone/local-session-runtime.mjs +21 -1
- package/src/standalone/session-client/daemon-unavailable.mjs +4 -1
- package/src/standalone/session-client.mjs +5 -1
- package/src/standalone/session-frame-stream.mjs +83 -11
- package/src/standalone/session-protocol.mjs +15 -0
- package/src/standalone/session-service/agent-route-follow.mjs +23 -20
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +18 -6
- package/src/standalone/session-service/agent-tree.mjs +45 -9
- package/src/standalone/session-service/projection/transcript-window.mjs +700 -64
- package/src/standalone/session-service/quota-resume.mjs +9 -0
- package/src/standalone/session-service/session-calls/session-action.mjs +51 -1
- package/src/standalone/session-service/session-calls/session-turns.mjs +37 -18
- package/src/standalone/session-service/session-calls/session-views.mjs +160 -104
- package/src/standalone/session-service/session-calls/turn-gate.mjs +34 -0
- package/src/standalone/session-service/session-calls.mjs +2 -1
- package/src/standalone/session-service/stored-reader.mjs +127 -40
- package/src/tui/App.jsx +162 -164
- package/src/tui/app/app-view/floating-panel.jsx +3 -0
- package/src/tui/app/app-view/text-entry-labels.mjs +1 -0
- package/src/tui/app/clipboard.mjs +22 -11
- package/src/tui/app/create-app-pickers.mjs +2 -0
- package/src/tui/app/doctor.mjs +2 -2
- package/src/tui/app/panel-signature.mjs +1 -1
- package/src/tui/app/prompt-handlers/use-prompt-history-nav.mjs +1 -1
- package/src/tui/app/prompt-handlers/use-prompt-interrupt.mjs +3 -0
- package/src/tui/app/prompt-submit/provider-prompts.mjs +3 -1
- package/src/tui/app/provider-setup/api-key-actions.mjs +31 -1
- package/src/tui/app/provider-setup/oauth-actions.mjs +25 -6
- package/src/tui/app/provider-setup-picker.mjs +20 -13
- package/src/tui/app/settings-picker.mjs +53 -8
- package/src/tui/app/shell-layout/row-budgets.mjs +14 -12
- package/src/tui/app/slash-commands.mjs +2 -1
- package/src/tui/app/slash-dispatch/route-commands.mjs +1 -1
- package/src/tui/app/slash-dispatch/session-commands.mjs +47 -1
- package/src/tui/app/slash-dispatch.mjs +1 -1
- package/src/tui/app/use-btw-panel.mjs +29 -0
- package/src/tui/app/use-context-panel-refresh.mjs +31 -0
- package/src/tui/app/use-model-catalog-cache.mjs +13 -10
- package/src/tui/app/use-mouse-input.mjs +11 -0
- package/src/tui/app/use-onboarding-start.mjs +8 -3
- package/src/tui/app/use-panel-transition.mjs +10 -1
- package/src/tui/app/use-pasted-buffers.mjs +28 -20
- package/src/tui/app/use-prompt-draft-flow.mjs +7 -0
- package/src/tui/app/use-prompt-layout-rows.mjs +3 -3
- package/src/tui/app/use-prompt-queue-history.mjs +5 -4
- package/src/tui/app/use-selection-focus.mjs +11 -2
- package/src/tui/app/use-selection-geometry.mjs +18 -9
- package/src/tui/app/use-selection-paint.mjs +4 -4
- package/src/tui/app/use-selection-stitch.mjs +3 -3
- package/src/tui/app/use-slash-palette.mjs +62 -0
- package/src/tui/app/use-terminal-chrome.mjs +2 -2
- package/src/tui/app/use-transcript-activity.mjs +48 -33
- package/src/tui/app/use-transcript-follow.mjs +12 -4
- package/src/tui/app/use-transcript-scroll.mjs +46 -17
- package/src/tui/app/use-transcript-swap-reset.mjs +27 -0
- package/src/tui/app/use-transcript-window/geometry.mjs +20 -6
- package/src/tui/app/use-transcript-window/instance-state.mjs +4 -0
- package/src/tui/app/use-transcript-window/selection-shift.mjs +5 -1
- package/src/tui/app/use-transcript-window.mjs +21 -11
- package/src/tui/app/use-tui-ready.mjs +18 -0
- package/src/tui/app/use-welcome-prompt-hint.mjs +5 -0
- package/src/tui/app/use-workflow-tab-cycle.mjs +5 -3
- package/src/tui/components/Picker.jsx +27 -3
- package/src/tui/components/SignInUrl.jsx +68 -0
- package/src/tui/components/TextEntryPanel.jsx +76 -46
- package/src/tui/components/prompt-input/escape-policy.d.mts +0 -1
- package/src/tui/components/prompt-input/escape-policy.mjs +1 -1
- package/src/tui/components/question-panel-model.mjs +4 -4
- package/src/tui/components/sign-in-url-layout.mjs +24 -0
- package/src/tui/components/tool-execution/standard-card.jsx +3 -4
- package/src/tui/components/user-message-skills.mjs +1 -1
- package/src/tui/dist/index.mjs +2205 -1371
- package/src/tui/markdown/render-ansi.mjs +1 -1
- package/src/tui/session/agent-job-feed/notification-router.mjs +10 -0
- package/src/tui/session/agent-job-feed.mjs +2 -0
- package/src/tui/session/context-state.mjs +3 -0
- package/src/tui/session/goal-turn-state.mjs +6 -2
- package/src/tui/session/quota-resume.mjs +1 -1
- package/src/tui/session/session-api/controls.mjs +4 -0
- package/src/tui/session/session-api/extensions.mjs +8 -0
- package/src/tui/session/session-api/intake/abort.mjs +2 -1
- package/src/tui/session/session-api/intake.mjs +2 -0
- package/src/tui/session/session-api/integrations.mjs +2 -2
- package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
- package/src/tui/session/session-api/lifecycle/session-reset.mjs +7 -0
- package/src/tui/session/session-api/routes-agent-definitions.mjs +6 -0
- package/src/tui/session/session-api/settings.mjs +2 -2
- package/src/tui/session/session-api/worktree.mjs +13 -1
- package/src/tui/session/session-flow/drain.mjs +11 -14
- package/src/tui/session/tool-card-results/grouped-result.mjs +2 -2
- package/src/tui/session/transcript-spill/spill-writer.mjs +15 -0
- package/src/tui/session/transcript-spill.mjs +92 -4
- package/src/tui/session/transcript-store.mjs +2 -0
- package/src/tui/session/turn-quiet.mjs +1 -1
- package/src/tui/session/turn.mjs +3 -0
- package/src/tui/session/worktree-setup-notice.mjs +1 -1
- package/src/tui/spinner-meta.mjs +3 -3
- package/src/tui/spinner-verbs.mjs +2 -2
- package/src/defaults/skills/goal-management/SKILL.md +0 -169
- package/src/defaults/skills/skill-creator/references/source-review.md +0 -94
- package/src/runtime/agent/orchestrator/runtime-core/goal-tasks.mjs +0 -156
- package/src/session-runtime/goal-tasks.mjs +0 -1
|
@@ -184,25 +184,28 @@ export function gmailAppPasswordServerInput(name, email, password) {
|
|
|
184
184
|
}
|
|
185
185
|
|
|
186
186
|
/** Whether several accounts of catalog connector `entry` can be connected at
|
|
187
|
-
* once:
|
|
188
|
-
* sign-in. Other remote servers keep one (their tokens and URL are shared). */
|
|
187
|
+
* once: every catalog connector holds its accounts in one server. */
|
|
189
188
|
export function connectorMultiAccount(entry) {
|
|
190
|
-
return entry?.
|
|
189
|
+
return Boolean(entry?.id) && connectorById(entry.id) === entry;
|
|
191
190
|
}
|
|
192
191
|
|
|
193
|
-
// ── One server per
|
|
194
|
-
// A
|
|
195
|
-
//
|
|
192
|
+
// ── One server per connector ────────────────────────────────────────────────
|
|
193
|
+
// A catalog connector is ONE MCP server (`gmail`, `notion`, `postgres`…)
|
|
194
|
+
// holding its accounts:
|
|
196
195
|
// { type: 'http', url: connectorAccountsUrl(id), connector: id,
|
|
197
|
-
// accounts: [{ name, url
|
|
198
|
-
//
|
|
199
|
-
//
|
|
200
|
-
// account
|
|
201
|
-
//
|
|
202
|
-
//
|
|
203
|
-
//
|
|
204
|
-
//
|
|
205
|
-
|
|
196
|
+
// accounts: [{ name, id?, type?, url?, headers?, oauthClientId?, oauthKey?,
|
|
197
|
+
// command?, args?, env? }, …] }
|
|
198
|
+
// (`id`: the account's random identity; connectorAccountId)
|
|
199
|
+
// Each account keeps the transport it had as a server of its own (its remote
|
|
200
|
+
// URL and sign-in, its key header, its app-password address, or its local
|
|
201
|
+
// command and environment), so its keychain entries are untouched. A remote
|
|
202
|
+
// sign-in is stored under the account's URL, or under its own `oauthKey` when
|
|
203
|
+
// another account of the connector already signs in at that URL. Account names
|
|
204
|
+
// share the server-name space (`notion`, `notion-2`…): a name-based call
|
|
205
|
+
// (remove, sign in, sign out) that names an account acts on that account. The
|
|
206
|
+
// server is answered in-process (connectors/connector-accounts-mcp.mjs): one
|
|
207
|
+
// tool set with an `account` argument.
|
|
208
|
+
const ACCOUNT_FIELDS = ['type', 'url', 'headers', 'oauthClientId', 'oauthKey', 'command', 'args', 'env'];
|
|
206
209
|
|
|
207
210
|
/** The reserved (never resolvable) address of connector `id`'s accounts server. */
|
|
208
211
|
export function connectorAccountsUrl(id) {
|
|
@@ -211,14 +214,16 @@ export function connectorAccountsUrl(id) {
|
|
|
211
214
|
|
|
212
215
|
const isRecord = (value) => Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
213
216
|
|
|
214
|
-
/** The stored accounts of a
|
|
215
|
-
*
|
|
217
|
+
/** The stored accounts of a connector server, [] for any other config (a
|
|
218
|
+
* legacy one-account server included). */
|
|
216
219
|
export function connectorAccountsOf(cfg) {
|
|
217
|
-
if (!isRecord(cfg) || !Array.isArray(cfg.accounts)) return [];
|
|
218
|
-
if (!connectorMultiAccount(connectorById(connectorOfServer(cfg)))) return [];
|
|
220
|
+
if (!isRecord(cfg) || !Array.isArray(cfg.accounts) || !connectorOfServer(cfg)) return [];
|
|
219
221
|
return cfg.accounts.filter(
|
|
220
222
|
(account) =>
|
|
221
|
-
isRecord(account) &&
|
|
223
|
+
isRecord(account) &&
|
|
224
|
+
typeof account.name === 'string' &&
|
|
225
|
+
account.name &&
|
|
226
|
+
(typeof account.url === 'string' || typeof account.command === 'string')
|
|
222
227
|
);
|
|
223
228
|
}
|
|
224
229
|
|
|
@@ -231,6 +236,21 @@ export function connectorAccountServer(cfg, account) {
|
|
|
231
236
|
return out;
|
|
232
237
|
}
|
|
233
238
|
|
|
239
|
+
/** `cfg` without what is an account's own connection: the settings of the
|
|
240
|
+
* server holding its accounts (timeouts, enabled…). */
|
|
241
|
+
export function connectorServerSettings(cfg) {
|
|
242
|
+
return Object.fromEntries(Object.entries(cfg).filter(([key]) => key !== 'accounts' && !ACCOUNT_FIELDS.includes(key)));
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/** The identity of stored account `account`, which a chosen account is
|
|
246
|
+
* remembered by: the random `id` stored with it (given when it is added, or
|
|
247
|
+
* on load to one stored without: connector-accounts-mcp.mjs
|
|
248
|
+
* ensureConnectorAccountIds). A new account given a removed one's name gets
|
|
249
|
+
* a new id; an edit keeps it. '' while it has none (nothing is bound to it). */
|
|
250
|
+
export function connectorAccountId(_cfg, account) {
|
|
251
|
+
return typeof account?.id === 'string' ? account.id : '';
|
|
252
|
+
}
|
|
253
|
+
|
|
234
254
|
/** Every account of `cfg` as its one-account server config. */
|
|
235
255
|
export function connectorAccountServers(cfg) {
|
|
236
256
|
return connectorAccountsOf(cfg).map((account) => connectorAccountServer(cfg, account));
|
|
@@ -264,33 +284,39 @@ export function withConnectorAccountEnabled(cfg, name, enabled) {
|
|
|
264
284
|
return connectorAccountsOf(next).some(connectorAccountEnabled) ? next : { ...next, enabled: false };
|
|
265
285
|
}
|
|
266
286
|
|
|
267
|
-
/** The stored account entry of one-account config `cfg` under `name
|
|
287
|
+
/** The stored account entry of one-account config `cfg` under `name` (an
|
|
288
|
+
* http transport is the default and is not stored). */
|
|
268
289
|
export function connectorAccountEntry(name, cfg) {
|
|
269
290
|
const out = { name };
|
|
270
291
|
for (const field of ACCOUNT_FIELDS) if (cfg?.[field] !== undefined) out[field] = cfg[field];
|
|
292
|
+
if (out.type === 'http') delete out.type;
|
|
271
293
|
return out;
|
|
272
294
|
}
|
|
273
295
|
|
|
274
296
|
const naturalOrder = (a, b) => a.localeCompare(b, 'en', { numeric: true });
|
|
275
297
|
|
|
298
|
+
/** What makes an account the same connection as another: its transport
|
|
299
|
+
* (URL, sign-in key, headers, command and environment), whatever its name. */
|
|
300
|
+
const connectionOf = (cfg, account) => JSON.stringify({ ...connectorAccountServer(cfg, account), name: '' });
|
|
301
|
+
|
|
276
302
|
/**
|
|
277
|
-
* Merges every
|
|
278
|
-
* accounts: legacy one-account servers (`
|
|
279
|
-
* Drive alike) and any second accounts server. The server keeps the name
|
|
280
|
-
* an existing accounts server, else the connector id when a server has it,
|
|
303
|
+
* Merges every catalog connector's servers into one server holding the
|
|
304
|
+
* accounts: legacy one-account servers (`notion`, `notion-2`…, Gmail, Calendar
|
|
305
|
+
* and Drive alike) and any second accounts server. The server keeps the name
|
|
306
|
+
* of an existing accounts server, else the connector id when a server has it,
|
|
281
307
|
* else the first name; its other fields come from that server. Accounts keep
|
|
282
308
|
* their names, transports and order (that server's first); a second entry
|
|
283
|
-
* for the same name
|
|
284
|
-
* off only when every merged one was; otherwise the accounts
|
|
285
|
-
* server that was off stay off (`enabled: false` on the account),
|
|
286
|
-
* account's own `enabled: false` is kept. A server left with no
|
|
287
|
-
* account is off. Idempotent: `merged` is empty when
|
|
288
|
-
*
|
|
309
|
+
* for the same name, app-password address or connection is dropped. The
|
|
310
|
+
* merged server is off only when every merged one was; otherwise the accounts
|
|
311
|
+
* of a merged server that was off stay off (`enabled: false` on the account),
|
|
312
|
+
* and an account's own `enabled: false` is kept. A server left with no
|
|
313
|
+
* switched-on account is off. Idempotent: `merged` is empty when nothing
|
|
314
|
+
* changed. Returns `{ servers, merged: [{ connector, name, from }] }`.
|
|
289
315
|
*/
|
|
290
316
|
export function mergeConnectorAccountServers(input) {
|
|
291
317
|
const servers = isRecord(input) ? { ...input } : {};
|
|
292
318
|
const merged = [];
|
|
293
|
-
for (const entry of CONNECTOR_CATALOG
|
|
319
|
+
for (const entry of CONNECTOR_CATALOG) {
|
|
294
320
|
const names = Object.keys(servers)
|
|
295
321
|
.filter((name) => isRecord(servers[name]) && connectorOfServer(servers[name]) === entry.id)
|
|
296
322
|
.sort(naturalOrder);
|
|
@@ -303,6 +329,7 @@ export function mergeConnectorAccountServers(input) {
|
|
|
303
329
|
const accounts = [];
|
|
304
330
|
const seenNames = new Set();
|
|
305
331
|
const seenAddresses = new Set();
|
|
332
|
+
const seenConnections = new Set();
|
|
306
333
|
for (const name of order) {
|
|
307
334
|
const cfg = servers[name];
|
|
308
335
|
const own = Array.isArray(cfg.accounts) ? connectorAccountsOf(cfg) : [connectorAccountEntry(name, cfg)];
|
|
@@ -311,21 +338,17 @@ export function mergeConnectorAccountServers(input) {
|
|
|
311
338
|
const serverOff = !off && cfg.enabled === false;
|
|
312
339
|
for (const account of own) {
|
|
313
340
|
const address = gmailAppPasswordAccount(connectorAccountServer(cfg, account));
|
|
314
|
-
|
|
341
|
+
const connection = connectionOf(cfg, account);
|
|
342
|
+
if (seenNames.has(account.name) || (address && seenAddresses.has(address)) || seenConnections.has(connection)) {
|
|
343
|
+
continue;
|
|
344
|
+
}
|
|
315
345
|
seenNames.add(account.name);
|
|
316
346
|
if (address) seenAddresses.add(address);
|
|
347
|
+
seenConnections.add(connection);
|
|
317
348
|
accounts.push(serverOff ? { ...account, enabled: false } : account);
|
|
318
349
|
}
|
|
319
350
|
}
|
|
320
|
-
const {
|
|
321
|
-
type: _type,
|
|
322
|
-
url: _url,
|
|
323
|
-
headers: _headers,
|
|
324
|
-
oauthClientId: _client,
|
|
325
|
-
accounts: _accounts,
|
|
326
|
-
enabled: _enabled,
|
|
327
|
-
...rest
|
|
328
|
-
} = servers[target];
|
|
351
|
+
const { enabled: _enabled, ...rest } = connectorServerSettings(servers[target]);
|
|
329
352
|
for (const name of order) delete servers[name];
|
|
330
353
|
servers[target] = {
|
|
331
354
|
...rest,
|
|
@@ -352,17 +375,12 @@ export function connectorUsesGoogleClient(entry) {
|
|
|
352
375
|
}
|
|
353
376
|
|
|
354
377
|
/** The MCP server input that connects catalog entry `entry` under `name`
|
|
355
|
-
* (oauth / apiKey); `key` fills an apiKey backend
|
|
356
|
-
*
|
|
357
|
-
|
|
378
|
+
* (oauth / apiKey); `key` fills an apiKey backend. Every account keeps the
|
|
379
|
+
* service's real URL; another account at that URL gets its own sign-in key
|
|
380
|
+
* (resource-mcp-connector-accounts.mjs). */
|
|
381
|
+
export function connectorServerInput(entry, name, key = '') {
|
|
358
382
|
const { backend } = entry;
|
|
359
|
-
if (backend.kind === 'oauth') {
|
|
360
|
-
// Tokens are stored per exact server URL, so another account of the same
|
|
361
|
-
// connector needs its own URL; the in-process Google servers ignore the query.
|
|
362
|
-
const url =
|
|
363
|
-
extraAccount && connectorMultiAccount(entry) ? `${backend.url}?account=${encodeURIComponent(name)}` : backend.url;
|
|
364
|
-
return { name, type: 'http', url, connector: entry.id };
|
|
365
|
-
}
|
|
383
|
+
if (backend.kind === 'oauth') return { name, type: 'http', url: backend.url, connector: entry.id };
|
|
366
384
|
if (backend.kind !== 'apiKey') throw new Error(`${entry.name} is not an MCP connector`);
|
|
367
385
|
const value = String(key || '').trim();
|
|
368
386
|
if (!value) throw new Error(`${entry.name} needs a key`);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
2
|
+
|
|
3
|
+
const require = createRequire(import.meta.url);
|
|
4
|
+
const { getSecret } = require('../../lib/keychain-cjs.cjs');
|
|
5
|
+
|
|
6
|
+
// A custom provider's additional API keys are keychain secrets beside its
|
|
7
|
+
// primary key (`agent.<id>.apiKey`), one per key id of its roster
|
|
8
|
+
// (provider-accounts.mjs `setCustomProviderKeyIds`). Never config values.
|
|
9
|
+
export function customProviderKeyAccount(providerId, keyId) {
|
|
10
|
+
return `agent.${providerId}.apiKey.${keyId}`;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** The stored value of additional key `keyId`, or '' when it is not readable. */
|
|
14
|
+
export function readCustomProviderKey(providerId, keyId) {
|
|
15
|
+
try {
|
|
16
|
+
return getSecret(customProviderKeyAccount(providerId, keyId)) || '';
|
|
17
|
+
} catch {
|
|
18
|
+
return '';
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
import { closeSync, openSync, readSync } from 'node:fs';
|
|
2
|
+
import { open } from 'node:fs/promises';
|
|
2
3
|
import { holdsNoData } from './atomic-file.mjs';
|
|
3
4
|
|
|
4
5
|
const PROBE_BYTES = 4096;
|
|
5
6
|
|
|
7
|
+
// Only these errno codes mean the path names no file. Every other failure
|
|
8
|
+
// leaves the file present (a scanner's or the running process's lock, EIO, ...):
|
|
9
|
+
// this is an install check on settings and status paths, so it never throws.
|
|
10
|
+
const ABSENT_CODES = new Set(['ENOENT', 'ENOTDIR']);
|
|
11
|
+
const presentDespite = (err) => !ABSENT_CODES.has(err?.code);
|
|
12
|
+
|
|
6
13
|
/**
|
|
7
14
|
* Install check for a downloaded binary or model: false when `path` is absent
|
|
8
15
|
* or its first bytes hold no data (empty, or NUL-filled by a crash that
|
|
9
16
|
* committed the size but not the bytes). Cheaper than hashing a multi-GB file
|
|
10
17
|
* on every use. A file that exists but cannot be opened right now (locked by a
|
|
11
|
-
* scanner or by the process running it) still counts as present
|
|
18
|
+
* scanner or by the process running it) still counts as present, as does any
|
|
19
|
+
* other failure.
|
|
12
20
|
*/
|
|
13
21
|
export function fileHasData(path) {
|
|
14
22
|
let fd;
|
|
@@ -17,7 +25,7 @@ export function fileHasData(path) {
|
|
|
17
25
|
const head = Buffer.alloc(PROBE_BYTES);
|
|
18
26
|
return !holdsNoData(head.subarray(0, readSync(fd, head, 0, PROBE_BYTES, 0)));
|
|
19
27
|
} catch (err) {
|
|
20
|
-
return err
|
|
28
|
+
return presentDespite(err);
|
|
21
29
|
} finally {
|
|
22
30
|
if (fd !== undefined) {
|
|
23
31
|
try {
|
|
@@ -26,3 +34,19 @@ export function fileHasData(path) {
|
|
|
26
34
|
}
|
|
27
35
|
}
|
|
28
36
|
}
|
|
37
|
+
|
|
38
|
+
/** Same verdict as `fileHasData`, without blocking the event loop on the open
|
|
39
|
+
* (an antivirus scan of a binary can stall a synchronous open for seconds). */
|
|
40
|
+
export async function fileHasDataAsync(path) {
|
|
41
|
+
let handle;
|
|
42
|
+
try {
|
|
43
|
+
handle = await open(path, 'r');
|
|
44
|
+
const head = Buffer.alloc(PROBE_BYTES);
|
|
45
|
+
const { bytesRead } = await handle.read(head, 0, PROBE_BYTES, 0);
|
|
46
|
+
return !holdsNoData(head.subarray(0, bytesRead));
|
|
47
|
+
} catch (err) {
|
|
48
|
+
return presentDespite(err);
|
|
49
|
+
} finally {
|
|
50
|
+
await handle?.close().catch(() => {});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -1,16 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
linkSync,
|
|
3
|
-
mkdirSync,
|
|
4
|
-
readdirSync,
|
|
5
|
-
readFileSync,
|
|
6
|
-
renameSync,
|
|
7
|
-
statSync,
|
|
8
|
-
unlinkSync,
|
|
9
|
-
writeFileSync,
|
|
10
|
-
} from 'node:fs';
|
|
1
|
+
import { linkSync, mkdirSync, readFileSync, renameSync, statSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
11
2
|
import {
|
|
12
3
|
link as linkAsync,
|
|
13
4
|
mkdir as mkdirAsync,
|
|
5
|
+
readdir as readdirAsync,
|
|
14
6
|
readFile as readFileAsync,
|
|
15
7
|
stat as statAsync,
|
|
16
8
|
unlink as unlinkAsync,
|
|
@@ -122,9 +114,14 @@ async function runAsync(steps) {
|
|
|
122
114
|
|
|
123
115
|
function* readLockOwner(lockPath) {
|
|
124
116
|
try {
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
117
|
+
const text = String(yield ['read', lockPath]).trim();
|
|
118
|
+
// v1.4.2 pg-spawn.lock wrote `{"pid":N,"startedAt":T}`; an older process
|
|
119
|
+
// may still hold one, so its pid must count as an owner.
|
|
120
|
+
if (text.startsWith('{')) {
|
|
121
|
+
const legacyPid = Number(JSON.parse(text)?.pid);
|
|
122
|
+
return { pid: Number.isInteger(legacyPid) && legacyPid > 0 ? legacyPid : null, token: null };
|
|
123
|
+
}
|
|
124
|
+
const parts = text.split(/\s+/);
|
|
128
125
|
const pid = Number.parseInt(parts[0], 10);
|
|
129
126
|
return {
|
|
130
127
|
pid: Number.isFinite(pid) && pid > 0 ? pid : null,
|
|
@@ -384,10 +381,16 @@ function lockStaleMs(opts) {
|
|
|
384
381
|
// A staged owner record lives for one link call; a process killed between its
|
|
385
382
|
// create and unlink leaves `<lock>.<pid>.<hex>.tmp` behind. Each lock path is
|
|
386
383
|
// swept once per process for staged files older than this whose pid is dead.
|
|
384
|
+
// The sweep is cleanup only — no lock decision depends on it — so it runs
|
|
385
|
+
// beside the acquisition instead of in front of it: listing a crowded
|
|
386
|
+
// directory synchronously blocked every lock taker for seconds. A file it
|
|
387
|
+
// removes belongs to a dead pid and is past any link call, so it cannot race
|
|
388
|
+
// a live acquisition.
|
|
387
389
|
const STAGED_LOCK_FILE_STALE_MS = 60_000;
|
|
388
390
|
const sweptLockPaths = new Set();
|
|
389
391
|
|
|
390
|
-
|
|
392
|
+
/** Resolves with the number of staged files removed; 0 once the path was swept in this process. */
|
|
393
|
+
export async function sweepStagedLockFiles(lockPath, now = Date.now()) {
|
|
391
394
|
if (sweptLockPaths.has(lockPath)) return 0;
|
|
392
395
|
sweptLockPaths.add(lockPath);
|
|
393
396
|
const dir = dirname(lockPath);
|
|
@@ -395,7 +398,7 @@ export function sweepStagedLockFiles(lockPath, now = Date.now()) {
|
|
|
395
398
|
let removed = 0;
|
|
396
399
|
let names;
|
|
397
400
|
try {
|
|
398
|
-
names =
|
|
401
|
+
names = await readdirAsync(dir);
|
|
399
402
|
} catch {
|
|
400
403
|
return 0;
|
|
401
404
|
}
|
|
@@ -405,9 +408,9 @@ export function sweepStagedLockFiles(lockPath, now = Date.now()) {
|
|
|
405
408
|
if (!match) continue;
|
|
406
409
|
const path = join(dir, name);
|
|
407
410
|
try {
|
|
408
|
-
if (now -
|
|
411
|
+
if (now - (await statAsync(path)).mtimeMs < STAGED_LOCK_FILE_STALE_MS) continue;
|
|
409
412
|
if (ownerIsLive({ pid: Number(match[1]), token: null })) continue;
|
|
410
|
-
|
|
413
|
+
await unlinkAsync(path);
|
|
411
414
|
removed += 1;
|
|
412
415
|
} catch {
|
|
413
416
|
// Another sweeper or a late unlink got there first.
|
|
@@ -421,7 +424,7 @@ function* acquireLock(lockPath, opts, mode, markHeld, timing = null) {
|
|
|
421
424
|
const staleMs = lockStaleMs(opts);
|
|
422
425
|
const deadline = Date.now() + timeoutMs;
|
|
423
426
|
yield ['mkdirp', dirname(lockPath)];
|
|
424
|
-
sweepStagedLockFiles(lockPath);
|
|
427
|
+
void sweepStagedLockFiles(lockPath);
|
|
425
428
|
const waitStartedAt = Date.now();
|
|
426
429
|
let attempt = 0;
|
|
427
430
|
let lastError = null;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export function gitCommand(env?: NodeJS.ProcessEnv | null): string;
|
|
2
|
+
export function gitChildEnv(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
|
|
3
|
+
export function gitChildEnv(env?: null): NodeJS.ProcessEnv | null;
|
|
4
|
+
export function forgetMissingGit(command: string, error: unknown): boolean;
|
|
5
|
+
export function startGit<T>(
|
|
6
|
+
env: NodeJS.ProcessEnv,
|
|
7
|
+
start: (command: string, env: NodeJS.ProcessEnv) => Promise<T>,
|
|
8
|
+
spawnError?: (outcome: T) => unknown
|
|
9
|
+
): Promise<T>;
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
// The git executable product code starts, and the environment it starts with.
|
|
2
|
+
//
|
|
3
|
+
// On Windows `git` on PATH is usually Git for Windows' launcher,
|
|
4
|
+
// <root>\cmd\git.exe (or the identical <root>\bin\git.exe). It only prepares
|
|
5
|
+
// the environment and starts <root>\<msystem>\bin\git.exe as a second process,
|
|
6
|
+
// so every git child costs two process creations. When PATH's git is that
|
|
7
|
+
// launcher, children start the real binary directly with the environment the
|
|
8
|
+
// launcher would have built. The steps below follow git-wrapper.c
|
|
9
|
+
// (git-for-windows/MINGW-packages, mingw-w64-git/git-wrapper.c): main()'s
|
|
10
|
+
// `git.exe` branch and setup_environment(top_level_path, full_path=1) plus
|
|
11
|
+
// maybe_read_config(). Anything else — another platform, a scoop shim, MinGit,
|
|
12
|
+
// a git.exe outside such a layout, an ambiguous or incomplete install — keeps
|
|
13
|
+
// plain `git` and the caller's environment, exactly as before.
|
|
14
|
+
import { readFileSync, realpathSync, statSync } from 'node:fs';
|
|
15
|
+
import { basename, delimiter, dirname, isAbsolute, join } from 'node:path';
|
|
16
|
+
|
|
17
|
+
// The wrapper's compile-time MSYSTEM, lower-cased, names its binary directory.
|
|
18
|
+
const MSYSTEM_DIRECTORIES = ['mingw64', 'clangarm64', 'mingw32'];
|
|
19
|
+
|
|
20
|
+
function isFile(path) {
|
|
21
|
+
try {
|
|
22
|
+
return statSync(path).isFile();
|
|
23
|
+
} catch {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function isDirectory(path) {
|
|
29
|
+
try {
|
|
30
|
+
return statSync(path).isDirectory();
|
|
31
|
+
} catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Windows names are case-insensitive. Of several spellings in one object
|
|
37
|
+
// Node passes the first in sorted order to the child, so that one is read and
|
|
38
|
+
// written.
|
|
39
|
+
function envKey(env, name) {
|
|
40
|
+
const upper = name.toUpperCase();
|
|
41
|
+
return (
|
|
42
|
+
Object.keys(env)
|
|
43
|
+
.filter((key) => key.toUpperCase() === upper)
|
|
44
|
+
.sort()[0] ?? name
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function envValue(env, name) {
|
|
49
|
+
const value = env[envKey(env, name)];
|
|
50
|
+
return value === undefined || value === null ? undefined : String(value);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// The wrapper's my_path_append: one backslash between the parts.
|
|
54
|
+
function appendPath(list, part) {
|
|
55
|
+
return list.endsWith('\\') ? `${list}${part}` : `${list}\\${part}`;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// libuv's search for a bare `git` (no directory, no extension): each PATH
|
|
59
|
+
// entry in order, `git.com` before `git.exe`.
|
|
60
|
+
function launcherOnPath(pathValue) {
|
|
61
|
+
for (const raw of String(pathValue || '').split(delimiter)) {
|
|
62
|
+
const entry = raw.trim().replace(/^"(.*)"$/, '$1');
|
|
63
|
+
if (!entry) continue;
|
|
64
|
+
// A relative entry resolves against each child's cwd; not decidable once.
|
|
65
|
+
if (!isAbsolute(entry)) return null;
|
|
66
|
+
if (isFile(join(entry, 'git.com'))) return null;
|
|
67
|
+
const candidate = join(entry, 'git.exe');
|
|
68
|
+
if (isFile(candidate)) return candidate;
|
|
69
|
+
}
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// etc\git-bash.config `MSYS=` lines, each prepended to MSYS in file order.
|
|
74
|
+
function readMsysConfig(root) {
|
|
75
|
+
let text = '';
|
|
76
|
+
try {
|
|
77
|
+
text = readFileSync(join(root, 'etc', 'git-bash.config'), 'utf8');
|
|
78
|
+
} catch {
|
|
79
|
+
return [];
|
|
80
|
+
}
|
|
81
|
+
return text
|
|
82
|
+
.split('\n')
|
|
83
|
+
.map((line) => line.replace(/\r$/, ''))
|
|
84
|
+
.filter((line) => line.startsWith('MSYS='))
|
|
85
|
+
.map((line) => line.slice(5));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* The Git for Windows layout behind PATH's `git`, or null when there is none
|
|
90
|
+
* to bypass. `{ command, root, msystem, msysConfig }`.
|
|
91
|
+
*/
|
|
92
|
+
export function resolveGitLaunch({ platform = process.platform, pathValue = process.env.PATH } = {}) {
|
|
93
|
+
if (platform !== 'win32') return null;
|
|
94
|
+
const found = launcherOnPath(pathValue);
|
|
95
|
+
if (!found) return null;
|
|
96
|
+
let launcher;
|
|
97
|
+
try {
|
|
98
|
+
// The wrapper locates its install from its own final path.
|
|
99
|
+
launcher = realpathSync.native(found);
|
|
100
|
+
} catch {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
if (basename(launcher).toLowerCase() !== 'git.exe') return null;
|
|
104
|
+
const launcherDirectory = dirname(launcher);
|
|
105
|
+
if (!['cmd', 'bin'].includes(basename(launcherDirectory).toLowerCase())) return null;
|
|
106
|
+
const root = dirname(launcherDirectory);
|
|
107
|
+
// The installer and PortableGit ship git-bash.exe; MinGit and other layouts do not.
|
|
108
|
+
if (!isFile(join(root, 'git-bash.exe')) || !isDirectory(join(root, 'usr', 'bin'))) return null;
|
|
109
|
+
const installed = MSYSTEM_DIRECTORIES.filter((name) => isFile(join(root, name, 'bin', 'git.exe')));
|
|
110
|
+
if (installed.length !== 1) return null;
|
|
111
|
+
const [msystemDirectory] = installed;
|
|
112
|
+
return {
|
|
113
|
+
command: join(root, msystemDirectory, 'bin', 'git.exe'),
|
|
114
|
+
root,
|
|
115
|
+
msystem: msystemDirectory.toUpperCase(),
|
|
116
|
+
msysConfig: readMsysConfig(root),
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function isSystemDirectory(path) {
|
|
121
|
+
const system = join(process.env.SystemRoot || process.env.windir || 'C:\\Windows', 'System32');
|
|
122
|
+
return path.toLowerCase() === system.toLowerCase();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** `base` as the launcher would hand it to the real git (setup_environment). */
|
|
126
|
+
export function gitLaunchEnvironment(launch, base) {
|
|
127
|
+
const env = { ...base };
|
|
128
|
+
const set = (name, value) => {
|
|
129
|
+
env[envKey(env, name)] = value;
|
|
130
|
+
};
|
|
131
|
+
set('MSYSTEM', launch.msystem);
|
|
132
|
+
if (envValue(env, 'PLINK_PROTOCOL') === undefined) set('PLINK_PROTOCOL', 'ssh');
|
|
133
|
+
if (envValue(env, 'HOME') === undefined) {
|
|
134
|
+
const homePath = envValue(env, 'HOMEPATH');
|
|
135
|
+
const drive = `${envValue(env, 'HOMEDRIVE') ?? ''}${homePath ?? ''}`;
|
|
136
|
+
if (homePath !== undefined && !isSystemDirectory(drive) && isDirectory(drive)) set('HOME', drive);
|
|
137
|
+
else if (envValue(env, 'USERPROFILE') !== undefined) set('HOME', envValue(env, 'USERPROFILE'));
|
|
138
|
+
}
|
|
139
|
+
// <root>\<msystem>\bin;<root>\usr\bin;<HOME>\bin; ahead of the inherited PATH.
|
|
140
|
+
const prefix =
|
|
141
|
+
`${appendPath(launch.root, `${launch.msystem.toLowerCase()}\\bin`)};` +
|
|
142
|
+
appendPath(launch.root, 'usr\\bin;') +
|
|
143
|
+
appendPath(envValue(env, 'HOME') ?? '', 'bin;');
|
|
144
|
+
set('PATH', `${prefix}${envValue(env, 'PATH') ?? ''}`);
|
|
145
|
+
for (const msys of launch.msysConfig) {
|
|
146
|
+
const current = envValue(env, 'MSYS');
|
|
147
|
+
set('MSYS', current === undefined ? msys : `${msys} ${current}`);
|
|
148
|
+
}
|
|
149
|
+
return env;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// PATH value -> its launch (or null), resolved once per PATH: a child is
|
|
153
|
+
// started with the git its own environment's PATH names, as bare `git` is.
|
|
154
|
+
const resolved = new Map();
|
|
155
|
+
function gitLaunch(env) {
|
|
156
|
+
const pathValue = envValue(env ?? process.env, 'PATH') ?? '';
|
|
157
|
+
if (!resolved.has(pathValue)) resolved.set(pathValue, resolveGitLaunch({ pathValue }));
|
|
158
|
+
return resolved.get(pathValue);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** The program to spawn for git with `env` (null: this process's environment). */
|
|
162
|
+
export function gitCommand(env = null) {
|
|
163
|
+
return gitLaunch(env)?.command ?? 'git';
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* The environment for a git child: `env` (null: this process's environment)
|
|
168
|
+
* with the launcher's additions when {@link gitCommand} bypasses it. Without a
|
|
169
|
+
* bypass `env` is returned unchanged, null included.
|
|
170
|
+
*/
|
|
171
|
+
export function gitChildEnv(env = null) {
|
|
172
|
+
const launch = gitLaunch(env);
|
|
173
|
+
return launch ? gitLaunchEnvironment(launch, env ?? process.env) : env;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Whether a spawn of `command` failed because that resolved binary is gone (an
|
|
178
|
+
* uninstalled or moved Git). Its resolutions are dropped then, so the next
|
|
179
|
+
* {@link gitCommand} resolves PATH afresh. ENOENT alone is not enough: a
|
|
180
|
+
* missing cwd reports it too, with the binary still in place.
|
|
181
|
+
*/
|
|
182
|
+
export function forgetMissingGit(command, error) {
|
|
183
|
+
if (error?.code !== 'ENOENT' || command === 'git' || isFile(command)) return false;
|
|
184
|
+
for (const [pathValue, launch] of resolved) if (launch?.command === command) resolved.delete(pathValue);
|
|
185
|
+
return true;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Starts git as `start(command, childEnv)` and, when that spawn failed only
|
|
190
|
+
* because the resolved binary is gone, once more with a fresh resolution —
|
|
191
|
+
* where bare `git` would have found whatever PATH holds now. `start` rejects
|
|
192
|
+
* with the spawn error, or settles an outcome `spawnError` reads it from.
|
|
193
|
+
*/
|
|
194
|
+
export async function startGit(env, start, spawnError = () => null) {
|
|
195
|
+
const command = gitCommand(env);
|
|
196
|
+
let outcome;
|
|
197
|
+
try {
|
|
198
|
+
outcome = await start(command, gitChildEnv(env));
|
|
199
|
+
} catch (error) {
|
|
200
|
+
if (!forgetMissingGit(command, error)) throw error;
|
|
201
|
+
return start(gitCommand(env), gitChildEnv(env));
|
|
202
|
+
}
|
|
203
|
+
if (!forgetMissingGit(command, spawnError(outcome))) return outcome;
|
|
204
|
+
return start(gitCommand(env), gitChildEnv(env));
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/** {@link startGit} for a synchronous `start` (spawnSync). */
|
|
208
|
+
export function startGitSync(env, start, spawnError = (result) => result?.error) {
|
|
209
|
+
const command = gitCommand(env);
|
|
210
|
+
const outcome = start(command, gitChildEnv(env));
|
|
211
|
+
if (!forgetMissingGit(command, spawnError(outcome))) return outcome;
|
|
212
|
+
return start(gitCommand(env), gitChildEnv(env));
|
|
213
|
+
}
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
// thread, never on the host event loop (run-child.mjs). Each request resolves
|
|
3
3
|
// to { code, stdout, stderr } or an error with the same codes the in-process
|
|
4
4
|
// runner used (ETIMEDOUT, EMAXBUFFER, spawn errors).
|
|
5
|
+
import { startGit } from './git-launch.mjs';
|
|
5
6
|
import { runChild } from './run-child.mjs';
|
|
6
7
|
import { serveWorkerRequests } from './worker-requests.mjs';
|
|
7
8
|
|
|
8
|
-
serveWorkerRequests((request) => runChild({ ...request, command
|
|
9
|
+
serveWorkerRequests((request) => startGit(request.env, (command, env) => runChild({ ...request, command, env })));
|
|
@@ -15,7 +15,12 @@ const requestGit = createWorkerRequestClient(new URL('./git-runner-worker.mjs',
|
|
|
15
15
|
* timeoutMs (the child is killed), EMAXBUFFER once stdout+stderr exceed
|
|
16
16
|
* maxBytes, or the spawn error itself. `stdoutEncoding: 'base64'` returns the
|
|
17
17
|
* exact stdout bytes base64-encoded instead of decoded as UTF-8.
|
|
18
|
+
* `waitForExitMs`: a timeout rejects only once the killed child exited (or
|
|
19
|
+
* after that bound), with `childExited` and `pid` on the error (run-child.mjs).
|
|
18
20
|
*/
|
|
19
|
-
export function runGitOffThread(
|
|
20
|
-
|
|
21
|
+
export function runGitOffThread(
|
|
22
|
+
args,
|
|
23
|
+
{ cwd, input = '', env = null, timeoutMs, maxBytes, stdoutEncoding = 'utf8', waitForExitMs = 0 }
|
|
24
|
+
) {
|
|
25
|
+
return requestGit({ args, cwd, input, env, timeoutMs, maxBytes, stdoutEncoding, waitForExitMs });
|
|
21
26
|
}
|