mixdog 1.2.2 → 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -0
- package/package.json +2 -1
- package/scripts/provider-pingpong-live.mjs +509 -0
- package/src/agents/advisor/AGENT.md +1 -1
- package/src/agents/advisor/agent.json +1 -1
- package/src/defaults/shipped-history.json +5 -0
- package/src/defaults/skills/setup/SKILL.md +6 -1
- package/src/defaults/skills/setup/references/actions.md +44 -22
- package/src/defaults/skills/setup/references/surfaces.md +10 -8
- package/src/headless-exec.mjs +15 -8
- package/src/lib/keychain-cjs.cjs +7 -4
- package/src/output-styles/common.md +11 -10
- package/src/rules/agent/AGENT.md +5 -5
- package/src/rules/lead/LEAD.md +5 -5
- package/src/runtime/agent/orchestrator/agent-trace-io.mjs +92 -61
- package/src/runtime/agent/orchestrator/cache-mtime.mjs +10 -1
- package/src/runtime/agent/orchestrator/config-providers-merge.mjs +7 -0
- package/src/runtime/agent/orchestrator/config.mjs +5 -0
- package/src/runtime/agent/orchestrator/context/collect.mjs +1 -0
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +26 -7
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +112 -7
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +48 -20
- package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +24 -17
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +7 -6
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +29 -10
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-blocks.mjs +20 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-delta.mjs +15 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +11 -4
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/message-events.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +12 -5
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-outcome.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-state.mjs +14 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +6 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +58 -7
- package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +29 -10
- package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +16 -3
- package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +10 -61
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +12 -6
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +114 -72
- package/src/runtime/agent/orchestrator/providers/compat-request-policy.mjs +78 -2
- package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +37 -5
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-messages.mjs +43 -2
- package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +64 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +70 -6
- package/src/runtime/agent/orchestrator/providers/custom-reasoning.mjs +34 -7
- package/src/runtime/agent/orchestrator/providers/custom-tool-wire.mjs +32 -6
- package/src/runtime/agent/orchestrator/providers/deepseek.mjs +67 -0
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +11 -4
- package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +25 -8
- package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +87 -5
- package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +41 -5
- package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +13 -13
- package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +355 -37
- package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +1 -2
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +93 -47
- package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +55 -10
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +26 -8
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/lib/action-input-contract.mjs +60 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-native-blocks.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +246 -42
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-server-tool-usage.mjs +18 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-system-blocks.mjs +27 -6
- package/src/runtime/agent/orchestrator/providers/lib/claude-bridge-schema.mjs +388 -0
- package/src/runtime/agent/orchestrator/providers/lib/inclusive-usage.mjs +54 -0
- package/src/runtime/agent/orchestrator/providers/lib/origin-bound-fetch.mjs +16 -0
- package/src/runtime/agent/orchestrator/providers/lib/responses-terminal-fields.mjs +11 -0
- package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +8 -0
- package/src/runtime/agent/orchestrator/providers/lib/wire-pairing.mjs +48 -22
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +119 -18
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +13 -15
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +1 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +33 -1
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +121 -61
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +35 -14
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +37 -7
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/tool-call-acc.mjs +2 -9
- package/src/runtime/agent/orchestrator/providers/openai-compat-error-contract.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +47 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +47 -25
- package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +5 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-reasoning-field.mjs +151 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +42 -24
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +63 -25
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2901 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-parity.fixtures.mjs +172 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +53 -5
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +103 -26
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +23 -4
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +11 -6
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +6 -1
- package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +15 -23
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +23 -10
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +25 -4
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +10 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-items.mjs +18 -7
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-state.mjs +5 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/text-relay.mjs +9 -1
- package/src/runtime/agent/orchestrator/providers/openai-model-capabilities.mjs +80 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +71 -24
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +323 -0
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +44 -16
- package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +7 -16
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/refusals.mjs +60 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/tool-calls.mjs +51 -35
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state.mjs +30 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +12 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/terminal-frames.mjs +25 -6
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +11 -3
- package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +170 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +75 -70
- package/src/runtime/agent/orchestrator/providers/openrouter.mjs +75 -0
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +147 -8
- package/src/runtime/agent/orchestrator/providers/registry.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +5 -0
- package/src/runtime/agent/orchestrator/providers/transport-scope.d.mts +6 -0
- package/src/runtime/agent/orchestrator/providers/transport-scope.mjs +28 -0
- package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +157 -0
- package/src/runtime/agent/orchestrator/providers/wire-route.mjs +512 -0
- package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +1131 -0
- package/src/runtime/agent/orchestrator/providers/xai-tool-search.fixtures.mjs +183 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +100 -0
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +21 -0
- package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +15 -0
- package/src/runtime/agent/orchestrator/runtime-core/provider-request-snapshot.mjs +7 -3
- package/src/runtime/agent/orchestrator/runtime-core/session-title.mjs +21 -1
- package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +14 -3
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +526 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +10 -7
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +176 -71
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +62 -10
- package/src/runtime/agent/orchestrator/runtime-core/tool-exposure.mjs +96 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/compact/constants.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +14 -93
- package/src/runtime/agent/orchestrator/session/compact/summary-anchor.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +120 -0
- package/src/runtime/agent/orchestrator/session/context-tool-schema.mjs +17 -2
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -4
- package/src/runtime/agent/orchestrator/session/eager-dispatch/admission.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +6 -1
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +91 -1
- package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +56 -0
- package/src/runtime/agent/orchestrator/session/loop/deferred-call-through.mjs +18 -8
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +21 -10
- package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +132 -0
- package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +30 -0
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +63 -20
- package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-call-resolution.mjs +95 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +30 -3
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +15 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +15 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +150 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +34 -12
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +57 -25
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +208 -14
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +15 -3
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +25 -3
- package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +82 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +19 -2
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/manager.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +13 -0
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +96 -0
- package/src/runtime/agent/orchestrator/session/side-question.mjs +192 -0
- package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +17 -3
- package/src/runtime/agent/orchestrator/session/store/live-state.mjs +23 -0
- package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +58 -2
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +41 -28
- package/src/runtime/agent/orchestrator/session/store/session-observers.mjs +4 -2
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +12 -1
- package/src/runtime/agent/orchestrator/session/store/write-admission.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/store-summary-archived-agent.mjs +34 -15
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +10 -1
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +10 -2
- package/src/runtime/agent/orchestrator/session/store.mjs +19 -3
- package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/tool-batch/state.mjs +7 -1
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/tool-schema-rejection.mjs +77 -0
- package/src/runtime/agent/orchestrator/tools/bash-policy-scan.mjs +8 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/command-preflight.mjs +3 -3
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +4 -1
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +14 -10
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +49 -34
- package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +23 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch/ui-diff.mjs +73 -39
- package/src/runtime/agent/orchestrator/tools/progress-message.mjs +18 -1
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -4
- package/src/runtime/agent/orchestrator/tools/shell-exec-policy.mjs +88 -12
- package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +2 -0
- package/src/runtime/computer-bridge/action-schema.mjs +44 -21
- package/src/runtime/github/tool.mjs +92 -2
- package/src/runtime/memory/index.mjs +1 -0
- package/src/runtime/memory/lib/http-router/ingest-routes.mjs +22 -1
- package/src/runtime/memory/lib/ingest/transcript-offsets.mjs +2 -0
- package/src/runtime/memory/lib/pg/adapter.mjs +98 -1
- package/src/runtime/memory/lib/pg/process.mjs +31 -26
- package/src/runtime/memory/lib/pg/run-child.mjs +49 -0
- package/src/runtime/memory/lib/pg/supervisor.mjs +108 -3
- package/src/runtime/memory/lib/runtime-fetcher.mjs +12 -13
- package/src/runtime/memory/lib/transcript-ingest.mjs +14 -0
- package/src/runtime/office/README.md +1 -1
- package/src/runtime/office/authoring/html-document-author.mjs +2 -0
- package/src/runtime/office/authoring/pptx-contact-sheet.mjs +2 -0
- package/src/runtime/office/authoring/pptx-html-measure.mjs +2 -0
- package/src/runtime/office/authoring/pptx-html-runner.mjs +2 -0
- package/src/runtime/office/authoring/xlsx-html-runner.mjs +2 -0
- package/src/runtime/office/core/office-actions-read.mjs +3 -0
- package/src/runtime/office/core/office-render-preview.mjs +2 -0
- package/src/runtime/office/core/office-session-dispatch.mjs +7 -0
- package/src/runtime/office/core/office-sessionless-actions.mjs +8 -0
- package/src/runtime/office/core/office-sessions.mjs +5 -0
- package/src/runtime/office/core/office-transactions.mjs +3 -0
- package/src/runtime/office/core/office-write-ledger.mjs +98 -0
- package/src/runtime/office/design/library/templates/mixdog-executive.mixdog-edit.pptx +0 -0
- package/src/runtime/office/index.mjs +30 -0
- package/src/runtime/office/pdf/pdf-edit-document.mjs +2 -0
- package/src/runtime/office/pdf/pdf-render.mjs +23 -7
- package/src/runtime/office/pdf/pdf-security.mjs +2 -0
- package/src/runtime/office/portable/portable-opc.mjs +4 -1
- package/src/runtime/office/quality/visual-diff.mjs +2 -0
- package/src/runtime/shared/bounded-file-read.mjs +13 -0
- package/src/runtime/shared/bounded-line-diff.mjs +182 -0
- package/src/runtime/shared/buffered-appender.mjs +18 -0
- package/src/runtime/shared/config.mjs +78 -18
- package/src/runtime/shared/err-text.mjs +6 -0
- package/src/runtime/shared/file-permissions.d.mts +6 -1
- package/src/runtime/shared/file-permissions.mjs +54 -6
- package/src/runtime/shared/llm/anthropic-effort.mjs +6 -0
- package/src/runtime/shared/llm/usage-accounting.mjs +5 -2
- package/src/runtime/shared/llm/usage-ledger-rollup.mjs +3 -0
- package/src/runtime/shared/loopback-listener.mjs +9 -0
- package/src/runtime/shared/provider-api-key.mjs +2 -0
- package/src/runtime/shared/review-diff.mjs +52 -0
- package/src/runtime/shared/session-sidebar-host.d.mts +4 -0
- package/src/runtime/shared/session-sidebar-host.mjs +38 -0
- package/src/runtime/shared/slow-span.mjs +114 -0
- package/src/runtime/shared/statusline/statusline-segments.mjs +28 -4
- package/src/runtime/shared/tool-card-model/card-header.mjs +6 -1
- package/src/runtime/shared/tool-card-model/generic-detail.mjs +39 -5
- package/src/runtime/shared/tool-card-model.mjs +5 -2
- package/src/runtime/shared/tool-output-limit.mjs +4 -0
- package/src/runtime/shared/tool-primitives.mjs +13 -0
- package/src/runtime/shared/tool-result-summary.mjs +8 -1
- package/src/runtime/shared/tool-surface.mjs +18 -3
- package/src/runtime/shared/tool-work-units.mjs +40 -4
- package/src/runtime/shared/transcript-writer/purge.mjs +74 -0
- package/src/runtime/shared/transcript-writer.mjs +10 -2
- package/src/runtime/shared/turn-changes.mjs +268 -100
- package/src/runtime/shared/turn-review-reply.mjs +8 -39
- package/src/runtime/shared/turn-snapshot-store.mjs +19 -108
- package/src/runtime/shared/turn-snapshot.mjs +857 -683
- package/src/runtime/shared/turn-worktree-snapshot.mjs +183 -255
- package/src/runtime/shared/user-data-guard.mjs +262 -49
- package/src/runtime/shared/worktrees/carry.mjs +531 -0
- package/src/runtime/shared/worktrees/contract.mjs +34 -0
- package/src/runtime/shared/worktrees/file-recovery.mjs +68 -0
- package/src/runtime/shared/worktrees/git-head.mjs +205 -0
- package/src/runtime/shared/worktrees/git.mjs +8 -3
- package/src/runtime/shared/worktrees/maintenance.mjs +1 -1
- package/src/runtime/shared/worktrees/manager.mjs +156 -8
- package/src/runtime/shared/worktrees/merge.mjs +31 -21
- package/src/runtime/shared/worktrees/paths.d.mts +6 -0
- package/src/runtime/terminal-bridge/client.mjs +44 -11
- package/src/runtime/terminal-bridge/tool-defs.mjs +13 -6
- package/src/runtime/tidy/apply.mjs +47 -2
- package/src/runtime/tidy/run-engines.mjs +11 -5
- package/src/session-runtime/agent-tool-routing.mjs +19 -13
- package/src/session-runtime/boot/apis.mjs +13 -5
- package/src/session-runtime/boot/facade.mjs +1 -0
- package/src/session-runtime/boot/infrastructure.mjs +6 -1
- package/src/session-runtime/boot/session.mjs +0 -1
- package/src/session-runtime/boot/tools.mjs +4 -1
- package/src/session-runtime/cwd-plugins/cwd-apply.mjs +12 -5
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +65 -0
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -1
- package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +11 -4
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +115 -18
- package/src/session-runtime/internal-tool-executor.mjs +6 -2
- package/src/session-runtime/lifecycle/cold-heir.mjs +188 -0
- package/src/session-runtime/lifecycle/inheritance.mjs +71 -27
- package/src/session-runtime/lifecycle/session-catalog.mjs +12 -3
- package/src/session-runtime/lifecycle/session-switch/resume.mjs +6 -0
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +29 -6
- package/src/session-runtime/lifecycle/teardown.mjs +72 -7
- package/src/session-runtime/lifecycle-api.mjs +1 -0
- package/src/session-runtime/mcp-glue/connect.mjs +17 -5
- package/src/session-runtime/model-route/set-route.mjs +2 -2
- package/src/session-runtime/native-web-search-usage.mjs +51 -0
- package/src/session-runtime/native-web-search.mjs +10 -1
- package/src/session-runtime/new-session-config.mjs +4 -2
- package/src/session-runtime/provider-auth/login.mjs +4 -0
- package/src/session-runtime/resource-scope-decorate.mjs +10 -3
- package/src/session-runtime/runtime-review-api.mjs +8 -2
- package/src/session-runtime/services/agent-tool/index-write-queue.mjs +81 -20
- package/src/session-runtime/services/agent-tool/lead-worker-index/forgotten-leads.mjs +29 -0
- package/src/session-runtime/services/agent-tool/lead-worker-index/index-file.mjs +1 -1
- package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +73 -7
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +15 -1
- package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +10 -1
- package/src/session-runtime/services/agent-tool/worker-index.mjs +46 -7
- package/src/session-runtime/services/agent-tool.mjs +3 -0
- package/src/session-runtime/services/channel-admin.mjs +19 -3
- package/src/session-runtime/services/memory-runtime-proxy/calls.mjs +4 -0
- package/src/session-runtime/services/memory-runtime-proxy.mjs +1 -0
- package/src/session-runtime/services/provider-admin.mjs +81 -15
- package/src/session-runtime/session-transcript-purge.mjs +32 -0
- package/src/session-runtime/session-turn-api.mjs +14 -5
- package/src/session-runtime/settings-builtin-tools-api.mjs +9 -0
- package/src/session-runtime/setup-tool/executor.mjs +36 -6
- package/src/session-runtime/setup-tool/extended-actions.mjs +86 -6
- package/src/session-runtime/setup-tool/settings-contract.mjs +13 -3
- package/src/session-runtime/setup-tool/tool-defs.mjs +13 -4
- package/src/session-runtime/skills-api.mjs +3 -5
- package/src/session-runtime/tool-surface.mjs +5 -1
- package/src/session-runtime/turn/compaction-gate.mjs +25 -0
- package/src/session-runtime/turn/session-ops.mjs +7 -5
- package/src/session-runtime/turn/side-question-ops.mjs +22 -0
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +5 -1
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +8 -3
- package/src/session-runtime/turn/turn-run/turn-settle.mjs +10 -0
- package/src/session-runtime/turn/turn-run/turn-timing.mjs +4 -3
- package/src/session-runtime/turn/turn-run.mjs +25 -9
- package/src/session-runtime/usage-stats-api.mjs +43 -11
- package/src/session-runtime/workspace/project-branches.mjs +7 -5
- package/src/session-runtime/workspace/transition-steps.mjs +129 -31
- package/src/session-runtime/workspace/transitions.mjs +190 -15
- package/src/standalone/daemon-agent-control.mjs +9 -1
- package/src/standalone/daemon-local-session-bridge.mjs +14 -1
- package/src/standalone/daemon-owner.mjs +17 -4
- package/src/standalone/daemon-pg-stop.mjs +51 -0
- package/src/standalone/daemon-stop-budget.d.mts +2 -0
- package/src/standalone/daemon-stop-budget.mjs +18 -0
- package/src/standalone/daemon-stored-session-views.mjs +2 -0
- package/src/standalone/daemon-telemetry.mjs +19 -0
- package/src/standalone/daemon.mjs +61 -1
- package/src/standalone/desktop-service-registry.mjs +5 -0
- package/src/standalone/local-session-runtime.mjs +70 -19
- package/src/standalone/session-client.mjs +42 -0
- package/src/standalone/session-protocol.mjs +7 -0
- package/src/standalone/session-proxy/projection.mjs +41 -4
- package/src/standalone/session-runtime-inline-host/boot-loaders.mjs +15 -1
- package/src/standalone/session-runtime-inline-host.mjs +1 -0
- package/src/standalone/session-service/session-calls/session-action.mjs +18 -3
- package/src/standalone/session-service-api.mjs +6 -1
- package/src/standalone/session-state-patch.d.mts +2 -1
- package/src/standalone/session-state-patch.mjs +41 -1
- package/src/tui/App.jsx +25 -0
- package/src/tui/app/app-view/floating-panel.jsx +26 -1
- package/src/tui/app/btw-controller.mjs +118 -0
- package/src/tui/app/create-app-pickers.mjs +2 -0
- package/src/tui/app/shell-layout/row-budgets.mjs +11 -1
- package/src/tui/app/shell-layout/surfaces.mjs +3 -1
- package/src/tui/app/slash-commands.mjs +13 -3
- package/src/tui/app/slash-dispatch/session-commands.mjs +19 -6
- package/src/tui/app/use-global-key-input/approval-shortcut.mjs +12 -0
- package/src/tui/app/use-global-key-input.mjs +5 -12
- package/src/tui/app/use-prompt-handlers.mjs +11 -0
- package/src/tui/components/BtwPanel.jsx +53 -0
- package/src/tui/components/QuestionPanel.jsx +275 -0
- package/src/tui/components/question-panel-model.mjs +156 -0
- package/src/tui/dist/index.mjs +2413 -1465
- package/src/tui/session/context-state.mjs +4 -2
- package/src/tui/session/session-api/commands.mjs +10 -0
- package/src/tui/session/session-api/controls.mjs +2 -2
- package/src/tui/session/session-api/integrations.mjs +9 -2
- package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
- package/src/tui/session/session-api/lifecycle.mjs +2 -1
- package/src/tui/session/session-api/settings.mjs +6 -0
- package/src/tui/session/session-api.mjs +1 -0
- package/src/tui/session/tool-approval.mjs +10 -7
- package/src/tui/session/transcript-spill.mjs +14 -7
- package/src/tui/session/turn-stream.mjs +174 -31
- package/src/tui/session/turn.mjs +12 -5
- package/src/workflows/default/WORKFLOW.md +3 -1
|
@@ -7,13 +7,17 @@
|
|
|
7
7
|
* `label`, `agent`, `provider`, `model`, `effort`, `fast`, `finished`) and the
|
|
8
8
|
* "\n\nResult:\n" marker are the wire format the notification writer emits;
|
|
9
9
|
* they are matched verbatim.
|
|
10
|
+
*
|
|
11
|
+
* Only the parent(s) named by metadata are read — never the sessions
|
|
12
|
+
* directory: every vanished id reaches this path (deleted Lead records too),
|
|
13
|
+
* and a synchronous scan of every session file froze the daemon loop.
|
|
10
14
|
*/
|
|
11
|
-
import {
|
|
15
|
+
import { readFile } from 'node:fs/promises';
|
|
12
16
|
import { join } from 'node:path';
|
|
13
|
-
import { probePath, PROBE_PRESENT } from './store/fs-probe.mjs';
|
|
14
17
|
import { readTopLevelLifecycleRecord, isLifecycleUnreadable } from './lifecycle-scan.mjs';
|
|
15
18
|
import { dataDir } from './store-summary-locations.mjs';
|
|
16
|
-
import {
|
|
19
|
+
import { listStoredAgentWorkerLinks } from './store-agent-worker-rows.mjs';
|
|
20
|
+
import { cleanValue, desktopSession, isStoredSessionId, positiveNumber } from './store-summary-fields.mjs';
|
|
17
21
|
|
|
18
22
|
function archivedAgentNotification(content, sessionId) {
|
|
19
23
|
const text = typeof content === 'string' ? content : '';
|
|
@@ -52,23 +56,38 @@ function archivedAgentNotification(content, sessionId) {
|
|
|
52
56
|
};
|
|
53
57
|
}
|
|
54
58
|
|
|
59
|
+
/** Parent session ids metadata names for `sessionId`: its agent-workers.json
|
|
60
|
+
* link and its summary-catalog row (`catalogRow(id)`, optional). */
|
|
61
|
+
function parentSessionIds(sessionId, catalogRow) {
|
|
62
|
+
const parents = new Set();
|
|
63
|
+
for (const link of listStoredAgentWorkerLinks()) {
|
|
64
|
+
if (link.sessionId !== sessionId) continue;
|
|
65
|
+
parents.add(link.parentSessionId);
|
|
66
|
+
parents.add(link.ownerSessionId);
|
|
67
|
+
}
|
|
68
|
+
const row = typeof catalogRow === 'function' ? catalogRow(sessionId) : null;
|
|
69
|
+
if (row) {
|
|
70
|
+
parents.add(cleanValue(row.parentSessionId));
|
|
71
|
+
parents.add(cleanValue(row.ownerSessionId));
|
|
72
|
+
}
|
|
73
|
+
parents.delete(sessionId);
|
|
74
|
+
return [...parents].filter(isStoredSessionId);
|
|
75
|
+
}
|
|
76
|
+
|
|
55
77
|
/** Legacy recovery for child transcripts already unlinked by terminal reaping.
|
|
56
|
-
* The parent owns one canonical body-carrying completion notification
|
|
57
|
-
* only
|
|
58
|
-
|
|
78
|
+
* The parent owns one canonical body-carrying completion notification: read
|
|
79
|
+
* only the parent(s) metadata links the child to, asynchronously, and project
|
|
80
|
+
* the newest valid body. An id with no parent link (a deleted Lead record)
|
|
81
|
+
* resolves to null without touching any session file. */
|
|
82
|
+
export async function readArchivedAgentResult(sessionId, { catalogRow } = {}) {
|
|
83
|
+
const parents = parentSessionIds(sessionId, catalogRow);
|
|
84
|
+
if (parents.length === 0) return null;
|
|
59
85
|
const dir = join(dataDir(), 'sessions');
|
|
60
|
-
if (probePath(dir).state !== PROBE_PRESENT) return null;
|
|
61
|
-
let files;
|
|
62
|
-
try {
|
|
63
|
-
files = readdirSync(dir).filter((file) => file.endsWith('.json'));
|
|
64
|
-
} catch {
|
|
65
|
-
return null;
|
|
66
|
-
}
|
|
67
86
|
let best = null;
|
|
68
|
-
for (const
|
|
87
|
+
for (const parentId of parents) {
|
|
69
88
|
let raw;
|
|
70
89
|
try {
|
|
71
|
-
raw =
|
|
90
|
+
raw = await readFile(join(dir, `${parentId}.json`), 'utf8');
|
|
72
91
|
} catch {
|
|
73
92
|
continue;
|
|
74
93
|
}
|
|
@@ -24,8 +24,10 @@ import {
|
|
|
24
24
|
inheritedFromSessionId,
|
|
25
25
|
isStoredSessionId,
|
|
26
26
|
positiveNumber,
|
|
27
|
+
realTurnCount,
|
|
27
28
|
workspaceSummary,
|
|
28
29
|
} from './store-summary-fields.mjs';
|
|
30
|
+
import { isRealTurnMessage } from './compact/user-message-kind.mjs';
|
|
29
31
|
import { byActivityThenId } from './catalog-db/schema.mjs';
|
|
30
32
|
import {
|
|
31
33
|
sessionStampOf,
|
|
@@ -182,6 +184,7 @@ export function normalizedRow(row, heartbeatAt = 0) {
|
|
|
182
184
|
permission: row.permission || null,
|
|
183
185
|
toolPermission: row.toolPermission || null,
|
|
184
186
|
messageCount: Math.max(0, Math.floor(Number(row.messageCount) || 0)),
|
|
187
|
+
realTurnCount: realTurnCount(row),
|
|
185
188
|
title: cleanText(row.title, 100),
|
|
186
189
|
preview: cleanText(row.preview),
|
|
187
190
|
generation: typeof row.generation === 'number' ? row.generation : 0,
|
|
@@ -240,6 +243,7 @@ function rowFromSession(session, heartbeatAt = 0) {
|
|
|
240
243
|
{
|
|
241
244
|
...session,
|
|
242
245
|
messageCount: messages.filter((message) => message?.role === 'user' || message?.role === 'assistant').length,
|
|
246
|
+
realTurnCount: messages.filter(isRealTurnMessage).length,
|
|
243
247
|
preview,
|
|
244
248
|
},
|
|
245
249
|
heartbeatAt
|
|
@@ -55,6 +55,14 @@ export function inheritedFromSessionId(value) {
|
|
|
55
55
|
return id || null;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
/** Count of real human turns a session persisted (actual user instructions
|
|
59
|
+
* plus compact summaries, which stand for earlier human turns); null for a
|
|
60
|
+
* row written before the field existed. */
|
|
61
|
+
export function realTurnCount(value) {
|
|
62
|
+
const count = value?.realTurnCount;
|
|
63
|
+
return typeof count === 'number' && Number.isFinite(count) && count >= 0 ? Math.floor(count) : null;
|
|
64
|
+
}
|
|
65
|
+
|
|
58
66
|
export function importKey(value) {
|
|
59
67
|
const key = typeof value?.importKey === 'string' ? value.importKey : value?.importOrigin?.key;
|
|
60
68
|
return typeof key === 'string' && key.trim() ? key : null;
|
|
@@ -23,8 +23,10 @@ import {
|
|
|
23
23
|
inheritedFromSessionId,
|
|
24
24
|
isStoredSessionId,
|
|
25
25
|
positiveNumber as _positiveNumber,
|
|
26
|
+
realTurnCount,
|
|
26
27
|
workspaceSummary,
|
|
27
28
|
} from './store-summary-fields.mjs';
|
|
29
|
+
import { isRealTurnMessage } from './compact/user-message-kind.mjs';
|
|
28
30
|
|
|
29
31
|
export const SESSION_SUMMARY_INDEX_VERSION = 2;
|
|
30
32
|
|
|
@@ -92,6 +94,7 @@ function _sessionMessageProjection(session) {
|
|
|
92
94
|
const cached = session && typeof session === 'object' ? sessionMessageProjectionMemo.get(session) : null;
|
|
93
95
|
let start = 0;
|
|
94
96
|
let count = 0;
|
|
97
|
+
let real = 0;
|
|
95
98
|
let preview = '';
|
|
96
99
|
let previewMessage = null;
|
|
97
100
|
const canAppend =
|
|
@@ -101,6 +104,7 @@ function _sessionMessageProjection(session) {
|
|
|
101
104
|
if (canAppend) {
|
|
102
105
|
start = cached.length;
|
|
103
106
|
count = cached.count;
|
|
107
|
+
real = cached.real;
|
|
104
108
|
preview = cached.preview;
|
|
105
109
|
previewMessage = cached.previewMessage;
|
|
106
110
|
// The first real user message is stable in normal append-only session
|
|
@@ -112,6 +116,7 @@ function _sessionMessageProjection(session) {
|
|
|
112
116
|
else {
|
|
113
117
|
start = 0;
|
|
114
118
|
count = 0;
|
|
119
|
+
real = 0;
|
|
115
120
|
preview = '';
|
|
116
121
|
previewMessage = null;
|
|
117
122
|
}
|
|
@@ -120,6 +125,7 @@ function _sessionMessageProjection(session) {
|
|
|
120
125
|
for (let index = start; index < messages.length; index += 1) {
|
|
121
126
|
const message = messages[index];
|
|
122
127
|
if (message && (message.role === 'user' || message.role === 'assistant')) count += 1;
|
|
128
|
+
if (isRealTurnMessage(message)) real += 1;
|
|
123
129
|
if (!preview) {
|
|
124
130
|
const candidate = _previewFromMessage(message);
|
|
125
131
|
if (candidate) {
|
|
@@ -133,11 +139,12 @@ function _sessionMessageProjection(session) {
|
|
|
133
139
|
length: messages.length,
|
|
134
140
|
lastMessage: messages[messages.length - 1] || null,
|
|
135
141
|
count,
|
|
142
|
+
real,
|
|
136
143
|
preview,
|
|
137
144
|
previewMessage,
|
|
138
145
|
});
|
|
139
146
|
}
|
|
140
|
-
return { count, preview };
|
|
147
|
+
return { count, real, preview };
|
|
141
148
|
}
|
|
142
149
|
|
|
143
150
|
function _desktopSessionSummary(value, cwd = null) {
|
|
@@ -199,6 +206,7 @@ export function _sessionSummary(session) {
|
|
|
199
206
|
: null,
|
|
200
207
|
taskType: session.taskType || null,
|
|
201
208
|
messageCount: messageProjection.count,
|
|
209
|
+
realTurnCount: messageProjection.real,
|
|
202
210
|
title: _cleanPreview(session.title || '', 100),
|
|
203
211
|
preview: messageProjection.preview,
|
|
204
212
|
generation: typeof session.generation === 'number' ? session.generation : 0,
|
|
@@ -253,6 +261,7 @@ function _normalizeSummaryRow(row) {
|
|
|
253
261
|
: null,
|
|
254
262
|
taskType: row.taskType || null,
|
|
255
263
|
messageCount: Math.max(0, Math.floor(Number(row.messageCount) || 0)),
|
|
264
|
+
realTurnCount: realTurnCount(row),
|
|
256
265
|
title: _cleanPreview(row.title || '', 100),
|
|
257
266
|
preview: _cleanPreview(row.preview || ''),
|
|
258
267
|
generation: typeof row.generation === 'number' ? row.generation : 0,
|
|
@@ -250,6 +250,14 @@ function storedSessionMetadata(sessionId, session) {
|
|
|
250
250
|
};
|
|
251
251
|
}
|
|
252
252
|
|
|
253
|
+
/** A record that is gone may be a reaped agent child: its parent is resolved
|
|
254
|
+
* from metadata only (worker link, summary-index row), never by a scan. */
|
|
255
|
+
function readVanishedSessionTranscript(sessionId) {
|
|
256
|
+
return readArchivedAgentResult(sessionId, {
|
|
257
|
+
catalogRow: (id) => ordinaryCatalog.loadIndex().rowsById.get(id) || null,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
|
|
253
261
|
/** The two files a stored transcript projection is built from. */
|
|
254
262
|
function storedTranscriptInputPaths(sessionId) {
|
|
255
263
|
return {
|
|
@@ -375,7 +383,7 @@ export async function readStoredSessionTranscript(id, options = {}) {
|
|
|
375
383
|
// Phase durations of the parse this call ran (absent on a cache hit).
|
|
376
384
|
const timing = {};
|
|
377
385
|
const recordStat = probePath(recordPath);
|
|
378
|
-
if (recordStat.state === PROBE_ABSENT) return
|
|
386
|
+
if (recordStat.state === PROBE_ABSENT) return readVanishedSessionTranscript(sessionId);
|
|
379
387
|
if (recordStat.state !== PROBE_PRESENT) return null;
|
|
380
388
|
const checkpoint = probePath(checkpointPath);
|
|
381
389
|
const archive = probePath(archivePath);
|
|
@@ -441,7 +449,7 @@ export async function readStoredSessionTranscript(id, options = {}) {
|
|
|
441
449
|
produce: (text) => produceStoredTranscript(text, readStamp, produceContext),
|
|
442
450
|
});
|
|
443
451
|
// The record vanished between stat and read: same answer as an absent probe.
|
|
444
|
-
if (readState === PROBE_ABSENT) return
|
|
452
|
+
if (readState === PROBE_ABSENT) return readVanishedSessionTranscript(sessionId);
|
|
445
453
|
if (typeof options.trace === 'function') {
|
|
446
454
|
options.trace({
|
|
447
455
|
sessionId,
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Sessions are saved to disk so CLI and MCP server can share state,
|
|
4
4
|
* and sessions survive server restarts (resume).
|
|
5
5
|
*/
|
|
6
|
-
import { writeFileSync } from 'node:fs';
|
|
6
|
+
import { closeSync, fsyncSync, openSync, writeFileSync } from 'node:fs';
|
|
7
7
|
import * as fsp from 'node:fs/promises';
|
|
8
8
|
import { randomBytes } from 'node:crypto';
|
|
9
9
|
import { sessionPath } from './store/paths-heartbeat.mjs';
|
|
@@ -354,7 +354,15 @@ function _doSaveSync(payload) {
|
|
|
354
354
|
attempted = JSON.stringify(disk);
|
|
355
355
|
// The lifecycle these exact bytes carry, recorded with the commit stamp.
|
|
356
356
|
const lifecycle = _lifecycleOfSessionDocument(disk);
|
|
357
|
-
|
|
357
|
+
// fsync before the rename: without it an OS crash can publish the
|
|
358
|
+
// renamed file with its data blocks never written (all-NUL record).
|
|
359
|
+
const fd = openSync(tmp, 'w');
|
|
360
|
+
try {
|
|
361
|
+
writeFileSync(fd, attempted, 'utf-8');
|
|
362
|
+
fsyncSync(fd);
|
|
363
|
+
} finally {
|
|
364
|
+
closeSync(fd);
|
|
365
|
+
}
|
|
358
366
|
if (_shouldDrop(id, opts, attempt)) {
|
|
359
367
|
_discardSaveTmp(tmp);
|
|
360
368
|
if (mayMutate()) _recordSaveDrop(id, epoch);
|
|
@@ -636,7 +644,14 @@ async function _doSave(payload) {
|
|
|
636
644
|
attempted = JSON.stringify(disk);
|
|
637
645
|
// Captured before the await: the lifecycle of exactly these bytes.
|
|
638
646
|
const lifecycle = _lifecycleOfSessionDocument(disk);
|
|
639
|
-
|
|
647
|
+
// fsync before the rename (see _doSaveSync).
|
|
648
|
+
const handle = await fsp.open(tmp, 'w');
|
|
649
|
+
try {
|
|
650
|
+
await handle.writeFile(attempted, 'utf-8');
|
|
651
|
+
await handle.sync();
|
|
652
|
+
} finally {
|
|
653
|
+
await handle.close();
|
|
654
|
+
}
|
|
640
655
|
// Second check: between the temp write and the rename, closeSession()
|
|
641
656
|
// may have planted a tombstone. Re-check on disk; if a newer tombstone
|
|
642
657
|
// now exists, discard our temp file rather than let rename clobber it.
|
|
@@ -706,6 +721,7 @@ export { loadSession } from './store/load-session.mjs';
|
|
|
706
721
|
// Hard delete + owned-agent enumeration live in store/session-delete.mjs;
|
|
707
722
|
// re-exported here so prior importers of store.mjs stay unchanged.
|
|
708
723
|
export { deleteSession, listOwnedAgentSessionIds } from './store/session-delete.mjs';
|
|
724
|
+
export { fenceSessionWrites } from './store/live-state.mjs';
|
|
709
725
|
|
|
710
726
|
// Listing / summaries live in store/listing.mjs and the stale sweep in
|
|
711
727
|
// store/sweep/stale-sweep.mjs; re-exported here so importers keep one
|
|
@@ -208,6 +208,7 @@ function invocationOptions(batch, call, exec) {
|
|
|
208
208
|
iteration: batch.iterations,
|
|
209
209
|
localSearchTelemetry: exec.localSearchTelemetry || {},
|
|
210
210
|
resultTelemetry: exec.resultTelemetry,
|
|
211
|
+
...(call.wireCall ? { bridgeWireCall: call.wireCall } : {}),
|
|
211
212
|
};
|
|
212
213
|
}
|
|
213
214
|
|
|
@@ -319,7 +319,7 @@ function stagePostProcessingFailure(batch, completed, postErr, postprocessStarte
|
|
|
319
319
|
if (sessionRef?._scopedCacheOutcomeByCallId instanceof Map && call?.id) {
|
|
320
320
|
sessionRef._scopedCacheOutcomeByCallId.delete(call.id);
|
|
321
321
|
}
|
|
322
|
-
if (call?.id) restoreToolCallBodyForId(batch.assistantTurnMsg, batch.
|
|
322
|
+
if (call?.id) restoreToolCallBodyForId(batch.assistantTurnMsg, batch.wireCalls, call.id);
|
|
323
323
|
const message = `Error: tool result post-processing failed for "${call.name}": ${postErr instanceof Error ? postErr.message : String(postErr)}`;
|
|
324
324
|
traceAgentToolFailure({
|
|
325
325
|
sessionId: batch.sessionId,
|
|
@@ -46,7 +46,7 @@ export async function recordCallOutcome(batch, call, exec, sigs, ctSig) {
|
|
|
46
46
|
// otherwise hide behind a `[mixdog compacted …]` placeholder). Restored
|
|
47
47
|
// immediately so an abort or post-processing throw cannot leave it
|
|
48
48
|
// compacted; early-skipped calls stay compacted.
|
|
49
|
-
if (executed && failed && call?.id) restoreToolCallBodyForId(batch.assistantTurnMsg, batch.
|
|
49
|
+
if (executed && failed && call?.id) restoreToolCallBodyForId(batch.assistantTurnMsg, batch.wireCalls, call.id);
|
|
50
50
|
if (sessionId && _stripMcpPrefix(call.name) === 'apply_patch') {
|
|
51
51
|
if (exec.executeOk && exec.resultKind === 'normal') invalidateAfterPatch(sessionId, call, cwd);
|
|
52
52
|
// Mutation tools invalidate even on returned-error/partial-fail — the
|
|
@@ -4,11 +4,17 @@
|
|
|
4
4
|
// live here so processToolBatch can hand them back.
|
|
5
5
|
import { executeTool } from '../loop/tool-exec.mjs';
|
|
6
6
|
import { planToolBatch } from './plan.mjs';
|
|
7
|
+
import { bridgeClassificationTools, resolveExecutionToolCalls } from '../loop/tool-call-resolution.mjs';
|
|
7
8
|
|
|
8
9
|
export function createBatchState(ctx) {
|
|
9
|
-
const {
|
|
10
|
+
const { assistantTurnMsg, sessionRef } = ctx;
|
|
11
|
+
// Bridged call_tool requests run as their targets from here on; the wire
|
|
12
|
+
// calls stay authoritative for the transcript and failed-argument restore.
|
|
13
|
+
const calls = resolveExecutionToolCalls(ctx.calls, sessionRef);
|
|
14
|
+
const tools = bridgeClassificationTools(ctx.tools, calls);
|
|
10
15
|
return {
|
|
11
16
|
calls,
|
|
17
|
+
wireCalls: ctx.calls,
|
|
12
18
|
messages: ctx.messages,
|
|
13
19
|
tools,
|
|
14
20
|
cwd: ctx.cwd,
|
|
@@ -19,8 +19,10 @@ import { getPluginData } from '../config.mjs';
|
|
|
19
19
|
import { countSplitLines, normalizeOutputPath } from '../tools/builtin/path-utils.mjs';
|
|
20
20
|
import { classifyResultKind } from './result-classification.mjs';
|
|
21
21
|
import { registerSessionPurgeHook } from './store.mjs';
|
|
22
|
+
import { SETUP_OUTPUT_MAX_BYTES } from '../../../shared/tool-output-limit.mjs';
|
|
22
23
|
|
|
23
24
|
const TOOL_RESULT_OFFLOAD_THRESHOLD_CHARS = 50_000;
|
|
25
|
+
const TOOL_RESULT_SETUP_THRESHOLD_CHARS = SETUP_OUTPUT_MAX_BYTES;
|
|
24
26
|
const TOOL_RESULT_PREVIEW_CHARS = 512;
|
|
25
27
|
const TOOL_RESULT_SHELL_THRESHOLD_CHARS = 30_000;
|
|
26
28
|
const TOOL_RESULT_SEARCH_THRESHOLD_CHARS = 50_000;
|
|
@@ -61,6 +63,7 @@ const INLINE_THRESHOLD_BY_TOOL = new Map([
|
|
|
61
63
|
['bash_session', TOOL_RESULT_SHELL_THRESHOLD_CHARS],
|
|
62
64
|
['terminal', TOOL_RESULT_SHELL_THRESHOLD_CHARS],
|
|
63
65
|
['task', TOOL_RESULT_SHELL_THRESHOLD_CHARS],
|
|
66
|
+
['setup', TOOL_RESULT_SETUP_THRESHOLD_CHARS],
|
|
64
67
|
]);
|
|
65
68
|
|
|
66
69
|
function getOffloadThreshold(toolName) {
|
|
@@ -554,6 +557,7 @@ export const _internals = {
|
|
|
554
557
|
TOOL_RESULT_SHELL_THRESHOLD_CHARS,
|
|
555
558
|
TOOL_RESULT_SEARCH_THRESHOLD_CHARS,
|
|
556
559
|
TOOL_RESULT_GREP_THRESHOLD_CHARS,
|
|
560
|
+
TOOL_RESULT_SETUP_THRESHOLD_CHARS,
|
|
557
561
|
getOffloadThreshold,
|
|
558
562
|
TOOL_RESULT_PREVIEW_CHARS,
|
|
559
563
|
TOOL_RESULT_MESSAGE_MAX_CHARS,
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// A provider 400 that names one tool's input schema (Anthropic
|
|
2
|
+
// `tools.3.custom.input_schema`, OpenAI `Invalid schema for function 'x'` /
|
|
3
|
+
// `tools[3].parameters`, Gemini `function_declarations[3]`): which tool of the
|
|
4
|
+
// request it is, so the session can drop it instead of failing every turn.
|
|
5
|
+
import { providerToolExclusionReason } from './loop/provider-tool-exclusions.mjs';
|
|
6
|
+
import { providerNativeToolPrefixCount } from '../runtime-core/provider-request-tools.mjs';
|
|
7
|
+
|
|
8
|
+
const MAX_REASON_CHARS = 240;
|
|
9
|
+
|
|
10
|
+
const text = (value) => (typeof value === 'string' ? value : '');
|
|
11
|
+
|
|
12
|
+
// Provider-structured places a rejection names its field, best evidence first:
|
|
13
|
+
// OpenAI `param` (also nested under `error`), Anthropic / OpenAI `error.message`,
|
|
14
|
+
// Google `details[].fieldViolations[].field`, then a JSON body, then the
|
|
15
|
+
// error's own message.
|
|
16
|
+
function evidence(error) {
|
|
17
|
+
const nested = [error?.error, error?.providerError, error?.response?.data?.error, error?.response?.data];
|
|
18
|
+
const violations = [error?.details, error?.error?.details, error?.errorDetails]
|
|
19
|
+
.flatMap((details) => (Array.isArray(details) ? details : []))
|
|
20
|
+
.flatMap((detail) => (Array.isArray(detail?.fieldViolations) ? detail.fieldViolations : []))
|
|
21
|
+
.flatMap((violation) => [text(violation?.field), text(violation?.description)]);
|
|
22
|
+
const bodies = [error?.body, error?.responseBody].map((body) => {
|
|
23
|
+
if (typeof body !== 'string') return [];
|
|
24
|
+
try {
|
|
25
|
+
const parsed = JSON.parse(body);
|
|
26
|
+
return [text(parsed?.error?.param), text(parsed?.error?.message), text(parsed?.message)];
|
|
27
|
+
} catch {
|
|
28
|
+
return [body];
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
return [
|
|
32
|
+
error?.param,
|
|
33
|
+
...nested.map((entry) => entry?.param),
|
|
34
|
+
...nested.map((entry) => entry?.message),
|
|
35
|
+
...violations,
|
|
36
|
+
...bodies.flat(),
|
|
37
|
+
error?.message,
|
|
38
|
+
error?.cause?.message,
|
|
39
|
+
].filter((entry) => typeof entry === 'string' && entry);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// One piece of evidence -> which tool: a wire index (`byIndex`, with the
|
|
43
|
+
// OpenAI Responses hosted-tool offset when `shifted`) or a function name.
|
|
44
|
+
function target(entry) {
|
|
45
|
+
let match = /\btools\.(\d+)\.(?:custom\.)?input_schema/.exec(entry);
|
|
46
|
+
if (match) return { index: Number(match[1]) };
|
|
47
|
+
match = /\btools(?:\[(\d+)\]|\.(\d+))\.(?:function\.)?parameters/.exec(entry);
|
|
48
|
+
if (match) return { index: Number(match[1] ?? match[2]), shifted: true };
|
|
49
|
+
match = /\b(?:function_declarations|functionDeclarations)(?:\[(\d+)\]|\.(\d+))/.exec(entry);
|
|
50
|
+
if (match) return { index: Number(match[1] ?? match[2]) };
|
|
51
|
+
match = /Invalid schema for function ['"`]([^'"`]+)['"`]/.exec(entry);
|
|
52
|
+
if (match) return { name: match[1] };
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** `{ name, pointer, reason }` of the tool a schema 400 points at, or null (any
|
|
57
|
+
* other error, or a tool that is not part of the request's own tools). */
|
|
58
|
+
export function rejectedToolSchema(error, { sendTools, sessionRef, opts }) {
|
|
59
|
+
if ((error?.httpStatus ?? error?.status ?? error?.statusCode) !== 400) return null;
|
|
60
|
+
const tools = Array.isArray(sendTools) ? sendTools : [];
|
|
61
|
+
const nativeCount = providerNativeToolPrefixCount(tools);
|
|
62
|
+
// The wire list: the request's tools minus those the wire left out.
|
|
63
|
+
const wire = tools.filter((tool) => !providerToolExclusionReason(sessionRef, tool?.name));
|
|
64
|
+
const hosted = sessionRef?.wireRoute?.wire !== 'chat' && Array.isArray(opts?.nativeTools) ? opts.nativeTools.length : 0;
|
|
65
|
+
const entries = evidence(error);
|
|
66
|
+
let name = '';
|
|
67
|
+
for (const entry of entries) {
|
|
68
|
+
const found = target(entry);
|
|
69
|
+
if (!found) continue;
|
|
70
|
+
const tool = found.name ? wire.find((t) => t?.name === found.name) : wire[found.index - (found.shifted ? hosted : 0)];
|
|
71
|
+
name = typeof tool?.name === 'string' ? tool.name : '';
|
|
72
|
+
if (name) break;
|
|
73
|
+
}
|
|
74
|
+
if (!name || tools.findIndex((t) => t?.name === name) < nativeCount) return null;
|
|
75
|
+
const detail = entries.join(' ').replace(/\s+/g, ' ').trim().slice(0, MAX_REASON_CHARS);
|
|
76
|
+
return { name, pointer: '/', reason: `the provider rejected it with HTTP 400: ${detail}` };
|
|
77
|
+
}
|
|
@@ -68,6 +68,12 @@ export function buildBashPolicyScanTargets(command) {
|
|
|
68
68
|
return out;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
export function
|
|
72
|
-
return
|
|
71
|
+
export function evaluateExecPolicy(command) {
|
|
72
|
+
return evaluateExecPolicyFromTargets(buildBashPolicyScanTargets(command));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// `elevationApproved` is runtime-supplied: the user approved this call's
|
|
76
|
+
// 'ask' (elevation) decision. It never lifts a deny.
|
|
77
|
+
export function checkExecPolicyMessage(command, { elevationApproved = false } = {}) {
|
|
78
|
+
return formatExecPolicyBlockMessage(evaluateExecPolicy(command), { elevationApproved });
|
|
73
79
|
}
|
|
@@ -8,11 +8,11 @@ import { formatShellToolFailure } from './result-format.mjs';
|
|
|
8
8
|
// Policy + shell-specific rewrites before any shell dispatch. Returns either
|
|
9
9
|
// `{ failure }` (a formatted tool failure) or the command to run with the
|
|
10
10
|
// resolved shell spec and the wmic rewrite (if any).
|
|
11
|
-
export function prepareShellCommand(args) {
|
|
11
|
+
export function prepareShellCommand(args, { elevationApproved = false } = {}) {
|
|
12
12
|
// Run hard-block policy before any shell dispatch.
|
|
13
13
|
const rawCmd = String(args && args.command != null ? args.command : '');
|
|
14
14
|
if (rawCmd) {
|
|
15
|
-
const policyBlock = checkExecPolicyMessage(rawCmd);
|
|
15
|
+
const policyBlock = checkExecPolicyMessage(rawCmd, { elevationApproved });
|
|
16
16
|
if (policyBlock) return { failure: formatShellToolFailure(policyBlock) };
|
|
17
17
|
}
|
|
18
18
|
let command = args.command;
|
|
@@ -52,7 +52,7 @@ export function prepareShellCommand(args) {
|
|
|
52
52
|
: null;
|
|
53
53
|
if (bashismRewrite) command = bashismRewrite.command;
|
|
54
54
|
|
|
55
|
-
const execPolicyBlock = checkExecPolicyMessage(command);
|
|
55
|
+
const execPolicyBlock = checkExecPolicyMessage(command, { elevationApproved });
|
|
56
56
|
if (execPolicyBlock) return { failure: formatShellToolFailure(execPolicyBlock) };
|
|
57
57
|
return { command, analysisCommand, resolvedSpec, wmicRewrite, bashismRewrite };
|
|
58
58
|
}
|
|
@@ -61,7 +61,9 @@ export async function executeBashTool(args, workDir, options = {}) {
|
|
|
61
61
|
// Every call starts from the current Project root. A command-local `cd`
|
|
62
62
|
// never creates a second session cwd authority beside the dedicated cwd tool.
|
|
63
63
|
const bashWorkDir = workDir;
|
|
64
|
-
|
|
64
|
+
// Approval comes from the runtime's options, never from model-supplied args.
|
|
65
|
+
const elevationApproved = options?.elevationApproved === true;
|
|
66
|
+
const prepared = prepareShellCommand(args, { elevationApproved });
|
|
65
67
|
if (prepared.failure) return prepared.failure;
|
|
66
68
|
const { resolvedSpec, wmicRewrite, bashismRewrite } = prepared;
|
|
67
69
|
// Effects are analyzed on the command as the caller meant it, before the
|
|
@@ -97,6 +99,7 @@ export async function executeBashTool(args, workDir, options = {}) {
|
|
|
97
99
|
command: invocation.wrappedCommand,
|
|
98
100
|
execScript: invocation.execScript,
|
|
99
101
|
directArgv: invocation.directArgv,
|
|
102
|
+
elevationApproved,
|
|
100
103
|
env: invocation.spawnEnv,
|
|
101
104
|
cwd: bashWorkDir,
|
|
102
105
|
timeoutMs: deadlines.timeout,
|
|
@@ -37,6 +37,7 @@ import { decodeValidUtf8OrNull, detectPatchTargetCodec, nearestPatchLineMatch }
|
|
|
37
37
|
import { hashText } from './hash-utils.mjs';
|
|
38
38
|
import { invalidateBuiltinResultCache } from './cache-layers.mjs';
|
|
39
39
|
import { markCodeGraphDirtyPaths } from '../code-graph-state.mjs';
|
|
40
|
+
import { reviewFileContent } from '../../../../shared/bounded-file-read.mjs';
|
|
40
41
|
|
|
41
42
|
const STR_REPLACE_NAMES = new Set(['edit', 'strreplace', 'str_replace', 'str_replace_editor', 'search_replace']);
|
|
42
43
|
const WRITE_NAMES = new Set(['write', 'create_file', 'createfile']);
|
|
@@ -189,26 +190,27 @@ function recordEditSnapshot(fullPath, options, contentHash = null, preMutationSt
|
|
|
189
190
|
// UI diff parity with apply_patch: register the before/after pair on the
|
|
190
191
|
// shared per-call side channel so tool cards render edit results with the
|
|
191
192
|
// same diff markup. Lazy import breaks the orchestrator→builtin→adapters
|
|
192
|
-
// module cycle; failures never affect the edit result.
|
|
193
|
-
|
|
193
|
+
// module cycle; failures never affect the edit result. `sides()` yields the
|
|
194
|
+
// file's `{ before, after }` content (null = absent).
|
|
195
|
+
async function recordToolUiDiff(options, workDir, fullPath, sides) {
|
|
194
196
|
const callId = options?.toolCallId;
|
|
195
197
|
const sessionId = options?.sessionId || options?.readStateScope;
|
|
196
198
|
if (!callId || !sessionId) return;
|
|
197
199
|
try {
|
|
198
200
|
const { registerEditToolUiDiff } = await import('../patch/orchestrator.mjs');
|
|
199
|
-
registerEditToolUiDiff({
|
|
200
|
-
callId,
|
|
201
|
-
sessionId,
|
|
202
|
-
basePath: workDir,
|
|
203
|
-
fullPath,
|
|
204
|
-
before: before === null ? null : encodeEditContent(before, encoding),
|
|
205
|
-
after: after === null ? null : encodeEditContent(after, encoding),
|
|
206
|
-
});
|
|
201
|
+
registerEditToolUiDiff({ callId, sessionId, basePath: workDir, fullPath, ...sides() });
|
|
207
202
|
} catch {
|
|
208
203
|
/* best-effort display channel */
|
|
209
204
|
}
|
|
210
205
|
}
|
|
211
206
|
|
|
207
|
+
async function recordEditUiDiff(options, workDir, fullPath, before, after, encoding) {
|
|
208
|
+
await recordToolUiDiff(options, workDir, fullPath, () => ({
|
|
209
|
+
before: before === null ? null : encodeEditContent(before, encoding),
|
|
210
|
+
after: after === null ? null : encodeEditContent(after, encoding),
|
|
211
|
+
}));
|
|
212
|
+
}
|
|
213
|
+
|
|
212
214
|
// The 0-based line the failure excerpt centres on, or -1: the engine's
|
|
213
215
|
// "nearest match" hint, else the exact old_string, else its longest tokens,
|
|
214
216
|
// else the fuzzy line scorer.
|
|
@@ -828,6 +830,7 @@ async function adaptWrite(args, workDir, options) {
|
|
|
828
830
|
if (target.error) return target.error;
|
|
829
831
|
const fullPath = target.full;
|
|
830
832
|
const existed = existsSync(fullPath);
|
|
833
|
+
const before = existed ? reviewFileContent(fullPath) : null;
|
|
831
834
|
try {
|
|
832
835
|
mkdirSync(dirname(fullPath), { recursive: true });
|
|
833
836
|
} catch {
|
|
@@ -835,6 +838,7 @@ async function adaptWrite(args, workDir, options) {
|
|
|
835
838
|
}
|
|
836
839
|
await atomicWrite(fullPath, contents, { sessionId: editScope(options) });
|
|
837
840
|
invalidateAfterWrite(fullPath);
|
|
841
|
+
await recordToolUiDiff(options, workDir, fullPath, () => ({ before, after: contents }));
|
|
838
842
|
return `${existed ? 'Updated' : 'Created'} ${fullPath} (${Buffer.byteLength(contents, 'utf8')} bytes)`;
|
|
839
843
|
}
|
|
840
844
|
|