summer-engine 3.0.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.
Files changed (413) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +27 -5
  3. package/.codex-plugin/plugin.json +28 -6
  4. package/.cursor-plugin/plugin.json +27 -5
  5. package/.factory-plugin/plugin.json +27 -5
  6. package/.opencode/plugins/summer.js +1 -1
  7. package/CHANGELOG.md +120 -0
  8. package/README.md +22 -7
  9. package/assets/audit/scene_audit.gd +4136 -0
  10. package/assets/seeing/seeing_probe.gd +1873 -0
  11. package/dist/cli/commands/setup.js +6 -19
  12. package/dist/cli/commands/skills.js +57 -32
  13. package/dist/core/api-client.d.ts +9 -1
  14. package/dist/core/api-client.js +21 -4
  15. package/dist/core/capabilities/agent-playbook.js +46 -0
  16. package/dist/core/capabilities/audit/accept.d.ts +55 -0
  17. package/dist/core/capabilities/audit/accept.js +147 -0
  18. package/dist/core/capabilities/audit/args.d.ts +95 -0
  19. package/dist/core/capabilities/audit/args.js +89 -0
  20. package/dist/core/capabilities/audit/audit.d.ts +56 -0
  21. package/dist/core/capabilities/audit/audit.js +287 -0
  22. package/dist/core/capabilities/audit/frame.d.ts +14 -0
  23. package/dist/core/capabilities/audit/frame.js +35 -0
  24. package/dist/core/capabilities/audit/gaps.d.ts +96 -0
  25. package/dist/core/capabilities/audit/gaps.js +257 -0
  26. package/dist/core/capabilities/audit/judge.d.ts +162 -0
  27. package/dist/core/capabilities/audit/judge.js +1134 -0
  28. package/dist/core/capabilities/audit/math.d.ts +110 -0
  29. package/dist/core/capabilities/audit/math.js +263 -0
  30. package/dist/core/capabilities/audit/summary.d.ts +74 -0
  31. package/dist/core/capabilities/audit/summary.js +212 -0
  32. package/dist/core/capabilities/board.d.ts +31 -0
  33. package/dist/core/capabilities/board.js +43 -0
  34. package/dist/core/capabilities/camera-view.d.ts +4 -2
  35. package/dist/core/capabilities/camera-view.js +6 -3
  36. package/dist/core/capabilities/connect-signal.d.ts +85 -0
  37. package/dist/core/capabilities/connect-signal.js +285 -0
  38. package/dist/core/capabilities/engine-fallbacks.d.ts +5 -0
  39. package/dist/core/capabilities/engine-fallbacks.js +5 -0
  40. package/dist/core/capabilities/engine-ops.d.ts +5 -1
  41. package/dist/core/capabilities/engine-ops.js +0 -3
  42. package/dist/core/capabilities/engine-receipt.d.ts +12 -0
  43. package/dist/core/capabilities/engine-receipt.js +26 -0
  44. package/dist/core/capabilities/file-read.d.ts +64 -0
  45. package/dist/core/capabilities/file-read.js +325 -0
  46. package/dist/core/capabilities/game-task-plan.js +4 -2
  47. package/dist/core/capabilities/grep.d.ts +60 -0
  48. package/dist/core/capabilities/grep.js +190 -0
  49. package/dist/core/capabilities/inspect-node.d.ts +56 -0
  50. package/dist/core/capabilities/inspect-node.js +225 -0
  51. package/dist/core/capabilities/inspect-resource.d.ts +61 -0
  52. package/dist/core/capabilities/inspect-resource.js +376 -0
  53. package/dist/core/capabilities/math3d.d.ts +28 -0
  54. package/dist/core/capabilities/math3d.js +88 -0
  55. package/dist/core/capabilities/motion-generation.d.ts +62 -0
  56. package/dist/core/capabilities/motion-generation.js +138 -0
  57. package/dist/core/capabilities/placement-batch.d.ts +102 -0
  58. package/dist/core/capabilities/placement-batch.js +483 -0
  59. package/dist/core/capabilities/placement-math.d.ts +70 -0
  60. package/dist/core/capabilities/placement-math.js +209 -0
  61. package/dist/core/capabilities/placement-script.d.ts +42 -0
  62. package/dist/core/capabilities/placement-script.js +1096 -0
  63. package/dist/core/capabilities/placement.d.ts +485 -0
  64. package/dist/core/capabilities/placement.js +1731 -0
  65. package/dist/core/capabilities/project-context.d.ts +33 -2
  66. package/dist/core/capabilities/project-context.js +87 -4
  67. package/dist/core/capabilities/replace-node.d.ts +91 -0
  68. package/dist/core/capabilities/replace-node.js +423 -0
  69. package/dist/core/capabilities/runtime-control.d.ts +20 -4
  70. package/dist/core/capabilities/runtime-control.js +67 -2
  71. package/dist/core/capabilities/scene-batch.d.ts +63 -0
  72. package/dist/core/capabilities/scene-batch.js +394 -0
  73. package/dist/core/capabilities/scene-readback.d.ts +36 -0
  74. package/dist/core/capabilities/scene-readback.js +54 -0
  75. package/dist/core/capabilities/seeing/args.d.ts +348 -0
  76. package/dist/core/capabilities/seeing/args.js +178 -0
  77. package/dist/core/capabilities/seeing/candidates.d.ts +127 -0
  78. package/dist/core/capabilities/seeing/candidates.js +282 -0
  79. package/dist/core/capabilities/seeing/math.d.ts +134 -0
  80. package/dist/core/capabilities/seeing/math.js +269 -0
  81. package/dist/core/capabilities/seeing/probe.d.ts +62 -0
  82. package/dist/core/capabilities/seeing/probe.js +188 -0
  83. package/dist/core/capabilities/seeing/scoring.d.ts +235 -0
  84. package/dist/core/capabilities/seeing/scoring.js +639 -0
  85. package/dist/core/capabilities/seeing/seeing.d.ts +233 -0
  86. package/dist/core/capabilities/seeing/seeing.js +1341 -0
  87. package/dist/core/capabilities/seeing/shot-store.d.ts +52 -0
  88. package/dist/core/capabilities/seeing/shot-store.js +204 -0
  89. package/dist/core/capabilities/surface-snap-mesh.d.ts +88 -0
  90. package/dist/core/capabilities/surface-snap-mesh.js +425 -0
  91. package/dist/core/capabilities/surface-snap.d.ts +77 -0
  92. package/dist/core/capabilities/surface-snap.js +461 -0
  93. package/dist/core/capabilities/tool-dispatch.js +231 -72
  94. package/dist/core/capabilities/tscn.d.ts +85 -0
  95. package/dist/core/capabilities/tscn.js +391 -0
  96. package/dist/core/capabilities/world-snapshot.d.ts +58 -0
  97. package/dist/core/capabilities/world-snapshot.js +150 -0
  98. package/dist/core/capability-skew.d.ts +5 -5
  99. package/dist/core/capability-skew.js +14 -6
  100. package/dist/core/headless/worker-engine-client.d.ts +1 -1
  101. package/dist/core/headless/worker-engine-client.js +2 -2
  102. package/dist/core/library-read.d.ts +37 -5
  103. package/dist/core/library-read.js +264 -33
  104. package/dist/core/library-search.d.ts +2 -2
  105. package/dist/core/skills-registry.d.ts +9 -1
  106. package/dist/core/skills-registry.js +25 -2
  107. package/dist/installer/agent-config.d.ts +9 -4
  108. package/dist/installer/agent-config.js +194 -392
  109. package/dist/installer/agent-table.d.ts +119 -0
  110. package/dist/installer/agent-table.js +619 -0
  111. package/dist/installer/setup.js +4 -2
  112. package/dist/installer/skill-locations.d.ts +8 -17
  113. package/dist/installer/skill-locations.js +22 -101
  114. package/dist/installer/version-check.d.ts +5 -1
  115. package/dist/installer/version-check.js +38 -28
  116. package/dist/mcp/server.js +9 -3
  117. package/dist/mcp/tools/asset-tools.js +21 -3
  118. package/dist/mcp/tools/audit-tools.d.ts +23 -0
  119. package/dist/mcp/tools/audit-tools.js +60 -0
  120. package/dist/mcp/tools/debug-tools.js +3 -1
  121. package/dist/mcp/tools/file-tools.js +17 -4
  122. package/dist/mcp/tools/generate-tools.js +74 -66
  123. package/dist/mcp/tools/library-tools.js +2 -0
  124. package/dist/mcp/tools/perception-tools.js +6 -19
  125. package/dist/mcp/tools/placement-tools.d.ts +24 -0
  126. package/dist/mcp/tools/placement-tools.js +91 -0
  127. package/dist/mcp/tools/project-tools.js +18 -15
  128. package/dist/mcp/tools/scene-tools.js +71 -83
  129. package/dist/mcp/tools/seeing-tools.d.ts +24 -0
  130. package/dist/mcp/tools/seeing-tools.js +64 -0
  131. package/dist/mcp/tools/spatial-tools.js +17 -9
  132. package/dist/mcp/tools/visual-tools.js +59 -7
  133. package/gemini-extension.json +26 -4
  134. package/integrations/README.md +48 -19
  135. package/integrations/amp/README.md +12 -0
  136. package/integrations/amp/manifest-target.json +3 -0
  137. package/integrations/antigravity/README.md +12 -0
  138. package/integrations/antigravity/manifest-target.json +3 -0
  139. package/integrations/claude-desktop/README.md +12 -0
  140. package/integrations/claude-desktop/manifest-target.json +3 -0
  141. package/integrations/cline/README.md +8 -9
  142. package/integrations/cline-cli/README.md +12 -0
  143. package/integrations/cline-cli/manifest-target.json +3 -0
  144. package/integrations/copilot-jetbrains/README.md +12 -0
  145. package/integrations/copilot-jetbrains/manifest-target.json +3 -0
  146. package/integrations/crush/README.md +12 -0
  147. package/integrations/crush/manifest-target.json +3 -0
  148. package/integrations/github-copilot/README.md +8 -8
  149. package/integrations/goose/README.md +12 -0
  150. package/integrations/goose/manifest-target.json +3 -0
  151. package/integrations/grok-build/README.md +12 -0
  152. package/integrations/grok-build/manifest-target.json +3 -0
  153. package/integrations/hermes/README.md +12 -0
  154. package/integrations/hermes/manifest-target.json +3 -0
  155. package/integrations/junie/README.md +12 -0
  156. package/integrations/junie/manifest-target.json +3 -0
  157. package/integrations/kilo-code/README.md +6 -10
  158. package/integrations/kimi-code/README.md +12 -0
  159. package/integrations/kimi-code/manifest-target.json +3 -0
  160. package/integrations/kiro/README.md +12 -0
  161. package/integrations/kiro/manifest-target.json +3 -0
  162. package/integrations/lm-studio/README.md +8 -8
  163. package/integrations/mistral-vibe/README.md +12 -0
  164. package/integrations/mistral-vibe/manifest-target.json +3 -0
  165. package/integrations/opencode/README.md +9 -12
  166. package/integrations/qoder/README.md +12 -0
  167. package/integrations/qoder/manifest-target.json +3 -0
  168. package/integrations/qwen-code/README.md +12 -0
  169. package/integrations/qwen-code/manifest-target.json +3 -0
  170. package/integrations/roo-code/README.md +8 -7
  171. package/integrations/rovo-dev/README.md +12 -0
  172. package/integrations/rovo-dev/manifest-target.json +3 -0
  173. package/integrations/trae/README.md +12 -0
  174. package/integrations/trae/manifest-target.json +3 -0
  175. package/integrations/visual-studio/README.md +12 -0
  176. package/integrations/visual-studio/manifest-target.json +3 -0
  177. package/integrations/vscode-copilot/README.md +9 -9
  178. package/integrations/warp/README.md +12 -0
  179. package/integrations/warp/manifest-target.json +3 -0
  180. package/integrations/windsurf/README.md +8 -9
  181. package/integrations/zed/README.md +12 -0
  182. package/integrations/zed/manifest-target.json +3 -0
  183. package/library/references/mcp-tools-reference/mcp-tools-reference.md +59 -15
  184. package/library/references/mcp-tools-reference/resource.yaml +1 -1
  185. package/library/references/summer-folder/resource.yaml +1 -1
  186. package/library/references/summer-folder/summer-folder.md +1 -1
  187. package/library/skills/3d-lighting/SKILL.md +1 -1
  188. package/library/skills/README.md +264 -0
  189. package/library/skills/adaptive-music/SKILL.md +1 -1
  190. package/library/skills/agent-playtesting/SKILL.md +1 -1
  191. package/library/skills/ai-characters-in-games/SKILL.md +220 -0
  192. package/library/skills/ai-characters-in-games/resource.yaml +30 -0
  193. package/library/skills/ambient-bed/SKILL.md +1 -1
  194. package/library/skills/animated-loop/SKILL.md +1 -1
  195. package/library/skills/animation-tree/SKILL.md +1 -1
  196. package/library/skills/art-direction/SKILL.md +1 -1
  197. package/library/skills/asset-strategy/SKILL.md +2 -1
  198. package/library/skills/asset-strategy/resource.yaml +2 -1
  199. package/library/skills/audio-direction/SKILL.md +1 -1
  200. package/library/skills/auto-fire-targeting/SKILL.md +1 -1
  201. package/library/skills/brainstorm-game/SKILL.md +1 -1
  202. package/library/skills/brainstorming/SKILL.md +1 -1
  203. package/library/skills/browse-templates/SKILL.md +3 -3
  204. package/library/skills/browse-templates/resource.yaml +1 -1
  205. package/library/skills/camera-rigs/SKILL.md +128 -0
  206. package/library/skills/camera-rigs/resource.yaml +29 -0
  207. package/library/skills/celeste-momentum-platforming/SKILL.md +1 -1
  208. package/library/skills/character-animation-wiring/SKILL.md +1 -1
  209. package/library/skills/character-model/SKILL.md +1 -1
  210. package/library/skills/character-movement/SKILL.md +326 -0
  211. package/library/skills/character-movement/references/default-third-person-controller.gd +201 -0
  212. package/library/skills/character-movement/references/default-third-person-verification-probe.gd +154 -0
  213. package/library/skills/character-movement/references/movement-3d.md +136 -0
  214. package/library/skills/character-movement/references/platformer-feel.md +83 -0
  215. package/library/skills/character-movement/resource.yaml +40 -0
  216. package/library/skills/character-portrait/SKILL.md +1 -1
  217. package/library/skills/cinematic-cutscene/SKILL.md +1 -1
  218. package/library/skills/combat-basics/SKILL.md +159 -0
  219. package/library/skills/combat-basics/references/projectiles-and-aoe.md +100 -0
  220. package/library/skills/combat-basics/resource.yaml +34 -0
  221. package/library/skills/concept-art/SKILL.md +1 -1
  222. package/library/skills/create-asset-sheet/SKILL.md +1 -1
  223. package/library/skills/debug/SKILL.md +1 -1
  224. package/library/skills/debugging-game-feel/SKILL.md +1 -1
  225. package/library/skills/design-level/SKILL.md +1 -1
  226. package/library/skills/design-mechanic/SKILL.md +1 -1
  227. package/library/skills/design-npc/SKILL.md +1 -1
  228. package/library/skills/diagnosing-perf-regressions/SKILL.md +1 -1
  229. package/library/skills/dispatching-parallel-agents/SKILL.md +1 -1
  230. package/library/skills/driving-the-editor-ui/SKILL.md +1 -1
  231. package/library/skills/environment-kit/SKILL.md +1 -1
  232. package/library/skills/export-and-ship/SKILL.md +1 -1
  233. package/library/skills/fabricating-assets/SKILL.md +1 -1
  234. package/library/skills/facial-and-lipsync/SKILL.md +1 -1
  235. package/library/skills/fps-controller/SKILL.md +9 -7
  236. package/library/skills/fps-controller/resource.yaml +4 -1
  237. package/library/skills/game-feel/SKILL.md +1 -1
  238. package/library/skills/gameskill/SKILL.md +1 -1
  239. package/library/skills/gdscript-patterns/SKILL.md +1 -1
  240. package/library/skills/generate-motion/SKILL.md +9 -9
  241. package/library/skills/generate-motion/resource.yaml +2 -1
  242. package/library/skills/godogen-visual-proof-game-generation/SKILL.md +1 -1
  243. package/library/skills/headless-scripting/SKILL.md +1 -1
  244. package/library/skills/in-game-purchases/SKILL.md +254 -0
  245. package/library/skills/in-game-purchases/resource.yaml +29 -0
  246. package/library/skills/instantiate-asset-pack/SKILL.md +1 -1
  247. package/library/skills/investigating-bugs/SKILL.md +1 -1
  248. package/library/skills/lumera-single-image-scene-reconstruction/SKILL.md +1 -1
  249. package/library/skills/make-game/SKILL.md +25 -3
  250. package/library/skills/make-game/references/2d-platformer-polish.md +93 -0
  251. package/library/skills/make-game/references/2d-platformer.md +117 -0
  252. package/library/skills/make-game/references/2d-rpg-content.md +234 -0
  253. package/library/skills/make-game/references/2d-rpg.md +241 -0
  254. package/library/skills/make-game/references/2d-survivors-progression.md +201 -0
  255. package/library/skills/make-game/references/2d-survivors.md +237 -0
  256. package/library/skills/make-game/references/3d-fps-systems.md +216 -0
  257. package/library/skills/make-game/references/3d-fps.md +177 -0
  258. package/library/skills/make-game/references/3d-horror-systems.md +186 -0
  259. package/library/skills/make-game/references/3d-horror.md +201 -0
  260. package/library/skills/make-game/references/3d-third-person-systems.md +220 -0
  261. package/library/skills/make-game/references/3d-third-person.md +215 -0
  262. package/library/skills/make-game/resource.yaml +6 -1
  263. package/library/skills/multiplayer/SKILL.md +150 -0
  264. package/library/skills/multiplayer/resource.yaml +33 -0
  265. package/library/skills/multiplayer-movement/SKILL.md +510 -0
  266. package/library/skills/multiplayer-movement/files.md +501 -0
  267. package/library/skills/multiplayer-movement/resource.yaml +30 -0
  268. package/library/skills/multiplayer-project/SKILL.md +521 -0
  269. package/library/skills/multiplayer-project/files.md +448 -0
  270. package/library/skills/multiplayer-project/resource.yaml +36 -0
  271. package/library/skills/multiplayer-publish/SKILL.md +229 -0
  272. package/library/skills/multiplayer-publish/export-errors.md +89 -0
  273. package/library/skills/multiplayer-publish/resource.yaml +28 -0
  274. package/library/skills/multiplayer-state/SKILL.md +438 -0
  275. package/library/skills/multiplayer-state/files.md +592 -0
  276. package/library/skills/multiplayer-state/resource.yaml +35 -0
  277. package/library/skills/multiplayer-testing/SKILL.md +236 -0
  278. package/library/skills/multiplayer-testing/resource.yaml +39 -0
  279. package/library/skills/music-track/SKILL.md +1 -1
  280. package/library/skills/navigate-summer/SKILL.md +1 -1
  281. package/library/skills/new-project/SKILL.md +1 -1
  282. package/library/skills/organic-model/SKILL.md +1 -1
  283. package/library/skills/pixel-art/SKILL.md +1 -1
  284. package/library/skills/play/SKILL.md +1 -1
  285. package/library/skills/playtesting-a-feature/SKILL.md +1 -1
  286. package/library/skills/procedural-animation/SKILL.md +2 -2
  287. package/library/skills/procedural-animation/resource.yaml +1 -1
  288. package/library/skills/prop-model/SKILL.md +1 -1
  289. package/library/skills/psx-retro-rendering/SKILL.md +1 -1
  290. package/library/skills/realtime-wet-surfaces/SKILL.md +2 -2
  291. package/library/skills/remote-deploy/SKILL.md +1 -1
  292. package/library/skills/retarget/SKILL.md +1 -1
  293. package/library/skills/running-in-the-cloud/SKILL.md +1 -1
  294. package/library/skills/save-load/SKILL.md +156 -0
  295. package/library/skills/save-load/resource.yaml +27 -0
  296. package/library/skills/scene-composition/SKILL.md +1 -1
  297. package/library/skills/scene-hierarchy-design/SKILL.md +1 -1
  298. package/library/skills/scene-scripting/SKILL.md +1 -1
  299. package/library/skills/scene-to-level/SKILL.md +1 -1
  300. package/library/skills/skill-create/SKILL.md +1 -1
  301. package/library/skills/skill-improve/SKILL.md +1 -1
  302. package/library/skills/skill-test/SKILL.md +1 -1
  303. package/library/skills/skintokens-auto-rigging/SKILL.md +1 -1
  304. package/library/skills/skybox-panorama/SKILL.md +1 -1
  305. package/library/skills/sound-effect/SKILL.md +1 -1
  306. package/library/skills/spatial-placement/SKILL.md +134 -3
  307. package/library/skills/spatial-placement/references/kit-placement-tools.md +364 -0
  308. package/library/skills/spatial-placement/resource.yaml +16 -2
  309. package/library/skills/sprite-sheet/SKILL.md +1 -1
  310. package/library/skills/summer-analytics/SKILL.md +147 -0
  311. package/library/skills/summer-analytics/resource.yaml +28 -0
  312. package/library/skills/summer-friends/SKILL.md +226 -0
  313. package/library/skills/summer-friends/resource.yaml +28 -0
  314. package/library/skills/summer-leaderboards/SKILL.md +231 -0
  315. package/library/skills/summer-leaderboards/resource.yaml +30 -0
  316. package/library/skills/summer-match-results/SKILL.md +286 -0
  317. package/library/skills/summer-match-results/resource.yaml +32 -0
  318. package/library/skills/summer-matchmaking/SKILL.md +301 -0
  319. package/library/skills/summer-matchmaking/resource.yaml +32 -0
  320. package/library/skills/summer-parties/SKILL.md +253 -0
  321. package/library/skills/summer-parties/resource.yaml +30 -0
  322. package/library/skills/summer-player-data/SKILL.md +322 -0
  323. package/library/skills/summer-player-data/resource.yaml +30 -0
  324. package/library/skills/summer-store/SKILL.md +271 -0
  325. package/library/skills/summer-store/resource.yaml +29 -0
  326. package/library/skills/summer-world-chat/SKILL.md +195 -0
  327. package/library/skills/summer-world-chat/resource.yaml +30 -0
  328. package/library/skills/summer-world-saves/SKILL.md +284 -0
  329. package/library/skills/summer-world-saves/resource.yaml +29 -0
  330. package/library/skills/text-to-motion/SKILL.md +99 -0
  331. package/library/skills/text-to-motion/prompts-and-controls.md +34 -0
  332. package/library/skills/text-to-motion/resource.yaml +41 -0
  333. package/library/skills/text-to-motion/rigging-for-text-motion.md +54 -0
  334. package/library/skills/tileable-texture/SKILL.md +1 -1
  335. package/library/skills/trailer-shot/SKILL.md +1 -1
  336. package/library/skills/tune-performance/SKILL.md +1 -1
  337. package/library/skills/ui-basics/SKILL.md +10 -1
  338. package/library/skills/ui-graphics/SKILL.md +1 -1
  339. package/library/skills/use-widget-asset/SKILL.md +1 -1
  340. package/library/skills/using-summer/SKILL.md +2 -2
  341. package/library/skills/using-summer/resource.yaml +2 -2
  342. package/library/skills/vehicle-model/SKILL.md +1 -1
  343. package/library/skills/verification-before-completion/SKILL.md +1 -1
  344. package/library/skills/verifying-scenes/SKILL.md +76 -2
  345. package/library/skills/verifying-scenes/resource.yaml +13 -2
  346. package/library/skills/vfx-dissolve/SKILL.md +1 -1
  347. package/library/skills/vfx-fire/SKILL.md +1 -1
  348. package/library/skills/vfx-hit-spark/SKILL.md +1 -1
  349. package/library/skills/vfx-lightning/SKILL.md +1 -1
  350. package/library/skills/vfx-magic-glow/SKILL.md +1 -1
  351. package/library/skills/vfx-muzzle-flash/SKILL.md +1 -1
  352. package/library/skills/vfx-smoke/SKILL.md +1 -1
  353. package/library/skills/vfx-water-ripple/SKILL.md +1 -1
  354. package/library/skills/voice-line/SKILL.md +1 -1
  355. package/library/skills/web-and-touch-input/SKILL.md +38 -0
  356. package/library/skills/web-and-touch-input/resource.yaml +28 -0
  357. package/library/skills/web-compatibility-look/SKILL.md +62 -0
  358. package/library/skills/web-compatibility-look/resource.yaml +30 -0
  359. package/library/skills/world-building-3d/SKILL.md +8 -1
  360. package/library/skills/world-building-3d/references/spatial-tools.md +1 -1
  361. package/library/skills/world-building-3d/resource.yaml +2 -1
  362. package/library/skills/writing-plans/SKILL.md +1 -1
  363. package/library/skills/writing-skills/SKILL.md +1 -1
  364. package/library/templates/3d-lan-multiplayer-starter/resource.yaml +2 -2
  365. package/library/tools/attach-to-surface/resource.yaml +142 -0
  366. package/library/tools/batch/resource.yaml +9 -3
  367. package/library/tools/connect-ports/resource.yaml +120 -0
  368. package/library/tools/connect-signal/resource.yaml +3 -2
  369. package/library/tools/debug-views/resource.yaml +94 -0
  370. package/library/tools/frame-nodes/resource.yaml +104 -0
  371. package/library/tools/frame-shot/resource.yaml +134 -0
  372. package/library/tools/generate-motion/resource.yaml +44 -9
  373. package/library/tools/get-board/resource.yaml +50 -0
  374. package/library/tools/get-project-context/resource.yaml +13 -2
  375. package/library/tools/grep/resource.yaml +77 -0
  376. package/library/tools/inspect-asset/resource.yaml +71 -0
  377. package/library/tools/inspect-node/resource.yaml +9 -2
  378. package/library/tools/inspect-resource/resource.yaml +16 -5
  379. package/library/tools/instantiate-scene/resource.yaml +27 -2
  380. package/library/tools/measure/resource.yaml +96 -0
  381. package/library/tools/place-adjacent/resource.yaml +113 -0
  382. package/library/tools/play/resource.yaml +15 -2
  383. package/library/tools/raycast/resource.yaml +101 -0
  384. package/library/tools/read-file/resource.yaml +36 -2
  385. package/library/tools/read-library/resource.yaml +2 -2
  386. package/library/tools/repeat-along/resource.yaml +129 -0
  387. package/library/tools/replace-node/resource.yaml +11 -5
  388. package/library/tools/scene-audit/resource.yaml +144 -0
  389. package/library/tools/screenshot/resource.yaml +13 -2
  390. package/library/tools/search-assets/resource.yaml +18 -0
  391. package/library/tools/shot-sheet/resource.yaml +110 -0
  392. package/library/tools/snap-to-surface/resource.yaml +4 -1
  393. package/library/tools/world-snapshot/resource.yaml +24 -3
  394. package/library/tools/zoom/resource.yaml +105 -0
  395. package/package.json +3 -3
  396. package/registry/generated/aliases.json +17 -3
  397. package/registry/generated/counts.json +3 -3
  398. package/registry/generated/gemini-extension.json +26 -4
  399. package/registry/generated/index.json +2154 -469
  400. package/registry/generated/marketplace.claude.json +2 -2
  401. package/registry/generated/plugin.claude.json +27 -5
  402. package/registry/generated/plugin.codex.json +28 -6
  403. package/registry/generated/plugin.cursor.json +27 -5
  404. package/registry/generated/plugin.factory.json +27 -5
  405. package/registry/generated/skills-index.md +264 -0
  406. package/registry/generated/skills-registry.json +901 -206
  407. package/registry/generated/templates-registry.json +2 -2
  408. package/library/skills/host-authoritative-state/SKILL.md +0 -332
  409. package/library/skills/host-authoritative-state/resource.yaml +0 -28
  410. package/library/skills/peer-to-peer-multiplayer/SKILL.md +0 -373
  411. package/library/skills/peer-to-peer-multiplayer/resource.yaml +0 -28
  412. package/library/skills/setup-multiplayer/SKILL.md +0 -336
  413. package/library/skills/setup-multiplayer/resource.yaml +0 -28
