summer-engine 3.4.0 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +5 -1
- package/.codex-plugin/plugin.json +5 -1
- package/.cursor-plugin/plugin.json +5 -1
- package/.factory-plugin/plugin.json +5 -1
- package/.opencode/INSTALL.md +8 -8
- package/.opencode/plugins/summer.js +2 -2
- package/AGENTS.md +7 -7
- package/CHANGELOG.md +37 -0
- package/GEMINI.md +1 -1
- package/NOTICE +1 -1
- package/README.md +35 -35
- 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/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/setup.js +24 -4
- package/dist/cli/commands/skills.js +2 -2
- 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 +72 -7
- package/dist/core/capabilities/capture-gameplay.js +386 -25
- 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/engine-receipt.d.ts +5 -7
- package/dist/core/capabilities/engine-receipt.js +7 -9
- package/dist/core/capabilities/export-engine-version.d.ts +7 -0
- package/dist/core/capabilities/export-engine-version.js +9 -0
- package/dist/core/capabilities/export-game.d.ts +4 -0
- package/dist/core/capabilities/export-game.js +53 -10
- 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 +12 -2
- package/dist/core/capabilities/image-generation.js +31 -2
- 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 +1 -1
- package/dist/core/capabilities/publish-build.js +21 -9
- 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 +11 -3
- package/dist/core/capabilities/summer-bundle.js +21 -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 +14 -3
- 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/feedback/client.js +1 -1
- package/dist/core/launch-posture.d.ts +3 -3
- package/dist/core/launch-posture.js +3 -3
- package/dist/core/library-read.d.ts +7 -0
- package/dist/core/library-read.js +60 -9
- package/dist/core/library-search.d.ts +2 -0
- package/dist/core/templates.d.ts +1 -2
- package/dist/core/templates.js +1 -2
- package/dist/installer/agent-config.d.ts +25 -0
- package/dist/installer/agent-config.js +114 -3
- package/dist/installer/agent-table.d.ts +12 -0
- package/dist/installer/agent-table.js +9 -0
- package/dist/mcp/server.d.ts +2 -2
- package/dist/mcp/server.js +2 -2
- package/dist/mcp/tools/creator-tools.js +33 -4
- package/dist/mcp/tools/debug-tools.js +1 -1
- package/dist/mcp/tools/generate-tools.js +18 -37
- package/dist/mcp/tools/library-tools.d.ts +2 -1
- package/dist/mcp/tools/library-tools.js +1 -0
- 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 +5 -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 +16 -15
- 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 +16 -6
- 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 +6 -7
- 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 +2 -2
- package/library/skills/concept-art/SKILL.md +3 -3
- 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 +24 -25
- package/library/skills/export-and-ship/resource.yaml +2 -1
- 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/grow-analytics/SKILL.md +21 -0
- package/library/skills/grow-analytics/resource.yaml +27 -0
- package/library/skills/headless-scripting/SKILL.md +8 -8
- 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/publish-your-game/SKILL.md +21 -0
- package/library/skills/publish-your-game/resource.yaml +29 -0
- 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/store-art/SKILL.md +23 -0
- package/library/skills/store-art/resource.yaml +30 -0
- package/library/skills/store-listing/SKILL.md +21 -0
- package/library/skills/store-listing/resource.yaml +25 -0
- package/library/skills/summer-analytics/SKILL.md +3 -3
- package/library/skills/summer-analytics/resource.yaml +1 -0
- 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/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 +66 -1
- package/library/tools/creator-publish/resource.yaml +4 -4
- package/library/tools/creator-releases/resource.yaml +5 -5
- package/library/tools/export-game/resource.yaml +3 -0
- package/library/tools/generate-image/resource.yaml +4 -2
- package/library/tools/publish-build/resource.yaml +5 -1
- package/package.json +1 -1
- package/registry/generated/counts.json +2 -2
- package/registry/generated/gemini-extension.json +5 -1
- package/registry/generated/index.json +280 -137
- package/registry/generated/marketplace.claude.json +1 -1
- package/registry/generated/plugin.claude.json +5 -1
- package/registry/generated/plugin.codex.json +5 -1
- package/registry/generated/plugin.cursor.json +5 -1
- package/registry/generated/plugin.factory.json +5 -1
- package/registry/generated/skills-index.md +16 -6
- package/registry/generated/skills-registry.json +57 -5
- package/registry/schemas/domains.json +1 -1
- package/registry/schemas/skill.schema.json +5 -0
|
@@ -7,6 +7,15 @@ import { BuildToolError } from "./summer-bundle.js";
|
|
|
7
7
|
* summer_export_game writes and fails after a full engine start.
|
|
8
8
|
*/
|
|
9
9
|
export const EXPORT_MIN_ENGINE_VERSION = "0.7.0";
|
|
10
|
+
/** Bundle targets that need a newer engine than EXPORT_MIN_ENGINE_VERSION. */
|
|
11
|
+
export const TARGET_MIN_ENGINE_VERSION = { android: "0.7.1" };
|
|
12
|
+
/** The requested targets this engine version cannot export; an unreadable version skips none. */
|
|
13
|
+
export function targetsNeedingNewerEngine(targets, version) {
|
|
14
|
+
return targets.flatMap((target) => {
|
|
15
|
+
const needs = TARGET_MIN_ENGINE_VERSION[target];
|
|
16
|
+
return needs && isVersionAtLeast(version, needs) === false ? [{ target, needs }] : [];
|
|
17
|
+
});
|
|
18
|
+
}
|
|
10
19
|
export const ENGINE_UPDATE_HOW = 'run "summer install --yes" (or download it from summerengine.com/download)';
|
|
11
20
|
/** Installed Summer version of an engine binary, or null when this system cannot read it. */
|
|
12
21
|
export function installedEngineVersion(binary) {
|
|
@@ -34,6 +34,8 @@ export interface ExportGameInput {
|
|
|
34
34
|
out?: string;
|
|
35
35
|
/** Export with debug enabled (--export-debug). */
|
|
36
36
|
debug?: boolean;
|
|
37
|
+
/** Bundle with targets: set summer.build.json targetPlatforms to the targets first, so the store takes the declaration. */
|
|
38
|
+
alignDeclaration?: boolean;
|
|
37
39
|
/** Export preset name; the engine's own is "summer.games". Bundle format without targets only. */
|
|
38
40
|
preset?: string;
|
|
39
41
|
/** Store platforms: macos, windows, ios, android, web. */
|
|
@@ -52,6 +54,8 @@ export interface ExportGameResult {
|
|
|
52
54
|
preset: string;
|
|
53
55
|
/** The targets asked for, when any were. */
|
|
54
56
|
targets?: StoreTarget[];
|
|
57
|
+
/** Asked-for targets left out of the bundle (an engine too old for them); warnings say why. */
|
|
58
|
+
skippedTargets?: StoreTarget[];
|
|
55
59
|
/** What happened to export_presets.cfg for the preset this export used. */
|
|
56
60
|
presetChange?: EnsuredPreset["change"];
|
|
57
61
|
debug: boolean;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
2
|
-
import { mkdir, readdir, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
2
|
+
import { mkdir, readdir, readFile, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
3
3
|
import { basename, dirname, extname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
4
4
|
import { platform } from "node:os";
|
|
5
5
|
import { engineSelectionFromEnv } from "../engine.js";
|
|
@@ -7,10 +7,10 @@ import { findEngineBinary } from "../engine-install.js";
|
|
|
7
7
|
import { readStoreJson, writeStoreJson } from "../store.js";
|
|
8
8
|
import { writeZip } from "../util/zip-write.js";
|
|
9
9
|
import { engineErrorLines, runEngine } from "./engine-run.js";
|
|
10
|
-
import { assertExportEngine, installedEngineVersion } from "./export-engine-version.js";
|
|
10
|
+
import { assertExportEngine, ENGINE_UPDATE_HOW, installedEngineVersion, targetsNeedingNewerEngine } from "./export-engine-version.js";
|
|
11
11
|
import { BUNDLE_TARGETS, DOWNLOAD_TARGETS, SUMMER_GAMES_PRESET, bundlePresetSpec, ensurePreset, normalizeTargets, variantString, } from "./export-presets.js";
|
|
12
12
|
import { engineTemplateInfo, findInstalledTemplate, templateFileFor } from "./export-templates.js";
|
|
13
|
-
import { BuildToolError, hashFile, readSummerBundle } from "./summer-bundle.js";
|
|
13
|
+
import { BuildToolError, declarationMismatch, hashFile, readSummerBundle, samePlatforms } from "./summer-bundle.js";
|
|
14
14
|
export { runEngine, SUMMER_GAMES_PRESET };
|
|
15
15
|
/**
|
|
16
16
|
* summer_export_game: run the installed Summer Engine headless and return the
|
|
@@ -36,15 +36,15 @@ export { runEngine, SUMMER_GAMES_PRESET };
|
|
|
36
36
|
*/
|
|
37
37
|
export const LAST_EXPORT_FILE = "last-export.json";
|
|
38
38
|
const DEFAULT_TIMEOUT_MS = 15 * 60_000;
|
|
39
|
-
/** Store platform ids of the versions intake
|
|
39
|
+
/** Store platform ids of the store's versions intake. */
|
|
40
40
|
const STORE_VERSION_PLATFORM = {
|
|
41
41
|
web: "web",
|
|
42
42
|
macos: "macos-universal",
|
|
43
43
|
windows: "windows-x64",
|
|
44
44
|
};
|
|
45
|
-
/** Web zip limits of the store
|
|
45
|
+
/** Web zip limits of the store. */
|
|
46
46
|
const WEB_LIMITS = { zipBytes: 500 * 1024 * 1024, fileBytes: 200 * 1024 * 1024, files: 2000 };
|
|
47
|
-
/** Games without a server run on the phone apps only (
|
|
47
|
+
/** Games without a server run on the phone apps only (the store's standalone targets). */
|
|
48
48
|
const STANDALONE_TARGETS = ["ios", "android"];
|
|
49
49
|
/** Engine support per bundle target, for the recovery text when a target is missing. */
|
|
50
50
|
const TARGET_ENGINE_NOTE = {
|
|
@@ -272,10 +272,27 @@ async function runExport(deps, binary, project, preset, out, debug, timeoutMs, n
|
|
|
272
272
|
throw new BuildToolError("export_failed", `Summer Engine did not export the game (exit ${run.code ?? run.signal})${named.length ? `: ${named.join(" | ")}` : "."}`, [exportFailureRecovery(errors, preset), ...notes].join(" "), undefined, { errors, output: outputTail(run.output) });
|
|
273
273
|
}
|
|
274
274
|
}
|
|
275
|
+
/** Set the project's summer.build.json targetPlatforms to the export targets (a hosted game's Build declaration). */
|
|
276
|
+
async function alignBuildDeclaration(project, targets) {
|
|
277
|
+
const path = join(project, "summer.build.json");
|
|
278
|
+
if (!existsSync(path))
|
|
279
|
+
return;
|
|
280
|
+
let build;
|
|
281
|
+
try {
|
|
282
|
+
build = JSON.parse(await readFile(path, "utf8"));
|
|
283
|
+
}
|
|
284
|
+
catch {
|
|
285
|
+
throw new BuildToolError("build_declaration_invalid", "summer.build.json is not valid JSON.", "Recovery: fix summer.build.json, then export again.");
|
|
286
|
+
}
|
|
287
|
+
if (Array.isArray(build.targetPlatforms) && samePlatforms(build.targetPlatforms.map(String), targets))
|
|
288
|
+
return;
|
|
289
|
+
build.targetPlatforms = [...targets];
|
|
290
|
+
await writeFile(path, `${JSON.stringify(build, null, 2)}\n`);
|
|
291
|
+
}
|
|
275
292
|
export async function exportGame(input, overrides = {}) {
|
|
276
293
|
const deps = { ...defaultDependencies, ...overrides };
|
|
277
294
|
const project = resolveExportProject(input.project);
|
|
278
|
-
|
|
295
|
+
let targets = input.targets?.length ? normalizeTargets(input.targets) : undefined;
|
|
279
296
|
const format = resolveFormat(input, targets);
|
|
280
297
|
const debug = input.debug === true;
|
|
281
298
|
const started = deps.now();
|
|
@@ -293,13 +310,26 @@ export async function exportGame(input, overrides = {}) {
|
|
|
293
310
|
throw new BuildToolError("engine_not_installed", "Summer Engine is not installed on this machine.", 'Recovery: run "summer install", or set SUMMER_BIN to the engine executable, then export again.');
|
|
294
311
|
}
|
|
295
312
|
// Before any preset is written: an old engine cannot read them.
|
|
296
|
-
|
|
313
|
+
const engineVersion = deps.engineVersion(binary);
|
|
314
|
+
assertExportEngine(binary, engineVersion);
|
|
315
|
+
// A target this engine cannot build is left out, not the whole export.
|
|
316
|
+
const skipped = format === "bundle" && targets ? targetsNeedingNewerEngine(targets, engineVersion) : [];
|
|
317
|
+
const skippedWarnings = skipped.map(({ target, needs }) => `${target} was not exported: it needs Summer Engine ${needs} or newer, and ${engineVersion} is installed. Update (${ENGINE_UPDATE_HOW}) and export ${target} again.`);
|
|
318
|
+
if (skipped.length) {
|
|
319
|
+
const left = targets.filter((target) => !skipped.some((entry) => entry.target === target));
|
|
320
|
+
if (!left.length) {
|
|
321
|
+
throw new BuildToolError("export_target_unsupported", `Summer Engine ${engineVersion} cannot export ${skipped.map((entry) => entry.target).join(", ")}.`, `Recovery: ${skippedWarnings.join(" ")}`, undefined, { engineVersion, skippedTargets: skipped });
|
|
322
|
+
}
|
|
323
|
+
targets = left;
|
|
324
|
+
}
|
|
297
325
|
if (format === "download") {
|
|
298
326
|
return exportDownload(deps, binary, project, targets[0], out, debug, timeoutMs, started);
|
|
299
327
|
}
|
|
300
328
|
out ??= join(await defaultExportDir(project), `${basename(project)}-${stamp(started)}.zip`);
|
|
301
329
|
const before = existsSync(out) ? statSync(out).mtimeMs : null;
|
|
302
330
|
const projectBefore = await snapshotProjectFiles(project);
|
|
331
|
+
if (targets && input.alignDeclaration === true)
|
|
332
|
+
await alignBuildDeclaration(project, targets);
|
|
303
333
|
const ensured = targets ? await ensurePreset(project, bundlePresetSpec(targets)) : undefined;
|
|
304
334
|
const preset = ensured?.name ?? (input.preset?.trim() || SUMMER_GAMES_PRESET);
|
|
305
335
|
const notes = (targets ?? []).flatMap((target) => TARGET_ENGINE_NOTE[target] ?? []);
|
|
@@ -310,10 +340,20 @@ export async function exportGame(input, overrides = {}) {
|
|
|
310
340
|
}
|
|
311
341
|
const bundle = await readSummerBundle(out);
|
|
312
342
|
const missing = (targets ?? []).filter((target) => !bundle.targetPlatforms.includes(target));
|
|
313
|
-
|
|
343
|
+
// Some targets made it: keep the bundle and say which did not.
|
|
344
|
+
const partial = missing.length > 0 && missing.length < (targets ?? []).length;
|
|
345
|
+
if (missing.length && !partial) {
|
|
314
346
|
throw new BuildToolError("export_target_unsupported", `This Summer Engine exported the bundle without ${missing.join(", ")}: its summer.games preset has no such platform.`, ["Recovery: update Summer Engine and export again, or export without those targets.", ...missing.flatMap((target) => TARGET_ENGINE_NOTE[target] ?? [])].join(" "), undefined, { exportedPlatforms: bundle.targetPlatforms, path: out });
|
|
315
347
|
}
|
|
316
|
-
const warnings = projectChangeWarnings(projectChanges);
|
|
348
|
+
const warnings = [...skippedWarnings, ...projectChangeWarnings(projectChanges)];
|
|
349
|
+
const mismatch = declarationMismatch(bundle);
|
|
350
|
+
if (mismatch) {
|
|
351
|
+
warnings.unshift(`summer_publish_build will refuse this export (declaration_mismatch): ${mismatch}. Export again with alignDeclaration:true to set summer.build.json targetPlatforms to [${bundle.targetPlatforms.join(", ")}], or with targets equal to what it declares.`);
|
|
352
|
+
}
|
|
353
|
+
if (partial) {
|
|
354
|
+
warnings.push(`This Summer Engine exported the bundle without ${missing.join(", ")}: its summer.games preset has no such platform. ` +
|
|
355
|
+
["Update Summer Engine and export them again.", ...missing.flatMap((target) => TARGET_ENGINE_NOTE[target] ?? [])].join(" "));
|
|
356
|
+
}
|
|
317
357
|
const desktopOnly = bundle.hosted ? [] : bundle.targetPlatforms.filter((target) => !STANDALONE_TARGETS.includes(target));
|
|
318
358
|
if (desktopOnly.length) {
|
|
319
359
|
warnings.push(`This game has no server, and the store runs games without a server on iPhone and Android only: summer_publish_build will refuse ${desktopOnly.join(", ")}. ` +
|
|
@@ -332,6 +372,9 @@ export async function exportGame(input, overrides = {}) {
|
|
|
332
372
|
project,
|
|
333
373
|
preset,
|
|
334
374
|
...(targets ? { targets, presetChange: ensured.change } : {}),
|
|
375
|
+
...(skipped.length || partial
|
|
376
|
+
? { skippedTargets: [...skipped.map((entry) => entry.target), ...(partial ? missing : [])] }
|
|
377
|
+
: {}),
|
|
335
378
|
debug,
|
|
336
379
|
engine: binary,
|
|
337
380
|
durationMs: deps.now().getTime() - started.getTime(),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Store targets for summer_export_game, and the export presets that make them.
|
|
3
3
|
*
|
|
4
|
-
* The Summer Games store has two intakes
|
|
4
|
+
* The Summer Games store has two intakes:
|
|
5
5
|
* - build-publications takes ONE summer.bundle.v1 .zip per Build. Summer runs
|
|
6
6
|
* its client.pck on its own client templates (the Summer Games iOS and
|
|
7
7
|
* Android apps, the Summer desktop app on macOS and Windows), so the creator
|
|
@@ -5,7 +5,7 @@ import { BuildToolError } from "./summer-bundle.js";
|
|
|
5
5
|
/**
|
|
6
6
|
* Store targets for summer_export_game, and the export presets that make them.
|
|
7
7
|
*
|
|
8
|
-
* The Summer Games store has two intakes
|
|
8
|
+
* The Summer Games store has two intakes:
|
|
9
9
|
* - build-publications takes ONE summer.bundle.v1 .zip per Build. Summer runs
|
|
10
10
|
* its client.pck on its own client templates (the Summer Games iOS and
|
|
11
11
|
* Android apps, the Summer desktop app on macOS and Windows), so the creator
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* (`summer tool fabricate-3d`) so both faces validate the same arguments, send
|
|
5
5
|
* the same op with the same clamps, and wait the same client poll budget.
|
|
6
6
|
*
|
|
7
|
-
* What the op does on the engine side
|
|
7
|
+
* What the op does on the engine side: run one
|
|
8
8
|
* agent-authored bpy script in a supervised headless child of the USER'S OWN
|
|
9
9
|
* Blender install, validate the .glb the child exported, move it under res://,
|
|
10
10
|
* wait for the editor import to settle, and optionally instantiate it into the
|
|
@@ -28,8 +28,7 @@ export declare const FABRICATE_DEFAULT_OUT_DIR = "res://assets/fabricated/";
|
|
|
28
28
|
/** What the tool tells the model to do when the engine lacks FabricateMesh. */
|
|
29
29
|
export declare const FABRICATE_FALLBACK = "generate the asset with summer_generate_3d, import one from the free library with summer_search_assets / summer_import_asset, use summer_import_hdri for environment lighting, or build blockout geometry in-scene with summer_add_node / summer_set_prop or a summer_run_editor_script";
|
|
30
30
|
/**
|
|
31
|
-
* Mirror of the engine's out_path pre-validation
|
|
32
|
-
* _resolve_out_path) so a bad destination is refused on this side with the
|
|
31
|
+
* Mirror of the engine's out_path pre-validation so a bad destination is refused on this side with the
|
|
33
32
|
* same words, and nothing is sent. Returns null when the path is acceptable.
|
|
34
33
|
*/
|
|
35
34
|
export declare function fabricateOutPathProblem(rawPath: string): string | null;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* (`summer tool fabricate-3d`) so both faces validate the same arguments, send
|
|
5
5
|
* the same op with the same clamps, and wait the same client poll budget.
|
|
6
6
|
*
|
|
7
|
-
* What the op does on the engine side
|
|
7
|
+
* What the op does on the engine side: run one
|
|
8
8
|
* agent-authored bpy script in a supervised headless child of the USER'S OWN
|
|
9
9
|
* Blender install, validate the .glb the child exported, move it under res://,
|
|
10
10
|
* wait for the editor import to settle, and optionally instantiate it into the
|
|
@@ -30,8 +30,7 @@ export const FABRICATE_DEFAULT_OUT_DIR = "res://assets/fabricated/";
|
|
|
30
30
|
export const FABRICATE_FALLBACK = "generate the asset with summer_generate_3d, import one from the free library with summer_search_assets / summer_import_asset, use summer_import_hdri for environment lighting, or build blockout geometry in-scene with summer_add_node / summer_set_prop or a summer_run_editor_script";
|
|
31
31
|
const VECTOR3_VARIANT_RE = /^Vector3\(\s*[-+]?(?:\d+\.?\d*|\.\d+)(?:[eE][-+]?\d+)?\s*,\s*[-+]?(?:\d+\.?\d*|\.\d+)(?:[eE][-+]?\d+)?\s*,\s*[-+]?(?:\d+\.?\d*|\.\d+)(?:[eE][-+]?\d+)?\s*\)$/;
|
|
32
32
|
/**
|
|
33
|
-
* Mirror of the engine's out_path pre-validation
|
|
34
|
-
* _resolve_out_path) so a bad destination is refused on this side with the
|
|
33
|
+
* Mirror of the engine's out_path pre-validation so a bad destination is refused on this side with the
|
|
35
34
|
* same words, and nothing is sent. Returns null when the path is acceptable.
|
|
36
35
|
*/
|
|
37
36
|
export function fabricateOutPathProblem(rawPath) {
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Frame-quality probe for engine screenshots (tool/screenshot).
|
|
3
3
|
*
|
|
4
|
-
* WHY THIS EXISTS. In the 2026-09-03 end-to-end run
|
|
5
|
-
*
|
|
4
|
+
* WHY THIS EXISTS. In the 2026-09-03 end-to-end run,
|
|
5
|
+
* `summer_screenshot target:"viewport"` returned an entirely black
|
|
6
6
|
* 1072x1280 JPEG (src/core/capabilities/__fixtures__/frames/01-mcp-viewport-black.jpg)
|
|
7
7
|
* with a caption
|
|
8
8
|
* telling the agent to describe what it saw. It was the first viewport capture
|
|
9
9
|
* after scene mutations had flipped the editor from the 3D to the 2D tab; the
|
|
10
10
|
* same call 67 s later returned real content. Engine side, the ViewportSnapshot
|
|
11
|
-
* op
|
|
11
|
+
* op reads the
|
|
12
12
|
* editor SubViewport's texture with get_texture()->get_image() AS-IS — no forced
|
|
13
13
|
* RenderingServer draw and no blank-frame retry, both of which ScenePreview has
|
|
14
|
-
*
|
|
14
|
+
* because a not-yet-drawn
|
|
15
15
|
* texture reads back black. That is consistent with a 2D subviewport that had
|
|
16
16
|
* not been redrawn since the tab switch, but it has NOT been proven by
|
|
17
17
|
* instrumenting the engine, so this module detects the SYMPTOM (a flat frame)
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Frame-quality probe for engine screenshots (tool/screenshot).
|
|
3
3
|
*
|
|
4
|
-
* WHY THIS EXISTS. In the 2026-09-03 end-to-end run
|
|
5
|
-
*
|
|
4
|
+
* WHY THIS EXISTS. In the 2026-09-03 end-to-end run,
|
|
5
|
+
* `summer_screenshot target:"viewport"` returned an entirely black
|
|
6
6
|
* 1072x1280 JPEG (src/core/capabilities/__fixtures__/frames/01-mcp-viewport-black.jpg)
|
|
7
7
|
* with a caption
|
|
8
8
|
* telling the agent to describe what it saw. It was the first viewport capture
|
|
9
9
|
* after scene mutations had flipped the editor from the 3D to the 2D tab; the
|
|
10
10
|
* same call 67 s later returned real content. Engine side, the ViewportSnapshot
|
|
11
|
-
* op
|
|
11
|
+
* op reads the
|
|
12
12
|
* editor SubViewport's texture with get_texture()->get_image() AS-IS — no forced
|
|
13
13
|
* RenderingServer draw and no blank-frame retry, both of which ScenePreview has
|
|
14
|
-
*
|
|
14
|
+
* because a not-yet-drawn
|
|
15
15
|
* texture reads back black. That is consistent with a 2D subviewport that had
|
|
16
16
|
* not been redrawn since the tab switch, but it has NOT been proven by
|
|
17
17
|
* instrumenting the engine, so this module detects the SYMPTOM (a flat frame)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* grep — ONE implementation of `summer_grep` for both faces
|
|
3
3
|
* (src/mcp/tools/file-tools.ts and tool-dispatch.ts), over the engine's
|
|
4
|
-
* ripgrep-backed Grep op
|
|
4
|
+
* ripgrep-backed Grep op.
|
|
5
5
|
*
|
|
6
6
|
* The engine op returns {file, line, content} per match and parses only
|
|
7
7
|
* ripgrep's "match" events, so its contextLines flag adds nothing to the
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* grep — ONE implementation of `summer_grep` for both faces
|
|
3
3
|
* (src/mcp/tools/file-tools.ts and tool-dispatch.ts), over the engine's
|
|
4
|
-
* ripgrep-backed Grep op
|
|
4
|
+
* ripgrep-backed Grep op.
|
|
5
5
|
*
|
|
6
6
|
* The engine op returns {file, line, content} per match and parses only
|
|
7
7
|
* ripgrep's "match" events, so its contextLines flag adds nothing to the
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
/** Image generation can take over a minute on the larger models; wait this long for the server. */
|
|
3
|
+
export declare const IMAGE_GENERATION_TIMEOUT_MS = 180000;
|
|
2
4
|
/** Shared MCP/CLI image request contract; optional flags preserve omission. */
|
|
3
5
|
export declare const imageGenerationArgsSchema: z.ZodObject<{
|
|
4
6
|
prompt: z.ZodString;
|
|
5
|
-
model: z.
|
|
7
|
+
model: z.ZodOptional<z.ZodString>;
|
|
6
8
|
style: z.ZodDefault<z.ZodString>;
|
|
7
9
|
referenceImageUrl: z.ZodOptional<z.ZodString>;
|
|
8
10
|
removeBackground: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -10,13 +12,15 @@ export declare const imageGenerationArgsSchema: z.ZodObject<{
|
|
|
10
12
|
width: z.ZodOptional<z.ZodNumber>;
|
|
11
13
|
height: z.ZodOptional<z.ZodNumber>;
|
|
12
14
|
options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
|
15
|
+
out: z.ZodOptional<z.ZodString>;
|
|
13
16
|
}, "strip", z.ZodTypeAny, {
|
|
14
17
|
prompt: string;
|
|
15
|
-
model: string;
|
|
16
18
|
style: string;
|
|
17
19
|
width?: number | undefined;
|
|
18
20
|
height?: number | undefined;
|
|
19
21
|
options?: Record<string, any> | undefined;
|
|
22
|
+
out?: string | undefined;
|
|
23
|
+
model?: string | undefined;
|
|
20
24
|
referenceImageUrl?: string | undefined;
|
|
21
25
|
removeBackground?: boolean | undefined;
|
|
22
26
|
aspectRatio?: "1:1" | "16:9" | "9:16" | "4:3" | "3:4" | "3:2" | "2:3" | "5:4" | "4:5" | "21:9" | undefined;
|
|
@@ -25,9 +29,15 @@ export declare const imageGenerationArgsSchema: z.ZodObject<{
|
|
|
25
29
|
width?: number | undefined;
|
|
26
30
|
height?: number | undefined;
|
|
27
31
|
options?: Record<string, any> | undefined;
|
|
32
|
+
out?: string | undefined;
|
|
28
33
|
model?: string | undefined;
|
|
29
34
|
style?: string | undefined;
|
|
30
35
|
referenceImageUrl?: string | undefined;
|
|
31
36
|
removeBackground?: boolean | undefined;
|
|
32
37
|
aspectRatio?: "1:1" | "16:9" | "9:16" | "4:3" | "3:4" | "3:2" | "2:3" | "5:4" | "4:5" | "21:9" | undefined;
|
|
33
38
|
}>;
|
|
39
|
+
/**
|
|
40
|
+
* Save a generated image where the caller asked (a folder or a file path), or
|
|
41
|
+
* under TMPDIR/summer-gen. Returns the path, or null when the download failed.
|
|
42
|
+
*/
|
|
43
|
+
export declare function saveGeneratedImage(url: string, out?: string, prefix?: string): Promise<string | null>;
|
|
@@ -1,11 +1,17 @@
|
|
|
1
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { dirname, extname, join, resolve } from "node:path";
|
|
1
4
|
import { z } from "zod";
|
|
5
|
+
/** Image generation can take over a minute on the larger models; wait this long for the server. */
|
|
6
|
+
export const IMAGE_GENERATION_TIMEOUT_MS = 180_000;
|
|
7
|
+
const IMAGE_EXTENSIONS = new Set([".png", ".jpg", ".jpeg", ".webp"]);
|
|
2
8
|
/** Shared MCP/CLI image request contract; optional flags preserve omission. */
|
|
3
9
|
export const imageGenerationArgsSchema = z.object({
|
|
4
10
|
prompt: z.string().describe("Description of the image to generate"),
|
|
5
11
|
model: z
|
|
6
12
|
.string()
|
|
7
|
-
.
|
|
8
|
-
.describe("Model name or full provider ID"),
|
|
13
|
+
.optional()
|
|
14
|
+
.describe("Model name or full provider ID. Omit it and the server picks one that reaches the requested size (nano-banana-2 when no size is asked)."),
|
|
9
15
|
style: z
|
|
10
16
|
.string()
|
|
11
17
|
.default("realistic")
|
|
@@ -37,4 +43,27 @@ export const imageGenerationArgsSchema = z.object({
|
|
|
37
43
|
.record(z.any())
|
|
38
44
|
.optional()
|
|
39
45
|
.describe("Extra model params (seed, negative_prompt, ...). The result lists any it did not use in ignoredOptions."),
|
|
46
|
+
out: z
|
|
47
|
+
.string()
|
|
48
|
+
.optional()
|
|
49
|
+
.describe("Where to save the image on this machine: a folder, or a file path ending in .png, .jpg or .webp. Default: <TMPDIR>/summer-gen/."),
|
|
40
50
|
});
|
|
51
|
+
/**
|
|
52
|
+
* Save a generated image where the caller asked (a folder or a file path), or
|
|
53
|
+
* under TMPDIR/summer-gen. Returns the path, or null when the download failed.
|
|
54
|
+
*/
|
|
55
|
+
export async function saveGeneratedImage(url, out, prefix = "img") {
|
|
56
|
+
try {
|
|
57
|
+
const target = out?.trim() ? resolve(out.trim()) : join(tmpdir(), "summer-gen");
|
|
58
|
+
const file = IMAGE_EXTENSIONS.has(extname(target).toLowerCase()) ? target : join(target, `${prefix}-${Date.now()}.png`);
|
|
59
|
+
await mkdir(dirname(file), { recursive: true });
|
|
60
|
+
const res = await fetch(url, { signal: AbortSignal.timeout(60_000) });
|
|
61
|
+
if (!res.ok)
|
|
62
|
+
return null;
|
|
63
|
+
await writeFile(file, Buffer.from(await res.arrayBuffer()));
|
|
64
|
+
return file;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* advertises `capabilities.navigation` the tool sends the one-table op
|
|
13
13
|
* `Navigate { target, ...args }`; on an engine that predates it the few ids the
|
|
14
14
|
* original ops can serve (scene, node, script, file, the three docks) use those
|
|
15
|
-
* ops and everything else answers `engine_lacks_op`.
|
|
15
|
+
* ops and everything else answers `engine_lacks_op`.
|
|
16
16
|
*
|
|
17
17
|
* Both faces call runOpen(); the CLI (tool-dispatch + `summer open`) and the
|
|
18
18
|
* MCP tool (src/mcp/tools/navigation-tools.ts) only differ in how the engine
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* advertises `capabilities.navigation` the tool sends the one-table op
|
|
13
13
|
* `Navigate { target, ...args }`; on an engine that predates it the few ids the
|
|
14
14
|
* original ops can serve (scene, node, script, file, the three docks) use those
|
|
15
|
-
* ops and everything else answers `engine_lacks_op`.
|
|
15
|
+
* ops and everything else answers `engine_lacks_op`.
|
|
16
16
|
*
|
|
17
17
|
* Both faces call runOpen(); the CLI (tool-dispatch + `summer open`) and the
|
|
18
18
|
* MCP tool (src/mcp/tools/navigation-tools.ts) only differ in how the engine
|
|
@@ -49,7 +49,7 @@ export function renderProductMap() {
|
|
|
49
49
|
lines.push("## Who owns what");
|
|
50
50
|
lines.push("");
|
|
51
51
|
lines.push("- **Web rows** come from summerengine.com's own route catalog (`/agent-routes.json`, published from the web repo's `src/lib/navigation/routes.ts`). The toolkit vendors a snapshot (`assets/navigation/web-routes.json`, refreshed with `npm run sync:web-routes`); it does not invent pages.");
|
|
52
|
-
lines.push("- **Editor rows** are ids of Summer Engine's one navigation table (
|
|
52
|
+
lines.push("- **Editor rows** are ids of Summer Engine's one navigation table (the `Navigate` op). The running engine advertises which ids it can open in `/api/health` `capabilities.navigation`; `summer open --list` shows availability from the connected engine. Engines that predate the `Navigate` op can still serve the rows with a legacy op (last-but-one column); every other row answers `engine_lacks_op` with an update hint.");
|
|
53
53
|
lines.push("");
|
|
54
54
|
lines.push("## How to read a row");
|
|
55
55
|
lines.push("");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The product map as the toolkit sees it (
|
|
2
|
+
* The product map as the toolkit sees it (rendered for agents as library/references/product-map).
|
|
3
3
|
*
|
|
4
4
|
* The toolkit does NOT own where things are. Each product does:
|
|
5
5
|
*
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* src/lib/navigation/routes.ts). A vendored snapshot lives at
|
|
8
8
|
* assets/navigation/web-routes.json (refresh: `npm run sync:web-routes`) and
|
|
9
9
|
* every web row below is built from it — nothing hand-written.
|
|
10
|
-
* - Summer Engine owns one table of editor destinations (
|
|
10
|
+
* - Summer Engine owns one table of editor destinations (the Navigate op) and
|
|
11
11
|
* advertises the ids it can open in /api/health capabilities.navigation.
|
|
12
12
|
* The rows below are METADATA for those ids (titles, intents, argument
|
|
13
13
|
* names) plus, for the few ids an older engine can serve through its
|
|
@@ -8,7 +8,7 @@ export type PlacementField = (typeof PLACEMENT_FIELDS)[number];
|
|
|
8
8
|
/** Model-visible budget for compact receipts (the 5 KB tool-result contract). */
|
|
9
9
|
export declare const COMPACT_LIMIT_BYTES: number;
|
|
10
10
|
/** Held-back transform SetProps sent per request; the engine refuses requests
|
|
11
|
-
* over 256 ops
|
|
11
|
+
* over 256 ops. */
|
|
12
12
|
export declare const TRANSFORM_OPS_PER_REQUEST = 200;
|
|
13
13
|
export interface PlacementProp {
|
|
14
14
|
key: PlacementField;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* twins.
|
|
5
5
|
*
|
|
6
6
|
* The engine's InstantiateScene accepts only parent / scene / name /
|
|
7
|
-
* target_size
|
|
7
|
+
* target_size and must travel as its own
|
|
8
8
|
* request (single-only). A placed piece is therefore an InstantiateScene plus
|
|
9
9
|
* SetProps on the node path its receipt reports (meta.nodePath, which already
|
|
10
10
|
* carries any collision rename). The caller writes ONE op; this module expands
|
|
@@ -35,7 +35,7 @@ export const PLACEMENT_FIELDS = ["position", "rotation_degrees", "scale", "trans
|
|
|
35
35
|
/** Model-visible budget for compact receipts (the 5 KB tool-result contract). */
|
|
36
36
|
export const COMPACT_LIMIT_BYTES = 5 * 1024;
|
|
37
37
|
/** Held-back transform SetProps sent per request; the engine refuses requests
|
|
38
|
-
* over 256 ops
|
|
38
|
+
* over 256 ops. */
|
|
39
39
|
export const TRANSFORM_OPS_PER_REQUEST = 200;
|
|
40
40
|
const SUMMARY_TARGET_BYTES = 4600;
|
|
41
41
|
const ERROR_TEXT_LIMIT = 240;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* summer_play tool and the CLI dispatcher.
|
|
6
6
|
*
|
|
7
7
|
* Transport note: the engine's /api/play rung copies only `scene` into the
|
|
8
|
-
* PlayGame op
|
|
8
|
+
* PlayGame op, so a launch that carries a
|
|
9
9
|
* pin is sent as an explicit PlayGame op through /api/ops instead. A launch
|
|
10
10
|
* without any pin stays on /api/play, byte-for-byte the v1 call.
|
|
11
11
|
*
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* summer_play tool and the CLI dispatcher.
|
|
6
6
|
*
|
|
7
7
|
* Transport note: the engine's /api/play rung copies only `scene` into the
|
|
8
|
-
* PlayGame op
|
|
8
|
+
* PlayGame op, so a launch that carries a
|
|
9
9
|
* pin is sent as an explicit PlayGame op through /api/ops instead. A launch
|
|
10
10
|
* without any pin stays on /api/play, byte-for-byte the v1 call.
|
|
11
11
|
*
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BuildToolError } from "./summer-bundle.js";
|
|
2
|
-
/**
|
|
2
|
+
/** Store client versions: vMAJOR.MINOR.PATCH[-rN]. */
|
|
3
3
|
export declare const CLIENT_VERSION: RegExp;
|
|
4
4
|
export interface PublishBuildInput {
|
|
5
5
|
gameId?: string;
|
|
@@ -8,12 +8,11 @@ import { appendStoreJsonLine } from "../store.js";
|
|
|
8
8
|
import { readJsonResponse } from "../util/http.js";
|
|
9
9
|
import { readLastExport } from "./export-game.js";
|
|
10
10
|
import { publishDownload } from "./publish-download.js";
|
|
11
|
-
import { BuildToolError, readSummerBundle } from "./summer-bundle.js";
|
|
11
|
+
import { BuildToolError, declarationMismatch, 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,18 +36,18 @@ 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 = {
|
|
49
47
|
game_identity_mismatch: "This export belongs to another game. Upload it to its original game, or make a portable export for this game.",
|
|
50
48
|
bundle_invalid: "Summer could not read this export. Export the game again and upload the new file.",
|
|
51
49
|
declaration_mismatch: "The export's game or settings do not match this upload. Use the original game or export a new version with the intended settings.",
|
|
52
|
-
template_set_unavailable: "Summer Games cannot run this Summer version yet.
|
|
50
|
+
template_set_unavailable: "Summer Games cannot run this Summer version yet. If you exported with the newest Summer Engine, Summer Games may still be turning that version on: retry the same upload later, there is nothing to update. With an older engine, update Summer Engine and export again.",
|
|
53
51
|
client_version_conflict: "This version number already belongs to a different export. Use a new clientVersion.",
|
|
54
52
|
artifact_exists: "This exact export is already uploaded for this game. Export a new version and upload that.",
|
|
55
53
|
approval_denied: "Summer Games did not approve this game, so it cannot take new builds.",
|
|
@@ -254,6 +252,10 @@ export function normalizeClientVersion(value) {
|
|
|
254
252
|
return version;
|
|
255
253
|
}
|
|
256
254
|
function targetPlatforms(bundle) {
|
|
255
|
+
const mismatch = declarationMismatch(bundle);
|
|
256
|
+
if (mismatch) {
|
|
257
|
+
throw new BuildToolError("declaration_mismatch", `The store would refuse this upload (declaration_mismatch): ${mismatch}. Nothing was uploaded and no version was used.`, "Recovery: export again with summer_export_game alignDeclaration:true (it sets summer.build.json targetPlatforms to the targets you export), or with targets equal to what summer.build.json declares; then upload the new export.");
|
|
258
|
+
}
|
|
257
259
|
if (bundle.hosted)
|
|
258
260
|
return bundle.targetPlatforms;
|
|
259
261
|
const other = bundle.targetPlatforms.filter((platform) => !STANDALONE_TARGETS.includes(platform));
|
|
@@ -423,7 +425,17 @@ export async function publishBuild(input, overrides = {}) {
|
|
|
423
425
|
break;
|
|
424
426
|
if (publication.state === "failed" || publication.state === "cancelled") {
|
|
425
427
|
const code = typeof publication.errorCode === "string" ? publication.errorCode : "publication_failed";
|
|
426
|
-
throw new BuildToolError(code, (code === "declaration_mismatch"
|
|
428
|
+
throw new BuildToolError(code, ((code === "declaration_mismatch" || code === "template_set_unavailable") && publication.errorMessage) ||
|
|
429
|
+
INTAKE_FAILURES[code] ||
|
|
430
|
+
publication.errorMessage ||
|
|
431
|
+
"Summer could not make a build from this upload.",
|
|
432
|
+
// The store checks the declaration and the bundle before it records a
|
|
433
|
+
// client pack, so those refusals leave the version free.
|
|
434
|
+
code === "declaration_mismatch" || code === "bundle_invalid"
|
|
435
|
+
? "Recovery: fix what the message names, export again and retry; the same clientVersion still works, because a refused upload records no version."
|
|
436
|
+
: code === "template_set_unavailable"
|
|
437
|
+
? `Recovery: ${INTAKE_FAILURES.template_set_unavailable.replace(/^Summer Games cannot run this Summer version yet\. /, "")} The same clientVersion works on the retry.`
|
|
438
|
+
: "Recovery: export again, use a new clientVersion, and retry.", undefined, { publicationId });
|
|
427
439
|
}
|
|
428
440
|
if (deps.now() >= deadline) {
|
|
429
441
|
const result = {
|
|
@@ -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
|