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
@@ -27,6 +27,7 @@
27
27
  import { existsSync, readFileSync } from "node:fs";
28
28
  import { join } from "node:path";
29
29
  import { z } from "zod";
30
+ import { summerRequestHeaders } from "./agent-host.js";
30
31
  import { getAuthToken } from "./auth.js";
31
32
  import { resolveGatewayUrl } from "./config.js";
32
33
  import { EMBED_PATH, EMBEDDINGS_FILE, cosineSimilarity, createEmbedProvider, decodeVector, parseEmbeddingsFile, reciprocalRankFusion, } from "./embeddings.js";
@@ -167,7 +168,7 @@ export async function embedQueryWithConfiguredProvider(query, env = process.env)
167
168
  catch {
168
169
  token = null;
169
170
  }
170
- const provider = createEmbedProvider({ url, token, timeoutMs: QUERY_EMBED_TIMEOUT_MS });
171
+ const provider = createEmbedProvider({ url, token, timeoutMs: QUERY_EMBED_TIMEOUT_MS, headers: summerRequestHeaders() });
171
172
  return (await provider(query)).vector;
172
173
  }
173
174
  catch {
@@ -115,6 +115,10 @@ async function postForm(deps, url, form) {
115
115
  const body = (json && typeof json === "object" ? json : {});
116
116
  if (!response.ok) {
117
117
  const reason = typeof body.error === "string" ? body.error : `http_${response.status}`;
118
+ // A 5xx is the sign-in server failing, not the sign-in being wrong.
119
+ if (response.status >= 500) {
120
+ throw new OAuthError("oauth_server_failed", `The sign-in server failed (${reason}).`, "Recovery: try again in a minute.");
121
+ }
118
122
  throw new OAuthError(reason === "invalid_grant" ? "oauth_grant_invalid" : "oauth_token_refused", `The sign-in server refused the token request (${reason}).`, 'Recovery: run "summer login --store --force" and approve access again.');
119
123
  }
120
124
  return body;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Where operations live and run, the part scripts/ needs too. No imports:
3
+ * scripts/validate-library loads this file as plain TypeScript to write the
4
+ * shell command of each tool a skill names.
5
+ */
6
+ /**
7
+ * Areas with operations today: each is one `summer <area> <action>` command
8
+ * (src/cli/commands/ops.ts). CLI command words stay out of this list.
9
+ */
10
+ export declare const CLI_AREAS: readonly ["team", "profile", "docs", "assets", "makers", "jobs", "projects", "plans", "games", "store", "jams", "pricing", "analytics", "experiments", "marketing", "content", "players", "economy", "inbox", "apps", "studio", "chats", "stories", "plugins", "engine", "account"];
11
+ export declare function isLocalOp(op: string): boolean;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Where operations live and run, the part scripts/ needs too. No imports:
3
+ * scripts/validate-library loads this file as plain TypeScript to write the
4
+ * shell command of each tool a skill names.
5
+ */
6
+ /**
7
+ * Areas with operations today: each is one `summer <area> <action>` command
8
+ * (src/cli/commands/ops.ts). CLI command words stay out of this list.
9
+ */
10
+ export const CLI_AREAS = [
11
+ "team", "profile", "docs", "assets", "makers", "jobs", "projects", "plans", "games", "store", "jams", "pricing",
12
+ "analytics", "experiments", "marketing", "content", "players", "economy", "inbox", "apps", "studio", "chats", "stories",
13
+ "plugins", "engine", "account",
14
+ ];
15
+ /**
16
+ * Operations that run in this package: everything in `engine`, the library
17
+ * (`docs`, apart from the Studio workflows, which are cloud), opening a
18
+ * page or an editor surface, docking an App in the editor, and uploading a
19
+ * local export. Everything else runs on the hosted server.
20
+ */
21
+ const LOCAL_OPS = new Set(["docs.search", "docs.read", "docs.feedback", "docs.plan", "docs.engine_api", "studio.open", "apps.dock", "apps.publish_folder", "store.upload_file"]);
22
+ export function isLocalOp(op) {
23
+ return op.startsWith("engine.") || LOCAL_OPS.has(op);
24
+ }
@@ -0,0 +1,45 @@
1
+ import { type Approval, type Effect, type Provider } from "./contract.js";
2
+ /**
3
+ * One searchable row per operation, the same shape the hosted server's
4
+ * summer_search answers with, so local and cloud hits merge into one list.
5
+ */
6
+ export interface CatalogEntry {
7
+ name: string;
8
+ title: string;
9
+ summary: string;
10
+ effect: Effect;
11
+ approval: Approval;
12
+ provider: Provider;
13
+ status: "stable" | "preview" | "deprecated";
14
+ available: boolean;
15
+ /** The MCP tool that runs it directly in this session, when there is one. */
16
+ mcpTool?: string;
17
+ tags?: string[];
18
+ legacy?: string[];
19
+ /** The exact input JSON Schema (search results and describe carry it). */
20
+ input?: Record<string, unknown>;
21
+ /** A cloud operation listed from the shipped catalog while no one is signed in: it runs after `summer login`. */
22
+ needsSignIn?: true;
23
+ /** Search words only, never printed: the library's topics for docs.search ("add multiplayer" is a how-to). */
24
+ topics?: string[];
25
+ }
26
+ /**
27
+ * The operations this package runs (engine and local), from the shipped
28
+ * library index and legacy-names.json. Their MCP tool is the 3.x name the
29
+ * local server registers (engine tools keep their names in 4.0), except the
30
+ * operations split out of a mixed 3.x tool (engine.ts), which are their own.
31
+ */
32
+ export declare function localEntries(): CatalogEntry[];
33
+ /** The input JSON Schema of a local operation, from its library descriptor (a split operation: cut from its tool's). */
34
+ export declare function localInputSchema(op: string): Record<string, unknown> | null;
35
+ /**
36
+ * A local operation in the contract's wire form (registry/schemas/operation.schema.json):
37
+ * what ops.describe answers and what the contract test validates.
38
+ */
39
+ export declare function localWireForm(op: string): Record<string, unknown> | null;
40
+ /**
41
+ * The first problem a JSON Schema's top level finds in an input: a missing
42
+ * required field or, when the schema is closed, an unknown one. Null when
43
+ * there is none (deeper checks are the tool's own).
44
+ */
45
+ export declare function missingInput(schema: Record<string, unknown> | null, input: Record<string, unknown>): string | null;
@@ -0,0 +1,157 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { parse as parseYaml } from "yaml";
4
+ import { loadLibraryIndex } from "../library-search.js";
5
+ import { PACKAGE_ROOT } from "../package-root.js";
6
+ import { CONTRACT_VERSION, isLocalOp, legacyNames, LOCAL_RUNNERS, mcpNameOf, MIN_APPROVAL } from "./contract.js";
7
+ import { ENGINE_SPLIT_OPS, engineOpDef, isSplitOp, splitInputSchema } from "./engine.js";
8
+ import { shippedTitle } from "./public-catalog.js";
9
+ /** A local tool's effect from its registry authority: scene edits and project files are writes. */
10
+ function effectOf(authority) {
11
+ if (authority?.publish)
12
+ return "publish";
13
+ if (authority?.editor_mutation || authority?.filesystem || authority?.credentials)
14
+ return "write";
15
+ return "read";
16
+ }
17
+ const titleOf = (summary, op) => {
18
+ const sentence = summary.split(/(?<=\.)\s/)[0]?.replace(/\.$/, "") ?? "";
19
+ return sentence && sentence.length <= 60 ? sentence : op.replace(/^[a-z]+\./, "").replace(/_/g, " ").replace(/^./, (c) => c.toUpperCase());
20
+ };
21
+ let entriesCache = null;
22
+ function entryFor(op, toolName, tool, legacy) {
23
+ // Engine operations carry their own title, summary and effect (engine.ts);
24
+ // other local operations fall back to the descriptor.
25
+ const def = engineOpDef(op);
26
+ const effect = def?.effect ?? effectOf(tool.authority);
27
+ const summary = def?.summary ?? (tool.summary ?? "").slice(0, 300);
28
+ return {
29
+ name: op,
30
+ // The hosted catalog's title when it has the op too (docs.search: "Search Summer docs", not "Search").
31
+ title: def?.title ?? shippedTitle(op) ?? titleOf(summary, op),
32
+ summary,
33
+ effect,
34
+ approval: MIN_APPROVAL[effect],
35
+ provider: op.startsWith("engine.") ? "engine" : "local",
36
+ status: tool.status === "preview" ? "preview" : "stable",
37
+ available: true,
38
+ // A split operation is its own tool; every other one runs under its 3.x name.
39
+ mcpTool: isSplitOp(op) ? mcpNameOf(op) : toolName,
40
+ tags: [...(tool.use_when ?? []), ...(tool.facets?.domains ?? [])],
41
+ legacy: [legacy],
42
+ };
43
+ }
44
+ /**
45
+ * The operations this package runs (engine and local), from the shipped
46
+ * library index and legacy-names.json. Their MCP tool is the 3.x name the
47
+ * local server registers (engine tools keep their names in 4.0), except the
48
+ * operations split out of a mixed 3.x tool (engine.ts), which are their own.
49
+ */
50
+ export function localEntries() {
51
+ if (entriesCache)
52
+ return entriesCache;
53
+ const tools = new Map(loadLibraryIndex().filter((entry) => entry.kind === "tool" && entry.mcp_tool_name).map((entry) => [entry.mcp_tool_name, entry]));
54
+ const out = new Map();
55
+ // The tool an operation was renamed from comes before the tools merged into it;
56
+ // then the local operations a 3.x tool runs although its 3.x name maps to a cloud one.
57
+ const rows = [
58
+ ...Object.entries(legacyNames()).sort(([, a], [, b]) => Number(a.kind === "merge") - Number(b.kind === "merge")),
59
+ ...Object.entries(LOCAL_RUNNERS).map(([op, name]) => [name, { op }]),
60
+ ];
61
+ for (const [name, row] of rows) {
62
+ if (!isLocalOp(row.op) || out.has(row.op))
63
+ continue;
64
+ const toolName = name.split("#")[0];
65
+ const tool = tools.get(toolName);
66
+ if (!tool)
67
+ continue;
68
+ if (name.includes("#") && !isSplitOp(row.op))
69
+ continue;
70
+ out.set(row.op, entryFor(row.op, toolName, tool, name));
71
+ }
72
+ const docsSearch = out.get("docs.search");
73
+ if (docsSearch)
74
+ out.set("docs.search", { ...docsSearch, topics: libraryTopics() });
75
+ entriesCache = [...out.values()];
76
+ return entriesCache;
77
+ }
78
+ /** The words of every skill, template and example slug (multiplayer, fps, lighting...): what the library teaches. */
79
+ function libraryTopics() {
80
+ const slugs = loadLibraryIndex()
81
+ .filter((entry) => entry.kind !== "tool" && entry.kind !== "reference")
82
+ .flatMap((entry) => entry.id.replace(/^[a-z]+\//, "").split("-"));
83
+ return [...new Set(slugs)].filter((word) => word.length > 2 && !/^\d/.test(word));
84
+ }
85
+ function descriptorSchema(toolName) {
86
+ const record = loadLibraryIndex().find((candidate) => candidate.kind === "tool" && candidate.mcp_tool_name === toolName);
87
+ const slug = record?.id.replace(/^tool\//, "");
88
+ if (!slug)
89
+ return null;
90
+ try {
91
+ const descriptor = parseYaml(readFileSync(join(PACKAGE_ROOT, "library", "tools", slug, "resource.yaml"), "utf8"));
92
+ return descriptor.input_schema ?? null;
93
+ }
94
+ catch {
95
+ return null;
96
+ }
97
+ }
98
+ /** The input JSON Schema of a local operation, from its library descriptor (a split operation: cut from its tool's). */
99
+ export function localInputSchema(op) {
100
+ const split = ENGINE_SPLIT_OPS[op];
101
+ if (split)
102
+ return splitInputSchema(split, descriptorSchema(split.tool));
103
+ const toolName = localEntries().find((candidate) => candidate.name === op)?.mcpTool;
104
+ return toolName ? descriptorSchema(toolName) : null;
105
+ }
106
+ /**
107
+ * A local operation in the contract's wire form (registry/schemas/operation.schema.json):
108
+ * what ops.describe answers and what the contract test validates.
109
+ */
110
+ export function localWireForm(op) {
111
+ const entry = localEntries().find((candidate) => candidate.name === op);
112
+ if (!entry)
113
+ return null;
114
+ const def = engineOpDef(op);
115
+ const legacy = Object.entries(legacyNames())
116
+ .filter(([, row]) => row.op === op)
117
+ .map(([name]) => name)
118
+ .sort();
119
+ return {
120
+ contract: CONTRACT_VERSION,
121
+ name: op,
122
+ title: entry.title,
123
+ summary: entry.summary,
124
+ effect: entry.effect,
125
+ approval: entry.approval,
126
+ provider: entry.provider,
127
+ auth: def?.auth ?? "none",
128
+ input: localInputSchema(op) ?? { type: "object" },
129
+ output: { type: "object" },
130
+ ...(legacy.length ? { legacy } : {}),
131
+ ...(entry.mcpTool && entry.mcpTool !== mcpNameOf(op) ? { mcpName: entry.mcpTool } : {}),
132
+ status: entry.status,
133
+ since: "4.0",
134
+ ...(entry.tags?.length ? { tags: entry.tags } : {}),
135
+ examples: def ? [def.example] : [{ input: {}, note: entry.title }],
136
+ };
137
+ }
138
+ /**
139
+ * The first problem a JSON Schema's top level finds in an input: a missing
140
+ * required field or, when the schema is closed, an unknown one. Null when
141
+ * there is none (deeper checks are the tool's own).
142
+ */
143
+ export function missingInput(schema, input) {
144
+ if (!schema)
145
+ return null;
146
+ const properties = (schema.properties ?? {});
147
+ const required = Array.isArray(schema.required) ? schema.required : [];
148
+ const absent = required.find((field) => input[field] === undefined);
149
+ if (absent)
150
+ return `${absent}: required.`;
151
+ if (schema.additionalProperties === false) {
152
+ const unknown = Object.keys(input).find((field) => !(field in properties));
153
+ if (unknown)
154
+ return `${unknown}: not a field of this operation.`;
155
+ }
156
+ return null;
157
+ }
@@ -0,0 +1,64 @@
1
+ import { type HostedConnectDependencies } from "../hosted-mcp.js";
2
+ import { type CatalogEntry } from "./catalog.js";
3
+ import { type Answer } from "./contract.js";
4
+ /**
5
+ * The hosted Summer server's v4 surface: the same address with `?surface=v4`
6
+ * (it keeps serving 3.x tools to every request that does not ask). Cloud
7
+ * operations run there with the person's sign-in (summer login). The assets
8
+ * profile also asks for its own direct tools (`profile=assets`: the asset
9
+ * reads and generators, jobs and whoami); every other profile gets the
10
+ * hosted set.
11
+ */
12
+ export declare function withV4Surface(url: string, profile?: string): string;
13
+ /** Where a profile's v4 session mounts the hosted server. */
14
+ export declare function v4HostedUrl(profile?: string): () => string;
15
+ export declare const v4HostedDependencies: HostedConnectDependencies;
16
+ /**
17
+ * One call to a tool on the hosted v4 surface (the CLI's path; the MCP uses
18
+ * its mounted client). A failure before the call is sent is an OAuthError
19
+ * (sign-in) or a HostedUnreachableError; one after it may have run.
20
+ */
21
+ export declare function callHostedV4(name: string, args: Record<string, unknown>, deps?: HostedConnectDependencies): Promise<Record<string, unknown>>;
22
+ /** True for operations that only read (`games.list`, `jobs.wait`, `whoami`). */
23
+ export declare function isReadOp(op: string): boolean;
24
+ /**
25
+ * The one answer for a hosted call that threw, decided by what is known to
26
+ * have happened:
27
+ * - a sign-in problem (an OAuthError, a 401) is not_signed_in; an account
28
+ * the server refuses (403) is forbidden;
29
+ * - nothing sent (never connected, connection refused, a 503 or another 4xx
30
+ * the server answers before it runs anything) is unavailable;
31
+ * - a call cut off after it was sent may have run: outcome_unknown, retried
32
+ * only with the same idempotencyKey, else checked first. A read or a dry
33
+ * run changes nothing, so a cut-off one is unavailable.
34
+ */
35
+ export declare function hostedCallFailure(error: unknown, call: {
36
+ op: string;
37
+ dryRun?: boolean;
38
+ idempotencyKey?: string;
39
+ read?: boolean;
40
+ }): Answer;
41
+ /** The answer a hosted v4 tool result carries (its JSON text), or the one error shape. */
42
+ export declare function answerOfHosted(result: Record<string, unknown>): Answer;
43
+ /** Runs a tool on the hosted v4 surface: the MCP's mounted client or the CLI's one-shot call. */
44
+ export type HostedCall = (name: string, args: Record<string, unknown>) => Promise<Record<string, unknown>>;
45
+ /**
46
+ * ops.describe of a cloud operation when Summer's server could not answer it
47
+ * (no sign-in, no network): the operation from the shipped catalog, with a
48
+ * warning. Null when the catalog has no such operation; the failure stands.
49
+ */
50
+ export declare function describeFromShipped(name: string, failure: Answer): Answer | null;
51
+ /**
52
+ * One ranked list of local and cloud operations for a plain-words query.
53
+ * Every cloud operation comes from the shipped catalog (public-catalog.ts),
54
+ * so search finds it signed out, marked needsSignIn; signed in, the server's
55
+ * own search lays its live rows over the shipped ones (and adds newer
56
+ * operations). Local hits carry their input schema from the library descriptor.
57
+ */
58
+ export declare function searchEverywhere(query: string, filters: {
59
+ area?: string;
60
+ limit: number;
61
+ }, call: HostedCall, isDirect?: (toolName: string) => boolean): Promise<{
62
+ items: CatalogEntry[];
63
+ warning: string | null;
64
+ }>;
@@ -0,0 +1,198 @@
1
+ import { defaultHostedConnectDependencies, hostedConnectFailure, HostedUnreachableError, httpStatusOf } from "../hosted-mcp.js";
2
+ import { OAuthError, resolveMcpResourceUrl } from "../oauth.js";
3
+ import { localEntries, localInputSchema } from "./catalog.js";
4
+ import { errorAnswer, isLocalOp, resolveOpName } from "./contract.js";
5
+ import { shippedCloudEntries, shippedWireForm } from "./public-catalog.js";
6
+ import { withOutField } from "./save-files.js";
7
+ import { searchEntries } from "./search.js";
8
+ /**
9
+ * The hosted Summer server's v4 surface: the same address with `?surface=v4`
10
+ * (it keeps serving 3.x tools to every request that does not ask). Cloud
11
+ * operations run there with the person's sign-in (summer login). The assets
12
+ * profile also asks for its own direct tools (`profile=assets`: the asset
13
+ * reads and generators, jobs and whoami); every other profile gets the
14
+ * hosted set.
15
+ */
16
+ export function withV4Surface(url, profile) {
17
+ const parsed = new URL(url);
18
+ parsed.searchParams.set("surface", "v4");
19
+ if (profile === "assets")
20
+ parsed.searchParams.set("profile", "assets");
21
+ return parsed.href;
22
+ }
23
+ /** Where a profile's v4 session mounts the hosted server. */
24
+ export function v4HostedUrl(profile) {
25
+ return () => withV4Surface(resolveMcpResourceUrl(), profile);
26
+ }
27
+ export const v4HostedDependencies = {
28
+ ...defaultHostedConnectDependencies,
29
+ url: v4HostedUrl(),
30
+ };
31
+ /**
32
+ * One call to a tool on the hosted v4 surface (the CLI's path; the MCP uses
33
+ * its mounted client). A failure before the call is sent is an OAuthError
34
+ * (sign-in) or a HostedUnreachableError; one after it may have run.
35
+ */
36
+ export async function callHostedV4(name, args, deps = v4HostedDependencies) {
37
+ let client;
38
+ try {
39
+ const url = deps.url();
40
+ await deps.token();
41
+ client = await deps.connect(url, deps.token);
42
+ }
43
+ catch (error) {
44
+ throw hostedConnectFailure(error, "Recovery: check the network and try again.");
45
+ }
46
+ try {
47
+ return await client.callTool({ name, arguments: args });
48
+ }
49
+ finally {
50
+ await client.close?.().catch(() => undefined);
51
+ }
52
+ }
53
+ /** OAuth failures that mean a server did not answer, not that the person must sign in again. */
54
+ const OAUTH_UNREACHABLE = new Set(["oauth_network_failed", "oauth_discovery_failed", "oauth_server_failed"]);
55
+ /** Connection errors raised before a request is written: nothing reached the server. */
56
+ const NOT_SENT_CAUSES = new Set(["ECONNREFUSED", "ENOTFOUND", "EAI_AGAIN", "UND_ERR_CONNECT_TIMEOUT"]);
57
+ /** Actions that only read; a cut-off read can simply run again. */
58
+ const READ_ACTIONS = new Set(["list", "get", "search", "describe", "status", "wait"]);
59
+ /** True for operations that only read (`games.list`, `jobs.wait`, `whoami`). */
60
+ export function isReadOp(op) {
61
+ return op === "whoami" || READ_ACTIONS.has(op.split(".")[1] ?? "");
62
+ }
63
+ function causeCode(error) {
64
+ for (let e = error, depth = 0; e && depth < 4; e = e.cause, depth++) {
65
+ const code = e.code;
66
+ if (typeof code === "string")
67
+ return code;
68
+ }
69
+ return undefined;
70
+ }
71
+ /**
72
+ * The one answer for a hosted call that threw, decided by what is known to
73
+ * have happened:
74
+ * - a sign-in problem (an OAuthError, a 401) is not_signed_in; an account
75
+ * the server refuses (403) is forbidden;
76
+ * - nothing sent (never connected, connection refused, a 503 or another 4xx
77
+ * the server answers before it runs anything) is unavailable;
78
+ * - a call cut off after it was sent may have run: outcome_unknown, retried
79
+ * only with the same idempotencyKey, else checked first. A read or a dry
80
+ * run changes nothing, so a cut-off one is unavailable.
81
+ */
82
+ export function hostedCallFailure(error, call) {
83
+ const known = error instanceof OAuthError || error instanceof HostedUnreachableError;
84
+ const cause = known ? error.message.replace(` ${error.recovery}`, "") : error instanceof Error ? error.message : String(error);
85
+ const status = httpStatusOf(error);
86
+ const details = { was: error instanceof OAuthError ? error.code : error instanceof HostedUnreachableError ? "unreachable" : status !== undefined ? `http_${status}` : causeCode(error) ?? "no_answer" };
87
+ // A bad SUMMER_MCP_RESOURCE: nothing was sent, and signing in again would not help.
88
+ if (error instanceof OAuthError && error.code === "oauth_resource_invalid") {
89
+ return errorAnswer("unavailable", cause, { retry: "no", next: { say: error.recovery.replace(/^Recovery:\s*/, "") }, details });
90
+ }
91
+ if (status === 401 || (error instanceof OAuthError && !OAUTH_UNREACHABLE.has(error.code) && error.code !== "store_access_denied") || (!known && /invalid_token/.test(cause))) {
92
+ // A missing store sign-in needs a sign-in; an expired or refused one needs a fresh store sign-in.
93
+ const fresh = !(error instanceof OAuthError && error.code === "store_login_required");
94
+ return errorAnswer("not_signed_in", `Cloud operations need the Summer sign-in: ${cause}`, { next: { say: fresh ? "Run: npx -y summer-engine login --store --force" : "Run: npx -y summer-engine login" }, details });
95
+ }
96
+ if (status === 403 || (error instanceof OAuthError && error.code === "store_access_denied")) {
97
+ return errorAnswer("forbidden", error instanceof OAuthError ? cause : `Summer's hosted server refused this account: ${cause}`, { next: { say: "Check the account in Summer Studio (for example confirm the email), then try again." }, details });
98
+ }
99
+ if (status === 429) {
100
+ return errorAnswer("rate_limited", `Summer's hosted server asked to slow down: ${cause}`, { next: { say: "Wait a minute, then call it again." }, details });
101
+ }
102
+ const notSent = known || status === 503 || (status !== undefined && status >= 400 && status < 500) || NOT_SENT_CAUSES.has(causeCode(error) ?? "");
103
+ if (notSent) {
104
+ const rejected = status !== undefined && status >= 400 && status < 500;
105
+ return errorAnswer("unavailable", `Summer's hosted server did not run ${call.op}: ${cause}`, {
106
+ retry: rejected ? "no" : "after",
107
+ next: { say: rejected ? "Summer's hosted server refused the request. If it repeats, report it to Summer with this message." : "Try again in a minute. If it repeats, check the network." },
108
+ details,
109
+ });
110
+ }
111
+ if (call.dryRun || call.read || isReadOp(call.op)) {
112
+ return errorAnswer("unavailable", `Summer's hosted server did not answer ${call.op} in time: ${cause}`, { retry: "safe", next: { say: "Call it again; it only reads." }, details });
113
+ }
114
+ return call.idempotencyKey
115
+ ? errorAnswer("outcome_unknown", `Summer's hosted server did not answer in time, so it is not known whether ${call.op} ran: ${cause}`, {
116
+ retry: "same_key",
117
+ next: { say: "Call it again with the same idempotencyKey: Summer runs a change once per key." },
118
+ details,
119
+ })
120
+ : errorAnswer("outcome_unknown", `Summer's hosted server did not answer in time, so it is not known whether ${call.op} ran: ${cause}`, {
121
+ retry: "no",
122
+ next: { say: "Check what it would have changed (or jobs.list) before you try again." },
123
+ details,
124
+ });
125
+ }
126
+ /** The answer a hosted v4 tool result carries (its JSON text), or the one error shape. */
127
+ export function answerOfHosted(result) {
128
+ const content = Array.isArray(result.content) ? result.content : [];
129
+ const first = content.find((part) => part.type === "text" && typeof part.text === "string")?.text ?? "";
130
+ try {
131
+ const parsed = JSON.parse(first);
132
+ if (parsed && typeof parsed === "object" && "ok" in parsed)
133
+ return parsed;
134
+ }
135
+ catch {
136
+ // not an answer: fall through
137
+ }
138
+ if (/summer_(call|search)\b.*(not found|disabled)/i.test(first)) {
139
+ return errorAnswer("unavailable", "The Summer server's operation catalog is not switched on yet.", { next: { say: "Use the 3.x tools for now: summer mcp --surface v3 (or SUMMER_SURFACE=v3)." } });
140
+ }
141
+ return result.isError === true ? errorAnswer("unavailable", first.slice(0, 300) || "The Summer server did not answer.") : { ok: true, status: "done", result: { text: first } };
142
+ }
143
+ /** Failures that mean Summer's server did not describe the operation, so the shipped catalog may. */
144
+ const DID_NOT_ANSWER = new Set(["not_signed_in", "forbidden", "rate_limited", "unavailable"]);
145
+ /**
146
+ * ops.describe of a cloud operation when Summer's server could not answer it
147
+ * (no sign-in, no network): the operation from the shipped catalog, with a
148
+ * warning. Null when the catalog has no such operation; the failure stands.
149
+ */
150
+ export function describeFromShipped(name, failure) {
151
+ // The server's own answer stands (not_found: it no longer has the operation).
152
+ if (failure.ok || !DID_NOT_ANSWER.has(failure.error.code))
153
+ return null;
154
+ const operation = shippedWireForm(resolveOpName(name));
155
+ if (!operation)
156
+ return null;
157
+ const warning = failure.error.code === "not_signed_in"
158
+ ? "Not signed in: this is the catalog in this version; the operation runs after `summer login`."
159
+ : `Summer's server did not answer (${failure.error.message}); this is the catalog in this version.`;
160
+ return { ok: true, status: "done", result: { operation }, warnings: [warning] };
161
+ }
162
+ /** The warning when cloud operations come from the shipped catalog, and whether that is because no one is signed in. */
163
+ function shippedReason(answer) {
164
+ if (!answer.ok && answer.error.code === "not_signed_in") {
165
+ return { warning: "Not signed in: cloud operations are listed from the catalog in this version and run after `summer login` (needsSignIn).", signedOut: true };
166
+ }
167
+ return { warning: `Cloud operations are listed from the catalog in this version; Summer's server did not search: ${answer.ok ? "no answer" : answer.error.message}`, signedOut: false };
168
+ }
169
+ /**
170
+ * One ranked list of local and cloud operations for a plain-words query.
171
+ * Every cloud operation comes from the shipped catalog (public-catalog.ts),
172
+ * so search finds it signed out, marked needsSignIn; signed in, the server's
173
+ * own search lays its live rows over the shipped ones (and adds newer
174
+ * operations). Local hits carry their input schema from the library descriptor.
175
+ */
176
+ export async function searchEverywhere(query, filters, call, isDirect = () => false) {
177
+ let live = [];
178
+ let reason = null;
179
+ try {
180
+ const answer = answerOfHosted(await call("summer_search", { query, ...(filters.area ? { area: filters.area } : {}), limit: 20 }));
181
+ if (answer.ok && answer.status === "done")
182
+ live = (answer.result.items ?? []).filter((entry) => !isLocalOp(entry.name));
183
+ else
184
+ reason = shippedReason(answer);
185
+ }
186
+ catch (error) {
187
+ reason = shippedReason(hostedCallFailure(error, { op: "ops.search", read: true }));
188
+ }
189
+ const cloud = new Map(shippedCloudEntries().map((entry) => [entry.name, reason?.signedOut ? { ...entry, needsSignIn: true } : entry]));
190
+ // The operations that save files take `out` here (save-files.ts), so their input shows it.
191
+ for (const entry of live) {
192
+ cloud.set(entry.name, { ...cloud.get(entry.name), ...entry, ...(entry.input ? { input: withOutField(entry.name, entry.input) } : {}) });
193
+ }
194
+ const items = searchEntries([...localEntries(), ...cloud.values()], query, filters).map(({ topics: _topics, ...entry }) => isLocalOp(entry.name)
195
+ ? { ...entry, input: localInputSchema(entry.name) ?? { type: "object" }, mcpTool: entry.mcpTool && isDirect(entry.mcpTool) ? entry.mcpTool : undefined }
196
+ : entry);
197
+ return { items, warning: reason?.warning ?? null };
198
+ }
@@ -0,0 +1,120 @@
1
+ import { isLocalOp } from "./areas.js";
2
+ /**
3
+ * The Summer operation catalog, the part this package needs (contract 1).
4
+ * Every Summer operation has one name (`area.action`), one effect, one
5
+ * approval rule and one answer shape; the MCP surface, the CLI and the
6
+ * store profiles are views of it. The machine contract is
7
+ * registry/schemas/operation.schema.json; old 3.x tool names map to
8
+ * operations in registry/operations/legacy-names.json.
9
+ *
10
+ * Engine and local operations run in this package. Cloud operations run on
11
+ * the hosted Summer server; this package reaches them through its v4
12
+ * surface (summer_search, summer_call) with the person's sign-in.
13
+ */
14
+ export declare const CONTRACT_VERSION = 1;
15
+ export declare const EFFECTS: readonly ["read", "write", "spend", "publish", "player_facing", "destructive"];
16
+ export type Effect = (typeof EFFECTS)[number];
17
+ export type Approval = "none" | "confirm" | "owner";
18
+ export type Provider = "engine" | "local" | "cloud";
19
+ export declare const MIN_APPROVAL: Record<Effect, Approval>;
20
+ export type ErrorCode = "invalid_input" | "not_signed_in" | "forbidden" | "not_found" | "conflict" | "idempotency_conflict" | "in_progress" | "rate_limited" | "no_credits" | "over_limit" | "engine_not_running" | "engine_lacks_op" | "unsupported" | "not_in_profile" | "moved" | "outcome_unknown" | "unavailable" | "internal";
21
+ export type NextStep = {
22
+ op: string;
23
+ input?: Record<string, unknown>;
24
+ } | {
25
+ url: string;
26
+ label: string;
27
+ } | {
28
+ say: string;
29
+ };
30
+ export type Retry = "no" | "safe" | "same_key" | "after";
31
+ export type OpErrorBody = {
32
+ code: ErrorCode;
33
+ message: string;
34
+ next?: NextStep;
35
+ retry: Retry;
36
+ details?: Record<string, unknown>;
37
+ requestId?: string;
38
+ };
39
+ export type JobState = "queued" | "running" | "awaiting_approval" | "done" | "failed" | "cancelled" | "declined" | "expired" | "stale";
40
+ export type JobRef = {
41
+ id: string;
42
+ op?: string;
43
+ state: JobState;
44
+ progress?: number;
45
+ pollAfterSeconds?: number;
46
+ };
47
+ /** The one answer shape every operation gives, in every view. */
48
+ export type Answer = {
49
+ ok: true;
50
+ status: "done";
51
+ result: unknown;
52
+ warnings?: string[];
53
+ } | {
54
+ ok: true;
55
+ status: "running";
56
+ job: JobRef;
57
+ warnings?: string[];
58
+ } | {
59
+ ok: true;
60
+ status: "needs_approval";
61
+ approval: {
62
+ id: string;
63
+ url: string;
64
+ who: "owner" | "person";
65
+ summary: string;
66
+ expiresAt?: string;
67
+ };
68
+ job: JobRef;
69
+ warnings?: string[];
70
+ } | {
71
+ ok: true;
72
+ status: "dry_run";
73
+ preview: Record<string, unknown>;
74
+ warnings?: string[];
75
+ } | {
76
+ ok: false;
77
+ error: OpErrorBody;
78
+ };
79
+ export declare function errorAnswer(code: ErrorCode, message: string, options?: {
80
+ next?: NextStep;
81
+ retry?: Retry;
82
+ details?: Record<string, unknown>;
83
+ }): Answer;
84
+ export declare const OP_NAME: RegExp;
85
+ /** `games.list` -> `summer_games_list`. */
86
+ export declare function mcpNameOf(op: string): string;
87
+ /** `assets generate-image` -> `assets.generate_image`; `whoami` stays. */
88
+ export declare function opFromCli(area: string, action?: string): string;
89
+ export type LegacyRow = {
90
+ op: string;
91
+ kind: "same" | "merge" | "split" | "keep";
92
+ note: string;
93
+ };
94
+ /** registry/operations/legacy-names.json: every 3.x tool name (and `#action`) to its operation. */
95
+ export declare function legacyNames(): Record<string, LegacyRow>;
96
+ /** A 3.x name as its operation name; an operation name unchanged. */
97
+ export declare function resolveOpName(name: string): string;
98
+ /**
99
+ * Local operations a 3.x tool runs although legacy-names.json maps that
100
+ * tool to a cloud operation: the local-only input is its own operation
101
+ * (apps.publish_folder reads a folder on disk; apps.publish takes files).
102
+ */
103
+ export declare const LOCAL_RUNNERS: Readonly<Record<string, string>>;
104
+ export { isLocalOp };
105
+ /**
106
+ * The local 3.x tools that run an operation here, first choice first: the
107
+ * tool the op was renamed from before the tools merged into it.
108
+ */
109
+ export declare function localToolsFor(op: string): string[];
110
+ /** `<kind>:<backend id>`; an id without a known kind is a 3.x generation job. */
111
+ export declare function parseJobId(id: string): {
112
+ kind: string;
113
+ parts: string[];
114
+ } | null;
115
+ /**
116
+ * The operation a tool call ran, for usage telemetry: summer_call's `op`,
117
+ * summer_search's own op, a 3.x name's op, or a v4 tool's op from its name
118
+ * (areas are single words, so the first underscore after `summer_` is the dot).
119
+ */
120
+ export declare function opForToolCall(tool: string, args: unknown): string | null;