@@ -3,9 +3,12 @@
3
3
  *
4
4
  * Lives in the installer layer (not cli/) so `summer setup` can report the
5
5
  * destination and count without importing the CLI (import-direction contract
6
- * §2: shared layers never import cli or mcp).
6
+ * §2: shared layers never import cli or mcp). The per-agent paths come from
7
+ * the one agent table (agent-table.ts); only the `summer` pseudo-client is
8
+ * resolved here.
7
9
  */
8
10
  import { type AgentClient } from "../core/skills-registry.js";
11
+ import { type SkillLocationKind } from "./agent-table.js";
9
12
  export declare const SKILL_SCOPES: readonly ["user", "project"];
10
13
  export type SkillScope = (typeof SKILL_SCOPES)[number];
11
14
  /** The agent/scope flags `summer skills install` accepts (legacy aliases included). */
@@ -22,24 +25,12 @@ export declare function parseSkillScope(value: string): SkillScope;
22
25
  /** Pick the agent from --agent / legacy --as-claude-skill / --as-cursor-skill
23
26
  * (default "summer"); throws on conflicting flags. */
24
27
  export declare function resolveSkillAgent(opts: SkillInstallSelection): AgentClient;
25
- /** Explicit --scope wins; otherwise project-rooted agents default to "project". */
28
+ /** Explicit --scope wins; otherwise the agent's default (rule-file agents default to "project"). */
26
29
  export declare function resolveSkillScope(agent: AgentClient, opts: SkillInstallSelection): SkillScope;
