tmux-ide 2.1.4 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (805) hide show
  1. package/README.md +115 -101
  2. package/bin/cli.js +13678 -4
  3. package/bin/cli.ts +1143 -260
  4. package/package.json +27 -17
  5. package/packages/daemon/dist/__tests__/support.d.ts +7 -0
  6. package/packages/daemon/dist/__tests__/support.js +33 -0
  7. package/packages/daemon/dist/agent-explain.d.ts +45 -0
  8. package/packages/daemon/dist/agent-explain.js +210 -0
  9. package/packages/daemon/dist/attach.d.ts +3 -0
  10. package/packages/daemon/dist/attach.js +14 -0
  11. package/packages/daemon/dist/bin.d.ts +2 -0
  12. package/packages/daemon/dist/bin.js +3 -0
  13. package/packages/daemon/dist/canonical.d.ts +2 -0
  14. package/packages/daemon/dist/canonical.js +1 -0
  15. package/packages/daemon/dist/cli.d.ts +1 -0
  16. package/packages/daemon/dist/cli.js +425 -0
  17. package/packages/daemon/dist/command-center/actions/contract.d.ts +1 -0
  18. package/packages/daemon/dist/command-center/actions/contract.js +2 -0
  19. package/packages/daemon/dist/command-center/actions/dispatcher.d.ts +27 -0
  20. package/packages/daemon/dist/command-center/actions/dispatcher.js +109 -0
  21. package/packages/daemon/dist/command-center/actions/errors.d.ts +38 -0
  22. package/packages/daemon/dist/command-center/actions/errors.js +56 -0
  23. package/packages/daemon/dist/command-center/actions/handlers/_project-context.d.ts +12 -0
  24. package/packages/daemon/dist/command-center/actions/handlers/_project-context.js +12 -0
  25. package/packages/daemon/dist/command-center/actions/handlers/_resolve-project.d.ts +42 -0
  26. package/packages/daemon/dist/command-center/actions/handlers/_resolve-project.js +48 -0
  27. package/packages/daemon/dist/command-center/actions/handlers/app-set-remote-access.d.ts +23 -0
  28. package/packages/daemon/dist/command-center/actions/handlers/app-set-remote-access.js +67 -0
  29. package/packages/daemon/dist/command-center/actions/handlers/config-actions.d.ts +12 -0
  30. package/packages/daemon/dist/command-center/actions/handlers/config-actions.js +69 -0
  31. package/packages/daemon/dist/command-center/actions/handlers/daemon-shutdown.d.ts +6 -0
  32. package/packages/daemon/dist/command-center/actions/handlers/daemon-shutdown.js +24 -0
  33. package/packages/daemon/dist/command-center/actions/handlers/project-activate.d.ts +7 -0
  34. package/packages/daemon/dist/command-center/actions/handlers/project-activate.js +19 -0
  35. package/packages/daemon/dist/command-center/actions/handlers/project-launch.d.ts +18 -0
  36. package/packages/daemon/dist/command-center/actions/handlers/project-launch.js +58 -0
  37. package/packages/daemon/dist/command-center/actions/handlers/project-open-terminal.d.ts +32 -0
  38. package/packages/daemon/dist/command-center/actions/handlers/project-open-terminal.js +69 -0
  39. package/packages/daemon/dist/command-center/actions/handlers/project-restart.d.ts +17 -0
  40. package/packages/daemon/dist/command-center/actions/handlers/project-restart.js +27 -0
  41. package/packages/daemon/dist/command-center/actions/handlers/project-stop.d.ts +24 -0
  42. package/packages/daemon/dist/command-center/actions/handlers/project-stop.js +38 -0
  43. package/packages/daemon/dist/command-center/actions/handlers/terminal-respawn.d.ts +24 -0
  44. package/packages/daemon/dist/command-center/actions/handlers/terminal-respawn.js +88 -0
  45. package/packages/daemon/dist/command-center/actions/handlers/terminal-stop.d.ts +14 -0
  46. package/packages/daemon/dist/command-center/actions/handlers/terminal-stop.js +22 -0
  47. package/packages/daemon/dist/command-center/actions/registry.d.ts +35 -0
  48. package/packages/daemon/dist/command-center/actions/registry.js +109 -0
  49. package/packages/daemon/dist/command-center/discovery.d.ts +23 -0
  50. package/packages/daemon/dist/command-center/discovery.js +67 -0
  51. package/packages/daemon/dist/command-center/index.d.ts +10 -0
  52. package/packages/daemon/dist/command-center/index.js +21 -0
  53. package/packages/daemon/dist/command-center/schemas.d.ts +76 -0
  54. package/packages/daemon/dist/command-center/schemas.js +68 -0
  55. package/packages/daemon/dist/command-center/server.d.ts +26 -0
  56. package/packages/daemon/dist/command-center/server.js +1103 -0
  57. package/packages/daemon/dist/command-center/ws-events.d.ts +59 -0
  58. package/packages/daemon/dist/command-center/ws-events.js +277 -0
  59. package/packages/daemon/dist/config.d.ts +19 -0
  60. package/packages/daemon/dist/config.js +494 -0
  61. package/packages/daemon/dist/detect.d.ts +15 -0
  62. package/packages/daemon/dist/detect.js +228 -0
  63. package/packages/daemon/dist/doctor.d.ts +21 -0
  64. package/packages/daemon/dist/doctor.js +154 -0
  65. package/packages/daemon/dist/embed.d.ts +1 -0
  66. package/packages/daemon/dist/embed.js +1 -0
  67. package/packages/daemon/dist/index.d.ts +3 -0
  68. package/packages/daemon/dist/index.js +2 -0
  69. package/packages/daemon/dist/init.d.ts +4 -0
  70. package/packages/daemon/dist/init.js +174 -0
  71. package/packages/daemon/dist/inspect.d.ts +54 -0
  72. package/packages/daemon/dist/inspect.js +118 -0
  73. package/packages/daemon/dist/launch.d.ts +23 -0
  74. package/packages/daemon/dist/launch.js +250 -0
  75. package/packages/daemon/dist/lib/active-projects.d.ts +12 -0
  76. package/packages/daemon/dist/lib/active-projects.js +35 -0
  77. package/packages/daemon/dist/lib/agent-discovery.d.ts +43 -0
  78. package/packages/daemon/dist/lib/agent-discovery.js +85 -0
  79. package/packages/daemon/dist/lib/app-config.d.ts +147 -0
  80. package/packages/daemon/dist/lib/app-config.js +191 -0
  81. package/packages/daemon/dist/lib/app-settings.d.ts +9 -0
  82. package/packages/daemon/dist/lib/app-settings.js +44 -0
  83. package/packages/daemon/dist/lib/auth/auth-service.d.ts +33 -0
  84. package/packages/daemon/dist/lib/auth/auth-service.js +172 -0
  85. package/packages/daemon/dist/lib/auth/middleware.d.ts +16 -0
  86. package/packages/daemon/dist/lib/auth/middleware.js +43 -0
  87. package/packages/daemon/dist/lib/auth/types.d.ts +1 -0
  88. package/packages/daemon/dist/lib/auth/types.js +2 -0
  89. package/packages/daemon/dist/lib/auth-token.d.ts +1 -0
  90. package/packages/daemon/dist/lib/auth-token.js +4 -0
  91. package/packages/daemon/dist/lib/authorship.d.ts +62 -0
  92. package/packages/daemon/dist/lib/authorship.js +209 -0
  93. package/packages/daemon/dist/lib/canonical-daemon.d.ts +21 -0
  94. package/packages/daemon/dist/lib/canonical-daemon.js +111 -0
  95. package/packages/daemon/dist/lib/cli-action-bridge.d.ts +27 -0
  96. package/packages/daemon/dist/lib/cli-action-bridge.js +161 -0
  97. package/packages/daemon/dist/lib/daemon-embed.d.ts +31 -0
  98. package/packages/daemon/dist/lib/daemon-embed.js +643 -0
  99. package/packages/daemon/dist/lib/daemon-watchdog.d.ts +16 -0
  100. package/packages/daemon/dist/lib/daemon-watchdog.js +98 -0
  101. package/packages/daemon/dist/lib/daemon.d.ts +8 -0
  102. package/packages/daemon/dist/lib/daemon.js +79 -0
  103. package/packages/daemon/dist/lib/dot-path.d.ts +2 -0
  104. package/packages/daemon/dist/lib/dot-path.js +17 -0
  105. package/packages/daemon/dist/lib/errors.d.ts +37 -0
  106. package/packages/daemon/dist/lib/errors.js +50 -0
  107. package/packages/daemon/dist/lib/filesystem-browser.d.ts +85 -0
  108. package/packages/daemon/dist/lib/filesystem-browser.js +257 -0
  109. package/packages/daemon/dist/lib/launch-plan.d.ts +6 -0
  110. package/packages/daemon/dist/lib/launch-plan.js +76 -0
  111. package/packages/daemon/dist/lib/log.d.ts +40 -0
  112. package/packages/daemon/dist/lib/log.js +86 -0
  113. package/packages/daemon/dist/lib/output.d.ts +9 -0
  114. package/packages/daemon/dist/lib/output.js +65 -0
  115. package/packages/daemon/dist/lib/project-init-runner.d.ts +46 -0
  116. package/packages/daemon/dist/lib/project-init-runner.js +117 -0
  117. package/packages/daemon/dist/lib/project-inspect.d.ts +28 -0
  118. package/packages/daemon/dist/lib/project-inspect.js +67 -0
  119. package/packages/daemon/dist/lib/project-onboard.d.ts +58 -0
  120. package/packages/daemon/dist/lib/project-onboard.js +108 -0
  121. package/packages/daemon/dist/lib/project-probe.d.ts +35 -0
  122. package/packages/daemon/dist/lib/project-probe.js +61 -0
  123. package/packages/daemon/dist/lib/project-registry.d.ts +76 -0
  124. package/packages/daemon/dist/lib/project-registry.js +230 -0
  125. package/packages/daemon/dist/lib/session-monitor.d.ts +15 -0
  126. package/packages/daemon/dist/lib/session-monitor.js +103 -0
  127. package/packages/daemon/dist/lib/session-options.d.ts +13 -0
  128. package/packages/daemon/dist/lib/session-options.js +85 -0
  129. package/packages/daemon/dist/lib/shell.d.ts +5 -0
  130. package/{src/lib/shell.ts → packages/daemon/dist/lib/shell.js} +3 -3
  131. package/packages/daemon/dist/lib/sizes.d.ts +16 -0
  132. package/packages/daemon/dist/lib/sizes.js +36 -0
  133. package/packages/daemon/dist/lib/skill-sync.d.ts +60 -0
  134. package/packages/daemon/dist/lib/skill-sync.js +128 -0
  135. package/packages/daemon/dist/lib/slugify.d.ts +4 -0
  136. package/packages/daemon/dist/lib/slugify.js +10 -0
  137. package/packages/daemon/dist/lib/terminals-store.d.ts +27 -0
  138. package/packages/daemon/dist/lib/terminals-store.js +111 -0
  139. package/packages/daemon/dist/lib/update-check.d.ts +118 -0
  140. package/packages/daemon/dist/lib/update-check.js +261 -0
  141. package/packages/daemon/dist/lib/update.d.ts +65 -0
  142. package/packages/daemon/dist/lib/update.js +141 -0
  143. package/packages/daemon/dist/lib/workspace-registry.d.ts +84 -0
  144. package/packages/daemon/dist/lib/workspace-registry.js +176 -0
  145. package/packages/daemon/dist/lib/worktree.d.ts +76 -0
  146. package/packages/daemon/dist/lib/worktree.js +207 -0
  147. package/packages/daemon/dist/lib/yaml-io.d.ts +10 -0
  148. package/packages/daemon/dist/lib/yaml-io.js +24 -0
  149. package/packages/daemon/dist/ls.d.ts +3 -0
  150. package/packages/daemon/dist/ls.js +35 -0
  151. package/packages/daemon/dist/restart.d.ts +4 -0
  152. package/packages/daemon/dist/restart.js +16 -0
  153. package/packages/daemon/dist/restore.d.ts +86 -0
  154. package/packages/daemon/dist/restore.js +406 -0
  155. package/packages/daemon/dist/schemas/domain.d.ts +1 -0
  156. package/packages/daemon/dist/schemas/domain.js +2 -0
  157. package/packages/daemon/dist/schemas/filesystem.d.ts +29 -0
  158. package/packages/daemon/dist/schemas/filesystem.js +29 -0
  159. package/packages/daemon/dist/schemas/ide-config.d.ts +1 -0
  160. package/packages/daemon/dist/schemas/ide-config.js +2 -0
  161. package/packages/daemon/dist/schemas/index.d.ts +12 -0
  162. package/packages/daemon/dist/schemas/index.js +6 -0
  163. package/packages/daemon/dist/schemas/inspect.d.ts +53 -0
  164. package/packages/daemon/dist/schemas/inspect.js +57 -0
  165. package/packages/daemon/dist/schemas/registry.d.ts +35 -0
  166. package/packages/daemon/dist/schemas/registry.js +43 -0
  167. package/packages/daemon/dist/schemas/ws-events.d.ts +72 -0
  168. package/packages/daemon/dist/schemas/ws-events.js +110 -0
  169. package/packages/daemon/dist/send.d.ts +27 -0
  170. package/packages/daemon/dist/send.js +141 -0
  171. package/packages/daemon/dist/server/index.d.ts +10 -0
  172. package/packages/daemon/dist/server/index.js +55 -0
  173. package/packages/daemon/dist/server/pty-bridge.d.ts +174 -0
  174. package/packages/daemon/dist/server/pty-bridge.js +422 -0
  175. package/packages/daemon/dist/server/standalone.d.ts +1 -0
  176. package/packages/daemon/dist/server/standalone.js +14 -0
  177. package/packages/daemon/dist/server/ws-route.d.ts +74 -0
  178. package/packages/daemon/dist/server/ws-route.js +379 -0
  179. package/packages/daemon/dist/status.d.ts +3 -0
  180. package/packages/daemon/dist/status.js +46 -0
  181. package/packages/daemon/dist/stop.d.ts +3 -0
  182. package/packages/daemon/dist/stop.js +21 -0
  183. package/packages/daemon/dist/terminal/NodePtyAdapter.d.ts +44 -0
  184. package/packages/daemon/dist/terminal/NodePtyAdapter.js +253 -0
  185. package/packages/daemon/dist/terminal/PtyAdapter.d.ts +124 -0
  186. package/packages/daemon/dist/terminal/PtyAdapter.js +43 -0
  187. package/packages/daemon/dist/terminal/__tests__/MockPtyAdapter.d.ts +77 -0
  188. package/packages/daemon/dist/terminal/__tests__/MockPtyAdapter.js +155 -0
  189. package/packages/daemon/dist/types.d.ts +2 -0
  190. package/packages/daemon/dist/types.js +1 -0
  191. package/packages/daemon/dist/validate.d.ts +4 -0
  192. package/packages/daemon/dist/validate.js +184 -0
  193. package/packages/daemon/dist/widgets/changes/index.d.ts +1 -0
  194. package/packages/daemon/dist/widgets/changes/index.jsx +575 -0
  195. package/packages/daemon/dist/widgets/config/index.d.ts +1 -0
  196. package/packages/daemon/dist/widgets/config/index.jsx +395 -0
  197. package/packages/daemon/dist/widgets/explorer/breadcrumbs.d.ts +10 -0
  198. package/packages/daemon/dist/widgets/explorer/breadcrumbs.jsx +51 -0
  199. package/packages/daemon/dist/widgets/explorer/footer.d.ts +6 -0
  200. package/packages/daemon/dist/widgets/explorer/footer.jsx +11 -0
  201. package/packages/daemon/dist/widgets/explorer/index.d.ts +1 -0
  202. package/packages/daemon/dist/widgets/explorer/index.jsx +393 -0
  203. package/packages/daemon/dist/widgets/explorer/tree-model.d.ts +13 -0
  204. package/packages/daemon/dist/widgets/explorer/tree-model.js +69 -0
  205. package/packages/daemon/dist/widgets/explorer/tree.d.ts +13 -0
  206. package/packages/daemon/dist/widgets/explorer/tree.jsx +108 -0
  207. package/packages/daemon/dist/widgets/lib/config-model.d.ts +22 -0
  208. package/packages/daemon/dist/widgets/lib/config-model.js +99 -0
  209. package/packages/daemon/dist/widgets/lib/files.d.ts +11 -0
  210. package/packages/daemon/dist/widgets/lib/files.js +76 -0
  211. package/packages/daemon/dist/widgets/lib/git.d.ts +11 -0
  212. package/packages/daemon/dist/widgets/lib/git.js +70 -0
  213. package/packages/daemon/dist/widgets/lib/grammar.d.ts +79 -0
  214. package/packages/daemon/dist/widgets/lib/grammar.js +95 -0
  215. package/packages/daemon/dist/widgets/lib/help-overlay.d.ts +19 -0
  216. package/packages/daemon/dist/widgets/lib/help-overlay.jsx +69 -0
  217. package/packages/daemon/dist/widgets/lib/pane-comms.d.ts +28 -0
  218. package/packages/daemon/dist/widgets/lib/pane-comms.js +189 -0
  219. package/packages/daemon/dist/widgets/lib/theme.d.ts +44 -0
  220. package/packages/daemon/dist/widgets/lib/theme.js +153 -0
  221. package/packages/daemon/dist/widgets/lib/watcher.d.ts +9 -0
  222. package/packages/daemon/dist/widgets/lib/watcher.js +92 -0
  223. package/packages/daemon/dist/widgets/preview/index.d.ts +1 -0
  224. package/packages/daemon/dist/widgets/preview/index.jsx +371 -0
  225. package/packages/daemon/dist/widgets/resolve.d.ts +20 -0
  226. package/packages/daemon/dist/widgets/resolve.js +100 -0
  227. package/packages/daemon/dist/widgets/setup/agent-naming.d.ts +9 -0
  228. package/packages/daemon/dist/widgets/setup/agent-naming.jsx +81 -0
  229. package/packages/daemon/dist/widgets/setup/config-tree.d.ts +13 -0
  230. package/packages/daemon/dist/widgets/setup/config-tree.jsx +203 -0
  231. package/packages/daemon/dist/widgets/setup/detect-panel.d.ts +14 -0
  232. package/{src/widgets/setup/detect-panel.tsx → packages/daemon/dist/widgets/setup/detect-panel.jsx} +16 -40
  233. package/packages/daemon/dist/widgets/setup/field-editor.d.ts +12 -0
  234. package/packages/daemon/dist/widgets/setup/field-editor.jsx +163 -0
  235. package/packages/daemon/dist/widgets/setup/footer.d.ts +17 -0
  236. package/packages/daemon/dist/widgets/setup/footer.jsx +64 -0
  237. package/packages/daemon/dist/widgets/setup/index.d.ts +1 -0
  238. package/packages/daemon/dist/widgets/setup/index.jsx +261 -0
  239. package/packages/daemon/dist/widgets/setup/layout-picker.d.ts +9 -0
  240. package/packages/daemon/dist/widgets/setup/layout-picker.jsx +69 -0
  241. package/packages/daemon/dist/widgets/setup/setup-model.d.ts +15 -0
  242. package/packages/daemon/dist/widgets/setup/setup-model.js +157 -0
  243. package/packages/daemon/dist/widgets/sidebar/index.d.ts +1 -0
  244. package/packages/daemon/dist/widgets/sidebar/index.jsx +462 -0
  245. package/scripts/build-cli.mjs +101 -0
  246. package/scripts/build-tui.mjs +58 -0
  247. package/scripts/capture-codex-traffic.mjs +195 -0
  248. package/scripts/check-src-additions.sh +74 -0
  249. package/scripts/coverage-summary.mjs +68 -0
  250. package/scripts/install-git-hooks.js +53 -0
  251. package/scripts/merge-update-manifests.mjs +58 -0
  252. package/scripts/merge-update-manifests.test.mjs +82 -0
  253. package/scripts/pack-check-run.mjs +83 -0
  254. package/scripts/postinstall.js +28 -6
  255. package/scripts/prepublish-check.mjs +44 -0
  256. package/scripts/stress-test.ts +141 -0
  257. package/scripts/verify-endpoints.sh +90 -0
  258. package/skill/SKILL.md +203 -236
  259. package/dashboard/out/404/index.html +0 -1
  260. package/dashboard/out/404.html +0 -1
  261. package/dashboard/out/__next.__PAGE__.txt +0 -9
  262. package/dashboard/out/__next._full.txt +0 -21
  263. package/dashboard/out/__next._head.txt +0 -5
  264. package/dashboard/out/__next._index.txt +0 -7
  265. package/dashboard/out/__next._tree.txt +0 -4
  266. package/dashboard/out/_next/static/Tl1KoIH7mHCyjo5KtXqQ0/_buildManifest.js +0 -11
  267. package/dashboard/out/_next/static/Tl1KoIH7mHCyjo5KtXqQ0/_clientMiddlewareManifest.json +0 -1
  268. package/dashboard/out/_next/static/Tl1KoIH7mHCyjo5KtXqQ0/_ssgManifest.js +0 -1
  269. package/dashboard/out/_next/static/chunks/048e2449530877e2.js +0 -1
  270. package/dashboard/out/_next/static/chunks/053c57bda6abb959.js +0 -1
  271. package/dashboard/out/_next/static/chunks/056760c6c2dd9172.js +0 -1
  272. package/dashboard/out/_next/static/chunks/06ab47357b6d3e35.js +0 -1
  273. package/dashboard/out/_next/static/chunks/0921cbe5dfd6738e.js +0 -1
  274. package/dashboard/out/_next/static/chunks/0b2599bf468cf5ea.js +0 -1
  275. package/dashboard/out/_next/static/chunks/0c012eac08ef2c4f.js +0 -1
  276. package/dashboard/out/_next/static/chunks/0c29e87fcdcffac3.js +0 -1
  277. package/dashboard/out/_next/static/chunks/0e1e98854430c693.js +0 -1
  278. package/dashboard/out/_next/static/chunks/0e24498976a88976.js +0 -1
  279. package/dashboard/out/_next/static/chunks/0e5bf11ff0b9ab90.js +0 -1
  280. package/dashboard/out/_next/static/chunks/0eae0a45ab8416c8.js +0 -1
  281. package/dashboard/out/_next/static/chunks/104797400d9d38ad.js +0 -1
  282. package/dashboard/out/_next/static/chunks/10cfcfce475f9d2d.js +0 -1
  283. package/dashboard/out/_next/static/chunks/11bac38e7cfb4ecc.js +0 -1
  284. package/dashboard/out/_next/static/chunks/120c5f6501ec3529.js +0 -1
  285. package/dashboard/out/_next/static/chunks/121fceb2b1dcd79f.js +0 -1
  286. package/dashboard/out/_next/static/chunks/13726b63e1be6b98.js +0 -1
  287. package/dashboard/out/_next/static/chunks/140c6ce631514660.js +0 -1
  288. package/dashboard/out/_next/static/chunks/1435ee3a51174c97.js +0 -1
  289. package/dashboard/out/_next/static/chunks/14dc927d2e2cca91.js +0 -1
  290. package/dashboard/out/_next/static/chunks/179c3031b292d98e.js +0 -1
  291. package/dashboard/out/_next/static/chunks/181e88957c47e5c1.js +0 -1
  292. package/dashboard/out/_next/static/chunks/18f70ba23873c432.js +0 -1
  293. package/dashboard/out/_next/static/chunks/1b58303b027fd135.js +0 -1
  294. package/dashboard/out/_next/static/chunks/1b5f49a358dcc71e.js +0 -1
  295. package/dashboard/out/_next/static/chunks/1bba44b81585099a.js +0 -1
  296. package/dashboard/out/_next/static/chunks/1bea8dee19a3e9ae.js +0 -1
  297. package/dashboard/out/_next/static/chunks/1cfad21646fc250e.js +0 -1
  298. package/dashboard/out/_next/static/chunks/1d053dc9e1e428ef.js +0 -1
  299. package/dashboard/out/_next/static/chunks/1e7d7639c6f0ee5e.js +0 -1
  300. package/dashboard/out/_next/static/chunks/1f42504ca81463f1.js +0 -1
  301. package/dashboard/out/_next/static/chunks/20c92047399305b4.js +0 -1
  302. package/dashboard/out/_next/static/chunks/214560e9514a9a4d.js +0 -1
  303. package/dashboard/out/_next/static/chunks/21d4ef106914e997.js +0 -1
  304. package/dashboard/out/_next/static/chunks/2586e83fc3dc2588.js +0 -1
  305. package/dashboard/out/_next/static/chunks/267136a09e94f5c2.js +0 -1
  306. package/dashboard/out/_next/static/chunks/271c50b329917c10.js +0 -1
  307. package/dashboard/out/_next/static/chunks/27fccecefffd88b5.js +0 -1
  308. package/dashboard/out/_next/static/chunks/28f058ed331315b6.js +0 -1
  309. package/dashboard/out/_next/static/chunks/28f704f2cc5713eb.js +0 -1
  310. package/dashboard/out/_next/static/chunks/290f67a6cd150a98.js +0 -1
  311. package/dashboard/out/_next/static/chunks/2ad12f4dcc30d30a.js +0 -1
  312. package/dashboard/out/_next/static/chunks/2b650b172078ab92.js +0 -1
  313. package/dashboard/out/_next/static/chunks/2bd91076019a6453.js +0 -1
  314. package/dashboard/out/_next/static/chunks/2e1278563a8e26be.js +0 -1
  315. package/dashboard/out/_next/static/chunks/309eb70780a3d67d.js +0 -1
  316. package/dashboard/out/_next/static/chunks/30f71950992e2307.js +0 -1
  317. package/dashboard/out/_next/static/chunks/31191873c2075784.js +0 -1
  318. package/dashboard/out/_next/static/chunks/31a790921a0c035e.js +0 -1
  319. package/dashboard/out/_next/static/chunks/34f8d7a5a06e8e32.js +0 -1
  320. package/dashboard/out/_next/static/chunks/36b3716436d9bc9d.js +0 -1
  321. package/dashboard/out/_next/static/chunks/3770b7d0ff004de3.js +0 -1
  322. package/dashboard/out/_next/static/chunks/381ab3bd4cffbf4d.js +0 -1
  323. package/dashboard/out/_next/static/chunks/38aa4eada5dcd1a4.js +0 -1
  324. package/dashboard/out/_next/static/chunks/39723132b78cb77e.js +0 -1
  325. package/dashboard/out/_next/static/chunks/399efdcc3fe56e09.js +0 -1
  326. package/dashboard/out/_next/static/chunks/3a8431a9221b0706.js +0 -1
  327. package/dashboard/out/_next/static/chunks/3a9b40810ce88cbf.js +0 -1
  328. package/dashboard/out/_next/static/chunks/3b322e3e9476ecdf.js +0 -1
  329. package/dashboard/out/_next/static/chunks/3bb14befeeb08c28.js +0 -1
  330. package/dashboard/out/_next/static/chunks/3c99637ebd462b20.js +0 -1
  331. package/dashboard/out/_next/static/chunks/3cbb9217d56459d8.js +0 -1
  332. package/dashboard/out/_next/static/chunks/3d438e0929a762f7.js +0 -1
  333. package/dashboard/out/_next/static/chunks/3e6d4834e0752f76.js +0 -2
  334. package/dashboard/out/_next/static/chunks/3e6f8cedaad4e89b.js +0 -1
  335. package/dashboard/out/_next/static/chunks/3e701259ce1b53e3.js +0 -1
  336. package/dashboard/out/_next/static/chunks/41562f7ab7c033eb.js +0 -1
  337. package/dashboard/out/_next/static/chunks/418fadd8a94e2fd7.js +0 -1
  338. package/dashboard/out/_next/static/chunks/42345437bb922e9c.js +0 -1
  339. package/dashboard/out/_next/static/chunks/434b6bd78c97b668.js +0 -1
  340. package/dashboard/out/_next/static/chunks/434febe897d33e2d.js +0 -1
  341. package/dashboard/out/_next/static/chunks/45d28707dd8ce1c1.js +0 -1
  342. package/dashboard/out/_next/static/chunks/4620a640e88cb1b7.js +0 -1
  343. package/dashboard/out/_next/static/chunks/468f8eb604502ea4.js +0 -1
  344. package/dashboard/out/_next/static/chunks/495f5cedf8afe823.js +0 -1
  345. package/dashboard/out/_next/static/chunks/49a89d1704d27740.js +0 -1
  346. package/dashboard/out/_next/static/chunks/49e5c37d15f63def.js +0 -1
  347. package/dashboard/out/_next/static/chunks/4a46ad186a8587ee.css +0 -2
  348. package/dashboard/out/_next/static/chunks/4a5c728574935d50.js +0 -1
  349. package/dashboard/out/_next/static/chunks/4b27ebd4d9304d8f.js +0 -1
  350. package/dashboard/out/_next/static/chunks/4b965aa320a9b358.js +0 -1
  351. package/dashboard/out/_next/static/chunks/4bb2da90bbe5794f.js +0 -1
  352. package/dashboard/out/_next/static/chunks/4d2f1c6f631e4b85.js +0 -1
  353. package/dashboard/out/_next/static/chunks/4d696d5a64dab42e.js +0 -1
  354. package/dashboard/out/_next/static/chunks/4f660dadb3f1e9e2.js +0 -1
  355. package/dashboard/out/_next/static/chunks/507b50d47f949333.js +0 -1
  356. package/dashboard/out/_next/static/chunks/50b1b7063bb044e2.js +0 -1
  357. package/dashboard/out/_next/static/chunks/50c0c2e3c4f02508.js +0 -1
  358. package/dashboard/out/_next/static/chunks/50d7ba9803e65b02.js +0 -1
  359. package/dashboard/out/_next/static/chunks/51535a6d4c98c7a4.js +0 -1
  360. package/dashboard/out/_next/static/chunks/526de6cc16c7dd2f.js +0 -1
  361. package/dashboard/out/_next/static/chunks/5307604f8632b3fd.js +0 -1
  362. package/dashboard/out/_next/static/chunks/5480bd722260f231.js +0 -1
  363. package/dashboard/out/_next/static/chunks/54c61c82e5f1dca5.js +0 -1
  364. package/dashboard/out/_next/static/chunks/555de6ac6bb9034c.js +0 -1
  365. package/dashboard/out/_next/static/chunks/562b89ee76a4b90c.js +0 -1
  366. package/dashboard/out/_next/static/chunks/5747f9a32edff429.js +0 -1
  367. package/dashboard/out/_next/static/chunks/57ee141430b4c05c.js +0 -1
  368. package/dashboard/out/_next/static/chunks/584c066a0837dd9a.js +0 -1
  369. package/dashboard/out/_next/static/chunks/5856aed4670a6253.js +0 -1
  370. package/dashboard/out/_next/static/chunks/58fe563414726511.js +0 -1
  371. package/dashboard/out/_next/static/chunks/5948196b2729b18c.js +0 -1
  372. package/dashboard/out/_next/static/chunks/5ab77c69e7306f97.js +0 -1
  373. package/dashboard/out/_next/static/chunks/5b3fa4c99d61611c.js +0 -1
  374. package/dashboard/out/_next/static/chunks/5cc87abaef616661.js +0 -1
  375. package/dashboard/out/_next/static/chunks/5dfa7913f99bb966.js +0 -1
  376. package/dashboard/out/_next/static/chunks/5e49b008432770f1.js +0 -1
  377. package/dashboard/out/_next/static/chunks/5e5a33dd81c45c47.js +0 -1
  378. package/dashboard/out/_next/static/chunks/5ee61bed638eb8a8.js +0 -1
  379. package/dashboard/out/_next/static/chunks/5eed557b9f45ae4a.js +0 -1
  380. package/dashboard/out/_next/static/chunks/60446823a7d30c1b.js +0 -1
  381. package/dashboard/out/_next/static/chunks/605150c490861442.js +0 -1
  382. package/dashboard/out/_next/static/chunks/609056d51c0bf332.js +0 -1
  383. package/dashboard/out/_next/static/chunks/60ec91dfeb50071b.js +0 -1
  384. package/dashboard/out/_next/static/chunks/61bc7be0bba6a33f.js +0 -1
  385. package/dashboard/out/_next/static/chunks/61f4a5c9ce23e55e.js +0 -1
  386. package/dashboard/out/_next/static/chunks/63aae3585be04e65.js +0 -1
  387. package/dashboard/out/_next/static/chunks/64e0e1ee7ef4f01b.js +0 -1
  388. package/dashboard/out/_next/static/chunks/66e9b4c26ff1aaaf.js +0 -1
  389. package/dashboard/out/_next/static/chunks/67068847aa1b5e98.js +0 -1
  390. package/dashboard/out/_next/static/chunks/68d7de1f2e202c26.js +0 -1
  391. package/dashboard/out/_next/static/chunks/698ca3ea1937ba4f.js +0 -1
  392. package/dashboard/out/_next/static/chunks/69eb97c24b5b6b9d.js +0 -1
  393. package/dashboard/out/_next/static/chunks/6b1ac098c228a479.js +0 -1
  394. package/dashboard/out/_next/static/chunks/6bb8020cb796bcc1.js +0 -1
  395. package/dashboard/out/_next/static/chunks/6cf8b1db17f2a155.js +0 -1
  396. package/dashboard/out/_next/static/chunks/6e7613643906ea88.js +0 -1
  397. package/dashboard/out/_next/static/chunks/6ea27ceb2e6feae5.js +0 -1
  398. package/dashboard/out/_next/static/chunks/6f95a8dbcf23dded.js +0 -1
  399. package/dashboard/out/_next/static/chunks/6fd44e759d82f64e.js +0 -1
  400. package/dashboard/out/_next/static/chunks/716ec29c268c38f6.js +0 -1
  401. package/dashboard/out/_next/static/chunks/717b399dfcf7c02c.js +0 -1
  402. package/dashboard/out/_next/static/chunks/72badd90e1c91348.js +0 -1
  403. package/dashboard/out/_next/static/chunks/72f9296dbb7ae3c4.js +0 -1
  404. package/dashboard/out/_next/static/chunks/73aa31e1144d8191.js +0 -1
  405. package/dashboard/out/_next/static/chunks/73f98ded8fe2e879.js +0 -1
  406. package/dashboard/out/_next/static/chunks/740a2e8ace15e13b.js +0 -1
  407. package/dashboard/out/_next/static/chunks/74e57c16e7304b6b.js +0 -1
  408. package/dashboard/out/_next/static/chunks/7628dead4d113df2.js +0 -1
  409. package/dashboard/out/_next/static/chunks/7717c88c07ed96e6.js +0 -1
  410. package/dashboard/out/_next/static/chunks/775581f7956d9a27.js +0 -1
  411. package/dashboard/out/_next/static/chunks/77d3b6661befdb98.js +0 -1
  412. package/dashboard/out/_next/static/chunks/78435c0e1c77fea7.js +0 -1
  413. package/dashboard/out/_next/static/chunks/791336748b9c9393.js +0 -1
  414. package/dashboard/out/_next/static/chunks/79ea68dfae65ef2f.js +0 -1
  415. package/dashboard/out/_next/static/chunks/7bae777a472eb13c.js +0 -1
  416. package/dashboard/out/_next/static/chunks/7fd847f47237a35c.js +0 -1
  417. package/dashboard/out/_next/static/chunks/804d718be0370058.css +0 -1
  418. package/dashboard/out/_next/static/chunks/807cb3c1923995ab.js +0 -1
  419. package/dashboard/out/_next/static/chunks/8286b39407d94447.js +0 -1
  420. package/dashboard/out/_next/static/chunks/84e4305b8dc830ed.js +0 -1
  421. package/dashboard/out/_next/static/chunks/850f99dbfabb53e0.js +0 -1
  422. package/dashboard/out/_next/static/chunks/85594127e66b6b7f.js +0 -1
  423. package/dashboard/out/_next/static/chunks/858c11169c183c9c.js +0 -1
  424. package/dashboard/out/_next/static/chunks/85e27005dfe4c3e3.js +0 -1
  425. package/dashboard/out/_next/static/chunks/8707bd3d8ddc1f1c.js +0 -1
  426. package/dashboard/out/_next/static/chunks/8851e5d7ef894973.js +0 -1
  427. package/dashboard/out/_next/static/chunks/88ba3782cc614989.js +0 -1
  428. package/dashboard/out/_next/static/chunks/8a0c9a181784c2ef.js +0 -1
  429. package/dashboard/out/_next/static/chunks/8ad01ae355a6e7f6.js +0 -1
  430. package/dashboard/out/_next/static/chunks/8d2ed93b0d0a4b4f.js +0 -1
  431. package/dashboard/out/_next/static/chunks/8dc352ebd5310d3c.js +0 -1
  432. package/dashboard/out/_next/static/chunks/8dd1d722c8c1a22c.js +0 -1
  433. package/dashboard/out/_next/static/chunks/8e60fe307e3e4986.js +0 -1
  434. package/dashboard/out/_next/static/chunks/8eea4dd71e25f32a.js +0 -1
  435. package/dashboard/out/_next/static/chunks/8f468a65bac34eaa.js +0 -1
  436. package/dashboard/out/_next/static/chunks/9057e5382d6a5059.js +0 -1
  437. package/dashboard/out/_next/static/chunks/931d056437805ecb.js +0 -1
  438. package/dashboard/out/_next/static/chunks/954eb11648dd8cff.js +0 -1
  439. package/dashboard/out/_next/static/chunks/955034d876d14bb3.js +0 -1
  440. package/dashboard/out/_next/static/chunks/966c4895773249f6.js +0 -1
  441. package/dashboard/out/_next/static/chunks/96aff410a6ab106c.js +0 -1
  442. package/dashboard/out/_next/static/chunks/99b396c821c1dd2d.js +0 -1
  443. package/dashboard/out/_next/static/chunks/9a255fd2cf4922ae.js +0 -1
  444. package/dashboard/out/_next/static/chunks/9b1f6aa73bc864b2.js +0 -1
  445. package/dashboard/out/_next/static/chunks/9b9ce582c533aa79.js +0 -1
  446. package/dashboard/out/_next/static/chunks/9c19bd3c773c6611.js +0 -1
  447. package/dashboard/out/_next/static/chunks/9ceeaa847eb15ca2.js +0 -1
  448. package/dashboard/out/_next/static/chunks/9d2e6e7b8b65f845.js +0 -1
  449. package/dashboard/out/_next/static/chunks/9de23802066128ff.js +0 -1
  450. package/dashboard/out/_next/static/chunks/9e327f94b3701170.js +0 -1
  451. package/dashboard/out/_next/static/chunks/9e7818421c2d455a.js +0 -1
  452. package/dashboard/out/_next/static/chunks/9e935acbcf2fb519.js +0 -1
  453. package/dashboard/out/_next/static/chunks/9ed9f68340343b51.js +0 -1
  454. package/dashboard/out/_next/static/chunks/9f94a0242455fc20.js +0 -1
  455. package/dashboard/out/_next/static/chunks/9fff46b5aaecf47e.js +0 -1
  456. package/dashboard/out/_next/static/chunks/a06d267a5c557657.js +0 -1
  457. package/dashboard/out/_next/static/chunks/a0eb8c81c54722fe.js +0 -1
  458. package/dashboard/out/_next/static/chunks/a16808e83106427d.js +0 -1
  459. package/dashboard/out/_next/static/chunks/a2215e2bc72739ef.js +0 -1
  460. package/dashboard/out/_next/static/chunks/a2de9e6696eb9c17.js +0 -1
  461. package/dashboard/out/_next/static/chunks/a33420b8c14090d6.js +0 -1
  462. package/dashboard/out/_next/static/chunks/a360bffef39d818b.js +0 -1
  463. package/dashboard/out/_next/static/chunks/a42852fdf5287cf5.js +0 -1
  464. package/dashboard/out/_next/static/chunks/a4efc88488322b67.js +0 -1
  465. package/dashboard/out/_next/static/chunks/a696a91d14101bdb.js +0 -1
  466. package/dashboard/out/_next/static/chunks/a6dad97d9634a72d.js +0 -1
  467. package/dashboard/out/_next/static/chunks/a6dad97d9634a72d.js.map +0 -1
  468. package/dashboard/out/_next/static/chunks/a705c7261712bd8e.js +0 -1
  469. package/dashboard/out/_next/static/chunks/a7d1e4b067ace180.js +0 -1
  470. package/dashboard/out/_next/static/chunks/a8590c121a7efaa5.js +0 -1
  471. package/dashboard/out/_next/static/chunks/a95953a83a6df6cf.js +0 -1
  472. package/dashboard/out/_next/static/chunks/a9d0a757d3b4afed.js +0 -1
  473. package/dashboard/out/_next/static/chunks/a9dc35514619c872.js +0 -1
  474. package/dashboard/out/_next/static/chunks/aae0253c73fba984.js +0 -193
  475. package/dashboard/out/_next/static/chunks/ab1821552066a74d.js +0 -1
  476. package/dashboard/out/_next/static/chunks/ac96bc0eccebe15a.js +0 -1
  477. package/dashboard/out/_next/static/chunks/acc03cfaaf6bb30f.js +0 -1
  478. package/dashboard/out/_next/static/chunks/acc298ae059b9fe4.js +0 -1
  479. package/dashboard/out/_next/static/chunks/ad076b6e996d250c.js +0 -1
  480. package/dashboard/out/_next/static/chunks/ae53b64af7ba16d5.js +0 -1
  481. package/dashboard/out/_next/static/chunks/ae5da7fa4bc5fa95.js +0 -1
  482. package/dashboard/out/_next/static/chunks/aefcf0eb033a155e.js +0 -1
  483. package/dashboard/out/_next/static/chunks/b12d43100ee10526.js +0 -1
  484. package/dashboard/out/_next/static/chunks/b137952dd5566a41.js +0 -1
  485. package/dashboard/out/_next/static/chunks/b2832d8a2d332a47.js +0 -1
  486. package/dashboard/out/_next/static/chunks/b417aa09c15f63c6.js +0 -1
  487. package/dashboard/out/_next/static/chunks/b48e152ba7bf6caf.js +0 -1
  488. package/dashboard/out/_next/static/chunks/b4cbef8e4714bf92.js +0 -1
  489. package/dashboard/out/_next/static/chunks/b568ff8383a37f53.js +0 -1
  490. package/dashboard/out/_next/static/chunks/b6e1495dd89a39e3.js +0 -1
  491. package/dashboard/out/_next/static/chunks/b73a21bd67528440.js +0 -1
  492. package/dashboard/out/_next/static/chunks/b77ee62bc71dcec7.js +0 -1
  493. package/dashboard/out/_next/static/chunks/b7f454615c11d4eb.js +0 -1
  494. package/dashboard/out/_next/static/chunks/b818ea32a839590f.js +0 -1
  495. package/dashboard/out/_next/static/chunks/b901ce78c1c65d66.js +0 -1
  496. package/dashboard/out/_next/static/chunks/b93d647b803be9fa.js +0 -1
  497. package/dashboard/out/_next/static/chunks/b960b09ff1ecd6bb.js +0 -1
  498. package/dashboard/out/_next/static/chunks/ba717c7779a778fc.js +0 -1
  499. package/dashboard/out/_next/static/chunks/bacb0ae7458d18b6.js +0 -1
  500. package/dashboard/out/_next/static/chunks/bb51f68b27346852.js +0 -1
  501. package/dashboard/out/_next/static/chunks/bb67f22e1ab632ae.js +0 -1
  502. package/dashboard/out/_next/static/chunks/bbae97ec58d1bb9d.js +0 -1
  503. package/dashboard/out/_next/static/chunks/bbaf38ee90307765.js +0 -1
  504. package/dashboard/out/_next/static/chunks/be01598fe1fce5db.js +0 -1
  505. package/dashboard/out/_next/static/chunks/bf4cbbc095987fec.js +0 -1
  506. package/dashboard/out/_next/static/chunks/c18f823797d57446.js +0 -1
  507. package/dashboard/out/_next/static/chunks/c1bcece34ec5b295.js +0 -1
  508. package/dashboard/out/_next/static/chunks/c1ccbc3a51adaf0a.js +0 -1
  509. package/dashboard/out/_next/static/chunks/c1f54a628f27791c.js +0 -1
  510. package/dashboard/out/_next/static/chunks/c21916bf5d232151.js +0 -1
  511. package/dashboard/out/_next/static/chunks/c27e570f0fc2f78b.js +0 -1
  512. package/dashboard/out/_next/static/chunks/c322b8005eebc0d8.js +0 -1
  513. package/dashboard/out/_next/static/chunks/c3900ac2b009b764.js +0 -1
  514. package/dashboard/out/_next/static/chunks/c3c597c8eb77ad6b.js +0 -1
  515. package/dashboard/out/_next/static/chunks/c58d45c1d88e208c.js +0 -1
  516. package/dashboard/out/_next/static/chunks/c63875998d7a655f.js +0 -1
  517. package/dashboard/out/_next/static/chunks/c6eaa7c8e7209c8e.js +0 -1
  518. package/dashboard/out/_next/static/chunks/c6f820f71162a59a.js +0 -1
  519. package/dashboard/out/_next/static/chunks/c7ce0941d1dfe7ed.js +0 -1
  520. package/dashboard/out/_next/static/chunks/c877259f784ec8e5.js +0 -1
  521. package/dashboard/out/_next/static/chunks/cb8057e86aaa1c68.js +0 -1
  522. package/dashboard/out/_next/static/chunks/ccb4e306ee4859b1.js +0 -1
  523. package/dashboard/out/_next/static/chunks/ccde62b0fa8112eb.js +0 -1
  524. package/dashboard/out/_next/static/chunks/cd421f0971c63c31.js +0 -1
  525. package/dashboard/out/_next/static/chunks/cde0317494d4adb7.js +0 -1
  526. package/dashboard/out/_next/static/chunks/cfae64434b92b8b6.js +0 -1
  527. package/dashboard/out/_next/static/chunks/cfc0e19310ec0a36.js +0 -1
  528. package/dashboard/out/_next/static/chunks/d0f344c7d0bcb59a.js +0 -1
  529. package/dashboard/out/_next/static/chunks/d1871c73e74e1f50.js +0 -1
  530. package/dashboard/out/_next/static/chunks/d18f658850711061.js +0 -1
  531. package/dashboard/out/_next/static/chunks/d25d9c48880697f6.js +0 -1
  532. package/dashboard/out/_next/static/chunks/d3f0a72bbc3060b0.js +0 -1
  533. package/dashboard/out/_next/static/chunks/d5fca429bc89060b.js +0 -1
  534. package/dashboard/out/_next/static/chunks/d6a6c75c9a4bef49.js +0 -1
  535. package/dashboard/out/_next/static/chunks/d6a8f93aa8f1e345.js +0 -1
  536. package/dashboard/out/_next/static/chunks/d7deab676b19ba0e.js +0 -1
  537. package/dashboard/out/_next/static/chunks/d80030dde88cec85.js +0 -1
  538. package/dashboard/out/_next/static/chunks/da84f9774c076ff1.js +0 -1
  539. package/dashboard/out/_next/static/chunks/da98ecc6b9b0ceb2.js +0 -1
  540. package/dashboard/out/_next/static/chunks/db550aabce60b912.js +0 -4
  541. package/dashboard/out/_next/static/chunks/dc87f77fcc029482.js +0 -1
  542. package/dashboard/out/_next/static/chunks/dd05f30acdb63a53.js +0 -1
  543. package/dashboard/out/_next/static/chunks/dea150155499b903.js +0 -1
  544. package/dashboard/out/_next/static/chunks/df4358754ff1d5e8.js +0 -1
  545. package/dashboard/out/_next/static/chunks/df8b21ff12d23b0e.js +0 -1
  546. package/dashboard/out/_next/static/chunks/df8fc68d77debf2c.js +0 -1
  547. package/dashboard/out/_next/static/chunks/df9ed1ffec90589f.js +0 -1
  548. package/dashboard/out/_next/static/chunks/dfa65ece1598f934.js +0 -1
  549. package/dashboard/out/_next/static/chunks/dfaab5cdd41a20d9.js +0 -1
  550. package/dashboard/out/_next/static/chunks/e00c03c942b5ae3e.js +0 -1
  551. package/dashboard/out/_next/static/chunks/e02d27cf679bece1.js +0 -1
  552. package/dashboard/out/_next/static/chunks/e0b747585f78513a.js +0 -1
  553. package/dashboard/out/_next/static/chunks/e19b71ca23fd7df0.js +0 -1
  554. package/dashboard/out/_next/static/chunks/e21cbe89d0cda120.js +0 -1
  555. package/dashboard/out/_next/static/chunks/e2a0386930edd34f.js +0 -1
  556. package/dashboard/out/_next/static/chunks/e375de19a36e2f38.js +0 -1
  557. package/dashboard/out/_next/static/chunks/e5241b4a6496a9e0.js +0 -1
  558. package/dashboard/out/_next/static/chunks/e569dd07c96eb4dd.js +0 -1
  559. package/dashboard/out/_next/static/chunks/e61c3ea91233f948.js +0 -1
  560. package/dashboard/out/_next/static/chunks/e73b42c5d34c4c28.js +0 -1
  561. package/dashboard/out/_next/static/chunks/e7c5b2105f651e87.js +0 -1
  562. package/dashboard/out/_next/static/chunks/e878e58a69bb01b6.js +0 -1
  563. package/dashboard/out/_next/static/chunks/e8f090a4dc571062.js +0 -1
  564. package/dashboard/out/_next/static/chunks/e98dc34dac91cdad.js +0 -1
  565. package/dashboard/out/_next/static/chunks/ea67cf7a0c5e7233.js +0 -1
  566. package/dashboard/out/_next/static/chunks/eacc98a1e3512fa9.js +0 -1
  567. package/dashboard/out/_next/static/chunks/eae9cd74d9bbed8b.js +0 -1
  568. package/dashboard/out/_next/static/chunks/eb187fd345852b34.js +0 -1
  569. package/dashboard/out/_next/static/chunks/ecea46df7a40b427.js +0 -1
  570. package/dashboard/out/_next/static/chunks/ecf48b83f4245d9c.js +0 -1
  571. package/dashboard/out/_next/static/chunks/eda41732bf966c6d.js +0 -1
  572. package/dashboard/out/_next/static/chunks/ee174a433049f43a.js +0 -1
  573. package/dashboard/out/_next/static/chunks/ee66b2d3b76de72e.js +0 -1
  574. package/dashboard/out/_next/static/chunks/ef058d3041c3d8ab.js +0 -1
  575. package/dashboard/out/_next/static/chunks/f3544b800b0d4969.js +0 -1
  576. package/dashboard/out/_next/static/chunks/f3b280e604b97509.js +0 -1
  577. package/dashboard/out/_next/static/chunks/f42e1d3693232993.js +0 -1
  578. package/dashboard/out/_next/static/chunks/f5a5fdd80166d304.js +0 -1
  579. package/dashboard/out/_next/static/chunks/f60adc5dd6169316.js +0 -1
  580. package/dashboard/out/_next/static/chunks/f6255bc2e6c68ce8.js +0 -1
  581. package/dashboard/out/_next/static/chunks/f6bb677d2d8840db.js +0 -1
  582. package/dashboard/out/_next/static/chunks/f6f3bf016239c33a.js +0 -1
  583. package/dashboard/out/_next/static/chunks/f6f57a46cd074bfe.js +0 -1
  584. package/dashboard/out/_next/static/chunks/f7feb9c1199e8cf6.js +0 -1
  585. package/dashboard/out/_next/static/chunks/f831087bf964cc3d.js +0 -1
  586. package/dashboard/out/_next/static/chunks/fa5a2f7244935aa2.js +0 -1
  587. package/dashboard/out/_next/static/chunks/fa73f36df4c38fa0.js +0 -1
  588. package/dashboard/out/_next/static/chunks/faa1461722d6a88d.js +0 -1
  589. package/dashboard/out/_next/static/chunks/fbf706b9a0edb7e6.js +0 -1
  590. package/dashboard/out/_next/static/chunks/fc2b8c8b7446bbc2.js +0 -1
  591. package/dashboard/out/_next/static/chunks/fd516f3930c128c1.js +0 -1
  592. package/dashboard/out/_next/static/chunks/fd663e7ff8de4887.js +0 -1
  593. package/dashboard/out/_next/static/chunks/fe5b656cc9bdd60e.js +0 -1
  594. package/dashboard/out/_next/static/chunks/turbopack-2f5dec4a537c0ee7.js +0 -4
  595. package/dashboard/out/_next/static/media/02263ebadd758ea4-s.8da66e7f.woff2 +0 -0
  596. package/dashboard/out/_next/static/media/2fe89d53234c61d4-s.cb53f04b.woff2 +0 -0
  597. package/dashboard/out/_next/static/media/59b15b4bcd7b1eb5-s.afa48be3.woff2 +0 -0
  598. package/dashboard/out/_next/static/media/5e05ae5b48faa55e-s.6b5ea6af.woff2 +0 -0
  599. package/dashboard/out/_next/static/media/68757d6cddeff913-s.e6cd1753.woff2 +0 -0
  600. package/dashboard/out/_next/static/media/99e609270109b47d-s.p.64b9304e.woff2 +0 -0
  601. package/dashboard/out/_next/static/media/a7afbb44bec2bb18-s.1dcddae6.woff2 +0 -0
  602. package/dashboard/out/_next/static/media/e390973e931a41c5-s.a82ecf4e.woff2 +0 -0
  603. package/dashboard/out/_next/static/media/e532fa1b9921e1cd-s.764b43eb.woff2 +0 -0
  604. package/dashboard/out/_next/static/media/effe91970fc4db64-s.p.19510058.woff2 +0 -0
  605. package/dashboard/out/_not-found/__next._full.txt +0 -15
  606. package/dashboard/out/_not-found/__next._head.txt +0 -5
  607. package/dashboard/out/_not-found/__next._index.txt +0 -7
  608. package/dashboard/out/_not-found/__next._not-found.__PAGE__.txt +0 -5
  609. package/dashboard/out/_not-found/__next._not-found.txt +0 -4
  610. package/dashboard/out/_not-found/__next._tree.txt +0 -2
  611. package/dashboard/out/_not-found/index.html +0 -1
  612. package/dashboard/out/_not-found/index.txt +0 -15
  613. package/dashboard/out/index.html +0 -1
  614. package/dashboard/out/index.txt +0 -21
  615. package/dashboard/out/project/__fallback/__next._full.txt +0 -19
  616. package/dashboard/out/project/__fallback/__next._head.txt +0 -5
  617. package/dashboard/out/project/__fallback/__next._index.txt +0 -7
  618. package/dashboard/out/project/__fallback/__next._tree.txt +0 -5
  619. package/dashboard/out/project/__fallback/__next.project.$d$name.__PAGE__.txt +0 -7
  620. package/dashboard/out/project/__fallback/__next.project.$d$name.txt +0 -4
  621. package/dashboard/out/project/__fallback/__next.project.txt +0 -4
  622. package/dashboard/out/project/__fallback/index.html +0 -1
  623. package/dashboard/out/project/__fallback/index.txt +0 -19
  624. package/src/__tests__/support.ts +0 -186
  625. package/src/attach.ts +0 -20
  626. package/src/cli.test.ts +0 -314
  627. package/src/command-center/discovery.test.ts +0 -265
  628. package/src/command-center/discovery.ts +0 -296
  629. package/src/command-center/index.ts +0 -31
  630. package/src/command-center/schemas.ts +0 -57
  631. package/src/command-center/server.test.ts +0 -814
  632. package/src/command-center/server.ts +0 -1427
  633. package/src/command-center/static.test.ts +0 -105
  634. package/src/command-center/static.ts +0 -122
  635. package/src/config-cli.test.ts +0 -86
  636. package/src/config.test.ts +0 -205
  637. package/src/config.ts +0 -313
  638. package/src/detect.test.ts +0 -142
  639. package/src/detect.ts +0 -248
  640. package/src/dispatch.ts +0 -102
  641. package/src/doctor.test.ts +0 -119
  642. package/src/doctor.ts +0 -167
  643. package/src/init.test.ts +0 -101
  644. package/src/init.ts +0 -211
  645. package/src/inspect.test.ts +0 -67
  646. package/src/inspect.ts +0 -212
  647. package/src/integration.test.ts.skip +0 -276
  648. package/src/js-yaml.d.ts +0 -10
  649. package/src/launch.test.ts +0 -149
  650. package/src/launch.ts +0 -583
  651. package/src/lib/auth/auth-service.test.ts +0 -178
  652. package/src/lib/auth/auth-service.ts +0 -227
  653. package/src/lib/auth/middleware.test.ts +0 -119
  654. package/src/lib/auth/middleware.ts +0 -56
  655. package/src/lib/auth/types.ts +0 -13
  656. package/src/lib/authorship.test.ts +0 -242
  657. package/src/lib/authorship.ts +0 -280
  658. package/src/lib/cast/recorder.test.ts +0 -127
  659. package/src/lib/cast/recorder.ts +0 -148
  660. package/src/lib/daemon-watchdog.ts +0 -102
  661. package/src/lib/daemon.ts +0 -431
  662. package/src/lib/dot-path.test.ts +0 -66
  663. package/src/lib/dot-path.ts +0 -17
  664. package/src/lib/errors.ts +0 -44
  665. package/src/lib/event-log.test.ts +0 -189
  666. package/src/lib/event-log.ts +0 -237
  667. package/src/lib/github-pr.ts +0 -182
  668. package/src/lib/hq/client.test.ts +0 -154
  669. package/src/lib/hq/client.ts +0 -142
  670. package/src/lib/hq/mdns.test.ts +0 -54
  671. package/src/lib/hq/mdns.ts +0 -88
  672. package/src/lib/hq/registry.test.ts +0 -237
  673. package/src/lib/hq/registry.ts +0 -145
  674. package/src/lib/hq/types.ts +0 -44
  675. package/src/lib/ipc/socket-protocol.test.ts +0 -126
  676. package/src/lib/ipc/socket-protocol.ts +0 -324
  677. package/src/lib/launch-plan.test.ts +0 -119
  678. package/src/lib/launch-plan.ts +0 -90
  679. package/src/lib/log.test.ts +0 -39
  680. package/src/lib/log.ts +0 -71
  681. package/src/lib/metrics.test.ts +0 -213
  682. package/src/lib/metrics.ts +0 -345
  683. package/src/lib/orchestrator.test.ts +0 -2358
  684. package/src/lib/orchestrator.ts +0 -1799
  685. package/src/lib/output.ts +0 -76
  686. package/src/lib/plan-store.test.ts +0 -148
  687. package/src/lib/plan-store.ts +0 -131
  688. package/src/lib/research.test.ts +0 -208
  689. package/src/lib/research.ts +0 -475
  690. package/src/lib/round-trip.test.ts +0 -341
  691. package/src/lib/session-monitor.test.ts +0 -152
  692. package/src/lib/session-monitor.ts +0 -282
  693. package/src/lib/session-options.test.ts +0 -146
  694. package/src/lib/session-options.ts +0 -100
  695. package/src/lib/shell.test.ts +0 -20
  696. package/src/lib/sizes.test.ts +0 -73
  697. package/src/lib/sizes.ts +0 -36
  698. package/src/lib/skill-registry.test.ts +0 -134
  699. package/src/lib/skill-registry.ts +0 -86
  700. package/src/lib/slugify.test.ts +0 -35
  701. package/src/lib/slugify.ts +0 -10
  702. package/src/lib/task-store.ts +0 -352
  703. package/src/lib/tmux.test.ts +0 -500
  704. package/src/lib/tmux.ts +0 -372
  705. package/src/lib/token-tracker.test.ts +0 -102
  706. package/src/lib/token-tracker.ts +0 -70
  707. package/src/lib/tunnels/cloudflare.test.ts +0 -73
  708. package/src/lib/tunnels/cloudflare.ts +0 -254
  709. package/src/lib/tunnels/manager.test.ts +0 -63
  710. package/src/lib/tunnels/manager.ts +0 -132
  711. package/src/lib/tunnels/ngrok.test.ts +0 -94
  712. package/src/lib/tunnels/ngrok.ts +0 -261
  713. package/src/lib/tunnels/tailscale.test.ts +0 -103
  714. package/src/lib/tunnels/tailscale.ts +0 -1048
  715. package/src/lib/tunnels/types.ts +0 -44
  716. package/src/lib/validation.test.ts +0 -289
  717. package/src/lib/validation.ts +0 -123
  718. package/src/lib/webhook.ts +0 -51
  719. package/src/lib/workflow-store.ts +0 -209
  720. package/src/lib/ws-v3/protocol.test.ts +0 -127
  721. package/src/lib/ws-v3/protocol.ts +0 -160
  722. package/src/lib/yaml-io.test.ts +0 -125
  723. package/src/lib/yaml-io.ts +0 -27
  724. package/src/ls.test.ts +0 -76
  725. package/src/ls.ts +0 -40
  726. package/src/metrics-cli.ts +0 -177
  727. package/src/notify.ts +0 -85
  728. package/src/orchestrator-status.ts +0 -228
  729. package/src/plan.ts +0 -117
  730. package/src/postinstall.test.ts +0 -79
  731. package/src/remote.test.ts +0 -115
  732. package/src/remote.ts +0 -148
  733. package/src/restart.ts +0 -24
  734. package/src/schemas/domain.ts +0 -422
  735. package/src/schemas/ide-config.ts +0 -148
  736. package/src/schemas/index.ts +0 -53
  737. package/src/send.test.ts +0 -70
  738. package/src/send.ts +0 -181
  739. package/src/skill.test.ts +0 -114
  740. package/src/skill.ts +0 -138
  741. package/src/status.ts +0 -66
  742. package/src/stop.test.ts +0 -151
  743. package/src/stop.ts +0 -37
  744. package/src/task.test.ts +0 -1466
  745. package/src/task.ts +0 -1143
  746. package/src/tunnel.test.ts +0 -80
  747. package/src/tunnel.ts +0 -133
  748. package/src/types.ts +0 -15
  749. package/src/ui/index.ts +0 -32
  750. package/src/ui/terminal/index.ts +0 -9
  751. package/src/ui/types.ts +0 -91
  752. package/src/ui/web/base.css +0 -80
  753. package/src/ui/web/components/Box.tsx +0 -59
  754. package/src/ui/web/components/Input.tsx +0 -32
  755. package/src/ui/web/components/ScrollBox.tsx +0 -60
  756. package/src/ui/web/components/Text.tsx +0 -28
  757. package/src/ui/web/hooks.ts +0 -106
  758. package/src/ui/web/index.ts +0 -27
  759. package/src/ui/web/render.ts +0 -77
  760. package/src/ui/web/utils/color.test.ts +0 -93
  761. package/src/ui/web/utils/color.ts +0 -27
  762. package/src/validate.test.ts +0 -385
  763. package/src/validate.ts +0 -217
  764. package/src/widgets/changes/index.tsx +0 -576
  765. package/src/widgets/config/index.tsx +0 -440
  766. package/src/widgets/costs/index.tsx +0 -216
  767. package/src/widgets/explorer/breadcrumbs.tsx +0 -77
  768. package/src/widgets/explorer/footer.tsx +0 -20
  769. package/src/widgets/explorer/header.tsx +0 -23
  770. package/src/widgets/explorer/index.tsx +0 -408
  771. package/src/widgets/explorer/tree-model.test.ts +0 -214
  772. package/src/widgets/explorer/tree-model.ts +0 -103
  773. package/src/widgets/explorer/tree.tsx +0 -156
  774. package/src/widgets/lib/config-model.ts +0 -116
  775. package/src/widgets/lib/files.test.ts +0 -103
  776. package/src/widgets/lib/files.ts +0 -88
  777. package/src/widgets/lib/git.test.ts +0 -151
  778. package/src/widgets/lib/git.ts +0 -88
  779. package/src/widgets/lib/pane-comms.test.ts +0 -178
  780. package/src/widgets/lib/pane-comms.ts +0 -207
  781. package/src/widgets/lib/theme.ts +0 -151
  782. package/src/widgets/lib/watcher.ts +0 -50
  783. package/src/widgets/mission-control/activity-feed.tsx +0 -59
  784. package/src/widgets/mission-control/agent-panel.tsx +0 -132
  785. package/src/widgets/mission-control/command-bar.tsx +0 -63
  786. package/src/widgets/mission-control/index.tsx +0 -751
  787. package/src/widgets/mission-control/task-panel.tsx +0 -238
  788. package/src/widgets/preview/index.tsx +0 -415
  789. package/src/widgets/resolve.ts +0 -40
  790. package/src/widgets/setup/agent-naming.tsx +0 -112
  791. package/src/widgets/setup/config-tree.tsx +0 -238
  792. package/src/widgets/setup/field-editor.tsx +0 -265
  793. package/src/widgets/setup/footer.tsx +0 -107
  794. package/src/widgets/setup/index.tsx +0 -340
  795. package/src/widgets/setup/layout-picker.tsx +0 -96
  796. package/src/widgets/setup/orchestrator-panel.tsx +0 -200
  797. package/src/widgets/setup/review-panel.tsx +0 -140
  798. package/src/widgets/setup/setup-model.test.ts +0 -303
  799. package/src/widgets/setup/setup-model.ts +0 -188
  800. package/src/widgets/tasks/index.tsx +0 -129
  801. package/src/widgets/tasks/task-detail.tsx +0 -309
  802. package/src/widgets/tasks/task-form.tsx +0 -193
  803. package/src/widgets/tasks/task-list.tsx +0 -205
  804. package/src/widgets/tasks/task-model.test.ts +0 -473
  805. package/src/widgets/tasks/task-model.ts +0 -157
@@ -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
+ }