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
|
@@ -25,6 +25,8 @@ import {
|
|
|
25
25
|
import { getProvider } from '../../providers/registry.mjs';
|
|
26
26
|
import { isSessionCompactionBlocked, getSessionAbortSignal, _runtimeEntries } from './runtime-liveness.mjs';
|
|
27
27
|
import { mintSessionId } from './session-id.mjs';
|
|
28
|
+
import { hideCompactionArchive } from '../compaction-archive-capture.mjs';
|
|
29
|
+
import { writeStderrBestEffort } from '../../../../shared/best-effort-stderr.mjs';
|
|
28
30
|
|
|
29
31
|
/** Force-flush session metrics to disk. Used by watchdog terminal-reap (fix B). */
|
|
30
32
|
export async function flushSessionMetrics(sessionId) {
|
|
@@ -97,14 +99,6 @@ export async function updateSessionManualTitle(id, title) {
|
|
|
97
99
|
return true;
|
|
98
100
|
}
|
|
99
101
|
// --- Clear messages (keep system prompt + provider/model/cwd) ---
|
|
100
|
-
function bestEffortStderr(line) {
|
|
101
|
-
try {
|
|
102
|
-
process.stderr.write(line);
|
|
103
|
-
} catch {
|
|
104
|
-
/* best-effort */
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
102
|
// Token/provider accounting a cleared transcript starts from; shared by the
|
|
109
103
|
// live session and the cold fork of its outgoing transcript.
|
|
110
104
|
function clearedTokenAccounting(now) {
|
|
@@ -112,6 +106,7 @@ function clearedTokenAccounting(now) {
|
|
|
112
106
|
providerState: undefined,
|
|
113
107
|
totalInputTokens: 0,
|
|
114
108
|
totalOutputTokens: 0,
|
|
109
|
+
totalToolCalls: 0,
|
|
115
110
|
reasoningUsage: null,
|
|
116
111
|
totalCachedReadTokens: 0,
|
|
117
112
|
totalCacheWriteTokens: 0,
|
|
@@ -133,11 +128,18 @@ async function compactBeforeClear(session, sessionId, clearOptions) {
|
|
|
133
128
|
let clearCompactError = null;
|
|
134
129
|
if (messages.length >= 3) {
|
|
135
130
|
try {
|
|
136
|
-
|
|
131
|
+
// The clear right after discards this compaction's display too, so it
|
|
132
|
+
// archives nothing (clear semantics are unchanged).
|
|
133
|
+
const compactResult = await runSessionCompaction(session, {
|
|
134
|
+
mode: 'manual',
|
|
135
|
+
force: true,
|
|
136
|
+
sessionId,
|
|
137
|
+
archive: false,
|
|
138
|
+
});
|
|
137
139
|
if (compactResult?.error) clearCompactError = new Error(compactResult.error);
|
|
138
140
|
} catch (err) {
|
|
139
141
|
clearCompactError = err;
|
|
140
|
-
|
|
142
|
+
writeStderrBestEffort(`[session] auto-clear pre-compact failed (sess=${sessionId}): ${err?.message || err}\n`);
|
|
141
143
|
}
|
|
142
144
|
messages = Array.isArray(session.messages) ? session.messages : [];
|
|
143
145
|
}
|
|
@@ -208,6 +210,11 @@ function forkOutgoingTranscript(session, messages, now) {
|
|
|
208
210
|
...clearedTokenAccounting(now),
|
|
209
211
|
};
|
|
210
212
|
delete fork.liveTurnMessages;
|
|
213
|
+
// The archive sidecar belongs to the source id; the fork has none.
|
|
214
|
+
if (fork.compaction?.archive) {
|
|
215
|
+
fork.compaction = { ...fork.compaction };
|
|
216
|
+
delete fork.compaction.archive;
|
|
217
|
+
}
|
|
211
218
|
setLiveSession(fork);
|
|
212
219
|
void saveSessionAsync(fork)
|
|
213
220
|
.then(() => {
|
|
@@ -219,10 +226,10 @@ function forkOutgoingTranscript(session, messages, now) {
|
|
|
219
226
|
evictLiveSession(forkId);
|
|
220
227
|
})
|
|
221
228
|
.catch((err) => {
|
|
222
|
-
|
|
229
|
+
writeStderrBestEffort(`[session] clear-fork save failed (sess=${forkId}): ${err?.message || err}\n`);
|
|
223
230
|
});
|
|
224
231
|
} catch (err) {
|
|
225
|
-
|
|
232
|
+
writeStderrBestEffort(`[session] clear-fork failed (sess=${session.id}): ${err?.message || err}\n`);
|
|
226
233
|
}
|
|
227
234
|
}
|
|
228
235
|
|
|
@@ -277,6 +284,9 @@ export async function clearSessionMessages(sessionId, options = {}) {
|
|
|
277
284
|
lastClearAfterMessageTokens: tokens.afterMessageTokens,
|
|
278
285
|
lastClearCompactError: clearCompactError?.message || null,
|
|
279
286
|
};
|
|
287
|
+
// A clear wipes the visible conversation: earlier compactions' archived
|
|
288
|
+
// display goes with it (nothing new is archived).
|
|
289
|
+
hideCompactionArchive(session);
|
|
280
290
|
if (summaryCarriedForward && tokens.postClearPolicy) {
|
|
281
291
|
recordContextUsageSnapshot(session, tokens.postClearPolicy, {
|
|
282
292
|
messages: keep,
|
|
@@ -32,11 +32,13 @@ import {
|
|
|
32
32
|
unusedModelEditToolName,
|
|
33
33
|
} from '../../../../shared/edit-tool-dialect.mjs';
|
|
34
34
|
import { resolveSessionContextMeta } from './context-meta.mjs';
|
|
35
|
+
import { normalizeContextTokens } from '../../../../shared/llm/default-context-window.mjs';
|
|
35
36
|
import { getAgentRuntimeSync, warnAgentRuntimeResolveFailureOnce } from './agent-runtime-singleton.mjs';
|
|
36
37
|
import { ensureCodexWireSessionId, mintSessionId } from './session-id.mjs';
|
|
37
38
|
import { providerCacheKey } from './provider-cache-key.mjs';
|
|
38
39
|
import { buildSessionRecord, normalizeDesktopSessionMetadata, sessionOriginFields } from './session-record.mjs';
|
|
39
40
|
import { refreshSessionBp3Environment } from './prompt-utils.mjs';
|
|
41
|
+
import { isWorktreeBound } from '../../../../shared/worktrees/contract.mjs';
|
|
40
42
|
|
|
41
43
|
// Owner liveness (attach-on-resume guard) and the durable turn-checkpoint
|
|
42
44
|
// recovery it gates; re-exported so prior importers of this module stay
|
|
@@ -153,6 +155,8 @@ function resolveSessionRoute(opts, presetObj, profile) {
|
|
|
153
155
|
const toolPreset = opts.tools || presetObj?.tools || (typeof opts.preset === 'string' ? opts.preset : null) || 'full';
|
|
154
156
|
const effort = Object.hasOwn(opts, 'effort') ? opts.effort || null : presetObj?.effort || null;
|
|
155
157
|
const fast = presetObj?.fast === true || opts.fast === true;
|
|
158
|
+
// Absent means on: an explicit request wins, else the preset's own flag.
|
|
159
|
+
const autoEffort = opts.autoEffort !== undefined ? opts.autoEffort !== false : presetObj?.autoEffort !== false;
|
|
156
160
|
let modelParameters = {};
|
|
157
161
|
if (opts.modelParameters && typeof opts.modelParameters === 'object') {
|
|
158
162
|
modelParameters = { ...opts.modelParameters };
|
|
@@ -160,6 +164,7 @@ function resolveSessionRoute(opts, presetObj, profile) {
|
|
|
160
164
|
modelParameters = { ...presetObj.modelParameters };
|
|
161
165
|
}
|
|
162
166
|
const contextPercent = normalizeContextPercent(opts.contextPercent);
|
|
167
|
+
const contextTokens = normalizeContextTokens(opts.contextTokens) || null;
|
|
163
168
|
if (!providerName) throw new Error('createSession: provider is required');
|
|
164
169
|
if (!modelName) throw new Error('createSession: model is required');
|
|
165
170
|
const provider = getProvider(providerName);
|
|
@@ -172,7 +177,19 @@ function resolveSessionRoute(opts, presetObj, profile) {
|
|
|
172
177
|
// materialization. Supplying that reservation here keeps the address
|
|
173
178
|
// stable across intake -> queued turn -> provider execution.
|
|
174
179
|
const id = requestedId || mintSessionId();
|
|
175
|
-
return {
|
|
180
|
+
return {
|
|
181
|
+
providerName,
|
|
182
|
+
modelName,
|
|
183
|
+
provider,
|
|
184
|
+
toolPreset,
|
|
185
|
+
effort,
|
|
186
|
+
fast,
|
|
187
|
+
autoEffort,
|
|
188
|
+
modelParameters,
|
|
189
|
+
contextPercent,
|
|
190
|
+
contextTokens,
|
|
191
|
+
id,
|
|
192
|
+
};
|
|
176
193
|
}
|
|
177
194
|
|
|
178
195
|
// Unified-shard policy — no broad role-specific schema filter. Keep
|
|
@@ -213,6 +230,7 @@ export function createSession(opts) {
|
|
|
213
230
|
const contextMeta = resolveSessionContextMeta(provider, modelName, {
|
|
214
231
|
selectedContextWindow: opts.selectedContextWindow,
|
|
215
232
|
contextPercent: route.contextPercent,
|
|
233
|
+
contextTokens: route.contextTokens,
|
|
216
234
|
});
|
|
217
235
|
const session = buildSessionRecord({
|
|
218
236
|
opts,
|
|
@@ -287,6 +305,10 @@ function applyRouteFields(session, route) {
|
|
|
287
305
|
if (route.provider) session.provider = route.provider;
|
|
288
306
|
if (route.model) session.model = route.model;
|
|
289
307
|
if (Object.hasOwn(route, 'fast')) session.fast = route.fast === true;
|
|
308
|
+
if (Object.hasOwn(route, 'autoEffort')) {
|
|
309
|
+
if (route.autoEffort === false) session.autoEffort = false;
|
|
310
|
+
else delete session.autoEffort;
|
|
311
|
+
}
|
|
290
312
|
if (Object.hasOwn(route, 'effort')) session.effort = route.effort || null;
|
|
291
313
|
ensureCodexWireSessionId(session);
|
|
292
314
|
if (Object.hasOwn(route, 'modelParameters')) {
|
|
@@ -294,6 +316,8 @@ function applyRouteFields(session, route) {
|
|
|
294
316
|
route.modelParameters && typeof route.modelParameters === 'object' ? { ...route.modelParameters } : {};
|
|
295
317
|
}
|
|
296
318
|
if (Object.hasOwn(route, 'contextPercent')) session.contextPercent = normalizeContextPercent(route.contextPercent);
|
|
319
|
+
if (Object.hasOwn(route, 'contextTokens'))
|
|
320
|
+
session.contextTokens = normalizeContextTokens(route.contextTokens) || null;
|
|
297
321
|
if (Object.hasOwn(route, 'selectedContextWindow')) {
|
|
298
322
|
session.selectedContextWindow = Number(route.selectedContextWindow) || null;
|
|
299
323
|
}
|
|
@@ -441,13 +465,18 @@ function _applyDesktopResumeScope(session, options) {
|
|
|
441
465
|
}
|
|
442
466
|
// The host's summary may predate a cwd change. It supplies the
|
|
443
467
|
// classification check, not permission to overwrite the session's
|
|
444
|
-
// newer execution Project. Task metadata always remains pathless.
|
|
468
|
+
// newer execution Project. Task metadata always remains pathless. A Lead
|
|
469
|
+
// in its worktree executes outside the Project: its registered Project
|
|
470
|
+
// stays the workspace record's projectPath, never the worktree cwd.
|
|
471
|
+
const workspace = session.workspace;
|
|
472
|
+
const executionProject =
|
|
473
|
+
isWorktreeBound(workspace) && typeof workspace.projectPath === 'string' ? workspace.projectPath : session.cwd;
|
|
445
474
|
session.desktopSession =
|
|
446
475
|
expectedDesktop.classification === 'project'
|
|
447
476
|
? normalizeDesktopSessionMetadata(
|
|
448
477
|
{
|
|
449
478
|
...expectedDesktop,
|
|
450
|
-
projectPath:
|
|
479
|
+
projectPath: executionProject || expectedDesktop.projectPath,
|
|
451
480
|
},
|
|
452
481
|
session.cwd
|
|
453
482
|
)
|
|
@@ -60,6 +60,33 @@ function buildShellEnvironmentContext(opts, ownerIsAgent, toolsForRouting) {
|
|
|
60
60
|
.join('\n');
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
/**
|
|
64
|
+
* Workspace-scoped prompt facts for an existing session re-rooted at `cwd`
|
|
65
|
+
* (a Lead workspace change or a worker following its Lead): the shell/git/
|
|
66
|
+
* listing environment and the instruction files of the new root, derived
|
|
67
|
+
* exactly as at creation. `undefined` means "keep what the session has": a
|
|
68
|
+
* tool-free role carries neither, a profile skipping instruction files keeps
|
|
69
|
+
* none.
|
|
70
|
+
* @returns {{ environmentContext: string|undefined, instructionFilesContext: string|undefined }}
|
|
71
|
+
*/
|
|
72
|
+
export function buildWorkspacePromptContext(session, cwd) {
|
|
73
|
+
const ownerIsAgent = session?.owner === 'agent';
|
|
74
|
+
const toolFreeRole =
|
|
75
|
+
ownerIsAgent && Array.isArray(session?.schemaAllowedTools) && session.schemaAllowedTools.length === 0;
|
|
76
|
+
if (toolFreeRole) return { environmentContext: undefined, instructionFilesContext: undefined };
|
|
77
|
+
const tools = [
|
|
78
|
+
...(Array.isArray(session?.tools) ? session.tools : []),
|
|
79
|
+
...(Array.isArray(session?.deferredToolCatalog) ? session.deferredToolCatalog : []),
|
|
80
|
+
];
|
|
81
|
+
return {
|
|
82
|
+
environmentContext: buildShellEnvironmentContext({ cwd }, ownerIsAgent, tools),
|
|
83
|
+
instructionFilesContext:
|
|
84
|
+
session?.skipInstructionFiles === true
|
|
85
|
+
? undefined
|
|
86
|
+
: loadInstructionFilesContext({ mode: configuredInstructionFilesMode(), cwd }),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
63
90
|
// BP1/BP2/BP3 rule blocks plus the volatile environment, composed into the
|
|
64
91
|
// four system blocks; environmentTailContext is the persisted env tail.
|
|
65
92
|
export function composeSessionSystem(opts, { profile, providerName, modelName, surface }) {
|
|
@@ -92,7 +92,18 @@ export function sessionOriginFields(opts, { profile, presetObj, providerCacheOpt
|
|
|
92
92
|
|
|
93
93
|
// The persisted session record.
|
|
94
94
|
export function buildSessionRecord({ opts, route, presetObj, surface, prompt, messages, contextMeta, origin }) {
|
|
95
|
-
const {
|
|
95
|
+
const {
|
|
96
|
+
providerName,
|
|
97
|
+
modelName,
|
|
98
|
+
toolPreset,
|
|
99
|
+
effort,
|
|
100
|
+
fast,
|
|
101
|
+
autoEffort,
|
|
102
|
+
modelParameters,
|
|
103
|
+
contextPercent,
|
|
104
|
+
contextTokens,
|
|
105
|
+
id,
|
|
106
|
+
} = route;
|
|
96
107
|
return {
|
|
97
108
|
id,
|
|
98
109
|
codexWireSessionId: providerName === 'openai-oauth' ? mintUuidV7() : null,
|
|
@@ -115,8 +126,11 @@ export function buildSessionRecord({ opts, route, presetObj, surface, prompt, me
|
|
|
115
126
|
presetName: presetObj?.name || null,
|
|
116
127
|
effort,
|
|
117
128
|
fast,
|
|
129
|
+
// Absent means Auto effort is on; only the off state is persisted.
|
|
130
|
+
...(autoEffort === false ? { autoEffort: false } : {}),
|
|
118
131
|
modelParameters,
|
|
119
132
|
contextPercent,
|
|
133
|
+
...(contextTokens ? { contextTokens } : {}),
|
|
120
134
|
selectedContextWindow: opts.selectedContextWindow || null,
|
|
121
135
|
agent: opts.agent,
|
|
122
136
|
owner: opts.owner || 'user',
|
|
@@ -144,6 +158,7 @@ export function buildSessionRecord({ opts, route, presetObj, surface, prompt, me
|
|
|
144
158
|
lastHeartbeatAt: null,
|
|
145
159
|
totalInputTokens: 0,
|
|
146
160
|
totalOutputTokens: 0,
|
|
161
|
+
totalToolCalls: 0,
|
|
147
162
|
// Refreshed on each completed ask() — surfaced by agent type=list for
|
|
148
163
|
// debugging + consumed by store.mjs's idle-sweep to reclaim stalled
|
|
149
164
|
// agent sessions past RUNNING_STALL_MS.
|
|
@@ -35,6 +35,7 @@ function standaloneStatusRouteInfo(session) {
|
|
|
35
35
|
modelDisplay: session.modelDisplay || session.displayName || session.model,
|
|
36
36
|
effort: session.effort || '',
|
|
37
37
|
fast: session.fast === true,
|
|
38
|
+
...(session.autoEffort === false ? { autoEffort: false } : {}),
|
|
38
39
|
modelParameters: session.modelParameters || {},
|
|
39
40
|
contextWindow: session.contextWindow || null,
|
|
40
41
|
rawContextWindow: session.rawContextWindow || session.contextWindow || null,
|
|
@@ -390,6 +390,7 @@ export function applyAskTerminalUsageTotals(session, result, options = {}) {
|
|
|
390
390
|
accumulateSessionUsage(session, {
|
|
391
391
|
deltaInput: result.usage.inputTokens || 0,
|
|
392
392
|
deltaOutput: result.usage.outputTokens || 0,
|
|
393
|
+
deltaToolCalls: result.toolCallsTotal || 0,
|
|
393
394
|
...reasoningUsage(result.usage),
|
|
394
395
|
deltaCachedRead: result.usage.cachedTokens || 0,
|
|
395
396
|
deltaCacheWrite: result.usage.cacheWriteTokens || 0,
|
|
@@ -465,6 +466,7 @@ function accumulateSessionUsage(session, delta) {
|
|
|
465
466
|
: uncachedInputTokensForProvider(session.provider, deltaInput, deltaCachedRead, deltaCacheWrite);
|
|
466
467
|
session.totalInputTokens = (session.totalInputTokens || 0) + (deltaInput || 0);
|
|
467
468
|
session.totalOutputTokens = (session.totalOutputTokens || 0) + (deltaOutput || 0);
|
|
469
|
+
session.totalToolCalls = (session.totalToolCalls || 0) + (delta.deltaToolCalls || 0);
|
|
468
470
|
session.tokensCumulative = (session.tokensCumulative || 0) + (deltaInput || 0) + (deltaOutput || 0);
|
|
469
471
|
session.totalCachedReadTokens = (session.totalCachedReadTokens || 0) + (deltaCachedRead || 0);
|
|
470
472
|
session.totalCacheWriteTokens = (session.totalCacheWriteTokens || 0) + (deltaCacheWrite || 0);
|
|
@@ -72,7 +72,6 @@ export {
|
|
|
72
72
|
// attach-on-resume guard) — resolved through the manager facade so the
|
|
73
73
|
// session-runtime turn API reaches it as mgr.publishSessionPresence.
|
|
74
74
|
export { publishSessionPresence, deleteSessionPresence } from './store.mjs';
|
|
75
|
-
export { isInternalRuntimeNotificationText as _isInternalRuntimeNotificationText } from './manager/prompt-utils.mjs';
|
|
76
75
|
|
|
77
76
|
// ── Usage-metrics surface — re-exported unchanged so loop.mjs / smoke scripts
|
|
78
77
|
// keep resolving these through the facade. ────────────────────────────────
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stable per-message identity: `meta.transcript.messageId`.
|
|
3
|
+
*
|
|
4
|
+
* Prompts and replies get theirs at creation (shared/transcript-metadata.mjs).
|
|
5
|
+
* Every other message — tool calls and results, injected rows, legacy
|
|
6
|
+
* transcripts — is stamped before a compaction runs or a stored session is
|
|
7
|
+
* resumed (stampMessageIds), and every compaction rewrite carries the id of
|
|
8
|
+
* the message it rewrites to its copy (spread copies keep `meta`;
|
|
9
|
+
* constructed copies use carryMessageId). A compaction's dropped messages
|
|
10
|
+
* are then exactly the ids its result no longer holds.
|
|
11
|
+
*
|
|
12
|
+
* A message whose `meta` is a string marker ('skill', 'hook': injected
|
|
13
|
+
* model context that is never displayed) cannot carry an id without changing
|
|
14
|
+
* what that marker means; it stays unstamped and has no display identity.
|
|
15
|
+
*
|
|
16
|
+
* Leaf module: no store, no config.
|
|
17
|
+
*/
|
|
18
|
+
import { createHash } from 'node:crypto';
|
|
19
|
+
|
|
20
|
+
/** The message's stable id, or ''. */
|
|
21
|
+
export function messageIdOf(message) {
|
|
22
|
+
const meta = message?.meta;
|
|
23
|
+
if (!meta || typeof meta !== 'object') return '';
|
|
24
|
+
const id = meta.transcript?.messageId;
|
|
25
|
+
return typeof id === 'string' ? id : '';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Whether `meta` can hold a transcript id (absent or a plain object). */
|
|
29
|
+
export function canCarryMessageId(message) {
|
|
30
|
+
if (!message || typeof message !== 'object') return false;
|
|
31
|
+
const meta = message.meta;
|
|
32
|
+
return meta === undefined || meta === null || (typeof meta === 'object' && !Array.isArray(meta));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function withMessageId(meta, messageId) {
|
|
36
|
+
const base = meta && typeof meta === 'object' ? meta : {};
|
|
37
|
+
const transcript = base.transcript && typeof base.transcript === 'object' ? base.transcript : {};
|
|
38
|
+
return { ...base, transcript: { ...transcript, messageId } };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// A deterministic seed: the same unstamped transcript gets the same ids on
|
|
42
|
+
// every stamping (a legacy session reopened twice before its stamps are
|
|
43
|
+
// saved keeps them; two compactions of one transcript agree). The content
|
|
44
|
+
// part is bounded — its length and edges, media by kind and size — so
|
|
45
|
+
// stamping never serializes whole images or documents. The position keeps
|
|
46
|
+
// equal messages apart.
|
|
47
|
+
const SEED_EDGE_CHARS = 512;
|
|
48
|
+
function boundedText(value) {
|
|
49
|
+
const text = String(value);
|
|
50
|
+
if (text.length <= SEED_EDGE_CHARS * 2) return text;
|
|
51
|
+
return `${text.slice(0, SEED_EDGE_CHARS)}\u0000${text.length}\u0000${text.slice(-SEED_EDGE_CHARS)}`;
|
|
52
|
+
}
|
|
53
|
+
function boundedContent(content) {
|
|
54
|
+
if (typeof content === 'string') return boundedText(content);
|
|
55
|
+
if (!Array.isArray(content)) return content == null ? '' : typeof content;
|
|
56
|
+
return content
|
|
57
|
+
.map((part) => {
|
|
58
|
+
if (!part || typeof part !== 'object') return String(part);
|
|
59
|
+
if (typeof part.text === 'string') return `t:${boundedText(part.text)}`;
|
|
60
|
+
const data = part.data ?? part.source?.data ?? part.image_url?.url ?? part.url ?? part.ref ?? '';
|
|
61
|
+
return `${part.type || 'part'}:${typeof data === 'string' ? data.length : 0}`;
|
|
62
|
+
})
|
|
63
|
+
.join('\u0001');
|
|
64
|
+
}
|
|
65
|
+
function seededMessageId(sessionId, index, message) {
|
|
66
|
+
const calls = Array.isArray(message.toolCalls) ? message.toolCalls : message.tool_calls;
|
|
67
|
+
const callIds = Array.isArray(calls) ? calls.map((call) => call?.id || '').join(',') : '';
|
|
68
|
+
const seed = [
|
|
69
|
+
sessionId,
|
|
70
|
+
index,
|
|
71
|
+
message.role,
|
|
72
|
+
message.toolCallId || message.tool_call_id || '',
|
|
73
|
+
callIds,
|
|
74
|
+
boundedContent(message.content),
|
|
75
|
+
].join('\u0002');
|
|
76
|
+
return `msg_${createHash('sha1').update(seed).digest('hex').slice(0, 32)}`;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Stamp a stable id on every message that can carry one and has none, in
|
|
80
|
+
* place. Returns how many were stamped (the caller persists them). */
|
|
81
|
+
export function stampMessageIds(messages, { sessionId = '' } = {}) {
|
|
82
|
+
if (!Array.isArray(messages)) return 0;
|
|
83
|
+
let stamped = 0;
|
|
84
|
+
const seen = new Set();
|
|
85
|
+
messages.forEach((message, index) => {
|
|
86
|
+
const existing = messageIdOf(message);
|
|
87
|
+
if (existing) {
|
|
88
|
+
seen.add(existing);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (!canCarryMessageId(message)) return;
|
|
92
|
+
let id = seededMessageId(String(sessionId || ''), index, message);
|
|
93
|
+
// Never two messages with one id within a transcript.
|
|
94
|
+
for (let salt = 1; seen.has(id); salt += 1) id = seededMessageId(`${sessionId}#${salt}`, index, message);
|
|
95
|
+
seen.add(id);
|
|
96
|
+
message.meta = withMessageId(message.meta, id);
|
|
97
|
+
stamped += 1;
|
|
98
|
+
});
|
|
99
|
+
return stamped;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** JSON.stringify replacer that leaves stable ids out: hashes and archives
|
|
103
|
+
* the compactor derives from message JSON describe the conversation, not
|
|
104
|
+
* its display bookkeeping (a meta that only held the id is left out too). */
|
|
105
|
+
export function withoutMessageIdsReplacer(key, value) {
|
|
106
|
+
if (key !== 'meta' || !value || typeof value !== 'object' || typeof value.transcript?.messageId !== 'string') {
|
|
107
|
+
return value;
|
|
108
|
+
}
|
|
109
|
+
const { messageId: _id, ...transcript } = value.transcript;
|
|
110
|
+
const meta = { ...value };
|
|
111
|
+
if (Object.keys(transcript).length) meta.transcript = transcript;
|
|
112
|
+
else delete meta.transcript;
|
|
113
|
+
return Object.keys(meta).length ? meta : undefined;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** `copy` carrying the stable id of `original` (a compaction rewrite that
|
|
117
|
+
* builds a new message instead of spreading the original). Only the id
|
|
118
|
+
* travels; the copy's own meta is kept. */
|
|
119
|
+
export function carryMessageId(copy, original) {
|
|
120
|
+
const id = messageIdOf(original);
|
|
121
|
+
if (!id || !canCarryMessageId(copy) || messageIdOf(copy) === id) return copy;
|
|
122
|
+
return { ...copy, meta: withMessageId(copy.meta, id) };
|
|
123
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Tests that compare a transcript before and after a compaction: compaction
|
|
2
|
+
// stamps stable ids (message-ids.mjs) on messages that had none, which is
|
|
3
|
+
// bookkeeping, not a change of the conversation.
|
|
4
|
+
|
|
5
|
+
/** `messages` without the stable ids stamped on them (and without the meta a
|
|
6
|
+
* stamp alone created). */
|
|
7
|
+
export function withoutStampedIds(messages) {
|
|
8
|
+
return messages.map((message) => {
|
|
9
|
+
const transcript = message?.meta?.transcript;
|
|
10
|
+
if (!transcript?.messageId) return message;
|
|
11
|
+
const { messageId: _id, ...rest } = transcript;
|
|
12
|
+
const meta = { ...message.meta };
|
|
13
|
+
if (Object.keys(rest).length) meta.transcript = rest;
|
|
14
|
+
else delete meta.transcript;
|
|
15
|
+
const out = { ...message };
|
|
16
|
+
if (Object.keys(meta).length) out.meta = meta;
|
|
17
|
+
else delete out.meta;
|
|
18
|
+
return out;
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Whether every message that can carry an id has one. */
|
|
23
|
+
export function everyMessageStamped(messages) {
|
|
24
|
+
return messages.every(
|
|
25
|
+
(message) =>
|
|
26
|
+
(message?.meta !== undefined && (typeof message.meta !== 'object' || message.meta === null)) ||
|
|
27
|
+
typeof message?.meta?.transcript?.messageId === 'string'
|
|
28
|
+
);
|
|
29
|
+
}
|
|
@@ -29,20 +29,14 @@ import { traceAgentCompact, messagePrefixHash } from '../agent-trace.mjs';
|
|
|
29
29
|
import { invalidateProviderRequestToolsScope } from '../runtime-core/provider-request-tools.mjs';
|
|
30
30
|
import { bumpUsageMetricsEpoch } from './manager/usage-metrics.mjs';
|
|
31
31
|
import { resetReadStateAfterCompaction } from './read-dedup.mjs';
|
|
32
|
+
import { scheduleCompactionArchive, stampCompactionMessageIds } from './compaction-archive-capture.mjs';
|
|
33
|
+
import { writeStderrBestEffort } from '../../../shared/best-effort-stderr.mjs';
|
|
32
34
|
import {
|
|
33
35
|
acknowledgePendingGoalReminder,
|
|
34
36
|
markPendingGoalReminder,
|
|
35
37
|
snapshotPendingGoalReminder,
|
|
36
38
|
} from '../runtime-core/goal-reminder.mjs';
|
|
37
39
|
|
|
38
|
-
function writeStderr(line) {
|
|
39
|
-
try {
|
|
40
|
-
process.stderr.write(line);
|
|
41
|
-
} catch {
|
|
42
|
-
/* best-effort */
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
40
|
async function setStage(opts, stage) {
|
|
47
41
|
try {
|
|
48
42
|
await opts.onStageChange?.(stage);
|
|
@@ -126,20 +120,23 @@ function preSendCompactDecision(state, compactPolicy) {
|
|
|
126
120
|
activeTurn: true,
|
|
127
121
|
}).reducesTokens;
|
|
128
122
|
}
|
|
123
|
+
let compactTrigger = 'auto';
|
|
124
|
+
if (reactivePending) compactTrigger = 'reactive';
|
|
125
|
+
else if (cacheExpired) compactTrigger = 'cache_expired';
|
|
129
126
|
return {
|
|
130
127
|
messageTokensEst,
|
|
131
128
|
pressureTokens,
|
|
132
129
|
shouldCompact,
|
|
133
130
|
requireReduction,
|
|
134
|
-
compactTrigger
|
|
131
|
+
compactTrigger,
|
|
135
132
|
compactBudgetTokens,
|
|
136
133
|
};
|
|
137
134
|
}
|
|
138
135
|
|
|
139
|
-
// Gauge sync
|
|
140
|
-
//
|
|
141
|
-
//
|
|
142
|
-
//
|
|
136
|
+
// Gauge sync. The host refreshes its context readout only on provider usage
|
|
137
|
+
// deltas and turn end, so a tool batch that pushed the transcript over the
|
|
138
|
+
// trigger would compact while the screen still showed headroom. Publish the
|
|
139
|
+
// decision's OWN numerator here —
|
|
143
140
|
// before compaction mutates the transcript — so the readout and the trigger
|
|
144
141
|
// describe one moment.
|
|
145
142
|
function publishContextPressure(opts, sessionId, compactPolicy, { pressureTokens, shouldCompact }) {
|
|
@@ -158,15 +155,14 @@ function publishContextPressure(opts, sessionId, compactPolicy, { pressureTokens
|
|
|
158
155
|
}
|
|
159
156
|
|
|
160
157
|
// Pre/PostCompact bridge to the standard hook bus: a session-property hook
|
|
161
|
-
// (manager/loop have no bus access)
|
|
162
|
-
// 'auto'
|
|
163
|
-
// loop.
|
|
158
|
+
// (manager/loop have no bus access); a pre-send pass is always trigger
|
|
159
|
+
// 'auto'. Best-effort — a hook must never break compaction or the loop.
|
|
164
160
|
async function runCompactHook(ctx, name) {
|
|
165
161
|
const { opts, sessionRef, sessionId, cwd } = ctx.state;
|
|
166
162
|
const hook = typeof opts[name] === 'function' ? opts[name] : sessionRef?.[name];
|
|
167
163
|
if (typeof hook !== 'function') return;
|
|
168
164
|
try {
|
|
169
|
-
await hook({ sessionId, cwd, trigger:
|
|
165
|
+
await hook({ sessionId, cwd, trigger: 'auto' });
|
|
170
166
|
} catch {
|
|
171
167
|
/* best-effort */
|
|
172
168
|
}
|
|
@@ -342,7 +338,7 @@ function throwCompactFailure(ctx, run, compactErr) {
|
|
|
342
338
|
const { sessionRef, sessionId, signal, model } = state;
|
|
343
339
|
acknowledgeGoalReminder(sessionRef, run);
|
|
344
340
|
if (isCompactAbort(signal, compactErr)) {
|
|
345
|
-
|
|
341
|
+
writeStderrBestEffort(
|
|
346
342
|
`[loop] pre-send compact cancelled (sess=${sessionId || 'unknown'}): ${compactErr?.message || compactErr}\n`
|
|
347
343
|
);
|
|
348
344
|
throw compactErr;
|
|
@@ -381,8 +377,16 @@ function throwCompactFailure(ctx, run, compactErr) {
|
|
|
381
377
|
function adoptCompactedTranscript(ctx, run) {
|
|
382
378
|
const { state } = ctx;
|
|
383
379
|
const { messages, sessionRef, sessionId, opts } = state;
|
|
380
|
+
const replaced = messages.slice();
|
|
384
381
|
messages.length = 0;
|
|
385
382
|
messages.push(...run.compacted);
|
|
383
|
+
// Display-only archive of the dropped conversation; the projection and the
|
|
384
|
+
// write run off this synchronous adoption.
|
|
385
|
+
const archived = sessionRef
|
|
386
|
+
? scheduleCompactionArchive({ session: sessionRef, sessionId, before: replaced, after: messages })
|
|
387
|
+
: null;
|
|
388
|
+
ctx.droppedMessages = archived?.dropped ?? 0;
|
|
389
|
+
ctx.droppedIdentities = archived?.identities ?? null;
|
|
386
390
|
acknowledgeGoalReminder(sessionRef, run);
|
|
387
391
|
resetReadStateAfterCompaction(sessionId);
|
|
388
392
|
// Cross-turn receipts reference tool results that compaction just removed
|
|
@@ -404,9 +408,10 @@ function adoptCompactedTranscript(ctx, run) {
|
|
|
404
408
|
// providerState so the next send starts a fresh chain.
|
|
405
409
|
ctx.providerState = undefined;
|
|
406
410
|
ctx.providerStateCleared = true;
|
|
407
|
-
// Compaction
|
|
408
|
-
//
|
|
409
|
-
//
|
|
411
|
+
// Compaction starts a new loop epoch: the iteration counter restarts at 0
|
|
412
|
+
// so iteration indices (traces, usage metrics, cross-turn dedup windows)
|
|
413
|
+
// count from the compacted transcript. The counter bounds nothing — the
|
|
414
|
+
// loop has no iteration cap.
|
|
410
415
|
ctx.iterations = 0;
|
|
411
416
|
// New loop epoch so persistIterationMetrics idempotency keys do not
|
|
412
417
|
// collide when iteration indices restart at 1 (incl. iter 1 → iter 1).
|
|
@@ -451,6 +456,8 @@ function reportCompactOutcome(ctx, run) {
|
|
|
451
456
|
status: changed ? 'compacted' : 'no_change',
|
|
452
457
|
afterTokens,
|
|
453
458
|
changed,
|
|
459
|
+
droppedMessages: ctx.droppedMessages || 0,
|
|
460
|
+
droppedIdentities: ctx.droppedIdentities || null,
|
|
454
461
|
freshContext: freshContextResult?.freshContext === true,
|
|
455
462
|
handoffSource: freshContextResult?.handoffSource || null,
|
|
456
463
|
durationMs,
|
|
@@ -460,6 +467,10 @@ function reportCompactOutcome(ctx, run) {
|
|
|
460
467
|
async function compactBeforeSend(ctx) {
|
|
461
468
|
const { state, decision } = ctx;
|
|
462
469
|
const { messages, sessionRef, sessionId, opts } = state;
|
|
470
|
+
// Every message enters the compaction with a stable id (legacy ones are
|
|
471
|
+
// stamped now; the turn's saves persist them): the result's rewrites carry
|
|
472
|
+
// it, so what was dropped is exactly the ids the result no longer holds.
|
|
473
|
+
stampCompactionMessageIds(messages, sessionId || sessionRef?.id || '');
|
|
463
474
|
// Snapshot BEFORE mutating the live array below, so compact_meta reports
|
|
464
475
|
// real savings and the true input prefix rather than the replacement
|
|
465
476
|
// transcript.
|
|
@@ -489,7 +500,7 @@ async function compactBeforeSend(ctx) {
|
|
|
489
500
|
await compactTranscript(ctx, run);
|
|
490
501
|
} catch (freshErr) {
|
|
491
502
|
run.freshContextError = freshErr;
|
|
492
|
-
|
|
503
|
+
writeStderrBestEffort(
|
|
493
504
|
`[loop] fresh-context compact failed (sess=${sessionId || 'unknown'}): ${freshErr?.message || freshErr}\n`
|
|
494
505
|
);
|
|
495
506
|
throw freshErr;
|
|
@@ -30,6 +30,7 @@ import { _saveAsyncQueued, _saveWorkerPending } from './save-worker.mjs';
|
|
|
30
30
|
import { STORED_SESSION_UNREADABLE, _ensureLifecycleFields, _storedSessionFromFile } from './serialize.mjs';
|
|
31
31
|
import { _savePending } from './pending-saves.mjs';
|
|
32
32
|
import { isOrdinarySession } from '../store-summary-visibility.mjs';
|
|
33
|
+
import { closeSessionCatalogDb } from '../catalog-db/index.mjs';
|
|
33
34
|
|
|
34
35
|
// Disk mtime of the summary index when the in-memory cache was last refreshed
|
|
35
36
|
// from it — the cross-process staleness detector.
|
|
@@ -145,8 +146,9 @@ function scheduleSessionSummaryIndexRebuild() {
|
|
|
145
146
|
|
|
146
147
|
/**
|
|
147
148
|
* Resolves once no summary-index writer of this process is running: the
|
|
148
|
-
* background rebuild worker a cold listing (or sweep) spawned has exited
|
|
149
|
-
* every queued index mutation has landed
|
|
149
|
+
* background rebuild worker a cold listing (or sweep) spawned has exited,
|
|
150
|
+
* every queued index mutation has landed and the session catalog DB is
|
|
151
|
+
* closed. Both write the index, its lock and
|
|
150
152
|
* temp files into the data dir after the listing/sweep/save that caused them
|
|
151
153
|
* has returned, so an owner that removes or switches the data dir awaits this
|
|
152
154
|
* first.
|
|
@@ -159,6 +161,8 @@ export async function settleSessionSummaryIndex() {
|
|
|
159
161
|
await new Promise((resolve) => worker.once('exit', resolve));
|
|
160
162
|
}
|
|
161
163
|
await settleSummaryIndexWrites();
|
|
164
|
+
// The daemon's session catalog DB holds its file, WAL and lock open.
|
|
165
|
+
await closeSessionCatalogDb();
|
|
162
166
|
}
|
|
163
167
|
|
|
164
168
|
export function listStoredSessionSummaries(options = {}) {
|
|
@@ -31,6 +31,7 @@ import { _uncacheSessionSummary, _queueSessionSummaryRemoval } from './summary-c
|
|
|
31
31
|
import { _savePending, _clearDebounce, _releasePendingSlot } from './pending-saves.mjs';
|
|
32
32
|
import { _runtimeLivenessVeto, _heartbeatLivenessVeto, _deleteHeartbeatUnlessNewer } from './liveness-veto.mjs';
|
|
33
33
|
import { _runSessionPurgeHooks } from './session-observers.mjs';
|
|
34
|
+
import { deleteCompactionArchive } from '../compaction-archive.mjs';
|
|
34
35
|
|
|
35
36
|
/** Strictly enumerate child-agent session files linked to one visible parent.
|
|
36
37
|
* Used only by explicit parent deletion; ordinary close/context switches keep
|
|
@@ -130,6 +131,8 @@ export function deleteSession(id, options = {}) {
|
|
|
130
131
|
// Preserve a sidecar published strictly after the sweep's scan snapshot.
|
|
131
132
|
_deleteHeartbeatUnlessNewer(id, options);
|
|
132
133
|
deleteSessionPresence(id);
|
|
134
|
+
// The display-only compaction archive has no meaning without its session.
|
|
135
|
+
deleteCompactionArchive(getStoreDir(), id);
|
|
133
136
|
_clearLiveSession(id);
|
|
134
137
|
// The file is gone: every marker of the retired incarnation goes with it
|
|
135
138
|
// (save error + failed-snapshot evidence, split-brain drop flag, lifecycle
|