summer-engine 4.6.0 → 4.8.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 +3 -2
- package/.codex-plugin/plugin.json +5 -4
- package/.cursor-plugin/plugin.json +4 -3
- package/.factory-plugin/plugin.json +4 -3
- package/CHANGELOG.md +37 -0
- package/README.md +3 -3
- package/commands/start.md +1 -1
- package/dist/cli/commands/api.d.ts +43 -0
- package/dist/cli/commands/api.js +191 -0
- package/dist/cli/commands/login.d.ts +2 -5
- package/dist/cli/commands/login.js +10 -81
- package/dist/cli/commands/token.d.ts +17 -0
- package/dist/cli/commands/token.js +25 -0
- package/dist/cli/index.js +4 -0
- package/dist/core/api-client.d.ts +5 -1
- package/dist/core/api-client.js +21 -0
- package/dist/core/capabilities/doctor.d.ts +1 -1
- package/dist/core/capabilities/doctor.js +1 -1
- package/dist/core/capabilities/game-task-plan.d.ts +2 -2
- package/dist/core/capabilities/navigation/open.d.ts +3 -0
- package/dist/core/capabilities/navigation/open.js +53 -0
- package/dist/core/capabilities/projects-local.js +2 -1
- package/dist/core/capabilities/runtime-control.d.ts +2 -2
- package/dist/core/capabilities/seeing/args.d.ts +4 -4
- package/dist/core/capabilities/tool-dispatch.js +37 -0
- package/dist/core/capabilities/ui-control.d.ts +2 -2
- package/dist/core/capabilities/view-set.d.ts +11 -0
- package/dist/core/capabilities/view-set.js +15 -0
- package/dist/core/capability-skew.d.ts +8 -0
- package/dist/core/capability-skew.js +18 -0
- package/dist/core/cli-session.d.ts +25 -0
- package/dist/core/cli-session.js +97 -0
- package/dist/core/engine-self-start.d.ts +20 -0
- package/dist/core/engine-self-start.js +108 -5
- package/dist/core/oauth.d.ts +15 -2
- package/dist/core/oauth.js +26 -3
- package/dist/core/ops/areas.d.ts +1 -1
- package/dist/core/ops/areas.js +5 -3
- package/dist/core/ops/engine-answer.js +5 -2
- package/dist/core/ops/engine.js +6 -0
- package/dist/core/ops/save-files.d.ts +2 -0
- package/dist/core/ops/save-files.js +13 -0
- package/dist/core/ops/studio-page.d.ts +22 -0
- package/dist/core/ops/studio-page.js +63 -0
- package/dist/core/sign-in-link.d.ts +38 -0
- package/dist/core/sign-in-link.js +106 -0
- package/dist/core/store.js +19 -1
- package/dist/core/summer-api.d.ts +114 -0
- package/dist/core/summer-api.js +281 -0
- package/dist/mcp/ops-surface.d.ts +3 -0
- package/dist/mcp/ops-surface.js +6 -0
- package/dist/mcp/server.js +16 -4
- package/dist/mcp/tool-results.d.ts +9 -0
- package/dist/mcp/tool-results.js +64 -0
- package/dist/mcp/tool-surface.js +7 -1
- package/dist/mcp/tools/api-tools.d.ts +50 -0
- package/dist/mcp/tools/api-tools.js +65 -0
- package/dist/mcp/tools/local-project-tools.d.ts +14 -0
- package/dist/mcp/tools/local-project-tools.js +13 -2
- package/dist/mcp/tools/navigation-tools.js +1 -0
- package/dist/mcp/tools/scene-tools.js +7 -0
- package/gemini-extension.json +3 -2
- package/library/references/mcp-tools-reference/mcp-tools-reference.md +15 -2
- package/library/references/mcp-tools-reference/resource.yaml +1 -1
- package/library/skills/README.md +6 -5
- package/library/skills/design-npc/SKILL.md +1 -1
- package/library/skills/design-npc/resource.yaml +2 -1
- package/library/skills/navigate-summer/SKILL.md +23 -2
- package/library/skills/navigate-summer/resource.yaml +5 -3
- package/library/skills/summer-api/SKILL.md +198 -0
- package/library/skills/summer-api/resource.yaml +38 -0
- package/library/skills/summer-assets/SKILL.md +1 -1
- package/library/skills/summer-assets/resource.yaml +3 -2
- package/library/skills/summer-router/SKILL.md +251 -0
- package/library/skills/summer-router/resource.yaml +35 -0
- package/library/tools/api-batch/resource.yaml +82 -0
- package/library/tools/api-estimate/resource.yaml +52 -0
- package/library/tools/api-job/resource.yaml +58 -0
- package/library/tools/api-models/resource.yaml +57 -0
- package/library/tools/api-run/resource.yaml +70 -0
- package/library/tools/view-set/GUIDE.md +3 -0
- package/library/tools/view-set/resource.yaml +78 -0
- package/package.json +3 -3
- package/registry/generated/aliases.json +7 -0
- package/registry/generated/counts.json +3 -3
- package/registry/generated/gemini-extension.json +3 -2
- package/registry/generated/index.json +316 -51
- package/registry/generated/marketplace.claude.json +1 -1
- package/registry/generated/plugin.claude-directory.json +4 -3
- package/registry/generated/plugin.claude.json +3 -2
- package/registry/generated/plugin.codex.json +5 -4
- package/registry/generated/plugin.cursor.json +4 -3
- package/registry/generated/plugin.factory.json +4 -3
- package/registry/generated/server.json +2 -2
- package/registry/generated/skills-index.md +6 -5
- package/registry/generated/skills-registry.json +29 -15
- package/registry/operations/legacy-names.json +30 -0
- package/registry/operations/public-catalog.json +9169 -4926
- package/library/skills/ai-characters-in-games/SKILL.md +0 -235
- package/library/skills/ai-characters-in-games/resource.yaml +0 -30
package/dist/mcp/tool-results.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BATCH_EDIT_TOOLS, SINGLE_EDIT_TOOLS } from "./tool-surface.js";
|
|
2
|
+
import { signInKindForCode, signInLinkText } from "../core/sign-in-link.js";
|
|
2
3
|
/** Pretty-printed JSON text as compact JSON; anything else unchanged. */
|
|
3
4
|
export function compactJsonText(text) {
|
|
4
5
|
const first = text[0];
|
|
@@ -79,3 +80,66 @@ export function singleEditCounter() {
|
|
|
79
80
|
return `Tip: ${run} single scene edits in a row. More than 3 edits: write one summer_run_script instead (snapshot, script, diff, screenshot).`;
|
|
80
81
|
};
|
|
81
82
|
}
|
|
83
|
+
/** The store sign-ins a v4 answer names in error.details.was (core/ops/cloud.ts hostedCallFailure). */
|
|
84
|
+
const STORE_SIGN_IN_WAS = new Set(["store_login_required", "store_login_expired"]);
|
|
85
|
+
/**
|
|
86
|
+
* A v4 cloud answer `not_signed_in` whose cause is the store sign-in (the
|
|
87
|
+
* hosted server's OAuth grant), not the Summer account: the Summer app, for
|
|
88
|
+
* one, is signed in to the account, so only the store approval link helps.
|
|
89
|
+
*/
|
|
90
|
+
function storeSignInAnswer(result) {
|
|
91
|
+
const first = result.content[0];
|
|
92
|
+
if (!first || first.type !== "text" || typeof first.text !== "string")
|
|
93
|
+
return false;
|
|
94
|
+
try {
|
|
95
|
+
const parsed = JSON.parse(first.text);
|
|
96
|
+
const error = parsed?.error;
|
|
97
|
+
return error?.code === "not_signed_in" && typeof error.details?.was === "string" && STORE_SIGN_IN_WAS.has(error.details.was);
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* A `not_signed_in` / `store_login_required` answer gets one more text block:
|
|
105
|
+
* the sign-in link for the person (core/sign-in-link.ts). Anything else, or
|
|
106
|
+
* no link, leaves the result as it is. Never throws.
|
|
107
|
+
*/
|
|
108
|
+
export async function withSignInLink(result, code, links) {
|
|
109
|
+
if (!result || typeof result !== "object" || !Array.isArray(result.content))
|
|
110
|
+
return result;
|
|
111
|
+
const kind = storeSignInAnswer(result) ? "store" : signInKindForCode(code);
|
|
112
|
+
if (!kind)
|
|
113
|
+
return result;
|
|
114
|
+
try {
|
|
115
|
+
const url = await links.link(kind);
|
|
116
|
+
if (!url)
|
|
117
|
+
return result;
|
|
118
|
+
const original = result;
|
|
119
|
+
const text = signInLinkText(kind, url);
|
|
120
|
+
// A JSON answer gets the link inside it (signInUrl, and recovery says what
|
|
121
|
+
// to do), so a caller that parses it (the v4 operation layer runs 3.x
|
|
122
|
+
// tools and reads their JSON) keeps the code and passes the link on.
|
|
123
|
+
const first = original.content[0];
|
|
124
|
+
if (first && first.type === "text" && typeof first.text === "string") {
|
|
125
|
+
try {
|
|
126
|
+
const parsed = JSON.parse(first.text);
|
|
127
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
128
|
+
const answer = parsed;
|
|
129
|
+
const nested = answer.error && typeof answer.error === "object" ? answer.error : null;
|
|
130
|
+
const target = nested && typeof nested.code === "string" ? nested : answer;
|
|
131
|
+
target.signInUrl = url;
|
|
132
|
+
target.recovery = text;
|
|
133
|
+
return { ...original, content: [{ ...first, text: JSON.stringify(answer) }, ...original.content.slice(1)] };
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
// plain text: the link goes in its own block below
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return { ...original, content: [...original.content, { type: "text", text }] };
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
return result;
|
|
144
|
+
}
|
|
145
|
+
}
|
package/dist/mcp/tool-surface.js
CHANGED
|
@@ -37,10 +37,14 @@ const LOCAL_TOOLSETS = {
|
|
|
37
37
|
"summer_get_asset_download_url",
|
|
38
38
|
],
|
|
39
39
|
ship: ["summer_export_game", "summer_export_templates", "summer_publish_build", "summer_go_live", "summer_store_set_details", "summer_capture_gameplay"],
|
|
40
|
-
|
|
40
|
+
// summer_view_set is in the catalog (engine.view_set, summer_call) for every profile.
|
|
41
|
+
ui: ["summer_ui_actions", "summer_ui_activate", "summer_ui_screenshot", "summer_ui_tree", "summer_view_set"],
|
|
41
42
|
// Create and open a project on this computer with no shell (the full profile;
|
|
42
43
|
// the engine profile's clients have a shell, `summer dev`, and a tool cap).
|
|
43
44
|
projects: ["summer_projects_create_local", "summer_projects_open_local"],
|
|
45
|
+
// The Summer API (the assets and full profiles; the engine profile's clients
|
|
46
|
+
// have a shell, `summer login` and `summer api`, and a tool cap).
|
|
47
|
+
tools: ["summer_api_models", "summer_api_estimate", "summer_api_run", "summer_api_batch", "summer_api_job"],
|
|
44
48
|
};
|
|
45
49
|
const localToolset = new Map(Object.entries(LOCAL_TOOLSETS).flatMap(([set, names]) => names.map((name) => [name, set])));
|
|
46
50
|
/** Hosted tool names by pattern, first match wins. Unknown names land in `other` (full only). */
|
|
@@ -185,6 +189,7 @@ const ADDITIVE_OR_TRANSIENT = new Set([
|
|
|
185
189
|
"summer_open_scene",
|
|
186
190
|
"summer_open_main_scene",
|
|
187
191
|
"summer_select_node",
|
|
192
|
+
"summer_view_set",
|
|
188
193
|
"summer_clear_console",
|
|
189
194
|
"summer_play",
|
|
190
195
|
"summer_stop",
|
|
@@ -208,6 +213,7 @@ const IDEMPOTENT_WRITES = new Set([
|
|
|
208
213
|
"summer_open_scene",
|
|
209
214
|
"summer_open_main_scene",
|
|
210
215
|
"summer_select_node",
|
|
216
|
+
"summer_view_set",
|
|
211
217
|
"summer_clear_console",
|
|
212
218
|
"summer_stop",
|
|
213
219
|
"summer_enable_plugin",
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* summer_api_models, summer_api_estimate, summer_api_run, summer_api_batch,
|
|
3
|
+
* summer_api_job — the Summer API (core/summer-api.ts), the same calls as
|
|
4
|
+
* `summer api models|estimate|run|run --batch|jobs`. MCP adapter only: schemas and descriptions here.
|
|
5
|
+
* Runs and jobs use the Summer sign-in on this computer (summer login: Supabase OAuth, refreshed by itself).
|
|
6
|
+
*/
|
|
7
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
export declare const apiModelsInputShape: {
|
|
10
|
+
model: z.ZodOptional<z.ZodString>;
|
|
11
|
+
capability: z.ZodOptional<z.ZodEnum<["image", "3d", "video", "voice", "dialogue", "sound", "music"]>>;
|
|
12
|
+
};
|
|
13
|
+
export declare const apiEstimateInputShape: {
|
|
14
|
+
model: z.ZodString;
|
|
15
|
+
input: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
16
|
+
};
|
|
17
|
+
export declare const apiRunInputShape: {
|
|
18
|
+
model: z.ZodString;
|
|
19
|
+
input: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
20
|
+
quoteId: z.ZodOptional<z.ZodString>;
|
|
21
|
+
idempotencyKey: z.ZodOptional<z.ZodString>;
|
|
22
|
+
wait: z.ZodOptional<z.ZodBoolean>;
|
|
23
|
+
out: z.ZodOptional<z.ZodString>;
|
|
24
|
+
};
|
|
25
|
+
export declare const apiBatchInputShape: {
|
|
26
|
+
jobs: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
27
|
+
model: z.ZodString;
|
|
28
|
+
input: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
29
|
+
idempotencyKey: z.ZodOptional<z.ZodString>;
|
|
30
|
+
}, "strip", z.ZodTypeAny, {
|
|
31
|
+
model: string;
|
|
32
|
+
input?: Record<string, unknown> | undefined;
|
|
33
|
+
idempotencyKey?: string | undefined;
|
|
34
|
+
}, {
|
|
35
|
+
model: string;
|
|
36
|
+
input?: Record<string, unknown> | undefined;
|
|
37
|
+
idempotencyKey?: string | undefined;
|
|
38
|
+
}>, "many">>;
|
|
39
|
+
batchId: z.ZodOptional<z.ZodString>;
|
|
40
|
+
idempotencyKey: z.ZodOptional<z.ZodString>;
|
|
41
|
+
wait: z.ZodOptional<z.ZodBoolean>;
|
|
42
|
+
out: z.ZodOptional<z.ZodString>;
|
|
43
|
+
};
|
|
44
|
+
export declare const apiJobInputShape: {
|
|
45
|
+
jobId: z.ZodString;
|
|
46
|
+
wait: z.ZodOptional<z.ZodBoolean>;
|
|
47
|
+
out: z.ZodOptional<z.ZodString>;
|
|
48
|
+
cancel: z.ZodOptional<z.ZodBoolean>;
|
|
49
|
+
};
|
|
50
|
+
export declare function registerApiTools(server: McpServer): void;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { batchToolResult, cancelJob, checkBatch, createBatch, estimateJob, getBatch, getJob, jobToolResult, listModels, runJob, summerApiToolAnswer, } from "../../core/summer-api.js";
|
|
3
|
+
import { textJson } from "./text-json.js";
|
|
4
|
+
const modelId = z.string().min(1).max(120).describe("A Summer API model id or alias from summer_api_models, e.g. 3d/default.");
|
|
5
|
+
const modelInput = z.record(z.string(), z.unknown()).optional().describe("The model's input, matching its inputSchema from summer_api_models.");
|
|
6
|
+
const out = z.string().min(1).optional().describe("A folder on this computer: save the finished job's files there (implies wait).");
|
|
7
|
+
export const apiModelsInputShape = {
|
|
8
|
+
model: modelId.optional().describe("One model id or alias; without it, every model."),
|
|
9
|
+
capability: z.enum(["image", "3d", "video", "voice", "dialogue", "sound", "music"]).optional().describe("Only this kind."),
|
|
10
|
+
};
|
|
11
|
+
export const apiEstimateInputShape = { model: modelId, input: modelInput };
|
|
12
|
+
export const apiRunInputShape = {
|
|
13
|
+
model: modelId,
|
|
14
|
+
input: modelInput,
|
|
15
|
+
quoteId: z.string().min(1).max(600).optional().describe("From summer_api_estimate: refuse to charge more than it quoted."),
|
|
16
|
+
idempotencyKey: z.string().min(1).max(200).optional().describe("Reuse to retry the same run without running it twice."),
|
|
17
|
+
wait: z.boolean().optional().describe("Follow the job until it finishes (up to about a minute in this call)."),
|
|
18
|
+
out,
|
|
19
|
+
};
|
|
20
|
+
export const apiBatchInputShape = {
|
|
21
|
+
jobs: z
|
|
22
|
+
.array(z.object({
|
|
23
|
+
model: modelId,
|
|
24
|
+
input: modelInput,
|
|
25
|
+
idempotencyKey: z.string().min(1).max(200).optional().describe("This job's own key; by default the batch key and the job's position."),
|
|
26
|
+
}))
|
|
27
|
+
.min(1)
|
|
28
|
+
.max(500)
|
|
29
|
+
.optional()
|
|
30
|
+
.describe("Up to 500 jobs, all or none. Leave out with batchId."),
|
|
31
|
+
batchId: z.string().min(1).max(200).optional().describe("Read a batch summer_api_batch answered, instead of starting one."),
|
|
32
|
+
idempotencyKey: z.string().min(1).max(200).optional().describe("Reuse to retry the same batch without queuing it twice."),
|
|
33
|
+
wait: z.boolean().optional().describe("Follow every job until it finishes (up to about a minute in this call)."),
|
|
34
|
+
out,
|
|
35
|
+
};
|
|
36
|
+
export const apiJobInputShape = {
|
|
37
|
+
jobId: z.string().min(1).max(200).describe("The job id summer_api_run answered."),
|
|
38
|
+
wait: z.boolean().optional().describe("Follow the job until it finishes (up to about a minute in this call)."),
|
|
39
|
+
out,
|
|
40
|
+
cancel: z.boolean().optional().describe("Ask to stop the job instead. Summer API jobs, queued or running, run to the end: the answer is unsupported."),
|
|
41
|
+
};
|
|
42
|
+
const answer = async (work) => {
|
|
43
|
+
const result = await summerApiToolAnswer(work);
|
|
44
|
+
return textJson(result, result.ok === false);
|
|
45
|
+
};
|
|
46
|
+
export function registerApiTools(server) {
|
|
47
|
+
server.tool("summer_api_models", "The Summer API's curated game-dev models: id, capability, input schema, output formats, typical time and price in USD. No sign-in needed. Next: summer_api_estimate for one exact request.", apiModelsInputShape, async (args) => answer(() => listModels(args)));
|
|
48
|
+
server.tool("summer_api_estimate", "The exact USD price of one Summer API job before it runs, what makes it up, and a quoteId that holds the price for 15 minutes. Charges nothing; no sign-in needed. Next: summer_api_run with the quoteId.", apiEstimateInputShape, async (args) => answer(() => estimateJob(args.model, args.input ?? {})));
|
|
49
|
+
server.tool("summer_api_run", "Run one Summer API job into the person's Summer assets with the Summer sign-in on this computer (the person runs summer login first). Spends their paid credits within this app's limit (Connected apps): say what you will make and estimate it first. Short jobs come back done; past the account's running slots a job answers queued at a held price and starts in order. wait follows it, out saves its files on this computer. no_credits (the paid balance) or over_limit (this app's limit): show the person the message and its link.", apiRunInputShape, async (args) => answer(async () => {
|
|
50
|
+
const follow = args.wait === true || typeof args.out === "string";
|
|
51
|
+
const job = await runJob(args.model, args.input ?? {}, {
|
|
52
|
+
...(args.quoteId ? { quoteId: args.quoteId } : {}),
|
|
53
|
+
...(args.idempotencyKey ? { idempotencyKey: args.idempotencyKey } : {}),
|
|
54
|
+
...(follow ? { waitSeconds: 30 } : {}),
|
|
55
|
+
});
|
|
56
|
+
return jobToolResult(job, args);
|
|
57
|
+
}));
|
|
58
|
+
server.tool("summer_api_batch", "Run up to 500 Summer API jobs at once with the Summer sign-in on this computer, all or none: when the person's paid credits and this app's limit (Connected apps) cover every job, all are queued at their held prices and run in order; if not, nothing runs and the error (no_credits or over_limit) says how many fit and how much more is needed (show the person its link). Say what you will make and what it costs first. batchId reads a batch; wait follows it, out saves the finished files on this computer.", apiBatchInputShape, async (args) => answer(async () => {
|
|
59
|
+
if (args.batchId)
|
|
60
|
+
return batchToolResult(await getBatch(args.batchId), args);
|
|
61
|
+
const batch = await createBatch(checkBatch(args.jobs ?? []), args.idempotencyKey ? { idempotencyKey: args.idempotencyKey } : {});
|
|
62
|
+
return batchToolResult(batch, args);
|
|
63
|
+
}));
|
|
64
|
+
server.tool("summer_api_job", "Read a Summer API job: its state (queued, running, done, failed, ...), price and, when done, its assets and Summer file URLs. wait follows it, out saves its files on this computer.", apiJobInputShape, async (args) => answer(async () => (args.cancel ? { job: await cancelJob(args.jobId) } : jobToolResult(await getJob(args.jobId), args))));
|
|
65
|
+
}
|
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
/** The tool call's progress line (notifications/progress), when the client asked for progress. */
|
|
3
|
+
export declare function progressReporter(extra: {
|
|
4
|
+
_meta?: {
|
|
5
|
+
progressToken?: string | number;
|
|
6
|
+
};
|
|
7
|
+
sendNotification?: (notification: {
|
|
8
|
+
method: "notifications/progress";
|
|
9
|
+
params: {
|
|
10
|
+
progressToken: string | number;
|
|
11
|
+
progress: number;
|
|
12
|
+
message?: string;
|
|
13
|
+
};
|
|
14
|
+
}) => Promise<void>;
|
|
15
|
+
} | undefined): ((message: string) => void) | undefined;
|
|
2
16
|
/**
|
|
3
17
|
* projects.create_local and projects.open_local: what `summer dev` does, for
|
|
4
18
|
* agents with no shell (core/capabilities/projects-local.ts).
|
|
@@ -16,6 +16,17 @@ async function localProjectResult(operation) {
|
|
|
16
16
|
throw error;
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
|
+
/** The tool call's progress line (notifications/progress), when the client asked for progress. */
|
|
20
|
+
export function progressReporter(extra) {
|
|
21
|
+
const token = extra?._meta?.progressToken;
|
|
22
|
+
const send = extra?.sendNotification;
|
|
23
|
+
if (token === undefined || !send)
|
|
24
|
+
return undefined;
|
|
25
|
+
let step = 0;
|
|
26
|
+
return (message) => {
|
|
27
|
+
void send({ method: "notifications/progress", params: { progressToken: token, progress: ++step, message } }).catch(() => undefined);
|
|
28
|
+
};
|
|
29
|
+
}
|
|
19
30
|
/**
|
|
20
31
|
* projects.create_local and projects.open_local: what `summer dev` does, for
|
|
21
32
|
* agents with no shell (core/capabilities/projects-local.ts).
|
|
@@ -26,8 +37,8 @@ export function registerLocalProjectTools(server) {
|
|
|
26
37
|
name: z.string().max(80).optional().describe("The project's name and folder name. Default my-game (or the template's name)."),
|
|
27
38
|
dir: z.string().max(1000).optional().describe("The project folder: a new or empty folder, not inside another project; ~ is home. Default <name> next to the session's project, in the session's folder, or in ~/Documents/Summer."),
|
|
28
39
|
}, async (args) => localProjectResult(() => createLocalProject(args, currentMcpEngineSelection()?.cwd)));
|
|
29
|
-
server.tool("summer_projects_open_local", "Open a project on this computer in Summer Engine, in the background, and wait until it connects (an editor that has it open is used as it is); this session's engine tools then work on it. When Summer Engine is not installed it answers engine_not_running: ask the person, and only with their yes call again with install: true (about 660 MB, free). A first open can take a few minutes: the answer says to call again. It adds summer-preview to the session folder's .claude/launch.json (Claude Code Desktop's Browser pane), and preview.url is where the game shows. Next: summer_get_project_context.", {
|
|
40
|
+
server.tool("summer_projects_open_local", "Open a project on this computer in Summer Engine, in the background, and wait until it connects (an editor that has it open is used as it is; an editor with another project open switches to it in the same window); this session's engine tools then work on it. When Summer Engine is not installed it answers engine_not_running: ask the person, and only with their yes call again with install: true (about 660 MB, free). A first open can take a few minutes: the answer says to call again. It adds summer-preview to the session folder's .claude/launch.json (Claude Code Desktop's Browser pane), and preview.url is where the game shows. Next: summer_get_project_context.", {
|
|
30
41
|
path: z.string().max(1000).optional().describe("The project folder (holds project.godot), e.g. projectPath from summer_projects_create_local. Default this session's project."),
|
|
31
42
|
install: z.boolean().default(false).describe("Install Summer Engine first when it is missing. Set true only after the person said yes."),
|
|
32
|
-
}, async (args) => localProjectResult(() => openLocalProject(args, currentMcpEngineSelection(), { log: logEngineSelfStart }, (root, client) => bindMcpProject(root, client))));
|
|
43
|
+
}, async (args, extra) => localProjectResult(() => openLocalProject(args, currentMcpEngineSelection(), { log: logEngineSelfStart, progress: progressReporter(extra) }, (root, client) => bindMcpProject(root, client))));
|
|
33
44
|
}
|
|
@@ -18,6 +18,7 @@ params: slot values — gameId + section (builds, releases, store-page, analytic
|
|
|
18
18
|
open: false resolves only and returns url (+ login_url when the page needs login) or op; nothing opens, no engine needed.
|
|
19
19
|
|
|
20
20
|
Result: { ok, action: opened | printed | listed | ambiguous | unsupported | engine_not_running | engine_error | not_found | invalid_params | open_failed | blocked_origin, target (with availability for editor ids), url, login_url, logged_in, opened_url, op, engine, failure_reason, matches, hint }.
|
|
21
|
+
- Studio pages (/studio...) open in the Summer app's own Studio tab when the running engine advertises the studio destination (op Navigate target studio; result hint says so); otherwise in the browser.
|
|
21
22
|
- Web targets that require login open through /login?returnUrl=<path> when this machine holds no Summer login token (logged_in:false) — the destination loads after sign-in.
|
|
22
23
|
- Editor targets need Summer Engine running with the project open; otherwise action engine_not_running with the op that would have been sent and a 'summer run' hint. Nothing was opened.
|
|
23
24
|
- Editor destinations are forwarded to the engine's own navigation table (op Navigate; ids advertised in /api/health capabilities.navigation). On an engine that predates it, scene/node/script/file and the three docks still work through their original ops; anything else answers action unsupported with failure_reason engine_lacks_op and an update hint. Never claim those opened. Listing (no target) shows each editor id's availability from the connected engine.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { viewSetOp } from "../../core/capabilities/view-set.js";
|
|
1
2
|
import { z } from "zod";
|
|
2
3
|
import { withEngine, ToolInputError } from "./with-engine.js";
|
|
3
4
|
import { executeSceneMutation } from "../../core/capabilities/engine-ops.js";
|
|
@@ -245,6 +246,12 @@ PERSISTENCE IS VERIFIED: the engine's ConnectSignal op connects without CONNECT_
|
|
|
245
246
|
op.scenePath = scenePath;
|
|
246
247
|
return client.executeOps([op]);
|
|
247
248
|
}));
|
|
249
|
+
server.tool("summer_view_set", "Show the person what you are working on: the editor's view (home, chat, 3d, 2d, script, game, studio), its right rail (files, scene, inspector, output, none), what to focus (a res:// script or scene, or a node path) and the nodes to frame the camera on. Changes only what is on screen. The navigate-summer skill says which view fits which moment.", {
|
|
250
|
+
view: z.enum(["home", "chat", "3d", "2d", "script", "game", "studio"]).describe("The view to show"),
|
|
251
|
+
rail: z.enum(["files", "scene", "inspector", "output", "none"]).optional().describe("The right rail; none hides it"),
|
|
252
|
+
focus: z.string().optional().describe("A res:// script or scene, or a node path"),
|
|
253
|
+
frame: z.array(z.string()).optional().describe("Node paths to frame the camera on"),
|
|
254
|
+
}, async ({ view, rail, focus, frame }) => withEngine(async (client) => client.executeOps([viewSetOp({ view, rail, focus, frame })])));
|
|
248
255
|
server.tool("summer_replace_node", `Replace a node with a different scene/model or node type, keeping its parent, sibling index, name, transform and property overrides, and the children the scene added under it. Use it to swap a kit piece for another (a wall host for a door host), a placeholder for a prefab, or a StaticBody3D for a RigidBody3D.
|
|
249
256
|
|
|
250
257
|
Give exactly one of scene or type. The scenePath must be a .tscn.
|
package/gemini-extension.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_generated": "GENERATED from integrations/gemini — do not edit; npm run generate:registry",
|
|
3
3
|
"name": "summer",
|
|
4
|
-
"version": "4.
|
|
4
|
+
"version": "4.8.0",
|
|
5
5
|
"description": "The game engine built for AI. Any agent makes a multiplayer game and publishes it. The Summer Engine MCP server, context primer and game-dev skills.",
|
|
6
6
|
"contextFileName": "GEMINI.md",
|
|
7
7
|
"mcpServers": {
|
|
@@ -27,7 +27,6 @@
|
|
|
27
27
|
"./library/skills/3d-lighting/",
|
|
28
28
|
"./library/skills/adaptive-music/",
|
|
29
29
|
"./library/skills/agent-playtesting/",
|
|
30
|
-
"./library/skills/ai-characters-in-games/",
|
|
31
30
|
"./library/skills/ambient-bed/",
|
|
32
31
|
"./library/skills/animated-loop/",
|
|
33
32
|
"./library/skills/animation-tree/",
|
|
@@ -107,6 +106,7 @@
|
|
|
107
106
|
"./library/skills/store-art/",
|
|
108
107
|
"./library/skills/store-listing/",
|
|
109
108
|
"./library/skills/summer-analytics/",
|
|
109
|
+
"./library/skills/summer-api/",
|
|
110
110
|
"./library/skills/summer-apps/",
|
|
111
111
|
"./library/skills/summer-apps-design/",
|
|
112
112
|
"./library/skills/summer-assets/",
|
|
@@ -117,6 +117,7 @@
|
|
|
117
117
|
"./library/skills/summer-matchmaking/",
|
|
118
118
|
"./library/skills/summer-parties/",
|
|
119
119
|
"./library/skills/summer-player-data/",
|
|
120
|
+
"./library/skills/summer-router/",
|
|
120
121
|
"./library/skills/summer-store/",
|
|
121
122
|
"./library/skills/summer-world-chat/",
|
|
122
123
|
"./library/skills/summer-world-saves/",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
**Rule of thumb:** project reads/writes go through Summer; live hierarchy/inspector changes use scene tools; process-level work remains with the host.
|
|
21
21
|
|
|
22
|
-
## Tool surface (
|
|
22
|
+
## Tool surface (131 tools)
|
|
23
23
|
|
|
24
24
|
### Local projects (2)
|
|
25
25
|
|
|
@@ -93,7 +93,7 @@ No shell needed (Claude Desktop, chat apps); the `summer dev` command does both
|
|
|
93
93
|
|---|---|
|
|
94
94
|
| `summer_fabricate_3d` | Run a Blender Python (bpy) script in the user's OWN installed Blender — headless, engine-supervised — then import the exported `.glb` into `res://` and optionally instantiate it with `target_size`. For modular kits with exact dimensions, VFX meshes (shatter, sweeps, LOD chains), and post-processing generated models (decimate/UV/bake); generic props go to the library and characters to generation. Requires Blender on the machine (never bundled); `blender_not_found` carries the fix. The `fabricating-assets` skill has the bpy rules that survive glTF export. |
|
|
95
95
|
|
|
96
|
-
### Editor UI control (
|
|
96
|
+
### Editor UI control (5)
|
|
97
97
|
|
|
98
98
|
Preview: needs Summer Engine 0.5.66 or newer; older engines return `engine_lacks_op`. Scene work never goes through the editor UI (use the scene, scripting, and perception tools). UI ops are for editor-workflow steps a human does with the mouse — open Project Settings, switch the main screen, clear a blocking dialog, read a dock. Ladder: dedicated tool → named action → tree + activate → screenshot (pixels last, never for coordinates). Quit / project-reload / delete-without-confirm actions are denied by the engine. The `driving-the-editor-ui` skill carries the patterns.
|
|
99
99
|
|
|
@@ -103,6 +103,7 @@ Preview: needs Summer Engine 0.5.66 or newer; older engines return `engine_lacks
|
|
|
103
103
|
| `summer_ui_tree` | Structured Control tree of the live editor UI (class, path, rect, text/tooltip, `checked`/`enabled`/`tabs`/`current_tab`/`value`) from `root:"main" \| "window" \| "dock:<title\|id>" \| "dialog:<title>" \| "path:<node path>"`; `root:"dialogs"` lists every visible dialog/popup with `blocking`, `blocking_dialog`, and its `buttons`. The token-cheap alternative to a screenshot; its paths are what `summer_ui_activate` takes. |
|
|
104
104
|
| `summer_ui_activate` | Activate one control by tree path through its own input path — `press`, `toggle`, `focus`, `select_tab` (incl. `path:"main_screen" value:"3D"`), `set_text` (+`submit`), `set_value` — and `action:"dismiss_dialog"` (by `path` or `title`, `button` cancel/ok/text) to clear a blocking dialog. `state` / `visible_after` are read back after the action, never echoed. |
|
|
105
105
|
| `summer_ui_screenshot` | PNG of the editor window or one dock/dialog/control (`root`, `max_size`) returned as an image — the pixels-last fallback for LOOKING at the editor UI. Not for scene verification (`summer_screenshot`) and never for picking click coordinates. Honest `no_renderer` under a headless editor. |
|
|
106
|
+
| `summer_view_set` (`engine.view_set`) | Show the person what you work on: the frame's view (home, chat, 3D, 2D, script, game, Studio), the right rail, the focus and the nodes to frame. Use it when you start editing a scene or script, play the game, or finish on the best view of the result; not for reading a node (`summer_inspect_node`) or opening a web page (`studio.open`). Needs Summer Engine 4.6 or newer. |
|
|
106
107
|
|
|
107
108
|
### Perception (4)
|
|
108
109
|
|
|
@@ -291,6 +292,18 @@ These come from the hosted Summer server (the one ChatGPT and Claude connect to)
|
|
|
291
292
|
| `summer_docs_search` | Search the library (skills, tools, templates, references, examples, collections) by describing the task in plain words; ranked ids with `matched_by` (lexical / semantic). The first move for any task; works without the engine. |
|
|
292
293
|
| `summer_docs_read` | Load one entry by id: a skill's SKILL.md plus metadata, a tool's call recipe, a template's pin, a reference's body. A body ends with its relative links and the id that loads each; a linked file loads by `<entry id>/<link as written>` (e.g. `skill/spatial-placement/references/kit-placement-tools.md`). The last line is the `entry_id` footer to report through `docs.feedback`. |
|
|
293
294
|
|
|
295
|
+
### Summer API (5)
|
|
296
|
+
|
|
297
|
+
Signed in with `summer login` (one browser sign-in on this computer, renewed by itself; `summer token` prints a one-hour token for the person's own HTTP code). Each app spends the person's paid credits up to the limit they set in Connected apps. No rate limits on paid usage: jobs past the account's running slots (10 at once, up to 40 as it buys credits) answer `queued` and start in order. Money is the only refusal: `no_credits` (the paid balance) or `over_limit` (the app's own limit). The `summer-api` skill has the workflow.
|
|
298
|
+
|
|
299
|
+
| Tool | Use |
|
|
300
|
+
|---|---|
|
|
301
|
+
| `summer_api_models` (`models.list`) | The Summer API's curated game-dev models: id, capability, input schema, output formats, typical time and USD price; `model` for one, `capability` to filter. No sign-in. Shell: `summer api models`. |
|
|
302
|
+
| `summer_api_estimate` (`models.estimate`) | The exact USD price of one job, its breakdown and a `quoteId` that holds it 15 minutes. Charges nothing. Shell: `summer api estimate`. |
|
|
303
|
+
| `summer_api_run` (`models.run`) | Run one job into the person's Summer assets with the Summer sign-in on this computer; spends paid credits within the app's limit. `wait` follows it, `out` saves its files, `quoteId` caps the charge. Shell: `summer api run --wait --download`. |
|
|
304
|
+
| `summer_api_batch` (`POST /v1/batches`) | Run up to 500 jobs at once, all or none: queued at held prices when paid credits and the app's limit cover them all; otherwise nothing runs and the error says how many fit. `batchId` reads a batch; `wait` and `out` as for one job. Shell: `summer api run --batch jobs.jsonl --wait --download`. |
|
|
305
|
+
| `summer_api_job` (`jobs.get`, `jobs.cancel`) | Read a job (state, price, assets and file URLs); `wait`, `out` or `cancel`. Shell: `summer api jobs`. |
|
|
306
|
+
|
|
294
307
|
### Library feedback (1)
|
|
295
308
|
|
|
296
309
|
| Tool | Use |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
id: reference/mcp-tools-reference
|
|
2
2
|
kind: reference
|
|
3
|
-
version: 1.4.
|
|
3
|
+
version: 1.4.3
|
|
4
4
|
summary: Canonical reference for which Summer MCP tool to call — skills should reference tool names exactly as written here.
|
|
5
5
|
use_when:
|
|
6
6
|
- choosing between Summer MCP tools and host tools for an operation
|
package/library/skills/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Summer skills
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> 133 skills, grouped by their primary domain. **Generated** by `npm run generate:registry` from each skill's `resource.yaml`; `--check` fails when this file and the library disagree. Do not edit by hand.
|
|
4
4
|
|
|
5
5
|
The folder is flat on purpose (`docs/design/DECISIONS.md`, D3): a skill usually belongs to several domains, so categories live in each skill's `facets.domains` and this index is rendered from them. The first domain listed is the primary one. `summer skills list --by-domain` prints the same grouping; `summer skills info <slug>` shows one skill.
|
|
6
6
|
|
|
@@ -13,7 +13,7 @@ Status: **stable** unless marked; *preview* = not yet exercised in-engine by the
|
|
|
13
13
|
- [agent-workflow](#agent-workflow) (19)
|
|
14
14
|
- [ai](#ai) (2)
|
|
15
15
|
- [animation](#animation) (7)
|
|
16
|
-
- [assets](#assets) (
|
|
16
|
+
- [assets](#assets) (5)
|
|
17
17
|
- [audio](#audio) (6)
|
|
18
18
|
- [character-controller](#character-controller) (2)
|
|
19
19
|
- [creator](#creator) (7)
|
|
@@ -89,8 +89,8 @@ Status: **stable** unless marked; *preview* = not yet exercised in-engine by the
|
|
|
89
89
|
|
|
90
90
|
| skill | when to use | also |
|
|
91
91
|
|---|---|---|
|
|
92
|
-
| [*ai-characters-in-games*](./ai-characters-in-games/SKILL.md) (preview) | Safe AI characters in published games: no keys in the build, Summer's player AI gateway, moderation, caps. | npc |
|
|
93
92
|
| [design-npc](./design-npc/SKILL.md) ★ | Design enemy, NPC, boss or companion behavior: perception, state machine, telegraphs, script stub. | npc |
|
|
93
|
+
| [*summer-router*](./summer-router/SKILL.md) (preview) | AI characters for games on Summer Games: Summer Router replies, tools, speech, images. | npc, multiplayer |
|
|
94
94
|
|
|
95
95
|
## animation
|
|
96
96
|
|
|
@@ -111,7 +111,8 @@ Status: **stable** unless marked; *preview* = not yet exercised in-engine by the
|
|
|
111
111
|
| [asset-strategy](./asset-strategy/SKILL.md) ★ | Route any 'I need a [thing]' asset request to the right skill: 2D, 3D, audio, video, VFX or animation. | pipeline |
|
|
112
112
|
| [*lumera-single-image-scene-reconstruction*](./lumera-single-image-scene-reconstruction/SKILL.md) (preview) (library only) | Lumera-style single image to editable 3D scene — VLM-parsed object boxes and parametric lights, per-object meshes, HDR probe, .tscn assembly, refinement loop. | pipeline, 3d, scenes |
|
|
113
113
|
| [*skintokens-auto-rigging*](./skintokens-auto-rigging/SKILL.md) (preview) (library only) | Offline auto-rigging with skin-tokens.cpp (GGML SkinTokens/TokenRig port) — skeleton and skin weights from a static GLB mesh on CPU/Vulkan, into Summer Engine. | pipeline, 3d, animation |
|
|
114
|
-
| [summer-
|
|
114
|
+
| [*summer-api*](./summer-api/SKILL.md) (preview) | Summer API game assets: models, estimate, one job or a batch, download the files. | agent-workflow |
|
|
115
|
+
| [summer-assets](./summer-assets/SKILL.md) | Game assets for any engine, no Summer Engine: find, generate and download them. | agent-workflow |
|
|
115
116
|
|
|
116
117
|
## audio
|
|
117
118
|
|
|
@@ -207,7 +208,7 @@ Status: **stable** unless marked; *preview* = not yet exercised in-engine by the
|
|
|
207
208
|
|
|
208
209
|
| skill | when to use | also |
|
|
209
210
|
|---|---|---|
|
|
210
|
-
| [navigate-summer](./navigate-summer/SKILL.md) ★ | Open a Summer
|
|
211
|
+
| [navigate-summer](./navigate-summer/SKILL.md) ★ | Open a Summer page or editor view for the person: studio.open, and engine.view_set while you work. | agent-workflow, meta |
|
|
211
212
|
|
|
212
213
|
## performance
|
|
213
214
|
|
|
@@ -493,7 +493,7 @@ For an animated NPC in a runnable project: `summer create 3d-fps-simple-animated
|
|
|
493
493
|
## See also
|
|
494
494
|
|
|
495
495
|
- `animation-tree` — wire the action states to animation clips
|
|
496
|
-
- `
|
|
496
|
+
- `summer-router` — NPCs that answer free-form player text in a game on Summer Games
|
|
497
497
|
- `vfx-hit-spark` — hit flash recipe
|
|
498
498
|
- `vfx-dissolve` — death dissolve recipe
|
|
499
499
|
- `game-feel` — screen-feel discipline (camera shake, hit-stop)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
id: skill/design-npc
|
|
2
2
|
kind: skill
|
|
3
|
-
version: 1.0.
|
|
3
|
+
version: 1.0.3
|
|
4
4
|
summary: "Design enemy, NPC, boss or companion behavior: perception, state machine, telegraphs, script stub."
|
|
5
5
|
use_when:
|
|
6
6
|
- designing an enemy, NPC, boss, companion, civilian, or wave-spawned mob's behavior — perception, intent, state machine, telegraphs, defeat handling
|
|
@@ -21,6 +21,7 @@ related:
|
|
|
21
21
|
- skill/game-feel
|
|
22
22
|
- skill/vfx-dissolve
|
|
23
23
|
- skill/vfx-hit-spark
|
|
24
|
+
- skill/summer-router
|
|
24
25
|
source: official
|
|
25
26
|
license: MIT
|
|
26
27
|
status: stable
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: navigate-summer
|
|
3
|
-
description: "Open a Summer
|
|
3
|
+
description: "Open a Summer page or editor view for the person: studio.open, and engine.view_set while you work."
|
|
4
4
|
license: MIT
|
|
5
5
|
compatibility: [Cursor, Claude Code, Codex, Windsurf, Gemini, OpenCode, Factory, Copilot]
|
|
6
6
|
category: _meta
|
|
7
7
|
user-invocable: true
|
|
8
|
-
allowed-tools: summer_call summer_get_project_context summer_is_running
|
|
8
|
+
allowed-tools: summer_call summer_get_project_context summer_is_running summer_view_set summer_frame_shot
|
|
9
9
|
paths: ["**/project.godot", "**/*.tscn", "**/.summer/**"]
|
|
10
10
|
---
|
|
11
11
|
|
|
@@ -55,6 +55,26 @@ Use `open: false` (CLI: `--print`) and paste the `url` (or `login_url`) when the
|
|
|
55
55
|
|
|
56
56
|
The editor owns its own table of destinations (the `Navigate` op) and tells the tool which ids it can open. `studio.open({})` lists every editor id with `availability`: `available` (Navigate op), `legacy` (an older engine serving it through its original op), `unavailable` (update Summer Engine), `unknown` (engine not running). Ids: `scene` (default = the project's main scene), `main-scene`, `node`, `script` (with `line`), `file`, `files`, `scene-tree`, `inspector`, `import-dock`, `signals-dock`, `changes-dock`, `screen-2d/3d/script/game/assetlib`, `viewport-show/hide`, `assistant`, `project-settings`, `editor-settings`, `output`, `debugger`, `editor-window`. On a legacy engine, `script` opens without taking focus — mention it if the user does not see it.
|
|
57
57
|
|
|
58
|
+
## While you work: what to open when
|
|
59
|
+
|
|
60
|
+
When you drive Summer Engine from outside (Claude Code, Codex, Cursor, the `summer` CLI), the person is not using the in-app chat. The editor is their window onto your work. A line at the bottom of it names your app and says what you are doing ("Claude Code · Placing 12 trees"). You choose what they see with `engine.view_set` (3.x `summer_view_set`): `view` (`3d`, `2d`, `script`, `game`, `chat`, `home`, `studio`), optional `rail` (`scene`, `inspector`, `files`, `output`, `none`), optional `focus` and optional `frame`. A node path in `focus` selects that node; a `res://` script or scene opens. `frame` lists the nodes to frame the camera on. Switching is instant and changes nothing in the game.
|
|
61
|
+
|
|
62
|
+
| You are about to… | Show |
|
|
63
|
+
|---|---|
|
|
64
|
+
| Edit a scene (place, move, remove nodes) | `{"view": "3d", "rail": "scene", "focus": "<the node or group you edit>", "frame": ["<it>"]}`; a 2D game uses `"2d"` |
|
|
65
|
+
| Write or fix a script | `{"view": "script", "focus": "res://<the script>.gd"}` |
|
|
66
|
+
| Tune one node's properties | `{"view": "3d", "rail": "inspector", "focus": "<that node>"}` |
|
|
67
|
+
| Playtest | `{"view": "game"}`, then play the game |
|
|
68
|
+
| Review how it looks | a `summer_frame_shot` of the result |
|
|
69
|
+
| Read errors or logs with the person | `{"view": "3d", "rail": "output"}` |
|
|
70
|
+
| Finish | the best view of the result: the game in `game` for gameplay work, the framed scene in `3d` or `2d` for level and art work, the script for code-only changes |
|
|
71
|
+
|
|
72
|
+
- Open the view before the first edit of a step, so the person watches the change happen.
|
|
73
|
+
- Focus what you change, not the scene root; for a group, focus its parent.
|
|
74
|
+
- Make one call when the kind of work changes, not one per edit.
|
|
75
|
+
- End on the result, never on an empty or unrelated view.
|
|
76
|
+
- When the person is using the in-app chat, let them choose the view.
|
|
77
|
+
|
|
58
78
|
## Anti-patterns
|
|
59
79
|
|
|
60
80
|
- Opening `billing` or `pricing` when the user asked about a **feature**, not money.
|
|
@@ -75,6 +95,7 @@ No Summer MCP tools in this session? Run each one as a command; when `summer --v
|
|
|
75
95
|
| `summer_is_running` | `summer engine is-running` |
|
|
76
96
|
| `summer_play` | `summer engine play` |
|
|
77
97
|
| `summer_screenshot` | `summer engine screenshot` |
|
|
98
|
+
| `engine.view_set`, `summer_view_set` | `summer engine view-set` |
|
|
78
99
|
| `store.publish` | `summer store publish` |
|
|
79
100
|
| `studio.open`, `summer_open` | `summer studio open` |
|
|
80
101
|
<!-- /shell-commands -->
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
id: skill/navigate-summer
|
|
2
2
|
kind: skill
|
|
3
|
-
version: 1.0.
|
|
4
|
-
summary: "Open a Summer
|
|
3
|
+
version: 1.0.1
|
|
4
|
+
summary: "Open a Summer page or editor view for the person: studio.open, and engine.view_set while you work."
|
|
5
5
|
use_when:
|
|
6
6
|
- the user asks to see, check, or decide something — "show me my billing", "where do I change my plan", "open my games", "let me look at the scene", "take me to the MCP guide for Cursor"
|
|
7
|
-
- deciding whether to open a surface for the user or to do the work through Summer tools
|
|
7
|
+
- deciding whether to open a surface (a page of the website) for the user or to do the work through Summer tools or an API
|
|
8
8
|
- handing the user a link (headless, remote, or the user prefers a link) instead of launching a browser
|
|
9
|
+
- "you drive Summer Engine from outside (Claude Code, Codex, Cursor, the summer CLI) and the editor should show what you work on: the view, rail and focus for editing, scripting, playtesting, review and the end result"
|
|
9
10
|
do_not_use_when:
|
|
10
11
|
- the user wants a change made — add/set/remove nodes, publish, generate; use the build skills and mutation tools
|
|
11
12
|
- opening a project directory in the engine — `summer run <path>`
|
|
@@ -25,6 +26,7 @@ compatibility:
|
|
|
25
26
|
related:
|
|
26
27
|
tools:
|
|
27
28
|
- tool/open
|
|
29
|
+
- tool/view-set
|
|
28
30
|
references:
|
|
29
31
|
- reference/product-map
|
|
30
32
|
skills:
|