aicodeman 1.42.0 → 1.44.0

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 (350) hide show
  1. package/README.md +13 -12
  2. package/dist/claude-session-title.d.ts +6 -4
  3. package/dist/claude-session-title.d.ts.map +1 -1
  4. package/dist/claude-session-title.js +6 -4
  5. package/dist/claude-session-title.js.map +1 -1
  6. package/dist/cli-agent.d.ts +3 -3
  7. package/dist/cli-agent.d.ts.map +1 -1
  8. package/dist/cli-agent.js +8 -6
  9. package/dist/cli-agent.js.map +1 -1
  10. package/dist/config/cli-registry/patterns.d.ts +1 -1
  11. package/dist/config/cli-registry/patterns.d.ts.map +1 -1
  12. package/dist/config/cli-registry/patterns.js +3 -0
  13. package/dist/config/cli-registry/patterns.js.map +1 -1
  14. package/dist/config/cli-registry/schema.d.ts +1 -0
  15. package/dist/config/cli-registry/schema.d.ts.map +1 -1
  16. package/dist/config/cli-registry/schema.js +5 -3
  17. package/dist/config/cli-registry/schema.js.map +1 -1
  18. package/dist/config/cli-registry/stock.d.ts.map +1 -1
  19. package/dist/config/cli-registry/stock.js +263 -4
  20. package/dist/config/cli-registry/stock.js.map +1 -1
  21. package/dist/config/cli-registry/types.d.ts +13 -5
  22. package/dist/config/cli-registry/types.d.ts.map +1 -1
  23. package/dist/config/map-limits.d.ts +13 -1
  24. package/dist/config/map-limits.d.ts.map +1 -1
  25. package/dist/config/map-limits.js +28 -1
  26. package/dist/config/map-limits.js.map +1 -1
  27. package/dist/config-backup.d.ts +279 -0
  28. package/dist/config-backup.d.ts.map +1 -0
  29. package/dist/config-backup.js +794 -0
  30. package/dist/config-backup.js.map +1 -0
  31. package/dist/cron/cron-service.d.ts +5 -5
  32. package/dist/cron/cron-service.js +6 -6
  33. package/dist/cron/cron-service.js.map +1 -1
  34. package/dist/custom-model-hosts.d.ts +16 -0
  35. package/dist/custom-model-hosts.d.ts.map +1 -1
  36. package/dist/custom-model-hosts.js.map +1 -1
  37. package/dist/hooks-config.d.ts +24 -0
  38. package/dist/hooks-config.d.ts.map +1 -1
  39. package/dist/hooks-config.js +47 -0
  40. package/dist/hooks-config.js.map +1 -1
  41. package/dist/intent-store.d.ts +2 -0
  42. package/dist/intent-store.d.ts.map +1 -1
  43. package/dist/intent-store.js +9 -0
  44. package/dist/intent-store.js.map +1 -1
  45. package/dist/mcp-sync-targets.d.ts +6 -3
  46. package/dist/mcp-sync-targets.d.ts.map +1 -1
  47. package/dist/mcp-sync-targets.js +6 -3
  48. package/dist/mcp-sync-targets.js.map +1 -1
  49. package/dist/mux-interface.d.ts +28 -7
  50. package/dist/mux-interface.d.ts.map +1 -1
  51. package/dist/prompt-cache-keepwarm.d.ts +193 -0
  52. package/dist/prompt-cache-keepwarm.d.ts.map +1 -0
  53. package/dist/prompt-cache-keepwarm.js +359 -0
  54. package/dist/prompt-cache-keepwarm.js.map +1 -0
  55. package/dist/respawn-controller.d.ts.map +1 -1
  56. package/dist/respawn-controller.js +6 -5
  57. package/dist/respawn-controller.js.map +1 -1
  58. package/dist/session-auto-ops.d.ts.map +1 -1
  59. package/dist/session-auto-ops.js +6 -1
  60. package/dist/session-auto-ops.js.map +1 -1
  61. package/dist/session-cli-registry-bridge.d.ts +15 -1
  62. package/dist/session-cli-registry-bridge.d.ts.map +1 -1
  63. package/dist/session-cli-registry-bridge.js +20 -3
  64. package/dist/session-cli-registry-bridge.js.map +1 -1
  65. package/dist/session-submit-verifier.d.ts +19 -0
  66. package/dist/session-submit-verifier.d.ts.map +1 -1
  67. package/dist/session-submit-verifier.js +88 -0
  68. package/dist/session-submit-verifier.js.map +1 -1
  69. package/dist/session.d.ts +83 -12
  70. package/dist/session.d.ts.map +1 -1
  71. package/dist/session.js +150 -16
  72. package/dist/session.js.map +1 -1
  73. package/dist/state-store.d.ts +10 -0
  74. package/dist/state-store.d.ts.map +1 -1
  75. package/dist/state-store.js +35 -0
  76. package/dist/state-store.js.map +1 -1
  77. package/dist/tab-layout-service.d.ts +33 -0
  78. package/dist/tab-layout-service.d.ts.map +1 -1
  79. package/dist/tab-layout-service.js +75 -3
  80. package/dist/tab-layout-service.js.map +1 -1
  81. package/dist/tmux-manager.d.ts +52 -9
  82. package/dist/tmux-manager.d.ts.map +1 -1
  83. package/dist/tmux-manager.js +148 -30
  84. package/dist/tmux-manager.js.map +1 -1
  85. package/dist/tmux-prefix-table.d.ts +54 -0
  86. package/dist/tmux-prefix-table.d.ts.map +1 -0
  87. package/dist/tmux-prefix-table.js +137 -0
  88. package/dist/tmux-prefix-table.js.map +1 -0
  89. package/dist/tui/tui-app.d.ts +9 -1
  90. package/dist/tui/tui-app.d.ts.map +1 -1
  91. package/dist/tui/tui-app.js +21 -8
  92. package/dist/tui/tui-app.js.map +1 -1
  93. package/dist/tui/tui-client.d.ts +3 -2
  94. package/dist/tui/tui-client.d.ts.map +1 -1
  95. package/dist/tui/tui-client.js +3 -2
  96. package/dist/tui/tui-client.js.map +1 -1
  97. package/dist/types/app-state.d.ts +6 -0
  98. package/dist/types/app-state.d.ts.map +1 -1
  99. package/dist/types/app-state.js.map +1 -1
  100. package/dist/types/session.d.ts +72 -5
  101. package/dist/types/session.d.ts.map +1 -1
  102. package/dist/types/session.js +2 -1
  103. package/dist/types/session.js.map +1 -1
  104. package/dist/usage-telemetry.d.ts +15 -0
  105. package/dist/usage-telemetry.d.ts.map +1 -1
  106. package/dist/usage-telemetry.js +45 -2
  107. package/dist/usage-telemetry.js.map +1 -1
  108. package/dist/utils/cli-installed-probes.d.ts +1 -1
  109. package/dist/utils/cli-installed-probes.d.ts.map +1 -1
  110. package/dist/utils/cli-installed-probes.js +4 -2
  111. package/dist/utils/cli-installed-probes.js.map +1 -1
  112. package/dist/utils/copilot-cli-resolver.d.ts +48 -0
  113. package/dist/utils/copilot-cli-resolver.d.ts.map +1 -0
  114. package/dist/utils/copilot-cli-resolver.js +112 -0
  115. package/dist/utils/copilot-cli-resolver.js.map +1 -0
  116. package/dist/utils/copilot-plan-usage.d.ts +46 -0
  117. package/dist/utils/copilot-plan-usage.d.ts.map +1 -0
  118. package/dist/utils/copilot-plan-usage.js +95 -0
  119. package/dist/utils/copilot-plan-usage.js.map +1 -0
  120. package/dist/utils/index.d.ts +3 -0
  121. package/dist/utils/index.d.ts.map +1 -1
  122. package/dist/utils/index.js +3 -0
  123. package/dist/utils/index.js.map +1 -1
  124. package/dist/utils/single-line.d.ts +22 -0
  125. package/dist/utils/single-line.d.ts.map +1 -0
  126. package/dist/utils/single-line.js +30 -0
  127. package/dist/utils/single-line.js.map +1 -0
  128. package/dist/web/approval-inbox.d.ts +6 -0
  129. package/dist/web/approval-inbox.d.ts.map +1 -1
  130. package/dist/web/approval-inbox.js +2 -2
  131. package/dist/web/approval-inbox.js.map +1 -1
  132. package/dist/web/case-path.d.ts +4 -2
  133. package/dist/web/case-path.d.ts.map +1 -1
  134. package/dist/web/case-path.js +13 -4
  135. package/dist/web/case-path.js.map +1 -1
  136. package/dist/web/plan-usage-latest.d.ts +2 -1
  137. package/dist/web/plan-usage-latest.d.ts.map +1 -1
  138. package/dist/web/plan-usage-latest.js +12 -2
  139. package/dist/web/plan-usage-latest.js.map +1 -1
  140. package/dist/web/ports/index.d.ts +1 -0
  141. package/dist/web/ports/index.d.ts.map +1 -1
  142. package/dist/web/ports/keep-warm-port.d.ts +9 -0
  143. package/dist/web/ports/keep-warm-port.d.ts.map +1 -0
  144. package/dist/web/ports/keep-warm-port.js +6 -0
  145. package/dist/web/ports/keep-warm-port.js.map +1 -0
  146. package/dist/web/ports/session-port.d.ts +3 -1
  147. package/dist/web/ports/session-port.d.ts.map +1 -1
  148. package/dist/web/public/admin-ui.js.gz +0 -0
  149. package/dist/web/public/api-client.c9b1cddc.js.gz +0 -0
  150. package/dist/web/public/app.9314ee60.js +43 -0
  151. package/dist/web/public/app.9314ee60.js.br +0 -0
  152. package/dist/web/public/app.9314ee60.js.gz +0 -0
  153. package/dist/web/public/approvals-ui.js.gz +0 -0
  154. package/dist/web/public/{constants.12b0c247.js → constants.4866ecc3.js} +205 -3
  155. package/dist/web/public/constants.4866ecc3.js.br +0 -0
  156. package/dist/web/public/constants.4866ecc3.js.gz +0 -0
  157. package/dist/web/public/cron-ui.js.gz +0 -0
  158. package/dist/web/public/entrance-animations.js.gz +0 -0
  159. package/dist/web/public/git-status-ui.js.gz +0 -0
  160. package/dist/web/public/home-sessions.js.gz +0 -0
  161. package/dist/web/public/host-wake-ui.js.gz +0 -0
  162. package/dist/web/public/i18n.22ca902b.js +2 -0
  163. package/dist/web/public/i18n.22ca902b.js.br +0 -0
  164. package/dist/web/public/i18n.22ca902b.js.gz +0 -0
  165. package/dist/web/public/{image-input.fcdcb46c.js → image-input.941386e7.js} +24 -14
  166. package/dist/web/public/image-input.941386e7.js.br +0 -0
  167. package/dist/web/public/image-input.941386e7.js.gz +0 -0
  168. package/dist/web/public/index.html +110 -16
  169. package/dist/web/public/index.html.br +0 -0
  170. package/dist/web/public/index.html.gz +0 -0
  171. package/dist/web/public/input-cjk.8bc46081.js.gz +0 -0
  172. package/dist/web/public/{keyboard-accessory.b42f539b.js → keyboard-accessory.4e8b20ac.js} +51 -22
  173. package/dist/web/public/keyboard-accessory.4e8b20ac.js.br +0 -0
  174. package/dist/web/public/keyboard-accessory.4e8b20ac.js.gz +0 -0
  175. package/dist/web/public/{mobile-handlers.0ef9c311.js → mobile-handlers.44adaa07.js} +48 -16
  176. package/dist/web/public/mobile-handlers.44adaa07.js.br +0 -0
  177. package/dist/web/public/mobile-handlers.44adaa07.js.gz +0 -0
  178. package/dist/web/public/mobile-ime-preview.2dbaf262.js.gz +0 -0
  179. package/dist/web/public/mobile-overview.js +1 -0
  180. package/dist/web/public/mobile-overview.js.br +0 -0
  181. package/dist/web/public/mobile-overview.js.gz +0 -0
  182. package/dist/web/public/mobile.12fb18de.css +1 -0
  183. package/dist/web/public/mobile.12fb18de.css.br +0 -0
  184. package/dist/web/public/mobile.12fb18de.css.gz +0 -0
  185. package/dist/web/public/notification-manager.feb82c04.js.gz +0 -0
  186. package/dist/web/public/orchestrator-panel.js.gz +0 -0
  187. package/dist/web/public/{panels-ui.73ec0137.js → panels-ui.cbb24ba1.js} +66 -66
  188. package/dist/web/public/panels-ui.cbb24ba1.js.br +0 -0
  189. package/dist/web/public/panels-ui.cbb24ba1.js.gz +0 -0
  190. package/dist/web/public/ralph-panel.b350e2ef.js.gz +0 -0
  191. package/dist/web/public/ralph-wizard.b6c0dd19.js.gz +0 -0
  192. package/dist/web/public/readmymind-ui.js.gz +0 -0
  193. package/dist/web/public/reboot-restore-ui.js.gz +0 -0
  194. package/dist/web/public/respawn-ui.d7adcf6a.js.gz +0 -0
  195. package/dist/web/public/sanitize-html.e7147e76.js.gz +0 -0
  196. package/dist/web/public/security-notices.json +21 -0
  197. package/dist/web/public/session-lineage.js.gz +0 -0
  198. package/dist/web/public/{session-ui.d52ff6aa.js → session-ui.9c1f009b.js} +8 -4
  199. package/dist/web/public/session-ui.9c1f009b.js.br +0 -0
  200. package/dist/web/public/session-ui.9c1f009b.js.gz +0 -0
  201. package/dist/web/public/settings-ui.fea9ddae.js +106 -0
  202. package/dist/web/public/settings-ui.fea9ddae.js.br +0 -0
  203. package/dist/web/public/settings-ui.fea9ddae.js.gz +0 -0
  204. package/dist/web/public/spreadsheet-preview-worker.js.gz +0 -0
  205. package/dist/web/public/spreadsheet-preview.75c751de.js.gz +0 -0
  206. package/dist/web/public/spreadsheet-xlsx-core.js.gz +0 -0
  207. package/dist/web/public/styles.e096fcd6.css +1 -0
  208. package/dist/web/public/styles.e096fcd6.css.br +0 -0
  209. package/dist/web/public/styles.e096fcd6.css.gz +0 -0
  210. package/dist/web/public/subagent-windows.07277a58.js.gz +0 -0
  211. package/dist/web/public/sw.js +2 -2
  212. package/dist/web/public/sw.js.br +0 -0
  213. package/dist/web/public/sw.js.gz +0 -0
  214. package/dist/web/public/tab-layout-browser.2d6189f7.js.gz +0 -0
  215. package/dist/web/public/tab-rail-resize.7157e0bd.js.gz +0 -0
  216. package/dist/web/public/terminal-keycode229-recovery.af09f99a.js.gz +0 -0
  217. package/dist/web/public/terminal-split.js.gz +0 -0
  218. package/dist/web/public/terminal-tile.js +41 -22
  219. package/dist/web/public/terminal-tile.js.br +0 -0
  220. package/dist/web/public/terminal-tile.js.gz +0 -0
  221. package/dist/web/public/terminal-ui.68dbd352.js +2 -0
  222. package/dist/web/public/terminal-ui.68dbd352.js.br +0 -0
  223. package/dist/web/public/terminal-ui.68dbd352.js.gz +0 -0
  224. package/dist/web/public/tile-grid.js +3 -6
  225. package/dist/web/public/tile-grid.js.br +0 -0
  226. package/dist/web/public/tile-grid.js.gz +0 -0
  227. package/dist/web/public/ultracode-panel.js.gz +0 -0
  228. package/dist/web/public/ultracode-windows.js.gz +0 -0
  229. package/dist/web/public/vendor/dompurify.min.js.gz +0 -0
  230. package/dist/web/public/vendor/exceljs.min.js.gz +0 -0
  231. package/dist/web/public/vendor/fflate.min.js.gz +0 -0
  232. package/dist/web/public/vendor/marked.min.js.gz +0 -0
  233. package/dist/web/public/vendor/xterm-addon-fit.min.js.gz +0 -0
  234. package/dist/web/public/vendor/xterm-addon-serialize.min.js.gz +0 -0
  235. package/dist/web/public/vendor/xterm-addon-unicode11.min.js.gz +0 -0
  236. package/dist/web/public/vendor/xterm-addon-webgl.min.js.gz +0 -0
  237. package/dist/web/public/vendor/xterm-predictive-echo.ae5e3d5d.js.gz +0 -0
  238. package/dist/web/public/vendor/xterm-zerolag-input.0b69623c.js.gz +0 -0
  239. package/dist/web/public/vendor/xterm.css.gz +0 -0
  240. package/dist/web/public/vendor/xterm.min.js.gz +0 -0
  241. package/dist/web/public/voice-input.2342c37b.js.gz +0 -0
  242. package/dist/web/public/voice-pcm-worklet.js.gz +0 -0
  243. package/dist/web/public/webview-tabs.js.gz +0 -0
  244. package/dist/web/public/whats-new.json +9 -9
  245. package/dist/web/response-viewer-transcript.d.ts +6 -0
  246. package/dist/web/response-viewer-transcript.d.ts.map +1 -1
  247. package/dist/web/response-viewer-transcript.js +134 -1
  248. package/dist/web/response-viewer-transcript.js.map +1 -1
  249. package/dist/web/routes/admin-routes.d.ts +2 -1
  250. package/dist/web/routes/admin-routes.d.ts.map +1 -1
  251. package/dist/web/routes/admin-routes.js +3 -0
  252. package/dist/web/routes/admin-routes.js.map +1 -1
  253. package/dist/web/routes/case-routes.d.ts +2 -2
  254. package/dist/web/routes/case-routes.d.ts.map +1 -1
  255. package/dist/web/routes/case-routes.js +81 -3
  256. package/dist/web/routes/case-routes.js.map +1 -1
  257. package/dist/web/routes/config-backup-routes.d.ts +54 -0
  258. package/dist/web/routes/config-backup-routes.d.ts.map +1 -0
  259. package/dist/web/routes/config-backup-routes.js +268 -0
  260. package/dist/web/routes/config-backup-routes.js.map +1 -0
  261. package/dist/web/routes/custom-model-routes.d.ts +17 -1
  262. package/dist/web/routes/custom-model-routes.d.ts.map +1 -1
  263. package/dist/web/routes/custom-model-routes.js +118 -13
  264. package/dist/web/routes/custom-model-routes.js.map +1 -1
  265. package/dist/web/routes/hook-event-routes.d.ts.map +1 -1
  266. package/dist/web/routes/hook-event-routes.js +26 -5
  267. package/dist/web/routes/hook-event-routes.js.map +1 -1
  268. package/dist/web/routes/index.d.ts +1 -0
  269. package/dist/web/routes/index.d.ts.map +1 -1
  270. package/dist/web/routes/index.js +1 -0
  271. package/dist/web/routes/index.js.map +1 -1
  272. package/dist/web/routes/mcp-sync-routes.d.ts +4 -4
  273. package/dist/web/routes/mcp-sync-routes.js +4 -4
  274. package/dist/web/routes/ralph-routes.js +2 -2
  275. package/dist/web/routes/ralph-routes.js.map +1 -1
  276. package/dist/web/routes/reboot-restore-routes.d.ts.map +1 -1
  277. package/dist/web/routes/reboot-restore-routes.js +2 -0
  278. package/dist/web/routes/reboot-restore-routes.js.map +1 -1
  279. package/dist/web/routes/session-routes.d.ts +14 -4
  280. package/dist/web/routes/session-routes.d.ts.map +1 -1
  281. package/dist/web/routes/session-routes.js +131 -30
  282. package/dist/web/routes/session-routes.js.map +1 -1
  283. package/dist/web/routes/status-telemetry-routes.d.ts +2 -2
  284. package/dist/web/routes/status-telemetry-routes.d.ts.map +1 -1
  285. package/dist/web/routes/status-telemetry-routes.js +8 -4
  286. package/dist/web/routes/status-telemetry-routes.js.map +1 -1
  287. package/dist/web/routes/system-routes.d.ts +2 -2
  288. package/dist/web/routes/system-routes.d.ts.map +1 -1
  289. package/dist/web/routes/system-routes.js +18 -0
  290. package/dist/web/routes/system-routes.js.map +1 -1
  291. package/dist/web/routes/webview-routes.d.ts.map +1 -1
  292. package/dist/web/routes/webview-routes.js +1 -0
  293. package/dist/web/routes/webview-routes.js.map +1 -1
  294. package/dist/web/schemas.d.ts +32 -0
  295. package/dist/web/schemas.d.ts.map +1 -1
  296. package/dist/web/schemas.js +64 -4
  297. package/dist/web/schemas.js.map +1 -1
  298. package/dist/web/server.d.ts +12 -2
  299. package/dist/web/server.d.ts.map +1 -1
  300. package/dist/web/server.js +127 -6
  301. package/dist/web/server.js.map +1 -1
  302. package/dist/web/session-listener-wiring.d.ts +6 -0
  303. package/dist/web/session-listener-wiring.d.ts.map +1 -1
  304. package/dist/web/session-listener-wiring.js +10 -3
  305. package/dist/web/session-listener-wiring.js.map +1 -1
  306. package/dist/web/sse-events.d.ts +5 -2
  307. package/dist/web/sse-events.d.ts.map +1 -1
  308. package/dist/web/sse-events.js +5 -2
  309. package/dist/web/sse-events.js.map +1 -1
  310. package/dist/web/webview-proxy.d.ts +8 -3
  311. package/dist/web/webview-proxy.d.ts.map +1 -1
  312. package/dist/web/webview-proxy.js +23 -5
  313. package/dist/web/webview-proxy.js.map +1 -1
  314. package/package.json +1 -1
  315. package/skills/codeman/SKILL.md +23 -11
  316. package/skills/codeman/preamble.sh +12 -2
  317. package/skills/codeman/reference/endpoints.md +16 -15
  318. package/skills/codeman/reference/messaging.md +5 -5
  319. package/skills/codeman/reference/recipes.md +2 -2
  320. package/skills/codeman/reference/verbs.md +25 -17
  321. package/dist/web/public/app.f04bb2a5.js +0 -43
  322. package/dist/web/public/app.f04bb2a5.js.br +0 -0
  323. package/dist/web/public/app.f04bb2a5.js.gz +0 -0
  324. package/dist/web/public/constants.12b0c247.js.br +0 -0
  325. package/dist/web/public/constants.12b0c247.js.gz +0 -0
  326. package/dist/web/public/i18n.06659676.js +0 -2
  327. package/dist/web/public/i18n.06659676.js.br +0 -0
  328. package/dist/web/public/i18n.06659676.js.gz +0 -0
  329. package/dist/web/public/image-input.fcdcb46c.js.br +0 -0
  330. package/dist/web/public/image-input.fcdcb46c.js.gz +0 -0
  331. package/dist/web/public/keyboard-accessory.b42f539b.js.br +0 -0
  332. package/dist/web/public/keyboard-accessory.b42f539b.js.gz +0 -0
  333. package/dist/web/public/mobile-handlers.0ef9c311.js.br +0 -0
  334. package/dist/web/public/mobile-handlers.0ef9c311.js.gz +0 -0
  335. package/dist/web/public/mobile.2dff1580.css +0 -1
  336. package/dist/web/public/mobile.2dff1580.css.br +0 -0
  337. package/dist/web/public/mobile.2dff1580.css.gz +0 -0
  338. package/dist/web/public/panels-ui.73ec0137.js.br +0 -0
  339. package/dist/web/public/panels-ui.73ec0137.js.gz +0 -0
  340. package/dist/web/public/session-ui.d52ff6aa.js.br +0 -0
  341. package/dist/web/public/session-ui.d52ff6aa.js.gz +0 -0
  342. package/dist/web/public/settings-ui.3a22bd2a.js +0 -97
  343. package/dist/web/public/settings-ui.3a22bd2a.js.br +0 -0
  344. package/dist/web/public/settings-ui.3a22bd2a.js.gz +0 -0
  345. package/dist/web/public/styles.ba6a9b84.css +0 -1
  346. package/dist/web/public/styles.ba6a9b84.css.br +0 -0
  347. package/dist/web/public/styles.ba6a9b84.css.gz +0 -0
  348. package/dist/web/public/terminal-ui.0a7ccc29.js +0 -2
  349. package/dist/web/public/terminal-ui.0a7ccc29.js.br +0 -0
  350. package/dist/web/public/terminal-ui.0a7ccc29.js.gz +0 -0
