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
|
@@ -23,6 +23,7 @@ export function createSessionFlow(bag) {
|
|
|
23
23
|
steering,
|
|
24
24
|
submissions,
|
|
25
25
|
flushDeferredClearedSessionUi: autoClear.flushDeferredClearedSessionUi,
|
|
26
|
+
autoClearBeforeWake: autoClear.autoClearBeforeWake,
|
|
26
27
|
});
|
|
27
28
|
|
|
28
29
|
return {
|
|
@@ -41,6 +42,7 @@ export function createSessionFlow(bag) {
|
|
|
41
42
|
drainPendingSteering: steering.drainPendingSteering,
|
|
42
43
|
restoreLeadSteeringFromDisk: steering.restoreLeadSteeringFromDisk,
|
|
43
44
|
autoClearBeforeSubmit: autoClear.autoClearBeforeSubmit,
|
|
45
|
+
autoClearBeforeWake: autoClear.autoClearBeforeWake,
|
|
44
46
|
performAutoClear: autoClear.performAutoClear,
|
|
45
47
|
restoreQueued: queue.restoreQueued,
|
|
46
48
|
prioritizeQueued: queue.prioritizeQueued,
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
} from '../../runtime/shared/tool-execution-contract.mjs';
|
|
12
12
|
import { isLateToolAnnouncement } from '../../runtime/agent/orchestrator/runtime-core/session-text.mjs';
|
|
13
13
|
import { appendPromptHistory } from '../prompt-history-store.mjs';
|
|
14
|
+
import { newTranscriptMessageId } from '../../runtime/shared/transcript-metadata.mjs';
|
|
14
15
|
import {
|
|
15
16
|
buildExecutionResponseToolItem,
|
|
16
17
|
completionCardFromExecution,
|
|
@@ -21,7 +22,7 @@ import { appendAgentResponseTail } from './agent-response-tail.mjs';
|
|
|
21
22
|
import { nextId } from './transcript-spill.mjs';
|
|
22
23
|
|
|
23
24
|
export function createTranscriptIntake({ getState, flags, pushItem, patchItem, transcriptRouteMetadata }) {
|
|
24
|
-
const upsertSyntheticToolItem = (text, id = nextId(), parsed = null) => {
|
|
25
|
+
const upsertSyntheticToolItem = (text, id = nextId(), parsed = null, messageId = '') => {
|
|
25
26
|
const synthetic = parsed || parseSyntheticAgentMessage(text);
|
|
26
27
|
if (!synthetic) return false;
|
|
27
28
|
const label = synthetic.label || 'notification';
|
|
@@ -56,6 +57,7 @@ export function createTranscriptIntake({ getState, flags, pushItem, patchItem, t
|
|
|
56
57
|
pushItem({
|
|
57
58
|
kind: 'tool',
|
|
58
59
|
id,
|
|
60
|
+
...(messageId ? { messageId } : {}),
|
|
59
61
|
name: synthetic.name || 'agent',
|
|
60
62
|
args,
|
|
61
63
|
result: synthetic.result,
|
|
@@ -75,11 +77,11 @@ export function createTranscriptIntake({ getState, flags, pushItem, patchItem, t
|
|
|
75
77
|
// the text parser cannot read still shows up instead of vanishing.
|
|
76
78
|
if (origin === 'injected' && (extra?.mode === 'task-notification' || extra?.execution)) {
|
|
77
79
|
const card = completionCardFromExecution(extra?.execution, text);
|
|
78
|
-
if (card && upsertSyntheticToolItem(text, id, card)) return;
|
|
80
|
+
if (card && upsertSyntheticToolItem(text, id, card, extra?.messageId)) return;
|
|
79
81
|
}
|
|
80
82
|
if (origin === 'injected') {
|
|
81
83
|
const completion = parseModelVisibleCompletionWrapper(text);
|
|
82
|
-
if (completion && upsertSyntheticToolItem(text, id, completion)) return;
|
|
84
|
+
if (completion && upsertSyntheticToolItem(text, id, completion, extra?.messageId)) return;
|
|
83
85
|
}
|
|
84
86
|
// The lenient shape-only wrapper check is display-suppression only and
|
|
85
87
|
// must never hide a real, directly-typed/pasted user prompt just because
|
|
@@ -95,13 +97,20 @@ export function createTranscriptIntake({ getState, flags, pushItem, patchItem, t
|
|
|
95
97
|
// keep it in model context, but render NOTHING user-facing — not even the
|
|
96
98
|
// collapsed one-line notice (user request: hide late-tool notices entirely).
|
|
97
99
|
if (isLateToolAnnouncement(text)) return;
|
|
98
|
-
if (upsertSyntheticToolItem(text, id)) return;
|
|
100
|
+
if (upsertSyntheticToolItem(text, id, null, extra?.messageId)) return;
|
|
99
101
|
// Genuine, directly-typed/pasted user submissions only (never injected or
|
|
100
102
|
// synthetic paths, which returned above): persist to the cwd-scoped store so
|
|
101
103
|
// up-arrow history survives across sessions. Runs before pushItem so the
|
|
102
104
|
// merge in pushItem's user branch (loadPromptHistory) already sees it.
|
|
103
105
|
if (origin === 'user') appendPromptHistory(getState().cwd, text);
|
|
104
|
-
|
|
106
|
+
// The row carries its message's stable id: the runtime's (a steered
|
|
107
|
+
// message reports it) or, for a typed prompt, a new one that goes with
|
|
108
|
+
// the prompt into the model transcript. An injected row with no message
|
|
109
|
+
// id of its own carries none.
|
|
110
|
+
let messageId = '';
|
|
111
|
+
if (typeof extra?.messageId === 'string' && extra.messageId) messageId = extra.messageId;
|
|
112
|
+
else if (origin === 'user') messageId = newTranscriptMessageId();
|
|
113
|
+
const transcriptMeta = { ...transcriptRouteMetadata(), ...(messageId ? { messageId } : {}) };
|
|
105
114
|
if (origin === 'user') flags.pendingTranscriptMeta = transcriptMeta;
|
|
106
115
|
pushItem({
|
|
107
116
|
kind: 'user',
|
|
@@ -15,11 +15,19 @@ const STALE_STEERING_RESTORE_TTL_MS = 30 * 60 * 1000;
|
|
|
15
15
|
// Cross-process mutual exclusion still comes from the shared lock protocol;
|
|
16
16
|
// this chain only orders same-process operations that were previously
|
|
17
17
|
// naturally ordered by the synchronous call site.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
// One chain per session key so a slow write for one session never delays
|
|
19
|
+
// another; an entry is removed once its chain is idle.
|
|
20
|
+
const _persistChains = new Map();
|
|
21
|
+
function _serialize(key, task) {
|
|
22
|
+
const prev = _persistChains.get(key) || Promise.resolve();
|
|
23
|
+
const run = prev.then(task, task);
|
|
21
24
|
// Never let a rejection poison the chain; each op logs its own error.
|
|
22
|
-
|
|
25
|
+
const tail = run
|
|
26
|
+
.catch(() => {})
|
|
27
|
+
.then(() => {
|
|
28
|
+
if (_persistChains.get(key) === tail) _persistChains.delete(key);
|
|
29
|
+
});
|
|
30
|
+
_persistChains.set(key, tail);
|
|
23
31
|
return run;
|
|
24
32
|
}
|
|
25
33
|
|
|
@@ -159,7 +167,7 @@ export function appendTuiSteeringPersist(leadSessionId, entry) {
|
|
|
159
167
|
...(submissionId ? { submissionId } : {}),
|
|
160
168
|
...(Number.isFinite(submittedAt) && submittedAt > 0 ? { submittedAt } : {}),
|
|
161
169
|
};
|
|
162
|
-
return _serialize(async () => {
|
|
170
|
+
return _serialize(key, async () => {
|
|
163
171
|
try {
|
|
164
172
|
await updatePendingShard(key, (raw) => {
|
|
165
173
|
const next = normalizePendingStore(raw);
|
|
@@ -184,7 +192,7 @@ export function dropTuiSteeringPersist(leadSessionId, entries) {
|
|
|
184
192
|
if (!key) return Promise.resolve();
|
|
185
193
|
const batch = Array.isArray(entries) ? entries : [];
|
|
186
194
|
if (batch.length === 0) return Promise.resolve();
|
|
187
|
-
return _serialize(async () => {
|
|
195
|
+
return _serialize(key, async () => {
|
|
188
196
|
try {
|
|
189
197
|
await updatePendingShard(key, (raw) => {
|
|
190
198
|
const next = normalizePendingStore(raw);
|
|
@@ -207,8 +215,16 @@ export function dropTuiSteeringPersist(leadSessionId, entries) {
|
|
|
207
215
|
});
|
|
208
216
|
}
|
|
209
217
|
|
|
210
|
-
export function flushTuiSteeringPersist() {
|
|
211
|
-
|
|
218
|
+
export async function flushTuiSteeringPersist() {
|
|
219
|
+
// Loop: chains started while waiting are awaited too.
|
|
220
|
+
while (_persistChains.size > 0) {
|
|
221
|
+
await Promise.all([..._persistChains.values()]);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Test hook: number of live per-key chains.
|
|
226
|
+
export function _steeringPersistChainCount() {
|
|
227
|
+
return _persistChains.size;
|
|
212
228
|
}
|
|
213
229
|
|
|
214
230
|
function drainedRowToRestore(row) {
|
|
@@ -233,7 +249,7 @@ function drainedRowToRestore(row) {
|
|
|
233
249
|
export function drainTuiSteeringPersist(leadSessionId) {
|
|
234
250
|
const key = tuiSteeringSessionKey(leadSessionId);
|
|
235
251
|
if (!key) return Promise.resolve([]);
|
|
236
|
-
return _serialize(async () => {
|
|
252
|
+
return _serialize(key, async () => {
|
|
237
253
|
let drained = [];
|
|
238
254
|
let droppedStale = 0;
|
|
239
255
|
try {
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
// scalars); every function here takes it as its first argument.
|
|
6
6
|
import { TUI_FRAME_MS, yieldToRenderer } from './render-timing.mjs';
|
|
7
7
|
import { retryStatusLine } from '../../runtime/shared/err-text.mjs';
|
|
8
|
+
import { newTranscriptMessageId } from '../../runtime/shared/transcript-metadata.mjs';
|
|
8
9
|
|
|
9
10
|
// Share Ink's exact 120fps cadence with the frame-batched store. A separate
|
|
10
11
|
// 16ms timer left every other terminal frame idle, so completed script lines
|
|
@@ -59,9 +60,27 @@ function ensureAssistant(stream, initialText = '') {
|
|
|
59
60
|
if (!stream.currentAssistantId) {
|
|
60
61
|
stream.currentAssistantId = stream.nextId();
|
|
61
62
|
const meta = stream.transcriptMeta;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
// A non-streaming continuation was persisted before its text reached this
|
|
64
|
+
// row: the runtime left that message's id and time (ask-session
|
|
65
|
+
// takeAssistant), and the row carries them instead of minting new ones.
|
|
66
|
+
const persisted = stream.claimPersistedAssistant ? meta.persistedAssistant : null;
|
|
67
|
+
if (persisted) meta.persistedAssistant = null;
|
|
68
|
+
let assistantAt = persisted?.at;
|
|
69
|
+
let messageId = persisted?.messageId;
|
|
70
|
+
if (!persisted) {
|
|
71
|
+
assistantAt =
|
|
72
|
+
Number.isFinite(Number(meta.assistantAt)) && Number(meta.assistantAt) > 0
|
|
73
|
+
? Number(meta.assistantAt)
|
|
74
|
+
: Date.now();
|
|
75
|
+
meta.assistantAt = assistantAt;
|
|
76
|
+
// The reply this segment becomes is persisted with this stable id (the
|
|
77
|
+
// runtime takes it with assistantAt), so a compaction that drops the
|
|
78
|
+
// reply greys this row.
|
|
79
|
+
if (!(typeof meta.assistantMessageId === 'string' && meta.assistantMessageId)) {
|
|
80
|
+
meta.assistantMessageId = newTranscriptMessageId();
|
|
81
|
+
}
|
|
82
|
+
messageId = meta.assistantMessageId;
|
|
83
|
+
}
|
|
65
84
|
// Do NOT reset currentAssistantText here: the first onTextDelta has
|
|
66
85
|
// already accumulated the opening chunk before this batched flush runs.
|
|
67
86
|
// Segment resets are owned by closeAssistantSegment(). Seed the new row
|
|
@@ -70,6 +89,7 @@ function ensureAssistant(stream, initialText = '') {
|
|
|
70
89
|
stream.updateStreamingTail(stream.currentAssistantId, {
|
|
71
90
|
text: String(initialText || ''),
|
|
72
91
|
at: assistantAt,
|
|
92
|
+
messageId,
|
|
73
93
|
...stream.routeMeta,
|
|
74
94
|
});
|
|
75
95
|
}
|
|
@@ -86,6 +106,7 @@ function resetLineScan(stream) {
|
|
|
86
106
|
function closeAssistantSegment(stream) {
|
|
87
107
|
stream.currentAssistantId = null;
|
|
88
108
|
stream.currentAssistantText = '';
|
|
109
|
+
stream.claimPersistedAssistant = false;
|
|
89
110
|
resetLineScan(stream);
|
|
90
111
|
}
|
|
91
112
|
|
|
@@ -290,11 +311,18 @@ export function appendTextDelta(stream, textChunk) {
|
|
|
290
311
|
// Mid-turn assistant text that precedes a tool call from a provider that only
|
|
291
312
|
// returns the final response.content (no deltas); the streaming path owns
|
|
292
313
|
// the render when it already produced text for this segment.
|
|
293
|
-
export function appendAssistantText(stream, full) {
|
|
314
|
+
export function appendAssistantText(stream, full, { committed = false } = {}) {
|
|
294
315
|
endThinkingForText(stream);
|
|
295
316
|
stream.assistantText += full;
|
|
296
317
|
stream.currentAssistantText += full;
|
|
297
318
|
stream.pendingTextFlush = true;
|
|
319
|
+
// Only post-commit text is the persisted message's own: its row takes that
|
|
320
|
+
// id. Any other text (a tool preamble published before its message commits)
|
|
321
|
+
// leaves an earlier recorded id unclaimed, so drop it.
|
|
322
|
+
stream.claimPersistedAssistant = committed;
|
|
323
|
+
if (!committed && stream.transcriptMeta && typeof stream.transcriptMeta === 'object') {
|
|
324
|
+
stream.transcriptMeta.persistedAssistant = null;
|
|
325
|
+
}
|
|
298
326
|
flushStreamBatch(stream);
|
|
299
327
|
}
|
|
300
328
|
|
|
@@ -57,10 +57,12 @@ export async function builtinSkillNamesFor(runtime, calls) {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
// Transcript spec for a standalone (non-aggregated) tool card.
|
|
60
|
-
function standaloneCardSpec(itemId, name, args) {
|
|
60
|
+
function standaloneCardSpec(itemId, name, args, callId = '') {
|
|
61
61
|
return {
|
|
62
62
|
kind: 'tool',
|
|
63
63
|
id: itemId,
|
|
64
|
+
// Ties the card to its call (a compaction that drops it greys the card).
|
|
65
|
+
...(callId ? { callId } : {}),
|
|
64
66
|
name,
|
|
65
67
|
args,
|
|
66
68
|
result: null,
|
|
@@ -221,7 +223,13 @@ function openToolCard(cards, call, index, batch) {
|
|
|
221
223
|
// Defer the visible push: the card enters the transcript when its real
|
|
222
224
|
// header will paint (delay elapsed) or its result lands first, so no
|
|
223
225
|
// blank placeholder height scrolls the body ahead of the glyphs.
|
|
224
|
-
const card = {
|
|
226
|
+
const card = {
|
|
227
|
+
itemId,
|
|
228
|
+
callId: callKey,
|
|
229
|
+
done: false,
|
|
230
|
+
pushed: false,
|
|
231
|
+
spec: standaloneCardSpec(itemId, name, args, callId),
|
|
232
|
+
};
|
|
225
233
|
cards.deferredCards.registerCard(card);
|
|
226
234
|
trackCard(cards, callId, card);
|
|
227
235
|
// Immediate row-reserve is deferred until every touched aggregate has its
|
package/src/tui/session/turn.mjs
CHANGED
|
@@ -18,6 +18,7 @@ import { isRejected429, safeErrorDetails } from '../../runtime/shared/error-pres
|
|
|
18
18
|
import { registerTaskWaitSteeringCheck } from '../../runtime/agent/orchestrator/session/task-wait-control.mjs';
|
|
19
19
|
import { promptDisplayText, STEERING_SUPPRESSED_DISPLAY } from './queue-helpers.mjs';
|
|
20
20
|
import { yieldToRenderer } from './render-timing.mjs';
|
|
21
|
+
import { archiveItemsForCompaction, compactionArchivedRows } from './compaction-view.mjs';
|
|
21
22
|
import {
|
|
22
23
|
createTurnStream,
|
|
23
24
|
flushStreamBatch,
|
|
@@ -105,7 +106,8 @@ function beginTurn({ flags, getState, transcriptRouteMetadata }, options) {
|
|
|
105
106
|
completionVerb,
|
|
106
107
|
};
|
|
107
108
|
flags.pendingTranscriptMeta = null;
|
|
108
|
-
|
|
109
|
+
// The prompt's own time and stable id stay on the prompt row.
|
|
110
|
+
const { at: _userItemAt, messageId: _promptMessageId, ...routeMeta } = transcriptMeta;
|
|
109
111
|
return {
|
|
110
112
|
index,
|
|
111
113
|
startedAt,
|
|
@@ -182,6 +184,11 @@ function commitPromptRestore(flags, turn) {
|
|
|
182
184
|
|
|
183
185
|
function steeringItemExtras(steeringMeta) {
|
|
184
186
|
return {
|
|
187
|
+
// The steered message's stable id, so a compaction that drops it greys
|
|
188
|
+
// this row.
|
|
189
|
+
...(typeof steeringMeta?.messageId === 'string' && steeringMeta.messageId
|
|
190
|
+
? { messageId: steeringMeta.messageId }
|
|
191
|
+
: {}),
|
|
185
192
|
// Queue mode + execution provenance: a task notification is rendered as
|
|
186
193
|
// a tool card, never as an injected user bubble.
|
|
187
194
|
...(steeringMeta?.mode === 'task-notification' ? { mode: 'task-notification' } : {}),
|
|
@@ -261,10 +268,10 @@ function publishContextPressure({ syncContextStats, getState, set }, info) {
|
|
|
261
268
|
}
|
|
262
269
|
|
|
263
270
|
// Compaction itself remains owned by the pre-provider-send pass. This event
|
|
264
|
-
//
|
|
265
|
-
//
|
|
266
|
-
// pressure.
|
|
267
|
-
function applyCompactEvent(ctx, event) {
|
|
271
|
+
// archives the visible rows before the current turn (they stay in view above
|
|
272
|
+
// the compaction divider) and refreshes the gauge from the already-mutated
|
|
273
|
+
// transcript before another render can show stale pressure.
|
|
274
|
+
export function applyCompactEvent(ctx, event) {
|
|
268
275
|
const { turn, stream, cards, getState, set, replaceItems, pushItem, nextId, syncContextStats, routeState } = ctx;
|
|
269
276
|
flushStreamBatch(stream);
|
|
270
277
|
// Non-tool transcript item — same block-boundary rule as the steered user
|
|
@@ -272,12 +279,31 @@ function applyCompactEvent(ctx, event) {
|
|
|
272
279
|
cards.aggregates.clearAggregateContinuation();
|
|
273
280
|
const compactStatus = String(event?.status || '').toLowerCase();
|
|
274
281
|
const compactChanged = !['failed', 'skipped', 'no_change'].includes(compactStatus);
|
|
282
|
+
const doneItem = {
|
|
283
|
+
kind: 'statusdone',
|
|
284
|
+
id: nextId(),
|
|
285
|
+
label: compactEventLabel(event),
|
|
286
|
+
detail: compactEventDetail(event),
|
|
287
|
+
};
|
|
275
288
|
if (compactChanged) {
|
|
276
|
-
|
|
277
|
-
turn.
|
|
289
|
+
// The current turn starts at its submitted row (spill paging may have
|
|
290
|
+
// shifted the index recorded at turn start).
|
|
291
|
+
const current = getState().items;
|
|
292
|
+
const submitted = new Set(turn.submittedIds.filter((id) => id != null));
|
|
293
|
+
const submittedIndex = submitted.size ? current.findIndex((item) => submitted.has(item?.id)) : -1;
|
|
294
|
+
const boundary = submittedIndex >= 0 ? submittedIndex : turn.currentItemsStart;
|
|
295
|
+
const { items, dividerIndex } = archiveItemsForCompaction(current, doneItem, boundary, {
|
|
296
|
+
archived: compactionArchivedRows(event),
|
|
297
|
+
// Only explicit identities name what left the current turn; a bare
|
|
298
|
+
// count says nothing about it.
|
|
299
|
+
archiveTail: Boolean(event?.droppedIdentities && typeof event.droppedIdentities === 'object'),
|
|
300
|
+
});
|
|
301
|
+
set({ items: replaceItems(items, { preserveStreamingTail: true, preserveSpill: true }) });
|
|
302
|
+
turn.currentItemsStart = dividerIndex + 1;
|
|
278
303
|
turn.transcriptCompacted = true;
|
|
304
|
+
} else {
|
|
305
|
+
pushItem(doneItem);
|
|
279
306
|
}
|
|
280
|
-
pushItem({ kind: 'statusdone', id: nextId(), label: compactEventLabel(event), detail: compactEventDetail(event) });
|
|
281
307
|
syncContextStats({ allowEstimated: true, invalidateExact: compactChanged });
|
|
282
308
|
// syncContextStats only STAGES its patch; publication is the caller's, and
|
|
283
309
|
// without this set the post-compact gauge reached React only if some later
|
|
@@ -296,9 +322,26 @@ function applyTurnUsageDelta({ turn, getState, set, syncContextStats }, delta) {
|
|
|
296
322
|
set({ stats: { ...getState().stats }, ...(spinner ? { spinner: { ...spinner, inputTokens, outputTokens } } : {}) });
|
|
297
323
|
}
|
|
298
324
|
|
|
325
|
+
// The runtime reports the skills a user turn actually loaded (`Skill:` header
|
|
326
|
+
// or inline `$name`); the prompt row carries them as `appliedSkills`, the same
|
|
327
|
+
// field a restored row reads from the persisted transcript metadata.
|
|
328
|
+
function applySkillsToPromptRow({ turn, getState, patchItem }, names, detail = {}) {
|
|
329
|
+
const appliedSkills = (Array.isArray(names) ? names : []).filter((name) => typeof name === 'string' && name);
|
|
330
|
+
if (!appliedSkills.length) return;
|
|
331
|
+
const messageId = typeof detail?.messageId === 'string' ? detail.messageId : '';
|
|
332
|
+
const submitted = turn.submittedIds[0];
|
|
333
|
+
const row = getState().items.findLast(
|
|
334
|
+
(item) => item?.kind === 'user' && (messageId ? item.messageId === messageId : item.id === submitted)
|
|
335
|
+
);
|
|
336
|
+
if (row) patchItem(row.id, { appliedSkills });
|
|
337
|
+
}
|
|
338
|
+
|
|
299
339
|
function turnHandlers(ctx) {
|
|
300
340
|
const { isCurrentTurn, drainPendingSteering } = ctx;
|
|
301
341
|
return {
|
|
342
|
+
onSkillsApplied: (names, detail) => {
|
|
343
|
+
if (isCurrentTurn()) applySkillsToPromptRow(ctx, names, detail);
|
|
344
|
+
},
|
|
302
345
|
drainSteering: (_sessionId, drainOptions) =>
|
|
303
346
|
isCurrentTurn() ? drainPendingSteering({ ...drainOptions, turnEpoch: ctx.turn.epoch }) : [],
|
|
304
347
|
onStreamDelta: () => {},
|
|
@@ -359,7 +402,7 @@ function streamHandlers(ctx) {
|
|
|
359
402
|
appendTextDelta(stream, textChunk);
|
|
360
403
|
},
|
|
361
404
|
onTextReset: (reset = {}) => (isCurrentTurn() ? resetStreamedText(stream, reset) : false),
|
|
362
|
-
onAssistantText: (text) => {
|
|
405
|
+
onAssistantText: (text, detail) => {
|
|
363
406
|
const full = String(text ?? '');
|
|
364
407
|
if (!full.trim() || !isCurrentTurn()) return;
|
|
365
408
|
// The streaming path owns this segment when it already produced text.
|
|
@@ -367,7 +410,7 @@ function streamHandlers(ctx) {
|
|
|
367
410
|
// there across tool calls.
|
|
368
411
|
if (stream.currentAssistantText.trim()) return;
|
|
369
412
|
ctx.markPromptCommitted();
|
|
370
|
-
appendAssistantText(stream, full);
|
|
413
|
+
appendAssistantText(stream, full, { committed: detail?.committed === true });
|
|
371
414
|
},
|
|
372
415
|
onReasoningDelta: (chunk) => {
|
|
373
416
|
if (isCurrentTurn()) appendReasoningDelta(stream, String(chunk ?? ''));
|
|
@@ -420,9 +463,12 @@ export function failTurn(ctx, error) {
|
|
|
420
463
|
}
|
|
421
464
|
|
|
422
465
|
export function turnDoneItem({ turn, stream, cards, getState, nextId }) {
|
|
466
|
+
// The outer prompt id is the turn's change-record key (runtime.ask `id`).
|
|
467
|
+
const checkpointId = turn.submittedIds[0] == null ? '' : String(turn.submittedIds[0]).trim();
|
|
423
468
|
return {
|
|
424
469
|
kind: 'turndone',
|
|
425
470
|
id: nextId(),
|
|
471
|
+
...(checkpointId ? { checkpointId } : {}),
|
|
426
472
|
elapsedMs: Date.now() - turn.startedAt,
|
|
427
473
|
status: turnOutcome(turn.cancelled, turn.failed),
|
|
428
474
|
// Notifications resolve this exact terminal assistant item, never a
|
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
// Pure pre-turn extraction of the previous human request and the assistant
|
|
2
|
-
// text around it, from the session history as it stands BEFORE the current
|
|
3
|
-
// turn is committed (the boundary resolveTurnAutoEffort runs at). Nothing here
|
|
4
|
-
// reads the current prompt's outcome; nothing is mutated; no text is matched
|
|
5
|
-
// against word lists. Ownership comes only from typed provenance that the
|
|
6
|
-
// runtime already writes (meta.runtimeUserContext, meta.synthetic, meta.source,
|
|
7
|
-
// the compaction/skill/reminder predicates in compact/messages.mjs).
|
|
8
|
-
//
|
|
9
|
-
// Result of previousHumanContext(messages, { retryPrompt }):
|
|
10
|
-
// {
|
|
11
|
-
// version: 1,
|
|
12
|
-
// boundary: number, // messages[0..boundary) were considered
|
|
13
|
-
// retryTrimmedIndex: number, // index of the unanswered resubmitted prompt
|
|
14
|
-
// // dropped from the view, or -1
|
|
15
|
-
// prevHuman: { text, index, source, runtimeContext } | null,
|
|
16
|
-
// // latest actual human message before the boundary. `text` is the
|
|
17
|
-
// // runtime-context-stripped, trimmed text (untruncated). `source` is
|
|
18
|
-
// // meta.source or null ('steering' = a human interjection).
|
|
19
|
-
// // `runtimeContext` is 'stripped' | 'none'.
|
|
20
|
-
// prevHumanMissing: 'empty-history' | 'no-human-request' | null,
|
|
21
|
-
// canonicalReply: { text, index } | null,
|
|
22
|
-
// // exactly what the shipped rp `prev` is: the latest non-empty
|
|
23
|
-
// // assistant message before the boundary, whatever turn it is from.
|
|
24
|
-
// pairedReply: { text, index } | null,
|
|
25
|
-
// // latest non-empty assistant text inside prevHuman's own turn span
|
|
26
|
-
// // (after prevHuman up to the next human message / boundary). Never
|
|
27
|
-
// // falls back to another turn: a tool-only or unanswered turn gives
|
|
28
|
-
// // null with pairedMissing set.
|
|
29
|
-
// pairedMissing: 'no-human-request' | 'no-assistant-text-in-turn' | null,
|
|
30
|
-
// replyIsPaired: boolean, // canonicalReply and pairedReply are the same message
|
|
31
|
-
// skipped: [{ index, role, reason }], // user messages passed over after
|
|
32
|
-
// // prevHuman's search began (newest first); reasons: 'summary',
|
|
33
|
-
// // 'protected-context', 'skill-body', 'synthetic-flag',
|
|
34
|
-
// // 'typed-source', 'runtime-owned', 'empty'.
|
|
35
|
-
// }
|
|
36
|
-
//
|
|
37
|
-
// Policy decisions (PREVIOUS_HUMAN_POLICY):
|
|
38
|
-
// synthetic meta.synthetic === true, or a source the runtime stores as
|
|
39
|
-
// "not the user speaking" (task-notification, skill-context),
|
|
40
|
-
// or anything isActualUserInstructionMessage rejects
|
|
41
|
-
// (goal-continuation/closeout, compact-*, *-recovery, control
|
|
42
|
-
// lines), is skipped, not treated as a request.
|
|
43
|
-
// steering meta.source === 'steering' is a human interjection (the
|
|
44
|
-
// provider layer keeps it as its own user turn for that
|
|
45
|
-
// reason) and counts as a human request.
|
|
46
|
-
// retry when retryPrompt repeats the trailing unanswered user prompt
|
|
47
|
-
// (trailingUnansweredPromptIndex), that stale copy is excluded
|
|
48
|
-
// so the prompt is never its own "previous request".
|
|
49
|
-
// summary compact summaries are skipped; nothing before them is
|
|
50
|
-
// recovered, so history truncated by compaction yields
|
|
51
|
-
// 'no-human-request' rather than a guess.
|
|
52
|
-
// Limitation: user messages stored without meta (old transcripts) cannot be
|
|
53
|
-
// told apart from the human when a runtime wrapper was never recorded; they
|
|
54
|
-
// are accepted as human, and a wrapper with stale provenance stays unstripped.
|
|
55
|
-
import { stripRuntimeUserContext } from '../agent/orchestrator/session/runtime-user-context.mjs';
|
|
56
|
-
import {
|
|
57
|
-
isActualUserInstructionMessage,
|
|
58
|
-
isInjectedSkillBodyMessage,
|
|
59
|
-
isProtectedContextUserMessage,
|
|
60
|
-
isSummaryMessage,
|
|
61
|
-
} from '../agent/orchestrator/session/compact/messages.mjs';
|
|
62
|
-
import { trailingUnansweredPromptIndex } from '../agent/orchestrator/session/manager/failed-turn-rewind.mjs';
|
|
63
|
-
import { promptContentText } from '../agent/orchestrator/session/manager/prompt-utils.mjs';
|
|
64
|
-
|
|
65
|
-
export const PREVIOUS_HUMAN_POLICY = Object.freeze({
|
|
66
|
-
synthetic: 'skip',
|
|
67
|
-
steering: 'human',
|
|
68
|
-
retry: 'exclude-trailing-unanswered-copy',
|
|
69
|
-
summary: 'skip-no-recovery',
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
const TYPED_NON_HUMAN_SOURCES = new Set(['task-notification', 'skill-context']);
|
|
73
|
-
|
|
74
|
-
const textOf = (message) => promptContentText(message?.content).trim();
|
|
75
|
-
|
|
76
|
-
/** { human, reason?, message } for a user message; null for other roles. */
|
|
77
|
-
function classify(message) {
|
|
78
|
-
if (message?.role !== 'user') return null;
|
|
79
|
-
const stripped = stripRuntimeUserContext(message);
|
|
80
|
-
const meta = stripped.meta && typeof stripped.meta === 'object' ? stripped.meta : {};
|
|
81
|
-
const no = (reason) => ({ human: false, reason, message: stripped });
|
|
82
|
-
if (isSummaryMessage(stripped)) return no('summary');
|
|
83
|
-
if (isProtectedContextUserMessage(stripped)) return no('protected-context');
|
|
84
|
-
if (isInjectedSkillBodyMessage(stripped)) return no('skill-body');
|
|
85
|
-
if (meta.synthetic === true) return no('synthetic-flag');
|
|
86
|
-
if (TYPED_NON_HUMAN_SOURCES.has(String(meta.source || ''))) return no('typed-source');
|
|
87
|
-
if (!isActualUserInstructionMessage(stripped)) return no('runtime-owned');
|
|
88
|
-
if (!textOf(stripped)) return no('empty');
|
|
89
|
-
return { human: true, message: stripped, stripped: stripped !== message };
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function latestAssistant(messages, from, to) {
|
|
93
|
-
for (let index = to - 1; index >= from; index -= 1) {
|
|
94
|
-
if (messages[index]?.role !== 'assistant') continue;
|
|
95
|
-
const text = textOf(messages[index]);
|
|
96
|
-
if (text) return { text, index };
|
|
97
|
-
}
|
|
98
|
-
return null;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export function previousHumanContext(messages, { retryPrompt } = {}) {
|
|
102
|
-
const list = Array.isArray(messages) ? messages : [];
|
|
103
|
-
const retryTrimmedIndex = retryPrompt == null ? -1 : trailingUnansweredPromptIndex(list, retryPrompt);
|
|
104
|
-
const boundary = retryTrimmedIndex >= 0 ? retryTrimmedIndex : list.length;
|
|
105
|
-
const verdicts = [];
|
|
106
|
-
for (let index = 0; index < boundary; index += 1) verdicts.push(classify(list[index]));
|
|
107
|
-
|
|
108
|
-
const skipped = [];
|
|
109
|
-
let humanIndex = -1;
|
|
110
|
-
for (let index = boundary - 1; index >= 0; index -= 1) {
|
|
111
|
-
const verdict = verdicts[index];
|
|
112
|
-
if (!verdict) continue;
|
|
113
|
-
if (verdict.human) {
|
|
114
|
-
humanIndex = index;
|
|
115
|
-
break;
|
|
116
|
-
}
|
|
117
|
-
skipped.push({ index, role: 'user', reason: verdict.reason });
|
|
118
|
-
// A summary replaces earlier conversational context; do not recover a
|
|
119
|
-
// request from an older retained fragment behind that boundary.
|
|
120
|
-
if (verdict.reason === 'summary') break;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
const canonicalReply = latestAssistant(list, 0, boundary);
|
|
124
|
-
let prevHuman = null;
|
|
125
|
-
let pairedReply = null;
|
|
126
|
-
let pairedMissing = 'no-human-request';
|
|
127
|
-
if (humanIndex >= 0) {
|
|
128
|
-
const verdict = verdicts[humanIndex];
|
|
129
|
-
const source = verdict.message.meta?.source;
|
|
130
|
-
prevHuman = {
|
|
131
|
-
text: textOf(verdict.message),
|
|
132
|
-
index: humanIndex,
|
|
133
|
-
source: typeof source === 'string' && source ? source : null,
|
|
134
|
-
runtimeContext: verdict.stripped ? 'stripped' : 'none',
|
|
135
|
-
};
|
|
136
|
-
let end = boundary;
|
|
137
|
-
for (let index = humanIndex + 1; index < boundary; index += 1) {
|
|
138
|
-
if (verdicts[index]?.human) {
|
|
139
|
-
end = index;
|
|
140
|
-
break;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
pairedReply = latestAssistant(list, humanIndex + 1, end);
|
|
144
|
-
pairedMissing = pairedReply ? null : 'no-assistant-text-in-turn';
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
let prevHumanMissing = null;
|
|
148
|
-
if (!prevHuman) prevHumanMissing = boundary === 0 ? 'empty-history' : 'no-human-request';
|
|
149
|
-
|
|
150
|
-
return {
|
|
151
|
-
version: 1,
|
|
152
|
-
boundary,
|
|
153
|
-
retryTrimmedIndex,
|
|
154
|
-
prevHuman,
|
|
155
|
-
prevHumanMissing,
|
|
156
|
-
canonicalReply,
|
|
157
|
-
pairedReply,
|
|
158
|
-
pairedMissing,
|
|
159
|
-
replyIsPaired: Boolean(pairedReply && canonicalReply && pairedReply.index === canonicalReply.index),
|
|
160
|
-
skipped,
|
|
161
|
-
};
|
|
162
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
// Experimental input only. An unavailable verified request preserves rp exactly.
|
|
2
|
-
// Ownership and pairing are established by the caller, never inferred here.
|
|
3
|
-
export function verifiedContextText({ request, prev, prevRequestVerified } = {}) {
|
|
4
|
-
const current = String(request || '').slice(0, 1500);
|
|
5
|
-
const reply = String(prev || '').slice(-1000);
|
|
6
|
-
const prior = Array.from(String(prevRequestVerified || ''))
|
|
7
|
-
.slice(0, 300)
|
|
8
|
-
.join('');
|
|
9
|
-
return `request: ${current}${prior ? `\nprevious request: ${prior}` : ''}\nprevious reply: ${reply}`;
|
|
10
|
-
}
|