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
@@ -0,0 +1,261 @@
1
+ import { closeSync, cpSync, existsSync, lstatSync, openSync, readdirSync, readFileSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { getSkillRegistry, resolveSkillDir } from "../core/skills-registry.js";
4
+ import { allAgentSpecs, defaultPathContext, resolveSkillPath } from "./agent-table.js";
5
+ import { compareSemver, parseSemver, readKeptSkills, readSkillMarker, SKILL_VERSION_MARKER_FILENAME } from "./version-check.js";
6
+ /**
7
+ * After an upgrade, bring the Summer skills already installed on this
8
+ * computer up to this CLI's version. Skills written for 3.x name 3.x tools,
9
+ * and while their marker says 3.x the MCP server keeps the legacy toolset on
10
+ * (legacy-toolset.ts), which gives back most of 4.0's smaller tool list.
11
+ *
12
+ * Only what Summer installed and nobody changed is replaced, in a skills
13
+ * folder that carries Summer's `.summer-version` marker older than this CLI:
14
+ * a real folder (not a link) whose `resource.yaml` says `id: skill/<name>`
15
+ * (every Summer release ships it; other packs reuse names such as
16
+ * `brainstorming`), with no file changed after the marker was written, and
17
+ * not one an earlier refresh already left for that reason (the marker lists
18
+ * them, so the protection lasts until `summer setup --force`). A copy that
19
+ * already matches the library counts as current, not as changed. Each
20
+ * replacement is a copy beside it and two renames, so a kill or a copy error
21
+ * leaves the old skill in place. One process per folder (a lock file).
22
+ * Nothing is removed. Missing library skills are added only to a folder that
23
+ * holds nearly the whole library, so an assets-only install stays one.
24
+ * Rule-file installs (Cline, Roo Code, old Cursor rules) keep the refresh
25
+ * command `summer doctor` prints.
26
+ */
27
+ const LOCK_FILE = ".summer-refresh.lock";
28
+ const STALE_LOCK_MS = 60_000;
29
+ /** Setup writes the marker right after its copy; a file changed later than this was changed by someone. */
30
+ const EDIT_GRACE_MS = 60_000;
31
+ /** A folder holding this share of the bundled library is a full install: new library skills join it. */
32
+ const FULL_INSTALL_SHARE = 0.9;
33
+ const TEMP_PREFIX = ".summer-refresh-";
34
+ const OLD_PREFIX = ".summer-old-";
35
+ /** User-scope skill folders with one folder per skill, each listed once. */
36
+ export function skillFolderLocations() {
37
+ const ctx = defaultPathContext();
38
+ const dirs = new Set([join(ctx.home, ".summer", "skills")]);
39
+ for (const spec of allAgentSpecs()) {
40
+ const home = resolveSkillPath(spec, "user", ctx);
41
+ if (home?.kind === "skill-dir")
42
+ dirs.add(home.path);
43
+ }
44
+ return [...dirs];
45
+ }
46
+ const isPrerelease = (version) => /^\d+\.\d+\.\d+-/.test(version.trim());
47
+ /** Refresh when the marker is older, or a pre-release of this release (4.2.0-next.1 -> 4.2.0, never back). */
48
+ function isBehind(marker, cliVersion) {
49
+ const installed = parseSemver(marker.version);
50
+ const current = parseSemver(cliVersion);
51
+ if (!installed || !current)
52
+ return false;
53
+ const order = compareSemver(installed, current);
54
+ return order < 0 || (order === 0 && isPrerelease(marker.version) && !isPrerelease(cliVersion));
55
+ }
56
+ const errorCode = (error) => error?.code ?? (error instanceof Error ? error.message : String(error));
57
+ /** Summer's own copy: a real folder (not a link) whose resource.yaml names this skill. */
58
+ function isSummersSkill(dest, name) {
59
+ try {
60
+ if (!lstatSync(dest).isDirectory())
61
+ return false;
62
+ const id = readFileSync(join(dest, "resource.yaml"), "utf-8").match(/^id:\s*["']?([^"'\s]+)["']?\s*$/m)?.[1];
63
+ return id === `skill/${name}`;
64
+ }
65
+ catch {
66
+ return false;
67
+ }
68
+ }
69
+ /** The folder, or any file in it, changed after `since` (ms); the folder's own time covers a deleted file. Links are not followed. */
70
+ function changedSince(dir, since) {
71
+ if (lstatSync(dir).mtimeMs > since)
72
+ return true;
73
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
74
+ const path = join(dir, entry.name);
75
+ if (lstatSync(path).mtimeMs > since)
76
+ return true;
77
+ if (entry.isDirectory() && changedSince(path, since))
78
+ return true;
79
+ }
80
+ return false;
81
+ }
82
+ /** Relative paths of every file under `dir`. */
83
+ function filesUnder(dir, prefix = "") {
84
+ return readdirSync(dir, { withFileTypes: true }).flatMap((entry) => entry.isDirectory() ? filesUnder(join(dir, entry.name), `${prefix}${entry.name}/`) : [`${prefix}${entry.name}`]);
85
+ }
86
+ /** The installed folder holds exactly the library's files with the library's bytes (a refresh a kill interrupted already wrote it). */
87
+ function sameAsLibrary(dest, src) {
88
+ try {
89
+ const installed = filesUnder(dest).sort();
90
+ const library = filesUnder(src).sort();
91
+ return (installed.length === library.length &&
92
+ installed.every((file, index) => file === library[index] && readFileSync(join(dest, file)).equals(readFileSync(join(src, file)))));
93
+ }
94
+ catch {
95
+ return false;
96
+ }
97
+ }
98
+ /** Copy beside, rename the old one aside, rename the new one in; the old one comes back on any error. */
99
+ function replaceSkill(dir, name, src) {
100
+ const dest = join(dir, name);
101
+ const temp = join(dir, `${TEMP_PREFIX}${name}-${process.pid}`);
102
+ const old = join(dir, `${OLD_PREFIX}${name}-${process.pid}`);
103
+ rmSync(temp, { recursive: true, force: true });
104
+ try {
105
+ cpSync(src, temp, { recursive: true });
106
+ }
107
+ catch (error) {
108
+ rmSync(temp, { recursive: true, force: true });
109
+ throw error;
110
+ }
111
+ const hadOld = existsSync(dest);
112
+ if (hadOld)
113
+ renameSync(dest, old);
114
+ try {
115
+ renameSync(temp, dest);
116
+ }
117
+ catch (error) {
118
+ if (hadOld)
119
+ renameSync(old, dest);
120
+ rmSync(temp, { recursive: true, force: true });
121
+ throw error;
122
+ }
123
+ if (hadOld)
124
+ rmSync(old, { recursive: true, force: true });
125
+ }
126
+ /** What a killed refresh left: half copies go, a skill renamed aside comes back. */
127
+ function recoverInterrupted(dir) {
128
+ for (const entry of readdirSync(dir)) {
129
+ const path = join(dir, entry);
130
+ if (entry.startsWith(TEMP_PREFIX))
131
+ rmSync(path, { recursive: true, force: true });
132
+ if (!entry.startsWith(OLD_PREFIX))
133
+ continue;
134
+ const name = entry.slice(OLD_PREFIX.length).replace(/-\d+$/, "");
135
+ if (existsSync(join(dir, name)))
136
+ rmSync(path, { recursive: true, force: true });
137
+ else
138
+ renameSync(path, join(dir, name));
139
+ }
140
+ }
141
+ /** The folder's lock, or null while another process holds a fresh one. */
142
+ function takeLock(dir) {
143
+ const path = join(dir, LOCK_FILE);
144
+ for (let attempt = 0; attempt < 2; attempt++) {
145
+ try {
146
+ closeSync(openSync(path, "wx"));
147
+ return () => rmSync(path, { force: true });
148
+ }
149
+ catch (error) {
150
+ if (errorCode(error) !== "EEXIST")
151
+ throw error;
152
+ try {
153
+ if (Date.now() - statSync(path).mtimeMs < STALE_LOCK_MS)
154
+ return null;
155
+ unlinkSync(path);
156
+ }
157
+ catch {
158
+ return null;
159
+ }
160
+ }
161
+ }
162
+ return null;
163
+ }
164
+ function refreshFolder(dir, marker, cliVersion, registry, failures) {
165
+ const release = takeLock(dir);
166
+ if (!release)
167
+ return null;
168
+ try {
169
+ recoverInterrupted(dir);
170
+ // The marker must be writable before anything is copied, or every start would copy again.
171
+ const markerTemp = join(dir, `${SKILL_VERSION_MARKER_FILENAME}.tmp`);
172
+ writeFileSync(markerTemp, "", "utf-8");
173
+ const installedAt = Date.parse(marker.installedAt);
174
+ const editedAfter = (Number.isFinite(installedAt) ? installedAt : 0) + EDIT_GRACE_MS;
175
+ const folder = { dir, from: marker.version, to: cliVersion, updated: [], added: [], kept: [] };
176
+ const keptBefore = new Set(readKeptSkills(dir));
177
+ const owned = registry.filter((entry) => isSummersSkill(join(dir, entry.name), entry.name));
178
+ for (const entry of owned) {
179
+ const dest = join(dir, entry.name);
180
+ if (sameAsLibrary(dest, resolveSkillDir(entry))) {
181
+ folder.updated.push(entry.name);
182
+ continue;
183
+ }
184
+ if (keptBefore.has(entry.name) || changedSince(dest, editedAfter)) {
185
+ folder.kept.push(entry.name);
186
+ continue;
187
+ }
188
+ try {
189
+ replaceSkill(dir, entry.name, resolveSkillDir(entry));
190
+ folder.updated.push(entry.name);
191
+ }
192
+ catch (error) {
193
+ failures.push({ dir, skill: entry.name, code: errorCode(error) });
194
+ }
195
+ }
196
+ const bundled = registry.filter((entry) => entry.bundled !== false && entry.status !== "deprecated");
197
+ if (bundled.length > 0 && owned.length >= FULL_INSTALL_SHARE * bundled.length) {
198
+ for (const entry of bundled) {
199
+ if (existsSync(join(dir, entry.name)))
200
+ continue;
201
+ try {
202
+ replaceSkill(dir, entry.name, resolveSkillDir(entry));
203
+ folder.added.push(entry.name);
204
+ }
205
+ catch (error) {
206
+ failures.push({ dir, skill: entry.name, code: errorCode(error) });
207
+ }
208
+ }
209
+ }
210
+ // Written last, through a rename: a kill before this leaves the old marker, and the next start finishes.
211
+ const next = { version: cliVersion, installedAt: new Date().toISOString(), ...(folder.kept.length > 0 ? { kept: folder.kept } : {}) };
212
+ writeFileSync(markerTemp, JSON.stringify(next, null, 2) + "\n", "utf-8");
213
+ renameSync(markerTemp, join(dir, SKILL_VERSION_MARKER_FILENAME));
214
+ return folder;
215
+ }
216
+ finally {
217
+ release();
218
+ }
219
+ }
220
+ export function refreshInstalledSkills(cliVersion, options = {}) {
221
+ const result = { refreshed: [], failures: [] };
222
+ if (!parseSemver(cliVersion))
223
+ return result;
224
+ for (const dir of options.dirs ?? skillFolderLocations()) {
225
+ const marker = readSkillMarker(dir);
226
+ if (!marker || !isBehind(marker, cliVersion))
227
+ continue;
228
+ try {
229
+ const folder = refreshFolder(dir, marker, cliVersion, options.registry ?? getSkillRegistry(), result.failures);
230
+ if (folder)
231
+ result.refreshed.push(folder);
232
+ }
233
+ catch (error) {
234
+ // A folder we cannot lock or write keeps its skills and its marker; doctor still names the refresh.
235
+ result.failures.push({ dir, code: errorCode(error) });
236
+ }
237
+ }
238
+ return result;
239
+ }
240
+ const listed = (names) => names.length > 5 ? `${names.slice(0, 5).join(", ")} and ${names.length - 5} more` : names.join(", ");
241
+ /** The one message a person and their agent see after a refresh, or null when nothing changed. */
242
+ export function refreshNotice(refreshed, failures = []) {
243
+ const skills = new Set(refreshed.flatMap((folder) => [...folder.updated, ...folder.added])).size;
244
+ const kept = [...new Set(refreshed.flatMap((folder) => folder.kept))];
245
+ const failed = [...new Set(failures.flatMap((failure) => (failure.skill ? [failure.skill] : [])))];
246
+ if (skills === 0 && kept.length === 0)
247
+ return null;
248
+ const changedFolders = refreshed.filter((folder) => folder.updated.length + folder.added.length > 0).length;
249
+ const from = [...new Set(refreshed.map((folder) => folder.from))].join(", ");
250
+ const to = refreshed[0].to;
251
+ return [
252
+ skills > 0 ? `Summer updated its ${skills} installed skills (${changedFolders === 1 ? "1 folder" : `${changedFolders} folders`}) from ${from} to ${to}.` : "",
253
+ kept.length > 0
254
+ ? `It left ${kept.length} Summer skills you changed as they are (${listed(kept)}); summer setup <agent> --force replaces them.`
255
+ : "",
256
+ failed.length > 0 ? `${failed.length} could not be updated (${listed(failed)}); summer setup <agent> --force retries them.` : "",
257
+ "3.x tool names still run through summer_call; summer mcp --toolsets legacy lists them again.",
258
+ ]
259
+ .filter(Boolean)
260
+ .join(" ");
261
+ }
@@ -52,6 +52,15 @@ export interface RegistryFetchFailure {
52
52
  message?: string;
53
53
  }
