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