mixdog 1.1.2 → 1.2.1
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 -5
- package/package.json +2 -1
- package/scripts/lib/run-node-tests.mjs +9 -0
- package/scripts/prune-desktop-runtime.mjs +3 -0
- package/scripts/test-direct.mjs +4 -2
- package/src/defaults/shipped-history.json +10 -0
- package/src/defaults/skills/pptx/SKILL.md +6 -6
- package/src/defaults/skills/pptx/references/review.md +6 -4
- package/src/defaults/skills/pptx/scripts/source-extract.mjs +1 -1
- package/src/defaults/skills/setup/references/actions.md +18 -5
- package/src/defaults/skills/visualize/SKILL.md +160 -0
- package/src/defaults/skills/visualize/references/craft.md +88 -0
- package/src/headless-command.mjs +56 -3
- package/src/headless-exec.mjs +17 -1
- package/src/help.mjs +2 -0
- package/src/rules/shared/60-verification.md +3 -1
- package/src/rules/shared/70-delivery.md +4 -2
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +1 -0
- package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +1 -0
- package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +2 -0
- package/src/runtime/agent/orchestrator/cache-mtime.mjs +26 -5
- package/src/runtime/agent/orchestrator/config-presets.mjs +2 -0
- package/src/runtime/agent/orchestrator/config-providers-merge.mjs +17 -11
- package/src/runtime/agent/orchestrator/config-storage.mjs +1 -0
- package/src/runtime/agent/orchestrator/config.mjs +19 -5
- package/src/runtime/agent/orchestrator/context/collect.mjs +2 -1
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +11 -5
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +74 -21
- package/src/runtime/agent/orchestrator/mcp/client-config.mjs +133 -15
- package/src/runtime/agent/orchestrator/mcp/client-handshake.mjs +55 -8
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +86 -8
- package/src/runtime/agent/orchestrator/mcp/client.mjs +474 -164
- package/src/runtime/agent/orchestrator/mcp/lazy-output-validator.mjs +25 -0
- package/src/runtime/agent/orchestrator/mcp/plugin-placeholders.mjs +54 -0
- package/src/runtime/agent/orchestrator/mcp/reconnect-singleflight.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +108 -17
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +15 -1
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +32 -12
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +337 -0
- package/src/runtime/agent/orchestrator/providers/command-code-oauth-tokens.mjs +159 -0
- package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +444 -0
- package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor-wire-normalization.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +7 -4
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +21 -6
- package/src/runtime/agent/orchestrator/providers/effort-rejection.mjs +244 -0
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +41 -28
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/lib/gemini-model-catalog.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +8 -40
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-tokens.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +51 -12
- package/src/runtime/agent/orchestrator/providers/model-cache.mjs +37 -2
- package/src/runtime/agent/orchestrator/providers/model-proxy-bridge.mjs +1080 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +82 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +556 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +251 -0
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth-tokens.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +69 -102
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +15 -0
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +6 -5
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +6 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +11 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +15 -4
- package/src/runtime/agent/orchestrator/providers/openai-oauth-catalog-store.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-catalog.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +4 -4
- package/src/runtime/agent/orchestrator/providers/registry.mjs +47 -7
- package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +10 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +36 -3
- package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +15 -11
- package/src/runtime/agent/orchestrator/runtime-core/extension-scopes.mjs +15 -55
- package/src/runtime/agent/orchestrator/runtime-core/goal-control.mjs +15 -2
- package/src/runtime/agent/orchestrator/runtime-core/model-capabilities.mjs +16 -1
- package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +278 -84
- package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +4 -1
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +21 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +54 -3
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +10 -3
- package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/cache/prefetch-cache.mjs +9 -5
- package/src/runtime/agent/orchestrator/session/cache/read-cache.mjs +18 -8
- package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +284 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +268 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/sqlite-gate.mjs +27 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/worker.mjs +628 -0
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +10 -3
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +24 -13
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +13 -5
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +362 -0
- package/src/runtime/agent/orchestrator/session/compaction-archive.mjs +253 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +184 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +136 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +128 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +127 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +101 -0
- package/src/runtime/agent/orchestrator/session/explicit-skills.mjs +83 -5
- package/src/runtime/agent/orchestrator/session/imported-message.mjs +11 -0
- package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/continuation.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/diagnostic.mjs +1 -7
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/refusal.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +5 -3
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +7 -4
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +21 -10
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/loop/usage.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +12 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +15 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +22 -12
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +9 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +9 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +5 -2
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +37 -16
- package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +17 -4
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +90 -0
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +22 -12
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +32 -3
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +27 -0
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +16 -1
- package/src/runtime/agent/orchestrator/session/manager/status-telemetry.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +0 -1
- package/src/runtime/agent/orchestrator/session/message-ids.mjs +123 -0
- package/src/runtime/agent/orchestrator/session/message-ids.test-support.mjs +29 -0
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +33 -22
- package/src/runtime/agent/orchestrator/session/store/listing.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +10 -3
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +11 -0
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +817 -0
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +36 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +23 -12
- package/src/runtime/agent/orchestrator/session/store-summary-reader-catalog-fixture.mjs +158 -0
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +202 -374
- package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +20 -3
- package/src/runtime/agent/orchestrator/session/synthetic-user-envelope.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +48 -9
- package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +161 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +17 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -0
- package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +52 -2
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +32 -22
- package/src/runtime/agent/orchestrator/tools/builtin/git-repo-rw-lock.mjs +10 -3
- package/src/runtime/agent/orchestrator/tools/builtin/lib/list-helpers.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/path-diagnostics.mjs +6 -6
- package/src/runtime/agent/orchestrator/tools/builtin/read-cache-policy.mjs +8 -0
- package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +203 -33
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-fast-paths.mjs +32 -35
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-guards.mjs +8 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-render.mjs +11 -12
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-stream.mjs +9 -6
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +83 -68
- package/src/runtime/agent/orchestrator/tools/builtin/read-snapshot-runtime.mjs +8 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-source-windows.mjs +20 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +16 -7
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-dispatch.mjs +2 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-publication.mjs +137 -0
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-snapshot.mjs +11 -10
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +21 -11
- package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +12 -1
- package/src/runtime/agent/orchestrator/tools/builtin/search-glob-tool.mjs +13 -10
- package/src/runtime/agent/orchestrator/tools/builtin/search-grep-tool.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +17 -12
- package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +56 -13
- package/src/runtime/agent/orchestrator/tools/code-graph/disk-cache.mjs +58 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/trusted-roots.mjs +25 -1
- package/src/runtime/agent/orchestrator/tools/patch/apply-patch/codex-batch.mjs +4 -4
- package/src/runtime/agent/orchestrator/tools/patch/apply-patch/route.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch/read-redirects.mjs +34 -30
- package/src/runtime/agent/orchestrator/tools/patch/sequence/units.mjs +7 -7
- package/src/runtime/agent/orchestrator/tools/patch/sequence.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch/ui-diff.mjs +78 -5
- package/src/runtime/agent/orchestrator/tools/progress-message.mjs +2 -0
- package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +4 -0
- package/src/runtime/attachments/store.d.mts +3 -0
- package/src/runtime/attachments/store.mjs +38 -0
- package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +1 -1
- package/src/runtime/channels/lib/webhook/session-dispatch.mjs +16 -4
- package/src/runtime/channels/lib/worker-main.mjs +17 -14
- package/src/runtime/computer-bridge/linux-readiness.mjs +0 -2
- package/src/runtime/effort-judge/judge-client.mjs +56 -18
- package/src/runtime/memory/lib/memory.mjs +1 -1
- package/src/runtime/memory/lib/session-ingest.mjs +2 -2
- package/src/runtime/shared/atomic-file.mjs +33 -6
- package/src/runtime/shared/best-effort-stderr.mjs +8 -0
- package/src/runtime/shared/code-graph-state.mjs +12 -0
- package/src/runtime/shared/defaults-separation.mjs +2 -0
- package/src/runtime/shared/extension-scopes.mjs +5 -3
- package/src/runtime/shared/file-lock.mjs +37 -11
- package/src/runtime/shared/git-runner-worker.mjs +3 -2
- package/src/runtime/shared/git-runner.mjs +4 -3
- package/src/runtime/shared/llm/anthropic-effort.mjs +14 -0
- package/src/runtime/shared/llm/default-context-window.mjs +6 -0
- package/src/runtime/shared/llm/model-catalog-projection.mjs +5 -4
- package/src/runtime/shared/llm/model-catalog.mjs +240 -130
- package/src/runtime/shared/llm/provider-catalog-cache.mjs +36 -28
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +162 -0
- package/src/runtime/shared/llm/provider-seed-rosters.mjs +130 -0
- package/src/runtime/shared/model-proxy-mode.d.mts +3 -0
- package/src/runtime/shared/model-proxy-mode.mjs +19 -0
- package/src/runtime/shared/plugin-manifest.mjs +18 -9
- package/src/runtime/shared/pristine-execution-contract.json +9 -2
- package/src/runtime/shared/pristine-execution.mjs +28 -4
- package/src/runtime/shared/provider-accounts.mjs +125 -21
- package/src/runtime/shared/provider-api-key.mjs +33 -1
- package/src/runtime/shared/schedule-model-ref.mjs +11 -2
- package/src/runtime/shared/session-usage-totals.mjs +19 -0
- package/src/runtime/shared/sharp-electron-linux.mjs +25 -0
- package/src/runtime/shared/shell-display.mjs +9 -3
- package/src/runtime/shared/singleton-owner.mjs +36 -6
- package/src/runtime/shared/skill-mentions.d.mts +10 -0
- package/src/runtime/shared/skill-mentions.mjs +133 -0
- package/src/runtime/shared/skill-script-runtime.mjs +264 -0
- package/src/runtime/shared/statusline/statusline-segments.mjs +68 -14
- package/src/runtime/shared/tool-primitives.mjs +35 -2
- package/src/runtime/shared/tool-surface.mjs +7 -0
- package/src/runtime/shared/tool-work-units.mjs +14 -0
- package/src/runtime/shared/transcript-metadata.mjs +17 -1
- package/src/runtime/shared/turn-changes.mjs +791 -0
- package/src/runtime/shared/turn-snapshot-store.mjs +346 -12
- package/src/runtime/shared/turn-snapshot.mjs +690 -81
- package/src/runtime/shared/turn-worktree-snapshot.mjs +185 -15
- package/src/runtime/shared/worker-requests.mjs +15 -2
- package/src/runtime/shared/worktrees/cache-cleanups.mjs +52 -0
- package/src/runtime/shared/worktrees/contract.mjs +551 -0
- package/src/runtime/shared/worktrees/disk.mjs +57 -0
- package/src/runtime/shared/worktrees/git.mjs +247 -0
- package/src/runtime/shared/worktrees/include.mjs +480 -0
- package/src/runtime/shared/worktrees/lock.mjs +46 -0
- package/src/runtime/shared/worktrees/maintenance.mjs +96 -0
- package/src/runtime/shared/worktrees/manager.mjs +1215 -0
- package/src/runtime/shared/worktrees/merge.mjs +182 -0
- package/src/runtime/shared/worktrees/owner.mjs +46 -0
- package/src/runtime/shared/worktrees/paths.mjs +62 -0
- package/src/runtime/shared/worktrees/registry.mjs +110 -0
- package/src/runtime/shared/worktrees/settings.mjs +84 -0
- package/src/runtime/shared/worktrees/slug.mjs +62 -0
- package/src/runtime/shared/worktrees/test-support.mjs +96 -0
- package/src/runtime/visualize-bridge/client.mjs +181 -0
- package/src/runtime/visualize-bridge/tool-defs.mjs +97 -0
- package/src/session-runtime/automation-agents.mjs +8 -2
- package/src/session-runtime/boot/apis.mjs +90 -0
- package/src/session-runtime/boot/config.mjs +7 -2
- package/src/session-runtime/boot/facade.mjs +21 -0
- package/src/session-runtime/boot/infrastructure.mjs +30 -18
- package/src/session-runtime/boot/session.mjs +1 -0
- package/src/session-runtime/boot/tools.mjs +4 -0
- package/src/session-runtime/config-lifecycle.mjs +10 -1
- package/src/session-runtime/conversation-import/discovery.mjs +698 -0
- package/src/session-runtime/conversation-import/service.mjs +369 -0
- package/src/session-runtime/cwd-plugins/cwd-apply.mjs +21 -6
- package/src/session-runtime/cwd-plugins/plugin-status.mjs +47 -42
- package/src/session-runtime/global-extensions.mjs +2 -2
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +27 -2
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +32 -1
- package/src/session-runtime/internal-tool-executor.mjs +9 -1
- package/src/session-runtime/lifecycle/session-catalog.mjs +8 -1
- package/src/session-runtime/lifecycle/session-switch/context-switch.mjs +5 -0
- package/src/session-runtime/lifecycle/session-switch/resume.mjs +21 -3
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +16 -0
- package/src/session-runtime/mcp-glue/connect.mjs +68 -16
- package/src/session-runtime/mcp-glue/plugin-servers.mjs +499 -0
- package/src/session-runtime/mcp-glue/server-catalog.mjs +122 -33
- package/src/session-runtime/mcp-glue/server-input.mjs +29 -0
- package/src/session-runtime/mcp-glue.mjs +22 -2
- package/src/session-runtime/model-route/route-persist.mjs +3 -0
- package/src/session-runtime/model-route/set-route.mjs +15 -2
- package/src/session-runtime/new-session-config.mjs +3 -2
- package/src/session-runtime/notification-bus.mjs +18 -3
- package/src/session-runtime/provider-auth/accounts.mjs +33 -15
- package/src/session-runtime/provider-models/row-hydration.mjs +2 -0
- package/src/session-runtime/provider-models/web-search-catalog.mjs +5 -1
- package/src/session-runtime/provider-readiness.mjs +16 -10
- package/src/session-runtime/resource-extension-sync.mjs +45 -7
- package/src/session-runtime/resource-mcp-api.mjs +121 -84
- package/src/session-runtime/resource-plugins-api.mjs +29 -41
- package/src/session-runtime/resource-scope-decorate.mjs +6 -8
- package/src/session-runtime/resource-skills-api.mjs +23 -2
- package/src/session-runtime/route-resolution.mjs +10 -1
- package/src/session-runtime/route-state.mjs +16 -2
- package/src/session-runtime/runtime-core.mjs +5 -0
- package/src/session-runtime/runtime-facade.mjs +8 -0
- package/src/session-runtime/runtime-review-api.mjs +9 -0
- package/src/session-runtime/schedule-session-run.mjs +1 -1
- package/src/session-runtime/services/agent-tool/helpers.mjs +5 -0
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +3 -0
- package/src/session-runtime/services/agent-tool/job-views/job-lookup.mjs +1 -0
- package/src/session-runtime/services/agent-tool/job-views/spawn-meta.mjs +1 -0
- package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +15 -0
- package/src/session-runtime/services/agent-tool/send-flow.mjs +1 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +10 -2
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +19 -7
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +3 -0
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +2 -1
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +5 -0
- package/src/session-runtime/services/agent-tool/worker-rows.mjs +1 -0
- package/src/session-runtime/services/agent-tool.mjs +1 -0
- package/src/session-runtime/services/channel-session-router.mjs +4 -1
- package/src/session-runtime/services/daemon-candidate.mjs +3 -2
- package/src/session-runtime/services/daemon-crash-capture/spawn-capture.mjs +55 -0
- package/src/session-runtime/services/hook-bus/command-handler.mjs +4 -1
- package/src/session-runtime/services/hook-bus/handlers.mjs +7 -3
- package/src/session-runtime/services/provider-admin.mjs +64 -18
- package/src/session-runtime/services/usage-dashboard-model.mjs +3 -0
- package/src/session-runtime/session-create/session-options.mjs +10 -1
- package/src/session-runtime/session-turn-api.mjs +1 -0
- package/src/session-runtime/settings-api.mjs +4 -2
- package/src/session-runtime/settings-builtin-tools-api.mjs +9 -2
- package/src/session-runtime/settings-worktree-api.mjs +17 -0
- package/src/session-runtime/setup-tool/executor.mjs +23 -5
- package/src/session-runtime/setup-tool/extended-actions.mjs +1 -0
- package/src/session-runtime/setup-tool/settings-contract.mjs +4 -1
- package/src/session-runtime/setup-tool/tool-defs.mjs +38 -4
- package/src/session-runtime/skills-api.mjs +7 -3
- package/src/session-runtime/turn/agent-ops.mjs +12 -1
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +14 -3
- package/src/session-runtime/turn/turn-run/snapshot-tracker.mjs +20 -15
- package/src/session-runtime/turn/turn-run/turn-open.mjs +4 -5
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +29 -1
- package/src/session-runtime/turn/turn-run/turn-settle.mjs +6 -1
- package/src/session-runtime/turn/turn-run.mjs +6 -7
- package/src/session-runtime/webhook-session-run.mjs +16 -4
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +15 -3
- package/src/session-runtime/workspace/admission-gate.mjs +197 -0
- package/src/session-runtime/workspace/project-branches.mjs +136 -0
- package/src/session-runtime/workspace/transition-steps.mjs +364 -0
- package/src/session-runtime/workspace/transitions.mjs +651 -0
- package/src/session-runtime/workspace/workspace-state.mjs +112 -0
- package/src/skill-script-entry.mjs +36 -0
- package/src/standalone/channel-transport/http-routes.mjs +17 -0
- package/src/standalone/channel-transport.mjs +13 -1
- package/src/standalone/daemon-desktop-runtime.mjs +1 -0
- package/src/standalone/daemon-owner.mjs +372 -0
- package/src/standalone/daemon-stored-session-views.mjs +15 -4
- package/src/standalone/daemon.mjs +179 -8
- package/src/standalone/desktop-service-registry.mjs +20 -0
- package/src/standalone/local-session-runtime.mjs +11 -0
- package/src/standalone/session-client/attachment-calls.mjs +3 -1
- package/src/standalone/session-client/daemon-unavailable.mjs +62 -0
- package/src/standalone/session-client/lease-heartbeat.mjs +47 -0
- package/src/standalone/session-client.mjs +104 -13
- package/src/standalone/session-protocol.mjs +21 -0
- package/src/standalone/session-proxy.mjs +3 -0
- package/src/standalone/session-service/agent-tree/agent-child.mjs +4 -0
- package/src/standalone/session-service/agent-tree/agent-rehydrate.mjs +1 -0
- package/src/standalone/session-service/entries/lifecycle.mjs +6 -0
- package/src/standalone/session-service/projection/revisions.mjs +2 -0
- package/src/standalone/session-service/projection/transcript-window.mjs +149 -19
- package/src/standalone/session-service/projection/workspace.mjs +14 -0
- package/src/standalone/session-service/session-calls/session-action.mjs +17 -4
- package/src/standalone/session-transport/call-route.mjs +13 -0
- package/src/standalone/session-transport/client-registry/client-grace.mjs +45 -3
- package/src/standalone/session-transport/client-registry/registration-replays.mjs +1 -0
- package/src/standalone/session-transport/client-registry.mjs +20 -3
- package/src/standalone/session-transport/routes.mjs +79 -2
- package/src/standalone/session-transport/stack.mjs +2 -0
- package/src/standalone/session-transport.mjs +24 -1
- package/src/tui/App.jsx +9 -1
- package/src/tui/app/app-view/floating-panel.jsx +9 -1
- package/src/tui/app/app-view.jsx +6 -0
- package/src/tui/app/extension-pickers/plugins-pickers.mjs +35 -16
- package/src/tui/app/message-selector.mjs +2 -1
- package/src/tui/app/model-options.mjs +37 -5
- package/src/tui/app/model-picker/provider-models-list.mjs +2 -2
- package/src/tui/app/model-picker.mjs +4 -2
- package/src/tui/app/skill-mention-palette.mjs +88 -0
- package/src/tui/app/slash-palette.mjs +23 -7
- package/src/tui/app/transcript-row-estimate.mjs +11 -3
- package/src/tui/app/use-prompt-draft-flow.mjs +7 -2
- package/src/tui/app/use-prompt-state.mjs +5 -0
- package/src/tui/components/Message.jsx +22 -1
- package/src/tui/components/PromptInput.jsx +21 -3
- package/src/tui/components/SlashCommandPalette.jsx +12 -3
- package/src/tui/components/TranscriptItem.jsx +9 -1
- package/src/tui/components/prompt-input/key-handler.mjs +21 -8
- package/src/tui/components/user-message-skills.mjs +38 -0
- package/src/tui/dist/index.mjs +839 -207
- package/src/tui/index.jsx +10 -2
- package/src/tui/session/compaction-view.mjs +147 -0
- package/src/tui/session/context-state.mjs +6 -0
- package/src/tui/session/initial-state.mjs +3 -0
- package/src/tui/session/queue-helpers.mjs +7 -2
- package/src/tui/session/quota-resume.mjs +2 -1
- package/src/tui/session/session-api/commands.mjs +10 -2
- package/src/tui/session/session-api/controls.mjs +4 -0
- package/src/tui/session/session-api/extensions.mjs +4 -2
- package/src/tui/session/session-api/intake/rewind.mjs +2 -1
- package/src/tui/session/session-api/integrations.mjs +17 -0
- package/src/tui/session/session-api/lifecycle/dispose.mjs +6 -1
- package/src/tui/session/session-api/lifecycle/inheritance.mjs +2 -0
- package/src/tui/session/session-api/lifecycle/resume.mjs +3 -0
- package/src/tui/session/session-api/routes.mjs +10 -1
- package/src/tui/session/session-api/settings.mjs +9 -0
- package/src/tui/session/session-api/worktree.mjs +60 -0
- package/src/tui/session/session-api.mjs +2 -0
- package/src/tui/session/session-flow/auto-clear.mjs +31 -12
- package/src/tui/session/session-flow/drain.mjs +27 -3
- package/src/tui/session/session-flow/session-reset.mjs +4 -3
- package/src/tui/session/session-flow.mjs +2 -0
- package/src/tui/session/transcript-intake.mjs +14 -5
- package/src/tui/session/tui-steering-persist.mjs +25 -9
- package/src/tui/session/turn-stream.mjs +32 -4
- package/src/tui/session/turn-tool-cards.mjs +10 -2
- package/src/tui/session/turn.mjs +56 -10
- package/src/runtime/effort-judge/previous-human-request.mjs +0 -162
- package/src/runtime/effort-judge/verified-context-input.mjs +0 -10
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Steering-message normalization/merge helpers.
|
|
2
2
|
// Merges queued steering entries into a single content payload + display text.
|
|
3
|
+
import { stableMessageId } from '../../../../shared/transcript-metadata.mjs';
|
|
3
4
|
|
|
4
5
|
function steeringContentText(content) {
|
|
5
6
|
if (typeof content === 'string') return content;
|
|
@@ -135,10 +136,14 @@ function injectSteeringEntry(merged, { messages, opts, stage, onSkillPrompt }) {
|
|
|
135
136
|
const rawSubmittedAt = Number(merged.submittedAt);
|
|
136
137
|
const submittedAt = Number.isFinite(rawSubmittedAt) && rawSubmittedAt > 0 ? rawSubmittedAt : undefined;
|
|
137
138
|
const injectedAt = Date.now();
|
|
139
|
+
// Every steered message carries a stable id from creation; the surface
|
|
140
|
+
// gets it back (onSteerMessage) for the row it draws. A steered prompt
|
|
141
|
+
// keeps the id the surface gave it, else gets one.
|
|
142
|
+
const messageId = stableMessageId(merged.transcriptMeta?.messageId);
|
|
138
143
|
const steeringTranscriptMeta =
|
|
139
144
|
merged.transcriptMeta && typeof merged.transcriptMeta === 'object'
|
|
140
|
-
? { at: submittedAt ?? injectedAt, ...merged.transcriptMeta }
|
|
141
|
-
:
|
|
145
|
+
? { at: submittedAt ?? injectedAt, ...merged.transcriptMeta, messageId }
|
|
146
|
+
: { messageId };
|
|
142
147
|
// Tag steering-origin user messages so provider lowering keeps them
|
|
143
148
|
// distinct from preceding tool results. Keep each queued command as
|
|
144
149
|
// its own user turn instead of collapsing priority/mode buckets
|
|
@@ -151,17 +156,18 @@ function injectSteeringEntry(merged, { messages, opts, stage, onSkillPrompt }) {
|
|
|
151
156
|
const notification = merged.mode === 'task-notification';
|
|
152
157
|
const execution =
|
|
153
158
|
notification && merged.execution && typeof merged.execution === 'object' ? { ...merged.execution } : null;
|
|
154
|
-
|
|
159
|
+
const message = {
|
|
155
160
|
role: 'user',
|
|
156
161
|
content: merged.content,
|
|
157
162
|
meta: {
|
|
158
163
|
source: notification ? 'task-notification' : 'steering',
|
|
159
164
|
...(execution ? { execution } : {}),
|
|
160
165
|
...(submissionIds.length ? { submissionIds } : {}),
|
|
161
|
-
|
|
166
|
+
transcript: steeringTranscriptMeta,
|
|
162
167
|
},
|
|
163
|
-
}
|
|
164
|
-
|
|
168
|
+
};
|
|
169
|
+
messages.push(message);
|
|
170
|
+
if (!notification) onSkillPrompt(merged.content, message);
|
|
165
171
|
const text = merged.text || steeringContentText(merged.content);
|
|
166
172
|
try {
|
|
167
173
|
opts.onSteerMessage?.(text, {
|
|
@@ -172,9 +178,12 @@ function injectSteeringEntry(merged, { messages, opts, stage, onSkillPrompt }) {
|
|
|
172
178
|
...(notification ? { mode: 'task-notification' } : {}),
|
|
173
179
|
...(execution ? { execution } : {}),
|
|
174
180
|
...(Array.isArray(merged.images) && merged.images.length ? { images: merged.images } : {}),
|
|
175
|
-
|
|
181
|
+
transcriptMeta: steeringTranscriptMeta,
|
|
182
|
+
messageId,
|
|
176
183
|
});
|
|
177
|
-
} catch {
|
|
184
|
+
} catch {
|
|
185
|
+
/* best-effort host callback */
|
|
186
|
+
}
|
|
178
187
|
return {
|
|
179
188
|
count: Number(merged.count) || 1,
|
|
180
189
|
textLength: String(text || '').length,
|
|
@@ -224,9 +233,11 @@ export function createSteeringDrain({ messages, opts, sessionId, onSkillPrompt }
|
|
|
224
233
|
try {
|
|
225
234
|
process.stderr.write(
|
|
226
235
|
`[steer] sess=${sessionId} injected ${stage} user message(s)` +
|
|
227
|
-
` (merged=${totalCount} len=${totalTextLen} waitMs=${
|
|
236
|
+
` (merged=${totalCount} len=${totalTextLen} waitMs=${maxQueueWaitMs})\n`
|
|
228
237
|
);
|
|
229
|
-
} catch {
|
|
238
|
+
} catch {
|
|
239
|
+
/* best-effort diagnostics */
|
|
240
|
+
}
|
|
230
241
|
}
|
|
231
242
|
return true;
|
|
232
243
|
};
|
|
@@ -12,6 +12,8 @@ import {
|
|
|
12
12
|
filterSkillsExcludingDisabled,
|
|
13
13
|
isSkillDisabled,
|
|
14
14
|
skillMissingFeature,
|
|
15
|
+
skillOutsideScope,
|
|
16
|
+
skillOutsideScopeError,
|
|
15
17
|
} from '../../context/collect.mjs';
|
|
16
18
|
|
|
17
19
|
// Eager-dispatch: tools with readOnlyHint:true in their declaration are safe
|
|
@@ -96,6 +98,7 @@ export function viewSkill(cwd, name, session = null) {
|
|
|
96
98
|
return `Error: skill "${skillName}" needs the ${missingFeature} built-in feature, which is not installed or is switched off in Extensions → Plugin → Built-in`;
|
|
97
99
|
}
|
|
98
100
|
if (isSkillDisabled(skillName)) return `Error: skill "${skillName}" is disabled`;
|
|
101
|
+
if (skillOutsideScope(skillName, cwd)) return skillOutsideScopeError(skillName);
|
|
99
102
|
const res = loadSkillResource(skillName, cwd);
|
|
100
103
|
if (!res) return `Error: skill "${skillName}" not found`;
|
|
101
104
|
// Return the general tool envelope: the model-visible tool_result is the
|
|
@@ -40,6 +40,7 @@ export function usageDeltaEvent({
|
|
|
40
40
|
model,
|
|
41
41
|
usage,
|
|
42
42
|
sendTools,
|
|
43
|
+
toolCalls = 0,
|
|
43
44
|
}) {
|
|
44
45
|
return {
|
|
45
46
|
sessionId,
|
|
@@ -51,6 +52,8 @@ export function usageDeltaEvent({
|
|
|
51
52
|
usageMetricsEpoch,
|
|
52
53
|
deltaInput: usage.inputTokens || 0,
|
|
53
54
|
deltaOutput: usage.outputTokens || 0,
|
|
55
|
+
// Tool calls this response dispatched; the session's cumulative count.
|
|
56
|
+
deltaToolCalls: toolCalls,
|
|
54
57
|
...reasoningUsage(usage),
|
|
55
58
|
deltaPrompt: usage.promptTokens || 0,
|
|
56
59
|
// Cache delta carried alongside input/output so live metrics reflect
|
|
@@ -12,6 +12,17 @@ import {
|
|
|
12
12
|
|
|
13
13
|
const SYNTHETIC_PROMPT_SOURCES = ['goal-continuation', 'goal-closeout'];
|
|
14
14
|
|
|
15
|
+
// A caller-declared prompt source the runtime trusts as provenance of the
|
|
16
|
+
// initial prompt: Goal turns are runtime-synthetic; a task notification (an
|
|
17
|
+
// idle-drained completion, an automation run's agent results) is stored like
|
|
18
|
+
// one the steering/queue drains inject, never as the user speaking — so none
|
|
19
|
+
// of these run explicit skill selection.
|
|
20
|
+
function initialPromptSourceFor(promptSource) {
|
|
21
|
+
if (SYNTHETIC_PROMPT_SOURCES.includes(promptSource)) return { source: promptSource, synthetic: true };
|
|
22
|
+
if (promptSource === PENDING_MODE_TASK_NOTIFICATION) return { source: promptSource };
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
|
|
15
26
|
/** Prompt provenance for a drained queue turn: the source plus its execution when one exists. */
|
|
16
27
|
const promptSourceFields = (source, execution) => {
|
|
17
28
|
if (!source) return null;
|
|
@@ -42,9 +53,7 @@ export function createAskPromptQueue({ sessionId, promptSource }) {
|
|
|
42
53
|
// Local FIFO of follow-up prompts drained from the pending-message queue
|
|
43
54
|
// after each turn — keeps queued `agent type=send` messages in order.
|
|
44
55
|
const tail = [];
|
|
45
|
-
let initialPromptSource =
|
|
46
|
-
? { source: promptSource, synthetic: true }
|
|
47
|
-
: null;
|
|
56
|
+
let initialPromptSource = initialPromptSourceFor(promptSource);
|
|
48
57
|
|
|
49
58
|
/** The next turn's input — prompt, caller context, consumed queue entries
|
|
50
59
|
* and provenance — or null when nothing model-visible is left to run. */
|
|
@@ -40,13 +40,23 @@ const traceAskStart = (sessionId, explicitPrefetch) => {
|
|
|
40
40
|
|
|
41
41
|
/** The transcript timestamps the caller supplied for this ask: the persisted
|
|
42
42
|
* user metadata plus a one-shot reader for the assistant metadata. */
|
|
43
|
-
function createAskTranscriptMeta(rawTranscriptMeta) {
|
|
43
|
+
export function createAskTranscriptMeta(rawTranscriptMeta) {
|
|
44
44
|
return {
|
|
45
45
|
raw: rawTranscriptMeta,
|
|
46
46
|
user: persistedUserTranscriptMetadata(rawTranscriptMeta),
|
|
47
47
|
takeAssistant: () => {
|
|
48
|
+
const live = rawTranscriptMeta && typeof rawTranscriptMeta === 'object';
|
|
49
|
+
// An id the live row already minted is the one persisted; otherwise the
|
|
50
|
+
// row has not been drawn yet and takes this message's id and time.
|
|
51
|
+
const rowKnowsId =
|
|
52
|
+
live && typeof rawTranscriptMeta.assistantMessageId === 'string' && rawTranscriptMeta.assistantMessageId;
|
|
48
53
|
const metadata = persistedAssistantTranscriptMetadata(rawTranscriptMeta);
|
|
49
|
-
if (
|
|
54
|
+
if (live) {
|
|
55
|
+
// One-shot: the next reply gets its own time and stable id.
|
|
56
|
+
delete rawTranscriptMeta.assistantAt;
|
|
57
|
+
delete rawTranscriptMeta.assistantMessageId;
|
|
58
|
+
rawTranscriptMeta.persistedAssistant = rowKnowsId ? null : { messageId: metadata.messageId, at: metadata.at };
|
|
59
|
+
}
|
|
50
60
|
return metadata;
|
|
51
61
|
},
|
|
52
62
|
};
|
|
@@ -138,7 +148,9 @@ export async function askSession(sessionId, prompt, context, onToolCall, cwdOver
|
|
|
138
148
|
// queued send always lands AFTER the in-flight prompt here, ordering is
|
|
139
149
|
// preserved and the spawn/connecting startup race disappears.
|
|
140
150
|
for (;;) {
|
|
141
|
-
|
|
151
|
+
// `skillSelection` (askOpts) is the trusted selection input of the
|
|
152
|
+
// caller's own prompt only; drained follow-up turns never inherit it.
|
|
153
|
+
const input = queue.nextTurn({ prompt, context, explicitPrefetch, skillSelection: askOpts.skillSelection });
|
|
142
154
|
if (!input) {
|
|
143
155
|
void takeoverHydration.then((count) => {
|
|
144
156
|
if (count <= 0) return;
|
|
@@ -8,7 +8,12 @@
|
|
|
8
8
|
// model declares effort levels (the effort is sent with each request).
|
|
9
9
|
import { readSection } from '../../../../shared/config.mjs';
|
|
10
10
|
import { autoEffortModel, turnEffortConfigurationMode } from '../../providers/effort-configuration.mjs';
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
autoEffortApplicable,
|
|
13
|
+
autoEffortBase,
|
|
14
|
+
normalizeAutoEffortMode,
|
|
15
|
+
resolveAutoEffort,
|
|
16
|
+
} from '../../providers/auto-effort.mjs';
|
|
12
17
|
import { builtinFeatureActive } from '../../runtime-core/builtin-features.mjs';
|
|
13
18
|
import { effortOptionsFor } from '../../runtime-core/effort.mjs';
|
|
14
19
|
import { effortJudgeSupportsSteps, judgeTurn, recordEffortDecision } from '../../../../effort-judge/judge-client.mjs';
|
|
@@ -70,18 +75,14 @@ export async function resolveTurnAutoEffort({ sessionId, session, provider, inpu
|
|
|
70
75
|
// Agent sessions are judged like any other: their spawn brief and later Lead
|
|
71
76
|
// `send` messages arrive as plain prompts.
|
|
72
77
|
if (mode === 'off' || input?.promptSource) return null;
|
|
78
|
+
// The session's route turned Auto effort off: its chosen effort stands.
|
|
79
|
+
if (session?.autoEffort === false) return null;
|
|
73
80
|
const request = promptContentText(input?.prompt).trim();
|
|
74
81
|
// Skill bodies and runtime blocks arrive as tagged text, not as a request.
|
|
75
82
|
if (!request || request.startsWith('<')) return null;
|
|
76
83
|
if (!turnEffortConfigurationMode(session, provider)) return null;
|
|
77
84
|
const chosen = String(session.effort || '').toLowerCase();
|
|
78
85
|
const base = autoEffortBase(chosen);
|
|
79
|
-
// The previous user request shows the work a short follow-up continues.
|
|
80
|
-
const judged = await judgeTurn({
|
|
81
|
-
request,
|
|
82
|
-
prev: lastText(session.messages, 'assistant'),
|
|
83
|
-
prevRequest: lastText(session.messages, 'user'),
|
|
84
|
-
});
|
|
85
86
|
const record = {
|
|
86
87
|
at: new Date().toISOString(),
|
|
87
88
|
sessionId,
|
|
@@ -92,15 +93,24 @@ export async function resolveTurnAutoEffort({ sessionId, session, provider, inpu
|
|
|
92
93
|
base,
|
|
93
94
|
requestChars: request.length,
|
|
94
95
|
};
|
|
96
|
+
const options = effortOptionsFor(session.provider, autoEffortModel(session.provider, provider, session.model));
|
|
97
|
+
// No judged outcome can apply when the base is off the model's ladder, so
|
|
98
|
+
// the judge is not asked (in observe mode too: nothing would be logged).
|
|
99
|
+
if (!autoEffortApplicable({ base, options })) {
|
|
100
|
+
recordEffortDecision({ ...record, skipped: 'default-outside-auto-range' });
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
// The previous user request shows the work a short follow-up continues.
|
|
104
|
+
const judged = await judgeTurn({
|
|
105
|
+
request,
|
|
106
|
+
prev: lastText(session.messages, 'assistant'),
|
|
107
|
+
prevRequest: lastText(session.messages, 'user'),
|
|
108
|
+
});
|
|
95
109
|
if (!judged.probs) {
|
|
96
110
|
recordEffortDecision({ ...record, skipped: judged.skipped });
|
|
97
111
|
return null;
|
|
98
112
|
}
|
|
99
|
-
const resolved = resolveAutoEffort({
|
|
100
|
-
base,
|
|
101
|
-
options: effortOptionsFor(session.provider, autoEffortModel(session.provider, provider, session.model)),
|
|
102
|
-
probs: judged.probs,
|
|
103
|
-
});
|
|
113
|
+
const resolved = resolveAutoEffort({ base, options, probs: judged.probs });
|
|
104
114
|
recordEffortDecision({
|
|
105
115
|
...record,
|
|
106
116
|
...(resolved || { skipped: 'default-outside-auto-range' }),
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// (runAskAgentLoop). Provider-not-available and trim failures throw here so
|
|
6
6
|
// the caller marks the session errored instead of leaving stage='connecting'.
|
|
7
7
|
import { getProvider } from '../../providers/registry.mjs';
|
|
8
|
-
import { prepareExplicitSkills } from '../explicit-skills.mjs';
|
|
8
|
+
import { notifySkillsApplied, prepareExplicitSkills, recordAppliedSkills } from '../explicit-skills.mjs';
|
|
9
9
|
import { prepareTurnEffortConfiguration } from '../../providers/effort-configuration.mjs';
|
|
10
10
|
import { resolveTurnAutoEffort, turnStepAutoEffort } from './ask-turn-auto-effort.mjs';
|
|
11
11
|
import { saveSessionAsync } from '../store.mjs';
|
|
@@ -151,9 +151,16 @@ export async function runAskAgentLoop({
|
|
|
151
151
|
}
|
|
152
152
|
try {
|
|
153
153
|
if (!input.promptSource) {
|
|
154
|
-
await prepareExplicitSkills(input.prompt, outgoing, session, {
|
|
154
|
+
const applied = await prepareExplicitSkills(input.prompt, outgoing, session, {
|
|
155
|
+
cwd: effectiveCwd,
|
|
156
|
+
signal: turnSignal,
|
|
157
|
+
selection: input.skillSelection,
|
|
158
|
+
});
|
|
159
|
+
// The user turn message sits right after the history it was built on.
|
|
160
|
+
const userMessage = recordAppliedSkills(outgoing, outgoing[prepared.beforeCount - 1], applied);
|
|
155
161
|
session.messages = filterModelVisibleSessionMessages(outgoing);
|
|
156
162
|
checkpoint.schedule(true);
|
|
163
|
+
notifySkillsApplied(askOpts?.onSkillsApplied, applied, userMessage);
|
|
157
164
|
}
|
|
158
165
|
return await _api_call_with_interrupt(sessionId, (signal) =>
|
|
159
166
|
agentLoop(
|
|
@@ -13,7 +13,9 @@ const optionalFn = (value) => (typeof value === 'function' ? value : undefined);
|
|
|
13
13
|
const relay = (fn, ...args) => {
|
|
14
14
|
try {
|
|
15
15
|
fn?.(...args);
|
|
16
|
-
} catch {
|
|
16
|
+
} catch {
|
|
17
|
+
/* a host callback must never break the turn */
|
|
18
|
+
}
|
|
17
19
|
};
|
|
18
20
|
|
|
19
21
|
/**
|
|
@@ -70,10 +72,10 @@ export function buildAgentLoopOptions({
|
|
|
70
72
|
checkpoint.schedule();
|
|
71
73
|
if (typeof askOpts?.onReasoningDelta === 'function') askOpts.onReasoningDelta(chunk);
|
|
72
74
|
},
|
|
73
|
-
onAssistantText: (text) => {
|
|
75
|
+
onAssistantText: (text, detail) => {
|
|
74
76
|
interruption.recordAssistantText(text);
|
|
75
77
|
checkpoint.schedule(true);
|
|
76
|
-
if (typeof askOpts?.onAssistantText === 'function') askOpts.onAssistantText(text);
|
|
78
|
+
if (typeof askOpts?.onAssistantText === 'function') askOpts.onAssistantText(text, detail);
|
|
77
79
|
},
|
|
78
80
|
takeAssistantTranscriptMetadata,
|
|
79
81
|
// Send-opt only. Never copy onto `session` — a transient
|
|
@@ -150,6 +152,10 @@ export function buildAgentLoopOptions({
|
|
|
150
152
|
checkpoint.schedule(true);
|
|
151
153
|
relay(askOpts?.onSteerMessage, text, detail);
|
|
152
154
|
},
|
|
155
|
+
onSkillsApplied: (names, detail) => {
|
|
156
|
+
checkpoint.schedule(true);
|
|
157
|
+
relay(askOpts?.onSkillsApplied, names, detail);
|
|
158
|
+
},
|
|
153
159
|
notifyFn: optionalFn(askOpts?.notifyFn),
|
|
154
160
|
// Same projection compaction uses, so a session presents one identity on
|
|
155
161
|
// every request it makes.
|
|
@@ -22,11 +22,13 @@ import { recordProviderContextBaseline } from '../loop/compact-policy.mjs';
|
|
|
22
22
|
import { throwIfAborted } from '../../../../shared/abort-race.mjs';
|
|
23
23
|
import { appendAssistantTurnMessage, persistProviderState, recordAskUsage } from './ask-turn-commit.mjs';
|
|
24
24
|
|
|
25
|
-
function attachAssistantTranscriptCompletion(messages, completion, turnStartedAt = 0) {
|
|
25
|
+
export function attachAssistantTranscriptCompletion(messages, completion, turnStartedAt = 0) {
|
|
26
26
|
if (!Array.isArray(messages) || !completion || typeof completion !== 'object') return false;
|
|
27
27
|
const elapsedMs = Math.max(0, Number(completion.elapsedMs || 0));
|
|
28
28
|
const status = typeof completion.status === 'string' && completion.status ? completion.status : 'done';
|
|
29
29
|
const verb = typeof completion.verb === 'string' && completion.verb ? completion.verb : 'Thought';
|
|
30
|
+
const checkpointId =
|
|
31
|
+
typeof completion.checkpointId === 'string' && completion.checkpointId ? completion.checkpointId : '';
|
|
30
32
|
let turnStart = -1;
|
|
31
33
|
const expectedAt = Number(turnStartedAt || 0);
|
|
32
34
|
if (expectedAt > 0) {
|
|
@@ -60,7 +62,7 @@ function attachAssistantTranscriptCompletion(messages, completion, turnStartedAt
|
|
|
60
62
|
...meta,
|
|
61
63
|
transcript: {
|
|
62
64
|
...transcript,
|
|
63
|
-
completion: { status, verb, elapsedMs },
|
|
65
|
+
completion: { status, verb, elapsedMs, ...(checkpointId ? { checkpointId } : {}) },
|
|
64
66
|
},
|
|
65
67
|
},
|
|
66
68
|
};
|
|
@@ -145,6 +147,7 @@ export function publishAskTurn({ sessionId, opened, terminalResultPreview, askOp
|
|
|
145
147
|
status: 'done',
|
|
146
148
|
verb: rawTranscriptMeta?.completionVerb,
|
|
147
149
|
elapsedMs: Date.now() - turnStartedAt,
|
|
150
|
+
checkpointId: rawTranscriptMeta?.checkpointId,
|
|
148
151
|
},
|
|
149
152
|
turnStartedAt
|
|
150
153
|
);
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
} from '../context-utils.mjs';
|
|
16
16
|
import { previewFreshContextCompaction, runFreshContextCompact } from '../loop/fresh-context.mjs';
|
|
17
17
|
import { positiveInt } from '../../../../shared/numbers.mjs';
|
|
18
|
+
import { writeStderrBestEffort } from '../../../../shared/best-effort-stderr.mjs';
|
|
18
19
|
import { traceAgentCompact, messagePrefixHash } from '../../agent-trace.mjs';
|
|
19
20
|
import { uncachedInputTokensForProvider } from './usage-metrics.mjs';
|
|
20
21
|
import { pruneOffloadSession } from '../tool-result-offload.mjs';
|
|
@@ -33,6 +34,7 @@ import {
|
|
|
33
34
|
shouldCompactForRequestMedia,
|
|
34
35
|
} from '../loop/compact-policy.mjs';
|
|
35
36
|
import { snapshotProviderRequestTools } from '../../runtime-core/tool-catalog.mjs';
|
|
37
|
+
import { scheduleCompactionArchive, stampCompactionMessageIds } from '../compaction-archive-capture.mjs';
|
|
36
38
|
|
|
37
39
|
// 'compacting' is a transient in-flight stage written just before Compact
|
|
38
40
|
// runs. If the process crashes or only partially
|
|
@@ -126,7 +128,7 @@ function handoffSummaryTimeoutMs(session, messageTokens) {
|
|
|
126
128
|
* mutated and nothing is persisted — so a caller may compact a COPY of a
|
|
127
129
|
* conversation. Session inheritance relies on exactly that: an oversized
|
|
128
130
|
* transcript is compacted for the heir while the session that owns it keeps
|
|
129
|
-
* every message
|
|
131
|
+
* every message.
|
|
130
132
|
*/
|
|
131
133
|
export async function runHandoffCompaction({
|
|
132
134
|
session,
|
|
@@ -190,9 +192,8 @@ async function sessionCompactionPlan(session, opts) {
|
|
|
190
192
|
}
|
|
191
193
|
// Reserve must mirror loop.mjs (buildCompactPolicy): request reserve (tool
|
|
192
194
|
// schema) PLUS the configured reserve (session.compaction.reservedTokens or
|
|
193
|
-
// MIXDOG_AGENT_COMPACT_RESERVED_TOKENS env).
|
|
194
|
-
// the
|
|
195
|
-
// loop path reserves, so a compacted transcript could overflow on next send.
|
|
195
|
+
// MIXDOG_AGENT_COMPACT_RESERVED_TOKENS env). Without the configured headroom
|
|
196
|
+
// the loop path reserves, a compacted transcript could overflow on next send.
|
|
196
197
|
// A cold (just loaded) transcript is metered in slices first; the plan
|
|
197
198
|
// numbers below then read the per-message memos.
|
|
198
199
|
await primeContextEstimates(messages, session);
|
|
@@ -202,6 +203,7 @@ async function sessionCompactionPlan(session, opts) {
|
|
|
202
203
|
resolvedSessionId,
|
|
203
204
|
mode,
|
|
204
205
|
force,
|
|
206
|
+
archive: opts.archive !== false,
|
|
205
207
|
messages,
|
|
206
208
|
boundary,
|
|
207
209
|
alignedPolicy,
|
|
@@ -292,8 +294,8 @@ function compactionRecord(plan, { stage, after, now, reserve, outcome }) {
|
|
|
292
294
|
}
|
|
293
295
|
|
|
294
296
|
// compact_meta parity with the loop's pre-send pass: the out-of-loop
|
|
295
|
-
// (post-turn/manual) compaction — and its failure —
|
|
296
|
-
//
|
|
297
|
+
// (post-turn/manual) compaction — and its failure — is visible to trace
|
|
298
|
+
// analytics.
|
|
297
299
|
function traceSessionCompaction(plan, compactStartedAt, { counts, failure }) {
|
|
298
300
|
const { session, mode } = plan;
|
|
299
301
|
traceAgentCompact({
|
|
@@ -342,13 +344,9 @@ async function runSessionHandoff(plan, opts) {
|
|
|
342
344
|
} catch (err) {
|
|
343
345
|
run.freshContextError = err;
|
|
344
346
|
run.compactError = err;
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
);
|
|
349
|
-
} catch {
|
|
350
|
-
/* best-effort */
|
|
351
|
-
}
|
|
347
|
+
writeStderrBestEffort(
|
|
348
|
+
`[session] fresh-context ${mode} compact failed (sess=${session.id || 'unknown'}): ${err?.message || err}\n`
|
|
349
|
+
);
|
|
352
350
|
}
|
|
353
351
|
if (!run.compacted && !run.compactError) {
|
|
354
352
|
run.compactError = new Error('fresh-context compact produced no messages');
|
|
@@ -515,8 +513,8 @@ function compactionOutcome(session, freshContextResult, changed, now) {
|
|
|
515
513
|
}
|
|
516
514
|
|
|
517
515
|
// Observability parity with the loop's pre-send pass: record the
|
|
518
|
-
// out-of-loop mutation as compact_meta
|
|
519
|
-
//
|
|
516
|
+
// out-of-loop mutation as compact_meta, so a large post-turn compact is not
|
|
517
|
+
// traced as intentional_transition: null.
|
|
520
518
|
function traceCommittedCompaction(plan, compactStartedAt, { messages, compacted, beforeBytes, afterBytes, changed }) {
|
|
521
519
|
let beforePrefixHash = null;
|
|
522
520
|
try {
|
|
@@ -645,6 +643,19 @@ async function commitSessionCompaction(plan, run, compactStartedAt) {
|
|
|
645
643
|
},
|
|
646
644
|
outcome: compactionOutcome(session, freshContextResult, changed, now),
|
|
647
645
|
});
|
|
646
|
+
// Display-only: the dropped conversation stays readable above the divider.
|
|
647
|
+
// Only the selection and the segment number happen here; the projection and
|
|
648
|
+
// the write run later, off this commit.
|
|
649
|
+
const archived =
|
|
650
|
+
changed && plan.archive
|
|
651
|
+
? scheduleCompactionArchive({
|
|
652
|
+
session,
|
|
653
|
+
sessionId: resolvedSessionId,
|
|
654
|
+
before: messages,
|
|
655
|
+
after: transcript,
|
|
656
|
+
at: now,
|
|
657
|
+
})
|
|
658
|
+
: null;
|
|
648
659
|
if (changed) {
|
|
649
660
|
invalidateProviderContextBaseline(session);
|
|
650
661
|
if (postCompactPolicy) {
|
|
@@ -678,6 +689,10 @@ async function commitSessionCompaction(plan, run, compactStartedAt) {
|
|
|
678
689
|
freshContextError: null,
|
|
679
690
|
handoffSource: freshContextResult?.handoffSource || 'session-local',
|
|
680
691
|
usage: freshContextResult?.usage || null,
|
|
692
|
+
// Messages that left the model context (0 for a rewrite-only pass):
|
|
693
|
+
// surfaces archive only those rows.
|
|
694
|
+
droppedMessages: archived?.dropped ?? 0,
|
|
695
|
+
droppedIdentities: archived?.identities ?? null,
|
|
681
696
|
}
|
|
682
697
|
);
|
|
683
698
|
}
|
|
@@ -692,7 +707,8 @@ export async function runSessionCompaction(session, opts = {}) {
|
|
|
692
707
|
});
|
|
693
708
|
}
|
|
694
709
|
plan.requireReduction =
|
|
695
|
-
(plan.mode === 'auto' || opts.requireReduction === true) &&
|
|
710
|
+
(plan.mode === 'auto' || opts.requireReduction === true) &&
|
|
711
|
+
!shouldCompactForRequestMedia(plan.messages, session.provider);
|
|
696
712
|
const skipped = () =>
|
|
697
713
|
compactionResult(plan, { changed: false, skipped: true, reason: 'no_token_reduction' }, unchangedAfter(plan), {
|
|
698
714
|
freshContext: false,
|
|
@@ -713,6 +729,11 @@ export async function runSessionCompaction(session, opts = {}) {
|
|
|
713
729
|
}).reducesTokens
|
|
714
730
|
)
|
|
715
731
|
return skipped();
|
|
732
|
+
// Every message enters the compaction with a stable id (legacy ones are
|
|
733
|
+
// stamped now and persisted): the result's rewrites carry it, so what was
|
|
734
|
+
// dropped is exactly the ids the result no longer holds. The snapshot is a
|
|
735
|
+
// prefix of the live transcript holding the same message objects.
|
|
736
|
+
stampCompactionMessageIds(plan.messages, plan.resolvedSessionId);
|
|
716
737
|
const compactStartedAt = Date.now();
|
|
717
738
|
try {
|
|
718
739
|
await opts.onStageChange?.('compacting');
|
|
@@ -117,8 +117,12 @@ export function resolveSessionContextMeta(provider, model, seed = {}, { wholeWin
|
|
|
117
117
|
// (a session older than selectedContextWindow, a route saved before the
|
|
118
118
|
// catalog warmed) is still the user's choice and keeps the served window.
|
|
119
119
|
const recordsSelection = wholeWindow || boundedPercent(seed.contextPercent) !== null;
|
|
120
|
+
// An exact token selection without its resolved window still names it,
|
|
121
|
+
// bounded by what the model serves.
|
|
122
|
+
const selectedTokens = positiveInt(seed.contextTokens);
|
|
120
123
|
const requestedContextWindow =
|
|
121
124
|
positiveInt(seed.selectedContextWindow) ||
|
|
125
|
+
(selectedTokens ? Math.min(selectedTokens, servedContextWindow) : 0) ||
|
|
122
126
|
(recordsSelection
|
|
123
127
|
? servedContextWindow
|
|
124
128
|
: contextWindowRange({ provider: providerNameOf(provider), contextWindow: servedContextWindow }).defaultWindow);
|
|
@@ -158,6 +158,14 @@ export function lateDeliveryText(text, entry, now = Date.now()) {
|
|
|
158
158
|
return `[late delivery: queued ${age} ago, before the current session owner started]\n${value}`;
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
+
// A non-completion entry may be queued explicitly as a task notification (a
|
|
162
|
+
// runtime/channel notice, never the user typing): the mode survives
|
|
163
|
+
// normalization and the durable spool so the drain stores it as one and it
|
|
164
|
+
// never drives explicit skill selection.
|
|
165
|
+
function explicitModeField(entry) {
|
|
166
|
+
return entry?.mode === PENDING_MODE_TASK_NOTIFICATION ? { mode: PENDING_MODE_TASK_NOTIFICATION } : {};
|
|
167
|
+
}
|
|
168
|
+
|
|
161
169
|
export function normalizePendingMessageEntry(entry) {
|
|
162
170
|
if (typeof entry === 'string') {
|
|
163
171
|
const text = entry.trim();
|
|
@@ -173,7 +181,10 @@ export function normalizePendingMessageEntry(entry) {
|
|
|
173
181
|
id: pendingMessageId(entry),
|
|
174
182
|
enqueuedAt: Number(entry.enqueuedAt) || Date.now(),
|
|
175
183
|
};
|
|
176
|
-
const entryOptions =
|
|
184
|
+
const entryOptions = {
|
|
185
|
+
...(entry.options && typeof entry.options === 'object' ? { options: entry.options } : {}),
|
|
186
|
+
...explicitModeField(entry),
|
|
187
|
+
};
|
|
177
188
|
const marker =
|
|
178
189
|
entry.notificationKind === COMPLETION_NOTIFICATION_KIND
|
|
179
190
|
? {
|
|
@@ -259,26 +270,28 @@ function normalizePersistedEntryBase(entry) {
|
|
|
259
270
|
}
|
|
260
271
|
: null;
|
|
261
272
|
}
|
|
273
|
+
const mode = explicitModeField(entry);
|
|
262
274
|
if (typeof entry.message === 'string') {
|
|
263
275
|
const message = entry.message.trim();
|
|
264
|
-
return message ? { id, message, enqueuedAt } : null;
|
|
276
|
+
return message ? { id, message, ...mode, enqueuedAt } : null;
|
|
265
277
|
}
|
|
266
278
|
if (Object.hasOwn(entry, 'content')) {
|
|
267
279
|
const normalized = normalizePendingMessageEntry(entry);
|
|
268
280
|
if (!normalized) return null;
|
|
269
281
|
if (typeof normalized.content === 'string' && !normalized.options) {
|
|
270
|
-
return { id, message: normalized.text || normalized.content, enqueuedAt };
|
|
282
|
+
return { id, message: normalized.text || normalized.content, ...mode, enqueuedAt };
|
|
271
283
|
}
|
|
272
284
|
return {
|
|
273
285
|
id,
|
|
274
286
|
content: normalized.content,
|
|
275
287
|
text: normalized.text,
|
|
276
288
|
...(normalized.options ? { options: normalized.options } : {}),
|
|
289
|
+
...mode,
|
|
277
290
|
enqueuedAt,
|
|
278
291
|
};
|
|
279
292
|
}
|
|
280
293
|
const text = pendingMessageText(entry);
|
|
281
|
-
return text ? { id, message: text, enqueuedAt } : null;
|
|
294
|
+
return text ? { id, message: text, ...mode, enqueuedAt } : null;
|
|
282
295
|
}
|
|
283
296
|
|
|
284
297
|
export function modelVisiblePendingMessages(messages) {
|
|
@@ -185,6 +185,96 @@ export function refreshSessionBp3Environment(session, cwd) {
|
|
|
185
185
|
return true;
|
|
186
186
|
}
|
|
187
187
|
|
|
188
|
+
const CORE_MEMORY_HEADING = '# Core Memory\n';
|
|
189
|
+
const INSTRUCTION_FILES_HEADING = '# Instruction Files';
|
|
190
|
+
|
|
191
|
+
function trimmedSlice(value) {
|
|
192
|
+
return typeof value === 'string' ? value.trim() : '';
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Where a heading-led slice starts in a BP3 join: `cut` ends the text before
|
|
196
|
+
// it (separator included), `start` is the slice's first character.
|
|
197
|
+
function bp3SliceAt(text, heading) {
|
|
198
|
+
if (text.startsWith(heading)) return { cut: 0, start: 0 };
|
|
199
|
+
const at = text.indexOf(`${BP3_PART_SEPARATOR}${heading}`);
|
|
200
|
+
return at < 0 ? null : { cut: at, start: at + BP3_PART_SEPARATOR.length };
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Replace the workspace-scoped tail of a BP3 core (composeSystemPrompt order:
|
|
205
|
+
* …, `# Core Memory`, `# Instruction Files`). The instruction-files slice is
|
|
206
|
+
* always last and may itself contain separators, so it is cut by position;
|
|
207
|
+
* the core-memory slice is one separator-free part. `undefined` keeps a slice,
|
|
208
|
+
* an empty string drops it.
|
|
209
|
+
* @param {string} core
|
|
210
|
+
* @param {{ coreMemoryContext?: string, instructionFilesContext?: string }} slices
|
|
211
|
+
*/
|
|
212
|
+
export function replaceWorkspaceCoreSlices(core, { coreMemoryContext, instructionFilesContext } = {}) {
|
|
213
|
+
let head = String(core || '');
|
|
214
|
+
let instructionFiles = '';
|
|
215
|
+
const instructionAt = bp3SliceAt(head, INSTRUCTION_FILES_HEADING);
|
|
216
|
+
if (instructionAt) {
|
|
217
|
+
instructionFiles = head.slice(instructionAt.start);
|
|
218
|
+
head = head.slice(0, instructionAt.cut);
|
|
219
|
+
}
|
|
220
|
+
let parts = head ? head.split(BP3_PART_SEPARATOR) : [];
|
|
221
|
+
if (coreMemoryContext !== undefined) {
|
|
222
|
+
parts = parts.filter((part) => !part.startsWith(CORE_MEMORY_HEADING));
|
|
223
|
+
const memory = trimmedSlice(coreMemoryContext);
|
|
224
|
+
if (memory) parts.push(`${CORE_MEMORY_HEADING}${memory}`);
|
|
225
|
+
}
|
|
226
|
+
if (instructionFilesContext !== undefined) instructionFiles = trimmedSlice(instructionFilesContext);
|
|
227
|
+
return [...parts, instructionFiles].filter((part) => part && part.trim()).join(BP3_PART_SEPARATOR);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Replace the shell/project facts that lead the persisted environment tail
|
|
232
|
+
* (`- Cwd …`, shell tools, git state, cwd listing); the trailing response
|
|
233
|
+
* language block is kept. `undefined` keeps the facts.
|
|
234
|
+
*/
|
|
235
|
+
export function replaceWorkspaceEnvironment(environmentTail, environmentContext) {
|
|
236
|
+
if (environmentContext === undefined) return environmentTail;
|
|
237
|
+
const parts = typeof environmentTail === 'string' && environmentTail ? environmentTail.split(BP3_PART_SEPARATOR) : [];
|
|
238
|
+
const facts = trimmedSlice(environmentContext);
|
|
239
|
+
if (parts[0]?.startsWith('- ')) parts[0] = facts;
|
|
240
|
+
else parts.unshift(facts);
|
|
241
|
+
return parts.filter((part) => part && part.trim()).join(BP3_PART_SEPARATOR);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Re-root an existing session's prompt at a new workspace without touching
|
|
246
|
+
* the conversation: environment facts, project memory and instruction files
|
|
247
|
+
* are replaced in place (never appended), then the `# Session` block is
|
|
248
|
+
* rebuilt for `cwd`. Messages are replaced, not mutated, so delta saves write
|
|
249
|
+
* a full snapshot.
|
|
250
|
+
* @param {object} session
|
|
251
|
+
* @param {{ cwd: string, environmentContext?: string, coreMemoryContext?: string, instructionFilesContext?: string }} context
|
|
252
|
+
* @returns {boolean}
|
|
253
|
+
*/
|
|
254
|
+
export function refreshSessionWorkspaceContext(
|
|
255
|
+
session,
|
|
256
|
+
{ cwd, environmentContext, coreMemoryContext, instructionFilesContext } = {}
|
|
257
|
+
) {
|
|
258
|
+
if (!session) return false;
|
|
259
|
+
if (typeof session.bp3EnvironmentContext === 'string') {
|
|
260
|
+
session.bp3EnvironmentContext = replaceWorkspaceEnvironment(session.bp3EnvironmentContext, environmentContext);
|
|
261
|
+
}
|
|
262
|
+
const slices = { coreMemoryContext, instructionFilesContext };
|
|
263
|
+
if (session.bp3EnvSplit === true) {
|
|
264
|
+
const target = bp3SystemMessage(session);
|
|
265
|
+
if (target && typeof target.content === 'string') {
|
|
266
|
+
const nextCore = replaceWorkspaceCoreSlices(target.content, slices);
|
|
267
|
+
replaceSystemMessageContent(session, target, nextCore);
|
|
268
|
+
session.bp3CoreContext = nextCore;
|
|
269
|
+
}
|
|
270
|
+
} else if (typeof session.bp3CoreContext === 'string') {
|
|
271
|
+
// Legacy combined layout: refreshSessionBp3Environment rebuilds the tier3
|
|
272
|
+
// block from the core plus the environment below.
|
|
273
|
+
session.bp3CoreContext = replaceWorkspaceCoreSlices(session.bp3CoreContext, slices);
|
|
274
|
+
}
|
|
275
|
+
return refreshSessionBp3Environment(session, cwd);
|
|
276
|
+
}
|
|
277
|
+
|
|
188
278
|
export function resetSessionBp3Environment(session) {
|
|
189
279
|
if (session?.bp3EnvSplit === true) {
|
|
190
280
|
const target = bpEnvSystemMessage(session);
|