summer-engine 3.2.0 → 3.3.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.
Files changed (61) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +2 -2
  3. package/.codex-plugin/plugin.json +3 -3
  4. package/.cursor-plugin/plugin.json +2 -2
  5. package/.factory-plugin/plugin.json +2 -2
  6. package/CHANGELOG.md +30 -0
  7. package/README.md +27 -12
  8. package/dist/cli/commands/login.js +12 -0
  9. package/dist/cli/commands/publish.js +2 -1
  10. package/dist/core/auth.js +3 -0
  11. package/dist/core/capabilities/audit/args.d.ts +14 -14
  12. package/dist/core/capabilities/engine-run.d.ts +8 -0
  13. package/dist/core/capabilities/engine-run.js +33 -0
  14. package/dist/core/capabilities/export-game.d.ts +99 -0
  15. package/dist/core/capabilities/export-game.js +369 -0
  16. package/dist/core/capabilities/export-presets.d.ts +50 -0
  17. package/dist/core/capabilities/export-presets.js +177 -0
  18. package/dist/core/capabilities/export-templates.d.ts +118 -0
  19. package/dist/core/capabilities/export-templates.js +291 -0
  20. package/dist/core/capabilities/publish-build.d.ts +64 -0
  21. package/dist/core/capabilities/publish-build.js +448 -0
  22. package/dist/core/capabilities/publish-download.d.ts +37 -0
  23. package/dist/core/capabilities/publish-download.js +168 -0
  24. package/dist/core/capabilities/runtime-control.d.ts +10 -10
  25. package/dist/core/capabilities/summer-bundle.d.ts +49 -0
  26. package/dist/core/capabilities/summer-bundle.js +156 -0
  27. package/dist/core/capabilities/tool-dispatch.js +33 -1
  28. package/dist/core/capabilities/ui-control.d.ts +2 -2
  29. package/dist/core/library-read.d.ts +2 -2
  30. package/dist/core/oauth.d.ts +78 -0
  31. package/dist/core/oauth.js +309 -0
  32. package/dist/core/util/zip-write.d.ts +18 -0
  33. package/dist/core/util/zip-write.js +112 -0
  34. package/dist/core/util/zip.d.ts +22 -0
  35. package/dist/core/util/zip.js +140 -0
  36. package/dist/mcp/hosted-mount.d.ts +96 -0
  37. package/dist/mcp/hosted-mount.js +206 -0
  38. package/dist/mcp/server.d.ts +2 -1
  39. package/dist/mcp/server.js +13 -6
  40. package/dist/mcp/tools/creator-tools.js +54 -1
  41. package/gemini-extension.json +1 -1
  42. package/library/references/mcp-tools-reference/mcp-tools-reference.md +6 -3
  43. package/library/skills/export-and-ship/SKILL.md +2 -0
  44. package/library/skills/multiplayer-publish/SKILL.md +5 -1
  45. package/library/skills/navigate-summer/SKILL.md +1 -1
  46. package/library/tools/creator-publish/resource.yaml +4 -3
  47. package/library/tools/creator-releases/resource.yaml +1 -1
  48. package/library/tools/export-game/resource.yaml +72 -0
  49. package/library/tools/export-templates/resource.yaml +63 -0
  50. package/library/tools/open/resource.yaml +1 -1
  51. package/library/tools/publish-build/resource.yaml +78 -0
  52. package/package.json +1 -1
  53. package/registry/generated/aliases.json +3 -0
  54. package/registry/generated/counts.json +2 -2
  55. package/registry/generated/gemini-extension.json +1 -1
  56. package/registry/generated/index.json +119 -10
  57. package/registry/generated/marketplace.claude.json +2 -2
  58. package/registry/generated/plugin.claude.json +2 -2
  59. package/registry/generated/plugin.codex.json +3 -3
  60. package/registry/generated/plugin.cursor.json +2 -2
  61. package/registry/generated/plugin.factory.json +2 -2
