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,6 +1,10 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
2
|
import { selectedSkillName } from '../../../shared/skill-selection.mjs';
|
|
3
|
+
import { mentionedSkillNames, skillMentionCandidates } from '../../../shared/skill-mentions.mjs';
|
|
4
|
+
import { isAttachmentReference } from '../../../attachments/store.mjs';
|
|
5
|
+
import { collectPromptSkillsCached } from '../context/collect.mjs';
|
|
3
6
|
import { executeTool } from './loop/tool-exec.mjs';
|
|
7
|
+
import { preDispatchDenyForSession } from './loop/pre-dispatch-deny.mjs';
|
|
4
8
|
import { parseNativeToolSearchPayload } from './loop/tool-helpers.mjs';
|
|
5
9
|
import { normalizeToolEnvelope } from './tool-envelope.mjs';
|
|
6
10
|
import { throwIfAborted } from '../../../shared/abort-race.mjs';
|
|
@@ -20,19 +24,91 @@ function nativeDefinitionsPresent(native, messages) {
|
|
|
20
24
|
);
|
|
21
25
|
}
|
|
22
26
|
|
|
27
|
+
// At most this many skills are prepared for one user turn; further selections
|
|
28
|
+
// stay prose.
|
|
29
|
+
const MAX_EXPLICIT_SKILLS = 5;
|
|
30
|
+
const LOADED_SKILL_RE = /^Loaded (?:built-in )?skill: /;
|
|
31
|
+
|
|
32
|
+
// The user's own typed text: plain strings and text parts, never attachment
|
|
33
|
+
// references (file contents the user attached, not words they typed).
|
|
34
|
+
function userPromptText(prompt) {
|
|
35
|
+
if (typeof prompt === 'string') return prompt;
|
|
36
|
+
if (!Array.isArray(prompt)) return '';
|
|
37
|
+
return prompt
|
|
38
|
+
.map((part) => {
|
|
39
|
+
if (typeof part === 'string') return part;
|
|
40
|
+
if (part?.type === 'text' && typeof part.text === 'string' && !isAttachmentReference(part)) return part.text;
|
|
41
|
+
return '';
|
|
42
|
+
})
|
|
43
|
+
.join('\n');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** The skills a prompt explicitly selects: the leading `Skill: "name"` header,
|
|
47
|
+
* then every inline `$name`, each only when it names a skill enabled and in
|
|
48
|
+
* scope for `cwd`, in first-mention order, deduplicated and capped. */
|
|
49
|
+
export function explicitSkillNames(prompt, cwd) {
|
|
50
|
+
const header = selectedSkillName(prompt);
|
|
51
|
+
const text = userPromptText(prompt);
|
|
52
|
+
if (!header && !skillMentionCandidates(text).length) return [];
|
|
53
|
+
const available = new Set(collectPromptSkillsCached(cwd).map((skill) => skill.name));
|
|
54
|
+
const isSkill = (name) => available.has(name);
|
|
55
|
+
const names = header && isSkill(header) ? [header] : [];
|
|
56
|
+
for (const name of mentionedSkillNames(text, isSkill)) {
|
|
57
|
+
if (!names.includes(name)) names.push(name);
|
|
58
|
+
}
|
|
59
|
+
return names.slice(0, MAX_EXPLICIT_SKILLS);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Stamps the skills a user turn actually loaded on its transcript metadata,
|
|
63
|
+
* where the live row, the persisted transcript and restore all read it.
|
|
64
|
+
* The stamped message REPLACES `message` in `messages` (returned): the
|
|
65
|
+
* session store ships reference-identical messages as an append-only delta,
|
|
66
|
+
* so an in-place edit of a user message an earlier save already sent would
|
|
67
|
+
* never reach disk. */
|
|
68
|
+
export function recordAppliedSkills(messages, message, names) {
|
|
69
|
+
if (!message || !Array.isArray(names) || !names.length) return message;
|
|
70
|
+
const meta = message.meta && typeof message.meta === 'object' ? message.meta : {};
|
|
71
|
+
const transcript = meta.transcript && typeof meta.transcript === 'object' ? meta.transcript : {};
|
|
72
|
+
const stamped = { ...message, meta: { ...meta, transcript: { ...transcript, appliedSkills: [...names] } } };
|
|
73
|
+
const index = Array.isArray(messages) ? messages.indexOf(message) : -1;
|
|
74
|
+
if (index >= 0) messages[index] = stamped;
|
|
75
|
+
return stamped;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Tells the host which skills a user turn loaded; a host callback failure
|
|
79
|
+
* never fails the turn. */
|
|
80
|
+
export function notifySkillsApplied(onSkillsApplied, applied, message) {
|
|
81
|
+
if (!applied.length) return;
|
|
82
|
+
try {
|
|
83
|
+
onSkillsApplied?.(applied, { messageId: message?.meta?.transcript?.messageId || null });
|
|
84
|
+
} catch {
|
|
85
|
+
/* best-effort host callback */
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
23
89
|
// Called before the first model request for a real user turn. This performs the
|
|
24
90
|
// same policy-checked Skill operation, without asking the model to request it.
|
|
25
91
|
// Native schemas still travel as a properly paired loader execution, never as
|
|
26
|
-
// new eager definitions or an orphan tool_search_output.
|
|
92
|
+
// new eager definitions or an orphan tool_search_output. Returns the names of
|
|
93
|
+
// the skills that loaded successfully, in selection order.
|
|
94
|
+
// `selection`, when given (even empty), is the turn's TRUSTED selection input
|
|
95
|
+
// and the only text skills are selected from: a host whose model-visible
|
|
96
|
+
// prompt carries external data (webhook payloads) passes just the
|
|
97
|
+
// operator-authored part, so nothing inside the data can load a skill.
|
|
27
98
|
export async function prepareExplicitSkills(
|
|
28
99
|
prompt,
|
|
29
100
|
messages,
|
|
30
101
|
session,
|
|
31
|
-
{ cwd = session?.cwd, signal, execute = executeTool } = {}
|
|
102
|
+
{ cwd = session?.cwd, signal, execute = executeTool, selection } = {}
|
|
32
103
|
) {
|
|
33
104
|
throwIfAborted(signal);
|
|
34
|
-
const
|
|
35
|
-
|
|
105
|
+
const applied = [];
|
|
106
|
+
// A session that cannot call Skill (schema allowlist, denied tools, read-only
|
|
107
|
+
// surface — the dispatcher's own gate) has nothing to select: preparing would
|
|
108
|
+
// only push a refused-tool reminder into history on every matching turn.
|
|
109
|
+
if (preDispatchDenyForSession(session, { name: 'Skill' })) return applied;
|
|
110
|
+
const source = selection === undefined || selection === null ? prompt : selection;
|
|
111
|
+
for (const name of explicitSkillNames(source, cwd)) {
|
|
36
112
|
const id = `skill-selection-${randomUUID()}`;
|
|
37
113
|
const args = { name };
|
|
38
114
|
const raw = await execute('Skill', args, cwd, session?.id, session, { signal, toolCallId: id });
|
|
@@ -55,6 +131,8 @@ export async function prepareExplicitSkills(
|
|
|
55
131
|
});
|
|
56
132
|
}
|
|
57
133
|
messages.push(...envelope.newMessages);
|
|
134
|
+
if (LOADED_SKILL_RE.test(String(summary))) applied.push(name);
|
|
135
|
+
throwIfAborted(signal);
|
|
58
136
|
}
|
|
59
|
-
|
|
137
|
+
return applied;
|
|
60
138
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provenance of messages carried over from another app's conversation
|
|
3
|
+
* (conversation-import). Their text is prose someone wrote elsewhere: it may
|
|
4
|
+
* look like a runtime reminder, a task envelope or a compaction summary, but
|
|
5
|
+
* restore and the model wire treat it as plain user/assistant text. Leaf, no IO.
|
|
6
|
+
*/
|
|
7
|
+
export const IMPORTED_MESSAGE_SOURCE = 'import';
|
|
8
|
+
|
|
9
|
+
export function isImportedMessage(message) {
|
|
10
|
+
return message?.meta?.source === IMPORTED_MESSAGE_SOURCE;
|
|
11
|
+
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// (signature + stub) and the edit-progress classification.
|
|
3
3
|
// Pure string/signature helpers; the loop body only wires state + messages.
|
|
4
4
|
// No provider/manager coupling.
|
|
5
|
+
import { knownMcpToolIdentity } from '../../../../shared/tool-primitives.mjs';
|
|
5
6
|
|
|
6
7
|
// Deterministic, key-sorted stringify for cross-turn call signatures (recursive,
|
|
7
8
|
// unlike tool-classify's top-level-only _canonicalArgs).
|
|
@@ -43,7 +44,7 @@ const NON_PROGRESS_TOOLS = new Set(['Skill', 'recall', 'agent', 'task', 'cwd', '
|
|
|
43
44
|
// not in the meta/non-progress set. apply_patch and shell/bash always count.
|
|
44
45
|
export function isEditProgressTool(name, isEager) {
|
|
45
46
|
if (isEager) return false;
|
|
46
|
-
const bare = name?.startsWith('mcp__') ? name.split('__').pop() : name;
|
|
47
|
+
const bare = name?.startsWith('mcp__') ? knownMcpToolIdentity(name)?.tool || name.split('__').pop() : name;
|
|
47
48
|
if (bare === 'apply_patch' || bare === 'shell' || bare === 'bash' || bare === 'bash_session') return true;
|
|
48
49
|
return !NON_PROGRESS_TOOLS.has(bare);
|
|
49
50
|
}
|
|
@@ -146,7 +146,7 @@ export function createLoopState({ provider, messages, model, tools, cwd, sendOpt
|
|
|
146
146
|
messages,
|
|
147
147
|
opts,
|
|
148
148
|
sessionId,
|
|
149
|
-
onSkillPrompt: (content) => state.pendingSkillPrompts.push(content),
|
|
149
|
+
onSkillPrompt: (content, message) => state.pendingSkillPrompts.push({ content, message }),
|
|
150
150
|
});
|
|
151
151
|
// Bounded recovery for provider turns that returned no client tool calls
|
|
152
152
|
// (max-output ladder, refusal retry, provider continuation, empty-turn
|
|
@@ -34,8 +34,9 @@ export function createNoToolTurnResolver({
|
|
|
34
34
|
refusalRetryUsed: false,
|
|
35
35
|
emptyNudgeStreak: 0,
|
|
36
36
|
// Structured provider continuation signals honored this turn. Diagnostic
|
|
37
|
-
// only
|
|
38
|
-
//
|
|
37
|
+
// only: the loop has no iteration cap, so this count bounds nothing. A
|
|
38
|
+
// text-only continuation runaway is bounded by continuationsSinceToolBatch
|
|
39
|
+
// below; continuations interleaved with tool batches are not limited.
|
|
39
40
|
providerContinuationCount: 0,
|
|
40
41
|
// Continuations since the last executed tool batch — bounds the text-only
|
|
41
42
|
// continuation runaway (see PROVIDER_CONTINUATION_NO_TOOL_LIMIT).
|
|
@@ -5,9 +5,10 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { traceCacheBreak } from '../../cache-break-trace.mjs';
|
|
7
7
|
import { resolveLiveToolCwd } from './tool-exec.mjs';
|
|
8
|
-
import { prepareExplicitSkills } from '../explicit-skills.mjs';
|
|
8
|
+
import { notifySkillsApplied, prepareExplicitSkills, recordAppliedSkills } from '../explicit-skills.mjs';
|
|
9
9
|
import { addUsage, usageDeltaEvent } from './usage.mjs';
|
|
10
10
|
import { prepareProviderRequest } from './request-boundary.mjs';
|
|
11
|
+
import { applyStepEffort } from './step-auto-effort.mjs';
|
|
11
12
|
import { projectProviderRequest } from './request-projection.mjs';
|
|
12
13
|
import { traceProviderSend, traceOutputTruncation } from './diagnostics.mjs';
|
|
13
14
|
import { createEagerDispatcher } from '../eager-dispatch.mjs';
|
|
@@ -44,10 +45,13 @@ export async function beginIteration(state) {
|
|
|
44
45
|
// policy-checked selection before the next provider snapshot instead of
|
|
45
46
|
// starting detached work from a drain callback.
|
|
46
47
|
while (state.pendingSkillPrompts.length) {
|
|
47
|
-
|
|
48
|
+
const { content, message: queued } = state.pendingSkillPrompts.shift();
|
|
49
|
+
const applied = await prepareExplicitSkills(content, messages, sessionRef, {
|
|
48
50
|
cwd: state.cwd,
|
|
49
51
|
signal: opts.signal,
|
|
50
52
|
});
|
|
53
|
+
const message = recordAppliedSkills(messages, queued, applied);
|
|
54
|
+
notifySkillsApplied(opts.onSkillsApplied, applied, message);
|
|
51
55
|
}
|
|
52
56
|
const boundary = await prepareProviderRequest({
|
|
53
57
|
provider,
|
|
@@ -129,6 +133,9 @@ export async function sendProviderRequest(state, round) {
|
|
|
129
133
|
const sendStartedAt = Date.now();
|
|
130
134
|
const preSendMs = sendStartedAt - round.iterT0;
|
|
131
135
|
const toolResumeMs = state.lastToolBatchEndedAt ? sendStartedAt - state.lastToolBatchEndedAt : null;
|
|
136
|
+
// The step judgment ran beside opening the iteration; wait for it only up to
|
|
137
|
+
// its grace, then it rides on this request or on the next.
|
|
138
|
+
await applyStepEffort(state);
|
|
132
139
|
// Every attempt is built from the live transcript, so a compaction between
|
|
133
140
|
// attempts reaches the provider; a pending image strip only filters it.
|
|
134
141
|
const messageSource = state.imageStrip
|
|
@@ -263,8 +270,7 @@ function traceActualCacheMiss(state, sent, response, { previousGuardState, previ
|
|
|
263
270
|
const ttlMs = MESSAGES_CACHE_TTL_MS[sessionRef.providerCacheOpts?.cacheStrategy?.messages];
|
|
264
271
|
const idleMs = sent.sendStartedAt - previousSendAt;
|
|
265
272
|
const requestPrefixChanged =
|
|
266
|
-
!!previousGuardState &&
|
|
267
|
-
previousGuardState.requestPrefixHash !== sent.prefixGuardCandidate?.requestPrefixHash;
|
|
273
|
+
!!previousGuardState && previousGuardState.requestPrefixHash !== sent.prefixGuardCandidate?.requestPrefixHash;
|
|
268
274
|
if (
|
|
269
275
|
baseline > 0 &&
|
|
270
276
|
ttlMs &&
|
|
@@ -156,7 +156,7 @@ function injectSteeringEntry(merged, { messages, opts, stage, onSkillPrompt }) {
|
|
|
156
156
|
const notification = merged.mode === 'task-notification';
|
|
157
157
|
const execution =
|
|
158
158
|
notification && merged.execution && typeof merged.execution === 'object' ? { ...merged.execution } : null;
|
|
159
|
-
|
|
159
|
+
const message = {
|
|
160
160
|
role: 'user',
|
|
161
161
|
content: merged.content,
|
|
162
162
|
meta: {
|
|
@@ -165,8 +165,9 @@ function injectSteeringEntry(merged, { messages, opts, stage, onSkillPrompt }) {
|
|
|
165
165
|
...(submissionIds.length ? { submissionIds } : {}),
|
|
166
166
|
transcript: steeringTranscriptMeta,
|
|
167
167
|
},
|
|
168
|
-
}
|
|
169
|
-
|
|
168
|
+
};
|
|
169
|
+
messages.push(message);
|
|
170
|
+
if (!notification) onSkillPrompt(merged.content, message);
|
|
170
171
|
const text = merged.text || steeringContentText(merged.content);
|
|
171
172
|
try {
|
|
172
173
|
opts.onSteerMessage?.(text, {
|
|
@@ -8,12 +8,13 @@
|
|
|
8
8
|
* later request rebuilds the same history and the prompt cache keeps hitting.
|
|
9
9
|
* A judge that is missing, slow or failing leaves the step at the effort in
|
|
10
10
|
* force (the turn's or the previous step's).
|
|
11
|
-
* A custom route
|
|
12
|
-
*
|
|
13
|
-
* turn's following requests
|
|
11
|
+
* A custom route snaps the judged effort onto the model's levels. Without a
|
|
12
|
+
* mid-conversation update (snapshot mode 'custom') it becomes the effort of
|
|
13
|
+
* the turn's following requests; a custom GPT-6+ Responses route (mode
|
|
14
|
+
* 'responses') also marks it as the update.
|
|
14
15
|
*/
|
|
15
16
|
import { resolveAutoEffort } from '../../providers/auto-effort.mjs';
|
|
16
|
-
import { resolveCustomReasoning } from '../../providers/custom-reasoning.mjs';
|
|
17
|
+
import { isCustomProviderName, resolveCustomReasoning } from '../../providers/custom-reasoning.mjs';
|
|
17
18
|
import { autoEffortModel, stepEffortConfiguration } from '../../providers/effort-configuration.mjs';
|
|
18
19
|
import { effortOptionsFor } from '../../runtime-core/effort.mjs';
|
|
19
20
|
import { judgeTurn, recordEffortDecision } from '../../../../effort-judge/judge-client.mjs';
|
|
@@ -35,12 +36,58 @@ const argText = (args) =>
|
|
|
35
36
|
.slice(0, 600)
|
|
36
37
|
.join('');
|
|
37
38
|
|
|
39
|
+
// A judgment runs beside the next iteration instead of in front of it. Its
|
|
40
|
+
// record lives on the loop state (`state.stepEffort`), so it can only ever
|
|
41
|
+
// reach the turn that started it; its promise settles the record and touches
|
|
42
|
+
// nothing else, so an aborted loop is never mutated afterwards. The result
|
|
43
|
+
// lands on the batch's last tool result in one of two places:
|
|
44
|
+
// - resolved before the next request is projected: on that tool result, so
|
|
45
|
+
// the request carries it (applyStepEffort);
|
|
46
|
+
// - resolved later: the request already went out with the earlier effort and
|
|
47
|
+
// its history is never rewritten (that would break the prompt cache), so
|
|
48
|
+
// the result marks the last tool result of the next batch, and the
|
|
49
|
+
// following request carries it (markStepEffort).
|
|
50
|
+
function applyResult(state, target, result) {
|
|
51
|
+
if (result.level) state.opts.effort = result.level;
|
|
52
|
+
if (result.marked) target.meta = { ...target.meta, effortConfiguration: result.marked };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// How long a request waits for its step judgment (measured judge p90 ≈ 284 ms).
|
|
56
|
+
export const STEP_EFFORT_GRACE_MS = 300;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Before a provider request is projected: wait up to the grace for the pending
|
|
60
|
+
* judgment and apply it if it resolved. A slower one leaves this request at
|
|
61
|
+
* the effort in force and lands on the following request.
|
|
62
|
+
*/
|
|
63
|
+
export async function applyStepEffort(state) {
|
|
64
|
+
const pending = state.stepEffort;
|
|
65
|
+
if (!pending || pending.sent) return;
|
|
66
|
+
if (!pending.settled && !state.signal?.aborted) {
|
|
67
|
+
let timer;
|
|
68
|
+
await Promise.race([
|
|
69
|
+
pending.promise,
|
|
70
|
+
new Promise((resolve) => {
|
|
71
|
+
timer = setTimeout(resolve, STEP_EFFORT_GRACE_MS);
|
|
72
|
+
}),
|
|
73
|
+
]);
|
|
74
|
+
clearTimeout(timer);
|
|
75
|
+
// Another caller may have handled it while this one waited.
|
|
76
|
+
if (pending.sent) return;
|
|
77
|
+
}
|
|
78
|
+
pending.sent = true;
|
|
79
|
+
if (!pending.result || state.signal?.aborted || !state.messages.includes(pending.target)) return;
|
|
80
|
+
applyResult(state, pending.target, pending.result);
|
|
81
|
+
pending.applied = true;
|
|
82
|
+
}
|
|
83
|
+
|
|
38
84
|
/**
|
|
39
|
-
*
|
|
85
|
+
* Start judging the step after this batch (not awaited). The result applies to
|
|
86
|
+
* the next request if it is ready by then, else to the one after.
|
|
40
87
|
* `state.opts.stepAutoEffort` ({ request, base }) is set only when auto effort
|
|
41
88
|
* is on for this turn and the installed judge was trained on steps.
|
|
42
89
|
*/
|
|
43
|
-
export
|
|
90
|
+
export function markStepEffort(state, assistantTurnMsg) {
|
|
44
91
|
const auto = state.opts?.stepAutoEffort;
|
|
45
92
|
const snapshot = state.opts?.effortConfiguration;
|
|
46
93
|
if (!auto || !snapshot || state.signal?.aborted) return;
|
|
@@ -55,11 +102,27 @@ export async function markStepEffort(state, assistantTurnMsg) {
|
|
|
55
102
|
}
|
|
56
103
|
}
|
|
57
104
|
if (!last) return;
|
|
105
|
+
const previous = state.stepEffort;
|
|
106
|
+
if (previous) {
|
|
107
|
+
// It resolved after its request went out: this batch carries it. One still
|
|
108
|
+
// running is superseded: the newest step's judgment queues behind it and
|
|
109
|
+
// any judgment still waiting in between is skipped (latest wins), so the
|
|
110
|
+
// judge never has more than one running and one queued.
|
|
111
|
+
if (previous.settled) {
|
|
112
|
+
if (previous.result && !previous.applied) applyResult(state, last, previous.result);
|
|
113
|
+
} else {
|
|
114
|
+
previous.superseded = true;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
58
117
|
state.autoEffortSteps = (state.autoEffortSteps || 0) + 1;
|
|
59
118
|
const step = state.autoEffortSteps;
|
|
60
119
|
const provider = state.sessionRef?.provider;
|
|
61
120
|
const model = state.model;
|
|
62
|
-
const
|
|
121
|
+
const pending = { target: last, sent: false, settled: false, applied: false, superseded: false, result: null };
|
|
122
|
+
const behind = previous && !previous.settled ? previous.promise : Promise.resolve();
|
|
123
|
+
state.stepEffort = pending;
|
|
124
|
+
const context = { auto, snapshot, step, provider, model, providerClient: state.provider, sessionId: state.sessionId };
|
|
125
|
+
const input = {
|
|
63
126
|
step: {
|
|
64
127
|
request: auto.request,
|
|
65
128
|
step,
|
|
@@ -70,11 +133,26 @@ export async function markStepEffort(state, assistantTurnMsg) {
|
|
|
70
133
|
result: stepResultWindow(textOf(results.get(call.id)?.content)),
|
|
71
134
|
})),
|
|
72
135
|
},
|
|
73
|
-
}
|
|
136
|
+
};
|
|
137
|
+
pending.promise = behind
|
|
138
|
+
.then(() => (pending.superseded ? null : judgeTurn(input)))
|
|
139
|
+
.then((judged) => (judged ? stepResult(context, judged) : null))
|
|
140
|
+
// A failed judgment leaves the step at the effort in force.
|
|
141
|
+
.catch(() => null)
|
|
142
|
+
.then((result) => {
|
|
143
|
+
// Only this record changes here; the loop reads it at its next boundary.
|
|
144
|
+
pending.result = result;
|
|
145
|
+
pending.settled = true;
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// What a resolved judgment sets: `{ marked, level }` (the tool result's effort
|
|
150
|
+
// configuration, and the per-request effort of a custom route), or null.
|
|
151
|
+
function stepResult({ auto, snapshot, step, provider, model, providerClient, sessionId }, judged) {
|
|
74
152
|
// `atStep` numbers the tool-result step; `step` in a resolved decision is the ladder move.
|
|
75
153
|
const record = {
|
|
76
154
|
at: new Date().toISOString(),
|
|
77
|
-
sessionId
|
|
155
|
+
sessionId,
|
|
78
156
|
provider,
|
|
79
157
|
model,
|
|
80
158
|
mode: 'on',
|
|
@@ -82,9 +160,9 @@ export async function markStepEffort(state, assistantTurnMsg) {
|
|
|
82
160
|
};
|
|
83
161
|
if (!judged.probs) {
|
|
84
162
|
recordEffortDecision({ ...record, skipped: judged.skipped });
|
|
85
|
-
return;
|
|
163
|
+
return null;
|
|
86
164
|
}
|
|
87
|
-
const modelMeta = autoEffortModel(provider,
|
|
165
|
+
const modelMeta = autoEffortModel(provider, providerClient, model);
|
|
88
166
|
const resolved = resolveAutoEffort({
|
|
89
167
|
base: auto.base,
|
|
90
168
|
options: effortOptionsFor(provider, modelMeta),
|
|
@@ -96,19 +174,25 @@ export async function markStepEffort(state, assistantTurnMsg) {
|
|
|
96
174
|
ms: judged.ms,
|
|
97
175
|
probs: judged.probs.map((value) => Number(value.toFixed(3))),
|
|
98
176
|
});
|
|
99
|
-
if (
|
|
177
|
+
if (isCustomProviderName(provider)) {
|
|
100
178
|
const level =
|
|
101
179
|
resolved &&
|
|
102
180
|
resolveCustomReasoning({
|
|
103
|
-
protocol:
|
|
181
|
+
protocol: providerClient?.customConfig?.protocol,
|
|
104
182
|
model: modelMeta,
|
|
105
183
|
effort: resolved.effort,
|
|
106
184
|
}).level;
|
|
107
|
-
if (!level) return;
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
return
|
|
185
|
+
if (!level) return null;
|
|
186
|
+
// The per-request effort also carries the step on an update route,
|
|
187
|
+
// where a rejected update replays the request with it.
|
|
188
|
+
return {
|
|
189
|
+
level,
|
|
190
|
+
marked:
|
|
191
|
+
snapshot.mode === 'custom'
|
|
192
|
+
? { ...snapshot, effort: level }
|
|
193
|
+
: stepEffortConfiguration(snapshot, provider, model, level),
|
|
194
|
+
};
|
|
111
195
|
}
|
|
112
196
|
const marked = resolved && stepEffortConfiguration(snapshot, provider, model, resolved.effort);
|
|
113
|
-
|
|
197
|
+
return marked ? { level: null, marked } : null;
|
|
114
198
|
}
|
|
@@ -12,6 +12,8 @@ import {
|
|
|
12
12
|
filterSkillsExcludingDisabled,
|
|
13
13
|
isSkillDisabled,
|
|
14
14
|
skillMissingFeature,
|
|
15
|
+
skillOutsideScope,
|
|
16
|
+
skillOutsideScopeError,
|
|
15
17
|
} from '../../context/collect.mjs';
|
|
16
18
|
|
|
17
19
|
// Eager-dispatch: tools with readOnlyHint:true in their declaration are safe
|
|
@@ -96,6 +98,7 @@ export function viewSkill(cwd, name, session = null) {
|
|
|
96
98
|
return `Error: skill "${skillName}" needs the ${missingFeature} built-in feature, which is not installed or is switched off in Extensions → Plugin → Built-in`;
|
|
97
99
|
}
|
|
98
100
|
if (isSkillDisabled(skillName)) return `Error: skill "${skillName}" is disabled`;
|
|
101
|
+
if (skillOutsideScope(skillName, cwd)) return skillOutsideScopeError(skillName);
|
|
99
102
|
const res = loadSkillResource(skillName, cwd);
|
|
100
103
|
if (!res) return `Error: skill "${skillName}" not found`;
|
|
101
104
|
// Return the general tool envelope: the model-visible tool_result is the
|
|
@@ -70,7 +70,9 @@ export async function runToolPhase(state, round, sent, onToolCall) {
|
|
|
70
70
|
// carries a runtime notice for the model, delivered after its results.
|
|
71
71
|
if (response.recoveryNotice) messages.push(response.recoveryNotice);
|
|
72
72
|
const toolsEndedAt = Date.now();
|
|
73
|
-
|
|
73
|
+
// Starts the step judgment; the next request uses it if it has resolved by
|
|
74
|
+
// then (send-phase.mjs applyStepEffort), else the one after.
|
|
75
|
+
markStepEffort(state, assistantTurnMsg);
|
|
74
76
|
try {
|
|
75
77
|
opts.onToolPhaseCompleted?.({
|
|
76
78
|
iteration: round.nextIteration,
|
|
@@ -12,6 +12,17 @@ import {
|
|
|
12
12
|
|
|
13
13
|
const SYNTHETIC_PROMPT_SOURCES = ['goal-continuation', 'goal-closeout'];
|
|
14
14
|
|
|
15
|
+
// A caller-declared prompt source the runtime trusts as provenance of the
|
|
16
|
+
// initial prompt: Goal turns are runtime-synthetic; a task notification (an
|
|
17
|
+
// idle-drained completion, an automation run's agent results) is stored like
|
|
18
|
+
// one the steering/queue drains inject, never as the user speaking — so none
|
|
19
|
+
// of these run explicit skill selection.
|
|
20
|
+
function initialPromptSourceFor(promptSource) {
|
|
21
|
+
if (SYNTHETIC_PROMPT_SOURCES.includes(promptSource)) return { source: promptSource, synthetic: true };
|
|
22
|
+
if (promptSource === PENDING_MODE_TASK_NOTIFICATION) return { source: promptSource };
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
|
|
15
26
|
/** Prompt provenance for a drained queue turn: the source plus its execution when one exists. */
|
|
16
27
|
const promptSourceFields = (source, execution) => {
|
|
17
28
|
if (!source) return null;
|
|
@@ -42,9 +53,13 @@ export function createAskPromptQueue({ sessionId, promptSource }) {
|
|
|
42
53
|
// Local FIFO of follow-up prompts drained from the pending-message queue
|
|
43
54
|
// after each turn — keeps queued `agent type=send` messages in order.
|
|
44
55
|
const tail = [];
|
|
45
|
-
let initialPromptSource =
|
|
46
|
-
|
|
47
|
-
|
|
56
|
+
let initialPromptSource = initialPromptSourceFor(promptSource);
|
|
57
|
+
// Queue entries of the input nextTurn handed out that no turn owns yet.
|
|
58
|
+
// Once a turn starts, its failure path acks or releases them instead.
|
|
59
|
+
let unstartedEntries = [];
|
|
60
|
+
const release = (entries) => {
|
|
61
|
+
if (entries?.length > 0) releasePendingMessages(sessionId, entries);
|
|
62
|
+
};
|
|
48
63
|
|
|
49
64
|
/** The next turn's input — prompt, caller context, consumed queue entries
|
|
50
65
|
* and provenance — or null when nothing model-visible is left to run. */
|
|
@@ -74,7 +89,26 @@ export function createAskPromptQueue({ sessionId, promptSource }) {
|
|
|
74
89
|
tail.unshift(...groups.slice(1).map(tailTurnFor));
|
|
75
90
|
input = queuedTurnInput(tailTurnFor(first));
|
|
76
91
|
}
|
|
77
|
-
|
|
92
|
+
if (!hasModelVisiblePromptContent(input.prompt)) {
|
|
93
|
+
release(input.pendingEntries);
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
unstartedEntries = input.pendingEntries;
|
|
97
|
+
return input;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
/** The turn for the last nextTurn input started: it now owns its entries. */
|
|
101
|
+
const markStarted = () => {
|
|
102
|
+
unstartedEntries = [];
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
/** Hands every drained entry no turn started back to the pending queue —
|
|
106
|
+
* the waiting follow-up turns and an input whose turn never opened.
|
|
107
|
+
* Called once when the ask unwinds; each entry is released once. */
|
|
108
|
+
const releaseUnstarted = () => {
|
|
109
|
+
const entries = [...unstartedEntries, ...tail.splice(0).flatMap((turn) => turn.entries || [])];
|
|
110
|
+
unstartedEntries = [];
|
|
111
|
+
release(entries);
|
|
78
112
|
};
|
|
79
113
|
|
|
80
114
|
/** Queues drained pending-message entries as follow-up turns; true when
|
|
@@ -92,5 +126,8 @@ export function createAskPromptQueue({ sessionId, promptSource }) {
|
|
|
92
126
|
return true;
|
|
93
127
|
};
|
|
94
128
|
|
|
95
|
-
|
|
129
|
+
/** True while drained follow-up turns are still waiting to run. */
|
|
130
|
+
const hasQueuedTurns = () => tail.length > 0;
|
|
131
|
+
|
|
132
|
+
return { nextTurn, pushDrained, hasQueuedTurns, markStarted, releaseUnstarted };
|
|
96
133
|
}
|
|
@@ -148,7 +148,9 @@ export async function askSession(sessionId, prompt, context, onToolCall, cwdOver
|
|
|
148
148
|
// queued send always lands AFTER the in-flight prompt here, ordering is
|
|
149
149
|
// preserved and the spawn/connecting startup race disappears.
|
|
150
150
|
for (;;) {
|
|
151
|
-
|
|
151
|
+
// `skillSelection` (askOpts) is the trusted selection input of the
|
|
152
|
+
// caller's own prompt only; drained follow-up turns never inherit it.
|
|
153
|
+
const input = queue.nextTurn({ prompt, context, explicitPrefetch, skillSelection: askOpts.skillSelection });
|
|
152
154
|
if (!input) {
|
|
153
155
|
void takeoverHydration.then((count) => {
|
|
154
156
|
if (count <= 0) return;
|
|
@@ -176,6 +178,9 @@ export async function askSession(sessionId, prompt, context, onToolCall, cwdOver
|
|
|
176
178
|
...claimed,
|
|
177
179
|
...armTurnDurability({ sessionId, ...claimed, pendingEntries: input.pendingEntries }),
|
|
178
180
|
};
|
|
181
|
+
// From here the turn's own unwind (ask-turn-failure) acks or releases
|
|
182
|
+
// its entries; the queue keeps owning only the not-yet-started ones.
|
|
183
|
+
queue.markStarted();
|
|
179
184
|
const turn = await runAskTurn({
|
|
180
185
|
sessionId,
|
|
181
186
|
opened,
|
|
@@ -191,9 +196,12 @@ export async function askSession(sessionId, prompt, context, onToolCall, cwdOver
|
|
|
191
196
|
// that arrived while this turn was in flight runs next, in order, as a
|
|
192
197
|
// follow-up user turn. The mutex is still held, so a send racing this
|
|
193
198
|
// drain either landed before (picked up here) or enqueues for the next
|
|
194
|
-
// loop.
|
|
199
|
+
// loop. Follow-ups an idle ask already drained wait in the queue's
|
|
200
|
+
// tail and run before anything new. When both are empty we return the
|
|
201
|
+
// latest turn's result.
|
|
195
202
|
const drained = turn.drained.length > 0 ? turn.drained : drainPendingMessages(sessionId);
|
|
196
|
-
|
|
203
|
+
queue.pushDrained(drained);
|
|
204
|
+
if (queue.hasQueuedTurns()) {
|
|
197
205
|
// Carry the just-committed in-memory session into the follow-up
|
|
198
206
|
// turn so the queued tail sees the preceding assistant/tool
|
|
199
207
|
// context. loadSession() would return this same live snapshot
|
|
@@ -214,6 +222,9 @@ export async function askSession(sessionId, prompt, context, onToolCall, cwdOver
|
|
|
214
222
|
return result;
|
|
215
223
|
}
|
|
216
224
|
} finally {
|
|
225
|
+
// A failed/cancelled turn ends the ask: the follow-up turns drained
|
|
226
|
+
// behind it never ran, so their entries go back to the pending queue.
|
|
227
|
+
queue.releaseUnstarted();
|
|
217
228
|
// A thrown setup/provider path must never leave a delayed checkpoint
|
|
218
229
|
// writer alive after the turn lock is released.
|
|
219
230
|
// Clear the controller only if it's still ours (closeSession may have
|
|
@@ -8,7 +8,12 @@
|
|
|
8
8
|
// model declares effort levels (the effort is sent with each request).
|
|
9
9
|
import { readSection } from '../../../../shared/config.mjs';
|
|
10
10
|
import { autoEffortModel, turnEffortConfigurationMode } from '../../providers/effort-configuration.mjs';
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
autoEffortApplicable,
|
|
13
|
+
autoEffortBase,
|
|
14
|
+
normalizeAutoEffortMode,
|
|
15
|
+
resolveAutoEffort,
|
|
16
|
+
} from '../../providers/auto-effort.mjs';
|
|
12
17
|
import { builtinFeatureActive } from '../../runtime-core/builtin-features.mjs';
|
|
13
18
|
import { effortOptionsFor } from '../../runtime-core/effort.mjs';
|
|
14
19
|
import { effortJudgeSupportsSteps, judgeTurn, recordEffortDecision } from '../../../../effort-judge/judge-client.mjs';
|
|
@@ -78,12 +83,6 @@ export async function resolveTurnAutoEffort({ sessionId, session, provider, inpu
|
|
|
78
83
|
if (!turnEffortConfigurationMode(session, provider)) return null;
|
|
79
84
|
const chosen = String(session.effort || '').toLowerCase();
|
|
80
85
|
const base = autoEffortBase(chosen);
|
|
81
|
-
// The previous user request shows the work a short follow-up continues.
|
|
82
|
-
const judged = await judgeTurn({
|
|
83
|
-
request,
|
|
84
|
-
prev: lastText(session.messages, 'assistant'),
|
|
85
|
-
prevRequest: lastText(session.messages, 'user'),
|
|
86
|
-
});
|
|
87
86
|
const record = {
|
|
88
87
|
at: new Date().toISOString(),
|
|
89
88
|
sessionId,
|
|
@@ -94,15 +93,24 @@ export async function resolveTurnAutoEffort({ sessionId, session, provider, inpu
|
|
|
94
93
|
base,
|
|
95
94
|
requestChars: request.length,
|
|
96
95
|
};
|
|
96
|
+
const options = effortOptionsFor(session.provider, autoEffortModel(session.provider, provider, session.model));
|
|
97
|
+
// No judged outcome can apply when the base is off the model's ladder, so
|
|
98
|
+
// the judge is not asked (in observe mode too: nothing would be logged).
|
|
99
|
+
if (!autoEffortApplicable({ base, options })) {
|
|
100
|
+
recordEffortDecision({ ...record, skipped: 'default-outside-auto-range' });
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
// The previous user request shows the work a short follow-up continues.
|
|
104
|
+
const judged = await judgeTurn({
|
|
105
|
+
request,
|
|
106
|
+
prev: lastText(session.messages, 'assistant'),
|
|
107
|
+
prevRequest: lastText(session.messages, 'user'),
|
|
108
|
+
});
|
|
97
109
|
if (!judged.probs) {
|
|
98
110
|
recordEffortDecision({ ...record, skipped: judged.skipped });
|
|
99
111
|
return null;
|
|
100
112
|
}
|
|
101
|
-
const resolved = resolveAutoEffort({
|
|
102
|
-
base,
|
|
103
|
-
options: effortOptionsFor(session.provider, autoEffortModel(session.provider, provider, session.model)),
|
|
104
|
-
probs: judged.probs,
|
|
105
|
-
});
|
|
113
|
+
const resolved = resolveAutoEffort({ base, options, probs: judged.probs });
|
|
106
114
|
recordEffortDecision({
|
|
107
115
|
...record,
|
|
108
116
|
...(resolved || { skipped: 'default-outside-auto-range' }),
|