@neuralnomads/codenomad-dev 0.10.3-dev-20260213-ba418a85

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 (462) hide show
  1. package/README.md +126 -0
  2. package/dist/api-types.js +1 -0
  3. package/dist/auth/auth-store.js +134 -0
  4. package/dist/auth/http-auth.js +37 -0
  5. package/dist/auth/manager.js +128 -0
  6. package/dist/auth/password-hash.js +32 -0
  7. package/dist/auth/session-manager.js +17 -0
  8. package/dist/auth/token-manager.js +27 -0
  9. package/dist/background-processes/manager.js +437 -0
  10. package/dist/bin.js +24 -0
  11. package/dist/config/binaries.js +148 -0
  12. package/dist/config/location.js +57 -0
  13. package/dist/config/schema.js +70 -0
  14. package/dist/config/store.js +200 -0
  15. package/dist/events/bus.js +41 -0
  16. package/dist/filesystem/__tests__/search-cache.test.js +40 -0
  17. package/dist/filesystem/browser.js +285 -0
  18. package/dist/filesystem/search-cache.js +43 -0
  19. package/dist/filesystem/search.js +135 -0
  20. package/dist/index.js +410 -0
  21. package/dist/integrations/github/bot-signature.js +11 -0
  22. package/dist/integrations/github/git-ops.js +133 -0
  23. package/dist/integrations/github/github-types.js +1 -0
  24. package/dist/integrations/github/job-runner.js +608 -0
  25. package/dist/integrations/github/octokit.js +58 -0
  26. package/dist/integrations/github/sanitize-webhook.js +42 -0
  27. package/dist/integrations/github/webhook-verify.js +21 -0
  28. package/dist/integrations/github/workspace-context.js +10 -0
  29. package/dist/integrations/github/worktree-context.js +15 -0
  30. package/dist/launcher.js +149 -0
  31. package/dist/loader.js +21 -0
  32. package/dist/logger.js +109 -0
  33. package/dist/opencode/request-context.js +39 -0
  34. package/dist/opencode/worktree-directory.js +42 -0
  35. package/dist/opencode-config/README.md +32 -0
  36. package/dist/opencode-config/opencode.jsonc +3 -0
  37. package/dist/opencode-config/package.json +9 -0
  38. package/dist/opencode-config/plugin/codenomad.ts +32 -0
  39. package/dist/opencode-config/plugin/lib/background-process.ts +253 -0
  40. package/dist/opencode-config/plugin/lib/client.ts +133 -0
  41. package/dist/opencode-config/plugin/lib/request.ts +214 -0
  42. package/dist/opencode-config-template/README.md +32 -0
  43. package/dist/opencode-config-template/opencode.jsonc +3 -0
  44. package/dist/opencode-config-template/plugin/codenomad.ts +40 -0
  45. package/dist/opencode-config-template/plugin/lib/background-process.ts +160 -0
  46. package/dist/opencode-config-template/plugin/lib/client.ts +165 -0
  47. package/dist/opencode-config.js +26 -0
  48. package/dist/plugins/channel.js +40 -0
  49. package/dist/plugins/handlers.js +17 -0
  50. package/dist/releases/dev-release-monitor.js +75 -0
  51. package/dist/releases/release-monitor.js +107 -0
  52. package/dist/server/http-server.js +547 -0
  53. package/dist/server/network-addresses.js +72 -0
  54. package/dist/server/routes/auth-pages/login.html +134 -0
  55. package/dist/server/routes/auth-pages/token.html +93 -0
  56. package/dist/server/routes/auth.js +134 -0
  57. package/dist/server/routes/background-processes.js +60 -0
  58. package/dist/server/routes/config.js +59 -0
  59. package/dist/server/routes/events.js +43 -0
  60. package/dist/server/routes/filesystem.js +43 -0
  61. package/dist/server/routes/github-plugin.js +215 -0
  62. package/dist/server/routes/github-webhook.js +32 -0
  63. package/dist/server/routes/meta.js +47 -0
  64. package/dist/server/routes/plugin.js +52 -0
  65. package/dist/server/routes/storage.js +52 -0
  66. package/dist/server/routes/workspaces.js +89 -0
  67. package/dist/server/routes/worktrees.js +156 -0
  68. package/dist/server/tls.js +224 -0
  69. package/dist/storage/instance-store.js +56 -0
  70. package/dist/ui/__tests__/remote-ui.test.js +46 -0
  71. package/dist/ui/remote-ui.js +462 -0
  72. package/dist/workspaces/git-worktrees.js +199 -0
  73. package/dist/workspaces/instance-events.js +180 -0
  74. package/dist/workspaces/manager.js +375 -0
  75. package/dist/workspaces/opencode-auth.js +16 -0
  76. package/dist/workspaces/runtime.js +346 -0
  77. package/dist/workspaces/worktree-map.js +116 -0
  78. package/package.json +49 -0
  79. package/public/apple-touch-icon-180x180.png +0 -0
  80. package/public/assets/CodeNomad-Icon-bmTWNPXy.png +0 -0
  81. package/public/assets/abap-BdImnpbu.js +1 -0
  82. package/public/assets/actionscript-3-CfeIJUat.js +1 -0
  83. package/public/assets/ada-bCR0ucgS.js +1 -0
  84. package/public/assets/andromeeda-C-Jbm3Hp.js +1 -0
  85. package/public/assets/angular-html-CU67Zn6k.js +1 -0
  86. package/public/assets/angular-ts-BwZT4LLn.js +1 -0
  87. package/public/assets/apache-Pmp26Uib.js +1 -0
  88. package/public/assets/apex-DhZLUxFE.js +1 -0
  89. package/public/assets/apl-dKokRX4l.js +1 -0
  90. package/public/assets/applescript-Co6uUVPk.js +1 -0
  91. package/public/assets/ara-BRHolxvo.js +1 -0
  92. package/public/assets/asciidoc-Dv7Oe6Be.js +1 -0
  93. package/public/assets/asm-D_Q5rh1f.js +1 -0
  94. package/public/assets/astro-CbQHKStN.js +1 -0
  95. package/public/assets/aurora-x-D-2ljcwZ.js +1 -0
  96. package/public/assets/awk-DMzUqQB5.js +1 -0
  97. package/public/assets/ayu-dark-Cv9koXgw.js +1 -0
  98. package/public/assets/ballerina-BFfxhgS-.js +1 -0
  99. package/public/assets/bat-BkioyH1T.js +1 -0
  100. package/public/assets/beancount-k_qm7-4y.js +1 -0
  101. package/public/assets/berry-D08WgyRC.js +1 -0
  102. package/public/assets/bibtex-CHM0blh-.js +1 -0
  103. package/public/assets/bicep-Bmn6On1c.js +1 -0
  104. package/public/assets/blade-DVc8C-J4.js +1 -0
  105. package/public/assets/bsl-BO_Y6i37.js +1 -0
  106. package/public/assets/c-BIGW1oBm.js +1 -0
  107. package/public/assets/cadence-Bv_4Rxtq.js +1 -0
  108. package/public/assets/cairo-KRGpt6FW.js +1 -0
  109. package/public/assets/catppuccin-frappe-DFWUc33u.js +1 -0
  110. package/public/assets/catppuccin-latte-C9dUb6Cb.js +1 -0
  111. package/public/assets/catppuccin-macchiato-DQyhUUbL.js +1 -0
  112. package/public/assets/catppuccin-mocha-D87Tk5Gz.js +1 -0
  113. package/public/assets/clarity-D53aC0YG.js +1 -0
  114. package/public/assets/clojure-P80f7IUj.js +1 -0
  115. package/public/assets/cmake-D1j8_8rp.js +1 -0
  116. package/public/assets/cobol-nwyudZeR.js +1 -0
  117. package/public/assets/codeowners-Bp6g37R7.js +1 -0
  118. package/public/assets/codeql-DsOJ9woJ.js +1 -0
  119. package/public/assets/coffee-Ch7k5sss.js +1 -0
  120. package/public/assets/common-lisp-Cg-RD9OK.js +1 -0
  121. package/public/assets/coq-DkFqJrB1.js +1 -0
  122. package/public/assets/core-BSTVzpXI.js +1 -0
  123. package/public/assets/cpp-CofmeUqb.js +1 -0
  124. package/public/assets/crystal-tKQVLTB8.js +1 -0
  125. package/public/assets/csharp-CX12Zw3r.js +1 -0
  126. package/public/assets/css-DPfMkruS.js +1 -0
  127. package/public/assets/csv-fuZLfV_i.js +1 -0
  128. package/public/assets/cue-D82EKSYY.js +1 -0
  129. package/public/assets/cypher-COkxafJQ.js +1 -0
  130. package/public/assets/d-85-TOEBH.js +1 -0
  131. package/public/assets/dark-plus-eOWES_5F.js +1 -0
  132. package/public/assets/dart-CF10PKvl.js +1 -0
  133. package/public/assets/dax-CEL-wOlO.js +1 -0
  134. package/public/assets/desktop-BmXAJ9_W.js +1 -0
  135. package/public/assets/diff-D97Zzqfu.js +1 -0
  136. package/public/assets/docker-BcOcwvcX.js +1 -0
  137. package/public/assets/dotenv-Da5cRb03.js +1 -0
  138. package/public/assets/dracula-BzJJZx-M.js +1 -0
  139. package/public/assets/dracula-soft-BXkSAIEj.js +1 -0
  140. package/public/assets/dream-maker-BtqSS_iP.js +1 -0
  141. package/public/assets/edge-BkV0erSs.js +1 -0
  142. package/public/assets/elixir-CDX3lj18.js +1 -0
  143. package/public/assets/elm-DbKCFpqz.js +1 -0
  144. package/public/assets/emacs-lisp-C9XAeP06.js +1 -0
  145. package/public/assets/erb-BOJIQeun.js +1 -0
  146. package/public/assets/erlang-DsQrWhSR.js +1 -0
  147. package/public/assets/everforest-dark-BgDCqdQA.js +1 -0
  148. package/public/assets/everforest-light-C8M2exoo.js +1 -0
  149. package/public/assets/fennel-BYunw83y.js +1 -0
  150. package/public/assets/fish-BvzEVeQv.js +1 -0
  151. package/public/assets/fluent-C4IJs8-o.js +1 -0
  152. package/public/assets/fortran-fixed-form-BZjJHVRy.js +1 -0
  153. package/public/assets/fortran-free-form-D22FLkUw.js +1 -0
  154. package/public/assets/fsharp-CXgrBDvD.js +1 -0
  155. package/public/assets/gdresource-B7Tvp0Sc.js +1 -0
  156. package/public/assets/gdscript-DTMYz4Jt.js +1 -0
  157. package/public/assets/gdshader-DkwncUOv.js +1 -0
  158. package/public/assets/genie-D0YGMca9.js +1 -0
  159. package/public/assets/gherkin-DyxjwDmM.js +1 -0
  160. package/public/assets/git-commit-F4YmCXRG.js +1 -0
  161. package/public/assets/git-rebase-r7XF79zn.js +1 -0
  162. package/public/assets/github-dark-DHJKELXO.js +1 -0
  163. package/public/assets/github-dark-default-Cuk6v7N8.js +1 -0
  164. package/public/assets/github-dark-dimmed-DH5Ifo-i.js +1 -0
  165. package/public/assets/github-dark-high-contrast-E3gJ1_iC.js +1 -0
  166. package/public/assets/github-light-DAi9KRSo.js +1 -0
  167. package/public/assets/github-light-default-D7oLnXFd.js +1 -0
  168. package/public/assets/github-light-high-contrast-BfjtVDDH.js +1 -0
  169. package/public/assets/gleam-BspZqrRM.js +1 -0
  170. package/public/assets/glimmer-js-Rg0-pVw9.js +1 -0
  171. package/public/assets/glimmer-ts-U6CK756n.js +1 -0
  172. package/public/assets/glsl-DplSGwfg.js +1 -0
  173. package/public/assets/gnuplot-DdkO51Og.js +1 -0
  174. package/public/assets/go-Dn2_MT6a.js +1 -0
  175. package/public/assets/graphql-ChdNCCLP.js +1 -0
  176. package/public/assets/groovy-gcz8RCvz.js +1 -0
  177. package/public/assets/gruvbox-dark-hard-CFHQjOhq.js +1 -0
  178. package/public/assets/gruvbox-dark-medium-GsRaNv29.js +1 -0
  179. package/public/assets/gruvbox-dark-soft-CVdnzihN.js +1 -0
  180. package/public/assets/gruvbox-light-hard-CH1njM8p.js +1 -0
  181. package/public/assets/gruvbox-light-medium-DRw_LuNl.js +1 -0
  182. package/public/assets/gruvbox-light-soft-hJgmCMqR.js +1 -0
  183. package/public/assets/hack-CaT9iCJl.js +1 -0
  184. package/public/assets/haml-B8DHNrY2.js +1 -0
  185. package/public/assets/handlebars-BL8al0AC.js +1 -0
  186. package/public/assets/haskell-Df6bDoY_.js +1 -0
  187. package/public/assets/haxe-CzTSHFRz.js +1 -0
  188. package/public/assets/hcl-BWvSN4gD.js +1 -0
  189. package/public/assets/hjson-D5-asLiD.js +1 -0
  190. package/public/assets/hlsl-D3lLCCz7.js +1 -0
  191. package/public/assets/houston-DnULxvSX.js +1 -0
  192. package/public/assets/html-GMplVEZG.js +1 -0
  193. package/public/assets/html-derivative-BFtXZ54Q.js +1 -0
  194. package/public/assets/http-jrhK8wxY.js +1 -0
  195. package/public/assets/hurl-irOxFIW8.js +1 -0
  196. package/public/assets/hxml-Bvhsp5Yf.js +1 -0
  197. package/public/assets/hy-DFXneXwc.js +1 -0
  198. package/public/assets/imba-DGztddWO.js +1 -0
  199. package/public/assets/index-D4PT0yE4.js +1 -0
  200. package/public/assets/index-DN20ggb1.js +1 -0
  201. package/public/assets/index-DdQ7zIzB.js +1 -0
  202. package/public/assets/index-Dl-rJJuP.js +1 -0
  203. package/public/assets/index-Dlo2gDiy.css +1 -0
  204. package/public/assets/ini-BEwlwnbL.js +1 -0
  205. package/public/assets/java-CylS5w8V.js +1 -0
  206. package/public/assets/javascript-wDzz0qaB.js +1 -0
  207. package/public/assets/jinja-4LBKfQ-Z.js +1 -0
  208. package/public/assets/jison-wvAkD_A8.js +1 -0
  209. package/public/assets/json-Cp-IABpG.js +1 -0
  210. package/public/assets/json5-C9tS-k6U.js +1 -0
  211. package/public/assets/jsonc-Des-eS-w.js +1 -0
  212. package/public/assets/jsonl-DcaNXYhu.js +1 -0
  213. package/public/assets/jsonnet-DFQXde-d.js +1 -0
  214. package/public/assets/jssm-C2t-YnRu.js +1 -0
  215. package/public/assets/jsx-g9-lgVsj.js +1 -0
  216. package/public/assets/julia-C8NyazO9.js +1 -0
  217. package/public/assets/kanagawa-dragon-CkXjmgJE.js +1 -0
  218. package/public/assets/kanagawa-lotus-CfQXZHmo.js +1 -0
  219. package/public/assets/kanagawa-wave-DWedfzmr.js +1 -0
  220. package/public/assets/kdl-DV7GczEv.js +1 -0
  221. package/public/assets/kotlin-BdnUsdx6.js +1 -0
  222. package/public/assets/kusto-BvAqAH-y.js +1 -0
  223. package/public/assets/laserwave-DUszq2jm.js +1 -0
  224. package/public/assets/latex-BUKiar2Z.js +1 -0
  225. package/public/assets/lean-DP1Csr6i.js +1 -0
  226. package/public/assets/less-B1dDrJ26.js +1 -0
  227. package/public/assets/light-plus-B7mTdjB0.js +1 -0
  228. package/public/assets/liquid-DYVedYrR.js +1 -0
  229. package/public/assets/llvm-BtvRca6l.js +1 -0
  230. package/public/assets/loading-CmEVQgyj.css +1 -0
  231. package/public/assets/loading-DgqIiz-T.js +1 -0
  232. package/public/assets/log-2UxHyX5q.js +1 -0
  233. package/public/assets/logo-BtOb2qkB.js +1 -0
  234. package/public/assets/lua-BbnMAYS6.js +1 -0
  235. package/public/assets/luau-CXu1NL6O.js +1 -0
  236. package/public/assets/main-CSlDZj4f.js +188 -0
  237. package/public/assets/main-HAZkIolJ.css +19 -0
  238. package/public/assets/make-CHLpvVh8.js +1 -0
  239. package/public/assets/markdown-Cvjx9yec.js +1 -0
  240. package/public/assets/marko-CPi9NSCl.js +1 -0
  241. package/public/assets/material-theme-D5KoaKCx.js +1 -0
  242. package/public/assets/material-theme-darker-BfHTSMKl.js +1 -0
  243. package/public/assets/material-theme-lighter-B0m2ddpp.js +1 -0
  244. package/public/assets/material-theme-ocean-CyktbL80.js +1 -0
  245. package/public/assets/material-theme-palenight-Csfq5Kiy.js +1 -0
  246. package/public/assets/matlab-D7o27uSR.js +1 -0
  247. package/public/assets/mdc-DUICxH0z.js +1 -0
  248. package/public/assets/mdx-Cmh6b_Ma.js +1 -0
  249. package/public/assets/mermaid-DKYwYmdq.js +1 -0
  250. package/public/assets/min-dark-CafNBF8u.js +1 -0
  251. package/public/assets/min-light-CTRr51gU.js +1 -0
  252. package/public/assets/mipsasm-CKIfxQSi.js +1 -0
  253. package/public/assets/mojo-1DNp92w6.js +1 -0
  254. package/public/assets/monokai-D4h5O-jR.js +1 -0
  255. package/public/assets/move-Bu9oaDYs.js +1 -0
  256. package/public/assets/narrat-DRg8JJMk.js +1 -0
  257. package/public/assets/nextflow-CUEJCptM.js +1 -0
  258. package/public/assets/nginx-DknmC5AR.js +1 -0
  259. package/public/assets/night-owl-C39BiMTA.js +1 -0
  260. package/public/assets/nim-CVrawwO9.js +1 -0
  261. package/public/assets/nix-BbRYJGeE.js +1 -0
  262. package/public/assets/nord-Ddv68eIx.js +1 -0
  263. package/public/assets/nushell-C-sUppwS.js +1 -0
  264. package/public/assets/objective-c-DXmwc3jG.js +1 -0
  265. package/public/assets/objective-cpp-CLxacb5B.js +1 -0
  266. package/public/assets/ocaml-C0hk2d4L.js +1 -0
  267. package/public/assets/one-dark-pro-DVMEJ2y_.js +1 -0
  268. package/public/assets/one-light-PoHY5YXO.js +1 -0
  269. package/public/assets/pascal-D93ZcfNL.js +1 -0
  270. package/public/assets/perl-C0TMdlhV.js +1 -0
  271. package/public/assets/php-CDn_0X-4.js +1 -0
  272. package/public/assets/pkl-u5AG7uiY.js +1 -0
  273. package/public/assets/plastic-3e1v2bzS.js +1 -0
  274. package/public/assets/plsql-ChMvpjG-.js +1 -0
  275. package/public/assets/po-BTJTHyun.js +1 -0
  276. package/public/assets/poimandres-CS3Unz2-.js +1 -0
  277. package/public/assets/polar-C0HS_06l.js +1 -0
  278. package/public/assets/postcss-CXtECtnM.js +1 -0
  279. package/public/assets/powerquery-CEu0bR-o.js +1 -0
  280. package/public/assets/powershell-Dpen1YoG.js +1 -0
  281. package/public/assets/prisma-Dd19v3D-.js +1 -0
  282. package/public/assets/prolog-CbFg5uaA.js +1 -0
  283. package/public/assets/proto-DyJlTyXw.js +1 -0
  284. package/public/assets/pug-CGlum2m_.js +1 -0
  285. package/public/assets/puppet-BMWR74SV.js +1 -0
  286. package/public/assets/purescript-CklMAg4u.js +1 -0
  287. package/public/assets/python-B6aJPvgy.js +1 -0
  288. package/public/assets/qml-3beO22l8.js +1 -0
  289. package/public/assets/qmldir-C8lEn-DE.js +1 -0
  290. package/public/assets/qss-IeuSbFQv.js +1 -0
  291. package/public/assets/r-DiinP2Uv.js +1 -0
  292. package/public/assets/racket-BqYA7rlc.js +1 -0
  293. package/public/assets/raku-DXvB9xmW.js +1 -0
  294. package/public/assets/razor-WgofotgN.js +1 -0
  295. package/public/assets/red-bN70gL4F.js +1 -0
  296. package/public/assets/reg-C-SQnVFl.js +1 -0
  297. package/public/assets/regexp-CDVJQ6XC.js +1 -0
  298. package/public/assets/rel-C3B-1QV4.js +1 -0
  299. package/public/assets/riscv-BM1_JUlF.js +1 -0
  300. package/public/assets/rose-pine-BHrmToEH.js +1 -0
  301. package/public/assets/rose-pine-dawn-CnK8MTSM.js +1 -0
  302. package/public/assets/rose-pine-moon-NleAzG8P.js +1 -0
  303. package/public/assets/rosmsg-BJDFO7_C.js +1 -0
  304. package/public/assets/rst-B0xPkSld.js +1 -0
  305. package/public/assets/ruby-BvKwtOVI.js +1 -0
  306. package/public/assets/rust-B1yitclQ.js +1 -0
  307. package/public/assets/sas-cz2c8ADy.js +1 -0
  308. package/public/assets/sass-Cj5Yp3dK.js +1 -0
  309. package/public/assets/scala-C151Ov-r.js +1 -0
  310. package/public/assets/scheme-C98Dy4si.js +1 -0
  311. package/public/assets/scss-OYdSNvt2.js +1 -0
  312. package/public/assets/sdbl-DVxCFoDh.js +1 -0
  313. package/public/assets/shaderlab-Dg9Lc6iA.js +1 -0
  314. package/public/assets/shellscript-Yzrsuije.js +1 -0
  315. package/public/assets/shellsession-BADoaaVG.js +1 -0
  316. package/public/assets/slack-dark-BthQWCQV.js +1 -0
  317. package/public/assets/slack-ochin-DqwNpetd.js +1 -0
  318. package/public/assets/smalltalk-BERRCDM3.js +1 -0
  319. package/public/assets/snazzy-light-Bw305WKR.js +1 -0
  320. package/public/assets/solarized-dark-DXbdFlpD.js +1 -0
  321. package/public/assets/solarized-light-L9t79GZl.js +1 -0
  322. package/public/assets/solidity-BbcW6ACK.js +1 -0
  323. package/public/assets/soy-Brmx7dQM.js +1 -0
  324. package/public/assets/sparql-rVzFXLq3.js +1 -0
  325. package/public/assets/splunk-BtCnVYZw.js +1 -0
  326. package/public/assets/sql-BLtJtn59.js +1 -0
  327. package/public/assets/ssh-config-_ykCGR6B.js +1 -0
  328. package/public/assets/stata-BH5u7GGu.js +1 -0
  329. package/public/assets/stylus-BEDo0Tqx.js +1 -0
  330. package/public/assets/svelte-3Dk4HxPD.js +1 -0
  331. package/public/assets/swift-Dg5xB15N.js +1 -0
  332. package/public/assets/synthwave-84-CbfX1IO0.js +1 -0
  333. package/public/assets/system-verilog-CnnmHF94.js +1 -0
  334. package/public/assets/systemd-4A_iFExJ.js +1 -0
  335. package/public/assets/talonscript-CkByrt1z.js +1 -0
  336. package/public/assets/tasl-QIJgUcNo.js +1 -0
  337. package/public/assets/tcl-dwOrl1Do.js +1 -0
  338. package/public/assets/templ-W15q3VgB.js +1 -0
  339. package/public/assets/terraform-BETggiCN.js +1 -0
  340. package/public/assets/tex-Cppo0RY3.js +1 -0
  341. package/public/assets/tokyo-night-hegEt444.js +1 -0
  342. package/public/assets/toml-vGWfd6FD.js +1 -0
  343. package/public/assets/ts-tags-zn1MmPIZ.js +1 -0
  344. package/public/assets/tsv-B_m7g4N7.js +1 -0
  345. package/public/assets/tsx-COt5Ahok.js +1 -0
  346. package/public/assets/turtle-BsS91CYL.js +1 -0
  347. package/public/assets/twig-CO9l9SDP.js +1 -0
  348. package/public/assets/typescript-BPQ3VLAy.js +1 -0
  349. package/public/assets/typespec-Df68jz8_.js +1 -0
  350. package/public/assets/typst-DHCkPAjA.js +1 -0
  351. package/public/assets/v-BcVCzyr7.js +1 -0
  352. package/public/assets/vala-CsfeWuGM.js +1 -0
  353. package/public/assets/vb-D17OF-Vu.js +1 -0
  354. package/public/assets/verilog-BQ8w6xss.js +1 -0
  355. package/public/assets/vesper-DU1UobuO.js +1 -0
  356. package/public/assets/vhdl-CeAyd5Ju.js +1 -0
  357. package/public/assets/viml-CJc9bBzg.js +1 -0
  358. package/public/assets/vitesse-black-Bkuqu6BP.js +1 -0
  359. package/public/assets/vitesse-dark-D0r3Knsf.js +1 -0
  360. package/public/assets/vitesse-light-CVO1_9PV.js +1 -0
  361. package/public/assets/vue-CCoi5OLL.js +1 -0
  362. package/public/assets/vue-html-DAAvJJDi.js +1 -0
  363. package/public/assets/vue-vine-_Ih-lPRR.js +1 -0
  364. package/public/assets/vyper-CDx5xZoG.js +1 -0
  365. package/public/assets/wasm-CG6Dc4jp.js +1 -0
  366. package/public/assets/wasm-MzD3tlZU.js +1 -0
  367. package/public/assets/wenyan-BV7otONQ.js +1 -0
  368. package/public/assets/wgsl-Dx-B1_4e.js +1 -0
  369. package/public/assets/wikitext-BhOHFoWU.js +1 -0
  370. package/public/assets/wit-5i3qLPDT.js +1 -0
  371. package/public/assets/wolfram-lXgVvXCa.js +1 -0
  372. package/public/assets/xml-sdJ4AIDG.js +1 -0
  373. package/public/assets/xsl-CtQFsRM5.js +1 -0
  374. package/public/assets/yaml-Buea-lGh.js +1 -0
  375. package/public/assets/zenscript-DVFEvuxE.js +1 -0
  376. package/public/assets/zig-VOosw3JB.js +1 -0
  377. package/public/favicon.ico +0 -0
  378. package/public/index.html +38 -0
  379. package/public/loading.html +28 -0
  380. package/public/logo.png +0 -0
  381. package/public/manifest.webmanifest +1 -0
  382. package/public/maskable-icon-512x512.png +0 -0
  383. package/public/monaco/vs/base/browser/ui/codicons/codicon/codicon.ttf +0 -0
  384. package/public/monaco/vs/base/worker/workerMain.js +31 -0
  385. package/public/monaco/vs/basic-languages/cpp/cpp.js +10 -0
  386. package/public/monaco/vs/basic-languages/kotlin/kotlin.js +10 -0
  387. package/public/monaco/vs/basic-languages/markdown/markdown.js +10 -0
  388. package/public/monaco/vs/basic-languages/python/python.js +10 -0
  389. package/public/monaco/vs/editor/editor.main.css +8 -0
  390. package/public/monaco/vs/editor/editor.main.js +798 -0
  391. package/public/monaco/vs/language/css/cssMode.js +13 -0
  392. package/public/monaco/vs/language/css/cssWorker.js +77 -0
  393. package/public/monaco/vs/language/html/htmlMode.js +13 -0
  394. package/public/monaco/vs/language/html/htmlWorker.js +454 -0
  395. package/public/monaco/vs/language/json/jsonMode.js +19 -0
  396. package/public/monaco/vs/language/json/jsonWorker.js +42 -0
  397. package/public/monaco/vs/language/typescript/tsMode.js +20 -0
  398. package/public/monaco/vs/language/typescript/tsWorker.js +51328 -0
  399. package/public/monaco/vs/loader.js +11 -0
  400. package/public/monaco.worker.js +7 -0
  401. package/public/pwa-192x192.png +0 -0
  402. package/public/pwa-512x512.png +0 -0
  403. package/public/pwa-64x64.png +0 -0
  404. package/public/registerSW.js +1 -0
  405. package/public/sw.js +1 -0
  406. package/public/ui-version.json +3 -0
  407. package/public/workbox-60d14903.js +1 -0
  408. package/scripts/copy-auth-pages.mjs +22 -0
  409. package/scripts/copy-opencode-config.mjs +61 -0
  410. package/scripts/copy-ui-dist.mjs +21 -0
  411. package/src/api-types.ts +326 -0
  412. package/src/auth/auth-store.ts +175 -0
  413. package/src/auth/http-auth.ts +38 -0
  414. package/src/auth/manager.ts +163 -0
  415. package/src/auth/password-hash.ts +49 -0
  416. package/src/auth/session-manager.ts +23 -0
  417. package/src/auth/token-manager.ts +32 -0
  418. package/src/background-processes/manager.ts +519 -0
  419. package/src/bin.ts +29 -0
  420. package/src/config/binaries.ts +192 -0
  421. package/src/config/location.ts +78 -0
  422. package/src/config/schema.ts +104 -0
  423. package/src/config/store.ts +244 -0
  424. package/src/events/bus.ts +45 -0
  425. package/src/filesystem/__tests__/search-cache.test.ts +61 -0
  426. package/src/filesystem/browser.ts +353 -0
  427. package/src/filesystem/search-cache.ts +66 -0
  428. package/src/filesystem/search.ts +184 -0
  429. package/src/index.ts +540 -0
  430. package/src/launcher.ts +177 -0
  431. package/src/loader.ts +21 -0
  432. package/src/logger.ts +133 -0
  433. package/src/opencode-config.ts +31 -0
  434. package/src/plugins/channel.ts +55 -0
  435. package/src/plugins/handlers.ts +36 -0
  436. package/src/releases/dev-release-monitor.ts +118 -0
  437. package/src/releases/release-monitor.ts +149 -0
  438. package/src/server/http-server.ts +693 -0
  439. package/src/server/network-addresses.ts +75 -0
  440. package/src/server/routes/auth-pages/login.html +134 -0
  441. package/src/server/routes/auth-pages/token.html +93 -0
  442. package/src/server/routes/auth.ts +164 -0
  443. package/src/server/routes/background-processes.ts +85 -0
  444. package/src/server/routes/config.ts +76 -0
  445. package/src/server/routes/events.ts +61 -0
  446. package/src/server/routes/filesystem.ts +54 -0
  447. package/src/server/routes/meta.ts +58 -0
  448. package/src/server/routes/plugin.ts +75 -0
  449. package/src/server/routes/storage.ts +66 -0
  450. package/src/server/routes/workspaces.ts +113 -0
  451. package/src/server/routes/worktrees.ts +195 -0
  452. package/src/server/tls.ts +283 -0
  453. package/src/storage/instance-store.ts +64 -0
  454. package/src/ui/__tests__/remote-ui.test.ts +58 -0
  455. package/src/ui/remote-ui.ts +571 -0
  456. package/src/workspaces/git-worktrees.ts +241 -0
  457. package/src/workspaces/instance-events.ts +226 -0
  458. package/src/workspaces/manager.ts +493 -0
  459. package/src/workspaces/opencode-auth.ts +22 -0
  460. package/src/workspaces/runtime.ts +428 -0
  461. package/src/workspaces/worktree-map.ts +129 -0
  462. package/tsconfig.json +17 -0
