mixdog 1.4.1 → 1.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -3
- package/scripts/build-shipped-history.mjs +125 -33
- package/scripts/gate-local.mjs +220 -63
- package/scripts/graph-parity.mjs +8 -3
- package/scripts/lib/gate-scheduler.mjs +139 -32
- package/scripts/lib/gate-timing-reporter.mjs +16 -0
- package/scripts/lib/run-node-tests.mjs +71 -34
- package/scripts/lib/scoped-temp.mjs +1 -0
- package/scripts/lib/test-failure-records.mjs +14 -1
- package/scripts/lib/test-failure-summary.mjs +9 -4
- package/scripts/lib/test-spawn-ledger.mjs +43 -3
- package/scripts/post-release-check.mjs +26 -16
- package/scripts/pptx-kit-index.mjs +5 -6
- package/scripts/provider-pingpong-live.mjs +1 -1
- package/scripts/prune-embedding-runtime.mjs +3 -1
- package/scripts/release-paths.mjs +7 -1
- package/scripts/suite-health.mjs +110 -28
- package/scripts/test.mjs +9 -14
- package/src/agents/advisor/AGENT.md +4 -4
- package/src/agents/advisor/agent.json +1 -1
- package/src/agents/explore/AGENT.md +22 -0
- package/src/agents/explore/agent.json +6 -0
- package/src/cli.mjs +7 -0
- package/src/defaults/agents.json +7 -0
- package/src/defaults/shipped-history.json +38 -2
- package/src/defaults/skills/browser-use/SKILL.md +4 -1
- package/src/defaults/skills/code-tidy/SKILL.md +71 -102
- package/src/defaults/skills/code-tidy/references/agent-cleanup.md +66 -114
- package/src/defaults/skills/code-tidy/references/cleanup-report.md +19 -35
- package/src/defaults/skills/code-tidy/references/dead-code.md +3 -9
- package/src/defaults/skills/code-tidy/references/test-suite-slop.md +16 -27
- package/src/defaults/skills/computer-use/SKILL.md +12 -2
- package/src/defaults/skills/setup/SKILL.md +2 -2
- package/src/defaults/skills/setup/references/actions.md +28 -9
- package/src/defaults/skills/setup/references/surfaces.md +5 -2
- package/src/defaults/skills/setup-guide/SKILL.md +11 -3
- package/src/defaults/skills/setup-guide/model-recommendations.json +13 -0
- package/src/defaults/skills/skill-creator/SKILL.md +85 -190
- package/src/defaults/skills/skill-creator/references/design.md +70 -162
- package/src/defaults/skills/skill-creator/references/evaluation.md +33 -92
- package/src/defaults/skills/test-suite/SKILL.md +194 -0
- package/src/defaults/skills/test-suite/references/case-management.md +51 -0
- package/src/defaults/skills/test-suite/references/flaky-policy.md +39 -0
- package/src/defaults/skills/test-suite/references/reliability.md +49 -0
- package/src/defaults/skills/test-suite/references/suite-design.md +78 -0
- package/src/defaults/skills/test-suite/scripts/inventory.mjs +335 -0
- package/src/defaults/skills/visualize/SKILL.md +6 -2
- package/src/lib/instruction-text.cjs +36 -0
- package/src/lib/rules-builder.cjs +40 -50
- package/src/orchestration/balanced.md +23 -0
- package/src/orchestration/focused.md +22 -0
- package/src/orchestration/none.md +5 -0
- package/src/orchestration/swarm.md +24 -0
- package/src/rules/agent-mode/AGENT_MODE.md +3 -1
- package/src/rules/agent-mode/MIXY.md +2 -2
- package/src/rules/lead/LEAD.md +3 -3
- package/src/rules/shared/20-research.md +3 -6
- package/src/rules/shared/40-editing.md +1 -0
- package/src/rules/shared/60-verification.md +10 -9
- package/src/rules/shared/70-delivery.md +4 -3
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/abort-link.mjs +5 -1
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/session-prep.mjs +3 -3
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +10 -2
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +132 -21
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +13 -9
- package/src/runtime/agent/orchestrator/agent-runtime/heartbeat-completion.mjs +2 -2
- package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +4 -1
- package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +67 -0
- package/src/runtime/agent/orchestrator/agent-trace-format.mjs +1 -0
- package/src/runtime/agent/orchestrator/config.mjs +12 -7
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +7 -7
- package/src/runtime/agent/orchestrator/context/role-instructions.mjs +9 -30
- package/src/runtime/agent/orchestrator/internal-agents.mjs +3 -14
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +124 -12
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +204 -49
- package/src/runtime/agent/orchestrator/mcp/client-config.mjs +16 -7
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +157 -57
- package/src/runtime/agent/orchestrator/mcp/client.mjs +54 -23
- package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +1 -1
- package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +8 -2
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +83 -52
- package/src/runtime/agent/orchestrator/mcp/oauth-probe.mjs +1 -1
- package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +14 -0
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +43 -27
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +43 -8
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +30 -28
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +31 -21
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-stop.mjs +3 -3
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +40 -0
- package/src/runtime/agent/orchestrator/providers/custom-provider-keys.mjs +34 -0
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/devin-auth.mjs +14 -7
- package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +48 -31
- package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +0 -18
- package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +138 -6
- package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/model-cache.mjs +100 -33
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/oauth-secret-fields.fixtures.mjs +45 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +4 -6
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2784 -2872
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +5 -8
- package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +26 -28
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +288 -300
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/registry.mjs +33 -2
- package/src/runtime/agent/orchestrator/providers/vertex-ai-auth.mjs +622 -0
- package/src/runtime/agent/orchestrator/providers/vertex-ai-maas.mjs +185 -0
- package/src/runtime/agent/orchestrator/providers/vertex-ai-models.mjs +445 -0
- package/src/runtime/agent/orchestrator/providers/vertex-ai.mjs +576 -0
- package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +10 -30
- package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +32 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +0 -11
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +8 -0
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +17 -3
- package/src/runtime/agent/orchestrator/runtime-core/goal-control.mjs +47 -27
- package/src/runtime/agent/orchestrator/runtime-core/goal-deadlines.mjs +141 -10
- package/src/runtime/agent/orchestrator/runtime-core/goal-mutations.mjs +26 -63
- package/src/runtime/agent/orchestrator/runtime-core/goal-reminder.mjs +28 -3
- package/src/runtime/agent/orchestrator/runtime-core/goal-runtime.mjs +36 -11
- package/src/runtime/agent/orchestrator/runtime-core/goal-state.mjs +88 -56
- package/src/runtime/agent/orchestrator/runtime-core/goal-storage.mjs +4 -1
- package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +51 -32
- package/src/runtime/agent/orchestrator/runtime-core/goal-text.mjs +45 -145
- package/src/runtime/agent/orchestrator/runtime-core/goal-tool-defs.mjs +15 -98
- package/src/runtime/agent/orchestrator/runtime-core/goal-tool-exec.mjs +32 -99
- package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +23 -78
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +69 -47
- package/src/runtime/agent/orchestrator/runtime-core/todo-list.mjs +367 -0
- package/src/runtime/agent/orchestrator/runtime-core/todo-tool-defs.mjs +47 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-availability.mjs +155 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +12 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +119 -35
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +4 -1
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +15 -6
- package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +28 -22
- package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +30 -0
- package/src/runtime/agent/orchestrator/session/agent-room.d.mts +30 -5
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +171 -37
- package/src/runtime/agent/orchestrator/session/attachment-preflight.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/cache-warm.mjs +94 -10
- package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/compact/summary-route.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -12
- package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +4 -4
- package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +11 -6
- package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +6 -6
- package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +7 -3
- package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +11 -1
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -3
- package/src/runtime/agent/orchestrator/session/human-gate/held-message.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +37 -8
- package/src/runtime/agent/orchestrator/session/human-gate/run-policy.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/image-strip-recovery.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +11 -1
- package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +5 -3
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +8 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/todo-check.mjs +196 -0
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +116 -50
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +8 -1
- package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +5 -6
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +27 -3
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +18 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +23 -1
- package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +13 -8
- package/src/runtime/agent/orchestrator/session/loop/turn-report.mjs +35 -0
- package/src/runtime/agent/orchestrator/session/loop/usage.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +103 -50
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +9 -7
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +21 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-failure.mjs +27 -11
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-open.mjs +37 -34
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +25 -15
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +79 -24
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +12 -1
- package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/idle-cleanup.mjs +6 -1
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +9 -1
- package/src/runtime/agent/orchestrator/session/manager/pending-spool-path.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/manager/pending-spool-shard.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/prompt-settings.mjs +598 -0
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +20 -0
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +22 -14
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +12 -0
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +56 -14
- package/src/runtime/agent/orchestrator/session/manager/session-lock.mjs +31 -0
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +59 -20
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/session-scratch-environment.mjs +70 -0
- package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +0 -3
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +18 -4
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +8 -9
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +339 -88
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-recovery.mjs +135 -11
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +377 -104
- package/src/runtime/agent/orchestrator/session/manager/turn-durability.mjs +144 -0
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +48 -30
- package/src/runtime/agent/orchestrator/session/manager/turn-reap.mjs +125 -0
- package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/mixy-name.mjs +12 -6
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +8 -1
- package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/save-session-worker.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/store/canonical-reader.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/liveness-veto.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +23 -2
- package/src/runtime/agent/orchestrator/session/store/sweep/sub-agent-retention.mjs +3 -3
- package/src/runtime/agent/orchestrator/session/store/transcript-durability.mjs +88 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/store-summary-log.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +243 -38
- package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +163 -64
- package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +177 -8
- package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +142 -18
- package/src/runtime/agent/orchestrator/session/store.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/synthetic-user-envelope.mjs +7 -1
- package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +9 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/agent-envelope.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +2 -2
- package/src/runtime/agent/orchestrator/stall-policy.mjs +3 -5
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +4 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +21 -3
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/worktree-add-guard.mjs +77 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +0 -1
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +42 -28
- package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +30 -14
- package/src/runtime/agent/orchestrator/tools/builtin/lib/search-input-helpers.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +58 -20
- package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-fast-paths.mjs +0 -1
- package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +20 -15
- package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +0 -10
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +95 -20
- package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +59 -10
- package/src/runtime/agent/orchestrator/tools/builtin.mjs +1 -24
- package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary/child-kill.mjs +4 -3
- package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary.mjs +1 -2
- package/src/runtime/agent/orchestrator/tools/code-graph/modes/calls.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/modes/symbols.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +4 -5
- package/src/runtime/agent/orchestrator/tools/code-graph/symbol-index.mjs +3 -4
- package/src/runtime/agent/orchestrator/tools/code-graph.mjs +4 -22
- package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
- package/src/runtime/agent/orchestrator/tools/lib/native-spawn-client.mjs +99 -2
- package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +2 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +105 -15
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +49 -15
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +45 -27
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +35 -11
- package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +2 -0
- package/src/runtime/agent/orchestrator/tools/lib/wait-until-fixture.mjs +26 -0
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -6
- package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +0 -1
- package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
- package/src/runtime/attachments/attachment-reference.mjs +1 -1
- package/src/runtime/attachments/pdf-extract.mjs +1 -1
- package/src/runtime/attachments/store.d.mts +1 -0
- package/src/runtime/attachments/store.mjs +2 -2
- package/src/runtime/channels/lib/config-reload-watch.mjs +42 -0
- package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +29 -9
- package/src/runtime/channels/lib/scheduler.mjs +33 -0
- package/src/runtime/channels/lib/schedules-db.mjs +11 -4
- package/src/runtime/channels/lib/webhook/session-dispatch.mjs +4 -1
- package/src/runtime/channels/lib/webhooks-db.mjs +9 -3
- package/src/runtime/channels/lib/whisper-port.mjs +19 -10
- package/src/runtime/channels/lib/whisper-server.mjs +22 -13
- package/src/runtime/channels/lib/worker-main.mjs +9 -31
- package/src/runtime/computer-bridge/linux-readiness.mjs +10 -14
- package/src/runtime/connectors/connector-accounts-mcp.mjs +372 -103
- package/src/runtime/connectors/gmail-app-password.mjs +4 -4
- package/src/runtime/connectors/google-mcp.mjs +1 -1
- package/src/runtime/effort-judge/judge-client.mjs +2 -2
- package/src/runtime/effort-judge/judge-input.mjs +4 -4
- package/src/runtime/explore/explorer.mjs +88 -0
- package/src/runtime/explore/tool-defs.mjs +35 -0
- package/src/runtime/explore/tool.mjs +123 -0
- package/src/runtime/local-provider/hardware.mjs +1 -1
- package/src/runtime/media/adapters/codex-image.mjs +3 -3
- package/src/runtime/media/adapters/gemini-video.mjs +1 -1
- package/src/runtime/media/media-usage.mjs +1 -1
- package/src/runtime/media/store.mjs +1 -1
- package/src/runtime/memory/index.mjs +15 -1
- package/src/runtime/memory/lib/embedding-provider.mjs +4 -1
- package/src/runtime/memory/lib/embedding-reindex.mjs +27 -0
- package/src/runtime/memory/lib/embedding-worker.mjs +4 -0
- package/src/runtime/memory/lib/memory-embed.mjs +83 -14
- package/src/runtime/memory/lib/memory-process-lock.mjs +159 -36
- package/src/runtime/memory/lib/memory-text-utils.mjs +6 -1
- package/src/runtime/memory/lib/memory.mjs +17 -0
- package/src/runtime/memory/lib/pg/process.mjs +1 -1
- package/src/runtime/memory/lib/pg/supervisor.mjs +16 -96
- package/src/runtime/memory/lib/recall-hybrid/hybrid-sql.mjs +12 -3
- package/src/runtime/office/authoring/docx-html-runner.mjs +1 -1
- package/src/runtime/office/authoring/pptx-author-action.mjs +1 -1
- package/src/runtime/office/authoring/xlsx-html-build.mjs +1 -1
- package/src/runtime/office/authoring/xlsx-html-runner.mjs +1 -1
- package/src/runtime/office/capabilities.mjs +1 -1
- package/src/runtime/office/core/office-core.mjs +1 -1
- package/src/runtime/office/design/content-model.mjs +3 -3
- package/src/runtime/office/design/docx/design-docx/section.mjs +6 -6
- package/src/runtime/office/design/xlsx/design-xlsx-components.mjs +1 -1
- package/src/runtime/office/design/xlsx/design-xlsx.mjs +1 -1
- package/src/runtime/office/pdf/ocr-engine.mjs +1 -1
- package/src/runtime/office/pdf/pdf-writer.mjs +4 -4
- package/src/runtime/office/portable/portable-docx-operations.mjs +2 -2
- package/src/runtime/office/portable/portable-soffice.mjs +8 -6
- package/src/runtime/office/portable/xlsx-contract.mjs +1 -1
- package/src/runtime/office/quality/assurance-structure-docx.mjs +1 -1
- package/src/runtime/shared/agent-route-config.mjs +17 -2
- package/src/runtime/shared/atomic-file.d.mts +8 -0
- package/src/runtime/shared/atomic-file.mjs +103 -2
- package/src/runtime/shared/background-tasks.mjs +37 -10
- package/src/runtime/shared/background-wait.mjs +66 -0
- package/src/runtime/shared/child-guardian.mjs +17 -7
- package/src/runtime/shared/config.mjs +313 -16
- package/src/runtime/shared/connector-accounts.mjs +5 -5
- package/src/runtime/shared/connector-catalog.d.mts +14 -8
- package/src/runtime/shared/connector-catalog.mjs +70 -52
- package/src/runtime/shared/custom-provider-keys.mjs +20 -0
- package/src/runtime/shared/file-has-data.mjs +26 -2
- package/src/runtime/shared/file-lock.mjs +21 -18
- package/src/runtime/shared/git-launch.d.mts +9 -0
- package/src/runtime/shared/git-launch.mjs +213 -0
- package/src/runtime/shared/git-runner-worker.mjs +2 -1
- package/src/runtime/shared/git-runner.mjs +7 -2
- package/src/runtime/shared/idle-gc.mjs +30 -7
- package/src/runtime/shared/llm/cost.mjs +6 -1
- package/src/runtime/shared/llm/http-agent.mjs +316 -29
- package/src/runtime/shared/llm/model-catalog-projection.mjs +3 -2
- package/src/runtime/shared/llm/model-catalog.mjs +46 -6
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +3 -0
- package/src/runtime/shared/llm/system-proxy.mjs +453 -0
- package/src/runtime/shared/llm/usage-ledger-quota.mjs +31 -12
- package/src/runtime/shared/llm/usage-ledger-rollup.mjs +84 -8
- package/src/runtime/shared/llm/usage-ledger.mjs +3 -0
- package/src/runtime/shared/llm/usage-rollup.mjs +48 -0
- package/src/runtime/shared/maintenance-schedule.mjs +109 -0
- package/src/runtime/shared/process-runner.mjs +8 -4
- package/src/runtime/shared/provider-accounts.mjs +52 -2
- package/src/runtime/shared/routine-trigger.d.mts +13 -0
- package/src/runtime/shared/routine-trigger.mjs +34 -0
- package/src/runtime/shared/run-child.d.mts +2 -1
- package/src/runtime/shared/run-child.mjs +70 -18
- package/src/runtime/shared/session-scratch.mjs +14 -2
- package/src/runtime/shared/shipped-definitions.mjs +7 -1
- package/src/runtime/shared/staged-install-worker.mjs +5 -0
- package/src/runtime/shared/staged-update.mjs +47 -2
- package/src/runtime/shared/tool-card-model.golden.json +3 -12
- package/src/runtime/shared/tool-execution-contract.mjs +2 -0
- package/src/runtime/shared/tool-surface.mjs +110 -36
- package/src/runtime/shared/tool-work-units.mjs +35 -6
- package/src/runtime/shared/turn-snapshot.mjs +26 -4
- package/src/runtime/shared/turn-worktree-snapshot.mjs +409 -54
- package/src/runtime/shared/worker-requests.mjs +17 -3
- package/src/runtime/shared/worktrees/activity-gate.mjs +215 -318
- package/src/runtime/shared/worktrees/activity-ledger-worker.mjs +56 -0
- package/src/runtime/shared/worktrees/activity-ledger.mjs +391 -0
- package/src/runtime/shared/worktrees/branch-management.mjs +5 -3
- package/src/runtime/shared/worktrees/contract.mjs +16 -6
- package/src/runtime/shared/worktrees/dependencies.mjs +127 -89
- package/src/runtime/shared/worktrees/disk.mjs +79 -2
- package/src/runtime/shared/worktrees/git.mjs +97 -7
- package/src/runtime/shared/worktrees/include.mjs +6 -4
- package/src/runtime/shared/worktrees/maintenance.mjs +422 -30
- package/src/runtime/shared/worktrees/manager.mjs +962 -197
- package/src/runtime/shared/worktrees/settings.mjs +33 -7
- package/src/runtime/shared/worktrees/test-support.mjs +5 -1
- package/src/runtime/shared/worktrees/worker-snapshots.mjs +82 -0
- package/src/runtime/tidy/install.mjs +95 -15
- package/src/runtime/tidy/languages.mjs +17 -15
- package/src/runtime/tidy/process.mjs +9 -5
- package/src/runtime/tidy/resolve.mjs +19 -16
- package/src/runtime/tidy/runners/biome.mjs +3 -3
- package/src/runtime/tidy/tool.mjs +1 -1
- package/src/runtime/tidy/worktree.mjs +10 -6
- package/src/runtime/visualize-bridge/client.mjs +4 -1
- package/src/runtime/visualize-bridge/tool-defs.mjs +7 -2
- package/src/runtime/web-search/index.mjs +4 -23
- package/src/runtime/web-search/lib/web-tools.mjs +2 -2
- package/src/runtime/web-search/tool-defs.mjs +17 -26
- package/src/session-runtime/agent-profile-changes.mjs +55 -4
- package/src/session-runtime/agent-task-sessions.mjs +410 -353
- package/src/session-runtime/boot/apis.mjs +27 -4
- package/src/session-runtime/boot/begin.mjs +2 -0
- package/src/session-runtime/boot/config.mjs +10 -1
- package/src/session-runtime/boot/facade.mjs +1 -0
- package/src/session-runtime/boot/providers.mjs +70 -3
- package/src/session-runtime/boot/session.mjs +2 -0
- package/src/session-runtime/boot/tools.mjs +71 -25
- package/src/session-runtime/bot-status.mjs +103 -103
- package/src/session-runtime/channel-config-api.mjs +1 -0
- package/src/session-runtime/config-change-effects.mjs +179 -0
- package/src/session-runtime/config-lifecycle/config-writers.mjs +1 -0
- package/src/session-runtime/config-lifecycle.mjs +160 -24
- package/src/session-runtime/connector-merge-migration.mjs +18 -15
- package/src/session-runtime/conversation-import/discovery.mjs +245 -47
- package/src/session-runtime/conversation-import/service.mjs +12 -5
- package/src/session-runtime/goal-facade-api.mjs +49 -3
- package/src/session-runtime/handoff-attachments.mjs +1 -1
- package/src/session-runtime/held-requests.mjs +3 -1
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +3 -0
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -2
- package/src/session-runtime/internal-tool-executor/feature-tools.mjs +5 -11
- package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +8 -0
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +161 -120
- package/src/session-runtime/internal-tool-executor.mjs +12 -19
- package/src/session-runtime/lifecycle/cold-heir.mjs +7 -0
- package/src/session-runtime/lifecycle/memory-ingest.mjs +3 -3
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +53 -5
- package/src/session-runtime/lifecycle/session-switch.mjs +13 -2
- package/src/session-runtime/lifecycle/teardown/session-close.mjs +10 -5
- package/src/session-runtime/lifecycle/teardown.mjs +1 -1
- package/src/session-runtime/lifecycle-api.mjs +1 -0
- package/src/session-runtime/mcp-glue/server-catalog.mjs +27 -10
- package/src/session-runtime/mcp-glue/server-connection.mjs +34 -8
- package/src/session-runtime/mcp-glue/server-input.mjs +4 -1
- package/src/session-runtime/mixy-heartbeat.mjs +1 -1
- package/src/session-runtime/model-route/set-route.mjs +40 -7
- package/src/session-runtime/native-web-search/routes.mjs +3 -3
- package/src/session-runtime/provider-auth/login.mjs +2 -2
- package/src/session-runtime/provider-auth/refresh.mjs +6 -3
- package/src/session-runtime/provider-auth/setup.mjs +1 -1
- package/src/session-runtime/provider-readiness.mjs +53 -4
- package/src/session-runtime/resource-api.mjs +1 -1
- package/src/session-runtime/resource-extension-sync.mjs +4 -8
- package/src/session-runtime/resource-mcp-api.mjs +98 -35
- package/src/session-runtime/resource-mcp-connector-accounts.mjs +49 -32
- package/src/session-runtime/resource-mcp-secrets.mjs +27 -10
- package/src/session-runtime/resource-mcp-servers.mjs +5 -4
- package/src/session-runtime/resource-plugins-api.mjs +4 -0
- package/src/session-runtime/routine-executor.mjs +152 -0
- package/src/session-runtime/routine-home-turn.mjs +46 -5
- package/src/session-runtime/runtime-facade.mjs +5 -0
- package/src/session-runtime/runtime-feature-gates.mjs +2 -11
- package/src/session-runtime/schedule-session-run.mjs +1 -0
- package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +6 -1
- package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +7 -0
- package/src/session-runtime/services/agent-tool/send-flow.mjs +120 -8
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +12 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +5 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +8 -3
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +28 -7
- package/src/session-runtime/services/agent-tool.mjs +51 -1
- package/src/session-runtime/services/agent-watchdog-registry.mjs +32 -4
- package/src/session-runtime/services/channel-admin.mjs +18 -0
- package/src/session-runtime/services/channel-worker/daemon-spawn.mjs +2 -0
- package/src/session-runtime/services/daemon-candidate.mjs +4 -1
- package/src/session-runtime/services/hook-bus/command-handler.mjs +7 -11
- package/src/session-runtime/services/memory-runtime-proxy/daemon-spawn.mjs +4 -0
- package/src/session-runtime/services/plugin-admin.mjs +14 -6
- package/src/session-runtime/services/provider-admin.mjs +281 -10
- package/src/session-runtime/services/seeds.mjs +7 -0
- package/src/session-runtime/services/usage-stats-model.mjs +32 -11
- package/src/session-runtime/session-create/materialize.mjs +4 -2
- package/src/session-runtime/session-create/session-options.mjs +2 -0
- package/src/session-runtime/session-turn-api.mjs +2 -0
- package/src/session-runtime/settings-builtin-tools-api.mjs +5 -10
- package/src/session-runtime/settings-system-api.mjs +1 -1
- package/src/session-runtime/setup-tool/agent-settings-actions.mjs +13 -3
- package/src/session-runtime/setup-tool/connector-widen-approval.mjs +96 -0
- package/src/session-runtime/setup-tool/executor.mjs +14 -3
- package/src/session-runtime/setup-tool/extended-actions.mjs +2 -0
- package/src/session-runtime/setup-tool/settings-contract.mjs +28 -0
- package/src/session-runtime/setup-tool/tool-defs.mjs +28 -2
- package/src/session-runtime/tool-policy/agent-profile-fold.mjs +40 -43
- package/src/session-runtime/tool-policy/mode-switch.mjs +1 -1
- package/src/session-runtime/tool-policy/policy-stage.mjs +106 -8
- package/src/session-runtime/tool-policy/workflow-overlay.mjs +2 -1
- package/src/session-runtime/tool-policy-refresh.mjs +182 -5
- package/src/session-runtime/tool-surface.mjs +38 -1
- package/src/session-runtime/turn/agent-ops.mjs +33 -2
- package/src/session-runtime/turn/session-ops.mjs +2 -0
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +5 -0
- package/src/session-runtime/turn/turn-run.mjs +1 -1
- package/src/session-runtime/webhook-session-run.mjs +2 -0
- package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +46 -11
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +2 -0
- package/src/session-runtime/workflow-agents-api/instruction-files.mjs +165 -0
- package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +5 -4
- package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +2 -3
- package/src/session-runtime/workflow-agents-api.mjs +2 -0
- package/src/session-runtime/workspace/activity-guards.mjs +176 -0
- package/src/session-runtime/workspace/project-branches.mjs +1 -1
- package/src/session-runtime/workspace/session-view.mjs +149 -0
- package/src/session-runtime/workspace/side-checkouts.mjs +203 -0
- package/src/session-runtime/workspace/transition-runner.mjs +188 -0
- package/src/session-runtime/workspace/transitions.mjs +128 -1070
- package/src/session-runtime/workspace/workspace-merge.mjs +132 -0
- package/src/session-runtime/workspace/worktree-intents.mjs +242 -0
- package/src/session-runtime/workspace/worktree-maintenance.mjs +200 -0
- package/src/session-runtime/workspace/worktree-setup.mjs +97 -0
- package/src/session-runtime/workspace/worktree-tool.mjs +70 -54
- package/src/standalone/daemon-agent-control.mjs +25 -8
- package/src/standalone/daemon-desktop-runtime.mjs +8 -2
- package/src/standalone/daemon-lag-profiler.mjs +7 -7
- package/src/standalone/daemon-session-control.mjs +151 -136
- package/src/standalone/daemon.mjs +61 -2
- package/src/standalone/desktop-service-registry.mjs +9 -0
- package/src/standalone/local-session-runtime.mjs +21 -1
- package/src/standalone/session-client/daemon-unavailable.mjs +4 -1
- package/src/standalone/session-client.mjs +5 -1
- package/src/standalone/session-frame-stream.mjs +83 -11
- package/src/standalone/session-protocol.mjs +15 -0
- package/src/standalone/session-service/agent-route-follow.mjs +23 -20
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +18 -6
- package/src/standalone/session-service/agent-tree.mjs +45 -9
- package/src/standalone/session-service/projection/transcript-window.mjs +700 -64
- package/src/standalone/session-service/quota-resume.mjs +9 -0
- package/src/standalone/session-service/session-calls/session-action.mjs +51 -1
- package/src/standalone/session-service/session-calls/session-turns.mjs +37 -18
- package/src/standalone/session-service/session-calls/session-views.mjs +160 -104
- package/src/standalone/session-service/session-calls/turn-gate.mjs +34 -0
- package/src/standalone/session-service/session-calls.mjs +2 -1
- package/src/standalone/session-service/stored-reader.mjs +127 -40
- package/src/tui/App.jsx +162 -164
- package/src/tui/app/app-view/floating-panel.jsx +3 -0
- package/src/tui/app/app-view/text-entry-labels.mjs +1 -0
- package/src/tui/app/clipboard.mjs +22 -11
- package/src/tui/app/create-app-pickers.mjs +2 -0
- package/src/tui/app/doctor.mjs +2 -2
- package/src/tui/app/panel-signature.mjs +1 -1
- package/src/tui/app/prompt-handlers/use-prompt-history-nav.mjs +1 -1
- package/src/tui/app/prompt-handlers/use-prompt-interrupt.mjs +3 -0
- package/src/tui/app/prompt-submit/provider-prompts.mjs +3 -1
- package/src/tui/app/provider-setup/api-key-actions.mjs +31 -1
- package/src/tui/app/provider-setup/oauth-actions.mjs +25 -6
- package/src/tui/app/provider-setup-picker.mjs +20 -13
- package/src/tui/app/settings-picker.mjs +53 -8
- package/src/tui/app/shell-layout/row-budgets.mjs +14 -12
- package/src/tui/app/slash-commands.mjs +2 -1
- package/src/tui/app/slash-dispatch/route-commands.mjs +1 -1
- package/src/tui/app/slash-dispatch/session-commands.mjs +47 -1
- package/src/tui/app/slash-dispatch.mjs +1 -1
- package/src/tui/app/use-btw-panel.mjs +29 -0
- package/src/tui/app/use-context-panel-refresh.mjs +31 -0
- package/src/tui/app/use-model-catalog-cache.mjs +13 -10
- package/src/tui/app/use-mouse-input.mjs +11 -0
- package/src/tui/app/use-onboarding-start.mjs +8 -3
- package/src/tui/app/use-panel-transition.mjs +10 -1
- package/src/tui/app/use-pasted-buffers.mjs +28 -20
- package/src/tui/app/use-prompt-draft-flow.mjs +7 -0
- package/src/tui/app/use-prompt-layout-rows.mjs +3 -3
- package/src/tui/app/use-prompt-queue-history.mjs +5 -4
- package/src/tui/app/use-selection-focus.mjs +11 -2
- package/src/tui/app/use-selection-geometry.mjs +18 -9
- package/src/tui/app/use-selection-paint.mjs +4 -4
- package/src/tui/app/use-selection-stitch.mjs +3 -3
- package/src/tui/app/use-slash-palette.mjs +62 -0
- package/src/tui/app/use-terminal-chrome.mjs +2 -2
- package/src/tui/app/use-transcript-activity.mjs +48 -33
- package/src/tui/app/use-transcript-follow.mjs +12 -4
- package/src/tui/app/use-transcript-scroll.mjs +46 -17
- package/src/tui/app/use-transcript-swap-reset.mjs +27 -0
- package/src/tui/app/use-transcript-window/geometry.mjs +20 -6
- package/src/tui/app/use-transcript-window/instance-state.mjs +4 -0
- package/src/tui/app/use-transcript-window/selection-shift.mjs +5 -1
- package/src/tui/app/use-transcript-window.mjs +21 -11
- package/src/tui/app/use-tui-ready.mjs +18 -0
- package/src/tui/app/use-welcome-prompt-hint.mjs +5 -0
- package/src/tui/app/use-workflow-tab-cycle.mjs +5 -3
- package/src/tui/components/Picker.jsx +27 -3
- package/src/tui/components/SignInUrl.jsx +68 -0
- package/src/tui/components/TextEntryPanel.jsx +76 -46
- package/src/tui/components/prompt-input/escape-policy.d.mts +0 -1
- package/src/tui/components/prompt-input/escape-policy.mjs +1 -1
- package/src/tui/components/question-panel-model.mjs +4 -4
- package/src/tui/components/sign-in-url-layout.mjs +24 -0
- package/src/tui/components/tool-execution/standard-card.jsx +3 -4
- package/src/tui/components/user-message-skills.mjs +1 -1
- package/src/tui/dist/index.mjs +2205 -1371
- package/src/tui/markdown/render-ansi.mjs +1 -1
- package/src/tui/session/agent-job-feed/notification-router.mjs +10 -0
- package/src/tui/session/agent-job-feed.mjs +2 -0
- package/src/tui/session/context-state.mjs +3 -0
- package/src/tui/session/goal-turn-state.mjs +6 -2
- package/src/tui/session/quota-resume.mjs +1 -1
- package/src/tui/session/session-api/controls.mjs +4 -0
- package/src/tui/session/session-api/extensions.mjs +8 -0
- package/src/tui/session/session-api/intake/abort.mjs +2 -1
- package/src/tui/session/session-api/intake.mjs +2 -0
- package/src/tui/session/session-api/integrations.mjs +2 -2
- package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
- package/src/tui/session/session-api/lifecycle/session-reset.mjs +7 -0
- package/src/tui/session/session-api/routes-agent-definitions.mjs +6 -0
- package/src/tui/session/session-api/settings.mjs +2 -2
- package/src/tui/session/session-api/worktree.mjs +13 -1
- package/src/tui/session/session-flow/drain.mjs +11 -14
- package/src/tui/session/tool-card-results/grouped-result.mjs +2 -2
- package/src/tui/session/transcript-spill/spill-writer.mjs +15 -0
- package/src/tui/session/transcript-spill.mjs +92 -4
- package/src/tui/session/transcript-store.mjs +2 -0
- package/src/tui/session/turn-quiet.mjs +1 -1
- package/src/tui/session/turn.mjs +3 -0
- package/src/tui/session/worktree-setup-notice.mjs +1 -1
- package/src/tui/spinner-meta.mjs +3 -3
- package/src/tui/spinner-verbs.mjs +2 -2
- package/src/defaults/skills/goal-management/SKILL.md +0 -169
- package/src/defaults/skills/skill-creator/references/source-review.md +0 -94
- package/src/runtime/agent/orchestrator/runtime-core/goal-tasks.mjs +0 -156
- package/src/session-runtime/goal-tasks.mjs +0 -1
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Discovery of importable foreign conversations on disk (read-only).
|
|
3
3
|
*
|
|
4
|
-
* codex $CODEX_HOME/sessions/**\/rollout-*.jsonl (default ~/.codex)
|
|
4
|
+
* codex $CODEX_HOME/sessions/**\/rollout-*.jsonl[.zst] (default ~/.codex)
|
|
5
5
|
* claude $CLAUDE_CONFIG_DIR/projects/*\/*.jsonl (default ~/.claude)
|
|
6
|
+
* cowork %APPDATA%\Claude\local-agent-mode-sessions (Claude Desktop; Windows only)
|
|
6
7
|
*
|
|
7
8
|
* Enumeration is stat-only; per-file metadata (foreign id, cwd, title, and
|
|
8
9
|
* the message count when the whole file fit the read) comes from a bounded
|
|
@@ -11,9 +12,11 @@
|
|
|
11
12
|
* shares one cache, one candidate registry and one set of listing views.
|
|
12
13
|
*/
|
|
13
14
|
import { createHash, randomUUID } from 'node:crypto';
|
|
14
|
-
import { open, readdir, realpath, stat } from 'node:fs/promises';
|
|
15
|
+
import { open, readdir, readFile, realpath, stat } from 'node:fs/promises';
|
|
15
16
|
import { homedir } from 'node:os';
|
|
16
|
-
import { basename, dirname,
|
|
17
|
+
import { basename, dirname, isAbsolute, join, relative, resolve } from 'node:path';
|
|
18
|
+
import { pipeline } from 'node:stream';
|
|
19
|
+
import zlib from 'node:zlib';
|
|
17
20
|
import {
|
|
18
21
|
IMPORT_MAX_FILE_BYTES,
|
|
19
22
|
IMPORT_MAX_LINE_BYTES,
|
|
@@ -24,7 +27,13 @@ import {
|
|
|
24
27
|
isImportSource,
|
|
25
28
|
} from '../../runtime/agent/orchestrator/session/conversation-import/convert.mjs';
|
|
26
29
|
import { codexMetaFromTruncatedLine } from '../../runtime/agent/orchestrator/session/conversation-import/codex.mjs';
|
|
27
|
-
import {
|
|
30
|
+
import {
|
|
31
|
+
IMPORT_ERROR_NEEDS_NEWER_NODE,
|
|
32
|
+
IMPORT_WARNING_CWD_MISSING,
|
|
33
|
+
IMPORT_WARNING_HISTORY_PARTIAL,
|
|
34
|
+
IMPORT_WARNING_HISTORY_SIZE_LIMIT,
|
|
35
|
+
IMPORT_WARNING_HISTORY_UNAVAILABLE,
|
|
36
|
+
} from '../../runtime/agent/orchestrator/session/conversation-import/turns.mjs';
|
|
28
37
|
import { importOriginKey } from '../../runtime/agent/orchestrator/session/conversation-import/imported-session.mjs';
|
|
29
38
|
import { loadCodexThreadTitles } from './codex-titles.mjs';
|
|
30
39
|
|
|
@@ -69,6 +78,11 @@ const envDir = (value) => (typeof value === 'string' && value.trim() ? resolve(v
|
|
|
69
78
|
export function sourceRoot(source, env = process.env) {
|
|
70
79
|
if (source === 'codex') return join(envDir(env.CODEX_HOME) || join(homedir(), '.codex'), 'sessions');
|
|
71
80
|
if (source === 'claude') return join(envDir(env.CLAUDE_CONFIG_DIR) || join(homedir(), '.claude'), 'projects');
|
|
81
|
+
// Only Windows sets APPDATA; elsewhere Claude Desktop has no Cowork folder to search.
|
|
82
|
+
if (source === 'cowork') {
|
|
83
|
+
const appData = envDir(env.APPDATA);
|
|
84
|
+
return appData ? join(appData, 'Claude', 'local-agent-mode-sessions') : null;
|
|
85
|
+
}
|
|
72
86
|
throw importError('unsupported');
|
|
73
87
|
}
|
|
74
88
|
|
|
@@ -83,8 +97,8 @@ export function loadStoredTitles(source, env = process.env) {
|
|
|
83
97
|
}
|
|
84
98
|
|
|
85
99
|
/** The app's stored title of a conversation, else the one derived from its messages. */
|
|
86
|
-
export function displayTitle(meta, titles) {
|
|
87
|
-
return (meta?.foreignSessionId && titles?.get(meta.foreignSessionId)) || meta?.title || null;
|
|
100
|
+
export function displayTitle(meta, titles, manifestTitle = null) {
|
|
101
|
+
return manifestTitle || (meta?.foreignSessionId && titles?.get(meta.foreignSessionId)) || meta?.title || null;
|
|
88
102
|
}
|
|
89
103
|
|
|
90
104
|
const caseFold = (value) => (process.platform === 'win32' ? value.toLowerCase() : value);
|
|
@@ -106,6 +120,51 @@ export function isNetworkOrDevicePath(path) {
|
|
|
106
120
|
|
|
107
121
|
const fileIdentity = (info) => `${info.dev}:${info.ino}`;
|
|
108
122
|
|
|
123
|
+
// Rollout file-name rules, as the source app applies them: a compressed rollout is a
|
|
124
|
+
// name ending `.jsonl.zst`; a rollout name is, after dropping a `.zst` suffix,
|
|
125
|
+
// `rollout-` … `.jsonl`. Both are case-sensitive.
|
|
126
|
+
const COMPRESSED_ROLLOUT_SUFFIX = '.jsonl.zst';
|
|
127
|
+
const isCompressed = (path) => basename(path).endsWith(COMPRESSED_ROLLOUT_SUFFIX);
|
|
128
|
+
const isRolloutName = (name) => {
|
|
129
|
+
const plain = name.endsWith(COMPRESSED_ROLLOUT_SUFFIX) ? name.slice(0, -'.zst'.length) : name;
|
|
130
|
+
return plain.startsWith('rollout-') && plain.endsWith('.jsonl');
|
|
131
|
+
};
|
|
132
|
+
const zstdSupported = () => typeof zlib.createZstdDecompress === 'function';
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Sequential `read(buffer, offset, length, position)` / `close()` over the
|
|
136
|
+
* decompressed bytes of an open compressed file, shaped like a file handle so
|
|
137
|
+
* the line reader needs no other change. Positions must run on from the last
|
|
138
|
+
* read; closing stops the decompression.
|
|
139
|
+
*/
|
|
140
|
+
function zstdReader(handle) {
|
|
141
|
+
if (!zstdSupported()) throw importError(IMPORT_ERROR_NEEDS_NEWER_NODE);
|
|
142
|
+
const decoder = zlib.createZstdDecompress();
|
|
143
|
+
pipeline(handle.createReadStream({ autoClose: false }), decoder, () => {});
|
|
144
|
+
const chunks = decoder[Symbol.asyncIterator]();
|
|
145
|
+
let rest = Buffer.alloc(0);
|
|
146
|
+
let position = 0;
|
|
147
|
+
return {
|
|
148
|
+
async read(buffer, offset, length, from) {
|
|
149
|
+
if (from !== position) throw importError('unreadable');
|
|
150
|
+
if (!rest.length) {
|
|
151
|
+
const next = await chunks.next();
|
|
152
|
+
if (next.done) return { bytesRead: 0, buffer };
|
|
153
|
+
rest = next.value;
|
|
154
|
+
}
|
|
155
|
+
const bytesRead = Math.min(length, rest.length);
|
|
156
|
+
rest.copy(buffer, offset, 0, bytesRead);
|
|
157
|
+
rest = rest.subarray(bytesRead);
|
|
158
|
+
position += bytesRead;
|
|
159
|
+
return { bytesRead, buffer };
|
|
160
|
+
},
|
|
161
|
+
async close() {
|
|
162
|
+
decoder.destroy();
|
|
163
|
+
await handle.close();
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
109
168
|
export function candidateId(source, canonicalPath) {
|
|
110
169
|
return createHash('sha256')
|
|
111
170
|
.update(`${source}\0${caseFold(canonicalPath)}`)
|
|
@@ -144,7 +203,10 @@ async function walkCodex(rootReal, dir, files, seenDirs) {
|
|
|
144
203
|
continue;
|
|
145
204
|
}
|
|
146
205
|
}
|
|
147
|
-
if (
|
|
206
|
+
if (!isRolloutName(entry.name)) continue;
|
|
207
|
+
// A compressed rollout is skipped while its plain sibling exists.
|
|
208
|
+
if (isCompressed(entry.name) && (await stat(path.slice(0, -'.zst'.length)).catch(() => null))) continue;
|
|
209
|
+
files.push(path);
|
|
148
210
|
}
|
|
149
211
|
}
|
|
150
212
|
|
|
@@ -159,6 +221,68 @@ async function walkClaude(rootReal, files) {
|
|
|
159
221
|
}
|
|
160
222
|
}
|
|
161
223
|
|
|
224
|
+
// Cowork keeps one `local_<id>.json` manifest per conversation (the account/org folders hold
|
|
225
|
+
// `local_*.json` directly, the agent variant under `agent/`), next to a `local_<id>/` folder whose
|
|
226
|
+
// `.claude/projects/<project>/<cliSessionId>.jsonl` is the Claude Code transcript. The manifest also
|
|
227
|
+
// holds the system prompt and account details, so only title / isStarred / cliSessionId are read.
|
|
228
|
+
// The agent variant (`local_ditto_*`, sessionType "agent") is the user's own Claude desktop chat
|
|
229
|
+
// (its initialMessage is user-typed), so it is listed like the others.
|
|
230
|
+
const COWORK_MANIFEST_MAX_BYTES = 8 * 1024 * 1024;
|
|
231
|
+
const COWORK_TITLE_MAX_CHARS = 200;
|
|
232
|
+
const COWORK_SESSION_ID_RE = /^[\w-]+$/;
|
|
233
|
+
|
|
234
|
+
async function coworkManifestPaths(rootReal) {
|
|
235
|
+
const manifests = [];
|
|
236
|
+
for (const account of await entriesOf(rootReal)) {
|
|
237
|
+
if (!account.isDirectory()) continue;
|
|
238
|
+
for (const org of await entriesOf(join(rootReal, account.name))) {
|
|
239
|
+
if (!org.isDirectory()) continue;
|
|
240
|
+
for (const dir of [join(rootReal, account.name, org.name), join(rootReal, account.name, org.name, 'agent')]) {
|
|
241
|
+
for (const file of await entriesOf(dir)) {
|
|
242
|
+
if (file.isFile() && /^local_.+\.json$/.test(file.name)) manifests.push(join(dir, file.name));
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return manifests;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// The transcript a manifest names, with the manifest's title and star; null when it has none.
|
|
251
|
+
async function coworkTranscript(rootReal, manifestPath) {
|
|
252
|
+
const real = await containedRealpath(rootReal, manifestPath);
|
|
253
|
+
const info = real ? await stat(real).catch(() => null) : null;
|
|
254
|
+
if (!info?.isFile() || info.size > COWORK_MANIFEST_MAX_BYTES) return null;
|
|
255
|
+
let manifest;
|
|
256
|
+
try {
|
|
257
|
+
manifest = JSON.parse(await readFile(real, 'utf8'));
|
|
258
|
+
} catch {
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
const cliSessionId = manifest?.cliSessionId;
|
|
262
|
+
if (typeof cliSessionId !== 'string' || !COWORK_SESSION_ID_RE.test(cliSessionId)) return null;
|
|
263
|
+
const projects = join(real.slice(0, -'.json'.length), '.claude', 'projects');
|
|
264
|
+
for (const project of await entriesOf(projects)) {
|
|
265
|
+
if (!project.isDirectory()) continue;
|
|
266
|
+
const path = join(projects, project.name, `${cliSessionId}.jsonl`);
|
|
267
|
+
if (await containedRealpath(rootReal, path)) {
|
|
268
|
+
const title = typeof manifest.title === 'string' ? manifest.title.trim().slice(0, COWORK_TITLE_MAX_CHARS) : '';
|
|
269
|
+
return { path, title: title || null, starred: manifest.isStarred === true };
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
async function walkCowork(rootReal, files, extras) {
|
|
276
|
+
const found = await mapBounded(await coworkManifestPaths(rootReal), STAT_CONCURRENCY, (path) =>
|
|
277
|
+
coworkTranscript(rootReal, path)
|
|
278
|
+
);
|
|
279
|
+
for (const entry of found) {
|
|
280
|
+
if (!entry) continue;
|
|
281
|
+
files.push(entry.path);
|
|
282
|
+
extras.set(entry.path, { title: entry.title, starred: entry.starred });
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
162
286
|
async function mapBounded(items, limit, fn) {
|
|
163
287
|
const out = new Array(items.length);
|
|
164
288
|
let next = 0;
|
|
@@ -175,6 +299,7 @@ async function mapBounded(items, limit, fn) {
|
|
|
175
299
|
/** Regular files under the source root, canonical and contained, as candidates. */
|
|
176
300
|
export async function enumerateCandidates(source, env = process.env) {
|
|
177
301
|
const root = sourceRoot(source, env);
|
|
302
|
+
if (!root) return { root: '', candidates: [] };
|
|
178
303
|
let rootReal;
|
|
179
304
|
try {
|
|
180
305
|
rootReal = await realpath(root);
|
|
@@ -182,13 +307,17 @@ export async function enumerateCandidates(source, env = process.env) {
|
|
|
182
307
|
return { root, candidates: [] };
|
|
183
308
|
}
|
|
184
309
|
const paths = [];
|
|
310
|
+
const extras = new Map(); // transcript path → manifest title / star (Cowork)
|
|
185
311
|
if (source === 'codex') await walkCodex(rootReal, rootReal, paths, new Set([caseFold(rootReal)]));
|
|
312
|
+
else if (source === 'cowork') await walkCowork(rootReal, paths, extras);
|
|
186
313
|
else await walkClaude(rootReal, paths);
|
|
187
314
|
const stamped = await mapBounded(paths, STAT_CONCURRENCY, async (path) => {
|
|
188
315
|
const real = await containedRealpath(rootReal, path);
|
|
189
316
|
if (!real) return null;
|
|
190
317
|
const info = await stat(real).catch(() => null);
|
|
191
|
-
return info?.isFile()
|
|
318
|
+
return info?.isFile()
|
|
319
|
+
? { path: real, size: info.size, mtimeMs: info.mtimeMs, fileId: fileIdentity(info), ...extras.get(path) }
|
|
320
|
+
: null;
|
|
192
321
|
});
|
|
193
322
|
const unique = new Map();
|
|
194
323
|
for (const file of stamped) {
|
|
@@ -205,7 +334,9 @@ function compareCodeUnits(left, right) {
|
|
|
205
334
|
return left < right ? -1 : 1;
|
|
206
335
|
}
|
|
207
336
|
|
|
337
|
+
// Starred conversations (Cowork) come first, then newest first.
|
|
208
338
|
function byModifiedThenId(left, right) {
|
|
339
|
+
if (!left.starred !== !right.starred) return left.starred ? -1 : 1;
|
|
209
340
|
if (right.mtimeMs !== left.mtimeMs) return right.mtimeMs - left.mtimeMs;
|
|
210
341
|
return compareCodeUnits(left.id, right.id);
|
|
211
342
|
}
|
|
@@ -275,7 +406,7 @@ async function openCandidate(candidate) {
|
|
|
275
406
|
) {
|
|
276
407
|
throw importError('unreadable');
|
|
277
408
|
}
|
|
278
|
-
return handle;
|
|
409
|
+
return isCompressed(candidate.path) ? zstdReader(handle) : handle;
|
|
279
410
|
} catch (error) {
|
|
280
411
|
await handle.close();
|
|
281
412
|
throw error;
|
|
@@ -351,6 +482,10 @@ async function readTailLines(handle, size) {
|
|
|
351
482
|
return (size > length ? text.slice(text.indexOf('\n') + 1) : text).split('\n');
|
|
352
483
|
}
|
|
353
484
|
|
|
485
|
+
// Whether the rollout a listed file continues is absent (a stat-only search): its own records are then all there is to name and count.
|
|
486
|
+
const baseIsMissing = async (candidate, meta) =>
|
|
487
|
+
!!meta.historyBaseId && !(await findRolloutById(dirname(candidate.root ?? sourceRoot('codex')), meta.historyBaseId));
|
|
488
|
+
|
|
354
489
|
async function readPrefixMeta(candidate) {
|
|
355
490
|
const converter = createConversationConverter(candidate.source);
|
|
356
491
|
const handle = await openCandidate(candidate);
|
|
@@ -358,7 +493,7 @@ async function readPrefixMeta(candidate) {
|
|
|
358
493
|
// nothing but sidechain messages has been seen the scan streams on, line by
|
|
359
494
|
// line, to EOF or to the import file-size limit. A file over that limit stays
|
|
360
495
|
// unclassified (listed); importing it fails as tooLarge.
|
|
361
|
-
const claude = candidate.source === 'claude';
|
|
496
|
+
const claude = candidate.source === 'claude' || candidate.source === 'cowork';
|
|
362
497
|
let read;
|
|
363
498
|
try {
|
|
364
499
|
read = await streamJsonlLines(handle, (line) => converter.pushLine(line), {
|
|
@@ -385,12 +520,14 @@ async function readPrefixMeta(candidate) {
|
|
|
385
520
|
}
|
|
386
521
|
const conversion = converter.result();
|
|
387
522
|
// A thread continuing a history base is only counted, named and judged empty once the base is followed (on import).
|
|
388
|
-
const listing = (meta) =>
|
|
389
|
-
conversion.historyBase
|
|
523
|
+
const listing = async (meta) =>
|
|
524
|
+
conversion.historyBase && !(await baseIsMissing(candidate, meta))
|
|
390
525
|
? { ...meta, title: null, messageCount: null, errorCode: meta.errorCode === 'empty' ? null : meta.errorCode }
|
|
391
|
-
:
|
|
526
|
+
: conversion.historyBase
|
|
527
|
+
? { ...meta, warnings: [...meta.warnings, IMPORT_WARNING_HISTORY_UNAVAILABLE] }
|
|
528
|
+
: meta;
|
|
392
529
|
if (read.eof) return listing(metaFromConversion(conversion, true));
|
|
393
|
-
const meta = listing(metaFromConversion(conversion, false));
|
|
530
|
+
const meta = await listing(metaFromConversion(conversion, false));
|
|
394
531
|
if (candidate.source === 'codex' && (!meta.foreignSessionId || !meta.cwd) && read.firstPartial) {
|
|
395
532
|
// A session_meta line longer than the prefix still names its id/cwd.
|
|
396
533
|
const fromLine = codexMetaFromTruncatedLine(read.firstPartial.replace(/^\uFEFF/, ''));
|
|
@@ -404,10 +541,13 @@ async function readPrefixMeta(candidate) {
|
|
|
404
541
|
// ── Codex history base chain ─────────────────────────────────────────────────
|
|
405
542
|
const HISTORY_CHAIN_MAX_DEPTH = 32;
|
|
406
543
|
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
407
|
-
const ROLLOUT_ID_RE = /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl
|
|
544
|
+
const ROLLOUT_ID_RE = /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl(?:\.zst)?$/i;
|
|
408
545
|
|
|
409
|
-
/** Rollout id a rollout file name ends with (`…-<thread>.jsonl` or `…-<thread>_<rollout>.jsonl`). */
|
|
410
|
-
const rolloutIdOf = (path) =>
|
|
546
|
+
/** Rollout id a rollout file name ends with (`…-<thread>.jsonl[.zst]` or `…-<thread>_<rollout>.jsonl[.zst]`). */
|
|
547
|
+
const rolloutIdOf = (path) => {
|
|
548
|
+
const name = basename(path);
|
|
549
|
+
return isRolloutName(name) ? (name.match(ROLLOUT_ID_RE)?.[1].toLowerCase() ?? null) : null;
|
|
550
|
+
};
|
|
411
551
|
|
|
412
552
|
const META_CHUNK_BYTES = 8 * 1024;
|
|
413
553
|
|
|
@@ -439,20 +579,34 @@ async function firstRecord(candidate, { maxBytes, maxLineBytes }) {
|
|
|
439
579
|
}
|
|
440
580
|
}
|
|
441
581
|
|
|
442
|
-
// Whether a cutoff falls on a record boundary: the end of the file or just after a line feed.
|
|
582
|
+
// Whether a cutoff, in (decompressed) file bytes, falls on a record boundary: the end of the file or just after a line feed.
|
|
443
583
|
async function endsOnRecord(candidate, end) {
|
|
444
|
-
|
|
584
|
+
const compressed = isCompressed(candidate.path);
|
|
585
|
+
if (!compressed && end === candidate.size) return true;
|
|
445
586
|
const handle = await openCandidate(candidate);
|
|
446
587
|
try {
|
|
447
588
|
const byte = Buffer.alloc(1);
|
|
448
|
-
|
|
449
|
-
|
|
589
|
+
if (!compressed) {
|
|
590
|
+
const { bytesRead } = await handle.read(byte, 0, 1, end - 1);
|
|
591
|
+
return bytesRead === 1 && byte[0] === 10;
|
|
592
|
+
}
|
|
593
|
+
// The decompressed size is unknown: read up to the cutoff, then see whether the file ends there.
|
|
594
|
+
const chunk = Buffer.allocUnsafe(IMPORT_CHUNK_BYTES);
|
|
595
|
+
let position = 0;
|
|
596
|
+
let last = 0;
|
|
597
|
+
while (position < end) {
|
|
598
|
+
const { bytesRead } = await handle.read(chunk, 0, Math.min(chunk.length, end - position), position);
|
|
599
|
+
if (!bytesRead) return false;
|
|
600
|
+
position += bytesRead;
|
|
601
|
+
last = chunk[bytesRead - 1];
|
|
602
|
+
}
|
|
603
|
+
return last === 10 || (await handle.read(byte, 0, 1, position)).bytesRead === 0;
|
|
450
604
|
} finally {
|
|
451
605
|
await handle.close();
|
|
452
606
|
}
|
|
453
607
|
}
|
|
454
608
|
|
|
455
|
-
/** The
|
|
609
|
+
/** The rollout file with this rollout id under the live, then the archived, sessions folder (walking lists a plain file instead of its compressed sibling). */
|
|
456
610
|
async function findRolloutById(home, rolloutId) {
|
|
457
611
|
for (const folder of ['sessions', 'archived_sessions']) {
|
|
458
612
|
let rootReal;
|
|
@@ -475,23 +629,43 @@ async function findRolloutById(home, rolloutId) {
|
|
|
475
629
|
return null;
|
|
476
630
|
}
|
|
477
631
|
|
|
632
|
+
// Size of a compressed file once decompressed, counting no further than `cap`.
|
|
633
|
+
async function decompressedLength(candidate, cap) {
|
|
634
|
+
const handle = await openCandidate(candidate);
|
|
635
|
+
try {
|
|
636
|
+
const chunk = Buffer.allocUnsafe(IMPORT_CHUNK_BYTES);
|
|
637
|
+
let length = 0;
|
|
638
|
+
while (length < cap) {
|
|
639
|
+
const { bytesRead } = await handle.read(chunk, 0, Math.min(chunk.length, cap - length), length);
|
|
640
|
+
if (!bytesRead) break;
|
|
641
|
+
length += bytesRead;
|
|
642
|
+
}
|
|
643
|
+
return length;
|
|
644
|
+
} finally {
|
|
645
|
+
await handle.close();
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
|
|
478
649
|
/**
|
|
479
650
|
* Rollouts a `history_base` leads to, nearest first, each with the byte offset
|
|
480
651
|
* its contribution ends at, and `metaBytes`, what reading their metadata took.
|
|
481
|
-
*
|
|
482
|
-
*
|
|
483
|
-
*
|
|
484
|
-
* does not end a record, or that would take the total read (the file, the
|
|
652
|
+
* Cutoffs and byte counts are of the decompressed rollout. Stops (`partial`,
|
|
653
|
+
* the warning code saying why) at a base that is missing or unreadable
|
|
654
|
+
* (`historyUnavailable`), that would take the total read (the file, the
|
|
485
655
|
* `spent` metadata reads so far, every cutoff and every metadata read) beyond
|
|
486
|
-
* `maxFileBytes
|
|
656
|
+
* `maxFileBytes` (`historySizeLimit`), or is not paginated, already visited,
|
|
657
|
+
* past the depth cap, with a cutoff that excludes the session metadata,
|
|
658
|
+
* passes the end of the file or does not end a record (`historyPartial`).
|
|
487
659
|
*/
|
|
488
660
|
async function resolveHistoryChain(candidate, firstBase, { maxFileBytes, maxLineBytes, spent }) {
|
|
489
661
|
const home = dirname(candidate.root ?? sourceRoot('codex'));
|
|
490
662
|
const seen = new Set([rolloutIdOf(candidate.path)]);
|
|
491
663
|
const segments = [];
|
|
492
|
-
|
|
664
|
+
// The file itself is reserved at its decompressed size, which only reading it tells.
|
|
665
|
+
let used =
|
|
666
|
+
(isCompressed(candidate.path) ? await decompressedLength(candidate, maxFileBytes) : candidate.size) + spent;
|
|
493
667
|
let metaBytes = 0;
|
|
494
|
-
const partial = () => ({ segments, partial:
|
|
668
|
+
const partial = (warning = IMPORT_WARNING_HISTORY_PARTIAL) => ({ segments, partial: warning, metaBytes });
|
|
495
669
|
for (let base = firstBase; base; ) {
|
|
496
670
|
const id = typeof base.thread_id === 'string' ? base.thread_id.toLowerCase() : '';
|
|
497
671
|
const end = base.end_byte_offset;
|
|
@@ -500,13 +674,20 @@ async function resolveHistoryChain(candidate, firstBase, { maxFileBytes, maxLine
|
|
|
500
674
|
seen.add(id);
|
|
501
675
|
if (!Number.isSafeInteger(ordinal) || ordinal <= 0 || !Number.isSafeInteger(end) || end <= 0) return partial();
|
|
502
676
|
const found = await findRolloutById(home, id);
|
|
503
|
-
if (!found
|
|
677
|
+
if (!found) return partial(IMPORT_WARNING_HISTORY_UNAVAILABLE);
|
|
678
|
+
if (!isCompressed(found.path) && end > found.size) return partial();
|
|
679
|
+
if (used + end > maxFileBytes) return partial(IMPORT_WARNING_HISTORY_SIZE_LIMIT);
|
|
504
680
|
let head;
|
|
505
681
|
try {
|
|
506
682
|
if (!(await endsOnRecord(found, end))) return partial();
|
|
507
683
|
head = await firstRecord(found, { maxBytes: Math.min(end, maxFileBytes - used - end), maxLineBytes });
|
|
508
|
-
} catch {
|
|
509
|
-
|
|
684
|
+
} catch (error) {
|
|
685
|
+
// A runtime without zstd names its own fix; any other failure to open or read the base is "unavailable".
|
|
686
|
+
return partial(
|
|
687
|
+
error?.code === IMPORT_ERROR_NEEDS_NEWER_NODE
|
|
688
|
+
? IMPORT_ERROR_NEEDS_NEWER_NODE
|
|
689
|
+
: IMPORT_WARNING_HISTORY_UNAVAILABLE
|
|
690
|
+
);
|
|
510
691
|
}
|
|
511
692
|
used += end + head.bytes;
|
|
512
693
|
metaBytes += head.bytes;
|
|
@@ -515,7 +696,7 @@ async function resolveHistoryChain(candidate, firstBase, { maxFileBytes, maxLine
|
|
|
515
696
|
const next = head.record.payload.history_base;
|
|
516
697
|
base = next && typeof next === 'object' ? next : null;
|
|
517
698
|
}
|
|
518
|
-
return { segments, partial:
|
|
699
|
+
return { segments, partial: null, metaBytes };
|
|
519
700
|
}
|
|
520
701
|
|
|
521
702
|
/**
|
|
@@ -524,8 +705,10 @@ async function resolveHistoryChain(candidate, firstBase, { maxFileBytes, maxLine
|
|
|
524
705
|
* converter's limits fails the file with `tooLarge` without reading the rest.
|
|
525
706
|
* A Codex rollout continuing a `history_base` is preceded by the records of
|
|
526
707
|
* each base up to its cutoff, oldest first (their session metadata dropped),
|
|
527
|
-
* all within the one `maxFileBytes
|
|
528
|
-
*
|
|
708
|
+
* all within the one `maxFileBytes` (counted in decompressed bytes for a
|
|
709
|
+
* compressed rollout); a base that cannot be followed leaves a `historyPartial`,
|
|
710
|
+
* `historySizeLimit` or `historyUnavailable` warning. `bytesRead` is how far
|
|
711
|
+
* the read got.
|
|
529
712
|
*/
|
|
530
713
|
export async function convertCandidateFile(
|
|
531
714
|
candidate,
|
|
@@ -553,10 +736,10 @@ export async function convertCandidateFile(
|
|
|
553
736
|
const chain =
|
|
554
737
|
head.record.payload.history_mode === 'paginated'
|
|
555
738
|
? await resolveHistoryChain(candidate, base, { maxFileBytes, maxLineBytes, spent: inheritedBytes })
|
|
556
|
-
: { segments: [], partial:
|
|
739
|
+
: { segments: [], partial: IMPORT_WARNING_HISTORY_PARTIAL, metaBytes: 0 };
|
|
557
740
|
inheritedBytes += chain.metaBytes;
|
|
558
741
|
const { segments, partial } = chain;
|
|
559
|
-
if (partial) converter.markHistoryPartial();
|
|
742
|
+
if (partial) converter.markHistoryPartial(partial);
|
|
560
743
|
for (const { candidate: baseFile, end } of segments.reverse()) {
|
|
561
744
|
const baseHandle = await openCandidate(baseFile);
|
|
562
745
|
try {
|
|
@@ -587,12 +770,22 @@ export async function convertCandidateFile(
|
|
|
587
770
|
}
|
|
588
771
|
}
|
|
589
772
|
|
|
773
|
+
// On a runtime without zstd, a listed conversation whose history base is compressed says so on its row.
|
|
774
|
+
async function withCompressedBaseNotice(candidate, meta) {
|
|
775
|
+
if (!meta.historyBaseId || zstdSupported()) return meta;
|
|
776
|
+
const found = await findRolloutById(dirname(candidate.root ?? sourceRoot('codex')), meta.historyBaseId);
|
|
777
|
+
return found && isCompressed(found.path)
|
|
778
|
+
? { ...meta, warnings: [...meta.warnings, IMPORT_ERROR_NEEDS_NEWER_NODE] }
|
|
779
|
+
: meta;
|
|
780
|
+
}
|
|
781
|
+
|
|
590
782
|
function pumpMetaQueue() {
|
|
591
783
|
while (state.active < META_CONCURRENCY && state.queue.length) {
|
|
592
784
|
const job = state.queue.shift();
|
|
593
785
|
state.active += 1;
|
|
594
786
|
readPrefixMeta(job.candidate)
|
|
595
|
-
.
|
|
787
|
+
.then((meta) => withCompressedBaseNotice(job.candidate, meta))
|
|
788
|
+
.catch((error) => ({
|
|
596
789
|
foreignSessionId: null,
|
|
597
790
|
cwd: null,
|
|
598
791
|
title: null,
|
|
@@ -600,7 +793,7 @@ function pumpMetaQueue() {
|
|
|
600
793
|
historyBaseId: null,
|
|
601
794
|
messageCount: null,
|
|
602
795
|
warnings: [],
|
|
603
|
-
errorCode: 'unreadable',
|
|
796
|
+
errorCode: error?.code === IMPORT_ERROR_NEEDS_NEWER_NODE ? IMPORT_ERROR_NEEDS_NEWER_NODE : 'unreadable',
|
|
604
797
|
}))
|
|
605
798
|
.then((value) => {
|
|
606
799
|
state.meta.set(job.candidate.path, { stampKey: stampKey(job.candidate), value });
|
|
@@ -675,7 +868,8 @@ function rowFor(candidate, meta, cwdInfo, imported, titles) {
|
|
|
675
868
|
return {
|
|
676
869
|
id: candidate.id,
|
|
677
870
|
source: candidate.source,
|
|
678
|
-
title: displayTitle(meta, titles),
|
|
871
|
+
title: displayTitle(meta, titles, candidate.title),
|
|
872
|
+
starred: candidate.starred === true,
|
|
679
873
|
cwd: cwdInfo?.path ?? null,
|
|
680
874
|
modifiedAt: candidate.mtimeMs,
|
|
681
875
|
messageCount: meta?.messageCount ?? null,
|
|
@@ -684,7 +878,7 @@ function rowFor(candidate, meta, cwdInfo, imported, titles) {
|
|
|
684
878
|
};
|
|
685
879
|
}
|
|
686
880
|
|
|
687
|
-
|
|
881
|
+
async function buildRow(candidate, imported, cwdCache = new Map(), titles = null) {
|
|
688
882
|
const meta = cachedMeta(candidate);
|
|
689
883
|
const cwdInfo = meta?.cwd ? await resolveSourceCwd(meta.cwd, cwdCache) : null;
|
|
690
884
|
return rowFor(candidate, meta, cwdInfo, imported, titles);
|
|
@@ -828,7 +1022,10 @@ async function filterCandidates(candidates, filters, imported, titles) {
|
|
|
828
1022
|
const cwdInfo = meta.cwd ? await resolveSourceCwd(meta.cwd, cwdCache) : null;
|
|
829
1023
|
if (
|
|
830
1024
|
needle &&
|
|
831
|
-
!(
|
|
1025
|
+
!(
|
|
1026
|
+
foldText(displayTitle(meta, titles, candidate.title)).includes(needle) ||
|
|
1027
|
+
foldText(cwdInfo?.path).includes(needle)
|
|
1028
|
+
)
|
|
832
1029
|
) {
|
|
833
1030
|
continue;
|
|
834
1031
|
}
|
|
@@ -903,7 +1100,7 @@ export async function resolveViewSelection(viewId, excludeIds, imported) {
|
|
|
903
1100
|
}
|
|
904
1101
|
|
|
905
1102
|
// ── picked files ─────────────────────────────────────────────────────────────
|
|
906
|
-
/** Validate and register a file chosen in a native picker (a local regular .jsonl). */
|
|
1103
|
+
/** Validate and register a file chosen in a native picker (a local regular .jsonl, or a Codex .jsonl.zst). */
|
|
907
1104
|
export async function registerFile({ source, path } = {}, { imported, limits, env = process.env } = {}) {
|
|
908
1105
|
requireSource(source);
|
|
909
1106
|
if (typeof path !== 'string' || !path.trim() || path.includes('\0')) throw importError('invalidPath');
|
|
@@ -911,7 +1108,8 @@ export async function registerFile({ source, path } = {}, { imported, limits, en
|
|
|
911
1108
|
// Network/device forms are refused before any filesystem call.
|
|
912
1109
|
if (isNetworkOrDevicePath(requested)) throw importError('unsupported');
|
|
913
1110
|
if (!isAbsolute(requested)) throw importError('invalidPath');
|
|
914
|
-
|
|
1111
|
+
const pickable = (path) => /\.jsonl$/i.test(path) || (source === 'codex' && isCompressed(path));
|
|
1112
|
+
if (!pickable(basename(requested))) throw importError('unsupported');
|
|
915
1113
|
let real;
|
|
916
1114
|
let info;
|
|
917
1115
|
try {
|
|
@@ -920,7 +1118,7 @@ export async function registerFile({ source, path } = {}, { imported, limits, en
|
|
|
920
1118
|
} catch {
|
|
921
1119
|
throw importError('unreadable');
|
|
922
1120
|
}
|
|
923
|
-
if (isNetworkOrDevicePath(real) || !info.isFile() ||
|
|
1121
|
+
if (isNetworkOrDevicePath(real) || !info.isFile() || !pickable(basename(real))) {
|
|
924
1122
|
throw importError('unsupported');
|
|
925
1123
|
}
|
|
926
1124
|
const candidate = registerCandidate({
|
|
@@ -935,8 +1133,8 @@ export async function registerFile({ source, path } = {}, { imported, limits, en
|
|
|
935
1133
|
let conversion;
|
|
936
1134
|
try {
|
|
937
1135
|
conversion = await convertCandidateFile(candidate, limits);
|
|
938
|
-
} catch {
|
|
939
|
-
throw importError('unreadable');
|
|
1136
|
+
} catch (error) {
|
|
1137
|
+
throw importError(error?.code === IMPORT_ERROR_NEEDS_NEWER_NODE ? IMPORT_ERROR_NEEDS_NEWER_NODE : 'unreadable');
|
|
940
1138
|
}
|
|
941
1139
|
if (conversion.errorCode) throw importError(conversion.errorCode);
|
|
942
1140
|
recordConversion(candidate, conversion);
|
|
@@ -20,7 +20,10 @@ import {
|
|
|
20
20
|
createImportedSession,
|
|
21
21
|
importOriginKey,
|
|
22
22
|
} from '../../runtime/agent/orchestrator/session/conversation-import/imported-session.mjs';
|
|
23
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
IMPORT_ERROR_NEEDS_NEWER_NODE,
|
|
25
|
+
IMPORT_WARNING_CWD_MISSING,
|
|
26
|
+
} from '../../runtime/agent/orchestrator/session/conversation-import/turns.mjs';
|
|
24
27
|
import { sessionPath } from '../../runtime/agent/orchestrator/session/store/session-paths.mjs';
|
|
25
28
|
import {
|
|
26
29
|
cachedMeta,
|
|
@@ -140,7 +143,7 @@ const titlesFor = (candidate, context) => (candidate.source === 'codex' ? contex
|
|
|
140
143
|
function describeCandidate(candidateId, context) {
|
|
141
144
|
const candidate = getCandidate(candidateId);
|
|
142
145
|
return {
|
|
143
|
-
title: candidate ? displayTitle(cachedMeta(candidate), titlesFor(candidate, context)) : null,
|
|
146
|
+
title: candidate ? displayTitle(cachedMeta(candidate), titlesFor(candidate, context), candidate.title) : null,
|
|
144
147
|
sourceName: candidate ? basename(candidate.path) : null,
|
|
145
148
|
};
|
|
146
149
|
}
|
|
@@ -185,12 +188,16 @@ async function importOne(candidateId, context) {
|
|
|
185
188
|
candidate.size = info.size;
|
|
186
189
|
candidate.mtimeMs = info.mtimeMs;
|
|
187
190
|
conversion = await convertCandidateFile(candidate, context.limits);
|
|
188
|
-
} catch {
|
|
189
|
-
return failed(
|
|
191
|
+
} catch (error) {
|
|
192
|
+
return failed(
|
|
193
|
+
candidateId,
|
|
194
|
+
error?.code === IMPORT_ERROR_NEEDS_NEWER_NODE ? IMPORT_ERROR_NEEDS_NEWER_NODE : 'unreadable'
|
|
195
|
+
);
|
|
190
196
|
}
|
|
191
197
|
const title = displayTitle(
|
|
192
198
|
{ foreignSessionId: conversion.foreignSessionId, title: listedTitle || conversion.title },
|
|
193
|
-
titlesFor(candidate, context)
|
|
199
|
+
titlesFor(candidate, context),
|
|
200
|
+
candidate.title
|
|
194
201
|
);
|
|
195
202
|
if (title) conversion = { ...conversion, title };
|
|
196
203
|
recordConversion(candidate, conversion);
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import { markPendingGoalReminder } from '../runtime/agent/orchestrator/runtime-core/goal-reminder.mjs';
|
|
2
|
+
import { adoptLegacyGoalTasks, todoContextBlock } from '../runtime/agent/orchestrator/runtime-core/todo-list.mjs';
|
|
3
|
+
import { SAVE_OUTCOME_SAVED } from '../runtime/agent/orchestrator/session/store/live-state.mjs';
|
|
2
4
|
|
|
3
|
-
export function createGoalFacadeApi({
|
|
5
|
+
export function createGoalFacadeApi({
|
|
6
|
+
agentStatusState,
|
|
7
|
+
createCurrentSession,
|
|
8
|
+
getSession,
|
|
9
|
+
getSessionId,
|
|
10
|
+
goalRuntime,
|
|
11
|
+
persistSession,
|
|
12
|
+
}) {
|
|
4
13
|
const markGoalReminder = (reason = '') => {
|
|
5
14
|
try {
|
|
6
15
|
const pending = markPendingGoalReminder(getSession(), reason);
|
|
@@ -14,10 +23,39 @@ export function createGoalFacadeApi({ agentStatusState, createCurrentSession, ge
|
|
|
14
23
|
return null;
|
|
15
24
|
}
|
|
16
25
|
};
|
|
26
|
+
// A Goal record written before the todo list still carries its tasks: the
|
|
27
|
+
// session's list adopts them, and only once that session is saved does the
|
|
28
|
+
// record let them go. A failed save keeps them on the record, so the next
|
|
29
|
+
// load adopts again (items already listed are skipped, never duplicated).
|
|
30
|
+
const adopting = new Map();
|
|
31
|
+
const adoptLegacyTasks = (sessionId) => {
|
|
32
|
+
if (adopting.has(sessionId)) return adopting.get(sessionId);
|
|
33
|
+
const tasks = goalRuntime.legacyTasks?.(sessionId) || [];
|
|
34
|
+
if (!tasks.length) return null;
|
|
35
|
+
const session = getSession();
|
|
36
|
+
if (session?.id !== sessionId) return null;
|
|
37
|
+
adoptLegacyGoalTasks(session, tasks);
|
|
38
|
+
const adoption = (async () => {
|
|
39
|
+
try {
|
|
40
|
+
// Only an explicit committed write lets the record go: a dropped or
|
|
41
|
+
// stale save resolves too, without the list on disk.
|
|
42
|
+
if ((await persistSession(session)) !== SAVE_OUTCOME_SAVED) return;
|
|
43
|
+
await goalRuntime.clearLegacyTasks(sessionId);
|
|
44
|
+
} catch {
|
|
45
|
+
// Kept on the record; retried on the next load.
|
|
46
|
+
} finally {
|
|
47
|
+
adopting.delete(sessionId);
|
|
48
|
+
}
|
|
49
|
+
})();
|
|
50
|
+
adopting.set(sessionId, adoption);
|
|
51
|
+
return adoption;
|
|
52
|
+
};
|
|
17
53
|
return {
|
|
18
54
|
goalStatus() {
|
|
19
55
|
const sessionId = getSessionId();
|
|
20
|
-
|
|
56
|
+
if (!sessionId) return null;
|
|
57
|
+
adoptLegacyTasks(sessionId);
|
|
58
|
+
return goalRuntime.snapshot(sessionId);
|
|
21
59
|
},
|
|
22
60
|
async goalControl(args = {}) {
|
|
23
61
|
let sessionId = getSessionId();
|
|
@@ -31,10 +69,18 @@ export function createGoalFacadeApi({ agentStatusState, createCurrentSession, ge
|
|
|
31
69
|
return result;
|
|
32
70
|
},
|
|
33
71
|
markGoalReminder,
|
|
72
|
+
/** Settles once a legacy Goal record's tasks are adopted and saved (or kept after a failed save). */
|
|
73
|
+
adoptLegacyGoalTasks(sessionId = getSessionId()) {
|
|
74
|
+
return Promise.resolve(sessionId ? adoptLegacyTasks(sessionId) : null);
|
|
75
|
+
},
|
|
34
76
|
goalContinuation() {
|
|
35
77
|
const sessionId = getSessionId();
|
|
36
78
|
if (!sessionId) return { run: false, reason: 'missing-session', goal: null };
|
|
37
|
-
|
|
79
|
+
adoptLegacyTasks(sessionId);
|
|
80
|
+
return goalRuntime.continuation(sessionId, {
|
|
81
|
+
agentStatus: agentStatusState(),
|
|
82
|
+
todo: todoContextBlock(getSession(), 'Todo list for this Goal (exact wordings):', { whole: true }),
|
|
83
|
+
});
|
|
38
84
|
},
|
|
39
85
|
goalTurnStarted() {
|
|
40
86
|
const sessionId = getSessionId();
|
|
@@ -523,7 +523,7 @@ export function turnSlice(messages, { runId = '', since = 0 } = {}) {
|
|
|
523
523
|
* what its final reply names, then media/office/visualize outputs, then the
|
|
524
524
|
* files it edited. `written`: only the files it created or modified (no
|
|
525
525
|
* reply paths, no visualize open targets). */
|
|
526
|
-
|
|
526
|
+
function turnArtifactCandidates(messages, { written = false } = {}) {
|
|
527
527
|
const list = Array.isArray(messages) ? messages : [];
|
|
528
528
|
const reply = list.findLast((message) => message?.role === 'assistant' && textOf(message.content).trim());
|
|
529
529
|
const produced = [];
|