auvrynt 1.0.2 → 1.0.5

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 (550) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +366 -233
  3. package/addons/auvrynt_bridge/auvrynt_bridge.gd +500 -0
  4. package/addons/auvrynt_bridge/plugin.cfg +7 -0
  5. package/bin/auvrynt-launcher.cjs +77 -0
  6. package/dist/artifact-registry.js +1 -0
  7. package/dist/aseprite-tools.js +1 -0
  8. package/dist/auth/connection-registry.js +145 -0
  9. package/dist/auth/connection-status.js +176 -0
  10. package/dist/auth/oauth-provider.js +617 -0
  11. package/dist/auth/room-registry.js +131 -0
  12. package/dist/auth/session-registry.js +531 -0
  13. package/dist/background-lifecycle.js +1 -0
  14. package/dist/blender-client.js +1 -109
  15. package/dist/blender-tools.js +1 -930
  16. package/dist/browser-stability.js +1 -0
  17. package/dist/cli/commands/help-command.js +10 -0
  18. package/dist/cli/commands/init-command.js +190 -0
  19. package/dist/cli/commands/integration-commands.js +88 -0
  20. package/dist/cli/commands/serve-command.js +83 -0
  21. package/dist/cli/commands/setup-command.js +81 -0
  22. package/dist/cli/commands/status-commands.js +166 -0
  23. package/dist/cli/commands/tunnel-command.js +127 -0
  24. package/dist/cli/commands/user-config-commands.js +105 -0
  25. package/dist/cli/dashboard-actions.js +516 -0
  26. package/dist/cli/dashboard-native-actions.js +282 -0
  27. package/dist/cli/foreground-server.js +270 -0
  28. package/dist/cli/instance-control.js +21 -0
  29. package/dist/cli/instance-lock.js +123 -0
  30. package/dist/cli/integration-bootstrap.js +206 -0
  31. package/dist/cli/lifecycle-manager.js +493 -0
  32. package/dist/cli/runtime-support.js +74 -0
  33. package/dist/cli/serena-detected-default.js +27 -0
  34. package/dist/cli/tunnel-health-monitor.js +182 -0
  35. package/dist/cli.js +82 -739
  36. package/dist/config.js +1 -243
  37. package/dist/connection-registry.js +1 -73
  38. package/dist/connection-status.js +1 -139
  39. package/dist/control-retry.js +1 -0
  40. package/dist/crash-recovery.js +1 -0
  41. package/dist/db/client.js +16 -3
  42. package/dist/db/schema.js +30 -0
  43. package/dist/dotnet-tools.js +1 -223
  44. package/dist/git-worktrees.js +1 -134
  45. package/dist/git.js +1 -41
  46. package/dist/godot-animation-tilemap.js +1 -82
  47. package/dist/godot-csharp-build.js +1 -93
  48. package/dist/godot-csharp-project.js +1 -157
  49. package/dist/godot-csharp-runner.js +1 -146
  50. package/dist/godot-csharp-semantic.js +1 -161
  51. package/dist/godot-csharp-validate.js +1 -71
  52. package/dist/godot-dotnet-env.js +1 -169
  53. package/dist/godot-editor-bridge.js +1 -140
  54. package/dist/godot-gdscript.js +1 -824
  55. package/dist/godot-project-settings.js +1 -223
  56. package/dist/godot-runtime-testing.js +1 -249
  57. package/dist/godot-tools.js +1 -183
  58. package/dist/http-rate-limit.js +1 -0
  59. package/dist/http-server-hardening.js +1 -0
  60. package/dist/image-tools.js +1 -157
  61. package/dist/infrastructure/command-reference.js +32 -0
  62. package/dist/infrastructure/config.js +424 -0
  63. package/dist/infrastructure/context7-auth.js +55 -0
  64. package/dist/infrastructure/http-rate-limit.js +42 -0
  65. package/dist/infrastructure/http-server-hardening.js +23 -0
  66. package/dist/infrastructure/integration-queue.js +46 -0
  67. package/dist/infrastructure/logger.js +129 -0
  68. package/dist/infrastructure/mcp-event-store.js +103 -0
  69. package/dist/infrastructure/ngrok-auth-pool.js +208 -0
  70. package/dist/infrastructure/request-context.js +14 -0
  71. package/dist/infrastructure/shutdown.js +37 -0
  72. package/dist/infrastructure/sse-heartbeat.js +47 -0
  73. package/dist/infrastructure/tool-capabilities.js +67 -0
  74. package/dist/infrastructure/tool-result-budget.js +175 -0
  75. package/dist/infrastructure/user-config.js +167 -0
  76. package/dist/integration-discovery.js +1 -98
  77. package/dist/integration-queue.js +1 -0
  78. package/dist/integrations/agent-reach/agent-reach-tools.js +196 -0
  79. package/dist/integrations/agent-reach/native-channels.js +468 -0
  80. package/dist/integrations/aseprite/aseprite-analysis-tools.js +368 -0
  81. package/dist/integrations/aseprite/aseprite-editing-tools.js +647 -0
  82. package/dist/integrations/aseprite/aseprite-live-tools.js +297 -0
  83. package/dist/integrations/aseprite/aseprite-safety-tools.js +594 -0
  84. package/dist/integrations/aseprite/aseprite-specialized-tools.js +289 -0
  85. package/dist/integrations/aseprite/aseprite-tools.js +837 -0
  86. package/dist/integrations/blender/blender-catalog-mesh.js +593 -0
  87. package/dist/integrations/blender/blender-catalog-object.js +906 -0
  88. package/dist/integrations/blender/blender-catalog-scene.js +266 -0
  89. package/dist/integrations/blender/blender-catalog-select.js +581 -0
  90. package/dist/integrations/blender/blender-catalog-stubs.js +7512 -0
  91. package/dist/integrations/blender/blender-catalog.js +165 -0
  92. package/dist/integrations/blender/blender-client.js +105 -0
  93. package/dist/integrations/blender/blender-tools.js +2243 -0
  94. package/dist/integrations/context7/context7-tools.js +106 -0
  95. package/dist/integrations/dotnet/dotnet-tools.js +195 -0
  96. package/dist/integrations/godot/godot-animation-tilemap.js +74 -0
  97. package/dist/integrations/godot/godot-csharp-build.js +91 -0
  98. package/dist/integrations/godot/godot-csharp-project.js +155 -0
  99. package/dist/integrations/godot/godot-csharp-runner.js +118 -0
  100. package/dist/integrations/godot/godot-csharp-semantic.js +146 -0
  101. package/dist/integrations/godot/godot-csharp-validate.js +71 -0
  102. package/dist/integrations/godot/godot-dotnet-env.js +134 -0
  103. package/dist/integrations/godot/godot-editor-bridge.js +328 -0
  104. package/dist/integrations/godot/godot-gdscript.js +536 -0
  105. package/dist/integrations/godot/godot-project-settings.js +178 -0
  106. package/dist/integrations/godot/godot-runtime-testing.js +263 -0
  107. package/dist/integrations/godot/godot-tools.js +193 -0
  108. package/dist/integrations/images/image-tools.js +414 -0
  109. package/dist/integrations/images/png-codec.js +251 -0
  110. package/dist/integrations/images/view-image.js +99 -0
  111. package/dist/integrations/images/window-capture.js +148 -0
  112. package/dist/integrations/integration-discovery.js +185 -0
  113. package/dist/integrations/obsidian/obsidian-tools.js +205 -0
  114. package/dist/integrations/playwright/browser-session.js +516 -0
  115. package/dist/integrations/playwright/browser-stability.js +36 -0
  116. package/dist/integrations/playwright/playwright-runtime.js +105 -0
  117. package/dist/integrations/playwright/web-tools.js +504 -0
  118. package/dist/integrations/roblox/roblox-helpers.js +381 -0
  119. package/dist/integrations/roblox/roblox-studio-client.js +112 -0
  120. package/dist/integrations/roblox/roblox-tools.js +106 -0
  121. package/dist/integrations/serena/serena-manager.js +464 -0
  122. package/dist/integrations/serena/serena-tools.js +411 -0
  123. package/dist/logger.js +1 -76
  124. package/dist/mcp-event-store.js +1 -0
  125. package/dist/oauth-provider.js +1 -377
  126. package/dist/pi-tools.js +1 -81
  127. package/dist/playwright-runtime.js +1 -0
  128. package/dist/process/background-lifecycle.js +189 -0
  129. package/dist/process/control-retry.js +42 -0
  130. package/dist/process/crash-recovery.js +23 -0
  131. package/dist/process/processes.js +456 -0
  132. package/dist/processes.js +1 -218
  133. package/dist/request-context.js +1 -0
  134. package/dist/review-checkpoints.js +1 -142
  135. package/dist/room-registry.js +1 -0
  136. package/dist/roots.js +1 -53
  137. package/dist/search-discovery.js +1 -271
  138. package/dist/serena-manager.js +1 -443
  139. package/dist/serena-tools.js +1 -411
  140. package/dist/server/dashboard-page-styles.js +331 -0
  141. package/dist/server/dashboard-page.js +1509 -0
  142. package/dist/server/dashboard-routes.js +46 -0
  143. package/dist/server/dashboard.js +240 -0
  144. package/dist/server/http-helpers.js +30 -0
  145. package/dist/server/integration-profile-update.js +37 -0
  146. package/dist/server/mcp-policy.js +169 -0
  147. package/dist/server/mcp-server-factory.js +127 -0
  148. package/dist/server/mcp-tool-registrar.js +182 -0
  149. package/dist/server/openai-session-hint.js +14 -0
  150. package/dist/server/tool-groups.js +29 -0
  151. package/dist/server/tool-logging.js +33 -0
  152. package/dist/server/tool-registration-shared.js +59 -0
  153. package/dist/server/tools/aseprite-advanced-tools-registration.js +547 -0
  154. package/dist/server/tools/aseprite-tools-registration.js +213 -0
  155. package/dist/server/tools/blender-tools-registration.js +690 -0
  156. package/dist/server/tools/core-file-tools-registration.js +459 -0
  157. package/dist/server/tools/dotnet-godot-window-tools-registration.js +120 -0
  158. package/dist/server/tools/godot-csharp-tools-registration.js +252 -0
  159. package/dist/server/tools/godot-gdscript-tools-registration.js +189 -0
  160. package/dist/server/tools/process-project-tools-registration.js +155 -0
  161. package/dist/server/tools/roblox-tools-registration.js +514 -0
  162. package/dist/server/tools/web-image-tools-registration.js +326 -0
  163. package/dist/server/tools/workspace-lifecycle-tools-registration.js +130 -0
  164. package/dist/server/ui-assets.js +97 -0
  165. package/dist/server/workspace-analytics.js +92 -0
  166. package/dist/server.js +453 -2713
  167. package/dist/session-registry.js +1 -0
  168. package/dist/shutdown.js +1 -0
  169. package/dist/skills.js +1 -45
  170. package/dist/sse-heartbeat.js +1 -0
  171. package/dist/tool-capabilities.js +1 -0
  172. package/dist/tool-result-budget.js +1 -0
  173. package/dist/tools/pi-tools.js +81 -0
  174. package/dist/tunnels/cloudflare-tunnel.js +217 -0
  175. package/dist/tunnels/cloudflared-service.js +174 -0
  176. package/dist/tunnels/ngrok-tunnel.js +220 -0
  177. package/dist/tunnels/tunnel-manager.js +186 -0
  178. package/dist/tunnels/tunnel-types.js +1 -0
  179. package/dist/tunnels/tunnel-utils.js +62 -0
  180. package/dist/ui/.vite/manifest.json +9 -2487
  181. package/dist/ui/assets/heavy-payload-D42A9ceL.js +1 -0
  182. package/dist/ui/assets/lightweight-diff-Cv4g9Hdr.js +13 -0
  183. package/dist/ui/assets/review-payload-DKIg1cKF.js +1 -0
  184. package/dist/ui/assets/workspace-app-CeK3NhmB.css +1 -0
  185. package/dist/ui/assets/{workspace-app-C5QsE314.js → workspace-app-CkUXnpl4.js} +6 -6
  186. package/dist/ui/brand-theme.js +23 -0
  187. package/dist/ui/workspace-app.html +15 -15
  188. package/dist/user-config.js +1 -57
  189. package/dist/view-image.js +1 -104
  190. package/dist/web-tools.js +1 -200
  191. package/dist/window-capture.js +1 -74
  192. package/dist/workspace/artifact-registry.js +69 -0
  193. package/dist/workspace/git-worktrees.js +141 -0
  194. package/dist/workspace/git.js +42 -0
  195. package/dist/workspace/review-checkpoints.js +142 -0
  196. package/dist/workspace/roots.js +56 -0
  197. package/dist/workspace/search-discovery.js +264 -0
  198. package/dist/workspace/skills.js +45 -0
  199. package/dist/workspace/workspace-store.js +219 -0
  200. package/dist/workspace/workspaces.js +314 -0
  201. package/dist/workspace-store.js +1 -125
  202. package/dist/workspaces.js +1 -226
  203. package/docs/CREATOR_STORE_FREE_ASSETS.md +162 -0
  204. package/docs/DEVELOPMENT_TOOLS.md +136 -93
  205. package/docs/assets/auvrynt-icon.png +0 -0
  206. package/docs/assets/auvrynt-icon.svg +20 -0
  207. package/docs/chatgpt-coding-workflow.md +143 -143
  208. package/docs/configuration.md +156 -124
  209. package/docs/diagnostics.md +79 -0
  210. package/docs/gotchas.md +244 -202
  211. package/docs/multi-agent-and-long-projects.md +91 -0
  212. package/docs/security.md +138 -100
  213. package/docs/setup.md +171 -131
  214. package/docs/source-layout.md +60 -0
  215. package/extensions/auvrynt_bridge/auvrynt_bridge.lua +594 -0
  216. package/extensions/auvrynt_bridge/live_analysis.lua +181 -0
  217. package/extensions/auvrynt_bridge/live_animation.lua +134 -0
  218. package/extensions/auvrynt_bridge/live_commands.lua +24 -0
  219. package/extensions/auvrynt_bridge/live_common.lua +130 -0
  220. package/extensions/auvrynt_bridge/live_document.lua +78 -0
  221. package/extensions/auvrynt_bridge/live_drawing.lua +125 -0
  222. package/extensions/auvrynt_bridge/live_effects.lua +91 -0
  223. package/extensions/auvrynt_bridge/live_palette_template.lua +167 -0
  224. package/extensions/auvrynt_bridge/live_selection.lua +110 -0
  225. package/extensions/auvrynt_bridge/live_structure.lua +129 -0
  226. package/extensions/auvrynt_bridge/package.json +17 -0
  227. package/guides/ASEPRITE_AGENT_GUIDE.md +133 -0
  228. package/guides/BLENDER_AGENT_GUIDE.md +472 -0
  229. package/guides/GODOT_AGENT_GUIDE.md +298 -0
  230. package/guides/PROJECT_ROUTER.md +165 -0
  231. package/guides/ROBLOX_AGENT_GUIDE.md +75 -0
  232. package/guides/SOFTWARE_AGENT_GUIDE.md +104 -0
  233. package/guides/WEB_AGENT_GUIDE.md +287 -0
  234. package/package.json +78 -70
  235. package/scripts/dev-server.mjs +121 -120
  236. package/scripts/live-tunnel-smoke.mjs +538 -0
  237. package/scripts/repo-hygiene.mjs +74 -0
  238. package/scripts/restart-after-crash.mjs +49 -0
  239. package/scripts/run-tests.mjs +166 -0
  240. package/dist/ui/assets/abap-CLvhMVsD.js +0 -1
  241. package/dist/ui/assets/actionscript-3--17pq3dv.js +0 -1
  242. package/dist/ui/assets/ada-C5qYipkI.js +0 -1
  243. package/dist/ui/assets/andromeeda-vGVdxbeo.js +0 -1
  244. package/dist/ui/assets/angular-html-BJqQFYI6.js +0 -1
  245. package/dist/ui/assets/angular-ts-CMJECO0Y.js +0 -1
  246. package/dist/ui/assets/apache-U0d_L8uA.js +0 -1
  247. package/dist/ui/assets/apex-CGTLDQj6.js +0 -1
  248. package/dist/ui/assets/apl-DWeXpBBr.js +0 -1
  249. package/dist/ui/assets/applescript-CCn79oCD.js +0 -1
  250. package/dist/ui/assets/ara-4CJ0cIlV.js +0 -1
  251. package/dist/ui/assets/asciidoc-DE70LPWp.js +0 -1
  252. package/dist/ui/assets/asm-Cmm7eHzH.js +0 -1
  253. package/dist/ui/assets/astro-CLbttLOq.js +0 -1
  254. package/dist/ui/assets/aurora-x-CDeNXAV0.js +0 -1
  255. package/dist/ui/assets/awk-BWXHIvNe.js +0 -1
  256. package/dist/ui/assets/ayu-dark-DluEY0Gj.js +0 -1
  257. package/dist/ui/assets/ayu-light-C3h-C4tm.js +0 -1
  258. package/dist/ui/assets/ayu-mirage-Bqwy1Gya.js +0 -1
  259. package/dist/ui/assets/ballerina-B7ZEbQpA.js +0 -1
  260. package/dist/ui/assets/bat-Bo4NYOV-.js +0 -1
  261. package/dist/ui/assets/beancount-D-usSTwE.js +0 -1
  262. package/dist/ui/assets/berry-DKpUyyne.js +0 -1
  263. package/dist/ui/assets/bibtex-Ci_nEsc7.js +0 -1
  264. package/dist/ui/assets/bicep-CUHmPFLl.js +0 -1
  265. package/dist/ui/assets/bird2-C2hNVINV.js +0 -1
  266. package/dist/ui/assets/blade-BOzY0P2V.js +0 -1
  267. package/dist/ui/assets/bsl-BkkzgIyY.js +0 -1
  268. package/dist/ui/assets/c-BG-8uJvh.js +0 -1
  269. package/dist/ui/assets/c3-CnJL0r0V.js +0 -1
  270. package/dist/ui/assets/cadence-CQ2zXKGN.js +0 -1
  271. package/dist/ui/assets/cairo-DLTphjLi.js +0 -1
  272. package/dist/ui/assets/catppuccin-frappe-3VR1Za6u.js +0 -1
  273. package/dist/ui/assets/catppuccin-latte-DwIHMF0Q.js +0 -1
  274. package/dist/ui/assets/catppuccin-macchiato-DYnBP6_5.js +0 -1
  275. package/dist/ui/assets/catppuccin-mocha-DYhrFGRu.js +0 -1
  276. package/dist/ui/assets/clarity-SemFz856.js +0 -1
  277. package/dist/ui/assets/clojure-DqKBuwfJ.js +0 -1
  278. package/dist/ui/assets/cmake-Bj61d0ZC.js +0 -1
  279. package/dist/ui/assets/cobol-I_17IuGe.js +0 -1
  280. package/dist/ui/assets/codeowners-C8r90Shi.js +0 -1
  281. package/dist/ui/assets/codeql-oeQT6MSM.js +0 -1
  282. package/dist/ui/assets/coffee-C0B8hmok.js +0 -1
  283. package/dist/ui/assets/common-lisp-Cv5bFMCO.js +0 -1
  284. package/dist/ui/assets/coq-BrsZFFmf.js +0 -1
  285. package/dist/ui/assets/cpp-DDJXt6Vs.js +0 -1
  286. package/dist/ui/assets/crystal-Bexqace6.js +0 -1
  287. package/dist/ui/assets/csharp-Ct8U2NOr.js +0 -1
  288. package/dist/ui/assets/css-DSQhw_9R.js +0 -1
  289. package/dist/ui/assets/csv-Dx-8-gkx.js +0 -1
  290. package/dist/ui/assets/cue-CE9AQfxI.js +0 -1
  291. package/dist/ui/assets/cypher-ClKdZ_lG.js +0 -1
  292. package/dist/ui/assets/d-qD-0Kul2.js +0 -1
  293. package/dist/ui/assets/dark-plus-Cs2F2srj.js +0 -1
  294. package/dist/ui/assets/dart-DkHntEIa.js +0 -1
  295. package/dist/ui/assets/dax-BkyTk9wS.js +0 -1
  296. package/dist/ui/assets/desktop-Dlh5hvp9.js +0 -1
  297. package/dist/ui/assets/diff-woXpYk--.js +0 -1
  298. package/dist/ui/assets/docker-IyjqRm3v.js +0 -1
  299. package/dist/ui/assets/dotenv-_5a1GRtc.js +0 -1
  300. package/dist/ui/assets/dracula-BHWKrbxM.js +0 -1
  301. package/dist/ui/assets/dracula-soft-5eyTD99u.js +0 -1
  302. package/dist/ui/assets/dream-maker-DW3nJb8Q.js +0 -1
  303. package/dist/ui/assets/edge-Z8YYkHOr.js +0 -1
  304. package/dist/ui/assets/elixir-CG9uKtAF.js +0 -1
  305. package/dist/ui/assets/elm-GfWG2IfT.js +0 -1
  306. package/dist/ui/assets/emacs-lisp-C9PiwqqW.js +0 -1
  307. package/dist/ui/assets/erb-xe89e73J.js +0 -1
  308. package/dist/ui/assets/erlang-Cphh6RMH.js +0 -1
  309. package/dist/ui/assets/everforest-dark-sB-x3p7T.js +0 -1
  310. package/dist/ui/assets/everforest-light-Df2xbC6M.js +0 -1
  311. package/dist/ui/assets/fennel-DQxkIbk2.js +0 -1
  312. package/dist/ui/assets/fish-BJitypiv.js +0 -1
  313. package/dist/ui/assets/fluent-C03EYrpw.js +0 -1
  314. package/dist/ui/assets/fortran-fixed-form-DEKoE2YW.js +0 -1
  315. package/dist/ui/assets/fortran-free-form-CYNrtFtB.js +0 -1
  316. package/dist/ui/assets/fsharp-D13ZGOAj.js +0 -1
  317. package/dist/ui/assets/gdresource-C0sCabJj.js +0 -1
  318. package/dist/ui/assets/gdscript-Cp2uCuqX.js +0 -1
  319. package/dist/ui/assets/gdshader-CBce3t8t.js +0 -1
  320. package/dist/ui/assets/genie-CV2tkWYe.js +0 -1
  321. package/dist/ui/assets/gherkin-DExj1W_8.js +0 -1
  322. package/dist/ui/assets/git-commit-BSykSTBG.js +0 -1
  323. package/dist/ui/assets/git-rebase-CoTL_uSE.js +0 -1
  324. package/dist/ui/assets/github-dark-C-LZuMrd.js +0 -1
  325. package/dist/ui/assets/github-dark-default-DXG-b-1a.js +0 -1
  326. package/dist/ui/assets/github-dark-dimmed-Bx1FflLF.js +0 -1
  327. package/dist/ui/assets/github-dark-high-contrast-B_tTalzw.js +0 -1
  328. package/dist/ui/assets/github-light-EUqPIrTm.js +0 -1
  329. package/dist/ui/assets/github-light-default-BXViO-2h.js +0 -1
  330. package/dist/ui/assets/github-light-high-contrast-B68TUdTA.js +0 -1
  331. package/dist/ui/assets/gleam-CSRkHgEL.js +0 -1
  332. package/dist/ui/assets/glimmer-js-DAn4UCSu.js +0 -1
  333. package/dist/ui/assets/glimmer-ts-Tjyi6Gh5.js +0 -1
  334. package/dist/ui/assets/glsl-CtTDZoqR.js +0 -1
  335. package/dist/ui/assets/gn-ilITqXS6.js +0 -1
  336. package/dist/ui/assets/gnuplot-7GGW24-e.js +0 -1
  337. package/dist/ui/assets/go-BJwz_mda.js +0 -1
  338. package/dist/ui/assets/graphql-D5gcC_Jk.js +0 -1
  339. package/dist/ui/assets/groovy-CacY0gHj.js +0 -1
  340. package/dist/ui/assets/gruvbox-dark-hard-C820rvS2.js +0 -1
  341. package/dist/ui/assets/gruvbox-dark-medium-BPjhmG05.js +0 -1
  342. package/dist/ui/assets/gruvbox-dark-soft-MrdJrrXF.js +0 -1
  343. package/dist/ui/assets/gruvbox-light-hard-BC_s9l72.js +0 -1
  344. package/dist/ui/assets/gruvbox-light-medium-BAWPOn9u.js +0 -1
  345. package/dist/ui/assets/gruvbox-light-soft-BSMLrYjP.js +0 -1
  346. package/dist/ui/assets/hack-BJXY27dt.js +0 -1
  347. package/dist/ui/assets/haml-BLfFoZf7.js +0 -1
  348. package/dist/ui/assets/handlebars-Dw6CWkvN.js +0 -1
  349. package/dist/ui/assets/haskell-D8IpX4py.js +0 -1
  350. package/dist/ui/assets/haxe-OTjmBuCE.js +0 -1
  351. package/dist/ui/assets/hcl-Dh228itO.js +0 -1
  352. package/dist/ui/assets/heavy-payload-Dcg0-F-S.js +0 -4
  353. package/dist/ui/assets/hjson-CxZEssPk.js +0 -1
  354. package/dist/ui/assets/hlsl-Cvrh5tZx.js +0 -1
  355. package/dist/ui/assets/horizon-CE9ld1lL.js +0 -1
  356. package/dist/ui/assets/horizon-bright-Br1oVSNq.js +0 -1
  357. package/dist/ui/assets/houston-CsvMBhTu.js +0 -1
  358. package/dist/ui/assets/html-CAcAWvoN.js +0 -1
  359. package/dist/ui/assets/html-derivative-8aSW2E_7.js +0 -1
  360. package/dist/ui/assets/http-B2YR_3V1.js +0 -1
  361. package/dist/ui/assets/hurl-BnDJ9Zhf.js +0 -1
  362. package/dist/ui/assets/hxml-B0Qn7Nwc.js +0 -1
  363. package/dist/ui/assets/hy-CZbG8q4J.js +0 -1
  364. package/dist/ui/assets/imba-DsUTQ-LC.js +0 -1
  365. package/dist/ui/assets/ini-B5eOa1yu.js +0 -1
  366. package/dist/ui/assets/java-Doxi4W8u.js +0 -1
  367. package/dist/ui/assets/javascript-BbRdEqti.js +0 -1
  368. package/dist/ui/assets/jinja-CS3Tpv_Q.js +0 -1
  369. package/dist/ui/assets/jison-BkPGYVHR.js +0 -1
  370. package/dist/ui/assets/json-BMt1m3m8.js +0 -1
  371. package/dist/ui/assets/json5-BR5RXkoi.js +0 -1
  372. package/dist/ui/assets/jsonc-CYpm1nAK.js +0 -1
  373. package/dist/ui/assets/jsonl-CmCQp5Yx.js +0 -1
  374. package/dist/ui/assets/jsonnet-CJTPZ8u_.js +0 -1
  375. package/dist/ui/assets/jssm-DXw9l8Rf.js +0 -1
  376. package/dist/ui/assets/jsx-CQKrJXXY.js +0 -1
  377. package/dist/ui/assets/julia-BuN7i2du.js +0 -1
  378. package/dist/ui/assets/just-BswEPFPu.js +0 -1
  379. package/dist/ui/assets/kanagawa-dragon-CXtmUGW6.js +0 -1
  380. package/dist/ui/assets/kanagawa-lotus-BN08jTvb.js +0 -1
  381. package/dist/ui/assets/kanagawa-wave-CTweb8Dz.js +0 -1
  382. package/dist/ui/assets/kdl-CsD5j6eV.js +0 -1
  383. package/dist/ui/assets/kotlin-DhhofPvG.js +0 -1
  384. package/dist/ui/assets/kusto-BUv0MjJC.js +0 -1
  385. package/dist/ui/assets/laserwave-C_8bwKvT.js +0 -1
  386. package/dist/ui/assets/latex-DU2VyFfA.js +0 -1
  387. package/dist/ui/assets/lean-CewbzKMR.js +0 -1
  388. package/dist/ui/assets/less-DVTAwKKz.js +0 -1
  389. package/dist/ui/assets/light-plus-DVQuIRkW.js +0 -1
  390. package/dist/ui/assets/liquid-Cmz1L3dq.js +0 -1
  391. package/dist/ui/assets/llvm-Cm23YOpf.js +0 -1
  392. package/dist/ui/assets/log-BNLmms1o.js +0 -1
  393. package/dist/ui/assets/logo-Cluzi2Zq.js +0 -1
  394. package/dist/ui/assets/lua-CfVXhkaJ.js +0 -1
  395. package/dist/ui/assets/luau-CNKltnaQ.js +0 -1
  396. package/dist/ui/assets/make-Dixweg8N.js +0 -1
  397. package/dist/ui/assets/markdown-BYOwaDjH.js +0 -1
  398. package/dist/ui/assets/marko-C5bfqGiA.js +0 -1
  399. package/dist/ui/assets/material-theme-Bm3Qr25_.js +0 -1
  400. package/dist/ui/assets/material-theme-darker-2IIEA8gg.js +0 -1
  401. package/dist/ui/assets/material-theme-lighter-uhdI0v04.js +0 -1
  402. package/dist/ui/assets/material-theme-ocean-CHQ94UKr.js +0 -1
  403. package/dist/ui/assets/material-theme-palenight-B5W6OYN7.js +0 -1
  404. package/dist/ui/assets/matlab-D7qyCx1q.js +0 -1
  405. package/dist/ui/assets/mdc-CVBXYfyq.js +0 -1
  406. package/dist/ui/assets/mdx-DQZ5AkYe.js +0 -1
  407. package/dist/ui/assets/mermaid-Bk4SNUv9.js +0 -1
  408. package/dist/ui/assets/min-dark-BSWPekZh.js +0 -1
  409. package/dist/ui/assets/min-light-DDpmG2fV.js +0 -1
  410. package/dist/ui/assets/mipsasm-BMqwQI7S.js +0 -1
  411. package/dist/ui/assets/mojo-BgCJLMeH.js +0 -1
  412. package/dist/ui/assets/monokai-CdkpiU2Y.js +0 -1
  413. package/dist/ui/assets/moonbit-CaWjb8XO.js +0 -1
  414. package/dist/ui/assets/move-B1IS1UjX.js +0 -1
  415. package/dist/ui/assets/narrat-_X_XdTYD.js +0 -1
  416. package/dist/ui/assets/nextflow-Bbiyy34d.js +0 -1
  417. package/dist/ui/assets/nextflow-groovy-Dc_ddanL.js +0 -1
  418. package/dist/ui/assets/nginx-CzJafxLa.js +0 -1
  419. package/dist/ui/assets/night-owl-DhmEMT88.js +0 -1
  420. package/dist/ui/assets/night-owl-light-eJ-hLW7d.js +0 -1
  421. package/dist/ui/assets/nim-DABKtHtM.js +0 -1
  422. package/dist/ui/assets/nix-IvuFDN5E.js +0 -1
  423. package/dist/ui/assets/nord-Cb4Vim4T.js +0 -1
  424. package/dist/ui/assets/nushell-DcLAeLz5.js +0 -1
  425. package/dist/ui/assets/objective-c-D1A_Heim.js +0 -1
  426. package/dist/ui/assets/objective-cpp-BsSzOQcm.js +0 -1
  427. package/dist/ui/assets/ocaml-O90oeIOV.js +0 -1
  428. package/dist/ui/assets/odin-B1RWQWA5.js +0 -1
  429. package/dist/ui/assets/one-dark-pro-CLwyXe_n.js +0 -1
  430. package/dist/ui/assets/one-light-D7Lr4KcI.js +0 -1
  431. package/dist/ui/assets/openscad-BUDT5pXO.js +0 -1
  432. package/dist/ui/assets/pascal-4ZHwLPI5.js +0 -1
  433. package/dist/ui/assets/perl-CBh7L3lZ.js +0 -1
  434. package/dist/ui/assets/php-DFbI9q5p.js +0 -1
  435. package/dist/ui/assets/pierre-dark-sU4Zdns8.js +0 -1
  436. package/dist/ui/assets/pierre-dark-soft-HXgun5vs.js +0 -1
  437. package/dist/ui/assets/pierre-light-DWBk51d8.js +0 -1
  438. package/dist/ui/assets/pierre-light-soft-CodEzPxf.js +0 -1
  439. package/dist/ui/assets/pkl-ot-7Btpt.js +0 -1
  440. package/dist/ui/assets/plastic-DQwYfKfQ.js +0 -1
  441. package/dist/ui/assets/plsql-DGHpHOYJ.js +0 -1
  442. package/dist/ui/assets/po-BiJDBrnU.js +0 -1
  443. package/dist/ui/assets/poimandres-DRFjx7u4.js +0 -1
  444. package/dist/ui/assets/polar-C7UOKdEL.js +0 -1
  445. package/dist/ui/assets/postcss-BXeXVLqQ.js +0 -1
  446. package/dist/ui/assets/powerquery-DNMTfnFr.js +0 -1
  447. package/dist/ui/assets/powershell-DshXNtvi.js +0 -1
  448. package/dist/ui/assets/prisma-BsRQq5mF.js +0 -1
  449. package/dist/ui/assets/prolog-iXnhIJG7.js +0 -1
  450. package/dist/ui/assets/proto-DB4EqR-F.js +0 -1
  451. package/dist/ui/assets/pug-C_PxC7gO.js +0 -1
  452. package/dist/ui/assets/puppet-CDv2pdJW.js +0 -1
  453. package/dist/ui/assets/purescript-9MfHhQsQ.js +0 -1
  454. package/dist/ui/assets/python-gzcpVVnB.js +0 -1
  455. package/dist/ui/assets/qml-DtngoFFK.js +0 -1
  456. package/dist/ui/assets/qmldir-DCQb3MpD.js +0 -1
  457. package/dist/ui/assets/qss-Fe1Jh2GI.js +0 -1
  458. package/dist/ui/assets/r-DohkcevW.js +0 -1
  459. package/dist/ui/assets/racket-DcIDlBhZ.js +0 -1
  460. package/dist/ui/assets/raku-B3gFvitq.js +0 -1
  461. package/dist/ui/assets/razor-C4t8J0_E.js +0 -1
  462. package/dist/ui/assets/red-CJ3rzSJv.js +0 -1
  463. package/dist/ui/assets/reg-CRGYupPL.js +0 -1
  464. package/dist/ui/assets/regexp-OGbTbjgY.js +0 -1
  465. package/dist/ui/assets/rel-BtDbiS_P.js +0 -1
  466. package/dist/ui/assets/review-payload-C5Qz60Kq.js +0 -1
  467. package/dist/ui/assets/riscv-Ckw8ddFX.js +0 -1
  468. package/dist/ui/assets/ron-VUp2lXgN.js +0 -1
  469. package/dist/ui/assets/rose-pine-BthvhNj6.js +0 -1
  470. package/dist/ui/assets/rose-pine-dawn-Dg85fqjY.js +0 -1
  471. package/dist/ui/assets/rose-pine-moon-hon4tzzS.js +0 -1
  472. package/dist/ui/assets/rosmsg-CAekHB0j.js +0 -1
  473. package/dist/ui/assets/rst-CfBbbcvC.js +0 -1
  474. package/dist/ui/assets/ruby-Bw0mpxHY.js +0 -1
  475. package/dist/ui/assets/rust-Cfkwpbl8.js +0 -1
  476. package/dist/ui/assets/sas-Cs3s9JOf.js +0 -1
  477. package/dist/ui/assets/sass-DXrisJhu.js +0 -1
  478. package/dist/ui/assets/scala-DKOlJaKm.js +0 -1
  479. package/dist/ui/assets/scheme-DQCgrYNe.js +0 -1
  480. package/dist/ui/assets/scss-sRxNJS54.js +0 -1
  481. package/dist/ui/assets/sdbl-bTVj8UrX.js +0 -1
  482. package/dist/ui/assets/shaderlab-TOUzSsQk.js +0 -1
  483. package/dist/ui/assets/shellscript-B0X6wh0R.js +0 -1
  484. package/dist/ui/assets/shellsession-D2FdOioR.js +0 -1
  485. package/dist/ui/assets/slack-dark-DnToyrRv.js +0 -1
  486. package/dist/ui/assets/slack-ochin-B2OO5cIa.js +0 -1
  487. package/dist/ui/assets/smalltalk-B16xEiuN.js +0 -1
  488. package/dist/ui/assets/snazzy-light-4G7pJPwS.js +0 -1
  489. package/dist/ui/assets/solarized-dark-DV17i1UV.js +0 -1
  490. package/dist/ui/assets/solarized-light-DSh2HLQt.js +0 -1
  491. package/dist/ui/assets/solidity-CKzVLygQ.js +0 -1
  492. package/dist/ui/assets/soy-s6g9OjJ1.js +0 -1
  493. package/dist/ui/assets/sparql-D_iOobhT.js +0 -1
  494. package/dist/ui/assets/splunk-BC2Px7Mm.js +0 -1
  495. package/dist/ui/assets/sql-DVTnh5V-.js +0 -1
  496. package/dist/ui/assets/ssh-config-BgfXC-Er.js +0 -1
  497. package/dist/ui/assets/stata-DFIDiXF9.js +0 -1
  498. package/dist/ui/assets/stylus-B6D30XZt.js +0 -1
  499. package/dist/ui/assets/surrealql-DVfrsLyg.js +0 -1
  500. package/dist/ui/assets/svelte-D5GsxESq.js +0 -1
  501. package/dist/ui/assets/swift-DonLKvLd.js +0 -1
  502. package/dist/ui/assets/synthwave-84-nFMaYfgc.js +0 -1
  503. package/dist/ui/assets/system-verilog-DJ5XKQeo.js +0 -1
  504. package/dist/ui/assets/systemd-BxMlprV5.js +0 -1
  505. package/dist/ui/assets/talonscript-CohzipZa.js +0 -1
  506. package/dist/ui/assets/tasl-DMoTqEGO.js +0 -1
  507. package/dist/ui/assets/tcl-CZd0xW_V.js +0 -1
  508. package/dist/ui/assets/templ-DI-Zyqzd.js +0 -1
  509. package/dist/ui/assets/terraform-DswuEJGm.js +0 -1
  510. package/dist/ui/assets/tex-WHHmlbJI.js +0 -1
  511. package/dist/ui/assets/tokyo-night-oM2G3aXe.js +0 -1
  512. package/dist/ui/assets/toml-CcmNWLt0.js +0 -1
  513. package/dist/ui/assets/ts-tags-Dwpo2RFJ.js +0 -1
  514. package/dist/ui/assets/tsv-sltzmVWM.js +0 -1
  515. package/dist/ui/assets/tsx-ph_idaAW.js +0 -1
  516. package/dist/ui/assets/turtle-ByJddavk.js +0 -1
  517. package/dist/ui/assets/twig-YO17jFjR.js +0 -1
  518. package/dist/ui/assets/typescript-CbAxjhkl.js +0 -1
  519. package/dist/ui/assets/typespec-B88KGewJ.js +0 -1
  520. package/dist/ui/assets/typst-DI99ib-x.js +0 -1
  521. package/dist/ui/assets/useFileDiffInstance-B2DLX3Vg.js +0 -244
  522. package/dist/ui/assets/v-DETTlOr0.js +0 -1
  523. package/dist/ui/assets/vala-zf12oZj6.js +0 -1
  524. package/dist/ui/assets/vb-Djn5o6TS.js +0 -1
  525. package/dist/ui/assets/verilog-CiiDBU1e.js +0 -1
  526. package/dist/ui/assets/vesper-D5bVUKB1.js +0 -1
  527. package/dist/ui/assets/vhdl-BroJfC0k.js +0 -1
  528. package/dist/ui/assets/viml-DvXPmvsu.js +0 -1
  529. package/dist/ui/assets/vitesse-black-fwtXNY1n.js +0 -1
  530. package/dist/ui/assets/vitesse-dark-BZCL-v6S.js +0 -1
  531. package/dist/ui/assets/vitesse-light-VbXTXTou.js +0 -1
  532. package/dist/ui/assets/vue-CraHL-Ps.js +0 -1
  533. package/dist/ui/assets/vue-html-e9tyZNtS.js +0 -1
  534. package/dist/ui/assets/vue-vine-CofmxaUb.js +0 -1
  535. package/dist/ui/assets/vyper-CgoNMtux.js +0 -1
  536. package/dist/ui/assets/wasm-BnjxR4X6.js +0 -1
  537. package/dist/ui/assets/wasm-ByWQv1Qj.js +0 -1
  538. package/dist/ui/assets/wenyan-C8pVoKbM.js +0 -1
  539. package/dist/ui/assets/wgsl-BsKzXJz4.js +0 -1
  540. package/dist/ui/assets/wikitext-ClFFjSW2.js +0 -1
  541. package/dist/ui/assets/wit-DdvCle-K.js +0 -1
  542. package/dist/ui/assets/wolfram-DLL8P-h_.js +0 -1
  543. package/dist/ui/assets/workspace-app-8--oTbCd.css +0 -1
  544. package/dist/ui/assets/xml-BWSdPZHm.js +0 -1
  545. package/dist/ui/assets/xsl-BtCt7Hx8.js +0 -1
  546. package/dist/ui/assets/yaml-BZiTw7cQ.js +0 -1
  547. package/dist/ui/assets/zenscript-BnlCZFoB.js +0 -1
  548. package/dist/ui/assets/zig-CMLA9XwU.js +0 -1
  549. package/docs/assets/auvrynt-logo-light.png +0 -0
  550. package/docs/assets/auvrynt-screenshot.png +0 -0
