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,538 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Live tunnel smoke test.
5
+ *
6
+ * This script actually connects to ngrok and/or Cloudflare if those tools
7
+ * are installed on the local machine. It cannot pass without at least one
8
+ * tunnel provider executable available.
9
+ *
10
+ * Use:
11
+ * node scripts/live-tunnel-smoke.mjs
12
+ *
13
+ * Environment:
14
+ * AUVRYNT_LIVE_TUNNEL_PORT port for the local listener (default 49321)
15
+ * AUVRYNT_NGROK_AUTHTOKEN optional, forwarded to ngrok
16
+ * AUVRYNT_NGROK_URL optional stable origin, verified if provided
17
+ */
18
+
19
+ import assert from "node:assert/strict";
20
+ import { execFileSync, spawn } from "node:child_process";
21
+ import { mkdtempSync, openSync, closeSync, rmSync } from "node:fs";
22
+ import { mkdir, readFile, writeFile, unlink } from "node:fs/promises";
23
+ import { createServer } from "node:http";
24
+ import { tmpdir } from "node:os";
25
+ import { join } from "node:path";
26
+
27
+ // ── Reproduce the tunnel-utils helpers inline so the smoke test does not
28
+ // depend on compiled TypeScript output.
29
+
30
+ function findCommand(command) {
31
+ try {
32
+ return execFileSync(
33
+ process.platform === "win32" ? "where.exe" : "which",
34
+ [command],
35
+ { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"], windowsHide: true },
36
+ ).split(/\r?\n/)[0]?.trim() || undefined;
37
+ } catch { return undefined; }
38
+ }
39
+
40
+ function normalizeUrl(value) {
41
+ if (!value?.trim()) return undefined;
42
+ const trimmed = value.trim();
43
+ const parsed = new URL(trimmed.includes("://") ? trimmed : `https://${trimmed}`);
44
+ if (parsed.protocol !== "https:") throw new Error("URL must use HTTPS.");
45
+ if (parsed.username || parsed.password) throw new Error("URL must not contain credentials.");
46
+ if (parsed.port) throw new Error("URL must not contain a custom port.");
47
+ if ((parsed.pathname && parsed.pathname !== "/") || parsed.search || parsed.hash) {
48
+ throw new Error("URL must be an origin without path, query, or fragment.");
49
+ }
50
+ return parsed.origin;
51
+ }
52
+
53
+ function isGeneratedNgrokUrl(value) {
54
+ try {
55
+ const parsed = new URL(value);
56
+ return parsed.protocol === "https:" && !parsed.username && !parsed.password
57
+ && !parsed.port && (parsed.pathname === "/" || parsed.pathname === "")
58
+ && !parsed.search && !parsed.hash
59
+ && /(^|\.)ngrok(?:-free)?\.(?:app|dev|io)$/i.test(parsed.hostname);
60
+ } catch { return false; }
61
+ }
62
+
63
+ function tunnelUrlMatchesProvider(url, provider, expectedNgrokUrl) {
64
+ if (provider === "ngrok") {
65
+ const expected = normalizeUrl(expectedNgrokUrl);
66
+ if (expected) return url === expected;
67
+ return isGeneratedNgrokUrl(url);
68
+ }
69
+ return /^https:\/\/[a-zA-Z0-9-]+\.trycloudflare\.com$/.test(url);
70
+ }
71
+
72
+ // ── Test result counters
73
+
74
+ let passed = 0;
75
+ let failed = 0;
76
+ let skipped = 0;
77
+ const failures = [];
78
+
79
+ function test(name, fn) {
80
+ try {
81
+ fn();
82
+ passed++;
83
+ console.log(` ✓ ${name}`);
84
+ } catch (error) {
85
+ failed++;
86
+ failures.push({ name, error });
87
+ console.error(` ✗ ${name}`);
88
+ console.error(` ${error.message}`);
89
+ }
90
+ }
91
+
92
+ async function testAsync(name, fn) {
93
+ try {
94
+ await fn();
95
+ passed++;
96
+ console.log(` ✓ ${name}`);
97
+ } catch (error) {
98
+ failed++;
99
+ failures.push({ name: `${name} (async)`, error });
100
+ console.error(` ✗ ${name}`);
101
+ console.error(` ${error.message}`);
102
+ }
103
+ }
104
+
105
+ // ── Temporary directories
106
+
107
+ const tempDir = mkdtempSync(join(tmpdir(), "auvrynt-tunnel-smoke-"));
108
+ const stateDir = join(tempDir, "state");
109
+
110
+ function tunnelJsonPath() {
111
+ return join(stateDir, "tunnel.json");
112
+ }
113
+
114
+ // ── Helpers (reproduce the production logic inline)
115
+
116
+ async function readJson(path) {
117
+ try {
118
+ return JSON.parse(await readFile(path, "utf8"));
119
+ } catch { return undefined; }
120
+ }
121
+
122
+ async function writeTunnelRecord(path, record) {
123
+ await writeFile(path, JSON.stringify(record), { mode: 0o600 });
124
+ }
125
+
126
+ function makeTunnelRecord(pid, url, port, provider) {
127
+ return { pid, url, port, provider, processPath: "smoke-test", processStartedAt: new Date().toISOString() };
128
+ }
129
+
130
+ // Wait for a URL to appear in a log file, with timeout
131
+ async function waitForUrlInLog(logPath, checkUrl, timeoutMs, pollMs = 100) {
132
+ const deadline = Date.now() + timeoutMs;
133
+ while (Date.now() < deadline) {
134
+ const output = await readFile(logPath, "utf8").catch(() => "");
135
+ const result = checkUrl(output);
136
+ if (result) return result;
137
+ await new Promise(r => setTimeout(r, pollMs));
138
+ }
139
+ return undefined;
140
+ }
141
+
142
+ // ── Smoke test suite
143
+
144
+ async function main() {
145
+ const PORT = Number(process.env.AUVRYNT_LIVE_TUNNEL_PORT || "49321");
146
+ const EXPECTED_NGROK_URL = normalizeUrl(process.env.AUVRYNT_NGROK_URL);
147
+
148
+ console.log(`\n=== Auvrynt Live Tunnel Smoke Test ===`);
149
+ console.log(`Port: ${PORT}`);
150
+ console.log(`Temp: ${tempDir}`);
151
+ console.log(`Expected ngrok URL: ${EXPECTED_NGROK_URL ?? "(none, use assigned)"}\n`);
152
+
153
+ // ── 1. Provider detection
154
+ console.log(`\n── Provider detection ──`);
155
+
156
+ const ngrokExe = findCommand("ngrok");
157
+ const hasNgrok = Boolean(ngrokExe);
158
+ test("ngrok installed", () => {
159
+ if (!hasNgrok) throw new Error("ngrok not found on PATH. Install from https://ngrok.com/download");
160
+ });
161
+ if (!hasNgrok) { skipped++; console.log(" → ngrok tests will be skipped"); }
162
+
163
+ const cfExe = findCommand("cloudflared");
164
+ const hasCloudflared = Boolean(cfExe);
165
+ test("cloudflared installed", () => {
166
+ if (!hasCloudflared) throw new Error("cloudflared not found on PATH. Install from https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/");
167
+ });
168
+ if (!hasCloudflared) { skipped++; console.log(" → Cloudflare tests will be skipped"); }
169
+
170
+ if (!hasNgrok && !hasCloudflared) {
171
+ console.log("\n⚠ No tunnel provider found. At least one of ngrok or cloudflared must be installed.");
172
+ console.log(" Install one and re-run.");
173
+ process.exitCode = 0;
174
+ console.log(`\nResults: 0 passed, 0 failed, 2 skipped (no tunnel provider)`);
175
+ return;
176
+ }
177
+
178
+ // ── Start a minimal local HTTP server to tunnel to
179
+ const server = createServer((_req, res) => {
180
+ res.writeHead(200, { "content-type": "application/json" });
181
+ res.end(JSON.stringify({ ok: true }));
182
+ });
183
+ await new Promise(resolve => server.listen(PORT, "127.0.0.1", resolve));
184
+ console.log(`\n Local HTTP server listening on 127.0.0.1:${PORT}`);
185
+
186
+ try {
187
+ await mkdir(stateDir, { recursive: true });
188
+
189
+ // ── 2. URL format helpers
190
+ console.log(`\n── URL format helpers ──`);
191
+
192
+ test("normalizeUrl: prepends https", () => {
193
+ assert.equal(normalizeUrl("demo.ngrok.app"), "https://demo.ngrok.app");
194
+ });
195
+
196
+ test("normalizeUrl: strips trailing slash", () => {
197
+ assert.equal(normalizeUrl("https://demo.ngrok.app/"), "https://demo.ngrok.app");
198
+ });
199
+
200
+ test("normalizeUrl: rejects path", () => {
201
+ assert.throws(() => normalizeUrl("https://demo.ngrok.app/path"), /origin/);
202
+ });
203
+
204
+ test("normalizeUrl: rejects HTTP", () => {
205
+ assert.throws(() => normalizeUrl("http://demo.ngrok.app"), /HTTPS/);
206
+ });
207
+
208
+ test("isGeneratedNgrokUrl: recognizes ngrok-free.app", () => {
209
+ assert.equal(isGeneratedNgrokUrl("https://abc123.ngrok-free.app"), true);
210
+ });
211
+
212
+ test("isGeneratedNgrokUrl: recognizes ngrok.app", () => {
213
+ assert.equal(isGeneratedNgrokUrl("https://abc123.ngrok.app"), true);
214
+ });
215
+
216
+ test("isGeneratedNgrokUrl: rejects custom domain", () => {
217
+ assert.equal(isGeneratedNgrokUrl("https://api.example.com"), false);
218
+ });
219
+
220
+ // ── 3. ngrok live tests
221
+ if (hasNgrok) {
222
+ console.log(`\n── ngrok live tunnel ──`);
223
+
224
+ // 3a. Start an assigned (generated) tunnel
225
+ let ngrokChild;
226
+ try {
227
+ const ngrokLog = join(tempDir, "ngrok-assigned.log");
228
+ await writeFile(ngrokLog, "", { mode: 0o600 });
229
+ const logHandle = openSync(ngrokLog, "a");
230
+
231
+ const args = ["http", String(PORT), "--log=stdout", "--log-format=json"];
232
+ const spawnEnv = { ...process.env };
233
+ if (process.env.AUVRYNT_NGROK_AUTHTOKEN) {
234
+ spawnEnv.NGROK_AUTHTOKEN = process.env.AUVRYNT_NGROK_AUTHTOKEN;
235
+ }
236
+
237
+ ngrokChild = spawn(ngrokExe, args, {
238
+ stdio: ["ignore", logHandle, logHandle],
239
+ windowsHide: true,
240
+ env: spawnEnv,
241
+ });
242
+ closeSync(logHandle);
243
+ let ngrokSpawnErr;
244
+ ngrokChild.once("error", (err) => { ngrokSpawnErr = err; });
245
+
246
+ // Wait for URL with 90s timeout
247
+ const ngrokAssignedUrl = await waitForUrlInLog(
248
+ ngrokLog,
249
+ (output) => {
250
+ const candidates = output.match(/https:\/\/[^\s"'\\]+/g) ?? [];
251
+ for (const raw of candidates) {
252
+ const cleaned = raw.replace(/[),.;]+$/, "");
253
+ try {
254
+ const n = normalizeUrl(cleaned);
255
+ if (n && isGeneratedNgrokUrl(n)) return n;
256
+ } catch {}
257
+ }
258
+ return undefined;
259
+ },
260
+ 90_000,
261
+ );
262
+
263
+ if (!ngrokAssignedUrl) throw new Error("ngrok did not provide a generated URL within 90 seconds.");
264
+
265
+ await testAsync("ngrok: assigned URL discovered", async () => {
266
+ assert.ok(ngrokAssignedUrl.startsWith("https://"), `Expected HTTPS URL, got: ${ngrokAssignedUrl}`);
267
+ assert.ok(isGeneratedNgrokUrl(ngrokAssignedUrl), `Expected generated ngrok URL, got: ${ngrokAssignedUrl}`);
268
+ });
269
+
270
+ test("ngrok: URL matches provider", () => {
271
+ assert.ok(tunnelUrlMatchesProvider(ngrokAssignedUrl, "ngrok"));
272
+ });
273
+
274
+ // 3b. Tunnel record persistence
275
+ const recordPath = tunnelJsonPath();
276
+ const record = makeTunnelRecord(ngrokChild.pid, ngrokAssignedUrl, PORT, "ngrok");
277
+ await writeTunnelRecord(recordPath, record);
278
+
279
+ await testAsync("ngrok: tunnel record persisted", async () => {
280
+ const saved = await readJson(recordPath);
281
+ assert.ok(saved, "tunnel.json should exist");
282
+ assert.equal(saved.url, ngrokAssignedUrl);
283
+ assert.equal(saved.port, PORT);
284
+ assert.equal(saved.provider, "ngrok");
285
+ assert.equal(saved.pid, ngrokChild.pid);
286
+ });
287
+
288
+ // 3c. Verify actual HTTP reachability through the tunnel
289
+ await testAsync("ngrok: HTTP reachable through tunnel", async () => {
290
+ const response = await fetch(`${ngrokAssignedUrl}/healthz`, { signal: AbortSignal.timeout(15_000) });
291
+ assert.equal(response.status, 200);
292
+ const body = await response.json();
293
+ assert.ok(body.ok);
294
+ });
295
+
296
+ // 3d. Stop tunnel and verify cleanup
297
+ const killedPid = ngrokChild.pid;
298
+ ngrokChild.kill();
299
+ await new Promise(resolve => ngrokChild.once("exit", resolve));
300
+ ngrokChild = undefined;
301
+
302
+ await testAsync("ngrok: cleanup after kill", async () => {
303
+ try { process.kill(killedPid, 0); throw new Error("process still running"); }
304
+ catch (e) { if (e.code !== "ESRCH") throw e; }
305
+ await unlink(recordPath);
306
+ const gone = await readJson(recordPath);
307
+ assert.equal(gone, undefined);
308
+ });
309
+
310
+ console.log(" → Assigned ngrok tunnel verified.");
311
+ } catch (error) {
312
+ failed++;
313
+ failures.push({ name: "ngrok assigned tunnel", error });
314
+ console.error(` ✗ ngrok assigned tunnel failed: ${error.message}`);
315
+ if (ngrokChild) {
316
+ ngrokChild.kill();
317
+ ngrokChild = undefined;
318
+ }
319
+ }
320
+
321
+ // ── 3e. Stable (reserved) URL test
322
+ if (hasNgrok && EXPECTED_NGROK_URL) {
323
+ let stableChild;
324
+ try {
325
+ const ngrokLog = join(tempDir, "ngrok-stable.log");
326
+ await writeFile(ngrokLog, "", { mode: 0o600 });
327
+ const logHandle = openSync(ngrokLog, "a");
328
+
329
+ const args = ["http", String(PORT), "--log=stdout", "--log-format=json", "--url", EXPECTED_NGROK_URL];
330
+ const spawnEnv = { ...process.env };
331
+ if (process.env.AUVRYNT_NGROK_AUTHTOKEN) {
332
+ spawnEnv.NGROK_AUTHTOKEN = process.env.AUVRYNT_NGROK_AUTHTOKEN;
333
+ }
334
+
335
+ stableChild = spawn(ngrokExe, args, {
336
+ stdio: ["ignore", logHandle, logHandle],
337
+ windowsHide: true,
338
+ env: spawnEnv,
339
+ });
340
+ closeSync(logHandle);
341
+ let stableSpawnErr;
342
+ stableChild.once("error", (err) => { stableSpawnErr = err; });
343
+
344
+ const stableUrl = await waitForUrlInLog(
345
+ ngrokLog,
346
+ (output) => {
347
+ const candidates = output.match(/https:\/\/[^\s"'\\]+/g) ?? [];
348
+ for (const raw of candidates) {
349
+ const cleaned = raw.replace(/[),.;]+$/, "");
350
+ try {
351
+ const n = normalizeUrl(cleaned);
352
+ if (n && n === EXPECTED_NGROK_URL) return n;
353
+ } catch {}
354
+ }
355
+ return undefined;
356
+ },
357
+ 90_000,
358
+ );
359
+
360
+ if (!stableUrl) throw new Error(`ngrok did not provide the stable URL ${EXPECTED_NGROK_URL} within 90 seconds.`);
361
+
362
+ await testAsync("ngrok: stable URL matches expected", async () => {
363
+ assert.equal(stableUrl, EXPECTED_NGROK_URL);
364
+ });
365
+
366
+ await testAsync("ngrok: stable URL HTTP reachable", async () => {
367
+ const response = await fetch(`${stableUrl}/healthz`, { signal: AbortSignal.timeout(15_000) });
368
+ assert.equal(response.status, 200);
369
+ });
370
+
371
+ test("ngrok: stable URL matches provider", () => {
372
+ assert.ok(tunnelUrlMatchesProvider(stableUrl, "ngrok", EXPECTED_NGROK_URL));
373
+ });
374
+
375
+ stableChild.kill();
376
+ await new Promise(resolve => stableChild.once("exit", resolve));
377
+ stableChild = undefined;
378
+ console.log(" → Stable ngrok tunnel verified.");
379
+ } catch (error) {
380
+ failed++;
381
+ failures.push({ name: "ngrok stable URL test", error });
382
+ console.error(` ✗ ngrok stable URL test failed: ${error.message}`);
383
+ if (stableChild) {
384
+ stableChild.kill();
385
+ stableChild = undefined;
386
+ }
387
+ }
388
+ } else if (hasNgrok) {
389
+ skipped++;
390
+ console.log(" → Skipping stable URL test (set AUVRYNT_NGROK_URL to test)");
391
+ }
392
+ }
393
+
394
+ // ── 4. Cloudflare live test
395
+ if (hasCloudflared) {
396
+ console.log(`\n── Cloudflare live tunnel ──`);
397
+
398
+ let cfChild;
399
+ try {
400
+ const cfLog = join(tempDir, "cloudflared.log");
401
+ await writeFile(cfLog, "", { mode: 0o600 });
402
+ const logHandle = openSync(cfLog, "a");
403
+
404
+ const args = ["tunnel", "--no-autoupdate", "--url", `http://127.0.0.1:${PORT}`];
405
+ cfChild = spawn(cfExe, args, {
406
+ stdio: ["ignore", logHandle, logHandle],
407
+ windowsHide: true,
408
+ });
409
+ closeSync(logHandle);
410
+ let cfSpawnErr;
411
+ cfChild.once("error", (err) => { cfSpawnErr = err; });
412
+
413
+ const cfUrl = await waitForUrlInLog(
414
+ cfLog,
415
+ (output) => {
416
+ const match = output.match(/https:\/\/[a-zA-Z0-9-]+\.trycloudflare\.com/);
417
+ return match ? match[0] : undefined;
418
+ },
419
+ 120_000,
420
+ 250,
421
+ );
422
+
423
+ if (!cfUrl) throw new Error("cloudflared did not provide a URL within 120 seconds.");
424
+
425
+ await testAsync("cloudflared: URL discovered", async () => {
426
+ assert.ok(cfUrl.startsWith("https://"), `Expected HTTPS URL, got: ${cfUrl}`);
427
+ assert.ok(cfUrl.includes(".trycloudflare.com"), `Expected trycloudflare.com URL, got: ${cfUrl}`);
428
+ });
429
+
430
+ test("cloudflared: URL matches provider", () => {
431
+ assert.ok(tunnelUrlMatchesProvider(cfUrl, "cloudflare"));
432
+ });
433
+
434
+ // Tunnel record persistence
435
+ const recordPath = tunnelJsonPath();
436
+ const record = makeTunnelRecord(cfChild.pid, cfUrl, PORT, "cloudflare");
437
+ await writeTunnelRecord(recordPath, record);
438
+
439
+ await testAsync("cloudflared: tunnel record persisted", async () => {
440
+ const saved = await readJson(recordPath);
441
+ assert.ok(saved);
442
+ assert.equal(saved.url, cfUrl);
443
+ assert.equal(saved.port, PORT);
444
+ assert.equal(saved.provider, "cloudflare");
445
+ });
446
+
447
+ // HTTP reachability through tunnel
448
+ await testAsync("cloudflared: HTTP reachable through tunnel", async () => {
449
+ const response = await fetch(`${cfUrl}/healthz`, { signal: AbortSignal.timeout(15_000) });
450
+ assert.equal(response.status, 200);
451
+ const body = await response.json();
452
+ assert.ok(body.ok);
453
+ });
454
+
455
+ // Stop and cleanup
456
+ const killedCfPid = cfChild.pid;
457
+ cfChild.kill();
458
+ await new Promise(resolve => cfChild.once("exit", resolve));
459
+ cfChild = undefined;
460
+
461
+ await testAsync("cloudflared: cleanup after kill", async () => {
462
+ try { process.kill(killedCfPid, 0); throw new Error("process still running"); }
463
+ catch (e) { if (e.code !== "ESRCH") throw e; }
464
+ await unlink(recordPath);
465
+ });
466
+
467
+ console.log(" → Cloudflare tunnel verified.");
468
+ } catch (error) {
469
+ failed++;
470
+ failures.push({ name: "Cloudflare tunnel", error });
471
+ console.error(` ✗ Cloudflare tunnel test failed: ${error.message}`);
472
+ if (cfChild) {
473
+ cfChild.kill();
474
+ cfChild = undefined;
475
+ }
476
+ }
477
+ }
478
+
479
+ // ── 5. Tunnel manager simulation
480
+ console.log(`\n── Tunnel manager simulation ──`);
481
+
482
+ test("tunnelUrlMatchesProvider: rejects wrong provider", () => {
483
+ const url = "https://abc123.ngrok-free.app";
484
+ assert.equal(tunnelUrlMatchesProvider(url, "cloudflare"), false);
485
+ });
486
+
487
+ test("tunnelUrlMatchesProvider: accepts correct ngrok", () => {
488
+ const url = "https://abc123.ngrok-free.app";
489
+ assert.equal(tunnelUrlMatchesProvider(url, "ngrok"), true);
490
+ });
491
+
492
+ test("tunnelUrlMatchesProvider: stable URL matching", () => {
493
+ const url = "https://custom.ngrok.app";
494
+ assert.equal(tunnelUrlMatchesProvider(url, "ngrok", "https://custom.ngrok.app"), true);
495
+ });
496
+
497
+ // Simulate read-managed-tunnel behavior
498
+ await testAsync("readManagedTunnel simulation: missing file returns undefined", async () => {
499
+ const data = await readJson(join(tempDir, "nonexistent.json"));
500
+ assert.equal(data, undefined);
501
+ });
502
+
503
+ await testAsync("readManagedTunnel simulation: valid record parsed", async () => {
504
+ const path = join(tempDir, "valid-record.json");
505
+ const record = makeTunnelRecord(99999, "https://test.ngrok-free.app", PORT, "ngrok");
506
+ await writeTunnelRecord(path, record);
507
+ const saved = await readJson(path);
508
+ assert.ok(saved);
509
+ assert.equal(saved.url, "https://test.ngrok-free.app");
510
+ assert.equal(saved.provider, "ngrok");
511
+ await unlink(path);
512
+ });
513
+
514
+ } finally {
515
+ // Cleanup — kill any orphaned child processes and remove temp dir
516
+ server.close();
517
+ rmSync(tempDir, { recursive: true, force: true });
518
+ }
519
+
520
+ // ── Results
521
+ const total = passed + failed + skipped;
522
+ console.log(`\n── Results ──`);
523
+ console.log(` ${passed} passed, ${failed} failed, ${skipped} skipped (${total} total)`);
524
+
525
+ if (failed > 0) {
526
+ console.log(`\nFailures:`);
527
+ for (const f of failures) {
528
+ console.log(` - ${f.name}: ${f.error.message}`);
529
+ }
530
+ process.exitCode = 1;
531
+ }
532
+ console.log(`\n${failed === 0 ? "✓ All tunnel smoke tests passed." : "✗ Some tunnel smoke tests failed."}`);
533
+ }
534
+
535
+ main().catch(error => {
536
+ console.error(`Fatal error: ${error.stack ?? error.message}`);
537
+ process.exitCode = 1;
538
+ });
@@ -0,0 +1,74 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { existsSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
3
+ import { dirname, extname, join, resolve } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+
6
+ const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
7
+ const checkOnly = process.argv.includes("--check") || !process.argv.includes("--fix");
8
+ const binaryExtensions = new Set([
9
+ ".png", ".jpg", ".jpeg", ".gif", ".webp", ".ico",
10
+ ".blend", ".glb", ".wasm", ".sqlite", ".db", ".zip", ".tgz",
11
+ ]);
12
+ const knownNulArtifact = "INFO: Could not find files for the given pattern(s).";
13
+
14
+ const git = spawnSync("git", ["ls-files", "-z"], {
15
+ cwd: root,
16
+ encoding: "utf8",
17
+ windowsHide: true,
18
+ });
19
+ if (git.status !== 0) {
20
+ process.stderr.write(git.stderr || "Could not list tracked files.\n");
21
+ process.exit(2);
22
+ }
23
+
24
+ const trackedFiles = git.stdout.split("\0").filter(Boolean);
25
+ const crlfFiles = [];
26
+
27
+ for (const relativePath of trackedFiles) {
28
+ if (binaryExtensions.has(extname(relativePath).toLowerCase())) continue;
29
+ const absolutePath = join(root, relativePath);
30
+ if (!existsSync(absolutePath)) continue;
31
+
32
+ const buffer = readFileSync(absolutePath);
33
+ if (buffer.includes(0)) continue;
34
+ const text = buffer.toString("utf8");
35
+ if (!text.includes("\r\n")) continue;
36
+
37
+ crlfFiles.push(relativePath);
38
+ if (!checkOnly) writeFileSync(absolutePath, text.replace(/\r\n/g, "\n"), "utf8");
39
+ }
40
+
41
+ let nulArtifact = false;
42
+ let unsafeNulArtifact = false;
43
+ if (process.platform === "win32") {
44
+ const normalPath = join(root, "NUL");
45
+ const extendedPath = `\\\\?\\${normalPath}`;
46
+ if (existsSync(extendedPath)) {
47
+ const content = readFileSync(extendedPath, "utf8").trim();
48
+ if (content === knownNulArtifact) {
49
+ nulArtifact = true;
50
+ if (!checkOnly) unlinkSync(extendedPath);
51
+ } else {
52
+ unsafeNulArtifact = true;
53
+ }
54
+ }
55
+ }
56
+
57
+ if (checkOnly) {
58
+ if (crlfFiles.length > 0) {
59
+ console.error(`CRLF normalization required in ${crlfFiles.length} tracked file(s):`);
60
+ for (const path of crlfFiles.slice(0, 20)) console.error(` ${path}`);
61
+ if (crlfFiles.length > 20) console.error(` ...and ${crlfFiles.length - 20} more`);
62
+ }
63
+ if (nulArtifact) console.error("Known accidental Windows NUL artifact is present at repository root.");
64
+ if (unsafeNulArtifact) console.error("A repository-root NUL file exists but does not match the known disposable artifact; it was not touched.");
65
+ if (crlfFiles.length > 0 || nulArtifact || unsafeNulArtifact) process.exit(1);
66
+ console.log("Repository hygiene check passed.");
67
+ } else {
68
+ console.log(`Normalized ${crlfFiles.length} tracked file(s) to LF.`);
69
+ console.log(nulArtifact ? "Removed the known accidental Windows NUL artifact." : "No known Windows NUL artifact needed removal.");
70
+ if (unsafeNulArtifact) {
71
+ console.warn("A repository-root NUL file exists but did not match the known disposable artifact; it was left untouched.");
72
+ process.exitCode = 1;
73
+ }
74
+ }
@@ -0,0 +1,49 @@
1
+ import { spawn } from "node:child_process";
2
+
3
+ const [, , parentPidText, cliPath, encodedArgs] = process.argv;
4
+ const parentPid = Number(parentPidText);
5
+
6
+ if (!Number.isInteger(parentPid) || parentPid <= 0 || !cliPath || !encodedArgs) {
7
+ process.exitCode = 2;
8
+ } else {
9
+ const originalArgs = JSON.parse(Buffer.from(encodedArgs, "base64url").toString("utf8"));
10
+ if (!Array.isArray(originalArgs) || originalArgs.some((value) => typeof value !== "string")) {
11
+ process.exitCode = 2;
12
+ } else {
13
+ const deadline = Date.now() + 30_000;
14
+ while (Date.now() < deadline && isRunning(parentPid)) {
15
+ await delay(250);
16
+ }
17
+
18
+ if (isRunning(parentPid)) {
19
+ console.error(`[auvrynt] Crash recovery abandoned because process ${parentPid} did not exit.`);
20
+ process.exitCode = 1;
21
+ } else {
22
+ await delay(500);
23
+ const child = spawn(process.execPath, [cliPath, ...originalArgs], {
24
+ cwd: process.cwd(),
25
+ detached: true,
26
+ stdio: ["ignore", "inherit", "inherit"],
27
+ windowsHide: true,
28
+ env: process.env,
29
+ });
30
+ child.once("error", (error) => {
31
+ console.error(`[auvrynt] Crash recovery restart failed: ${error.message}`);
32
+ });
33
+ child.unref();
34
+ }
35
+ }
36
+ }
37
+
38
+ function isRunning(pid) {
39
+ try {
40
+ process.kill(pid, 0);
41
+ return true;
42
+ } catch {
43
+ return false;
44
+ }
45
+ }
46
+
47
+ function delay(ms) {
48
+ return new Promise((resolve) => setTimeout(resolve, ms));
49
+ }