@@ -97,14 +97,14 @@ export declare const runtimeSetArgsSchema: z.ZodObject<{
97
97
  field: z.ZodOptional<z.ZodString>;
98
98
  instance: z.ZodOptional<z.ZodString>;
99
99
  }, "strip", z.ZodTypeAny, {
100
- path: string;
101
100
  value: string | number | boolean;
101
+ path: string;
102
102
  property: string;
103
103
  instance?: string | undefined;
104
104
  field?: string | undefined;
105
105
  }, {
106
- path: string;
107
106
  value: string | number | boolean;
107
+ path: string;
108
108
  property: string;
109
109
  instance?: string | undefined;
110
110
  field?: string | undefined;
@@ -117,13 +117,13 @@ export declare const runtimeCallArgsSchema: z.ZodObject<{
117
117
  args: z.ZodOptional<z.ZodArray<z.ZodUnknown, "many">>;
118
118
  instance: z.ZodOptional<z.ZodString>;
119
119
  }, "strip", z.ZodTypeAny, {
120
- path: string;
121
120
  method: string;
121
+ path: string;
122
122
  args?: unknown[] | undefined;
123
123
  instance?: string | undefined;
124
124
  }, {
125
- path: string;
126
125
  method: string;
126
+ path: string;
127
127
  args?: unknown[] | undefined;
128
128
  instance?: string | undefined;
129
129
  }>;
@@ -183,13 +183,13 @@ export declare const runtimeAnimateArgsSchema: z.ZodObject<{
183
183
  }, "strip", z.ZodTypeAny, {
184
184
  path: string;
185
185
  target: "tree" | "player" | "bones";
186
+ state?: string | undefined;
187
+ value?: string | number | boolean | undefined;
186
188
  instance?: string | undefined;
187
189
  name?: string | undefined;
188
- value?: string | number | boolean | undefined;
189
- cmd?: "pause" | "play" | "stop" | "state" | "seek" | "speed" | "travel" | "start" | "set_param" | "get_param" | undefined;
190
+ cmd?: "state" | "pause" | "play" | "stop" | "seek" | "speed" | "travel" | "start" | "set_param" | "get_param" | undefined;
190
191
  space?: "local" | "global" | "both" | undefined;
191
192
  blend?: number | undefined;
192
- state?: string | undefined;
193
193
  position?: number | undefined;
194
194
  speed?: number | undefined;
195
195
  bones?: string[] | undefined;
@@ -202,13 +202,13 @@ export declare const runtimeAnimateArgsSchema: z.ZodObject<{
202
202
  }, {
203
203
  path: string;
204
204
  target: "tree" | "player" | "bones";
205
+ state?: string | undefined;
206
+ value?: string | number | boolean | undefined;
205
207
  instance?: string | undefined;
206
208
  name?: string | undefined;
207
- value?: string | number | boolean | undefined;
208
- cmd?: "pause" | "play" | "stop" | "state" | "seek" | "speed" | "travel" | "start" | "set_param" | "get_param" | undefined;
209
+ cmd?: "state" | "pause" | "play" | "stop" | "seek" | "speed" | "travel" | "start" | "set_param" | "get_param" | undefined;
209
210
  space?: "local" | "global" | "both" | undefined;
210
211
  blend?: number | undefined;
211
- state?: string | undefined;
212
212
  position?: number | undefined;
213
213
  speed?: number | undefined;
214
214
  bones?: string[] | undefined;
@@ -0,0 +1,49 @@
1
+ /**
2
+ * The summer.games export (summer-platform ADR 0033): one .zip with
3
+ * summer-bundle.json, client.pck, and for a game with a host server.pck plus
4
+ * config/. This reads what the build upload declares; the Platform verifies
5
+ * the uploaded bytes again. Same rules as Studio's browser check
6
+ * (publicsummerengine src/lib/creator-store/pck-check.ts, checkBundle).
7
+ */
8
+ export declare const BUNDLE_SCHEMA = "summer.bundle.v1";
9
+ export declare const BUNDLE_MANIFEST = "summer-bundle.json";
10
+ /** A failure with a stable code, a plain message and the next step. */
11
+ export declare class BuildToolError extends Error {
12
+ readonly code: string;
13
+ readonly recovery: string;
14
+ readonly status?: number | undefined;
15
+ readonly detail?: Record<string, unknown> | undefined;
16
+ constructor(code: string, message: string, recovery: string, status?: number | undefined, detail?: Record<string, unknown> | undefined);
17
+ }
18
+ export interface BundleFile {
19
+ path: string;
20
+ sha256: string;
21
+ size: number;
22
+ }
23
+ export interface SummerBundle {
24
+ schema: typeof BUNDLE_SCHEMA;
25
+ summerVersion: string | null;
26
+ engineSha: string | null;
27
+ /** res:// scene the client pack opens. */
28
+ mainScene: string;
29
+ /** Client platforms the export was made for (ios, macos, windows, ...). */
30
+ targetPlatforms: string[];
31
+ /** True when the game has a host (server.pck + config/summer.build.json). */
32
+ hosted: boolean;
33
+ compositionPath: string | null;
34
+ /** client.pck as summer-bundle.json lists it ("sha256:<hex>"). */
35
+ clientPack: {
36
+ sha256: string;
37
+ size: number;
38
+ };
39
+ /** Hosted only: config/summer.build.json, sent as the Build declaration. */
40
+ hostedBuild?: Record<string, unknown>;
41
+ files: BundleFile[];
42
+ }
43
+ /** Read and check summer-bundle.json in an exported .zip. */
44
+ export declare function readSummerBundle(path: string): Promise<SummerBundle>;
45
+ /** "sha256:<hex>" and size of a whole file, streamed. */
46
+ export declare function hashFile(path: string): Promise<{
47
+ sha256: string;
48
+ sizeBytes: number;
49
+ }>;
@@ -0,0 +1,156 @@
1
+ import { createHash } from "node:crypto";
2
+ import { createReadStream } from "node:fs";
3
+ import { readZipEntries, readZipEntry, ZipReadError } from "../util/zip.js";
4
+ /**
5
+ * The summer.games export (summer-platform ADR 0033): one .zip with
6
+ * summer-bundle.json, client.pck, and for a game with a host server.pck plus
7
+ * config/. This reads what the build upload declares; the Platform verifies
8
+ * the uploaded bytes again. Same rules as Studio's browser check
9
+ * (publicsummerengine src/lib/creator-store/pck-check.ts, checkBundle).
10
+ */
11
+ export const BUNDLE_SCHEMA = "summer.bundle.v1";
12
+ export const BUNDLE_MANIFEST = "summer-bundle.json";
13
+ const BUNDLE_CLIENT = "client.pck";
14
+ const BUNDLE_SERVER = "server.pck";
15
+ const BUNDLE_BUILD = "config/summer.build.json";
16
+ const SHA256 = /^sha256:[0-9a-f]{64}$/;
17
+ const AS_EXPORTED = "Recovery: export the game again with the summer.games preset and use the .zip exactly as Summer Engine wrote it.";
18
+ /** A failure with a stable code, a plain message and the next step. */
19
+ export class BuildToolError extends Error {
20
+ code;
21
+ recovery;
22
+ status;
23
+ detail;
24
+ constructor(code, message, recovery, status, detail) {
25
+ super(`${message} ${recovery}`);
26
+ this.code = code;
27
+ this.recovery = recovery;
28
+ this.status = status;
29
+ this.detail = detail;
30
+ this.name = "BuildToolError";
31
+ }
32
+ }
33
+ function bundleError(message) {
34
+ return new BuildToolError("bundle_invalid", message, AS_EXPORTED);
35
+ }
36
+ /** Read and check summer-bundle.json in an exported .zip. */
37
+ export async function readSummerBundle(path) {
38
+ let entries;
39
+ try {
40
+ entries = await readZipEntries(path);
41
+ }
42
+ catch (error) {
43
+ throw bundleError(`${path} is not a readable summer.games export (${error instanceof Error ? error.message : String(error)}).`);
44
+ }
45
+ const byName = new Map(entries.map((entry) => [entry.name, entry]));
46
+ const manifestEntry = byName.get(BUNDLE_MANIFEST);
47
+ const clientEntry = byName.get(BUNDLE_CLIENT);
48
+ if (!manifestEntry || !clientEntry) {
49
+ throw bundleError(`${path} is not a summer.games export: it has no ${BUNDLE_MANIFEST} and ${BUNDLE_CLIENT}.`);
50
+ }
51
+ if (byName.size !== entries.length ||
52
+ entries.some((entry) => entry.encrypted ||
53
+ entry.name.endsWith("/") ||
54
+ entry.name.split("/").some((part) => !part || part === "." || part === "..") ||
55
+ /[\\\0\r\n]/.test(entry.name))) {
56
+ throw bundleError("The export contains a repeated or unsafe file path.");
57
+ }
58
+ let manifest;
59
+ try {
60
+ manifest = JSON.parse((await readZipEntry(path, manifestEntry)).toString("utf8"));
61
+ }
62
+ catch (error) {
63
+ if (error instanceof ZipReadError)
64
+ throw bundleError(`${BUNDLE_MANIFEST} could not be read: ${error.message}`);
65
+ throw bundleError(`${BUNDLE_MANIFEST} is not valid JSON.`);
66
+ }
67
+ const client = manifest?.client;
68
+ const mainScene = typeof client?.mainScene === "string" ? client.mainScene : null;
69
+ if (manifest?.schema !== BUNDLE_SCHEMA ||
70
+ client?.path !== BUNDLE_CLIENT ||
71
+ !mainScene?.startsWith("res://") ||
72
+ !Array.isArray(client?.targetPlatforms) ||
73
+ !client.targetPlatforms.every((value) => typeof value === "string") ||
74
+ !Array.isArray(manifest.files)) {
75
+ throw new BuildToolError("bundle_invalid", `${BUNDLE_MANIFEST} is not a ${BUNDLE_SCHEMA} manifest.`, "Recovery: update Summer Engine and export again.");
76
+ }
77
+ const hosted = Boolean(manifest.server);
78
+ const compositionPath = typeof manifest.compositionPath === "string" ? manifest.compositionPath : null;
79
+ if ((!hosted && manifest.compositionPath != null) ||
80
+ hosted !== byName.has(BUNDLE_SERVER) ||
81
+ (hosted &&
82
+ (manifest.server?.path !== BUNDLE_SERVER ||
83
+ typeof manifest.server.mainScene !== "string" ||
84
+ !/^res:\/\/.+\.tscn$/.test(manifest.server.mainScene) ||
85
+ !compositionPath ||
86
+ !/^res:\/\/.+\.tres$/.test(compositionPath)))) {
87
+ throw bundleError("The export must name its server pack, main scene and network composition together.");
88
+ }
89
+ const allowed = (name) => name === BUNDLE_MANIFEST ||
90
+ name === BUNDLE_CLIENT ||
91
+ name === BUNDLE_BUILD ||
92
+ (hosted && (name === BUNDLE_SERVER || name.startsWith("config/")));
93
+ const extra = entries.find((entry) => !allowed(entry.name));
94
+ if (extra)
95
+ throw bundleError(`The export contains ${extra.name}, which a summer.games export never has.`);
96
+ const files = [];
97
+ for (const item of manifest.files) {
98
+ const entry = typeof item?.path === "string" ? byName.get(item.path) : undefined;
99
+ if (!entry ||
100
+ item.path === BUNDLE_MANIFEST ||
101
+ typeof item.sha256 !== "string" ||
102
+ !SHA256.test(item.sha256) ||
103
+ item.size !== entry.uncompressedSize) {
104
+ throw bundleError(`The files do not match ${BUNDLE_MANIFEST}.`);
105
+ }
106
+ files.push({ path: entry.name, sha256: item.sha256, size: entry.uncompressedSize });
107
+ }
108
+ if (new Set(files.map((file) => file.path)).size !== files.length || files.length !== entries.length - 1) {
109
+ throw bundleError(`The files do not match ${BUNDLE_MANIFEST}.`);
110
+ }
111
+ const listedClient = files.find((file) => file.path === BUNDLE_CLIENT);
112
+ if (clientEntry.method !== 0) {
113
+ throw bundleError(`${BUNDLE_CLIENT} is compressed in this zip; Summer reads it in place, so it must be stored.`);
114
+ }
115
+ let hostedBuild;
116
+ if (hosted) {
117
+ const config = byName.get(BUNDLE_BUILD);
118
+ let build;
119
+ try {
120
+ build = config ? JSON.parse((await readZipEntry(path, config, 64 * 1024)).toString("utf8")) : undefined;
121
+ }
122
+ catch {
123
+ build = undefined;
124
+ }
125
+ if (!build || typeof build !== "object" || Array.isArray(build) || build.executionMode !== "hosted") {
126
+ throw bundleError(`${BUNDLE_BUILD} is missing or does not declare a hosted game.`);
127
+ }
128
+ hostedBuild = build;
129
+ }
130
+ const targetPlatforms = client.targetPlatforms;
131
+ if (new Set(targetPlatforms).size !== targetPlatforms.length || targetPlatforms.length === 0) {
132
+ throw bundleError("The export must name at least one platform, each once.");
133
+ }
134
+ return {
135
+ schema: BUNDLE_SCHEMA,
136
+ summerVersion: typeof manifest.export?.summerVersion === "string" ? manifest.export.summerVersion : null,
137
+ engineSha: typeof manifest.export?.engineSha === "string" ? manifest.export.engineSha : null,
138
+ mainScene: mainScene,
139
+ targetPlatforms,
140
+ hosted,
141
+ compositionPath,
142
+ clientPack: { sha256: listedClient.sha256, size: listedClient.size },
143
+ ...(hostedBuild ? { hostedBuild } : {}),
144
+ files,
145
+ };
146
+ }
147
+ /** "sha256:<hex>" and size of a whole file, streamed. */
148
+ export async function hashFile(path) {
149
+ const hash = createHash("sha256");
150
+ let sizeBytes = 0;
151
+ for await (const chunk of createReadStream(path)) {
152
+ hash.update(chunk);
153
+ sizeBytes += chunk.length;
154
+ }
155
+ return { sha256: `sha256:${hash.digest("hex")}`, sizeBytes };
156
+ }
@@ -47,6 +47,9 @@ import open from "open";
47
47
  import { openArgsSchema, runOpen } from "./navigation/open.js";
48
48
  import { shapeEngineLogResponse } from "../log-filters.js";
49
49
  import { listCreatorReleases, publishCreator, } from "./creator.js";
50
+ import { exportGame } from "./export-game.js";
51
+ import { exportTemplates } from "./export-templates.js";
52
+ import { publishBuild } from "./publish-build.js";
50
53
  import { CONFIG_KEYS, getConfigValue, isConfigKey, readSummerConfig, resolveGatewayUrl, setConfigValue, unsetConfigValue, } from "../config.js";
51
54
  import { createDebugReportArtifact } from "./debug-report.js";
52
55
  import { buildGameTaskPlan, gameTaskPlanInputSchema } from "./game-task-plan.js";
@@ -608,7 +611,36 @@ export const TOOL_DISPATCH = [
608
611
  throw err;
609
612
  }
610
613
  }),
611
- entry("summer_creator_publish", "Publish an exported .pck through the creator API (confirm-gated)", false, (args) => publishCreator({
614
+ entry("summer_export_game", "Export the game as a summer.games .zip with the installed engine (headless)", false, (args) => exportGame({
615
+ project: optStr(args, "project"),
616
+ out: optStr(args, "out"),
617
+ targets: Array.isArray(args.targets) ? args.targets.map(String) : undefined,
618
+ format: optStr(args, "format"),
619
+ debug: args.debug === true,
620
+ ...(typeof args.timeoutSeconds === "number" ? { timeoutMs: args.timeoutSeconds * 1000 } : {}),
621
+ })),
622
+ entry("summer_export_templates", "List or install Summer export templates from the CDN (web, macos, windows)", false, (args) => {
623
+ const action = optStr(args, "action");
624
+ if (action !== "list" && action !== "install")
625
+ throw new ToolDispatchError('action must be "list" or "install".');
626
+ return exportTemplates({
627
+ action,
628
+ platforms: Array.isArray(args.platforms) ? args.platforms.map(String) : undefined,
629
+ includeDebug: args.includeDebug === true,
630
+ summerVersion: optStr(args, "summerVersion"),
631
+ });
632
+ }),
633
+ entry("summer_publish_build", "Upload a summer.games export to your store game (confirm-gated)", false, (args) => publishBuild({
634
+ gameId: optStr(args, "gameId"),
635
+ file: optStr(args, "file"),
636
+ clientVersion: optStr(args, "clientVersion"),
637
+ publish: args.publish === true,
638
+ platform: optStr(args, "platform"),
639
+ confirm: args.confirm === true,
640
+ ...(typeof args.waitSeconds === "number" ? { waitSeconds: args.waitSeconds } : {}),
641
+ face: "cli",
642
+ })),
643
+ entry("summer_creator_publish", "Deprecated: publish a .pck to the legacy creator API; use publish-build", false, (args) => publishCreator({
612
644
  project: optStr(args, "project"),
613
645
  artifact: optStr(args, "artifact"),
614
646
  version: optStr(args, "version"),
@@ -88,17 +88,17 @@ export declare const uiActivateArgsSchema: z.ZodObject<{
88
88
  title: z.ZodOptional<z.ZodString>;
89
89
  button: z.ZodOptional<z.ZodString>;
90
90
  }, "strip", z.ZodTypeAny, {
91
+ value?: string | number | undefined;
91
92
  title?: string | undefined;
92
93
  path?: string | undefined;
93
- value?: string | number | undefined;
94
94
  action?: "focus" | "press" | "toggle" | "select_tab" | "set_text" | "set_value" | "dismiss_dialog" | undefined;
95
95
  button?: string | undefined;
96
96
  index?: number | undefined;
97
97
  submit?: boolean | undefined;
98
98
  }, {
99
+ value?: string | number | undefined;
99
100
  title?: string | undefined;
100
101
  path?: string | undefined;
101
- value?: string | number | undefined;
102
102
  action?: "focus" | "press" | "toggle" | "select_tab" | "set_text" | "set_value" | "dismiss_dialog" | undefined;
103
103
  button?: string | undefined;
104
104
  index?: number | undefined;
@@ -19,10 +19,10 @@ export declare const readLibraryInputSchema: z.ZodObject<{
19
19
  part: z.ZodOptional<z.ZodEnum<["skill", "resource", "all"]>>;
20
20
  }, "strict", z.ZodTypeAny, {
21
21
  id: string;
22
- part?: "all" | "resource" | "skill" | undefined;
22
+ part?: "resource" | "all" | "skill" | undefined;
23
23
  }, {
24
24
  id: string;
25
- part?: "all" | "resource" | "skill" | undefined;
25
+ part?: "resource" | "all" | "skill" | undefined;
26
26
  }>;
27
27
  export type ReadLibraryArgs = z.infer<typeof readLibraryInputSchema>;
28
28
  export interface LibraryReadDeps extends LibrarySearchDeps {
@@ -0,0 +1,78 @@
1
+ /**
2
+ * The Summer store sign-in for local tools (summer_publish_build): OAuth 2.1
3
+ * authorization code + PKCE against the same Supabase authorization server
4
+ * and resource the hosted MCP uses (mcp.summerengine.com/mcp), with a
5
+ * loopback redirect (RFC 8252). The access token's audience is the MCP
6
+ * resource, the one token the creator store accepts for agents (creator
7
+ * publishing spec, part C.3).
8
+ *
9
+ * The Summer CLI is one public client (no secret; PKCE proves each login).
10
+ * The authorization server matches redirect URIs exactly, so the CLI listens
11
+ * on one of a few fixed loopback ports and registers its client once per
12
+ * machine with exactly those redirect URIs. Later logins and refreshes reuse
13
+ * that client id (~/.summer/oauth-client); only --force registers anew.
14
+ *
15
+ * The token is stored in ~/.summer/oauth-token (0600) with its refresh token,
16
+ * separate from the CLI JWT in auth-token: the engine reads that file and
17
+ * expects the summer-cli contract.
18
+ */
19
+ export declare const OAUTH_TOKEN_FILE = "oauth-token";
20
+ export declare const OAUTH_CLIENT_FILE = "oauth-client";
21
+ /** Loopback ports the Summer CLI client is registered for, tried in order. */
22
+ export declare const STORE_LOGIN_PORTS: readonly [47615, 47616, 47617];
23
+ export declare const DEFAULT_MCP_RESOURCE_URL = "https://mcp.summerengine.com/mcp";
24
+ export declare const MCP_RESOURCE_ENV = "SUMMER_MCP_RESOURCE_URL";
25
+ export declare class OAuthError extends Error {
26
+ readonly code: string;
27
+ readonly recovery: string;
28
+ constructor(code: string, message: string, recovery: string);
29
+ }
30
+ export interface StoredOAuthToken {
31
+ schemaVersion: 1;
32
+ resource: string;
33
+ issuer: string;
34
+ tokenEndpoint: string;
35
+ clientId: string;
36
+ accessToken: string;
37
+ refreshToken?: string;
38
+ expiresAt: string;
39
+ scope?: string;
40
+ }
41
+ /** The machine's registered Summer CLI client for one authorization server. */
42
+ export interface StoredOAuthClient {
43
+ schemaVersion: 1;
44
+ issuer: string;
45
+ clientId: string;
46
+ redirectUris: string[];
47
+ }
48
+ interface AuthorizationServer {
49
+ issuer: string;
50
+ authorizationEndpoint: string;
51
+ tokenEndpoint: string;
52
+ registrationEndpoint: string;
53
+ }
54
+ export interface OAuthDependencies {
55
+ fetch: typeof fetch;
56
+ now: () => number;
57
+ }
58
+ export declare function resolveMcpResourceUrl(env?: NodeJS.ProcessEnv): string;
59
+ /** RFC 9728 resource metadata, then RFC 8414 server metadata (path-aware first). */
60
+ export declare function discoverAuthorizationServer(resource: string, deps?: OAuthDependencies): Promise<AuthorizationServer>;
61
+ export interface StoreLoginDependencies extends OAuthDependencies {
62
+ openUrl: (url: string) => Promise<unknown>;
63
+ log: (message: string) => void;
64
+ timeoutMs?: number;
65
+ /** Register a new client instead of reusing this machine's ("summer login --store --force"). */
66
+ newClient?: boolean;
67
+ /** Tests only: other loopback ports. */
68
+ ports?: readonly number[];
69
+ }
70
+ /** Browser sign-in (authorization code + PKCE) that stores ~/.summer/oauth-token. */
71
+ export declare function runStoreLogin(deps: StoreLoginDependencies): Promise<StoredOAuthToken>;
72
+ export declare function readStoredOAuthToken(): Promise<StoredOAuthToken | null>;
73
+ /**
74
+ * A current store access token: the stored one, refreshed when it expires
75
+ * within a minute.
76
+ */
77
+ export declare function getStoreAccessToken(deps?: OAuthDependencies): Promise<string>;
78
+ export {};