27
- export type InstallLocation = {
28
- kind: "skill-dir";
30
+ export interface InstallLocation {
31
+ kind: SkillLocationKind;
29
32
  path: string;
30
- } | {
31
- kind: "cursor-rule-dir";
32
- path: string;
33
- } | {
34
- kind: "windsurf-rule-file";
35
- path: string;
36
- } | {
37
- kind: "cline-rule-dir";
38
- path: string;
39
- } | {
40
- kind: "opencode-skill-dir";
41
- path: string;
42
- };
33
+ }
43
34
  export declare function resolveInstallLocation(agent: AgentClient, scope: SkillScope): InstallLocation;
44
35
  /** One-line, human path pattern for where an install location puts skills. */
45
36
  export declare function describeInstallLocation(location: InstallLocation): string;
@@ -3,12 +3,15 @@
3
3
  *
4
4
  * Lives in the installer layer (not cli/) so `summer setup` can report the
5
5
  * destination and count without importing the CLI (import-direction contract
6
- * §2: shared layers never import cli or mcp).
6
+ * §2: shared layers never import cli or mcp). The per-agent paths come from
7
+ * the one agent table (agent-table.ts); only the `summer` pseudo-client is
8
+ * resolved here.
7
9
  */
8
10
  import { join } from "path";
