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
|
@@ -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,
|
|
@@ -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.
|
|
@@ -67,8 +67,7 @@ function annotateEndedChain(session, error, skipped = null) {
|
|
|
67
67
|
|
|
68
68
|
// A context overflow moves only to a model whose window is larger.
|
|
69
69
|
async function nextContextGrows(state, next) {
|
|
70
|
-
|
|
71
|
-
await initProviders(config.providers, { signal: state.signal });
|
|
70
|
+
await initProviders(ensureProviderEnabled(loadConfig(), next.provider), { signal: state.signal });
|
|
72
71
|
state.throwIfAborted();
|
|
73
72
|
const provider = getProvider(next.provider);
|
|
74
73
|
if (!provider) return false;
|
|
@@ -93,8 +92,7 @@ export async function advanceAgentRoute(state, error) {
|
|
|
93
92
|
return false;
|
|
94
93
|
}
|
|
95
94
|
state.throwIfAborted();
|
|
96
|
-
|
|
97
|
-
await initProviders(config.providers, { signal: state.signal });
|
|
95
|
+
await initProviders(ensureProviderEnabled(loadConfig(), next.provider), { signal: state.signal });
|
|
98
96
|
state.throwIfAborted();
|
|
99
97
|
const provider = getProvider(next.provider);
|
|
100
98
|
if (!provider) throw new Error(`Provider "${next.provider}" not available`);
|
|
@@ -128,7 +126,9 @@ export async function advanceAgentRoute(state, error) {
|
|
|
128
126
|
contextTokens: next.contextTokens,
|
|
129
127
|
selectedContextWindow: resolveSessionContextMeta(provider, next.model, next).rawContextWindow,
|
|
130
128
|
},
|
|
131
|
-
|
|
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 }
|
|
132
132
|
);
|
|
133
133
|
if (!updated) throw new Error('agent session closed during model fallback');
|
|
134
134
|
updated.routeFallbackIndex = index + 1;
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* consume a retry verdict, and settle a completed send into the loop state.
|
|
5
5
|
*/
|
|
6
6
|
import { traceCacheBreak } from '../../cache-break-trace.mjs';
|
|
7
|
+
import { anthropicPrefixChanges } from '../../providers/lib/anthropic-prefix-trace.mjs';
|
|
7
8
|
import { resolveLiveToolCwd } from './tool-exec.mjs';
|
|
8
9
|
import { notifySkillsApplied, prepareExplicitSkills, recordAppliedSkills } from '../explicit-skills.mjs';
|
|
9
10
|
import { addUsage, usageDeltaEvent } from './usage.mjs';
|
|
@@ -352,6 +353,8 @@ function traceActualCacheMiss(state, sent, response, { previousGuardState, previ
|
|
|
352
353
|
previousCachedPrefixTokens: baseline,
|
|
353
354
|
idleMs,
|
|
354
355
|
missingPrefixGuardBaseline: !previousGuardState,
|
|
356
|
+
// Which wire block moved ('none': same bytes, so the cache itself dropped it).
|
|
357
|
+
...anthropicPrefixChanges(sessionId),
|
|
355
358
|
},
|
|
356
359
|
state.cacheBreakTraceOptions
|
|
357
360
|
);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Steering-message normalization/merge helpers.
|
|
2
2
|
// Merges queued steering entries into a single content payload + display text.
|
|
3
3
|
import { stableMessageId } from '../../../../shared/transcript-metadata.mjs';
|
|
4
|
+
import { raiseTurnHop } from '../../../../shared/bot-hops.mjs';
|
|
4
5
|
|
|
5
6
|
function steeringContentText(content) {
|
|
6
7
|
if (typeof content === 'string') return content;
|
|
@@ -140,6 +141,8 @@ function injectSteeringEntry(merged, { messages, opts, stage, onSkillPrompt }) {
|
|
|
140
141
|
// gets it back (onSteerMessage) for the row it draws. A steered prompt
|
|
141
142
|
// keeps the id the surface gave it, else gets one.
|
|
142
143
|
const messageId = stableMessageId(merged.transcriptMeta?.messageId);
|
|
144
|
+
// A bot's message at a higher hop makes the running turn bot-descended at that hop.
|
|
145
|
+
raiseTurnHop(opts.session, merged.transcriptMeta);
|
|
143
146
|
const steeringTranscriptMeta =
|
|
144
147
|
merged.transcriptMeta && typeof merged.transcriptMeta === 'object'
|
|
145
148
|
? { at: submittedAt ?? injectedAt, ...merged.transcriptMeta, messageId }
|
|
@@ -6,15 +6,20 @@ import { resolvePreToolAskApproval } from '../tool-helpers.mjs';
|
|
|
6
6
|
import { runAbortable, throwIfAborted } from '../../../../../shared/abort-race.mjs';
|
|
7
7
|
import { evaluateExecPolicy } from '../../../tools/bash-policy-scan.mjs';
|
|
8
8
|
import { beginSessionApprovalWait } from '../../manager/runtime-liveness.mjs';
|
|
9
|
-
import { agentMcpToolPermission } from '../../../mcp/agent-connectors.mjs';
|
|
10
|
-
import {
|
|
9
|
+
import { agentMcpToolPermission, writeAgentMcpToolPermission } from '../../../mcp/agent-connectors.mjs';
|
|
10
|
+
import {
|
|
11
|
+
actingContactBotId,
|
|
12
|
+
humanGateDecision,
|
|
13
|
+
recordHumanDecision,
|
|
14
|
+
rememberSurfaceOf,
|
|
15
|
+
} from '../../human-gate/gate.mjs';
|
|
11
16
|
import { applyEditedArgs } from '../../human-gate/requests.mjs';
|
|
12
17
|
|
|
13
18
|
const isArgsObject = (value) => value && typeof value === 'object' && !Array.isArray(value);
|
|
14
19
|
|
|
15
20
|
async function askApproval(
|
|
16
21
|
call,
|
|
17
|
-
{ callerSessionId, executeOpts, toolApprovalHook, decision, request = null, gate = null }
|
|
22
|
+
{ callerSessionId, executeOpts, toolApprovalHook, decision, request = null, gate = null, onApproved = null }
|
|
18
23
|
) {
|
|
19
24
|
const askReason = String(decision?.reason || 'approval requested by hook').trim();
|
|
20
25
|
// While the user decides, the session is waiting on them, not working.
|
|
@@ -46,26 +51,52 @@ async function askApproval(
|
|
|
46
51
|
}
|
|
47
52
|
// The user approved this very call on the richer outbound card.
|
|
48
53
|
if (request?.kind === 'outbound') call.outboundApproved = true;
|
|
54
|
+
await onApproved?.(approval);
|
|
49
55
|
return null;
|
|
50
56
|
}
|
|
51
57
|
|
|
58
|
+
/** The renderer translates this exact text (desktop-toasts.tsx ALLOW_NOT_SAVED_TEXT). */
|
|
59
|
+
export const ALLOW_NOT_SAVED_NOTICE = 'Allowed this once. The setting could not be saved.';
|
|
52
60
|
export const CONNECTOR_APPROVAL_REASON = 'This connector tool is set to ask before it runs for this agent.';
|
|
53
61
|
|
|
54
62
|
/**
|
|
55
63
|
* A connector tool the running agent set to `needs_approval` asks through the
|
|
56
64
|
* ordinary approval hook, whatever the PreToolUse hooks decided. Run after
|
|
57
65
|
* them, on the final call: a renamed call is judged under its final name.
|
|
58
|
-
* A call the outbound
|
|
66
|
+
* A call the outbound gate owns (its card approved it, or a remembered
|
|
67
|
+
* outbound grant answered it) is not asked a second time.
|
|
59
68
|
* @returns {Promise<{ denial: string } | null>} the denial, or null to run
|
|
60
69
|
*/
|
|
61
70
|
export function applyConnectorApproval(call, { agentId, callerSessionId, executeOpts, toolApprovalHook }) {
|
|
62
71
|
if (call.outboundApproved) return null;
|
|
63
72
|
if (agentMcpToolPermission(agentId, call.name) !== 'needs_approval') return null;
|
|
73
|
+
// "Always allow" is offered only to the contact bot that is acting, for its
|
|
74
|
+
// own policy entry for this one tool: never another bot, Mixy or the Lead.
|
|
75
|
+
const botId = actingContactBotId(callerSessionId);
|
|
76
|
+
const rememberable = Boolean(botId) && botId === agentId;
|
|
64
77
|
return askApproval(call, {
|
|
65
78
|
callerSessionId,
|
|
66
79
|
executeOpts,
|
|
67
80
|
toolApprovalHook,
|
|
68
81
|
decision: { reason: CONNECTOR_APPROVAL_REASON },
|
|
82
|
+
request: rememberable
|
|
83
|
+
? {
|
|
84
|
+
kind: 'approval',
|
|
85
|
+
agentId: botId,
|
|
86
|
+
remember: ['once', 'agent'],
|
|
87
|
+
rememberAt: rememberSurfaceOf(callerSessionId),
|
|
88
|
+
}
|
|
89
|
+
: null,
|
|
90
|
+
onApproved: async (approval) => {
|
|
91
|
+
if (!rememberable || approval?.remember !== 'agent') return;
|
|
92
|
+
try {
|
|
93
|
+
if (await writeAgentMcpToolPermission(botId, call.name, 'auto')) return;
|
|
94
|
+
} catch {
|
|
95
|
+
// fall through to the notice below
|
|
96
|
+
}
|
|
97
|
+
// Not saved: this call still runs once, and the next one asks again.
|
|
98
|
+
toolApprovalHook?.notice?.(ALLOW_NOT_SAVED_NOTICE, 'warn');
|
|
99
|
+
},
|
|
69
100
|
});
|
|
70
101
|
}
|
|
71
102
|
|
|
@@ -120,7 +151,7 @@ export async function applyBeforeToolHook({
|
|
|
120
151
|
// Judged as the call will run: only a rewriting decision changes name/args.
|
|
121
152
|
const hookAction = String(hookDecision?.action || hookDecision?.decision || '').toLowerCase();
|
|
122
153
|
const rewritten = hookAction === 'ask' || hookAction === 'modify' || hookAction === 'rewrite';
|
|
123
|
-
const { decision, request, gate } = await humanGateDecision(
|
|
154
|
+
const { decision, request, gate, remembered } = await humanGateDecision(
|
|
124
155
|
{
|
|
125
156
|
name:
|
|
126
157
|
rewritten && typeof hookDecision?.name === 'string' && hookDecision.name.trim()
|
|
@@ -132,6 +163,8 @@ export async function applyBeforeToolHook({
|
|
|
132
163
|
{ sessionId: callerSessionId, mcpScopeId }
|
|
133
164
|
);
|
|
134
165
|
const action = String(decision?.action || decision?.decision || '').toLowerCase();
|
|
166
|
+
// A remembered outbound grant answered this call: the connector ask is not repeated.
|
|
167
|
+
if (remembered) call.outboundApproved = true;
|
|
135
168
|
if (action === 'deny' || action === 'block') {
|
|
136
169
|
const reason = decision?.reason ? `: ${decision.reason}` : '';
|
|
137
170
|
return { denial: `Error: tool "${name}" denied by hook${reason}` };
|
|
@@ -17,6 +17,26 @@ import { isOnDeferredToolSurface } from '../deferred-call-through.mjs';
|
|
|
17
17
|
import { _executeCodeGraphToolLazy } from '../../manager/runtime-loaders.mjs';
|
|
18
18
|
import { requiresReadBody } from '../tool-classify.mjs';
|
|
19
19
|
import { executeCursorNativeBuiltin } from '../../../tools/builtin/external-tool-adapters.mjs';
|
|
20
|
+
import { providerNativePdf, providerReadsImages } from '../../../providers/registry.mjs';
|
|
21
|
+
import { getModelMetadataSync } from '../../../../../shared/llm/model-catalog.mjs';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* How read returns a PDF to this session's model. Native PDF support decides
|
|
25
|
+
* only whether a short PDF may arrive whole as a document block. A scanned
|
|
26
|
+
* page arrives as a page image whenever the model sees images — the provider
|
|
27
|
+
* sends image input (only the text-only local runtime does not) and the
|
|
28
|
+
* catalog does not say the model lacks it — and as OCR text otherwise.
|
|
29
|
+
*/
|
|
30
|
+
export function pdfReadModes(
|
|
31
|
+
sessionRef,
|
|
32
|
+
{ nativePdf = providerNativePdf, readsImages = providerReadsImages, catalogRow = getModelMetadataSync } = {}
|
|
33
|
+
) {
|
|
34
|
+
const provider = sessionRef?.provider;
|
|
35
|
+
const model = sessionRef?.model;
|
|
36
|
+
const seesImages =
|
|
37
|
+
readsImages(provider) && (model ? catalogRow(model, provider)?.supportsVision : undefined) !== false;
|
|
38
|
+
return { pdfPageMode: seesImages ? 'image' : 'ocr', pdfNativeDocument: nativePdf(provider) };
|
|
39
|
+
}
|
|
20
40
|
|
|
21
41
|
function dispatchMcp(name, args, { cwd, callerSessionId, sessionRef, executeOpts }) {
|
|
22
42
|
const mcpScopeId = sessionRef?.mcpScopeId || null;
|
|
@@ -107,6 +127,7 @@ export function dispatchToolCall({ name, args }, ctx) {
|
|
|
107
127
|
: {}),
|
|
108
128
|
// Runtime-granted only; any value inherited from executeOpts is overridden.
|
|
109
129
|
elevationApproved: ctx.elevationApproved === true,
|
|
130
|
+
...pdfReadModes(sessionRef),
|
|
110
131
|
};
|
|
111
132
|
return executeCursorNativeBuiltin(
|
|
112
133
|
name,
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
// tool-exec/after-hook.mjs — PostToolUse result override
|
|
7
7
|
// tool-exec/read-only-deadline.mjs — bounded read-only I/O with partial-output grace
|
|
8
8
|
import { isMcpTool } from '../../mcp/client.mjs';
|
|
9
|
+
import { connectorPolicyAgentOf } from '../../mcp/agent-connectors.mjs';
|
|
9
10
|
import { prepareDeferredToolCallThrough } from './deferred-call-through.mjs';
|
|
10
11
|
import { refreshDeferredMcpToolCatalog } from '../../runtime-core/tool-catalog.mjs';
|
|
11
12
|
import { bridgeTargetUnavailable } from '../../runtime-core/tool-bridge.mjs';
|
|
@@ -54,7 +55,7 @@ async function executeToolOwned(name, args, cwd, callerSessionId, sessionRef, ex
|
|
|
54
55
|
});
|
|
55
56
|
if (hooked.denial) return hooked.denial;
|
|
56
57
|
const connectorDenied = await applyConnectorApproval(hooked, {
|
|
57
|
-
agentId: sessionRef
|
|
58
|
+
agentId: connectorPolicyAgentOf(sessionRef),
|
|
58
59
|
callerSessionId,
|
|
59
60
|
executeOpts,
|
|
60
61
|
toolApprovalHook,
|