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.
Files changed (301) hide show
  1. package/package.json +9 -1
  2. package/scripts/_bench-cwc.json +20 -0
  3. package/scripts/agent-loop-policy-test.mjs +37 -0
  4. package/scripts/agent-parallel-smoke.mjs +54 -10
  5. package/scripts/anthropic-maxtokens-test.mjs +119 -0
  6. package/scripts/background-task-meta-smoke.mjs +1 -1
  7. package/scripts/bench-run.mjs +262 -0
  8. package/scripts/build-tui.mjs +13 -1
  9. package/scripts/compact-smoke.mjs +12 -0
  10. package/scripts/compact-trigger-migration-smoke.mjs +67 -1
  11. package/scripts/explore-bench.mjs +124 -0
  12. package/scripts/hook-bus-test.mjs +191 -0
  13. package/scripts/ingest-pure-conversation-smoke.mjs +148 -0
  14. package/scripts/internal-comms-bench.mjs +727 -0
  15. package/scripts/internal-comms-smoke.mjs +75 -0
  16. package/scripts/lead-workflow-smoke.mjs +4 -4
  17. package/scripts/live-worker-smoke.mjs +9 -9
  18. package/scripts/output-style-bench.mjs +285 -0
  19. package/scripts/output-style-smoke.mjs +13 -10
  20. package/scripts/patch-replay.mjs +90 -0
  21. package/scripts/path-suffix-test.mjs +57 -0
  22. package/scripts/provider-stream-stall-test.mjs +276 -0
  23. package/scripts/provider-toolcall-test.mjs +599 -1
  24. package/scripts/recall-bench.mjs +207 -0
  25. package/scripts/routing-corpus.mjs +281 -0
  26. package/scripts/session-bench.mjs +1526 -0
  27. package/scripts/session-diag.mjs +595 -0
  28. package/scripts/task-bench.mjs +207 -0
  29. package/scripts/tool-failures.mjs +6 -6
  30. package/scripts/tool-smoke.mjs +310 -67
  31. package/scripts/toolcall-args-test.mjs +81 -0
  32. package/src/agents/debugger/AGENT.md +4 -4
  33. package/src/agents/heavy-worker/AGENT.md +20 -9
  34. package/src/agents/reviewer/AGENT.md +4 -4
  35. package/src/agents/worker/AGENT.md +17 -9
  36. package/src/app.mjs +10 -6
  37. package/src/defaults/{hidden-roles.json → agents.json} +7 -7
  38. package/src/examples/schedules/SCHEDULE.example.md +32 -0
  39. package/src/examples/webhooks/WEBHOOK.example.md +40 -0
  40. package/src/headless-role.mjs +14 -14
  41. package/src/help.mjs +1 -0
  42. package/src/lib/rules-builder.cjs +32 -54
  43. package/src/mixdog-session-runtime.mjs +1040 -2036
  44. package/src/output-styles/default.md +12 -7
  45. package/src/output-styles/minimal.md +25 -0
  46. package/src/output-styles/oneline.md +21 -0
  47. package/src/output-styles/simple.md +10 -9
  48. package/src/repl.mjs +17 -7
  49. package/src/rules/agent/00-common.md +7 -5
  50. package/src/rules/agent/30-explorer.md +8 -12
  51. package/src/rules/lead/01-general.md +3 -1
  52. package/src/rules/lead/lead-tool.md +13 -2
  53. package/src/rules/shared/01-tool.md +23 -12
  54. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +90 -32
  55. package/src/runtime/agent/orchestrator/agent-runtime/agent-loop-policy.mjs +32 -0
  56. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +18 -6
  57. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +23 -20
  58. package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +48 -14
  59. package/src/runtime/agent/orchestrator/agent-trace.mjs +87 -12
  60. package/src/runtime/agent/orchestrator/config.mjs +3 -0
  61. package/src/runtime/agent/orchestrator/context/collect.mjs +182 -67
  62. package/src/runtime/agent/orchestrator/{internal-roles.mjs → internal-agents.mjs} +72 -72
  63. package/src/runtime/agent/orchestrator/internal-tools.mjs +13 -26
  64. package/src/runtime/agent/orchestrator/mcp/client.mjs +100 -18
  65. package/src/runtime/agent/orchestrator/providers/anthropic-betas.mjs +7 -0
  66. package/src/runtime/agent/orchestrator/providers/anthropic-effort.mjs +188 -0
  67. package/src/runtime/agent/orchestrator/providers/anthropic-leaked-toolcall.mjs +444 -0
  68. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +93 -0
  69. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +313 -84
  70. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +104 -38
  71. package/src/runtime/agent/orchestrator/providers/api-usage.mjs +28 -33
  72. package/src/runtime/agent/orchestrator/providers/gemini.mjs +184 -17
  73. package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +8 -1
  74. package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +32 -0
  75. package/src/runtime/agent/orchestrator/providers/model-catalog.mjs +18 -8
  76. package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +54 -20
  77. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +227 -31
  78. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +83 -6
  79. package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +229 -115
  80. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +213 -33
  81. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +18 -0
  82. package/src/runtime/agent/orchestrator/providers/opencode-go-usage.mjs +49 -17
  83. package/src/runtime/agent/orchestrator/providers/registry.mjs +2 -1
  84. package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +22 -17
  85. package/src/runtime/agent/orchestrator/session/compact.mjs +560 -51
  86. package/src/runtime/agent/orchestrator/session/context-utils.mjs +250 -3
  87. package/src/runtime/agent/orchestrator/session/loop/compact-debug.mjs +28 -0
  88. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +262 -0
  89. package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +38 -0
  90. package/src/runtime/agent/orchestrator/session/loop/env.mjs +14 -0
  91. package/src/runtime/agent/orchestrator/session/loop/hidden-agents.mjs +21 -0
  92. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +49 -0
  93. package/src/runtime/agent/orchestrator/session/loop/steering.mjs +63 -0
  94. package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +100 -0
  95. package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +52 -0
  96. package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +218 -0
  97. package/src/runtime/agent/orchestrator/session/loop/transcript-repair.mjs +101 -0
  98. package/src/runtime/agent/orchestrator/session/loop/usage.mjs +35 -0
  99. package/src/runtime/agent/orchestrator/session/loop.mjs +513 -1000
  100. package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +227 -0
  101. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +235 -0
  102. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +137 -0
  103. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +155 -0
  104. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +303 -0
  105. package/src/runtime/agent/orchestrator/session/manager.mjs +232 -1152
  106. package/src/runtime/agent/orchestrator/session/store.mjs +4 -4
  107. package/src/runtime/agent/orchestrator/session/tool-envelope.mjs +61 -0
  108. package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +5 -0
  109. package/src/runtime/agent/orchestrator/stall-policy.mjs +63 -15
  110. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +194 -24
  111. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.test.mjs +143 -0
  112. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +34 -18
  113. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +241 -0
  114. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.test.mjs +162 -0
  115. package/src/runtime/agent/orchestrator/tools/builtin/fuzzy-match.mjs +1 -1
  116. package/src/runtime/agent/orchestrator/tools/builtin/list-formatting.mjs +10 -0
  117. package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +5 -4
  118. package/src/runtime/agent/orchestrator/tools/builtin/path-diagnostics.mjs +42 -2
  119. package/src/runtime/agent/orchestrator/tools/builtin/path-utils.mjs +15 -0
  120. package/src/runtime/agent/orchestrator/tools/builtin/read-args.mjs +9 -44
  121. package/src/runtime/agent/orchestrator/tools/builtin/read-constants.mjs +2 -1
  122. package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +14 -5
  123. package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +11 -4
  124. package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +10 -17
  125. package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +23 -2
  126. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +50 -39
  127. package/src/runtime/agent/orchestrator/tools/builtin/shell-output.mjs +3 -2
  128. package/src/runtime/agent/orchestrator/tools/builtin/tool-output-limit.mjs +10 -0
  129. package/src/runtime/agent/orchestrator/tools/builtin.mjs +70 -1
  130. package/src/runtime/agent/orchestrator/tools/code-graph/build.mjs +303 -0
  131. package/src/runtime/agent/orchestrator/tools/code-graph/constants.mjs +43 -0
  132. package/src/runtime/agent/orchestrator/tools/code-graph/disk-cache.mjs +382 -0
  133. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +497 -0
  134. package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary.mjs +295 -0
  135. package/src/runtime/agent/orchestrator/tools/code-graph/graph-model.mjs +158 -0
  136. package/src/runtime/agent/orchestrator/tools/code-graph/lang-predicates.mjs +128 -0
  137. package/src/runtime/agent/orchestrator/tools/code-graph/memory-cache.mjs +66 -0
  138. package/src/runtime/agent/orchestrator/tools/code-graph/project-root.mjs +44 -0
  139. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +1192 -0
  140. package/src/runtime/agent/orchestrator/tools/code-graph/source-access.mjs +81 -0
  141. package/src/runtime/agent/orchestrator/tools/code-graph/span.mjs +19 -0
  142. package/src/runtime/agent/orchestrator/tools/code-graph/symbol-index.mjs +280 -0
  143. package/src/runtime/agent/orchestrator/tools/code-graph/text-mask.mjs +347 -0
  144. package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +5 -5
  145. package/src/runtime/agent/orchestrator/tools/code-graph.mjs +39 -4189
  146. package/src/runtime/agent/orchestrator/tools/patch.mjs +119 -5
  147. package/src/runtime/agent/orchestrator/tools/progress-message.mjs +1 -2
  148. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +1 -2
  149. package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +2 -4
  150. package/src/runtime/channels/backends/discord.mjs +99 -9
  151. package/src/runtime/channels/backends/telegram.mjs +501 -0
  152. package/src/runtime/channels/index.mjs +437 -1439
  153. package/src/runtime/channels/lib/boot-profile.mjs +23 -0
  154. package/src/runtime/channels/lib/config.mjs +54 -2
  155. package/src/runtime/channels/lib/crash-log.mjs +106 -0
  156. package/src/runtime/channels/lib/format.mjs +4 -2
  157. package/src/runtime/channels/lib/index-drop-trace.mjs +72 -0
  158. package/src/runtime/channels/lib/output-forwarder.mjs +88 -67
  159. package/src/runtime/channels/lib/runtime-paths.mjs +29 -0
  160. package/src/runtime/channels/lib/scheduler.mjs +1 -1
  161. package/src/runtime/channels/lib/telegram-format.mjs +280 -0
  162. package/src/runtime/channels/lib/tool-format.mjs +1 -1
  163. package/src/runtime/channels/lib/transcript-discovery.mjs +19 -1
  164. package/src/runtime/channels/lib/webhook.mjs +59 -31
  165. package/src/runtime/channels/lib/whisper-language.mjs +42 -0
  166. package/src/runtime/channels/tool-defs.mjs +1 -1
  167. package/src/runtime/memory/index.mjs +465 -345
  168. package/src/runtime/memory/lib/agent-ipc.mjs +2 -2
  169. package/src/runtime/memory/lib/core-memory-store.mjs +352 -2
  170. package/src/runtime/memory/lib/cycle-signatures.mjs +34 -0
  171. package/src/runtime/memory/lib/http-wire.mjs +57 -0
  172. package/src/runtime/memory/lib/memory-cycle1.mjs +1 -1
  173. package/src/runtime/memory/lib/memory-cycle2.mjs +65 -9
  174. package/src/runtime/memory/lib/memory-cycle3.mjs +1 -1
  175. package/src/runtime/memory/lib/memory-recall-scope-filter.mjs +24 -0
  176. package/src/runtime/memory/lib/memory-retrievers.mjs +8 -0
  177. package/src/runtime/memory/lib/memory.mjs +121 -4
  178. package/src/runtime/memory/lib/pg/adapter.mjs +139 -15
  179. package/src/runtime/memory/lib/promotion-fingerprint.mjs +50 -0
  180. package/src/runtime/memory/lib/recall-format.mjs +183 -0
  181. package/src/runtime/memory/lib/session-ingest.mjs +107 -0
  182. package/src/runtime/memory/lib/trace-store.mjs +69 -22
  183. package/src/runtime/memory/tool-defs.mjs +10 -7
  184. package/src/runtime/shared/abort-controller.mjs +1 -1
  185. package/src/runtime/shared/background-tasks.mjs +2 -3
  186. package/src/runtime/shared/buffered-appender.mjs +149 -0
  187. package/src/runtime/shared/channel-notification-routing.mjs +12 -0
  188. package/src/runtime/shared/channel-notification-routing.test.mjs +45 -0
  189. package/src/runtime/shared/config.mjs +9 -0
  190. package/src/runtime/shared/llm/http-agent.mjs +12 -5
  191. package/src/runtime/shared/schedules-store.mjs +21 -19
  192. package/src/runtime/shared/task-notification-envelope.mjs +98 -0
  193. package/src/runtime/shared/task-notification-envelope.test.mjs +107 -0
  194. package/src/runtime/shared/tool-execution-contract.mjs +2 -2
  195. package/src/runtime/shared/tool-surface.mjs +98 -13
  196. package/src/runtime/shared/transcript-writer.mjs +156 -0
  197. package/src/runtime/shared/update-checker.mjs +214 -0
  198. package/src/session-runtime/config-helpers.mjs +209 -0
  199. package/src/session-runtime/effort.mjs +128 -0
  200. package/src/session-runtime/fs-utils.mjs +10 -0
  201. package/src/session-runtime/model-capabilities.mjs +130 -0
  202. package/src/session-runtime/output-styles.mjs +124 -0
  203. package/src/session-runtime/plugin-mcp.mjs +114 -0
  204. package/src/session-runtime/session-text.mjs +100 -0
  205. package/src/session-runtime/statusline-route.mjs +35 -0
  206. package/src/session-runtime/tool-catalog.mjs +720 -0
  207. package/src/session-runtime/workflow.mjs +358 -0
  208. package/src/standalone/agent-tool.mjs +302 -117
  209. package/src/standalone/channel-admin.mjs +133 -40
  210. package/src/standalone/channel-worker.mjs +10 -292
  211. package/src/standalone/explore-tool.mjs +12 -5
  212. package/src/standalone/hook-bus.mjs +165 -8
  213. package/src/standalone/memory-runtime-proxy.mjs +3 -1
  214. package/src/standalone/opencode-go-login.mjs +121 -0
  215. package/src/standalone/provider-admin.mjs +25 -3
  216. package/src/standalone/usage-dashboard.mjs +1 -1
  217. package/src/tui/App.jsx +2883 -778
  218. package/src/tui/components/ConfirmBar.jsx +47 -0
  219. package/src/tui/components/ContextPanel.jsx +5 -3
  220. package/src/tui/components/ItemRightHintOverprint.jsx +54 -0
  221. package/src/tui/components/Markdown.jsx +22 -98
  222. package/src/tui/components/Message.jsx +14 -35
  223. package/src/tui/components/Picker.jsx +87 -12
  224. package/src/tui/components/PromptInput.jsx +355 -22
  225. package/src/tui/components/QueuedCommands.jsx +1 -1
  226. package/src/tui/components/SlashCommandPalette.jsx +8 -5
  227. package/src/tui/components/Spinner.jsx +7 -7
  228. package/src/tui/components/StatusLine.jsx +40 -21
  229. package/src/tui/components/TextEntryPanel.jsx +51 -7
  230. package/src/tui/components/ToolExecution.jsx +183 -101
  231. package/src/tui/components/TurnDone.jsx +4 -4
  232. package/src/tui/components/UsagePanel.jsx +1 -1
  233. package/src/tui/components/tool-output-format.mjs +161 -23
  234. package/src/tui/components/tool-output-format.test.mjs +87 -0
  235. package/src/tui/display-width.mjs +69 -0
  236. package/src/tui/display-width.test.mjs +35 -0
  237. package/src/tui/dist/index.mjs +6731 -2333
  238. package/src/tui/engine/agent-envelope.mjs +296 -0
  239. package/src/tui/engine/boot-profile.mjs +21 -0
  240. package/src/tui/engine/labels.mjs +67 -0
  241. package/src/tui/engine/notice-text.mjs +112 -0
  242. package/src/tui/engine/queue-helpers.mjs +161 -0
  243. package/src/tui/engine/session-stats.mjs +46 -0
  244. package/src/tui/engine/tool-call-fields.mjs +23 -0
  245. package/src/tui/engine/tool-result-text.mjs +126 -0
  246. package/src/tui/engine.mjs +569 -948
  247. package/src/tui/index.jsx +117 -7
  248. package/src/tui/input-editing.mjs +58 -8
  249. package/src/tui/input-editing.selection.test.mjs +75 -0
  250. package/src/tui/keyboard-protocol.mjs +42 -0
  251. package/src/tui/lib/voice-recorder.mjs +469 -0
  252. package/src/tui/markdown/format-token.mjs +128 -76
  253. package/src/tui/markdown/format-token.test.mjs +61 -19
  254. package/src/tui/markdown/measure-rendered-rows.mjs +85 -0
  255. package/src/tui/markdown/render-ansi.test.mjs +1 -1
  256. package/src/tui/markdown/streaming-markdown.mjs +167 -0
  257. package/src/tui/markdown/streaming-markdown.test.mjs +70 -0
  258. package/src/tui/markdown/table-layout.mjs +9 -9
  259. package/src/tui/paste-attachments.mjs +36 -9
  260. package/src/tui/paste-fix.test.mjs +119 -0
  261. package/src/tui/prompt-history-store.mjs +129 -0
  262. package/src/tui/prompt-history-store.test.mjs +52 -0
  263. package/src/tui/statusline-ansi-bridge.test.mjs +3 -3
  264. package/src/tui/theme.mjs +41 -657
  265. package/src/tui/themes/base.mjs +86 -0
  266. package/src/tui/themes/basic.mjs +85 -0
  267. package/src/tui/themes/catppuccin.mjs +72 -0
  268. package/src/tui/themes/dracula.mjs +70 -0
  269. package/src/tui/themes/everforest.mjs +71 -0
  270. package/src/tui/themes/gruvbox.mjs +71 -0
  271. package/src/tui/themes/index.mjs +71 -0
  272. package/src/tui/themes/indigo.mjs +78 -0
  273. package/src/tui/themes/kanagawa.mjs +80 -0
  274. package/src/tui/themes/light.mjs +81 -0
  275. package/src/tui/themes/nord.mjs +72 -0
  276. package/src/tui/themes/onedark.mjs +16 -0
  277. package/src/tui/themes/rosepine.mjs +70 -0
  278. package/src/tui/themes/teal.mjs +80 -0
  279. package/src/tui/themes/tokyonight.mjs +79 -0
  280. package/src/tui/themes/utils.mjs +106 -0
  281. package/src/tui/themes/warm.mjs +79 -0
  282. package/src/tui/transcript-tool-failures.mjs +13 -2
  283. package/src/ui/markdown.mjs +1 -1
  284. package/src/ui/model-display.mjs +2 -2
  285. package/src/ui/statusline.mjs +75 -27
  286. package/src/vendor/statusline/bin/statusline-route.mjs +5 -12
  287. package/src/vendor/statusline/src/gateway/claude-current.mjs +3 -3
  288. package/src/vendor/statusline/src/gateway/route-meta.mjs +30 -16
  289. package/src/workflows/default/WORKFLOW.md +46 -12
  290. package/src/workflows/sequential/WORKFLOW.md +51 -0
  291. package/src/workflows/solo/WORKFLOW.md +12 -1
  292. package/vendor/ink/build/display-width.js +62 -0
  293. package/vendor/ink/build/ink.js +100 -12
  294. package/vendor/ink/build/measure-text.js +4 -1
  295. package/vendor/ink/build/output.js +115 -9
  296. package/vendor/ink/build/render-node-to-output.js +4 -1
  297. package/vendor/ink/build/render.js +4 -0
  298. package/src/output-styles/extreme-simple.md +0 -20
  299. package/src/rules/lead/04-workflow.md +0 -51
  300. package/src/workflows/default/workflow.json +0 -13
  301. package/src/workflows/solo/workflow.json +0 -7
