mixdog 1.3.0 → 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/NOTICE.md +52 -9
- package/README.md +8 -4
- package/package.json +2 -2
- package/scripts/native-release-status.mjs +238 -0
- package/src/defaults/shipped-history.json +8 -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 +54 -4
- package/src/defaults/skills/setup/references/surfaces.md +23 -3
- package/src/defaults/skills/setup-guide/SKILL.md +17 -10
- 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/output-styles/common.md +13 -8
- package/src/rules/agent-mode/AGENT_MODE.md +9 -6
- package/src/rules/agent-mode/MIXY.md +11 -6
- 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 +81 -16
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +97 -4
- 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-oauth-catalog.mjs +7 -2
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +6 -2
- package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +34 -16
- 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 +19 -1
- package/src/runtime/agent/orchestrator/providers/lib/tail-reminder-split.mjs +13 -0
- package/src/runtime/agent/orchestrator/providers/lib/tool-call-wire-ids.mjs +65 -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-retry-profile.mjs +8 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +10 -2
- 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-responses-input.mjs +3 -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/provider-error-kind.mjs +14 -2
- package/src/runtime/agent/orchestrator/providers/registry.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +17 -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 +5 -5
- 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 +17 -6
- package/src/runtime/agent/orchestrator/runtime-core/workflow/agents.mjs +41 -10
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +6 -4
- 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 +21 -2
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +149 -45
- 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 +156 -25
- 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/loop-state.mjs +9 -0
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +111 -9
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +11 -14
- 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/loop/usage.mjs +46 -4
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +13 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +18 -8
- 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/provider-replay.mjs +50 -0
- 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 +62 -47
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +6 -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-checkpoint.mjs +7 -1
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +24 -8
- package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/workflow-switch-notice.mjs +94 -13
- package/src/runtime/agent/orchestrator/session/mixy-name.mjs +5 -2
- 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 +35 -4
- package/src/runtime/agent/orchestrator/session/routine-result.mjs +179 -16
- 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 +49 -14
- package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +134 -17
- 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 +55 -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 +6 -3
- package/src/runtime/effort-judge/model-install.mjs +16 -8
- package/src/runtime/effort-judge/model-manifest.json +7 -7
- 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-kind.mjs +152 -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-route-config.d.mts +1 -0
- package/src/runtime/shared/agent-route-config.mjs +22 -8
- package/src/runtime/shared/agent-store.mjs +149 -0
- 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 +457 -0
- package/src/runtime/shared/bounded-download.mjs +4 -2
- package/src/runtime/shared/config-patch.mjs +20 -1
- package/src/runtime/shared/config.mjs +39 -9
- package/src/runtime/shared/connector-catalog.d.mts +1 -2
- package/src/runtime/shared/connector-catalog.mjs +2 -4
- package/src/runtime/shared/connector-triggers.mjs +2 -0
- 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 +7 -1
- package/src/runtime/shared/error-presentation.mjs +113 -10
- package/src/runtime/shared/file-has-data.mjs +28 -0
- package/src/runtime/shared/handoff-artifacts.d.mts +20 -0
- package/src/runtime/shared/handoff-artifacts.mjs +61 -0
- package/src/runtime/shared/llm/provider-model-identities.mjs +6 -1
- package/src/runtime/shared/llm/usage-accounting.mjs +7 -1
- package/src/runtime/shared/llm/usage-ledger-import.mjs +37 -18
- package/src/runtime/shared/model-route-fallback.mjs +79 -7
- package/src/runtime/shared/pending-agent-work.mjs +54 -0
- package/src/runtime/shared/plain-preview.mjs +22 -17
- 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/sensitive-path-rules.d.mts +15 -0
- package/src/runtime/shared/sensitive-path-rules.mjs +256 -0
- 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/usage-readout-totals.mjs +15 -13
- package/src/runtime/shared/user-cwd.mjs +9 -4
- package/src/runtime/shared/user-data-guard.mjs +46 -44
- 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 +859 -136
- package/src/session-runtime/agent-room-delivery.mjs +167 -19
- package/src/session-runtime/agent-task-sessions.mjs +831 -69
- package/src/session-runtime/agent-tool-routing.mjs +1 -0
- package/src/session-runtime/boot/apis.mjs +58 -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 +16 -6
- 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 +78 -32
- package/src/session-runtime/cwd-plugins/core-memory-context.mjs +2 -4
- package/src/session-runtime/handoff-attachments.mjs +593 -0
- 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 +45 -6
- 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-persist.mjs +2 -2
- package/src/session-runtime/model-route/route-tuning.mjs +11 -2
- package/src/session-runtime/model-route/set-route.mjs +82 -2
- package/src/session-runtime/native-web-search.mjs +2 -2
- package/src/session-runtime/new-session-config.mjs +6 -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 +21 -19
- 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/helpers.mjs +24 -5
- package/src/session-runtime/services/agent-tool/restart-notify.mjs +10 -0
- package/src/session-runtime/services/agent-tool/send-flow.mjs +36 -24
- 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 +12 -6
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +5 -8
- package/src/session-runtime/services/agent-tool/tool-def.mjs +7 -0
- 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 +20 -3
- package/src/session-runtime/setup-tool/extended-actions.mjs +19 -7
- package/src/session-runtime/setup-tool/settings-contract.mjs +37 -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 -358
- package/src/session-runtime/tool-surface.mjs +5 -3
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +99 -81
- 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 +578 -301
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +113 -53
- package/src/session-runtime/workflow-agents-api/onboarding.mjs +11 -4
- 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 +60 -11
- package/src/standalone/daemon.mjs +34 -4
- 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/agent-tree/agent-turns.mjs +46 -3
- package/src/standalone/session-service/agent-tree.mjs +4 -3
- package/src/standalone/session-service/session-calls/session-turns.mjs +19 -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 +599 -342
- package/src/tui/prompt-history-store.mjs +16 -21
- package/src/tui/session/context-state.mjs +4 -0
- package/src/tui/session/notice-surface.mjs +3 -4
- 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 -236
- 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 +4 -0
- package/src/tui/session/turn-live-call.mjs +11 -3
- package/src/tui/session/turn.mjs +36 -17
- 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
|
@@ -5,7 +5,6 @@ import { getProvider, initProviders } from '../../providers/registry.mjs';
|
|
|
5
5
|
import { resolveMaintenanceRoute } from '../../agent-runtime/maintenance-route.mjs';
|
|
6
6
|
import { resolveSessionContextMeta } from '../manager/context-meta.mjs';
|
|
7
7
|
import { isAccountQuotaError } from '../../providers/account-pool.mjs';
|
|
8
|
-
import { builtinFeatureActive } from '../../runtime-core/builtin-features.mjs';
|
|
9
8
|
import { positiveInt } from '../../../../shared/numbers.mjs';
|
|
10
9
|
import { estimateMessagesTokens, providerTokenCalibration } from '../context-utils.mjs';
|
|
11
10
|
import {
|
|
@@ -16,6 +15,8 @@ import {
|
|
|
16
15
|
COMPACT_TARGET_MIN_TOKENS,
|
|
17
16
|
} from '../compact.mjs';
|
|
18
17
|
import { summarizeOnSharedPrefix } from '../compact/forked-summary.mjs';
|
|
18
|
+
import { normalizeCompactionSummaryMode } from '../compact/summary-mode.mjs';
|
|
19
|
+
import { compactionCacheWarm, lighterSubscriptionModel } from '../compact/summary-route.mjs';
|
|
19
20
|
import { retireCompactionFork } from '../side-question-store.mjs';
|
|
20
21
|
|
|
21
22
|
// Conversation summarization triggers independently of the post-compact target:
|
|
@@ -24,52 +25,103 @@ import { retireCompactionFork } from '../side-question-store.mjs';
|
|
|
24
25
|
const CONVERSATION_COMPACT_TRIGGER_RATIO = 0.05;
|
|
25
26
|
const CONVERSATION_COMPACT_TRIGGER_MAX_TOKENS = 20_000;
|
|
26
27
|
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
|
|
28
|
+
// One summary route: the provider, its model and the window the summary
|
|
29
|
+
// request must fit. `source` names the step: 'session' (the conversation's
|
|
30
|
+
// own model), 'maintenance' (the Maintainer) or 'lighter' (the subscription
|
|
31
|
+
// provider's lighter model).
|
|
32
|
+
function summaryRoute({ sessionRef, provider, providerName, model, fast, source }) {
|
|
33
|
+
if (!provider || typeof provider.send !== 'function' || !model) {
|
|
34
|
+
throw new Error(`compact summary route unavailable: ${providerName || 'unknown'}/${model || 'unknown'}`);
|
|
35
|
+
}
|
|
36
|
+
const sameModel = providerName === sessionRef?.provider && model === sessionRef?.model;
|
|
37
|
+
const contextWindow =
|
|
38
|
+
sameModel && positiveInt(sessionRef?.contextWindow)
|
|
39
|
+
? positiveInt(sessionRef.contextWindow)
|
|
40
|
+
: resolveSessionContextMeta(provider, model, {}, { wholeWindow: true }).contextWindow;
|
|
41
|
+
return { provider, providerName, model, contextWindow, fast, source };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// The Maintainer's own model when one is set and enabled, whatever the memory
|
|
45
|
+
// or recap settings; null otherwise (an unrelated global default is never
|
|
46
|
+
// borrowed). Provider failures/cancellation are not absence and propagate.
|
|
47
|
+
async function resolveMaintainerRoute({ sessionRef, config, signal, getProviderFn, initProvidersFn }) {
|
|
48
|
+
const route = resolveMaintenanceRoute({ agent: 'cycle1-agent', config, includeDefault: false });
|
|
49
|
+
if (!(route?.provider && route?.model && config.providers?.[route.provider]?.enabled !== false)) return null;
|
|
50
|
+
await initProvidersFn(config.providers || {}, { signal });
|
|
51
|
+
signal?.throwIfAborted();
|
|
52
|
+
return summaryRoute({
|
|
53
|
+
sessionRef,
|
|
54
|
+
provider: getProviderFn(route.provider),
|
|
55
|
+
providerName: route.provider,
|
|
56
|
+
model: route.model,
|
|
57
|
+
fast: route.fast === true,
|
|
58
|
+
source: 'maintenance',
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function resolveSessionRoute({ sessionRef, provider, model, getProviderFn }) {
|
|
63
|
+
const providerName = sessionRef?.provider || provider?.name;
|
|
64
|
+
return summaryRoute({
|
|
65
|
+
sessionRef,
|
|
66
|
+
provider: provider || getProviderFn(providerName),
|
|
67
|
+
providerName,
|
|
68
|
+
model: model || sessionRef?.model,
|
|
69
|
+
source: 'session',
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// The newest lighter model of a subscription provider's saved account
|
|
74
|
+
// catalog; null on any other provider, without a saved catalog, when none is
|
|
75
|
+
// listed, or when the conversation already runs on it.
|
|
76
|
+
async function resolveLighterRoute(input) {
|
|
77
|
+
const session = resolveSessionRoute(input);
|
|
78
|
+
const lighter = await lighterSubscriptionModel(session.providerName);
|
|
79
|
+
input.signal?.throwIfAborted();
|
|
80
|
+
if (!lighter || lighter === session.model) return null;
|
|
81
|
+
return summaryRoute({
|
|
82
|
+
sessionRef: input.sessionRef,
|
|
83
|
+
provider: session.provider,
|
|
84
|
+
providerName: session.providerName,
|
|
85
|
+
model: lighter,
|
|
86
|
+
source: 'lighter',
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* The compaction summary plan (compact/summary-mode.mjs): the saved mode,
|
|
92
|
+
* whether the session's prompt cache is warm, and the routes in the order
|
|
93
|
+
* they are tried, each resolved only when reached (null = unavailable, the
|
|
94
|
+
* next one runs). The conversation's own model is always the last step.
|
|
95
|
+
*/
|
|
96
|
+
export function compactionSummaryPlan({
|
|
32
97
|
sessionRef,
|
|
98
|
+
sessionId = sessionRef?.id,
|
|
33
99
|
provider,
|
|
34
100
|
model,
|
|
35
101
|
config = loadConfig(),
|
|
36
102
|
signal,
|
|
37
103
|
getProviderFn = getProvider,
|
|
38
104
|
initProvidersFn = initProviders,
|
|
39
|
-
|
|
105
|
+
now = Date.now(),
|
|
40
106
|
} = {}) {
|
|
41
107
|
signal?.throwIfAborted();
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
if (
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
if (!selectedProvider || typeof selectedProvider.send !== 'function' || !selectedModel) {
|
|
53
|
-
throw new Error(`compact summary route unavailable: ${providerName || 'unknown'}/${selectedModel || 'unknown'}`);
|
|
54
|
-
}
|
|
55
|
-
const sameModel = providerName === sessionRef?.provider && selectedModel === sessionRef?.model;
|
|
56
|
-
const contextWindow =
|
|
57
|
-
sameModel && positiveInt(sessionRef?.contextWindow)
|
|
58
|
-
? positiveInt(sessionRef.contextWindow)
|
|
59
|
-
: resolveSessionContextMeta(selectedProvider, selectedModel, {}, { wholeWindow: true }).contextWindow;
|
|
60
|
-
return {
|
|
61
|
-
provider: selectedProvider,
|
|
62
|
-
providerName,
|
|
63
|
-
model: selectedModel,
|
|
64
|
-
contextWindow,
|
|
65
|
-
fast: useMaintenance ? route.fast === true : undefined,
|
|
66
|
-
source: useMaintenance ? 'maintenance' : 'session',
|
|
67
|
-
};
|
|
108
|
+
const input = { sessionRef, provider, model, config, signal, getProviderFn, initProvidersFn };
|
|
109
|
+
const mode = normalizeCompactionSummaryMode(config.compaction);
|
|
110
|
+
const warm = compactionCacheWarm(sessionId, now);
|
|
111
|
+
const session = async () => resolveSessionRoute(input);
|
|
112
|
+
const maintainer = () => resolveMaintainerRoute(input);
|
|
113
|
+
const lighter = () => resolveLighterRoute(input);
|
|
114
|
+
let steps = [session];
|
|
115
|
+
if (mode === 'maintainer') steps = [maintainer, session];
|
|
116
|
+
else if (mode === 'smart' && !warm) steps = [maintainer, lighter, session];
|
|
117
|
+
return { mode, warm, steps };
|
|
68
118
|
}
|
|
69
119
|
|
|
70
|
-
// The
|
|
71
|
-
//
|
|
72
|
-
//
|
|
120
|
+
// The summary request on one route: the conversation alone (earlier summary
|
|
121
|
+
// and dialogue; tool output, skills and injections excluded), never the
|
|
122
|
+
// cached context. Its input budget belongs to its OWN model, split into
|
|
123
|
+
// batches when the conversation is larger, whereas the rebuilt conversation
|
|
124
|
+
// must fit the original session's target/window.
|
|
73
125
|
function summarizeConversation(target, ctx) {
|
|
74
126
|
const { sessionRef, sessionId, signal, sendOpts, compactPolicy } = ctx;
|
|
75
127
|
const summaryWindow = positiveInt(target.contextWindow) || ctx.contextWindow;
|
|
@@ -117,24 +169,24 @@ function sumUsage(a, b) {
|
|
|
117
169
|
return Object.fromEntries(Object.keys(a).map((key) => [key, (a[key] || 0) + (Number(b[key]) || 0)]));
|
|
118
170
|
}
|
|
119
171
|
|
|
120
|
-
//
|
|
121
|
-
// the latest cached request
|
|
122
|
-
//
|
|
123
|
-
// sending the text-only transcript uncached, and the summary
|
|
124
|
-
// execution context. A
|
|
125
|
-
//
|
|
126
|
-
//
|
|
127
|
-
//
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
172
|
+
// The summary on one route. While the session's prompt cache is warm, the
|
|
173
|
+
// summary forks the latest cached request on the conversation's own model
|
|
174
|
+
// (compact/forked-summary.mjs): reading the cached context costs a tenth to a
|
|
175
|
+
// twentieth of sending the text-only transcript uncached, and the summary
|
|
176
|
+
// sees the full execution context. A cold cache would be rewritten in full,
|
|
177
|
+
// so the isolated text-only request runs instead; so does any other route
|
|
178
|
+
// (a cache is never shared across models). A fork that cannot run or fails
|
|
179
|
+
// falls back to the isolated request on the same route.
|
|
180
|
+
async function summarizeOnRoute(route, ctx, warm) {
|
|
181
|
+
const shared = warm
|
|
182
|
+
? await summarizeOnSharedPrefix({
|
|
183
|
+
sessionId: ctx.sessionId,
|
|
184
|
+
route,
|
|
185
|
+
conversationInput: ctx.conversationInput,
|
|
186
|
+
signal: ctx.signal,
|
|
187
|
+
timeoutMs: ctx.compactPolicy.handoffTimeoutMs,
|
|
188
|
+
})
|
|
189
|
+
: { fallback: 'cold_cache' };
|
|
138
190
|
if (shared.generated) return shared.generated;
|
|
139
191
|
ctx.signal?.throwIfAborted();
|
|
140
192
|
const generated = await summarizeConversation(route, ctx);
|
|
@@ -145,34 +197,45 @@ async function summarizeOnRoute(route, ctx) {
|
|
|
145
197
|
};
|
|
146
198
|
}
|
|
147
199
|
|
|
148
|
-
// A
|
|
149
|
-
// turn down: the
|
|
150
|
-
// summarize.
|
|
151
|
-
//
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
200
|
+
// A Maintainer or lighter model that is out of quota or not available to the
|
|
201
|
+
// account must not take the whole turn down: the next route still can
|
|
202
|
+
// summarize. Every other compaction failure (overflow, malformed summary,
|
|
203
|
+
// transport) keeps its existing handling, and an aborted turn stays aborted.
|
|
204
|
+
function fallsToNextRoute(error) {
|
|
205
|
+
const status = Number(error?.status || error?.httpStatus || error?.response?.status || 0);
|
|
206
|
+
return (
|
|
207
|
+
error?.code === 'provider_accounts_exhausted' ||
|
|
208
|
+
error?.code === 'model_not_found' ||
|
|
209
|
+
status === 429 ||
|
|
210
|
+
status === 404 ||
|
|
211
|
+
isAccountQuotaError(error)
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Resolving a route (provider init, catalog lookup) is part of its step: a
|
|
216
|
+
// quota or availability failure there moves to the next route like one from
|
|
217
|
+
// the summary request. The conversation's own model is the last step, so its
|
|
218
|
+
// failure always ends the compaction.
|
|
219
|
+
async function summarizeOnPlan(ctx, plan) {
|
|
220
|
+
const tried = new Set();
|
|
221
|
+
let failure = null;
|
|
222
|
+
for (const step of plan.steps) {
|
|
223
|
+
let route = null;
|
|
169
224
|
try {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
225
|
+
route = await step();
|
|
226
|
+
ctx.signal?.throwIfAborted();
|
|
227
|
+
const key = route && `${route.providerName}\u0000${route.model}`;
|
|
228
|
+
if (!route || tried.has(key)) continue;
|
|
229
|
+
tried.add(key);
|
|
230
|
+
return { route, generated: await summarizeOnRoute(route, ctx, plan.warm) };
|
|
231
|
+
} catch (error) {
|
|
232
|
+
ctx.signal?.throwIfAborted();
|
|
233
|
+
if (route) error.compactRoute = { provider: route.providerName, model: route.model };
|
|
234
|
+
if (route?.source === 'session' || !fallsToNextRoute(error)) throw error;
|
|
235
|
+
failure = error;
|
|
174
236
|
}
|
|
175
237
|
}
|
|
238
|
+
throw failure;
|
|
176
239
|
}
|
|
177
240
|
|
|
178
241
|
// The window this compaction must fit (calibrated to the provider's token
|
|
@@ -200,7 +263,10 @@ function freshContextBudget({ compactPolicy, sessionRef, provider, compactBudget
|
|
|
200
263
|
return { contextWindow, hardBudget, conversationInput, conversationTokens, conversationThresholdTokens };
|
|
201
264
|
}
|
|
202
265
|
|
|
203
|
-
function freshContextBuildOptions(
|
|
266
|
+
function freshContextBuildOptions(
|
|
267
|
+
{ compactPolicy = {}, sessionId, goalReminderText, activeTurn, referenceLatestAttachments },
|
|
268
|
+
budget
|
|
269
|
+
) {
|
|
204
270
|
return {
|
|
205
271
|
reserveTokens: compactPolicy.reserveTokens,
|
|
206
272
|
maxBudgetTokens: budget.hardBudget,
|
|
@@ -209,6 +275,7 @@ function freshContextBuildOptions({ compactPolicy = {}, sessionId, goalReminderT
|
|
|
209
275
|
sessionId,
|
|
210
276
|
latestUserPrefix: goalReminderText,
|
|
211
277
|
activeTurn,
|
|
278
|
+
referenceLatestAttachments: referenceLatestAttachments === true,
|
|
212
279
|
};
|
|
213
280
|
}
|
|
214
281
|
|
|
@@ -230,6 +297,27 @@ export function previewFreshContextCompaction(input) {
|
|
|
230
297
|
return { beforeTokens, afterTokens, reducesTokens: afterTokens < beforeTokens, summaryTriggered };
|
|
231
298
|
}
|
|
232
299
|
|
|
300
|
+
function buildFreshContextResult(
|
|
301
|
+
{ messages, compactBudgetTokens, buildOptions, requireReduction, sessionId },
|
|
302
|
+
handoffText
|
|
303
|
+
) {
|
|
304
|
+
const result = freshContextCompactMessages(messages, compactBudgetTokens, { ...buildOptions, handoffText });
|
|
305
|
+
// A generated summary can differ from its prediction. Never replace the
|
|
306
|
+
// original with an automatic result that is equal-sized or larger.
|
|
307
|
+
if (requireReduction && estimateMessagesTokens(result.messages) >= estimateMessagesTokens(messages)) {
|
|
308
|
+
return {
|
|
309
|
+
...result,
|
|
310
|
+
messages,
|
|
311
|
+
freshContext: false,
|
|
312
|
+
skipped: true,
|
|
313
|
+
diagnostics: { ...result.diagnostics, noOp: true, reason: 'no_token_reduction' },
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
// The rewritten transcript is no longer what the saved request carried.
|
|
317
|
+
if (result.freshContext) retireCompactionFork(sessionId);
|
|
318
|
+
return result;
|
|
319
|
+
}
|
|
320
|
+
|
|
233
321
|
export async function runFreshContextCompact({
|
|
234
322
|
sessionRef,
|
|
235
323
|
messages,
|
|
@@ -246,35 +334,19 @@ export async function runFreshContextCompact({
|
|
|
246
334
|
getProviderFn,
|
|
247
335
|
initProvidersFn,
|
|
248
336
|
requireReduction = false,
|
|
337
|
+
referenceLatestAttachments = false,
|
|
249
338
|
} = {}) {
|
|
250
339
|
const startedAt = Date.now();
|
|
251
340
|
signal?.throwIfAborted();
|
|
252
341
|
const { contextWindow, hardBudget, conversationInput, conversationTokens, conversationThresholdTokens } =
|
|
253
342
|
freshContextBudget({ compactPolicy, sessionRef, provider, compactBudgetTokens, messages });
|
|
254
343
|
const summaryTriggered = conversationTokens >= conversationThresholdTokens;
|
|
255
|
-
const
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
handoffText,
|
|
262
|
-
});
|
|
263
|
-
// A generated summary can differ from its prediction. Never replace the
|
|
264
|
-
// original with an automatic result that is equal-sized or larger.
|
|
265
|
-
if (requireReduction && estimateMessagesTokens(result.messages) >= estimateMessagesTokens(messages)) {
|
|
266
|
-
return {
|
|
267
|
-
...result,
|
|
268
|
-
messages,
|
|
269
|
-
freshContext: false,
|
|
270
|
-
skipped: true,
|
|
271
|
-
diagnostics: { ...result.diagnostics, noOp: true, reason: 'no_token_reduction' },
|
|
272
|
-
};
|
|
273
|
-
}
|
|
274
|
-
// The rewritten transcript is no longer what the saved request carried.
|
|
275
|
-
if (result.freshContext) retireCompactionFork(sessionId);
|
|
276
|
-
return result;
|
|
277
|
-
};
|
|
344
|
+
const buildOptions = freshContextBuildOptions(
|
|
345
|
+
{ compactPolicy, sessionId, goalReminderText, activeTurn, referenceLatestAttachments },
|
|
346
|
+
{ contextWindow, hardBudget }
|
|
347
|
+
);
|
|
348
|
+
const build = (handoffText) =>
|
|
349
|
+
buildFreshContextResult({ messages, compactBudgetTokens, buildOptions, requireReduction, sessionId }, handoffText);
|
|
278
350
|
const pipeline = {
|
|
279
351
|
mode: summaryTriggered ? 'conversation-summary' : 'rules',
|
|
280
352
|
conversationTokens,
|
|
@@ -291,7 +363,17 @@ export async function runFreshContextCompact({
|
|
|
291
363
|
pipeline: { ...pipeline, totalMs: Date.now() - startedAt },
|
|
292
364
|
});
|
|
293
365
|
}
|
|
294
|
-
const
|
|
366
|
+
const plan = compactionSummaryPlan({
|
|
367
|
+
sessionRef,
|
|
368
|
+
sessionId,
|
|
369
|
+
provider,
|
|
370
|
+
model,
|
|
371
|
+
config,
|
|
372
|
+
signal,
|
|
373
|
+
getProviderFn,
|
|
374
|
+
initProvidersFn,
|
|
375
|
+
});
|
|
376
|
+
const { route, generated } = await summarizeOnPlan(
|
|
295
377
|
{
|
|
296
378
|
sessionRef,
|
|
297
379
|
sessionId,
|
|
@@ -303,7 +385,7 @@ export async function runFreshContextCompact({
|
|
|
303
385
|
contextWindow,
|
|
304
386
|
conversationInput,
|
|
305
387
|
},
|
|
306
|
-
|
|
388
|
+
plan
|
|
307
389
|
);
|
|
308
390
|
signal?.throwIfAborted();
|
|
309
391
|
const result = build(generated.summary);
|
|
@@ -315,6 +397,8 @@ export async function runFreshContextCompact({
|
|
|
315
397
|
pipeline: {
|
|
316
398
|
...pipeline,
|
|
317
399
|
handoffSource: 'session-local',
|
|
400
|
+
summaryMode: plan.mode,
|
|
401
|
+
cacheWarm: plan.warm,
|
|
318
402
|
summaryRoute: route.source,
|
|
319
403
|
summaryProvider: route.providerName,
|
|
320
404
|
summaryModel: route.model,
|
|
@@ -8,6 +8,7 @@ import { resolveLiveToolCwd } from './tool-exec.mjs';
|
|
|
8
8
|
import { createSteeringDrain } from './steering.mjs';
|
|
9
9
|
import { createNoToolTurnResolver } from './no-tool-turn.mjs';
|
|
10
10
|
import { classifyTerminationReason } from './termination.mjs';
|
|
11
|
+
import { routeUsageSegments } from './usage.mjs';
|
|
11
12
|
|
|
12
13
|
// Consecutive identical-AND-failing tool calls (same name+args, error result)
|
|
13
14
|
// tolerated across iterations before the loop refuses to re-execute and steers
|
|
@@ -153,5 +154,13 @@ export function finishLoop(state) {
|
|
|
153
154
|
providerStateUpdated: state.providerStateUpdated,
|
|
154
155
|
terminationReason: classifyTerminationReason(response, { sessionAgent: state.sessionAgent }),
|
|
155
156
|
providerContinuations: state.noToolTurn.providerContinuations,
|
|
157
|
+
...(state.routeUsageHops?.length
|
|
158
|
+
? {
|
|
159
|
+
usageSegments: routeUsageSegments(state.routeUsageHops, state.lastUsage, {
|
|
160
|
+
provider: state.sessionRef?.provider,
|
|
161
|
+
model: state.sessionRef?.model,
|
|
162
|
+
}),
|
|
163
|
+
}
|
|
164
|
+
: {}),
|
|
156
165
|
};
|
|
157
166
|
}
|
|
@@ -16,7 +16,8 @@ import { isOffReadonlySurface } from './deferred-call-through.mjs';
|
|
|
16
16
|
import { BRIDGE_CALL_TOOL_NAME, bridgeErrorText, isToolBridgeEnabled } from '../../runtime-core/tool-bridge.mjs';
|
|
17
17
|
import { sessionAllowlistExcludes, sessionDisallows } from '../../runtime-core/deferred-tool-availability.mjs';
|
|
18
18
|
import { providerToolExclusionReason } from './provider-tool-exclusions.mjs';
|
|
19
|
-
import {
|
|
19
|
+
import { workflowOverlayDenial } from '../manager/workflow-switch-notice.mjs';
|
|
20
|
+
import { agentMcpToolPermission, connectorPolicyAgentOf, projectMcpToolDisabled } from '../../mcp/agent-connectors.mjs';
|
|
20
21
|
|
|
21
22
|
const WORKER_DENIED_TOOLS = new Set(['agent', 'ask_user', 'session']);
|
|
22
23
|
const BRIDGE_DISCOVERY_TOOL_NAMES = new Set(['load_tool']);
|
|
@@ -120,12 +121,15 @@ export function preDispatchDenyForSession(sessionRef, call) {
|
|
|
120
121
|
if (!bridgeDiscovery && sessionAllowlistExcludes(sessionRef, schemaName)) {
|
|
121
122
|
return `Error: tool "${name}" is not available on this session's schema allowlist.`;
|
|
122
123
|
}
|
|
124
|
+
// A workflow switched mid-conversation keeps the schema; its denials apply here.
|
|
125
|
+
const workflowDenial = workflowOverlayDenial(sessionRef, schemaName);
|
|
126
|
+
if (workflowDenial) return workflowDenial;
|
|
123
127
|
if (sessionDisallows(sessionRef, schemaName)) {
|
|
124
128
|
return `Error: tool "${name}" is not available in this session.`;
|
|
125
129
|
}
|
|
126
130
|
// An agent's connectors: a tool of a server it does not mount, or one set
|
|
127
131
|
// to `disabled`, stays refused though the process-wide registry knows it.
|
|
128
|
-
if (agentMcpToolPermission(sessionRef
|
|
132
|
+
if (agentMcpToolPermission(connectorPolicyAgentOf(sessionRef), schemaName) === 'disabled') {
|
|
129
133
|
return `Error: tool "${name}" is not available to this agent.`;
|
|
130
134
|
}
|
|
131
135
|
// The project the session runs in may switch a connector off as well.
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { routeFallbackVerdict } from '../../../../shared/model-route-fallback.mjs';
|
|
2
|
+
import { providerErrorKind } from '../../providers/provider-error-kind.mjs';
|
|
3
|
+
import { displayModelName } from '../../../../shared/model-display.mjs';
|
|
4
|
+
import { presentErrorText } from '../../../../shared/err-text.mjs';
|
|
2
5
|
import { getProvider, initProviders } from '../../providers/registry.mjs';
|
|
3
6
|
import { loadConfig } from '../../config.mjs';
|
|
4
7
|
import { ensureProviderEnabled } from '../../runtime-core/config-helpers.mjs';
|
|
@@ -7,19 +10,105 @@ import { pinSessionWireRoute } from '../../providers/wire-route.mjs';
|
|
|
7
10
|
import { buildRequestSendOptions } from '../manager/ask-turn-loop-options.mjs';
|
|
8
11
|
import { prepareTurnEffortConfiguration } from '../../providers/effort-configuration.mjs';
|
|
9
12
|
import { resolveSessionContextMeta } from '../manager/context-meta.mjs';
|
|
13
|
+
import { stripProviderReplayMessages } from '../manager/provider-replay.mjs';
|
|
14
|
+
|
|
15
|
+
// The short reason a notice gives for leaving a model, by provider kind.
|
|
16
|
+
const HOP_REASONS = {
|
|
17
|
+
quota_exhausted: 'usage limit reached',
|
|
18
|
+
entitlement: 'not included in the plan',
|
|
19
|
+
billing: 'out of credits',
|
|
20
|
+
rate_limited: 'rate-limited',
|
|
21
|
+
overloaded: 'unavailable',
|
|
22
|
+
transient: 'unavailable',
|
|
23
|
+
service_tier_unavailable: 'unavailable',
|
|
24
|
+
auth: 'sign-in failed',
|
|
25
|
+
permission: 'access denied',
|
|
26
|
+
invalid_request: 'model not available',
|
|
27
|
+
context_overflow: 'context too long',
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const routeLabel = (route) => displayModelName(route.model, route.provider) || `${route.provider}/${route.model}`;
|
|
31
|
+
|
|
32
|
+
/** The muted transcript line for a hop: `<from> <reason> — switched to <to>.` */
|
|
33
|
+
export function routeFallbackNoticeText(from, to, error) {
|
|
34
|
+
const reason = HOP_REASONS[providerErrorKind(error).kind] || 'unavailable';
|
|
35
|
+
return `${routeLabel(from)} ${reason} — switched to ${routeLabel(to)}.`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function routeFailure(route, error) {
|
|
39
|
+
return {
|
|
40
|
+
provider: route.provider,
|
|
41
|
+
model: route.model,
|
|
42
|
+
kind: providerErrorKind(error).kind,
|
|
43
|
+
error: presentErrorText(error),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// The chain ended after at least one hop: the final error keeps its own kind
|
|
48
|
+
// and names every model that was tried and why each failed. `skipped` is the
|
|
49
|
+
// next route when the chain stopped before it (a context overflow whose next
|
|
50
|
+
// window is no larger), so the text says why instead of "every model failed".
|
|
51
|
+
function annotateEndedChain(session, error, skipped = null) {
|
|
52
|
+
const tried = session?.routeFallbackFailures;
|
|
53
|
+
if (!tried?.length || !error || typeof error !== 'object' || error.routeFallbackAttempts) return;
|
|
54
|
+
const attempts = [...tried, routeFailure(session, error)];
|
|
55
|
+
try {
|
|
56
|
+
error.routeFallbackAttempts = attempts;
|
|
57
|
+
const lines = attempts.map((attempt) => `${routeLabel(attempt)}: ${attempt.error}`).join('; ');
|
|
58
|
+
const head = skipped
|
|
59
|
+
? `Fallback chain stopped before ${routeLabel(skipped)} (its context window is not larger) — tried`
|
|
60
|
+
: 'Every model in the fallback chain failed —';
|
|
61
|
+
error.message = `${error.message}\n${head} ${lines}`;
|
|
62
|
+
if (skipped) error.routeFallbackStoppedBefore = { provider: skipped.provider, model: skipped.model };
|
|
63
|
+
} catch {
|
|
64
|
+
/* frozen errors keep their own message */
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// A context overflow moves only to a model whose window is larger.
|
|
69
|
+
async function nextContextGrows(state, next) {
|
|
70
|
+
await initProviders(ensureProviderEnabled(loadConfig(), next.provider), { signal: state.signal });
|
|
71
|
+
state.throwIfAborted();
|
|
72
|
+
const provider = getProvider(next.provider);
|
|
73
|
+
if (!provider) return false;
|
|
74
|
+
const current = resolveSessionContextMeta(state.provider, state.sessionRef.model, state.sessionRef).rawContextWindow;
|
|
75
|
+
const window = resolveSessionContextMeta(provider, next.model, next).rawContextWindow;
|
|
76
|
+
return Number(window) > Number(current || state.sessionRef.selectedContextWindow || 0);
|
|
77
|
+
}
|
|
10
78
|
|
|
11
79
|
export async function advanceAgentRoute(state, error) {
|
|
12
80
|
const session = state.sessionRef;
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
|
|
81
|
+
if (!session?.agent || !session.routeFallbacks?.length) return false;
|
|
82
|
+
const index = session.routeFallbackIndex || 0;
|
|
83
|
+
const next = session.routeFallbacks[index];
|
|
84
|
+
// Only THIS request must have produced nothing (its stream outcome says so):
|
|
85
|
+
// earlier requests of the turn may have run tools. Their calls and results
|
|
86
|
+
// are already in the live turn, which the next model continues from, so no
|
|
87
|
+
// completed tool runs again.
|
|
88
|
+
const verdict = routeFallbackVerdict(error, { signal: state.signal });
|
|
89
|
+
const hops = verdict === 'hop' || (verdict === 'context' && next && (await nextContextGrows(state, next)));
|
|
90
|
+
if (!next || !hops) {
|
|
91
|
+
if (verdict !== 'stay') annotateEndedChain(session, error, next || null);
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
17
94
|
state.throwIfAborted();
|
|
18
|
-
|
|
19
|
-
await initProviders(config.providers, { signal: state.signal });
|
|
95
|
+
await initProviders(ensureProviderEnabled(loadConfig(), next.provider), { signal: state.signal });
|
|
20
96
|
state.throwIfAborted();
|
|
21
97
|
const provider = getProvider(next.provider);
|
|
22
98
|
if (!provider) throw new Error(`Provider "${next.provider}" not available`);
|
|
99
|
+
const failed = routeFailure(session, error);
|
|
100
|
+
// The left model's share of the turn ends here: the running total at the
|
|
101
|
+
// switch bounds it, so each model's tokens are booked at its own rates.
|
|
102
|
+
state.routeUsageHops = [
|
|
103
|
+
...(state.routeUsageHops || []),
|
|
104
|
+
{ provider: session.provider, model: session.model, usage: state.lastUsage ? { ...state.lastUsage } : null },
|
|
105
|
+
];
|
|
106
|
+
const notice = routeFallbackNoticeText(session, next, error);
|
|
107
|
+
// Saved with the new route: a crash before the live turn is checkpointed
|
|
108
|
+
// again recovers that turn without the previous provider's native state.
|
|
109
|
+
if (session.activeTurnCheckpoint && typeof session.activeTurnCheckpoint === 'object') {
|
|
110
|
+
session.activeTurnCheckpoint = { ...session.activeTurnCheckpoint, routeChanged: true };
|
|
111
|
+
}
|
|
23
112
|
const oldOptions = buildRequestSendOptions({
|
|
24
113
|
sessionId: state.sessionId,
|
|
25
114
|
session,
|
|
@@ -37,13 +126,18 @@ export async function advanceAgentRoute(state, error) {
|
|
|
37
126
|
contextTokens: next.contextTokens,
|
|
38
127
|
selectedContextWindow: resolveSessionContextMeta(provider, next.model, next).rawContextWindow,
|
|
39
128
|
},
|
|
40
|
-
|
|
129
|
+
// The live turn object is what changes: the route is applied to it in place, never to
|
|
130
|
+
// another copy of the id (a disk reload after a generation takeover).
|
|
131
|
+
{ crossProvider: true, session }
|
|
41
132
|
);
|
|
42
133
|
if (!updated) throw new Error('agent session closed during model fallback');
|
|
43
134
|
updated.routeFallbackIndex = index + 1;
|
|
135
|
+
updated.routeFallbackFailures = [...(session.routeFallbackFailures || []), failed];
|
|
44
136
|
await pinSessionWireRoute(updated, provider);
|
|
45
137
|
state.throwIfAborted();
|
|
46
|
-
|
|
138
|
+
// The live turn (prompt, assistant tool calls, tool results) carries on;
|
|
139
|
+
// only the previous provider's native replay state is dropped from it.
|
|
140
|
+
state.messages.splice(0, state.messages.length, ...stripProviderReplayMessages(state.messages));
|
|
47
141
|
updated.liveTurnMessages = state.messages;
|
|
48
142
|
state.sessionRef = updated;
|
|
49
143
|
state.provider = provider;
|
|
@@ -67,6 +161,14 @@ export async function advanceAgentRoute(state, error) {
|
|
|
67
161
|
signal: state.signal,
|
|
68
162
|
})
|
|
69
163
|
);
|
|
164
|
+
try {
|
|
165
|
+
process.stderr.write(
|
|
166
|
+
`[route-fallback] ${failed.provider}/${failed.model} (${failed.kind}) -> ${updated.provider}/${updated.model}\n`
|
|
167
|
+
);
|
|
168
|
+
state.opts.onStageChange?.('notice', { tone: 'info', message: notice });
|
|
169
|
+
} catch {
|
|
170
|
+
/* display-only */
|
|
171
|
+
}
|
|
70
172
|
state.opts.onStageChange?.('connecting', {
|
|
71
173
|
provider: updated.provider,
|
|
72
174
|
model: updated.model,
|