@dyyz1993/codenomad 0.15.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 (496) hide show
  1. package/README.md +173 -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 +140 -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 +576 -0
  10. package/dist/bin.js +24 -0
  11. package/dist/cli-upgrade.js +53 -0
  12. package/dist/cli-upgrade.test.js +31 -0
  13. package/dist/clients/connection-manager.js +93 -0
  14. package/dist/config/location.js +57 -0
  15. package/dist/config/schema.js +71 -0
  16. package/dist/events/bus.js +45 -0
  17. package/dist/filesystem/__tests__/browser.test.js +65 -0
  18. package/dist/filesystem/__tests__/search-cache.test.js +40 -0
  19. package/dist/filesystem/browser.js +306 -0
  20. package/dist/filesystem/search-cache.js +43 -0
  21. package/dist/filesystem/search.js +135 -0
  22. package/dist/index.js +477 -0
  23. package/dist/launcher.js +149 -0
  24. package/dist/loader.js +21 -0
  25. package/dist/logger.js +109 -0
  26. package/dist/opencode-config/README.md +32 -0
  27. package/dist/opencode-config/opencode.jsonc +3 -0
  28. package/dist/opencode-config/package-lock.json +380 -0
  29. package/dist/opencode-config/package.json +9 -0
  30. package/dist/opencode-config/plugin/codenomad.ts +62 -0
  31. package/dist/opencode-config/plugin/lib/background-process.ts +265 -0
  32. package/dist/opencode-config/plugin/lib/client.ts +133 -0
  33. package/dist/opencode-config/plugin/lib/request.ts +214 -0
  34. package/dist/opencode-config.js +26 -0
  35. package/dist/plugins/channel.js +40 -0
  36. package/dist/plugins/handlers.js +17 -0
  37. package/dist/plugins/voice-mode.js +78 -0
  38. package/dist/releases/dev-release-monitor.js +75 -0
  39. package/dist/releases/release-monitor.js +107 -0
  40. package/dist/server/__tests__/network-addresses.test.js +68 -0
  41. package/dist/server/__tests__/remote-proxy.test.js +204 -0
  42. package/dist/server/http-server.js +926 -0
  43. package/dist/server/network-addresses.js +114 -0
  44. package/dist/server/remote-proxy.js +466 -0
  45. package/dist/server/routes/auth-pages/login.html +135 -0
  46. package/dist/server/routes/auth-pages/token.html +93 -0
  47. package/dist/server/routes/auth.js +148 -0
  48. package/dist/server/routes/background-processes.js +78 -0
  49. package/dist/server/routes/events.js +66 -0
  50. package/dist/server/routes/filesystem.js +43 -0
  51. package/dist/server/routes/meta.js +44 -0
  52. package/dist/server/routes/plugin.js +70 -0
  53. package/dist/server/routes/remote-proxy.js +42 -0
  54. package/dist/server/routes/remote-servers.js +142 -0
  55. package/dist/server/routes/settings.js +69 -0
  56. package/dist/server/routes/sidecars.js +46 -0
  57. package/dist/server/routes/speech.js +63 -0
  58. package/dist/server/routes/storage.js +52 -0
  59. package/dist/server/routes/workspaces.js +221 -0
  60. package/dist/server/routes/worktrees.js +156 -0
  61. package/dist/server/tls.js +224 -0
  62. package/dist/settings/binaries.js +37 -0
  63. package/dist/settings/merge-patch.js +33 -0
  64. package/dist/settings/migrate.js +238 -0
  65. package/dist/settings/public-config.js +33 -0
  66. package/dist/settings/service.js +101 -0
  67. package/dist/settings/yaml-doc-store.js +96 -0
  68. package/dist/sidecars/manager.js +193 -0
  69. package/dist/speech/providers/openai-compatible.js +189 -0
  70. package/dist/speech/service.js +58 -0
  71. package/dist/storage/instance-store.js +56 -0
  72. package/dist/ui/__tests__/remote-ui.test.js +67 -0
  73. package/dist/ui/remote-ui.js +462 -0
  74. package/dist/workspaces/__tests__/git-worktrees.test.js +43 -0
  75. package/dist/workspaces/__tests__/spawn.test.js +140 -0
  76. package/dist/workspaces/git-mutations.js +98 -0
  77. package/dist/workspaces/git-status.js +323 -0
  78. package/dist/workspaces/git-worktrees.js +216 -0
  79. package/dist/workspaces/instance-events.js +180 -0
  80. package/dist/workspaces/manager.js +368 -0
  81. package/dist/workspaces/opencode-auth.js +34 -0
  82. package/dist/workspaces/opencode-auth.test.js +34 -0
  83. package/dist/workspaces/runtime.js +366 -0
  84. package/dist/workspaces/spawn.js +219 -0
  85. package/dist/workspaces/worktree-directory.js +74 -0
  86. package/dist/workspaces/worktree-map.js +116 -0
  87. package/package.json +50 -0
  88. package/public/apple-touch-icon-180x180.png +0 -0
  89. package/public/assets/ChangesTab-BRNmSjeC.js +2 -0
  90. package/public/assets/CodeNomad-Icon-bmTWNPXy.png +0 -0
  91. package/public/assets/DiffToolbar-DPPgfx42.js +1 -0
  92. package/public/assets/FilesTab-sEeGPOoz.js +2 -0
  93. package/public/assets/GitChangesTab-tJ-TCq0c.js +2 -0
  94. package/public/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  95. package/public/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  96. package/public/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  97. package/public/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  98. package/public/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  99. package/public/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  100. package/public/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  101. package/public/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  102. package/public/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  103. package/public/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  104. package/public/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  105. package/public/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  106. package/public/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  107. package/public/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  108. package/public/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  109. package/public/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  110. package/public/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  111. package/public/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  112. package/public/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  113. package/public/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  114. package/public/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  115. package/public/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  116. package/public/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  117. package/public/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  118. package/public/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  119. package/public/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  120. package/public/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  121. package/public/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  122. package/public/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  123. package/public/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  124. package/public/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  125. package/public/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  126. package/public/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  127. package/public/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  128. package/public/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  129. package/public/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  130. package/public/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  131. package/public/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  132. package/public/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  133. package/public/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  134. package/public/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  135. package/public/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  136. package/public/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  137. package/public/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  138. package/public/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  139. package/public/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  140. package/public/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  141. package/public/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  142. package/public/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  143. package/public/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  144. package/public/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  145. package/public/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  146. package/public/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  147. package/public/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  148. package/public/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  149. package/public/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  150. package/public/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  151. package/public/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  152. package/public/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  153. package/public/assets/SplitFilePanel-CHqNLZvU.js +1 -0
  154. package/public/assets/StatusTab-DMd0ByCA.js +1 -0
  155. package/public/assets/abap-BdImnpbu.js +1 -0
  156. package/public/assets/actionscript-3-CfeIJUat.js +1 -0
  157. package/public/assets/ada-bCR0ucgS.js +1 -0
  158. package/public/assets/align-justify-BWapkGTe.js +1 -0
  159. package/public/assets/andromeeda-C-Jbm3Hp.js +1 -0
  160. package/public/assets/angular-html-CU67Zn6k.js +1 -0
  161. package/public/assets/angular-ts-BwZT4LLn.js +1 -0
  162. package/public/assets/apache-Pmp26Uib.js +1 -0
  163. package/public/assets/apex-DhZLUxFE.js +1 -0
  164. package/public/assets/apl-dKokRX4l.js +1 -0
  165. package/public/assets/applescript-Co6uUVPk.js +1 -0
  166. package/public/assets/ara-BRHolxvo.js +1 -0
  167. package/public/assets/asciidoc-Dv7Oe6Be.js +1 -0
  168. package/public/assets/asm-D_Q5rh1f.js +1 -0
  169. package/public/assets/astro-CbQHKStN.js +1 -0
  170. package/public/assets/aurora-x-D-2ljcwZ.js +1 -0
  171. package/public/assets/awk-DMzUqQB5.js +1 -0
  172. package/public/assets/ayu-dark-Cv9koXgw.js +1 -0
  173. package/public/assets/ballerina-BFfxhgS-.js +1 -0
  174. package/public/assets/bat-BkioyH1T.js +1 -0
  175. package/public/assets/beancount-k_qm7-4y.js +1 -0
  176. package/public/assets/berry-D08WgyRC.js +1 -0
  177. package/public/assets/bibtex-CHM0blh-.js +1 -0
  178. package/public/assets/bicep-Bmn6On1c.js +1 -0
  179. package/public/assets/blade-DVc8C-J4.js +1 -0
  180. package/public/assets/bsl-BO_Y6i37.js +1 -0
  181. package/public/assets/bundle-full-CXlKQh5B.js +13 -0
  182. package/public/assets/c-BIGW1oBm.js +1 -0
  183. package/public/assets/cadence-Bv_4Rxtq.js +1 -0
  184. package/public/assets/cairo-KRGpt6FW.js +1 -0
  185. package/public/assets/catppuccin-frappe-DFWUc33u.js +1 -0
  186. package/public/assets/catppuccin-latte-C9dUb6Cb.js +1 -0
  187. package/public/assets/catppuccin-macchiato-DQyhUUbL.js +1 -0
  188. package/public/assets/catppuccin-mocha-D87Tk5Gz.js +1 -0
  189. package/public/assets/clarity-D53aC0YG.js +1 -0
  190. package/public/assets/clojure-P80f7IUj.js +1 -0
  191. package/public/assets/cmake-D1j8_8rp.js +1 -0
  192. package/public/assets/cobol-nwyudZeR.js +1 -0
  193. package/public/assets/codeowners-Bp6g37R7.js +1 -0
  194. package/public/assets/codeql-DsOJ9woJ.js +1 -0
  195. package/public/assets/coffee-Ch7k5sss.js +1 -0
  196. package/public/assets/common-lisp-Cg-RD9OK.js +1 -0
  197. package/public/assets/coq-DkFqJrB1.js +1 -0
  198. package/public/assets/cpp-CofmeUqb.js +1 -0
  199. package/public/assets/crystal-tKQVLTB8.js +1 -0
  200. package/public/assets/csharp-CX12Zw3r.js +1 -0
  201. package/public/assets/css-DPfMkruS.js +1 -0
  202. package/public/assets/csv-fuZLfV_i.js +1 -0
  203. package/public/assets/cue-D82EKSYY.js +1 -0
  204. package/public/assets/cypher-COkxafJQ.js +1 -0
  205. package/public/assets/d-85-TOEBH.js +1 -0
  206. package/public/assets/dark-plus-eOWES_5F.js +1 -0
  207. package/public/assets/dart-CF10PKvl.js +1 -0
  208. package/public/assets/dax-CEL-wOlO.js +1 -0
  209. package/public/assets/desktop-BmXAJ9_W.js +1 -0
  210. package/public/assets/diff-D97Zzqfu.js +1 -0
  211. package/public/assets/diff-viewer-BFtW5J8P.js +1 -0
  212. package/public/assets/docker-BcOcwvcX.js +1 -0
  213. package/public/assets/dotenv-Da5cRb03.js +1 -0
  214. package/public/assets/dracula-BzJJZx-M.js +1 -0
  215. package/public/assets/dracula-soft-BXkSAIEj.js +1 -0
  216. package/public/assets/dream-maker-BtqSS_iP.js +1 -0
  217. package/public/assets/edge-BkV0erSs.js +1 -0
  218. package/public/assets/elixir-CDX3lj18.js +1 -0
  219. package/public/assets/elm-DbKCFpqz.js +1 -0
  220. package/public/assets/emacs-lisp-C9XAeP06.js +1 -0
  221. package/public/assets/erb-BOJIQeun.js +1 -0
  222. package/public/assets/erlang-DsQrWhSR.js +1 -0
  223. package/public/assets/everforest-dark-BgDCqdQA.js +1 -0
  224. package/public/assets/everforest-light-C8M2exoo.js +1 -0
  225. package/public/assets/fast-diff-vendor-DgdwVvTQ.js +1 -0
  226. package/public/assets/fennel-BYunw83y.js +1 -0
  227. package/public/assets/fish-BvzEVeQv.js +1 -0
  228. package/public/assets/fluent-C4IJs8-o.js +1 -0
  229. package/public/assets/fortran-fixed-form-BZjJHVRy.js +1 -0
  230. package/public/assets/fortran-free-form-D22FLkUw.js +1 -0
  231. package/public/assets/fsharp-CXgrBDvD.js +1 -0
  232. package/public/assets/gdresource-B7Tvp0Sc.js +1 -0
  233. package/public/assets/gdscript-DTMYz4Jt.js +1 -0
  234. package/public/assets/gdshader-DkwncUOv.js +1 -0
  235. package/public/assets/genie-D0YGMca9.js +1 -0
  236. package/public/assets/gherkin-DyxjwDmM.js +1 -0
  237. package/public/assets/git-commit-F4YmCXRG.js +1 -0
  238. package/public/assets/git-diff-vendor-CSgooKT_.js +52 -0
  239. package/public/assets/git-diff-vendor-HAZkIolJ.css +19 -0
  240. package/public/assets/git-rebase-r7XF79zn.js +1 -0
  241. package/public/assets/github-dark-DHJKELXO.js +1 -0
  242. package/public/assets/github-dark-default-Cuk6v7N8.js +1 -0
  243. package/public/assets/github-dark-dimmed-DH5Ifo-i.js +1 -0
  244. package/public/assets/github-dark-high-contrast-E3gJ1_iC.js +1 -0
  245. package/public/assets/github-light-DAi9KRSo.js +1 -0
  246. package/public/assets/github-light-default-D7oLnXFd.js +1 -0
  247. package/public/assets/github-light-high-contrast-BfjtVDDH.js +1 -0
  248. package/public/assets/gleam-BspZqrRM.js +1 -0
  249. package/public/assets/glimmer-js-Rg0-pVw9.js +1 -0
  250. package/public/assets/glimmer-ts-U6CK756n.js +1 -0
  251. package/public/assets/glsl-DplSGwfg.js +1 -0
  252. package/public/assets/gnuplot-DdkO51Og.js +1 -0
  253. package/public/assets/go-Dn2_MT6a.js +1 -0
  254. package/public/assets/graphql-ChdNCCLP.js +1 -0
  255. package/public/assets/groovy-gcz8RCvz.js +1 -0
  256. package/public/assets/gruvbox-dark-hard-CFHQjOhq.js +1 -0
  257. package/public/assets/gruvbox-dark-medium-GsRaNv29.js +1 -0
  258. package/public/assets/gruvbox-dark-soft-CVdnzihN.js +1 -0
  259. package/public/assets/gruvbox-light-hard-CH1njM8p.js +1 -0
  260. package/public/assets/gruvbox-light-medium-DRw_LuNl.js +1 -0
  261. package/public/assets/gruvbox-light-soft-hJgmCMqR.js +1 -0
  262. package/public/assets/hack-CaT9iCJl.js +1 -0
  263. package/public/assets/haml-B8DHNrY2.js +1 -0
  264. package/public/assets/handlebars-BL8al0AC.js +1 -0
  265. package/public/assets/haskell-Df6bDoY_.js +1 -0
  266. package/public/assets/haxe-CzTSHFRz.js +1 -0
  267. package/public/assets/hcl-BWvSN4gD.js +1 -0
  268. package/public/assets/highlight-vendor-8FKMu9os.js +10 -0
  269. package/public/assets/hjson-D5-asLiD.js +1 -0
  270. package/public/assets/hlsl-D3lLCCz7.js +1 -0
  271. package/public/assets/houston-DnULxvSX.js +1 -0
  272. package/public/assets/html-GMplVEZG.js +1 -0
  273. package/public/assets/html-derivative-BFtXZ54Q.js +1 -0
  274. package/public/assets/http-jrhK8wxY.js +1 -0
  275. package/public/assets/hurl-irOxFIW8.js +1 -0
  276. package/public/assets/hxml-Bvhsp5Yf.js +1 -0
  277. package/public/assets/hy-DFXneXwc.js +1 -0
  278. package/public/assets/imba-DGztddWO.js +1 -0
  279. package/public/assets/index-Bdy3MTIn.js +1 -0
  280. package/public/assets/index-BvRe9GiS.js +1 -0
  281. package/public/assets/index-Ctq8RqRf.js +1 -0
  282. package/public/assets/index-D-NvysdX.js +1 -0
  283. package/public/assets/index-D6RMBXUk.js +2 -0
  284. package/public/assets/index-DXI9DoVB.css +1 -0
  285. package/public/assets/index-DYWkPhKo.js +1 -0
  286. package/public/assets/index-D_FDiI6a.js +1 -0
  287. package/public/assets/index-Dty5bSHf.js +1 -0
  288. package/public/assets/index-H16e4Rqc.js +1 -0
  289. package/public/assets/ini-BEwlwnbL.js +1 -0
  290. package/public/assets/java-CylS5w8V.js +1 -0
  291. package/public/assets/javascript-wDzz0qaB.js +1 -0
  292. package/public/assets/jinja-4LBKfQ-Z.js +1 -0
  293. package/public/assets/jison-wvAkD_A8.js +1 -0
  294. package/public/assets/json-Cp-IABpG.js +1 -0
  295. package/public/assets/json5-C9tS-k6U.js +1 -0
  296. package/public/assets/jsonc-Des-eS-w.js +1 -0
  297. package/public/assets/jsonl-DcaNXYhu.js +1 -0
  298. package/public/assets/jsonnet-DFQXde-d.js +1 -0
  299. package/public/assets/jssm-C2t-YnRu.js +1 -0
  300. package/public/assets/jsx-g9-lgVsj.js +1 -0
  301. package/public/assets/julia-C8NyazO9.js +1 -0
  302. package/public/assets/kanagawa-dragon-CkXjmgJE.js +1 -0
  303. package/public/assets/kanagawa-lotus-CfQXZHmo.js +1 -0
  304. package/public/assets/kanagawa-wave-DWedfzmr.js +1 -0
  305. package/public/assets/kdl-DV7GczEv.js +1 -0
  306. package/public/assets/kotlin-BdnUsdx6.js +1 -0
  307. package/public/assets/kusto-BvAqAH-y.js +1 -0
  308. package/public/assets/laserwave-DUszq2jm.js +1 -0
  309. package/public/assets/latex-BUKiar2Z.js +1 -0
  310. package/public/assets/lean-DP1Csr6i.js +1 -0
  311. package/public/assets/less-B1dDrJ26.js +1 -0
  312. package/public/assets/light-plus-B7mTdjB0.js +1 -0
  313. package/public/assets/liquid-DYVedYrR.js +1 -0
  314. package/public/assets/llvm-BtvRca6l.js +1 -0
  315. package/public/assets/loading-CmEVQgyj.css +1 -0
  316. package/public/assets/loading-W2Y_wR0P.js +1 -0
  317. package/public/assets/log-2UxHyX5q.js +1 -0
  318. package/public/assets/logo-BtOb2qkB.js +1 -0
  319. package/public/assets/lua-BbnMAYS6.js +1 -0
  320. package/public/assets/luau-CXu1NL6O.js +1 -0
  321. package/public/assets/main-Bala0YJ4.js +57 -0
  322. package/public/assets/make-CHLpvVh8.js +1 -0
  323. package/public/assets/markdown-Cvjx9yec.js +1 -0
  324. package/public/assets/markdown-Db8cvZ4Z.js +315 -0
  325. package/public/assets/marko-CPi9NSCl.js +1 -0
  326. package/public/assets/material-theme-D5KoaKCx.js +1 -0
  327. package/public/assets/material-theme-darker-BfHTSMKl.js +1 -0
  328. package/public/assets/material-theme-lighter-B0m2ddpp.js +1 -0
  329. package/public/assets/material-theme-ocean-CyktbL80.js +1 -0
  330. package/public/assets/material-theme-palenight-Csfq5Kiy.js +1 -0
  331. package/public/assets/matlab-D7o27uSR.js +1 -0
  332. package/public/assets/mdc-DUICxH0z.js +1 -0
  333. package/public/assets/mdx-Cmh6b_Ma.js +1 -0
  334. package/public/assets/mermaid-DKYwYmdq.js +1 -0
  335. package/public/assets/min-dark-CafNBF8u.js +1 -0
  336. package/public/assets/min-light-CTRr51gU.js +1 -0
  337. package/public/assets/mipsasm-CKIfxQSi.js +1 -0
  338. package/public/assets/mojo-1DNp92w6.js +1 -0
  339. package/public/assets/monaco-viewer-DWQqXKm3.js +26 -0
  340. package/public/assets/monokai-D4h5O-jR.js +1 -0
  341. package/public/assets/move-Bu9oaDYs.js +1 -0
  342. package/public/assets/narrat-DRg8JJMk.js +1 -0
  343. package/public/assets/nextflow-CUEJCptM.js +1 -0
  344. package/public/assets/nginx-DknmC5AR.js +1 -0
  345. package/public/assets/night-owl-C39BiMTA.js +1 -0
  346. package/public/assets/nim-CVrawwO9.js +1 -0
  347. package/public/assets/nix-BbRYJGeE.js +1 -0
  348. package/public/assets/nord-Ddv68eIx.js +1 -0
  349. package/public/assets/nushell-C-sUppwS.js +1 -0
  350. package/public/assets/objective-c-DXmwc3jG.js +1 -0
  351. package/public/assets/objective-cpp-CLxacb5B.js +1 -0
  352. package/public/assets/ocaml-C0hk2d4L.js +1 -0
  353. package/public/assets/one-dark-pro-DVMEJ2y_.js +1 -0
  354. package/public/assets/one-light-PoHY5YXO.js +1 -0
  355. package/public/assets/pascal-D93ZcfNL.js +1 -0
  356. package/public/assets/perl-C0TMdlhV.js +1 -0
  357. package/public/assets/php-CDn_0X-4.js +1 -0
  358. package/public/assets/pkl-u5AG7uiY.js +1 -0
  359. package/public/assets/plastic-3e1v2bzS.js +1 -0
  360. package/public/assets/plsql-ChMvpjG-.js +1 -0
  361. package/public/assets/po-BTJTHyun.js +1 -0
  362. package/public/assets/poimandres-CS3Unz2-.js +1 -0
  363. package/public/assets/polar-C0HS_06l.js +1 -0
  364. package/public/assets/postcss-CXtECtnM.js +1 -0
  365. package/public/assets/powerquery-CEu0bR-o.js +1 -0
  366. package/public/assets/powershell-Dpen1YoG.js +1 -0
  367. package/public/assets/prisma-Dd19v3D-.js +1 -0
  368. package/public/assets/prolog-CbFg5uaA.js +1 -0
  369. package/public/assets/proto-DyJlTyXw.js +1 -0
  370. package/public/assets/pug-CGlum2m_.js +1 -0
  371. package/public/assets/puppet-BMWR74SV.js +1 -0
  372. package/public/assets/purescript-CklMAg4u.js +1 -0
  373. package/public/assets/python-B6aJPvgy.js +1 -0
  374. package/public/assets/qml-3beO22l8.js +1 -0
  375. package/public/assets/qmldir-C8lEn-DE.js +1 -0
  376. package/public/assets/qss-IeuSbFQv.js +1 -0
  377. package/public/assets/r-DiinP2Uv.js +1 -0
  378. package/public/assets/racket-BqYA7rlc.js +1 -0
  379. package/public/assets/raku-DXvB9xmW.js +1 -0
  380. package/public/assets/razor-WgofotgN.js +1 -0
  381. package/public/assets/red-bN70gL4F.js +1 -0
  382. package/public/assets/reg-C-SQnVFl.js +1 -0
  383. package/public/assets/regexp-CDVJQ6XC.js +1 -0
  384. package/public/assets/rel-C3B-1QV4.js +1 -0
  385. package/public/assets/riscv-BM1_JUlF.js +1 -0
  386. package/public/assets/rose-pine-BHrmToEH.js +1 -0
  387. package/public/assets/rose-pine-dawn-CnK8MTSM.js +1 -0
  388. package/public/assets/rose-pine-moon-NleAzG8P.js +1 -0
  389. package/public/assets/rosmsg-BJDFO7_C.js +1 -0
  390. package/public/assets/rst-B0xPkSld.js +1 -0
  391. package/public/assets/ruby-BvKwtOVI.js +1 -0
  392. package/public/assets/rust-B1yitclQ.js +1 -0
  393. package/public/assets/sas-cz2c8ADy.js +1 -0
  394. package/public/assets/sass-Cj5Yp3dK.js +1 -0
  395. package/public/assets/scala-C151Ov-r.js +1 -0
  396. package/public/assets/scheme-C98Dy4si.js +1 -0
  397. package/public/assets/scss-OYdSNvt2.js +1 -0
  398. package/public/assets/sdbl-DVxCFoDh.js +1 -0
  399. package/public/assets/shaderlab-Dg9Lc6iA.js +1 -0
  400. package/public/assets/shellscript-Yzrsuije.js +1 -0
  401. package/public/assets/shellsession-BADoaaVG.js +1 -0
  402. package/public/assets/slack-dark-BthQWCQV.js +1 -0
  403. package/public/assets/slack-ochin-DqwNpetd.js +1 -0
  404. package/public/assets/smalltalk-BERRCDM3.js +1 -0
  405. package/public/assets/snazzy-light-Bw305WKR.js +1 -0
  406. package/public/assets/solarized-dark-DXbdFlpD.js +1 -0
  407. package/public/assets/solarized-light-L9t79GZl.js +1 -0
  408. package/public/assets/solidity-BbcW6ACK.js +1 -0
  409. package/public/assets/soy-Brmx7dQM.js +1 -0
  410. package/public/assets/sparql-rVzFXLq3.js +1 -0
  411. package/public/assets/splunk-BtCnVYZw.js +1 -0
  412. package/public/assets/sql-BLtJtn59.js +1 -0
  413. package/public/assets/ssh-config-_ykCGR6B.js +1 -0
  414. package/public/assets/stata-BH5u7GGu.js +1 -0
  415. package/public/assets/stylus-BEDo0Tqx.js +1 -0
  416. package/public/assets/svelte-3Dk4HxPD.js +1 -0
  417. package/public/assets/swift-Dg5xB15N.js +1 -0
  418. package/public/assets/synthwave-84-CbfX1IO0.js +1 -0
  419. package/public/assets/system-verilog-CnnmHF94.js +1 -0
  420. package/public/assets/systemd-4A_iFExJ.js +1 -0
  421. package/public/assets/talonscript-CkByrt1z.js +1 -0
  422. package/public/assets/tasl-QIJgUcNo.js +1 -0
  423. package/public/assets/tcl-dwOrl1Do.js +1 -0
  424. package/public/assets/templ-W15q3VgB.js +1 -0
  425. package/public/assets/terraform-BETggiCN.js +1 -0
  426. package/public/assets/tex-Cppo0RY3.js +1 -0
  427. package/public/assets/tokyo-night-hegEt444.js +1 -0
  428. package/public/assets/toml-vGWfd6FD.js +1 -0
  429. package/public/assets/tool-call-D0BYXlFe.js +59 -0
  430. package/public/assets/ts-tags-zn1MmPIZ.js +1 -0
  431. package/public/assets/tsv-B_m7g4N7.js +1 -0
  432. package/public/assets/tsx-COt5Ahok.js +1 -0
  433. package/public/assets/turtle-BsS91CYL.js +1 -0
  434. package/public/assets/twig-CO9l9SDP.js +1 -0
  435. package/public/assets/typescript-BPQ3VLAy.js +1 -0
  436. package/public/assets/typespec-Df68jz8_.js +1 -0
  437. package/public/assets/typst-DHCkPAjA.js +1 -0
  438. package/public/assets/unified-picker-QgONWj_1.js +1 -0
  439. package/public/assets/v-BcVCzyr7.js +1 -0
  440. package/public/assets/vala-CsfeWuGM.js +1 -0
  441. package/public/assets/vb-D17OF-Vu.js +1 -0
  442. package/public/assets/verilog-BQ8w6xss.js +1 -0
  443. package/public/assets/vesper-DU1UobuO.js +1 -0
  444. package/public/assets/vhdl-CeAyd5Ju.js +1 -0
  445. package/public/assets/viml-CJc9bBzg.js +1 -0
  446. package/public/assets/vitesse-black-Bkuqu6BP.js +1 -0
  447. package/public/assets/vitesse-dark-D0r3Knsf.js +1 -0
  448. package/public/assets/vitesse-light-CVO1_9PV.js +1 -0
  449. package/public/assets/vue-CCoi5OLL.js +1 -0
  450. package/public/assets/vue-html-DAAvJJDi.js +1 -0
  451. package/public/assets/vue-vine-_Ih-lPRR.js +1 -0
  452. package/public/assets/vyper-CDx5xZoG.js +1 -0
  453. package/public/assets/wasm-CG6Dc4jp.js +1 -0
  454. package/public/assets/wasm-MzD3tlZU.js +1 -0
  455. package/public/assets/wenyan-BV7otONQ.js +1 -0
  456. package/public/assets/wgsl-Dx-B1_4e.js +1 -0
  457. package/public/assets/wikitext-BhOHFoWU.js +1 -0
  458. package/public/assets/wit-5i3qLPDT.js +1 -0
  459. package/public/assets/wolfram-lXgVvXCa.js +1 -0
  460. package/public/assets/wrap-text-CEH9wOr_.js +1 -0
  461. package/public/assets/xml-sdJ4AIDG.js +1 -0
  462. package/public/assets/xsl-CtQFsRM5.js +1 -0
  463. package/public/assets/yaml-Buea-lGh.js +1 -0
  464. package/public/assets/zenscript-DVFEvuxE.js +1 -0
  465. package/public/assets/zig-VOosw3JB.js +1 -0
  466. package/public/favicon.ico +0 -0
  467. package/public/index.html +42 -0
  468. package/public/loading.html +33 -0
  469. package/public/logo.png +0 -0
  470. package/public/manifest.webmanifest +1 -0
  471. package/public/maskable-icon-512x512.png +0 -0
  472. package/public/monaco/vs/base/browser/ui/codicons/codicon/codicon.ttf +0 -0
  473. package/public/monaco/vs/base/worker/workerMain.js +31 -0
  474. package/public/monaco/vs/basic-languages/cpp/cpp.js +10 -0
  475. package/public/monaco/vs/basic-languages/kotlin/kotlin.js +10 -0
  476. package/public/monaco/vs/basic-languages/markdown/markdown.js +10 -0
  477. package/public/monaco/vs/basic-languages/python/python.js +10 -0
  478. package/public/monaco/vs/editor/editor.main.css +8 -0
  479. package/public/monaco/vs/editor/editor.main.js +798 -0
  480. package/public/monaco/vs/language/css/cssMode.js +13 -0
  481. package/public/monaco/vs/language/css/cssWorker.js +77 -0
  482. package/public/monaco/vs/language/html/htmlMode.js +13 -0
  483. package/public/monaco/vs/language/html/htmlWorker.js +454 -0
  484. package/public/monaco/vs/language/json/jsonMode.js +19 -0
  485. package/public/monaco/vs/language/json/jsonWorker.js +42 -0
  486. package/public/monaco/vs/language/typescript/tsMode.js +20 -0
  487. package/public/monaco/vs/language/typescript/tsWorker.js +51328 -0
  488. package/public/monaco/vs/loader.js +11 -0
  489. package/public/monaco.worker.js +7 -0
  490. package/public/pwa-192x192.png +0 -0
  491. package/public/pwa-512x512.png +0 -0
  492. package/public/pwa-64x64.png +0 -0
  493. package/public/registerSW.js +1 -0
  494. package/public/sw.js +1 -0
  495. package/public/ui-version.json +3 -0
  496. package/public/workbox-60d14903.js +1 -0