9
- import { homedir, platform } from "os";
11
+ import { homedir } from "os";
10
12
  import { AGENT_CLIENTS } from "../core/skills-registry.js";
11
13
  import { tildeify } from "../core/format.js";
14
+ import { agentSpec, defaultPathContext, resolveSkillPath, } from "./agent-table.js";
12
15
  export const SKILL_SCOPES = ["user", "project"];
13
16
  function isAgentClient(value) {
14
17
  return AGENT_CLIENTS.includes(value);
@@ -44,114 +47,32 @@ export function resolveSkillAgent(opts) {
44
47
  }
45
48
  return parseSkillAgent(opts.agent ?? legacyAgent ?? "summer");
46
49
  }
47
- /** Explicit --scope wins; otherwise project-rooted agents default to "project". */
50
+ /** Explicit --scope wins; otherwise the agent's default (rule-file agents default to "project"). */
48
51
  export function resolveSkillScope(agent, opts) {
49
52
  if (opts.scope)
50
53
  return parseSkillScope(opts.scope);
51
- if (agent === "cursor" ||
52
- agent === "windsurf" ||
53
- agent === "cline" ||
54
- agent === "roo-code" ||
55
- agent === "kilo-code") {
56
- return "project";
57
- }
58
- return "user";
54
+ if (agent === "summer")
55
+ return "user";
56
+ return agentSpec(agent).skills?.defaultScope ?? "user";
59
57
  }