@@ -77,7 +77,7 @@ import { createRequire } from 'node:module';
77
77
  import { RunSummaryTracker } from '../run-summary.js';
78
78
  import { OrchestratorLoop } from '../orchestrator-loop.js';
79
79
  import { getLifecycleLog } from '../session-lifecycle-log.js';
80
- import { applyWorkspaceHooks, pruneAgentSessionPreambles, removeAgentSessionPreamble } from '../hooks-config.js';
80
+ import { applyWorkspaceHooks, pruneAgentSessionPreambles, readKeepWarmSettingsOrThrow, readPlanUsageTelemetryEnabled, removeAgentSessionPreamble, } from '../hooks-config.js';
81
81
  import { PushSubscriptionStore } from '../push-store.js';
82
82
  import webpush from 'web-push';
83
83
  import { SseStreamManager } from './sse-stream-manager.js';
@@ -89,6 +89,9 @@ import { intentStore } from '../intent-store.js';
89
89
  import { AI_CHECK_MODEL } from '../config/ai-defaults.js';
90
90
  import { approvalInbox } from './approval-inbox.js';
91
91
  import { SCREEN_BLOCKED_SOURCE } from './screen-blocked.js';
92
+ import { PromptCacheKeepWarmService } from '../prompt-cache-keepwarm.js';
93
+ import { composerIsEmpty, plainFrame } from '../session-submit-verifier.js';
94
+ import { detectUsageLimitPause } from '../usage-limit-patterns.js';
92
95
  import { stopDeepSeekWeb } from '../deepseek-web-server.js';
