summer-engine 3.8.0 → 4.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 (527) hide show
  1. package/.claude-plugin/marketplace.json +2 -13
  2. package/.claude-plugin/plugin.json +24 -22
  3. package/.codex-plugin/plugin.json +18 -22
  4. package/.cursor-plugin/plugin.json +8 -14
  5. package/.factory-plugin/plugin.json +6 -13
  6. package/AGENTS.md +19 -12
  7. package/CHANGELOG.md +133 -0
  8. package/GEMINI.md +3 -3
  9. package/README.md +118 -37
  10. package/assets/icon.png +0 -0
  11. package/commands/start.md +71 -0
  12. package/commands/summer.md +3 -2
  13. package/dist/cli/banner.js +3 -0
  14. package/dist/cli/commands/config.js +3 -2
  15. package/dist/cli/commands/create.js +12 -3
  16. package/dist/cli/commands/list.d.ts +5 -0
  17. package/dist/cli/commands/list.js +30 -13
  18. package/dist/cli/commands/login.d.ts +27 -0
  19. package/dist/cli/commands/login.js +58 -12
  20. package/dist/cli/commands/memory.js +6 -2
  21. package/dist/cli/commands/ops.d.ts +64 -0
  22. package/dist/cli/commands/ops.js +329 -0
  23. package/dist/cli/commands/setup.d.ts +4 -0
  24. package/dist/cli/commands/setup.js +254 -26
  25. package/dist/cli/commands/skills.js +28 -11
  26. package/dist/cli/commands/status.d.ts +26 -0
  27. package/dist/cli/commands/status.js +36 -21
  28. package/dist/cli/index.js +7 -0
  29. package/dist/core/agent-host.d.ts +65 -0
  30. package/dist/core/agent-host.js +193 -0
  31. package/dist/core/capabilities/agent-playbook.d.ts +3 -0
  32. package/dist/core/capabilities/agent-playbook.js +54 -2
  33. package/dist/core/capabilities/apps.d.ts +33 -10
  34. package/dist/core/capabilities/apps.js +25 -12
  35. package/dist/core/capabilities/audit/args.d.ts +6 -6
  36. package/dist/core/capabilities/doctor.d.ts +3 -0
  37. package/dist/core/capabilities/doctor.js +20 -15
  38. package/dist/core/capabilities/fabricate-mesh.d.ts +4 -4
  39. package/dist/core/capabilities/game-task-plan.d.ts +12 -6
  40. package/dist/core/capabilities/game-task-plan.js +80 -5
  41. package/dist/core/capabilities/hdri-import.d.ts +2 -2
  42. package/dist/core/capabilities/motion-generation.d.ts +2 -2
  43. package/dist/core/capabilities/motion-generation.js +2 -2
  44. package/dist/core/capabilities/navigation/open.d.ts +6 -2
  45. package/dist/core/capabilities/navigation/open.js +3 -0
  46. package/dist/core/capabilities/placement.d.ts +23 -23
  47. package/dist/core/capabilities/publish-build.js +2 -0
  48. package/dist/core/capabilities/runtime-control.d.ts +42 -42
  49. package/dist/core/capabilities/scene-script-target.d.ts +17 -0
  50. package/dist/core/capabilities/scene-script-target.js +70 -0
  51. package/dist/core/capabilities/seeing/args.d.ts +16 -16
  52. package/dist/core/capabilities/sfx-choices.d.ts +4 -0
  53. package/dist/core/capabilities/sfx-choices.js +13 -6
  54. package/dist/core/capabilities/tool-dispatch.d.ts +12 -3
  55. package/dist/core/capabilities/tool-dispatch.js +81 -46
  56. package/dist/core/capabilities/ui-control.d.ts +2 -2
  57. package/dist/core/capabilities/world-snapshot.d.ts +4 -4
  58. package/dist/core/embeddings.d.ts +2 -0
  59. package/dist/core/embeddings.js +1 -1
  60. package/dist/core/error-codes.d.ts +62 -0
  61. package/dist/core/error-codes.js +97 -0
  62. package/dist/core/format.d.ts +2 -0
  63. package/dist/core/format.js +2 -1
  64. package/dist/core/hosted-mcp.d.ts +22 -0
  65. package/dist/core/hosted-mcp.js +56 -1
  66. package/dist/core/library-read.js +5 -0
  67. package/dist/core/library-search.d.ts +2 -2
  68. package/dist/core/library-search.js +2 -1
  69. package/dist/core/oauth.js +4 -0
  70. package/dist/core/ops/areas.d.ts +11 -0
  71. package/dist/core/ops/areas.js +24 -0
  72. package/dist/core/ops/catalog.d.ts +45 -0
  73. package/dist/core/ops/catalog.js +157 -0
  74. package/dist/core/ops/cloud.d.ts +64 -0
  75. package/dist/core/ops/cloud.js +198 -0
  76. package/dist/core/ops/contract.d.ts +120 -0
  77. package/dist/core/ops/contract.js +134 -0
  78. package/dist/core/ops/engine-answer.d.ts +25 -0
  79. package/dist/core/ops/engine-answer.js +117 -0
  80. package/dist/core/ops/engine.d.ts +55 -0
  81. package/dist/core/ops/engine.js +649 -0
  82. package/dist/core/ops/public-catalog.d.ts +48 -0
  83. package/dist/core/ops/public-catalog.js +56 -0
  84. package/dist/core/ops/save-files.d.ts +78 -0
  85. package/dist/core/ops/save-files.js +419 -0
  86. package/dist/core/ops/search.d.ts +8 -0
  87. package/dist/core/ops/search.js +187 -0
  88. package/dist/core/skills-registry.d.ts +16 -1
  89. package/dist/core/skills-registry.js +35 -2
  90. package/dist/core/telemetry.d.ts +32 -0
  91. package/dist/core/telemetry.js +38 -10
  92. package/dist/core/tool-profiles.d.ts +25 -0
  93. package/dist/core/tool-profiles.js +41 -0
  94. package/dist/installer/agent-config.d.ts +17 -4
  95. package/dist/installer/agent-config.js +27 -6
  96. package/dist/installer/agent-table.d.ts +12 -0
  97. package/dist/installer/agent-table.js +33 -9
  98. package/dist/installer/cli-permissions.d.ts +65 -0
  99. package/dist/installer/cli-permissions.js +182 -0
  100. package/dist/installer/setup.d.ts +4 -0
  101. package/dist/installer/setup.js +12 -4
  102. package/dist/installer/skills-refresh.d.ts +29 -0
  103. package/dist/installer/skills-refresh.js +261 -0
  104. package/dist/installer/version-check.d.ts +51 -11
  105. package/dist/installer/version-check.js +147 -37
  106. package/dist/mcp/command.js +7 -0
  107. package/dist/mcp/hosted-mount.d.ts +27 -2
  108. package/dist/mcp/hosted-mount.js +53 -23
  109. package/dist/mcp/legacy-toolset.d.ts +27 -0
  110. package/dist/mcp/legacy-toolset.js +43 -0
  111. package/dist/mcp/ops-surface.d.ts +59 -0
  112. package/dist/mcp/ops-surface.js +453 -0
  113. package/dist/mcp/server.d.ts +45 -11
  114. package/dist/mcp/server.js +263 -89
  115. package/dist/mcp/tool-results.d.ts +26 -0
  116. package/dist/mcp/tool-results.js +81 -0
  117. package/dist/mcp/tool-surface.d.ts +65 -0
  118. package/dist/mcp/tool-surface.js +317 -0
  119. package/dist/mcp/tools/app-tools.js +9 -2
  120. package/dist/mcp/tools/asset-tools.js +55 -53
  121. package/dist/mcp/tools/audit-tools.js +21 -21
  122. package/dist/mcp/tools/debug-tools.js +6 -6
  123. package/dist/mcp/tools/fabricate-tools.js +6 -6
  124. package/dist/mcp/tools/generate-tools.js +76 -70
  125. package/dist/mcp/tools/project-tools.d.ts +9 -4
  126. package/dist/mcp/tools/project-tools.js +16 -10
  127. package/dist/mcp/tools/scene-tools.js +12 -23
  128. package/dist/mcp/tools/script-tools.js +9 -5
  129. package/dist/mcp/tools/with-engine.d.ts +6 -0
  130. package/dist/mcp/tools/with-engine.js +19 -0
  131. package/dist/project-memory/agent-instructions.d.ts +47 -0
  132. package/dist/project-memory/agent-instructions.js +226 -0
  133. package/gemini-extension.json +6 -13
  134. package/hooks/pre-commit-doctor.sh +5 -4
  135. package/hooks/session-start.sh +24 -28
  136. package/integrations/README.md +1 -1
  137. package/integrations/claude/README.md +6 -0
  138. package/integrations/claude/manifest-target.json +4 -0
  139. package/integrations/claude-desktop/README.md +1 -1
  140. package/integrations/copilot-jetbrains/README.md +1 -1
  141. package/integrations/gemini/README.md +11 -0
  142. package/integrations/junie/README.md +1 -1
  143. package/integrations/lm-studio/README.md +1 -1
  144. package/integrations/trae/README.md +1 -1
  145. package/integrations/visual-studio/README.md +1 -1
  146. package/integrations/windsurf/README.md +1 -1
  147. package/library/references/mcp-tools-reference/mcp-tools-reference.md +79 -51
  148. package/library/references/mcp-tools-reference/resource.yaml +1 -1
  149. package/library/references/product-map/resource.yaml +2 -2
  150. package/library/skills/3d-lighting/SKILL.md +69 -28
  151. package/library/skills/3d-lighting/resource.yaml +1 -1
  152. package/library/skills/README.md +121 -118
  153. package/library/skills/adaptive-music/SKILL.md +40 -23
  154. package/library/skills/adaptive-music/resource.yaml +1 -1
  155. package/library/skills/agent-playtesting/SKILL.md +23 -1
  156. package/library/skills/agent-playtesting/resource.yaml +1 -1
  157. package/library/skills/ai-characters-in-games/SKILL.md +16 -1
  158. package/library/skills/ai-characters-in-games/resource.yaml +1 -1
  159. package/library/skills/ambient-bed/SKILL.md +38 -13
  160. package/library/skills/ambient-bed/resource.yaml +1 -1
  161. package/library/skills/animated-loop/SKILL.md +60 -32
  162. package/library/skills/animated-loop/resource.yaml +1 -1
  163. package/library/skills/animation-tree/SKILL.md +27 -1
  164. package/library/skills/animation-tree/resource.yaml +1 -1
  165. package/library/skills/art-direction/SKILL.md +17 -3
  166. package/library/skills/art-direction/resource.yaml +1 -1
  167. package/library/skills/asset-strategy/SKILL.md +51 -4
  168. package/library/skills/asset-strategy/resource.yaml +2 -1
  169. package/library/skills/audio-direction/SKILL.md +26 -10
  170. package/library/skills/audio-direction/resource.yaml +1 -1
  171. package/library/skills/auto-fire-targeting/SKILL.md +15 -1
  172. package/library/skills/auto-fire-targeting/resource.yaml +1 -1
  173. package/library/skills/bounded-engine-runs/SKILL.md +1 -1
  174. package/library/skills/bounded-engine-runs/resource.yaml +1 -1
  175. package/library/skills/brainstorm-game/SKILL.md +14 -1
  176. package/library/skills/brainstorm-game/resource.yaml +1 -1
  177. package/library/skills/brainstorming/SKILL.md +1 -1
  178. package/library/skills/brainstorming/resource.yaml +1 -1
  179. package/library/skills/browse-templates/SKILL.md +11 -1
  180. package/library/skills/browse-templates/resource.yaml +1 -1
  181. package/library/skills/camera-rigs/SKILL.md +22 -2
  182. package/library/skills/camera-rigs/resource.yaml +1 -1
  183. package/library/skills/celeste-momentum-platforming/resource.yaml +1 -0
  184. package/library/skills/character-animation-wiring/SKILL.md +28 -4
  185. package/library/skills/character-animation-wiring/resource.yaml +1 -1
  186. package/library/skills/character-model/SKILL.md +83 -47
  187. package/library/skills/character-model/resource.yaml +1 -1
  188. package/library/skills/character-movement/SKILL.md +27 -3
  189. package/library/skills/character-movement/resource.yaml +1 -1
  190. package/library/skills/character-portrait/SKILL.md +39 -19
  191. package/library/skills/character-portrait/resource.yaml +1 -1
  192. package/library/skills/cinematic-cutscene/SKILL.md +79 -46
  193. package/library/skills/cinematic-cutscene/resource.yaml +1 -1
  194. package/library/skills/combat-basics/SKILL.md +20 -1
  195. package/library/skills/combat-basics/resource.yaml +1 -1
  196. package/library/skills/compatibility-renderer-traps/SKILL.md +12 -1
  197. package/library/skills/compatibility-renderer-traps/resource.yaml +1 -1
  198. package/library/skills/concept-art/SKILL.md +29 -12
  199. package/library/skills/concept-art/resource.yaml +1 -1
  200. package/library/skills/concept-to-level/SKILL.md +258 -0
  201. package/library/skills/concept-to-level/references/technical-rules.md +150 -0
  202. package/library/skills/concept-to-level/resource.yaml +44 -0
  203. package/library/skills/create-asset-sheet/SKILL.md +37 -13
  204. package/library/skills/create-asset-sheet/resource.yaml +1 -1
  205. package/library/skills/debug/SKILL.md +34 -2
  206. package/library/skills/debug/resource.yaml +1 -1
  207. package/library/skills/debugging-game-feel/SKILL.md +13 -1
  208. package/library/skills/debugging-game-feel/resource.yaml +1 -1
  209. package/library/skills/design-level/SKILL.md +40 -35
  210. package/library/skills/design-level/resource.yaml +1 -1
  211. package/library/skills/design-mechanic/SKILL.md +18 -1
  212. package/library/skills/design-mechanic/resource.yaml +1 -1
  213. package/library/skills/design-npc/SKILL.md +43 -24
  214. package/library/skills/design-npc/resource.yaml +1 -1
  215. package/library/skills/diagnosing-perf-regressions/SKILL.md +13 -1
  216. package/library/skills/diagnosing-perf-regressions/resource.yaml +1 -1
  217. package/library/skills/driving-the-editor-ui/SKILL.md +24 -1
  218. package/library/skills/driving-the-editor-ui/resource.yaml +1 -1
  219. package/library/skills/environment-kit/SKILL.md +43 -16
  220. package/library/skills/environment-kit/resource.yaml +1 -1
  221. package/library/skills/export-and-ship/SKILL.md +29 -6
  222. package/library/skills/export-and-ship/resource.yaml +1 -1
  223. package/library/skills/fabricating-assets/SKILL.md +30 -7
  224. package/library/skills/fabricating-assets/resource.yaml +3 -3
  225. package/library/skills/facial-and-lipsync/SKILL.md +36 -15
  226. package/library/skills/facial-and-lipsync/resource.yaml +1 -1
  227. package/library/skills/fps-controller/SKILL.md +50 -41
  228. package/library/skills/fps-controller/resource.yaml +1 -1
  229. package/library/skills/game-feel/SKILL.md +34 -8
  230. package/library/skills/game-feel/resource.yaml +1 -1
  231. package/library/skills/gameskill/SKILL.md +15 -4
  232. package/library/skills/gameskill/resource.yaml +1 -1
  233. package/library/skills/gdscript-patterns/SKILL.md +16 -1
  234. package/library/skills/gdscript-patterns/resource.yaml +1 -1
  235. package/library/skills/generate-motion/SKILL.md +51 -21
  236. package/library/skills/generate-motion/resource.yaml +1 -1
  237. package/library/skills/godogen-visual-proof-game-generation/SKILL.md +18 -1
  238. package/library/skills/godogen-visual-proof-game-generation/resource.yaml +1 -0
  239. package/library/skills/grow-analytics/SKILL.md +13 -3
  240. package/library/skills/grow-analytics/resource.yaml +1 -1
  241. package/library/skills/headless-scripting/SKILL.md +14 -1
  242. package/library/skills/headless-scripting/resource.yaml +1 -1
  243. package/library/skills/in-game-purchases/SKILL.md +12 -1
  244. package/library/skills/in-game-purchases/resource.yaml +1 -1
  245. package/library/skills/instantiate-asset-pack/SKILL.md +19 -2
  246. package/library/skills/instantiate-asset-pack/resource.yaml +1 -1
  247. package/library/skills/lumera-single-image-scene-reconstruction/resource.yaml +1 -0
  248. package/library/skills/make-game/SKILL.md +33 -4
  249. package/library/skills/make-game/references/2d-platformer.md +1 -1
  250. package/library/skills/make-game/references/3d-fps.md +1 -1
  251. package/library/skills/make-game/references/3d-horror.md +1 -1
  252. package/library/skills/make-game/references/3d-third-person.md +2 -2
  253. package/library/skills/make-game/resource.yaml +1 -1
  254. package/library/skills/multiplayer/SKILL.md +13 -1
  255. package/library/skills/multiplayer/resource.yaml +1 -1
  256. package/library/skills/multiplayer-movement/SKILL.md +19 -1
  257. package/library/skills/multiplayer-movement/resource.yaml +1 -1
  258. package/library/skills/multiplayer-project/SKILL.md +18 -1
  259. package/library/skills/multiplayer-project/resource.yaml +1 -1
  260. package/library/skills/multiplayer-publish/SKILL.md +25 -7
  261. package/library/skills/multiplayer-publish/resource.yaml +3 -3
  262. package/library/skills/multiplayer-state/SKILL.md +17 -1
  263. package/library/skills/multiplayer-state/resource.yaml +1 -1
  264. package/library/skills/multiplayer-testing/SKILL.md +16 -1
  265. package/library/skills/multiplayer-testing/resource.yaml +1 -1
  266. package/library/skills/music-track/SKILL.md +38 -13
  267. package/library/skills/music-track/resource.yaml +1 -1
  268. package/library/skills/navigate-summer/SKILL.md +26 -9
  269. package/library/skills/navigate-summer/resource.yaml +1 -1
  270. package/library/skills/new-project/SKILL.md +12 -1
  271. package/library/skills/new-project/resource.yaml +1 -1
  272. package/library/skills/organic-model/SKILL.md +48 -18
  273. package/library/skills/organic-model/resource.yaml +1 -1
  274. package/library/skills/pixel-art/SKILL.md +42 -23
  275. package/library/skills/pixel-art/resource.yaml +1 -1
  276. package/library/skills/play/SKILL.md +19 -1
  277. package/library/skills/play/resource.yaml +1 -1
  278. package/library/skills/playtesting-a-feature/SKILL.md +24 -1
  279. package/library/skills/playtesting-a-feature/resource.yaml +1 -1
  280. package/library/skills/procedural-animation/SKILL.md +38 -16
  281. package/library/skills/procedural-animation/resource.yaml +1 -1
  282. package/library/skills/prop-model/SKILL.md +48 -19
  283. package/library/skills/prop-model/resource.yaml +1 -1
  284. package/library/skills/psx-retro-rendering/resource.yaml +1 -0
  285. package/library/skills/publish-your-game/SKILL.md +43 -6
  286. package/library/skills/publish-your-game/resource.yaml +3 -3
  287. package/library/skills/realtime-wet-surfaces/resource.yaml +1 -0
  288. package/library/skills/release-readiness/SKILL.md +13 -1
  289. package/library/skills/release-readiness/resource.yaml +1 -1
  290. package/library/skills/remote-deploy/SKILL.md +15 -1
  291. package/library/skills/remote-deploy/resource.yaml +1 -1
  292. package/library/skills/retarget/SKILL.md +43 -20
  293. package/library/skills/retarget/resource.yaml +1 -1
  294. package/library/skills/running-in-the-cloud/SKILL.md +11 -1
  295. package/library/skills/running-in-the-cloud/resource.yaml +1 -1
  296. package/library/skills/save-load/SKILL.md +16 -1
  297. package/library/skills/save-load/resource.yaml +1 -1
  298. package/library/skills/scene-composition/SKILL.md +18 -1
  299. package/library/skills/scene-composition/resource.yaml +1 -1
  300. package/library/skills/scene-hierarchy-design/SKILL.md +26 -2
  301. package/library/skills/scene-hierarchy-design/resource.yaml +1 -1
  302. package/library/skills/scene-scripting/SKILL.md +96 -636
  303. package/library/skills/scene-scripting/references/ctx-api.md +184 -0
  304. package/library/skills/scene-scripting/references/recipes-2d-ui.md +193 -0
  305. package/library/skills/scene-scripting/references/recipes-3d.md +280 -0
  306. package/library/skills/scene-scripting/resource.yaml +4 -4
  307. package/library/skills/scene-to-level/SKILL.md +24 -2
  308. package/library/skills/scene-to-level/resource.yaml +1 -1
  309. package/library/skills/skill-create/resource.yaml +1 -0
  310. package/library/skills/skill-improve/resource.yaml +1 -0
  311. package/library/skills/skill-test/SKILL.md +12 -2
  312. package/library/skills/skill-test/resource.yaml +1 -0
  313. package/library/skills/skintokens-auto-rigging/resource.yaml +1 -0
  314. package/library/skills/skybox-panorama/SKILL.md +47 -21
  315. package/library/skills/skybox-panorama/resource.yaml +1 -1
  316. package/library/skills/sound-effect/SKILL.md +52 -20
  317. package/library/skills/sound-effect/resource.yaml +1 -1
  318. package/library/skills/spatial-placement/SKILL.md +44 -9
  319. package/library/skills/spatial-placement/resource.yaml +1 -1
  320. package/library/skills/sprite-sheet/SKILL.md +55 -27
  321. package/library/skills/sprite-sheet/resource.yaml +1 -1
  322. package/library/skills/store-art/SKILL.md +14 -3
  323. package/library/skills/store-art/resource.yaml +2 -2
  324. package/library/skills/store-listing/SKILL.md +13 -3
  325. package/library/skills/store-listing/resource.yaml +2 -2
  326. package/library/skills/summer-analytics/SKILL.md +22 -5
  327. package/library/skills/summer-analytics/resource.yaml +2 -2
  328. package/library/skills/summer-apps/SKILL.md +77 -32
  329. package/library/skills/summer-apps/manifest.md +1 -1
  330. package/library/skills/summer-apps/minimal-app.md +7 -7
  331. package/library/skills/summer-apps/resource.yaml +1 -1
  332. package/library/skills/summer-apps/sdk-reference.md +5 -5
  333. package/library/skills/summer-apps-design/SKILL.md +1 -1
  334. package/library/skills/summer-apps-design/resource.yaml +1 -1
  335. package/library/skills/summer-assets/SKILL.md +86 -0
  336. package/library/skills/summer-assets/resource.yaml +34 -0
  337. package/library/skills/summer-cli/SKILL.md +133 -0
  338. package/library/skills/summer-cli/resource.yaml +31 -0
  339. package/library/skills/summer-friends/SKILL.md +14 -0
  340. package/library/skills/summer-leaderboards/SKILL.md +16 -0
  341. package/library/skills/summer-match-results/SKILL.md +17 -0
  342. package/library/skills/summer-matchmaking/SKILL.md +17 -0
  343. package/library/skills/summer-parties/SKILL.md +14 -0
  344. package/library/skills/summer-player-data/SKILL.md +14 -0
  345. package/library/skills/summer-store/SKILL.md +16 -1
  346. package/library/skills/summer-world-chat/SKILL.md +14 -0
  347. package/library/skills/summer-world-saves/SKILL.md +14 -0
  348. package/library/skills/text-to-motion/SKILL.md +45 -23
  349. package/library/skills/text-to-motion/prompts-and-controls.md +5 -5
  350. package/library/skills/text-to-motion/resource.yaml +1 -1
  351. package/library/skills/text-to-motion/rigging-for-text-motion.md +2 -2
  352. package/library/skills/tileable-texture/SKILL.md +37 -15
  353. package/library/skills/tileable-texture/resource.yaml +1 -1
  354. package/library/skills/trailer-shot/SKILL.md +46 -24
  355. package/library/skills/trailer-shot/resource.yaml +1 -1
  356. package/library/skills/tune-performance/SKILL.md +32 -6
  357. package/library/skills/tune-performance/resource.yaml +1 -1
  358. package/library/skills/ui-basics/SKILL.md +55 -36
  359. package/library/skills/ui-basics/resource.yaml +1 -1
  360. package/library/skills/ui-graphics/SKILL.md +64 -38
  361. package/library/skills/ui-graphics/resource.yaml +1 -1
  362. package/library/skills/use-widget-asset/SKILL.md +15 -1
  363. package/library/skills/use-widget-asset/resource.yaml +1 -1
  364. package/library/skills/using-summer/SKILL.md +32 -5
  365. package/library/skills/using-summer/resource.yaml +3 -2
  366. package/library/skills/vehicle-model/SKILL.md +92 -57
  367. package/library/skills/vehicle-model/resource.yaml +1 -1
  368. package/library/skills/verification-before-completion/SKILL.md +1 -1
  369. package/library/skills/verification-before-completion/resource.yaml +1 -1
  370. package/library/skills/verifying-scenes/SKILL.md +31 -2
  371. package/library/skills/verifying-scenes/resource.yaml +1 -1
  372. package/library/skills/vfx-dissolve/SKILL.md +21 -2
  373. package/library/skills/vfx-dissolve/resource.yaml +1 -1
  374. package/library/skills/vfx-fire/SKILL.md +41 -41
  375. package/library/skills/vfx-fire/resource.yaml +1 -1
  376. package/library/skills/vfx-hit-spark/SKILL.md +24 -1
  377. package/library/skills/vfx-hit-spark/resource.yaml +1 -1
  378. package/library/skills/vfx-lightning/SKILL.md +30 -16
  379. package/library/skills/vfx-lightning/resource.yaml +1 -1
  380. package/library/skills/vfx-magic-glow/SKILL.md +46 -32
  381. package/library/skills/vfx-magic-glow/resource.yaml +1 -1
  382. package/library/skills/vfx-muzzle-flash/SKILL.md +43 -35
  383. package/library/skills/vfx-muzzle-flash/resource.yaml +1 -1
  384. package/library/skills/vfx-smoke/SKILL.md +39 -31
  385. package/library/skills/vfx-smoke/resource.yaml +1 -1
  386. package/library/skills/vfx-water-ripple/SKILL.md +35 -31
  387. package/library/skills/vfx-water-ripple/resource.yaml +1 -1
  388. package/library/skills/voice-line/SKILL.md +87 -40
  389. package/library/skills/voice-line/resource.yaml +1 -1
  390. package/library/skills/web-and-touch-input/SKILL.md +20 -1
  391. package/library/skills/web-and-touch-input/resource.yaml +1 -1
  392. package/library/skills/web-compatibility-look/SKILL.md +21 -1
  393. package/library/skills/web-compatibility-look/resource.yaml +1 -1
  394. package/library/skills/world-building-3d/SKILL.md +29 -1
  395. package/library/skills/world-building-3d/resource.yaml +1 -1
  396. package/library/skills/writing-skills/resource.yaml +1 -0
  397. package/library/tools/add-node/GUIDE.md +14 -0
  398. package/library/tools/align-distribute-3d/GUIDE.md +7 -0
  399. package/library/tools/app-call/resource.yaml +1 -1
  400. package/library/tools/app-guide/resource.yaml +2 -2
  401. package/library/tools/app-page/resource.yaml +1 -1
  402. package/library/tools/app-screenshot/resource.yaml +19 -1
  403. package/library/tools/app-tools/resource.yaml +1 -1
  404. package/library/tools/attach-to-surface/GUIDE.md +15 -0
  405. package/library/tools/batch/GUIDE.md +27 -0
  406. package/library/tools/camera-bookmark/GUIDE.md +12 -0
  407. package/library/tools/capture-gameplay/GUIDE.md +3 -0
  408. package/library/tools/capture-gameplay/resource.yaml +3 -3
  409. package/library/tools/check-job/resource.yaml +1 -1
  410. package/library/tools/clear-console/GUIDE.md +3 -0
  411. package/library/tools/connect-ports/GUIDE.md +9 -0
  412. package/library/tools/connect-signal/GUIDE.md +14 -0
  413. package/library/tools/create-debug-report/GUIDE.md +10 -0
  414. package/library/tools/create-scene/GUIDE.md +10 -0
  415. package/library/tools/debug-views/GUIDE.md +7 -0
  416. package/library/tools/enable-plugin/GUIDE.md +3 -0
  417. package/library/tools/export-game/GUIDE.md +3 -0
  418. package/library/tools/export-game/resource.yaml +3 -3
  419. package/library/tools/export-templates/GUIDE.md +3 -0
  420. package/library/tools/fabricate-3d/GUIDE.md +19 -0
  421. package/library/tools/frame-nodes/GUIDE.md +9 -0
  422. package/library/tools/frame-shot/GUIDE.md +9 -0
  423. package/library/tools/game-control/GUIDE.md +9 -0
  424. package/library/tools/game-input/GUIDE.md +9 -0
  425. package/library/tools/game-probe/GUIDE.md +9 -0
  426. package/library/tools/generate-3d/resource.yaml +3 -3
  427. package/library/tools/generate-motion/resource.yaml +2 -2
  428. package/library/tools/get-console/GUIDE.md +9 -0
  429. package/library/tools/get-console/resource.yaml +5 -0
  430. package/library/tools/get-debugger-errors/GUIDE.md +7 -0
  431. package/library/tools/get-debugger-errors/resource.yaml +5 -0
  432. package/library/tools/get-debugger-warnings/GUIDE.md +7 -0
  433. package/library/tools/get-debugger-warnings/resource.yaml +5 -0
  434. package/library/tools/get-diagnostics/GUIDE.md +13 -0
  435. package/library/tools/get-project-context/GUIDE.md +25 -0
  436. package/library/tools/get-runtime-tree/GUIDE.md +7 -0
  437. package/library/tools/get-runtime-tree/resource.yaml +5 -0
  438. package/library/tools/get-scene-tree/GUIDE.md +11 -0
  439. package/library/tools/get-scene-tree/resource.yaml +5 -0
  440. package/library/tools/get-script-errors/GUIDE.md +5 -0
  441. package/library/tools/grep/GUIDE.md +11 -0
  442. package/library/tools/import-asset/GUIDE.md +8 -0
  443. package/library/tools/import-asset-by-id/GUIDE.md +12 -0
  444. package/library/tools/import-from-url/GUIDE.md +10 -0
  445. package/library/tools/import-from-url-batch/GUIDE.md +3 -0
  446. package/library/tools/import-hdri/GUIDE.md +16 -0
  447. package/library/tools/input-map-bind/GUIDE.md +11 -0
  448. package/library/tools/inspect-asset/GUIDE.md +14 -0
  449. package/library/tools/inspect-asset/resource.yaml +5 -0
  450. package/library/tools/inspect-node/GUIDE.md +11 -0
  451. package/library/tools/inspect-node/resource.yaml +5 -0
  452. package/library/tools/inspect-resource/GUIDE.md +7 -0
  453. package/library/tools/inspect-resource/resource.yaml +5 -0
  454. package/library/tools/inspect-runtime-node/GUIDE.md +7 -0
  455. package/library/tools/inspect-runtime-node/resource.yaml +5 -0
  456. package/library/tools/instantiate-scene/GUIDE.md +12 -0
  457. package/library/tools/is-running/GUIDE.md +3 -0
  458. package/library/tools/measure/GUIDE.md +8 -0
  459. package/library/tools/navigation-probe/GUIDE.md +9 -0
  460. package/library/tools/open/resource.yaml +2 -2
  461. package/library/tools/open-main-scene/GUIDE.md +6 -0
  462. package/library/tools/open-scene/GUIDE.md +8 -0
  463. package/library/tools/place-adjacent/GUIDE.md +7 -0
  464. package/library/tools/play/GUIDE.md +13 -0
  465. package/library/tools/project-setting/GUIDE.md +9 -0
  466. package/library/tools/publish-build/resource.yaml +6 -6
  467. package/library/tools/raycast/GUIDE.md +7 -0
  468. package/library/tools/read-file/GUIDE.md +10 -0
  469. package/library/tools/read-library/resource.yaml +5 -0
  470. package/library/tools/recent-events/GUIDE.md +7 -0
  471. package/library/tools/remove-node/GUIDE.md +3 -0
  472. package/library/tools/repeat-along/GUIDE.md +5 -0
  473. package/library/tools/replace-node/GUIDE.md +9 -0
  474. package/library/tools/replace-text/GUIDE.md +5 -0
  475. package/library/tools/run-editor-script/GUIDE.md +16 -0
  476. package/library/tools/run-script/GUIDE.md +30 -0
  477. package/library/tools/run-script/resource.yaml +6 -3
  478. package/library/tools/runtime-animate/GUIDE.md +7 -0
  479. package/library/tools/runtime-call/GUIDE.md +7 -0
  480. package/library/tools/runtime-set/GUIDE.md +9 -0
  481. package/library/tools/runtime-spawn/GUIDE.md +9 -0
  482. package/library/tools/save-scene/GUIDE.md +3 -0
  483. package/library/tools/scene-audit/GUIDE.md +29 -0
  484. package/library/tools/screenshot/GUIDE.md +17 -0
  485. package/library/tools/select-node/GUIDE.md +3 -0
  486. package/library/tools/set-prop/GUIDE.md +23 -0
  487. package/library/tools/set-resource-property/GUIDE.md +8 -0
  488. package/library/tools/shot-sheet/GUIDE.md +7 -0
  489. package/library/tools/snap-to-surface/GUIDE.md +17 -0
  490. package/library/tools/snapshot-diff/GUIDE.md +7 -0
  491. package/library/tools/starcast/GUIDE.md +12 -0
  492. package/library/tools/stop/GUIDE.md +3 -0
  493. package/library/tools/test-placement/GUIDE.md +7 -0
  494. package/library/tools/ui-actions/GUIDE.md +12 -0
  495. package/library/tools/ui-activate/GUIDE.md +11 -0
  496. package/library/tools/ui-screenshot/GUIDE.md +9 -0
  497. package/library/tools/ui-tree/GUIDE.md +10 -0
  498. package/library/tools/wait-for-event/GUIDE.md +11 -0
  499. package/library/tools/world-snapshot/GUIDE.md +9 -0
  500. package/library/tools/write-file/GUIDE.md +5 -0
  501. package/library/tools/zoom/GUIDE.md +5 -0
  502. package/package.json +8 -5
  503. package/registry/generated/counts.json +2 -2
  504. package/registry/generated/gemini-extension.json +6 -13
  505. package/registry/generated/index.json +482 -349
  506. package/registry/generated/marketplace.claude.json +2 -13
  507. package/registry/generated/plugin.claude-directory.json +168 -0
  508. package/registry/generated/plugin.claude.json +24 -22
  509. package/registry/generated/plugin.codex.json +18 -22
  510. package/registry/generated/plugin.cursor.json +8 -14
  511. package/registry/generated/plugin.factory.json +6 -13
  512. package/registry/generated/server.json +43 -0
  513. package/registry/generated/skills-index.md +121 -118
  514. package/registry/generated/skills-registry.json +167 -115
  515. package/registry/operations/fixtures/invalid-deprecated-without-replacement.json +60 -0
  516. package/registry/operations/fixtures/invalid-name.json +60 -0
  517. package/registry/operations/fixtures/invalid-publish-without-owner.json +82 -0
  518. package/registry/operations/fixtures/invalid-spend-without-estimate.json +42 -0
  519. package/registry/operations/fixtures/invalid-unknown-field.json +61 -0
  520. package/registry/operations/fixtures/valid-player-facing.json +82 -0
  521. package/registry/operations/fixtures/valid-read.json +60 -0
  522. package/registry/operations/fixtures/valid-spend.json +43 -0
  523. package/registry/operations/legacy-names.json +1241 -0
  524. package/registry/operations/public-catalog.json +33160 -0
  525. package/registry/schemas/operation.schema.json +318 -0
  526. package/registry/schemas/skill.schema.json +4 -0
  527. package/CLAUDE.md +0 -7