@@ -0,0 +1,42 @@
1
+ import { z } from "zod";
2
+ import { isLoopbackAddress } from "../../auth/http-auth";
3
+ const CreateSessionSchema = z.object({
4
+ baseUrl: z.string().min(1),
5
+ skipTlsVerify: z.boolean().optional(),
6
+ });
7
+ const SessionParamsSchema = z.object({
8
+ id: z.string().uuid(),
9
+ });
10
+ export function registerRemoteProxyRoutes(app, deps) {
11
+ app.post("/api/remote-proxy/sessions", async (request, reply) => {
12
+ try {
13
+ const body = CreateSessionSchema.parse(request.body ?? {});
14
+ return await deps.sessionManager.createSession(body.baseUrl, Boolean(body.skipTlsVerify));
15
+ }
16
+ catch (error) {
17
+ deps.logger.warn({ err: error }, "Failed to create remote proxy session");
18
+ reply.code(400);
19
+ return { error: error instanceof Error ? error.message : "Failed to create remote proxy session" };
20
+ }
21
+ });
22
+ app.delete("/api/remote-proxy/sessions/:id", async (request, reply) => {
23
+ if (!isLoopbackAddress(request.socket.remoteAddress)) {
24
+ reply.code(404);
25
+ return { error: "Not found" };
26
+ }
27
+ try {
28
+ const params = SessionParamsSchema.parse(request.params ?? {});
29
+ const deleted = await deps.sessionManager.deleteSession(params.id);
30
+ if (!deleted) {
31
+ reply.code(404);
32
+ return { error: "Remote proxy session not found" };
33
+ }
34
+ return { ok: true };
35
+ }
36
+ catch (error) {
37
+ deps.logger.warn({ err: error }, "Failed to delete remote proxy session");
38
+ reply.code(400);
39
+ return { error: error instanceof Error ? error.message : "Failed to delete remote proxy session" };
40
+ }
41
+ });
42
+ }
@@ -0,0 +1,142 @@
1
+ import { Agent, fetch } from "undici";
2
+ import { z } from "zod";
3
+ const ProbeSchema = z.object({
4
+ baseUrl: z.string().min(1),
5
+ skipTlsVerify: z.boolean().optional(),
6
+ });
7
+ const PROBE_TIMEOUT_MS = 8000;
8
+ export function registerRemoteServerRoutes(app, deps) {
9
+ app.post("/api/remote-servers/probe", async (request, reply) => {
10
+ try {
11
+ const body = ProbeSchema.parse(request.body ?? {});
12
+ return await probeRemoteServer(body.baseUrl, Boolean(body.skipTlsVerify));
13
+ }
14
+ catch (error) {
15
+ deps.logger.warn({ err: error }, "Failed to probe remote server");
16
+ reply.code(400);
17
+ return { error: error instanceof Error ? error.message : "Invalid request" };
18
+ }
19
+ });
20
+ }
21
+ async function probeRemoteServer(baseUrl, skipTlsVerify) {
22
+ const normalizedUrl = normalizeBaseUrl(baseUrl);
23
+ const probeUrl = new URL("./api/auth/status", `${normalizedUrl}/`);
24
+ const controller = new AbortController();
25
+ const timeout = setTimeout(() => controller.abort(), PROBE_TIMEOUT_MS);
26
+ const dispatcher = skipTlsVerify ? new Agent({ connect: { rejectUnauthorized: false } }) : undefined;
27
+ try {
28
+ const response = await fetch(probeUrl, {
29
+ method: "GET",
30
+ dispatcher,
31
+ signal: controller.signal,
32
+ headers: {
33
+ Accept: "application/json",
34
+ },
35
+ });
36
+ if (!response.ok) {
37
+ return {
38
+ ok: false,
39
+ reachable: true,
40
+ normalizedUrl,
41
+ skipTlsVerify,
42
+ requiresAuth: false,
43
+ authenticated: false,
44
+ error: `Remote server returned HTTP ${response.status}`,
45
+ errorCode: "http_error",
46
+ };
47
+ }
48
+ const payload = (await response.json());
49
+ if (typeof payload?.authenticated !== "boolean") {
50
+ return {
51
+ ok: false,
52
+ reachable: true,
53
+ normalizedUrl,
54
+ skipTlsVerify,
55
+ requiresAuth: false,
56
+ authenticated: false,
57
+ error: "Remote server did not return a valid CodeNomad auth response",
58
+ errorCode: "invalid_server",
59
+ };
60
+ }
61
+ return {
62
+ ok: true,
63
+ reachable: true,
64
+ normalizedUrl,
65
+ skipTlsVerify,
66
+ requiresAuth: !payload.authenticated,
67
+ authenticated: payload.authenticated,
68
+ };
69
+ }
70
+ catch (error) {
71
+ const message = describeProbeError(error);
72
+ return {
73
+ ok: false,
74
+ reachable: false,
75
+ normalizedUrl,
76
+ skipTlsVerify,
77
+ requiresAuth: false,
78
+ authenticated: false,
79
+ error: message.message,
80
+ errorCode: message.code,
81
+ };
82
+ }
83
+ finally {
84
+ clearTimeout(timeout);
85
+ await dispatcher?.close().catch(() => { });
86
+ }
87
+ }
88
+ function normalizeBaseUrl(input) {
89
+ const parsed = new URL(input.trim());
90
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
91
+ throw new Error("Server URL must use http:// or https://");
92
+ }
93
+ parsed.hash = "";
94
+ parsed.search = "";
95
+ parsed.pathname = parsed.pathname === "/" ? "/" : parsed.pathname.replace(/\/+$/, "") || "/";
96
+ const value = parsed.toString();
97
+ return parsed.pathname === "/" ? value.replace(/\/$/, "") : value.replace(/\/$/, "");
98
+ }
99
+ function describeProbeError(error) {
100
+ const chain = unwrapErrorChain(error);
101
+ const detailed = chain.find((entry) => {
102
+ const code = (entry?.code ?? "").toString();
103
+ return Boolean(code) && code !== "UND_ERR_RESPONSE_STATUS_CODE";
104
+ }) ?? chain[0];
105
+ const code = (detailed?.code ?? "").toString();
106
+ const exactMessage = detailed?.message?.trim() || chain.find((entry) => entry.message?.trim())?.message?.trim();
107
+ if (code === "DEPTH_ZERO_SELF_SIGNED_CERT" || code === "SELF_SIGNED_CERT_IN_CHAIN" || code === "CERT_HAS_EXPIRED") {
108
+ return {
109
+ code: "tls_error",
110
+ message: "Certificate check failed while connecting to the remote server.",
111
+ };
112
+ }
113
+ return {
114
+ code: code === "ERR_INVALID_URL"
115
+ ? "invalid_url"
116
+ : code === "ECONNREFUSED"
117
+ ? "connection_refused"
118
+ : code === "ENOTFOUND"
119
+ ? "dns_error"
120
+ : code === "UND_ERR_CONNECT_TIMEOUT" || code === "ABORT_ERR"
121
+ ? "timeout"
122
+ : code
123
+ ? code.toLowerCase()
124
+ : "probe_failed",
125
+ message: exactMessage || "Failed to connect to the remote server.",
126
+ };
127
+ }
128
+ function unwrapErrorChain(error) {
129
+ const results = [];
130
+ let current = error;
131
+ const seen = new Set();
132
+ while (current && typeof current === "object" && !seen.has(current)) {
133
+ seen.add(current);
134
+ const entry = current;
135
+ results.push({ code: entry.code, message: entry.message });
136
+ current = entry.cause;
137
+ }
138
+ if (results.length === 0 && error instanceof Error) {
139
+ results.push({ message: error.message });
140
+ }
141
+ return results;
142
+ }
@@ -0,0 +1,69 @@
1
+ import { z } from "zod";
2
+ import { probeBinaryVersion } from "../../workspaces/spawn";
3
+ import { sanitizeConfigDoc, sanitizeConfigOwner } from "../../settings/public-config";
4
+ const ValidateBinarySchema = z.object({
5
+ path: z.string(),
6
+ });
7
+ function validateBinaryPath(binaryPath) {
8
+ const result = probeBinaryVersion(binaryPath);
9
+ return { valid: result.valid, version: result.version, error: result.error };
10
+ }
11
+ export function registerSettingsRoutes(app, deps) {
12
+ // Full-document access
13
+ app.get("/api/storage/config", async () => sanitizeConfigDoc(deps.settings.getDoc("config")));
14
+ app.patch("/api/storage/config", async (request, reply) => {
15
+ try {
16
+ return sanitizeConfigDoc(deps.settings.mergePatchDoc("config", request.body ?? {}));
17
+ }
18
+ catch (error) {
19
+ reply.code(400);
20
+ return { error: error instanceof Error ? error.message : "Invalid patch" };
21
+ }
22
+ });
23
+ app.get("/api/storage/config/:owner", async (request) => {
24
+ return sanitizeConfigOwner(request.params.owner, deps.settings.getOwner("config", request.params.owner));
25
+ });
26
+ app.patch("/api/storage/config/:owner", async (request, reply) => {
27
+ try {
28
+ return sanitizeConfigOwner(request.params.owner, deps.settings.mergePatchOwner("config", request.params.owner, request.body ?? {}));
29
+ }
30
+ catch (error) {
31
+ reply.code(400);
32
+ return { error: error instanceof Error ? error.message : "Invalid patch" };
33
+ }
34
+ });
35
+ app.get("/api/storage/state", async () => deps.settings.getDoc("state"));
36
+ app.patch("/api/storage/state", async (request, reply) => {
37
+ try {
38
+ return deps.settings.mergePatchDoc("state", request.body ?? {});
39
+ }
40
+ catch (error) {
41
+ reply.code(400);
42
+ return { error: error instanceof Error ? error.message : "Invalid patch" };
43
+ }
44
+ });
45
+ app.get("/api/storage/state/:owner", async (request) => {
46
+ return deps.settings.getOwner("state", request.params.owner);
47
+ });
48
+ app.patch("/api/storage/state/:owner", async (request, reply) => {
49
+ try {
50
+ return deps.settings.mergePatchOwner("state", request.params.owner, request.body ?? {});
51
+ }
52
+ catch (error) {
53
+ reply.code(400);
54
+ return { error: error instanceof Error ? error.message : "Invalid patch" };
55
+ }
56
+ });
57
+ // Binary validation helper (used by UI when adding binaries)
58
+ app.post("/api/storage/binaries/validate", async (request, reply) => {
59
+ try {
60
+ const body = ValidateBinarySchema.parse(request.body ?? {});
61
+ return validateBinaryPath(body.path);
62
+ }
63
+ catch (error) {
64
+ deps.logger.warn({ err: error }, "Failed to validate binary");
65
+ reply.code(400);
66
+ return { valid: false, error: error instanceof Error ? error.message : "Invalid request" };
67
+ }
68
+ });
69
+ }
@@ -0,0 +1,46 @@
1
+ import { z } from "zod";
2
+ const SideCarCreateSchema = z.object({
3
+ kind: z.literal("port").default("port"),
4
+ name: z.string().trim().min(1),
5
+ port: z.number().int().min(1).max(65535),
6
+ insecure: z.boolean().default(false),
7
+ prefixMode: z.enum(["strip", "preserve"]).default("strip"),
8
+ });
9
+ const SideCarUpdateSchema = SideCarCreateSchema.omit({ kind: true }).partial().refine((value) => Object.keys(value).length > 0, {
10
+ message: "At least one field is required",
11
+ });
12
+ export function registerSideCarRoutes(app, deps) {
13
+ app.get("/api/sidecars", async () => {
14
+ return { sidecars: await deps.sidecarManager.list() };
15
+ });
16
+ app.post("/api/sidecars", async (request, reply) => {
17
+ try {
18
+ const body = SideCarCreateSchema.parse(request.body ?? {});
19
+ const sidecar = await deps.sidecarManager.create(body);
20
+ reply.code(201);
21
+ return sidecar;
22
+ }
23
+ catch (error) {
24
+ reply.code(400);
25
+ return { error: error instanceof Error ? error.message : "Failed to create SideCar" };
26
+ }
27
+ });
28
+ app.put("/api/sidecars/:id", async (request, reply) => {
29
+ try {
30
+ const body = SideCarUpdateSchema.parse(request.body ?? {});
31
+ return await deps.sidecarManager.update(request.params.id, body);
32
+ }
33
+ catch (error) {
34
+ reply.code(400);
35
+ return { error: error instanceof Error ? error.message : "Failed to update SideCar" };
36
+ }
37
+ });
38
+ app.delete("/api/sidecars/:id", async (request, reply) => {
39
+ const removed = await deps.sidecarManager.delete(request.params.id);
40
+ if (!removed) {
41
+ reply.code(404);
42
+ return { error: "SideCar not found" };
43
+ }
44
+ reply.code(204);
45
+ });
46
+ }
@@ -0,0 +1,63 @@
1
+ import { z } from "zod";
2
+ const TranscribeBodySchema = z.object({
3
+ audioBase64: z.string().min(1, "Audio payload is required"),
4
+ mimeType: z.string().min(1, "Audio MIME type is required"),
5
+ filename: z.string().optional(),
6
+ language: z.string().optional(),
7
+ prompt: z.string().optional(),
8
+ });
9
+ const SynthesizeBodySchema = z.object({
10
+ text: z.string().trim().min(1, "Text is required"),
11
+ format: z.enum(["mp3", "wav", "opus", "aac"]).optional(),
12
+ });
13
+ function getSpeechErrorStatus(error) {
14
+ if (error instanceof z.ZodError) {
15
+ return 400;
16
+ }
17
+ if (error instanceof Error && /not configured/i.test(error.message)) {
18
+ return 503;
19
+ }
20
+ return 502;
21
+ }
22
+ function getSpeechErrorMessage(error, fallback) {
23
+ return error instanceof Error ? error.message : fallback;
24
+ }
25
+ export function registerSpeechRoutes(app, deps) {
26
+ app.get("/api/speech/capabilities", async () => deps.speechService.getCapabilities());
27
+ app.post("/api/speech/transcribe", async (request, reply) => {
28
+ try {
29
+ const body = TranscribeBodySchema.parse(request.body ?? {});
30
+ return await deps.speechService.transcribe(body);
31
+ }
32
+ catch (error) {
33
+ request.log.error({ err: error }, "Failed to transcribe audio");
34
+ reply.code(getSpeechErrorStatus(error));
35
+ return { error: getSpeechErrorMessage(error, "Failed to transcribe audio") };
36
+ }
37
+ });
38
+ app.post("/api/speech/synthesize", async (request, reply) => {
39
+ try {
40
+ const body = SynthesizeBodySchema.parse(request.body ?? {});
41
+ return await deps.speechService.synthesize(body);
42
+ }
43
+ catch (error) {
44
+ request.log.error({ err: error }, "Failed to synthesize audio");
45
+ reply.code(getSpeechErrorStatus(error));
46
+ return { error: getSpeechErrorMessage(error, "Failed to synthesize audio") };
47
+ }
48
+ });
49
+ app.post("/api/speech/synthesize/stream", async (request, reply) => {
50
+ try {
51
+ const body = SynthesizeBodySchema.parse(request.body ?? {});
52
+ const result = await deps.speechService.synthesizeStream(body);
53
+ reply.header("Content-Type", result.mimeType);
54
+ reply.header("Cache-Control", "no-store");
55
+ return reply.send(result.stream);
56
+ }
57
+ catch (error) {
58
+ request.log.error({ err: error }, "Failed to stream synthesized audio");
59
+ reply.code(getSpeechErrorStatus(error));
60
+ return { error: getSpeechErrorMessage(error, "Failed to stream synthesized audio") };
61
+ }
62
+ });
63
+ }
@@ -0,0 +1,52 @@
1
+ import { z } from "zod";
2
+ import { ModelPreferenceSchema } from "../../config/schema";
3
+ const InstanceDataSchema = z.object({
4
+ messageHistory: z.array(z.string()).default([]),
5
+ agentModelSelections: z.record(z.string(), ModelPreferenceSchema).default({}),
6
+ });
7
+ const EMPTY_INSTANCE_DATA = {
8
+ messageHistory: [],
9
+ agentModelSelections: {},
10
+ };
11
+ export function registerStorageRoutes(app, deps) {
12
+ const resolveStorageKey = (instanceId) => {
13
+ const workspace = deps.workspaceManager.get(instanceId);
14
+ return workspace?.path ?? instanceId;
15
+ };
16
+ app.get("/api/storage/instances/:id", async (request, reply) => {
17
+ try {
18
+ const storageId = resolveStorageKey(request.params.id);
19
+ const data = await deps.instanceStore.read(storageId);
20
+ return data;
21
+ }
22
+ catch (error) {
23
+ reply.code(500);
24
+ return { error: error instanceof Error ? error.message : "Failed to read instance data" };
25
+ }
26
+ });
27
+ app.put("/api/storage/instances/:id", async (request, reply) => {
28
+ try {
29
+ const body = InstanceDataSchema.parse(request.body ?? {});
30
+ const storageId = resolveStorageKey(request.params.id);
31
+ await deps.instanceStore.write(storageId, body);
32
+ deps.eventBus.publish({ type: "instance.dataChanged", instanceId: request.params.id, data: body });
33
+ reply.code(204);
34
+ }
35
+ catch (error) {
36
+ reply.code(400);
37
+ return { error: error instanceof Error ? error.message : "Failed to save instance data" };
38
+ }
39
+ });
40
+ app.delete("/api/storage/instances/:id", async (request, reply) => {
41
+ try {
42
+ const storageId = resolveStorageKey(request.params.id);
43
+ await deps.instanceStore.delete(storageId);
44
+ deps.eventBus.publish({ type: "instance.dataChanged", instanceId: request.params.id, data: EMPTY_INSTANCE_DATA });
45
+ reply.code(204);
46
+ }
47
+ catch (error) {
48
+ reply.code(500);
49
+ return { error: error instanceof Error ? error.message : "Failed to delete instance data" };
50
+ }
51
+ });
52
+ }
@@ -0,0 +1,221 @@
1
+ import { z } from "zod";
2
+ import { getWorktreeGitDiff, getWorktreeGitStatus } from "../../workspaces/git-status";
3
+ import { commitWorktreeChanges, isGitMutationError, stageWorktreePaths, unstageWorktreePaths } from "../../workspaces/git-mutations";
4
+ import { isGitAvailable, resolveRepoRoot } from "../../workspaces/git-worktrees";
5
+ import { resolveWorktreeDirectory } from "../../workspaces/worktree-directory";
6
+ const WorkspaceCreateSchema = z.object({
7
+ path: z.string(),
8
+ name: z.string().optional(),
9
+ });
10
+ const WorkspaceFilesQuerySchema = z.object({
11
+ path: z.string().optional(),
12
+ });
13
+ const WorkspaceFileContentQuerySchema = z.object({
14
+ path: z.string(),
15
+ });
16
+ const WorkspaceFileContentBodySchema = z.object({
17
+ contents: z.string(),
18
+ });
19
+ const WorktreeGitDiffQuerySchema = z.object({
20
+ path: z.string().trim().min(1, "Path is required"),
21
+ originalPath: z.string().trim().optional(),
22
+ scope: z.enum(["staged", "unstaged"]),
23
+ });
24
+ const WorktreeGitPathsBodySchema = z.object({
25
+ paths: z.array(z.string().trim().min(1, "Path is required")).min(1, "At least one path is required"),
26
+ });
27
+ const WorktreeGitCommitBodySchema = z.object({
28
+ message: z.string().trim().min(1, "Commit message is required"),
29
+ });
30
+ const WorkspaceFileSearchQuerySchema = z.object({
31
+ q: z.string().trim().min(1, "Query is required"),
32
+ limit: z.coerce.number().int().positive().max(200).optional(),
33
+ type: z.enum(["all", "file", "directory"]).optional(),
34
+ refresh: z
35
+ .string()
36
+ .optional()
37
+ .transform((value) => (value === undefined ? undefined : value === "true")),
38
+ });
39
+ export function registerWorkspaceRoutes(app, deps) {
40
+ app.get("/api/workspaces", async () => {
41
+ return deps.workspaceManager.list();
42
+ });
43
+ app.post("/api/workspaces", async (request, reply) => {
44
+ try {
45
+ const body = WorkspaceCreateSchema.parse(request.body ?? {});
46
+ const workspace = await deps.workspaceManager.create(body.path, body.name);
47
+ reply.code(201);
48
+ return workspace;
49
+ }
50
+ catch (error) {
51
+ request.log.error({ err: error }, "Failed to create workspace");
52
+ const message = error instanceof Error ? error.message : "Failed to create workspace";
53
+ reply.code(400).type("text/plain").send(message);
54
+ }
55
+ });
56
+ app.get("/api/workspaces/:id", async (request, reply) => {
57
+ const workspace = deps.workspaceManager.get(request.params.id);
58
+ if (!workspace) {
59
+ reply.code(404);
60
+ return { error: "Workspace not found" };
61
+ }
62
+ return workspace;
63
+ });
64
+ app.delete("/api/workspaces/:id", async (request, reply) => {
65
+ await deps.workspaceManager.delete(request.params.id);
66
+ reply.code(204);
67
+ });
68
+ app.get("/api/workspaces/:id/files", async (request, reply) => {
69
+ try {
70
+ const query = WorkspaceFilesQuerySchema.parse(request.query ?? {});
71
+ return deps.workspaceManager.listFiles(request.params.id, query.path ?? ".");
72
+ }
73
+ catch (error) {
74
+ return handleWorkspaceError(error, reply);
75
+ }
76
+ });
77
+ app.get("/api/workspaces/:id/files/search", async (request, reply) => {
78
+ try {
79
+ const query = WorkspaceFileSearchQuerySchema.parse(request.query ?? {});
80
+ return deps.workspaceManager.searchFiles(request.params.id, query.q, {
81
+ limit: query.limit,
82
+ type: query.type,
83
+ refresh: query.refresh,
84
+ });
85
+ }
86
+ catch (error) {
87
+ return handleWorkspaceError(error, reply);
88
+ }
89
+ });
90
+ app.get("/api/workspaces/:id/files/content", async (request, reply) => {
91
+ try {
92
+ const query = WorkspaceFileContentQuerySchema.parse(request.query ?? {});
93
+ return deps.workspaceManager.readFile(request.params.id, query.path);
94
+ }
95
+ catch (error) {
96
+ return handleWorkspaceError(error, reply);
97
+ }
98
+ });
99
+ app.put("/api/workspaces/:id/files/content", async (request, reply) => {
100
+ try {
101
+ const query = WorkspaceFileContentQuerySchema.parse(request.query ?? {});
102
+ const body = WorkspaceFileContentBodySchema.parse(request.body ?? {});
103
+ deps.workspaceManager.writeFile(request.params.id, query.path, body.contents);
104
+ reply.code(204);
105
+ }
106
+ catch (error) {
107
+ return handleWorkspaceError(error, reply);
108
+ }
109
+ });
110
+ app.get("/api/workspaces/:id/worktrees/:slug/git-status", async (request, reply) => {
111
+ try {
112
+ const directory = await resolveGitWorktreeDirectory(deps.workspaceManager, request.params.id, request.params.slug, request.log, reply);
113
+ if (!directory)
114
+ return;
115
+ return await getWorktreeGitStatus({ workspaceFolder: directory, logger: request.log });
116
+ }
117
+ catch (error) {
118
+ return handleWorkspaceError(error, reply);
119
+ }
120
+ });
121
+ app.get("/api/workspaces/:id/worktrees/:slug/git-diff", async (request, reply) => {
122
+ try {
123
+ const query = WorktreeGitDiffQuerySchema.parse(request.query ?? {});
124
+ const directory = await resolveGitWorktreeDirectory(deps.workspaceManager, request.params.id, request.params.slug, request.log, reply);
125
+ if (!directory)
126
+ return;
127
+ return await getWorktreeGitDiff({
128
+ workspaceFolder: directory,
129
+ path: query.path,
130
+ originalPath: query.originalPath,
131
+ scope: query.scope,
132
+ });
133
+ }
134
+ catch (error) {
135
+ return handleWorkspaceError(error, reply);
136
+ }
137
+ });
138
+ app.post("/api/workspaces/:id/worktrees/:slug/git-stage", async (request, reply) => {
139
+ try {
140
+ const body = WorktreeGitPathsBodySchema.parse(request.body ?? {});
141
+ const directory = await resolveGitWorktreeDirectory(deps.workspaceManager, request.params.id, request.params.slug, request.log, reply);
142
+ if (!directory)
143
+ return;
144
+ await stageWorktreePaths({ workspaceFolder: directory, paths: body.paths });
145
+ return { ok: true };
146
+ }
147
+ catch (error) {
148
+ return handleWorkspaceError(error, reply);
149
+ }
150
+ });
151
+ app.post("/api/workspaces/:id/worktrees/:slug/git-unstage", async (request, reply) => {
152
+ try {
153
+ const body = WorktreeGitPathsBodySchema.parse(request.body ?? {});
154
+ const directory = await resolveGitWorktreeDirectory(deps.workspaceManager, request.params.id, request.params.slug, request.log, reply);
155
+ if (!directory)
156
+ return;
157
+ await unstageWorktreePaths({ workspaceFolder: directory, paths: body.paths });
158
+ return { ok: true };
159
+ }
160
+ catch (error) {
161
+ return handleWorkspaceError(error, reply);
162
+ }
163
+ });
164
+ app.post("/api/workspaces/:id/worktrees/:slug/git-commit", async (request, reply) => {
165
+ try {
166
+ const body = WorktreeGitCommitBodySchema.parse(request.body ?? {});
167
+ const directory = await resolveGitWorktreeDirectory(deps.workspaceManager, request.params.id, request.params.slug, request.log, reply);
168
+ if (!directory)
169
+ return;
170
+ const result = await commitWorktreeChanges({ workspaceFolder: directory, message: body.message });
171
+ return { ok: true, ...result };
172
+ }
173
+ catch (error) {
174
+ return handleWorkspaceError(error, reply);
175
+ }
176
+ });
177
+ }
178
+ async function resolveGitWorktreeDirectory(workspaceManager, workspaceId, worktreeSlug, logger, reply) {
179
+ const workspace = workspaceManager.get(workspaceId);
180
+ if (!workspace) {
181
+ reply.code(404);
182
+ reply.send({ error: "Workspace not found" });
183
+ return null;
184
+ }
185
+ const gitAvailable = await isGitAvailable(workspace.path);
186
+ if (!gitAvailable) {
187
+ reply.code(503);
188
+ reply.send({ error: "Git is not installed or not available in PATH" });
189
+ return null;
190
+ }
191
+ const { isGitRepo } = await resolveRepoRoot(workspace.path, logger);
192
+ if (!isGitRepo) {
193
+ reply.code(400);
194
+ reply.send({ error: "Workspace is not a Git repository" });
195
+ return null;
196
+ }
197
+ const directory = await resolveWorktreeDirectory({
198
+ workspaceId: workspace.id,
199
+ workspacePath: workspace.path,
200
+ worktreeSlug,
201
+ logger,
202
+ });
203
+ if (!directory) {
204
+ reply.code(404);
205
+ reply.send({ error: "Worktree not found" });
206
+ return null;
207
+ }
208
+ return directory;
209
+ }
210
+ function handleWorkspaceError(error, reply) {
211
+ if (isGitMutationError(error)) {
212
+ reply.code(error.statusCode);
213
+ return { error: error.message };
214
+ }
215
+ if (error instanceof Error && error.message === "Workspace not found") {
216
+ reply.code(404);
217
+ return { error: "Workspace not found" };
218
+ }
219
+ reply.code(400);
220
+ return { error: error instanceof Error ? error.message : "Unable to fulfill request" };
221
+ }