93
96
  import { wireRespawnListeners, setupTimedRespawn, restoreRespawnController, saveRespawnConfig, } from './respawn-event-wiring.js';
94
97
  import { reconcileUpdateOnBoot } from './self-update.js';
@@ -114,15 +117,17 @@ import { MAX_PASTE_IMAGE_BYTES } from '../config/buffer-limits.js';
114
117
  import { resolveTerminalHistoryConfig } from '../config/terminal-history.js';
115
118
  import { SseEvent } from './sse-events.js';
116
119
  import { MAX_ROUTE_PARAM_LENGTH } from './route-helpers.js';
117
- import { getLatestPlanUsage, setLatestCodexPlanUsage } from './plan-usage-latest.js';
120
+ import { getLatestPlanUsage, setLatestCodexPlanUsage, setLatestCopilotPlanUsage } from './plan-usage-latest.js';
118
121
  import { telemetrySignature } from '../usage-telemetry.js';
119
122
  import { readCodexPlanUsage, resolveCodexBinaryPath } from '../utils/codex-cli-resolver.js';
123
+ import { isCopilotAvailable } from '../utils/copilot-cli-resolver.js';
124
+ import { readCopilotPlanUsage, readCopilotPlanUsageIfEnabled, resolveCopilotToken, } from '../utils/copilot-plan-usage.js';
120
125
  import { registerAuthMiddleware, registerSecurityHeaders, registerHostGuard, isLostWebviewRootFrame, sendLostWebviewFramePage, } from './middleware/auth.js';