package/src/index.ts ADDED
@@ -0,0 +1,540 @@
1
+ /**
2
+ * CLI entry point.
3
+ * For now this only wires the typed modules together; actual command handling comes later.
4
+ */
5
+ import { Command, InvalidArgumentError, Option } from "commander"
6
+ import path from "path"
7
+ import { fileURLToPath } from "url"
8
+ import { createRequire } from "module"
9
+ import { createHttpServer } from "./server/http-server"
10
+ import { WorkspaceManager } from "./workspaces/manager"
11
+ import { ConfigStore } from "./config/store"
12
+ import { resolveConfigLocation } from "./config/location"
13
+ import { BinaryRegistry } from "./config/binaries"
14
+ import { FileSystemBrowser } from "./filesystem/browser"
15
+ import { EventBus } from "./events/bus"
16
+ import { ServerMeta } from "./api-types"
17
+ import { InstanceStore } from "./storage/instance-store"
18
+ import { InstanceEventBridge } from "./workspaces/instance-events"
19
+ import { createLogger } from "./logger"
20
+ import { launchInBrowser } from "./launcher"
21
+ import { resolveUi } from "./ui/remote-ui"
22
+ import { AuthManager, BOOTSTRAP_TOKEN_STDOUT_PREFIX, DEFAULT_AUTH_USERNAME } from "./auth/manager"
23
+ import { resolveHttpsOptions } from "./server/tls"
24
+ import { resolveNetworkAddresses } from "./server/network-addresses"
25
+ import { startDevReleaseMonitor } from "./releases/dev-release-monitor"
26
+
27
+ const require = createRequire(import.meta.url)
28
+
29
+ const packageJson = require("../package.json") as { version: string }
30
+ const __filename = fileURLToPath(import.meta.url)
31
+ const __dirname = path.dirname(__filename)
32
+ const DEFAULT_UI_STATIC_DIR = path.resolve(__dirname, "../public")
33
+
34
+ interface CliOptions {
35
+ host: string
36
+ https: boolean
37
+ http: boolean
38
+ httpsPort: number
39
+ httpPort: number
40
+ tlsKeyPath?: string
41
+ tlsCertPath?: string
42
+ tlsCaPath?: string
43
+ tlsSANs?: string
44
+ rootDir: string
45
+ configPath: string
46
+ unrestrictedRoot: boolean
47
+ logLevel?: string
48
+ logDestination?: string
49
+ uiStaticDir: string
50
+ uiDevServer?: string
51
+ uiAutoUpdate: boolean
52
+ uiNoUpdate: boolean
53
+ uiManifestUrl?: string
54
+ launch: boolean
55
+ authUsername: string
56
+ authPassword?: string
57
+ generateToken: boolean
58
+ dangerouslySkipAuth: boolean
59
+ }
60
+
61
+ const DEFAULT_HOST = "127.0.0.1"
62
+ const DEFAULT_CONFIG_PATH = "~/.config/codenomad/config.json"
63
+ const DEFAULT_HTTPS_PORT = 9898
64
+ const DEFAULT_HTTP_PORT = 9899
65
+
66
+ function parseCliOptions(argv: string[]): CliOptions {
67
+ const program = new Command()
68
+ .name("codenomad")
69
+ .description("CodeNomad CLI server")
70
+ .version(packageJson.version, "-v, --version", "Show the CLI version")
71
+ .addOption(new Option("--host <host>", "Host interface to bind").env("CLI_HOST").default(DEFAULT_HOST))
72
+ .addOption(new Option("--https <enabled>", "Enable HTTPS listener (true|false)").env("CLI_HTTPS").default("true"))
73
+ .addOption(new Option("--http <enabled>", "Enable HTTP listener (true|false)").env("CLI_HTTP").default("false"))
74
+ .addOption(new Option("--https-port <number>", "HTTPS port (0 for auto)").env("CLI_HTTPS_PORT").default(DEFAULT_HTTPS_PORT).argParser(parsePort))
75
+ .addOption(new Option("--http-port <number>", "HTTP port (0 for auto)").env("CLI_HTTP_PORT").default(DEFAULT_HTTP_PORT).argParser(parsePort))
76
+ .addOption(new Option("--tls-key <path>", "TLS private key (PEM)").env("CLI_TLS_KEY"))
77
+ .addOption(new Option("--tls-cert <path>", "TLS certificate (PEM)").env("CLI_TLS_CERT"))
78
+ .addOption(new Option("--tls-ca <path>", "TLS CA chain (PEM)").env("CLI_TLS_CA"))
79
+ .addOption(new Option("--tlsSANs <list>", "Additional TLS SANs (comma-separated)").env("CLI_TLS_SANS"))
80
+ .addOption(
81
+ new Option("--workspace-root <path>", "Workspace root directory").env("CLI_WORKSPACE_ROOT").default(process.cwd()),
82
+ )
83
+ .addOption(new Option("--root <path>").env("CLI_ROOT").hideHelp(true))
84
+ .addOption(new Option("--unrestricted-root", "Allow browsing the full filesystem").env("CLI_UNRESTRICTED_ROOT").default(false))
85
+ .addOption(new Option("--config <path>", "Path to the config file").env("CLI_CONFIG").default(DEFAULT_CONFIG_PATH))
86
+ .addOption(new Option("--log-level <level>", "Log level (trace|debug|info|warn|error)").env("CLI_LOG_LEVEL"))
87
+ .addOption(new Option("--log-destination <path>", "Log destination file (defaults to stdout)").env("CLI_LOG_DESTINATION"))
88
+ .addOption(
89
+ new Option("--ui-dir <path>", "Directory containing the built UI bundle").env("CLI_UI_DIR").default(DEFAULT_UI_STATIC_DIR),
90
+ )
91
+ .addOption(new Option("--ui-dev-server <url>", "Proxy UI requests to a running dev server").env("CLI_UI_DEV_SERVER"))
92
+ .addOption(new Option("--ui-no-update", "Disable remote UI updates").env("CLI_UI_NO_UPDATE").default(false))
93
+ .addOption(new Option("--ui-auto-update <enabled>", "Enable remote UI updates (true|false)").env("CLI_UI_AUTO_UPDATE").default("true"))
94
+ .addOption(new Option("--ui-manifest-url <url>", "Remote UI manifest URL").env("CLI_UI_MANIFEST_URL"))
95
+ .addOption(new Option("--launch", "Launch the UI in a browser after start").env("CLI_LAUNCH").default(false))
96
+ .addOption(
97
+ new Option("--username <username>", "Username for server authentication")
98
+ .env("CODENOMAD_SERVER_USERNAME")
99
+ .default(DEFAULT_AUTH_USERNAME),
100
+ )
101
+ .addOption(new Option("--password <password>", "Password for server authentication").env("CODENOMAD_SERVER_PASSWORD"))
102
+ .addOption(
103
+ new Option("--generate-token", "Emit a one-time bootstrap token for desktop")
104
+ .env("CODENOMAD_GENERATE_TOKEN")
105
+ .default(false),
106
+ )
107
+ .addOption(
108
+ new Option(
109
+ "--dangerously-skip-auth",
110
+ "Disable CodeNomad's internal auth. Use only behind a trusted perimeter (SSO/VPN/etc).",
111
+ )
112
+ .env("CODENOMAD_SKIP_AUTH")
113
+ .default(false),
114
+ )
115
+
116
+ program.parse(argv, { from: "user" })
117
+ const parsed = program.opts<{
118
+ host: string
119
+ https?: string
120
+ http?: string
121
+ httpsPort: number
122
+ httpPort: number
123
+ tlsKey?: string
124
+ tlsCert?: string
125
+ tlsCa?: string
126
+ tlsSANs?: string
127
+ workspaceRoot?: string
128
+ root?: string
129
+ unrestrictedRoot?: boolean
130
+ config: string
131
+ logLevel?: string
132
+ logDestination?: string
133
+ uiDir: string
134
+ uiDevServer?: string
135
+ uiNoUpdate?: boolean
136
+ uiAutoUpdate?: string
137
+ uiManifestUrl?: string
138
+ launch?: boolean
139
+ username: string
140
+ password?: string
141
+ generateToken?: boolean
142
+ dangerouslySkipAuth?: boolean
143
+ }>()
144
+
145
+ const parseBooleanEnv = (value: string | undefined): boolean => {
146
+ const normalized = (value ?? "").trim().toLowerCase()
147
+ return normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "y" || normalized === "on"
148
+ }
149
+
150
+ const resolvedRoot = parsed.workspaceRoot ?? parsed.root ?? process.cwd()
151
+
152
+ const normalizedHost = resolveHost(parsed.host)
153
+
154
+ const autoUpdateString = (parsed.uiAutoUpdate ?? "true").trim().toLowerCase()
155
+ const uiAutoUpdate = autoUpdateString === "1" || autoUpdateString === "true" || autoUpdateString === "yes"
156
+
157
+ const httpsEnabled = parseBooleanEnv(parsed.https)
158
+ const httpEnabled = parseBooleanEnv(parsed.http)
159
+
160
+ if (!httpsEnabled && !httpEnabled) {
161
+ throw new InvalidArgumentError("At least one listener must be enabled (--https or --http)")
162
+ }
163
+
164
+ return {
165
+ host: normalizedHost,
166
+ https: httpsEnabled,
167
+ http: httpEnabled,
168
+ httpsPort: parsed.httpsPort,
169
+ httpPort: parsed.httpPort,
170
+ tlsKeyPath: parsed.tlsKey,
171
+ tlsCertPath: parsed.tlsCert,
172
+ tlsCaPath: parsed.tlsCa,
173
+ tlsSANs: parsed.tlsSANs,
174
+ rootDir: resolvedRoot,
175
+ configPath: parsed.config,
176
+ unrestrictedRoot: Boolean(parsed.unrestrictedRoot),
177
+ logLevel: parsed.logLevel,
178
+ logDestination: parsed.logDestination,
179
+ uiStaticDir: parsed.uiDir,
180
+ uiDevServer: parsed.uiDevServer,
181
+ uiAutoUpdate,
182
+ uiNoUpdate: Boolean(parsed.uiNoUpdate),
183
+ uiManifestUrl: parsed.uiManifestUrl,
184
+ launch: Boolean(parsed.launch),
185
+ authUsername: parsed.username,
186
+ authPassword: parsed.password,
187
+ generateToken: Boolean(parsed.generateToken),
188
+ dangerouslySkipAuth: Boolean(parsed.dangerouslySkipAuth),
189
+ }
190
+ }
191
+
192
+ function parsePort(input: string): number {
193
+ const value = Number(input)
194
+ if (!Number.isInteger(value) || value < 0 || value > 65535) {
195
+ throw new InvalidArgumentError("Port must be an integer between 0 and 65535")
196
+ }
197
+ return value
198
+ }
199
+
200
+ function resolveHost(input: string | undefined): string {
201
+ const trimmed = input?.trim()
202
+ if (!trimmed) return DEFAULT_HOST
203
+
204
+ if (trimmed === "0.0.0.0") {
205
+ return "0.0.0.0"
206
+ }
207
+
208
+ if (trimmed === "localhost") {
209
+ return DEFAULT_HOST
210
+ }
211
+
212
+ return trimmed
213
+ }
214
+
215
+ function programHasArg(argv: string[], flag: string): boolean {
216
+ return argv.includes(flag)
217
+ }
218
+
219
+ async function main() {
220
+ const options = parseCliOptions(process.argv.slice(2))
221
+ const logger = createLogger({ level: options.logLevel, destination: options.logDestination, component: "app" })
222
+ const workspaceLogger = logger.child({ component: "workspace" })
223
+ const configLogger = logger.child({ component: "config" })
224
+ const eventLogger = logger.child({ component: "events" })
225
+
226
+ const logOptions = {
227
+ ...options,
228
+ authPassword: options.authPassword ? "[REDACTED]" : undefined,
229
+ }
230
+
231
+ logger.info({ options: logOptions }, "Starting CodeNomad CLI server")
232
+
233
+ if (options.dangerouslySkipAuth) {
234
+ logger.warn(
235
+ "DANGEROUS: internal authentication is disabled (--dangerously-skip-auth / CODENOMAD_SKIP_AUTH).",
236
+ )
237
+ }
238
+
239
+ const eventBus = new EventBus(eventLogger)
240
+
241
+ const isLoopbackHost = (host: string) => host === "127.0.0.1" || host === "::1" || host.startsWith("127.")
242
+
243
+ const configLocation = resolveConfigLocation(options.configPath)
244
+ const configDir = configLocation.baseDir
245
+
246
+ if ((options.tlsKeyPath && !options.tlsCertPath) || (!options.tlsKeyPath && options.tlsCertPath)) {
247
+ throw new InvalidArgumentError("--tls-key and --tls-cert must be provided together")
248
+ }
249
+
250
+ const serverMeta: ServerMeta = {
251
+ localUrl: "http://localhost:0",
252
+ remoteUrl: undefined,
253
+ eventsUrl: `/api/events`,
254
+ host: options.host,
255
+ listeningMode: isLoopbackHost(options.host) ? "local" : "all",
256
+ localPort: 0,
257
+ remotePort: undefined,
258
+ hostLabel: options.host,
259
+ workspaceRoot: options.rootDir,
260
+ addresses: [],
261
+ }
262
+
263
+ const authManager = new AuthManager(
264
+ {
265
+ configPath: configLocation.configYamlPath,
266
+ username: options.authUsername,
267
+ password: options.authPassword,
268
+ generateToken: options.generateToken,
269
+ dangerouslySkipAuth: options.dangerouslySkipAuth,
270
+ },
271
+ logger.child({ component: "auth" }),
272
+ )
273
+
274
+ if (options.generateToken && !options.dangerouslySkipAuth) {
275
+ const token = authManager.issueBootstrapToken()
276
+ if (token) {
277
+ console.log(`${BOOTSTRAP_TOKEN_STDOUT_PREFIX}${token}`)
278
+ }
279
+ }
280
+
281
+ const tlsResolution = resolveHttpsOptions({
282
+ enabled: options.https,
283
+ configDir,
284
+ host: options.host,
285
+ tlsKeyPath: options.tlsKeyPath,
286
+ tlsCertPath: options.tlsCertPath,
287
+ tlsCaPath: options.tlsCaPath,
288
+ tlsSANs: options.tlsSANs,
289
+ logger: logger.child({ component: "tls" }),
290
+ })
291
+
292
+ const nodeExtraCaCertsPath = !options.http ? tlsResolution?.caCertPath : undefined
293
+
294
+ const configStore = new ConfigStore(configLocation, eventBus, configLogger)
295
+
296
+ // Eagerly load config at boot so migrations run immediately
297
+ // (instead of waiting for the first /api/config request).
298
+ try {
299
+ configStore.get()
300
+ } catch (error) {
301
+ configLogger.warn({ err: error }, "Failed to load config at boot; continuing with defaults")
302
+ }
303
+
304
+ const binaryRegistry = new BinaryRegistry(configStore, eventBus, configLogger)
305
+ const workspaceManager = new WorkspaceManager({
306
+ rootDir: options.rootDir,
307
+ configStore,
308
+ binaryRegistry,
309
+ eventBus,
310
+ logger: workspaceLogger,
311
+ getServerBaseUrl: () => serverMeta.localUrl,
312
+ nodeExtraCaCertsPath,
313
+ })
314
+ const fileSystemBrowser = new FileSystemBrowser({ rootDir: options.rootDir, unrestricted: options.unrestrictedRoot })
315
+ const instanceStore = new InstanceStore(configLocation.instancesDir)
316
+ const instanceEventBridge = new InstanceEventBridge({
317
+ workspaceManager,
318
+ eventBus,
319
+ logger: logger.child({ component: "instance-events" }),
320
+ })
321
+
322
+ const uiDirEnvOverride = Boolean(process.env.CLI_UI_DIR)
323
+ const uiDirCliOverride = programHasArg(process.argv.slice(2), "--ui-dir")
324
+ const uiOverrideIsExplicit = uiDirEnvOverride || uiDirCliOverride
325
+ const uiDirOverride = uiOverrideIsExplicit ? options.uiStaticDir : undefined
326
+
327
+ const autoUpdateEnabled = options.uiAutoUpdate && !options.uiNoUpdate
328
+
329
+ const uiResolution = await resolveUi({
330
+ serverVersion: packageJson.version,
331
+ bundledUiDir: DEFAULT_UI_STATIC_DIR,
332
+ autoUpdate: autoUpdateEnabled,
333
+ overrideUiDir: uiDirOverride,
334
+ uiDevServerUrl: options.uiDevServer,
335
+ manifestUrl: options.uiManifestUrl,
336
+ logger: logger.child({ component: "ui" }),
337
+ })
338
+
339
+ serverMeta.serverVersion = packageJson.version
340
+ serverMeta.ui = {
341
+ version: uiResolution.uiVersion,
342
+ source: uiResolution.source,
343
+ }
344
+ serverMeta.support = {
345
+ supported: uiResolution.supported,
346
+ message: uiResolution.message,
347
+ latestServerVersion: uiResolution.latestServerVersion,
348
+ latestServerUrl: uiResolution.latestServerUrl,
349
+ minServerVersion: uiResolution.minServerVersion,
350
+ }
351
+
352
+ const updateChannel = (process.env.CODENOMAD_UPDATE_CHANNEL ?? "").trim().toLowerCase()
353
+ const githubRepo = (process.env.CODENOMAD_GITHUB_REPO ?? "NeuralNomadsAI/CodeNomad").trim()
354
+ const isDevVersion = packageJson.version.includes("-dev.") || packageJson.version.includes("-dev-")
355
+ const enableDevUpdateChecks = updateChannel === "dev" || (updateChannel === "" && isDevVersion)
356
+ const devReleaseMonitor = enableDevUpdateChecks
357
+ ? startDevReleaseMonitor({
358
+ currentVersion: packageJson.version,
359
+ repo: githubRepo,
360
+ logger: logger.child({ component: "updates" }),
361
+ onUpdate: (release) => {
362
+ serverMeta.update = release
363
+ },
364
+ })
365
+ : null
366
+
367
+ if (uiResolution.uiDevServerUrl && options.https) {
368
+ throw new InvalidArgumentError("UI dev proxy is only supported with --https=false --http=true")
369
+ }
370
+
371
+ const remoteAccessEnabled = options.host === "0.0.0.0" || !isLoopbackHost(options.host)
372
+
373
+ const httpsPortExplicit = programHasArg(process.argv.slice(2), "--https-port") || Boolean(process.env.CLI_HTTPS_PORT)
374
+ const httpPortExplicit = programHasArg(process.argv.slice(2), "--http-port") || Boolean(process.env.CLI_HTTP_PORT)
375
+
376
+ const httpsBindPort = httpsPortExplicit ? options.httpsPort : 0
377
+ const httpBindPort = httpPortExplicit ? options.httpPort : 0
378
+
379
+ // Listener binding rules:
380
+ // - Remote access enabled: HTTP listens on loopback, HTTPS on all IPs (host=0.0.0.0 / LAN IP).
381
+ // - Remote access disabled: both listen on loopback.
382
+ // - HTTP-only mode: respect --host (used for dev/testing).
383
+ const httpsBindHost = remoteAccessEnabled ? options.host : "127.0.0.1"
384
+ const httpBindHost = options.http ? (options.https ? "127.0.0.1" : options.host) : "127.0.0.1"
385
+
386
+ const servers: Array<ReturnType<typeof createHttpServer>> = []
387
+
388
+ const httpServer = options.http
389
+ ? createHttpServer({
390
+ bindHost: httpBindHost,
391
+ bindPort: httpBindPort,
392
+ defaultPort: options.httpPort,
393
+ protocol: "http",
394
+ workspaceManager,
395
+ configStore,
396
+ binaryRegistry,
397
+ fileSystemBrowser,
398
+ eventBus,
399
+ serverMeta,
400
+ instanceStore,
401
+ authManager,
402
+ uiStaticDir: uiResolution.uiStaticDir ?? DEFAULT_UI_STATIC_DIR,
403
+ uiDevServerUrl: uiResolution.uiDevServerUrl,
404
+ logger,
405
+ })
406
+ : null
407
+
408
+ const httpsServer = options.https
409
+ ? createHttpServer({
410
+ bindHost: httpsBindHost,
411
+ bindPort: httpsBindPort,
412
+ defaultPort: options.httpsPort,
413
+ protocol: "https",
414
+ httpsOptions: tlsResolution?.httpsOptions,
415
+ workspaceManager,
416
+ configStore,
417
+ binaryRegistry,
418
+ fileSystemBrowser,
419
+ eventBus,
420
+ serverMeta,
421
+ instanceStore,
422
+ authManager,
423
+ uiStaticDir: uiResolution.uiStaticDir ?? DEFAULT_UI_STATIC_DIR,
424
+ uiDevServerUrl: undefined,
425
+ logger,
426
+ })
427
+ : null
428
+
429
+ if (httpServer) servers.push(httpServer)
430
+ if (httpsServer) servers.push(httpsServer)
431
+
432
+ const [httpStart, httpsStart] = await Promise.all([
433
+ httpServer ? httpServer.start() : Promise.resolve(null),
434
+ httpsServer ? httpsServer.start() : Promise.resolve(null),
435
+ ])
436
+
437
+ const localStart = httpStart ?? httpsStart
438
+ if (!localStart) {
439
+ throw new Error("No listeners started")
440
+ }
441
+
442
+ const remoteStart = httpsStart ?? httpStart
443
+ const localProtocol: "http" | "https" = httpStart ? "http" : "https"
444
+ const remoteProtocol: "http" | "https" = httpsStart ? "https" : "http"
445
+
446
+ // Use an explicit IPv4 loopback address for the "local" URL.
447
+ // On macOS, `localhost` often resolves to ::1 first, and it is possible to have
448
+ // another instance bound on IPv6 while this instance binds IPv4 (or vice versa),
449
+ // which can lead clients to talk to the wrong process.
450
+ const localUrl = `${localProtocol}://127.0.0.1:${localStart.port}`
451
+ let remoteUrl: string | undefined
452
+ if (remoteStart) {
453
+ const wantsAll = options.host === "0.0.0.0" || !isLoopbackHost(options.host)
454
+ let remoteHost = options.host
455
+ if (wantsAll) {
456
+ if (options.host === "0.0.0.0") {
457
+ const candidates = resolveNetworkAddresses({ host: options.host, protocol: remoteProtocol, port: remoteStart.port })
458
+ remoteHost = candidates.find((addr) => addr.scope === "external")?.ip ?? "localhost"
459
+ }
460
+ } else {
461
+ remoteHost = "localhost"
462
+ }
463
+ remoteUrl = `${remoteProtocol}://${remoteHost}:${remoteStart.port}`
464
+ }
465
+
466
+ serverMeta.localUrl = localUrl
467
+ serverMeta.localPort = localStart.port
468
+ serverMeta.remoteUrl = remoteUrl
469
+ serverMeta.remotePort = remoteStart?.port
470
+ serverMeta.host = options.host
471
+ serverMeta.listeningMode = options.host === "0.0.0.0" || !isLoopbackHost(options.host) ? "all" : "local"
472
+
473
+ if (serverMeta.remotePort && remoteUrl) {
474
+ serverMeta.addresses = resolveNetworkAddresses({ host: options.host, protocol: remoteProtocol, port: serverMeta.remotePort })
475
+ } else {
476
+ serverMeta.addresses = []
477
+ }
478
+
479
+ console.log(`Local Connection URL : ${serverMeta.localUrl}`)
480
+ if (serverMeta.remoteUrl) {
481
+ console.log(`Remote Connection URL : ${serverMeta.remoteUrl}`)
482
+ }
483
+
484
+ if (options.launch) {
485
+ await launchInBrowser(serverMeta.localUrl, logger.child({ component: "launcher" }))
486
+ }
487
+
488
+ let shuttingDown = false
489
+
490
+ const shutdown = async () => {
491
+ if (shuttingDown) {
492
+ logger.info("Shutdown already in progress, ignoring signal")
493
+ return
494
+ }
495
+ shuttingDown = true
496
+ logger.info("Received shutdown signal, stopping workspaces and server")
497
+
498
+ const shutdownWorkspaces = (async () => {
499
+ try {
500
+ instanceEventBridge.shutdown()
501
+ } catch (error) {
502
+ logger.warn({ err: error }, "Instance event bridge shutdown failed")
503
+ }
504
+
505
+ try {
506
+ await workspaceManager.shutdown()
507
+ logger.info("Workspace manager shutdown complete")
508
+ } catch (error) {
509
+ logger.error({ err: error }, "Workspace manager shutdown failed")
510
+ }
511
+ })()
512
+
513
+ const shutdownHttp = (async () => {
514
+ try {
515
+ await Promise.allSettled(servers.map((srv) => srv.stop()))
516
+ logger.info("HTTP server(s) stopped")
517
+ } catch (error) {
518
+ logger.error({ err: error }, "Failed to stop HTTP server")
519
+ }
520
+ })()
521
+
522
+ await Promise.allSettled([shutdownWorkspaces, shutdownHttp])
523
+
524
+ // no-op: remote UI manifest replaces GitHub release monitor
525
+
526
+ devReleaseMonitor?.stop()
527
+
528
+ logger.info("Exiting process")
529
+ process.exit(0)
530
+ }
531
+
532
+ process.on("SIGINT", shutdown)
533
+ process.on("SIGTERM", shutdown)
534
+ }
535
+
536
+ main().catch((error) => {
537
+ const logger = createLogger({ component: "app" })
538
+ logger.error({ err: error }, "CLI server crashed")
539
+ process.exit(1)
540
+ })