summer-engine 3.7.0 → 4.0.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 +25 -22
- package/.codex-plugin/plugin.json +8 -14
- package/.cursor-plugin/plugin.json +7 -13
- package/.factory-plugin/plugin.json +7 -13
- package/AGENTS.md +19 -12
- package/CHANGELOG.md +112 -0
- package/GEMINI.md +3 -3
- package/README.md +111 -31
- package/assets/icon.png +0 -0
- package/commands/start.md +71 -0
- package/commands/summer.md +5 -3
- package/dist/cli/banner.js +3 -0
- package/dist/cli/commands/login.d.ts +27 -0
- package/dist/cli/commands/login.js +58 -12
- package/dist/cli/commands/ops.d.ts +47 -0
- package/dist/cli/commands/ops.js +301 -0
- package/dist/cli/commands/setup.d.ts +2 -0
- package/dist/cli/commands/setup.js +37 -12
- package/dist/cli/commands/skills.js +11 -7
- 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 +341 -0
- package/dist/core/capabilities/apps.js +353 -0
- package/dist/core/capabilities/doctor.d.ts +3 -0
- package/dist/core/capabilities/doctor.js +20 -15
- package/dist/core/capabilities/enable-plugin.d.ts +27 -0
- package/dist/core/capabilities/enable-plugin.js +75 -0
- package/dist/core/capabilities/fabricate-mesh.d.ts +2 -2
- 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/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/publish-build.js +2 -0
- package/dist/core/capabilities/runtime-control.d.ts +4 -4
- 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/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 +130 -46
- package/dist/core/capability-skew.js +4 -0
- 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.js +2 -1
- package/dist/core/oauth.js +4 -0
- package/dist/core/ops/catalog.d.ts +41 -0
- package/dist/core/ops/catalog.js +145 -0
- package/dist/core/ops/cloud.d.ts +56 -0
- package/dist/core/ops/cloud.js +175 -0
- package/dist/core/ops/contract.d.ts +119 -0
- package/dist/core/ops/contract.js +142 -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/save-files.d.ts +78 -0
- package/dist/core/ops/save-files.js +419 -0
- package/dist/core/ops/search.d.ts +9 -0
- package/dist/core/ops/search.js +55 -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 +22 -6
- package/dist/installer/agent-table.d.ts +3 -0
- package/dist/installer/agent-table.js +10 -7
- package/dist/installer/setup.d.ts +2 -0
- package/dist/installer/setup.js +9 -4
- package/dist/installer/version-check.d.ts +29 -9
- package/dist/installer/version-check.js +81 -28
- package/dist/mcp/command.js +7 -0
- package/dist/mcp/hosted-mount.d.ts +27 -2
- package/dist/mcp/hosted-mount.js +66 -24
- 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 +443 -0
- package/dist/mcp/server.d.ts +35 -11
- package/dist/mcp/server.js +236 -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.d.ts +2 -0
- package/dist/mcp/tools/app-tools.js +71 -0
- 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/gemini-extension.json +6 -12
- package/hooks/pre-commit-doctor.sh +5 -4
- package/hooks/session-start.sh +24 -28
- package/integrations/claude-desktop/README.md +1 -1
- package/integrations/copilot-jetbrains/README.md +1 -1
- 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/library/references/mcp-tools-reference/mcp-tools-reference.md +85 -35
- 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 +53 -28
- package/library/skills/3d-lighting/resource.yaml +1 -1
- package/library/skills/README.md +126 -116
- package/library/skills/adaptive-music/SKILL.md +19 -23
- package/library/skills/adaptive-music/resource.yaml +1 -1
- package/library/skills/agent-playtesting/SKILL.md +1 -1
- package/library/skills/agent-playtesting/resource.yaml +1 -1
- package/library/skills/ai-characters-in-games/SKILL.md +1 -1
- package/library/skills/ai-characters-in-games/resource.yaml +1 -1
- package/library/skills/ambient-bed/SKILL.md +22 -13
- package/library/skills/ambient-bed/resource.yaml +1 -1
- package/library/skills/animated-loop/SKILL.md +41 -32
- package/library/skills/animated-loop/resource.yaml +1 -1
- package/library/skills/animation-tree/SKILL.md +1 -1
- package/library/skills/animation-tree/resource.yaml +1 -1
- package/library/skills/art-direction/SKILL.md +3 -3
- package/library/skills/art-direction/resource.yaml +1 -1
- package/library/skills/asset-strategy/SKILL.md +21 -4
- package/library/skills/asset-strategy/resource.yaml +2 -1
- package/library/skills/audio-direction/SKILL.md +10 -10
- package/library/skills/audio-direction/resource.yaml +1 -1
- package/library/skills/auto-fire-targeting/SKILL.md +1 -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 +1 -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 +1 -1
- package/library/skills/browse-templates/resource.yaml +1 -1
- package/library/skills/camera-rigs/SKILL.md +2 -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 +4 -4
- package/library/skills/character-animation-wiring/resource.yaml +1 -1
- package/library/skills/character-model/SKILL.md +55 -47
- package/library/skills/character-model/resource.yaml +1 -1
- package/library/skills/character-movement/SKILL.md +3 -3
- package/library/skills/character-movement/resource.yaml +1 -1
- package/library/skills/character-portrait/SKILL.md +24 -19
- package/library/skills/character-portrait/resource.yaml +1 -1
- package/library/skills/cinematic-cutscene/SKILL.md +58 -46
- package/library/skills/cinematic-cutscene/resource.yaml +1 -1
- package/library/skills/combat-basics/SKILL.md +1 -1
- package/library/skills/combat-basics/resource.yaml +1 -1
- package/library/skills/compatibility-renderer-traps/SKILL.md +1 -1
- package/library/skills/compatibility-renderer-traps/resource.yaml +1 -1
- package/library/skills/concept-art/SKILL.md +16 -12
- package/library/skills/concept-art/resource.yaml +1 -1
- package/library/skills/concept-to-level/SKILL.md +239 -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 +19 -13
- package/library/skills/create-asset-sheet/resource.yaml +1 -1
- package/library/skills/debug/SKILL.md +2 -2
- package/library/skills/debug/resource.yaml +1 -1
- package/library/skills/debugging-game-feel/SKILL.md +1 -1
- package/library/skills/debugging-game-feel/resource.yaml +1 -1
- package/library/skills/design-level/SKILL.md +23 -35
- package/library/skills/design-level/resource.yaml +1 -1
- package/library/skills/design-mechanic/SKILL.md +1 -1
- package/library/skills/design-mechanic/resource.yaml +1 -1
- package/library/skills/design-npc/SKILL.md +22 -24
- package/library/skills/design-npc/resource.yaml +1 -1
- package/library/skills/diagnosing-perf-regressions/SKILL.md +1 -1
- package/library/skills/diagnosing-perf-regressions/resource.yaml +1 -1
- package/library/skills/driving-the-editor-ui/SKILL.md +1 -1
- package/library/skills/driving-the-editor-ui/resource.yaml +1 -1
- package/library/skills/environment-kit/SKILL.md +20 -16
- package/library/skills/environment-kit/resource.yaml +1 -1
- package/library/skills/export-and-ship/SKILL.md +6 -6
- package/library/skills/export-and-ship/resource.yaml +1 -1
- package/library/skills/fabricating-assets/SKILL.md +7 -7
- package/library/skills/fabricating-assets/resource.yaml +3 -3
- package/library/skills/facial-and-lipsync/SKILL.md +14 -15
- package/library/skills/facial-and-lipsync/resource.yaml +1 -1
- package/library/skills/fps-controller/SKILL.md +33 -41
- package/library/skills/fps-controller/resource.yaml +1 -1
- package/library/skills/game-feel/SKILL.md +8 -8
- package/library/skills/game-feel/resource.yaml +1 -1
- package/library/skills/gameskill/SKILL.md +4 -4
- package/library/skills/gameskill/resource.yaml +1 -1
- package/library/skills/gdscript-patterns/SKILL.md +1 -1
- package/library/skills/gdscript-patterns/resource.yaml +1 -1
- package/library/skills/generate-motion/SKILL.md +30 -21
- package/library/skills/generate-motion/resource.yaml +1 -1
- package/library/skills/godogen-visual-proof-game-generation/SKILL.md +1 -1
- package/library/skills/godogen-visual-proof-game-generation/resource.yaml +1 -0
- package/library/skills/grow-analytics/SKILL.md +3 -3
- package/library/skills/grow-analytics/resource.yaml +1 -1
- package/library/skills/headless-scripting/SKILL.md +1 -1
- package/library/skills/headless-scripting/resource.yaml +1 -1
- package/library/skills/in-game-purchases/SKILL.md +1 -1
- package/library/skills/in-game-purchases/resource.yaml +1 -1
- package/library/skills/instantiate-asset-pack/SKILL.md +2 -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 +4 -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 +1 -1
- package/library/skills/multiplayer/resource.yaml +1 -1
- package/library/skills/multiplayer-movement/SKILL.md +1 -1
- package/library/skills/multiplayer-movement/resource.yaml +1 -1
- package/library/skills/multiplayer-project/SKILL.md +1 -1
- package/library/skills/multiplayer-project/resource.yaml +1 -1
- package/library/skills/multiplayer-publish/SKILL.md +8 -7
- package/library/skills/multiplayer-publish/resource.yaml +3 -3
- package/library/skills/multiplayer-state/SKILL.md +1 -1
- package/library/skills/multiplayer-state/resource.yaml +1 -1
- package/library/skills/multiplayer-testing/SKILL.md +1 -1
- package/library/skills/multiplayer-testing/resource.yaml +1 -1
- package/library/skills/music-track/SKILL.md +22 -13
- package/library/skills/music-track/resource.yaml +1 -1
- package/library/skills/navigate-summer/SKILL.md +11 -9
- package/library/skills/navigate-summer/resource.yaml +1 -1
- package/library/skills/new-project/SKILL.md +1 -1
- package/library/skills/new-project/resource.yaml +1 -1
- package/library/skills/organic-model/SKILL.md +24 -18
- package/library/skills/organic-model/resource.yaml +1 -1
- package/library/skills/pixel-art/SKILL.md +27 -23
- package/library/skills/pixel-art/resource.yaml +1 -1
- package/library/skills/play/SKILL.md +1 -1
- package/library/skills/play/resource.yaml +1 -1
- package/library/skills/playtesting-a-feature/SKILL.md +1 -1
- package/library/skills/playtesting-a-feature/resource.yaml +1 -1
- package/library/skills/procedural-animation/SKILL.md +20 -16
- package/library/skills/procedural-animation/resource.yaml +1 -1
- package/library/skills/prop-model/SKILL.md +25 -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 +16 -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 +1 -1
- package/library/skills/release-readiness/resource.yaml +1 -1
- package/library/skills/remote-deploy/SKILL.md +1 -1
- package/library/skills/remote-deploy/resource.yaml +1 -1
- package/library/skills/retarget/SKILL.md +23 -20
- package/library/skills/retarget/resource.yaml +1 -1
- package/library/skills/running-in-the-cloud/SKILL.md +1 -1
- package/library/skills/running-in-the-cloud/resource.yaml +1 -1
- package/library/skills/save-load/SKILL.md +1 -1
- package/library/skills/save-load/resource.yaml +1 -1
- package/library/skills/scene-composition/SKILL.md +1 -1
- package/library/skills/scene-composition/resource.yaml +1 -1
- package/library/skills/scene-hierarchy-design/SKILL.md +2 -2
- package/library/skills/scene-hierarchy-design/resource.yaml +1 -1
- package/library/skills/scene-scripting/SKILL.md +66 -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 +2 -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 +2 -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 +27 -21
- package/library/skills/skybox-panorama/resource.yaml +1 -1
- package/library/skills/sound-effect/SKILL.md +31 -20
- package/library/skills/sound-effect/resource.yaml +1 -1
- package/library/skills/spatial-placement/SKILL.md +14 -9
- package/library/skills/spatial-placement/resource.yaml +1 -1
- package/library/skills/sprite-sheet/SKILL.md +32 -27
- package/library/skills/sprite-sheet/resource.yaml +1 -1
- package/library/skills/store-art/SKILL.md +3 -3
- package/library/skills/store-art/resource.yaml +2 -2
- package/library/skills/store-listing/SKILL.md +3 -3
- package/library/skills/store-listing/resource.yaml +2 -2
- package/library/skills/summer-analytics/SKILL.md +7 -5
- package/library/skills/summer-analytics/resource.yaml +2 -2
- package/library/skills/summer-apps/SKILL.md +168 -0
- package/library/skills/summer-apps/manifest.md +57 -0
- package/library/skills/summer-apps/minimal-app.md +183 -0
- package/library/skills/summer-apps/resource.yaml +36 -0
- package/library/skills/summer-apps/sdk-reference.md +135 -0
- package/library/skills/summer-apps-design/SKILL.md +197 -0
- package/library/skills/summer-apps-design/resource.yaml +23 -0
- package/library/skills/summer-assets/SKILL.md +56 -0
- package/library/skills/summer-assets/resource.yaml +34 -0
- package/library/skills/summer-store/SKILL.md +1 -1
- package/library/skills/text-to-motion/SKILL.md +30 -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 +19 -15
- package/library/skills/tileable-texture/resource.yaml +1 -1
- package/library/skills/trailer-shot/SKILL.md +28 -24
- package/library/skills/trailer-shot/resource.yaml +1 -1
- package/library/skills/tune-performance/SKILL.md +6 -6
- package/library/skills/tune-performance/resource.yaml +1 -1
- package/library/skills/ui-basics/SKILL.md +41 -36
- package/library/skills/ui-basics/resource.yaml +1 -1
- package/library/skills/ui-graphics/SKILL.md +47 -38
- package/library/skills/ui-graphics/resource.yaml +1 -1
- package/library/skills/use-widget-asset/SKILL.md +1 -1
- package/library/skills/use-widget-asset/resource.yaml +1 -1
- package/library/skills/using-summer/SKILL.md +7 -5
- package/library/skills/using-summer/resource.yaml +1 -1
- package/library/skills/vehicle-model/SKILL.md +65 -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 +2 -2
- package/library/skills/verifying-scenes/resource.yaml +1 -1
- package/library/skills/vfx-dissolve/SKILL.md +2 -2
- package/library/skills/vfx-dissolve/resource.yaml +1 -1
- package/library/skills/vfx-fire/SKILL.md +15 -41
- package/library/skills/vfx-fire/resource.yaml +1 -1
- package/library/skills/vfx-hit-spark/SKILL.md +1 -1
- package/library/skills/vfx-hit-spark/resource.yaml +1 -1
- package/library/skills/vfx-lightning/SKILL.md +7 -16
- package/library/skills/vfx-lightning/resource.yaml +1 -1
- package/library/skills/vfx-magic-glow/SKILL.md +23 -32
- package/library/skills/vfx-magic-glow/resource.yaml +1 -1
- package/library/skills/vfx-muzzle-flash/SKILL.md +20 -35
- package/library/skills/vfx-muzzle-flash/resource.yaml +1 -1
- package/library/skills/vfx-smoke/SKILL.md +13 -31
- package/library/skills/vfx-smoke/resource.yaml +1 -1
- package/library/skills/vfx-water-ripple/SKILL.md +12 -31
- package/library/skills/vfx-water-ripple/resource.yaml +1 -1
- package/library/skills/voice-line/SKILL.md +71 -40
- package/library/skills/voice-line/resource.yaml +1 -1
- package/library/skills/web-and-touch-input/SKILL.md +1 -1
- package/library/skills/web-and-touch-input/resource.yaml +1 -1
- package/library/skills/web-compatibility-look/SKILL.md +1 -1
- package/library/skills/web-compatibility-look/resource.yaml +1 -1
- package/library/skills/world-building-3d/SKILL.md +1 -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 +59 -0
- package/library/tools/app-create/resource.yaml +67 -0
- package/library/tools/app-data/resource.yaml +74 -0
- package/library/tools/app-dock/resource.yaml +59 -0
- package/library/tools/app-events/resource.yaml +68 -0
- package/library/tools/app-get/resource.yaml +46 -0
- package/library/tools/app-guide/resource.yaml +55 -0
- package/library/tools/app-list/resource.yaml +48 -0
- package/library/tools/app-page/resource.yaml +74 -0
- package/library/tools/app-publish/resource.yaml +90 -0
- package/library/tools/app-report-gap/resource.yaml +58 -0
- package/library/tools/app-screenshot/resource.yaml +103 -0
- package/library/tools/app-tools/resource.yaml +46 -0
- package/library/tools/app-update/resource.yaml +68 -0
- 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/enable-plugin/resource.yaml +53 -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 +6 -4
- package/registry/generated/aliases.json +15 -0
- package/registry/generated/counts.json +3 -3
- package/registry/generated/gemini-extension.json +6 -12
- package/registry/generated/index.json +1155 -408
- package/registry/generated/marketplace.claude.json +2 -13
- package/registry/generated/plugin.claude.json +25 -22
- package/registry/generated/plugin.codex.json +8 -14
- package/registry/generated/plugin.cursor.json +7 -13
- package/registry/generated/plugin.factory.json +7 -13
- package/registry/generated/server.json +34 -0
- package/registry/generated/skills-index.md +126 -116
- package/registry/generated/skills-registry.json +178 -113
- 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 +1206 -0
- package/registry/schemas/allowed-hosts.json +4 -2
- package/registry/schemas/operation.schema.json +318 -0
- package/registry/schemas/skill.schema.json +4 -0
- package/CLAUDE.md +0 -7
|
@@ -20,6 +20,7 @@ import { tmpdir } from "node:os";
|
|
|
20
20
|
import { join } from "node:path";
|
|
21
21
|
import { mkdir, mkdtemp, writeFile } from "node:fs/promises";
|
|
22
22
|
import { EngineApiClient } from "../api-client.js";
|
|
23
|
+
import { CLI_RECOVERY, codedFailure, codeForStatus, describeNetworkError, engineNotRunningFromConnectError, networkDetails, NOT_SIGNED_IN, } from "../error-codes.js";
|
|
23
24
|
import { missingEngineEventsResult, missingEngineOpResult, } from "../capability-skew.js";
|
|
24
25
|
import { buildAgentPlaybook } from "./agent-playbook.js";
|
|
25
26
|
import { recentEvents, recentEventsArgsSchema, waitForEvent, waitForEventArgsSchema, } from "./events.js";
|
|
@@ -35,7 +36,8 @@ import { ImportHdriError, importHdriArgsSchema, importPolyHavenHdri } from "./hd
|
|
|
35
36
|
import { FABRICATE_FALLBACK, buildFabricateMeshOp, fabricateArgsSchema } from "./fabricate-mesh.js";
|
|
36
37
|
import { buildUiActionsOp, buildUiActivateOp, buildUiScreenshotOp, buildUiTreeOp, executeUiOp, uiActionsArgsSchema, uiActivateArgsSchema, uiScreenshotArgsSchema, uiScreenshotCaption, uiScreenshotImage, uiTreeArgsSchema, withUiFailureDetails, } from "./ui-control.js";
|
|
37
38
|
import { PLAY_INSTANCE_FALLBACK, RUNTIME_FALLBACKS, buildGameControlOp, buildGameInputOp, buildGameProbeOp, buildRuntimeAnimateOp, buildRuntimeCallOp, buildRuntimeSetOp, buildRuntimeSpawnOp, buildStopGameOp, findProbePayload, gameControlArgsSchema, gameInputArgsSchema, gameProbeArgsSchema, playGame, probeFrameStamp, runtimeAnimateArgsSchema, runtimeCallArgsSchema, runtimeSetArgsSchema, runtimeSpawnArgsSchema, stripProbeImage, withRuntimeFailureHints, } from "./runtime-control.js";
|
|
38
|
-
import { RUN_EDITOR_SCRIPT_FALLBACK, RUN_SCRIPT_FALLBACK, buildRunEditorScriptOp,
|
|
39
|
+
import { RUN_EDITOR_SCRIPT_FALLBACK, RUN_SCRIPT_FALLBACK, buildRunEditorScriptOp, } from "./scene-script.js";
|
|
40
|
+
import { runSceneScriptOn } from "./scene-script-target.js";
|
|
39
41
|
import { CAMERA_BOOKMARK_ACTIONS, CAMERA_BOOKMARK_FALLBACK, SCREENSHOT_FRAMINGS, buildCameraBookmarkOp, buildScenePreviewInput, } from "./camera-view.js";
|
|
40
42
|
import { PLAY_DETERMINISM_NOT_SUPPORTED, pickPlayDeterminism, readPlayDeterminism } from "./play-determinism.js";
|
|
41
43
|
import { debugViews, frameNodes, frameShot, rememberBookmarkRender, shotSheet, slotPolicy, zoom, } from "./seeing/seeing.js";
|
|
@@ -75,13 +77,12 @@ import { PLACEMENT_FIELDS, SCENE_MUTATION_OPS, SCENE_QUERY_OPS, instantiateScene
|
|
|
75
77
|
import { attachToSurface, attachToSurfaceArgsSchema, connectPorts, connectPortsArgsSchema, inspectAsset, inspectAssetArgsSchema, measure, measureArgsSchema, placeAdjacent, placeAdjacentArgsSchema, raycast, raycastArgsSchema, repeatAlong, repeatAlongArgsSchema, } from "./placement.js";
|
|
76
78
|
import { readLibraryEntry, readLibraryInputSchema } from "../library-read.js";
|
|
77
79
|
import { runSearchLibrary, searchLibraryInputSchema } from "../library-search.js";
|
|
78
|
-
import {
|
|
80
|
+
import { runWithToolContext, summerRequestHeaders } from "../agent-host.js";
|
|
81
|
+
import { APP_DOCK_FALLBACK, appCall, appCallArgsSchema, appCreate, appCreateArgsSchema, appData, appDataArgsSchema, appDockArgsSchema, appDockOp, appEvents, appEventsArgsSchema, appGet, appGetArgsSchema, appGuide, appGuideArgsSchema, appList, appListArgsSchema, appPage, appPageArgsSchema, appScreenshot, appScreenshotArgsSchema, appUpdate, appUpdateArgsSchema, appPublish, appPublishArgsSchema, appReportGap, appReportGapArgsSchema, appsGateway, appTools, appToolsArgsSchema, } from "./apps.js";
|
|
82
|
+
import { enablePluginArgsSchema, enablePluginOp, interpretEnablePluginResult } from "./enable-plugin.js";
|
|
79
83
|
/** Dispatch-level failure with a user-facing message (no stack needed). */
|
|
80
84
|
export class ToolDispatchError extends Error {
|
|
81
85
|
}
|
|
82
|
-
/** The local engine is not reachable — a clean state, not a crash. */
|
|
83
|
-
export class EngineUnavailableError extends ToolDispatchError {
|
|
84
|
-
}
|
|
85
86
|
/** A tool failed with a structured receipt that `summer tool` prints whole
|
|
86
87
|
* (JSON on stdout, exit 1) instead of flattening to `message`: every engine
|
|
87
88
|
* envelope extractOpError reads as a failure (the same gate the MCP face
|
|
@@ -96,6 +97,23 @@ export class ToolResultError extends ToolDispatchError {
|
|
|
96
97
|
this.result = result;
|
|
97
98
|
}
|
|
98
99
|
}
|
|
100
|
+
/** A shared failure (core/error-codes.ts) — not signed in, no credits,
|
|
101
|
+
* network — printed as `{ok:false, code, error, recovery}` with the shell
|
|
102
|
+
* wording of the next step. */
|
|
103
|
+
export class CodedToolError extends ToolResultError {
|
|
104
|
+
constructor(code, message, extra = {}, recovery = CLI_RECOVERY[code]) {
|
|
105
|
+
super(codedFailure(code, message, extra, recovery), message);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/** The local engine is not reachable — a clean state, not a crash. Prints
|
|
109
|
+
* `{ok:false, code:"engine_not_running", error, recovery, hint}`. */
|
|
110
|
+
export class EngineUnavailableError extends CodedToolError {
|
|
111
|
+
constructor(message) {
|
|
112
|
+
super("engine_not_running", message, {
|
|
113
|
+
hint: "Engine-free tools (generate-*, asset search/list/get, library search/read, plan) work without it.",
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
99
117
|
export function createDefaultDispatchContext() {
|
|
100
118
|
let cached = null;
|
|
101
119
|
return {
|
|
@@ -108,10 +126,12 @@ export function createDefaultDispatchContext() {
|
|
|
108
126
|
}
|
|
109
127
|
catch (error) {
|
|
110
128
|
const reason = error instanceof Error ? error.message : String(error);
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
129
|
+
// Several editors open (or another selection problem) already says
|
|
130
|
+
// how to pick one; only "nothing reachable" is engine_not_running.
|
|
131
|
+
const notRunning = engineNotRunningFromConnectError(reason);
|
|
132
|
+
if (!notRunning)
|
|
133
|
+
throw new ToolDispatchError(reason);
|
|
134
|
+
throw new EngineUnavailableError(notRunning.message);
|
|
115
135
|
}
|
|
116
136
|
},
|
|
117
137
|
};
|
|
@@ -263,17 +283,24 @@ async function dispatchUiOp(ctx, built) {
|
|
|
263
283
|
// ---------------------------------------------------------------------------
|
|
264
284
|
async function requireToken() {
|
|
265
285
|
const token = await getAuthToken();
|
|
266
|
-
if (!token)
|
|
267
|
-
throw new
|
|
268
|
-
}
|
|
286
|
+
if (!token)
|
|
287
|
+
throw new CodedToolError("not_signed_in", NOT_SIGNED_IN);
|
|
269
288
|
return token;
|
|
270
289
|
}
|
|
290
|
+
/** A non-OK Summer web reply: 401 and 402 carry the shared codes. */
|
|
291
|
+
function gatewayFailure(status, data) {
|
|
292
|
+
const message = String(data.message || data.error || `Request failed (${status})`);
|
|
293
|
+
const code = codeForStatus(status);
|
|
294
|
+
if (code === "not_signed_in")
|
|
295
|
+
return new CodedToolError(code, message, { status }, "Run: summer login --force");
|
|
296
|
+
if (code)
|
|
297
|
+
return new CodedToolError(code, message, { status });
|
|
298
|
+
return new ToolDispatchError(message);
|
|
299
|
+
}
|
|
271
300
|
function gatewayHeaders(token, endpoint) {
|
|
272
301
|
return {
|
|
302
|
+
...summerRequestHeaders({ surface: "cli" }),
|
|
273
303
|
Authorization: `Bearer ${token}`,
|
|
274
|
-
"X-Summer-Client": "summer-cli",
|
|
275
|
-
"X-Summer-Client-Version": CLI_VERSION,
|
|
276
|
-
"X-Summer-Client-Surface": "cli",
|
|
277
304
|
"X-Summer-MCP-Endpoint": endpoint,
|
|
278
305
|
};
|
|
279
306
|
}
|
|
@@ -303,12 +330,11 @@ async function gatewayGet(endpoint, params, timeoutMs = 30_000) {
|
|
|
303
330
|
});
|
|
304
331
|
}
|
|
305
332
|
catch (err) {
|
|
306
|
-
throw new
|
|
333
|
+
throw new CodedToolError("unavailable", `Request failed: ${describeNetworkError(err)}`, networkDetails(err));
|
|
307
334
|
}
|
|
308
335
|
const data = await readJsonBody(res);
|
|
309
|
-
if (!res.ok)
|
|
310
|
-
throw
|
|
311
|
-
}
|
|
336
|
+
if (!res.ok)
|
|
337
|
+
throw gatewayFailure(res.status, data);
|
|
312
338
|
return data;
|
|
313
339
|
}
|
|
314
340
|
async function gatewayPost(endpoint, body, timeoutMs = 120_000) {
|
|
@@ -327,19 +353,11 @@ async function gatewayPost(endpoint, body, timeoutMs = 120_000) {
|
|
|
327
353
|
});
|
|
328
354
|
}
|
|
329
355
|
catch (err) {
|
|
330
|
-
throw new
|
|
356
|
+
throw new CodedToolError("unavailable", `Generation request failed: ${describeNetworkError(err)}`, networkDetails(err));
|
|
331
357
|
}
|
|
332
358
|
const data = await readJsonBody(res);
|
|
333
|
-
if (!res.ok)
|
|
334
|
-
|
|
335
|
-
if (res.status === 402) {
|
|
336
|
-
message = `${message} — insufficient credits; top up or upgrade on the Summer dashboard.`;
|
|
337
|
-
}
|
|
338
|
-
if (res.status === 401) {
|
|
339
|
-
message = `${message} — auth token expired; run 'summer login' again.`;
|
|
340
|
-
}
|
|
341
|
-
throw new ToolDispatchError(message);
|
|
342
|
-
}
|
|
359
|
+
if (!res.ok)
|
|
360
|
+
throw gatewayFailure(res.status, data);
|
|
343
361
|
return data;
|
|
344
362
|
}
|
|
345
363
|
async function pollGenerationJob(jobId, maxWaitMs = 600_000, intervalMs = 5_000) {
|
|
@@ -348,14 +366,19 @@ async function pollGenerationJob(jobId, maxWaitMs = 600_000, intervalMs = 5_000)
|
|
|
348
366
|
const deadline = Date.now() + maxWaitMs;
|
|
349
367
|
let interval = intervalMs;
|
|
350
368
|
while (Date.now() < deadline) {
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
throw new ToolDispatchError(String(data.message || "Job poll failed"));
|
|
369
|
+
let res;
|
|
370
|
+
try {
|
|
371
|
+
res = await fetch(`${gatewayUrl}/api/mcp/jobs/${encodeURIComponent(jobId)}`, {
|
|
372
|
+
headers: gatewayHeaders(token, "/api/mcp/jobs"),
|
|
373
|
+
signal: AbortSignal.timeout(15_000),
|
|
374
|
+
});
|
|
358
375
|
}
|
|
376
|
+
catch (err) {
|
|
377
|
+
throw new CodedToolError("unavailable", `Job poll failed: ${describeNetworkError(err)}`, { jobId, ...networkDetails(err) });
|
|
378
|
+
}
|
|
379
|
+
const data = await readJsonBody(res);
|
|
380
|
+
if (!res.ok)
|
|
381
|
+
throw gatewayFailure(res.status, { message: "Job poll failed", ...data });
|
|
359
382
|
if (data.status === "completed")
|
|
360
383
|
return data;
|
|
361
384
|
if (data.status === "failed") {
|
|
@@ -364,7 +387,15 @@ async function pollGenerationJob(jobId, maxWaitMs = 600_000, intervalMs = 5_000)
|
|
|
364
387
|
await new Promise((resolve) => setTimeout(resolve, interval));
|
|
365
388
|
interval = Math.min(interval * 1.2, 15_000);
|
|
366
389
|
}
|
|
367
|
-
throw new ToolDispatchError(`Timed out after ${maxWaitMs / 1000}s. Re-check later with:
|
|
390
|
+
throw new ToolDispatchError(`Timed out after ${maxWaitMs / 1000}s. Re-check later with: ${cliCheckJobCommand(jobId)}`);
|
|
391
|
+
}
|
|
392
|
+
function cliCheckJobCommand(jobId) {
|
|
393
|
+
return `summer tool check-job --args '{"jobId":"${jobId}"}'`;
|
|
394
|
+
}
|
|
395
|
+
/** generate-3d / generate-motion return the job at once, like the MCP face;
|
|
396
|
+
* `--args '{"wait":true,…}'` blocks instead. */
|
|
397
|
+
function cliCheckJobNext(jobId) {
|
|
398
|
+
return `The job runs on Summer's servers. Check it with: ${cliCheckJobCommand(jobId)}`;
|
|
368
399
|
}
|
|
369
400
|
async function searchAssetsGateway(params) {
|
|
370
401
|
const search = new URLSearchParams();
|
|
@@ -401,9 +432,21 @@ async function gatewayReply(call) {
|
|
|
401
432
|
catch (error) {
|
|
402
433
|
if (!(error instanceof ToolDispatchError))
|
|
403
434
|
throw error;
|
|
435
|
+
if (error instanceof CodedToolError) {
|
|
436
|
+
const { code, recovery } = error.result;
|
|
437
|
+
return { error: error.message, status: 0, code, recovery };
|
|
438
|
+
}
|
|
404
439
|
return { error: error.message, status: 0 };
|
|
405
440
|
}
|
|
406
441
|
}
|
|
442
|
+
/** summer tool app-screenshot: the PNG goes to `out` (default ./summer-app-screenshot.png), not into the printed JSON. */
|
|
443
|
+
async function cliScreenshot(args, deps) {
|
|
444
|
+
const shot = await appScreenshot({ ...args, out: args.out ?? "summer-app-screenshot.png" }, deps);
|
|
445
|
+
if (shot.ok !== true || !("image" in shot))
|
|
446
|
+
return shot;
|
|
447
|
+
const { image: _image, ...report } = shot;
|
|
448
|
+
return report;
|
|
449
|
+
}
|
|
407
450
|
function sfxChoicesDeps() {
|
|
408
451
|
return {
|
|
409
452
|
post: (endpoint, body, timeoutMs) => gatewayReply(() => gatewayPost(endpoint, body, timeoutMs)),
|
|
@@ -906,6 +949,45 @@ export const TOOL_DISPATCH = [
|
|
|
906
949
|
throw new ToolResultError(result, String(result.error));
|
|
907
950
|
return result;
|
|
908
951
|
}),
|
|
952
|
+
// Summer Apps (core/capabilities/apps.ts): the same functions as the MCP face.
|
|
953
|
+
...[
|
|
954
|
+
["summer_app_guide", "Read the Summer Apps build guide (SDK, manifest, kit, layout, design, examples)", appGuideArgsSchema, appGuide],
|
|
955
|
+
["summer_app_list", "List the Summer Apps in the person's workspaces", appListArgsSchema, appList],
|
|
956
|
+
["summer_app_create", "Create a scratch Summer App and open it in Summer Studio", appCreateArgsSchema, appCreate],
|
|
957
|
+
["summer_app_publish", "Publish a new version of a Summer App from a folder or files", appPublishArgsSchema, appPublish],
|
|
958
|
+
["summer_app_get", "Read a Summer App's manifest, files and data summary", appGetArgsSchema, appGet],
|
|
959
|
+
["summer_app_update", "Rename a Summer App or keep, archive or restore it", appUpdateArgsSchema, appUpdate],
|
|
960
|
+
["summer_app_events", "Wait for events a Summer App sends to agents", appEventsArgsSchema, appEvents],
|
|
961
|
+
["summer_app_page", "Read or use the open app's declared fields and buttons", appPageArgsSchema, appPage],
|
|
962
|
+
["summer_app_data", "Read or write a Summer App's shared data", appDataArgsSchema, appData],
|
|
963
|
+
["summer_app_screenshot", "See a Summer App rendered (read-only) with its console and errors; out saves the PNG", appScreenshotArgsSchema, cliScreenshot],
|
|
964
|
+
["summer_app_tools", "List a Summer App's agent tools", appToolsArgsSchema, appTools],
|
|
965
|
+
["summer_app_call", "Run a Summer App's agent tool in the person's open app", appCallArgsSchema, appCall],
|
|
966
|
+
["summer_app_report_gap", "Report an SDK capability a Summer App needed", appReportGapArgsSchema, appReportGap],
|
|
967
|
+
].map(([name, summary, schema, run]) => entry(name, summary, false, async (args) => {
|
|
968
|
+
const result = await run(parseToolArgs(schema, args, name.replace(/^summer_/, "").replace(/_/g, "-")), { request: appsGateway("cli", name) });
|
|
969
|
+
if (result.ok !== true)
|
|
970
|
+
throw new ToolResultError(result, String(result.error));
|
|
971
|
+
return result;
|
|
972
|
+
})),
|
|
973
|
+
entry("summer_enable_plugin", "Enable an editor plugin and report whether it really loaded", true, async (args, ctx) => {
|
|
974
|
+
const parsed = parseToolArgs(enablePluginArgsSchema, args, "enable-plugin");
|
|
975
|
+
const result = interpretEnablePluginResult(await (await ctx.engine()).executeOps([enablePluginOp(parsed)]));
|
|
976
|
+
if (result.ok !== true)
|
|
977
|
+
throw new ToolResultError(result, String(result.error));
|
|
978
|
+
return result;
|
|
979
|
+
}),
|
|
980
|
+
entry("summer_app_dock", "Dock a Summer App in the editor, close its dock, or list docks", true, async (args, ctx) => {
|
|
981
|
+
const parsed = parseToolArgs(appDockArgsSchema, args, "app-dock");
|
|
982
|
+
if (parsed.action !== "list" && !parsed.appId)
|
|
983
|
+
throw new ToolDispatchError(`${parsed.action} needs appId`);
|
|
984
|
+
const op = appDockOp(parsed);
|
|
985
|
+
const client = await ctx.engine();
|
|
986
|
+
const missing = missingEngineOpResult(client, op.op, APP_DOCK_FALLBACK);
|
|
987
|
+
if (missing)
|
|
988
|
+
throw new ToolResultError({ ...missing }, missing.error);
|
|
989
|
+
return requireEngineSuccess(await client.executeOps([op]));
|
|
990
|
+
}),
|
|
909
991
|
entry("summer_generate_3d", "Generate a 3D model (optional auto-rig + animations)", false, async (args) => {
|
|
910
992
|
const options = {
|
|
911
993
|
...(args.options ?? {}),
|
|
@@ -929,8 +1011,8 @@ export const TOOL_DISPATCH = [
|
|
|
929
1011
|
options,
|
|
930
1012
|
});
|
|
931
1013
|
const jobId = typeof result.jobId === "string" ? result.jobId : undefined;
|
|
932
|
-
if (args.wait
|
|
933
|
-
return result;
|
|
1014
|
+
if (args.wait !== true || !jobId)
|
|
1015
|
+
return jobId ? { ...result, next: cliCheckJobNext(jobId) } : result;
|
|
934
1016
|
const final = await pollGenerationJob(jobId);
|
|
935
1017
|
return { ...final, jobId };
|
|
936
1018
|
}),
|
|
@@ -951,7 +1033,7 @@ export const TOOL_DISPATCH = [
|
|
|
951
1033
|
const result = await gatewayPost("/api/mcp/generate/motion", built.body);
|
|
952
1034
|
const jobId = typeof result.jobId === "string" ? result.jobId : undefined;
|
|
953
1035
|
if (!parsed.wait || !jobId)
|
|
954
|
-
return result;
|
|
1036
|
+
return jobId ? { ...result, next: cliCheckJobNext(jobId) } : result;
|
|
955
1037
|
const final = await pollGenerationJob(jobId, 600_000);
|
|
956
1038
|
return { ...final, jobId };
|
|
957
1039
|
}),
|
|
@@ -1204,19 +1286,19 @@ export const TOOL_DISPATCH = [
|
|
|
1204
1286
|
return runBatch(await ctx.engine(), { scenePath, ops, receipt });
|
|
1205
1287
|
}),
|
|
1206
1288
|
// --- scene scripting ---
|
|
1207
|
-
entry("summer_run_script", "Run a GDScript func run(ctx) inside the live editor against the open scene", true, async (args, ctx) => {
|
|
1289
|
+
entry("summer_run_script", "Run a GDScript func run(ctx) inside the live editor against scenePath (or the open scene)", true, async (args, ctx) => {
|
|
1208
1290
|
const client = await ctx.engine();
|
|
1209
1291
|
const missing = missingEngineOpResult(client, "RunSceneScript", RUN_SCRIPT_FALLBACK);
|
|
1210
1292
|
if (missing)
|
|
1211
1293
|
refuseMissingOp(missing);
|
|
1212
1294
|
const undo = optStr(args, "undo");
|
|
1213
|
-
|
|
1295
|
+
return requireSupportedOp(await runSceneScriptOn(client, {
|
|
1296
|
+
scenePath: optStr(args, "scenePath"),
|
|
1214
1297
|
source: str(args, "source"),
|
|
1215
1298
|
max_seconds: typeof args.max_seconds === "number" ? args.max_seconds : undefined,
|
|
1216
1299
|
checkpoint: typeof args.checkpoint === "boolean" ? args.checkpoint : undefined,
|
|
1217
1300
|
undo: undo === "action" || undo === "none" ? undo : undefined,
|
|
1218
|
-
});
|
|
1219
|
-
return requireSupportedOp(await client.executeIdentityBoundOps([op], undefined, timeoutMs), "RunSceneScript", RUN_SCRIPT_FALLBACK);
|
|
1301
|
+
}), "RunSceneScript", RUN_SCRIPT_FALLBACK);
|
|
1220
1302
|
}),
|
|
1221
1303
|
entry("summer_run_editor_script", "Run an EditorScript in a fresh headless child editor against the on-disk project", true, async (args, ctx) => {
|
|
1222
1304
|
const client = await ctx.engine();
|
|
@@ -1681,5 +1763,7 @@ export async function dispatchTool(nameOrSlug, args, ctx = createDefaultDispatch
|
|
|
1681
1763
|
// The one gate every result passes, mirroring withEngine on the MCP face:
|
|
1682
1764
|
// whatever the MCP face would mark isError is a ToolResultError here, so the
|
|
1683
1765
|
// CLI exit code says what the receipt says — for every tool, not per handler.
|
|
1684
|
-
|
|
1766
|
+
// Summer requests made for this call name the tool (core/agent-host.ts); the
|
|
1767
|
+
// MCP face sets the same context in its call wrapper.
|
|
1768
|
+
return requireEngineSuccess(await runWithToolContext(dispatchEntry.name, "cli", () => dispatchEntry.handler(args, ctx)));
|
|
1685
1769
|
}
|
|
@@ -49,6 +49,10 @@ export const CLI_KNOWN_OP_NEEDS = [
|
|
|
49
49
|
// engine's one-table op; the other three are the legacy
|
|
50
50
|
// fallbacks on engines that predate it.
|
|
51
51
|
"Navigate", "OpenResource", "FocusDock", "RevealInFileSystem",
|
|
52
|
+
// Summer Apps editor docks (summer_app_dock: core/capabilities/apps.ts)
|
|
53
|
+
"OpenAppDock", "CloseAppDock", "ListAppDocks",
|
|
54
|
+
// summer_enable_plugin (core/capabilities/enable-plugin.ts)
|
|
55
|
+
"EnableEditorPlugin",
|
|
52
56
|
// Project + input
|
|
53
57
|
"ProjectSetting", "InputMapAddAction", "InputMapBind",
|
|
54
58
|
// Files (summer_write_file / summer_replace_text / summer_create_scene)
|
|
@@ -47,6 +47,8 @@ export interface EmbedProviderOptions {
|
|
|
47
47
|
token?: string | null;
|
|
48
48
|
timeoutMs: number;
|
|
49
49
|
fetchImpl?: typeof fetch;
|
|
50
|
+
/** Extra request headers (the runtime's client and agent-host headers). */
|
|
51
|
+
headers?: Record<string, string>;
|
|
50
52
|
}
|
|
51
53
|
export declare function encodeVector(vector: readonly number[]): string;
|
|
52
54
|
export declare function decodeVector(encoded: string): Float32Array;
|
package/dist/core/embeddings.js
CHANGED
|
@@ -140,7 +140,7 @@ export function createEmbedProvider(options) {
|
|
|
140
140
|
const controller = new AbortController();
|
|
141
141
|
const timer = setTimeout(() => controller.abort(), options.timeoutMs);
|
|
142
142
|
try {
|
|
143
|
-
const headers = { "Content-Type": "application/json" };
|
|
143
|
+
const headers = { ...options.headers, "Content-Type": "application/json" };
|
|
144
144
|
if (options.token)
|
|
145
145
|
headers.Authorization = `Bearer ${options.token}`;
|
|
146
146
|
const response = await fetchImpl(options.url, {
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stable codes for the failures any Summer tool can hit before it does its
|
|
3
|
+
* job: the engine is not running, the person is not signed in, the account
|
|
4
|
+
* has no credits left, or the network failed. Agents branch on `code` and
|
|
5
|
+
* follow `recovery` (one next step); the older fields each tool returned
|
|
6
|
+
* (`error`, `message`, `hint`) stay next to them so 3.x callers keep working.
|
|
7
|
+
*
|
|
8
|
+
* The store sign-in keeps its own code, `store_login_required`
|
|
9
|
+
* (core/oauth.ts): it is a second grant with its own recovery
|
|
10
|
+
* (`summer login --store`).
|
|
11
|
+
*
|
|
12
|
+
* The codes are the ones the 4.0 tools use (one closed list, shared with the
|
|
13
|
+
* hosted Summer MCP), so 4.0 changes where they sit, not their names.
|
|
14
|
+
*/
|
|
15
|
+
export type SummerErrorCode = "engine_not_running" | "not_signed_in" | "no_credits" | "unavailable";
|
|
16
|
+
export declare const SIGN_IN_COMMAND = "npx -y summer-engine@latest login";
|
|
17
|
+
export declare const CREDITS_URL = "https://summerengine.com/studio/credits";
|
|
18
|
+
/** The one sentence every tool uses when there is no Summer account token. */
|
|
19
|
+
export declare const NOT_SIGNED_IN = "Not signed in to Summer.";
|
|
20
|
+
/** A token the server refused (expired, revoked): plain `login` would say
|
|
21
|
+
* "Already logged in", so the step forces a new sign-in. */
|
|
22
|
+
export declare const SIGN_IN_AGAIN_RECOVERY = "Ask the person to sign in again: npx -y summer-engine@latest login --force";
|
|
23
|
+
/** The one next step per code, as the MCP face words it (the agent may not
|
|
24
|
+
* have `summer` on PATH, so commands go through npx). */
|
|
25
|
+
export declare const RECOVERY: Record<SummerErrorCode, string>;
|
|
26
|
+
/** The same steps for `summer tool` in a shell, where `summer` is the CLI. */
|
|
27
|
+
export declare const CLI_RECOVERY: Record<SummerErrorCode, string>;
|
|
28
|
+
export interface CodedFailure {
|
|
29
|
+
ok: false;
|
|
30
|
+
code: SummerErrorCode;
|
|
31
|
+
error: string;
|
|
32
|
+
recovery: string;
|
|
33
|
+
}
|
|
34
|
+
/** `{ok:false, code, error, recovery}` first, then any other fields the
|
|
35
|
+
* tool already returned (`message`, `hint`, `status`, …). The four named
|
|
36
|
+
* fields win over `extra`; `recovery` defaults to the MCP wording. */
|
|
37
|
+
export declare function codedFailure(code: SummerErrorCode, error: string, extra?: Record<string, unknown>, recovery?: string): CodedFailure & Record<string, unknown>;
|
|
38
|
+
/** The code for a failed Summer web request by HTTP status, when it is one
|
|
39
|
+
* of the shared ones. */
|
|
40
|
+
export declare function codeForStatus(status: number): SummerErrorCode | null;
|
|
41
|
+
/** The message for a failed request, with the real cause in it. */
|
|
42
|
+
export declare function describeNetworkError(error: unknown): string;
|
|
43
|
+
/** `details.cause` for an `unavailable` answer. */
|
|
44
|
+
export declare function networkDetails(error: unknown): {
|
|
45
|
+
details: {
|
|
46
|
+
cause: string;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
/** The engine connect failure that means "nothing is running for this
|
|
50
|
+
* project", worded for the person; the raw reason (token files, instance
|
|
51
|
+
* registry paths) stays in the logs, not in the line the agent repeats. */
|
|
52
|
+
export declare class EngineNotRunningError extends Error {
|
|
53
|
+
readonly reason: string;
|
|
54
|
+
readonly code: "engine_not_running";
|
|
55
|
+
constructor(message: string, reason: string);
|
|
56
|
+
}
|
|
57
|
+
/** A connect error from core/engine.ts → EngineNotRunningError when it means
|
|
58
|
+
* no editor is reachable; null for the others (several editors open, …),
|
|
59
|
+
* which already say what to do. */
|
|
60
|
+
export declare function engineNotRunningFromConnectError(reason: string): EngineNotRunningError | null;
|
|
61
|
+
/** Engine-free tools keep working while the engine is down. */
|
|
62
|
+
export declare const ENGINE_FREE_NOTE: string;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stable codes for the failures any Summer tool can hit before it does its
|
|
3
|
+
* job: the engine is not running, the person is not signed in, the account
|
|
4
|
+
* has no credits left, or the network failed. Agents branch on `code` and
|
|
5
|
+
* follow `recovery` (one next step); the older fields each tool returned
|
|
6
|
+
* (`error`, `message`, `hint`) stay next to them so 3.x callers keep working.
|
|
7
|
+
*
|
|
8
|
+
* The store sign-in keeps its own code, `store_login_required`
|
|
9
|
+
* (core/oauth.ts): it is a second grant with its own recovery
|
|
10
|
+
* (`summer login --store`).
|
|
11
|
+
*
|
|
12
|
+
* The codes are the ones the 4.0 tools use (one closed list, shared with the
|
|
13
|
+
* hosted Summer MCP), so 4.0 changes where they sit, not their names.
|
|
14
|
+
*/
|
|
15
|
+
export const SIGN_IN_COMMAND = "npx -y summer-engine@latest login";
|
|
16
|
+
export const CREDITS_URL = "https://summerengine.com/studio/credits";
|
|
17
|
+
/** The one sentence every tool uses when there is no Summer account token. */
|
|
18
|
+
export const NOT_SIGNED_IN = "Not signed in to Summer.";
|
|
19
|
+
/** A token the server refused (expired, revoked): plain `login` would say
|
|
20
|
+
* "Already logged in", so the step forces a new sign-in. */
|
|
21
|
+
export const SIGN_IN_AGAIN_RECOVERY = `Ask the person to sign in again: ${SIGN_IN_COMMAND} --force`;
|
|
22
|
+
/** The one next step per code, as the MCP face words it (the agent may not
|
|
23
|
+
* have `summer` on PATH, so commands go through npx). */
|
|
24
|
+
export const RECOVERY = {
|
|
25
|
+
engine_not_running: "Open the project in Summer Engine, or run: npx -y summer-engine@latest run <project-path> (the folder that holds project.godot).",
|
|
26
|
+
not_signed_in: `Ask the person to sign in: ${SIGN_IN_COMMAND}`,
|
|
27
|
+
no_credits: `Ask the person to add credits: ${CREDITS_URL}`,
|
|
28
|
+
unavailable: "Check the network connection, then retry.",
|
|
29
|
+
};
|
|
30
|
+
/** The same steps for `summer tool` in a shell, where `summer` is the CLI. */
|
|
31
|
+
export const CLI_RECOVERY = {
|
|
32
|
+
...RECOVERY,
|
|
33
|
+
engine_not_running: "Open the project in Summer Engine, or run: summer run <project-path> (the folder that holds project.godot).",
|
|
34
|
+
not_signed_in: "Run: summer login",
|
|
35
|
+
};
|
|
36
|
+
/** `{ok:false, code, error, recovery}` first, then any other fields the
|
|
37
|
+
* tool already returned (`message`, `hint`, `status`, …). The four named
|
|
38
|
+
* fields win over `extra`; `recovery` defaults to the MCP wording. */
|
|
39
|
+
export function codedFailure(code, error, extra = {}, recovery = RECOVERY[code]) {
|
|
40
|
+
const named = { ok: false, code, error, recovery };
|
|
41
|
+
return Object.assign({ ...named }, extra, named);
|
|
42
|
+
}
|
|
43
|
+
/** The code for a failed Summer web request by HTTP status, when it is one
|
|
44
|
+
* of the shared ones. */
|
|
45
|
+
export function codeForStatus(status) {
|
|
46
|
+
if (status === 401)
|
|
47
|
+
return "not_signed_in";
|
|
48
|
+
if (status === 402)
|
|
49
|
+
return "no_credits";
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
/** `fetch failed` says nothing; Node puts the real reason on `cause`
|
|
53
|
+
* (`connect ECONNREFUSED 127.0.0.1:443`, `getaddrinfo ENOTFOUND …`). */
|
|
54
|
+
function networkCause(error) {
|
|
55
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
56
|
+
const cause = error instanceof Error ? error.cause : undefined;
|
|
57
|
+
return cause instanceof Error ? cause.message : typeof cause === "string" ? cause : message;
|
|
58
|
+
}
|
|
59
|
+
/** The message for a failed request, with the real cause in it. */
|
|
60
|
+
export function describeNetworkError(error) {
|
|
61
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
62
|
+
const cause = networkCause(error);
|
|
63
|
+
return message.includes(cause) ? message : `${message} (${cause})`;
|
|
64
|
+
}
|
|
65
|
+
/** `details.cause` for an `unavailable` answer. */
|
|
66
|
+
export function networkDetails(error) {
|
|
67
|
+
return { details: { cause: networkCause(error) } };
|
|
68
|
+
}
|
|
69
|
+
/** The engine connect failure that means "nothing is running for this
|
|
70
|
+
* project", worded for the person; the raw reason (token files, instance
|
|
71
|
+
* registry paths) stays in the logs, not in the line the agent repeats. */
|
|
72
|
+
export class EngineNotRunningError extends Error {
|
|
73
|
+
reason;
|
|
74
|
+
code = "engine_not_running";
|
|
75
|
+
constructor(message, reason) {
|
|
76
|
+
super(message);
|
|
77
|
+
this.reason = reason;
|
|
78
|
+
this.name = "EngineNotRunningError";
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/** A connect error from core/engine.ts → EngineNotRunningError when it means
|
|
82
|
+
* no editor is reachable; null for the others (several editors open, …),
|
|
83
|
+
* which already say what to do. */
|
|
84
|
+
export function engineNotRunningFromConnectError(reason) {
|
|
85
|
+
const port = reason.match(/not responding on port (\d+)/)?.[1];
|
|
86
|
+
if (port)
|
|
87
|
+
return new EngineNotRunningError(`Summer Engine is not responding on port ${port}.`, reason);
|
|
88
|
+
if (/^No running Summer editor matches/.test(reason)) {
|
|
89
|
+
return new EngineNotRunningError(reason.split(/(?<=\.)\s/)[0], reason);
|
|
90
|
+
}
|
|
91
|
+
if (/not running/i.test(reason))
|
|
92
|
+
return new EngineNotRunningError("Summer Engine is not running.", reason);
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
/** Engine-free tools keep working while the engine is down. */
|
|
96
|
+
export const ENGINE_FREE_NOTE = "Only tools that touch the local project need the engine. Library, generation and asset tools " +
|
|
97
|
+
"(summer_search_library, summer_generate_*, summer_search_assets, summer_list_my_assets, summer_get_asset, summer_check_job) work now.";
|
package/dist/core/format.d.ts
CHANGED
package/dist/core/format.js
CHANGED
|
@@ -10,7 +10,8 @@ const ANSI = {
|
|
|
10
10
|
// Summer brand orange (matches banner.ts mid gradient)
|
|
11
11
|
brand: "\x1b[38;2;255;143;23m",
|
|
12
12
|
};
|
|
13
|
-
|
|
13
|
+
/** ANSI colour only for a terminal: NO_COLOR turns it off, FORCE_COLOR on. */
|
|
14
|
+
export function useColor() {
|
|
14
15
|
if (process.env.NO_COLOR)
|
|
15
16
|
return false;
|
|
16
17
|
if (process.env.FORCE_COLOR)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import { OAuthError } from "./oauth.js";
|
|
2
3
|
/** The part of an MCP client the mount and the CLI use (a fake in tests). */
|
|
3
4
|
export interface HostedClient {
|
|
4
5
|
listTools(params?: {
|
|
@@ -54,7 +55,26 @@ export interface HostedConnectDependencies {
|
|
|
54
55
|
connect: (url: string, token: () => Promise<string>) => Promise<HostedClient>;
|
|
55
56
|
}
|
|
56
57
|
export declare function connectHostedMcp(url: string, token: () => Promise<string>): Promise<HostedClient>;
|
|
58
|
+
/**
|
|
59
|
+
* The hosted server's 3.x surface: the same address with `?surface=v3`. Once
|
|
60
|
+
* the hosted server serves 4.0 to every request that does not ask, only 3.x
|
|
61
|
+
* npm releases keep 3.x without asking, so the 3.x tool names here ask.
|
|
62
|
+
*/
|
|
63
|
+
export declare function withV3Surface(url: string): string;
|
|
57
64
|
export declare const defaultHostedConnectDependencies: HostedConnectDependencies;
|
|
65
|
+
/** The hosted server could not be reached, so no call was sent (a sign-in problem is an OAuthError instead). */
|
|
66
|
+
export declare class HostedUnreachableError extends Error {
|
|
67
|
+
readonly recovery: string;
|
|
68
|
+
constructor(message: string, recovery: string);
|
|
69
|
+
}
|
|
70
|
+
/** The HTTP status an MCP transport error carries (the SDK's StreamableHTTPError puts it on `code`). */
|
|
71
|
+
export declare function httpStatusOf(error: unknown): number | undefined;
|
|
72
|
+
/**
|
|
73
|
+
* A failure to connect to the hosted server, before any call was sent: a
|
|
74
|
+
* sign-in problem (an OAuthError, or a 401), an account the server refuses
|
|
75
|
+
* (403, store_access_denied), or the server not answering.
|
|
76
|
+
*/
|
|
77
|
+
export declare function hostedConnectFailure(error: unknown, unreachableRecovery: string): OAuthError | HostedUnreachableError;
|
|
58
78
|
/** True when this machine has a store sign-in on disk (no network). */
|
|
59
79
|
export declare function hasStoreSignIn(): Promise<boolean>;
|
|
60
80
|
export declare function listAllHostedTools(client: HostedClient): Promise<Tool[]>;
|
|
@@ -113,3 +133,5 @@ export type HostedCallOutcome = {
|
|
|
113
133
|
};
|
|
114
134
|
/** Call a hosted tool by its name or slug with the store sign-in (one connection). */
|
|
115
135
|
export declare function callHostedToolForCli(name: string, args: Record<string, unknown>, deps?: HostedConnectDependencies, signedIn?: () => Promise<boolean>): Promise<HostedCallOutcome>;
|
|
136
|
+
/** The tool a tools/call JSON-RPC body names, for the X-Summer-MCP-Tool header. */
|
|
137
|
+
export declare function calledTool(body: unknown): string | undefined;
|
package/dist/core/hosted-mcp.js
CHANGED
|
@@ -2,6 +2,7 @@ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
|
2
2
|
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
3
3
|
import { getStoreAccessToken, OAuthError, readStoredOAuthToken, resolveMcpResourceUrl } from "./oauth.js";
|
|
4
4
|
import { TOOLKIT_VERSION } from "./version.js";
|
|
5
|
+
import { summerRequestHeaders } from "./agent-host.js";
|
|
5
6
|
/**
|
|
6
7
|
* A client for the hosted Summer Engine MCP (mcp.summerengine.com), signed in
|
|
7
8
|
* with the store sign-in ("summer login --store"). The local MCP mounts its
|
|
@@ -15,6 +16,8 @@ export async function connectHostedMcp(url, token) {
|
|
|
15
16
|
// A fresh (refreshed when near expiry) token on every request.
|
|
16
17
|
fetch: async (input, init) => {
|
|
17
18
|
const headers = new Headers(init?.headers);
|
|
19
|
+
for (const [name, value] of Object.entries(summerRequestHeaders({ tool: calledTool(init?.body), surface: "mcp" })))
|
|
20
|
+
headers.set(name, value);
|
|
18
21
|
headers.set("authorization", `Bearer ${await token()}`);
|
|
19
22
|
return fetch(input, { ...init, headers });
|
|
20
23
|
},
|
|
@@ -32,11 +35,51 @@ export async function connectHostedMcp(url, token) {
|
|
|
32
35
|
close: () => client.close(),
|
|
33
36
|
};
|
|
34
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* The hosted server's 3.x surface: the same address with `?surface=v3`. Once
|
|
40
|
+
* the hosted server serves 4.0 to every request that does not ask, only 3.x
|
|
41
|
+
* npm releases keep 3.x without asking, so the 3.x tool names here ask.
|
|
42
|
+
*/
|
|
43
|
+
export function withV3Surface(url) {
|
|
44
|
+
const parsed = new URL(url);
|
|
45
|
+
parsed.searchParams.set("surface", "v3");
|
|
46
|
+
return parsed.href;
|
|
47
|
+
}
|
|
35
48
|
export const defaultHostedConnectDependencies = {
|
|
36
|
-
url: () => resolveMcpResourceUrl(),
|
|
49
|
+
url: () => withV3Surface(resolveMcpResourceUrl()),
|
|
37
50
|
token: () => getStoreAccessToken(),
|
|
38
51
|
connect: connectHostedMcp,
|
|
39
52
|
};
|
|
53
|
+
/** The hosted server could not be reached, so no call was sent (a sign-in problem is an OAuthError instead). */
|
|
54
|
+
export class HostedUnreachableError extends Error {
|
|
55
|
+
recovery;
|
|
56
|
+
constructor(message, recovery) {
|
|
57
|
+
super(`${message} ${recovery}`);
|
|
58
|
+
this.recovery = recovery;
|
|
59
|
+
this.name = "HostedUnreachableError";
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/** The HTTP status an MCP transport error carries (the SDK's StreamableHTTPError puts it on `code`). */
|
|
63
|
+
export function httpStatusOf(error) {
|
|
64
|
+
const code = error?.code;
|
|
65
|
+
return typeof code === "number" && code >= 100 && code <= 599 ? code : undefined;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* A failure to connect to the hosted server, before any call was sent: a
|
|
69
|
+
* sign-in problem (an OAuthError, or a 401), an account the server refuses
|
|
70
|
+
* (403, store_access_denied), or the server not answering.
|
|
71
|
+
*/
|
|
72
|
+
export function hostedConnectFailure(error, unreachableRecovery) {
|
|
73
|
+
if (error instanceof OAuthError || error instanceof HostedUnreachableError)
|
|
74
|
+
return error;
|
|
75
|
+
const cause = error instanceof Error ? error.message : String(error);
|
|
76
|
+
const status = httpStatusOf(error);
|
|
77
|
+
if (status === 401)
|
|
78
|
+
return new OAuthError("oauth_token_invalid", `Summer's hosted server refused the sign-in: ${cause}.`, 'Recovery: run "summer login --store --force".');
|
|
79
|
+
if (status === 403)
|
|
80
|
+
return new OAuthError("store_access_denied", `Summer's hosted server refused this account: ${cause}.`, "Recovery: check the account in Summer Studio (for example confirm the email), then try again.");
|
|
81
|
+
return new HostedUnreachableError(`The hosted Summer Engine MCP did not answer: ${cause}.`, unreachableRecovery);
|
|
82
|
+
}
|
|
40
83
|
/** True when this machine has a store sign-in on disk (no network). */
|
|
41
84
|
export async function hasStoreSignIn() {
|
|
42
85
|
return (await readStoredOAuthToken()) !== null;
|
|
@@ -162,3 +205,15 @@ export async function callHostedToolForCli(name, args, deps = defaultHostedConne
|
|
|
162
205
|
return { status: "unavailable", message: error instanceof Error ? error.message : String(error) };
|
|
163
206
|
}
|
|
164
207
|
}
|
|
208
|
+
/** The tool a tools/call JSON-RPC body names, for the X-Summer-MCP-Tool header. */
|
|
209
|
+
export function calledTool(body) {
|
|
210
|
+
if (typeof body !== "string" || !body.includes('"tools/call"'))
|
|
211
|
+
return undefined;
|
|
212
|
+
try {
|
|
213
|
+
const message = JSON.parse(body);
|
|
214
|
+
return message.method === "tools/call" && typeof message.params?.name === "string" ? message.params.name : undefined;
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
217
|
+
return undefined;
|
|
218
|
+
}
|
|
219
|
+
}
|