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
|
@@ -111,13 +111,25 @@ import {
|
|
|
111
111
|
providerAccountLimit,
|
|
112
112
|
providerAccountBlockedUntil,
|
|
113
113
|
ACCOUNT_PROVIDERS,
|
|
114
|
+
MAX_ACCOUNTS,
|
|
115
|
+
customProviderKeyIds,
|
|
116
|
+
setCustomProviderKeyIds,
|
|
114
117
|
} from '../../runtime/shared/provider-accounts.mjs';
|
|
118
|
+
import { customProviderKeyAccount } from '../../runtime/shared/custom-provider-keys.mjs';
|
|
115
119
|
import { currentProviderAccountId, withProviderAccount } from '../../runtime/shared/provider-auth-binding.mjs';
|
|
116
120
|
import {
|
|
117
121
|
CUSTOM_API_KEY_ENV_RE,
|
|
118
122
|
effectiveCustomModelRows,
|
|
119
123
|
normalizeCustomProviderConfig as normalizeStoredCustomConfig,
|
|
120
124
|
} from '../../runtime/agent/orchestrator/providers/custom-provider-config.mjs';
|
|
125
|
+
import {
|
|
126
|
+
VERTEX_ADC_MODE,
|
|
127
|
+
VERTEX_API_KEY_MODE,
|
|
128
|
+
describeVertexAdc,
|
|
129
|
+
parseVertexServiceAccount,
|
|
130
|
+
probeVertexMetadata,
|
|
131
|
+
} from '../../runtime/agent/orchestrator/providers/vertex-ai-auth.mjs';
|
|
132
|
+
import { vertexEnvLocation } from '../../runtime/agent/orchestrator/providers/vertex-ai-models.mjs';
|
|
121
133
|
|
|
122
134
|
const API_PROVIDERS = Object.freeze([
|
|
123
135
|
Object.freeze({ id: 'openrouter', name: 'OpenRouter', env: 'OPENROUTER_API_KEY', url: 'https://openrouter.ai/keys' }),
|
|
@@ -134,6 +146,7 @@ const API_PROVIDERS = Object.freeze([
|
|
|
134
146
|
url: 'https://console.anthropic.com/settings/keys',
|
|
135
147
|
}),
|
|
136
148
|
Object.freeze({ id: 'gemini', name: 'Gemini API', env: 'GEMINI_API_KEY', url: 'https://aistudio.google.com/apikey' }),
|
|
149
|
+
Object.freeze({ id: 'vertex-ai', name: 'Vertex AI', env: null, url: null }),
|
|
137
150
|
Object.freeze({
|
|
138
151
|
id: 'deepseek',
|
|
139
152
|
name: 'DeepSeek API',
|
|
@@ -374,6 +387,23 @@ function storedSecretDetail(account) {
|
|
|
374
387
|
return isFallbackSecret(account) ? 'stored in private file' : 'stored in keychain';
|
|
375
388
|
}
|
|
376
389
|
|
|
390
|
+
// The Vertex AI gcloud-login row's detail: who is signed in and where, or what to fix.
|
|
391
|
+
function vertexAdcDetail(adc, location) {
|
|
392
|
+
if (!adc) return `gcloud login · ${location}`;
|
|
393
|
+
if (adc.state !== 'ready') return adc.message;
|
|
394
|
+
const account = adc.account || (adc.type === 'metadata' ? 'metadata server' : 'gcloud user login');
|
|
395
|
+
return [account, adc.projectId || 'no project', location].join(' · ');
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// The Vertex AI location a row shows and where it comes from: the saved one
|
|
399
|
+
// ('config'), else what the runtime would use unset ('environment' or
|
|
400
|
+
// 'default'), which the connect form offers as a hint without saving it.
|
|
401
|
+
function vertexRowLocation(configured) {
|
|
402
|
+
if (configured.location) return { location: String(configured.location), locationSource: 'config' };
|
|
403
|
+
const env = vertexEnvLocation();
|
|
404
|
+
return env ? { location: env, locationSource: 'environment' } : { location: 'global', locationSource: 'default' };
|
|
405
|
+
}
|
|
406
|
+
|
|
377
407
|
// `keychainIssue`: the setup response's one keyring check (never asked per row).
|
|
378
408
|
function apiProviderSetup(p, providers, checkSecrets, keychainIssue) {
|
|
379
409
|
const configured = providers[p.id] || {};
|
|
@@ -402,6 +432,74 @@ function apiProviderSetup(p, providers, checkSecrets, keychainIssue) {
|
|
|
402
432
|
}
|
|
403
433
|
const rowIssue = authenticated ? null : keychainIssue;
|
|
404
434
|
if (rowIssue) detail = rowIssue.message;
|
|
435
|
+
if (p.id === 'vertex-ai' && configured.authMode === VERTEX_ADC_MODE) {
|
|
436
|
+
// gcloud login: nothing is stored; connected while enabled and the login is readable.
|
|
437
|
+
const { location, locationSource } = vertexRowLocation(configured);
|
|
438
|
+
const adc = checkSecrets ? describeVertexAdc({ projectId: configured.projectId }) : null;
|
|
439
|
+
// Without a login file a metadata server may stand in: probed once, in the
|
|
440
|
+
// background, for the next refresh to report.
|
|
441
|
+
if (adc?.state === 'missing') void probeVertexMetadata();
|
|
442
|
+
const ready = configuredEnabled && (!adc || adc.state === 'ready');
|
|
443
|
+
let adcStatus = configuredEnabled ? 'Not connected' : 'Off';
|
|
444
|
+
if (ready) adcStatus = 'Set';
|
|
445
|
+
return {
|
|
446
|
+
...p,
|
|
447
|
+
group: 'api',
|
|
448
|
+
type: 'api-key',
|
|
449
|
+
authKind: 'adc',
|
|
450
|
+
authMode: VERTEX_ADC_MODE,
|
|
451
|
+
enabled: configuredEnabled,
|
|
452
|
+
authenticated: ready,
|
|
453
|
+
stored: false,
|
|
454
|
+
env: false,
|
|
455
|
+
envName: null,
|
|
456
|
+
status: adcStatus,
|
|
457
|
+
detail: vertexAdcDetail(adc, location),
|
|
458
|
+
location,
|
|
459
|
+
locationSource,
|
|
460
|
+
projectId: adc?.projectId || String(configured.projectId || '') || null,
|
|
461
|
+
...(adc ? { adc } : {}),
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
if (p.id === 'vertex-ai') {
|
|
465
|
+
const { location, locationSource } = vertexRowLocation(configured);
|
|
466
|
+
// An express-mode API key, or the service-account key.
|
|
467
|
+
const express = configured.authMode === VERTEX_API_KEY_MODE;
|
|
468
|
+
// The connect form offers the gcloud login too; its status line reads this.
|
|
469
|
+
const adc = checkSecrets && !authenticated ? describeVertexAdc({ projectId: configured.projectId }) : null;
|
|
470
|
+
let projectId = String(configured.projectId || '');
|
|
471
|
+
if (!projectId && authenticated && checkSecrets && !express) {
|
|
472
|
+
try {
|
|
473
|
+
projectId = parseVertexServiceAccount(getAgentApiKey(p.id)).projectId;
|
|
474
|
+
} catch {
|
|
475
|
+
// An unreadable key leaves the project id empty; the status line then shows the location only.
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
if (!rowIssue) {
|
|
479
|
+
if (express) detail = `API key (express mode) · ${location}`;
|
|
480
|
+
else detail = projectId ? `${projectId} · ${location}` : `Location: ${location}`;
|
|
481
|
+
}
|
|
482
|
+
return {
|
|
483
|
+
...p,
|
|
484
|
+
...(rowIssue ? { keychainIssue: rowIssue } : {}),
|
|
485
|
+
group: 'api',
|
|
486
|
+
type: 'api-key',
|
|
487
|
+
authKind: express ? 'api-key' : 'service-account',
|
|
488
|
+
authMode: express ? VERTEX_API_KEY_MODE : 'service-account',
|
|
489
|
+
...(adc ? { adc } : {}),
|
|
490
|
+
enabled: configuredEnabled || authenticated,
|
|
491
|
+
authenticated,
|
|
492
|
+
stored,
|
|
493
|
+
env: false,
|
|
494
|
+
envName: null,
|
|
495
|
+
status,
|
|
496
|
+
detail,
|
|
497
|
+
location,
|
|
498
|
+
locationSource,
|
|
499
|
+
projectId: projectId || null,
|
|
500
|
+
...(credentialSource ? { credentialSource } : {}),
|
|
501
|
+
};
|
|
502
|
+
}
|
|
405
503
|
return {
|
|
406
504
|
...p,
|
|
407
505
|
...(rowIssue ? { keychainIssue: rowIssue } : {}),
|
|
@@ -561,8 +659,12 @@ function customProviderRow(id, entry, checkSecrets = true) {
|
|
|
561
659
|
row.auth = keyless ? 'none' : 'key';
|
|
562
660
|
row.discovery = structuredClone(config?.discovery ?? entry.discovery ?? { newModelsHidden: false });
|
|
563
661
|
row.modelOverrides = structuredClone(config?.modelOverrides ?? entry.modelOverrides ?? {});
|
|
662
|
+
if (config?.headers) row.headers = { ...config.headers };
|
|
564
663
|
if (config?.wires) row.wires = [...config.wires];
|
|
565
664
|
if (config?.modelWires) row.modelWires = { ...config.modelWires };
|
|
665
|
+
// Additional API keys by id only; their values never leave the keychain.
|
|
666
|
+
const extraKeyIds = keyless ? [] : customProviderKeyIds(id);
|
|
667
|
+
if (extraKeyIds.length) row.extraApiKeys = extraKeyIds.map((keyId) => ({ id: keyId }));
|
|
566
668
|
// A stored config that does not normalize cannot run (the registry skips
|
|
567
669
|
// it): say so explicitly instead of listing it as connected.
|
|
568
670
|
// Every readiness flag consumers read says "not ready" (`stored` stays the
|
|
@@ -660,6 +762,20 @@ async function modelProxyProviderSetup(options) {
|
|
|
660
762
|
|
|
661
763
|
function apiProviderStatusRow(p, config) {
|
|
662
764
|
const configured = config.providers?.[p.id] || {};
|
|
765
|
+
if (p.id === 'vertex-ai' && configured.authMode === VERTEX_ADC_MODE) {
|
|
766
|
+
const adc = describeVertexAdc({ projectId: configured.projectId });
|
|
767
|
+
return {
|
|
768
|
+
id: p.id,
|
|
769
|
+
type: 'api-key',
|
|
770
|
+
enabled: configured.enabled === true,
|
|
771
|
+
authenticated: configured.enabled === true && adc.state === 'ready',
|
|
772
|
+
stored: false,
|
|
773
|
+
env: false,
|
|
774
|
+
envName: null,
|
|
775
|
+
label: p.name,
|
|
776
|
+
detail: vertexAdcDetail(adc, vertexRowLocation(configured).location),
|
|
777
|
+
};
|
|
778
|
+
}
|
|
663
779
|
const envName = AGENT_PROVIDER_ENV[p.id] || p.env;
|
|
664
780
|
const env = Boolean(envName && process.env[envName]);
|
|
665
781
|
const stored = hasStoredSecret(SECRET_ACCOUNTS.agentApiKey(p.id));
|
|
@@ -720,6 +836,7 @@ export function renderProviderStatus(config = {}) {
|
|
|
720
836
|
if (row.type === 'oauth') source = row.detail || 'oauth';
|
|
721
837
|
else if (row.env) source = `env:${row.envName}`;
|
|
722
838
|
else if (row.stored) source = 'keychain';
|
|
839
|
+
else if (row.detail) source = row.detail;
|
|
723
840
|
const enabled = row.enabled ? 'enabled' : 'disabled';
|
|
724
841
|
return `${row.id.padEnd(width)} ${row.type.padEnd(7)} ${auth.padEnd(8)} ${enabled.padEnd(8)} ${source}`;
|
|
725
842
|
})
|
|
@@ -984,15 +1101,68 @@ export async function updateProviderAccounts(provider, change) {
|
|
|
984
1101
|
return listProviderAccounts(provider);
|
|
985
1102
|
}
|
|
986
1103
|
|
|
987
|
-
export async function saveProviderApiKey(cfgMod, provider, secret) {
|
|
1104
|
+
export async function saveProviderApiKey(cfgMod, provider, secret, options) {
|
|
988
1105
|
requireLocalProviderManagement();
|
|
989
1106
|
const id = String(provider || '').trim();
|
|
990
1107
|
if (!API_PROVIDER_IDS.has(id)) throw new Error(`unknown API-key provider "${id}"`);
|
|
991
1108
|
const value = String(secret || '').trim();
|
|
992
|
-
|
|
1109
|
+
const adc = id === 'vertex-ai' && options?.authMode === VERTEX_ADC_MODE;
|
|
1110
|
+
const express = id === 'vertex-ai' && options?.authMode === VERTEX_API_KEY_MODE;
|
|
1111
|
+
if (!value && !adc) throw new Error(`API key is required for ${id}`);
|
|
1112
|
+
let patch = { enabled: true };
|
|
1113
|
+
if (id === 'vertex-ai') {
|
|
1114
|
+
if (adc && value) throw new Error('Vertex AI gcloud login takes no key');
|
|
1115
|
+
if (express && /[\s{]/.test(value)) throw new Error('Vertex AI express mode takes an API key, not a JSON key file');
|
|
1116
|
+
if (!adc && !express) parseVertexServiceAccount(value);
|
|
1117
|
+
// Only a location the user chose is saved: an empty one is unset (the
|
|
1118
|
+
// runtime then follows the environment's region, then global). None given
|
|
1119
|
+
// at all (the terminal setup) keeps a saved one; express mode never keeps
|
|
1120
|
+
// one, as it serves global only.
|
|
1121
|
+
const location = String(options?.location ?? '')
|
|
1122
|
+
.trim()
|
|
1123
|
+
.toLowerCase();
|
|
1124
|
+
const projectId = String(options?.projectId || '').trim();
|
|
1125
|
+
if (location && !/^[a-z0-9-]{1,63}$/.test(location)) throw new Error('Vertex AI location is invalid');
|
|
1126
|
+
if (express && location && location !== 'global') {
|
|
1127
|
+
throw new Error('Vertex AI express mode serves only the global location');
|
|
1128
|
+
}
|
|
1129
|
+
const locationPatch =
|
|
1130
|
+
location || express || options?.location !== undefined ? { location: location || undefined } : {};
|
|
1131
|
+
if (projectId && (!/^[a-zA-Z0-9._:-]{1,128}$/.test(projectId) || projectId.includes('/'))) {
|
|
1132
|
+
throw new Error('Vertex AI project ID override is invalid');
|
|
1133
|
+
}
|
|
1134
|
+
if (adc) {
|
|
1135
|
+
// gcloud login: nothing secret is stored, and the login must already be usable.
|
|
1136
|
+
let login = describeVertexAdc({ projectId });
|
|
1137
|
+
// No login file: a GCE / Cloud Run / GKE host's metadata server.
|
|
1138
|
+
if (login.state === 'missing' && (await probeVertexMetadata())) login = describeVertexAdc({ projectId });
|
|
1139
|
+
if (login.state !== 'ready') throw new Error(login.message);
|
|
1140
|
+
if (!login.projectId) {
|
|
1141
|
+
throw new Error(
|
|
1142
|
+
'No Google Cloud project found for the gcloud login. Enter a project ID override, or run `gcloud config set project PROJECT_ID`.'
|
|
1143
|
+
);
|
|
1144
|
+
}
|
|
1145
|
+
// The login replaces a key saved earlier rather than sitting beside it.
|
|
1146
|
+
const account = SECRET_ACCOUNTS.agentApiKey(id);
|
|
1147
|
+
if (hasStoredSecret(account)) await deleteSecretAsync(account);
|
|
1148
|
+
updateConfigProvider(cfgMod, id, {
|
|
1149
|
+
enabled: true,
|
|
1150
|
+
...locationPatch,
|
|
1151
|
+
projectId: projectId || undefined,
|
|
1152
|
+
authMode: VERTEX_ADC_MODE,
|
|
1153
|
+
});
|
|
1154
|
+
return { provider: id, type: 'adc', authenticated: true };
|
|
1155
|
+
}
|
|
1156
|
+
patch = {
|
|
1157
|
+
enabled: true,
|
|
1158
|
+
...locationPatch,
|
|
1159
|
+
projectId: projectId || undefined,
|
|
1160
|
+
authMode: express ? VERTEX_API_KEY_MODE : 'service-account',
|
|
1161
|
+
};
|
|
1162
|
+
}
|
|
993
1163
|
await saveSecretAsync(SECRET_ACCOUNTS.agentApiKey(id), value);
|
|
994
|
-
updateConfigProvider(cfgMod, id,
|
|
995
|
-
return { provider: id, type: 'api-key', authenticated: true };
|
|
1164
|
+
updateConfigProvider(cfgMod, id, patch);
|
|
1165
|
+
return { provider: id, type: id === 'vertex-ai' && !express ? 'service-account' : 'api-key', authenticated: true };
|
|
996
1166
|
}
|
|
997
1167
|
|
|
998
1168
|
function sanitizeCustomError(error, secrets = []) {
|
|
@@ -1049,6 +1219,63 @@ function validateCustomTransportFields(input) {
|
|
|
1049
1219
|
if (typeof input.apiKey === 'string' && input.apiKey !== '')
|
|
1050
1220
|
throw new TypeError('custom provider apiKey and apiKeyEnv are mutually exclusive');
|
|
1051
1221
|
}
|
|
1222
|
+
if (input.extraApiKeys !== undefined) validateExtraApiKeys(input.extraApiKeys);
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
const CUSTOM_KEY_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
1226
|
+
|
|
1227
|
+
// Additional API keys in use order, beside the primary key (MAX_ACCOUNTS in
|
|
1228
|
+
// all): `{ id }` keeps a saved key, `{ apiKey }` adds one and `{ id, apiKey }`
|
|
1229
|
+
// replaces a saved key's value; a blank `apiKey` keeps the saved key.
|
|
1230
|
+
function validateExtraApiKeys(rows) {
|
|
1231
|
+
const invalid = () => new TypeError('custom provider extraApiKeys are invalid');
|
|
1232
|
+
if (!Array.isArray(rows) || rows.length >= MAX_ACCOUNTS) throw invalid();
|
|
1233
|
+
const ids = new Set();
|
|
1234
|
+
for (const row of rows) {
|
|
1235
|
+
if (!row || typeof row !== 'object' || Array.isArray(row)) throw invalid();
|
|
1236
|
+
if (Object.keys(row).some((key) => key !== 'id' && key !== 'apiKey')) throw invalid();
|
|
1237
|
+
if (row.id !== undefined && (typeof row.id !== 'string' || !CUSTOM_KEY_ID_RE.test(row.id) || ids.has(row.id)))
|
|
1238
|
+
throw new TypeError('custom provider extraApiKeys id is invalid');
|
|
1239
|
+
if (row.apiKey !== undefined && (typeof row.apiKey !== 'string' || row.apiKey.length > CUSTOM_API_KEY_MAX))
|
|
1240
|
+
throw new TypeError('custom provider extraApiKeys apiKey is invalid');
|
|
1241
|
+
if (row.id === undefined && !row.apiKey?.trim()) throw new TypeError('custom provider additional API key is empty');
|
|
1242
|
+
if (row.id !== undefined) ids.add(row.id);
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
// The additional-key change a save makes over the `saved` key ids: `rows`
|
|
1247
|
+
// absent keeps them; a typed key is stored under a new id, so a replaced key
|
|
1248
|
+
// starts without the old one's cooldown. A keyless provider keeps none.
|
|
1249
|
+
function extraKeyPlan(saved, rows, keyless) {
|
|
1250
|
+
if (keyless) return { saved, ids: [], added: [], removed: saved };
|
|
1251
|
+
if (rows === undefined) return { saved, ids: saved, added: [], removed: [] };
|
|
1252
|
+
const ids = [];
|
|
1253
|
+
const added = [];
|
|
1254
|
+
for (const row of rows) {
|
|
1255
|
+
if (row.id !== undefined && !saved.includes(row.id)) throw new Error('An additional API key is no longer saved.');
|
|
1256
|
+
const typed = typeof row.apiKey === 'string' ? row.apiKey.trim() : '';
|
|
1257
|
+
if (!typed) {
|
|
1258
|
+
ids.push(row.id);
|
|
1259
|
+
continue;
|
|
1260
|
+
}
|
|
1261
|
+
const keyId = randomUUID();
|
|
1262
|
+
ids.push(keyId);
|
|
1263
|
+
added.push({ keyId, key: typed });
|
|
1264
|
+
}
|
|
1265
|
+
return { saved, ids, added, removed: saved.filter((keyId) => !ids.includes(keyId)) };
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
const extraKeysChanged = (plan) => plan.ids.join() !== plan.saved.join();
|
|
1269
|
+
|
|
1270
|
+
async function applyExtraKeys(id, plan) {
|
|
1271
|
+
for (const { keyId, key } of plan.added) await saveSecretAsync(customProviderKeyAccount(id, keyId), key);
|
|
1272
|
+
if (extraKeysChanged(plan)) await setCustomProviderKeyIds(id, plan.ids);
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
// A failed save puts the saved roster back and drops the keys it added.
|
|
1276
|
+
async function revertExtraKeys(id, plan) {
|
|
1277
|
+
if (extraKeysChanged(plan)) await setCustomProviderKeyIds(id, plan.saved);
|
|
1278
|
+
for (const { keyId } of plan.added) await deleteSecretAsync(customProviderKeyAccount(id, keyId));
|
|
1052
1279
|
}
|
|
1053
1280
|
|
|
1054
1281
|
/** Whether the named environment variable is set to a non-empty value. */
|
|
@@ -1064,7 +1291,7 @@ function inputObject(input) {
|
|
|
1064
1291
|
}
|
|
1065
1292
|
|
|
1066
1293
|
// An edit that omits a stored setting keeps it: `auth` for every input shape,
|
|
1067
|
-
// and `discovery` / `modelOverrides` for a v2 input (a legacy `models` input
|
|
1294
|
+
// and `discovery` / `modelOverrides` / `headers` for a v2 input (a legacy `models` input
|
|
1068
1295
|
// states the whole manual model list itself).
|
|
1069
1296
|
function withStoredSettings(input, entry) {
|
|
1070
1297
|
const stored = storedCustomConfig(entry);
|
|
@@ -1079,6 +1306,8 @@ function withStoredSettings(input, entry) {
|
|
|
1079
1306
|
if (out.schemaVersion === stored.schemaVersion) {
|
|
1080
1307
|
if (out.discovery === undefined) out.discovery = stored.discovery;
|
|
1081
1308
|
if (out.modelOverrides === undefined) out.modelOverrides = stored.modelOverrides;
|
|
1309
|
+
// `headers: {}` clears them; an omitted field keeps the stored ones.
|
|
1310
|
+
if (out.headers === undefined && stored.headers) out.headers = stored.headers;
|
|
1082
1311
|
// Served wires and per-model wires have no setup field yet: an edit on
|
|
1083
1312
|
// the same protocol keeps them (another protocol serves other wires).
|
|
1084
1313
|
if ((out.protocol ?? stored.protocol) === stored.protocol) {
|
|
@@ -1095,7 +1324,9 @@ function withStoredSettings(input, entry) {
|
|
|
1095
1324
|
// the config. Synchronous, so a caller can merge and commit one snapshot.
|
|
1096
1325
|
function customInputAt(snapshot, input, normalizeCustomProviderConfig, options) {
|
|
1097
1326
|
const id = input.id === undefined ? null : input.id;
|
|
1098
|
-
|
|
1327
|
+
// Additional keys are secrets, applied by the save itself (extraKeyPlan).
|
|
1328
|
+
const { extraApiKeys: _extraKeys, ...settings } = input;
|
|
1329
|
+
const merged = id ? withStoredSettings(settings, existingCustomEntry(snapshot, id)) : settings;
|
|
1099
1330
|
const config = normalizeCustomProviderConfig(merged, options);
|
|
1100
1331
|
const typed = typeof merged.apiKey === 'string' ? merged.apiKey.trim() : '';
|
|
1101
1332
|
const keyless = config.auth === 'none';
|
|
@@ -1147,9 +1378,16 @@ export async function saveCustomProvider(cfgMod, rawInput) {
|
|
|
1147
1378
|
const commit = async () => {
|
|
1148
1379
|
const account = SECRET_ACCOUNTS.agentApiKey(id);
|
|
1149
1380
|
const previousKey = typed && existingId ? getAgentApiKey(id) : null;
|
|
1381
|
+
// Auth as of this save's turn in the key queue: a no-auth save queued
|
|
1382
|
+
// earlier may have landed since the input was resolved.
|
|
1383
|
+
const keyless = existingId
|
|
1384
|
+
? customInputAt(cfgMod.loadConfig(), rawInput, normalizeCustomProviderConfig, { requireModels: false }).keyless
|
|
1385
|
+
: resolved.keyless;
|
|
1386
|
+
const extra = extraKeyPlan(existingId ? customProviderKeyIds(id) : [], rawInput.extraApiKeys, keyless);
|
|
1150
1387
|
if (typed) await saveSecretAsync(account, typed);
|
|
1151
1388
|
let entry;
|
|
1152
1389
|
try {
|
|
1390
|
+
await applyExtraKeys(id, extra);
|
|
1153
1391
|
// Synchronous from here: omitted settings come from the config this
|
|
1154
1392
|
// save commits over, so an edit that landed during the awaits above (a
|
|
1155
1393
|
// model's visibility, a peer save, a removal) is never reverted.
|
|
@@ -1162,15 +1400,29 @@ export async function saveCustomProvider(cfgMod, rawInput) {
|
|
|
1162
1400
|
{ baseConfig: current }
|
|
1163
1401
|
);
|
|
1164
1402
|
} catch (error) {
|
|
1403
|
+
await revertExtraKeys(id, extra);
|
|
1165
1404
|
if (typed) {
|
|
1166
1405
|
if (previousKey) await saveSecretAsync(account, previousKey);
|
|
1167
1406
|
else await deleteSecretAsync(account);
|
|
1168
1407
|
}
|
|
1169
1408
|
throw error;
|
|
1170
1409
|
}
|
|
1410
|
+
// A removed key is dropped once the save holds; a keychain refusal then
|
|
1411
|
+
// leaves an unused secret behind (reported), never a failed save that did commit.
|
|
1412
|
+
for (const keyId of extra.removed) {
|
|
1413
|
+
await deleteSecretAsync(customProviderKeyAccount(id, keyId)).catch((error) => {
|
|
1414
|
+
process.stderr.write(
|
|
1415
|
+
`[provider-admin] could not delete additional API key ${keyId} of ${id}: ${error?.message || error}\n`
|
|
1416
|
+
);
|
|
1417
|
+
});
|
|
1418
|
+
}
|
|
1171
1419
|
return customProviderRow(id, entry);
|
|
1172
1420
|
};
|
|
1173
|
-
|
|
1421
|
+
// Every save that may change the keys runs in the provider's key queue: a
|
|
1422
|
+
// typed key, an additional-key list, or a no-auth save (which drops them),
|
|
1423
|
+
// decided from the input alone, never from a roster read outside the queue.
|
|
1424
|
+
const keysChange = typed || rawInput.extraApiKeys !== undefined || (existingId && resolved.keyless);
|
|
1425
|
+
return keysChange ? serializeCustomKeySave(id, commit) : commit();
|
|
1174
1426
|
}
|
|
1175
1427
|
|
|
1176
1428
|
// Replaces only the stored key of an existing custom provider. The provider's
|
|
@@ -1399,6 +1651,9 @@ export async function removeCustomProvider(cfgMod, rawId) {
|
|
|
1399
1651
|
// provider registered so the removal can be retried. A missing secret
|
|
1400
1652
|
// (keyless provider) is not an error.
|
|
1401
1653
|
await deleteSecretAsync(SECRET_ACCOUNTS.agentApiKey(id));
|
|
1654
|
+
const extraKeyIds = customProviderKeyIds(id);
|
|
1655
|
+
for (const keyId of extraKeyIds) await deleteSecretAsync(customProviderKeyAccount(id, keyId));
|
|
1656
|
+
if (extraKeyIds.length) await setCustomProviderKeyIds(id, []);
|
|
1402
1657
|
const current = cfgMod.loadConfig();
|
|
1403
1658
|
const { [id]: _removed, ...providers } = current.providers || {};
|
|
1404
1659
|
cfgMod.saveConfig(withoutProviderReferences({ ...current, providers }, id), { baseConfig: current });
|
|
@@ -1425,13 +1680,29 @@ export async function testCustomProvider(cfgMod, rawInput) {
|
|
|
1425
1680
|
error: { kind: 'empty', message: 'No models were found for this provider' },
|
|
1426
1681
|
};
|
|
1427
1682
|
const { createCustomProvider } = await loadCustomProviderModule();
|
|
1428
|
-
const
|
|
1429
|
-
|
|
1683
|
+
const primary = await createCustomProvider(id || 'custom-test', { ...config, apiKey });
|
|
1684
|
+
// A provider with additional keys tests through the same key pool as a
|
|
1685
|
+
// real request: an explicit quota refusal moves on to the next key.
|
|
1686
|
+
const keyIds = id && !config.apiKeyEnv && config.auth !== 'none' ? customProviderKeyIds(id) : [];
|
|
1687
|
+
let provider = primary;
|
|
1688
|
+
let routingKey;
|
|
1689
|
+
if (keyIds.length) {
|
|
1690
|
+
const [pool, keys] = await Promise.all([
|
|
1691
|
+
import('../../runtime/agent/orchestrator/providers/account-pool.mjs'),
|
|
1692
|
+
import('../../runtime/agent/orchestrator/providers/custom-provider-keys.mjs'),
|
|
1693
|
+
]);
|
|
1694
|
+
routingKey = pool.ROUTING_METADATA_KEY;
|
|
1695
|
+
provider = pool.createCustomKeyPoolProvider(id, primary, (keyId) => keys.customKeyEngine(primary, id, keyId));
|
|
1696
|
+
}
|
|
1697
|
+
const answer = await withTimeout(
|
|
1430
1698
|
(signal) => provider.send([{ role: 'user', content: 'Reply with OK.' }], model, [], { signal, maxTokens: 16 }),
|
|
1431
1699
|
CUSTOM_TEST_TIMEOUT_MS,
|
|
1432
1700
|
'connection test'
|
|
1433
1701
|
);
|
|
1434
|
-
|
|
1702
|
+
// Key numbers count the primary key as 1.
|
|
1703
|
+
const served = routingKey ? answer?.providerMetadata?.[routingKey]?.accountId : undefined;
|
|
1704
|
+
const index = keyIds.indexOf(served);
|
|
1705
|
+
return index < 0 ? { ok: true } : { ok: true, key: { id: served, number: index + 2 } };
|
|
1435
1706
|
} catch (error) {
|
|
1436
1707
|
throw sanitizeCustomError(error, customSecrets(apiKey, config));
|
|
1437
1708
|
}
|
|
@@ -127,6 +127,13 @@ export function retireSeededPackCopies({ rootDir, dataDir, backup = makeBackup(d
|
|
|
127
127
|
if (![bundled, ...(history.outputStyles[name] || [])].includes(fileHash(copy))) continue;
|
|
128
128
|
if (backup.move(copy)) retired.push(`output-styles/${name}`);
|
|
129
129
|
}
|
|
130
|
+
for (const name of childNames(join(dataDir, 'orchestration'), 'md')) {
|
|
131
|
+
const bundled = fileHash(join(rootDir, 'orchestration', name));
|
|
132
|
+
if (!bundled) continue;
|
|
133
|
+
const copy = join(dataDir, 'orchestration', name);
|
|
134
|
+
if (![bundled, ...(history.orchestration[name] || [])].includes(fileHash(copy))) continue;
|
|
135
|
+
if (backup.move(copy)) retired.push(`orchestration/${name}`);
|
|
136
|
+
}
|
|
130
137
|
return retired;
|
|
131
138
|
}
|
|
132
139
|
|
|
@@ -24,8 +24,11 @@
|
|
|
24
24
|
import { billableInputTokensForProvider } from '../../runtime/shared/llm/cost.mjs';
|
|
25
25
|
import { hourlySeries } from './usage-stats-hours.mjs';
|
|
26
26
|
import {
|
|
27
|
+
FAST_KEY,
|
|
27
28
|
isConversationUsageSource,
|
|
29
|
+
isFastCall,
|
|
28
30
|
knownCostTurns,
|
|
31
|
+
sortFastBesideModel,
|
|
29
32
|
usageRollupDayKey,
|
|
30
33
|
} from '../../runtime/shared/llm/usage-rollup.mjs';
|
|
31
34
|
|
|
@@ -132,11 +135,14 @@ function providerBucket(state, provider, kind) {
|
|
|
132
135
|
return bucket;
|
|
133
136
|
}
|
|
134
137
|
|
|
135
|
-
|
|
136
|
-
|
|
138
|
+
// A model's Fast-mode calls are their own row beside its normal row.
|
|
139
|
+
function modelBucket(provider, model, fast = false) {
|
|
140
|
+
const key = fast ? model + FAST_KEY : model;
|
|
141
|
+
let bucket = provider.models.get(key);
|
|
137
142
|
if (!bucket) {
|
|
138
143
|
bucket = {
|
|
139
144
|
model,
|
|
145
|
+
fast,
|
|
140
146
|
turns: 0,
|
|
141
147
|
input: 0,
|
|
142
148
|
output: 0,
|
|
@@ -146,7 +152,7 @@ function modelBucket(provider, model) {
|
|
|
146
152
|
sessions: new Set(),
|
|
147
153
|
sessionsComplete: true,
|
|
148
154
|
};
|
|
149
|
-
provider.models.set(
|
|
155
|
+
provider.models.set(key, bucket);
|
|
150
156
|
}
|
|
151
157
|
return bucket;
|
|
152
158
|
}
|
|
@@ -166,9 +172,9 @@ function addUsage(target, usage) {
|
|
|
166
172
|
target.speedMs = (target.speedMs || 0) + (usage.speedMs || 0);
|
|
167
173
|
}
|
|
168
174
|
|
|
169
|
-
function foldRoute(state, providerId, modelId, kind, usage) {
|
|
175
|
+
function foldRoute(state, providerId, modelId, kind, usage, fast = false) {
|
|
170
176
|
const provider = providerBucket(state, providerId, kind);
|
|
171
|
-
const model = modelBucket(provider, modelId);
|
|
177
|
+
const model = modelBucket(provider, modelId, fast);
|
|
172
178
|
for (const bucket of [provider, model]) {
|
|
173
179
|
addUsage(bucket, usage);
|
|
174
180
|
if (usage.turns > 0 && (!usage.sessions || usage.sessionsComplete === false)) {
|
|
@@ -258,7 +264,7 @@ function foldRollupDay(state, key, day, conversationOnly) {
|
|
|
258
264
|
speedOutput: num(raw?.speedOutput),
|
|
259
265
|
speedMs: num(raw?.speedMs),
|
|
260
266
|
};
|
|
261
|
-
foldRoute(state, providerId, modelId, text(raw?.kind), usage);
|
|
267
|
+
foldRoute(state, providerId, modelId, text(raw?.kind), usage, raw?.fast === true);
|
|
262
268
|
addDaily(state, key, usage, providerId);
|
|
263
269
|
}
|
|
264
270
|
|
|
@@ -313,7 +319,14 @@ function foldEvent(state, key, event, conversationOnly) {
|
|
|
313
319
|
speedOutput: timed ? output : 0,
|
|
314
320
|
speedMs: timed ? durationMs : 0,
|
|
315
321
|
};
|
|
316
|
-
|
|
322
|
+
// Tiers are kept on the record's rates (see makeUsageRecord), not top level.
|
|
323
|
+
const kind = text(event?.providerKind);
|
|
324
|
+
const fast = isFastCall({
|
|
325
|
+
kind,
|
|
326
|
+
requestServiceTier: event?.rates?.requestServiceTier,
|
|
327
|
+
serviceTier: event?.rates?.serviceTier,
|
|
328
|
+
});
|
|
329
|
+
foldRoute(state, providerId, modelId, kind, usage, fast);
|
|
317
330
|
addDaily(state, key, usage, providerId);
|
|
318
331
|
|
|
319
332
|
if (durationMs > 0) {
|
|
@@ -513,9 +526,12 @@ function exportRoute(bucket, totalTokens) {
|
|
|
513
526
|
function exportProviders(state, { totalTokens, modelLimit }) {
|
|
514
527
|
return [...state.providers.values()]
|
|
515
528
|
.map((bucket) => {
|
|
516
|
-
const
|
|
517
|
-
|
|
518
|
-
.
|
|
529
|
+
const exported = [...bucket.models.values()].map((model) => ({
|
|
530
|
+
model: model.model,
|
|
531
|
+
...(model.fast ? { fast: true } : {}),
|
|
532
|
+
...exportRoute(model, totalTokens),
|
|
533
|
+
}));
|
|
534
|
+
const models = sortFastBesideModel(exported, (row) => row.model, ['tokens', 'costUsd']);
|
|
519
535
|
return {
|
|
520
536
|
provider: bucket.provider,
|
|
521
537
|
providerKind: bucket.providerKind,
|
|
@@ -535,7 +551,12 @@ function exportUnpricedModels(state) {
|
|
|
535
551
|
const rows = [];
|
|
536
552
|
for (const provider of state.providers.values()) {
|
|
537
553
|
for (const model of provider.models.values()) {
|
|
538
|
-
|
|
554
|
+
// A model's Fast bucket is the same identity as its normal one.
|
|
555
|
+
if (
|
|
556
|
+
model.turns > 0 &&
|
|
557
|
+
model.costKnownTurns < model.turns &&
|
|
558
|
+
!rows.some((row) => row.provider === provider.provider && row.model === model.model)
|
|
559
|
+
)
|
|
539
560
|
rows.push({ provider: provider.provider, model: model.model });
|
|
540
561
|
}
|
|
541
562
|
}
|
|
@@ -12,7 +12,7 @@ import { sessionOptions } from './session-options.mjs';
|
|
|
12
12
|
* time. A boot connect still mid-handshake is caught on the first user
|
|
13
13
|
* turn by refreshInitialDeferredMcpSurface (session-turn-api), which
|
|
14
14
|
* re-folds the live registry before the prompt renders. */
|
|
15
|
-
function seedToolSurface(deps, reason) {
|
|
15
|
+
function seedToolSurface(deps, reason, coreMemoryContext) {
|
|
16
16
|
const { rt, mcpClient, modelStandaloneTools, applyPreSessionToolSelection } = deps;
|
|
17
17
|
let connectedMcpTools = [];
|
|
18
18
|
try {
|
|
@@ -37,6 +37,8 @@ function seedToolSurface(deps, reason) {
|
|
|
37
37
|
// process-wide firstTurnCompleted.
|
|
38
38
|
rt.session.deferredInitialRefreshPending = !/resume/i.test(String(reason || ''));
|
|
39
39
|
applyPreSessionToolSelection();
|
|
40
|
+
// Built from the settings as they stand: its first turn need not rebuild it.
|
|
41
|
+
deps.noteToolAvailability?.(rt.session, coreMemoryContext);
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
/** Adopt the provider session and publish it to hooks and statusline. */
|
|
@@ -45,7 +47,7 @@ export function materializeSession(deps, reason, coreMemoryContext) {
|
|
|
45
47
|
// adoptSession attaches the hook bridge (boot/infrastructure.mjs sessionAdopter).
|
|
46
48
|
adoptSession(mgr.createSession(sessionOptions(deps, coreMemoryContext)));
|
|
47
49
|
rt.reservedSessionId = null;
|
|
48
|
-
seedToolSurface(deps, reason);
|
|
50
|
+
seedToolSurface(deps, reason, coreMemoryContext);
|
|
49
51
|
writeStatuslineRoute(statusRoutes, rt.session, rt.route);
|
|
50
52
|
hooks.emit('session:create', {
|
|
51
53
|
sessionId: rt.session.id,
|
|
@@ -111,6 +111,8 @@ export function sessionOptions(deps, coreMemoryContext) {
|
|
|
111
111
|
cwd: rt.currentCwd,
|
|
112
112
|
...(rt.desktopSession && typeof rt.desktopSession === 'object' ? { desktopSession: rt.desktopSession } : {}),
|
|
113
113
|
coreMemoryContext,
|
|
114
|
+
// Prompt settings from the in-memory config (its disk copy trails it).
|
|
115
|
+
promptConfig: rt.config,
|
|
114
116
|
workflow,
|
|
115
117
|
workflowContext,
|
|
116
118
|
...(leadWorkflowParts ? { leadWorkflowParts } : {}),
|
|
@@ -36,6 +36,8 @@ export function createSessionTurnApi(deps) {
|
|
|
36
36
|
agentControl: agent.agentControl,
|
|
37
37
|
taskControl: agent.taskControl,
|
|
38
38
|
stopShellJob: agent.stopShellJob,
|
|
39
|
+
listStoppableShellJobs: agent.listStoppableShellJobs,
|
|
40
|
+
stopShellJobs: agent.stopShellJobs,
|
|
39
41
|
releaseShellJob: agent.releaseShellJob,
|
|
40
42
|
listShellJobs: agent.listShellJobs,
|
|
41
43
|
onNotification: agent.onNotification,
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
setBuiltinInstalledInConfig,
|
|
9
9
|
} from '../runtime/agent/orchestrator/runtime-core/builtin-features.mjs';
|
|
10
10
|
import { featureEnvOverride, moduleEnabled } from '../runtime/agent/orchestrator/runtime-core/config-helpers.mjs';
|
|
11
|
+
import { noteCacheWarmingEnabled } from '../runtime/agent/orchestrator/session/cache-warm.mjs';
|
|
11
12
|
import { normalizeAgentAvatar } from '../runtime/shared/agent-avatar.mjs';
|
|
12
13
|
import { LOCAL_PROVIDER_ID } from '../runtime/local-provider/managed-runtime.mjs';
|
|
13
14
|
import { INSTRUCTION_FILES_MODES, normalizeInstructionFilesMode } from '../runtime/shared/instruction-files-mode.mjs';
|
|
@@ -66,7 +67,6 @@ export function createBuiltinToolSettings(
|
|
|
66
67
|
webSearchEnabled,
|
|
67
68
|
invalidateContextStatusCache,
|
|
68
69
|
invalidatePreSessionToolSurface,
|
|
69
|
-
refreshEmptySessionToolPolicy,
|
|
70
70
|
},
|
|
71
71
|
localSettings
|
|
72
72
|
) {
|
|
@@ -100,11 +100,13 @@ export function createBuiltinToolSettings(
|
|
|
100
100
|
// default on. The warmer reads the saved value at each
|
|
101
101
|
// warm, so a change applies without a restart.
|
|
102
102
|
getCacheWarmingSettings() {
|
|
103
|
-
return { enabled: getConfig()?.promptCacheWarming
|
|
103
|
+
return { enabled: getConfig()?.promptCacheWarming === true };
|
|
104
104
|
},
|
|
105
105
|
setCacheWarmingEnabled(enabled) {
|
|
106
106
|
if (typeof enabled !== 'boolean') throw new TypeError('cache warming must be on or off (a boolean)');
|
|
107
107
|
saveConfigAndAdopt({ ...getConfig(), promptCacheWarming: enabled });
|
|
108
|
+
// The warmer's synchronous state follows at once (off cancels chains).
|
|
109
|
+
noteCacheWarmingEnabled(enabled);
|
|
108
110
|
return this.getCacheWarmingSettings();
|
|
109
111
|
},
|
|
110
112
|
// The one pixel face every Lead row on the bot page wears, shared by every
|
|
@@ -198,19 +200,15 @@ export function createBuiltinToolSettings(
|
|
|
198
200
|
async setWebSearchEnabled(enabled) {
|
|
199
201
|
const config = getConfig();
|
|
200
202
|
saveConfigAndAdopt(setModuleEnabledInConfig({ ...config }, 'webSearch', enabled !== false));
|
|
201
|
-
// Empty/reserved sessions rebuild now so session entry does not still
|
|
202
|
-
// advertise web_search. A conversation keeps its frozen schema.
|
|
203
|
-
await refreshEmptySessionToolPolicy?.();
|
|
204
203
|
return this.getToolModuleSettings();
|
|
205
204
|
},
|
|
206
205
|
/** Which user instruction files (AGENTS.md / CLAUDE.md) new sessions load:
|
|
207
|
-
* 'all' | 'agents' | 'claude' | 'off'.
|
|
206
|
+
* 'all' | 'agents' | 'claude' | 'off'. An empty session rebuilds at its next turn. */
|
|
208
207
|
async setInstructionFiles(mode) {
|
|
209
208
|
if (!INSTRUCTION_FILES_MODES.includes(mode)) {
|
|
210
209
|
throw new TypeError(`Instruction files must be one of ${INSTRUCTION_FILES_MODES.join(', ')}.`);
|
|
211
210
|
}
|
|
212
211
|
saveConfigAndAdopt({ ...getConfig(), instructionFiles: mode });
|
|
213
|
-
await refreshEmptySessionToolPolicy?.();
|
|
214
212
|
return this.getToolModuleSettings();
|
|
215
213
|
},
|
|
216
214
|
/** The global "Auto reasoning base": the effort Auto works around. */
|
|
@@ -235,7 +233,6 @@ export function createBuiltinToolSettings(
|
|
|
235
233
|
if (memoryEnabled) nextConfig = setBuiltinInstalledInConfig(nextConfig, 'memory', true);
|
|
236
234
|
saveConfigAndAdopt(nextConfig);
|
|
237
235
|
invalidateContextStatusCache();
|
|
238
|
-
await refreshEmptySessionToolPolicy?.();
|
|
239
236
|
return this.getToolModuleSettings();
|
|
240
237
|
},
|
|
241
238
|
async setBuiltinToolEnabled(name, enabled) {
|
|
@@ -265,7 +262,6 @@ export function createBuiltinToolSettings(
|
|
|
265
262
|
}
|
|
266
263
|
// Turning Auto on loads nothing: the judge starts on its first turn.
|
|
267
264
|
if (name === 'autoEffort' && enabled === false) await shutdownEffortJudge();
|
|
268
|
-
await refreshEmptySessionToolPolicy?.();
|
|
269
265
|
return this.getToolModuleSettings();
|
|
270
266
|
},
|
|
271
267
|
/** Extensions → Built-in Install: run the feature's preparation adapter
|
|
@@ -297,7 +293,6 @@ export function createBuiltinToolSettings(
|
|
|
297
293
|
await syncLocalProviderRegistry?.(true);
|
|
298
294
|
}
|
|
299
295
|
if (name === 'memory') invalidateContextStatusCache();
|
|
300
|
-
await refreshEmptySessionToolPolicy?.();
|
|
301
296
|
return this.getToolModuleSettings();
|
|
302
297
|
},
|
|
303
298
|
/** Extensions → Code Tidy: which engines exist, where each one comes from,
|