@vividcodeai/embeddedcowork 0.0.22 → 0.0.24

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 (438) hide show
  1. package/dist/api-types.js +1 -0
  2. package/dist/auth/auth-store.js +134 -0
  3. package/dist/auth/http-auth.js +37 -0
  4. package/dist/auth/manager.js +140 -0
  5. package/dist/auth/password-hash.js +32 -0
  6. package/dist/auth/session-manager.js +17 -0
  7. package/dist/auth/token-manager.js +27 -0
  8. package/dist/background-processes/manager.js +576 -0
  9. package/dist/bin.js +24 -0
  10. package/dist/clients/connection-manager.js +93 -0
  11. package/dist/config/location.js +57 -0
  12. package/dist/config/schema.js +72 -0
  13. package/dist/events/bus.js +47 -0
  14. package/dist/filesystem/__tests__/search-cache.test.js +40 -0
  15. package/dist/filesystem/browser.js +292 -0
  16. package/dist/filesystem/search-cache.js +43 -0
  17. package/dist/filesystem/search.js +135 -0
  18. package/dist/index.js +496 -0
  19. package/dist/launcher.js +149 -0
  20. package/dist/loader.js +21 -0
  21. package/dist/logger.js +109 -0
  22. package/dist/opencode-config/README.md +32 -0
  23. package/dist/opencode-config/opencode.jsonc +35 -0
  24. package/dist/opencode-config/package.json +9 -0
  25. package/dist/opencode-config/plugin/embeddedcowork.ts +62 -0
  26. package/dist/opencode-config/plugin/lib/background-process.ts +265 -0
  27. package/dist/opencode-config/plugin/lib/client.ts +133 -0
  28. package/dist/opencode-config/plugin/lib/request.ts +214 -0
  29. package/dist/opencode-config.js +15 -0
  30. package/dist/opencode-downloader.js +295 -0
  31. package/dist/opencode-paths.js +167 -0
  32. package/dist/plugins/channel.js +40 -0
  33. package/dist/plugins/handlers.js +17 -0
  34. package/dist/plugins/voice-mode.js +78 -0
  35. package/dist/releases/dev-release-monitor.js +75 -0
  36. package/dist/releases/release-monitor.js +107 -0
  37. package/dist/releases/rollback.js +54 -0
  38. package/dist/runtime-paths.js +67 -0
  39. package/dist/server/__tests__/network-addresses.test.js +68 -0
  40. package/dist/server/__tests__/remote-proxy.test.js +204 -0
  41. package/dist/server/http-server.js +998 -0
  42. package/dist/server/network-addresses.js +114 -0
  43. package/dist/server/remote-proxy.js +466 -0
  44. package/dist/server/routes/auth-pages/login.html +135 -0
  45. package/dist/server/routes/auth-pages/token.html +93 -0
  46. package/dist/server/routes/auth.js +149 -0
  47. package/dist/server/routes/background-processes.js +78 -0
  48. package/dist/server/routes/events.js +66 -0
  49. package/dist/server/routes/filesystem.js +43 -0
  50. package/dist/server/routes/meta.js +44 -0
  51. package/dist/server/routes/opencode-status.js +10 -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__/spawn.test.js +139 -0
  75. package/dist/workspaces/git-mutations.js +98 -0
  76. package/dist/workspaces/git-status.js +323 -0
  77. package/dist/workspaces/git-worktrees.js +216 -0
  78. package/dist/workspaces/instance-events.js +180 -0
  79. package/dist/workspaces/manager.js +432 -0
  80. package/dist/workspaces/opencode-auth.js +16 -0
  81. package/dist/workspaces/runtime.js +366 -0
  82. package/dist/workspaces/spawn.js +219 -0
  83. package/dist/workspaces/worktree-directory.js +74 -0
  84. package/dist/workspaces/worktree-map.js +116 -0
  85. package/package.json +3 -12
  86. package/public/apple-touch-icon-180x180.png +0 -0
  87. package/public/assets/ChangesTab-Uu8GvqIU.js +2 -0
  88. package/public/assets/DiffToolbar-BgdJy7ap.js +1 -0
  89. package/public/assets/EmbeddedCowork-Icon-DSw5nKk7.png +0 -0
  90. package/public/assets/FilesTab-BlKXggYW.js +2 -0
  91. package/public/assets/GitChangesTab-DRAyGtTx.js +2 -0
  92. package/public/assets/SplitFilePanel-DR88B4Vy.js +1 -0
  93. package/public/assets/StatusTab-BS7K80gj.js +1 -0
  94. package/public/assets/abap-BdImnpbu.js +1 -0
  95. package/public/assets/actionscript-3-CfeIJUat.js +1 -0
  96. package/public/assets/ada-bCR0ucgS.js +1 -0
  97. package/public/assets/andromeeda-C-Jbm3Hp.js +1 -0
  98. package/public/assets/angular-html-CU67Zn6k.js +1 -0
  99. package/public/assets/angular-ts-BwZT4LLn.js +1 -0
  100. package/public/assets/apache-Pmp26Uib.js +1 -0
  101. package/public/assets/apex-DhZLUxFE.js +1 -0
  102. package/public/assets/apl-dKokRX4l.js +1 -0
  103. package/public/assets/applescript-Co6uUVPk.js +1 -0
  104. package/public/assets/ara-BRHolxvo.js +1 -0
  105. package/public/assets/asciidoc-Dv7Oe6Be.js +1 -0
  106. package/public/assets/asm-D_Q5rh1f.js +1 -0
  107. package/public/assets/astro-CbQHKStN.js +1 -0
  108. package/public/assets/aurora-x-D-2ljcwZ.js +1 -0
  109. package/public/assets/awk-DMzUqQB5.js +1 -0
  110. package/public/assets/ayu-dark-Cv9koXgw.js +1 -0
  111. package/public/assets/ballerina-BFfxhgS-.js +1 -0
  112. package/public/assets/bat-BkioyH1T.js +1 -0
  113. package/public/assets/beancount-k_qm7-4y.js +1 -0
  114. package/public/assets/berry-D08WgyRC.js +1 -0
  115. package/public/assets/bibtex-CHM0blh-.js +1 -0
  116. package/public/assets/bicep-Bmn6On1c.js +1 -0
  117. package/public/assets/blade-DVc8C-J4.js +1 -0
  118. package/public/assets/bsl-BO_Y6i37.js +1 -0
  119. package/public/assets/bundle-full-BusrfhOv.js +13 -0
  120. package/public/assets/c-BIGW1oBm.js +1 -0
  121. package/public/assets/cadence-Bv_4Rxtq.js +1 -0
  122. package/public/assets/cairo-KRGpt6FW.js +1 -0
  123. package/public/assets/catppuccin-frappe-DFWUc33u.js +1 -0
  124. package/public/assets/catppuccin-latte-C9dUb6Cb.js +1 -0
  125. package/public/assets/catppuccin-macchiato-DQyhUUbL.js +1 -0
  126. package/public/assets/catppuccin-mocha-D87Tk5Gz.js +1 -0
  127. package/public/assets/clarity-D53aC0YG.js +1 -0
  128. package/public/assets/clojure-P80f7IUj.js +1 -0
  129. package/public/assets/cmake-D1j8_8rp.js +1 -0
  130. package/public/assets/cobol-nwyudZeR.js +1 -0
  131. package/public/assets/codeowners-Bp6g37R7.js +1 -0
  132. package/public/assets/codeql-DsOJ9woJ.js +1 -0
  133. package/public/assets/coffee-Ch7k5sss.js +1 -0
  134. package/public/assets/common-lisp-Cg-RD9OK.js +1 -0
  135. package/public/assets/coq-DkFqJrB1.js +1 -0
  136. package/public/assets/core-DhEqZVGG.js +1 -0
  137. package/public/assets/cpp-CofmeUqb.js +1 -0
  138. package/public/assets/crystal-tKQVLTB8.js +1 -0
  139. package/public/assets/csharp-CX12Zw3r.js +1 -0
  140. package/public/assets/css-DPfMkruS.js +1 -0
  141. package/public/assets/csv-fuZLfV_i.js +1 -0
  142. package/public/assets/cue-D82EKSYY.js +1 -0
  143. package/public/assets/cypher-COkxafJQ.js +1 -0
  144. package/public/assets/d-85-TOEBH.js +1 -0
  145. package/public/assets/dark-plus-eOWES_5F.js +1 -0
  146. package/public/assets/dart-CF10PKvl.js +1 -0
  147. package/public/assets/dax-CEL-wOlO.js +1 -0
  148. package/public/assets/desktop-BmXAJ9_W.js +1 -0
  149. package/public/assets/diff-D97Zzqfu.js +1 -0
  150. package/public/assets/diff-viewer-BDYT5S-Q.js +1 -0
  151. package/public/assets/docker-BcOcwvcX.js +1 -0
  152. package/public/assets/dotenv-Da5cRb03.js +1 -0
  153. package/public/assets/dracula-BzJJZx-M.js +1 -0
  154. package/public/assets/dracula-soft-BXkSAIEj.js +1 -0
  155. package/public/assets/dream-maker-BtqSS_iP.js +1 -0
  156. package/public/assets/edge-BkV0erSs.js +1 -0
  157. package/public/assets/elixir-CDX3lj18.js +1 -0
  158. package/public/assets/elm-DbKCFpqz.js +1 -0
  159. package/public/assets/emacs-lisp-C9XAeP06.js +1 -0
  160. package/public/assets/erb-BOJIQeun.js +1 -0
  161. package/public/assets/erlang-DsQrWhSR.js +1 -0
  162. package/public/assets/everforest-dark-BgDCqdQA.js +1 -0
  163. package/public/assets/everforest-light-C8M2exoo.js +1 -0
  164. package/public/assets/fast-diff-vendor-DgdwVvTQ.js +1 -0
  165. package/public/assets/fennel-BYunw83y.js +1 -0
  166. package/public/assets/fish-BvzEVeQv.js +1 -0
  167. package/public/assets/fluent-C4IJs8-o.js +1 -0
  168. package/public/assets/fortran-fixed-form-BZjJHVRy.js +1 -0
  169. package/public/assets/fortran-free-form-D22FLkUw.js +1 -0
  170. package/public/assets/fsharp-CXgrBDvD.js +1 -0
  171. package/public/assets/gdresource-B7Tvp0Sc.js +1 -0
  172. package/public/assets/gdscript-DTMYz4Jt.js +1 -0
  173. package/public/assets/gdshader-DkwncUOv.js +1 -0
  174. package/public/assets/genie-D0YGMca9.js +1 -0
  175. package/public/assets/gherkin-DyxjwDmM.js +1 -0
  176. package/public/assets/git-commit-F4YmCXRG.js +1 -0
  177. package/public/assets/git-diff-vendor-DaSE45SW.js +52 -0
  178. package/public/assets/git-diff-vendor-HAZkIolJ.css +19 -0
  179. package/public/assets/git-rebase-r7XF79zn.js +1 -0
  180. package/public/assets/github-dark-DHJKELXO.js +1 -0
  181. package/public/assets/github-dark-default-Cuk6v7N8.js +1 -0
  182. package/public/assets/github-dark-dimmed-DH5Ifo-i.js +1 -0
  183. package/public/assets/github-dark-high-contrast-E3gJ1_iC.js +1 -0
  184. package/public/assets/github-light-DAi9KRSo.js +1 -0
  185. package/public/assets/github-light-default-D7oLnXFd.js +1 -0
  186. package/public/assets/github-light-high-contrast-BfjtVDDH.js +1 -0
  187. package/public/assets/gleam-BspZqrRM.js +1 -0
  188. package/public/assets/glimmer-js-Rg0-pVw9.js +1 -0
  189. package/public/assets/glimmer-ts-U6CK756n.js +1 -0
  190. package/public/assets/glsl-DplSGwfg.js +1 -0
  191. package/public/assets/gnuplot-DdkO51Og.js +1 -0
  192. package/public/assets/go-Dn2_MT6a.js +1 -0
  193. package/public/assets/graphql-ChdNCCLP.js +1 -0
  194. package/public/assets/groovy-gcz8RCvz.js +1 -0
  195. package/public/assets/gruvbox-dark-hard-CFHQjOhq.js +1 -0
  196. package/public/assets/gruvbox-dark-medium-GsRaNv29.js +1 -0
  197. package/public/assets/gruvbox-dark-soft-CVdnzihN.js +1 -0
  198. package/public/assets/gruvbox-light-hard-CH1njM8p.js +1 -0
  199. package/public/assets/gruvbox-light-medium-DRw_LuNl.js +1 -0
  200. package/public/assets/gruvbox-light-soft-hJgmCMqR.js +1 -0
  201. package/public/assets/hack-CaT9iCJl.js +1 -0
  202. package/public/assets/haml-B8DHNrY2.js +1 -0
  203. package/public/assets/handlebars-BL8al0AC.js +1 -0
  204. package/public/assets/haskell-Df6bDoY_.js +1 -0
  205. package/public/assets/haxe-CzTSHFRz.js +1 -0
  206. package/public/assets/hcl-BWvSN4gD.js +1 -0
  207. package/public/assets/highlight-vendor-8FKMu9os.js +10 -0
  208. package/public/assets/hjson-D5-asLiD.js +1 -0
  209. package/public/assets/hlsl-D3lLCCz7.js +1 -0
  210. package/public/assets/houston-DnULxvSX.js +1 -0
  211. package/public/assets/html-GMplVEZG.js +1 -0
  212. package/public/assets/html-derivative-BFtXZ54Q.js +1 -0
  213. package/public/assets/http-jrhK8wxY.js +1 -0
  214. package/public/assets/hurl-irOxFIW8.js +1 -0
  215. package/public/assets/hxml-Bvhsp5Yf.js +1 -0
  216. package/public/assets/hy-DFXneXwc.js +1 -0
  217. package/public/assets/imba-DGztddWO.js +1 -0
  218. package/public/assets/index-BKMyzTSR.js +1 -0
  219. package/public/assets/index-BWhMWtCP.js +2 -0
  220. package/public/assets/index-Bsb7z85O.js +1 -0
  221. package/public/assets/index-By8QJmOa.js +1 -0
  222. package/public/assets/index-CLSJ4cO9.js +1 -0
  223. package/public/assets/index-DBPzV8JQ.js +1 -0
  224. package/public/assets/index-DhOdialG.js +1 -0
  225. package/public/assets/index-DlobuxMv.js +1 -0
  226. package/public/assets/index-QdhU2jY3.css +1 -0
  227. package/public/assets/index-WYKVZxn4.js +1 -0
  228. package/public/assets/index-gBWCTkMr.js +1 -0
  229. package/public/assets/ini-BEwlwnbL.js +1 -0
  230. package/public/assets/java-CylS5w8V.js +1 -0
  231. package/public/assets/javascript-wDzz0qaB.js +1 -0
  232. package/public/assets/jinja-4LBKfQ-Z.js +1 -0
  233. package/public/assets/jison-wvAkD_A8.js +1 -0
  234. package/public/assets/json-Cp-IABpG.js +1 -0
  235. package/public/assets/json5-C9tS-k6U.js +1 -0
  236. package/public/assets/jsonc-Des-eS-w.js +1 -0
  237. package/public/assets/jsonl-DcaNXYhu.js +1 -0
  238. package/public/assets/jsonnet-DFQXde-d.js +1 -0
  239. package/public/assets/jssm-C2t-YnRu.js +1 -0
  240. package/public/assets/jsx-g9-lgVsj.js +1 -0
  241. package/public/assets/julia-C8NyazO9.js +1 -0
  242. package/public/assets/kanagawa-dragon-CkXjmgJE.js +1 -0
  243. package/public/assets/kanagawa-lotus-CfQXZHmo.js +1 -0
  244. package/public/assets/kanagawa-wave-DWedfzmr.js +1 -0
  245. package/public/assets/kdl-DV7GczEv.js +1 -0
  246. package/public/assets/kotlin-BdnUsdx6.js +1 -0
  247. package/public/assets/kusto-BvAqAH-y.js +1 -0
  248. package/public/assets/laserwave-DUszq2jm.js +1 -0
  249. package/public/assets/latex-BUKiar2Z.js +1 -0
  250. package/public/assets/lean-DP1Csr6i.js +1 -0
  251. package/public/assets/less-B1dDrJ26.js +1 -0
  252. package/public/assets/light-plus-B7mTdjB0.js +1 -0
  253. package/public/assets/liquid-DYVedYrR.js +1 -0
  254. package/public/assets/llvm-BtvRca6l.js +1 -0
  255. package/public/assets/loading-C4yc63Qi.js +2 -0
  256. package/public/assets/loading-CugGjKDZ.css +1 -0
  257. package/public/assets/log-2UxHyX5q.js +1 -0
  258. package/public/assets/logo-BtOb2qkB.js +1 -0
  259. package/public/assets/lua-BbnMAYS6.js +1 -0
  260. package/public/assets/luau-CXu1NL6O.js +1 -0
  261. package/public/assets/main-y4WbiJBN.js +53 -0
  262. package/public/assets/make-CHLpvVh8.js +1 -0
  263. package/public/assets/markdown-Cvjx9yec.js +1 -0
  264. package/public/assets/markdown-DmuP22dE.js +58 -0
  265. package/public/assets/marko-CPi9NSCl.js +1 -0
  266. package/public/assets/material-theme-D5KoaKCx.js +1 -0
  267. package/public/assets/material-theme-darker-BfHTSMKl.js +1 -0
  268. package/public/assets/material-theme-lighter-B0m2ddpp.js +1 -0
  269. package/public/assets/material-theme-ocean-CyktbL80.js +1 -0
  270. package/public/assets/material-theme-palenight-Csfq5Kiy.js +1 -0
  271. package/public/assets/matlab-D7o27uSR.js +1 -0
  272. package/public/assets/mdc-DUICxH0z.js +1 -0
  273. package/public/assets/mdx-Cmh6b_Ma.js +1 -0
  274. package/public/assets/mermaid-DKYwYmdq.js +1 -0
  275. package/public/assets/min-dark-CafNBF8u.js +1 -0
  276. package/public/assets/min-light-CTRr51gU.js +1 -0
  277. package/public/assets/mipsasm-CKIfxQSi.js +1 -0
  278. package/public/assets/mojo-1DNp92w6.js +1 -0
  279. package/public/assets/monaco-viewer-OXO07Mos.js +26 -0
  280. package/public/assets/monokai-D4h5O-jR.js +1 -0
  281. package/public/assets/move-Bu9oaDYs.js +1 -0
  282. package/public/assets/narrat-DRg8JJMk.js +1 -0
  283. package/public/assets/nextflow-CUEJCptM.js +1 -0
  284. package/public/assets/nginx-DknmC5AR.js +1 -0
  285. package/public/assets/night-owl-C39BiMTA.js +1 -0
  286. package/public/assets/nim-CVrawwO9.js +1 -0
  287. package/public/assets/nix-BbRYJGeE.js +1 -0
  288. package/public/assets/nord-Ddv68eIx.js +1 -0
  289. package/public/assets/nushell-C-sUppwS.js +1 -0
  290. package/public/assets/objective-c-DXmwc3jG.js +1 -0
  291. package/public/assets/objective-cpp-CLxacb5B.js +1 -0
  292. package/public/assets/ocaml-C0hk2d4L.js +1 -0
  293. package/public/assets/one-dark-pro-DVMEJ2y_.js +1 -0
  294. package/public/assets/one-light-PoHY5YXO.js +1 -0
  295. package/public/assets/pascal-D93ZcfNL.js +1 -0
  296. package/public/assets/perl-C0TMdlhV.js +1 -0
  297. package/public/assets/php-CDn_0X-4.js +1 -0
  298. package/public/assets/pkl-u5AG7uiY.js +1 -0
  299. package/public/assets/plastic-3e1v2bzS.js +1 -0
  300. package/public/assets/plsql-ChMvpjG-.js +1 -0
  301. package/public/assets/po-BTJTHyun.js +1 -0
  302. package/public/assets/poimandres-CS3Unz2-.js +1 -0
  303. package/public/assets/polar-C0HS_06l.js +1 -0
  304. package/public/assets/postcss-CXtECtnM.js +1 -0
  305. package/public/assets/powerquery-CEu0bR-o.js +1 -0
  306. package/public/assets/powershell-Dpen1YoG.js +1 -0
  307. package/public/assets/prisma-Dd19v3D-.js +1 -0
  308. package/public/assets/prolog-CbFg5uaA.js +1 -0
  309. package/public/assets/proto-DyJlTyXw.js +1 -0
  310. package/public/assets/pug-CGlum2m_.js +1 -0
  311. package/public/assets/puppet-BMWR74SV.js +1 -0
  312. package/public/assets/purescript-CklMAg4u.js +1 -0
  313. package/public/assets/python-B6aJPvgy.js +1 -0
  314. package/public/assets/qml-3beO22l8.js +1 -0
  315. package/public/assets/qmldir-C8lEn-DE.js +1 -0
  316. package/public/assets/qss-IeuSbFQv.js +1 -0
  317. package/public/assets/r-DiinP2Uv.js +1 -0
  318. package/public/assets/racket-BqYA7rlc.js +1 -0
  319. package/public/assets/raku-DXvB9xmW.js +1 -0
  320. package/public/assets/razor-WgofotgN.js +1 -0
  321. package/public/assets/red-bN70gL4F.js +1 -0
  322. package/public/assets/reg-C-SQnVFl.js +1 -0
  323. package/public/assets/regexp-CDVJQ6XC.js +1 -0
  324. package/public/assets/rel-C3B-1QV4.js +1 -0
  325. package/public/assets/riscv-BM1_JUlF.js +1 -0
  326. package/public/assets/rose-pine-BHrmToEH.js +1 -0
  327. package/public/assets/rose-pine-dawn-CnK8MTSM.js +1 -0
  328. package/public/assets/rose-pine-moon-NleAzG8P.js +1 -0
  329. package/public/assets/rosmsg-BJDFO7_C.js +1 -0
  330. package/public/assets/rst-B0xPkSld.js +1 -0
  331. package/public/assets/ruby-BvKwtOVI.js +1 -0
  332. package/public/assets/rust-B1yitclQ.js +1 -0
  333. package/public/assets/sas-cz2c8ADy.js +1 -0
  334. package/public/assets/sass-Cj5Yp3dK.js +1 -0
  335. package/public/assets/scala-C151Ov-r.js +1 -0
  336. package/public/assets/scheme-C98Dy4si.js +1 -0
  337. package/public/assets/scss-OYdSNvt2.js +1 -0
  338. package/public/assets/sdbl-DVxCFoDh.js +1 -0
  339. package/public/assets/shaderlab-Dg9Lc6iA.js +1 -0
  340. package/public/assets/shellscript-Yzrsuije.js +1 -0
  341. package/public/assets/shellsession-BADoaaVG.js +1 -0
  342. package/public/assets/slack-dark-BthQWCQV.js +1 -0
  343. package/public/assets/slack-ochin-DqwNpetd.js +1 -0
  344. package/public/assets/smalltalk-BERRCDM3.js +1 -0
  345. package/public/assets/snazzy-light-Bw305WKR.js +1 -0
  346. package/public/assets/solarized-dark-DXbdFlpD.js +1 -0
  347. package/public/assets/solarized-light-L9t79GZl.js +1 -0
  348. package/public/assets/solidity-BbcW6ACK.js +1 -0
  349. package/public/assets/soy-Brmx7dQM.js +1 -0
  350. package/public/assets/sparql-rVzFXLq3.js +1 -0
  351. package/public/assets/splunk-BtCnVYZw.js +1 -0
  352. package/public/assets/sql-BLtJtn59.js +1 -0
  353. package/public/assets/ssh-config-_ykCGR6B.js +1 -0
  354. package/public/assets/stata-BH5u7GGu.js +1 -0
  355. package/public/assets/stylus-BEDo0Tqx.js +1 -0
  356. package/public/assets/svelte-3Dk4HxPD.js +1 -0
  357. package/public/assets/swift-Dg5xB15N.js +1 -0
  358. package/public/assets/synthwave-84-CbfX1IO0.js +1 -0
  359. package/public/assets/system-verilog-CnnmHF94.js +1 -0
  360. package/public/assets/systemd-4A_iFExJ.js +1 -0
  361. package/public/assets/talonscript-CkByrt1z.js +1 -0
  362. package/public/assets/tasl-QIJgUcNo.js +1 -0
  363. package/public/assets/tcl-dwOrl1Do.js +1 -0
  364. package/public/assets/templ-W15q3VgB.js +1 -0
  365. package/public/assets/terraform-BETggiCN.js +1 -0
  366. package/public/assets/tex-Cppo0RY3.js +1 -0
  367. package/public/assets/todo-_6sSKM36.js +1 -0
  368. package/public/assets/tokyo-night-hegEt444.js +1 -0
  369. package/public/assets/toml-vGWfd6FD.js +1 -0
  370. package/public/assets/tool-call-ChcZ5m6V.js +60 -0
  371. package/public/assets/ts-tags-zn1MmPIZ.js +1 -0
  372. package/public/assets/tsv-B_m7g4N7.js +1 -0
  373. package/public/assets/tsx-COt5Ahok.js +1 -0
  374. package/public/assets/turtle-BsS91CYL.js +1 -0
  375. package/public/assets/twig-CO9l9SDP.js +1 -0
  376. package/public/assets/typescript-BPQ3VLAy.js +1 -0
  377. package/public/assets/typespec-Df68jz8_.js +1 -0
  378. package/public/assets/typst-DHCkPAjA.js +1 -0
  379. package/public/assets/unified-picker-BkweRxZy.js +1 -0
  380. package/public/assets/v-BcVCzyr7.js +1 -0
  381. package/public/assets/vala-CsfeWuGM.js +1 -0
  382. package/public/assets/vb-D17OF-Vu.js +1 -0
  383. package/public/assets/verilog-BQ8w6xss.js +1 -0
  384. package/public/assets/vesper-DU1UobuO.js +1 -0
  385. package/public/assets/vhdl-CeAyd5Ju.js +1 -0
  386. package/public/assets/viml-CJc9bBzg.js +1 -0
  387. package/public/assets/vitesse-black-Bkuqu6BP.js +1 -0
  388. package/public/assets/vitesse-dark-D0r3Knsf.js +1 -0
  389. package/public/assets/vitesse-light-CVO1_9PV.js +1 -0
  390. package/public/assets/vue-CCoi5OLL.js +1 -0
  391. package/public/assets/vue-html-DAAvJJDi.js +1 -0
  392. package/public/assets/vue-vine-_Ih-lPRR.js +1 -0
  393. package/public/assets/vyper-CDx5xZoG.js +1 -0
  394. package/public/assets/wasm-CG6Dc4jp.js +1 -0
  395. package/public/assets/wasm-MzD3tlZU.js +1 -0
  396. package/public/assets/wenyan-BV7otONQ.js +1 -0
  397. package/public/assets/wgsl-Dx-B1_4e.js +1 -0
  398. package/public/assets/wikitext-BhOHFoWU.js +1 -0
  399. package/public/assets/wit-5i3qLPDT.js +1 -0
  400. package/public/assets/wolfram-lXgVvXCa.js +1 -0
  401. package/public/assets/wrap-text-DDrpiK4b.js +1 -0
  402. package/public/assets/xml-sdJ4AIDG.js +1 -0
  403. package/public/assets/xsl-CtQFsRM5.js +1 -0
  404. package/public/assets/yaml-Buea-lGh.js +1 -0
  405. package/public/assets/zenscript-DVFEvuxE.js +1 -0
  406. package/public/assets/zig-VOosw3JB.js +1 -0
  407. package/public/favicon.ico +0 -0
  408. package/public/index.html +44 -0
  409. package/public/loading.html +33 -0
  410. package/public/logo.png +0 -0
  411. package/public/manifest.webmanifest +1 -0
  412. package/public/maskable-icon-512x512.png +0 -0
  413. package/public/monaco/vs/base/browser/ui/codicons/codicon/codicon.ttf +0 -0
  414. package/public/monaco/vs/base/worker/workerMain.js +31 -0
  415. package/public/monaco/vs/basic-languages/cpp/cpp.js +10 -0
  416. package/public/monaco/vs/basic-languages/kotlin/kotlin.js +10 -0
  417. package/public/monaco/vs/basic-languages/markdown/markdown.js +10 -0
  418. package/public/monaco/vs/basic-languages/python/python.js +10 -0
  419. package/public/monaco/vs/editor/editor.main.css +8 -0
  420. package/public/monaco/vs/editor/editor.main.js +798 -0
  421. package/public/monaco/vs/language/css/cssMode.js +13 -0
  422. package/public/monaco/vs/language/css/cssWorker.js +77 -0
  423. package/public/monaco/vs/language/html/htmlMode.js +13 -0
  424. package/public/monaco/vs/language/html/htmlWorker.js +454 -0
  425. package/public/monaco/vs/language/json/jsonMode.js +19 -0
  426. package/public/monaco/vs/language/json/jsonWorker.js +42 -0
  427. package/public/monaco/vs/language/typescript/tsMode.js +20 -0
  428. package/public/monaco/vs/language/typescript/tsWorker.js +51328 -0
  429. package/public/monaco/vs/loader.js +11 -0
  430. package/public/monaco.worker.js +7 -0
  431. package/public/pwa-192x192.png +0 -0
  432. package/public/pwa-512x512.png +0 -0
  433. package/public/pwa-64x64.png +0 -0
  434. package/public/registerSW.js +1 -0
  435. package/public/sw.js +1 -0
  436. package/public/ui-version.json +3 -0
  437. package/public/workbox-60d14903.js +1 -0
  438. package/bin/cli.js +0 -56
