mixdog 0.9.1 → 0.9.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/package.json +9 -1
- package/scripts/_bench-cwc.json +20 -0
- package/scripts/agent-loop-policy-test.mjs +37 -0
- package/scripts/agent-parallel-smoke.mjs +54 -10
- package/scripts/anthropic-maxtokens-test.mjs +119 -0
- package/scripts/background-task-meta-smoke.mjs +1 -1
- package/scripts/bench-run.mjs +262 -0
- package/scripts/build-tui.mjs +13 -1
- package/scripts/compact-smoke.mjs +12 -0
- package/scripts/compact-trigger-migration-smoke.mjs +67 -1
- package/scripts/explore-bench.mjs +124 -0
- package/scripts/hook-bus-test.mjs +191 -0
- package/scripts/ingest-pure-conversation-smoke.mjs +148 -0
- package/scripts/internal-comms-bench.mjs +727 -0
- package/scripts/internal-comms-smoke.mjs +75 -0
- package/scripts/lead-workflow-smoke.mjs +4 -4
- package/scripts/live-worker-smoke.mjs +9 -9
- package/scripts/output-style-bench.mjs +285 -0
- package/scripts/output-style-smoke.mjs +13 -10
- package/scripts/patch-replay.mjs +90 -0
- package/scripts/path-suffix-test.mjs +57 -0
- package/scripts/provider-stream-stall-test.mjs +276 -0
- package/scripts/provider-toolcall-test.mjs +599 -1
- package/scripts/recall-bench.mjs +207 -0
- package/scripts/routing-corpus.mjs +281 -0
- package/scripts/session-bench.mjs +1526 -0
- package/scripts/session-diag.mjs +595 -0
- package/scripts/task-bench.mjs +207 -0
- package/scripts/tool-failures.mjs +6 -6
- package/scripts/tool-smoke.mjs +310 -67
- package/scripts/toolcall-args-test.mjs +81 -0
- package/src/agents/debugger/AGENT.md +4 -4
- package/src/agents/heavy-worker/AGENT.md +20 -9
- package/src/agents/reviewer/AGENT.md +4 -4
- package/src/agents/worker/AGENT.md +17 -9
- package/src/app.mjs +10 -6
- package/src/defaults/{hidden-roles.json → agents.json} +7 -7
- package/src/examples/schedules/SCHEDULE.example.md +32 -0
- package/src/examples/webhooks/WEBHOOK.example.md +40 -0
- package/src/headless-role.mjs +14 -14
- package/src/help.mjs +1 -0
- package/src/lib/rules-builder.cjs +32 -54
- package/src/mixdog-session-runtime.mjs +1040 -2036
- package/src/output-styles/default.md +12 -7
- package/src/output-styles/minimal.md +25 -0
- package/src/output-styles/oneline.md +21 -0
- package/src/output-styles/simple.md +10 -9
- package/src/repl.mjs +17 -7
- package/src/rules/agent/00-common.md +7 -5
- package/src/rules/agent/30-explorer.md +8 -12
- package/src/rules/lead/01-general.md +3 -1
- package/src/rules/lead/lead-tool.md +13 -2
- package/src/rules/shared/01-tool.md +23 -12
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +90 -32
- package/src/runtime/agent/orchestrator/agent-runtime/agent-loop-policy.mjs +32 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +18 -6
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +23 -20
- package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +48 -14
- package/src/runtime/agent/orchestrator/agent-trace.mjs +87 -12
- package/src/runtime/agent/orchestrator/config.mjs +3 -0
- package/src/runtime/agent/orchestrator/context/collect.mjs +182 -67
- package/src/runtime/agent/orchestrator/{internal-roles.mjs → internal-agents.mjs} +72 -72
- package/src/runtime/agent/orchestrator/internal-tools.mjs +13 -26
- package/src/runtime/agent/orchestrator/mcp/client.mjs +100 -18
- package/src/runtime/agent/orchestrator/providers/anthropic-betas.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-effort.mjs +188 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-leaked-toolcall.mjs +444 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +93 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +313 -84
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +104 -38
- package/src/runtime/agent/orchestrator/providers/api-usage.mjs +28 -33
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +184 -17
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +8 -1
- package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +32 -0
- package/src/runtime/agent/orchestrator/providers/model-catalog.mjs +18 -8
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +54 -20
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +227 -31
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +83 -6
- package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +229 -115
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +213 -33
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +18 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-usage.mjs +49 -17
- package/src/runtime/agent/orchestrator/providers/registry.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +22 -17
- package/src/runtime/agent/orchestrator/session/compact.mjs +560 -51
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +250 -3
- package/src/runtime/agent/orchestrator/session/loop/compact-debug.mjs +28 -0
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +262 -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 +49 -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/tool-classify.mjs +52 -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 +513 -1000
- package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +227 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +235 -0
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +137 -0
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +155 -0
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +303 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +232 -1152
- package/src/runtime/agent/orchestrator/session/store.mjs +4 -4
- package/src/runtime/agent/orchestrator/session/tool-envelope.mjs +61 -0
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +5 -0
- package/src/runtime/agent/orchestrator/stall-policy.mjs +63 -15
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +194 -24
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.test.mjs +143 -0
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +34 -18
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +241 -0
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.test.mjs +162 -0
- package/src/runtime/agent/orchestrator/tools/builtin/fuzzy-match.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/list-formatting.mjs +10 -0
- package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +5 -4
- package/src/runtime/agent/orchestrator/tools/builtin/path-diagnostics.mjs +42 -2
- package/src/runtime/agent/orchestrator/tools/builtin/path-utils.mjs +15 -0
- package/src/runtime/agent/orchestrator/tools/builtin/read-args.mjs +9 -44
- package/src/runtime/agent/orchestrator/tools/builtin/read-constants.mjs +2 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +14 -5
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +11 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +10 -17
- package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +23 -2
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +50 -39
- package/src/runtime/agent/orchestrator/tools/builtin/shell-output.mjs +3 -2
- package/src/runtime/agent/orchestrator/tools/builtin/tool-output-limit.mjs +10 -0
- package/src/runtime/agent/orchestrator/tools/builtin.mjs +70 -1
- 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 +497 -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/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 +1192 -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-mask.mjs +347 -0
- package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +5 -5
- package/src/runtime/agent/orchestrator/tools/code-graph.mjs +39 -4189
- package/src/runtime/agent/orchestrator/tools/patch.mjs +119 -5
- package/src/runtime/agent/orchestrator/tools/progress-message.mjs +1 -2
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +1 -2
- package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +2 -4
- package/src/runtime/channels/backends/discord.mjs +99 -9
- package/src/runtime/channels/backends/telegram.mjs +501 -0
- package/src/runtime/channels/index.mjs +437 -1439
- package/src/runtime/channels/lib/boot-profile.mjs +23 -0
- package/src/runtime/channels/lib/config.mjs +54 -2
- package/src/runtime/channels/lib/crash-log.mjs +106 -0
- package/src/runtime/channels/lib/format.mjs +4 -2
- package/src/runtime/channels/lib/index-drop-trace.mjs +72 -0
- package/src/runtime/channels/lib/output-forwarder.mjs +88 -67
- package/src/runtime/channels/lib/runtime-paths.mjs +29 -0
- package/src/runtime/channels/lib/scheduler.mjs +1 -1
- package/src/runtime/channels/lib/telegram-format.mjs +280 -0
- package/src/runtime/channels/lib/tool-format.mjs +1 -1
- package/src/runtime/channels/lib/transcript-discovery.mjs +19 -1
- package/src/runtime/channels/lib/webhook.mjs +59 -31
- package/src/runtime/channels/lib/whisper-language.mjs +42 -0
- package/src/runtime/channels/tool-defs.mjs +1 -1
- package/src/runtime/memory/index.mjs +465 -345
- package/src/runtime/memory/lib/agent-ipc.mjs +2 -2
- package/src/runtime/memory/lib/core-memory-store.mjs +352 -2
- package/src/runtime/memory/lib/cycle-signatures.mjs +34 -0
- package/src/runtime/memory/lib/http-wire.mjs +57 -0
- package/src/runtime/memory/lib/memory-cycle1.mjs +1 -1
- package/src/runtime/memory/lib/memory-cycle2.mjs +65 -9
- package/src/runtime/memory/lib/memory-cycle3.mjs +1 -1
- package/src/runtime/memory/lib/memory-recall-scope-filter.mjs +24 -0
- package/src/runtime/memory/lib/memory-retrievers.mjs +8 -0
- package/src/runtime/memory/lib/memory.mjs +121 -4
- package/src/runtime/memory/lib/pg/adapter.mjs +139 -15
- package/src/runtime/memory/lib/promotion-fingerprint.mjs +50 -0
- package/src/runtime/memory/lib/recall-format.mjs +183 -0
- package/src/runtime/memory/lib/session-ingest.mjs +107 -0
- package/src/runtime/memory/lib/trace-store.mjs +69 -22
- package/src/runtime/memory/tool-defs.mjs +10 -7
- package/src/runtime/shared/abort-controller.mjs +1 -1
- package/src/runtime/shared/background-tasks.mjs +2 -3
- package/src/runtime/shared/buffered-appender.mjs +149 -0
- package/src/runtime/shared/channel-notification-routing.mjs +12 -0
- package/src/runtime/shared/channel-notification-routing.test.mjs +45 -0
- package/src/runtime/shared/config.mjs +9 -0
- package/src/runtime/shared/llm/http-agent.mjs +12 -5
- package/src/runtime/shared/schedules-store.mjs +21 -19
- package/src/runtime/shared/task-notification-envelope.mjs +98 -0
- package/src/runtime/shared/task-notification-envelope.test.mjs +107 -0
- package/src/runtime/shared/tool-execution-contract.mjs +2 -2
- package/src/runtime/shared/tool-surface.mjs +98 -13
- package/src/runtime/shared/transcript-writer.mjs +156 -0
- package/src/runtime/shared/update-checker.mjs +214 -0
- package/src/session-runtime/config-helpers.mjs +209 -0
- package/src/session-runtime/effort.mjs +128 -0
- package/src/session-runtime/fs-utils.mjs +10 -0
- package/src/session-runtime/model-capabilities.mjs +130 -0
- package/src/session-runtime/output-styles.mjs +124 -0
- package/src/session-runtime/plugin-mcp.mjs +114 -0
- package/src/session-runtime/session-text.mjs +100 -0
- package/src/session-runtime/statusline-route.mjs +35 -0
- package/src/session-runtime/tool-catalog.mjs +720 -0
- package/src/session-runtime/workflow.mjs +358 -0
- package/src/standalone/agent-tool.mjs +302 -117
- package/src/standalone/channel-admin.mjs +133 -40
- package/src/standalone/channel-worker.mjs +10 -292
- package/src/standalone/explore-tool.mjs +12 -5
- package/src/standalone/hook-bus.mjs +165 -8
- package/src/standalone/memory-runtime-proxy.mjs +3 -1
- package/src/standalone/opencode-go-login.mjs +121 -0
- package/src/standalone/provider-admin.mjs +25 -3
- package/src/standalone/usage-dashboard.mjs +1 -1
- package/src/tui/App.jsx +2883 -778
- package/src/tui/components/ConfirmBar.jsx +47 -0
- package/src/tui/components/ContextPanel.jsx +5 -3
- package/src/tui/components/ItemRightHintOverprint.jsx +54 -0
- package/src/tui/components/Markdown.jsx +22 -98
- package/src/tui/components/Message.jsx +14 -35
- package/src/tui/components/Picker.jsx +87 -12
- package/src/tui/components/PromptInput.jsx +355 -22
- package/src/tui/components/QueuedCommands.jsx +1 -1
- package/src/tui/components/SlashCommandPalette.jsx +8 -5
- package/src/tui/components/Spinner.jsx +7 -7
- package/src/tui/components/StatusLine.jsx +40 -21
- package/src/tui/components/TextEntryPanel.jsx +51 -7
- package/src/tui/components/ToolExecution.jsx +183 -101
- package/src/tui/components/TurnDone.jsx +4 -4
- package/src/tui/components/UsagePanel.jsx +1 -1
- package/src/tui/components/tool-output-format.mjs +161 -23
- package/src/tui/components/tool-output-format.test.mjs +87 -0
- package/src/tui/display-width.mjs +69 -0
- package/src/tui/display-width.test.mjs +35 -0
- package/src/tui/dist/index.mjs +6731 -2333
- package/src/tui/engine/agent-envelope.mjs +296 -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/queue-helpers.mjs +161 -0
- package/src/tui/engine/session-stats.mjs +46 -0
- package/src/tui/engine/tool-call-fields.mjs +23 -0
- package/src/tui/engine/tool-result-text.mjs +126 -0
- package/src/tui/engine.mjs +569 -948
- package/src/tui/index.jsx +117 -7
- package/src/tui/input-editing.mjs +58 -8
- package/src/tui/input-editing.selection.test.mjs +75 -0
- package/src/tui/keyboard-protocol.mjs +42 -0
- package/src/tui/lib/voice-recorder.mjs +469 -0
- package/src/tui/markdown/format-token.mjs +128 -76
- package/src/tui/markdown/format-token.test.mjs +61 -19
- package/src/tui/markdown/measure-rendered-rows.mjs +85 -0
- package/src/tui/markdown/render-ansi.test.mjs +1 -1
- package/src/tui/markdown/streaming-markdown.mjs +167 -0
- package/src/tui/markdown/streaming-markdown.test.mjs +70 -0
- package/src/tui/markdown/table-layout.mjs +9 -9
- package/src/tui/paste-attachments.mjs +36 -9
- package/src/tui/paste-fix.test.mjs +119 -0
- package/src/tui/prompt-history-store.mjs +129 -0
- package/src/tui/prompt-history-store.test.mjs +52 -0
- package/src/tui/statusline-ansi-bridge.test.mjs +3 -3
- package/src/tui/theme.mjs +41 -657
- package/src/tui/themes/base.mjs +86 -0
- package/src/tui/themes/basic.mjs +85 -0
- package/src/tui/themes/catppuccin.mjs +72 -0
- package/src/tui/themes/dracula.mjs +70 -0
- package/src/tui/themes/everforest.mjs +71 -0
- package/src/tui/themes/gruvbox.mjs +71 -0
- package/src/tui/themes/index.mjs +71 -0
- package/src/tui/themes/indigo.mjs +78 -0
- package/src/tui/themes/kanagawa.mjs +80 -0
- package/src/tui/themes/light.mjs +81 -0
- package/src/tui/themes/nord.mjs +72 -0
- package/src/tui/themes/onedark.mjs +16 -0
- package/src/tui/themes/rosepine.mjs +70 -0
- package/src/tui/themes/teal.mjs +80 -0
- package/src/tui/themes/tokyonight.mjs +79 -0
- package/src/tui/themes/utils.mjs +106 -0
- package/src/tui/themes/warm.mjs +79 -0
- package/src/tui/transcript-tool-failures.mjs +13 -2
- package/src/ui/markdown.mjs +1 -1
- package/src/ui/model-display.mjs +2 -2
- package/src/ui/statusline.mjs +75 -27
- package/src/vendor/statusline/bin/statusline-route.mjs +5 -12
- package/src/vendor/statusline/src/gateway/claude-current.mjs +3 -3
- package/src/vendor/statusline/src/gateway/route-meta.mjs +30 -16
- package/src/workflows/default/WORKFLOW.md +46 -12
- package/src/workflows/sequential/WORKFLOW.md +51 -0
- package/src/workflows/solo/WORKFLOW.md +12 -1
- package/vendor/ink/build/display-width.js +62 -0
- package/vendor/ink/build/ink.js +100 -12
- package/vendor/ink/build/measure-text.js +4 -1
- package/vendor/ink/build/output.js +115 -9
- package/vendor/ink/build/render-node-to-output.js +4 -1
- package/vendor/ink/build/render.js +4 -0
- package/src/output-styles/extreme-simple.md +0 -20
- package/src/rules/lead/04-workflow.md +0 -51
- package/src/workflows/default/workflow.json +0 -13
- package/src/workflows/solo/workflow.json +0 -7
|
@@ -5,8 +5,15 @@
|
|
|
5
5
|
|
|
6
6
|
import { parseToolArgs } from '../runtime/shared/tool-surface.mjs';
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
// Anchor to the orchestrator's actual denial envelope:
|
|
9
|
+
// `Error: tool "<name>" denied by hook[: ...]`
|
|
10
|
+
// `Error: tool "<name>" denied by hook: approval required but no approval UI is available`
|
|
11
|
+
// Matching the bare phrase anywhere in the body produced FALSE POSITIVES when a
|
|
12
|
+
// normal (successful) tool result merely CONTAINED the text — e.g. a read/grep
|
|
13
|
+
// over this very file or the hook source. The denial is always an Error
|
|
14
|
+
// envelope emitted at the START of the result, so anchor on that prefix.
|
|
15
|
+
const HOOK_DENIAL_RE = /^Error:\s*tool\s*"[^"]*"\s*denied by hook\b/im;
|
|
16
|
+
const APPROVAL_UNAVAILABLE_RE = /denied by hook:\s*approval required but no approval UI is available/i;
|
|
10
17
|
|
|
11
18
|
export function toolItemResultText(item) {
|
|
12
19
|
if (!item) return '';
|
|
@@ -26,6 +33,10 @@ export function isHookApprovalDenialToolResult(text) {
|
|
|
26
33
|
|
|
27
34
|
export function isHookApprovalDenialToolItem(item) {
|
|
28
35
|
if (!item || item.kind !== 'tool') return false;
|
|
36
|
+
// A genuine hook denial is always surfaced as an ERROR result. Gating on
|
|
37
|
+
// isError stops a successful result whose body happens to contain the denial
|
|
38
|
+
// phrase (e.g. reading the hook source) from rendering a phantom "Denied".
|
|
39
|
+
if (!item.isError) return false;
|
|
29
40
|
return isHookApprovalDenialToolResult(toolItemResultText(item));
|
|
30
41
|
}
|
|
31
42
|
|
package/src/ui/markdown.mjs
CHANGED
|
@@ -137,7 +137,7 @@ function renderLine(line, width) {
|
|
|
137
137
|
// Blockquote (possibly nested).
|
|
138
138
|
const q = /^(\s*>+)\s?(.*)$/.exec(line);
|
|
139
139
|
if (q) {
|
|
140
|
-
return dim(
|
|
140
|
+
return dim('│ ') + italic(renderInline(q[2]));
|
|
141
141
|
}
|
|
142
142
|
|
|
143
143
|
// Bullet list.
|
package/src/ui/model-display.mjs
CHANGED
|
@@ -74,13 +74,13 @@ export function canonicalModelDisplay(model, provider) {
|
|
|
74
74
|
return `Grok ${grok[1].split('-').map(titleModelPart).filter(Boolean).join(' ')}`;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
const claudeLegacy = raw.match(/^claude-(\d+)(?:-(\d+))?-(opus|sonnet|haiku)(?:-|$)/i);
|
|
77
|
+
const claudeLegacy = raw.match(/^claude-(\d+)(?:-(\d+))?-(opus|sonnet|haiku|fable)(?:-|$)/i);
|
|
78
78
|
if (claudeLegacy) {
|
|
79
79
|
const version = `${claudeLegacy[1]}${claudeLegacy[2] ? `.${claudeLegacy[2]}` : ''}`;
|
|
80
80
|
return `Claude ${titleModelPart(claudeLegacy[3])} ${version}`;
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
const claude = raw.match(/^claude-(opus|sonnet|haiku)-(.+)$/i);
|
|
83
|
+
const claude = raw.match(/^claude-(opus|sonnet|haiku|fable)-(.+)$/i);
|
|
84
84
|
if (claude) {
|
|
85
85
|
return `Claude ${titleModelPart(claude[1])} ${claude[2].replace(/-/g, '.')}`;
|
|
86
86
|
}
|
package/src/ui/statusline.mjs
CHANGED
|
@@ -16,7 +16,7 @@ import { bold, colorEnabled, rgb } from './ansi.mjs';
|
|
|
16
16
|
import { displayModelName, shortenModelName } from './model-display.mjs';
|
|
17
17
|
import { createSessionStats } from './session-stats.mjs';
|
|
18
18
|
import { forEachSessionRuntime } from '../runtime/agent/orchestrator/session/manager.mjs';
|
|
19
|
-
import {
|
|
19
|
+
import { listHiddenAgentNames } from '../runtime/agent/orchestrator/internal-agents.mjs';
|
|
20
20
|
import { getModelMetadataSync } from '../runtime/agent/orchestrator/providers/model-catalog.mjs';
|
|
21
21
|
import { readCachedOAuthUsageSnapshot } from '../runtime/agent/orchestrator/providers/oauth-usage.mjs';
|
|
22
22
|
import { readCachedOpenCodeGoUsageSnapshot } from '../runtime/agent/orchestrator/providers/opencode-go-usage.mjs';
|
|
@@ -61,11 +61,11 @@ const L2_SPINNER_FRAME_MS = 120;
|
|
|
61
61
|
// replaces them. Snapshots from a previous launch stay hidden during boot so the
|
|
62
62
|
// statusline starts empty until the current session captures usage once.
|
|
63
63
|
const STATUSLINE_PROCESS_STARTED_AT_MS = Date.now() - Math.floor((Number(process.uptime?.()) || 0) * 1000);
|
|
64
|
-
const
|
|
64
|
+
const DEFAULT_HIDDEN_STATUSLINE_AGENTS = Object.freeze(['explorer', 'cycle1-agent', 'cycle2-agent', 'cycle3-agent', 'scheduler-task', 'webhook-handler']);
|
|
65
65
|
let _shellJobsSegmentCache = { ownerPid: 0, at: 0, value: { count: 0, elapsedLabel: '' } };
|
|
66
66
|
let _gatewayQuotaStatusCache = { key: '', at: 0, value: null };
|
|
67
67
|
let _fallbackQuotaStatusCache = { key: '', at: 0, value: null };
|
|
68
|
-
let
|
|
68
|
+
let _hiddenStatuslineAgents = null;
|
|
69
69
|
// Option A boot gate: the L1 usage/quota segment stays fully empty until THIS
|
|
70
70
|
// process has captured its FIRST confirmed (current-process) OAuth usage
|
|
71
71
|
// snapshot for THAT provider. The latch is monotonic PER PROVIDER — once a
|
|
@@ -211,7 +211,7 @@ function resolveContextUsedPct({
|
|
|
211
211
|
}
|
|
212
212
|
|
|
213
213
|
function normalizeAgentWorkerForStatusline(worker = {}) {
|
|
214
|
-
const tag = String(worker.tag || worker.
|
|
214
|
+
const tag = String(worker.tag || worker.agent || worker.name || '').trim();
|
|
215
215
|
if (!tag) return null;
|
|
216
216
|
const statusText = String(worker.stage || worker.status || '').toLowerCase();
|
|
217
217
|
const status = isTerminalBridgeStatus(statusText) ? 'idle' : 'running';
|
|
@@ -219,7 +219,7 @@ function normalizeAgentWorkerForStatusline(worker = {}) {
|
|
|
219
219
|
tag,
|
|
220
220
|
status,
|
|
221
221
|
startedAtMs: timeMs(worker.startedAt || worker.startTime || worker.createdAt),
|
|
222
|
-
|
|
222
|
+
agent: worker.agent || null,
|
|
223
223
|
stage: worker.stage || worker.status || null,
|
|
224
224
|
sessionId: worker.sessionId || null,
|
|
225
225
|
provider: worker.provider || null,
|
|
@@ -231,7 +231,7 @@ function normalizeAgentJobForStatusline(job = {}) {
|
|
|
231
231
|
const statusText = String(job.status || job.stage || '').toLowerCase();
|
|
232
232
|
if (!statusText) return null;
|
|
233
233
|
const taskId = String(job.task_id || job.taskId || '').trim();
|
|
234
|
-
const tag = String(job.tag || job.
|
|
234
|
+
const tag = String(job.tag || job.agent || job.type || taskId || '').trim();
|
|
235
235
|
if (!tag && !taskId) return null;
|
|
236
236
|
const startedAtMs = timeMs(job.startedAt);
|
|
237
237
|
const finishedAtMs = timeMs(job.finishedAt);
|
|
@@ -243,7 +243,7 @@ function normalizeAgentJobForStatusline(job = {}) {
|
|
|
243
243
|
finalStatus: statusText,
|
|
244
244
|
startedAtMs,
|
|
245
245
|
finishedAtMs,
|
|
246
|
-
|
|
246
|
+
agent: job.agent || null,
|
|
247
247
|
stage: job.stage || job.workerStatus || job.status || null,
|
|
248
248
|
sessionId: job.sessionId || null,
|
|
249
249
|
provider: job.provider || null,
|
|
@@ -256,7 +256,7 @@ function normalizeAgentJobForStatusline(job = {}) {
|
|
|
256
256
|
taskId,
|
|
257
257
|
status: 'running',
|
|
258
258
|
startedAtMs,
|
|
259
|
-
|
|
259
|
+
agent: job.agent || null,
|
|
260
260
|
stage: job.stage || job.workerStatus || job.status || null,
|
|
261
261
|
sessionId: job.sessionId || null,
|
|
262
262
|
provider: job.provider || null,
|
|
@@ -387,10 +387,9 @@ function renderNativeStatusline({
|
|
|
387
387
|
|
|
388
388
|
const agentPayload = agentStatuslinePayload([
|
|
389
389
|
...(Array.isArray(agentWorkers) ? agentWorkers : []),
|
|
390
|
-
...
|
|
390
|
+
...activeHiddenAgentWorkers({ sessionId, clientHostPid }),
|
|
391
391
|
], agentJobs);
|
|
392
|
-
const {
|
|
393
|
-
if (maintenance.length) addL1(maintenance.join(' '));
|
|
392
|
+
const { runningWorkers } = classifyAgentWorkers(agentPayload.workers);
|
|
394
393
|
const shellStatus = shellJobsStatus({ clientHostPid });
|
|
395
394
|
|
|
396
395
|
const spinnerNow = Date.now();
|
|
@@ -426,6 +425,16 @@ function renderNativeStatusline({
|
|
|
426
425
|
const label = `Running ${n} Shell${n === 1 ? '' : 's'}`;
|
|
427
426
|
addL2(`${spin} ${B}${label}${R}${elapsedSuffix(shellStatus.elapsedLabel)}`);
|
|
428
427
|
}
|
|
428
|
+
// Memory cycle segment — single unified "Memory" wording for all states:
|
|
429
|
+
// running -> "⠋ Memory · 12s"; backlog warning -> "⠋ Memory · backlog 512"
|
|
430
|
+
// (yellow). Nothing when idle (no L2 pollution).
|
|
431
|
+
const memStatus = memoryCycleStatus();
|
|
432
|
+
if (memStatus?.kind === 'running') {
|
|
433
|
+
const elapsed = formatElapsed(Date.now() - memStatus.startedAt);
|
|
434
|
+
addL2(`${spin} ${B}Memory${R}${elapsedSuffix(elapsed)}`);
|
|
435
|
+
} else if (memStatus?.kind === 'backlog') {
|
|
436
|
+
addL2(`${spin} ${B}Memory${R} ${D}·${R} ${YLW}backlog ${memStatus.pending}${R}`);
|
|
437
|
+
}
|
|
429
438
|
const l1 = l1Parts.join(sep) || 'mixdog';
|
|
430
439
|
const l2 = l2Parts.join(sep);
|
|
431
440
|
return l2 ? `${l1}\n${l2}` : l1;
|
|
@@ -688,30 +697,30 @@ function classifyAgentWorkers(workers = []) {
|
|
|
688
697
|
}
|
|
689
698
|
|
|
690
699
|
function hiddenWorkerLabel(worker = {}) {
|
|
691
|
-
const
|
|
700
|
+
const agent = String(worker?.agent || '').trim();
|
|
692
701
|
const tag = String(worker?.tag || '').trim();
|
|
693
|
-
return maintenanceLabel(
|
|
702
|
+
return maintenanceLabel(agent) || (!agent ? maintenanceLabel(tag) : '');
|
|
694
703
|
}
|
|
695
704
|
|
|
696
|
-
function
|
|
697
|
-
if (
|
|
698
|
-
const
|
|
705
|
+
function hiddenStatuslineAgents() {
|
|
706
|
+
if (_hiddenStatuslineAgents) return _hiddenStatuslineAgents;
|
|
707
|
+
const agents = new Set(DEFAULT_HIDDEN_STATUSLINE_AGENTS);
|
|
699
708
|
try {
|
|
700
|
-
for (const
|
|
701
|
-
const clean = String(
|
|
702
|
-
if (clean)
|
|
709
|
+
for (const agent of listHiddenAgentNames()) {
|
|
710
|
+
const clean = String(agent || '').trim();
|
|
711
|
+
if (clean) agents.add(clean);
|
|
703
712
|
}
|
|
704
713
|
} catch {}
|
|
705
|
-
|
|
706
|
-
return
|
|
714
|
+
_hiddenStatuslineAgents = agents;
|
|
715
|
+
return agents;
|
|
707
716
|
}
|
|
708
717
|
|
|
709
718
|
function isActiveHiddenStatus(statusText) {
|
|
710
719
|
return /^(connecting|requesting|streaming|tool_running|running)$/i.test(String(statusText || '').trim());
|
|
711
720
|
}
|
|
712
721
|
|
|
713
|
-
function
|
|
714
|
-
const
|
|
722
|
+
function activeHiddenAgentWorkers({ sessionId = '', clientHostPid = 0 } = {}) {
|
|
723
|
+
const agents = hiddenStatuslineAgents();
|
|
715
724
|
const ownerPid = positiveInt(clientHostPid);
|
|
716
725
|
const ownerSessionId = String(sessionId || '').trim();
|
|
717
726
|
const rows = [];
|
|
@@ -720,8 +729,8 @@ function activeHiddenRoleWorkers({ sessionId = '', clientHostPid = 0 } = {}) {
|
|
|
720
729
|
if (!entry || entry.closed === true) continue;
|
|
721
730
|
const session = entry.session || null;
|
|
722
731
|
if (!session || session.closed === true) continue;
|
|
723
|
-
const
|
|
724
|
-
if (!
|
|
732
|
+
const agent = String(session?.agent || '').trim();
|
|
733
|
+
if (!agent || !agents.has(agent)) continue;
|
|
725
734
|
const id = session?.id || runtimeSessionId || null;
|
|
726
735
|
if (ownerSessionId && id === ownerSessionId) continue;
|
|
727
736
|
const sessionOwnerId = String(session?.ownerSessionId || '').trim();
|
|
@@ -732,8 +741,8 @@ function activeHiddenRoleWorkers({ sessionId = '', clientHostPid = 0 } = {}) {
|
|
|
732
741
|
const status = String(session?.status || stage || '').trim().toLowerCase();
|
|
733
742
|
if (!isActiveHiddenStatus(stage || status)) continue;
|
|
734
743
|
rows.push({
|
|
735
|
-
tag: String(session?.agentTag || `${
|
|
736
|
-
|
|
744
|
+
tag: String(session?.agentTag || `${agent}:${id || rows.length}`).trim(),
|
|
745
|
+
agent,
|
|
737
746
|
status: 'running',
|
|
738
747
|
stage: stage || status || 'running',
|
|
739
748
|
sessionId: id,
|
|
@@ -768,6 +777,45 @@ function maintenanceLabel(tag) {
|
|
|
768
777
|
}
|
|
769
778
|
|
|
770
779
|
function shellJobsStatus({ clientHostPid } = {}) {
|
|
780
|
+
return _shellJobsStatusImpl({ clientHostPid });
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
// Memory cycle L2 segment source. The memory daemon writes
|
|
784
|
+
// data/memory-cycle-state.json on every cycle start/finish (index.mjs
|
|
785
|
+
// _writeCycleStateFile) — no HTTP call from the statusline path. Cached at
|
|
786
|
+
// the same 1s cadence as the shell segment. Shows a single unified "Memory"
|
|
787
|
+
// segment: running (spinner + elapsed) or backlog warning (yellow count).
|
|
788
|
+
let _memoryCycleSegmentCache = { at: 0, value: null };
|
|
789
|
+
const MEMORY_CYCLE_SEGMENT_CACHE_MS = 1000;
|
|
790
|
+
const MEMORY_CYCLE_BACKLOG_WARN = 500;
|
|
791
|
+
function memoryCycleStatus() {
|
|
792
|
+
const now = Date.now();
|
|
793
|
+
if (now - _memoryCycleSegmentCache.at < MEMORY_CYCLE_SEGMENT_CACHE_MS) {
|
|
794
|
+
return _memoryCycleSegmentCache.value;
|
|
795
|
+
}
|
|
796
|
+
let value = null;
|
|
797
|
+
try {
|
|
798
|
+
const p = join(dataDir(), 'memory-cycle-state.json');
|
|
799
|
+
if (existsSync(p)) {
|
|
800
|
+
const state = JSON.parse(readFileSync(p, 'utf-8'));
|
|
801
|
+
const running = state?.running || null;
|
|
802
|
+
const backlog = state?.backlog || {};
|
|
803
|
+
// Stale-file guard: a daemon that died mid-run leaves running set —
|
|
804
|
+
// ignore anything not refreshed in the last 10 minutes.
|
|
805
|
+
const fresh = Number(state?.updatedAt) > now - 10 * 60_000;
|
|
806
|
+
if (fresh && running?.cycle && Number(running.started_at) > 0) {
|
|
807
|
+
value = { kind: 'running', startedAt: Number(running.started_at) };
|
|
808
|
+
} else if (fresh) {
|
|
809
|
+
const pending = Math.max(Number(backlog?.unchunked) || 0, Number(backlog?.cycle2_pending) || 0);
|
|
810
|
+
if (pending > MEMORY_CYCLE_BACKLOG_WARN) value = { kind: 'backlog', pending };
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
} catch { value = null; }
|
|
814
|
+
_memoryCycleSegmentCache = { at: now, value };
|
|
815
|
+
return value;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
function _shellJobsStatusImpl({ clientHostPid } = {}) {
|
|
771
819
|
const ownerPid = positiveInt(clientHostPid);
|
|
772
820
|
const empty = { count: 0, elapsedLabel: '' };
|
|
773
821
|
if (!ownerPid) return empty;
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
readLatestGatewayHostRoute,
|
|
12
12
|
readGatewaySessionRoute,
|
|
13
13
|
} from '../src/gateway/session-routes.mjs';
|
|
14
|
+
import { compactBoundaryDenominator } from '../src/gateway/route-meta.mjs';
|
|
14
15
|
|
|
15
16
|
function positiveInt(value) {
|
|
16
17
|
const n = parseInt(String(value || ''), 10);
|
|
@@ -278,16 +279,8 @@ function resolveStatusAutoCompactTokenLimit(configured, active = {}, lastCompact
|
|
|
278
279
|
export const _resolveStatusAutoCompactTokenLimit = resolveStatusAutoCompactTokenLimit;
|
|
279
280
|
|
|
280
281
|
export function compactBoundaryForStatus(routeInfo = {}, compact = null) {
|
|
281
|
-
const
|
|
282
|
-
|
|
283
|
-
const budgetWindow = num(compact?.budgetWindow, 0);
|
|
284
|
-
const rawContextWindow = num(routeInfo?.rawContextWindow ?? compact?.rawContextWindow, 0);
|
|
285
|
-
if (compactLimit > 0 && contextWindow > 0) return Math.min(compactLimit, contextWindow);
|
|
286
|
-
if (compactLimit > 0) return compactLimit;
|
|
287
|
-
if (budgetWindow > 0 && contextWindow > 0) return Math.min(budgetWindow, contextWindow);
|
|
288
|
-
if (budgetWindow > 0) return budgetWindow;
|
|
289
|
-
if (contextWindow > 0) return contextWindow;
|
|
290
|
-
return rawContextWindow > 0 ? rawContextWindow : null;
|
|
282
|
+
const n = compactBoundaryDenominator(routeInfo, compact);
|
|
283
|
+
return n > 0 ? n : null;
|
|
291
284
|
}
|
|
292
285
|
|
|
293
286
|
function sessionIdFromTranscriptPath(transcriptPath) {
|
|
@@ -378,8 +371,8 @@ function displayForModel(provider, model, info) {
|
|
|
378
371
|
const display = cleanString(info?.display) || cleanString(info?.displayName) || cleanString(info?.name);
|
|
379
372
|
if (display) return display;
|
|
380
373
|
if (provider === 'anthropic-oauth') {
|
|
381
|
-
const m = String(model || '').match(/^claude-(opus|sonnet|haiku)-(\d+)
|
|
382
|
-
if (m) return `${m[1][0].toUpperCase()}${m[1].slice(1).toLowerCase()} ${m[2]}
|
|
374
|
+
const m = String(model || '').match(/^claude-(opus|sonnet|haiku|fable)-(\d+)(?:-(\d+))?/i);
|
|
375
|
+
if (m) return `${m[1][0].toUpperCase()}${m[1].slice(1).toLowerCase()} ${m[2]}${m[3] ? `.${m[3]}` : ''}`;
|
|
383
376
|
}
|
|
384
377
|
const raw = cleanString(model);
|
|
385
378
|
const gpt = raw.match(/^gpt[-_](.+)$/i);
|
|
@@ -119,7 +119,7 @@ export function resolveClaudeModelAlias(model) {
|
|
|
119
119
|
if (!raw) return null;
|
|
120
120
|
const stripped = stripClaudeContextSuffix(raw);
|
|
121
121
|
if (/^claude-/i.test(stripped)) return stripped;
|
|
122
|
-
const family = stripped.match(/^(opus|sonnet|haiku)(?:[-_].*)?$/i)?.[1]?.toLowerCase();
|
|
122
|
+
const family = stripped.match(/^(opus|sonnet|haiku|fable)(?:[-_].*)?$/i)?.[1]?.toLowerCase();
|
|
123
123
|
if (family) return familyDefaultModel(family);
|
|
124
124
|
return null;
|
|
125
125
|
}
|
|
@@ -128,11 +128,11 @@ export function displayClaudeModel(model, raw = '', display = '') {
|
|
|
128
128
|
const explicit = cleanString(display);
|
|
129
129
|
if (explicit) return explicit;
|
|
130
130
|
const id = cleanString(model) || resolveClaudeModelAlias(raw) || cleanString(raw);
|
|
131
|
-
const m = id.match(/^claude-(opus|sonnet|haiku)-(\d+)
|
|
131
|
+
const m = id.match(/^claude-(opus|sonnet|haiku|fable)-(\d+)(?:-(\d+))?(?:-\d{8})?$/i);
|
|
132
132
|
if (m) {
|
|
133
133
|
const family = `${m[1][0].toUpperCase()}${m[1].slice(1).toLowerCase()}`;
|
|
134
134
|
const suffix = /\[1m\]/i.test(raw) || contextWindowFromRawModel(raw, id) === 1000000 ? ' (1M context)' : '';
|
|
135
|
-
return `${family} ${m[2]}
|
|
135
|
+
return `${family} ${m[2]}${m[3] ? `.${m[3]}` : ''}${suffix}`;
|
|
136
136
|
}
|
|
137
137
|
return id || raw || '';
|
|
138
138
|
}
|
|
@@ -254,8 +254,8 @@ function displayForModel(provider, model, info) {
|
|
|
254
254
|
const display = cleanString(info?.display) || cleanString(info?.displayName) || cleanString(info?.name);
|
|
255
255
|
if (display) return display;
|
|
256
256
|
if (provider === 'anthropic-oauth') {
|
|
257
|
-
const m = String(model || '').match(/^claude-(opus|sonnet|haiku)-(\d+)
|
|
258
|
-
if (m) return `${m[1][0].toUpperCase()}${m[1].slice(1).toLowerCase()} ${m[2]}
|
|
257
|
+
const m = String(model || '').match(/^claude-(opus|sonnet|haiku|fable)-(\d+)(?:-(\d+))?/i);
|
|
258
|
+
if (m) return `${m[1][0].toUpperCase()}${m[1].slice(1).toLowerCase()} ${m[2]}${m[3] ? `.${m[3]}` : ''}`;
|
|
259
259
|
}
|
|
260
260
|
return model || '';
|
|
261
261
|
}
|
|
@@ -343,25 +343,44 @@ export function readGatewayRouteInfo(seed = {}, providerObj = null) {
|
|
|
343
343
|
};
|
|
344
344
|
}
|
|
345
345
|
|
|
346
|
-
|
|
347
|
-
|
|
346
|
+
// Boundary denominator for status %, overflow checks, and gateway env window.
|
|
347
|
+
// Order: explicit boundary (routeInfo or compact) → contextWindow → budgetWindow
|
|
348
|
+
// → rawContextWindow. autoCompactTokenLimit / compactLimitTokens are triggers
|
|
349
|
+
// only and are never read here.
|
|
350
|
+
export function compactBoundaryDenominator(routeInfo = {}, compact = null) {
|
|
351
|
+
const fromRoute = num(
|
|
352
|
+
routeInfo?.compactBoundaryTokens
|
|
353
|
+
?? routeInfo?.compact_boundary_tokens
|
|
354
|
+
?? routeInfo?.boundaryTokens,
|
|
355
|
+
0,
|
|
356
|
+
);
|
|
357
|
+
const fromCompact = num(
|
|
358
|
+
compact?.boundaryTokens
|
|
359
|
+
?? compact?.compactBoundaryTokens
|
|
360
|
+
?? compact?.compact_boundary_tokens,
|
|
361
|
+
0,
|
|
362
|
+
);
|
|
363
|
+
const boundaryTokens = fromRoute > 0 ? fromRoute : fromCompact;
|
|
348
364
|
const contextWindow = num(routeInfo?.contextWindow ?? compact?.contextWindow, 0);
|
|
349
365
|
const budgetWindow = num(compact?.budgetWindow, 0);
|
|
350
366
|
const rawContextWindow = num(routeInfo?.rawContextWindow ?? compact?.rawContextWindow, 0);
|
|
351
|
-
if (
|
|
352
|
-
if (compactLimit > 0) return compactLimit;
|
|
353
|
-
if (budgetWindow > 0 && contextWindow > 0) return Math.min(budgetWindow, contextWindow);
|
|
354
|
-
if (budgetWindow > 0) return budgetWindow;
|
|
367
|
+
if (boundaryTokens > 0) return boundaryTokens;
|
|
355
368
|
if (contextWindow > 0) return contextWindow;
|
|
369
|
+
if (budgetWindow > 0) return budgetWindow;
|
|
356
370
|
return rawContextWindow > 0 ? rawContextWindow : 0;
|
|
357
371
|
}
|
|
358
372
|
|
|
373
|
+
function compactBoundaryForRoute(routeInfo = {}, compact = null) {
|
|
374
|
+
return compactBoundaryDenominator(routeInfo, compact);
|
|
375
|
+
}
|
|
376
|
+
|
|
359
377
|
// Single source of truth for the value synced to host env
|
|
360
378
|
// CLAUDE_CODE_AUTO_COMPACT_WINDOW. BOTH the --enable-time write
|
|
361
379
|
// (scripts/gateway-model.mjs) and the runtime sync (src/gateway/server.mjs)
|
|
362
380
|
// must derive the window the SAME way, or they disagree on the value written to
|
|
363
|
-
// settings.json.
|
|
364
|
-
//
|
|
381
|
+
// settings.json. Denominator order: compactBoundaryTokens / boundaryTokens (route
|
|
382
|
+
// or compact) → contextWindow → budgetWindow → rawContextWindow. Never
|
|
383
|
+
// autoCompactTokenLimit or compactLimitTokens (trigger-only). Returns a positive
|
|
365
384
|
// integer, or null when unknown.
|
|
366
385
|
export function autoCompactWindowForRoute(routeInfo) {
|
|
367
386
|
const n = compactBoundaryForRoute(routeInfo);
|
|
@@ -428,12 +447,7 @@ function usageCostUsd(routeInfo, usage) {
|
|
|
428
447
|
}
|
|
429
448
|
|
|
430
449
|
function contextUsageBoundary(routeInfo, compact = null) {
|
|
431
|
-
|
|
432
|
-
const budgetWindow = num(compact?.budgetWindow, 0);
|
|
433
|
-
const rawContextWindow = num(routeInfo?.rawContextWindow ?? compact?.rawContextWindow, 0);
|
|
434
|
-
if (contextWindow > 0) return contextWindow;
|
|
435
|
-
if (budgetWindow > 0) return budgetWindow;
|
|
436
|
-
return rawContextWindow > 0 ? rawContextWindow : compactBoundaryForRoute(routeInfo, compact);
|
|
450
|
+
return compactBoundaryDenominator(routeInfo, compact);
|
|
437
451
|
}
|
|
438
452
|
|
|
439
453
|
export function summarizeGatewayUsage(routeInfo, providerOut, compact = null, durationMs = null) {
|
|
@@ -1,14 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: default
|
|
3
|
+
name: Default
|
|
4
|
+
description: "Default agent workflow — fan-out parallel delegation across independent scopes."
|
|
5
|
+
agents: worker, heavy-worker, reviewer, debugger, maintainer
|
|
6
|
+
---
|
|
7
|
+
|
|
1
8
|
# Default Workflow
|
|
2
9
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
Lead supervises: delegates, coordinates, judges, decides. Route by complexity:
|
|
11
|
+
- Lead handles directly: simple 1–2 step work, plus coordination, pre-planning,
|
|
12
|
+
config changes, and final git deployment.
|
|
13
|
+
- Worker: implementation that takes several steps.
|
|
14
|
+
- Heavy Worker: high-complexity, multi-step implementation.
|
|
15
|
+
- Reviewer: verify implementation scopes (diff, regressions, missing checks).
|
|
16
|
+
- Debugger: deploy for very high complexity, or when root-causing has already
|
|
17
|
+
failed at least once.
|
|
18
|
+
|
|
19
|
+
1. Plan — discuss the request with the user, form a plan, and wait for approval.
|
|
20
|
+
2. Delegate — split into the maximum number of independent scopes.
|
|
21
|
+
- PARALLEL across independent scopes by default (implementation, analysis,
|
|
22
|
+
review, debugging split alike). Spawn every scope in the SAME turn. Shared
|
|
23
|
+
or cross-cutting code does NOT justify merging: split per path and verify
|
|
24
|
+
the shared parts yourself. The only single scope is a genuinely
|
|
25
|
+
inseparable dependency — then state it.
|
|
26
|
+
- SEQUENTIAL within a single complex scope — split it into ordered steps
|
|
27
|
+
rather than handing it off in one shot, with a build/test-green gate
|
|
28
|
+
between steps.
|
|
29
|
+
- Write briefs per the lead-tool brief contract (token-optimized labeled
|
|
30
|
+
fragments).
|
|
31
|
+
- After spawning async agent(s), END THE TURN — do not poll, guess, or start
|
|
32
|
+
dependent work until the completion notification resumes you. Then wait
|
|
33
|
+
and continue automatically.
|
|
34
|
+
3. Review — pair one reviewer 1:1 with each implementation scope, spawned in the
|
|
35
|
+
same turn; never defer or batch the reviewer call — wait for its result.
|
|
36
|
+
Fact-check the agent response and cross-check implementation and review
|
|
37
|
+
results yourself before acting on them. Send fixes back to the original
|
|
38
|
+
scope and loop verify -> fix -> re-verify until clean. Skip review only for
|
|
39
|
+
simple, low-risk tasks. If the user asks for debugging, or a bug survives
|
|
40
|
+
2+ fix cycles, have the debugger investigate first instead of another fix
|
|
41
|
+
round.
|
|
42
|
+
4. Report — deliver the final report: synthesize results (outcome + key
|
|
43
|
+
evidence; never forward raw agent output), state the final state, and ask the
|
|
44
|
+
user whether to ship/deploy when relevant. Only after user feedback with no
|
|
45
|
+
issues prepare deploy/build/commit.
|
|
46
|
+
|
|
47
|
+
On any major change or direction shift mid-work, pause and re-consult the user
|
|
48
|
+
before continuing.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: sequential
|
|
3
|
+
name: Sequential
|
|
4
|
+
description: "Sequential workflow — delegates 1:1 with no fan-out; one agent at a time."
|
|
5
|
+
agents: worker, heavy-worker, reviewer, debugger, maintainer
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Sequential Workflow
|
|
9
|
+
|
|
10
|
+
Unlike Default, which fans out independent scopes in parallel, this mode runs
|
|
11
|
+
with no fan-out: it delegates one scope at a time, 1:1, and only moves to the
|
|
12
|
+
next after the current one completes.
|
|
13
|
+
|
|
14
|
+
Lead supervises: delegates, coordinates, judges, decides. Route by complexity:
|
|
15
|
+
- Lead handles directly: simple 1–2 step work, plus coordination, pre-planning,
|
|
16
|
+
config changes, and final git deployment.
|
|
17
|
+
- Worker: implementation that takes several steps.
|
|
18
|
+
- Heavy Worker: high-complexity, multi-step implementation.
|
|
19
|
+
- Reviewer: verify implementation scopes (diff, regressions, missing checks).
|
|
20
|
+
- Debugger: deploy for very high complexity, or when root-causing has already
|
|
21
|
+
failed at least once.
|
|
22
|
+
|
|
23
|
+
1. Plan — discuss the request with the user, form a plan, and wait for approval.
|
|
24
|
+
2. Delegate — split into ordered scopes and hand them off ONE AT A TIME.
|
|
25
|
+
- NO PARALLEL, NO FAN-OUT. Even when scopes are independent, spawn exactly
|
|
26
|
+
one agent per turn; never spawn multiple agents in the same turn. Wait for
|
|
27
|
+
the current scope's completion notification before spawning the next scope
|
|
28
|
+
(1:1 sequential).
|
|
29
|
+
- SEQUENTIAL within a single complex scope — split it into ordered steps
|
|
30
|
+
rather than handing it off in one shot, with a build/test-green gate
|
|
31
|
+
between steps.
|
|
32
|
+
- Write briefs per the lead-tool brief contract (token-optimized labeled
|
|
33
|
+
fragments).
|
|
34
|
+
- After spawning an async agent, END THE TURN — do not poll, guess, or start
|
|
35
|
+
dependent or subsequent work until the completion notification resumes
|
|
36
|
+
you. Then wait and continue automatically.
|
|
37
|
+
3. Review — after each implementation scope completes, pair one reviewer 1:1
|
|
38
|
+
with that scope (spawned on its own turn, not batched); never defer the
|
|
39
|
+
reviewer call — wait for its result. Fact-check the agent response and
|
|
40
|
+
cross-check implementation and review results yourself before acting on
|
|
41
|
+
them. Send fixes back to the original scope and loop verify -> fix ->
|
|
42
|
+
re-verify until clean. Skip review only for simple, low-risk tasks. If the
|
|
43
|
+
user asks for debugging, or a bug survives 2+ fix cycles, have the debugger
|
|
44
|
+
investigate first instead of another fix round.
|
|
45
|
+
4. Report — deliver the final report: synthesize results (outcome + key
|
|
46
|
+
evidence; never forward raw agent output), state the final state, and ask the
|
|
47
|
+
user whether to ship/deploy when relevant. Only after user feedback with no
|
|
48
|
+
issues prepare deploy/build/commit.
|
|
49
|
+
|
|
50
|
+
On any major change or direction shift mid-work, pause and re-consult the user
|
|
51
|
+
before continuing.
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: solo
|
|
3
|
+
name: Solo
|
|
4
|
+
description: "Solo workflow — Lead handles everything directly; delegation forbidden."
|
|
5
|
+
agents:
|
|
6
|
+
---
|
|
7
|
+
|
|
1
8
|
# Solo Workflow
|
|
2
9
|
|
|
3
10
|
1. Plan — Lead discusses the request with the user, forms a plan, and waits for
|
|
@@ -7,7 +14,11 @@
|
|
|
7
14
|
3. Verify — Lead checks the result directly, fixes issues directly, and repeats
|
|
8
15
|
until the work is clean or a blocker must be reported.
|
|
9
16
|
4. Report — Lead summarizes the final state, verification result, and any
|
|
10
|
-
remaining risk or requested next step.
|
|
17
|
+
remaining risk or requested next step. Only after user feedback with no
|
|
18
|
+
issues prepare deploy/build/commit.
|
|
19
|
+
|
|
20
|
+
On any major change or direction shift mid-work, pause and re-consult the user
|
|
21
|
+
before continuing.
|
|
11
22
|
|
|
12
23
|
Delegation rule:
|
|
13
24
|
- Do not delegate, spawn, send, or ask any agent to perform work.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* display-width.js — [mixdog fork] vendored copy of the shared display-width
|
|
3
|
+
* policy from src/tui/display-width.mjs.
|
|
4
|
+
*
|
|
5
|
+
* MUST STAY IN SYNC with src/tui/display-width.mjs. ink is aliased as an
|
|
6
|
+
* external bundle (see scripts/build-tui.mjs), so it cannot cleanly import from
|
|
7
|
+
* src; the small policy is replicated here verbatim instead. If the problem
|
|
8
|
+
* ranges or the WT_SESSION/MIXDOG_TUI_AMBIGUOUS_WIDE gate change there, change
|
|
9
|
+
* them here too — ink's MEASUREMENT must agree with OUR wrap/row math or the
|
|
10
|
+
* overlap gets worse, not better.
|
|
11
|
+
*
|
|
12
|
+
* Policy: widen ONLY U+2460–U+24FF (enclosed alphanumerics / circled digits)
|
|
13
|
+
* and U+2190–U+21FF (arrows) to 2 cells when ON. NEVER widen box-drawing
|
|
14
|
+
* (U+2500–U+257F), block elements, or other ambiguous glyphs. ON by default
|
|
15
|
+
* only under Windows Terminal (WT_SESSION); MIXDOG_TUI_AMBIGUOUS_WIDE='1'/'0'
|
|
16
|
+
* overrides and wins. OFF ⇒ identical to plain string-width.
|
|
17
|
+
*/
|
|
18
|
+
import stringWidth from 'string-width';
|
|
19
|
+
|
|
20
|
+
function isProblemCodePoint(cp) {
|
|
21
|
+
return (cp >= 0x2460 && cp <= 0x24ff) || (cp >= 0x2190 && cp <= 0x21ff);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function resolveAmbiguousWidePolicy(env = process.env) {
|
|
25
|
+
const override = env?.MIXDOG_TUI_AMBIGUOUS_WIDE;
|
|
26
|
+
if (override === '1')
|
|
27
|
+
return true;
|
|
28
|
+
if (override === '0')
|
|
29
|
+
return false;
|
|
30
|
+
return Boolean(env?.WT_SESSION);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Resolved once at module load (matches src/tui/display-width.mjs).
|
|
34
|
+
export const AMBIGUOUS_WIDE = resolveAmbiguousWidePolicy();
|
|
35
|
+
|
|
36
|
+
export function displayWidthWith(str, wide) {
|
|
37
|
+
const s = String(str ?? '');
|
|
38
|
+
const base = stringWidth(s);
|
|
39
|
+
if (!wide)
|
|
40
|
+
return base;
|
|
41
|
+
let extra = 0;
|
|
42
|
+
for (const ch of s) {
|
|
43
|
+
const cp = ch.codePointAt(0);
|
|
44
|
+
if (isProblemCodePoint(cp) && stringWidth(ch) === 1)
|
|
45
|
+
extra += 1;
|
|
46
|
+
}
|
|
47
|
+
return base + extra;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Visible display width under the resolved policy (ink-side stringWidth). */
|
|
51
|
+
export function displayStringWidth(str) {
|
|
52
|
+
return displayWidthWith(str, AMBIGUOUS_WIDE);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** widest-line equivalent under the policy. */
|
|
56
|
+
export function displayWidestLine(text) {
|
|
57
|
+
let lineWidth = 0;
|
|
58
|
+
for (const line of String(text ?? '').split('\n')) {
|
|
59
|
+
lineWidth = Math.max(lineWidth, displayStringWidth(line));
|
|
60
|
+
}
|
|
61
|
+
return lineWidth;
|
|
62
|
+
}
|