@vividcodeai/embeddedcowork-dev 0.0.3-dev-20260507-b76190e8

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 (434) 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/clients/connection-manager.js +93 -0
  12. package/dist/config/location.js +57 -0
  13. package/dist/config/schema.js +71 -0
  14. package/dist/events/bus.js +45 -0
  15. package/dist/filesystem/__tests__/search-cache.test.js +40 -0
  16. package/dist/filesystem/browser.js +292 -0
  17. package/dist/filesystem/search-cache.js +43 -0
  18. package/dist/filesystem/search.js +135 -0
  19. package/dist/index.js +466 -0
  20. package/dist/launcher.js +149 -0
  21. package/dist/loader.js +21 -0
  22. package/dist/logger.js +109 -0
  23. package/dist/opencode-config/README.md +32 -0
  24. package/dist/opencode-config/opencode.jsonc +3 -0
  25. package/dist/opencode-config/package.json +9 -0
  26. package/dist/opencode-config/plugin/embeddedcowork.ts +62 -0
  27. package/dist/opencode-config/plugin/lib/background-process.ts +265 -0
  28. package/dist/opencode-config/plugin/lib/client.ts +133 -0
  29. package/dist/opencode-config/plugin/lib/request.ts +214 -0
  30. package/dist/opencode-config.js +15 -0
  31. package/dist/plugins/channel.js +40 -0
  32. package/dist/plugins/handlers.js +17 -0
  33. package/dist/plugins/voice-mode.js +78 -0
  34. package/dist/releases/dev-release-monitor.js +75 -0
  35. package/dist/releases/release-monitor.js +107 -0
  36. package/dist/runtime-paths.js +67 -0
  37. package/dist/server/__tests__/network-addresses.test.js +68 -0
  38. package/dist/server/__tests__/remote-proxy.test.js +204 -0
  39. package/dist/server/http-server.js +996 -0
  40. package/dist/server/network-addresses.js +114 -0
  41. package/dist/server/remote-proxy.js +466 -0
  42. package/dist/server/routes/auth-pages/login.html +135 -0
  43. package/dist/server/routes/auth-pages/token.html +93 -0
  44. package/dist/server/routes/auth.js +149 -0
  45. package/dist/server/routes/background-processes.js +78 -0
  46. package/dist/server/routes/events.js +66 -0
  47. package/dist/server/routes/filesystem.js +43 -0
  48. package/dist/server/routes/meta.js +44 -0
  49. package/dist/server/routes/plugin.js +70 -0
  50. package/dist/server/routes/remote-proxy.js +42 -0
  51. package/dist/server/routes/remote-servers.js +142 -0
  52. package/dist/server/routes/settings.js +69 -0
  53. package/dist/server/routes/sidecars.js +46 -0
  54. package/dist/server/routes/speech.js +63 -0
  55. package/dist/server/routes/storage.js +52 -0
  56. package/dist/server/routes/workspaces.js +221 -0
  57. package/dist/server/routes/worktrees.js +156 -0
  58. package/dist/server/tls.js +224 -0
  59. package/dist/settings/binaries.js +37 -0
  60. package/dist/settings/merge-patch.js +33 -0
  61. package/dist/settings/migrate.js +238 -0
  62. package/dist/settings/public-config.js +33 -0
  63. package/dist/settings/service.js +101 -0
  64. package/dist/settings/yaml-doc-store.js +96 -0
  65. package/dist/sidecars/manager.js +193 -0
  66. package/dist/speech/providers/openai-compatible.js +189 -0
  67. package/dist/speech/service.js +58 -0
  68. package/dist/storage/instance-store.js +56 -0
  69. package/dist/ui/__tests__/remote-ui.test.js +67 -0
  70. package/dist/ui/remote-ui.js +462 -0
  71. package/dist/workspaces/__tests__/spawn.test.js +139 -0
  72. package/dist/workspaces/git-mutations.js +98 -0
  73. package/dist/workspaces/git-status.js +323 -0
  74. package/dist/workspaces/git-worktrees.js +216 -0
  75. package/dist/workspaces/instance-events.js +180 -0
  76. package/dist/workspaces/manager.js +420 -0
  77. package/dist/workspaces/opencode-auth.js +16 -0
  78. package/dist/workspaces/runtime.js +366 -0
  79. package/dist/workspaces/spawn.js +219 -0
  80. package/dist/workspaces/worktree-directory.js +74 -0
  81. package/dist/workspaces/worktree-map.js +116 -0
  82. package/package.json +57 -0
  83. package/public/apple-touch-icon-180x180.png +0 -0
  84. package/public/assets/ChangesTab-C2DJXDf9.js +2 -0
  85. package/public/assets/DiffToolbar-De-3SRCF.js +1 -0
  86. package/public/assets/EmbeddedCowork-Icon-DSw5nKk7.png +0 -0
  87. package/public/assets/FilesTab-BuQ00MEc.js +2 -0
  88. package/public/assets/GitChangesTab-D9bf2jkM.js +2 -0
  89. package/public/assets/SplitFilePanel-B-3h60o2.js +1 -0
  90. package/public/assets/StatusTab-D5s19fRN.js +1 -0
  91. package/public/assets/abap-BdImnpbu.js +1 -0
  92. package/public/assets/actionscript-3-CfeIJUat.js +1 -0
  93. package/public/assets/ada-bCR0ucgS.js +1 -0
  94. package/public/assets/andromeeda-C-Jbm3Hp.js +1 -0
  95. package/public/assets/angular-html-CU67Zn6k.js +1 -0
  96. package/public/assets/angular-ts-BwZT4LLn.js +1 -0
  97. package/public/assets/apache-Pmp26Uib.js +1 -0
  98. package/public/assets/apex-DhZLUxFE.js +1 -0
  99. package/public/assets/apl-dKokRX4l.js +1 -0
  100. package/public/assets/applescript-Co6uUVPk.js +1 -0
  101. package/public/assets/ara-BRHolxvo.js +1 -0
  102. package/public/assets/asciidoc-Dv7Oe6Be.js +1 -0
  103. package/public/assets/asm-D_Q5rh1f.js +1 -0
  104. package/public/assets/astro-CbQHKStN.js +1 -0
  105. package/public/assets/aurora-x-D-2ljcwZ.js +1 -0
  106. package/public/assets/awk-DMzUqQB5.js +1 -0
  107. package/public/assets/ayu-dark-Cv9koXgw.js +1 -0
  108. package/public/assets/ballerina-BFfxhgS-.js +1 -0
  109. package/public/assets/bat-BkioyH1T.js +1 -0
  110. package/public/assets/beancount-k_qm7-4y.js +1 -0
  111. package/public/assets/berry-D08WgyRC.js +1 -0
  112. package/public/assets/bibtex-CHM0blh-.js +1 -0
  113. package/public/assets/bicep-Bmn6On1c.js +1 -0
  114. package/public/assets/blade-DVc8C-J4.js +1 -0
  115. package/public/assets/bsl-BO_Y6i37.js +1 -0
  116. package/public/assets/bundle-full-CdNbUxmo.js +13 -0
  117. package/public/assets/c-BIGW1oBm.js +1 -0
  118. package/public/assets/cadence-Bv_4Rxtq.js +1 -0
  119. package/public/assets/cairo-KRGpt6FW.js +1 -0
  120. package/public/assets/catppuccin-frappe-DFWUc33u.js +1 -0
  121. package/public/assets/catppuccin-latte-C9dUb6Cb.js +1 -0
  122. package/public/assets/catppuccin-macchiato-DQyhUUbL.js +1 -0
  123. package/public/assets/catppuccin-mocha-D87Tk5Gz.js +1 -0
  124. package/public/assets/clarity-D53aC0YG.js +1 -0
  125. package/public/assets/clojure-P80f7IUj.js +1 -0
  126. package/public/assets/cmake-D1j8_8rp.js +1 -0
  127. package/public/assets/cobol-nwyudZeR.js +1 -0
  128. package/public/assets/codeowners-Bp6g37R7.js +1 -0
  129. package/public/assets/codeql-DsOJ9woJ.js +1 -0
  130. package/public/assets/coffee-Ch7k5sss.js +1 -0
  131. package/public/assets/common-lisp-Cg-RD9OK.js +1 -0
  132. package/public/assets/coq-DkFqJrB1.js +1 -0
  133. package/public/assets/core-DhEqZVGG.js +1 -0
  134. package/public/assets/cpp-CofmeUqb.js +1 -0
  135. package/public/assets/crystal-tKQVLTB8.js +1 -0
  136. package/public/assets/csharp-CX12Zw3r.js +1 -0
  137. package/public/assets/css-DPfMkruS.js +1 -0
  138. package/public/assets/csv-fuZLfV_i.js +1 -0
  139. package/public/assets/cue-D82EKSYY.js +1 -0
  140. package/public/assets/cypher-COkxafJQ.js +1 -0
  141. package/public/assets/d-85-TOEBH.js +1 -0
  142. package/public/assets/dark-plus-eOWES_5F.js +1 -0
  143. package/public/assets/dart-CF10PKvl.js +1 -0
  144. package/public/assets/dax-CEL-wOlO.js +1 -0
  145. package/public/assets/desktop-BmXAJ9_W.js +1 -0
  146. package/public/assets/diff-D97Zzqfu.js +1 -0
  147. package/public/assets/diff-viewer-B1l_VZc1.js +1 -0
  148. package/public/assets/docker-BcOcwvcX.js +1 -0
  149. package/public/assets/dotenv-Da5cRb03.js +1 -0
  150. package/public/assets/dracula-BzJJZx-M.js +1 -0
  151. package/public/assets/dracula-soft-BXkSAIEj.js +1 -0
  152. package/public/assets/dream-maker-BtqSS_iP.js +1 -0
  153. package/public/assets/edge-BkV0erSs.js +1 -0
  154. package/public/assets/elixir-CDX3lj18.js +1 -0
  155. package/public/assets/elm-DbKCFpqz.js +1 -0
  156. package/public/assets/emacs-lisp-C9XAeP06.js +1 -0
  157. package/public/assets/erb-BOJIQeun.js +1 -0
  158. package/public/assets/erlang-DsQrWhSR.js +1 -0
  159. package/public/assets/event-DjZVAIBO.js +1 -0
  160. package/public/assets/everforest-dark-BgDCqdQA.js +1 -0
  161. package/public/assets/everforest-light-C8M2exoo.js +1 -0
  162. package/public/assets/fast-diff-vendor-DgdwVvTQ.js +1 -0
  163. package/public/assets/fennel-BYunw83y.js +1 -0
  164. package/public/assets/fish-BvzEVeQv.js +1 -0
  165. package/public/assets/fluent-C4IJs8-o.js +1 -0
  166. package/public/assets/fortran-fixed-form-BZjJHVRy.js +1 -0
  167. package/public/assets/fortran-free-form-D22FLkUw.js +1 -0
  168. package/public/assets/fsharp-CXgrBDvD.js +1 -0
  169. package/public/assets/gdresource-B7Tvp0Sc.js +1 -0
  170. package/public/assets/gdscript-DTMYz4Jt.js +1 -0
  171. package/public/assets/gdshader-DkwncUOv.js +1 -0
  172. package/public/assets/genie-D0YGMca9.js +1 -0
  173. package/public/assets/gherkin-DyxjwDmM.js +1 -0
  174. package/public/assets/git-commit-F4YmCXRG.js +1 -0
  175. package/public/assets/git-diff-vendor-CSgooKT_.js +52 -0
  176. package/public/assets/git-diff-vendor-HAZkIolJ.css +19 -0
  177. package/public/assets/git-rebase-r7XF79zn.js +1 -0
  178. package/public/assets/github-dark-DHJKELXO.js +1 -0
  179. package/public/assets/github-dark-default-Cuk6v7N8.js +1 -0
  180. package/public/assets/github-dark-dimmed-DH5Ifo-i.js +1 -0
  181. package/public/assets/github-dark-high-contrast-E3gJ1_iC.js +1 -0
  182. package/public/assets/github-light-DAi9KRSo.js +1 -0
  183. package/public/assets/github-light-default-D7oLnXFd.js +1 -0
  184. package/public/assets/github-light-high-contrast-BfjtVDDH.js +1 -0
  185. package/public/assets/gleam-BspZqrRM.js +1 -0
  186. package/public/assets/glimmer-js-Rg0-pVw9.js +1 -0
  187. package/public/assets/glimmer-ts-U6CK756n.js +1 -0
  188. package/public/assets/glsl-DplSGwfg.js +1 -0
  189. package/public/assets/gnuplot-DdkO51Og.js +1 -0
  190. package/public/assets/go-Dn2_MT6a.js +1 -0
  191. package/public/assets/graphql-ChdNCCLP.js +1 -0
  192. package/public/assets/groovy-gcz8RCvz.js +1 -0
  193. package/public/assets/gruvbox-dark-hard-CFHQjOhq.js +1 -0
  194. package/public/assets/gruvbox-dark-medium-GsRaNv29.js +1 -0
  195. package/public/assets/gruvbox-dark-soft-CVdnzihN.js +1 -0
  196. package/public/assets/gruvbox-light-hard-CH1njM8p.js +1 -0
  197. package/public/assets/gruvbox-light-medium-DRw_LuNl.js +1 -0
  198. package/public/assets/gruvbox-light-soft-hJgmCMqR.js +1 -0
  199. package/public/assets/hack-CaT9iCJl.js +1 -0
  200. package/public/assets/haml-B8DHNrY2.js +1 -0
  201. package/public/assets/handlebars-BL8al0AC.js +1 -0
  202. package/public/assets/haskell-Df6bDoY_.js +1 -0
  203. package/public/assets/haxe-CzTSHFRz.js +1 -0
  204. package/public/assets/hcl-BWvSN4gD.js +1 -0
  205. package/public/assets/highlight-vendor-8FKMu9os.js +10 -0
  206. package/public/assets/hjson-D5-asLiD.js +1 -0
  207. package/public/assets/hlsl-D3lLCCz7.js +1 -0
  208. package/public/assets/houston-DnULxvSX.js +1 -0
  209. package/public/assets/html-GMplVEZG.js +1 -0
  210. package/public/assets/html-derivative-BFtXZ54Q.js +1 -0
  211. package/public/assets/http-jrhK8wxY.js +1 -0
  212. package/public/assets/hurl-irOxFIW8.js +1 -0
  213. package/public/assets/hxml-Bvhsp5Yf.js +1 -0
  214. package/public/assets/hy-DFXneXwc.js +1 -0
  215. package/public/assets/imba-DGztddWO.js +1 -0
  216. package/public/assets/index-B2LsA7hD.js +1 -0
  217. package/public/assets/index-BErmCqgL.js +1 -0
  218. package/public/assets/index-BKMyzTSR.js +1 -0
  219. package/public/assets/index-BKvZBimW.js +1 -0
  220. package/public/assets/index-BQeBs108.js +1 -0
  221. package/public/assets/index-BqQARTCd.js +1 -0
  222. package/public/assets/index-C9Tl2tHH.js +2 -0
  223. package/public/assets/index-CLSJ4cO9.js +1 -0
  224. package/public/assets/index-DElsPAzQ.css +1 -0
  225. package/public/assets/index-ixx_g9gD.js +1 -0
  226. package/public/assets/ini-BEwlwnbL.js +1 -0
  227. package/public/assets/java-CylS5w8V.js +1 -0
  228. package/public/assets/javascript-wDzz0qaB.js +1 -0
  229. package/public/assets/jinja-4LBKfQ-Z.js +1 -0
  230. package/public/assets/jison-wvAkD_A8.js +1 -0
  231. package/public/assets/json-Cp-IABpG.js +1 -0
  232. package/public/assets/json5-C9tS-k6U.js +1 -0
  233. package/public/assets/jsonc-Des-eS-w.js +1 -0
  234. package/public/assets/jsonl-DcaNXYhu.js +1 -0
  235. package/public/assets/jsonnet-DFQXde-d.js +1 -0
  236. package/public/assets/jssm-C2t-YnRu.js +1 -0
  237. package/public/assets/jsx-g9-lgVsj.js +1 -0
  238. package/public/assets/julia-C8NyazO9.js +1 -0
  239. package/public/assets/kanagawa-dragon-CkXjmgJE.js +1 -0
  240. package/public/assets/kanagawa-lotus-CfQXZHmo.js +1 -0
  241. package/public/assets/kanagawa-wave-DWedfzmr.js +1 -0
  242. package/public/assets/kdl-DV7GczEv.js +1 -0
  243. package/public/assets/kotlin-BdnUsdx6.js +1 -0
  244. package/public/assets/kusto-BvAqAH-y.js +1 -0
  245. package/public/assets/laserwave-DUszq2jm.js +1 -0
  246. package/public/assets/latex-BUKiar2Z.js +1 -0
  247. package/public/assets/lean-DP1Csr6i.js +1 -0
  248. package/public/assets/less-B1dDrJ26.js +1 -0
  249. package/public/assets/light-plus-B7mTdjB0.js +1 -0
  250. package/public/assets/liquid-DYVedYrR.js +1 -0
  251. package/public/assets/llvm-BtvRca6l.js +1 -0
  252. package/public/assets/loading-CQjaT4lJ.js +2 -0
  253. package/public/assets/loading-CugGjKDZ.css +1 -0
  254. package/public/assets/log-2UxHyX5q.js +1 -0
  255. package/public/assets/logo-BtOb2qkB.js +1 -0
  256. package/public/assets/lua-BbnMAYS6.js +1 -0
  257. package/public/assets/luau-CXu1NL6O.js +1 -0
  258. package/public/assets/main-C1yBw4P8.js +53 -0
  259. package/public/assets/make-CHLpvVh8.js +1 -0
  260. package/public/assets/markdown-Cvjx9yec.js +1 -0
  261. package/public/assets/markdown-D5eIdNMf.js +58 -0
  262. package/public/assets/marko-CPi9NSCl.js +1 -0
  263. package/public/assets/material-theme-D5KoaKCx.js +1 -0
  264. package/public/assets/material-theme-darker-BfHTSMKl.js +1 -0
  265. package/public/assets/material-theme-lighter-B0m2ddpp.js +1 -0
  266. package/public/assets/material-theme-ocean-CyktbL80.js +1 -0
  267. package/public/assets/material-theme-palenight-Csfq5Kiy.js +1 -0
  268. package/public/assets/matlab-D7o27uSR.js +1 -0
  269. package/public/assets/mdc-DUICxH0z.js +1 -0
  270. package/public/assets/mdx-Cmh6b_Ma.js +1 -0
  271. package/public/assets/mermaid-DKYwYmdq.js +1 -0
  272. package/public/assets/min-dark-CafNBF8u.js +1 -0
  273. package/public/assets/min-light-CTRr51gU.js +1 -0
  274. package/public/assets/mipsasm-CKIfxQSi.js +1 -0
  275. package/public/assets/mojo-1DNp92w6.js +1 -0
  276. package/public/assets/monaco-viewer-9Byc1Kpy.js +26 -0
  277. package/public/assets/monokai-D4h5O-jR.js +1 -0
  278. package/public/assets/move-Bu9oaDYs.js +1 -0
  279. package/public/assets/narrat-DRg8JJMk.js +1 -0
  280. package/public/assets/nextflow-CUEJCptM.js +1 -0
  281. package/public/assets/nginx-DknmC5AR.js +1 -0
  282. package/public/assets/night-owl-C39BiMTA.js +1 -0
  283. package/public/assets/nim-CVrawwO9.js +1 -0
  284. package/public/assets/nix-BbRYJGeE.js +1 -0
  285. package/public/assets/nord-Ddv68eIx.js +1 -0
  286. package/public/assets/nushell-C-sUppwS.js +1 -0
  287. package/public/assets/objective-c-DXmwc3jG.js +1 -0
  288. package/public/assets/objective-cpp-CLxacb5B.js +1 -0
  289. package/public/assets/ocaml-C0hk2d4L.js +1 -0
  290. package/public/assets/one-dark-pro-DVMEJ2y_.js +1 -0
  291. package/public/assets/one-light-PoHY5YXO.js +1 -0
  292. package/public/assets/pascal-D93ZcfNL.js +1 -0
  293. package/public/assets/perl-C0TMdlhV.js +1 -0
  294. package/public/assets/php-CDn_0X-4.js +1 -0
  295. package/public/assets/pkl-u5AG7uiY.js +1 -0
  296. package/public/assets/plastic-3e1v2bzS.js +1 -0
  297. package/public/assets/plsql-ChMvpjG-.js +1 -0
  298. package/public/assets/po-BTJTHyun.js +1 -0
  299. package/public/assets/poimandres-CS3Unz2-.js +1 -0
  300. package/public/assets/polar-C0HS_06l.js +1 -0
  301. package/public/assets/postcss-CXtECtnM.js +1 -0
  302. package/public/assets/powerquery-CEu0bR-o.js +1 -0
  303. package/public/assets/powershell-Dpen1YoG.js +1 -0
  304. package/public/assets/prisma-Dd19v3D-.js +1 -0
  305. package/public/assets/prolog-CbFg5uaA.js +1 -0
  306. package/public/assets/proto-DyJlTyXw.js +1 -0
  307. package/public/assets/pug-CGlum2m_.js +1 -0
  308. package/public/assets/puppet-BMWR74SV.js +1 -0
  309. package/public/assets/purescript-CklMAg4u.js +1 -0
  310. package/public/assets/python-B6aJPvgy.js +1 -0
  311. package/public/assets/qml-3beO22l8.js +1 -0
  312. package/public/assets/qmldir-C8lEn-DE.js +1 -0
  313. package/public/assets/qss-IeuSbFQv.js +1 -0
  314. package/public/assets/r-DiinP2Uv.js +1 -0
  315. package/public/assets/racket-BqYA7rlc.js +1 -0
  316. package/public/assets/raku-DXvB9xmW.js +1 -0
  317. package/public/assets/razor-WgofotgN.js +1 -0
  318. package/public/assets/red-bN70gL4F.js +1 -0
  319. package/public/assets/reg-C-SQnVFl.js +1 -0
  320. package/public/assets/regexp-CDVJQ6XC.js +1 -0
  321. package/public/assets/rel-C3B-1QV4.js +1 -0
  322. package/public/assets/riscv-BM1_JUlF.js +1 -0
  323. package/public/assets/rose-pine-BHrmToEH.js +1 -0
  324. package/public/assets/rose-pine-dawn-CnK8MTSM.js +1 -0
  325. package/public/assets/rose-pine-moon-NleAzG8P.js +1 -0
  326. package/public/assets/rosmsg-BJDFO7_C.js +1 -0
  327. package/public/assets/rst-B0xPkSld.js +1 -0
  328. package/public/assets/ruby-BvKwtOVI.js +1 -0
  329. package/public/assets/rust-B1yitclQ.js +1 -0
  330. package/public/assets/sas-cz2c8ADy.js +1 -0
  331. package/public/assets/sass-Cj5Yp3dK.js +1 -0
  332. package/public/assets/scala-C151Ov-r.js +1 -0
  333. package/public/assets/scheme-C98Dy4si.js +1 -0
  334. package/public/assets/scss-OYdSNvt2.js +1 -0
  335. package/public/assets/sdbl-DVxCFoDh.js +1 -0
  336. package/public/assets/shaderlab-Dg9Lc6iA.js +1 -0
  337. package/public/assets/shellscript-Yzrsuije.js +1 -0
  338. package/public/assets/shellsession-BADoaaVG.js +1 -0
  339. package/public/assets/slack-dark-BthQWCQV.js +1 -0
  340. package/public/assets/slack-ochin-DqwNpetd.js +1 -0
  341. package/public/assets/smalltalk-BERRCDM3.js +1 -0
  342. package/public/assets/snazzy-light-Bw305WKR.js +1 -0
  343. package/public/assets/solarized-dark-DXbdFlpD.js +1 -0
  344. package/public/assets/solarized-light-L9t79GZl.js +1 -0
  345. package/public/assets/solidity-BbcW6ACK.js +1 -0
  346. package/public/assets/soy-Brmx7dQM.js +1 -0
  347. package/public/assets/sparql-rVzFXLq3.js +1 -0
  348. package/public/assets/splunk-BtCnVYZw.js +1 -0
  349. package/public/assets/sql-BLtJtn59.js +1 -0
  350. package/public/assets/ssh-config-_ykCGR6B.js +1 -0
  351. package/public/assets/stata-BH5u7GGu.js +1 -0
  352. package/public/assets/stylus-BEDo0Tqx.js +1 -0
  353. package/public/assets/svelte-3Dk4HxPD.js +1 -0
  354. package/public/assets/swift-Dg5xB15N.js +1 -0
  355. package/public/assets/synthwave-84-CbfX1IO0.js +1 -0
  356. package/public/assets/system-verilog-CnnmHF94.js +1 -0
  357. package/public/assets/systemd-4A_iFExJ.js +1 -0
  358. package/public/assets/talonscript-CkByrt1z.js +1 -0
  359. package/public/assets/tasl-QIJgUcNo.js +1 -0
  360. package/public/assets/tcl-dwOrl1Do.js +1 -0
  361. package/public/assets/templ-W15q3VgB.js +1 -0
  362. package/public/assets/terraform-BETggiCN.js +1 -0
  363. package/public/assets/tex-Cppo0RY3.js +1 -0
  364. package/public/assets/todo-uxdyLWei.js +1 -0
  365. package/public/assets/tokyo-night-hegEt444.js +1 -0
  366. package/public/assets/toml-vGWfd6FD.js +1 -0
  367. package/public/assets/tool-call-C_JEoVSV.js +60 -0
  368. package/public/assets/ts-tags-zn1MmPIZ.js +1 -0
  369. package/public/assets/tsv-B_m7g4N7.js +1 -0
  370. package/public/assets/tsx-COt5Ahok.js +1 -0
  371. package/public/assets/turtle-BsS91CYL.js +1 -0
  372. package/public/assets/twig-CO9l9SDP.js +1 -0
  373. package/public/assets/typescript-BPQ3VLAy.js +1 -0
  374. package/public/assets/typespec-Df68jz8_.js +1 -0
  375. package/public/assets/typst-DHCkPAjA.js +1 -0
  376. package/public/assets/unified-picker-ePaJEYDm.js +1 -0
  377. package/public/assets/v-BcVCzyr7.js +1 -0
  378. package/public/assets/vala-CsfeWuGM.js +1 -0
  379. package/public/assets/vb-D17OF-Vu.js +1 -0
  380. package/public/assets/verilog-BQ8w6xss.js +1 -0
  381. package/public/assets/vesper-DU1UobuO.js +1 -0
  382. package/public/assets/vhdl-CeAyd5Ju.js +1 -0
  383. package/public/assets/viml-CJc9bBzg.js +1 -0
  384. package/public/assets/vitesse-black-Bkuqu6BP.js +1 -0
  385. package/public/assets/vitesse-dark-D0r3Knsf.js +1 -0
  386. package/public/assets/vitesse-light-CVO1_9PV.js +1 -0
  387. package/public/assets/vue-CCoi5OLL.js +1 -0
  388. package/public/assets/vue-html-DAAvJJDi.js +1 -0
  389. package/public/assets/vue-vine-_Ih-lPRR.js +1 -0
  390. package/public/assets/vyper-CDx5xZoG.js +1 -0
  391. package/public/assets/wasm-CG6Dc4jp.js +1 -0
  392. package/public/assets/wasm-MzD3tlZU.js +1 -0
  393. package/public/assets/wenyan-BV7otONQ.js +1 -0
  394. package/public/assets/wgsl-Dx-B1_4e.js +1 -0
  395. package/public/assets/wikitext-BhOHFoWU.js +1 -0
  396. package/public/assets/wit-5i3qLPDT.js +1 -0
  397. package/public/assets/wolfram-lXgVvXCa.js +1 -0
  398. package/public/assets/wrap-text-S8HH4qqP.js +1 -0
  399. package/public/assets/xml-sdJ4AIDG.js +1 -0
  400. package/public/assets/xsl-CtQFsRM5.js +1 -0
  401. package/public/assets/yaml-Buea-lGh.js +1 -0
  402. package/public/assets/zenscript-DVFEvuxE.js +1 -0
  403. package/public/assets/zig-VOosw3JB.js +1 -0
  404. package/public/favicon.ico +0 -0
  405. package/public/index.html +44 -0
  406. package/public/loading.html +33 -0
  407. package/public/logo.png +0 -0
  408. package/public/manifest.webmanifest +1 -0
  409. package/public/maskable-icon-512x512.png +0 -0
  410. package/public/monaco/vs/base/browser/ui/codicons/codicon/codicon.ttf +0 -0
  411. package/public/monaco/vs/base/worker/workerMain.js +31 -0
  412. package/public/monaco/vs/basic-languages/cpp/cpp.js +10 -0
  413. package/public/monaco/vs/basic-languages/kotlin/kotlin.js +10 -0
  414. package/public/monaco/vs/basic-languages/markdown/markdown.js +10 -0
  415. package/public/monaco/vs/basic-languages/python/python.js +10 -0
  416. package/public/monaco/vs/editor/editor.main.css +8 -0
  417. package/public/monaco/vs/editor/editor.main.js +798 -0
  418. package/public/monaco/vs/language/css/cssMode.js +13 -0
  419. package/public/monaco/vs/language/css/cssWorker.js +77 -0
  420. package/public/monaco/vs/language/html/htmlMode.js +13 -0
  421. package/public/monaco/vs/language/html/htmlWorker.js +454 -0
  422. package/public/monaco/vs/language/json/jsonMode.js +19 -0
  423. package/public/monaco/vs/language/json/jsonWorker.js +42 -0
  424. package/public/monaco/vs/language/typescript/tsMode.js +20 -0
  425. package/public/monaco/vs/language/typescript/tsWorker.js +51328 -0
  426. package/public/monaco/vs/loader.js +11 -0
  427. package/public/monaco.worker.js +7 -0
  428. package/public/pwa-192x192.png +0 -0
  429. package/public/pwa-512x512.png +0 -0
  430. package/public/pwa-64x64.png +0 -0
  431. package/public/registerSW.js +1 -0
  432. package/public/sw.js +1 -0
  433. package/public/ui-version.json +3 -0
  434. package/public/workbox-60d14903.js +1 -0
