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
|
@@ -7,11 +7,14 @@
|
|
|
7
7
|
* Kept apart from the cache/fingerprint policy in store-summary-reader.mjs
|
|
8
8
|
* because this runs exactly once per distinct content and is the only part
|
|
9
9
|
* that lazily enters the heavier reconnect-recovery boundary (dynamic imports
|
|
10
|
-
*
|
|
10
|
+
* keep the cold summary path leaf-only).
|
|
11
11
|
*/
|
|
12
12
|
import { sessionContextMeasurement, contextMeasurementStats } from '../../../shared/context-measurement.mjs';
|
|
13
13
|
import { nextProjectionStamp } from './store-transcript-cache.mjs';
|
|
14
|
+
import { join } from 'node:path';
|
|
14
15
|
import { cleanValue, desktopSession, positiveNumber } from './store-summary-fields.mjs';
|
|
16
|
+
import { compactionArchiveRange, readCompactionArchivePage } from './compaction-archive.mjs';
|
|
17
|
+
import { dataDir } from './store-summary-locations.mjs';
|
|
15
18
|
|
|
16
19
|
/** The parse/recovery/projection body of a stored transcript read. Runs once
|
|
17
20
|
* per distinct content; its result is shared read-only through the cache. */
|
|
@@ -90,17 +93,31 @@ export async function projectStoredTranscript(sessionId, doc, options) {
|
|
|
90
93
|
// tail is identical either way.
|
|
91
94
|
const itemLimit = Number.isFinite(options.itemLimit) ? options.itemLimit : Number.POSITIVE_INFINITY;
|
|
92
95
|
const restored = restoreTranscriptItems(messages, { sessionId, itemLimit: itemLimit + 1 });
|
|
93
|
-
|
|
96
|
+
let transcriptHasOlder = restored.length > itemLimit;
|
|
97
|
+
let items = transcriptHasOlder ? restored.slice(-itemLimit) : restored;
|
|
98
|
+
// A paged window continues past the first stored message into the
|
|
99
|
+
// display-only compaction archive (newest segment first). A legacy whole
|
|
100
|
+
// read never receives it.
|
|
101
|
+
const archiveRange = Number.isFinite(itemLimit) && !transcriptHasOlder ? compactionArchiveRange(session) : null;
|
|
102
|
+
if (archiveRange) {
|
|
103
|
+
const archived = await readCompactionArchivePage(join(dataDir(), 'sessions'), sessionId, {
|
|
104
|
+
...archiveRange,
|
|
105
|
+
limit: itemLimit - restored.length,
|
|
106
|
+
});
|
|
107
|
+
if (archived.items.length) items = [...archived.items, ...restored];
|
|
108
|
+
transcriptHasOlder = archived.hasOlder;
|
|
109
|
+
}
|
|
94
110
|
return {
|
|
95
111
|
sessionId,
|
|
96
112
|
projectionStamp: nextProjectionStamp(),
|
|
97
113
|
...(options.includeMessages ? { messages } : {}),
|
|
98
|
-
items
|
|
114
|
+
items,
|
|
99
115
|
transcriptHasOlder,
|
|
100
116
|
provider: session.provider || '',
|
|
101
117
|
model: session.model || '',
|
|
102
118
|
effort: session.effort || '',
|
|
103
119
|
fast: session.fast === true,
|
|
120
|
+
...(session.autoEffort === false ? { autoEffort: false } : {}),
|
|
104
121
|
modelParameters: session.modelParameters || {},
|
|
105
122
|
cwd: session.cwd || '',
|
|
106
123
|
desktopSession: desktopSession(session.desktopSession, session.cwd),
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
import { isActualUserInstructionMessage, isInjectedSkillBodyMessage, isSummaryMessage } from './compact/messages.mjs';
|
|
17
17
|
import { ACTIVE_TURN_CONTINUATION_ANCHOR, ACTIVE_TURN_CONTINUATION_SOURCE } from './compact/continuation.mjs';
|
|
18
18
|
import { parseTaskNotification } from '../../../shared/task-notification-envelope.mjs';
|
|
19
|
+
import { isImportedMessage } from './imported-message.mjs';
|
|
19
20
|
|
|
20
21
|
export const SYNTHETIC_USER_ENVELOPE_TAG = 'mixdog-runtime';
|
|
21
22
|
|
|
@@ -62,7 +63,8 @@ function isAlreadyEnveloped(text) {
|
|
|
62
63
|
|
|
63
64
|
// null => a real user instruction (or nothing to wrap); otherwise the kind.
|
|
64
65
|
export function classifySyntheticUserMessage(message) {
|
|
65
|
-
|
|
66
|
+
// Imported prose stays the user's own (unwrapped) voice.
|
|
67
|
+
if (message?.role !== 'user' || isImportedMessage(message)) return null;
|
|
66
68
|
const text = messageText(message);
|
|
67
69
|
if (!text.trim()) return null;
|
|
68
70
|
if (isAlreadyEnveloped(text)) return null;
|
|
@@ -92,7 +92,7 @@ function crossTurnStub(batch, call, ctSig) {
|
|
|
92
92
|
// (which spans ONE assistant turn): when the model re-issues an IDENTICAL
|
|
93
93
|
// normalized call that has already failed repeatFailLimit times in a row
|
|
94
94
|
// across iterations, stop re-executing — the result will not change, and
|
|
95
|
-
// each retry burns a full LLM round-trip
|
|
95
|
+
// each retry burns a full LLM round-trip with no iteration cap to end it. The
|
|
96
96
|
// call stays unresolved; the guard only skips re-execution.
|
|
97
97
|
function repeatFailureSkip(batch, call, sigs) {
|
|
98
98
|
const { sessionRef, repeatFailLimit } = batch;
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { contextMeasurementStats } from '../../../../shared/context-measurement.mjs';
|
|
8
8
|
import { toolResultText } from './tool-result-text.mjs';
|
|
9
|
+
import { restoredUserImageRefs, restoredUserText } from './user-text.mjs';
|
|
9
10
|
import {
|
|
10
11
|
completionCardFromExecution,
|
|
11
12
|
parseModelVisibleCompletionWrapper,
|
|
@@ -37,6 +38,7 @@ import {
|
|
|
37
38
|
} from '../../../../shared/tool-execution-contract.mjs';
|
|
38
39
|
import { toolResultTerminalStatus } from '../../../../shared/tool-status.mjs';
|
|
39
40
|
import { transcriptRouteMetadataFields } from '../../../../shared/transcript-metadata.mjs';
|
|
41
|
+
import { isImportedMessage } from '../imported-message.mjs';
|
|
40
42
|
|
|
41
43
|
function restoredTranscriptMetadata(message) {
|
|
42
44
|
const value = message?.meta?.transcript;
|
|
@@ -48,12 +50,23 @@ function restoredTranscriptMetadata(message) {
|
|
|
48
50
|
if (completionValue && completionStatus && Number.isFinite(completionElapsedMs)) {
|
|
49
51
|
completion = { status: completionStatus, elapsedMs: Math.max(0, completionElapsedMs) };
|
|
50
52
|
if (typeof completionValue.verb === 'string' && completionValue.verb) completion.verb = completionValue.verb;
|
|
53
|
+
if (typeof completionValue.checkpointId === 'string' && completionValue.checkpointId) {
|
|
54
|
+
completion.checkpointId = completionValue.checkpointId;
|
|
55
|
+
}
|
|
51
56
|
}
|
|
52
57
|
return {
|
|
58
|
+
// The stable message id lets a live view map a compaction's dropped
|
|
59
|
+
// messages back to these rows.
|
|
60
|
+
...(typeof value.messageId === 'string' && value.messageId ? { messageId: value.messageId } : {}),
|
|
53
61
|
...(Number.isFinite(Number(value.at)) ? { at: Number(value.at) } : {}),
|
|
54
62
|
...transcriptRouteMetadataFields(value),
|
|
55
63
|
...(typeof value.sender === 'string' && value.sender ? { sender: value.sender } : {}),
|
|
56
64
|
...(typeof value.device === 'string' && value.device ? { device: value.device } : {}),
|
|
65
|
+
...(typeof value.checkpointId === 'string' && value.checkpointId ? { checkpointId: value.checkpointId } : {}),
|
|
66
|
+
// Skills this user turn explicitly loaded (header selection or `$name`).
|
|
67
|
+
...(Array.isArray(value.appliedSkills) && value.appliedSkills.length
|
|
68
|
+
? { appliedSkills: value.appliedSkills.filter((name) => typeof name === 'string' && name) }
|
|
69
|
+
: {}),
|
|
57
70
|
...(completion ? { completion } : {}),
|
|
58
71
|
};
|
|
59
72
|
}
|
|
@@ -70,15 +83,16 @@ function restoredAssistantTranscriptItems(message, nextId) {
|
|
|
70
83
|
...completion,
|
|
71
84
|
...(completion.status === 'done' ? { finalAssistantId: items[0].id } : {}),
|
|
72
85
|
...(metadata.at ? { at: metadata.at } : {}),
|
|
86
|
+
...(metadata.messageId ? { messageId: metadata.messageId } : {}),
|
|
73
87
|
});
|
|
74
88
|
}
|
|
75
89
|
return items;
|
|
76
90
|
}
|
|
77
91
|
|
|
78
92
|
// Restored tool cards: stored assistant messages keep their (compacted)
|
|
79
|
-
// tool_calls and the follow-up role:'tool' results
|
|
80
|
-
//
|
|
81
|
-
//
|
|
93
|
+
// tool_calls and the follow-up role:'tool' results. Rebuild one transcript
|
|
94
|
+
// tool item per call and attach its result by tool_call_id, so a reopened
|
|
95
|
+
// session keeps its tool markers.
|
|
82
96
|
function restoredMessageToolCalls(message) {
|
|
83
97
|
if (Array.isArray(message?.tool_calls)) return message.tool_calls;
|
|
84
98
|
if (Array.isArray(message?.toolCalls)) return message.toolCalls;
|
|
@@ -112,7 +126,12 @@ function restoredToolCallItems(message, nextId, pendingByCallId) {
|
|
|
112
126
|
...(Number.isFinite(at) ? { at, startedAt: at, completedAt: at } : {}),
|
|
113
127
|
};
|
|
114
128
|
const callId = typeof call?.id === 'string' ? call.id : '';
|
|
115
|
-
|
|
129
|
+
// The call id ties the card to its call and result messages (a live view
|
|
130
|
+
// greys it when a compaction drops them).
|
|
131
|
+
if (callId) {
|
|
132
|
+
item.callId = callId;
|
|
133
|
+
pendingByCallId.set(callId, item);
|
|
134
|
+
}
|
|
116
135
|
items.push(item);
|
|
117
136
|
}
|
|
118
137
|
return items;
|
|
@@ -203,6 +222,9 @@ function buildRestoredAggregateItem(members) {
|
|
|
203
222
|
...(loadingTargets.length > 0 ? { loadingTargets } : {}),
|
|
204
223
|
},
|
|
205
224
|
aggregate: true,
|
|
225
|
+
...(members.some(({ item }) => item.callId)
|
|
226
|
+
? { callIds: members.map(({ item }) => item.callId).filter(Boolean) }
|
|
227
|
+
: {}),
|
|
206
228
|
categories: Object.fromEntries(header.categories),
|
|
207
229
|
doneCategories: aggregateDoneCategories(calls),
|
|
208
230
|
completedCount: calls.length,
|
|
@@ -219,8 +241,8 @@ function buildRestoredAggregateItem(members) {
|
|
|
219
241
|
|
|
220
242
|
// Restored transcripts must mirror the live turn's category merging: the live
|
|
221
243
|
// session runtime (turn.mjs) collapses consecutive same-bucket tool calls into one
|
|
222
|
-
// aggregate card,
|
|
223
|
-
//
|
|
244
|
+
// aggregate card, so a reopened session must not show them un-merged. Walk the
|
|
245
|
+
// restored items and merge adjacent
|
|
224
246
|
// tool cards whose aggregateBucketForCategory matches; any non-tool item
|
|
225
247
|
// (user/assistant/turndone) is a block boundary, same as the live seal rule.
|
|
226
248
|
// Runs of 1 keep the plain per-call card (its argument summary stays visible).
|
|
@@ -279,9 +301,11 @@ function restoredMessageItemUpperBound(message) {
|
|
|
279
301
|
function restoredNotificationToolItem(parsed, text, message, nextId, errorLabel) {
|
|
280
302
|
const label = parsed.label || 'notification';
|
|
281
303
|
const at = Number(message?.meta?.transcript?.at);
|
|
304
|
+
const messageId = message?.meta?.transcript?.messageId;
|
|
282
305
|
return {
|
|
283
306
|
kind: 'tool',
|
|
284
307
|
id: nextId(),
|
|
308
|
+
...(typeof messageId === 'string' && messageId ? { messageId } : {}),
|
|
285
309
|
name: parsed.name || 'agent',
|
|
286
310
|
args: parsed.args || {
|
|
287
311
|
type: label,
|
|
@@ -303,7 +327,12 @@ function restoredUserTranscriptItems(message, nextId) {
|
|
|
303
327
|
// skill bodies (meta:'skill'), hook/system reminders, and tag-wrapped context
|
|
304
328
|
// blocks must not restore as user bubbles in any client.
|
|
305
329
|
if (message?.meta === 'skill' || message?.meta === 'hook') return [];
|
|
306
|
-
|
|
330
|
+
// Imported prose renders verbatim: never a control row, card or display rewrite.
|
|
331
|
+
if (isImportedMessage(message)) {
|
|
332
|
+
const text = (typeof message.content === 'string' ? message.content : toolResultText(message.content)).trim();
|
|
333
|
+
return text ? [{ kind: 'user', id: nextId(), text, ...restoredTranscriptMetadata(message) }] : [];
|
|
334
|
+
}
|
|
335
|
+
const text = restoredUserText(message?.content).trim();
|
|
307
336
|
// Persisted async-completion wrappers ("Async shell task ... finished. Result:
|
|
308
337
|
// > ...") are the only durable record of a background completion — the live
|
|
309
338
|
// Response card is an event-time push that does not survive a transcript
|
|
@@ -329,11 +358,21 @@ function restoredUserTranscriptItems(message, nextId) {
|
|
|
329
358
|
// step, but render it like a live cancel tail (◈ Cancelled) instead of a
|
|
330
359
|
// raw user bubble with bracketed internals.
|
|
331
360
|
if (isTranscriptCancelledStatusText(text)) {
|
|
332
|
-
|
|
361
|
+
const { messageId } = restoredTranscriptMetadata(message);
|
|
362
|
+
return [{ kind: 'turndone', id: nextId(), status: 'cancelled', elapsedMs: 0, ...(messageId ? { messageId } : {}) }];
|
|
333
363
|
}
|
|
334
364
|
const synthetic = parseSyntheticAgentMessage(text);
|
|
335
365
|
if (!synthetic) {
|
|
336
|
-
|
|
366
|
+
const imageRefs = restoredUserImageRefs(message?.content);
|
|
367
|
+
return [
|
|
368
|
+
{
|
|
369
|
+
kind: 'user',
|
|
370
|
+
id: nextId(),
|
|
371
|
+
text,
|
|
372
|
+
...restoredTranscriptMetadata(message),
|
|
373
|
+
...(imageRefs.length ? { imageRefs } : {}),
|
|
374
|
+
},
|
|
375
|
+
];
|
|
337
376
|
}
|
|
338
377
|
return [restoredNotificationToolItem(synthetic, text, message, nextId, /^(failed|error|killed|cancelled)$/i)];
|
|
339
378
|
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The text a restored user bubble shows for a stored prompt, matching what the
|
|
3
|
+
* live bubble showed for it:
|
|
4
|
+
* - An image part is drawn by the `[Image: …]` metadata line the composer put
|
|
5
|
+
* before it; the part itself adds no raw `[image: image/png]` marker (a bare
|
|
6
|
+
* one gets a metadata line of its own, which renders as an image chip).
|
|
7
|
+
* - A desktop `<visualize_feedback>` block (the agent-facing pin/choice
|
|
8
|
+
* record) is shown as the lines the live bubble showed: `📌 N · label —
|
|
9
|
+
* note` per pin, one `☑ group: label, …` line for the picks and one
|
|
10
|
+
* `🎚 id: value (was old), …` line for tweaks (drawn with an icon). Intake
|
|
11
|
+
* moves a long block into the attachment store; it is read back from there.
|
|
12
|
+
*/
|
|
13
|
+
import { isAttachmentReference, readAttachmentTextWithin } from '../../../../attachments/store.mjs';
|
|
14
|
+
import { toolResultText } from './tool-result-text.mjs';
|
|
15
|
+
|
|
16
|
+
const IMAGE_METADATA_LINE = /\[Image(?::| source:) [^\]\r\n]+\]\s*$/;
|
|
17
|
+
const FEEDBACK_OPEN = '<visualize_feedback>';
|
|
18
|
+
const FEEDBACK_BLOCK = /<visualize_feedback>\n([\s\S]*?)\n?<\/visualize_feedback>/g;
|
|
19
|
+
// Feedback blocks are bounded (20 pins, trimmed HTML); a larger blob is a long
|
|
20
|
+
// prompt or paste, which restores as before without being read. The cap holds
|
|
21
|
+
// on the blob itself: the reference's claimed sizeBytes is not trusted.
|
|
22
|
+
const FEEDBACK_MAX_BYTES = 128 * 1024;
|
|
23
|
+
const QUOTED = '("(?:[^"\\\\]|\\\\.)*")';
|
|
24
|
+
const CHOICE_LINE = new RegExp(`· group: (?:${QUOTED}|\\(none\\)) → choice: ${QUOTED}(?: \\(${QUOTED}\\))?$`);
|
|
25
|
+
|
|
26
|
+
function unquote(value) {
|
|
27
|
+
if (!value) return '';
|
|
28
|
+
try {
|
|
29
|
+
return String(JSON.parse(value));
|
|
30
|
+
} catch {
|
|
31
|
+
return '';
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** The live bubble's lines for one feedback block body. */
|
|
36
|
+
function feedbackDisplay(body) {
|
|
37
|
+
const pins = [];
|
|
38
|
+
const choices = [];
|
|
39
|
+
let pin = null;
|
|
40
|
+
let note = false;
|
|
41
|
+
let inChoices = false;
|
|
42
|
+
const tweakSets = [];
|
|
43
|
+
let tweaks = null;
|
|
44
|
+
for (const line of body.split('\n')) {
|
|
45
|
+
if (line.startsWith('tweaks (')) {
|
|
46
|
+
pin = null;
|
|
47
|
+
inChoices = false;
|
|
48
|
+
tweaks = null;
|
|
49
|
+
tweakSets.push([]);
|
|
50
|
+
tweaks = tweakSets.at(-1);
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (tweaks) {
|
|
54
|
+
const change = /^ {4}(.+?) \([^)]*\): (.*) \(was (.*)\)$/.exec(line);
|
|
55
|
+
if (change) tweaks.push(`${change[1]}: ${change[2]} (was ${change[3]})`);
|
|
56
|
+
else if (line.startsWith(' - tab: ')) {
|
|
57
|
+
tweaks = [];
|
|
58
|
+
tweakSets.push(tweaks);
|
|
59
|
+
} else tweaks = null;
|
|
60
|
+
if (tweaks) continue;
|
|
61
|
+
}
|
|
62
|
+
const head = /^pin (\d+) · (.*)$/.exec(line);
|
|
63
|
+
if (head) {
|
|
64
|
+
pin = { n: head[1], label: head[2], note: '' };
|
|
65
|
+
pins.push(pin);
|
|
66
|
+
note = false;
|
|
67
|
+
inChoices = false;
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (line === 'choices:') {
|
|
71
|
+
pin = null;
|
|
72
|
+
inChoices = true;
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (pin && line.startsWith(' note: ')) {
|
|
76
|
+
pin.note = line.slice(8);
|
|
77
|
+
note = true;
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (pin && note && line.startsWith(' ')) {
|
|
81
|
+
pin.note += `\n${line.slice(4)}`;
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
note = false;
|
|
85
|
+
const choice = inChoices ? CHOICE_LINE.exec(line) : null;
|
|
86
|
+
if (choice) {
|
|
87
|
+
choices.push({ group: unquote(choice[1]), choice: unquote(choice[2]), label: unquote(choice[3]) });
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const lines = pins.map((entry) => `📌 ${entry.n} · ${entry.label} — ${entry.note.replace(/\s+/g, ' ')}`);
|
|
91
|
+
if (choices.length) {
|
|
92
|
+
lines.push(
|
|
93
|
+
`☑ ${choices.map((entry) => (entry.group ? `${entry.group}: ` : '') + (entry.label || entry.choice)).join(', ')}`
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
const changed = tweakSets.filter((set) => set.length).map((set) => set.join(', '));
|
|
97
|
+
if (changed.length) lines.push(`🎚 ${changed.join('; ')}`);
|
|
98
|
+
return lines.join('\n');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function withVisualizeFeedbackDisplay(text) {
|
|
102
|
+
const value = String(text ?? '');
|
|
103
|
+
if (!value.includes(FEEDBACK_OPEN)) return value;
|
|
104
|
+
return value.replace(FEEDBACK_BLOCK, (_block, body) => feedbackDisplay(body));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** A stored text reference's body when it is a feedback block, else ''. */
|
|
108
|
+
function referencedFeedbackText(part) {
|
|
109
|
+
if (part?.type !== 'text' || part.textKind) return '';
|
|
110
|
+
try {
|
|
111
|
+
const text = readAttachmentTextWithin(part, FEEDBACK_MAX_BYTES);
|
|
112
|
+
return text?.startsWith(FEEDBACK_OPEN) ? text : '';
|
|
113
|
+
} catch {
|
|
114
|
+
// A blob gone from the store restores as it always did: without its text.
|
|
115
|
+
return '';
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** The display lines of a stored prompt's parts, and for each image part the
|
|
120
|
+
* line that draws it: the composer's metadata line right before it, else a
|
|
121
|
+
* bare line of its own (a bare line never stands for the next image). */
|
|
122
|
+
function restoredUserParts(content) {
|
|
123
|
+
const texts = [];
|
|
124
|
+
const images = [];
|
|
125
|
+
let pendingMetadata = '';
|
|
126
|
+
for (const part of content) {
|
|
127
|
+
if (part?.type === 'image' || part?.type === 'input_image') {
|
|
128
|
+
let line = pendingMetadata;
|
|
129
|
+
if (!line) {
|
|
130
|
+
line = `[Image: ${part.mimeType || part.mediaType || 'image'}]`;
|
|
131
|
+
texts.push(line);
|
|
132
|
+
}
|
|
133
|
+
pendingMetadata = '';
|
|
134
|
+
images.push({ part, line });
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
const text = isAttachmentReference(part) ? referencedFeedbackText(part) : toolResultText([part]);
|
|
138
|
+
if (text) texts.push(text);
|
|
139
|
+
pendingMetadata = IMAGE_METADATA_LINE.test(text) ? text.trimEnd().split(/\r?\n/).pop().trim() : '';
|
|
140
|
+
}
|
|
141
|
+
return { texts, images };
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function restoredUserText(content) {
|
|
145
|
+
if (!Array.isArray(content)) {
|
|
146
|
+
return withVisualizeFeedbackDisplay(typeof content === 'string' ? content : toolResultText(content));
|
|
147
|
+
}
|
|
148
|
+
return withVisualizeFeedbackDisplay(restoredUserParts(content).texts.join('\n'));
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** The stored original of each image the restored bubble draws, by the
|
|
152
|
+
* `[Image: …]` line that draws it. Every image keeps its slot (one without a
|
|
153
|
+
* stored original has no `ref`) so later images do not shift onto it; empty
|
|
154
|
+
* when no image has a stored original. */
|
|
155
|
+
export function restoredUserImageRefs(content) {
|
|
156
|
+
if (!Array.isArray(content)) return [];
|
|
157
|
+
const slots = restoredUserParts(content).images.map(({ part, line }) =>
|
|
158
|
+
isAttachmentReference(part) ? { line, ref: part.attachmentRef } : { line }
|
|
159
|
+
);
|
|
160
|
+
return slots.some((slot) => slot.ref) ? slots : [];
|
|
161
|
+
}
|
|
@@ -3,13 +3,25 @@ import { buildPowerShellFilterTeePlan } from '../shell-analysis.mjs';
|
|
|
3
3
|
import { normalizeErrorMessage } from '../path-diagnostics.mjs';
|
|
4
4
|
import { planDirectExeSpawn } from '../shell-direct-exe.mjs';
|
|
5
5
|
import { POWERSHELL_UTF8_PREFIX } from '../../../../../shared/shell-display.mjs';
|
|
6
|
+
import { renderPowerShellSkillFunction, skillScriptRuntime } from '../../../../../shared/skill-script-runtime.mjs';
|
|
6
7
|
import { buildShellSpawnEnv } from './spawn-env.mjs';
|
|
7
8
|
import { formatShellToolFailure } from './result-format.mjs';
|
|
8
9
|
|
|
10
|
+
// Every PowerShell model command defines `mixdog-skill-node` first, so the
|
|
11
|
+
// skill launcher runs without the .cmd's cmd.exe argument re-parsing.
|
|
12
|
+
// Injected whenever absent, independent of the UTF-8 prefix deduplication.
|
|
13
|
+
function prefixPowerShellSkillFunction(command) {
|
|
14
|
+
const fn = renderPowerShellSkillFunction(skillScriptRuntime());
|
|
15
|
+
const text = String(command || '');
|
|
16
|
+
return text.trimStart().startsWith(`${fn}\n`) ? text : `${fn}\n${text}`;
|
|
17
|
+
}
|
|
18
|
+
|
|
9
19
|
function prefixPowerShellUtf8(command) {
|
|
10
20
|
const prefix = POWERSHELL_UTF8_PREFIX;
|
|
11
21
|
const text = String(command || '');
|
|
12
|
-
|
|
22
|
+
const trimmed = text.trimStart();
|
|
23
|
+
const body = trimmed.startsWith(prefix) ? trimmed.slice(prefix.length).replace(/^[ \t]*\r?\n/, '') : text;
|
|
24
|
+
return `${prefix}\n${prefixPowerShellSkillFunction(body)}`;
|
|
13
25
|
}
|
|
14
26
|
|
|
15
27
|
// How the command reaches the child: a direct exe spawn, PowerShell with the
|
|
@@ -54,6 +66,10 @@ export async function planShellInvocation({ command, resolvedSpec, cwd }) {
|
|
|
54
66
|
plan.wrappedCommand = prefixPowerShellUtf8(plan.teePlan ? plan.teePlan.command : command);
|
|
55
67
|
return plan;
|
|
56
68
|
}
|
|
69
|
+
if (shellType === 'powershell') {
|
|
70
|
+
plan.wrappedCommand = prefixPowerShellSkillFunction(command);
|
|
71
|
+
return plan;
|
|
72
|
+
}
|
|
57
73
|
if (process.platform !== 'win32' && (shell.includes('bash') || shell.includes('zsh'))) {
|
|
58
74
|
try {
|
|
59
75
|
plan.wrappedCommand = await wrapCommandWithSnapshot(shell, command);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { resourceAdmission } from '../../../../../shared/resource-admission.mjs';
|
|
2
|
+
import { withSkillLauncherPath } from '../../../../../shared/skill-script-runtime.mjs';
|
|
2
3
|
import {
|
|
3
4
|
applyShellEgressPolicy,
|
|
4
5
|
scrubLoaderVars,
|
|
@@ -24,5 +25,8 @@ export function buildShellSpawnEnv(cwd, baseEnv = process.env) {
|
|
|
24
25
|
scrubLoaderVars(spawnEnv);
|
|
25
26
|
scrubRuntimeRootVars(spawnEnv);
|
|
26
27
|
applyShellEgressPolicy(spawnEnv);
|
|
28
|
+
// `mixdog-skill-node` (a skill's ${MIXDOG_SKILL_NODE}) resolves in every
|
|
29
|
+
// model shell; only this env gets the entry, never the daemon's own.
|
|
30
|
+
withSkillLauncherPath(spawnEnv);
|
|
27
31
|
return spawnEnv;
|
|
28
32
|
}
|
|
@@ -5,10 +5,15 @@ import { isAbsolute, sep } from 'node:path';
|
|
|
5
5
|
import { canonicalCachePath, deleteReadRangeIndexForPath } from './read-range-index.mjs';
|
|
6
6
|
import { resolveAgainstCwd } from './path-utils.mjs';
|
|
7
7
|
import { fileVersion, sameFileVersion } from './file-version.mjs';
|
|
8
|
+
import { canCacheReadFile } from './read-cache-policy.mjs';
|
|
8
9
|
|
|
9
10
|
const RESULT_CACHE = new Map(); // key → { ts, value, paths, scopes, readSnapshotMeta, contentPrefixHash, bytes }
|
|
10
11
|
const RESULT_CACHE_INFLIGHT = new Map(); // key → { promise, controller, subscribers, settled }
|
|
11
12
|
const RESULT_CACHE_COMPUTE = new AsyncLocalStorage();
|
|
13
|
+
const READ_CACHE_PUBLICATION = new AsyncLocalStorage();
|
|
14
|
+
// Only active reads retain a slot. Invalidating an inactive path creates
|
|
15
|
+
// no history, and the final reader releases its path in a finally block.
|
|
16
|
+
const ACTIVE_READ_CACHE_PATHS = new Map();
|
|
12
17
|
const RESULT_CACHE_TTL_MS = 30_000;
|
|
13
18
|
const RESULT_CACHE_MAX_ENTRIES = 200;
|
|
14
19
|
// A byte budget from the bytes env var, else the megabytes one, else the
|
|
@@ -72,6 +77,37 @@ function cachePathsOverlap(a, b) {
|
|
|
72
77
|
return a.startsWith(b.endsWith(sep) ? b : `${b}${sep}`) || b.startsWith(a.endsWith(sep) ? a : `${a}${sep}`);
|
|
73
78
|
}
|
|
74
79
|
|
|
80
|
+
export async function runReadCachePublication(fullPaths, read) {
|
|
81
|
+
const paths = normalizeCacheMetaPaths(Array.isArray(fullPaths) ? fullPaths : [fullPaths]);
|
|
82
|
+
const leases = paths.map((path) => {
|
|
83
|
+
let slot = ACTIVE_READ_CACHE_PATHS.get(path);
|
|
84
|
+
if (!slot) {
|
|
85
|
+
slot = { generation: 0, references: 0 };
|
|
86
|
+
ACTIVE_READ_CACHE_PATHS.set(path, slot);
|
|
87
|
+
}
|
|
88
|
+
slot.references++;
|
|
89
|
+
return { path, slot, generation: slot.generation, released: false };
|
|
90
|
+
});
|
|
91
|
+
try {
|
|
92
|
+
return await READ_CACHE_PUBLICATION.run(leases, read);
|
|
93
|
+
} finally {
|
|
94
|
+
for (const lease of leases) {
|
|
95
|
+
lease.released = true;
|
|
96
|
+
if (--lease.slot.references === 0) ACTIVE_READ_CACHE_PATHS.delete(lease.path);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function canPublishReadCache(targets = null) {
|
|
102
|
+
const leases = READ_CACHE_PUBLICATION.getStore();
|
|
103
|
+
if (!leases) return true;
|
|
104
|
+
const paths = normalizeCacheMetaPaths(Array.isArray(targets) ? targets : [targets]);
|
|
105
|
+
return leases.every((lease) => {
|
|
106
|
+
if (paths.length && !paths.some((path) => cachePathsOverlap(path, lease.path))) return true;
|
|
107
|
+
return !lease.released && lease.generation === lease.slot.generation;
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
75
111
|
function cacheEntryOverlapsPaths(entry, affectedPaths) {
|
|
76
112
|
const entryPaths = Array.isArray(entry?.paths) ? entry.paths : [];
|
|
77
113
|
const entryScopes = Array.isArray(entry?.scopes) ? entry.scopes : [];
|
|
@@ -107,6 +143,11 @@ export function cacheSet(key, value, meta = {}) {
|
|
|
107
143
|
// A detached/aborted computation must never repopulate a newer cache.
|
|
108
144
|
const computation = RESULT_CACHE_COMPUTE.getStore();
|
|
109
145
|
if (computation?.invalidated || computation?.controller?.signal?.aborted) return;
|
|
146
|
+
const publicationPaths = [
|
|
147
|
+
...(Array.isArray(meta.paths) ? meta.paths : []),
|
|
148
|
+
...(Array.isArray(meta.scopes) ? meta.scopes : []),
|
|
149
|
+
];
|
|
150
|
+
if (!canPublishReadCache(publicationPaths)) return;
|
|
110
151
|
// Replace-in-place: clear old entry's byte accounting before write.
|
|
111
152
|
if (RESULT_CACHE.has(key)) resultCacheDelete(key);
|
|
112
153
|
const bytes = estimateResultBytes(value);
|
|
@@ -239,7 +280,7 @@ export async function runRawContentInFlight(fullPath, loader = fsPromises.readFi
|
|
|
239
280
|
// Buffered reads provide their observed version: a later read must not
|
|
240
281
|
// join older bytes merely because a watcher has not fired yet. Preserve
|
|
241
282
|
// the unversioned helper contract for callers that supply no stat.
|
|
242
|
-
if (stat !== undefined && !version) return await loader(fullPath);
|
|
283
|
+
if (stat !== undefined && (!version || !canCacheReadFile(version))) return await loader(fullPath);
|
|
243
284
|
const key = version ? JSON.stringify([path, version]) : path;
|
|
244
285
|
return await runPathInFlight(RAW_CONTENT_INFLIGHT, key, path, () => loader(fullPath));
|
|
245
286
|
}
|
|
@@ -260,6 +301,10 @@ function rawContentCacheDelete(key) {
|
|
|
260
301
|
export function rawContentCacheGet(fullPath, stat, now = Date.now()) {
|
|
261
302
|
if (!fullPath || !stat) return null;
|
|
262
303
|
const key = canonicalCachePath(fullPath);
|
|
304
|
+
if (!canCacheReadFile(stat)) {
|
|
305
|
+
rawContentCacheDelete(key);
|
|
306
|
+
return null;
|
|
307
|
+
}
|
|
263
308
|
const entry = RAW_CONTENT_CACHE.get(key);
|
|
264
309
|
if (!entry) return null;
|
|
265
310
|
if (now - entry.ts > RAW_CONTENT_CACHE_TTL_MS) {
|
|
@@ -276,9 +321,10 @@ export function rawContentCacheGet(fullPath, stat, now = Date.now()) {
|
|
|
276
321
|
}
|
|
277
322
|
|
|
278
323
|
export function rawContentCacheSet(fullPath, stat, rawBuf, now = Date.now()) {
|
|
324
|
+
if (!canPublishReadCache(fullPath)) return;
|
|
279
325
|
if (!fullPath || !Buffer.isBuffer(rawBuf)) return;
|
|
280
326
|
const version = fileVersion(stat);
|
|
281
|
-
if (!version || rawBuf.length !== version.size || rawBuf.length > RAW_CONTENT_CACHE_MAX_BYTES) return;
|
|
327
|
+
if (!version || !canCacheReadFile(version) || rawBuf.length !== version.size || rawBuf.length > RAW_CONTENT_CACHE_MAX_BYTES) return;
|
|
282
328
|
const key = canonicalCachePath(fullPath);
|
|
283
329
|
rawContentCacheDelete(key);
|
|
284
330
|
RAW_CONTENT_CACHE.set(key, {
|
|
@@ -450,6 +496,7 @@ function runExtraInvalidationListeners(affectedPaths = null) {
|
|
|
450
496
|
}
|
|
451
497
|
|
|
452
498
|
function cacheInvalidateAll() {
|
|
499
|
+
for (const slot of ACTIVE_READ_CACHE_PATHS.values()) slot.generation++;
|
|
453
500
|
for (const entry of RESULT_CACHE_INFLIGHT.values()) {
|
|
454
501
|
entry.invalidated = true;
|
|
455
502
|
}
|
|
@@ -470,6 +517,9 @@ function cacheInvalidatePaths(paths) {
|
|
|
470
517
|
cacheInvalidateAll();
|
|
471
518
|
return;
|
|
472
519
|
}
|
|
520
|
+
for (const [path, slot] of ACTIVE_READ_CACHE_PATHS) {
|
|
521
|
+
if (affectedPaths.some((affected) => cachePathsOverlap(path, affected))) slot.generation++;
|
|
522
|
+
}
|
|
473
523
|
for (const inFlight of [RAW_CONTENT_INFLIGHT, READ_ONLY_STAT_INFLIGHT]) {
|
|
474
524
|
for (const [key, entry] of inFlight) {
|
|
475
525
|
if (affectedPaths.some((affected) => cachePathsOverlap(entry.path, affected))) inFlight.delete(key);
|