60
58
  export function resolveInstallLocation(agent, scope) {
61
59
  const overrideDir = process.env.SUMMER_SKILLS_DIR;
62
- if (overrideDir) {
63
- if (agent === "cursor")
64
- return { kind: "cursor-rule-dir", path: overrideDir };
65
- if (agent === "windsurf") {
66
- return { kind: "windsurf-rule-file", path: join(overrideDir, ".windsurfrules") };
67
- }
68
- if (agent === "cline" || agent === "roo-code" || agent === "kilo-code") {
69
- return { kind: "cline-rule-dir", path: overrideDir };
70
- }
71
- if (agent === "gemini") {
72
- return { kind: "skill-dir", path: overrideDir };
73
- }
74
- if (agent === "opencode") {
75
- return { kind: "opencode-skill-dir", path: overrideDir };
76
- }
77
- return { kind: "skill-dir", path: overrideDir };
60
+ if (agent === "summer") {
61
+ const root = scope === "user" ? homedir() : process.cwd();
62
+ return { kind: "skill-dir", path: overrideDir ?? join(root, ".summer", "skills") };
78
63
  }
79
- const root = scope === "user" ? homedir() : process.cwd();
80
- switch (agent) {
81
- case "codex":
82
- return { kind: "skill-dir", path: join(root, ".agents", "skills") };
83
- case "claude-code":
84
- return { kind: "skill-dir", path: join(root, ".claude", "skills") };
85
- case "cursor":
86
- return { kind: "cursor-rule-dir", path: join(root, ".cursor", "rules") };
87
- case "windsurf":
88
- return { kind: "windsurf-rule-file", path: join(root, ".windsurfrules") };
89
- case "cline":
90
- return {
91
- kind: "cline-rule-dir",
92
- path: scope === "user"
93
- ? clineUserRulesDir()
94
- : join(process.cwd(), ".clinerules"),
95
- };
96
- case "roo-code":
97
- return {
98
- kind: "cline-rule-dir",
99
- path: scope === "user"
100
- ? rooCodeUserRulesDir()
101
- : join(process.cwd(), ".clinerules"),
102
- };
103
- case "kilo-code":
104
- return {
105
- kind: "cline-rule-dir",
106
- path: scope === "user"
107
- ? join(homedir(), ".kilocode", "rules")
108
- : join(process.cwd(), ".kilocode", "rules"),
109
- };
110
- case "gemini":
111
- // Gemini discovers extension skills from <extension>/skills/<name>/SKILL.md
112
- // (geminicli.com/docs/extensions/reference), so copy the skill directories
113
- // as-is. The extension dir itself is written by `summer setup gemini`.
114
- return {
115
- kind: "skill-dir",
116
- path: join(homedir(), ".gemini", "extensions", "summer-engine", "skills"),
117
- };
118
- case "github-copilot":
119
- case "vscode-copilot":
120
- return {
121
- kind: "skill-dir",
122
- path: scope === "user"
123
- ? join(homedir(), ".copilot", "skills")
124
- : join(process.cwd(), ".github", "skills"),
125
- };
126
- case "opencode":
127
- return {
128
- kind: "opencode-skill-dir",
129
- path: scope === "user"
130
- ? opencodeUserAgentsDir()
131
- : join(process.cwd(), ".opencode", "agents", "summer"),
132
- };
133
- case "summer":
134
- return { kind: "skill-dir", path: join(root, ".summer", "skills") };
64
+ const spec = agentSpec(agent);
65
+ const resolved = resolveSkillPath(spec, scope, defaultPathContext());
66
+ if (!resolved) {
67
+ throw new Error(`${spec.label} has no skills folder. ${spec.noSkillsNote ?? ""}`.trim());
135
68
  }
136
- }
137
- function clineUserRulesDir() {
138
- // Cline reads global rules from the user's Documents/Cline/Rules folder.
139
- return join(homedir(), "Documents", "Cline", "Rules");
140
- }
141
- function rooCodeUserRulesDir() {
142
- // Roo Code reads global rules from the user's Documents/Roo/Rules folder.
143
- return join(homedir(), "Documents", "Roo", "Rules");
144
- }
145
- function opencodeUserAgentsDir() {
146
- // OpenCode's user-scope agent definition directory varies by OS.
147
- // On Windows, OpenCode reads from %APPDATA%/opencode/agents/summer.
148
- // On Linux/macOS, it reads from $XDG_CONFIG_HOME or ~/.config/opencode/agents/summer.
149
- if (platform() === "win32") {
150
- const appData = process.env.APPDATA ?? join(homedir(), "AppData", "Roaming");
151
- return join(appData, "opencode", "agents", "summer");
69
+ if (overrideDir) {
70
+ return {
71
+ kind: resolved.kind,
72
+ path: resolved.kind === "windsurf-rule-file" ? join(overrideDir, ".windsurfrules") : overrideDir,
73
+ };
152
74
  }
153
- const xdg = process.env.XDG_CONFIG_HOME ?? join(homedir(), ".config");
154
- return join(xdg, "opencode", "agents", "summer");
75
+ return { kind: resolved.kind, path: resolved.path };
155
76
  }
156
77
  /** One-line, human path pattern for where an install location puts skills. */
157
78
  export function describeInstallLocation(location) {
@@ -11,6 +11,7 @@
11
11
  * Both are designed to be silent on offline / network errors — we never want
12
12
  * to false-alarm a user just because their wifi is flaky.
13
13
  */
14
+ import { type McpFormat } from "./agent-table.js";
14
15
  import { type StdioMcpServerConfig } from "./agent-config.js";
15
16
  export interface SemverParts {
16
17
  major: number;
@@ -145,10 +146,13 @@ export declare function isLocalDevServerConfig(server: StdioMcpServerConfig): bo
145
146
  * json-copilot {"mcpServers": {"summer-engine": {type, command, args}}}
146
147
  * json-vscode {"servers": {"summer-engine": {type, command, args}}}
147
148
  * json-opencode {"mcp": {"summer-engine": {type, command: [cmd, ...args]}}}
149
+ * json-zed {"context_servers": {"summer-engine": {source, command, args}}}
150
+ * yaml-goose extensions: summer-engine: {cmd, args}
151
+ * yaml-hermes mcp_servers: summer-engine: {command, args}
148
152
  * toml (codex) [mcp_servers.summer-engine]\ncommand = "…"\nargs = ["…", …]
149
153
  * Returns null when the file is missing, unparsable, or has no Summer entry.
150
154
  */
151
- export declare function readRecordedMcpServer(text: string, format: "json" | "toml" | "json-opencode" | "json-copilot" | "json-vscode"): StdioMcpServerConfig | null;
155
+ export declare function readRecordedMcpServer(text: string, format: McpFormat): StdioMcpServerConfig | null;
152
156
  /** Is the CLI running this check a source checkout rather than an installed
153
157
  * package? npm/npx/global installs all live under a node_modules directory. */
154
158
  export declare function runningCliIsCheckout(packageRoot?: string): boolean;
@@ -12,10 +12,11 @@
12
12
  * to false-alarm a user just because their wifi is flaky.
13
13
  */
14
14
  import { existsSync, readFileSync, writeFileSync } from "node:fs";
15
- import { homedir, platform } from "node:os";
15
+ import { parse as parseYaml } from "yaml";
16
+ import { allAgentSpecs, defaultPathContext, resolveSkillPath } from "./agent-table.js";
16
17
  import { join, sep } from "node:path";
17
18
  import { PACKAGE_ROOT } from "../core/package-root.js";
18
- import { configureAgentMcp, parseAgent, SUMMER_MCP_SERVER_NAME, } from "./agent-config.js";
19
+ import { configureAgentMcp, parseAgent, SUMMER_MCP_SERVER_NAME, topLevelKey, } from "./agent-config.js";
19
20
  const NPM_REGISTRY_LATEST_URL = "https://registry.npmjs.org/summer-engine/latest";
20
21
  const REGISTRY_FETCH_TIMEOUT_MS = 3000;
21
22
  export function parseSemver(version) {
@@ -197,32 +198,17 @@ export function writeSkillMarker(dir, version, now = new Date()) {
197
198
  return path;
198
199
  }
199
200
  export function defaultSkillMarkerCandidates() {
200
- const home = homedir();
201
+ const ctx = defaultPathContext();
201
202
  const candidates = [
202
- { agent: "claude-code", dir: join(home, ".claude", "skills") },
203
- { agent: "codex", dir: join(home, ".agents", "skills") },
204
- { agent: "summer", dir: join(home, ".summer", "skills") },
205
- { agent: "cline", dir: join(home, "Documents", "Cline", "Rules") },
206
- { agent: "roo-code", dir: join(home, "Documents", "Roo", "Rules") },
207
- {
208
- agent: "gemini",
209
- dir: join(home, ".gemini", "extensions", "summer-engine", "skills"),
210
- },
203
+ { agent: "summer", dir: join(ctx.home, ".summer", "skills") },
211
204
  ];
212
- // OpenCode user-scope agent dir is OS-dependent.
213
- if (platform() === "win32") {
214
- const appData = process.env.APPDATA ?? join(home, "AppData", "Roaming");
215
- candidates.push({
216
- agent: "opencode",
217
- dir: join(appData, "opencode", "agents", "summer"),
218
- });
219
- }
220
- else {
221
- const xdg = process.env.XDG_CONFIG_HOME ?? join(home, ".config");
222
- candidates.push({
223
- agent: "opencode",
224
- dir: join(xdg, "opencode", "agents", "summer"),
225
- });
205
+ // Every agent with a user-scope skills home, from the one agent table.
206
+ // Devin Desktop's single rules file has no dir to mark; skip that kind.
207
+ for (const spec of allAgentSpecs()) {
208
+ const home = resolveSkillPath(spec, "user", ctx);
209
+ if (!home || home.kind === "windsurf-rule-file")
210
+ continue;
211
+ candidates.push({ agent: spec.id, dir: home.path });
226
212
  }
227
213
  return candidates;
228
214
  }
@@ -362,12 +348,29 @@ export function isLocalDevServerConfig(server) {
362
348
  * json-copilot {"mcpServers": {"summer-engine": {type, command, args}}}
363
349
  * json-vscode {"servers": {"summer-engine": {type, command, args}}}
364
350
  * json-opencode {"mcp": {"summer-engine": {type, command: [cmd, ...args]}}}
351
+ * json-zed {"context_servers": {"summer-engine": {source, command, args}}}
352
+ * yaml-goose extensions: summer-engine: {cmd, args}
353
+ * yaml-hermes mcp_servers: summer-engine: {command, args}
365
354
  * toml (codex) [mcp_servers.summer-engine]\ncommand = "…"\nargs = ["…", …]
366
355
  * Returns null when the file is missing, unparsable, or has no Summer entry.
367
356
  */
368
357
  export function readRecordedMcpServer(text, format) {
369
358
  if (!text.trim())
370
359
  return null;
360
+ if (format === "toml-array") {
361
+ const block = text.match(new RegExp(`^\\[\\[mcp_servers\\]\\]\\s*$([\\s\\S]*?)(?=^\\[|(?![\\s\\S]))`, "gm"));
362
+ for (const candidate of block ?? []) {
363
+ if (!new RegExp(`^name\\s*=\\s*"${SUMMER_MCP_SERVER_NAME}"`, "m").test(candidate))
364
+ continue;
365
+ const command = candidate.match(/^command\s*=\s*"((?:[^"\\]|\\.)*)"/m)?.[1];
366
+ const argsText = candidate.match(/^args\s*=\s*\[([^\]]*)\]/m)?.[1] ?? "";
367
+ if (!command)
368
+ return null;
369
+ const args = [...argsText.matchAll(/"((?:[^"\\]|\\.)*)"/g)].map((m) => m[1].replace(/\\(.)/g, "$1"));
370
+ return { command: command.replace(/\\(.)/g, "$1"), args };
371
+ }
372
+ return null;
373
+ }
371
374
  if (format === "toml") {
372
375
  const table = text.match(new RegExp(`^\\[mcp_servers\\.${SUMMER_MCP_SERVER_NAME.replace(/[-.]/g, "\\$&")}\\]\\s*$([\\s\\S]*?)(?=^\\[|(?![\\s\\S]))`, "m"));
373
376
  if (!table)
@@ -381,7 +384,7 @@ export function readRecordedMcpServer(text, format) {
381
384
  }
382
385
  let parsed;
383
386
  try {
384
- parsed = JSON.parse(text);
387
+ parsed = format === "yaml-goose" || format === "yaml-hermes" ? parseYaml(text) : JSON.parse(text);
385
388
  }
386
389
  catch {
387
390
  return null;
@@ -389,7 +392,9 @@ export function readRecordedMcpServer(text, format) {
389
392
  if (!parsed || typeof parsed !== "object")
390
393
  return null;
391
394
  const root = parsed;
392
- for (const container of ["mcpServers", "servers", "mcp"]) {
395
+ // The format's own key first, then the other shapes (a user may have moved to a newer file layout).
396
+ const containers = [topLevelKey(format), "mcpServers", "servers", "mcp", "context_servers", "extensions", "mcp_servers", "amp.mcpServers"];
397
+ for (const container of [...new Set(containers)]) {
393
398
  const servers = root[container];
394
399
  if (!servers || typeof servers !== "object")
395
400
  continue;
@@ -397,6 +402,11 @@ export function readRecordedMcpServer(text, format) {
397
402
  if (!entry || typeof entry !== "object")
398
403
  continue;
399
404
  const record = entry;
405
+ if (typeof record.cmd === "string") {
406
+ // Goose: { cmd, args }
407
+ const args = Array.isArray(record.args) ? record.args.filter((part) => typeof part === "string") : [];
408
+ return { command: record.cmd, args };
409
+ }
400
410
  if (Array.isArray(record.command)) {
401
411
  const [command, ...args] = record.command.filter((part) => typeof part === "string");
402
412
  return command ? { command, args } : null;
@@ -4,10 +4,13 @@ import { EngineApiClient } from "../core/api-client.js";
4
4
  import { registerSceneTools } from "./tools/scene-tools.js";
5
5
  import { registerDebugTools } from "./tools/debug-tools.js";
6
6
  import { registerVisualTools } from "./tools/visual-tools.js";
7
+ import { registerSeeingTools } from "./tools/seeing-tools.js";
8
+ import { registerAuditTools } from "./tools/audit-tools.js";
7
9
  import { WITH_ENGINE_META } from "./tools/with-engine.js";
8
10
  import { registerPlaybookPrompt, registerProjectTools, } from "./tools/project-tools.js";
9
11
  import { registerPerceptionTools } from "./tools/perception-tools.js";
10
12
  import { registerSpatialTools } from "./tools/spatial-tools.js";
13
+ import { registerPlacementTools } from "./tools/placement-tools.js";
11
14
  import { registerScriptTools } from "./tools/script-tools.js";
12
15
  import { registerEventTools } from "./tools/event-tools.js";
13
16
  import { registerFabricateTools } from "./tools/fabricate-tools.js";
@@ -36,10 +39,10 @@ export const getCachedBootDriftNotice = getCachedNotice;
36
39
  * it costs a few hundred tokens once; the full operating guide stays in the
37
40
  * summer_agent_playbook prompt / summer_get_agent_playbook tool.
38
41
  */
39
- export const SUMMER_MCP_INSTRUCTIONS = "Summer Engine MCP. Call summer_get_project_context first: it binds this session to the open project and returns mainScene, projectMemory (GameSoul, template pin) and any capabilitySkewWarning. " +
40
- "Before building or fixing, summer_search_library then summer_read_library the hit — skills, examples and templates live there. " +
42
+ export const SUMMER_MCP_INSTRUCTIONS = "Summer Engine MCP. Call summer_get_project_context first: it binds this session to the open project and returns mainScene, projectMemory (GameSoul, template pin) and any capabilitySkewWarning, compactly. " +
43
+ "Before building or fixing, summer_search_library then summer_read_library the hit: skills, examples, templates live there. " +
41
44
  "After a playthrough read summer_get_diagnostics, not summer_get_console alone (runtime errors live in the debugger). " +
42
- "A uniformly black screenshot means the viewport had not redrawn — recapture before concluding. " +
45
+ "An all-black screenshot means the viewport had not redrawn — recapture before concluding. " +
43
46
  "Report entries you verified in-engine via summer_library_feedback.";
44
47
  /**
45
48
  * Fire-and-forget probe of the npm registry on MCP boot. Caches the result for
@@ -302,6 +305,8 @@ export function createMcpServer() {
302
305
  registerSceneTools(server);
303
306
  registerDebugTools(server);
304
307
  registerVisualTools(server);
308
+ registerSeeingTools(server);
309
+ registerAuditTools(server);
305
310
  registerProjectTools(server);
306
311
  registerFileTools(server);
307
312
  registerAssetTools(server);
@@ -311,6 +316,7 @@ export function createMcpServer() {
311
316
  registerScriptTools(server);
312
317
  registerPerceptionTools(server);
313
318
  registerSpatialTools(server);
319
+ registerPlacementTools(server);
314
320
  registerNavigationTools(server);
315
321
  registerLibraryTools(server);
316
322
  registerEventTools(server);
@@ -23,6 +23,12 @@ async function searchAssetsApi(params) {
23
23
  if (params.source) {
24
24
  searchParams.set("source", params.source);
25
25
  }
26
+ if (params.style)
27
+ searchParams.set("style", params.style);
28
+ if (params.includeCommunity)
29
+ searchParams.set("includeCommunity", "true");
30
+ if (params.preview)
31
+ searchParams.set("contactSheet", "true");
26
32
  const gatewayUrl = await resolveGatewayUrl();
27
33
  const res = await fetch(`${gatewayUrl}/api/mcp/assets?${searchParams}`, {
28
34
  headers: { Authorization: `Bearer ${token}` },
@@ -120,7 +126,10 @@ Sources:
120
126
  - "all" — Search both library and your assets.
121
127
 
122
128
  Uses hybrid search: keywords + semantic similarity. Finds assets by name AND by meaning.
123
- Returns asset names, types, preview URLs, and import-ready file URLs.
129
+ Returns asset names, types, each asset's art style, preview URLs, and import-ready file URLs.
130
+ Keep a game in ONE art direction: pass style (the game's chosen family) so clashing styles are
131
+ left out, and set preview to see the first results as one numbered picture before importing.
132
+ Curated, open-source and Summer packs come first; people's own public generations only with includeCommunity.
124
133
 
125
134
  Cloud tool — works WITHOUT the Summer Engine app open.
126
135
  Requires authentication (so we can attribute usage and apply per-user rate limits): run 'npx -y summer-engine@latest login' first.`, {
@@ -128,8 +137,14 @@ Requires authentication (so we can attribute usage and apply per-user rate limit
128
137
  assetType: z.enum(["2d_image", "animation", "3d_model", "audio", "music", "all"]).default("all").describe("Filter by asset type"),
129
138
  limit: z.number().default(10).describe("Max results (1-20)"),
130
139
  source: z.enum(["library", "my_assets", "all"]).default("library").describe("Where to search: library (public 25k+), my_assets (your generated assets), all"),
131
- }, async ({ query, assetType, limit, source }) => {
132
- const result = await searchAssetsApi({ query, assetType, limit: Math.min(limit, 20), source });
140
+ style: z
141
+ .enum(["realistic", "stylized-lowpoly", "toon", "pixel", "hand-painted", "voxel"])
142
+ .optional()
143
+ .describe("The game's one art direction: clashing styles are left out, matches come first"),
144
+ preview: z.boolean().default(false).describe("Also return one picture of the first 9 results, numbered in order, to see them before importing"),
145
+ includeCommunity: z.boolean().default(false).describe("Also include people's own public AI generations"),
146
+ }, async ({ query, assetType, limit, source, style, preview, includeCommunity }) => {
147
+ const result = await searchAssetsApi({ query, assetType, limit: Math.min(limit, 20), source, style, preview, includeCommunity });
133
148
  if (result.error) {
134
149
  return {
135
150
  content: [
@@ -141,6 +156,7 @@ Requires authentication (so we can attribute usage and apply per-user rate limit
141
156
  isError: true,
142
157
  };
143
158
  }
159
+ const sheet = result.contactSheet?.match(/^data:(image\/[a-z]+);base64,(.+)$/);
144
160
  return {
145
161
  content: [
146
162
  {
@@ -150,8 +166,10 @@ Requires authentication (so we can attribute usage and apply per-user rate limit
150
166
  count: result.count,
151
167
  summary: result.summary,
152
168
  message: result.message,
169
+ ...(sheet ? { preview: "attached: the first results, numbered in this order" } : {}),
153
170
  }, null, 2),
154
171
  },
172
+ ...(sheet ? [{ type: "image", data: sheet[2], mimeType: sheet[1] }] : []),
155
173
  ],
156
174
  };
157
175
  });
@@ -0,0 +1,23 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { type AuditResult } from "../../core/capabilities/audit/audit.js";
3
+ /**
4
+ * summer_scene_audit: one read-only call that walks every node of a 3D scene
5
+ * and lists likely visual and placement problems, so a build agent knows
6
+ * exactly where to look. Implementation and the in-engine kernel:
7
+ * src/core/capabilities/audit/ and assets/audit/scene_audit.gd.
8
+ */
9
+ type ToolResultContent = {
10
+ type: "text";
11
+ text: string;
12
+ } | {
13
+ type: "image";
14
+ data: string;
15
+ mimeType: string;
16
+ };
17
+ type ToolResult = {
18
+ content: ToolResultContent[];
19
+ isError?: boolean;
20
+ };
21
+ export declare function auditContent(result: AuditResult): ToolResult;
22
+ export declare function registerAuditTools(server: McpServer): void;
23
+ export {};
@@ -0,0 +1,60 @@
1
+ import { withEngine } from "./with-engine.js";
2
+ import { sceneAudit } from "../../core/capabilities/audit/audit.js";
3
+ import { sceneAuditShape } from "../../core/capabilities/audit/args.js";
4
+ export function auditContent(result) {
5
+ if (!result.ok) {
6
+ return {
7
+ isError: true,
8
+ content: [
9
+ {
10
+ type: "text",
11
+ text: JSON.stringify({
12
+ ok: false,
13
+ tool: "summer_scene_audit",
14
+ failure_reason: result.failure_reason,
15
+ error: result.error,
16
+ ...(result.hint ? { hint: result.hint } : {}),
17
+ ...(result.detail ? { detail: result.detail } : {}),
18
+ }),
19
+ },
20
+ ],
21
+ };
22
+ }
23
+ const content = [];
24
+ if (result.image)
25
+ content.push({ type: "image", data: result.image.base64, mimeType: result.image.mime || "image/jpeg" });
26
+ content.push({ type: "text", text: JSON.stringify(result.summary) });
27
+ return { content };
28
+ }
29
+ export function registerAuditTools(server) {
30
+ server.tool("summer_scene_audit", `Audit a 3D scene in one fast, read-only call: every node and subnode is walked and likely visual and placement problems come back as a short list, sorted by severity, so you know exactly where to look. Each issue is a flag to LOOK at, never an auto-fix.
31
+
32
+ Checks (each can be picked with checks):
33
+ - through_hole: capped ray grids through every facade line (coplanar wall fronts); clusters of rays that pass the wall AND reach the far side of the building (a door insert narrower than its frame, a missing module, a seam). Walls, structure and inserts close an opening; props do not.
34
+ - exposed_edge: open outline edges of walls and facade members (bands, piers, corner blocks; cached per mesh) that nothing covers within 4-7 mm, seen from walkable space (eye points over open-sky floor cells, flood-filled from the scene's cameras and characters, sight lines not through a building), with a 2-60 cm reveal behind them, or a coplanar sheet continuing within 4 cm (seam) or 35 cm (gap). Warn on band pieces and when depth_step agrees, look otherwise; repeats group per piece type.
35
+ - open_fixture_end: open ends of run pieces (a mesh with two or more open rims of one size: pipe, duct or gutter sections, elbows, tees) that nothing joins within 2.5 cm (sleeve tolerance), seen from walkable space: a missing elbow, coupler, section or end piece (warn). A piece with one rim or rims of different sizes (a cap, a funnel, an outlet) is open by design.
36
+ - depth_step (look): ray rows across each visible facade side at its band levels and every 1.25 m: band recesses and missing runs, seams, modules standing proud, holes with something behind them; a hole next to a through_hole confirms it (warn -> error); runs a door-like opening covers are skipped.
37
+ - floor_gap: down rays over the floor tiles, along their seams, and from each tile edge to a wall within 1 m (bare strips at wall bases), classified by the FIRST surface hit: the void (error); an underlay over the floor's own lower surface such as a drain channel ("covers the floor", warn, not a hole); an underlay through a hole or strip. Areas are the missed rays' own footprints with the strip's size; a tile whose own mesh has holes is one issue for the piece.
38
+ - floating / sunken: support under each prop's footprint; gap over 2 cm, embed over 3 cm, measured against the first surface from above (the tile it is buried in, not the underlay under it); structure and pieces touching a wall well off the ground excluded.
39
+ - interpenetration: each prop's convex hulls against props, walls, structure and inserts; a deepest overlap over 3 cm, then every partner it cuts (up to 3).
40
+ - orientation (look): long props within 1.2 m of a wall more than 15 deg off parallel. It never says which way a piece should face.
41
+ - uv_stretch: per mesh resource, large triangles whose UV-to-world mapping is stretched over 8:1 or collapsed to a line, where an instance shows them (a reveal that inserts normally cover = warn).
42
+ - duplicate: the same scene at the same transform.
43
+ - z_fight: coplanar overlapping faces anywhere, from each mesh's planar face groups: between any two pieces (props, roofs, ledges, side walls, inserts against hosts, decals; opposite-facing only when both are double-sided) and between two surfaces of one mesh (once per mesh), plus the ray samples. Coplanar = a gap under twice the 24-bit depth step at the view distance (the nearest walkable eye point, camera or bookmark; 30 m without one) for the main camera's near/far; ev carries the overlap, gap, tolerance, surfaces, the plane's normal and the axis to nudge (nudge.world, nudge.local: a window can share its head or a jamb with its host, not its front). Warn over 0.05 m2 seen from a viewpoint; the material decides what is demoted to look, with the reason: render_priority, depth or normal offsets, a see-through (alpha) material, no depth test or depth writes.
44
+ - lights: meshes paired with more than the per-object limit of omni or spot lights (Compatibility: 8 each; light cuts off at seams), spot lights with spot_angle_attenuation under 3; shadowed light counts.
45
+ - transform: NaN, negative or non-uniform scale, a piece far out of bounds, and pieces left at the origin: an identity LOCAL transform under an identity parent, touching nothing and not one of a row of siblings (several sharing it warn, one alone is look; a module whose corner is the world origin is placed).
46
+ - resource: missing dependency files, MeshInstance3D without a mesh, surfaces without a material.
47
+
48
+ budget_ms (default 3000) bounds the editor time: each check gets a weighted share of it, and a check past its share stops and is marked counts.<check>.partial (the share it covered), never clean. The three gap detectors (exposed_edge, open_fixture_end, depth_step) run last on the time the other checks leave (band pieces and band rows first); rerun them alone when partial.
49
+
50
+ accept:[{key, reason}] (keys from issues[].key) records look and warn items you judged fine in res://.summer/audit-accept.json (the only file the audit writes); later audits count them (counts.<check>.accepted) but hide them until their evidence changes materially (severity rises, or the measured size moves by over 25%: shown again with accept_stale). Errors cannot be accepted; show_accepted lists them.
51
+
52
+ Returns at most 5 KB of JSON: counts per check, time per check (editor ms), the scene size, and ONE page of issues {n, check, sev (error|warn|look), path, pos (world), why, ev (evidence numbers: sizes, distances, angles, the ray to reproduce), next (the tool to use next), key (for accept)}. Page with offset/limit (next_offset names the next page); filter with checks, root (a subtree) and min_severity. render:"sheet" adds ONE inline image of the page's first 6 issues framed up close from their open side (a camera never behind a wall), each tile labelled #n.
53
+
54
+ Every check works on any scene from geometry, the engine's node and resource data and materials alone: never node or file names, never kit metadata. Each piece's role comes from its shape: see-through cards (every material alpha) are dressing; thin upright sheets are walls (facing their side with more face area); flat slabs whose tops cover their footprint are floors (raised ones with walls under them are roofs, a large one below the rest is the underlay); a piece inside a wall's rectangle that reaches through the wall where it is open is an insert; bands, piers and corner blocks touching a facade wall are structure; the rest are props up to 3.5 m.
55
+
56
+ Read-only: it audits the SAVED file in a private offscreen copy (ScenePreview), so the open tab never becomes unsaved, undo is untouched and nothing is saved (accept writes only its own file). Save the scene first. Failures are structured (failure_reason), never a silent fallback.`, sceneAuditShape, async (args) => withEngine(async (client) => {
57
+ const audit = await sceneAudit(client, args);
58
+ return audit.ok ? { audit } : { audit, failure_reason: audit.failure_reason };
59
+ }, { onResult: (wrapped) => auditContent(wrapped.audit) }));
60
+ }
@@ -200,7 +200,9 @@ After starting, confirm boot with summer_is_running (boot time varies — never
200
200
 
201
201
  DETERMINISTIC RUNS (newer engines): seed / fixed_fps / time_scale pin THIS launch only (nothing is persisted). seed pins the game's GLOBAL RNG (randi/randf/randi_range/randf_range/randfn, Array.shuffle/pick_random) — it does NOT pin RandomNumberGenerator instances, scripts that call randomize(), rand_from_seed, wall-clock reads, or thread/IO/audio timing. fixed_fps decouples scene time from the wall clock so frame-count-derived state lands on the same frame run to run. The result's \`determinism\` block says whether the pins were applied (applied:false carries a reason: already_running, editor_run_args_override, launch_not_started) and restates seed_scope. If the result has NO determinism block although you sent a pin, the engine predates the params and the run is NOT reproducible — the tool says so; do not claim otherwise. Omitting every pin and instance parameter is exactly the v1 launch.
202
202
 
203
- PLAYTEST LAUNCH (engine runtime-control build): instance + mode:'offscreen' spawn a disposable hidden instance (at most 3) that summer_game_probe / summer_game_input / summer_game_control / summer_runtime_* address by name — run two variants side by side for an A/B. deterministic:true (offscreen only) launches with --fixed-fps 60 --summer-seed --audio-driver Dummy and is what lets summer_game_input action:'replay' accept a seed; speed sets the user time scale on session start. The instance result reports session_attached; poll summer_game_control action:'instances' until attached:true before addressing it. Then: probe -> act -> step/probe -> assert (the agent-playtesting skill). Failure reasons: too_many_instances, instance_exists, session_timeout (child never attached — check summer_get_console), unsupported_mode, main_scene_not_configured. A game already running answers playing:true with determinism.applied:false — summer_stop first to apply seed/fixed_fps.`, {
203
+ PLAYTEST LAUNCH (engine runtime-control build): instance + mode:'offscreen' spawn a disposable hidden instance (at most 3) that summer_game_probe / summer_game_input / summer_game_control / summer_runtime_* address by name — run two variants side by side for an A/B. deterministic:true (offscreen only) launches with --fixed-fps 60 --summer-seed --audio-driver Dummy and is what lets summer_game_input action:'replay' accept a seed; speed sets the user time scale on session start. The instance result reports session_attached; poll summer_game_control action:'instances' until attached:true before addressing it. Then: probe -> act -> step/probe -> assert (the agent-playtesting skill). Failure reasons: too_many_instances, instance_exists, session_timeout (child never attached — check summer_get_console), unsupported_mode, main_scene_not_configured. A game already running answers playing:true with determinism.applied:false — summer_stop first to apply seed/fixed_fps.
204
+
205
+ MULTIPLAYER — LOCAL PLAY (Summer multiplayer games; engine with Local Play): players:N starts the game's authority headless plus N clients on this machine, each joining through the game's OWN Summer.client.join(SummerJoinTarget.queue(...)) — no account, login, Docker, CLI or local-only game code. The scenes and queue come from the project's summer.build.json and its WorldDefinition (client_entry_point + the headless_engine component entry_point); queue picks another declared queue — pass queue WITHOUT players to start that queue's minPlayers (a 4-player queue starts 4), or players to choose; spectators adds spectator clients. local_play.warnings flags a roster outside the queue's minPlayers..maxPlayers. The result's local_play block lists every process (label, role, persona) and the port; failure_reason local_play_unavailable says exactly what to declare. Every process attaches to the editor debugger: screenshots, input and summer_game_* go to the FIRST client, the authority's output is in summer_get_console, and summer_stop stops them all. A join for a different queue fails with a message naming both queues. It is not a proof of sign-in, matchmaking or hosted admission (staging). No local_play block although you sent players means the engine predates Local Play and ran ONE client — the tool says so.`, {
204
206
  scene: z.string().optional().describe("Scene to run instead of main scene, e.g. 'res://levels/test_level.tscn'"),
205
207
  ...playGameExtensionSchema,
206
208
  }, async (args) => {
@@ -1,6 +1,8 @@
1
1
  import { z } from "zod";
2
2
  import { withEngine, ToolInputError } from "./with-engine.js";
3
3
  import { occurrenceCount, readTextPayload, safeProjectPath, validSha256, } from "../../core/capabilities/engine-ops.js";
4
+ import { readFileInputShape, readProjectFileWindow } from "../../core/capabilities/file-read.js";
5
+ import { GREP_DEFAULT_MAX_RESULTS, GREP_MAX_RESULTS, grepInputShape, grepProject, } from "../../core/capabilities/grep.js";
4
6
  // MCP clients may issue tool calls concurrently. Keep the complete read->write
5
7
  // transaction ordered for one project file while allowing unrelated files to
6
8
  // proceed in parallel. The tail is always released in `finally`, so a rejected
@@ -32,10 +34,21 @@ async function withFileMutationTurn(projectIdHash, path, fn) {
32
34
  export function registerFileTools(server) {
33
35
  server.tool("summer_read_file", `Read a text file from the engine-bound project and return its full-file sha256 receipt.
34
36
 
35
- Use the returned sha256 as expected_sha256 when overwriting an existing file. Paths must begin with res://.`, {
36
- path: z.string().describe("Project path, e.g. res://scripts/player.gd"),
37
- max_bytes: z.number().int().positive().max(1_000_000).default(200_000),
38
- }, async ({ path, max_bytes }) => withEngine(async (client) => client.readProjectFile(safeProjectPath(path), max_bytes)));
37
+ Use the returned sha256 as expected_sha256 when overwriting an existing file. Paths must begin with res://.
38
+
39
+ READ BIG FILES IN PARTS instead of all at once:
40
+ - offset + limit page the file: lines by default (unit:'bytes' for a byte range on UTF-8 boundaries). The result's data.window gives start_line/end_line, total_lines, next_offset (null at the end) and eof.
41
+ - For JSON: json_path picks one value ('pieces.wall_a', 'items[3]'); keys keeps matching object keys (['wall_*']); keys_only lists key names only. data.json says what matched. offset/limit then page the selection.
42
+ The sha256 always covers the WHOLE file, so a windowed read still guards a later overwrite. Files over 1 MB can be paged only within their first 1 MB.`, readFileInputShape, async (args) => withEngine(async (client) => readProjectFileWindow(client, args)));
43
+ server.tool("summer_grep", `Search project files with a regular expression (ripgrep, through the engine) and get file + line + text per match, optionally with context lines around each.
44
+
45
+ Use it to find things in big files without reading them whole: every '"fits_into"' in a kit manifest, the scenes of a kit (glob '*.tscn'), where a signal handler is defined. Then read exactly the part you need with summer_read_file (offset/limit, or json_path for JSON).
46
+
47
+ - path: a res:// directory or file (default: the whole project; .godot/ and .import/ are never searched).
48
+ - glob: ripgrep --glob filter ('*.gd', '**/*.json', '!addons/**'). Ripgrep skips files ignored by .gitignore unless a glob names them.
49
+ - context_lines (0-10): lines before/after each match, as before[] / after[].
50
+ - max_results (default ${GREP_DEFAULT_MAX_RESULTS}, max ${GREP_MAX_RESULTS}) caps the matches; truncated:true says there were more. Lines are clipped to max_line_chars.
51
+ Case-insensitive unless case_sensitive:true. Read-only.`, grepInputShape, async (args) => withEngine(async (client) => grepProject(client, args)));
39
52
  server.tool("summer_write_file", `Create or safely overwrite a complete text file through the identity-bound engine.
40
53
 
41
54
  For a new file, set create_only:true. For an existing file, first call summer_read_file and pass its sha256 as expected_sha256. Exactly one guard is required; unguarded writes fail closed. Supports scripts, .tscn scenes, .tres resources, JSON, docs, and project config.`, {