mixdog 1.3.5 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE.md +2 -2
- package/README.md +2 -2
- package/package.json +2 -11
- package/scripts/check-voice-runtime-inputs.mjs +25 -0
- package/scripts/daemon-stub.mjs +1 -1
- package/scripts/gate-local.mjs +16 -5
- package/scripts/latest-guard.mjs +21 -9
- package/scripts/lib/isolated-test-env.mjs +10 -5
- package/scripts/lib/run-node-tests.mjs +37 -37
- package/scripts/lib/scoped-temp.d.mts +16 -0
- package/scripts/lib/scoped-temp.mjs +123 -0
- package/scripts/lib/stale-temp.mjs +44 -0
- package/scripts/native-release-status.mjs +2 -2
- package/scripts/post-release-check.mjs +1 -6
- package/scripts/pptx-kit-index.mjs +17 -4
- package/scripts/recall-history-cases.json +1 -1
- package/scripts/suite-health.mjs +20 -2
- package/scripts/test-data-dir.mjs +10 -7
- package/scripts/test.mjs +7 -11
- package/src/agents/reviewer/AGENT.md +7 -11
- package/src/agents/reviewer/agent.json +1 -1
- package/src/app.mjs +4 -0
- package/src/defaults/shipped-history.json +22 -1
- package/src/defaults/skills/browser-use/SKILL.md +62 -12
- package/src/defaults/skills/code-tidy/SKILL.md +142 -270
- package/src/defaults/skills/code-tidy/references/agent-cleanup.md +4 -4
- package/src/defaults/skills/code-tidy/references/cleanup-report.md +31 -76
- package/src/defaults/skills/code-tidy/references/dead-code.md +6 -12
- package/src/defaults/skills/computer-use/SKILL.md +35 -9
- package/src/defaults/skills/setup/SKILL.md +22 -0
- package/src/defaults/skills/setup/references/actions.md +39 -5
- package/src/defaults/skills/setup/references/surfaces.md +11 -2
- package/src/defaults/skills/visualize/SKILL.md +2 -1
- package/src/lib/rules-builder.cjs +39 -20
- package/src/output-styles/common.md +2 -2
- package/src/output-styles/simple.md +1 -1
- package/src/rules/agent/AGENT.md +11 -10
- package/src/rules/lead/LEAD.md +23 -20
- package/src/rules/shared/05-tool-calls.md +5 -6
- package/src/rules/shared/10-tool-workflow.md +4 -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 +7 -5
- package/src/rules/shared/70-delivery.md +7 -9
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +29 -6
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -3
- package/src/runtime/agent/orchestrator/agent-runtime/title-completion.mjs +3 -1
- package/src/runtime/agent/orchestrator/agent-trace-format.mjs +3 -1
- package/src/runtime/agent/orchestrator/cache-break-trace.mjs +2 -0
- package/src/runtime/agent/orchestrator/config.mjs +17 -1
- package/src/runtime/agent/orchestrator/context/collect.mjs +3 -0
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +73 -68
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +57 -2
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +3 -3
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +176 -72
- package/src/runtime/agent/orchestrator/mcp/client.mjs +19 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +192 -133
- package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +42 -6
- package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +7 -3
- package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +8 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-cache-warm.mjs +165 -0
- 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 +4 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +14 -14
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/initial-status.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +159 -69
- package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +25 -3
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +70 -33
- package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +135 -87
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +123 -102
- package/src/runtime/agent/orchestrator/providers/cache-warm-admission.mjs +90 -0
- package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +1 -10
- package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +25 -9
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +25 -13
- package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/devin.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +210 -20
- 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-token-utils.mjs +17 -3
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +52 -10
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-login.mjs +1 -10
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +8 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/npm-cli-version.mjs +11 -3
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +2 -1
- 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 +136 -5
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +10 -9
- package/src/runtime/agent/orchestrator/providers/openai-ws-send/send-context.mjs +22 -3
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +43 -5
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/handshake-failure.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/stream-failure.mjs +6 -3
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +20 -12
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +48 -22
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +65 -1
- package/src/runtime/agent/orchestrator/providers/quota-reading.mjs +38 -12
- package/src/runtime/agent/orchestrator/providers/registry.mjs +38 -0
- package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +39 -7
- package/src/runtime/agent/orchestrator/providers/statusline-route-meta.mjs +6 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +49 -16
- package/src/runtime/agent/orchestrator/runtime-core/compaction-config-keys.mjs +62 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +37 -16
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +100 -23
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +7 -6
- package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +9 -3
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +19 -4
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +125 -30
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +3 -1
- package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +5 -2
- package/src/runtime/agent/orchestrator/session/cache/scoped-cache.mjs +1 -3
- package/src/runtime/agent/orchestrator/session/cache-warm.mjs +798 -0
- 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 +280 -45
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +475 -58
- package/src/runtime/agent/orchestrator/session/compaction-archive.mjs +42 -17
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +13 -1
- package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +163 -22
- package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +132 -17
- 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 +90 -22
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +11 -5
- package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +0 -2
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -4
- package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +51 -25
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +37 -3
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +1 -1
- 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 +31 -3
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +20 -3
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/after-hook.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +5 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +16 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +16 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +49 -21
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -10
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +12 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +12 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +19 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +133 -90
- 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/ask-turn-state.mjs +31 -4
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +30 -18
- package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +24 -14
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +11 -2
- package/src/runtime/agent/orchestrator/session/manager/provider-replay.mjs +13 -0
- package/src/runtime/agent/orchestrator/session/manager/route-fallback-chain.mjs +130 -0
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +27 -9
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +81 -8
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +27 -8
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +12 -5
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +9 -4
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +102 -15
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +21 -5
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +9 -0
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +24 -9
- package/src/runtime/agent/orchestrator/session/prompt-cache-idle-gaps.mjs +113 -0
- package/src/runtime/agent/orchestrator/session/prompt-cache-touch-store.mjs +150 -0
- package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +154 -0
- package/src/runtime/agent/orchestrator/session/routine-result.mjs +36 -9
- package/src/runtime/agent/orchestrator/session/sensitive-projection.mjs +100 -0
- package/src/runtime/agent/orchestrator/session/sensitive-values.mjs +257 -0
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +20 -7
- package/src/runtime/agent/orchestrator/session/side-question.mjs +18 -0
- package/src/runtime/agent/orchestrator/session/skill-update-notice.mjs +60 -0
- package/src/runtime/agent/orchestrator/session/store/live-state.mjs +6 -3
- package/src/runtime/agent/orchestrator/session/store/save-delta.mjs +9 -5
- package/src/runtime/agent/orchestrator/session/store/serialize.mjs +9 -8
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +7 -0
- package/src/runtime/agent/orchestrator/session/store/session-persistence-events.mjs +29 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +8 -6
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +16 -2
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +81 -22
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +92 -3
- package/src/runtime/agent/orchestrator/session/stored-attachment-history.mjs +32 -0
- package/src/runtime/agent/orchestrator/session/thinking-binding.mjs +108 -0
- package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +79 -3
- package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-status.mjs +9 -7
- package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-text.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/turn-failure.mjs +5 -1
- package/src/runtime/agent/orchestrator/stall-policy.mjs +23 -0
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +5 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +12 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +240 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/shell-cwd.mjs +38 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +31 -6
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +110 -26
- package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +31 -5
- package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +22 -8
- package/src/runtime/agent/orchestrator/tools/builtin/lib/scoped-search-flight.mjs +9 -5
- 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/shell-runtime.mjs +7 -1
- 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/shell-warm-standby.mjs +26 -4
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +36 -13
- package/src/runtime/browser-bridge/action-schema.mjs +13 -2
- package/src/runtime/browser-bridge/client.mjs +73 -8
- package/src/runtime/browser-bridge/input-fields.mjs +8 -9
- package/src/runtime/browser-bridge/mail-links.mjs +107 -0
- package/src/runtime/browser-bridge/tool-defs.mjs +1 -1
- package/src/runtime/channels/lib/config.mjs +6 -61
- package/src/runtime/channels/lib/crash-log.mjs +1 -1
- package/src/runtime/channels/lib/event-pipeline.mjs +4 -19
- package/src/runtime/channels/lib/event-queue.mjs +3 -18
- package/src/runtime/channels/lib/owned-runtime/automation-services.mjs +2 -2
- package/src/runtime/channels/lib/owned-runtime/automation-start.mjs +3 -4
- package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +4 -59
- package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +33 -115
- package/src/runtime/channels/lib/owned-runtime/owned-stop.mjs +5 -22
- package/src/runtime/channels/lib/owned-runtime/state.mjs +2 -8
- package/src/runtime/channels/lib/owned-runtime.mjs +6 -23
- package/src/runtime/channels/lib/parent-bridge.mjs +2 -2
- package/src/runtime/channels/lib/runtime-paths.mjs +4 -43
- package/src/runtime/channels/lib/scheduler.mjs +33 -147
- package/src/runtime/channels/lib/schedules-db.mjs +34 -11
- package/src/runtime/channels/lib/status-snapshot.mjs +1 -1
- package/src/runtime/channels/lib/tool-dispatch.mjs +1 -2
- package/src/runtime/channels/lib/webhook/signature.mjs +4 -1
- package/src/runtime/channels/lib/webhooks-db.mjs +5 -9
- package/src/runtime/channels/lib/whisper-port.mjs +10 -1
- package/src/runtime/channels/lib/worker-bootstrap.mjs +0 -1
- package/src/runtime/channels/lib/worker-ipc.mjs +0 -1
- package/src/runtime/channels/lib/worker-main.mjs +10 -34
- package/src/runtime/computer-bridge/action-schema.mjs +42 -1
- package/src/runtime/computer-bridge/actions.mjs +9 -1
- package/src/runtime/computer-bridge/client.mjs +180 -8
- package/src/runtime/computer-bridge/core-actions.mjs +2 -2
- package/src/runtime/computer-bridge/error-recovery.mjs +28 -2
- 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/computer-bridge/linux-readiness.mjs +65 -23
- package/src/runtime/computer-bridge/pending-continuation.mjs +1 -1
- package/src/runtime/connectors/connector-accounts-mcp.mjs +230 -0
- package/src/runtime/connectors/gmail-app-password.mjs +172 -39
- package/src/runtime/connectors/google-mcp.mjs +10 -12
- 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/lib/embedding-worker.mjs +6 -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/memory/lib/pg/adapter.mjs +77 -70
- package/src/runtime/memory/lib/pg/supervisor.mjs +24 -12
- package/src/runtime/memory/lib/runtime-fetcher.mjs +23 -5
- 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 +3 -1
- 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/session-search/session-search-db.mjs +73 -9
- package/src/runtime/session-search/session-search-ingest.mjs +110 -20
- package/src/runtime/shared/abort-race.mjs +89 -0
- package/src/runtime/shared/agent-avatar.d.mts +0 -1
- package/src/runtime/shared/agent-kind.mjs +4 -3
- package/src/runtime/shared/bot-owned-work.mjs +56 -0
- package/src/runtime/shared/bounded-download.mjs +8 -3
- package/src/runtime/shared/config.mjs +2 -13
- package/src/runtime/shared/connector-accounts.mjs +20 -10
- package/src/runtime/shared/connector-catalog.d.mts +29 -0
- package/src/runtime/shared/connector-catalog.mjs +150 -0
- package/src/runtime/shared/connector-triggers.mjs +22 -19
- package/src/runtime/shared/defaults-separation.mjs +2 -17
- package/src/runtime/shared/delegated-approval-host.mjs +103 -11
- package/src/runtime/shared/err-text.mjs +24 -15
- 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-permissions.d.mts +0 -8
- package/src/runtime/shared/file-permissions.mjs +0 -11
- package/src/runtime/shared/git-direct.test-support.mjs +19 -0
- package/src/runtime/shared/handoff-artifacts.d.mts +2 -1
- package/src/runtime/shared/handoff-artifacts.mjs +18 -8
- package/src/runtime/shared/heartbeat-interval.d.mts +4 -0
- package/src/runtime/shared/heartbeat-interval.mjs +19 -0
- package/src/runtime/shared/idle-auto-clear-gate.mjs +126 -0
- package/src/runtime/shared/llm/cost.mjs +5 -1
- package/src/runtime/shared/llm/usage-rollup.mjs +1 -1
- package/src/runtime/shared/loopback-listener.mjs +25 -2
- package/src/runtime/shared/mixy-presence.mjs +22 -0
- 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/orchestration.d.mts +2 -0
- package/src/runtime/shared/pg-schema-db.mjs +27 -16
- package/src/runtime/shared/profile-config.cjs +1 -1
- package/src/runtime/shared/prompt-origin.d.mts +4 -0
- package/src/runtime/shared/prompt-origin.mjs +21 -0
- package/src/runtime/shared/provider-accounts.mjs +7 -1
- package/src/runtime/shared/provider-display-name.mjs +29 -0
- package/src/runtime/shared/provider-timeout-phase.mjs +2 -0
- package/src/runtime/shared/routine-trigger.d.mts +2 -0
- package/src/runtime/shared/routine-trigger.mjs +10 -0
- package/src/runtime/shared/sensitive-path-rules.d.mts +2 -10
- package/src/runtime/shared/sensitive-path-rules.mjs +19 -41
- package/src/runtime/shared/session-activity-signal.mjs +48 -1
- package/src/runtime/shared/session-scratch.mjs +37 -0
- package/src/runtime/shared/session-sidebar-host.d.mts +1 -1
- package/src/runtime/shared/session-sidebar-host.mjs +7 -3
- package/src/runtime/shared/session-turn-prelude.mjs +18 -0
- 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 +2 -15
- package/src/runtime/shared/tool-surface.mjs +3 -0
- package/src/runtime/shared/tool-work-units.mjs +2 -0
- package/src/runtime/shared/turn-snapshot-store.mjs +13 -6
- package/src/runtime/shared/worktrees/contract.mjs +4 -1
- package/src/runtime/shared/worktrees/git.mjs +15 -0
- package/src/runtime/shared/worktrees/manager.mjs +87 -38
- package/src/runtime/shared/worktrees/test-support.mjs +14 -13
- package/src/runtime/terminal-bridge/client.mjs +10 -1
- package/src/runtime/visualize-bridge/client.mjs +29 -8
- package/src/runtime/visualize-bridge/tool-defs.mjs +22 -8
- package/src/runtime/visualize-bridge/tool-meta.d.mts +5 -0
- package/src/runtime/visualize-bridge/tool-meta.mjs +22 -0
- package/src/runtime/web-search/lib/fetch-pipeline.mjs +2 -2
- package/src/session-runtime/agent-home-delivery.mjs +489 -185
- package/src/session-runtime/agent-task-sessions.mjs +467 -229
- package/src/session-runtime/agent-tool-routing.mjs +8 -41
- package/src/session-runtime/boot/apis.mjs +9 -0
- package/src/session-runtime/boot/infrastructure.mjs +4 -0
- package/src/session-runtime/boot/providers.mjs +3 -0
- package/src/session-runtime/boot/tools.mjs +11 -2
- package/src/session-runtime/bot-status.mjs +12 -6
- package/src/session-runtime/bot-target.mjs +38 -0
- package/src/session-runtime/channel-config-api.mjs +6 -1
- package/src/session-runtime/config-lifecycle.mjs +6 -0
- package/src/session-runtime/connector-merge-migration.mjs +305 -0
- package/src/session-runtime/conversation-import/codex-titles.mjs +88 -0
- package/src/session-runtime/conversation-import/discovery.mjs +271 -25
- package/src/session-runtime/conversation-import/service.mjs +26 -5
- package/src/session-runtime/handoff-attachments.mjs +82 -31
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +144 -41
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -0
- package/src/session-runtime/internal-tool-executor/reaction-tool.mjs +4 -1
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +8 -2
- package/src/session-runtime/lifecycle/cold-heir.mjs +11 -6
- package/src/session-runtime/lifecycle/inheritance.mjs +16 -3
- package/src/session-runtime/lifecycle/session-catalog.mjs +12 -2
- package/src/session-runtime/lifecycle/teardown/runtime-stops.mjs +50 -4
- package/src/session-runtime/lifecycle/teardown.mjs +23 -5
- package/src/session-runtime/mcp-glue/server-catalog.mjs +55 -3
- package/src/session-runtime/mcp-oauth-login.mjs +5 -3
- package/src/session-runtime/mixy-heartbeat.mjs +153 -33
- package/src/session-runtime/model-route/set-route.mjs +11 -2
- package/src/session-runtime/notification-bus.mjs +31 -117
- package/src/session-runtime/notification-completion-queue.mjs +54 -0
- package/src/session-runtime/notification-listeners.mjs +76 -0
- package/src/session-runtime/owned-automation-run.mjs +2 -1
- package/src/session-runtime/prewarm/channel-start.mjs +3 -7
- 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 +143 -224
- package/src/session-runtime/resource-mcp-connector-accounts.mjs +163 -0
- package/src/session-runtime/resource-mcp-oauth-api.mjs +217 -0
- package/src/session-runtime/resource-mcp-secrets.mjs +82 -0
- package/src/session-runtime/resource-mcp-servers.mjs +78 -0
- package/src/session-runtime/resource-mcp-store.mjs +49 -0
- package/src/session-runtime/resource-recall-api.mjs +6 -1
- package/src/session-runtime/routine-owner.mjs +40 -9
- package/src/session-runtime/runtime-feature-gates.mjs +5 -1
- package/src/session-runtime/services/agent-tool/close-flow.mjs +3 -0
- 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/spawn-preset.mjs +13 -4
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +1 -0
- package/src/session-runtime/services/agent-tool/tool-def.mjs +9 -9
- package/src/session-runtime/services/agent-tool/worker-index/awaiting-user-sync.mjs +51 -0
- package/src/session-runtime/services/agent-tool/worker-index/disposal.mjs +55 -0
- package/src/session-runtime/services/agent-tool/worker-index/released-store.mjs +123 -0
- package/src/session-runtime/services/agent-tool/worker-index/restart-settlement.mjs +112 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-reads.mjs +36 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +17 -4
- package/src/session-runtime/services/agent-tool/worker-index/row-writes.mjs +58 -0
- package/src/session-runtime/services/agent-tool/worker-index.mjs +41 -241
- package/src/session-runtime/services/agent-tool/worker-rows.mjs +3 -0
- package/src/session-runtime/services/channel-admin.mjs +7 -13
- package/src/session-runtime/services/channel-session-router.mjs +4 -2
- package/src/session-runtime/services/provider-admin.mjs +2 -1
- package/src/session-runtime/services/seeds.mjs +0 -28
- package/src/session-runtime/session-compaction-sync.mjs +27 -0
- package/src/session-runtime/session-create/session-options.mjs +1 -0
- package/src/session-runtime/settings-builtin-tools-api.mjs +11 -0
- package/src/session-runtime/settings-compaction-api.mjs +2 -40
- package/src/session-runtime/settings-system-api.mjs +13 -1
- package/src/session-runtime/setup-tool/agent-settings-actions.mjs +65 -0
- package/src/session-runtime/setup-tool/executor.mjs +145 -22
- package/src/session-runtime/setup-tool/extended-actions.mjs +8 -3
- package/src/session-runtime/setup-tool/session-route-actions.mjs +152 -0
- package/src/session-runtime/setup-tool/settings-contract.mjs +4 -3
- package/src/session-runtime/setup-tool/tool-defs.mjs +64 -5
- package/src/session-runtime/tool-policy/agent-profile-fold.mjs +17 -13
- package/src/session-runtime/tool-policy/policy-stage.mjs +17 -2
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +5 -1
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +15 -4
- package/src/session-runtime/workflow-agents-api/onboarding.mjs +3 -3
- package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +4 -0
- package/src/session-runtime/workspace/transitions.mjs +25 -0
- package/src/session-runtime/workspace/worktree-tool.mjs +26 -9
- package/src/standalone/channel-transport/client-registry/client-records.mjs +65 -0
- package/src/standalone/channel-transport/client-registry/client-registration.mjs +118 -0
- package/src/standalone/channel-transport/client-registry.mjs +24 -163
- package/src/standalone/channel-transport.mjs +1 -1
- package/src/standalone/daemon-channels-loader.mjs +10 -8
- package/src/standalone/daemon-session-control/list-page.mjs +72 -0
- package/src/standalone/daemon-session-control/request.mjs +51 -0
- package/src/standalone/daemon-session-control/room-host.mjs +57 -0
- package/src/standalone/daemon-session-control/route-control.mjs +48 -0
- package/src/standalone/daemon-session-control/send-turn.mjs +60 -0
- package/src/standalone/daemon-session-control/worktree-control.mjs +40 -0
- package/src/standalone/daemon-session-control.mjs +142 -190
- package/src/standalone/daemon.mjs +26 -3
- package/src/standalone/session-client.mjs +7 -3
- package/src/standalone/session-protocol.mjs +5 -0
- package/src/standalone/session-service/agent-tree/agent-child.mjs +1 -0
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +16 -12
- package/src/standalone/session-service/quota-resume.mjs +3 -0
- package/src/standalone/session-service/retention/busy.mjs +65 -1
- package/src/standalone/session-service/session-calls/session-action.mjs +30 -2
- package/src/standalone/session-service/session-calls/session-views.mjs +8 -0
- package/src/standalone/session-tool-output.mjs +15 -7
- package/src/standalone/session-transport/client-registry/client-grace.mjs +12 -9
- package/src/tui/app/app-view/floating-panel.jsx +7 -4
- package/src/tui/app/model-options.mjs +3 -28
- 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/provider-setup/oauth-actions.mjs +38 -20
- package/src/tui/app/provider-setup/provider-items.mjs +8 -2
- package/src/tui/app/provider-setup-picker.mjs +9 -5
- package/src/tui/components/QuestionPanel.jsx +13 -4
- package/src/tui/dist/index.mjs +133 -92
- package/src/tui/session/agent-job-feed/model-notification.mjs +3 -0
- package/src/tui/session/initial-state.mjs +3 -0
- package/src/tui/session/notice-surface.mjs +7 -1
- package/src/tui/session/queue-helpers.mjs +3 -42
- package/src/tui/session/session-api/routes-agent-definitions.mjs +14 -2
- package/src/tui/session/session-api/routes-write.mjs +5 -1
- package/src/tui/session/session-api/routes.mjs +1 -0
- package/src/tui/session/session-api/settings.mjs +17 -1
- package/src/tui/session/session-flow/auto-clear.mjs +4 -33
- package/src/tui/session/session-flow/drain-closed-queue.mjs +38 -0
- package/src/tui/session/session-flow/drain-enqueue.mjs +86 -0
- package/src/tui/session/session-flow/drain-retry.mjs +35 -0
- package/src/tui/session/session-flow/drain.mjs +118 -149
- package/src/tui/session/session-flow/queue/entry-shape.mjs +5 -0
- package/src/tui/session/session-flow/queue/take-entries.mjs +16 -2
- package/src/tui/session/tool-approval-delegation.mjs +64 -0
- package/src/tui/session/tool-approval-request.mjs +39 -0
- package/src/tui/session/tool-approval-settle.mjs +62 -0
- package/src/tui/session/tool-approval.mjs +69 -115
- package/src/tui/session/tui-steering-persist.mjs +8 -1
- package/src/tui/session/turn-stream.mjs +19 -2
- package/src/tui/session/turn.mjs +1 -0
- package/src/ui/statusline-agents.mjs +1 -3
- package/src/vendor/statusline/bin/statusline-route.mjs +1 -219
- package/src/vendor/statusline/src/gateway/route-meta.mjs +35 -13
- package/scripts/code-graph-description-contract.mjs +0 -188
- package/src/runtime/channels/lib/owned-runtime/ownership-refresh.mjs +0 -36
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
scanSessionFiles,
|
|
23
23
|
scanSessionFilesAsync,
|
|
24
24
|
stampedDerivation,
|
|
25
|
+
storedSessionCatalogRow,
|
|
25
26
|
} from './store-summary-catalog.mjs';
|
|
26
27
|
import { createStoredTranscriptCache, nextProjectionStamp } from './store-transcript-cache.mjs';
|
|
27
28
|
import {
|
|
@@ -34,10 +35,21 @@ import { projectStoredTranscript } from './store-transcript-projection.mjs';
|
|
|
34
35
|
import { dataDir } from './store-summary-locations.mjs';
|
|
35
36
|
import { isStoredSessionId, workspaceSummary } from './store-summary-fields.mjs';
|
|
36
37
|
import { readArchivedAgentResult } from './store-summary-archived-agent.mjs';
|
|
37
|
-
import {
|
|
38
|
+
import {
|
|
39
|
+
compactionArchivePath,
|
|
40
|
+
compactionArchiveRange,
|
|
41
|
+
readCompactionArchivePage,
|
|
42
|
+
visitCompactionArchive,
|
|
43
|
+
} from './compaction-archive.mjs';
|
|
44
|
+
import { attachmentHistoryRows } from './stored-attachment-history.mjs';
|
|
38
45
|
import { currentSessionCatalogDb, onSessionCatalogDbChange, sessionCatalogDb } from './catalog-db/index.mjs';
|
|
39
46
|
import { decodeCatalogCursor, encodeCatalogCursor, isAfterCursor } from './catalog-db/schema.mjs';
|
|
40
|
-
import {
|
|
47
|
+
import {
|
|
48
|
+
onSessionActivityChange,
|
|
49
|
+
onSessionApprovalCardChange,
|
|
50
|
+
onSessionBotWorkChange,
|
|
51
|
+
} from '../../../shared/session-activity-signal.mjs';
|
|
52
|
+
import { inFlightSessionActivity } from './manager/runtime-state.mjs';
|
|
41
53
|
import {
|
|
42
54
|
readCanonicalSessionRecord as readCanonicalLifecycle,
|
|
43
55
|
offerStrictSessionRecord,
|
|
@@ -59,6 +71,11 @@ export { storedAgentWorkerIndexPath } from './store-summary-locations.mjs';
|
|
|
59
71
|
// the desktop service worker keeps its own for the deep-history prefetch.
|
|
60
72
|
const storedTranscriptCache = createStoredTranscriptCache();
|
|
61
73
|
|
|
74
|
+
// The attachment rows of whole stored conversations: the same cache mechanism
|
|
75
|
+
// and byte budget as the windows above, as an instance of its own, which a
|
|
76
|
+
// lookup can neither fill nor evict.
|
|
77
|
+
const attachmentHistoryCache = createStoredTranscriptCache();
|
|
78
|
+
|
|
62
79
|
/** Test seam: forget every cached projection. */
|
|
63
80
|
export function clearStoredTranscriptCache() {
|
|
64
81
|
storedTranscriptCache.clear();
|
|
@@ -106,7 +123,27 @@ onSessionCatalogDbChange(() => notifyCatalogListeners());
|
|
|
106
123
|
// Runtime activity transitions (turn start/settle, task wait, background
|
|
107
124
|
// hand-off/finish) change only the Agents pool projection: `agent-activity`
|
|
108
125
|
// lets the reader refresh just that, at once.
|
|
109
|
-
|
|
126
|
+
// A transition that starts or settles a turn also changes the catalog rows'
|
|
127
|
+
// `working` / `agentWorking` overlay. The listing that a turn's final save
|
|
128
|
+
// triggers can run before the turn leaves the runtime map, and nothing else
|
|
129
|
+
// re-lists: a bot home (no title write after its turn) kept `working` — a
|
|
130
|
+
// spinner and no completion dot — until its next file change.
|
|
131
|
+
let catalogActivity = '';
|
|
132
|
+
onSessionActivityChange(() => {
|
|
133
|
+
notifyCatalogListeners('agent-activity');
|
|
134
|
+
const { working, agentWorking } = inFlightSessionActivity();
|
|
135
|
+
const next = `${[...working].sort().join(',')}|${[...agentWorking].sort().join(',')}`;
|
|
136
|
+
if (next === catalogActivity) return;
|
|
137
|
+
catalogActivity = next;
|
|
138
|
+
notifyCatalogListeners('turn-activity');
|
|
139
|
+
});
|
|
140
|
+
// A session started or stopped waiting on the user's approval: its catalog row
|
|
141
|
+
// (`awaitingApproval`) changed, though no store file did.
|
|
142
|
+
onSessionApprovalCardChange(() => notifyCatalogListeners('approval'));
|
|
143
|
+
// A bot started or stopped having a send in flight in a session: its catalog
|
|
144
|
+
// row (`handedBy`) changed, though neither a file nor the set of working
|
|
145
|
+
// sessions did (the work may already be running, or continue past the end).
|
|
146
|
+
onSessionBotWorkChange(() => notifyCatalogListeners('bot-work'));
|
|
110
147
|
|
|
111
148
|
/** `listener()` runs when a background pass finds a session file that changed
|
|
112
149
|
* without a directory or index change, i.e. when an ordinary listing would
|
|
@@ -232,6 +269,12 @@ export async function listStoredSessionSummaryPage(options = {}) {
|
|
|
232
269
|
};
|
|
233
270
|
}
|
|
234
271
|
|
|
272
|
+
/** One session's catalog row by id, read off its record (not the paged
|
|
273
|
+
* listing): null when the catalog would not list it. */
|
|
274
|
+
export function readStoredSessionCatalogRow(id) {
|
|
275
|
+
return storedSessionCatalogRow(join(dataDir(), 'sessions'), String(id || '').trim());
|
|
276
|
+
}
|
|
277
|
+
|
|
235
278
|
/** Exact, fail-closed existence check for a durable session address.
|
|
236
279
|
* Summary indexes and desktop metadata are presentation caches; neither may
|
|
237
280
|
* make a missing sessions/<id>.json record addressable again. */
|
|
@@ -269,6 +312,7 @@ function storedSessionMetadata(sessionId, session) {
|
|
|
269
312
|
ownerSessionId: session.ownerSessionId || session.parentSessionId || null,
|
|
270
313
|
visibility: sessionVisibility(session),
|
|
271
314
|
agentTag: session.agentTag || null,
|
|
315
|
+
title: session.title || null,
|
|
272
316
|
cwd: session.cwd || '',
|
|
273
317
|
...(workspaceSummary(session.workspace) ? { workspace: workspaceSummary(session.workspace) } : {}),
|
|
274
318
|
provider: session.provider || null,
|
|
@@ -405,6 +449,49 @@ async function produceStoredTranscript(text, stamp, context) {
|
|
|
405
449
|
}
|
|
406
450
|
}
|
|
407
451
|
|
|
452
|
+
/** The rows of one session's whole stored conversation that name attachments
|
|
453
|
+
* (see attachmentHistoryRows): its record's messages and every visible
|
|
454
|
+
* segment of its compaction archive (a cleared or capped archive stays
|
|
455
|
+
* excluded, as for a window). Read from the files alone, under the same
|
|
456
|
+
* strict record authority as a transcript read, and cached by content
|
|
457
|
+
* identity in a cache of its own: the transcript windows are untouched.
|
|
458
|
+
* Null when the record is absent, unreadable or not this session's. */
|
|
459
|
+
async function readStoredAttachmentHistory(sessionId, recordPath, archivePath) {
|
|
460
|
+
const recordStat = probePath(recordPath);
|
|
461
|
+
if (recordStat.state !== PROBE_PRESENT) return null;
|
|
462
|
+
const archive = probePath(archivePath);
|
|
463
|
+
const key = `${sessionId}|attachments`;
|
|
464
|
+
let complete = true;
|
|
465
|
+
const { value } = await attachmentHistoryCache.read({
|
|
466
|
+
key,
|
|
467
|
+
fingerprint: [archive.state, archive.mtimeMs, archive.ctimeMs, archive.size, archive.ino, archive.dev].join(':'),
|
|
468
|
+
fileStat: recordStat,
|
|
469
|
+
loadText: () => {
|
|
470
|
+
const body = readTextFile(recordPath);
|
|
471
|
+
return body.state === PROBE_PRESENT ? body.text : null;
|
|
472
|
+
},
|
|
473
|
+
produce: async (text) => {
|
|
474
|
+
const record = readTopLevelLifecycleRecord(text);
|
|
475
|
+
if (isLifecycleUnreadable(record) || record.id !== sessionId) return null;
|
|
476
|
+
const { restoreTranscriptItems } = await import('./transcript-restore/restore.mjs');
|
|
477
|
+
const items = [];
|
|
478
|
+
const range = compactionArchiveRange(record.doc);
|
|
479
|
+
// An archive that exists but could not be walked is a transient miss,
|
|
480
|
+
// not a state worth keeping.
|
|
481
|
+
const walked = range
|
|
482
|
+
? await visitCompactionArchive(join(dataDir(), 'sessions'), sessionId, range, (segment) =>
|
|
483
|
+
items.push(...attachmentHistoryRows(segment))
|
|
484
|
+
)
|
|
485
|
+
: true;
|
|
486
|
+
complete = walked || archive.state !== PROBE_PRESENT;
|
|
487
|
+
items.push(...attachmentHistoryRows(restoreTranscriptItems(record.doc.messages, { sessionId })));
|
|
488
|
+
return { sessionId, items };
|
|
489
|
+
},
|
|
490
|
+
});
|
|
491
|
+
if (!complete) attachmentHistoryCache.forget(key);
|
|
492
|
+
return value ?? null;
|
|
493
|
+
}
|
|
494
|
+
|
|
408
495
|
/** Read exactly one persisted session for a visible desktop pane. This never
|
|
409
496
|
* enumerates siblings. Normal reads stay independent of runtime ownership;
|
|
410
497
|
* interrupted turns conditionally use the same durable reconnect recovery as
|
|
@@ -416,6 +503,8 @@ export async function readStoredSessionTranscript(id, options = {}) {
|
|
|
416
503
|
// absent, unreadable, ambiguous or foreign record yields no transcript.
|
|
417
504
|
const { recordPath, checkpointPath, archivePath } = storedTranscriptInputPaths(sessionId);
|
|
418
505
|
if (options.metadataOnly === true) return readStoredSessionMetadata(recordPath, sessionId);
|
|
506
|
+
// The attachments the whole conversation names, apart from any window.
|
|
507
|
+
if (options.attachmentHistory === true) return readStoredAttachmentHistory(sessionId, recordPath, archivePath);
|
|
419
508
|
// One page of the display-only compaction archive (the live head loader
|
|
420
509
|
// pages it once a runtime's in-memory rows are exhausted).
|
|
421
510
|
if (options.compactionArchive && typeof options.compactionArchive === 'object') {
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// The attachments a session's whole stored conversation names (its record and
|
|
2
|
+
// its compaction archive), reduced to the metadata that says which rows name
|
|
3
|
+
// which attachment. Whether an attachment id belongs to a session is decided
|
|
4
|
+
// against this, not against a transcript window (a tail plus the pages paged
|
|
5
|
+
// in), which no longer holds rows a compaction moved into the archive.
|
|
6
|
+
|
|
7
|
+
const pick = (entry, keys) =>
|
|
8
|
+
Object.fromEntries(keys.filter((key) => entry?.[key] != null).map((key) => [key, entry[key]]));
|
|
9
|
+
const picked = (list, keys) => (Array.isArray(list) ? list.map((entry) => pick(entry, keys)) : []);
|
|
10
|
+
|
|
11
|
+
/** The rows of `items` that name attachments, reduced to the fields the
|
|
12
|
+
* desktop reads to attribute an id to its row: the row kind (and a notice's
|
|
13
|
+
* routine / room kind) and each attachment's id, name, type and size. No
|
|
14
|
+
* text, tool output or other row content is kept. */
|
|
15
|
+
export function attachmentHistoryRows(items) {
|
|
16
|
+
const rows = [];
|
|
17
|
+
for (const item of Array.isArray(items) ? items : []) {
|
|
18
|
+
const attachments = picked(item?.attachments, ['id', 'name', 'mimeType', 'kind', 'size']);
|
|
19
|
+
const images = picked(item?.images, ['attachmentRef', 'name', 'mimeType', 'bytes']);
|
|
20
|
+
const imageRefs = picked(item?.imageRefs, ['ref']);
|
|
21
|
+
if (!attachments.length && !images.length && !imageRefs.length) continue;
|
|
22
|
+
rows.push({
|
|
23
|
+
kind: item.kind,
|
|
24
|
+
...(item.routine?.kind ? { routine: { kind: item.routine.kind } } : {}),
|
|
25
|
+
...(item.room?.kind ? { room: { kind: item.room.kind } } : {}),
|
|
26
|
+
...(attachments.length ? { attachments } : {}),
|
|
27
|
+
...(images.length ? { images } : {}),
|
|
28
|
+
...(imageRefs.length ? { imageRefs } : {}),
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
return rows;
|
|
32
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// Thinking replay is bound to the request prefix that produced it.
|
|
2
|
+
//
|
|
3
|
+
// An Anthropic thinking block's signature records the conversation prefix it
|
|
4
|
+
// was generated under: the top-level system prompt, the tool set, and every
|
|
5
|
+
// earlier message. A request whose system or tools changed since then carries
|
|
6
|
+
// blocks the API drops before the model sees them (unbilled, so the provider's
|
|
7
|
+
// count no longer includes them) or, where the check is enforced, refuses with
|
|
8
|
+
// a 400. The drop also takes every LATER thinking block, so a transcript that
|
|
9
|
+
// keeps the stale blocks loses the reasoning of every turn that follows them.
|
|
10
|
+
//
|
|
11
|
+
// Where the runtime itself changes that prefix — a heir carrying a conversation
|
|
12
|
+
// into a prompt built for it, a folded or migrated prompt — the stored thinking
|
|
13
|
+
// can never be replayed again. It is stripped once, at that boundary, the
|
|
14
|
+
// documented recovery: each turn keeps its text and tool calls, and the next
|
|
15
|
+
// turns' thinking binds to the new prefix and is replayed normally. Leaving it
|
|
16
|
+
// in place also kept charging every signature to the local context estimate,
|
|
17
|
+
// which then ran far above what the provider actually counted.
|
|
18
|
+
//
|
|
19
|
+
// One round is never stripped: a trailing tool round whose next request still
|
|
20
|
+
// continues it (the latest assistant turn called tools and no final reply
|
|
21
|
+
// followed — an idle session can stop there after a provider error). Its
|
|
22
|
+
// latest assistant turn must go back starting with its thinking, so removing
|
|
23
|
+
// that thinking is a refused request too. When the prefix changed under such a
|
|
24
|
+
// round, the round is ended explicitly instead (`rebindToChangedPrefix`).
|
|
25
|
+
import { contextAckMessage } from './compact/user-message-kind.mjs';
|
|
26
|
+
import { collectAssistantToolCallIds } from './context-tool-pairs.mjs';
|
|
27
|
+
import { assistantMessageWithoutThinkingReplay } from './thinking-replay-recovery.mjs';
|
|
28
|
+
|
|
29
|
+
/** The runtime turn that ends an open tool round: a context ack, so the
|
|
30
|
+
* transcript never shows it and Compact never reads it as a reply. */
|
|
31
|
+
function toolRoundClosure() {
|
|
32
|
+
const ack = contextAckMessage();
|
|
33
|
+
return { ...ack, meta: { ...ack.meta, synthetic: true } };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const callsTools = (message) =>
|
|
37
|
+
collectAssistantToolCallIds(message).length > 0 ||
|
|
38
|
+
(Array.isArray(message?.providerReplay?.items) &&
|
|
39
|
+
message.providerReplay.items.some((item) => item?.type === 'tool_use'));
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Index where the trailing open tool round starts (the assistant/tool run that
|
|
43
|
+
* ends with the latest assistant turn's results; later user or notification
|
|
44
|
+
* input may follow), or -1 when the latest assistant turn is a final reply.
|
|
45
|
+
* Read from the persisted transcript alone.
|
|
46
|
+
*/
|
|
47
|
+
export function openToolRoundStart(messages) {
|
|
48
|
+
if (!Array.isArray(messages)) return -1;
|
|
49
|
+
const latest = messages.findLastIndex((message) => message?.role === 'assistant');
|
|
50
|
+
if (latest < 0 || !callsTools(messages[latest])) return -1;
|
|
51
|
+
let start = latest;
|
|
52
|
+
while (start > 0 && ['assistant', 'tool'].includes(messages[start - 1]?.role)) start -= 1;
|
|
53
|
+
return start;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** What the next request sends ahead of the conversation: the system blocks and tools. */
|
|
57
|
+
export function requestPrefixIdentity(session) {
|
|
58
|
+
return JSON.stringify([
|
|
59
|
+
(Array.isArray(session?.messages) ? session.messages : [])
|
|
60
|
+
.filter((message) => message?.role === 'system')
|
|
61
|
+
.map((message) => message.content),
|
|
62
|
+
session?.tools,
|
|
63
|
+
]);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* `messages` without Anthropic thinking replay (thinking / redacted_thinking
|
|
68
|
+
* blocks, wherever an assistant turn stores them); text and tool calls stay.
|
|
69
|
+
* The trailing open tool round keeps its thinking: everything stripped is a
|
|
70
|
+
* leading run, which leaves the round's own blocks valid.
|
|
71
|
+
* Replaces changed messages, never mutates; the same array when none changed.
|
|
72
|
+
*/
|
|
73
|
+
export function withoutThinkingReplay(messages) {
|
|
74
|
+
if (!Array.isArray(messages)) return messages;
|
|
75
|
+
const open = openToolRoundStart(messages);
|
|
76
|
+
const end = open < 0 ? messages.length : open;
|
|
77
|
+
let changed = false;
|
|
78
|
+
const out = messages.map((message, index) => {
|
|
79
|
+
const stripped = index < end ? assistantMessageWithoutThinkingReplay(message) : null;
|
|
80
|
+
if (!stripped) return message;
|
|
81
|
+
changed = true;
|
|
82
|
+
return stripped;
|
|
83
|
+
});
|
|
84
|
+
return changed ? out : messages;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* `messages` for a request prefix that changed under them: no thinking replay
|
|
89
|
+
* at all. An open tool round that carries thinking can neither keep it (bound
|
|
90
|
+
* to the old prefix) nor lose it (its continuation must start with it), so it
|
|
91
|
+
* is ended first by a runtime turn right after its last tool result, ahead of
|
|
92
|
+
* any later input (a task notification stays pending after it); the next
|
|
93
|
+
* request then starts a new turn. Never mutates; the same array when nothing
|
|
94
|
+
* changed.
|
|
95
|
+
*/
|
|
96
|
+
export function rebindToChangedPrefix(messages) {
|
|
97
|
+
if (!Array.isArray(messages)) return messages;
|
|
98
|
+
const open = openToolRoundStart(messages);
|
|
99
|
+
if (open < 0) return withoutThinkingReplay(messages);
|
|
100
|
+
let end = messages.findLastIndex((message) => message?.role === 'assistant') + 1;
|
|
101
|
+
while (messages[end]?.role === 'tool') end += 1;
|
|
102
|
+
const roundThinks = messages
|
|
103
|
+
.slice(open, end)
|
|
104
|
+
.some((message) => assistantMessageWithoutThinkingReplay(message) !== null);
|
|
105
|
+
return withoutThinkingReplay(
|
|
106
|
+
roundThinks ? [...messages.slice(0, end), toolRoundClosure(), ...messages.slice(end)] : messages
|
|
107
|
+
);
|
|
108
|
+
}
|
|
@@ -103,8 +103,8 @@ function crossTurnStub(batch, call, ctSig) {
|
|
|
103
103
|
// (which spans ONE assistant turn): when the model re-issues an IDENTICAL
|
|
104
104
|
// normalized call that has already failed repeatFailLimit times in a row
|
|
105
105
|
// across iterations, stop re-executing — the result will not change, and
|
|
106
|
-
// each retry burns a full LLM round-trip
|
|
107
|
-
//
|
|
106
|
+
// each retry burns a full LLM round-trip. The call stays unresolved; the
|
|
107
|
+
// guard only skips re-execution.
|
|
108
108
|
function repeatFailureSkip(batch, call, sigs) {
|
|
109
109
|
const { sessionRef, repeatFailLimit } = batch;
|
|
110
110
|
const rfg = sessionRef?._repeatFailGuard;
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
// consumes.
|
|
5
5
|
import { resolve as resolvePath, isAbsolute } from 'node:path';
|
|
6
6
|
import { normalizeToolEnvelope } from '../tool-envelope.mjs';
|
|
7
|
+
import { effectiveToolCwd } from '../../tools/builtin/bash-tool/shell-cwd.mjs';
|
|
7
8
|
import {
|
|
8
9
|
invalidatePathForSession,
|
|
9
10
|
clearReadDedupSession,
|
|
@@ -85,7 +86,7 @@ async function fireToolFailureHook(batch, call, result) {
|
|
|
85
86
|
await hook({
|
|
86
87
|
name: call.name,
|
|
87
88
|
args: call.arguments,
|
|
88
|
-
cwd: batch.cwd,
|
|
89
|
+
cwd: effectiveToolCwd(call.name, call.arguments, batch.cwd),
|
|
89
90
|
sessionId: batch.sessionId,
|
|
90
91
|
toolCallId: call.id,
|
|
91
92
|
result: typeof result === 'string' ? result : String(result ?? ''),
|
|
@@ -44,6 +44,7 @@ import {
|
|
|
44
44
|
} from '../../../../shared/transcript-metadata.mjs';
|
|
45
45
|
import { routineTriggerField } from '../../../../shared/routine-trigger.mjs';
|
|
46
46
|
import { isImportedMessage } from '../imported-message.mjs';
|
|
47
|
+
import { toolRunLine } from '../conversation-import/turns.mjs';
|
|
47
48
|
import { isContextAckMessage } from '../compact/user-message-kind.mjs';
|
|
48
49
|
import { isRoutineResultMessage, routineResultNotice } from '../routine-result.mjs';
|
|
49
50
|
import { heldRequestNotice, isHeldRequestMessage } from '../human-gate/held-message.mjs';
|
|
@@ -64,6 +65,20 @@ function restoredFailureFields(value) {
|
|
|
64
65
|
};
|
|
65
66
|
}
|
|
66
67
|
|
|
68
|
+
/** Whether `message` was posted into the thread outside any turn: it says so
|
|
69
|
+
* (`transcript.posted`, stamped by agent-home-delivery.mjs), or it is a row
|
|
70
|
+
* stored before that marker existed. Those carry the id agent-home-delivery
|
|
71
|
+
* mints for every posted row (`messageIdOf`: `routine_<runId>`) and are not
|
|
72
|
+
* prompts: an agent's own message (assistant role) or a result/held-request
|
|
73
|
+
* notice (stored under the user role, but not a prompt). The `routine_` scheme
|
|
74
|
+
* alone is not enough: routine-home-turn.mjs:144 gives the prompt of a routine
|
|
75
|
+
* fire (user role) the same prefix, and that prompt opens a real turn. */
|
|
76
|
+
function isPostedMessage(message, transcript) {
|
|
77
|
+
if (transcript.posted === true) return true;
|
|
78
|
+
if (typeof transcript.messageId !== 'string' || !transcript.messageId.startsWith('routine_')) return false;
|
|
79
|
+
return message?.role !== 'user' || isRoutineResultMessage(message) || isHeldRequestMessage(message);
|
|
80
|
+
}
|
|
81
|
+
|
|
67
82
|
function restoredTranscriptMetadata(message) {
|
|
68
83
|
const value = message?.meta?.transcript;
|
|
69
84
|
if (!value || typeof value !== 'object') return {};
|
|
@@ -87,6 +102,8 @@ function restoredTranscriptMetadata(message) {
|
|
|
87
102
|
// messages back to these rows.
|
|
88
103
|
...(typeof value.messageId === 'string' && value.messageId ? { messageId: value.messageId } : {}),
|
|
89
104
|
...(Number.isFinite(Number(value.at)) ? { at: Number(value.at) } : {}),
|
|
105
|
+
// Delivered into the thread outside any turn (agent-home-delivery.mjs).
|
|
106
|
+
...(isPostedMessage(message, value) ? { posted: true } : {}),
|
|
90
107
|
...transcriptRouteMetadataFields(value),
|
|
91
108
|
...(typeof value.sender === 'string' && value.sender ? { sender: value.sender } : {}),
|
|
92
109
|
...(typeof value.device === 'string' && value.device ? { device: value.device } : {}),
|
|
@@ -124,7 +141,64 @@ function restoredContentText(message) {
|
|
|
124
141
|
return typeof message?.content === 'string' ? message.content : toolResultText(message?.content);
|
|
125
142
|
}
|
|
126
143
|
|
|
144
|
+
// The runs of tool use an imported assistant message recorded (conversation-import
|
|
145
|
+
// turns.mjs), kept only where the text still holds exactly their canonical line.
|
|
146
|
+
function importedToolRuns(message) {
|
|
147
|
+
const runs = message?.meta?.importedToolRuns;
|
|
148
|
+
if (!isImportedMessage(message) || typeof message.content !== 'string' || !Array.isArray(runs)) return [];
|
|
149
|
+
let cursor = 0;
|
|
150
|
+
return runs.filter((run) => {
|
|
151
|
+
const valid =
|
|
152
|
+
Number.isInteger(run?.start) &&
|
|
153
|
+
Number.isInteger(run?.end) &&
|
|
154
|
+
run.start >= cursor &&
|
|
155
|
+
run.end > run.start &&
|
|
156
|
+
run.end <= message.content.length &&
|
|
157
|
+
Array.isArray(run.tools) &&
|
|
158
|
+
run.tools.length > 0 &&
|
|
159
|
+
run.tools.every((tool) => typeof tool?.name === 'string' && Number.isInteger(tool.count) && tool.count > 0) &&
|
|
160
|
+
message.content.slice(run.start, run.end) === toolRunLine(run.tools);
|
|
161
|
+
if (valid) cursor = run.end;
|
|
162
|
+
return valid;
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// An imported reply with tool use: its text around each run as assistant rows,
|
|
167
|
+
// each run as tool rows (one per tool, counted). The calls' results were never
|
|
168
|
+
// imported; the `imported` mark lets the row say so.
|
|
169
|
+
function restoredImportedAssistantItems(message, runs, nextId) {
|
|
170
|
+
const { completion: _completion, ...metadata } = restoredTranscriptMetadata(message);
|
|
171
|
+
const at = Number(message?.meta?.transcript?.at);
|
|
172
|
+
const items = [];
|
|
173
|
+
const pushText = (raw) => {
|
|
174
|
+
const text = raw.trim();
|
|
175
|
+
if (text) items.push({ kind: 'assistant', id: nextId(), text, ...metadata });
|
|
176
|
+
};
|
|
177
|
+
let cursor = 0;
|
|
178
|
+
for (const run of runs) {
|
|
179
|
+
pushText(message.content.slice(cursor, run.start));
|
|
180
|
+
for (const { name, count } of run.tools) {
|
|
181
|
+
if (isTranscriptHiddenControlToolName(name)) continue;
|
|
182
|
+
items.push({
|
|
183
|
+
kind: 'tool',
|
|
184
|
+
id: nextId(),
|
|
185
|
+
name,
|
|
186
|
+
imported: true,
|
|
187
|
+
expanded: false,
|
|
188
|
+
count,
|
|
189
|
+
completedCount: count,
|
|
190
|
+
...(Number.isFinite(at) ? { at, startedAt: at, completedAt: at } : {}),
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
cursor = run.end;
|
|
194
|
+
}
|
|
195
|
+
pushText(message.content.slice(cursor));
|
|
196
|
+
return items;
|
|
197
|
+
}
|
|
198
|
+
|
|
127
199
|
function restoredAssistantTranscriptItems(message, nextId) {
|
|
200
|
+
const runs = importedToolRuns(message);
|
|
201
|
+
if (runs.length) return restoredImportedAssistantItems(message, runs, nextId);
|
|
128
202
|
const text = restoredContentText(message).trim();
|
|
129
203
|
if (!text) return [];
|
|
130
204
|
const { completion, ...metadata } = restoredTranscriptMetadata(message);
|
|
@@ -323,7 +397,7 @@ function mergeRestoredToolItems(items) {
|
|
|
323
397
|
// Result-dependent hiding (built-in skill loads) resolves here, after
|
|
324
398
|
// every role:'tool' result has been attached to its restored call.
|
|
325
399
|
if (item?.kind === 'tool' && isTranscriptHiddenToolItem(item)) continue;
|
|
326
|
-
const mergeable = item?.kind === 'tool' && item.aggregate !== true;
|
|
400
|
+
const mergeable = item?.kind === 'tool' && item.aggregate !== true && item.imported !== true;
|
|
327
401
|
if (!mergeable) {
|
|
328
402
|
flushRun();
|
|
329
403
|
merged.push(item);
|
|
@@ -363,7 +437,8 @@ function restoredMessageItemUpperBound(message) {
|
|
|
363
437
|
const calls = restoredMessageToolCalls(message);
|
|
364
438
|
const content = message?.content;
|
|
365
439
|
const hasContent = typeof content === 'string' ? content.length > 0 : Array.isArray(content) && content.length > 0;
|
|
366
|
-
|
|
440
|
+
const importedRows = importedToolRuns(message).reduce((total, run) => total + run.tools.length + 1, 0);
|
|
441
|
+
return Number(hasContent) + completionCount + calls.length + importedRows + boundaries;
|
|
367
442
|
}
|
|
368
443
|
|
|
369
444
|
// One restored tool card for a parsed notification/completion envelope.
|
|
@@ -400,7 +475,7 @@ function restoredUserTranscriptItems(message, nextId, userText) {
|
|
|
400
475
|
// A schedule's result in its owner's home thread: a notice row.
|
|
401
476
|
// A held request of an unattended run (human-gate/held-message.mjs) likewise.
|
|
402
477
|
if (isRoutineResultMessage(message) || isHeldRequestMessage(message)) {
|
|
403
|
-
const { messageId, at } = restoredTranscriptMetadata(message);
|
|
478
|
+
const { messageId, at, posted } = restoredTranscriptMetadata(message);
|
|
404
479
|
return [
|
|
405
480
|
{
|
|
406
481
|
kind: 'notice',
|
|
@@ -408,6 +483,7 @@ function restoredUserTranscriptItems(message, nextId, userText) {
|
|
|
408
483
|
...(isHeldRequestMessage(message) ? heldRequestNotice(message) : routineResultNotice(message)),
|
|
409
484
|
...(messageId ? { messageId } : {}),
|
|
410
485
|
...(at ? { at } : {}),
|
|
486
|
+
...(posted ? { posted } : {}),
|
|
411
487
|
},
|
|
412
488
|
];
|
|
413
489
|
}
|
|
@@ -13,6 +13,7 @@ import { formatAggregateDetail, summarizeToolResult, toolLoadingTargets } from '
|
|
|
13
13
|
import { normalizeToolName } from '../../../../shared/tool-primitives.mjs';
|
|
14
14
|
import { gitResultError, gitResultExitCode } from '../../../../shared/tool-card-model/git-result.mjs';
|
|
15
15
|
import { readRowsForDisplay } from '../../../../shared/read-row-numbers.mjs';
|
|
16
|
+
import { visualizeOwnerMetaSessionId } from '../../../../visualize-bridge/tool-meta.mjs';
|
|
16
17
|
|
|
17
18
|
const CANCELLED_RESULT_STATUS_LINE = '[status: cancelled]';
|
|
18
19
|
|
|
@@ -292,15 +293,16 @@ export function assignUiDiffFromMessage(target, source) {
|
|
|
292
293
|
}
|
|
293
294
|
|
|
294
295
|
/** Structured side channel a tool result may carry next to its text (the
|
|
295
|
-
* Computer Use capability refusal): a stable code plus the capability names
|
|
296
|
-
*
|
|
297
|
-
|
|
296
|
+
* Computer Use capability refusal): a stable code plus the capability names,
|
|
297
|
+
* and the owner conversation of a `visualize` call run for another session's
|
|
298
|
+
* work (visualize-bridge/tool-meta.mjs). Anything else is dropped so stored
|
|
299
|
+
* history stays small and predictable. */
|
|
300
|
+
function toolMetaFromMessage(source) {
|
|
298
301
|
const meta = source?.toolMeta ?? source?.content?.toolMeta;
|
|
299
302
|
if (!meta || typeof meta !== 'object' || typeof meta.code !== 'string' || !meta.code) return undefined;
|
|
300
|
-
const missing = Array.isArray(meta.missing)
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
return { code: meta.code, missing };
|
|
303
|
+
const missing = Array.isArray(meta.missing) ? meta.missing.filter((name) => typeof name === 'string' && name) : [];
|
|
304
|
+
const ownerSessionId = visualizeOwnerMetaSessionId(meta.ownerSessionId);
|
|
305
|
+
return { code: meta.code, missing, ...(ownerSessionId ? { ownerSessionId } : {}) };
|
|
304
306
|
}
|
|
305
307
|
|
|
306
308
|
export function toolMetaPatchFromMessage(source) {
|
|
@@ -132,8 +132,8 @@ export function toolGroupedDisplayFallback(resultText, text, rawText) {
|
|
|
132
132
|
return resultText;
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
-
export function toolErrorDisplay(value, surface = 'tool') {
|
|
136
|
-
const text = presentErrorText(value, { surface });
|
|
135
|
+
export function toolErrorDisplay(value, surface = 'tool', { providerLabel } = {}) {
|
|
136
|
+
const text = presentErrorText(value, { surface, providerLabel });
|
|
137
137
|
if (
|
|
138
138
|
/^(?:Search failed|Fetch failed|No first response|No progress|Cancelled|The .+ went stale|(?:Web search agent|Agent|Tool|Request) (?:stopped|was cancelled))/i.test(
|
|
139
139
|
text
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// session shows the same failure, reason and quota stop as the live one.
|
|
4
4
|
import { errText } from '../../../shared/err-text.mjs';
|
|
5
5
|
import { safeErrorDetails } from '../../../shared/error-presentation.mjs';
|
|
6
|
+
import { providerDisplayName } from '../../../shared/provider-display-name.mjs';
|
|
6
7
|
import { providerErrorKind } from '../providers/provider-error-kind.mjs';
|
|
7
8
|
import { toolErrorDisplay } from './transcript-restore/tool-result-text.mjs';
|
|
8
9
|
|
|
@@ -39,7 +40,10 @@ export function turnFailureRecord(error, route = {}) {
|
|
|
39
40
|
providerKind,
|
|
40
41
|
errorKind,
|
|
41
42
|
quota,
|
|
42
|
-
|
|
43
|
+
// The provider is named from the turn's own route, never from the error.
|
|
44
|
+
detail: toolErrorDisplay(error, 'turn', {
|
|
45
|
+
providerLabel: route.provider ? providerDisplayName(route.provider) : undefined,
|
|
46
|
+
}).replace(/^Error:\s*/i, ''),
|
|
43
47
|
errorDetails: safeErrorDetails(errText(error)),
|
|
44
48
|
};
|
|
45
49
|
}
|
|
@@ -259,6 +259,29 @@ export const PROVIDER_WS_SEMANTIC_IDLE_TIMEOUT_MS = resolveTimeoutMs(
|
|
|
259
259
|
{ minMs: 10_000, maxMs: Math.max(10_000, STALL_ABORT_MS - STALL_TICK_MS) }
|
|
260
260
|
);
|
|
261
261
|
|
|
262
|
+
// First-OUTPUT window of one provider stream: from the stream opening until
|
|
263
|
+
// the model's first semantic output (reasoning, text or a tool call). Server
|
|
264
|
+
// metadata and keepalives (response.created / in_progress, an empty reasoning
|
|
265
|
+
// or message item, a role-only chunk, pings) neither end this phase nor start
|
|
266
|
+
// the semantic-idle clock, so a reasoning model may think silently past the
|
|
267
|
+
// idle window (issue #244: 4–6 min on a large post-tool-result prompt). The
|
|
268
|
+
// window sits one tick under the stall abort — the same ceiling the semantic
|
|
269
|
+
// idle uses — so the provider still fails (and may retry or fall back) before
|
|
270
|
+
// the agent watchdog's first-output deadline (600s default), and it is never
|
|
271
|
+
// shorter than the idle window it replaces. Not separately tunable: it
|
|
272
|
+
// follows STALL_TIMEOUT_S.
|
|
273
|
+
export const PROVIDER_FIRST_OUTPUT_TIMEOUT_MS = Math.max(
|
|
274
|
+
PROVIDER_SEMANTIC_IDLE_TIMEOUT_MS,
|
|
275
|
+
PROVIDER_WS_SEMANTIC_IDLE_TIMEOUT_MS,
|
|
276
|
+
STALL_ABORT_MS - STALL_TICK_MS
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
/** The first-output window of a stream whose semantic idle is `idleMs`: a
|
|
280
|
+
* longer idle window (a provider profile) is never cut short by it. */
|
|
281
|
+
export function providerFirstOutputTimeoutMs(idleMs) {
|
|
282
|
+
return Math.max(idleMs, PROVIDER_FIRST_OUTPUT_TIMEOUT_MS);
|
|
283
|
+
}
|
|
284
|
+
|
|
262
285
|
/**
|
|
263
286
|
* The longest a provider's own first-byte handling may legitimately run
|
|
264
287
|
* before it gives up, over every attempt it permits: `windowMs(n)` is the wait
|
|
@@ -780,10 +780,13 @@ function guardRead(a) {
|
|
|
780
780
|
}
|
|
781
781
|
|
|
782
782
|
function guardShell(a) {
|
|
783
|
-
const allowed = new Set(['command', 'timeout_ms', 'wait_ms', 'background']);
|
|
783
|
+
const allowed = new Set(['command', 'cwd', 'timeout_ms', 'wait_ms', 'background']);
|
|
784
784
|
const unsupported = Object.keys(a).find((key) => !allowed.has(key));
|
|
785
785
|
if (unsupported) {
|
|
786
|
-
return `Error: shell arg "${unsupported}" is unsupported; use only command, timeout_ms, wait_ms, and background`;
|
|
786
|
+
return `Error: shell arg "${unsupported}" is unsupported; use only command, cwd, timeout_ms, wait_ms, and background`;
|
|
787
|
+
}
|
|
788
|
+
if (hasOwn(a, 'cwd') && (typeof a.cwd !== 'string' || a.cwd.trim().length === 0)) {
|
|
789
|
+
return `Error: shell arg "cwd" must be a non-empty string (got ${describeType(a.cwd)})`;
|
|
787
790
|
}
|
|
788
791
|
if (hasOwn(a, 'background') && typeof a.background !== 'boolean') {
|
|
789
792
|
return `Error: shell arg "background" must be a boolean (got ${describeType(a.background)})`;
|
|
@@ -52,7 +52,17 @@ function registerPromotedTask({ result, command, cwd, options, startedAtMs }) {
|
|
|
52
52
|
// running, now promoted as a tracked shell-job. Surface the task_id + partial
|
|
53
53
|
// output for manual task control instead of keeping the tool call open until
|
|
54
54
|
// the hard timeout.
|
|
55
|
-
export function renderBackgroundedResult({
|
|
55
|
+
export function renderBackgroundedResult({
|
|
56
|
+
result,
|
|
57
|
+
command,
|
|
58
|
+
cwd,
|
|
59
|
+
options,
|
|
60
|
+
startedAtMs,
|
|
61
|
+
teePlan,
|
|
62
|
+
stdout,
|
|
63
|
+
stderr,
|
|
64
|
+
notes = '',
|
|
65
|
+
}) {
|
|
56
66
|
let task = null;
|
|
57
67
|
if (result.jobId) {
|
|
58
68
|
task = registerPromotedTask({ result, command, cwd, options, startedAtMs });
|
|
@@ -91,6 +101,7 @@ export function renderBackgroundedResult({ result, command, cwd, options, starte
|
|
|
91
101
|
)
|
|
92
102
|
: renderBackgroundPartialOutput(stdout, stderr);
|
|
93
103
|
const lines = _backgroundResultLines({
|
|
104
|
+
warning: notes,
|
|
94
105
|
taskBlock,
|
|
95
106
|
message: result.backgroundMessage || DEFAULT_BACKGROUND_MESSAGE,
|
|
96
107
|
partialOutput,
|
|
@@ -28,9 +28,9 @@ function prefixPowerShellUtf8(command) {
|
|
|
28
28
|
// UTF-8 prefix (+ optional filter-tee rescue), or a POSIX bash/zsh snapshot
|
|
29
29
|
// wrapper delivered through the environment. Returns `{ failure }` when the
|
|
30
30
|
// snapshot wrapper cannot be built.
|
|
31
|
-
export async function planShellInvocation({ command, resolvedSpec, cwd }) {
|
|
31
|
+
export async function planShellInvocation({ command, resolvedSpec, cwd, sessionId = null }) {
|
|
32
32
|
const { shell, shellArg, shellArgs, shellType } = resolvedSpec;
|
|
33
|
-
const spawnEnv = buildShellSpawnEnv(cwd);
|
|
33
|
+
const spawnEnv = buildShellSpawnEnv(cwd, process.env, sessionId);
|
|
34
34
|
const plan = {
|
|
35
35
|
execShell: shell,
|
|
36
36
|
execShellArg: shellArg,
|