summer-engine 3.6.0 → 3.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 +2 -2
- package/.claude-plugin/plugin.json +4 -2
- package/.codex-plugin/plugin.json +5 -3
- package/.cursor-plugin/plugin.json +4 -2
- package/.factory-plugin/plugin.json +4 -2
- package/CHANGELOG.md +24 -0
- package/README.md +11 -5
- package/commands/summer.md +2 -1
- package/dist/cli/commands/login.d.ts +0 -10
- package/dist/cli/commands/login.js +2 -82
- package/dist/cli/index.js +0 -4
- package/dist/core/auth.d.ts +0 -8
- package/dist/core/auth.js +5 -35
- package/dist/core/capabilities/apps.d.ts +318 -0
- package/dist/core/capabilities/apps.js +340 -0
- package/dist/core/capabilities/enable-plugin.d.ts +27 -0
- package/dist/core/capabilities/enable-plugin.js +75 -0
- package/dist/core/capabilities/seeing/args.d.ts +2 -2
- package/dist/core/capabilities/seeing/seeing.d.ts +1 -1
- package/dist/core/capabilities/sfx-choices.d.ts +2 -15
- package/dist/core/capabilities/sfx-choices.js +26 -64
- package/dist/core/capabilities/tool-dispatch.js +51 -54
- package/dist/core/capability-skew.js +4 -0
- package/dist/core/config.d.ts +1 -7
- package/dist/core/config.js +5 -75
- package/dist/mcp/hosted-mount.js +13 -1
- package/dist/mcp/server.d.ts +2 -1
- package/dist/mcp/server.js +8 -5
- package/dist/mcp/tools/app-tools.d.ts +2 -0
- package/dist/mcp/tools/app-tools.js +64 -0
- package/dist/mcp/tools/creator-tools.js +0 -71
- package/dist/mcp/tools/generate-tools.js +6 -7
- package/gemini-extension.json +3 -1
- package/library/references/mcp-tools-reference/mcp-tools-reference.md +24 -5
- package/library/skills/README.md +10 -2
- package/library/skills/publish-your-game/SKILL.md +2 -0
- package/library/skills/sound-effect/SKILL.md +2 -0
- package/library/skills/summer-apps/SKILL.md +152 -0
- package/library/skills/summer-apps/manifest.md +57 -0
- package/library/skills/summer-apps/minimal-app.md +183 -0
- package/library/skills/summer-apps/resource.yaml +36 -0
- package/library/skills/summer-apps/sdk-reference.md +135 -0
- package/library/skills/summer-apps-design/SKILL.md +197 -0
- package/library/skills/summer-apps-design/resource.yaml +23 -0
- package/library/skills/using-summer/SKILL.md +1 -0
- package/library/tools/app-call/resource.yaml +59 -0
- package/library/tools/app-create/resource.yaml +67 -0
- package/library/tools/app-data/resource.yaml +74 -0
- package/library/tools/app-dock/resource.yaml +59 -0
- package/library/tools/app-events/resource.yaml +68 -0
- package/library/tools/app-get/resource.yaml +46 -0
- package/library/tools/app-guide/resource.yaml +55 -0
- package/library/tools/app-list/resource.yaml +48 -0
- package/library/tools/app-page/resource.yaml +74 -0
- package/library/tools/app-publish/resource.yaml +90 -0
- package/library/tools/app-report-gap/resource.yaml +58 -0
- package/library/tools/app-screenshot/resource.yaml +85 -0
- package/library/tools/app-tools/resource.yaml +46 -0
- package/library/tools/app-update/resource.yaml +68 -0
- package/library/tools/enable-plugin/resource.yaml +53 -0
- package/library/tools/generate-sfx-choices/resource.yaml +2 -2
- package/package.json +1 -1
- package/registry/generated/aliases.json +15 -3
- package/registry/generated/counts.json +3 -3
- package/registry/generated/gemini-extension.json +3 -1
- package/registry/generated/index.json +759 -209
- package/registry/generated/marketplace.claude.json +2 -2
- package/registry/generated/plugin.claude.json +4 -2
- package/registry/generated/plugin.codex.json +5 -3
- package/registry/generated/plugin.cursor.json +4 -2
- package/registry/generated/plugin.factory.json +4 -2
- package/registry/generated/skills-index.md +10 -2
- package/registry/generated/skills-registry.json +27 -0
- package/registry/schemas/allowed-hosts.json +4 -2
- package/dist/cli/commands/publish.d.ts +0 -2
- package/dist/cli/commands/publish.js +0 -21
- package/dist/cli/commands/releases.d.ts +0 -2
- package/dist/cli/commands/releases.js +0 -20
- package/dist/core/capabilities/creator.d.ts +0 -65
- package/dist/core/capabilities/creator.js +0 -374
- package/library/tools/creator-config/resource.yaml +0 -63
- package/library/tools/creator-publish/resource.yaml +0 -74
- package/library/tools/creator-releases/resource.yaml +0 -53
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* summer_enable_plugin: enable an editor plugin (`res://addons/<name>/`) and
|
|
4
|
+
* report what really happened. Engines with Summer Apps support run the
|
|
5
|
+
* EnableEditorPlugin op until the plugin's `_enter_tree` has run and answer
|
|
6
|
+
* `enabled` (or a failure `code`); older engines only queue the enable and
|
|
7
|
+
* answer `deferred: true`, so this tool says the result is unknown instead of
|
|
8
|
+
* claiming success. One implementation for the MCP tool and `summer tool
|
|
9
|
+
* enable-plugin`.
|
|
10
|
+
*/
|
|
11
|
+
export declare const enablePluginArgsSchema: z.ZodObject<{
|
|
12
|
+
plugin: z.ZodString;
|
|
13
|
+
timeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
14
|
+
}, "strip", z.ZodTypeAny, {
|
|
15
|
+
plugin: string;
|
|
16
|
+
timeoutMs?: number | undefined;
|
|
17
|
+
}, {
|
|
18
|
+
plugin: string;
|
|
19
|
+
timeoutMs?: number | undefined;
|
|
20
|
+
}>;
|
|
21
|
+
export declare function enablePluginOp(args: z.output<typeof enablePluginArgsSchema>): {
|
|
22
|
+
op: string;
|
|
23
|
+
[key: string]: unknown;
|
|
24
|
+
};
|
|
25
|
+
export declare const QUEUED_ONLY_NOTE: string;
|
|
26
|
+
/** The engine's answer for EnableEditorPlugin, as one result an agent can trust. */
|
|
27
|
+
export declare function interpretEnablePluginResult(raw: unknown): Record<string, unknown>;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { asRecord } from "../util/json.js";
|
|
3
|
+
import { extractOpError } from "./engine-receipt.js";
|
|
4
|
+
/**
|
|
5
|
+
* summer_enable_plugin: enable an editor plugin (`res://addons/<name>/`) and
|
|
6
|
+
* report what really happened. Engines with Summer Apps support run the
|
|
7
|
+
* EnableEditorPlugin op until the plugin's `_enter_tree` has run and answer
|
|
8
|
+
* `enabled` (or a failure `code`); older engines only queue the enable and
|
|
9
|
+
* answer `deferred: true`, so this tool says the result is unknown instead of
|
|
10
|
+
* claiming success. One implementation for the MCP tool and `summer tool
|
|
11
|
+
* enable-plugin`.
|
|
12
|
+
*/
|
|
13
|
+
export const enablePluginArgsSchema = z.object({
|
|
14
|
+
plugin: z
|
|
15
|
+
.string()
|
|
16
|
+
.min(1)
|
|
17
|
+
.max(200)
|
|
18
|
+
.describe("The plugin folder under res://addons/ (e.g. 'quest_tools') or its 'res://addons/<name>/plugin.cfg'"),
|
|
19
|
+
timeoutMs: z
|
|
20
|
+
.number()
|
|
21
|
+
.int()
|
|
22
|
+
.min(1000)
|
|
23
|
+
.max(120_000)
|
|
24
|
+
.optional()
|
|
25
|
+
.describe("How long the engine waits for the plugin to load (default 30000)"),
|
|
26
|
+
});
|
|
27
|
+
export function enablePluginOp(args) {
|
|
28
|
+
return { op: "EnableEditorPlugin", pluginPath: args.plugin.trim(), ...(args.timeoutMs ? { timeoutMs: args.timeoutMs } : {}) };
|
|
29
|
+
}
|
|
30
|
+
const FAILURE_HINTS = {
|
|
31
|
+
CFG_MISSING: "No plugin.cfg there. Check the folder name under res://addons/.",
|
|
32
|
+
CFG_PARSE_FAILED: "plugin.cfg does not parse. Fix it and enable again.",
|
|
33
|
+
NO_SCRIPT_KEY: "plugin.cfg needs a script= entry under [plugin].",
|
|
34
|
+
EMPTY_SCRIPT_PATH: "plugin.cfg needs a script= entry under [plugin].",
|
|
35
|
+
SCRIPT_MISSING: "The script plugin.cfg names does not exist.",
|
|
36
|
+
SCRIPT_LOAD_FAILED: "The plugin script did not load. Read summer_get_script_errors for it.",
|
|
37
|
+
SCRIPT_ERROR: "The plugin script has errors. Read summer_get_script_errors, fix them, and enable again.",
|
|
38
|
+
NOT_EDITOR_PLUGIN: "The plugin script must extend EditorPlugin.",
|
|
39
|
+
NOT_TOOL: "The plugin script must start with @tool.",
|
|
40
|
+
TIMEOUT: "The plugin did not finish loading in time (often a filesystem scan). Try again, or raise timeoutMs.",
|
|
41
|
+
};
|
|
42
|
+
export const QUEUED_ONLY_NOTE = "This Summer Engine build only queues the enable and does not report whether the plugin loaded. " +
|
|
43
|
+
"Check summer_get_debugger_errors and summer_get_script_errors for the plugin script before relying on it, or update Summer Engine for the real result.";
|
|
44
|
+
/** The engine's answer for EnableEditorPlugin, as one result an agent can trust. */
|
|
45
|
+
export function interpretEnablePluginResult(raw) {
|
|
46
|
+
const root = asRecord(raw) ?? {};
|
|
47
|
+
const results = Array.isArray(root.results) ? root.results : [];
|
|
48
|
+
const entry = asRecord(results.find((item) => asRecord(item)?.op === "EnableEditorPlugin") ?? results[0]) ?? root;
|
|
49
|
+
const addonPath = typeof entry.addonPath === "string" ? entry.addonPath : undefined;
|
|
50
|
+
const error = extractOpError(raw) ?? (entry.ok === false ? String(entry.error ?? "The plugin was not enabled.") : null);
|
|
51
|
+
if (error) {
|
|
52
|
+
const code = typeof entry.code === "string" ? entry.code : undefined;
|
|
53
|
+
return {
|
|
54
|
+
ok: false,
|
|
55
|
+
enabled: false,
|
|
56
|
+
...(addonPath ? { addonPath } : {}),
|
|
57
|
+
...(code ? { code } : {}),
|
|
58
|
+
error,
|
|
59
|
+
...(code && FAILURE_HINTS[code] ? { hint: FAILURE_HINTS[code] } : {}),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
if (entry.alreadyEnabled === true)
|
|
63
|
+
return { ok: true, enabled: true, alreadyEnabled: true, ...(addonPath ? { addonPath } : {}) };
|
|
64
|
+
if (entry.enabled === true) {
|
|
65
|
+
return {
|
|
66
|
+
ok: true,
|
|
67
|
+
enabled: true,
|
|
68
|
+
...(addonPath ? { addonPath } : {}),
|
|
69
|
+
autoloadsRegistered: Array.isArray(entry.autoloadsRegistered) ? entry.autoloadsRegistered : [],
|
|
70
|
+
...(typeof entry.elapsedMs === "number" ? { elapsedMs: entry.elapsedMs } : {}),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
// Older engines: { ok: true, deferred: true } means "scheduled", not "loaded".
|
|
74
|
+
return { ok: true, enabled: null, queued: true, ...(addonPath ? { addonPath } : {}), note: QUEUED_ONLY_NOTE };
|
|
75
|
+
}
|
|
@@ -306,7 +306,7 @@ export declare const frameShotArgsSchema: z.ZodObject<{
|
|
|
306
306
|
render: z.ZodOptional<z.ZodEnum<["sheet", "best", "none"]>>;
|
|
307
307
|
max_size: z.ZodOptional<z.ZodNumber>;
|
|
308
308
|
}, "strict", z.ZodTypeAny, {
|
|
309
|
-
shot: "
|
|
309
|
+
shot: "establishing" | "eye_level" | "low_angle" | "detail" | "corridor";
|
|
310
310
|
spawn?: string | undefined;
|
|
311
311
|
scenePath?: string | undefined;
|
|
312
312
|
fov?: number | undefined;
|
|
@@ -326,7 +326,7 @@ export declare const frameShotArgsSchema: z.ZodObject<{
|
|
|
326
326
|
max_soft_fraction?: number | undefined;
|
|
327
327
|
save_bookmark?: boolean | undefined;
|
|
328
328
|
}, {
|
|
329
|
-
shot: "
|
|
329
|
+
shot: "establishing" | "eye_level" | "low_angle" | "detail" | "corridor";
|
|
330
330
|
spawn?: string | undefined;
|
|
331
331
|
scenePath?: string | undefined;
|
|
332
332
|
fov?: number | undefined;
|
|
@@ -230,4 +230,4 @@ export interface CorridorScanFloor {
|
|
|
230
230
|
}
|
|
231
231
|
export declare function scanFloorText(floor: CorridorScanFloor, subject: Aabb): string;
|
|
232
232
|
export declare function frameShot(client: SeeingClient, args: FrameShotArgs): Promise<SeeingResult>;
|
|
233
|
-
export declare const SHOT_TYPE_DEFAULTS: Record<"
|
|
233
|
+
export declare const SHOT_TYPE_DEFAULTS: Record<"establishing" | "eye_level" | "low_angle" | "detail" | "corridor", import("./candidates.js").ShotDefaults>;
|
|
@@ -7,6 +7,8 @@ import { z } from "zod";
|
|
|
7
7
|
* POST /api/mcp/generate/audio/choices makes the versions and a choice set,
|
|
8
8
|
* the person listens and approves one or more on the Studio page
|
|
9
9
|
* /studio/choices/<id>, and GET /api/mcp/choices/<id> reads the decision.
|
|
10
|
+
* The server queues the page for the person's open Studio tab itself
|
|
11
|
+
* (studioTab.queued); only when no tab took it does this open a browser.
|
|
10
12
|
* An approval makes that model the person's default for later
|
|
11
13
|
* summer_generate_audio sound_effects calls without a modelId.
|
|
12
14
|
*
|
|
@@ -58,17 +60,9 @@ export interface GatewayReply {
|
|
|
58
60
|
error?: string;
|
|
59
61
|
status: number;
|
|
60
62
|
}
|
|
61
|
-
export type StudioOpenOutcome = {
|
|
62
|
-
ok: true;
|
|
63
|
-
} | {
|
|
64
|
-
ok: false;
|
|
65
|
-
reason: string;
|
|
66
|
-
};
|
|
67
63
|
export interface SfxChoicesDeps {
|
|
68
64
|
post(endpoint: string, body: Record<string, unknown>, timeoutMs: number): Promise<GatewayReply>;
|
|
69
65
|
get(endpoint: string, params: URLSearchParams, timeoutMs: number): Promise<GatewayReply>;
|
|
70
|
-
/** Move the person's open Studio tab to a /studio path (reviewUrl: the same page as a full URL). */
|
|
71
|
-
studioOpen(path: string, reviewUrl: string): Promise<StudioOpenOutcome>;
|
|
72
66
|
openUrl(url: string): Promise<unknown>;
|
|
73
67
|
canOpenBrowser(): boolean;
|
|
74
68
|
}
|
|
@@ -77,13 +71,6 @@ export type ShownIn = "studio_tab" | "browser" | "not_opened";
|
|
|
77
71
|
export declare function canOpenReviewUrl(url: string): boolean;
|
|
78
72
|
/** False where a browser launch cannot reach the person: CI, or Linux with no display. */
|
|
79
73
|
export declare function defaultCanOpenBrowser(env?: NodeJS.ProcessEnv, platform?: NodeJS.Platform): boolean;
|
|
80
|
-
/**
|
|
81
|
-
* Move the person's open Studio tab through the hosted Summer Engine MCP's
|
|
82
|
-
* summer_studio_open (needs the store sign-in). Only for the production site:
|
|
83
|
-
* the hosted MCP moves tabs on summerengine.com, so a review page on another
|
|
84
|
-
* origin (a preview deploy, local web dev) is opened in the browser instead.
|
|
85
|
-
*/
|
|
86
|
-
export declare function openInStudioTab(path: string, reviewUrl: string): Promise<StudioOpenOutcome>;
|
|
87
74
|
export declare function sfxChoicesRequestBody(args: z.output<typeof sfxChoicesArgsSchema>): Record<string, unknown>;
|
|
88
75
|
export declare function generateSfxChoices(args: z.output<typeof sfxChoicesArgsSchema>, deps: SfxChoicesDeps): Promise<Record<string, unknown>>;
|
|
89
76
|
export declare function choicesEndpoint(choiceSetId: string): string;
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { hasStoreSignIn, hostedResultPayload, withHostedMcp } from "../hosted-mcp.js";
|
|
3
|
-
import { resolveMcpResourceUrl } from "../oauth.js";
|
|
4
2
|
/**
|
|
5
3
|
* Sound-effect choices (summer_generate_sfx_choices + summer_get_choices).
|
|
6
4
|
*
|
|
@@ -9,6 +7,8 @@ import { resolveMcpResourceUrl } from "../oauth.js";
|
|
|
9
7
|
* POST /api/mcp/generate/audio/choices makes the versions and a choice set,
|
|
10
8
|
* the person listens and approves one or more on the Studio page
|
|
11
9
|
* /studio/choices/<id>, and GET /api/mcp/choices/<id> reads the decision.
|
|
10
|
+
* The server queues the page for the person's open Studio tab itself
|
|
11
|
+
* (studioTab.queued); only when no tab took it does this open a browser.
|
|
12
12
|
* An approval makes that model the person's default for later
|
|
13
13
|
* summer_generate_audio sound_effects calls without a modelId.
|
|
14
14
|
*
|
|
@@ -22,7 +22,6 @@ export const CHOICES_ENDPOINT_PREFIX = "/api/mcp/choices/";
|
|
|
22
22
|
/** Three models run in parallel on the server; the slowest decides. */
|
|
23
23
|
export const SFX_CHOICES_TIMEOUT_MS = 240_000;
|
|
24
24
|
export const MAX_CHOICES_WAIT_SECONDS = 50;
|
|
25
|
-
const STUDIO_OPEN_TIMEOUT_MS = 20_000;
|
|
26
25
|
export const sfxChoicesArgsSchema = z.object({
|
|
27
26
|
text: z
|
|
28
27
|
.string()
|
|
@@ -48,7 +47,7 @@ export const sfxChoicesArgsSchema = z.object({
|
|
|
48
47
|
open: z
|
|
49
48
|
.boolean()
|
|
50
49
|
.default(true)
|
|
51
|
-
.describe("Show the choices page
|
|
50
|
+
.describe("Show the choices page in the browser when no open Studio tab took it. false: no browser, only return the URL"),
|
|
52
51
|
});
|
|
53
52
|
export const getChoicesArgsSchema = z.object({
|
|
54
53
|
choiceSetId: z.string().min(1).max(200).describe("The choiceSetId from summer_generate_sfx_choices"),
|
|
@@ -90,70 +89,28 @@ export function defaultCanOpenBrowser(env = process.env, platform = process.plat
|
|
|
90
89
|
return false;
|
|
91
90
|
return true;
|
|
92
91
|
}
|
|
93
|
-
/**
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
let resource;
|
|
103
|
-
try {
|
|
104
|
-
resource = resolveMcpResourceUrl();
|
|
105
|
-
}
|
|
106
|
-
catch {
|
|
107
|
-
return { ok: false, reason: "hosted_mcp_url_invalid" };
|
|
108
|
-
}
|
|
109
|
-
if (!isSummerHost(hostOf(resource)))
|
|
110
|
-
return { ok: false, reason: "hosted_mcp_not_summerengine_com" };
|
|
111
|
-
if (!(await hasStoreSignIn()))
|
|
112
|
-
return { ok: false, reason: "no_store_sign_in" };
|
|
113
|
-
let timer;
|
|
114
|
-
const timeout = new Promise((resolve) => {
|
|
115
|
-
timer = setTimeout(() => resolve({ ok: false, reason: "studio_tab_timeout" }), STUDIO_OPEN_TIMEOUT_MS);
|
|
116
|
-
timer.unref?.();
|
|
117
|
-
});
|
|
118
|
-
const attempt = (async () => {
|
|
119
|
-
try {
|
|
120
|
-
const result = await withHostedMcp((client) => client.callTool({ name: "summer_studio_open", arguments: { path } }));
|
|
121
|
-
const payload = hostedResultPayload(result);
|
|
122
|
-
if (payload.isError || payload.json?.ok === false) {
|
|
123
|
-
const code = typeof payload.json?.error === "string" ? payload.json.error : "studio_open_failed";
|
|
124
|
-
return { ok: false, reason: code };
|
|
125
|
-
}
|
|
126
|
-
return { ok: true };
|
|
127
|
-
}
|
|
128
|
-
catch (error) {
|
|
129
|
-
return { ok: false, reason: error instanceof Error ? error.message : String(error) };
|
|
130
|
-
}
|
|
131
|
-
})();
|
|
132
|
-
try {
|
|
133
|
-
return await Promise.race([attempt, timeout]);
|
|
134
|
-
}
|
|
135
|
-
finally {
|
|
136
|
-
clearTimeout(timer);
|
|
137
|
-
}
|
|
92
|
+
/** The server's studioTab answer: queued for the person's open tab, or why not. Missing on older servers. */
|
|
93
|
+
function studioTabAnswer(value) {
|
|
94
|
+
if (!value || typeof value !== "object")
|
|
95
|
+
return null;
|
|
96
|
+
const record = value;
|
|
97
|
+
return {
|
|
98
|
+
queued: record.queued === true,
|
|
99
|
+
...(typeof record.reason === "string" ? { reason: record.reason } : {}),
|
|
100
|
+
};
|
|
138
101
|
}
|
|
139
|
-
async function showChoicesPage(reviewUrl,
|
|
140
|
-
|
|
141
|
-
if (studioPath) {
|
|
142
|
-
const moved = await deps.studioOpen(studioPath, reviewUrl);
|
|
143
|
-
if (moved.ok)
|
|
144
|
-
return { shown: "studio_tab" };
|
|
145
|
-
studioTab = moved.reason;
|
|
146
|
-
}
|
|
102
|
+
async function showChoicesPage(reviewUrl, studioTab, deps) {
|
|
103
|
+
const notQueued = studioTab ? (studioTab.reason ?? "not_queued") : undefined;
|
|
147
104
|
if (!canOpenReviewUrl(reviewUrl))
|
|
148
|
-
return { shown: "not_opened", studioTab, browser: "not_a_summer_url" };
|
|
105
|
+
return { shown: "not_opened", studioTab: notQueued, browser: "not_a_summer_url" };
|
|
149
106
|
if (!deps.canOpenBrowser())
|
|
150
|
-
return { shown: "not_opened", studioTab, browser: "no_browser_here" };
|
|
107
|
+
return { shown: "not_opened", studioTab: notQueued, browser: "no_browser_here" };
|
|
151
108
|
try {
|
|
152
109
|
await deps.openUrl(reviewUrl);
|
|
153
|
-
return { shown: "browser", studioTab };
|
|
110
|
+
return { shown: "browser", studioTab: notQueued };
|
|
154
111
|
}
|
|
155
112
|
catch (error) {
|
|
156
|
-
return { shown: "not_opened", studioTab, browser: error instanceof Error ? error.message : String(error) };
|
|
113
|
+
return { shown: "not_opened", studioTab: notQueued, browser: error instanceof Error ? error.message : String(error) };
|
|
157
114
|
}
|
|
158
115
|
}
|
|
159
116
|
// ---------------------------------------------------------------------------
|
|
@@ -198,9 +155,14 @@ export async function generateSfxChoices(args, deps) {
|
|
|
198
155
|
hint: "Read failed[] for each model's error. Fix the request (a longer durationSeconds, a plainer description) or call summer_generate_audio with one modelId.",
|
|
199
156
|
};
|
|
200
157
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
158
|
+
// The server queued the Studio-tab open already; that happens even with
|
|
159
|
+
// open:false, so report it rather than hide it.
|
|
160
|
+
const studioTab = studioTabAnswer(data.studioTab);
|
|
161
|
+
const shown = studioTab?.queued
|
|
162
|
+
? { shown: "studio_tab" }
|
|
163
|
+
: args.open
|
|
164
|
+
? await showChoicesPage(reviewUrl, studioTab, deps)
|
|
165
|
+
: { shown: "not_opened", browser: "open_false" };
|
|
204
166
|
const count = clips.length;
|
|
205
167
|
const where = shown.shown === "studio_tab"
|
|
206
168
|
? "I opened them in your Summer Studio tab"
|
|
@@ -30,7 +30,7 @@ import { lookupApiDocs } from "./api-docs.js";
|
|
|
30
30
|
import { BOARD_ENDPOINT, boardArgsSchema, boardQuery } from "./board.js";
|
|
31
31
|
import { IMAGE_GENERATION_TIMEOUT_MS, imageGenerationArgsSchema, saveGeneratedImage } from "./image-generation.js";
|
|
32
32
|
import { buildMotionRequestBody, motionGenerationArgsSchema } from "./motion-generation.js";
|
|
33
|
-
import { defaultCanOpenBrowser, generateSfxChoices, getChoices, getChoicesArgsSchema,
|
|
33
|
+
import { defaultCanOpenBrowser, generateSfxChoices, getChoices, getChoicesArgsSchema, sfxChoicesArgsSchema, } from "./sfx-choices.js";
|
|
34
34
|
import { ImportHdriError, importHdriArgsSchema, importPolyHavenHdri } from "./hdri-import.js";
|
|
35
35
|
import { FABRICATE_FALLBACK, buildFabricateMeshOp, fabricateArgsSchema } from "./fabricate-mesh.js";
|
|
36
36
|
import { buildUiActionsOp, buildUiActivateOp, buildUiScreenshotOp, buildUiTreeOp, executeUiOp, uiActionsArgsSchema, uiActivateArgsSchema, uiScreenshotArgsSchema, uiScreenshotCaption, uiScreenshotImage, uiTreeArgsSchema, withUiFailureDetails, } from "./ui-control.js";
|
|
@@ -47,12 +47,11 @@ import { getAuthToken } from "../auth.js";
|
|
|
47
47
|
import open from "open";
|
|
48
48
|
import { openArgsSchema, runOpen } from "./navigation/open.js";
|
|
49
49
|
import { shapeEngineLogResponse } from "../log-filters.js";
|
|
50
|
-
import { listCreatorReleases, publishCreator, } from "./creator.js";
|
|
51
50
|
import { exportGame } from "./export-game.js";
|
|
52
51
|
import { exportTemplates } from "./export-templates.js";
|
|
53
52
|
import { captureGameplay } from "./capture-gameplay.js";
|
|
54
53
|
import { publishBuild } from "./publish-build.js";
|
|
55
|
-
import {
|
|
54
|
+
import { resolveGatewayUrl } from "../config.js";
|
|
56
55
|
import { createDebugReportArtifact } from "./debug-report.js";
|
|
57
56
|
import { buildGameTaskPlan, gameTaskPlanInputSchema } from "./game-task-plan.js";
|
|
58
57
|
import { buildProjectContext, projectContextInputSchema, projectSettingValue, } from "./project-context.js";
|
|
@@ -77,6 +76,8 @@ import { attachToSurface, attachToSurfaceArgsSchema, connectPorts, connectPortsA
|
|
|
77
76
|
import { readLibraryEntry, readLibraryInputSchema } from "../library-read.js";
|
|
78
77
|
import { runSearchLibrary, searchLibraryInputSchema } from "../library-search.js";
|
|
79
78
|
import { TOOLKIT_VERSION as CLI_VERSION } from "../version.js";
|
|
79
|
+
import { APP_DOCK_FALLBACK, appCall, appCallArgsSchema, appCreate, appCreateArgsSchema, appData, appDataArgsSchema, appDockArgsSchema, appDockOp, appEvents, appEventsArgsSchema, appGet, appGetArgsSchema, appGuide, appGuideArgsSchema, appList, appListArgsSchema, appPage, appPageArgsSchema, appScreenshot, appScreenshotArgsSchema, appUpdate, appUpdateArgsSchema, appPublish, appPublishArgsSchema, appReportGap, appReportGapArgsSchema, appsGateway, appTools, appToolsArgsSchema, } from "./apps.js";
|
|
80
|
+
import { enablePluginArgsSchema, enablePluginOp, interpretEnablePluginResult } from "./enable-plugin.js";
|
|
80
81
|
/** Dispatch-level failure with a user-facing message (no stack needed). */
|
|
81
82
|
export class ToolDispatchError extends Error {
|
|
82
83
|
}
|
|
@@ -405,11 +406,18 @@ async function gatewayReply(call) {
|
|
|
405
406
|
return { error: error.message, status: 0 };
|
|
406
407
|
}
|
|
407
408
|
}
|
|
409
|
+
/** summer tool app-screenshot: the PNG goes to `out` (default ./summer-app-screenshot.png), not into the printed JSON. */
|
|
410
|
+
async function cliScreenshot(args, deps) {
|
|
411
|
+
const shot = await appScreenshot({ ...args, out: args.out ?? "summer-app-screenshot.png" }, deps);
|
|
412
|
+
if (shot.ok !== true || !("image" in shot))
|
|
413
|
+
return shot;
|
|
414
|
+
const { image: _image, ...report } = shot;
|
|
415
|
+
return report;
|
|
416
|
+
}
|
|
408
417
|
function sfxChoicesDeps() {
|
|
409
418
|
return {
|
|
410
419
|
post: (endpoint, body, timeoutMs) => gatewayReply(() => gatewayPost(endpoint, body, timeoutMs)),
|
|
411
420
|
get: (endpoint, params, timeoutMs) => gatewayReply(() => gatewayGet(endpoint, params, timeoutMs)),
|
|
412
|
-
studioOpen: (path, reviewUrl) => openInStudioTab(path, reviewUrl),
|
|
413
421
|
openUrl: (url) => open(url),
|
|
414
422
|
canOpenBrowser: () => defaultCanOpenBrowser(),
|
|
415
423
|
};
|
|
@@ -674,56 +682,6 @@ export const TOOL_DISPATCH = [
|
|
|
674
682
|
...(typeof args.waitSeconds === "number" ? { waitSeconds: args.waitSeconds } : {}),
|
|
675
683
|
face: "cli",
|
|
676
684
|
})),
|
|
677
|
-
entry("summer_creator_publish", "Deprecated: publish a .pck to the legacy creator API; use publish-build", false, (args) => publishCreator({
|
|
678
|
-
project: optStr(args, "project"),
|
|
679
|
-
artifact: optStr(args, "artifact"),
|
|
680
|
-
version: optStr(args, "version"),
|
|
681
|
-
manifest: optStr(args, "manifest"),
|
|
682
|
-
projectId: optStr(args, "projectId"),
|
|
683
|
-
channel: optStr(args, "channel"),
|
|
684
|
-
notes: optStr(args, "notes"),
|
|
685
|
-
confirm: args.confirm === true,
|
|
686
|
-
face: "cli",
|
|
687
|
-
})),
|
|
688
|
-
entry("summer_creator_releases", "Deprecated: list releases on the legacy creator API; use summer_store_releases", false, (args) => listCreatorReleases({
|
|
689
|
-
projectId: optStr(args, "projectId"),
|
|
690
|
-
limit: typeof args.limit === "number" ? args.limit : 20,
|
|
691
|
-
cursor: optStr(args, "cursor"),
|
|
692
|
-
face: "cli",
|
|
693
|
-
})),
|
|
694
|
-
entry("summer_creator_config", "Read or update the shared non-secret Summer configuration", false, async (args) => {
|
|
695
|
-
const action = str(args, "action");
|
|
696
|
-
if (action === "list") {
|
|
697
|
-
const config = await readSummerConfig();
|
|
698
|
-
return {
|
|
699
|
-
ok: true,
|
|
700
|
-
values: Object.fromEntries(CONFIG_KEYS.map((name) => [name, getConfigValue(config, name) ?? null])),
|
|
701
|
-
};
|
|
702
|
-
}
|
|
703
|
-
const key = optStr(args, "key");
|
|
704
|
-
if (!key || !isConfigKey(key)) {
|
|
705
|
-
throw new ToolDispatchError(`A valid key is required. Use one of ${CONFIG_KEYS.join(", ")}.`);
|
|
706
|
-
}
|
|
707
|
-
if (action === "get") {
|
|
708
|
-
return { ok: true, key, value: getConfigValue(await readSummerConfig(), key) ?? null };
|
|
709
|
-
}
|
|
710
|
-
if (args.confirm !== true) {
|
|
711
|
-
throw new ToolDispatchError(`Changing ${key} requires confirmation. Retry with "confirm": true after the user approves the exact change.`);
|
|
712
|
-
}
|
|
713
|
-
if (action === "set") {
|
|
714
|
-
const value = optStr(args, "value");
|
|
715
|
-
if (value === undefined) {
|
|
716
|
-
throw new ToolDispatchError(`A value is required for ${key}.`);
|
|
717
|
-
}
|
|
718
|
-
const config = await setConfigValue(key, value);
|
|
719
|
-
return { ok: true, key, value: getConfigValue(config, key) };
|
|
720
|
-
}
|
|
721
|
-
if (action === "unset") {
|
|
722
|
-
const config = await unsetConfigValue(key);
|
|
723
|
-
return { ok: true, key, value: getConfigValue(config, key) ?? null };
|
|
724
|
-
}
|
|
725
|
-
throw new ToolDispatchError(`Unknown action "${action}". Use list, get, set, or unset.`);
|
|
726
|
-
}),
|
|
727
685
|
// --- debug ---
|
|
728
686
|
entry("summer_get_diagnostics", "Overview of editor console and runtime debugger errors/warnings", true, async (args, ctx) => requireEngineSuccess(await (await ctx.engine()).getDiagnostics())),
|
|
729
687
|
entry("summer_get_console", "Read recent editor Output panel messages (deduplicated)", true, async (args, ctx) => {
|
|
@@ -958,6 +916,45 @@ export const TOOL_DISPATCH = [
|
|
|
958
916
|
throw new ToolResultError(result, String(result.error));
|
|
959
917
|
return result;
|
|
960
918
|
}),
|
|
919
|
+
// Summer Apps (core/capabilities/apps.ts): the same functions as the MCP face.
|
|
920
|
+
...[
|
|
921
|
+
["summer_app_guide", "Read the Summer Apps build guide (SDK, manifest, kit, layout, design, examples)", appGuideArgsSchema, appGuide],
|
|
922
|
+
["summer_app_list", "List the Summer Apps in the person's workspaces", appListArgsSchema, appList],
|
|
923
|
+
["summer_app_create", "Create a scratch Summer App and open it in Summer Studio", appCreateArgsSchema, appCreate],
|
|
924
|
+
["summer_app_publish", "Publish a new version of a Summer App from a folder or files", appPublishArgsSchema, appPublish],
|
|
925
|
+
["summer_app_get", "Read a Summer App's manifest, files and data summary", appGetArgsSchema, appGet],
|
|
926
|
+
["summer_app_update", "Rename a Summer App or keep, archive or restore it", appUpdateArgsSchema, appUpdate],
|
|
927
|
+
["summer_app_events", "Wait for events a Summer App sends to agents", appEventsArgsSchema, appEvents],
|
|
928
|
+
["summer_app_page", "Read or use the open app's declared fields and buttons", appPageArgsSchema, appPage],
|
|
929
|
+
["summer_app_data", "Read or write a Summer App's shared data", appDataArgsSchema, appData],
|
|
930
|
+
["summer_app_screenshot", "See a Summer App rendered (read-only) with its console and errors; out saves the PNG", appScreenshotArgsSchema, cliScreenshot],
|
|
931
|
+
["summer_app_tools", "List a Summer App's agent tools", appToolsArgsSchema, appTools],
|
|
932
|
+
["summer_app_call", "Run a Summer App's agent tool in the person's open app", appCallArgsSchema, appCall],
|
|
933
|
+
["summer_app_report_gap", "Report an SDK capability a Summer App needed", appReportGapArgsSchema, appReportGap],
|
|
934
|
+
].map(([name, summary, schema, run]) => entry(name, summary, false, async (args) => {
|
|
935
|
+
const result = await run(parseToolArgs(schema, args, name.replace(/^summer_/, "").replace(/_/g, "-")), { request: appsGateway("cli", name) });
|
|
936
|
+
if (result.ok !== true)
|
|
937
|
+
throw new ToolResultError(result, String(result.error));
|
|
938
|
+
return result;
|
|
939
|
+
})),
|
|
940
|
+
entry("summer_enable_plugin", "Enable an editor plugin and report whether it really loaded", true, async (args, ctx) => {
|
|
941
|
+
const parsed = parseToolArgs(enablePluginArgsSchema, args, "enable-plugin");
|
|
942
|
+
const result = interpretEnablePluginResult(await (await ctx.engine()).executeOps([enablePluginOp(parsed)]));
|
|
943
|
+
if (result.ok !== true)
|
|
944
|
+
throw new ToolResultError(result, String(result.error));
|
|
945
|
+
return result;
|
|
946
|
+
}),
|
|
947
|
+
entry("summer_app_dock", "Dock a Summer App in the editor, close its dock, or list docks", true, async (args, ctx) => {
|
|
948
|
+
const parsed = parseToolArgs(appDockArgsSchema, args, "app-dock");
|
|
949
|
+
if (parsed.action !== "list" && !parsed.appId)
|
|
950
|
+
throw new ToolDispatchError(`${parsed.action} needs appId`);
|
|
951
|
+
const op = appDockOp(parsed);
|
|
952
|
+
const client = await ctx.engine();
|
|
953
|
+
const missing = missingEngineOpResult(client, op.op, APP_DOCK_FALLBACK);
|
|
954
|
+
if (missing)
|
|
955
|
+
throw new ToolResultError({ ...missing }, missing.error);
|
|
956
|
+
return requireEngineSuccess(await client.executeOps([op]));
|
|
957
|
+
}),
|
|
961
958
|
entry("summer_generate_3d", "Generate a 3D model (optional auto-rig + animations)", false, async (args) => {
|
|
962
959
|
const options = {
|
|
963
960
|
...(args.options ?? {}),
|
|
@@ -49,6 +49,10 @@ export const CLI_KNOWN_OP_NEEDS = [
|
|
|
49
49
|
// engine's one-table op; the other three are the legacy
|
|
50
50
|
// fallbacks on engines that predate it.
|
|
51
51
|
"Navigate", "OpenResource", "FocusDock", "RevealInFileSystem",
|
|
52
|
+
// Summer Apps editor docks (summer_app_dock: core/capabilities/apps.ts)
|
|
53
|
+
"OpenAppDock", "CloseAppDock", "ListAppDocks",
|
|
54
|
+
// summer_enable_plugin (core/capabilities/enable-plugin.ts)
|
|
55
|
+
"EnableEditorPlugin",
|
|
52
56
|
// Project + input
|
|
53
57
|
"ProjectSetting", "InputMapAddAction", "InputMapBind",
|
|
54
58
|
// Files (summer_write_file / summer_replace_text / summer_create_scene)
|
package/dist/core/config.d.ts
CHANGED
|
@@ -3,13 +3,8 @@ export interface SummerConfig {
|
|
|
3
3
|
gateway?: {
|
|
4
4
|
url?: string;
|
|
5
5
|
};
|
|
6
|
-
creator?: {
|
|
7
|
-
apiUrl?: string;
|
|
8
|
-
projectId?: string;
|
|
9
|
-
channel?: string;
|
|
10
|
-
};
|
|
11
6
|
}
|
|
12
|
-
export declare const CONFIG_KEYS: readonly ["gateway.url"
|
|
7
|
+
export declare const CONFIG_KEYS: readonly ["gateway.url"];
|
|
13
8
|
export type ConfigKey = (typeof CONFIG_KEYS)[number];
|
|
14
9
|
export declare function readSummerConfig(): Promise<SummerConfig>;
|
|
15
10
|
export declare function getConfigValue(config: SummerConfig, key: ConfigKey): string | undefined;
|
|
@@ -27,4 +22,3 @@ export declare function isConfigKey(value: string): value is ConfigKey;
|
|
|
27
22
|
* Returns an origin-like base without a trailing slash.
|
|
28
23
|
*/
|
|
29
24
|
export declare function resolveGatewayUrl(): Promise<string>;
|
|
30
|
-
export declare function getCreatorApiUrl(): Promise<string>;
|
package/dist/core/config.js
CHANGED
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
import { readStoreJson, writeStoreJson } from "./store.js";
|
|
2
2
|
const CONFIG_FILE = "config.json";
|
|
3
3
|
const DEFAULT_GATEWAY_URL = "https://www.summerengine.com";
|
|
4
|
-
const
|
|
5
|
-
export const CONFIG_KEYS = [
|
|
6
|
-
"gateway.url",
|
|
7
|
-
"creator.apiUrl",
|
|
8
|
-
"creator.projectId",
|
|
9
|
-
"creator.channel",
|
|
10
|
-
];
|
|
4
|
+
export const CONFIG_KEYS = ["gateway.url"];
|
|
11
5
|
function emptyConfig() {
|
|
12
6
|
return { schemaVersion: 1 };
|
|
13
7
|
}
|
|
@@ -39,90 +33,30 @@ function validateGatewayUrl(value) {
|
|
|
39
33
|
}
|
|
40
34
|
return parsed.toString().replace(/\/+$/, "");
|
|
41
35
|
}
|
|
42
|
-
function validateCreatorApiUrl(value) {
|
|
43
|
-
let parsed;
|
|
44
|
-
try {
|
|
45
|
-
parsed = new URL(value);
|
|
46
|
-
}
|
|
47
|
-
catch {
|
|
48
|
-
throw new Error('creator.apiUrl must be a complete URL. Recovery: use "summer config set creator.apiUrl https://summercraft.ai".');
|
|
49
|
-
}
|
|
50
|
-
const local = parsed.hostname === "localhost" ||
|
|
51
|
-
parsed.hostname === "127.0.0.1" ||
|
|
52
|
-
parsed.hostname === "[::1]";
|
|
53
|
-
if (parsed.protocol !== "https:" && !(local && parsed.protocol === "http:")) {
|
|
54
|
-
throw new Error("creator.apiUrl must use HTTPS (HTTP is allowed only for localhost). Recovery: set an HTTPS URL and retry.");
|
|
55
|
-
}
|
|
56
|
-
if (parsed.username ||
|
|
57
|
-
parsed.password ||
|
|
58
|
-
parsed.pathname !== "/" ||
|
|
59
|
-
parsed.search ||
|
|
60
|
-
parsed.hash) {
|
|
61
|
-
throw new Error("creator.apiUrl must be an origin without credentials, a path, query parameters, or fragments.");
|
|
62
|
-
}
|
|
63
|
-
return parsed.origin;
|
|
64
|
-
}
|
|
65
36
|
function validateValue(key, value) {
|
|
66
37
|
const clean = value.trim();
|
|
67
38
|
if (!clean) {
|
|
68
39
|
throw new Error(`Cannot set ${key} to an empty value. Recovery: provide a value, or run "summer config unset ${key}".`);
|
|
69
40
|
}
|
|
70
|
-
|
|
71
|
-
return validateGatewayUrl(clean);
|
|
72
|
-
if (key === "creator.apiUrl")
|
|
73
|
-
return validateCreatorApiUrl(clean);
|
|
74
|
-
if (key === "creator.channel" && !/^[a-z0-9][a-z0-9._-]{0,63}$/i.test(clean)) {
|
|
75
|
-
throw new Error("creator.channel may contain letters, numbers, dots, underscores, and hyphens. Recovery: choose a channel such as production or preview.");
|
|
76
|
-
}
|
|
77
|
-
if (key === "creator.projectId" && clean.length > 128) {
|
|
78
|
-
throw new Error("creator.projectId is too long. Recovery: copy the project ID from the Summer creator dashboard and retry.");
|
|
79
|
-
}
|
|
80
|
-
return clean;
|
|
41
|
+
return validateGatewayUrl(clean);
|
|
81
42
|
}
|
|
82
43
|
export function getConfigValue(config, key) {
|
|
83
|
-
|
|
84
|
-
return config.gateway?.url;
|
|
85
|
-
if (key === "creator.apiUrl")
|
|
86
|
-
return config.creator?.apiUrl;
|
|
87
|
-
if (key === "creator.projectId")
|
|
88
|
-
return config.creator?.projectId;
|
|
89
|
-
return config.creator?.channel;
|
|
44
|
+
return config.gateway?.url;
|
|
90
45
|
}
|
|
91
46
|
export async function setConfigValue(key, rawValue) {
|
|
92
47
|
const config = await readSummerConfig();
|
|
93
48
|
const value = validateValue(key, rawValue);
|
|
94
|
-
|
|
95
|
-
config.gateway = { ...config.gateway, url: value };
|
|
96
|
-
}
|
|
97
|
-
else if (key === "creator.apiUrl") {
|
|
98
|
-
config.creator = { ...config.creator, apiUrl: value };
|
|
99
|
-
}
|
|
100
|
-
else if (key === "creator.projectId") {
|
|
101
|
-
config.creator = { ...config.creator, projectId: value };
|
|
102
|
-
}
|
|
103
|
-
else {
|
|
104
|
-
config.creator = { ...config.creator, channel: value };
|
|
105
|
-
}
|
|
49
|
+
config.gateway = { ...config.gateway, url: value };
|
|
106
50
|
await writeStoreJson(CONFIG_FILE, config);
|
|
107
51
|
return config;
|
|
108
52
|
}
|
|
109
53
|
export async function unsetConfigValue(key) {
|
|
110
54
|
const config = await readSummerConfig();
|
|
111
|
-
if (
|
|
55
|
+
if (config.gateway)
|
|
112
56
|
delete config.gateway.url;
|
|
113
|
-
if (key === "creator.apiUrl" && config.creator)
|
|
114
|
-
delete config.creator.apiUrl;
|
|
115
|
-
if (key === "creator.projectId" && config.creator) {
|
|
116
|
-
delete config.creator.projectId;
|
|
117
|
-
}
|
|
118
|
-
if (key === "creator.channel" && config.creator)
|
|
119
|
-
delete config.creator.channel;
|
|
120
57
|
if (config.gateway && Object.keys(config.gateway).length === 0) {
|
|
121
58
|
delete config.gateway;
|
|
122
59
|
}
|
|
123
|
-
if (config.creator && Object.keys(config.creator).length === 0) {
|
|
124
|
-
delete config.creator;
|
|
125
|
-
}
|
|
126
60
|
await writeStoreJson(CONFIG_FILE, config);
|
|
127
61
|
return config;
|
|
128
62
|
}
|
|
@@ -147,7 +81,3 @@ export async function resolveGatewayUrl() {
|
|
|
147
81
|
const configured = config.gateway?.url?.trim();
|
|
148
82
|
return configured ? validateGatewayUrl(configured) : DEFAULT_GATEWAY_URL;
|
|
149
83
|
}
|
|
150
|
-
export async function getCreatorApiUrl() {
|
|
151
|
-
const config = await readSummerConfig();
|
|
152
|
-
return config.creator?.apiUrl ?? DEFAULT_CREATOR_API_URL;
|
|
153
|
-
}
|
package/dist/mcp/hosted-mount.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
1
|
+
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { connectHostedMcp } from "../core/hosted-mcp.js";
|
|
4
4
|
import { getStoreAccessToken, OAuthError, resolveMcpResourceUrl } from "../core/oauth.js";
|
|
@@ -79,6 +79,18 @@ export function prepareHostedMount(server, deps = defaultHostedMountDependencies
|
|
|
79
79
|
};
|
|
80
80
|
});
|
|
81
81
|
}
|
|
82
|
+
// tools/call for a name the server does not know yet: a hosted tool whose mount
|
|
83
|
+
// is still running (an agent that calls before it lists). Wait for that mount,
|
|
84
|
+
// at most the first-list cap, then dispatch; an unknown name still errors.
|
|
85
|
+
const callTool = handlers.get("tools/call");
|
|
86
|
+
if (callTool) {
|
|
87
|
+
server.server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
88
|
+
const name = request.params?.name;
|
|
89
|
+
if (typeof name === "string" && !(name in registries._registeredTools))
|
|
90
|
+
await waitForMount(firstListWaitMs);
|
|
91
|
+
return (await callTool(request, extra));
|
|
92
|
+
});
|
|
93
|
+
}
|
|
82
94
|
let statusTool = null;
|
|
83
95
|
let running = null;
|
|
84
96
|
/** Wait for a mount in progress, at most ms; returns at once when none runs. */
|
package/dist/mcp/server.d.ts
CHANGED
|
@@ -11,7 +11,8 @@ export declare const getCachedBootDriftNotice: typeof getCachedNotice;
|
|
|
11
11
|
* turn and would otherwise learn the hard way. Kept under 600 characters so
|
|
12
12
|
* it costs a few hundred tokens once; the full operating guide stays in the
|
|
13
13
|
* summer_agent_playbook prompt / summer_get_agent_playbook tool. The last
|
|
14
|
-
* sentence names the publishing path
|
|
14
|
+
* sentence names the publishing path, the owner-approval rule and where
|
|
15
|
+
* review feedback is read.
|
|
15
16
|
*/
|
|
16
17
|
export declare const SUMMER_MCP_INSTRUCTIONS: string;
|
|
17
18
|
export declare function configureMcpEngineSelection(selection?: EngineSelection): void;
|