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
|
@@ -12,8 +12,7 @@ import { BuildToolError, readSummerBundle } from "./summer-bundle.js";
|
|
|
12
12
|
/**
|
|
13
13
|
* summer_publish_build: upload a summer.games export to the creator's game
|
|
14
14
|
* through the same creator store routes Studio's export upload uses
|
|
15
|
-
* (
|
|
16
|
-
* /v1/management/*, build-publications, ADR 0033):
|
|
15
|
+
* (/api/creator-store/*, build-publications):
|
|
17
16
|
*
|
|
18
17
|
* POST games/{g}/build-publications declare the export (idempotent)
|
|
19
18
|
* POST .../{p}:source-upload open the part plan (64 MiB parts)
|
|
@@ -24,8 +23,7 @@ import { BuildToolError, readSummerBundle } from "./summer-bundle.js";
|
|
|
24
23
|
* POST games/{g}/builds/{b}/client-packages name the Build's client pack
|
|
25
24
|
* POST .../{p}:publish only with publish=true
|
|
26
25
|
*
|
|
27
|
-
* Mirrors
|
|
28
|
-
* (uploadExportedGame), including its idempotency keys, so a retry continues
|
|
26
|
+
* Mirrors Studio's export upload, including its idempotency keys, so a retry continues
|
|
29
27
|
* the same publication instead of creating another one.
|
|
30
28
|
*
|
|
31
29
|
* Auth: the Summer store OAuth token from "summer login --store" (audience
|
|
@@ -38,11 +36,11 @@ const CONCURRENCY = 3;
|
|
|
38
36
|
const PART_RETRIES = 3;
|
|
39
37
|
const DEFAULT_WAIT_SECONDS = 600;
|
|
40
38
|
const POLL_MS = 3_000;
|
|
41
|
-
/**
|
|
39
|
+
/** Store client versions: vMAJOR.MINOR.PATCH[-rN]. */
|
|
42
40
|
export const CLIENT_VERSION = /^v(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(-r[1-9]\d*)?$/;
|
|
43
41
|
const INTAKE_DONE = ["preview_ready", "published", "ready", "succeeded"];
|
|
44
42
|
const NOT_ACTIONABLE = "deployment_not_actionable";
|
|
45
|
-
/** Games without a server run on the Summer Games phone apps only (
|
|
43
|
+
/** Games without a server run on the Summer Games phone apps only (the store's standalone targets). */
|
|
46
44
|
const STANDALONE_TARGETS = ["ios", "android"];
|
|
47
45
|
/** Why the Platform did not take the export, in plain words (same text Studio shows). */
|
|
48
46
|
const INTAKE_FAILURES = {
|
|
@@ -61,9 +59,11 @@ export const defaultDependencies = {
|
|
|
61
59
|
now: Date.now,
|
|
62
60
|
token: () => getStoreAccessToken(),
|
|
63
61
|
};
|
|
64
|
-
export function storeError(status, code, message) {
|
|
62
|
+
export function storeError(status, code, message, requestId) {
|
|
65
63
|
if (status === 401) {
|
|
66
|
-
|
|
64
|
+
// The token was sent and refused: signing in again gives the same token
|
|
65
|
+
// shape and the same answer, so it is not the first thing to try.
|
|
66
|
+
return new BuildToolError("store_auth_refused", `The Summer store did not accept this sign-in${message ? `: ${message.replace(/\.$/, "")}` : ""}.`, 'Recovery: run "summer doctor" (Store line) to see the store\'s answer. Signing in again does not change a refusal of a valid sign-in. Until the store accepts agent sign-in for this account, upload the .zip in Studio (Store > your game > Exports).', status, requestId ? { requestId } : undefined);
|
|
67
67
|
}
|
|
68
68
|
if (status === 403 && code === "owner_approval_required") {
|
|
69
69
|
return new BuildToolError("owner_approval_required", message || "Only the game's owner can do this.", "Recovery: nothing went live. Submit with summer_store_submit and give the owner the approval link it returns; a live game's new download is finished by the owner in Studio.", status);
|
|
@@ -104,7 +104,8 @@ export function createStore(baseUrl, token, deps) {
|
|
|
104
104
|
const body = (json && typeof json === "object" ? json : {});
|
|
105
105
|
if (!response.ok) {
|
|
106
106
|
const error = body.error && typeof body.error === "object" ? body.error : {};
|
|
107
|
-
|
|
107
|
+
const requestId = [error.requestId, body.requestId, response.headers.get("x-request-id")].find((value) => typeof value === "string" && value);
|
|
108
|
+
throw storeError(response.status, typeof error.code === "string" ? error.code : `http_${response.status}`, typeof error.message === "string" ? error.message : undefined, requestId);
|
|
108
109
|
}
|
|
109
110
|
return body;
|
|
110
111
|
},
|
|
@@ -260,18 +261,68 @@ function targetPlatforms(bundle) {
|
|
|
260
261
|
// The Build declares exactly what the bundle declares (declaration_mismatch otherwise).
|
|
261
262
|
return bundle.targetPlatforms;
|
|
262
263
|
}
|
|
263
|
-
/**
|
|
264
|
-
async function
|
|
265
|
-
let games;
|
|
264
|
+
/** The signed-in person's store games, or why the store did not list them. */
|
|
265
|
+
async function listGames(deps) {
|
|
266
266
|
try {
|
|
267
|
-
const store = createStore(await resolveGatewayUrl(), await deps
|
|
267
|
+
const store = createStore(await resolveGatewayUrl(), await storeToken(deps), deps);
|
|
268
268
|
const page = await store.call("GET", "games");
|
|
269
|
-
games
|
|
269
|
+
return { games: (page.items ?? []).map((game) => ({ id: game.id, name: game.name, slug: game.slug, status: game.status, targets: game.supportedPlatforms ?? [] })) };
|
|
270
270
|
}
|
|
271
|
-
catch {
|
|
272
|
-
|
|
271
|
+
catch (error) {
|
|
272
|
+
return { error: error instanceof Error ? error.message : String(error) };
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
/** gameId is required: the error carries the person's games, or why the store did not list them. */
|
|
276
|
+
async function listGamesOrThrow(deps) {
|
|
277
|
+
const listed = await listGames(deps);
|
|
278
|
+
if ("games" in listed) {
|
|
279
|
+
throw new BuildToolError("game_required", listed.games.length
|
|
280
|
+
? "gameId is required: pick one of your store games below (the export is uploaded to one existing game)."
|
|
281
|
+
: "gameId is required, and this account has no store game yet.", listed.games.length
|
|
282
|
+
? "Recovery: call again with gameId from the list."
|
|
283
|
+
: "Recovery: create the store game first (summer_store_create_game), then call again with its gameId.", undefined, { games: listed.games });
|
|
284
|
+
}
|
|
285
|
+
throw new BuildToolError("game_required", `gameId is required, and the store did not list your games: ${listed.error}`, "Recovery: copy the game id from Studio (the store page URL) and retry.", undefined, { listError: listed.error });
|
|
286
|
+
}
|
|
287
|
+
async function storeToken(deps) {
|
|
288
|
+
try {
|
|
289
|
+
return await deps.token();
|
|
290
|
+
}
|
|
291
|
+
catch (error) {
|
|
292
|
+
if (error instanceof OAuthError)
|
|
293
|
+
throw new BuildToolError(error.code, error.message.replace(` ${error.recovery}`, ""), error.recovery);
|
|
294
|
+
throw error;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Before the person confirms, prove the target is real: the game exists for
|
|
299
|
+
* this account, and its store page lists the platforms the export targets.
|
|
300
|
+
*/
|
|
301
|
+
export async function checkStoreGame(gameId, exportTargets, deps) {
|
|
302
|
+
const store = createStore(await resolveGatewayUrl(), await storeToken(deps), deps);
|
|
303
|
+
let game;
|
|
304
|
+
try {
|
|
305
|
+
game = await store.call("GET", `games/${seg(gameId)}`);
|
|
306
|
+
}
|
|
307
|
+
catch (error) {
|
|
308
|
+
if (error instanceof BuildToolError && error.status === 404) {
|
|
309
|
+
const listed = await listGames(deps);
|
|
310
|
+
throw new BuildToolError("game_not_found", "games" in listed
|
|
311
|
+
? `There is no store game "${gameId}" for this account, so nothing can be uploaded to it.`
|
|
312
|
+
: `The store did not find game "${gameId}", and did not list your games either: ${listed.error}`, "games" in listed && listed.games.length
|
|
313
|
+
? "Recovery: call again with gameId from the list."
|
|
314
|
+
: "Recovery: create the store game first (summer_store_create_game), or copy its id from Studio (the store page URL).", 404, "games" in listed ? { games: listed.games } : undefined);
|
|
315
|
+
}
|
|
316
|
+
throw error;
|
|
273
317
|
}
|
|
274
|
-
|
|
318
|
+
const targets = Array.isArray(game.supportedPlatforms) ? game.supportedPlatforms.filter((value) => typeof value === "string") : [];
|
|
319
|
+
// The store page speaks catalog names (ios, android, macos, windows, linux, web) or store ids (macos-universal, ...).
|
|
320
|
+
const catalog = new Set(targets.map((target) => target.replace(/-(universal|x64)$/, "")));
|
|
321
|
+
const unlisted = exportTargets.filter((target) => !catalog.has(target));
|
|
322
|
+
const warnings = unlisted.length
|
|
323
|
+
? [`The store page of "${game.name ?? gameId}" does not list ${unlisted.join(", ")} (it lists ${targets.join(", ") || "no platforms"}). Players on ${unlisted.join(", ")} will not see this build until the store page lists them: add them with summer_store_update_listing.`]
|
|
324
|
+
: [];
|
|
325
|
+
return { game: { gameId, name: typeof game.name === "string" ? game.name : null, status: typeof game.status === "string" ? game.status : null, targets }, warnings };
|
|
275
326
|
}
|
|
276
327
|
export async function publishBuild(input, overrides = {}) {
|
|
277
328
|
const deps = { ...defaultDependencies, ...overrides };
|
|
@@ -288,7 +339,11 @@ export async function publishBuild(input, overrides = {}) {
|
|
|
288
339
|
const clientVersion = normalizeClientVersion(input.clientVersion);
|
|
289
340
|
if (!gameId)
|
|
290
341
|
return listGamesOrThrow(deps);
|
|
291
|
-
|
|
342
|
+
const download = { gameId, file, platform, clientVersion, confirm: input.confirm, waitSeconds: input.waitSeconds, face: input.face };
|
|
343
|
+
if (input.confirm === true)
|
|
344
|
+
return publishDownload(download, deps);
|
|
345
|
+
const preview = await publishDownload(download, deps);
|
|
346
|
+
return { ...preview, game: (await checkStoreGame(gameId, [], deps)).game };
|
|
292
347
|
}
|
|
293
348
|
if (extname(file).toLowerCase() !== ".zip") {
|
|
294
349
|
throw new BuildToolError("export_format_unsupported", `${file} is not a summer.games .zip export.`, "Recovery: export with summer_export_game and upload that .zip.");
|
|
@@ -313,23 +368,18 @@ export async function publishBuild(input, overrides = {}) {
|
|
|
313
368
|
if (!gameId)
|
|
314
369
|
return listGamesOrThrow(deps);
|
|
315
370
|
if (input.confirm !== true) {
|
|
371
|
+
const checked = await checkStoreGame(gameId, platforms, deps);
|
|
316
372
|
return {
|
|
317
373
|
ok: true,
|
|
318
374
|
status: "confirmation_required",
|
|
319
375
|
target,
|
|
320
|
-
|
|
376
|
+
game: checked.game,
|
|
377
|
+
...(checked.warnings.length ? { warnings: checked.warnings } : {}),
|
|
378
|
+
next: `Show the user this exact game (name and id), file, digest, size, version and publish choice. Only after they approve, call again with confirm=true. Nothing was uploaded.`,
|
|
321
379
|
};
|
|
322
380
|
}
|
|
323
381
|
const audit = { at: new Date(deps.now()).toISOString(), operation: "publish_build", face: input.face, ...target };
|
|
324
|
-
|
|
325
|
-
try {
|
|
326
|
-
token = await deps.token();
|
|
327
|
-
}
|
|
328
|
-
catch (error) {
|
|
329
|
-
if (error instanceof OAuthError)
|
|
330
|
-
throw new BuildToolError(error.code, error.message.replace(` ${error.recovery}`, ""), error.recovery);
|
|
331
|
-
throw error;
|
|
332
|
-
}
|
|
382
|
+
const token = await storeToken(deps);
|
|
333
383
|
const store = createStore(await resolveGatewayUrl(), token, deps);
|
|
334
384
|
await appendStoreJsonLine("creator-audit.jsonl", { ...audit, outcome: "started" });
|
|
335
385
|
// Same keys Studio derives: the same bytes, version and scene are one declaration.
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { type PublishBuildDependencies } from "./publish-build.js";
|
|
2
2
|
/**
|
|
3
|
-
* The store's second build path (
|
|
4
|
-
* internal/creatorstore): a web build (an HTML5 .zip played on summer.games)
|
|
3
|
+
* The store's second build path (store versions): a web build (an HTML5 .zip played on summer.games)
|
|
5
4
|
* or a native download (macOS universal, Windows x64, Linux x64) that players
|
|
6
5
|
* download. summer_export_game format "download" makes these files;
|
|
7
6
|
* summer_publish_build uploads them here, through the same creator store
|
|
@@ -7,8 +7,7 @@ import { readZipEntries } from "../util/zip.js";
|
|
|
7
7
|
import { BuildToolError } from "./summer-bundle.js";
|
|
8
8
|
import { createStore, readGrants, uploadParts } from "./publish-build.js";
|
|
9
9
|
/**
|
|
10
|
-
* The store's second build path (
|
|
11
|
-
* internal/creatorstore): a web build (an HTML5 .zip played on summer.games)
|
|
10
|
+
* The store's second build path (store versions): a web build (an HTML5 .zip played on summer.games)
|
|
12
11
|
* or a native download (macOS universal, Windows x64, Linux x64) that players
|
|
13
12
|
* download. summer_export_game format "download" makes these files;
|
|
14
13
|
* summer_publish_build uploads them here, through the same creator store
|
|
@@ -25,7 +24,7 @@ import { createStore, readGrants, uploadParts } from "./publish-build.js";
|
|
|
25
24
|
* already live the store refuses an agent's :complete (the owner finishes it).
|
|
26
25
|
*/
|
|
27
26
|
export const DOWNLOAD_PLATFORMS = ["web", "macos-universal", "windows-x64", "linux-x64"];
|
|
28
|
-
/**
|
|
27
|
+
/** The store's upload limits for store versions and web zips. */
|
|
29
28
|
const WEB_MAX_BYTES = 500 * 1024 * 1024;
|
|
30
29
|
const WEB_MAX_FILES = 2000;
|
|
31
30
|
const WEB_MAX_FILE_BYTES = 200 * 1024 * 1024;
|
|
@@ -3,9 +3,7 @@
|
|
|
3
3
|
* (src/mcp/tools/scene-tools.ts and tool-dispatch.ts), built from ops whose
|
|
4
4
|
* results persist, and verified against the SAVED scene file.
|
|
5
5
|
*
|
|
6
|
-
* Why not the engine's ReplaceNode op for scenes:
|
|
7
|
-
* (engine modules/1summer_engine/editor/ops/scene_ops.cpp, scene branch and
|
|
8
|
-
* the async _finish_replace_node) instantiates the new PackedScene and hands
|
|
6
|
+
* Why not the engine's ReplaceNode op for scenes: for a scene it instantiates the new PackedScene and hands
|
|
9
7
|
* it to SceneTreeDock::replace_node — the editor's "Change Type" path — which
|
|
10
8
|
* ends in Node::replace_by (scene/main/node.cpp). replace_by finishes with
|
|
11
9
|
* `p_node->set_scene_file_path(get_scene_file_path())`: the new instance is
|
|
@@ -3,9 +3,7 @@
|
|
|
3
3
|
* (src/mcp/tools/scene-tools.ts and tool-dispatch.ts), built from ops whose
|
|
4
4
|
* results persist, and verified against the SAVED scene file.
|
|
5
5
|
*
|
|
6
|
-
* Why not the engine's ReplaceNode op for scenes:
|
|
7
|
-
* (engine modules/1summer_engine/editor/ops/scene_ops.cpp, scene branch and
|
|
8
|
-
* the async _finish_replace_node) instantiates the new PackedScene and hands
|
|
6
|
+
* Why not the engine's ReplaceNode op for scenes: for a scene it instantiates the new PackedScene and hands
|
|
9
7
|
* it to SceneTreeDock::replace_node — the editor's "Change Type" path — which
|
|
10
8
|
* ends in Node::replace_by (scene/main/node.cpp). replace_by finishes with
|
|
11
9
|
* `p_node->set_scene_file_path(get_scene_file_path())`: the new instance is
|
|
@@ -6,8 +6,7 @@
|
|
|
6
6
|
* both faces validate the same inputs, send the same op and wait the same
|
|
7
7
|
* budget.
|
|
8
8
|
*
|
|
9
|
-
* Engine contract (frozen):
|
|
10
|
-
* Runtime control & playtest ops" + editor/ops/runtime_ops.h. Every op except
|
|
9
|
+
* Engine contract (frozen): the runtime control and playtest ops. Every op except
|
|
11
10
|
* ListGameInstances is SINGLE-ONLY and ASYNC (a debugger round-trip needs the
|
|
12
11
|
* reply channel), requires a RUNNING game, accepts `instance?` (default
|
|
13
12
|
* "main"), stamps the game frame it describes, rounds floats to 3dp and
|
|
@@ -499,9 +498,8 @@ export declare function playRequestsLocalPlay(args: PlayGameArgs): boolean;
|
|
|
499
498
|
/**
|
|
500
499
|
* Quiet is the default whenever an agent drives play — both faces of this tool
|
|
501
500
|
* (MCP and `summer tool`) ARE agent faces, so the only way to a focus-stealing
|
|
502
|
-
* launch is an explicit focus:true. Quiet travels as PlayGame `agent:true
|
|
503
|
-
*
|
|
504
|
-
* has honoured since 0.5.45 (c7c490d84f3, 2026-07-02).
|
|
501
|
+
* launch is an explicit focus:true. Quiet travels as PlayGame `agent:true`,
|
|
502
|
+
* which the engine has honoured since 0.5.45.
|
|
505
503
|
*/
|
|
506
504
|
export declare function playIsQuiet(args: PlayGameArgs): boolean;
|
|
507
505
|
/** True when the call needs the PlayGame OP (instance-aware / determinism
|
|
@@ -529,8 +527,8 @@ export declare function withLocalPlayEcho(result: unknown, args: PlayGameArgs):
|
|
|
529
527
|
export declare const PLAY_QUIET_NOT_SUPPORTED = "This Summer Engine build did not echo `agent_quiet` in its PlayGame result \u2014 it predates quiet play and has most likely switched the editor to the Game tab and taken focus. Update Summer Engine (restart it after updating) for launches that leave the user's screen alone.";
|
|
530
528
|
/**
|
|
531
529
|
* Quiet was requested: the engine echoes `agent_quiet` when it understood the
|
|
532
|
-
* flag (
|
|
533
|
-
*
|
|
530
|
+
* flag (in the launch branch AND the already-running branch on current
|
|
531
|
+
* engines). No echo at all means an engine that predates
|
|
534
532
|
* the flag ignored it — say so instead of letting the model believe the user
|
|
535
533
|
* was left alone. The field is the contract; the `note` text is never matched.
|
|
536
534
|
*/
|
|
@@ -6,8 +6,7 @@
|
|
|
6
6
|
* both faces validate the same inputs, send the same op and wait the same
|
|
7
7
|
* budget.
|
|
8
8
|
*
|
|
9
|
-
* Engine contract (frozen):
|
|
10
|
-
* Runtime control & playtest ops" + editor/ops/runtime_ops.h. Every op except
|
|
9
|
+
* Engine contract (frozen): the runtime control and playtest ops. Every op except
|
|
11
10
|
* ListGameInstances is SINGLE-ONLY and ASYNC (a debugger round-trip needs the
|
|
12
11
|
* reply channel), requires a RUNNING game, accepts `instance?` (default
|
|
13
12
|
* "main"), stamps the game frame it describes, rounds floats to 3dp and
|
|
@@ -59,7 +58,7 @@ export const RUNTIME_CONTROL_OP_KINDS = [
|
|
|
59
58
|
"ListGameInstances",
|
|
60
59
|
];
|
|
61
60
|
// ---------------------------------------------------------------------------
|
|
62
|
-
// Budgets — mirror the engine's watchdogs
|
|
61
|
+
// Budgets — mirror the engine's runtime-op watchdogs plus relay headroom.
|
|
63
62
|
// ---------------------------------------------------------------------------
|
|
64
63
|
/** Default editor-side watchdog for a runtime op (_RT_DEFAULT_TIMEOUT_SEC). */
|
|
65
64
|
export const RUNTIME_WATCHDOG_DEFAULT_SEC = 10;
|
|
@@ -882,9 +881,8 @@ export function playRequestsLocalPlay(args) {
|
|
|
882
881
|
/**
|
|
883
882
|
* Quiet is the default whenever an agent drives play — both faces of this tool
|
|
884
883
|
* (MCP and `summer tool`) ARE agent faces, so the only way to a focus-stealing
|
|
885
|
-
* launch is an explicit focus:true. Quiet travels as PlayGame `agent:true
|
|
886
|
-
*
|
|
887
|
-
* has honoured since 0.5.45 (c7c490d84f3, 2026-07-02).
|
|
884
|
+
* launch is an explicit focus:true. Quiet travels as PlayGame `agent:true`,
|
|
885
|
+
* which the engine has honoured since 0.5.45.
|
|
888
886
|
*/
|
|
889
887
|
export function playIsQuiet(args) {
|
|
890
888
|
return args.focus !== true;
|
|
@@ -894,7 +892,7 @@ export function playIsQuiet(args) {
|
|
|
894
892
|
export function playNeedsOp(args) {
|
|
895
893
|
return (
|
|
896
894
|
// The /api/play rung builds a PlayGame op with ONLY `scene`
|
|
897
|
-
// (
|
|
895
|
+
// (the engine's /api/play handler), so `agent:true` has to ride the op.
|
|
898
896
|
playIsQuiet(args) ||
|
|
899
897
|
(typeof args.instance === "string" && args.instance.trim().length > 0) ||
|
|
900
898
|
args.mode !== undefined ||
|
|
@@ -1031,8 +1029,8 @@ export function withLocalPlayEcho(result, args) {
|
|
|
1031
1029
|
export const PLAY_QUIET_NOT_SUPPORTED = "This Summer Engine build did not echo `agent_quiet` in its PlayGame result — it predates quiet play and has most likely switched the editor to the Game tab and taken focus. Update Summer Engine (restart it after updating) for launches that leave the user's screen alone.";
|
|
1032
1030
|
/**
|
|
1033
1031
|
* Quiet was requested: the engine echoes `agent_quiet` when it understood the
|
|
1034
|
-
* flag (
|
|
1035
|
-
*
|
|
1032
|
+
* flag (in the launch branch AND the already-running branch on current
|
|
1033
|
+
* engines). No echo at all means an engine that predates
|
|
1036
1034
|
* the flag ignored it — say so instead of letting the model believe the user
|
|
1037
1035
|
* was left alone. The field is the contract; the `note` text is never matched.
|
|
1038
1036
|
*/
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* re-owning step every MCP path that sends ReparentNode shares.
|
|
5
5
|
*
|
|
6
6
|
* Two engine ops answer ok for changes SaveScene then leaves out of the file
|
|
7
|
-
* (engine
|
|
7
|
+
* (engine 0.6.0):
|
|
8
8
|
*
|
|
9
9
|
* - ReparentNode (SceneOps::reparent_node) re-owns only the node it moves
|
|
10
10
|
* (`add_do_method(node, "set_owner", root)`). The remove_child before it
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* re-owning step every MCP path that sends ReparentNode shares.
|
|
5
5
|
*
|
|
6
6
|
* Two engine ops answer ok for changes SaveScene then leaves out of the file
|
|
7
|
-
* (engine
|
|
7
|
+
* (engine 0.6.0):
|
|
8
8
|
*
|
|
9
9
|
* - ReparentNode (SceneOps::reparent_node) re-owns only the node it moves
|
|
10
10
|
* (`add_do_method(node, "set_owner", root)`). The remove_child before it
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Is a scene 2D or 3D? Decided from a scene-tree read, the way the engine's
|
|
3
|
-
* ScenePreview decides it
|
|
3
|
+
* ScenePreview decides it:
|
|
4
4
|
* any Node3D anywhere in the tree makes the scene 3D; otherwise any CanvasItem
|
|
5
5
|
* makes it 2D; a tree of plain Nodes is neither.
|
|
6
6
|
*
|
|
@@ -4,10 +4,9 @@
|
|
|
4
4
|
* trusting the engine receipt (summer_replace_node, summer_batch with
|
|
5
5
|
* ReparentNode, summer_connect_signal).
|
|
6
6
|
*
|
|
7
|
-
* The engine's `scenePersistence.persisted` only says SaveScene returned OK
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* it. The client renames that flag to `saved` (engine-receipt.ts
|
|
7
|
+
* The engine's `scenePersistence.persisted` only says SaveScene returned OK;
|
|
8
|
+
* what the file holds is only known by reading it. The client renames that
|
|
9
|
+
* flag to `saved` (engine-receipt.ts
|
|
11
10
|
* honestSceneReceipt); `verified` is set only by tools that read back here.
|
|
12
11
|
*/
|
|
13
12
|
import { type JsonRecord } from "../util/json.js";
|
|
@@ -4,10 +4,9 @@
|
|
|
4
4
|
* trusting the engine receipt (summer_replace_node, summer_batch with
|
|
5
5
|
* ReparentNode, summer_connect_signal).
|
|
6
6
|
*
|
|
7
|
-
* The engine's `scenePersistence.persisted` only says SaveScene returned OK
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* it. The client renames that flag to `saved` (engine-receipt.ts
|
|
7
|
+
* The engine's `scenePersistence.persisted` only says SaveScene returned OK;
|
|
8
|
+
* what the file holds is only known by reading it. The client renames that
|
|
9
|
+
* flag to `saved` (engine-receipt.ts
|
|
11
10
|
* honestSceneReceipt); `verified` is set only by tools that read back here.
|
|
12
11
|
*/
|
|
13
12
|
import { asRecord } from "../util/json.js";
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Server-side clamps: RunSceneScript blocks between frames of the LIVE editor,
|
|
7
7
|
* so its ceiling is deliberately low; RunEditorScript boots a whole headless
|
|
8
|
-
* child editor, so its floor covers the boot cost (
|
|
9
|
-
*
|
|
8
|
+
* child editor, so its floor covers the boot cost (engine clamp: 15..600,
|
|
9
|
+
* default 120).
|
|
10
10
|
*/
|
|
11
11
|
export declare const SCENE_SCRIPT_MIN_SECONDS = 5;
|
|
12
12
|
export declare const SCENE_SCRIPT_MAX_SECONDS = 120;
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Server-side clamps: RunSceneScript blocks between frames of the LIVE editor,
|
|
7
7
|
* so its ceiling is deliberately low; RunEditorScript boots a whole headless
|
|
8
|
-
* child editor, so its floor covers the boot cost (
|
|
9
|
-
*
|
|
8
|
+
* child editor, so its floor covers the boot cost (engine clamp: 15..600,
|
|
9
|
+
* default 120).
|
|
10
10
|
*/
|
|
11
11
|
export const SCENE_SCRIPT_MIN_SECONDS = 5;
|
|
12
12
|
export const SCENE_SCRIPT_MAX_SECONDS = 120;
|
|
@@ -2,7 +2,7 @@ export declare const SHOTS_DIR: string;
|
|
|
2
2
|
export declare const SAVED_SUBDIR = "saved";
|
|
3
3
|
export declare const SHOT_MAX_EDGE = 1024;
|
|
4
4
|
export declare const SHOTS_MAX_TOTAL_BYTES: number;
|
|
5
|
-
/** Same grammar as camera bookmark names
|
|
5
|
+
/** Same grammar as camera bookmark names. */
|
|
6
6
|
export declare const SHOT_NAME_PATTERN: RegExp;
|
|
7
7
|
export declare class ShotStoreError extends Error {
|
|
8
8
|
readonly reason: "bad_name" | "not_jpeg" | "too_large" | "over_cap" | "unsafe_path" | "no_project";
|
|
@@ -22,7 +22,7 @@ export const SHOTS_DIR = join(".summer", "shots");
|
|
|
22
22
|
export const SAVED_SUBDIR = "saved";
|
|
23
23
|
export const SHOT_MAX_EDGE = 1024;
|
|
24
24
|
export const SHOTS_MAX_TOTAL_BYTES = 20 * 1024 * 1024;
|
|
25
|
-
/** Same grammar as camera bookmark names
|
|
25
|
+
/** Same grammar as camera bookmark names. */
|
|
26
26
|
export const SHOT_NAME_PATTERN = /^[A-Za-z0-9_-]{1,64}$/;
|
|
27
27
|
export class ShotStoreError extends Error {
|
|
28
28
|
reason;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The summer.games export
|
|
2
|
+
* The summer.games export: one .zip with
|
|
3
3
|
* summer-bundle.json, client.pck, and for a game with a host server.pck plus
|
|
4
4
|
* config/. This reads what the build upload declares; the Platform verifies
|
|
5
|
-
* the uploaded bytes again. Same rules as Studio's browser check
|
|
6
|
-
* (publicsummerengine src/lib/creator-store/pck-check.ts, checkBundle).
|
|
5
|
+
* the uploaded bytes again. Same rules as Studio's browser check.
|
|
7
6
|
*/
|
|
8
7
|
export declare const BUNDLE_SCHEMA = "summer.bundle.v1";
|
|
9
8
|
export declare const BUNDLE_MANIFEST = "summer-bundle.json";
|
|
@@ -2,11 +2,10 @@ import { createHash } from "node:crypto";
|
|
|
2
2
|
import { createReadStream } from "node:fs";
|
|
3
3
|
import { readZipEntries, readZipEntry, ZipReadError } from "../util/zip.js";
|
|
4
4
|
/**
|
|
5
|
-
* The summer.games export
|
|
5
|
+
* The summer.games export: one .zip with
|
|
6
6
|
* summer-bundle.json, client.pck, and for a game with a host server.pck plus
|
|
7
7
|
* config/. This reads what the build upload declares; the Platform verifies
|
|
8
|
-
* the uploaded bytes again. Same rules as Studio's browser check
|
|
9
|
-
* (publicsummerengine src/lib/creator-store/pck-check.ts, checkBundle).
|
|
8
|
+
* the uploaded bytes again. Same rules as Studio's browser check.
|
|
10
9
|
*/
|
|
11
10
|
export const BUNDLE_SCHEMA = "summer.bundle.v1";
|
|
12
11
|
export const BUNDLE_MANIFEST = "summer-bundle.json";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* surface-snap — ONE implementation of `summer_snap_to_surface` for both faces
|
|
3
3
|
* (src/mcp/tools/spatial-tools.ts and tool-dispatch.ts), around the engine's
|
|
4
|
-
* SnapToSurface op
|
|
4
|
+
* SnapToSurface op.
|
|
5
5
|
*
|
|
6
6
|
* Two gaps in the engine op, closed here with ops main already ships:
|
|
7
7
|
*
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* surface-snap — ONE implementation of `summer_snap_to_surface` for both faces
|
|
3
3
|
* (src/mcp/tools/spatial-tools.ts and tool-dispatch.ts), around the engine's
|
|
4
|
-
* SnapToSurface op
|
|
4
|
+
* SnapToSurface op.
|
|
5
5
|
*
|
|
6
6
|
* Two gaps in the engine op, closed here with ops main already ships:
|
|
7
7
|
*
|
|
@@ -49,6 +49,7 @@ import { shapeEngineLogResponse } from "../log-filters.js";
|
|
|
49
49
|
import { listCreatorReleases, publishCreator, } from "./creator.js";
|
|
50
50
|
import { exportGame } from "./export-game.js";
|
|
51
51
|
import { exportTemplates } from "./export-templates.js";
|
|
52
|
+
import { captureGameplay } from "./capture-gameplay.js";
|
|
52
53
|
import { publishBuild } from "./publish-build.js";
|
|
53
54
|
import { CONFIG_KEYS, getConfigValue, isConfigKey, readSummerConfig, resolveGatewayUrl, setConfigValue, unsetConfigValue, } from "../config.js";
|
|
54
55
|
import { createDebugReportArtifact } from "./debug-report.js";
|
|
@@ -630,6 +631,15 @@ export const TOOL_DISPATCH = [
|
|
|
630
631
|
summerVersion: optStr(args, "summerVersion"),
|
|
631
632
|
});
|
|
632
633
|
}),
|
|
634
|
+
entry("summer_capture_gameplay", "Capture real gameplay frames offscreen, without a running editor", false, (args) => captureGameplay({
|
|
635
|
+
project: optStr(args, "project"),
|
|
636
|
+
scene: optStr(args, "scene"),
|
|
637
|
+
resolution: optStr(args, "resolution"),
|
|
638
|
+
frames: optNumberOrUndefined(args, "frames"),
|
|
639
|
+
waitSeconds: optNumberOrUndefined(args, "waitSeconds"),
|
|
640
|
+
intervalSeconds: optNumberOrUndefined(args, "intervalSeconds"),
|
|
641
|
+
out: optStr(args, "out"),
|
|
642
|
+
})),
|
|
633
643
|
entry("summer_publish_build", "Upload a summer.games export to your store game (confirm-gated)", false, (args) => publishBuild({
|
|
634
644
|
gameId: optStr(args, "gameId"),
|
|
635
645
|
file: optStr(args, "file"),
|
|
@@ -651,7 +661,7 @@ export const TOOL_DISPATCH = [
|
|
|
651
661
|
confirm: args.confirm === true,
|
|
652
662
|
face: "cli",
|
|
653
663
|
})),
|
|
654
|
-
entry("summer_creator_releases", "
|
|
664
|
+
entry("summer_creator_releases", "Deprecated: list releases on the legacy creator API; use summer_store_releases", false, (args) => listCreatorReleases({
|
|
655
665
|
projectId: optStr(args, "projectId"),
|
|
656
666
|
limit: typeof args.limit === "number" ? args.limit : 20,
|
|
657
667
|
cursor: optStr(args, "cursor"),
|
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
* both faces validate the same arguments, send the same op, and render the
|
|
5
5
|
* engine's failure taxonomy the same way.
|
|
6
6
|
*
|
|
7
|
-
* Seven engine ops (
|
|
8
|
-
* doc/SUMMER/SCENE_SCRIPTING_CONTRACTS.md "Wave L") behind four tools:
|
|
7
|
+
* Seven engine ops (a frozen engine contract) behind four tools:
|
|
9
8
|
*
|
|
10
9
|
* summer_ui_actions mode:"list" -> UiListActions (read)
|
|
11
10
|
* mode:"invoke" -> UiInvoke (mutates)
|
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
* both faces validate the same arguments, send the same op, and render the
|
|
5
5
|
* engine's failure taxonomy the same way.
|
|
6
6
|
*
|
|
7
|
-
* Seven engine ops (
|
|
8
|
-
* doc/SUMMER/SCENE_SCRIPTING_CONTRACTS.md "Wave L") behind four tools:
|
|
7
|
+
* Seven engine ops (a frozen engine contract) behind four tools:
|
|
9
8
|
*
|
|
10
9
|
* summer_ui_actions mode:"list" -> UiListActions (read)
|
|
11
10
|
* mode:"invoke" -> UiInvoke (mutates)
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* `summer_world_snapshot` (src/mcp/tools/perception-tools.ts and
|
|
4
4
|
* tool-dispatch.ts).
|
|
5
5
|
*
|
|
6
|
-
* The engine's GetWorldSnapshot
|
|
6
|
+
* The engine's GetWorldSnapshot op takes only
|
|
7
7
|
* scene_path / max_nodes / max_lights / include_2d and returns every node it
|
|
8
8
|
* walked, about 250 bytes each: a scene of a few thousand nodes is far too
|
|
9
9
|
* big to read.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* `summer_world_snapshot` (src/mcp/tools/perception-tools.ts and
|
|
4
4
|
* tool-dispatch.ts).
|
|
5
5
|
*
|
|
6
|
-
* The engine's GetWorldSnapshot
|
|
6
|
+
* The engine's GetWorldSnapshot op takes only
|
|
7
7
|
* scene_path / max_nodes / max_lights / include_2d and returns every node it
|
|
8
8
|
* walked, about 250 bytes each: a scene of a few thousand nodes is far too
|
|
9
9
|
* big to read.
|
|
@@ -77,7 +77,7 @@ export interface EngineCapabilities {
|
|
|
77
77
|
* `summer` capture ships, and the offscreen instance cap. Absent = engine
|
|
78
78
|
* predates runtime control (or advertises the kinds only in opKinds). */
|
|
79
79
|
runtimeControl?: EngineRuntimeControlCapabilities;
|
|
80
|
-
/** Editor navigation advert (engine `Navigate` op
|
|
80
|
+
/** Editor navigation advert (engine `Navigate` op): the
|
|
81
81
|
* destination ids this build can open. Absent = engine predates the op;
|
|
82
82
|
* summer_open then falls back to the legacy per-surface ops it can map. */
|
|
83
83
|
navigation?: EngineNavigationCapabilities;
|
|
@@ -174,8 +174,7 @@ export declare function missingEngineEventsResult(client: CapabilityAdvertisingC
|
|
|
174
174
|
export declare function buildCapabilitySkewWarning(health: unknown): string | null;
|
|
175
175
|
/**
|
|
176
176
|
* Engine ops that MUST be dispatched as their own single-op request. Mirrors
|
|
177
|
-
*
|
|
178
|
-
* 0.5.60+): the engine rejects any multi-op batch containing one of these
|
|
177
|
+
* the engine's single-async-op list (engine 0.5.60+): the engine rejects any multi-op batch containing one of these
|
|
179
178
|
* WHOLESALE — nothing in the batch executes, and the batch fails with per-op
|
|
180
179
|
* failure_reason "unsupported_transport"/"skipped". Git ops are covered by a
|
|
181
180
|
* prefix check in the dispatchers.
|
|
@@ -46,7 +46,7 @@ export const CLI_KNOWN_OP_NEEDS = [
|
|
|
46
46
|
// summer_grep (core/capabilities/grep.ts)
|
|
47
47
|
"Grep",
|
|
48
48
|
// Navigation (summer_open: core/capabilities/navigation/) — Navigate is the
|
|
49
|
-
// one-table op
|
|
49
|
+
// engine's one-table op; the other three are the legacy
|
|
50
50
|
// fallbacks on engines that predate it.
|
|
51
51
|
"Navigate", "OpenResource", "FocusDock", "RevealInFileSystem",
|
|
52
52
|
// Project + input
|
|
@@ -334,8 +334,7 @@ export function buildCapabilitySkewWarning(health) {
|
|
|
334
334
|
// ---------------------------------------------------------------------------
|
|
335
335
|
/**
|
|
336
336
|
* Engine ops that MUST be dispatched as their own single-op request. Mirrors
|
|
337
|
-
*
|
|
338
|
-
* 0.5.60+): the engine rejects any multi-op batch containing one of these
|
|
337
|
+
* the engine's single-async-op list (engine 0.5.60+): the engine rejects any multi-op batch containing one of these
|
|
339
338
|
* WHOLESALE — nothing in the batch executes, and the batch fails with per-op
|
|
340
339
|
* failure_reason "unsupported_transport"/"skipped". Git ops are covered by a
|
|
341
340
|
* prefix check in the dispatchers.
|
|
@@ -353,12 +352,12 @@ export const FALLBACK_SINGLE_ONLY_OPS = new Set([
|
|
|
353
352
|
"RunCommand", "RunVerification", "RunEditorScript", "RunSceneScript",
|
|
354
353
|
"ImportFromUrl", "ImportFromUrlBatch", "ExtractZipFromUrl",
|
|
355
354
|
// Mesh fabrication: a headless Blender child on the same async single-op lane as
|
|
356
|
-
// RunEditorScript
|
|
355
|
+
// RunEditorScript.
|
|
357
356
|
"FabricateMesh",
|
|
358
357
|
// runtime control (RuntimeOps::async_op_kinds): every op below rides
|
|
359
358
|
// the `summer` debugger capture, so like GameSnapshot each needs the async
|
|
360
359
|
// single-op reply channel. ListGameInstances is deliberately NOT here — it
|
|
361
|
-
// is a cheap synchronous editor read that batches fine
|
|
360
|
+
// is a cheap synchronous editor read that batches fine.
|
|
362
361
|
"SetRuntimeProp", "CallRuntimeMethod", "SpawnRuntimeScene", "FreeRuntimeNode",
|
|
363
362
|
"RuntimeAnimation", "RuntimeAnimationTree", "GetRuntimeBones",
|
|
364
363
|
"GamePause", "GameSpeed", "GameStep",
|
package/dist/core/config.js
CHANGED
|
@@ -30,7 +30,7 @@ function validateGatewayUrl(value) {
|
|
|
30
30
|
}
|
|
31
31
|
const local = parsed.hostname === "localhost" ||
|
|
32
32
|
parsed.hostname === "127.0.0.1" ||
|
|
33
|
-
parsed.hostname === "::1";
|
|
33
|
+
parsed.hostname === "[::1]";
|
|
34
34
|
if (parsed.protocol !== "https:" && !(local && parsed.protocol === "http:")) {
|
|
35
35
|
throw new Error("gateway.url must use HTTPS (HTTP is allowed only for localhost). Recovery: set an HTTPS URL and retry.");
|
|
36
36
|
}
|
|
@@ -49,7 +49,7 @@ function validateCreatorApiUrl(value) {
|
|
|
49
49
|
}
|
|
50
50
|
const local = parsed.hostname === "localhost" ||
|
|
51
51
|
parsed.hostname === "127.0.0.1" ||
|
|
52
|
-
parsed.hostname === "::1";
|
|
52
|
+
parsed.hostname === "[::1]";
|
|
53
53
|
if (parsed.protocol !== "https:" && !(local && parsed.protocol === "http:")) {
|
|
54
54
|
throw new Error("creator.apiUrl must use HTTPS (HTTP is allowed only for localhost). Recovery: set an HTTPS URL and retry.");
|
|
55
55
|
}
|