mixdog 0.9.2 → 0.9.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +8 -3
- package/scripts/anthropic-maxtokens-test.mjs +119 -0
- package/scripts/bench/lead-review-tasks-r3.json +20 -0
- package/scripts/bench/lead-review-tasks.json +20 -0
- package/scripts/bench/r4-mixed-tasks.json +20 -0
- package/scripts/bench/review-tasks.json +20 -0
- package/scripts/bench/round-codex.json +114 -0
- package/scripts/bench/round-mixdog-lead-r3.json +269 -0
- package/scripts/bench/round-mixdog-lead.json +269 -0
- package/scripts/bench/round-mixdog.json +126 -0
- package/scripts/bench/round-r10-bigsample.json +679 -0
- package/scripts/bench/round-r11-codexalign.json +257 -0
- package/scripts/bench/round-r4-codex.json +114 -0
- package/scripts/bench/round-r4-mixed.json +225 -0
- package/scripts/bench/round-r5-gpt-lead.json +259 -0
- package/scripts/bench/round-r6-codex.json +114 -0
- package/scripts/bench/round-r6-solo.json +257 -0
- package/scripts/bench/round-r7-full.json +254 -0
- package/scripts/bench/round-r8-fulldefault.json +255 -0
- package/scripts/bench-run.mjs +215 -29
- package/scripts/build-tui.mjs +13 -1
- package/scripts/explore-bench.mjs +124 -0
- package/scripts/freevar-smoke.mjs +95 -0
- package/scripts/hook-bus-test.mjs +191 -0
- package/scripts/internal-comms-bench.mjs +1 -0
- package/scripts/internal-comms-smoke.mjs +10 -9
- package/scripts/mouse-probe.mjs +45 -0
- package/scripts/output-style-bench.mjs +13 -6
- package/scripts/output-style-smoke.mjs +4 -4
- package/scripts/path-suffix-test.mjs +57 -0
- package/scripts/provider-toolcall-test.mjs +7 -3
- package/scripts/recall-bench.mjs +207 -0
- package/scripts/recall-usecase-cases.json +18 -0
- package/scripts/recall-usecase-probe.json +6 -0
- package/scripts/session-bench.mjs +152 -6
- package/scripts/tool-smoke.mjs +30 -67
- package/scripts/tui-render-smoke.mjs +90 -0
- package/scripts/webhook-smoke.mjs +208 -0
- package/src/agents/debugger/AGENT.md +5 -2
- package/src/agents/heavy-worker/AGENT.md +21 -11
- package/src/agents/maintainer/AGENT.md +4 -0
- package/src/agents/reviewer/AGENT.md +3 -2
- package/src/agents/worker/AGENT.md +21 -11
- package/src/lib/rules-builder.cjs +4 -0
- package/src/mixdog-session-runtime.mjs +933 -3731
- package/src/output-styles/default.md +34 -9
- package/src/output-styles/{oneline.md → extreme-minimal.md} +5 -4
- package/src/output-styles/minimal.md +4 -1
- package/src/output-styles/simple.md +22 -7
- package/src/repl.mjs +5 -5
- package/src/rules/agent/00-common.md +2 -0
- package/src/rules/agent/30-explorer.md +8 -11
- package/src/rules/lead/lead-brief.md +12 -0
- package/src/rules/lead/lead-tool.md +2 -9
- package/src/rules/shared/01-tool.md +11 -5
- package/src/runtime/agent/orchestrator/agent-runtime/agent-loop-policy.mjs +25 -0
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +100 -23
- package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +6 -15
- package/src/runtime/agent/orchestrator/agent-trace-format.mjs +362 -0
- package/src/runtime/agent/orchestrator/agent-trace-io.mjs +410 -0
- package/src/runtime/agent/orchestrator/agent-trace.mjs +16 -735
- package/src/runtime/agent/orchestrator/config.mjs +69 -2
- package/src/runtime/agent/orchestrator/context/collect.mjs +51 -0
- package/src/runtime/agent/orchestrator/mcp/client.mjs +6 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-effort.mjs +63 -21
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +93 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +209 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +489 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +97 -1343
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +607 -0
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +78 -10
- package/src/runtime/agent/orchestrator/providers/api-usage.mjs +1 -13
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +81 -0
- package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +248 -0
- package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +303 -0
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +505 -0
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +44 -1014
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +18 -4
- package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +32 -0
- package/src/runtime/agent/orchestrator/providers/model-catalog.mjs +86 -11
- package/src/runtime/agent/orchestrator/providers/model-list-sanitize.mjs +348 -0
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +54 -20
- package/src/runtime/agent/orchestrator/providers/openai-codex-model.mjs +108 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +19 -12
- package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +58 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +368 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +760 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +41 -1142
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +732 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +193 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +303 -2119
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +140 -995
- package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +227 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-events.mjs +67 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +436 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +1105 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/opencode-go-usage.mjs +38 -12
- package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +7 -8
- package/src/runtime/agent/orchestrator/session/compact/budget.mjs +288 -0
- package/src/runtime/agent/orchestrator/session/compact/constants.mjs +85 -0
- package/src/runtime/agent/orchestrator/session/compact/engine.mjs +749 -0
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +82 -0
- package/src/runtime/agent/orchestrator/session/compact/summary-schema.mjs +315 -0
- package/src/runtime/agent/orchestrator/session/compact/summary.mjs +643 -0
- package/src/runtime/agent/orchestrator/session/compact/text-utils.mjs +326 -0
- package/src/runtime/agent/orchestrator/session/compact.mjs +40 -2282
- package/src/runtime/agent/orchestrator/session/loop/compact-debug.mjs +28 -0
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +274 -0
- package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +61 -0
- package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +38 -0
- package/src/runtime/agent/orchestrator/session/loop/env.mjs +14 -0
- package/src/runtime/agent/orchestrator/session/loop/hidden-agents.mjs +21 -0
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +47 -0
- package/src/runtime/agent/orchestrator/session/loop/recall-fasttrack.mjs +182 -0
- package/src/runtime/agent/orchestrator/session/loop/steering-ladder.mjs +173 -0
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +63 -0
- package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +100 -0
- package/src/runtime/agent/orchestrator/session/loop/termination.mjs +58 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +52 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +239 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +218 -0
- package/src/runtime/agent/orchestrator/session/loop/transcript-repair.mjs +101 -0
- package/src/runtime/agent/orchestrator/session/loop/usage.mjs +35 -0
- package/src/runtime/agent/orchestrator/session/loop.mjs +409 -1304
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +471 -0
- package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +230 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +235 -0
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +149 -0
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +155 -0
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +406 -0
- package/src/runtime/agent/orchestrator/session/manager/status-telemetry.mjs +80 -0
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +303 -0
- package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +210 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +226 -2114
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +189 -0
- package/src/runtime/agent/orchestrator/session/store.mjs +74 -179
- package/src/runtime/agent/orchestrator/stall-policy.mjs +3 -3
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +70 -20
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +22 -2
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +33 -42
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +241 -0
- package/src/runtime/agent/orchestrator/tools/builtin/fuzzy-match.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +40 -0
- package/src/runtime/agent/orchestrator/tools/builtin/path-diagnostics.mjs +42 -2
- package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +11 -4
- package/src/runtime/agent/orchestrator/tools/builtin/rg-runner.mjs +29 -0
- package/src/runtime/agent/orchestrator/tools/builtin/search-builders.mjs +8 -0
- package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +126 -0
- package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +81 -87
- package/src/runtime/agent/orchestrator/tools/builtin/shell-job-paths.mjs +161 -0
- package/src/runtime/agent/orchestrator/tools/builtin/shell-job-process.mjs +108 -0
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +78 -304
- package/src/runtime/agent/orchestrator/tools/builtin.mjs +11 -6
- package/src/runtime/agent/orchestrator/tools/code-graph/build.mjs +303 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/constants.mjs +43 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/disk-cache.mjs +382 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +551 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary.mjs +295 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/graph-model.mjs +158 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/keyword-match.mjs +82 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/lang-predicates.mjs +128 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/memory-cache.mjs +66 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/project-root.mjs +44 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +1080 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/source-access.mjs +81 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/span.mjs +19 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/symbol-index.mjs +280 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/text-columns.mjs +45 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/text-mask.mjs +347 -0
- package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +6 -6
- package/src/runtime/agent/orchestrator/tools/code-graph.mjs +36 -4277
- package/src/runtime/agent/orchestrator/tools/graph-binary-fetcher.mjs +6 -3
- package/src/runtime/agent/orchestrator/tools/patch/constants.mjs +9 -0
- package/src/runtime/agent/orchestrator/tools/patch/dispatch.mjs +171 -0
- package/src/runtime/agent/orchestrator/tools/patch/matcher.mjs +471 -0
- package/src/runtime/agent/orchestrator/tools/patch/native-server.mjs +436 -0
- package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +342 -0
- package/src/runtime/agent/orchestrator/tools/patch/parsing.mjs +359 -0
- package/src/runtime/agent/orchestrator/tools/patch/paths.mjs +340 -0
- package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +643 -0
- package/src/runtime/agent/orchestrator/tools/patch.mjs +36 -2959
- package/src/runtime/agent/orchestrator/tools/progress-message.mjs +1 -23
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +10 -74
- package/src/runtime/agent/orchestrator/tools/shell-powershell.mjs +77 -0
- package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +2 -4
- package/src/runtime/agent/orchestrator/tools/shell-state.mjs +154 -0
- package/src/runtime/channels/backends/discord-access.mjs +32 -0
- package/src/runtime/channels/backends/discord-attachments.mjs +65 -0
- package/src/runtime/channels/backends/discord-gateway.mjs +233 -0
- package/src/runtime/channels/backends/discord.mjs +12 -292
- package/src/runtime/channels/index.mjs +241 -894
- package/src/runtime/channels/lib/backend-dispatch.mjs +44 -0
- package/src/runtime/channels/lib/boot-profile.mjs +23 -0
- package/src/runtime/channels/lib/crash-log.mjs +106 -0
- package/src/runtime/channels/lib/event-pipeline.mjs +18 -1
- package/src/runtime/channels/lib/event-queue.mjs +63 -4
- package/src/runtime/channels/lib/inbound-routing.mjs +111 -0
- package/src/runtime/channels/lib/index-drop-trace.mjs +72 -0
- package/src/runtime/channels/lib/output-forwarder.mjs +9 -1
- package/src/runtime/channels/lib/owner-heartbeat.mjs +75 -0
- package/src/runtime/channels/lib/parent-bridge.mjs +88 -0
- package/src/runtime/channels/lib/runtime-paths.mjs +14 -4
- package/src/runtime/channels/lib/session-discovery.mjs +56 -4
- package/src/runtime/channels/lib/telegram-format.mjs +19 -22
- package/src/runtime/channels/lib/tool-dispatch.mjs +158 -0
- package/src/runtime/channels/lib/tool-format.mjs +1 -1
- package/src/runtime/channels/lib/transcript-discovery.mjs +4 -4
- package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +6 -3
- package/src/runtime/channels/lib/voice-transcription.mjs +179 -0
- package/src/runtime/channels/lib/webhook/deliveries.mjs +312 -0
- package/src/runtime/channels/lib/webhook/log.mjs +42 -0
- package/src/runtime/channels/lib/webhook/ngrok.mjs +181 -0
- package/src/runtime/channels/lib/webhook/signature.mjs +60 -0
- package/src/runtime/channels/lib/webhook.mjs +36 -570
- package/src/runtime/channels/lib/whisper-language.mjs +42 -0
- package/src/runtime/channels/tool-defs.mjs +11 -130
- package/src/runtime/memory/index.mjs +258 -2050
- package/src/runtime/memory/lib/core-memory-store.mjs +351 -1
- package/src/runtime/memory/lib/cycle-llm-adapters.mjs +58 -0
- package/src/runtime/memory/lib/cycle-scheduler.mjs +497 -0
- package/src/runtime/memory/lib/cycle-signatures.mjs +34 -0
- package/src/runtime/memory/lib/embedding-warmup.mjs +58 -0
- package/src/runtime/memory/lib/http-wire.mjs +57 -0
- package/src/runtime/memory/lib/memory-config-flags.mjs +91 -0
- package/src/runtime/memory/lib/memory-cycle.mjs +1 -1
- package/src/runtime/memory/lib/memory-cycle2-gate.mjs +515 -0
- package/src/runtime/memory/lib/memory-cycle2-mutations.mjs +324 -0
- package/src/runtime/memory/lib/memory-cycle2-shared.mjs +18 -0
- package/src/runtime/memory/lib/memory-cycle2.mjs +72 -837
- package/src/runtime/memory/lib/memory-embed.mjs +149 -0
- package/src/runtime/memory/lib/memory-process-lock.mjs +162 -0
- package/src/runtime/memory/lib/memory-recall-scope-filter.mjs +24 -0
- package/src/runtime/memory/lib/memory-recall-store.mjs +22 -2
- package/src/runtime/memory/lib/memory-retrievers.mjs +8 -0
- package/src/runtime/memory/lib/memory.mjs +20 -0
- package/src/runtime/memory/lib/pg/supervisor.mjs +1 -1
- package/src/runtime/memory/lib/promotion-fingerprint.mjs +50 -0
- package/src/runtime/memory/lib/query-handlers.mjs +780 -0
- package/src/runtime/memory/lib/recall-format.mjs +238 -0
- package/src/runtime/memory/lib/runtime-fetcher.mjs +8 -3
- package/src/runtime/memory/lib/transcript-ingest.mjs +425 -0
- package/src/runtime/memory/tool-defs.mjs +6 -14
- package/src/runtime/search/lib/http-fetch.mjs +274 -0
- package/src/runtime/search/lib/ssrf-guard.mjs +333 -0
- package/src/runtime/search/lib/web-tools.mjs +24 -602
- package/src/runtime/shared/abort-controller.mjs +1 -1
- package/src/runtime/shared/atomic-file.mjs +26 -1
- package/src/runtime/shared/background-tasks.mjs +2 -3
- package/src/runtime/shared/buffered-appender.mjs +149 -0
- package/src/runtime/shared/launcher-control.mjs +2 -2
- package/src/runtime/shared/task-notification-envelope.mjs +98 -0
- package/src/runtime/shared/tool-execution-contract.mjs +2 -2
- package/src/runtime/shared/tool-primitives.mjs +308 -0
- package/src/runtime/shared/tool-result-summary.mjs +515 -0
- package/src/runtime/shared/tool-surface.mjs +80 -898
- package/src/runtime/shared/transcript-writer.mjs +52 -2
- package/src/runtime/shared/update-checker.mjs +7 -4
- package/src/session-runtime/config-helpers.mjs +291 -0
- package/src/session-runtime/config-lifecycle.mjs +232 -0
- package/src/session-runtime/cwd-plugins.mjs +226 -0
- package/src/session-runtime/effort.mjs +128 -0
- package/src/session-runtime/fs-utils.mjs +10 -0
- package/src/session-runtime/mcp-glue.mjs +177 -0
- package/src/session-runtime/model-capabilities.mjs +130 -0
- package/src/session-runtime/model-recency.mjs +111 -0
- package/src/session-runtime/native-search.mjs +247 -0
- package/src/session-runtime/output-styles.mjs +126 -0
- package/src/session-runtime/plugin-mcp.mjs +114 -0
- package/src/session-runtime/prewarm.mjs +142 -0
- package/src/session-runtime/provider-models.mjs +278 -0
- package/src/session-runtime/provider-usage.mjs +120 -0
- package/src/session-runtime/quick-model-rows.mjs +170 -0
- package/src/session-runtime/quick-search-models.mjs +46 -0
- package/src/session-runtime/session-hooks.mjs +93 -0
- package/src/session-runtime/session-text.mjs +100 -0
- package/src/session-runtime/settings-api.mjs +319 -0
- package/src/session-runtime/statusline-route.mjs +35 -0
- package/src/session-runtime/tool-catalog.mjs +720 -0
- package/src/session-runtime/tool-defs.mjs +84 -0
- package/src/session-runtime/warmup-schedulers.mjs +201 -0
- package/src/session-runtime/workflow.mjs +358 -0
- package/src/standalone/agent-tool/helpers.mjs +237 -0
- package/src/standalone/agent-tool/notify.mjs +107 -0
- package/src/standalone/agent-tool/provider-init.mjs +143 -0
- package/src/standalone/agent-tool/render.mjs +152 -0
- package/src/standalone/agent-tool/tool-def.mjs +55 -0
- package/src/standalone/agent-tool.mjs +155 -677
- package/src/standalone/channel-worker.mjs +7 -9
- package/src/standalone/explore-tool.mjs +40 -12
- package/src/standalone/hook-bus/config.mjs +207 -0
- package/src/standalone/hook-bus/constants.mjs +90 -0
- package/src/standalone/hook-bus/handlers.mjs +481 -0
- package/src/standalone/hook-bus/payload.mjs +31 -0
- package/src/standalone/hook-bus/rules.mjs +77 -0
- package/src/standalone/hook-bus.mjs +110 -746
- package/src/standalone/memory-runtime-proxy.mjs +7 -0
- package/src/standalone/opencode-go-login.mjs +125 -0
- package/src/standalone/provider-admin.mjs +15 -19
- package/src/standalone/usage-dashboard.mjs +3 -1
- package/src/tui/App.jsx +1163 -7571
- package/src/tui/app/app-format.mjs +206 -0
- package/src/tui/app/channel-pickers.mjs +510 -0
- package/src/tui/app/clipboard.mjs +67 -0
- package/src/tui/app/core-memory-picker.mjs +210 -0
- package/src/tui/app/extension-pickers.mjs +506 -0
- package/src/tui/app/input-parsers.mjs +193 -0
- package/src/tui/app/maintenance-pickers.mjs +324 -0
- package/src/tui/app/model-options.mjs +330 -0
- package/src/tui/app/model-picker.mjs +365 -0
- package/src/tui/app/onboarding-steps.mjs +400 -0
- package/src/tui/app/project-picker.mjs +247 -0
- package/src/tui/app/provider-setup-picker.mjs +580 -0
- package/src/tui/app/resume-picker.mjs +55 -0
- package/src/tui/app/route-pickers.mjs +419 -0
- package/src/tui/app/settings-picker.mjs +490 -0
- package/src/tui/app/slash-commands.mjs +101 -0
- package/src/tui/app/slash-dispatch.mjs +427 -0
- package/src/tui/app/text-layout.mjs +46 -0
- package/src/tui/app/theme-effort-pickers.mjs +154 -0
- package/src/tui/app/transcript-window.mjs +671 -0
- package/src/tui/app/use-mouse-input.mjs +460 -0
- package/src/tui/app/use-prompt-handlers.mjs +310 -0
- package/src/tui/app/use-transcript-scroll.mjs +510 -0
- package/src/tui/app/use-transcript-window.mjs +589 -0
- package/src/tui/components/ConfirmBar.jsx +1 -1
- package/src/tui/components/Picker.jsx +32 -4
- package/src/tui/components/PromptInput.jsx +259 -80
- package/src/tui/components/SlashCommandPalette.jsx +8 -1
- package/src/tui/components/StatusLine.jsx +63 -12
- package/src/tui/components/TextEntryPanel.jsx +11 -0
- package/src/tui/components/ToolExecution.jsx +56 -588
- package/src/tui/components/TranscriptItem.jsx +105 -0
- package/src/tui/components/UsagePanel.jsx +18 -4
- package/src/tui/components/prompt-input/edit-helpers.mjs +72 -0
- package/src/tui/components/prompt-input/voice-indicator.mjs +39 -0
- package/src/tui/components/tool-execution/ResultBody.jsx +56 -0
- package/src/tui/components/tool-execution/surface-detail.mjs +405 -0
- package/src/tui/components/tool-execution/text-format.mjs +161 -0
- package/src/tui/components/tool-output-format.mjs +2 -2
- package/src/tui/display-width.mjs +20 -3
- package/src/tui/dist/index.mjs +18034 -17188
- package/src/tui/engine/agent-envelope.mjs +296 -0
- package/src/tui/engine/agent-job-feed.mjs +133 -0
- package/src/tui/engine/boot-profile.mjs +21 -0
- package/src/tui/engine/labels.mjs +67 -0
- package/src/tui/engine/notice-text.mjs +112 -0
- package/src/tui/engine/notification-plan.mjs +76 -0
- package/src/tui/engine/queue-helpers.mjs +161 -0
- package/src/tui/engine/render-timing.mjs +17 -0
- package/src/tui/engine/session-stats.mjs +46 -0
- package/src/tui/engine/tool-approval.mjs +94 -0
- package/src/tui/engine/tool-call-fields.mjs +23 -0
- package/src/tui/engine/tool-card-results.mjs +234 -0
- package/src/tui/engine/tool-result-status.mjs +135 -0
- package/src/tui/engine/tool-result-text.mjs +126 -0
- package/src/tui/engine.mjs +405 -1385
- package/src/tui/figures.mjs +5 -0
- package/src/tui/index.jsx +105 -0
- package/src/tui/input-editing.mjs +60 -10
- package/src/tui/keyboard-protocol.mjs +2 -2
- package/src/tui/lib/voice-recorder.mjs +35 -19
- package/src/tui/markdown/format-token.mjs +11 -9
- package/src/tui/paste-attachments.mjs +38 -0
- package/src/tui/statusline-ansi-bridge.mjs +11 -3
- package/src/tui/theme.mjs +6 -0
- package/src/tui/themes/base.mjs +2 -2
- package/src/tui/themes/kanagawa.mjs +4 -4
- package/src/tui/themes/teal.mjs +4 -5
- package/src/tui/themes/utils.mjs +1 -1
- package/src/ui/statusline-agents.mjs +213 -0
- package/src/ui/statusline-format.mjs +146 -0
- package/src/ui/statusline-segments.mjs +148 -0
- package/src/ui/statusline.mjs +77 -462
- package/src/ui/tool-card.mjs +0 -1
- package/src/vendor/statusline/bin/statusline-route.mjs +15 -2
- package/src/workflows/default/WORKFLOW.md +16 -9
- package/src/workflows/sequential/WORKFLOW.md +16 -11
- package/src/workflows/solo/WORKFLOW.md +5 -1
- package/vendor/ink/build/display-width.js +19 -3
- package/vendor/ink/build/ink.js +103 -6
- package/vendor/ink/build/log-update.js +17 -3
- package/vendor/ink/build/wrap-text.js +125 -0
- package/scripts/_test-folder-dialog.mjs +0 -30
- package/scripts/fix-brief-fn.mjs +0 -35
- package/scripts/fix-format-tool-surface.mjs +0 -24
- package/scripts/fix-tool-exec-visible.mjs +0 -42
- package/scripts/patch-agent-brief.mjs +0 -48
- package/scripts/patch-app.mjs +0 -21
- package/scripts/patch-app2.mjs +0 -18
- package/scripts/patch-dist-brief.mjs +0 -96
- package/scripts/patch-tool-exec.mjs +0 -70
- package/src/examples/schedules/SCHEDULE.example.md +0 -32
- package/src/examples/webhooks/WEBHOOK.example.md +0 -40
- package/src/runtime/agent/orchestrator/session/manager.reactive-persist.test.mjs +0 -107
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.test.mjs +0 -143
- package/src/runtime/agent/orchestrator/tools/builtin/diagnostics-tool.mjs +0 -285
- package/src/runtime/agent/orchestrator/tools/builtin/open-config-tool.mjs +0 -26
- package/src/runtime/shared/channel-notification-routing.test.mjs +0 -45
- package/src/runtime/shared/tool-execution-contract.test.mjs +0 -183
- package/src/standalone/agent-task-status.test.mjs +0 -76
- package/src/tui/components/tool-output-format.test.mjs +0 -399
- package/src/tui/display-width.test.mjs +0 -35
- package/src/tui/engine-runtime-notification.test.mjs +0 -115
- package/src/tui/engine-tool-result-text.test.mjs +0 -75
- package/src/tui/markdown/format-token.test.mjs +0 -354
- package/src/tui/markdown/render-ansi.test.mjs +0 -108
- package/src/tui/markdown/stream-fence.test.mjs +0 -26
- package/src/tui/markdown/streaming-markdown.test.mjs +0 -70
- package/src/tui/prompt-history-store.test.mjs +0 -52
- package/src/tui/statusline-ansi-bridge.test.mjs +0 -159
- package/src/tui/transcript-tool-failures.test.mjs +0 -111
- package/src/ui/markdown.test.mjs +0 -70
- package/src/ui/statusline-context-label.test.mjs +0 -15
- package/src/vendor/statusline/bin/statusline-lib.mjs +0 -186
- package/src/vendor/statusline/bin/statusline-route.test.mjs +0 -80
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/tui/engine/agent-envelope.mjs - parse agent/background-task/shell
|
|
3
|
+
* notification envelopes into synthetic tool-item shapes, and derive
|
|
4
|
+
* status/result text. Extracted from engine.mjs; parseBackgroundTaskEnvelope
|
|
5
|
+
* remains part of engine.mjs's public surface.
|
|
6
|
+
*/
|
|
7
|
+
import { isBackgroundErrorOnlyBody } from '../../runtime/shared/err-text.mjs';
|
|
8
|
+
|
|
9
|
+
export function textBetweenTag(text, tag) {
|
|
10
|
+
const re = new RegExp(`<${tag}[^>]*>([\\s\\S]*?)<\\/${tag}>`, 'i');
|
|
11
|
+
const match = re.exec(String(text ?? ''));
|
|
12
|
+
return match ? match[1].trim() : '';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function stripSyntheticAgentTags(text) {
|
|
16
|
+
const value = String(text ?? '').trim();
|
|
17
|
+
const finalAnswer = textBetweenTag(value, 'final-answer');
|
|
18
|
+
if (finalAnswer) return finalAnswer;
|
|
19
|
+
const taskResult = textBetweenTag(value, 'result');
|
|
20
|
+
if (taskResult) return taskResult;
|
|
21
|
+
return value
|
|
22
|
+
.replace(/^agent result[^\n]*(?:\n|$)/i, '')
|
|
23
|
+
.replace(/<\/?(?:final-answer|task-notification|task-id|tool-use-id|output-file|result|status|summary|usage|total_tokens|tool_uses|duration_ms|worktree|worktreePath|worktreeBranch)[^>]*>/gi, '')
|
|
24
|
+
.trim();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function splitBridgeEnvelope(text) {
|
|
28
|
+
const value = String(text ?? '').trim();
|
|
29
|
+
if (!value) return { head: '', body: '' };
|
|
30
|
+
const match = /\n\s*\n/.exec(value);
|
|
31
|
+
if (!match) return { head: value, body: '' };
|
|
32
|
+
return {
|
|
33
|
+
head: value.slice(0, match.index).trim(),
|
|
34
|
+
body: value.slice(match.index + match[0].length).trim(),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function agentJobStatusText(parsed) {
|
|
39
|
+
if (!parsed) return '';
|
|
40
|
+
const parts = [];
|
|
41
|
+
if (parsed.status) parts.push(`status: ${parsed.status}`);
|
|
42
|
+
if (parsed.taskId) parts.push(`task_id: ${parsed.taskId}`);
|
|
43
|
+
return parts.join(' · ');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function agentJobResultText(text, parsed = parseAgentJob(text)) {
|
|
47
|
+
const value = String(text ?? '').trim();
|
|
48
|
+
if (!value) return '';
|
|
49
|
+
if (parsed?.taskId) {
|
|
50
|
+
const { body } = splitBridgeEnvelope(value);
|
|
51
|
+
const cleanBody = stripSyntheticAgentTags(body);
|
|
52
|
+
if (cleanBody) return cleanBody;
|
|
53
|
+
return agentJobStatusText(parsed);
|
|
54
|
+
}
|
|
55
|
+
return stripSyntheticAgentTags(value) || value;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function parseAgentResultEnvelope(text, fallback = {}) {
|
|
59
|
+
const value = String(text ?? '').trim();
|
|
60
|
+
if (!/^agent result\b/i.test(value)) return null;
|
|
61
|
+
const [head = '', ...restLines] = value.split('\n');
|
|
62
|
+
const body = stripSyntheticAgentTags(restLines.join('\n'));
|
|
63
|
+
const attrs = {};
|
|
64
|
+
const attrRe = /([a-zA-Z][\w-]*)=("[^"]*"|'[^']*'|\S+)/g;
|
|
65
|
+
let match;
|
|
66
|
+
while ((match = attrRe.exec(head))) {
|
|
67
|
+
attrs[match[1].toLowerCase()] = String(match[2] || '').replace(/^["']|["']$/g, '');
|
|
68
|
+
}
|
|
69
|
+
const providerModel = /\s([a-zA-Z0-9_.-]+)\/([^\s]+)\s*$/i.exec(head);
|
|
70
|
+
const agent = attrs.agent || fallback.agent || '';
|
|
71
|
+
return {
|
|
72
|
+
name: 'agent',
|
|
73
|
+
label: String(fallback.status || attrs.status || 'completed').toLowerCase(),
|
|
74
|
+
args: {
|
|
75
|
+
type: 'result',
|
|
76
|
+
status: fallback.status || attrs.status || 'completed',
|
|
77
|
+
task_id: fallback.taskId || attrs.task_id || attrs.taskid || undefined,
|
|
78
|
+
tag: fallback.tag || attrs.tag || undefined,
|
|
79
|
+
agent: agent || undefined,
|
|
80
|
+
provider: fallback.provider || attrs.provider || providerModel?.[1] || undefined,
|
|
81
|
+
model: fallback.model || attrs.model || providerModel?.[2] || undefined,
|
|
82
|
+
preset: fallback.preset || attrs.preset || undefined,
|
|
83
|
+
effort: fallback.effort || attrs.effort || undefined,
|
|
84
|
+
fast: fallback.fast ?? attrs.fast,
|
|
85
|
+
},
|
|
86
|
+
result: body || agentJobStatusText({ status: fallback.status || attrs.status || 'completed', taskId: fallback.taskId || attrs.task_id || attrs.taskid || '' }),
|
|
87
|
+
isError: /^(failed|error|timeout|cancelled|canceled|killed)$/i.test(fallback.status || attrs.status || ''),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function parseBackgroundTaskEnvelope(text) {
|
|
92
|
+
const value = String(text ?? '').trim();
|
|
93
|
+
if (!/^background task\b/i.test(value)) return null;
|
|
94
|
+
const allLines = value.split('\n');
|
|
95
|
+
const rest = allLines.slice(1);
|
|
96
|
+
const blank = rest.findIndex((line) => !line.trim());
|
|
97
|
+
const headLines = blank >= 0 ? rest.slice(0, blank) : rest;
|
|
98
|
+
const body = blank >= 0 ? rest.slice(blank + 1).join('\n').trim() : '';
|
|
99
|
+
const fields = {};
|
|
100
|
+
for (const line of headLines) {
|
|
101
|
+
const match = /^([a-zA-Z][\w-]*):\s*(.*)$/.exec(line.trim());
|
|
102
|
+
if (match) fields[match[1].toLowerCase()] = match[2].trim();
|
|
103
|
+
}
|
|
104
|
+
const surface = String(fields.surface || fields.operation || 'task').toLowerCase();
|
|
105
|
+
const name = surface === 'explore' || surface === 'search' || surface === 'shell' || surface === 'agent' ? surface : 'task';
|
|
106
|
+
const status = String(fields.status || '').toLowerCase();
|
|
107
|
+
const taskId = fields.task_id || fields.taskid || '';
|
|
108
|
+
const errorText = fields.error || '';
|
|
109
|
+
const agentResult = parseAgentResultEnvelope(body, {
|
|
110
|
+
status,
|
|
111
|
+
taskId,
|
|
112
|
+
tag: fields.tag || fields.label || '',
|
|
113
|
+
agent: fields.agent || '',
|
|
114
|
+
provider: fields.provider || '',
|
|
115
|
+
model: fields.model || '',
|
|
116
|
+
preset: fields.preset || '',
|
|
117
|
+
effort: fields.effort || '',
|
|
118
|
+
fast: fields.fast,
|
|
119
|
+
});
|
|
120
|
+
if (agentResult) return { ...agentResult, rawResult: value };
|
|
121
|
+
const errorOnlyBody = isBackgroundErrorOnlyBody(body, errorText);
|
|
122
|
+
const resultBody = body && !errorOnlyBody ? body : '';
|
|
123
|
+
return {
|
|
124
|
+
name,
|
|
125
|
+
label: status || 'notification',
|
|
126
|
+
args: {
|
|
127
|
+
type: body ? 'result' : (fields.operation || 'status'),
|
|
128
|
+
status,
|
|
129
|
+
task_id: taskId || undefined,
|
|
130
|
+
surface,
|
|
131
|
+
operation: fields.operation || undefined,
|
|
132
|
+
label: fields.label || undefined,
|
|
133
|
+
tag: fields.tag || undefined,
|
|
134
|
+
agent: fields.agent || undefined,
|
|
135
|
+
provider: fields.provider || undefined,
|
|
136
|
+
model: fields.model || undefined,
|
|
137
|
+
preset: fields.preset || undefined,
|
|
138
|
+
effort: fields.effort || undefined,
|
|
139
|
+
fast: fields.fast || undefined,
|
|
140
|
+
error: errorText || undefined,
|
|
141
|
+
startedAt: fields.started || fields.startedat || undefined,
|
|
142
|
+
finishedAt: fields.finished || fields.finishedat || undefined,
|
|
143
|
+
},
|
|
144
|
+
result: resultBody || (!errorText ? [status ? `status: ${status}` : '', taskId ? `task_id: ${taskId}` : ''].filter(Boolean).join(' · ') : ''),
|
|
145
|
+
rawResult: value,
|
|
146
|
+
isError: /^(failed|error|timeout|cancelled|canceled|killed)$/i.test(status) || /^error:/i.test(body) || Boolean(errorText),
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export function isStatusOnlyAgentCompletionNotification(text) {
|
|
151
|
+
const background = parseBackgroundTaskEnvelope(text);
|
|
152
|
+
if (background?.name === 'agent' && /^(completed|cancelled|canceled)$/i.test(background.label || '')) {
|
|
153
|
+
return !(hasAgentResponseResultText(background.result) || hasAgentResponseResultText(text));
|
|
154
|
+
}
|
|
155
|
+
const parsed = parseAgentJob(text);
|
|
156
|
+
const result = agentJobResultText(text, parsed);
|
|
157
|
+
if (!parsed?.taskId || !/^(completed|cancelled|canceled)$/i.test(parsed.status || '')) return false;
|
|
158
|
+
return !(hasAgentResponseResultText(result) || hasAgentResponseResultText(text));
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export function hasAgentResponseResultText(text) {
|
|
162
|
+
const value = String(text || '').trim();
|
|
163
|
+
if (!value) return false;
|
|
164
|
+
if (/^status:\s*(?:running|pending|queued|completed|failed|cancelled|canceled)(?:\s*·\s*task_id:\s*\S+)?$/i.test(value)) return false;
|
|
165
|
+
if (/^(?:background task\b|agent task:|task_id:)/i.test(value) && !/\n\s*\n[\s\S]*\S/.test(value)) return false;
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export function bracketField(text, name) {
|
|
170
|
+
const re = new RegExp(`^\\[${name}:\\s*([^\\]]*)\\]`, 'mi');
|
|
171
|
+
return re.exec(String(text ?? ''))?.[1]?.trim() || '';
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export function toolResultStatus(text) {
|
|
175
|
+
const value = String(text ?? '');
|
|
176
|
+
const tagged = textBetweenTag(value, 'status');
|
|
177
|
+
if (tagged) return tagged.trim();
|
|
178
|
+
const bracketed = bracketField(value, 'status');
|
|
179
|
+
if (bracketed) return bracketed.trim();
|
|
180
|
+
const inline = /^(?:status|state):\s*([^\s·,;]+)/mi.exec(value);
|
|
181
|
+
return inline ? inline[1].trim() : '';
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export function isErrorToolStatus(status) {
|
|
185
|
+
return /^(failed|error|timeout|cancelled|canceled|killed)$/i.test(String(status || '').trim());
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export function parseSyntheticAgentMessage(text) {
|
|
189
|
+
const value = String(text ?? '').trim();
|
|
190
|
+
if (!value) return null;
|
|
191
|
+
const finalAnswer = textBetweenTag(value, 'final-answer');
|
|
192
|
+
if (finalAnswer) {
|
|
193
|
+
return {
|
|
194
|
+
name: 'agent',
|
|
195
|
+
label: 'final',
|
|
196
|
+
args: { type: 'read', description: 'agent result' },
|
|
197
|
+
result: finalAnswer,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
const agentResult = parseAgentResultEnvelope(value);
|
|
201
|
+
if (agentResult) return agentResult;
|
|
202
|
+
const backgroundTask = parseBackgroundTaskEnvelope(value);
|
|
203
|
+
if (backgroundTask) return backgroundTask;
|
|
204
|
+
const shellTaskId = bracketField(value, 'task_id');
|
|
205
|
+
if (shellTaskId) {
|
|
206
|
+
const status = bracketField(value, 'status') || 'done';
|
|
207
|
+
const exit = bracketField(value, 'exit');
|
|
208
|
+
const command = bracketField(value, 'command');
|
|
209
|
+
return {
|
|
210
|
+
name: 'shell',
|
|
211
|
+
label: status,
|
|
212
|
+
args: { type: 'result', task_id: shellTaskId, command },
|
|
213
|
+
result: value,
|
|
214
|
+
isError: /^(failed|error|timeout|cancelled|killed)$/i.test(status) || (exit && exit !== '0' && exit !== 'n/a'),
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
const agentJob = parseAgentJob(value);
|
|
218
|
+
if (agentJob?.taskId) {
|
|
219
|
+
const label = agentJob.status || 'notification';
|
|
220
|
+
const result = agentJobResultText(value, agentJob);
|
|
221
|
+
return {
|
|
222
|
+
name: 'agent',
|
|
223
|
+
label,
|
|
224
|
+
args: agentArgsWithResultMetadata({ type: agentJob.type || 'notification', description: 'agent notification' }, agentJob),
|
|
225
|
+
result: result || agentJobStatusText(agentJob) || 'agent notification',
|
|
226
|
+
isError: /^(failed|error|timeout|cancelled|killed)$/i.test(label),
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
if (/<task-notification\b/i.test(value)) {
|
|
230
|
+
const status = textBetweenTag(value, 'status') || 'completed';
|
|
231
|
+
const summary = textBetweenTag(value, 'summary') || `Agent ${status}`;
|
|
232
|
+
const taskId = textBetweenTag(value, 'task-id');
|
|
233
|
+
const result = stripSyntheticAgentTags(value);
|
|
234
|
+
return {
|
|
235
|
+
name: 'agent',
|
|
236
|
+
label: status,
|
|
237
|
+
taskId,
|
|
238
|
+
summary,
|
|
239
|
+
result: result || summary,
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export function parseAgentJob(text) {
|
|
246
|
+
const value = String(text || '');
|
|
247
|
+
const idMatch = /^agent task:\s*([^\s]+)/m.exec(value) || /^task_id:\s*([^\s]+)/m.exec(value);
|
|
248
|
+
if (!idMatch) return null;
|
|
249
|
+
const statusMatch = /^status:\s*([^\s(]+)/m.exec(value);
|
|
250
|
+
const typeMatch = /^type:\s*(.+)$/m.exec(value);
|
|
251
|
+
const targetMatch = /^target:\s*(.+)$/m.exec(value);
|
|
252
|
+
const agentMatch = /^agent:\s*(.+)$/m.exec(value);
|
|
253
|
+
const presetMatch = /^preset:\s*(.+)$/m.exec(value);
|
|
254
|
+
const modelMatch = /^model:\s*([^/\s]+)\/(.+)$/m.exec(value);
|
|
255
|
+
const effortMatch = /^effort:\s*(.+)$/m.exec(value);
|
|
256
|
+
const fastMatch = /^fast:\s*(on|off|true|false)$/m.exec(value);
|
|
257
|
+
return {
|
|
258
|
+
taskId: idMatch[1],
|
|
259
|
+
status: (statusMatch?.[1] || '').toLowerCase(),
|
|
260
|
+
type: (typeMatch?.[1] || '').trim(),
|
|
261
|
+
target: (targetMatch?.[1] || '').trim(),
|
|
262
|
+
agent: (agentMatch?.[1] || '').trim(),
|
|
263
|
+
preset: (presetMatch?.[1] || '').trim(),
|
|
264
|
+
provider: (modelMatch?.[1] || '').trim(),
|
|
265
|
+
model: (modelMatch?.[2] || '').trim(),
|
|
266
|
+
effort: (effortMatch?.[1] || '').trim(),
|
|
267
|
+
fast: fastMatch ? /^(on|true)$/i.test(fastMatch[1]) : undefined,
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export function agentArgsWithResultMetadata(args, parsed) {
|
|
272
|
+
if (!parsed) return args;
|
|
273
|
+
const next = { ...(args && typeof args === 'object' ? args : {}) };
|
|
274
|
+
const requestedAction = String(next.type || next.action || next.mode || '').trim().toLowerCase();
|
|
275
|
+
if (parsed.type) {
|
|
276
|
+
// Job status envelopes report the original job type (usually "spawn").
|
|
277
|
+
// Preserve the user's current agent tool action ("status", "read", …) so
|
|
278
|
+
// manual checks render as "Reviewer status" instead of another
|
|
279
|
+
// "Spawning Reviewer" card. Keep the job type as metadata for detail.
|
|
280
|
+
if (!requestedAction || /^(notification|result|completion)$/i.test(requestedAction)) next.type = parsed.type;
|
|
281
|
+
else next.jobType = parsed.type;
|
|
282
|
+
}
|
|
283
|
+
if (parsed.status) next.status = parsed.status;
|
|
284
|
+
if (parsed.taskId) next.task_id = parsed.taskId;
|
|
285
|
+
if (parsed.agent) next.agent = parsed.agent;
|
|
286
|
+
if (parsed.preset) next.preset = parsed.preset;
|
|
287
|
+
if (parsed.provider) next.provider = parsed.provider;
|
|
288
|
+
if (parsed.model) next.model = parsed.model;
|
|
289
|
+
if (parsed.effort) next.effort = parsed.effort;
|
|
290
|
+
if (parsed.fast !== undefined) next.fast = parsed.fast;
|
|
291
|
+
if (!next.tag && parsed.target) {
|
|
292
|
+
const target = parsed.target.split(/\s+/)[0];
|
|
293
|
+
if (target && !target.startsWith('sess_')) next.tag = target;
|
|
294
|
+
}
|
|
295
|
+
return next;
|
|
296
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/tui/engine/agent-job-feed.mjs — agent-job / runtime-notification plumbing
|
|
3
|
+
* extracted from createEngineSession (engine.mjs) as a dependency-injection
|
|
4
|
+
* factory.
|
|
5
|
+
*
|
|
6
|
+
* Owns: the agent-job card result patch (updateAgentJobCard), the
|
|
7
|
+
* execution-pending-resume kick trio (kick / flushDeferred / schedule), and the
|
|
8
|
+
* runtime.onNotification subscription that routes runtime notifications into the
|
|
9
|
+
* store (status refresh, execution-ui synthetic items, model-visible enqueue).
|
|
10
|
+
*
|
|
11
|
+
* These handlers mutate live session state and drive the queue, so
|
|
12
|
+
* state/set/enqueue/drain/pushUserOrSyntheticItem/patchItem/etc are threaded via
|
|
13
|
+
* the factory argument (getters/callbacks) — never stale snapshots. Every body
|
|
14
|
+
* is the original engine.mjs logic verbatim.
|
|
15
|
+
*/
|
|
16
|
+
import {
|
|
17
|
+
parseAgentJob,
|
|
18
|
+
agentJobResultText,
|
|
19
|
+
agentArgsWithResultMetadata,
|
|
20
|
+
} from './agent-envelope.mjs';
|
|
21
|
+
import { toolErrorDisplay } from './tool-result-text.mjs';
|
|
22
|
+
import {
|
|
23
|
+
notificationQueueKey,
|
|
24
|
+
resolveTuiRuntimeNotificationDelivery,
|
|
25
|
+
} from './notification-plan.mjs';
|
|
26
|
+
|
|
27
|
+
export function createAgentJobFeed({
|
|
28
|
+
runtime,
|
|
29
|
+
getState,
|
|
30
|
+
set,
|
|
31
|
+
nextId,
|
|
32
|
+
getDisposed,
|
|
33
|
+
patchItem,
|
|
34
|
+
enqueue,
|
|
35
|
+
drain,
|
|
36
|
+
pushUserOrSyntheticItem,
|
|
37
|
+
makeQueueEntry,
|
|
38
|
+
getPending,
|
|
39
|
+
agentStatusState,
|
|
40
|
+
displayedExecutionNotificationKeys,
|
|
41
|
+
}) {
|
|
42
|
+
let executionResumeKickDeferred = false;
|
|
43
|
+
|
|
44
|
+
function kickExecutionPendingResume() {
|
|
45
|
+
if (getDisposed()) return;
|
|
46
|
+
if (getState().busy) {
|
|
47
|
+
executionResumeKickDeferred = true;
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const pending = getPending();
|
|
51
|
+
if (pending.some((entry) => entry.mode === 'pending-resume')) {
|
|
52
|
+
executionResumeKickDeferred = true;
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
executionResumeKickDeferred = false;
|
|
56
|
+
pending.push(makeQueueEntry('', { mode: 'pending-resume', priority: 'next' }));
|
|
57
|
+
void drain();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function flushDeferredExecutionPendingResumeKick() {
|
|
61
|
+
if (!executionResumeKickDeferred || getDisposed() || getState().busy) return;
|
|
62
|
+
kickExecutionPendingResume();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function scheduleExecutionPendingResumeKick() {
|
|
66
|
+
// notifyFnForSession enqueues the model-visible body after onNotification
|
|
67
|
+
// returns; defer the kick so askSession pre-drain sees session pending.
|
|
68
|
+
queueMicrotask(() => kickExecutionPendingResume());
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function updateAgentJobCard(itemId, text, isError = false) {
|
|
72
|
+
const parsed = parseAgentJob(text);
|
|
73
|
+
const current = getState().items.find((it) => it.id === itemId);
|
|
74
|
+
const rawDisplayText = agentJobResultText(text, parsed) || String(text ?? '').trim();
|
|
75
|
+
const displayText = isError ? toolErrorDisplay(rawDisplayText, 'agent') : rawDisplayText;
|
|
76
|
+
patchItem(itemId, {
|
|
77
|
+
result: displayText,
|
|
78
|
+
text: displayText,
|
|
79
|
+
isError,
|
|
80
|
+
errorCount: isError ? 1 : 0,
|
|
81
|
+
...(parsed ? { args: agentArgsWithResultMetadata(current?.args, parsed) } : {}),
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function subscribeRuntimeNotifications() {
|
|
86
|
+
if (typeof runtime.onNotification !== 'function') return null;
|
|
87
|
+
return runtime.onNotification((event) => {
|
|
88
|
+
if (getDisposed()) return;
|
|
89
|
+
const text = String(event?.content ?? event?.text ?? event ?? '').trim();
|
|
90
|
+
if (!text) return;
|
|
91
|
+
const parsed = parseAgentJob(text);
|
|
92
|
+
const notificationKey = notificationQueueKey(event, text, parsed);
|
|
93
|
+
const delivery = resolveTuiRuntimeNotificationDelivery(event, text);
|
|
94
|
+
if (delivery.action === 'ignore') return;
|
|
95
|
+
if (delivery.action === 'status-only') {
|
|
96
|
+
if (parsed?.taskId) set(agentStatusState({ force: true }));
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
if (delivery.action === 'execution-ui') {
|
|
100
|
+
const firstDelivery = !notificationKey || !displayedExecutionNotificationKeys.has(notificationKey);
|
|
101
|
+
if (firstDelivery) {
|
|
102
|
+
if (notificationKey) displayedExecutionNotificationKeys.add(notificationKey);
|
|
103
|
+
pushUserOrSyntheticItem(delivery.displayText, nextId());
|
|
104
|
+
}
|
|
105
|
+
if (parsed?.taskId) set(agentStatusState({ force: true }));
|
|
106
|
+
if (String(delivery.modelContent || '').trim()) {
|
|
107
|
+
scheduleExecutionPendingResumeKick();
|
|
108
|
+
}
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
if (parsed?.taskId) {
|
|
112
|
+
set(agentStatusState({ force: true }));
|
|
113
|
+
}
|
|
114
|
+
const modelContent = String(delivery.modelContent ?? delivery.displayText ?? text).trim();
|
|
115
|
+
if (!modelContent) return true;
|
|
116
|
+
enqueue(modelContent, {
|
|
117
|
+
mode: 'task-notification',
|
|
118
|
+
priority: 'next',
|
|
119
|
+
key: notificationKey || undefined,
|
|
120
|
+
displayText: delivery.displayText || text,
|
|
121
|
+
});
|
|
122
|
+
return true;
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
kickExecutionPendingResume,
|
|
128
|
+
flushDeferredExecutionPendingResumeKick,
|
|
129
|
+
scheduleExecutionPendingResumeKick,
|
|
130
|
+
updateAgentJobCard,
|
|
131
|
+
subscribeRuntimeNotifications,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/tui/engine/boot-profile.mjs - opt-in boot timing trace.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from engine.mjs. Emits `[mixdog-boot]` stderr lines when
|
|
5
|
+
* MIXDOG_BOOT_PROFILE is truthy; a no-op otherwise.
|
|
6
|
+
*/
|
|
7
|
+
import { performance } from 'node:perf_hooks';
|
|
8
|
+
|
|
9
|
+
const BOOT_PROFILE_ENABLED = /^(1|true|yes|on)$/i.test(String(process.env.MIXDOG_BOOT_PROFILE || ''));
|
|
10
|
+
const BOOT_PROFILE_START = globalThis.__mixdogBootProfileStart || (globalThis.__mixdogBootProfileStart = performance.now());
|
|
11
|
+
|
|
12
|
+
export function bootProfile(event, fields = {}) {
|
|
13
|
+
if (!BOOT_PROFILE_ENABLED) return;
|
|
14
|
+
const elapsedMs = performance.now() - BOOT_PROFILE_START;
|
|
15
|
+
const parts = [`[mixdog-boot] +${elapsedMs.toFixed(1)}ms`, `tui:${event}`];
|
|
16
|
+
for (const [key, value] of Object.entries(fields || {})) {
|
|
17
|
+
if (value === undefined || value === null || value === '') continue;
|
|
18
|
+
parts.push(`${key}=${String(value).replace(/\s+/g, '_')}`);
|
|
19
|
+
}
|
|
20
|
+
try { process.stderr.write(`${parts.join(' ')}\n`); } catch {}
|
|
21
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/tui/engine/labels.mjs - spinner verbs, elapsed formatting, and compact
|
|
3
|
+
* event label/detail helpers. Extracted from engine.mjs.
|
|
4
|
+
*/
|
|
5
|
+
import { SPINNER_VERBS } from '../spinner-verbs.mjs';
|
|
6
|
+
|
|
7
|
+
export function pickVerb(turn) {
|
|
8
|
+
return SPINNER_VERBS[(turn * 7 + 3) % SPINNER_VERBS.length];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const TURN_DONE_VERBS = [
|
|
12
|
+
'Thought',
|
|
13
|
+
'Reasoned',
|
|
14
|
+
'Mapped',
|
|
15
|
+
'Checked',
|
|
16
|
+
'Solved',
|
|
17
|
+
'Composed',
|
|
18
|
+
'Synthesized',
|
|
19
|
+
'Wrapped',
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
export function pickDoneVerb(turn) {
|
|
23
|
+
return TURN_DONE_VERBS[(turn * 5 + 2) % TURN_DONE_VERBS.length];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function formatElapsedSeconds(ms) {
|
|
27
|
+
const value = Math.max(0, Number(ms) || 0);
|
|
28
|
+
if (value <= 0) return '0s';
|
|
29
|
+
return `${Math.max(1, Math.ceil(value / 1000))}s`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function compactEventLabel(event = {}) {
|
|
33
|
+
const status = String(event.status || '').toLowerCase();
|
|
34
|
+
const reactive = String(event.trigger || '').toLowerCase() === 'reactive';
|
|
35
|
+
if (status === 'failed') return reactive ? 'Compact failed (overflow retry)' : 'Compact failed';
|
|
36
|
+
if (status === 'skipped') return 'Compact skipped';
|
|
37
|
+
if (status === 'no_change') return 'Compact checked';
|
|
38
|
+
return reactive ? 'Compact complete (overflow recovery)' : 'Compact complete';
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function compactEventDetail(event = {}) {
|
|
42
|
+
// Keep the elapsed time as the lead detail, but no longer discard the rest of
|
|
43
|
+
// the compact metadata. Surface type/trigger and the boundary/pressure so the
|
|
44
|
+
// statusdone marker reflects what actually fired.
|
|
45
|
+
const parts = [];
|
|
46
|
+
const elapsed = formatElapsedSeconds(Number(event.durationMs ?? event.elapsedMs ?? 0));
|
|
47
|
+
if (elapsed) parts.push(elapsed);
|
|
48
|
+
const type = String(event.compactType || event.type || '').trim();
|
|
49
|
+
if (type && type !== 'semantic') parts.push(type);
|
|
50
|
+
const trigger = String(event.trigger || '').toLowerCase();
|
|
51
|
+
if (trigger === 'reactive') parts.push('reactive');
|
|
52
|
+
else if (trigger === 'manual') parts.push('manual');
|
|
53
|
+
const before = Number(event.beforeTokens ?? event.pressureTokens ?? 0);
|
|
54
|
+
const after = Number(event.afterTokens ?? 0);
|
|
55
|
+
const fmtTok = (n) => {
|
|
56
|
+
const v = Number(n) || 0;
|
|
57
|
+
if (v >= 1000) return `${(v / 1000).toFixed(v >= 10_000 ? 0 : 1)}k`;
|
|
58
|
+
return `${Math.round(v)}`;
|
|
59
|
+
};
|
|
60
|
+
if (before > 0 && after > 0 && after !== before) parts.push(`${fmtTok(before)}→${fmtTok(after)}`);
|
|
61
|
+
return parts.join(' · ');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function projectNameFromPath(value) {
|
|
65
|
+
const text = String(value || '').replace(/[\\/]+$/, '');
|
|
66
|
+
return text.split(/[\\/]/).pop() || text || '(current)';
|
|
67
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/tui/engine/notice-text.mjs - polish user-facing failure/notice text.
|
|
3
|
+
* Extracted from engine.mjs.
|
|
4
|
+
*/
|
|
5
|
+
const FAILED_NOTICE_ACTIONS = new Map([
|
|
6
|
+
['api key save', 'save API key'],
|
|
7
|
+
['auth-forget', 'forget auth'],
|
|
8
|
+
['auto-clear', 'update auto-clear'],
|
|
9
|
+
['autoclear', 'update auto-clear'],
|
|
10
|
+
['agent', 'run agent command'],
|
|
11
|
+
['channels', 'load channels'],
|
|
12
|
+
['channels update', 'update channels'],
|
|
13
|
+
['clear', 'clear chat'],
|
|
14
|
+
['compact', 'compact context'],
|
|
15
|
+
['copy', 'copy'],
|
|
16
|
+
['core memory', 'load core memory'],
|
|
17
|
+
['cwd', 'update working directory'],
|
|
18
|
+
['effort switch', 'switch effort'],
|
|
19
|
+
['fast', 'update fast mode'],
|
|
20
|
+
['hook rule update', 'update hook rule'],
|
|
21
|
+
['hook toggle', 'toggle hook'],
|
|
22
|
+
['hook update', 'update hook'],
|
|
23
|
+
['hooks status', 'load hooks'],
|
|
24
|
+
['local provider update', 'update local provider'],
|
|
25
|
+
['mcp add', 'add MCP server'],
|
|
26
|
+
['mcp reconnect', 'reconnect MCP server'],
|
|
27
|
+
['mcp status', 'load MCP status'],
|
|
28
|
+
['mcp toggle', 'toggle MCP server'],
|
|
29
|
+
['memory', 'run memory command'],
|
|
30
|
+
['memory status', 'load memory status'],
|
|
31
|
+
['model save', 'save model'],
|
|
32
|
+
['model switch', 'switch model'],
|
|
33
|
+
['oauth code', 'finish OAuth login'],
|
|
34
|
+
['oauth login', 'start OAuth login'],
|
|
35
|
+
['output style switch', 'switch output style'],
|
|
36
|
+
['OpenAI usage auth save', 'save OpenAI usage auth'],
|
|
37
|
+
['OpenCode Go usage auth save', 'save OpenCode Go usage auth'],
|
|
38
|
+
['plugin add', 'add plugin'],
|
|
39
|
+
['plugin MCP enable', 'enable plugin MCP'],
|
|
40
|
+
['plugin uninstall', 'uninstall plugin'],
|
|
41
|
+
['plugin update', 'update plugin'],
|
|
42
|
+
['plugins status', 'load plugins'],
|
|
43
|
+
['providers', 'load providers'],
|
|
44
|
+
['recall', 'run recall'],
|
|
45
|
+
['resume', 'resume chat'],
|
|
46
|
+
['schedule toggle', 'toggle schedule'],
|
|
47
|
+
['setup save', 'save setup'],
|
|
48
|
+
['settings update', 'update settings'],
|
|
49
|
+
['skill add', 'add skill'],
|
|
50
|
+
['skills status', 'load skills'],
|
|
51
|
+
['tools status', 'load tool status'],
|
|
52
|
+
['usage', 'load usage'],
|
|
53
|
+
['webhook toggle', 'toggle webhook'],
|
|
54
|
+
['workflow switch', 'switch workflow'],
|
|
55
|
+
]);
|
|
56
|
+
|
|
57
|
+
function polishNoticeAction(action) {
|
|
58
|
+
const value = String(action || '').trim();
|
|
59
|
+
if (!value) return 'finish';
|
|
60
|
+
const key = value.toLowerCase();
|
|
61
|
+
for (const [candidate, replacement] of FAILED_NOTICE_ACTIONS.entries()) {
|
|
62
|
+
if (candidate.toLowerCase() === key) return replacement;
|
|
63
|
+
}
|
|
64
|
+
const suffixes = [
|
|
65
|
+
[' save', 'save'],
|
|
66
|
+
[' switch', 'switch'],
|
|
67
|
+
[' update', 'update'],
|
|
68
|
+
[' toggle', 'toggle'],
|
|
69
|
+
[' reconnect', 'reconnect'],
|
|
70
|
+
[' enable', 'enable'],
|
|
71
|
+
[' uninstall', 'uninstall'],
|
|
72
|
+
[' add', 'add'],
|
|
73
|
+
];
|
|
74
|
+
for (const [suffix, verb] of suffixes) {
|
|
75
|
+
if (!key.endsWith(suffix)) continue;
|
|
76
|
+
const subject = value.slice(0, -suffix.length).trim();
|
|
77
|
+
return subject ? `${verb} ${subject}` : verb;
|
|
78
|
+
}
|
|
79
|
+
return value;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function sentenceStart(text) {
|
|
83
|
+
const value = String(text || '').trim();
|
|
84
|
+
return value ? `${value[0].toUpperCase()}${value.slice(1)}` : value;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function polishNoticeText(text) {
|
|
88
|
+
let value = String(text ?? '').trim().replace(/^✓\s*/, '');
|
|
89
|
+
if (!value) return '';
|
|
90
|
+
const error = /^error\s*:\s*(.+)$/i.exec(value);
|
|
91
|
+
if (error?.[1]) value = error[1].trim();
|
|
92
|
+
const couldNot = /^could not\s+(.+?)(?::\s*(.+))?$/i.exec(value);
|
|
93
|
+
if (couldNot) {
|
|
94
|
+
return couldNot[2]
|
|
95
|
+
? `Couldn’t ${couldNot[1]}: ${couldNot[2]}`
|
|
96
|
+
: `Couldn’t ${couldNot[1]}.`;
|
|
97
|
+
}
|
|
98
|
+
const failed = /^(.+?)\s+failed(?::\s*(.+))?$/i.exec(value);
|
|
99
|
+
if (failed) {
|
|
100
|
+
const action = polishNoticeAction(failed[1]);
|
|
101
|
+
return failed[2] ? `Couldn’t ${action}: ${failed[2]}` : `Couldn’t ${action}.`;
|
|
102
|
+
}
|
|
103
|
+
const busy = /^(.+?)\s+already in progress\.?$/i.exec(value);
|
|
104
|
+
if (busy) return `${sentenceStart(polishNoticeAction(busy[1]))} is already running.`;
|
|
105
|
+
const required = /^(.+?)\s+is required(?:\s+for\s+(.+))?\.?$/i.exec(value);
|
|
106
|
+
if (required) {
|
|
107
|
+
const subject = required[1].trim();
|
|
108
|
+
const target = required[2]?.trim();
|
|
109
|
+
return `${subject}${target ? ` required for ${target}` : ' required'}.`;
|
|
110
|
+
}
|
|
111
|
+
return value;
|
|
112
|
+
}
|