@@ -0,0 +1,57 @@
1
+ import os from "os";
2
+ import path from "path";
3
+ function resolvePath(inputPath) {
4
+ if (inputPath.startsWith("~/")) {
5
+ return path.join(os.homedir(), inputPath.slice(2));
6
+ }
7
+ return path.resolve(inputPath);
8
+ }
9
+ function isYamlPath(filePath) {
10
+ const lower = filePath.toLowerCase();
11
+ return lower.endsWith(".yaml") || lower.endsWith(".yml");
12
+ }
13
+ function isJsonPath(filePath) {
14
+ return filePath.toLowerCase().endsWith(".json");
15
+ }
16
+ /**
17
+ * Resolve EmbeddedCowork's config location into a stable base directory + derived file paths.
18
+ *
19
+ * Supported inputs:
20
+ * - Directory: "~/.config/embeddedcowork"
21
+ * - YAML file: "~/.config/embeddedcowork/config.yaml" (or any *.yml/*.yaml)
22
+ * - Legacy JSON file: "~/.config/embeddedcowork/config.json"
23
+ */
24
+ export function resolveConfigLocation(raw) {
25
+ const trimmed = (raw ?? "").trim();
26
+ const fallback = "~/.config/embeddedcowork/config.json";
27
+ const input = trimmed.length > 0 ? trimmed : fallback;
28
+ const resolvedInput = resolvePath(input);
29
+ if (isYamlPath(resolvedInput)) {
30
+ const baseDir = path.dirname(resolvedInput);
31
+ return {
32
+ baseDir,
33
+ configYamlPath: resolvedInput,
34
+ stateYamlPath: path.join(baseDir, "state.yaml"),
35
+ legacyJsonPath: path.join(baseDir, "config.json"),
36
+ instancesDir: path.join(baseDir, "instances"),
37
+ };
38
+ }
39
+ if (isJsonPath(resolvedInput)) {
40
+ const baseDir = path.dirname(resolvedInput);
41
+ return {
42
+ baseDir,
43
+ configYamlPath: path.join(baseDir, "config.yaml"),
44
+ stateYamlPath: path.join(baseDir, "state.yaml"),
45
+ legacyJsonPath: resolvedInput,
46
+ instancesDir: path.join(baseDir, "instances"),
47
+ };
48
+ }
49
+ const baseDir = resolvedInput;
50
+ return {
51
+ baseDir,
52
+ configYamlPath: path.join(baseDir, "config.yaml"),
53
+ stateYamlPath: path.join(baseDir, "state.yaml"),
54
+ legacyJsonPath: path.join(baseDir, "config.json"),
55
+ instancesDir: path.join(baseDir, "instances"),
56
+ };
57
+ }
@@ -0,0 +1,71 @@
1
+ import { z } from "zod";
2
+ const ModelPreferenceSchema = z.object({
3
+ providerId: z.string(),
4
+ modelId: z.string(),
5
+ });
6
+ const AgentModelSelectionSchema = z.record(z.string(), ModelPreferenceSchema);
7
+ const AgentModelSelectionsSchema = z.record(z.string(), AgentModelSelectionSchema);
8
+ const PreferencesSchema = z
9
+ .object({
10
+ showThinkingBlocks: z.boolean().default(false),
11
+ thinkingBlocksExpansion: z.enum(["expanded", "collapsed"]).default("expanded"),
12
+ showTimelineTools: z.boolean().default(true),
13
+ promptSubmitOnEnter: z.boolean().default(false),
14
+ lastUsedBinary: z.string().optional(),
15
+ locale: z.string().optional(),
16
+ environmentVariables: z.record(z.string()).default({}),
17
+ modelRecents: z.array(ModelPreferenceSchema).default([]),
18
+ modelFavorites: z.array(ModelPreferenceSchema).default([]),
19
+ modelThinkingSelections: z.record(z.string(), z.string()).default({}),
20
+ diffViewMode: z.enum(["split", "unified"]).default("split"),
21
+ toolOutputExpansion: z.enum(["expanded", "collapsed"]).default("expanded"),
22
+ diagnosticsExpansion: z.enum(["expanded", "collapsed"]).default("expanded"),
23
+ showUsageMetrics: z.boolean().default(true),
24
+ autoCleanupBlankSessions: z.boolean().default(true),
25
+ listeningMode: z.enum(["local", "all"]).default("local"),
26
+ logLevel: z.enum(["DEBUG", "INFO", "WARN", "ERROR"]).default("DEBUG"),
27
+ // OS notifications
28
+ osNotificationsEnabled: z.boolean().default(false),
29
+ osNotificationsAllowWhenVisible: z.boolean().default(false),
30
+ notifyOnNeedsInput: z.boolean().default(true),
31
+ notifyOnIdle: z.boolean().default(true),
32
+ })
33
+ // Preserve unknown preference keys so newer configs survive older binaries.
34
+ .passthrough();
35
+ const RecentFolderSchema = z.object({
36
+ path: z.string(),
37
+ lastAccessed: z.number().nonnegative(),
38
+ });
39
+ const OpenCodeBinarySchema = z.object({
40
+ path: z.string(),
41
+ version: z.string().optional(),
42
+ lastUsed: z.number().nonnegative(),
43
+ label: z.string().optional(),
44
+ });
45
+ const ConfigFileSchema = z
46
+ .object({
47
+ preferences: PreferencesSchema.default({}),
48
+ recentFolders: z.array(RecentFolderSchema).default([]),
49
+ opencodeBinaries: z.array(OpenCodeBinarySchema).default([]),
50
+ theme: z.enum(["light", "dark", "system"]).optional(),
51
+ })
52
+ // Preserve unknown top-level keys so optional future features survive downgrades.
53
+ .passthrough();
54
+ // On-disk config.yaml only stores stable configuration (not volatile state like recent folders).
55
+ const ConfigYamlSchema = z
56
+ .object({
57
+ preferences: PreferencesSchema.default({}),
58
+ opencodeBinaries: z.array(OpenCodeBinarySchema).default([]),
59
+ theme: z.enum(["light", "dark", "system"]).optional(),
60
+ })
61
+ .passthrough();
62
+ // On-disk state.yaml stores server-scoped mutable state (per-server, not per-client).
63
+ const StateFileSchema = z
64
+ .object({
65
+ recentFolders: z.array(RecentFolderSchema).default([]),
66
+ })
67
+ .passthrough();
68
+ const DEFAULT_CONFIG = ConfigFileSchema.parse({});
69
+ const DEFAULT_CONFIG_YAML = ConfigYamlSchema.parse({});
70
+ const DEFAULT_STATE = StateFileSchema.parse({});
71
+ export { ModelPreferenceSchema, AgentModelSelectionSchema, AgentModelSelectionsSchema, PreferencesSchema, RecentFolderSchema, OpenCodeBinarySchema, ConfigFileSchema, ConfigYamlSchema, StateFileSchema, DEFAULT_CONFIG, DEFAULT_CONFIG_YAML, DEFAULT_STATE, };
@@ -0,0 +1,45 @@
1
+ import { EventEmitter } from "events";
2
+ export class EventBus extends EventEmitter {
3
+ constructor(logger) {
4
+ super();
5
+ this.logger = logger;
6
+ }
7
+ publish(event) {
8
+ if (event.type !== "instance.event" && event.type !== "instance.eventStatus") {
9
+ this.logger?.debug({ type: event.type }, "Publishing workspace event");
10
+ if (this.logger?.isLevelEnabled("trace")) {
11
+ this.logger.trace({ event }, "Workspace event payload");
12
+ }
13
+ }
14
+ return super.emit(event.type, event);
15
+ }
16
+ onEvent(listener) {
17
+ const handler = (event) => listener(event);
18
+ this.on("workspace.created", handler);
19
+ this.on("workspace.started", handler);
20
+ this.on("workspace.error", handler);
21
+ this.on("workspace.stopped", handler);
22
+ this.on("workspace.log", handler);
23
+ this.on("sidecar.updated", handler);
24
+ this.on("sidecar.removed", handler);
25
+ this.on("storage.configChanged", handler);
26
+ this.on("storage.stateChanged", handler);
27
+ this.on("instance.dataChanged", handler);
28
+ this.on("instance.event", handler);
29
+ this.on("instance.eventStatus", handler);
30
+ return () => {
31
+ this.off("workspace.created", handler);
32
+ this.off("workspace.started", handler);
33
+ this.off("workspace.error", handler);
34
+ this.off("workspace.stopped", handler);
35
+ this.off("workspace.log", handler);
36
+ this.off("sidecar.updated", handler);
37
+ this.off("sidecar.removed", handler);
38
+ this.off("storage.configChanged", handler);
39
+ this.off("storage.stateChanged", handler);
40
+ this.off("instance.dataChanged", handler);
41
+ this.off("instance.event", handler);
42
+ this.off("instance.eventStatus", handler);
43
+ };
44
+ }
45
+ }
@@ -0,0 +1,40 @@
1
+ import assert from "node:assert/strict";
2
+ import { beforeEach, describe, it } from "node:test";
3
+ import { clearWorkspaceSearchCache, getWorkspaceCandidates, refreshWorkspaceCandidates, WORKSPACE_CANDIDATE_CACHE_TTL_MS, } from "../search-cache";
4
+ describe("workspace search cache", () => {
5
+ beforeEach(() => {
6
+ clearWorkspaceSearchCache();
7
+ });
8
+ it("expires cached candidates after the TTL", () => {
9
+ const workspacePath = "/tmp/workspace";
10
+ const startTime = 1000;
11
+ refreshWorkspaceCandidates(workspacePath, () => [createEntry("file-a")], startTime);
12
+ const beforeExpiry = getWorkspaceCandidates(workspacePath, startTime + WORKSPACE_CANDIDATE_CACHE_TTL_MS - 1);
13
+ assert.ok(beforeExpiry);
14
+ assert.equal(beforeExpiry.length, 1);
15
+ assert.equal(beforeExpiry[0].name, "file-a");
16
+ const afterExpiry = getWorkspaceCandidates(workspacePath, startTime + WORKSPACE_CANDIDATE_CACHE_TTL_MS + 1);
17
+ assert.equal(afterExpiry, undefined);
18
+ });
19
+ it("replaces cached entries when manually refreshed", () => {
20
+ const workspacePath = "/tmp/workspace";
21
+ refreshWorkspaceCandidates(workspacePath, () => [createEntry("file-a")], 5000);
22
+ const initial = getWorkspaceCandidates(workspacePath);
23
+ assert.ok(initial);
24
+ assert.equal(initial[0].name, "file-a");
25
+ refreshWorkspaceCandidates(workspacePath, () => [createEntry("file-b")], 6000);
26
+ const refreshed = getWorkspaceCandidates(workspacePath);
27
+ assert.ok(refreshed);
28
+ assert.equal(refreshed[0].name, "file-b");
29
+ });
30
+ });
31
+ function createEntry(name) {
32
+ return {
33
+ name,
34
+ path: name,
35
+ absolutePath: `/tmp/${name}`,
36
+ type: "file",
37
+ size: 1,
38
+ modifiedAt: new Date().toISOString(),
39
+ };
40
+ }
@@ -0,0 +1,292 @@
1
+ import fs from "fs";
2
+ import os from "os";
3
+ import path from "path";
4
+ import { WINDOWS_DRIVES_ROOT, } from "../api-types";
5
+ const WINDOWS_DRIVE_LETTERS = Array.from({ length: 26 }, (_, i) => String.fromCharCode(65 + i));
6
+ export class FileSystemBrowser {
7
+ constructor(options) {
8
+ this.root = path.resolve(options.rootDir);
9
+ this.unrestricted = Boolean(options.unrestricted);
10
+ this.homeDir = os.homedir();
11
+ this.isWindows = process.platform === "win32";
12
+ }
13
+ list(relativePath = ".", options = {}) {
14
+ if (this.unrestricted) {
15
+ throw new Error("Relative listing is unavailable when running with unrestricted root");
16
+ }
17
+ const includeFiles = options.includeFiles ?? true;
18
+ const normalizedPath = this.normalizeRelativePath(relativePath);
19
+ const absolutePath = this.toRestrictedAbsolute(normalizedPath);
20
+ return this.readDirectoryEntries(absolutePath, {
21
+ includeFiles,
22
+ formatPath: (entryName) => this.buildRelativePath(normalizedPath, entryName),
23
+ formatAbsolutePath: (entryName) => this.resolveRestrictedAbsoluteChild(normalizedPath, entryName),
24
+ });
25
+ }
26
+ browse(targetPath, options = {}) {
27
+ const includeFiles = options.includeFiles ?? true;
28
+ if (this.unrestricted) {
29
+ return this.listUnrestricted(targetPath, includeFiles);
30
+ }
31
+ return this.listRestrictedWithMetadata(targetPath, includeFiles);
32
+ }
33
+ createFolder(parentPath, folderName) {
34
+ const name = this.normalizeFolderName(folderName);
35
+ if (this.unrestricted) {
36
+ const resolvedParent = this.resolveUnrestrictedPath(parentPath);
37
+ if (this.isWindows && resolvedParent === WINDOWS_DRIVES_ROOT) {
38
+ throw new Error("Cannot create folders at drive root");
39
+ }
40
+ this.assertDirectoryExists(resolvedParent);
41
+ const absolutePath = this.resolveAbsoluteChild(resolvedParent, name);
42
+ fs.mkdirSync(absolutePath);
43
+ return { path: absolutePath, absolutePath };
44
+ }
45
+ const normalizedParent = this.normalizeRelativePath(parentPath);
46
+ const parentAbsolute = this.toRestrictedAbsolute(normalizedParent);
47
+ this.assertDirectoryExists(parentAbsolute);
48
+ const relativePath = this.buildRelativePath(normalizedParent, name);
49
+ const absolutePath = this.toRestrictedAbsolute(relativePath);
50
+ fs.mkdirSync(absolutePath);
51
+ return { path: relativePath, absolutePath };
52
+ }
53
+ writeFile(relativePath, contents) {
54
+ if (this.unrestricted) {
55
+ throw new Error("writeFile is not available in unrestricted mode");
56
+ }
57
+ const resolved = this.toRestrictedAbsolute(relativePath);
58
+ fs.writeFileSync(resolved, contents, "utf-8");
59
+ }
60
+ readFile(relativePath) {
61
+ if (this.unrestricted) {
62
+ throw new Error("readFile is not available in unrestricted mode");
63
+ }
64
+ const resolved = this.toRestrictedAbsolute(relativePath);
65
+ return fs.readFileSync(resolved, "utf-8");
66
+ }
67
+ listRestrictedWithMetadata(relativePath, includeFiles) {
68
+ const normalizedPath = this.normalizeRelativePath(relativePath);
69
+ const absolutePath = this.toRestrictedAbsolute(normalizedPath);
70
+ const entries = this.readDirectoryEntries(absolutePath, {
71
+ includeFiles,
72
+ formatPath: (entryName) => this.buildRelativePath(normalizedPath, entryName),
73
+ formatAbsolutePath: (entryName) => this.resolveRestrictedAbsoluteChild(normalizedPath, entryName),
74
+ });
75
+ const metadata = {
76
+ scope: "restricted",
77
+ currentPath: normalizedPath,
78
+ parentPath: normalizedPath === "." ? undefined : this.getRestrictedParent(normalizedPath),
79
+ rootPath: this.root,
80
+ homePath: this.homeDir,
81
+ displayPath: this.resolveRestrictedAbsolute(normalizedPath),
82
+ pathKind: "relative",
83
+ };
84
+ return { entries, metadata };
85
+ }
86
+ listUnrestricted(targetPath, includeFiles) {
87
+ const resolvedPath = this.resolveUnrestrictedPath(targetPath);
88
+ if (this.isWindows && resolvedPath === WINDOWS_DRIVES_ROOT) {
89
+ return this.listWindowsDrives();
90
+ }
91
+ const entries = this.readDirectoryEntries(resolvedPath, {
92
+ includeFiles,
93
+ formatPath: (entryName) => this.resolveAbsoluteChild(resolvedPath, entryName),
94
+ formatAbsolutePath: (entryName) => this.resolveAbsoluteChild(resolvedPath, entryName),
95
+ });
96
+ const parentPath = this.getUnrestrictedParent(resolvedPath);
97
+ const metadata = {
98
+ scope: "unrestricted",
99
+ currentPath: resolvedPath,
100
+ parentPath,
101
+ rootPath: this.homeDir,
102
+ homePath: this.homeDir,
103
+ displayPath: resolvedPath,
104
+ pathKind: "absolute",
105
+ };
106
+ return { entries, metadata };
107
+ }
108
+ listWindowsDrives() {
109
+ if (!this.isWindows) {
110
+ throw new Error("Drive listing is only supported on Windows hosts");
111
+ }
112
+ const entries = [];
113
+ for (const letter of WINDOWS_DRIVE_LETTERS) {
114
+ const drivePath = `${letter}:\\`;
115
+ try {
116
+ if (fs.existsSync(drivePath)) {
117
+ entries.push({
118
+ name: `${letter}:`,
119
+ path: drivePath,
120
+ absolutePath: drivePath,
121
+ type: "directory",
122
+ });
123
+ }
124
+ }
125
+ catch {
126
+ // Ignore inaccessible drives
127
+ }
128
+ }
129
+ // Provide a generic UNC root entry so users can navigate to network shares manually.
130
+ entries.push({
131
+ name: "UNC Network",
132
+ path: "\\\\",
133
+ absolutePath: "\\\\",
134
+ type: "directory",
135
+ });
136
+ const metadata = {
137
+ scope: "unrestricted",
138
+ currentPath: WINDOWS_DRIVES_ROOT,
139
+ parentPath: undefined,
140
+ rootPath: this.homeDir,
141
+ homePath: this.homeDir,
142
+ displayPath: "Drives",
143
+ pathKind: "drives",
144
+ };
145
+ return { entries, metadata };
146
+ }
147
+ normalizeFolderName(input) {
148
+ const name = input.trim();
149
+ if (!name) {
150
+ throw new Error("Folder name is required");
151
+ }
152
+ if (name === "." || name === "..") {
153
+ throw new Error("Invalid folder name");
154
+ }
155
+ if (name.startsWith("~")) {
156
+ throw new Error("Invalid folder name");
157
+ }
158
+ if (name.includes("/") || name.includes("\\")) {
159
+ throw new Error("Folder name must not include path separators");
160
+ }
161
+ if (name.includes("\u0000")) {
162
+ throw new Error("Invalid folder name");
163
+ }
164
+ return name;
165
+ }
166
+ assertDirectoryExists(directory) {
167
+ if (!fs.existsSync(directory)) {
168
+ throw new Error(`Directory does not exist: ${directory}`);
169
+ }
170
+ const stats = fs.statSync(directory);
171
+ if (!stats.isDirectory()) {
172
+ throw new Error(`Path is not a directory: ${directory}`);
173
+ }
174
+ }
175
+ readDirectoryEntries(directory, options) {
176
+ const dirents = fs.readdirSync(directory, { withFileTypes: true });
177
+ const results = [];
178
+ for (const entry of dirents) {
179
+ const absoluteEntryPath = path.join(directory, entry.name);
180
+ let stats;
181
+ try {
182
+ // Use fs.statSync (not Dirent.isDirectory) so symlinks to directories
183
+ // are treated as directories in directory-only listings.
184
+ stats = fs.statSync(absoluteEntryPath);
185
+ }
186
+ catch {
187
+ // Skip entries we cannot stat (insufficient permissions, etc.)
188
+ continue;
189
+ }
190
+ const isDirectory = stats.isDirectory();
191
+ if (!options.includeFiles && !isDirectory) {
192
+ continue;
193
+ }
194
+ results.push({
195
+ name: entry.name,
196
+ path: options.formatPath(entry.name),
197
+ absolutePath: options.formatAbsolutePath(entry.name),
198
+ type: isDirectory ? "directory" : "file",
199
+ size: isDirectory ? undefined : stats.size,
200
+ modifiedAt: stats.mtime.toISOString(),
201
+ });
202
+ }
203
+ return results.sort((a, b) => a.name.localeCompare(b.name));
204
+ }
205
+ normalizeRelativePath(input) {
206
+ if (!input || input === "." || input === "./" || input === "/") {
207
+ return ".";
208
+ }
209
+ let normalized = input.replace(/\\+/g, "/");
210
+ if (normalized.startsWith("./")) {
211
+ normalized = normalized.replace(/^\.\/+/, "");
212
+ }
213
+ if (normalized.startsWith("/")) {
214
+ normalized = normalized.replace(/^\/+/g, "");
215
+ }
216
+ return normalized === "" ? "." : normalized;
217
+ }
218
+ buildRelativePath(parent, child) {
219
+ if (!parent || parent === ".") {
220
+ return this.normalizeRelativePath(child);
221
+ }
222
+ return this.normalizeRelativePath(`${parent}/${child}`);
223
+ }
224
+ resolveRestrictedAbsolute(relativePath) {
225
+ return this.toRestrictedAbsolute(relativePath);
226
+ }
227
+ resolveRestrictedAbsoluteChild(parent, child) {
228
+ const normalized = this.buildRelativePath(parent, child);
229
+ return this.toRestrictedAbsolute(normalized);
230
+ }
231
+ toRestrictedAbsolute(relativePath) {
232
+ const normalized = this.normalizeRelativePath(relativePath);
233
+ const target = path.resolve(this.root, normalized);
234
+ const relativeToRoot = path.relative(this.root, target);
235
+ if (relativeToRoot.startsWith("..") || path.isAbsolute(relativeToRoot) && relativeToRoot !== "") {
236
+ throw new Error("Access outside of root is not allowed");
237
+ }
238
+ return target;
239
+ }
240
+ resolveUnrestrictedPath(input) {
241
+ if (!input || input === "." || input === "./") {
242
+ return this.homeDir;
243
+ }
244
+ if (this.isWindows) {
245
+ if (input === WINDOWS_DRIVES_ROOT) {
246
+ return WINDOWS_DRIVES_ROOT;
247
+ }
248
+ const normalized = path.win32.normalize(input);
249
+ if (/^[a-zA-Z]:/.test(normalized) || normalized.startsWith("\\\\")) {
250
+ return normalized;
251
+ }
252
+ return path.win32.resolve(this.homeDir, normalized);
253
+ }
254
+ if (input.startsWith("/")) {
255
+ return path.posix.normalize(input);
256
+ }
257
+ return path.posix.resolve(this.homeDir, input);
258
+ }
259
+ resolveAbsoluteChild(parent, child) {
260
+ if (this.isWindows) {
261
+ return path.win32.normalize(path.win32.join(parent, child));
262
+ }
263
+ return path.posix.normalize(path.posix.join(parent, child));
264
+ }
265
+ getRestrictedParent(relativePath) {
266
+ const normalized = this.normalizeRelativePath(relativePath);
267
+ if (normalized === ".") {
268
+ return undefined;
269
+ }
270
+ const segments = normalized.split("/");
271
+ segments.pop();
272
+ return segments.length === 0 ? "." : segments.join("/");
273
+ }
274
+ getUnrestrictedParent(currentPath) {
275
+ if (this.isWindows) {
276
+ const normalized = path.win32.normalize(currentPath);
277
+ const parsed = path.win32.parse(normalized);
278
+ if (normalized === WINDOWS_DRIVES_ROOT) {
279
+ return undefined;
280
+ }
281
+ if (normalized === parsed.root) {
282
+ return WINDOWS_DRIVES_ROOT;
283
+ }
284
+ return path.win32.dirname(normalized);
285
+ }
286
+ const normalized = path.posix.normalize(currentPath);
287
+ if (normalized === "/") {
288
+ return undefined;
289
+ }
290
+ return path.posix.dirname(normalized);
291
+ }
292
+ }
@@ -0,0 +1,43 @@
1
+ import path from "path";
2
+ export const WORKSPACE_CANDIDATE_CACHE_TTL_MS = 30000;
3
+ const workspaceCandidateCache = new Map();
4
+ export function getWorkspaceCandidates(rootDir, now = Date.now()) {
5
+ const key = normalizeKey(rootDir);
6
+ const cached = workspaceCandidateCache.get(key);
7
+ if (!cached) {
8
+ return undefined;
9
+ }
10
+ if (cached.expiresAt <= now) {
11
+ workspaceCandidateCache.delete(key);
12
+ return undefined;
13
+ }
14
+ return cloneEntries(cached.candidates);
15
+ }
16
+ export function refreshWorkspaceCandidates(rootDir, builder, now = Date.now()) {
17
+ const key = normalizeKey(rootDir);
18
+ const freshCandidates = builder();
19
+ if (!freshCandidates || freshCandidates.length === 0) {
20
+ workspaceCandidateCache.delete(key);
21
+ return [];
22
+ }
23
+ const storedCandidates = cloneEntries(freshCandidates);
24
+ workspaceCandidateCache.set(key, {
25
+ expiresAt: now + WORKSPACE_CANDIDATE_CACHE_TTL_MS,
26
+ candidates: storedCandidates,
27
+ });
28
+ return cloneEntries(storedCandidates);
29
+ }
30
+ export function clearWorkspaceSearchCache(rootDir) {
31
+ if (typeof rootDir === "undefined") {
32
+ workspaceCandidateCache.clear();
33
+ return;
34
+ }
35
+ const key = normalizeKey(rootDir);
36
+ workspaceCandidateCache.delete(key);
37
+ }
38
+ function cloneEntries(entries) {
39
+ return entries.map((entry) => ({ ...entry }));
40
+ }
41
+ function normalizeKey(rootDir) {
42
+ return path.resolve(rootDir);
43
+ }
@@ -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
+ }