tmux-ide 2.1.5 → 2.6.1

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 (969) hide show
  1. package/README.md +115 -101
  2. package/bin/cli.js +13686 -4
  3. package/bin/cli.ts +1143 -260
  4. package/bunfig.toml +4 -0
  5. package/package.json +36 -18
  6. package/packages/contracts/package.json +22 -0
  7. package/packages/contracts/src/__tests__/ide-config.test.ts +46 -0
  8. package/packages/contracts/src/__tests__/terminals.test.ts +87 -0
  9. package/packages/contracts/src/actions-contract.ts +310 -0
  10. package/packages/contracts/src/actions-errors.ts +41 -0
  11. package/packages/contracts/src/domain.ts +36 -0
  12. package/packages/contracts/src/ide-config.ts +170 -0
  13. package/packages/contracts/src/index.ts +24 -0
  14. package/packages/contracts/src/lib-internal/hq.ts +38 -0
  15. package/packages/contracts/src/terminals.ts +116 -0
  16. package/packages/contracts/src/tmux.ts +60 -0
  17. package/packages/contracts/src/workspace.ts +67 -0
  18. package/packages/daemon/dist/__tests__/support.d.ts +7 -0
  19. package/packages/daemon/dist/__tests__/support.js +33 -0
  20. package/packages/daemon/dist/agent-explain.d.ts +45 -0
  21. package/packages/daemon/dist/agent-explain.js +210 -0
  22. package/packages/daemon/dist/attach.d.ts +3 -0
  23. package/packages/daemon/dist/attach.js +14 -0
  24. package/packages/daemon/dist/bin.d.ts +2 -0
  25. package/packages/daemon/dist/bin.js +3 -0
  26. package/packages/daemon/dist/canonical.d.ts +2 -0
  27. package/packages/daemon/dist/canonical.js +1 -0
  28. package/packages/daemon/dist/cli.d.ts +1 -0
  29. package/packages/daemon/dist/cli.js +425 -0
  30. package/packages/daemon/dist/command-center/actions/contract.d.ts +1 -0
  31. package/packages/daemon/dist/command-center/actions/contract.js +2 -0
  32. package/packages/daemon/dist/command-center/actions/dispatcher.d.ts +27 -0
  33. package/packages/daemon/dist/command-center/actions/dispatcher.js +109 -0
  34. package/packages/daemon/dist/command-center/actions/errors.d.ts +38 -0
  35. package/packages/daemon/dist/command-center/actions/errors.js +56 -0
  36. package/packages/daemon/dist/command-center/actions/handlers/_project-context.d.ts +12 -0
  37. package/packages/daemon/dist/command-center/actions/handlers/_project-context.js +12 -0
  38. package/packages/daemon/dist/command-center/actions/handlers/_resolve-project.d.ts +42 -0
  39. package/packages/daemon/dist/command-center/actions/handlers/_resolve-project.js +48 -0
  40. package/packages/daemon/dist/command-center/actions/handlers/app-set-remote-access.d.ts +23 -0
  41. package/packages/daemon/dist/command-center/actions/handlers/app-set-remote-access.js +67 -0
  42. package/packages/daemon/dist/command-center/actions/handlers/config-actions.d.ts +12 -0
  43. package/packages/daemon/dist/command-center/actions/handlers/config-actions.js +69 -0
  44. package/packages/daemon/dist/command-center/actions/handlers/daemon-shutdown.d.ts +6 -0
  45. package/packages/daemon/dist/command-center/actions/handlers/daemon-shutdown.js +24 -0
  46. package/packages/daemon/dist/command-center/actions/handlers/project-activate.d.ts +7 -0
  47. package/packages/daemon/dist/command-center/actions/handlers/project-activate.js +19 -0
  48. package/packages/daemon/dist/command-center/actions/handlers/project-launch.d.ts +18 -0
  49. package/packages/daemon/dist/command-center/actions/handlers/project-launch.js +58 -0
  50. package/packages/daemon/dist/command-center/actions/handlers/project-open-terminal.d.ts +32 -0
  51. package/packages/daemon/dist/command-center/actions/handlers/project-open-terminal.js +69 -0
  52. package/packages/daemon/dist/command-center/actions/handlers/project-restart.d.ts +17 -0
  53. package/packages/daemon/dist/command-center/actions/handlers/project-restart.js +27 -0
  54. package/packages/daemon/dist/command-center/actions/handlers/project-stop.d.ts +24 -0
  55. package/packages/daemon/dist/command-center/actions/handlers/project-stop.js +38 -0
  56. package/packages/daemon/dist/command-center/actions/handlers/terminal-respawn.d.ts +24 -0
  57. package/packages/daemon/dist/command-center/actions/handlers/terminal-respawn.js +88 -0
  58. package/packages/daemon/dist/command-center/actions/handlers/terminal-stop.d.ts +14 -0
  59. package/packages/daemon/dist/command-center/actions/handlers/terminal-stop.js +22 -0
  60. package/packages/daemon/dist/command-center/actions/registry.d.ts +35 -0
  61. package/packages/daemon/dist/command-center/actions/registry.js +109 -0
  62. package/packages/daemon/dist/command-center/discovery.d.ts +23 -0
  63. package/packages/daemon/dist/command-center/discovery.js +67 -0
  64. package/packages/daemon/dist/command-center/index.d.ts +10 -0
  65. package/packages/daemon/dist/command-center/index.js +21 -0
  66. package/packages/daemon/dist/command-center/schemas.d.ts +76 -0
  67. package/packages/daemon/dist/command-center/schemas.js +68 -0
  68. package/packages/daemon/dist/command-center/server.d.ts +26 -0
  69. package/packages/daemon/dist/command-center/server.js +1103 -0
  70. package/packages/daemon/dist/command-center/ws-events.d.ts +59 -0
  71. package/packages/daemon/dist/command-center/ws-events.js +277 -0
  72. package/packages/daemon/dist/config.d.ts +19 -0
  73. package/packages/daemon/dist/config.js +494 -0
  74. package/packages/daemon/dist/detect.d.ts +15 -0
  75. package/packages/daemon/dist/detect.js +228 -0
  76. package/packages/daemon/dist/doctor.d.ts +21 -0
  77. package/packages/daemon/dist/doctor.js +154 -0
  78. package/packages/daemon/dist/embed.d.ts +1 -0
  79. package/packages/daemon/dist/embed.js +1 -0
  80. package/packages/daemon/dist/index.d.ts +3 -0
  81. package/packages/daemon/dist/index.js +2 -0
  82. package/packages/daemon/dist/init.d.ts +4 -0
  83. package/packages/daemon/dist/init.js +174 -0
  84. package/packages/daemon/dist/inspect.d.ts +54 -0
  85. package/packages/daemon/dist/inspect.js +118 -0
  86. package/packages/daemon/dist/launch.d.ts +23 -0
  87. package/packages/daemon/dist/launch.js +250 -0
  88. package/packages/daemon/dist/lib/active-projects.d.ts +12 -0
  89. package/packages/daemon/dist/lib/active-projects.js +35 -0
  90. package/packages/daemon/dist/lib/agent-discovery.d.ts +43 -0
  91. package/packages/daemon/dist/lib/agent-discovery.js +85 -0
  92. package/packages/daemon/dist/lib/app-config.d.ts +147 -0
  93. package/packages/daemon/dist/lib/app-config.js +191 -0
  94. package/packages/daemon/dist/lib/app-settings.d.ts +9 -0
  95. package/packages/daemon/dist/lib/app-settings.js +44 -0
  96. package/packages/daemon/dist/lib/auth/auth-service.d.ts +33 -0
  97. package/packages/daemon/dist/lib/auth/auth-service.js +172 -0
  98. package/packages/daemon/dist/lib/auth/middleware.d.ts +16 -0
  99. package/packages/daemon/dist/lib/auth/middleware.js +43 -0
  100. package/packages/daemon/dist/lib/auth/types.d.ts +1 -0
  101. package/packages/daemon/dist/lib/auth/types.js +2 -0
  102. package/packages/daemon/dist/lib/auth-token.d.ts +1 -0
  103. package/packages/daemon/dist/lib/auth-token.js +4 -0
  104. package/packages/daemon/dist/lib/authorship.d.ts +62 -0
  105. package/packages/daemon/dist/lib/authorship.js +209 -0
  106. package/packages/daemon/dist/lib/canonical-daemon.d.ts +21 -0
  107. package/packages/daemon/dist/lib/canonical-daemon.js +111 -0
  108. package/packages/daemon/dist/lib/cli-action-bridge.d.ts +27 -0
  109. package/packages/daemon/dist/lib/cli-action-bridge.js +161 -0
  110. package/packages/daemon/dist/lib/daemon-embed.d.ts +31 -0
  111. package/packages/daemon/dist/lib/daemon-embed.js +643 -0
  112. package/packages/daemon/dist/lib/daemon-watchdog.d.ts +16 -0
  113. package/packages/daemon/dist/lib/daemon-watchdog.js +98 -0
  114. package/packages/daemon/dist/lib/daemon.d.ts +8 -0
  115. package/packages/daemon/dist/lib/daemon.js +79 -0
  116. package/packages/daemon/dist/lib/dot-path.d.ts +2 -0
  117. package/packages/daemon/dist/lib/dot-path.js +17 -0
  118. package/packages/daemon/dist/lib/errors.d.ts +37 -0
  119. package/packages/daemon/dist/lib/errors.js +50 -0
  120. package/packages/daemon/dist/lib/filesystem-browser.d.ts +85 -0
  121. package/packages/daemon/dist/lib/filesystem-browser.js +257 -0
  122. package/packages/daemon/dist/lib/launch-plan.d.ts +6 -0
  123. package/packages/daemon/dist/lib/launch-plan.js +76 -0
  124. package/packages/daemon/dist/lib/log.d.ts +40 -0
  125. package/packages/daemon/dist/lib/log.js +86 -0
  126. package/packages/daemon/dist/lib/output.d.ts +9 -0
  127. package/packages/daemon/dist/lib/output.js +65 -0
  128. package/packages/daemon/dist/lib/project-init-runner.d.ts +46 -0
  129. package/packages/daemon/dist/lib/project-init-runner.js +117 -0
  130. package/packages/daemon/dist/lib/project-inspect.d.ts +28 -0
  131. package/packages/daemon/dist/lib/project-inspect.js +67 -0
  132. package/packages/daemon/dist/lib/project-onboard.d.ts +58 -0
  133. package/packages/daemon/dist/lib/project-onboard.js +108 -0
  134. package/packages/daemon/dist/lib/project-probe.d.ts +35 -0
  135. package/packages/daemon/dist/lib/project-probe.js +61 -0
  136. package/packages/daemon/dist/lib/project-registry.d.ts +76 -0
  137. package/packages/daemon/dist/lib/project-registry.js +230 -0
  138. package/packages/daemon/dist/lib/session-monitor.d.ts +15 -0
  139. package/packages/daemon/dist/lib/session-monitor.js +103 -0
  140. package/packages/daemon/dist/lib/session-options.d.ts +13 -0
  141. package/packages/daemon/dist/lib/session-options.js +85 -0
  142. package/packages/daemon/dist/lib/shell.d.ts +5 -0
  143. package/packages/daemon/dist/lib/shell.js +8 -0
  144. package/packages/daemon/dist/lib/sizes.d.ts +16 -0
  145. package/packages/daemon/dist/lib/sizes.js +36 -0
  146. package/packages/daemon/dist/lib/skill-sync.d.ts +60 -0
  147. package/packages/daemon/dist/lib/skill-sync.js +128 -0
  148. package/packages/daemon/dist/lib/slugify.d.ts +4 -0
  149. package/packages/daemon/dist/lib/slugify.js +10 -0
  150. package/packages/daemon/dist/lib/terminals-store.d.ts +27 -0
  151. package/packages/daemon/dist/lib/terminals-store.js +111 -0
  152. package/packages/daemon/dist/lib/update-check.d.ts +118 -0
  153. package/packages/daemon/dist/lib/update-check.js +261 -0
  154. package/packages/daemon/dist/lib/update.d.ts +65 -0
  155. package/packages/daemon/dist/lib/update.js +141 -0
  156. package/packages/daemon/dist/lib/workspace-registry.d.ts +84 -0
  157. package/packages/daemon/dist/lib/workspace-registry.js +176 -0
  158. package/packages/daemon/dist/lib/worktree.d.ts +76 -0
  159. package/packages/daemon/dist/lib/worktree.js +207 -0
  160. package/packages/daemon/dist/lib/yaml-io.d.ts +10 -0
  161. package/packages/daemon/dist/lib/yaml-io.js +24 -0
  162. package/packages/daemon/dist/ls.d.ts +3 -0
  163. package/packages/daemon/dist/ls.js +35 -0
  164. package/packages/daemon/dist/restart.d.ts +4 -0
  165. package/packages/daemon/dist/restart.js +16 -0
  166. package/packages/daemon/dist/restore.d.ts +86 -0
  167. package/packages/daemon/dist/restore.js +406 -0
  168. package/packages/daemon/dist/schemas/domain.d.ts +1 -0
  169. package/packages/daemon/dist/schemas/domain.js +2 -0
  170. package/packages/daemon/dist/schemas/filesystem.d.ts +29 -0
  171. package/packages/daemon/dist/schemas/filesystem.js +29 -0
  172. package/packages/daemon/dist/schemas/ide-config.d.ts +1 -0
  173. package/packages/daemon/dist/schemas/ide-config.js +2 -0
  174. package/packages/daemon/dist/schemas/index.d.ts +12 -0
  175. package/packages/daemon/dist/schemas/index.js +6 -0
  176. package/packages/daemon/dist/schemas/inspect.d.ts +53 -0
  177. package/packages/daemon/dist/schemas/inspect.js +57 -0
  178. package/packages/daemon/dist/schemas/registry.d.ts +35 -0
  179. package/packages/daemon/dist/schemas/registry.js +43 -0
  180. package/packages/daemon/dist/schemas/ws-events.d.ts +72 -0
  181. package/packages/daemon/dist/schemas/ws-events.js +110 -0
  182. package/packages/daemon/dist/send.d.ts +27 -0
  183. package/packages/daemon/dist/send.js +141 -0
  184. package/packages/daemon/dist/server/index.d.ts +10 -0
  185. package/packages/daemon/dist/server/index.js +55 -0
  186. package/packages/daemon/dist/server/pty-bridge.d.ts +174 -0
  187. package/packages/daemon/dist/server/pty-bridge.js +422 -0
  188. package/packages/daemon/dist/server/standalone.d.ts +1 -0
  189. package/packages/daemon/dist/server/standalone.js +14 -0
  190. package/packages/daemon/dist/server/ws-route.d.ts +74 -0
  191. package/packages/daemon/dist/server/ws-route.js +379 -0
  192. package/packages/daemon/dist/status.d.ts +3 -0
  193. package/packages/daemon/dist/status.js +46 -0
  194. package/packages/daemon/dist/stop.d.ts +3 -0
  195. package/packages/daemon/dist/stop.js +21 -0
  196. package/packages/daemon/dist/terminal/NodePtyAdapter.d.ts +44 -0
  197. package/packages/daemon/dist/terminal/NodePtyAdapter.js +253 -0
  198. package/packages/daemon/dist/terminal/PtyAdapter.d.ts +124 -0
  199. package/packages/daemon/dist/terminal/PtyAdapter.js +43 -0
  200. package/packages/daemon/dist/terminal/__tests__/MockPtyAdapter.d.ts +77 -0
  201. package/packages/daemon/dist/terminal/__tests__/MockPtyAdapter.js +155 -0
  202. package/packages/daemon/dist/types.d.ts +2 -0
  203. package/packages/daemon/dist/types.js +1 -0
  204. package/packages/daemon/dist/validate.d.ts +4 -0
  205. package/packages/daemon/dist/validate.js +184 -0
  206. package/packages/daemon/dist/widgets/changes/index.d.ts +1 -0
  207. package/packages/daemon/dist/widgets/changes/index.jsx +575 -0
  208. package/packages/daemon/dist/widgets/config/index.d.ts +1 -0
  209. package/packages/daemon/dist/widgets/config/index.jsx +395 -0
  210. package/packages/daemon/dist/widgets/explorer/breadcrumbs.d.ts +10 -0
  211. package/packages/daemon/dist/widgets/explorer/breadcrumbs.jsx +51 -0
  212. package/packages/daemon/dist/widgets/explorer/footer.d.ts +6 -0
  213. package/packages/daemon/dist/widgets/explorer/footer.jsx +11 -0
  214. package/packages/daemon/dist/widgets/explorer/index.d.ts +1 -0
  215. package/packages/daemon/dist/widgets/explorer/index.jsx +393 -0
  216. package/packages/daemon/dist/widgets/explorer/tree-model.d.ts +13 -0
  217. package/packages/daemon/dist/widgets/explorer/tree-model.js +69 -0
  218. package/packages/daemon/dist/widgets/explorer/tree.d.ts +13 -0
  219. package/packages/daemon/dist/widgets/explorer/tree.jsx +108 -0
  220. package/packages/daemon/dist/widgets/lib/config-model.d.ts +22 -0
  221. package/packages/daemon/dist/widgets/lib/config-model.js +99 -0
  222. package/packages/daemon/dist/widgets/lib/files.d.ts +11 -0
  223. package/packages/daemon/dist/widgets/lib/files.js +76 -0
  224. package/packages/daemon/dist/widgets/lib/git.d.ts +11 -0
  225. package/packages/daemon/dist/widgets/lib/git.js +70 -0
  226. package/packages/daemon/dist/widgets/lib/grammar.d.ts +79 -0
  227. package/packages/daemon/dist/widgets/lib/grammar.js +95 -0
  228. package/packages/daemon/dist/widgets/lib/help-overlay.d.ts +19 -0
  229. package/packages/daemon/dist/widgets/lib/help-overlay.jsx +69 -0
  230. package/packages/daemon/dist/widgets/lib/pane-comms.d.ts +28 -0
  231. package/packages/daemon/dist/widgets/lib/pane-comms.js +189 -0
  232. package/packages/daemon/dist/widgets/lib/theme.d.ts +44 -0
  233. package/packages/daemon/dist/widgets/lib/theme.js +153 -0
  234. package/packages/daemon/dist/widgets/lib/watcher.d.ts +9 -0
  235. package/packages/daemon/dist/widgets/lib/watcher.js +92 -0
  236. package/packages/daemon/dist/widgets/preview/index.d.ts +1 -0
  237. package/packages/daemon/dist/widgets/preview/index.jsx +371 -0
  238. package/packages/daemon/dist/widgets/resolve.d.ts +20 -0
  239. package/packages/daemon/dist/widgets/resolve.js +100 -0
  240. package/packages/daemon/dist/widgets/setup/agent-naming.d.ts +9 -0
  241. package/packages/daemon/dist/widgets/setup/agent-naming.jsx +81 -0
  242. package/packages/daemon/dist/widgets/setup/config-tree.d.ts +13 -0
  243. package/packages/daemon/dist/widgets/setup/config-tree.jsx +203 -0
  244. package/packages/daemon/dist/widgets/setup/detect-panel.d.ts +14 -0
  245. package/packages/daemon/dist/widgets/setup/detect-panel.jsx +48 -0
  246. package/packages/daemon/dist/widgets/setup/field-editor.d.ts +12 -0
  247. package/packages/daemon/dist/widgets/setup/field-editor.jsx +163 -0
  248. package/packages/daemon/dist/widgets/setup/footer.d.ts +17 -0
  249. package/packages/daemon/dist/widgets/setup/footer.jsx +64 -0
  250. package/packages/daemon/dist/widgets/setup/index.d.ts +1 -0
  251. package/packages/daemon/dist/widgets/setup/index.jsx +261 -0
  252. package/packages/daemon/dist/widgets/setup/layout-picker.d.ts +9 -0
  253. package/packages/daemon/dist/widgets/setup/layout-picker.jsx +69 -0
  254. package/packages/daemon/dist/widgets/setup/setup-model.d.ts +15 -0
  255. package/packages/daemon/dist/widgets/setup/setup-model.js +157 -0
  256. package/packages/daemon/dist/widgets/sidebar/index.d.ts +1 -0
  257. package/packages/daemon/dist/widgets/sidebar/index.jsx +462 -0
  258. package/packages/daemon/src/agent-explain.ts +270 -0
  259. package/packages/daemon/src/attach.ts +20 -0
  260. package/packages/daemon/src/bin.ts +4 -0
  261. package/packages/daemon/src/canonical.ts +7 -0
  262. package/packages/daemon/src/cli.ts +499 -0
  263. package/packages/daemon/src/command-center/actions/contract.ts +2 -0
  264. package/packages/daemon/src/command-center/actions/dispatcher.ts +137 -0
  265. package/packages/daemon/src/command-center/actions/errors.ts +105 -0
  266. package/packages/daemon/src/command-center/actions/handlers/_project-context.ts +30 -0
  267. package/packages/daemon/src/command-center/actions/handlers/_resolve-project.ts +78 -0
  268. package/packages/daemon/src/command-center/actions/handlers/app-set-remote-access.ts +118 -0
  269. package/packages/daemon/src/command-center/actions/handlers/config-actions.ts +113 -0
  270. package/packages/daemon/src/command-center/actions/handlers/daemon-shutdown.ts +38 -0
  271. package/packages/daemon/src/command-center/actions/handlers/project-activate.ts +30 -0
  272. package/packages/daemon/src/command-center/actions/handlers/project-launch.ts +70 -0
  273. package/packages/daemon/src/command-center/actions/handlers/project-open-terminal.ts +87 -0
  274. package/packages/daemon/src/command-center/actions/handlers/project-restart.ts +38 -0
  275. package/packages/daemon/src/command-center/actions/handlers/project-stop.ts +62 -0
  276. package/packages/daemon/src/command-center/actions/handlers/terminal-respawn.ts +119 -0
  277. package/packages/daemon/src/command-center/actions/handlers/terminal-stop.ts +35 -0
  278. package/packages/daemon/src/command-center/actions/registry.ts +149 -0
  279. package/packages/daemon/src/command-center/discovery.ts +96 -0
  280. package/packages/daemon/src/command-center/schemas.ts +85 -0
  281. package/packages/daemon/src/command-center/server.ts +1260 -0
  282. package/packages/daemon/src/command-center/ws-events.ts +316 -0
  283. package/packages/daemon/src/config.ts +549 -0
  284. package/packages/daemon/src/doctor.ts +242 -0
  285. package/packages/daemon/src/embed.ts +5 -0
  286. package/packages/daemon/src/index.ts +12 -0
  287. package/packages/daemon/src/init.ts +211 -0
  288. package/packages/daemon/src/inspect.ts +178 -0
  289. package/packages/daemon/src/launch.ts +349 -0
  290. package/packages/daemon/src/lib/active-projects.ts +49 -0
  291. package/packages/daemon/src/lib/agent-discovery.ts +121 -0
  292. package/packages/daemon/src/lib/app-config.ts +336 -0
  293. package/packages/daemon/src/lib/app-settings.ts +53 -0
  294. package/packages/daemon/src/lib/auth/types.ts +2 -0
  295. package/packages/daemon/src/lib/auth-token.ts +5 -0
  296. package/packages/daemon/src/lib/canonical-daemon.ts +122 -0
  297. package/packages/daemon/src/lib/cli-action-bridge.ts +216 -0
  298. package/packages/daemon/src/lib/daemon-embed.ts +782 -0
  299. package/packages/daemon/src/lib/daemon-watchdog.ts +111 -0
  300. package/packages/daemon/src/lib/daemon.ts +79 -0
  301. package/packages/daemon/src/lib/errors.ts +67 -0
  302. package/packages/daemon/src/lib/filesystem-browser.ts +292 -0
  303. package/packages/daemon/src/lib/log.ts +134 -0
  304. package/packages/daemon/src/lib/output.ts +76 -0
  305. package/packages/daemon/src/lib/project-init-runner.ts +150 -0
  306. package/packages/daemon/src/lib/project-inspect.ts +80 -0
  307. package/packages/daemon/src/lib/project-onboard.ts +149 -0
  308. package/packages/daemon/src/lib/project-probe.ts +92 -0
  309. package/packages/daemon/src/lib/project-registry.ts +296 -0
  310. package/packages/daemon/src/lib/session-monitor.ts +122 -0
  311. package/packages/daemon/src/lib/skill-sync.ts +155 -0
  312. package/packages/daemon/src/lib/terminals-store.ts +125 -0
  313. package/packages/daemon/src/lib/update-check.ts +298 -0
  314. package/packages/daemon/src/lib/update.ts +158 -0
  315. package/packages/daemon/src/lib/workspace-registry.ts +229 -0
  316. package/packages/daemon/src/lib/worktree.ts +289 -0
  317. package/packages/daemon/src/restart.ts +24 -0
  318. package/packages/daemon/src/restore.ts +514 -0
  319. package/packages/daemon/src/schemas/domain.ts +2 -0
  320. package/packages/daemon/src/schemas/filesystem.ts +34 -0
  321. package/packages/daemon/src/schemas/ide-config.ts +2 -0
  322. package/packages/daemon/src/schemas/index.ts +59 -0
  323. package/packages/daemon/src/schemas/inspect.ts +67 -0
  324. package/packages/daemon/src/schemas/registry.ts +55 -0
  325. package/packages/daemon/src/schemas/ws-events.ts +135 -0
  326. package/packages/daemon/src/send.ts +171 -0
  327. package/packages/daemon/src/server/README.md +15 -0
  328. package/packages/daemon/src/server/index.ts +74 -0
  329. package/packages/daemon/src/server/pty-bridge.ts +532 -0
  330. package/packages/daemon/src/server/standalone.ts +18 -0
  331. package/packages/daemon/src/server/ws-route.ts +483 -0
  332. package/packages/daemon/src/status.ts +59 -0
  333. package/packages/daemon/src/stop.ts +28 -0
  334. package/packages/daemon/src/terminal/NodePtyAdapter.ts +271 -0
  335. package/packages/daemon/src/terminal/PtyAdapter.ts +140 -0
  336. package/packages/daemon/src/terminal/README.md +92 -0
  337. package/packages/daemon/src/tui/chrome/cheatsheet.ts +260 -0
  338. package/packages/daemon/src/tui/chrome/chip.ts +30 -0
  339. package/packages/daemon/src/tui/chrome/events.ts +119 -0
  340. package/packages/daemon/src/tui/chrome/kitty-keys.ts +55 -0
  341. package/packages/daemon/src/tui/chrome/menu.ts +289 -0
  342. package/packages/daemon/src/tui/chrome/notify.ts +195 -0
  343. package/packages/daemon/src/tui/chrome/panels.ts +111 -0
  344. package/packages/daemon/src/tui/chrome/sidebar.ts +222 -0
  345. package/packages/daemon/src/tui/chrome/snapshot.ts +425 -0
  346. package/packages/daemon/src/tui/chrome/statusline.ts +595 -0
  347. package/packages/daemon/src/tui/chrome/updater.ts +428 -0
  348. package/packages/daemon/src/tui/chrome/welcome.ts +124 -0
  349. package/packages/daemon/src/tui/compiled.ts +113 -0
  350. package/packages/daemon/src/tui/detect/classify.ts +193 -0
  351. package/packages/daemon/src/tui/detect/manifest-loader.ts +192 -0
  352. package/packages/daemon/src/tui/detect/manifest.ts +184 -0
  353. package/packages/daemon/src/tui/detect/manifests.ts +226 -0
  354. package/packages/daemon/src/tui/detect/process-tree.ts +197 -0
  355. package/packages/daemon/src/tui/detect/snapshot.ts +70 -0
  356. package/packages/daemon/src/tui/integrations/claude.ts +176 -0
  357. package/packages/daemon/src/tui/integrations/offer.ts +145 -0
  358. package/packages/daemon/src/tui/main.ts +70 -0
  359. package/packages/daemon/src/tui/mirror/control-client.ts +143 -0
  360. package/packages/daemon/src/tui/mirror/control.ts +97 -0
  361. package/packages/daemon/src/tui/mirror/pane-mirror.ts +81 -0
  362. package/packages/daemon/src/tui/mirror/viewer.tsx +166 -0
  363. package/packages/daemon/src/tui/team/CONTROL.md +50 -0
  364. package/packages/daemon/src/tui/team/entry.ts +11 -0
  365. package/packages/daemon/src/tui/team/fuzzy.ts +133 -0
  366. package/packages/daemon/src/tui/team/home.ts +170 -0
  367. package/packages/daemon/src/tui/team/index.tsx +1521 -0
  368. package/packages/daemon/src/tui/team/input.ts +34 -0
  369. package/packages/daemon/src/tui/team/keymap.ts +127 -0
  370. package/packages/daemon/src/tui/team/mouse.ts +29 -0
  371. package/packages/daemon/src/tui/team/nav.ts +31 -0
  372. package/packages/daemon/src/tui/team/preview.ts +34 -0
  373. package/packages/daemon/src/tui/team/projects.ts +191 -0
  374. package/packages/daemon/src/tui/team/report.ts +73 -0
  375. package/packages/daemon/src/tui/team/sessions.ts +344 -0
  376. package/packages/daemon/src/tui/team/tree.ts +62 -0
  377. package/packages/daemon/src/types.ts +13 -0
  378. package/packages/daemon/src/widgets/changes/README.md +3 -0
  379. package/packages/daemon/src/widgets/changes/index.tsx +691 -0
  380. package/packages/daemon/src/widgets/config/README.md +3 -0
  381. package/packages/daemon/src/widgets/config/index.tsx +481 -0
  382. package/packages/daemon/src/widgets/explorer/README.md +3 -0
  383. package/packages/daemon/src/widgets/explorer/index.tsx +456 -0
  384. package/packages/daemon/src/widgets/explorer/tree.tsx +165 -0
  385. package/packages/daemon/src/widgets/lib/grammar.ts +126 -0
  386. package/packages/daemon/src/widgets/lib/help-overlay.tsx +101 -0
  387. package/packages/daemon/src/widgets/lib/pane-comms.ts +209 -0
  388. package/packages/daemon/src/widgets/lib/theme.ts +194 -0
  389. package/packages/daemon/src/widgets/lib/watcher.ts +132 -0
  390. package/packages/daemon/src/widgets/preview/README.md +3 -0
  391. package/packages/daemon/src/widgets/preview/index.tsx +416 -0
  392. package/packages/daemon/src/widgets/resolve.ts +121 -0
  393. package/packages/daemon/src/widgets/setup/README.md +3 -0
  394. package/packages/daemon/src/widgets/setup/config-tree.tsx +246 -0
  395. package/packages/daemon/src/widgets/setup/index.tsx +341 -0
  396. package/packages/daemon/src/widgets/sidebar/index.tsx +527 -0
  397. package/packages/tmux-bridge/package.json +22 -0
  398. package/packages/tmux-bridge/src/errors.ts +28 -0
  399. package/packages/tmux-bridge/src/index.ts +31 -0
  400. package/packages/tmux-bridge/src/monitor.ts +77 -0
  401. package/packages/tmux-bridge/src/panes.ts +136 -0
  402. package/packages/tmux-bridge/src/runner.test.ts +501 -0
  403. package/packages/tmux-bridge/src/runner.ts +91 -0
  404. package/packages/tmux-bridge/src/sessions.ts +126 -0
  405. package/packages/tmux-bridge/src/targeting.test.ts +107 -0
  406. package/packages/tmux-bridge/src/targeting.ts +90 -0
  407. package/scripts/build-cli.mjs +101 -0
  408. package/scripts/build-tui.mjs +58 -0
  409. package/scripts/capture-codex-traffic.mjs +195 -0
  410. package/scripts/check-src-additions.sh +74 -0
  411. package/scripts/coverage-summary.mjs +68 -0
  412. package/scripts/install-git-hooks.js +53 -0
  413. package/scripts/merge-update-manifests.mjs +58 -0
  414. package/scripts/merge-update-manifests.test.mjs +82 -0
  415. package/scripts/pack-check-run.mjs +83 -0
  416. package/scripts/postinstall.js +53 -7
  417. package/scripts/prepublish-check.mjs +44 -0
  418. package/scripts/stress-test.ts +141 -0
  419. package/scripts/verify-endpoints.sh +90 -0
  420. package/skill/SKILL.md +203 -236
  421. package/dashboard/out/404/index.html +0 -1
  422. package/dashboard/out/404.html +0 -1
  423. package/dashboard/out/__next.__PAGE__.txt +0 -9
  424. package/dashboard/out/__next._full.txt +0 -21
  425. package/dashboard/out/__next._head.txt +0 -5
  426. package/dashboard/out/__next._index.txt +0 -7
  427. package/dashboard/out/__next._tree.txt +0 -4
  428. package/dashboard/out/_next/static/BDqbxLkiJrlXDfMXNb3cK/_buildManifest.js +0 -11
  429. package/dashboard/out/_next/static/BDqbxLkiJrlXDfMXNb3cK/_clientMiddlewareManifest.json +0 -1
  430. package/dashboard/out/_next/static/BDqbxLkiJrlXDfMXNb3cK/_ssgManifest.js +0 -1
  431. package/dashboard/out/_next/static/chunks/048e2449530877e2.js +0 -1
  432. package/dashboard/out/_next/static/chunks/053c57bda6abb959.js +0 -1
  433. package/dashboard/out/_next/static/chunks/056760c6c2dd9172.js +0 -1
  434. package/dashboard/out/_next/static/chunks/06ab47357b6d3e35.js +0 -1
  435. package/dashboard/out/_next/static/chunks/0921cbe5dfd6738e.js +0 -1
  436. package/dashboard/out/_next/static/chunks/0b2599bf468cf5ea.js +0 -1
  437. package/dashboard/out/_next/static/chunks/0c012eac08ef2c4f.js +0 -1
  438. package/dashboard/out/_next/static/chunks/0c29e87fcdcffac3.js +0 -1
  439. package/dashboard/out/_next/static/chunks/0e1e98854430c693.js +0 -1
  440. package/dashboard/out/_next/static/chunks/0e24498976a88976.js +0 -1
  441. package/dashboard/out/_next/static/chunks/0e5bf11ff0b9ab90.js +0 -1
  442. package/dashboard/out/_next/static/chunks/0eae0a45ab8416c8.js +0 -1
  443. package/dashboard/out/_next/static/chunks/104797400d9d38ad.js +0 -1
  444. package/dashboard/out/_next/static/chunks/10cfcfce475f9d2d.js +0 -1
  445. package/dashboard/out/_next/static/chunks/11bac38e7cfb4ecc.js +0 -1
  446. package/dashboard/out/_next/static/chunks/120c5f6501ec3529.js +0 -1
  447. package/dashboard/out/_next/static/chunks/121fceb2b1dcd79f.js +0 -1
  448. package/dashboard/out/_next/static/chunks/13726b63e1be6b98.js +0 -1
  449. package/dashboard/out/_next/static/chunks/140c6ce631514660.js +0 -1
  450. package/dashboard/out/_next/static/chunks/1435ee3a51174c97.js +0 -1
  451. package/dashboard/out/_next/static/chunks/14dc927d2e2cca91.js +0 -1
  452. package/dashboard/out/_next/static/chunks/179c3031b292d98e.js +0 -1
  453. package/dashboard/out/_next/static/chunks/181e88957c47e5c1.js +0 -1
  454. package/dashboard/out/_next/static/chunks/18f70ba23873c432.js +0 -1
  455. package/dashboard/out/_next/static/chunks/1b58303b027fd135.js +0 -1
  456. package/dashboard/out/_next/static/chunks/1b5f49a358dcc71e.js +0 -1
  457. package/dashboard/out/_next/static/chunks/1bba44b81585099a.js +0 -1
  458. package/dashboard/out/_next/static/chunks/1bea8dee19a3e9ae.js +0 -1
  459. package/dashboard/out/_next/static/chunks/1cfad21646fc250e.js +0 -1
  460. package/dashboard/out/_next/static/chunks/1d053dc9e1e428ef.js +0 -1
  461. package/dashboard/out/_next/static/chunks/1e7d7639c6f0ee5e.js +0 -1
  462. package/dashboard/out/_next/static/chunks/1f42504ca81463f1.js +0 -1
  463. package/dashboard/out/_next/static/chunks/20c92047399305b4.js +0 -1
  464. package/dashboard/out/_next/static/chunks/214560e9514a9a4d.js +0 -1
  465. package/dashboard/out/_next/static/chunks/21d4ef106914e997.js +0 -1
  466. package/dashboard/out/_next/static/chunks/2586e83fc3dc2588.js +0 -1
  467. package/dashboard/out/_next/static/chunks/267136a09e94f5c2.js +0 -1
  468. package/dashboard/out/_next/static/chunks/271c50b329917c10.js +0 -1
  469. package/dashboard/out/_next/static/chunks/27fccecefffd88b5.js +0 -1
  470. package/dashboard/out/_next/static/chunks/28f058ed331315b6.js +0 -1
  471. package/dashboard/out/_next/static/chunks/28f704f2cc5713eb.js +0 -1
  472. package/dashboard/out/_next/static/chunks/290f67a6cd150a98.js +0 -1
  473. package/dashboard/out/_next/static/chunks/2ad12f4dcc30d30a.js +0 -1
  474. package/dashboard/out/_next/static/chunks/2b650b172078ab92.js +0 -1
  475. package/dashboard/out/_next/static/chunks/2bd91076019a6453.js +0 -1
  476. package/dashboard/out/_next/static/chunks/2e1278563a8e26be.js +0 -1
  477. package/dashboard/out/_next/static/chunks/309eb70780a3d67d.js +0 -1
  478. package/dashboard/out/_next/static/chunks/30f71950992e2307.js +0 -1
  479. package/dashboard/out/_next/static/chunks/31191873c2075784.js +0 -1
  480. package/dashboard/out/_next/static/chunks/31a790921a0c035e.js +0 -1
  481. package/dashboard/out/_next/static/chunks/34f8d7a5a06e8e32.js +0 -1
  482. package/dashboard/out/_next/static/chunks/36b3716436d9bc9d.js +0 -1
  483. package/dashboard/out/_next/static/chunks/3770b7d0ff004de3.js +0 -1
  484. package/dashboard/out/_next/static/chunks/381ab3bd4cffbf4d.js +0 -1
  485. package/dashboard/out/_next/static/chunks/38aa4eada5dcd1a4.js +0 -1
  486. package/dashboard/out/_next/static/chunks/39723132b78cb77e.js +0 -1
  487. package/dashboard/out/_next/static/chunks/399efdcc3fe56e09.js +0 -1
  488. package/dashboard/out/_next/static/chunks/3a8431a9221b0706.js +0 -1
  489. package/dashboard/out/_next/static/chunks/3a9b40810ce88cbf.js +0 -1
  490. package/dashboard/out/_next/static/chunks/3b322e3e9476ecdf.js +0 -1
  491. package/dashboard/out/_next/static/chunks/3bb14befeeb08c28.js +0 -1
  492. package/dashboard/out/_next/static/chunks/3c99637ebd462b20.js +0 -1
  493. package/dashboard/out/_next/static/chunks/3cbb9217d56459d8.js +0 -1
  494. package/dashboard/out/_next/static/chunks/3d438e0929a762f7.js +0 -1
  495. package/dashboard/out/_next/static/chunks/3e6d4834e0752f76.js +0 -2
  496. package/dashboard/out/_next/static/chunks/3e6f8cedaad4e89b.js +0 -1
  497. package/dashboard/out/_next/static/chunks/3e701259ce1b53e3.js +0 -1
  498. package/dashboard/out/_next/static/chunks/41562f7ab7c033eb.js +0 -1
  499. package/dashboard/out/_next/static/chunks/418fadd8a94e2fd7.js +0 -1
  500. package/dashboard/out/_next/static/chunks/42345437bb922e9c.js +0 -1
  501. package/dashboard/out/_next/static/chunks/434b6bd78c97b668.js +0 -1
  502. package/dashboard/out/_next/static/chunks/434febe897d33e2d.js +0 -1
  503. package/dashboard/out/_next/static/chunks/45d28707dd8ce1c1.js +0 -1
  504. package/dashboard/out/_next/static/chunks/4620a640e88cb1b7.js +0 -1
  505. package/dashboard/out/_next/static/chunks/468f8eb604502ea4.js +0 -1
  506. package/dashboard/out/_next/static/chunks/495f5cedf8afe823.js +0 -1
  507. package/dashboard/out/_next/static/chunks/49a89d1704d27740.js +0 -1
  508. package/dashboard/out/_next/static/chunks/49e5c37d15f63def.js +0 -1
  509. package/dashboard/out/_next/static/chunks/4a46ad186a8587ee.css +0 -2
  510. package/dashboard/out/_next/static/chunks/4a5c728574935d50.js +0 -1
  511. package/dashboard/out/_next/static/chunks/4b27ebd4d9304d8f.js +0 -1
  512. package/dashboard/out/_next/static/chunks/4b965aa320a9b358.js +0 -1
  513. package/dashboard/out/_next/static/chunks/4bb2da90bbe5794f.js +0 -1
  514. package/dashboard/out/_next/static/chunks/4d2f1c6f631e4b85.js +0 -1
  515. package/dashboard/out/_next/static/chunks/4d696d5a64dab42e.js +0 -1
  516. package/dashboard/out/_next/static/chunks/4f660dadb3f1e9e2.js +0 -1
  517. package/dashboard/out/_next/static/chunks/507b50d47f949333.js +0 -1
  518. package/dashboard/out/_next/static/chunks/50b1b7063bb044e2.js +0 -1
  519. package/dashboard/out/_next/static/chunks/50c0c2e3c4f02508.js +0 -1
  520. package/dashboard/out/_next/static/chunks/50d7ba9803e65b02.js +0 -1
  521. package/dashboard/out/_next/static/chunks/51535a6d4c98c7a4.js +0 -1
  522. package/dashboard/out/_next/static/chunks/526de6cc16c7dd2f.js +0 -1
  523. package/dashboard/out/_next/static/chunks/5307604f8632b3fd.js +0 -1
  524. package/dashboard/out/_next/static/chunks/5480bd722260f231.js +0 -1
  525. package/dashboard/out/_next/static/chunks/54c61c82e5f1dca5.js +0 -1
  526. package/dashboard/out/_next/static/chunks/555de6ac6bb9034c.js +0 -1
  527. package/dashboard/out/_next/static/chunks/562b89ee76a4b90c.js +0 -1
  528. package/dashboard/out/_next/static/chunks/5747f9a32edff429.js +0 -1
  529. package/dashboard/out/_next/static/chunks/57ee141430b4c05c.js +0 -1
  530. package/dashboard/out/_next/static/chunks/584c066a0837dd9a.js +0 -1
  531. package/dashboard/out/_next/static/chunks/5856aed4670a6253.js +0 -1
  532. package/dashboard/out/_next/static/chunks/58fe563414726511.js +0 -1
  533. package/dashboard/out/_next/static/chunks/5948196b2729b18c.js +0 -1
  534. package/dashboard/out/_next/static/chunks/5ab77c69e7306f97.js +0 -1
  535. package/dashboard/out/_next/static/chunks/5b3fa4c99d61611c.js +0 -1
  536. package/dashboard/out/_next/static/chunks/5cc87abaef616661.js +0 -1
  537. package/dashboard/out/_next/static/chunks/5dfa7913f99bb966.js +0 -1
  538. package/dashboard/out/_next/static/chunks/5e49b008432770f1.js +0 -1
  539. package/dashboard/out/_next/static/chunks/5e5a33dd81c45c47.js +0 -1
  540. package/dashboard/out/_next/static/chunks/5ee61bed638eb8a8.js +0 -1
  541. package/dashboard/out/_next/static/chunks/5eed557b9f45ae4a.js +0 -1
  542. package/dashboard/out/_next/static/chunks/60446823a7d30c1b.js +0 -1
  543. package/dashboard/out/_next/static/chunks/605150c490861442.js +0 -1
  544. package/dashboard/out/_next/static/chunks/609056d51c0bf332.js +0 -1
  545. package/dashboard/out/_next/static/chunks/60ec91dfeb50071b.js +0 -1
  546. package/dashboard/out/_next/static/chunks/61bc7be0bba6a33f.js +0 -1
  547. package/dashboard/out/_next/static/chunks/61f4a5c9ce23e55e.js +0 -1
  548. package/dashboard/out/_next/static/chunks/63aae3585be04e65.js +0 -1
  549. package/dashboard/out/_next/static/chunks/64e0e1ee7ef4f01b.js +0 -1
  550. package/dashboard/out/_next/static/chunks/66e9b4c26ff1aaaf.js +0 -1
  551. package/dashboard/out/_next/static/chunks/67068847aa1b5e98.js +0 -1
  552. package/dashboard/out/_next/static/chunks/68d7de1f2e202c26.js +0 -1
  553. package/dashboard/out/_next/static/chunks/698ca3ea1937ba4f.js +0 -1
  554. package/dashboard/out/_next/static/chunks/69eb97c24b5b6b9d.js +0 -1
  555. package/dashboard/out/_next/static/chunks/6b1ac098c228a479.js +0 -1
  556. package/dashboard/out/_next/static/chunks/6bb8020cb796bcc1.js +0 -1
  557. package/dashboard/out/_next/static/chunks/6cf8b1db17f2a155.js +0 -1
  558. package/dashboard/out/_next/static/chunks/6e7613643906ea88.js +0 -1
  559. package/dashboard/out/_next/static/chunks/6ea27ceb2e6feae5.js +0 -1
  560. package/dashboard/out/_next/static/chunks/6f95a8dbcf23dded.js +0 -1
  561. package/dashboard/out/_next/static/chunks/6fd44e759d82f64e.js +0 -1
  562. package/dashboard/out/_next/static/chunks/716ec29c268c38f6.js +0 -1
  563. package/dashboard/out/_next/static/chunks/717b399dfcf7c02c.js +0 -1
  564. package/dashboard/out/_next/static/chunks/72badd90e1c91348.js +0 -1
  565. package/dashboard/out/_next/static/chunks/72f9296dbb7ae3c4.js +0 -1
  566. package/dashboard/out/_next/static/chunks/73aa31e1144d8191.js +0 -1
  567. package/dashboard/out/_next/static/chunks/73f98ded8fe2e879.js +0 -1
  568. package/dashboard/out/_next/static/chunks/740a2e8ace15e13b.js +0 -1
  569. package/dashboard/out/_next/static/chunks/74e57c16e7304b6b.js +0 -1
  570. package/dashboard/out/_next/static/chunks/7628dead4d113df2.js +0 -1
  571. package/dashboard/out/_next/static/chunks/7717c88c07ed96e6.js +0 -1
  572. package/dashboard/out/_next/static/chunks/775581f7956d9a27.js +0 -1
  573. package/dashboard/out/_next/static/chunks/77d3b6661befdb98.js +0 -1
  574. package/dashboard/out/_next/static/chunks/78435c0e1c77fea7.js +0 -1
  575. package/dashboard/out/_next/static/chunks/791336748b9c9393.js +0 -1
  576. package/dashboard/out/_next/static/chunks/79ea68dfae65ef2f.js +0 -1
  577. package/dashboard/out/_next/static/chunks/7bae777a472eb13c.js +0 -1
  578. package/dashboard/out/_next/static/chunks/7fd847f47237a35c.js +0 -1
  579. package/dashboard/out/_next/static/chunks/804d718be0370058.css +0 -1
  580. package/dashboard/out/_next/static/chunks/807cb3c1923995ab.js +0 -1
  581. package/dashboard/out/_next/static/chunks/8286b39407d94447.js +0 -1
  582. package/dashboard/out/_next/static/chunks/84e4305b8dc830ed.js +0 -1
  583. package/dashboard/out/_next/static/chunks/850f99dbfabb53e0.js +0 -1
  584. package/dashboard/out/_next/static/chunks/85594127e66b6b7f.js +0 -1
  585. package/dashboard/out/_next/static/chunks/858c11169c183c9c.js +0 -1
  586. package/dashboard/out/_next/static/chunks/85e27005dfe4c3e3.js +0 -1
  587. package/dashboard/out/_next/static/chunks/8707bd3d8ddc1f1c.js +0 -1
  588. package/dashboard/out/_next/static/chunks/8851e5d7ef894973.js +0 -1
  589. package/dashboard/out/_next/static/chunks/88ba3782cc614989.js +0 -1
  590. package/dashboard/out/_next/static/chunks/8a0c9a181784c2ef.js +0 -1
  591. package/dashboard/out/_next/static/chunks/8ad01ae355a6e7f6.js +0 -1
  592. package/dashboard/out/_next/static/chunks/8d2ed93b0d0a4b4f.js +0 -1
  593. package/dashboard/out/_next/static/chunks/8dc352ebd5310d3c.js +0 -1
  594. package/dashboard/out/_next/static/chunks/8dd1d722c8c1a22c.js +0 -1
  595. package/dashboard/out/_next/static/chunks/8e60fe307e3e4986.js +0 -1
  596. package/dashboard/out/_next/static/chunks/8eea4dd71e25f32a.js +0 -1
  597. package/dashboard/out/_next/static/chunks/8f468a65bac34eaa.js +0 -1
  598. package/dashboard/out/_next/static/chunks/9057e5382d6a5059.js +0 -1
  599. package/dashboard/out/_next/static/chunks/931d056437805ecb.js +0 -1
  600. package/dashboard/out/_next/static/chunks/954eb11648dd8cff.js +0 -1
  601. package/dashboard/out/_next/static/chunks/955034d876d14bb3.js +0 -1
  602. package/dashboard/out/_next/static/chunks/966c4895773249f6.js +0 -1
  603. package/dashboard/out/_next/static/chunks/96aff410a6ab106c.js +0 -1
  604. package/dashboard/out/_next/static/chunks/99b396c821c1dd2d.js +0 -1
  605. package/dashboard/out/_next/static/chunks/9a255fd2cf4922ae.js +0 -1
  606. package/dashboard/out/_next/static/chunks/9b1f6aa73bc864b2.js +0 -1
  607. package/dashboard/out/_next/static/chunks/9b9ce582c533aa79.js +0 -1
  608. package/dashboard/out/_next/static/chunks/9c19bd3c773c6611.js +0 -1
  609. package/dashboard/out/_next/static/chunks/9ceeaa847eb15ca2.js +0 -1
  610. package/dashboard/out/_next/static/chunks/9d2e6e7b8b65f845.js +0 -1
  611. package/dashboard/out/_next/static/chunks/9de23802066128ff.js +0 -1
  612. package/dashboard/out/_next/static/chunks/9e327f94b3701170.js +0 -1
  613. package/dashboard/out/_next/static/chunks/9e7818421c2d455a.js +0 -1
  614. package/dashboard/out/_next/static/chunks/9e935acbcf2fb519.js +0 -1
  615. package/dashboard/out/_next/static/chunks/9ed9f68340343b51.js +0 -1
  616. package/dashboard/out/_next/static/chunks/9f94a0242455fc20.js +0 -1
  617. package/dashboard/out/_next/static/chunks/9fff46b5aaecf47e.js +0 -1
  618. package/dashboard/out/_next/static/chunks/a06d267a5c557657.js +0 -1
  619. package/dashboard/out/_next/static/chunks/a0eb8c81c54722fe.js +0 -1
  620. package/dashboard/out/_next/static/chunks/a16808e83106427d.js +0 -1
  621. package/dashboard/out/_next/static/chunks/a2215e2bc72739ef.js +0 -1
  622. package/dashboard/out/_next/static/chunks/a2de9e6696eb9c17.js +0 -1
  623. package/dashboard/out/_next/static/chunks/a33420b8c14090d6.js +0 -1
  624. package/dashboard/out/_next/static/chunks/a360bffef39d818b.js +0 -1
  625. package/dashboard/out/_next/static/chunks/a42852fdf5287cf5.js +0 -1
  626. package/dashboard/out/_next/static/chunks/a4efc88488322b67.js +0 -1
  627. package/dashboard/out/_next/static/chunks/a696a91d14101bdb.js +0 -1
  628. package/dashboard/out/_next/static/chunks/a6dad97d9634a72d.js +0 -1
  629. package/dashboard/out/_next/static/chunks/a6dad97d9634a72d.js.map +0 -1
  630. package/dashboard/out/_next/static/chunks/a705c7261712bd8e.js +0 -1
  631. package/dashboard/out/_next/static/chunks/a7d1e4b067ace180.js +0 -1
  632. package/dashboard/out/_next/static/chunks/a8590c121a7efaa5.js +0 -1
  633. package/dashboard/out/_next/static/chunks/a95953a83a6df6cf.js +0 -1
  634. package/dashboard/out/_next/static/chunks/a9d0a757d3b4afed.js +0 -1
  635. package/dashboard/out/_next/static/chunks/a9dc35514619c872.js +0 -1
  636. package/dashboard/out/_next/static/chunks/aae0253c73fba984.js +0 -193
  637. package/dashboard/out/_next/static/chunks/ab1821552066a74d.js +0 -1
  638. package/dashboard/out/_next/static/chunks/ac96bc0eccebe15a.js +0 -1
  639. package/dashboard/out/_next/static/chunks/acc03cfaaf6bb30f.js +0 -1
  640. package/dashboard/out/_next/static/chunks/acc298ae059b9fe4.js +0 -1
  641. package/dashboard/out/_next/static/chunks/ad076b6e996d250c.js +0 -1
  642. package/dashboard/out/_next/static/chunks/ae53b64af7ba16d5.js +0 -1
  643. package/dashboard/out/_next/static/chunks/ae5da7fa4bc5fa95.js +0 -1
  644. package/dashboard/out/_next/static/chunks/aefcf0eb033a155e.js +0 -1
  645. package/dashboard/out/_next/static/chunks/b12d43100ee10526.js +0 -1
  646. package/dashboard/out/_next/static/chunks/b137952dd5566a41.js +0 -1
  647. package/dashboard/out/_next/static/chunks/b2832d8a2d332a47.js +0 -1
  648. package/dashboard/out/_next/static/chunks/b417aa09c15f63c6.js +0 -1
  649. package/dashboard/out/_next/static/chunks/b48e152ba7bf6caf.js +0 -1
  650. package/dashboard/out/_next/static/chunks/b4cbef8e4714bf92.js +0 -1
  651. package/dashboard/out/_next/static/chunks/b568ff8383a37f53.js +0 -1
  652. package/dashboard/out/_next/static/chunks/b6e1495dd89a39e3.js +0 -1
  653. package/dashboard/out/_next/static/chunks/b73a21bd67528440.js +0 -1
  654. package/dashboard/out/_next/static/chunks/b77ee62bc71dcec7.js +0 -1
  655. package/dashboard/out/_next/static/chunks/b7f454615c11d4eb.js +0 -1
  656. package/dashboard/out/_next/static/chunks/b818ea32a839590f.js +0 -1
  657. package/dashboard/out/_next/static/chunks/b901ce78c1c65d66.js +0 -1
  658. package/dashboard/out/_next/static/chunks/b93d647b803be9fa.js +0 -1
  659. package/dashboard/out/_next/static/chunks/b960b09ff1ecd6bb.js +0 -1
  660. package/dashboard/out/_next/static/chunks/ba717c7779a778fc.js +0 -1
  661. package/dashboard/out/_next/static/chunks/bacb0ae7458d18b6.js +0 -1
  662. package/dashboard/out/_next/static/chunks/bb51f68b27346852.js +0 -1
  663. package/dashboard/out/_next/static/chunks/bb67f22e1ab632ae.js +0 -1
  664. package/dashboard/out/_next/static/chunks/bbae97ec58d1bb9d.js +0 -1
  665. package/dashboard/out/_next/static/chunks/bbaf38ee90307765.js +0 -1
  666. package/dashboard/out/_next/static/chunks/be01598fe1fce5db.js +0 -1
  667. package/dashboard/out/_next/static/chunks/bf4cbbc095987fec.js +0 -1
  668. package/dashboard/out/_next/static/chunks/c18f823797d57446.js +0 -1
  669. package/dashboard/out/_next/static/chunks/c1bcece34ec5b295.js +0 -1
  670. package/dashboard/out/_next/static/chunks/c1ccbc3a51adaf0a.js +0 -1
  671. package/dashboard/out/_next/static/chunks/c1f54a628f27791c.js +0 -1
  672. package/dashboard/out/_next/static/chunks/c21916bf5d232151.js +0 -1
  673. package/dashboard/out/_next/static/chunks/c27e570f0fc2f78b.js +0 -1
  674. package/dashboard/out/_next/static/chunks/c322b8005eebc0d8.js +0 -1
  675. package/dashboard/out/_next/static/chunks/c3900ac2b009b764.js +0 -1
  676. package/dashboard/out/_next/static/chunks/c3c597c8eb77ad6b.js +0 -1
  677. package/dashboard/out/_next/static/chunks/c58d45c1d88e208c.js +0 -1
  678. package/dashboard/out/_next/static/chunks/c63875998d7a655f.js +0 -1
  679. package/dashboard/out/_next/static/chunks/c6eaa7c8e7209c8e.js +0 -1
  680. package/dashboard/out/_next/static/chunks/c6f820f71162a59a.js +0 -1
  681. package/dashboard/out/_next/static/chunks/c7ce0941d1dfe7ed.js +0 -1
  682. package/dashboard/out/_next/static/chunks/c877259f784ec8e5.js +0 -1
  683. package/dashboard/out/_next/static/chunks/cb8057e86aaa1c68.js +0 -1
  684. package/dashboard/out/_next/static/chunks/ccb4e306ee4859b1.js +0 -1
  685. package/dashboard/out/_next/static/chunks/ccde62b0fa8112eb.js +0 -1
  686. package/dashboard/out/_next/static/chunks/cd421f0971c63c31.js +0 -1
  687. package/dashboard/out/_next/static/chunks/cde0317494d4adb7.js +0 -1
  688. package/dashboard/out/_next/static/chunks/cfae64434b92b8b6.js +0 -1
  689. package/dashboard/out/_next/static/chunks/cfc0e19310ec0a36.js +0 -1
  690. package/dashboard/out/_next/static/chunks/d0f344c7d0bcb59a.js +0 -1
  691. package/dashboard/out/_next/static/chunks/d1871c73e74e1f50.js +0 -1
  692. package/dashboard/out/_next/static/chunks/d18f658850711061.js +0 -1
  693. package/dashboard/out/_next/static/chunks/d25d9c48880697f6.js +0 -1
  694. package/dashboard/out/_next/static/chunks/d3f0a72bbc3060b0.js +0 -1
  695. package/dashboard/out/_next/static/chunks/d5fca429bc89060b.js +0 -1
  696. package/dashboard/out/_next/static/chunks/d6a6c75c9a4bef49.js +0 -1
  697. package/dashboard/out/_next/static/chunks/d6a8f93aa8f1e345.js +0 -1
  698. package/dashboard/out/_next/static/chunks/d7deab676b19ba0e.js +0 -1
  699. package/dashboard/out/_next/static/chunks/d80030dde88cec85.js +0 -1
  700. package/dashboard/out/_next/static/chunks/da84f9774c076ff1.js +0 -1
  701. package/dashboard/out/_next/static/chunks/da98ecc6b9b0ceb2.js +0 -1
  702. package/dashboard/out/_next/static/chunks/db550aabce60b912.js +0 -4
  703. package/dashboard/out/_next/static/chunks/dc87f77fcc029482.js +0 -1
  704. package/dashboard/out/_next/static/chunks/dd05f30acdb63a53.js +0 -1
  705. package/dashboard/out/_next/static/chunks/dea150155499b903.js +0 -1
  706. package/dashboard/out/_next/static/chunks/df4358754ff1d5e8.js +0 -1
  707. package/dashboard/out/_next/static/chunks/df8b21ff12d23b0e.js +0 -1
  708. package/dashboard/out/_next/static/chunks/df8fc68d77debf2c.js +0 -1
  709. package/dashboard/out/_next/static/chunks/df9ed1ffec90589f.js +0 -1
  710. package/dashboard/out/_next/static/chunks/dfa65ece1598f934.js +0 -1
  711. package/dashboard/out/_next/static/chunks/dfaab5cdd41a20d9.js +0 -1
  712. package/dashboard/out/_next/static/chunks/e00c03c942b5ae3e.js +0 -1
  713. package/dashboard/out/_next/static/chunks/e02d27cf679bece1.js +0 -1
  714. package/dashboard/out/_next/static/chunks/e0b747585f78513a.js +0 -1
  715. package/dashboard/out/_next/static/chunks/e19b71ca23fd7df0.js +0 -1
  716. package/dashboard/out/_next/static/chunks/e21cbe89d0cda120.js +0 -1
  717. package/dashboard/out/_next/static/chunks/e2a0386930edd34f.js +0 -1
  718. package/dashboard/out/_next/static/chunks/e375de19a36e2f38.js +0 -1
  719. package/dashboard/out/_next/static/chunks/e5241b4a6496a9e0.js +0 -1
  720. package/dashboard/out/_next/static/chunks/e569dd07c96eb4dd.js +0 -1
  721. package/dashboard/out/_next/static/chunks/e61c3ea91233f948.js +0 -1
  722. package/dashboard/out/_next/static/chunks/e73b42c5d34c4c28.js +0 -1
  723. package/dashboard/out/_next/static/chunks/e7c5b2105f651e87.js +0 -1
  724. package/dashboard/out/_next/static/chunks/e878e58a69bb01b6.js +0 -1
  725. package/dashboard/out/_next/static/chunks/e8f090a4dc571062.js +0 -1
  726. package/dashboard/out/_next/static/chunks/e98dc34dac91cdad.js +0 -1
  727. package/dashboard/out/_next/static/chunks/ea67cf7a0c5e7233.js +0 -1
  728. package/dashboard/out/_next/static/chunks/eacc98a1e3512fa9.js +0 -1
  729. package/dashboard/out/_next/static/chunks/eae9cd74d9bbed8b.js +0 -1
  730. package/dashboard/out/_next/static/chunks/eb187fd345852b34.js +0 -1
  731. package/dashboard/out/_next/static/chunks/ecea46df7a40b427.js +0 -1
  732. package/dashboard/out/_next/static/chunks/ecf48b83f4245d9c.js +0 -1
  733. package/dashboard/out/_next/static/chunks/eda41732bf966c6d.js +0 -1
  734. package/dashboard/out/_next/static/chunks/ee174a433049f43a.js +0 -1
  735. package/dashboard/out/_next/static/chunks/ee66b2d3b76de72e.js +0 -1
  736. package/dashboard/out/_next/static/chunks/ef058d3041c3d8ab.js +0 -1
  737. package/dashboard/out/_next/static/chunks/f3544b800b0d4969.js +0 -1
  738. package/dashboard/out/_next/static/chunks/f3b280e604b97509.js +0 -1
  739. package/dashboard/out/_next/static/chunks/f42e1d3693232993.js +0 -1
  740. package/dashboard/out/_next/static/chunks/f5a5fdd80166d304.js +0 -1
  741. package/dashboard/out/_next/static/chunks/f60adc5dd6169316.js +0 -1
  742. package/dashboard/out/_next/static/chunks/f6255bc2e6c68ce8.js +0 -1
  743. package/dashboard/out/_next/static/chunks/f6bb677d2d8840db.js +0 -1
  744. package/dashboard/out/_next/static/chunks/f6f3bf016239c33a.js +0 -1
  745. package/dashboard/out/_next/static/chunks/f6f57a46cd074bfe.js +0 -1
  746. package/dashboard/out/_next/static/chunks/f7feb9c1199e8cf6.js +0 -1
  747. package/dashboard/out/_next/static/chunks/f831087bf964cc3d.js +0 -1
  748. package/dashboard/out/_next/static/chunks/fa5a2f7244935aa2.js +0 -1
  749. package/dashboard/out/_next/static/chunks/fa73f36df4c38fa0.js +0 -1
  750. package/dashboard/out/_next/static/chunks/faa1461722d6a88d.js +0 -1
  751. package/dashboard/out/_next/static/chunks/fbf706b9a0edb7e6.js +0 -1
  752. package/dashboard/out/_next/static/chunks/fc2b8c8b7446bbc2.js +0 -1
  753. package/dashboard/out/_next/static/chunks/fd516f3930c128c1.js +0 -1
  754. package/dashboard/out/_next/static/chunks/fd663e7ff8de4887.js +0 -1
  755. package/dashboard/out/_next/static/chunks/fe5b656cc9bdd60e.js +0 -1
  756. package/dashboard/out/_next/static/chunks/turbopack-2f5dec4a537c0ee7.js +0 -4
  757. package/dashboard/out/_next/static/media/02263ebadd758ea4-s.8da66e7f.woff2 +0 -0
  758. package/dashboard/out/_next/static/media/2fe89d53234c61d4-s.cb53f04b.woff2 +0 -0
  759. package/dashboard/out/_next/static/media/59b15b4bcd7b1eb5-s.afa48be3.woff2 +0 -0
  760. package/dashboard/out/_next/static/media/5e05ae5b48faa55e-s.6b5ea6af.woff2 +0 -0
  761. package/dashboard/out/_next/static/media/68757d6cddeff913-s.e6cd1753.woff2 +0 -0
  762. package/dashboard/out/_next/static/media/99e609270109b47d-s.p.64b9304e.woff2 +0 -0
  763. package/dashboard/out/_next/static/media/a7afbb44bec2bb18-s.1dcddae6.woff2 +0 -0
  764. package/dashboard/out/_next/static/media/e390973e931a41c5-s.a82ecf4e.woff2 +0 -0
  765. package/dashboard/out/_next/static/media/e532fa1b9921e1cd-s.764b43eb.woff2 +0 -0
  766. package/dashboard/out/_next/static/media/effe91970fc4db64-s.p.19510058.woff2 +0 -0
  767. package/dashboard/out/_not-found/__next._full.txt +0 -15
  768. package/dashboard/out/_not-found/__next._head.txt +0 -5
  769. package/dashboard/out/_not-found/__next._index.txt +0 -7
  770. package/dashboard/out/_not-found/__next._not-found.__PAGE__.txt +0 -5
  771. package/dashboard/out/_not-found/__next._not-found.txt +0 -4
  772. package/dashboard/out/_not-found/__next._tree.txt +0 -2
  773. package/dashboard/out/_not-found/index.html +0 -1
  774. package/dashboard/out/_not-found/index.txt +0 -15
  775. package/dashboard/out/index.html +0 -1
  776. package/dashboard/out/index.txt +0 -21
  777. package/dashboard/out/project/__fallback/__next._full.txt +0 -19
  778. package/dashboard/out/project/__fallback/__next._head.txt +0 -5
  779. package/dashboard/out/project/__fallback/__next._index.txt +0 -7
  780. package/dashboard/out/project/__fallback/__next._tree.txt +0 -5
  781. package/dashboard/out/project/__fallback/__next.project.$d$name.__PAGE__.txt +0 -7
  782. package/dashboard/out/project/__fallback/__next.project.$d$name.txt +0 -4
  783. package/dashboard/out/project/__fallback/__next.project.txt +0 -4
  784. package/dashboard/out/project/__fallback/index.html +0 -1
  785. package/dashboard/out/project/__fallback/index.txt +0 -19
  786. package/src/__tests__/support.ts +0 -186
  787. package/src/attach.ts +0 -20
  788. package/src/cli.test.ts +0 -314
  789. package/src/command-center/discovery.test.ts +0 -265
  790. package/src/command-center/discovery.ts +0 -296
  791. package/src/command-center/schemas.ts +0 -57
  792. package/src/command-center/server.test.ts +0 -814
  793. package/src/command-center/server.ts +0 -1427
  794. package/src/command-center/static.test.ts +0 -105
  795. package/src/command-center/static.ts +0 -122
  796. package/src/config-cli.test.ts +0 -86
  797. package/src/config.test.ts +0 -205
  798. package/src/config.ts +0 -313
  799. package/src/detect.test.ts +0 -142
  800. package/src/dispatch.ts +0 -102
  801. package/src/doctor.test.ts +0 -119
  802. package/src/doctor.ts +0 -167
  803. package/src/init.test.ts +0 -101
  804. package/src/init.ts +0 -211
  805. package/src/inspect.test.ts +0 -67
  806. package/src/inspect.ts +0 -212
  807. package/src/integration.test.ts.skip +0 -276
  808. package/src/launch.test.ts +0 -149
  809. package/src/launch.ts +0 -583
  810. package/src/lib/auth/auth-service.test.ts +0 -178
  811. package/src/lib/auth/middleware.test.ts +0 -119
  812. package/src/lib/authorship.test.ts +0 -242
  813. package/src/lib/cast/recorder.test.ts +0 -127
  814. package/src/lib/cast/recorder.ts +0 -148
  815. package/src/lib/daemon-watchdog.ts +0 -102
  816. package/src/lib/daemon.ts +0 -440
  817. package/src/lib/dot-path.test.ts +0 -66
  818. package/src/lib/errors.ts +0 -44
  819. package/src/lib/event-log.test.ts +0 -189
  820. package/src/lib/event-log.ts +0 -237
  821. package/src/lib/github-pr.ts +0 -182
  822. package/src/lib/hq/client.test.ts +0 -154
  823. package/src/lib/hq/client.ts +0 -142
  824. package/src/lib/hq/mdns.test.ts +0 -54
  825. package/src/lib/hq/mdns.ts +0 -88
  826. package/src/lib/hq/registry.test.ts +0 -237
  827. package/src/lib/hq/registry.ts +0 -145
  828. package/src/lib/hq/types.ts +0 -44
  829. package/src/lib/ipc/socket-protocol.test.ts +0 -126
  830. package/src/lib/ipc/socket-protocol.ts +0 -324
  831. package/src/lib/launch-plan.test.ts +0 -119
  832. package/src/lib/log.test.ts +0 -39
  833. package/src/lib/log.ts +0 -71
  834. package/src/lib/metrics.test.ts +0 -213
  835. package/src/lib/metrics.ts +0 -345
  836. package/src/lib/orchestrator.test.ts +0 -2358
  837. package/src/lib/orchestrator.ts +0 -1799
  838. package/src/lib/output.ts +0 -76
  839. package/src/lib/plan-store.test.ts +0 -148
  840. package/src/lib/plan-store.ts +0 -131
  841. package/src/lib/research.test.ts +0 -208
  842. package/src/lib/research.ts +0 -475
  843. package/src/lib/round-trip.test.ts +0 -341
  844. package/src/lib/session-monitor.test.ts +0 -152
  845. package/src/lib/session-monitor.ts +0 -284
  846. package/src/lib/session-options.test.ts +0 -146
  847. package/src/lib/shell.test.ts +0 -20
  848. package/src/lib/sizes.test.ts +0 -73
  849. package/src/lib/skill-registry.test.ts +0 -134
  850. package/src/lib/skill-registry.ts +0 -86
  851. package/src/lib/slugify.test.ts +0 -35
  852. package/src/lib/task-store.ts +0 -352
  853. package/src/lib/tmux.test.ts +0 -500
  854. package/src/lib/tmux.ts +0 -372
  855. package/src/lib/token-tracker.test.ts +0 -102
  856. package/src/lib/token-tracker.ts +0 -70
  857. package/src/lib/tunnels/cloudflare.test.ts +0 -73
  858. package/src/lib/tunnels/cloudflare.ts +0 -254
  859. package/src/lib/tunnels/manager.test.ts +0 -63
  860. package/src/lib/tunnels/manager.ts +0 -132
  861. package/src/lib/tunnels/ngrok.test.ts +0 -94
  862. package/src/lib/tunnels/ngrok.ts +0 -261
  863. package/src/lib/tunnels/tailscale.test.ts +0 -103
  864. package/src/lib/tunnels/tailscale.ts +0 -1048
  865. package/src/lib/tunnels/types.ts +0 -44
  866. package/src/lib/validation.test.ts +0 -289
  867. package/src/lib/validation.ts +0 -123
  868. package/src/lib/webhook.ts +0 -51
  869. package/src/lib/workflow-store.ts +0 -209
  870. package/src/lib/ws-v3/protocol.test.ts +0 -127
  871. package/src/lib/ws-v3/protocol.ts +0 -160
  872. package/src/lib/yaml-io.test.ts +0 -125
  873. package/src/ls.test.ts +0 -76
  874. package/src/metrics-cli.ts +0 -177
  875. package/src/notify.ts +0 -85
  876. package/src/orchestrator-status.ts +0 -228
  877. package/src/plan.ts +0 -117
  878. package/src/postinstall.test.ts +0 -79
  879. package/src/remote.test.ts +0 -115
  880. package/src/remote.ts +0 -148
  881. package/src/restart.ts +0 -24
  882. package/src/schemas/domain.ts +0 -422
  883. package/src/schemas/ide-config.ts +0 -148
  884. package/src/schemas/index.ts +0 -53
  885. package/src/send.test.ts +0 -70
  886. package/src/send.ts +0 -181
  887. package/src/skill.test.ts +0 -114
  888. package/src/skill.ts +0 -138
  889. package/src/status.ts +0 -66
  890. package/src/stop.test.ts +0 -151
  891. package/src/stop.ts +0 -37
  892. package/src/task.test.ts +0 -1466
  893. package/src/task.ts +0 -1143
  894. package/src/tunnel.test.ts +0 -80
  895. package/src/tunnel.ts +0 -133
  896. package/src/types.ts +0 -15
  897. package/src/ui/web/utils/color.test.ts +0 -93
  898. package/src/validate.test.ts +0 -385
  899. package/src/widgets/changes/index.tsx +0 -576
  900. package/src/widgets/config/index.tsx +0 -440
  901. package/src/widgets/costs/index.tsx +0 -216
  902. package/src/widgets/explorer/index.tsx +0 -408
  903. package/src/widgets/explorer/tree-model.test.ts +0 -214
  904. package/src/widgets/explorer/tree.tsx +0 -156
  905. package/src/widgets/lib/files.test.ts +0 -103
  906. package/src/widgets/lib/git.test.ts +0 -151
  907. package/src/widgets/lib/pane-comms.test.ts +0 -178
  908. package/src/widgets/lib/pane-comms.ts +0 -207
  909. package/src/widgets/lib/theme.ts +0 -151
  910. package/src/widgets/lib/watcher.ts +0 -50
  911. package/src/widgets/mission-control/activity-feed.tsx +0 -59
  912. package/src/widgets/mission-control/agent-panel.tsx +0 -132
  913. package/src/widgets/mission-control/command-bar.tsx +0 -63
  914. package/src/widgets/mission-control/index.tsx +0 -751
  915. package/src/widgets/mission-control/task-panel.tsx +0 -238
  916. package/src/widgets/preview/index.tsx +0 -415
  917. package/src/widgets/resolve.ts +0 -40
  918. package/src/widgets/setup/config-tree.tsx +0 -238
  919. package/src/widgets/setup/index.tsx +0 -340
  920. package/src/widgets/setup/setup-model.test.ts +0 -303
  921. package/src/widgets/tasks/index.tsx +0 -129
  922. package/src/widgets/tasks/task-detail.tsx +0 -309
  923. package/src/widgets/tasks/task-form.tsx +0 -193
  924. package/src/widgets/tasks/task-list.tsx +0 -205
  925. package/src/widgets/tasks/task-model.test.ts +0 -473
  926. package/src/widgets/tasks/task-model.ts +0 -157
  927. /package/{src/lib/auth/types.ts → packages/contracts/src/lib-internal/auth.ts} +0 -0
  928. /package/{src → packages/daemon/src}/command-center/index.ts +0 -0
  929. /package/{src → packages/daemon/src}/detect.ts +0 -0
  930. /package/{src → packages/daemon/src}/js-yaml.d.ts +0 -0
  931. /package/{src → packages/daemon/src}/lib/auth/auth-service.ts +0 -0
  932. /package/{src → packages/daemon/src}/lib/auth/middleware.ts +0 -0
  933. /package/{src → packages/daemon/src}/lib/authorship.ts +0 -0
  934. /package/{src → packages/daemon/src}/lib/dot-path.ts +0 -0
  935. /package/{src → packages/daemon/src}/lib/launch-plan.ts +0 -0
  936. /package/{src → packages/daemon/src}/lib/session-options.ts +0 -0
  937. /package/{src → packages/daemon/src}/lib/shell.ts +0 -0
  938. /package/{src → packages/daemon/src}/lib/sizes.ts +0 -0
  939. /package/{src → packages/daemon/src}/lib/slugify.ts +0 -0
  940. /package/{src → packages/daemon/src}/lib/yaml-io.ts +0 -0
  941. /package/{src → packages/daemon/src}/ls.ts +0 -0
  942. /package/{src → packages/daemon/src}/ui/index.ts +0 -0
  943. /package/{src → packages/daemon/src}/ui/terminal/index.ts +0 -0
  944. /package/{src → packages/daemon/src}/ui/types.ts +0 -0
  945. /package/{src → packages/daemon/src}/ui/web/base.css +0 -0
  946. /package/{src → packages/daemon/src}/ui/web/components/Box.tsx +0 -0
  947. /package/{src → packages/daemon/src}/ui/web/components/Input.tsx +0 -0
  948. /package/{src → packages/daemon/src}/ui/web/components/ScrollBox.tsx +0 -0
  949. /package/{src → packages/daemon/src}/ui/web/components/Text.tsx +0 -0
  950. /package/{src → packages/daemon/src}/ui/web/hooks.ts +0 -0
  951. /package/{src → packages/daemon/src}/ui/web/index.ts +0 -0
  952. /package/{src → packages/daemon/src}/ui/web/render.ts +0 -0
  953. /package/{src → packages/daemon/src}/ui/web/utils/color.ts +0 -0
  954. /package/{src → packages/daemon/src}/validate.ts +0 -0
  955. /package/{src → packages/daemon/src}/widgets/explorer/breadcrumbs.tsx +0 -0
  956. /package/{src → packages/daemon/src}/widgets/explorer/footer.tsx +0 -0
  957. /package/{src → packages/daemon/src}/widgets/explorer/header.tsx +0 -0
  958. /package/{src → packages/daemon/src}/widgets/explorer/tree-model.ts +0 -0
  959. /package/{src → packages/daemon/src}/widgets/lib/config-model.ts +0 -0
  960. /package/{src → packages/daemon/src}/widgets/lib/files.ts +0 -0
  961. /package/{src → packages/daemon/src}/widgets/lib/git.ts +0 -0
  962. /package/{src → packages/daemon/src}/widgets/setup/agent-naming.tsx +0 -0
  963. /package/{src → packages/daemon/src}/widgets/setup/detect-panel.tsx +0 -0
  964. /package/{src → packages/daemon/src}/widgets/setup/field-editor.tsx +0 -0
  965. /package/{src → packages/daemon/src}/widgets/setup/footer.tsx +0 -0
  966. /package/{src → packages/daemon/src}/widgets/setup/layout-picker.tsx +0 -0
  967. /package/{src → packages/daemon/src}/widgets/setup/orchestrator-panel.tsx +0 -0
  968. /package/{src → packages/daemon/src}/widgets/setup/review-panel.tsx +0 -0
  969. /package/{src → packages/daemon/src}/widgets/setup/setup-model.ts +0 -0
