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
@@ -1,377 +1 @@
1
- import { timingSafeEqual, randomBytes, randomUUID, createHash } from "node:crypto";
2
- import { AccessDeniedError, InvalidGrantError, InvalidRequestError, InvalidTokenError } from "@modelcontextprotocol/sdk/server/auth/errors.js";
3
- import { checkResourceAllowed, resourceUrlFromServerUrl } from "@modelcontextprotocol/sdk/shared/auth-utils.js";
4
- const CODE_TTL_MS = 5 * 60 * 1000;
5
- function randomToken() {
6
- return randomBytes(32).toString("base64url");
7
- }
8
- function safeEquals(a, b) {
9
- const left = Buffer.from(a);
10
- const right = Buffer.from(b);
11
- if (left.byteLength !== right.byteLength)
12
- return false;
13
- return timingSafeEqual(left, right);
14
- }
15
- function htmlEscape(value) {
16
- return value
17
- .replaceAll("&", "&")
18
- .replaceAll("<", "&lt;")
19
- .replaceAll(">", "&gt;")
20
- .replaceAll('"', "&quot;")
21
- .replaceAll("'", "&#39;");
22
- }
23
- function formHtml(params) {
24
- const scopeDescriptions = {
25
- "auvrynt:read": "Inspect files, search, and perform read-only project analysis",
26
- "auvrynt:write": "Edit and create files",
27
- "auvrynt:process": "Start and stop approved workspace processes",
28
- "auvrynt:web": "Use browser and web-development tools",
29
- "auvrynt:software": "Use software and .NET tools",
30
- "auvrynt:godot": "Use Godot project tools",
31
- "auvrynt:blender": "Use Blender 3D tools",
32
- "auvrynt:serena": "Use local Serena semantic code tools",
33
- };
34
- const scopeItems = params.scopes.length > 0
35
- ? params.scopes.map((s) => {
36
- const desc = scopeDescriptions[s];
37
- return `<li><strong>${htmlEscape(s)}</strong>${desc ? ` <span>${htmlEscape(desc)}</span>` : ""}</li>`;
38
- }).join("\n ")
39
- : "<li><strong>auvrynt</strong><span>General access</span></li>";
40
- const resourceText = params.resource?.href ?? "Auvrynt Webkit Arsenal endpoint";
41
- const error = params.error
42
- ? `<output role="alert" class="error">${htmlEscape(params.error)}</output>`
43
- : "";
44
- const hiddenFields = Object.entries(params.fields)
45
- .filter((entry) => entry[1] !== undefined)
46
- .map(([name, value]) => ` <input type="hidden" name="${htmlEscape(name)}" value="${htmlEscape(value)}" />`)
47
- .join("\n");
48
- return `<!doctype html>
49
- <html lang="en">
50
- <head>
51
- <meta charset="utf-8" />
52
- <meta name="viewport" content="width=device-width, initial-scale=1" />
53
- <title>Auvrynt: Webkit Arsenal</title>
54
- <style>
55
- *, *::before, *::after { box-sizing: border-box; }
56
- :root { color-scheme: dark; font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; }
57
- body { margin: 0; min-height: 100vh; background: #080b10; color: #f4f7fb; display: grid; place-items: center; padding: 24px; }
58
- main { width: min(100%, 960px); display: grid; grid-template-columns: .82fr 1.18fr; overflow: hidden; background: #10151d; border: 1px solid #273241; border-radius: 18px; box-shadow: 0 28px 90px rgba(0,0,0,.42); }
59
- .identity { padding: 44px 38px; background: #0c1118; border-right: 1px solid #273241; display: flex; flex-direction: column; justify-content: space-between; min-height: 620px; }
60
- .mark { display: inline-flex; align-items: center; gap: 10px; color: #a9b8c9; font-size: 12px; font-weight: 750; letter-spacing: .14em; text-transform: uppercase; }
61
- .mark-icon { width: 26px; height: 26px; display: grid; place-items: center; border: 1px solid #64748b; color: #b8f36b; border-radius: 7px; font-size: 13px; }
62
- .identity h1 { max-width: 310px; margin: 56px 0 16px; font-size: clamp(34px, 4vw, 52px); line-height: .98; letter-spacing: -.055em; font-weight: 760; }
63
- .identity h1 span { color: #b8f36b; }
64
- .identity-copy { max-width: 310px; margin: 0; color: #8e9bad; font-size: 15px; line-height: 1.65; }
65
- .connection-meta { display: grid; gap: 14px; margin-top: 36px; }
66
- .meta-row { display: flex; justify-content: space-between; gap: 16px; padding-top: 12px; border-top: 1px solid #273241; color: #778598; font-size: 12px; }
67
- .meta-row strong { color: #d7e0eb; font-weight: 600; text-align: right; overflow-wrap: anywhere; }
68
- .status { display: inline-flex; align-items: center; gap: 7px; color: #b8f36b; font-weight: 650; }
69
- .status::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: #b8f36b; box-shadow: 0 0 0 3px rgba(184,243,107,.12); }
70
- .identity-footer { color: #617084; font-size: 11px; line-height: 1.5; }
71
- .form-panel { padding: 44px 48px; }
72
- .eyebrow { margin: 0 0 12px; color: #b8f36b; font-size: 11px; font-weight: 750; letter-spacing: .14em; text-transform: uppercase; }
73
- .form-panel h2 { margin: 0 0 10px; font-size: 28px; line-height: 1.1; letter-spacing: -.035em; }
74
- .intro { max-width: 520px; margin: 0 0 28px; color: #9ba8b8; font-size: 15px; line-height: 1.6; }
75
- .client-badge { display: inline-flex; align-items: center; gap: 8px; margin-bottom: 24px; padding: 8px 11px; border: 1px solid #344153; border-radius: 8px; color: #dce6f1; background: #171e28; font-size: 13px; }
76
- .client-badge::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: #b8f36b; }
77
- .section-label { margin: 0 0 10px; color: #718095; font-size: 11px; font-weight: 750; letter-spacing: .12em; text-transform: uppercase; }
78
- .scope-list { list-style: none; padding: 0; margin: 0 0 28px; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
79
- .scope-list li { min-height: 68px; padding: 12px 13px; border: 1px solid #2b3747; border-radius: 10px; background: #141b24; color: #8e9bad; font-size: 12px; line-height: 1.45; }
80
- .scope-list li strong { display: block; margin-bottom: 4px; color: #f1f5f9; font-size: 13px; font-weight: 650; }
81
- .token-group { margin-bottom: 22px; }
82
- .token-group label { display: block; margin-bottom: 8px; color: #dce6f1; font-size: 13px; font-weight: 650; }
83
- .input-wrapper { position: relative; }
84
- .input-wrapper input { width: 100%; padding: 13px 58px 13px 14px; border: 1px solid #3a485a; border-radius: 9px; background: #0c1118; color: #f4f7fb; font: inherit; font-size: 15px; outline: none; transition: border-color .18s, box-shadow .18s; }
85
- .input-wrapper input:focus { border-color: #b8f36b; box-shadow: 0 0 0 3px rgba(184,243,107,.14); }
86
- .input-wrapper input::placeholder { color: #657388; }
87
- .toggle-vis { position: absolute; right: 5px; top: 50%; transform: translateY(-50%); border: 0; border-radius: 6px; padding: 7px 9px; background: transparent; color: #9ba8b8; cursor: pointer; font-size: 12px; font-weight: 650; }
88
- .toggle-vis:hover { color: #b8f36b; background: #1b2632; }
89
- .button-group { display: flex; gap: 10px; }
90
- .button-group button { flex: 1; min-height: 46px; border-radius: 9px; padding: 12px 14px; font: inherit; font-size: 14px; font-weight: 750; cursor: pointer; transition: transform .18s, background .18s, border-color .18s; }
91
- .button-group button:hover { transform: translateY(-1px); }
92
- .button-group button:focus-visible, .toggle-vis:focus-visible { outline: 2px solid #b8f36b; outline-offset: 3px; }
93
- .btn-approve { border: 1px solid #b8f36b; color: #10150c; background: #b8f36b; }
94
- .btn-approve:hover { background: #c8fa89; }
95
- .btn-deny { border: 1px solid #3a485a; color: #dce6f1; background: transparent; }
96
- .btn-deny:hover { border-color: #718095; background: #171e28; }
97
- .error { display: block; margin: 0 0 20px; padding: 12px 14px; border: 1px solid #b45555; border-radius: 9px; color: #ffd1d1; background: #321a1e; font-size: 13px; line-height: 1.45; }
98
- .security-note { display: flex; gap: 8px; margin: 22px 0 0; color: #718095; font-size: 12px; line-height: 1.5; }
99
- .security-note::before { content: "✓"; color: #b8f36b; font-weight: 800; }
100
- @media (prefers-reduced-motion: reduce) { *, *::before, *::after { transition: none !important; } .button-group button:hover { transform: none; } }
101
- @media (max-width: 720px) { body { padding: 12px; place-items: start center; } main { grid-template-columns: 1fr; } .identity { min-height: auto; padding: 28px 24px; border-right: 0; border-bottom: 1px solid #273241; } .identity h1 { margin: 34px 0 12px; font-size: 40px; } .identity-copy { max-width: 520px; } .connection-meta { margin-top: 24px; } .identity-footer { display: none; } .form-panel { padding: 28px 24px 32px; } }
102
- @media (max-width: 480px) { .scope-list { grid-template-columns: 1fr; } .button-group { flex-direction: column-reverse; } }
103
- .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }
104
- </style>
105
- </head>
106
- <body>
107
- <main role="main">
108
- <section class="identity" aria-label="Auvrynt connection details">
109
- <div>
110
- <div class="mark"><span class="mark-icon" aria-hidden="true">A</span> Auvrynt</div>
111
- <h1>Local power.<br /><span>Explicit access.</span></h1>
112
- <p class="identity-copy">Auvrynt keeps your development workspace local while giving your web agent a controlled MCP connection.</p>
113
- <div class="connection-meta" aria-label="Connection summary">
114
- <div class="meta-row"><span>Requesting agent</span><strong>${htmlEscape(params.clientName)}</strong></div>
115
- <div class="meta-row"><span>Connection state</span><strong class="status">Awaiting approval</strong></div>
116
- <div class="meta-row"><span>Permissions</span><strong>${params.scopes.length} requested</strong></div>
117
- </div>
118
- </div>
119
- <p class="identity-footer">Review every permission before continuing. You can deny this request without changing your workspace.</p>
120
- </section>
121
- <section class="form-panel" aria-labelledby="authorize-title">
122
- <p class="eyebrow">Secure handshake</p>
123
- <h2 id="authorize-title">Approve this connection</h2>
124
- <p class="intro">Review what the web agent can do in your workspace, then confirm with your local owner token.</p>
125
- ${error}
126
- <div class="client-badge">${htmlEscape(params.clientName)}</div>
127
- <p class="section-label">Requested permissions</p>
128
- <ul class="scope-list" aria-label="Requested permissions">
129
- ${scopeItems}
130
- </ul>
131
- <form method="post" aria-describedby="token-desc">
132
- <div class="token-group">
133
- <label for="owner_token">Local owner token</label>
134
- <p id="token-desc" class="sr-only">Enter your Auvrynt owner token to authorize this connection. This token stays on this page and is never shared with the web agent.</p>
135
- <div class="input-wrapper">
136
- <input id="owner_token" name="owner_token" type="password" placeholder="Enter your owner token" autocomplete="off" autofocus required aria-required="true" />
137
- <button type="button" class="toggle-vis" aria-label="Show owner token" data-target="owner_token">Show</button>
138
- </div>
139
- </div>
140
- ${hiddenFields}
141
- <div class="button-group">
142
- <button type="submit" name="denied" value="true" class="btn-deny" formnovalidate>Deny request</button>
143
- <button type="submit" class="btn-approve">Approve connection</button>
144
- </div>
145
- </form>
146
- <p class="security-note">Your owner token is validated locally. It is never sent to the web agent, stored in cookies, or written to logs.</p>
147
- </section>
148
- </main>
149
- <script nonce="${randomUUID()}">
150
- (function() {
151
- var btn = document.querySelector('.toggle-vis');
152
- var input = document.getElementById('owner_token');
153
- if (btn && input) {
154
- btn.addEventListener('click', function() {
155
- var isPassword = input.type === 'password';
156
- input.type = isPassword ? 'text' : 'password';
157
- btn.textContent = isPassword ? 'Hide' : 'Show';
158
- btn.setAttribute('aria-label', isPassword ? 'Hide owner token' : 'Show owner token');
159
- input.setAttribute('aria-live', 'polite');
160
- });
161
- }
162
- var form = document.querySelector('form');
163
- var denyBtn = document.querySelector('button[name="denied"]');
164
- if (form && denyBtn) {
165
- denyBtn.addEventListener('click', function(e) {
166
- e.preventDefault();
167
- var redirect = new URL(window.location.href);
168
- redirect.searchParams.set('error', 'access_denied');
169
- window.location.href = redirect.href;
170
- });
171
- }
172
- })();
173
- </script>
174
- </body>
175
- </html>`;
176
- }
177
- function requestedScopesAllowed(requested, supported) {
178
- return requested.every((scope) => supported.includes(scope));
179
- }
180
- function redirectHostAllowed(redirectUri, allowedHosts) {
181
- let parsed;
182
- try {
183
- parsed = new URL(redirectUri);
184
- }
185
- catch {
186
- return false;
187
- }
188
- if (["localhost", "127.0.0.1", "[::1]"].includes(parsed.hostname))
189
- return true;
190
- return allowedHosts.includes(parsed.hostname);
191
- }
192
- export class InMemoryOAuthClientsStore {
193
- allowedRedirectHosts;
194
- clients = new Map();
195
- constructor(allowedRedirectHosts) {
196
- this.allowedRedirectHosts = allowedRedirectHosts;
197
- }
198
- getClient(clientId) {
199
- return this.clients.get(clientId);
200
- }
201
- registerClient(client) {
202
- if (!client.redirect_uris.every((uri) => redirectHostAllowed(uri, this.allowedRedirectHosts))) {
203
- throw new InvalidRequestError("Client redirect_uri is not allowed for this Auvrynt server");
204
- }
205
- const now = Math.floor(Date.now() / 1000);
206
- const registered = {
207
- ...client,
208
- client_id: `auvrynt-${randomUUID()}`,
209
- client_id_issued_at: now,
210
- token_endpoint_auth_method: client.token_endpoint_auth_method ?? "none",
211
- grant_types: client.grant_types ?? ["authorization_code", "refresh_token"],
212
- response_types: client.response_types ?? ["code"],
213
- };
214
- this.clients.set(registered.client_id, registered);
215
- return registered;
216
- }
217
- }
218
- export class SingleUserOAuthProvider {
219
- config;
220
- clientsStore;
221
- codes = new Map();
222
- accessTokens = new Map();
223
- refreshTokens = new Map();
224
- resourceServerUrl;
225
- constructor(config, resourceServerUrl) {
226
- this.config = config;
227
- this.resourceServerUrl = resourceUrlFromServerUrl(resourceServerUrl);
228
- this.clientsStore = new InMemoryOAuthClientsStore(config.allowedRedirectHosts);
229
- }
230
- async authorize(client, params, res) {
231
- if (!params.resource || !checkResourceAllowed({ requestedResource: params.resource, configuredResource: this.resourceServerUrl })) {
232
- throw new InvalidRequestError("Invalid or missing OAuth resource");
233
- }
234
- if (!requestedScopesAllowed(params.scopes ?? [], this.config.scopes)) {
235
- throw new InvalidRequestError("Requested scope is not supported");
236
- }
237
- const req = res.req;
238
- const queryError = req.query?.error;
239
- if (queryError === "access_denied") {
240
- throw new AccessDeniedError("Authorization denied by user");
241
- }
242
- if (req.method !== "POST") {
243
- res.status(200).setHeader("Content-Type", "text/html; charset=utf-8");
244
- res.send(formHtml({
245
- clientName: client.client_name ?? client.client_id,
246
- scopes: params.scopes ?? this.config.scopes,
247
- resource: params.resource,
248
- fields: authorizationFormFields(client, params),
249
- }));
250
- return;
251
- }
252
- if (req.body?.denied === "true") {
253
- throw new AccessDeniedError("Authorization denied by user");
254
- }
255
- const providedToken = String(req.body?.owner_token ?? "");
256
- if (!safeEquals(providedToken, this.config.ownerToken)) {
257
- res.status(401).setHeader("Content-Type", "text/html; charset=utf-8");
258
- res.send(formHtml({
259
- error: "The owner password was not accepted.",
260
- clientName: client.client_name ?? client.client_id,
261
- scopes: params.scopes ?? this.config.scopes,
262
- resource: params.resource,
263
- fields: authorizationFormFields(client, params),
264
- }));
265
- return;
266
- }
267
- const code = `code-${randomUUID()}`;
268
- this.codes.set(code, {
269
- clientId: client.client_id,
270
- params,
271
- expiresAtMs: Date.now() + CODE_TTL_MS,
272
- });
273
- const redirectUrl = new URL(params.redirectUri);
274
- redirectUrl.searchParams.set("code", code);
275
- if (params.state !== undefined)
276
- redirectUrl.searchParams.set("state", params.state);
277
- res.redirect(302, redirectUrl.href);
278
- }
279
- async challengeForAuthorizationCode(client, authorizationCode) {
280
- const record = this.validCodeRecord(client, authorizationCode);
281
- return record.params.codeChallenge;
282
- }
283
- async exchangeAuthorizationCode(client, authorizationCode, _codeVerifier, redirectUri, resource) {
284
- const record = this.validCodeRecord(client, authorizationCode);
285
- if (redirectUri && redirectUri !== record.params.redirectUri) {
286
- throw new InvalidGrantError("redirect_uri does not match the authorization request");
287
- }
288
- if (resource && !checkResourceAllowed({ requestedResource: resource, configuredResource: this.resourceServerUrl })) {
289
- throw new InvalidGrantError("Invalid resource");
290
- }
291
- this.codes.delete(authorizationCode);
292
- return this.issueTokens(client.client_id, record.params.scopes ?? this.config.scopes, record.params.resource);
293
- }
294
- async exchangeRefreshToken(client, refreshToken, scopes, resource) {
295
- const record = this.refreshTokens.get(hashToken(refreshToken));
296
- if (!record || record.clientId !== client.client_id || record.expiresAt < Math.floor(Date.now() / 1000)) {
297
- throw new InvalidGrantError("Invalid refresh token");
298
- }
299
- if (resource && !checkResourceAllowed({ requestedResource: resource, configuredResource: this.resourceServerUrl })) {
300
- throw new InvalidGrantError("Invalid resource");
301
- }
302
- const requestedScopes = scopes ?? record.scopes;
303
- if (!requestedScopes.every((scope) => record.scopes.includes(scope))) {
304
- throw new AccessDeniedError("Refresh token cannot grant requested scopes");
305
- }
306
- this.refreshTokens.delete(hashToken(refreshToken));
307
- return this.issueTokens(client.client_id, requestedScopes, resource ?? record.resource);
308
- }
309
- async verifyAccessToken(token) {
310
- const record = this.accessTokens.get(hashToken(token));
311
- if (!record || record.expiresAt < Math.floor(Date.now() / 1000)) {
312
- throw new InvalidTokenError("Invalid or expired access token");
313
- }
314
- return {
315
- token,
316
- clientId: record.clientId,
317
- scopes: record.scopes,
318
- expiresAt: record.expiresAt,
319
- resource: record.resource,
320
- };
321
- }
322
- async revokeToken(_client, request) {
323
- const hashed = hashToken(request.token);
324
- this.accessTokens.delete(hashed);
325
- this.refreshTokens.delete(hashed);
326
- }
327
- validCodeRecord(client, authorizationCode) {
328
- const record = this.codes.get(authorizationCode);
329
- if (!record || record.clientId !== client.client_id || record.expiresAtMs < Date.now()) {
330
- throw new InvalidGrantError("Invalid authorization code");
331
- }
332
- return record;
333
- }
334
- issueTokens(clientId, scopes, resource) {
335
- const now = Math.floor(Date.now() / 1000);
336
- const accessToken = randomToken();
337
- const refreshToken = randomToken();
338
- const accessExpiresAt = now + this.config.accessTokenTtlSeconds;
339
- const refreshExpiresAt = now + this.config.refreshTokenTtlSeconds;
340
- this.accessTokens.set(hashToken(accessToken), {
341
- token: accessToken,
342
- clientId,
343
- scopes,
344
- expiresAt: accessExpiresAt,
345
- resource,
346
- });
347
- this.refreshTokens.set(hashToken(refreshToken), {
348
- token: refreshToken,
349
- clientId,
350
- scopes,
351
- expiresAt: refreshExpiresAt,
352
- resource,
353
- });
354
- return {
355
- access_token: accessToken,
356
- token_type: "bearer",
357
- expires_in: this.config.accessTokenTtlSeconds,
358
- refresh_token: refreshToken,
359
- scope: scopes.join(" "),
360
- };
361
- }
362
- }
363
- function authorizationFormFields(client, params) {
364
- return {
365
- response_type: "code",
366
- client_id: client.client_id,
367
- redirect_uri: params.redirectUri,
368
- code_challenge: params.codeChallenge,
369
- code_challenge_method: "S256",
370
- scope: params.scopes?.join(" "),
371
- state: params.state,
372
- resource: params.resource?.href,
373
- };
374
- }
375
- function hashToken(token) {
376
- return createHash("sha256").update(token).digest("base64url");
377
- }
1
+ export * from "./auth/oauth-provider.js";
package/dist/pi-tools.js CHANGED
@@ -1,81 +1 @@
1
- import { createBashTool, createEditTool, createFindTool, createGrepTool, createLsTool, createReadTool, createWriteTool, } from "@earendil-works/pi-coding-agent";
2
- import { resolveAllowedPath } from "./roots.js";
3
- function toMcpContent(result) {
4
- return result.content.map((content) => {
5
- if (content.type === "text") {
6
- return { type: "text", text: content.text };
7
- }
8
- return {
9
- type: "image",
10
- data: content.data,
11
- mimeType: content.mimeType,
12
- };
13
- });
14
- }
15
- function formatToolError(error) {
16
- const message = error instanceof Error ? error.message : String(error);
17
- return [{ type: "text", text: message }];
18
- }
19
- async function runTool(execute, input, context) {
20
- try {
21
- const result = await execute(input);
22
- return {
23
- content: toMcpContent(result),
24
- details: result.details,
25
- };
26
- }
27
- catch (error) {
28
- return { content: formatToolError(error), isError: true };
29
- }
30
- }
31
- export async function readFileTool(input, context) {
32
- const path = resolveAllowedPath(input.path, context.cwd, context.readRoots ?? [context.root]);
33
- const tool = createReadTool(context.cwd);
34
- return runTool((params) => tool.execute("read_file", params), {
35
- path,
36
- offset: input.offset,
37
- limit: input.limit,
38
- }, context);
39
- }
40
- export async function writeFileTool(input, context) {
41
- const path = resolveAllowedPath(input.path, context.cwd, [context.root]);
42
- const tool = createWriteTool(context.cwd);
43
- return runTool((params) => tool.execute("write_file", params), {
44
- path,
45
- content: input.content,
46
- }, context);
47
- }
48
- export async function editFileTool(input, context) {
49
- const path = resolveAllowedPath(input.path, context.cwd, [context.root]);
50
- const tool = createEditTool(context.cwd);
51
- return runTool((params) => tool.execute("edit_file", params), {
52
- path,
53
- edits: input.edits,
54
- }, context);
55
- }
56
- export async function grepFilesTool(input, context) {
57
- if (input.path)
58
- resolveAllowedPath(input.path, context.cwd, [context.root]);
59
- const tool = createGrepTool(context.cwd);
60
- return runTool((params) => tool.execute("grep_files", params), input, context);
61
- }
62
- export async function findFilesTool(input, context) {
63
- if (input.path)
64
- resolveAllowedPath(input.path, context.cwd, [context.root]);
65
- const tool = createFindTool(context.cwd);
66
- return runTool((params) => tool.execute("find_files", params), input, context);
67
- }
68
- export async function listDirectoryTool(input, context) {
69
- if (input.path)
70
- resolveAllowedPath(input.path, context.cwd, [context.root]);
71
- const tool = createLsTool(context.cwd);
72
- return runTool((params) => tool.execute("list_directory", params), input, context);
73
- }
74
- export async function runShellTool(input, context) {
75
- const tool = createBashTool(context.cwd);
76
- const timeout = input.timeout === undefined ? 30 : Math.min(input.timeout, 300);
77
- return runTool((params) => tool.execute("run_shell", params), {
78
- command: input.command,
79
- timeout,
80
- }, context);
81
- }
1
+ export * from "./tools/pi-tools.js";
@@ -0,0 +1 @@
1
+ export * from "./integrations/playwright/playwright-runtime.js";
@@ -0,0 +1,189 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { execFileSync } from "node:child_process";
3
+ import { closeSync, existsSync, fsyncSync, openSync, writeSync } from "node:fs";
4
+ import { mkdir, readFile, rename, stat, unlink, writeFile } from "node:fs/promises";
5
+ import { join, resolve } from "node:path";
6
+ export const INTEGRATION_KEYS = ["godotGdscript", "godotCsharp", "blender", "aseprite", "serena", "playwright", "context7", "obsidian", "roblox"];
7
+ export const INTEGRATION_LABELS = {
8
+ godotGdscript: "Godot GDScript",
9
+ godotCsharp: "Godot C#",
10
+ blender: "Blender",
11
+ aseprite: "Aseprite",
12
+ serena: "Software Development",
13
+ playwright: "Web Development",
14
+ context7: "Context7",
15
+ obsidian: "Obsidian",
16
+ roblox: "Roblox Studio",
17
+ };
18
+ const START_PROFILE_ALIASES = {
19
+ model: "blender",
20
+ blender: "blender",
21
+ pixel: "aseprite",
22
+ aseprite: "aseprite",
23
+ web: "playwright",
24
+ playwright: "playwright",
25
+ godotcs: "godotCsharp",
26
+ "godot-cs": "godotCsharp",
27
+ godotcsharp: "godotCsharp",
28
+ godotgd: "godotGdscript",
29
+ "godot-gd": "godotGdscript",
30
+ godotgdscript: "godotGdscript",
31
+ se: "serena",
32
+ serena: "serena",
33
+ context7: "context7",
34
+ c7: "context7",
35
+ obsidian: "obsidian",
36
+ notes: "obsidian",
37
+ roblox: "roblox",
38
+ robloxstudio: "roblox",
39
+ rbx: "roblox",
40
+ };
41
+ export function parseIntegrationProfiles(args) {
42
+ const tokens = args
43
+ .flatMap((arg) => arg.split(/[\s,]+/))
44
+ .map((value) => value.trim().toLowerCase())
45
+ .filter(Boolean);
46
+ if (tokens.length === 0)
47
+ throw new Error("Choose at least one profile: blender, pixel, web, godotcs, godotgd, se, or roblox.");
48
+ const profiles = new Set();
49
+ for (const token of tokens) {
50
+ const profile = START_PROFILE_ALIASES[token];
51
+ if (!profile)
52
+ throw new Error(`Unknown start profile: ${token}. Use blender, pixel, web, godotcs, godotgd, se, or roblox.`);
53
+ profiles.add(profile);
54
+ }
55
+ return [...profiles];
56
+ }
57
+ export function parseStartRequest(args) {
58
+ const backgroundChild = args.includes("--background-child");
59
+ const replace = args.includes("--replace");
60
+ const noIntegrations = args.includes("--no-integrations");
61
+ const profiles = args.filter((arg) => arg !== "--background-child" && arg !== "--replace" && arg !== "--no-integrations");
62
+ if (noIntegrations && profiles.length > 0)
63
+ throw new Error("Do not combine --no-integrations with start profiles.");
64
+ const unknownOption = profiles.find((arg) => arg.startsWith("--"));
65
+ if (unknownOption)
66
+ throw new Error(`Unknown start option: ${unknownOption}`);
67
+ return { profiles: noIntegrations ? [] : profiles.length > 0 ? parseIntegrationProfiles(profiles) : [], replace, backgroundChild };
68
+ }
69
+ export function isProcessRunning(pid) {
70
+ try {
71
+ process.kill(pid, 0);
72
+ return true;
73
+ }
74
+ catch {
75
+ return false;
76
+ }
77
+ }
78
+ export function getProcessIdentity(pid) {
79
+ if (!Number.isInteger(pid) || pid < 1 || !isProcessRunning(pid))
80
+ return undefined;
81
+ if (process.platform !== "win32") {
82
+ return {
83
+ processPath: pid === process.pid ? resolve(process.execPath) : `pid:${pid}`,
84
+ processStartedAt: pid === process.pid ? new Date(Date.now() - process.uptime() * 1000).toISOString() : "unknown",
85
+ };
86
+ }
87
+ try {
88
+ const script = [
89
+ `$p = Get-Process -Id ${pid} -ErrorAction Stop`,
90
+ "[pscustomobject]@{ processPath = $p.Path; processStartedAt = $p.StartTime.ToUniversalTime().ToString('o') }",
91
+ "| ConvertTo-Json -Compress",
92
+ ].join("; ").replace("; |", " |");
93
+ const raw = execFileSync("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", script], {
94
+ encoding: "utf8",
95
+ stdio: ["ignore", "pipe", "ignore"],
96
+ windowsHide: true,
97
+ }).trim();
98
+ const parsed = JSON.parse(raw);
99
+ if (!parsed.processPath || !parsed.processStartedAt)
100
+ return undefined;
101
+ return { processPath: resolve(parsed.processPath), processStartedAt: parsed.processStartedAt };
102
+ }
103
+ catch {
104
+ return undefined;
105
+ }
106
+ }
107
+ export function processIdentityMatches(pid, expected) {
108
+ if (!expected.processPath || !expected.processStartedAt)
109
+ return false;
110
+ const actual = getProcessIdentity(pid);
111
+ if (!actual)
112
+ return false;
113
+ const samePath = resolve(actual.processPath).toLowerCase() === resolve(expected.processPath).toLowerCase();
114
+ const actualStart = Date.parse(actual.processStartedAt);
115
+ const expectedStart = Date.parse(expected.processStartedAt);
116
+ return samePath && Number.isFinite(actualStart) && Number.isFinite(expectedStart) && Math.abs(actualStart - expectedStart) < 1_000;
117
+ }
118
+ export async function readJsonFile(path) {
119
+ try {
120
+ return JSON.parse(await readFile(path, "utf8"));
121
+ }
122
+ catch {
123
+ return undefined;
124
+ }
125
+ }
126
+ export async function atomicWriteJson(path, value) {
127
+ const tempPath = `${path}.${process.pid}.${randomBytes(6).toString("hex")}.tmp`;
128
+ await writeFile(tempPath, JSON.stringify(value), { mode: 0o600, flag: "wx" });
129
+ try {
130
+ await rename(tempPath, path);
131
+ }
132
+ catch (error) {
133
+ await unlink(tempPath).catch(() => undefined);
134
+ throw error;
135
+ }
136
+ }
137
+ export async function acquireManagementLock(stateDir) {
138
+ await mkdir(stateDir, { recursive: true, mode: 0o700 });
139
+ const lockPath = join(stateDir, "manager.lock");
140
+ const identity = getProcessIdentity(process.pid);
141
+ if (!identity)
142
+ throw new Error("Could not identify the current Auvrynt management process.");
143
+ for (let attempt = 0; attempt < 3; attempt++) {
144
+ const nonce = randomBytes(16).toString("hex");
145
+ try {
146
+ const handle = openSync(lockPath, "wx", 0o600);
147
+ const record = { pid: process.pid, nonce, ...identity };
148
+ try {
149
+ const bytes = Buffer.from(JSON.stringify(record));
150
+ writeSync(handle, bytes);
151
+ fsyncSync(handle);
152
+ }
153
+ finally {
154
+ closeSync(handle);
155
+ }
156
+ return {
157
+ release: async () => {
158
+ const current = await readJsonFile(lockPath);
159
+ if (current?.pid === process.pid && current.nonce === nonce) {
160
+ await unlink(lockPath).catch(() => undefined);
161
+ }
162
+ },
163
+ };
164
+ }
165
+ catch (error) {
166
+ if (error.code !== "EEXIST")
167
+ throw error;
168
+ const current = await readJsonFile(lockPath);
169
+ if (current && processIdentityMatches(current.pid, current)) {
170
+ throw new Error(`Another Auvrynt lifecycle command is already running (PID ${current.pid}).`);
171
+ }
172
+ await unlink(lockPath).catch((unlinkError) => {
173
+ if (unlinkError.code !== "ENOENT")
174
+ throw unlinkError;
175
+ });
176
+ }
177
+ }
178
+ throw new Error("Could not acquire the Auvrynt lifecycle lock.");
179
+ }
180
+ export async function rotateLogFile(path, maxBytes = 5 * 1024 * 1024) {
181
+ if (!existsSync(path))
182
+ return;
183
+ const info = await stat(path).catch(() => undefined);
184
+ if (!info || info.size < maxBytes)
185
+ return;
186
+ const backup = `${path}.1`;
187
+ await unlink(backup).catch(() => undefined);
188
+ await rename(path, backup);
189
+ }