mixdog 1.3.1 → 1.3.3
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 +8 -8
- package/scripts/native-release-status.mjs +238 -0
- package/scripts/verify-runtime-dependency-versions.mjs +158 -0
- package/src/agents/reviewer/AGENT.md +5 -7
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +9 -1
- package/src/defaults/skills/browser-use/SKILL.md +6 -3
- package/src/defaults/skills/local-provider/SKILL.md +33 -6
- 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 +7 -10
- package/src/rules/shared/10-tool-workflow.md +4 -0
- package/src/rules/shared/20-research.md +2 -0
- package/src/rules/shared/45-destructive.md +5 -1
- package/src/rules/shared/60-verification.md +6 -4
- 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 +84 -32
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +38 -11
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +15 -3
- 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 +84 -42
- package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +14 -1
- 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-client-version.mjs +1 -1
- 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-config.mjs +14 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +11 -8
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
- 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 +19 -0
- package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +13 -1
- 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-runtime.mjs +5 -0
- 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/goal-turns.mjs +10 -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 +52 -6
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +35 -13
- 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 +8 -3
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +1 -1
- 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 +30 -2
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +196 -45
- package/src/runtime/agent/orchestrator/session/attachment-preflight.mjs +80 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/compact/continuation.mjs +15 -6
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +45 -19
- package/src/runtime/agent/orchestrator/session/compact/forked-summary.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +44 -0
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +185 -37
- 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 +6 -2
- package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +4 -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 +240 -0
- package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +102 -35
- package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +20 -0
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +19 -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 +199 -109
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/continuation.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/empty-nudge.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/output-limit.mjs +62 -13
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +22 -6
- 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 +10 -0
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +33 -8
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/call-prep.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +27 -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/agent-listing-notice.mjs +102 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +13 -1
- 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 +27 -14
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +14 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +44 -18
- package/src/runtime/agent/orchestrator/session/manager/idle-cleanup.mjs +32 -1
- package/src/runtime/agent/orchestrator/session/manager/orchestration-mode-switch-notice.mjs +115 -0
- package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +42 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +6 -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/prompt-utils.mjs +36 -0
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +40 -1
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +12 -0
- package/src/runtime/agent/orchestrator/session/manager/runtime-state.mjs +20 -0
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +28 -9
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +55 -27
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +4 -9
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +14 -1
- package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +7 -3
- 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 +52 -11
- 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 +126 -12
- package/src/runtime/agent/orchestrator/session/runtime-user-context.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +16 -3
- 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/stale-sweep.mjs +5 -4
- package/src/runtime/agent/orchestrator/session/store/sweep/sub-agent-retention.mjs +140 -0
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-plan.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-record.mjs +15 -5
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +49 -1
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +80 -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/store-summary-reader.mjs +33 -1
- package/src/runtime/agent/orchestrator/session/store-summary-visibility.d.mts +5 -0
- package/src/runtime/agent/orchestrator/session/store-summary-visibility.mjs +37 -0
- package/src/runtime/agent/orchestrator/session/store.mjs +1 -0
- 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 +47 -14
- package/src/runtime/agent/orchestrator/tools/builtin/atomic-write.mjs +25 -5
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +6 -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/git-command-tool.mjs +127 -20
- package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +557 -0
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +10 -12
- 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 +42 -23
- 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/legacy-office.mjs +110 -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/prompt-restore.mjs +70 -0
- package/src/runtime/attachments/store.mjs +109 -33
- 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 +66 -16
- package/src/runtime/effort-judge/model-install.mjs +47 -7
- package/src/runtime/local-provider/asset-installer.mjs +10 -4
- package/src/runtime/local-provider/catalog.mjs +5 -2
- package/src/runtime/local-provider/registered-models.mjs +64 -27
- package/src/runtime/local-provider/server.mjs +2 -3
- package/src/runtime/media/adapters/image-api.mjs +89 -0
- package/src/runtime/media/auth.mjs +64 -1
- package/src/runtime/media/catalog.mjs +66 -4
- package/src/runtime/media/jobs.mjs +4 -0
- package/src/runtime/media/lanes.mjs +46 -5
- package/src/runtime/media/media-usage.mjs +17 -0
- package/src/runtime/media/renditions.mjs +15 -15
- package/src/runtime/media/store.mjs +36 -35
- package/src/runtime/media/tool.mjs +8 -1
- package/src/runtime/memory/lib/cycle-scheduler/health-ledger.mjs +8 -2
- package/src/runtime/memory/lib/embedding-model-files.mjs +30 -7
- package/src/runtime/memory/lib/ingest/transcript-tail.mjs +16 -7
- package/src/runtime/memory/lib/memory-chunk-quality.mjs +14 -2
- 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 +135 -29
- package/src/runtime/shared/agent-avatar-sprites.mjs +23 -8
- package/src/runtime/shared/agent-avatar.mjs +3 -2
- 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-room-host.d.mts +31 -0
- package/src/runtime/shared/agent-room-host.mjs +58 -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 +35 -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/redact-directories.mjs +18 -0
- package/src/runtime/shared/remove-directory.mjs +28 -0
- 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/session-sidebar-host.d.mts +11 -2
- package/src/runtime/shared/session-sidebar-host.mjs +16 -3
- 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 +10 -0
- package/src/runtime/shared/tool-work-units.mjs +12 -9
- 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 +277 -124
- package/src/runtime/shared/user-cwd.mjs +9 -4
- package/src/runtime/shared/user-data-guard.mjs +92 -61
- package/src/runtime/shared/utf8-cut.mjs +10 -0
- package/src/runtime/shared/worktrees/activity-gate.mjs +251 -61
- package/src/runtime/shared/worktrees/contract.mjs +11 -3
- package/src/runtime/shared/worktrees/maintenance.mjs +11 -2
- package/src/runtime/shared/worktrees/manager.mjs +419 -52
- package/src/runtime/shared/worktrees/registry.mjs +29 -27
- package/src/runtime/shared/worktrees/tool-host.mjs +39 -0
- package/src/runtime/tidy/core-install.mjs +26 -4
- package/src/runtime/tidy/install.mjs +91 -23
- package/src/runtime/tidy/process.mjs +41 -8
- package/src/runtime/tidy/resolve.mjs +10 -7
- package/src/runtime/web-search/lib/config.mjs +4 -16
- package/src/session-runtime/agent-home-delivery.mjs +542 -204
- package/src/session-runtime/agent-profile-changes.mjs +16 -0
- package/src/session-runtime/agent-room-delivery.mjs +81 -35
- package/src/session-runtime/agent-task-sessions.mjs +811 -179
- package/src/session-runtime/agent-tool-routing.mjs +1 -0
- package/src/session-runtime/boot/apis.mjs +48 -24
- package/src/session-runtime/boot/config.mjs +1 -0
- package/src/session-runtime/boot/facade.mjs +16 -7
- 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 +23 -3
- 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 +31 -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 +24 -26
- 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-recency.mjs +1 -0
- 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/provider-models/row-hydration.mjs +8 -1
- package/src/session-runtime/quick-model-rows/model-meta.mjs +2 -0
- package/src/session-runtime/quick-model-rows/provider-rows.mjs +7 -1
- 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-review-api.mjs +4 -1
- 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/job-views/agent-list.mjs +34 -19
- 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 +7 -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 +26 -6
- 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/services/worktree-access.mjs +27 -0
- 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/session-hooks.mjs +9 -17
- package/src/session-runtime/settings-builtin-tools-api.mjs +65 -1
- package/src/session-runtime/settings-compaction-api.mjs +86 -39
- package/src/session-runtime/setup-tool/executor.mjs +12 -2
- package/src/session-runtime/setup-tool/settings-contract.mjs +34 -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 +349 -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 +183 -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 +48 -369
- package/src/session-runtime/tool-surface.mjs +10 -4
- package/src/session-runtime/turn/session-ops.mjs +8 -0
- 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 +7 -2
- package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +54 -7
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +527 -333
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +85 -63
- 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/transition-steps.mjs +1 -18
- package/src/session-runtime/workspace/transitions.mjs +279 -67
- package/src/session-runtime/workspace/workspace-state.mjs +7 -6
- package/src/session-runtime/workspace/worktree-tool.mjs +194 -0
- package/src/standalone/daemon-agent-control.mjs +4 -1
- package/src/standalone/daemon-lag-profiler.mjs +3 -1
- package/src/standalone/daemon-session-control.mjs +173 -15
- package/src/standalone/daemon-telemetry.mjs +9 -0
- package/src/standalone/daemon.mjs +33 -10
- package/src/standalone/local-session-runtime.mjs +33 -16
- package/src/standalone/session-client.mjs +7 -2
- package/src/standalone/session-protocol.mjs +8 -0
- package/src/standalone/session-runtime-inline-host/boot-loaders.mjs +2 -0
- package/src/standalone/session-service/agent-route-follow.mjs +69 -0
- package/src/standalone/session-service/session-calls/session-turns.mjs +33 -4
- package/src/standalone/session-service.mjs +21 -0
- package/src/standalone/session-state-projection.mjs +19 -9
- package/src/standalone/session-tool-output.mjs +36 -9
- package/src/standalone/staged-import.mjs +47 -0
- package/src/tui/App.jsx +2 -0
- package/src/tui/app/maintenance-pickers/auto-clear-picker.mjs +19 -13
- package/src/tui/app/message-selector.mjs +15 -2
- package/src/tui/app/model-options.mjs +16 -2
- package/src/tui/app/model-picker.mjs +2 -1
- package/src/tui/app/route-pickers.mjs +3 -1
- 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 +617 -369
- package/src/tui/paste-attachments.mjs +0 -1
- package/src/tui/paste-text-policy.mjs +4 -5
- package/src/tui/prompt-history-store.mjs +16 -21
- package/src/tui/session/agent-job-feed/execution-delivery.mjs +4 -1
- package/src/tui/session/context-state.mjs +4 -0
- package/src/tui/session/notice-surface.mjs +3 -0
- package/src/tui/session/session-api/intake/abort.mjs +52 -18
- package/src/tui/session/session-api/intake/rewind.mjs +39 -4
- package/src/tui/session/session-api/media.mjs +2 -1
- package/src/tui/session/session-api/routes-agent-definitions.mjs +76 -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 +142 -14
- 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
- package/src/session-runtime/room-member-gate.mjs +0 -48
|
@@ -19,6 +19,25 @@ export function isTurnInFlight(entry) {
|
|
|
19
19
|
return IN_FLIGHT_STAGES.has(entry.stage);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
// Sessions whose turn was handed to the runtime but has not claimed its
|
|
23
|
+
// controller yet (spawn dispatched, askSession still loading the session).
|
|
24
|
+
// The row already declares work; without this the pool cannot tell that
|
|
25
|
+
// first-turn gap from a worker it lost track of, and reads `unknown`.
|
|
26
|
+
const dispatchedTurns = new Map();
|
|
27
|
+
|
|
28
|
+
/** Runs `run` (the turn's dispatch) with `id` counted as working until it
|
|
29
|
+
* settles, covering the gap before the turn's own runtime entry is in flight. */
|
|
30
|
+
export async function whileTurnDispatched(id, run) {
|
|
31
|
+
dispatchedTurns.set(id, (dispatchedTurns.get(id) || 0) + 1);
|
|
32
|
+
try {
|
|
33
|
+
return await run();
|
|
34
|
+
} finally {
|
|
35
|
+
const left = dispatchedTurns.get(id) - 1;
|
|
36
|
+
if (left > 0) dispatchedTurns.set(id, left);
|
|
37
|
+
else dispatchedTurns.delete(id);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
22
41
|
const cleanLower = (value) =>
|
|
23
42
|
String(value || '')
|
|
24
43
|
.trim()
|
|
@@ -32,6 +51,7 @@ const cleanLower = (value) =>
|
|
|
32
51
|
export function inFlightSessionActivity() {
|
|
33
52
|
const working = new Set();
|
|
34
53
|
const agentWorking = new Set();
|
|
54
|
+
for (const id of dispatchedTurns.keys()) working.add(id);
|
|
35
55
|
for (const [id, entry] of runtimeState) {
|
|
36
56
|
if (!isTurnInFlight(entry)) continue;
|
|
37
57
|
working.add(id);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// manager/session-crud.mjs
|
|
2
2
|
// Session read + mutate CRUD: lookup (getSession/listSessions/findSessionByScopeKey),
|
|
3
3
|
// message clear (with clear-fork), manual compaction, status update, and metric flush.
|
|
4
|
+
import { createHash } from 'node:crypto';
|
|
4
5
|
import {
|
|
5
6
|
loadSession,
|
|
6
7
|
saveSessionAsync,
|
|
@@ -29,6 +30,7 @@ import { hideCompactionArchive } from '../compaction-archive-capture.mjs';
|
|
|
29
30
|
import { writeStderrBestEffort } from '../../../../shared/best-effort-stderr.mjs';
|
|
30
31
|
import { forgetSideQuestion } from '../side-question-store.mjs';
|
|
31
32
|
import { isAgentHomeSessionId } from '../agent-home.mjs';
|
|
33
|
+
import { messageIdOf } from '../message-ids.mjs';
|
|
32
34
|
|
|
33
35
|
/** Force-flush session metrics to disk. */
|
|
34
36
|
export async function flushSessionMetrics(sessionId) {
|
|
@@ -412,19 +414,36 @@ export async function updateSessionStatus(id, status) {
|
|
|
412
414
|
export async function rewindSessionMessagesTo(sessionId, options = {}) {
|
|
413
415
|
const session = loadSession(sessionId);
|
|
414
416
|
if (!session || session.closed === true) return null;
|
|
417
|
+
const targetId = String(options?.messageId ?? '').trim();
|
|
415
418
|
const target = String(options?.text ?? '').trim();
|
|
416
|
-
if (!target) return null;
|
|
419
|
+
if (!targetId && !target) return null;
|
|
417
420
|
const messages = Array.isArray(session.messages) ? session.messages : [];
|
|
418
|
-
|
|
421
|
+
// The stable message id is the identity: the stored prompt is the EXPANDED
|
|
422
|
+
// text (attachment tokens materialized), so display text cannot find it.
|
|
423
|
+
// Text is only the fallback for a row that carries no id.
|
|
424
|
+
const matches = targetId
|
|
425
|
+
? (message) => messageIdOf(message) === targetId
|
|
426
|
+
: (message) => promptContentText(message.content).trim() === target;
|
|
427
|
+
const found = [];
|
|
419
428
|
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
420
|
-
|
|
421
|
-
if (message?.role !== 'user') continue;
|
|
422
|
-
if (promptContentText(message.content).trim() !== target) continue;
|
|
423
|
-
start = index;
|
|
424
|
-
break;
|
|
429
|
+
if (messages[index]?.role === 'user' && matches(messages[index])) found.push(index);
|
|
425
430
|
}
|
|
426
|
-
|
|
431
|
+
// Without an id, text that several prompts repeat cannot say which one the
|
|
432
|
+
// user picked: refuse rather than rewind the wrong occurrence.
|
|
433
|
+
if (found.length === 0 || (!targetId && found.length > 1)) return null;
|
|
434
|
+
const start = found[0];
|
|
427
435
|
const removed = messages.length - start;
|
|
436
|
+
const rewoundMessage = messages[start];
|
|
437
|
+
// `dryRun` resolves the target and reports what a rewind would do, changing
|
|
438
|
+
// nothing: the caller prepares the restore payload first and commits after.
|
|
439
|
+
// The marker names the exact history the dry run saw (generation alone only
|
|
440
|
+
// moves on lifecycle changes); the commit passes it back and is refused when
|
|
441
|
+
// the history differs.
|
|
442
|
+
const historyMarker = `${session.generation ?? 0}:${messages.length}:${createHash('sha1')
|
|
443
|
+
.update(JSON.stringify(messages))
|
|
444
|
+
.digest('hex')}`;
|
|
445
|
+
if (options?.dryRun === true) return { removed, remaining: start, message: rewoundMessage, historyMarker };
|
|
446
|
+
if (options?.expectedHistoryMarker != null && options.expectedHistoryMarker !== historyMarker) return null;
|
|
428
447
|
session.messages = messages.slice(0, start);
|
|
429
448
|
// The provider cache is keyed on the exact prefix we just truncated;
|
|
430
449
|
// the prefix-guard snapshot and the /btw fork request describe it too and
|
|
@@ -435,5 +454,5 @@ export async function rewindSessionMessagesTo(sessionId, options = {}) {
|
|
|
435
454
|
session.updatedAt = Date.now();
|
|
436
455
|
session.lastUsedAt = Date.now();
|
|
437
456
|
await saveSessionAsync(session, { expectedGeneration: session.generation });
|
|
438
|
-
return { removed, remaining: session.messages.length };
|
|
457
|
+
return { removed, remaining: session.messages.length, message: rewoundMessage };
|
|
439
458
|
}
|
|
@@ -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,
|
|
@@ -163,7 +159,7 @@ export function composeSessionSystem(opts, { profile, providerName, modelName, s
|
|
|
163
159
|
provider: providerName,
|
|
164
160
|
model: modelName,
|
|
165
161
|
});
|
|
166
|
-
const delegationFree = delegationDisabled(opts, ownerIsAgent);
|
|
162
|
+
const delegationFree = delegationDisabled({ ...opts, sessionMode }, ownerIsAgent);
|
|
167
163
|
const promptIdentity = {
|
|
168
164
|
systemPrompt: opts.systemPrompt || '',
|
|
169
165
|
skipAgentRules: opts.skipAgentRules === true,
|
|
@@ -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, runForNewSession } 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,20 @@ 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 root and the run (if any) that started a sub-agent or a
|
|
107
|
+
// bot-created task session, derived from its creator — the one read here —
|
|
108
|
+
// 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
|
+
// Work a schedule/webhook run started (a sub-agent, a task session) stays the run's.
|
|
116
|
+
const run = runForNewSession(opts);
|
|
117
|
+
return { ...(delegation ? { delegation } : {}), ...(run ? { run } : {}) };
|
|
118
|
+
}
|
|
119
|
+
|
|
107
120
|
// The persisted session record.
|
|
108
121
|
export function buildSessionRecord({ opts, route, presetObj, surface, prompt, messages, contextMeta, origin }) {
|
|
109
122
|
const {
|
|
@@ -9,15 +9,19 @@ import { collectPromptSkillsCached } from '../../context/collect.mjs';
|
|
|
9
9
|
import { isAgentOwner } from '../../agent-owner.mjs';
|
|
10
10
|
import { getHiddenAgent } from '../../internal-agents.mjs';
|
|
11
11
|
import { workflowDisallowsAgentTool } from '../../runtime-core/workflow.mjs';
|
|
12
|
+
import { isAgentModeSession } from '../agent-mode.mjs';
|
|
12
13
|
import { finalizeSessionToolList, resolveSessionTools, permissionFromToolSpec } from './tool-resolution.mjs';
|
|
13
14
|
import { unusedModelEditToolName } from '../../../../shared/edit-tool-dialect.mjs';
|
|
14
15
|
import { getAgentRuntimeSync } from './agent-runtime-singleton.mjs';
|
|
15
16
|
|
|
16
17
|
// A lead session may not delegate when its workflow forbids the agent tool
|
|
17
|
-
// (
|
|
18
|
-
// An agent-owned session never gets the tool anyway.
|
|
18
|
+
// (an agent-mode Lead without delegatable agents); Solo keeps it deferred for
|
|
19
|
+
// explicit user requests. An agent-owned session never gets the tool anyway.
|
|
19
20
|
export function delegationDisabled(source, ownerIsAgent) {
|
|
20
|
-
return
|
|
21
|
+
return (
|
|
22
|
+
!ownerIsAgent &&
|
|
23
|
+
workflowDisallowsAgentTool(source?.workflow, { agentMode: Boolean(source) && isAgentModeSession(source) })
|
|
24
|
+
);
|
|
21
25
|
}
|
|
22
26
|
|
|
23
27
|
// Exactly two schema surfaces exist: Lead and Agent. Every Agent role gets
|
|
@@ -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. */
|