summer-engine 3.1.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (366) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +27 -5
  3. package/.codex-plugin/plugin.json +28 -6
  4. package/.cursor-plugin/plugin.json +27 -5
  5. package/.factory-plugin/plugin.json +27 -5
  6. package/.opencode/plugins/summer.js +1 -1
  7. package/CHANGELOG.md +102 -0
  8. package/README.md +18 -3
  9. package/assets/audit/scene_audit.gd +4136 -0
  10. package/assets/seeing/seeing_probe.gd +1873 -0
  11. package/dist/cli/commands/skills.js +20 -2
  12. package/dist/core/api-client.d.ts +9 -1
  13. package/dist/core/api-client.js +21 -4
  14. package/dist/core/capabilities/agent-playbook.js +46 -0
  15. package/dist/core/capabilities/audit/accept.d.ts +55 -0
  16. package/dist/core/capabilities/audit/accept.js +147 -0
  17. package/dist/core/capabilities/audit/args.d.ts +95 -0
  18. package/dist/core/capabilities/audit/args.js +89 -0
  19. package/dist/core/capabilities/audit/audit.d.ts +56 -0
  20. package/dist/core/capabilities/audit/audit.js +287 -0
  21. package/dist/core/capabilities/audit/frame.d.ts +14 -0
  22. package/dist/core/capabilities/audit/frame.js +35 -0
  23. package/dist/core/capabilities/audit/gaps.d.ts +96 -0
  24. package/dist/core/capabilities/audit/gaps.js +257 -0
  25. package/dist/core/capabilities/audit/judge.d.ts +162 -0
  26. package/dist/core/capabilities/audit/judge.js +1134 -0
  27. package/dist/core/capabilities/audit/math.d.ts +110 -0
  28. package/dist/core/capabilities/audit/math.js +263 -0
  29. package/dist/core/capabilities/audit/summary.d.ts +74 -0
  30. package/dist/core/capabilities/audit/summary.js +212 -0
  31. package/dist/core/capabilities/board.d.ts +31 -0
  32. package/dist/core/capabilities/board.js +43 -0
  33. package/dist/core/capabilities/camera-view.d.ts +4 -2
  34. package/dist/core/capabilities/camera-view.js +6 -3
  35. package/dist/core/capabilities/connect-signal.d.ts +85 -0
  36. package/dist/core/capabilities/connect-signal.js +285 -0
  37. package/dist/core/capabilities/engine-fallbacks.d.ts +5 -0
  38. package/dist/core/capabilities/engine-fallbacks.js +5 -0
  39. package/dist/core/capabilities/engine-ops.d.ts +5 -1
  40. package/dist/core/capabilities/engine-ops.js +0 -3
  41. package/dist/core/capabilities/engine-receipt.d.ts +12 -0
  42. package/dist/core/capabilities/engine-receipt.js +26 -0
  43. package/dist/core/capabilities/file-read.d.ts +64 -0
  44. package/dist/core/capabilities/file-read.js +325 -0
  45. package/dist/core/capabilities/game-task-plan.js +4 -2
  46. package/dist/core/capabilities/grep.d.ts +60 -0
  47. package/dist/core/capabilities/grep.js +190 -0
  48. package/dist/core/capabilities/inspect-node.d.ts +56 -0
  49. package/dist/core/capabilities/inspect-node.js +225 -0
  50. package/dist/core/capabilities/inspect-resource.d.ts +61 -0
  51. package/dist/core/capabilities/inspect-resource.js +376 -0
  52. package/dist/core/capabilities/math3d.d.ts +28 -0
  53. package/dist/core/capabilities/math3d.js +88 -0
  54. package/dist/core/capabilities/motion-generation.d.ts +62 -0
  55. package/dist/core/capabilities/motion-generation.js +138 -0
  56. package/dist/core/capabilities/placement-batch.d.ts +102 -0
  57. package/dist/core/capabilities/placement-batch.js +483 -0
  58. package/dist/core/capabilities/placement-math.d.ts +70 -0
  59. package/dist/core/capabilities/placement-math.js +209 -0
  60. package/dist/core/capabilities/placement-script.d.ts +42 -0
  61. package/dist/core/capabilities/placement-script.js +1096 -0
  62. package/dist/core/capabilities/placement.d.ts +485 -0
  63. package/dist/core/capabilities/placement.js +1731 -0
  64. package/dist/core/capabilities/project-context.d.ts +33 -2
  65. package/dist/core/capabilities/project-context.js +87 -4
  66. package/dist/core/capabilities/replace-node.d.ts +91 -0
  67. package/dist/core/capabilities/replace-node.js +423 -0
  68. package/dist/core/capabilities/runtime-control.d.ts +18 -2
  69. package/dist/core/capabilities/runtime-control.js +67 -2
  70. package/dist/core/capabilities/scene-batch.d.ts +63 -0
  71. package/dist/core/capabilities/scene-batch.js +394 -0
  72. package/dist/core/capabilities/scene-readback.d.ts +36 -0
  73. package/dist/core/capabilities/scene-readback.js +54 -0
  74. package/dist/core/capabilities/seeing/args.d.ts +348 -0
  75. package/dist/core/capabilities/seeing/args.js +178 -0
  76. package/dist/core/capabilities/seeing/candidates.d.ts +127 -0
  77. package/dist/core/capabilities/seeing/candidates.js +282 -0
  78. package/dist/core/capabilities/seeing/math.d.ts +134 -0
  79. package/dist/core/capabilities/seeing/math.js +269 -0
  80. package/dist/core/capabilities/seeing/probe.d.ts +62 -0
  81. package/dist/core/capabilities/seeing/probe.js +188 -0
  82. package/dist/core/capabilities/seeing/scoring.d.ts +235 -0
  83. package/dist/core/capabilities/seeing/scoring.js +639 -0
  84. package/dist/core/capabilities/seeing/seeing.d.ts +233 -0
  85. package/dist/core/capabilities/seeing/seeing.js +1341 -0
  86. package/dist/core/capabilities/seeing/shot-store.d.ts +52 -0
  87. package/dist/core/capabilities/seeing/shot-store.js +204 -0
  88. package/dist/core/capabilities/surface-snap-mesh.d.ts +88 -0
  89. package/dist/core/capabilities/surface-snap-mesh.js +425 -0
  90. package/dist/core/capabilities/surface-snap.d.ts +77 -0
  91. package/dist/core/capabilities/surface-snap.js +461 -0
  92. package/dist/core/capabilities/tool-dispatch.js +231 -72
  93. package/dist/core/capabilities/tscn.d.ts +85 -0
  94. package/dist/core/capabilities/tscn.js +391 -0
  95. package/dist/core/capabilities/world-snapshot.d.ts +58 -0
  96. package/dist/core/capabilities/world-snapshot.js +150 -0
  97. package/dist/core/capability-skew.d.ts +5 -5
  98. package/dist/core/capability-skew.js +14 -6
  99. package/dist/core/headless/worker-engine-client.d.ts +1 -1
  100. package/dist/core/headless/worker-engine-client.js +2 -2
  101. package/dist/core/library-read.d.ts +37 -5
  102. package/dist/core/library-read.js +264 -33
  103. package/dist/core/library-search.d.ts +2 -2
  104. package/dist/installer/agent-config.js +5 -3
  105. package/dist/installer/agent-table.d.ts +16 -0
  106. package/dist/installer/agent-table.js +52 -17
  107. package/dist/mcp/server.js +9 -3
  108. package/dist/mcp/tools/asset-tools.js +21 -3
  109. package/dist/mcp/tools/audit-tools.d.ts +23 -0
  110. package/dist/mcp/tools/audit-tools.js +60 -0
  111. package/dist/mcp/tools/debug-tools.js +3 -1
  112. package/dist/mcp/tools/file-tools.js +17 -4
  113. package/dist/mcp/tools/generate-tools.js +74 -66
  114. package/dist/mcp/tools/library-tools.js +2 -0
  115. package/dist/mcp/tools/perception-tools.js +6 -19
  116. package/dist/mcp/tools/placement-tools.d.ts +24 -0
  117. package/dist/mcp/tools/placement-tools.js +91 -0
  118. package/dist/mcp/tools/project-tools.js +18 -15
  119. package/dist/mcp/tools/scene-tools.js +71 -83
  120. package/dist/mcp/tools/seeing-tools.d.ts +24 -0
  121. package/dist/mcp/tools/seeing-tools.js +64 -0
  122. package/dist/mcp/tools/spatial-tools.js +17 -9
  123. package/dist/mcp/tools/visual-tools.js +59 -7
  124. package/gemini-extension.json +26 -4
  125. package/integrations/amp/README.md +1 -1
  126. package/integrations/crush/README.md +1 -1
  127. package/integrations/grok-build/README.md +1 -1
  128. package/integrations/hermes/README.md +1 -1
  129. package/integrations/kimi-code/README.md +1 -1
  130. package/integrations/mistral-vibe/README.md +1 -1
  131. package/integrations/opencode/README.md +1 -1
  132. package/integrations/rovo-dev/README.md +1 -1
  133. package/integrations/vscode-copilot/README.md +1 -1
  134. package/integrations/warp/README.md +1 -1
  135. package/integrations/windsurf/README.md +1 -1
  136. package/library/references/mcp-tools-reference/mcp-tools-reference.md +59 -15
  137. package/library/references/mcp-tools-reference/resource.yaml +1 -1
  138. package/library/references/summer-folder/resource.yaml +1 -1
  139. package/library/references/summer-folder/summer-folder.md +1 -1
  140. package/library/skills/3d-lighting/SKILL.md +1 -1
  141. package/library/skills/README.md +36 -14
  142. package/library/skills/adaptive-music/SKILL.md +1 -1
  143. package/library/skills/agent-playtesting/SKILL.md +1 -1
  144. package/library/skills/ai-characters-in-games/SKILL.md +220 -0
  145. package/library/skills/ai-characters-in-games/resource.yaml +30 -0
  146. package/library/skills/ambient-bed/SKILL.md +1 -1
  147. package/library/skills/animated-loop/SKILL.md +1 -1
  148. package/library/skills/animation-tree/SKILL.md +1 -1
  149. package/library/skills/art-direction/SKILL.md +1 -1
  150. package/library/skills/asset-strategy/SKILL.md +2 -1
  151. package/library/skills/asset-strategy/resource.yaml +2 -1
  152. package/library/skills/audio-direction/SKILL.md +1 -1
  153. package/library/skills/auto-fire-targeting/SKILL.md +1 -1
  154. package/library/skills/brainstorm-game/SKILL.md +1 -1
  155. package/library/skills/brainstorming/SKILL.md +1 -1
  156. package/library/skills/browse-templates/SKILL.md +3 -3
  157. package/library/skills/browse-templates/resource.yaml +1 -1
  158. package/library/skills/camera-rigs/SKILL.md +128 -0
  159. package/library/skills/camera-rigs/resource.yaml +29 -0
  160. package/library/skills/celeste-momentum-platforming/SKILL.md +1 -1
  161. package/library/skills/character-animation-wiring/SKILL.md +1 -1
  162. package/library/skills/character-model/SKILL.md +1 -1
  163. package/library/skills/character-movement/SKILL.md +326 -0
  164. package/library/skills/character-movement/references/default-third-person-controller.gd +201 -0
  165. package/library/skills/character-movement/references/default-third-person-verification-probe.gd +154 -0
  166. package/library/skills/character-movement/references/movement-3d.md +136 -0
  167. package/library/skills/character-movement/references/platformer-feel.md +83 -0
  168. package/library/skills/character-movement/resource.yaml +40 -0
  169. package/library/skills/character-portrait/SKILL.md +1 -1
  170. package/library/skills/cinematic-cutscene/SKILL.md +1 -1
  171. package/library/skills/combat-basics/SKILL.md +159 -0
  172. package/library/skills/combat-basics/references/projectiles-and-aoe.md +100 -0
  173. package/library/skills/combat-basics/resource.yaml +34 -0
  174. package/library/skills/concept-art/SKILL.md +1 -1
  175. package/library/skills/create-asset-sheet/SKILL.md +1 -1
  176. package/library/skills/debug/SKILL.md +1 -1
  177. package/library/skills/debugging-game-feel/SKILL.md +1 -1
  178. package/library/skills/design-level/SKILL.md +1 -1
  179. package/library/skills/design-mechanic/SKILL.md +1 -1
  180. package/library/skills/design-npc/SKILL.md +1 -1
  181. package/library/skills/diagnosing-perf-regressions/SKILL.md +1 -1
  182. package/library/skills/dispatching-parallel-agents/SKILL.md +1 -1
  183. package/library/skills/driving-the-editor-ui/SKILL.md +1 -1
  184. package/library/skills/environment-kit/SKILL.md +1 -1
  185. package/library/skills/export-and-ship/SKILL.md +1 -1
  186. package/library/skills/fabricating-assets/SKILL.md +1 -1
  187. package/library/skills/facial-and-lipsync/SKILL.md +1 -1
  188. package/library/skills/fps-controller/SKILL.md +9 -7
  189. package/library/skills/fps-controller/resource.yaml +4 -1
  190. package/library/skills/game-feel/SKILL.md +1 -1
  191. package/library/skills/gameskill/SKILL.md +1 -1
  192. package/library/skills/gdscript-patterns/SKILL.md +1 -1
  193. package/library/skills/generate-motion/SKILL.md +9 -9
  194. package/library/skills/generate-motion/resource.yaml +2 -1
  195. package/library/skills/godogen-visual-proof-game-generation/SKILL.md +1 -1
  196. package/library/skills/headless-scripting/SKILL.md +1 -1
  197. package/library/skills/in-game-purchases/SKILL.md +254 -0
  198. package/library/skills/in-game-purchases/resource.yaml +29 -0
  199. package/library/skills/instantiate-asset-pack/SKILL.md +1 -1
  200. package/library/skills/investigating-bugs/SKILL.md +1 -1
  201. package/library/skills/lumera-single-image-scene-reconstruction/SKILL.md +1 -1
  202. package/library/skills/make-game/SKILL.md +25 -3
  203. package/library/skills/make-game/references/2d-platformer-polish.md +93 -0
  204. package/library/skills/make-game/references/2d-platformer.md +117 -0
  205. package/library/skills/make-game/references/2d-rpg-content.md +234 -0
  206. package/library/skills/make-game/references/2d-rpg.md +241 -0
  207. package/library/skills/make-game/references/2d-survivors-progression.md +201 -0
  208. package/library/skills/make-game/references/2d-survivors.md +237 -0
  209. package/library/skills/make-game/references/3d-fps-systems.md +216 -0
  210. package/library/skills/make-game/references/3d-fps.md +177 -0
  211. package/library/skills/make-game/references/3d-horror-systems.md +186 -0
  212. package/library/skills/make-game/references/3d-horror.md +201 -0
  213. package/library/skills/make-game/references/3d-third-person-systems.md +220 -0
  214. package/library/skills/make-game/references/3d-third-person.md +215 -0
  215. package/library/skills/make-game/resource.yaml +6 -1
  216. package/library/skills/multiplayer/SKILL.md +150 -0
  217. package/library/skills/multiplayer/resource.yaml +33 -0
  218. package/library/skills/multiplayer-movement/SKILL.md +510 -0
  219. package/library/skills/multiplayer-movement/files.md +501 -0
  220. package/library/skills/multiplayer-movement/resource.yaml +30 -0
  221. package/library/skills/multiplayer-project/SKILL.md +521 -0
  222. package/library/skills/multiplayer-project/files.md +448 -0
  223. package/library/skills/multiplayer-project/resource.yaml +36 -0
  224. package/library/skills/multiplayer-publish/SKILL.md +229 -0
  225. package/library/skills/multiplayer-publish/export-errors.md +89 -0
  226. package/library/skills/multiplayer-publish/resource.yaml +28 -0
  227. package/library/skills/multiplayer-state/SKILL.md +438 -0
  228. package/library/skills/multiplayer-state/files.md +592 -0
  229. package/library/skills/multiplayer-state/resource.yaml +35 -0
  230. package/library/skills/multiplayer-testing/SKILL.md +236 -0
  231. package/library/skills/multiplayer-testing/resource.yaml +39 -0
  232. package/library/skills/music-track/SKILL.md +1 -1
  233. package/library/skills/navigate-summer/SKILL.md +1 -1
  234. package/library/skills/new-project/SKILL.md +1 -1
  235. package/library/skills/organic-model/SKILL.md +1 -1
  236. package/library/skills/pixel-art/SKILL.md +1 -1
  237. package/library/skills/play/SKILL.md +1 -1
  238. package/library/skills/playtesting-a-feature/SKILL.md +1 -1
  239. package/library/skills/procedural-animation/SKILL.md +2 -2
  240. package/library/skills/procedural-animation/resource.yaml +1 -1
  241. package/library/skills/prop-model/SKILL.md +1 -1
  242. package/library/skills/psx-retro-rendering/SKILL.md +1 -1
  243. package/library/skills/realtime-wet-surfaces/SKILL.md +2 -2
  244. package/library/skills/remote-deploy/SKILL.md +1 -1
  245. package/library/skills/retarget/SKILL.md +1 -1
  246. package/library/skills/running-in-the-cloud/SKILL.md +1 -1
  247. package/library/skills/save-load/SKILL.md +156 -0
  248. package/library/skills/save-load/resource.yaml +27 -0
  249. package/library/skills/scene-composition/SKILL.md +1 -1
  250. package/library/skills/scene-hierarchy-design/SKILL.md +1 -1
  251. package/library/skills/scene-scripting/SKILL.md +1 -1
  252. package/library/skills/scene-to-level/SKILL.md +1 -1
  253. package/library/skills/skill-create/SKILL.md +1 -1
  254. package/library/skills/skill-improve/SKILL.md +1 -1
  255. package/library/skills/skill-test/SKILL.md +1 -1
  256. package/library/skills/skintokens-auto-rigging/SKILL.md +1 -1
  257. package/library/skills/skybox-panorama/SKILL.md +1 -1
  258. package/library/skills/sound-effect/SKILL.md +1 -1
  259. package/library/skills/spatial-placement/SKILL.md +134 -3
  260. package/library/skills/spatial-placement/references/kit-placement-tools.md +364 -0
  261. package/library/skills/spatial-placement/resource.yaml +16 -2
  262. package/library/skills/sprite-sheet/SKILL.md +1 -1
  263. package/library/skills/summer-analytics/SKILL.md +147 -0
  264. package/library/skills/summer-analytics/resource.yaml +28 -0
  265. package/library/skills/summer-friends/SKILL.md +226 -0
  266. package/library/skills/summer-friends/resource.yaml +28 -0
  267. package/library/skills/summer-leaderboards/SKILL.md +231 -0
  268. package/library/skills/summer-leaderboards/resource.yaml +30 -0
  269. package/library/skills/summer-match-results/SKILL.md +286 -0
  270. package/library/skills/summer-match-results/resource.yaml +32 -0
  271. package/library/skills/summer-matchmaking/SKILL.md +301 -0
  272. package/library/skills/summer-matchmaking/resource.yaml +32 -0
  273. package/library/skills/summer-parties/SKILL.md +253 -0
  274. package/library/skills/summer-parties/resource.yaml +30 -0
  275. package/library/skills/summer-player-data/SKILL.md +322 -0
  276. package/library/skills/summer-player-data/resource.yaml +30 -0
  277. package/library/skills/summer-store/SKILL.md +271 -0
  278. package/library/skills/summer-store/resource.yaml +29 -0
  279. package/library/skills/summer-world-chat/SKILL.md +195 -0
  280. package/library/skills/summer-world-chat/resource.yaml +30 -0
  281. package/library/skills/summer-world-saves/SKILL.md +284 -0
  282. package/library/skills/summer-world-saves/resource.yaml +29 -0
  283. package/library/skills/text-to-motion/SKILL.md +99 -0
  284. package/library/skills/text-to-motion/prompts-and-controls.md +34 -0
  285. package/library/skills/text-to-motion/resource.yaml +41 -0
  286. package/library/skills/text-to-motion/rigging-for-text-motion.md +54 -0
  287. package/library/skills/tileable-texture/SKILL.md +1 -1
  288. package/library/skills/trailer-shot/SKILL.md +1 -1
  289. package/library/skills/tune-performance/SKILL.md +1 -1
  290. package/library/skills/ui-basics/SKILL.md +10 -1
  291. package/library/skills/ui-graphics/SKILL.md +1 -1
  292. package/library/skills/use-widget-asset/SKILL.md +1 -1
  293. package/library/skills/using-summer/SKILL.md +2 -2
  294. package/library/skills/using-summer/resource.yaml +2 -2
  295. package/library/skills/vehicle-model/SKILL.md +1 -1
  296. package/library/skills/verification-before-completion/SKILL.md +1 -1
  297. package/library/skills/verifying-scenes/SKILL.md +76 -2
  298. package/library/skills/verifying-scenes/resource.yaml +13 -2
  299. package/library/skills/vfx-dissolve/SKILL.md +1 -1
  300. package/library/skills/vfx-fire/SKILL.md +1 -1
  301. package/library/skills/vfx-hit-spark/SKILL.md +1 -1
  302. package/library/skills/vfx-lightning/SKILL.md +1 -1
  303. package/library/skills/vfx-magic-glow/SKILL.md +1 -1
  304. package/library/skills/vfx-muzzle-flash/SKILL.md +1 -1
  305. package/library/skills/vfx-smoke/SKILL.md +1 -1
  306. package/library/skills/vfx-water-ripple/SKILL.md +1 -1
  307. package/library/skills/voice-line/SKILL.md +1 -1
  308. package/library/skills/web-and-touch-input/SKILL.md +38 -0
  309. package/library/skills/web-and-touch-input/resource.yaml +28 -0
  310. package/library/skills/web-compatibility-look/SKILL.md +62 -0
  311. package/library/skills/web-compatibility-look/resource.yaml +30 -0
  312. package/library/skills/world-building-3d/SKILL.md +8 -1
  313. package/library/skills/world-building-3d/references/spatial-tools.md +1 -1
  314. package/library/skills/world-building-3d/resource.yaml +2 -1
  315. package/library/skills/writing-plans/SKILL.md +1 -1
  316. package/library/skills/writing-skills/SKILL.md +1 -1
  317. package/library/templates/3d-lan-multiplayer-starter/resource.yaml +2 -2
  318. package/library/tools/attach-to-surface/resource.yaml +142 -0
  319. package/library/tools/batch/resource.yaml +9 -3
  320. package/library/tools/connect-ports/resource.yaml +120 -0
  321. package/library/tools/connect-signal/resource.yaml +3 -2
  322. package/library/tools/debug-views/resource.yaml +94 -0
  323. package/library/tools/frame-nodes/resource.yaml +104 -0
  324. package/library/tools/frame-shot/resource.yaml +134 -0
  325. package/library/tools/generate-motion/resource.yaml +44 -9
  326. package/library/tools/get-board/resource.yaml +50 -0
  327. package/library/tools/get-project-context/resource.yaml +13 -2
  328. package/library/tools/grep/resource.yaml +77 -0
  329. package/library/tools/inspect-asset/resource.yaml +71 -0
  330. package/library/tools/inspect-node/resource.yaml +9 -2
  331. package/library/tools/inspect-resource/resource.yaml +16 -5
  332. package/library/tools/instantiate-scene/resource.yaml +27 -2
  333. package/library/tools/measure/resource.yaml +96 -0
  334. package/library/tools/place-adjacent/resource.yaml +113 -0
  335. package/library/tools/play/resource.yaml +15 -2
  336. package/library/tools/raycast/resource.yaml +101 -0
  337. package/library/tools/read-file/resource.yaml +36 -2
  338. package/library/tools/read-library/resource.yaml +2 -2
  339. package/library/tools/repeat-along/resource.yaml +129 -0
  340. package/library/tools/replace-node/resource.yaml +11 -5
  341. package/library/tools/scene-audit/resource.yaml +144 -0
  342. package/library/tools/screenshot/resource.yaml +13 -2
  343. package/library/tools/search-assets/resource.yaml +18 -0
  344. package/library/tools/shot-sheet/resource.yaml +110 -0
  345. package/library/tools/snap-to-surface/resource.yaml +4 -1
  346. package/library/tools/world-snapshot/resource.yaml +24 -3
  347. package/library/tools/zoom/resource.yaml +105 -0
  348. package/package.json +1 -1
  349. package/registry/generated/aliases.json +17 -3
  350. package/registry/generated/counts.json +3 -3
  351. package/registry/generated/gemini-extension.json +26 -4
  352. package/registry/generated/index.json +2154 -469
  353. package/registry/generated/marketplace.claude.json +2 -2
  354. package/registry/generated/plugin.claude.json +27 -5
  355. package/registry/generated/plugin.codex.json +28 -6
  356. package/registry/generated/plugin.cursor.json +27 -5
  357. package/registry/generated/plugin.factory.json +27 -5
  358. package/registry/generated/skills-index.md +36 -14
  359. package/registry/generated/skills-registry.json +421 -124
  360. package/registry/generated/templates-registry.json +2 -2
  361. package/library/skills/host-authoritative-state/SKILL.md +0 -332
  362. package/library/skills/host-authoritative-state/resource.yaml +0 -28
  363. package/library/skills/peer-to-peer-multiplayer/SKILL.md +0 -373
  364. package/library/skills/peer-to-peer-multiplayer/resource.yaml +0 -28
  365. package/library/skills/setup-multiplayer/SKILL.md +0 -336
  366. package/library/skills/setup-multiplayer/resource.yaml +0 -28