@@ -0,0 +1,1103 @@
1
+ import { execFile } from "node:child_process";
2
+ import { promisify } from "node:util";
3
+ import { existsSync, readFileSync, readdirSync } from "node:fs";
4
+ import { join, dirname, basename } from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ import { Hono } from "hono";
7
+ import { streamSSE } from "hono/streaming";
8
+ import { cors } from "hono/cors";
9
+ import { discoverSessions, buildOverviews, buildProjectDetail, } from "./discovery.js";
10
+ import { listSessionPanes, sendCommand, sendEnterToPane, sendLiteralToPane, sendText, getPaneBusyStatus, } from "../widgets/lib/pane-comms.js";
11
+ import { resolvePane } from "../send.js";
12
+ import { getSessionState, killSession, stopSessionMonitor } from "@tmux-ide/tmux-bridge";
13
+ import { readConfig, writeConfig } from "../lib/yaml-io.js";
14
+ import { IdeConfigSchema } from "../schemas/ide-config.js";
15
+ import { getLogBuffer, subscribeLogs } from "../lib/log.js";
16
+ import { zValidator } from "@hono/zod-validator";
17
+ import { getDefaultWorkspaceRegistry, WorkspaceAlreadyExistsError, WorkspaceNotFoundError, } from "../lib/workspace-registry.js";
18
+ import { AddWorkspaceRequestSchemaZ } from "@tmux-ide/contracts";
19
+ import { sendCommandSchema } from "./schemas.js";
20
+ import { createScriptTerminalId, terminalCreateRequestSchema, terminalRenameRequestSchema, } from "@tmux-ide/contracts";
21
+ import { deleteTerminal as deleteTerminalRecord, loadTerminals, renameTerminal as renameTerminalRecord, upsertTerminal as upsertTerminalRecord, } from "../lib/terminals-store.js";
22
+ import { defaultPtyBridgeRegistry } from "../server/ws-route.js";
23
+ import { broadcastTerminalsChanged } from "./ws-events.js";
24
+ import { AuthService } from "../lib/auth/auth-service.js";
25
+ import { authMiddleware } from "../lib/auth/middleware.js";
26
+ import { handleWsEventsConnection, broadcastInitOutput, broadcastInitError } from "./ws-events.js";
27
+ import { createActionDispatcher } from "./actions/dispatcher.js";
28
+ import { listProjects, getProject, registerProject, unregisterProject, refreshProject, ProjectAlreadyRegisteredError, ProjectDirNotFoundError, ProjectNotFoundError, } from "../lib/project-registry.js";
29
+ import { runInit, ProjectInitFailedError, ProjectInitTimeoutError, } from "../lib/project-init-runner.js";
30
+ import { RegisterProjectRequestSchemaZ, InitProjectRequestSchemaZ, } from "../schemas/registry.js";
31
+ import { OnboardProjectRequestSchemaZ } from "../schemas/inspect.js";
32
+ import { SandboxViolationError, assertInsideSandbox } from "../lib/filesystem-browser.js";
33
+ import { inspectProject, InspectDirNotFoundError } from "../lib/project-inspect.js";
34
+ import { composeIdeYmlConfig, assertNoExistingIdeYml, OnboardConflictError, OnboardInvalidInputError, } from "../lib/project-onboard.js";
35
+ import { realpathSync } from "node:fs";
36
+ import { homedir } from "node:os";
37
+ import { isAbsolute, resolve as pathResolve } from "node:path";
38
+ import { randomUUID } from "node:crypto";
39
+ import { WebSocketServer } from "ws";
40
+ const __dirname = dirname(fileURLToPath(import.meta.url));
41
+ // Resolve our package.json's version. The lookup needs to handle BOTH
42
+ // dev (this file lives at src/command-center/, so the workspace root
43
+ // is two levels up) AND the packaged Electron bundle (this file is
44
+ // flattened into app.asar/dist-electron/, so the bundled package.json
45
+ // is ONE level up; two levels up escapes the asar). Try the candidates
46
+ // in order; fall back to a sentinel if neither is readable.
47
+ function resolvePackageVersion() {
48
+ const candidates = [join(__dirname, "../../package.json"), join(__dirname, "../package.json")];
49
+ for (const candidate of candidates) {
50
+ try {
51
+ const parsed = JSON.parse(readFileSync(candidate, "utf-8"));
52
+ if (typeof parsed.version === "string")
53
+ return parsed.version;
54
+ }
55
+ catch {
56
+ /* try the next candidate */
57
+ }
58
+ }
59
+ return "0.0.0";
60
+ }
61
+ const pkgVersion = resolvePackageVersion();
62
+ let projectStreamConnections = 0;
63
+ function bearerToken(authHeader) {
64
+ if (!authHeader?.startsWith("Bearer "))
65
+ return null;
66
+ return authHeader.slice("Bearer ".length);
67
+ }
68
+ function requireAuth(token, localBypassToken) {
69
+ return async (c, next) => {
70
+ if (!token)
71
+ return next();
72
+ const url = new URL(c.req.url);
73
+ const suppliedToken = bearerToken(c.req.header("Authorization")) ?? url.searchParams.get("token");
74
+ if (suppliedToken === token || (localBypassToken && suppliedToken === localBypassToken)) {
75
+ return next();
76
+ }
77
+ return c.json({ error: "Remote access token required" }, 401);
78
+ };
79
+ }
80
+ function remoteAccessAuth(options) {
81
+ const bindHostname = options.remoteAccess?.bindHostname ?? "127.0.0.1";
82
+ return {
83
+ token: bindHostname === "127.0.0.1" ? null : (options.remoteAccess?.token ?? null),
84
+ localBypassToken: options.remoteAccess?.localBypassToken ?? null,
85
+ };
86
+ }
87
+ const sseMetrics = {
88
+ connections: 0,
89
+ messagesSent: 0,
90
+ };
91
+ export function getSseMetrics() {
92
+ return { ...sseMetrics };
93
+ }
94
+ /**
95
+ * Resolve a BottomPanel Output-tab channel id to a `LogEntry` predicate.
96
+ * Channels are simple component-prefix filters over the single in-process
97
+ * structured logger. Returns `null` for unknown channels (handler emits
98
+ * 404). Add new channels here when adding new log components.
99
+ */
100
+ function matchLogChannel(channel) {
101
+ switch (channel) {
102
+ case "daemon":
103
+ return () => true;
104
+ case "hq":
105
+ return (entry) => entry.component.startsWith("hq") || entry.component.startsWith("remote");
106
+ case "watchdog":
107
+ return (entry) => entry.component.startsWith("watchdog");
108
+ default:
109
+ return null;
110
+ }
111
+ }
112
+ function freezePayload(payload) {
113
+ if (payload && typeof payload === "object") {
114
+ for (const value of Object.values(payload)) {
115
+ freezePayload(value);
116
+ }
117
+ Object.freeze(payload);
118
+ }
119
+ return payload;
120
+ }
121
+ function buildProjectStreamSnapshot(session) {
122
+ return {
123
+ project: buildProjectDetail(session),
124
+ };
125
+ }
126
+ function sandboxResolveDir(rawDir) {
127
+ const trimmed = rawDir.trim();
128
+ if (!trimmed)
129
+ return { error: "invalid-path", message: "Path must not be empty", status: 400 };
130
+ if (trimmed.includes("\0")) {
131
+ return { error: "invalid-path", message: "Path contains a null byte", status: 400 };
132
+ }
133
+ const home = process.env.TMUX_IDE_HOME_OVERRIDE && process.env.TMUX_IDE_HOME_OVERRIDE.trim().length > 0
134
+ ? process.env.TMUX_IDE_HOME_OVERRIDE
135
+ : homedir();
136
+ let candidate = trimmed;
137
+ if (candidate === "~") {
138
+ candidate = home;
139
+ }
140
+ else if (candidate.startsWith("~/")) {
141
+ candidate = `${home.replace(/\/+$/, "")}/${candidate.slice(2)}`;
142
+ }
143
+ if (!isAbsolute(candidate)) {
144
+ return { error: "invalid-path", message: "Path must be absolute", status: 400 };
145
+ }
146
+ const resolved = pathResolve(candidate);
147
+ let canonical;
148
+ try {
149
+ canonical = realpathSync(resolved);
150
+ }
151
+ catch (err) {
152
+ const code = err.code;
153
+ if (code === "ENOENT" || code === "ENOTDIR") {
154
+ return {
155
+ error: "not-found",
156
+ message: `Path "${resolved}" does not exist`,
157
+ status: 404,
158
+ };
159
+ }
160
+ throw err;
161
+ }
162
+ try {
163
+ assertInsideSandbox(canonical, home);
164
+ }
165
+ catch (err) {
166
+ if (err instanceof SandboxViolationError) {
167
+ return { error: "outside-sandbox", message: err.message, status: 403 };
168
+ }
169
+ throw err;
170
+ }
171
+ return { canonical };
172
+ }
173
+ export function createApp(options = {}) {
174
+ const authConfig = options.authConfig ?? { method: "none", token_expiry: 86400 };
175
+ const authService = options.authService ?? new AuthService();
176
+ const app = new Hono();
177
+ // Allow cross-origin (Next.js dashboard, Tailscale, etc.)
178
+ app.use("/*", cors());
179
+ // Remote access bearer gate. Local Electron access uses a per-daemon
180
+ // bypass token from preload; loopback IPs are not implicitly trusted.
181
+ const remoteAuth = remoteAccessAuth(options);
182
+ app.use("/api/*", requireAuth(remoteAuth.token, remoteAuth.localBypassToken));
183
+ // Auth middleware — passes through when method is "none"
184
+ app.use("/*", authMiddleware(authService, authConfig));
185
+ // Global error handler
186
+ app.onError((err, c) => {
187
+ console.error("[command-center]", err.message);
188
+ return c.json({ error: err.message }, 500);
189
+ });
190
+ // --- Auth routes (always available, bypassed by middleware) ---
191
+ app.post("/api/auth/challenge", async (c) => {
192
+ const body = await c.req.json();
193
+ const userId = body.userId ?? authService.getCurrentUser();
194
+ const challenge = authService.createChallenge(userId);
195
+ return c.json(challenge);
196
+ });
197
+ app.post("/api/auth/verify", async (c) => {
198
+ const body = await c.req.json();
199
+ const result = await authService.authenticateWithSSHKey({
200
+ publicKey: body.publicKey,
201
+ signature: body.signature,
202
+ challengeId: body.challengeId,
203
+ });
204
+ if (!result.success) {
205
+ return c.json({ error: result.error }, 401);
206
+ }
207
+ return c.json({ token: result.token, userId: result.userId });
208
+ });
209
+ app.post("/api/auth/token", async (c) => {
210
+ if (authConfig.method !== "none") {
211
+ return c.json({ error: "Direct token generation requires auth method 'none'" }, 403);
212
+ }
213
+ const body = await c.req.json();
214
+ const userId = body.userId ?? authService.getCurrentUser();
215
+ const token = authService.generateToken(userId);
216
+ return c.json({ token, userId });
217
+ });
218
+ // --- v2 action dispatcher (single typed entry-point for state-changing
219
+ // project / terminal operations — see src/command-center/actions/) ---
220
+ app.post("/api/v2/action/:name", createActionDispatcher());
221
+ app.get("/api/widget/:name/spawn", async (c) => {
222
+ const { resolveWidgetSpawn, WIDGET_TYPES } = await import("../widgets/resolve.js");
223
+ const name = c.req.param("name");
224
+ if (!WIDGET_TYPES.includes(name)) {
225
+ return c.json({ error: `unknown widget: ${name}`, available: WIDGET_TYPES }, 404);
226
+ }
227
+ const session = c.req.query("session");
228
+ const dir = c.req.query("dir");
229
+ if (!session || !dir) {
230
+ return c.json({ error: "session and dir query params are required" }, 400);
231
+ }
232
+ const target = c.req.query("target") ?? null;
233
+ const themeRaw = c.req.query("theme");
234
+ let theme = null;
235
+ if (themeRaw) {
236
+ try {
237
+ theme = JSON.parse(themeRaw);
238
+ }
239
+ catch {
240
+ return c.json({ error: "theme must be valid JSON" }, 400);
241
+ }
242
+ }
243
+ try {
244
+ const spec = resolveWidgetSpawn(name, {
245
+ session,
246
+ dir,
247
+ target,
248
+ theme: theme,
249
+ });
250
+ return c.json(spec);
251
+ }
252
+ catch (err) {
253
+ return c.json({ error: err instanceof Error ? err.message : String(err) }, 500);
254
+ }
255
+ });
256
+ // T067: /healthz — minimal liveness probe used by daemon-client.
257
+ // Intentionally NOT under /api so it bypasses the auth middleware on
258
+ // every consumer. Returns ok + version + uptime (ms since boot).
259
+ const HEALTHZ_BOOTED_AT = Date.now();
260
+ app.get("/healthz", (c) => {
261
+ return c.json({
262
+ ok: true,
263
+ version: process.env.npm_package_version ?? "dev",
264
+ uptimeMs: Date.now() - HEALTHZ_BOOTED_AT,
265
+ });
266
+ });
267
+ app.get("/api/sessions", (c) => {
268
+ const sessions = discoverSessions();
269
+ const overviews = buildOverviews(sessions);
270
+ return c.json({ sessions: overviews });
271
+ });
272
+ // ---------------------------------------------------------------------
273
+ // /api/workspaces — registry-backed CRUD. The registry is the source of
274
+ // truth for which projects the daemon serves. WS frames `workspace.added`
275
+ // and `workspace.removed` are emitted by the registry's emitter, picked
276
+ // up by ws-events' ensureWorkspaceRegistryListener and fanned to clients.
277
+ // ---------------------------------------------------------------------
278
+ app.get("/api/workspaces", (c) => {
279
+ const registry = getDefaultWorkspaceRegistry();
280
+ return c.json({ workspaces: registry.list() });
281
+ });
282
+ app.get("/api/workspaces/:name", (c) => {
283
+ const name = c.req.param("name");
284
+ const registry = getDefaultWorkspaceRegistry();
285
+ const workspace = registry.get(name);
286
+ if (!workspace)
287
+ return c.json({ error: "Workspace not found" }, 404);
288
+ return c.json({ workspace });
289
+ });
290
+ app.post("/api/workspaces", zValidator("json", AddWorkspaceRequestSchemaZ), (c) => {
291
+ const body = c.req.valid("json");
292
+ const registry = getDefaultWorkspaceRegistry();
293
+ const name = body.name ?? basename(body.projectDir);
294
+ if (!name || name.length === 0) {
295
+ return c.json({ error: "Cannot derive workspace name from projectDir" }, 400);
296
+ }
297
+ try {
298
+ const workspace = registry.add({
299
+ name,
300
+ sessionName: body.sessionName,
301
+ projectDir: body.projectDir,
302
+ ideConfigPath: body.ideConfigPath ?? null,
303
+ });
304
+ return c.json({ workspace }, 201);
305
+ }
306
+ catch (err) {
307
+ if (err instanceof WorkspaceAlreadyExistsError) {
308
+ return c.json({ error: err.message, code: err.code }, 409);
309
+ }
310
+ throw err;
311
+ }
312
+ });
313
+ // GET /api/chat/providers — discovery (claude-code / codex binaries on
314
+ // PATH). Distinct from `/api/providers`, which serves the redacted
315
+ // user-configured `ProviderInstanceSummary` set (T079).
316
+ app.delete("/api/workspaces/:name", (c) => {
317
+ const name = c.req.param("name");
318
+ const registry = getDefaultWorkspaceRegistry();
319
+ try {
320
+ registry.remove(name);
321
+ return c.body(null, 204);
322
+ }
323
+ catch (err) {
324
+ if (err instanceof WorkspaceNotFoundError) {
325
+ return c.json({ error: err.message, code: err.code }, 404);
326
+ }
327
+ throw err;
328
+ }
329
+ });
330
+ app.get("/api/project/:name", (c) => {
331
+ const name = c.req.param("name");
332
+ const sessions = discoverSessions();
333
+ const session = sessions.find((s) => s.name === name);
334
+ if (!session) {
335
+ return c.json({ error: "Session not found" }, 404);
336
+ }
337
+ const detail = buildProjectDetail(session);
338
+ return c.json({ ...detail });
339
+ });
340
+ app.get("/api/project/:name/panes", (c) => {
341
+ const name = c.req.param("name");
342
+ let panes;
343
+ try {
344
+ panes = listSessionPanes(name);
345
+ }
346
+ catch {
347
+ return c.json({ error: "Session not found" }, 404);
348
+ }
349
+ if (panes.length === 0) {
350
+ // Verify the session actually exists before returning empty
351
+ const sessions = discoverSessions();
352
+ if (!sessions.find((s) => s.name === name)) {
353
+ return c.json({ error: "Session not found" }, 404);
354
+ }
355
+ }
356
+ return c.json({
357
+ panes: panes.map((p) => ({
358
+ id: p.id,
359
+ index: p.index,
360
+ title: p.title,
361
+ currentCommand: p.currentCommand,
362
+ width: p.width,
363
+ height: p.height,
364
+ active: p.active,
365
+ role: p.role,
366
+ name: p.name,
367
+ type: p.type,
368
+ })),
369
+ });
370
+ });
371
+ app.get("/api/project/:name/terminals", async (c) => {
372
+ const name = c.req.param("name");
373
+ const sessions = discoverSessions();
374
+ const session = sessions.find((s) => s.name === name);
375
+ if (!session)
376
+ return c.json({ error: "Session not found" }, 404);
377
+ const records = loadTerminals(session.dir);
378
+ const terminals = records.map((t) => {
379
+ const bridge = defaultPtyBridgeRegistry.peek(t.id);
380
+ let runtime = { running: false };
381
+ if (bridge) {
382
+ const cols = typeof bridge.cols === "number" ? bridge.cols : undefined;
383
+ const rows = typeof bridge.rows === "number" ? bridge.rows : undefined;
384
+ const replay = typeof bridge.getReplayBuffer === "function"
385
+ ? bridge.getReplayBuffer().byteLength
386
+ : undefined;
387
+ runtime = {
388
+ running: bridge.running !== false,
389
+ ...(cols !== undefined ? { cols } : {}),
390
+ ...(rows !== undefined ? { rows } : {}),
391
+ ...(replay !== undefined ? { replayBytes: replay } : {}),
392
+ };
393
+ }
394
+ return { ...t, runtime };
395
+ });
396
+ return c.json({ terminals });
397
+ });
398
+ app.post("/api/project/:name/terminals", zValidator("json", terminalCreateRequestSchema), async (c) => {
399
+ const name = c.req.param("name");
400
+ const sessions = discoverSessions();
401
+ const session = sessions.find((s) => s.name === name);
402
+ if (!session)
403
+ return c.json({ error: "Session not found" }, 404);
404
+ const body = c.req.valid("json");
405
+ // Pick the id: explicit > deterministic (when script provided) >
406
+ // UUID. The script-derived id collapse is the load-bearing bit
407
+ // for "two callers asking for the same run-script tab share a
408
+ // bridge + scrollback".
409
+ let id = body.id;
410
+ let scripted = false;
411
+ const kind = body.kind ?? "shell";
412
+ if (!id && body.script) {
413
+ id = await createScriptTerminalId({
414
+ projectId: name,
415
+ scopeId: body.scopeId,
416
+ kind,
417
+ script: body.script,
418
+ });
419
+ scripted = true;
420
+ }
421
+ if (!id)
422
+ id = randomUUID();
423
+ try {
424
+ const upsertInput = {
425
+ id,
426
+ projectId: name,
427
+ scopeId: body.scopeId,
428
+ name: body.name,
429
+ kind,
430
+ };
431
+ if (scripted)
432
+ upsertInput.scripted = true;
433
+ const record = upsertTerminalRecord(session.dir, upsertInput);
434
+ broadcastTerminalsChanged(name);
435
+ return c.json({ ok: true, terminal: record });
436
+ }
437
+ catch (err) {
438
+ return c.json({ error: err.message }, 400);
439
+ }
440
+ });
441
+ app.post("/api/project/:name/terminals/:id/rename", zValidator("json", terminalRenameRequestSchema), async (c) => {
442
+ const name = c.req.param("name");
443
+ const id = c.req.param("id");
444
+ const sessions = discoverSessions();
445
+ const session = sessions.find((s) => s.name === name);
446
+ if (!session)
447
+ return c.json({ error: "Session not found" }, 404);
448
+ try {
449
+ const record = renameTerminalRecord(session.dir, id, c.req.valid("json").name);
450
+ if (!record)
451
+ return c.json({ error: "Terminal not found" }, 404);
452
+ broadcastTerminalsChanged(name);
453
+ return c.json({ ok: true, terminal: record });
454
+ }
455
+ catch (err) {
456
+ return c.json({ error: err.message }, 400);
457
+ }
458
+ });
459
+ app.delete("/api/project/:name/terminals/:id", async (c) => {
460
+ const name = c.req.param("name");
461
+ const id = c.req.param("id");
462
+ const sessions = discoverSessions();
463
+ const session = sessions.find((s) => s.name === name);
464
+ if (!session)
465
+ return c.json({ error: "Session not found" }, 404);
466
+ const removedRecord = deleteTerminalRecord(session.dir, id);
467
+ // Kill the live bridge too — keep store + registry consistent.
468
+ const killed = defaultPtyBridgeRegistry.delete(id);
469
+ if (!removedRecord && !killed) {
470
+ return c.json({ error: "Terminal not found" }, 404);
471
+ }
472
+ broadcastTerminalsChanged(name);
473
+ return c.json({ ok: true });
474
+ });
475
+ // --- Project event/stream endpoints ---
476
+ // The orchestrator/task event feed moved out of tmux-ide (now in sfora.ai),
477
+ // so these surfaces only carry the live pane/project snapshot.
478
+ app.get("/api/project/:name/events", (c) => {
479
+ const name = c.req.param("name");
480
+ const session = discoverSessions().find((s) => s.name === name);
481
+ if (!session) {
482
+ return c.json({ error: "Session not found" }, 404);
483
+ }
484
+ return c.json({ events: [] });
485
+ });
486
+ app.get("/api/project/:name/stream", (c) => {
487
+ const name = c.req.param("name");
488
+ const session = discoverSessions().find((s) => s.name === name);
489
+ if (!session) {
490
+ return c.json({ error: "Session not found" }, 404);
491
+ }
492
+ return streamSSE(c, async (stream) => {
493
+ projectStreamConnections += 1;
494
+ sseMetrics.connections = projectStreamConnections;
495
+ let closed = false;
496
+ let previousSnapshotHash = "";
497
+ let lastPing = Date.now();
498
+ function writeSse(event, payload) {
499
+ sseMetrics.messagesSent += 1;
500
+ void stream.writeSSE({ event, data: JSON.stringify(freezePayload(payload)) });
501
+ }
502
+ function writeChanges(currentSession) {
503
+ const snapshot = buildProjectStreamSnapshot(currentSession);
504
+ const snapshotHash = JSON.stringify(snapshot);
505
+ if (snapshotHash !== previousSnapshotHash) {
506
+ writeSse("snapshot", snapshot);
507
+ previousSnapshotHash = snapshotHash;
508
+ }
509
+ }
510
+ try {
511
+ stream.onAbort(() => {
512
+ closed = true;
513
+ });
514
+ writeChanges(session);
515
+ while (!closed) {
516
+ await stream.sleep(250);
517
+ const current = discoverSessions().find((candidate) => candidate.name === name);
518
+ if (!current)
519
+ break;
520
+ writeChanges(current);
521
+ const now = Date.now();
522
+ if (now - lastPing >= 25_000) {
523
+ writeSse("ping", { at: new Date().toISOString() });
524
+ lastPing = now;
525
+ }
526
+ }
527
+ }
528
+ finally {
529
+ projectStreamConnections = Math.max(0, projectStreamConnections - 1);
530
+ sseMetrics.connections = projectStreamConnections;
531
+ }
532
+ });
533
+ });
534
+ app.post("/api/project/:name/inject", async (c) => {
535
+ const name = c.req.param("name");
536
+ const sessions = discoverSessions();
537
+ const session = sessions.find((s) => s.name === name);
538
+ if (!session) {
539
+ return c.json({ error: "Session not found" }, 404);
540
+ }
541
+ let body;
542
+ try {
543
+ body = await c.req.json();
544
+ }
545
+ catch {
546
+ return c.json({ error: "Invalid JSON body" }, 400);
547
+ }
548
+ if (!body || typeof body !== "object" || Array.isArray(body)) {
549
+ return c.json({ error: "Invalid request body" }, 400);
550
+ }
551
+ const text = body.text;
552
+ const paneId = body.paneId;
553
+ const sendEnter = body.sendEnter;
554
+ if (typeof text !== "string" || text.trim().length === 0) {
555
+ return c.json({ error: "text must be a non-empty string" }, 400);
556
+ }
557
+ if (paneId !== undefined && (typeof paneId !== "string" || !/^%\d+$/.test(paneId))) {
558
+ return c.json({ error: "paneId must match /^%\\d+$/" }, 400);
559
+ }
560
+ if (sendEnter !== undefined && typeof sendEnter !== "boolean") {
561
+ return c.json({ error: "sendEnter must be a boolean" }, 400);
562
+ }
563
+ const panes = listSessionPanes(name);
564
+ const pane = paneId
565
+ ? panes.find((candidate) => candidate.id === paneId)
566
+ : panes.find((p) => p.active);
567
+ if (!pane) {
568
+ return c.json({ error: "Pane not found" }, 404);
569
+ }
570
+ sendLiteralToPane(name, pane.id, text);
571
+ if (sendEnter)
572
+ sendEnterToPane(name, pane.id);
573
+ return c.json({ ok: true });
574
+ });
575
+ // Send message to a pane by name/title/role/ID
576
+ app.post("/api/project/:name/send", zValidator("json", sendCommandSchema), async (c) => {
577
+ const name = c.req.param("name");
578
+ const sessions = discoverSessions();
579
+ const session = sessions.find((s) => s.name === name);
580
+ if (!session) {
581
+ return c.json({ error: "Session not found" }, 404);
582
+ }
583
+ const { target, message, noEnter } = c.req.valid("json");
584
+ const panes = listSessionPanes(name);
585
+ const pane = resolvePane(panes, target);
586
+ if (!pane) {
587
+ const available = panes.map((p) => ({
588
+ id: p.id,
589
+ title: p.title,
590
+ name: p.name,
591
+ role: p.role,
592
+ }));
593
+ return c.json({ error: "Pane not found", target, available }, 404);
594
+ }
595
+ const busyStatus = getPaneBusyStatus(name, pane.id);
596
+ // Collapse multiline for agent panes
597
+ const prepared = busyStatus === "agent" ? message.replace(/\n+/g, " ").trim() : message;
598
+ if (noEnter) {
599
+ sendText(name, pane.id, prepared);
600
+ }
601
+ else {
602
+ sendCommand(name, pane.id, prepared);
603
+ }
604
+ return c.json({
605
+ ok: true,
606
+ session: name,
607
+ target: {
608
+ paneId: pane.id,
609
+ name: pane.name,
610
+ title: pane.title,
611
+ role: pane.role,
612
+ },
613
+ busyStatus,
614
+ });
615
+ });
616
+ // GET /api/project/:name/config — read parsed ide.yml + raw text. Used by
617
+ // the v2 Config editor to hydrate the form.
618
+ app.get("/api/project/:name/config", (c) => {
619
+ const name = c.req.param("name");
620
+ const sessions = discoverSessions();
621
+ const session = sessions.find((s) => s.name === name);
622
+ if (!session)
623
+ return c.json({ error: "Session not found" }, 404);
624
+ try {
625
+ const { config, configPath } = readConfig(session.dir);
626
+ return c.json({ ok: true, config, configPath });
627
+ }
628
+ catch (err) {
629
+ const message = err instanceof Error ? err.message : String(err);
630
+ return c.json({ error: "Failed to read ide.yml", detail: message }, 500);
631
+ }
632
+ });
633
+ // POST /api/project/:name/config — accept a full IdeConfig payload, validate
634
+ // against IdeConfigSchema, and write to ide.yml. Returns the persisted
635
+ // config so the client can re-hydrate without a follow-up GET.
636
+ app.post("/api/project/:name/config", async (c) => {
637
+ const name = c.req.param("name");
638
+ const sessions = discoverSessions();
639
+ const session = sessions.find((s) => s.name === name);
640
+ if (!session)
641
+ return c.json({ error: "Session not found" }, 404);
642
+ let body;
643
+ try {
644
+ body = await c.req.json();
645
+ }
646
+ catch {
647
+ return c.json({ error: "Invalid JSON body" }, 400);
648
+ }
649
+ const parsed = IdeConfigSchema.safeParse(body);
650
+ if (!parsed.success) {
651
+ return c.json({ error: "Invalid config", details: parsed.error.issues }, 400);
652
+ }
653
+ try {
654
+ const configPath = writeConfig(session.dir, parsed.data);
655
+ return c.json({ ok: true, config: parsed.data, configPath });
656
+ }
657
+ catch (err) {
658
+ const message = err instanceof Error ? err.message : String(err);
659
+ return c.json({ error: "Failed to write ide.yml", detail: message }, 500);
660
+ }
661
+ });
662
+ // Launch a tmux-ide session (shells out to CLI since launch has complex side effects)
663
+ const execFileAsync = promisify(execFile);
664
+ // POST /api/project/:name/restart — fire `tmux-ide restart` async. The CLI
665
+ // handles stop+launch; this endpoint is fire-and-forget aside from a short
666
+ // 30s timeout so the client can retry on its own.
667
+ app.post("/api/project/:name/restart", async (c) => {
668
+ const name = c.req.param("name");
669
+ const sessions = discoverSessions();
670
+ const session = sessions.find((s) => s.name === name);
671
+ if (!session)
672
+ return c.json({ error: "Session not found" }, 404);
673
+ try {
674
+ await execFileAsync("tmux-ide", ["restart", "--json"], {
675
+ cwd: session.dir,
676
+ timeout: 30000,
677
+ env: { ...process.env, TMUX: "" },
678
+ });
679
+ return c.json({ ok: true, session: name, status: "restarted" });
680
+ }
681
+ catch (err) {
682
+ const message = err instanceof Error ? err.message : String(err);
683
+ return c.json({ error: "Restart failed", detail: message }, 500);
684
+ }
685
+ });
686
+ app.post("/api/project/:name/launch", async (c) => {
687
+ const name = c.req.param("name");
688
+ const sessions = discoverSessions();
689
+ const session = sessions.find((s) => s.name === name);
690
+ if (!session) {
691
+ return c.json({ error: "Session not found" }, 404);
692
+ }
693
+ // Check if already running
694
+ const state = getSessionState(name);
695
+ if (state.running) {
696
+ return c.json({ ok: true, session: name, status: "already_running" });
697
+ }
698
+ try {
699
+ await execFileAsync("tmux-ide", ["--json"], {
700
+ cwd: session.dir,
701
+ timeout: 30000,
702
+ env: { ...process.env, TMUX: "" }, // Clear TMUX to avoid nesting
703
+ });
704
+ return c.json({ ok: true, session: name, status: "launched" });
705
+ }
706
+ catch (err) {
707
+ const message = err instanceof Error ? err.message : String(err);
708
+ return c.json({ error: "Launch failed", detail: message }, 500);
709
+ }
710
+ });
711
+ // Stop a tmux-ide session
712
+ app.post("/api/project/:name/stop", async (c) => {
713
+ const name = c.req.param("name");
714
+ const sessions = discoverSessions();
715
+ const session = sessions.find((s) => s.name === name);
716
+ if (!session) {
717
+ return c.json({ error: "Session not found" }, 404);
718
+ }
719
+ const state = getSessionState(name);
720
+ if (!state.running) {
721
+ return c.json({ ok: true, session: name, status: "not_running" });
722
+ }
723
+ stopSessionMonitor(name);
724
+ const result = killSession(name);
725
+ if (result.stopped) {
726
+ return c.json({ ok: true, session: name, status: "stopped" });
727
+ }
728
+ return c.json({ error: "Stop failed", reason: result.reason }, 500);
729
+ });
730
+ // SSE endpoint — cursor-based event streaming with orchestrator state
731
+ app.get("/api/events", (c) => {
732
+ return streamSSE(c, async (stream) => {
733
+ let prevOverviews = [];
734
+ const poll = () => {
735
+ const sessions = discoverSessions();
736
+ const overviews = buildOverviews(sessions);
737
+ const prevNames = new Set(prevOverviews.map((s) => s.name));
738
+ const currNames = new Set(overviews.map((s) => s.name));
739
+ for (const overview of overviews) {
740
+ if (!prevNames.has(overview.name)) {
741
+ stream.writeSSE({ event: "session_added", data: JSON.stringify(overview) });
742
+ }
743
+ }
744
+ for (const prev of prevOverviews) {
745
+ if (!currNames.has(prev.name)) {
746
+ stream.writeSSE({
747
+ event: "session_removed",
748
+ data: JSON.stringify({ name: prev.name }),
749
+ });
750
+ }
751
+ }
752
+ prevOverviews = overviews;
753
+ };
754
+ poll();
755
+ while (true) {
756
+ await stream.sleep(2000);
757
+ poll();
758
+ }
759
+ });
760
+ });
761
+ // ---------------------------------------------------------------------
762
+ // GET /api/logs/:channel — SSE stream of structured logger entries.
763
+ //
764
+ // Channels are filtered views over the single in-process logger:
765
+ // - "daemon" → no component filter (all entries)
766
+ // - "hq" → component starts with "hq" or "remote"
767
+ // - "watchdog" → component starts with "watchdog"
768
+ // The dashboard BottomPanel Output tab opens one EventSource per
769
+ // selected channel. Backfill from the in-memory ring buffer is sent
770
+ // first as `event: "backfill"` followed by a `bookmark` event so the
771
+ // client can render history immediately; new entries arrive as
772
+ // `event: "entry"` data.
773
+ // ---------------------------------------------------------------------
774
+ app.get("/api/logs/:channel", (c) => {
775
+ const channel = c.req.param("channel");
776
+ const match = matchLogChannel(channel);
777
+ if (!match) {
778
+ return c.json({ error: `Unknown log channel: ${channel}` }, 404);
779
+ }
780
+ return streamSSE(c, async (stream) => {
781
+ // 1. Backfill from the ring buffer.
782
+ const backfill = getLogBuffer().filter(match);
783
+ for (const entry of backfill) {
784
+ await stream.writeSSE({ event: "entry", data: JSON.stringify(entry) });
785
+ }
786
+ await stream.writeSSE({ event: "bookmark", data: String(backfill.length) });
787
+ // 2. Subscribe to live entries.
788
+ const queue = [];
789
+ let cancelled = false;
790
+ const unsub = subscribeLogs((entry) => {
791
+ if (cancelled)
792
+ return;
793
+ if (match(entry))
794
+ queue.push(entry);
795
+ });
796
+ try {
797
+ while (!cancelled) {
798
+ if (queue.length === 0) {
799
+ await stream.sleep(500);
800
+ continue;
801
+ }
802
+ const drained = queue.splice(0, queue.length);
803
+ for (const entry of drained) {
804
+ await stream.writeSSE({ event: "entry", data: JSON.stringify(entry) });
805
+ }
806
+ }
807
+ }
808
+ finally {
809
+ cancelled = true;
810
+ unsub();
811
+ }
812
+ });
813
+ });
814
+ app.get("/health", (c) => {
815
+ return c.json({
816
+ ok: true,
817
+ uptime: Math.round(process.uptime()),
818
+ version: pkgVersion,
819
+ });
820
+ });
821
+ // --- Project registry ---
822
+ app.get("/api/projects", (c) => {
823
+ return c.json({ projects: listProjects() });
824
+ });
825
+ app.get("/api/projects/templates", (c) => {
826
+ return c.json({ templates: listAvailableTemplates() });
827
+ });
828
+ app.post("/api/projects", async (c) => {
829
+ let body;
830
+ try {
831
+ body = await c.req.json();
832
+ }
833
+ catch {
834
+ return c.json({ error: "Invalid JSON body" }, 400);
835
+ }
836
+ const parsed = RegisterProjectRequestSchemaZ.safeParse(body);
837
+ if (!parsed.success) {
838
+ return c.json({ error: "Invalid request", details: parsed.error.issues }, 400);
839
+ }
840
+ try {
841
+ const project = await registerProject({
842
+ dir: parsed.data.dir,
843
+ name: parsed.data.name,
844
+ });
845
+ return c.json({ project }, 201);
846
+ }
847
+ catch (err) {
848
+ if (err instanceof ProjectDirNotFoundError) {
849
+ return c.json({ error: err.message, code: err.code }, 400);
850
+ }
851
+ if (err instanceof ProjectAlreadyRegisteredError) {
852
+ return c.json({ error: err.message, code: err.code, suggestion: err.suggestion }, 409);
853
+ }
854
+ throw err;
855
+ }
856
+ });
857
+ app.delete("/api/projects/:name", (c) => {
858
+ const name = c.req.param("name");
859
+ try {
860
+ unregisterProject(name);
861
+ return c.json({ ok: true });
862
+ }
863
+ catch (err) {
864
+ if (err instanceof ProjectNotFoundError) {
865
+ return c.json({ error: err.message, code: err.code }, 404);
866
+ }
867
+ throw err;
868
+ }
869
+ });
870
+ app.post("/api/projects/:name/probe", async (c) => {
871
+ const name = c.req.param("name");
872
+ if (!getProject(name)) {
873
+ return c.json({ error: `Project "${name}" not found in registry`, code: "NOT_FOUND" }, 404);
874
+ }
875
+ try {
876
+ const project = await refreshProject(name);
877
+ return c.json({ project });
878
+ }
879
+ catch (err) {
880
+ if (err instanceof ProjectNotFoundError) {
881
+ return c.json({ error: err.message, code: err.code }, 404);
882
+ }
883
+ throw err;
884
+ }
885
+ });
886
+ app.post("/api/projects/init", async (c) => {
887
+ let body;
888
+ try {
889
+ body = await c.req.json();
890
+ }
891
+ catch {
892
+ return c.json({ error: "Invalid JSON body" }, 400);
893
+ }
894
+ const parsed = InitProjectRequestSchemaZ.safeParse(body);
895
+ if (!parsed.success) {
896
+ return c.json({ error: "Invalid request", details: parsed.error.issues }, 400);
897
+ }
898
+ if (!existsSync(parsed.data.dir)) {
899
+ return c.json({ error: `Directory "${parsed.data.dir}" does not exist` }, 400);
900
+ }
901
+ const jobId = randomUUID();
902
+ const command = process.env.TMUX_IDE_INIT_COMMAND ?? "tmux-ide";
903
+ // Fire-and-forget — runs in the background and streams chunks via WS.
904
+ void (async () => {
905
+ try {
906
+ await runInit({
907
+ cwd: parsed.data.dir,
908
+ template: parsed.data.template,
909
+ command,
910
+ onChunk: (chunk) => {
911
+ broadcastInitOutput(jobId, chunk);
912
+ },
913
+ });
914
+ // Mark stream complete
915
+ broadcastInitOutput(jobId, "", true);
916
+ // Probe + register the freshly-init'd project so it shows up in
917
+ // the registry — also broadcasts `projects.changed`.
918
+ try {
919
+ await registerProject({ dir: parsed.data.dir });
920
+ }
921
+ catch (err) {
922
+ // Already-registered is benign here; report anything else.
923
+ if (!(err instanceof ProjectAlreadyRegisteredError) &&
924
+ !(err instanceof ProjectDirNotFoundError)) {
925
+ broadcastInitError(jobId, err.message);
926
+ }
927
+ }
928
+ }
929
+ catch (err) {
930
+ if (err instanceof ProjectInitTimeoutError) {
931
+ broadcastInitError(jobId, err.message);
932
+ }
933
+ else if (err instanceof ProjectInitFailedError) {
934
+ broadcastInitError(jobId, err.message);
935
+ }
936
+ else {
937
+ broadcastInitError(jobId, err.message);
938
+ }
939
+ }
940
+ })();
941
+ return c.json({ jobId }, 202);
942
+ });
943
+ // -------------------------------------------------------------------------
944
+ // POST /api/filesystem/inspect — registry-agnostic directory inspection.
945
+ // POST /api/projects/onboard — generate ide.yml + register the project.
946
+ // -------------------------------------------------------------------------
947
+ app.post("/api/projects/onboard", async (c) => {
948
+ let body;
949
+ try {
950
+ body = await c.req.json();
951
+ }
952
+ catch {
953
+ return c.json({ error: "Invalid JSON body" }, 400);
954
+ }
955
+ const parsed = OnboardProjectRequestSchemaZ.safeParse(body);
956
+ if (!parsed.success) {
957
+ return c.json({ error: "Invalid request", details: parsed.error.issues }, 400);
958
+ }
959
+ const sandboxResult = sandboxResolveDir(parsed.data.dir);
960
+ if ("error" in sandboxResult) {
961
+ return c.json({ error: sandboxResult.error, message: sandboxResult.message }, sandboxResult.status);
962
+ }
963
+ const dir = sandboxResult.canonical;
964
+ let inspect;
965
+ try {
966
+ inspect = await inspectProject(dir);
967
+ }
968
+ catch (err) {
969
+ if (err instanceof InspectDirNotFoundError) {
970
+ return c.json({ error: "not-found", message: err.message }, 404);
971
+ }
972
+ throw err;
973
+ }
974
+ // Never overwrite an existing ide.yml.
975
+ try {
976
+ assertNoExistingIdeYml(dir);
977
+ }
978
+ catch (err) {
979
+ if (err instanceof OnboardConflictError) {
980
+ return c.json({ error: err.message, code: err.code }, 409);
981
+ }
982
+ throw err;
983
+ }
984
+ // Compose the config from inputs (defaults to inspect.name).
985
+ const finalName = parsed.data.name?.trim() || inspect.name;
986
+ let config;
987
+ try {
988
+ config = composeIdeYmlConfig({
989
+ name: finalName,
990
+ agents: parsed.data.agents,
991
+ agentNames: parsed.data.agentNames,
992
+ devCommand: parsed.data.devCommand ?? null,
993
+ testCommand: parsed.data.testCommand ?? null,
994
+ lintCommand: parsed.data.lintCommand ?? null,
995
+ });
996
+ }
997
+ catch (err) {
998
+ if (err instanceof OnboardInvalidInputError) {
999
+ return c.json({ error: err.message, code: err.code }, 400);
1000
+ }
1001
+ throw err;
1002
+ }
1003
+ writeConfig(dir, config);
1004
+ // Now register — this also broadcasts `projects.changed`.
1005
+ try {
1006
+ const project = await registerProject({ dir, name: finalName });
1007
+ return c.json({ project }, 201);
1008
+ }
1009
+ catch (err) {
1010
+ if (err instanceof ProjectAlreadyRegisteredError) {
1011
+ return c.json({ error: err.message, code: err.code, suggestion: err.suggestion }, 409);
1012
+ }
1013
+ if (err instanceof ProjectDirNotFoundError) {
1014
+ return c.json({ error: err.message, code: err.code }, 400);
1015
+ }
1016
+ throw err;
1017
+ }
1018
+ });
1019
+ return app;
1020
+ }
1021
+ /**
1022
+ * Discover bundled templates by reading `templates/*.yml`. Hardcoded
1023
+ * descriptions for the canonical set; unknown templates surface with a
1024
+ * generic label so we don't break if templates are added without updating
1025
+ * this map.
1026
+ */
1027
+ function listAvailableTemplates() {
1028
+ const __filename = fileURLToPath(import.meta.url);
1029
+ const __dir = dirname(__filename);
1030
+ // Repo-root templates/ — 4 levels up from packages/daemon/src/command-center/.
1031
+ // Pre-fold this lived at <pkg>/templates (..,.. worked); post-fold the
1032
+ // canonical templates dir is at the repo root.
1033
+ const templatesDir = join(__dir, "..", "..", "..", "..", "templates");
1034
+ if (!existsSync(templatesDir))
1035
+ return [];
1036
+ const labels = {
1037
+ default: { label: "Default", description: "Single Claude pane + dev/shell row" },
1038
+ nextjs: {
1039
+ label: "Next.js",
1040
+ description: "Two Claude panes + Next.js dev server + shell",
1041
+ },
1042
+ vite: { label: "Vite", description: "Vite dev server + Claude + shell" },
1043
+ convex: {
1044
+ label: "Convex",
1045
+ description: "Convex dev + Next.js + Claude pane",
1046
+ },
1047
+ python: { label: "Python", description: "Python project with Claude + tests" },
1048
+ go: { label: "Go", description: "Go project with Claude + tests + shell" },
1049
+ "agent-team": {
1050
+ label: "Agent Team",
1051
+ description: "Lead + teammate Claude panes for coordinated multi-agent work",
1052
+ },
1053
+ "agent-team-nextjs": {
1054
+ label: "Agent Team — Next.js",
1055
+ description: "Agent team layout tuned for a Next.js app",
1056
+ },
1057
+ "agent-team-monorepo": {
1058
+ label: "Agent Team — Monorepo",
1059
+ description: "Agent team layout for monorepos with multiple apps",
1060
+ },
1061
+ missions: {
1062
+ label: "Missions",
1063
+ description: "Mission-driven layout with planner, validator, and researcher",
1064
+ },
1065
+ };
1066
+ const entries = readdirSync(templatesDir).filter((f) => f.endsWith(".yml"));
1067
+ return entries
1068
+ .map((file) => {
1069
+ const id = file.replace(/\.yml$/, "");
1070
+ const meta = labels[id];
1071
+ return {
1072
+ id,
1073
+ label: meta?.label ?? id,
1074
+ description: meta?.description ?? `Template: ${id}`,
1075
+ };
1076
+ })
1077
+ .sort((a, b) => a.id.localeCompare(b.id));
1078
+ }
1079
+ /**
1080
+ * Attach the unified `/ws/events` push channel to a Node HTTP server. The
1081
+ * daemon calls this once after binding the command-center port. Existing
1082
+ * SSE endpoints (`/api/events`, `/api/project/<name>/stream`) continue to
1083
+ * work alongside this — they will be retired in a follow-up slice.
1084
+ */
1085
+ export function attachWsEvents(server) {
1086
+ const wss = new WebSocketServer({ noServer: true });
1087
+ const upgradeListener = (req, socket, head) => {
1088
+ const url = req.url ?? "/";
1089
+ const pathname = url.split("?")[0];
1090
+ if (pathname !== "/ws/events")
1091
+ return;
1092
+ wss.handleUpgrade(req, socket, head, (ws) => {
1093
+ handleWsEventsConnection(ws);
1094
+ });
1095
+ };
1096
+ server.on("upgrade", upgradeListener);
1097
+ return {
1098
+ close: () => {
1099
+ server.off("upgrade", upgradeListener);
1100
+ wss.close();
1101
+ },
1102
+ };
1103
+ }