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,516 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { mkdir, writeFile } from "node:fs/promises";
3
+ import { dirname, relative } from "node:path";
4
+ import { loadPlaywright } from "./playwright-runtime.js";
5
+ import { closeBrowserWithDeadline, settleWithin, shouldEmbedScreenshot, } from "./browser-stability.js";
6
+ import { assertSafeWebUrl, validateWebUrl } from "./web-tools.js";
7
+ const MAX_SESSIONS = 4;
8
+ const SESSION_TTL_MS = 15 * 60_000;
9
+ const MAX_DIAGNOSTICS = 100;
10
+ const MAX_INLINE_SCREENSHOT_BYTES = 512 * 1024;
11
+ const DEFAULT_TIMEOUT_MS = 15_000;
12
+ const CLOSE_CTX_MS = 3_000;
13
+ const CLOSE_BR_MS = 8_000;
14
+ const LAUNCH_OPTIONS = {
15
+ headless: true,
16
+ args: ["--disable-gpu", "--disable-breakpad", "--disable-crash-reporter", "--noerrdialogs"],
17
+ ...(process.platform === "win32" ? { channel: "chromium" } : {}),
18
+ };
19
+ const sessions = new Map();
20
+ function textResult(payload, isError = false) {
21
+ return {
22
+ content: [{ type: "text", text: typeof payload === "string" ? payload : JSON.stringify(payload, null, 2) }],
23
+ ...(isError ? { isError: true } : {}),
24
+ };
25
+ }
26
+ function inlineScreenshot(buffer, label) {
27
+ if (shouldEmbedScreenshot(buffer.length, 0, MAX_INLINE_SCREENSHOT_BYTES, MAX_INLINE_SCREENSHOT_BYTES)) {
28
+ return [{ type: "image", data: buffer.toString("base64"), mimeType: "image/png" }];
29
+ }
30
+ return [{
31
+ type: "text",
32
+ text: `${label} was saved, but its ${buffer.length}-byte PNG was not embedded because it exceeded the stable MCP inline-image limit.`,
33
+ }];
34
+ }
35
+ async function destroySession(sessionId) {
36
+ const session = sessions.get(sessionId);
37
+ if (!session)
38
+ return;
39
+ sessions.delete(sessionId);
40
+ await settleWithin(() => session.context.close(), CLOSE_CTX_MS);
41
+ await closeBrowserWithDeadline(session.browser, CLOSE_BR_MS);
42
+ }
43
+ function pruneExpiredSessions() {
44
+ const now = Date.now();
45
+ for (const [id, session] of sessions) {
46
+ if (now - session.lastUsedAt > SESSION_TTL_MS)
47
+ void destroySession(id);
48
+ }
49
+ }
50
+ function getSession(sessionId) {
51
+ pruneExpiredSessions();
52
+ const session = sessions.get(sessionId);
53
+ if (!session)
54
+ throw new Error(`Unknown browser session: ${sessionId}. Open one with browser_open first.`);
55
+ session.lastUsedAt = Date.now();
56
+ return session;
57
+ }
58
+ function isLocalHost(hostname) {
59
+ const host = hostname.toLowerCase();
60
+ return host === "localhost" || host.endsWith(".localhost") || host === "0.0.0.0" || host === "::1" || host.startsWith("127.");
61
+ }
62
+ async function installGuard(context, initialUrl, blocked, allowLoopback) {
63
+ await context.route("**/*", async (route) => {
64
+ const requestUrl = route.request().url();
65
+ try {
66
+ const protocol = new URL(requestUrl).protocol;
67
+ if (["data:", "blob:", "about:"].includes(protocol)) {
68
+ await route.continue();
69
+ return;
70
+ }
71
+ await assertSafeWebUrl(requestUrl, allowLoopback);
72
+ await route.continue();
73
+ }
74
+ catch (error) {
75
+ if (blocked.length < MAX_DIAGNOSTICS) {
76
+ blocked.push(`${requestUrl} (${error instanceof Error ? error.message : String(error)})`);
77
+ }
78
+ await route.abort("blockedbyclient");
79
+ }
80
+ });
81
+ await context.routeWebSocket("**/*", async (ws) => {
82
+ const socketUrl = ws.url();
83
+ try {
84
+ await assertSafeWebUrl(socketUrl.replace(/^ws/, "http"), allowLoopback);
85
+ ws.connectToServer();
86
+ }
87
+ catch (error) {
88
+ if (blocked.length < MAX_DIAGNOSTICS) {
89
+ blocked.push(`${socketUrl} (${error instanceof Error ? error.message : String(error)})`);
90
+ }
91
+ await ws.close({ code: 1008, reason: "Blocked by Auvrynt network policy" });
92
+ }
93
+ });
94
+ if (!initialUrl)
95
+ return undefined;
96
+ return assertSafeWebUrl(initialUrl, allowLoopback);
97
+ }
98
+ function attachDiagnostics(session) {
99
+ session.page.on("console", (msg) => {
100
+ if (session.consoleLogs.length < MAX_DIAGNOSTICS) {
101
+ session.consoleLogs.push({ type: msg.type(), text: msg.text(), at: Date.now() });
102
+ }
103
+ });
104
+ session.page.on("request", (req) => {
105
+ if (session.network.length < MAX_DIAGNOSTICS) {
106
+ session.network.push({
107
+ method: req.method(),
108
+ url: req.url(),
109
+ resourceType: req.resourceType(),
110
+ at: Date.now(),
111
+ });
112
+ }
113
+ });
114
+ session.page.on("response", (res) => {
115
+ const entry = session.network.find((item) => item.url === res.url() && item.status === undefined);
116
+ if (entry)
117
+ entry.status = res.status();
118
+ });
119
+ session.page.on("requestfailed", (req) => {
120
+ const entry = session.network.find((item) => item.url === req.url() && !item.failed);
121
+ if (entry)
122
+ entry.failed = req.failure()?.errorText ?? "failed";
123
+ });
124
+ }
125
+ export async function browserOpen(registry, input) {
126
+ registry.getWorkspace(input.workspaceId);
127
+ pruneExpiredSessions();
128
+ if (sessions.size >= MAX_SESSIONS) {
129
+ return textResult(`Browser session capacity reached (max ${MAX_SESSIONS}). Close an existing session with browser_close.`, true);
130
+ }
131
+ let playwright;
132
+ try {
133
+ playwright = await loadPlaywright();
134
+ }
135
+ catch (error) {
136
+ return textResult(`Playwright browser support is unavailable: ${error instanceof Error ? error.message : String(error)}. Run 'auvrynt start' to repair it automatically.`, true);
137
+ }
138
+ const width = Math.min(Math.max(input.viewportWidth ?? 1280, 320), 3840);
139
+ const height = Math.min(Math.max(input.viewportHeight ?? 800, 240), 2160);
140
+ let browser;
141
+ let context;
142
+ try {
143
+ const validated = input.url ? validateWebUrl(input.url) : undefined;
144
+ const allowLoopback = validated ? isLocalHost(new URL(validated).hostname) : true;
145
+ browser = await playwright.chromium.launch(LAUNCH_OPTIONS);
146
+ context = await browser.newContext({
147
+ viewport: { width, height },
148
+ serviceWorkers: "block",
149
+ ...(input.userAgent ? { userAgent: input.userAgent } : {}),
150
+ });
151
+ const blockedRequests = [];
152
+ const safeUrl = await installGuard(context, validated, blockedRequests, allowLoopback);
153
+ const page = await context.newPage();
154
+ const session = {
155
+ id: randomUUID(),
156
+ workspaceId: input.workspaceId,
157
+ browser: browser,
158
+ context,
159
+ page,
160
+ createdAt: Date.now(),
161
+ lastUsedAt: Date.now(),
162
+ allowLoopback,
163
+ blockedRequests,
164
+ consoleLogs: [],
165
+ network: [],
166
+ };
167
+ attachDiagnostics(session);
168
+ if (safeUrl)
169
+ await page.goto(safeUrl, { waitUntil: "domcontentloaded", timeout: DEFAULT_TIMEOUT_MS });
170
+ sessions.set(session.id, session);
171
+ return textResult({
172
+ sessionId: session.id,
173
+ url: page.url(),
174
+ title: await page.title(),
175
+ viewport: { width, height },
176
+ blockedRequests,
177
+ });
178
+ }
179
+ catch (error) {
180
+ if (context)
181
+ await settleWithin(() => context.close(), CLOSE_CTX_MS);
182
+ if (browser)
183
+ await closeBrowserWithDeadline(browser, CLOSE_BR_MS);
184
+ return textResult(`browser_open failed: ${error instanceof Error ? error.message : String(error)}`, true);
185
+ }
186
+ }
187
+ export async function browserClose(input) {
188
+ if (!sessions.has(input.sessionId)) {
189
+ return textResult({ closed: false, reason: "Session not found or already closed." });
190
+ }
191
+ await destroySession(input.sessionId);
192
+ return textResult({ closed: true, sessionId: input.sessionId });
193
+ }
194
+ export async function browserListSessions(input) {
195
+ pruneExpiredSessions();
196
+ const items = Array.from(sessions.values())
197
+ .filter((s) => !input.workspaceId || s.workspaceId === input.workspaceId)
198
+ .map((s) => ({
199
+ sessionId: s.id,
200
+ workspaceId: s.workspaceId,
201
+ url: s.page.url(),
202
+ createdAt: s.createdAt,
203
+ lastUsedAt: s.lastUsedAt,
204
+ }));
205
+ return textResult({ sessions: items, count: items.length });
206
+ }
207
+ export async function browserNavigate(input) {
208
+ try {
209
+ const session = getSession(input.sessionId);
210
+ const safeUrl = await assertSafeWebUrl(input.url, session.allowLoopback);
211
+ await session.page.goto(safeUrl, {
212
+ waitUntil: input.waitUntil ?? "domcontentloaded",
213
+ timeout: DEFAULT_TIMEOUT_MS,
214
+ });
215
+ return textResult({ sessionId: session.id, url: session.page.url(), title: await session.page.title() });
216
+ }
217
+ catch (error) {
218
+ return textResult(`browser_navigate failed: ${error instanceof Error ? error.message : String(error)}`, true);
219
+ }
220
+ }
221
+ export async function browserReload(input) {
222
+ try {
223
+ const session = getSession(input.sessionId);
224
+ await session.page.reload({ waitUntil: "domcontentloaded", timeout: DEFAULT_TIMEOUT_MS });
225
+ return textResult({ sessionId: session.id, url: session.page.url(), title: await session.page.title() });
226
+ }
227
+ catch (error) {
228
+ return textResult(`browser_reload failed: ${error instanceof Error ? error.message : String(error)}`, true);
229
+ }
230
+ }
231
+ export async function browserGoBack(input) {
232
+ try {
233
+ const session = getSession(input.sessionId);
234
+ await session.page.goBack({ waitUntil: "domcontentloaded", timeout: DEFAULT_TIMEOUT_MS });
235
+ return textResult({ sessionId: session.id, url: session.page.url(), title: await session.page.title() });
236
+ }
237
+ catch (error) {
238
+ return textResult(`browser_go_back failed: ${error instanceof Error ? error.message : String(error)}`, true);
239
+ }
240
+ }
241
+ export async function browserGoForward(input) {
242
+ try {
243
+ const session = getSession(input.sessionId);
244
+ await session.page.goForward({ waitUntil: "domcontentloaded", timeout: DEFAULT_TIMEOUT_MS });
245
+ return textResult({ sessionId: session.id, url: session.page.url(), title: await session.page.title() });
246
+ }
247
+ catch (error) {
248
+ return textResult(`browser_go_forward failed: ${error instanceof Error ? error.message : String(error)}`, true);
249
+ }
250
+ }
251
+ export async function browserSnapshot(input) {
252
+ try {
253
+ const session = getSession(input.sessionId);
254
+ const maxChars = Math.min(Math.max(input.maxChars ?? 12_000, 500), 50_000);
255
+ let accessibility = null;
256
+ if (session.page.accessibility?.snapshot) {
257
+ accessibility = await session.page.accessibility.snapshot({ interestingOnly: input.interestingOnly ?? true });
258
+ }
259
+ const summary = await session.page.evaluate(() => {
260
+ const pick = (selector, limit = 20) => Array.from(document.querySelectorAll(selector)).slice(0, limit).map((el) => {
261
+ const text = (el.textContent || "").trim().replace(/\s+/g, " ").slice(0, 120);
262
+ return {
263
+ tag: el.tagName.toLowerCase(),
264
+ id: el.id || undefined,
265
+ name: el.getAttribute("name") || undefined,
266
+ type: el.getAttribute("type") || undefined,
267
+ href: el.getAttribute("href") || undefined,
268
+ role: el.getAttribute("role") || undefined,
269
+ text: text || undefined,
270
+ };
271
+ });
272
+ return {
273
+ title: document.title,
274
+ url: location.href,
275
+ headings: pick("h1,h2,h3,h4"),
276
+ buttons: pick("button,[role='button'],input[type='button'],input[type='submit']"),
277
+ links: pick("a[href]"),
278
+ inputs: pick("input,textarea,select"),
279
+ };
280
+ });
281
+ let text = JSON.stringify({ sessionId: session.id, summary, accessibility }, null, 2);
282
+ if (text.length > maxChars)
283
+ text = `${text.slice(0, maxChars)}\n…truncated`;
284
+ return textResult(text);
285
+ }
286
+ catch (error) {
287
+ return textResult(`browser_snapshot failed: ${error instanceof Error ? error.message : String(error)}`, true);
288
+ }
289
+ }
290
+ export async function browserClick(input) {
291
+ try {
292
+ const session = getSession(input.sessionId);
293
+ await session.page.locator(input.selector).click({
294
+ timeout: Math.min(input.timeoutMs ?? DEFAULT_TIMEOUT_MS, 60_000),
295
+ button: input.button,
296
+ clickCount: input.clickCount,
297
+ });
298
+ return textResult({ sessionId: session.id, clicked: input.selector, url: session.page.url() });
299
+ }
300
+ catch (error) {
301
+ return textResult(`browser_click failed: ${error instanceof Error ? error.message : String(error)}`, true);
302
+ }
303
+ }
304
+ export async function browserType(input) {
305
+ try {
306
+ const session = getSession(input.sessionId);
307
+ const locator = session.page.locator(input.selector);
308
+ const timeout = Math.min(input.timeoutMs ?? DEFAULT_TIMEOUT_MS, 60_000);
309
+ if (input.clear ?? true)
310
+ await locator.fill(input.text, { timeout });
311
+ else
312
+ await locator.type(input.text, { timeout, delay: Math.min(input.delayMs ?? 0, 200) });
313
+ return textResult({ sessionId: session.id, typed: true, selector: input.selector });
314
+ }
315
+ catch (error) {
316
+ return textResult(`browser_type failed: ${error instanceof Error ? error.message : String(error)}`, true);
317
+ }
318
+ }
319
+ export async function browserSelectOption(input) {
320
+ try {
321
+ const session = getSession(input.sessionId);
322
+ const selected = await session.page.locator(input.selector).selectOption(input.values, {
323
+ timeout: Math.min(input.timeoutMs ?? DEFAULT_TIMEOUT_MS, 60_000),
324
+ });
325
+ return textResult({ sessionId: session.id, selected });
326
+ }
327
+ catch (error) {
328
+ return textResult(`browser_select_option failed: ${error instanceof Error ? error.message : String(error)}`, true);
329
+ }
330
+ }
331
+ export async function browserHover(input) {
332
+ try {
333
+ const session = getSession(input.sessionId);
334
+ await session.page.locator(input.selector).hover({
335
+ timeout: Math.min(input.timeoutMs ?? DEFAULT_TIMEOUT_MS, 60_000),
336
+ });
337
+ return textResult({ sessionId: session.id, hovered: input.selector });
338
+ }
339
+ catch (error) {
340
+ return textResult(`browser_hover failed: ${error instanceof Error ? error.message : String(error)}`, true);
341
+ }
342
+ }
343
+ export async function browserPressKey(input) {
344
+ try {
345
+ const session = getSession(input.sessionId);
346
+ if (input.selector) {
347
+ await session.page.locator(input.selector).press(input.key, {
348
+ timeout: Math.min(input.timeoutMs ?? DEFAULT_TIMEOUT_MS, 60_000),
349
+ });
350
+ }
351
+ else {
352
+ await session.page.keyboard.press(input.key);
353
+ }
354
+ return textResult({ sessionId: session.id, key: input.key, selector: input.selector ?? null });
355
+ }
356
+ catch (error) {
357
+ return textResult(`browser_press_key failed: ${error instanceof Error ? error.message : String(error)}`, true);
358
+ }
359
+ }
360
+ export async function browserWaitFor(input) {
361
+ try {
362
+ const session = getSession(input.sessionId);
363
+ const timeout = Math.min(input.timeoutMs ?? DEFAULT_TIMEOUT_MS, 60_000);
364
+ if (input.selector) {
365
+ await session.page.locator(input.selector).waitFor({ state: input.state ?? "visible", timeout });
366
+ }
367
+ else if (input.url) {
368
+ await session.page.waitForURL(input.url, { timeout });
369
+ }
370
+ else if (input.loadState) {
371
+ await session.page.waitForLoadState(input.loadState, { timeout });
372
+ }
373
+ else {
374
+ await session.page.waitForTimeout(Math.min(timeout, 5_000));
375
+ }
376
+ return textResult({ sessionId: session.id, waited: true, url: session.page.url() });
377
+ }
378
+ catch (error) {
379
+ return textResult(`browser_wait_for failed: ${error instanceof Error ? error.message : String(error)}`, true);
380
+ }
381
+ }
382
+ export async function browserGetText(input) {
383
+ try {
384
+ const session = getSession(input.sessionId);
385
+ const text = await session.page.locator(input.selector).textContent({
386
+ timeout: Math.min(input.timeoutMs ?? DEFAULT_TIMEOUT_MS, 60_000),
387
+ });
388
+ return textResult({ sessionId: session.id, selector: input.selector, text: text ?? "" });
389
+ }
390
+ catch (error) {
391
+ return textResult(`browser_get_text failed: ${error instanceof Error ? error.message : String(error)}`, true);
392
+ }
393
+ }
394
+ export async function browserGetAttribute(input) {
395
+ try {
396
+ const session = getSession(input.sessionId);
397
+ const value = await session.page.locator(input.selector).getAttribute(input.name, {
398
+ timeout: Math.min(input.timeoutMs ?? DEFAULT_TIMEOUT_MS, 60_000),
399
+ });
400
+ return textResult({ sessionId: session.id, selector: input.selector, name: input.name, value });
401
+ }
402
+ catch (error) {
403
+ return textResult(`browser_get_attribute failed: ${error instanceof Error ? error.message : String(error)}`, true);
404
+ }
405
+ }
406
+ export async function browserIsVisible(input) {
407
+ try {
408
+ const session = getSession(input.sessionId);
409
+ const visible = await session.page.locator(input.selector).isVisible({
410
+ timeout: Math.min(input.timeoutMs ?? 2_000, 30_000),
411
+ });
412
+ return textResult({ sessionId: session.id, selector: input.selector, visible });
413
+ }
414
+ catch (error) {
415
+ return textResult({
416
+ sessionId: input.sessionId,
417
+ selector: input.selector,
418
+ visible: false,
419
+ error: error instanceof Error ? error.message : String(error),
420
+ });
421
+ }
422
+ }
423
+ export async function browserScroll(input) {
424
+ try {
425
+ const session = getSession(input.sessionId);
426
+ if (input.selector)
427
+ await session.page.locator(input.selector).scrollIntoViewIfNeeded();
428
+ else
429
+ await session.page.mouse.wheel(input.deltaX ?? 0, input.deltaY ?? 600);
430
+ return textResult({ sessionId: session.id, scrolled: true });
431
+ }
432
+ catch (error) {
433
+ return textResult(`browser_scroll failed: ${error instanceof Error ? error.message : String(error)}`, true);
434
+ }
435
+ }
436
+ export async function browserConsole(input) {
437
+ try {
438
+ const session = getSession(input.sessionId);
439
+ const types = input.types?.map((t) => t.toLowerCase());
440
+ const logs = session.consoleLogs.filter((entry) => !types || types.includes(entry.type));
441
+ if (input.clear)
442
+ session.consoleLogs.length = 0;
443
+ return textResult({ sessionId: session.id, logs, count: logs.length });
444
+ }
445
+ catch (error) {
446
+ return textResult(`browser_console failed: ${error instanceof Error ? error.message : String(error)}`, true);
447
+ }
448
+ }
449
+ export async function browserNetwork(input) {
450
+ try {
451
+ const session = getSession(input.sessionId);
452
+ let requests = session.network.slice();
453
+ if (input.onlyFailed) {
454
+ requests = requests.filter((entry) => entry.failed || (entry.status !== undefined && entry.status >= 400));
455
+ }
456
+ if (input.clear)
457
+ session.network.length = 0;
458
+ return textResult({
459
+ sessionId: session.id,
460
+ requests,
461
+ blockedRequests: session.blockedRequests.slice(),
462
+ count: requests.length,
463
+ });
464
+ }
465
+ catch (error) {
466
+ return textResult(`browser_network failed: ${error instanceof Error ? error.message : String(error)}`, true);
467
+ }
468
+ }
469
+ export async function browserEvaluate(input) {
470
+ try {
471
+ const session = getSession(input.sessionId);
472
+ const expression = input.expression.trim();
473
+ if (!expression)
474
+ return textResult("browser_evaluate requires a non-empty expression.", true);
475
+ if (/\b(fetch|XMLHttpRequest|WebSocket|import\s*\(|require\s*\()/i.test(expression)) {
476
+ return textResult("browser_evaluate blocked network/module side effects in expression.", true);
477
+ }
478
+ if (expression.length > 4_000)
479
+ return textResult("browser_evaluate expression too long (max 4000 chars).", true);
480
+ const result = await session.page.evaluate((expr) => {
481
+ const fn = new Function(`"use strict"; return (${expr});`);
482
+ return fn();
483
+ }, expression);
484
+ return textResult({ sessionId: session.id, result });
485
+ }
486
+ catch (error) {
487
+ return textResult(`browser_evaluate failed: ${error instanceof Error ? error.message : String(error)}`, true);
488
+ }
489
+ }
490
+ export async function browserScreenshot(registry, input) {
491
+ try {
492
+ const session = getSession(input.sessionId);
493
+ const workspace = registry.getWorkspace(session.workspaceId);
494
+ const absoluteOutputPath = registry.resolveArtifactPath(workspace, input.outputPath, "playwright");
495
+ await mkdir(dirname(absoluteOutputPath), { recursive: true });
496
+ const buffer = await session.page.screenshot({ fullPage: input.fullPage ?? false, type: "png" });
497
+ await writeFile(absoluteOutputPath, buffer);
498
+ const relPath = relative(workspace.root, absoluteOutputPath).replace(/\\/g, "/");
499
+ return {
500
+ content: [
501
+ ...inlineScreenshot(buffer, `Screenshot ${relPath}`),
502
+ {
503
+ type: "text",
504
+ text: JSON.stringify({ sessionId: session.id, path: relPath, url: session.page.url() }, null, 2),
505
+ },
506
+ ],
507
+ };
508
+ }
509
+ catch (error) {
510
+ return textResult(`browser_screenshot failed: ${error instanceof Error ? error.message : String(error)}`, true);
511
+ }
512
+ }
513
+ export function browserSessionCount() {
514
+ pruneExpiredSessions();
515
+ return sessions.size;
516
+ }
@@ -0,0 +1,36 @@
1
+ export async function settleWithin(action, timeoutMs) {
2
+ let timer;
3
+ try {
4
+ return await Promise.race([
5
+ action().then(() => true, () => false),
6
+ new Promise((resolve) => {
7
+ timer = setTimeout(() => resolve(false), timeoutMs);
8
+ }),
9
+ ]);
10
+ }
11
+ finally {
12
+ if (timer)
13
+ clearTimeout(timer);
14
+ }
15
+ }
16
+ export async function closeBrowserWithDeadline(browser, timeoutMs) {
17
+ if (!browser)
18
+ return { closed: true, forceKilled: false };
19
+ const closed = await settleWithin(() => browser.close(), timeoutMs);
20
+ if (closed)
21
+ return { closed: true, forceKilled: false };
22
+ let forceKilled = false;
23
+ try {
24
+ forceKilled = browser.process?.()?.kill("SIGKILL") ?? false;
25
+ }
26
+ catch {
27
+ forceKilled = false;
28
+ }
29
+ return { closed: false, forceKilled };
30
+ }
31
+ export function shouldEmbedScreenshot(bytes, alreadyEmbeddedBytes, perImageLimitBytes, totalLimitBytes) {
32
+ return Number.isFinite(bytes)
33
+ && bytes >= 0
34
+ && bytes <= perImageLimitBytes
35
+ && alreadyEmbeddedBytes + bytes <= totalLimitBytes;
36
+ }
@@ -0,0 +1,105 @@
1
+ import { createRequire } from "node:module";
2
+ import { existsSync, mkdirSync } from "node:fs";
3
+ import { homedir } from "node:os";
4
+ import { dirname, join } from "node:path";
5
+ import { pathToFileURL } from "node:url";
6
+ import { execFileSync } from "node:child_process";
7
+ const localRequire = createRequire(import.meta.url);
8
+ const PLAYWRIGHT_VERSION = "1.62.0";
9
+ const MANAGED_ROOT = join(homedir(), ".auvrynt", "browser-support");
10
+ const managedRequire = createRequire(join(MANAGED_ROOT, "package.json"));
11
+ function resolvePlaywrightModule() {
12
+ try {
13
+ return { path: localRequire.resolve("playwright"), source: "package" };
14
+ }
15
+ catch { }
16
+ try {
17
+ return { path: managedRequire.resolve("playwright"), source: "managed" };
18
+ }
19
+ catch { }
20
+ return undefined;
21
+ }
22
+ function resolveNpmCli() {
23
+ const candidates = [
24
+ process.env.npm_execpath,
25
+ join(dirname(process.execPath), "node_modules", "npm", "bin", "npm-cli.js"),
26
+ ].filter((candidate) => Boolean(candidate));
27
+ const npmCli = candidates.find((candidate) => existsSync(candidate));
28
+ if (!npmCli) {
29
+ throw new Error("npm-cli.js was not found beside Node.js. Reinstall Node.js with npm included.");
30
+ }
31
+ return npmCli;
32
+ }
33
+ export function getPlaywrightRuntimeStatus() {
34
+ const resolved = resolvePlaywrightModule();
35
+ if (!resolved) {
36
+ return { packageInstalled: false, chromiumInstalled: false };
37
+ }
38
+ try {
39
+ const playwright = resolved.source === "package"
40
+ ? localRequire("playwright")
41
+ : managedRequire("playwright");
42
+ const chromiumExecutablePath = playwright?.chromium?.executablePath?.();
43
+ return {
44
+ packageInstalled: true,
45
+ chromiumInstalled: Boolean(chromiumExecutablePath && existsSync(chromiumExecutablePath)),
46
+ modulePath: resolved.path,
47
+ chromiumExecutablePath,
48
+ source: resolved.source,
49
+ };
50
+ }
51
+ catch {
52
+ return {
53
+ packageInstalled: true,
54
+ chromiumInstalled: false,
55
+ modulePath: resolved.path,
56
+ source: resolved.source,
57
+ };
58
+ }
59
+ }
60
+ export async function loadPlaywright() {
61
+ const resolved = resolvePlaywrightModule();
62
+ if (!resolved) {
63
+ throw new Error("Playwright is not installed.");
64
+ }
65
+ return normalizePlaywrightModule(await import(pathToFileURL(resolved.path).href));
66
+ }
67
+ export function normalizePlaywrightModule(imported) {
68
+ const playwright = imported?.chromium ? imported : imported?.default;
69
+ if (!playwright?.chromium?.launch) {
70
+ throw new Error("Playwright loaded, but its Chromium launcher is unavailable.");
71
+ }
72
+ return playwright;
73
+ }
74
+ export function ensurePlaywrightRuntime() {
75
+ let status = getPlaywrightRuntimeStatus();
76
+ if (!status.packageInstalled) {
77
+ mkdirSync(MANAGED_ROOT, { recursive: true });
78
+ execFileSync(process.execPath, [
79
+ resolveNpmCli(),
80
+ "install",
81
+ "--prefix",
82
+ MANAGED_ROOT,
83
+ "--no-save",
84
+ "--package-lock=false",
85
+ "--ignore-scripts",
86
+ `playwright@${PLAYWRIGHT_VERSION}`,
87
+ ], { stdio: "inherit", windowsHide: true });
88
+ status = getPlaywrightRuntimeStatus();
89
+ }
90
+ if (!status.packageInstalled || !status.modulePath) {
91
+ throw new Error("Playwright package installation completed, but the package could not be resolved.");
92
+ }
93
+ if (!status.chromiumInstalled) {
94
+ const cliPath = join(dirname(status.modulePath), "cli.js");
95
+ if (!existsSync(cliPath)) {
96
+ throw new Error(`Playwright CLI was not found at ${cliPath}.`);
97
+ }
98
+ execFileSync(process.execPath, [cliPath, "install", "chromium"], { stdio: "inherit", windowsHide: true });
99
+ status = getPlaywrightRuntimeStatus();
100
+ }
101
+ if (!status.chromiumInstalled) {
102
+ throw new Error("Playwright Chromium installation completed, but Chromium is still unavailable.");
103
+ }
104
+ return status;
105
+ }