summer-engine 4.5.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 +50 -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/setup.js +175 -32
- 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/installer/agent-config.d.ts +29 -0
- package/dist/installer/agent-config.js +75 -11
- package/dist/installer/agent-detect.d.ts +44 -0
- package/dist/installer/agent-detect.js +166 -0
- package/dist/installer/agent-table.d.ts +19 -0
- package/dist/installer/agent-table.js +130 -0
- package/dist/installer/setup-error.d.ts +19 -0
- package/dist/installer/setup-error.js +34 -0
- package/dist/installer/version-check.d.ts +5 -0
- package/dist/installer/version-check.js +21 -0
- package/dist/mcp/ops-surface.d.ts +10 -0
- package/dist/mcp/ops-surface.js +18 -1
- 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/dist/project-memory/agent-instructions.js +11 -3
- 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/make-game/SKILL.md +4 -4
- 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 +317 -52
- 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
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `summer setup --detect`: which agents from agent-table.ts are on this
|
|
3
|
+
* computer, where each one's MCP config file is, and whether it already lists
|
|
4
|
+
* summer-engine. Reads only; never writes.
|
|
5
|
+
*
|
|
6
|
+
* How an agent counts as installed (any one hit; `detectedBy` names each):
|
|
7
|
+
* - bin: one of its commands is a file on PATH, or in a usual install folder
|
|
8
|
+
* (~/.local/bin, /opt/homebrew/bin, %APPDATA%\npm, ...). A desktop app's
|
|
9
|
+
* installer runs with a short PATH that leaves those out, so they are
|
|
10
|
+
* checked by name. On Windows each name is tried with every PATHEXT ending.
|
|
11
|
+
* - app: a macOS app bundle in /Applications or ~/Applications, or a Windows
|
|
12
|
+
* executable under %LOCALAPPDATA%, %ProgramFiles% or %ProgramFiles(x86)%.
|
|
13
|
+
* - folder: a config, data or install folder the agent makes on first run.
|
|
14
|
+
* - extension: a VS Code extension folder in ~/.vscode/extensions.
|
|
15
|
+
* The per-agent names live in agent-table.ts (`detect`).
|
|
16
|
+
*/
|
|
17
|
+
import { accessSync, constants, existsSync, readdirSync, readFileSync, statSync } from "fs";
|
|
18
|
+
import { join } from "path";
|
|
19
|
+
import { allAgentSpecs, defaultPathContext, resolveMcpPath, } from "./agent-table.js";
|
|
20
|
+
import { listsSummerEngine, readRecordedMcpServer } from "./version-check.js";
|
|
21
|
+
import { toStepError } from "./setup-error.js";
|
|
22
|
+
export function detectAgents(options = {}) {
|
|
23
|
+
const ctx = options.ctx ?? defaultPathContext();
|
|
24
|
+
const binDirs = searchedBinDirs(ctx, options.systemBinDirs);
|
|
25
|
+
const macAppDirs = options.macAppDirs ?? ["/Applications", join(ctx.home, "Applications")];
|
|
26
|
+
return allAgentSpecs().map((spec) => detectAgent(spec, ctx, binDirs, macAppDirs));
|
|
27
|
+
}
|
|
28
|
+
function detectAgent(spec, ctx, binDirs, macAppDirs) {
|
|
29
|
+
const detectedBy = [
|
|
30
|
+
...(spec.detect.bins ?? []).flatMap((name) => findBin(name, binDirs, ctx)).map((path) => ({ kind: "bin", path })),
|
|
31
|
+
...findApps(spec, ctx, macAppDirs).map((path) => ({ kind: "app", path })),
|
|
32
|
+
...(spec.detect.dirs?.(ctx) ?? []).filter((path) => existsSync(path)).map((path) => ({ kind: "folder", path })),
|
|
33
|
+
...findVsCodeExtensions(spec.detect.vscodeExtensions ?? [], ctx).map((path) => ({ kind: "extension", path })),
|
|
34
|
+
];
|
|
35
|
+
const unique = detectedBy.filter((hit, index) => detectedBy.findIndex((other) => other.path === hit.path) === index);
|
|
36
|
+
const resolved = resolveMcpPath(spec, "user", ctx);
|
|
37
|
+
const override = ctx.env[spec.envOverride];
|
|
38
|
+
const configPath = override || resolved.path;
|
|
39
|
+
const configExists = existsSync(configPath);
|
|
40
|
+
let mcpEntry = false;
|
|
41
|
+
let mcpServer = null;
|
|
42
|
+
let configError;
|
|
43
|
+
if (configExists) {
|
|
44
|
+
try {
|
|
45
|
+
const text = readFileSync(configPath, "utf-8");
|
|
46
|
+
mcpEntry = listsSummerEngine(text, spec.format);
|
|
47
|
+
mcpServer = readRecordedMcpServer(text, spec.format);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
configError = toStepError(error, "config_unreadable");
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
id: spec.id,
|
|
55
|
+
label: spec.label,
|
|
56
|
+
status: spec.status,
|
|
57
|
+
installed: unique.length > 0,
|
|
58
|
+
programFound: unique.some((hit) => hit.kind !== "folder"),
|
|
59
|
+
detectedBy: unique,
|
|
60
|
+
configPath,
|
|
61
|
+
configScope: resolved.scope,
|
|
62
|
+
configFormat: spec.format,
|
|
63
|
+
configExists,
|
|
64
|
+
mcpEntry,
|
|
65
|
+
mcpServer,
|
|
66
|
+
summerGames: Boolean(spec.remoteMcp),
|
|
67
|
+
skills: spec.skills !== null,
|
|
68
|
+
...(configError ? { configError } : {}),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/** PATH first, then the install folders a GUI-launched process's PATH leaves out. */
|
|
72
|
+
export function searchedBinDirs(ctx, systemBinDirs = ["/opt/homebrew/bin", "/usr/local/bin"]) {
|
|
73
|
+
const path = ctx.env.PATH ?? ctx.env.Path ?? "";
|
|
74
|
+
const sep = ctx.os === "win32" ? ";" : ":";
|
|
75
|
+
const fromPath = path.split(sep).filter(Boolean);
|
|
76
|
+
const home = ctx.home;
|
|
77
|
+
const usual = ctx.os === "win32"
|
|
78
|
+
? [
|
|
79
|
+
join(home, ".local", "bin"),
|
|
80
|
+
join(ctx.env.APPDATA ?? join(home, "AppData", "Roaming"), "npm"),
|
|
81
|
+
join(localAppData(ctx), "Microsoft", "WinGet", "Links"),
|
|
82
|
+
join(localAppData(ctx), "pnpm"),
|
|
83
|
+
join(home, ".bun", "bin"),
|
|
84
|
+
join(home, ".volta", "bin"),
|
|
85
|
+
join(home, ".lmstudio", "bin"),
|
|
86
|
+
]
|
|
87
|
+
: [
|
|
88
|
+
join(home, ".local", "bin"),
|
|
89
|
+
join(home, "bin"),
|
|
90
|
+
...systemBinDirs,
|
|
91
|
+
join(home, ".npm-global", "bin"),
|
|
92
|
+
join(home, ".bun", "bin"),
|
|
93
|
+
join(home, ".volta", "bin"),
|
|
94
|
+
join(home, "Library", "pnpm"),
|
|
95
|
+
join(home, ".local", "share", "pnpm"),
|
|
96
|
+
join(home, ".claude", "local"),
|
|
97
|
+
join(home, ".opencode", "bin"),
|
|
98
|
+
join(home, ".lmstudio", "bin"),
|
|
99
|
+
...nvmBinDirs(home),
|
|
100
|
+
];
|
|
101
|
+
return [...new Set([...fromPath, ...usual])];
|
|
102
|
+
}
|
|
103
|
+
/** ~/.nvm/versions/node/<version>/bin for each installed Node (npm -g installs land there). */
|
|
104
|
+
function nvmBinDirs(home) {
|
|
105
|
+
const root = join(home, ".nvm", "versions", "node");
|
|
106
|
+
try {
|
|
107
|
+
return readdirSync(root).map((version) => join(root, version, "bin"));
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return [];
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function localAppData(ctx) {
|
|
114
|
+
return ctx.env.LOCALAPPDATA ?? join(ctx.home, "AppData", "Local");
|
|
115
|
+
}
|
|
116
|
+
function findBin(name, dirs, ctx) {
|
|
117
|
+
const names = ctx.os === "win32"
|
|
118
|
+
? [name, ...(ctx.env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean).map((ext) => `${name}${ext.toLowerCase()}`)]
|
|
119
|
+
: [name];
|
|
120
|
+
const hits = [];
|
|
121
|
+
for (const dir of dirs) {
|
|
122
|
+
for (const candidate of names) {
|
|
123
|
+
const path = join(dir, candidate);
|
|
124
|
+
if (isRunnable(path, ctx)) {
|
|
125
|
+
hits.push(path);
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return hits;
|
|
131
|
+
}
|
|
132
|
+
function isRunnable(path, ctx) {
|
|
133
|
+
try {
|
|
134
|
+
if (!statSync(path).isFile())
|
|
135
|
+
return false;
|
|
136
|
+
if (ctx.os !== "win32")
|
|
137
|
+
accessSync(path, constants.X_OK);
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
function findApps(spec, ctx, macAppDirs) {
|
|
145
|
+
if (ctx.os === "darwin") {
|
|
146
|
+
return (spec.detect.macApps ?? []).flatMap((app) => macAppDirs.map((dir) => join(dir, app))).filter((path) => existsSync(path));
|
|
147
|
+
}
|
|
148
|
+
if (ctx.os === "win32") {
|
|
149
|
+
const roots = [localAppData(ctx), ctx.env.ProgramFiles, ctx.env["ProgramFiles(x86)"]].filter((root) => Boolean(root));
|
|
150
|
+
return (spec.detect.winApps ?? []).flatMap((exe) => roots.map((root) => join(root, exe))).filter((path) => existsSync(path));
|
|
151
|
+
}
|
|
152
|
+
return [];
|
|
153
|
+
}
|
|
154
|
+
function findVsCodeExtensions(prefixes, ctx) {
|
|
155
|
+
if (prefixes.length === 0)
|
|
156
|
+
return [];
|
|
157
|
+
const dir = join(ctx.home, ".vscode", "extensions");
|
|
158
|
+
let entries;
|
|
159
|
+
try {
|
|
160
|
+
entries = readdirSync(dir);
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
return [];
|
|
164
|
+
}
|
|
165
|
+
return entries.filter((entry) => prefixes.some((prefix) => entry.toLowerCase().startsWith(prefix))).map((entry) => join(dir, entry));
|
|
166
|
+
}
|
|
@@ -101,6 +101,25 @@ export interface AgentSpec {
|
|
|
101
101
|
/** null: no skills/rules mechanism — MCP only. */
|
|
102
102
|
skills: SkillHome | null;
|
|
103
103
|
noSkillsNote?: string;
|
|
104
|
+
/** How `summer setup --detect` tells the agent is on this computer (agent-detect.ts). */
|
|
105
|
+
detect: AgentDetect;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Where an agent shows up once it is installed, on macOS and Windows (Linux
|
|
109
|
+
* uses the bins and folders). Any one hit counts as installed; `--detect`
|
|
110
|
+
* names each hit, so a caller can tell a live binary from a leftover folder.
|
|
111
|
+
*/
|
|
112
|
+
export interface AgentDetect {
|
|
113
|
+
/** Commands: looked up on PATH and in the usual install folders a GUI app's short PATH misses (agent-detect.ts). */
|
|
114
|
+
bins?: readonly string[];
|
|
115
|
+
/** macOS app bundles, looked up in /Applications and ~/Applications. */
|
|
116
|
+
macApps?: readonly string[];
|
|
117
|
+
/** Windows executables, relative to %LOCALAPPDATA%, %ProgramFiles% and %ProgramFiles(x86)%. */
|
|
118
|
+
winApps?: readonly string[];
|
|
119
|
+
/** Folders the agent creates on install or first run (config, data or install folder). */
|
|
120
|
+
dirs?: (ctx: PathContext) => string[];
|
|
121
|
+
/** VS Code extension id prefixes, looked up in ~/.vscode/extensions (folders named <id>-<version>). */
|
|
122
|
+
vscodeExtensions?: readonly string[];
|
|
104
123
|
}
|
|
105
124
|
/** True when this location is the shared agentskills.io folder. */
|
|
106
125
|
export declare function isSharedSkillsPath(path: string): boolean;
|
|
@@ -114,6 +114,11 @@ const SPECS = [
|
|
|
114
114
|
signIn: (name) => `In Claude Code, run /mcp, choose ${name} and sign in.`,
|
|
115
115
|
},
|
|
116
116
|
mcp: { user: home(".claude.json"), project: project(".mcp.json") },
|
|
117
|
+
detect: {
|
|
118
|
+
// The native installer puts claude in ~/.local/bin (macOS and Windows); older npm installs in ~/.claude/local.
|
|
119
|
+
bins: ["claude"],
|
|
120
|
+
dirs: (ctx) => [join(ctx.home, ".claude"), join(ctx.home, ".claude.json")],
|
|
121
|
+
},
|
|
117
122
|
restart: "Restart Claude Code or run /mcp in a new session.",
|
|
118
123
|
skills: skillDirs(home(".claude", "skills"), project(".claude", "skills")),
|
|
119
124
|
},
|
|
@@ -129,6 +134,12 @@ const SPECS = [
|
|
|
129
134
|
user: (ctx) => join(appConfigRoot(ctx), "Claude", "claude_desktop_config.json"),
|
|
130
135
|
project: null,
|
|
131
136
|
},
|
|
137
|
+
detect: {
|
|
138
|
+
macApps: ["Claude.app"],
|
|
139
|
+
// Squirrel install: %LOCALAPPDATA%/AnthropicClaude/claude.exe.
|
|
140
|
+
winApps: [join("AnthropicClaude", "claude.exe")],
|
|
141
|
+
dirs: (ctx) => [join(appConfigRoot(ctx), "Claude")],
|
|
142
|
+
},
|
|
132
143
|
restart: "Quit and reopen Claude Desktop; the summer-engine tools appear under the tools menu in a new chat.",
|
|
133
144
|
skills: null,
|
|
134
145
|
noSkillsNote: "Claude Desktop has no skills folder. The MCP server ships summer_docs_search and summer_docs_read, so the model can pull Summer guidance in-chat.",
|
|
@@ -150,6 +161,12 @@ const SPECS = [
|
|
|
150
161
|
project: project(".codex", "config.toml"),
|
|
151
162
|
projectNote: "Codex only loads project .codex/config.toml from trusted projects.",
|
|
152
163
|
},
|
|
164
|
+
detect: {
|
|
165
|
+
// The codex CLI (npm or Homebrew) and the Codex desktop app share $CODEX_HOME (default ~/.codex).
|
|
166
|
+
bins: ["codex"],
|
|
167
|
+
macApps: ["Codex.app"],
|
|
168
|
+
dirs: (ctx) => [ctx.env.CODEX_HOME || join(ctx.home, ".codex")],
|
|
169
|
+
},
|
|
153
170
|
restart: "Restart Codex or run /mcp in a new session.",
|
|
154
171
|
skills: sharedSkills(),
|
|
155
172
|
},
|
|
@@ -165,6 +182,12 @@ const SPECS = [
|
|
|
165
182
|
signIn: (name) => `In Cursor Settings, open MCP and click Connect (or Authenticate) next to ${name}.`,
|
|
166
183
|
},
|
|
167
184
|
mcp: { user: home(".cursor", "mcp.json"), project: project(".cursor", "mcp.json") },
|
|
185
|
+
detect: {
|
|
186
|
+
bins: ["cursor", "cursor-agent"],
|
|
187
|
+
macApps: ["Cursor.app"],
|
|
188
|
+
winApps: [join("Programs", "cursor", "Cursor.exe")],
|
|
189
|
+
dirs: (ctx) => [join(ctx.home, ".cursor")],
|
|
190
|
+
},
|
|
168
191
|
restart: "Restart Cursor and enable the summer-engine MCP server if prompted.",
|
|
169
192
|
skills: sharedSkills({
|
|
170
193
|
reloadHint: "Cursor loads skills in the next chat. Summer 3.0 wrote rule files to .cursor/rules and 3.1.0 wrote .cursor/skills; `--force` removes both.",
|
|
@@ -189,6 +212,12 @@ const SPECS = [
|
|
|
189
212
|
project: null,
|
|
190
213
|
movedFrom: home(".codeium", "windsurf", "mcp_config.json"),
|
|
191
214
|
},
|
|
215
|
+
detect: {
|
|
216
|
+
bins: ["windsurf", "devin"],
|
|
217
|
+
macApps: ["Windsurf.app", "Devin.app"],
|
|
218
|
+
winApps: [join("Programs", "Windsurf", "Windsurf.exe"), join("Programs", "Devin", "Devin.exe")],
|
|
219
|
+
dirs: (ctx) => [join(xdgOrAppData(ctx), "devin"), join(ctx.home, ".codeium", "windsurf")],
|
|
220
|
+
},
|
|
192
221
|
restart: "Restart Devin Desktop (formerly Windsurf) and refresh MCP servers from the agent settings. Devin's docs say mcp_config.json configures the Cascade agent; for the Devin agent add the server in the app's MCP settings with the same command.",
|
|
193
222
|
skills: sharedSkills({ legacyDirs: { user: home(".codeium", "windsurf", "skills"), project: project(".windsurf", "skills") } }),
|
|
194
223
|
},
|
|
@@ -207,6 +236,12 @@ const SPECS = [
|
|
|
207
236
|
user: home(".gemini", "config", "mcp_config.json"),
|
|
208
237
|
project: project(".agents", "mcp_config.json"),
|
|
209
238
|
},
|
|
239
|
+
detect: {
|
|
240
|
+
bins: ["antigravity", "agy"],
|
|
241
|
+
macApps: ["Antigravity.app"],
|
|
242
|
+
winApps: [join("Programs", "Antigravity", "Antigravity.exe")],
|
|
243
|
+
dirs: (ctx) => [join(ctx.home, ".gemini", "antigravity"), join(ctx.home, ".gemini", "config")],
|
|
244
|
+
},
|
|
210
245
|
restart: "In Antigravity open the agent panel's MCP servers view and refresh; summer-engine appears in the list (IDE and CLI share this file).",
|
|
211
246
|
skills: skillDirs(home(".gemini", "config", "skills"), project(".agents", "skills")),
|
|
212
247
|
},
|
|
@@ -223,6 +258,7 @@ const SPECS = [
|
|
|
223
258
|
user: home(".gemini", "extensions", "summer-engine", "gemini-extension.json"),
|
|
224
259
|
project: null,
|
|
225
260
|
},
|
|
261
|
+
detect: { bins: ["gemini"], dirs: (ctx) => [join(ctx.home, ".gemini", "extensions")] },
|
|
226
262
|
restart: "Run `summer skills install --all --agent gemini` if skills were not installed, then restart Gemini CLI (or `gemini extensions enable summer-engine` if it is disabled).",
|
|
227
263
|
skills: skillDirs(home(".gemini", "extensions", "summer-engine", "skills"), null),
|
|
228
264
|
},
|
|
@@ -241,6 +277,11 @@ const SPECS = [
|
|
|
241
277
|
user: (ctx) => vsCodeGlobalStorage(ctx, "saoudrizwan.claude-dev", "cline_mcp_settings.json"),
|
|
242
278
|
project: null,
|
|
243
279
|
},
|
|
280
|
+
detect: {
|
|
281
|
+
// A VS Code extension: its install folder, or the storage it makes on first run.
|
|
282
|
+
vscodeExtensions: ["saoudrizwan.claude-dev-"],
|
|
283
|
+
dirs: (ctx) => [join(vsCodeUserDir(ctx), "globalStorage", "saoudrizwan.claude-dev")],
|
|
284
|
+
},
|
|
244
285
|
restart: "Restart VS Code so Cline reloads its MCP config.",
|
|
245
286
|
skills: skillDirs(home(".cline", "skills"), project(".cline", "skills")),
|
|
246
287
|
},
|
|
@@ -256,6 +297,7 @@ const SPECS = [
|
|
|
256
297
|
signIn: (name) => `Run \`cline mcp\`, pick ${name} and choose Authorize OAuth.`,
|
|
257
298
|
},
|
|
258
299
|
mcp: { user: home(".cline", "data", "settings", "cline_mcp_settings.json"), project: null },
|
|
300
|
+
detect: { bins: ["cline"], dirs: (ctx) => [join(ctx.home, ".cline", "data")] },
|
|
259
301
|
restart: "Restart the Cline CLI so it reloads its MCP settings.",
|
|
260
302
|
skills: skillDirs(home(".cline", "skills"), project(".cline", "skills")),
|
|
261
303
|
},
|
|
@@ -272,6 +314,10 @@ const SPECS = [
|
|
|
272
314
|
user: (ctx) => vsCodeGlobalStorage(ctx, "rooveterinaryinc.roo-cline", "cline_mcp_settings.json"),
|
|
273
315
|
project: null,
|
|
274
316
|
},
|
|
317
|
+
detect: {
|
|
318
|
+
vscodeExtensions: ["rooveterinaryinc.roo-cline-"],
|
|
319
|
+
dirs: (ctx) => [join(vsCodeUserDir(ctx), "globalStorage", "rooveterinaryinc.roo-cline")],
|
|
320
|
+
},
|
|
275
321
|
restart: "Restart VS Code so Roo Code reloads its MCP config.",
|
|
276
322
|
skills: {
|
|
277
323
|
kind: "cline-rule-dir",
|
|
@@ -295,6 +341,12 @@ const SPECS = [
|
|
|
295
341
|
user: (ctx) => join(xdgOrAppData(ctx), "kilo", "kilo.json"),
|
|
296
342
|
project: project("kilo.json"),
|
|
297
343
|
},
|
|
344
|
+
detect: {
|
|
345
|
+
// The kilo CLI, or the VS Code extension.
|
|
346
|
+
bins: ["kilo", "kilocode"],
|
|
347
|
+
vscodeExtensions: ["kilocode.kilo-code-"],
|
|
348
|
+
dirs: (ctx) => [join(xdgOrAppData(ctx), "kilo"), join(ctx.home, ".kilo")],
|
|
349
|
+
},
|
|
298
350
|
restart: "Restart Kilo (CLI or the VS Code extension) so it reloads kilo.json.",
|
|
299
351
|
skills: skillDirs(home(".kilo", "skills"), project(".kilo", "skills")),
|
|
300
352
|
},
|
|
@@ -310,6 +362,7 @@ const SPECS = [
|
|
|
310
362
|
signIn: (name) => `Copilot CLI opens summer.games to sign in when ${name} first connects; /mcp signs in again.`,
|
|
311
363
|
},
|
|
312
364
|
mcp: { user: home(".copilot", "mcp-config.json"), project: project(".mcp.json") },
|
|
365
|
+
detect: { bins: ["copilot"], dirs: (ctx) => [join(ctx.home, ".copilot")] },
|
|
313
366
|
restart: "Restart Copilot CLI, or run /mcp reload and /skills reload in the active session.",
|
|
314
367
|
skills: skillDirs(home(".copilot", "skills"), project(".github", "skills")),
|
|
315
368
|
},
|
|
@@ -327,6 +380,13 @@ const SPECS = [
|
|
|
327
380
|
signIn: (name) => `In VS Code, click Allow when ${name} asks to authenticate, then sign in on summer.games.`,
|
|
328
381
|
},
|
|
329
382
|
mcp: { user: (ctx) => join(vsCodeUserDir(ctx), "mcp.json"), project: project(".vscode", "mcp.json") },
|
|
383
|
+
detect: {
|
|
384
|
+
// Copilot Chat ships with VS Code, so VS Code itself is the signal.
|
|
385
|
+
bins: ["code"],
|
|
386
|
+
macApps: ["Visual Studio Code.app"],
|
|
387
|
+
winApps: [join("Programs", "Microsoft VS Code", "Code.exe"), join("Microsoft VS Code", "Code.exe")],
|
|
388
|
+
dirs: (ctx) => [vsCodeUserDir(ctx)],
|
|
389
|
+
},
|
|
330
390
|
restart: "Restart VS Code or run MCP: List Servers, then start summer-engine in Copilot Agent mode.",
|
|
331
391
|
skills: sharedSkills({ legacyDirs: { user: home(".copilot", "skills"), project: project(".github", "skills") } }),
|
|
332
392
|
},
|
|
@@ -339,6 +399,10 @@ const SPECS = [
|
|
|
339
399
|
format: "json-vscode",
|
|
340
400
|
// No Summer Games entry: Visual Studio's OAuth redirect for MCP is not documented; not checked against api.summer.games.
|
|
341
401
|
mcp: { user: home(".mcp.json"), project: project(".mcp.json") },
|
|
402
|
+
detect: {
|
|
403
|
+
// Windows only (Visual Studio for Mac is retired): the install root under Program Files.
|
|
404
|
+
winApps: [join("Microsoft Visual Studio", "Installer", "vswhere.exe")],
|
|
405
|
+
},
|
|
342
406
|
restart: "Restart Visual Studio, open Copilot Chat in Agent mode, and enable summer-engine in the tools picker.",
|
|
343
407
|
skills: null,
|
|
344
408
|
noSkillsNote: "Visual Studio's Copilot has no skills folder yet; the MCP server ships summer_docs_search and summer_docs_read for in-chat guidance.",
|
|
@@ -358,6 +422,10 @@ const SPECS = [
|
|
|
358
422
|
user: (ctx) => join(xdgOrAppData(ctx), "github-copilot", "intellij", "mcp.json"),
|
|
359
423
|
project: null,
|
|
360
424
|
},
|
|
425
|
+
detect: {
|
|
426
|
+
// The Copilot plugin writes its settings here on first run; the IDE itself can be any JetBrains product.
|
|
427
|
+
dirs: (ctx) => [join(xdgOrAppData(ctx), "github-copilot", "intellij")],
|
|
428
|
+
},
|
|
361
429
|
restart: "Restart the JetBrains IDE and open Copilot Chat in Agent mode; summer-engine shows in the tools list.",
|
|
362
430
|
skills: null,
|
|
363
431
|
noSkillsNote: "Copilot in JetBrains documents no skills folder; the MCP server ships summer_docs_search and summer_docs_read for in-chat guidance.",
|
|
@@ -377,6 +445,12 @@ const SPECS = [
|
|
|
377
445
|
user: (ctx) => join(xdgOrAppData(ctx), "opencode", "opencode.json"),
|
|
378
446
|
project: project("opencode.json"),
|
|
379
447
|
},
|
|
448
|
+
detect: {
|
|
449
|
+
// The install script puts opencode in ~/.opencode/bin.
|
|
450
|
+
bins: ["opencode"],
|
|
451
|
+
macApps: ["OpenCode.app"],
|
|
452
|
+
dirs: (ctx) => [join(xdgOrAppData(ctx), "opencode"), join(ctx.home, ".opencode")],
|
|
453
|
+
},
|
|
380
454
|
restart: "Restart OpenCode so it reloads opencode.json.",
|
|
381
455
|
skills: sharedSkills({
|
|
382
456
|
reloadHint: "OpenCode loads skills from this folder on the next session. Summer 3.0 wrote markdown under agents/summer and 3.1.0 wrote opencode/skills; `--force` removes both.",
|
|
@@ -399,6 +473,12 @@ const SPECS = [
|
|
|
399
473
|
user: (ctx) => join(xdgOrAppData(ctx), "zed", "settings.json"),
|
|
400
474
|
project: null,
|
|
401
475
|
},
|
|
476
|
+
detect: {
|
|
477
|
+
bins: ["zed"],
|
|
478
|
+
macApps: ["Zed.app", "Zed Preview.app"],
|
|
479
|
+
winApps: [join("Programs", "Zed", "Zed.exe")],
|
|
480
|
+
dirs: (ctx) => [join(xdgOrAppData(ctx), "zed")],
|
|
481
|
+
},
|
|
402
482
|
restart: "Zed reloads settings.json live; open the Agent panel and check summer-engine under MCP servers.",
|
|
403
483
|
skills: sharedSkills(),
|
|
404
484
|
},
|
|
@@ -414,6 +494,12 @@ const SPECS = [
|
|
|
414
494
|
signIn: (name) => `Kiro opens summer.games to sign in when ${name} connects (Kiro CLI: /mcp auth).`,
|
|
415
495
|
},
|
|
416
496
|
mcp: { user: home(".kiro", "settings", "mcp.json"), project: project(".kiro", "settings", "mcp.json") },
|
|
497
|
+
detect: {
|
|
498
|
+
bins: ["kiro", "kiro-cli"],
|
|
499
|
+
macApps: ["Kiro.app"],
|
|
500
|
+
winApps: [join("Programs", "Kiro", "Kiro.exe")],
|
|
501
|
+
dirs: (ctx) => [join(ctx.home, ".kiro")],
|
|
502
|
+
},
|
|
417
503
|
restart: "Kiro reloads MCP config on save; open the MCP Servers view to confirm summer-engine is connected.",
|
|
418
504
|
skills: skillDirs(home(".kiro", "skills"), project(".kiro", "skills")),
|
|
419
505
|
},
|
|
@@ -443,6 +529,12 @@ const SPECS = [
|
|
|
443
529
|
: join(xdgConfig(ctx), "goose", "config.yaml"),
|
|
444
530
|
project: null,
|
|
445
531
|
},
|
|
532
|
+
detect: {
|
|
533
|
+
bins: ["goose"],
|
|
534
|
+
macApps: ["Goose.app"],
|
|
535
|
+
winApps: [join("Programs", "Goose", "Goose.exe")],
|
|
536
|
+
dirs: (ctx) => [ctx.os === "win32" ? join(appData(ctx), "Block", "goose") : join(xdgConfig(ctx), "goose")],
|
|
537
|
+
},
|
|
446
538
|
restart: "Restart Goose (CLI or Desktop); summer-engine is listed under Extensions.",
|
|
447
539
|
skills: skillDirs((ctx) => join(xdgConfig(ctx), "agents", "skills"), project(".agents", "skills")),
|
|
448
540
|
},
|
|
@@ -458,6 +550,7 @@ const SPECS = [
|
|
|
458
550
|
signIn: (name) => `Run \`hermes mcp login ${name}\`, or sign in on summer.games when Hermes first connects.`,
|
|
459
551
|
},
|
|
460
552
|
mcp: { user: home(".hermes", "config.yaml"), project: null },
|
|
553
|
+
detect: { bins: ["hermes"], dirs: (ctx) => [join(ctx.home, ".hermes")] },
|
|
461
554
|
restart: "Run /reload-mcp in Hermes Agent (or restart it).",
|
|
462
555
|
skills: skillDirs(home(".hermes", "skills"), SHARED_SKILLS_PROJECT, {
|
|
463
556
|
reloadHint: "Project skills need `hermes skills trust` before Hermes loads them.",
|
|
@@ -480,6 +573,12 @@ const SPECS = [
|
|
|
480
573
|
project: project(".trae", "mcp.json"),
|
|
481
574
|
projectNote: "Trae manages user-level MCP servers in its UI; writing the project file .trae/mcp.json instead.",
|
|
482
575
|
},
|
|
576
|
+
detect: {
|
|
577
|
+
bins: ["trae"],
|
|
578
|
+
macApps: ["Trae.app"],
|
|
579
|
+
winApps: [join("Programs", "Trae", "Trae.exe")],
|
|
580
|
+
dirs: (ctx) => [join(appConfigRoot(ctx), "Trae"), join(ctx.home, ".trae")],
|
|
581
|
+
},
|
|
483
582
|
restart: "Restart Trae and open the MCP settings; summer-engine should show as connected.",
|
|
484
583
|
skills: null,
|
|
485
584
|
noSkillsNote: "Trae documents no skills folder; the MCP server ships summer_docs_search and summer_docs_read for in-chat guidance.",
|
|
@@ -496,6 +595,7 @@ const SPECS = [
|
|
|
496
595
|
signIn: (name) => `In Qwen Code, run /mcp auth ${name} and sign in.`,
|
|
497
596
|
},
|
|
498
597
|
mcp: { user: home(".qwen", "settings.json"), project: project(".qwen", "settings.json") },
|
|
598
|
+
detect: { bins: ["qwen"], dirs: (ctx) => [join(ctx.home, ".qwen")] },
|
|
499
599
|
restart: "Restart Qwen Code or run /mcp in a new session.",
|
|
500
600
|
skills: skillDirs(home(".qwen", "skills"), project(".qwen", "skills")),
|
|
501
601
|
},
|
|
@@ -511,6 +611,7 @@ const SPECS = [
|
|
|
511
611
|
signIn: (name) => `Run \`kimi mcp auth ${name}\`; it opens summer.games to sign in.`,
|
|
512
612
|
},
|
|
513
613
|
mcp: { user: home(".kimi-code", "mcp.json"), project: project(".kimi-code", "mcp.json") },
|
|
614
|
+
detect: { bins: ["kimi"], dirs: (ctx) => [join(ctx.home, ".kimi-code"), join(ctx.home, ".kimi")] },
|
|
514
615
|
restart: "Restart Kimi Code CLI so it reconnects its MCP servers.",
|
|
515
616
|
skills: sharedSkills({ legacyDirs: { user: home(".kimi-code", "skills"), project: project(".kimi-code", "skills") } }),
|
|
516
617
|
},
|
|
@@ -529,6 +630,7 @@ const SPECS = [
|
|
|
529
630
|
user: home(".config", "crush", "crushrc"),
|
|
530
631
|
project: project(".crushrc"),
|
|
531
632
|
},
|
|
633
|
+
detect: { bins: ["crush"], dirs: (ctx) => [join(ctx.home, ".config", "crush"), join(ctx.home, ".local", "share", "crush")] },
|
|
532
634
|
restart: "Restart Crush so it reloads crushrc.",
|
|
533
635
|
skills: sharedSkills({ legacyDirs: { user: home(".config", "crush", "skills"), project: project(".crush", "skills") } }),
|
|
534
636
|
},
|
|
@@ -544,6 +646,7 @@ const SPECS = [
|
|
|
544
646
|
signIn: (name) => `Amp opens summer.games to sign in for ${name} when it starts.`,
|
|
545
647
|
},
|
|
546
648
|
mcp: { user: (ctx) => join(xdgOrAppData(ctx), "amp", "settings.json"), project: null },
|
|
649
|
+
detect: { bins: ["amp"], dirs: (ctx) => [join(xdgOrAppData(ctx), "amp")] },
|
|
547
650
|
restart: "Restart Amp so it reloads settings.json.",
|
|
548
651
|
skills: sharedSkills({ legacyDirs: { user: (ctx) => join(xdgOrAppData(ctx), "amp", "skills"), project: null } }),
|
|
549
652
|
},
|
|
@@ -559,6 +662,7 @@ const SPECS = [
|
|
|
559
662
|
signIn: (name) => `In Droid, run /mcp, choose ${name} and Authenticate.`,
|
|
560
663
|
},
|
|
561
664
|
mcp: { user: home(".factory", "mcp.json"), project: project(".factory", "mcp.json") },
|
|
665
|
+
detect: { bins: ["droid"], dirs: (ctx) => [join(ctx.home, ".factory")] },
|
|
562
666
|
restart: "Restart droid or run /mcp in the active session.",
|
|
563
667
|
skills: sharedSkills({ legacyDirs: { user: home(".factory", "skills"), project: project(".factory", "skills") } }),
|
|
564
668
|
},
|
|
@@ -574,6 +678,7 @@ const SPECS = [
|
|
|
574
678
|
signIn: (name) => `In Junie, run /mcp, open ${name} and choose Authorize.`,
|
|
575
679
|
},
|
|
576
680
|
mcp: { user: home(".junie", "mcp", "mcp.json"), project: project(".junie", "mcp", "mcp.json") },
|
|
681
|
+
detect: { bins: ["junie"], dirs: (ctx) => [join(ctx.home, ".junie")] },
|
|
577
682
|
restart: "Restart the JetBrains IDE so Junie reloads its MCP config.",
|
|
578
683
|
skills: null,
|
|
579
684
|
noSkillsNote: "Junie has no skills folder; put project guidance in .junie/guidelines.md. The MCP server ships summer_docs_search and summer_docs_read for in-chat guidance.",
|
|
@@ -590,6 +695,11 @@ const SPECS = [
|
|
|
590
695
|
signIn: (name) => `Warp opens summer.games to sign in when ${name} starts.`,
|
|
591
696
|
},
|
|
592
697
|
mcp: { user: home(".warp", ".mcp.json"), project: project(".warp", ".mcp.json") },
|
|
698
|
+
detect: {
|
|
699
|
+
macApps: ["Warp.app"],
|
|
700
|
+
winApps: [join("Programs", "Warp", "warp.exe")],
|
|
701
|
+
dirs: (ctx) => [join(ctx.home, ".warp")],
|
|
702
|
+
},
|
|
593
703
|
restart: "Warp detects the file and spawns the server; check Settings > AI > MCP servers.",
|
|
594
704
|
skills: sharedSkills({ legacyDirs: { user: home(".warp", "skills"), project: project(".warp", "skills") } }),
|
|
595
705
|
},
|
|
@@ -602,6 +712,11 @@ const SPECS = [
|
|
|
602
712
|
format: "json-transport",
|
|
603
713
|
// No Summer Games entry: Rovo Dev CLI has no OAuth sign-in for remote MCP servers (headers only).
|
|
604
714
|
mcp: { user: home(".rovodev", "mcp.json"), project: null },
|
|
715
|
+
detect: {
|
|
716
|
+
// Rovo Dev runs as `acli rovodev`; acli alone is the Atlassian CLI, so the ~/.rovodev folder is the firmer signal.
|
|
717
|
+
bins: ["acli"],
|
|
718
|
+
dirs: (ctx) => [join(ctx.home, ".rovodev")],
|
|
719
|
+
},
|
|
605
720
|
restart: "Restart Rovo Dev CLI so it reconnects its MCP servers.",
|
|
606
721
|
skills: sharedSkills({ legacyDirs: { user: home(".rovodev", "skills"), project: project(".rovodev", "skills") } }),
|
|
607
722
|
},
|
|
@@ -614,6 +729,12 @@ const SPECS = [
|
|
|
614
729
|
format: "json",
|
|
615
730
|
// No Summer Games entry: Qoder's remote-server fields in settings.json are not documented.
|
|
616
731
|
mcp: { user: home(".qoder", "settings.json"), project: project(".mcp.json") },
|
|
732
|
+
detect: {
|
|
733
|
+
bins: ["qodercli"],
|
|
734
|
+
macApps: ["Qoder.app"],
|
|
735
|
+
winApps: [join("Programs", "Qoder", "Qoder.exe")],
|
|
736
|
+
dirs: (ctx) => [join(ctx.home, ".qoder")],
|
|
737
|
+
},
|
|
617
738
|
restart: "Restart Qoder CLI so it reloads its MCP settings (the Qoder IDE manages servers in its UI).",
|
|
618
739
|
skills: skillDirs(home(".qoder", "skills"), project(".qoder", "skills")),
|
|
619
740
|
},
|
|
@@ -629,6 +750,7 @@ const SPECS = [
|
|
|
629
750
|
signIn: (name) => `In Grok Build, run /mcps, select ${name} and press i to sign in.`,
|
|
630
751
|
},
|
|
631
752
|
mcp: { user: home(".grok", "config.toml"), project: project(".grok", "config.toml") },
|
|
753
|
+
detect: { bins: ["grok"], dirs: (ctx) => [join(ctx.home, ".grok")] },
|
|
632
754
|
restart: "Restart Grok Build so it reloads config.toml (it also reads ~/.claude.json and .cursor/mcp.json).",
|
|
633
755
|
skills: sharedSkills({ legacyDirs: { user: home(".grok", "skills"), project: project(".grok", "skills") } }),
|
|
634
756
|
},
|
|
@@ -644,6 +766,7 @@ const SPECS = [
|
|
|
644
766
|
signIn: (name) => `In Vibe, run /mcp login ${name}.`,
|
|
645
767
|
},
|
|
646
768
|
mcp: { user: home(".vibe", "config.toml"), project: project(".vibe", "config.toml") },
|
|
769
|
+
detect: { bins: ["vibe"], dirs: (ctx) => [join(ctx.home, ".vibe")] },
|
|
647
770
|
restart: "Restart Vibe so it reloads config.toml.",
|
|
648
771
|
skills: skillDirs(home(".vibe", "skills"), SHARED_SKILLS_PROJECT, { legacyDirs: { user: home(".vibe", "skills"), project: project(".vibe", "skills") } }),
|
|
649
772
|
},
|
|
@@ -656,6 +779,13 @@ const SPECS = [
|
|
|
656
779
|
format: "json",
|
|
657
780
|
// No Summer Games entry: LM Studio's MCP client registration is closed and unverified.
|
|
658
781
|
mcp: { user: home(".lmstudio", "mcp.json"), project: null },
|
|
782
|
+
detect: {
|
|
783
|
+
// The app installs the lms command into ~/.lmstudio/bin.
|
|
784
|
+
bins: ["lms"],
|
|
785
|
+
macApps: ["LM Studio.app"],
|
|
786
|
+
winApps: [join("Programs", "LM Studio", "LM Studio.exe"), join("Programs", "lm-studio", "LM Studio.exe")],
|
|
787
|
+
dirs: (ctx) => [join(ctx.home, ".lmstudio")],
|
|
788
|
+
},
|
|
659
789
|
restart: "Open LM Studio, toggle on the summer-engine MCP server in the Program tab, and raise the loaded model's context length to 32k or higher.",
|
|
660
790
|
skills: null,
|
|
661
791
|
noSkillsNote: "LM Studio has no rules or skills folder. The MCP server ships summer_docs_search and summer_docs_read, so the model can pull Summer guidance in-chat.",
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An error `summer setup` reports with a stable code, so a caller reading
|
|
3
|
+
* `--json` (the Summer desktop installer) can branch on the code instead of
|
|
4
|
+
* the message. The message stays the human sentence it always was.
|
|
5
|
+
*/
|
|
6
|
+
export declare class SetupError extends Error {
|
|
7
|
+
readonly code: string;
|
|
8
|
+
constructor(code: string, message: string);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* The code for any error a setup step throws: a SetupError's own code, a
|
|
12
|
+
* file-system failure by kind, else `fallback` (the step's generic code).
|
|
13
|
+
*/
|
|
14
|
+
export declare function setupErrorCode(error: unknown, fallback: string): string;
|
|
15
|
+
export interface SetupStepError {
|
|
16
|
+
code: string;
|
|
17
|
+
message: string;
|
|
18
|
+
}
|
|
19
|
+
export declare function toStepError(error: unknown, fallback: string): SetupStepError;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An error `summer setup` reports with a stable code, so a caller reading
|
|
3
|
+
* `--json` (the Summer desktop installer) can branch on the code instead of
|
|
4
|
+
* the message. The message stays the human sentence it always was.
|
|
5
|
+
*/
|
|
6
|
+
export class SetupError extends Error {
|
|
7
|
+
code;
|
|
8
|
+
constructor(code, message) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.code = code;
|
|
11
|
+
this.name = "SetupError";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/** File-system errno codes that mean "this file cannot be written here". */
|
|
15
|
+
const NOT_WRITABLE = new Set(["EACCES", "EPERM", "EROFS", "EISDIR", "ENOTDIR"]);
|
|
16
|
+
/**
|
|
17
|
+
* The code for any error a setup step throws: a SetupError's own code, a
|
|
18
|
+
* file-system failure by kind, else `fallback` (the step's generic code).
|
|
19
|
+
*/
|
|
20
|
+
export function setupErrorCode(error, fallback) {
|
|
21
|
+
if (error instanceof SetupError)
|
|
22
|
+
return error.code;
|
|
23
|
+
const errno = error?.code;
|
|
24
|
+
if (typeof errno === "string") {
|
|
25
|
+
if (NOT_WRITABLE.has(errno))
|
|
26
|
+
return "config_not_writable";
|
|
27
|
+
if (errno === "ENOSPC")
|
|
28
|
+
return "disk_full";
|
|
29
|
+
}
|
|
30
|
+
return fallback;
|
|
31
|
+
}
|
|
32
|
+
export function toStepError(error, fallback) {
|
|
33
|
+
return { code: setupErrorCode(error, fallback), message: error instanceof Error ? error.message : String(error) };
|
|
34
|
+
}
|
|
@@ -121,6 +121,8 @@ export interface RecordedInstall {
|
|
|
121
121
|
* --cli`, or skills installed alone) and `setup --cli` can set the agent
|
|
122
122
|
* up: the refresh keeps it without an MCP server. */
|
|
123
123
|
cliOnly?: boolean;
|
|
124
|
+
/** The bundled node executable the entry runs (`setup --runtime <node> --package-dir <dir>`); cliPath is then that package's dist/bin/summer.js. */
|
|
125
|
+
runtime?: string;
|
|
124
126
|
}
|
|
125
127
|
/** An npm dist-tag (`latest`, `next`) or an exact version (`3.9.1`). */
|
|
126
128
|
export type RefreshChannel = string;
|
|
@@ -170,6 +172,9 @@ export declare function buildSkillsVersionCheck(input: SkillsVersionCheckInput):
|
|
|
170
172
|
* summer-engine entry refreshes with `--cli`, so the refresh adds no MCP server.
|
|
171
173
|
*/
|
|
172
174
|
export declare function skillsRefreshCommand(agent: string, install: RecordedInstall | null, channel?: RefreshChannel): string;
|
|
175
|
+
/** The shape `summer setup --runtime <node> --package-dir <dir>` writes:
|
|
176
|
+
* `<absolute path to node> <dir>/dist/bin/summer.js mcp` (bundledRuntimeServerConfig). */
|
|
177
|
+
export declare function isBundledRuntimeServerConfig(server: StdioMcpServerConfig): boolean;
|
|
173
178
|
/** The shape `summer setup --local-dev` writes: `node <…>/dist/bin/summer.js mcp`
|
|
174
179
|
* (createSummerMcpServerConfig(true)). */
|
|
175
180
|
export declare function isLocalDevServerConfig(server: StdioMcpServerConfig): boolean;
|
|
@@ -405,11 +405,29 @@ export function skillsRefreshCommand(agent, install, channel = "latest") {
|
|
|
405
405
|
? `node ${install.cliPath} setup ${agent} --cli --yes --force`
|
|
406
406
|
: `npx clear-npx-cache && npx -y summer-engine@${channel} setup ${agent} --cli --yes --force`;
|
|
407
407
|
}
|
|
408
|
+
if (install?.runtime && install.cliPath) {
|
|
409
|
+
// Keep the bundled runtime: the npx form needs a Node.js the person may not have.
|
|
410
|
+
const packageDir = install.cliPath.replace(/[\\/]dist[\\/]bin[\\/]summer\.js$/, "");
|
|
411
|
+
const runtime = shellArg(install.runtime);
|
|
412
|
+
return `${runtime} ${shellArg(install.cliPath)} setup ${agent} --runtime ${runtime} --package-dir ${shellArg(packageDir)} --yes --force`;
|
|
413
|
+
}
|
|
408
414
|
if (install?.localDev && install.cliPath) {
|
|
409
415
|
return `node ${install.cliPath} setup ${agent} --local-dev --yes --force`;
|
|
410
416
|
}
|
|
411
417
|
return `npx clear-npx-cache && npx -y summer-engine@${channel} setup ${agent} --yes --force${channel === "latest" ? "" : ` --channel ${channel}`}`;
|
|
412
418
|
}
|
|
419
|
+
/** A path in a printed command: quoted when it has a space (~/Library/Application Support, C:\\Program Files). */
|
|
420
|
+
function shellArg(value) {
|
|
421
|
+
return /[\s"'$`]/.test(value) ? JSON.stringify(value) : value;
|
|
422
|
+
}
|
|
423
|
+
/** The shape `summer setup --runtime <node> --package-dir <dir>` writes:
|
|
424
|
+
* `<absolute path to node> <dir>/dist/bin/summer.js mcp` (bundledRuntimeServerConfig). */
|
|
425
|
+
export function isBundledRuntimeServerConfig(server) {
|
|
426
|
+
return (/^([a-z]:)?[\\/]/i.test(server.command) &&
|
|
427
|
+
/(^|[\\/])node(\.exe)?$/i.test(server.command) &&
|
|
428
|
+
/[\\/]dist[\\/]bin[\\/]summer\.js$/.test(server.args[0] ?? "") &&
|
|
429
|
+
server.args[1] === "mcp");
|
|
430
|
+
}
|
|
413
431
|
/** The shape `summer setup --local-dev` writes: `node <…>/dist/bin/summer.js mcp`
|
|
414
432
|
* (createSummerMcpServerConfig(true)). */
|
|
415
433
|
export function isLocalDevServerConfig(server) {
|
|
@@ -550,6 +568,9 @@ export async function detectRecordedInstall(agent) {
|
|
|
550
568
|
const text = existsSync(target.path) ? readFileSync(target.path, "utf-8") : "";
|
|
551
569
|
const recorded = readRecordedMcpServer(text, target.format);
|
|
552
570
|
if (recorded) {
|
|
571
|
+
if (isBundledRuntimeServerConfig(recorded)) {
|
|
572
|
+
return { localDev: false, cliPath: recorded.args[0], runtime: recorded.command, source: "agent-config" };
|
|
573
|
+
}
|
|
553
574
|
const localDev = isLocalDevServerConfig(recorded);
|
|
554
575
|
return { localDev, cliPath: localDev ? recorded.args[0] ?? null : null, source: "agent-config" };
|
|
555
576
|
}
|