121
126
  import { isMultiUserMode } from '../config/multiuser.js';
122
127
  import { bootstrapInitialAdmin, hasUsers, resolveClaudeModeForUsername } from '../user-store.js';
123
128
  import { installRouteErrorHandler } from './route-error-handler.js';
124
129
  import { isExplicitlyEnabled, isLoopbackBindHost, buildHostPolicy } from './network-auth-policy.js';
125
- import { registerPushRoutes, registerTeamRoutes, registerMuxRoutes, registerFileRoutes, registerHtmlViewRoutes, registerScheduledRoutes, registerHookEventRoutes, registerApprovalRoutes, registerRebootRestoreRoutes, registerReadMyMindRoutes, registerGitStatusRoutes, registerStatusTelemetryRoutes, registerSystemRoutes, registerCaseRoutes, registerWorktreeRoutes, registerSessionRoutes, registerRespawnRoutes, registerRalphRoutes, registerPlanRoutes, registerClipboardRoutes, registerSearchRoutes, registerOrchestratorRoutes, registerCronRoutes, registerMeRoutes, registerAdminRoutes, registerWsRoutes, registerVoiceRoutes, registerWebviewRoutes, registerTabLayoutRoutes, registerMcpSyncRoutes, registerWebhookRoutes, registerDoctorRoutes, registerCustomModelRoutes, refreshAllCustomModelHosts, readCustomModelEndpointsEnabled, closeAllLlamaSwapLogTails, detectCustomModelSwapDisplacements, pruneIdleLlamaSwapLogTails, tryWebviewRefererFallback, registerCliRegistryRoutes, } from './routes/index.js';
130
+ import { registerPushRoutes, registerTeamRoutes, registerMuxRoutes, registerFileRoutes, registerHtmlViewRoutes, registerScheduledRoutes, registerHookEventRoutes, registerApprovalRoutes, registerRebootRestoreRoutes, registerReadMyMindRoutes, registerGitStatusRoutes, registerStatusTelemetryRoutes, registerSystemRoutes, registerCaseRoutes, registerWorktreeRoutes, registerSessionRoutes, registerRespawnRoutes, registerRalphRoutes, registerPlanRoutes, registerClipboardRoutes, registerSearchRoutes, registerOrchestratorRoutes, registerCronRoutes, registerMeRoutes, registerAdminRoutes, registerWsRoutes, registerVoiceRoutes, registerWebviewRoutes, registerTabLayoutRoutes, registerMcpSyncRoutes, registerConfigBackupRoutes, runConfigBackup, registerWebhookRoutes, registerDoctorRoutes, registerCustomModelRoutes, refreshAllCustomModelHosts, readCustomModelEndpointsEnabled, closeAllLlamaSwapLogTails, detectCustomModelSwapDisplacements, pruneIdleLlamaSwapLogTails, tryWebviewRefererFallback, registerCliRegistryRoutes, } from './routes/index.js';
126
131
  import { isLostWebviewFrameNavigation } from './webview-proxy.js';
