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,594 @@
1
+ import { createHash } from "node:crypto";
2
+ import { execFile } from "node:child_process";
3
+ import { existsSync } from "node:fs";
4
+ import { copyFile, cp, lstat, mkdir, readFile, readdir, rename, rm, stat, writeFile, } from "node:fs/promises";
5
+ import { homedir } from "node:os";
6
+ import { basename, dirname, extname, join } from "node:path";
7
+ import { promisify } from "node:util";
8
+ import { asepriteConvertFile, asepriteExportSpriteSheet, errorResponse, luaString, openSpriteScript, resolveAsepriteExecutable, runLua, sanitizeCliOutput, textResponse, workspacePath, } from "./aseprite-tools.js";
9
+ import { asepriteAuditSprite, asepriteCompareDocuments } from "./aseprite-analysis-tools.js";
10
+ const execFileAsync = promisify(execFile);
11
+ const MAX_BATCH_FILES = 128;
12
+ function safeSegment(value) {
13
+ const normalized = value.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
14
+ return normalized.slice(0, 120) || "sprite";
15
+ }
16
+ async function sha256(path) {
17
+ return createHash("sha256").update(await readFile(path)).digest("hex");
18
+ }
19
+ function checkpointRoot(registry, workspaceId, filePath) {
20
+ const workspace = registry.getWorkspace(workspaceId);
21
+ return registry.resolveArtifactPath(workspace, `checkpoints/${safeSegment(filePath)}`, "aseprite");
22
+ }
23
+ function asepriteUserDataRoot() {
24
+ if (process.env.ASEPRITE_USER_DATA_DIR?.trim())
25
+ return process.env.ASEPRITE_USER_DATA_DIR.trim();
26
+ if (process.platform === "win32" && process.env.APPDATA)
27
+ return join(process.env.APPDATA, "Aseprite");
28
+ if (process.platform === "darwin")
29
+ return join(homedir(), "Library", "Application Support", "Aseprite");
30
+ return join(process.env.XDG_CONFIG_HOME || join(homedir(), ".config"), "aseprite");
31
+ }
32
+ async function assertTreeContainsNoSymlinks(path) {
33
+ const info = await lstat(path);
34
+ if (info.isSymbolicLink())
35
+ throw new Error(`Symbolic links are not allowed in extension packages: ${path}`);
36
+ if (!info.isDirectory())
37
+ return;
38
+ for (const entry of await readdir(path, { withFileTypes: true })) {
39
+ await assertTreeContainsNoSymlinks(join(path, entry.name));
40
+ }
41
+ }
42
+ async function directorySize(path) {
43
+ let total = 0;
44
+ for (const entry of await readdir(path, { withFileTypes: true }).catch(() => [])) {
45
+ const child = join(path, entry.name);
46
+ if (entry.isDirectory())
47
+ total += await directorySize(child);
48
+ else if (entry.isFile())
49
+ total += (await stat(child)).size;
50
+ }
51
+ return total;
52
+ }
53
+ export async function assertAsepriteExpectedVersion(registry, workspaceId, filePath, expectedVersion) {
54
+ const file = workspacePath(registry, workspaceId, filePath);
55
+ const actual = await sha256(file.absolute);
56
+ if (expectedVersion && expectedVersion !== actual) {
57
+ throw new Error(`Aseprite file changed since it was inspected. Expected ${expectedVersion}, current ${actual}.`);
58
+ }
59
+ return actual;
60
+ }
61
+ export async function asepriteFileSafety(config, registry, input) {
62
+ try {
63
+ const file = workspacePath(registry, input.workspaceId, input.filePath);
64
+ const root = checkpointRoot(registry, input.workspaceId, file.relative);
65
+ await mkdir(root, { recursive: true });
66
+ if (input.action === "status" || input.action === "assert_version") {
67
+ const info = await stat(file.absolute);
68
+ const version = await assertAsepriteExpectedVersion(registry, input.workspaceId, input.filePath, input.action === "assert_version" ? input.expectedVersion : undefined);
69
+ return textResponse({
70
+ file: file.relative,
71
+ version,
72
+ size: info.size,
73
+ modifiedAt: info.mtime.toISOString(),
74
+ asepriteRunning: (await import("../integration-discovery.js")).processDetected(await (await import("../integration-discovery.js")).discoverLocalIntegrations({ forceRefresh: true }), "aseprite"),
75
+ });
76
+ }
77
+ if (input.action === "checkpoint") {
78
+ const version = await assertAsepriteExpectedVersion(registry, input.workspaceId, input.filePath, input.expectedVersion);
79
+ const id = `${new Date().toISOString().replace(/[:.]/g, "-")}-${version.slice(0, 12)}`;
80
+ const extension = extname(file.absolute) || ".aseprite";
81
+ const copyPath = join(root, `${id}${extension}`);
82
+ const metadataPath = join(root, `${id}.json`);
83
+ await copyFile(file.absolute, copyPath);
84
+ await writeFile(metadataPath, JSON.stringify({
85
+ id,
86
+ file: file.relative,
87
+ version,
88
+ label: input.label?.trim() || undefined,
89
+ createdAt: new Date().toISOString(),
90
+ copyFile: basename(copyPath),
91
+ }, null, 2), "utf8");
92
+ return textResponse({ checkpointId: id, file: file.relative, version });
93
+ }
94
+ const metadataFiles = (await readdir(root)).filter((name) => name.endsWith(".json")).sort().reverse();
95
+ const checkpoints = [];
96
+ for (const name of metadataFiles) {
97
+ try {
98
+ checkpoints.push(JSON.parse(await readFile(join(root, name), "utf8")));
99
+ }
100
+ catch {
101
+ checkpoints.push({ id: name.slice(0, -5), invalidMetadata: true });
102
+ }
103
+ }
104
+ if (input.action === "list_checkpoints")
105
+ return textResponse({ file: file.relative, checkpoints });
106
+ const id = input.checkpointId?.trim();
107
+ if (!id || !/^[a-zA-Z0-9._-]+$/.test(id))
108
+ throw new Error("A valid checkpointId is required.");
109
+ const metadata = checkpoints.find((item) => item.id === id);
110
+ if (!metadata)
111
+ throw new Error(`Checkpoint ${id} was not found.`);
112
+ const copyPath = join(root, metadata.copyFile);
113
+ if (input.action === "delete_checkpoint") {
114
+ await rm(copyPath, { force: true });
115
+ await rm(join(root, `${id}.json`), { force: true });
116
+ return textResponse({ deleted: id });
117
+ }
118
+ await assertAsepriteExpectedVersion(registry, input.workspaceId, input.filePath, input.expectedVersion);
119
+ const temporary = `${file.absolute}.auvrynt-rollback-${Date.now()}`;
120
+ await copyFile(copyPath, temporary);
121
+ await rename(temporary, file.absolute);
122
+ return textResponse({
123
+ restored: id,
124
+ file: file.relative,
125
+ version: await sha256(file.absolute),
126
+ });
127
+ }
128
+ catch (error) {
129
+ return errorResponse(error instanceof Error ? error.message : String(error));
130
+ }
131
+ }
132
+ function presetDirectory(registry, workspaceId) {
133
+ const workspace = registry.getWorkspace(workspaceId);
134
+ return registry.resolvePath(workspace, ".auvrynt/aseprite-export-presets");
135
+ }
136
+ async function runExtendedExport(config, registry, workspaceId, preset) {
137
+ const workspace = registry.getWorkspace(workspaceId);
138
+ const executable = await resolveAsepriteExecutable(config);
139
+ const source = workspacePath(registry, workspaceId, preset.filePath);
140
+ const sheet = workspacePath(registry, workspaceId, preset.sheetPath);
141
+ const data = preset.dataPath ? workspacePath(registry, workspaceId, preset.dataPath) : undefined;
142
+ await mkdir(dirname(sheet.absolute), { recursive: true });
143
+ if (data)
144
+ await mkdir(dirname(data.absolute), { recursive: true });
145
+ const args = ["-b", source.absolute, "--sheet", sheet.absolute, "--sheet-type", preset.sheetType ?? "horizontal"];
146
+ if (data)
147
+ args.push("--data", data.absolute, "--format", preset.dataFormat ?? "json-array");
148
+ if (preset.columns)
149
+ args.push("--sheet-columns", String(preset.columns));
150
+ if (preset.rows)
151
+ args.push("--sheet-rows", String(preset.rows));
152
+ if (preset.sheetWidth)
153
+ args.push("--sheet-width", String(preset.sheetWidth));
154
+ if (preset.sheetHeight)
155
+ args.push("--sheet-height", String(preset.sheetHeight));
156
+ if (preset.tag)
157
+ args.push("--tag", preset.tag);
158
+ if (preset.layer)
159
+ args.push("--layer", preset.layer);
160
+ for (const ignored of preset.ignoreLayers ?? [])
161
+ args.push("--ignore-layer", ignored);
162
+ if (preset.allLayers)
163
+ args.push("--all-layers");
164
+ if (preset.splitLayers)
165
+ args.push("--split-layers");
166
+ if (preset.splitTags)
167
+ args.push("--split-tags");
168
+ if (preset.splitSlices)
169
+ args.push("--split-slices");
170
+ if (preset.splitGrid)
171
+ args.push("--split-grid");
172
+ if (preset.playSubtags)
173
+ args.push("--play-subtags");
174
+ if (preset.ignoreEmpty)
175
+ args.push("--ignore-empty");
176
+ if (preset.trim)
177
+ args.push("--trim");
178
+ if (preset.trimSprite)
179
+ args.push("--trim-sprite");
180
+ if (preset.trimByGrid)
181
+ args.push("--trim-by-grid");
182
+ if (preset.extrude)
183
+ args.push("--extrude");
184
+ if (preset.mergeDuplicates)
185
+ args.push("--merge-duplicates");
186
+ if (preset.borderPadding !== undefined)
187
+ args.push("--border-padding", String(preset.borderPadding));
188
+ if (preset.shapePadding !== undefined)
189
+ args.push("--shape-padding", String(preset.shapePadding));
190
+ if (preset.innerPadding !== undefined)
191
+ args.push("--inner-padding", String(preset.innerPadding));
192
+ if (preset.filenameFormat)
193
+ args.push("--filename-format", preset.filenameFormat);
194
+ if (preset.tagnameFormat)
195
+ args.push("--tagname-format", preset.tagnameFormat);
196
+ const { stdout, stderr } = await execFileAsync(executable, args, {
197
+ cwd: workspace.root,
198
+ timeout: 120_000,
199
+ maxBuffer: 10 * 1024 * 1024,
200
+ windowsHide: true,
201
+ });
202
+ return {
203
+ source: source.relative,
204
+ sheet: sheet.relative,
205
+ data: data?.relative,
206
+ output: sanitizeCliOutput([stdout.trim(), stderr.trim()].filter(Boolean).join("\n")).slice(-4000),
207
+ };
208
+ }
209
+ async function validateExportData(config, registry, workspaceId, preset) {
210
+ const source = workspacePath(registry, workspaceId, preset.filePath);
211
+ const sheet = workspacePath(registry, workspaceId, preset.sheetPath);
212
+ const data = preset.dataPath ? workspacePath(registry, workspaceId, preset.dataPath) : undefined;
213
+ const problems = [];
214
+ if (!existsSync(sheet.absolute))
215
+ problems.push({ code: "missing_sheet", path: sheet.relative });
216
+ let metadataFrames = [];
217
+ if (data) {
218
+ if (!existsSync(data.absolute))
219
+ problems.push({ code: "missing_metadata", path: data.relative });
220
+ else {
221
+ const parsed = JSON.parse(await readFile(data.absolute, "utf8"));
222
+ const frames = parsed.frames ?? parsed;
223
+ metadataFrames = Array.isArray(frames)
224
+ ? frames
225
+ : frames && typeof frames === "object"
226
+ ? Object.values(frames)
227
+ : [];
228
+ const rectangles = metadataFrames.map((entry, index) => ({
229
+ index,
230
+ x: entry.frame?.x,
231
+ y: entry.frame?.y,
232
+ width: entry.frame?.w ?? entry.frame?.width,
233
+ height: entry.frame?.h ?? entry.frame?.height,
234
+ })).filter((rect) => [rect.x, rect.y, rect.width, rect.height].every(Number.isFinite));
235
+ for (let i = 0; i < rectangles.length; i++) {
236
+ for (let j = i + 1; j < rectangles.length; j++) {
237
+ const a = rectangles[i];
238
+ const b = rectangles[j];
239
+ const overlap = a.x < b.x + b.width && a.x + a.width > b.x
240
+ && a.y < b.y + b.height && a.y + a.height > b.y;
241
+ if (overlap)
242
+ problems.push({ code: "overlapping_frames", first: a.index, second: b.index });
243
+ }
244
+ }
245
+ }
246
+ }
247
+ const sourceInfo = await runLua(config, registry, workspaceId, `
248
+ ${openSpriteScript(source.absolute)}
249
+ local count=#sprite.frames
250
+ if ${preset.tag ? "true" : "false"} then
251
+ local found=nil
252
+ for _,tag in ipairs(sprite.tags) do if tag.name==${luaString(preset.tag ?? "")} then found=tag break end end
253
+ if found==nil then fail("Configured export tag was not found") end
254
+ count=found.toFrame.frameNumber-found.fromFrame.frameNumber+1
255
+ end
256
+ emit_result({expected_frames=count,summary=sprite_summary(sprite)})
257
+ sprite:close()
258
+ `);
259
+ if (data && !preset.mergeDuplicates && metadataFrames.length !== sourceInfo.expected_frames) {
260
+ problems.push({ code: "frame_count_mismatch", expected: sourceInfo.expected_frames, actual: metadataFrames.length });
261
+ }
262
+ return { valid: problems.length === 0, problems, source: sourceInfo.summary, metadataFrames: metadataFrames.length };
263
+ }
264
+ export async function asepriteManageExportPreset(config, registry, input) {
265
+ try {
266
+ const directory = presetDirectory(registry, input.workspaceId);
267
+ await mkdir(directory, { recursive: true });
268
+ const lastPath = join(directory, "_last-export.json");
269
+ if (input.action === "list") {
270
+ const names = (await readdir(directory)).filter((name) => name.endsWith(".json") && name !== "_last-export.json").map((name) => name.slice(0, -5));
271
+ return textResponse({ presets: names.sort() });
272
+ }
273
+ const name = input.name?.trim();
274
+ if (input.action !== "repeat" && (!name || !/^[a-zA-Z0-9._-]+$/.test(name)))
275
+ throw new Error("A valid preset name is required.");
276
+ const path = name ? join(directory, `${name}.json`) : lastPath;
277
+ if (input.action === "save") {
278
+ if (!input.preset)
279
+ throw new Error("preset is required.");
280
+ await writeFile(path, JSON.stringify(input.preset, null, 2), "utf8");
281
+ return textResponse({ saved: name });
282
+ }
283
+ if (input.action === "delete") {
284
+ await rm(path, { force: true });
285
+ return textResponse({ deleted: name });
286
+ }
287
+ const preset = input.action === "repeat"
288
+ ? JSON.parse(await readFile(lastPath, "utf8"))
289
+ : JSON.parse(await readFile(path, "utf8"));
290
+ if (input.action === "validate")
291
+ return textResponse(await validateExportData(config, registry, input.workspaceId, preset));
292
+ const result = await runExtendedExport(config, registry, input.workspaceId, preset);
293
+ await writeFile(lastPath, JSON.stringify(preset, null, 2), "utf8");
294
+ return textResponse({ ...result, validation: await validateExportData(config, registry, input.workspaceId, preset) });
295
+ }
296
+ catch (error) {
297
+ return errorResponse(error instanceof Error ? error.message : String(error));
298
+ }
299
+ }
300
+ export async function asepriteBatchProcess(config, registry, input) {
301
+ try {
302
+ if (!Array.isArray(input.filePaths) || input.filePaths.length === 0)
303
+ throw new Error("filePaths must not be empty.");
304
+ if (input.filePaths.length > MAX_BATCH_FILES)
305
+ throw new Error(`A maximum of ${MAX_BATCH_FILES} files is supported.`);
306
+ if (!input.inPlace && input.operation !== "audit" && !input.outputDirectory)
307
+ throw new Error("outputDirectory is required unless inPlace is true.");
308
+ const plan = input.filePaths.map((filePath) => ({ filePath, operation: input.operation }));
309
+ if (input.dryRun)
310
+ return textResponse({ dryRun: true, plan });
311
+ const results = [];
312
+ for (const filePath of input.filePaths) {
313
+ const source = workspacePath(registry, input.workspaceId, filePath);
314
+ if (input.operation === "audit") {
315
+ const response = await asepriteAuditSprite(config, registry, { workspaceId: input.workspaceId, filePath });
316
+ results.push({ filePath, response: response.content[0]?.type === "text" ? response.content[0].text : response });
317
+ continue;
318
+ }
319
+ if (input.inPlace) {
320
+ await asepriteFileSafety(config, registry, {
321
+ workspaceId: input.workspaceId,
322
+ filePath,
323
+ action: "checkpoint",
324
+ label: `batch-${input.operation}`,
325
+ });
326
+ }
327
+ const outputPath = input.inPlace
328
+ ? filePath
329
+ : `${input.outputDirectory.replace(/[\\/]$/, "")}/${basename(filePath)}`;
330
+ if (input.operation === "convert") {
331
+ const response = await asepriteConvertFile(config, registry, {
332
+ workspaceId: input.workspaceId,
333
+ filePath,
334
+ outputPath,
335
+ scale: input.scale,
336
+ colorMode: input.colorMode,
337
+ palettePath: input.palettePath,
338
+ trim: input.trim,
339
+ });
340
+ results.push({ filePath, outputPath, response: response.content[0]?.type === "text" ? response.content[0].text : response });
341
+ }
342
+ else if (input.operation === "export") {
343
+ const base = basename(filePath, extname(filePath));
344
+ const sheetPath = `${input.outputDirectory.replace(/[\\/]$/, "")}/${base}.png`;
345
+ const dataPath = `${input.outputDirectory.replace(/[\\/]$/, "")}/${base}.json`;
346
+ const response = await asepriteExportSpriteSheet(config, registry, {
347
+ workspaceId: input.workspaceId,
348
+ filePath,
349
+ sheetPath,
350
+ dataPath,
351
+ sheetType: input.sheetType,
352
+ trim: input.trim,
353
+ });
354
+ results.push({ filePath, sheetPath, dataPath, response: response.content[0]?.type === "text" ? response.content[0].text : response });
355
+ }
356
+ else {
357
+ const response = await asepriteMaintenance(config, registry, {
358
+ workspaceId: input.workspaceId,
359
+ action: "repair",
360
+ filePath,
361
+ outputPath,
362
+ });
363
+ results.push({ filePath, outputPath, response: response.content[0]?.type === "text" ? response.content[0].text : response });
364
+ }
365
+ }
366
+ return textResponse({ processed: results.length, results });
367
+ }
368
+ catch (error) {
369
+ return errorResponse(error instanceof Error ? error.message : String(error));
370
+ }
371
+ }
372
+ export async function asepriteMaintenance(config, registry, input) {
373
+ try {
374
+ const source = workspacePath(registry, input.workspaceId, input.filePath);
375
+ if (input.action === "validate") {
376
+ const result = await runLua(config, registry, input.workspaceId, `
377
+ ${openSpriteScript(source.absolute)}
378
+ emit_result({valid=true,summary=sprite_summary(sprite),modified=sprite.isModified})
379
+ sprite:close()
380
+ `);
381
+ return textResponse(result);
382
+ }
383
+ if (!input.outputPath)
384
+ throw new Error("outputPath is required.");
385
+ const output = workspacePath(registry, input.workspaceId, input.outputPath);
386
+ await mkdir(dirname(output.absolute), { recursive: true });
387
+ if (input.action === "repair") {
388
+ const result = await runLua(config, registry, input.workspaceId, `
389
+ ${openSpriteScript(source.absolute)}
390
+ if not sprite:saveCopyAs(${luaString(output.absolute)}) then fail("Unable to save repaired copy") end
391
+ local reopened=app.open(${luaString(output.absolute)})
392
+ if reopened==nil then fail("Repaired copy could not be reopened") end
393
+ emit_result({source=${luaString(source.relative)},output=${luaString(output.relative)},summary=sprite_summary(reopened)})
394
+ reopened:close() sprite:close()
395
+ `);
396
+ return textResponse(result);
397
+ }
398
+ const workspace = registry.getWorkspace(input.workspaceId);
399
+ const executable = await resolveAsepriteExecutable(config);
400
+ const format = input.intermediateFormat ?? "png";
401
+ const intermediate = registry.resolveArtifactPath(workspace, `roundtrip/${Date.now()}.${format}`, "aseprite");
402
+ await mkdir(dirname(intermediate), { recursive: true });
403
+ await execFileAsync(executable, ["-b", source.absolute, "--save-as", intermediate], { cwd: workspace.root, timeout: 120_000, windowsHide: true });
404
+ await execFileAsync(executable, ["-b", intermediate, "--save-as", output.absolute], { cwd: workspace.root, timeout: 120_000, windowsHide: true });
405
+ const comparison = await asepriteCompareDocuments(config, registry, {
406
+ workspaceId: input.workspaceId,
407
+ referencePath: input.filePath,
408
+ candidatePath: input.outputPath,
409
+ comparePixels: true,
410
+ });
411
+ return textResponse({
412
+ source: source.relative,
413
+ output: output.relative,
414
+ intermediateFormat: format,
415
+ comparison: comparison.content[0]?.type === "text" ? JSON.parse(comparison.content[0].text) : comparison,
416
+ });
417
+ }
418
+ catch (error) {
419
+ return errorResponse(error instanceof Error ? error.message : String(error));
420
+ }
421
+ }
422
+ async function listRecoverySessions() {
423
+ const sessionsRoot = join(asepriteUserDataRoot(), "sessions");
424
+ const entries = await readdir(sessionsRoot, { withFileTypes: true }).catch(() => []);
425
+ const sessions = [];
426
+ for (const entry of entries) {
427
+ if (!entry.isDirectory())
428
+ continue;
429
+ const path = join(sessionsRoot, entry.name);
430
+ const info = await stat(path);
431
+ const documents = (await readdir(path, { withFileTypes: true }).catch(() => [])).filter((child) => child.isDirectory()).map((child) => child.name);
432
+ sessions.push({
433
+ id: entry.name,
434
+ modifiedAt: info.mtime.toISOString(),
435
+ bytes: await directorySize(path),
436
+ documents,
437
+ activePidFile: existsSync(join(path, "pid")),
438
+ });
439
+ }
440
+ return sessions.sort((a, b) => String(b.modifiedAt).localeCompare(String(a.modifiedAt)));
441
+ }
442
+ export async function asepriteRecovery(config, registry, processManager, input) {
443
+ try {
444
+ const sessionsRoot = join(asepriteUserDataRoot(), "sessions");
445
+ if (input.action === "list")
446
+ return textResponse({ sessions: await listRecoverySessions() });
447
+ if (input.action === "open_recovery_ui") {
448
+ const executable = await resolveAsepriteExecutable(config);
449
+ const command = `"${executable.replace(/"/g, '\\"')}"`;
450
+ return textResponse(processManager.startProcess({
451
+ workspaceId: input.workspaceId,
452
+ command,
453
+ useShell: false,
454
+ }));
455
+ }
456
+ const id = input.sessionId?.trim();
457
+ if (!id || !/^[a-zA-Z0-9._-]+$/.test(id))
458
+ throw new Error("A valid sessionId is required.");
459
+ const source = join(sessionsRoot, id);
460
+ if (!existsSync(source))
461
+ throw new Error(`Recovery session ${id} was not found.`);
462
+ const sourceInfo = await lstat(source);
463
+ if (!sourceInfo.isDirectory() || sourceInfo.isSymbolicLink())
464
+ throw new Error("Recovery session is not a real directory.");
465
+ if (input.action === "archive") {
466
+ if (!input.outputDirectory)
467
+ throw new Error("outputDirectory is required.");
468
+ const target = workspacePath(registry, input.workspaceId, `${input.outputDirectory.replace(/[\\/]$/, "")}/${id}`);
469
+ await cp(source, target.absolute, { recursive: true, force: true });
470
+ return textResponse({ archived: id, output: target.relative, note: "Open Aseprite's Recovery UI to reconstruct the archived native session." });
471
+ }
472
+ if (!input.allowGlobalWrite)
473
+ throw new Error("allowGlobalWrite=true is required to discard an Aseprite recovery session.");
474
+ await rm(source, { recursive: true, force: true });
475
+ return textResponse({ discarded: id });
476
+ }
477
+ catch (error) {
478
+ return errorResponse(error instanceof Error ? error.message : String(error));
479
+ }
480
+ }
481
+ async function readExtensionManifests() {
482
+ const root = join(asepriteUserDataRoot(), "extensions");
483
+ const iniPath = join(asepriteUserDataRoot(), "aseprite.ini");
484
+ const ini = await readFile(iniPath, "utf8").catch(() => "");
485
+ const enabledMap = new Map();
486
+ const section = ini.match(/(?:^|\r?\n)\[extensions\]\r?\n([\s\S]*?)(?=\r?\n\[|$)/i)?.[1] ?? "";
487
+ for (const line of section.split(/\r?\n/)) {
488
+ const match = line.match(/^([^=]+)=(true|false|yes|no|1|0)$/i);
489
+ if (match)
490
+ enabledMap.set(match[1].trim(), /^(true|yes|1)$/i.test(match[2]));
491
+ }
492
+ const entries = await readdir(root, { withFileTypes: true }).catch(() => []);
493
+ const extensions = [];
494
+ for (const entry of entries) {
495
+ if (!entry.isDirectory())
496
+ continue;
497
+ const manifestPath = join(root, entry.name, "package.json");
498
+ let manifest = {};
499
+ try {
500
+ manifest = JSON.parse(await readFile(manifestPath, "utf8"));
501
+ }
502
+ catch {
503
+ manifest = { invalidManifest: true };
504
+ }
505
+ const name = String(manifest.name ?? entry.name);
506
+ extensions.push({
507
+ directory: entry.name,
508
+ name,
509
+ displayName: manifest.displayName,
510
+ version: manifest.version,
511
+ description: manifest.description,
512
+ enabled: enabledMap.get(name) ?? true,
513
+ contributes: manifest.contributes,
514
+ invalidManifest: manifest.invalidManifest,
515
+ });
516
+ }
517
+ return extensions;
518
+ }
519
+ async function setExtensionEnabled(name, enabled) {
520
+ const iniPath = join(asepriteUserDataRoot(), "aseprite.ini");
521
+ let ini = await readFile(iniPath, "utf8").catch(() => "");
522
+ const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
523
+ const sectionPattern = /(^|\r?\n)\[extensions\]\r?\n([\s\S]*?)(?=\r?\n\[|$)/i;
524
+ const match = ini.match(sectionPattern);
525
+ const value = `${name}=${enabled ? "true" : "false"}`;
526
+ if (match) {
527
+ let body = match[2];
528
+ const keyPattern = new RegExp(`^${escaped}=.*$`, "mi");
529
+ body = keyPattern.test(body) ? body.replace(keyPattern, value) : `${body.trimEnd()}\r\n${value}\r\n`;
530
+ ini = ini.replace(sectionPattern, `${match[1]}[extensions]\r\n${body}`);
531
+ }
532
+ else {
533
+ ini = `${ini.trimEnd()}\r\n\r\n[extensions]\r\n${value}\r\n`;
534
+ }
535
+ await writeFile(iniPath, ini, "utf8");
536
+ }
537
+ export async function asepriteExtensions(registry, input) {
538
+ try {
539
+ registry.getWorkspace(input.workspaceId);
540
+ const root = asepriteUserDataRoot();
541
+ if (input.action === "list_extensions")
542
+ return textResponse({ root, extensions: await readExtensionManifests() });
543
+ if (input.action === "list_resources") {
544
+ const resources = {};
545
+ for (const name of ["extensions", "palettes", "scripts", "themes", "brushes", "files", "sessions"]) {
546
+ const path = join(root, name);
547
+ resources[name] = (await readdir(path).catch(() => [])).sort();
548
+ }
549
+ const standalone = (await readdir(root).catch(() => [])).filter((name) => /\.(aseprite-brushes|aseprite-layouts|ini)$/i.test(name));
550
+ return textResponse({ root, resources, standalone });
551
+ }
552
+ if (input.action === "startup_errors") {
553
+ const logPath = join(root, "Aseprite.log");
554
+ const lines = (await readFile(logPath, "utf8").catch(() => "")).split(/\r?\n/);
555
+ return textResponse({ logPath, errors: lines.filter((line) => /error|failed|exception/i.test(line)).slice(-200) });
556
+ }
557
+ if (!input.allowGlobalWrite)
558
+ throw new Error("allowGlobalWrite=true is required for extension changes.");
559
+ const extensionsRoot = join(root, "extensions");
560
+ await mkdir(extensionsRoot, { recursive: true });
561
+ if (input.action === "install") {
562
+ if (!input.sourceDirectoryPath)
563
+ throw new Error("sourceDirectoryPath is required.");
564
+ const source = workspacePath(registry, input.workspaceId, input.sourceDirectoryPath);
565
+ const info = await lstat(source.absolute);
566
+ if (!info.isDirectory() || info.isSymbolicLink())
567
+ throw new Error("Extension source must be a real workspace directory.");
568
+ await assertTreeContainsNoSymlinks(source.absolute);
569
+ const manifest = JSON.parse(await readFile(join(source.absolute, "package.json"), "utf8"));
570
+ const name = safeSegment(String(manifest.name ?? basename(source.absolute)));
571
+ const target = join(extensionsRoot, name);
572
+ await cp(source.absolute, target, { recursive: true, force: true, dereference: false });
573
+ await setExtensionEnabled(String(manifest.name ?? name), true);
574
+ return textResponse({ installed: manifest.name ?? name, target, restartRequired: true });
575
+ }
576
+ const name = input.extensionName?.trim();
577
+ if (!name)
578
+ throw new Error("extensionName is required.");
579
+ const extensions = await readExtensionManifests();
580
+ const extension = extensions.find((item) => item.name === name || item.directory === name);
581
+ if (!extension)
582
+ throw new Error(`Extension ${name} was not found.`);
583
+ if (input.action === "enable" || input.action === "disable") {
584
+ await setExtensionEnabled(extension.name, input.action === "enable");
585
+ return textResponse({ extension: extension.name, enabled: input.action === "enable", restartRequired: true });
586
+ }
587
+ await rm(join(extensionsRoot, extension.directory), { recursive: true, force: true });
588
+ await setExtensionEnabled(extension.name, false);
589
+ return textResponse({ removed: extension.name, restartRequired: true });
590
+ }
591
+ catch (error) {
592
+ return errorResponse(error instanceof Error ? error.message : String(error));
593
+ }
594
+ }