@@ -0,0 +1,220 @@
1
+ import { closeSync, existsSync, openSync } from "node:fs";
2
+ import { mkdtemp, mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
3
+ import { execFileSync, spawn } from "node:child_process";
4
+ import { homedir, tmpdir } from "node:os";
5
+ import { join } from "node:path";
6
+ import { isProcessRunning } from "../background-lifecycle.js";
7
+ import { findCommand, isGeneratedNgrokUrl, normalizeNgrokUrl } from "./tunnel-utils.js";
8
+ const MAX_STARTUP_OUTPUT_BYTES = 1024 * 1024;
9
+ const MAX_NGROK_DOWNLOAD_BYTES = 64 * 1024 * 1024;
10
+ const NGROK_DOWNLOAD_ORIGIN = "https://bin.equinox.io";
11
+ export function ngrokWindowsDownloadUrl(architecture = process.arch) {
12
+ const artifact = architecture === "arm64"
13
+ ? "ngrok-v3-stable-windows-arm64.zip"
14
+ : architecture === "ia32"
15
+ ? "ngrok-v3-stable-windows-386.zip"
16
+ : "ngrok-v3-stable-windows-amd64.zip";
17
+ return `${NGROK_DOWNLOAD_ORIGIN}/c/bNyj1mQVY4c/${artifact}`;
18
+ }
19
+ export function buildNgrokArgs(port, url) {
20
+ const args = ["http", String(port), "--log=stdout", "--log-format=json"];
21
+ const normalizedUrl = normalizeNgrokUrl(url);
22
+ if (normalizedUrl)
23
+ args.push("--url", normalizedUrl);
24
+ return args;
25
+ }
26
+ export function extractNgrokPublicUrl(output, expectedUrl) {
27
+ const expected = normalizeNgrokUrl(expectedUrl);
28
+ const candidates = output.match(/https:\/\/[^\s"'\\]+/g) ?? [];
29
+ for (const raw of candidates) {
30
+ const cleaned = raw.replace(/[),.;]+$/, "");
31
+ try {
32
+ const normalized = normalizeNgrokUrl(cleaned);
33
+ if (!normalized)
34
+ continue;
35
+ if (expected ? normalized === expected : isGeneratedNgrokUrl(normalized))
36
+ return normalized;
37
+ }
38
+ catch {
39
+ // Startup logs can include unrelated URLs; only valid endpoint origins count.
40
+ }
41
+ }
42
+ return undefined;
43
+ }
44
+ async function resolveNgrokExecutable() {
45
+ const found = findCommand("ngrok");
46
+ if (found)
47
+ return found;
48
+ if (process.platform === "win32") {
49
+ const storeExecutable = findWindowsStoreNgrok();
50
+ if (storeExecutable)
51
+ return storeExecutable;
52
+ const managedExecutable = join(homedir(), ".auvrynt", "bin", "ngrok.exe");
53
+ if (existsSync(managedExecutable) && verifyWindowsExecutable(managedExecutable)) {
54
+ return managedExecutable;
55
+ }
56
+ return installWindowsNgrok();
57
+ }
58
+ throw new Error("ngrok is required for AUVRYNT_TUNNEL_PROVIDER=ngrok. Install it from https://ngrok.com/download, ensure `ngrok` is on PATH, "
59
+ + "and either run `ngrok config add-authtoken <token>` or set AUVRYNT_NGROK_AUTHTOKEN.");
60
+ }
61
+ function findWindowsStoreNgrok() {
62
+ try {
63
+ const installLocation = execFileSync("powershell.exe", [
64
+ "-NoProfile",
65
+ "-NonInteractive",
66
+ "-Command",
67
+ "Get-AppxPackage -Name 'ngrok.ngrok' | Select-Object -First 1 -ExpandProperty InstallLocation",
68
+ ], { encoding: "utf8", windowsHide: true }).trim();
69
+ if (!installLocation)
70
+ return undefined;
71
+ const executable = join(installLocation, "ngrok.exe");
72
+ return existsSync(executable) ? executable : undefined;
73
+ }
74
+ catch {
75
+ return undefined;
76
+ }
77
+ }
78
+ async function installWindowsNgrok() {
79
+ const targetDir = join(homedir(), ".auvrynt", "bin");
80
+ const executable = join(targetDir, "ngrok.exe");
81
+ const downloadUrl = ngrokWindowsDownloadUrl();
82
+ const tempRoot = await mkdtemp(join(tmpdir(), "auvrynt-ngrok-"));
83
+ const archive = join(tempRoot, "ngrok.zip");
84
+ const extractedDir = join(tempRoot, "extracted");
85
+ try {
86
+ console.log("ngrok is not installed; downloading and verifying the official Windows build...");
87
+ const response = await fetch(downloadUrl, { signal: AbortSignal.timeout(120_000) });
88
+ if (!response.ok)
89
+ throw new Error(`Could not download ngrok (HTTP ${response.status}).`);
90
+ const length = Number(response.headers.get("content-length"));
91
+ if (Number.isFinite(length) && (length <= 0 || length > MAX_NGROK_DOWNLOAD_BYTES)) {
92
+ throw new Error("ngrok download size is invalid or exceeds the 64 MB safety limit.");
93
+ }
94
+ const bytes = Buffer.from(await response.arrayBuffer());
95
+ if (bytes.byteLength < 4 || bytes.byteLength > MAX_NGROK_DOWNLOAD_BYTES || bytes.subarray(0, 2).toString("ascii") !== "PK") {
96
+ throw new Error("ngrok download is not a valid ZIP archive.");
97
+ }
98
+ await writeFile(archive, bytes, { mode: 0o600 });
99
+ await mkdir(extractedDir, { recursive: true });
100
+ extractNgrokArchive(archive, extractedDir);
101
+ const extractedExecutable = join(extractedDir, "ngrok.exe");
102
+ if (!existsSync(extractedExecutable) || !verifyWindowsExecutable(extractedExecutable)) {
103
+ throw new Error("ngrok signature verification failed; the download was not installed.");
104
+ }
105
+ runWindowsDefenderScan(extractedExecutable);
106
+ await mkdir(targetDir, { recursive: true });
107
+ await rm(executable, { force: true });
108
+ await rename(extractedExecutable, executable);
109
+ execFileSync(executable, ["version"], { stdio: "ignore", windowsHide: true });
110
+ return executable;
111
+ }
112
+ finally {
113
+ await rm(tempRoot, { recursive: true, force: true });
114
+ }
115
+ }
116
+ function extractNgrokArchive(archive, destination) {
117
+ const entries = execFileSync("tar.exe", ["-tf", archive], { encoding: "utf8", windowsHide: true });
118
+ const normalized = entries.split(/\r?\n/).map((entry) => entry.trim()).filter(Boolean);
119
+ if (!normalized.includes("ngrok.exe") || normalized.some((entry) => entry.includes("..") || entry.startsWith("/") || entry.startsWith("\\"))) {
120
+ throw new Error("ngrok archive contains an unexpected file layout.");
121
+ }
122
+ execFileSync("tar.exe", ["-xf", archive, "-C", destination], { windowsHide: true });
123
+ }
124
+ function verifyWindowsExecutable(executable) {
125
+ try {
126
+ const quotedPath = executable.replaceAll("'", "''");
127
+ const status = execFileSync("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", `(Get-AuthenticodeSignature -LiteralPath '${quotedPath}').Status`], { encoding: "utf8", windowsHide: true }).trim();
128
+ return status === "Valid";
129
+ }
130
+ catch {
131
+ return false;
132
+ }
133
+ }
134
+ function runWindowsDefenderScan(executable) {
135
+ const quotedPath = executable.replaceAll("'", "''");
136
+ try {
137
+ const available = execFileSync("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", "[bool](Get-Command Start-MpScan -ErrorAction SilentlyContinue)"], { encoding: "utf8", windowsHide: true }).trim();
138
+ if (available.toLowerCase() === "true") {
139
+ execFileSync("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", `Start-MpScan -ScanType CustomScan -ScanPath '${quotedPath}' -ErrorAction Stop`], { windowsHide: true });
140
+ }
141
+ }
142
+ catch (error) {
143
+ throw new Error(`Microsoft Defender scan failed; ngrok was not installed. ${error instanceof Error ? error.message : String(error)}`);
144
+ }
145
+ }
146
+ async function waitForNgrokUrl(child, readOutput, spawnError, expectedUrl, timeoutMs) {
147
+ const deadline = Date.now() + timeoutMs;
148
+ while (Date.now() < deadline) {
149
+ const error = spawnError();
150
+ if (error)
151
+ throw new Error(`ngrok tunnel failed to start: ${error.message}`);
152
+ if (!child.pid || !isProcessRunning(child.pid))
153
+ throw new Error("ngrok tunnel exited before connecting.");
154
+ const output = await readOutput();
155
+ if (Buffer.byteLength(output, "utf8") > MAX_STARTUP_OUTPUT_BYTES) {
156
+ throw new Error("ngrok startup output exceeded 1 MB before providing a public URL.");
157
+ }
158
+ const url = extractNgrokPublicUrl(output, expectedUrl);
159
+ if (url)
160
+ return url;
161
+ await new Promise((resolveDelay) => setTimeout(resolveDelay, 100));
162
+ }
163
+ throw new Error(`ngrok tunnel did not provide a public URL within ${Math.round(timeoutMs / 1000)} seconds.`);
164
+ }
165
+ export async function startNgrokTunnel(port, options = {}) {
166
+ const executable = options.executable ?? await resolveNgrokExecutable();
167
+ const expectedUrl = normalizeNgrokUrl(options.url);
168
+ const spawnEnv = { ...process.env, ...(options.authtoken ? { NGROK_AUTHTOKEN: options.authtoken } : {}) };
169
+ const args = [...(options.executableArgsPrefix ?? []), ...buildNgrokArgs(port, expectedUrl)];
170
+ const timeoutMs = options.timeoutMs ?? (options.detached ? 90_000 : 30_000);
171
+ if (options.detached && options.logPath) {
172
+ await writeFile(options.logPath, "", { mode: 0o600 });
173
+ const logHandle = openSync(options.logPath, "a");
174
+ const child = spawn(executable, args, {
175
+ stdio: ["ignore", logHandle, logHandle],
176
+ windowsHide: true,
177
+ detached: true,
178
+ env: spawnEnv,
179
+ });
180
+ closeSync(logHandle);
181
+ let spawnError;
182
+ child.once("error", (error) => { spawnError = error; });
183
+ try {
184
+ const url = await waitForNgrokUrl(child, () => readFile(options.logPath, "utf8").catch(() => ""), () => spawnError, expectedUrl, timeoutMs);
185
+ child.unref();
186
+ return { process: child, url };
187
+ }
188
+ catch (error) {
189
+ child.kill();
190
+ throw error;
191
+ }
192
+ }
193
+ const child = spawn(executable, args, {
194
+ stdio: ["ignore", "pipe", "pipe"],
195
+ windowsHide: true,
196
+ detached: options.detached,
197
+ env: spawnEnv,
198
+ });
199
+ let spawnError;
200
+ let output = "";
201
+ child.once("error", (error) => { spawnError = error; });
202
+ const append = (chunk) => {
203
+ if (Buffer.byteLength(output, "utf8") <= MAX_STARTUP_OUTPUT_BYTES)
204
+ output += chunk.toString();
205
+ };
206
+ child.stdout?.on("data", append);
207
+ child.stderr?.on("data", append);
208
+ try {
209
+ const url = await waitForNgrokUrl(child, async () => output, () => spawnError, expectedUrl, timeoutMs);
210
+ return { process: child, url };
211
+ }
212
+ catch (error) {
213
+ child.kill();
214
+ throw error;
215
+ }
216
+ finally {
217
+ child.stdout?.off("data", append);
218
+ child.stderr?.off("data", append);
219
+ }
220
+ }
@@ -0,0 +1,186 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { unlink } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ import { atomicWriteJson, getProcessIdentity, isProcessRunning, processIdentityMatches, readJsonFile, } from "../background-lifecycle.js";
5
+ import { startCloudflareTunnel } from "./cloudflare-tunnel.js";
6
+ import { startNgrokTunnel } from "./ngrok-tunnel.js";
7
+ import { tunnelExecutableNamePattern, tunnelProviderLabel, tunnelUrlMatchesProvider, } from "./tunnel-utils.js";
8
+ export { tunnelExecutableNamePattern, tunnelProviderLabel, tunnelUrlMatchesProvider } from "./tunnel-utils.js";
9
+ export function managedTunnelPath(stateDir) {
10
+ return join(stateDir, "tunnel.json");
11
+ }
12
+ export async function startTunnel(provider, port, options = {}) {
13
+ if (provider === "custom" && !options.cloudflareTunnelToken) {
14
+ throw new Error("Custom external URLs are managed outside Auvrynt. Configure a Cloudflare tunnel token to manage it with Auvrynt.");
15
+ }
16
+ if (provider === "ngrok") {
17
+ return startNgrokTunnel(port, {
18
+ detached: options.detached,
19
+ logPath: options.logPath,
20
+ authtoken: options.ngrokAuthtoken,
21
+ url: options.ngrokUrl,
22
+ });
23
+ }
24
+ return startCloudflareTunnel(port, {
25
+ detached: options.detached,
26
+ logPath: options.logPath,
27
+ cloudflareTunnelToken: options.cloudflareTunnelToken,
28
+ publicUrl: options.publicUrl,
29
+ });
30
+ }
31
+ export async function readManagedTunnel(options) {
32
+ const tunnelPath = managedTunnelPath(options.stateDir);
33
+ const record = await readJsonFile(tunnelPath);
34
+ if (!record || !Number.isInteger(record.pid) || record.pid < 1)
35
+ return undefined;
36
+ const recordProvider = record.provider ?? "cloudflare";
37
+ const matchesConfiguration = record.port === options.port
38
+ && recordProvider === options.provider
39
+ && tunnelUrlMatchesProvider(record.url, options.provider, options.ngrokUrl);
40
+ if (!matchesConfiguration)
41
+ return undefined;
42
+ if (processIdentityMatches(record.pid, record))
43
+ return record;
44
+ if (!record.processPath || !record.processStartedAt) {
45
+ const identity = getProcessIdentity(record.pid);
46
+ if (identity && tunnelExecutableNamePattern(options.provider).test(identity.processPath)) {
47
+ const migrated = { ...record, ...identity, provider: options.provider };
48
+ await atomicWriteJson(tunnelPath, migrated);
49
+ return migrated;
50
+ }
51
+ }
52
+ await unlink(tunnelPath).catch(() => undefined);
53
+ return undefined;
54
+ }
55
+ export async function ensureManagedTunnel(options) {
56
+ if (options.provider === "custom" && !options.cloudflareTunnelToken) {
57
+ throw new Error("A Cloudflare tunnel token is required to manage a custom domain from Auvrynt.");
58
+ }
59
+ const existing = await readManagedTunnel(options);
60
+ if (existing) {
61
+ cleanupOrphanedTunnelProcesses(options, existing.pid);
62
+ return { record: existing, created: false };
63
+ }
64
+ await stopManagedTunnel(options);
65
+ const logFileName = options.provider === "ngrok" ? "ngrok.log" : "cloudflared.log";
66
+ const tunnel = await startTunnel(options.provider, options.port, {
67
+ detached: true,
68
+ logPath: join(options.stateDir, logFileName),
69
+ ngrokAuthtoken: options.ngrokAuthtoken,
70
+ ngrokUrl: options.ngrokUrl,
71
+ cloudflareTunnelToken: options.cloudflareTunnelToken,
72
+ publicUrl: options.publicUrl,
73
+ });
74
+ if (!tunnel.process.pid)
75
+ throw new Error(`${tunnelProviderLabel(options.provider)} tunnel started without a process ID.`);
76
+ const identity = getProcessIdentity(tunnel.process.pid);
77
+ if (!identity) {
78
+ tunnel.process.kill();
79
+ throw new Error(`Could not verify the ${tunnelProviderLabel(options.provider)} tunnel process.`);
80
+ }
81
+ const record = {
82
+ pid: tunnel.process.pid,
83
+ url: tunnel.url,
84
+ port: options.port,
85
+ provider: options.provider,
86
+ ...identity,
87
+ };
88
+ await atomicWriteJson(managedTunnelPath(options.stateDir), record);
89
+ return { record, created: true };
90
+ }
91
+ export async function stopManagedTunnel(options) {
92
+ const tunnelPath = managedTunnelPath(options.stateDir);
93
+ const tunnel = await readJsonFile(tunnelPath);
94
+ let stopped = false;
95
+ if (tunnel && Number.isInteger(tunnel.pid) && tunnel.pid > 0) {
96
+ const provider = tunnel.provider ?? "cloudflare";
97
+ if (processIdentityMatches(tunnel.pid, tunnel)) {
98
+ stopTunnelProcess(tunnel.pid, provider);
99
+ stopped = true;
100
+ }
101
+ }
102
+ await unlink(tunnelPath).catch(() => undefined);
103
+ return cleanupOrphanedTunnelProcesses(options) > 0 || stopped;
104
+ }
105
+ export function tunnelCommandMatches(provider, port, commandLine) {
106
+ const escapedPort = String(port).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
107
+ if (provider === "custom")
108
+ return false;
109
+ if (provider === "ngrok") {
110
+ return new RegExp(`ngrok(?:\\.exe)?["']?\\s+http\\s+${escapedPort}(?:\\s|$)`, "i").test(commandLine);
111
+ }
112
+ return /cloudflared(?:\.exe)?["']?\s+tunnel(?:\s|$)/i.test(commandLine)
113
+ && new RegExp(`--url(?:=|\\s+)https?://(?:127\\.0\\.0\\.1|localhost):${escapedPort}(?:\\s|$)`, "i").test(commandLine);
114
+ }
115
+ function cleanupOrphanedTunnelProcesses(options, keepPid) {
116
+ let stopped = 0;
117
+ for (const candidate of listTunnelProcessCandidates(options.provider)) {
118
+ if (candidate.pid === keepPid || !tunnelCommandMatches(options.provider, options.port, candidate.commandLine)) {
119
+ continue;
120
+ }
121
+ const identity = getProcessIdentity(candidate.pid);
122
+ if (!identity || !tunnelExecutableNamePattern(options.provider).test(identity.processPath))
123
+ continue;
124
+ stopTunnelProcess(candidate.pid, options.provider);
125
+ stopped++;
126
+ }
127
+ return stopped;
128
+ }
129
+ function listTunnelProcessCandidates(provider) {
130
+ if (provider === "custom")
131
+ return [];
132
+ try {
133
+ if (process.platform === "win32") {
134
+ const executable = provider === "ngrok" ? "ngrok.exe" : "cloudflared.exe";
135
+ const script = [
136
+ `$items = @(Get-CimInstance Win32_Process -Filter \"Name = '${executable}'\" -ErrorAction Stop`,
137
+ "| ForEach-Object { [pscustomobject]@{ pid = $_.ProcessId; commandLine = [string]$_.CommandLine } })",
138
+ "$items | ConvertTo-Json -Compress",
139
+ ].join(" ; ").replace(/ ; \|/g, " |");
140
+ const raw = execFileSync("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", script], {
141
+ encoding: "utf8",
142
+ stdio: ["ignore", "pipe", "ignore"],
143
+ windowsHide: true,
144
+ }).trim();
145
+ if (!raw)
146
+ return [];
147
+ const parsed = JSON.parse(raw);
148
+ const values = Array.isArray(parsed) ? parsed : [parsed];
149
+ return values.flatMap((value) => {
150
+ if (!value || typeof value !== "object")
151
+ return [];
152
+ const item = value;
153
+ return Number.isInteger(item.pid) && typeof item.commandLine === "string"
154
+ ? [{ pid: item.pid, commandLine: item.commandLine }]
155
+ : [];
156
+ });
157
+ }
158
+ const raw = execFileSync("ps", ["-eo", "pid=,args="], {
159
+ encoding: "utf8",
160
+ stdio: ["ignore", "pipe", "ignore"],
161
+ windowsHide: true,
162
+ });
163
+ return raw.split(/\r?\n/).flatMap((line) => {
164
+ const match = line.trim().match(/^(\d+)\s+(.+)$/);
165
+ return match ? [{ pid: Number(match[1]), commandLine: match[2] }] : [];
166
+ });
167
+ }
168
+ catch {
169
+ return [];
170
+ }
171
+ }
172
+ function stopTunnelProcess(pid, provider) {
173
+ try {
174
+ if (process.platform === "win32") {
175
+ execFileSync("taskkill.exe", ["/PID", String(pid), "/F"], { stdio: "ignore", windowsHide: true });
176
+ }
177
+ else {
178
+ process.kill(pid, "SIGTERM");
179
+ }
180
+ }
181
+ catch {
182
+ if (isProcessRunning(pid)) {
183
+ throw new Error(`Could not stop ${tunnelProviderLabel(provider)} tunnel process ${pid}.`);
184
+ }
185
+ }
186
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,62 @@
1
+ import { execFileSync } from "node:child_process";
2
+ const GENERATED_NGROK_HOST = /(^|\.)ngrok(?:-free)?\.(?:app|dev|io)$/i;
3
+ export function findCommand(command) {
4
+ try {
5
+ return execFileSync(process.platform === "win32" ? "where.exe" : "which", [command], { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"], windowsHide: true }).split(/\r?\n/)[0]?.trim() || undefined;
6
+ }
7
+ catch {
8
+ return undefined;
9
+ }
10
+ }
11
+ export function tunnelProviderLabel(provider) {
12
+ if (provider === "ngrok")
13
+ return "ngrok";
14
+ if (provider === "custom")
15
+ return "Custom external URL";
16
+ return "Cloudflare";
17
+ }
18
+ export function normalizeNgrokUrl(value) {
19
+ const trimmed = value?.trim();
20
+ if (!trimmed)
21
+ return undefined;
22
+ const parsed = new URL(trimmed.includes("://") ? trimmed : `https://${trimmed}`);
23
+ if (parsed.protocol !== "https:")
24
+ throw new Error("ngrok URL must use HTTPS.");
25
+ if (parsed.username || parsed.password)
26
+ throw new Error("ngrok URL must not contain credentials.");
27
+ if (parsed.port)
28
+ throw new Error("ngrok URL must not contain a custom port.");
29
+ if ((parsed.pathname && parsed.pathname !== "/") || parsed.search || parsed.hash) {
30
+ throw new Error("ngrok URL must be an origin without a path, query, or fragment.");
31
+ }
32
+ return parsed.origin;
33
+ }
34
+ export function isGeneratedNgrokUrl(value) {
35
+ try {
36
+ const parsed = new URL(value);
37
+ return parsed.protocol === "https:" && !parsed.username && !parsed.password
38
+ && !parsed.port && (parsed.pathname === "/" || parsed.pathname === "")
39
+ && !parsed.search && !parsed.hash && GENERATED_NGROK_HOST.test(parsed.hostname);
40
+ }
41
+ catch {
42
+ return false;
43
+ }
44
+ }
45
+ export function tunnelUrlMatchesProvider(url, provider, expectedNgrokUrl) {
46
+ if (provider === "ngrok") {
47
+ const expected = normalizeNgrokUrl(expectedNgrokUrl);
48
+ if (expected)
49
+ return url === expected;
50
+ return isGeneratedNgrokUrl(url);
51
+ }
52
+ if (provider === "custom")
53
+ return /^https:\/\//i.test(url);
54
+ return /^https:\/\/[a-zA-Z0-9-]+\.trycloudflare\.com$/.test(url);
55
+ }
56
+ export function tunnelExecutableNamePattern(provider) {
57
+ if (provider === "ngrok")
58
+ return /(^|[\\/])ngrok(?:\.exe)?$/i;
59
+ if (provider === "custom")
60
+ return /$a/;
61
+ return /(^|[\\/])cloudflared(?:\.exe)?$/i;
62
+ }