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,368 @@
1
+ import { assertInteger, assertPositiveInteger, errorResponse, luaString, openSpriteScript, runLua, textResponse, workspacePath, } from "./aseprite-tools.js";
2
+ const MAX_READ_PIXELS = 65_536;
3
+ const MAX_ANALYSIS_PIXELS = 4_194_304;
4
+ function normalizeRegion(region) {
5
+ if (!region)
6
+ return undefined;
7
+ return {
8
+ x: assertInteger(region.x, "region.x"),
9
+ y: assertInteger(region.y, "region.y"),
10
+ width: assertPositiveInteger(region.width, "region.width"),
11
+ height: assertPositiveInteger(region.height, "region.height"),
12
+ };
13
+ }
14
+ export async function asepriteReadPixels(config, registry, input) {
15
+ try {
16
+ const file = workspacePath(registry, input.workspaceId, input.filePath);
17
+ const frame = input.frame === undefined ? 1 : assertPositiveInteger(input.frame, "frame");
18
+ const region = normalizeRegion(input.region);
19
+ const format = input.format ?? "rows";
20
+ const result = await runLua(config, registry, input.workspaceId, `
21
+ ${openSpriteScript(file.absolute)}
22
+ local layer = ${input.layer ? `find_layer(sprite.layers, ${luaString(input.layer)})` : "sprite.layers[1]"}
23
+ if layer == nil or layer.isGroup then fail("A drawable layer was not found") end
24
+ if ${frame} > #sprite.frames then fail("Frame is outside the sprite") end
25
+ local x0 = ${region?.x ?? 0}
26
+ local y0 = ${region?.y ?? 0}
27
+ local width = ${region?.width ?? "sprite.width"}
28
+ local height = ${region?.height ?? "sprite.height"}
29
+ if x0 < 0 or y0 < 0 or x0 + width > sprite.width or y0 + height > sprite.height then fail("Region is outside the sprite") end
30
+ if width * height > ${MAX_READ_PIXELS} then fail("Requested region exceeds ${MAX_READ_PIXELS} pixels") end
31
+ local format = ${luaString(format)}
32
+ local rows = {}
33
+ local index_rows = {}
34
+ local points = {}
35
+ local histogram = {}
36
+ local transparent = 0
37
+ local semi_transparent = 0
38
+ local bounds = nil
39
+ for y = y0, y0 + height - 1 do
40
+ local row = {}
41
+ local index_row = {}
42
+ for x = x0, x0 + width - 1 do
43
+ local color = canvas_pixel(sprite, layer, ${frame}, x, y)
44
+ local hex = rgba_hex(color)
45
+ histogram[hex] = (histogram[hex] or 0) + 1
46
+ if color.a == 0 then transparent = transparent + 1
47
+ elseif color.a < 255 then semi_transparent = semi_transparent + 1 end
48
+ if color.a > 0 then
49
+ if bounds == nil then bounds = { x=x, y=y, right=x, bottom=y }
50
+ else
51
+ if x < bounds.x then bounds.x = x end
52
+ if y < bounds.y then bounds.y = y end
53
+ if x > bounds.right then bounds.right = x end
54
+ if y > bounds.bottom then bounds.bottom = y end
55
+ end
56
+ end
57
+ if format == "rows" then
58
+ table.insert(row, hex)
59
+ if color.index ~= nil then table.insert(index_row, color.index) end
60
+ elseif format == "points" and (${input.includeTransparent === true ? "true" : "false"} or color.a > 0) then
61
+ table.insert(points, { x=x, y=y, color=hex, index=color.index })
62
+ end
63
+ end
64
+ if format == "rows" then
65
+ table.insert(rows, row)
66
+ if #index_row > 0 then table.insert(index_rows, index_row) end
67
+ end
68
+ end
69
+ if bounds ~= nil then
70
+ bounds.width = bounds.right - bounds.x + 1
71
+ bounds.height = bounds.bottom - bounds.y + 1
72
+ bounds.right = nil
73
+ bounds.bottom = nil
74
+ end
75
+ local histogram_rows = {}
76
+ for color, count in pairs(histogram) do table.insert(histogram_rows, { color=color, count=count }) end
77
+ table.sort(histogram_rows, function(a, b) if a.count == b.count then return a.color < b.color else return a.count > b.count end end)
78
+ emit_result({
79
+ file=${luaString(file.relative)}, layer=layer.name, frame=${frame},
80
+ region={x=x0,y=y0,width=width,height=height}, format=format,
81
+ rows=format == "rows" and rows or nil,
82
+ palette_indices=(format == "rows" and #index_rows > 0) and index_rows or nil,
83
+ points=format == "points" and points or nil,
84
+ histogram=histogram_rows,
85
+ alpha_bounds=bounds,
86
+ transparent_pixels=transparent,
87
+ semi_transparent_pixels=semi_transparent,
88
+ })
89
+ sprite:close()
90
+ `);
91
+ return textResponse(result);
92
+ }
93
+ catch (error) {
94
+ return errorResponse(error instanceof Error ? error.message : String(error));
95
+ }
96
+ }
97
+ export async function asepriteAuditSprite(config, registry, input) {
98
+ try {
99
+ const file = workspacePath(registry, input.workspaceId, input.filePath);
100
+ const neighbors = input.isolatedNeighborMode === 4 ? 4 : 8;
101
+ const result = await runLua(config, registry, input.workspaceId, `
102
+ ${openSpriteScript(file.absolute)}
103
+ if sprite.width * sprite.height * #sprite.frames > ${MAX_ANALYSIS_PIXELS} then fail("Sprite is too large for a full audit") end
104
+ local issues = {}
105
+ local colors = {}
106
+ local frame_rows = {}
107
+ local duplicate_map = {}
108
+ local empty_frames = {}
109
+ local semi = 0
110
+ local isolated = 0
111
+ local occupied_total = 0
112
+ local linked_images = {}
113
+ for _, cel in ipairs(sprite.cels) do
114
+ local id = tostring(cel.image.id or cel.image)
115
+ linked_images[id] = (linked_images[id] or 0) + 1
116
+ end
117
+ for frame_number = 1, #sprite.frames do
118
+ local render = Image(sprite.spec)
119
+ render:clear()
120
+ render:drawSprite(sprite, frame_number, Point(0, 0))
121
+ local hash_parts = {}
122
+ local bounds = nil
123
+ local occupied = 0
124
+ local frame_semi = 0
125
+ local frame_isolated = 0
126
+ for y = 0, sprite.height - 1 do
127
+ for x = 0, sprite.width - 1 do
128
+ local color = pixel_rgba(sprite, render:getPixel(x, y))
129
+ local hex = rgba_hex(color)
130
+ table.insert(hash_parts, hex)
131
+ colors[hex] = (colors[hex] or 0) + 1
132
+ if color.a > 0 then
133
+ occupied = occupied + 1
134
+ occupied_total = occupied_total + 1
135
+ if color.a < 255 then semi = semi + 1; frame_semi = frame_semi + 1 end
136
+ if bounds == nil then bounds = {x=x,y=y,right=x,bottom=y}
137
+ else
138
+ if x < bounds.x then bounds.x=x end
139
+ if y < bounds.y then bounds.y=y end
140
+ if x > bounds.right then bounds.right=x end
141
+ if y > bounds.bottom then bounds.bottom=y end
142
+ end
143
+ local count = 0
144
+ for dy=-1,1 do for dx=-1,1 do
145
+ if not (dx == 0 and dy == 0) and (${neighbors} == 8 or dx == 0 or dy == 0) then
146
+ local nx=x+dx local ny=y+dy
147
+ if nx>=0 and ny>=0 and nx<sprite.width and ny<sprite.height then
148
+ if pixel_rgba(sprite, render:getPixel(nx, ny)).a > 0 then count=count+1 end
149
+ end
150
+ end
151
+ end end
152
+ if count == 0 then isolated=isolated+1; frame_isolated=frame_isolated+1 end
153
+ end
154
+ end
155
+ end
156
+ if bounds ~= nil then
157
+ bounds.width=bounds.right-bounds.x+1 bounds.height=bounds.bottom-bounds.y+1 bounds.right=nil bounds.bottom=nil
158
+ else table.insert(empty_frames, frame_number) end
159
+ local hash = table.concat(hash_parts)
160
+ if duplicate_map[hash] == nil then duplicate_map[hash] = {frame_number}
161
+ else table.insert(duplicate_map[hash], frame_number) end
162
+ table.insert(frame_rows, {
163
+ frame=frame_number,
164
+ duration_ms=math.floor(sprite.frames[frame_number].duration*1000+0.5),
165
+ occupied_pixels=occupied,
166
+ occupancy=occupied/(sprite.width*sprite.height),
167
+ alpha_bounds=bounds,
168
+ semi_transparent_pixels=frame_semi,
169
+ isolated_pixels=frame_isolated,
170
+ })
171
+ end
172
+ local duplicates = {}
173
+ for _, frames in pairs(duplicate_map) do if #frames > 1 then table.insert(duplicates, frames) end end
174
+ local palette = {}
175
+ local unused_palette = {}
176
+ local duplicate_palette = {}
177
+ if #sprite.palettes > 0 then
178
+ local seen = {}
179
+ local pal = sprite.palettes[1]
180
+ for index=0,#pal-1 do
181
+ local c=pal:getColor(index)
182
+ local hex=rgba_hex({r=c.red,g=c.green,b=c.blue,a=(index==sprite.transparentColor and 0 or c.alpha)})
183
+ table.insert(palette,{index=index,color=hex})
184
+ if colors[hex] == nil then table.insert(unused_palette,index) end
185
+ if seen[hex] ~= nil then table.insert(duplicate_palette,{index=index,duplicate_of=seen[hex],color=hex}) else seen[hex]=index end
186
+ end
187
+ end
188
+ local overlapping_tags = {}
189
+ for i=1,#sprite.tags do for j=i+1,#sprite.tags do
190
+ local a=sprite.tags[i] local b=sprite.tags[j]
191
+ if a.fromFrame.frameNumber <= b.toFrame.frameNumber and b.fromFrame.frameNumber <= a.toFrame.frameNumber then
192
+ table.insert(overlapping_tags,{first=a.name,second=b.name})
193
+ end
194
+ end end
195
+ local linked_groups = 0
196
+ for _, count in pairs(linked_images) do if count > 1 then linked_groups=linked_groups+1 end end
197
+ if #empty_frames > 0 then table.insert(issues,{severity="warning",code="empty_frames",frames=empty_frames}) end
198
+ if #duplicates > 0 then table.insert(issues,{severity="info",code="duplicate_frames",groups=duplicates}) end
199
+ if semi > 0 then table.insert(issues,{severity="warning",code="semi_transparent_pixels",count=semi}) end
200
+ if isolated > 0 then table.insert(issues,{severity="info",code="isolated_pixels",count=isolated}) end
201
+ if #unused_palette > 0 then table.insert(issues,{severity="info",code="unused_palette_entries",indices=unused_palette}) end
202
+ if #duplicate_palette > 0 then table.insert(issues,{severity="info",code="duplicate_palette_entries",entries=duplicate_palette}) end
203
+ if #overlapping_tags > 0 then table.insert(issues,{severity="warning",code="overlapping_tags",pairs=overlapping_tags}) end
204
+ if #sprite.tags == 0 and #sprite.frames > 1 then table.insert(issues,{severity="warning",code="animation_without_tags"}) end
205
+ local average_occupancy = occupied_total / (sprite.width*sprite.height*#sprite.frames)
206
+ if average_occupancy < 0.05 then table.insert(issues,{severity="info",code="oversized_canvas",average_occupancy=average_occupancy}) end
207
+ emit_result({
208
+ file=${luaString(file.relative)}, width=sprite.width, height=sprite.height,
209
+ frames=frame_rows, issues=issues, colors_used=colors, palette=palette,
210
+ linked_cel_groups=linked_groups, average_occupancy=average_occupancy,
211
+ })
212
+ sprite:close()
213
+ `);
214
+ return textResponse(result);
215
+ }
216
+ catch (error) {
217
+ return errorResponse(error instanceof Error ? error.message : String(error));
218
+ }
219
+ }
220
+ export async function asepriteCompareDocuments(config, registry, input) {
221
+ try {
222
+ const reference = workspacePath(registry, input.workspaceId, input.referencePath);
223
+ const candidate = workspacePath(registry, input.workspaceId, input.candidatePath);
224
+ const result = await runLua(config, registry, input.workspaceId, `
225
+ local reference = app.open(${luaString(reference.absolute)})
226
+ if reference == nil then fail("Unable to open reference sprite") end
227
+ local candidate = app.open(${luaString(candidate.absolute)})
228
+ if candidate == nil then fail("Unable to open candidate sprite") end
229
+ if math.max(reference.width,candidate.width)*math.max(reference.height,candidate.height)*math.max(#reference.frames,#candidate.frames) > ${MAX_ANALYSIS_PIXELS} then fail("Documents are too large for full comparison") end
230
+ local differences = {}
231
+ local function add(code, expected, actual) table.insert(differences,{code=code,expected=expected,actual=actual}) end
232
+ if reference.width ~= candidate.width then add("width",reference.width,candidate.width) end
233
+ if reference.height ~= candidate.height then add("height",reference.height,candidate.height) end
234
+ if reference.colorMode ~= candidate.colorMode then add("color_mode",color_mode_name(reference.colorMode),color_mode_name(candidate.colorMode)) end
235
+ if #reference.frames ~= #candidate.frames then add("frame_count",#reference.frames,#candidate.frames) end
236
+ local ref_summary=sprite_summary(reference)
237
+ local cand_summary=sprite_summary(candidate)
238
+ local function encode(value) return json.encode(value) end
239
+ if encode(ref_summary.layers) ~= encode(cand_summary.layers) then add("layers",ref_summary.layers,cand_summary.layers) end
240
+ if encode(ref_summary.frames) ~= encode(cand_summary.frames) then add("frame_timing",ref_summary.frames,cand_summary.frames) end
241
+ if encode(ref_summary.tags) ~= encode(cand_summary.tags) then add("tags",ref_summary.tags,cand_summary.tags) end
242
+ if encode(ref_summary.slices) ~= encode(cand_summary.slices) then add("slices",ref_summary.slices,cand_summary.slices) end
243
+ local palette_changes = {}
244
+ local ref_pal = #reference.palettes > 0 and reference.palettes[1] or nil
245
+ local cand_pal = #candidate.palettes > 0 and candidate.palettes[1] or nil
246
+ local pal_count = math.max(ref_pal and #ref_pal or 0,cand_pal and #cand_pal or 0)
247
+ for index=0,pal_count-1 do
248
+ local a=ref_pal and index<#ref_pal and ref_pal:getColor(index) or nil
249
+ local b=cand_pal and index<#cand_pal and cand_pal:getColor(index) or nil
250
+ local ah=a and rgba_hex({r=a.red,g=a.green,b=a.blue,a=a.alpha}) or nil
251
+ local bh=b and rgba_hex({r=b.red,g=b.green,b=b.blue,a=b.alpha}) or nil
252
+ if ah~=bh then table.insert(palette_changes,{index=index,reference=ah,candidate=bh}) end
253
+ end
254
+ local pixel_frames = {}
255
+ local changed_total = 0
256
+ if ${input.comparePixels === false ? "false" : "true"} then
257
+ local max_frames=math.max(#reference.frames,#candidate.frames)
258
+ local max_width=math.max(reference.width,candidate.width)
259
+ local max_height=math.max(reference.height,candidate.height)
260
+ for frame=1,max_frames do
261
+ local a=Image{width=max_width,height=max_height,colorMode=ColorMode.RGB}
262
+ local b=Image{width=max_width,height=max_height,colorMode=ColorMode.RGB}
263
+ a:clear() b:clear()
264
+ if frame<=#reference.frames then a:drawSprite(reference,frame,Point(0,0)) end
265
+ if frame<=#candidate.frames then b:drawSprite(candidate,frame,Point(0,0)) end
266
+ local changed=0
267
+ local bounds=nil
268
+ for y=0,max_height-1 do for x=0,max_width-1 do
269
+ if a:getPixel(x,y) ~= b:getPixel(x,y) then
270
+ changed=changed+1 changed_total=changed_total+1
271
+ if bounds==nil then bounds={x=x,y=y,right=x,bottom=y}
272
+ else
273
+ if x<bounds.x then bounds.x=x end if y<bounds.y then bounds.y=y end
274
+ if x>bounds.right then bounds.right=x end if y>bounds.bottom then bounds.bottom=y end
275
+ end
276
+ end
277
+ end end
278
+ if bounds~=nil then bounds.width=bounds.right-bounds.x+1 bounds.height=bounds.bottom-bounds.y+1 bounds.right=nil bounds.bottom=nil end
279
+ table.insert(pixel_frames,{frame=frame,changed_pixels=changed,bounds=bounds})
280
+ end
281
+ end
282
+ emit_result({
283
+ reference=${luaString(reference.relative)},candidate=${luaString(candidate.relative)},
284
+ exact_match=#differences==0 and #palette_changes==0 and changed_total==0,
285
+ structural_differences=differences,palette_changes=palette_changes,
286
+ changed_pixels=changed_total,pixel_frames=pixel_frames,
287
+ })
288
+ reference:close() candidate:close()
289
+ `);
290
+ return textResponse(result);
291
+ }
292
+ catch (error) {
293
+ return errorResponse(error instanceof Error ? error.message : String(error));
294
+ }
295
+ }
296
+ export async function asepriteAnimationAudit(config, registry, input) {
297
+ try {
298
+ const file = workspacePath(registry, input.workspaceId, input.filePath);
299
+ const result = await runLua(config, registry, input.workspaceId, `
300
+ ${openSpriteScript(file.absolute)}
301
+ if sprite.width*sprite.height*#sprite.frames > ${MAX_ANALYSIS_PIXELS} then fail("Animation is too large for a full audit") end
302
+ local from_frame=1 local to_frame=#sprite.frames
303
+ ${input.tag ? `
304
+ local selected_tag=nil
305
+ for _,tag in ipairs(sprite.tags) do if tag.name==${luaString(input.tag)} then selected_tag=tag break end end
306
+ if selected_tag==nil then fail("Animation tag was not found") end
307
+ from_frame=selected_tag.fromFrame.frameNumber to_frame=selected_tag.toFrame.frameNumber
308
+ ` : ""}
309
+ local anchor_layer=${input.anchorLayer ? `find_layer(sprite.layers,${luaString(input.anchorLayer)})` : "nil"}
310
+ if ${input.anchorLayer ? "true" : "false"} and (anchor_layer==nil or anchor_layer.isGroup) then fail("Anchor layer was not found") end
311
+ local frames={}
312
+ local previous=nil
313
+ local first=nil
314
+ local duplicate_pairs={}
315
+ local duration_sum=0
316
+ for frame=from_frame,to_frame do
317
+ local render=Image(sprite.spec) render:clear() render:drawSprite(sprite,frame,Point(0,0))
318
+ local bounds=nil local occupied=0 local sum_x=0 local sum_y=0 local changed=0
319
+ local anchor_bounds=nil
320
+ for y=0,sprite.height-1 do for x=0,sprite.width-1 do
321
+ local c=pixel_rgba(sprite,render:getPixel(x,y))
322
+ if c.a>0 then
323
+ occupied=occupied+1 sum_x=sum_x+x sum_y=sum_y+y
324
+ if bounds==nil then bounds={x=x,y=y,right=x,bottom=y}
325
+ else if x<bounds.x then bounds.x=x end if y<bounds.y then bounds.y=y end if x>bounds.right then bounds.right=x end if y>bounds.bottom then bounds.bottom=y end end
326
+ end
327
+ if previous~=nil and render:getPixel(x,y)~=previous:getPixel(x,y) then changed=changed+1 end
328
+ if anchor_layer~=nil then
329
+ local ac=canvas_pixel(sprite,anchor_layer,frame,x,y)
330
+ if ac.a>0 then
331
+ if anchor_bounds==nil then anchor_bounds={x=x,y=y,right=x,bottom=y}
332
+ else if x<anchor_bounds.x then anchor_bounds.x=x end if y<anchor_bounds.y then anchor_bounds.y=y end if x>anchor_bounds.right then anchor_bounds.right=x end if y>anchor_bounds.bottom then anchor_bounds.bottom=y end end
333
+ end
334
+ end
335
+ end end
336
+ if bounds~=nil then bounds.width=bounds.right-bounds.x+1 bounds.height=bounds.bottom-bounds.y+1 bounds.center_x=sum_x/occupied bounds.center_y=sum_y/occupied bounds.right=nil bounds.bottom=nil end
337
+ if anchor_bounds~=nil then anchor_bounds.width=anchor_bounds.right-anchor_bounds.x+1 anchor_bounds.height=anchor_bounds.bottom-anchor_bounds.y+1 anchor_bounds.right=nil anchor_bounds.bottom=nil end
338
+ local duration=math.floor(sprite.frames[frame].duration*1000+0.5) duration_sum=duration_sum+duration
339
+ if previous~=nil and changed==0 then table.insert(duplicate_pairs,{previous=frame-1,current=frame}) end
340
+ table.insert(frames,{frame=frame,duration_ms=duration,bounds=bounds,anchor_bounds=anchor_bounds,changed_from_previous=changed,motion_ratio=changed/(sprite.width*sprite.height)})
341
+ if first==nil then first=Image(render) end previous=Image(render)
342
+ end
343
+ local loop_difference=0
344
+ if first~=nil and previous~=nil then for y=0,sprite.height-1 do for x=0,sprite.width-1 do if first:getPixel(x,y)~=previous:getPixel(x,y) then loop_difference=loop_difference+1 end end end end
345
+ local average_duration=duration_sum/#frames
346
+ local issues={}
347
+ for _,row in ipairs(frames) do
348
+ if row.duration_ms>average_duration*2 or row.duration_ms<average_duration*0.5 then table.insert(issues,{severity="info",code="duration_outlier",frame=row.frame,duration_ms=row.duration_ms,average_ms=average_duration}) end
349
+ end
350
+ for i=2,#frames do
351
+ local a=frames[i-1].bounds local b=frames[i].bounds
352
+ if a~=nil and b~=nil then
353
+ local dx=b.center_x-a.center_x local dy=b.center_y-a.center_y
354
+ frames[i].center_delta={x=dx,y=dy}
355
+ frames[i].baseline_delta=b.y+b.height-(a.y+a.height)
356
+ end
357
+ end
358
+ if #duplicate_pairs>0 then table.insert(issues,{severity="info",code="duplicate_consecutive_frames",pairs=duplicate_pairs}) end
359
+ if loop_difference>sprite.width*sprite.height*0.25 then table.insert(issues,{severity="warning",code="loop_discontinuity",changed_pixels=loop_difference}) end
360
+ emit_result({file=${luaString(file.relative)},from=from_frame,to=to_frame,frames=frames,average_duration_ms=average_duration,loop_changed_pixels=loop_difference,issues=issues})
361
+ sprite:close()
362
+ `);
363
+ return textResponse(result);
364
+ }
365
+ catch (error) {
366
+ return errorResponse(error instanceof Error ? error.message : String(error));
367
+ }
368
+ }