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
|
@@ -8,6 +8,7 @@ import { currentProviderAccountId } from '../provider-auth-binding.mjs';
|
|
|
8
8
|
// fallback, catalog retry) runs its own accounting and its result or error
|
|
9
9
|
// then returns through the enclosing send, which must not write it again.
|
|
10
10
|
const recorded = new WeakSet();
|
|
11
|
+
const UNMEASURED_USAGE = Object.freeze({ inputTokens: null, inputTokensKnown: false });
|
|
11
12
|
const hasTokens = (usage) =>
|
|
12
13
|
['inputTokens', 'outputTokens', 'cachedTokens', 'cacheWriteTokens'].some((key) => Number(usage?.[key]) > 0);
|
|
13
14
|
// One rule for every reported usage object: tokens, or a provider-reported
|
|
@@ -51,7 +52,9 @@ export async function accountProviderSend(provider, instance, send, model, opts
|
|
|
51
52
|
// abandoned attempt or a failure shares that clock with the final attempt,
|
|
52
53
|
// so timing it too would count the same seconds twice and understate speed.
|
|
53
54
|
const record = async (result, id, owner, timed) => {
|
|
54
|
-
|
|
55
|
+
// A completed call that reported no usage is still a call: it is recorded
|
|
56
|
+
// as unmeasured (unknown input, unpriced) instead of vanishing from totals.
|
|
57
|
+
if (!result?.usage && !(timed && result && typeof result === 'object')) return;
|
|
55
58
|
// A nested send (e.g. a fallback model re-send) already stamped its own
|
|
56
59
|
// final attempt's tier; the outer context only saw the abandoned attempt.
|
|
57
60
|
result.requestServiceTier ??= identity.requestServiceTier || '';
|
|
@@ -59,7 +62,7 @@ export async function accountProviderSend(provider, instance, send, model, opts
|
|
|
59
62
|
if (openingError) throw openingError;
|
|
60
63
|
if (!ledger) return;
|
|
61
64
|
recorded.add(owner);
|
|
62
|
-
const usage = result.usage;
|
|
65
|
+
const usage = result.usage || UNMEASURED_USAGE;
|
|
63
66
|
const row = makeUsageRecord({
|
|
64
67
|
id: result.responseId ? undefined : id,
|
|
65
68
|
ts: Date.now(),
|
|
@@ -61,6 +61,8 @@ const add = (target, row) => {
|
|
|
61
61
|
costBilled: row.cost_source === 'provider' ? row.cost_usd : 0,
|
|
62
62
|
costEstimated: row.cost_source === 'provider' ? 0 : row.cost_usd,
|
|
63
63
|
});
|
|
64
|
+
// A call recorded without provider usage is unmeasured whatever its provider.
|
|
65
|
+
if (row.unmeasured && !usage.unmeasuredTurns) usage.unmeasuredTurns = usage.turns || 0;
|
|
64
66
|
for (const field of [
|
|
65
67
|
'turns',
|
|
66
68
|
'input',
|
|
@@ -311,6 +313,7 @@ export function readSessionUsage(db, sessionIds) {
|
|
|
311
313
|
json_extract(r.signature,'$[1]') AS model,
|
|
312
314
|
json_extract(r.signature,'$[4]') AS cost_source,
|
|
313
315
|
json_extract(r.signature,'$[7]') AS rank,
|
|
316
|
+
COALESCE(json_extract(json_extract(r.signature,'$[5]'),'$.inputTokensKnown'),1)=0 AS unmeasured,
|
|
314
317
|
m.turns,m.input,m.output,m.cache_read,m.cache_write,m.cost_usd,m.duration_ms,
|
|
315
318
|
m.speed_output,m.speed_ms
|
|
316
319
|
FROM mine m JOIN usage_routes r ON r.id=m.route
|
|
@@ -9,6 +9,15 @@ export function createLoopbackListener({
|
|
|
9
9
|
let current = null;
|
|
10
10
|
let closing = null;
|
|
11
11
|
|
|
12
|
+
// close() drops only the keep-alive sockets idle at that moment; one whose
|
|
13
|
+
// in-flight response ends later would hold the close for the server's whole
|
|
14
|
+
// keepAliveTimeout (~5 s). Drop each as its response settles while stopping.
|
|
15
|
+
server.on('request', (_req, res) => {
|
|
16
|
+
res.once('close', () => {
|
|
17
|
+
if (closing) server.closeIdleConnections();
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
|
|
12
21
|
function start() {
|
|
13
22
|
if (closing) return Promise.reject(new Error('HTTP listener is stopping'));
|
|
14
23
|
if (current) return current.promise;
|
|
@@ -72,12 +72,14 @@ export function getAgentApiKey(provider) {
|
|
|
72
72
|
/** The one API-key resolver for key-based providers: an explicit config key
|
|
73
73
|
* wins, otherwise the environment/keychain (getAgentApiKey). */
|
|
74
74
|
export function resolveProviderApiKey(provider, config) {
|
|
75
|
+
if (config?.apiKeyEnv) return process.env[config.apiKeyEnv] || '';
|
|
75
76
|
return config?.apiKey || getAgentApiKey(provider) || '';
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
/** Auth-error reload: the stored/environment key is re-read first so a
|
|
79
80
|
* rotated key beats the stale one captured in config. */
|
|
80
81
|
export function reloadProviderApiKey(provider, config) {
|
|
82
|
+
if (config?.apiKeyEnv) return process.env[config.apiKeyEnv] || '';
|
|
81
83
|
return getAgentApiKey(provider) || config?.apiKey || '';
|
|
82
84
|
}
|
|
83
85
|
|
|
@@ -1,5 +1,57 @@
|
|
|
1
1
|
const TRUNCATED = '… [diff truncated for display]';
|
|
2
2
|
|
|
3
|
+
// Review replies always list every changed file with its counts. Patch text
|
|
4
|
+
// is carried per file within these caps (UTF-8 bytes); a file past either one
|
|
5
|
+
// is listed `patchOmitted` with reason PATCH_TOO_LARGE and is read on its own,
|
|
6
|
+
// up to the larger "show anyway" cap, when it is opened.
|
|
7
|
+
/** Largest single-file patch a review reply carries inline. */
|
|
8
|
+
export const REVIEW_FILE_PATCH_MAX_BYTES = 1024 * 1024;
|
|
9
|
+
/** Largest total patch text a review reply carries. */
|
|
10
|
+
export const REVIEW_PATCH_MAX_BYTES = 2 * 1024 * 1024;
|
|
11
|
+
/** Largest single-file patch a file-patch read returns. */
|
|
12
|
+
export const REVIEW_FILE_PATCH_SHOW_MAX_BYTES = 8 * 1024 * 1024;
|
|
13
|
+
export const PATCH_TOO_LARGE = 'too_large';
|
|
14
|
+
|
|
15
|
+
/** A reply file listed with its counts but without its patch, for size. */
|
|
16
|
+
export function patchOmittedFile(file) {
|
|
17
|
+
return { ...file, patchOmitted: true, reason: PATCH_TOO_LARGE };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** A `diff --git` section (string or Buffer) whose hunks boundReviewPatch cut. */
|
|
21
|
+
export function reviewSectionTruncated(section) {
|
|
22
|
+
return section.includes(TRUNCATED);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Nothing of the reply's patch fit: no patch text, a file omitted for size. */
|
|
26
|
+
export function reviewDiffTooLarge(files, patch) {
|
|
27
|
+
return !patch && (files || []).some((file) => file?.patchOmitted === true && file.reason === PATCH_TOO_LARGE);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** The per-file and total caps of one reply. `admit(bytes)` takes a patch of
|
|
31
|
+
* that size from the remaining total, or refuses it. */
|
|
32
|
+
export function createReviewPatchBudget(total = REVIEW_PATCH_MAX_BYTES) {
|
|
33
|
+
let remaining = total;
|
|
34
|
+
return {
|
|
35
|
+
get remaining() {
|
|
36
|
+
return remaining;
|
|
37
|
+
},
|
|
38
|
+
admit(bytes) {
|
|
39
|
+
if (bytes > REVIEW_FILE_PATCH_MAX_BYTES || bytes > remaining) return false;
|
|
40
|
+
remaining -= bytes;
|
|
41
|
+
return true;
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** One file-patch read's reply: its patch, or none when past `maxBytes`. */
|
|
47
|
+
export function filePatchReply(path, patch, maxBytes = REVIEW_FILE_PATCH_SHOW_MAX_BYTES) {
|
|
48
|
+
const text = typeof patch === 'string' ? patch : '';
|
|
49
|
+
if (Buffer.byteLength(text, 'utf8') > maxBytes) {
|
|
50
|
+
return { supported: true, path, patch: '', patchOmitted: true, reason: PATCH_TOO_LARGE };
|
|
51
|
+
}
|
|
52
|
+
return { supported: true, path, patch: text };
|
|
53
|
+
}
|
|
54
|
+
|
|
3
55
|
/** Bound hunk bodies, never the inventory of changed files. Headers are kept
|
|
4
56
|
* even when the inventory itself exceeds the display budget. */
|
|
5
57
|
export function boundReviewPatch(patch, maxChars) {
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export type SessionSidebarChange = { favorite: boolean } | { archived: boolean };
|
|
2
|
+
export type SessionSidebarHost = (sessionId: unknown, change: unknown) => unknown;
|
|
3
|
+
export function registerSessionSidebarHost(host: SessionSidebarHost): () => void;
|
|
4
|
+
export function applySessionSidebarChange(sessionId: string, change: SessionSidebarChange): Promise<void>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Runtime → desktop request channel for a session's sidebar metadata
|
|
2
|
+
// (favorite, archive). That metadata belongs to the desktop
|
|
3
|
+
// service hosted in this daemon: it registers a host here, and the Lead's
|
|
4
|
+
// `session` tool applies a change through it, so the sidebar republishes live.
|
|
5
|
+
//
|
|
6
|
+
// Deliberately dependency-free: the desktop service bundle imports this file
|
|
7
|
+
// too, and both copies share one registry through a global symbol.
|
|
8
|
+
|
|
9
|
+
const HOSTS_KEY = Symbol.for('mixdog.sessionSidebarHosts.v1');
|
|
10
|
+
|
|
11
|
+
function hosts() {
|
|
12
|
+
globalThis[HOSTS_KEY] ??= [];
|
|
13
|
+
return globalThis[HOSTS_KEY];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Register a desktop host. `host(sessionId, change)` applies one change:
|
|
18
|
+
* `{ favorite: boolean }` or `{ archived: boolean }`.
|
|
19
|
+
* @returns {() => void} Unregister.
|
|
20
|
+
*/
|
|
21
|
+
export function registerSessionSidebarHost(host) {
|
|
22
|
+
const entry = { host };
|
|
23
|
+
hosts().push(entry);
|
|
24
|
+
return () => {
|
|
25
|
+
const list = hosts();
|
|
26
|
+
const index = list.indexOf(entry);
|
|
27
|
+
if (index >= 0) list.splice(index, 1);
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Apply one change through exactly one host: the most recently registered
|
|
32
|
+
* (active) desktop service. Never broadcast — each service writes the shared
|
|
33
|
+
* metadata file, so a second write would be redundant at best. */
|
|
34
|
+
export async function applySessionSidebarChange(sessionId, change) {
|
|
35
|
+
const active = hosts().at(-1);
|
|
36
|
+
if (!active) throw new Error('no desktop app is attached to this runtime');
|
|
37
|
+
await active.host(sessionId, change);
|
|
38
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
// slow-span.mjs
|
|
2
|
+
// Passive per-request timing spans. Every traced call is timed on the same
|
|
3
|
+
// monotonic clock the owner heartbeat uses (performance.now), completed spans
|
|
4
|
+
// over `minMs` land in a bounded ring, and spans over `slowMs` are logged as
|
|
5
|
+
// `[slow-op] <label> <ms>`. When the event loop stalls, `describe(from, to)`
|
|
6
|
+
// names the spans that overlapped the stall window. Spans carry labels, phase
|
|
7
|
+
// durations and sizes only — never payloads.
|
|
8
|
+
|
|
9
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
10
|
+
import { performance } from 'node:perf_hooks';
|
|
11
|
+
|
|
12
|
+
export const SPAN_RING_MIN_MS = 25;
|
|
13
|
+
export const SPAN_SLOW_MS = 1000;
|
|
14
|
+
export const SPAN_RING_CAPACITY = 64;
|
|
15
|
+
|
|
16
|
+
const current = new AsyncLocalStorage();
|
|
17
|
+
|
|
18
|
+
/** Short, log-safe id of a session id. */
|
|
19
|
+
export function shortId(id) {
|
|
20
|
+
const text = String(id ?? '');
|
|
21
|
+
return text ? text.slice(0, 8) : '';
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Appends detail (e.g. the action name) to the label of the span the caller runs in. */
|
|
25
|
+
export function annotateSpan(detail) {
|
|
26
|
+
const span = current.getStore();
|
|
27
|
+
if (span && detail) span.label += `:${detail}`;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Closes the running phase of the caller's span at `now`, under `name`. */
|
|
31
|
+
export function markPhase(name) {
|
|
32
|
+
const span = current.getStore();
|
|
33
|
+
if (!span) return;
|
|
34
|
+
const t = span.now();
|
|
35
|
+
span.phases.push([name, t - span.mark]);
|
|
36
|
+
span.mark = t;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Records a size (count/bytes) on the caller's span. */
|
|
40
|
+
export function noteSpanSize(size) {
|
|
41
|
+
const span = current.getStore();
|
|
42
|
+
if (span && Number.isFinite(size)) span.size = size;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const round = (ms) => Math.round(ms);
|
|
46
|
+
|
|
47
|
+
function formatSpan(span) {
|
|
48
|
+
const phases = span.phases.map(([name, ms]) => `${name}=${round(ms)}`).join(' ');
|
|
49
|
+
const size = span.size === undefined ? '' : ` size=${span.size}`;
|
|
50
|
+
return `${span.label} ${round(span.ms)}ms${phases ? ` ${phases}` : ''}${size}`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function createSlowSpans({
|
|
54
|
+
now = () => performance.now(),
|
|
55
|
+
capacity = SPAN_RING_CAPACITY,
|
|
56
|
+
minMs = SPAN_RING_MIN_MS,
|
|
57
|
+
slowMs = SPAN_SLOW_MS,
|
|
58
|
+
log = () => {},
|
|
59
|
+
} = {}) {
|
|
60
|
+
const ring = [];
|
|
61
|
+
let sink = log;
|
|
62
|
+
|
|
63
|
+
function complete(span) {
|
|
64
|
+
span.end = now();
|
|
65
|
+
span.ms = span.end - span.start;
|
|
66
|
+
if (span.ms >= minMs) {
|
|
67
|
+
ring.push({ label: span.label, start: span.start, end: span.end, ms: span.ms, phases: span.phases, size: span.size });
|
|
68
|
+
if (ring.length > capacity) ring.shift();
|
|
69
|
+
}
|
|
70
|
+
if (span.ms >= slowMs) {
|
|
71
|
+
try {
|
|
72
|
+
sink(`[slow-op] ${formatSpan(span)}`);
|
|
73
|
+
} catch {
|
|
74
|
+
/* logging must not fail the call */
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
setLog(next) {
|
|
81
|
+
sink = typeof next === 'function' ? next : () => {};
|
|
82
|
+
},
|
|
83
|
+
/** Runs `fn` inside a span; markPhase/annotateSpan inside it attach to this span. */
|
|
84
|
+
async trace(label, fn) {
|
|
85
|
+
const start = now();
|
|
86
|
+
const span = { label: String(label), start, mark: start, now, phases: [], size: undefined };
|
|
87
|
+
try {
|
|
88
|
+
return await current.run(span, fn);
|
|
89
|
+
} finally {
|
|
90
|
+
complete(span);
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
/** Completed spans overlapping [from, to], longest overlap first. */
|
|
94
|
+
overlapping(from, to, limit = 3) {
|
|
95
|
+
return ring
|
|
96
|
+
.map((span) => ({ span, overlap: Math.min(span.end, to) - Math.max(span.start, from) }))
|
|
97
|
+
.filter((row) => row.overlap > 0)
|
|
98
|
+
.sort((a, b) => b.overlap - a.overlap || b.span.end - a.span.end)
|
|
99
|
+
.slice(0, limit)
|
|
100
|
+
.map((row) => row.span);
|
|
101
|
+
},
|
|
102
|
+
/** One-line description of the spans overlapping a stall window ('' when none). */
|
|
103
|
+
describe(from, to, limit = 3) {
|
|
104
|
+
const spans = this.overlapping(from, to, limit);
|
|
105
|
+
return spans.length ? `spans: ${spans.map((span) => formatSpan({ ...span })).join('; ')}` : '';
|
|
106
|
+
},
|
|
107
|
+
get recent() {
|
|
108
|
+
return ring.slice();
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** Process-wide recorder; the daemon points its log at daemon.log. */
|
|
114
|
+
export const slowSpans = createSlowSpans();
|
|
@@ -76,9 +76,32 @@ export function shellJobsStatus({ clientHostPid, sessionId } = {}) {
|
|
|
76
76
|
_shellJobsRefreshInFlight.delete(ownerPid);
|
|
77
77
|
});
|
|
78
78
|
}
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
79
|
+
const own = cached?.value || EMPTY_SHELL_JOBS;
|
|
80
|
+
// Session buckets are not pid-scoped, so they come from the freshest scan of
|
|
81
|
+
// ANY owner. Reading them from this owner's own slot made the list follow
|
|
82
|
+
// that slot's age: an owner polled again after its entry was evicted (or
|
|
83
|
+
// went stale) answered with "no sessions", and the finished shells vanished
|
|
84
|
+
// until the next poll brought them back.
|
|
85
|
+
const sessions = freshestShellJobsSessions() ?? own.sessions;
|
|
86
|
+
if (!scoped) return sessions === own.sessions ? own : { ...own, sessions };
|
|
87
|
+
return (scope && sessions?.[scope]) || EMPTY_SHELL_JOBS_SESSION;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Awaited fresh scan for pollers that own their cadence (desktop): the result
|
|
91
|
+
// reflects the disk at call time instead of the previous poll. The CLI render
|
|
92
|
+
// path keeps using the cache-only shellJobsStatus.
|
|
93
|
+
export async function shellJobsStatusFresh({ clientHostPid } = {}) {
|
|
94
|
+
const ownerPid = positiveInt(clientHostPid);
|
|
95
|
+
if (!ownerPid) return EMPTY_SHELL_JOBS;
|
|
96
|
+
return refreshShellJobsStatus(ownerPid);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function freshestShellJobsSessions() {
|
|
100
|
+
let freshest = null;
|
|
101
|
+
for (const entry of _shellJobsSegmentCache.values()) {
|
|
102
|
+
if (!freshest || entry.at >= freshest.at) freshest = entry;
|
|
103
|
+
}
|
|
104
|
+
return freshest?.value.sessions;
|
|
82
105
|
}
|
|
83
106
|
|
|
84
107
|
// Memory cycle L2 segment source. The daemon-hosted memory runtime writes
|
|
@@ -142,7 +165,7 @@ async function refreshShellJobsStatus(ownerPid) {
|
|
|
142
165
|
names = await readdir(dir);
|
|
143
166
|
} catch {
|
|
144
167
|
rememberShellJobs(ownerPid, value);
|
|
145
|
-
return;
|
|
168
|
+
return value;
|
|
146
169
|
}
|
|
147
170
|
const { ids, ownerByJob, doneIds } = listOpenShellJobs(names);
|
|
148
171
|
let count = 0;
|
|
@@ -225,6 +248,7 @@ async function refreshShellJobsStatus(ownerPid) {
|
|
|
225
248
|
value = EMPTY_SHELL_JOBS;
|
|
226
249
|
}
|
|
227
250
|
rememberShellJobs(ownerPid, value);
|
|
251
|
+
return value;
|
|
228
252
|
}
|
|
229
253
|
|
|
230
254
|
// Newest-first, capped ids of job records with no `.done` marker, plus the
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
import { formatToolActionHeader, toolLoadingTargets } from '../tool-surface.mjs';
|
|
6
6
|
import { agentActionSummary, agentActionTitle, agentResponseTitle, isAgentTool } from './agent-surface.mjs';
|
|
7
7
|
import { backgroundTaskActionTitle, backgroundTaskResultTitle, taskControlTitle } from './background-task.mjs';
|
|
8
|
-
import { toolSearchLoadedSummary } from './generic-detail.mjs';
|
|
8
|
+
import { bridgeDescribedToolNames, toolSearchLoadedSummary } from './generic-detail.mjs';
|
|
9
|
+
import { displayToolSearchTarget } from '../tool-primitives.mjs';
|
|
9
10
|
import { safeInlineText } from './inline-text.mjs';
|
|
10
11
|
import { shellHeader } from './shell-surface.mjs';
|
|
11
12
|
|
|
@@ -20,6 +21,10 @@ function headerLabel(base, surface, display, status, detail) {
|
|
|
20
21
|
}
|
|
21
22
|
if (display.isBackgroundMetadataResult) return backgroundTaskActionTitle(normalizedName, display.backgroundMeta);
|
|
22
23
|
if (isShellSurface) return shellHeader(status.shellStatus, groupCount, parsedArgs?.verifyShell === true);
|
|
24
|
+
// Bridge load_tool describes definitions; it never loads a tool.
|
|
25
|
+
const described =
|
|
26
|
+
normalizedName === 'load_tool' && !headerPending ? bridgeDescribedToolNames(display.displayedResultText) : null;
|
|
27
|
+
if (described) return described.length ? `Described ${described.map(displayToolSearchTarget).join(', ')}` : 'Described';
|
|
23
28
|
return (
|
|
24
29
|
(isAgentTool(normalizedName) ? agentActionTitle(parsedArgs, display.displayedResultText) : '') ||
|
|
25
30
|
formatToolActionHeader(name, args, {
|
|
@@ -51,6 +51,34 @@ export function genericCompletedDetail({ normalizedName, label, hasResult, first
|
|
|
51
51
|
return '';
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
const uniqueToolNames = (names) => [
|
|
55
|
+
...new Set((Array.isArray(names) ? names : []).map((name) => String(name || '').trim()).filter(Boolean)),
|
|
56
|
+
];
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* What a bridge load_tool result described, missed and blocked; null for a
|
|
60
|
+
* loader result (or anything that is not a describe result).
|
|
61
|
+
*/
|
|
62
|
+
export function bridgeDescribeResult(resultText) {
|
|
63
|
+
let parsed;
|
|
64
|
+
try {
|
|
65
|
+
parsed = JSON.parse(String(resultText || ''));
|
|
66
|
+
} catch {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
if (!Array.isArray(parsed?.entries)) return null;
|
|
70
|
+
return {
|
|
71
|
+
described: uniqueToolNames(parsed.entries.map((entry) => entry?.name)),
|
|
72
|
+
missing: uniqueToolNames(parsed.missing),
|
|
73
|
+
blocked: uniqueToolNames((Array.isArray(parsed.blocked) ? parsed.blocked : []).map((entry) => entry?.name)),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Names a bridge load_tool result described, or null for a loader result. */
|
|
78
|
+
export function bridgeDescribedToolNames(resultText) {
|
|
79
|
+
return bridgeDescribeResult(resultText)?.described ?? null;
|
|
80
|
+
}
|
|
81
|
+
|
|
54
82
|
export function toolSearchLoadedSummary(resultText) {
|
|
55
83
|
let parsed;
|
|
56
84
|
try {
|
|
@@ -61,13 +89,19 @@ export function toolSearchLoadedSummary(resultText) {
|
|
|
61
89
|
const already = /^Already active:\s*(.+)$/m.exec(text)?.[1] || '';
|
|
62
90
|
return [...(loaded ? [`Loaded: ${loaded}`] : []), ...(already ? [`Already active: ${already}`] : [])].join(' · ');
|
|
63
91
|
}
|
|
92
|
+
// Bridge describe result: nothing was loaded; report what was not described.
|
|
93
|
+
const describe = bridgeDescribeResult(resultText);
|
|
94
|
+
if (describe) {
|
|
95
|
+
const { missing, blocked } = describe;
|
|
96
|
+
return [
|
|
97
|
+
...(missing.length ? [`Missing: ${missing.join(', ')}`] : []),
|
|
98
|
+
...(blocked.length ? [`Blocked: ${blocked.join(', ')}`] : []),
|
|
99
|
+
].join(' · ');
|
|
100
|
+
}
|
|
64
101
|
const tools = parsed?.selected?.tools;
|
|
65
102
|
if (!tools || typeof tools !== 'object') return '';
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
];
|
|
69
|
-
const loaded = uniqueNames(tools.added);
|
|
70
|
-
const already = uniqueNames(tools.already);
|
|
103
|
+
const loaded = uniqueToolNames(tools.added);
|
|
104
|
+
const already = uniqueToolNames(tools.already);
|
|
71
105
|
return [
|
|
72
106
|
...(loaded.length ? [`Loaded: ${loaded.join(', ')}`] : []),
|
|
73
107
|
...(already.length ? [`Already active: ${already.join(', ')}`] : []),
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
* tool-card-model/card-header.mjs — header label + arg summary
|
|
24
24
|
*/
|
|
25
25
|
import { formatToolSurface } from './tool-surface.mjs';
|
|
26
|
-
import { pluralize } from './tool-primitives.mjs';
|
|
26
|
+
import { pluralize, toolCallDisplayIdentity } from './tool-primitives.mjs';
|
|
27
27
|
import { deriveAggregateCardModel } from './tool-card-model/aggregate-card.mjs';
|
|
28
28
|
import { isShellTool } from './tool-card-model/shell-surface.mjs';
|
|
29
29
|
import { SKILL_SURFACE_NAMES } from './tool-card-model/agent-surface.mjs';
|
|
@@ -77,6 +77,7 @@ export {
|
|
|
77
77
|
resolveBackgroundTaskMeta,
|
|
78
78
|
} from './tool-card-model/background-task.mjs';
|
|
79
79
|
export {
|
|
80
|
+
bridgeDescribeResult,
|
|
80
81
|
genericCompletedDetail,
|
|
81
82
|
shouldPrefixSyncElapsed,
|
|
82
83
|
toolSearchLoadedSummary,
|
|
@@ -95,7 +96,8 @@ export { pluralize as plural };
|
|
|
95
96
|
* @param {object} options { truncate(text,width), maxResultChars }.
|
|
96
97
|
*/
|
|
97
98
|
export function deriveToolCardModel(input = {}, options = {}) {
|
|
98
|
-
const
|
|
99
|
+
const identity = toolCallDisplayIdentity(input.name, input.args);
|
|
100
|
+
const base = readCardInput({ ...input, name: identity.name, args: identity.args }, options);
|
|
99
101
|
if (base.aggregate) return deriveAggregateCardModel(base);
|
|
100
102
|
|
|
101
103
|
const { label, summary, normalizedName, args: parsedArgs } = formatToolSurface(base.name, base.args);
|
|
@@ -115,6 +117,7 @@ export function deriveToolCardModel(input = {}, options = {}) {
|
|
|
115
117
|
return {
|
|
116
118
|
aggregate: false,
|
|
117
119
|
...commonCardFields(base, status.terminalStatus),
|
|
120
|
+
...(identity.via ? { via: identity.via } : {}),
|
|
118
121
|
labelText: header.labelText,
|
|
119
122
|
summaryText: header.summaryText,
|
|
120
123
|
headerFailureText: status.headerFailureText,
|
|
@@ -22,6 +22,10 @@ export const RECALL_OUTPUT_MAX_BYTES = positiveEnvInt('MIXDOG_RECALL_OUTPUT_MAX_
|
|
|
22
22
|
// github results after field reduction; the full response stays in a raw
|
|
23
23
|
// artifact. Provisional: reduced pr.list/run.list pages measured ~2k tokens.
|
|
24
24
|
export const GITHUB_OUTPUT_MAX_BYTES = positiveEnvInt('MIXDOG_GITHUB_OUTPUT_MAX_BYTES', 10 * 1024);
|
|
25
|
+
// setup results are compact JSON (a provider index, a 25-row model page, minimal
|
|
26
|
+
// status rows). The same figure is the setup inline-offload threshold, so one
|
|
27
|
+
// result can no longer sit just under the 50KB default (a 34-model catalog did).
|
|
28
|
+
export const SETUP_OUTPUT_MAX_BYTES = positiveEnvInt('MIXDOG_SETUP_OUTPUT_MAX_BYTES', 20 * 1024);
|
|
25
29
|
|
|
26
30
|
function _prefixByBytes(value, maxBytes) {
|
|
27
31
|
const text = String(value || '');
|
|
@@ -133,6 +133,19 @@ export function parseToolArgs(args) {
|
|
|
133
133
|
return { value: args };
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
+
/**
|
|
137
|
+
* Display identity of a tool call. A call_tool bridge request shows the tool
|
|
138
|
+
* it runs, with `via: 'call_tool'`; the transcript keeps the wire call.
|
|
139
|
+
*/
|
|
140
|
+
export function toolCallDisplayIdentity(name, args) {
|
|
141
|
+
if (rawToolName(name) !== 'call_tool') return { name, args };
|
|
142
|
+
const parsed = parseToolArgs(args);
|
|
143
|
+
const target = typeof parsed?.name === 'string' ? parsed.name.trim() : '';
|
|
144
|
+
if (!target) return { name, args };
|
|
145
|
+
const targetArgs = parsed.arguments && typeof parsed.arguments === 'object' ? parsed.arguments : {};
|
|
146
|
+
return { name: target, args: targetArgs, via: 'call_tool' };
|
|
147
|
+
}
|
|
148
|
+
|
|
136
149
|
export function displayToolPath(path) {
|
|
137
150
|
const text = String(path ?? '');
|
|
138
151
|
return text.replace(/\\/g, '/').split('/').filter(Boolean).at(-1) || text;
|
|
@@ -640,8 +640,14 @@ function summarizeAgentResult({ text, trimmed, translate }) {
|
|
|
640
640
|
|
|
641
641
|
const summarizeGeneric = ({ text, translate }) => summarizeGenericResult(text, translate);
|
|
642
642
|
|
|
643
|
+
const summarizeAskUserResult = ({ text }) => {
|
|
644
|
+
const answers = /^User has answered your questions:\s*(.*?)(?:\s*You can now continue with these answers in mind\.)?$/s.exec(String(text ?? '').trim());
|
|
645
|
+
return truncateSingleLine(answers ? answers[1] : String(text ?? '').trim(), AGENT_SURFACE_BRIEF_MAX) || null;
|
|
646
|
+
};
|
|
647
|
+
|
|
643
648
|
const TOOL_RESULT_SUMMARIZERS = new Map(
|
|
644
649
|
[
|
|
650
|
+
[['ask_user'], summarizeAskUserResult],
|
|
645
651
|
[['read', 'view_image', 'read_mcp_resource'], summarizeReadResult],
|
|
646
652
|
[['apply_patch'], summarizePatchResult],
|
|
647
653
|
[['grep'], summarizeGrepResult],
|
|
@@ -662,7 +668,8 @@ const TOOL_RESULT_SUMMARIZERS = new Map(
|
|
|
662
668
|
'update_memory',
|
|
663
669
|
'request_user_input',
|
|
664
670
|
'update_plan',
|
|
665
|
-
'cwd',
|
|
671
|
+
'cwd', // legacy: old transcripts
|
|
672
|
+
'session',
|
|
666
673
|
'list_mcp_resources',
|
|
667
674
|
'list_mcp_resource_templates',
|
|
668
675
|
],
|
|
@@ -144,11 +144,14 @@ export function displayToolName(name, args = {}) {
|
|
|
144
144
|
return 'Visualize';
|
|
145
145
|
case 'list_mcp_resources':
|
|
146
146
|
case 'list_mcp_resource_templates':
|
|
147
|
-
case 'cwd':
|
|
147
|
+
case 'cwd': // legacy: old transcripts
|
|
148
|
+
case 'session':
|
|
148
149
|
case 'setup':
|
|
149
150
|
return 'Setup';
|
|
150
151
|
case 'request_user_input':
|
|
151
152
|
return 'Ask User';
|
|
153
|
+
case 'ask_user':
|
|
154
|
+
return 'Question';
|
|
152
155
|
case 'update_plan':
|
|
153
156
|
return 'Plan';
|
|
154
157
|
case 'memory':
|
|
@@ -236,6 +239,14 @@ export function summarizeToolArgs(name, args, { max = DEFAULT_SUMMARY_MAX } = {}
|
|
|
236
239
|
return summarizeGithub(a, max);
|
|
237
240
|
case 'goal':
|
|
238
241
|
return compactParts([String(a.action || ''), truncateToolText(a.objective, max)]);
|
|
242
|
+
case 'ask_user':
|
|
243
|
+
return truncateToolText(
|
|
244
|
+
(Array.isArray(a.questions) ? a.questions : [])
|
|
245
|
+
.map((q) => String(q?.header || q?.question || '').trim())
|
|
246
|
+
.filter(Boolean)
|
|
247
|
+
.join(', '),
|
|
248
|
+
max
|
|
249
|
+
);
|
|
239
250
|
case 'list':
|
|
240
251
|
case 'ls':
|
|
241
252
|
if (Array.isArray(a.path) || Array.isArray(a.dir) || Array.isArray(a.cwd)) {
|
|
@@ -333,8 +344,12 @@ export function summarizeToolArgs(name, args, { max = DEFAULT_SUMMARY_MAX } = {}
|
|
|
333
344
|
case 'list_mcp_resources':
|
|
334
345
|
case 'list_mcp_resource_templates':
|
|
335
346
|
return a.server ? `server "${truncateToolText(a.server, max)}"` : 'all servers';
|
|
336
|
-
case 'cwd':
|
|
337
|
-
|
|
347
|
+
case 'cwd': // legacy: old transcripts
|
|
348
|
+
case 'session':
|
|
349
|
+
return compactParts([
|
|
350
|
+
String(a.action || a.type || ''),
|
|
351
|
+
truncateToolText(firstText(a.title, a.path, a.cwd, a.dir), max),
|
|
352
|
+
]);
|
|
338
353
|
case 'setup':
|
|
339
354
|
return compactParts([
|
|
340
355
|
String(a.action || ''),
|
|
@@ -85,10 +85,12 @@ const TOOL_CATEGORY = new Map([
|
|
|
85
85
|
['visualize', 'Visualize'],
|
|
86
86
|
['list_mcp_resources', 'Setup'],
|
|
87
87
|
['list_mcp_resource_templates', 'Setup'],
|
|
88
|
-
['cwd', 'Setup'],
|
|
88
|
+
['cwd', 'Setup'], // legacy: old transcripts
|
|
89
|
+
['session', 'Setup'],
|
|
89
90
|
['setup', 'Setup'],
|
|
90
91
|
['goal', 'Setup'],
|
|
91
92
|
['request_user_input', 'Setup'],
|
|
93
|
+
['ask_user', 'Setup'],
|
|
92
94
|
['update_plan', 'Setup'],
|
|
93
95
|
['skill', 'Skill'],
|
|
94
96
|
['skill_execute', 'Skill'],
|
|
@@ -568,7 +570,7 @@ function gitStageUnit(a) {
|
|
|
568
570
|
function cwdUnit(a) {
|
|
569
571
|
const action = String(a.action || a.type || '').toLowerCase();
|
|
570
572
|
// A bare `path` selects that Project even when action is omitted.
|
|
571
|
-
if (action === 'set' || (!action && a.path)) {
|
|
573
|
+
if (action === 'set' || action === 'set-project' || (!action && a.path)) {
|
|
572
574
|
return unitDescriptor('Setup', {
|
|
573
575
|
active: 'Selecting',
|
|
574
576
|
done: 'Selected',
|
|
@@ -576,9 +578,41 @@ function cwdUnit(a) {
|
|
|
576
578
|
effect: true,
|
|
577
579
|
});
|
|
578
580
|
}
|
|
579
|
-
if (action === 'list') {
|
|
581
|
+
if (action === 'list' || action === 'list-projects') {
|
|
580
582
|
return unitDescriptor('Setup', { active: 'Listing', done: 'Listed', noun: 'project' });
|
|
581
583
|
}
|
|
584
|
+
if (action === 'rename') {
|
|
585
|
+
return unitDescriptor('Setup', { active: 'Renaming', done: 'Renamed', noun: 'session', effect: true });
|
|
586
|
+
}
|
|
587
|
+
if (action === 'compact') {
|
|
588
|
+
return unitDescriptor('Setup', { active: 'Scheduling', done: 'Scheduled', noun: 'compaction', effect: true });
|
|
589
|
+
}
|
|
590
|
+
if (action === 'fork') {
|
|
591
|
+
return unitDescriptor('Setup', { active: 'Forking', done: 'Forked', noun: 'session', effect: true });
|
|
592
|
+
}
|
|
593
|
+
if (action === 'favorite' || action === 'archive') {
|
|
594
|
+
const off = a.value === false;
|
|
595
|
+
const [active, done] =
|
|
596
|
+
action === 'favorite'
|
|
597
|
+
? off
|
|
598
|
+
? ['Unfavoriting', 'Unfavorited']
|
|
599
|
+
: ['Favoriting', 'Favorited']
|
|
600
|
+
: off
|
|
601
|
+
? ['Unarchiving', 'Unarchived']
|
|
602
|
+
: ['Archiving', 'Archived'];
|
|
603
|
+
return unitDescriptor('Setup', { active, done, noun: 'session', effect: true });
|
|
604
|
+
}
|
|
605
|
+
if (action.endsWith('-worktree') || action.endsWith('-worktrees')) {
|
|
606
|
+
return unitDescriptor('Setup', {
|
|
607
|
+
active: 'Managing',
|
|
608
|
+
done: 'Managed',
|
|
609
|
+
noun: 'worktree',
|
|
610
|
+
effect: !action.startsWith('list'),
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
if (action === 'status') {
|
|
614
|
+
return unitDescriptor('Setup', { active: 'Checking', done: 'Checked', noun: 'session' });
|
|
615
|
+
}
|
|
582
616
|
return unitDescriptor('Setup', { active: 'Checking', done: 'Checked', noun: 'working directory', pluralNoun: 'working directories' });
|
|
583
617
|
}
|
|
584
618
|
|
|
@@ -689,13 +723,15 @@ const TOOL_UNITS = new Map([
|
|
|
689
723
|
['use_skill', skillUnit],
|
|
690
724
|
['code_graph', codeGraphUnit],
|
|
691
725
|
['request_user_input', () => unitDescriptor('Setup', { active: 'Asking', done: 'Asked', noun: 'user' })],
|
|
726
|
+
['ask_user', () => unitDescriptor('Setup', { active: 'Asking', done: 'Asked', noun: 'user' })],
|
|
692
727
|
['update_plan', () => unitDescriptor('Setup', { active: 'Updating', done: 'Updated', noun: 'plan' })],
|
|
693
728
|
['list_mcp_resources', () => unitDescriptor('Setup', { active: 'Listing', done: 'Listed', noun: 'MCP resource' })],
|
|
694
729
|
[
|
|
695
730
|
'list_mcp_resource_templates',
|
|
696
731
|
() => unitDescriptor('Setup', { active: 'Listing', done: 'Listed', noun: 'MCP resource template' }),
|
|
697
732
|
],
|
|
698
|
-
['cwd', cwdUnit],
|
|
733
|
+
['cwd', cwdUnit], // legacy: old transcripts
|
|
734
|
+
['session', cwdUnit],
|
|
699
735
|
]);
|
|
700
736
|
|
|
701
737
|
function mcpUnit(name, a) {
|