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
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { readFileSync, readdirSync, statSync, mkdirSync, existsSync, watch as fsWatch } from 'node:fs';
|
|
6
6
|
import { basename, join, dirname } from 'node:path';
|
|
7
7
|
import { createRequire } from 'node:module';
|
|
8
|
+
import { randomUUID } from 'node:crypto';
|
|
8
9
|
import { resolvePluginData } from './plugin-paths.mjs';
|
|
9
10
|
import { hasOwn, isPlainObject } from './object.mjs';
|
|
10
11
|
import {
|
|
@@ -13,6 +14,8 @@ import {
|
|
|
13
14
|
renameWithRetrySync,
|
|
14
15
|
writeJsonAtomicSync,
|
|
15
16
|
writeJsonAtomicAsync,
|
|
17
|
+
updateJsonAtomicSync,
|
|
18
|
+
updateJsonAtomic,
|
|
16
19
|
withFileLockSync,
|
|
17
20
|
withFileLock,
|
|
18
21
|
} from './atomic-file.mjs';
|
|
@@ -30,6 +33,7 @@ import { AGENT_PROVIDER_ENV, AGENT_PROVIDER_ENV_ALIASES, getAgentApiKey } from '
|
|
|
30
33
|
export { AGENT_PROVIDER_ENV, AGENT_PROVIDER_ENV_ALIASES, getAgentApiKey };
|
|
31
34
|
|
|
32
35
|
const _require = createRequire(import.meta.url);
|
|
36
|
+
const _keychain = _require('../../lib/keychain-cjs.cjs');
|
|
33
37
|
const {
|
|
34
38
|
getSecret: _getSecret,
|
|
35
39
|
setSecret: _setSecret,
|
|
@@ -42,7 +46,8 @@ const {
|
|
|
42
46
|
retryKeychain: _retryKeychain,
|
|
43
47
|
refreshKeychainStatus: _refreshKeychainStatus,
|
|
44
48
|
onKeychainRecovered: _onKeychainRecovered,
|
|
45
|
-
|
|
49
|
+
prewarmSecrets: _prewarmSecrets,
|
|
50
|
+
} = _keychain;
|
|
46
51
|
const _setSecretAsync = _setSecretAsyncImpl ?? (async (account, value) => _setSecret(account, value));
|
|
47
52
|
const _deleteSecretAsync = _deleteSecretAsyncImpl ?? (async (account) => _deleteSecret(account));
|
|
48
53
|
|
|
@@ -80,7 +85,9 @@ function withFreshDefaultsVersion(fresh, root) {
|
|
|
80
85
|
// isolated, freely-mutable object (no shared-reference poisoning). Only the
|
|
81
86
|
// non-RMW readAll() consults this; the RMW path (readAllForRmW) always reads
|
|
82
87
|
// disk under the lock. Read errors and malformed JSON are never cached.
|
|
83
|
-
let _configReadCache = null; // { raw,
|
|
88
|
+
let _configReadCache = null; // { raw, path, stat, atMs } | null
|
|
89
|
+
// While a change notification runs its listeners (runConfigChangeListeners).
|
|
90
|
+
let _inNotificationPass = false;
|
|
84
91
|
// Optional coarse fast-path window (ms). Default 0 => the cached raw string is
|
|
85
92
|
// validated against the file's mtime+size on EVERY read via a cheap statSync
|
|
86
93
|
// (no content read, no whole-file JSON.parse), so a cross-process edit is
|
|
@@ -97,6 +104,12 @@ export function invalidateConfigReadCache() {
|
|
|
97
104
|
_configReadCache = null;
|
|
98
105
|
}
|
|
99
106
|
|
|
107
|
+
// A replacement of the same size within the mtime's resolution still moves the
|
|
108
|
+
// inode (atomic rename) or the change time.
|
|
109
|
+
function statKey(st) {
|
|
110
|
+
return `${st.mtimeMs}:${st.ctimeMs}:${st.size}:${st.ino}`;
|
|
111
|
+
}
|
|
112
|
+
|
|
100
113
|
function readConfigRawCached() {
|
|
101
114
|
const now = Date.now();
|
|
102
115
|
if (_configReadCache && _configReadCache.path !== configPath()) _configReadCache = null;
|
|
@@ -106,12 +119,12 @@ function readConfigRawCached() {
|
|
|
106
119
|
if (CONFIG_READ_TTL_MS > 0 && now - _configReadCache.atMs < CONFIG_READ_TTL_MS) {
|
|
107
120
|
return _configReadCache.raw;
|
|
108
121
|
}
|
|
109
|
-
// Freshness gate: metadata-only stat. Unchanged mtime+size => the cached
|
|
122
|
+
// Freshness gate: metadata-only stat. Unchanged mtime+ctime+size+inode => the cached
|
|
110
123
|
// raw is still current, cross-process writes included — atomic writers land
|
|
111
124
|
// a new inode with a fresh mtime, so this reliably detects them.
|
|
112
125
|
try {
|
|
113
126
|
const st = statSync(configPath());
|
|
114
|
-
if (st
|
|
127
|
+
if (statKey(st) === _configReadCache.stat) {
|
|
115
128
|
_configReadCache.atMs = now;
|
|
116
129
|
return _configReadCache.raw;
|
|
117
130
|
}
|
|
@@ -146,7 +159,7 @@ function readConfigRawCached() {
|
|
|
146
159
|
process.stderr.write(`[config] readJsonFile: unexpected read error for ${configPath()}: ${err.message}\n`);
|
|
147
160
|
throw err;
|
|
148
161
|
}
|
|
149
|
-
_configReadCache = { raw, path: configPath(),
|
|
162
|
+
_configReadCache = { raw, path: configPath(), stat: statKey(st), atMs: now };
|
|
150
163
|
return raw;
|
|
151
164
|
}
|
|
152
165
|
|
|
@@ -225,6 +238,7 @@ function readConfigFile() {
|
|
|
225
238
|
// parse must not be re-served; drop it so the post-quarantine/restore read
|
|
226
239
|
// hits disk fresh (malformed = never cached).
|
|
227
240
|
invalidateConfigReadCache();
|
|
241
|
+
if (_inNotificationPass) throw configMidWriteError(err);
|
|
228
242
|
quarantineMalformedConfig(err);
|
|
229
243
|
return null;
|
|
230
244
|
}
|
|
@@ -422,19 +436,164 @@ function readAllForRmW() {
|
|
|
422
436
|
if (!isPlainObject(parsed)) throw new SyntaxError('config root must be a JSON object');
|
|
423
437
|
return parsed;
|
|
424
438
|
} catch (parseErr) {
|
|
439
|
+
if (_inNotificationPass) throw configMidWriteError(parseErr);
|
|
425
440
|
return restoreAllForRmWOrThrow(parseErr.message, quarantineMalformedConfig(parseErr));
|
|
426
441
|
}
|
|
427
442
|
}
|
|
428
443
|
|
|
444
|
+
// Secret change marker. Keychain writes never touch mixdog-config.json, so they
|
|
445
|
+
// publish through this file beside it (account -> token of its last change):
|
|
446
|
+
// it rides the same directory watch and notification as a config write. Each
|
|
447
|
+
// process remembers the tokens it has applied and drops exactly the changed
|
|
448
|
+
// accounts from its keychain read cache before listeners reload.
|
|
449
|
+
// A deletion removes the account's entry (the marker holds live accounts only)
|
|
450
|
+
// and moves this token: a process that never saw the account's entry (a secret
|
|
451
|
+
// stored before the marker existed, or set and deleted between two of its
|
|
452
|
+
// syncs) may still cache it, so it drops its whole keychain read cache.
|
|
453
|
+
const SECRETS_MARKER_FILE = 'mixdog-secrets-changed.json';
|
|
454
|
+
const SECRET_DELETED_KEY = '#deleted';
|
|
455
|
+
let _secretsSeen = null;
|
|
456
|
+
let _secretsSeenPath = '';
|
|
457
|
+
let _secretsMarkerStat = '';
|
|
458
|
+
|
|
459
|
+
function secretsMarkerPath() {
|
|
460
|
+
return join(dirname(configPath()), SECRETS_MARKER_FILE);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
function secretsMarkerStat(path) {
|
|
464
|
+
try {
|
|
465
|
+
const stat = statSync(path);
|
|
466
|
+
return `${stat.mtimeMs}:${stat.size}:${stat.ino}`;
|
|
467
|
+
} catch {
|
|
468
|
+
return 'missing';
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
function readSecretsMarker() {
|
|
473
|
+
try {
|
|
474
|
+
const parsed = parseJsonText(readFileSync(secretsMarkerPath(), 'utf8'));
|
|
475
|
+
return isPlainObject(parsed) ? parsed : {};
|
|
476
|
+
} catch {
|
|
477
|
+
return {};
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/** Apply marker entries this process has not seen; answers the changed accounts. */
|
|
482
|
+
function syncSecretsMarker() {
|
|
483
|
+
const path = secretsMarkerPath();
|
|
484
|
+
if (_secretsSeenPath !== path) {
|
|
485
|
+
_secretsSeen = null;
|
|
486
|
+
_secretsSeenPath = path;
|
|
487
|
+
}
|
|
488
|
+
_secretsMarkerStat = secretsMarkerStat(path);
|
|
489
|
+
const marker = readSecretsMarker();
|
|
490
|
+
if (_secretsSeen === null) {
|
|
491
|
+
_secretsSeen = marker;
|
|
492
|
+
return [];
|
|
493
|
+
}
|
|
494
|
+
const seen = _secretsSeen;
|
|
495
|
+
const changed = [...new Set([...Object.keys(seen), ...Object.keys(marker)])].filter(
|
|
496
|
+
(account) => seen[account] !== marker[account]
|
|
497
|
+
);
|
|
498
|
+
_secretsSeen = marker;
|
|
499
|
+
if (changed.includes(SECRET_DELETED_KEY)) _keychain.invalidateSecretCache?.();
|
|
500
|
+
else for (const account of changed) if (!account.startsWith('#')) _keychain.invalidateSecretCache?.(account);
|
|
501
|
+
return changed;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// The read path of a process that may have no config-change subscriber (an
|
|
505
|
+
// injected config, a helper process): one stat, and a re-read only when the
|
|
506
|
+
// marker moved, so a secret changed or forgotten elsewhere is never served
|
|
507
|
+
// from this process's cache.
|
|
508
|
+
function syncSecretsMarkerIfMoved() {
|
|
509
|
+
if (_secretsSeen !== null && _secretsSeenPath === secretsMarkerPath()) {
|
|
510
|
+
if (secretsMarkerStat(_secretsSeenPath) === _secretsMarkerStat) return;
|
|
511
|
+
}
|
|
512
|
+
syncSecretsMarker();
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/** account -> token of the last change of that secret this process has
|
|
516
|
+
* applied (its own writes and other processes'). Values are never included. */
|
|
517
|
+
export function secretChangeTokens() {
|
|
518
|
+
if (_secretsSeen === null) syncSecretsMarker();
|
|
519
|
+
return { ..._secretsSeen };
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
const secretChangeToken = () => `${process.pid}:${Date.now()}:${randomUUID()}`;
|
|
523
|
+
function withSecretChange(marker, account, token, deleted) {
|
|
524
|
+
const next = { ...(isPlainObject(marker) ? marker : {}) };
|
|
525
|
+
if (deleted) {
|
|
526
|
+
delete next[account];
|
|
527
|
+
next[SECRET_DELETED_KEY] = token;
|
|
528
|
+
} else {
|
|
529
|
+
next[account] = token;
|
|
530
|
+
}
|
|
531
|
+
return next;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
function beginSecretChange() {
|
|
535
|
+
// Other processes' changes are applied first, so recording our own token
|
|
536
|
+
// never absorbs theirs unapplied.
|
|
537
|
+
syncSecretsMarker();
|
|
538
|
+
return secretChangeToken();
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
function finishSecretChange(account, token, deleted) {
|
|
542
|
+
// This process already holds the new value (the keychain module updated its
|
|
543
|
+
// cache), so its own change is recorded as applied.
|
|
544
|
+
_secretsSeen = withSecretChange(_secretsSeen, account, token, deleted);
|
|
545
|
+
_secretsMarkerStat = secretsMarkerStat(secretsMarkerPath());
|
|
546
|
+
notifyConfigChanged();
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
const secretMarkerFailure = (err) =>
|
|
550
|
+
process.stderr.write(`[config] secret change marker write failed: ${err?.message || err}\n`);
|
|
551
|
+
|
|
552
|
+
// Never throws: the secret itself is already stored; a marker that could not
|
|
553
|
+
// be written is reported and only delays what other processes see.
|
|
554
|
+
function publishSecretChange(account, deleted = false) {
|
|
555
|
+
const token = beginSecretChange();
|
|
556
|
+
try {
|
|
557
|
+
mkdirSync(dirname(secretsMarkerPath()), { recursive: true, mode: 0o700 });
|
|
558
|
+
updateJsonAtomicSync(secretsMarkerPath(), (marker) => withSecretChange(marker, account, token, deleted), {
|
|
559
|
+
mode: 0o600,
|
|
560
|
+
});
|
|
561
|
+
} catch (err) {
|
|
562
|
+
secretMarkerFailure(err);
|
|
563
|
+
}
|
|
564
|
+
finishSecretChange(account, token, deleted);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
async function publishSecretChangeAsync(account, deleted = false) {
|
|
568
|
+
const token = beginSecretChange();
|
|
569
|
+
try {
|
|
570
|
+
mkdirSync(dirname(secretsMarkerPath()), { recursive: true, mode: 0o700 });
|
|
571
|
+
await updateJsonAtomic(secretsMarkerPath(), (marker) => withSecretChange(marker, account, token, deleted), {
|
|
572
|
+
mode: 0o600,
|
|
573
|
+
});
|
|
574
|
+
} catch (err) {
|
|
575
|
+
secretMarkerFailure(err);
|
|
576
|
+
}
|
|
577
|
+
finishSecretChange(account, token, deleted);
|
|
578
|
+
}
|
|
579
|
+
|
|
429
580
|
// Config-change notification. In-process writes notify directly after the file
|
|
430
581
|
// is persisted; writes from other processes arrive through one lazily started
|
|
431
582
|
// directory watch (the atomic rename replaces the file, which would orphan a
|
|
432
583
|
// file-level watch on POSIX). Bursts coalesce into one listener pass.
|
|
433
584
|
const CONFIG_CHANGE_DEBOUNCE_MS = 100;
|
|
585
|
+
// A watch that failed (or could not start) is re-established on this delay
|
|
586
|
+
// while anyone listens; changes missed meanwhile are announced once it is back.
|
|
587
|
+
const CONFIG_WATCH_RETRY_MS = 1000;
|
|
588
|
+
const WATCHED_FILES = new Set(['mixdog-config.json', SECRETS_MARKER_FILE]);
|
|
434
589
|
const _configChangeListeners = new Set();
|
|
435
590
|
let _configChangeTimer = null;
|
|
436
591
|
let _configWatcher = null;
|
|
437
592
|
let _configWatchDir = '';
|
|
593
|
+
let _configWatchRetryTimer = null;
|
|
594
|
+
|
|
595
|
+
/** The directory watch implementation; tests substitute a failing watcher. */
|
|
596
|
+
export const configWatchDeps = { watch: fsWatch };
|
|
438
597
|
|
|
439
598
|
function stopConfigWatcher() {
|
|
440
599
|
try {
|
|
@@ -444,46 +603,142 @@ function stopConfigWatcher() {
|
|
|
444
603
|
_configWatchDir = '';
|
|
445
604
|
}
|
|
446
605
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
606
|
+
// The watched files' bytes at the last listener pass (or the first subscribe).
|
|
607
|
+
// A pass caused only by the watch finds nothing to do when they are unchanged,
|
|
608
|
+
// e.g. another process rewriting a marker with identical content.
|
|
609
|
+
let _configChangeForced = false;
|
|
610
|
+
let _watchedContent = null;
|
|
611
|
+
|
|
612
|
+
function watchedContent() {
|
|
613
|
+
const dir = dirname(configPath());
|
|
614
|
+
return [...WATCHED_FILES].map((file) => {
|
|
615
|
+
try {
|
|
616
|
+
return readFileSync(join(dir, file), 'latin1');
|
|
617
|
+
} catch {
|
|
618
|
+
return null;
|
|
619
|
+
}
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
// A config that does not parse while a notification pass runs its listeners
|
|
624
|
+
// is usually a write in progress (a hand edit saved half-typed or torn, maybe
|
|
625
|
+
// landing after the pass began): every read of the pass (readConfigFile,
|
|
626
|
+
// readAllForRmW) then throws instead of quarantining it, so the listeners keep
|
|
627
|
+
// their current config, and the pass runs again once shortly. Only reads
|
|
628
|
+
// outside a pass (boot, explicit reads, writes) quarantine it.
|
|
629
|
+
const CONFIG_SETTLE_RETRY_MS = 300;
|
|
630
|
+
let _configSettleTimer = null;
|
|
631
|
+
let _configSettleRetried = false;
|
|
632
|
+
|
|
633
|
+
function configMidWriteError(parseErr) {
|
|
634
|
+
// The retry runs the listeners even when the bytes then equal the ones this
|
|
635
|
+
// pass saw (the save completed back to them).
|
|
636
|
+
_configChangeForced = true;
|
|
637
|
+
if (!_configSettleRetried && !_configSettleTimer && _configChangeListeners.size) {
|
|
638
|
+
_configSettleTimer = setTimeout(() => {
|
|
639
|
+
_configSettleTimer = null;
|
|
640
|
+
_configSettleRetried = true;
|
|
641
|
+
void runConfigChangeListeners();
|
|
642
|
+
}, CONFIG_SETTLE_RETRY_MS);
|
|
643
|
+
_configSettleTimer.unref?.();
|
|
644
|
+
}
|
|
645
|
+
const error = new Error(
|
|
646
|
+
`[config] mixdog-config.json does not parse yet (${parseErr.message}); keeping the current config`
|
|
647
|
+
);
|
|
648
|
+
error.code = 'ECONFIG_MID_WRITE';
|
|
649
|
+
return error;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
async function runConfigChangeListeners() {
|
|
653
|
+
const forced = _configChangeForced;
|
|
654
|
+
_configChangeForced = false;
|
|
655
|
+
const content = watchedContent();
|
|
656
|
+
const last = _watchedContent;
|
|
657
|
+
if (!forced && Array.isArray(last) && last.every((value, index) => value === content[index])) return;
|
|
658
|
+
_watchedContent = content;
|
|
659
|
+
invalidateConfigReadCache();
|
|
660
|
+
// A Linux keyring is read only through a snapshot, which the invalidation
|
|
661
|
+
// dropped: re-take it so listeners reload the changed keys.
|
|
662
|
+
if (syncSecretsMarker().length && process.platform === 'linux') {
|
|
663
|
+
try {
|
|
664
|
+
await _prewarmSecrets?.();
|
|
665
|
+
} catch {}
|
|
666
|
+
}
|
|
667
|
+
_inNotificationPass = true;
|
|
668
|
+
try {
|
|
453
669
|
for (const listener of [..._configChangeListeners]) {
|
|
454
670
|
try {
|
|
455
671
|
listener();
|
|
456
672
|
} catch {}
|
|
457
673
|
}
|
|
674
|
+
} finally {
|
|
675
|
+
_inNotificationPass = false;
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
// In-process writes and a re-established watch always run the listeners (a
|
|
680
|
+
// secret stored while its marker write failed changes no watched byte).
|
|
681
|
+
function notifyConfigChanged({ fromWatch = false } = {}) {
|
|
682
|
+
if (!_configChangeListeners.size) return;
|
|
683
|
+
if (!fromWatch) _configChangeForced = true;
|
|
684
|
+
_configSettleRetried = false;
|
|
685
|
+
if (_configChangeTimer) clearTimeout(_configChangeTimer);
|
|
686
|
+
_configChangeTimer = setTimeout(() => {
|
|
687
|
+
_configChangeTimer = null;
|
|
688
|
+
void runConfigChangeListeners();
|
|
458
689
|
}, CONFIG_CHANGE_DEBOUNCE_MS);
|
|
459
690
|
_configChangeTimer.unref?.();
|
|
460
691
|
}
|
|
461
692
|
|
|
693
|
+
function scheduleConfigWatchRetry() {
|
|
694
|
+
if (_configWatchRetryTimer || !_configChangeListeners.size) return;
|
|
695
|
+
_configWatchRetryTimer = setTimeout(() => {
|
|
696
|
+
_configWatchRetryTimer = null;
|
|
697
|
+
if (!_configChangeListeners.size) return;
|
|
698
|
+
ensureConfigWatcher();
|
|
699
|
+
if (_configWatcher) notifyConfigChanged();
|
|
700
|
+
}, CONFIG_WATCH_RETRY_MS);
|
|
701
|
+
_configWatchRetryTimer.unref?.();
|
|
702
|
+
}
|
|
703
|
+
|
|
462
704
|
function ensureConfigWatcher() {
|
|
463
705
|
const dir = dirname(configPath());
|
|
464
706
|
if (_configWatcher && _configWatchDir === dir) return;
|
|
465
707
|
stopConfigWatcher();
|
|
466
708
|
try {
|
|
467
|
-
|
|
468
|
-
if (!filename || String(filename)
|
|
709
|
+
const watcher = configWatchDeps.watch(dir, (_event, filename) => {
|
|
710
|
+
if (!filename || WATCHED_FILES.has(String(filename))) notifyConfigChanged({ fromWatch: true });
|
|
469
711
|
});
|
|
470
|
-
|
|
471
|
-
|
|
712
|
+
watcher.unref?.();
|
|
713
|
+
watcher.on?.('error', () => {
|
|
714
|
+
if (_configWatcher !== watcher) return;
|
|
715
|
+
stopConfigWatcher();
|
|
716
|
+
scheduleConfigWatchRetry();
|
|
717
|
+
});
|
|
718
|
+
_configWatcher = watcher;
|
|
472
719
|
_configWatchDir = dir;
|
|
473
720
|
} catch {
|
|
474
721
|
_configWatcher = null;
|
|
722
|
+
scheduleConfigWatchRetry();
|
|
475
723
|
}
|
|
476
724
|
}
|
|
477
725
|
|
|
478
|
-
/** Subscribe to persisted config changes (this process or another). Returns unsubscribe. */
|
|
726
|
+
/** Subscribe to persisted config and secret changes (this process or another). Returns unsubscribe. */
|
|
479
727
|
export function subscribeConfigChange(listener) {
|
|
728
|
+
if (!_configChangeListeners.size) _watchedContent = watchedContent();
|
|
480
729
|
_configChangeListeners.add(listener);
|
|
730
|
+
// The first subscriber fixes the secret baseline this process applies from.
|
|
731
|
+
if (_secretsSeen === null) syncSecretsMarker();
|
|
481
732
|
ensureConfigWatcher();
|
|
482
733
|
return () => {
|
|
483
734
|
_configChangeListeners.delete(listener);
|
|
484
735
|
if (!_configChangeListeners.size) {
|
|
485
736
|
if (_configChangeTimer) clearTimeout(_configChangeTimer);
|
|
486
737
|
_configChangeTimer = null;
|
|
738
|
+
clearTimeout(_configSettleTimer);
|
|
739
|
+
_configSettleTimer = null;
|
|
740
|
+
if (_configWatchRetryTimer) clearTimeout(_configWatchRetryTimer);
|
|
741
|
+
_configWatchRetryTimer = null;
|
|
487
742
|
stopConfigWatcher();
|
|
488
743
|
}
|
|
489
744
|
};
|
|
@@ -664,6 +919,7 @@ function _readSecret(account) {
|
|
|
664
919
|
const envVal = process.env[_envKey(account)];
|
|
665
920
|
if (envVal) return envVal;
|
|
666
921
|
try {
|
|
922
|
+
syncSecretsMarkerIfMoved();
|
|
667
923
|
return _getSecret(account);
|
|
668
924
|
} catch {
|
|
669
925
|
return null;
|
|
@@ -692,6 +948,7 @@ export function saveSecret(account, value) {
|
|
|
692
948
|
} catch (err) {
|
|
693
949
|
throw saveSecretError(account, err);
|
|
694
950
|
}
|
|
951
|
+
publishSecretChange(account);
|
|
695
952
|
}
|
|
696
953
|
|
|
697
954
|
/** Non-blocking saveSecret: Linux secret-tool runs off the event loop. */
|
|
@@ -701,6 +958,7 @@ export async function saveSecretAsync(account, value) {
|
|
|
701
958
|
} catch (err) {
|
|
702
959
|
throw saveSecretError(account, err);
|
|
703
960
|
}
|
|
961
|
+
await publishSecretChangeAsync(account);
|
|
704
962
|
}
|
|
705
963
|
|
|
706
964
|
function saveSecretError(account, err) {
|
|
@@ -725,11 +983,49 @@ function saveSecretError(account, err) {
|
|
|
725
983
|
/** Remove a secret from the OS keychain (if present) and the Linux fallback file. */
|
|
726
984
|
export function deleteSecret(account) {
|
|
727
985
|
_deleteSecret(account);
|
|
986
|
+
publishSecretChange(account, true);
|
|
728
987
|
}
|
|
729
988
|
|
|
730
989
|
/** Non-blocking deleteSecret: Linux secret-tool runs off the event loop. */
|
|
731
990
|
export async function deleteSecretAsync(account) {
|
|
732
991
|
await _deleteSecretAsync(account);
|
|
992
|
+
await publishSecretChangeAsync(account, true);
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
/**
|
|
996
|
+
* The keychain as a credential store for modules that keep their own secrets
|
|
997
|
+
* in it (MCP OAuth tokens and client secrets, Gmail app passwords). Reads are
|
|
998
|
+
* the keychain's own; every write publishes the secret change marker exactly
|
|
999
|
+
* as saveSecret/deleteSecret do, so other processes learn of it. Write errors
|
|
1000
|
+
* stay the keychain's: the provider-key environment hint of saveSecret does
|
|
1001
|
+
* not apply to these accounts. Calls reach the keychain module at call time.
|
|
1002
|
+
* `{ announce: false }` writes without the marker, for a change other
|
|
1003
|
+
* processes observe by their own means (an MCP OAuth token refresh: its
|
|
1004
|
+
* revision marker), so it does not reach every runtime as a settings change.
|
|
1005
|
+
* Reads first apply the marker, so a process without a config-change
|
|
1006
|
+
* subscriber never serves a secret changed or forgotten elsewhere.
|
|
1007
|
+
*/
|
|
1008
|
+
export const keychainSecretStore = Object.freeze({
|
|
1009
|
+
getSecretAsync(account) {
|
|
1010
|
+
syncSecretsMarkerIfMoved();
|
|
1011
|
+
return _keychain.getSecretAsync(account);
|
|
1012
|
+
},
|
|
1013
|
+
invalidateSecretCache: (account) => _keychain.invalidateSecretCache?.(account),
|
|
1014
|
+
async setSecretAsync(account, value, { announce = true } = {}) {
|
|
1015
|
+
await _keychain.setSecretAsync(account, value);
|
|
1016
|
+
if (announce) await publishSecretChangeAsync(account);
|
|
1017
|
+
},
|
|
1018
|
+
async deleteSecretAsync(account, { announce = true } = {}) {
|
|
1019
|
+
await _keychain.deleteSecretAsync(account);
|
|
1020
|
+
if (announce) await publishSecretChangeAsync(account, true);
|
|
1021
|
+
},
|
|
1022
|
+
});
|
|
1023
|
+
|
|
1024
|
+
/** Announce a change of state kept outside mixdog-config.json that settings
|
|
1025
|
+
* depend on (`plugins`: the plugin registry), under a reserved `#` key of the
|
|
1026
|
+
* secret change marker, so it reaches other processes on the same path. */
|
|
1027
|
+
export function announceStoredStateChange(key) {
|
|
1028
|
+
publishSecretChange(`#${key}`);
|
|
733
1029
|
}
|
|
734
1030
|
|
|
735
1031
|
/** Retry a failed Linux keyring read; true when it just recovered. */
|
|
@@ -763,6 +1059,7 @@ export function getKeychainStatus() {
|
|
|
763
1059
|
*/
|
|
764
1060
|
export function hasStoredSecret(account) {
|
|
765
1061
|
try {
|
|
1062
|
+
syncSecretsMarkerIfMoved();
|
|
766
1063
|
if (typeof _hasSecret === 'function') return !!_hasSecret(account);
|
|
767
1064
|
return !!_getSecret(account);
|
|
768
1065
|
} catch {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
// What a
|
|
1
|
+
// What a connector server tells the model about its accounts (MCP
|
|
2
2
|
// `instructions`), in one line: the connected accounts, and that each tool
|
|
3
|
-
// takes `account` (
|
|
4
|
-
//
|
|
3
|
+
// takes `account` (left out, the account used last). An account that cannot
|
|
4
|
+
// be used right now is listed with why.
|
|
5
5
|
|
|
6
6
|
/** The MCP instructions naming `accounts` (`{ email, note? }`, `note` a short
|
|
7
7
|
* reason it is unusable such as "needs sign-in"; one without an address is
|
|
@@ -12,12 +12,12 @@ export function connectorAccountsInstructions(accounts) {
|
|
|
12
12
|
const list = named.map(({ email, note }) => (note ? `${email} (${note})` : email)).join(', ');
|
|
13
13
|
return named.length === 1
|
|
14
14
|
? `Accounts: ${list}. \`account\` may be left out.`
|
|
15
|
-
: `Accounts: ${list}.
|
|
15
|
+
: `Accounts: ${list}. \`account\` picks one; left out, a call uses the account used last, and its result names it.`;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
/** The account addresses instructions from connectorAccountsInstructions name. */
|
|
19
19
|
export function accountsOfInstructions(instructions) {
|
|
20
|
-
const list = /^Accounts: (.+?)\.
|
|
20
|
+
const list = /^Accounts: (.+?)\. `account`/.exec(String(instructions || ''))?.[1] || '';
|
|
21
21
|
return list
|
|
22
22
|
.split(', ')
|
|
23
23
|
.map((part) => part.replace(/ \(.*\)$/, '').trim())
|
|
@@ -37,12 +37,7 @@ export const CONNECTOR_IDS: readonly string[];
|
|
|
37
37
|
export function connectorById(id: unknown): ConnectorCatalogEntry | null;
|
|
38
38
|
export function connectorOfServer(cfg: unknown): string;
|
|
39
39
|
export function connectorToolDefault(connectorId: string, tool: string): 'auto' | 'needs_approval';
|
|
40
|
-
export function connectorServerInput(
|
|
41
|
-
entry: ConnectorCatalogEntry,
|
|
42
|
-
name: string,
|
|
43
|
-
key?: string,
|
|
44
|
-
options?: { extraAccount?: boolean }
|
|
45
|
-
): Record<string, unknown>;
|
|
40
|
+
export function connectorServerInput(entry: ConnectorCatalogEntry, name: string, key?: string): Record<string, unknown>;
|
|
46
41
|
export function connectorAppPasswordOnly(entry: ConnectorCatalogEntry | null | undefined): boolean;
|
|
47
42
|
export function connectorUsesGoogleClient(entry: ConnectorCatalogEntry | null | undefined): boolean;
|
|
48
43
|
export function connectorMultiAccount(entry: ConnectorCatalogEntry | null | undefined): boolean;
|
|
@@ -52,12 +47,21 @@ export function gmailAppPasswordValue(value: unknown): string;
|
|
|
52
47
|
export function gmailAppPasswordAccount(cfg: unknown): string;
|
|
53
48
|
export function gmailAppPasswordServerInput(name: string, email: string, password: string): Record<string, unknown>;
|
|
54
49
|
|
|
55
|
-
/** One stored account of a
|
|
50
|
+
/** One stored account of a connector server. */
|
|
56
51
|
export interface ConnectorAccountEntry {
|
|
57
52
|
name: string;
|
|
58
|
-
|
|
53
|
+
/** Its identity, given when it was added (connectorAccountId). */
|
|
54
|
+
id?: string;
|
|
55
|
+
/** Absent: http. */
|
|
56
|
+
type?: string;
|
|
57
|
+
url?: string;
|
|
59
58
|
headers?: Record<string, string>;
|
|
60
59
|
oauthClientId?: string;
|
|
60
|
+
/** The account's own sign-in key, when another account signs in at its URL. */
|
|
61
|
+
oauthKey?: string;
|
|
62
|
+
command?: string;
|
|
63
|
+
args?: string[];
|
|
64
|
+
env?: Record<string, string>;
|
|
61
65
|
/** `false`: the account is kept but neither connected nor called. */
|
|
62
66
|
enabled?: boolean;
|
|
63
67
|
}
|
|
@@ -67,6 +71,7 @@ export function connectorAccountServer(
|
|
|
67
71
|
cfg: Record<string, unknown>,
|
|
68
72
|
account: ConnectorAccountEntry
|
|
69
73
|
): Record<string, unknown>;
|
|
74
|
+
export function connectorAccountId(cfg: Record<string, unknown>, account: ConnectorAccountEntry): string;
|
|
70
75
|
export function connectorAccountServers(cfg: unknown): Record<string, unknown>[];
|
|
71
76
|
export function connectorAccountEnabled(account: ConnectorAccountEntry): boolean;
|
|
72
77
|
export function connectorLiveAccountServers(cfg: unknown): Record<string, unknown>[];
|
|
@@ -76,6 +81,7 @@ export function withConnectorAccountEnabled(
|
|
|
76
81
|
enabled: boolean
|
|
77
82
|
): Record<string, unknown>;
|
|
78
83
|
export function connectorAccountEntry(name: string, cfg: Record<string, unknown>): ConnectorAccountEntry;
|
|
84
|
+
export function connectorServerSettings(cfg: Record<string, unknown>): Record<string, unknown>;
|
|
79
85
|
export function mergeConnectorAccountServers(servers: Record<string, unknown>): {
|
|
80
86
|
servers: Record<string, unknown>;
|
|
81
87
|
merged: { connector: string; name: string; from: string[] }[];
|