54
54
  export declare function fetchLatestRegistryVersion(options?: RegistryFetchOptions): Promise<RegistryFetchResult | RegistryFetchFailure>;
55
+ export interface RegistryDistTagsResult {
56
+ ok: true;
57
+ /** dist-tag -> version, e.g. { latest: "3.8.0", next: "3.1.0" }. */
58
+ tags: Record<string, string>;
59
+ }
60
+ export declare function fetchRegistryDistTags(options?: RegistryFetchOptions): Promise<RegistryDistTagsResult | RegistryFetchFailure>;
61
+ /** Whether npm has this exact version: true, false (registry says 404), or
62
+ * null when the registry could not be asked. */
63
+ export declare function isRegistryVersionPublished(version: string, options?: RegistryFetchOptions): Promise<boolean | null>;
55
64
  /**
56
65
  * Build the `cli-version-current` doctor check. Pure helper so tests can drive
57
66
  * registry responses through `fetchImpl` rather than touching the network.
@@ -70,9 +79,18 @@ export declare const SKILL_VERSION_MARKER_FILENAME = ".summer-version";
70
79
  export interface SkillVersionMarker {
71
80
  version: string;
72
81
  installedAt: string;
82
+ /** Summer skills the upgrade refresh left because someone changed them (installer/skills-refresh.ts). */
83
+ kept?: string[];
73
84
  }
