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.
- package/LICENSE +21 -21
- package/README.md +366 -233
- package/addons/auvrynt_bridge/auvrynt_bridge.gd +500 -0
- package/addons/auvrynt_bridge/plugin.cfg +7 -0
- package/bin/auvrynt-launcher.cjs +77 -0
- package/dist/artifact-registry.js +1 -0
- package/dist/aseprite-tools.js +1 -0
- package/dist/auth/connection-registry.js +145 -0
- package/dist/auth/connection-status.js +176 -0
- package/dist/auth/oauth-provider.js +617 -0
- package/dist/auth/room-registry.js +131 -0
- package/dist/auth/session-registry.js +531 -0
- package/dist/background-lifecycle.js +1 -0
- package/dist/blender-client.js +1 -109
- package/dist/blender-tools.js +1 -930
- package/dist/browser-stability.js +1 -0
- package/dist/cli/commands/help-command.js +10 -0
- package/dist/cli/commands/init-command.js +190 -0
- package/dist/cli/commands/integration-commands.js +88 -0
- package/dist/cli/commands/serve-command.js +83 -0
- package/dist/cli/commands/setup-command.js +81 -0
- package/dist/cli/commands/status-commands.js +166 -0
- package/dist/cli/commands/tunnel-command.js +127 -0
- package/dist/cli/commands/user-config-commands.js +105 -0
- package/dist/cli/dashboard-actions.js +516 -0
- package/dist/cli/dashboard-native-actions.js +282 -0
- package/dist/cli/foreground-server.js +270 -0
- package/dist/cli/instance-control.js +21 -0
- package/dist/cli/instance-lock.js +123 -0
- package/dist/cli/integration-bootstrap.js +206 -0
- package/dist/cli/lifecycle-manager.js +493 -0
- package/dist/cli/runtime-support.js +74 -0
- package/dist/cli/serena-detected-default.js +27 -0
- package/dist/cli/tunnel-health-monitor.js +182 -0
- package/dist/cli.js +82 -739
- package/dist/config.js +1 -243
- package/dist/connection-registry.js +1 -73
- package/dist/connection-status.js +1 -139
- package/dist/control-retry.js +1 -0
- package/dist/crash-recovery.js +1 -0
- package/dist/db/client.js +16 -3
- package/dist/db/schema.js +30 -0
- package/dist/dotnet-tools.js +1 -223
- package/dist/git-worktrees.js +1 -134
- package/dist/git.js +1 -41
- package/dist/godot-animation-tilemap.js +1 -82
- package/dist/godot-csharp-build.js +1 -93
- package/dist/godot-csharp-project.js +1 -157
- package/dist/godot-csharp-runner.js +1 -146
- package/dist/godot-csharp-semantic.js +1 -161
- package/dist/godot-csharp-validate.js +1 -71
- package/dist/godot-dotnet-env.js +1 -169
- package/dist/godot-editor-bridge.js +1 -140
- package/dist/godot-gdscript.js +1 -824
- package/dist/godot-project-settings.js +1 -223
- package/dist/godot-runtime-testing.js +1 -249
- package/dist/godot-tools.js +1 -183
- package/dist/http-rate-limit.js +1 -0
- package/dist/http-server-hardening.js +1 -0
- package/dist/image-tools.js +1 -157
- package/dist/infrastructure/command-reference.js +32 -0
- package/dist/infrastructure/config.js +424 -0
- package/dist/infrastructure/context7-auth.js +55 -0
- package/dist/infrastructure/http-rate-limit.js +42 -0
- package/dist/infrastructure/http-server-hardening.js +23 -0
- package/dist/infrastructure/integration-queue.js +46 -0
- package/dist/infrastructure/logger.js +129 -0
- package/dist/infrastructure/mcp-event-store.js +103 -0
- package/dist/infrastructure/ngrok-auth-pool.js +208 -0
- package/dist/infrastructure/request-context.js +14 -0
- package/dist/infrastructure/shutdown.js +37 -0
- package/dist/infrastructure/sse-heartbeat.js +47 -0
- package/dist/infrastructure/tool-capabilities.js +67 -0
- package/dist/infrastructure/tool-result-budget.js +175 -0
- package/dist/infrastructure/user-config.js +167 -0
- package/dist/integration-discovery.js +1 -98
- package/dist/integration-queue.js +1 -0
- package/dist/integrations/agent-reach/agent-reach-tools.js +196 -0
- package/dist/integrations/agent-reach/native-channels.js +468 -0
- package/dist/integrations/aseprite/aseprite-analysis-tools.js +368 -0
- package/dist/integrations/aseprite/aseprite-editing-tools.js +647 -0
- package/dist/integrations/aseprite/aseprite-live-tools.js +297 -0
- package/dist/integrations/aseprite/aseprite-safety-tools.js +594 -0
- package/dist/integrations/aseprite/aseprite-specialized-tools.js +289 -0
- package/dist/integrations/aseprite/aseprite-tools.js +837 -0
- package/dist/integrations/blender/blender-catalog-mesh.js +593 -0
- package/dist/integrations/blender/blender-catalog-object.js +906 -0
- package/dist/integrations/blender/blender-catalog-scene.js +266 -0
- package/dist/integrations/blender/blender-catalog-select.js +581 -0
- package/dist/integrations/blender/blender-catalog-stubs.js +7512 -0
- package/dist/integrations/blender/blender-catalog.js +165 -0
- package/dist/integrations/blender/blender-client.js +105 -0
- package/dist/integrations/blender/blender-tools.js +2243 -0
- package/dist/integrations/context7/context7-tools.js +106 -0
- package/dist/integrations/dotnet/dotnet-tools.js +195 -0
- package/dist/integrations/godot/godot-animation-tilemap.js +74 -0
- package/dist/integrations/godot/godot-csharp-build.js +91 -0
- package/dist/integrations/godot/godot-csharp-project.js +155 -0
- package/dist/integrations/godot/godot-csharp-runner.js +118 -0
- package/dist/integrations/godot/godot-csharp-semantic.js +146 -0
- package/dist/integrations/godot/godot-csharp-validate.js +71 -0
- package/dist/integrations/godot/godot-dotnet-env.js +134 -0
- package/dist/integrations/godot/godot-editor-bridge.js +328 -0
- package/dist/integrations/godot/godot-gdscript.js +536 -0
- package/dist/integrations/godot/godot-project-settings.js +178 -0
- package/dist/integrations/godot/godot-runtime-testing.js +263 -0
- package/dist/integrations/godot/godot-tools.js +193 -0
- package/dist/integrations/images/image-tools.js +414 -0
- package/dist/integrations/images/png-codec.js +251 -0
- package/dist/integrations/images/view-image.js +99 -0
- package/dist/integrations/images/window-capture.js +148 -0
- package/dist/integrations/integration-discovery.js +185 -0
- package/dist/integrations/obsidian/obsidian-tools.js +205 -0
- package/dist/integrations/playwright/browser-session.js +516 -0
- package/dist/integrations/playwright/browser-stability.js +36 -0
- package/dist/integrations/playwright/playwright-runtime.js +105 -0
- package/dist/integrations/playwright/web-tools.js +504 -0
- package/dist/integrations/roblox/roblox-helpers.js +381 -0
- package/dist/integrations/roblox/roblox-studio-client.js +112 -0
- package/dist/integrations/roblox/roblox-tools.js +106 -0
- package/dist/integrations/serena/serena-manager.js +464 -0
- package/dist/integrations/serena/serena-tools.js +411 -0
- package/dist/logger.js +1 -76
- package/dist/mcp-event-store.js +1 -0
- package/dist/oauth-provider.js +1 -377
- package/dist/pi-tools.js +1 -81
- package/dist/playwright-runtime.js +1 -0
- package/dist/process/background-lifecycle.js +189 -0
- package/dist/process/control-retry.js +42 -0
- package/dist/process/crash-recovery.js +23 -0
- package/dist/process/processes.js +456 -0
- package/dist/processes.js +1 -218
- package/dist/request-context.js +1 -0
- package/dist/review-checkpoints.js +1 -142
- package/dist/room-registry.js +1 -0
- package/dist/roots.js +1 -53
- package/dist/search-discovery.js +1 -271
- package/dist/serena-manager.js +1 -443
- package/dist/serena-tools.js +1 -411
- package/dist/server/dashboard-page-styles.js +331 -0
- package/dist/server/dashboard-page.js +1509 -0
- package/dist/server/dashboard-routes.js +46 -0
- package/dist/server/dashboard.js +240 -0
- package/dist/server/http-helpers.js +30 -0
- package/dist/server/integration-profile-update.js +37 -0
- package/dist/server/mcp-policy.js +169 -0
- package/dist/server/mcp-server-factory.js +127 -0
- package/dist/server/mcp-tool-registrar.js +182 -0
- package/dist/server/openai-session-hint.js +14 -0
- package/dist/server/tool-groups.js +29 -0
- package/dist/server/tool-logging.js +33 -0
- package/dist/server/tool-registration-shared.js +59 -0
- package/dist/server/tools/aseprite-advanced-tools-registration.js +547 -0
- package/dist/server/tools/aseprite-tools-registration.js +213 -0
- package/dist/server/tools/blender-tools-registration.js +690 -0
- package/dist/server/tools/core-file-tools-registration.js +459 -0
- package/dist/server/tools/dotnet-godot-window-tools-registration.js +120 -0
- package/dist/server/tools/godot-csharp-tools-registration.js +252 -0
- package/dist/server/tools/godot-gdscript-tools-registration.js +189 -0
- package/dist/server/tools/process-project-tools-registration.js +155 -0
- package/dist/server/tools/roblox-tools-registration.js +514 -0
- package/dist/server/tools/web-image-tools-registration.js +326 -0
- package/dist/server/tools/workspace-lifecycle-tools-registration.js +130 -0
- package/dist/server/ui-assets.js +97 -0
- package/dist/server/workspace-analytics.js +92 -0
- package/dist/server.js +453 -2713
- package/dist/session-registry.js +1 -0
- package/dist/shutdown.js +1 -0
- package/dist/skills.js +1 -45
- package/dist/sse-heartbeat.js +1 -0
- package/dist/tool-capabilities.js +1 -0
- package/dist/tool-result-budget.js +1 -0
- package/dist/tools/pi-tools.js +81 -0
- package/dist/tunnels/cloudflare-tunnel.js +217 -0
- package/dist/tunnels/cloudflared-service.js +174 -0
- package/dist/tunnels/ngrok-tunnel.js +220 -0
- package/dist/tunnels/tunnel-manager.js +186 -0
- package/dist/tunnels/tunnel-types.js +1 -0
- package/dist/tunnels/tunnel-utils.js +62 -0
- package/dist/ui/.vite/manifest.json +9 -2487
- package/dist/ui/assets/heavy-payload-D42A9ceL.js +1 -0
- package/dist/ui/assets/lightweight-diff-Cv4g9Hdr.js +13 -0
- package/dist/ui/assets/review-payload-DKIg1cKF.js +1 -0
- package/dist/ui/assets/workspace-app-CeK3NhmB.css +1 -0
- package/dist/ui/assets/{workspace-app-C5QsE314.js → workspace-app-CkUXnpl4.js} +6 -6
- package/dist/ui/brand-theme.js +23 -0
- package/dist/ui/workspace-app.html +15 -15
- package/dist/user-config.js +1 -57
- package/dist/view-image.js +1 -104
- package/dist/web-tools.js +1 -200
- package/dist/window-capture.js +1 -74
- package/dist/workspace/artifact-registry.js +69 -0
- package/dist/workspace/git-worktrees.js +141 -0
- package/dist/workspace/git.js +42 -0
- package/dist/workspace/review-checkpoints.js +142 -0
- package/dist/workspace/roots.js +56 -0
- package/dist/workspace/search-discovery.js +264 -0
- package/dist/workspace/skills.js +45 -0
- package/dist/workspace/workspace-store.js +219 -0
- package/dist/workspace/workspaces.js +314 -0
- package/dist/workspace-store.js +1 -125
- package/dist/workspaces.js +1 -226
- package/docs/CREATOR_STORE_FREE_ASSETS.md +162 -0
- package/docs/DEVELOPMENT_TOOLS.md +136 -93
- package/docs/assets/auvrynt-icon.png +0 -0
- package/docs/assets/auvrynt-icon.svg +20 -0
- package/docs/chatgpt-coding-workflow.md +143 -143
- package/docs/configuration.md +156 -124
- package/docs/diagnostics.md +79 -0
- package/docs/gotchas.md +244 -202
- package/docs/multi-agent-and-long-projects.md +91 -0
- package/docs/security.md +138 -100
- package/docs/setup.md +171 -131
- package/docs/source-layout.md +60 -0
- package/extensions/auvrynt_bridge/auvrynt_bridge.lua +594 -0
- package/extensions/auvrynt_bridge/live_analysis.lua +181 -0
- package/extensions/auvrynt_bridge/live_animation.lua +134 -0
- package/extensions/auvrynt_bridge/live_commands.lua +24 -0
- package/extensions/auvrynt_bridge/live_common.lua +130 -0
- package/extensions/auvrynt_bridge/live_document.lua +78 -0
- package/extensions/auvrynt_bridge/live_drawing.lua +125 -0
- package/extensions/auvrynt_bridge/live_effects.lua +91 -0
- package/extensions/auvrynt_bridge/live_palette_template.lua +167 -0
- package/extensions/auvrynt_bridge/live_selection.lua +110 -0
- package/extensions/auvrynt_bridge/live_structure.lua +129 -0
- package/extensions/auvrynt_bridge/package.json +17 -0
- package/guides/ASEPRITE_AGENT_GUIDE.md +133 -0
- package/guides/BLENDER_AGENT_GUIDE.md +472 -0
- package/guides/GODOT_AGENT_GUIDE.md +298 -0
- package/guides/PROJECT_ROUTER.md +165 -0
- package/guides/ROBLOX_AGENT_GUIDE.md +75 -0
- package/guides/SOFTWARE_AGENT_GUIDE.md +104 -0
- package/guides/WEB_AGENT_GUIDE.md +287 -0
- package/package.json +78 -70
- package/scripts/dev-server.mjs +121 -120
- package/scripts/live-tunnel-smoke.mjs +538 -0
- package/scripts/repo-hygiene.mjs +74 -0
- package/scripts/restart-after-crash.mjs +49 -0
- package/scripts/run-tests.mjs +166 -0
- package/dist/ui/assets/abap-CLvhMVsD.js +0 -1
- package/dist/ui/assets/actionscript-3--17pq3dv.js +0 -1
- package/dist/ui/assets/ada-C5qYipkI.js +0 -1
- package/dist/ui/assets/andromeeda-vGVdxbeo.js +0 -1
- package/dist/ui/assets/angular-html-BJqQFYI6.js +0 -1
- package/dist/ui/assets/angular-ts-CMJECO0Y.js +0 -1
- package/dist/ui/assets/apache-U0d_L8uA.js +0 -1
- package/dist/ui/assets/apex-CGTLDQj6.js +0 -1
- package/dist/ui/assets/apl-DWeXpBBr.js +0 -1
- package/dist/ui/assets/applescript-CCn79oCD.js +0 -1
- package/dist/ui/assets/ara-4CJ0cIlV.js +0 -1
- package/dist/ui/assets/asciidoc-DE70LPWp.js +0 -1
- package/dist/ui/assets/asm-Cmm7eHzH.js +0 -1
- package/dist/ui/assets/astro-CLbttLOq.js +0 -1
- package/dist/ui/assets/aurora-x-CDeNXAV0.js +0 -1
- package/dist/ui/assets/awk-BWXHIvNe.js +0 -1
- package/dist/ui/assets/ayu-dark-DluEY0Gj.js +0 -1
- package/dist/ui/assets/ayu-light-C3h-C4tm.js +0 -1
- package/dist/ui/assets/ayu-mirage-Bqwy1Gya.js +0 -1
- package/dist/ui/assets/ballerina-B7ZEbQpA.js +0 -1
- package/dist/ui/assets/bat-Bo4NYOV-.js +0 -1
- package/dist/ui/assets/beancount-D-usSTwE.js +0 -1
- package/dist/ui/assets/berry-DKpUyyne.js +0 -1
- package/dist/ui/assets/bibtex-Ci_nEsc7.js +0 -1
- package/dist/ui/assets/bicep-CUHmPFLl.js +0 -1
- package/dist/ui/assets/bird2-C2hNVINV.js +0 -1
- package/dist/ui/assets/blade-BOzY0P2V.js +0 -1
- package/dist/ui/assets/bsl-BkkzgIyY.js +0 -1
- package/dist/ui/assets/c-BG-8uJvh.js +0 -1
- package/dist/ui/assets/c3-CnJL0r0V.js +0 -1
- package/dist/ui/assets/cadence-CQ2zXKGN.js +0 -1
- package/dist/ui/assets/cairo-DLTphjLi.js +0 -1
- package/dist/ui/assets/catppuccin-frappe-3VR1Za6u.js +0 -1
- package/dist/ui/assets/catppuccin-latte-DwIHMF0Q.js +0 -1
- package/dist/ui/assets/catppuccin-macchiato-DYnBP6_5.js +0 -1
- package/dist/ui/assets/catppuccin-mocha-DYhrFGRu.js +0 -1
- package/dist/ui/assets/clarity-SemFz856.js +0 -1
- package/dist/ui/assets/clojure-DqKBuwfJ.js +0 -1
- package/dist/ui/assets/cmake-Bj61d0ZC.js +0 -1
- package/dist/ui/assets/cobol-I_17IuGe.js +0 -1
- package/dist/ui/assets/codeowners-C8r90Shi.js +0 -1
- package/dist/ui/assets/codeql-oeQT6MSM.js +0 -1
- package/dist/ui/assets/coffee-C0B8hmok.js +0 -1
- package/dist/ui/assets/common-lisp-Cv5bFMCO.js +0 -1
- package/dist/ui/assets/coq-BrsZFFmf.js +0 -1
- package/dist/ui/assets/cpp-DDJXt6Vs.js +0 -1
- package/dist/ui/assets/crystal-Bexqace6.js +0 -1
- package/dist/ui/assets/csharp-Ct8U2NOr.js +0 -1
- package/dist/ui/assets/css-DSQhw_9R.js +0 -1
- package/dist/ui/assets/csv-Dx-8-gkx.js +0 -1
- package/dist/ui/assets/cue-CE9AQfxI.js +0 -1
- package/dist/ui/assets/cypher-ClKdZ_lG.js +0 -1
- package/dist/ui/assets/d-qD-0Kul2.js +0 -1
- package/dist/ui/assets/dark-plus-Cs2F2srj.js +0 -1
- package/dist/ui/assets/dart-DkHntEIa.js +0 -1
- package/dist/ui/assets/dax-BkyTk9wS.js +0 -1
- package/dist/ui/assets/desktop-Dlh5hvp9.js +0 -1
- package/dist/ui/assets/diff-woXpYk--.js +0 -1
- package/dist/ui/assets/docker-IyjqRm3v.js +0 -1
- package/dist/ui/assets/dotenv-_5a1GRtc.js +0 -1
- package/dist/ui/assets/dracula-BHWKrbxM.js +0 -1
- package/dist/ui/assets/dracula-soft-5eyTD99u.js +0 -1
- package/dist/ui/assets/dream-maker-DW3nJb8Q.js +0 -1
- package/dist/ui/assets/edge-Z8YYkHOr.js +0 -1
- package/dist/ui/assets/elixir-CG9uKtAF.js +0 -1
- package/dist/ui/assets/elm-GfWG2IfT.js +0 -1
- package/dist/ui/assets/emacs-lisp-C9PiwqqW.js +0 -1
- package/dist/ui/assets/erb-xe89e73J.js +0 -1
- package/dist/ui/assets/erlang-Cphh6RMH.js +0 -1
- package/dist/ui/assets/everforest-dark-sB-x3p7T.js +0 -1
- package/dist/ui/assets/everforest-light-Df2xbC6M.js +0 -1
- package/dist/ui/assets/fennel-DQxkIbk2.js +0 -1
- package/dist/ui/assets/fish-BJitypiv.js +0 -1
- package/dist/ui/assets/fluent-C03EYrpw.js +0 -1
- package/dist/ui/assets/fortran-fixed-form-DEKoE2YW.js +0 -1
- package/dist/ui/assets/fortran-free-form-CYNrtFtB.js +0 -1
- package/dist/ui/assets/fsharp-D13ZGOAj.js +0 -1
- package/dist/ui/assets/gdresource-C0sCabJj.js +0 -1
- package/dist/ui/assets/gdscript-Cp2uCuqX.js +0 -1
- package/dist/ui/assets/gdshader-CBce3t8t.js +0 -1
- package/dist/ui/assets/genie-CV2tkWYe.js +0 -1
- package/dist/ui/assets/gherkin-DExj1W_8.js +0 -1
- package/dist/ui/assets/git-commit-BSykSTBG.js +0 -1
- package/dist/ui/assets/git-rebase-CoTL_uSE.js +0 -1
- package/dist/ui/assets/github-dark-C-LZuMrd.js +0 -1
- package/dist/ui/assets/github-dark-default-DXG-b-1a.js +0 -1
- package/dist/ui/assets/github-dark-dimmed-Bx1FflLF.js +0 -1
- package/dist/ui/assets/github-dark-high-contrast-B_tTalzw.js +0 -1
- package/dist/ui/assets/github-light-EUqPIrTm.js +0 -1
- package/dist/ui/assets/github-light-default-BXViO-2h.js +0 -1
- package/dist/ui/assets/github-light-high-contrast-B68TUdTA.js +0 -1
- package/dist/ui/assets/gleam-CSRkHgEL.js +0 -1
- package/dist/ui/assets/glimmer-js-DAn4UCSu.js +0 -1
- package/dist/ui/assets/glimmer-ts-Tjyi6Gh5.js +0 -1
- package/dist/ui/assets/glsl-CtTDZoqR.js +0 -1
- package/dist/ui/assets/gn-ilITqXS6.js +0 -1
- package/dist/ui/assets/gnuplot-7GGW24-e.js +0 -1
- package/dist/ui/assets/go-BJwz_mda.js +0 -1
- package/dist/ui/assets/graphql-D5gcC_Jk.js +0 -1
- package/dist/ui/assets/groovy-CacY0gHj.js +0 -1
- package/dist/ui/assets/gruvbox-dark-hard-C820rvS2.js +0 -1
- package/dist/ui/assets/gruvbox-dark-medium-BPjhmG05.js +0 -1
- package/dist/ui/assets/gruvbox-dark-soft-MrdJrrXF.js +0 -1
- package/dist/ui/assets/gruvbox-light-hard-BC_s9l72.js +0 -1
- package/dist/ui/assets/gruvbox-light-medium-BAWPOn9u.js +0 -1
- package/dist/ui/assets/gruvbox-light-soft-BSMLrYjP.js +0 -1
- package/dist/ui/assets/hack-BJXY27dt.js +0 -1
- package/dist/ui/assets/haml-BLfFoZf7.js +0 -1
- package/dist/ui/assets/handlebars-Dw6CWkvN.js +0 -1
- package/dist/ui/assets/haskell-D8IpX4py.js +0 -1
- package/dist/ui/assets/haxe-OTjmBuCE.js +0 -1
- package/dist/ui/assets/hcl-Dh228itO.js +0 -1
- package/dist/ui/assets/heavy-payload-Dcg0-F-S.js +0 -4
- package/dist/ui/assets/hjson-CxZEssPk.js +0 -1
- package/dist/ui/assets/hlsl-Cvrh5tZx.js +0 -1
- package/dist/ui/assets/horizon-CE9ld1lL.js +0 -1
- package/dist/ui/assets/horizon-bright-Br1oVSNq.js +0 -1
- package/dist/ui/assets/houston-CsvMBhTu.js +0 -1
- package/dist/ui/assets/html-CAcAWvoN.js +0 -1
- package/dist/ui/assets/html-derivative-8aSW2E_7.js +0 -1
- package/dist/ui/assets/http-B2YR_3V1.js +0 -1
- package/dist/ui/assets/hurl-BnDJ9Zhf.js +0 -1
- package/dist/ui/assets/hxml-B0Qn7Nwc.js +0 -1
- package/dist/ui/assets/hy-CZbG8q4J.js +0 -1
- package/dist/ui/assets/imba-DsUTQ-LC.js +0 -1
- package/dist/ui/assets/ini-B5eOa1yu.js +0 -1
- package/dist/ui/assets/java-Doxi4W8u.js +0 -1
- package/dist/ui/assets/javascript-BbRdEqti.js +0 -1
- package/dist/ui/assets/jinja-CS3Tpv_Q.js +0 -1
- package/dist/ui/assets/jison-BkPGYVHR.js +0 -1
- package/dist/ui/assets/json-BMt1m3m8.js +0 -1
- package/dist/ui/assets/json5-BR5RXkoi.js +0 -1
- package/dist/ui/assets/jsonc-CYpm1nAK.js +0 -1
- package/dist/ui/assets/jsonl-CmCQp5Yx.js +0 -1
- package/dist/ui/assets/jsonnet-CJTPZ8u_.js +0 -1
- package/dist/ui/assets/jssm-DXw9l8Rf.js +0 -1
- package/dist/ui/assets/jsx-CQKrJXXY.js +0 -1
- package/dist/ui/assets/julia-BuN7i2du.js +0 -1
- package/dist/ui/assets/just-BswEPFPu.js +0 -1
- package/dist/ui/assets/kanagawa-dragon-CXtmUGW6.js +0 -1
- package/dist/ui/assets/kanagawa-lotus-BN08jTvb.js +0 -1
- package/dist/ui/assets/kanagawa-wave-CTweb8Dz.js +0 -1
- package/dist/ui/assets/kdl-CsD5j6eV.js +0 -1
- package/dist/ui/assets/kotlin-DhhofPvG.js +0 -1
- package/dist/ui/assets/kusto-BUv0MjJC.js +0 -1
- package/dist/ui/assets/laserwave-C_8bwKvT.js +0 -1
- package/dist/ui/assets/latex-DU2VyFfA.js +0 -1
- package/dist/ui/assets/lean-CewbzKMR.js +0 -1
- package/dist/ui/assets/less-DVTAwKKz.js +0 -1
- package/dist/ui/assets/light-plus-DVQuIRkW.js +0 -1
- package/dist/ui/assets/liquid-Cmz1L3dq.js +0 -1
- package/dist/ui/assets/llvm-Cm23YOpf.js +0 -1
- package/dist/ui/assets/log-BNLmms1o.js +0 -1
- package/dist/ui/assets/logo-Cluzi2Zq.js +0 -1
- package/dist/ui/assets/lua-CfVXhkaJ.js +0 -1
- package/dist/ui/assets/luau-CNKltnaQ.js +0 -1
- package/dist/ui/assets/make-Dixweg8N.js +0 -1
- package/dist/ui/assets/markdown-BYOwaDjH.js +0 -1
- package/dist/ui/assets/marko-C5bfqGiA.js +0 -1
- package/dist/ui/assets/material-theme-Bm3Qr25_.js +0 -1
- package/dist/ui/assets/material-theme-darker-2IIEA8gg.js +0 -1
- package/dist/ui/assets/material-theme-lighter-uhdI0v04.js +0 -1
- package/dist/ui/assets/material-theme-ocean-CHQ94UKr.js +0 -1
- package/dist/ui/assets/material-theme-palenight-B5W6OYN7.js +0 -1
- package/dist/ui/assets/matlab-D7qyCx1q.js +0 -1
- package/dist/ui/assets/mdc-CVBXYfyq.js +0 -1
- package/dist/ui/assets/mdx-DQZ5AkYe.js +0 -1
- package/dist/ui/assets/mermaid-Bk4SNUv9.js +0 -1
- package/dist/ui/assets/min-dark-BSWPekZh.js +0 -1
- package/dist/ui/assets/min-light-DDpmG2fV.js +0 -1
- package/dist/ui/assets/mipsasm-BMqwQI7S.js +0 -1
- package/dist/ui/assets/mojo-BgCJLMeH.js +0 -1
- package/dist/ui/assets/monokai-CdkpiU2Y.js +0 -1
- package/dist/ui/assets/moonbit-CaWjb8XO.js +0 -1
- package/dist/ui/assets/move-B1IS1UjX.js +0 -1
- package/dist/ui/assets/narrat-_X_XdTYD.js +0 -1
- package/dist/ui/assets/nextflow-Bbiyy34d.js +0 -1
- package/dist/ui/assets/nextflow-groovy-Dc_ddanL.js +0 -1
- package/dist/ui/assets/nginx-CzJafxLa.js +0 -1
- package/dist/ui/assets/night-owl-DhmEMT88.js +0 -1
- package/dist/ui/assets/night-owl-light-eJ-hLW7d.js +0 -1
- package/dist/ui/assets/nim-DABKtHtM.js +0 -1
- package/dist/ui/assets/nix-IvuFDN5E.js +0 -1
- package/dist/ui/assets/nord-Cb4Vim4T.js +0 -1
- package/dist/ui/assets/nushell-DcLAeLz5.js +0 -1
- package/dist/ui/assets/objective-c-D1A_Heim.js +0 -1
- package/dist/ui/assets/objective-cpp-BsSzOQcm.js +0 -1
- package/dist/ui/assets/ocaml-O90oeIOV.js +0 -1
- package/dist/ui/assets/odin-B1RWQWA5.js +0 -1
- package/dist/ui/assets/one-dark-pro-CLwyXe_n.js +0 -1
- package/dist/ui/assets/one-light-D7Lr4KcI.js +0 -1
- package/dist/ui/assets/openscad-BUDT5pXO.js +0 -1
- package/dist/ui/assets/pascal-4ZHwLPI5.js +0 -1
- package/dist/ui/assets/perl-CBh7L3lZ.js +0 -1
- package/dist/ui/assets/php-DFbI9q5p.js +0 -1
- package/dist/ui/assets/pierre-dark-sU4Zdns8.js +0 -1
- package/dist/ui/assets/pierre-dark-soft-HXgun5vs.js +0 -1
- package/dist/ui/assets/pierre-light-DWBk51d8.js +0 -1
- package/dist/ui/assets/pierre-light-soft-CodEzPxf.js +0 -1
- package/dist/ui/assets/pkl-ot-7Btpt.js +0 -1
- package/dist/ui/assets/plastic-DQwYfKfQ.js +0 -1
- package/dist/ui/assets/plsql-DGHpHOYJ.js +0 -1
- package/dist/ui/assets/po-BiJDBrnU.js +0 -1
- package/dist/ui/assets/poimandres-DRFjx7u4.js +0 -1
- package/dist/ui/assets/polar-C7UOKdEL.js +0 -1
- package/dist/ui/assets/postcss-BXeXVLqQ.js +0 -1
- package/dist/ui/assets/powerquery-DNMTfnFr.js +0 -1
- package/dist/ui/assets/powershell-DshXNtvi.js +0 -1
- package/dist/ui/assets/prisma-BsRQq5mF.js +0 -1
- package/dist/ui/assets/prolog-iXnhIJG7.js +0 -1
- package/dist/ui/assets/proto-DB4EqR-F.js +0 -1
- package/dist/ui/assets/pug-C_PxC7gO.js +0 -1
- package/dist/ui/assets/puppet-CDv2pdJW.js +0 -1
- package/dist/ui/assets/purescript-9MfHhQsQ.js +0 -1
- package/dist/ui/assets/python-gzcpVVnB.js +0 -1
- package/dist/ui/assets/qml-DtngoFFK.js +0 -1
- package/dist/ui/assets/qmldir-DCQb3MpD.js +0 -1
- package/dist/ui/assets/qss-Fe1Jh2GI.js +0 -1
- package/dist/ui/assets/r-DohkcevW.js +0 -1
- package/dist/ui/assets/racket-DcIDlBhZ.js +0 -1
- package/dist/ui/assets/raku-B3gFvitq.js +0 -1
- package/dist/ui/assets/razor-C4t8J0_E.js +0 -1
- package/dist/ui/assets/red-CJ3rzSJv.js +0 -1
- package/dist/ui/assets/reg-CRGYupPL.js +0 -1
- package/dist/ui/assets/regexp-OGbTbjgY.js +0 -1
- package/dist/ui/assets/rel-BtDbiS_P.js +0 -1
- package/dist/ui/assets/review-payload-C5Qz60Kq.js +0 -1
- package/dist/ui/assets/riscv-Ckw8ddFX.js +0 -1
- package/dist/ui/assets/ron-VUp2lXgN.js +0 -1
- package/dist/ui/assets/rose-pine-BthvhNj6.js +0 -1
- package/dist/ui/assets/rose-pine-dawn-Dg85fqjY.js +0 -1
- package/dist/ui/assets/rose-pine-moon-hon4tzzS.js +0 -1
- package/dist/ui/assets/rosmsg-CAekHB0j.js +0 -1
- package/dist/ui/assets/rst-CfBbbcvC.js +0 -1
- package/dist/ui/assets/ruby-Bw0mpxHY.js +0 -1
- package/dist/ui/assets/rust-Cfkwpbl8.js +0 -1
- package/dist/ui/assets/sas-Cs3s9JOf.js +0 -1
- package/dist/ui/assets/sass-DXrisJhu.js +0 -1
- package/dist/ui/assets/scala-DKOlJaKm.js +0 -1
- package/dist/ui/assets/scheme-DQCgrYNe.js +0 -1
- package/dist/ui/assets/scss-sRxNJS54.js +0 -1
- package/dist/ui/assets/sdbl-bTVj8UrX.js +0 -1
- package/dist/ui/assets/shaderlab-TOUzSsQk.js +0 -1
- package/dist/ui/assets/shellscript-B0X6wh0R.js +0 -1
- package/dist/ui/assets/shellsession-D2FdOioR.js +0 -1
- package/dist/ui/assets/slack-dark-DnToyrRv.js +0 -1
- package/dist/ui/assets/slack-ochin-B2OO5cIa.js +0 -1
- package/dist/ui/assets/smalltalk-B16xEiuN.js +0 -1
- package/dist/ui/assets/snazzy-light-4G7pJPwS.js +0 -1
- package/dist/ui/assets/solarized-dark-DV17i1UV.js +0 -1
- package/dist/ui/assets/solarized-light-DSh2HLQt.js +0 -1
- package/dist/ui/assets/solidity-CKzVLygQ.js +0 -1
- package/dist/ui/assets/soy-s6g9OjJ1.js +0 -1
- package/dist/ui/assets/sparql-D_iOobhT.js +0 -1
- package/dist/ui/assets/splunk-BC2Px7Mm.js +0 -1
- package/dist/ui/assets/sql-DVTnh5V-.js +0 -1
- package/dist/ui/assets/ssh-config-BgfXC-Er.js +0 -1
- package/dist/ui/assets/stata-DFIDiXF9.js +0 -1
- package/dist/ui/assets/stylus-B6D30XZt.js +0 -1
- package/dist/ui/assets/surrealql-DVfrsLyg.js +0 -1
- package/dist/ui/assets/svelte-D5GsxESq.js +0 -1
- package/dist/ui/assets/swift-DonLKvLd.js +0 -1
- package/dist/ui/assets/synthwave-84-nFMaYfgc.js +0 -1
- package/dist/ui/assets/system-verilog-DJ5XKQeo.js +0 -1
- package/dist/ui/assets/systemd-BxMlprV5.js +0 -1
- package/dist/ui/assets/talonscript-CohzipZa.js +0 -1
- package/dist/ui/assets/tasl-DMoTqEGO.js +0 -1
- package/dist/ui/assets/tcl-CZd0xW_V.js +0 -1
- package/dist/ui/assets/templ-DI-Zyqzd.js +0 -1
- package/dist/ui/assets/terraform-DswuEJGm.js +0 -1
- package/dist/ui/assets/tex-WHHmlbJI.js +0 -1
- package/dist/ui/assets/tokyo-night-oM2G3aXe.js +0 -1
- package/dist/ui/assets/toml-CcmNWLt0.js +0 -1
- package/dist/ui/assets/ts-tags-Dwpo2RFJ.js +0 -1
- package/dist/ui/assets/tsv-sltzmVWM.js +0 -1
- package/dist/ui/assets/tsx-ph_idaAW.js +0 -1
- package/dist/ui/assets/turtle-ByJddavk.js +0 -1
- package/dist/ui/assets/twig-YO17jFjR.js +0 -1
- package/dist/ui/assets/typescript-CbAxjhkl.js +0 -1
- package/dist/ui/assets/typespec-B88KGewJ.js +0 -1
- package/dist/ui/assets/typst-DI99ib-x.js +0 -1
- package/dist/ui/assets/useFileDiffInstance-B2DLX3Vg.js +0 -244
- package/dist/ui/assets/v-DETTlOr0.js +0 -1
- package/dist/ui/assets/vala-zf12oZj6.js +0 -1
- package/dist/ui/assets/vb-Djn5o6TS.js +0 -1
- package/dist/ui/assets/verilog-CiiDBU1e.js +0 -1
- package/dist/ui/assets/vesper-D5bVUKB1.js +0 -1
- package/dist/ui/assets/vhdl-BroJfC0k.js +0 -1
- package/dist/ui/assets/viml-DvXPmvsu.js +0 -1
- package/dist/ui/assets/vitesse-black-fwtXNY1n.js +0 -1
- package/dist/ui/assets/vitesse-dark-BZCL-v6S.js +0 -1
- package/dist/ui/assets/vitesse-light-VbXTXTou.js +0 -1
- package/dist/ui/assets/vue-CraHL-Ps.js +0 -1
- package/dist/ui/assets/vue-html-e9tyZNtS.js +0 -1
- package/dist/ui/assets/vue-vine-CofmxaUb.js +0 -1
- package/dist/ui/assets/vyper-CgoNMtux.js +0 -1
- package/dist/ui/assets/wasm-BnjxR4X6.js +0 -1
- package/dist/ui/assets/wasm-ByWQv1Qj.js +0 -1
- package/dist/ui/assets/wenyan-C8pVoKbM.js +0 -1
- package/dist/ui/assets/wgsl-BsKzXJz4.js +0 -1
- package/dist/ui/assets/wikitext-ClFFjSW2.js +0 -1
- package/dist/ui/assets/wit-DdvCle-K.js +0 -1
- package/dist/ui/assets/wolfram-DLL8P-h_.js +0 -1
- package/dist/ui/assets/workspace-app-8--oTbCd.css +0 -1
- package/dist/ui/assets/xml-BWSdPZHm.js +0 -1
- package/dist/ui/assets/xsl-BtCt7Hx8.js +0 -1
- package/dist/ui/assets/yaml-BZiTw7cQ.js +0 -1
- package/dist/ui/assets/zenscript-BnlCZFoB.js +0 -1
- package/dist/ui/assets/zig-CMLA9XwU.js +0 -1
- package/docs/assets/auvrynt-logo-light.png +0 -0
- package/docs/assets/auvrynt-screenshot.png +0 -0
package/dist/image-tools.js
CHANGED
|
@@ -1,157 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { readFile, writeFile, stat, mkdir } from "node:fs/promises";
|
|
3
|
-
export function parseImageDimensions(buffer) {
|
|
4
|
-
if (buffer.length < 8)
|
|
5
|
-
throw new Error("Image file buffer too small.");
|
|
6
|
-
// PNG: signature \x89PNG\r\n\x1a\n, width at offset 16 (BE), height at offset 20 (BE)
|
|
7
|
-
if (buffer[0] === 0x89 && buffer[1] === 0x50 && buffer[2] === 0x4e && buffer[3] === 0x47) {
|
|
8
|
-
const width = buffer.readUInt32BE(16);
|
|
9
|
-
const height = buffer.readUInt32BE(20);
|
|
10
|
-
return { width, height };
|
|
11
|
-
}
|
|
12
|
-
// GIF: GIF87a or GIF89a, width at offset 6 (LE), height at offset 8 (LE)
|
|
13
|
-
if (buffer[0] === 0x47 && buffer[1] === 0x49 && buffer[2] === 0x46) {
|
|
14
|
-
const width = buffer.readUInt16LE(6);
|
|
15
|
-
const height = buffer.readUInt16LE(8);
|
|
16
|
-
return { width, height };
|
|
17
|
-
}
|
|
18
|
-
// WebP: RIFF...WEBP
|
|
19
|
-
if (buffer.length >= 30 &&
|
|
20
|
-
buffer.toString("ascii", 0, 4) === "RIFF" &&
|
|
21
|
-
buffer.toString("ascii", 8, 12) === "WEBP") {
|
|
22
|
-
// VP8
|
|
23
|
-
if (buffer.toString("ascii", 12, 15) === "VP8") {
|
|
24
|
-
const width = buffer.readUInt16LE(26) & 0x3fff;
|
|
25
|
-
const height = buffer.readUInt16LE(28) & 0x3fff;
|
|
26
|
-
return { width, height };
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
// Default fallback dimensions if header format varies
|
|
30
|
-
return { width: 100, height: 100 };
|
|
31
|
-
}
|
|
32
|
-
export async function inspectImage(registry, input) {
|
|
33
|
-
const workspace = registry.getWorkspace(input.workspaceId);
|
|
34
|
-
const absolutePath = registry.resolvePath(workspace, input.path);
|
|
35
|
-
const fileStats = await stat(absolutePath);
|
|
36
|
-
const buffer = await readFile(absolutePath);
|
|
37
|
-
const ext = extname(input.path).toLowerCase();
|
|
38
|
-
const dimensions = parseImageDimensions(buffer);
|
|
39
|
-
const mimeTypes = {
|
|
40
|
-
".png": "image/png",
|
|
41
|
-
".jpg": "image/jpeg",
|
|
42
|
-
".jpeg": "image/jpeg",
|
|
43
|
-
".webp": "image/webp",
|
|
44
|
-
".gif": "image/gif",
|
|
45
|
-
};
|
|
46
|
-
const info = {
|
|
47
|
-
format: ext.slice(1),
|
|
48
|
-
mimeType: mimeTypes[ext] ?? "image/png",
|
|
49
|
-
width: dimensions.width,
|
|
50
|
-
height: dimensions.height,
|
|
51
|
-
fileSize: fileStats.size,
|
|
52
|
-
hasAlpha: ext === ".png" || ext === ".webp" || ext === ".gif",
|
|
53
|
-
pixelArtStatus: dimensions.width <= 256 && dimensions.height <= 256 ? "likely" : "unlikely",
|
|
54
|
-
};
|
|
55
|
-
return {
|
|
56
|
-
content: [{ type: "text", text: JSON.stringify(info, null, 2) }],
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
export async function compareImages(registry, input) {
|
|
60
|
-
const workspace = registry.getWorkspace(input.workspaceId);
|
|
61
|
-
const refPath = registry.resolvePath(workspace, input.referencePath);
|
|
62
|
-
const candPath = registry.resolvePath(workspace, input.candidatePath);
|
|
63
|
-
const refBuffer = await readFile(refPath);
|
|
64
|
-
const candBuffer = await readFile(candPath);
|
|
65
|
-
const refDim = parseImageDimensions(refBuffer);
|
|
66
|
-
const candDim = parseImageDimensions(candBuffer);
|
|
67
|
-
const dimensionsMatch = refDim.width === candDim.width && refDim.height === candDim.height;
|
|
68
|
-
const isExactByteMatch = refBuffer.equals(candBuffer);
|
|
69
|
-
const matchingPixels = isExactByteMatch ? refDim.width * refDim.height : Math.floor(refDim.width * refDim.height * (dimensionsMatch ? 0.98 : 0.7));
|
|
70
|
-
const totalPixels = refDim.width * refDim.height;
|
|
71
|
-
const changedPixels = totalPixels - matchingPixels;
|
|
72
|
-
const exactMatchPercentage = Number(((matchingPixels / totalPixels) * 100).toFixed(2));
|
|
73
|
-
let diffPath;
|
|
74
|
-
let diffBase64;
|
|
75
|
-
if (input.diffOutputPath) {
|
|
76
|
-
const absDiffPath = registry.resolvePath(workspace, input.diffOutputPath);
|
|
77
|
-
await mkdir(dirname(absDiffPath), { recursive: true });
|
|
78
|
-
// Write simple diff image (reuse candidate buffer or reference buffer)
|
|
79
|
-
await writeFile(absDiffPath, candBuffer);
|
|
80
|
-
diffPath = relative(workspace.root, absDiffPath).replace(/\\/g, "/");
|
|
81
|
-
diffBase64 = candBuffer.toString("base64");
|
|
82
|
-
}
|
|
83
|
-
const resultData = {
|
|
84
|
-
referenceDimensions: refDim,
|
|
85
|
-
candidateDimensions: candDim,
|
|
86
|
-
dimensionsMatch,
|
|
87
|
-
isExactByteMatch,
|
|
88
|
-
matchingPixels,
|
|
89
|
-
changedPixels,
|
|
90
|
-
exactMatchPercentage,
|
|
91
|
-
similarityPercentage: exactMatchPercentage,
|
|
92
|
-
maxChannelDifference: isExactByteMatch ? 0 : 25,
|
|
93
|
-
meanRgbaDifference: isExactByteMatch ? 0 : 2.5,
|
|
94
|
-
diffOutputPath: diffPath,
|
|
95
|
-
};
|
|
96
|
-
const responseContent = [
|
|
97
|
-
{ type: "text", text: JSON.stringify(resultData, null, 2) },
|
|
98
|
-
];
|
|
99
|
-
if (diffBase64) {
|
|
100
|
-
responseContent.unshift({
|
|
101
|
-
type: "image",
|
|
102
|
-
data: diffBase64,
|
|
103
|
-
mimeType: "image/png",
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
return { content: responseContent };
|
|
107
|
-
}
|
|
108
|
-
export async function inspectSprite(registry, input) {
|
|
109
|
-
const workspace = registry.getWorkspace(input.workspaceId);
|
|
110
|
-
const absolutePath = registry.resolvePath(workspace, input.path);
|
|
111
|
-
const buffer = await readFile(absolutePath);
|
|
112
|
-
const dimensions = parseImageDimensions(buffer);
|
|
113
|
-
const cellW = input.expectedCellWidth ?? 32;
|
|
114
|
-
const cellH = input.expectedCellHeight ?? 32;
|
|
115
|
-
const cols = Math.floor(dimensions.width / cellW);
|
|
116
|
-
const rows = Math.floor(dimensions.height / cellH);
|
|
117
|
-
const dividesEvenly = dimensions.width % cellW === 0 && dimensions.height % cellH === 0;
|
|
118
|
-
const spriteInfo = {
|
|
119
|
-
dimensions,
|
|
120
|
-
cellWidth: cellW,
|
|
121
|
-
cellHeight: cellH,
|
|
122
|
-
possibleColumns: cols,
|
|
123
|
-
possibleRows: rows,
|
|
124
|
-
dividesEvenly,
|
|
125
|
-
pixelArtStatus: "likely",
|
|
126
|
-
};
|
|
127
|
-
return {
|
|
128
|
-
content: [{ type: "text", text: JSON.stringify(spriteInfo, null, 2) }],
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
export async function splitSpriteSheet(registry, input) {
|
|
132
|
-
const workspace = registry.getWorkspace(input.workspaceId);
|
|
133
|
-
const absolutePath = registry.resolvePath(workspace, input.path);
|
|
134
|
-
const outDir = registry.resolvePath(workspace, input.outputDirectory);
|
|
135
|
-
const buffer = await readFile(absolutePath);
|
|
136
|
-
const dimensions = parseImageDimensions(buffer);
|
|
137
|
-
await mkdir(outDir, { recursive: true });
|
|
138
|
-
const generatedPaths = [];
|
|
139
|
-
const pattern = input.namingPattern ?? "frame_{col}_{row}.png";
|
|
140
|
-
for (let r = 0; r < input.rows; r++) {
|
|
141
|
-
for (let c = 0; c < input.columns; c++) {
|
|
142
|
-
const fileName = pattern.replace("{col}", String(c)).replace("{row}", String(r));
|
|
143
|
-
const framePath = join(outDir, fileName);
|
|
144
|
-
// Save frame file inside workspace
|
|
145
|
-
await writeFile(framePath, buffer);
|
|
146
|
-
generatedPaths.push(relative(workspace.root, framePath).replace(/\\/g, "/"));
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
return {
|
|
150
|
-
content: [
|
|
151
|
-
{
|
|
152
|
-
type: "text",
|
|
153
|
-
text: `Split sprite sheet into ${generatedPaths.length} frames:\n${generatedPaths.join("\n")}`,
|
|
154
|
-
},
|
|
155
|
-
],
|
|
156
|
-
};
|
|
157
|
-
}
|
|
1
|
+
export * from "./integrations/images/image-tools.js";
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export const AUVRYNT_COMMANDS = [
|
|
2
|
+
{ command: "auvrynt", description: "Run first-time setup if needed, then start the server." },
|
|
3
|
+
{ command: "auvrynt start", description: "Start Auvrynt with all integrations disabled by default." },
|
|
4
|
+
{ command: "auvrynt start blender", description: "Start Blender MCP detection only." },
|
|
5
|
+
{ command: "auvrynt start web", description: "Start Playwright/browser tools only." },
|
|
6
|
+
{ command: "auvrynt start godotcs", description: "Start Godot C# only." },
|
|
7
|
+
{ command: "auvrynt start godotgd", description: "Start Godot GDScript only." },
|
|
8
|
+
{ command: "auvrynt start se", description: "Start Serena only." },
|
|
9
|
+
{ command: "auvrynt start web,blender", description: "Start multiple integrations together." },
|
|
10
|
+
{ command: "auvrynt start ... --replace", description: "Replace active profiles or change the managed workspace." },
|
|
11
|
+
{ command: "auvrynt add web", description: "Add profiles live without restarting the server or tunnel." },
|
|
12
|
+
{ command: "auvrynt change", description: "Switch the running workspace to the current directory." },
|
|
13
|
+
{ command: "auvrynt stop", description: "Stop Auvrynt and, on Windows custom mode, the cloudflared service." },
|
|
14
|
+
{ command: "auvrynt tunnel", description: "Switch between Cloudflare, ngrok, or a custom Cloudflare Named Tunnel." },
|
|
15
|
+
{ command: "auvrynt restart [combo]", description: "Restart only Auvrynt while keeping the current tunnel URL." },
|
|
16
|
+
{ command: "auvrynt restart hard", description: "Stop and start Auvrynt plus its managed tunnel." },
|
|
17
|
+
{ command: "auvrynt serve", description: "Start the server in the foreground with verbose console logs." },
|
|
18
|
+
{ command: "auvrynt init", description: "Create or update ~/.auvrynt/config.json and auth.json." },
|
|
19
|
+
{ command: "auvrynt setup", description: "Configure executable paths for local tools." },
|
|
20
|
+
{ command: "auvrynt enable", description: "Enable or disable integrations one by one." },
|
|
21
|
+
{ command: "auvrynt disable", description: "Select enabled integrations to disable." },
|
|
22
|
+
{ command: "auvrynt doctor", description: "Show configuration, runtime, and native dependency status." },
|
|
23
|
+
{ command: "auvrynt status", description: "Show local MCP, tunnel, and integration connection status." },
|
|
24
|
+
{ command: "auvrynt connected", description: "Show recently connected MCP and web-agent providers." },
|
|
25
|
+
{ command: "auvrynt token", description: "Print the owner token for authentication on explicit local request." },
|
|
26
|
+
{ command: "auvrynt token reset", description: "Generate and save a new owner token." },
|
|
27
|
+
{ command: "auvrynt uninstall", description: "Remove Auvrynt configuration after confirmation." },
|
|
28
|
+
{ command: "auvrynt uninstall -y", description: "Remove Auvrynt configuration without confirmation." },
|
|
29
|
+
{ command: "auvrynt config get", description: "Print the persisted configuration." },
|
|
30
|
+
{ command: "auvrynt config set publicBaseUrl <url|null>", description: "Set or clear the public base URL." },
|
|
31
|
+
{ command: "AUVRYNT_PUBLIC_BASE_URL=https://example.com auvrynt serve", description: "Run a foreground server with a custom public tunnel URL." },
|
|
32
|
+
];
|
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
import { isIP } from "node:net";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join, resolve } from "node:path";
|
|
4
|
+
import { expandHomePath } from "../roots.js";
|
|
5
|
+
import { loadAuvryntFiles } from "../user-config.js";
|
|
6
|
+
import { resolveNgrokAuthtoken } from "./ngrok-auth-pool.js";
|
|
7
|
+
import { normalizeNgrokUrl } from "../tunnels/tunnel-utils.js";
|
|
8
|
+
const DEFAULT_OAUTH_ACCESS_TOKEN_TTL_SECONDS = 60 * 60;
|
|
9
|
+
const DEFAULT_OAUTH_REFRESH_TOKEN_TTL_SECONDS = 30 * 24 * 60 * 60;
|
|
10
|
+
export const SUPPORTED_SCOPES = [
|
|
11
|
+
"auvrynt:read",
|
|
12
|
+
"auvrynt:write",
|
|
13
|
+
"auvrynt:process",
|
|
14
|
+
"auvrynt:web",
|
|
15
|
+
"auvrynt:software",
|
|
16
|
+
"auvrynt:godot",
|
|
17
|
+
"auvrynt:blender",
|
|
18
|
+
"auvrynt:blender-python",
|
|
19
|
+
"auvrynt:aseprite",
|
|
20
|
+
"auvrynt:serena",
|
|
21
|
+
"auvrynt:roblox",
|
|
22
|
+
];
|
|
23
|
+
const DEFAULT_OAUTH_SCOPES = SUPPORTED_SCOPES.filter((scope) => scope !== "auvrynt:blender-python");
|
|
24
|
+
export const SCOPE_DESCRIPTIONS = {
|
|
25
|
+
"auvrynt:read": "Inspect files, search, and perform read-only project analysis",
|
|
26
|
+
"auvrynt:write": "Edit and create files",
|
|
27
|
+
"auvrynt:process": "Run local commands and processes with the current OS user's privileges",
|
|
28
|
+
"auvrynt:web": "Use browser and web-development tools",
|
|
29
|
+
"auvrynt:software": "Use software and .NET tools",
|
|
30
|
+
"auvrynt:godot": "Use Godot project and editor tools",
|
|
31
|
+
"auvrynt:blender": "Use workspace-bound Blender 3D tools",
|
|
32
|
+
"auvrynt:blender-python": "Execute arbitrary Python inside Blender (host-level capability)",
|
|
33
|
+
"auvrynt:aseprite": "Use workspace-bound Aseprite pixel-art and animation tools",
|
|
34
|
+
"auvrynt:serena": "Use local Serena semantic code tools",
|
|
35
|
+
"auvrynt:roblox": "Use official Roblox Studio MCP tools",
|
|
36
|
+
};
|
|
37
|
+
export const MAX_MCP_SESSIONS = 99999;
|
|
38
|
+
export const MIN_SESSION_IDLE_TIMEOUT_MS = 60 * 1000;
|
|
39
|
+
export const DEFAULT_SESSION_IDLE_TIMEOUT_MS = 12 * 60 * 60 * 1000;
|
|
40
|
+
export const MAX_SESSION_IDLE_TIMEOUT_MS = 7 * 24 * 60 * 60 * 1000;
|
|
41
|
+
function parsePort(value) {
|
|
42
|
+
if (value === undefined || value === "")
|
|
43
|
+
return 49321;
|
|
44
|
+
const port = Number(value);
|
|
45
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
46
|
+
throw new Error(`Invalid PORT: ${value}`);
|
|
47
|
+
}
|
|
48
|
+
return port;
|
|
49
|
+
}
|
|
50
|
+
function parseAllowedRoots(value) {
|
|
51
|
+
if (Array.isArray(value)) {
|
|
52
|
+
const roots = value.map((entry) => entry.trim()).filter(Boolean);
|
|
53
|
+
return (roots.length > 0 ? roots : [process.cwd()]).map((root) => resolve(expandHomePath(root)));
|
|
54
|
+
}
|
|
55
|
+
const rawRoots = value
|
|
56
|
+
?.split(",")
|
|
57
|
+
.map((entry) => entry.trim())
|
|
58
|
+
.filter(Boolean) ?? [];
|
|
59
|
+
const roots = rawRoots.length > 0 ? rawRoots : [process.cwd()];
|
|
60
|
+
return roots.map((root) => resolve(expandHomePath(root)));
|
|
61
|
+
}
|
|
62
|
+
function parseAllowedHosts(value, derivedHosts) {
|
|
63
|
+
if (Array.isArray(value)) {
|
|
64
|
+
return normalizeAllowedHosts(value, derivedHosts);
|
|
65
|
+
}
|
|
66
|
+
const rawHosts = value
|
|
67
|
+
?.split(",")
|
|
68
|
+
.map((entry) => entry.trim())
|
|
69
|
+
.filter(Boolean) ?? [];
|
|
70
|
+
return normalizeAllowedHosts(rawHosts, derivedHosts);
|
|
71
|
+
}
|
|
72
|
+
function normalizeAllowedHost(host) {
|
|
73
|
+
const trimmed = host.trim().toLowerCase();
|
|
74
|
+
if (!trimmed)
|
|
75
|
+
throw new Error("Allowed Host entries must not be empty.");
|
|
76
|
+
if (trimmed === "*")
|
|
77
|
+
return trimmed;
|
|
78
|
+
if (/[\/@?#]/.test(trimmed)) {
|
|
79
|
+
throw new Error(`Invalid allowed Host entry: ${host}. Use a hostname or IP address without scheme, path, query, or fragment.`);
|
|
80
|
+
}
|
|
81
|
+
const unbracketed = trimmed.startsWith("[") && trimmed.endsWith("]")
|
|
82
|
+
? trimmed.slice(1, -1)
|
|
83
|
+
: trimmed;
|
|
84
|
+
const ipVersion = isIP(unbracketed);
|
|
85
|
+
if (ipVersion === 6)
|
|
86
|
+
return `[${unbracketed}]`;
|
|
87
|
+
if (ipVersion === 4)
|
|
88
|
+
return unbracketed;
|
|
89
|
+
if (trimmed.includes(":")) {
|
|
90
|
+
throw new Error(`Invalid allowed Host entry: ${host}. Ports are not part of the Host allowlist.`);
|
|
91
|
+
}
|
|
92
|
+
if (!/^[a-z0-9.-]+$/.test(trimmed) || trimmed.startsWith(".") || trimmed.endsWith(".")) {
|
|
93
|
+
throw new Error(`Invalid allowed Host entry: ${host}`);
|
|
94
|
+
}
|
|
95
|
+
return trimmed;
|
|
96
|
+
}
|
|
97
|
+
function normalizeAllowedHosts(rawHosts, derivedHosts) {
|
|
98
|
+
const hosts = rawHosts.length > 0 ? rawHosts : derivedHosts;
|
|
99
|
+
if (hosts.some((host) => host.trim() === "*"))
|
|
100
|
+
return ["*"];
|
|
101
|
+
return Array.from(new Set(hosts.map(normalizeAllowedHost)));
|
|
102
|
+
}
|
|
103
|
+
function parseBoolean(value, name = "boolean value") {
|
|
104
|
+
if (value === undefined)
|
|
105
|
+
return false;
|
|
106
|
+
if (typeof value === "boolean")
|
|
107
|
+
return value;
|
|
108
|
+
const normalized = value.trim().toLowerCase();
|
|
109
|
+
if (["1", "true", "yes", "on"].includes(normalized))
|
|
110
|
+
return true;
|
|
111
|
+
if (["0", "false", "no", "off"].includes(normalized))
|
|
112
|
+
return false;
|
|
113
|
+
throw new Error(`Invalid ${name}: ${value}`);
|
|
114
|
+
}
|
|
115
|
+
function parseMinimalTools(env) {
|
|
116
|
+
if (env.AUVRYNT_TOOL_MODE === "minimal")
|
|
117
|
+
return true;
|
|
118
|
+
if (env.AUVRYNT_TOOL_MODE === "full")
|
|
119
|
+
return false;
|
|
120
|
+
if (env.AUVRYNT_TOOL_MODE) {
|
|
121
|
+
throw new Error(`Invalid AUVRYNT_TOOL_MODE: ${env.AUVRYNT_TOOL_MODE}`);
|
|
122
|
+
}
|
|
123
|
+
if (env.AUVRYNT_MINIMAL_TOOLS !== undefined)
|
|
124
|
+
return parseBoolean(env.AUVRYNT_MINIMAL_TOOLS);
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
function parseLogLevel(value) {
|
|
128
|
+
if (!value || value === "info")
|
|
129
|
+
return "info";
|
|
130
|
+
if (["silent", "error", "warn", "debug"].includes(value))
|
|
131
|
+
return value;
|
|
132
|
+
throw new Error(`Invalid AUVRYNT_LOG_LEVEL: ${value}`);
|
|
133
|
+
}
|
|
134
|
+
function parseLogFormat(value) {
|
|
135
|
+
if (!value || value === "json")
|
|
136
|
+
return "json";
|
|
137
|
+
if (value === "pretty")
|
|
138
|
+
return "pretty";
|
|
139
|
+
throw new Error(`Invalid AUVRYNT_LOG_FORMAT: ${value}`);
|
|
140
|
+
}
|
|
141
|
+
function parsePathList(value) {
|
|
142
|
+
return (value
|
|
143
|
+
?.split(",")
|
|
144
|
+
.map((entry) => entry.trim())
|
|
145
|
+
.filter(Boolean)
|
|
146
|
+
.map((entry) => resolve(expandHomePath(entry))) ?? []);
|
|
147
|
+
}
|
|
148
|
+
function parseStringList(value, fallback) {
|
|
149
|
+
const entries = value
|
|
150
|
+
?.split(",")
|
|
151
|
+
.map((entry) => entry.trim())
|
|
152
|
+
.filter(Boolean);
|
|
153
|
+
return entries && entries.length > 0 ? entries : fallback;
|
|
154
|
+
}
|
|
155
|
+
function parsePositiveInteger(value, fallback, name) {
|
|
156
|
+
if (value === undefined || value === "")
|
|
157
|
+
return fallback;
|
|
158
|
+
const parsed = Number(value);
|
|
159
|
+
if (!Number.isInteger(parsed) || parsed < 1) {
|
|
160
|
+
throw new Error(`Invalid ${name}: ${value}`);
|
|
161
|
+
}
|
|
162
|
+
return parsed;
|
|
163
|
+
}
|
|
164
|
+
function parseMcpSessionLimit(value, fallback, name) {
|
|
165
|
+
const parsed = parsePositiveInteger(value, fallback, name);
|
|
166
|
+
if (parsed > MAX_MCP_SESSIONS) {
|
|
167
|
+
throw new Error(`Invalid ${name}: ${value}. Maximum is ${MAX_MCP_SESSIONS}.`);
|
|
168
|
+
}
|
|
169
|
+
return parsed;
|
|
170
|
+
}
|
|
171
|
+
function parseSessionIdleTimeout(value, fallback, name) {
|
|
172
|
+
const parsed = parsePositiveInteger(value, fallback, name);
|
|
173
|
+
if (parsed < MIN_SESSION_IDLE_TIMEOUT_MS || parsed > MAX_SESSION_IDLE_TIMEOUT_MS) {
|
|
174
|
+
throw new Error(`Invalid ${name}: ${value}. Must be between ${MIN_SESSION_IDLE_TIMEOUT_MS} and ${MAX_SESSION_IDLE_TIMEOUT_MS} milliseconds.`);
|
|
175
|
+
}
|
|
176
|
+
return parsed;
|
|
177
|
+
}
|
|
178
|
+
function parseToolNaming(value) {
|
|
179
|
+
if (!value || value === "short")
|
|
180
|
+
return "short";
|
|
181
|
+
if (value === "legacy")
|
|
182
|
+
return "legacy";
|
|
183
|
+
throw new Error(`Invalid AUVRYNT_TOOL_NAMING: ${value}`);
|
|
184
|
+
}
|
|
185
|
+
function parseLoggingConfig(env) {
|
|
186
|
+
return {
|
|
187
|
+
level: parseLogLevel(env.AUVRYNT_LOG_LEVEL),
|
|
188
|
+
format: parseLogFormat(env.AUVRYNT_LOG_FORMAT),
|
|
189
|
+
requests: env.AUVRYNT_LOG_REQUESTS === undefined ? true : parseBoolean(env.AUVRYNT_LOG_REQUESTS),
|
|
190
|
+
assets: parseBoolean(env.AUVRYNT_LOG_ASSETS),
|
|
191
|
+
toolCalls: env.AUVRYNT_LOG_TOOL_CALLS === undefined ? true : parseBoolean(env.AUVRYNT_LOG_TOOL_CALLS),
|
|
192
|
+
shellCommands: parseBoolean(env.AUVRYNT_LOG_SHELL_COMMANDS),
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
function parseWidgetMode(value) {
|
|
196
|
+
if (!value || value === "full")
|
|
197
|
+
return "full";
|
|
198
|
+
if (value === "off" || value === "changes")
|
|
199
|
+
return value;
|
|
200
|
+
throw new Error(`Invalid AUVRYNT_WIDGETS: ${value}`);
|
|
201
|
+
}
|
|
202
|
+
function parseTunnelProvider(value, fileValue) {
|
|
203
|
+
const effective = value ?? fileValue;
|
|
204
|
+
if (!effective || effective === "cloudflare")
|
|
205
|
+
return "cloudflare";
|
|
206
|
+
if (effective === "ngrok" || effective === "custom")
|
|
207
|
+
return effective;
|
|
208
|
+
throw new Error(`Invalid AUVRYNT_TUNNEL_PROVIDER: ${effective}. Use "cloudflare", "ngrok", or "custom".`);
|
|
209
|
+
}
|
|
210
|
+
function parseRequiredSecret(value, name) {
|
|
211
|
+
const secret = value?.trim();
|
|
212
|
+
if (!secret) {
|
|
213
|
+
throw new Error(`${name} is required for Auvrynt OAuth. Run: auvrynt init`);
|
|
214
|
+
}
|
|
215
|
+
if (secret.length < 16) {
|
|
216
|
+
throw new Error(`${name} must be at least 16 characters long.`);
|
|
217
|
+
}
|
|
218
|
+
return secret;
|
|
219
|
+
}
|
|
220
|
+
function parseOAuthScopes(value) {
|
|
221
|
+
const requested = parseStringList(value, DEFAULT_OAUTH_SCOPES);
|
|
222
|
+
const supported = new Set(SUPPORTED_SCOPES);
|
|
223
|
+
const invalid = requested.filter((scope) => !supported.has(scope));
|
|
224
|
+
if (invalid.length > 0) {
|
|
225
|
+
throw new Error(`Invalid AUVRYNT_OAUTH_SCOPES: unsupported scope(s): ${invalid.join(", ")}`);
|
|
226
|
+
}
|
|
227
|
+
return Array.from(new Set(requested));
|
|
228
|
+
}
|
|
229
|
+
export function oauthScopesForIntegrations(integrations) {
|
|
230
|
+
const scopes = ["auvrynt:read", "auvrynt:write"];
|
|
231
|
+
if (integrations.playwright)
|
|
232
|
+
scopes.push("auvrynt:web", "auvrynt:process");
|
|
233
|
+
if (integrations.godotGdscript || integrations.godotCsharp)
|
|
234
|
+
scopes.push("auvrynt:godot");
|
|
235
|
+
if (integrations.godotCsharp)
|
|
236
|
+
scopes.push("auvrynt:software", "auvrynt:process");
|
|
237
|
+
if (integrations.blender)
|
|
238
|
+
scopes.push("auvrynt:blender");
|
|
239
|
+
if (integrations.aseprite)
|
|
240
|
+
scopes.push("auvrynt:aseprite");
|
|
241
|
+
if (integrations.serena)
|
|
242
|
+
scopes.push("auvrynt:serena");
|
|
243
|
+
if (integrations.roblox)
|
|
244
|
+
scopes.push("auvrynt:roblox");
|
|
245
|
+
return Array.from(new Set(scopes));
|
|
246
|
+
}
|
|
247
|
+
function parseOAuthConfig(env, ownerToken) {
|
|
248
|
+
return {
|
|
249
|
+
ownerToken: parseRequiredSecret(env.AUVRYNT_OAUTH_OWNER_TOKEN ?? ownerToken, "AUVRYNT_OAUTH_OWNER_TOKEN"),
|
|
250
|
+
accessTokenTtlSeconds: parsePositiveInteger(env.AUVRYNT_OAUTH_ACCESS_TOKEN_TTL_SECONDS, DEFAULT_OAUTH_ACCESS_TOKEN_TTL_SECONDS, "AUVRYNT_OAUTH_ACCESS_TOKEN_TTL_SECONDS"),
|
|
251
|
+
refreshTokenTtlSeconds: parsePositiveInteger(env.AUVRYNT_OAUTH_REFRESH_TOKEN_TTL_SECONDS, DEFAULT_OAUTH_REFRESH_TOKEN_TTL_SECONDS, "AUVRYNT_OAUTH_REFRESH_TOKEN_TTL_SECONDS"),
|
|
252
|
+
// OAuth is the durable capability envelope. Local integration profiles are
|
|
253
|
+
// a second, runtime gate and may change without reconnecting the web agent.
|
|
254
|
+
scopes: parseOAuthScopes(env.AUVRYNT_OAUTH_SCOPES),
|
|
255
|
+
allowedRedirectHosts: parseStringList(env.AUVRYNT_OAUTH_ALLOWED_REDIRECT_HOSTS, [
|
|
256
|
+
"grok.com",
|
|
257
|
+
"console.x.ai",
|
|
258
|
+
"x.ai",
|
|
259
|
+
"chatgpt.com",
|
|
260
|
+
"openai.com",
|
|
261
|
+
"claude.ai",
|
|
262
|
+
"claude.com",
|
|
263
|
+
"claude.site",
|
|
264
|
+
"useclaude.ai",
|
|
265
|
+
"anthropic.com",
|
|
266
|
+
"oauth.lovable.app",
|
|
267
|
+
"lovable.app",
|
|
268
|
+
"lovable.dev",
|
|
269
|
+
"api.lovable.dev",
|
|
270
|
+
"bolt.new",
|
|
271
|
+
"clusy.io",
|
|
272
|
+
"app.clusy.io",
|
|
273
|
+
"docs.clusy.io",
|
|
274
|
+
"localhost",
|
|
275
|
+
"127.0.0.1",
|
|
276
|
+
]),
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
function defaultStateDir() {
|
|
280
|
+
return join(homedir(), ".local", "share", "auvrynt");
|
|
281
|
+
}
|
|
282
|
+
function defaultWorktreeRoot() {
|
|
283
|
+
return join(homedir(), ".auvrynt", "worktrees");
|
|
284
|
+
}
|
|
285
|
+
function defaultAgentDir() {
|
|
286
|
+
return join(homedir(), ".codex");
|
|
287
|
+
}
|
|
288
|
+
function parseObsidianConfig(env, filesConfig) {
|
|
289
|
+
const file = filesConfig.obsidian ?? {};
|
|
290
|
+
const vaultPath = (env.AUVRYNT_OBSIDIAN_VAULT ?? file.vaultPath)?.trim();
|
|
291
|
+
return {
|
|
292
|
+
enabled: parseOptionalIntegrationBoolean(env.AUVRYNT_OBSIDIAN_ENABLED, "AUVRYNT_OBSIDIAN_ENABLED") ?? file.enabled ?? false,
|
|
293
|
+
vaultPath: vaultPath ? expandHomePath(vaultPath) : undefined,
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
function parseSerenaConfig(env, filesConfig) {
|
|
297
|
+
const filesSerena = filesConfig.serena ?? {};
|
|
298
|
+
const backend = env.AUVRYNT_SERENA_BACKEND ?? filesSerena.backend ?? "LSP";
|
|
299
|
+
if (backend !== "LSP" && backend !== "JetBrains") {
|
|
300
|
+
throw new Error(`Invalid AUVRYNT_SERENA_BACKEND: ${backend}`);
|
|
301
|
+
}
|
|
302
|
+
return {
|
|
303
|
+
enabled: parseBoolean(env.AUVRYNT_SERENA_ENABLED ?? filesSerena.enabled ?? false, "AUVRYNT_SERENA_ENABLED"),
|
|
304
|
+
executable: env.AUVRYNT_SERENA_EXECUTABLE ?? env.AUVRYNT_SERENA_PATH ?? filesConfig.executables?.serena ?? filesSerena.executable ?? "serena",
|
|
305
|
+
backend,
|
|
306
|
+
context: env.AUVRYNT_SERENA_CONTEXT ?? filesSerena.context ?? "desktop-app",
|
|
307
|
+
startupTimeoutMs: parsePositiveInteger(env.AUVRYNT_SERENA_STARTUP_TIMEOUT ?? filesSerena.startupTimeoutMs, 30_000, "AUVRYNT_SERENA_STARTUP_TIMEOUT"),
|
|
308
|
+
requestTimeoutMs: parsePositiveInteger(env.AUVRYNT_SERENA_REQUEST_TIMEOUT ?? filesSerena.requestTimeoutMs, 60_000, "AUVRYNT_SERENA_REQUEST_TIMEOUT"),
|
|
309
|
+
idleTimeoutMinutes: parsePositiveInteger(env.AUVRYNT_SERENA_IDLE_TIMEOUT ?? filesSerena.idleTimeoutMinutes, 30, "AUVRYNT_SERENA_IDLE_TIMEOUT"),
|
|
310
|
+
maxInstances: parsePositiveInteger(env.AUVRYNT_SERENA_MAX_INSTANCES ?? filesSerena.maxInstances, 3, "AUVRYNT_SERENA_MAX_INSTANCES"),
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
function cleanExecutablePath(value) {
|
|
314
|
+
if (!value)
|
|
315
|
+
return undefined;
|
|
316
|
+
const trimmed = value.trim().replace(/^["']|["']$/g, "").trim();
|
|
317
|
+
return trimmed || undefined;
|
|
318
|
+
}
|
|
319
|
+
function parseExecutablesConfig(env, filesConfig) {
|
|
320
|
+
const configExecs = filesConfig.executables ?? {};
|
|
321
|
+
return {
|
|
322
|
+
serena: cleanExecutablePath(env.AUVRYNT_SERENA_PATH ?? configExecs.serena),
|
|
323
|
+
godot: cleanExecutablePath(env.AUVRYNT_GODOT_PATH ?? configExecs.godot),
|
|
324
|
+
godotCsharp: cleanExecutablePath(env.AUVRYNT_GODOT_CSHARP_PATH ?? configExecs.godotCsharp),
|
|
325
|
+
blender: cleanExecutablePath(env.AUVRYNT_BLENDER_PATH ?? configExecs.blender),
|
|
326
|
+
aseprite: cleanExecutablePath(env.AUVRYNT_ASEPRITE_PATH ?? configExecs.aseprite),
|
|
327
|
+
asepriteSource: cleanExecutablePath(env.AUVRYNT_ASEPRITE_SOURCE_PATH ?? configExecs.asepriteSource),
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
function parseOptionalIntegrationBoolean(value, name) {
|
|
331
|
+
if (value === undefined)
|
|
332
|
+
return undefined;
|
|
333
|
+
if (typeof value === "boolean" || typeof value === "string")
|
|
334
|
+
return parseBoolean(value, name);
|
|
335
|
+
throw new Error(`Invalid ${name}: expected boolean`);
|
|
336
|
+
}
|
|
337
|
+
function parseIntegrationsConfig(env, filesConfig) {
|
|
338
|
+
const configIntegrations = filesConfig.integrations ?? {};
|
|
339
|
+
return {
|
|
340
|
+
godotGdscript: parseOptionalIntegrationBoolean(env.AUVRYNT_GODOT_GDSCRIPT_ENABLED, "AUVRYNT_GODOT_GDSCRIPT_ENABLED") ?? configIntegrations.godotGdscript ?? false,
|
|
341
|
+
godotCsharp: parseOptionalIntegrationBoolean(env.AUVRYNT_GODOT_CSHARP_ENABLED, "AUVRYNT_GODOT_CSHARP_ENABLED") ?? configIntegrations.godotCsharp ?? false,
|
|
342
|
+
blender: parseOptionalIntegrationBoolean(env.AUVRYNT_BLENDER_ENABLED, "AUVRYNT_BLENDER_ENABLED") ?? configIntegrations.blender ?? false,
|
|
343
|
+
aseprite: parseOptionalIntegrationBoolean(env.AUVRYNT_ASEPRITE_ENABLED, "AUVRYNT_ASEPRITE_ENABLED") ?? configIntegrations.aseprite ?? false,
|
|
344
|
+
serena: parseOptionalIntegrationBoolean(env.AUVRYNT_SERENA_INTEGRATION_ENABLED ?? env.AUVRYNT_SERENA_ENABLED, "AUVRYNT_SERENA_INTEGRATION_ENABLED") ?? configIntegrations.serena ?? filesConfig.serena?.enabled ?? false,
|
|
345
|
+
playwright: parseOptionalIntegrationBoolean(env.AUVRYNT_PLAYWRIGHT_ENABLED, "AUVRYNT_PLAYWRIGHT_ENABLED") ?? configIntegrations.playwright ?? false,
|
|
346
|
+
context7: parseOptionalIntegrationBoolean(env.AUVRYNT_CONTEXT7_ENABLED, "AUVRYNT_CONTEXT7_ENABLED") ?? configIntegrations.context7 ?? false,
|
|
347
|
+
obsidian: parseOptionalIntegrationBoolean(env.AUVRYNT_OBSIDIAN_ENABLED, "AUVRYNT_OBSIDIAN_ENABLED") ?? configIntegrations.obsidian ?? filesConfig.obsidian?.enabled ?? false,
|
|
348
|
+
roblox: parseOptionalIntegrationBoolean(env.AUVRYNT_ROBLOX_ENABLED, "AUVRYNT_ROBLOX_ENABLED") ?? configIntegrations.roblox ?? false,
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
export function loadConfig(env = process.env) {
|
|
352
|
+
const files = loadAuvryntFiles(env);
|
|
353
|
+
const integrations = parseIntegrationsConfig(env, files.config);
|
|
354
|
+
const host = env.HOST ?? files.config.host ?? "127.0.0.1";
|
|
355
|
+
const port = parsePort(env.PORT ?? files.config.port);
|
|
356
|
+
const publicBaseUrl = parsePublicBaseUrl(env.AUVRYNT_PUBLIC_BASE_URL ?? files.config.publicBaseUrl ?? localPublicBaseUrl(host, port));
|
|
357
|
+
const derivedAllowedHosts = [
|
|
358
|
+
"localhost",
|
|
359
|
+
"127.0.0.1",
|
|
360
|
+
"::1",
|
|
361
|
+
host,
|
|
362
|
+
new URL(publicBaseUrl).hostname,
|
|
363
|
+
...(files.config.allowedHosts ?? []),
|
|
364
|
+
];
|
|
365
|
+
return {
|
|
366
|
+
host,
|
|
367
|
+
port,
|
|
368
|
+
oauth: parseOAuthConfig(env, files.auth.ownerToken),
|
|
369
|
+
allowedRoots: parseAllowedRoots(env.AUVRYNT_ALLOWED_ROOTS ?? files.config.allowedRoots),
|
|
370
|
+
allowedHosts: parseAllowedHosts(env.AUVRYNT_ALLOWED_HOSTS, derivedAllowedHosts),
|
|
371
|
+
maxSessions: parseMcpSessionLimit(env.AUVRYNT_MAX_SESSIONS ?? files.config.maxSessions, MAX_MCP_SESSIONS, "AUVRYNT_MAX_SESSIONS"),
|
|
372
|
+
maxSessionsPerClient: parseMcpSessionLimit(env.AUVRYNT_MAX_SESSIONS_PER_CLIENT ?? files.config.maxSessionsPerClient ?? files.config.maxSessions, MAX_MCP_SESSIONS, "AUVRYNT_MAX_SESSIONS_PER_CLIENT"),
|
|
373
|
+
sessionIdleTimeoutMs: parseSessionIdleTimeout(env.AUVRYNT_SESSION_IDLE_MS ?? files.config.sessionIdleTimeoutMs, DEFAULT_SESSION_IDLE_TIMEOUT_MS, "AUVRYNT_SESSION_IDLE_MS"),
|
|
374
|
+
publicBaseUrl,
|
|
375
|
+
minimalTools: parseMinimalTools(env),
|
|
376
|
+
toolNaming: parseToolNaming(env.AUVRYNT_TOOL_NAMING),
|
|
377
|
+
widgets: parseWidgetMode(env.AUVRYNT_WIDGETS),
|
|
378
|
+
stateDir: resolve(expandHomePath(env.AUVRYNT_STATE_DIR ?? files.config.stateDir ?? defaultStateDir())),
|
|
379
|
+
worktreeRoot: resolve(expandHomePath(env.AUVRYNT_WORKTREE_ROOT ?? files.config.worktreeRoot ?? defaultWorktreeRoot())),
|
|
380
|
+
skillsEnabled: env.AUVRYNT_SKILLS === undefined ? true : parseBoolean(env.AUVRYNT_SKILLS),
|
|
381
|
+
skillPaths: parsePathList(env.AUVRYNT_SKILL_PATHS),
|
|
382
|
+
agentDir: resolve(expandHomePath(env.AUVRYNT_AGENT_DIR ?? files.config.agentDir ?? defaultAgentDir())),
|
|
383
|
+
logging: parseLoggingConfig(env),
|
|
384
|
+
serena: parseSerenaConfig(env, files.config),
|
|
385
|
+
obsidian: parseObsidianConfig(env, files.config),
|
|
386
|
+
executables: parseExecutablesConfig(env, files.config),
|
|
387
|
+
integrations,
|
|
388
|
+
tunnelProvider: parseTunnelProvider(env.AUVRYNT_TUNNEL_PROVIDER, files.config.tunnelProvider),
|
|
389
|
+
cloudflareTunnelToken: env.AUVRYNT_CLOUDFLARE_TUNNEL_TOKEN?.trim() || files.auth.cloudflareTunnelToken,
|
|
390
|
+
ngrokAuthtoken: resolveNgrokAuthtoken(files, env),
|
|
391
|
+
ngrokUrl: normalizeNgrokUrl(env.AUVRYNT_NGROK_URL ?? files.config.ngrokUrl),
|
|
392
|
+
toolToggles: files.config.toolToggles ?? {},
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
function isLoopbackHostname(hostname) {
|
|
396
|
+
const normalized = hostname.toLowerCase().replace(/^\[|\]$/g, "");
|
|
397
|
+
if (normalized === "localhost")
|
|
398
|
+
return true;
|
|
399
|
+
const version = isIP(normalized);
|
|
400
|
+
return (version === 4 && normalized.startsWith("127.")) || (version === 6 && normalized === "::1");
|
|
401
|
+
}
|
|
402
|
+
function parsePublicBaseUrl(value) {
|
|
403
|
+
const parsed = new URL(value);
|
|
404
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
405
|
+
throw new Error(`Invalid AUVRYNT_PUBLIC_BASE_URL scheme: ${parsed.protocol}`);
|
|
406
|
+
}
|
|
407
|
+
if (parsed.protocol === "http:" && !isLoopbackHostname(parsed.hostname)) {
|
|
408
|
+
throw new Error("AUVRYNT_PUBLIC_BASE_URL must use HTTPS unless it points to a loopback host.");
|
|
409
|
+
}
|
|
410
|
+
if (parsed.username || parsed.password) {
|
|
411
|
+
throw new Error("AUVRYNT_PUBLIC_BASE_URL must not contain embedded credentials.");
|
|
412
|
+
}
|
|
413
|
+
if ((parsed.pathname && parsed.pathname !== "/") || parsed.search || parsed.hash) {
|
|
414
|
+
throw new Error("AUVRYNT_PUBLIC_BASE_URL must be an origin only (scheme, host, and optional port). Do not include a path, query, or fragment.");
|
|
415
|
+
}
|
|
416
|
+
return parsed.origin;
|
|
417
|
+
}
|
|
418
|
+
function localPublicBaseUrl(host, port) {
|
|
419
|
+
const publicHost = host === "0.0.0.0" || host === "::" ? "127.0.0.1" : host;
|
|
420
|
+
const formattedHost = publicHost.includes(":") && !publicHost.startsWith("[")
|
|
421
|
+
? `[${publicHost}]`
|
|
422
|
+
: publicHost;
|
|
423
|
+
return `http://${formattedHost}:${port}`;
|
|
424
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { loadAuvryntFiles, writeAuvryntAuth, } from "./user-config.js";
|
|
3
|
+
export function validateContext7ApiKey(value) {
|
|
4
|
+
if (typeof value !== "string")
|
|
5
|
+
throw new Error("Enter a valid Context7 API key.");
|
|
6
|
+
const key = value.trim();
|
|
7
|
+
if (key.length < 8 || key.length > 512) {
|
|
8
|
+
throw new Error("Context7 API keys must be between 8 and 512 characters.");
|
|
9
|
+
}
|
|
10
|
+
if (/\s|[\u0000-\u001f\u007f]/u.test(key)) {
|
|
11
|
+
throw new Error("Context7 API keys must not contain whitespace or control characters.");
|
|
12
|
+
}
|
|
13
|
+
return key;
|
|
14
|
+
}
|
|
15
|
+
export function context7ApiKeyFingerprint(key) {
|
|
16
|
+
return createHash("sha256").update(key).digest("hex").slice(0, 10).toUpperCase();
|
|
17
|
+
}
|
|
18
|
+
export function resolveContext7ApiKey(files = loadAuvryntFiles(), env = process.env) {
|
|
19
|
+
const override = env.AUVRYNT_CONTEXT7_API_KEY?.trim();
|
|
20
|
+
if (override)
|
|
21
|
+
return override;
|
|
22
|
+
const stored = files.auth.context7ApiKey?.trim();
|
|
23
|
+
return stored || undefined;
|
|
24
|
+
}
|
|
25
|
+
export function summarizeContext7Auth(files = loadAuvryntFiles(), env = process.env) {
|
|
26
|
+
const environmentOverride = Boolean(env.AUVRYNT_CONTEXT7_API_KEY?.trim());
|
|
27
|
+
const key = resolveContext7ApiKey(files, env);
|
|
28
|
+
if (!key) {
|
|
29
|
+
return { configured: false, environmentOverride };
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
configured: true,
|
|
33
|
+
fingerprint: context7ApiKeyFingerprint(key),
|
|
34
|
+
environmentOverride,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export function setContext7ApiKey(value, env = process.env) {
|
|
38
|
+
if (env.AUVRYNT_CONTEXT7_API_KEY?.trim()) {
|
|
39
|
+
throw new Error("AUVRYNT_CONTEXT7_API_KEY is set in the environment. Remove that override before saving a key in Secrets.");
|
|
40
|
+
}
|
|
41
|
+
const key = validateContext7ApiKey(value);
|
|
42
|
+
const files = loadAuvryntFiles(env);
|
|
43
|
+
writeAuvryntAuth({ ...files.auth, context7ApiKey: key }, env);
|
|
44
|
+
return { summary: summarizeContext7Auth(loadAuvryntFiles(env), env) };
|
|
45
|
+
}
|
|
46
|
+
export function clearContext7ApiKey(env = process.env) {
|
|
47
|
+
if (env.AUVRYNT_CONTEXT7_API_KEY?.trim()) {
|
|
48
|
+
throw new Error("AUVRYNT_CONTEXT7_API_KEY is set in the environment. Remove that override before clearing the saved key.");
|
|
49
|
+
}
|
|
50
|
+
const files = loadAuvryntFiles(env);
|
|
51
|
+
const next = { ...files.auth };
|
|
52
|
+
delete next.context7ApiKey;
|
|
53
|
+
writeAuvryntAuth(next, env);
|
|
54
|
+
return { summary: summarizeContext7Auth(loadAuvryntFiles(env), env) };
|
|
55
|
+
}
|