@neuralnomads/codenomad 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (315) hide show
  1. package/dist/api-types.js +1 -0
  2. package/dist/bin.js +24 -0
  3. package/dist/config/binaries.js +118 -0
  4. package/dist/config/schema.js +34 -0
  5. package/dist/config/store.js +68 -0
  6. package/dist/events/bus.js +32 -0
  7. package/dist/filesystem/__tests__/search-cache.test.js +40 -0
  8. package/dist/filesystem/browser.js +238 -0
  9. package/dist/filesystem/search-cache.js +43 -0
  10. package/dist/filesystem/search.js +135 -0
  11. package/dist/index.js +142 -0
  12. package/dist/launcher.js +149 -0
  13. package/dist/loader.js +21 -0
  14. package/dist/logger.js +109 -0
  15. package/dist/server/http-server.js +224 -0
  16. package/dist/server/routes/config.js +44 -0
  17. package/dist/server/routes/events.js +35 -0
  18. package/dist/server/routes/filesystem.js +19 -0
  19. package/dist/server/routes/meta.js +3 -0
  20. package/dist/server/routes/storage.js +52 -0
  21. package/dist/server/routes/workspaces.js +82 -0
  22. package/dist/storage/instance-store.js +56 -0
  23. package/dist/workspaces/manager.js +147 -0
  24. package/dist/workspaces/runtime.js +168 -0
  25. package/package.json +38 -0
  26. package/public/assets/CodeNomad-Icon-bmTWNPXy.png +0 -0
  27. package/public/assets/abap-BdImnpbu.js +1 -0
  28. package/public/assets/actionscript-3-CfeIJUat.js +1 -0
  29. package/public/assets/ada-bCR0ucgS.js +1 -0
  30. package/public/assets/andromeeda-C-Jbm3Hp.js +1 -0
  31. package/public/assets/angular-html-CU67Zn6k.js +1 -0
  32. package/public/assets/angular-ts-BwZT4LLn.js +1 -0
  33. package/public/assets/apache-Pmp26Uib.js +1 -0
  34. package/public/assets/apex-DhZLUxFE.js +1 -0
  35. package/public/assets/apl-dKokRX4l.js +1 -0
  36. package/public/assets/applescript-Co6uUVPk.js +1 -0
  37. package/public/assets/ara-BRHolxvo.js +1 -0
  38. package/public/assets/asciidoc-Dv7Oe6Be.js +1 -0
  39. package/public/assets/asm-D_Q5rh1f.js +1 -0
  40. package/public/assets/astro-CbQHKStN.js +1 -0
  41. package/public/assets/aurora-x-D-2ljcwZ.js +1 -0
  42. package/public/assets/awk-DMzUqQB5.js +1 -0
  43. package/public/assets/ayu-dark-Cv9koXgw.js +1 -0
  44. package/public/assets/ballerina-BFfxhgS-.js +1 -0
  45. package/public/assets/bat-BkioyH1T.js +1 -0
  46. package/public/assets/beancount-k_qm7-4y.js +1 -0
  47. package/public/assets/berry-D08WgyRC.js +1 -0
  48. package/public/assets/bibtex-CHM0blh-.js +1 -0
  49. package/public/assets/bicep-Bmn6On1c.js +1 -0
  50. package/public/assets/blade-DVc8C-J4.js +1 -0
  51. package/public/assets/bsl-BO_Y6i37.js +1 -0
  52. package/public/assets/c-BIGW1oBm.js +1 -0
  53. package/public/assets/cadence-Bv_4Rxtq.js +1 -0
  54. package/public/assets/cairo-KRGpt6FW.js +1 -0
  55. package/public/assets/catppuccin-frappe-DFWUc33u.js +1 -0
  56. package/public/assets/catppuccin-latte-C9dUb6Cb.js +1 -0
  57. package/public/assets/catppuccin-macchiato-DQyhUUbL.js +1 -0
  58. package/public/assets/catppuccin-mocha-D87Tk5Gz.js +1 -0
  59. package/public/assets/clarity-D53aC0YG.js +1 -0
  60. package/public/assets/clojure-P80f7IUj.js +1 -0
  61. package/public/assets/cmake-D1j8_8rp.js +1 -0
  62. package/public/assets/cobol-nwyudZeR.js +1 -0
  63. package/public/assets/codeowners-Bp6g37R7.js +1 -0
  64. package/public/assets/codeql-DsOJ9woJ.js +1 -0
  65. package/public/assets/coffee-Ch7k5sss.js +1 -0
  66. package/public/assets/common-lisp-Cg-RD9OK.js +1 -0
  67. package/public/assets/coq-DkFqJrB1.js +1 -0
  68. package/public/assets/cpp-CofmeUqb.js +1 -0
  69. package/public/assets/crystal-tKQVLTB8.js +1 -0
  70. package/public/assets/csharp-CX12Zw3r.js +1 -0
  71. package/public/assets/css-DPfMkruS.js +1 -0
  72. package/public/assets/csv-fuZLfV_i.js +1 -0
  73. package/public/assets/cue-D82EKSYY.js +1 -0
  74. package/public/assets/cypher-COkxafJQ.js +1 -0
  75. package/public/assets/d-85-TOEBH.js +1 -0
  76. package/public/assets/dark-plus-eOWES_5F.js +1 -0
  77. package/public/assets/dart-CF10PKvl.js +1 -0
  78. package/public/assets/dax-CEL-wOlO.js +1 -0
  79. package/public/assets/desktop-BmXAJ9_W.js +1 -0
  80. package/public/assets/diff-D97Zzqfu.js +1 -0
  81. package/public/assets/docker-BcOcwvcX.js +1 -0
  82. package/public/assets/dotenv-Da5cRb03.js +1 -0
  83. package/public/assets/dracula-BzJJZx-M.js +1 -0
  84. package/public/assets/dracula-soft-BXkSAIEj.js +1 -0
  85. package/public/assets/dream-maker-BtqSS_iP.js +1 -0
  86. package/public/assets/edge-BkV0erSs.js +1 -0
  87. package/public/assets/elixir-CDX3lj18.js +1 -0
  88. package/public/assets/elm-DbKCFpqz.js +1 -0
  89. package/public/assets/emacs-lisp-C9XAeP06.js +1 -0
  90. package/public/assets/erb-BOJIQeun.js +1 -0
  91. package/public/assets/erlang-DsQrWhSR.js +1 -0
  92. package/public/assets/everforest-dark-BgDCqdQA.js +1 -0
  93. package/public/assets/everforest-light-C8M2exoo.js +1 -0
  94. package/public/assets/fennel-BYunw83y.js +1 -0
  95. package/public/assets/fish-BvzEVeQv.js +1 -0
  96. package/public/assets/fluent-C4IJs8-o.js +1 -0
  97. package/public/assets/fortran-fixed-form-BZjJHVRy.js +1 -0
  98. package/public/assets/fortran-free-form-D22FLkUw.js +1 -0
  99. package/public/assets/fsharp-CXgrBDvD.js +1 -0
  100. package/public/assets/gdresource-B7Tvp0Sc.js +1 -0
  101. package/public/assets/gdscript-DTMYz4Jt.js +1 -0
  102. package/public/assets/gdshader-DkwncUOv.js +1 -0
  103. package/public/assets/genie-D0YGMca9.js +1 -0
  104. package/public/assets/gherkin-DyxjwDmM.js +1 -0
  105. package/public/assets/git-commit-F4YmCXRG.js +1 -0
  106. package/public/assets/git-rebase-r7XF79zn.js +1 -0
  107. package/public/assets/github-dark-DHJKELXO.js +1 -0
  108. package/public/assets/github-dark-default-Cuk6v7N8.js +1 -0
  109. package/public/assets/github-dark-dimmed-DH5Ifo-i.js +1 -0
  110. package/public/assets/github-dark-high-contrast-E3gJ1_iC.js +1 -0
  111. package/public/assets/github-light-DAi9KRSo.js +1 -0
  112. package/public/assets/github-light-default-D7oLnXFd.js +1 -0
  113. package/public/assets/github-light-high-contrast-BfjtVDDH.js +1 -0
  114. package/public/assets/gleam-BspZqrRM.js +1 -0
  115. package/public/assets/glimmer-js-Rg0-pVw9.js +1 -0
  116. package/public/assets/glimmer-ts-U6CK756n.js +1 -0
  117. package/public/assets/glsl-DplSGwfg.js +1 -0
  118. package/public/assets/gnuplot-DdkO51Og.js +1 -0
  119. package/public/assets/go-Dn2_MT6a.js +1 -0
  120. package/public/assets/graphql-ChdNCCLP.js +1 -0
  121. package/public/assets/groovy-gcz8RCvz.js +1 -0
  122. package/public/assets/gruvbox-dark-hard-CFHQjOhq.js +1 -0
  123. package/public/assets/gruvbox-dark-medium-GsRaNv29.js +1 -0
  124. package/public/assets/gruvbox-dark-soft-CVdnzihN.js +1 -0
  125. package/public/assets/gruvbox-light-hard-CH1njM8p.js +1 -0
  126. package/public/assets/gruvbox-light-medium-DRw_LuNl.js +1 -0
  127. package/public/assets/gruvbox-light-soft-hJgmCMqR.js +1 -0
  128. package/public/assets/hack-CaT9iCJl.js +1 -0
  129. package/public/assets/haml-B8DHNrY2.js +1 -0
  130. package/public/assets/handlebars-BL8al0AC.js +1 -0
  131. package/public/assets/haskell-Df6bDoY_.js +1 -0
  132. package/public/assets/haxe-CzTSHFRz.js +1 -0
  133. package/public/assets/hcl-BWvSN4gD.js +1 -0
  134. package/public/assets/hjson-D5-asLiD.js +1 -0
  135. package/public/assets/hlsl-D3lLCCz7.js +1 -0
  136. package/public/assets/houston-DnULxvSX.js +1 -0
  137. package/public/assets/html-GMplVEZG.js +1 -0
  138. package/public/assets/html-derivative-BFtXZ54Q.js +1 -0
  139. package/public/assets/http-jrhK8wxY.js +1 -0
  140. package/public/assets/hurl-irOxFIW8.js +1 -0
  141. package/public/assets/hxml-Bvhsp5Yf.js +1 -0
  142. package/public/assets/hy-DFXneXwc.js +1 -0
  143. package/public/assets/imba-DGztddWO.js +1 -0
  144. package/public/assets/index-CoTu_3WL.js +147 -0
  145. package/public/assets/index-Cyy59ha1.css +19 -0
  146. package/public/assets/ini-BEwlwnbL.js +1 -0
  147. package/public/assets/java-CylS5w8V.js +1 -0
  148. package/public/assets/javascript-wDzz0qaB.js +1 -0
  149. package/public/assets/jinja-4LBKfQ-Z.js +1 -0
  150. package/public/assets/jison-wvAkD_A8.js +1 -0
  151. package/public/assets/json-Cp-IABpG.js +1 -0
  152. package/public/assets/json5-C9tS-k6U.js +1 -0
  153. package/public/assets/jsonc-Des-eS-w.js +1 -0
  154. package/public/assets/jsonl-DcaNXYhu.js +1 -0
  155. package/public/assets/jsonnet-DFQXde-d.js +1 -0
  156. package/public/assets/jssm-C2t-YnRu.js +1 -0
  157. package/public/assets/jsx-g9-lgVsj.js +1 -0
  158. package/public/assets/julia-C8NyazO9.js +1 -0
  159. package/public/assets/kanagawa-dragon-CkXjmgJE.js +1 -0
  160. package/public/assets/kanagawa-lotus-CfQXZHmo.js +1 -0
  161. package/public/assets/kanagawa-wave-DWedfzmr.js +1 -0
  162. package/public/assets/kdl-DV7GczEv.js +1 -0
  163. package/public/assets/kotlin-BdnUsdx6.js +1 -0
  164. package/public/assets/kusto-BvAqAH-y.js +1 -0
  165. package/public/assets/laserwave-DUszq2jm.js +1 -0
  166. package/public/assets/latex-BUKiar2Z.js +1 -0
  167. package/public/assets/lean-DP1Csr6i.js +1 -0
  168. package/public/assets/less-B1dDrJ26.js +1 -0
  169. package/public/assets/light-plus-B7mTdjB0.js +1 -0
  170. package/public/assets/liquid-DYVedYrR.js +1 -0
  171. package/public/assets/llvm-BtvRca6l.js +1 -0
  172. package/public/assets/log-2UxHyX5q.js +1 -0
  173. package/public/assets/logo-BtOb2qkB.js +1 -0
  174. package/public/assets/lua-BbnMAYS6.js +1 -0
  175. package/public/assets/luau-CXu1NL6O.js +1 -0
  176. package/public/assets/make-CHLpvVh8.js +1 -0
  177. package/public/assets/markdown-Cvjx9yec.js +1 -0
  178. package/public/assets/marko-CPi9NSCl.js +1 -0
  179. package/public/assets/material-theme-D5KoaKCx.js +1 -0
  180. package/public/assets/material-theme-darker-BfHTSMKl.js +1 -0
  181. package/public/assets/material-theme-lighter-B0m2ddpp.js +1 -0
  182. package/public/assets/material-theme-ocean-CyktbL80.js +1 -0
  183. package/public/assets/material-theme-palenight-Csfq5Kiy.js +1 -0
  184. package/public/assets/matlab-D7o27uSR.js +1 -0
  185. package/public/assets/mdc-DUICxH0z.js +1 -0
  186. package/public/assets/mdx-Cmh6b_Ma.js +1 -0
  187. package/public/assets/mermaid-DKYwYmdq.js +1 -0
  188. package/public/assets/min-dark-CafNBF8u.js +1 -0
  189. package/public/assets/min-light-CTRr51gU.js +1 -0
  190. package/public/assets/mipsasm-CKIfxQSi.js +1 -0
  191. package/public/assets/mojo-1DNp92w6.js +1 -0
  192. package/public/assets/monokai-D4h5O-jR.js +1 -0
  193. package/public/assets/move-Bu9oaDYs.js +1 -0
  194. package/public/assets/narrat-DRg8JJMk.js +1 -0
  195. package/public/assets/nextflow-CUEJCptM.js +1 -0
  196. package/public/assets/nginx-DknmC5AR.js +1 -0
  197. package/public/assets/night-owl-C39BiMTA.js +1 -0
  198. package/public/assets/nim-CVrawwO9.js +1 -0
  199. package/public/assets/nix-BbRYJGeE.js +1 -0
  200. package/public/assets/nord-Ddv68eIx.js +1 -0
  201. package/public/assets/nushell-C-sUppwS.js +1 -0
  202. package/public/assets/objective-c-DXmwc3jG.js +1 -0
  203. package/public/assets/objective-cpp-CLxacb5B.js +1 -0
  204. package/public/assets/ocaml-C0hk2d4L.js +1 -0
  205. package/public/assets/one-dark-pro-DVMEJ2y_.js +1 -0
  206. package/public/assets/one-light-PoHY5YXO.js +1 -0
  207. package/public/assets/pascal-D93ZcfNL.js +1 -0
  208. package/public/assets/perl-C0TMdlhV.js +1 -0
  209. package/public/assets/php-CDn_0X-4.js +1 -0
  210. package/public/assets/pkl-u5AG7uiY.js +1 -0
  211. package/public/assets/plastic-3e1v2bzS.js +1 -0
  212. package/public/assets/plsql-ChMvpjG-.js +1 -0
  213. package/public/assets/po-BTJTHyun.js +1 -0
  214. package/public/assets/poimandres-CS3Unz2-.js +1 -0
  215. package/public/assets/polar-C0HS_06l.js +1 -0
  216. package/public/assets/postcss-CXtECtnM.js +1 -0
  217. package/public/assets/powerquery-CEu0bR-o.js +1 -0
  218. package/public/assets/powershell-Dpen1YoG.js +1 -0
  219. package/public/assets/prisma-Dd19v3D-.js +1 -0
  220. package/public/assets/prolog-CbFg5uaA.js +1 -0
  221. package/public/assets/proto-DyJlTyXw.js +1 -0
  222. package/public/assets/pug-CGlum2m_.js +1 -0
  223. package/public/assets/puppet-BMWR74SV.js +1 -0
  224. package/public/assets/purescript-CklMAg4u.js +1 -0
  225. package/public/assets/python-B6aJPvgy.js +1 -0
  226. package/public/assets/qml-3beO22l8.js +1 -0
  227. package/public/assets/qmldir-C8lEn-DE.js +1 -0
  228. package/public/assets/qss-IeuSbFQv.js +1 -0
  229. package/public/assets/r-DiinP2Uv.js +1 -0
  230. package/public/assets/racket-BqYA7rlc.js +1 -0
  231. package/public/assets/raku-DXvB9xmW.js +1 -0
  232. package/public/assets/razor-WgofotgN.js +1 -0
  233. package/public/assets/red-bN70gL4F.js +1 -0
  234. package/public/assets/reg-C-SQnVFl.js +1 -0
  235. package/public/assets/regexp-CDVJQ6XC.js +1 -0
  236. package/public/assets/rel-C3B-1QV4.js +1 -0
  237. package/public/assets/riscv-BM1_JUlF.js +1 -0
  238. package/public/assets/rose-pine-BHrmToEH.js +1 -0
  239. package/public/assets/rose-pine-dawn-CnK8MTSM.js +1 -0
  240. package/public/assets/rose-pine-moon-NleAzG8P.js +1 -0
  241. package/public/assets/rosmsg-BJDFO7_C.js +1 -0
  242. package/public/assets/rst-B0xPkSld.js +1 -0
  243. package/public/assets/ruby-BvKwtOVI.js +1 -0
  244. package/public/assets/rust-B1yitclQ.js +1 -0
  245. package/public/assets/sas-cz2c8ADy.js +1 -0
  246. package/public/assets/sass-Cj5Yp3dK.js +1 -0
  247. package/public/assets/scala-C151Ov-r.js +1 -0
  248. package/public/assets/scheme-C98Dy4si.js +1 -0
  249. package/public/assets/scss-OYdSNvt2.js +1 -0
  250. package/public/assets/sdbl-DVxCFoDh.js +1 -0
  251. package/public/assets/shaderlab-Dg9Lc6iA.js +1 -0
  252. package/public/assets/shellscript-Yzrsuije.js +1 -0
  253. package/public/assets/shellsession-BADoaaVG.js +1 -0
  254. package/public/assets/slack-dark-BthQWCQV.js +1 -0
  255. package/public/assets/slack-ochin-DqwNpetd.js +1 -0
  256. package/public/assets/smalltalk-BERRCDM3.js +1 -0
  257. package/public/assets/snazzy-light-Bw305WKR.js +1 -0
  258. package/public/assets/solarized-dark-DXbdFlpD.js +1 -0
  259. package/public/assets/solarized-light-L9t79GZl.js +1 -0
  260. package/public/assets/solidity-BbcW6ACK.js +1 -0
  261. package/public/assets/soy-Brmx7dQM.js +1 -0
  262. package/public/assets/sparql-rVzFXLq3.js +1 -0
  263. package/public/assets/splunk-BtCnVYZw.js +1 -0
  264. package/public/assets/sql-BLtJtn59.js +1 -0
  265. package/public/assets/ssh-config-_ykCGR6B.js +1 -0
  266. package/public/assets/stata-BH5u7GGu.js +1 -0
  267. package/public/assets/stylus-BEDo0Tqx.js +1 -0
  268. package/public/assets/svelte-3Dk4HxPD.js +1 -0
  269. package/public/assets/swift-Dg5xB15N.js +1 -0
  270. package/public/assets/synthwave-84-CbfX1IO0.js +1 -0
  271. package/public/assets/system-verilog-CnnmHF94.js +1 -0
  272. package/public/assets/systemd-4A_iFExJ.js +1 -0
  273. package/public/assets/talonscript-CkByrt1z.js +1 -0
  274. package/public/assets/tasl-QIJgUcNo.js +1 -0
  275. package/public/assets/tcl-dwOrl1Do.js +1 -0
  276. package/public/assets/templ-W15q3VgB.js +1 -0
  277. package/public/assets/terraform-BETggiCN.js +1 -0
  278. package/public/assets/tex-Cppo0RY3.js +1 -0
  279. package/public/assets/tokyo-night-hegEt444.js +1 -0
  280. package/public/assets/toml-vGWfd6FD.js +1 -0
  281. package/public/assets/ts-tags-zn1MmPIZ.js +1 -0
  282. package/public/assets/tsv-B_m7g4N7.js +1 -0
  283. package/public/assets/tsx-COt5Ahok.js +1 -0
  284. package/public/assets/turtle-BsS91CYL.js +1 -0
  285. package/public/assets/twig-CO9l9SDP.js +1 -0
  286. package/public/assets/typescript-BPQ3VLAy.js +1 -0
  287. package/public/assets/typespec-Df68jz8_.js +1 -0
  288. package/public/assets/typst-DHCkPAjA.js +1 -0
  289. package/public/assets/v-BcVCzyr7.js +1 -0
  290. package/public/assets/vala-CsfeWuGM.js +1 -0
  291. package/public/assets/vb-D17OF-Vu.js +1 -0
  292. package/public/assets/verilog-BQ8w6xss.js +1 -0
  293. package/public/assets/vesper-DU1UobuO.js +1 -0
  294. package/public/assets/vhdl-CeAyd5Ju.js +1 -0
  295. package/public/assets/viml-CJc9bBzg.js +1 -0
  296. package/public/assets/vitesse-black-Bkuqu6BP.js +1 -0
  297. package/public/assets/vitesse-dark-D0r3Knsf.js +1 -0
  298. package/public/assets/vitesse-light-CVO1_9PV.js +1 -0
  299. package/public/assets/vue-CCoi5OLL.js +1 -0
  300. package/public/assets/vue-html-DAAvJJDi.js +1 -0
  301. package/public/assets/vue-vine-_Ih-lPRR.js +1 -0
  302. package/public/assets/vyper-CDx5xZoG.js +1 -0
  303. package/public/assets/wasm-CG6Dc4jp.js +1 -0
  304. package/public/assets/wasm-MzD3tlZU.js +1 -0
  305. package/public/assets/wenyan-BV7otONQ.js +1 -0
  306. package/public/assets/wgsl-Dx-B1_4e.js +1 -0
  307. package/public/assets/wikitext-BhOHFoWU.js +1 -0
  308. package/public/assets/wit-5i3qLPDT.js +1 -0
  309. package/public/assets/wolfram-lXgVvXCa.js +1 -0
  310. package/public/assets/xml-sdJ4AIDG.js +1 -0
  311. package/public/assets/xsl-CtQFsRM5.js +1 -0
  312. package/public/assets/yaml-Buea-lGh.js +1 -0
  313. package/public/assets/zenscript-DVFEvuxE.js +1 -0
  314. package/public/assets/zig-VOosw3JB.js +1 -0
  315. package/public/index.html +44 -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,142 @@
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 { BinaryRegistry } from "./config/binaries";
13
+ import { FileSystemBrowser } from "./filesystem/browser";
14
+ import { EventBus } from "./events/bus";
15
+ import { InstanceStore } from "./storage/instance-store";
16
+ import { createLogger } from "./logger";
17
+ import { launchInBrowser } from "./launcher";
18
+ const require = createRequire(import.meta.url);
19
+ const packageJson = require("../package.json");
20
+ const __filename = fileURLToPath(import.meta.url);
21
+ const __dirname = path.dirname(__filename);
22
+ const DEFAULT_UI_STATIC_DIR = path.resolve(__dirname, "../public");
23
+ const DEFAULT_PORT = 9898;
24
+ const DEFAULT_HOST = "127.0.0.1";
25
+ const DEFAULT_CONFIG_PATH = "~/.config/codenomad/config.json";
26
+ function parseCliOptions(argv) {
27
+ const program = new Command()
28
+ .name("codenomad")
29
+ .description("CodeNomad CLI server")
30
+ .version(packageJson.version, "-v, --version", "Show the CLI version")
31
+ .addOption(new Option("--host <host>", "Host interface to bind").env("CLI_HOST").default(DEFAULT_HOST))
32
+ .addOption(new Option("--port <number>", "Port for the HTTP server").env("CLI_PORT").default(DEFAULT_PORT).argParser(parsePort))
33
+ .addOption(new Option("--workspace-root <path>", "Workspace root directory").env("CLI_WORKSPACE_ROOT").default(process.cwd()))
34
+ .addOption(new Option("--root <path>").env("CLI_ROOT").hideHelp(true))
35
+ .addOption(new Option("--unrestricted-root", "Allow browsing the full filesystem").env("CLI_UNRESTRICTED_ROOT").default(false))
36
+ .addOption(new Option("--config <path>", "Path to the config file").env("CLI_CONFIG").default(DEFAULT_CONFIG_PATH))
37
+ .addOption(new Option("--log-level <level>", "Log level (trace|debug|info|warn|error)").env("CLI_LOG_LEVEL"))
38
+ .addOption(new Option("--log-destination <path>", "Log destination file (defaults to stdout)").env("CLI_LOG_DESTINATION"))
39
+ .addOption(new Option("--ui-dir <path>", "Directory containing the built UI bundle").env("CLI_UI_DIR").default(DEFAULT_UI_STATIC_DIR))
40
+ .addOption(new Option("--ui-dev-server <url>", "Proxy UI requests to a running dev server").env("CLI_UI_DEV_SERVER"))
41
+ .addOption(new Option("--launch", "Launch the UI in a browser after start").env("CLI_LAUNCH").default(false));
42
+ program.parse(argv, { from: "user" });
43
+ const parsed = program.opts();
44
+ const resolvedRoot = parsed.workspaceRoot ?? parsed.root ?? process.cwd();
45
+ return {
46
+ port: parsed.port,
47
+ host: parsed.host,
48
+ rootDir: resolvedRoot,
49
+ configPath: parsed.config,
50
+ unrestrictedRoot: Boolean(parsed.unrestrictedRoot),
51
+ logLevel: parsed.logLevel,
52
+ logDestination: parsed.logDestination,
53
+ uiStaticDir: parsed.uiDir,
54
+ uiDevServer: parsed.uiDevServer,
55
+ launch: Boolean(parsed.launch),
56
+ };
57
+ }
58
+ function parsePort(input) {
59
+ const value = Number(input);
60
+ if (!Number.isInteger(value) || value < 0 || value > 65535) {
61
+ throw new InvalidArgumentError("Port must be an integer between 0 and 65535");
62
+ }
63
+ return value;
64
+ }
65
+ async function main() {
66
+ const options = parseCliOptions(process.argv.slice(2));
67
+ const logger = createLogger({ level: options.logLevel, destination: options.logDestination, component: "app" });
68
+ const workspaceLogger = logger.child({ component: "workspace" });
69
+ const configLogger = logger.child({ component: "config" });
70
+ const eventLogger = logger.child({ component: "events" });
71
+ logger.info({ options }, "Starting CodeNomad CLI server");
72
+ const eventBus = new EventBus(eventLogger);
73
+ const configStore = new ConfigStore(options.configPath, eventBus, configLogger);
74
+ const binaryRegistry = new BinaryRegistry(configStore, eventBus, configLogger);
75
+ const workspaceManager = new WorkspaceManager({
76
+ rootDir: options.rootDir,
77
+ configStore,
78
+ binaryRegistry,
79
+ eventBus,
80
+ logger: workspaceLogger,
81
+ });
82
+ const fileSystemBrowser = new FileSystemBrowser({ rootDir: options.rootDir, unrestricted: options.unrestrictedRoot });
83
+ const instanceStore = new InstanceStore();
84
+ const serverMeta = {
85
+ httpBaseUrl: `http://${options.host}:${options.port}`,
86
+ eventsUrl: `/api/events`,
87
+ hostLabel: options.host,
88
+ workspaceRoot: options.rootDir,
89
+ };
90
+ const server = createHttpServer({
91
+ host: options.host,
92
+ port: options.port,
93
+ workspaceManager,
94
+ configStore,
95
+ binaryRegistry,
96
+ fileSystemBrowser,
97
+ eventBus,
98
+ serverMeta,
99
+ instanceStore,
100
+ uiStaticDir: options.uiStaticDir,
101
+ uiDevServerUrl: options.uiDevServer,
102
+ logger,
103
+ });
104
+ const startInfo = await server.start();
105
+ logger.info({ port: startInfo.port, host: options.host }, "HTTP server listening");
106
+ console.log(`CodeNomad Server is ready at ${startInfo.url}`);
107
+ if (options.launch) {
108
+ await launchInBrowser(startInfo.url, logger.child({ component: "launcher" }));
109
+ }
110
+ let shuttingDown = false;
111
+ const shutdown = async () => {
112
+ if (shuttingDown) {
113
+ logger.info("Shutdown already in progress, ignoring signal");
114
+ return;
115
+ }
116
+ shuttingDown = true;
117
+ logger.info("Received shutdown signal, closing server");
118
+ try {
119
+ await server.stop();
120
+ logger.info("HTTP server stopped");
121
+ }
122
+ catch (error) {
123
+ logger.error({ err: error }, "Failed to stop HTTP server");
124
+ }
125
+ try {
126
+ await workspaceManager.shutdown();
127
+ logger.info("Workspace manager shutdown complete");
128
+ }
129
+ catch (error) {
130
+ logger.error({ err: error }, "Workspace manager shutdown failed");
131
+ }
132
+ logger.info("Exiting process");
133
+ process.exit(0);
134
+ };
135
+ process.on("SIGINT", shutdown);
136
+ process.on("SIGTERM", shutdown);
137
+ }
138
+ main().catch((error) => {
139
+ const logger = createLogger({ component: "app" });
140
+ logger.error({ err: error }, "CLI server crashed");
141
+ process.exit(1);
142
+ });
@@ -0,0 +1,149 @@
1
+ import { spawn } from "child_process";
2
+ import os from "os";
3
+ import path from "path";
4
+ const APP_ARGS = (url) => [`--app=${url}`, "--new-window"];
5
+ export async function launchInBrowser(url, logger) {
6
+ const { platform, candidates, manualExamples } = buildPlatformCandidates(url);
7
+ console.log(`Attempting to launch browser (${platform}) using:`);
8
+ candidates.forEach((candidate) => console.log(` - ${candidate.name}: ${candidate.command}`));
9
+ for (const candidate of candidates) {
10
+ const success = await tryLaunch(candidate, url, logger);
11
+ if (success) {
12
+ return true;
13
+ }
14
+ }
15
+ console.error("No supported browser found to launch. Run without --launch and use one of the commands below or install a compatible browser.");
16
+ if (manualExamples.length > 0) {
17
+ console.error("Manual launch commands:");
18
+ manualExamples.forEach((line) => console.error(` ${line}`));
19
+ }
20
+ return false;
21
+ }
22
+ async function tryLaunch(candidate, url, logger) {
23
+ return new Promise((resolve) => {
24
+ let resolved = false;
25
+ try {
26
+ const args = candidate.args(url);
27
+ const child = spawn(candidate.command, args, { stdio: "ignore", detached: true });
28
+ child.once("error", (error) => {
29
+ if (resolved)
30
+ return;
31
+ resolved = true;
32
+ logger.debug({ err: error, candidate: candidate.name, command: candidate.command, args }, "Browser launch failed");
33
+ resolve(false);
34
+ });
35
+ child.once("spawn", () => {
36
+ if (resolved)
37
+ return;
38
+ resolved = true;
39
+ logger.info({
40
+ browser: candidate.name,
41
+ command: candidate.command,
42
+ args,
43
+ fullCommand: [candidate.command, ...args].join(" "),
44
+ }, "Launched browser in app mode");
45
+ child.unref();
46
+ resolve(true);
47
+ });
48
+ }
49
+ catch (error) {
50
+ if (resolved)
51
+ return;
52
+ resolved = true;
53
+ logger.debug({ err: error, candidate: candidate.name, command: candidate.command }, "Browser spawn threw");
54
+ resolve(false);
55
+ }
56
+ });
57
+ }
58
+ function buildPlatformCandidates(url) {
59
+ switch (os.platform()) {
60
+ case "darwin":
61
+ return {
62
+ platform: "macOS",
63
+ candidates: buildMacCandidates(),
64
+ manualExamples: buildMacManualExamples(url),
65
+ };
66
+ case "win32":
67
+ return {
68
+ platform: "Windows",
69
+ candidates: buildWindowsCandidates(),
70
+ manualExamples: buildWindowsManualExamples(url),
71
+ };
72
+ default:
73
+ return {
74
+ platform: "Linux",
75
+ candidates: buildLinuxCandidates(),
76
+ manualExamples: buildLinuxManualExamples(url),
77
+ };
78
+ }
79
+ }
80
+ function buildMacCandidates() {
81
+ const apps = [
82
+ { name: "Google Chrome", path: "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" },
83
+ { name: "Google Chrome Canary", path: "/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary" },
84
+ { name: "Microsoft Edge", path: "/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge" },
85
+ { name: "Brave Browser", path: "/Applications/Brave Browser.app/Contents/MacOS/Brave Browser" },
86
+ { name: "Chromium", path: "/Applications/Chromium.app/Contents/MacOS/Chromium" },
87
+ { name: "Vivaldi", path: "/Applications/Vivaldi.app/Contents/MacOS/Vivaldi" },
88
+ { name: "Arc", path: "/Applications/Arc.app/Contents/MacOS/Arc" },
89
+ ];
90
+ return apps.map((entry) => ({ name: entry.name, command: entry.path, args: APP_ARGS }));
91
+ }
92
+ function buildWindowsCandidates() {
93
+ const programFiles = process.env["ProgramFiles"];
94
+ const programFilesX86 = process.env["ProgramFiles(x86)"];
95
+ const localAppData = process.env["LocalAppData"];
96
+ const paths = [
97
+ [programFiles, "Google/Chrome/Application/chrome.exe", "Google Chrome"],
98
+ [programFilesX86, "Google/Chrome/Application/chrome.exe", "Google Chrome (x86)"],
99
+ [localAppData, "Google/Chrome/Application/chrome.exe", "Google Chrome (User)"],
100
+ [programFiles, "Microsoft/Edge/Application/msedge.exe", "Microsoft Edge"],
101
+ [programFilesX86, "Microsoft/Edge/Application/msedge.exe", "Microsoft Edge (x86)"],
102
+ [localAppData, "Microsoft/Edge/Application/msedge.exe", "Microsoft Edge (User)"],
103
+ [programFiles, "BraveSoftware/Brave-Browser/Application/brave.exe", "Brave"],
104
+ [localAppData, "BraveSoftware/Brave-Browser/Application/brave.exe", "Brave (User)"],
105
+ [programFiles, "Chromium/Application/chromium.exe", "Chromium"],
106
+ ];
107
+ return paths
108
+ .filter(([root]) => Boolean(root))
109
+ .map(([root, rel, name]) => ({
110
+ name,
111
+ command: path.join(root, rel),
112
+ args: APP_ARGS,
113
+ }));
114
+ }
115
+ function buildLinuxCandidates() {
116
+ const names = [
117
+ "google-chrome",
118
+ "google-chrome-stable",
119
+ "chromium",
120
+ "chromium-browser",
121
+ "brave-browser",
122
+ "microsoft-edge",
123
+ "microsoft-edge-stable",
124
+ "vivaldi",
125
+ ];
126
+ return names.map((name) => ({ name, command: name, args: APP_ARGS }));
127
+ }
128
+ function buildMacManualExamples(url) {
129
+ return [
130
+ `"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --app="${url}" --new-window`,
131
+ `"/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge" --app="${url}" --new-window`,
132
+ `"/Applications/Brave Browser.app/Contents/MacOS/Brave Browser" --app="${url}" --new-window`,
133
+ ];
134
+ }
135
+ function buildWindowsManualExamples(url) {
136
+ return [
137
+ `"%ProgramFiles%\\Google\\Chrome\\Application\\chrome.exe" --app="${url}" --new-window`,
138
+ `"%ProgramFiles%\\Microsoft\\Edge\\Application\\msedge.exe" --app="${url}" --new-window`,
139
+ `"%ProgramFiles%\\BraveSoftware\\Brave-Browser\\Application\\brave.exe" --app="${url}" --new-window`,
140
+ ];
141
+ }
142
+ function buildLinuxManualExamples(url) {
143
+ return [
144
+ `google-chrome --app="${url}" --new-window`,
145
+ `chromium --app="${url}" --new-window`,
146
+ `brave-browser --app="${url}" --new-window`,
147
+ `microsoft-edge --app="${url}" --new-window`,
148
+ ];
149
+ }
package/dist/loader.js ADDED
@@ -0,0 +1,21 @@
1
+ export async function resolve(specifier, context, defaultResolve) {
2
+ try {
3
+ return await defaultResolve(specifier, context, defaultResolve);
4
+ }
5
+ catch (error) {
6
+ if (shouldRetry(specifier, error)) {
7
+ const retried = specifier.endsWith(".js") ? specifier : `${specifier}.js`;
8
+ return defaultResolve(retried, context, defaultResolve);
9
+ }
10
+ throw error;
11
+ }
12
+ }
13
+ function shouldRetry(specifier, error) {
14
+ if (!error || error.code !== "ERR_MODULE_NOT_FOUND") {
15
+ return false;
16
+ }
17
+ if (specifier.startsWith("./") || specifier.startsWith("../")) {
18
+ return true;
19
+ }
20
+ return false;
21
+ }
package/dist/logger.js ADDED
@@ -0,0 +1,109 @@
1
+ import { Transform } from "node:stream";
2
+ import pino from "pino";
3
+ const LEVEL_LABELS = {
4
+ 10: "trace",
5
+ 20: "debug",
6
+ 30: "info",
7
+ 40: "warn",
8
+ 50: "error",
9
+ 60: "fatal",
10
+ };
11
+ const LIFECYCLE_COMPONENTS = new Set(["app", "workspace"]);
12
+ const OMITTED_FIELDS = new Set(["time", "msg", "level", "component", "module"]);
13
+ export function createLogger(options = {}) {
14
+ const level = (options.level ?? process.env.CLI_LOG_LEVEL ?? "info").toLowerCase();
15
+ const destination = options.destination ?? process.env.CLI_LOG_DESTINATION ?? "stdout";
16
+ const baseComponent = options.component ?? "app";
17
+ const loggerOptions = {
18
+ level,
19
+ base: { component: baseComponent },
20
+ timestamp: false,
21
+ };
22
+ if (destination && destination !== "stdout") {
23
+ const stream = pino.destination({ dest: destination, mkdir: true, sync: false });
24
+ return pino(loggerOptions, stream);
25
+ }
26
+ const lifecycleStream = new LifecycleLogStream({ restrictInfoToLifecycle: level === "info" });
27
+ lifecycleStream.pipe(process.stdout);
28
+ return pino(loggerOptions, lifecycleStream);
29
+ }
30
+ class LifecycleLogStream extends Transform {
31
+ constructor(options) {
32
+ super();
33
+ this.options = options;
34
+ this.buffer = "";
35
+ }
36
+ _transform(chunk, _encoding, callback) {
37
+ this.buffer += chunk.toString();
38
+ let newlineIndex = this.buffer.indexOf("\n");
39
+ while (newlineIndex >= 0) {
40
+ const line = this.buffer.slice(0, newlineIndex);
41
+ this.buffer = this.buffer.slice(newlineIndex + 1);
42
+ this.pushFormatted(line);
43
+ newlineIndex = this.buffer.indexOf("\n");
44
+ }
45
+ callback();
46
+ }
47
+ _flush(callback) {
48
+ if (this.buffer.length > 0) {
49
+ this.pushFormatted(this.buffer);
50
+ this.buffer = "";
51
+ }
52
+ callback();
53
+ }
54
+ pushFormatted(line) {
55
+ if (!line.trim()) {
56
+ return;
57
+ }
58
+ let entry;
59
+ try {
60
+ entry = JSON.parse(line);
61
+ }
62
+ catch {
63
+ return;
64
+ }
65
+ const levelNumber = typeof entry.level === "number" ? entry.level : 30;
66
+ const levelLabel = LEVEL_LABELS[levelNumber] ?? "info";
67
+ const component = entry.component ?? entry.module ?? "app";
68
+ if (this.options.restrictInfoToLifecycle && levelNumber <= 30 && !LIFECYCLE_COMPONENTS.has(component)) {
69
+ return;
70
+ }
71
+ const message = typeof entry.msg === "string" ? entry.msg : "";
72
+ const metadata = this.formatMetadata(entry);
73
+ const formatted = metadata.length > 0 ? `[${levelLabel.toUpperCase()}] [${component}] ${message} ${metadata}` : `[${levelLabel.toUpperCase()}] [${component}] ${message}`;
74
+ this.push(`${formatted}\n`);
75
+ }
76
+ formatMetadata(entry) {
77
+ const pairs = [];
78
+ for (const [key, value] of Object.entries(entry)) {
79
+ if (OMITTED_FIELDS.has(key)) {
80
+ continue;
81
+ }
82
+ if (key === "err" && value && typeof value === "object") {
83
+ const err = value;
84
+ const errLabel = err.type ?? "Error";
85
+ const errMessage = err.message ? `: ${err.message}` : "";
86
+ pairs.push(`err=${errLabel}${errMessage}`);
87
+ if (err.stack) {
88
+ pairs.push(`stack="${err.stack}"`);
89
+ }
90
+ continue;
91
+ }
92
+ pairs.push(`${key}=${this.stringifyValue(value)}`);
93
+ }
94
+ return pairs.join(" ").trim();
95
+ }
96
+ stringifyValue(value) {
97
+ if (value === undefined)
98
+ return "undefined";
99
+ if (value === null)
100
+ return "null";
101
+ if (typeof value === "string")
102
+ return value;
103
+ if (typeof value === "number" || typeof value === "boolean")
104
+ return String(value);
105
+ if (value instanceof Error)
106
+ return value.message ?? value.name;
107
+ return JSON.stringify(value);
108
+ }
109
+ }