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
|
@@ -15,10 +15,11 @@ import { loadConfig } from '../../config.mjs';
|
|
|
15
15
|
import {
|
|
16
16
|
buildProviderCacheOpts,
|
|
17
17
|
cacheCapabilityForProvider,
|
|
18
|
+
isLeadCacheClass,
|
|
18
19
|
roleProviderCacheOpts,
|
|
19
20
|
} from '../../agent-runtime/cache-strategy.mjs';
|
|
20
21
|
import { normalizeAutoClearConfig, resolveAutoClearIdleMs } from '../../runtime-core/config-helpers.mjs';
|
|
21
|
-
import { _buildBaseRules } from './rules-cache.mjs';
|
|
22
|
+
import { _buildBaseRules, promptRulesRevision } from './rules-cache.mjs';
|
|
22
23
|
import { stripProviderReplayMessages } from './provider-replay.mjs';
|
|
23
24
|
import { composeSessionSystem, seedSessionMessages } from './session-prompt-composition.mjs';
|
|
24
25
|
import { agentProfileRevision, leadRosterRevision } from '../../context/role-instructions.mjs';
|
|
@@ -41,6 +42,7 @@ import { ensureCodexWireSessionId, mintSessionId } from './session-id.mjs';
|
|
|
41
42
|
import { providerCacheKey } from './provider-cache-key.mjs';
|
|
42
43
|
import { buildSessionRecord, normalizeDesktopSessionMetadata, sessionOriginFields } from './session-record.mjs';
|
|
43
44
|
import { normalizeWorkflowRoute } from '../../runtime-core/workflow.mjs';
|
|
45
|
+
import { ownerRouteFallbacks } from './owner-route-fallbacks.mjs';
|
|
44
46
|
import { applyPendingWorkspaceReroot, refreshSessionBp3Environment } from './prompt-utils.mjs';
|
|
45
47
|
import { isWorktreeBound } from '../../../../shared/worktrees/contract.mjs';
|
|
46
48
|
import { applyAgentToolExposure } from '../loop/tool-exposure-migration.mjs';
|
|
@@ -53,17 +55,20 @@ export { recoverSessionAfterProcessRestart } from './turn-checkpoint-recovery.mj
|
|
|
53
55
|
// re-exported so prior importers of this module stay unchanged.
|
|
54
56
|
export { prefetchSession, prepareSessionProjection } from './prepared-resume-cache.mjs';
|
|
55
57
|
|
|
56
|
-
|
|
58
|
+
// `session` is the record or create options; it classifies agent-mode Leads
|
|
59
|
+
// (bot home threads, routine runs) into the Lead cache class.
|
|
60
|
+
function buildSessionProviderCacheOpts(providerName, sessionId, agent = null, config = null, session = null) {
|
|
57
61
|
// Keep this in sync with createSession's provider-cache policy: only
|
|
58
|
-
// explicit-breakpoint providers get BP cache opts here;
|
|
59
|
-
// providers use promptCacheKey and request-time strategy instead
|
|
60
|
-
//
|
|
62
|
+
// explicit-breakpoint providers get BP cache opts here; key-prefix
|
|
63
|
+
// providers use promptCacheKey and request-time strategy instead (plus the
|
|
64
|
+
// OpenAI API's Lead-class 12h prefix TTL and a one-shot role's shared
|
|
65
|
+
// prompt-cache scope).
|
|
61
66
|
if (cacheCapabilityForProvider(providerName) !== 'explicit-breakpoint') {
|
|
62
|
-
return roleProviderCacheOpts(providerName, agent);
|
|
67
|
+
return roleProviderCacheOpts(providerName, agent, { session });
|
|
63
68
|
}
|
|
64
69
|
try {
|
|
65
70
|
let autoClear = null;
|
|
66
|
-
if (
|
|
71
|
+
if (isLeadCacheClass(agent, session)) {
|
|
67
72
|
const loadedConfig = config || loadConfig({ secrets: false });
|
|
68
73
|
const normalizedAutoClear = normalizeAutoClearConfig(loadedConfig?.autoClear);
|
|
69
74
|
autoClear = {
|
|
@@ -71,20 +76,23 @@ function buildSessionProviderCacheOpts(providerName, sessionId, agent = null, co
|
|
|
71
76
|
idleMs: resolveAutoClearIdleMs(loadedConfig, providerName),
|
|
72
77
|
};
|
|
73
78
|
}
|
|
74
|
-
return buildProviderCacheOpts(providerName, sessionId, agent, { autoClear });
|
|
79
|
+
return buildProviderCacheOpts(providerName, sessionId, agent, { autoClear, session });
|
|
75
80
|
} catch {
|
|
76
81
|
return null;
|
|
77
82
|
}
|
|
78
83
|
}
|
|
79
84
|
|
|
80
|
-
// Re-derive a Lead session's builder-made cache policy (
|
|
81
|
-
// the auto-clear idle window
|
|
82
|
-
//
|
|
85
|
+
// Re-derive a Lead-class session's builder-made cache policy (Anthropic
|
|
86
|
+
// messages TTL follows the auto-clear idle window; the OpenAI API prefix TTL
|
|
87
|
+
// follows the cache class). Explicit caller/profile policies, sub-agents and
|
|
88
|
+
// other providers are left untouched.
|
|
83
89
|
export function refreshSessionProviderCacheOpts(session, config = null) {
|
|
84
90
|
if (!session || session.providerCacheOptsOverride === true) return false;
|
|
85
|
-
if (session.agent
|
|
86
|
-
if (cacheCapabilityForProvider(session.provider) !== 'explicit-breakpoint')
|
|
87
|
-
|
|
91
|
+
if (!isLeadCacheClass(session.agent, session)) return false;
|
|
92
|
+
if (cacheCapabilityForProvider(session.provider) !== 'explicit-breakpoint' && session.provider !== 'openai') {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
const next = buildSessionProviderCacheOpts(session.provider, session.id, session.agent, config, session);
|
|
88
96
|
if (!next) return false;
|
|
89
97
|
session.providerCacheOpts = next;
|
|
90
98
|
return true;
|
|
@@ -225,26 +233,35 @@ export function createSession(createOpts) {
|
|
|
225
233
|
sessionMode === AGENT_MODE && !createOpts.agent && actingAgent
|
|
226
234
|
? { ...createOpts, agent: actingAgent, sessionMode }
|
|
227
235
|
: { ...createOpts, sessionMode };
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
236
|
+
// A Lead-class session (actingAgent set) takes its owner's chain while it
|
|
237
|
+
// runs on the owner's primary model; an agent keeps its preset's.
|
|
238
|
+
const routeFallbacks = actingAgent
|
|
239
|
+
? Object.hasOwn(opts, 'routeFallbacks')
|
|
240
|
+
? opts.routeFallbacks
|
|
241
|
+
: ownerRouteFallbacks({ sessionMode, agentId: actingAgent, provider: providerName, model: modelName })
|
|
242
|
+
: normalizeWorkflowRoute({
|
|
243
|
+
provider: providerName,
|
|
244
|
+
model: modelName,
|
|
245
|
+
fallbacks: Object.hasOwn(opts, 'routeFallbacks') ? opts.routeFallbacks : presetObj?.fallbacks,
|
|
246
|
+
})?.fallbacks;
|
|
233
247
|
// Provider cache strategy — agentRuntime.resolveSync() above is a
|
|
234
248
|
// best-effort injection point (setAgentRuntime() has no live caller
|
|
235
249
|
// today, so that branch never fires); build it directly here so every
|
|
236
|
-
// session still gets a cache strategy. Lead sessions (
|
|
237
|
-
//
|
|
238
|
-
// tail TTL linked to the user's autoClear idle-sweep config
|
|
239
|
-
//
|
|
240
|
-
//
|
|
241
|
-
const providerCacheOpts =
|
|
250
|
+
// session still gets a cache strategy. Lead-class sessions (the Lead, raw
|
|
251
|
+
// callers, bot home threads and other agent-mode Leads) get their BP4
|
|
252
|
+
// message tail TTL linked to the user's autoClear idle-sweep config and,
|
|
253
|
+
// on the OpenAI API, the 12h stable-prefix TTL; sub-agents and hidden roles
|
|
254
|
+
// keep the agent defaults (see cache-strategy.mjs docs).
|
|
255
|
+
const providerCacheOpts =
|
|
256
|
+
resolved.providerCacheOpts || buildSessionProviderCacheOpts(providerName, id, opts.agent, null, { ...opts, id });
|
|
242
257
|
const surface = resolveSessionToolSurface(opts, { profile, toolPreset, modelName });
|
|
243
258
|
// The agent profile the prompt is composed from, read first: an edit landing
|
|
244
259
|
// during composition leaves the stamp behind, never ahead (refreshAgentProfile).
|
|
245
260
|
const agentProfile = surface.ownerIsAgent
|
|
246
261
|
? ''
|
|
247
262
|
: agentProfileRevision(surface.resolvedAgent, { mixy: sessionMode === AGENT_MODE });
|
|
263
|
+
// A bot thread lives on across releases: the rules it was built from.
|
|
264
|
+
const rulesRevision = agentProfile && sessionMode === AGENT_MODE ? promptRulesRevision() : '';
|
|
248
265
|
const prompt = composeSessionSystem(opts, { profile, providerName, modelName, surface, sessionMode });
|
|
249
266
|
const messages = seedSessionMessages(prompt, opts.files);
|
|
250
267
|
logSessionSurface(surface);
|
|
@@ -268,6 +285,7 @@ export function createSession(createOpts) {
|
|
|
268
285
|
session.agentProfileRevision = agentProfile;
|
|
269
286
|
// The bot roster its prompt lists (a Lead's catalog slices).
|
|
270
287
|
session.agentRosterRevision = leadRosterRevision(opts.leadWorkflowParts);
|
|
288
|
+
if (rulesRevision) session.rulesRevision = rulesRevision;
|
|
271
289
|
}
|
|
272
290
|
if (routeFallbacks?.length) session.routeFallbacks = routeFallbacks;
|
|
273
291
|
// A non-native agent sends core + bridge, built from its filtered tools.
|
|
@@ -340,6 +358,13 @@ function applyRouteFields(session, route) {
|
|
|
340
358
|
else delete session.autoEffort;
|
|
341
359
|
}
|
|
342
360
|
if (Object.hasOwn(route, 'effort')) session.effort = route.effort || null;
|
|
361
|
+
// A deliberate route choice restarts the chain (a fallback hop never passes this).
|
|
362
|
+
if (Object.hasOwn(route, 'routeFallbacks')) {
|
|
363
|
+
if (route.routeFallbacks?.length) session.routeFallbacks = route.routeFallbacks;
|
|
364
|
+
else delete session.routeFallbacks;
|
|
365
|
+
delete session.routeFallbackIndex;
|
|
366
|
+
delete session.routeFallbackFailures;
|
|
367
|
+
}
|
|
343
368
|
ensureCodexWireSessionId(session);
|
|
344
369
|
if (Object.hasOwn(route, 'modelParameters')) {
|
|
345
370
|
session.modelParameters =
|
|
@@ -387,7 +412,8 @@ function applyRouteContextWindow(session, routeChanged, selectedContextWindowPro
|
|
|
387
412
|
// surface: the previous route's readings and prepared tools no longer apply.
|
|
388
413
|
function resetSessionForRouteChange(id, session, previousModel, previousProvider) {
|
|
389
414
|
session.promptCacheKey = providerCacheKey(session.provider);
|
|
390
|
-
session.providerCacheOpts =
|
|
415
|
+
session.providerCacheOpts =
|
|
416
|
+
buildSessionProviderCacheOpts(session.provider, session.id, session.agent, null, session) || null;
|
|
391
417
|
session.providerCacheOptsOverride = false;
|
|
392
418
|
session.lastInputTokens = 0;
|
|
393
419
|
session.lastOutputTokens = 0;
|
|
@@ -437,7 +463,9 @@ function stripProviderReplay(session) {
|
|
|
437
463
|
// auto-compacts) against the new model's window.
|
|
438
464
|
export function updateSessionRoute(id, route = {}, options = {}) {
|
|
439
465
|
if (!id) return null;
|
|
440
|
-
|
|
466
|
+
// options.session: the live object of a running turn, changed in place; the id's
|
|
467
|
+
// stored copy (a disk reload after another process took the generation) is not.
|
|
468
|
+
const session = options.session?.id === id ? options.session : loadSession(id);
|
|
441
469
|
if (!session || session.closed === true) return null;
|
|
442
470
|
const previousProvider = session.provider || null;
|
|
443
471
|
const previousModel = session.model || null;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { buildSkillManifest, composeSystemPrompt } from '../../context/collect.mjs';
|
|
6
6
|
import { configuredInstructionFilesMode, loadInstructionFilesContext } from '../../context/instruction-files.mjs';
|
|
7
7
|
import { agentModeIdentityLine } from '../../context/role-instructions.mjs';
|
|
8
|
-
import { AGENT_MODE,
|
|
8
|
+
import { AGENT_MODE, sessionModeOf } from '../agent-mode.mjs';
|
|
9
9
|
import { MIXY_AGENT_ID } from '../agent-home.mjs';
|
|
10
10
|
import {
|
|
11
11
|
_buildBaseRules,
|
|
@@ -98,12 +98,9 @@ export function buildWorkspacePromptContext(session, cwd) {
|
|
|
98
98
|
// A Lead's BP3 rule slices, ordered for prefix sharing (composeSystemPrompt):
|
|
99
99
|
// LEAD.md's common lines first; then the mode block (coding: LEAD.md's two
|
|
100
100
|
// passages; agent mode: their conversational variants and AGENT_MODE.md);
|
|
101
|
-
// then Mixy's MIXY.md; last the per-session tail —
|
|
101
|
+
// then Mixy's MIXY.md; last the per-session tail — identity.
|
|
102
102
|
// Agent mode is a Lead created as an agent (agent-mode.mjs).
|
|
103
|
-
export function sessionRolePromptFields(
|
|
104
|
-
identity,
|
|
105
|
-
{ ownerIsAgent, toolFreeRole, delegationFree, sessionMode, routine = false }
|
|
106
|
-
) {
|
|
103
|
+
export function sessionRolePromptFields(identity, { ownerIsAgent, toolFreeRole, delegationFree, sessionMode }) {
|
|
107
104
|
const skipRules = identity.skipAgentRules || toolFreeRole;
|
|
108
105
|
const lead = !ownerIsAgent && !skipRules;
|
|
109
106
|
const agentMode = lead && sessionMode === AGENT_MODE;
|
|
@@ -131,7 +128,6 @@ export function sessionRolePromptFields(
|
|
|
131
128
|
? {
|
|
132
129
|
agentModeRules: _buildAgentModeRules({ part: 'conduct' }),
|
|
133
130
|
...(mixy ? { mixyRules: _buildAgentModeRules({ part: 'mixy' }) } : {}),
|
|
134
|
-
...(routine ? { routineRules: _buildAgentModeRules({ part: 'routine' }) } : {}),
|
|
135
131
|
}
|
|
136
132
|
: {}),
|
|
137
133
|
userPrompt: identity.systemPrompt,
|
|
@@ -176,7 +172,6 @@ export function composeSessionSystem(opts, { profile, providerName, modelName, s
|
|
|
176
172
|
toolFreeRole,
|
|
177
173
|
delegationFree,
|
|
178
174
|
sessionMode,
|
|
179
|
-
routine: isRoutineSource(opts.sourceType),
|
|
180
175
|
});
|
|
181
176
|
const leadOnly = !skipAgentRules && !ownerIsAgent;
|
|
182
177
|
const metaContext = leadOnly ? _buildLeadMetaContext({ includeOutputStyle: !agentMode }) : '';
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
// What a persisted session row contains and where each field comes from: the
|
|
3
3
|
// compaction budget, the origin/permission/cache metadata analytics slice on,
|
|
4
4
|
// the desktop classification, and the record assembled from them. Everything
|
|
5
|
-
// here is field derivation — no
|
|
5
|
+
// here is field derivation — no ownership, no prompt text; the only read is the
|
|
6
|
+
// parent's record a delegated session takes its root from.
|
|
6
7
|
import { toSessionWorkflowMeta } from '../../runtime-core/workflow.mjs';
|
|
8
|
+
import { delegationForNewSession } from '../human-gate/delegation.mjs';
|
|
7
9
|
import { sessionOrchestrationMode } from '../../../../shared/orchestration.mjs';
|
|
8
10
|
import { preserveBufferConfigFields } from './context-meta.mjs';
|
|
9
11
|
import { positiveInt } from '../../../../shared/numbers.mjs';
|
|
@@ -101,9 +103,18 @@ export function sessionOriginFields(opts, { profile, presetObj, providerCacheOpt
|
|
|
101
103
|
ownerSessionId: opts.ownerSessionId || null,
|
|
102
104
|
visibility: opts.visibility || null,
|
|
103
105
|
clientHostPid: opts.clientHostPid || null,
|
|
106
|
+
// A sub-agent's or a bot-created task session's root (who it works for, and
|
|
107
|
+
// how that root was acting), derived from the parent's record — the one
|
|
108
|
+
// read here — never taken from the options (human-gate/delegation.mjs).
|
|
109
|
+
...delegationFields(opts),
|
|
104
110
|
};
|
|
105
111
|
}
|
|
106
112
|
|
|
113
|
+
function delegationFields(opts) {
|
|
114
|
+
const delegation = delegationForNewSession(opts);
|
|
115
|
+
return delegation ? { delegation } : {};
|
|
116
|
+
}
|
|
117
|
+
|
|
107
118
|
// The persisted session record.
|
|
108
119
|
export function buildSessionRecord({ opts, route, presetObj, surface, prompt, messages, contextMeta, origin }) {
|
|
109
120
|
const {
|
|
@@ -35,10 +35,9 @@
|
|
|
35
35
|
// keeps the durable prefix.
|
|
36
36
|
import { appendFileSync, existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
37
37
|
import { appendFile, unlink, writeFile } from 'node:fs/promises';
|
|
38
|
-
import { randomBytes } from 'node:crypto';
|
|
39
38
|
import { join } from 'node:path';
|
|
40
39
|
import { getPluginData } from '../../config.mjs';
|
|
41
|
-
import {
|
|
40
|
+
import { writeFileAtomicSync } from '../../../../shared/atomic-file.mjs';
|
|
42
41
|
import { sanitizeContentForStoredHistory } from '../../providers/media-normalization.mjs';
|
|
43
42
|
import { promptContentText } from './prompt-utils.mjs';
|
|
44
43
|
|
|
@@ -145,19 +144,11 @@ export function writeCheckpointHeader(checkpoint) {
|
|
|
145
144
|
contextState: checkpoint.contextState ?? null,
|
|
146
145
|
updatedAt: Date.now(),
|
|
147
146
|
};
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
} catch (error) {
|
|
154
|
-
try {
|
|
155
|
-
unlinkSync(temp);
|
|
156
|
-
} catch {
|
|
157
|
-
/* best-effort */
|
|
158
|
-
}
|
|
159
|
-
throw error;
|
|
160
|
-
}
|
|
147
|
+
// Durable (fsynced through its handle, then renamed): a crash must not
|
|
148
|
+
// publish a header whose bytes never landed. A damaged header already reads
|
|
149
|
+
// as "no checkpoint" (parseTurnCheckpointHeader) and the next turn rewrites it.
|
|
150
|
+
writeFileAtomicSync(target, JSON.stringify(payload));
|
|
151
|
+
return true;
|
|
161
152
|
}
|
|
162
153
|
|
|
163
154
|
export function readTurnCheckpointHeader(sessionId) {
|
|
@@ -20,7 +20,15 @@ const INTERRUPTED_TOOL_RESULT = 'Cancelled';
|
|
|
20
20
|
// PRESERVE the just-sent user turn: nothing restores the prompt there, and
|
|
21
21
|
// rewinding erases the user's message from the persisted transcript (the
|
|
22
22
|
// exact loss seen when the desktop app quits mid-turn).
|
|
23
|
-
|
|
23
|
+
//
|
|
24
|
+
// A user cancel the host will NOT answer with the prompt back in the input box
|
|
25
|
+
// (the desktop Stop button, a prompt carrying attachments cancelled from
|
|
26
|
+
// another device) names `USER_CANCEL_KEEP_PROMPT_REASON`: it is still a user
|
|
27
|
+
// cancel, but the unanswered prompt stays in the stored transcript. Rewinding
|
|
28
|
+
// it left a first message with zero stored messages — a session every catalog
|
|
29
|
+
// hides — and its text nowhere.
|
|
30
|
+
export const USER_CANCEL_KEEP_PROMPT_REASON = 'user-cancel-keep-prompt';
|
|
31
|
+
const USER_CANCEL_ABORT_REASONS = new Set(['cli-abort', 'user-cancel', 'turn-abort', USER_CANCEL_KEEP_PROMPT_REASON]);
|
|
24
32
|
|
|
25
33
|
function provisionalUserTurnIndex(messages, currentUserContent) {
|
|
26
34
|
const currentText = promptContentText(currentUserContent);
|
|
@@ -78,7 +86,17 @@ function finalizeInterruptedTurn({
|
|
|
78
86
|
// turn and its side effects from history.
|
|
79
87
|
const preserveResponse = responseStarted && (producedOutput || !userCancelled);
|
|
80
88
|
if (!preserveResponse) {
|
|
81
|
-
if (!userCancelled) {
|
|
89
|
+
if (!userCancelled || abortReason === USER_CANCEL_KEEP_PROMPT_REASON) {
|
|
90
|
+
// A kept prompt gets the generic interruption row (rendered as the
|
|
91
|
+
// Cancelled status, unlike the hidden by-user control row): without it a
|
|
92
|
+
// rebuilt transcript shows the stopped prompt as if it were still
|
|
93
|
+
// awaiting an answer, directly above the next one.
|
|
94
|
+
if (
|
|
95
|
+
abortReason === USER_CANCEL_KEEP_PROMPT_REASON &&
|
|
96
|
+
provisionalUserTurnIndex(messages, currentUserContent) >= 0
|
|
97
|
+
) {
|
|
98
|
+
messages.push({ role: 'user', content: SESSION_INTERRUPT_MESSAGE });
|
|
99
|
+
}
|
|
82
100
|
return {
|
|
83
101
|
messages,
|
|
84
102
|
responsePreserved: false,
|
|
@@ -145,18 +163,16 @@ function appendObservedTurnOutput(
|
|
|
145
163
|
if (!result?.toolCallId || representedToolResultIds.has(result.toolCallId)) continue;
|
|
146
164
|
messages.push({
|
|
147
165
|
role: 'tool',
|
|
148
|
-
content: result.content
|
|
166
|
+
content: result.content ?? '',
|
|
149
167
|
toolCallId: result.toolCallId,
|
|
150
168
|
...(result.toolKind ? { toolKind: result.toolKind } : {}),
|
|
151
169
|
});
|
|
152
170
|
representedToolResultIds.add(result.toolCallId);
|
|
153
171
|
}
|
|
154
172
|
|
|
155
|
-
const allToolCallIds =
|
|
173
|
+
const allToolCallIds = new Set();
|
|
156
174
|
for (const message of messages) {
|
|
157
|
-
for (const id of assistantToolCallIds(message))
|
|
158
|
-
if (!allToolCallIds.includes(id)) allToolCallIds.push(id);
|
|
159
|
-
}
|
|
175
|
+
for (const id of assistantToolCallIds(message)) allToolCallIds.add(id);
|
|
160
176
|
}
|
|
161
177
|
for (const callId of allToolCallIds) {
|
|
162
178
|
if (representedToolResultIds.has(callId)) continue;
|
|
@@ -283,7 +299,7 @@ export function createTurnInterruptionTracker() {
|
|
|
283
299
|
if (message.__earlyNotify === true) {
|
|
284
300
|
state.observedToolResults.set(callId, {
|
|
285
301
|
role: 'tool',
|
|
286
|
-
content: message.content
|
|
302
|
+
content: message.content ?? '',
|
|
287
303
|
toolCallId: callId,
|
|
288
304
|
toolKind: message.toolKind || (message.isError ? 'error' : null),
|
|
289
305
|
});
|
|
@@ -1,20 +1,97 @@
|
|
|
1
1
|
// manager/workflow-switch-notice.mjs
|
|
2
2
|
// A mid-conversation workflow switch (session-runtime/tool-policy-refresh.mjs
|
|
3
|
-
// switchSessionWorkflow)
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
3
|
+
// switchSessionWorkflow) leaves the request prefix — system blocks and tool
|
|
4
|
+
// schemas — byte-identical, so the provider cache survives. The switch lives
|
|
5
|
+
// in two pieces of session state:
|
|
6
|
+
// session.workflowOverlay — while the session's workflow differs from the
|
|
7
|
+
// one its system prompt carries: the prompt's workflow (`prompt`, and the
|
|
8
|
+
// orchestration mode its tool surface was built with), the new workflow,
|
|
9
|
+
// its tools that are refused at call time (`deniedTools`), the tools it
|
|
10
|
+
// allows that this session cannot reach (`unavailableTools`) and the
|
|
11
|
+
// self-contained reminder (`content`) with the new workflow's rules,
|
|
12
|
+
// orchestration and agents. It is folded into the prompt (and dropped) at
|
|
13
|
+
// the next point where the cache is cold anyway (tool-policy-refresh.mjs).
|
|
14
|
+
// session.workflowSwitch — the notice the next user turn carries in its
|
|
15
|
+
// reminder block. Lifecycle mirrors the working-folder notice
|
|
16
|
+
// (prompt-utils snapshotPendingWorkspaceNotice): snapshot when the turn is
|
|
17
|
+
// built, acknowledge once the provider accepted it, so a failed turn
|
|
18
|
+
// re-sends it. Delivered, it stays in the conversation. Replaced, never
|
|
19
|
+
// mutated:
|
|
20
|
+
// from — the workflow the model was last told about (kept across
|
|
21
|
+
// switches made before a notice reached it);
|
|
22
|
+
// to — the session's workflow now.
|
|
23
|
+
// Every notice says it replaces the earlier ones, so the latest one wins.
|
|
12
24
|
|
|
13
25
|
function workflowRef(workflow) {
|
|
14
26
|
const id = String(workflow?.id || '').trim();
|
|
15
27
|
return id ? { id, name: String(workflow?.name || id).trim() } : null;
|
|
16
28
|
}
|
|
17
29
|
|
|
30
|
+
/** The workflow the session's system prompt and tool surface were built with. */
|
|
31
|
+
export function promptWorkflowOf(session) {
|
|
32
|
+
return session?.workflowOverlay?.prompt || session?.workflow || null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const lower = (name) => String(name || '').toLowerCase();
|
|
36
|
+
|
|
37
|
+
/** The refusal of a call to a tool the session's current workflow denies
|
|
38
|
+
* while its schema (built for the prompt's workflow) still carries it; null
|
|
39
|
+
* for any other call. */
|
|
40
|
+
export function workflowOverlayDenial(session, name) {
|
|
41
|
+
const overlay = session?.workflowOverlay;
|
|
42
|
+
if (!overlay?.deniedTools?.some((denied) => lower(denied) === lower(name))) return null;
|
|
43
|
+
return `Error: tool "${name}" is not available in workflow ${overlay.workflow.name}: this conversation switched to it. Do the work without it.`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const listed = (names) => names.map((name) => `\`${name}\``).join(', ');
|
|
47
|
+
|
|
48
|
+
/** The reminder that makes the Lead follow `workflow` while its system prompt
|
|
49
|
+
* still carries `promptName`'s: self-contained (rules, orchestration, agents,
|
|
50
|
+
* tool changes) and superseding every earlier one. */
|
|
51
|
+
export function workflowOverlayContent({
|
|
52
|
+
promptName,
|
|
53
|
+
workflow,
|
|
54
|
+
instructions,
|
|
55
|
+
deniedTools = [],
|
|
56
|
+
loadableTools = [],
|
|
57
|
+
unavailableTools = [],
|
|
58
|
+
}) {
|
|
59
|
+
const name = workflow.name;
|
|
60
|
+
return [
|
|
61
|
+
'<system-reminder>',
|
|
62
|
+
'# Workflow Changed',
|
|
63
|
+
`This conversation now runs the ${name} workflow. The system prompt's Active Workflow, orchestration mode and available agents are still ${promptName}'s: they no longer apply; follow ${name}'s below instead. This replaces every earlier Workflow Changed reminder in this conversation.`,
|
|
64
|
+
...(deniedTools.length ? [`Not available in ${name} (calls are refused): ${listed(deniedTools)}.`] : []),
|
|
65
|
+
...(loadableTools.length
|
|
66
|
+
? [
|
|
67
|
+
`${name} adds ${listed(loadableTools)}: not among your directly defined tools yet; load ${loadableTools.length === 1 ? 'it' : 'them'} with \`load_tool\` before the first call.`,
|
|
68
|
+
]
|
|
69
|
+
: []),
|
|
70
|
+
...(unavailableTools.length
|
|
71
|
+
? [`${name} allows ${listed(unavailableTools)}, but this session cannot use them; a new session can.`]
|
|
72
|
+
: []),
|
|
73
|
+
`Agents already started under ${promptName} keep running with their own instructions; new delegation follows ${name}.`,
|
|
74
|
+
'',
|
|
75
|
+
instructions,
|
|
76
|
+
'</system-reminder>',
|
|
77
|
+
].join('\n');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function messageText(message) {
|
|
81
|
+
if (typeof message?.content === 'string') return message.content;
|
|
82
|
+
if (!Array.isArray(message?.content)) return '';
|
|
83
|
+
return message.content.map((part) => (typeof part === 'string' ? part : part?.text || '')).join('');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** The conversation still holds `content` (a delivered reminder); false once
|
|
87
|
+
* a compaction or a clear dropped it. */
|
|
88
|
+
export function conversationHolds(session, content) {
|
|
89
|
+
if (!content) return false;
|
|
90
|
+
return (Array.isArray(session?.messages) ? session.messages : []).some(
|
|
91
|
+
(message) => message?.role !== 'system' && messageText(message).includes(content)
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
18
95
|
/** Stage the notice of a switch from `from` to `to`; a switch back to what the
|
|
19
96
|
* model was last told drops it. Returns the staged state or null. */
|
|
20
97
|
export function stageWorkflowSwitchNotice(session, from, to) {
|
|
@@ -29,13 +106,14 @@ export function stageWorkflowSwitchNotice(session, from, to) {
|
|
|
29
106
|
return session.workflowSwitch;
|
|
30
107
|
}
|
|
31
108
|
|
|
32
|
-
|
|
109
|
+
// The prompt itself carries `to` (a switch back to it, or the overlay folded in).
|
|
110
|
+
function promptWorkflowNoticeContent({ from, to }) {
|
|
33
111
|
const before = from?.name || 'the previous workflow';
|
|
34
112
|
return [
|
|
35
113
|
'<system-reminder>',
|
|
36
114
|
'# Workflow Changed',
|
|
37
|
-
`
|
|
38
|
-
`Agents already started under ${before} keep running with their own instructions; new delegation
|
|
115
|
+
`This conversation now runs the ${to.name} workflow, the one the system prompt carries: its Active Workflow, orchestration mode, available agents and tools apply. This replaces every earlier Workflow Changed reminder in this conversation.`,
|
|
116
|
+
`Agents already started under ${before} keep running with their own instructions; new delegation follows ${to.name}.`,
|
|
39
117
|
'</system-reminder>',
|
|
40
118
|
].join('\n');
|
|
41
119
|
}
|
|
@@ -47,7 +125,10 @@ function workflowNoticeContent({ from, to }) {
|
|
|
47
125
|
export function snapshotPendingWorkflowNotice(session) {
|
|
48
126
|
const pending = session?.workflowSwitch;
|
|
49
127
|
if (!pending?.to?.id) return null;
|
|
50
|
-
|
|
128
|
+
const overlay = session.workflowOverlay;
|
|
129
|
+
const content =
|
|
130
|
+
overlay?.workflow?.id === pending.to.id && overlay.content ? overlay.content : promptWorkflowNoticeContent(pending);
|
|
131
|
+
return { revision: pending.revision, content };
|
|
51
132
|
}
|
|
52
133
|
|
|
53
134
|
/** The notice of `revision` reached the model: nothing is due any more. */
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
import { previewFreshContextCompaction, runFreshContextCompact } from './loop/fresh-context.mjs';
|
|
20
20
|
import { estimateMessagesTokensSafe } from './loop/compact-debug.mjs';
|
|
21
21
|
import { textPdfAllowanceDiscount } from './context-utils.mjs';
|
|
22
|
+
import { referenceOversizedAttachments } from './attachment-preflight.mjs';
|
|
22
23
|
import { providerNativePdf } from '../providers/registry.mjs';
|
|
23
24
|
import { messagesArrayChanged } from './loop/tool-helpers.mjs';
|
|
24
25
|
import { normalizeUsage, addUsage } from './loop/usage.mjs';
|
|
@@ -274,6 +275,9 @@ async function compactTranscript(ctx, run) {
|
|
|
274
275
|
goalReminderText: run.inlineGoalReminder?.content || '',
|
|
275
276
|
activeTurn: true,
|
|
276
277
|
requireReduction: decision.requireReduction,
|
|
278
|
+
// The provider refused this request as too long: whatever the estimate
|
|
279
|
+
// said, the latest request's attachments now travel by reference.
|
|
280
|
+
referenceLatestAttachments: decision.compactTrigger === 'reactive',
|
|
277
281
|
});
|
|
278
282
|
const freshMessages = Array.isArray(run.freshContextResult?.messages) ? run.freshContextResult.messages : null;
|
|
279
283
|
if (!freshMessages) throw new Error('fresh-context compact produced no messages');
|
|
@@ -290,6 +294,9 @@ function acknowledgeGoalReminder(sessionRef, run) {
|
|
|
290
294
|
}
|
|
291
295
|
}
|
|
292
296
|
|
|
297
|
+
// Detection is narrow on purpose — signal.aborted or a true AbortError — so
|
|
298
|
+
// the recall pipeline's SYNTHETIC "…aborted: memory … ; head preserved"
|
|
299
|
+
// failure (a real compact failure, message text aside) still escalates.
|
|
293
300
|
function isCompactAbort(signal, err) {
|
|
294
301
|
return signal?.aborted === true || err?.name === 'AbortError' || err?.code === 'ABORT_ERR' || err?.code === 'ABORT';
|
|
295
302
|
}
|
|
@@ -326,16 +333,6 @@ function reportCompactFailure(ctx, run, compactErr) {
|
|
|
326
333
|
});
|
|
327
334
|
}
|
|
328
335
|
|
|
329
|
-
// A failed compact pass ends the send. A genuine cancellation/abort surfaced
|
|
330
|
-
// from the compact pipeline is NOT a context overflow: the fresh-context
|
|
331
|
-
// pipeline deliberately rethrows the original abort error unchanged so the
|
|
332
|
-
// session records a clean cancellation — and the manual/auto-clear runner
|
|
333
|
-
// (manager/compaction-runner.mjs) likewise never fabricates an
|
|
334
|
-
// AGENT_CONTEXT_OVERFLOW for an aborted compact. Mirror that here: preserve
|
|
335
|
-
// the real error (code/name/cause intact) instead of masking it as overflow.
|
|
336
|
-
// Detection is narrow on purpose — signal.aborted or a true AbortError — so
|
|
337
|
-
// the recall pipeline's SYNTHETIC "…aborted: memory … ; head preserved"
|
|
338
|
-
// failure (a real compact failure, message text aside) still escalates.
|
|
339
336
|
function isGenuineCompactOverflow(compactErr) {
|
|
340
337
|
return (
|
|
341
338
|
compactErr?.code === 'AGENT_CONTEXT_OVERFLOW' ||
|
|
@@ -362,6 +359,13 @@ function retryCompactQuietly(ctx, run, compactErr) {
|
|
|
362
359
|
return true;
|
|
363
360
|
}
|
|
364
361
|
|
|
362
|
+
// A failed compact pass ends the send. A genuine cancellation/abort surfaced
|
|
363
|
+
// from the compact pipeline is NOT a context overflow: the fresh-context
|
|
364
|
+
// pipeline deliberately rethrows the original abort error unchanged so the
|
|
365
|
+
// session records a clean cancellation — and the manual/auto-clear runner
|
|
366
|
+
// (manager/compaction-runner.mjs) likewise never fabricates an
|
|
367
|
+
// AGENT_CONTEXT_OVERFLOW for an aborted compact. Mirror that here: preserve
|
|
368
|
+
// the real error (code/name/cause intact) instead of masking it as overflow.
|
|
365
369
|
function throwCompactFailure(ctx, run, compactErr) {
|
|
366
370
|
const { state, compactPolicy, decision } = ctx;
|
|
367
371
|
const { sessionRef, sessionId, signal, model } = state;
|
|
@@ -555,6 +559,33 @@ async function compactBeforeSend(ctx) {
|
|
|
555
559
|
await runCompactHook(ctx, 'postCompactHook');
|
|
556
560
|
}
|
|
557
561
|
|
|
562
|
+
// Attachments that would crowd the window travel by reference from this send
|
|
563
|
+
// on (session/attachment-preflight.mjs). Runs whether or not auto-compaction
|
|
564
|
+
// is on: it is what keeps an oversized attachment message from ever reaching
|
|
565
|
+
// the provider. A rewrite changes the transcript the provider chain was built
|
|
566
|
+
// on, so the continuation is dropped and the send is tagged exactly like an
|
|
567
|
+
// automatic compaction: the prefix guard accepts that boundary, whereas a
|
|
568
|
+
// transcript-repair tag would refuse the rewritten earlier message.
|
|
569
|
+
function preflightAttachments(ctx, compactPolicy) {
|
|
570
|
+
const { state } = ctx;
|
|
571
|
+
const contextWindow = compactPolicy?.contextWindow || state.sessionRef?.contextWindow;
|
|
572
|
+
const outcome = referenceOversizedAttachments(state.messages, {
|
|
573
|
+
contextWindow,
|
|
574
|
+
nativePdf: providerNativePdf(state.sessionRef?.provider),
|
|
575
|
+
});
|
|
576
|
+
if (!outcome.changed) return;
|
|
577
|
+
ctx.providerState = undefined;
|
|
578
|
+
ctx.providerStateCleared = true;
|
|
579
|
+
ctx.compactChanged = true;
|
|
580
|
+
if (state.opts && !String(state.opts.cacheBreakIntent || '').endsWith('_compaction')) {
|
|
581
|
+
state.opts.cacheBreakIntent = 'automatic_compaction';
|
|
582
|
+
}
|
|
583
|
+
writeStderrBestEffort(
|
|
584
|
+
`[loop] attachments sent by reference (sess=${state.sessionId || 'unknown'}): ` +
|
|
585
|
+
`${outcome.referencedMessages} message(s), inline estimate ${outcome.inlineTokensBefore} > budget ${outcome.budgetTokens}\n`
|
|
586
|
+
);
|
|
587
|
+
}
|
|
588
|
+
|
|
558
589
|
export async function runPreSendCompactPass(state) {
|
|
559
590
|
const ctx = {
|
|
560
591
|
state,
|
|
@@ -567,6 +598,7 @@ export async function runPreSendCompactPass(state) {
|
|
|
567
598
|
compactChanged: false,
|
|
568
599
|
};
|
|
569
600
|
const compactPolicy = resolveWorkerCompactPolicy(state.sessionRef, state.requestTools);
|
|
601
|
+
preflightAttachments(ctx, compactPolicy);
|
|
570
602
|
if (compactPolicy?.auto) {
|
|
571
603
|
ctx.compactPolicy = compactPolicy;
|
|
572
604
|
ctx.decision = preSendCompactDecision(state, compactPolicy);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
2
|
import { hasPlainPrototype } from '../../../shared/object.mjs';
|
|
3
|
+
import { withoutMessageIdsReplacer } from './message-ids.mjs';
|
|
3
4
|
|
|
4
5
|
const COMPACTION_INTENTS = new Set([
|
|
5
6
|
'automatic_compaction',
|
|
@@ -8,8 +9,8 @@ const COMPACTION_INTENTS = new Set([
|
|
|
8
9
|
'post_turn_compaction',
|
|
9
10
|
]);
|
|
10
11
|
|
|
11
|
-
function digest(value) {
|
|
12
|
-
const encoded = JSON.stringify(value);
|
|
12
|
+
function digest(value, replacer) {
|
|
13
|
+
const encoded = JSON.stringify(value, replacer);
|
|
13
14
|
if (typeof encoded !== 'string') {
|
|
14
15
|
throw new TypeError('provider prefix value is not serializable');
|
|
15
16
|
}
|
|
@@ -82,11 +83,28 @@ function matchShape(value, tokens, cursor) {
|
|
|
82
83
|
return count === tokens[cursor + 1] ? next : -1;
|
|
83
84
|
}
|
|
84
85
|
|
|
86
|
+
// A message's digest covers what the provider can see of it. The stable
|
|
87
|
+
// message id (`meta.transcript.messageId`, message-ids.mjs) is display
|
|
88
|
+
// bookkeeping that is stamped onto live messages in place — a compaction pass
|
|
89
|
+
// stamps every unstamped message before it runs, whatever it then decides —
|
|
90
|
+
// and no provider request builder reads or sends it (the rest of `meta` is
|
|
91
|
+
// not bookkeeping: `meta.source` and `meta.effortConfiguration` steer the
|
|
92
|
+
// wire and stay in the digest). Hashing it would make a pass that changes
|
|
93
|
+
// nothing look like a rewritten prefix on the next send.
|
|
94
|
+
//
|
|
95
|
+
// Only the message root's own `meta` is projected: a `meta` nested in content
|
|
96
|
+
// (e.g. a structured tool result) is provider-visible and stays in the digest.
|
|
97
|
+
function rootMessageIdsReplacer(message) {
|
|
98
|
+
return function replacer(key, value) {
|
|
99
|
+
return this === message ? withoutMessageIdsReplacer(key, value) : value;
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
85
103
|
function messageDigest(message) {
|
|
86
104
|
if (message === null || typeof message !== 'object') return digest(message);
|
|
87
105
|
const memo = messageDigestMemo.get(message);
|
|
88
106
|
if (memo && matchShape(message, memo.tokens, 0) === memo.tokens.length) return memo.hash;
|
|
89
|
-
const hash = digest(message);
|
|
107
|
+
const hash = digest(message, rootMessageIdsReplacer(message));
|
|
90
108
|
const tokens = [];
|
|
91
109
|
if (recordShape(message, tokens)) messageDigestMemo.set(message, { hash, tokens });
|
|
92
110
|
else messageDigestMemo.delete(message);
|