mixdog 1.2.0 → 1.2.2
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/README.md +7 -5
- package/package.json +1 -1
- package/scripts/gate-local.mjs +19 -3
- package/scripts/model-catalog-audit.mjs +1 -15
- package/src/agents/reviewer/AGENT.md +3 -3
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +5 -0
- package/src/defaults/skills/pptx/SKILL.md +6 -6
- package/src/defaults/skills/pptx/references/review.md +6 -4
- package/src/defaults/skills/pptx/scripts/source-extract.mjs +1 -1
- package/src/defaults/skills/setup/references/actions.md +13 -3
- package/src/defaults/skills/visualize/SKILL.md +12 -9
- package/src/repl/slash-commands.mjs +16 -1
- package/src/rules/shared/60-verification.md +3 -1
- package/src/rules/shared/70-delivery.md +4 -2
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +29 -4
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +10 -0
- package/src/runtime/agent/orchestrator/cache-mtime.mjs +26 -5
- package/src/runtime/agent/orchestrator/config.mjs +10 -4
- package/src/runtime/agent/orchestrator/context/collect.mjs +2 -1
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +11 -5
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +74 -21
- package/src/runtime/agent/orchestrator/mcp/client-config.mjs +122 -15
- package/src/runtime/agent/orchestrator/mcp/client-handshake.mjs +54 -11
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +104 -9
- package/src/runtime/agent/orchestrator/mcp/client.mjs +358 -140
- package/src/runtime/agent/orchestrator/mcp/lazy-output-validator.mjs +25 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +103 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +150 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +111 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-probe.mjs +87 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +95 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-request.mjs +122 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-shared.mjs +9 -0
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +229 -0
- package/src/runtime/agent/orchestrator/mcp/plugin-placeholders.mjs +54 -0
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +294 -44
- package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +94 -31
- package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +96 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-fast-mode.mjs +39 -18
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +55 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +25 -21
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-midstream-recovery.mjs +18 -4
- package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +13 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-midstream.mjs +10 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-recovery.mjs +23 -9
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/initial-status.mjs +46 -20
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request.mjs +14 -9
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +73 -35
- package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +69 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-server-fallback.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +8 -1
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +53 -18
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +30 -9
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +30 -14
- package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +93 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +82 -9
- package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +337 -0
- package/src/runtime/agent/orchestrator/providers/command-code-oauth-tokens.mjs +159 -0
- package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +447 -0
- package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +38 -5
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor-wire-guards.mjs +97 -2
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +102 -23
- package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +103 -33
- package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +29 -6
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +18 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +7 -4
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +86 -19
- package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +29 -8
- package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +191 -0
- package/src/runtime/agent/orchestrator/providers/gemini-family.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/gemini-history-signatures.mjs +9 -4
- package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +180 -0
- package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +21 -82
- package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +71 -12
- package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +21 -20
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +97 -51
- package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +68 -19
- package/src/runtime/agent/orchestrator/providers/lib/gemini-model-catalog.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/model-list-sanitize.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-bridge.mjs +1080 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +15 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +35 -0
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +4 -9
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +12 -0
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +6 -5
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +5 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +22 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-error-contract.mjs +50 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +6 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +11 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +23 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +16 -8
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-state.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +94 -13
- package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +193 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +66 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +6 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +6 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +23 -14
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +26 -6
- package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +42 -25
- package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +274 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-request.mjs +72 -32
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +18 -11
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs +1 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-stamps.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-state.mjs +2 -3
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +1 -3
- package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +34 -3
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +5 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +22 -2
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +5 -0
- package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +5 -9
- package/src/runtime/agent/orchestrator/providers/openai-retry-policy.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-handshake.mjs +16 -8
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +1 -2
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/policy.mjs +25 -14
- package/src/runtime/agent/orchestrator/providers/openai-ws-terminal.mjs +18 -11
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +35 -24
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +581 -0
- package/src/runtime/agent/orchestrator/providers/registry.mjs +35 -9
- package/src/runtime/agent/orchestrator/providers/retry-backoff.mjs +46 -7
- package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +118 -219
- package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +148 -45
- package/src/runtime/agent/orchestrator/providers/retry-midstream.mjs +81 -16
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/extension-scopes.mjs +15 -55
- package/src/runtime/agent/orchestrator/runtime-core/goal-control.mjs +15 -2
- package/src/runtime/agent/orchestrator/runtime-core/goal-reminder.mjs +0 -18
- package/src/runtime/agent/orchestrator/runtime-core/model-capabilities.mjs +57 -28
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +19 -16
- package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +268 -181
- package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +4 -1
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +21 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +54 -3
- package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +284 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +270 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/sqlite-gate.mjs +27 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/worker.mjs +628 -0
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +184 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +136 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +128 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +127 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +101 -0
- package/src/runtime/agent/orchestrator/session/explicit-skills.mjs +83 -5
- package/src/runtime/agent/orchestrator/session/imported-message.mjs +11 -0
- package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +10 -4
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +4 -3
- package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +102 -18
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +42 -5
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +14 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +20 -12
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +50 -23
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +22 -14
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +18 -7
- package/src/runtime/agent/orchestrator/session/manager.mjs +0 -1
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +4 -3
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +155 -29
- package/src/runtime/agent/orchestrator/session/store/listing.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +6 -3
- package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/store/write-guards.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +22 -10
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +819 -0
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +12 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +22 -12
- package/src/runtime/agent/orchestrator/session/store-summary-reader-catalog-fixture.mjs +158 -0
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +183 -374
- package/src/runtime/agent/orchestrator/session/synthetic-user-envelope.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +41 -3
- package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +38 -17
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/deadline-plan.mjs +12 -15
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +17 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -0
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +5 -5
- package/src/runtime/agent/orchestrator/tools/builtin/lib/list-helpers.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/path-diagnostics.mjs +6 -6
- package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +173 -22
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-guards.mjs +8 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +5 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-source-windows.mjs +15 -2
- package/src/runtime/agent/orchestrator/tools/builtin/search-glob-tool.mjs +13 -10
- package/src/runtime/agent/orchestrator/tools/builtin/search-grep-tool.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +17 -12
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch/apply-patch/codex-batch.mjs +4 -4
- package/src/runtime/agent/orchestrator/tools/patch/apply-patch/route.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch/read-redirects.mjs +34 -30
- package/src/runtime/agent/orchestrator/tools/patch/sequence/units.mjs +7 -7
- package/src/runtime/agent/orchestrator/tools/patch/sequence.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +4 -0
- package/src/runtime/attachments/store.d.mts +3 -0
- package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +1 -1
- package/src/runtime/channels/lib/webhook/session-dispatch.mjs +16 -4
- package/src/runtime/channels/lib/worker-main.mjs +17 -14
- package/src/runtime/computer-bridge/linux-readiness.mjs +0 -2
- package/src/runtime/effort-judge/judge-client.mjs +56 -18
- package/src/runtime/memory/lib/memory.mjs +1 -1
- package/src/runtime/memory/lib/pg/process.mjs +34 -24
- package/src/runtime/memory/lib/pg/supervisor.mjs +16 -13
- package/src/runtime/memory/lib/session-ingest.mjs +2 -2
- package/src/runtime/office/README.md +1 -1
- package/src/runtime/office/shared/values.mjs +0 -5
- package/src/runtime/shared/atomic-file.mjs +25 -4
- package/src/runtime/shared/background-tasks.mjs +92 -14
- package/src/runtime/shared/err-text.mjs +25 -0
- package/src/runtime/shared/error-presentation.mjs +159 -19
- package/src/runtime/shared/extension-scopes.mjs +5 -3
- package/src/runtime/shared/file-lock.mjs +37 -11
- package/src/runtime/shared/llm/anthropic-betas.mjs +4 -3
- package/src/runtime/shared/llm/anthropic-effort.mjs +134 -131
- package/src/runtime/shared/llm/anthropic-thinking-contract.mjs +50 -14
- package/src/runtime/shared/llm/model-catalog.mjs +53 -52
- package/src/runtime/shared/llm/openai-daybreak.mjs +4 -16
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +17 -0
- package/src/runtime/shared/llm/provider-model-identities.mjs +13 -4
- package/src/runtime/shared/llm/usage-rollup.mjs +0 -1
- package/src/runtime/shared/model-display.mjs +13 -0
- package/src/runtime/shared/plugin-manifest.mjs +18 -9
- package/src/runtime/shared/pristine-execution-contract.json +9 -2
- package/src/runtime/shared/pristine-execution.mjs +28 -4
- package/src/runtime/shared/provider-accounts.mjs +124 -20
- package/src/runtime/shared/provider-api-key.mjs +12 -0
- package/src/runtime/shared/quota-resume-store.mjs +11 -0
- package/src/runtime/shared/session-baseline-store.mjs +960 -0
- package/src/runtime/shared/shell-display.mjs +9 -3
- package/src/runtime/shared/skill-mentions.d.mts +10 -0
- package/src/runtime/shared/skill-mentions.mjs +133 -0
- package/src/runtime/shared/skill-script-runtime.mjs +264 -0
- package/src/runtime/shared/statusline/statusline-format.mjs +4 -4
- package/src/runtime/shared/task-notification-envelope.mjs +2 -2
- package/src/runtime/shared/tool-primitives.mjs +35 -2
- package/src/runtime/shared/turn-changes.mjs +447 -219
- package/src/runtime/shared/turn-snapshot-store.mjs +182 -1
- package/src/runtime/shared/turn-snapshot.mjs +170 -48
- package/src/runtime/shared/turn-worktree-snapshot.mjs +160 -51
- package/src/runtime/shared/worker-requests.mjs +15 -2
- package/src/runtime/shared/worktrees/contract.mjs +0 -24
- package/src/runtime/shared/worktrees/test-support.mjs +19 -4
- package/src/session-runtime/automation-agents.mjs +8 -2
- package/src/session-runtime/boot/apis.mjs +61 -0
- package/src/session-runtime/boot/config.mjs +5 -2
- package/src/session-runtime/boot/facade.mjs +1 -0
- package/src/session-runtime/boot/infrastructure.mjs +35 -18
- package/src/session-runtime/conversation-import/discovery.mjs +698 -0
- package/src/session-runtime/conversation-import/service.mjs +369 -0
- package/src/session-runtime/cwd-plugins/cwd-apply.mjs +10 -5
- package/src/session-runtime/cwd-plugins/plugin-status.mjs +47 -42
- package/src/session-runtime/lifecycle/session-catalog.mjs +2 -0
- package/src/session-runtime/lifecycle/teardown.mjs +1 -1
- package/src/session-runtime/mcp-glue/connect.mjs +83 -16
- package/src/session-runtime/mcp-glue/plugin-servers.mjs +499 -0
- package/src/session-runtime/mcp-glue/server-catalog.mjs +135 -33
- package/src/session-runtime/mcp-glue.mjs +25 -2
- package/src/session-runtime/mcp-oauth-login.mjs +174 -0
- package/src/session-runtime/model-route/model-switch-target.mjs +34 -0
- package/src/session-runtime/model-route/set-route.mjs +83 -15
- package/src/session-runtime/model-route/web-search-route.mjs +1 -1
- package/src/session-runtime/native-web-search/routes.mjs +22 -3
- package/src/session-runtime/new-session-config.mjs +3 -2
- package/src/session-runtime/notification-bus.mjs +9 -2
- package/src/session-runtime/provider-auth/accounts.mjs +33 -15
- package/src/session-runtime/provider-models/model-meta.mjs +12 -3
- package/src/session-runtime/provider-models/web-search-catalog.mjs +5 -1
- package/src/session-runtime/provider-readiness.mjs +16 -10
- package/src/session-runtime/quick-model-rows/web-search-rows.mjs +13 -8
- package/src/session-runtime/quick-web-search-models.mjs +13 -38
- package/src/session-runtime/resource-extension-sync.mjs +24 -5
- package/src/session-runtime/resource-mcp-api.mjs +198 -78
- package/src/session-runtime/resource-plugins-api.mjs +29 -41
- package/src/session-runtime/resource-scope-decorate.mjs +6 -8
- package/src/session-runtime/resource-skills-api.mjs +23 -2
- package/src/session-runtime/runtime-review-api.mjs +13 -0
- package/src/session-runtime/schedule-session-run.mjs +1 -1
- package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +13 -1
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +7 -2
- package/src/session-runtime/services/agent-tool/send-flow.mjs +22 -4
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +2 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +22 -5
- package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +8 -1
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -2
- package/src/session-runtime/services/agent-tool/worker-rows.mjs +17 -0
- package/src/session-runtime/services/channel-session-router.mjs +4 -1
- package/src/session-runtime/services/hook-bus/command-handler.mjs +4 -1
- package/src/session-runtime/services/hook-bus/handlers.mjs +7 -3
- package/src/session-runtime/services/provider-admin.mjs +64 -18
- package/src/session-runtime/services/usage-dashboard-model.mjs +3 -0
- package/src/session-runtime/settings-compaction-api.mjs +1 -0
- package/src/session-runtime/setup-tool/executor.mjs +12 -1
- package/src/session-runtime/setup-tool/extended-actions.mjs +1 -0
- package/src/session-runtime/setup-tool/settings-contract.mjs +1 -0
- package/src/session-runtime/setup-tool/tool-defs.mjs +7 -1
- package/src/session-runtime/skills-api.mjs +7 -3
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
- package/src/session-runtime/webhook-session-run.mjs +16 -4
- package/src/skill-script-entry.mjs +36 -0
- package/src/standalone/daemon-drain-policy.mjs +8 -0
- package/src/standalone/daemon-stored-session-views.mjs +11 -3
- package/src/standalone/daemon-telemetry.mjs +55 -0
- package/src/standalone/daemon.mjs +44 -11
- package/src/standalone/session-protocol.mjs +12 -0
- package/src/standalone/session-service/agent-tree/agent-cancel.mjs +33 -2
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +26 -10
- package/src/standalone/session-service/agent-tree.mjs +12 -0
- package/src/standalone/session-service/quota-resume.mjs +8 -0
- package/src/standalone/session-service/retention/busy.mjs +15 -1
- package/src/standalone/session-service/session-calls/session-action.mjs +6 -1
- package/src/standalone/session-service-api.mjs +5 -0
- package/src/standalone/session-service.mjs +1 -0
- package/src/tui/App.jsx +9 -1
- package/src/tui/app/app-view/floating-panel.jsx +9 -1
- package/src/tui/app/app-view.jsx +7 -0
- package/src/tui/app/create-app-pickers.mjs +4 -0
- package/src/tui/app/extension-pickers/mcp-login.mjs +107 -0
- package/src/tui/app/extension-pickers/mcp-servers-picker.mjs +2 -1
- package/src/tui/app/extension-pickers/plugins-pickers.mjs +35 -16
- package/src/tui/app/extension-pickers.mjs +2 -1
- package/src/tui/app/model-options.mjs +13 -16
- package/src/tui/app/skill-mention-palette.mjs +88 -0
- package/src/tui/app/slash-commands.mjs +7 -2
- package/src/tui/app/slash-dispatch/panel-commands.mjs +16 -1
- package/src/tui/app/slash-palette.mjs +23 -7
- package/src/tui/app/transcript-row-estimate.mjs +11 -3
- package/src/tui/app/use-prompt-draft-flow.mjs +7 -2
- package/src/tui/app/use-prompt-state.mjs +5 -0
- package/src/tui/components/Message.jsx +22 -1
- package/src/tui/components/PromptInput.jsx +21 -3
- package/src/tui/components/SlashCommandPalette.jsx +12 -3
- package/src/tui/components/StatusLine.jsx +2 -0
- package/src/tui/components/TranscriptItem.jsx +9 -1
- package/src/tui/components/prompt-input/key-handler.mjs +21 -8
- package/src/tui/components/status-line/local-line.mjs +5 -2
- package/src/tui/components/status-line/use-statusline-text.mjs +7 -1
- package/src/tui/components/user-message-skills.mjs +38 -0
- package/src/tui/dist/index.mjs +1323 -214
- package/src/tui/session/queue-helpers.mjs +7 -2
- package/src/tui/session/quota-resume.mjs +46 -14
- package/src/tui/session/session-api/commands.mjs +33 -24
- package/src/tui/session/session-api/extensions.mjs +26 -2
- package/src/tui/session/session-api/integrations.mjs +7 -0
- package/src/tui/session/session-api/lifecycle.mjs +5 -1
- package/src/tui/session/session-api/routes.mjs +71 -7
- package/src/tui/session/session-api/settings.mjs +12 -14
- package/src/tui/session/session-flow/drain.mjs +21 -5
- package/src/tui/session/session-flow/failed-turn-rewind.mjs +10 -4
- package/src/tui/session/tui-steering-persist.mjs +25 -9
- package/src/tui/session/turn.mjs +55 -15
- package/src/tui/statusline-ansi-bridge.mjs +1 -1
- package/src/ui/statusline-agents.mjs +15 -4
- package/src/ui/statusline.mjs +7 -3
- package/src/ui/streaming-markdown-heal.mjs +34 -3
- package/src/vendor/statusline/src/gateway/claude-current.mjs +14 -4
- package/src/runtime/effort-judge/previous-human-request.mjs +0 -162
- package/src/runtime/effort-judge/verified-context-input.mjs +0 -10
- package/src/runtime/memory/lib/memory-session-merge.mjs +0 -32
- package/src/runtime/shared/llm/usage-session-history.mjs +0 -266
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
|
-
import { existsSync, realpathSync } from 'node:fs';
|
|
2
|
+
import { existsSync, lstatSync, realpathSync } from 'node:fs';
|
|
3
3
|
import { access, copyFile, lstat, mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises';
|
|
4
|
-
import { dirname, isAbsolute, join, relative, resolve } from 'node:path';
|
|
4
|
+
import { basename, dirname, isAbsolute, join, relative, resolve } from 'node:path';
|
|
5
5
|
import { PATCH_EDIT_MAX_BYTES } from './bounded-file-read.mjs';
|
|
6
6
|
import { cleanString as clean } from './clean.mjs';
|
|
7
7
|
import { runGitOffThread } from './git-runner.mjs';
|
|
@@ -44,8 +44,26 @@ function pathKey(value) {
|
|
|
44
44
|
|
|
45
45
|
/** `resolve` plus symlinks of the nearest existing ancestor: git reports the
|
|
46
46
|
* worktree root canonically (macOS /var -> /private/var), callers may not. */
|
|
47
|
-
function canonicalPath(value) {
|
|
47
|
+
function canonicalPath(value, dirs = null) {
|
|
48
48
|
const full = resolve(value);
|
|
49
|
+
if (dirs) {
|
|
50
|
+
// Same result as the walk below without repeating it per file: the parent
|
|
51
|
+
// directory is canonicalized once per call; the final component only
|
|
52
|
+
// matters when it is itself a link (or its state is unknown).
|
|
53
|
+
const parent = dirname(full);
|
|
54
|
+
if (parent !== full) {
|
|
55
|
+
let canonicalParent = dirs.get(parent);
|
|
56
|
+
if (canonicalParent === undefined) {
|
|
57
|
+
canonicalParent = canonicalPath(parent);
|
|
58
|
+
dirs.set(parent, canonicalParent);
|
|
59
|
+
}
|
|
60
|
+
try {
|
|
61
|
+
if (!lstatSync(full).isSymbolicLink()) return join(canonicalParent, basename(full));
|
|
62
|
+
} catch (error) {
|
|
63
|
+
if (error?.code === 'ENOENT' || error?.code === 'ENOTDIR') return join(canonicalParent, basename(full));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
49
67
|
let head = full;
|
|
50
68
|
while (!existsSync(head)) {
|
|
51
69
|
const parent = dirname(head);
|
|
@@ -139,8 +157,10 @@ function stateForRoot(root) {
|
|
|
139
157
|
/** Report written paths (or `null`: anything may have changed). The next
|
|
140
158
|
* review poll of an affected worktree captures instead of reusing. */
|
|
141
159
|
export function noteTurnWorktreeChange(paths = null) {
|
|
160
|
+
if (states.size === 0) return;
|
|
142
161
|
const list = Array.isArray(paths) ? paths.filter((value) => clean(value)) : [];
|
|
143
|
-
const
|
|
162
|
+
const dirs = new Map();
|
|
163
|
+
const keys = list.map((value) => pathKey(canonicalPath(value, dirs)));
|
|
144
164
|
for (const state of states.values()) {
|
|
145
165
|
const root = pathKey(state.root);
|
|
146
166
|
if (keys.length === 0 || keys.some((key) => key === root || key.startsWith(`${root}/`))) {
|
|
@@ -149,8 +169,30 @@ export function noteTurnWorktreeChange(paths = null) {
|
|
|
149
169
|
}
|
|
150
170
|
}
|
|
151
171
|
|
|
152
|
-
|
|
153
|
-
|
|
172
|
+
// A lock hold (queue wait plus work) at least this long is logged, so a slow
|
|
173
|
+
// review bar can be told apart as waiting behind other captures or slow git.
|
|
174
|
+
const SLOW_LOCK_LOG_MS = 1_000;
|
|
175
|
+
|
|
176
|
+
function withStateLock(state, task, op = 'task') {
|
|
177
|
+
const queuedAt = Date.now();
|
|
178
|
+
const queuedBehind = state.lockDepth || 0;
|
|
179
|
+
state.lockDepth = queuedBehind + 1;
|
|
180
|
+
let startedAt = 0;
|
|
181
|
+
const timed = async () => {
|
|
182
|
+
startedAt = Date.now();
|
|
183
|
+
return await task();
|
|
184
|
+
};
|
|
185
|
+
const next = state.lock.then(timed, timed).finally(() => {
|
|
186
|
+
state.lockDepth -= 1;
|
|
187
|
+
const finishedAt = Date.now();
|
|
188
|
+
const waitMs = (startedAt || finishedAt) - queuedAt;
|
|
189
|
+
if (finishedAt - queuedAt >= SLOW_LOCK_LOG_MS) {
|
|
190
|
+
console.info(
|
|
191
|
+
`[turn-snapshot-lock] op=${op} waitMs=${waitMs} workMs=${finishedAt - (startedAt || finishedAt)} ` +
|
|
192
|
+
`queuedBehind=${queuedBehind} root=${state.root}`
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
});
|
|
154
196
|
state.lock = next.then(
|
|
155
197
|
() => undefined,
|
|
156
198
|
() => undefined
|
|
@@ -318,6 +360,7 @@ async function ensureState(state) {
|
|
|
318
360
|
}
|
|
319
361
|
|
|
320
362
|
async function resetShadowIndex(state) {
|
|
363
|
+
state.lastCapture = null;
|
|
321
364
|
state.sourceIndexPath ??= await sourceGitPath(state.root, 'index');
|
|
322
365
|
const sourceIndex = state.sourceIndexPath;
|
|
323
366
|
const target = join(state.gitDir, 'index');
|
|
@@ -380,10 +423,33 @@ async function changedWorktreePaths(state) {
|
|
|
380
423
|
};
|
|
381
424
|
}
|
|
382
425
|
|
|
383
|
-
|
|
426
|
+
/** The capture sequence a caller observes before queueing on the lock. */
|
|
427
|
+
function captureSequence(state) {
|
|
428
|
+
return state.captureSeq || 0;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/** `after` (a captureSequence() read before queueing): a capture of this root
|
|
432
|
+
* that began after that point, with no reported write since and covering
|
|
433
|
+
* every explicit path, already is a capture that began after the call. Many
|
|
434
|
+
* sessions of one repository queue reads together; they share that capture
|
|
435
|
+
* instead of each re-scanning the worktree in turn. */
|
|
436
|
+
async function captureTreeUnlocked(state, toolPaths = [], { after = -1 } = {}) {
|
|
384
437
|
await ensureState(state);
|
|
385
|
-
const { paths, excludedUntracked } = await changedWorktreePaths(state);
|
|
386
438
|
const explicit = new Set(toolPaths);
|
|
439
|
+
const last = state.lastCapture;
|
|
440
|
+
if (
|
|
441
|
+
after >= 0 &&
|
|
442
|
+
last &&
|
|
443
|
+
last.seq > after &&
|
|
444
|
+
last.stamp === state.changeStamp &&
|
|
445
|
+
[...explicit].every((rel) => last.explicit.has(rel))
|
|
446
|
+
) {
|
|
447
|
+
return last.tree;
|
|
448
|
+
}
|
|
449
|
+
state.captureSeq = captureSequence(state) + 1;
|
|
450
|
+
const capture = { seq: state.captureSeq, stamp: state.changeStamp, explicit, tree: '' };
|
|
451
|
+
state.lastCapture = null;
|
|
452
|
+
const { paths, excludedUntracked } = await changedWorktreePaths(state);
|
|
387
453
|
for (const rel of explicit) {
|
|
388
454
|
try {
|
|
389
455
|
const stat = await lstat(resolve(state.root, rel));
|
|
@@ -412,7 +478,9 @@ async function captureTreeUnlocked(state, toolPaths = []) {
|
|
|
412
478
|
});
|
|
413
479
|
}
|
|
414
480
|
const tree = await runGit(shadowArgs(state, ['write-tree']), { cwd: state.root });
|
|
415
|
-
|
|
481
|
+
capture.tree = clean(tree.stdout);
|
|
482
|
+
state.lastCapture = capture;
|
|
483
|
+
return capture.tree;
|
|
416
484
|
}
|
|
417
485
|
|
|
418
486
|
/** Only explicit tool targets bypass ignore/size filters. Their first-before
|
|
@@ -781,7 +849,7 @@ function scheduleShadowGc(state) {
|
|
|
781
849
|
async function removeShadowDir(gitDir, removed, kept) {
|
|
782
850
|
if (!(await exists(gitDir))) return;
|
|
783
851
|
await rm(gitDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 }).catch(() => {});
|
|
784
|
-
(await exists(gitDir) ? kept : removed).push(gitDir);
|
|
852
|
+
((await exists(gitDir)) ? kept : removed).push(gitDir);
|
|
785
853
|
}
|
|
786
854
|
|
|
787
855
|
/** Drop every trace of one worktree root: serialize behind its pending capture
|
|
@@ -855,39 +923,74 @@ export async function resumeTurnWorktreeSnapshot(
|
|
|
855
923
|
const root = await repositoryRoot(worktree).catch(() => null);
|
|
856
924
|
if (!root) return null;
|
|
857
925
|
const state = stateForRoot(root);
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
926
|
+
const after = captureSequence(state);
|
|
927
|
+
return await withStateLock(
|
|
928
|
+
state,
|
|
929
|
+
async () => {
|
|
930
|
+
await ensureState(state);
|
|
931
|
+
// A collected or never-written baseline restores nothing. Report that as
|
|
932
|
+
// "no snapshot" instead of failing every later call made against it.
|
|
933
|
+
const kind = await runGit(shadowArgs(state, ['cat-file', '-t', tree]), {
|
|
934
|
+
cwd: state.root,
|
|
935
|
+
allowFailure: true,
|
|
936
|
+
});
|
|
937
|
+
if (kind.code !== 0 || clean(kind.stdout) !== 'tree') return null;
|
|
938
|
+
const scopePaths = Array.isArray(paths) && paths.length > 0 ? [...new Set(paths)] : null;
|
|
939
|
+
const applied = await applyBaselineFilesUnlocked(state, tree, baselineFiles || []);
|
|
940
|
+
const snapshot = {
|
|
941
|
+
state,
|
|
942
|
+
root,
|
|
943
|
+
baselineTree: applied.tree,
|
|
944
|
+
currentTree: tree,
|
|
945
|
+
patch: '',
|
|
946
|
+
files: [],
|
|
947
|
+
patchTruncated: false,
|
|
948
|
+
scopePaths,
|
|
949
|
+
toolPaths: new Set(scopePaths || []),
|
|
950
|
+
pendingBaselines: new Map(),
|
|
951
|
+
baselineFiles: new Map(applied.files.map((entry) => [pathKey(entry.path), entry])),
|
|
952
|
+
};
|
|
953
|
+
const currentTree = await captureTreeUnlocked(state, snapshot.toolPaths, { after });
|
|
954
|
+
Object.assign(
|
|
955
|
+
snapshot,
|
|
956
|
+
withOmittedBaselines(
|
|
957
|
+
snapshot,
|
|
958
|
+
await diffTreesUnlocked(state, snapshot.baselineTree, currentTree, scopePaths, { omitPatch })
|
|
959
|
+
)
|
|
960
|
+
);
|
|
961
|
+
return snapshot;
|
|
962
|
+
},
|
|
963
|
+
'resume'
|
|
964
|
+
);
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
// Git's well-known empty tree: what an unborn HEAD (no commit yet) compares as.
|
|
968
|
+
const EMPTY_TREE = '4b825dc642cb6eb9a060e54bf8d69288fbee4904';
|
|
969
|
+
|
|
970
|
+
/** The files among `paths` whose bytes in the snapshot's last capture still
|
|
971
|
+
* differ from the source repository's current HEAD (staged or not), with
|
|
972
|
+
* their counts against HEAD; no patch text. An ignored file that HEAD does
|
|
973
|
+
* not hold is no uncommitted change and is left out. */
|
|
974
|
+
export async function diffTurnWorktreeHead(snapshot, paths) {
|
|
975
|
+
const scope = [...new Set((paths || []).filter(Boolean))];
|
|
976
|
+
if (!snapshot?.state || !snapshot.currentTree || scope.length === 0) return [];
|
|
977
|
+
return await withStateLock(snapshot.state, async () => {
|
|
978
|
+
const { state } = snapshot;
|
|
979
|
+
const head = await runGit(['rev-parse', '--verify', '--quiet', 'HEAD^{tree}'], {
|
|
863
980
|
cwd: state.root,
|
|
864
981
|
allowFailure: true,
|
|
865
982
|
});
|
|
866
|
-
|
|
867
|
-
const
|
|
868
|
-
const
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
root,
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
scopePaths,
|
|
878
|
-
toolPaths: new Set(scopePaths || []),
|
|
879
|
-
pendingBaselines: new Map(),
|
|
880
|
-
baselineFiles: new Map(applied.files.map((entry) => [pathKey(entry.path), entry])),
|
|
881
|
-
};
|
|
882
|
-
const currentTree = await captureTreeUnlocked(state, snapshot.toolPaths);
|
|
883
|
-
Object.assign(
|
|
884
|
-
snapshot,
|
|
885
|
-
withOmittedBaselines(
|
|
886
|
-
snapshot,
|
|
887
|
-
await diffTreesUnlocked(state, snapshot.baselineTree, currentTree, scopePaths, { omitPatch })
|
|
888
|
-
)
|
|
889
|
-
);
|
|
890
|
-
return snapshot;
|
|
983
|
+
const headTree = head.code === 0 ? clean(head.stdout) : EMPTY_TREE;
|
|
984
|
+
const { files } = await diffTreesUnlocked(state, headTree, snapshot.currentTree, scope, { omitPatch: true });
|
|
985
|
+
const added = files.filter((file) => file.status === 'A').map((file) => file.path);
|
|
986
|
+
if (added.length === 0) return files;
|
|
987
|
+
const ignored = await runGit(['check-ignore', '-z', '--stdin'], {
|
|
988
|
+
cwd: state.root,
|
|
989
|
+
input: `${added.join('\0')}\0`,
|
|
990
|
+
allowFailure: true,
|
|
991
|
+
});
|
|
992
|
+
const skip = new Set(splitNulList(ignored.stdout).map(pathKey));
|
|
993
|
+
return files.filter((file) => file.status !== 'A' || !skip.has(pathKey(file.path)));
|
|
891
994
|
});
|
|
892
995
|
}
|
|
893
996
|
|
|
@@ -910,17 +1013,22 @@ function startRefresh(snapshot) {
|
|
|
910
1013
|
const flight = { seq: (snapshot.refreshSeq || 0) + 1, promise: null };
|
|
911
1014
|
snapshot.refreshSeq = flight.seq;
|
|
912
1015
|
snapshot.refreshing = flight;
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
1016
|
+
const after = captureSequence(snapshot.state);
|
|
1017
|
+
flight.promise = withStateLock(
|
|
1018
|
+
snapshot.state,
|
|
1019
|
+
async () => {
|
|
1020
|
+
const mark = await captureMark(snapshot.state);
|
|
1021
|
+
await materializeToolBaselines(snapshot);
|
|
1022
|
+
const currentTree = await captureTreeUnlocked(snapshot.state, snapshot.toolPaths, { after });
|
|
1023
|
+
if (currentTree !== snapshot.currentTree) {
|
|
1024
|
+
const review = await diffTreesUnlocked(snapshot.state, snapshot.baselineTree, currentTree, snapshot.scopePaths);
|
|
1025
|
+
Object.assign(snapshot, withOmittedBaselines(snapshot, review));
|
|
1026
|
+
}
|
|
1027
|
+
snapshot.captured = mark;
|
|
1028
|
+
return snapshot;
|
|
1029
|
+
},
|
|
1030
|
+
'refresh'
|
|
1031
|
+
).finally(() => {
|
|
924
1032
|
if (snapshot.refreshing === flight) snapshot.refreshing = null;
|
|
925
1033
|
});
|
|
926
1034
|
return flight.promise;
|
|
@@ -962,6 +1070,7 @@ function safeRelativePath(root, value) {
|
|
|
962
1070
|
}
|
|
963
1071
|
|
|
964
1072
|
async function restorePathFromTree(snapshot, rel) {
|
|
1073
|
+
snapshot.state.lastCapture = null;
|
|
965
1074
|
const listed = await runGit(
|
|
966
1075
|
shadowArgs(snapshot.state, ['ls-tree', '-z', '--name-only', snapshot.baselineTree, '--', rel]),
|
|
967
1076
|
{ cwd: snapshot.root }
|
|
@@ -14,8 +14,11 @@ import { parentPort, Worker } from 'node:worker_threads';
|
|
|
14
14
|
* worker is detached before it is terminated, so no request is ever sent to
|
|
15
15
|
* (or lost with) a worker that is shutting down.
|
|
16
16
|
* `request.running()` reports whether a worker thread is currently attached.
|
|
17
|
+
*
|
|
18
|
+
* `onEvent` (optional): receives what the worker sends with postWorkerEvent
|
|
19
|
+
* (messages that answer no request).
|
|
17
20
|
*/
|
|
18
|
-
export function createWorkerRequestClient(url, { idleExitMs = 0, ...workerOptions } = {}) {
|
|
21
|
+
export function createWorkerRequestClient(url, { idleExitMs = 0, onEvent = null, ...workerOptions } = {}) {
|
|
19
22
|
let worker = null;
|
|
20
23
|
let nextRequestId = 0;
|
|
21
24
|
// Requests belong to the worker they were posted to: a replacement worker
|
|
@@ -50,7 +53,12 @@ export function createWorkerRequestClient(url, { idleExitMs = 0, ...workerOption
|
|
|
50
53
|
owned.clear();
|
|
51
54
|
for (const entry of entries) entry.reject(error);
|
|
52
55
|
};
|
|
53
|
-
created.on('message', (
|
|
56
|
+
created.on('message', (message) => {
|
|
57
|
+
if (message && Object.hasOwn(message, 'event')) {
|
|
58
|
+
onEvent?.(message.event);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const { id, result, error } = message;
|
|
54
62
|
const entry = owned.get(id);
|
|
55
63
|
if (!entry) return;
|
|
56
64
|
owned.delete(id);
|
|
@@ -109,6 +117,11 @@ export function createWorkerRequestClient(url, { idleExitMs = 0, ...workerOption
|
|
|
109
117
|
return request;
|
|
110
118
|
}
|
|
111
119
|
|
|
120
|
+
/** Worker side: send `event` to the client's `onEvent`, outside any request. */
|
|
121
|
+
export function postWorkerEvent(event) {
|
|
122
|
+
parentPort.postMessage({ event });
|
|
123
|
+
}
|
|
124
|
+
|
|
112
125
|
/** Worker side: answer every request with `handler(payload)` (sync or async). */
|
|
113
126
|
export function serveWorkerRequests(handler) {
|
|
114
127
|
parentPort.on('message', ({ id, payload }) => {
|
|
@@ -19,7 +19,6 @@ export const DEFAULT_WORKTREE_BRANCH_PREFIX = 'mixdog/';
|
|
|
19
19
|
|
|
20
20
|
export const WORKSPACE_TRANSITION_STATES = Object.freeze(['idle', 'provisioning', 'switching', 'removing', 'recovery']);
|
|
21
21
|
const WORKTREE_ENTRY_STATES = Object.freeze(['creating', 'ready', 'deleting', 'recovery']);
|
|
22
|
-
const BRANCH_OCCUPANCY_KINDS = Object.freeze(['current', 'session', 'external', 'free']);
|
|
23
22
|
|
|
24
23
|
/**
|
|
25
24
|
* Stable error codes. Clients branch on `error.code`, never on message text.
|
|
@@ -302,29 +301,6 @@ export function normalizeWorktreeOwner(input) {
|
|
|
302
301
|
* @typedef {{ branch: string, kind: BranchOccupancyKind, sessionId?: string, path?: string }} BranchOccupancy
|
|
303
302
|
*/
|
|
304
303
|
|
|
305
|
-
/**
|
|
306
|
-
* @param {unknown} input
|
|
307
|
-
* @returns {BranchOccupancy}
|
|
308
|
-
*/
|
|
309
|
-
export function normalizeBranchOccupancy(input) {
|
|
310
|
-
const value = record(input, 'occupancy');
|
|
311
|
-
const branch = text(value.branch, 'occupancy.branch');
|
|
312
|
-
const kind = oneOf(value.kind, BRANCH_OCCUPANCY_KINDS, 'occupancy.kind');
|
|
313
|
-
if (kind === 'free') {
|
|
314
|
-
if (value.sessionId != null || value.path != null) {
|
|
315
|
-
throw new TypeError('A free branch carries no sessionId or path.');
|
|
316
|
-
}
|
|
317
|
-
return { branch, kind };
|
|
318
|
-
}
|
|
319
|
-
if (kind !== 'session' && value.sessionId != null) {
|
|
320
|
-
throw new TypeError('Only a session occupancy carries a sessionId.');
|
|
321
|
-
}
|
|
322
|
-
const occupancy = { branch, kind };
|
|
323
|
-
if (kind === 'session') occupancy.sessionId = text(value.sessionId, 'occupancy.sessionId');
|
|
324
|
-
if (value.path != null) occupancy.path = text(value.path, 'occupancy.path');
|
|
325
|
-
return occupancy;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
304
|
/**
|
|
329
305
|
* The branch menu's rows (the desktop DesktopGitBranch shape) for the local
|
|
330
306
|
* branch names the manager lists: `current` marks the branch checked out in
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Temporary git repositories and data dirs for the worktree suites.
|
|
2
2
|
import { execFileSync } from 'node:child_process';
|
|
3
|
-
import { chmodSync, mkdtempSync, rmSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
3
|
+
import { chmodSync, cpSync, existsSync, mkdtempSync, rmSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
4
4
|
import { tmpdir } from 'node:os';
|
|
5
5
|
import { dirname, join } from 'node:path';
|
|
6
6
|
|
|
@@ -56,14 +56,29 @@ export function commitFile(cwd, rel, content, message = `edit ${rel}`) {
|
|
|
56
56
|
return git(cwd, 'rev-parse', 'HEAD');
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
// Built once per process and copied per repository: the five or six git
|
|
60
|
+
// spawns behind one fresh repository cost ~0.8 s on win32, and the worktree
|
|
61
|
+
// suites make dozens. A non-bare repository holds no absolute paths, so a copy
|
|
62
|
+
// is the same repository at its new location.
|
|
63
|
+
const templates = new Map();
|
|
64
|
+
|
|
65
|
+
function repoTemplate(commit) {
|
|
66
|
+
const existing = templates.get(commit);
|
|
67
|
+
if (existing && existsSync(existing)) return existing;
|
|
68
|
+
const dir = tempDir('mixdog-wt-template-');
|
|
62
69
|
git(dir, 'init', '-q', '-b', 'main');
|
|
63
70
|
git(dir, 'config', 'user.name', 'Mixdog Test');
|
|
64
71
|
git(dir, 'config', 'user.email', 'mixdog@example.com');
|
|
65
72
|
git(dir, 'config', 'core.autocrlf', 'false');
|
|
66
73
|
if (commit) commitFile(dir, 'README.md', 'hello\n', 'initial');
|
|
74
|
+
templates.set(commit, dir);
|
|
75
|
+
return dir;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** A repository on `main` with one commit. */
|
|
79
|
+
export function makeRepo({ commit = true } = {}) {
|
|
80
|
+
const dir = tempDir('mixdog-wt-repo-');
|
|
81
|
+
cpSync(repoTemplate(commit), dir, { recursive: true });
|
|
67
82
|
return dir;
|
|
68
83
|
}
|
|
69
84
|
|
|
@@ -57,10 +57,16 @@ export function deliverAutomationCompletion(sessionId, text, meta = {}) {
|
|
|
57
57
|
return true;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
// Ask options for a follow-up turn fed by agent results: the runtime reporting
|
|
61
|
+
// worker output, not the user — stored as a task notification and never a
|
|
62
|
+
// source of explicit skill selection.
|
|
63
|
+
export const AUTOMATION_RESULT_TURN_OPTS = Object.freeze({ promptSource: 'task-notification' });
|
|
64
|
+
|
|
60
65
|
/**
|
|
61
66
|
* Runs an automation conversation to its end: the first turn, then one more
|
|
62
67
|
* turn per batch of agent results while agents it started are still out.
|
|
63
|
-
*
|
|
68
|
+
* `nextTurn(text, askOpts)` receives AUTOMATION_RESULT_TURN_OPTS as the
|
|
69
|
+
* results' provenance. Resolves with the last turn's result.
|
|
64
70
|
*/
|
|
65
71
|
export async function runAutomationTurns(sessionId, firstTurn, nextTurn, { waitMs = AGENT_RESULT_WAIT_MS } = {}) {
|
|
66
72
|
const run = { pending: new Set(), ready: [], wake: null };
|
|
@@ -79,7 +85,7 @@ export async function runAutomationTurns(sessionId, firstTurn, nextTurn, { waitM
|
|
|
79
85
|
run.wake = null;
|
|
80
86
|
if (!arrived) break;
|
|
81
87
|
}
|
|
82
|
-
result = await nextTurn(run.ready.splice(0).join('\n\n'));
|
|
88
|
+
result = await nextTurn(run.ready.splice(0).join('\n\n'), { ...AUTOMATION_RESULT_TURN_OPTS });
|
|
83
89
|
}
|
|
84
90
|
return result;
|
|
85
91
|
} finally {
|
|
@@ -60,6 +60,10 @@ import { createGoalFacadeApi } from '../goal-facade-api.mjs';
|
|
|
60
60
|
import { createRuntimeReviewApi } from '../runtime-review-api.mjs';
|
|
61
61
|
import { createWorkspaceTransitions, refreshWorkspacePrompt } from '../workspace/transitions.mjs';
|
|
62
62
|
import { saveSession } from '../../runtime/agent/orchestrator/session/store.mjs';
|
|
63
|
+
import { modelToolSchemaAllowlist } from '../../runtime/agent/orchestrator/runtime-core/tool-profile.mjs';
|
|
64
|
+
import { sessionOptions } from '../session-create/session-options.mjs';
|
|
65
|
+
import { createConversationImportApi } from '../conversation-import/service.mjs';
|
|
66
|
+
import { importError } from '../conversation-import/discovery.mjs';
|
|
63
67
|
import { bootProfile } from '../boot-profile.mjs';
|
|
64
68
|
import { STANDALONE_DATA_DIR } from '../runtime-paths.mjs';
|
|
65
69
|
import {
|
|
@@ -88,12 +92,22 @@ export function wireApis(boot) {
|
|
|
88
92
|
});
|
|
89
93
|
boot.providerAuthApi = providerAuthApiFor(boot);
|
|
90
94
|
boot.mediaApi = createMediaApi();
|
|
95
|
+
boot.conversationImportApi = conversationImportApiFor(boot);
|
|
91
96
|
boot.sessionTitles = createSessionTitleController({
|
|
92
97
|
dataRoot: () => dataDirOf(boot.cfgMod),
|
|
93
98
|
promoteGeneratedTitle: (sessionId, title, stage) => boot.mgr.updateSessionGeneratedTitle(sessionId, title, stage),
|
|
94
99
|
});
|
|
95
100
|
boot.lifecycleApi = lifecycleApiFor(boot);
|
|
96
101
|
boot.resourceApi = resourceApiFor(boot);
|
|
102
|
+
// Plugin MCP servers are derived live; copies an earlier enable action wrote
|
|
103
|
+
// into mcpServers are adopted once (an injected headless config is left as is).
|
|
104
|
+
if (!boot.params.initialConfig || typeof boot.params.initialConfig !== 'object') {
|
|
105
|
+
try {
|
|
106
|
+
boot.resourceApi.migratePluginMcpCopies();
|
|
107
|
+
} catch (error) {
|
|
108
|
+
bootProfile('plugin-mcp:adopt-failed', { error: error?.message || String(error) });
|
|
109
|
+
}
|
|
110
|
+
}
|
|
97
111
|
boot.disposeGlobalExtensionSubscription = () => {
|
|
98
112
|
boot.disposeConfigSync?.();
|
|
99
113
|
boot.resourceApi.disposeGlobalExtensionSubscription?.();
|
|
@@ -282,6 +296,45 @@ function settingsApiFor(boot) {
|
|
|
282
296
|
});
|
|
283
297
|
}
|
|
284
298
|
|
|
299
|
+
// Conversation import: imported sessions are built with the Lead options a new
|
|
300
|
+
// session of this runtime would get (current route, tools, workflow, memory),
|
|
301
|
+
// minus its reservation, profile ownership and desktop placement.
|
|
302
|
+
function conversationImportApiFor(boot) {
|
|
303
|
+
const { rt, mgr } = boot;
|
|
304
|
+
return createConversationImportApi({
|
|
305
|
+
// The async catalog (the daemon's SQLite catalog worker, else JSON),
|
|
306
|
+
// loaded on first use so boot does not pull in the cold reader.
|
|
307
|
+
listSessionSummaries: async () => {
|
|
308
|
+
const reader = await import('../../runtime/agent/orchestrator/session/store-summary-reader.mjs');
|
|
309
|
+
return reader.listStoredSessionSummariesAsync();
|
|
310
|
+
},
|
|
311
|
+
createSession: (options) => mgr.createSession(options),
|
|
312
|
+
prepareLeadOptions: async () => {
|
|
313
|
+
await boot.awaitKeychainPrewarm();
|
|
314
|
+
const route = rt.route?.provider && rt.route?.model ? rt.route : resolveRoute(rt.config, {});
|
|
315
|
+
if (!route?.provider || !route?.model) throw importError('noModelRoute');
|
|
316
|
+
await boot.ensureProvidersReady(rt.config.providers || {});
|
|
317
|
+
const coreMemoryContext = await boot.loadCoreMemoryContext();
|
|
318
|
+
const leadView = Object.assign(Object.create(rt), {
|
|
319
|
+
route,
|
|
320
|
+
reservedSessionId: null,
|
|
321
|
+
sessionProfile: null,
|
|
322
|
+
desktopSession: null,
|
|
323
|
+
});
|
|
324
|
+
return sessionOptions(
|
|
325
|
+
{
|
|
326
|
+
rt: leadView,
|
|
327
|
+
cfgMod: boot.cfgMod,
|
|
328
|
+
activeWorkflowContext: workflowHelpers.activeWorkflowContext,
|
|
329
|
+
schemaAllowedTools: modelToolSchemaAllowlist(rt.toolProfile),
|
|
330
|
+
featureDisallowedTools: boot.featureDisallowedTools,
|
|
331
|
+
},
|
|
332
|
+
coreMemoryContext
|
|
333
|
+
);
|
|
334
|
+
},
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
|
|
285
338
|
function providerAuthApiFor(boot) {
|
|
286
339
|
const { rt, cfgMod, reg, ensureProvidersReady } = boot;
|
|
287
340
|
return createProviderAuthApi({
|
|
@@ -398,11 +451,19 @@ function resourceApiFor(boot) {
|
|
|
398
451
|
STANDALONE_DATA_DIR,
|
|
399
452
|
saveConfigAndAdopt: boot.saveConfigAndAdopt,
|
|
400
453
|
connectConfiguredMcp: boot.connectConfiguredMcp,
|
|
454
|
+
cancelMcpLogin: boot.cancelMcpLogin,
|
|
455
|
+
completeMcpLogin: boot.completeMcpLogin,
|
|
456
|
+
clearMcpServerOAuth: (cfg) => boot.mcpClient.clearMcpServerOAuth(cfg),
|
|
457
|
+
getMcpServerOAuthState: (cfg) => boot.mcpClient.getMcpServerOAuthState(cfg),
|
|
458
|
+
probeMcpServerAuth: (cfg) => boot.mcpClient.probeMcpServerAuth(cfg),
|
|
401
459
|
invalidatePreSessionToolSurface: boot.invalidatePreSessionToolSurface,
|
|
402
460
|
refreshEmptySessionToolPolicy: boot.refreshEmptySessionToolPolicy,
|
|
403
461
|
normalizeMcpServerInput: boot.normalizeMcpServerInput,
|
|
404
462
|
mcpStatus: boot.mcpStatus,
|
|
405
463
|
getMcpServerConfig: boot.getMcpServerConfig,
|
|
464
|
+
resolveMcpCatalog: boot.resolveMcpCatalog,
|
|
465
|
+
resolveConfiguredMcpCatalog: boot.resolveConfiguredMcpCatalog,
|
|
466
|
+
pluginMcpServer: boot.pluginMcpServer,
|
|
406
467
|
skillsStatus: boot.skillsStatus,
|
|
407
468
|
skillContent: boot.skillContent,
|
|
408
469
|
addGlobalSkill: boot.addGlobalSkill,
|
|
@@ -87,7 +87,8 @@ function initRuntimeState(rt, params) {
|
|
|
87
87
|
rt.activeTurnAbortControllers = new Set();
|
|
88
88
|
rt.firstTurnCompleted = false;
|
|
89
89
|
rt.codeGraphFirstTurnPrewarmDone = false;
|
|
90
|
-
|
|
90
|
+
// Last registry catalog-refresh promise this runtime attached handling to.
|
|
91
|
+
rt.startupProviderCatalogRefreshObserved = null;
|
|
91
92
|
// True while the boot-time provider-catalog refresh is in flight: warming a
|
|
92
93
|
// model cache it is about to invalidate only burns the load twice.
|
|
93
94
|
rt.startupProviderCatalogRefreshPending = false;
|
|
@@ -106,7 +107,9 @@ function activeTurnControls(rt) {
|
|
|
106
107
|
aborted = true;
|
|
107
108
|
try {
|
|
108
109
|
controller.abort(reason);
|
|
109
|
-
} catch {
|
|
110
|
+
} catch {
|
|
111
|
+
// Best-effort: one throwing abort listener must not stop the others.
|
|
112
|
+
}
|
|
110
113
|
}
|
|
111
114
|
return aborted;
|
|
112
115
|
},
|
|
@@ -7,11 +7,7 @@ import { createStandaloneHookBus } from '../services/hook-bus.mjs';
|
|
|
7
7
|
import { updateCurrentCwdOverride, writeLastSessionCwd } from '../../runtime/shared/user-cwd.mjs';
|
|
8
8
|
import { listRegisteredPlugins, pluginAdminStatus } from '../services/plugin-admin.mjs';
|
|
9
9
|
import { clean } from '../../runtime/agent/orchestrator/runtime-core/session-text.mjs';
|
|
10
|
-
import {
|
|
11
|
-
countSkillFiles,
|
|
12
|
-
pluginManifest,
|
|
13
|
-
pluginMcpServerName,
|
|
14
|
-
} from '../../runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs';
|
|
10
|
+
import { countSkillFiles, pluginManifest } from '../../runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs';
|
|
15
11
|
import { bootProfile } from '../boot-profile.mjs';
|
|
16
12
|
import { createMcpGlue } from '../mcp-glue.mjs';
|
|
17
13
|
import { createSelfUpdateController } from '../self-update.mjs';
|
|
@@ -41,23 +37,39 @@ function wireMcp(boot) {
|
|
|
41
37
|
mcpConnectGeneration: 0,
|
|
42
38
|
mcpConnectInFlight: null,
|
|
43
39
|
};
|
|
44
|
-
const {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
40
|
+
const {
|
|
41
|
+
mcpStatus,
|
|
42
|
+
resolveMcpCatalog,
|
|
43
|
+
resolveConfiguredMcpCatalog,
|
|
44
|
+
pluginMcpServer,
|
|
45
|
+
pluginMcpSummary,
|
|
46
|
+
getMcpServerConfig,
|
|
47
|
+
connectConfiguredMcp,
|
|
48
|
+
awaitInitialMcpConnect,
|
|
49
|
+
cancelMcpLogin,
|
|
50
|
+
completeMcpLogin,
|
|
51
|
+
normalizeMcpServerInput,
|
|
52
|
+
} = createMcpGlue({
|
|
53
|
+
mcpClient,
|
|
54
|
+
getConfig: () => rt.config,
|
|
55
|
+
getCurrentCwd: () => rt.currentCwd,
|
|
56
|
+
getMcpScopeId: () => rt.mcpScopeId,
|
|
57
|
+
// Plugin-declared servers are derived from the registry on every resolve.
|
|
58
|
+
getPluginDataDir: () => dataDirOf(boot.cfgMod),
|
|
59
|
+
listPlugins: () => listRegisteredPlugins({ dataDir: boot.cfgMod.getPluginData() }),
|
|
60
|
+
state: mcpState,
|
|
61
|
+
});
|
|
56
62
|
Object.assign(boot, {
|
|
57
63
|
mcpStatus,
|
|
64
|
+
resolveMcpCatalog,
|
|
65
|
+
resolveConfiguredMcpCatalog,
|
|
66
|
+
pluginMcpServer,
|
|
67
|
+
pluginMcpSummary,
|
|
58
68
|
getMcpServerConfig,
|
|
59
69
|
connectConfiguredMcp,
|
|
60
70
|
awaitInitialMcpConnect,
|
|
71
|
+
cancelMcpLogin,
|
|
72
|
+
completeMcpLogin,
|
|
61
73
|
normalizeMcpServerInput,
|
|
62
74
|
});
|
|
63
75
|
}
|
|
@@ -250,7 +262,12 @@ function wireCwdPlugins(boot) {
|
|
|
250
262
|
listRegisteredPlugins,
|
|
251
263
|
pluginAdminStatus,
|
|
252
264
|
pluginManifest,
|
|
253
|
-
|
|
265
|
+
pluginMcpSummary: boot.pluginMcpSummary,
|
|
266
|
+
// Plugin MCP servers without a declared cwd follow this runtime's cwd:
|
|
267
|
+
// reconnect just those (and refresh advertised roots) in place.
|
|
268
|
+
onCwdChanged: () => {
|
|
269
|
+
void boot.connectConfiguredMcp({ reconcile: true }).catch(() => {});
|
|
270
|
+
},
|
|
254
271
|
countSkillFiles,
|
|
255
272
|
writeLastSessionCwd,
|
|
256
273
|
updateCurrentCwdOverride,
|