mixdog 0.9.2 → 0.9.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (417) hide show
  1. package/package.json +8 -3
  2. package/scripts/anthropic-maxtokens-test.mjs +119 -0
  3. package/scripts/bench/lead-review-tasks-r3.json +20 -0
  4. package/scripts/bench/lead-review-tasks.json +20 -0
  5. package/scripts/bench/r4-mixed-tasks.json +20 -0
  6. package/scripts/bench/review-tasks.json +20 -0
  7. package/scripts/bench/round-codex.json +114 -0
  8. package/scripts/bench/round-mixdog-lead-r3.json +269 -0
  9. package/scripts/bench/round-mixdog-lead.json +269 -0
  10. package/scripts/bench/round-mixdog.json +126 -0
  11. package/scripts/bench/round-r10-bigsample.json +679 -0
  12. package/scripts/bench/round-r11-codexalign.json +257 -0
  13. package/scripts/bench/round-r4-codex.json +114 -0
  14. package/scripts/bench/round-r4-mixed.json +225 -0
  15. package/scripts/bench/round-r5-gpt-lead.json +259 -0
  16. package/scripts/bench/round-r6-codex.json +114 -0
  17. package/scripts/bench/round-r6-solo.json +257 -0
  18. package/scripts/bench/round-r7-full.json +254 -0
  19. package/scripts/bench/round-r8-fulldefault.json +255 -0
  20. package/scripts/bench-run.mjs +215 -29
  21. package/scripts/build-tui.mjs +13 -1
  22. package/scripts/explore-bench.mjs +124 -0
  23. package/scripts/freevar-smoke.mjs +95 -0
  24. package/scripts/hook-bus-test.mjs +191 -0
  25. package/scripts/internal-comms-bench.mjs +1 -0
  26. package/scripts/internal-comms-smoke.mjs +10 -9
  27. package/scripts/mouse-probe.mjs +45 -0
  28. package/scripts/output-style-bench.mjs +13 -6
  29. package/scripts/output-style-smoke.mjs +4 -4
  30. package/scripts/path-suffix-test.mjs +57 -0
  31. package/scripts/provider-toolcall-test.mjs +7 -3
  32. package/scripts/recall-bench.mjs +207 -0
  33. package/scripts/recall-usecase-cases.json +18 -0
  34. package/scripts/recall-usecase-probe.json +6 -0
  35. package/scripts/session-bench.mjs +152 -6
  36. package/scripts/tool-smoke.mjs +30 -67
  37. package/scripts/tui-render-smoke.mjs +90 -0
  38. package/scripts/webhook-smoke.mjs +208 -0
  39. package/src/agents/debugger/AGENT.md +5 -2
  40. package/src/agents/heavy-worker/AGENT.md +21 -11
  41. package/src/agents/maintainer/AGENT.md +4 -0
  42. package/src/agents/reviewer/AGENT.md +3 -2
  43. package/src/agents/worker/AGENT.md +21 -11
  44. package/src/lib/rules-builder.cjs +4 -0
  45. package/src/mixdog-session-runtime.mjs +933 -3731
  46. package/src/output-styles/default.md +34 -9
  47. package/src/output-styles/{oneline.md → extreme-minimal.md} +5 -4
  48. package/src/output-styles/minimal.md +4 -1
  49. package/src/output-styles/simple.md +22 -7
  50. package/src/repl.mjs +5 -5
  51. package/src/rules/agent/00-common.md +2 -0
  52. package/src/rules/agent/30-explorer.md +8 -11
  53. package/src/rules/lead/lead-brief.md +12 -0
  54. package/src/rules/lead/lead-tool.md +2 -9
  55. package/src/rules/shared/01-tool.md +11 -5
  56. package/src/runtime/agent/orchestrator/agent-runtime/agent-loop-policy.mjs +25 -0
  57. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +100 -23
  58. package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +6 -15
  59. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +362 -0
  60. package/src/runtime/agent/orchestrator/agent-trace-io.mjs +410 -0
  61. package/src/runtime/agent/orchestrator/agent-trace.mjs +16 -735
  62. package/src/runtime/agent/orchestrator/config.mjs +69 -2
  63. package/src/runtime/agent/orchestrator/context/collect.mjs +51 -0
  64. package/src/runtime/agent/orchestrator/mcp/client.mjs +6 -2
  65. package/src/runtime/agent/orchestrator/providers/anthropic-effort.mjs +63 -21
  66. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +93 -0
  67. package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +209 -0
  68. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +489 -0
  69. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +97 -1343
  70. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +607 -0
  71. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +78 -10
  72. package/src/runtime/agent/orchestrator/providers/api-usage.mjs +1 -13
  73. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +81 -0
  74. package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +248 -0
  75. package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +303 -0
  76. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +505 -0
  77. package/src/runtime/agent/orchestrator/providers/gemini.mjs +44 -1014
  78. package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +18 -4
  79. package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +32 -0
  80. package/src/runtime/agent/orchestrator/providers/model-catalog.mjs +86 -11
  81. package/src/runtime/agent/orchestrator/providers/model-list-sanitize.mjs +348 -0
  82. package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +54 -20
  83. package/src/runtime/agent/orchestrator/providers/openai-codex-model.mjs +108 -0
  84. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +19 -12
  85. package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +58 -0
  86. package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +368 -0
  87. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +760 -0
  88. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +41 -1142
  89. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +732 -0
  90. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +193 -0
  91. package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +303 -2119
  92. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +140 -995
  93. package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +227 -0
  94. package/src/runtime/agent/orchestrator/providers/openai-ws-events.mjs +67 -0
  95. package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +436 -0
  96. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +1105 -0
  97. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +2 -1
  98. package/src/runtime/agent/orchestrator/providers/opencode-go-usage.mjs +38 -12
  99. package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +7 -8
  100. package/src/runtime/agent/orchestrator/session/compact/budget.mjs +288 -0
  101. package/src/runtime/agent/orchestrator/session/compact/constants.mjs +85 -0
  102. package/src/runtime/agent/orchestrator/session/compact/engine.mjs +749 -0
  103. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +82 -0
  104. package/src/runtime/agent/orchestrator/session/compact/summary-schema.mjs +315 -0
  105. package/src/runtime/agent/orchestrator/session/compact/summary.mjs +643 -0
  106. package/src/runtime/agent/orchestrator/session/compact/text-utils.mjs +326 -0
  107. package/src/runtime/agent/orchestrator/session/compact.mjs +40 -2282
  108. package/src/runtime/agent/orchestrator/session/loop/compact-debug.mjs +28 -0
  109. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +274 -0
  110. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +61 -0
  111. package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +38 -0
  112. package/src/runtime/agent/orchestrator/session/loop/env.mjs +14 -0
  113. package/src/runtime/agent/orchestrator/session/loop/hidden-agents.mjs +21 -0
  114. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +47 -0
  115. package/src/runtime/agent/orchestrator/session/loop/recall-fasttrack.mjs +182 -0
  116. package/src/runtime/agent/orchestrator/session/loop/steering-ladder.mjs +173 -0
  117. package/src/runtime/agent/orchestrator/session/loop/steering.mjs +63 -0
  118. package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +100 -0
  119. package/src/runtime/agent/orchestrator/session/loop/termination.mjs +58 -0
  120. package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +52 -0
  121. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +239 -0
  122. package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +218 -0
  123. package/src/runtime/agent/orchestrator/session/loop/transcript-repair.mjs +101 -0
  124. package/src/runtime/agent/orchestrator/session/loop/usage.mjs +35 -0
  125. package/src/runtime/agent/orchestrator/session/loop.mjs +409 -1304
  126. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +471 -0
  127. package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +230 -0
  128. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +235 -0
  129. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +149 -0
  130. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +155 -0
  131. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +406 -0
  132. package/src/runtime/agent/orchestrator/session/manager/status-telemetry.mjs +80 -0
  133. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +303 -0
  134. package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +210 -0
  135. package/src/runtime/agent/orchestrator/session/manager.mjs +226 -2114
  136. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +189 -0
  137. package/src/runtime/agent/orchestrator/session/store.mjs +74 -179
  138. package/src/runtime/agent/orchestrator/stall-policy.mjs +3 -3
  139. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +70 -20
  140. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +22 -2
  141. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +33 -42
  142. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +241 -0
  143. package/src/runtime/agent/orchestrator/tools/builtin/fuzzy-match.mjs +1 -1
  144. package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +40 -0
  145. package/src/runtime/agent/orchestrator/tools/builtin/path-diagnostics.mjs +42 -2
  146. package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +1 -1
  147. package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +11 -4
  148. package/src/runtime/agent/orchestrator/tools/builtin/rg-runner.mjs +29 -0
  149. package/src/runtime/agent/orchestrator/tools/builtin/search-builders.mjs +8 -0
  150. package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +126 -0
  151. package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +81 -87
  152. package/src/runtime/agent/orchestrator/tools/builtin/shell-job-paths.mjs +161 -0
  153. package/src/runtime/agent/orchestrator/tools/builtin/shell-job-process.mjs +108 -0
  154. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +78 -304
  155. package/src/runtime/agent/orchestrator/tools/builtin.mjs +11 -6
  156. package/src/runtime/agent/orchestrator/tools/code-graph/build.mjs +303 -0
  157. package/src/runtime/agent/orchestrator/tools/code-graph/constants.mjs +43 -0
  158. package/src/runtime/agent/orchestrator/tools/code-graph/disk-cache.mjs +382 -0
  159. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +551 -0
  160. package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary.mjs +295 -0
  161. package/src/runtime/agent/orchestrator/tools/code-graph/graph-model.mjs +158 -0
  162. package/src/runtime/agent/orchestrator/tools/code-graph/keyword-match.mjs +82 -0
  163. package/src/runtime/agent/orchestrator/tools/code-graph/lang-predicates.mjs +128 -0
  164. package/src/runtime/agent/orchestrator/tools/code-graph/memory-cache.mjs +66 -0
  165. package/src/runtime/agent/orchestrator/tools/code-graph/project-root.mjs +44 -0
  166. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +1080 -0
  167. package/src/runtime/agent/orchestrator/tools/code-graph/source-access.mjs +81 -0
  168. package/src/runtime/agent/orchestrator/tools/code-graph/span.mjs +19 -0
  169. package/src/runtime/agent/orchestrator/tools/code-graph/symbol-index.mjs +280 -0
  170. package/src/runtime/agent/orchestrator/tools/code-graph/text-columns.mjs +45 -0
  171. package/src/runtime/agent/orchestrator/tools/code-graph/text-mask.mjs +347 -0
  172. package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +6 -6
  173. package/src/runtime/agent/orchestrator/tools/code-graph.mjs +36 -4277
  174. package/src/runtime/agent/orchestrator/tools/graph-binary-fetcher.mjs +6 -3
  175. package/src/runtime/agent/orchestrator/tools/patch/constants.mjs +9 -0
  176. package/src/runtime/agent/orchestrator/tools/patch/dispatch.mjs +171 -0
  177. package/src/runtime/agent/orchestrator/tools/patch/matcher.mjs +471 -0
  178. package/src/runtime/agent/orchestrator/tools/patch/native-server.mjs +436 -0
  179. package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +342 -0
  180. package/src/runtime/agent/orchestrator/tools/patch/parsing.mjs +359 -0
  181. package/src/runtime/agent/orchestrator/tools/patch/paths.mjs +340 -0
  182. package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +643 -0
  183. package/src/runtime/agent/orchestrator/tools/patch.mjs +36 -2959
  184. package/src/runtime/agent/orchestrator/tools/progress-message.mjs +1 -23
  185. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +10 -74
  186. package/src/runtime/agent/orchestrator/tools/shell-powershell.mjs +77 -0
  187. package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +2 -4
  188. package/src/runtime/agent/orchestrator/tools/shell-state.mjs +154 -0
  189. package/src/runtime/channels/backends/discord-access.mjs +32 -0
  190. package/src/runtime/channels/backends/discord-attachments.mjs +65 -0
  191. package/src/runtime/channels/backends/discord-gateway.mjs +233 -0
  192. package/src/runtime/channels/backends/discord.mjs +12 -292
  193. package/src/runtime/channels/index.mjs +241 -894
  194. package/src/runtime/channels/lib/backend-dispatch.mjs +44 -0
  195. package/src/runtime/channels/lib/boot-profile.mjs +23 -0
  196. package/src/runtime/channels/lib/crash-log.mjs +106 -0
  197. package/src/runtime/channels/lib/event-pipeline.mjs +18 -1
  198. package/src/runtime/channels/lib/event-queue.mjs +63 -4
  199. package/src/runtime/channels/lib/inbound-routing.mjs +111 -0
  200. package/src/runtime/channels/lib/index-drop-trace.mjs +72 -0
  201. package/src/runtime/channels/lib/output-forwarder.mjs +9 -1
  202. package/src/runtime/channels/lib/owner-heartbeat.mjs +75 -0
  203. package/src/runtime/channels/lib/parent-bridge.mjs +88 -0
  204. package/src/runtime/channels/lib/runtime-paths.mjs +14 -4
  205. package/src/runtime/channels/lib/session-discovery.mjs +56 -4
  206. package/src/runtime/channels/lib/telegram-format.mjs +19 -22
  207. package/src/runtime/channels/lib/tool-dispatch.mjs +158 -0
  208. package/src/runtime/channels/lib/tool-format.mjs +1 -1
  209. package/src/runtime/channels/lib/transcript-discovery.mjs +4 -4
  210. package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +6 -3
  211. package/src/runtime/channels/lib/voice-transcription.mjs +179 -0
  212. package/src/runtime/channels/lib/webhook/deliveries.mjs +312 -0
  213. package/src/runtime/channels/lib/webhook/log.mjs +42 -0
  214. package/src/runtime/channels/lib/webhook/ngrok.mjs +181 -0
  215. package/src/runtime/channels/lib/webhook/signature.mjs +60 -0
  216. package/src/runtime/channels/lib/webhook.mjs +36 -570
  217. package/src/runtime/channels/lib/whisper-language.mjs +42 -0
  218. package/src/runtime/channels/tool-defs.mjs +11 -130
  219. package/src/runtime/memory/index.mjs +258 -2050
  220. package/src/runtime/memory/lib/core-memory-store.mjs +351 -1
  221. package/src/runtime/memory/lib/cycle-llm-adapters.mjs +58 -0
  222. package/src/runtime/memory/lib/cycle-scheduler.mjs +497 -0
  223. package/src/runtime/memory/lib/cycle-signatures.mjs +34 -0
  224. package/src/runtime/memory/lib/embedding-warmup.mjs +58 -0
  225. package/src/runtime/memory/lib/http-wire.mjs +57 -0
  226. package/src/runtime/memory/lib/memory-config-flags.mjs +91 -0
  227. package/src/runtime/memory/lib/memory-cycle.mjs +1 -1
  228. package/src/runtime/memory/lib/memory-cycle2-gate.mjs +515 -0
  229. package/src/runtime/memory/lib/memory-cycle2-mutations.mjs +324 -0
  230. package/src/runtime/memory/lib/memory-cycle2-shared.mjs +18 -0
  231. package/src/runtime/memory/lib/memory-cycle2.mjs +72 -837
  232. package/src/runtime/memory/lib/memory-embed.mjs +149 -0
  233. package/src/runtime/memory/lib/memory-process-lock.mjs +162 -0
  234. package/src/runtime/memory/lib/memory-recall-scope-filter.mjs +24 -0
  235. package/src/runtime/memory/lib/memory-recall-store.mjs +22 -2
  236. package/src/runtime/memory/lib/memory-retrievers.mjs +8 -0
  237. package/src/runtime/memory/lib/memory.mjs +20 -0
  238. package/src/runtime/memory/lib/pg/supervisor.mjs +1 -1
  239. package/src/runtime/memory/lib/promotion-fingerprint.mjs +50 -0
  240. package/src/runtime/memory/lib/query-handlers.mjs +780 -0
  241. package/src/runtime/memory/lib/recall-format.mjs +238 -0
  242. package/src/runtime/memory/lib/runtime-fetcher.mjs +8 -3
  243. package/src/runtime/memory/lib/transcript-ingest.mjs +425 -0
  244. package/src/runtime/memory/tool-defs.mjs +6 -14
  245. package/src/runtime/search/lib/http-fetch.mjs +274 -0
  246. package/src/runtime/search/lib/ssrf-guard.mjs +333 -0
  247. package/src/runtime/search/lib/web-tools.mjs +24 -602
  248. package/src/runtime/shared/abort-controller.mjs +1 -1
  249. package/src/runtime/shared/atomic-file.mjs +26 -1
  250. package/src/runtime/shared/background-tasks.mjs +2 -3
  251. package/src/runtime/shared/buffered-appender.mjs +149 -0
  252. package/src/runtime/shared/launcher-control.mjs +2 -2
  253. package/src/runtime/shared/task-notification-envelope.mjs +98 -0
  254. package/src/runtime/shared/tool-execution-contract.mjs +2 -2
  255. package/src/runtime/shared/tool-primitives.mjs +308 -0
  256. package/src/runtime/shared/tool-result-summary.mjs +515 -0
  257. package/src/runtime/shared/tool-surface.mjs +80 -898
  258. package/src/runtime/shared/transcript-writer.mjs +52 -2
  259. package/src/runtime/shared/update-checker.mjs +7 -4
  260. package/src/session-runtime/config-helpers.mjs +291 -0
  261. package/src/session-runtime/config-lifecycle.mjs +232 -0
  262. package/src/session-runtime/cwd-plugins.mjs +226 -0
  263. package/src/session-runtime/effort.mjs +128 -0
  264. package/src/session-runtime/fs-utils.mjs +10 -0
  265. package/src/session-runtime/mcp-glue.mjs +177 -0
  266. package/src/session-runtime/model-capabilities.mjs +130 -0
  267. package/src/session-runtime/model-recency.mjs +111 -0
  268. package/src/session-runtime/native-search.mjs +247 -0
  269. package/src/session-runtime/output-styles.mjs +126 -0
  270. package/src/session-runtime/plugin-mcp.mjs +114 -0
  271. package/src/session-runtime/prewarm.mjs +142 -0
  272. package/src/session-runtime/provider-models.mjs +278 -0
  273. package/src/session-runtime/provider-usage.mjs +120 -0
  274. package/src/session-runtime/quick-model-rows.mjs +170 -0
  275. package/src/session-runtime/quick-search-models.mjs +46 -0
  276. package/src/session-runtime/session-hooks.mjs +93 -0
  277. package/src/session-runtime/session-text.mjs +100 -0
  278. package/src/session-runtime/settings-api.mjs +319 -0
  279. package/src/session-runtime/statusline-route.mjs +35 -0
  280. package/src/session-runtime/tool-catalog.mjs +720 -0
  281. package/src/session-runtime/tool-defs.mjs +84 -0
  282. package/src/session-runtime/warmup-schedulers.mjs +201 -0
  283. package/src/session-runtime/workflow.mjs +358 -0
  284. package/src/standalone/agent-tool/helpers.mjs +237 -0
  285. package/src/standalone/agent-tool/notify.mjs +107 -0
  286. package/src/standalone/agent-tool/provider-init.mjs +143 -0
  287. package/src/standalone/agent-tool/render.mjs +152 -0
  288. package/src/standalone/agent-tool/tool-def.mjs +55 -0
  289. package/src/standalone/agent-tool.mjs +155 -677
  290. package/src/standalone/channel-worker.mjs +7 -9
  291. package/src/standalone/explore-tool.mjs +40 -12
  292. package/src/standalone/hook-bus/config.mjs +207 -0
  293. package/src/standalone/hook-bus/constants.mjs +90 -0
  294. package/src/standalone/hook-bus/handlers.mjs +481 -0
  295. package/src/standalone/hook-bus/payload.mjs +31 -0
  296. package/src/standalone/hook-bus/rules.mjs +77 -0
  297. package/src/standalone/hook-bus.mjs +110 -746
  298. package/src/standalone/memory-runtime-proxy.mjs +7 -0
  299. package/src/standalone/opencode-go-login.mjs +125 -0
  300. package/src/standalone/provider-admin.mjs +15 -19
  301. package/src/standalone/usage-dashboard.mjs +3 -1
  302. package/src/tui/App.jsx +1163 -7571
  303. package/src/tui/app/app-format.mjs +206 -0
  304. package/src/tui/app/channel-pickers.mjs +510 -0
  305. package/src/tui/app/clipboard.mjs +67 -0
  306. package/src/tui/app/core-memory-picker.mjs +210 -0
  307. package/src/tui/app/extension-pickers.mjs +506 -0
  308. package/src/tui/app/input-parsers.mjs +193 -0
  309. package/src/tui/app/maintenance-pickers.mjs +324 -0
  310. package/src/tui/app/model-options.mjs +330 -0
  311. package/src/tui/app/model-picker.mjs +365 -0
  312. package/src/tui/app/onboarding-steps.mjs +400 -0
  313. package/src/tui/app/project-picker.mjs +247 -0
  314. package/src/tui/app/provider-setup-picker.mjs +580 -0
  315. package/src/tui/app/resume-picker.mjs +55 -0
  316. package/src/tui/app/route-pickers.mjs +419 -0
  317. package/src/tui/app/settings-picker.mjs +490 -0
  318. package/src/tui/app/slash-commands.mjs +101 -0
  319. package/src/tui/app/slash-dispatch.mjs +427 -0
  320. package/src/tui/app/text-layout.mjs +46 -0
  321. package/src/tui/app/theme-effort-pickers.mjs +154 -0
  322. package/src/tui/app/transcript-window.mjs +671 -0
  323. package/src/tui/app/use-mouse-input.mjs +460 -0
  324. package/src/tui/app/use-prompt-handlers.mjs +310 -0
  325. package/src/tui/app/use-transcript-scroll.mjs +510 -0
  326. package/src/tui/app/use-transcript-window.mjs +589 -0
  327. package/src/tui/components/ConfirmBar.jsx +1 -1
  328. package/src/tui/components/Picker.jsx +32 -4
  329. package/src/tui/components/PromptInput.jsx +259 -80
  330. package/src/tui/components/SlashCommandPalette.jsx +8 -1
  331. package/src/tui/components/StatusLine.jsx +63 -12
  332. package/src/tui/components/TextEntryPanel.jsx +11 -0
  333. package/src/tui/components/ToolExecution.jsx +56 -588
  334. package/src/tui/components/TranscriptItem.jsx +105 -0
  335. package/src/tui/components/UsagePanel.jsx +18 -4
  336. package/src/tui/components/prompt-input/edit-helpers.mjs +72 -0
  337. package/src/tui/components/prompt-input/voice-indicator.mjs +39 -0
  338. package/src/tui/components/tool-execution/ResultBody.jsx +56 -0
  339. package/src/tui/components/tool-execution/surface-detail.mjs +405 -0
  340. package/src/tui/components/tool-execution/text-format.mjs +161 -0
  341. package/src/tui/components/tool-output-format.mjs +2 -2
  342. package/src/tui/display-width.mjs +20 -3
  343. package/src/tui/dist/index.mjs +18034 -17188
  344. package/src/tui/engine/agent-envelope.mjs +296 -0
  345. package/src/tui/engine/agent-job-feed.mjs +133 -0
  346. package/src/tui/engine/boot-profile.mjs +21 -0
  347. package/src/tui/engine/labels.mjs +67 -0
  348. package/src/tui/engine/notice-text.mjs +112 -0
  349. package/src/tui/engine/notification-plan.mjs +76 -0
  350. package/src/tui/engine/queue-helpers.mjs +161 -0
  351. package/src/tui/engine/render-timing.mjs +17 -0
  352. package/src/tui/engine/session-stats.mjs +46 -0
  353. package/src/tui/engine/tool-approval.mjs +94 -0
  354. package/src/tui/engine/tool-call-fields.mjs +23 -0
  355. package/src/tui/engine/tool-card-results.mjs +234 -0
  356. package/src/tui/engine/tool-result-status.mjs +135 -0
  357. package/src/tui/engine/tool-result-text.mjs +126 -0
  358. package/src/tui/engine.mjs +405 -1385
  359. package/src/tui/figures.mjs +5 -0
  360. package/src/tui/index.jsx +105 -0
  361. package/src/tui/input-editing.mjs +60 -10
  362. package/src/tui/keyboard-protocol.mjs +2 -2
  363. package/src/tui/lib/voice-recorder.mjs +35 -19
  364. package/src/tui/markdown/format-token.mjs +11 -9
  365. package/src/tui/paste-attachments.mjs +38 -0
  366. package/src/tui/statusline-ansi-bridge.mjs +11 -3
  367. package/src/tui/theme.mjs +6 -0
  368. package/src/tui/themes/base.mjs +2 -2
  369. package/src/tui/themes/kanagawa.mjs +4 -4
  370. package/src/tui/themes/teal.mjs +4 -5
  371. package/src/tui/themes/utils.mjs +1 -1
  372. package/src/ui/statusline-agents.mjs +213 -0
  373. package/src/ui/statusline-format.mjs +146 -0
  374. package/src/ui/statusline-segments.mjs +148 -0
  375. package/src/ui/statusline.mjs +77 -462
  376. package/src/ui/tool-card.mjs +0 -1
  377. package/src/vendor/statusline/bin/statusline-route.mjs +15 -2
  378. package/src/workflows/default/WORKFLOW.md +16 -9
  379. package/src/workflows/sequential/WORKFLOW.md +16 -11
  380. package/src/workflows/solo/WORKFLOW.md +5 -1
  381. package/vendor/ink/build/display-width.js +19 -3
  382. package/vendor/ink/build/ink.js +103 -6
  383. package/vendor/ink/build/log-update.js +17 -3
  384. package/vendor/ink/build/wrap-text.js +125 -0
  385. package/scripts/_test-folder-dialog.mjs +0 -30
  386. package/scripts/fix-brief-fn.mjs +0 -35
  387. package/scripts/fix-format-tool-surface.mjs +0 -24
  388. package/scripts/fix-tool-exec-visible.mjs +0 -42
  389. package/scripts/patch-agent-brief.mjs +0 -48
  390. package/scripts/patch-app.mjs +0 -21
  391. package/scripts/patch-app2.mjs +0 -18
  392. package/scripts/patch-dist-brief.mjs +0 -96
  393. package/scripts/patch-tool-exec.mjs +0 -70
  394. package/src/examples/schedules/SCHEDULE.example.md +0 -32
  395. package/src/examples/webhooks/WEBHOOK.example.md +0 -40
  396. package/src/runtime/agent/orchestrator/session/manager.reactive-persist.test.mjs +0 -107
  397. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.test.mjs +0 -143
  398. package/src/runtime/agent/orchestrator/tools/builtin/diagnostics-tool.mjs +0 -285
  399. package/src/runtime/agent/orchestrator/tools/builtin/open-config-tool.mjs +0 -26
  400. package/src/runtime/shared/channel-notification-routing.test.mjs +0 -45
  401. package/src/runtime/shared/tool-execution-contract.test.mjs +0 -183
  402. package/src/standalone/agent-task-status.test.mjs +0 -76
  403. package/src/tui/components/tool-output-format.test.mjs +0 -399
  404. package/src/tui/display-width.test.mjs +0 -35
  405. package/src/tui/engine-runtime-notification.test.mjs +0 -115
  406. package/src/tui/engine-tool-result-text.test.mjs +0 -75
  407. package/src/tui/markdown/format-token.test.mjs +0 -354
  408. package/src/tui/markdown/render-ansi.test.mjs +0 -108
  409. package/src/tui/markdown/stream-fence.test.mjs +0 -26
  410. package/src/tui/markdown/streaming-markdown.test.mjs +0 -70
  411. package/src/tui/prompt-history-store.test.mjs +0 -52
  412. package/src/tui/statusline-ansi-bridge.test.mjs +0 -159
  413. package/src/tui/transcript-tool-failures.test.mjs +0 -111
  414. package/src/ui/markdown.test.mjs +0 -70
  415. package/src/ui/statusline-context-label.test.mjs +0 -15
  416. package/src/vendor/statusline/bin/statusline-lib.mjs +0 -186
  417. package/src/vendor/statusline/bin/statusline-route.test.mjs +0 -80