@@ -192,17 +192,17 @@ Use this when summer_get_diagnostics shows a non-zero \`debugger.warnings\` coun
192
192
  const { result } = shapeEngineLogResponse(engineResult, { maxEntries: max_warnings });
193
193
  return result;
194
194
  }));
195
- server.tool("summer_play", `Start running the game in the engine. With no extra parameters the game runs inside Summer Engine's viewport (the 'main' instance) QUIETLY — see below.
195
+ server.tool("summer_play", `Start the game. With no parameters it runs QUIETLY inside Summer Engine's viewport (the 'main' instance); scene runs one level or UI screen instead of the main scene.
196
196
 
197
- QUIET BY DEFAULT (focus:false, PlayGame agent:true): the user is usually working on the same machine while you build, so a play must not take over their screen. Quiet play makes the EDITOR stay put: it does not switch the main screen to the Game tab, does not grab keyboard focus for the embedded game, ignores the game's later focus report, and skips the render-health self-check that would otherwise misread the untouched Game view as a GPU failure and flip the user's embed setting. Quiet play does NOT hide the game: it still runs embedded in the Game view (visible if the user already has that tab open), it is the running game for summer_is_running / summer_screenshot target:'game' / summer_get_diagnostics, and on engines without the background launch posture it does not change a user who has "Embed Game on Play" turned off — their game opens in its own OS window as always. Engines with the background posture (--summer-background, 0.5.66+) also launch the play child with that flag, so a separate-window game appears without activating or taking focus either. The result echoes agent_quiet:true when honoured; a launch result WITHOUT agent_quiet means the engine predates quiet play and most likely took focus — the tool adds posture_note saying so. focus:true launches like the toolbar Play button (Game tab + focus): use it ONLY when the user is watching and asked to see the game come up.
197
+ QUIET BY DEFAULT (focus:false, PlayGame agent:true): the user usually works on the same machine, so the EDITOR stays put. It does not switch to the Game tab or take keyboard focus (nor follow the game's later focus report), and skips the render-health self-check that would misread the untouched Game view as a GPU failure and flip the user's embed setting. Quiet play does NOT hide the game: it runs embedded in the Game view (visible if that tab is open) and is the running game for summer_is_running / summer_screenshot target:'game' / summer_get_diagnostics. With "Embed Game on Play" off the game gets its own OS window; engines with --summer-background (0.5.66+) open it without taking focus. The result echoes agent_quiet:true when honoured; without agent_quiet the engine predates quiet play and most likely took focus (posture_note says so). focus:true launches like the toolbar Play button (Game tab + focus): ONLY when the user is watching and asked to see the game come up.
198
198
 
199
- After starting, confirm boot with summer_is_running (boot time varies — never sleep a guessed delay), then summer_get_diagnostics for runtime errors. You can run a specific scene instead of the main scene — useful for testing individual levels or UI screens.
199
+ After starting, confirm boot with summer_is_running (boot time varies; never sleep a guessed delay), then summer_get_diagnostics for runtime errors.
200
200
 
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.
201
+ DETERMINISTIC RUNS (newer engines): seed / fixed_fps / time_scale pin THIS launch only, nothing persisted. seed pins the GLOBAL RNG only (not RandomNumberGenerator instances, randomize(), rand_from_seed, wall-clock, thread/IO/audio timing). The result's \`determinism\` block says whether the pins applied (applied:false carries a reason: already_running, editor_run_args_override, launch_not_started) and restates seed_scope. NO determinism block although you sent a pin = the engine predates the params and the run is NOT reproducible (the tool says so); never claim otherwise.
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; two side by side make an A/B. deterministic:true (offscreen only) is what lets summer_game_input action:'replay' accept a seed. Poll summer_game_control action:'instances' until attached:true (the result reports session_attached) 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
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.`, {
205
+ MULTIPLAYER — LOCAL PLAY (engine with Local Play; the multiplayer-testing skill): 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. Scenes and queue come from summer.build.json's WorldDefinition (client_entry_point, the headless_engine component entry_point). queue picks another declared queue; queue WITHOUT players starts its minPlayers; spectators adds spectator clients. local_play.warnings flags a roster outside minPlayers..maxPlayers. The local_play block lists every process (label, role, persona) and the port; failure_reason local_play_unavailable says 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, summer_stop stops them all. A join for a different queue fails naming both queues. Not a proof of sign-in, matchmaking or hosted admission (staging). No local_play block although you sent players = the engine predates Local Play and ran ONE client; the tool says so.`, {
206
206
  scene: z.string().optional().describe("Scene to run instead of main scene, e.g. 'res://levels/test_level.tscn'"),
207
207
  ...playGameExtensionSchema,
208
208
  }, async (args) => {
@@ -7,17 +7,17 @@ WHEN — the three asset classes neither generation nor the free library serve w
7
7
  - modular kits with exact dimensions and snapping (walls, pipes, fences, rails: array + boolean + bevel, one shared material) — generation cannot hold size and style across 30 pieces;
8
8
  - VFX meshes (shatter pieces, curve sweeps, trails, LOD chains) — one-liners in bpy, absent in the engine;
9
9
  - post-processing a generated model (decimate -> UV unwrap -> bake) before it goes into the scene.
10
- WHEN NOT: a generic prop (barrel, crate, chair) -> summer_search_assets / summer_import_asset first, then summer_generate_3d; a character or any organic shape -> summer_generate_3d (scripted organic modelling is the documented failure mode); a blockout or placeholder -> summer_run_script primitives/CSG, instant and in-scene. Route with the asset-strategy skill; the fabricating-assets skill carries the bpy rules and recipes.
10
+ WHEN NOT: a generic prop (barrel, crate, chair) -> summer_search_assets / summer_import_asset first, then summer_generate_3d; a character or any organic shape -> summer_generate_3d (scripted organic modelling is the documented failure mode); a blockout or placeholder -> summer_run_script primitives/CSG, instant and in-scene. Route with the asset-strategy skill; the fabricating-assets skill carries the bpy rules, recipes and the fix for each failure_reason.
11
11
 
12
- SCRIPT CONTRACT: 'source' is plain bpy code. Pre-bound names: bpy, bmesh, mathutils, math, Vector, Matrix, Euler. The script must CREATE mesh objects and leave them linked in the scene — do NOT export and do NOT quit (the engine's bootstrap exports for you: modifiers applied at export, Geometry Nodes realized, +Y-up conversion, materials carried as Principled BSDF only, a procedural Base Color baked to a 2K texture; procedural Metallic/Roughness/Normal/Emission are NOT baked and come back in 'warnings'). Objects hidden or render-disabled are treated as helpers (boolean cutters, guides) and are not exported — they are listed in 'skipped'. Model in metres. MESH/CURVE/SURFACE/META/FONT export as meshes, EMPTY/ARMATURE keep hierarchy, cameras and lights are dropped. Name your objects — they become node names.
12
+ SCRIPT CONTRACT: 'source' is plain bpy that must CREATE mesh objects and leave them linked in the scene — do NOT export and do NOT quit. The engine's bootstrap exports for you: modifiers applied, Geometry Nodes realized, +Y-up conversion, materials as Principled BSDF only, a procedural Base Color baked to a 2K texture; procedural Metallic/Roughness/Normal/Emission are NOT baked (see 'warnings'). Hidden or render-disabled objects are helpers (boolean cutters, guides), not exported, listed in 'skipped'. Model in metres. MESH/CURVE/SURFACE/META/FONT export as meshes, EMPTY/ARMATURE keep hierarchy, cameras and lights are dropped. Name your objects — they become node names.
13
13
 
14
- REQUIRES BLENDER on the user's machine (4.2 LTS or newer). Resolution order: 'blender_path' -> SUMMER_BLENDER_BIN in the editor's environment -> Editor Settings filesystem/import/blender/blender_path (shared with .blend import) -> PATH, well-known install dirs, ~/.summer/tools/blender-*. Not found -> failure_reason blender_not_found with the exact fix and every path that was checked; relay it to the user as a one-line decision, never guess a path and never install anything on their behalf.
14
+ REQUIRES BLENDER 4.2 LTS or newer. Resolution: 'blender_path' -> SUMMER_BLENDER_BIN in the editor's environment -> Editor Settings filesystem/import/blender/blender_path -> PATH, well-known install dirs, ~/.summer/tools/blender-*. Not found -> failure_reason blender_not_found with the exact fix and every path checked; relay it to the user as a one-line decision; never guess a path or install anything for them.
15
15
 
16
- ONE fabrication runs at a time per editor (failure_reason busy — wait for the result, never fire two in parallel). Budget max_seconds 15-600 (default 120) covers Blender boot + script + bakes + export; the client waits max_seconds + 60 s. Blind until import: there is no viewport feedback while the script runs, so keep scripts deterministic (fixed seeds) and verify afterwards.
16
+ ONE fabrication runs at a time per editor (failure_reason busy: wait for the result, never fire two in parallel). There is no viewport feedback while the script runs, so keep scripts deterministic (fixed seeds) and verify afterwards.
17
17
 
18
- Returns {ok, ran, blender_version, blender_path, out_path, objects[{name,type,vertices,faces,triangles,materials,modifiers}], object_count, dimensions{x,y,z} (+Y up, source scale), warnings[], baked[], skipped[], output[], errors[], exit_code, duration_ms, checkpoint} plus imported_node_path / scale_applied / instance_dimensions with import_to_scene, and no_rewind_point:true when no checkpoint exists. Failures carry failure_reason: blender_not_found | blender_launch_failed | script_error (traceback_tail + script_line — fix the bpy against the reported blender_version and re-run; bpy APIs change across majors) | timeout (raise max_seconds or split the job) | export_empty (no exportable object — check hide/render flags and collection links) | export_failed | export_missing | import_failed / instantiate_failed (the .glb IS at out_path — summer_instantiate_scene it yourself; the importer's message is in summer_get_console) | busy | cancelled.
18
+ Returns blender_version, blender_path, out_path, objects[{name, type, vertices, faces, triangles, materials, modifiers}], object_count, dimensions{x,y,z} (+Y up, source scale), warnings, baked, skipped, output, errors, exit_code, duration_ms, checkpoint; with import_to_scene also imported_node_path / scale_applied / instance_dimensions; no_rewind_point:true when no checkpoint exists. failure_reason: blender_not_found | blender_launch_failed | script_error (traceback_tail + script_line; fix the bpy for the reported blender_version) | timeout (raise max_seconds or split the job) | export_empty (check hide/render flags and collection links) | export_failed | export_missing | import_failed / instantiate_failed (the .glb IS at out_path: summer_instantiate_scene it yourself; importer message in summer_get_console) | busy | cancelled.
19
19
 
20
- THE LOOP: summer_world_snapshot BEFORE (keep snapshot_id) -> summer_fabricate_3d with import_to_scene (+ target_size for real-world scale) -> read dimensions/warnings/skipped -> summer_snapshot_diff + summer_screenshot -> iterate. Never claim a visual result without the screenshot. If this engine build predates FabricateMesh, the result is a structured engine_lacks_op failure (nothing is sent): use summer_generate_3d / summer_search_assets, or update Summer Engine.`, fabricateArgsSchema.shape, async (args) => withEngine(async (client) => {
20
+ THE LOOP: summer_world_snapshot BEFORE (keep snapshot_id) -> summer_fabricate_3d with import_to_scene (+ target_size for real-world scale) -> read dimensions/warnings/skipped -> summer_snapshot_diff + summer_screenshot -> iterate. Never claim a visual result without the screenshot. An engine build without FabricateMesh returns a structured engine_lacks_op failure (nothing is sent): use summer_generate_3d / summer_search_assets, or update Summer Engine.`, fabricateArgsSchema.shape, async (args) => withEngine(async (client) => {
21
21
  const missing = missingEngineOpResult(client, "FabricateMesh", FABRICATE_FALLBACK);
22
22
  if (missing)
23
23
  return missing;
@@ -8,7 +8,8 @@ import { getAuthToken } from "../../core/auth.js";
8
8
  import { resolveGatewayUrl } from "../../core/config.js";
9
9
  import { readJsonResponse } from "../../core/util/http.js";
10
10
  import { asRecord, stringFrom } from "../../core/util/json.js";
11
- import { TOOLKIT_VERSION as CLI_VERSION } from "../../core/version.js";
11
+ import { summerRequestHeaders } from "../../core/agent-host.js";
12
+ import { codedFailure, codeForStatus, describeNetworkError, networkDetails, NOT_SIGNED_IN, SIGN_IN_AGAIN_RECOVERY, } from "../../core/error-codes.js";
12
13
  const TOOL_BY_ENDPOINT = {
13
14
  "/api/mcp/generate/image": "summer_generate_image",
14
15
  "/api/mcp/generate/audio": "summer_generate_audio",
@@ -72,13 +73,18 @@ async function readLenientJson(res) {
72
73
  return json;
73
74
  return text ? { message: text.slice(0, 1000) } : {};
74
75
  }
76
+ /** The coded failure for a non-OK reply: 401 (token expired) and 402 (no
77
+ * credits) carry the shared codes. */
78
+ function statusFailure(status) {
79
+ const code = codeForStatus(status);
80
+ if (!code)
81
+ return {};
82
+ return code === "not_signed_in" ? { code, recovery: SIGN_IN_AGAIN_RECOVERY } : { code };
83
+ }
75
84
  async function mcpGenerate(endpoint, body, timeoutMs = 120_000) {
76
85
  const token = await getAuthToken();
77
86
  if (!token) {
78
- return {
79
- error: "Not signed in. Run in your terminal:\n npx -y summer-engine@latest login\nOr open: https://www.summerengine.com/login",
80
- status: 401,
81
- };
87
+ return { error: NOT_SIGNED_IN, status: 401, code: "not_signed_in" };
82
88
  }
83
89
  const gatewayUrl = await resolveGatewayUrl();
84
90
  let res;
@@ -86,36 +92,27 @@ async function mcpGenerate(endpoint, body, timeoutMs = 120_000) {
86
92
  res = await fetch(`${gatewayUrl}${endpoint}`, {
87
93
  method: "POST",
88
94
  headers: {
95
+ ...summerRequestHeaders({ tool: TOOL_BY_ENDPOINT[endpoint], surface: "mcp" }),
89
96
  Authorization: `Bearer ${token}`,
90
97
  "Content-Type": "application/json",
91
- "X-Summer-Client": "summer-cli",
92
- "X-Summer-Client-Version": CLI_VERSION,
93
- "X-Summer-Client-Surface": "mcp",
94
98
  "X-Summer-MCP-Endpoint": endpoint,
95
- "X-Summer-MCP-Tool": TOOL_BY_ENDPOINT[endpoint] ?? "unknown",
96
99
  },
97
100
  body: JSON.stringify(body),
98
101
  signal: AbortSignal.timeout(timeoutMs),
99
102
  });
100
103
  }
101
104
  catch (err) {
102
- const msg = err instanceof Error ? err.message : String(err);
103
- return { error: `Generation request failed: ${msg}`, status: 0 };
105
+ return { error: `Generation request failed: ${describeNetworkError(err)}`, status: 0, code: "unavailable", data: networkDetails(err) };
104
106
  }
105
107
  const data = await readLenientJson(res);
106
108
  if (!res.ok) {
107
109
  let message = formattedApiErrorMessage(res.status, data);
108
- if (res.status === 402) {
109
- // One link: the Add credits step in Studio (no plan needed). Newer servers already put it in the message.
110
- const base = String(data.message || "Not enough credits.");
111
- message = base.includes("/studio/credits") ? base : `${base}\nAdd credits: https://summerengine.com/studio/credits`;
112
- }
113
- if (res.status === 401) {
114
- message =
115
- (data.message || "Auth token expired.") +
116
- "\nRe-authenticate:\n npx -y summer-engine@latest login";
117
- }
118
- return { error: message, data: { ...data, status: res.status }, status: res.status };
110
+ // The next step (Add credits, sign in again) rides in `recovery`.
111
+ if (res.status === 402)
112
+ message = String(data.message || "Not enough credits.");
113
+ if (res.status === 401)
114
+ message = String(data.message || "Auth token expired.");
115
+ return { error: message, data: { ...data, status: res.status }, status: res.status, ...statusFailure(res.status) };
119
116
  }
120
117
  return { data, status: res.status };
121
118
  }
@@ -127,19 +124,15 @@ async function mcpGet(endpoint, searchParams, timeoutMs = 30_000) {
127
124
  try {
128
125
  res = await fetch(`${gatewayUrl}${endpoint}${suffix}`, {
129
126
  headers: {
127
+ ...summerRequestHeaders({ tool: TOOL_BY_ENDPOINT[endpoint], surface: "mcp" }),
130
128
  ...(token ? { Authorization: `Bearer ${token}` } : {}),
131
- "X-Summer-Client": "summer-cli",
132
- "X-Summer-Client-Version": CLI_VERSION,
133
- "X-Summer-Client-Surface": "mcp",
134
129
  "X-Summer-MCP-Endpoint": endpoint,
135
- "X-Summer-MCP-Tool": TOOL_BY_ENDPOINT[endpoint] ?? "unknown",
136
130
  },
137
131
  signal: AbortSignal.timeout(timeoutMs),
138
132
  });
139
133
  }
140
134
  catch (err) {
141
- const msg = err instanceof Error ? err.message : String(err);
142
- return { error: `Request failed: ${msg}`, status: 0 };
135
+ return { error: `Request failed: ${describeNetworkError(err)}`, status: 0, code: "unavailable", data: networkDetails(err) };
143
136
  }
144
137
  const data = await readLenientJson(res);
145
138
  if (!res.ok) {
@@ -147,6 +140,8 @@ async function mcpGet(endpoint, searchParams, timeoutMs = 30_000) {
147
140
  error: formattedApiErrorMessage(res.status, data),
148
141
  data: { ...data, status: res.status },
149
142
  status: res.status,
143
+ // Without a token a 401 means "sign in", not "sign in again".
144
+ ...(!token && res.status === 401 ? { code: "not_signed_in" } : statusFailure(res.status)),
150
145
  };
151
146
  }
152
147
  return { data, status: res.status };
@@ -158,18 +153,18 @@ async function mcpGet(endpoint, searchParams, timeoutMs = 30_000) {
158
153
  async function pollJob(jobId, maxWaitMs = 600_000, intervalMs = 5_000) {
159
154
  const token = await getAuthToken();
160
155
  if (!token)
161
- return { error: "Not signed in" };
156
+ return { error: NOT_SIGNED_IN, code: "not_signed_in" };
162
157
  const gatewayUrl = await resolveGatewayUrl();
163
158
  const deadline = Date.now() + maxWaitMs;
164
159
  while (Date.now() < deadline) {
165
160
  try {
166
161
  const res = await fetch(`${gatewayUrl}/api/mcp/jobs/${encodeURIComponent(jobId)}`, {
167
- headers: { Authorization: `Bearer ${token}` },
162
+ headers: { ...summerRequestHeaders({ surface: "mcp" }), Authorization: `Bearer ${token}` },
168
163
  signal: AbortSignal.timeout(15_000),
169
164
  });
170
- const data = await res.json();
165
+ const data = await readLenientJson(res);
171
166
  if (!res.ok)
172
- return { error: data.message || "Poll failed", data };
167
+ return { error: data.message || "Poll failed", data, ...statusFailure(res.status) };
173
168
  if (data.status === "completed")
174
169
  return { data };
175
170
  if (data.status === "failed")
@@ -182,23 +177,32 @@ async function pollJob(jobId, maxWaitMs = 600_000, intervalMs = 5_000) {
182
177
  }
183
178
  }
184
179
  catch (err) {
185
- const msg = err instanceof Error ? err.message : String(err);
186
- return { error: `Poll error: ${msg}` };
180
+ return { error: `Poll error: ${describeNetworkError(err)}`, code: "unavailable", data: networkDetails(err) };
187
181
  }
188
182
  }
189
183
  return { error: `Timed out after ${maxWaitMs / 1000}s. Use summer_check_job({ jobId: "${jobId}" }) to check later.` };
190
184
  }
191
- function errorResult(message, extra) {
185
+ /** A failed tool call. With a shared code (core/error-codes.ts) the body is
186
+ * `{ok:false, code, error, recovery, …, message}`; otherwise the older
187
+ * `{error:true, …, message}`. */
188
+ function errorResult(message, extra, coded) {
189
+ const body = coded?.code
190
+ ? codedFailure(coded.code, message, { ...extra, message }, coded.recovery)
191
+ : { error: true, ...extra, message };
192
192
  return {
193
193
  content: [
194
194
  {
195
195
  type: "text",
196
- text: JSON.stringify({ error: true, ...extra, message }, null, 2),
196
+ text: JSON.stringify(body, null, 2),
197
197
  },
198
198
  ],
199
199
  isError: true,
200
200
  };
201
201
  }
202
+ /** The step after a generation job starts (the hosted tools answer the same way). */
203
+ function checkJobNext(jobId) {
204
+ return `The job runs on Summer's servers. Poll summer_check_job({ jobId: "${jobId}" }) every 15-30 seconds until status is "completed".`;
205
+ }
202
206
  function successResult(data) {
203
207
  return {
204
208
  content: [
@@ -232,7 +236,7 @@ handoff that MCP cannot perform automatically; do not pretend that stage ran.`,
232
236
  params.set("id", workflowId);
233
237
  const result = await mcpGet("/api/mcp/workflows", params);
234
238
  if (result.error)
235
- return errorResult(result.error, result.data);
239
+ return errorResult(result.error, result.data, result);
236
240
  return successResult(result.data);
237
241
  });
238
242
  // ========================================================================
@@ -252,7 +256,7 @@ Cloud tool — runs on Summer's servers and works WITHOUT the Summer Engine app
252
256
  Requires authentication: run 'npx -y summer-engine@latest login' first.`, boardArgsSchema.shape, async (args) => {
253
257
  const result = await mcpGet(BOARD_ENDPOINT, boardQuery(args), 45_000);
254
258
  if (result.error)
255
- return errorResult(result.error, result.data);
259
+ return errorResult(result.error, result.data, result);
256
260
  return { content: boardContent(result.data ?? {}) };
257
261
  });
258
262
  // ========================================================================
@@ -307,7 +311,7 @@ Requires authentication: run 'npx -y summer-engine@latest login' first.`, imageG
307
311
  options,
308
312
  }, IMAGE_GENERATION_TIMEOUT_MS);
309
313
  if (result.error) {
310
- return errorResult(result.error, result.data);
314
+ return errorResult(result.error, result.data, result);
311
315
  }
312
316
  // Download to temp so the AI can Read and show the image
313
317
  const imageUrl = result.data?.asset?.fileUrl || result.data?.asset?.thumbnailUrl;
@@ -343,7 +347,7 @@ Requires authentication: run 'npx -y summer-engine@latest login' first.`, {
343
347
  }, async ({ assetId }) => {
344
348
  const result = await mcpGenerate("/api/mcp/generate/slice-asset-sheet", { assetId }, 300_000);
345
349
  if (result.error) {
346
- return errorResult(result.error, result.data);
350
+ return errorResult(result.error, result.data, result);
347
351
  }
348
352
  return successResult({
349
353
  ...result.data,
@@ -442,7 +446,7 @@ Requires authentication: run 'npx -y summer-engine@latest login' first.`, {
442
446
  body.options = options;
443
447
  const result = await mcpGenerate("/api/mcp/generate/audio", body);
444
448
  if (result.error) {
445
- return errorResult(result.error, result.data);
449
+ return errorResult(result.error, result.data, result);
446
450
  }
447
451
  return successResult(result.data);
448
452
  });
@@ -533,8 +537,9 @@ For a complete animated humanoid package, pass rig=true plus animationNames or
533
537
  actionIds. This routes through the shared character pipeline instead of a
534
538
  one-off mesh job.
535
539
 
536
- By default, waits for completion (up to 10 min) and returns the result directly.
537
- Set wait=false to get the jobId immediately and poll manually with summer_check_job.
540
+ Returns a jobId within seconds. Poll summer_check_job with it until status is
541
+ "completed" (most models take 1-5 minutes; tell the user it is running and keep
542
+ working meanwhile). wait=true blocks up to 10 minutes instead.
538
543
 
539
544
  Cloud tool — runs on Summer's servers and works WITHOUT the Summer Engine app open.
540
545
  Requires authentication: run 'npx -y summer-engine@latest login' first.`, {
@@ -589,8 +594,8 @@ Requires authentication: run 'npx -y summer-engine@latest login' first.`, {
589
594
  .describe("Character height used by auto-rigging"),
590
595
  wait: z
591
596
  .boolean()
592
- .default(true)
593
- .describe("Wait for completion (default true, up to 10 min). Set false to get jobId immediately."),
597
+ .default(false)
598
+ .describe("Block until the job finishes (up to 10 min) and return the result. Default false returns the jobId at once; poll summer_check_job."),
594
599
  options: z
595
600
  .record(z.any())
596
601
  .optional()
@@ -616,17 +621,17 @@ Requires authentication: run 'npx -y summer-engine@latest login' first.`, {
616
621
  options: mergedOptions,
617
622
  });
618
623
  if (result.error) {
619
- return errorResult(result.error, result.data);
624
+ return errorResult(result.error, result.data, result);
620
625
  }
621
626
  const jobId = result.data?.jobId;
622
- // If not waiting or no jobId, return immediately
627
+ // The job runs on Summer's servers; the agent polls summer_check_job.
623
628
  if (!wait || !jobId) {
624
- return successResult(result.data);
629
+ return successResult(jobId ? { ...result.data, next: checkJobNext(jobId) } : result.data);
625
630
  }
626
- // Auto-poll until done
631
+ // wait=true: block until done
627
632
  const pollResult = await pollJob(jobId);
628
633
  if (pollResult.error) {
629
- return errorResult(pollResult.error, { ...pollResult.data, jobId });
634
+ return errorResult(pollResult.error, { ...pollResult.data, jobId }, pollResult);
630
635
  }
631
636
  return successResult({
632
637
  ...pollResult.data,
@@ -688,7 +693,7 @@ Requires authentication: run 'npx -y summer-engine@latest login' first.`, {
688
693
  options,
689
694
  });
690
695
  if (result.error) {
691
- return errorResult(result.error, result.data);
696
+ return errorResult(result.error, result.data, result);
692
697
  }
693
698
  return successResult(result.data);
694
699
  });
@@ -697,9 +702,10 @@ Requires authentication: run 'npx -y summer-engine@latest login' first.`, {
697
702
  // ========================================================================
698
703
  server.tool("summer_check_job", `Check the status of an async generation job.
699
704
 
700
- Use this when you called summer_generate_3d with wait=false, or need to re-check
701
- a job that timed out. Most of the time you won't need this — summer_generate_3d
702
- waits automatically.
705
+ summer_generate_3d and summer_generate_motion return a jobId; call this with it
706
+ every 15-30 seconds until status is "completed" or "failed". A completed job
707
+ carries the result: assetId (3D), rigAssetId (rig=true), animationAssetId or
708
+ result.assets (motion), with file URLs. Import with summer_import_asset_by_id.
703
709
 
704
710
  Status values: waiting, active, completed, failed, delayed, unknown.
705
711
 
@@ -709,24 +715,24 @@ Requires authentication: run 'npx -y summer-engine@latest login' first.`, {
709
715
  }, async ({ jobId }) => {
710
716
  const token = await getAuthToken();
711
717
  if (!token) {
712
- return errorResult("Not signed in. Run: npx -y summer-engine@latest login");
718
+ return errorResult(NOT_SIGNED_IN, undefined, { code: "not_signed_in" });
713
719
  }
720
+ let res;
714
721
  try {
715
722
  const gatewayUrl = await resolveGatewayUrl();
716
- const res = await fetch(`${gatewayUrl}/api/mcp/jobs/${encodeURIComponent(jobId)}`, {
717
- headers: { Authorization: `Bearer ${token}` },
723
+ res = await fetch(`${gatewayUrl}/api/mcp/jobs/${encodeURIComponent(jobId)}`, {
724
+ headers: { ...summerRequestHeaders({ surface: "mcp" }), Authorization: `Bearer ${token}` },
718
725
  signal: AbortSignal.timeout(15_000),
719
726
  });
720
- const data = await res.json();
721
- if (!res.ok) {
722
- return errorResult(data.message || data.error || "Failed to check job status", data);
723
- }
724
- return successResult(data);
725
727
  }
726
728
  catch (err) {
727
- const msg = err instanceof Error ? err.message : String(err);
728
- return errorResult(`Job status check failed: ${msg}`);
729
+ return errorResult(`Job status check failed: ${describeNetworkError(err)}`, networkDetails(err), { code: "unavailable" });
730
+ }
731
+ const data = await readLenientJson(res);
732
+ if (!res.ok) {
733
+ return errorResult(data.message || data.error || "Failed to check job status", data, statusFailure(res.status));
729
734
  }
735
+ return successResult(data);
730
736
  });
731
737
  // ========================================================================
732
738
  // summer_generate_motion
@@ -763,9 +769,9 @@ Each clip (meshy: each motion; text-to-motion: each prompt x take) is billed.
763
769
  State the clip list and estimated cost and confirm with the user before
764
770
  spending.
765
771
 
766
- By default, waits for completion (up to 10 min) and returns the result directly.
767
- Set wait=false to get the jobId immediately and poll with summer_check_job.
768
- Import finished clips with summer_import_asset_by_id.
772
+ Returns a jobId within seconds. Poll summer_check_job with it until status is
773
+ "completed" (wait=true blocks up to 10 minutes instead). Import finished clips
774
+ with summer_import_asset_by_id.
769
775
 
770
776
  Errors: backend_unavailable means text-to-motion is not enabled on this server
771
777
  yet — use meshy-library for humanoids and do not retry. Job failures starting
@@ -782,16 +788,16 @@ Requires authentication: run 'npx -y summer-engine@latest login' first.`, motion
782
788
  const result = await mcpGenerate("/api/mcp/generate/motion", built.body);
783
789
  if (result.error) {
784
790
  const hint = motionErrorHint(result.data?.error);
785
- return errorResult(result.error, hint ? { ...result.data, hint } : result.data);
791
+ return errorResult(result.error, hint ? { ...result.data, hint } : result.data, result);
786
792
  }
787
793
  const jobId = result.data?.jobId;
788
794
  if (!args.wait || !jobId) {
789
- return successResult(result.data);
795
+ return successResult(jobId ? { ...result.data, next: checkJobNext(jobId) } : result.data);
790
796
  }
791
797
  const pollResult = await pollJob(jobId);
792
798
  if (pollResult.error) {
793
799
  const hint = motionJobFailureHint(pollResult.error);
794
- return errorResult(pollResult.error, { ...pollResult.data, jobId, ...(hint ? { hint } : {}) });
800
+ return errorResult(pollResult.error, { ...pollResult.data, jobId, ...(hint ? { hint } : {}) }, pollResult);
795
801
  }
796
802
  return successResult({
797
803
  ...pollResult.data,
@@ -5,12 +5,17 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
5
  * share ONE implementation. The MCP surface contributes the boot drift notice
6
6
  * it owns. Exported for tests.
7
7
  */
8
- export declare function buildAgentPlaybook(): Record<string, unknown>;
9
- export declare function renderAgentPlaybook(): string;
8
+ export declare function buildAgentPlaybook(options?: ProjectToolsOptions): Record<string, unknown>;
9
+ export declare function renderAgentPlaybook(options?: ProjectToolsOptions): string;
10
+ /** What the session's profile serves. `engine: false` (the assets profile)
11
+ * turns the playbook and the task plan into their no-engine versions. */
12
+ export interface ProjectToolsOptions {
13
+ engine?: boolean;
14
+ }
10
15
  /**
11
16
  * Register the playbook as an MCP PROMPT as well, so hosts that surface
12
17
  * prompts (prompt pickers, slash commands) get the operating guide natively
13
18
  * without knowing to call the tool. Same content, second doorway.
14
19
  */
15
- export declare function registerPlaybookPrompt(server: McpServer): void;
16
- export declare function registerProjectTools(server: McpServer): void;
20
+ export declare function registerPlaybookPrompt(server: McpServer, options?: ProjectToolsOptions): void;
21
+ export declare function registerProjectTools(server: McpServer, options?: ProjectToolsOptions): void;
@@ -38,37 +38,42 @@ function getScenePathFromSceneState(sceneState) {
38
38
  * share ONE implementation. The MCP surface contributes the boot drift notice
39
39
  * it owns. Exported for tests.
40
40
  */
41
- export function buildAgentPlaybook() {
41
+ export function buildAgentPlaybook(options = {}) {
42
42
  return buildCoreAgentPlaybook({
43
43
  summerUpdateNotice: getCachedBootDriftNotice()?.text ?? null,
44
+ engine: options.engine,
44
45
  });
45
46
  }
46
- export function renderAgentPlaybook() {
47
- return JSON.stringify(buildAgentPlaybook(), null, 2);
47
+ export function renderAgentPlaybook(options = {}) {
48
+ return JSON.stringify(buildAgentPlaybook(options), null, 2);
48
49
  }
49
50
  /**
50
51
  * Register the playbook as an MCP PROMPT as well, so hosts that surface
51
52
  * prompts (prompt pickers, slash commands) get the operating guide natively
52
53
  * without knowing to call the tool. Same content, second doorway.
53
54
  */
54
- export function registerPlaybookPrompt(server) {
55
+ export function registerPlaybookPrompt(server, options = {}) {
55
56
  server.registerPrompt("summer_agent_playbook", {
56
- title: "Summer Engine agent playbook",
57
- description: "AI-first operating guide for the Summer Engine MCP tools: observe-first loop, screenshot before/after every mutation, content routing (reuse -> import -> generate -> script last), physical invariants, cost rules, verification ritual, honesty rules, and recovery steps.",
57
+ title: options.engine === false ? "Summer assets playbook" : "Summer Engine agent playbook",
58
+ description: options.engine === false
59
+ ? "Operating guide for the Summer assets tools without Summer Engine: ask what the asset is for, reuse before generating, confirm spend, check the preview, hand over the file."
60
+ : "AI-first operating guide for the Summer Engine MCP tools: observe-first loop, screenshot before/after every mutation, content routing (reuse -> import -> generate -> script last), physical invariants, cost rules, verification ritual, honesty rules, and recovery steps.",
58
61
  }, async () => ({
59
62
  messages: [
60
63
  {
61
64
  role: "user",
62
65
  content: {
63
66
  type: "text",
64
- text: "Operate Summer Engine by this playbook for the rest of the session:\n\n" +
65
- renderAgentPlaybook(),
67
+ text: (options.engine === false
68
+ ? "Work with the Summer assets tools by this playbook for the rest of the session:\n\n"
69
+ : "Operate Summer Engine by this playbook for the rest of the session:\n\n") +
70
+ renderAgentPlaybook(options),
66
71
  },
67
72
  },
68
73
  ],
69
74
  }));
70
75
  }
71
- export function registerProjectTools(server) {
76
+ export function registerProjectTools(server, options = {}) {
72
77
  server.tool("summer_start_game_task", `Start here for any substantial AI game-building task.
73
78
 
74
79
  Takes the user's goal and returns the recommended Summer workflow: skill routes,
@@ -102,6 +107,7 @@ mutating the project.`, {
102
107
  target,
103
108
  assetPolicy,
104
109
  verification,
110
+ engine: options.engine,
105
111
  }), null, 2),
106
112
  },
107
113
  ],
@@ -115,7 +121,7 @@ ladder, honesty rules, anti-patterns, and recovery steps.`, {}, async () => ({
115
121
  content: [
116
122
  {
117
123
  type: "text",
118
- text: renderAgentPlaybook(),
124
+ text: renderAgentPlaybook(options),
119
125
  },
120
126
  ],
121
127
  }));
@@ -268,42 +268,31 @@ The full read is about 5 KB. To read only what you need, pass fields: property n
268
268
  Two forms, pass exactly one:
269
269
  - path: a resource FILE ('res://materials/ground.tres', a mesh 'res://kit/meshes/wall_01.res', 'res://models/player.glb'), loaded read-only in the editor. A Mesh returns its AABB, surface_count and per surface the primitive, vertex and index counts, attributes, triangles and material (class, path or embedded, albedo for standard materials), plus the unique materials and blend shapes. A scene or model (.tscn/.glb/.gltf) returns its node count, the first 40 nodes with type, instanced scene and mesh, and its meshes; summer_inspect_asset measures it (AABB, planes, ports). Every other resource (and a mesh) returns its editor properties that differ from the class default (props), with props_at_default counting the rest.
270
270
  - nodePath + property: a resource a node of the ACTIVE scene tab holds, e.g. nodePath 'Floor', property 'mesh'. For example, summer_inspect_node tells you a MeshInstance3D has a "StandardMaterial3D" material_override — this form returns its albedo_color, metallic, roughness, etc.`, inspectResourceInputShape, async (args) => withEngine(async (client) => inspectResource(client, args)));
271
- server.tool("summer_batch", `Execute multiple operations in a single call. Each op is forwarded to the engine VERBATIM, so this is also how you reach engine ops that have no dedicated tool.
271
+ server.tool("summer_batch", `Execute multiple operations (a multi-node build) in a single call. Each op is forwarded to the engine VERBATIM: this is also how you reach engine ops without a dedicated tool.
272
272
 
273
- UNDO: when nothing in the list forces a split (see the single-op contract below), the whole batch is ONE undo step — the user undoes everything with a single Ctrl+Z. When single-only ops are present the list is split into sequential requests and EACH chunk is its own undo step (one Ctrl+Z per chunk; the receipt shows the chunks). Use this when building something that involves multiple nodes and properties — e.g., creating a player character with collision, camera, and properties.
273
+ UNDO: when nothing in the list forces a split (see SPLITS), the whole batch is ONE undo step (one Ctrl+Z). Single-only ops split the list into sequential requests, and EACH chunk is its own undo step (the receipt shows the chunks).
274
274
 
275
- Each op in the array uses the same format as the individual tools:
275
+ Ops use the individual tools' format:
276
276
  - {"op": "AddNode", "parent": "/", "type": "MeshInstance3D", "name": "Floor"}
277
277
  - {"op": "SetProp", "path": "Floor", "key": "position", "value": "Vector3(0, -1, 0)"}
278
278
  - {"op": "SetProp", "path": "Floor", "key": "mesh", "value": "PlaneMesh"}
279
279
  - {"op": "SetResourceProperty", "nodePath": "Floor", "resourceProperty": "mesh", "subProperty": "size", "value": "Vector2(20, 20)"}
280
280
 
281
- RAW RUNTIME OPS (interactive verification — structured failure_reason passes through verbatim):
282
- - RunVerification — spawn a hidden, disposable game instance that runs a GDScript probe and dies (never touches the editor): {"op": "RunVerification", "probe_source": "...", "max_seconds": 20}. Returns {ok, results, frames, out_dir}. Probe API: report(name, value) / save_frame(name) / press(action) / key(keycode) / finish(). save_frame REQUIRES a name argument — save_frame() with no args is a script error. Mount scenes deferred: get_tree().root.add_child.call_deferred(instance); await get_tree().process_frame; await settle() — a direct add_child in _ready can hit the parent-busy guard and capture a black frame.
283
- - SimulateInput — inject an action/key/mouse/axis into the RUNNING game (summer_play first): {"op": "SimulateInput", "type": "action", "action": "jump", "pressed": true}. It MUST be sent alone (single-op batch). failure_reason "not_running" = start the game first; "unsupported" = the running game build predates the handler — fall back to RunVerification or ask the user.
281
+ SPLITS AND SAVE: scenePath selects every mutation target. Send OpenScene (a UI action) separately, never mixed with scene mutations. The tool appends one final SaveScene when the batch mutates a scene; a SaveScene you supply must appear exactly once, as the final op. The engine requires SaveScene, InstantiateScene, ReplaceNode, SimulateInput, the runtime reads (GetRuntimeSceneTree/GetRuntimeNode) and the Run*/Import* ops to travel alone, so the tool splits the list around them; if a later chunk fails, the receipt names the earlier ops that already applied.
284
282
 
285
- A raw ReplaceNode with scene is refused (it saves the old scene reference); use summer_replace_node.
286
- A raw ConnectSignal is refused (the engine connects without CONNECT_PERSIST, so the file never holds it); use summer_connect_signal.
283
+ RAW RUNTIME OPS (structured failure_reason passes through verbatim):
284
+ - RunVerification: a hidden, disposable game instance runs a GDScript probe and dies, never touching the editor: {"op": "RunVerification", "probe_source": "...", "max_seconds": 20} returns {ok, results, frames, out_dir}. Probe API: report(name, value) / save_frame(name) / press(action) / key(keycode) / finish(); save_frame() without a name is a script error. Mount scenes deferred (add_child.call_deferred) or the capture can be black; summer_get_agent_playbook has the probe rules.
285
+ - SimulateInput: inject an action/key/mouse/axis into the RUNNING game (summer_play first), sent ALONE: {"op": "SimulateInput", "type": "action", "action": "jump", "pressed": true}. failure_reason "not_running" = start the game first; "unsupported" = the game build predates the handler: use RunVerification or ask the user.
287
286
 
288
- REPARENTNODE KEEPS ITS SUBTREE AND IS VERIFIED: the engine's ReparentNode re-owns only the moved node, so its children and grandchildren were dropped from the saved file. A batch with ReparentNode saves first, reads the saved .tscn, sends each ReparentNode in its own request with an in-place ReparentNode (same parent, same index) per scene-owned descendant to give it back to the scene, then reads the saved file again: persisted:true / verified:true only when every moved node and descendant is at its new path; otherwise an error with failure_reason not_persisted. A move onto a parent that already has a child of that name is refused (failure_reason name_collision). The scenePath must be a .tscn, and Undo cannot share the batch.
287
+ REFUSED: a raw ReplaceNode with scene (it saves the old scene reference; use summer_replace_node) and a raw ConnectSignal (no CONNECT_PERSIST, so the file never holds it; use summer_connect_signal).
289
288
 
290
- Do not mix OpenScene with scene mutations in one batch. OpenScene is a UI action;
291
- send it separately. scenePath selects every mutation target. The tool appends one
292
- final SaveScene when the batch mutates a scene; if supplied explicitly, SaveScene
293
- must appear exactly once and be the final operation. The engine requires
294
- SaveScene, InstantiateScene, ReplaceNode, SimulateInput, the runtime reads
295
- (GetRuntimeSceneTree/GetRuntimeNode), and the Run*/Import*
296
- ops to travel as their own request, so this tool automatically splits your op
297
- list into sequential requests around them — each split chunk is its own undo
298
- step (NOT one step for the whole batch), and if a later chunk fails the receipt
299
- reports exactly which earlier ops already applied.
289
+ REPARENTNODE KEEPS ITS SUBTREE AND IS VERIFIED: the engine op re-owns only the moved node and drops its descendants from the saved file, so the tool saves, sends each ReparentNode alone plus an in-place ReparentNode per scene-owned descendant, then reads the saved .tscn back: persisted:true / verified:true only when every moved node and descendant is at its new path, else failure_reason not_persisted. A move onto a parent with a same-named child is refused (name_collision). scenePath must be a .tscn; Undo cannot share the batch.
300
290
 
301
- PLACED INSTANCES: an InstantiateScene op may also carry position, rotation_degrees, scale ([x, y, z] or "Vector3(...)") or transform ("Transform3D(...)"); the tool sets them on the created node. One op per piece. Other ops are forwarded verbatim. Cost: each InstantiateScene is its own engine request (the engine requires it); the transforms of a run of InstantiateScene ops are then sent together (up to 200 per request) before the next other op, so N placed pieces plus the save cost about N + 2 requests and N + 2 undo steps. Every later op (a SetProp, SnapToSurface, the save) sees the pieces already placed; if an InstantiateScene fails, the pieces created before it still get their transforms.
291
+ PLACED INSTANCES: an InstantiateScene op may carry position, rotation_degrees, scale ([x, y, z] or "Vector3(...)") or transform ("Transform3D(...)"), set on the created node; one op per piece. Each InstantiateScene is its own request and the transforms of a run follow together (up to 200 per request), so N pieces plus the save cost about N + 2 requests and undo steps. Later ops (SetProp, SnapToSurface, the save) see the pieces placed; if one fails, the pieces before it still get their transforms.
302
292
 
303
- RECEIPTS: receipt "summary" returns only counts, failures [{index, op, error}] (index = position in your ops list), created node paths and renames, under 5 KB with any cut declared. Use it for any batch over a few ops; the full receipt of a large batch overflows the tool-output limit.
293
+ RECEIPTS: receipt "summary" returns only counts, failures [{index, op, error}] (index into your ops), created node paths and renames, under 5 KB with any cut declared. Use it for any batch over a few ops: a large full receipt overflows the tool-output limit.
304
294
 
305
- scenePersistence.saved means the SaveScene ran; it does not prove what the file
306
- holds. verified:true is set only where the tool read the saved file back.`, {
295
+ scenePersistence.saved means the SaveScene ran, not what the file holds; verified:true is set only where the tool read the file back.`, {
307
296
  scenePath: z.string().optional().describe("Required when ops contains scene mutations; exact res:// target scene path"),
308
297
  ops: z.array(z.record(z.unknown())).describe("Array of operation objects, each with 'op' plus its parameters"),
309
298
  receipt: z