summer-engine 3.3.0 → 3.4.1
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 -2
- package/.claude-plugin/plugin.json +4 -2
- package/.codex-plugin/plugin.json +5 -3
- package/.cursor-plugin/plugin.json +4 -2
- package/.factory-plugin/plugin.json +4 -2
- package/.opencode/INSTALL.md +8 -8
- package/.opencode/plugins/summer.js +2 -2
- package/AGENTS.md +7 -7
- package/CHANGELOG.md +50 -0
- package/GEMINI.md +1 -1
- package/NOTICE +1 -1
- package/README.md +32 -35
- package/assets/api-docs.json.gz +0 -0
- package/assets/autopilot/run.sh +2 -2
- package/assets/navigation/web-routes.json +1 -1
- package/commands/gameskill.md +2 -2
- package/commands/summer.md +25 -25
- package/dist/cli/commands/install.d.ts +10 -0
- package/dist/cli/commands/install.js +55 -10
- package/dist/cli/commands/open.d.ts +1 -1
- package/dist/cli/commands/run.d.ts +1 -1
- package/dist/cli/commands/run.js +1 -1
- package/dist/cli/commands/skills.js +2 -2
- package/dist/cli/commands/tool.d.ts +7 -0
- package/dist/cli/commands/tool.js +36 -1
- package/dist/core/api-client.d.ts +5 -6
- package/dist/core/api-client.js +12 -15
- package/dist/core/auth.js +2 -2
- package/dist/core/capabilities/asset-import.d.ts +0 -1
- package/dist/core/capabilities/camera-view.d.ts +1 -1
- package/dist/core/capabilities/camera-view.js +2 -2
- package/dist/core/capabilities/capture-gameplay.d.ts +69 -0
- package/dist/core/capabilities/capture-gameplay.js +283 -0
- package/dist/core/capabilities/connect-signal.d.ts +1 -2
- package/dist/core/capabilities/connect-signal.js +1 -2
- package/dist/core/capabilities/console-read.d.ts +2 -2
- package/dist/core/capabilities/console-read.js +2 -2
- package/dist/core/capabilities/creator.js +1 -1
- package/dist/core/capabilities/doctor.d.ts +9 -1
- package/dist/core/capabilities/doctor.js +47 -4
- package/dist/core/capabilities/engine-receipt.d.ts +5 -7
- package/dist/core/capabilities/engine-receipt.js +7 -9
- package/dist/core/capabilities/engine-run.d.ts +4 -0
- package/dist/core/capabilities/engine-run.js +33 -5
- package/dist/core/capabilities/export-engine-version.d.ts +15 -0
- package/dist/core/capabilities/export-engine-version.js +24 -0
- package/dist/core/capabilities/export-game.d.ts +9 -1
- package/dist/core/capabilities/export-game.js +115 -39
- package/dist/core/capabilities/export-presets.d.ts +1 -1
- package/dist/core/capabilities/export-presets.js +1 -1
- package/dist/core/capabilities/fabricate-mesh.d.ts +2 -3
- package/dist/core/capabilities/fabricate-mesh.js +2 -3
- package/dist/core/capabilities/frame-quality.d.ts +4 -4
- package/dist/core/capabilities/frame-quality.js +4 -4
- package/dist/core/capabilities/grep.d.ts +1 -1
- package/dist/core/capabilities/grep.js +1 -1
- package/dist/core/capabilities/image-generation.d.ts +9 -0
- package/dist/core/capabilities/image-generation.js +19 -1
- package/dist/core/capabilities/navigation/open.d.ts +1 -1
- package/dist/core/capabilities/navigation/open.js +1 -1
- package/dist/core/capabilities/navigation/render-product-map.js +1 -1
- package/dist/core/capabilities/navigation/targets.js +2 -2
- package/dist/core/capabilities/placement-batch.d.ts +1 -1
- package/dist/core/capabilities/placement-batch.js +2 -2
- package/dist/core/capabilities/play-determinism.d.ts +1 -1
- package/dist/core/capabilities/play-determinism.js +1 -1
- package/dist/core/capabilities/publish-build.d.ts +15 -2
- package/dist/core/capabilities/publish-build.js +78 -28
- package/dist/core/capabilities/publish-download.d.ts +1 -2
- package/dist/core/capabilities/publish-download.js +2 -3
- package/dist/core/capabilities/replace-node.d.ts +1 -3
- package/dist/core/capabilities/replace-node.js +1 -3
- package/dist/core/capabilities/runtime-control.d.ts +5 -7
- package/dist/core/capabilities/runtime-control.js +7 -9
- package/dist/core/capabilities/scene-batch.d.ts +1 -1
- package/dist/core/capabilities/scene-batch.js +1 -1
- package/dist/core/capabilities/scene-kind.js +1 -1
- package/dist/core/capabilities/scene-readback.d.ts +3 -4
- package/dist/core/capabilities/scene-readback.js +3 -4
- package/dist/core/capabilities/scene-script.d.ts +2 -2
- package/dist/core/capabilities/scene-script.js +2 -2
- package/dist/core/capabilities/seeing/shot-store.d.ts +1 -1
- package/dist/core/capabilities/seeing/shot-store.js +1 -1
- package/dist/core/capabilities/summer-bundle.d.ts +2 -3
- package/dist/core/capabilities/summer-bundle.js +2 -3
- package/dist/core/capabilities/surface-snap.d.ts +1 -1
- package/dist/core/capabilities/surface-snap.js +1 -1
- package/dist/core/capabilities/tool-dispatch.js +11 -1
- package/dist/core/capabilities/ui-control.d.ts +1 -2
- package/dist/core/capabilities/ui-control.js +1 -2
- package/dist/core/capabilities/world-snapshot.d.ts +1 -1
- package/dist/core/capabilities/world-snapshot.js +1 -1
- package/dist/core/capability-skew.d.ts +2 -3
- package/dist/core/capability-skew.js +4 -5
- package/dist/core/config.js +2 -2
- package/dist/core/engine-install.d.ts +16 -0
- package/dist/core/engine-install.js +32 -2
- package/dist/core/feedback/client.js +1 -1
- package/dist/core/hosted-mcp.d.ts +115 -0
- package/dist/core/hosted-mcp.js +164 -0
- package/dist/core/launch-posture.d.ts +6 -3
- package/dist/core/launch-posture.js +18 -5
- package/dist/core/library-read.js +1 -2
- package/dist/core/templates.d.ts +1 -2
- package/dist/core/templates.js +1 -2
- package/dist/mcp/hosted-mount.d.ts +13 -59
- package/dist/mcp/hosted-mount.js +24 -30
- package/dist/mcp/server.d.ts +2 -2
- package/dist/mcp/server.js +5 -4
- package/dist/mcp/tools/creator-tools.js +14 -4
- package/dist/mcp/tools/debug-tools.js +1 -1
- package/dist/mcp/tools/generate-tools.js +19 -9
- package/dist/mcp/tools/navigation-tools.d.ts +1 -1
- package/dist/mcp/tools/navigation-tools.js +1 -1
- package/dist/mcp/tools/spatial-tools.js +1 -1
- package/dist/mcp/tools/visual-tools.js +2 -2
- package/dist/mcp/tools/with-engine.d.ts +1 -2
- package/dist/mcp/tools/with-engine.js +1 -2
- package/gemini-extension.json +3 -1
- package/hooks/session-start.sh +2 -2
- package/integrations/README.md +70 -76
- package/integrations/claude/README.md +0 -3
- package/integrations/codex/README.md +1 -2
- package/integrations/copilot-jetbrains/README.md +1 -1
- package/integrations/cursor/README.md +1 -2
- package/integrations/factory/README.md +15 -11
- package/integrations/mistral-vibe/README.md +1 -1
- package/integrations/opencode/README.md +1 -1
- package/integrations/roo-code/README.md +1 -1
- package/integrations/rovo-dev/README.md +1 -1
- package/integrations/trae/README.md +1 -1
- package/integrations/windsurf/README.md +3 -3
- package/library/references/collaborative-protocol/collaborative-protocol.md +5 -5
- package/library/references/gd-style/gd-style.md +4 -6
- package/library/references/godot-version/godot-version.md +3 -3
- package/library/references/headless-routing/headless-routing.md +2 -2
- package/library/references/mcp-fresh-chat-playbook/mcp-fresh-chat-playbook.md +2 -2
- package/library/references/mcp-tools-reference/mcp-tools-reference.md +18 -16
- package/library/references/product-map/product-map.md +1 -1
- package/library/references/public-surface-language/public-surface-language.md +1 -1
- package/library/references/summer-folder/summer-folder.md +1 -1
- package/library/skills/3d-lighting/SKILL.md +4 -4
- package/library/skills/README.md +11 -9
- package/library/skills/adaptive-music/SKILL.md +7 -7
- package/library/skills/ai-characters-in-games/SKILL.md +1 -1
- package/library/skills/ambient-bed/SKILL.md +12 -14
- package/library/skills/animated-loop/SKILL.md +42 -42
- package/library/skills/animation-tree/SKILL.md +6 -6
- package/library/skills/art-direction/SKILL.md +8 -11
- package/library/skills/asset-strategy/SKILL.md +3 -3
- package/library/skills/audio-direction/SKILL.md +8 -10
- package/library/skills/auto-fire-targeting/SKILL.md +4 -3
- package/library/skills/bounded-engine-runs/SKILL.md +95 -0
- package/library/skills/bounded-engine-runs/resource.yaml +29 -0
- package/library/skills/brainstorm-game/SKILL.md +5 -5
- package/library/skills/brainstorming/SKILL.md +9 -15
- package/library/skills/celeste-momentum-platforming/SKILL.md +8 -13
- package/library/skills/celeste-momentum-platforming/resource.yaml +1 -1
- package/library/skills/character-animation-wiring/SKILL.md +2 -2
- package/library/skills/character-model/SKILL.md +15 -26
- package/library/skills/character-movement/SKILL.md +1 -1
- package/library/skills/character-movement/references/movement-3d.md +1 -1
- package/library/skills/character-portrait/SKILL.md +4 -4
- package/library/skills/cinematic-cutscene/SKILL.md +38 -38
- package/library/skills/combat-basics/SKILL.md +1 -1
- package/library/skills/compatibility-renderer-traps/SKILL.md +78 -0
- package/library/skills/compatibility-renderer-traps/resource.yaml +28 -0
- package/library/skills/concept-art/SKILL.md +4 -4
- package/library/skills/create-asset-sheet/SKILL.md +12 -31
- package/library/skills/debug/SKILL.md +5 -4
- package/library/skills/debugging-game-feel/SKILL.md +1 -4
- package/library/skills/debugging-game-feel/resource.yaml +1 -1
- package/library/skills/design-level/SKILL.md +5 -5
- package/library/skills/design-mechanic/SKILL.md +6 -6
- package/library/skills/design-npc/SKILL.md +8 -15
- package/library/skills/diagnosing-perf-regressions/SKILL.md +5 -10
- package/library/skills/dispatching-parallel-agents/SKILL.md +1 -19
- package/library/skills/environment-kit/SKILL.md +5 -5
- package/library/skills/export-and-ship/SKILL.md +25 -24
- package/library/skills/fabricating-assets/SKILL.md +1 -1
- package/library/skills/facial-and-lipsync/SKILL.md +5 -5
- package/library/skills/fps-controller/SKILL.md +17 -16
- package/library/skills/fps-controller/resource.yaml +0 -2
- package/library/skills/game-feel/SKILL.md +6 -7
- package/library/skills/gameskill/SKILL.md +3 -3
- package/library/skills/gdscript-patterns/SKILL.md +3 -3
- package/library/skills/generate-motion/SKILL.md +5 -22
- package/library/skills/godogen-visual-proof-game-generation/SKILL.md +72 -90
- package/library/skills/godogen-visual-proof-game-generation/resource.yaml +0 -1
- package/library/skills/headless-scripting/SKILL.md +8 -8
- package/library/skills/headless-scripting/resource.yaml +1 -0
- package/library/skills/in-game-purchases/SKILL.md +123 -118
- package/library/skills/in-game-purchases/resource.yaml +2 -2
- package/library/skills/instantiate-asset-pack/SKILL.md +7 -3
- package/library/skills/investigating-bugs/SKILL.md +3 -11
- package/library/skills/investigating-bugs/condition-based-waiting.md +0 -10
- package/library/skills/investigating-bugs/root-cause-tracing.md +0 -8
- package/library/skills/lumera-single-image-scene-reconstruction/SKILL.md +15 -15
- package/library/skills/lumera-single-image-scene-reconstruction/resource.yaml +0 -1
- package/library/skills/make-game/SKILL.md +3 -5
- package/library/skills/make-game/references/2d-platformer.md +1 -1
- package/library/skills/multiplayer-project/SKILL.md +1 -1
- package/library/skills/multiplayer-testing/SKILL.md +4 -4
- package/library/skills/music-track/SKILL.md +40 -38
- package/library/skills/new-project/SKILL.md +4 -6
- package/library/skills/organic-model/SKILL.md +9 -9
- package/library/skills/pixel-art/SKILL.md +6 -6
- package/library/skills/play/SKILL.md +3 -4
- package/library/skills/playtesting-a-feature/SKILL.md +4 -6
- package/library/skills/procedural-animation/SKILL.md +10 -11
- package/library/skills/prop-model/SKILL.md +4 -4
- package/library/skills/psx-retro-rendering/SKILL.md +20 -20
- package/library/skills/psx-retro-rendering/resource.yaml +2 -3
- package/library/skills/realtime-wet-surfaces/SKILL.md +15 -15
- package/library/skills/realtime-wet-surfaces/resource.yaml +1 -2
- package/library/skills/remote-deploy/SKILL.md +20 -21
- package/library/skills/retarget/SKILL.md +19 -23
- package/library/skills/running-in-the-cloud/SKILL.md +5 -5
- package/library/skills/scene-composition/SKILL.md +5 -5
- package/library/skills/scene-hierarchy-design/SKILL.md +3 -3
- package/library/skills/scene-hierarchy-design/resource.yaml +0 -1
- package/library/skills/scene-scripting/SKILL.md +3 -3
- package/library/skills/scene-to-level/SKILL.md +28 -31
- package/library/skills/skill-create/SKILL.md +1 -1
- package/library/skills/skill-improve/SKILL.md +9 -9
- package/library/skills/skill-test/SKILL.md +10 -10
- package/library/skills/skintokens-auto-rigging/SKILL.md +18 -18
- package/library/skills/skintokens-auto-rigging/resource.yaml +3 -3
- package/library/skills/skybox-panorama/SKILL.md +8 -9
- package/library/skills/sound-effect/SKILL.md +19 -19
- package/library/skills/spatial-placement/SKILL.md +2 -2
- package/library/skills/spatial-placement/references/kit-placement-tools.md +12 -22
- package/library/skills/sprite-sheet/SKILL.md +10 -10
- package/library/skills/summer-analytics/SKILL.md +3 -3
- package/library/skills/summer-friends/SKILL.md +10 -10
- package/library/skills/summer-leaderboards/SKILL.md +6 -6
- package/library/skills/summer-match-results/SKILL.md +13 -13
- package/library/skills/summer-matchmaking/SKILL.md +11 -11
- package/library/skills/summer-parties/SKILL.md +9 -9
- package/library/skills/summer-player-data/SKILL.md +12 -12
- package/library/skills/summer-store/SKILL.md +6 -6
- package/library/skills/summer-world-chat/SKILL.md +9 -9
- package/library/skills/summer-world-saves/SKILL.md +7 -7
- package/library/skills/text-to-motion/rigging-for-text-motion.md +1 -1
- package/library/skills/tileable-texture/SKILL.md +1 -1
- package/library/skills/trailer-shot/SKILL.md +36 -36
- package/library/skills/tune-performance/SKILL.md +13 -13
- package/library/skills/tune-performance/resource.yaml +1 -1
- package/library/skills/ui-graphics/SKILL.md +7 -7
- package/library/skills/use-widget-asset/SKILL.md +7 -7
- package/library/skills/using-summer/SKILL.md +5 -7
- package/library/skills/vehicle-model/SKILL.md +6 -7
- package/library/skills/vehicle-model/resource.yaml +2 -2
- package/library/skills/verification-before-completion/SKILL.md +5 -6
- package/library/skills/vfx-dissolve/SKILL.md +4 -4
- package/library/skills/vfx-fire/SKILL.md +6 -6
- package/library/skills/vfx-fire/_building-blocks/additive-billboard-particles.md +3 -3
- package/library/skills/vfx-hit-spark/SKILL.md +4 -4
- package/library/skills/vfx-hit-spark/_building-blocks/additive-billboard-particles.md +3 -3
- package/library/skills/vfx-lightning/SKILL.md +5 -5
- package/library/skills/vfx-lightning/_building-blocks/additive-billboard-particles.md +3 -3
- package/library/skills/vfx-lightning/_building-blocks/trauma-shake-snippet.md +9 -3
- package/library/skills/vfx-magic-glow/SKILL.md +4 -4
- package/library/skills/vfx-magic-glow/_building-blocks/additive-billboard-particles.md +3 -3
- package/library/skills/vfx-muzzle-flash/SKILL.md +5 -5
- package/library/skills/vfx-muzzle-flash/_building-blocks/additive-billboard-particles.md +3 -3
- package/library/skills/vfx-muzzle-flash/_building-blocks/trauma-shake-snippet.md +9 -3
- package/library/skills/vfx-smoke/SKILL.md +5 -5
- package/library/skills/vfx-water-ripple/SKILL.md +2 -2
- package/library/skills/vfx-water-ripple/_building-blocks/additive-billboard-particles.md +3 -3
- package/library/skills/voice-line/SKILL.md +9 -9
- package/library/skills/web-compatibility-look/resource.yaml +1 -0
- package/library/skills/world-building-3d/references/spatial-tools.md +2 -2
- package/library/skills/writing-plans/SKILL.md +4 -4
- package/library/skills/writing-skills/SKILL.md +8 -8
- package/library/tools/capture-gameplay/resource.yaml +73 -0
- package/library/tools/creator-publish/resource.yaml +4 -4
- package/library/tools/creator-releases/resource.yaml +5 -5
- package/library/tools/generate-image/resource.yaml +15 -1
- package/library/tools/publish-build/resource.yaml +6 -2
- package/package.json +1 -1
- package/registry/generated/aliases.json +1 -0
- package/registry/generated/counts.json +3 -3
- package/registry/generated/gemini-extension.json +3 -1
- package/registry/generated/index.json +248 -135
- package/registry/generated/marketplace.claude.json +2 -2
- package/registry/generated/plugin.claude.json +4 -2
- package/registry/generated/plugin.codex.json +5 -3
- package/registry/generated/plugin.cursor.json +4 -2
- package/registry/generated/plugin.factory.json +4 -2
- package/registry/generated/skills-index.md +11 -9
- package/registry/generated/skills-registry.json +33 -6
- package/registry/schemas/domains.json +1 -1
package/commands/gameskill.md
CHANGED
|
@@ -5,10 +5,10 @@ allowed-tools: Read Write Edit Glob Grep Bash Skill
|
|
|
5
5
|
|
|
6
6
|
# /gameskill — capture session learnings
|
|
7
7
|
|
|
8
|
-
Activate the library skill `
|
|
8
|
+
Activate the library skill `gameskill` and follow it exactly; this command is only the entry point. If the `Skill` tool cannot find it, read `library/skills/gameskill/SKILL.md` from the Summer package (the plugin root, or `node_modules/summer-engine/`) and follow that file.
|
|
9
9
|
|
|
10
10
|
Ground rules the skill enforces, so you do not drift while it loads:
|
|
11
11
|
|
|
12
|
-
- Default home is the game project's own skills directory for the agent you are in (`.claude/skills/<slug>/`, `.agents/skills/<slug
|
|
12
|
+
- Default home is the game project's own skills directory for the agent you are in (`.claude/skills/<slug>/`, `.agents/skills/<slug>/`). Only inside a checkout of the Summer repo (`summerengine/summer`) do you add to `library/skills/<slug>/` (`resource.yaml` + `SKILL.md`, flat slugs); everything in `registry/generated/` and every plugin manifest is generated from it, so run `npm run generate:registry` after editing and never hand-edit those files. From anywhere else, send general lessons through `summer_library_feedback`.
|
|
13
13
|
- Capture only learnings that are non-obvious AND general. Lead with the why. Real working code from the active project beats invented examples. VFX is shader + GDScript + node setup, never an image-generation pipeline.
|
|
14
14
|
- It is fine to report "session was tactical, no durable learnings." Do not manufacture skills.
|
package/commands/summer.md
CHANGED
|
@@ -20,43 +20,43 @@ You know the engine cold. Scenes are `.tscn`, resources are `.tres`, scripts are
|
|
|
20
20
|
|
|
21
21
|
You are opinionated about scope. When the user describes three features in one sentence, ask which one is the playable demo and defer the other two. "Wouldn't it be cool if" gets "yes, after the core loop runs." Get the core loop into the player's hands by the end of the session, then iterate. Polish happens after the game is playable, not before.
|
|
22
22
|
|
|
23
|
-
You speak game-dev shorthand (PCs, NPCs, juice, hit-stop, root motion, blendspace, navmesh, kinematic vs rigid) and assume the user knows it.
|
|
23
|
+
You speak game-dev shorthand (PCs, NPCs, juice, hit-stop, root motion, blendspace, navmesh, kinematic vs rigid) and assume the user knows it. Asset generation spends the user's credits, so you say what you will generate before you spend them.
|
|
24
24
|
|
|
25
25
|
## What to do
|
|
26
26
|
|
|
27
27
|
1. Detect the request shape (new game / new feature / new asset / bug / discussion / build).
|
|
28
|
-
2. Confirm Summer Engine context. Call `summer_get_project_context` if available. If it returns nothing, the user is not in a Summer project yet — route to `
|
|
28
|
+
2. Confirm Summer Engine context. Call `summer_get_project_context` if available. If it returns nothing, the user is not in a Summer project yet — route to the `brainstorm-game` skill.
|
|
29
29
|
3. Invoke the right Summer skill with the `Skill` tool. Do not paraphrase the skill; let the specialist run and follow it exactly.
|
|
30
|
-
4.
|
|
30
|
+
4. Before any generation call, say what you will generate and roughly how long it takes, and wait for an OK.
|
|
31
31
|
|
|
32
32
|
## Routing
|
|
33
33
|
|
|
34
|
-
Skills are
|
|
34
|
+
Skills are invoked by their bare slug, such as `brainstorm-game`. There is no `summer:` prefix and there are no category paths.
|
|
35
35
|
|
|
36
36
|
| Request shape | First skill |
|
|
37
37
|
|---|---|
|
|
38
|
-
| brainstorm a [genre] game / let's make a [genre] / I'm stuck / what should I work on | `
|
|
39
|
-
| start a new project | `
|
|
40
|
-
| make me a game from scratch | `
|
|
41
|
-
| add a [character / enemy / NPC / prop / vehicle] | `
|
|
42
|
-
| add a sound for [event] | `
|
|
43
|
-
| add ambient music | `
|
|
44
|
-
| make me fire / smoke / lightning / muzzle flash / magic glow / hit spark / dissolve / water ripple | `
|
|
45
|
-
| build the FPS controller | `
|
|
46
|
-
| debug / the game crashes when [X] / broken behavior / cloud or Codex failure / send this to support | `
|
|
47
|
-
| add an animation to [character] | `
|
|
48
|
-
| wire up a state machine for [character] | `
|
|
49
|
-
| the game feels mushy / add juice | `
|
|
50
|
-
| ship a trailer | `
|
|
51
|
-
| cutscene for [X] | `
|
|
52
|
-
| let me play it | `
|
|
53
|
-
|
|
54
|
-
If nothing fits, activate `
|
|
38
|
+
| brainstorm a [genre] game / let's make a [genre] / I'm stuck / what should I work on | `brainstorm-game` |
|
|
39
|
+
| start a new project | `new-project` |
|
|
40
|
+
| make me a game from scratch | `make-game` |
|
|
41
|
+
| add a [character / enemy / NPC / prop / vehicle] | `asset-strategy` |
|
|
42
|
+
| add a sound for [event] | `sound-effect` |
|
|
43
|
+
| add ambient music | `music-track` |
|
|
44
|
+
| make me fire / smoke / lightning / muzzle flash / magic glow / hit spark / dissolve / water ripple | `vfx-fire`, `vfx-smoke`, `vfx-lightning`, `vfx-muzzle-flash`, `vfx-magic-glow`, `vfx-hit-spark`, `vfx-dissolve`, `vfx-water-ripple` |
|
|
45
|
+
| build the FPS controller | `fps-controller` |
|
|
46
|
+
| debug / the game crashes when [X] / broken behavior / cloud or Codex failure / send this to support | `debug` (support-report mode first: call `summer_create_debug_report` when available and tell the user where the Markdown report was written; keep fixing only if they also asked for a fix) |
|
|
47
|
+
| add an animation to [character] | `generate-motion` |
|
|
48
|
+
| wire up a state machine for [character] | `animation-tree` |
|
|
49
|
+
| the game feels mushy / add juice | `game-feel` |
|
|
50
|
+
| ship a trailer | `trailer-shot` |
|
|
51
|
+
| cutscene for [X] | `cinematic-cutscene` |
|
|
52
|
+
| let me play it | `play` |
|
|
53
|
+
|
|
54
|
+
If nothing fits, activate `using-summer` and call `summer_search_library` (then `summer_read_library`) to find the closest skill. Never invent a skill name; verify it exists first.
|
|
55
55
|
|
|
56
56
|
## Tone rules
|
|
57
57
|
|
|
58
58
|
- No corporate hedging. "I'd recommend" becomes "do this." "It might be worth considering" becomes "next step is."
|
|
59
|
-
-
|
|
59
|
+
- Ask before spending: "Generating a 5s clip with kling, about 3 minutes. OK?" Never "I'll generate a video now."
|
|
60
60
|
- Scope-aware: the cut list goes in `.summer/GameSoul.md`, not in V1.
|
|
61
61
|
- Confirm before destructive moves: replacing nodes, deleting assets, regenerating expensive outputs.
|
|
62
62
|
- Do not redirect users to external docs; solve it in-conversation.
|
|
@@ -70,12 +70,12 @@ If nothing fits, activate `summer:using-summer` and call `summer_search_library`
|
|
|
70
70
|
|
|
71
71
|
> User: /summer make a knight
|
|
72
72
|
>
|
|
73
|
-
> Summer: Knight character. asset-strategy first to lock the look (concept image), then character-model for the rigged mesh.
|
|
73
|
+
> Summer: Knight character. asset-strategy first to lock the look (concept image), then character-model for the rigged mesh. Two generations. OK?
|
|
74
74
|
>
|
|
75
|
-
> [invokes `
|
|
75
|
+
> [invokes `asset-strategy`]
|
|
76
76
|
|
|
77
77
|
> User: /summer the game crashes when I pick up the sword
|
|
78
78
|
>
|
|
79
79
|
> Summer: Going to debug. Writing the support report first, then the fix.
|
|
80
80
|
>
|
|
81
|
-
> [invokes `
|
|
81
|
+
> [invokes `debug`]
|
|
@@ -44,6 +44,16 @@ export declare function replaceMacApp(mountPoint: string, destApp: string, exec:
|
|
|
44
44
|
* setup.exe CLI). The old NSIS flags (/S, /D=) are rejected by the Velopack
|
|
45
45
|
* installer with "unexpected argument '/S' found" — this is the wizard bug. */
|
|
46
46
|
export declare function windowsInstallerArgs(customPath?: string): string;
|
|
47
|
+
/** Printed after an install: the first start of a new engine is slow and silent. */
|
|
48
|
+
export declare const FIRST_START_NOTE: string;
|
|
49
|
+
/** Where the Velopack installer put Summer.exe: <dir>/current/Summer.exe for --path, else the default locations. */
|
|
50
|
+
export declare function windowsInstalledBinary(customPath?: string, exists?: (path: string) => boolean): string | null;
|
|
51
|
+
/**
|
|
52
|
+
* Download progress: rewrites one line on a terminal; elsewhere (an agent,
|
|
53
|
+
* a log file) one line per 10%, so a 1 GB download is about ten lines
|
|
54
|
+
* instead of hundreds of kilobytes.
|
|
55
|
+
*/
|
|
56
|
+
export declare function createProgressReporter(isTTY: boolean, write: (text: string) => void): (downloaded: number, total: number) => void;
|
|
47
57
|
export declare const installCommand: Command;
|
|
48
58
|
export declare function downloadFile(url: string, dest: string): Promise<{
|
|
49
59
|
sha256: string;
|
|
@@ -6,8 +6,8 @@ import { chmodSync, createWriteStream, existsSync, mkdirSync, readdirSync, renam
|
|
|
6
6
|
import { pipeline } from "stream/promises";
|
|
7
7
|
import { Readable } from "stream";
|
|
8
8
|
import { tmpdir, platform } from "os";
|
|
9
|
-
import { join, resolve } from "path";
|
|
10
|
-
import { ENGINE_BINARY_ENV, LINUX_ENGINE_BINARY_NAME, findExtractedEngineBinary, linuxArchiveKind, linuxEngineInstallDir, pickLinuxReleaseAsset, resolveLinuxInstallSource, } from "../../core/engine-install.js";
|
|
9
|
+
import { dirname, join, resolve } from "path";
|
|
10
|
+
import { ENGINE_BINARY_ENV, LINUX_ENGINE_BINARY_NAME, macInstallDestination, recordEngineInstall, windowsEnginePaths, findExtractedEngineBinary, linuxArchiveKind, linuxEngineInstallDir, pickLinuxReleaseAsset, resolveLinuxInstallSource, } from "../../core/engine-install.js";
|
|
11
11
|
const RELEASES_URL = "https://www.summerengine.com/api/desktop/releases";
|
|
12
12
|
/** Guard a download URL from the releases endpoint. A missing/empty URL (an
|
|
13
13
|
* outdated or misconfigured endpoint) otherwise becomes a cryptic
|
|
@@ -116,9 +116,42 @@ async function confirm(question) {
|
|
|
116
116
|
export function windowsInstallerArgs(customPath) {
|
|
117
117
|
return customPath ? `--silent --installto "${customPath}"` : "--silent";
|
|
118
118
|
}
|
|
119
|
+
/** Printed after an install: the first start of a new engine is slow and silent. */
|
|
120
|
+
export const FIRST_START_NOTE = "The first start of a new engine version can take several minutes with no output " +
|
|
121
|
+
"(the system checks the new app and the engine builds its caches). Later starts are fast.";
|
|
122
|
+
/** Where the Velopack installer put Summer.exe: <dir>/current/Summer.exe for --path, else the default locations. */
|
|
123
|
+
export function windowsInstalledBinary(customPath, exists = existsSync) {
|
|
124
|
+
const candidates = customPath
|
|
125
|
+
? [join(customPath, "current", "Summer.exe"), join(customPath, "Summer.exe")]
|
|
126
|
+
: windowsEnginePaths();
|
|
127
|
+
return candidates.find((path) => exists(path)) ?? null;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Download progress: rewrites one line on a terminal; elsewhere (an agent,
|
|
131
|
+
* a log file) one line per 10%, so a 1 GB download is about ten lines
|
|
132
|
+
* instead of hundreds of kilobytes.
|
|
133
|
+
*/
|
|
134
|
+
export function createProgressReporter(isTTY, write) {
|
|
135
|
+
let lastStep = -1;
|
|
136
|
+
return (downloaded, total) => {
|
|
137
|
+
if (total <= 0)
|
|
138
|
+
return;
|
|
139
|
+
const pct = Math.min(100, Math.floor((downloaded / total) * 100));
|
|
140
|
+
const mb = (downloaded / 1024 / 1024).toFixed(1);
|
|
141
|
+
if (isTTY) {
|
|
142
|
+
write(`\r ${pct}% (${mb}MB)`);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
const step = Math.floor(pct / 10);
|
|
146
|
+
if (step > lastStep) {
|
|
147
|
+
lastStep = step;
|
|
148
|
+
write(` ${pct}% (${mb}MB)\n`);
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
}
|
|
119
152
|
export const installCommand = new Command("install")
|
|
120
153
|
.description("Download and install Summer Engine")
|
|
121
|
-
.option("--path <dir>", "Custom install directory")
|
|
154
|
+
.option("--path <dir>", "Custom install directory (macOS: the engine goes in <dir>/Summer.app). summer remembers it, so later commands find this engine")
|
|
122
155
|
.option("--yes", "Replace an already-installed engine without prompting")
|
|
123
156
|
.action(async (opts) => {
|
|
124
157
|
const os = platform();
|
|
@@ -160,7 +193,8 @@ async function installMac(releases, customPath, yes = false) {
|
|
|
160
193
|
}
|
|
161
194
|
const dmgUrl = requireDownloadUrl(info.dmg_url, "macOS DMG");
|
|
162
195
|
console.log(`Latest version: ${info.version}`);
|
|
163
|
-
const destApp = customPath
|
|
196
|
+
const destApp = macInstallDestination(customPath);
|
|
197
|
+
const destBinary = join(destApp, "Contents", "MacOS", "Summer");
|
|
164
198
|
const exists = existsSync(destApp);
|
|
165
199
|
const installedVersion = exists ? readMacBundleVersion(destApp) : null;
|
|
166
200
|
const plan = planMacInstall({
|
|
@@ -171,6 +205,7 @@ async function installMac(releases, customPath, yes = false) {
|
|
|
171
205
|
isTTY: Boolean(process.stdin.isTTY),
|
|
172
206
|
});
|
|
173
207
|
if (plan.action === "up-to-date") {
|
|
208
|
+
await recordEngineInstall(destBinary, plan.version);
|
|
174
209
|
console.log(`Summer Engine v${plan.version} is already installed at ${destApp} (up to date).`);
|
|
175
210
|
return;
|
|
176
211
|
}
|
|
@@ -218,6 +253,7 @@ async function installMac(releases, customPath, yes = false) {
|
|
|
218
253
|
}
|
|
219
254
|
try {
|
|
220
255
|
console.log("Installing to " + destApp + "...");
|
|
256
|
+
mkdirSync(dirname(destApp), { recursive: true });
|
|
221
257
|
replaceMacApp(mountPoint, destApp, (command) => execSync(command, { stdio: "ignore" }));
|
|
222
258
|
console.log("Done!");
|
|
223
259
|
}
|
|
@@ -235,7 +271,9 @@ async function installMac(releases, customPath, yes = false) {
|
|
|
235
271
|
catch { }
|
|
236
272
|
releaseSignals();
|
|
237
273
|
}
|
|
274
|
+
await recordEngineInstall(destBinary, info.version);
|
|
238
275
|
console.log(`\nSummer Engine v${info.version} installed to ${destApp}`);
|
|
276
|
+
console.log(FIRST_START_NOTE);
|
|
239
277
|
console.log("\nNext steps:");
|
|
240
278
|
console.log(" summer login # Sign in to your account");
|
|
241
279
|
console.log(" summer run # Launch the engine");
|
|
@@ -276,7 +314,11 @@ async function installWindows(releases, customPath) {
|
|
|
276
314
|
execSync(`del "${exePath}"`, { stdio: "ignore" });
|
|
277
315
|
}
|
|
278
316
|
catch { }
|
|
279
|
-
|
|
317
|
+
const installed = windowsInstalledBinary(customPath);
|
|
318
|
+
if (installed)
|
|
319
|
+
await recordEngineInstall(installed, info.version);
|
|
320
|
+
console.log(`\nSummer Engine v${info.version} installed${installed ? ` to ${installed}` : "!"}`);
|
|
321
|
+
console.log(FIRST_START_NOTE);
|
|
280
322
|
console.log("\nNext steps:");
|
|
281
323
|
console.log(" summer login # Sign in to your account");
|
|
282
324
|
console.log(" summer run # Launch the engine");
|
|
@@ -338,6 +380,7 @@ async function installLinux(customPath) {
|
|
|
338
380
|
const source = resolveLinuxInstallSource();
|
|
339
381
|
if (source.kind === "binary") {
|
|
340
382
|
registerExistingLinuxBinary(source.path, destDir, destBinary);
|
|
383
|
+
await recordEngineInstall(destBinary, null);
|
|
341
384
|
printLinuxNextSteps(destBinary);
|
|
342
385
|
return;
|
|
343
386
|
}
|
|
@@ -409,7 +452,9 @@ async function installLinux(customPath) {
|
|
|
409
452
|
finally {
|
|
410
453
|
rmSync(downloadPath, { force: true });
|
|
411
454
|
}
|
|
455
|
+
await recordEngineInstall(destBinary, versionLabel === "custom" ? null : versionLabel);
|
|
412
456
|
console.log(`\nSummer Engine (${versionLabel}) installed to ${destBinary}`);
|
|
457
|
+
console.log(FIRST_START_NOTE);
|
|
413
458
|
printLinuxNextSteps(destBinary);
|
|
414
459
|
}
|
|
415
460
|
function printLinuxNextSteps(binary) {
|
|
@@ -433,15 +478,15 @@ export async function downloadFile(url, dest) {
|
|
|
433
478
|
const hash = createHash("sha256");
|
|
434
479
|
let downloaded = 0;
|
|
435
480
|
const total = parseInt(res.headers.get("content-length") || "0", 10);
|
|
481
|
+
const isTTY = Boolean(process.stdout.isTTY);
|
|
482
|
+
const report = createProgressReporter(isTTY, (text) => process.stdout.write(text));
|
|
436
483
|
readable.on("data", (chunk) => {
|
|
437
484
|
hash.update(chunk);
|
|
438
485
|
downloaded += chunk.length;
|
|
439
|
-
|
|
440
|
-
const pct = Math.round((downloaded / total) * 100);
|
|
441
|
-
process.stdout.write(`\r ${pct}% (${(downloaded / 1024 / 1024).toFixed(1)}MB)`);
|
|
442
|
-
}
|
|
486
|
+
report(downloaded, total);
|
|
443
487
|
});
|
|
444
488
|
await pipeline(readable, fileStream);
|
|
445
|
-
|
|
489
|
+
if (isTTY)
|
|
490
|
+
process.stdout.write("\n");
|
|
446
491
|
return { sha256: hash.digest("hex") };
|
|
447
492
|
}
|
|
@@ -7,7 +7,7 @@ import { type OpenDeps, type OpenResult, type OpenSurface } from "../../core/cap
|
|
|
7
7
|
* Summer Engine (launching it when it is not running). Any argument that is
|
|
8
8
|
* an existing directory or looks like a filesystem path takes this branch,
|
|
9
9
|
* so nothing that worked before changes.
|
|
10
|
-
* 2. `summer open <target>` — navigation
|
|
10
|
+
* 2. `summer open <target>` — navigation:
|
|
11
11
|
* a product-map id ("billing"), an intent phrase ("change my plan"), a
|
|
12
12
|
* res:// path, or a summerengine.com path. Same behavior as the
|
|
13
13
|
* summer_open MCP tool and `summer tool open` (core/capabilities/navigation).
|
|
@@ -13,7 +13,7 @@ export type RunBinaryResolution = {
|
|
|
13
13
|
* (findEngineBinary, which also honours the older SUMMER_ENGINE_BINARY).
|
|
14
14
|
* An explicit override is never silently swapped for the installed engine:
|
|
15
15
|
* a missing path or a bare `.app` bundle is an error, because the caller
|
|
16
|
-
* asked for THAT build
|
|
16
|
+
* asked for THAT build.
|
|
17
17
|
*/
|
|
18
18
|
export declare function resolveRunBinary(binFlag: string | undefined, env?: NodeJS.ProcessEnv): RunBinaryResolution;
|
|
19
19
|
export declare const runCommand: Command;
|
package/dist/cli/commands/run.js
CHANGED
|
@@ -79,7 +79,7 @@ async function withLaunchLock(fn) {
|
|
|
79
79
|
* (findEngineBinary, which also honours the older SUMMER_ENGINE_BINARY).
|
|
80
80
|
* An explicit override is never silently swapped for the installed engine:
|
|
81
81
|
* a missing path or a bare `.app` bundle is an error, because the caller
|
|
82
|
-
* asked for THAT build
|
|
82
|
+
* asked for THAT build.
|
|
83
83
|
*/
|
|
84
84
|
export function resolveRunBinary(binFlag, env = process.env) {
|
|
85
85
|
const fromEnv = engineBinaryOverride(env);
|
|
@@ -340,7 +340,7 @@ skillsCommand
|
|
|
340
340
|
console.log(previewIncludedLine(previewIncluded));
|
|
341
341
|
if (previewSkipped > 0)
|
|
342
342
|
console.log(previewSkippedLine(previewSkipped));
|
|
343
|
-
// Claude Code: also install slash commands (`
|
|
343
|
+
// Claude Code: also install slash commands (`commands/*.md`)
|
|
344
344
|
// into `~/.claude/commands/`. Other agents don't have an equivalent today.
|
|
345
345
|
if (agent === "claude-code") {
|
|
346
346
|
const commandResults = installClaudeCommands(scope, Boolean(opts.force));
|
|
@@ -352,7 +352,7 @@ skillsCommand
|
|
|
352
352
|
printInstallSummary(skills.length, agent, scope, location);
|
|
353
353
|
});
|
|
354
354
|
/**
|
|
355
|
-
* Copy every `.md` file in `
|
|
355
|
+
* Copy every `.md` file in the package's `commands/` to the user's
|
|
356
356
|
* `~/.claude/commands/` directory so the slash commands (e.g. `/gameskill`)
|
|
357
357
|
* are available on every machine that runs `summer skills install`.
|
|
358
358
|
*
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
2
|
import { type ToolDispatchEntry } from "../../core/capabilities/tool-dispatch.js";
|
|
3
|
+
import { callHostedToolForCli, listHostedToolsForCli, type HostedToolsListing } from "../../core/hosted-mcp.js";
|
|
4
|
+
/** The hosted store and publishing tools (Summer Engine MCP); replaceable in tests. */
|
|
5
|
+
export declare const hostedCli: {
|
|
6
|
+
list: typeof listHostedToolsForCli;
|
|
7
|
+
call: typeof callHostedToolForCli;
|
|
8
|
+
};
|
|
9
|
+
export declare function formatHostedToolList(listing: HostedToolsListing): string;
|
|
3
10
|
/** Resolve a name through the compiled registry index when it exists —
|
|
4
11
|
* accepts full ids ("tool/add-node") and legacy aliases, returning the slug
|
|
5
12
|
* the dispatch table knows. Returns null when the index is absent or the
|
|
@@ -14,6 +14,25 @@ import { PACKAGE_ROOT } from "../../core/package-root.js";
|
|
|
14
14
|
import { Command, Option } from "commander";
|
|
15
15
|
import { ToolDispatchError, ToolResultError, dispatchTool, listToolDispatches, resolveToolDispatch, } from "../../core/capabilities/tool-dispatch.js";
|
|
16
16
|
import { c } from "../../core/format.js";
|
|
17
|
+
import { callHostedToolForCli, hostedResultPayload, listHostedToolsForCli, } from "../../core/hosted-mcp.js";
|
|
18
|
+
/** The hosted store and publishing tools (Summer Engine MCP); replaceable in tests. */
|
|
19
|
+
export const hostedCli = { list: listHostedToolsForCli, call: callHostedToolForCli };
|
|
20
|
+
const STORE_SIGN_IN_HINT = "Store and publishing tools (summer_store_*, summer_upload_image_*, summer_list_projects, ...) come from the hosted Summer Engine MCP: run 'summer login --store' to use them here.";
|
|
21
|
+
export function formatHostedToolList(listing) {
|
|
22
|
+
if (listing.status === "not_signed_in")
|
|
23
|
+
return c.dim(STORE_SIGN_IN_HINT);
|
|
24
|
+
if (listing.status === "unavailable")
|
|
25
|
+
return c.dim(`Store and publishing tools: the hosted Summer Engine MCP did not answer (${listing.message}).`);
|
|
26
|
+
const local = new Set(listToolDispatches().map((entry) => `summer_${entry.slug.replace(/-/g, "_")}`));
|
|
27
|
+
const tools = listing.tools.filter((tool) => !local.has(tool.name)).sort((a, b) => a.name.localeCompare(b.name));
|
|
28
|
+
if (!tools.length)
|
|
29
|
+
return c.dim("Store and publishing tools: none listed by the hosted Summer Engine MCP.");
|
|
30
|
+
const width = Math.max(...tools.map((tool) => tool.name.length));
|
|
31
|
+
return [
|
|
32
|
+
c.bold(`Store and publishing tools (${tools.length}, hosted, with your store sign-in)`),
|
|
33
|
+
...tools.map((tool) => ` ${tool.name.padEnd(width)} ${(tool.description ?? "").split(/(?<=\.)\s/)[0].slice(0, 120)}`),
|
|
34
|
+
].join("\n");
|
|
35
|
+
}
|
|
17
36
|
/** Resolve a name through the compiled registry index when it exists —
|
|
18
37
|
* accepts full ids ("tool/add-node") and legacy aliases, returning the slug
|
|
19
38
|
* the dispatch table knows. Returns null when the index is absent or the
|
|
@@ -86,6 +105,8 @@ export const toolCommand = new Command("tool")
|
|
|
86
105
|
.action(async (name, options) => {
|
|
87
106
|
if (options.list || name === undefined) {
|
|
88
107
|
console.log(formatToolList(listToolDispatches()));
|
|
108
|
+
console.log("");
|
|
109
|
+
console.log(formatHostedToolList(await hostedCli.list()));
|
|
89
110
|
if (name === undefined && !options.list) {
|
|
90
111
|
console.log("");
|
|
91
112
|
console.log(c.dim("Pass a tool name to run one."));
|
|
@@ -94,7 +115,21 @@ export const toolCommand = new Command("tool")
|
|
|
94
115
|
}
|
|
95
116
|
const entry = resolveToolForCli(name);
|
|
96
117
|
if (!entry) {
|
|
97
|
-
|
|
118
|
+
// Not a local tool: the hosted store and publishing tools, with the store sign-in.
|
|
119
|
+
const hosted = await hostedCli.call(name, parseJsonArgs(options.args ?? options.json));
|
|
120
|
+
if (hosted.status === "called") {
|
|
121
|
+
const payload = hostedResultPayload(hosted.result);
|
|
122
|
+
console.log(payload.json ? JSON.stringify(payload.json, null, 2) : payload.text);
|
|
123
|
+
if (payload.isError)
|
|
124
|
+
process.exitCode = 1;
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const why = hosted.status === "not_signed_in"
|
|
128
|
+
? ` ${STORE_SIGN_IN_HINT}`
|
|
129
|
+
: hosted.status === "unavailable"
|
|
130
|
+
? ` The hosted Summer Engine MCP did not answer: ${hosted.message}.`
|
|
131
|
+
: "";
|
|
132
|
+
throw new ToolDispatchError(`Unknown tool "${name}". Run 'summer tool --list' to see every tool.${why}`);
|
|
98
133
|
}
|
|
99
134
|
if (options.json !== undefined && options.args === undefined) {
|
|
100
135
|
console.error("Note: 'summer tool --json <args>' is deprecated; use --args <json>.");
|
|
@@ -22,7 +22,7 @@ export type EngineSnapshot = {
|
|
|
22
22
|
/** Structured failure classifier the engine returns on a game snapshot over
|
|
23
23
|
* local HTTP (409 `bridge_required`) — surfaced verbatim so the tool can give
|
|
24
24
|
* an honest, actionable message instead of a truncated generic 409 string.
|
|
25
|
-
*
|
|
25
|
+
* Once game snapshots answer 200/202 over HTTP this simply
|
|
26
26
|
* never fires and the tool works. */
|
|
27
27
|
failureReason?: string;
|
|
28
28
|
/** Scene-preview confession fields (P4.3). Populated only for target:"scene".
|
|
@@ -194,8 +194,8 @@ export declare class EngineApiClient {
|
|
|
194
194
|
private _parseSnapshotResponse;
|
|
195
195
|
/**
|
|
196
196
|
* Turn a 409 from /api/snapshot/game into a structured failure. The engine's
|
|
197
|
-
* structural refusal carries `bridge_required` / `unsupported_transport
|
|
198
|
-
*
|
|
197
|
+
* structural refusal carries `bridge_required` / `unsupported_transport`;
|
|
198
|
+
* a 409 without that shape is surfaced as a
|
|
199
199
|
* plain error rather than silently claiming "bridge required".
|
|
200
200
|
*/
|
|
201
201
|
private _bridgeRequiredFromResponse;
|
|
@@ -246,9 +246,8 @@ export declare class EngineApiClient {
|
|
|
246
246
|
getPort(): number;
|
|
247
247
|
/**
|
|
248
248
|
* Cheap drift probe for the MCP client cache. The engine mints a fresh
|
|
249
|
-
* api-token on every launch
|
|
250
|
-
*
|
|
251
|
-
* the old socket lingers), so a client built before an engine restart holds
|
|
249
|
+
* api-token on every launch and can bind a different port (it increments
|
|
250
|
+
* 6550..6565 when the old socket lingers), so a client built before an engine restart holds
|
|
252
251
|
* dead credentials. Re-read the on-disk creds and report whether they no longer
|
|
253
252
|
* match this client's snapshot.
|
|
254
253
|
*
|
package/dist/core/api-client.js
CHANGED
|
@@ -492,8 +492,7 @@ export class EngineApiClient {
|
|
|
492
492
|
async getSceneState(scenePath, options) {
|
|
493
493
|
// depth/limit/root only take effect on targeted (scene=) reads: the engine
|
|
494
494
|
// routes those through the live command queue and forwards every query
|
|
495
|
-
// param into
|
|
496
|
-
// _parse_state_args). An UNtargeted read is answered from a pre-published
|
|
495
|
+
// param into the engine's scene-state reader. An UNtargeted read is answered from a pre-published
|
|
497
496
|
// snapshot built with the defaults (depth 2, limit 200) and its query
|
|
498
497
|
// params are ignored — callers who need depth/limit must pass scenePath
|
|
499
498
|
// (summer_get_scene_tree resolves the current scene path for this).
|
|
@@ -515,9 +514,8 @@ export class EngineApiClient {
|
|
|
515
514
|
async getProjectState(prefix) {
|
|
516
515
|
// ?prefix= is sent for forward-compatibility, but current engine builds
|
|
517
516
|
// IGNORE it: /api/state/project is always served from the snapshot, which
|
|
518
|
-
// is published with empty args
|
|
519
|
-
//
|
|
520
|
-
// query. Callers that need a prefix subset must also filter client-side
|
|
517
|
+
// is published with empty args, so the engine's project-state reader never
|
|
518
|
+
// sees the query. Callers that need a prefix subset must also filter client-side
|
|
521
519
|
// (summer_get_project_context does).
|
|
522
520
|
const query = prefix ? `?prefix=${encodeURIComponent(prefix)}` : "";
|
|
523
521
|
return this.request("GET", `/api/state/project${query}`);
|
|
@@ -542,13 +540,13 @@ export class EngineApiClient {
|
|
|
542
540
|
if (pins) {
|
|
543
541
|
// Determinism params (seed / fixed_fps / time_scale) — the /api/play rung
|
|
544
542
|
// copies ONLY `scene` from options into the PlayGame op
|
|
545
|
-
// (
|
|
543
|
+
// (the engine's /api/play handler), so a pinned launch travels as an
|
|
546
544
|
// explicit PlayGame op through /api/ops. executeOps stamps the bound
|
|
547
545
|
// identity like every other op. An engine that predates the params
|
|
548
546
|
// ignores the extra keys and answers the v1 result (no `determinism`).
|
|
549
547
|
return this.executeOps([{ op: "PlayGame", ...(scene ? { scene } : {}), ...pins }], undefined, 60_000);
|
|
550
548
|
}
|
|
551
|
-
// The engine reads play params from body.options
|
|
549
|
+
// The engine reads play params from body.options,
|
|
552
550
|
// and the play handler reads options["scene"] — a top-level { scene } is
|
|
553
551
|
// dropped, so the scene MUST be nested inside options. The bound identity
|
|
554
552
|
// rides in the same options dict so play is refused on a mismatched project.
|
|
@@ -593,10 +591,10 @@ export class EngineApiClient {
|
|
|
593
591
|
// with the same payload shape — _requestQueued resolves both.
|
|
594
592
|
//
|
|
595
593
|
// Game capture over local HTTP structurally 409s today with a STRUCTURED
|
|
596
|
-
// reason (`failure_reason:"unsupported_transport"`, `bridge_required:true
|
|
597
|
-
//
|
|
594
|
+
// reason (`failure_reason:"unsupported_transport"`, `bridge_required:true`).
|
|
595
|
+
// Detect that specific shape and return it
|
|
598
596
|
// verbatim so the tool can give an honest message — do NOT hardcode "game
|
|
599
|
-
// always fails": once the engine answers 200/202
|
|
597
|
+
// always fails": once the engine answers 200/202, the same response
|
|
600
598
|
// flows into the normal queued path. ONE request either way: a probe that
|
|
601
599
|
// discarded a 200 (or orphaned an accepted 202 requestId) and then asked
|
|
602
600
|
// again would capture the game twice.
|
|
@@ -681,8 +679,8 @@ export class EngineApiClient {
|
|
|
681
679
|
}
|
|
682
680
|
/**
|
|
683
681
|
* Turn a 409 from /api/snapshot/game into a structured failure. The engine's
|
|
684
|
-
* structural refusal carries `bridge_required` / `unsupported_transport
|
|
685
|
-
*
|
|
682
|
+
* structural refusal carries `bridge_required` / `unsupported_transport`;
|
|
683
|
+
* a 409 without that shape is surfaced as a
|
|
686
684
|
* plain error rather than silently claiming "bridge required".
|
|
687
685
|
*/
|
|
688
686
|
async _bridgeRequiredFromResponse(res) {
|
|
@@ -777,9 +775,8 @@ export class EngineApiClient {
|
|
|
777
775
|
}
|
|
778
776
|
/**
|
|
779
777
|
* Cheap drift probe for the MCP client cache. The engine mints a fresh
|
|
780
|
-
* api-token on every launch
|
|
781
|
-
*
|
|
782
|
-
* the old socket lingers), so a client built before an engine restart holds
|
|
778
|
+
* api-token on every launch and can bind a different port (it increments
|
|
779
|
+
* 6550..6565 when the old socket lingers), so a client built before an engine restart holds
|
|
783
780
|
* dead credentials. Re-read the on-disk creds and report whether they no longer
|
|
784
781
|
* match this client's snapshot.
|
|
785
782
|
*
|
package/dist/core/auth.js
CHANGED
|
@@ -161,8 +161,8 @@ export async function saveLoginSession(session) {
|
|
|
161
161
|
// those exact files. credential-metadata.json adds audience/scope information
|
|
162
162
|
// without changing or duplicating the secret.
|
|
163
163
|
// Write order: user.json, then auth-token, then the advisory metadata. The
|
|
164
|
-
// desktop engine cross-checks token.sub against user.json's id
|
|
165
|
-
//
|
|
164
|
+
// desktop engine cross-checks token.sub against user.json's id when it
|
|
165
|
+
// adopts the CLI credential, so a
|
|
166
166
|
// write interrupted between the first two files fails closed instead of
|
|
167
167
|
// adopting a mismatched identity. The metadata write is last and is NOT a
|
|
168
168
|
// gate: the token is already live by then, and its contents are re-derived
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
* Asset import into the engine-bound project (Kenney texture pairing + path
|
|
3
3
|
* inference + optional scene placement). ONE copy shared by the MCP asset tools
|
|
4
4
|
* and the CLI dispatch table.
|
|
5
|
-
* See: publicsummerengine/Docs/ASSET_IMPORT_END_TO_END.md
|
|
6
5
|
*/
|
|
7
6
|
import type { EngineApiClient } from "../api-client.js";
|
|
8
7
|
/** An asset record as returned by the Summer gateway asset APIs. */
|
|
@@ -4,7 +4,7 @@ export type CameraBookmarkAction = (typeof CAMERA_BOOKMARK_ACTIONS)[number];
|
|
|
4
4
|
export declare const CAMERA_BOOKMARK_OPS: Record<CameraBookmarkAction, string>;
|
|
5
5
|
/** What the engine_lacks_op result tells the model to do instead. */
|
|
6
6
|
export declare const CAMERA_BOOKMARK_FALLBACK = "pass the pose explicitly on every capture with summer_screenshot framing:\"free\" (camera_position + camera_look_at), or render through a Camera3D placed in the scene with framing:\"camera\"";
|
|
7
|
-
/** Bookmark name grammar (
|
|
7
|
+
/** Bookmark name grammar (same as the engine's): 1-64 of [A-Za-z0-9_-]. */
|
|
8
8
|
export declare const BOOKMARK_NAME_PATTERN: RegExp;
|
|
9
9
|
export interface CameraBookmarkArgs {
|
|
10
10
|
action: CameraBookmarkAction;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* and the CLI dispatcher so both faces validate the same way and send the same
|
|
5
5
|
* op.
|
|
6
6
|
*
|
|
7
|
-
* Engine contract
|
|
7
|
+
* Engine contract:
|
|
8
8
|
* SaveCameraBookmark { name, position?, look_at?, fov? } -> pose_source
|
|
9
9
|
* ListCameraBookmarks {} -> names, bookmarks
|
|
10
10
|
* DeleteCameraBookmark { name } -> remaining
|
|
@@ -25,7 +25,7 @@ export const CAMERA_BOOKMARK_OPS = {
|
|
|
25
25
|
};
|
|
26
26
|
/** What the engine_lacks_op result tells the model to do instead. */
|
|
27
27
|
export const CAMERA_BOOKMARK_FALLBACK = "pass the pose explicitly on every capture with summer_screenshot framing:\"free\" (camera_position + camera_look_at), or render through a Camera3D placed in the scene with framing:\"camera\"";
|
|
28
|
-
/** Bookmark name grammar (
|
|
28
|
+
/** Bookmark name grammar (same as the engine's): 1-64 of [A-Za-z0-9_-]. */
|
|
29
29
|
export const BOOKMARK_NAME_PATTERN = /^[A-Za-z0-9_-]{1,64}$/;
|
|
30
30
|
function requireBookmarkName(name, action) {
|
|
31
31
|
const trimmed = name?.trim() ?? "";
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { type EngineRun } from "./engine-run.js";
|
|
2
|
+
/**
|
|
3
|
+
* summer_capture_gameplay: real gameplay frames without a running editor.
|
|
4
|
+
*
|
|
5
|
+
* Reuses the engine's offscreen verify instance (the one RunVerification and
|
|
6
|
+
* tests/autopilot spawn): a real renderer in a window parked offscreen with no
|
|
7
|
+
* focus, so it never shows on screen, unlike --headless, which has no pixels.
|
|
8
|
+
*
|
|
9
|
+
* <engine> --disable-crash-handler --summer-no-api --path <project> --resolution WxH
|
|
10
|
+
* [--scene res://...] --summer-verify <probe.gd>
|
|
11
|
+
* --summer-verify-out <dir> --summer-verify-max <s>
|
|
12
|
+
*
|
|
13
|
+
* The stock probe waits for the scene to draw and settle, saves PNG frames of
|
|
14
|
+
* the game viewport, and writes results.json. The frames are what the game
|
|
15
|
+
* really draws, HUD included: use them as store screenshots.
|
|
16
|
+
*/
|
|
17
|
+
export interface CaptureGameplayInput {
|
|
18
|
+
/** Project root (has project.godot). Defaults to the MCP's --project, then the working directory. */
|
|
19
|
+
project?: string;
|
|
20
|
+
/** Scene to start (res:// or uid://). Default: the project's main scene. */
|
|
21
|
+
scene?: string;
|
|
22
|
+
/** Window size, WIDTHxHEIGHT. Default 1920x1080; 1080x1920 for portrait. */
|
|
23
|
+
resolution?: string;
|
|
24
|
+
/** Frames to save. Default 1. */
|
|
25
|
+
frames?: number;
|
|
26
|
+
/** Seconds to let the game run before the first frame. Default 3. */
|
|
27
|
+
waitSeconds?: number;
|
|
28
|
+
/** Seconds between frames. Default 1. */
|
|
29
|
+
intervalSeconds?: number;
|
|
30
|
+
/** Output folder. Default <project>/.summer/captures/<time>/. */
|
|
31
|
+
out?: string;
|
|
32
|
+
}
|
|
33
|
+
export interface CapturedFrame {
|
|
34
|
+
path: string;
|
|
35
|
+
width: number;
|
|
36
|
+
height: number;
|
|
37
|
+
}
|
|
38
|
+
export interface CaptureGameplayResult {
|
|
39
|
+
ok: true;
|
|
40
|
+
project: string;
|
|
41
|
+
scene: string;
|
|
42
|
+
resolution: string;
|
|
43
|
+
frames: CapturedFrame[];
|
|
44
|
+
out: string;
|
|
45
|
+
engine: string;
|
|
46
|
+
imported: boolean;
|
|
47
|
+
durationMs: number;
|
|
48
|
+
warnings?: string[];
|
|
49
|
+
next: string;
|
|
50
|
+
}
|
|
51
|
+
export interface CaptureGameplayDependencies {
|
|
52
|
+
findBinary: () => string | null;
|
|
53
|
+
run: (binary: string, args: string[], timeoutMs: number) => Promise<EngineRun>;
|
|
54
|
+
now: () => Date;
|
|
55
|
+
}
|
|
56
|
+
/** Width and height from a PNG's IHDR chunk, or null when the file is not a PNG. */
|
|
57
|
+
export declare function pngSize(bytes: Buffer): {
|
|
58
|
+
width: number;
|
|
59
|
+
height: number;
|
|
60
|
+
} | null;
|
|
61
|
+
/**
|
|
62
|
+
* The stock probe. Self-contained (extends Node, no base class to copy into the
|
|
63
|
+
* project); follows the verify-instance contract of assets/autopilot/probe_base.gd:
|
|
64
|
+
* the engine sets summer_out_dir and summer_max_seconds before _ready(), the
|
|
65
|
+
* first frames are empty until the scene has drawn twice, results.json is
|
|
66
|
+
* always written.
|
|
67
|
+
*/
|
|
68
|
+
export declare function captureProbeSource(frames: number, waitSeconds: number, intervalSeconds: number): string;
|
|
69
|
+
export declare function captureGameplay(input: CaptureGameplayInput, overrides?: Partial<CaptureGameplayDependencies>): Promise<CaptureGameplayResult>;
|