@@ -0,0 +1,142 @@
1
+ // Background prewarm/start schedulers, extracted from
2
+ // mixdog-session-runtime.mjs. Dependency-injected factory: timer handles live
3
+ // in a caller-owned `timers` object (so the facade's clearTimeout teardown
4
+ // still sees them) and all state reads go through supplied accessors. Byte-for-
5
+ // byte identical behavior; only grouping changes.
6
+ import { performance } from 'node:perf_hooks';
7
+
8
+ export function createPrewarmSchedulers({
9
+ timers,
10
+ bootProfile,
11
+ getCurrentCwd,
12
+ isCloseRequested,
13
+ getActiveTurnCount,
14
+ getSessionCreatePromise,
15
+ getSession,
16
+ isRemoteEnabled,
17
+ channelsEnabled,
18
+ getCodeGraphModule,
19
+ createCurrentSession,
20
+ channels,
21
+ envFlag,
22
+ delays,
23
+ flags,
24
+ state,
25
+ }) {
26
+ const { codeGraphPrewarmDelayMs, channelStartDelayMs, sessionPrewarmDelayMs, backgroundBusyRetryMs } = delays;
27
+ const { codeGraphPrewarmEnabled, sessionPrewarmEnabled } = flags;
28
+
29
+ function scheduleCodeGraphPrewarm(delayMs = codeGraphPrewarmDelayMs, reason = 'cwd') {
30
+ if (!codeGraphPrewarmEnabled) {
31
+ bootProfile('code-graph:prewarm-skipped', { reason: 'disabled' });
32
+ return;
33
+ }
34
+ if (isCloseRequested()) return;
35
+ state.codeGraphPrewarmQueuedCwd = getCurrentCwd();
36
+ if (timers.codeGraphPrewarmTimer) return;
37
+ timers.codeGraphPrewarmTimer = setTimeout(() => {
38
+ timers.codeGraphPrewarmTimer = null;
39
+ if (isCloseRequested()) return;
40
+ if (getActiveTurnCount() > 0 || getSessionCreatePromise()) {
41
+ bootProfile('code-graph:prewarm-deferred', { reason: getActiveTurnCount() > 0 ? 'turn-active' : 'session-create' });
42
+ scheduleCodeGraphPrewarm(backgroundBusyRetryMs, 'busy');
43
+ return;
44
+ }
45
+ if (state.codeGraphPrewarmInFlight) {
46
+ bootProfile('code-graph:prewarm-deferred', { reason: 'in-flight' });
47
+ scheduleCodeGraphPrewarm(backgroundBusyRetryMs, 'in-flight');
48
+ return;
49
+ }
50
+ const prewarmCwd = state.codeGraphPrewarmQueuedCwd || getCurrentCwd();
51
+ state.codeGraphPrewarmQueuedCwd = '';
52
+ state.codeGraphPrewarmInFlight = true;
53
+ const startedAt = performance.now();
54
+ bootProfile('code-graph:prewarm:start', { cwd: prewarmCwd, reason });
55
+ void getCodeGraphModule()
56
+ .then((mod) => {
57
+ if (typeof mod?.prewarmCodeGraphIfProject !== 'function') return false;
58
+ return mod.prewarmCodeGraphIfProject(prewarmCwd);
59
+ })
60
+ .then((scheduled) => bootProfile(scheduled ? 'code-graph:prewarm:scheduled' : 'code-graph:prewarm:no-project', {
61
+ cwd: prewarmCwd,
62
+ ms: (performance.now() - startedAt).toFixed(1),
63
+ }))
64
+ .catch((error) => bootProfile('code-graph:prewarm:failed', {
65
+ cwd: prewarmCwd,
66
+ ms: (performance.now() - startedAt).toFixed(1),
67
+ error: error?.message || String(error),
68
+ }))
69
+ .finally(() => {
70
+ state.codeGraphPrewarmInFlight = false;
71
+ if (state.codeGraphPrewarmQueuedCwd && !isCloseRequested()) {
72
+ scheduleCodeGraphPrewarm(backgroundBusyRetryMs, 'queued');
73
+ }
74
+ });
75
+ }, delayMs);
76
+ timers.codeGraphPrewarmTimer.unref?.();
77
+ }
78
+
79
+ function scheduleLeadSessionPrewarm() {
80
+ if (!sessionPrewarmEnabled) {
81
+ bootProfile('session:prewarm-skipped');
82
+ return;
83
+ }
84
+ const timer = setTimeout(() => {
85
+ if (isCloseRequested() || getSession()?.id || getSessionCreatePromise() || getActiveTurnCount() > 0) return;
86
+ void createCurrentSession('prewarm')
87
+ .then(() => bootProfile('session:prewarm:ready'))
88
+ .catch((error) => bootProfile('session:prewarm:failed', { error: error?.message || String(error) }));
89
+ }, sessionPrewarmDelayMs);
90
+ timer.unref?.();
91
+ }
92
+
93
+ function invokeChannelStart() {
94
+ if (state.channelStartPromise) return state.channelStartPromise;
95
+ const startedAt = performance.now();
96
+ bootProfile('channels:start:begin');
97
+ state.channelStartPromise = channels.start()
98
+ .then(() => bootProfile('channels:start:ready', { ms: (performance.now() - startedAt).toFixed(1) }))
99
+ .catch((error) => bootProfile('channels:start:failed', {
100
+ ms: (performance.now() - startedAt).toFixed(1),
101
+ error: error?.message || String(error),
102
+ }))
103
+ .finally(() => {
104
+ state.channelStartPromise = null;
105
+ });
106
+ return state.channelStartPromise;
107
+ }
108
+
109
+ function scheduleChannelStart(delayMs = channelStartDelayMs) {
110
+ if (envFlag('MIXDOG_DISABLE_CHANNEL_START')) {
111
+ bootProfile('channels:start-skipped');
112
+ return;
113
+ }
114
+ if (!channelsEnabled()) {
115
+ bootProfile('channels:start-disabled');
116
+ return;
117
+ }
118
+ if (timers.channelStartTimer || state.channelStartPromise || isCloseRequested()) return;
119
+ bootProfile('channels:start-scheduled', { delayMs });
120
+ timers.channelStartTimer = setTimeout(() => {
121
+ timers.channelStartTimer = null;
122
+ if (isCloseRequested()) return;
123
+ // A deferred start may straddle a stopRemote(); re-check before booting so
124
+ // a turned-off session neither starts channels nor keeps rescheduling.
125
+ if (!isRemoteEnabled()) return;
126
+ if (getActiveTurnCount() > 0 || getSessionCreatePromise()) {
127
+ bootProfile('channels:start-deferred', { reason: getActiveTurnCount() > 0 ? 'turn-active' : 'session-create' });
128
+ scheduleChannelStart(backgroundBusyRetryMs);
129
+ return;
130
+ }
131
+ void invokeChannelStart();
132
+ }, delayMs);
133
+ timers.channelStartTimer.unref?.();
134
+ }
135
+
136
+ return {
137
+ scheduleCodeGraphPrewarm,
138
+ scheduleLeadSessionPrewarm,
139
+ invokeChannelStart,
140
+ scheduleChannelStart,
141
+ };
142
+ }
@@ -0,0 +1,278 @@
1
+ // Provider/search model catalog + cache glue, extracted from
2
+ // mixdog-session-runtime.mjs. Dependency-injected factory following the
3
+ // createWarmupSchedulers/createNativeSearch pattern: mutable cache state lives
4
+ // in a caller-owned `caches` object (so the facade's invalidateProviderCaches
5
+ // teardown still sees the same references) and all route/config/registry reads
6
+ // go through supplied accessors so live-binding is preserved (no stale
7
+ // snapshot of route/config/searchRoute).
8
+ import { clean } from './session-text.mjs';
9
+ import { effortItemsFor } from './effort.mjs';
10
+ import { fastCapableFor, fastPreferenceFor } from './model-capabilities.mjs';
11
+ import { modelSettingsFor } from './config-helpers.mjs';
12
+ import { isSelectableLlmModel } from './model-recency.mjs';
13
+
14
+ export function createProviderModels({
15
+ caches,
16
+ modelMetaByRoute,
17
+ getRoute,
18
+ getConfig,
19
+ getReg,
20
+ searchCapableFor,
21
+ sortProviderModelsRaw,
22
+ providerModelCacheRowRaw,
23
+ normalizeSearchProviderId,
24
+ isSearchCapableProvider,
25
+ ensureFullConfig,
26
+ ensureProvidersReady,
27
+ bootProfile,
28
+ scheduleProviderModelWarmup,
29
+ // Quick-row helpers wired in after createQuickModelRows resolves.
30
+ quickHelpers,
31
+ }) {
32
+ const config = () => getConfig();
33
+ const route = () => getRoute();
34
+ const reg = () => getReg();
35
+
36
+ function modelMetaKey(providerId, modelId) {
37
+ return `${clean(providerId)}\n${clean(modelId)}`;
38
+ }
39
+
40
+ async function lookupModelMeta(providerId, modelId, { allowFetch = false } = {}) {
41
+ const key = modelMetaKey(providerId, modelId);
42
+ if (modelMetaByRoute.has(key)) return modelMetaByRoute.get(key);
43
+ const providerImpl = reg().getProvider(providerId);
44
+ if (!providerImpl || typeof providerImpl.listModels !== 'function') {
45
+ const fallback = { id: modelId, provider: providerId };
46
+ modelMetaByRoute.set(key, fallback);
47
+ return fallback;
48
+ }
49
+ if (typeof providerImpl.getCachedModelInfo === 'function') {
50
+ const cached = providerImpl.getCachedModelInfo(modelId);
51
+ if (cached) {
52
+ const meta = { ...cached, id: cached.id || modelId, provider: providerId };
53
+ modelMetaByRoute.set(key, meta);
54
+ return meta;
55
+ }
56
+ }
57
+ if (!allowFetch) {
58
+ const fallback = { id: modelId, provider: providerId };
59
+ modelMetaByRoute.set(key, fallback);
60
+ scheduleProviderModelWarmup();
61
+ return fallback;
62
+ }
63
+ try {
64
+ const models = await providerImpl.listModels();
65
+ const found = Array.isArray(models) ? models.find((m) => m?.id === modelId) : null;
66
+ const meta = found || { id: modelId, provider: providerId };
67
+ modelMetaByRoute.set(key, meta);
68
+ return meta;
69
+ } catch {
70
+ const fallback = { id: modelId, provider: providerId };
71
+ modelMetaByRoute.set(key, fallback);
72
+ return fallback;
73
+ }
74
+ }
75
+
76
+ function hydrateProviderModelRow(row) {
77
+ const cfg = config();
78
+ return {
79
+ ...row,
80
+ effortOptions: effortItemsFor(row.provider, row, null),
81
+ fastCapable: fastCapableFor(row.provider, row),
82
+ fastPreferred: fastPreferenceFor(cfg, row.provider, row.id),
83
+ savedEffort: modelSettingsFor(cfg, row.provider, row.id).effort || null,
84
+ savedFast: modelSettingsFor(cfg, row.provider, row.id).fast === true,
85
+ };
86
+ }
87
+
88
+ const sortProviderModels = (models) => sortProviderModelsRaw(models, route().provider);
89
+ const providerModelCacheRow = (name, m) => providerModelCacheRowRaw(name, m, searchCapableFor);
90
+
91
+ function providerModelsFromCacheRows(rows) {
92
+ return sortProviderModels((rows || []).map(hydrateProviderModelRow));
93
+ }
94
+
95
+ function enabledSearchProviderConfig() {
96
+ ensureFullConfig();
97
+ const out = {};
98
+ for (const [name, providerConfig] of Object.entries(config().providers || {})) {
99
+ const providerName = normalizeSearchProviderId(name);
100
+ if (!providerConfig?.enabled || !isSearchCapableProvider(providerName)) continue;
101
+ out[providerName] = { ...providerConfig, enabled: true };
102
+ }
103
+ return out;
104
+ }
105
+
106
+ async function loadSearchProviderModelsFresh({ forceRefresh = false } = {}) {
107
+ const searchProviders = enabledSearchProviderConfig();
108
+ const providerNames = Object.keys(searchProviders);
109
+ if (!providerNames.length) return [];
110
+ await ensureProvidersReady(config().providers || {});
111
+ const providerResults = await Promise.all(providerNames.map(async (name) => {
112
+ const provider = reg().getProvider(name);
113
+ if (typeof provider?.listModels !== 'function') return [];
114
+ try {
115
+ let models = null;
116
+ if (forceRefresh && typeof provider._refreshModelCache === 'function') {
117
+ models = await provider._refreshModelCache();
118
+ }
119
+ if (!Array.isArray(models)) {
120
+ models = await provider.listModels();
121
+ }
122
+ if (!Array.isArray(models)) return [];
123
+ const rows = [];
124
+ for (const m of models) {
125
+ if (!m?.id || !isSelectableLlmModel(m)) continue;
126
+ const row = providerModelCacheRow(name, m);
127
+ if (row.supportsWebSearch !== true) continue;
128
+ rows.push({
129
+ ...row,
130
+ provider: normalizeSearchProviderId(row.provider),
131
+ searchCapable: true,
132
+ searchToolType: row.searchToolType || 'web_search',
133
+ });
134
+ modelMetaByRoute.set(modelMetaKey(name, m.id), row);
135
+ }
136
+ return rows;
137
+ } catch {
138
+ // Keep the picker responsive if one search-capable provider has a
139
+ // transient catalog/auth failure.
140
+ return [];
141
+ }
142
+ }));
143
+ const results = [];
144
+ const seen = new Set();
145
+ quickHelpers.addDefaultSearchModel(results, seen);
146
+ for (const row of providerResults.flat()) {
147
+ const key = `${normalizeSearchProviderId(row.provider)}:${row.id}`;
148
+ if (seen.has(key)) continue;
149
+ seen.add(key);
150
+ results.push(row);
151
+ }
152
+ return results;
153
+ }
154
+
155
+ async function loadProviderModelsFresh({ forceRefresh = false } = {}) {
156
+ ensureFullConfig();
157
+ await ensureProvidersReady(config().providers || {});
158
+ const allProviders = [...reg().getAllProviders()];
159
+ const providerResults = await Promise.all(allProviders.map(async ([name, provider]) => {
160
+ if (typeof provider?.listModels !== 'function') return [];
161
+ try {
162
+ let models = null;
163
+ if (forceRefresh && typeof provider._refreshModelCache === 'function') {
164
+ models = await provider._refreshModelCache();
165
+ }
166
+ if (!Array.isArray(models)) {
167
+ models = await provider.listModels();
168
+ }
169
+ if (!Array.isArray(models)) return [];
170
+ const rows = [];
171
+ for (const m of models) {
172
+ if (!m?.id) continue;
173
+ if (!isSelectableLlmModel(m)) continue;
174
+ rows.push(providerModelCacheRow(name, m));
175
+ }
176
+ return rows;
177
+ } catch {
178
+ // Ignore per-provider catalog failures so one bad credential or
179
+ // transient /models error does not hide other authenticated models.
180
+ return [];
181
+ }
182
+ }));
183
+ const results = [];
184
+ const seen = new Set();
185
+ for (const row of providerResults.flat()) {
186
+ const key = `${row.provider}:${row.id}`;
187
+ if (seen.has(key)) continue;
188
+ seen.add(key);
189
+ results.push(row);
190
+ modelMetaByRoute.set(modelMetaKey(row.provider, row.id), row);
191
+ }
192
+ return results;
193
+ }
194
+
195
+ async function collectSearchProviderModels({ force = false } = {}) {
196
+ if (!force && Array.isArray(caches.searchProviderModelsCache.models)) {
197
+ return providerModelsFromCacheRows(quickHelpers.searchRowsWithDefault(caches.searchProviderModelsCache.models));
198
+ }
199
+ if (!force && Array.isArray(caches.providerModelsCache.models)) {
200
+ const rows = quickHelpers.searchRowsWithDefault(quickHelpers.searchModelsFromRows(caches.providerModelsCache.models));
201
+ caches.searchProviderModelsCache = { models: rows, at: Date.now() };
202
+ return providerModelsFromCacheRows(rows);
203
+ }
204
+ if (!force) {
205
+ const rows = quickHelpers.searchRowsWithDefault(quickHelpers.quickSearchProviderModelRows());
206
+ caches.searchProviderModelsCache = { models: rows, at: Date.now() };
207
+ return providerModelsFromCacheRows(rows);
208
+ }
209
+ if (force) {
210
+ const models = await loadSearchProviderModelsFresh({ forceRefresh: true });
211
+ caches.searchProviderModelsCache = { models, at: Date.now() };
212
+ return providerModelsFromCacheRows(models);
213
+ }
214
+ }
215
+
216
+ async function collectProviderModels({ force = false, quick = false } = {}) {
217
+ if (!force && Array.isArray(caches.providerModelsCache.models)) {
218
+ return providerModelsFromCacheRows(caches.providerModelsCache.models);
219
+ }
220
+ if (!force && quick) {
221
+ warmProviderModelCache();
222
+ return quickHelpers.quickProviderModelRows();
223
+ }
224
+ if (force) {
225
+ const seq = ++caches.providerModelsLoadSeq;
226
+ const models = await loadProviderModelsFresh({ forceRefresh: true });
227
+ if (seq === caches.providerModelsLoadSeq) caches.providerModelsCache = { models, at: Date.now() };
228
+ return providerModelsFromCacheRows(models);
229
+ }
230
+ if (!caches.providerModelsPromise) {
231
+ const seq = ++caches.providerModelsLoadSeq;
232
+ caches.providerModelsPromise = loadProviderModelsFresh()
233
+ .then((models) => {
234
+ if (seq === caches.providerModelsLoadSeq) caches.providerModelsCache = { models, at: Date.now() };
235
+ return models;
236
+ })
237
+ .finally(() => {
238
+ caches.providerModelsPromise = null;
239
+ });
240
+ }
241
+ return providerModelsFromCacheRows(await caches.providerModelsPromise);
242
+ }
243
+
244
+ function warmProviderModelCache() {
245
+ if (Array.isArray(caches.providerModelsCache.models) || caches.providerModelsPromise) return caches.providerModelsPromise;
246
+ const seq = ++caches.providerModelsLoadSeq;
247
+ caches.providerModelsPromise = loadProviderModelsFresh()
248
+ .then((models) => {
249
+ if (seq === caches.providerModelsLoadSeq) caches.providerModelsCache = { models, at: Date.now() };
250
+ bootProfile('provider-models:warm-ready', { count: models.length });
251
+ return models;
252
+ })
253
+ .catch((err) => {
254
+ const msg = err instanceof Error ? err.message : String(err);
255
+ bootProfile('provider-models:warm-failed', { error: msg });
256
+ return [];
257
+ })
258
+ .finally(() => {
259
+ caches.providerModelsPromise = null;
260
+ });
261
+ return caches.providerModelsPromise;
262
+ }
263
+
264
+ return {
265
+ modelMetaKey,
266
+ lookupModelMeta,
267
+ hydrateProviderModelRow,
268
+ sortProviderModels,
269
+ providerModelCacheRow,
270
+ providerModelsFromCacheRows,
271
+ enabledSearchProviderConfig,
272
+ loadSearchProviderModelsFresh,
273
+ loadProviderModelsFresh,
274
+ collectSearchProviderModels,
275
+ collectProviderModels,
276
+ warmProviderModelCache,
277
+ };
278
+ }
@@ -0,0 +1,120 @@
1
+ // Provider-setup snapshot + usage-dashboard cache glue, extracted from
2
+ // mixdog-session-runtime.mjs. Dependency-injected factory following the same
3
+ // pattern as createProviderModels: mutable cache state lives in a caller-owned
4
+ // `caches` object (so invalidateProviderCaches still resets the same
5
+ // references) and all config/registry reads flow through supplied accessors so
6
+ // live-binding is preserved.
7
+ import { clean } from './session-text.mjs';
8
+
9
+ export function createProviderUsage({
10
+ caches,
11
+ getConfig,
12
+ getReg,
13
+ displayConfig,
14
+ providerSetup,
15
+ createUsageDashboard,
16
+ fetchOAuthUsageSnapshot,
17
+ isCloseRequested,
18
+ getProviderSetupWarmupTimer,
19
+ scheduleProviderSetupWarmup,
20
+ }) {
21
+ const reg = () => getReg();
22
+
23
+ function refreshStatuslineUsageSnapshot(routeLike = {}) {
24
+ const providerId = clean(routeLike.provider);
25
+ const modelId = clean(routeLike.model);
26
+ if (!providerId || !providerId.includes('oauth')) return;
27
+ const providerObj = reg().getProvider(providerId);
28
+ if (!providerObj) return;
29
+ void fetchOAuthUsageSnapshot({ provider: providerId, model: modelId }, providerObj, (message) => {
30
+ if (process.env.MIXDOG_STATUSLINE_TRACE) {
31
+ try { process.stderr.write(`[statusline] ${message}\n`); } catch {}
32
+ }
33
+ }).catch(() => {});
34
+ }
35
+
36
+ async function cachedProviderSetup({ force = false, quick = false } = {}) {
37
+ if (!force && caches.providerSetupCache.setup) {
38
+ return caches.providerSetupCache.setup;
39
+ }
40
+ if (quick) {
41
+ if (!force && caches.providerSetupQuickCache.setup) {
42
+ return caches.providerSetupQuickCache.setup;
43
+ }
44
+ const setup = await providerSetup(displayConfig(), { detectLocal: false, checkSecrets: false });
45
+ caches.providerSetupQuickCache = { setup, at: Date.now() };
46
+ if (!caches.providerSetupPromise && !getProviderSetupWarmupTimer() && !isCloseRequested()) {
47
+ scheduleProviderSetupWarmup(0);
48
+ }
49
+ return setup;
50
+ }
51
+ if (caches.providerSetupPromise) return await caches.providerSetupPromise;
52
+ caches.providerSetupPromise = providerSetup(displayConfig(), { detectLocal: true })
53
+ .then((setup) => {
54
+ caches.providerSetupCache = { setup, at: Date.now() };
55
+ return setup;
56
+ })
57
+ .finally(() => {
58
+ caches.providerSetupPromise = null;
59
+ });
60
+ return await caches.providerSetupPromise;
61
+ }
62
+
63
+ async function getUsageDashboard(options = {}) {
64
+ const forceSetup = options?.force === true || options?.refresh === true;
65
+ if (!forceSetup && caches.usageDashboardCache.dashboard) {
66
+ const cached = {
67
+ ...caches.usageDashboardCache.dashboard,
68
+ refresh: false,
69
+ checking: false,
70
+ cached: true,
71
+ cachedAt: caches.usageDashboardCache.at,
72
+ };
73
+ if (typeof options?.onUpdate === 'function') {
74
+ try { options.onUpdate(cached); } catch {}
75
+ }
76
+ return cached;
77
+ }
78
+ if (!forceSetup && caches.usageDashboardPromise) return await caches.usageDashboardPromise;
79
+ const quickSetup = options?.quickSetup !== false;
80
+ const getProvider = (providerId) => reg().getProvider(providerId);
81
+ const log = (message) => {
82
+ if (process.env.MIXDOG_USAGE_TRACE) {
83
+ try { process.stderr.write(`[usage] ${message}\n`); } catch {}
84
+ }
85
+ };
86
+ if (quickSetup && typeof options?.onUpdate === 'function') {
87
+ const previewConfig = displayConfig();
88
+ const previewSetup = await cachedProviderSetup({ force: false, quick: true });
89
+ await createUsageDashboard(previewConfig, {
90
+ ...(options || {}),
91
+ preview: true,
92
+ setup: previewSetup,
93
+ getProvider,
94
+ log,
95
+ });
96
+ }
97
+ const buildDashboard = async () => {
98
+ const dashboard = await createUsageDashboard(displayConfig(), {
99
+ ...(options || {}),
100
+ setup: await cachedProviderSetup({ force: forceSetup, quick: false }),
101
+ getProvider,
102
+ log,
103
+ });
104
+ caches.usageDashboardCache = { dashboard, at: Date.now() };
105
+ return dashboard;
106
+ };
107
+ if (forceSetup) return await buildDashboard();
108
+ caches.usageDashboardPromise = buildDashboard()
109
+ .finally(() => {
110
+ caches.usageDashboardPromise = null;
111
+ });
112
+ return await caches.usageDashboardPromise;
113
+ }
114
+
115
+ return {
116
+ refreshStatuslineUsageSnapshot,
117
+ cachedProviderSetup,
118
+ getUsageDashboard,
119
+ };
120
+ }