@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
@@ -0,0 +1,135 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import fuzzysort from "fuzzysort";
4
+ import { clearWorkspaceSearchCache, getWorkspaceCandidates, refreshWorkspaceCandidates } from "./search-cache";
5
+ const DEFAULT_LIMIT = 100;
6
+ const MAX_LIMIT = 200;
7
+ const MAX_CANDIDATES = 8000;
8
+ const IGNORED_DIRECTORIES = new Set([".git", ".hg", ".svn", "node_modules", "dist", "build", ".next", ".nuxt", ".turbo", ".cache", "coverage"].map((name) => name.toLowerCase()));
9
+ export function searchWorkspaceFiles(rootDir, query, options = {}) {
10
+ const trimmedQuery = query.trim();
11
+ if (!trimmedQuery) {
12
+ throw new Error("Search query is required");
13
+ }
14
+ const normalizedRoot = path.resolve(rootDir);
15
+ const limit = normalizeLimit(options.limit);
16
+ const typeFilter = options.type ?? "all";
17
+ const refreshRequested = options.refresh === true;
18
+ let entries;
19
+ try {
20
+ if (!refreshRequested) {
21
+ entries = getWorkspaceCandidates(normalizedRoot);
22
+ }
23
+ if (!entries) {
24
+ entries = refreshWorkspaceCandidates(normalizedRoot, () => collectCandidates(normalizedRoot));
25
+ }
26
+ }
27
+ catch (error) {
28
+ clearWorkspaceSearchCache(normalizedRoot);
29
+ throw error;
30
+ }
31
+ if (!entries || entries.length === 0) {
32
+ clearWorkspaceSearchCache(normalizedRoot);
33
+ return [];
34
+ }
35
+ const candidates = buildCandidateEntries(entries, typeFilter);
36
+ if (candidates.length === 0) {
37
+ return [];
38
+ }
39
+ const matches = fuzzysort.go(trimmedQuery, candidates, {
40
+ key: "key",
41
+ limit,
42
+ });
43
+ if (!matches || matches.length === 0) {
44
+ return [];
45
+ }
46
+ return matches.map((match) => match.obj.entry);
47
+ }
48
+ function collectCandidates(rootDir) {
49
+ const queue = [""];
50
+ const entries = [];
51
+ while (queue.length > 0 && entries.length < MAX_CANDIDATES) {
52
+ const relativeDir = queue.pop() || "";
53
+ const absoluteDir = relativeDir ? path.join(rootDir, relativeDir) : rootDir;
54
+ let dirents;
55
+ try {
56
+ dirents = fs.readdirSync(absoluteDir, { withFileTypes: true });
57
+ }
58
+ catch {
59
+ continue;
60
+ }
61
+ for (const dirent of dirents) {
62
+ const entryName = dirent.name;
63
+ const lowerName = entryName.toLowerCase();
64
+ const relativePath = relativeDir ? `${relativeDir}/${entryName}` : entryName;
65
+ const absolutePath = path.join(absoluteDir, entryName);
66
+ if (dirent.isDirectory() && IGNORED_DIRECTORIES.has(lowerName)) {
67
+ continue;
68
+ }
69
+ let stats;
70
+ try {
71
+ stats = fs.statSync(absolutePath);
72
+ }
73
+ catch {
74
+ continue;
75
+ }
76
+ const isDirectory = stats.isDirectory();
77
+ if (isDirectory && !IGNORED_DIRECTORIES.has(lowerName)) {
78
+ if (entries.length < MAX_CANDIDATES) {
79
+ queue.push(relativePath);
80
+ }
81
+ }
82
+ const entryType = isDirectory ? "directory" : "file";
83
+ const normalizedPath = normalizeRelativeEntryPath(relativePath);
84
+ const entry = {
85
+ name: entryName,
86
+ path: normalizedPath,
87
+ absolutePath: path.resolve(rootDir, normalizedPath === "." ? "" : normalizedPath),
88
+ type: entryType,
89
+ size: entryType === "file" ? stats.size : undefined,
90
+ modifiedAt: stats.mtime.toISOString(),
91
+ };
92
+ entries.push(entry);
93
+ if (entries.length >= MAX_CANDIDATES) {
94
+ break;
95
+ }
96
+ }
97
+ }
98
+ return entries;
99
+ }
100
+ function buildCandidateEntries(entries, filter) {
101
+ const filtered = [];
102
+ for (const entry of entries) {
103
+ if (!shouldInclude(entry.type, filter)) {
104
+ continue;
105
+ }
106
+ filtered.push({ entry, key: buildSearchKey(entry) });
107
+ }
108
+ return filtered;
109
+ }
110
+ function normalizeLimit(limit) {
111
+ if (!limit || Number.isNaN(limit)) {
112
+ return DEFAULT_LIMIT;
113
+ }
114
+ const clamped = Math.min(Math.max(limit, 1), MAX_LIMIT);
115
+ return clamped;
116
+ }
117
+ function shouldInclude(entryType, filter) {
118
+ return filter === "all" || entryType === filter;
119
+ }
120
+ function normalizeRelativeEntryPath(relativePath) {
121
+ if (!relativePath) {
122
+ return ".";
123
+ }
124
+ let normalized = relativePath.replace(/\\+/g, "/");
125
+ if (normalized.startsWith("./")) {
126
+ normalized = normalized.replace(/^\.\/+/, "");
127
+ }
128
+ if (normalized.startsWith("/")) {
129
+ normalized = normalized.replace(/^\/+/g, "");
130
+ }
131
+ return normalized || ".";
132
+ }
133
+ function buildSearchKey(entry) {
134
+ return entry.path.toLowerCase();
135
+ }
package/dist/index.js ADDED
@@ -0,0 +1,410 @@
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 { InstanceStore } from "./storage/instance-store";
17
+ import { InstanceEventBridge } from "./workspaces/instance-events";
18
+ import { createLogger } from "./logger";
19
+ import { launchInBrowser } from "./launcher";
20
+ import { resolveUi } from "./ui/remote-ui";
21
+ import { AuthManager, BOOTSTRAP_TOKEN_STDOUT_PREFIX, DEFAULT_AUTH_USERNAME } from "./auth/manager";
22
+ import { resolveHttpsOptions } from "./server/tls";
23
+ import { resolveNetworkAddresses } from "./server/network-addresses";
24
+ import { startDevReleaseMonitor } from "./releases/dev-release-monitor";
25
+ const require = createRequire(import.meta.url);
26
+ const packageJson = require("../package.json");
27
+ const __filename = fileURLToPath(import.meta.url);
28
+ const __dirname = path.dirname(__filename);
29
+ const DEFAULT_UI_STATIC_DIR = path.resolve(__dirname, "../public");
30
+ const DEFAULT_HOST = "127.0.0.1";
31
+ const DEFAULT_CONFIG_PATH = "~/.config/codenomad/config.json";
32
+ const DEFAULT_HTTPS_PORT = 9898;
33
+ const DEFAULT_HTTP_PORT = 9899;
34
+ function parseCliOptions(argv) {
35
+ const program = new Command()
36
+ .name("codenomad")
37
+ .description("CodeNomad CLI server")
38
+ .version(packageJson.version, "-v, --version", "Show the CLI version")
39
+ .addOption(new Option("--host <host>", "Host interface to bind").env("CLI_HOST").default(DEFAULT_HOST))
40
+ .addOption(new Option("--https <enabled>", "Enable HTTPS listener (true|false)").env("CLI_HTTPS").default("true"))
41
+ .addOption(new Option("--http <enabled>", "Enable HTTP listener (true|false)").env("CLI_HTTP").default("false"))
42
+ .addOption(new Option("--https-port <number>", "HTTPS port (0 for auto)").env("CLI_HTTPS_PORT").default(DEFAULT_HTTPS_PORT).argParser(parsePort))
43
+ .addOption(new Option("--http-port <number>", "HTTP port (0 for auto)").env("CLI_HTTP_PORT").default(DEFAULT_HTTP_PORT).argParser(parsePort))
44
+ .addOption(new Option("--tls-key <path>", "TLS private key (PEM)").env("CLI_TLS_KEY"))
45
+ .addOption(new Option("--tls-cert <path>", "TLS certificate (PEM)").env("CLI_TLS_CERT"))
46
+ .addOption(new Option("--tls-ca <path>", "TLS CA chain (PEM)").env("CLI_TLS_CA"))
47
+ .addOption(new Option("--tlsSANs <list>", "Additional TLS SANs (comma-separated)").env("CLI_TLS_SANS"))
48
+ .addOption(new Option("--workspace-root <path>", "Workspace root directory").env("CLI_WORKSPACE_ROOT").default(process.cwd()))
49
+ .addOption(new Option("--root <path>").env("CLI_ROOT").hideHelp(true))
50
+ .addOption(new Option("--unrestricted-root", "Allow browsing the full filesystem").env("CLI_UNRESTRICTED_ROOT").default(false))
51
+ .addOption(new Option("--config <path>", "Path to the config file").env("CLI_CONFIG").default(DEFAULT_CONFIG_PATH))
52
+ .addOption(new Option("--log-level <level>", "Log level (trace|debug|info|warn|error)").env("CLI_LOG_LEVEL"))
53
+ .addOption(new Option("--log-destination <path>", "Log destination file (defaults to stdout)").env("CLI_LOG_DESTINATION"))
54
+ .addOption(new Option("--ui-dir <path>", "Directory containing the built UI bundle").env("CLI_UI_DIR").default(DEFAULT_UI_STATIC_DIR))
55
+ .addOption(new Option("--ui-dev-server <url>", "Proxy UI requests to a running dev server").env("CLI_UI_DEV_SERVER"))
56
+ .addOption(new Option("--ui-no-update", "Disable remote UI updates").env("CLI_UI_NO_UPDATE").default(false))
57
+ .addOption(new Option("--ui-auto-update <enabled>", "Enable remote UI updates (true|false)").env("CLI_UI_AUTO_UPDATE").default("true"))
58
+ .addOption(new Option("--ui-manifest-url <url>", "Remote UI manifest URL").env("CLI_UI_MANIFEST_URL"))
59
+ .addOption(new Option("--launch", "Launch the UI in a browser after start").env("CLI_LAUNCH").default(false))
60
+ .addOption(new Option("--username <username>", "Username for server authentication")
61
+ .env("CODENOMAD_SERVER_USERNAME")
62
+ .default(DEFAULT_AUTH_USERNAME))
63
+ .addOption(new Option("--password <password>", "Password for server authentication").env("CODENOMAD_SERVER_PASSWORD"))
64
+ .addOption(new Option("--generate-token", "Emit a one-time bootstrap token for desktop")
65
+ .env("CODENOMAD_GENERATE_TOKEN")
66
+ .default(false))
67
+ .addOption(new Option("--dangerously-skip-auth", "Disable CodeNomad's internal auth. Use only behind a trusted perimeter (SSO/VPN/etc).")
68
+ .env("CODENOMAD_SKIP_AUTH")
69
+ .default(false));
70
+ program.parse(argv, { from: "user" });
71
+ const parsed = program.opts();
72
+ const parseBooleanEnv = (value) => {
73
+ const normalized = (value ?? "").trim().toLowerCase();
74
+ return normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "y" || normalized === "on";
75
+ };
76
+ const resolvedRoot = parsed.workspaceRoot ?? parsed.root ?? process.cwd();
77
+ const normalizedHost = resolveHost(parsed.host);
78
+ const autoUpdateString = (parsed.uiAutoUpdate ?? "true").trim().toLowerCase();
79
+ const uiAutoUpdate = autoUpdateString === "1" || autoUpdateString === "true" || autoUpdateString === "yes";
80
+ const httpsEnabled = parseBooleanEnv(parsed.https);
81
+ const httpEnabled = parseBooleanEnv(parsed.http);
82
+ if (!httpsEnabled && !httpEnabled) {
83
+ throw new InvalidArgumentError("At least one listener must be enabled (--https or --http)");
84
+ }
85
+ return {
86
+ host: normalizedHost,
87
+ https: httpsEnabled,
88
+ http: httpEnabled,
89
+ httpsPort: parsed.httpsPort,
90
+ httpPort: parsed.httpPort,
91
+ tlsKeyPath: parsed.tlsKey,
92
+ tlsCertPath: parsed.tlsCert,
93
+ tlsCaPath: parsed.tlsCa,
94
+ tlsSANs: parsed.tlsSANs,
95
+ rootDir: resolvedRoot,
96
+ configPath: parsed.config,
97
+ unrestrictedRoot: Boolean(parsed.unrestrictedRoot),
98
+ logLevel: parsed.logLevel,
99
+ logDestination: parsed.logDestination,
100
+ uiStaticDir: parsed.uiDir,
101
+ uiDevServer: parsed.uiDevServer,
102
+ uiAutoUpdate,
103
+ uiNoUpdate: Boolean(parsed.uiNoUpdate),
104
+ uiManifestUrl: parsed.uiManifestUrl,
105
+ launch: Boolean(parsed.launch),
106
+ authUsername: parsed.username,
107
+ authPassword: parsed.password,
108
+ generateToken: Boolean(parsed.generateToken),
109
+ dangerouslySkipAuth: Boolean(parsed.dangerouslySkipAuth),
110
+ };
111
+ }
112
+ function parsePort(input) {
113
+ const value = Number(input);
114
+ if (!Number.isInteger(value) || value < 0 || value > 65535) {
115
+ throw new InvalidArgumentError("Port must be an integer between 0 and 65535");
116
+ }
117
+ return value;
118
+ }
119
+ function resolveHost(input) {
120
+ const trimmed = input?.trim();
121
+ if (!trimmed)
122
+ return DEFAULT_HOST;
123
+ if (trimmed === "0.0.0.0") {
124
+ return "0.0.0.0";
125
+ }
126
+ if (trimmed === "localhost") {
127
+ return DEFAULT_HOST;
128
+ }
129
+ return trimmed;
130
+ }
131
+ function programHasArg(argv, flag) {
132
+ return argv.includes(flag);
133
+ }
134
+ async function main() {
135
+ const options = parseCliOptions(process.argv.slice(2));
136
+ const logger = createLogger({ level: options.logLevel, destination: options.logDestination, component: "app" });
137
+ const workspaceLogger = logger.child({ component: "workspace" });
138
+ const configLogger = logger.child({ component: "config" });
139
+ const eventLogger = logger.child({ component: "events" });
140
+ const logOptions = {
141
+ ...options,
142
+ authPassword: options.authPassword ? "[REDACTED]" : undefined,
143
+ };
144
+ logger.info({ options: logOptions }, "Starting CodeNomad CLI server");
145
+ if (options.dangerouslySkipAuth) {
146
+ logger.warn("DANGEROUS: internal authentication is disabled (--dangerously-skip-auth / CODENOMAD_SKIP_AUTH).");
147
+ }
148
+ const eventBus = new EventBus(eventLogger);
149
+ const isLoopbackHost = (host) => host === "127.0.0.1" || host === "::1" || host.startsWith("127.");
150
+ const configLocation = resolveConfigLocation(options.configPath);
151
+ const configDir = configLocation.baseDir;
152
+ if ((options.tlsKeyPath && !options.tlsCertPath) || (!options.tlsKeyPath && options.tlsCertPath)) {
153
+ throw new InvalidArgumentError("--tls-key and --tls-cert must be provided together");
154
+ }
155
+ const serverMeta = {
156
+ localUrl: "http://localhost:0",
157
+ remoteUrl: undefined,
158
+ eventsUrl: `/api/events`,
159
+ host: options.host,
160
+ listeningMode: isLoopbackHost(options.host) ? "local" : "all",
161
+ localPort: 0,
162
+ remotePort: undefined,
163
+ hostLabel: options.host,
164
+ workspaceRoot: options.rootDir,
165
+ addresses: [],
166
+ };
167
+ const authManager = new AuthManager({
168
+ configPath: configLocation.configYamlPath,
169
+ username: options.authUsername,
170
+ password: options.authPassword,
171
+ generateToken: options.generateToken,
172
+ dangerouslySkipAuth: options.dangerouslySkipAuth,
173
+ }, logger.child({ component: "auth" }));
174
+ if (options.generateToken && !options.dangerouslySkipAuth) {
175
+ const token = authManager.issueBootstrapToken();
176
+ if (token) {
177
+ console.log(`${BOOTSTRAP_TOKEN_STDOUT_PREFIX}${token}`);
178
+ }
179
+ }
180
+ const tlsResolution = resolveHttpsOptions({
181
+ enabled: options.https,
182
+ configDir,
183
+ host: options.host,
184
+ tlsKeyPath: options.tlsKeyPath,
185
+ tlsCertPath: options.tlsCertPath,
186
+ tlsCaPath: options.tlsCaPath,
187
+ tlsSANs: options.tlsSANs,
188
+ logger: logger.child({ component: "tls" }),
189
+ });
190
+ const nodeExtraCaCertsPath = !options.http ? tlsResolution?.caCertPath : undefined;
191
+ const configStore = new ConfigStore(configLocation, eventBus, configLogger);
192
+ // Eagerly load config at boot so migrations run immediately
193
+ // (instead of waiting for the first /api/config request).
194
+ try {
195
+ configStore.get();
196
+ }
197
+ catch (error) {
198
+ configLogger.warn({ err: error }, "Failed to load config at boot; continuing with defaults");
199
+ }
200
+ const binaryRegistry = new BinaryRegistry(configStore, eventBus, configLogger);
201
+ const workspaceManager = new WorkspaceManager({
202
+ rootDir: options.rootDir,
203
+ configStore,
204
+ binaryRegistry,
205
+ eventBus,
206
+ logger: workspaceLogger,
207
+ getServerBaseUrl: () => serverMeta.localUrl,
208
+ nodeExtraCaCertsPath,
209
+ });
210
+ const fileSystemBrowser = new FileSystemBrowser({ rootDir: options.rootDir, unrestricted: options.unrestrictedRoot });
211
+ const instanceStore = new InstanceStore(configLocation.instancesDir);
212
+ const instanceEventBridge = new InstanceEventBridge({
213
+ workspaceManager,
214
+ eventBus,
215
+ logger: logger.child({ component: "instance-events" }),
216
+ });
217
+ const uiDirEnvOverride = Boolean(process.env.CLI_UI_DIR);
218
+ const uiDirCliOverride = programHasArg(process.argv.slice(2), "--ui-dir");
219
+ const uiOverrideIsExplicit = uiDirEnvOverride || uiDirCliOverride;
220
+ const uiDirOverride = uiOverrideIsExplicit ? options.uiStaticDir : undefined;
221
+ const autoUpdateEnabled = options.uiAutoUpdate && !options.uiNoUpdate;
222
+ const uiResolution = await resolveUi({
223
+ serverVersion: packageJson.version,
224
+ bundledUiDir: DEFAULT_UI_STATIC_DIR,
225
+ autoUpdate: autoUpdateEnabled,
226
+ overrideUiDir: uiDirOverride,
227
+ uiDevServerUrl: options.uiDevServer,
228
+ manifestUrl: options.uiManifestUrl,
229
+ logger: logger.child({ component: "ui" }),
230
+ });
231
+ serverMeta.serverVersion = packageJson.version;
232
+ serverMeta.ui = {
233
+ version: uiResolution.uiVersion,
234
+ source: uiResolution.source,
235
+ };
236
+ serverMeta.support = {
237
+ supported: uiResolution.supported,
238
+ message: uiResolution.message,
239
+ latestServerVersion: uiResolution.latestServerVersion,
240
+ latestServerUrl: uiResolution.latestServerUrl,
241
+ minServerVersion: uiResolution.minServerVersion,
242
+ };
243
+ const updateChannel = (process.env.CODENOMAD_UPDATE_CHANNEL ?? "").trim().toLowerCase();
244
+ const githubRepo = (process.env.CODENOMAD_GITHUB_REPO ?? "NeuralNomadsAI/CodeNomad").trim();
245
+ const isDevVersion = packageJson.version.includes("-dev.") || packageJson.version.includes("-dev-");
246
+ const enableDevUpdateChecks = updateChannel === "dev" || (updateChannel === "" && isDevVersion);
247
+ const devReleaseMonitor = enableDevUpdateChecks
248
+ ? startDevReleaseMonitor({
249
+ currentVersion: packageJson.version,
250
+ repo: githubRepo,
251
+ logger: logger.child({ component: "updates" }),
252
+ onUpdate: (release) => {
253
+ serverMeta.update = release;
254
+ },
255
+ })
256
+ : null;
257
+ if (uiResolution.uiDevServerUrl && options.https) {
258
+ throw new InvalidArgumentError("UI dev proxy is only supported with --https=false --http=true");
259
+ }
260
+ const remoteAccessEnabled = options.host === "0.0.0.0" || !isLoopbackHost(options.host);
261
+ const httpsPortExplicit = programHasArg(process.argv.slice(2), "--https-port") || Boolean(process.env.CLI_HTTPS_PORT);
262
+ const httpPortExplicit = programHasArg(process.argv.slice(2), "--http-port") || Boolean(process.env.CLI_HTTP_PORT);
263
+ const httpsBindPort = httpsPortExplicit ? options.httpsPort : 0;
264
+ const httpBindPort = httpPortExplicit ? options.httpPort : 0;
265
+ // Listener binding rules:
266
+ // - Remote access enabled: HTTP listens on loopback, HTTPS on all IPs (host=0.0.0.0 / LAN IP).
267
+ // - Remote access disabled: both listen on loopback.
268
+ // - HTTP-only mode: respect --host (used for dev/testing).
269
+ const httpsBindHost = remoteAccessEnabled ? options.host : "127.0.0.1";
270
+ const httpBindHost = options.http ? (options.https ? "127.0.0.1" : options.host) : "127.0.0.1";
271
+ const servers = [];
272
+ const httpServer = options.http
273
+ ? createHttpServer({
274
+ bindHost: httpBindHost,
275
+ bindPort: httpBindPort,
276
+ defaultPort: options.httpPort,
277
+ protocol: "http",
278
+ workspaceManager,
279
+ configStore,
280
+ binaryRegistry,
281
+ fileSystemBrowser,
282
+ eventBus,
283
+ serverMeta,
284
+ instanceStore,
285
+ authManager,
286
+ uiStaticDir: uiResolution.uiStaticDir ?? DEFAULT_UI_STATIC_DIR,
287
+ uiDevServerUrl: uiResolution.uiDevServerUrl,
288
+ logger,
289
+ })
290
+ : null;
291
+ const httpsServer = options.https
292
+ ? createHttpServer({
293
+ bindHost: httpsBindHost,
294
+ bindPort: httpsBindPort,
295
+ defaultPort: options.httpsPort,
296
+ protocol: "https",
297
+ httpsOptions: tlsResolution?.httpsOptions,
298
+ workspaceManager,
299
+ configStore,
300
+ binaryRegistry,
301
+ fileSystemBrowser,
302
+ eventBus,
303
+ serverMeta,
304
+ instanceStore,
305
+ authManager,
306
+ uiStaticDir: uiResolution.uiStaticDir ?? DEFAULT_UI_STATIC_DIR,
307
+ uiDevServerUrl: undefined,
308
+ logger,
309
+ })
310
+ : null;
311
+ if (httpServer)
312
+ servers.push(httpServer);
313
+ if (httpsServer)
314
+ servers.push(httpsServer);
315
+ const [httpStart, httpsStart] = await Promise.all([
316
+ httpServer ? httpServer.start() : Promise.resolve(null),
317
+ httpsServer ? httpsServer.start() : Promise.resolve(null),
318
+ ]);
319
+ const localStart = httpStart ?? httpsStart;
320
+ if (!localStart) {
321
+ throw new Error("No listeners started");
322
+ }
323
+ const remoteStart = httpsStart ?? httpStart;
324
+ const localProtocol = httpStart ? "http" : "https";
325
+ const remoteProtocol = httpsStart ? "https" : "http";
326
+ // Use an explicit IPv4 loopback address for the "local" URL.
327
+ // On macOS, `localhost` often resolves to ::1 first, and it is possible to have
328
+ // another instance bound on IPv6 while this instance binds IPv4 (or vice versa),
329
+ // which can lead clients to talk to the wrong process.
330
+ const localUrl = `${localProtocol}://127.0.0.1:${localStart.port}`;
331
+ let remoteUrl;
332
+ if (remoteStart) {
333
+ const wantsAll = options.host === "0.0.0.0" || !isLoopbackHost(options.host);
334
+ let remoteHost = options.host;
335
+ if (wantsAll) {
336
+ if (options.host === "0.0.0.0") {
337
+ const candidates = resolveNetworkAddresses({ host: options.host, protocol: remoteProtocol, port: remoteStart.port });
338
+ remoteHost = candidates.find((addr) => addr.scope === "external")?.ip ?? "localhost";
339
+ }
340
+ }
341
+ else {
342
+ remoteHost = "localhost";
343
+ }
344
+ remoteUrl = `${remoteProtocol}://${remoteHost}:${remoteStart.port}`;
345
+ }
346
+ serverMeta.localUrl = localUrl;
347
+ serverMeta.localPort = localStart.port;
348
+ serverMeta.remoteUrl = remoteUrl;
349
+ serverMeta.remotePort = remoteStart?.port;
350
+ serverMeta.host = options.host;
351
+ serverMeta.listeningMode = options.host === "0.0.0.0" || !isLoopbackHost(options.host) ? "all" : "local";
352
+ if (serverMeta.remotePort && remoteUrl) {
353
+ serverMeta.addresses = resolveNetworkAddresses({ host: options.host, protocol: remoteProtocol, port: serverMeta.remotePort });
354
+ }
355
+ else {
356
+ serverMeta.addresses = [];
357
+ }
358
+ console.log(`Local Connection URL : ${serverMeta.localUrl}`);
359
+ if (serverMeta.remoteUrl) {
360
+ console.log(`Remote Connection URL : ${serverMeta.remoteUrl}`);
361
+ }
362
+ if (options.launch) {
363
+ await launchInBrowser(serverMeta.localUrl, logger.child({ component: "launcher" }));
364
+ }
365
+ let shuttingDown = false;
366
+ const shutdown = async () => {
367
+ if (shuttingDown) {
368
+ logger.info("Shutdown already in progress, ignoring signal");
369
+ return;
370
+ }
371
+ shuttingDown = true;
372
+ logger.info("Received shutdown signal, stopping workspaces and server");
373
+ const shutdownWorkspaces = (async () => {
374
+ try {
375
+ instanceEventBridge.shutdown();
376
+ }
377
+ catch (error) {
378
+ logger.warn({ err: error }, "Instance event bridge shutdown failed");
379
+ }
380
+ try {
381
+ await workspaceManager.shutdown();
382
+ logger.info("Workspace manager shutdown complete");
383
+ }
384
+ catch (error) {
385
+ logger.error({ err: error }, "Workspace manager shutdown failed");
386
+ }
387
+ })();
388
+ const shutdownHttp = (async () => {
389
+ try {
390
+ await Promise.allSettled(servers.map((srv) => srv.stop()));
391
+ logger.info("HTTP server(s) stopped");
392
+ }
393
+ catch (error) {
394
+ logger.error({ err: error }, "Failed to stop HTTP server");
395
+ }
396
+ })();
397
+ await Promise.allSettled([shutdownWorkspaces, shutdownHttp]);
398
+ // no-op: remote UI manifest replaces GitHub release monitor
399
+ devReleaseMonitor?.stop();
400
+ logger.info("Exiting process");
401
+ process.exit(0);
402
+ };
403
+ process.on("SIGINT", shutdown);
404
+ process.on("SIGTERM", shutdown);
405
+ }
406
+ main().catch((error) => {
407
+ const logger = createLogger({ component: "app" });
408
+ logger.error({ err: error }, "CLI server crashed");
409
+ process.exit(1);
410
+ });
@@ -0,0 +1,11 @@
1
+ const BOT_SIGNATURE = "--\nYours, [CodeNomadBot](https://github.com/NeuralNomadsAI/CodeNomad)";
2
+ const BOT_SIGNATURE_BLOCK = `\n\n${BOT_SIGNATURE}`;
3
+ export function appendCodeNomadBotSignature(body) {
4
+ const trimmed = (body ?? "").trimEnd();
5
+ if (!trimmed)
6
+ return body;
7
+ if (trimmed.includes(BOT_SIGNATURE))
8
+ return body;
9
+ return `${trimmed}${BOT_SIGNATURE_BLOCK}`;
10
+ }
11
+ export { BOT_SIGNATURE };