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.
- package/.claude-plugin/marketplace.json +2 -13
- package/.claude-plugin/plugin.json +24 -22
- package/.codex-plugin/plugin.json +18 -22
- package/.cursor-plugin/plugin.json +8 -14
- package/.factory-plugin/plugin.json +6 -13
- package/AGENTS.md +19 -12
- package/CHANGELOG.md +133 -0
- package/GEMINI.md +3 -3
- package/README.md +118 -37
- package/assets/icon.png +0 -0
- package/commands/start.md +71 -0
- package/commands/summer.md +3 -2
- package/dist/cli/banner.js +3 -0
- package/dist/cli/commands/config.js +3 -2
- package/dist/cli/commands/create.js +12 -3
- package/dist/cli/commands/list.d.ts +5 -0
- package/dist/cli/commands/list.js +30 -13
- package/dist/cli/commands/login.d.ts +27 -0
- package/dist/cli/commands/login.js +58 -12
- package/dist/cli/commands/memory.js +6 -2
- package/dist/cli/commands/ops.d.ts +64 -0
- package/dist/cli/commands/ops.js +329 -0
- package/dist/cli/commands/setup.d.ts +4 -0
- package/dist/cli/commands/setup.js +254 -26
- package/dist/cli/commands/skills.js +28 -11
- package/dist/cli/commands/status.d.ts +26 -0
- package/dist/cli/commands/status.js +36 -21
- package/dist/cli/index.js +7 -0
- package/dist/core/agent-host.d.ts +65 -0
- package/dist/core/agent-host.js +193 -0
- package/dist/core/capabilities/agent-playbook.d.ts +3 -0
- package/dist/core/capabilities/agent-playbook.js +54 -2
- package/dist/core/capabilities/apps.d.ts +33 -10
- package/dist/core/capabilities/apps.js +25 -12
- package/dist/core/capabilities/audit/args.d.ts +6 -6
- package/dist/core/capabilities/doctor.d.ts +3 -0
- package/dist/core/capabilities/doctor.js +20 -15
- package/dist/core/capabilities/fabricate-mesh.d.ts +4 -4
- package/dist/core/capabilities/game-task-plan.d.ts +12 -6
- package/dist/core/capabilities/game-task-plan.js +80 -5
- package/dist/core/capabilities/hdri-import.d.ts +2 -2
- package/dist/core/capabilities/motion-generation.d.ts +2 -2
- package/dist/core/capabilities/motion-generation.js +2 -2
- package/dist/core/capabilities/navigation/open.d.ts +6 -2
- package/dist/core/capabilities/navigation/open.js +3 -0
- package/dist/core/capabilities/placement.d.ts +23 -23
- package/dist/core/capabilities/publish-build.js +2 -0
- package/dist/core/capabilities/runtime-control.d.ts +42 -42
- package/dist/core/capabilities/scene-script-target.d.ts +17 -0
- package/dist/core/capabilities/scene-script-target.js +70 -0
- package/dist/core/capabilities/seeing/args.d.ts +16 -16
- package/dist/core/capabilities/sfx-choices.d.ts +4 -0
- package/dist/core/capabilities/sfx-choices.js +13 -6
- package/dist/core/capabilities/tool-dispatch.d.ts +12 -3
- package/dist/core/capabilities/tool-dispatch.js +81 -46
- package/dist/core/capabilities/ui-control.d.ts +2 -2
- package/dist/core/capabilities/world-snapshot.d.ts +4 -4
- package/dist/core/embeddings.d.ts +2 -0
- package/dist/core/embeddings.js +1 -1
- package/dist/core/error-codes.d.ts +62 -0
- package/dist/core/error-codes.js +97 -0
- package/dist/core/format.d.ts +2 -0
- package/dist/core/format.js +2 -1
- package/dist/core/hosted-mcp.d.ts +22 -0
- package/dist/core/hosted-mcp.js +56 -1
- package/dist/core/library-read.js +5 -0
- package/dist/core/library-search.d.ts +2 -2
- package/dist/core/library-search.js +2 -1
- package/dist/core/oauth.js +4 -0
- package/dist/core/ops/areas.d.ts +11 -0
- package/dist/core/ops/areas.js +24 -0
- package/dist/core/ops/catalog.d.ts +45 -0
- package/dist/core/ops/catalog.js +157 -0
- package/dist/core/ops/cloud.d.ts +64 -0
- package/dist/core/ops/cloud.js +198 -0
- package/dist/core/ops/contract.d.ts +120 -0
- package/dist/core/ops/contract.js +134 -0
- package/dist/core/ops/engine-answer.d.ts +25 -0
- package/dist/core/ops/engine-answer.js +117 -0
- package/dist/core/ops/engine.d.ts +55 -0
- package/dist/core/ops/engine.js +649 -0
- package/dist/core/ops/public-catalog.d.ts +48 -0
- package/dist/core/ops/public-catalog.js +56 -0
- package/dist/core/ops/save-files.d.ts +78 -0
- package/dist/core/ops/save-files.js +419 -0
- package/dist/core/ops/search.d.ts +8 -0
- package/dist/core/ops/search.js +187 -0
- package/dist/core/skills-registry.d.ts +16 -1
- package/dist/core/skills-registry.js +35 -2
- package/dist/core/telemetry.d.ts +32 -0
- package/dist/core/telemetry.js +38 -10
- package/dist/core/tool-profiles.d.ts +25 -0
- package/dist/core/tool-profiles.js +41 -0
- package/dist/installer/agent-config.d.ts +17 -4
- package/dist/installer/agent-config.js +27 -6
- package/dist/installer/agent-table.d.ts +12 -0
- package/dist/installer/agent-table.js +33 -9
- package/dist/installer/cli-permissions.d.ts +65 -0
- package/dist/installer/cli-permissions.js +182 -0
- package/dist/installer/setup.d.ts +4 -0
- package/dist/installer/setup.js +12 -4
- package/dist/installer/skills-refresh.d.ts +29 -0
- package/dist/installer/skills-refresh.js +261 -0
- package/dist/installer/version-check.d.ts +51 -11
- package/dist/installer/version-check.js +147 -37
- package/dist/mcp/command.js +7 -0
- package/dist/mcp/hosted-mount.d.ts +27 -2
- package/dist/mcp/hosted-mount.js +53 -23
- package/dist/mcp/legacy-toolset.d.ts +27 -0
- package/dist/mcp/legacy-toolset.js +43 -0
- package/dist/mcp/ops-surface.d.ts +59 -0
- package/dist/mcp/ops-surface.js +453 -0
- package/dist/mcp/server.d.ts +45 -11
- package/dist/mcp/server.js +263 -89
- package/dist/mcp/tool-results.d.ts +26 -0
- package/dist/mcp/tool-results.js +81 -0
- package/dist/mcp/tool-surface.d.ts +65 -0
- package/dist/mcp/tool-surface.js +317 -0
- package/dist/mcp/tools/app-tools.js +9 -2
- package/dist/mcp/tools/asset-tools.js +55 -53
- package/dist/mcp/tools/audit-tools.js +21 -21
- package/dist/mcp/tools/debug-tools.js +6 -6
- package/dist/mcp/tools/fabricate-tools.js +6 -6
- package/dist/mcp/tools/generate-tools.js +76 -70
- package/dist/mcp/tools/project-tools.d.ts +9 -4
- package/dist/mcp/tools/project-tools.js +16 -10
- package/dist/mcp/tools/scene-tools.js +12 -23
- package/dist/mcp/tools/script-tools.js +9 -5
- package/dist/mcp/tools/with-engine.d.ts +6 -0
- package/dist/mcp/tools/with-engine.js +19 -0
- package/dist/project-memory/agent-instructions.d.ts +47 -0
- package/dist/project-memory/agent-instructions.js +226 -0
- package/gemini-extension.json +6 -13
- package/hooks/pre-commit-doctor.sh +5 -4
- package/hooks/session-start.sh +24 -28
- package/integrations/README.md +1 -1
- package/integrations/claude/README.md +6 -0
- package/integrations/claude/manifest-target.json +4 -0
- package/integrations/claude-desktop/README.md +1 -1
- package/integrations/copilot-jetbrains/README.md +1 -1
- package/integrations/gemini/README.md +11 -0
- package/integrations/junie/README.md +1 -1
- package/integrations/lm-studio/README.md +1 -1
- package/integrations/trae/README.md +1 -1
- package/integrations/visual-studio/README.md +1 -1
- package/integrations/windsurf/README.md +1 -1
- package/library/references/mcp-tools-reference/mcp-tools-reference.md +79 -51
- package/library/references/mcp-tools-reference/resource.yaml +1 -1
- package/library/references/product-map/resource.yaml +2 -2
- package/library/skills/3d-lighting/SKILL.md +69 -28
- package/library/skills/3d-lighting/resource.yaml +1 -1
- package/library/skills/README.md +121 -118
- package/library/skills/adaptive-music/SKILL.md +40 -23
- package/library/skills/adaptive-music/resource.yaml +1 -1
- package/library/skills/agent-playtesting/SKILL.md +23 -1
- package/library/skills/agent-playtesting/resource.yaml +1 -1
- package/library/skills/ai-characters-in-games/SKILL.md +16 -1
- package/library/skills/ai-characters-in-games/resource.yaml +1 -1
- package/library/skills/ambient-bed/SKILL.md +38 -13
- package/library/skills/ambient-bed/resource.yaml +1 -1
- package/library/skills/animated-loop/SKILL.md +60 -32
- package/library/skills/animated-loop/resource.yaml +1 -1
- package/library/skills/animation-tree/SKILL.md +27 -1
- package/library/skills/animation-tree/resource.yaml +1 -1
- package/library/skills/art-direction/SKILL.md +17 -3
- package/library/skills/art-direction/resource.yaml +1 -1
- package/library/skills/asset-strategy/SKILL.md +51 -4
- package/library/skills/asset-strategy/resource.yaml +2 -1
- package/library/skills/audio-direction/SKILL.md +26 -10
- package/library/skills/audio-direction/resource.yaml +1 -1
- package/library/skills/auto-fire-targeting/SKILL.md +15 -1
- package/library/skills/auto-fire-targeting/resource.yaml +1 -1
- package/library/skills/bounded-engine-runs/SKILL.md +1 -1
- package/library/skills/bounded-engine-runs/resource.yaml +1 -1
- package/library/skills/brainstorm-game/SKILL.md +14 -1
- package/library/skills/brainstorm-game/resource.yaml +1 -1
- package/library/skills/brainstorming/SKILL.md +1 -1
- package/library/skills/brainstorming/resource.yaml +1 -1
- package/library/skills/browse-templates/SKILL.md +11 -1
- package/library/skills/browse-templates/resource.yaml +1 -1
- package/library/skills/camera-rigs/SKILL.md +22 -2
- package/library/skills/camera-rigs/resource.yaml +1 -1
- package/library/skills/celeste-momentum-platforming/resource.yaml +1 -0
- package/library/skills/character-animation-wiring/SKILL.md +28 -4
- package/library/skills/character-animation-wiring/resource.yaml +1 -1
- package/library/skills/character-model/SKILL.md +83 -47
- package/library/skills/character-model/resource.yaml +1 -1
- package/library/skills/character-movement/SKILL.md +27 -3
- package/library/skills/character-movement/resource.yaml +1 -1
- package/library/skills/character-portrait/SKILL.md +39 -19
- package/library/skills/character-portrait/resource.yaml +1 -1
- package/library/skills/cinematic-cutscene/SKILL.md +79 -46
- package/library/skills/cinematic-cutscene/resource.yaml +1 -1
- package/library/skills/combat-basics/SKILL.md +20 -1
- package/library/skills/combat-basics/resource.yaml +1 -1
- package/library/skills/compatibility-renderer-traps/SKILL.md +12 -1
- package/library/skills/compatibility-renderer-traps/resource.yaml +1 -1
- package/library/skills/concept-art/SKILL.md +29 -12
- package/library/skills/concept-art/resource.yaml +1 -1
- package/library/skills/concept-to-level/SKILL.md +258 -0
- package/library/skills/concept-to-level/references/technical-rules.md +150 -0
- package/library/skills/concept-to-level/resource.yaml +44 -0
- package/library/skills/create-asset-sheet/SKILL.md +37 -13
- package/library/skills/create-asset-sheet/resource.yaml +1 -1
- package/library/skills/debug/SKILL.md +34 -2
- package/library/skills/debug/resource.yaml +1 -1
- package/library/skills/debugging-game-feel/SKILL.md +13 -1
- package/library/skills/debugging-game-feel/resource.yaml +1 -1
- package/library/skills/design-level/SKILL.md +40 -35
- package/library/skills/design-level/resource.yaml +1 -1
- package/library/skills/design-mechanic/SKILL.md +18 -1
- package/library/skills/design-mechanic/resource.yaml +1 -1
- package/library/skills/design-npc/SKILL.md +43 -24
- package/library/skills/design-npc/resource.yaml +1 -1
- package/library/skills/diagnosing-perf-regressions/SKILL.md +13 -1
- package/library/skills/diagnosing-perf-regressions/resource.yaml +1 -1
- package/library/skills/driving-the-editor-ui/SKILL.md +24 -1
- package/library/skills/driving-the-editor-ui/resource.yaml +1 -1
- package/library/skills/environment-kit/SKILL.md +43 -16
- package/library/skills/environment-kit/resource.yaml +1 -1
- package/library/skills/export-and-ship/SKILL.md +29 -6
- package/library/skills/export-and-ship/resource.yaml +1 -1
- package/library/skills/fabricating-assets/SKILL.md +30 -7
- package/library/skills/fabricating-assets/resource.yaml +3 -3
- package/library/skills/facial-and-lipsync/SKILL.md +36 -15
- package/library/skills/facial-and-lipsync/resource.yaml +1 -1
- package/library/skills/fps-controller/SKILL.md +50 -41
- package/library/skills/fps-controller/resource.yaml +1 -1
- package/library/skills/game-feel/SKILL.md +34 -8
- package/library/skills/game-feel/resource.yaml +1 -1
- package/library/skills/gameskill/SKILL.md +15 -4
- package/library/skills/gameskill/resource.yaml +1 -1
- package/library/skills/gdscript-patterns/SKILL.md +16 -1
- package/library/skills/gdscript-patterns/resource.yaml +1 -1
- package/library/skills/generate-motion/SKILL.md +51 -21
- package/library/skills/generate-motion/resource.yaml +1 -1
- package/library/skills/godogen-visual-proof-game-generation/SKILL.md +18 -1
- package/library/skills/godogen-visual-proof-game-generation/resource.yaml +1 -0
- package/library/skills/grow-analytics/SKILL.md +13 -3
- package/library/skills/grow-analytics/resource.yaml +1 -1
- package/library/skills/headless-scripting/SKILL.md +14 -1
- package/library/skills/headless-scripting/resource.yaml +1 -1
- package/library/skills/in-game-purchases/SKILL.md +12 -1
- package/library/skills/in-game-purchases/resource.yaml +1 -1
- package/library/skills/instantiate-asset-pack/SKILL.md +19 -2
- package/library/skills/instantiate-asset-pack/resource.yaml +1 -1
- package/library/skills/lumera-single-image-scene-reconstruction/resource.yaml +1 -0
- package/library/skills/make-game/SKILL.md +33 -4
- package/library/skills/make-game/references/2d-platformer.md +1 -1
- package/library/skills/make-game/references/3d-fps.md +1 -1
- package/library/skills/make-game/references/3d-horror.md +1 -1
- package/library/skills/make-game/references/3d-third-person.md +2 -2
- package/library/skills/make-game/resource.yaml +1 -1
- package/library/skills/multiplayer/SKILL.md +13 -1
- package/library/skills/multiplayer/resource.yaml +1 -1
- package/library/skills/multiplayer-movement/SKILL.md +19 -1
- package/library/skills/multiplayer-movement/resource.yaml +1 -1
- package/library/skills/multiplayer-project/SKILL.md +18 -1
- package/library/skills/multiplayer-project/resource.yaml +1 -1
- package/library/skills/multiplayer-publish/SKILL.md +25 -7
- package/library/skills/multiplayer-publish/resource.yaml +3 -3
- package/library/skills/multiplayer-state/SKILL.md +17 -1
- package/library/skills/multiplayer-state/resource.yaml +1 -1
- package/library/skills/multiplayer-testing/SKILL.md +16 -1
- package/library/skills/multiplayer-testing/resource.yaml +1 -1
- package/library/skills/music-track/SKILL.md +38 -13
- package/library/skills/music-track/resource.yaml +1 -1
- package/library/skills/navigate-summer/SKILL.md +26 -9
- package/library/skills/navigate-summer/resource.yaml +1 -1
- package/library/skills/new-project/SKILL.md +12 -1
- package/library/skills/new-project/resource.yaml +1 -1
- package/library/skills/organic-model/SKILL.md +48 -18
- package/library/skills/organic-model/resource.yaml +1 -1
- package/library/skills/pixel-art/SKILL.md +42 -23
- package/library/skills/pixel-art/resource.yaml +1 -1
- package/library/skills/play/SKILL.md +19 -1
- package/library/skills/play/resource.yaml +1 -1
- package/library/skills/playtesting-a-feature/SKILL.md +24 -1
- package/library/skills/playtesting-a-feature/resource.yaml +1 -1
- package/library/skills/procedural-animation/SKILL.md +38 -16
- package/library/skills/procedural-animation/resource.yaml +1 -1
- package/library/skills/prop-model/SKILL.md +48 -19
- package/library/skills/prop-model/resource.yaml +1 -1
- package/library/skills/psx-retro-rendering/resource.yaml +1 -0
- package/library/skills/publish-your-game/SKILL.md +43 -6
- package/library/skills/publish-your-game/resource.yaml +3 -3
- package/library/skills/realtime-wet-surfaces/resource.yaml +1 -0
- package/library/skills/release-readiness/SKILL.md +13 -1
- package/library/skills/release-readiness/resource.yaml +1 -1
- package/library/skills/remote-deploy/SKILL.md +15 -1
- package/library/skills/remote-deploy/resource.yaml +1 -1
- package/library/skills/retarget/SKILL.md +43 -20
- package/library/skills/retarget/resource.yaml +1 -1
- package/library/skills/running-in-the-cloud/SKILL.md +11 -1
- package/library/skills/running-in-the-cloud/resource.yaml +1 -1
- package/library/skills/save-load/SKILL.md +16 -1
- package/library/skills/save-load/resource.yaml +1 -1
- package/library/skills/scene-composition/SKILL.md +18 -1
- package/library/skills/scene-composition/resource.yaml +1 -1
- package/library/skills/scene-hierarchy-design/SKILL.md +26 -2
- package/library/skills/scene-hierarchy-design/resource.yaml +1 -1
- package/library/skills/scene-scripting/SKILL.md +96 -636
- package/library/skills/scene-scripting/references/ctx-api.md +184 -0
- package/library/skills/scene-scripting/references/recipes-2d-ui.md +193 -0
- package/library/skills/scene-scripting/references/recipes-3d.md +280 -0
- package/library/skills/scene-scripting/resource.yaml +4 -4
- package/library/skills/scene-to-level/SKILL.md +24 -2
- package/library/skills/scene-to-level/resource.yaml +1 -1
- package/library/skills/skill-create/resource.yaml +1 -0
- package/library/skills/skill-improve/resource.yaml +1 -0
- package/library/skills/skill-test/SKILL.md +12 -2
- package/library/skills/skill-test/resource.yaml +1 -0
- package/library/skills/skintokens-auto-rigging/resource.yaml +1 -0
- package/library/skills/skybox-panorama/SKILL.md +47 -21
- package/library/skills/skybox-panorama/resource.yaml +1 -1
- package/library/skills/sound-effect/SKILL.md +52 -20
- package/library/skills/sound-effect/resource.yaml +1 -1
- package/library/skills/spatial-placement/SKILL.md +44 -9
- package/library/skills/spatial-placement/resource.yaml +1 -1
- package/library/skills/sprite-sheet/SKILL.md +55 -27
- package/library/skills/sprite-sheet/resource.yaml +1 -1
- package/library/skills/store-art/SKILL.md +14 -3
- package/library/skills/store-art/resource.yaml +2 -2
- package/library/skills/store-listing/SKILL.md +13 -3
- package/library/skills/store-listing/resource.yaml +2 -2
- package/library/skills/summer-analytics/SKILL.md +22 -5
- package/library/skills/summer-analytics/resource.yaml +2 -2
- package/library/skills/summer-apps/SKILL.md +77 -32
- package/library/skills/summer-apps/manifest.md +1 -1
- package/library/skills/summer-apps/minimal-app.md +7 -7
- package/library/skills/summer-apps/resource.yaml +1 -1
- package/library/skills/summer-apps/sdk-reference.md +5 -5
- package/library/skills/summer-apps-design/SKILL.md +1 -1
- package/library/skills/summer-apps-design/resource.yaml +1 -1
- package/library/skills/summer-assets/SKILL.md +86 -0
- package/library/skills/summer-assets/resource.yaml +34 -0
- package/library/skills/summer-cli/SKILL.md +133 -0
- package/library/skills/summer-cli/resource.yaml +31 -0
- package/library/skills/summer-friends/SKILL.md +14 -0
- package/library/skills/summer-leaderboards/SKILL.md +16 -0
- package/library/skills/summer-match-results/SKILL.md +17 -0
- package/library/skills/summer-matchmaking/SKILL.md +17 -0
- package/library/skills/summer-parties/SKILL.md +14 -0
- package/library/skills/summer-player-data/SKILL.md +14 -0
- package/library/skills/summer-store/SKILL.md +16 -1
- package/library/skills/summer-world-chat/SKILL.md +14 -0
- package/library/skills/summer-world-saves/SKILL.md +14 -0
- package/library/skills/text-to-motion/SKILL.md +45 -23
- package/library/skills/text-to-motion/prompts-and-controls.md +5 -5
- package/library/skills/text-to-motion/resource.yaml +1 -1
- package/library/skills/text-to-motion/rigging-for-text-motion.md +2 -2
- package/library/skills/tileable-texture/SKILL.md +37 -15
- package/library/skills/tileable-texture/resource.yaml +1 -1
- package/library/skills/trailer-shot/SKILL.md +46 -24
- package/library/skills/trailer-shot/resource.yaml +1 -1
- package/library/skills/tune-performance/SKILL.md +32 -6
- package/library/skills/tune-performance/resource.yaml +1 -1
- package/library/skills/ui-basics/SKILL.md +55 -36
- package/library/skills/ui-basics/resource.yaml +1 -1
- package/library/skills/ui-graphics/SKILL.md +64 -38
- package/library/skills/ui-graphics/resource.yaml +1 -1
- package/library/skills/use-widget-asset/SKILL.md +15 -1
- package/library/skills/use-widget-asset/resource.yaml +1 -1
- package/library/skills/using-summer/SKILL.md +32 -5
- package/library/skills/using-summer/resource.yaml +3 -2
- package/library/skills/vehicle-model/SKILL.md +92 -57
- package/library/skills/vehicle-model/resource.yaml +1 -1
- package/library/skills/verification-before-completion/SKILL.md +1 -1
- package/library/skills/verification-before-completion/resource.yaml +1 -1
- package/library/skills/verifying-scenes/SKILL.md +31 -2
- package/library/skills/verifying-scenes/resource.yaml +1 -1
- package/library/skills/vfx-dissolve/SKILL.md +21 -2
- package/library/skills/vfx-dissolve/resource.yaml +1 -1
- package/library/skills/vfx-fire/SKILL.md +41 -41
- package/library/skills/vfx-fire/resource.yaml +1 -1
- package/library/skills/vfx-hit-spark/SKILL.md +24 -1
- package/library/skills/vfx-hit-spark/resource.yaml +1 -1
- package/library/skills/vfx-lightning/SKILL.md +30 -16
- package/library/skills/vfx-lightning/resource.yaml +1 -1
- package/library/skills/vfx-magic-glow/SKILL.md +46 -32
- package/library/skills/vfx-magic-glow/resource.yaml +1 -1
- package/library/skills/vfx-muzzle-flash/SKILL.md +43 -35
- package/library/skills/vfx-muzzle-flash/resource.yaml +1 -1
- package/library/skills/vfx-smoke/SKILL.md +39 -31
- package/library/skills/vfx-smoke/resource.yaml +1 -1
- package/library/skills/vfx-water-ripple/SKILL.md +35 -31
- package/library/skills/vfx-water-ripple/resource.yaml +1 -1
- package/library/skills/voice-line/SKILL.md +87 -40
- package/library/skills/voice-line/resource.yaml +1 -1
- package/library/skills/web-and-touch-input/SKILL.md +20 -1
- package/library/skills/web-and-touch-input/resource.yaml +1 -1
- package/library/skills/web-compatibility-look/SKILL.md +21 -1
- package/library/skills/web-compatibility-look/resource.yaml +1 -1
- package/library/skills/world-building-3d/SKILL.md +29 -1
- package/library/skills/world-building-3d/resource.yaml +1 -1
- package/library/skills/writing-skills/resource.yaml +1 -0
- package/library/tools/add-node/GUIDE.md +14 -0
- package/library/tools/align-distribute-3d/GUIDE.md +7 -0
- package/library/tools/app-call/resource.yaml +1 -1
- package/library/tools/app-guide/resource.yaml +2 -2
- package/library/tools/app-page/resource.yaml +1 -1
- package/library/tools/app-screenshot/resource.yaml +19 -1
- package/library/tools/app-tools/resource.yaml +1 -1
- package/library/tools/attach-to-surface/GUIDE.md +15 -0
- package/library/tools/batch/GUIDE.md +27 -0
- package/library/tools/camera-bookmark/GUIDE.md +12 -0
- package/library/tools/capture-gameplay/GUIDE.md +3 -0
- package/library/tools/capture-gameplay/resource.yaml +3 -3
- package/library/tools/check-job/resource.yaml +1 -1
- package/library/tools/clear-console/GUIDE.md +3 -0
- package/library/tools/connect-ports/GUIDE.md +9 -0
- package/library/tools/connect-signal/GUIDE.md +14 -0
- package/library/tools/create-debug-report/GUIDE.md +10 -0
- package/library/tools/create-scene/GUIDE.md +10 -0
- package/library/tools/debug-views/GUIDE.md +7 -0
- package/library/tools/enable-plugin/GUIDE.md +3 -0
- package/library/tools/export-game/GUIDE.md +3 -0
- package/library/tools/export-game/resource.yaml +3 -3
- package/library/tools/export-templates/GUIDE.md +3 -0
- package/library/tools/fabricate-3d/GUIDE.md +19 -0
- package/library/tools/frame-nodes/GUIDE.md +9 -0
- package/library/tools/frame-shot/GUIDE.md +9 -0
- package/library/tools/game-control/GUIDE.md +9 -0
- package/library/tools/game-input/GUIDE.md +9 -0
- package/library/tools/game-probe/GUIDE.md +9 -0
- package/library/tools/generate-3d/resource.yaml +3 -3
- package/library/tools/generate-motion/resource.yaml +2 -2
- package/library/tools/get-console/GUIDE.md +9 -0
- package/library/tools/get-console/resource.yaml +5 -0
- package/library/tools/get-debugger-errors/GUIDE.md +7 -0
- package/library/tools/get-debugger-errors/resource.yaml +5 -0
- package/library/tools/get-debugger-warnings/GUIDE.md +7 -0
- package/library/tools/get-debugger-warnings/resource.yaml +5 -0
- package/library/tools/get-diagnostics/GUIDE.md +13 -0
- package/library/tools/get-project-context/GUIDE.md +25 -0
- package/library/tools/get-runtime-tree/GUIDE.md +7 -0
- package/library/tools/get-runtime-tree/resource.yaml +5 -0
- package/library/tools/get-scene-tree/GUIDE.md +11 -0
- package/library/tools/get-scene-tree/resource.yaml +5 -0
- package/library/tools/get-script-errors/GUIDE.md +5 -0
- package/library/tools/grep/GUIDE.md +11 -0
- package/library/tools/import-asset/GUIDE.md +8 -0
- package/library/tools/import-asset-by-id/GUIDE.md +12 -0
- package/library/tools/import-from-url/GUIDE.md +10 -0
- package/library/tools/import-from-url-batch/GUIDE.md +3 -0
- package/library/tools/import-hdri/GUIDE.md +16 -0
- package/library/tools/input-map-bind/GUIDE.md +11 -0
- package/library/tools/inspect-asset/GUIDE.md +14 -0
- package/library/tools/inspect-asset/resource.yaml +5 -0
- package/library/tools/inspect-node/GUIDE.md +11 -0
- package/library/tools/inspect-node/resource.yaml +5 -0
- package/library/tools/inspect-resource/GUIDE.md +7 -0
- package/library/tools/inspect-resource/resource.yaml +5 -0
- package/library/tools/inspect-runtime-node/GUIDE.md +7 -0
- package/library/tools/inspect-runtime-node/resource.yaml +5 -0
- package/library/tools/instantiate-scene/GUIDE.md +12 -0
- package/library/tools/is-running/GUIDE.md +3 -0
- package/library/tools/measure/GUIDE.md +8 -0
- package/library/tools/navigation-probe/GUIDE.md +9 -0
- package/library/tools/open/resource.yaml +2 -2
- package/library/tools/open-main-scene/GUIDE.md +6 -0
- package/library/tools/open-scene/GUIDE.md +8 -0
- package/library/tools/place-adjacent/GUIDE.md +7 -0
- package/library/tools/play/GUIDE.md +13 -0
- package/library/tools/project-setting/GUIDE.md +9 -0
- package/library/tools/publish-build/resource.yaml +6 -6
- package/library/tools/raycast/GUIDE.md +7 -0
- package/library/tools/read-file/GUIDE.md +10 -0
- package/library/tools/read-library/resource.yaml +5 -0
- package/library/tools/recent-events/GUIDE.md +7 -0
- package/library/tools/remove-node/GUIDE.md +3 -0
- package/library/tools/repeat-along/GUIDE.md +5 -0
- package/library/tools/replace-node/GUIDE.md +9 -0
- package/library/tools/replace-text/GUIDE.md +5 -0
- package/library/tools/run-editor-script/GUIDE.md +16 -0
- package/library/tools/run-script/GUIDE.md +30 -0
- package/library/tools/run-script/resource.yaml +6 -3
- package/library/tools/runtime-animate/GUIDE.md +7 -0
- package/library/tools/runtime-call/GUIDE.md +7 -0
- package/library/tools/runtime-set/GUIDE.md +9 -0
- package/library/tools/runtime-spawn/GUIDE.md +9 -0
- package/library/tools/save-scene/GUIDE.md +3 -0
- package/library/tools/scene-audit/GUIDE.md +29 -0
- package/library/tools/screenshot/GUIDE.md +17 -0
- package/library/tools/select-node/GUIDE.md +3 -0
- package/library/tools/set-prop/GUIDE.md +23 -0
- package/library/tools/set-resource-property/GUIDE.md +8 -0
- package/library/tools/shot-sheet/GUIDE.md +7 -0
- package/library/tools/snap-to-surface/GUIDE.md +17 -0
- package/library/tools/snapshot-diff/GUIDE.md +7 -0
- package/library/tools/starcast/GUIDE.md +12 -0
- package/library/tools/stop/GUIDE.md +3 -0
- package/library/tools/test-placement/GUIDE.md +7 -0
- package/library/tools/ui-actions/GUIDE.md +12 -0
- package/library/tools/ui-activate/GUIDE.md +11 -0
- package/library/tools/ui-screenshot/GUIDE.md +9 -0
- package/library/tools/ui-tree/GUIDE.md +10 -0
- package/library/tools/wait-for-event/GUIDE.md +11 -0
- package/library/tools/world-snapshot/GUIDE.md +9 -0
- package/library/tools/write-file/GUIDE.md +5 -0
- package/library/tools/zoom/GUIDE.md +5 -0
- package/package.json +8 -5
- package/registry/generated/counts.json +2 -2
- package/registry/generated/gemini-extension.json +6 -13
- package/registry/generated/index.json +482 -349
- package/registry/generated/marketplace.claude.json +2 -13
- package/registry/generated/plugin.claude-directory.json +168 -0
- package/registry/generated/plugin.claude.json +24 -22
- package/registry/generated/plugin.codex.json +18 -22
- package/registry/generated/plugin.cursor.json +8 -14
- package/registry/generated/plugin.factory.json +6 -13
- package/registry/generated/server.json +43 -0
- package/registry/generated/skills-index.md +121 -118
- package/registry/generated/skills-registry.json +167 -115
- package/registry/operations/fixtures/invalid-deprecated-without-replacement.json +60 -0
- package/registry/operations/fixtures/invalid-name.json +60 -0
- package/registry/operations/fixtures/invalid-publish-without-owner.json +82 -0
- package/registry/operations/fixtures/invalid-spend-without-estimate.json +42 -0
- package/registry/operations/fixtures/invalid-unknown-field.json +61 -0
- package/registry/operations/fixtures/valid-player-facing.json +82 -0
- package/registry/operations/fixtures/valid-read.json +60 -0
- package/registry/operations/fixtures/valid-spend.json +43 -0
- package/registry/operations/legacy-names.json +1241 -0
- package/registry/operations/public-catalog.json +33160 -0
- package/registry/schemas/operation.schema.json +318 -0
- package/registry/schemas/skill.schema.json +4 -0
- 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
|
-
|
|
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: `
|
|
111
|
-
*
|
|
112
|
-
|
|
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
|
-
|
|
73
|
-
const url = options.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
|
-
|
|
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
|
-
|
|
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
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
*
|
|
219
|
-
|
|
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
|
-
|
|
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: `
|
|
228
|
-
*
|
|
229
|
-
|
|
230
|
-
|
|
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
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
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
|
-
|
|
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
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
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) {
|