@@ -1,11 +1,15 @@
1
1
  import { z } from "zod";
2
- import { type LibrarySearchDeps } from "./library-search.js";
2
+ import { type LibraryIndexEntry, type LibrarySearchDeps } from "./library-search.js";
3
3
  import { type TemplateEntry } from "./templates.js";
4
4
  export declare const READ_PARTS: readonly ["skill", "resource", "all"];
5
5
  export type ReadPart = (typeof READ_PARTS)[number];
6
6
  /** How many content_hash hex chars the footer's entry_id carries. */
7
7
  export declare const FOOTER_HASH_LENGTH = 12;
8
8
  export declare const FOOTER_SUFFIX = "If this entry is wrong, stale, or you deviate from it, report via summer_library_feedback.";
9
+ /** Text files read_library loads when an entry links them. */
10
+ export declare const LINKED_FILE_EXTENSIONS: ReadonlySet<string>;
11
+ /** A linked file larger than this is refused rather than dumped. */
12
+ export declare const LINKED_FILE_MAX_BYTES: number;
9
13
  export declare const readLibraryInputShape: {
10
14
  id: z.ZodString;
11
15
  part: z.ZodOptional<z.ZodEnum<["skill", "resource", "all"]>>;
@@ -15,10 +19,10 @@ export declare const readLibraryInputSchema: z.ZodObject<{
15
19
  part: z.ZodOptional<z.ZodEnum<["skill", "resource", "all"]>>;
16
20
  }, "strict", z.ZodTypeAny, {
17
21
  id: string;
18
- part?: "all" | "skill" | "resource" | undefined;
22
+ part?: "all" | "resource" | "skill" | undefined;
19
23
  }, {
20
24
  id: string;
21
- part?: "all" | "skill" | "resource" | undefined;
25
+ part?: "all" | "resource" | "skill" | undefined;
22
26
  }>;
23
27
  export type ReadLibraryArgs = z.infer<typeof readLibraryInputSchema>;
24
28
  export interface LibraryReadDeps extends LibrarySearchDeps {
@@ -44,6 +48,15 @@ export interface LibraryReadOk {
44
48
  files: string[];
45
49
  /** The file the body came from, when the body is a file. */
46
50
  body_file?: string;
51
+ /** Set when the load is a file the entry ships rather than the entry body:
52
+ * its path inside the entry directory, e.g. "references/kit-placement-tools.md". */
53
+ linked_file?: string;
54
+ /** Relative links in the body and the summer_read_library id that loads
55
+ * each (null: the target is not shipped with this package). */
56
+ links?: Array<{
57
+ target: string;
58
+ id: string | null;
59
+ }>;
47
60
  /** Tool records: how to reach it. */
48
61
  mcp_tool_name?: string;
49
62
  cli_command?: string;
@@ -67,7 +80,26 @@ export type LibraryReadResult = LibraryReadOk | LibraryReadNotFound;
67
80
  export declare function feedbackFooter(id: string, contentHash: string | undefined): string;
68
81
  export declare function entryIdWithHash(id: string, contentHash: string | undefined): string;
69
82
  /**
70
- * Read one entry. `deps.entries`/`deps.packageRoot`/`deps.templates` let
71
- * tests point at a fixture; production reads the installed package.
83
+ * Relative link targets in a markdown body: markdown links outside code
84
+ * (`[x](references/y.md)`, fragment dropped) and inline code spans that name a
85
+ * library file by a relative path (`../../references/gd-style/gd-style.md`,
86
+ * `references/y.md`; a `./scripts/x.gd` span is a project path and is not
87
+ * one). URLs, anchors, absolute paths and fenced code blocks are skipped.
88
+ * Exported for the every-link-resolves test.
89
+ */
90
+ export declare function relativeLinkTargets(markdown: string): string[];
91
+ /**
92
+ * Where a link written in `fromFile` (a path inside `entry`'s directory, ""
93
+ * or "SKILL.md" for the body) points, as the id summer_read_library loads it
94
+ * by; null when the target is not shipped inside library/.
95
+ */
96
+ export declare function resolveLibraryLink(entry: LibraryIndexEntry, fromFile: string, link: string, deps: {
97
+ entries: LibraryIndexEntry[];
98
+ packageRoot?: string;
99
+ }): string | null;
100
+ /**
101
+ * Read one entry, or a file an entry links. `deps.entries`/`deps.packageRoot`/
102
+ * `deps.templates` let tests point at a fixture; production reads the
103
+ * installed package.
72
104
  */
73
105
  export declare function readLibraryEntry(requestedId: string, part?: ReadPart, deps?: LibraryReadDeps): Promise<LibraryReadResult>;
@@ -23,9 +23,18 @@
23
23
  * Metadata comes from registry/generated/index.json (no YAML parser at
24
24
  * runtime); resource.yaml is returned as text. Unknown id -> not_found with
25
25
  * the three nearest ids from searchLibrary.
26
+ *
27
+ * Linked files: a body links files its entry ships (a skill's
28
+ * `references/kit-placement-tools.md`) and other entries
29
+ * (`../multiplayer-project/SKILL.md`, `../../references/gd-style/gd-style.md`).
30
+ * Each loads by `<entry id>/<link as written>`, resolved inside library/ only
31
+ * and for text files only; by the relative path alone when exactly one entry
32
+ * ships it; and `reference/<slug>` that is no entry falls back to the one
33
+ * `references/<slug>.md` an entry ships. A body render ends with its links and
34
+ * the id that loads each. A linked file's footer names its entry.
26
35
  */
27
- import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
28
- import { join } from "node:path";
36
+ import { existsSync, readdirSync, readFileSync, realpathSync, statSync } from "node:fs";
37
+ import { join, posix, sep } from "node:path";
29
38
  import { z } from "zod";
30
39
  import { LIBRARY_KIND_DIRS, loadLibraryIndex, searchLibrary, } from "./library-search.js";
31
40
  import { PACKAGE_ROOT } from "./package-root.js";
@@ -34,12 +43,30 @@ export const READ_PARTS = ["skill", "resource", "all"];
34
43
  /** How many content_hash hex chars the footer's entry_id carries. */
35
44
  export const FOOTER_HASH_LENGTH = 12;
36
45
  export const FOOTER_SUFFIX = "If this entry is wrong, stale, or you deviate from it, report via summer_library_feedback.";
46
+ /** Text files read_library loads when an entry links them. */
47
+ export const LINKED_FILE_EXTENSIONS = new Set([
48
+ ".md",
49
+ ".markdown",
50
+ ".txt",
51
+ ".yaml",
52
+ ".yml",
53
+ ".json",
54
+ ".gd",
55
+ ".gdshader",
56
+ ".shader",
57
+ ".cfg",
58
+ ".tscn",
59
+ ".tres",
60
+ ".csv",
61
+ ]);
62
+ /** A linked file larger than this is refused rather than dumped. */
63
+ export const LINKED_FILE_MAX_BYTES = 256 * 1024;
37
64
  export const readLibraryInputShape = {
38
65
  id: z
39
66
  .string()
40
67
  .min(1)
41
68
  .max(200)
42
- .describe("The entry id as returned by summer_search_library: <kind>/<slug>, e.g. skill/vfx-water-ripple or tool/screenshot."),
69
+ .describe("The entry id as returned by summer_search_library: <kind>/<slug>, e.g. skill/vfx-water-ripple or tool/screenshot. A file an entry links loads by <entry id>/<link as written>, e.g. skill/spatial-placement/references/kit-placement-tools.md; the 'linked files' list at the end of a body gives each id."),
43
70
  part: z
44
71
  .enum(READ_PARTS)
45
72
  .optional()
@@ -71,6 +98,111 @@ function resolveEntry(requested, entries) {
71
98
  }
72
99
  return null;
73
100
  }
101
+ const KIND_BY_DIR = new Map(Object.entries(LIBRARY_KIND_DIRS).map(([kind, dir]) => [dir, kind]));
102
+ const ENTRY_PATH_ID = /^(tool|skill|example|template|collection|reference)\/([a-z0-9]+(?:-[a-z0-9]+)*)\/(.+)$/;
103
+ function entryDirOf(entry) {
104
+ const kind = entry.kind;
105
+ return `library/${LIBRARY_KIND_DIRS[kind] ?? `${kind}s`}/${entry.id.split("/").pop()}`;
106
+ }
107
+ /** Join a link onto a package-relative directory; null when it is absolute,
108
+ * malformed, or leaves library/. */
109
+ function joinInsideLibrary(baseDir, link) {
110
+ let decoded;
111
+ try {
112
+ decoded = decodeURIComponent(link.trim());
113
+ }
114
+ catch {
115
+ return null;
116
+ }
117
+ if (!decoded || /[\u0000-\u001f\\]/.test(decoded) || decoded.startsWith("/") || /^[a-z][a-z0-9+.-]*:/i.test(decoded))
118
+ return null;
119
+ const joined = posix.normalize(posix.join(baseDir, decoded)).replace(/\/+$/, "");
120
+ return joined === "library" || joined.startsWith("library/") ? joined : null;
121
+ }
122
+ /** library/<dir>/<slug>[/<file>] -> the entry and the file inside it. */
123
+ function targetFromLibraryPath(libPath, entries) {
124
+ const parts = libPath.split("/");
125
+ if (parts.length < 3 || parts[0] !== "library")
126
+ return null;
127
+ const kind = KIND_BY_DIR.get(parts[1]);
128
+ if (!kind)
129
+ return null;
130
+ const entry = entries.find((e) => e.id === `${kind}/${parts[2]}`);
131
+ return entry ? { entry, file: parts.slice(3).join("/") } : null;
132
+ }
133
+ function isFileInsideLibrary(root, libPath) {
134
+ const abs = join(root, ...libPath.split("/"));
135
+ try {
136
+ if (!statSync(abs).isFile())
137
+ return false;
138
+ const libraryRoot = realpathSync(join(root, "library"));
139
+ return realpathSync(abs).startsWith(libraryRoot + sep);
140
+ }
141
+ catch {
142
+ return false;
143
+ }
144
+ }
145
+ /** Resolve an id that names a file an entry ships (see the module comment). */
146
+ function resolveLinkedFile(requested, entries, root) {
147
+ const bare = requested.trim();
148
+ const qualified = ENTRY_PATH_ID.exec(bare);
149
+ if (qualified) {
150
+ const entry = entries.find((e) => e.id === `${qualified[1]}/${qualified[2]}`);
151
+ if (entry) {
152
+ const libPath = joinInsideLibrary(entryDirOf(entry), qualified[3]);
153
+ const target = libPath ? targetFromLibraryPath(libPath, entries) : null;
154
+ if (!target || (target.file !== "" && !isFileInsideLibrary(root, libPath)))
155
+ return null;
156
+ return target;
157
+ }
158
+ }
159
+ const shipping = (relative) => entries
160
+ .map((entry) => ({ entry, libPath: joinInsideLibrary(entryDirOf(entry), relative) }))
161
+ .filter((c) => !!c.libPath && c.libPath.startsWith(`${entryDirOf(c.entry)}/`))
162
+ .filter((c) => isFileInsideLibrary(root, c.libPath))
163
+ .map((c) => ({ entry: c.entry, file: c.libPath.slice(entryDirOf(c.entry).length + 1) }));
164
+ // A relative path alone, when exactly one entry ships that file.
165
+ if ((bare.includes("/") || /\.[a-z0-9]+$/i.test(bare)) && !bare.startsWith("../")) {
166
+ const found = shipping(bare.replace(/^\.\//, ""));
167
+ if (found.length === 1)
168
+ return found[0];
169
+ }
170
+ // reference/<slug> that is no entry: the references/<slug>.md one entry ships.
171
+ const asReference = /^references?\/([a-z0-9]+(?:[-_][a-z0-9]+)*)(?:\.md)?$/.exec(bare);
172
+ if (asReference) {
173
+ const found = shipping(`references/${asReference[1]}.md`);
174
+ if (found.length === 1)
175
+ return found[0];
176
+ }
177
+ return null;
178
+ }
179
+ /**
180
+ * Relative link targets in a markdown body: markdown links outside code
181
+ * (`[x](references/y.md)`, fragment dropped) and inline code spans that name a
182
+ * library file by a relative path (`../../references/gd-style/gd-style.md`,
183
+ * `references/y.md`; a `./scripts/x.gd` span is a project path and is not
184
+ * one). URLs, anchors, absolute paths and fenced code blocks are skipped.
185
+ * Exported for the every-link-resolves test.
186
+ */
187
+ export function relativeLinkTargets(markdown) {
188
+ const out = new Set();
189
+ const text = markdown.replace(/^(```|~~~)[^\n]*\n[\s\S]*?^\1[^\n]*$/gm, "");
190
+ for (const match of text.matchAll(/`([^`\n]+)`/g)) {
191
+ const span = match[1].trim();
192
+ if (/^((\.\.\/)+|(\.\/)?references\/)[^\s*?<>|]+\.[A-Za-z0-9]+$/.test(span))
193
+ out.add(span);
194
+ }
195
+ const prose = text.replace(/`[^`\n]*`/g, "");
196
+ for (const match of prose.matchAll(/\]\(\s*<?([^)\s>]+)>?(?:\s+"[^"]*")?\s*\)/g)) {
197
+ const target = match[1];
198
+ if (target.startsWith("#") || target.startsWith("/") || /^[a-z][a-z0-9+.-]*:/i.test(target))
199
+ continue;
200
+ const path = target.split("#")[0];
201
+ if (path)
202
+ out.add(path);
203
+ }
204
+ return [...out];
205
+ }
74
206
  // ── Rendering ──────────────────────────────────────────────────────────────
75
207
  function readText(file) {
76
208
  try {
@@ -109,6 +241,41 @@ function pickBodyFile(kind, slug, dir) {
109
241
  return null;
110
242
  }
111
243
  }
244
+ /** The summer_read_library id that loads a target: the entry id for the
245
+ * entry itself or its body file, else <entry id>/<file>. */
246
+ function canonicalId(target, root) {
247
+ if (target.file === "")
248
+ return target.entry.id;
249
+ const slug = target.entry.id.split("/").pop();
250
+ const body = pickBodyFile(target.entry.kind, slug, join(root, ...entryDirOf(target.entry).split("/")));
251
+ return target.file === body ? target.entry.id : `${target.entry.id}/${target.file}`;
252
+ }
253
+ /**
254
+ * Where a link written in `fromFile` (a path inside `entry`'s directory, ""
255
+ * or "SKILL.md" for the body) points, as the id summer_read_library loads it
256
+ * by; null when the target is not shipped inside library/.
257
+ */
258
+ export function resolveLibraryLink(entry, fromFile, link, deps) {
259
+ const root = deps.packageRoot ?? PACKAGE_ROOT;
260
+ const libPath = joinInsideLibrary(posix.dirname(posix.join(entryDirOf(entry), fromFile || "_")), link);
261
+ if (!libPath)
262
+ return null;
263
+ const target = targetFromLibraryPath(libPath, deps.entries);
264
+ if (!target)
265
+ return null;
266
+ if (target.file !== "" && !isFileInsideLibrary(root, libPath))
267
+ return null;
268
+ return canonicalId(target, root);
269
+ }
270
+ function linksOf(body, entry, fromFile, entries, root) {
271
+ return relativeLinkTargets(body).map((target) => ({ target, id: resolveLibraryLink(entry, fromFile, target, { entries, packageRoot: root }) }));
272
+ }
273
+ function linksSection(links) {
274
+ const lines = ["--- linked files (load each with summer_read_library and the id after the arrow) ---"];
275
+ for (const link of links)
276
+ lines.push(`${link.target} -> ${link.id ?? "(not shipped with this package)"}`);
277
+ return lines.join("\n");
278
+ }
112
279
  function toolBody(entry, slug) {
113
280
  const lines = [];
114
281
  const mcpName = entry.mcp_tool_name ?? `summer_${slug.replace(/-/g, "_")}`;
@@ -179,36 +346,112 @@ function header(entry, slug, related) {
179
346
  }
180
347
  // ── Entry point ────────────────────────────────────────────────────────────
181
348
  /**
182
- * Read one entry. `deps.entries`/`deps.packageRoot`/`deps.templates` let
183
- * tests point at a fixture; production reads the installed package.
349
+ * Read one entry, or a file an entry links. `deps.entries`/`deps.packageRoot`/
350
+ * `deps.templates` let tests point at a fixture; production reads the
351
+ * installed package.
184
352
  */
185
353
  export async function readLibraryEntry(requestedId, part = "all", deps = {}) {
186
354
  const entries = deps.entries ?? loadLibraryIndex();
187
355
  const root = deps.packageRoot ?? PACKAGE_ROOT;
188
- const entry = resolveEntry(requestedId, entries);
356
+ let entry = resolveEntry(requestedId, entries);
357
+ let linkedFile;
189
358
  if (!entry) {
190
- const query = requestedId.replace(/[/@_-]+/g, " ").replace(/[a-f0-9]{8,}/gi, " ").trim() || requestedId;
359
+ const target = resolveLinkedFile(requestedId, entries, root);
360
+ if (target) {
361
+ entry = target.entry;
362
+ const canonical = canonicalId(target, root);
363
+ // The entry's own body file and resource.yaml render as the entry.
364
+ if (target.file === "resource.yaml")
365
+ part = "resource";
366
+ else if (canonical !== entry.id)
367
+ linkedFile = target.file;
368
+ }
369
+ }
370
+ if (!entry) {
371
+ const query = requestedId.replace(/[/@_.-]+/g, " ").replace(/[a-f0-9]{8,}/gi, " ").replace(/\bmd\b/g, " ").trim() || requestedId;
191
372
  const nearest = (await searchLibrary(query, { limit: 3 }, deps)).map((hit) => hit.id);
192
373
  return {
193
374
  ok: false,
194
375
  error: "not_found",
195
376
  id: requestedId,
196
377
  nearest,
197
- hint: nearest.length > 0
378
+ hint: (nearest.length > 0
198
379
  ? `No library entry has id "${requestedId}". Nearest by search: ${nearest.join(", ")}. Ids are <kind>/<slug>; use summer_search_library to find the right one.`
199
- : `No library entry has id "${requestedId}" and nothing similar was found. Ids are <kind>/<slug>; use summer_search_library.`,
380
+ : `No library entry has id "${requestedId}" and nothing similar was found. Ids are <kind>/<slug>; use summer_search_library.`) +
381
+ " A file an entry links loads by <entry id>/<link as written> (inside library/ only).",
200
382
  };
201
383
  }
202
384
  const kind = entry.kind;
203
385
  const slug = entry.id.split("/").pop();
204
- const kindDir = LIBRARY_KIND_DIRS[kind] ?? `${kind}s`;
205
- const relPath = `library/${kindDir}/${slug}`;
206
- const dir = join(root, "library", kindDir, slug);
386
+ const relPath = entryDirOf(entry);
387
+ const dir = join(root, ...relPath.split("/"));
207
388
  const files = listFiles(dir);
208
389
  const related = relatedMap(entry);
390
+ const footer = feedbackFooter(entry.id, entry.content_hash);
391
+ const resourceYaml = readText(join(dir, "resource.yaml"))?.replace(/\s+$/, "") ?? "(resource.yaml not found in this install)";
392
+ const base = {
393
+ ok: true,
394
+ id: entry.id,
395
+ kind: entry.kind,
396
+ slug,
397
+ version: entry.version ?? "",
398
+ status: entry.status ?? "stable",
399
+ content_hash: entry.content_hash ?? "",
400
+ summary: entry.summary ?? "",
401
+ use_when: Array.isArray(entry.use_when) ? entry.use_when : [],
402
+ related,
403
+ part,
404
+ path: relPath,
405
+ files,
406
+ entry_id: entryIdWithHash(entry.id, entry.content_hash),
407
+ footer,
408
+ };
409
+ if (linkedFile !== undefined) {
410
+ const libPath = `${relPath}/${linkedFile}`;
411
+ const extension = posix.extname(linkedFile).toLowerCase();
412
+ const size = (() => {
413
+ try {
414
+ return statSync(join(root, ...libPath.split("/"))).size;
415
+ }
416
+ catch {
417
+ return Number.POSITIVE_INFINITY;
418
+ }
419
+ })();
420
+ const sections = [
421
+ `${entry.id}/${linkedFile} — a file shipped with ${entry.id} (${entry.kind} v${entry.version ?? "?"}, ${entry.status ?? "stable"}). The entry itself: summer_read_library id "${entry.id}".`,
422
+ ];
423
+ let links = [];
424
+ if (part === "resource") {
425
+ sections.push(`--- ${relPath}/resource.yaml ---\n${resourceYaml}`);
426
+ }
427
+ else if (!LINKED_FILE_EXTENSIONS.has(extension)) {
428
+ sections.push(`--- ${libPath} ---\n(not a text file read_library loads: ${extension || "no extension"}; it ships at ${libPath} in the package)`);
429
+ }
430
+ else if (size > LINKED_FILE_MAX_BYTES) {
431
+ sections.push(`--- ${libPath} ---\n(${size} bytes, over the ${LINKED_FILE_MAX_BYTES}-byte limit for a linked file; it ships at ${libPath} in the package)`);
432
+ }
433
+ else {
434
+ const text = readText(join(root, ...libPath.split("/")))?.replace(/\s+$/, "") ?? "(file could not be read)";
435
+ sections.push(`--- ${libPath} ---\n${text}`);
436
+ if (extension === ".md" || extension === ".markdown") {
437
+ links = linksOf(text, entry, linkedFile, entries, root);
438
+ if (links.length > 0)
439
+ sections.push(linksSection(links));
440
+ }
441
+ }
442
+ sections.push(footer);
443
+ return {
444
+ ...base,
445
+ body_file: linkedFile,
446
+ linked_file: linkedFile,
447
+ ...(links.length > 0 ? { links } : {}),
448
+ text: sections.join("\n\n"),
449
+ };
450
+ }
209
451
  let bodyFile;
210
452
  let bodyTitle;
211
453
  let body;
454
+ let links = [];
212
455
  if (kind === "tool") {
213
456
  bodyTitle = "how to call";
214
457
  body = toolBody(entry, slug);
@@ -224,40 +467,28 @@ export async function readLibraryEntry(requestedId, part = "all", deps = {}) {
224
467
  bodyFile = picked;
225
468
  bodyTitle = `${relPath}/${picked}`;
226
469
  body = text.replace(/\s+$/, "");
470
+ if (picked.toLowerCase().endsWith(".md"))
471
+ links = linksOf(body, entry, picked, entries, root);
227
472
  }
228
473
  else {
229
474
  bodyTitle = "body";
230
475
  body = `(no body file shipped for this ${kind}; the descriptor below is all there is)`;
231
476
  }
232
477
  }
233
- const resourceYaml = readText(join(dir, "resource.yaml"))?.replace(/\s+$/, "") ?? "(resource.yaml not found in this install)";
234
- const footer = feedbackFooter(entry.id, entry.content_hash);
235
478
  const sections = [header(entry, slug, related)];
236
- if (part === "skill" || part === "all")
479
+ if (part === "skill" || part === "all") {
237
480
  sections.push(`--- ${bodyTitle} ---\n${body}`);
481
+ if (links.length > 0)
482
+ sections.push(linksSection(links));
483
+ }
238
484
  if (part === "resource" || part === "all")
239
485
  sections.push(`--- ${relPath}/resource.yaml ---\n${resourceYaml}`);
240
486
  sections.push(footer);
241
- const result = {
242
- ok: true,
243
- id: entry.id,
244
- kind: entry.kind,
245
- slug,
246
- version: entry.version ?? "",
247
- status: entry.status ?? "stable",
248
- content_hash: entry.content_hash ?? "",
249
- summary: entry.summary ?? "",
250
- use_when: Array.isArray(entry.use_when) ? entry.use_when : [],
251
- related,
252
- part,
253
- path: relPath,
254
- files,
255
- entry_id: entryIdWithHash(entry.id, entry.content_hash),
256
- footer,
257
- text: sections.join("\n\n"),
258
- };
487
+ const result = { ...base, text: sections.join("\n\n") };
259
488
  if (bodyFile)
260
489
  result.body_file = bodyFile;
490
+ if (links.length > 0 && part !== "resource")
491
+ result.links = links;
261
492
  if (kind === "tool") {
262
493
  if (entry.mcp_tool_name)
263
494
  result.mcp_tool_name = entry.mcp_tool_name;
@@ -96,12 +96,12 @@ export declare const searchLibraryInputSchema: z.ZodObject<{
96
96
  include_preview: z.ZodOptional<z.ZodBoolean>;
97
97
  }, "strict", z.ZodTypeAny, {
98
98
  query: string;
99
- kinds?: ("template" | "tool" | "skill" | "reference" | "example" | "collection")[] | undefined;
99
+ kinds?: ("template" | "tool" | "reference" | "skill" | "example" | "collection")[] | undefined;
100
100
  limit?: number | undefined;
101
101
  include_preview?: boolean | undefined;
102
102
  }, {
103
103
  query: string;
104
- kinds?: ("template" | "tool" | "skill" | "reference" | "example" | "collection")[] | undefined;
104
+ kinds?: ("template" | "tool" | "reference" | "skill" | "example" | "collection")[] | undefined;
105
105
  limit?: number | undefined;
106
106
  include_preview?: boolean | undefined;
107
107
  }>;
@@ -2,7 +2,7 @@ import { existsSync, readFileSync } from "fs";
2
2
  import { copyFile, mkdir, readFile, writeFile } from "fs/promises";
3
3
  import { dirname, join, resolve } from "path";
4
4
  import { fileURLToPath } from "url";
5
- import { isMap, parseDocument } from "yaml";
5
+ import { Document, isMap, parseDocument } from "yaml";
6
6
  import { PACKAGE_ROOT } from "../core/package-root.js";
7
7
  import { agentAliasMap, agentSpec, defaultPathContext, resolveMcpPath, supportedAgents, } from "./agent-table.js";
8
8
  export { supportedAgents } from "./agent-table.js";
@@ -135,7 +135,7 @@ export function renderConfigSnippet(agent, server) {
135
135
  return renderJsonFile(geminiExtensionManifest(server, readBundledGeminiManifestSync()));
136
136
  }
137
137
  if (format === "yaml-goose" || format === "yaml-hermes") {
138
- const doc = parseDocument("{}");
138
+ const doc = new Document({});
139
139
  doc.setIn([topLevelKey(format), SUMMER_MCP_SERVER_NAME], doc.createNode(mcpEntry(format, server)));
140
140
  return doc.toString();
141
141
  }
@@ -250,7 +250,9 @@ async function upsertJsonEntry(path, format, server, write) {
250
250
  */
251
251
  async function upsertYamlConfig(path, keyPath, entry, write) {
252
252
  const current = await readTextFileIfExists(path);
253
- const doc = parseDocument(current.trim() === "" ? "{}" : current);
253
+ // An empty file starts from a fresh block-style document; parseDocument("{}")
254
+ // would make the root a flow mapping and the whole file would render as {}.
255
+ const doc = current.trim() === "" ? new Document({}) : parseDocument(current);
254
256
  if (doc.errors.length > 0) {
255
257
  throw new Error(`Could not parse YAML in ${path}: ${doc.errors[0].message}`);
256
258
  }
@@ -48,6 +48,16 @@ export interface SkillHome {
48
48
  project: ((ctx: PathContext) => string) | null;
49
49
  suffix: string;
50
50
  };
51
+ /**
52
+ * Skill folders Summer 3.1.0 wrote for this agent before it moved to the
53
+ * shared agentskills.io folder (~/.agents/skills). `skills install --force`
54
+ * removes Summer's own skill dirs there so the agent does not load the same
55
+ * skill twice.
56
+ */
57
+ legacyDirs?: {
58
+ user: (ctx: PathContext) => string;
59
+ project: ((ctx: PathContext) => string) | null;
60
+ };
51
61
  }
52
62
  export interface AgentSpec {
53
63
  id: SupportedAgent;
@@ -74,6 +84,10 @@ export interface AgentSpec {
74
84
  skills: SkillHome | null;
75
85
  noSkillsNote?: string;
76
86
  }
87
+ /** True when this location is the shared agentskills.io folder. */
88
+ export declare function isSharedSkillsPath(path: string): boolean;
89
+ /** Agents that read the shared folder at the given scope (for the install summary). */
90
+ export declare function agentsSharingSkills(scope: ConfigScope, ctx: PathContext): AgentSpec[];
77
91
  export declare function agentSpec(id: SupportedAgent): AgentSpec;
78
92
  export declare function allAgentSpecs(): readonly AgentSpec[];
79
93
  /** Ids shown in help and error messages (legacy ids still parse). */
@@ -94,6 +108,8 @@ export interface ResolvedMcpPath {
94
108
  export declare function resolveMcpPath(spec: AgentSpec, scope: ConfigScope, ctx: PathContext): ResolvedMcpPath;
95
109
  /** Rule files a pre-3.1 Summer wrote for this agent at this scope; `null` when the agent never had any. */
96
110
  export declare function legacyRuleFiles(spec: AgentSpec, scope: ConfigScope, ctx: PathContext, skillNames: Iterable<string>): string[] | null;
111
+ /** Skill dirs a Summer 3.1.0 install may have written at this agent's old native location; `null` when it never moved. */
112
+ export declare function legacySkillDirs(spec: AgentSpec, scope: ConfigScope, ctx: PathContext, skillNames: Iterable<string>): string[] | null;
97
113
  export interface ResolvedSkillPath {
98
114
  kind: SkillLocationKind;
99
115
  path: string;