mixdog 1.3.1 → 1.3.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 +8 -4
- package/package.json +2 -2
- package/scripts/native-release-status.mjs +238 -0
- package/src/defaults/shipped-history.json +5 -1
- package/src/defaults/skills/pptx/scripts/qc-pages.mjs +3 -2
- package/src/defaults/skills/setup/SKILL.md +23 -1
- package/src/defaults/skills/setup/references/actions.md +50 -3
- package/src/defaults/skills/setup/references/surfaces.md +23 -3
- package/src/defaults/skills/setup-guide/SKILL.md +7 -3
- package/src/defaults/skills/visualize/SKILL.md +9 -6
- package/src/defaults/skills/visualize/references/craft.md +8 -1
- package/src/help.mjs +1 -1
- package/src/lib/keychain-cjs.cjs +4 -1
- package/src/lib/rules-builder.cjs +14 -7
- package/src/rules/agent-mode/AGENT_MODE.md +8 -5
- package/src/rules/agent-mode/MIXY.md +6 -8
- package/src/rules/lead/LEAD.md +2 -2
- package/src/rules/shared/10-tool-workflow.md +4 -0
- package/src/rules/shared/20-research.md +2 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +5 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/session-prep.mjs +8 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +6 -1
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +114 -26
- package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +8 -0
- package/src/runtime/agent/orchestrator/agent-runtime/room-supervisor-completion.mjs +5 -4
- package/src/runtime/agent/orchestrator/agent-trace.mjs +3 -0
- package/src/runtime/agent/orchestrator/cache-break-trace.mjs +4 -0
- package/src/runtime/agent/orchestrator/config-presets.mjs +2 -0
- package/src/runtime/agent/orchestrator/config-storage.mjs +10 -3
- package/src/runtime/agent/orchestrator/config.mjs +11 -0
- package/src/runtime/agent/orchestrator/context/role-instructions.mjs +9 -2
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +97 -5
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +6 -10
- package/src/runtime/agent/orchestrator/mcp/client.mjs +7 -4
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +80 -31
- package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +67 -38
- package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +6 -2
- package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +27 -8
- package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +31 -4
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +11 -8
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-prefix-trace.mjs +76 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +16 -0
- package/src/runtime/agent/orchestrator/providers/lib/tail-reminder-split.mjs +13 -0
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +16 -1
- package/src/runtime/agent/orchestrator/providers/mixdog-local.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +5 -5
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +9 -5
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +9 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +30 -3
- package/src/runtime/agent/orchestrator/providers/openai-model-capabilities.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +61 -8
- package/src/runtime/agent/orchestrator/providers/registry.mjs +9 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +90 -24
- package/src/runtime/agent/orchestrator/runtime-core/fs-utils.mjs +8 -1
- package/src/runtime/agent/orchestrator/runtime-core/goal-mutations.mjs +1 -1
- package/src/runtime/agent/orchestrator/runtime-core/goal-storage.mjs +68 -22
- package/src/runtime/agent/orchestrator/runtime-core/goal-tool-exec.mjs +1 -1
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +4 -6
- package/src/runtime/agent/orchestrator/runtime-core/route-context-state.mjs +81 -0
- package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +2 -1
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +12 -1
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +6 -5
- package/src/runtime/agent/orchestrator/runtime-core/workflow/agents.mjs +7 -6
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +1 -1
- package/src/runtime/agent/orchestrator/runtime-core/workflow/packs.mjs +8 -4
- package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/agent-mode.mjs +0 -6
- package/src/runtime/agent/orchestrator/session/agent-room-supervisor.d.mts +1 -1
- package/src/runtime/agent/orchestrator/session/agent-room-supervisor.mjs +22 -4
- package/src/runtime/agent/orchestrator/session/agent-room.d.mts +17 -2
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +133 -38
- package/src/runtime/agent/orchestrator/session/attachment-preflight.mjs +80 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +14 -11
- package/src/runtime/agent/orchestrator/session/compact/forked-summary.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +68 -18
- package/src/runtime/agent/orchestrator/session/compact/summary-mode.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/compact/summary-route.mjs +87 -0
- package/src/runtime/agent/orchestrator/session/compact/summary.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/compact/text-utils.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +41 -10
- package/src/runtime/agent/orchestrator/session/human-gate/delegation.mjs +230 -0
- package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +136 -32
- package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +20 -0
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +21 -9
- package/src/runtime/agent/orchestrator/session/human-gate/run-policy.mjs +73 -0
- package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +55 -27
- package/src/runtime/agent/orchestrator/session/human-gate/unattended-port.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +189 -105
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +5 -5
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +38 -5
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +21 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +12 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +11 -5
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +13 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +44 -18
- package/src/runtime/agent/orchestrator/session/manager/orchestration-mode-switch-notice.mjs +99 -0
- package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +42 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +3 -9
- package/src/runtime/agent/orchestrator/session/manager/pending-spool-file.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/pending-spool-shard.mjs +5 -3
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +40 -1
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +12 -0
- package/src/runtime/agent/orchestrator/session/manager/runtime-state.mjs +20 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +55 -27
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +3 -8
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +12 -1
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +6 -15
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +24 -8
- package/src/runtime/agent/orchestrator/session/manager/workflow-switch-notice.mjs +94 -13
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +42 -10
- package/src/runtime/agent/orchestrator/session/provider-prefix-guard.mjs +21 -3
- package/src/runtime/agent/orchestrator/session/routine-result.d.mts +18 -3
- package/src/runtime/agent/orchestrator/session/routine-result.mjs +120 -9
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/store/canonical-reader.mjs +41 -7
- package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +10 -2
- package/src/runtime/agent/orchestrator/session/store/load-cache.mjs +14 -2
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +15 -1
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-record.mjs +8 -3
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +36 -1
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +40 -5
- package/src/runtime/agent/orchestrator/session/store-summary-last-message.mjs +47 -2
- package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +125 -0
- package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +78 -43
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +35 -5
- package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +42 -2
- package/src/runtime/agent/orchestrator/tools/builtin/advisory-lock.mjs +35 -13
- package/src/runtime/agent/orchestrator/tools/builtin/atomic-write.mjs +25 -5
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +4 -3
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +13 -14
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/transport-artifacts.mjs +9 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +19 -14
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +6 -14
- package/src/runtime/agent/orchestrator/tools/builtin/pdf-test-fixtures.mjs +5 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-image.mjs +4 -2
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-media.mjs +47 -2
- package/src/runtime/agent/orchestrator/tools/builtin/read-special-files.mjs +264 -87
- package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +10 -4
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +34 -21
- package/src/runtime/agent/orchestrator/tools/code-graph/constants.mjs +8 -4
- package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +9 -30
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +24 -12
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +3 -2
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/patch/delete-quarantine.mjs +2 -1
- package/src/runtime/agent/orchestrator/tools/patch/replay-capture.mjs +4 -2
- package/src/runtime/agent/orchestrator/tools/patch/rollback-state.mjs +33 -2
- package/src/runtime/agent/orchestrator/tools/patch-manifest.json +13 -13
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +5 -3
- package/src/runtime/agent/orchestrator/tools/shell-exec-output.mjs +3 -1
- package/src/runtime/attachments/attachment-reference.mjs +155 -0
- package/src/runtime/attachments/limits.mjs +5 -1
- package/src/runtime/attachments/office-extract.mjs +3 -6
- package/src/runtime/attachments/pdf-extract.mjs +84 -10
- package/src/runtime/attachments/store.mjs +49 -30
- package/src/runtime/browser-bridge/client.mjs +73 -20
- package/src/runtime/channels/lib/runtime-paths.mjs +1 -1
- package/src/runtime/channels/lib/scheduler.mjs +14 -7
- package/src/runtime/channels/lib/state-file.mjs +15 -15
- package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +14 -13
- package/src/runtime/channels/lib/webhook/relay-tunnel.mjs +22 -18
- package/src/runtime/channels/lib/webhook/session-dispatch.mjs +14 -36
- package/src/runtime/channels/lib/worker-main.mjs +3 -2
- package/src/runtime/effort-judge/compact-tokenizer.mjs +8 -2
- package/src/runtime/effort-judge/judge-client.mjs +5 -2
- package/src/runtime/effort-judge/model-install.mjs +16 -8
- package/src/runtime/local-provider/asset-installer.mjs +10 -4
- package/src/runtime/local-provider/catalog.mjs +5 -2
- package/src/runtime/local-provider/registered-models.mjs +64 -27
- package/src/runtime/local-provider/server.mjs +2 -3
- package/src/runtime/media/adapters/image-api.mjs +89 -0
- package/src/runtime/media/auth.mjs +64 -1
- package/src/runtime/media/catalog.mjs +66 -4
- package/src/runtime/media/jobs.mjs +4 -0
- package/src/runtime/media/lanes.mjs +46 -5
- package/src/runtime/media/media-usage.mjs +17 -0
- package/src/runtime/media/renditions.mjs +15 -15
- package/src/runtime/media/store.mjs +36 -35
- package/src/runtime/media/tool.mjs +8 -1
- package/src/runtime/memory/lib/cycle-scheduler/health-ledger.mjs +8 -2
- package/src/runtime/memory/lib/embedding-model-files.mjs +30 -7
- package/src/runtime/memory/lib/ingest/transcript-tail.mjs +16 -7
- package/src/runtime/memory/lib/pg/process.mjs +8 -4
- package/src/runtime/memory/lib/project-id-resolver.mjs +5 -1
- package/src/runtime/memory/lib/runtime-fetcher.mjs +6 -1
- package/src/runtime/office/core/journal.mjs +7 -14
- package/src/runtime/office/design/library/design-library-core.mjs +4 -16
- package/src/runtime/office/pdf/ocr-engine-worker.mjs +37 -0
- package/src/runtime/office/pdf/ocr-engine.mjs +146 -0
- package/src/runtime/office/pdf/pdf-ocr.mjs +51 -21
- package/src/runtime/office/pdf/pdf-render.mjs +30 -18
- package/src/runtime/office/portable/ooxml-validator.mjs +2 -2
- package/src/runtime/office/portable/portable-soffice.mjs +4 -0
- package/src/runtime/shared/agent-kind-migration.mjs +200 -0
- package/src/runtime/shared/agent-message-envelope.d.mts +6 -0
- package/src/runtime/shared/agent-message-envelope.mjs +44 -0
- package/src/runtime/shared/agent-reap-state.d.mts +4 -0
- package/src/runtime/shared/agent-store.mjs +24 -7
- package/src/runtime/shared/agent-task-starts.mjs +27 -0
- package/src/runtime/shared/atomic-file.d.mts +50 -0
- package/src/runtime/shared/atomic-file.mjs +394 -132
- package/src/runtime/shared/background-tasks.mjs +7 -4
- package/src/runtime/shared/bot-hops.mjs +30 -0
- package/src/runtime/shared/bot-split-migration.mjs +1 -1
- package/src/runtime/shared/bounded-download.mjs +4 -2
- package/src/runtime/shared/config.mjs +39 -9
- package/src/runtime/shared/defaults-separation.mjs +6 -2
- package/src/runtime/shared/delegated-approval-host.mjs +74 -0
- package/src/runtime/shared/err-text.mjs +4 -0
- package/src/runtime/shared/error-presentation.mjs +22 -4
- package/src/runtime/shared/file-has-data.mjs +28 -0
- package/src/runtime/shared/llm/usage-ledger-import.mjs +37 -18
- package/src/runtime/shared/pending-agent-work.mjs +54 -0
- package/src/runtime/shared/process-lifecycle.mjs +8 -12
- package/src/runtime/shared/projects.mjs +50 -41
- package/src/runtime/shared/provider-accounts.mjs +17 -12
- package/src/runtime/shared/routine-trigger.d.mts +6 -1
- package/src/runtime/shared/routine-trigger.mjs +14 -6
- package/src/runtime/shared/run-child.d.mts +3 -0
- package/src/runtime/shared/run-child.mjs +24 -3
- package/src/runtime/shared/session-baseline-store.mjs +8 -2
- package/src/runtime/shared/singleton-owner.mjs +7 -6
- package/src/runtime/shared/skill-tool-dependencies.mjs +4 -10
- package/src/runtime/shared/staged-update.mjs +4 -2
- package/src/runtime/shared/statusline/statusline-segments.mjs +4 -15
- package/src/runtime/shared/tool-execution-contract.mjs +6 -0
- package/src/runtime/shared/transcript-metadata.mjs +28 -3
- package/src/runtime/shared/transcript-writer/session-record.mjs +7 -6
- package/src/runtime/shared/turn-snapshot-store.mjs +5 -4
- package/src/runtime/shared/turn-snapshot.mjs +44 -2
- package/src/runtime/shared/user-cwd.mjs +9 -4
- package/src/runtime/shared/user-data-guard.mjs +41 -42
- package/src/runtime/shared/utf8-cut.mjs +10 -0
- package/src/runtime/shared/worktrees/activity-gate.mjs +269 -61
- package/src/runtime/shared/worktrees/registry.mjs +26 -26
- package/src/runtime/tidy/core-install.mjs +26 -4
- package/src/runtime/tidy/install.mjs +91 -23
- package/src/runtime/web-search/lib/config.mjs +4 -16
- package/src/session-runtime/agent-home-delivery.mjs +555 -199
- package/src/session-runtime/agent-room-delivery.mjs +143 -36
- package/src/session-runtime/agent-task-sessions.mjs +667 -165
- package/src/session-runtime/agent-tool-routing.mjs +1 -0
- package/src/session-runtime/boot/apis.mjs +45 -24
- package/src/session-runtime/boot/config.mjs +1 -0
- package/src/session-runtime/boot/facade.mjs +11 -1
- package/src/session-runtime/boot/infrastructure.mjs +14 -2
- package/src/session-runtime/boot/providers.mjs +2 -2
- package/src/session-runtime/boot/shared.mjs +12 -6
- package/src/session-runtime/boot/tools.mjs +2 -2
- package/src/session-runtime/bot-status.mjs +432 -0
- package/src/session-runtime/config-lifecycle/lead-route-sync.mjs +29 -0
- package/src/session-runtime/config-lifecycle.mjs +60 -55
- package/src/session-runtime/cwd-plugins/core-memory-context.mjs +2 -4
- package/src/session-runtime/held-requests.mjs +36 -33
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +10 -1
- package/src/session-runtime/internal-tool-executor/feature-tools.mjs +2 -2
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +19 -4
- package/src/session-runtime/lifecycle/session-catalog.mjs +12 -2
- package/src/session-runtime/lifecycle/teardown.mjs +11 -3
- package/src/session-runtime/mcp-glue/connect.mjs +100 -186
- package/src/session-runtime/mcp-glue/initial-connect-gate.mjs +57 -0
- package/src/session-runtime/mcp-glue/server-connection.mjs +71 -0
- package/src/session-runtime/media-api.mjs +5 -2
- package/src/session-runtime/model-route/route-tuning.mjs +4 -1
- package/src/session-runtime/model-route/set-route.mjs +61 -1
- package/src/session-runtime/owned-automation-run.mjs +8 -1
- package/src/session-runtime/room-member-gate.mjs +16 -3
- package/src/session-runtime/route-resolution.mjs +16 -8
- package/src/session-runtime/route-state.mjs +1 -59
- package/src/session-runtime/routine-home-turn.mjs +5 -3
- package/src/session-runtime/runtime-bootstrap.mjs +5 -3
- package/src/session-runtime/runtime-paths.mjs +11 -5
- package/src/session-runtime/runtime-tunables.mjs +6 -0
- package/src/session-runtime/services/agent-tool/close-flow/close-all.mjs +11 -2
- package/src/session-runtime/services/agent-tool/close-flow.mjs +4 -2
- package/src/session-runtime/services/agent-tool/execute-send.mjs +1 -0
- package/src/session-runtime/services/agent-tool/execute-spawn.mjs +1 -0
- package/src/session-runtime/services/agent-tool/restart-notify.mjs +10 -0
- package/src/session-runtime/services/agent-tool/send-flow.mjs +25 -21
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +4 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +6 -3
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +8 -5
- package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +22 -2
- package/src/session-runtime/services/agent-tool/worker-index.mjs +4 -6
- package/src/session-runtime/services/agent-tool.mjs +6 -0
- package/src/session-runtime/services/daemon-crash-capture/daemon-exit-record.mjs +1 -1
- package/src/session-runtime/services/daemon-crash-capture/retention.mjs +4 -3
- package/src/session-runtime/services/hook-bus/config-loader.mjs +14 -5
- package/src/session-runtime/services/hook-bus/rule-file.mjs +49 -11
- package/src/session-runtime/services/plugin-admin.mjs +26 -26
- package/src/session-runtime/services/provider-admin.mjs +14 -4
- package/src/session-runtime/services/schedule-access.mjs +33 -4
- package/src/session-runtime/services/seeds.mjs +4 -3
- package/src/session-runtime/services/usage-dashboard.mjs +1 -1
- package/src/session-runtime/services/usage-stats-model.mjs +2 -1
- package/src/session-runtime/session-create/materialize.mjs +2 -3
- package/src/session-runtime/session-create/session-options.mjs +15 -2
- package/src/session-runtime/settings-builtin-tools-api.mjs +63 -1
- package/src/session-runtime/settings-compaction-api.mjs +86 -39
- package/src/session-runtime/setup-tool/executor.mjs +8 -2
- package/src/session-runtime/setup-tool/settings-contract.mjs +31 -1
- package/src/session-runtime/setup-tool/tool-defs.mjs +20 -3
- package/src/session-runtime/skills-api.mjs +12 -5
- package/src/session-runtime/tool-policy/agent-profile-fold.mjs +265 -0
- package/src/session-runtime/tool-policy/mode-switch.mjs +54 -0
- package/src/session-runtime/tool-policy/pending-switches.mjs +59 -0
- package/src/session-runtime/tool-policy/policy-stage.mjs +165 -0
- package/src/session-runtime/tool-policy/session-switches.mjs +169 -0
- package/src/session-runtime/tool-policy/surface-helpers.mjs +114 -0
- package/src/session-runtime/tool-policy/workflow-overlay.mjs +145 -0
- package/src/session-runtime/tool-policy-refresh.mjs +47 -369
- package/src/session-runtime/tool-surface.mjs +5 -3
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +95 -88
- package/src/session-runtime/turn/turn-run/turn-timing.mjs +4 -3
- package/src/session-runtime/turn/turn-run.mjs +2 -1
- package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +54 -7
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +519 -333
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +46 -46
- package/src/session-runtime/workflow-agents-api/shared.mjs +5 -1
- package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +14 -1
- package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +6 -3
- package/src/session-runtime/workspace/workspace-state.mjs +7 -6
- package/src/standalone/daemon-agent-control.mjs +4 -1
- package/src/standalone/daemon-session-control.mjs +51 -10
- package/src/standalone/daemon.mjs +28 -10
- package/src/standalone/local-session-runtime.mjs +22 -14
- package/src/standalone/session-client.mjs +7 -2
- package/src/standalone/session-protocol.mjs +7 -0
- package/src/standalone/session-service.mjs +11 -0
- package/src/standalone/session-state-projection.mjs +19 -9
- package/src/standalone/session-tool-output.mjs +35 -9
- package/src/tui/app/maintenance-pickers/auto-clear-picker.mjs +19 -13
- package/src/tui/app/settings-picker/settings-rows.mjs +2 -2
- package/src/tui/app/slash-commands.mjs +1 -1
- package/src/tui/app/usage-context-panels/context-model.mjs +8 -2
- package/src/tui/dist/index.mjs +529 -333
- package/src/tui/prompt-history-store.mjs +16 -21
- package/src/tui/session/context-state.mjs +4 -0
- package/src/tui/session/session-api/intake/abort.mjs +19 -1
- package/src/tui/session/session-api/media.mjs +2 -1
- package/src/tui/session/session-api/routes-agent-definitions.mjs +75 -0
- package/src/tui/session/session-api/routes-write.mjs +203 -0
- package/src/tui/session/session-api/routes.mjs +23 -247
- package/src/tui/session/session-api/settings.mjs +14 -1
- package/src/tui/session/session-flow/drain.mjs +28 -3
- package/src/tui/session/session-flow/failed-turn-rewind.mjs +4 -2
- package/src/tui/session/session-flow/queue/take-entries.mjs +8 -0
- package/src/tui/session/session-flow/steering.mjs +8 -3
- package/src/tui/session/tool-approval.mjs +185 -20
- package/src/tui/session/transcript-intake.mjs +2 -0
- package/src/tui/session/turn.mjs +23 -14
- package/src/tui/transcript-tool-failures.mjs +8 -2
- package/src/vendor/statusline/src/gateway/route-meta.mjs +7 -8
- package/src/vendor/statusline/src/gateway/session-routes.mjs +6 -7
- package/src/rules/agent-mode/ROUTINE.md +0 -6
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
* Stored under MIXDOG data dir (not the repo working tree).
|
|
4
4
|
*/
|
|
5
5
|
import { createHash } from 'node:crypto';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { mkdirSync } from 'node:fs';
|
|
7
|
+
import { mkdir } from 'node:fs/promises';
|
|
8
8
|
import { dirname, join, resolve } from 'node:path';
|
|
9
|
+
import { readJsonStateSync, writeFileAtomicAsync, writeFileAtomicSync } from '../runtime/shared/atomic-file.mjs';
|
|
9
10
|
import { resolvePluginData } from '../runtime/shared/plugin-paths.mjs';
|
|
10
11
|
|
|
11
12
|
export const PROMPT_HISTORY_LIMIT = 50;
|
|
@@ -33,10 +34,18 @@ function historyFilePath(cwd) {
|
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
function readEntries(filePath) {
|
|
36
|
-
if (!filePath
|
|
37
|
+
if (!filePath) return [];
|
|
37
38
|
try {
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
// A damaged file (NUL, truncated) is kept aside as *.corrupt-<ts> and the
|
|
40
|
+
// history starts empty; the next flush writes a fresh file.
|
|
41
|
+
const parsed = readJsonStateSync(filePath, {
|
|
42
|
+
mode: 0o600,
|
|
43
|
+
validate: (value) => {
|
|
44
|
+
if (!Array.isArray(value?.entries)) throw new TypeError('prompt history has no entries');
|
|
45
|
+
return value;
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
const entries = parsed ? parsed.entries : [];
|
|
40
49
|
return entries.map((entry) => String(entry || '').trim()).filter((entry) => promptHistoryKey(entry));
|
|
41
50
|
} catch {
|
|
42
51
|
return [];
|
|
@@ -52,14 +61,7 @@ function writeEntriesSync(filePath, entries) {
|
|
|
52
61
|
try {
|
|
53
62
|
// Prompt text may be sensitive; restrict directory/file to the owning user.
|
|
54
63
|
mkdirSync(dirname(filePath), { recursive: true, mode: 0o700 });
|
|
55
|
-
|
|
56
|
-
writeFileSync(tmp, buildPayload(entries), { encoding: 'utf8', mode: 0o600 });
|
|
57
|
-
renameSync(tmp, filePath);
|
|
58
|
-
try {
|
|
59
|
-
chmodSync(filePath, 0o600);
|
|
60
|
-
} catch {
|
|
61
|
-
/* best-effort; Windows may ignore mode bits */
|
|
62
|
-
}
|
|
64
|
+
writeFileAtomicSync(filePath, buildPayload(entries), { mode: 0o600 });
|
|
63
65
|
return true;
|
|
64
66
|
} catch {
|
|
65
67
|
return false;
|
|
@@ -72,14 +74,7 @@ async function writeEntriesAsync(filePath, entries) {
|
|
|
72
74
|
if (!filePath) return false;
|
|
73
75
|
try {
|
|
74
76
|
await mkdir(dirname(filePath), { recursive: true, mode: 0o700 });
|
|
75
|
-
|
|
76
|
-
await writeFile(tmp, buildPayload(entries), { encoding: 'utf8', mode: 0o600 });
|
|
77
|
-
await rename(tmp, filePath);
|
|
78
|
-
try {
|
|
79
|
-
await chmod(filePath, 0o600);
|
|
80
|
-
} catch {
|
|
81
|
-
/* best-effort; Windows may ignore mode bits */
|
|
82
|
-
}
|
|
77
|
+
await writeFileAtomicAsync(filePath, buildPayload(entries), { mode: 0o600 });
|
|
83
78
|
return true;
|
|
84
79
|
} catch {
|
|
85
80
|
return false;
|
|
@@ -77,6 +77,10 @@ export function createContextState({
|
|
|
77
77
|
autoClear: autoClearState(),
|
|
78
78
|
workflow: runtime.workflow || null,
|
|
79
79
|
orchestrationMode: runtime.orchestrationMode || 'none',
|
|
80
|
+
// A workflow / orchestration mode chosen during a turn: shown above,
|
|
81
|
+
// applied when the next turn starts (tool-policy-refresh.mjs).
|
|
82
|
+
pendingWorkflowSwitch: runtime.session?.pendingWorkflowId !== undefined,
|
|
83
|
+
pendingOrchestrationModeSwitch: runtime.session?.pendingOrchestrationMode !== undefined,
|
|
80
84
|
// Every `set({ ...routeState() })` (the 2s runtime pulse, model/effort
|
|
81
85
|
// switches, turn end, resume) republishes the Goal. It must read it
|
|
82
86
|
// through the goal-continuation mask: the raw record still holds a
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// during a turn cancels it and, unless a steering prompt is already queued,
|
|
3
3
|
// reclaims the in-flight prompt, its history slot and its requeue entries.
|
|
4
4
|
import { hydratePastedAttachments, hydrateRestorableFileParts } from '../../../../runtime/attachments/store.mjs';
|
|
5
|
+
import { USER_CANCEL_KEEP_PROMPT_REASON } from '../../../../runtime/agent/orchestrator/session/manager/turn-interruption.mjs';
|
|
5
6
|
import { abortGoalTurn } from '../../goal-turn-state.mjs';
|
|
6
7
|
import { promptHistoryWithout } from '../../prompt-history.mjs';
|
|
7
8
|
import { isQueuedEntryEditable } from '../../queue-helpers.mjs';
|
|
@@ -146,8 +147,25 @@ export function createAbortAction(bag) {
|
|
|
146
147
|
(entry) => entry?.abortDiscardOnAbort !== true && entry?.mode !== 'pending-resume'
|
|
147
148
|
)
|
|
148
149
|
: [];
|
|
149
|
-
|
|
150
|
+
// A user Stop that hands the prompt back is rewound by the runtime (the
|
|
151
|
+
// prompt returns to the input box); one that does not keeps it in the
|
|
152
|
+
// stored transcript, as it stays in the visible one. A turn that already
|
|
153
|
+
// committed (output produced) needs neither.
|
|
154
|
+
const keepsPrompt = reason === 'user-cancel' && !canRestore && restoreState?.restorable && !restoreState.committed;
|
|
155
|
+
const aborted = abortGoalTurn(
|
|
156
|
+
runtime,
|
|
157
|
+
flags,
|
|
158
|
+
hasPendingSteering,
|
|
159
|
+
keepsPrompt ? USER_CANCEL_KEEP_PROMPT_REASON : reason
|
|
160
|
+
);
|
|
150
161
|
if (restoreState) {
|
|
162
|
+
// A user Stop consumes this input even when no draft is requested.
|
|
163
|
+
// Explicit draft reclamation also releases it; automatic interruptions
|
|
164
|
+
// such as the watchdog must retain input that has not been committed.
|
|
165
|
+
if (aborted !== false && !restoreState.committed && (reason === 'user-cancel' || restoreText)) {
|
|
166
|
+
restoreState.onAborted?.();
|
|
167
|
+
restoreState.onAborted = null;
|
|
168
|
+
}
|
|
151
169
|
if (aborted !== false && Array.isArray(restoreState.discardExecutionPendingResumeKeys)) {
|
|
152
170
|
discardExecutionPendingResume?.(restoreState.discardExecutionPendingResumeKeys);
|
|
153
171
|
}
|
|
@@ -119,7 +119,8 @@ export function createSessionMediaApi(bag) {
|
|
|
119
119
|
// Media studio (image/video generation). Reads stay quiet, and there is no
|
|
120
120
|
// notice on start either: the Studio surfaces progress on its own pending
|
|
121
121
|
// tile, and a toast for a user-initiated generation is pure noise.
|
|
122
|
-
|
|
122
|
+
// `{ budgetMs }` bounds the per-lane catalog wait (Studio, Settings).
|
|
123
|
+
listMediaLanes: (options) => runtime.listMediaLanes?.(options),
|
|
123
124
|
getMediaDefault: (kind) => runtime.getMediaDefault?.(kind),
|
|
124
125
|
setMediaDefault: (input) => runtime.setMediaDefault?.(input),
|
|
125
126
|
getMediaPins: () => runtime.getMediaPins?.(),
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* routes-agent-definitions.mjs — the session route surface's passthroughs to
|
|
3
|
+
* the runtime's agent, workflow-pack, connector and lead-identity services.
|
|
4
|
+
*/
|
|
5
|
+
export function createAgentDefinitionApi(runtime) {
|
|
6
|
+
return {
|
|
7
|
+
listAgents: () => {
|
|
8
|
+
return runtime.listAgents?.() || [];
|
|
9
|
+
},
|
|
10
|
+
listWorkflows: () => {
|
|
11
|
+
return runtime.listWorkflows?.() || [];
|
|
12
|
+
},
|
|
13
|
+
// Workflow pack editing (desktop Workflows page): direct passthroughs —
|
|
14
|
+
// the runtime owns validation, user-pack persistence, and delete guards.
|
|
15
|
+
getWorkflowPack: (workflowId) => runtime.getWorkflowPack?.(workflowId) ?? null,
|
|
16
|
+
saveWorkflowPack: async (payload) => runtime.saveWorkflowPack?.(payload) ?? null,
|
|
17
|
+
createWorkflow: async (payload) => runtime.createWorkflow?.(payload) ?? null,
|
|
18
|
+
deleteWorkflow: async (workflowId) => runtime.deleteWorkflow?.(workflowId) ?? null,
|
|
19
|
+
getAgentDefinition: (agentId) => runtime.getAgentDefinition?.(agentId) ?? null,
|
|
20
|
+
getAgentAvatarImage: (agentId) => runtime.getAgentAvatarImage?.(agentId) ?? null,
|
|
21
|
+
getAgentConnectors: (agentId) => runtime.getAgentConnectors?.(agentId) ?? [],
|
|
22
|
+
listConnectors: () => runtime.listConnectors?.() ?? [],
|
|
23
|
+
listConnectorTools: (connectorId) => runtime.listConnectorTools?.(connectorId) ?? [],
|
|
24
|
+
// `options.noWiden` is only ever added by the desktop's remote method table: the
|
|
25
|
+
// change is refused if it would give the agent more authority (checked atomically with the write).
|
|
26
|
+
setAgentConnectors: async (agentId, connectors, options) =>
|
|
27
|
+
runtime.setAgentConnectors?.(agentId, connectors, options) ?? null,
|
|
28
|
+
setAgentConnectorEnabled: async (agentId, connectorId, enabled, options) =>
|
|
29
|
+
runtime.setAgentConnectorEnabled?.(agentId, connectorId, enabled, options) ?? [],
|
|
30
|
+
getProjectConnectors: (projectPath) => runtime.getProjectConnectors?.(projectPath) ?? [],
|
|
31
|
+
setProjectConnectorEnabled: async (projectPath, connectorId, enabled, options) =>
|
|
32
|
+
runtime.setProjectConnectorEnabled?.(projectPath, connectorId, enabled, options) ?? [],
|
|
33
|
+
setAgentConnectorToolPermission: async (agentId, connectorId, toolName, permission, options) =>
|
|
34
|
+
runtime.setAgentConnectorToolPermission?.(agentId, connectorId, toolName, permission, options) ?? null,
|
|
35
|
+
getAgentAlwaysAllowedTools: (agentId) => runtime.getAgentAlwaysAllowedTools?.(agentId) ?? [],
|
|
36
|
+
// Per-agent action-kind permissions (ask / allow / block) for the profile.
|
|
37
|
+
getAgentPermissions: async (agentId) =>
|
|
38
|
+
(await import('../../../runtime/agent/orchestrator/session/human-gate/store.mjs')).agentPermissions(agentId),
|
|
39
|
+
setAgentPermission: async (agentId, action, mode, options) =>
|
|
40
|
+
(await import('../../../runtime/agent/orchestrator/session/human-gate/store.mjs')).setAgentPermission(
|
|
41
|
+
agentId,
|
|
42
|
+
action,
|
|
43
|
+
mode,
|
|
44
|
+
options
|
|
45
|
+
),
|
|
46
|
+
recordAgentApprovalAudit: async (agentId, action, decision) =>
|
|
47
|
+
(await import('../../../runtime/agent/orchestrator/session/human-gate/store.mjs')).recordAgentApprovalAudit(
|
|
48
|
+
agentId,
|
|
49
|
+
action,
|
|
50
|
+
decision
|
|
51
|
+
),
|
|
52
|
+
getLeadPersona: () => runtime.getLeadPersona?.() ?? '',
|
|
53
|
+
saveLeadPersona: async (text) => runtime.saveLeadPersona?.(text) ?? '',
|
|
54
|
+
getLeadAgentBody: () => runtime.getLeadAgentBody?.() ?? '',
|
|
55
|
+
saveLeadAgentBody: async (text) => runtime.saveLeadAgentBody?.(text) ?? '',
|
|
56
|
+
getLeadStatus: () =>
|
|
57
|
+
runtime.getLeadStatus?.() ?? { created: null, name: '', avatar: null, homeChatted: false, route: null },
|
|
58
|
+
saveLeadIdentity: async (payload) => runtime.saveLeadIdentity?.(payload) ?? null,
|
|
59
|
+
setLeadCreated: async (created, description) => runtime.setLeadCreated?.(created, description) ?? null,
|
|
60
|
+
saveAgentDefinition: async (payload, options) => runtime.saveAgentDefinition?.(payload, options) ?? null,
|
|
61
|
+
deleteAgentDefinition: async (agentId) => runtime.deleteAgentDefinition?.(agentId) ?? null,
|
|
62
|
+
agentDefinitionPresence: (agentIds) => runtime.agentDefinitionPresence?.(agentIds) ?? null,
|
|
63
|
+
restoreAgentDefinition: async (agentId) => runtime.restoreAgentDefinition?.(agentId) ?? null,
|
|
64
|
+
purgeAgentDefinition: async (agentId) => runtime.purgeAgentDefinition?.(agentId) ?? null,
|
|
65
|
+
archivedAgentIdentities: (agentIds) => runtime.archivedAgentIdentities?.(agentIds) ?? null,
|
|
66
|
+
// Group-room rows posted by the desktop host into a room's log session.
|
|
67
|
+
appendRoomRows: async (sessionId, rows) =>
|
|
68
|
+
(await import('../../../session-runtime/agent-room-delivery.mjs')).appendRoomRows(sessionId, rows),
|
|
69
|
+
// One group-room supervisor step on the Maintainer route.
|
|
70
|
+
decideRoomTurn: async (input) =>
|
|
71
|
+
(await import('../../../runtime/agent/orchestrator/agent-runtime/room-supervisor-completion.mjs')).decideRoomTurn(
|
|
72
|
+
input
|
|
73
|
+
),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* routes-write.mjs — the serialized, optimistic route write behind the
|
|
3
|
+
* session's setRoute (every model picker, presets, agent child routes).
|
|
4
|
+
*/
|
|
5
|
+
import { modelSwitchItem } from '../../../runtime/agent/orchestrator/session/transcript-restore/restore.mjs';
|
|
6
|
+
import { selectedModel } from '../../../session-runtime/model-route/model-switch-target.mjs';
|
|
7
|
+
|
|
8
|
+
// Optimistic route preview: the requested provider/model/effort/fast are
|
|
9
|
+
// published before the runtime write settles. What is NOT previewed about the
|
|
10
|
+
// route (effort options, Fast capability, context window) is provider
|
|
11
|
+
// metadata the runtime resolves while the preview is already on screen.
|
|
12
|
+
const ROUTE_PREVIEW_KEYS = [
|
|
13
|
+
'provider',
|
|
14
|
+
'model',
|
|
15
|
+
'effort',
|
|
16
|
+
'fast',
|
|
17
|
+
'autoEffort',
|
|
18
|
+
'modelParameters',
|
|
19
|
+
'contextPercent',
|
|
20
|
+
'contextTokens',
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The patch that publishes a requested route before the runtime write settles.
|
|
25
|
+
* Returns null when the request carries nothing previewable.
|
|
26
|
+
*/
|
|
27
|
+
function optimisticRoutePatch(requested = {}, current = {}) {
|
|
28
|
+
const route = requested && typeof requested === 'object' ? requested : {};
|
|
29
|
+
const has = (key) => Object.hasOwn(route, key);
|
|
30
|
+
const patch = {};
|
|
31
|
+
for (const key of ROUTE_PREVIEW_KEYS) {
|
|
32
|
+
if (has(key)) patch[key] = route[key];
|
|
33
|
+
}
|
|
34
|
+
if (!has('provider') && !has('model')) {
|
|
35
|
+
return Object.keys(patch).length > 0 ? patch : null;
|
|
36
|
+
}
|
|
37
|
+
const sameModel =
|
|
38
|
+
String(patch.provider ?? current.provider ?? '') === String(current.provider ?? '') &&
|
|
39
|
+
String(patch.model ?? current.model ?? '') === String(current.model ?? '');
|
|
40
|
+
// A different model carries none of the previous model's tuning: an omitted
|
|
41
|
+
// key means "this model has no such control", not "keep the old value".
|
|
42
|
+
if (!sameModel) {
|
|
43
|
+
if (!has('effort')) patch.effort = null;
|
|
44
|
+
if (!has('fast')) patch.fast = false;
|
|
45
|
+
if (!has('modelParameters')) patch.modelParameters = {};
|
|
46
|
+
}
|
|
47
|
+
return patch;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const SESSION_ONLY_KEYS = new Set(['provider', 'model', 'effort', 'fast', 'autoEffort']);
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* A session-only request (an agent child's route) may name just the model, just
|
|
54
|
+
* the tuning, or both. Completed here, inside the serialized route write,
|
|
55
|
+
* against the latest selected route — so a Fast-only change keeps the effort a
|
|
56
|
+
* previous write selected. `unchanged` when it asks for nothing the selected
|
|
57
|
+
* route does not already have.
|
|
58
|
+
*/
|
|
59
|
+
function completeSessionOnlyRequest(request, selected) {
|
|
60
|
+
const named = Boolean(request.provider || request.model);
|
|
61
|
+
const target = named ? request : { ...request, provider: selected.provider, model: selected.model };
|
|
62
|
+
const sameModel = target.provider === selected.provider && target.model === selected.model;
|
|
63
|
+
if (!sameModel) return { request: target, unchanged: false };
|
|
64
|
+
const unchanged =
|
|
65
|
+
Object.keys(request).every((key) => SESSION_ONLY_KEYS.has(key)) &&
|
|
66
|
+
(request.effort === undefined || request.effort === selected.effort) &&
|
|
67
|
+
(request.fast === undefined || request.fast === (selected.fast === true)) &&
|
|
68
|
+
(request.autoEffort === undefined || request.autoEffort === (selected.autoEffort !== false));
|
|
69
|
+
return {
|
|
70
|
+
unchanged,
|
|
71
|
+
request: {
|
|
72
|
+
...(selected.effort ? { effort: selected.effort } : {}),
|
|
73
|
+
fast: selected.fast === true,
|
|
74
|
+
autoEffort: selected.autoEffort !== false,
|
|
75
|
+
...target,
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** The live divider of an in-place model switch (restored from message meta
|
|
81
|
+
* after a reload); every switch path publishes it the same way. */
|
|
82
|
+
export function publishModelSwitch(bag, modelSwitch) {
|
|
83
|
+
if (modelSwitch) bag.pushItem(modelSwitchItem(bag.nextId(), modelSwitch));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function createRouteWrite(
|
|
87
|
+
bag,
|
|
88
|
+
{ runtime, getState, set, flushEmitImmediate, routeState, syncContextStats, publishRoute }
|
|
89
|
+
) {
|
|
90
|
+
let routeWrite = null;
|
|
91
|
+
let routeSequence = 0;
|
|
92
|
+
// Whether this API (not another command) is the one holding commandBusy.
|
|
93
|
+
let routeLocked = false;
|
|
94
|
+
|
|
95
|
+
// A preset selector previews as the preset's model, never as its id.
|
|
96
|
+
const previewedRequest = (routeOpts) => {
|
|
97
|
+
if (routeOpts.provider || !routeOpts.model) return routeOpts;
|
|
98
|
+
const target = selectedModel(runtime, routeOpts, '', '');
|
|
99
|
+
return target.provider ? { ...routeOpts, ...target } : routeOpts;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const setRoute = async (opts) => {
|
|
103
|
+
const routeOpts = opts && typeof opts === 'object' ? opts : {};
|
|
104
|
+
// All model pickers save a selection for the conversation's next turn; a
|
|
105
|
+
// running turn keeps the session model it started on. A selection is never
|
|
106
|
+
// refused: another command's lock neither blocks it nor is released by it.
|
|
107
|
+
const token = ++routeSequence;
|
|
108
|
+
const previousWrite = routeWrite;
|
|
109
|
+
// The session generation this selection was made under. The write below
|
|
110
|
+
// waits behind earlier ones, so "current" is never read later: the runtime
|
|
111
|
+
// validates this token before every route side effect, and `settle` below
|
|
112
|
+
// is the only place the display is touched once the write has started.
|
|
113
|
+
const originGeneration = runtime.sessionGeneration;
|
|
114
|
+
const owned = () => runtime.sessionGeneration === originGeneration;
|
|
115
|
+
// A conditional fill (only when the route is still empty) may not apply, so
|
|
116
|
+
// it never previews: the runtime's answer is what gets published.
|
|
117
|
+
const onlyIfEmpty = routeOpts.onlyIfEmpty === true;
|
|
118
|
+
const preview = onlyIfEmpty ? null : optimisticRoutePatch(previewedRequest(routeOpts), getState());
|
|
119
|
+
// Preview immediately, serialize persistence without dropping a later
|
|
120
|
+
// click. Earlier completions cannot replace the newest visible choice.
|
|
121
|
+
if (!getState().commandBusy) routeLocked = true;
|
|
122
|
+
set({ ...(routeLocked ? { commandBusy: true } : {}), ...(preview || {}) });
|
|
123
|
+
flushEmitImmediate();
|
|
124
|
+
const write = (async () => {
|
|
125
|
+
if (previousWrite) await previousWrite.catch(() => {});
|
|
126
|
+
const previousRoute = routeState();
|
|
127
|
+
// A stale selection only republishes the route that is actually
|
|
128
|
+
// selected; it never restores or announces its own session's state.
|
|
129
|
+
const settle = ({ failed = false, sync = false, modelSwitch = null } = {}) => {
|
|
130
|
+
const stillOwned = owned();
|
|
131
|
+
if (stillOwned) publishModelSwitch(bag, modelSwitch);
|
|
132
|
+
// A newer selection publishes the final route itself.
|
|
133
|
+
if (token !== routeSequence) return;
|
|
134
|
+
if (stillOwned && failed) {
|
|
135
|
+
if (preview) set({ ...previousRoute, stats: { ...getState().stats } });
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
if (stillOwned && sync) syncContextStats({ allowEstimated: true });
|
|
139
|
+
publishRoute();
|
|
140
|
+
};
|
|
141
|
+
try {
|
|
142
|
+
// Keep the durable session address while deferring route application.
|
|
143
|
+
const applyToCurrentSession = routeOpts.applyToCurrentSession === true;
|
|
144
|
+
const keepMainModel = routeOpts.keepMainModel !== false;
|
|
145
|
+
const sessionOnly = routeOpts.sessionOnly === true;
|
|
146
|
+
const {
|
|
147
|
+
applyToCurrentSession: _drop,
|
|
148
|
+
keepMainModel: _keep,
|
|
149
|
+
sessionOnly: _scope,
|
|
150
|
+
onlyIfEmpty: _fill,
|
|
151
|
+
...requested
|
|
152
|
+
} = routeOpts;
|
|
153
|
+
let nextRoute = requested;
|
|
154
|
+
if (sessionOnly) {
|
|
155
|
+
const completed = completeSessionOnlyRequest(requested, previousRoute);
|
|
156
|
+
if (completed.unchanged) {
|
|
157
|
+
// An earlier failed write skipped its rollback because this one is
|
|
158
|
+
// newer, so the shown route may still be that write's preview.
|
|
159
|
+
settle();
|
|
160
|
+
return previousRoute;
|
|
161
|
+
}
|
|
162
|
+
nextRoute = completed.request;
|
|
163
|
+
}
|
|
164
|
+
const resolvedRoute = await runtime.setRoute(nextRoute, {
|
|
165
|
+
applyToCurrentSession,
|
|
166
|
+
keepMainModel,
|
|
167
|
+
...(sessionOnly ? { sessionOnly } : {}),
|
|
168
|
+
...(onlyIfEmpty ? { onlyIfEmpty } : {}),
|
|
169
|
+
...(originGeneration !== undefined ? { originGeneration } : {}),
|
|
170
|
+
switchEstablished: true,
|
|
171
|
+
deferUntilNextTurn: true,
|
|
172
|
+
});
|
|
173
|
+
settle({
|
|
174
|
+
sync: applyToCurrentSession || Boolean(resolvedRoute?.modelSwitch),
|
|
175
|
+
modelSwitch: resolvedRoute?.modelSwitch,
|
|
176
|
+
});
|
|
177
|
+
return resolvedRoute;
|
|
178
|
+
} catch (error) {
|
|
179
|
+
settle({ failed: true });
|
|
180
|
+
throw error;
|
|
181
|
+
} finally {
|
|
182
|
+
if (token === routeSequence) {
|
|
183
|
+
if (routeLocked) set({ commandBusy: false });
|
|
184
|
+
routeLocked = false;
|
|
185
|
+
// Publish the resolved route (or rollback) before an RPC reply
|
|
186
|
+
// reads getState(), even while the display-frame clock is busy.
|
|
187
|
+
flushEmitImmediate();
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
})();
|
|
191
|
+
routeWrite = write;
|
|
192
|
+
try {
|
|
193
|
+
return await write;
|
|
194
|
+
} finally {
|
|
195
|
+
if (routeWrite === write) routeWrite = null;
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
// The settings surface's setModel (/model, presets) is the same user
|
|
199
|
+
// model choice and runs through this one path.
|
|
200
|
+
bag.setSessionRoute = setRoute;
|
|
201
|
+
|
|
202
|
+
return setRoute;
|
|
203
|
+
}
|