74
85
  export declare function readSkillMarker(dir: string): SkillVersionMarker | null;
75
- export declare function writeSkillMarker(dir: string, version: string, now?: Date): string;
86
+ /** The skills the upgrade refresh left in this folder (the raw marker; readSkillMarker keeps setup's fields). */
87
+ export declare function readKeptSkills(dir: string): string[];
88
+ /**
89
+ * Write the folder's marker. The skills an upgrade refresh left stay listed
90
+ * (so later refreshes keep leaving them), except the ones this install just
91
+ * wrote: `installed` names them; leave it out to keep every one.
92
+ */
93
+ export declare function writeSkillMarker(dir: string, version: string, now?: Date, installed?: readonly string[]): string;
76
94
  /**
77
95
  * Candidate locations for skill-version markers. Listed roughly in order of
78
96
  * how likely a Summer user is to have them populated. We probe every candidate,
@@ -99,17 +117,30 @@ export interface RecordedInstall {
99
117
  /** Where the answer came from: the agent's config file, or — when it has
100
118
  * no readable Summer entry — the nature of the CLI running this check. */
101
119
  source: "agent-config" | "running-cli";
120
+ /** The agent's config lists no summer-engine server in any shape (`setup
121
+ * --cli`, or skills installed alone) and `setup --cli` can set the agent
122
+ * up: the refresh keeps it without an MCP server. */
123
+ cliOnly?: boolean;
124
+ }
125
+ /** An npm dist-tag (`latest`, `next`) or an exact version (`3.9.1`). */
126
+ export type RefreshChannel = string;
127
+ /** The npm spec a refresh command or a new MCP entry should name, so the agent
128
+ * never runs an older release than this CLI (release review P1-3). `latest`
129
+ * unless this CLI is AHEAD of npm latest; then `next` only when the next
130
+ * dist-tag is this exact version, else this exact version. A CLI that is ahead
131
+ * is not always on `next`: `next` stayed on 3.1.0 while latest moved to 3.8.0,
132
+ * and pinning it dropped every option newer than 3.1.0 (SUMMER_PROFILE). */
133
+ export declare function refreshChannel(installedVersion: string, latestVersion: string | undefined, nextVersion?: string): RefreshChannel;
134
+ export interface DefaultChannelDeps {
135
+ fetchDistTags?: typeof fetchRegistryDistTags;
136
+ isPublished?: typeof isRegistryVersionPublished;
102
137
  }