@@ -0,0 +1,40 @@
1
+ export class PluginChannelManager {
2
+ constructor(logger) {
3
+ this.logger = logger;
4
+ this.clients = new Set();
5
+ }
6
+ register(workspaceId, reply) {
7
+ const connection = { workspaceId, reply };
8
+ this.clients.add(connection);
9
+ this.logger.debug({ workspaceId }, "Plugin SSE client connected");
10
+ let closed = false;
11
+ const close = () => {
12
+ if (closed)
13
+ return;
14
+ closed = true;
15
+ this.clients.delete(connection);
16
+ this.logger.debug({ workspaceId }, "Plugin SSE client disconnected");
17
+ };
18
+ return { close };
19
+ }
20
+ send(workspaceId, event) {
21
+ for (const client of this.clients) {
22
+ if (client.workspaceId !== workspaceId)
23
+ continue;
24
+ this.write(client.reply, event);
25
+ }
26
+ }
27
+ broadcast(event) {
28
+ for (const client of this.clients) {
29
+ this.write(client.reply, event);
30
+ }
31
+ }
32
+ write(reply, event) {
33
+ try {
34
+ reply.raw.write(`data: ${JSON.stringify(event)}\n\n`);
35
+ }
36
+ catch (error) {
37
+ this.logger.warn({ err: error }, "Failed to write plugin SSE event");
38
+ }
39
+ }
40
+ }
@@ -0,0 +1,17 @@
1
+ export function handlePluginEvent(workspaceId, event, deps) {
2
+ switch (event.type) {
3
+ case "embeddedcowork.pong":
4
+ deps.logger.debug({ workspaceId, properties: event.properties }, "Plugin pong received");
5
+ return;
6
+ default:
7
+ deps.logger.debug({ workspaceId, eventType: event.type }, "Unhandled plugin event");
8
+ }
9
+ }
10
+ export function buildPingEvent() {
11
+ return {
12
+ type: "embeddedcowork.ping",
13
+ properties: {
14
+ ts: Date.now(),
15
+ },
16
+ };
17
+ }
@@ -0,0 +1,78 @@
1
+ export class VoiceModeManager {
2
+ constructor(options) {
3
+ this.options = options;
4
+ this.enabledConnectionsByInstance = new Map();
5
+ this.aggregateByInstance = new Map();
6
+ this.options.connections.subscribe((event) => {
7
+ if (event.type !== "disconnected")
8
+ return;
9
+ this.clearConnection(event.connection);
10
+ });
11
+ }
12
+ setEnabled(instanceId, connection, enabled) {
13
+ if (enabled && !this.options.connections.isConnected(connection)) {
14
+ this.options.logger.debug({ instanceId, clientId: connection.clientId, connectionId: connection.connectionId }, "Ignoring voice mode enable for disconnected client connection");
15
+ return false;
16
+ }
17
+ const key = getConnectionKey(connection);
18
+ const current = this.enabledConnectionsByInstance.get(instanceId) ?? new Set();
19
+ if (enabled) {
20
+ current.add(key);
21
+ this.enabledConnectionsByInstance.set(instanceId, current);
22
+ }
23
+ else if (current.delete(key)) {
24
+ if (current.size === 0) {
25
+ this.enabledConnectionsByInstance.delete(instanceId);
26
+ }
27
+ else {
28
+ this.enabledConnectionsByInstance.set(instanceId, current);
29
+ }
30
+ }
31
+ this.options.logger.debug({ instanceId, clientId: connection.clientId, connectionId: connection.connectionId, enabled }, "Voice mode updated for client connection");
32
+ this.publishIfChanged(instanceId);
33
+ return true;
34
+ }
35
+ syncInstance(instanceId) {
36
+ this.options.channel.send(instanceId, buildVoiceModeEvent(this.isEnabled(instanceId)));
37
+ }
38
+ isEnabled(instanceId) {
39
+ return this.aggregateByInstance.get(instanceId) === true;
40
+ }
41
+ clearConnection(connection) {
42
+ const key = getConnectionKey(connection);
43
+ for (const [instanceId, enabledConnections] of Array.from(this.enabledConnectionsByInstance.entries())) {
44
+ if (!enabledConnections.delete(key))
45
+ continue;
46
+ if (enabledConnections.size === 0) {
47
+ this.enabledConnectionsByInstance.delete(instanceId);
48
+ }
49
+ this.publishIfChanged(instanceId);
50
+ }
51
+ }
52
+ publishIfChanged(instanceId) {
53
+ const enabled = (this.enabledConnectionsByInstance.get(instanceId)?.size ?? 0) > 0;
54
+ const previous = this.aggregateByInstance.get(instanceId) === true;
55
+ if (enabled === previous)
56
+ return;
57
+ if (enabled) {
58
+ this.aggregateByInstance.set(instanceId, true);
59
+ }
60
+ else {
61
+ this.aggregateByInstance.delete(instanceId);
62
+ }
63
+ this.options.logger.debug({ instanceId, enabled }, "Broadcasting aggregate voice mode");
64
+ this.options.channel.send(instanceId, buildVoiceModeEvent(enabled));
65
+ }
66
+ }
67
+ function buildVoiceModeEvent(enabled) {
68
+ return {
69
+ type: "embeddedcowork.voiceMode",
70
+ properties: {
71
+ enabled,
72
+ formatVersion: "v1",
73
+ },
74
+ };
75
+ }
76
+ function getConnectionKey(connection) {
77
+ return `${connection.clientId}:${connection.connectionId}`;
78
+ }
@@ -0,0 +1,75 @@
1
+ import { fetch } from "undici";
2
+ import { compareVersionStrings, stripTagPrefix } from "./release-monitor";
3
+ const DEFAULT_POLL_INTERVAL_MS = 15 * 60 * 1000;
4
+ export function startDevReleaseMonitor(options) {
5
+ let stopped = false;
6
+ let timer = null;
7
+ const pollIntervalMs = Number.isFinite(options.pollIntervalMs) && (options.pollIntervalMs ?? 0) > 0
8
+ ? options.pollIntervalMs
9
+ : DEFAULT_POLL_INTERVAL_MS;
10
+ const refresh = async () => {
11
+ if (stopped)
12
+ return;
13
+ try {
14
+ const release = await fetchLatestPrerelease({
15
+ repo: options.repo,
16
+ currentVersion: options.currentVersion,
17
+ });
18
+ options.onUpdate(release);
19
+ }
20
+ catch (error) {
21
+ options.logger.debug({ err: error }, "Failed to refresh dev prerelease information");
22
+ }
23
+ };
24
+ void refresh();
25
+ timer = setInterval(() => void refresh(), pollIntervalMs);
26
+ return {
27
+ stop() {
28
+ stopped = true;
29
+ if (timer) {
30
+ clearInterval(timer);
31
+ timer = null;
32
+ }
33
+ },
34
+ };
35
+ }
36
+ async function fetchLatestPrerelease(args) {
37
+ const normalizedRepo = args.repo.trim();
38
+ if (!/^[^/\s]+\/[^/\s]+$/.test(normalizedRepo)) {
39
+ throw new Error(`Invalid GitHub repo: ${args.repo}`);
40
+ }
41
+ const apiUrl = `https://api.github.com/repos/${normalizedRepo}/releases?per_page=20`;
42
+ const response = await fetch(apiUrl, {
43
+ headers: {
44
+ Accept: "application/vnd.github+json",
45
+ "User-Agent": "EmbeddedCowork-CLI",
46
+ },
47
+ });
48
+ if (!response.ok) {
49
+ throw new Error(`GitHub releases API responded with ${response.status}`);
50
+ }
51
+ const list = (await response.json());
52
+ const latest = list.find((r) => r && r.prerelease === true && r.draft !== true);
53
+ if (!latest) {
54
+ return null;
55
+ }
56
+ const tag = latest.tag_name || latest.name;
57
+ if (!tag) {
58
+ return null;
59
+ }
60
+ const normalizedVersion = stripTagPrefix(tag);
61
+ if (!normalizedVersion) {
62
+ return null;
63
+ }
64
+ if (compareVersionStrings(normalizedVersion, args.currentVersion) <= 0) {
65
+ return null;
66
+ }
67
+ return {
68
+ version: normalizedVersion,
69
+ tag,
70
+ url: latest.html_url ?? `https://github.com/${normalizedRepo}/releases/tag/${encodeURIComponent(tag)}`,
71
+ channel: "dev",
72
+ publishedAt: latest.published_at ?? latest.created_at,
73
+ notes: latest.body,
74
+ };
75
+ }
@@ -0,0 +1,107 @@
1
+ import { fetch } from "undici";
2
+ const RELEASES_API_URL = "https://api.github.com/repos/vividcode-ai/EmbeddedCowork/releases/latest";
3
+ export function startReleaseMonitor(options) {
4
+ let stopped = false;
5
+ const refreshRelease = async () => {
6
+ if (stopped)
7
+ return;
8
+ try {
9
+ const release = await fetchLatestRelease(options);
10
+ options.onUpdate(release);
11
+ }
12
+ catch (error) {
13
+ options.logger.warn({ err: error }, "Failed to refresh release information");
14
+ }
15
+ };
16
+ void refreshRelease();
17
+ return {
18
+ stop() {
19
+ stopped = true;
20
+ },
21
+ };
22
+ }
23
+ export function compareVersionStrings(a, b) {
24
+ const left = parseVersion(a);
25
+ const right = parseVersion(b);
26
+ return compareVersions(left, right);
27
+ }
28
+ async function fetchLatestRelease(options) {
29
+ const response = await fetch(RELEASES_API_URL, {
30
+ headers: {
31
+ Accept: "application/vnd.github+json",
32
+ "User-Agent": "EmbeddedCowork-CLI",
33
+ },
34
+ });
35
+ if (!response.ok) {
36
+ throw new Error(`Release API responded with ${response.status}`);
37
+ }
38
+ const json = (await response.json());
39
+ const tagFromServer = json.tag_name || json.name;
40
+ if (!tagFromServer) {
41
+ return null;
42
+ }
43
+ const normalizedVersion = stripTagPrefix(tagFromServer);
44
+ if (!normalizedVersion) {
45
+ return null;
46
+ }
47
+ const current = parseVersion(options.currentVersion);
48
+ const remote = parseVersion(normalizedVersion);
49
+ if (compareVersions(remote, current) <= 0) {
50
+ return null;
51
+ }
52
+ return {
53
+ version: normalizedVersion,
54
+ tag: tagFromServer,
55
+ url: json.html_url ?? `https://github.com/vividcode-ai/EmbeddedCowork/releases/tag/${encodeURIComponent(tagFromServer)}`,
56
+ channel: json.prerelease || normalizedVersion.includes("-") ? "dev" : "stable",
57
+ publishedAt: json.published_at ?? json.created_at,
58
+ notes: json.body,
59
+ };
60
+ }
61
+ export function stripTagPrefix(tag) {
62
+ if (!tag)
63
+ return null;
64
+ const trimmed = tag.trim();
65
+ if (!trimmed)
66
+ return null;
67
+ return trimmed.replace(/^v/i, "");
68
+ }
69
+ function parseVersion(value) {
70
+ const normalized = stripTagPrefix(value) ?? "0.0.0";
71
+ const dashIndex = normalized.indexOf("-");
72
+ const core = dashIndex >= 0 ? normalized.slice(0, dashIndex) : normalized;
73
+ const prerelease = dashIndex >= 0 ? normalized.slice(dashIndex + 1) : null;
74
+ const [major = 0, minor = 0, patch = 0] = core.split(".").map((segment) => {
75
+ const parsed = Number.parseInt(segment, 10);
76
+ return Number.isFinite(parsed) ? parsed : 0;
77
+ });
78
+ return {
79
+ major,
80
+ minor,
81
+ patch,
82
+ prerelease,
83
+ };
84
+ }
85
+ function compareVersions(a, b) {
86
+ if (a.major !== b.major) {
87
+ return a.major > b.major ? 1 : -1;
88
+ }
89
+ if (a.minor !== b.minor) {
90
+ return a.minor > b.minor ? 1 : -1;
91
+ }
92
+ if (a.patch !== b.patch) {
93
+ return a.patch > b.patch ? 1 : -1;
94
+ }
95
+ const aPre = a.prerelease && a.prerelease.length > 0 ? a.prerelease : null;
96
+ const bPre = b.prerelease && b.prerelease.length > 0 ? b.prerelease : null;
97
+ if (aPre === bPre) {
98
+ return 0;
99
+ }
100
+ if (!aPre) {
101
+ return 1;
102
+ }
103
+ if (!bPre) {
104
+ return -1;
105
+ }
106
+ return aPre.localeCompare(bPre);
107
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * rollback.ts - Shared rollback state machine types and helpers.
3
+ *
4
+ * This module defines the update-meta.json schema and helper functions.
5
+ * Used by both Electron and Tauri rollback implementations.
6
+ */
7
+ /** Create a fresh UpdateMeta for a backup operation */
8
+ export function createBackupMeta(oldVersion, backupPath) {
9
+ return {
10
+ state: "backed_up",
11
+ oldVersion,
12
+ newVersion: "",
13
+ backupPath,
14
+ createdAt: new Date().toISOString(),
15
+ };
16
+ }
17
+ /** Transition: update download is complete and about to be installed */
18
+ export function markInstalling(meta, newVersion) {
19
+ return { ...meta, state: "installing", newVersion };
20
+ }
21
+ /** Transition: app started successfully after update */
22
+ export function markStarted(meta) {
23
+ return { ...meta, state: "started" };
24
+ }
25
+ /** Transition: update confirmed (health window passed or clean exit) */
26
+ export function markConfirmed(meta) {
27
+ return { ...meta, state: "confirmed" };
28
+ }
29
+ /** Transition: rollback performed */
30
+ export function markRolledBack(meta) {
31
+ return { ...meta, state: "rolled_back" };
32
+ }
33
+ /** Check if the state indicates a rollback is needed */
34
+ export function needsRollback(meta) {
35
+ return meta.state === "started" || meta.state === "failed";
36
+ }
37
+ /** Check if update is in progress (should not be interrupted) */
38
+ export function isUpdateInProgress(meta) {
39
+ return ["backed_up", "installing", "started"].includes(meta.state);
40
+ }
41
+ /** Check if this is a fresh install that needs the health window */
42
+ export function isNewInstall(meta) {
43
+ return meta.state === "installing";
44
+ }
45
+ /** Default path components for the update meta directory */
46
+ export function getUpdaterDirName() {
47
+ return "embeddedcowork-updater";
48
+ }
49
+ export function getMetaFileName() {
50
+ return "update-meta.json";
51
+ }
52
+ export function getBackupDirName() {
53
+ return "backup";
54
+ }
@@ -0,0 +1,67 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { fileURLToPath } from "url";
4
+ function safeModuleDir(importMetaUrl) {
5
+ try {
6
+ return path.dirname(fileURLToPath(importMetaUrl));
7
+ }
8
+ catch {
9
+ return null;
10
+ }
11
+ }
12
+ function firstExistingPath(candidates, predicate) {
13
+ for (const candidate of candidates) {
14
+ if (!candidate)
15
+ continue;
16
+ if (predicate(candidate)) {
17
+ return candidate;
18
+ }
19
+ }
20
+ return null;
21
+ }
22
+ export function getPackagedDistDir() {
23
+ return path.dirname(process.execPath);
24
+ }
25
+ export function resolveServerPackageRoot(importMetaUrl) {
26
+ const moduleDir = safeModuleDir(importMetaUrl);
27
+ const configuredRoot = process.env.EMBEDDEDCOWORK_SERVER_ROOT?.trim();
28
+ const candidates = [
29
+ configuredRoot ? path.resolve(configuredRoot) : null,
30
+ moduleDir ? path.resolve(moduleDir, "..") : null,
31
+ path.resolve(getPackagedDistDir(), ".."),
32
+ ];
33
+ return (firstExistingPath(candidates, (value) => fs.existsSync(path.join(value, "package.json"))) ??
34
+ candidates.find((value) => Boolean(value)) ??
35
+ process.cwd());
36
+ }
37
+ export function resolveServerPublicDir(importMetaUrl) {
38
+ const moduleDir = safeModuleDir(importMetaUrl);
39
+ const candidates = [moduleDir ? path.resolve(moduleDir, "../public") : null, path.join(resolveServerPackageRoot(importMetaUrl), "public")];
40
+ return firstExistingPath(candidates, (value) => fs.existsSync(value)) ?? candidates[candidates.length - 1];
41
+ }
42
+ export function resolveAuthTemplatePath(importMetaUrl, fileName) {
43
+ const moduleDir = safeModuleDir(importMetaUrl);
44
+ const distDir = getPackagedDistDir();
45
+ const candidates = [
46
+ moduleDir ? path.join(moduleDir, "auth-pages", fileName) : null,
47
+ path.join(distDir, "auth-pages", fileName),
48
+ path.join(distDir, "server", "routes", "auth-pages", fileName),
49
+ ];
50
+ return firstExistingPath(candidates, (value) => fs.existsSync(value)) ?? candidates[0];
51
+ }
52
+ export function resolveOpencodeTemplateDir(importMetaUrl) {
53
+ const moduleDir = safeModuleDir(importMetaUrl);
54
+ const resourcesPath = process.resourcesPath;
55
+ const candidates = [
56
+ moduleDir ? path.resolve(moduleDir, "../../opencode-config") : null,
57
+ resourcesPath ? path.resolve(resourcesPath, "opencode-config") : null,
58
+ moduleDir ? path.resolve(moduleDir, "opencode-config") : null,
59
+ path.join(getPackagedDistDir(), "opencode-config"),
60
+ ];
61
+ return firstExistingPath(candidates, (value) => fs.existsSync(value)) ?? candidates[candidates.length - 1];
62
+ }
63
+ export function readServerPackageVersion(importMetaUrl) {
64
+ const packageJsonPath = path.join(resolveServerPackageRoot(importMetaUrl), "package.json");
65
+ const parsed = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
66
+ return typeof parsed.version === "string" && parsed.version.trim().length > 0 ? parsed.version : "0.0.0";
67
+ }
@@ -0,0 +1,68 @@
1
+ import assert from "node:assert/strict";
2
+ import os from "node:os";
3
+ import { describe, it } from "node:test";
4
+ import { resolveNetworkAddresses, resolveRemoteAddresses } from "../network-addresses";
5
+ describe("resolveNetworkAddresses", () => {
6
+ it("preserves interface order among external addresses", () => {
7
+ const addresses = [
8
+ { address: "172.24.0.1", family: "IPv4", internal: false },
9
+ { address: "192.168.1.128", family: "IPv4", internal: false },
10
+ { address: "10.0.0.8", family: 4, internal: false },
11
+ { address: "127.0.0.1", family: "IPv4", internal: true },
12
+ { address: "169.254.10.20", family: "IPv4", internal: false },
13
+ ];
14
+ usingMockedNetworkInterfaces(addresses, () => {
15
+ const result = resolveNetworkAddresses({ host: "0.0.0.0", protocol: "https", port: 9898 });
16
+ assert.deepEqual(result.map((entry) => entry.ip), ["172.24.0.1", "192.168.1.128", "10.0.0.8", "169.254.10.20", "127.0.0.1"]);
17
+ });
18
+ });
19
+ });
20
+ describe("resolveRemoteAddresses", () => {
21
+ it("keeps all external addresses user-visible while preferring non-link-local addresses for the primary URL", () => {
22
+ const addresses = [
23
+ { address: "169.254.10.20", family: "IPv4", internal: false },
24
+ { address: "192.168.1.128", family: "IPv4", internal: false },
25
+ { address: "172.24.0.1", family: "IPv4", internal: false },
26
+ ];
27
+ usingMockedNetworkInterfaces(addresses, () => {
28
+ const result = resolveRemoteAddresses({ host: "0.0.0.0", protocol: "https", port: 9898 });
29
+ assert.deepEqual(result.userVisible.map((entry) => entry.ip), ["192.168.1.128", "172.24.0.1", "169.254.10.20"]);
30
+ assert.equal(result.primaryRemoteUrl, "https://192.168.1.128:9898");
31
+ });
32
+ });
33
+ it("prefers private LAN addresses over public addresses", () => {
34
+ const addresses = [
35
+ { address: "203.0.113.40", family: "IPv4", internal: false },
36
+ { address: "192.168.1.128", family: "IPv4", internal: false },
37
+ { address: "8.8.8.8", family: "IPv4", internal: false },
38
+ ];
39
+ usingMockedNetworkInterfaces(addresses, () => {
40
+ const result = resolveRemoteAddresses({ host: "0.0.0.0", protocol: "https", port: 9898 });
41
+ assert.deepEqual(result.userVisible.map((entry) => entry.ip), ["192.168.1.128", "203.0.113.40", "8.8.8.8"]);
42
+ assert.equal(result.primaryRemoteUrl, "https://192.168.1.128:9898");
43
+ });
44
+ });
45
+ it("uses a public address when no private LAN address is available", () => {
46
+ const addresses = [
47
+ { address: "169.254.10.20", family: "IPv4", internal: false },
48
+ { address: "203.0.113.40", family: "IPv4", internal: false },
49
+ ];
50
+ usingMockedNetworkInterfaces(addresses, () => {
51
+ const result = resolveRemoteAddresses({ host: "0.0.0.0", protocol: "https", port: 9898 });
52
+ assert.deepEqual(result.userVisible.map((entry) => entry.ip), ["203.0.113.40", "169.254.10.20"]);
53
+ assert.equal(result.primaryRemoteUrl, "https://203.0.113.40:9898");
54
+ });
55
+ });
56
+ });
57
+ function usingMockedNetworkInterfaces(addresses, callback) {
58
+ const original = os.networkInterfaces;
59
+ os.networkInterfaces = (() => ({
60
+ ethernet0: addresses,
61
+ }));
62
+ try {
63
+ callback();
64
+ }
65
+ finally {
66
+ os.networkInterfaces = original;
67
+ }
68
+ }