mixdog 1.4.0 → 1.4.2
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 +3 -2
- package/scripts/build-shipped-history.mjs +115 -33
- package/scripts/check-voice-runtime-inputs.mjs +25 -0
- package/scripts/gate-local.mjs +183 -63
- package/scripts/latest-guard.mjs +21 -9
- package/scripts/lib/gate-scheduler.mjs +138 -32
- package/scripts/lib/gate-timing-reporter.mjs +16 -0
- package/scripts/lib/isolated-test-env.mjs +10 -5
- package/scripts/lib/run-node-tests.mjs +91 -66
- package/scripts/lib/scoped-temp.d.mts +16 -0
- package/scripts/lib/scoped-temp.mjs +124 -0
- package/scripts/lib/stale-temp.mjs +44 -0
- package/scripts/lib/test-failure-records.mjs +14 -1
- package/scripts/lib/test-failure-summary.mjs +16 -4
- package/scripts/lib/test-spawn-ledger.mjs +12 -3
- package/scripts/post-release-check.mjs +1 -6
- package/scripts/pptx-kit-index.mjs +17 -5
- package/scripts/suite-health.mjs +115 -24
- package/scripts/test-data-dir.mjs +10 -7
- 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/app.mjs +4 -0
- package/src/cli.mjs +7 -0
- package/src/defaults/agents.json +7 -0
- package/src/defaults/shipped-history.json +23 -2
- package/src/defaults/skills/browser-use/SKILL.md +10 -5
- 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 +16 -4
- package/src/defaults/skills/goal-management/SKILL.md +1 -1
- package/src/defaults/skills/setup/references/actions.md +12 -6
- package/src/defaults/skills/setup/references/surfaces.md +2 -2
- package/src/defaults/skills/setup-guide/SKILL.md +5 -2
- 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/rules-builder.cjs +35 -42
- package/src/output-styles/common.md +2 -2
- package/src/output-styles/simple.md +1 -1
- package/src/rules/agent/AGENT.md +5 -4
- package/src/rules/lead/LEAD.md +12 -7
- package/src/rules/shared/10-tool-workflow.md +3 -1
- package/src/rules/shared/20-research.md +3 -6
- package/src/rules/shared/40-editing.md +1 -0
- package/src/rules/shared/45-destructive.md +0 -2
- package/src/rules/shared/50-execution.md +2 -0
- package/src/rules/shared/60-verification.md +10 -9
- package/src/rules/shared/70-delivery.md +8 -9
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/abort-link.mjs +5 -1
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +10 -1
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +156 -24
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +13 -0
- package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +4 -1
- package/src/runtime/agent/orchestrator/cache-break-trace.mjs +2 -0
- package/src/runtime/agent/orchestrator/config.mjs +12 -7
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +8 -8
- package/src/runtime/agent/orchestrator/context/role-instructions.mjs +5 -26
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +3 -1
- package/src/runtime/agent/orchestrator/internal-agents.mjs +3 -14
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +122 -12
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +5 -3
- package/src/runtime/agent/orchestrator/mcp/client-config.mjs +13 -2
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +152 -58
- package/src/runtime/agent/orchestrator/mcp/client.mjs +51 -18
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +88 -54
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +42 -26
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +54 -8
- package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +37 -31
- package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +8 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +6 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +2 -2
- 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-oauth-request/initial-status.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +14 -3
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +6 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +2 -2
- 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-login.mjs +1 -10
- package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +3 -0
- 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/devin.mjs +3 -0
- 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/grok-oauth-login.mjs +248 -41
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-prefix-trace.mjs +76 -11
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +45 -6
- package/src/runtime/agent/orchestrator/providers/lib/first-output-window.mjs +58 -0
- package/src/runtime/agent/orchestrator/providers/lib/listen-on.mjs +14 -0
- 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-login.mjs +1 -10
- 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-chat-send.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +14 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +4 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +5 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +16 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +13 -3
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +13 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +81 -42
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +8 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +160 -31
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +22 -12
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +49 -22
- 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 +45 -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 +567 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +41 -13
- package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +2 -0
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +8 -6
- package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +7 -3
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +6 -1
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +14 -5
- package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -0
- package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +5 -2
- 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/cache/scoped-cache.mjs +1 -3
- package/src/runtime/agent/orchestrator/session/cache-warm.mjs +102 -12
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -8
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +23 -0
- package/src/runtime/agent/orchestrator/session/compact/observation-supersession.mjs +103 -23
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +160 -36
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +13 -1
- package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +164 -23
- package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +139 -19
- package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +38 -7
- package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +100 -22
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -3
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -6
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +33 -3
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +9 -2
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +13 -5
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +14 -0
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +13 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +23 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +23 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +39 -21
- package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +13 -8
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +50 -28
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/manager/route-fallback-chain.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +30 -13
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +63 -6
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +7 -0
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +35 -13
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +24 -14
- 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 +10 -6
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +56 -29
- package/src/runtime/agent/orchestrator/session/manager/turn-reap.mjs +125 -0
- package/src/runtime/agent/orchestrator/session/mixy-name.mjs +11 -5
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/prompt-cache-touch-store.mjs +30 -7
- package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +154 -0
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +7 -0
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +37 -8
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +252 -39
- package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +163 -64
- package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +164 -4
- package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +142 -18
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +61 -2
- package/src/runtime/agent/orchestrator/stall-policy.mjs +23 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +6 -1
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +46 -20
- package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +67 -31
- package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +25 -13
- package/src/runtime/agent/orchestrator/tools/builtin/lib/scoped-search-flight.mjs +9 -5
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +58 -20
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-stream.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +6 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-dispatch.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-publication.mjs +23 -12
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-snapshot.mjs +6 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +1 -8
- package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +20 -15
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +96 -20
- package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +59 -10
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/federation.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
- package/src/runtime/agent/orchestrator/tools/lib/isolated-test-env.mjs +4 -3
- 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 +103 -13
- 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 +34 -10
- package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +28 -4
- package/src/runtime/agent/orchestrator/tools/lib/wait-until-fixture.mjs +26 -0
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -2
- package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
- package/src/runtime/channels/lib/webhook/signature.mjs +4 -1
- package/src/runtime/channels/lib/whisper-port.mjs +29 -11
- package/src/runtime/channels/lib/whisper-server.mjs +10 -1
- package/src/runtime/computer-bridge/action-schema.mjs +2 -2
- package/src/runtime/computer-bridge/core-actions.mjs +2 -2
- package/src/runtime/computer-bridge/error-recovery.mjs +5 -4
- package/src/runtime/computer-bridge/linux-action-capabilities.mjs +24 -5
- package/src/runtime/computer-bridge/linux-readiness.d.mts +7 -2
- package/src/runtime/connectors/connector-accounts-mcp.mjs +236 -103
- package/src/runtime/connectors/gmail-app-password.mjs +3 -3
- package/src/runtime/explore/explorer.mjs +93 -0
- package/src/runtime/explore/tool-defs.mjs +35 -0
- package/src/runtime/explore/tool.mjs +123 -0
- package/src/runtime/local-provider/server-process.mjs +2 -1
- package/src/runtime/media/adapters/gemini-video.mjs +4 -1
- package/src/runtime/media/adapters/xai-media.mjs +2 -1
- package/src/runtime/memory/index.mjs +4 -0
- package/src/runtime/memory/lib/embedding-provider.mjs +4 -1
- package/src/runtime/memory/lib/embedding-worker.mjs +10 -3
- package/src/runtime/memory/lib/memory-action-handlers/cycle-backfill-action.mjs +1 -7
- package/src/runtime/memory/lib/memory-chunk-quality.mjs +1 -6
- package/src/runtime/office/authoring/pdf-author-action.mjs +1 -6
- package/src/runtime/office/design/design-art-direction.mjs +29 -27
- package/src/runtime/office/pdf/pdf-writer.mjs +6 -1
- package/src/runtime/office/portable/portable-snapshot-docx.mjs +7 -1
- package/src/runtime/office/portable/portable-snapshot-shared.mjs +6 -1
- package/src/runtime/office/quality/assurance-rendered.mjs +9 -2
- package/src/runtime/office/quality/assurance-structure-docx.mjs +4 -2
- package/src/runtime/office/quality/design-review.mjs +1 -5
- package/src/runtime/office/quality/document-brief.mjs +1 -5
- package/src/runtime/office/quality/forced-break-pages.mjs +9 -6
- package/src/runtime/office/quality/quality-pipeline.mjs +1 -1
- package/src/runtime/shared/agent-route-config.mjs +17 -2
- package/src/runtime/shared/atomic-file.mjs +103 -2
- package/src/runtime/shared/background-tasks.mjs +15 -6
- package/src/runtime/shared/bot-owned-work.mjs +56 -0
- package/src/runtime/shared/connector-accounts.mjs +5 -5
- package/src/runtime/shared/connector-catalog.d.mts +11 -4
- package/src/runtime/shared/connector-catalog.mjs +60 -52
- package/src/runtime/shared/custom-provider-keys.mjs +20 -0
- package/src/runtime/shared/defaults-separation.mjs +1 -4
- package/src/runtime/shared/fetch-safe-listen.d.mts +16 -0
- package/src/runtime/shared/fetch-safe-listen.mjs +50 -0
- package/src/runtime/shared/file-has-data.mjs +26 -2
- package/src/runtime/shared/file-lock.mjs +13 -15
- 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/handoff-artifacts.d.mts +2 -1
- package/src/runtime/shared/handoff-artifacts.mjs +18 -8
- package/src/runtime/shared/idle-auto-clear-gate.mjs +29 -7
- package/src/runtime/shared/llm/cost.mjs +11 -2
- package/src/runtime/shared/llm/http-agent.mjs +313 -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 +452 -0
- package/src/runtime/shared/loopback-listener.mjs +25 -2
- package/src/runtime/shared/model-route-chain.d.mts +7 -2
- package/src/runtime/shared/model-route-chain.mjs +22 -4
- package/src/runtime/shared/open-url.mjs +10 -0
- package/src/runtime/shared/provider-accounts.mjs +52 -2
- package/src/runtime/shared/session-activity-signal.mjs +14 -0
- package/src/runtime/shared/session-scratch.mjs +37 -0
- 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/agent-surface.mjs +1 -3
- package/src/runtime/shared/tool-card-model/card-status.mjs +15 -2
- package/src/runtime/shared/tool-result-summary.mjs +1 -1
- package/src/runtime/shared/tool-surface.mjs +113 -36
- package/src/runtime/shared/tool-work-units.mjs +6 -0
- package/src/runtime/shared/turn-snapshot-store.mjs +13 -6
- package/src/runtime/shared/turn-worktree-snapshot.mjs +414 -54
- 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 +9 -3
- package/src/runtime/shared/worktrees/contract.mjs +4 -1
- package/src/runtime/shared/worktrees/git.mjs +72 -0
- package/src/runtime/shared/worktrees/manager.mjs +285 -168
- package/src/runtime/shared/worktrees/test-support.mjs +6 -10
- package/src/runtime/tidy/install.mjs +95 -15
- package/src/runtime/tidy/languages.mjs +17 -15
- package/src/runtime/tidy/process.mjs +7 -4
- 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 +6 -1
- package/src/runtime/visualize-bridge/tool-defs.mjs +7 -2
- package/src/runtime/web-search/index.mjs +1 -1
- package/src/session-runtime/agent-home-delivery.mjs +41 -0
- package/src/session-runtime/agent-task-sessions.mjs +458 -312
- package/src/session-runtime/agent-tool-routing.mjs +8 -41
- package/src/session-runtime/boot/tools.mjs +7 -1
- package/src/session-runtime/bot-status.mjs +107 -101
- package/src/session-runtime/bot-target.mjs +38 -0
- package/src/session-runtime/channel-config-api.mjs +6 -1
- package/src/session-runtime/connector-merge-migration.mjs +18 -15
- package/src/session-runtime/conversation-import/codex-titles.mjs +88 -0
- package/src/session-runtime/conversation-import/discovery.mjs +401 -36
- package/src/session-runtime/conversation-import/service.mjs +35 -8
- package/src/session-runtime/handoff-attachments.mjs +82 -31
- package/src/session-runtime/held-requests.mjs +3 -1
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +12 -13
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +1 -0
- package/src/session-runtime/internal-tool-executor/feature-tools.mjs +2 -0
- package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +8 -0
- package/src/session-runtime/internal-tool-executor/reaction-tool.mjs +4 -1
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +145 -112
- package/src/session-runtime/lifecycle/cold-heir.mjs +11 -6
- package/src/session-runtime/lifecycle/session-catalog.mjs +9 -1
- package/src/session-runtime/lifecycle/teardown/session-close.mjs +6 -1
- package/src/session-runtime/lifecycle/teardown.mjs +1 -1
- package/src/session-runtime/mcp-glue/server-catalog.mjs +16 -10
- 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 +11 -2
- package/src/session-runtime/provider-auth/login.mjs +2 -2
- package/src/session-runtime/provider-catalog-cache.mjs +82 -36
- package/src/session-runtime/provider-models/catalog-load.mjs +23 -6
- package/src/session-runtime/provider-models.mjs +4 -2
- package/src/session-runtime/resource-mcp-api.mjs +98 -35
- package/src/session-runtime/resource-mcp-connector-accounts.mjs +44 -31
- package/src/session-runtime/resource-mcp-secrets.mjs +28 -11
- package/src/session-runtime/resource-mcp-servers.mjs +5 -4
- package/src/session-runtime/resource-recall-api.mjs +6 -1
- package/src/session-runtime/runtime-feature-gates.mjs +5 -1
- package/src/session-runtime/services/agent-tool/execute.mjs +14 -9
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +20 -4
- package/src/session-runtime/services/agent-tool/model-select.mjs +48 -7
- package/src/session-runtime/services/agent-tool/render.mjs +71 -17
- package/src/session-runtime/services/agent-tool/send-flow.mjs +10 -2
- 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 +4 -1
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +6 -2
- package/src/session-runtime/services/agent-tool/tool-def.mjs +9 -9
- package/src/session-runtime/services/agent-watchdog-registry.mjs +32 -4
- 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/memory-runtime-proxy/daemon-spawn.mjs +4 -0
- package/src/session-runtime/services/plugin-admin.mjs +10 -6
- package/src/session-runtime/services/provider-admin.mjs +283 -11
- package/src/session-runtime/session-turn-api.mjs +2 -0
- package/src/session-runtime/settings-builtin-tools-api.mjs +4 -1
- 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 +6 -2
- package/src/session-runtime/setup-tool/tool-defs.mjs +2 -1
- package/src/session-runtime/tool-policy/policy-stage.mjs +1 -0
- package/src/session-runtime/turn/agent-ops.mjs +23 -0
- package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +49 -11
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +5 -1
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +25 -5
- package/src/session-runtime/workflow-agents-api/onboarding.mjs +3 -3
- package/src/session-runtime/workspace/activity-guards.mjs +176 -0
- 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 +108 -1041
- 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 +80 -0
- package/src/session-runtime/workspace/worktree-setup.mjs +85 -0
- package/src/session-runtime/workspace/worktree-tool.mjs +73 -56
- package/src/standalone/daemon-desktop-runtime.mjs +2 -0
- package/src/standalone/daemon-session-control.mjs +169 -138
- package/src/standalone/daemon.mjs +7 -0
- package/src/standalone/desktop-service-registry.mjs +9 -0
- package/src/standalone/local-session-runtime.mjs +5 -1
- package/src/standalone/session-client/daemon-unavailable.mjs +3 -0
- package/src/standalone/session-client.mjs +5 -1
- package/src/standalone/session-frame-stream.mjs +83 -11
- package/src/standalone/session-protocol.mjs +4 -0
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +16 -12
- 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/session-calls/session-action.mjs +10 -3
- package/src/standalone/session-service/session-calls/session-views.mjs +160 -104
- package/src/standalone/session-service/stored-reader.mjs +127 -40
- package/src/standalone/session-transport/client-registry/client-grace.mjs +12 -9
- package/src/tui/App.jsx +154 -164
- package/src/tui/app/app-view/floating-panel.jsx +10 -4
- package/src/tui/app/app-view/text-entry-labels.mjs +1 -0
- package/src/tui/app/clipboard.mjs +21 -10
- package/src/tui/app/model-picker/route-selection/fast-parameters.mjs +1 -3
- package/src/tui/app/model-picker/route-selection.mjs +5 -6
- 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 +58 -21
- package/src/tui/app/provider-setup/provider-items.mjs +8 -2
- package/src/tui/app/provider-setup-picker.mjs +29 -18
- package/src/tui/app/shell-layout/row-budgets.mjs +12 -10
- package/src/tui/app/slash-commands.mjs +1 -0
- package/src/tui/app/slash-dispatch/session-commands.mjs +46 -0
- 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 +3 -2
- 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 +47 -32
- 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 +19 -5
- 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/QuestionPanel.jsx +13 -4
- package/src/tui/components/SignInUrl.jsx +68 -0
- package/src/tui/components/TextEntryPanel.jsx +76 -46
- package/src/tui/components/sign-in-url-layout.mjs +24 -0
- package/src/tui/dist/index.mjs +1963 -1361
- package/src/tui/session/goal-turn-state.mjs +6 -2
- 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/routes-agent-definitions.mjs +1 -0
- package/src/tui/session/session-api/settings.mjs +2 -2
- package/src/tui/session/session-flow/queue/take-entries.mjs +11 -0
- 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/ui/statusline-agents.mjs +1 -3
- package/src/defaults/skills/skill-creator/references/source-review.md +0 -94
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { compareCodePoints } from '../../../../shared/code-point-order.mjs';
|
|
4
4
|
import { getMcpTools } from '../../mcp/client.mjs';
|
|
5
5
|
import { getInternalTools } from '../../internal-tools.mjs';
|
|
6
|
-
import { BUILTIN_TOOLS, bindShellKind } from '../../tools/builtin/builtin-tools.mjs';
|
|
6
|
+
import { BUILTIN_TOOLS, bindAgentOwner, bindShellKind } from '../../tools/builtin/builtin-tools.mjs';
|
|
7
7
|
import { resolveShellFor } from '../../tools/builtin/shell-runtime.mjs';
|
|
8
8
|
import { PATCH_TOOL_DEFS } from '../../tools/patch-tool-defs.mjs';
|
|
9
9
|
import { CODE_GRAPH_TOOL_DEFS } from '../../tools/code-graph-tool-defs.mjs';
|
|
@@ -51,7 +51,7 @@ const FILESYSTEM_TOOL_NAMES = new Set(['code_graph', 'find', 'glob', 'list', 'gr
|
|
|
51
51
|
const READONLY_FS_TOOL_NAMES = new Set(['code_graph', 'find', 'glob', 'list', 'grep', 'read']);
|
|
52
52
|
|
|
53
53
|
// Lead-only control tools: never part of a worker/sub-agent session surface.
|
|
54
|
-
export const AGENT_WORKER_DENIED_TOOLS = Object.freeze(new Set(['agent', 'ask_user', 'session']));
|
|
54
|
+
export const AGENT_WORKER_DENIED_TOOLS = Object.freeze(new Set(['agent', 'ask_user', 'handoff_user', 'session']));
|
|
55
55
|
|
|
56
56
|
export function finalizeSessionToolList(
|
|
57
57
|
tools,
|
|
@@ -70,7 +70,7 @@ export function finalizeSessionToolList(
|
|
|
70
70
|
}
|
|
71
71
|
if (ownerIsAgent) {
|
|
72
72
|
out = out.filter((t) => !AGENT_WORKER_DENIED_TOOLS.has(String(t?.name || '').toLowerCase()));
|
|
73
|
-
out = orderSessionTools(out);
|
|
73
|
+
out = orderSessionTools(out.map(bindAgentOwner));
|
|
74
74
|
}
|
|
75
75
|
return out;
|
|
76
76
|
}
|
|
@@ -91,6 +91,11 @@ const ALL_BUILTIN_SESSION_TOOLS = orderSessionTools(
|
|
|
91
91
|
_dedupByName([...BUILTIN_TOOLS, ...PATCH_TOOL_DEFS, ...CODE_GRAPH_TOOL_DEFS])
|
|
92
92
|
);
|
|
93
93
|
|
|
94
|
+
/** The read-only filesystem tools (`tools:readonly`), in session route order. */
|
|
95
|
+
export function readOnlyFilesystemTools() {
|
|
96
|
+
return ALL_BUILTIN_SESSION_TOOLS.filter((t) => READONLY_FS_TOOL_NAMES.has(t.name));
|
|
97
|
+
}
|
|
98
|
+
|
|
94
99
|
export function resolveSessionTools(
|
|
95
100
|
toolSpec,
|
|
96
101
|
skills,
|
|
@@ -154,7 +159,7 @@ function _computeBaseTools(toolSpec, mcp, skillTools) {
|
|
|
154
159
|
addMany(ALL_BUILTIN_SESSION_TOOLS.filter((t) => FILESYSTEM_TOOL_NAMES.has(t.name)));
|
|
155
160
|
break;
|
|
156
161
|
case 'tools:readonly':
|
|
157
|
-
addMany(
|
|
162
|
+
addMany(readOnlyFilesystemTools());
|
|
158
163
|
break;
|
|
159
164
|
case 'tools:shell':
|
|
160
165
|
case 'tools:analysis':
|
|
@@ -186,8 +191,7 @@ function _computeBaseTools(toolSpec, mcp, skillTools) {
|
|
|
186
191
|
case 'mcp':
|
|
187
192
|
return orderSessionTools(_dedupByName([...mcp, ...skillTools]));
|
|
188
193
|
case 'readonly': {
|
|
189
|
-
|
|
190
|
-
return orderSessionTools(_dedupByName([...readTools, ...mcp, ...skillTools]));
|
|
194
|
+
return orderSessionTools(_dedupByName([...readOnlyFilesystemTools(), ...mcp, ...skillTools]));
|
|
191
195
|
}
|
|
192
196
|
// 'full' and any unknown spec.
|
|
193
197
|
default:
|
|
@@ -93,6 +93,10 @@ export function captureTurnCheckpointContextState(session, messages, currentUser
|
|
|
93
93
|
),
|
|
94
94
|
...(kind === 'post_compact' ? { usageSnapshot: { ...usageSnapshot } } : {}),
|
|
95
95
|
compaction: compactCheckpointState(session.compaction),
|
|
96
|
+
// Diagnostic only: the prefix fingerprint of the turn's last settled
|
|
97
|
+
// request (anthropic-prefix-trace.mjs), so the first request after a
|
|
98
|
+
// crash is still traced against it.
|
|
99
|
+
...(session.providerPrefixBaseline ? { prefixBaseline: session.providerPrefixBaseline } : {}),
|
|
96
100
|
};
|
|
97
101
|
}
|
|
98
102
|
|
|
@@ -224,6 +224,9 @@ export function recoverTurnCheckpoint(session) {
|
|
|
224
224
|
// mark it unanchored so the first resumed send cannot compact from a gross
|
|
225
225
|
// whole-transcript estimate.
|
|
226
226
|
const contextStateRestored = restoreTurnCheckpointContextState(session, checkpoint);
|
|
227
|
+
// Diagnostic only (anthropic-prefix-trace.mjs): the turn's last settled
|
|
228
|
+
// request, whatever the context reading's alignment.
|
|
229
|
+
if (checkpoint.contextState?.prefixBaseline) session.providerPrefixBaseline = checkpoint.contextState.prefixBaseline;
|
|
227
230
|
delete session.activeTurnCheckpoint;
|
|
228
231
|
delete session.providerState;
|
|
229
232
|
delete session._providerPrefixGuardState;
|
|
@@ -110,6 +110,15 @@ function finalizeInterruptedTurn({
|
|
|
110
110
|
};
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
+
// Killed with a request on the wire (phase 'streaming' after a tool run):
|
|
114
|
+
// the provider received the transcript up to its last message, and may
|
|
115
|
+
// have cached it. Stamping that message keeps what this interruption
|
|
116
|
+
// appends (the marker, the next prompt) out of the tool_result it ends —
|
|
117
|
+
// see toAnthropicMessages. The stamp is meta only; no wire bytes change.
|
|
118
|
+
const sentTail = messages.length - 1;
|
|
119
|
+
if (phase === 'streaming' && (messages[sentTail]?.role === 'tool' || messages[sentTail]?.role === 'user')) {
|
|
120
|
+
messages[sentTail] = { ...messages[sentTail], meta: { ...messages[sentTail].meta, sentRequestTail: true } };
|
|
121
|
+
}
|
|
113
122
|
appendObservedTurnOutput(messages, {
|
|
114
123
|
partialAssistantContent,
|
|
115
124
|
partialReasoningContent,
|
|
@@ -186,8 +195,8 @@ function appendObservedTurnOutput(
|
|
|
186
195
|
}
|
|
187
196
|
}
|
|
188
197
|
|
|
189
|
-
|
|
190
|
-
|
|
198
|
+
function newInterruptionState() {
|
|
199
|
+
return {
|
|
191
200
|
responseStarted: false,
|
|
192
201
|
partialAssistantContent: '',
|
|
193
202
|
tombstonedAssistantContent: '',
|
|
@@ -204,7 +213,10 @@ export function createTurnInterruptionTracker() {
|
|
|
204
213
|
tombEpoch: 0,
|
|
205
214
|
callsEpoch: 0,
|
|
206
215
|
};
|
|
216
|
+
}
|
|
207
217
|
|
|
218
|
+
/** Streamed assistant text, including the tombstone of a retracted attempt. */
|
|
219
|
+
function textBufferMethods(state) {
|
|
208
220
|
return {
|
|
209
221
|
recordTextDelta(chunk) {
|
|
210
222
|
const value = String(chunk ?? '');
|
|
@@ -254,33 +266,12 @@ export function createTurnInterruptionTracker() {
|
|
|
254
266
|
state.tombEpoch += 1;
|
|
255
267
|
return true;
|
|
256
268
|
},
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
state.responseStarted = true;
|
|
264
|
-
state.partialReasoningContent += value;
|
|
265
|
-
},
|
|
266
|
-
recordAssistantText(text) {
|
|
267
|
-
const value = String(text ?? '');
|
|
268
|
-
if (!value.trim()) return;
|
|
269
|
-
state.responseStarted = true;
|
|
270
|
-
// Buffered providers report the whole segment here; streaming
|
|
271
|
-
// providers already accumulated the same segment via text deltas.
|
|
272
|
-
if (!state.partialAssistantContent.trim()) state.partialAssistantContent += value;
|
|
273
|
-
},
|
|
274
|
-
markAssistantMessageCommitted() {
|
|
275
|
-
state.partialAssistantContent = '';
|
|
276
|
-
state.tombstonedAssistantContent = '';
|
|
277
|
-
state.partialReasoningContent = '';
|
|
278
|
-
state.observedToolCalls.clear();
|
|
279
|
-
state.textEpoch += 1;
|
|
280
|
-
state.reasoningEpoch += 1;
|
|
281
|
-
state.tombEpoch += 1;
|
|
282
|
-
state.callsEpoch += 1;
|
|
283
|
-
},
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/** Tool calls and early-notified results observed during the turn. */
|
|
273
|
+
function toolObservationMethods(state) {
|
|
274
|
+
return {
|
|
284
275
|
recordToolCalls(calls, { eagerStarted = false } = {}) {
|
|
285
276
|
for (const call of Array.isArray(calls) ? calls : []) {
|
|
286
277
|
if (!call?.id) continue;
|
|
@@ -308,6 +299,42 @@ export function createTurnInterruptionTracker() {
|
|
|
308
299
|
state.observedToolResults.delete(callId);
|
|
309
300
|
}
|
|
310
301
|
},
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
export function createTurnInterruptionTracker() {
|
|
306
|
+
const state = newInterruptionState();
|
|
307
|
+
|
|
308
|
+
return {
|
|
309
|
+
...textBufferMethods(state),
|
|
310
|
+
...toolObservationMethods(state),
|
|
311
|
+
hasResponseStarted() {
|
|
312
|
+
return state.responseStarted;
|
|
313
|
+
},
|
|
314
|
+
recordReasoningDelta(chunk) {
|
|
315
|
+
const value = String(chunk ?? '');
|
|
316
|
+
if (!value) return;
|
|
317
|
+
state.responseStarted = true;
|
|
318
|
+
state.partialReasoningContent += value;
|
|
319
|
+
},
|
|
320
|
+
recordAssistantText(text) {
|
|
321
|
+
const value = String(text ?? '');
|
|
322
|
+
if (!value.trim()) return;
|
|
323
|
+
state.responseStarted = true;
|
|
324
|
+
// Buffered providers report the whole segment here; streaming
|
|
325
|
+
// providers already accumulated the same segment via text deltas.
|
|
326
|
+
if (!state.partialAssistantContent.trim()) state.partialAssistantContent += value;
|
|
327
|
+
},
|
|
328
|
+
markAssistantMessageCommitted() {
|
|
329
|
+
state.partialAssistantContent = '';
|
|
330
|
+
state.tombstonedAssistantContent = '';
|
|
331
|
+
state.partialReasoningContent = '';
|
|
332
|
+
state.observedToolCalls.clear();
|
|
333
|
+
state.textEpoch += 1;
|
|
334
|
+
state.reasoningEpoch += 1;
|
|
335
|
+
state.tombEpoch += 1;
|
|
336
|
+
state.callsEpoch += 1;
|
|
337
|
+
},
|
|
311
338
|
markProviderSendStarted() {
|
|
312
339
|
state.phase = 'streaming';
|
|
313
340
|
},
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// manager/turn-reap.mjs
|
|
2
|
+
// A turn abandoned by a timeout or stall stops the background shell work that
|
|
3
|
+
// turn started — a job auto-promoted during it, and the survivors its commands
|
|
4
|
+
// left running. Only those: a user cancel, a steering interrupt, a normal
|
|
5
|
+
// finish, and jobs from earlier turns keep their jobs. Only the entry's own
|
|
6
|
+
// turn start is armed, and a new turn clears it, so a reap that runs late
|
|
7
|
+
// never touches a newer turn's work.
|
|
8
|
+
import { cancelBackgroundTasks, getBackgroundTask } from '../../../../shared/background-tasks.mjs';
|
|
9
|
+
import { runtimeState } from './runtime-state.mjs';
|
|
10
|
+
|
|
11
|
+
// Timeout ownership is explicit and turn-scoped: the code that makes a timeout
|
|
12
|
+
// WIN (the watchdog's own abort, the provider's terminal error) arms the reap
|
|
13
|
+
// itself, and only while nothing else has stopped the turn. An abort that
|
|
14
|
+
// arrives first stays a cancel; an error chain is never read afterwards.
|
|
15
|
+
|
|
16
|
+
// Codes of the runtime's own timeout/stall errors (stall-policy's
|
|
17
|
+
// streamStalledError / providerTimeoutError, the Gemini stream timeout).
|
|
18
|
+
const PROVIDER_TIMEOUT_CODES = new Set(['ESTREAMSTALL', 'EPROVIDERTIMEOUT', 'EGEMINITIMEOUT']);
|
|
19
|
+
|
|
20
|
+
/** A timeout is the first thing to stop this session's turn: arm its reap now,
|
|
21
|
+
* before the abort propagates. No-op when the turn's controller is already
|
|
22
|
+
* aborted (a cancel, interrupt or close won) or no turn runs. */
|
|
23
|
+
export function armTurnTimeout(id) {
|
|
24
|
+
const entry = runtimeState.get(id);
|
|
25
|
+
if (!entry || entry.controller?.signal.aborted) return;
|
|
26
|
+
armTurnShellReap(id, entry);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** The turn ended with a provider timeout/stall error that no retry recovered
|
|
30
|
+
* from: arm only while the turn's own signal is un-aborted and the error
|
|
31
|
+
* itself carries a timeout code or the producer's own `streamStalled` flag. */
|
|
32
|
+
export function armTurnTimeoutOnProviderError(id, entry, turnSignal, err) {
|
|
33
|
+
if (turnSignal?.aborted) return;
|
|
34
|
+
if (!PROVIDER_TIMEOUT_CODES.has(err?.code) && err?.streamStalled !== true) return;
|
|
35
|
+
armTurnShellReap(id, entry);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// session id -> jobs stopped by a timeout reap, until the owner's handoff
|
|
39
|
+
// reports them (or the session's next turn starts).
|
|
40
|
+
const stoppedJobs = new Map();
|
|
41
|
+
|
|
42
|
+
// What the cancel path already produces, read without waiting: a task whose
|
|
43
|
+
// own cancel hook kills (survivors of a finished command) answers with its
|
|
44
|
+
// kill outcome; a promoted job is over once its process tree is no longer
|
|
45
|
+
// tracked.
|
|
46
|
+
function trackStoppedJob(taskId) {
|
|
47
|
+
const job = { taskId, outcome: null, terminated: false };
|
|
48
|
+
const kill = getBackgroundTask(taskId)?.cancelOutcome;
|
|
49
|
+
if (kill) {
|
|
50
|
+
job.outcome = kill;
|
|
51
|
+
Promise.resolve(kill).then(
|
|
52
|
+
(result) => {
|
|
53
|
+
job.terminated = result?.terminated === true;
|
|
54
|
+
},
|
|
55
|
+
() => {}
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
return job;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// shell-jobs depends on the session manager, which loads this module, so it is
|
|
62
|
+
// loaded at the first reap. The classification awaits only this module load,
|
|
63
|
+
// never a process; a probe that cannot be loaded leaves a job "still stopping".
|
|
64
|
+
let shellJobProbe = null;
|
|
65
|
+
function loadShellJobProbe() {
|
|
66
|
+
shellJobProbe ??= import('../../tools/builtin/shell-jobs.mjs').then(
|
|
67
|
+
(shellJobs) => shellJobs.isShellJobRunning,
|
|
68
|
+
() => null
|
|
69
|
+
);
|
|
70
|
+
return shellJobProbe;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Confirmed by the runtime's own state, never assumed: a task whose cancel hook
|
|
74
|
+
// kills is confirmed by that kill's `terminated`; a promoted job once neither
|
|
75
|
+
// its native task nor its process-tree tracker is live. Without the probe
|
|
76
|
+
// (shell-jobs not loaded) nothing is confirmed.
|
|
77
|
+
function isConfirmedGone(job, isRunning) {
|
|
78
|
+
if (job.outcome) return job.terminated;
|
|
79
|
+
return Boolean(isRunning) && !isRunning(job.taskId);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function reap(id, entry) {
|
|
83
|
+
loadShellJobProbe();
|
|
84
|
+
const { taskIds } = cancelBackgroundTasks({
|
|
85
|
+
surface: 'shell',
|
|
86
|
+
executionSessionId: id,
|
|
87
|
+
startedSinceMs: entry.shellReapSince,
|
|
88
|
+
reason: 'turn-timeout',
|
|
89
|
+
notify: false,
|
|
90
|
+
});
|
|
91
|
+
if (taskIds.length > 0) stoppedJobs.set(id, [...(stoppedJobs.get(id) || []), ...taskIds.map(trackStoppedJob)]);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** The turn is being abandoned by a timeout: remember when it started and stop
|
|
95
|
+
* what it has started so far. A settled (idle) entry has no turn to reap. */
|
|
96
|
+
export function armTurnShellReap(id, entry) {
|
|
97
|
+
if (!(entry?.askStartedAt > 0) || entry.closed) return;
|
|
98
|
+
entry.shellReapSince = entry.askStartedAt;
|
|
99
|
+
reap(id, entry);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** The abandoned turn has unwound: sweep what it registered while stopping
|
|
103
|
+
* (survivors of its aborted commands). No-op unless this turn was armed. */
|
|
104
|
+
export function reapTurnShellJobs(id, entry) {
|
|
105
|
+
if (entry?.shellReapSince > 0 && !entry.closed && runtimeState.get(id) === entry) reap(id, entry);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** A new turn owns the session: nothing earlier may be reaped on its account. */
|
|
109
|
+
export function resetTurnShellReap(id, entry) {
|
|
110
|
+
entry.shellReapSince = null;
|
|
111
|
+
stoppedJobs.delete(id);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** The jobs the reap stopped, split by what is known now: `stopped` are
|
|
115
|
+
* confirmed gone, `stopping` were killed but their processes are not yet
|
|
116
|
+
* confirmed gone (they keep being terminated). */
|
|
117
|
+
export async function takeStoppedShellJobs(id) {
|
|
118
|
+
const jobs = stoppedJobs.get(id) || [];
|
|
119
|
+
stoppedJobs.delete(id);
|
|
120
|
+
if (jobs.length === 0) return { stopped: [], stopping: [] };
|
|
121
|
+
const isRunning = await loadShellJobProbe();
|
|
122
|
+
const taskIds = (confirmed) =>
|
|
123
|
+
jobs.filter((job) => isConfirmedGone(job, isRunning) === confirmed).map((job) => job.taskId);
|
|
124
|
+
return { stopped: taskIds(true), stopping: taskIds(false) };
|
|
125
|
+
}
|
|
@@ -3,9 +3,13 @@
|
|
|
3
3
|
// Every model- or user-facing string that names it reads this, re-read on each
|
|
4
4
|
// use so a rename applies at once. Text shared across agents (tool schemas,
|
|
5
5
|
// other agents' shared prompt block) says "the representative agent" instead,
|
|
6
|
-
// so a rename never changes cached bytes.
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
// so a rename never changes those cached bytes. Each other bot's own contact
|
|
7
|
+
// catalog (workflow/context.mjs) names her, so a request naming her finds her.
|
|
8
|
+
// Light imports only: the prompt's contact catalog (workflow/context.mjs) reads
|
|
9
|
+
// the name too, and must not pull the skill catalog and config in with it.
|
|
10
|
+
import { readFileSync } from 'node:fs';
|
|
11
|
+
import { join } from 'node:path';
|
|
12
|
+
import { resolvePluginData } from '../../../shared/plugin-paths.mjs';
|
|
9
13
|
import { mixyIdentityDir } from '../../../shared/agent-store.mjs';
|
|
10
14
|
|
|
11
15
|
export const DEFAULT_MIXY_NAME = 'Mixy';
|
|
@@ -19,9 +23,11 @@ export function mixyNameOf(manifest) {
|
|
|
19
23
|
export function mixyDisplayName() {
|
|
20
24
|
try {
|
|
21
25
|
// bots/mixy once Mixy is its own bot, agents/lead before (agent-store.mjs).
|
|
22
|
-
const dir = mixyIdentityDir(
|
|
23
|
-
return mixyNameOf(JSON.parse(
|
|
26
|
+
const dir = mixyIdentityDir(resolvePluginData());
|
|
27
|
+
return mixyNameOf(JSON.parse(readFileSync(join(dir, 'agent.json'), 'utf8')));
|
|
24
28
|
} catch {
|
|
29
|
+
// Never throws: prompt composition calls this unguarded, and the name only labels Mixy.
|
|
30
|
+
// A missing, empty, unreadable or malformed agent.json is the unrenamed default.
|
|
25
31
|
return DEFAULT_MIXY_NAME;
|
|
26
32
|
}
|
|
27
33
|
}
|
|
@@ -92,7 +92,11 @@ function preSendCompactDecision(state, compactPolicy) {
|
|
|
92
92
|
messages,
|
|
93
93
|
sessionRef,
|
|
94
94
|
});
|
|
95
|
-
const cacheExpired = shouldCompactForExpiredAgentCache(sessionRef, state.opts
|
|
95
|
+
const cacheExpired = shouldCompactForExpiredAgentCache(sessionRef, state.opts, {
|
|
96
|
+
provider: sessionRef?.provider || state.provider?.name,
|
|
97
|
+
model: state.model,
|
|
98
|
+
messages,
|
|
99
|
+
});
|
|
96
100
|
const mediaPressure = shouldCompactForRequestMedia(messages, sessionRef?.provider);
|
|
97
101
|
const requireReduction = !reactivePending && !mediaPressure;
|
|
98
102
|
let shouldCompact =
|
|
@@ -26,6 +26,20 @@ function validTouch(value) {
|
|
|
26
26
|
);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
// A warm use as stored: `{ at, provider, model, accountId }` — the route and
|
|
30
|
+
// account whose cached prefix the warm read. A bare time (written before the
|
|
31
|
+
// identity was recorded) keeps its time and matches no route.
|
|
32
|
+
function warmUseRecord(value) {
|
|
33
|
+
const record = value && typeof value === 'object' ? value : { at: value };
|
|
34
|
+
if (!(Number(record.at) > 0)) return null;
|
|
35
|
+
return {
|
|
36
|
+
at: Number(record.at),
|
|
37
|
+
provider: String(record.provider || ''),
|
|
38
|
+
model: String(record.model || ''),
|
|
39
|
+
accountId: String(record.accountId || ''),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
29
43
|
/** A touch store backed by `path` (default: the data dir's file). */
|
|
30
44
|
export function createPromptCacheTouchStore(
|
|
31
45
|
path = () => join(resolvePluginData(), PROMPT_CACHE_TOUCH_FILE),
|
|
@@ -43,8 +57,9 @@ export function createPromptCacheTouchStore(
|
|
|
43
57
|
for (const [sessionId, touch] of Object.entries(stored?.touches || {})) {
|
|
44
58
|
if (validTouch(touch)) touches.set(sessionId, { ...touch });
|
|
45
59
|
}
|
|
46
|
-
for (const [sessionId,
|
|
47
|
-
|
|
60
|
+
for (const [sessionId, use] of Object.entries(stored?.warmUses || {})) {
|
|
61
|
+
const record = warmUseRecord(use);
|
|
62
|
+
if (record) warmUses.set(sessionId, record);
|
|
48
63
|
}
|
|
49
64
|
return touches;
|
|
50
65
|
};
|
|
@@ -102,12 +117,20 @@ export function createPromptCacheTouchStore(
|
|
|
102
117
|
},
|
|
103
118
|
/** When a warm last used the session's cache successfully, or 0. */
|
|
104
119
|
lastWarmUse(sessionId) {
|
|
105
|
-
return uses().get(String(sessionId || '')) || 0;
|
|
120
|
+
return uses().get(String(sessionId || ''))?.at || 0;
|
|
121
|
+
},
|
|
122
|
+
/** The session's last successful warm use `{ at, provider, model,
|
|
123
|
+
* accountId }`, or null. */
|
|
124
|
+
warmUse(sessionId) {
|
|
125
|
+
const use = uses().get(String(sessionId || ''));
|
|
126
|
+
return use ? { ...use } : null;
|
|
106
127
|
},
|
|
107
|
-
/** A warm read the session's cache without writing at `at
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
128
|
+
/** A warm read the session's cache without writing at `at`, on the
|
|
129
|
+
* route and account `{ provider, model, accountId }`. */
|
|
130
|
+
recordWarmUse(sessionId, at, identity = {}) {
|
|
131
|
+
const record = warmUseRecord({ ...identity, at });
|
|
132
|
+
if (!sessionId || !record) return;
|
|
133
|
+
uses().set(String(sessionId), record);
|
|
111
134
|
scheduleFlush();
|
|
112
135
|
},
|
|
113
136
|
/** The session's own activity supersedes its warm use (a real request
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
// Child process of restart-prefix-parity.slow.test.mjs: one phase of a scripted
|
|
2
|
+
// anthropic-oauth session in its own process, so a "restart" is a real new
|
|
3
|
+
// process reading the data dir the previous one left. The fake provider
|
|
4
|
+
// records the request body the real OAuth builder makes for every main-loop
|
|
5
|
+
// send (providers/anthropic-oauth.mjs buildRequestBody, after the same
|
|
6
|
+
// tool-pair sanitize its send path runs) and answers from a script.
|
|
7
|
+
//
|
|
8
|
+
// node restart-prefix-parity.fixture.mjs <phase> <dataDir> <outFile> [sessionId]
|
|
9
|
+
// phase idle two complete turns, then exit
|
|
10
|
+
// phase killtool one complete turn; the second turn's second request is
|
|
11
|
+
// answered with a tool call whose run settles the journal,
|
|
12
|
+
// prints READY and hangs until the parent kills the process
|
|
13
|
+
// phase killrequest the same, but it hangs in the second request itself
|
|
14
|
+
// (sent, never answered)
|
|
15
|
+
// phase resume one turn on the stored session (crash recovery included)
|
|
16
|
+
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
17
|
+
import { join } from 'node:path';
|
|
18
|
+
|
|
19
|
+
const [phase, dataDir, outFile, resumeId] = process.argv.slice(2);
|
|
20
|
+
process.env.MIXDOG_DATA_DIR = dataDir;
|
|
21
|
+
process.env.MIXDOG_AGENT_TRACE_DISABLE = '1';
|
|
22
|
+
const workDir = join(dataDir, '..', 'work');
|
|
23
|
+
mkdirSync(workDir, { recursive: true });
|
|
24
|
+
// The response language defaults to the system locale, and only a Korean one
|
|
25
|
+
// gets Opus 5.5's turn-scoped tail reminder (tail-reminder-rules.mjs), so the
|
|
26
|
+
// language is pinned: every host sends the same requests. The resume phase
|
|
27
|
+
// reads what the first phase wrote.
|
|
28
|
+
if (phase !== 'resume') {
|
|
29
|
+
writeFileSync(join(dataDir, 'mixdog-config.json'), JSON.stringify({ agent: { profile: { language: 'ko' } } }));
|
|
30
|
+
}
|
|
31
|
+
// One file per call: a repeated read is answered from the read cache, which
|
|
32
|
+
// never reaches the tool run the midturn phase hangs in.
|
|
33
|
+
for (const name of ['call_1', 'call_2', 'call_3']) writeFileSync(join(workDir, `${name}.txt`), `${name}\n`);
|
|
34
|
+
|
|
35
|
+
const { createSession } = await import('./manager/session-lifecycle.mjs');
|
|
36
|
+
const { askSession } = await import('./manager/ask-session.mjs');
|
|
37
|
+
const { settleTurnCheckpointWrites } = await import('./manager/turn-checkpoint.mjs');
|
|
38
|
+
const { sanitizeToolPairs } = await import('./context-utils.mjs');
|
|
39
|
+
const { _withRegisteredProviderForTestAsync } = await import('../providers/registry.mjs');
|
|
40
|
+
const { _buildRequestBodyForCacheSmoke } = await import('../providers/anthropic-oauth.mjs');
|
|
41
|
+
const { modelToolSchemaAllowlist } = await import('../runtime-core/tool-profile.mjs');
|
|
42
|
+
const { anthropicPrefixChanges, anthropicPrefixFingerprint, anthropicPrefixSessionId, recordAnthropicPrefix } =
|
|
43
|
+
await import('../providers/lib/anthropic-prefix-trace.mjs');
|
|
44
|
+
|
|
45
|
+
const MODEL = 'claude-opus-5-5';
|
|
46
|
+
const USAGE = { inputTokens: 10, outputTokens: 5, cachedTokens: 0, cacheWriteTokens: 0 };
|
|
47
|
+
const thinking = (id) => [{ type: 'thinking', thinking: `plan ${id}`, signature: `sig-${id}` }];
|
|
48
|
+
const toolStep = (id) => async () => ({
|
|
49
|
+
content: 'Reading.',
|
|
50
|
+
thinkingBlocks: thinking(id),
|
|
51
|
+
hasThinkingContent: true,
|
|
52
|
+
toolCalls: [{ id, name: 'read', arguments: { path: `${id}.txt` } }],
|
|
53
|
+
stopReason: 'tool_use',
|
|
54
|
+
usage: USAGE,
|
|
55
|
+
});
|
|
56
|
+
const textStep = (text) => async () => ({
|
|
57
|
+
content: text,
|
|
58
|
+
thinkingBlocks: thinking(text),
|
|
59
|
+
hasThinkingContent: true,
|
|
60
|
+
stopReason: 'end_turn',
|
|
61
|
+
usage: USAGE,
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
const bodies = [];
|
|
65
|
+
const changes = [];
|
|
66
|
+
let warmBody = null;
|
|
67
|
+
let script = [];
|
|
68
|
+
let sessionId = resumeId || null;
|
|
69
|
+
const provider = {
|
|
70
|
+
name: 'anthropic-oauth',
|
|
71
|
+
contextWindow: 200_000,
|
|
72
|
+
async send(messages, model, tools, opts) {
|
|
73
|
+
if (opts?.requestKind && opts.requestKind !== 'turn') return { content: 'Title', usage: USAGE };
|
|
74
|
+
const body = await _buildRequestBodyForCacheSmoke(sanitizeToolPairs(messages), model, tools || [], opts);
|
|
75
|
+
bodies.push(JSON.parse(JSON.stringify(body)));
|
|
76
|
+
// The diagnostic fingerprint the real send records, and what it reports
|
|
77
|
+
// against the previous request (the record's, after a restart).
|
|
78
|
+
recordAnthropicPrefix(anthropicPrefixSessionId(opts), anthropicPrefixFingerprint(body));
|
|
79
|
+
changes.push(anthropicPrefixChanges(anthropicPrefixSessionId(opts)));
|
|
80
|
+
const step = script.shift();
|
|
81
|
+
if (!step) throw new Error(`unscripted send #${bodies.length}`);
|
|
82
|
+
return step();
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
// Where the interrupted turn stops: the checkpoint made durable, the recorded
|
|
87
|
+
// bodies handed over, and nothing ever finishes (the parent kills the process).
|
|
88
|
+
const hang = async () => {
|
|
89
|
+
await settleTurnCheckpointWrites(sessionId);
|
|
90
|
+
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
91
|
+
await settleTurnCheckpointWrites(sessionId);
|
|
92
|
+
writeFileSync(outFile, JSON.stringify({ sessionId, bodies, changes }));
|
|
93
|
+
process.stdout.write('READY\n');
|
|
94
|
+
return new Promise(() => {});
|
|
95
|
+
};
|
|
96
|
+
// killtool: in the second tool run of the turn (after its second request settled).
|
|
97
|
+
let toolRuns = 0;
|
|
98
|
+
const hangInSecondTool = async () => {
|
|
99
|
+
toolRuns += 1;
|
|
100
|
+
if (toolRuns >= 2) await hang();
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
await _withRegisteredProviderForTestAsync('anthropic-oauth', provider, async () => {
|
|
104
|
+
if (phase === 'resume') {
|
|
105
|
+
// The cache warm a restart re-arms (cache-warm.mjs rearmCacheWarmsAfterRestart)
|
|
106
|
+
// replays this request, built before the next turn touches the session.
|
|
107
|
+
const { lastSentMainRequest } = await import('./side-question.mjs');
|
|
108
|
+
const { cacheWarmSend } = await import('./cache-warm.mjs');
|
|
109
|
+
const request = lastSentMainRequest(sessionId);
|
|
110
|
+
if (request) {
|
|
111
|
+
const send = cacheWarmSend(request);
|
|
112
|
+
warmBody = await _buildRequestBodyForCacheSmoke(
|
|
113
|
+
sanitizeToolPairs(send.messages),
|
|
114
|
+
send.model,
|
|
115
|
+
send.tools || [],
|
|
116
|
+
send.opts
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
script = [textStep('resumed')];
|
|
120
|
+
await askSession(sessionId, 'third task', null, null, null, null, {});
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
const session = createSession({
|
|
124
|
+
provider: 'anthropic-oauth',
|
|
125
|
+
model: MODEL,
|
|
126
|
+
cwd: workDir,
|
|
127
|
+
skipSkills: true,
|
|
128
|
+
schemaAllowedTools: modelToolSchemaAllowlist('headless'),
|
|
129
|
+
workflow: { id: 'headless', delegatesAgents: false },
|
|
130
|
+
});
|
|
131
|
+
sessionId = session.id;
|
|
132
|
+
if (phase === 'idle') {
|
|
133
|
+
script = [toolStep('call_1'), textStep('done one'), toolStep('call_2'), textStep('done two')];
|
|
134
|
+
await askSession(sessionId, 'first task', null, null, null, null, {});
|
|
135
|
+
await askSession(sessionId, 'second task', null, null, null, null, {});
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
// killrequest: while the turn's second request is on the wire.
|
|
139
|
+
const killTool = phase === 'killtool';
|
|
140
|
+
script = [toolStep('call_1'), textStep('done one'), toolStep('call_2'), killTool ? toolStep('call_3') : hang];
|
|
141
|
+
await askSession(sessionId, 'first task', null, null, null, null, {});
|
|
142
|
+
await askSession(
|
|
143
|
+
sessionId,
|
|
144
|
+
'second task',
|
|
145
|
+
null,
|
|
146
|
+
null,
|
|
147
|
+
null,
|
|
148
|
+
null,
|
|
149
|
+
killTool ? { beforeToolExecution: hangInSecondTool } : {}
|
|
150
|
+
);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
writeFileSync(outFile, JSON.stringify({ sessionId, bodies, changes, warmBody }));
|
|
154
|
+
process.exit(0);
|
|
@@ -36,6 +36,7 @@ import { _savePending, _clearDebounce, _releasePendingSlot } from './pending-sav
|
|
|
36
36
|
import { _runtimeLivenessVeto } from './liveness-veto.mjs';
|
|
37
37
|
import { _runSessionPurgeHooks } from './session-observers.mjs';
|
|
38
38
|
import { deleteCompactionArchive } from '../compaction-archive.mjs';
|
|
39
|
+
import { removeSessionScratchDir } from '../../../../shared/session-scratch.mjs';
|
|
39
40
|
|
|
40
41
|
/** Child-agent session ids linked to one visible parent. Candidates come from
|
|
41
42
|
* metadata only (the summary rows and the agent-worker links — no folder
|
|
@@ -154,6 +155,12 @@ export function deleteSession(id, options = {}) {
|
|
|
154
155
|
_runSessionPurgeHooks(id, { cwds: knownSessionCwds(id) });
|
|
155
156
|
// The display-only compaction archive has no meaning without its session.
|
|
156
157
|
deleteCompactionArchive(getStoreDir(), id);
|
|
158
|
+
// The session's scratch directory (shell TEMP/TMP/TMPDIR) goes with it.
|
|
159
|
+
try {
|
|
160
|
+
removeSessionScratchDir(id);
|
|
161
|
+
} catch {
|
|
162
|
+
/* a locked scratch file never fails the delete */
|
|
163
|
+
}
|
|
157
164
|
_clearLiveSession(id);
|
|
158
165
|
// The file is gone: every marker of the retired incarnation goes with it
|
|
159
166
|
// (save error + failed-snapshot evidence, split-brain drop flag, lifecycle
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
inheritedFromSessionId,
|
|
31
31
|
isStoredSessionId,
|
|
32
32
|
positiveNumber,
|
|
33
|
+
compactCountField,
|
|
33
34
|
realTurnCount,
|
|
34
35
|
workspaceSummary,
|
|
35
36
|
} from './store-summary-fields.mjs';
|
|
@@ -216,6 +217,9 @@ export function normalizedRow(row) {
|
|
|
216
217
|
// Absent from a row read off a session file: its assistant text is not
|
|
217
218
|
// decoded there, so the unread count falls back until the next save.
|
|
218
219
|
...(Array.isArray(row.incomingTail) ? { incomingTail: normalizedIncomingTail(row.incomingTail) } : {}),
|
|
220
|
+
// Absent from a row read off a session file (its compaction record is not
|
|
221
|
+
// decoded there) until the next save.
|
|
222
|
+
...compactCountField(row),
|
|
219
223
|
realTurnCount: realTurnCount(row),
|
|
220
224
|
title: cleanText(row.title, 100),
|
|
221
225
|
preview: cleanText(row.preview),
|
|
@@ -63,6 +63,21 @@ export function realTurnCount(value) {
|
|
|
63
63
|
return typeof count === 'number' && Number.isFinite(count) && count >= 0 ? Math.floor(count) : null;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
/** How many compactions a session has had (`compaction.compactCount`): each
|
|
67
|
+
* one trims the live messages and so restarts their numbering (the unread
|
|
68
|
+
* cursors count them). Null for a value without it, e.g. a row written
|
|
69
|
+
* before the field existed. */
|
|
70
|
+
export function compactCount(value) {
|
|
71
|
+
const count = value?.compactCount;
|
|
72
|
+
return typeof count === 'number' && Number.isSafeInteger(count) && count >= 0 ? count : null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** `{ compactCount }` for a row that carries one, else nothing. */
|
|
76
|
+
export function compactCountField(value) {
|
|
77
|
+
const count = compactCount(value);
|
|
78
|
+
return count === null ? {} : { compactCount: count };
|
|
79
|
+
}
|
|
80
|
+
|
|
66
81
|
export function importKey(value) {
|
|
67
82
|
const key = typeof value?.importKey === 'string' ? value.importKey : value?.importOrigin?.key;
|
|
68
83
|
return typeof key === 'string' && key.trim() ? key : null;
|