summer-engine 2.8.2 → 3.0.0
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/.claude-plugin/marketplace.json +27 -7
- package/.claude-plugin/plugin.json +99 -83
- package/.codex-plugin/plugin.json +112 -82
- package/.cursor-plugin/plugin.json +119 -83
- package/.factory-plugin/plugin.json +100 -3
- package/.mcp.json +6 -1
- package/.opencode/INSTALL.md +7 -4
- package/.opencode/plugins/summer.js +31 -18
- package/AGENTS.md +107 -34
- package/CHANGELOG.md +131 -44
- package/CLAUDE.md +4 -2
- package/GEMINI.md +7 -53
- package/NOTICE +31 -0
- package/README.md +159 -391
- package/assets/api-docs.json.gz +0 -0
- package/assets/autopilot/README.md +20 -6
- package/assets/autopilot/autopilot.gd +80 -26
- package/assets/autopilot/run.sh +132 -7
- package/assets/navigation/web-routes.json +719 -0
- package/commands/gameskill.md +10 -108
- package/commands/summer.md +72 -4
- package/dist/bin/summer.js +6 -87
- package/dist/cli/banner.d.ts +1 -0
- package/dist/cli/banner.js +33 -0
- package/dist/{commands → cli/commands}/config.js +1 -1
- package/dist/cli/commands/create.d.ts +30 -0
- package/dist/cli/commands/create.js +212 -0
- package/dist/{commands → cli/commands}/debug.js +2 -2
- package/dist/cli/commands/doctor.d.ts +2 -0
- package/dist/cli/commands/doctor.js +18 -0
- package/dist/cli/commands/events.d.ts +57 -0
- package/dist/cli/commands/events.js +158 -0
- package/dist/cli/commands/install.d.ts +50 -0
- package/dist/cli/commands/install.js +447 -0
- package/dist/cli/commands/list.js +72 -0
- package/dist/{commands → cli/commands}/login.js +33 -17
- package/dist/{commands → cli/commands}/logout.d.ts +1 -0
- package/dist/cli/commands/logout.js +19 -0
- package/dist/{commands → cli/commands}/memory.d.ts +1 -8
- package/dist/{commands → cli/commands}/memory.js +20 -11
- package/dist/cli/commands/open.d.ts +45 -0
- package/dist/cli/commands/open.js +216 -0
- package/dist/{commands → cli/commands}/plan.js +2 -2
- package/dist/{commands → cli/commands}/publish.js +1 -1
- package/dist/{commands → cli/commands}/releases.js +1 -1
- package/dist/cli/commands/run.d.ts +19 -0
- package/dist/cli/commands/run.js +255 -0
- package/dist/{commands → cli/commands}/setup.js +43 -89
- package/dist/{commands → cli/commands}/skills.js +85 -222
- package/dist/{commands → cli/commands}/status.d.ts +1 -0
- package/dist/cli/commands/status.js +62 -0
- package/dist/cli/commands/tool.d.ts +11 -0
- package/dist/cli/commands/tool.js +121 -0
- package/dist/cli/index.d.ts +6 -0
- package/dist/cli/index.js +89 -0
- package/dist/cli/root-action.d.ts +7 -0
- package/dist/cli/root-action.js +15 -0
- package/dist/{lib → core}/api-client.d.ts +106 -15
- package/dist/{lib → core}/api-client.js +267 -75
- package/dist/{lib → core}/async-op-lifecycle.d.ts +3 -4
- package/dist/{lib → core}/async-op-lifecycle.js +3 -4
- package/dist/{lib → core}/auth.d.ts +14 -6
- package/dist/{lib → core}/auth.js +56 -40
- package/dist/core/capabilities/agent-playbook.d.ts +20 -0
- package/dist/core/capabilities/agent-playbook.js +218 -0
- package/dist/core/capabilities/api-docs.d.ts +36 -0
- package/dist/core/capabilities/api-docs.js +118 -0
- package/dist/core/capabilities/asset-import.d.ts +49 -0
- package/dist/core/capabilities/asset-import.js +134 -0
- package/dist/core/capabilities/camera-view.d.ts +98 -0
- package/dist/core/capabilities/camera-view.js +222 -0
- package/dist/core/capabilities/capture.d.ts +63 -0
- package/dist/core/capabilities/capture.js +67 -0
- package/dist/core/capabilities/console-read.d.ts +17 -0
- package/dist/core/capabilities/console-read.js +21 -0
- package/dist/{lib → core/capabilities}/creator.d.ts +1 -29
- package/dist/{lib → core/capabilities}/creator.js +14 -33
- package/dist/{lib → core/capabilities}/debug-report.d.ts +1 -1
- package/dist/{lib → core/capabilities}/debug-report.js +12 -31
- package/dist/{commands → core/capabilities}/doctor.d.ts +7 -2
- package/dist/{commands → core/capabilities}/doctor.js +47 -73
- package/dist/core/capabilities/engine-fallbacks.d.ts +26 -0
- package/dist/core/capabilities/engine-fallbacks.js +36 -0
- package/dist/core/capabilities/engine-ops.d.ts +33 -0
- package/dist/core/capabilities/engine-ops.js +145 -0
- package/dist/core/capabilities/engine-receipt.d.ts +53 -0
- package/dist/core/capabilities/engine-receipt.js +134 -0
- package/dist/core/capabilities/events.d.ts +200 -0
- package/dist/core/capabilities/events.js +383 -0
- package/dist/core/capabilities/fabricate-mesh.d.ts +111 -0
- package/dist/core/capabilities/fabricate-mesh.js +165 -0
- package/dist/core/capabilities/frame-quality.d.ts +71 -0
- package/dist/core/capabilities/frame-quality.js +449 -0
- package/dist/core/capabilities/game-task-plan.d.ts +66 -0
- package/dist/{lib → core/capabilities}/game-task-plan.js +59 -8
- package/dist/core/capabilities/hdri-import.d.ts +90 -0
- package/dist/core/capabilities/hdri-import.js +250 -0
- package/dist/core/capabilities/image-generation.d.ts +24 -0
- package/dist/core/capabilities/image-generation.js +22 -0
- package/dist/core/capabilities/navigation/open.d.ts +156 -0
- package/dist/core/capabilities/navigation/open.js +567 -0
- package/dist/core/capabilities/navigation/render-product-map.d.ts +1 -0
- package/dist/core/capabilities/navigation/render-product-map.js +84 -0
- package/dist/core/capabilities/navigation/targets.d.ts +87 -0
- package/dist/core/capabilities/navigation/targets.js +250 -0
- package/dist/core/capabilities/play-determinism.d.ts +35 -0
- package/dist/core/capabilities/play-determinism.js +86 -0
- package/dist/core/capabilities/project-context.d.ts +114 -0
- package/dist/core/capabilities/project-context.js +249 -0
- package/dist/core/capabilities/runtime-control.d.ts +540 -0
- package/dist/core/capabilities/runtime-control.js +1011 -0
- package/dist/core/capabilities/scene-kind.d.ts +19 -0
- package/dist/core/capabilities/scene-kind.js +137 -0
- package/dist/core/capabilities/scene-script.d.ts +38 -0
- package/dist/core/capabilities/scene-script.js +45 -0
- package/dist/core/capabilities/tool-dispatch.d.ts +42 -0
- package/dist/core/capabilities/tool-dispatch.js +1490 -0
- package/dist/core/capabilities/ui-control.d.ts +179 -0
- package/dist/core/capabilities/ui-control.js +423 -0
- package/dist/core/capabilities/variant-types.d.ts +22 -0
- package/dist/core/capabilities/variant-types.js +101 -0
- package/dist/core/capability-skew.d.ts +205 -0
- package/dist/core/capability-skew.js +386 -0
- package/dist/{lib → core}/config.d.ts +11 -1
- package/dist/{lib → core}/config.js +13 -2
- package/dist/core/embeddings.d.ts +78 -0
- package/dist/core/embeddings.js +166 -0
- package/dist/core/engine-install.d.ts +105 -0
- package/dist/core/engine-install.js +190 -0
- package/dist/core/engine.d.ts +94 -0
- package/dist/{lib → core}/engine.js +74 -28
- package/dist/core/feedback/client.d.ts +88 -0
- package/dist/core/feedback/client.js +182 -0
- package/dist/{lib → core}/format.d.ts +0 -1
- package/dist/{lib → core}/format.js +1 -1
- package/dist/core/headless/connection.d.ts +86 -0
- package/dist/core/headless/connection.js +97 -0
- package/dist/core/headless/editor-connection.d.ts +26 -0
- package/dist/core/headless/editor-connection.js +81 -0
- package/dist/core/headless/mcp-routing.d.ts +38 -0
- package/dist/core/headless/mcp-routing.js +83 -0
- package/dist/core/headless/registry.d.ts +91 -0
- package/dist/core/headless/registry.js +226 -0
- package/dist/core/headless/resolve.d.ts +46 -0
- package/dist/core/headless/resolve.js +75 -0
- package/dist/core/headless/spawn.d.ts +46 -0
- package/dist/core/headless/spawn.js +205 -0
- package/dist/core/headless/worker-connection.d.ts +96 -0
- package/dist/core/headless/worker-connection.js +353 -0
- package/dist/core/headless/worker-engine-client.d.ts +58 -0
- package/dist/core/headless/worker-engine-client.js +246 -0
- package/dist/core/launch-posture.d.ts +170 -0
- package/dist/core/launch-posture.js +317 -0
- package/dist/core/library-read.d.ts +73 -0
- package/dist/core/library-read.js +279 -0
- package/dist/core/library-search.d.ts +143 -0
- package/dist/core/library-search.js +301 -0
- package/dist/{lib → core}/log-filters.js +4 -2
- package/dist/{lib → core}/mcp-log.js +2 -17
- package/dist/core/package-root.d.ts +9 -0
- package/dist/core/package-root.js +11 -0
- package/dist/core/redact.d.ts +20 -0
- package/dist/core/redact.js +64 -0
- package/dist/core/registry-search.d.ts +167 -0
- package/dist/core/registry-search.js +358 -0
- package/dist/core/skills-registry.d.ts +47 -0
- package/dist/core/skills-registry.js +83 -0
- package/dist/{lib → core}/store.js +11 -7
- package/dist/{lib → core}/summer-compatibility.js +3 -3
- package/dist/{lib → core}/telemetry.js +5 -2
- package/dist/core/templates.d.ts +98 -0
- package/dist/core/templates.js +241 -0
- package/dist/core/tool-errors.d.ts +30 -0
- package/dist/core/tool-errors.js +40 -0
- package/dist/core/trajectory.d.ts +80 -0
- package/dist/core/trajectory.js +307 -0
- package/dist/core/util/http.d.ts +13 -0
- package/dist/core/util/http.js +28 -0
- package/dist/core/util/json.d.ts +12 -0
- package/dist/core/util/json.js +21 -0
- package/dist/core/util/process.d.ts +3 -0
- package/dist/core/util/process.js +13 -0
- package/dist/core/util/sleep.d.ts +1 -0
- package/dist/core/util/sleep.js +3 -0
- package/dist/core/version.d.ts +3 -0
- package/dist/core/version.js +5 -0
- package/dist/{lib → installer}/agent-config.d.ts +20 -1
- package/dist/{lib → installer}/agent-config.js +138 -24
- package/dist/installer/legacy-skills.d.ts +26 -0
- package/dist/installer/legacy-skills.js +53 -0
- package/dist/installer/setup.d.ts +76 -0
- package/dist/installer/setup.js +146 -0
- package/dist/installer/skill-locations.d.ts +45 -0
- package/dist/installer/skill-locations.js +170 -0
- package/dist/installer/version-check.d.ts +174 -0
- package/dist/{lib → installer}/version-check.js +173 -42
- package/dist/{lib/mcp-boot-notice.d.ts → mcp/boot-notice.d.ts} +1 -1
- package/dist/{commands/mcp.js → mcp/command.js} +18 -6
- package/dist/mcp/server.d.ts +23 -3
- package/dist/mcp/server.js +122 -28
- package/dist/mcp/tools/asset-tools.js +62 -142
- package/dist/mcp/tools/creator-tools.js +5 -23
- package/dist/mcp/tools/debug-tools.js +61 -18
- package/dist/mcp/tools/event-tools.d.ts +14 -0
- package/dist/mcp/tools/event-tools.js +41 -0
- package/dist/mcp/tools/fabricate-tools.d.ts +2 -0
- package/dist/mcp/tools/fabricate-tools.js +28 -0
- package/dist/mcp/tools/feedback-tools.d.ts +77 -0
- package/dist/mcp/tools/feedback-tools.js +88 -0
- package/dist/mcp/tools/file-tools.js +6 -53
- package/dist/mcp/tools/generate-tools.js +37 -63
- package/dist/mcp/tools/library-tools.d.ts +11 -0
- package/dist/mcp/tools/library-tools.js +42 -0
- package/dist/mcp/tools/navigation-tools.d.ts +7 -0
- package/dist/mcp/tools/navigation-tools.js +37 -0
- package/dist/mcp/tools/perception-tools.d.ts +20 -0
- package/dist/mcp/tools/perception-tools.js +146 -0
- package/dist/mcp/tools/project-tools.d.ts +14 -0
- package/dist/mcp/tools/project-tools.js +72 -281
- package/dist/mcp/tools/runtime-tools.d.ts +2 -0
- package/dist/mcp/tools/runtime-tools.js +92 -0
- package/dist/mcp/tools/scene-tools.d.ts +3 -0
- package/dist/mcp/tools/scene-tools.js +68 -119
- package/dist/mcp/tools/script-tools.d.ts +3 -0
- package/dist/mcp/tools/script-tools.js +118 -0
- package/dist/mcp/tools/spatial-tools.d.ts +2 -0
- package/dist/mcp/tools/spatial-tools.js +485 -0
- package/dist/mcp/tools/text-json.d.ts +8 -0
- package/dist/mcp/tools/text-json.js +12 -0
- package/dist/mcp/tools/{cloud-tools.d.ts → ui-tools.d.ts} +1 -1
- package/dist/mcp/tools/ui-tools.js +82 -0
- package/dist/mcp/tools/visual-tools.d.ts +2 -7
- package/dist/mcp/tools/visual-tools.js +383 -101
- package/dist/mcp/tools/with-engine.d.ts +9 -15
- package/dist/mcp/tools/with-engine.js +60 -96
- package/dist/project-memory/project-manifest.d.ts +36 -0
- package/dist/project-memory/project-manifest.js +50 -0
- package/dist/project-memory/project-memory.d.ts +57 -0
- package/dist/{lib → project-memory}/project-memory.js +46 -0
- package/gemini-extension.json +103 -2
- package/hooks/hooks-cursor.json +2 -2
- package/hooks/hooks.json +2 -1
- package/hooks/pre-commit-doctor.sh +45 -39
- package/hooks/run-hook.cmd +30 -23
- package/hooks/run-hook.sh +20 -0
- package/hooks/session-start.sh +18 -7
- package/integrations/README.md +70 -0
- package/integrations/claude/README.md +19 -0
- package/integrations/claude/manifest-target.json +16 -0
- package/integrations/cline/README.md +13 -0
- package/integrations/cline/manifest-target.json +3 -0
- package/integrations/codex/README.md +15 -0
- package/integrations/codex/manifest-target.json +5 -0
- package/integrations/cursor/README.md +16 -0
- package/integrations/cursor/manifest-target.json +5 -0
- package/integrations/factory/README.md +26 -0
- package/integrations/factory/manifest-target.json +5 -0
- package/integrations/gemini/README.md +26 -0
- package/integrations/gemini/manifest-target.json +5 -0
- package/integrations/github-copilot/README.md +12 -0
- package/integrations/github-copilot/manifest-target.json +3 -0
- package/integrations/kilo-code/README.md +16 -0
- package/integrations/kilo-code/manifest-target.json +3 -0
- package/integrations/lm-studio/README.md +12 -0
- package/integrations/lm-studio/manifest-target.json +3 -0
- package/integrations/opencode/README.md +15 -0
- package/integrations/opencode/manifest-target.json +3 -0
- package/integrations/roo-code/README.md +13 -0
- package/integrations/roo-code/manifest-target.json +3 -0
- package/integrations/vscode-copilot/README.md +12 -0
- package/integrations/vscode-copilot/manifest-target.json +3 -0
- package/integrations/windsurf/README.md +13 -0
- package/integrations/windsurf/manifest-target.json +3 -0
- package/library/references/collaborative-protocol/resource.yaml +24 -0
- package/library/references/gd-style/resource.yaml +24 -0
- package/{references → library/references/godot-version}/godot-version.md +6 -6
- package/library/references/godot-version/resource.yaml +22 -0
- package/library/references/headless-routing/headless-routing.md +46 -0
- package/library/references/headless-routing/resource.yaml +24 -0
- package/library/references/mcp-fresh-chat-playbook/mcp-fresh-chat-playbook.md +49 -0
- package/library/references/mcp-fresh-chat-playbook/resource.yaml +23 -0
- package/library/references/mcp-tools-reference/mcp-tools-reference.md +271 -0
- package/library/references/mcp-tools-reference/resource.yaml +17 -0
- package/library/references/product-map/product-map.md +103 -0
- package/library/references/product-map/resource.yaml +33 -0
- package/{references → library/references/public-surface-language}/public-surface-language.md +5 -7
- package/library/references/public-surface-language/resource.yaml +17 -0
- package/library/references/summer-folder/resource.yaml +20 -0
- package/{references → library/references/summer-folder}/summer-folder.md +22 -21
- package/{skills/rendering-and-lighting → library/skills}/3d-lighting/SKILL.md +15 -11
- package/library/skills/3d-lighting/resource.yaml +27 -0
- package/{skills/audio → library/skills}/adaptive-music/SKILL.md +1 -1
- package/library/skills/adaptive-music/resource.yaml +28 -0
- package/library/skills/agent-playtesting/SKILL.md +148 -0
- package/library/skills/agent-playtesting/resource.yaml +52 -0
- package/library/skills/ambient-bed/resource.yaml +24 -0
- package/{skills/video → library/skills}/animated-loop/SKILL.md +1 -1
- package/library/skills/animated-loop/resource.yaml +27 -0
- package/{skills/animation → library/skills}/animation-tree/SKILL.md +29 -14
- package/library/skills/animation-tree/resource.yaml +33 -0
- package/{skills/rendering-and-lighting → library/skills}/art-direction/SKILL.md +3 -3
- package/library/skills/art-direction/resource.yaml +29 -0
- package/{skills/asset-pipeline → library/skills}/asset-strategy/SKILL.md +44 -44
- package/library/skills/asset-strategy/resource.yaml +63 -0
- package/{skills/audio → library/skills}/audio-direction/SKILL.md +7 -7
- package/library/skills/audio-direction/resource.yaml +32 -0
- package/library/skills/auto-fire-targeting/resource.yaml +22 -0
- package/{skills/scene-and-project → library/skills}/brainstorm-game/SKILL.md +8 -8
- package/library/skills/brainstorm-game/resource.yaml +30 -0
- package/{skills/workflow → library/skills}/brainstorming/SKILL.md +2 -22
- package/library/skills/brainstorming/resource.yaml +23 -0
- package/{skills/workflow → library/skills}/brainstorming/spec-document-reviewer-prompt.md +1 -1
- package/{skills/scene-and-project → library/skills}/browse-templates/SKILL.md +18 -18
- package/library/skills/browse-templates/resource.yaml +23 -0
- package/library/skills/celeste-momentum-platforming/SKILL.md +366 -0
- package/library/skills/celeste-momentum-platforming/resource.yaml +33 -0
- package/library/skills/character-animation-wiring/SKILL.md +249 -0
- package/library/skills/character-animation-wiring/resource.yaml +39 -0
- package/{skills/3d-assets → library/skills}/character-model/SKILL.md +25 -25
- package/library/skills/character-model/resource.yaml +36 -0
- package/{skills/2d-assets → library/skills}/character-portrait/SKILL.md +14 -14
- package/library/skills/character-portrait/resource.yaml +30 -0
- package/{skills/video → library/skills}/cinematic-cutscene/SKILL.md +2 -2
- package/library/skills/cinematic-cutscene/resource.yaml +29 -0
- package/{skills/2d-assets → library/skills}/concept-art/SKILL.md +15 -15
- package/library/skills/concept-art/resource.yaml +34 -0
- package/{skills/2d-assets → library/skills}/create-asset-sheet/SKILL.md +8 -8
- package/library/skills/create-asset-sheet/resource.yaml +33 -0
- package/{skills/debugging → library/skills}/debug/SKILL.md +3 -3
- package/library/skills/debug/resource.yaml +31 -0
- package/{skills/workflow → library/skills}/debugging-game-feel/SKILL.md +11 -11
- package/library/skills/debugging-game-feel/resource.yaml +25 -0
- package/{skills/level-design → library/skills}/design-level/SKILL.md +6 -6
- package/library/skills/design-level/resource.yaml +31 -0
- package/{skills/gameplay-mechanics → library/skills}/design-mechanic/SKILL.md +3 -3
- package/library/skills/design-mechanic/resource.yaml +31 -0
- package/{skills/ai-and-npcs → library/skills}/design-npc/SKILL.md +7 -3
- package/library/skills/design-npc/resource.yaml +29 -0
- package/{skills/workflow → library/skills}/diagnosing-perf-regressions/SKILL.md +10 -10
- package/library/skills/diagnosing-perf-regressions/resource.yaml +25 -0
- package/{skills/workflow → library/skills}/dispatching-parallel-agents/SKILL.md +8 -8
- package/library/skills/dispatching-parallel-agents/resource.yaml +23 -0
- package/library/skills/driving-the-editor-ui/SKILL.md +85 -0
- package/library/skills/driving-the-editor-ui/resource.yaml +46 -0
- package/{skills/3d-assets → library/skills}/environment-kit/SKILL.md +11 -11
- package/library/skills/environment-kit/resource.yaml +29 -0
- package/{skills/deployment → library/skills}/export-and-ship/SKILL.md +5 -5
- package/library/skills/export-and-ship/resource.yaml +32 -0
- package/library/skills/fabricating-assets/SKILL.md +195 -0
- package/library/skills/fabricating-assets/resource.yaml +52 -0
- package/{skills/animation → library/skills}/facial-and-lipsync/SKILL.md +23 -11
- package/library/skills/facial-and-lipsync/resource.yaml +36 -0
- package/{skills/character-controllers → library/skills}/fps-controller/SKILL.md +8 -4
- package/library/skills/fps-controller/resource.yaml +29 -0
- package/{skills/visual-effects → library/skills}/game-feel/SKILL.md +7 -7
- package/library/skills/game-feel/resource.yaml +27 -0
- package/library/skills/gameskill/SKILL.md +64 -0
- package/library/skills/gameskill/resource.yaml +22 -0
- package/library/skills/gdscript-patterns/resource.yaml +23 -0
- package/{skills/animation → library/skills}/generate-motion/SKILL.md +16 -16
- package/library/skills/generate-motion/resource.yaml +34 -0
- package/library/skills/godogen-visual-proof-game-generation/SKILL.md +223 -0
- package/library/skills/godogen-visual-proof-game-generation/resource.yaml +33 -0
- package/{skills/workflow → library/skills}/headless-scripting/SKILL.md +14 -7
- package/library/skills/headless-scripting/resource.yaml +26 -0
- package/library/skills/host-authoritative-state/resource.yaml +28 -0
- package/{skills/2d-assets → library/skills}/instantiate-asset-pack/SKILL.md +10 -12
- package/library/skills/instantiate-asset-pack/resource.yaml +29 -0
- package/{skills/workflow → library/skills}/investigating-bugs/SKILL.md +4 -4
- package/{skills/workflow → library/skills}/investigating-bugs/condition-based-waiting.md +8 -8
- package/library/skills/investigating-bugs/resource.yaml +24 -0
- package/{skills/workflow → library/skills}/investigating-bugs/root-cause-tracing.md +1 -7
- package/library/skills/lumera-single-image-scene-reconstruction/SKILL.md +164 -0
- package/library/skills/lumera-single-image-scene-reconstruction/resource.yaml +35 -0
- package/{skills/scene-and-project → library/skills}/make-game/SKILL.md +22 -22
- package/library/skills/make-game/resource.yaml +35 -0
- package/library/skills/music-track/resource.yaml +28 -0
- package/library/skills/navigate-summer/SKILL.md +61 -0
- package/library/skills/navigate-summer/resource.yaml +35 -0
- package/{skills/scene-and-project → library/skills}/new-project/SKILL.md +10 -10
- package/library/skills/new-project/resource.yaml +28 -0
- package/{skills/3d-assets → library/skills}/organic-model/SKILL.md +16 -16
- package/library/skills/organic-model/resource.yaml +32 -0
- package/{skills/multiplayer-and-networking → library/skills}/peer-to-peer-multiplayer/SKILL.md +2 -2
- package/library/skills/peer-to-peer-multiplayer/resource.yaml +28 -0
- package/{skills/2d-assets → library/skills}/pixel-art/SKILL.md +13 -13
- package/library/skills/pixel-art/resource.yaml +31 -0
- package/library/skills/play/resource.yaml +26 -0
- package/{skills/workflow → library/skills}/playtesting-a-feature/SKILL.md +41 -22
- package/library/skills/playtesting-a-feature/resource.yaml +31 -0
- package/{skills/animation → library/skills}/procedural-animation/SKILL.md +25 -10
- package/library/skills/procedural-animation/resource.yaml +33 -0
- package/{skills/3d-assets → library/skills}/prop-model/SKILL.md +13 -13
- package/library/skills/prop-model/resource.yaml +33 -0
- package/library/skills/psx-retro-rendering/SKILL.md +416 -0
- package/library/skills/psx-retro-rendering/resource.yaml +36 -0
- package/library/skills/realtime-wet-surfaces/SKILL.md +189 -0
- package/library/skills/realtime-wet-surfaces/resource.yaml +31 -0
- package/{skills/deployment → library/skills}/remote-deploy/SKILL.md +3 -3
- package/library/skills/remote-deploy/resource.yaml +23 -0
- package/{skills/animation → library/skills}/retarget/SKILL.md +15 -14
- package/library/skills/retarget/resource.yaml +33 -0
- package/library/skills/running-in-the-cloud/SKILL.md +103 -0
- package/library/skills/running-in-the-cloud/resource.yaml +33 -0
- package/{skills/scene-and-project → library/skills}/scene-composition/SKILL.md +8 -0
- package/library/skills/scene-composition/resource.yaml +27 -0
- package/library/skills/scene-hierarchy-design/SKILL.md +102 -0
- package/library/skills/scene-hierarchy-design/resource.yaml +31 -0
- package/library/skills/scene-scripting/SKILL.md +764 -0
- package/library/skills/scene-scripting/resource.yaml +58 -0
- package/{skills/level-design → library/skills}/scene-to-level/SKILL.md +16 -17
- package/library/skills/scene-to-level/resource.yaml +33 -0
- package/library/skills/setup-multiplayer/resource.yaml +28 -0
- package/library/skills/skill-create/SKILL.md +138 -0
- package/library/skills/skill-create/resource.yaml +25 -0
- package/{skills/workflow → library/skills}/skill-improve/SKILL.md +2 -2
- package/library/skills/skill-improve/resource.yaml +25 -0
- package/{skills/workflow → library/skills}/skill-test/SKILL.md +4 -4
- package/library/skills/skill-test/resource.yaml +26 -0
- package/library/skills/skintokens-auto-rigging/SKILL.md +200 -0
- package/library/skills/skintokens-auto-rigging/resource.yaml +38 -0
- package/{skills/2d-assets → library/skills}/skybox-panorama/SKILL.md +8 -8
- package/library/skills/skybox-panorama/resource.yaml +28 -0
- package/{skills/audio → library/skills}/sound-effect/SKILL.md +2 -2
- package/library/skills/sound-effect/resource.yaml +27 -0
- package/library/skills/spatial-placement/SKILL.md +74 -0
- package/library/skills/spatial-placement/resource.yaml +42 -0
- package/library/skills/spatial-placement/tests/spec.md +65 -0
- package/{skills/2d-assets → library/skills}/sprite-sheet/SKILL.md +12 -12
- package/library/skills/sprite-sheet/resource.yaml +32 -0
- package/{skills/2d-assets → library/skills}/tileable-texture/SKILL.md +9 -9
- package/library/skills/tileable-texture/resource.yaml +31 -0
- package/{skills/video → library/skills}/trailer-shot/SKILL.md +1 -1
- package/library/skills/trailer-shot/resource.yaml +27 -0
- package/{skills/performance → library/skills}/tune-performance/SKILL.md +6 -6
- package/library/skills/tune-performance/resource.yaml +31 -0
- package/library/skills/ui-basics/resource.yaml +25 -0
- package/{skills/2d-assets → library/skills}/ui-graphics/SKILL.md +11 -11
- package/library/skills/ui-graphics/resource.yaml +29 -0
- package/{skills/2d-assets → library/skills}/use-widget-asset/SKILL.md +4 -4
- package/library/skills/use-widget-asset/resource.yaml +29 -0
- package/{skills/workflow → library/skills}/using-summer/SKILL.md +12 -9
- package/library/skills/using-summer/resource.yaml +41 -0
- package/{skills/3d-assets → library/skills}/vehicle-model/SKILL.md +18 -18
- package/library/skills/vehicle-model/resource.yaml +34 -0
- package/{skills/workflow → library/skills}/verification-before-completion/SKILL.md +10 -10
- package/library/skills/verification-before-completion/resource.yaml +23 -0
- package/library/skills/verifying-scenes/SKILL.md +98 -0
- package/library/skills/verifying-scenes/resource.yaml +42 -0
- package/{skills/visual-effects/recipes/dissolve → library/skills/vfx-dissolve}/SKILL.md +31 -11
- package/library/skills/vfx-dissolve/resource.yaml +33 -0
- package/{skills/visual-effects/recipes/fire → library/skills/vfx-fire}/SKILL.md +43 -12
- package/library/skills/vfx-fire/_building-blocks/noise-3d-fbm.gdshaderinc +45 -0
- package/library/skills/vfx-fire/resource.yaml +35 -0
- package/{skills/visual-effects/recipes/hit-spark → library/skills/vfx-hit-spark}/SKILL.md +16 -10
- package/library/skills/vfx-hit-spark/_building-blocks/additive-billboard-particles.md +37 -0
- package/library/skills/vfx-hit-spark/resource.yaml +34 -0
- package/{skills/visual-effects/recipes/lightning → library/skills/vfx-lightning}/SKILL.md +24 -11
- package/library/skills/vfx-lightning/_building-blocks/additive-billboard-particles.md +37 -0
- package/library/skills/vfx-lightning/resource.yaml +33 -0
- package/{skills/visual-effects/recipes/magic-glow → library/skills/vfx-magic-glow}/SKILL.md +31 -11
- package/library/skills/vfx-magic-glow/_building-blocks/additive-billboard-particles.md +37 -0
- package/library/skills/vfx-magic-glow/resource.yaml +34 -0
- package/{skills/visual-effects/recipes/muzzle-flash → library/skills/vfx-muzzle-flash}/SKILL.md +29 -9
- package/library/skills/vfx-muzzle-flash/_building-blocks/additive-billboard-particles.md +37 -0
- package/library/skills/vfx-muzzle-flash/_building-blocks/trauma-shake-snippet.md +53 -0
- package/library/skills/vfx-muzzle-flash/resource.yaml +35 -0
- package/{skills/visual-effects/recipes/smoke → library/skills/vfx-smoke}/SKILL.md +35 -9
- package/library/skills/vfx-smoke/_building-blocks/noise-3d-fbm.gdshaderinc +45 -0
- package/library/skills/vfx-smoke/resource.yaml +32 -0
- package/{skills/visual-effects/recipes/water-ripple → library/skills/vfx-water-ripple}/SKILL.md +31 -9
- package/library/skills/vfx-water-ripple/_building-blocks/additive-billboard-particles.md +37 -0
- package/library/skills/vfx-water-ripple/resource.yaml +31 -0
- package/library/skills/voice-line/resource.yaml +27 -0
- package/library/skills/world-building-3d/SKILL.md +105 -0
- package/library/skills/world-building-3d/references/spatial-tools.md +50 -0
- package/library/skills/world-building-3d/resource.yaml +44 -0
- package/library/skills/world-building-3d/tests/spec.md +48 -0
- package/{skills/workflow → library/skills}/writing-plans/SKILL.md +19 -14
- package/library/skills/writing-plans/resource.yaml +23 -0
- package/{skills/workflow → library/skills}/writing-skills/SKILL.md +38 -44
- package/library/skills/writing-skills/resource.yaml +29 -0
- package/{skills/workflow → library/skills}/writing-skills/testing-skills-with-subagents.md +13 -14
- package/library/templates/2d-brario-platformer/resource.yaml +21 -0
- package/library/templates/2d-dungeon-roguelike/resource.yaml +23 -0
- package/library/templates/2d-grid-puzzle/resource.yaml +21 -0
- package/library/templates/2d-plants-and-zombies-tower-defense/resource.yaml +21 -0
- package/library/templates/2d-platformer/resource.yaml +24 -0
- package/library/templates/2d-rpg/resource.yaml +21 -0
- package/library/templates/2d-vampire-survivor-roguelike/resource.yaml +21 -0
- package/library/templates/3d-basic/resource.yaml +16 -0
- package/library/templates/3d-city-kit/resource.yaml +24 -0
- package/library/templates/3d-fps-old-school/resource.yaml +21 -0
- package/library/templates/3d-fps-simple-animated-npc/resource.yaml +21 -0
- package/library/templates/3d-lan-multiplayer-starter/resource.yaml +22 -0
- package/library/templates/3d-open-world-explore-tps/resource.yaml +21 -0
- package/library/templates/3d-procedural-road-world/resource.yaml +21 -0
- package/library/templates/3d-racing-game/resource.yaml +21 -0
- package/library/templates/3d-royale-clash-type/resource.yaml +21 -0
- package/library/templates/3d-third-person-controller/resource.yaml +21 -0
- package/library/templates/3d-voxel-sandbox/resource.yaml +24 -0
- package/library/templates/README.md +94 -0
- package/library/templates/empty/resource.yaml +16 -0
- package/library/tools/add-node/resource.yaml +60 -0
- package/library/tools/align-distribute-3d/resource.yaml +87 -0
- package/library/tools/api-docs/resource.yaml +57 -0
- package/library/tools/batch/resource.yaml +52 -0
- package/library/tools/camera-bookmark/resource.yaml +73 -0
- package/library/tools/check-job/resource.yaml +45 -0
- package/library/tools/clear-console/resource.yaml +40 -0
- package/library/tools/connect-signal/resource.yaml +63 -0
- package/library/tools/create-debug-report/resource.yaml +67 -0
- package/library/tools/create-scene/resource.yaml +59 -0
- package/library/tools/creator-config/resource.yaml +63 -0
- package/library/tools/creator-publish/resource.yaml +73 -0
- package/library/tools/creator-releases/resource.yaml +53 -0
- package/library/tools/fabricate-3d/resource.yaml +108 -0
- package/library/tools/game-control/resource.yaml +84 -0
- package/library/tools/game-input/resource.yaml +159 -0
- package/library/tools/game-probe/resource.yaml +90 -0
- package/library/tools/generate-3d/resource.yaml +112 -0
- package/library/tools/generate-audio/resource.yaml +80 -0
- package/library/tools/generate-image/resource.yaml +62 -0
- package/library/tools/generate-motion/resource.yaml +66 -0
- package/library/tools/generate-video/resource.yaml +66 -0
- package/library/tools/get-agent-playbook/resource.yaml +40 -0
- package/library/tools/get-asset/resource.yaml +42 -0
- package/library/tools/get-asset-download-url/resource.yaml +52 -0
- package/library/tools/get-console/resource.yaml +69 -0
- package/library/tools/get-debugger-errors/resource.yaml +56 -0
- package/library/tools/get-debugger-warnings/resource.yaml +52 -0
- package/library/tools/get-diagnostics/resource.yaml +42 -0
- package/library/tools/get-project-context/resource.yaml +45 -0
- package/library/tools/get-runtime-tree/resource.yaml +62 -0
- package/library/tools/get-scene-tree/resource.yaml +52 -0
- package/library/tools/get-script-errors/resource.yaml +45 -0
- package/library/tools/get-studio-workflow/resource.yaml +43 -0
- package/library/tools/import-asset/resource.yaml +73 -0
- package/library/tools/import-asset-by-id/resource.yaml +56 -0
- package/library/tools/import-from-url/resource.yaml +51 -0
- package/library/tools/import-from-url-batch/resource.yaml +60 -0
- package/library/tools/import-hdri/resource.yaml +69 -0
- package/library/tools/input-map-bind/resource.yaml +52 -0
- package/library/tools/inspect-node/resource.yaml +46 -0
- package/library/tools/inspect-resource/resource.yaml +45 -0
- package/library/tools/inspect-runtime-node/resource.yaml +54 -0
- package/library/tools/instantiate-scene/resource.yaml +62 -0
- package/library/tools/is-running/resource.yaml +40 -0
- package/library/tools/library-feedback/resource.yaml +89 -0
- package/library/tools/list-my-assets/resource.yaml +56 -0
- package/library/tools/navigation-probe/resource.yaml +85 -0
- package/library/tools/open/resource.yaml +80 -0
- package/library/tools/open-main-scene/resource.yaml +40 -0
- package/library/tools/open-scene/resource.yaml +46 -0
- package/library/tools/play/resource.yaml +91 -0
- package/library/tools/project-setting/resource.yaml +53 -0
- package/library/tools/read-file/resource.yaml +47 -0
- package/library/tools/read-library/resource.yaml +67 -0
- package/library/tools/recent-events/resource.yaml +71 -0
- package/library/tools/remove-node/resource.yaml +51 -0
- package/library/tools/replace-node/resource.yaml +57 -0
- package/library/tools/replace-text/resource.yaml +61 -0
- package/library/tools/run-editor-script/resource.yaml +61 -0
- package/library/tools/run-script/resource.yaml +73 -0
- package/library/tools/runtime-animate/resource.yaml +140 -0
- package/library/tools/runtime-call/resource.yaml +74 -0
- package/library/tools/runtime-set/resource.yaml +80 -0
- package/library/tools/runtime-spawn/resource.yaml +95 -0
- package/library/tools/save-scene/resource.yaml +50 -0
- package/library/tools/screenshot/resource.yaml +112 -0
- package/library/tools/search-assets/resource.yaml +67 -0
- package/library/tools/search-library/resource.yaml +81 -0
- package/library/tools/select-node/resource.yaml +48 -0
- package/library/tools/set-prop/resource.yaml +64 -0
- package/library/tools/set-resource-property/resource.yaml +66 -0
- package/library/tools/slice-asset-sheet/resource.yaml +47 -0
- package/library/tools/snap-to-surface/resource.yaml +90 -0
- package/library/tools/snapshot-diff/resource.yaml +58 -0
- package/library/tools/starcast/resource.yaml +120 -0
- package/library/tools/start-game-task/resource.yaml +91 -0
- package/library/tools/stop/resource.yaml +51 -0
- package/library/tools/test-placement/resource.yaml +109 -0
- package/library/tools/ui-actions/resource.yaml +77 -0
- package/library/tools/ui-activate/resource.yaml +88 -0
- package/library/tools/ui-screenshot/resource.yaml +63 -0
- package/library/tools/ui-tree/resource.yaml +69 -0
- package/library/tools/wait-for-event/resource.yaml +84 -0
- package/library/tools/world-snapshot/resource.yaml +60 -0
- package/library/tools/write-file/resource.yaml +54 -0
- package/package.json +22 -16
- package/registry/generated/aliases.json +207 -0
- package/registry/generated/counts.json +12 -0
- package/registry/generated/gemini-extension.json +122 -0
- package/registry/generated/index.json +7709 -0
- package/registry/generated/marketplace.claude.json +44 -0
- package/registry/generated/mcp.json +13 -0
- package/registry/generated/plugin.claude.json +135 -0
- package/registry/generated/plugin.codex.json +144 -0
- package/registry/generated/plugin.cursor.json +134 -0
- package/registry/generated/plugin.factory.json +117 -0
- package/registry/generated/skills-registry.json +851 -0
- package/registry/generated/templates-registry.json +455 -0
- package/registry/schemas/allowed-hosts.json +19 -0
- package/registry/schemas/collection.schema.json +68 -0
- package/registry/schemas/domains.json +96 -0
- package/registry/schemas/example.schema.json +11 -0
- package/registry/schemas/reference.schema.json +10 -0
- package/registry/schemas/resource.schema.json +154 -0
- package/registry/schemas/skill.schema.json +14 -0
- package/registry/schemas/template.schema.json +46 -0
- package/registry/schemas/tool.schema.json +61 -0
- package/_persona/summer/SKILL.md +0 -113
- package/dist/bin/postinstall.d.ts +0 -2
- package/dist/bin/postinstall.js +0 -3
- package/dist/commands/cloud.d.ts +0 -2
- package/dist/commands/cloud.js +0 -80
- package/dist/commands/create.d.ts +0 -3
- package/dist/commands/create.js +0 -171
- package/dist/commands/install.d.ts +0 -19
- package/dist/commands/install.js +0 -194
- package/dist/commands/list.js +0 -67
- package/dist/commands/logout.js +0 -13
- package/dist/commands/logs.d.ts +0 -2
- package/dist/commands/logs.js +0 -19
- package/dist/commands/open.d.ts +0 -2
- package/dist/commands/open.js +0 -32
- package/dist/commands/orchestrator.d.ts +0 -8
- package/dist/commands/orchestrator.js +0 -143
- package/dist/commands/run.d.ts +0 -2
- package/dist/commands/run.js +0 -167
- package/dist/commands/status.js +0 -46
- package/dist/lib/banner.d.ts +0 -4
- package/dist/lib/banner.js +0 -122
- package/dist/lib/cloud/api.d.ts +0 -79
- package/dist/lib/cloud/api.js +0 -107
- package/dist/lib/cloud/apply.d.ts +0 -32
- package/dist/lib/cloud/apply.js +0 -294
- package/dist/lib/cloud/checkpoint.d.ts +0 -26
- package/dist/lib/cloud/checkpoint.js +0 -142
- package/dist/lib/cloud/conflicts.d.ts +0 -55
- package/dist/lib/cloud/conflicts.js +0 -131
- package/dist/lib/cloud/containment.d.ts +0 -8
- package/dist/lib/cloud/containment.js +0 -52
- package/dist/lib/cloud/diff.d.ts +0 -39
- package/dist/lib/cloud/diff.js +0 -138
- package/dist/lib/cloud/engine-bridge.d.ts +0 -34
- package/dist/lib/cloud/engine-bridge.js +0 -139
- package/dist/lib/cloud/hash-cache.d.ts +0 -23
- package/dist/lib/cloud/hash-cache.js +0 -44
- package/dist/lib/cloud/hash.d.ts +0 -10
- package/dist/lib/cloud/hash.js +0 -111
- package/dist/lib/cloud/http.d.ts +0 -17
- package/dist/lib/cloud/http.js +0 -47
- package/dist/lib/cloud/lock-path.d.ts +0 -1
- package/dist/lib/cloud/lock-path.js +0 -5
- package/dist/lib/cloud/lock.d.ts +0 -14
- package/dist/lib/cloud/lock.js +0 -143
- package/dist/lib/cloud/manifest.d.ts +0 -6
- package/dist/lib/cloud/manifest.js +0 -41
- package/dist/lib/cloud/paths.d.ts +0 -20
- package/dist/lib/cloud/paths.js +0 -90
- package/dist/lib/cloud/project-godot-merge.d.ts +0 -32
- package/dist/lib/cloud/project-godot-merge.js +0 -185
- package/dist/lib/cloud/rules.d.ts +0 -39
- package/dist/lib/cloud/rules.js +0 -159
- package/dist/lib/cloud/sync.d.ts +0 -21
- package/dist/lib/cloud/sync.js +0 -518
- package/dist/lib/cloud/transfer.d.ts +0 -23
- package/dist/lib/cloud/transfer.js +0 -184
- package/dist/lib/cloud/types.d.ts +0 -62
- package/dist/lib/cloud/types.js +0 -1
- package/dist/lib/cloud/validate-path.d.ts +0 -23
- package/dist/lib/cloud/validate-path.js +0 -103
- package/dist/lib/engine.d.ts +0 -51
- package/dist/lib/game-task-plan.d.ts +0 -42
- package/dist/lib/project-memory.d.ts +0 -33
- package/dist/lib/public-surface-paths.d.ts +0 -13
- package/dist/lib/public-surface-paths.js +0 -42
- package/dist/lib/remote-templates.d.ts +0 -25
- package/dist/lib/remote-templates.js +0 -86
- package/dist/lib/skills-registry.d.ts +0 -572
- package/dist/lib/skills-registry.js +0 -1061
- package/dist/lib/version-check.d.ts +0 -106
- package/dist/mcp/tools/cloud-tools.js +0 -42
- package/references/mcp-tools-reference.md +0 -199
- package/references/template-registry.md +0 -73
- package/skills/README.md +0 -103
- package/skills/scene-and-project/summer-cloud/SKILL.md +0 -92
- package/skills/workflow/brainstorming/scripts/frame-template.html +0 -214
- package/skills/workflow/brainstorming/scripts/helper.js +0 -88
- package/skills/workflow/brainstorming/scripts/server.cjs +0 -354
- package/skills/workflow/brainstorming/scripts/start-server.sh +0 -148
- package/skills/workflow/brainstorming/scripts/stop-server.sh +0 -56
- package/skills/workflow/brainstorming/visual-companion.md +0 -287
- package/skills/workflow/gameskill/SKILL.md +0 -120
- package/skills/workflow/investigating-bugs/CREATION-LOG.md +0 -119
- package/skills/workflow/investigating-bugs/condition-based-waiting-example.ts +0 -158
- package/skills/workflow/investigating-bugs/find-polluter.sh +0 -63
- package/skills/workflow/investigating-bugs/test-academic.md +0 -14
- package/skills/workflow/investigating-bugs/test-pressure-1.md +0 -58
- package/skills/workflow/investigating-bugs/test-pressure-2.md +0 -68
- package/skills/workflow/investigating-bugs/test-pressure-3.md +0 -69
- package/skills/workflow/mcpupdate/SKILL.md +0 -134
- package/skills/workflow/skill-create/SKILL.md +0 -153
- package/skills/workflow/writing-skills/anthropic-best-practices.md +0 -1150
- package/skills/workflow/writing-skills/examples/CLAUDE_MD_TESTING.md +0 -189
- package/skills/workflow/writing-skills/graphviz-conventions.dot +0 -172
- package/skills/workflow/writing-skills/persuasion-principles.md +0 -187
- package/skills/workflow/writing-skills/render-graphs.js +0 -168
- /package/dist/{commands → cli/commands}/config.d.ts +0 -0
- /package/dist/{commands → cli/commands}/debug.d.ts +0 -0
- /package/dist/{commands → cli/commands}/list.d.ts +0 -0
- /package/dist/{commands → cli/commands}/login.d.ts +0 -0
- /package/dist/{commands → cli/commands}/plan.d.ts +0 -0
- /package/dist/{commands → cli/commands}/publish.d.ts +0 -0
- /package/dist/{commands → cli/commands}/releases.d.ts +0 -0
- /package/dist/{commands → cli/commands}/setup.d.ts +0 -0
- /package/dist/{commands → cli/commands}/skills.d.ts +0 -0
- /package/dist/{lib → core}/log-filters.d.ts +0 -0
- /package/dist/{lib → core}/mcp-log.d.ts +0 -0
- /package/dist/{lib → core}/store.d.ts +0 -0
- /package/dist/{lib → core}/summer-compatibility.d.ts +0 -0
- /package/dist/{lib → core}/telemetry.d.ts +0 -0
- /package/dist/{lib/mcp-boot-notice.js → mcp/boot-notice.js} +0 -0
- /package/dist/{commands/mcp.d.ts → mcp/command.d.ts} +0 -0
- /package/{references → library/references/collaborative-protocol}/collaborative-protocol.md +0 -0
- /package/{references → library/references/gd-style}/gd-style.md +0 -0
- /package/{skills/audio → library/skills}/ambient-bed/SKILL.md +0 -0
- /package/{skills/gameplay-mechanics → library/skills}/auto-fire-targeting/SKILL.md +0 -0
- /package/{skills/scripting-patterns → library/skills}/gdscript-patterns/SKILL.md +0 -0
- /package/{skills/scripting-patterns → library/skills}/gdscript-patterns/reference.md +0 -0
- /package/{skills/multiplayer-and-networking → library/skills}/host-authoritative-state/SKILL.md +0 -0
- /package/{skills/workflow → library/skills}/investigating-bugs/defense-in-depth.md +0 -0
- /package/{skills/audio → library/skills}/music-track/SKILL.md +0 -0
- /package/{skills/scene-and-project → library/skills}/play/SKILL.md +0 -0
- /package/{skills/multiplayer-and-networking → library/skills}/setup-multiplayer/SKILL.md +0 -0
- /package/{skills/ui-and-ux → library/skills}/ui-basics/SKILL.md +0 -0
- /package/{skills/visual-effects → library/skills/vfx-dissolve}/_building-blocks/noise-3d-fbm.gdshaderinc +0 -0
- /package/{skills/visual-effects → library/skills/vfx-fire}/_building-blocks/additive-billboard-particles.md +0 -0
- /package/{skills/visual-effects → library/skills/vfx-lightning}/_building-blocks/trauma-shake-snippet.md +0 -0
- /package/{skills/audio → library/skills}/voice-line/SKILL.md +0 -0
- /package/{skills/workflow → library/skills}/writing-plans/plan-document-reviewer-prompt.md +0 -0
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { withEngine, missingEngineOpResult, ToolInputError, withOldEngineHint } from "./with-engine.js";
|
|
3
|
+
import { executeSceneMutation } from "./scene-tools.js";
|
|
4
|
+
// engine_lacks_op fallbacks: ONE copy for every face (E2E 2026-09-03 F-16).
|
|
5
|
+
import { ALIGN_DISTRIBUTE_FALLBACK, NAVIGATION_PROBE_FALLBACK, SNAP_TO_SURFACE_FALLBACK, STARCAST_FALLBACK, TEST_PLACEMENT_FALLBACK, } from "../../core/capabilities/engine-fallbacks.js";
|
|
6
|
+
/** Hard budget for one tool's model-visible result. These ops are designed to
|
|
7
|
+
* answer in a few hundred bytes; anything past this means the engine returned
|
|
8
|
+
* something this CLI does not understand (a newer/older receipt shape), and
|
|
9
|
+
* forwarding 40 KB of it to the model is worse than a 300-byte honest failure.
|
|
10
|
+
* Deliberately per-tool: v3 rejects a blanket cap in with-engine/server (see
|
|
11
|
+
* installResultSizeLogger) because the big read tools legitimately exceed it. */
|
|
12
|
+
const COMPACT_RESULT_LIMIT_BYTES = 5 * 1024;
|
|
13
|
+
const SCENE_PATH_LIMIT_BYTES = 512;
|
|
14
|
+
const NODE_PATH_LIMIT_BYTES = 256;
|
|
15
|
+
const MIN_PLACEMENT_FLOOR_DISTANCE = 0.001;
|
|
16
|
+
/** Mirrors the engine's SnapToSurface direction guard (length² > 1e-5). */
|
|
17
|
+
const MIN_SNAP_DIRECTION_LENGTH_SQUARED = 0.00001;
|
|
18
|
+
/** Starcast's own ceilings (engine spatial_ops.cpp starcast_3d): the engine
|
|
19
|
+
* measures the compact receipt as UTF-8 JSON, downgrades full -> summary
|
|
20
|
+
* above 12 KiB, and strips secondary paths above 5 KiB, so a receipt past the
|
|
21
|
+
* ceiling for its returnedDetail is one this CLI does not understand. Unlike
|
|
22
|
+
* COMPACT_RESULT_LIMIT_BYTES these are inclusive: the engine's contract is
|
|
23
|
+
* "at most". */
|
|
24
|
+
const STARCAST_SUMMARY_LIMIT_BYTES = 5 * 1024;
|
|
25
|
+
const STARCAST_FULL_LIMIT_BYTES = 12 * 1024;
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// Shared helpers
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
function snapDirectionExceedsNativeMinimum(direction) {
|
|
30
|
+
const lengthSquared = direction.reduce((sum, component) => sum + component * component, 0);
|
|
31
|
+
return Number.isFinite(lengthSquared) && lengthSquared > MIN_SNAP_DIRECTION_LENGTH_SQUARED;
|
|
32
|
+
}
|
|
33
|
+
/** Zod's .max() counts UTF-16 code units; the engine's limit is UTF-8 bytes.
|
|
34
|
+
* The schemas below carry the same byte-boundary refine, so a host that
|
|
35
|
+
* validates the schema never reaches these; they stay as the defence for
|
|
36
|
+
* direct callers and throw ToolInputError (classified "input", nothing sent —
|
|
37
|
+
* never "transport"). */
|
|
38
|
+
function requireBoundedExactPath(value, label, limitBytes, emptyMessage) {
|
|
39
|
+
const exactPath = value.trim();
|
|
40
|
+
if (!exactPath) {
|
|
41
|
+
throw new ToolInputError(emptyMessage ?? `${label} must name one exact path.`);
|
|
42
|
+
}
|
|
43
|
+
const pathBytes = Buffer.byteLength(exactPath, "utf8");
|
|
44
|
+
if (pathBytes > limitBytes) {
|
|
45
|
+
throw new ToolInputError(`${label} must be at most ${limitBytes} UTF-8 bytes after trimming.`);
|
|
46
|
+
}
|
|
47
|
+
return exactPath;
|
|
48
|
+
}
|
|
49
|
+
function requireBoundedSubjects(subjectPaths, min, max, combinedLimitBytes) {
|
|
50
|
+
const subjects = subjectPaths.map((path, index) => requireBoundedExactPath(path, `subjectPaths[${index}]`, NODE_PATH_LIMIT_BYTES));
|
|
51
|
+
if (subjects.length < min || subjects.length > max) {
|
|
52
|
+
throw new ToolInputError(`subjectPaths must contain ${min}..${max} exact paths.`);
|
|
53
|
+
}
|
|
54
|
+
if (subjects.reduce((sum, path) => sum + Buffer.byteLength(path, "utf8"), 0) > combinedLimitBytes) {
|
|
55
|
+
throw new ToolInputError(`Combined subject paths exceed the ${combinedLimitBytes}-byte UTF-8 limit.`);
|
|
56
|
+
}
|
|
57
|
+
if (new Set(subjects).size !== subjects.length) {
|
|
58
|
+
throw new ToolInputError("subjectPaths must not contain duplicates.");
|
|
59
|
+
}
|
|
60
|
+
return subjects;
|
|
61
|
+
}
|
|
62
|
+
/** The receipt's entry for `op` (a mutation batch also carries the SaveScene
|
|
63
|
+
* result), else the first result, else the raw receipt. */
|
|
64
|
+
function opResult(receipt, op) {
|
|
65
|
+
const results = receipt?.results;
|
|
66
|
+
if (!Array.isArray(results))
|
|
67
|
+
return receipt;
|
|
68
|
+
return results.find((entry) => entry?.op === op) ?? results[0] ?? receipt;
|
|
69
|
+
}
|
|
70
|
+
/** withEngine options that return ONLY the compact native op result (not the
|
|
71
|
+
* transport envelope) and fail loud with a tiny envelope if it is oversized. */
|
|
72
|
+
function compactResult(options) {
|
|
73
|
+
const resultText = (receipt) => JSON.stringify(opResult(receipt, options.op));
|
|
74
|
+
return {
|
|
75
|
+
onResult: (receipt) => {
|
|
76
|
+
const text = resultText(receipt);
|
|
77
|
+
const bytes = Buffer.byteLength(text, "utf8");
|
|
78
|
+
if (bytes < COMPACT_RESULT_LIMIT_BYTES)
|
|
79
|
+
return null;
|
|
80
|
+
return {
|
|
81
|
+
isError: true,
|
|
82
|
+
content: [{
|
|
83
|
+
type: "text",
|
|
84
|
+
text: JSON.stringify({
|
|
85
|
+
ok: false,
|
|
86
|
+
op: options.op,
|
|
87
|
+
failure_reason: options.failureReason,
|
|
88
|
+
...(options.extra ?? {}),
|
|
89
|
+
actualBytes: bytes,
|
|
90
|
+
limitBytes: COMPACT_RESULT_LIMIT_BYTES,
|
|
91
|
+
}),
|
|
92
|
+
}],
|
|
93
|
+
};
|
|
94
|
+
},
|
|
95
|
+
toContent: (receipt) => [{ type: "text", text: resultText(receipt) }],
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
const MUTATION_LANDED = { mutationApplied: true, saved: true, retrySafe: false };
|
|
99
|
+
const READ_ONLY = { readOnly: true };
|
|
100
|
+
/** withEngine options for summer_starcast: return ONLY the compact native op
|
|
101
|
+
* result and fail loud when it exceeds the ceiling for its returnedDetail
|
|
102
|
+
* (at most 5 KiB summary, at most 12 KiB full — the engine's own contract).
|
|
103
|
+
* A downgraded receipt (requestedDetail full, returnedDetail summary) is
|
|
104
|
+
* judged against the summary ceiling, exactly as the engine judged it. */
|
|
105
|
+
function starcastResult() {
|
|
106
|
+
const op = "Starcast3D";
|
|
107
|
+
const resultText = (receipt) => JSON.stringify(opResult(receipt, op));
|
|
108
|
+
const returnedDetail = (receipt) => {
|
|
109
|
+
const detail = opResult(receipt, op)?.returnedDetail;
|
|
110
|
+
return detail === "full" ? "full" : "summary";
|
|
111
|
+
};
|
|
112
|
+
return {
|
|
113
|
+
onResult: (receipt) => {
|
|
114
|
+
const text = resultText(receipt);
|
|
115
|
+
const bytes = Buffer.byteLength(text, "utf8");
|
|
116
|
+
const detail = returnedDetail(receipt);
|
|
117
|
+
const limitBytes = detail === "full" ? STARCAST_FULL_LIMIT_BYTES : STARCAST_SUMMARY_LIMIT_BYTES;
|
|
118
|
+
if (bytes <= limitBytes)
|
|
119
|
+
return null;
|
|
120
|
+
return {
|
|
121
|
+
isError: true,
|
|
122
|
+
content: [{
|
|
123
|
+
type: "text",
|
|
124
|
+
text: JSON.stringify({
|
|
125
|
+
ok: false,
|
|
126
|
+
op,
|
|
127
|
+
failure_reason: "starcast_result_exceeded_byte_limit",
|
|
128
|
+
...READ_ONLY,
|
|
129
|
+
returnedDetail: detail,
|
|
130
|
+
actualBytes: bytes,
|
|
131
|
+
limitBytes,
|
|
132
|
+
hint: "Update Summer Engine so Starcast3D returns its compact schema (schemaVersion 1).",
|
|
133
|
+
}),
|
|
134
|
+
}],
|
|
135
|
+
};
|
|
136
|
+
},
|
|
137
|
+
toContent: (receipt) => [{ type: "text", text: resultText(receipt) }],
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
// Every check the engine would reject on is expressed in the schema so the
|
|
141
|
+
// MCP host rejects the call BEFORE the handler runs (an -32602 invalid-args
|
|
142
|
+
// error, never a tool result that looks like an engine failure). Byte caps
|
|
143
|
+
// and dedupe live here as refines; the fn-side helpers above repeat them only
|
|
144
|
+
// for direct callers.
|
|
145
|
+
const utf8Within = (limitBytes) => (value) => Buffer.byteLength(value, "utf8") <= limitBytes;
|
|
146
|
+
const exactScenePath = z
|
|
147
|
+
.string()
|
|
148
|
+
.trim()
|
|
149
|
+
.min(1)
|
|
150
|
+
.max(SCENE_PATH_LIMIT_BYTES)
|
|
151
|
+
.refine(utf8Within(SCENE_PATH_LIMIT_BYTES), `scenePath must be at most ${SCENE_PATH_LIMIT_BYTES} UTF-8 bytes`);
|
|
152
|
+
const exactNodePath = z
|
|
153
|
+
.string()
|
|
154
|
+
.trim()
|
|
155
|
+
.min(1)
|
|
156
|
+
.max(NODE_PATH_LIMIT_BYTES)
|
|
157
|
+
.refine(utf8Within(NODE_PATH_LIMIT_BYTES), `node paths must be at most ${NODE_PATH_LIMIT_BYTES} UTF-8 bytes`);
|
|
158
|
+
const noDuplicates = (paths) => new Set(paths).size === paths.length;
|
|
159
|
+
const combinedUtf8Within = (limitBytes) => (paths) => paths.reduce((sum, path) => sum + Buffer.byteLength(path, "utf8"), 0) <= limitBytes;
|
|
160
|
+
/** Ordered, nonduplicate exact node paths with the engine's combined byte cap. */
|
|
161
|
+
const subjectPathList = (min, max, combinedLimitBytes) => z
|
|
162
|
+
.array(exactNodePath)
|
|
163
|
+
.min(min)
|
|
164
|
+
.max(max)
|
|
165
|
+
.refine(noDuplicates, "subjectPaths must not contain duplicates")
|
|
166
|
+
.refine(combinedUtf8Within(combinedLimitBytes), `Combined subject paths exceed the ${combinedLimitBytes}-byte UTF-8 limit`);
|
|
167
|
+
const finiteVector3 = z.tuple([z.number().finite(), z.number().finite(), z.number().finite()]);
|
|
168
|
+
// ---------------------------------------------------------------------------
|
|
169
|
+
// Registration
|
|
170
|
+
// ---------------------------------------------------------------------------
|
|
171
|
+
export function registerSpatialTools(server) {
|
|
172
|
+
server.tool("summer_test_placement", `Ghost-test one 3D node at an explicit candidate global pose without moving it or saving the scene.
|
|
173
|
+
|
|
174
|
+
Use this before placing a prop in a shelf, cubby, doorway, platform, or dense set. The compact result reports known overlap evidence, grounded state, signed floor gap, and at most eight overlapping object paths. Physics evidence uses enabled collider shapes; because Godot exposes no query-completeness bit, its overlap count is labeled a lower bound and an otherwise-clear physics result reports fits:null rather than claiming proof. visual_aabb evidence is a broad-phase fallback that also catches visible mesh-only obstacles.
|
|
175
|
+
|
|
176
|
+
The pose is always global/world-space: position and Euler rotation in degrees are both required, while the subject's current global scale is preserved. scenePath and subjectPath are exact; this tool never falls back to editor selection. The normal result is below 5 KB and the scene is never mutated. On an engine build that predates TestPlacement3D the result is a structured engine_lacks_op failure naming the fallback.`, {
|
|
177
|
+
scenePath: exactScenePath.describe("Exact scene path containing the subject, e.g. 'res://levels/workshop.tscn'."),
|
|
178
|
+
subjectPath: exactNodePath.describe("Exact node path relative to the scene root, e.g. './World/Crate'."),
|
|
179
|
+
candidateGlobalPosition: finiteVector3.describe("Candidate global/world position as [x, y, z]."),
|
|
180
|
+
candidateGlobalRotationDegrees: finiteVector3.describe("Candidate global/world Euler rotation in degrees as [x, y, z]; current global scale is preserved."),
|
|
181
|
+
collisionMask: z
|
|
182
|
+
.number()
|
|
183
|
+
.int()
|
|
184
|
+
.nonnegative()
|
|
185
|
+
.max(0xffffffff)
|
|
186
|
+
.optional()
|
|
187
|
+
.default(0xffffffff)
|
|
188
|
+
.describe("Godot 3D physics layers included in overlap and floor queries."),
|
|
189
|
+
collideWithAreas: z
|
|
190
|
+
.boolean()
|
|
191
|
+
.optional()
|
|
192
|
+
.default(true)
|
|
193
|
+
.describe("Include Area3D objects as placement obstacles/support candidates."),
|
|
194
|
+
maxFloorDistance: z
|
|
195
|
+
.number()
|
|
196
|
+
.min(MIN_PLACEMENT_FLOOR_DISTANCE)
|
|
197
|
+
.max(1000)
|
|
198
|
+
.optional()
|
|
199
|
+
.default(5)
|
|
200
|
+
.describe("Maximum world-space distance searched below the candidate footprint; range 0.001..1000."),
|
|
201
|
+
groundTolerance: z
|
|
202
|
+
.number()
|
|
203
|
+
.nonnegative()
|
|
204
|
+
.max(1)
|
|
205
|
+
.optional()
|
|
206
|
+
.default(0.05)
|
|
207
|
+
.describe("Absolute floor-gap tolerance used to classify grounded support."),
|
|
208
|
+
margin: z
|
|
209
|
+
.number()
|
|
210
|
+
.nonnegative()
|
|
211
|
+
.max(1)
|
|
212
|
+
.optional()
|
|
213
|
+
.default(0.001)
|
|
214
|
+
.describe("Physics shape-intersection margin; only an exact physics support collider+shape contact is excluded from overlaps."),
|
|
215
|
+
}, async ({ scenePath, subjectPath, candidateGlobalPosition, candidateGlobalRotationDegrees, collisionMask, collideWithAreas, maxFloorDistance, groundTolerance, margin, }) => withEngine(async (client) => {
|
|
216
|
+
const missing = missingEngineOpResult(client, "TestPlacement3D", TEST_PLACEMENT_FALLBACK);
|
|
217
|
+
if (missing)
|
|
218
|
+
return missing;
|
|
219
|
+
const exactScene = requireBoundedExactPath(scenePath, "scenePath", SCENE_PATH_LIMIT_BYTES);
|
|
220
|
+
const exactSubject = requireBoundedExactPath(subjectPath, "subjectPath", NODE_PATH_LIMIT_BYTES);
|
|
221
|
+
if (!Number.isFinite(maxFloorDistance) || maxFloorDistance < MIN_PLACEMENT_FLOOR_DISTANCE) {
|
|
222
|
+
throw new ToolInputError("maxFloorDistance must be at least 0.001.");
|
|
223
|
+
}
|
|
224
|
+
const receipt = await client.executeIdentityBoundOps([{
|
|
225
|
+
op: "TestPlacement3D",
|
|
226
|
+
subject_path: exactSubject,
|
|
227
|
+
candidate_global_position: candidateGlobalPosition,
|
|
228
|
+
candidate_global_rotation_degrees: candidateGlobalRotationDegrees,
|
|
229
|
+
collision_mask: collisionMask,
|
|
230
|
+
collide_with_areas: collideWithAreas,
|
|
231
|
+
max_floor_distance: maxFloorDistance,
|
|
232
|
+
ground_tolerance: groundTolerance,
|
|
233
|
+
margin,
|
|
234
|
+
}], { scenePath: exactScene });
|
|
235
|
+
return withOldEngineHint(receipt, "TestPlacement3D", TEST_PLACEMENT_FALLBACK);
|
|
236
|
+
}, compactResult({
|
|
237
|
+
op: "TestPlacement3D",
|
|
238
|
+
failureReason: "placement_result_exceeded_byte_limit",
|
|
239
|
+
extra: READ_ONLY,
|
|
240
|
+
})));
|
|
241
|
+
server.tool("summer_snap_to_surface", `Move one exact 3D subject along a world-space ray until its support face sits at the requested gap from the first surface. This changes only the subject's global transform, saves the scene, and is one reversible editor undo.
|
|
242
|
+
|
|
243
|
+
Use the default downward direction to seat props on floors, ramps, tables, or shelves. Set alignUp only when the prop should tilt to match the support normal.
|
|
244
|
+
|
|
245
|
+
EVIDENCE BOUNDARY:
|
|
246
|
+
- physics means Godot swept the subject's enabled collider shapes against body colliders and refined the first-contact bracket.
|
|
247
|
+
- visual_aabb is an explicit broad-phase fallback for mesh-only geometry; it does not prove triangle contact, and alignUp is not applied from that approximate normal.
|
|
248
|
+
- initiallyOverlapping and backoffDistance expose bounded pre-sweep recovery. The tool fails instead of teleporting when the subject cannot be cleared within maxDistance.
|
|
249
|
+
|
|
250
|
+
The normal result is bounded below 5 KB and returns before/after transforms, supportPath, finalGap with an error bound, slopeDeg, evidence, and warnings. scenePath and subjectPath are always required; there is no editor-selection fallback. On an engine build that predates SnapToSurface the result is a structured engine_lacks_op failure naming the fallback.`, {
|
|
251
|
+
scenePath: exactScenePath.describe("Exact scene containing the subject, e.g. 'res://levels/market.tscn'"),
|
|
252
|
+
subjectPath: exactNodePath.describe("Exact Node3D path relative to the scene root, e.g. './Props/Crate'"),
|
|
253
|
+
direction: finiteVector3
|
|
254
|
+
.refine(snapDirectionExceedsNativeMinimum, "direction squared length must exceed 0.00001")
|
|
255
|
+
.optional()
|
|
256
|
+
.default([0, -1, 0])
|
|
257
|
+
.describe("Finite world-space cast direction [x,y,z] whose squared length exceeds 0.00001. Defaults downward."),
|
|
258
|
+
maxDistance: z
|
|
259
|
+
.number()
|
|
260
|
+
.positive()
|
|
261
|
+
.max(10000)
|
|
262
|
+
.optional()
|
|
263
|
+
.default(20)
|
|
264
|
+
.describe("Maximum cast and overlap-recovery distance in scene units."),
|
|
265
|
+
gap: z
|
|
266
|
+
.number()
|
|
267
|
+
.nonnegative()
|
|
268
|
+
.max(10000)
|
|
269
|
+
.optional()
|
|
270
|
+
.default(0)
|
|
271
|
+
.describe("Requested separation from the support surface; must not exceed maxDistance."),
|
|
272
|
+
alignUp: z
|
|
273
|
+
.boolean()
|
|
274
|
+
.optional()
|
|
275
|
+
.default(false)
|
|
276
|
+
.describe("Rotate the subject's current world up toward an exact physics contact normal before seating it."),
|
|
277
|
+
}, async ({ scenePath, subjectPath, direction, maxDistance, gap, alignUp }) => withEngine(async (client) => {
|
|
278
|
+
const missing = missingEngineOpResult(client, "SnapToSurface", SNAP_TO_SURFACE_FALLBACK);
|
|
279
|
+
if (missing)
|
|
280
|
+
return missing;
|
|
281
|
+
const exactScene = requireBoundedExactPath(scenePath, "scenePath", SCENE_PATH_LIMIT_BYTES);
|
|
282
|
+
const exactSubject = requireBoundedExactPath(subjectPath, "subjectPath", NODE_PATH_LIMIT_BYTES, "subjectPath must name one exact Node3D; selection fallback is not supported.");
|
|
283
|
+
if (!snapDirectionExceedsNativeMinimum(direction)) {
|
|
284
|
+
throw new ToolInputError("direction squared length must exceed 0.00001.");
|
|
285
|
+
}
|
|
286
|
+
// Cross-field: a raw zod shape cannot express it, so it stays here.
|
|
287
|
+
if (gap > maxDistance)
|
|
288
|
+
throw new ToolInputError("gap must not exceed maxDistance.");
|
|
289
|
+
const receipt = await executeSceneMutation(client, exactScene, [{
|
|
290
|
+
op: "SnapToSurface",
|
|
291
|
+
subject_path: exactSubject,
|
|
292
|
+
direction,
|
|
293
|
+
max_distance: maxDistance,
|
|
294
|
+
gap,
|
|
295
|
+
align_up: alignUp,
|
|
296
|
+
}]);
|
|
297
|
+
return withOldEngineHint(receipt, "SnapToSurface", SNAP_TO_SURFACE_FALLBACK);
|
|
298
|
+
}, compactResult({
|
|
299
|
+
op: "SnapToSurface",
|
|
300
|
+
failureReason: "snap_to_surface_result_exceeded_byte_limit",
|
|
301
|
+
extra: MUTATION_LANDED,
|
|
302
|
+
})));
|
|
303
|
+
server.tool("summer_align_distribute_3d", `Align or equal-space an explicit ordered list of 3D subjects along one world-space axis, then save the exact target scene.
|
|
304
|
+
|
|
305
|
+
Every anchor and extent comes from visible descendant GeometryInstance3D world AABBs (evidence: visual_aabb). The tool never uses editor selection and fails instead of fabricating bounds. It preserves each subject's authored basis and scale, translates only along the normalized axis, and records all changed transforms in one undoable editor operation.
|
|
306
|
+
|
|
307
|
+
Alignment modes use the first ordered subject's minimum, center, or maximum projected anchor. Distribution modes keep the first and last subjects fixed and honor caller order. distribute_gaps accounts for each subject's projected half-extent and fails if the endpoint span cannot fit non-overlapping equal gaps. The compact result returns ordered before/after origins, resolved spacing, and numeric residuals under 5 KB. On an engine build that predates AlignDistribute3D the result is a structured engine_lacks_op failure naming the fallback.`, {
|
|
308
|
+
scenePath: exactScenePath.describe("Exact target scene, e.g. 'res://levels/market.tscn'."),
|
|
309
|
+
subjectPaths: subjectPathList(2, 16, 1536)
|
|
310
|
+
.describe("Two to sixteen exact nonduplicate Node3D paths in the order to align or distribute."),
|
|
311
|
+
axis: finiteVector3
|
|
312
|
+
.refine(([x, y, zValue]) => Math.hypot(x, y, zValue) > 1e-6, "axis must be non-zero")
|
|
313
|
+
.describe("Finite, non-zero world axis [x,y,z]; normalization is automatic."),
|
|
314
|
+
mode: z
|
|
315
|
+
.enum(["align_min", "align_center", "align_max", "distribute_centers", "distribute_gaps"])
|
|
316
|
+
.describe("Alignment anchor or equal-spacing policy."),
|
|
317
|
+
}, async ({ scenePath, subjectPaths, axis, mode }) => withEngine(async (client) => {
|
|
318
|
+
const missing = missingEngineOpResult(client, "AlignDistribute3D", ALIGN_DISTRIBUTE_FALLBACK);
|
|
319
|
+
if (missing)
|
|
320
|
+
return missing;
|
|
321
|
+
const exactScene = requireBoundedExactPath(scenePath, "scenePath", SCENE_PATH_LIMIT_BYTES);
|
|
322
|
+
const paths = requireBoundedSubjects(subjectPaths, 2, 16, 1536);
|
|
323
|
+
if (axis.some((component) => !Number.isFinite(component)) || Math.hypot(...axis) <= 1e-6) {
|
|
324
|
+
throw new ToolInputError("axis must contain three finite values and have non-zero length.");
|
|
325
|
+
}
|
|
326
|
+
const receipt = await executeSceneMutation(client, exactScene, [{
|
|
327
|
+
op: "AlignDistribute3D",
|
|
328
|
+
subject_paths: paths,
|
|
329
|
+
axis,
|
|
330
|
+
mode,
|
|
331
|
+
}]);
|
|
332
|
+
return withOldEngineHint(receipt, "AlignDistribute3D", ALIGN_DISTRIBUTE_FALLBACK);
|
|
333
|
+
}, compactResult({
|
|
334
|
+
op: "AlignDistribute3D",
|
|
335
|
+
failureReason: "align_result_exceeded_byte_limit",
|
|
336
|
+
extra: MUTATION_LANDED,
|
|
337
|
+
})));
|
|
338
|
+
server.tool("summer_navigation_probe", `Inspect whether two explicit world-space points are connected by the targeted 3D scene's built-in Godot navigation map without changing or saving the scene.
|
|
339
|
+
|
|
340
|
+
Returns navigation readiness and its reason, map iteration and region counts, requested and layer-filtered snapped endpoints, snap distances, conservative reachability, full route length, and at most 16 deterministic route points. A path is reachable only when it terminates at both snapped endpoints within the reported tolerance.
|
|
341
|
+
|
|
342
|
+
ready:false means navigation evidence is unavailable, not that the route is unreachable. In particular, map iteration 0 precedes the first usable synchronization and can return silently empty paths; iteration 1 and later are usable. evidence is always navigation. Normal results are capped below 5 KB.
|
|
343
|
+
|
|
344
|
+
Always pass an exact scenePath and finite world-space start/end points. This read-only tool never uses editor selection, creates undo history, or calls SaveScene. On an engine build that predates NavigationProbe3D the result is a structured engine_lacks_op failure naming the fallback.`, {
|
|
345
|
+
scenePath: exactScenePath.describe("Exact 3D scene whose World3D navigation map should be queried."),
|
|
346
|
+
start: finiteVector3.describe("Requested world-space route start [x,y,z]."),
|
|
347
|
+
end: finiteVector3.describe("Requested world-space route destination [x,y,z]."),
|
|
348
|
+
navigationLayers: z
|
|
349
|
+
.number()
|
|
350
|
+
.int()
|
|
351
|
+
.min(1)
|
|
352
|
+
.max(0xffffffff)
|
|
353
|
+
.optional()
|
|
354
|
+
.default(1)
|
|
355
|
+
.describe("Godot navigation-layer bitmask; only enabled matching regions are used."),
|
|
356
|
+
optimize: z
|
|
357
|
+
.boolean()
|
|
358
|
+
.optional()
|
|
359
|
+
.default(true)
|
|
360
|
+
.describe("Use Godot's corridor-funnel path post-processing; false uses edge-centered points."),
|
|
361
|
+
}, async ({ scenePath, start, end, navigationLayers, optimize }) => withEngine(async (client) => {
|
|
362
|
+
const missing = missingEngineOpResult(client, "NavigationProbe3D", NAVIGATION_PROBE_FALLBACK);
|
|
363
|
+
if (missing)
|
|
364
|
+
return missing;
|
|
365
|
+
const exactScene = requireBoundedExactPath(scenePath, "scenePath", SCENE_PATH_LIMIT_BYTES);
|
|
366
|
+
if (start.length !== 3 || end.length !== 3 ||
|
|
367
|
+
!start.every(Number.isFinite) || !end.every(Number.isFinite)) {
|
|
368
|
+
throw new ToolInputError("start and end must each contain exactly three finite world-space numbers.");
|
|
369
|
+
}
|
|
370
|
+
if (!Number.isInteger(navigationLayers) || navigationLayers < 1 || navigationLayers > 0xffffffff) {
|
|
371
|
+
throw new ToolInputError("navigationLayers must be an integer from 1 through 4294967295.");
|
|
372
|
+
}
|
|
373
|
+
const receipt = await client.executeIdentityBoundOps([{
|
|
374
|
+
op: "NavigationProbe3D",
|
|
375
|
+
start,
|
|
376
|
+
end,
|
|
377
|
+
navigation_layers: navigationLayers,
|
|
378
|
+
optimize,
|
|
379
|
+
}], { scenePath: exactScene });
|
|
380
|
+
return withOldEngineHint(receipt, "NavigationProbe3D", NAVIGATION_PROBE_FALLBACK);
|
|
381
|
+
}, compactResult({
|
|
382
|
+
op: "NavigationProbe3D",
|
|
383
|
+
failureReason: "navigation_probe_result_exceeded_byte_limit",
|
|
384
|
+
extra: { ...READ_ONLY, evidence: "navigation" },
|
|
385
|
+
})));
|
|
386
|
+
server.tool("summer_starcast", `Read a 3D spatial rundown for one exact node in an exact scene without moving it or saving the scene: 26 directional clearance casts (6 axes, 12 edges, 8 corners) from the subject's bounds, contact-or-overlap evidence, grounded state, and, in full detail, bounded nearby-object lists. Use it before and after placing an object to learn which side is blocked, by what, and at what distance.
|
|
387
|
+
|
|
388
|
+
detail 'summary' (default) is a placement report of at most 5 KB: subject position and size, grounded and contactStatus, deduplicated contact paths, one compact record per direction (status open|blocked, nearest distance, object, evidence, relationship), coverage, and warnings. detail 'full' adds per-direction hit geometry, an objects table, nearby lists, and the query echo, at most 12 KB; the engine downgrades to summary rather than exceed that (warning full_result_exceeded_12kb_returned_summary) and always reports requestedDetail vs returnedDetail.
|
|
389
|
+
|
|
390
|
+
EVIDENCE BOUNDARY:
|
|
391
|
+
- evidence 'physics' uses Godot's PhysicsDirectSpaceState3D against exact collider geometry on collisionMask. Shape intersections say contact_or_overlap because the query does not establish penetration depth; touching and anything within margin are included.
|
|
392
|
+
- evidence 'visual_aabb' uses visible world-axis-aligned bounding boxes: it catches meshes without colliders but is broad-phase only, never triangle-level contact.
|
|
393
|
+
- Lights, cameras, audio, navigation, scripts, and plain Nodes are not obstacles unless they own visual or collision geometry. One representative ray per direction can miss off-center geometry.
|
|
394
|
+
|
|
395
|
+
scenePath and path are exact; editor selection is never consulted. This tool is read-only: it never moves the node or saves the scene. On an engine build that predates Starcast3D the result is a structured engine_lacks_op failure naming the fallback.`, {
|
|
396
|
+
scenePath: exactScenePath.describe("Exact scene containing the subject, e.g. 'res://levels/level1.tscn'."),
|
|
397
|
+
path: exactNodePath.describe("Exact Node3D path relative to the scene root, e.g. './World/Crate'."),
|
|
398
|
+
detail: z
|
|
399
|
+
.enum(["summary", "full"])
|
|
400
|
+
.optional()
|
|
401
|
+
.default("summary")
|
|
402
|
+
.describe("summary: compact placement report (at most 5 KB). full: adds bounded hit geometry, an objects table, and nearby lists (at most 12 KB; the engine downgrades to summary rather than exceed it)."),
|
|
403
|
+
maxDistance: z
|
|
404
|
+
.number()
|
|
405
|
+
.positive()
|
|
406
|
+
.max(10000)
|
|
407
|
+
.optional()
|
|
408
|
+
.default(20)
|
|
409
|
+
.describe("Maximum outward cast distance in scene units."),
|
|
410
|
+
nearbyRadius: z
|
|
411
|
+
.number()
|
|
412
|
+
.nonnegative()
|
|
413
|
+
.max(10000)
|
|
414
|
+
.optional()
|
|
415
|
+
.default(10)
|
|
416
|
+
.describe("Maximum gap from the subject bounds for the nearby-object lists (full detail)."),
|
|
417
|
+
directionSpace: z
|
|
418
|
+
.enum(["world", "local"])
|
|
419
|
+
.optional()
|
|
420
|
+
.default("world")
|
|
421
|
+
.describe("Cast along world axes, or along the subject's orthonormalized local axes when 'front', 'side', or 'up' mean the rotated subject's own orientation."),
|
|
422
|
+
collisionMask: z
|
|
423
|
+
.number()
|
|
424
|
+
.int()
|
|
425
|
+
.nonnegative()
|
|
426
|
+
.max(0xffffffff)
|
|
427
|
+
.optional()
|
|
428
|
+
.default(0xffffffff)
|
|
429
|
+
.describe("Godot 3D physics layer mask queried by rays, shape contacts/overlaps, and nearby-collider scans."),
|
|
430
|
+
collideWithAreas: z
|
|
431
|
+
.boolean()
|
|
432
|
+
.optional()
|
|
433
|
+
.default(true)
|
|
434
|
+
.describe("Include Area3D objects as well as physics bodies."),
|
|
435
|
+
maxHitsPerDirection: z
|
|
436
|
+
.number()
|
|
437
|
+
.int()
|
|
438
|
+
.min(1)
|
|
439
|
+
.max(8)
|
|
440
|
+
.optional()
|
|
441
|
+
.default(3)
|
|
442
|
+
.describe("Maximum physics hits and visual AABB hits retained for each direction."),
|
|
443
|
+
maxResults: z
|
|
444
|
+
.number()
|
|
445
|
+
.int()
|
|
446
|
+
.min(1)
|
|
447
|
+
.max(128)
|
|
448
|
+
.optional()
|
|
449
|
+
.default(64)
|
|
450
|
+
.describe("Maximum retained contact/overlap and nearby entries per evidence channel."),
|
|
451
|
+
margin: z
|
|
452
|
+
.number()
|
|
453
|
+
.nonnegative()
|
|
454
|
+
.max(1)
|
|
455
|
+
.optional()
|
|
456
|
+
.default(0.001)
|
|
457
|
+
.describe("Tolerance for exact-geometry physics shape intersection queries; touching and candidates within this margin are reported as contact_or_overlap."),
|
|
458
|
+
}, async ({ scenePath, path, detail, maxDistance, nearbyRadius, directionSpace, collisionMask, collideWithAreas, maxHitsPerDirection, maxResults, margin, }) => withEngine(async (client) => {
|
|
459
|
+
const missing = missingEngineOpResult(client, "Starcast3D", STARCAST_FALLBACK);
|
|
460
|
+
if (missing)
|
|
461
|
+
return missing;
|
|
462
|
+
const exactScene = requireBoundedExactPath(scenePath, "scenePath", SCENE_PATH_LIMIT_BYTES);
|
|
463
|
+
const exactSubject = requireBoundedExactPath(path, "path", NODE_PATH_LIMIT_BYTES, "path must name one exact Node3D; selection fallback is not supported.");
|
|
464
|
+
if (!Number.isFinite(maxDistance) || maxDistance <= 0) {
|
|
465
|
+
throw new ToolInputError("maxDistance must be positive.");
|
|
466
|
+
}
|
|
467
|
+
if (!Number.isFinite(nearbyRadius) || nearbyRadius < 0) {
|
|
468
|
+
throw new ToolInputError("nearbyRadius must be zero or positive.");
|
|
469
|
+
}
|
|
470
|
+
const receipt = await client.executeIdentityBoundOps([{
|
|
471
|
+
op: "Starcast3D",
|
|
472
|
+
path: exactSubject,
|
|
473
|
+
detail,
|
|
474
|
+
max_distance: maxDistance,
|
|
475
|
+
nearby_radius: nearbyRadius,
|
|
476
|
+
direction_space: directionSpace,
|
|
477
|
+
collision_mask: collisionMask,
|
|
478
|
+
collide_with_areas: collideWithAreas,
|
|
479
|
+
max_hits_per_direction: maxHitsPerDirection,
|
|
480
|
+
max_results: maxResults,
|
|
481
|
+
margin,
|
|
482
|
+
}], { scenePath: exactScene });
|
|
483
|
+
return withOldEngineHint(receipt, "Starcast3D", STARCAST_FALLBACK);
|
|
484
|
+
}, starcastResult()));
|
|
485
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Wrap a JSON-serializable value as an MCP text ToolResult. */
|
|
2
|
+
export function textJson(value, isError = false) {
|
|
3
|
+
return {
|
|
4
|
+
content: [
|
|
5
|
+
{
|
|
6
|
+
type: "text",
|
|
7
|
+
text: JSON.stringify(value, null, 2),
|
|
8
|
+
},
|
|
9
|
+
],
|
|
10
|
+
...(isError ? { isError: true } : {}),
|
|
11
|
+
};
|
|
12
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
-
export declare function
|
|
2
|
+
export declare function registerUiTools(server: McpServer): void;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { withEngine, missingEngineOpResult, withOldEngineHint } from "./with-engine.js";
|
|
2
|
+
import { buildUiActionsOp, buildUiActivateOp, buildUiScreenshotOp, buildUiTreeOp, executeUiOp, uiActionsArgsSchema, uiActivateArgsSchema, uiScreenshotArgsSchema, uiScreenshotCaption, uiScreenshotImage, uiTreeArgsSchema, withUiFailureDetails, } from "../../core/capabilities/ui-control.js";
|
|
3
|
+
/**
|
|
4
|
+
* Editor UI control tools (editor UI control). The MCP face only — the op builders, the
|
|
5
|
+
* shared zod contracts, and the failure rendering live in
|
|
6
|
+
* core/capabilities/ui-control.ts and are used verbatim by the CLI dispatcher.
|
|
7
|
+
*
|
|
8
|
+
* Doctrine these descriptions teach (research/agent-platform/04-total-control
|
|
9
|
+
* §1): SEMANTIC FIRST. Scene work goes through the scene and perception tools;
|
|
10
|
+
* the UI ops are for editor-WORKFLOW steps a human would do with the mouse —
|
|
11
|
+
* open Project Settings, switch the main screen, clear a blocking dialog, read
|
|
12
|
+
* a dock. Within the UI ops: a named action beats a tree walk, a tree walk
|
|
13
|
+
* beats pixels, and pixels never drive clicks (there is no coordinate-click
|
|
14
|
+
* op). Quit / project-reload / delete-without-confirm actions are denied by
|
|
15
|
+
* the engine and are never attempted.
|
|
16
|
+
*/
|
|
17
|
+
const DOCTRINE = "SCENE WORK IS NOT UI WORK: to add, move, retune, or read nodes use summer_run_script, the scene tools, summer_world_snapshot and summer_screenshot — never by clicking through the editor. UI ops are for editor-workflow steps a human would do with the mouse: open Project Settings or the Import dock, switch the 2D/3D/Script main screen, clear a dialog that is blocking input, read what a dock currently shows.";
|
|
18
|
+
const LADDER = "Order of preference: a dedicated tool -> summer_ui_actions mode:'invoke' by name -> summer_ui_tree + summer_ui_activate by control path -> summer_ui_screenshot (pixels, last, and only to LOOK — never to pick coordinates).";
|
|
19
|
+
const DENY = "Never try to quit the editor, quit to the project list, reload the project, or delete without confirmation (editor/file_quit, editor/quit_to_project_list, editor/reload_current_project, scene_tree/delete_no_confirm, project_manager/*): the engine refuses them with denied_action, and buttons/menu items with those labels are denied the same way. They end the session you are talking over.";
|
|
20
|
+
async function sendUiOp(client, built) {
|
|
21
|
+
const missing = missingEngineOpResult(client, built.kind, built.fallback);
|
|
22
|
+
if (missing)
|
|
23
|
+
return missing;
|
|
24
|
+
const result = await executeUiOp(client, built);
|
|
25
|
+
return withOldEngineHint(withUiFailureDetails(result), built.kind, built.fallback);
|
|
26
|
+
}
|
|
27
|
+
export function registerUiTools(server) {
|
|
28
|
+
server.tool("summer_ui_actions", `List the editor's named actions, or invoke ONE by name exactly as its menu item / shortcut would — the primary way to drive the editor UI. (preview — needs an engine build with UiListActions/UiInvoke)
|
|
29
|
+
|
|
30
|
+
${DOCTRINE}
|
|
31
|
+
|
|
32
|
+
mode:'list' -> {actions:[{name, label, shortcut_text, category, source:'shortcut'|'command', denied?}], total, truncated, filter}. name is the stable shortcut path ('editor/save_scene', 'editor/project_settings', 'spatial_editor/focus_selection', 'summer/design_mode'); filter is a case-insensitive substring over name and label. denied:true marks names mode:'invoke' will refuse — read it and do not try them.
|
|
33
|
+
mode:'invoke' action_name:'<name>' -> {action, label, invoked:true, handled, via:'shortcut_event'|'command_palette', opened_dialog?, mutates:true}. The event runs through the same MenuBar/PopupMenu/EditorNode handlers the key would. opened_dialog is a window that appeared synchronously; a dialog shown deferred appears on the next summer_ui_tree root:'dialogs'.
|
|
34
|
+
|
|
35
|
+
${LADDER} Read back, never assume: after an invoke, confirm the effect with summer_ui_tree root:'dialogs' (a dialog opened), summer_ui_tree root:'dock:<name>' (a dock changed), or the scene/perception tools (the scene changed).
|
|
36
|
+
|
|
37
|
+
Failures carry failure_reason: unknown_action (+close_matches — pick the exact name) | denied_action (+reason — stop; do not route around it) | modal_open (+blocking_dialog — an exclusive dialog is eating input: summer_ui_tree root:'dialogs', then summer_ui_activate action:'dismiss_dialog', then retry) | not_handled (invoked but no live receiver — switch context first, e.g. summer_ui_activate path:'main_screen' action:'select_tab' value:'3D') | editor_unavailable. ${DENY} On an engine build without these ops the result is a structured engine_lacks_op failure (nothing is sent) naming the dedicated tools to use instead.`, uiActionsArgsSchema.shape, async (args) => withEngine(async (client) => sendUiOp(client, buildUiActionsOp(args))));
|
|
38
|
+
server.tool("summer_ui_tree", `Structured tree of the live editor UI — every visible Control with its class, path, rect, text/tooltip and state (checked, enabled, focused, tabs + current_tab, value/min/max, selected item) — or, with root:'dialogs', every visible dialog/popup and whether one is BLOCKING input. The structured alternative to a screenshot: the tree states outright what exists and what is clickable, at a fraction of the tokens, and its paths are what summer_ui_activate takes. (preview — needs an engine build with UiTree/UiDialogs)
|
|
39
|
+
|
|
40
|
+
${DOCTRINE} Use this tree to READ editor state (which main screen is active, what a dock shows, what a dialog says and which buttons it has) and to find a control's path when no named action covers the step; use summer_get_scene_tree / summer_world_snapshot for the SCENE — the editor's Scene dock is a view of that data, not the data.
|
|
41
|
+
|
|
42
|
+
root: 'main' (default; the editor chrome) | 'window' (incl. every sub-window) | 'dock:<title|id>' (file_system | scene_tree | inspector or any dock title) | 'dialog:<title>' | 'path:<node path>' (zoom into an earlier result) | 'dialogs' -> {count, blocking, blocking_dialog?, dialogs:[{title, path, class, kind, exclusive, popup, embedded, focused, text?, items?, buttons:[{text, path, kind:'ok'|'cancel'|'custom', enabled}]}]}.
|
|
43
|
+
Tree results: {root, root_path, total_emitted, truncated, tree:{name, class, path, visible, rect, text?, tooltip?, enabled?, checked?, focused?, tabs?, current_tab?, value?, child_count, children_truncated?, children}}. Strings clip at 200 chars; icon-only toolbar buttons are named by tooltip; child_count is always the real count, so a children_truncated node can be re-read with root:'path:<its path>' and a larger depth/limit.
|
|
44
|
+
|
|
45
|
+
Paths (@Panel@123) are stable within a session, not across builds — re-read instead of persisting them. The blocking-dialog pattern: root:'dialogs' -> blocking:true -> summer_ui_activate action:'dismiss_dialog' path:<blocking_dialog.path> -> root:'dialogs' again to confirm blocking:false. Failures: unknown_root (+available_docks, dock_ids) | not_found (+visible_titles) | ambiguous_dialog (+candidates) | editor_unavailable. Engine builds without these ops return a structured engine_lacks_op failure (nothing is sent).`, uiTreeArgsSchema.shape, async (args) => withEngine(async (client) => sendUiOp(client, buildUiTreeOp(args))));
|
|
46
|
+
server.tool("summer_ui_activate", `Activate ONE editor control by its summer_ui_tree path through the control's own input path — a synthetic click for buttons, the public setter + signal for tabs, text fields and ranges — or dismiss a visible dialog (action:'dismiss_dialog'). Mutates editor state; the result's state is READ BACK from the control after the action, not echoed. (preview — needs an engine build with UiActivate/UiDismissDialog)
|
|
47
|
+
|
|
48
|
+
${DOCTRINE} Reach for this only when no named action covers the step (summer_ui_actions mode:'list' first). There is no coordinate click: if a thing is visible it is in the tree and this reaches it by path.
|
|
49
|
+
|
|
50
|
+
actions: press (BaseButton: hover+press+release at the rect centre — pressed_emitted is observed, not assumed; ItemList/PopupMenu item by index; MenuBar -> unsupported_control, use summer_ui_actions) | toggle (toggle-mode button) | focus (any control/window) | select_tab (TabContainer/TabBar by value title or index; path:'main_screen' switches the 2D/3D/Script/Game/AssetLib editor by value or index and reads back current_tab + text) | set_text (LineEdit/TextEdit; submit:true also presses Enter; value '' clears) | set_value (Range number) | dismiss_dialog (path or title from summer_ui_tree root:'dialogs'; button 'cancel' default = the safe close, 'ok' or a button text to confirm — only when the user asked for that).
|
|
51
|
+
|
|
52
|
+
Returns {path, class, action, via, state:{...the node's tree fields...}, mutates:true} plus clicked_at/hover_established/pressed_emitted for press, item_text for menus, submitted for set_text; dismiss_dialog returns {title, class, button, via, visible_after} — visible_after:true means the dialog re-validated and stayed up (read it: summer_ui_tree root:'dialog:<title>'). Verify with the read-back (state.checked, state.current_tab, state.text, visible_after), never by assumption.
|
|
53
|
+
|
|
54
|
+
Failures: not_found | not_visible (hidden — reveal the dock/tab first) | disabled | unsupported_control (+supported_actions) | obscured (+hit_control — something on top, usually a dialog) | modal_open (+blocking_dialog — dismiss it first) | no_activation_path (use the named action instead) | denied_action / denied_path (safety: quit/reload labels, file-dialog paths outside the project) | tab_not_found (+tabs) | index_out_of_range | missing_value | not_selected | button_not_found (+buttons) | ambiguous_dialog (+candidates). ${DENY} Engine builds without these ops return a structured engine_lacks_op failure (nothing is sent).`, uiActivateArgsSchema.shape, async (args) => withEngine(async (client) => sendUiOp(client, buildUiActivateOp(args))));
|
|
55
|
+
server.tool("summer_ui_screenshot", `PNG of the editor window (or one dock / dialog / control's rect) returned as an image you can look at — the PIXELS-LAST fallback of the UI ladder: use it to see layout, an unfamiliar panel, or to sanity-check what the tree described, never to pick click coordinates (there is no coordinate click; summer_ui_activate takes paths). For the 3D/2D viewport, a scene render, or the running game use summer_screenshot instead — that is the visual-verification tool for scene work, and scene work itself goes through summer_run_script and the scene tools, never through the editor UI. (preview — needs an engine build with UiScreenshot)
|
|
56
|
+
|
|
57
|
+
${LADDER} Prefer summer_ui_tree for state: a control's checked/current_tab/text is exact there and costs a fraction of an image.
|
|
58
|
+
|
|
59
|
+
root: 'window' (default; the whole editor window incl. embedded dialogs) | 'main' | 'dock:<title|id>' | 'dialog:<title>' | 'path:<node path>' — a Control or embedded dialog is cropped out of the root viewport texture; a native OS sub-window is not in it (native_subwindow). max_size caps the longest edge (default 1024, 16-4096). Captured from the editor's own root viewport texture, never the OS screen (safety_boundary:'no_os_screen_capture').
|
|
60
|
+
|
|
61
|
+
Headless is honest: under a headless editor (dummy rendering driver) the result is failure_reason no_renderer — nothing was drawn, so there are no pixels; summer_ui_tree is the structured view of the same UI and a display (Linux: --xvfb) is needed for pixels. Other failures: texture_unavailable | zero_size | native_subwindow | unknown_root | not_found | encode_failed. Engine builds without the op return a structured engine_lacks_op failure (nothing is sent).`, uiScreenshotArgsSchema.shape, async (args) => withEngine(async (client) => sendUiOp(client, buildUiScreenshotOp(args)), {
|
|
62
|
+
// withEngine calls toContent only on genuine success (extractOpError
|
|
63
|
+
// cleared): hand the frame back as an image block, or fall back to
|
|
64
|
+
// text when a "success" carries no bytes rather than emit a broken
|
|
65
|
+
// image.
|
|
66
|
+
toContent: (result) => {
|
|
67
|
+
const image = uiScreenshotImage(result);
|
|
68
|
+
if (!image) {
|
|
69
|
+
return [
|
|
70
|
+
{
|
|
71
|
+
type: "text",
|
|
72
|
+
text: "UiScreenshot succeeded but returned no image data. Retry once; if it persists, read the UI structurally with summer_ui_tree.",
|
|
73
|
+
},
|
|
74
|
+
];
|
|
75
|
+
}
|
|
76
|
+
return [
|
|
77
|
+
{ type: "image", data: image.base64, mimeType: image.mime },
|
|
78
|
+
{ type: "text", text: uiScreenshotCaption(image) },
|
|
79
|
+
];
|
|
80
|
+
},
|
|
81
|
+
}));
|
|
82
|
+
}
|
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
* that needs a separate vision model to describe frames for it), an MCP client
|
|
5
|
-
* like Claude Code can SEE images directly. So we hand the raw engine frame back
|
|
6
|
-
* as an MCP image content block — no vision-model prepass, no paraphrase. The
|
|
7
|
-
* model reviews the actual pixels.
|
|
8
|
-
*/
|
|
2
|
+
import { analyzedSnapshot, captureScene, captureViewport, VIEWPORT_RECAPTURE_DELAY_MS, type CaptureResult, type RecaptureInfo } from "../../core/capabilities/capture.js";
|
|
3
|
+
export { analyzedSnapshot, captureScene, captureViewport, VIEWPORT_RECAPTURE_DELAY_MS, type CaptureResult, type RecaptureInfo };
|
|
9
4
|
export declare function registerVisualTools(server: McpServer): void;
|