mixdog 1.2.5 → 1.2.6

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 (290) hide show
  1. package/package.json +1 -1
  2. package/scripts/lib/gate-scheduler.mjs +2 -2
  3. package/scripts/lib/run-node-tests.mjs +5 -14
  4. package/scripts/provider-pingpong-live.mjs +9 -9
  5. package/src/agents/advisor/AGENT.md +4 -4
  6. package/src/agents/advisor/agent.json +1 -1
  7. package/src/agents/reviewer/AGENT.md +2 -3
  8. package/src/agents/reviewer/agent.json +1 -1
  9. package/src/defaults/shipped-history.json +10 -0
  10. package/src/defaults/skills/browser-use/SKILL.md +2 -1
  11. package/src/defaults/skills/computer-use/SKILL.md +3 -1
  12. package/src/defaults/skills/visualize/SKILL.md +3 -2
  13. package/src/lib/rules-builder.cjs +1 -1
  14. package/src/output-styles/common.md +22 -6
  15. package/src/output-styles/detailed.md +7 -5
  16. package/src/output-styles/minimal.md +7 -3
  17. package/src/output-styles/simple.md +2 -3
  18. package/src/rules/agent/AGENT.md +3 -1
  19. package/src/rules/lead/LEAD.md +4 -3
  20. package/src/rules/shared/10-tool-workflow.md +2 -1
  21. package/src/rules/shared/60-verification.md +4 -5
  22. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -1
  23. package/src/runtime/agent/orchestrator/config.mjs +6 -0
  24. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +1 -1
  25. package/src/runtime/agent/orchestrator/internal-agents.mjs +10 -0
  26. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +53 -60
  27. package/src/runtime/agent/orchestrator/mcp/client.mjs +7 -4
  28. package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +2 -3
  29. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +9 -2
  30. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +40 -19
  31. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +3 -2
  32. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +4 -1
  33. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +2 -0
  34. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn.mjs +3 -0
  35. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +2 -1
  36. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +3 -1
  37. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +1 -2
  38. package/src/runtime/agent/orchestrator/providers/catalog-deadline.mjs +163 -0
  39. package/src/runtime/agent/orchestrator/providers/catalog-failures.mjs +34 -0
  40. package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +38 -14
  41. package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +100 -26
  42. package/src/runtime/agent/orchestrator/providers/lib/send-callbacks.mjs +24 -0
  43. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +13 -0
  44. package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +2 -1
  45. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -0
  46. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +4 -0
  47. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +3 -1
  48. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +2 -0
  49. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +49 -4
  50. package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +0 -7
  51. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +7 -1
  52. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +1 -0
  53. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +2 -0
  54. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +1 -0
  55. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +5 -1
  56. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +11 -2
  57. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +1 -0
  58. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +45 -16
  59. package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +1 -0
  60. package/src/runtime/agent/orchestrator/providers/openai-ws-connect.mjs +196 -0
  61. package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +74 -9
  62. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +14 -1
  63. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +2 -0
  64. package/src/runtime/agent/orchestrator/providers/opencode-go-oauth-login.mjs +194 -0
  65. package/src/runtime/agent/orchestrator/providers/opencode-go-oauth-tokens.mjs +353 -0
  66. package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +293 -0
  67. package/src/runtime/agent/orchestrator/providers/opencode-go-usage.mjs +33 -100
  68. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +23 -14
  69. package/src/runtime/agent/orchestrator/providers/registry.mjs +41 -27
  70. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +2 -3
  71. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +3 -8
  72. package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +15 -3
  73. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +74 -13
  74. package/src/runtime/agent/orchestrator/session/compact/forked-summary.mjs +102 -0
  75. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +8 -2
  76. package/src/runtime/agent/orchestrator/session/compact/summary.mjs +16 -0
  77. package/src/runtime/agent/orchestrator/session/lifecycle-scan.mjs +9 -0
  78. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +39 -2
  79. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +9 -19
  80. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +2 -3
  81. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -0
  82. package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +13 -5
  83. package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +10 -7
  84. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +62 -22
  85. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +23 -1
  86. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +81 -34
  87. package/src/runtime/agent/orchestrator/session/manager.mjs +2 -2
  88. package/src/runtime/agent/orchestrator/session/request-fork.mjs +47 -0
  89. package/src/runtime/agent/orchestrator/session/side-question-store.mjs +16 -1
  90. package/src/runtime/agent/orchestrator/session/side-question.mjs +5 -43
  91. package/src/runtime/agent/orchestrator/session/store/fs-probe.mjs +10 -0
  92. package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +73 -6
  93. package/src/runtime/agent/orchestrator/session/store/load-session.mjs +40 -0
  94. package/src/runtime/agent/orchestrator/session/store/save-fault.mjs +15 -0
  95. package/src/runtime/agent/orchestrator/session/store/session-paths.mjs +12 -0
  96. package/src/runtime/agent/orchestrator/session/store-agent-worker-header.mjs +36 -0
  97. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +258 -43
  98. package/src/runtime/agent/orchestrator/session/store-record-strict-scan.mjs +306 -0
  99. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +70 -21
  100. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +46 -30
  101. package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +144 -45
  102. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +32 -13
  103. package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +364 -38
  104. package/src/runtime/agent/orchestrator/session/store.mjs +9 -2
  105. package/src/runtime/agent/orchestrator/session/task-wait-control.mjs +43 -12
  106. package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +23 -6
  107. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +12 -6
  108. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +13 -7
  109. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/bashism-rewrite.mjs +1 -1
  110. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/benign-exit.mjs +7 -1
  111. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +40 -7
  112. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/deadline-plan.mjs +37 -34
  113. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/inline-hoist.mjs +1 -1
  114. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +0 -4
  115. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +6 -0
  116. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +29 -27
  117. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +1 -1
  118. package/src/runtime/agent/orchestrator/tools/builtin/find-files-tool.mjs +28 -11
  119. package/src/runtime/agent/orchestrator/tools/builtin/git-command-policy.mjs +12 -3
  120. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +203 -101
  121. package/src/runtime/agent/orchestrator/tools/builtin/git-repo-rw-lock.mjs +90 -41
  122. package/src/runtime/agent/orchestrator/tools/builtin/lib/list-helpers.mjs +17 -1
  123. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-delivery.mjs +199 -0
  124. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-task-output.mjs +165 -39
  125. package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +25 -13
  126. package/src/runtime/agent/orchestrator/tools/builtin/read-batch.mjs +7 -6
  127. package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +19 -4
  128. package/src/runtime/agent/orchestrator/tools/builtin/read-line-collector.mjs +5 -3
  129. package/src/runtime/agent/orchestrator/tools/builtin/read-single-render.mjs +25 -7
  130. package/src/runtime/agent/orchestrator/tools/builtin/read-special-files.mjs +2 -1
  131. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-render.mjs +3 -1
  132. package/src/runtime/agent/orchestrator/tools/builtin/search-glob-tool.mjs +12 -5
  133. package/src/runtime/agent/orchestrator/tools/builtin/search-grep-tool.mjs +61 -22
  134. package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +32 -8
  135. package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +193 -19
  136. package/src/runtime/agent/orchestrator/tools/builtin/shell-direct-exe.mjs +57 -7
  137. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +119 -32
  138. package/src/runtime/agent/orchestrator/tools/builtin/shell-lossless-compact.mjs +26 -1
  139. package/src/runtime/agent/orchestrator/tools/builtin/shell-output.mjs +13 -28
  140. package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +90 -11
  141. package/src/runtime/agent/orchestrator/tools/builtin/wait-budgets.mjs +23 -0
  142. package/src/runtime/agent/orchestrator/tools/builtin.mjs +54 -10
  143. package/src/runtime/agent/orchestrator/tools/code-graph/build.mjs +22 -28
  144. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +11 -7
  145. package/src/runtime/agent/orchestrator/tools/destructive-warning.mjs +126 -9
  146. package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
  147. package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +15 -6
  148. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +40 -2
  149. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +2 -2
  150. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promotion-results.mjs +13 -3
  151. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +2 -0
  152. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +3 -1
  153. package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +1 -1
  154. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +35 -4
  155. package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +7 -2
  156. package/src/runtime/agent/orchestrator/tools/shell-powershell.mjs +39 -23
  157. package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +6 -2
  158. package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
  159. package/src/runtime/attachments/office-extract.mjs +11 -9
  160. package/src/runtime/memory/lib/embedding-tokenizer.mjs +32 -18
  161. package/src/runtime/memory/lib/runtime-fetcher.mjs +1 -1
  162. package/src/runtime/memory/lib/tool-call-handler.mjs +7 -5
  163. package/src/runtime/office/authoring/pptx-script-normalize.mjs +11 -8
  164. package/src/runtime/office/core/tabular.mjs +1 -1
  165. package/src/runtime/office/design/library/design-template-inspect.mjs +7 -4
  166. package/src/runtime/office/portable/docx-formatting.mjs +1 -1
  167. package/src/runtime/office/portable/docx-runs.mjs +1 -1
  168. package/src/runtime/office/portable/docx-tracked-edits.mjs +2 -2
  169. package/src/runtime/office/portable/portable-docx-edits.mjs +11 -10
  170. package/src/runtime/office/portable/portable-docx-operations.mjs +21 -17
  171. package/src/runtime/office/portable/portable-docx-parts.mjs +15 -9
  172. package/src/runtime/office/portable/portable-docx-styles.mjs +4 -1
  173. package/src/runtime/office/portable/portable-docx-xml.mjs +9 -9
  174. package/src/runtime/office/portable/portable-opc.mjs +27 -13
  175. package/src/runtime/office/portable/portable-pivot.mjs +3 -3
  176. package/src/runtime/office/portable/portable-pptx-chart.mjs +3 -3
  177. package/src/runtime/office/portable/portable-pptx-charts.mjs +24 -18
  178. package/src/runtime/office/portable/portable-pptx-core.mjs +5 -5
  179. package/src/runtime/office/portable/portable-pptx-deck.mjs +8 -4
  180. package/src/runtime/office/portable/portable-pptx-package.mjs +7 -4
  181. package/src/runtime/office/portable/portable-pptx-shapes.mjs +18 -9
  182. package/src/runtime/office/portable/portable-sheet-parts.mjs +9 -3
  183. package/src/runtime/office/portable/portable-sheet-xml.mjs +5 -5
  184. package/src/runtime/office/portable/portable-xlsx-charts.mjs +4 -1
  185. package/src/runtime/office/portable/portable-xlsx-drawings.mjs +10 -6
  186. package/src/runtime/office/portable/portable-xlsx-operations.mjs +8 -5
  187. package/src/runtime/office/portable/portable-xlsx-pivot-ops.mjs +1 -1
  188. package/src/runtime/office/portable/portable-xlsx-reference-shift.mjs +11 -7
  189. package/src/runtime/office/portable/portable-xlsx-sheet-edits.mjs +6 -3
  190. package/src/runtime/office/portable/portable-xml.mjs +1 -1
  191. package/src/runtime/shared/atomic-file.mjs +22 -13
  192. package/src/runtime/shared/background-tasks.mjs +60 -20
  193. package/src/runtime/shared/child-spawn-gate.mjs +26 -16
  194. package/src/runtime/shared/config.mjs +0 -10
  195. package/src/runtime/shared/file-lock.mjs +7 -1
  196. package/src/runtime/shared/file-permissions-worker.mjs +38 -0
  197. package/src/runtime/shared/file-permissions.d.mts +19 -4
  198. package/src/runtime/shared/file-permissions.mjs +310 -4
  199. package/src/runtime/shared/git-runner-worker.mjs +6 -78
  200. package/src/runtime/shared/llm/http-agent.mjs +7 -3
  201. package/src/runtime/shared/llm/provider-catalog-registry.mjs +10 -0
  202. package/src/runtime/shared/llm/usage-accounting.mjs +2 -0
  203. package/src/runtime/shared/llm/usage-ledger-import.mjs +32 -3
  204. package/src/runtime/shared/llm/usage-ledger-rollup.mjs +12 -5
  205. package/src/runtime/shared/llm/usage-ledger-worker.mjs +1 -1
  206. package/src/runtime/shared/llm/usage-ledger.mjs +20 -5
  207. package/src/runtime/shared/memory-snapshot.mjs +5 -1
  208. package/src/runtime/shared/notify-trace.mjs +8 -1
  209. package/src/runtime/shared/pristine-execution-contract.json +5 -1
  210. package/src/runtime/shared/process-runner-worker.mjs +7 -0
  211. package/src/runtime/shared/process-runner.mjs +38 -0
  212. package/src/runtime/shared/provider-accounts.mjs +2 -1
  213. package/src/runtime/shared/provider-api-key.mjs +0 -1
  214. package/src/runtime/shared/read-row-numbers.mjs +1 -1
  215. package/src/runtime/shared/resource-admission.mjs +60 -18
  216. package/src/runtime/shared/run-child.mjs +84 -0
  217. package/src/runtime/shared/session-activity-signal.mjs +23 -0
  218. package/src/runtime/shared/shell-output-summary.mjs +23 -0
  219. package/src/runtime/shared/singleton-owner.mjs +126 -42
  220. package/src/runtime/shared/tool-output-limit.mjs +4 -2
  221. package/src/runtime/shared/tool-output-marker.mjs +58 -0
  222. package/src/runtime/shared/user-data-guard.mjs +28 -9
  223. package/src/runtime/shared/worktrees/activity-gate.mjs +33 -8
  224. package/src/runtime/shared/worktrees/git-head.mjs +20 -2
  225. package/src/runtime/shared/worktrees/lock.mjs +3 -2
  226. package/src/runtime/terminal-bridge/tool-defs.mjs +1 -1
  227. package/src/runtime/tidy/runners/biome.mjs +3 -1
  228. package/src/runtime/tidy/shadow.mjs +2 -1
  229. package/src/runtime/web-search/index.mjs +5 -7
  230. package/src/runtime/web-search/lib/formatter.mjs +42 -6
  231. package/src/runtime/web-search/tool-defs.mjs +6 -1
  232. package/src/session-runtime/lifecycle/session-switch/context-switch.mjs +4 -3
  233. package/src/session-runtime/lifecycle/session-switch/resume.mjs +7 -4
  234. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +3 -3
  235. package/src/session-runtime/lifecycle/shared.mjs +19 -2
  236. package/src/session-runtime/lifecycle/teardown/session-close.mjs +2 -0
  237. package/src/session-runtime/lifecycle/teardown.mjs +5 -2
  238. package/src/session-runtime/lifecycle-api.mjs +3 -1
  239. package/src/session-runtime/provider-auth/login.mjs +10 -6
  240. package/src/session-runtime/provider-auth/setup.mjs +19 -2
  241. package/src/session-runtime/provider-catalog-cache.mjs +101 -25
  242. package/src/session-runtime/provider-models/catalog-load.mjs +14 -3
  243. package/src/session-runtime/provider-models/row-hydration.mjs +4 -0
  244. package/src/session-runtime/provider-models.mjs +76 -10
  245. package/src/session-runtime/provider-readiness.mjs +4 -0
  246. package/src/session-runtime/services/agent-tool/close-flow.mjs +2 -1
  247. package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +10 -2
  248. package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +13 -4
  249. package/src/session-runtime/services/agent-tool/notify.mjs +15 -4
  250. package/src/session-runtime/services/agent-tool/restart-notify.mjs +134 -0
  251. package/src/session-runtime/services/agent-tool/send-flow.mjs +24 -1
  252. package/src/session-runtime/services/agent-tool/spawn-flow/deferred-spawn.mjs +2 -1
  253. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +4 -3
  254. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +5 -1
  255. package/src/session-runtime/services/agent-tool/tag-registry/tag-lookup.mjs +8 -3
  256. package/src/session-runtime/services/agent-tool/tag-registry.mjs +3 -0
  257. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +4 -0
  258. package/src/session-runtime/services/agent-tool/worker-index.mjs +44 -10
  259. package/src/session-runtime/services/agent-tool.mjs +20 -0
  260. package/src/session-runtime/services/provider-admin.mjs +92 -20
  261. package/src/session-runtime/services/usage-dashboard-model.mjs +2 -2
  262. package/src/session-runtime/services/usage-dashboard.mjs +27 -69
  263. package/src/session-runtime/turn/session-ops.mjs +2 -2
  264. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
  265. package/src/session-runtime/usage-stats-api.mjs +6 -1
  266. package/src/standalone/channel-transport/http-routes.mjs +10 -9
  267. package/src/standalone/daemon-desktop-runtime.mjs +20 -7
  268. package/src/standalone/daemon-owner.mjs +117 -25
  269. package/src/standalone/daemon.mjs +43 -13
  270. package/src/standalone/session-call-cache.mjs +6 -0
  271. package/src/standalone/session-protocol.mjs +1 -1
  272. package/src/standalone/session-service/retention/busy.mjs +7 -2
  273. package/src/standalone/session-transport/routes.mjs +7 -6
  274. package/src/tui/app/model-options.mjs +39 -2
  275. package/src/tui/app/model-picker.mjs +16 -2
  276. package/src/tui/app/provider-setup-picker.mjs +1 -2
  277. package/src/tui/dist/index.mjs +385 -104
  278. package/src/tui/session/notice-text.mjs +0 -1
  279. package/src/tui/session/session-api/intake/submission.mjs +7 -13
  280. package/src/tui/session/session-api/integrations.mjs +1 -5
  281. package/src/tui/session/session-flow/drain.mjs +8 -0
  282. package/src/tui/session/session-flow/steering.mjs +46 -0
  283. package/src/tui/session/session-flow.mjs +2 -0
  284. package/src/tui/session/turn-stream.mjs +33 -0
  285. package/src/tui/session/turn.mjs +30 -3
  286. package/src/ui/statusline.mjs +1 -6
  287. package/src/ui/streaming-markdown-heal.mjs +24 -7
  288. package/src/vendor/statusline/bin/statusline-route.mjs +0 -1
  289. package/src/vendor/statusline/src/gateway/route-meta.mjs +0 -1
  290. package/src/workflows/default/WORKFLOW.md +9 -13