103
- export type RefreshChannel = "latest" | "next";
104
- /** The npm dist-tag a refresh command should name. A CLI that is AHEAD of
105
- * npm `latest` was installed from `next` (a soaking release); telling that
106
- * user to run `summer-engine@latest` would silently downgrade the MCP server
107
- * while leaving the newer skills in place (release review P1-3). */
108
- export declare function refreshChannel(installedVersion: string, latestVersion: string | undefined): RefreshChannel;
109
138
  /** Default `summer setup` channel when neither --channel nor SUMMER_CHANNEL is
110
- * given: `next` while this CLI is ahead of npm latest, else `latest`. Network
111
- * failure means `latest` (never blocks setup). */
112
- export declare function resolveDefaultChannel(installedVersion: string): Promise<{
139
+ * given: `latest`, unless this CLI is ahead of npm latest. Then `next` when
140
+ * next is this exact version, this exact version when npm has it, and
141
+ * otherwise (a checkout that was never published) `latest` with a note that
142
+ * points at --local-dev. Network failure means `latest` (never blocks setup). */
143
+ export declare function resolveDefaultChannel(installedVersion: string, deps?: DefaultChannelDeps): Promise<{
113
144
  channel: RefreshChannel;
114
145
  note?: string;
115
146
  }>;
@@ -118,6 +149,8 @@ export interface SkillsVersionCheckInput {
118
149
  candidates: SkillMarkerCandidate[];
119
150
  /** npm latest, when known, so the refresh command names the right dist-tag. */
120
151
  latestRegistryVersion?: string;
152
+ /** npm next, when known: the refresh names `next` only when it is this CLI. */
153
+ nextRegistryVersion?: string;
121
154
  /** Resolves how the stale agent's MCP entry was recorded; defaults to
122
155
  * detectRecordedInstall. Seam for tests. */
123
156
  recordedInstall?: (agent: string) => Promise<RecordedInstall | null> | RecordedInstall | null;
@@ -133,7 +166,8 @@ export declare function buildSkillsVersionCheck(input: SkillsVersionCheckInput):
133
166
  * The command that refreshes an agent's skills without changing how its MCP
134
167
  * entry was recorded: the local-dev form re-links the same checkout
135
168
  * (`setup --local-dev --force` re-copies the checkout's skills); the npx form
136
- * is for installs that already run the published package.
169
+ * is for installs that already run the published package. An agent with no
170
+ * summer-engine entry refreshes with `--cli`, so the refresh adds no MCP server.
137
171
  */
138
172
  export declare function skillsRefreshCommand(agent: string, install: RecordedInstall | null, channel?: RefreshChannel): string;
139
173
  /** The shape `summer setup --local-dev` writes: `node <…>/dist/bin/summer.js mcp`
@@ -153,6 +187,12 @@ export declare function isLocalDevServerConfig(server: StdioMcpServerConfig): bo
153
187
  * Returns null when the file is missing, unparsable, or has no Summer entry.
154
188
  */
155
189
  export declare function readRecordedMcpServer(text: string, format: McpFormat): StdioMcpServerConfig | null;
190
+ /**
191
+ * Does the agent's config list a summer-engine server in any shape: the stdio
192
+ * entry setup writes, a URL entry under that name, or (Claude Code) a
193
+ * per-project entry under projects.<dir>.mcpServers?
194
+ */
195
+ export declare function listsSummerEngine(text: string, format: McpFormat): boolean;
156
196
  /** Is the CLI running this check a source checkout rather than an installed
157
197
  * package? npm/npx/global installs all live under a node_modules directory. */
158
198
  export declare function runningCliIsCheckout(packageRoot?: string): boolean;
@@ -13,11 +13,13 @@
13
13
  */
14
14
  import { existsSync, readFileSync, writeFileSync } from "node:fs";
15
15
  import { parse as parseYaml } from "yaml";
16
- import { allAgentSpecs, defaultPathContext, resolveSkillPath } from "./agent-table.js";
16
+ import { agentSpec, allAgentSpecs, cliSetupRefusal, defaultPathContext, resolveSkillPath } from "./agent-table.js";
17
17
  import { join, sep } from "node:path";
18
18
  import { PACKAGE_ROOT } from "../core/package-root.js";
19
19
  import { configureAgentMcp, parseAgent, SUMMER_MCP_SERVER_NAME, topLevelKey, } from "./agent-config.js";
20
20
  const NPM_REGISTRY_LATEST_URL = "https://registry.npmjs.org/summer-engine/latest";
21
+ const NPM_REGISTRY_DIST_TAGS_URL = "https://registry.npmjs.org/-/package/summer-engine/dist-tags";
22
+ const NPM_REGISTRY_PACKAGE_URL = "https://registry.npmjs.org/summer-engine";
21
23
  const REGISTRY_FETCH_TIMEOUT_MS = 3000;
22
24
  export function parseSemver(version) {
23
25
  if (!version)
@@ -69,8 +71,8 @@ export function classifyDrift(installed, target) {
69
71
  }
70
72
  return { severity: "warning", reason: "minor-drift" };
71
73
  }
72
- export async function fetchLatestRegistryVersion(options = {}) {
73
- const url = options.url ?? NPM_REGISTRY_LATEST_URL;
74
+ async function fetchRegistryJson(defaultUrl, options) {
75
+ const url = options.url ?? defaultUrl;
74
76
  const timeoutMs = options.timeoutMs ?? REGISTRY_FETCH_TIMEOUT_MS;
75
77
  const fetchImpl = options.fetchImpl ?? globalThis.fetch;
76
78
  if (!fetchImpl) {
@@ -88,15 +90,7 @@ export async function fetchLatestRegistryVersion(options = {}) {
88
90
  message: `registry responded ${response.status}`,
89
91
  };
90
92
  }
91
- const body = (await response.json());
92
- if (typeof body.version !== "string") {
93
- return {
94
- ok: false,
95
- reason: "registry-unreachable",
96
- message: "registry payload missing version",
97
- };
98
- }
99
- return { ok: true, version: body.version };
93
+ return { ok: true, body: await response.json() };
100
94
  }
101
95
  catch (error) {
102
96
  return {
@@ -106,6 +100,43 @@ export async function fetchLatestRegistryVersion(options = {}) {
106
100
  };
107
101
  }
108
102
  }
103
+ export async function fetchLatestRegistryVersion(options = {}) {
104
+ const result = await fetchRegistryJson(NPM_REGISTRY_LATEST_URL, options);
105
+ if (!result.ok)
106
+ return result;
107
+ const body = result.body;
108
+ if (typeof body?.version !== "string") {
109
+ return {
110
+ ok: false,
111
+ reason: "registry-unreachable",
112
+ message: "registry payload missing version",
113
+ };
114
+ }
115
+ return { ok: true, version: body.version };
116
+ }
117
+ export async function fetchRegistryDistTags(options = {}) {
118
+ const result = await fetchRegistryJson(NPM_REGISTRY_DIST_TAGS_URL, options);
119
+ if (!result.ok)
120
+ return result;
121
+ const body = result.body;
122
+ const tags = {};
123
+ for (const [tag, value] of Object.entries(body ?? {})) {
124
+ if (typeof value === "string")
125
+ tags[tag] = value;
126
+ }
127
+ if (!tags.latest) {
128
+ return { ok: false, reason: "registry-unreachable", message: "registry payload missing latest" };
129
+ }
130
+ return { ok: true, tags };
131
+ }
132
+ /** Whether npm has this exact version: true, false (registry says 404), or
133
+ * null when the registry could not be asked. */
134
+ export async function isRegistryVersionPublished(version, options = {}) {
135
+ const result = await fetchRegistryJson(`${NPM_REGISTRY_PACKAGE_URL}/${encodeURIComponent(version)}`, options);
136
+ if (result.ok)
137
+ return true;
138
+ return result.message === "registry responded 404" ? false : null;
139
+ }
109
140
  const RECOMMENDED_REFRESH_COMMAND = "npx clear-npx-cache && npx -y summer-engine@latest setup <agent> --yes --force";
110
141
  export function buildCliVersionCheck(input) {
111
142
  if (!input.registry.ok) {
@@ -188,11 +219,28 @@ export function readSkillMarker(dir) {
188
219
  return null;
189
220
  }
190
221
  }
191
- export function writeSkillMarker(dir, version, now = new Date()) {
222
+ /** The skills the upgrade refresh left in this folder (the raw marker; readSkillMarker keeps setup's fields). */
223
+ export function readKeptSkills(dir) {
224
+ try {
225
+ const kept = JSON.parse(readFileSync(join(dir, SKILL_VERSION_MARKER_FILENAME), "utf-8")).kept;
226
+ return Array.isArray(kept) ? kept.filter((name) => typeof name === "string") : [];
227
+ }
228
+ catch {
229
+ return [];
230
+ }
231
+ }
232
+ /**
233
+ * Write the folder's marker. The skills an upgrade refresh left stay listed
234
+ * (so later refreshes keep leaving them), except the ones this install just
235
+ * wrote: `installed` names them; leave it out to keep every one.
236
+ */
237
+ export function writeSkillMarker(dir, version, now = new Date(), installed) {
192
238
  const path = join(dir, SKILL_VERSION_MARKER_FILENAME);
239
+ const kept = readKeptSkills(dir).filter((name) => !installed?.includes(name));
193
240
  const payload = {
194
241
  version,
195
242
  installedAt: now.toISOString(),
243
+ ...(kept.length > 0 ? { kept } : {}),
196
244
  };
197
245
  writeFileSync(path, JSON.stringify(payload, null, 2) + "\n", "utf-8");
198
246
  return path;
@@ -212,28 +260,51 @@ export function defaultSkillMarkerCandidates() {
212
260
  }
213
261
  return candidates;
214
262
  }
215
- /** The npm dist-tag a refresh command should name. A CLI that is AHEAD of
216
- * npm `latest` was installed from `next` (a soaking release); telling that
217
- * user to run `summer-engine@latest` would silently downgrade the MCP server
218
- * while leaving the newer skills in place (release review P1-3). */
219
- export function refreshChannel(installedVersion, latestVersion) {
263
+ /** The npm spec a refresh command or a new MCP entry should name, so the agent
264
+ * never runs an older release than this CLI (release review P1-3). `latest`
265
+ * unless this CLI is AHEAD of npm latest; then `next` only when the next
266
+ * dist-tag is this exact version, else this exact version. A CLI that is ahead
267
+ * is not always on `next`: `next` stayed on 3.1.0 while latest moved to 3.8.0,
268
+ * and pinning it dropped every option newer than 3.1.0 (SUMMER_PROFILE). */
269
+ export function refreshChannel(installedVersion, latestVersion, nextVersion) {
220
270
  const installed = parseSemver(installedVersion);
221
271
  const latest = latestVersion ? parseSemver(latestVersion) : null;
222
272
  if (!installed || !latest)
223
273
  return "latest";
224
- return classifyDrift(installed, latest).reason === "ahead" ? "next" : "latest";
274
+ if (classifyDrift(installed, latest).reason !== "ahead")
275
+ return "latest";
276
+ return nextVersion?.trim() === installedVersion.trim() ? "next" : installedVersion.trim();
225
277
  }
226
278
  /** Default `summer setup` channel when neither --channel nor SUMMER_CHANNEL is
227
- * given: `next` while this CLI is ahead of npm latest, else `latest`. Network
228
- * failure means `latest` (never blocks setup). */
229
- export async function resolveDefaultChannel(installedVersion) {
230
- const registry = await fetchLatestRegistryVersion();
279
+ * given: `latest`, unless this CLI is ahead of npm latest. Then `next` when
280
+ * next is this exact version, this exact version when npm has it, and
281
+ * otherwise (a checkout that was never published) `latest` with a note that
282
+ * points at --local-dev. Network failure means `latest` (never blocks setup). */
283
+ export async function resolveDefaultChannel(installedVersion, deps = {}) {
284
+ const registry = await (deps.fetchDistTags ?? fetchRegistryDistTags)();
231
285
  if (!registry.ok)
232
286
  return { channel: "latest" };
233
- const channel = refreshChannel(installedVersion, registry.version);
234
- return channel === "next"
235
- ? { channel, note: `This CLI (${installedVersion}) is ahead of npm latest (${registry.version}); the MCP entry is pinned to summer-engine@next so the agent keeps running this release. Pass --channel latest to override.` }
236
- : { channel };
287
+ const latest = registry.tags.latest;
288
+ const channel = refreshChannel(installedVersion, latest, registry.tags.next);
289
+ if (channel === "latest")
290
+ return { channel };
291
+ if (channel === "next") {
292
+ return {
293
+ channel,
294
+ note: `This CLI (${installedVersion}) is the npm next release, ahead of latest (${latest}); the MCP entry runs summer-engine@next. Pass --channel latest to override.`,
295
+ };
296
+ }
297
+ const published = await (deps.isPublished ?? isRegistryVersionPublished)(installedVersion);
298
+ if (published) {
299
+ return {
300
+ channel,
301
+ note: `This CLI (${installedVersion}) is ahead of npm latest (${latest}); the MCP entry is pinned to summer-engine@${installedVersion} so the agent runs this release. Pass --channel latest to override.`,
302
+ };
303
+ }
304
+ return {
305
+ channel: "latest",
306
+ note: `This CLI (${installedVersion}) is not on npm, so the MCP entry runs summer-engine@latest (${latest}), which can lack options this CLI has. To run this build, pass --local-dev.`,
307
+ };
237
308
  }
238
309
  export async function buildSkillsVersionCheck(input) {
239
310
  const cliParsed = parseSemver(input.installedCliVersion);
@@ -306,7 +377,7 @@ export async function buildSkillsVersionCheck(input) {
306
377
  ...baseDetails,
307
378
  drift: worst.drift.reason,
308
379
  ...(install ? { install } : {}),
309
- recommendedAction: skillsRefreshCommand(worst.agent, install, refreshChannel(input.installedCliVersion, input.latestRegistryVersion)),
380
+ recommendedAction: skillsRefreshCommand(worst.agent, install, refreshChannel(input.installedCliVersion, input.latestRegistryVersion, input.nextRegistryVersion)),
310
381
  },
311
382
  };
312
383
  }
@@ -324,14 +395,20 @@ async function resolveRecordedInstall(resolver, agent) {
324
395
  * The command that refreshes an agent's skills without changing how its MCP
325
396
  * entry was recorded: the local-dev form re-links the same checkout
326
397
  * (`setup --local-dev --force` re-copies the checkout's skills); the npx form
327
- * is for installs that already run the published package.
398
+ * is for installs that already run the published package. An agent with no
399
+ * summer-engine entry refreshes with `--cli`, so the refresh adds no MCP server.
328
400
  */
329
401
  export function skillsRefreshCommand(agent, install, channel = "latest") {
402
+ if (install?.cliOnly) {
403
+ // No MCP entry to keep: --local-dev and --channel shape only that entry.
404
+ return install.localDev && install.cliPath
405
+ ? `node ${install.cliPath} setup ${agent} --cli --yes --force`
406
+ : `npx clear-npx-cache && npx -y summer-engine@${channel} setup ${agent} --cli --yes --force`;
407
+ }
330
408
  if (install?.localDev && install.cliPath) {
331
409
  return `node ${install.cliPath} setup ${agent} --local-dev --yes --force`;
332
410
  }
333
- const tag = channel === "next" ? "next" : "latest";
334
- return `npx clear-npx-cache && npx -y summer-engine@${tag} setup ${agent} --yes --force${channel === "next" ? " --channel next" : ""}`;
411
+ return `npx clear-npx-cache && npx -y summer-engine@${channel} setup ${agent} --yes --force${channel === "latest" ? "" : ` --channel ${channel}`}`;
335
412
  }
336
413
  /** The shape `summer setup --local-dev` writes: `node <…>/dist/bin/summer.js mcp`
337
414
  * (createSummerMcpServerConfig(true)). */
@@ -420,6 +497,37 @@ export function readRecordedMcpServer(text, format) {
420
497
  }
421
498
  return null;
422
499
  }
500
+ /**
501
+ * Does the agent's config list a summer-engine server in any shape: the stdio
502
+ * entry setup writes, a URL entry under that name, or (Claude Code) a
503
+ * per-project entry under projects.<dir>.mcpServers?
504
+ */
505
+ export function listsSummerEngine(text, format) {
506
+ if (readRecordedMcpServer(text, format))
507
+ return true;
508
+ if (!text.trim())
509
+ return false;
510
+ if (format === "toml")
511
+ return new RegExp(`^\\s*\\[mcp_servers\\.(?:"${SUMMER_MCP_SERVER_NAME}"|${SUMMER_MCP_SERVER_NAME})[\\].]`, "m").test(text);
512
+ if (format === "toml-array")
513
+ return new RegExp(`^\\s*name\\s*=\\s*"${SUMMER_MCP_SERVER_NAME}"`, "m").test(text);
514
+ let parsed;
515
+ try {
516
+ parsed = format === "yaml-goose" || format === "yaml-hermes" ? parseYaml(text) : JSON.parse(text);
517
+ }
518
+ catch {
519
+ return false;
520
+ }
521
+ if (!parsed || typeof parsed !== "object")
522
+ return false;
523
+ const root = parsed;
524
+ const projects = root.projects && typeof root.projects === "object" ? Object.values(root.projects) : [];
525
+ const maps = [
526
+ ...[topLevelKey(format), "mcpServers", "servers", "mcp", "context_servers", "extensions", "mcp_servers", "amp.mcpServers"].map((key) => root[key]),
527
+ ...projects.map((project) => (project && typeof project === "object" ? project.mcpServers : undefined)),
528
+ ];
529
+ return maps.some((map) => Boolean(map) && typeof map === "object" && SUMMER_MCP_SERVER_NAME in map);
530
+ }
423
531
  /** Is the CLI running this check a source checkout rather than an installed
424
532
  * package? npm/npx/global installs all live under a node_modules directory. */
425
533
  export function runningCliIsCheckout(packageRoot = PACKAGE_ROOT) {
@@ -435,16 +543,17 @@ export function runningCliIsCheckout(packageRoot = PACKAGE_ROOT) {
435
543
  */
436
544
  export async function detectRecordedInstall(agent) {
437
545
  const supported = parseAgent(agent);
546
+ let cliOnly = false;
438
547
  if (supported) {
439
548
  try {
440
549
  const target = await configureAgentMcp({ agent: supported, scope: "user", print: true });
441
- if (existsSync(target.path)) {
442
- const recorded = readRecordedMcpServer(readFileSync(target.path, "utf-8"), target.format);
443
- if (recorded) {
444
- const localDev = isLocalDevServerConfig(recorded);
445
- return { localDev, cliPath: localDev ? recorded.args[0] ?? null : null, source: "agent-config" };
446
- }
550
+ const text = existsSync(target.path) ? readFileSync(target.path, "utf-8") : "";
551
+ const recorded = readRecordedMcpServer(text, target.format);
552
+ if (recorded) {
553
+ const localDev = isLocalDevServerConfig(recorded);
554
+ return { localDev, cliPath: localDev ? recorded.args[0] ?? null : null, source: "agent-config" };
447
555
  }
556
+ cliOnly = !listsSummerEngine(text, target.format) && cliSetupRefusal(agentSpec(supported)) === null;
448
557
  }
449
558
  catch {
450
559
  // Unreadable config: fall through to the running-CLI answer.
@@ -455,6 +564,7 @@ export async function detectRecordedInstall(agent) {
455
564
  localDev: checkout,
456
565
  cliPath: checkout ? [PACKAGE_ROOT, "dist", "bin", "summer.js"].join(sep) : null,
457
566
  source: "running-cli",
567
+ ...(cliOnly ? { cliOnly } : {}),
458
568
  };
459
569
  }
460
570
  export function buildBootDriftNotice(installedVersion, registry, agent) {