mixdog 1.3.5 → 1.4.0
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/NOTICE.md +2 -2
- package/README.md +2 -2
- package/package.json +2 -11
- package/scripts/daemon-stub.mjs +1 -1
- package/scripts/gate-local.mjs +4 -2
- package/scripts/native-release-status.mjs +2 -2
- package/scripts/recall-history-cases.json +1 -1
- package/scripts/suite-health.mjs +10 -1
- package/scripts/test.mjs +7 -11
- package/src/agents/reviewer/AGENT.md +7 -11
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +17 -1
- package/src/defaults/skills/browser-use/SKILL.md +59 -11
- package/src/defaults/skills/code-tidy/SKILL.md +142 -270
- package/src/defaults/skills/code-tidy/references/agent-cleanup.md +4 -4
- package/src/defaults/skills/code-tidy/references/cleanup-report.md +31 -76
- package/src/defaults/skills/code-tidy/references/dead-code.md +6 -12
- package/src/defaults/skills/computer-use/SKILL.md +33 -9
- package/src/defaults/skills/setup/SKILL.md +22 -0
- package/src/defaults/skills/setup/references/actions.md +39 -5
- package/src/defaults/skills/setup/references/surfaces.md +11 -2
- package/src/defaults/skills/visualize/SKILL.md +2 -1
- package/src/lib/rules-builder.cjs +10 -8
- package/src/rules/agent/AGENT.md +6 -6
- package/src/rules/lead/LEAD.md +18 -20
- package/src/rules/shared/05-tool-calls.md +5 -6
- package/src/rules/shared/10-tool-workflow.md +2 -0
- package/src/rules/shared/60-verification.md +7 -5
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -3
- package/src/runtime/agent/orchestrator/agent-runtime/title-completion.mjs +3 -1
- package/src/runtime/agent/orchestrator/agent-trace-format.mjs +3 -1
- package/src/runtime/agent/orchestrator/config.mjs +17 -1
- package/src/runtime/agent/orchestrator/context/collect.mjs +3 -0
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +72 -67
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +54 -1
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +3 -3
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +176 -72
- package/src/runtime/agent/orchestrator/mcp/client.mjs +19 -0
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +181 -133
- package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +42 -6
- package/src/runtime/agent/orchestrator/providers/anthropic-cache-warm.mjs +165 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +14 -14
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +145 -66
- package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +25 -3
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +64 -33
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +135 -87
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +123 -102
- package/src/runtime/agent/orchestrator/providers/cache-warm-admission.mjs +90 -0
- package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +25 -9
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +22 -13
- package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +17 -3
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +52 -10
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +8 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/npm-cli-version.mjs +11 -3
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +10 -9
- package/src/runtime/agent/orchestrator/providers/openai-ws-send/send-context.mjs +22 -3
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +43 -5
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/handshake-failure.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/stream-failure.mjs +6 -3
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +65 -1
- package/src/runtime/agent/orchestrator/providers/quota-reading.mjs +38 -12
- package/src/runtime/agent/orchestrator/providers/registry.mjs +26 -0
- package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +39 -7
- package/src/runtime/agent/orchestrator/providers/statusline-route-meta.mjs +6 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +12 -7
- package/src/runtime/agent/orchestrator/runtime-core/compaction-config-keys.mjs +62 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +37 -16
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +100 -23
- package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +2 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +19 -4
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +125 -30
- package/src/runtime/agent/orchestrator/session/cache-warm.mjs +792 -0
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +133 -22
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +475 -58
- package/src/runtime/agent/orchestrator/session/compaction-archive.mjs +42 -17
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +11 -5
- package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +0 -2
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -4
- package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +18 -22
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +32 -3
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +17 -3
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +7 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/after-hook.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +16 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +16 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -10
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +12 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +12 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +19 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +133 -90
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +31 -4
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +30 -18
- package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +23 -13
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +11 -2
- package/src/runtime/agent/orchestrator/session/manager/provider-replay.mjs +13 -0
- package/src/runtime/agent/orchestrator/session/manager/route-fallback-chain.mjs +129 -0
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +20 -2
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +7 -2
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +102 -15
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +18 -5
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +19 -8
- package/src/runtime/agent/orchestrator/session/prompt-cache-idle-gaps.mjs +113 -0
- package/src/runtime/agent/orchestrator/session/prompt-cache-touch-store.mjs +127 -0
- package/src/runtime/agent/orchestrator/session/routine-result.mjs +36 -9
- package/src/runtime/agent/orchestrator/session/sensitive-projection.mjs +100 -0
- package/src/runtime/agent/orchestrator/session/sensitive-values.mjs +257 -0
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +20 -7
- package/src/runtime/agent/orchestrator/session/side-question.mjs +18 -0
- package/src/runtime/agent/orchestrator/session/skill-update-notice.mjs +60 -0
- package/src/runtime/agent/orchestrator/session/store/live-state.mjs +6 -3
- package/src/runtime/agent/orchestrator/session/store/save-delta.mjs +9 -5
- package/src/runtime/agent/orchestrator/session/store/serialize.mjs +9 -8
- package/src/runtime/agent/orchestrator/session/store/session-persistence-events.mjs +29 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +8 -6
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +12 -2
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +44 -14
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +84 -3
- package/src/runtime/agent/orchestrator/session/stored-attachment-history.mjs +32 -0
- package/src/runtime/agent/orchestrator/session/thinking-binding.mjs +108 -0
- package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +18 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-status.mjs +9 -7
- package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-text.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/turn-failure.mjs +5 -1
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +5 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +12 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +240 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/shell-cwd.mjs +38 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +25 -5
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +65 -7
- package/src/runtime/agent/orchestrator/tools/builtin/shell-runtime.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +36 -13
- package/src/runtime/browser-bridge/action-schema.mjs +13 -2
- package/src/runtime/browser-bridge/client.mjs +73 -8
- package/src/runtime/browser-bridge/input-fields.mjs +8 -9
- package/src/runtime/browser-bridge/mail-links.mjs +107 -0
- package/src/runtime/browser-bridge/tool-defs.mjs +1 -1
- package/src/runtime/channels/lib/config.mjs +6 -61
- package/src/runtime/channels/lib/crash-log.mjs +1 -1
- package/src/runtime/channels/lib/event-pipeline.mjs +4 -19
- package/src/runtime/channels/lib/event-queue.mjs +3 -18
- package/src/runtime/channels/lib/owned-runtime/automation-services.mjs +2 -2
- package/src/runtime/channels/lib/owned-runtime/automation-start.mjs +3 -4
- package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +4 -59
- package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +33 -115
- package/src/runtime/channels/lib/owned-runtime/owned-stop.mjs +5 -22
- package/src/runtime/channels/lib/owned-runtime/state.mjs +2 -8
- package/src/runtime/channels/lib/owned-runtime.mjs +6 -23
- package/src/runtime/channels/lib/parent-bridge.mjs +2 -2
- package/src/runtime/channels/lib/runtime-paths.mjs +4 -43
- package/src/runtime/channels/lib/scheduler.mjs +33 -147
- package/src/runtime/channels/lib/schedules-db.mjs +34 -11
- package/src/runtime/channels/lib/status-snapshot.mjs +1 -1
- package/src/runtime/channels/lib/tool-dispatch.mjs +1 -2
- package/src/runtime/channels/lib/webhooks-db.mjs +5 -9
- package/src/runtime/channels/lib/worker-bootstrap.mjs +0 -1
- package/src/runtime/channels/lib/worker-ipc.mjs +0 -1
- package/src/runtime/channels/lib/worker-main.mjs +10 -34
- package/src/runtime/computer-bridge/action-schema.mjs +42 -1
- package/src/runtime/computer-bridge/actions.mjs +9 -1
- package/src/runtime/computer-bridge/client.mjs +180 -8
- package/src/runtime/computer-bridge/core-actions.mjs +2 -2
- package/src/runtime/computer-bridge/error-recovery.mjs +27 -2
- package/src/runtime/computer-bridge/linux-readiness.mjs +65 -23
- package/src/runtime/computer-bridge/pending-continuation.mjs +1 -1
- package/src/runtime/connectors/connector-accounts-mcp.mjs +230 -0
- package/src/runtime/connectors/gmail-app-password.mjs +172 -39
- package/src/runtime/connectors/google-mcp.mjs +10 -12
- package/src/runtime/memory/lib/pg/adapter.mjs +77 -70
- package/src/runtime/memory/lib/pg/supervisor.mjs +24 -12
- package/src/runtime/memory/lib/runtime-fetcher.mjs +23 -5
- package/src/runtime/session-search/session-search-db.mjs +73 -9
- package/src/runtime/session-search/session-search-ingest.mjs +110 -20
- package/src/runtime/shared/abort-race.mjs +89 -0
- package/src/runtime/shared/agent-avatar.d.mts +0 -1
- package/src/runtime/shared/agent-kind.mjs +4 -3
- package/src/runtime/shared/bounded-download.mjs +8 -3
- package/src/runtime/shared/config.mjs +2 -13
- package/src/runtime/shared/connector-accounts.mjs +20 -10
- package/src/runtime/shared/connector-catalog.d.mts +29 -0
- package/src/runtime/shared/connector-catalog.mjs +150 -0
- package/src/runtime/shared/connector-triggers.mjs +22 -19
- package/src/runtime/shared/defaults-separation.mjs +2 -14
- package/src/runtime/shared/delegated-approval-host.mjs +103 -11
- package/src/runtime/shared/err-text.mjs +24 -15
- package/src/runtime/shared/file-permissions.d.mts +0 -8
- package/src/runtime/shared/file-permissions.mjs +0 -11
- package/src/runtime/shared/git-direct.test-support.mjs +19 -0
- package/src/runtime/shared/heartbeat-interval.d.mts +4 -0
- package/src/runtime/shared/heartbeat-interval.mjs +19 -0
- package/src/runtime/shared/idle-auto-clear-gate.mjs +104 -0
- package/src/runtime/shared/llm/usage-rollup.mjs +1 -1
- package/src/runtime/shared/mixy-presence.mjs +22 -0
- package/src/runtime/shared/orchestration.d.mts +2 -0
- package/src/runtime/shared/pg-schema-db.mjs +27 -16
- package/src/runtime/shared/profile-config.cjs +1 -1
- package/src/runtime/shared/prompt-origin.d.mts +4 -0
- package/src/runtime/shared/prompt-origin.mjs +21 -0
- package/src/runtime/shared/provider-accounts.mjs +7 -1
- package/src/runtime/shared/provider-display-name.mjs +29 -0
- package/src/runtime/shared/provider-timeout-phase.mjs +2 -0
- package/src/runtime/shared/routine-trigger.d.mts +2 -0
- package/src/runtime/shared/routine-trigger.mjs +10 -0
- package/src/runtime/shared/sensitive-path-rules.d.mts +2 -10
- package/src/runtime/shared/sensitive-path-rules.mjs +19 -41
- package/src/runtime/shared/session-activity-signal.mjs +34 -1
- package/src/runtime/shared/session-sidebar-host.d.mts +1 -1
- package/src/runtime/shared/session-sidebar-host.mjs +7 -3
- package/src/runtime/shared/session-turn-prelude.mjs +18 -0
- package/src/runtime/shared/tool-result-summary.mjs +1 -14
- package/src/runtime/shared/worktrees/test-support.mjs +9 -4
- package/src/runtime/terminal-bridge/client.mjs +10 -1
- package/src/runtime/visualize-bridge/client.mjs +27 -8
- package/src/runtime/visualize-bridge/tool-defs.mjs +22 -8
- package/src/runtime/visualize-bridge/tool-meta.d.mts +5 -0
- package/src/runtime/visualize-bridge/tool-meta.mjs +22 -0
- package/src/runtime/web-search/lib/fetch-pipeline.mjs +2 -2
- package/src/session-runtime/agent-home-delivery.mjs +448 -185
- package/src/session-runtime/agent-task-sessions.mjs +329 -180
- package/src/session-runtime/boot/apis.mjs +9 -0
- package/src/session-runtime/boot/infrastructure.mjs +4 -0
- package/src/session-runtime/boot/providers.mjs +3 -0
- package/src/session-runtime/boot/tools.mjs +6 -1
- package/src/session-runtime/config-lifecycle.mjs +6 -0
- package/src/session-runtime/connector-merge-migration.mjs +305 -0
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +132 -28
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +2 -0
- package/src/session-runtime/lifecycle/inheritance.mjs +16 -3
- package/src/session-runtime/lifecycle/session-catalog.mjs +3 -1
- package/src/session-runtime/lifecycle/teardown/runtime-stops.mjs +50 -4
- package/src/session-runtime/lifecycle/teardown.mjs +23 -5
- package/src/session-runtime/mcp-glue/server-catalog.mjs +55 -3
- package/src/session-runtime/mcp-oauth-login.mjs +5 -3
- package/src/session-runtime/mixy-heartbeat.mjs +153 -33
- package/src/session-runtime/notification-bus.mjs +31 -117
- package/src/session-runtime/notification-completion-queue.mjs +54 -0
- package/src/session-runtime/notification-listeners.mjs +76 -0
- package/src/session-runtime/owned-automation-run.mjs +2 -1
- package/src/session-runtime/prewarm/channel-start.mjs +3 -7
- package/src/session-runtime/resource-mcp-api.mjs +143 -224
- package/src/session-runtime/resource-mcp-connector-accounts.mjs +163 -0
- package/src/session-runtime/resource-mcp-oauth-api.mjs +217 -0
- package/src/session-runtime/resource-mcp-secrets.mjs +82 -0
- package/src/session-runtime/resource-mcp-servers.mjs +78 -0
- package/src/session-runtime/resource-mcp-store.mjs +49 -0
- package/src/session-runtime/routine-owner.mjs +40 -9
- package/src/session-runtime/services/agent-tool/close-flow.mjs +3 -0
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +7 -2
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +1 -0
- package/src/session-runtime/services/agent-tool/worker-index/awaiting-user-sync.mjs +51 -0
- package/src/session-runtime/services/agent-tool/worker-index/disposal.mjs +55 -0
- package/src/session-runtime/services/agent-tool/worker-index/released-store.mjs +123 -0
- package/src/session-runtime/services/agent-tool/worker-index/restart-settlement.mjs +112 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-reads.mjs +36 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +17 -4
- package/src/session-runtime/services/agent-tool/worker-index/row-writes.mjs +58 -0
- package/src/session-runtime/services/agent-tool/worker-index.mjs +41 -241
- package/src/session-runtime/services/agent-tool/worker-rows.mjs +3 -0
- package/src/session-runtime/services/channel-admin.mjs +7 -13
- package/src/session-runtime/services/channel-session-router.mjs +4 -2
- package/src/session-runtime/services/seeds.mjs +0 -28
- package/src/session-runtime/session-compaction-sync.mjs +27 -0
- package/src/session-runtime/session-create/session-options.mjs +1 -0
- package/src/session-runtime/settings-builtin-tools-api.mjs +11 -0
- package/src/session-runtime/settings-compaction-api.mjs +2 -40
- package/src/session-runtime/settings-system-api.mjs +13 -1
- package/src/session-runtime/setup-tool/agent-settings-actions.mjs +65 -0
- package/src/session-runtime/setup-tool/executor.mjs +145 -22
- package/src/session-runtime/setup-tool/extended-actions.mjs +8 -3
- package/src/session-runtime/setup-tool/session-route-actions.mjs +152 -0
- package/src/session-runtime/setup-tool/settings-contract.mjs +4 -3
- package/src/session-runtime/setup-tool/tool-defs.mjs +64 -5
- package/src/session-runtime/tool-policy/agent-profile-fold.mjs +17 -13
- package/src/session-runtime/tool-policy/policy-stage.mjs +16 -2
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
- package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +4 -0
- package/src/standalone/channel-transport/client-registry/client-records.mjs +65 -0
- package/src/standalone/channel-transport/client-registry/client-registration.mjs +118 -0
- package/src/standalone/channel-transport/client-registry.mjs +24 -163
- package/src/standalone/channel-transport.mjs +1 -1
- package/src/standalone/daemon-channels-loader.mjs +10 -8
- package/src/standalone/daemon-session-control/list-page.mjs +72 -0
- package/src/standalone/daemon-session-control/request.mjs +51 -0
- package/src/standalone/daemon-session-control/room-host.mjs +57 -0
- package/src/standalone/daemon-session-control/route-control.mjs +48 -0
- package/src/standalone/daemon-session-control/send-turn.mjs +60 -0
- package/src/standalone/daemon-session-control/worktree-control.mjs +40 -0
- package/src/standalone/daemon-session-control.mjs +124 -188
- package/src/standalone/daemon.mjs +26 -3
- package/src/standalone/session-client.mjs +7 -3
- package/src/standalone/session-protocol.mjs +5 -0
- package/src/standalone/session-service/agent-tree/agent-child.mjs +1 -0
- package/src/standalone/session-service/quota-resume.mjs +3 -0
- package/src/standalone/session-service/retention/busy.mjs +65 -1
- package/src/standalone/session-service/session-calls/session-action.mjs +23 -2
- package/src/standalone/session-service/session-calls/session-views.mjs +8 -0
- package/src/standalone/session-tool-output.mjs +15 -7
- package/src/tui/app/model-options.mjs +3 -28
- package/src/tui/dist/index.mjs +58 -64
- package/src/tui/session/agent-job-feed/model-notification.mjs +3 -0
- package/src/tui/session/initial-state.mjs +3 -0
- package/src/tui/session/notice-surface.mjs +7 -1
- package/src/tui/session/queue-helpers.mjs +3 -42
- package/src/tui/session/session-api/routes-agent-definitions.mjs +14 -2
- package/src/tui/session/session-api/routes-write.mjs +5 -1
- package/src/tui/session/session-api/routes.mjs +1 -0
- package/src/tui/session/session-api/settings.mjs +17 -1
- package/src/tui/session/session-flow/auto-clear.mjs +4 -33
- package/src/tui/session/session-flow/drain-closed-queue.mjs +38 -0
- package/src/tui/session/session-flow/drain-enqueue.mjs +86 -0
- package/src/tui/session/session-flow/drain-retry.mjs +35 -0
- package/src/tui/session/session-flow/drain.mjs +118 -149
- package/src/tui/session/session-flow/queue/entry-shape.mjs +5 -0
- package/src/tui/session/session-flow/queue/take-entries.mjs +5 -2
- package/src/tui/session/tool-approval-delegation.mjs +64 -0
- package/src/tui/session/tool-approval-request.mjs +39 -0
- package/src/tui/session/tool-approval-settle.mjs +62 -0
- package/src/tui/session/tool-approval.mjs +69 -115
- package/src/tui/session/tui-steering-persist.mjs +8 -1
- package/src/tui/session/turn-stream.mjs +19 -2
- package/src/tui/session/turn.mjs +1 -0
- package/src/vendor/statusline/bin/statusline-route.mjs +1 -219
- package/src/vendor/statusline/src/gateway/route-meta.mjs +35 -13
- package/scripts/code-graph-description-contract.mjs +0 -188
- package/src/runtime/channels/lib/owned-runtime/ownership-refresh.mjs +0 -36
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
// to the older fields (httpStatus, responseFailed, providerError, SDK error
|
|
6
6
|
// bodies, RPC status strings). Message text is consulted only for untyped
|
|
7
7
|
// errors and only for unambiguous wordings.
|
|
8
|
+
import { TIMEOUT_PHASE, isFirstByteTimeout } from '../../../shared/provider-timeout-phase.mjs';
|
|
8
9
|
|
|
9
10
|
export const PROVIDER_ERROR_KINDS = Object.freeze([
|
|
10
11
|
'overloaded',
|
|
@@ -391,6 +392,13 @@ const CODE_KINDS = new Map(
|
|
|
391
392
|
}).flatMap(([kind, codes]) => codes.map((code) => [code, kind]))
|
|
392
393
|
);
|
|
393
394
|
const RESOURCE_EXHAUSTED = 'resource_exhausted';
|
|
395
|
+
|
|
396
|
+
/** True when `code` is one of the provider error codes this module classifies
|
|
397
|
+
* (rate/usage limits, quota, overload, server/transient, context length,
|
|
398
|
+
* model not found, auth, policy, …): a known vocabulary word, never free text. */
|
|
399
|
+
function isKnownProviderErrorCode(code) {
|
|
400
|
+
return typeof code === 'string' && (CODE_KINDS.has(code) || code === RESOURCE_EXHAUSTED);
|
|
401
|
+
}
|
|
394
402
|
// When several typed codes are present (an envelope type plus a specific
|
|
395
403
|
// code), the most specific verdict wins.
|
|
396
404
|
const KIND_RANK = [
|
|
@@ -435,7 +443,7 @@ const GATEWAY_ERROR_TYPE_CODES = Object.freeze({
|
|
|
435
443
|
});
|
|
436
444
|
|
|
437
445
|
/** The typed code a gateway `error_type` names, or null for an absent/unmapped one. */
|
|
438
|
-
|
|
446
|
+
function gatewayErrorTypeCode(errorType) {
|
|
439
447
|
const key = typeof errorType === 'string' ? errorType.trim().toLowerCase() : '';
|
|
440
448
|
return key && Object.hasOwn(GATEWAY_ERROR_TYPE_CODES, key) ? GATEWAY_ERROR_TYPE_CODES[key] : null;
|
|
441
449
|
}
|
|
@@ -718,6 +726,62 @@ export function providerErrorKind(err, options = {}) {
|
|
|
718
726
|
return describe(kind, code || undefined);
|
|
719
727
|
}
|
|
720
728
|
|
|
729
|
+
// ── Retry reason, without server text ───────────────────────────────────────
|
|
730
|
+
// A server error's free text can echo request content (prompt, tokens,
|
|
731
|
+
// account ids), so neither the retry trace nor the reconnect status carries
|
|
732
|
+
// it: only a fixed reason class derived from typed status/code, and a code
|
|
733
|
+
// only when it is a known provider error code (an identifier-shaped value can
|
|
734
|
+
// still be private, e.g. an account id in a `code` field).
|
|
735
|
+
const SERVER_ERROR_CODES = new Set([
|
|
736
|
+
'server_error',
|
|
737
|
+
'api_error',
|
|
738
|
+
'internal',
|
|
739
|
+
'internal_error',
|
|
740
|
+
'unavailable',
|
|
741
|
+
'service_unavailable',
|
|
742
|
+
]);
|
|
743
|
+
// Responses failure codes the WS retry classifier acts on beyond the shared
|
|
744
|
+
// provider vocabulary.
|
|
745
|
+
const WS_RETRY_ERROR_CODES = new Set(['auth_context_expired', 'auth_expired']);
|
|
746
|
+
|
|
747
|
+
/** The typed error code when it is a known provider error code; null otherwise. */
|
|
748
|
+
export function safeRetryErrorCode(err) {
|
|
749
|
+
const code = providerErrorKind(err).code;
|
|
750
|
+
return isKnownProviderErrorCode(code) || WS_RETRY_ERROR_CODES.has(code) ? code : null;
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
const STALL_ERROR_NAMES = new Set(['StreamStalledError', 'StreamStalledAbortError']);
|
|
754
|
+
|
|
755
|
+
/**
|
|
756
|
+
* One of rate_limited / overloaded / server_error / auth / first_response_timeout /
|
|
757
|
+
* stalled / other. The timeout classes read our own typed timeout stamps
|
|
758
|
+
* (name, code, timeoutPhase), never message text.
|
|
759
|
+
*/
|
|
760
|
+
export function retryReasonClass(err) {
|
|
761
|
+
const { kind, status } = providerErrorKind(err);
|
|
762
|
+
const code = safeRetryErrorCode(err);
|
|
763
|
+
if (kind === 'rate_limited' || kind === 'quota_exhausted' || status === 429) return 'rate_limited';
|
|
764
|
+
if (kind === 'overloaded' || status === 529) return 'overloaded';
|
|
765
|
+
if (kind === 'auth' || kind === 'permission' || status === 401 || status === 403) return 'auth';
|
|
766
|
+
// A token-refresh timeout is a sign-in problem, not a slow model.
|
|
767
|
+
if (err?.timeoutPhase === TIMEOUT_PHASE.AUTH) return 'auth';
|
|
768
|
+
if ((status >= 500 && status < 600) || (code && SERVER_ERROR_CODES.has(code))) return 'server_error';
|
|
769
|
+
if (err?.timeoutPhase === TIMEOUT_PHASE.IDLE || STALL_ERROR_NAMES.has(err?.name) || err?.code === 'ESTREAMSTALL') {
|
|
770
|
+
return 'stalled';
|
|
771
|
+
}
|
|
772
|
+
// `firstByteTimeout` is the stamp the Anthropic first-message and OpenAI
|
|
773
|
+
// WS/HTTP first-event watchdogs put on their errors.
|
|
774
|
+
if (
|
|
775
|
+
isFirstByteTimeout(err) ||
|
|
776
|
+
err?.firstByteTimeout === true ||
|
|
777
|
+
err?.name === 'ProviderTimeoutError' ||
|
|
778
|
+
err?.code === 'EPROVIDERTIMEOUT'
|
|
779
|
+
) {
|
|
780
|
+
return 'first_response_timeout';
|
|
781
|
+
}
|
|
782
|
+
return 'other';
|
|
783
|
+
}
|
|
784
|
+
|
|
721
785
|
/** Kinds whose refusal no wait or replay can change: quota, plan and billing. */
|
|
722
786
|
export const QUOTA_KINDS = new Set(['quota_exhausted', 'entitlement', 'billing']);
|
|
723
787
|
/** Kinds that are deterministic refusals of this request (never replayed as-is). */
|
|
@@ -13,6 +13,8 @@ import {
|
|
|
13
13
|
} from '../../../shared/provider-accounts.mjs';
|
|
14
14
|
import { fetchOAuthUsageSnapshot } from './oauth-usage.mjs';
|
|
15
15
|
import { getProvider } from './registry.mjs';
|
|
16
|
+
import { modelProxyClientMode } from '../../../shared/model-proxy-mode.mjs';
|
|
17
|
+
import { getModelProxyChannel } from './model-proxy-channel.mjs';
|
|
16
18
|
|
|
17
19
|
const forcedReading = (routeInfo, providerObj) =>
|
|
18
20
|
fetchOAuthUsageSnapshot(routeInfo, providerObj, () => {}, { force: true }).catch(() => null);
|
|
@@ -40,15 +42,15 @@ function readingServesModel(reading, model, useCredits) {
|
|
|
40
42
|
return measured.length > 0 && measured.every((window) => window.usedPct < 100);
|
|
41
43
|
}
|
|
42
44
|
|
|
43
|
-
|
|
45
|
+
/** The model-independent, account-wide measurement: one forced usage reading
|
|
46
|
+
* per roster account (or the single credential). Null for a provider that
|
|
47
|
+
* reports no exhausted quota. */
|
|
48
|
+
export async function measureProviderQuota(providerName, { provider } = {}) {
|
|
44
49
|
// Only an account-pooled provider reports exhausted quota at all.
|
|
45
|
-
if (!ACCOUNT_PROVIDERS.includes(providerName)) return
|
|
50
|
+
if (!ACCOUNT_PROVIDERS.includes(providerName)) return null;
|
|
51
|
+
if (provider === undefined) provider = getProvider(providerName);
|
|
46
52
|
const pool = readProviderAccountPool(providerName);
|
|
47
53
|
const useCredits = pool.useCredits === true;
|
|
48
|
-
// Only this reading counts as evidence: an account whose forced reading
|
|
49
|
-
// failed or measured nothing for this model stays exhausted however its
|
|
50
|
-
// older record reads; the pool's own choice (selection, blocks) decides
|
|
51
|
-
// among the rest.
|
|
52
54
|
if (pool.accounts.length > 0) {
|
|
53
55
|
const readings = await Promise.all(
|
|
54
56
|
pool.accounts.map((row) =>
|
|
@@ -58,13 +60,37 @@ export async function providerQuotaUsable(providerName, model = '', { provider =
|
|
|
58
60
|
)
|
|
59
61
|
)
|
|
60
62
|
);
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
return {
|
|
64
|
+
providerName,
|
|
65
|
+
useCredits,
|
|
66
|
+
accounts: pool.accounts.map((row, index) => ({ id: row.id, reading: readings[index] })),
|
|
67
|
+
};
|
|
66
68
|
}
|
|
67
69
|
// No roster: the single credential's fresh meter decides.
|
|
68
70
|
const reading = await forcedReading({ provider: providerName, model: '' }, provider);
|
|
69
|
-
return
|
|
71
|
+
return { providerName, useCredits, accounts: null, reading };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Whether `model` can be served per `measurement` (from measureProviderQuota).
|
|
75
|
+
* Only the measurement counts as evidence: an account whose forced reading
|
|
76
|
+
* failed or measured nothing for this model stays exhausted however its
|
|
77
|
+
* older record reads; the pool's own choice (selection, blocks) decides
|
|
78
|
+
* among the rest. */
|
|
79
|
+
export function quotaMeasurementServesModel(measurement, model = '') {
|
|
80
|
+
if (!measurement) return true;
|
|
81
|
+
const { providerName, useCredits, accounts } = measurement;
|
|
82
|
+
if (!accounts) return readingServesModel(measurement.reading, model, useCredits);
|
|
83
|
+
const unproven = new Set(
|
|
84
|
+
accounts.filter((row) => !readingServesModel(row.reading, model, useCredits)).map((row) => row.id)
|
|
85
|
+
);
|
|
86
|
+
if (unproven.size === accounts.length) return false;
|
|
87
|
+
return chooseProviderAccount(readProviderAccountPool(providerName), unproven, Date.now(), model) !== null;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export async function providerQuotaUsable(providerName, model = '', { provider } = {}) {
|
|
91
|
+
// The PC owns the accounts in proxy mode; do not resolve a server provider.
|
|
92
|
+
if (modelProxyClientMode()) {
|
|
93
|
+
return (await getModelProxyChannel().request({ provider: providerName, method: 'quotaUsable', model })) === true;
|
|
94
|
+
}
|
|
95
|
+
return quotaMeasurementServesModel(await measureProviderQuota(providerName, { provider }), model);
|
|
70
96
|
}
|
|
@@ -70,6 +70,17 @@ let _initChain = Promise.resolve();
|
|
|
70
70
|
let _inFlightPromise = null;
|
|
71
71
|
let _inFlightSig = null;
|
|
72
72
|
let _lastAppliedSig = null;
|
|
73
|
+
// Settles when an initialization by the owning runtime first applies.
|
|
74
|
+
let _markProvidersInitialized;
|
|
75
|
+
const _providersInitialized = new Promise((resolve) => {
|
|
76
|
+
_markProvidersInitialized = resolve;
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
/** Read-only readiness: resolves once the owning runtime's provider
|
|
80
|
+
* initialization has applied a config (never starts one). */
|
|
81
|
+
export function providersInitialized() {
|
|
82
|
+
return _providersInitialized;
|
|
83
|
+
}
|
|
73
84
|
// Provider instances are process-global inside the daemon. Catalog
|
|
74
85
|
// readers use this revision to share one raw model snapshot while still
|
|
75
86
|
// rebuilding their cheap route/config projection after auth/config changes.
|
|
@@ -223,7 +234,14 @@ async function instantiateProvider(name, Ctor, cfg, proxyChannel = null) {
|
|
|
223
234
|
return createAccountPoolProvider(name, () => wrapProviderAdmission(new Ctor(cfg), name));
|
|
224
235
|
}
|
|
225
236
|
|
|
237
|
+
let _initProvidersCalls = 0;
|
|
238
|
+
/** Test seam: how many times initProviders was called in this process. */
|
|
239
|
+
export function _initProvidersCallCountForTest() {
|
|
240
|
+
return _initProvidersCalls;
|
|
241
|
+
}
|
|
242
|
+
|
|
226
243
|
export async function initProviders(config, { signal = null } = {}) {
|
|
244
|
+
_initProvidersCalls += 1;
|
|
227
245
|
throwIfAborted(signal);
|
|
228
246
|
// Remote mode: provider availability and config are the PC's, never this
|
|
229
247
|
// server's credential probes. No connected client fails here, clearly.
|
|
@@ -263,6 +281,7 @@ export async function initProviders(config, { signal = null } = {}) {
|
|
|
263
281
|
if (_lastAppliedSig !== sig) _providerCatalogRevision += 1;
|
|
264
282
|
_lastAppliedSig = sig;
|
|
265
283
|
settle();
|
|
284
|
+
_markProvidersInitialized();
|
|
266
285
|
return v;
|
|
267
286
|
},
|
|
268
287
|
(err) => {
|
|
@@ -452,6 +471,13 @@ function _scheduleOAuthSelfHeal(name) {
|
|
|
452
471
|
// by its replacement account. When that account is not connected the lookup
|
|
453
472
|
// misses like any other unconnected provider.
|
|
454
473
|
const RETIRED_PROVIDER_ALIASES = Object.freeze({ 'opencode-go': 'opencode-go-oauth' });
|
|
474
|
+
|
|
475
|
+
/** The instance registered under `name` right now, or null — a read-only
|
|
476
|
+
* lookup (no lazy registration, unlike getProvider). */
|
|
477
|
+
export function registeredProvider(name) {
|
|
478
|
+
return providers.get(name) || null;
|
|
479
|
+
}
|
|
480
|
+
|
|
455
481
|
export function getProvider(requestedName) {
|
|
456
482
|
const name = Object.hasOwn(RETIRED_PROVIDER_ALIASES, requestedName)
|
|
457
483
|
? RETIRED_PROVIDER_ALIASES[requestedName]
|
|
@@ -4,7 +4,7 @@ import { PROVIDER_RETRY_JITTER_RATIO, createTimeoutSignal } from '../stall-polic
|
|
|
4
4
|
import { readStreamOutcome } from './lib/stream-outcome.mjs';
|
|
5
5
|
import { recycleLlmDispatcher } from '../../../shared/llm/http-agent.mjs';
|
|
6
6
|
import { noteErrorUsage } from './lib/note-error-usage.mjs';
|
|
7
|
-
import {
|
|
7
|
+
import { retryStatusLine, retryTimeoutText } from '../../../shared/err-text.mjs';
|
|
8
8
|
import {
|
|
9
9
|
TERMINAL_EDGE_STATUSES,
|
|
10
10
|
boundedCauseChain,
|
|
@@ -13,7 +13,14 @@ import {
|
|
|
13
13
|
isToolInputCut,
|
|
14
14
|
retryAfterMsFromError,
|
|
15
15
|
} from './retry-classification.mjs';
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
DETERMINISTIC_KINDS,
|
|
18
|
+
QUOTA_KINDS,
|
|
19
|
+
errorHeaderValue,
|
|
20
|
+
providerErrorKind,
|
|
21
|
+
retryReasonClass,
|
|
22
|
+
safeRetryErrorCode,
|
|
23
|
+
} from './provider-error-kind.mjs';
|
|
17
24
|
import { adviceGatedRetry } from './retry-midstream.mjs';
|
|
18
25
|
import {
|
|
19
26
|
ModelFallbackTriggeredError,
|
|
@@ -35,7 +42,9 @@ export function createStreamSafetyStamps() {
|
|
|
35
42
|
try {
|
|
36
43
|
e.liveTextEmitted = true;
|
|
37
44
|
e.unsafeToRetry = true;
|
|
38
|
-
} catch {
|
|
45
|
+
} catch {
|
|
46
|
+
// the error object may be frozen; the live-text stamp is advisory
|
|
47
|
+
}
|
|
39
48
|
}
|
|
40
49
|
return e;
|
|
41
50
|
};
|
|
@@ -44,7 +53,9 @@ export function createStreamSafetyStamps() {
|
|
|
44
53
|
try {
|
|
45
54
|
e.emittedToolCall = true;
|
|
46
55
|
e.unsafeToRetry = true;
|
|
47
|
-
} catch {
|
|
56
|
+
} catch {
|
|
57
|
+
// the error object may be frozen; the tool-call stamp is advisory
|
|
58
|
+
}
|
|
48
59
|
}
|
|
49
60
|
return e;
|
|
50
61
|
};
|
|
@@ -313,6 +324,19 @@ function retryWaitMs(
|
|
|
313
324
|
return retryAfterJitterRatio > 0 ? jitterDelayMs(wait, retryAfterJitterRatio, 'positive') : wait;
|
|
314
325
|
}
|
|
315
326
|
|
|
327
|
+
/** Fixed status phrases for a caller-classified retry reason. */
|
|
328
|
+
const RETRY_REASON_TEXT = Object.freeze({
|
|
329
|
+
rate_limited: 'Rate limited by the provider',
|
|
330
|
+
overloaded: 'Provider overloaded',
|
|
331
|
+
server_error: 'Provider server error',
|
|
332
|
+
auth: 'Provider rejected the sign-in',
|
|
333
|
+
other: 'Connection interrupted',
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
// Timeout classes read our own typed timeout stamps (retryTimeoutText), so
|
|
337
|
+
// their phrases carry the wait window.
|
|
338
|
+
const TIMEOUT_REASON_CLASSES = new Set(['first_response_timeout', 'stalled']);
|
|
339
|
+
|
|
316
340
|
/**
|
|
317
341
|
* Display-only 'reconnecting' stage for one retry wait, so it reads as a
|
|
318
342
|
* reconnect instead of a silent spinner. `attempt` is the attempt about to run
|
|
@@ -321,20 +345,28 @@ function retryWaitMs(
|
|
|
321
345
|
*/
|
|
322
346
|
export function emitProviderRetryStage(
|
|
323
347
|
onStageChange,
|
|
324
|
-
{ attempt, maxAttempts, lastErr, delayMs, classifier = null, extra = null }
|
|
348
|
+
{ attempt, maxAttempts, lastErr, delayMs, classifier = null, extra = null, reasonClass = null, providerLabel = null }
|
|
325
349
|
) {
|
|
326
350
|
if (typeof onStageChange !== 'function') return;
|
|
327
351
|
try {
|
|
328
|
-
|
|
352
|
+
// The reason is a fixed phrase for a class (the caller's, else derived from
|
|
353
|
+
// the error's typed status/code), never the error's own text; an
|
|
354
|
+
// unrecognized class reads as `other`.
|
|
355
|
+
const cls = reasonClass == null ? retryReasonClass(lastErr) : reasonClass;
|
|
356
|
+
const fixedClass = Object.hasOwn(RETRY_REASON_TEXT, cls) || TIMEOUT_REASON_CLASSES.has(cls) ? cls : 'other';
|
|
357
|
+
const reason = TIMEOUT_REASON_CLASSES.has(fixedClass)
|
|
358
|
+
? retryTimeoutText(lastErr, fixedClass, providerLabel)
|
|
359
|
+
: RETRY_REASON_TEXT[fixedClass];
|
|
329
360
|
const waitMs = Math.max(0, Number(delayMs) || 0);
|
|
330
361
|
onStageChange('reconnecting', {
|
|
331
362
|
...extra,
|
|
363
|
+
reasonClass: fixedClass,
|
|
332
364
|
attempt,
|
|
333
365
|
max: maxAttempts,
|
|
334
366
|
waitMs,
|
|
335
367
|
retryAt: Date.now() + waitMs,
|
|
336
368
|
reason,
|
|
337
|
-
classifier: classifier || lastErr?.retryClassifier || lastErr
|
|
369
|
+
classifier: classifier || lastErr?.retryClassifier || safeRetryErrorCode(lastErr),
|
|
338
370
|
message: retryStatusLine({ reason, attempt, maxAttempts, delayMs: waitMs }),
|
|
339
371
|
});
|
|
340
372
|
} catch {
|
|
@@ -34,6 +34,12 @@ export function recordGatewayUsageEvent(summary) {
|
|
|
34
34
|
return requireRouteMeta().recordGatewayUsageEvent(summary);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
/** Resolves once every recorded usage event has been written; nothing was
|
|
38
|
+
* recorded while the module is not loaded. */
|
|
39
|
+
export function settleGatewayUsageWrites() {
|
|
40
|
+
return routeMeta ? routeMeta.settleGatewayUsageWrites() : Promise.resolve();
|
|
41
|
+
}
|
|
42
|
+
|
|
37
43
|
export function summarizeGatewayUsage(routeInfo, providerOut, compact = null, durationMs = null) {
|
|
38
44
|
return requireRouteMeta().summarizeGatewayUsage(routeInfo, providerOut, compact, durationMs);
|
|
39
45
|
}
|
|
@@ -8,9 +8,9 @@ export const ASK_USER_TOOL_DEFS = Object.freeze([
|
|
|
8
8
|
name: 'ask_user',
|
|
9
9
|
title: 'Ask User',
|
|
10
10
|
trigger:
|
|
11
|
-
'Ask the user 1–4 multiple-choice questions and wait; when a plan needs the user to pick between clear options, instead of listing them in chat.',
|
|
11
|
+
'Ask the user 1–4 multiple-choice questions and wait; when a plan needs the user to pick between clear options, instead of listing them in chat. Also hands the user a page or app step (CAPTCHA, sign-in, 2FA, a secret).',
|
|
12
12
|
description:
|
|
13
|
-
'Ask the user multiple-choice questions and wait. Only for a decision only the user can make, with clear options; never for minor choices or approval of requested work, and open questions go in chat. Do not repeat the options in your message.',
|
|
13
|
+
'Ask the user multiple-choice questions and wait. Only for a decision only the user can make, with clear options; never for minor choices or approval of requested work, and open questions go in chat. Do not repeat the options in your message. A step only the user can do on a page or app (CAPTCHA, human check, sign-in, 2FA, a password) is a handoff here, never a request in plain chat.',
|
|
14
14
|
annotations: {
|
|
15
15
|
title: 'Ask User',
|
|
16
16
|
readOnlyHint: true,
|
|
@@ -55,7 +55,7 @@ export const ASK_USER_TOOL_DEFS = Object.freeze([
|
|
|
55
55
|
handoff: {
|
|
56
56
|
type: 'object',
|
|
57
57
|
description:
|
|
58
|
-
'Instead of questions: secret = the user types a password
|
|
58
|
+
'Instead of questions: secret = the user types a password, sign-in, new password or one-time code into that field of the page (you never see it; result entered/user_skipped/no_field/page_changed/blocked/expired); takeover = the user does a step (sign-in, CAPTCHA, 2FA) and says done.',
|
|
59
59
|
properties: {
|
|
60
60
|
kind: { type: 'string', enum: ['secret', 'takeover'] },
|
|
61
61
|
surface: { type: 'string', enum: ['browser', 'computer'] },
|
|
@@ -74,8 +74,9 @@ export const ASK_USER_TOOL_DEFS = Object.freeze([
|
|
|
74
74
|
description: 'browser takeover: login = sign-in window on url.',
|
|
75
75
|
},
|
|
76
76
|
url: { type: 'string', maxLength: 2048, description: 'login: sign-in page (https).' },
|
|
77
|
-
tab: { type: 'string', maxLength: 64, description: 'browser
|
|
78
|
-
window_id: { type: 'string', maxLength: 128, description: 'computer
|
|
77
|
+
tab: { type: 'string', maxLength: 64, description: 'browser: page ID from list_tabs.' },
|
|
78
|
+
window_id: { type: 'string', maxLength: 128, description: 'computer: exact window id (secret: required).' },
|
|
79
|
+
ref: { type: 'string', maxLength: 64, description: 'computer secret: field ref (required).' },
|
|
79
80
|
app: { type: 'string', maxLength: 120, description: 'computer takeover: app name.' },
|
|
80
81
|
},
|
|
81
82
|
required: ['kind', 'surface'],
|
|
@@ -106,13 +107,16 @@ export function validateAskUserHandoff(args) {
|
|
|
106
107
|
const login = handoffLogin(handoff);
|
|
107
108
|
let need = login ? 'sign_in' : 'action';
|
|
108
109
|
if (['sign_in', 'action', 'confirmation'].includes(handoff.need)) need = handoff.need;
|
|
110
|
+
const loginField = login ? { login } : {};
|
|
109
111
|
return {
|
|
110
112
|
kind: handoff.kind,
|
|
111
113
|
surface: handoff.surface,
|
|
112
114
|
target: text('target', 200),
|
|
113
115
|
field: text('field', 80),
|
|
114
116
|
instructions: text('instructions', 2000),
|
|
115
|
-
|
|
117
|
+
// A secret is bound to its page (browser tab) or window and field (computer).
|
|
118
|
+
identity: handoffIdentity(handoff),
|
|
119
|
+
...(handoff.kind === 'takeover' ? { need, ...loginField } : {}),
|
|
116
120
|
};
|
|
117
121
|
}
|
|
118
122
|
|
|
@@ -149,7 +153,8 @@ function handoffIdentity(handoff) {
|
|
|
149
153
|
.trim()
|
|
150
154
|
.slice(0, 120)
|
|
151
155
|
: '';
|
|
152
|
-
|
|
156
|
+
const ref = handoff.kind === 'secret' ? token('ref', 64) : '';
|
|
157
|
+
return { ...(windowId ? { windowId } : {}), ...(app ? { app } : {}), ...(ref ? { ref } : {}) };
|
|
153
158
|
}
|
|
154
159
|
|
|
155
160
|
/** Throws a clear error when the questions are malformed; returns the list. */
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// The fields of `session.compaction` that the saved global config owns, as
|
|
2
|
+
// opposed to the per-session state (archive, thresholds, outcome telemetry)
|
|
3
|
+
// the session owns. Shared by the config sync and by the compaction commit, so
|
|
4
|
+
// a commit that finishes after a reload never writes back a stale config value.
|
|
5
|
+
import { RETIRED_COMPACTION_FIELDS } from '../config-storage.mjs';
|
|
6
|
+
import { normalizeCompactionConfig } from './config-helpers.mjs';
|
|
7
|
+
|
|
8
|
+
// Every spelling of the main-context buffer budget; a new representation
|
|
9
|
+
// replaces the previous one.
|
|
10
|
+
export const MAIN_BUFFER_KEYS = [
|
|
11
|
+
'mainBufferTokens',
|
|
12
|
+
'mainBuffer',
|
|
13
|
+
'mainBufferPercent',
|
|
14
|
+
'mainBufferPct',
|
|
15
|
+
'mainBufferRatio',
|
|
16
|
+
'mainBufferFraction',
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
// Everything the normalizer emits for an empty config, the retired aliases it
|
|
20
|
+
// folds away, and every setting a session record is seeded from the config
|
|
21
|
+
// (session-record.mjs initialCompactionConfig). A field the config no longer
|
|
22
|
+
// sets is cleared so the session falls back to the default.
|
|
23
|
+
export const COMPACTION_CONFIG_KEYS = Object.freeze([
|
|
24
|
+
...Object.keys(normalizeCompactionConfig({})),
|
|
25
|
+
...RETIRED_COMPACTION_FIELDS,
|
|
26
|
+
'enabled',
|
|
27
|
+
'useMaintainer',
|
|
28
|
+
'model',
|
|
29
|
+
'summaryModel',
|
|
30
|
+
'timeoutMs',
|
|
31
|
+
'memoryTimeoutMs',
|
|
32
|
+
'buffer',
|
|
33
|
+
'bufferTokens',
|
|
34
|
+
'reservedTokens',
|
|
35
|
+
'bufferPercent',
|
|
36
|
+
'bufferPct',
|
|
37
|
+
'bufferRatio',
|
|
38
|
+
'bufferFraction',
|
|
39
|
+
...MAIN_BUFFER_KEYS,
|
|
40
|
+
]);
|
|
41
|
+
|
|
42
|
+
// The resolved buffer is the plan's own measurement, recorded on every compact
|
|
43
|
+
// pass, so for the writers below it is telemetry and not a setting.
|
|
44
|
+
const RESOLVED_BUFFER_KEYS = new Set(['bufferTokens', 'bufferRatio']);
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The `session.compaction` record a compaction writer produces: the live record
|
|
48
|
+
* plus its own outcome telemetry. Config-owned fields always come from the
|
|
49
|
+
* live record, never from the policy or the plan the writer started with: a
|
|
50
|
+
* reload that landed while the compaction was running (auto turned off, a
|
|
51
|
+
* model removed) must not be undone by the write that follows it.
|
|
52
|
+
*/
|
|
53
|
+
export function withLiveCompactionConfig(live, telemetry) {
|
|
54
|
+
const record = { ...live, auto: live.auto !== false, ...telemetry };
|
|
55
|
+
for (const key of COMPACTION_CONFIG_KEYS) {
|
|
56
|
+
if (key === 'auto' || RESOLVED_BUFFER_KEYS.has(key)) continue;
|
|
57
|
+
if (Object.hasOwn(live, key)) record[key] = live[key];
|
|
58
|
+
else delete record[key];
|
|
59
|
+
}
|
|
60
|
+
record.auto = live.auto !== false;
|
|
61
|
+
return record;
|
|
62
|
+
}
|
|
@@ -78,6 +78,14 @@ function resolveAutoEffort({ autoEffort, saved, preset = null }) {
|
|
|
78
78
|
return preset?.autoEffort !== false;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
/** The route's context percent: an explicit request, else the saved choice
|
|
82
|
+
* (read lazily) unless an exact token selection replaced it. */
|
|
83
|
+
function resolveContextPercent({ hasExplicitContextPercent, contextPercent, keepsSavedPercent, savedPercent }) {
|
|
84
|
+
if (hasExplicitContextPercent) return cleanContextPercent(contextPercent);
|
|
85
|
+
if (keepsSavedPercent) return cleanContextPercent(savedPercent());
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
|
|
81
89
|
export function makeResolveRoute(resolveDefaultProvider) {
|
|
82
90
|
return function resolveRoute(
|
|
83
91
|
config,
|
|
@@ -119,11 +127,12 @@ export function makeResolveRoute(resolveDefaultProvider) {
|
|
|
119
127
|
modelParameters: hasExplicitModelParameters
|
|
120
128
|
? cleanModelParameters(modelParameters)
|
|
121
129
|
: cleanModelParameters(saved.modelParameters ?? preset.modelParameters),
|
|
122
|
-
contextPercent:
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
130
|
+
contextPercent: resolveContextPercent({
|
|
131
|
+
hasExplicitContextPercent,
|
|
132
|
+
contextPercent,
|
|
133
|
+
keepsSavedPercent,
|
|
134
|
+
savedPercent: () => saved.contextPercent ?? preset.contextPercent,
|
|
135
|
+
}),
|
|
127
136
|
...(tokens ? { contextTokens: tokens } : {}),
|
|
128
137
|
};
|
|
129
138
|
}
|
|
@@ -144,11 +153,12 @@ export function makeResolveRoute(resolveDefaultProvider) {
|
|
|
144
153
|
modelParameters: hasExplicitModelParameters
|
|
145
154
|
? cleanModelParameters(modelParameters)
|
|
146
155
|
: cleanModelParameters(saved.modelParameters),
|
|
147
|
-
contextPercent:
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
156
|
+
contextPercent: resolveContextPercent({
|
|
157
|
+
hasExplicitContextPercent,
|
|
158
|
+
contextPercent,
|
|
159
|
+
keepsSavedPercent,
|
|
160
|
+
savedPercent: () => saved.contextPercent,
|
|
161
|
+
}),
|
|
152
162
|
...(tokens ? { contextTokens: tokens } : {}),
|
|
153
163
|
};
|
|
154
164
|
};
|
|
@@ -231,7 +241,7 @@ const AGENT_TERMINAL_REAP_MS = Object.freeze({ 'openai-oauth': 60 * 60 * 1000 })
|
|
|
231
241
|
|
|
232
242
|
/** A stored/requested idle value: AUTO_CLEAR_UNLIMITED, a window ≥ 1 min, or
|
|
233
243
|
* null when absent or invalid. */
|
|
234
|
-
|
|
244
|
+
function normalizeAutoClearIdleValue(value) {
|
|
235
245
|
if (value === null || value === undefined || typeof value === 'boolean') return null;
|
|
236
246
|
if (typeof value === 'string') {
|
|
237
247
|
const text = value.trim().toLowerCase();
|
|
@@ -290,11 +300,11 @@ export function autoClearProviderDefaults(providerIdleMs = null, extraProviders
|
|
|
290
300
|
const builtIn = Object.hasOwn(AUTO_CLEAR_PROVIDER_IDLE_MS, provider)
|
|
291
301
|
? AUTO_CLEAR_PROVIDER_IDLE_MS[provider]
|
|
292
302
|
: AUTO_CLEAR_PROVIDER_IDLE_MS.default;
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
303
|
+
let idleMs;
|
|
304
|
+
if (Object.hasOwn(overrides, provider)) idleMs = resolvedIdleMs(overrides[provider]);
|
|
305
|
+
else if (provider === 'default' || Object.hasOwn(AUTO_CLEAR_PROVIDER_IDLE_MS, provider)) {
|
|
306
|
+
idleMs = resolvedIdleMs(builtIn);
|
|
307
|
+
} else idleMs = autoClearIdleMsForProvider(provider, overrides);
|
|
298
308
|
return {
|
|
299
309
|
provider,
|
|
300
310
|
idleMs,
|
|
@@ -338,6 +348,17 @@ export function resolveAutoClearIdleMs(config, provider) {
|
|
|
338
348
|
return autoClearIdleMsForProvider(provider, raw.providerIdleMs);
|
|
339
349
|
}
|
|
340
350
|
|
|
351
|
+
/** The idle auto-clear gate's settings for a thread on `provider`
|
|
352
|
+
* (idle-auto-clear-gate.mjs): `{ enabled, idleMs, minContextPercent }`. */
|
|
353
|
+
function autoClearGateSettings(config, provider) {
|
|
354
|
+
const normalized = normalizeAutoClearConfig(config?.autoClear);
|
|
355
|
+
return {
|
|
356
|
+
enabled: normalized.enabled,
|
|
357
|
+
idleMs: resolveAutoClearIdleMs(config, provider),
|
|
358
|
+
minContextPercent: normalized.minContextPercent,
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
|
|
341
362
|
export function normalizeSystemShellConfig(value = {}) {
|
|
342
363
|
const raw = value && typeof value === 'object' ? value : {};
|
|
343
364
|
const command = clean(raw.command);
|