@@ -35,7 +35,6 @@ const FAILED_NOTICE_ACTIONS = new Map([
35
35
  ['oauth login', 'start OAuth login'],
36
36
  ['output style switch', 'switch output style'],
37
37
  ['openai usage auth save', 'save OpenAI usage auth'],
38
- ['opencode go usage auth save', 'save OpenCode Go usage auth'],
39
38
  ['plugin add', 'add plugin'],
40
39
  ['plugin mcp enable', 'enable plugin MCP'],
41
40
  ['plugin uninstall', 'uninstall plugin'],
@@ -4,7 +4,7 @@
4
4
  import { promptDisplayText } from '../../queue-helpers.mjs';
5
5
 
6
6
  export function createSubmissionIntake(bag) {
7
- const { runtime, nextId, flags, getState, enqueue, autoClearBeforeSubmit } = bag;
7
+ const { nextId, flags, getState, enqueue, autoClearBeforeSubmit } = bag;
8
8
 
9
9
  const submission = (text, options = {}) => {
10
10
  const displayText = promptDisplayText(text, options);
@@ -25,19 +25,13 @@ export function createSubmissionIntake(bag) {
25
25
  };
26
26
 
27
27
  const enqueueSubmission = (intake) => {
28
+ // The queue itself wakes a passive `task wait` or shell hold for typed
29
+ // input (not for slash commands, which run after the turn); see enqueue.
28
30
  const accepted = enqueue(intake.text, intake.queueOptions);
29
- // User input wakes a passive `task wait` without cancelling either the
30
- // turn or the background task. The returned running snapshot creates the
31
- // normal post-tool boundary, where this queued prompt is injected.
32
- if (accepted !== false) {
33
- if ((intake.queueOptions.mode || 'prompt') === 'prompt') {
34
- bag.cancelQuotaResumeOnUserInput?.();
35
- bag.cancelQueuedGoalContinuations?.();
36
- bag.archiveCompletedGoalOnUserInput?.();
37
- }
38
- try {
39
- runtime.interruptTaskWait?.('user-message');
40
- } catch {}
31
+ if (accepted !== false && (intake.queueOptions.mode || 'prompt') === 'prompt') {
32
+ bag.cancelQuotaResumeOnUserInput?.();
33
+ bag.cancelQueuedGoalContinuations?.();
34
+ bag.archiveCompletedGoalOnUserInput?.();
41
35
  }
42
36
  return accepted;
43
37
  };
@@ -139,6 +139,7 @@ export function createSessionIntegrationsApi(bag, { oauthFlows }) {
139
139
  (result) => `custom provider saved: ${result.id}`
140
140
  ),
141
141
  updateCustomProviderModel: (id, modelId, patch) => runtime.updateCustomProviderModel(id, modelId, patch),
142
+ setModelPreferences: (provider, changes) => runtime.setModelPreferences(provider, changes),
142
143
  removeCustomProvider: async (id) => {
143
144
  const result = await runtime.removeCustomProvider(id);
144
145
  refreshRouteStats();
@@ -148,11 +149,6 @@ export function createSessionIntegrationsApi(bag, { oauthFlows }) {
148
149
  testCustomProvider: (input) => runtime.testCustomProvider(input),
149
150
  checkCustomProviderKeyEnv: (name) => runtime.checkCustomProviderKeyEnv(name),
150
151
  discoverCustomProviderModels: (input) => runtime.discoverCustomProviderModels(input),
151
- saveOpenCodeGoUsageAuth: async (opts) => {
152
- await runtime.saveOpenCodeGoUsageAuth(opts);
153
- pushNotice('OpenCode Go usage auth saved', 'info');
154
- return true;
155
- },
156
152
  saveOpenAIUsageSessionKey: async (secret) => {
157
153
  await runtime.saveOpenAIUsageSessionKey(secret);
158
154
  pushNotice('OpenAI usage auth saved', 'info');
@@ -332,6 +332,14 @@ export function createDrainLoop(
332
332
  }
333
333
  submissions.remember(submissionId);
334
334
  pending.push(entry);
335
+ // Typed input or a deliverable notification ends a passive task wait or
336
+ // shell hold so the next boundary hands it to the model now.
337
+ const wake = steering.taskWaitWakeForEntry(entry);
338
+ if (wake) {
339
+ try {
340
+ bag.runtime?.interruptTaskWait?.(wake, wake === 'notification' ? entry.execution?.id || null : null);
341
+ } catch {}
342
+ }
335
343
  const needsDurableSteering =
336
344
  (getState().busy || getState().commandBusy || flags.autoClearRunning || flags.quotaResumePending) &&
337
345
  steering.shouldMirrorSteeringEntry(entry);
@@ -131,6 +131,47 @@ export function createSteeringOps(bag, { queue, submissions }) {
131
131
  );
132
132
  }
133
133
 
134
+ // Queued input the user typed (editable prompts), not runtime notices.
135
+ function hasPendingUserInput() {
136
+ if (!admissionOpen()) return false;
137
+ return pending.some((entry) => isQueuedEntryEditable(entry) && !isSlashQueuedEntry(entry));
138
+ }
139
+
140
+ // A notification the next boundary will deliver: a task notification (one
141
+ // the agent already received through task wait/read is not deliverable) or
142
+ // the Goal closeout. `later` entries (scheduled and channel injects) wait
143
+ // for the turn to end, so they are not deliverable mid-turn.
144
+ function isDeliverableNotification(entry) {
145
+ const mode = entry?.mode;
146
+ return (
147
+ admissionOpen() &&
148
+ (mode === 'task-notification' || mode === 'goal-closeout') &&
149
+ queuePriorityValue(entry.priority) <= queuePriorityValue('next') &&
150
+ canDeliverSteeringEntry(entry) &&
151
+ steeringMessageFromEntry(entry) !== null
152
+ );
153
+ }
154
+
155
+ function hasPendingNotification() {
156
+ return pending.some(isDeliverableNotification);
157
+ }
158
+
159
+ // What one queued entry should wake a passive wait or shell hold for: typed
160
+ // input, a deliverable notification, or nothing (slash commands and
161
+ // informational meta prompts run or ride along without ending a wait).
162
+ function taskWaitWakeForEntry(entry) {
163
+ if (!admissionOpen()) return false;
164
+ if (isQueuedEntryEditable(entry) && !isSlashQueuedEntry(entry)) return 'user-message';
165
+ return isDeliverableNotification(entry) ? 'notification' : false;
166
+ }
167
+
168
+ // What a passive wait or shell hold should wake for right now: user input
169
+ // first, else a deliverable notification.
170
+ function pendingTaskWaitWake() {
171
+ if (hasPendingUserInput()) return 'user-message';
172
+ return hasPendingNotification() ? 'notification' : false;
173
+ }
174
+
134
175
  // `later` notifications (scheduled tasks) are skipped unless the runtime
135
176
  // explicitly asks for a later flush.
136
177
  function drainPendingSteering(_sessionIdOrOptions = null, maybeOptions = null) {
@@ -219,6 +260,11 @@ export function createSteeringOps(bag, { queue, submissions }) {
219
260
  commitSteeringQueueEntries,
220
261
  settleSteeredSubmissions,
221
262
  hasPendingSteering,
263
+ hasPendingUserInput,
264
+ isDeliverableNotification,
265
+ hasPendingNotification,
266
+ taskWaitWakeForEntry,
267
+ pendingTaskWaitWake,
222
268
  drainPendingSteering,
223
269
  restoreLeadSteeringFromDisk,
224
270
  };
@@ -39,6 +39,8 @@ export function createSessionFlow(bag) {
39
39
  enqueue: loop.enqueue,
40
40
  settleClosedQueue: loop.settleClosedQueue,
41
41
  hasPendingSteering: steering.hasPendingSteering,
42
+ hasPendingUserInput: steering.hasPendingUserInput,
43
+ pendingTaskWaitWake: steering.pendingTaskWaitWake,
42
44
  drainPendingSteering: steering.drainPendingSteering,
43
45
  restoreLeadSteeringFromDisk: steering.restoreLeadSteeringFromDisk,
44
46
  autoClearBeforeSubmit: autoClear.autoClearBeforeSubmit,
@@ -33,6 +33,12 @@ export function createTurnStream(deps) {
33
33
  // segment out of the provider's final content individually: the combined
34
34
  // prefix no longer matches when the provider omits an earlier segment.
35
35
  committedSegments: [],
36
+ // The open segment was settled when the provider streamed a tool call
37
+ // (turn.mjs); cleared when that response's tool calls open.
38
+ settledBeforeToolCall: false,
39
+ // The phase the provider named for the message this segment streams
40
+ // (`commentary` / `final_answer`), or null; the desktop row carries it.
41
+ phase: null,
36
42
  thinkingText: '',
37
43
  thinkingStartedAt: 0,
38
44
  thinkingSegmentStartedAt: 0,
@@ -113,6 +119,7 @@ function ensureAssistant(stream, initialText = '') {
113
119
  text: String(initialText || ''),
114
120
  at,
115
121
  messageId,
122
+ ...phaseField(stream),
116
123
  ...stream.routeMeta,
117
124
  });
118
125
  }
@@ -149,11 +156,17 @@ function partialNow(stream) {
149
156
  streaming: true,
150
157
  at: identity.at,
151
158
  messageId: identity.messageId,
159
+ ...phaseField(stream),
152
160
  ...stream.routeMeta,
153
161
  },
154
162
  };
155
163
  }
156
164
 
165
+ // The row's `phase` field; absent when the provider named none.
166
+ function phaseField(stream) {
167
+ return stream.phase ? { phase: stream.phase } : {};
168
+ }
169
+
157
170
  function samePartial(left, right) {
158
171
  if (left === right) return true;
159
172
  if (!left || !right) return false;
@@ -208,6 +221,7 @@ function resetLineScan(stream) {
208
221
  function closeAssistantSegment(stream) {
209
222
  stream.currentAssistantId = null;
210
223
  stream.currentAssistantText = '';
224
+ stream.phase = null;
211
225
  stream.claimPersistedAssistant = false;
212
226
  stream.assistantIdentity = null;
213
227
  resetLineScan(stream);
@@ -296,6 +310,7 @@ function flushTextBatch(stream) {
296
310
  text: visibleText,
297
311
  streaming: true,
298
312
  at: current?.at || Date.now(),
313
+ phase: stream.phase || undefined,
299
314
  ...stream.routeMeta,
300
315
  };
301
316
  }
@@ -449,6 +464,24 @@ export function appendAssistantText(stream, full, { committed = false } = {}) {
449
464
  flushStreamBatch(stream);
450
465
  }
451
466
 
467
+ // The provider named the phase of the message it is streaming. A message of
468
+ // another phase than the open segment's text is its own row: that segment
469
+ // settles first. A segment whose phase was not known yet (the provider named
470
+ // it only on the finished message) takes it.
471
+ export function noteAssistantPhase(stream, phase) {
472
+ if (phase !== 'commentary' && phase !== 'final_answer') return;
473
+ if (stream.phase === phase) return;
474
+ if (stream.phase && stream.currentAssistantText.trim()) {
475
+ flushStreamBatch(stream);
476
+ commitAssistantSegment(stream);
477
+ }
478
+ stream.phase = phase;
479
+ const tail = stream.getState().streamingTail;
480
+ if (stream.currentAssistantId != null && tail?.id === stream.currentAssistantId) {
481
+ stream.updateStreamingTail(tail.id, { phase });
482
+ }
483
+ }
484
+
452
485
  // Reasoning is not a commit boundary: a turn interrupted while it is still
453
486
  // thinking produced no model-visible message, so Esc must hand the prompt
454
487
  // back to the input box. Text, tool calls and turn end still commit it.
@@ -34,6 +34,7 @@ import {
34
34
  appendTextDelta,
35
35
  appendAssistantText,
36
36
  appendReasoningDelta,
37
+ noteAssistantPhase,
37
38
  resetStreamedText,
38
39
  applyStageChange,
39
40
  settleFinalText,
@@ -241,9 +242,21 @@ function injectSteerMessage({ stream, cards, pushUserOrSyntheticItem }, text, st
241
242
  pushUserOrSyntheticItem(value, steeringIds[0], 'injected', steeringItemExtras(steeringMeta));
242
243
  }
243
244
 
245
+ function settleSegmentBeforeToolCall(ctx) {
246
+ const { stream } = ctx;
247
+ if (!stream.currentAssistantText.trim()) return;
248
+ ctx.markPromptCommitted();
249
+ flushStreamBatch(stream);
250
+ commitAssistantSegment(stream, { sealToolBlock: true });
251
+ // The response's own content (onAssistantText, before its tool calls open)
252
+ // is this streamed text again: it must not reopen as a second row.
253
+ stream.settledBeforeToolCall = true;
254
+ }
255
+
244
256
  async function openToolCalls(ctx, calls) {
245
257
  const { stream, cards, runtime } = ctx;
246
258
  ctx.markPromptCommitted();
259
+ stream.settledBeforeToolCall = false;
247
260
  // Flush buffered mid-turn assistant text before the tool card appears;
248
261
  // otherwise, with neither a thinking panel nor a spinner active, the
249
262
  // message above the tool card vanished.
@@ -372,9 +385,14 @@ function turnHandlers(ctx) {
372
385
  };
373
386
  }
374
387
 
375
- function toolHandlers(ctx) {
388
+ export function toolHandlers(ctx) {
376
389
  const { isCurrentTurn, cards, getState, set, options } = ctx;
377
390
  return {
391
+ // The provider streamed a tool call: the text before it is complete (a
392
+ // preamble), so it settles now instead of after the whole response.
393
+ onAssistantToolCallObserved: () => {
394
+ if (isCurrentTurn()) settleSegmentBeforeToolCall(ctx);
395
+ },
378
396
  onToolCall: async (_iter, calls) => {
379
397
  if (isCurrentTurn()) await openToolCalls(ctx, calls);
380
398
  },
@@ -431,13 +449,22 @@ export function streamHandlers(ctx) {
431
449
  // The streaming path owns this segment when it already produced text.
432
450
  // Do not check turn-global assistantText: earlier closed preambles stay
433
451
  // there across tool calls.
434
- if (stream.currentAssistantText.trim()) return;
452
+ if (stream.currentAssistantText.trim() || stream.settledBeforeToolCall) return;
435
453
  ctx.markPromptCommitted();
436
454
  appendAssistantText(stream, full, { committed: detail?.committed === true });
437
455
  },
438
456
  onReasoningDelta: (chunk) => {
439
457
  if (isCurrentTurn()) appendReasoningDelta(stream, String(chunk ?? ''));
440
458
  },
459
+ // A provider output item started. A tool call ends the text before it
460
+ // (a preamble settles at the call's start, not after its arguments or
461
+ // the whole response); a message naming its phase marks its row as
462
+ // commentary or final answer.
463
+ onStreamItemStart: (detail) => {
464
+ if (!isCurrentTurn()) return;
465
+ if (detail?.kind === 'tool') settleSegmentBeforeToolCall(ctx);
466
+ else if (detail?.kind === 'text') noteAssistantPhase(stream, detail.phase);
467
+ },
441
468
  };
442
469
  }
443
470
 
@@ -693,7 +720,7 @@ export function createRunTurn(bag) {
693
720
  markPromptCommitted: () => commitPromptRestore(flags, turn),
694
721
  };
695
722
  const stopTaskWaitSteeringCheck = registerTaskWaitSteeringCheck(
696
- (sessionId) => isCurrentTurn() && runtime.id === sessionId && bag.hasPendingSteering()
723
+ (sessionId) => isCurrentTurn() && runtime.id === sessionId && bag.pendingTaskWaitWake()
697
724
  );
698
725
  try {
699
726
  const { result, session } = await runtime.ask(userText, {
@@ -10,7 +10,6 @@
10
10
  * CLI route passed here.
11
11
  */
12
12
  import { readCachedOAuthUsageSnapshot } from '../runtime/agent/orchestrator/providers/oauth-usage.mjs';
13
- import { readCachedOpenCodeGoUsageSnapshot } from '../runtime/agent/orchestrator/providers/opencode-go-usage.mjs';
14
13
  import { buildGatewayLimits } from '../runtime/agent/orchestrator/providers/statusline-route-meta.mjs';
15
14
  import { formatGatewayLimitSegments, loadGatewayStatus } from '../vendor/statusline/bin/statusline-route.mjs';
16
15
  import { createSessionStats } from './session-stats.mjs';
@@ -614,14 +613,11 @@ function refreshFallbackQuotaStatus(cacheKey, normalizedProvider, model) {
614
613
  // the route reports nothing worth a segment.
615
614
  function fallbackQuotaValue(routeInfo, normalizedProvider) {
616
615
  let usageSnapshot = null;
617
- if (normalizedProvider === 'opencode-go') {
618
- usageSnapshot = readCachedOpenCodeGoUsageSnapshot();
619
- } else if (normalizedProvider.includes('oauth')) {
616
+ if (normalizedProvider.includes('oauth')) {
620
617
  try {
621
618
  usageSnapshot = readCachedOAuthUsageSnapshot(routeInfo, { allowStale: true });
622
619
  } catch {}
623
620
  }
624
- if (normalizedProvider === 'opencode-go' && !usageSnapshot) return null;
625
621
  // Boot guard: do not render previous-launch usage before the current
626
622
  // runtime has captured at least one snapshot. Once captured in this
627
623
  // process, keep it visible while idle even if refreshes are delayed.
@@ -647,7 +643,6 @@ function fallbackQuotaValue(routeInfo, normalizedProvider) {
647
643
 
648
644
  function providerKindForQuota(provider) {
649
645
  const p = String(provider || '').toLowerCase();
650
- if (p === 'opencode-go') return 'quota-api';
651
646
  if (p.includes('oauth')) return 'oauth';
652
647
  if (p === 'mixdog-local') return 'local';
653
648
  return 'api';
@@ -279,19 +279,36 @@ function tableCells(line) {
279
279
  // time. Until the delimiter is complete (and has the header's cell count) the
280
280
  // rows are a paragraph of raw pipes, which then re-laid out as a table of a
281
281
  // different height — the reply grew and shrank under a followed transcript.
282
- // Hold both rows back until the table can form in one step.
282
+ // Hold both rows back until the table can form in one step. The head may end
283
+ // a block under paragraph lines (a table directly below its caption line),
284
+ // and a header row needs no leading pipe: such a row is held while it is the
285
+ // block's last line, and with a partial delimiter row below it.
283
286
  function trimPendingTableHead(text) {
284
287
  let offset = 0;
285
288
  for (const blank of text.matchAll(/\n[ \t]*\r?\n/g)) offset = blank.index + blank[0].length;
286
289
  const block = text.slice(offset);
287
290
  const lines = block.split('\n').map((line) => line.replace(/\r$/, ''));
288
- if (lines.length === 0 || lines.length > 2 || !PIPE_ROW.test(lines[0])) return text;
289
- if (lines.length === 2) {
290
- const delimiter = lines[1];
291
- if (!PARTIAL_DELIMITER_ROW.test(delimiter)) return text;
292
- if (DELIMITER_ROW.test(delimiter) && tableCells(delimiter) === tableCells(lines[0])) return text;
291
+ // A row that ended with its newline is still the block's last row: the
292
+ // empty line after it is not a (partial) delimiter row.
293
+ let last = lines.length - 1;
294
+ if (last >= 1 && !lines[last].trim()) last -= 1;
295
+ let head = last;
296
+ if (last >= 1 && PARTIAL_DELIMITER_ROW.test(lines[last]) && hasCellPipe(lines[last - 1])) {
297
+ const delimiter = lines[last];
298
+ if (DELIMITER_ROW.test(delimiter) && tableCells(delimiter) === tableCells(lines[last - 1])) return text;
299
+ head = last - 1;
293
300
  }
294
- return text.slice(0, offset);
301
+ if (!(PIPE_ROW.test(lines[head]) || hasCellPipe(lines[head]))) return text;
302
+ // Rows below a delimiter belong to a table that already formed.
303
+ if (lines.slice(0, head).some((line) => DELIMITER_ROW.test(line))) return text;
304
+ let start = offset;
305
+ for (let index = 0; index < head; index += 1) start += lines[index].length + 1;
306
+ return text.slice(0, start);
307
+ }
308
+
309
+ // A cell separator outside inline code: the line can head a table.
310
+ function hasCellPipe(line) {
311
+ return /(?<!\\)\|/.test(line.replace(INLINE_CODE_SPAN, ''));
295
312
  }
296
313
 
297
314
  export function healStreamingMarkdownTail(text, isPendingLocalPath) {
@@ -113,7 +113,6 @@ function cleanString(value) {
113
113
  function providerKind(provider) {
114
114
  const p = String(provider || '').toLowerCase();
115
115
  if (!p) return 'unknown';
116
- if (p === 'opencode-go') return 'quota-api';
117
116
  if (p.includes('oauth')) return 'oauth';
118
117
  if (p === 'mixdog-local') return 'local';
119
118
  return 'api';
@@ -101,7 +101,6 @@ function cleanBool(value) {
101
101
  function providerKind(provider) {
102
102
  const p = String(provider || '').toLowerCase();
103
103
  if (!p) return 'unknown';
104
- if (p === 'opencode-go') return 'quota-api';
105
104
  if (p.includes('oauth')) return 'oauth';
106
105
  if (p === 'mixdog-local') return 'local';
107
106
  return 'api';
@@ -4,17 +4,13 @@ name: Default
4
4
  description: "Handle tasks as requested."
5
5
  ---
6
6
 
7
- Consult the user and build the work plan together. Explicit read-only requests
8
- proceed immediately. When file edits, state mutation, or delegation are
9
- required, investigate and plan only until the user approves the latest plan. If the
10
- plan leaves the user a choice among clear options, ask it with `ask_user`
11
- before asking for approval.
7
+ An explicit request is the approval within its scope: carry it out, including
8
+ routine supporting steps and delegation, without asking again. Resolve
9
+ discoverable facts by inspection; decide minor details yourself and say which
10
+ you chose. Read-only requests do not authorize changes.
12
11
 
13
- When user input is required, park only the affected work and continue
14
- unaffected approved work. Ask pending questions together once no such work
15
- remains.
16
-
17
- While an approved Goal is active, work inside its objective is already
18
- approved: carry it out without stepwise approval. Reserve questions for scope
19
- outside that objective, including a commit, push, release, deployment, or
20
- payment the user has not requested.
12
+ Ask only for a decision that only the user can make and that materially
13
+ changes the outcome, or for authorization outside the request's scope —
14
+ including a commit, push, release, deployment, or payment the user has not
15
+ requested. When user input is required, park only the affected work, continue
16
+ the rest, and ask pending questions together once no such work remains.