127
132
  import { CronService } from '../cron/cron-service.js';
128
133
  const __dirname = dirname(fileURLToPath(import.meta.url));
@@ -131,6 +136,11 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
131
136
  // while capping growth of `sseClientsById` and blocking pathological inputs.
132
137
  const SSE_CLIENT_ID_RE = /^[A-Za-z0-9_-]{8,64}$/;
133
138
  const CODEX_USAGE_POLL_INTERVAL_MS = 5 * 60_000;
139
+ // Copilot's quota is read over the network from GitHub, and a monthly figure moves slowly.
140
+ const COPILOT_USAGE_POLL_INTERVAL_MS = 10 * 60_000;
141
+ // Config backups: one cheap read-and-hash of a handful of small files; a snapshot is written only when
142
+ // their content changed since the latest one, so this is one entry per real change, not per tick.
143
+ const CONFIG_BACKUP_INTERVAL_MS = 5 * 60_000;
134
144
  const CUSTOM_MODEL_REDISCOVER_INTERVAL_MS = 5 * 60_000;
135
145
  // Much shorter than the model-LIST refresh above on purpose: this catches an actual
136
146
  // eviction (a session's model no longer loaded, silently swapped out by another
@@ -196,6 +206,50 @@ export class WebServer extends EventEmitter {
196
206
  _customModelDisplacedNotified = new Set();
197
207
  /** Cron service (assigned in setupRoutes). */
198
208
  cronService;
209
+ // Prompt-cache keep-warm (prompt-cache-keepwarm.ts): the rulebook and timers live in the
210
+ // service; the server only lends it the facts a decision needs. A field initializer, not a
211
+ // setupRoutes() step: cleanup and listener wiring reach it on servers that never set up routes
212
+ // (the pane-exit and discard tests build a bare WebServer), and every port reads `this.*` lazily.
213
+ keepWarmService = new PromptCacheKeepWarmService({
214
+ getSession: (id) => this.sessions.get(id),
215
+ sessionIds: () => this.sessions.keys(),
216
+ readSettings: readKeepWarmSettingsOrThrow,
217
+ isAutomationActive: (id) => {
218
+ const session = this.sessions.get(id);
219
+ if (!session)
220
+ return true;
221
+ return ((this.respawnControllers.get(id)?.isRunning ?? false) ||
222
+ session.ralphTracker.loopState.active ||
223
+ session.currentTaskId !== null ||
224
+ sessionWaits.signalWaiterCount(id) > 0);
225
+ },
226
+ hasPendingApproval: (id) => approvalInbox.listPending().some((item) => item.sessionId === id && item.kind !== 'idle'),
227
+ readPane: (view) => {
228
+ const session = view;
229
+ const muxName = session.muxName;
230
+ // `capture-pane -p -e`: the visible frame with its styles, which is how `composerIsEmpty()`
231
+ // tells Claude Code's faint prompt suggestion from a typed draft.
232
+ const text = muxName ? (this.mux.capturePaneText?.(muxName, undefined, { styles: true }) ?? null) : null;
233
+ if (!text)
234
+ return { composerEmpty: null, limitShown: false };
235
+ const limit = detectUsageLimitPause(plainFrame(text));
236
+ return {
237
+ composerEmpty: composerIsEmpty(text, getCli(session.mode)?.capabilities.workDetect?.promptGlyph ?? '') ?? null,
238
+ limitShown: limit !== null && limit.resetAt > Date.now(),
239
+ };
240
+ },
241
+ publish: (id, status) => {
242
+ const session = this.sessions.get(id);
243
+ if (!session?.setKeepWarmStatus(status))
244
+ return;
245
+ this.broadcast(SseEvent.SessionKeepWarm, { sessionId: id, ...status });
246
+ // Change-only, so one line per transition names whichever guard holds it now.
247
+ if (status.state !== 'off' || status.reason !== 'off') {
248
+ console.log(`[KeepWarm] ${id.slice(0, 8)}: ${status.state}${status.reason ? ` (${status.reason})` : ''}`);
249
+ }
250
+ },
251
+ log: (message) => console.log(message),
252
+ });
199
253
  /**
200
254
  * Wake-on-LAN registry, returned by `registerSessionRoutes`. Held for its LIFETIME
201
255
  * only — `drop()` on session cleanup, `stop()` on shutdown. Waking from here would
@@ -232,6 +286,8 @@ export class WebServer extends EventEmitter {
232
286
  lastRecordedTokens = new Map();
233
287
  codexUsageRefreshInFlight = false;
234
288
  lastCodexUsageSignature = null;
289
+ copilotUsageRefreshInFlight = false;
290
+ lastCopilotUsageSignature = null;
235
291
  // Server startup time for respawn grace period calculation
236
292
  serverStartTime = Date.now();
237
293
  // Pending respawn start timers (for cleanup on shutdown)
@@ -315,6 +371,7 @@ export class WebServer extends EventEmitter {
315
371
  // Fresh, not the 2s cache: the settings PUT does not invalidate it, and a
316
372
  // flip must apply to the very next spawn.
317
373
  childrenFollowParent: async () => (await this.readSettings(true)).spawnedTabsFollowParent === true,
374
+ caseDefaults: this.store,
318
375
  });
319
376
  if (this.testMode)
320
377
  this.tabLayouts.markRestorationSkipped();
@@ -551,8 +608,8 @@ export class WebServer extends EventEmitter {
551
608
  /**
552
609
  * Add a tentative session only after its owner layout accepts the creation.
553
610
  * The session enters the live map inside the layout service's owner lock, so
554
- * the placement it asked for (`tabGroupId`) lands in the same versioned write
555
- * that first records it.
611
+ * the placement it asked for (`tabGroupId`, else its case's default group)
612
+ * lands in the same versioned write that first records it.
556
613
  */
557
614
  async registerSessionWithLayout(session, placement) {
558
615
  return this.tabLayouts.sessionCreated(ownerLayoutKey(session.owner), session.id, placement, () => {
@@ -573,6 +630,7 @@ export class WebServer extends EventEmitter {
573
630
  return {
574
631
  // SessionPort
575
632
  sessions: this.sessions,
633
+ keepWarm: this.keepWarmService,
576
634
  addSession: this.registerSessionWithLayout.bind(this),
577
635
  tabLayouts: this.tabLayouts,
578
636
  cleanupSession: this.cleanupSession.bind(this),
@@ -782,7 +840,7 @@ export class WebServer extends EventEmitter {
782
840
  // `ServerResponse` to a `FastifyReply`, so it is `reply.header()` here and
783
841
  // NOT `res.setHeader()`. A v9-style body throws TypeError on every static
784
842
  // request, which is every page load. See the v10.0.0 release notes.
785
- setHeaders: (reply) => {
843
+ setHeaders: (reply, filePath) => {
786
844
  // ⚠️ That same change ALSO flipped precedence, and silently. Under v9 this
787
845
  // callback wrote to the raw response and Fastify's staged reply headers then
788
846
  // overwrote it, so a route that set its own Cache-Control before .sendFile()
@@ -792,6 +850,15 @@ export class WebServer extends EventEmitter {
792
850
  // So: a route that already decided keeps its answer.
793
851
  if (reply.getHeader('Cache-Control') !== undefined)
794
852
  return;
853
+ // A JSON file here is DATA the page fetches at runtime (whats-new.json is rewritten every
854
+ // release, security-notices.json by hand, manifest.json), never content-hashed and never
855
+ // `?v=`-busted, so it must revalidate. Under `immutable` a browser may keep last release's
856
+ // copy for a year, and the page's `fetch(..., { cache: 'no-cache' })` is the only thing
857
+ // asking it not to; the response header is what every browser honours.
858
+ if (filePath.endsWith('.json')) {
859
+ reply.header('Cache-Control', 'no-cache');
860
+ return;
861
+ }
795
862
  reply.header('Cache-Control', 'public, max-age=31536000, immutable');
796
863
  },
797
864
  });
@@ -984,6 +1051,7 @@ export class WebServer extends EventEmitter {
984
1051
  registerWebviewRoutes(this.app, ctx, this.basePath);
985
1052
  registerTabLayoutRoutes(this.app, ctx);
986
1053
  registerMcpSyncRoutes(this.app);
1054
+ registerConfigBackupRoutes(this.app);
987
1055
  registerWebhookRoutes(this.app, {
988
1056
  notifier: this.webhookNotifier,
989
1057
  configDir: getDataDir(),
@@ -1194,6 +1262,7 @@ export class WebServer extends EventEmitter {
1194
1262
  }
1195
1263
  async _doCleanupSession(sessionId, killMux, reason, coordinateLayout = true) {
1196
1264
  const session = this.sessions.get(sessionId);
1265
+ this.keepWarmService.remove(sessionId);
1197
1266
  const pinned = session?.pinned === true || this.store.getSession(sessionId)?.pinned === true;
1198
1267
  if (coordinateLayout && session && killMux && !pinned) {
1199
1268
  return this.tabLayouts.runSessionDeletion([{ id: sessionId, owner: session.owner }], () => this._doCleanupSession(sessionId, killMux, reason, false));
@@ -1616,6 +1685,9 @@ export class WebServer extends EventEmitter {
1616
1685
  });
1617
1686
  }
1618
1687
  async setupSessionListeners(session) {
1688
+ // First keep-warm evaluation: publishes the effective opt-in for the Session Options
1689
+ // readout even before any cache report arrives.
1690
+ void this.keepWarmService.schedule(session.id);
1619
1691
  // Idempotent: the wiring exit handler detaches ALL listeners on every PTY exit
1620
1692
  // (removeSessionListenerRefs), so the re-attach routes (/interactive,
1621
1693
  // /interactive-respawn, /shell) call this again to restore observability
@@ -1644,6 +1716,7 @@ export class WebServer extends EventEmitter {
1644
1716
  buildSessionListenerDeps() {
1645
1717
  return {
1646
1718
  broadcast: this.broadcast.bind(this),
1719
+ keepWarmSchedule: (id) => void this.keepWarmService.schedule(id),
1647
1720
  batchTerminalData: this.batchTerminalData.bind(this),
1648
1721
  batchTaskUpdate: this.batchTaskUpdate.bind(this),
1649
1722
  broadcastSessionStateDebounced: this.broadcastSessionStateDebounced.bind(this),
@@ -2543,6 +2616,36 @@ export class WebServer extends EventEmitter {
2543
2616
  this.codexUsageRefreshInFlight = false;
2544
2617
  }
2545
2618
  }
2619
+ /**
2620
+ * Copilot's monthly premium-request quota for the shared plan-usage chip. Host-scoped and read-only
2621
+ * like the Codex poll, and additionally gated by `readCopilotPlanUsageIfEnabled()`: only while
2622
+ * plan-usage display is on (so turning the chip off also stops the outbound request), only with a
2623
+ * sign-in token and only with the Copilot CLI installed; nothing is sent to GitHub otherwise.
2624
+ */
2625
+ async refreshCopilotPlanUsage() {
2626
+ if (this.copilotUsageRefreshInFlight)
2627
+ return;
2628
+ this.copilotUsageRefreshInFlight = true;
2629
+ try {
2630
+ // A null clears the row, so switching the chip off also takes the last quota off the page.
2631
+ const usage = await readCopilotPlanUsageIfEnabled({
2632
+ planUsageEnabled: readPlanUsageTelemetryEnabled,
2633
+ resolveToken: () => resolveCopilotToken(),
2634
+ copilotInstalled: isCopilotAvailable,
2635
+ read: (token) => readCopilotPlanUsage({ token }),
2636
+ });
2637
+ const signature = usage ? telemetrySignature(usage) : '';
2638
+ if (signature === this.lastCopilotUsageSignature)
2639
+ return;
2640
+ this.lastCopilotUsageSignature = signature;
2641
+ const snapshot = setLatestCopilotPlanUsage(usage);
2642
+ this.cachedLightState = null;
2643
+ this.broadcast(SseEvent.SessionStatusTelemetry, snapshot);
2644
+ }
2645
+ finally {
2646
+ this.copilotUsageRefreshInFlight = false;
2647
+ }
2648
+ }
2546
2649
  async start() {
2547
2650
  // Multi-user first boot: create the initial admin from CODEMAN_USERNAME/PASSWORD
2548
2651
  // if there are no users yet, else refuse to start (there would be no way in).
@@ -2674,6 +2777,14 @@ export class WebServer extends EventEmitter {
2674
2777
  // Ensure the COD-54 hook secret exists on disk before any session exports
2675
2778
  // $CODEMAN_HOOK_SECRET_FILE — hook curls cat that path at execution time.
2676
2779
  getHookSecret();
2780
+ // Config backups: a snapshot at start (the state the process found) and then on change.
2781
+ if (!this.testMode) {
2782
+ const backup = (reason) => void runConfigBackup(reason).catch((err) => console.warn('[config-backup] snapshot failed:', err instanceof Error ? err.message : err));
2783
+ backup('startup');
2784
+ this.cleanup.setInterval(() => backup('auto'), CONFIG_BACKUP_INTERVAL_MS, {
2785
+ description: 'Config backup',
2786
+ });
2787
+ }
2677
2788
  // Main Codex subscription limits come from the signed-in local CLI. Keep
2678
2789
  // this read-only and host-scoped; multi-user SSE routing makes it admin-only.
2679
2790
  if (!this.testMode) {
@@ -2681,6 +2792,10 @@ export class WebServer extends EventEmitter {
2681
2792
  this.cleanup.setInterval(() => void this.refreshCodexPlanUsage(), CODEX_USAGE_POLL_INTERVAL_MS, {
2682
2793
  description: 'Codex plan-usage refresh',
2683
2794
  });
2795
+ void this.refreshCopilotPlanUsage();
2796
+ this.cleanup.setInterval(() => void this.refreshCopilotPlanUsage(), COPILOT_USAGE_POLL_INTERVAL_MS, {
2797
+ description: 'Copilot plan-usage refresh',
2798
+ });
2684
2799
  }
2685
2800
  // Custom Model Endpoint Profiles (docs/custom-model-endpoints-plan.md): keeps
2686
2801
  // each saved endpoint's discovered model list current with no manual
@@ -3161,6 +3276,7 @@ export class WebServer extends EventEmitter {
3161
3276
  antigravityConfig: muxSession.mode === 'antigravity' ? savedState?.antigravityConfig : undefined,
3162
3277
  piConfig: muxSession.mode === 'pi' ? savedState?.piConfig : undefined,
3163
3278
  grokConfig: muxSession.mode === 'grok' ? savedState?.grokConfig : undefined,
3279
+ copilotConfig: muxSession.mode === 'copilot' ? savedState?.copilotConfig : undefined,
3164
3280
  deepSeekConfig: muxSession.mode === 'deepseek' ? savedState?.deepSeekConfig : undefined,
3165
3281
  ompConfig: muxSession.mode === 'omp' ? savedState?.ompConfig : undefined,
3166
3282
  envOverrides: savedEnvOverrides,
@@ -3172,6 +3288,10 @@ export class WebServer extends EventEmitter {
3172
3288
  // the launch conversation until the user types again, even though
3173
3289
  // the re-attached CLI is on a post-`/clear` one.
3174
3290
  lastSubmitAt: savedState?.lastSubmitAt,
3291
+ // The keep-warm choice and its cap's clock; with the restored `promptCache`
3292
+ // below, a future `expiresAt` re-arms the timer once the pane is attached.
3293
+ lastRealPromptAt: savedState?.lastRealPromptAt,
3294
+ keepWarmEnabled: savedState?.keepWarmEnabled,
3175
3295
  // Conversations this pane provably owned, oldest first. Its tail is
3176
3296
  // the conversation the CLI was on when the server stopped, which is
3177
3297
  // what a re-attach must point the viewer at instead of the launch id.
@@ -3584,6 +3704,7 @@ export class WebServer extends EventEmitter {
3584
3704
  // response), so without this a 10-minute wait holds shutdown open.
3585
3705
  sessionWaits.cancelEverything();
3586
3706
  approvalInbox.stop();
3707
+ this.keepWarmService.stop();
3587
3708
  // Same reason as `cancelEverything` above: an in-flight wake is awaited by a request,
3588
3709
  // and `app.close()` (the last line of this method) does not abort in-flight requests —
3589
3710
  // so without this a restart during a wake waits out the readiness poll.