@@ -9,7 +9,7 @@
9
9
  import React, { useEffect, useRef, useState } from 'react';
10
10
  import { Box, Text } from 'ink';
11
11
  import { displayModelName, shortenModelName } from '../../ui/model-display.mjs';
12
- import { theme } from '../theme.mjs';
12
+ import { theme, surfaceBackground } from '../theme.mjs';
13
13
  import {
14
14
  normalizeStatuslineAnsi,
15
15
  statuslineFooterCacheKey,
@@ -33,6 +33,20 @@ function resetStatuslineModuleLoad() {
33
33
 
34
34
  const RESET = '\x1b[0m';
35
35
  const STATUSLINE_RENDER_DEBOUNCE_MS = 150;
36
+ /** Background import of statusline.mjs before the +1000ms full-render tick. */
37
+ const STATUSLINE_MODULE_PREWARM_DELAY_MS = 300;
38
+
39
+ let statuslineModulePrewarmScheduled = false;
40
+
41
+ function scheduleStatuslineModulePrewarm() {
42
+ if (statuslineModulePrewarmScheduled) return;
43
+ statuslineModulePrewarmScheduled = true;
44
+ const timer = setTimeout(() => {
45
+ loadStatuslineModule().catch(() => {});
46
+ }, STATUSLINE_MODULE_PREWARM_DELAY_MS);
47
+ timer.unref?.();
48
+ }
49
+
36
50
  const STATUSLINE_BOOT_FULL_DELAY_MS = 1000;
37
51
  const STATUSLINE_BOOT_FULL_DELAY_ACTIVE_MS = 2200;
38
52
  const STATUSLINE_BOOT_FULL_RETRY_MS = 2000;
@@ -46,7 +60,7 @@ function isTerminalStatus(statusText) {
46
60
 
47
61
  function hasRunningStatuslineWorkers(agentWorkers = [], agentJobs = []) {
48
62
  for (const worker of Array.isArray(agentWorkers) ? agentWorkers : []) {
49
- const tag = String(worker?.tag || worker?.role || worker?.name || '').trim();
63
+ const tag = String(worker?.tag || worker?.agent || worker?.name || '').trim();
50
64
  if (tag && !isTerminalStatus(worker?.stage || worker?.status)) return true;
51
65
  }
52
66
  for (const job of Array.isArray(agentJobs) ? agentJobs : []) {
@@ -143,8 +157,8 @@ function localContextPct({
143
157
  : (localNum(contextWindow) > 0
144
158
  ? localNum(contextWindow)
145
159
  : (localNum(rawContextWindow) > 0 ? localNum(rawContextWindow) : 200_000)));
146
- const compactTrigger = localNum(autoCompactTokenLimit);
147
- const window = compactTrigger > 0 && compactTrigger < baseWindow ? compactTrigger : baseWindow;
160
+ // autoCompactTokenLimit is the compaction trigger only; pct uses the boundary window.
161
+ const window = baseWindow;
148
162
  const s = stats && typeof stats === 'object' ? stats : {};
149
163
  const source = String(s.currentContextSource || '').toLowerCase();
150
164
  const estimated = localNum(s.currentEstimatedContextTokens);
@@ -190,11 +204,6 @@ const LOCAL_WORKER_SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '
190
204
  // render stay in sync (no flicker).
191
205
  const LOCAL_L2_SPINNER_FRAME_MS = 120;
192
206
 
193
- function localWorkerSpinnerFrame(now = Date.now()) {
194
- const index = Math.floor(now / 160) % LOCAL_WORKER_SPINNER_FRAMES.length;
195
- return LOCAL_WORKER_SPINNER_FRAMES[index] || LOCAL_WORKER_SPINNER_FRAMES[0];
196
- }
197
-
198
207
  function localL2SpinnerFrame(now = Date.now()) {
199
208
  const index = Math.floor(now / LOCAL_L2_SPINNER_FRAME_MS) % LOCAL_WORKER_SPINNER_FRAMES.length;
200
209
  return LOCAL_WORKER_SPINNER_FRAMES[index] || LOCAL_WORKER_SPINNER_FRAMES[0];
@@ -224,13 +233,13 @@ function localFormatElapsed(ms) {
224
233
  function localRunningWorkerCount(agentWorkers = [], agentJobs = []) {
225
234
  const seen = new Set();
226
235
  for (const worker of Array.isArray(agentWorkers) ? agentWorkers : []) {
227
- const tag = String(worker?.tag || worker?.role || worker?.name || '').trim();
236
+ const tag = String(worker?.tag || worker?.agent || worker?.name || '').trim();
228
237
  if (!tag || isTerminalStatus(worker?.stage || worker?.status)) continue;
229
238
  seen.add(tag);
230
239
  }
231
240
  for (const job of Array.isArray(agentJobs) ? agentJobs : []) {
232
241
  if (!/running/i.test(String(job?.status || job?.stage || ''))) continue;
233
- const tag = String(job?.tag || job?.role || job?.type || job?.task_id || job?.taskId || '').trim();
242
+ const tag = String(job?.tag || job?.agent || job?.type || job?.task_id || job?.taskId || '').trim();
234
243
  if (!tag) continue;
235
244
  seen.add(tag);
236
245
  }
@@ -241,14 +250,14 @@ function localRunningWorkerTags(agentWorkers = [], agentJobs = [], limit = 3) {
241
250
  const tags = [];
242
251
  const seen = new Set();
243
252
  for (const worker of Array.isArray(agentWorkers) ? agentWorkers : []) {
244
- const tag = String(worker?.tag || worker?.role || worker?.name || '').trim();
253
+ const tag = String(worker?.tag || worker?.agent || worker?.name || '').trim();
245
254
  if (!tag || isTerminalStatus(worker?.stage || worker?.status) || seen.has(tag)) continue;
246
255
  seen.add(tag);
247
256
  tags.push(tag);
248
257
  }
249
258
  for (const job of Array.isArray(agentJobs) ? agentJobs : []) {
250
259
  if (!/running/i.test(String(job?.status || job?.stage || ''))) continue;
251
- const tag = String(job?.tag || job?.role || job?.type || job?.task_id || job?.taskId || '').trim();
260
+ const tag = String(job?.tag || job?.agent || job?.type || job?.task_id || job?.taskId || '').trim();
252
261
  if (!tag || seen.has(tag)) continue;
253
262
  seen.add(tag);
254
263
  tags.push(tag);
@@ -417,12 +426,13 @@ export function normalizeStatusLine(text) {
417
426
  return normalizeStatuslineAnsi(text, statusColors(), { reset: RESET });
418
427
  }
419
428
 
420
- function workflowModeLabel(workflow = {}) {
429
+ function workflowModeLabel(workflow = {}, remoteEnabled = false) {
421
430
  const name = String(workflow?.name || workflow?.id || 'Default').trim() || 'Default';
422
- return `${name} Mode`;
431
+ const base = `${name} Mode`;
432
+ return remoteEnabled === true ? `Remote / ${base}` : base;
423
433
  }
424
434
 
425
- function StatusLineView({ sessionId, clientHostPid, provider, model, effort, fast, cwd, stats, contextWindow, displayContextWindow = 0, compactBoundaryTokens = 0, autoCompactTokenLimit = 0, rawContextWindow, resizeEpoch, agentRevision = '', agentWorkers = [], agentJobs = [], activeTools = null, initialLine = '', workflow = null, themeEpoch = 0 }) {
435
+ function StatusLineView({ sessionId, clientHostPid, provider, model, effort, fast, cwd, stats, contextWindow, displayContextWindow = 0, compactBoundaryTokens = 0, autoCompactTokenLimit = 0, rawContextWindow, resizeEpoch, agentRevision = '', agentWorkers = [], agentJobs = [], activeTools = null, initialLine = '', workflow = null, remoteEnabled = false, themeEpoch = 0 }) {
426
436
  const [line, setLine] = useState(() => normalizeStatusLine(initialLine || localBootStatusLine({
427
437
  provider,
428
438
  model,
@@ -474,6 +484,10 @@ function StatusLineView({ sessionId, clientHostPid, provider, model, effort, fas
474
484
  : '';
475
485
  const refreshMs = hasActiveStatuslineWork(line, agentWorkers, agentJobs, activeTools) ? STATUSLINE_ACTIVE_REFRESH_MS : STATUSLINE_REFRESH_MS;
476
486
 
487
+ useEffect(() => {
488
+ scheduleStatuslineModulePrewarm();
489
+ }, []);
490
+
477
491
  useEffect(() => {
478
492
  const timer = setInterval(() => {
479
493
  setRefreshTick((tick) => (tick + 1) % 1_000_000);
@@ -634,11 +648,12 @@ function StatusLineView({ sessionId, clientHostPid, provider, model, effort, fas
634
648
  }, [sessionId, clientHostPid, provider, model, effort, fast, cwd, stats, contextWindow, displayContextWindow, compactBoundaryTokens, autoCompactTokenLimit, rawContextWindow, resizeEpoch, agentRevision, agentWorkers, agentJobs, activeToolsSignature, refreshTick, themeEpoch]);
635
649
 
636
650
  const lines = line ? line.split('\n').slice(0, 2) : [' ', ' '];
637
- const workflowLabel = workflowModeLabel(workflow);
638
- // Footer footprint stays 3 rows total, but L2 sits directly under L1 without
639
- // an internal spacer; the remaining row is kept as outer breathing room.
651
+ const workflowLabel = workflowModeLabel(workflow, remoteEnabled);
652
+ // Footer footprint stays 3 rows total (L1 + L2 + one spacer). Keep L1/L2 in
653
+ // the TOP two rows so the statusline is visually attached to the prompt box;
654
+ // the leftover breathing row sits below L2 at the terminal bottom.
640
655
  return (
641
- <Box flexDirection="column" width="100%" height={3} overflow="hidden" paddingLeft={2} backgroundColor={theme.background}>
656
+ <Box flexDirection="column" width="100%" height={3} overflow="hidden" justifyContent="flex-start" paddingLeft={2} backgroundColor={surfaceBackground()}>
642
657
  <Box flexDirection="row" width="100%" overflow="hidden">
643
658
  <Box flexGrow={1} flexShrink={1} overflow="hidden">
644
659
  <Text wrap="truncate">{lines[0] || ' '}</Text>
@@ -647,7 +662,11 @@ function StatusLineView({ sessionId, clientHostPid, provider, model, effort, fas
647
662
  <Text color={theme.statusText} wrap="truncate">{workflowLabel}</Text>
648
663
  </Box>
649
664
  </Box>
650
- <Text wrap="truncate">{lines[1] || ' '}</Text>
665
+ <Box flexDirection="row" width="100%" overflow="hidden">
666
+ <Box flexGrow={1} flexShrink={1} overflow="hidden">
667
+ <Text wrap="truncate">{lines[1] || ' '}</Text>
668
+ </Box>
669
+ </Box>
651
670
  </Box>
652
671
  );
653
672
  }
@@ -4,7 +4,7 @@
4
4
  import React, { useEffect, useLayoutEffect, useRef, useState } from 'react';
5
5
  import { Box, Text, useInput, usePaste, useStdin } from 'ink';
6
6
  import stringWidth from 'string-width';
7
- import { theme } from '../theme.mjs';
7
+ import { theme, surfaceBackground } from '../theme.mjs';
8
8
  import {
9
9
  clearSelection,
10
10
  deleteBackwardWord,
@@ -126,14 +126,34 @@ function singleTrailingLineBreakPrefix(text) {
126
126
  return prefix.includes('\n') ? null : prefix;
127
127
  }
128
128
 
129
- function isCtrlEnterSequence(input) {
129
+ // Recognize a MODIFIED Enter (Ctrl+Enter or Shift+Enter) delivered via the kitty
130
+ // keyboard protocol (\x1b[13;<mod>u) or modifyOtherKeys (\x1b[27;<mod>;13~). The
131
+ // xterm modifier param is (1 + bitmask): shift=1, alt=2, ctrl=4. We match when
132
+ // the shift OR ctrl bit is set so both chords insert a newline. Ctrl+J is the
133
+ // protocol-independent fallback, handled separately.
134
+ const MODIFIED_ENTER_SHIFT_OR_CTRL = 1 | 4;
135
+ function isModifiedEnterSequence(input) {
130
136
  const text = String(input ?? '');
131
137
  const body = text.startsWith('\x1b[') ? text.slice(2) : text.startsWith('[') ? text.slice(1) : '';
132
138
  if (!body) return false;
133
139
  const kitty = /^13;(\d+)(?::\d+)?(?:;[\d:]+)?u$/.exec(body);
134
- if (kitty) return ((Number(kitty[1]) - 1) & 4) !== 0;
140
+ if (kitty) return ((Number(kitty[1]) - 1) & MODIFIED_ENTER_SHIFT_OR_CTRL) !== 0;
135
141
  const modifyOtherKeys = /^27;(\d+);13~$/.exec(body);
136
- return Boolean(modifyOtherKeys && (((Number(modifyOtherKeys[1]) - 1) & 4) !== 0));
142
+ return Boolean(modifyOtherKeys && (((Number(modifyOtherKeys[1]) - 1) & MODIFIED_ENTER_SHIFT_OR_CTRL) !== 0));
143
+ }
144
+
145
+ // Recognize ANY modified Enter (any modifier bitmask, e.g. Alt+Enter). Used to
146
+ // CONSUME modified-Enter sequences we don't map to a newline so they aren't
147
+ // typed as raw CSI text under modifyOtherKeys. Plain Enter (mod=1) is NOT
148
+ // matched, so it still submits.
149
+ function isAnyModifiedEnterSequence(input) {
150
+ const text = String(input ?? '');
151
+ const body = text.startsWith('\x1b[') ? text.slice(2) : text.startsWith('[') ? text.slice(1) : '';
152
+ if (!body) return false;
153
+ const kitty = /^13;(\d+)(?::\d+)?(?:;[\d:]+)?u$/.exec(body);
154
+ if (kitty) return (Number(kitty[1]) - 1) !== 0;
155
+ const modifyOtherKeys = /^27;(\d+);13~$/.exec(body);
156
+ return Boolean(modifyOtherKeys && ((Number(modifyOtherKeys[1]) - 1) !== 0));
137
157
  }
138
158
 
139
159
  export function TextEntryPanel({
@@ -227,6 +247,11 @@ export function TextEntryPanel({
227
247
  const rawSource = String(input ?? '');
228
248
  const rawInput = normalizeInput(input);
229
249
  if (/(?:\x1b)?\[<\d+;\d+;\d+[Mm]/.test(rawSource)) return;
250
+ // Safety net: drop CSI-private replies/fragments (\x1b[?<n>u / \x1b[?...c).
251
+ // We no longer query the terminal, so these should not normally appear, but
252
+ // a volunteered report must never type into the field. See PromptInput for
253
+ // the full rationale; optional final byte also discards partial fragments.
254
+ if (/^(?:\x1b)?\[\?[\d;]*[uc]?$/.test(rawSource)) return;
230
255
 
231
256
  if (key.escape) {
232
257
  if (selectionRange(draftRef.current)) {
@@ -237,8 +262,27 @@ export function TextEntryPanel({
237
262
  return;
238
263
  }
239
264
  const trailingEnterPrefix = singleTrailingLineBreakPrefix(rawInput);
240
- const rawCtrlEnter = isCtrlEnterSequence(rawSource) || isCtrlEnterSequence(rawInput);
265
+ const rawCtrlEnter = isModifiedEnterSequence(rawSource) || isModifiedEnterSequence(rawInput);
241
266
  const modifiedLineBreak = key.shift || key.meta || key.ctrl || rawCtrlEnter;
267
+
268
+ // Ctrl+J — the protocol-independent newline that works on every terminal.
269
+ // Legacy/modifyOtherKeys: a lone '\n' (real Enter is CR → key.return). Kitty:
270
+ // \x1b[106;5u → input 'j' with key.ctrl. Either → insert a newline. Must
271
+ // precede the trailing-newline/submit paths since
272
+ // singleTrailingLineBreakPrefix('\n') returns '' (not null) and would
273
+ // otherwise route Ctrl+J to submit.
274
+ if ((rawSource === '\n' && !key.return) || (key.ctrl && rawSource.toLowerCase() === 'j')) {
275
+ updateDraft((d) => replaceSelection(d, '\n'));
276
+ return;
277
+ }
278
+
279
+ // A modified Enter that is NOT a newline chord (e.g. Alt+Enter): consume it
280
+ // so its raw CSI bytes don't type into the field under modifyOtherKeys. Plain
281
+ // Enter (mod=1) is not matched and still submits below.
282
+ if (!rawCtrlEnter && (isAnyModifiedEnterSequence(rawSource) || isAnyModifiedEnterSequence(rawInput))) {
283
+ return;
284
+ }
285
+
242
286
  const pasteFallback = rawInput.includes('\n') && trailingEnterPrefix === null && (rawInput.length > 1 || !key.return);
243
287
  if (pasteFallback) {
244
288
  updateDraft((d) => insertText(d, rawInput));
@@ -256,7 +300,7 @@ export function TextEntryPanel({
256
300
  updateDraft((d) => replaceSelection(d, '\n'));
257
301
  return;
258
302
  }
259
- if (key.return || rawInput === '\n') {
303
+ if (key.return) {
260
304
  if (modifiedLineBreak) {
261
305
  updateDraft((d) => replaceSelection(d, '\n'));
262
306
  return;
@@ -432,7 +476,7 @@ export function TextEntryPanel({
432
476
  <Text> </Text>
433
477
  <Text color={theme.subtle}>{hintText || ' '}</Text>
434
478
  <Text> </Text>
435
- <Box ref={boxRef} flexDirection="row" width="100%" backgroundColor={theme.background}>
479
+ <Box ref={boxRef} flexDirection="row" width="100%" backgroundColor={surfaceBackground()}>
436
480
  <Text color={theme.inactive}>{promptLabel}</Text>
437
481
  <Text color={theme.text} wrap="truncate">{renderedValue}</Text>
438
482
  </Box>