summer-engine 3.1.0 → 3.2.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 +2 -2
- package/.claude-plugin/plugin.json +27 -5
- package/.codex-plugin/plugin.json +28 -6
- package/.cursor-plugin/plugin.json +27 -5
- package/.factory-plugin/plugin.json +27 -5
- package/.opencode/plugins/summer.js +1 -1
- package/CHANGELOG.md +102 -0
- package/README.md +18 -3
- package/assets/audit/scene_audit.gd +4136 -0
- package/assets/seeing/seeing_probe.gd +1873 -0
- package/dist/cli/commands/skills.js +20 -2
- package/dist/core/api-client.d.ts +9 -1
- package/dist/core/api-client.js +21 -4
- package/dist/core/capabilities/agent-playbook.js +46 -0
- package/dist/core/capabilities/audit/accept.d.ts +55 -0
- package/dist/core/capabilities/audit/accept.js +147 -0
- package/dist/core/capabilities/audit/args.d.ts +95 -0
- package/dist/core/capabilities/audit/args.js +89 -0
- package/dist/core/capabilities/audit/audit.d.ts +56 -0
- package/dist/core/capabilities/audit/audit.js +287 -0
- package/dist/core/capabilities/audit/frame.d.ts +14 -0
- package/dist/core/capabilities/audit/frame.js +35 -0
- package/dist/core/capabilities/audit/gaps.d.ts +96 -0
- package/dist/core/capabilities/audit/gaps.js +257 -0
- package/dist/core/capabilities/audit/judge.d.ts +162 -0
- package/dist/core/capabilities/audit/judge.js +1134 -0
- package/dist/core/capabilities/audit/math.d.ts +110 -0
- package/dist/core/capabilities/audit/math.js +263 -0
- package/dist/core/capabilities/audit/summary.d.ts +74 -0
- package/dist/core/capabilities/audit/summary.js +212 -0
- package/dist/core/capabilities/board.d.ts +31 -0
- package/dist/core/capabilities/board.js +43 -0
- package/dist/core/capabilities/camera-view.d.ts +4 -2
- package/dist/core/capabilities/camera-view.js +6 -3
- package/dist/core/capabilities/connect-signal.d.ts +85 -0
- package/dist/core/capabilities/connect-signal.js +285 -0
- package/dist/core/capabilities/engine-fallbacks.d.ts +5 -0
- package/dist/core/capabilities/engine-fallbacks.js +5 -0
- package/dist/core/capabilities/engine-ops.d.ts +5 -1
- package/dist/core/capabilities/engine-ops.js +0 -3
- package/dist/core/capabilities/engine-receipt.d.ts +12 -0
- package/dist/core/capabilities/engine-receipt.js +26 -0
- package/dist/core/capabilities/file-read.d.ts +64 -0
- package/dist/core/capabilities/file-read.js +325 -0
- package/dist/core/capabilities/game-task-plan.js +4 -2
- package/dist/core/capabilities/grep.d.ts +60 -0
- package/dist/core/capabilities/grep.js +190 -0
- package/dist/core/capabilities/inspect-node.d.ts +56 -0
- package/dist/core/capabilities/inspect-node.js +225 -0
- package/dist/core/capabilities/inspect-resource.d.ts +61 -0
- package/dist/core/capabilities/inspect-resource.js +376 -0
- package/dist/core/capabilities/math3d.d.ts +28 -0
- package/dist/core/capabilities/math3d.js +88 -0
- package/dist/core/capabilities/motion-generation.d.ts +62 -0
- package/dist/core/capabilities/motion-generation.js +138 -0
- package/dist/core/capabilities/placement-batch.d.ts +102 -0
- package/dist/core/capabilities/placement-batch.js +483 -0
- package/dist/core/capabilities/placement-math.d.ts +70 -0
- package/dist/core/capabilities/placement-math.js +209 -0
- package/dist/core/capabilities/placement-script.d.ts +42 -0
- package/dist/core/capabilities/placement-script.js +1096 -0
- package/dist/core/capabilities/placement.d.ts +485 -0
- package/dist/core/capabilities/placement.js +1731 -0
- package/dist/core/capabilities/project-context.d.ts +33 -2
- package/dist/core/capabilities/project-context.js +87 -4
- package/dist/core/capabilities/replace-node.d.ts +91 -0
- package/dist/core/capabilities/replace-node.js +423 -0
- package/dist/core/capabilities/runtime-control.d.ts +18 -2
- package/dist/core/capabilities/runtime-control.js +67 -2
- package/dist/core/capabilities/scene-batch.d.ts +63 -0
- package/dist/core/capabilities/scene-batch.js +394 -0
- package/dist/core/capabilities/scene-readback.d.ts +36 -0
- package/dist/core/capabilities/scene-readback.js +54 -0
- package/dist/core/capabilities/seeing/args.d.ts +348 -0
- package/dist/core/capabilities/seeing/args.js +178 -0
- package/dist/core/capabilities/seeing/candidates.d.ts +127 -0
- package/dist/core/capabilities/seeing/candidates.js +282 -0
- package/dist/core/capabilities/seeing/math.d.ts +134 -0
- package/dist/core/capabilities/seeing/math.js +269 -0
- package/dist/core/capabilities/seeing/probe.d.ts +62 -0
- package/dist/core/capabilities/seeing/probe.js +188 -0
- package/dist/core/capabilities/seeing/scoring.d.ts +235 -0
- package/dist/core/capabilities/seeing/scoring.js +639 -0
- package/dist/core/capabilities/seeing/seeing.d.ts +233 -0
- package/dist/core/capabilities/seeing/seeing.js +1341 -0
- package/dist/core/capabilities/seeing/shot-store.d.ts +52 -0
- package/dist/core/capabilities/seeing/shot-store.js +204 -0
- package/dist/core/capabilities/surface-snap-mesh.d.ts +88 -0
- package/dist/core/capabilities/surface-snap-mesh.js +425 -0
- package/dist/core/capabilities/surface-snap.d.ts +77 -0
- package/dist/core/capabilities/surface-snap.js +461 -0
- package/dist/core/capabilities/tool-dispatch.js +231 -72
- package/dist/core/capabilities/tscn.d.ts +85 -0
- package/dist/core/capabilities/tscn.js +391 -0
- package/dist/core/capabilities/world-snapshot.d.ts +58 -0
- package/dist/core/capabilities/world-snapshot.js +150 -0
- package/dist/core/capability-skew.d.ts +5 -5
- package/dist/core/capability-skew.js +14 -6
- package/dist/core/headless/worker-engine-client.d.ts +1 -1
- package/dist/core/headless/worker-engine-client.js +2 -2
- package/dist/core/library-read.d.ts +37 -5
- package/dist/core/library-read.js +264 -33
- package/dist/core/library-search.d.ts +2 -2
- package/dist/installer/agent-config.js +5 -3
- package/dist/installer/agent-table.d.ts +16 -0
- package/dist/installer/agent-table.js +52 -17
- package/dist/mcp/server.js +9 -3
- package/dist/mcp/tools/asset-tools.js +21 -3
- package/dist/mcp/tools/audit-tools.d.ts +23 -0
- package/dist/mcp/tools/audit-tools.js +60 -0
- package/dist/mcp/tools/debug-tools.js +3 -1
- package/dist/mcp/tools/file-tools.js +17 -4
- package/dist/mcp/tools/generate-tools.js +74 -66
- package/dist/mcp/tools/library-tools.js +2 -0
- package/dist/mcp/tools/perception-tools.js +6 -19
- package/dist/mcp/tools/placement-tools.d.ts +24 -0
- package/dist/mcp/tools/placement-tools.js +91 -0
- package/dist/mcp/tools/project-tools.js +18 -15
- package/dist/mcp/tools/scene-tools.js +71 -83
- package/dist/mcp/tools/seeing-tools.d.ts +24 -0
- package/dist/mcp/tools/seeing-tools.js +64 -0
- package/dist/mcp/tools/spatial-tools.js +17 -9
- package/dist/mcp/tools/visual-tools.js +59 -7
- package/gemini-extension.json +26 -4
- package/integrations/amp/README.md +1 -1
- package/integrations/crush/README.md +1 -1
- package/integrations/grok-build/README.md +1 -1
- package/integrations/hermes/README.md +1 -1
- package/integrations/kimi-code/README.md +1 -1
- package/integrations/mistral-vibe/README.md +1 -1
- package/integrations/opencode/README.md +1 -1
- package/integrations/rovo-dev/README.md +1 -1
- package/integrations/vscode-copilot/README.md +1 -1
- package/integrations/warp/README.md +1 -1
- package/integrations/windsurf/README.md +1 -1
- package/library/references/mcp-tools-reference/mcp-tools-reference.md +59 -15
- package/library/references/mcp-tools-reference/resource.yaml +1 -1
- package/library/references/summer-folder/resource.yaml +1 -1
- package/library/references/summer-folder/summer-folder.md +1 -1
- package/library/skills/3d-lighting/SKILL.md +1 -1
- package/library/skills/README.md +36 -14
- package/library/skills/adaptive-music/SKILL.md +1 -1
- package/library/skills/agent-playtesting/SKILL.md +1 -1
- package/library/skills/ai-characters-in-games/SKILL.md +220 -0
- package/library/skills/ai-characters-in-games/resource.yaml +30 -0
- package/library/skills/ambient-bed/SKILL.md +1 -1
- package/library/skills/animated-loop/SKILL.md +1 -1
- package/library/skills/animation-tree/SKILL.md +1 -1
- package/library/skills/art-direction/SKILL.md +1 -1
- package/library/skills/asset-strategy/SKILL.md +2 -1
- package/library/skills/asset-strategy/resource.yaml +2 -1
- package/library/skills/audio-direction/SKILL.md +1 -1
- package/library/skills/auto-fire-targeting/SKILL.md +1 -1
- package/library/skills/brainstorm-game/SKILL.md +1 -1
- package/library/skills/brainstorming/SKILL.md +1 -1
- package/library/skills/browse-templates/SKILL.md +3 -3
- package/library/skills/browse-templates/resource.yaml +1 -1
- package/library/skills/camera-rigs/SKILL.md +128 -0
- package/library/skills/camera-rigs/resource.yaml +29 -0
- package/library/skills/celeste-momentum-platforming/SKILL.md +1 -1
- package/library/skills/character-animation-wiring/SKILL.md +1 -1
- package/library/skills/character-model/SKILL.md +1 -1
- package/library/skills/character-movement/SKILL.md +326 -0
- package/library/skills/character-movement/references/default-third-person-controller.gd +201 -0
- package/library/skills/character-movement/references/default-third-person-verification-probe.gd +154 -0
- package/library/skills/character-movement/references/movement-3d.md +136 -0
- package/library/skills/character-movement/references/platformer-feel.md +83 -0
- package/library/skills/character-movement/resource.yaml +40 -0
- package/library/skills/character-portrait/SKILL.md +1 -1
- package/library/skills/cinematic-cutscene/SKILL.md +1 -1
- package/library/skills/combat-basics/SKILL.md +159 -0
- package/library/skills/combat-basics/references/projectiles-and-aoe.md +100 -0
- package/library/skills/combat-basics/resource.yaml +34 -0
- package/library/skills/concept-art/SKILL.md +1 -1
- package/library/skills/create-asset-sheet/SKILL.md +1 -1
- package/library/skills/debug/SKILL.md +1 -1
- package/library/skills/debugging-game-feel/SKILL.md +1 -1
- package/library/skills/design-level/SKILL.md +1 -1
- package/library/skills/design-mechanic/SKILL.md +1 -1
- package/library/skills/design-npc/SKILL.md +1 -1
- package/library/skills/diagnosing-perf-regressions/SKILL.md +1 -1
- package/library/skills/dispatching-parallel-agents/SKILL.md +1 -1
- package/library/skills/driving-the-editor-ui/SKILL.md +1 -1
- package/library/skills/environment-kit/SKILL.md +1 -1
- package/library/skills/export-and-ship/SKILL.md +1 -1
- package/library/skills/fabricating-assets/SKILL.md +1 -1
- package/library/skills/facial-and-lipsync/SKILL.md +1 -1
- package/library/skills/fps-controller/SKILL.md +9 -7
- package/library/skills/fps-controller/resource.yaml +4 -1
- package/library/skills/game-feel/SKILL.md +1 -1
- package/library/skills/gameskill/SKILL.md +1 -1
- package/library/skills/gdscript-patterns/SKILL.md +1 -1
- package/library/skills/generate-motion/SKILL.md +9 -9
- package/library/skills/generate-motion/resource.yaml +2 -1
- package/library/skills/godogen-visual-proof-game-generation/SKILL.md +1 -1
- package/library/skills/headless-scripting/SKILL.md +1 -1
- package/library/skills/in-game-purchases/SKILL.md +254 -0
- package/library/skills/in-game-purchases/resource.yaml +29 -0
- package/library/skills/instantiate-asset-pack/SKILL.md +1 -1
- package/library/skills/investigating-bugs/SKILL.md +1 -1
- package/library/skills/lumera-single-image-scene-reconstruction/SKILL.md +1 -1
- package/library/skills/make-game/SKILL.md +25 -3
- package/library/skills/make-game/references/2d-platformer-polish.md +93 -0
- package/library/skills/make-game/references/2d-platformer.md +117 -0
- package/library/skills/make-game/references/2d-rpg-content.md +234 -0
- package/library/skills/make-game/references/2d-rpg.md +241 -0
- package/library/skills/make-game/references/2d-survivors-progression.md +201 -0
- package/library/skills/make-game/references/2d-survivors.md +237 -0
- package/library/skills/make-game/references/3d-fps-systems.md +216 -0
- package/library/skills/make-game/references/3d-fps.md +177 -0
- package/library/skills/make-game/references/3d-horror-systems.md +186 -0
- package/library/skills/make-game/references/3d-horror.md +201 -0
- package/library/skills/make-game/references/3d-third-person-systems.md +220 -0
- package/library/skills/make-game/references/3d-third-person.md +215 -0
- package/library/skills/make-game/resource.yaml +6 -1
- package/library/skills/multiplayer/SKILL.md +150 -0
- package/library/skills/multiplayer/resource.yaml +33 -0
- package/library/skills/multiplayer-movement/SKILL.md +510 -0
- package/library/skills/multiplayer-movement/files.md +501 -0
- package/library/skills/multiplayer-movement/resource.yaml +30 -0
- package/library/skills/multiplayer-project/SKILL.md +521 -0
- package/library/skills/multiplayer-project/files.md +448 -0
- package/library/skills/multiplayer-project/resource.yaml +36 -0
- package/library/skills/multiplayer-publish/SKILL.md +229 -0
- package/library/skills/multiplayer-publish/export-errors.md +89 -0
- package/library/skills/multiplayer-publish/resource.yaml +28 -0
- package/library/skills/multiplayer-state/SKILL.md +438 -0
- package/library/skills/multiplayer-state/files.md +592 -0
- package/library/skills/multiplayer-state/resource.yaml +35 -0
- package/library/skills/multiplayer-testing/SKILL.md +236 -0
- package/library/skills/multiplayer-testing/resource.yaml +39 -0
- package/library/skills/music-track/SKILL.md +1 -1
- package/library/skills/navigate-summer/SKILL.md +1 -1
- package/library/skills/new-project/SKILL.md +1 -1
- package/library/skills/organic-model/SKILL.md +1 -1
- package/library/skills/pixel-art/SKILL.md +1 -1
- package/library/skills/play/SKILL.md +1 -1
- package/library/skills/playtesting-a-feature/SKILL.md +1 -1
- package/library/skills/procedural-animation/SKILL.md +2 -2
- package/library/skills/procedural-animation/resource.yaml +1 -1
- package/library/skills/prop-model/SKILL.md +1 -1
- package/library/skills/psx-retro-rendering/SKILL.md +1 -1
- package/library/skills/realtime-wet-surfaces/SKILL.md +2 -2
- package/library/skills/remote-deploy/SKILL.md +1 -1
- package/library/skills/retarget/SKILL.md +1 -1
- package/library/skills/running-in-the-cloud/SKILL.md +1 -1
- package/library/skills/save-load/SKILL.md +156 -0
- package/library/skills/save-load/resource.yaml +27 -0
- package/library/skills/scene-composition/SKILL.md +1 -1
- package/library/skills/scene-hierarchy-design/SKILL.md +1 -1
- package/library/skills/scene-scripting/SKILL.md +1 -1
- package/library/skills/scene-to-level/SKILL.md +1 -1
- package/library/skills/skill-create/SKILL.md +1 -1
- package/library/skills/skill-improve/SKILL.md +1 -1
- package/library/skills/skill-test/SKILL.md +1 -1
- package/library/skills/skintokens-auto-rigging/SKILL.md +1 -1
- package/library/skills/skybox-panorama/SKILL.md +1 -1
- package/library/skills/sound-effect/SKILL.md +1 -1
- package/library/skills/spatial-placement/SKILL.md +134 -3
- package/library/skills/spatial-placement/references/kit-placement-tools.md +364 -0
- package/library/skills/spatial-placement/resource.yaml +16 -2
- package/library/skills/sprite-sheet/SKILL.md +1 -1
- package/library/skills/summer-analytics/SKILL.md +147 -0
- package/library/skills/summer-analytics/resource.yaml +28 -0
- package/library/skills/summer-friends/SKILL.md +226 -0
- package/library/skills/summer-friends/resource.yaml +28 -0
- package/library/skills/summer-leaderboards/SKILL.md +231 -0
- package/library/skills/summer-leaderboards/resource.yaml +30 -0
- package/library/skills/summer-match-results/SKILL.md +286 -0
- package/library/skills/summer-match-results/resource.yaml +32 -0
- package/library/skills/summer-matchmaking/SKILL.md +301 -0
- package/library/skills/summer-matchmaking/resource.yaml +32 -0
- package/library/skills/summer-parties/SKILL.md +253 -0
- package/library/skills/summer-parties/resource.yaml +30 -0
- package/library/skills/summer-player-data/SKILL.md +322 -0
- package/library/skills/summer-player-data/resource.yaml +30 -0
- package/library/skills/summer-store/SKILL.md +271 -0
- package/library/skills/summer-store/resource.yaml +29 -0
- package/library/skills/summer-world-chat/SKILL.md +195 -0
- package/library/skills/summer-world-chat/resource.yaml +30 -0
- package/library/skills/summer-world-saves/SKILL.md +284 -0
- package/library/skills/summer-world-saves/resource.yaml +29 -0
- package/library/skills/text-to-motion/SKILL.md +99 -0
- package/library/skills/text-to-motion/prompts-and-controls.md +34 -0
- package/library/skills/text-to-motion/resource.yaml +41 -0
- package/library/skills/text-to-motion/rigging-for-text-motion.md +54 -0
- package/library/skills/tileable-texture/SKILL.md +1 -1
- package/library/skills/trailer-shot/SKILL.md +1 -1
- package/library/skills/tune-performance/SKILL.md +1 -1
- package/library/skills/ui-basics/SKILL.md +10 -1
- package/library/skills/ui-graphics/SKILL.md +1 -1
- package/library/skills/use-widget-asset/SKILL.md +1 -1
- package/library/skills/using-summer/SKILL.md +2 -2
- package/library/skills/using-summer/resource.yaml +2 -2
- package/library/skills/vehicle-model/SKILL.md +1 -1
- package/library/skills/verification-before-completion/SKILL.md +1 -1
- package/library/skills/verifying-scenes/SKILL.md +76 -2
- package/library/skills/verifying-scenes/resource.yaml +13 -2
- package/library/skills/vfx-dissolve/SKILL.md +1 -1
- package/library/skills/vfx-fire/SKILL.md +1 -1
- package/library/skills/vfx-hit-spark/SKILL.md +1 -1
- package/library/skills/vfx-lightning/SKILL.md +1 -1
- package/library/skills/vfx-magic-glow/SKILL.md +1 -1
- package/library/skills/vfx-muzzle-flash/SKILL.md +1 -1
- package/library/skills/vfx-smoke/SKILL.md +1 -1
- package/library/skills/vfx-water-ripple/SKILL.md +1 -1
- package/library/skills/voice-line/SKILL.md +1 -1
- package/library/skills/web-and-touch-input/SKILL.md +38 -0
- package/library/skills/web-and-touch-input/resource.yaml +28 -0
- package/library/skills/web-compatibility-look/SKILL.md +62 -0
- package/library/skills/web-compatibility-look/resource.yaml +30 -0
- package/library/skills/world-building-3d/SKILL.md +8 -1
- package/library/skills/world-building-3d/references/spatial-tools.md +1 -1
- package/library/skills/world-building-3d/resource.yaml +2 -1
- package/library/skills/writing-plans/SKILL.md +1 -1
- package/library/skills/writing-skills/SKILL.md +1 -1
- package/library/templates/3d-lan-multiplayer-starter/resource.yaml +2 -2
- package/library/tools/attach-to-surface/resource.yaml +142 -0
- package/library/tools/batch/resource.yaml +9 -3
- package/library/tools/connect-ports/resource.yaml +120 -0
- package/library/tools/connect-signal/resource.yaml +3 -2
- package/library/tools/debug-views/resource.yaml +94 -0
- package/library/tools/frame-nodes/resource.yaml +104 -0
- package/library/tools/frame-shot/resource.yaml +134 -0
- package/library/tools/generate-motion/resource.yaml +44 -9
- package/library/tools/get-board/resource.yaml +50 -0
- package/library/tools/get-project-context/resource.yaml +13 -2
- package/library/tools/grep/resource.yaml +77 -0
- package/library/tools/inspect-asset/resource.yaml +71 -0
- package/library/tools/inspect-node/resource.yaml +9 -2
- package/library/tools/inspect-resource/resource.yaml +16 -5
- package/library/tools/instantiate-scene/resource.yaml +27 -2
- package/library/tools/measure/resource.yaml +96 -0
- package/library/tools/place-adjacent/resource.yaml +113 -0
- package/library/tools/play/resource.yaml +15 -2
- package/library/tools/raycast/resource.yaml +101 -0
- package/library/tools/read-file/resource.yaml +36 -2
- package/library/tools/read-library/resource.yaml +2 -2
- package/library/tools/repeat-along/resource.yaml +129 -0
- package/library/tools/replace-node/resource.yaml +11 -5
- package/library/tools/scene-audit/resource.yaml +144 -0
- package/library/tools/screenshot/resource.yaml +13 -2
- package/library/tools/search-assets/resource.yaml +18 -0
- package/library/tools/shot-sheet/resource.yaml +110 -0
- package/library/tools/snap-to-surface/resource.yaml +4 -1
- package/library/tools/world-snapshot/resource.yaml +24 -3
- package/library/tools/zoom/resource.yaml +105 -0
- package/package.json +1 -1
- package/registry/generated/aliases.json +17 -3
- package/registry/generated/counts.json +3 -3
- package/registry/generated/gemini-extension.json +26 -4
- package/registry/generated/index.json +2154 -469
- package/registry/generated/marketplace.claude.json +2 -2
- package/registry/generated/plugin.claude.json +27 -5
- package/registry/generated/plugin.codex.json +28 -6
- package/registry/generated/plugin.cursor.json +27 -5
- package/registry/generated/plugin.factory.json +27 -5
- package/registry/generated/skills-index.md +36 -14
- package/registry/generated/skills-registry.json +421 -124
- package/registry/generated/templates-registry.json +2 -2
- package/library/skills/host-authoritative-state/SKILL.md +0 -332
- package/library/skills/host-authoritative-state/resource.yaml +0 -28
- package/library/skills/peer-to-peer-multiplayer/SKILL.md +0 -373
- package/library/skills/peer-to-peer-multiplayer/resource.yaml +0 -28
- package/library/skills/setup-multiplayer/SKILL.md +0 -336
- package/library/skills/setup-multiplayer/resource.yaml +0 -28
|
@@ -18,16 +18,18 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import { tmpdir } from "node:os";
|
|
20
20
|
import { join } from "node:path";
|
|
21
|
-
import { mkdir, writeFile } from "node:fs/promises";
|
|
21
|
+
import { mkdir, mkdtemp, writeFile } from "node:fs/promises";
|
|
22
22
|
import { EngineApiClient } from "../api-client.js";
|
|
23
|
-
import { missingEngineEventsResult, missingEngineOpResult,
|
|
23
|
+
import { missingEngineEventsResult, missingEngineOpResult, } from "../capability-skew.js";
|
|
24
24
|
import { buildAgentPlaybook } from "./agent-playbook.js";
|
|
25
25
|
import { recentEvents, recentEventsArgsSchema, waitForEvent, waitForEventArgsSchema, } from "./events.js";
|
|
26
26
|
import { importResolvedAsset } from "./asset-import.js";
|
|
27
|
-
import {
|
|
27
|
+
import { executeSceneMutation, occurrenceCount, readTextPayload, safeProjectPath, validSha256, } from "./engine-ops.js";
|
|
28
28
|
import { extractOpError, withOldEngineHint } from "./engine-receipt.js";
|
|
29
29
|
import { lookupApiDocs } from "./api-docs.js";
|
|
30
|
+
import { BOARD_ENDPOINT, boardArgsSchema, boardQuery } from "./board.js";
|
|
30
31
|
import { imageGenerationArgsSchema } from "./image-generation.js";
|
|
32
|
+
import { buildMotionRequestBody, motionGenerationArgsSchema } from "./motion-generation.js";
|
|
31
33
|
import { ImportHdriError, importHdriArgsSchema, importPolyHavenHdri } from "./hdri-import.js";
|
|
32
34
|
import { FABRICATE_FALLBACK, buildFabricateMeshOp, fabricateArgsSchema } from "./fabricate-mesh.js";
|
|
33
35
|
import { buildUiActionsOp, buildUiActivateOp, buildUiScreenshotOp, buildUiTreeOp, executeUiOp, uiActionsArgsSchema, uiActivateArgsSchema, uiScreenshotArgsSchema, uiScreenshotCaption, uiScreenshotImage, uiTreeArgsSchema, withUiFailureDetails, } from "./ui-control.js";
|
|
@@ -35,6 +37,10 @@ import { PLAY_INSTANCE_FALLBACK, RUNTIME_FALLBACKS, buildGameControlOp, buildGam
|
|
|
35
37
|
import { RUN_EDITOR_SCRIPT_FALLBACK, RUN_SCRIPT_FALLBACK, buildRunEditorScriptOp, buildRunSceneScriptOp, } from "./scene-script.js";
|
|
36
38
|
import { CAMERA_BOOKMARK_ACTIONS, CAMERA_BOOKMARK_FALLBACK, SCREENSHOT_FRAMINGS, buildCameraBookmarkOp, buildScenePreviewInput, } from "./camera-view.js";
|
|
37
39
|
import { PLAY_DETERMINISM_NOT_SUPPORTED, pickPlayDeterminism, readPlayDeterminism } from "./play-determinism.js";
|
|
40
|
+
import { debugViews, frameNodes, frameShot, rememberBookmarkRender, shotSheet, slotPolicy, zoom, } from "./seeing/seeing.js";
|
|
41
|
+
import { debugViewsArgsSchema, frameNodesArgsSchema, frameShotArgsSchema, shotSheetArgsSchema, zoomArgsSchema, } from "./seeing/args.js";
|
|
42
|
+
import { sceneAudit } from "./audit/audit.js";
|
|
43
|
+
import { sceneAuditArgsSchema } from "./audit/args.js";
|
|
38
44
|
import { ToolInputError } from "../tool-errors.js";
|
|
39
45
|
import { getAuthToken } from "../auth.js";
|
|
40
46
|
import open from "open";
|
|
@@ -45,13 +51,24 @@ import { CONFIG_KEYS, getConfigValue, isConfigKey, readSummerConfig, resolveGate
|
|
|
45
51
|
import { createDebugReportArtifact } from "./debug-report.js";
|
|
46
52
|
import { buildGameTaskPlan, gameTaskPlanInputSchema } from "./game-task-plan.js";
|
|
47
53
|
import { buildProjectContext, projectContextInputSchema, projectSettingValue, } from "./project-context.js";
|
|
48
|
-
import {
|
|
54
|
+
import { rawSceneReplaceRefusal, replaceNodeInputSchema, replaceNodePersisted } from "./replace-node.js";
|
|
55
|
+
import { connectSignalInputSchema, connectSignalPersisted } from "./connect-signal.js";
|
|
56
|
+
import { readFileInputSchema, readProjectFileWindow } from "./file-read.js";
|
|
57
|
+
import { buildWorldSnapshotOp, shapeWorldSnapshot, worldSnapshotInputSchema } from "./world-snapshot.js";
|
|
58
|
+
import { inspectNodeFields, inspectNodeInputSchema } from "./inspect-node.js";
|
|
59
|
+
import { inspectResource, inspectResourceInputSchema } from "./inspect-resource.js";
|
|
60
|
+
import { grepInputSchema, grepProject } from "./grep.js";
|
|
61
|
+
import { snapToSurface } from "./surface-snap.js";
|
|
49
62
|
import { withConsoleScope } from "./console-read.js";
|
|
50
63
|
import { captureGame, captureScene, captureViewport } from "./capture.js";
|
|
51
64
|
// engine_lacks_op fallbacks: ONE copy for every face (E2E 2026-09-03 F-16);
|
|
52
65
|
// the scripting ones come with their op builders from ./scene-script.js.
|
|
53
|
-
import { ALIGN_DISTRIBUTE_FALLBACK, NAVIGATION_PROBE_FALLBACK, RUNTIME_NODE_FALLBACK, RUNTIME_TREE_FALLBACK, SNAP_TO_SURFACE_FALLBACK, SNAPSHOT_DIFF_FALLBACK, STARCAST_FALLBACK, TEST_PLACEMENT_FALLBACK, WORLD_SNAPSHOT_FALLBACK, } from "./engine-fallbacks.js";
|
|
66
|
+
import { ALIGN_DISTRIBUTE_FALLBACK, GREP_FALLBACK, NAVIGATION_PROBE_FALLBACK, RUNTIME_NODE_FALLBACK, RUNTIME_TREE_FALLBACK, SNAP_TO_SURFACE_FALLBACK, SNAPSHOT_DIFF_FALLBACK, STARCAST_FALLBACK, TEST_PLACEMENT_FALLBACK, WORLD_SNAPSHOT_FALLBACK, } from "./engine-fallbacks.js";
|
|
54
67
|
import { sendLibraryFeedback, } from "../feedback/client.js";
|
|
68
|
+
// One copy of the batch op classification and the instantiate/batch engine
|
|
69
|
+
// path, shared with the MCP face.
|
|
70
|
+
import { PLACEMENT_FIELDS, SCENE_MUTATION_OPS, SCENE_QUERY_OPS, instantiateScene, runBatch, } from "./placement-batch.js";
|
|
71
|
+
import { attachToSurface, attachToSurfaceArgsSchema, connectPorts, connectPortsArgsSchema, inspectAsset, inspectAssetArgsSchema, measure, measureArgsSchema, placeAdjacent, placeAdjacentArgsSchema, raycast, raycastArgsSchema, repeatAlong, repeatAlongArgsSchema, } from "./placement.js";
|
|
55
72
|
import { readLibraryEntry, readLibraryInputSchema } from "../library-read.js";
|
|
56
73
|
import { runSearchLibrary, searchLibraryInputSchema } from "../library-search.js";
|
|
57
74
|
import { TOOLKIT_VERSION as CLI_VERSION } from "../version.js";
|
|
@@ -398,6 +415,41 @@ async function snapshotResult(snap, target) {
|
|
|
398
415
|
const { base64: _dropped, ...rest } = snap;
|
|
399
416
|
return { ...rest, localPath };
|
|
400
417
|
}
|
|
418
|
+
/** The shell face of the seeing tools: the same implementation as the MCP
|
|
419
|
+
* face; the image (inline over MCP) is written to the OS temp directory here
|
|
420
|
+
* like `summer tool screenshot`, and the receipt + caption print as JSON. */
|
|
421
|
+
async function seeingResult(result, name) {
|
|
422
|
+
if (!result.ok) {
|
|
423
|
+
throw new ToolResultError({ ok: false, failure_reason: result.failure_reason, error: result.error, ...(result.hint ? { hint: result.hint } : {}), ...(result.detail ? { detail: result.detail } : {}) }, result.error);
|
|
424
|
+
}
|
|
425
|
+
let localPath;
|
|
426
|
+
if (result.image) {
|
|
427
|
+
// A private mkdtemp directly in the OS temp dir, never a shared fixed
|
|
428
|
+
// parent another local user could pre-create or symlink.
|
|
429
|
+
const dir = await mkdtemp(join(tmpdir(), `summer-seeing-cli-${name}-`));
|
|
430
|
+
localPath = join(dir, `${name}.jpg`);
|
|
431
|
+
await writeFile(localPath, Buffer.from(result.image.base64, "base64"), { mode: 0o600 });
|
|
432
|
+
}
|
|
433
|
+
return {
|
|
434
|
+
ok: true,
|
|
435
|
+
...result.receipt,
|
|
436
|
+
caption: result.caption,
|
|
437
|
+
...(result.image ? { image: { localPath, width: result.image.width, height: result.image.height, mime: result.image.mime } } : {}),
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
/** The shell face of summer_scene_audit: the same page as the MCP face; a
|
|
441
|
+
* sheet image (inline over MCP) goes to a private temp file here. */
|
|
442
|
+
async function auditResult(result) {
|
|
443
|
+
if (!result.ok) {
|
|
444
|
+
throw new ToolResultError({ ok: false, failure_reason: result.failure_reason, error: result.error, ...(result.hint ? { hint: result.hint } : {}), ...(result.detail ? { detail: result.detail } : {}) }, result.error);
|
|
445
|
+
}
|
|
446
|
+
if (!result.image)
|
|
447
|
+
return result.summary;
|
|
448
|
+
const dir = await mkdtemp(join(tmpdir(), "summer-audit-cli-"));
|
|
449
|
+
const localPath = join(dir, "scene-audit-sheet.jpg");
|
|
450
|
+
await writeFile(localPath, Buffer.from(result.image.base64, "base64"), { mode: 0o600 });
|
|
451
|
+
return { ...result.summary, image: { localPath, width: result.image.width, height: result.image.height, mime: result.image.mime } };
|
|
452
|
+
}
|
|
401
453
|
// ---------------------------------------------------------------------------
|
|
402
454
|
// The registry
|
|
403
455
|
// ---------------------------------------------------------------------------
|
|
@@ -410,13 +462,6 @@ function entry(name, summary, engineRequired, handler) {
|
|
|
410
462
|
handler,
|
|
411
463
|
};
|
|
412
464
|
}
|
|
413
|
-
const SCENE_MUTATION_OPS = new Set([
|
|
414
|
-
"AddNode", "RemoveNode", "MoveNode", "ReparentNode", "ReplaceNode",
|
|
415
|
-
"SetProp", "SetResourceProperty", "ConnectSignal", "DisconnectSignal",
|
|
416
|
-
"InstantiateScene", "SaveScene", "SnapToSurface", "AlignDistribute3D", "Undo",
|
|
417
|
-
]);
|
|
418
|
-
/** Read-only spatial queries: identity-bound to an exact scene, never saved. */
|
|
419
|
-
const SCENE_QUERY_OPS = new Set(["TestPlacement3D", "NavigationProbe3D", "Starcast3D"]);
|
|
420
465
|
// ---------------------------------------------------------------------------
|
|
421
466
|
// Spatial tool argument helpers. Mirror of the bounds in
|
|
422
467
|
// src/mcp/tools/spatial-tools.ts (exact paths, UTF-8 byte limits, subject
|
|
@@ -662,7 +707,7 @@ export const TOOL_DISPATCH = [
|
|
|
662
707
|
return engineResult;
|
|
663
708
|
return shapeEngineLogResponse(engineResult, { maxEntries: maxWarnings }).result;
|
|
664
709
|
}),
|
|
665
|
-
entry("summer_play", "Start the game quietly (no Game-tab switch or focus grab; focus:true for the toolbar-style launch) — main scene or a specific scene; seed/fixed_fps/time_scale pins, instance/mode for playtests", true, async (args, ctx) => {
|
|
710
|
+
entry("summer_play", "Start the game quietly (no Game-tab switch or focus grab; focus:true for the toolbar-style launch) — main scene or a specific scene; seed/fixed_fps/time_scale pins, instance/mode for playtests, players for a Local Play multiplayer session", true, async (args, ctx) => {
|
|
666
711
|
const seed = optNumberOrUndefined(args, "seed");
|
|
667
712
|
const fixedFps = optNumberOrUndefined(args, "fixed_fps");
|
|
668
713
|
const timeScale = optNumberOrUndefined(args, "time_scale");
|
|
@@ -684,6 +729,9 @@ export const TOOL_DISPATCH = [
|
|
|
684
729
|
time_scale: timeScale,
|
|
685
730
|
speed,
|
|
686
731
|
focus: typeof args.focus === "boolean" ? args.focus : undefined,
|
|
732
|
+
players: optNumberOrUndefined(args, "players"),
|
|
733
|
+
spectators: optNumberOrUndefined(args, "spectators"),
|
|
734
|
+
queue: optStr(args, "queue"),
|
|
687
735
|
};
|
|
688
736
|
if (args.focus !== undefined && typeof args.focus !== "boolean")
|
|
689
737
|
throw new ToolDispatchError("focus must be a boolean");
|
|
@@ -736,7 +784,18 @@ export const TOOL_DISPATCH = [
|
|
|
736
784
|
};
|
|
737
785
|
}),
|
|
738
786
|
// --- file ---
|
|
739
|
-
entry("summer_read_file", "Read a project text file and its sha256 receipt", true, async (args, ctx) =>
|
|
787
|
+
entry("summer_read_file", "Read a project text file (or a window / JSON selection of it) and its sha256 receipt", true, async (args, ctx) => {
|
|
788
|
+
// ONE implementation for both faces (core/capabilities/file-read.ts).
|
|
789
|
+
const parsed = parseToolArgs(readFileInputSchema, args, "read-file");
|
|
790
|
+
const client = await ctx.engine();
|
|
791
|
+
return requireEngineSuccess(await buildOrRefuseAsync(() => readProjectFileWindow(client, parsed)));
|
|
792
|
+
}),
|
|
793
|
+
entry("summer_grep", "Search project files with a regex (ripgrep) and return matches with context lines", true, async (args, ctx) => {
|
|
794
|
+
// ONE implementation for both faces (core/capabilities/grep.ts).
|
|
795
|
+
const parsed = parseToolArgs(grepInputSchema, args, "grep");
|
|
796
|
+
const client = await ctx.engine();
|
|
797
|
+
return requireSupportedOp(await buildOrRefuseAsync(() => grepProject(client, parsed)), "Grep", GREP_FALLBACK);
|
|
798
|
+
}),
|
|
740
799
|
entry("summer_write_file", "Create or safely overwrite one complete project text file", true, async (args, ctx) => {
|
|
741
800
|
const safePath = safeProjectPath(str(args, "path"));
|
|
742
801
|
const content = args.content;
|
|
@@ -790,6 +849,11 @@ export const TOOL_DISPATCH = [
|
|
|
790
849
|
params.set("id", workflowId);
|
|
791
850
|
return gatewayGet("/api/mcp/workflows", params);
|
|
792
851
|
}),
|
|
852
|
+
entry("summer_get_board", "Read the approved planning board for a game", false, (args) => {
|
|
853
|
+
// The CLI prints JSON: pictures (base64) only when asked for.
|
|
854
|
+
const parsed = parseToolArgs(boardArgsSchema, args, "get-board");
|
|
855
|
+
return gatewayGet(BOARD_ENDPOINT, boardQuery({ ...parsed, pictures: parsed.pictures ?? false }), 45_000);
|
|
856
|
+
}),
|
|
793
857
|
entry("summer_generate_image", "Generate or edit an image via Summer Studio", false, (args) => gatewayPost("/api/mcp/generate/image", parseToolArgs(imageGenerationArgsSchema, args, "generate-image"))),
|
|
794
858
|
entry("summer_slice_asset_sheet", "Detect and crop every asset from a generated sheet image", false, (args) => gatewayPost("/api/mcp/generate/slice-asset-sheet", { assetId: str(args, "assetId") }, 300_000)),
|
|
795
859
|
entry("summer_generate_audio", "Generate speech, sound effects, music, or dialogue", false, (args) => {
|
|
@@ -843,17 +907,16 @@ export const TOOL_DISPATCH = [
|
|
|
843
907
|
options: args.options,
|
|
844
908
|
})),
|
|
845
909
|
entry("summer_check_job", "Check the status of an async generation job", false, (args) => gatewayGet(`/api/mcp/jobs/${encodeURIComponent(str(args, "jobId"))}`, undefined, 15_000)),
|
|
846
|
-
entry("summer_generate_motion", "Generate
|
|
847
|
-
const
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
});
|
|
910
|
+
entry("summer_generate_motion", "Generate animation clips: curated humanoid mocap, or text-to-motion on any rig", false, async (args) => {
|
|
911
|
+
const parsed = parseToolArgs(motionGenerationArgsSchema, args, "generate-motion");
|
|
912
|
+
const built = buildMotionRequestBody(parsed);
|
|
913
|
+
if ("error" in built)
|
|
914
|
+
throw new ToolDispatchError(built.error);
|
|
915
|
+
const result = await gatewayPost("/api/mcp/generate/motion", built.body);
|
|
853
916
|
const jobId = typeof result.jobId === "string" ? result.jobId : undefined;
|
|
854
|
-
if (
|
|
917
|
+
if (!parsed.wait || !jobId)
|
|
855
918
|
return result;
|
|
856
|
-
const final = await pollGenerationJob(jobId,
|
|
919
|
+
const final = await pollGenerationJob(jobId, 600_000);
|
|
857
920
|
return { ...final, jobId };
|
|
858
921
|
}),
|
|
859
922
|
// --- project ---
|
|
@@ -1020,44 +1083,60 @@ export const TOOL_DISPATCH = [
|
|
|
1020
1083
|
return executeSceneMutation(await ctx.engine(), str(args, "scenePath"), [op]);
|
|
1021
1084
|
}),
|
|
1022
1085
|
entry("summer_open_scene", "Open a scene file in the editor", true, async (args, ctx) => requireEngineSuccess(await (await ctx.engine()).executeOps([{ op: "OpenScene", path: str(args, "path") }]))),
|
|
1023
|
-
entry("summer_instantiate_scene", "Add an existing scene or 3D model as a child node", true, async (args, ctx) => {
|
|
1024
|
-
const
|
|
1025
|
-
|
|
1086
|
+
entry("summer_instantiate_scene", "Add an existing scene or 3D model as a child node, optionally placed (position/rotation_degrees/scale/transform)", true, async (args, ctx) => {
|
|
1087
|
+
const parsed = {
|
|
1088
|
+
scenePath: str(args, "scenePath"),
|
|
1026
1089
|
parent: str(args, "parent"),
|
|
1027
1090
|
scene: str(args, "scene"),
|
|
1028
1091
|
};
|
|
1029
1092
|
if (optStr(args, "name"))
|
|
1030
|
-
|
|
1031
|
-
|
|
1093
|
+
parsed.name = String(args.name);
|
|
1094
|
+
if (args.target_size !== undefined) {
|
|
1095
|
+
if (typeof args.target_size !== "number" || !(args.target_size > 0)) {
|
|
1096
|
+
throw new ToolDispatchError("target_size must be a positive number");
|
|
1097
|
+
}
|
|
1098
|
+
parsed.target_size = args.target_size;
|
|
1099
|
+
}
|
|
1100
|
+
// Shape-checked in placement-batch (arrays or Godot strings), same as MCP.
|
|
1101
|
+
const placement = parsed;
|
|
1102
|
+
for (const field of PLACEMENT_FIELDS) {
|
|
1103
|
+
if (args[field] !== undefined)
|
|
1104
|
+
placement[field] = args[field];
|
|
1105
|
+
}
|
|
1106
|
+
return instantiateScene(await ctx.engine(), parsed);
|
|
1107
|
+
}),
|
|
1108
|
+
entry("summer_connect_signal", "Connect a signal between two nodes and verify it in the saved scene", true, async (args, ctx) => {
|
|
1109
|
+
// ONE implementation for both faces (core/capabilities/connect-signal.ts):
|
|
1110
|
+
// CONNECT_PERSIST through a RunSceneScript probe + read-back of the .tscn.
|
|
1111
|
+
const parsed = parseToolArgs(connectSignalInputSchema, args, "connect-signal");
|
|
1112
|
+
const client = await ctx.engine();
|
|
1113
|
+
return buildOrRefuseAsync(() => connectSignalPersisted(client, parsed));
|
|
1032
1114
|
}),
|
|
1033
|
-
entry("summer_connect_signal", "Connect a signal between two nodes", true, async (args, ctx) => executeSceneMutation(await ctx.engine(), str(args, "scenePath"), [
|
|
1034
|
-
{
|
|
1035
|
-
op: "ConnectSignal",
|
|
1036
|
-
emitter: str(args, "emitter"),
|
|
1037
|
-
signal: str(args, "signal"),
|
|
1038
|
-
receiver: str(args, "receiver"),
|
|
1039
|
-
method: str(args, "method"),
|
|
1040
|
-
},
|
|
1041
|
-
])),
|
|
1042
1115
|
entry("summer_select_node", "Select a node in the editor scene tree", true, async (args, ctx) => {
|
|
1043
1116
|
const op = { op: "SelectNode", nodePath: str(args, "nodePath") };
|
|
1044
1117
|
if (optStr(args, "scenePath"))
|
|
1045
1118
|
op.scenePath = args.scenePath;
|
|
1046
1119
|
return requireEngineSuccess(await (await ctx.engine()).executeOps([op]));
|
|
1047
1120
|
}),
|
|
1048
|
-
entry("summer_replace_node", "Replace a node with a different
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1121
|
+
entry("summer_replace_node", "Replace a node with a different scene or type and verify the saved scene", true, async (args, ctx) => {
|
|
1122
|
+
// ONE implementation for both faces (core/capabilities/replace-node.ts):
|
|
1123
|
+
// persisted ops + read-back of the saved .tscn.
|
|
1124
|
+
const parsed = parseToolArgs(replaceNodeInputSchema, args, "replace-node");
|
|
1125
|
+
const client = await ctx.engine();
|
|
1126
|
+
return buildOrRefuseAsync(() => replaceNodePersisted(client, parsed));
|
|
1127
|
+
}),
|
|
1128
|
+
entry("summer_inspect_node", "Get a node's editable properties (or only the named fields)", true, async (args, ctx) => {
|
|
1129
|
+
// E2E 2026-09-03 F-14: the engine returns Variant.Type as a bare int; both
|
|
1130
|
+
// faces add type_name. The fields filter lives with it in
|
|
1131
|
+
// core/capabilities/inspect-node.ts.
|
|
1132
|
+
const parsed = parseToolArgs(inspectNodeInputSchema, args, "inspect-node");
|
|
1133
|
+
return requireEngineSuccess(await inspectNodeFields(await ctx.engine(), parsed));
|
|
1134
|
+
}),
|
|
1135
|
+
entry("summer_inspect_resource", "Describe a resource file (mesh surfaces, AABB, materials; scene nodes; properties) or a resource a node holds", true, async (args, ctx) => {
|
|
1136
|
+
// ONE implementation for both faces (core/capabilities/inspect-resource.ts).
|
|
1137
|
+
const parsed = parseToolArgs(inspectResourceInputSchema, args, "inspect-resource");
|
|
1138
|
+
return requireEngineSuccess(await inspectResource(await ctx.engine(), parsed));
|
|
1055
1139
|
}),
|
|
1056
|
-
entry("summer_inspect_node", "Get all editable properties of a node", true, async (args, ctx) =>
|
|
1057
|
-
// E2E 2026-09-03 F-14: the engine returns Variant.Type as a bare int; both
|
|
1058
|
-
// faces add type_name (core/capabilities/variant-types.ts).
|
|
1059
|
-
annotateVariantTypes(requireEngineSuccess(await (await ctx.engine()).inspectNode(str(args, "path"))))),
|
|
1060
|
-
entry("summer_inspect_resource", "Get all properties of a resource", true, async (args, ctx) => requireEngineSuccess(await (await ctx.engine()).inspectResource(str(args, "path")))),
|
|
1061
1140
|
entry("summer_batch", "Run multiple engine ops as one undo group (verbatim passthrough)", true, async (args, ctx) => {
|
|
1062
1141
|
if (!Array.isArray(args.ops)) {
|
|
1063
1142
|
throw new ToolDispatchError("ops must be an array of operation objects");
|
|
@@ -1071,19 +1150,22 @@ export const TOOL_DISPATCH = [
|
|
|
1071
1150
|
throw new ToolDispatchError(`batch does not accept raw ${String(rawFileMutation.op)} operations. ` +
|
|
1072
1151
|
"Use write-file or replace-text so content guards are enforced.");
|
|
1073
1152
|
}
|
|
1153
|
+
const replaceRefusal = rawSceneReplaceRefusal(ops);
|
|
1154
|
+
if (replaceRefusal)
|
|
1155
|
+
throw new ToolDispatchError(replaceRefusal);
|
|
1074
1156
|
const scenePath = optStr(args, "scenePath");
|
|
1075
1157
|
const containsMutation = ops.some((op) => SCENE_MUTATION_OPS.has(String(op.op ?? "")));
|
|
1076
1158
|
const needsScenePath = containsMutation || ops.some((op) => SCENE_QUERY_OPS.has(String(op.op ?? "")));
|
|
1077
1159
|
if (needsScenePath && !scenePath) {
|
|
1078
1160
|
throw new ToolDispatchError("batch requires scenePath when ops targets a scene");
|
|
1079
1161
|
}
|
|
1080
|
-
const
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1162
|
+
const receipt = optStr(args, "receipt");
|
|
1163
|
+
if (receipt !== undefined && receipt !== "full" && receipt !== "summary") {
|
|
1164
|
+
throw new ToolDispatchError("receipt must be one of full, summary");
|
|
1165
|
+
}
|
|
1166
|
+
// Same engine path as the MCP face (core/capabilities/placement-batch.ts):
|
|
1167
|
+
// InstantiateScene placement fields and the compact summary receipt.
|
|
1168
|
+
return runBatch(await ctx.engine(), { scenePath, ops, receipt });
|
|
1087
1169
|
}),
|
|
1088
1170
|
// --- scene scripting ---
|
|
1089
1171
|
entry("summer_run_script", "Run a GDScript func run(ctx) inside the live editor against the open scene", true, async (args, ctx) => {
|
|
@@ -1175,15 +1257,13 @@ export const TOOL_DISPATCH = [
|
|
|
1175
1257
|
// --- perception ---
|
|
1176
1258
|
entry("summer_world_snapshot", "Structured snapshot of the edited scene (transforms, AABBs, fingerprints, counts)", true, async (args, ctx) => {
|
|
1177
1259
|
const client = await ctx.engine();
|
|
1260
|
+
const parsed = parseToolArgs(worldSnapshotInputSchema, args, "world-snapshot");
|
|
1178
1261
|
const missing = missingEngineOpResult(client, "GetWorldSnapshot", WORLD_SNAPSHOT_FALLBACK);
|
|
1179
1262
|
if (missing)
|
|
1180
1263
|
refuseMissingOp(missing);
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
if (typeof args.max_nodes === "number")
|
|
1185
|
-
op.max_nodes = args.max_nodes;
|
|
1186
|
-
return requireSupportedOp(await client.executeOps([op]), "GetWorldSnapshot", WORLD_SNAPSHOT_FALLBACK);
|
|
1264
|
+
// Same request + filter as the MCP face (core/capabilities/world-snapshot.ts).
|
|
1265
|
+
const result = await client.executeOps([buildWorldSnapshotOp(parsed)]);
|
|
1266
|
+
return requireSupportedOp(shapeWorldSnapshot(result, parsed), "GetWorldSnapshot", WORLD_SNAPSHOT_FALLBACK);
|
|
1187
1267
|
}),
|
|
1188
1268
|
entry("summer_snapshot_diff", "Diff two world snapshots into added/removed/changed nodes and count deltas", true, async (args, ctx) => {
|
|
1189
1269
|
const client = await ctx.engine();
|
|
@@ -1273,16 +1353,15 @@ export const TOOL_DISPATCH = [
|
|
|
1273
1353
|
throw new ToolDispatchError("maxDistance must be positive.");
|
|
1274
1354
|
if (gap < 0 || gap > maxDistance)
|
|
1275
1355
|
throw new ToolDispatchError("gap must be >= 0 and must not exceed maxDistance.");
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
]), "SnapToSurface", SNAP_TO_SURFACE_FALLBACK);
|
|
1356
|
+
// Same implementation as the MCP face (core/capabilities/surface-snap.ts).
|
|
1357
|
+
return requireSupportedOp(await snapToSurface(client, {
|
|
1358
|
+
scenePath,
|
|
1359
|
+
subjectPath: exactPath(args, "subjectPath", SPATIAL_NODE_PATH_LIMIT_BYTES),
|
|
1360
|
+
direction: direction,
|
|
1361
|
+
maxDistance,
|
|
1362
|
+
gap,
|
|
1363
|
+
alignUp: optBoolean(args, "alignUp", false),
|
|
1364
|
+
}), "SnapToSurface", SNAP_TO_SURFACE_FALLBACK);
|
|
1286
1365
|
}),
|
|
1287
1366
|
entry("summer_align_distribute_3d", "Align or equal-space 2-16 ordered subjects along one world axis (mutation + save)", true, async (args, ctx) => {
|
|
1288
1367
|
const client = await requireSpatialOp(ctx, "AlignDistribute3D", ALIGN_DISTRIBUTE_FALLBACK);
|
|
@@ -1363,10 +1442,53 @@ export const TOOL_DISPATCH = [
|
|
|
1363
1442
|
},
|
|
1364
1443
|
], { scenePath }), "Starcast3D", STARCAST_FALLBACK);
|
|
1365
1444
|
}),
|
|
1445
|
+
// --- kit placement (core/capabilities/placement.ts, shared with the MCP face) ---
|
|
1446
|
+
entry("summer_inspect_asset", "Measure an asset file (AABB, origin, meshes, planar faces, open loops, anchors, collision) without adding it to a scene", true, async (args, ctx) => {
|
|
1447
|
+
const parsed = parseToolArgs(inspectAssetArgsSchema, args, "inspect-asset");
|
|
1448
|
+
return inspectAsset(await ctx.engine(), parsed);
|
|
1449
|
+
}),
|
|
1450
|
+
entry("summer_place_adjacent", "Put one node's bounds face against another's along an axis and line up the other axes (mutation + save)", true, async (args, ctx) => {
|
|
1451
|
+
const parsed = parseToolArgs(placeAdjacentArgsSchema, args, "place-adjacent");
|
|
1452
|
+
return placeAdjacent(await ctx.engine(), parsed);
|
|
1453
|
+
}),
|
|
1454
|
+
entry("summer_attach_to_surface", "Turn a piece's back onto a surface hit by a ray and seat it at a standoff (mutation + save)", true, async (args, ctx) => {
|
|
1455
|
+
const parsed = parseToolArgs(attachToSurfaceArgsSchema, args, "attach-to-surface");
|
|
1456
|
+
return attachToSurface(await ctx.engine(), parsed);
|
|
1457
|
+
}),
|
|
1458
|
+
entry("summer_repeat_along", "Instance copies of a scene along a line at a spacing or count (mutation + save)", true, async (args, ctx) => {
|
|
1459
|
+
const parsed = parseToolArgs(repeatAlongArgsSchema, args, "repeat-along");
|
|
1460
|
+
return repeatAlong(await ctx.engine(), parsed);
|
|
1461
|
+
}),
|
|
1462
|
+
entry("summer_connect_ports", "Move and turn a piece so its port meets another piece's port (mutation + save)", true, async (args, ctx) => {
|
|
1463
|
+
const parsed = parseToolArgs(connectPortsArgsSchema, args, "connect-ports");
|
|
1464
|
+
return connectPorts(await ctx.engine(), parsed);
|
|
1465
|
+
}),
|
|
1466
|
+
entry("summer_raycast", "Cast one ray from any point: hit path, point, normal (physics first, visual AABB fallback declared)", true, async (args, ctx) => {
|
|
1467
|
+
const parsed = parseToolArgs(raycastArgsSchema, args, "raycast");
|
|
1468
|
+
return raycast(await ctx.engine(), parsed);
|
|
1469
|
+
}),
|
|
1470
|
+
entry("summer_measure", "Gap or overlap per axis between two nodes, or face coplanarity across nodes (read-only)", true, async (args, ctx) => {
|
|
1471
|
+
const parsed = parseToolArgs(measureArgsSchema, args, "measure");
|
|
1472
|
+
return measure(await ctx.engine(), parsed);
|
|
1473
|
+
}),
|
|
1366
1474
|
// --- visual ---
|
|
1367
1475
|
entry("summer_screenshot", "Capture an editor viewport, scene render, or game frame to a file", true, async (args, ctx) => {
|
|
1368
1476
|
const client = await ctx.engine();
|
|
1369
1477
|
const target = optStr(args, "target") ?? "viewport";
|
|
1478
|
+
if (args.compare_previous === true) {
|
|
1479
|
+
const bookmarkName = optStr(args, "bookmark_name");
|
|
1480
|
+
const framingArg = optStr(args, "framing");
|
|
1481
|
+
if (target !== "scene" || !bookmarkName || (framingArg !== undefined && framingArg !== "bookmark")) {
|
|
1482
|
+
throw new ToolDispatchError('compare_previous needs target "scene" with framing "bookmark" and bookmark_name.');
|
|
1483
|
+
}
|
|
1484
|
+
const fovArg = optNumberOrUndefined(args, "fov");
|
|
1485
|
+
return seeingResult(await buildOrRefuseAsync(() => shotSheet(client, {
|
|
1486
|
+
scenePath: optStr(args, "scenePath"),
|
|
1487
|
+
shots: [{ bookmark_name: bookmarkName, ...(fovArg !== undefined ? { fov: fovArg } : {}) }],
|
|
1488
|
+
compare_previous: true,
|
|
1489
|
+
max_size: 1536,
|
|
1490
|
+
})), "screenshot-compare");
|
|
1491
|
+
}
|
|
1370
1492
|
// Same capture path as the MCP face (core/capabilities/capture.ts): every
|
|
1371
1493
|
// frame is content-checked, a flat viewport frame is recaptured once, and a
|
|
1372
1494
|
// camera-less scene render learns its 2D/3D kind — the receipt carries
|
|
@@ -1394,6 +1516,11 @@ export const TOOL_DISPATCH = [
|
|
|
1394
1516
|
max_marks: optNumberOrUndefined(args, "max_marks"),
|
|
1395
1517
|
}));
|
|
1396
1518
|
snap = await captureScene(client, preview);
|
|
1519
|
+
const bookmark = preview.framing?.startsWith("bookmark:") ? preview.framing.slice("bookmark:".length) : undefined;
|
|
1520
|
+
if (snap.ok && snap.base64 && bookmark && snap.framing === preview.framing) {
|
|
1521
|
+
const slotNotes = await rememberBookmarkRender(typeof client.getProjectRoot === "function" ? client.getProjectRoot() : undefined, bookmark, { base64: snap.base64, width: snap.width, height: snap.height }, preview.marks === true, slotPolicy({ updatePrevious: optBoolean(args, "update_previous", false) }));
|
|
1522
|
+
return { ...(await snapshotResult(snap, target)), slot_notes: slotNotes };
|
|
1523
|
+
}
|
|
1397
1524
|
}
|
|
1398
1525
|
else {
|
|
1399
1526
|
snap = await captureViewport(client);
|
|
@@ -1419,6 +1546,38 @@ export const TOOL_DISPATCH = [
|
|
|
1419
1546
|
refuseMissingOp(missing);
|
|
1420
1547
|
return requireSupportedOp(await client.executeOps([op]), kind, CAMERA_BOOKMARK_FALLBACK);
|
|
1421
1548
|
}),
|
|
1549
|
+
// --- seeing (shared implementation: core/capabilities/seeing/) ---
|
|
1550
|
+
entry("summer_frame_nodes", "Frame nodes by their world bounds and render with the REAL environment (image to a temp file)", true, async (args, ctx) => {
|
|
1551
|
+
const parsed = parseToolArgs(frameNodesArgsSchema, args, "frame-nodes");
|
|
1552
|
+
const client = (await ctx.engine());
|
|
1553
|
+
return seeingResult(await buildOrRefuseAsync(() => frameNodes(client, parsed)), "frame-nodes");
|
|
1554
|
+
}),
|
|
1555
|
+
entry("summer_shot_sheet", "Render N bookmarks/poses into one labelled grid with real lighting; compare_previous adds a difference map", true, async (args, ctx) => {
|
|
1556
|
+
const parsed = parseToolArgs(shotSheetArgsSchema, args, "shot-sheet");
|
|
1557
|
+
const client = (await ctx.engine());
|
|
1558
|
+
return seeingResult(await buildOrRefuseAsync(() => shotSheet(client, parsed)), "shot-sheet");
|
|
1559
|
+
}),
|
|
1560
|
+
entry("summer_debug_views", "One pose as beauty/lighting/unshaded/normals/overdraw/wireframe in one grid", true, async (args, ctx) => {
|
|
1561
|
+
const parsed = parseToolArgs(debugViewsArgsSchema, args, "debug-views");
|
|
1562
|
+
const client = (await ctx.engine());
|
|
1563
|
+
return seeingResult(await buildOrRefuseAsync(() => debugViews(client, parsed)), "debug-views");
|
|
1564
|
+
}),
|
|
1565
|
+
entry("summer_zoom", "High-resolution sub-frustum render of a frame region or mark N", true, async (args, ctx) => {
|
|
1566
|
+
const parsed = parseToolArgs(zoomArgsSchema, args, "zoom");
|
|
1567
|
+
const client = (await ctx.engine());
|
|
1568
|
+
return seeingResult(await buildOrRefuseAsync(() => zoom(client, parsed)), "zoom");
|
|
1569
|
+
}),
|
|
1570
|
+
entry("summer_frame_shot", "Smart framing: score candidate poses for a shot type in-engine, bookmark the best, render the top 3", true, async (args, ctx) => {
|
|
1571
|
+
const parsed = parseToolArgs(frameShotArgsSchema, args, "frame-shot");
|
|
1572
|
+
const client = (await ctx.engine());
|
|
1573
|
+
return seeingResult(await buildOrRefuseAsync(() => frameShot(client, parsed)), "frame-shot");
|
|
1574
|
+
}),
|
|
1575
|
+
// --- scene audit (shared implementation: core/capabilities/audit/) ---
|
|
1576
|
+
entry("summer_scene_audit", "Read-only audit of a 3D scene from geometry and materials: see-through holes, exposed edges, open pipe ends, depth steps, floor gaps, floating/sunken/overlapping props, orientation, UV stretch, z-fighting, lights, transforms, resources (<= 5 KB page; accept hides judged-fine look items)", true, async (args, ctx) => {
|
|
1577
|
+
const parsed = parseToolArgs(sceneAuditArgsSchema, args, "scene-audit");
|
|
1578
|
+
const client = (await ctx.engine());
|
|
1579
|
+
return auditResult(await buildOrRefuseAsync(() => sceneAudit(client, parsed)));
|
|
1580
|
+
}),
|
|
1422
1581
|
// --- library (the runtime librarian; engine-free) ---
|
|
1423
1582
|
entry("summer_search_library", "Search the Summer library by describing the task in plain words", false, async (args) => runSearchLibrary(parseToolArgs(searchLibraryInputSchema, args, "search-library"))),
|
|
1424
1583
|
entry("summer_read_library", "Load one library entry by id — body, metadata, how to call or install it", false, async (args) => {
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tscn — a small reader for the Godot text scene format (`.tscn`, format 3),
|
|
3
|
+
* enough to answer "what did the editor actually SAVE": which ext_resources
|
|
4
|
+
* the file references, every [node] entry (name, parent, type/instance,
|
|
5
|
+
* groups, its property overrides as raw text), [connection] and [editable]
|
|
6
|
+
* entries.
|
|
7
|
+
*
|
|
8
|
+
* Used by summer_replace_node to read the scene before a replacement (which
|
|
9
|
+
* children the user added under the node, which properties it overrides) and
|
|
10
|
+
* to verify afterwards that the saved file really references the new scene.
|
|
11
|
+
* Property values stay raw Godot literal text; nothing here evaluates them.
|
|
12
|
+
*/
|
|
13
|
+
export interface TscnProp {
|
|
14
|
+
key: string;
|
|
15
|
+
/** Raw value text exactly as written (may span several lines). */
|
|
16
|
+
value: string;
|
|
17
|
+
}
|
|
18
|
+
export interface TscnExtResource {
|
|
19
|
+
id: string;
|
|
20
|
+
type?: string;
|
|
21
|
+
path?: string;
|
|
22
|
+
uid?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface TscnNode {
|
|
25
|
+
name: string;
|
|
26
|
+
/** Scene-root-relative path: "." for the root, else "A/B". */
|
|
27
|
+
path: string;
|
|
28
|
+
/** null for the root; "." or "A/B" otherwise (as written in the file). */
|
|
29
|
+
parent: string | null;
|
|
30
|
+
type?: string;
|
|
31
|
+
/** ext_resource id of `instance=ExtResource("…")`. */
|
|
32
|
+
instance?: string;
|
|
33
|
+
/** Resolved res:// path of the instanced scene, when the ext_resource is listed. */
|
|
34
|
+
instancePath?: string;
|
|
35
|
+
instancePlaceholder?: string;
|
|
36
|
+
index?: number;
|
|
37
|
+
groups: string[];
|
|
38
|
+
props: TscnProp[];
|
|
39
|
+
/** Position of the [node] entry in the file (0-based). */
|
|
40
|
+
order: number;
|
|
41
|
+
}
|
|
42
|
+
export interface TscnConnection {
|
|
43
|
+
signal: string;
|
|
44
|
+
from: string;
|
|
45
|
+
to: string;
|
|
46
|
+
method: string;
|
|
47
|
+
flags?: number;
|
|
48
|
+
/** The header line as written. */
|
|
49
|
+
raw: string;
|
|
50
|
+
}
|
|
51
|
+
export interface ParsedTscn {
|
|
52
|
+
format?: number;
|
|
53
|
+
extResources: Map<string, TscnExtResource>;
|
|
54
|
+
nodes: TscnNode[];
|
|
55
|
+
connections: TscnConnection[];
|
|
56
|
+
/** [editable path="…"] entries (instances with editable children). */
|
|
57
|
+
editable: string[];
|
|
58
|
+
}
|
|
59
|
+
/** Decode a Godot quoted string body (without the quotes). */
|
|
60
|
+
export declare function decodeGodotString(body: string): string;
|
|
61
|
+
/** If `raw` is exactly one quoted string literal (optionally prefixed with
|
|
62
|
+
* & for StringName or ^ for NodePath), its decoded text; else undefined. */
|
|
63
|
+
export declare function quotedLiteral(raw: string): string | undefined;
|
|
64
|
+
/** `ExtResource("1_ab")` / `ExtResource( 1 )` -> "1_ab" / "1". */
|
|
65
|
+
export declare function extResourceId(raw: string | undefined): string | undefined;
|
|
66
|
+
/** `SubResource("Box_x")` -> "Box_x". */
|
|
67
|
+
export declare function subResourceId(raw: string): string | undefined;
|
|
68
|
+
/** Normalize a scene-relative node path the way the engine resolves it:
|
|
69
|
+
* "", ".", "./" and "/" are the root (returned as "."); a leading "./" is
|
|
70
|
+
* dropped; trailing slashes are dropped. */
|
|
71
|
+
export declare function normalizeNodePath(path: string): string;
|
|
72
|
+
/** Join a parent path ("." or "A/B") and a child name. */
|
|
73
|
+
export declare function joinNodePath(parent: string, name: string): string;
|
|
74
|
+
/** Parent of a normalized path ("A/B" -> "A", "A" -> "."). The root has none. */
|
|
75
|
+
export declare function parentNodePath(path: string): string | null;
|
|
76
|
+
/** True when `path` is `ancestor` or below it. */
|
|
77
|
+
export declare function isAtOrBelow(path: string, ancestor: string): boolean;
|
|
78
|
+
export declare function parseTscn(text: string): ParsedTscn;
|
|
79
|
+
export declare function findTscnNode(parsed: ParsedTscn, path: string): TscnNode | undefined;
|
|
80
|
+
/** A node the scene itself creates (and owns): it has a type, an instance or
|
|
81
|
+
* a placeholder. An entry with none of those is a property override of a
|
|
82
|
+
* node that an instanced (or inherited) scene creates. */
|
|
83
|
+
export declare function isSceneCreatedNode(node: TscnNode): boolean;
|
|
84
|
+
/** Normalize a res:// path for comparison. */
|
|
85
|
+
export declare function normalizeResPath(path: string): string;
|