@primeuicom/agent-setup 0.1.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/dist/index.d.ts +136 -0
- package/dist/index.js +1002 -0
- package/dist/index.js.map +1 -0
- package/package.json +37 -0
- package/presets/claude-code/.claude/settings.json +25 -0
- package/presets/claude-code/.claude/skills/git-commit/SKILL.md +124 -0
- package/presets/claude-code/.claude/skills/next-best-practices/SKILL.md +152 -0
- package/presets/claude-code/.claude/skills/tailwind-design-system/SKILL.md +874 -0
- package/presets/claude-code/.claude/skills/vitest/SKILL.md +52 -0
- package/presets/claude-code/.mcp.json +25 -0
- package/presets/claude-code/skills-lock.json +16 -0
- package/presets/codex/.agents/skills/git-commit/SKILL.md +124 -0
- package/presets/codex/.agents/skills/next-best-practices/SKILL.md +152 -0
- package/presets/codex/.agents/skills/tailwind-design-system/SKILL.md +874 -0
- package/presets/codex/.agents/skills/vitest/SKILL.md +52 -0
- package/presets/codex/.codex/config.toml +17 -0
- package/presets/codex/skills-lock.json +16 -0
- package/presets/cursor/.agents/skills/git-commit/SKILL.md +124 -0
- package/presets/cursor/.agents/skills/next-best-practices/SKILL.md +152 -0
- package/presets/cursor/.agents/skills/tailwind-design-system/SKILL.md +874 -0
- package/presets/cursor/.agents/skills/vitest/SKILL.md +52 -0
- package/presets/cursor/.cursor/cli.json +17 -0
- package/presets/cursor/.cursor/mcp.json +25 -0
- package/presets/cursor/.mcp.json +28 -0
- package/presets/cursor/skills-lock.json +16 -0
- package/presets/gemini-cli/.agents/skills/git-commit/SKILL.md +124 -0
- package/presets/gemini-cli/.agents/skills/next-best-practices/SKILL.md +152 -0
- package/presets/gemini-cli/.agents/skills/tailwind-design-system/SKILL.md +874 -0
- package/presets/gemini-cli/.agents/skills/vitest/SKILL.md +52 -0
- package/presets/gemini-cli/.gemini/settings.json +25 -0
- package/presets/gemini-cli/skills-lock.json +16 -0
- package/presets/mcporter/config/mcporter.json +25 -0
- package/presets/opencode/.agents/skills/git-commit/SKILL.md +124 -0
- package/presets/opencode/.agents/skills/next-best-practices/SKILL.md +152 -0
- package/presets/opencode/.agents/skills/tailwind-design-system/SKILL.md +874 -0
- package/presets/opencode/.agents/skills/vitest/SKILL.md +52 -0
- package/presets/opencode/opencode.json +34 -0
- package/presets/opencode/skills-lock.json +16 -0
- package/presets/vscode/.vscode/mcp.json +25 -0
- package/presets/zed/.zed/settings.json +31 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1002 @@
|
|
|
1
|
+
// src/ai-presets.ts
|
|
2
|
+
var PRIMEUI_AI_PRESET_VALUES = ["codex", "claude", "cursor"];
|
|
3
|
+
var DEFAULT_PRIMEUI_AI_PRESET = "codex";
|
|
4
|
+
var PRIMEUI_AI_SETUP_CHOICE_VALUES = [
|
|
5
|
+
...PRIMEUI_AI_PRESET_VALUES,
|
|
6
|
+
"nothing"
|
|
7
|
+
];
|
|
8
|
+
var PRIMEUI_AI_PRESET_OPTIONS = [
|
|
9
|
+
{
|
|
10
|
+
value: "codex",
|
|
11
|
+
label: "Codex",
|
|
12
|
+
hint: "Write project-local Codex config and install the shared PrimeUI AI toolchain."
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
value: "claude",
|
|
16
|
+
label: "Claude Code",
|
|
17
|
+
hint: "Write project-local Claude settings and install the shared PrimeUI AI toolchain."
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
value: "cursor",
|
|
21
|
+
label: "Cursor",
|
|
22
|
+
hint: "Write project-local Cursor config and install the shared PrimeUI AI toolchain."
|
|
23
|
+
}
|
|
24
|
+
];
|
|
25
|
+
var PRIMEUI_AI_SETUP_CHOICE_OPTIONS = [
|
|
26
|
+
...PRIMEUI_AI_PRESET_OPTIONS,
|
|
27
|
+
{
|
|
28
|
+
value: "nothing",
|
|
29
|
+
label: "Nothing",
|
|
30
|
+
hint: "Skip project-local AI setup for now and leave the project unconfigured."
|
|
31
|
+
}
|
|
32
|
+
];
|
|
33
|
+
function isPrimeUiAiPreset(value) {
|
|
34
|
+
return PRIMEUI_AI_PRESET_VALUES.includes(value);
|
|
35
|
+
}
|
|
36
|
+
function isPrimeUiAiSetupChoice(value) {
|
|
37
|
+
return PRIMEUI_AI_SETUP_CHOICE_VALUES.includes(value);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// src/agent-presets.ts
|
|
41
|
+
import { readdir } from "fs/promises";
|
|
42
|
+
import path from "path";
|
|
43
|
+
import { fileURLToPath } from "url";
|
|
44
|
+
var PRIMEUI_SUPPORTED_AGENT_VALUES = [
|
|
45
|
+
"claude-code",
|
|
46
|
+
"codex",
|
|
47
|
+
"cursor",
|
|
48
|
+
"gemini-cli",
|
|
49
|
+
"opencode",
|
|
50
|
+
"vscode",
|
|
51
|
+
"zed",
|
|
52
|
+
"mcporter"
|
|
53
|
+
];
|
|
54
|
+
var PRESET_ROOT_DIRECTORY = fileURLToPath(
|
|
55
|
+
new URL("../presets", import.meta.url)
|
|
56
|
+
);
|
|
57
|
+
var SUPPORTED_AGENT_PRESETS = {
|
|
58
|
+
"claude-code": {
|
|
59
|
+
agent: "claude-code",
|
|
60
|
+
supportLevel: "full",
|
|
61
|
+
presetDirName: "claude-code",
|
|
62
|
+
mcpFiles: [".mcp.json", ".claude/settings.json"],
|
|
63
|
+
detectionPaths: [".claude/settings.json", ".claude"],
|
|
64
|
+
presetInferencePaths: [".claude/settings.json"],
|
|
65
|
+
skillsDirectory: ".claude/skills",
|
|
66
|
+
skillsLockFile: "skills-lock.json",
|
|
67
|
+
aiPreset: "claude"
|
|
68
|
+
},
|
|
69
|
+
codex: {
|
|
70
|
+
agent: "codex",
|
|
71
|
+
supportLevel: "full",
|
|
72
|
+
presetDirName: "codex",
|
|
73
|
+
mcpFiles: [".codex/config.toml"],
|
|
74
|
+
detectionPaths: [".codex/config.toml", ".codex"],
|
|
75
|
+
presetInferencePaths: [".codex/config.toml"],
|
|
76
|
+
skillsDirectory: ".agents/skills",
|
|
77
|
+
skillsLockFile: "skills-lock.json",
|
|
78
|
+
aiPreset: "codex"
|
|
79
|
+
},
|
|
80
|
+
cursor: {
|
|
81
|
+
agent: "cursor",
|
|
82
|
+
supportLevel: "full",
|
|
83
|
+
presetDirName: "cursor",
|
|
84
|
+
mcpFiles: [".mcp.json", ".cursor/cli.json", ".cursor/mcp.json"],
|
|
85
|
+
detectionPaths: [".cursor/cli.json", ".cursor/mcp.json", ".cursor"],
|
|
86
|
+
presetInferencePaths: [".cursor/cli.json"],
|
|
87
|
+
skillsDirectory: ".agents/skills",
|
|
88
|
+
skillsLockFile: "skills-lock.json",
|
|
89
|
+
aiPreset: "cursor"
|
|
90
|
+
},
|
|
91
|
+
"gemini-cli": {
|
|
92
|
+
agent: "gemini-cli",
|
|
93
|
+
supportLevel: "full",
|
|
94
|
+
presetDirName: "gemini-cli",
|
|
95
|
+
mcpFiles: [".gemini/settings.json"],
|
|
96
|
+
detectionPaths: [".gemini/settings.json", ".gemini"],
|
|
97
|
+
skillsDirectory: ".agents/skills",
|
|
98
|
+
skillsLockFile: "skills-lock.json"
|
|
99
|
+
},
|
|
100
|
+
opencode: {
|
|
101
|
+
agent: "opencode",
|
|
102
|
+
supportLevel: "full",
|
|
103
|
+
presetDirName: "opencode",
|
|
104
|
+
mcpFiles: ["opencode.json"],
|
|
105
|
+
detectionPaths: ["opencode.json", ".opencode"],
|
|
106
|
+
skillsDirectory: ".agents/skills",
|
|
107
|
+
skillsLockFile: "skills-lock.json"
|
|
108
|
+
},
|
|
109
|
+
vscode: {
|
|
110
|
+
agent: "vscode",
|
|
111
|
+
supportLevel: "mcp-only",
|
|
112
|
+
presetDirName: "vscode",
|
|
113
|
+
mcpFiles: [".vscode/mcp.json"],
|
|
114
|
+
detectionPaths: [".vscode/mcp.json", ".vscode"]
|
|
115
|
+
},
|
|
116
|
+
zed: {
|
|
117
|
+
agent: "zed",
|
|
118
|
+
supportLevel: "mcp-only",
|
|
119
|
+
presetDirName: "zed",
|
|
120
|
+
mcpFiles: [".zed/settings.json"],
|
|
121
|
+
detectionPaths: [".zed/settings.json", ".zed"]
|
|
122
|
+
},
|
|
123
|
+
mcporter: {
|
|
124
|
+
agent: "mcporter",
|
|
125
|
+
supportLevel: "mcp-only",
|
|
126
|
+
presetDirName: "mcporter",
|
|
127
|
+
mcpFiles: ["config/mcporter.json"],
|
|
128
|
+
detectionPaths: ["config/mcporter.json"]
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
function listPrimeUiSupportedAgents() {
|
|
132
|
+
return [...PRIMEUI_SUPPORTED_AGENT_VALUES];
|
|
133
|
+
}
|
|
134
|
+
function listPrimeUiSupportedAgentPresets() {
|
|
135
|
+
return PRIMEUI_SUPPORTED_AGENT_VALUES.map((agent) => ({
|
|
136
|
+
...SUPPORTED_AGENT_PRESETS[agent]
|
|
137
|
+
}));
|
|
138
|
+
}
|
|
139
|
+
function getPrimeUiSupportedAgentPreset(agent) {
|
|
140
|
+
return {
|
|
141
|
+
...SUPPORTED_AGENT_PRESETS[agent]
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
function getPrimeUiAgentPresetDirectory(agent) {
|
|
145
|
+
return path.join(
|
|
146
|
+
PRESET_ROOT_DIRECTORY,
|
|
147
|
+
SUPPORTED_AGENT_PRESETS[agent].presetDirName
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
async function walkFiles(rootDirectory, currentDirectory) {
|
|
151
|
+
const entries = await readdir(currentDirectory, { withFileTypes: true });
|
|
152
|
+
const files = [];
|
|
153
|
+
for (const entry of entries) {
|
|
154
|
+
const absolutePath = path.join(currentDirectory, entry.name);
|
|
155
|
+
if (entry.isDirectory()) {
|
|
156
|
+
files.push(...await walkFiles(rootDirectory, absolutePath));
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
if (entry.isFile()) {
|
|
160
|
+
files.push(
|
|
161
|
+
path.relative(rootDirectory, absolutePath).replaceAll(path.sep, "/")
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return files;
|
|
166
|
+
}
|
|
167
|
+
async function listPrimeUiAgentPresetFiles(agent) {
|
|
168
|
+
const presetDirectory = getPrimeUiAgentPresetDirectory(agent);
|
|
169
|
+
const files = await walkFiles(presetDirectory, presetDirectory);
|
|
170
|
+
return files.sort();
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// src/ai-setup-config.ts
|
|
174
|
+
var ROOT_AGENTS_PATH = "AGENTS.md";
|
|
175
|
+
var CLAUDE_INSTRUCTIONS_PATH = "CLAUDE.md";
|
|
176
|
+
var CURSOR_CLI_CONFIG_PATH = ".cursor/cli.json";
|
|
177
|
+
var CLAUDE_SETTINGS_PATH = ".claude/settings.json";
|
|
178
|
+
var CODEX_CONFIG_PATH = ".codex/config.toml";
|
|
179
|
+
var SHARED_MCP_CONFIG = {
|
|
180
|
+
mcpServers: {
|
|
181
|
+
primeui: {
|
|
182
|
+
type: "stdio",
|
|
183
|
+
command: "npx",
|
|
184
|
+
args: ["-y", "@primeuicom/mcp@latest"]
|
|
185
|
+
},
|
|
186
|
+
"chrome-devtools": {
|
|
187
|
+
type: "stdio",
|
|
188
|
+
command: "npx",
|
|
189
|
+
args: ["-y", "chrome-devtools-mcp@latest"]
|
|
190
|
+
},
|
|
191
|
+
"next-devtools": {
|
|
192
|
+
type: "stdio",
|
|
193
|
+
command: "npx",
|
|
194
|
+
args: ["-y", "next-devtools-mcp@latest"]
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
var SHARED_MCP_OVERRIDES = {
|
|
199
|
+
mcpServers: {
|
|
200
|
+
primeui: {
|
|
201
|
+
env: {
|
|
202
|
+
PRIMEUI_API_BASE_URL: {
|
|
203
|
+
from: "runtime-env",
|
|
204
|
+
envName: "PRIMEUI_API_BASE_URL",
|
|
205
|
+
optional: true
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
var SHARED_SKILL_COLLECTIONS = [
|
|
212
|
+
{
|
|
213
|
+
source: "github/awesome-copilot",
|
|
214
|
+
skills: ["git-commit"]
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
source: "vercel-labs/next-skills",
|
|
218
|
+
skills: ["next-best-practices"]
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
source: "pproenca/dot-skills",
|
|
222
|
+
skills: ["vitest"]
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
source: "wshobson/agents",
|
|
226
|
+
skills: ["tailwind-design-system"]
|
|
227
|
+
}
|
|
228
|
+
];
|
|
229
|
+
var SHARED_PERMISSION_PROFILE = {
|
|
230
|
+
shellCommands: ["pnpm", "git", "node", "npx"],
|
|
231
|
+
allowReadAll: true,
|
|
232
|
+
allowWriteAll: true,
|
|
233
|
+
allowMcpServers: Object.keys(SHARED_MCP_CONFIG.mcpServers),
|
|
234
|
+
enableNetworkAccess: true
|
|
235
|
+
};
|
|
236
|
+
var PRESET_DEFINITIONS = {
|
|
237
|
+
codex: {
|
|
238
|
+
agent: "codex",
|
|
239
|
+
configFiles: [CODEX_CONFIG_PATH],
|
|
240
|
+
instructionFiles: [ROOT_AGENTS_PATH]
|
|
241
|
+
},
|
|
242
|
+
claude: {
|
|
243
|
+
agent: "claude-code",
|
|
244
|
+
configFiles: [CLAUDE_SETTINGS_PATH],
|
|
245
|
+
instructionFiles: [CLAUDE_INSTRUCTIONS_PATH]
|
|
246
|
+
},
|
|
247
|
+
cursor: {
|
|
248
|
+
agent: "cursor",
|
|
249
|
+
configFiles: [CURSOR_CLI_CONFIG_PATH],
|
|
250
|
+
instructionFiles: [ROOT_AGENTS_PATH]
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
var PRIMEUI_SHARED_MCP_CONFIG_PATH = ".mcp.json";
|
|
254
|
+
var PRIMEUI_SHARED_SKILLS_LOCK_PATH = "skills-lock.json";
|
|
255
|
+
var PRIMEUI_SHARED_VERIFICATION_SCRIPTS = [
|
|
256
|
+
"format",
|
|
257
|
+
"lint",
|
|
258
|
+
"typecheck",
|
|
259
|
+
"build"
|
|
260
|
+
];
|
|
261
|
+
var PRIMEUI_LOCAL_AI_ARTIFACT_PATHS = [
|
|
262
|
+
".codex",
|
|
263
|
+
".claude",
|
|
264
|
+
".cursor",
|
|
265
|
+
".agents",
|
|
266
|
+
PRIMEUI_SHARED_MCP_CONFIG_PATH,
|
|
267
|
+
PRIMEUI_SHARED_SKILLS_LOCK_PATH
|
|
268
|
+
];
|
|
269
|
+
var PRIMEUI_MANAGED_AI_CLEANUP_PATHS = [
|
|
270
|
+
".codex",
|
|
271
|
+
".claude",
|
|
272
|
+
".cursor",
|
|
273
|
+
PRIMEUI_SHARED_MCP_CONFIG_PATH
|
|
274
|
+
];
|
|
275
|
+
var PRIMEUI_INSTRUCTION_FILE_PATHS = [
|
|
276
|
+
ROOT_AGENTS_PATH,
|
|
277
|
+
CLAUDE_INSTRUCTIONS_PATH
|
|
278
|
+
];
|
|
279
|
+
var SHARED_WORKFLOW_LINES = [
|
|
280
|
+
"- Use `pnpm` for installs and scripts.",
|
|
281
|
+
"- Use the checked-in project scripts before finishing code changes:",
|
|
282
|
+
" - `pnpm format`",
|
|
283
|
+
" - `pnpm lint`",
|
|
284
|
+
" - `pnpm typecheck`",
|
|
285
|
+
" - `pnpm build`",
|
|
286
|
+
"- Start the local preview with `pnpm dev`."
|
|
287
|
+
];
|
|
288
|
+
var SHARED_PRIMEUI_LINES = [
|
|
289
|
+
"- PrimeUI project linkage lives in `.primeui/project.json`.",
|
|
290
|
+
"- PrimeUI CLI configures project-local AI tooling with `npx @primeuicom/cli ai-setup --ai-preset <codex|claude|cursor>`.",
|
|
291
|
+
"- Codex stores PrimeUI MCP server entries in `.codex/config.toml`; Claude and Cursor also keep shared MCP definitions in `.mcp.json`.",
|
|
292
|
+
"- Keep agent configuration project-local and reversible. Do not modify user-global config from this repository."
|
|
293
|
+
];
|
|
294
|
+
function readRuntimeEnvBinding(binding, env) {
|
|
295
|
+
if (binding.from !== "runtime-env") {
|
|
296
|
+
return void 0;
|
|
297
|
+
}
|
|
298
|
+
const value = env[binding.envName]?.trim();
|
|
299
|
+
if (!value) {
|
|
300
|
+
return void 0;
|
|
301
|
+
}
|
|
302
|
+
return value;
|
|
303
|
+
}
|
|
304
|
+
function buildCodexPermissionConfigLines() {
|
|
305
|
+
return [
|
|
306
|
+
'approval_policy = "never"',
|
|
307
|
+
'sandbox_mode = "workspace-write"',
|
|
308
|
+
"",
|
|
309
|
+
"[sandbox_workspace_write]",
|
|
310
|
+
`network_access = ${SHARED_PERMISSION_PROFILE.enableNetworkAccess ? "true" : "false"}`
|
|
311
|
+
];
|
|
312
|
+
}
|
|
313
|
+
function buildClaudeAllowedPermissions() {
|
|
314
|
+
const mcpPermissions = SHARED_PERMISSION_PROFILE.allowMcpServers.map(
|
|
315
|
+
(serverName) => `mcp__${serverName}__*`
|
|
316
|
+
);
|
|
317
|
+
return [
|
|
318
|
+
...SHARED_PERMISSION_PROFILE.shellCommands.map(
|
|
319
|
+
(command) => `Bash(${command}:*)`
|
|
320
|
+
),
|
|
321
|
+
"Bash(sleep:*)",
|
|
322
|
+
"Bash(kill:*)",
|
|
323
|
+
"Bash(wait:*)",
|
|
324
|
+
...SHARED_PERMISSION_PROFILE.allowReadAll ? ["Read"] : [],
|
|
325
|
+
...SHARED_PERMISSION_PROFILE.allowWriteAll ? ["Edit"] : [],
|
|
326
|
+
...mcpPermissions
|
|
327
|
+
];
|
|
328
|
+
}
|
|
329
|
+
function buildCursorAllowedPermissions() {
|
|
330
|
+
const mcpPermissions = SHARED_PERMISSION_PROFILE.allowMcpServers.map(
|
|
331
|
+
(serverName) => `Mcp(${serverName}:*)`
|
|
332
|
+
);
|
|
333
|
+
return [
|
|
334
|
+
...SHARED_PERMISSION_PROFILE.shellCommands.map(
|
|
335
|
+
(command) => `Shell(${command}:*)`
|
|
336
|
+
),
|
|
337
|
+
...SHARED_PERMISSION_PROFILE.allowReadAll ? ["Read(**/*)"] : [],
|
|
338
|
+
...SHARED_PERMISSION_PROFILE.allowWriteAll ? ["Write(**/*)"] : [],
|
|
339
|
+
...mcpPermissions
|
|
340
|
+
];
|
|
341
|
+
}
|
|
342
|
+
function buildSharedWorkflowSectionLines() {
|
|
343
|
+
return ["## Workflow", "", ...SHARED_WORKFLOW_LINES];
|
|
344
|
+
}
|
|
345
|
+
function buildSharedPrimeUiSectionLines() {
|
|
346
|
+
return ["## PrimeUI Integration", "", ...SHARED_PRIMEUI_LINES];
|
|
347
|
+
}
|
|
348
|
+
function buildSharedAgentsInstructionsContent() {
|
|
349
|
+
return [
|
|
350
|
+
"# PrimeUI Exported Project",
|
|
351
|
+
"",
|
|
352
|
+
...buildSharedWorkflowSectionLines(),
|
|
353
|
+
"",
|
|
354
|
+
...buildSharedPrimeUiSectionLines(),
|
|
355
|
+
"",
|
|
356
|
+
"## Codex and Cursor Notes",
|
|
357
|
+
"",
|
|
358
|
+
"- Codex and Cursor both read repository instructions from `AGENTS.md`.",
|
|
359
|
+
"- Project-local Codex settings live in `.codex/config.toml` after CLI AI setup.",
|
|
360
|
+
"- Project-local Cursor settings live in `.cursor/cli.json` after CLI AI setup.",
|
|
361
|
+
"- PrimeUI CLI installs shared MCP servers and public skills project-locally during AI setup.",
|
|
362
|
+
"- The user still needs a local agent install/login for Codex or Cursor."
|
|
363
|
+
].join("\n");
|
|
364
|
+
}
|
|
365
|
+
function buildClaudeInstructionsContent() {
|
|
366
|
+
return [
|
|
367
|
+
"# PrimeUI Exported Project",
|
|
368
|
+
"",
|
|
369
|
+
...buildSharedWorkflowSectionLines(),
|
|
370
|
+
"",
|
|
371
|
+
...buildSharedPrimeUiSectionLines(),
|
|
372
|
+
"",
|
|
373
|
+
"## Claude Code Notes",
|
|
374
|
+
"",
|
|
375
|
+
"- Claude Code reads repository instructions from `CLAUDE.md`.",
|
|
376
|
+
"- Project-local Claude settings live in `.claude/settings.json` after CLI AI setup.",
|
|
377
|
+
"- PrimeUI CLI installs shared MCP servers and public skills project-locally during AI setup.",
|
|
378
|
+
"- The user still needs a local Claude Code install/login."
|
|
379
|
+
].join("\n");
|
|
380
|
+
}
|
|
381
|
+
function getPrimeUiAiAgent(aiPreset) {
|
|
382
|
+
return PRESET_DEFINITIONS[aiPreset].agent;
|
|
383
|
+
}
|
|
384
|
+
function getPrimeUiManagedConfigFiles(aiPreset) {
|
|
385
|
+
return [...PRESET_DEFINITIONS[aiPreset].configFiles];
|
|
386
|
+
}
|
|
387
|
+
function getPrimeUiManagedInstructionFiles(aiPreset) {
|
|
388
|
+
return [...PRESET_DEFINITIONS[aiPreset].instructionFiles];
|
|
389
|
+
}
|
|
390
|
+
function getPrimeUiManagedConfigFileContents(aiPreset) {
|
|
391
|
+
switch (aiPreset) {
|
|
392
|
+
case "codex":
|
|
393
|
+
return {
|
|
394
|
+
[CODEX_CONFIG_PATH]: buildPrimeUiCodexConfigToml()
|
|
395
|
+
};
|
|
396
|
+
case "claude":
|
|
397
|
+
return {
|
|
398
|
+
[CLAUDE_SETTINGS_PATH]: buildPrimeUiClaudeSettingsFileContent()
|
|
399
|
+
};
|
|
400
|
+
case "cursor":
|
|
401
|
+
return {
|
|
402
|
+
[CURSOR_CLI_CONFIG_PATH]: buildPrimeUiCursorCliConfigFileContent()
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
function getPrimeUiManagedInstructionFileContents(aiPreset) {
|
|
407
|
+
switch (aiPreset) {
|
|
408
|
+
case "codex":
|
|
409
|
+
case "cursor":
|
|
410
|
+
return {
|
|
411
|
+
[ROOT_AGENTS_PATH]: `${buildSharedAgentsInstructionsContent()}
|
|
412
|
+
`
|
|
413
|
+
};
|
|
414
|
+
case "claude":
|
|
415
|
+
return {
|
|
416
|
+
[CLAUDE_INSTRUCTIONS_PATH]: `${buildClaudeInstructionsContent()}
|
|
417
|
+
`
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
function listPrimeUiAiSkillRefs() {
|
|
422
|
+
return SHARED_SKILL_COLLECTIONS.flatMap(
|
|
423
|
+
(collection) => collection.skills.map((skill) => `${collection.source}@${skill}`)
|
|
424
|
+
);
|
|
425
|
+
}
|
|
426
|
+
function listPrimeUiAiSkillCollections() {
|
|
427
|
+
return SHARED_SKILL_COLLECTIONS.map((collection) => ({
|
|
428
|
+
source: collection.source,
|
|
429
|
+
skills: [...collection.skills]
|
|
430
|
+
}));
|
|
431
|
+
}
|
|
432
|
+
function getPrimeUiInstalledSkillsDirectory(aiPreset) {
|
|
433
|
+
return aiPreset === "claude" ? ".claude/skills" : ".agents/skills";
|
|
434
|
+
}
|
|
435
|
+
function listPrimeUiAllowedShellCommands() {
|
|
436
|
+
return [...SHARED_PERMISSION_PROFILE.shellCommands];
|
|
437
|
+
}
|
|
438
|
+
function listPrimeUiAllowedMcpServers() {
|
|
439
|
+
return [...SHARED_PERMISSION_PROFILE.allowMcpServers];
|
|
440
|
+
}
|
|
441
|
+
function listPrimeUiClaudeAllowedPermissions() {
|
|
442
|
+
return buildClaudeAllowedPermissions();
|
|
443
|
+
}
|
|
444
|
+
function listPrimeUiCursorAllowedPermissions() {
|
|
445
|
+
return buildCursorAllowedPermissions();
|
|
446
|
+
}
|
|
447
|
+
function listPrimeUiInstructionFilePaths() {
|
|
448
|
+
return [...PRIMEUI_INSTRUCTION_FILE_PATHS];
|
|
449
|
+
}
|
|
450
|
+
function listPrimeUiVerificationScripts() {
|
|
451
|
+
return [...PRIMEUI_SHARED_VERIFICATION_SCRIPTS];
|
|
452
|
+
}
|
|
453
|
+
function shouldWritePrimeUiSharedMcpConfig(aiPreset) {
|
|
454
|
+
return aiPreset !== "codex";
|
|
455
|
+
}
|
|
456
|
+
function resolvePrimeUiMcpConfig(env = process.env) {
|
|
457
|
+
const mcpServers = Object.fromEntries(
|
|
458
|
+
Object.entries(SHARED_MCP_CONFIG.mcpServers).map(
|
|
459
|
+
([serverName, serverConfig]) => {
|
|
460
|
+
const overrideEnv = SHARED_MCP_OVERRIDES.mcpServers[serverName]?.env;
|
|
461
|
+
const resolvedEnvEntries = Object.entries(overrideEnv ?? {}).map(([envName, binding]) => {
|
|
462
|
+
const value = readRuntimeEnvBinding(binding, env);
|
|
463
|
+
if (!value) {
|
|
464
|
+
return void 0;
|
|
465
|
+
}
|
|
466
|
+
return [envName, value];
|
|
467
|
+
}).filter(
|
|
468
|
+
(entry) => Boolean(entry)
|
|
469
|
+
);
|
|
470
|
+
return [
|
|
471
|
+
serverName,
|
|
472
|
+
{
|
|
473
|
+
...serverConfig,
|
|
474
|
+
...resolvedEnvEntries.length > 0 ? { env: Object.fromEntries(resolvedEnvEntries) } : {}
|
|
475
|
+
}
|
|
476
|
+
];
|
|
477
|
+
}
|
|
478
|
+
)
|
|
479
|
+
);
|
|
480
|
+
return { mcpServers };
|
|
481
|
+
}
|
|
482
|
+
function createPrimeUiAiSetupEnv(env = process.env, primeUiApiBaseUrl) {
|
|
483
|
+
if (!primeUiApiBaseUrl?.trim()) {
|
|
484
|
+
return env;
|
|
485
|
+
}
|
|
486
|
+
return {
|
|
487
|
+
...env,
|
|
488
|
+
PRIMEUI_API_BASE_URL: primeUiApiBaseUrl.trim()
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
function buildPrimeUiCodexConfigToml() {
|
|
492
|
+
return [
|
|
493
|
+
"# Project-scoped Codex config for this PrimeUI project.",
|
|
494
|
+
"# PrimeUI CLI manages this file and add-mcp appends MCP server entries.",
|
|
495
|
+
...buildCodexPermissionConfigLines(),
|
|
496
|
+
""
|
|
497
|
+
].join("\n");
|
|
498
|
+
}
|
|
499
|
+
function buildPrimeUiClaudeSettings() {
|
|
500
|
+
return {
|
|
501
|
+
enableAllProjectMcpServers: true,
|
|
502
|
+
enabledMcpjsonServers: SHARED_PERMISSION_PROFILE.allowMcpServers,
|
|
503
|
+
permissions: {
|
|
504
|
+
allow: buildClaudeAllowedPermissions(),
|
|
505
|
+
deny: []
|
|
506
|
+
}
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
function buildPrimeUiClaudeSettingsFileContent() {
|
|
510
|
+
return `${JSON.stringify(buildPrimeUiClaudeSettings(), null, 2)}
|
|
511
|
+
`;
|
|
512
|
+
}
|
|
513
|
+
function buildPrimeUiCursorCliConfig() {
|
|
514
|
+
return {
|
|
515
|
+
version: 1,
|
|
516
|
+
permissions: {
|
|
517
|
+
allow: buildCursorAllowedPermissions(),
|
|
518
|
+
deny: []
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
function buildPrimeUiCursorCliConfigFileContent() {
|
|
523
|
+
return `${JSON.stringify(buildPrimeUiCursorCliConfig(), null, 2)}
|
|
524
|
+
`;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
// src/ai-setup.ts
|
|
528
|
+
import {
|
|
529
|
+
access,
|
|
530
|
+
cp,
|
|
531
|
+
mkdir,
|
|
532
|
+
mkdtemp,
|
|
533
|
+
readFile,
|
|
534
|
+
rm,
|
|
535
|
+
writeFile
|
|
536
|
+
} from "fs/promises";
|
|
537
|
+
import os from "os";
|
|
538
|
+
import path2 from "path";
|
|
539
|
+
import { execa } from "execa";
|
|
540
|
+
|
|
541
|
+
// src/errors.ts
|
|
542
|
+
var PRIMEUI_AGENT_SETUP_ERROR_CODES = {
|
|
543
|
+
AI_SETUP_FAILED: "AI_SETUP_FAILED",
|
|
544
|
+
UNKNOWN: "UNKNOWN"
|
|
545
|
+
};
|
|
546
|
+
var PrimeUiAgentSetupError = class extends Error {
|
|
547
|
+
code;
|
|
548
|
+
hint;
|
|
549
|
+
constructor(message, options = {}) {
|
|
550
|
+
super(message, { cause: options.cause });
|
|
551
|
+
this.name = "PrimeUiAgentSetupError";
|
|
552
|
+
this.code = options.code ?? PRIMEUI_AGENT_SETUP_ERROR_CODES.UNKNOWN;
|
|
553
|
+
this.hint = options.hint;
|
|
554
|
+
}
|
|
555
|
+
};
|
|
556
|
+
function toPrimeUiAgentSetupError(error) {
|
|
557
|
+
if (error instanceof PrimeUiAgentSetupError) {
|
|
558
|
+
return error;
|
|
559
|
+
}
|
|
560
|
+
return new PrimeUiAgentSetupError(
|
|
561
|
+
error instanceof Error ? error.message : String(error),
|
|
562
|
+
{
|
|
563
|
+
cause: error
|
|
564
|
+
}
|
|
565
|
+
);
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
// src/ai-setup.ts
|
|
569
|
+
function formatCommandHint(command, args) {
|
|
570
|
+
return [command, ...args].join(" ");
|
|
571
|
+
}
|
|
572
|
+
function createCommandFailure(message, command, args, result) {
|
|
573
|
+
const stderr = result.stderr.trim();
|
|
574
|
+
const stdout = result.stdout.trim();
|
|
575
|
+
return new PrimeUiAgentSetupError(message, {
|
|
576
|
+
code: PRIMEUI_AGENT_SETUP_ERROR_CODES.AI_SETUP_FAILED,
|
|
577
|
+
hint: stderr || stdout || `Retry from the project directory with: ${formatCommandHint(command, args)}`
|
|
578
|
+
});
|
|
579
|
+
}
|
|
580
|
+
function resolveAddMcpInstallTarget(serverName, serverConfig) {
|
|
581
|
+
if (serverConfig.type === "stdio" && serverConfig.command === "npx" && serverConfig.args.length === 2 && serverConfig.args[0] === "-y") {
|
|
582
|
+
return serverConfig.args[1];
|
|
583
|
+
}
|
|
584
|
+
throw new PrimeUiAgentSetupError(
|
|
585
|
+
`PrimeUI AI setup cannot install MCP server "${serverName}" from this config shape automatically.`,
|
|
586
|
+
{
|
|
587
|
+
code: PRIMEUI_AGENT_SETUP_ERROR_CODES.AI_SETUP_FAILED,
|
|
588
|
+
hint: "Only stdio MCP entries shaped like `npx -y <package>` are supported for automated setup right now."
|
|
589
|
+
}
|
|
590
|
+
);
|
|
591
|
+
}
|
|
592
|
+
function collapseStringArrayBlocks(json) {
|
|
593
|
+
return json.replace(
|
|
594
|
+
/\[\n(\s+)((?:"(?:\\.|[^"\n])*"(?:,\n\1"(?:\\.|[^"\n])*")*))\n(\s*)\]/g,
|
|
595
|
+
(_match, _indent, items) => {
|
|
596
|
+
const collapsedItems = items.split("\n").map((line) => line.trim()).join(" ");
|
|
597
|
+
return `[${collapsedItems}]`;
|
|
598
|
+
}
|
|
599
|
+
);
|
|
600
|
+
}
|
|
601
|
+
function formatSharedMcpConfigFileContent(config) {
|
|
602
|
+
return `${collapseStringArrayBlocks(JSON.stringify(config, null, 2))}
|
|
603
|
+
`;
|
|
604
|
+
}
|
|
605
|
+
async function pathExists(targetPath) {
|
|
606
|
+
try {
|
|
607
|
+
await access(targetPath);
|
|
608
|
+
return true;
|
|
609
|
+
} catch {
|
|
610
|
+
return false;
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
async function writeManagedFile(projectDirectory, relativePath, content) {
|
|
614
|
+
const filePath = path2.join(projectDirectory, relativePath);
|
|
615
|
+
await mkdir(path2.dirname(filePath), { recursive: true });
|
|
616
|
+
await writeFile(filePath, content, "utf-8");
|
|
617
|
+
}
|
|
618
|
+
async function cleanupManagedAiFiles(projectDirectory) {
|
|
619
|
+
for (const relativePath of PRIMEUI_MANAGED_AI_CLEANUP_PATHS) {
|
|
620
|
+
await rm(path2.join(projectDirectory, relativePath), {
|
|
621
|
+
force: true,
|
|
622
|
+
recursive: true
|
|
623
|
+
}).catch(() => void 0);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
function listAiSetupBackupPaths() {
|
|
627
|
+
return [
|
|
628
|
+
...PRIMEUI_LOCAL_AI_ARTIFACT_PATHS,
|
|
629
|
+
...listPrimeUiInstructionFilePaths()
|
|
630
|
+
];
|
|
631
|
+
}
|
|
632
|
+
async function createAiSetupBackup(projectDirectory) {
|
|
633
|
+
const backupDir = await mkdtemp(
|
|
634
|
+
path2.join(os.tmpdir(), "primeui-agent-setup-backup-")
|
|
635
|
+
);
|
|
636
|
+
for (const relativePath of listAiSetupBackupPaths()) {
|
|
637
|
+
const sourcePath = path2.join(projectDirectory, relativePath);
|
|
638
|
+
if (!await pathExists(sourcePath)) {
|
|
639
|
+
continue;
|
|
640
|
+
}
|
|
641
|
+
const backupPath = path2.join(backupDir, relativePath);
|
|
642
|
+
await mkdir(path2.dirname(backupPath), { recursive: true });
|
|
643
|
+
await cp(sourcePath, backupPath, {
|
|
644
|
+
force: true,
|
|
645
|
+
recursive: true
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
return backupDir;
|
|
649
|
+
}
|
|
650
|
+
async function removeLocalAiArtifacts(projectDirectory) {
|
|
651
|
+
for (const relativePath of listAiSetupBackupPaths()) {
|
|
652
|
+
await rm(path2.join(projectDirectory, relativePath), {
|
|
653
|
+
force: true,
|
|
654
|
+
recursive: true
|
|
655
|
+
}).catch(() => void 0);
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
async function restoreAiSetupBackup(projectDirectory, backupDir) {
|
|
659
|
+
await removeLocalAiArtifacts(projectDirectory);
|
|
660
|
+
for (const relativePath of listAiSetupBackupPaths()) {
|
|
661
|
+
const backupPath = path2.join(backupDir, relativePath);
|
|
662
|
+
if (!await pathExists(backupPath)) {
|
|
663
|
+
continue;
|
|
664
|
+
}
|
|
665
|
+
const targetPath = path2.join(projectDirectory, relativePath);
|
|
666
|
+
await mkdir(path2.dirname(targetPath), { recursive: true });
|
|
667
|
+
await cp(backupPath, targetPath, {
|
|
668
|
+
force: true,
|
|
669
|
+
recursive: true
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
async function writeManagedPresetFiles(projectDirectory, aiPreset) {
|
|
674
|
+
const managedFiles = getPrimeUiManagedConfigFileContents(aiPreset);
|
|
675
|
+
for (const [relativePath, content] of Object.entries(managedFiles)) {
|
|
676
|
+
await writeManagedFile(projectDirectory, relativePath, content);
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
async function writeManagedInstructionFiles(projectDirectory, aiPreset) {
|
|
680
|
+
const managedFiles = getPrimeUiManagedInstructionFileContents(aiPreset);
|
|
681
|
+
for (const [relativePath, content] of Object.entries(managedFiles)) {
|
|
682
|
+
await writeManagedFile(projectDirectory, relativePath, content);
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
async function writeSharedMcpConfig(projectDirectory, config) {
|
|
686
|
+
await writeManagedFile(
|
|
687
|
+
projectDirectory,
|
|
688
|
+
PRIMEUI_SHARED_MCP_CONFIG_PATH,
|
|
689
|
+
formatSharedMcpConfigFileContent(config)
|
|
690
|
+
);
|
|
691
|
+
}
|
|
692
|
+
async function installMcpServer(params) {
|
|
693
|
+
const installTarget = resolveAddMcpInstallTarget(
|
|
694
|
+
params.serverName,
|
|
695
|
+
params.serverConfig
|
|
696
|
+
);
|
|
697
|
+
const args = [
|
|
698
|
+
"-y",
|
|
699
|
+
"add-mcp@latest",
|
|
700
|
+
"-a",
|
|
701
|
+
params.agent,
|
|
702
|
+
"-n",
|
|
703
|
+
params.serverName,
|
|
704
|
+
installTarget,
|
|
705
|
+
"--yes"
|
|
706
|
+
];
|
|
707
|
+
for (const [envName, value] of Object.entries(
|
|
708
|
+
params.serverConfig.env ?? {}
|
|
709
|
+
)) {
|
|
710
|
+
args.push("--env", `${envName}=${value}`);
|
|
711
|
+
}
|
|
712
|
+
const result = await params.execaFn("npx", args, {
|
|
713
|
+
cwd: params.cwd,
|
|
714
|
+
reject: false,
|
|
715
|
+
stdout: "pipe",
|
|
716
|
+
stderr: "pipe"
|
|
717
|
+
});
|
|
718
|
+
if (result.exitCode !== 0) {
|
|
719
|
+
throw createCommandFailure(
|
|
720
|
+
`Failed to install MCP server "${params.serverName}" for ${params.agent}.`,
|
|
721
|
+
"npx",
|
|
722
|
+
args,
|
|
723
|
+
result
|
|
724
|
+
);
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
async function cleanupUnmanagedInstructionFiles(projectDirectory, aiPreset) {
|
|
728
|
+
const managedInstructionFiles = new Set(
|
|
729
|
+
getPrimeUiManagedInstructionFiles(aiPreset)
|
|
730
|
+
);
|
|
731
|
+
for (const relativePath of listPrimeUiInstructionFilePaths()) {
|
|
732
|
+
if (managedInstructionFiles.has(relativePath)) {
|
|
733
|
+
continue;
|
|
734
|
+
}
|
|
735
|
+
await rm(path2.join(projectDirectory, relativePath), {
|
|
736
|
+
force: true,
|
|
737
|
+
recursive: true
|
|
738
|
+
}).catch(() => void 0);
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
function getTopLevelArtifactPath(relativePath) {
|
|
742
|
+
const [topLevelPath] = relativePath.split("/", 1);
|
|
743
|
+
return topLevelPath || relativePath;
|
|
744
|
+
}
|
|
745
|
+
async function cleanupUnmanagedLocalArtifacts(projectDirectory, aiPreset) {
|
|
746
|
+
const managedArtifactPaths = /* @__PURE__ */ new Set([
|
|
747
|
+
PRIMEUI_SHARED_SKILLS_LOCK_PATH,
|
|
748
|
+
...getPrimeUiManagedConfigFiles(aiPreset).map(getTopLevelArtifactPath)
|
|
749
|
+
]);
|
|
750
|
+
managedArtifactPaths.add(
|
|
751
|
+
getTopLevelArtifactPath(getPrimeUiInstalledSkillsDirectory(aiPreset))
|
|
752
|
+
);
|
|
753
|
+
if (shouldWritePrimeUiSharedMcpConfig(aiPreset)) {
|
|
754
|
+
managedArtifactPaths.add(PRIMEUI_SHARED_MCP_CONFIG_PATH);
|
|
755
|
+
}
|
|
756
|
+
for (const relativePath of PRIMEUI_LOCAL_AI_ARTIFACT_PATHS) {
|
|
757
|
+
if (managedArtifactPaths.has(relativePath)) {
|
|
758
|
+
continue;
|
|
759
|
+
}
|
|
760
|
+
await rm(path2.join(projectDirectory, relativePath), {
|
|
761
|
+
force: true,
|
|
762
|
+
recursive: true
|
|
763
|
+
}).catch(() => void 0);
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
async function normalizeInstalledSkillsDirectory(projectDirectory, aiPreset) {
|
|
767
|
+
const expectedSkillsDirectory = path2.join(
|
|
768
|
+
projectDirectory,
|
|
769
|
+
getPrimeUiInstalledSkillsDirectory(aiPreset)
|
|
770
|
+
);
|
|
771
|
+
const sharedSkillsDirectory = path2.join(
|
|
772
|
+
projectDirectory,
|
|
773
|
+
".agents",
|
|
774
|
+
"skills"
|
|
775
|
+
);
|
|
776
|
+
if (aiPreset === "claude") {
|
|
777
|
+
if (!await pathExists(expectedSkillsDirectory) && await pathExists(sharedSkillsDirectory)) {
|
|
778
|
+
await mkdir(path2.dirname(expectedSkillsDirectory), { recursive: true });
|
|
779
|
+
await cp(sharedSkillsDirectory, expectedSkillsDirectory, {
|
|
780
|
+
force: true,
|
|
781
|
+
recursive: true
|
|
782
|
+
});
|
|
783
|
+
}
|
|
784
|
+
await rm(path2.join(projectDirectory, ".agents"), {
|
|
785
|
+
force: true,
|
|
786
|
+
recursive: true
|
|
787
|
+
}).catch(() => void 0);
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
async function normalizeCodexConfigFormatting(projectDirectory, aiPreset) {
|
|
791
|
+
if (aiPreset !== "codex") {
|
|
792
|
+
return;
|
|
793
|
+
}
|
|
794
|
+
const codexConfigPath = path2.join(projectDirectory, ".codex", "config.toml");
|
|
795
|
+
if (!await pathExists(codexConfigPath)) {
|
|
796
|
+
return;
|
|
797
|
+
}
|
|
798
|
+
const rawConfig = await readFile(codexConfigPath, "utf-8");
|
|
799
|
+
const normalizedConfig = rawConfig.split("\n").map((line) => line.trimStart()).join("\n");
|
|
800
|
+
if (normalizedConfig !== rawConfig) {
|
|
801
|
+
await writeFile(codexConfigPath, normalizedConfig, "utf-8");
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
async function installSkill(params) {
|
|
805
|
+
const args = [
|
|
806
|
+
"-y",
|
|
807
|
+
"skills@latest",
|
|
808
|
+
"add",
|
|
809
|
+
params.skillRef,
|
|
810
|
+
"--copy",
|
|
811
|
+
"--agent",
|
|
812
|
+
params.agent,
|
|
813
|
+
"-y"
|
|
814
|
+
];
|
|
815
|
+
const result = await params.execaFn("npx", args, {
|
|
816
|
+
cwd: params.cwd,
|
|
817
|
+
reject: false,
|
|
818
|
+
stdout: "pipe",
|
|
819
|
+
stderr: "pipe"
|
|
820
|
+
});
|
|
821
|
+
if (result.exitCode !== 0) {
|
|
822
|
+
throw createCommandFailure(
|
|
823
|
+
`Failed to install skill "${params.skillRef}".`,
|
|
824
|
+
"npx",
|
|
825
|
+
args,
|
|
826
|
+
result
|
|
827
|
+
);
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
async function applyPrimeUiAiSetup(projectDirectory, options) {
|
|
831
|
+
const execaFn = options.execaFn ?? execa;
|
|
832
|
+
const aiPreset = options.aiPreset;
|
|
833
|
+
const agent = getPrimeUiAiAgent(aiPreset);
|
|
834
|
+
const resolvedMcpConfig = resolvePrimeUiMcpConfig(options.env);
|
|
835
|
+
const backupDir = await createAiSetupBackup(projectDirectory);
|
|
836
|
+
try {
|
|
837
|
+
await cleanupManagedAiFiles(projectDirectory);
|
|
838
|
+
await writeManagedPresetFiles(projectDirectory, aiPreset);
|
|
839
|
+
await writeManagedInstructionFiles(projectDirectory, aiPreset);
|
|
840
|
+
const installedMcpServers = [];
|
|
841
|
+
for (const [serverName, serverConfig] of Object.entries(
|
|
842
|
+
resolvedMcpConfig.mcpServers
|
|
843
|
+
)) {
|
|
844
|
+
await installMcpServer({
|
|
845
|
+
agent,
|
|
846
|
+
cwd: projectDirectory,
|
|
847
|
+
execaFn,
|
|
848
|
+
serverName,
|
|
849
|
+
serverConfig
|
|
850
|
+
});
|
|
851
|
+
installedMcpServers.push(serverName);
|
|
852
|
+
}
|
|
853
|
+
const installedSkillRefs = [];
|
|
854
|
+
for (const skillRef of listPrimeUiAiSkillRefs()) {
|
|
855
|
+
await installSkill({
|
|
856
|
+
agent,
|
|
857
|
+
cwd: projectDirectory,
|
|
858
|
+
execaFn,
|
|
859
|
+
skillRef
|
|
860
|
+
});
|
|
861
|
+
installedSkillRefs.push(skillRef);
|
|
862
|
+
}
|
|
863
|
+
await normalizeInstalledSkillsDirectory(projectDirectory, aiPreset);
|
|
864
|
+
await normalizeCodexConfigFormatting(projectDirectory, aiPreset);
|
|
865
|
+
if (shouldWritePrimeUiSharedMcpConfig(aiPreset)) {
|
|
866
|
+
await writeSharedMcpConfig(projectDirectory, resolvedMcpConfig);
|
|
867
|
+
}
|
|
868
|
+
await cleanupUnmanagedLocalArtifacts(projectDirectory, aiPreset);
|
|
869
|
+
await cleanupUnmanagedInstructionFiles(projectDirectory, aiPreset);
|
|
870
|
+
return {
|
|
871
|
+
status: "applied",
|
|
872
|
+
aiPreset,
|
|
873
|
+
agent,
|
|
874
|
+
installedMcpServers,
|
|
875
|
+
installedSkillRefs
|
|
876
|
+
};
|
|
877
|
+
} catch (error) {
|
|
878
|
+
try {
|
|
879
|
+
await restoreAiSetupBackup(projectDirectory, backupDir);
|
|
880
|
+
} catch (restoreError) {
|
|
881
|
+
throw new PrimeUiAgentSetupError(
|
|
882
|
+
"PrimeUI AI setup failed and the previous local AI setup could not be restored cleanly.",
|
|
883
|
+
{
|
|
884
|
+
code: PRIMEUI_AGENT_SETUP_ERROR_CODES.AI_SETUP_FAILED,
|
|
885
|
+
hint: restoreError instanceof Error ? restoreError.message : String(restoreError),
|
|
886
|
+
cause: error
|
|
887
|
+
}
|
|
888
|
+
);
|
|
889
|
+
}
|
|
890
|
+
throw error;
|
|
891
|
+
} finally {
|
|
892
|
+
await rm(backupDir, {
|
|
893
|
+
force: true,
|
|
894
|
+
recursive: true
|
|
895
|
+
}).catch(() => void 0);
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
// src/detect-agent-setup.ts
|
|
900
|
+
import { access as access2 } from "fs/promises";
|
|
901
|
+
import path3 from "path";
|
|
902
|
+
async function pathExists2(targetPath) {
|
|
903
|
+
try {
|
|
904
|
+
await access2(targetPath);
|
|
905
|
+
return true;
|
|
906
|
+
} catch {
|
|
907
|
+
return false;
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
function getDetectionPaths(preset) {
|
|
911
|
+
return preset.detectionPaths;
|
|
912
|
+
}
|
|
913
|
+
async function detectPrimeUiLocalAgentSetup(projectDirectory) {
|
|
914
|
+
const detectedAgents = [];
|
|
915
|
+
for (const preset of listPrimeUiSupportedAgentPresets()) {
|
|
916
|
+
const matchedPaths = [];
|
|
917
|
+
for (const relativePath of getDetectionPaths(preset)) {
|
|
918
|
+
if (await pathExists2(path3.join(projectDirectory, relativePath))) {
|
|
919
|
+
matchedPaths.push(relativePath);
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
if (matchedPaths.length === 0) {
|
|
923
|
+
continue;
|
|
924
|
+
}
|
|
925
|
+
detectedAgents.push({
|
|
926
|
+
agent: preset.agent,
|
|
927
|
+
supportLevel: preset.supportLevel,
|
|
928
|
+
matchedPaths
|
|
929
|
+
});
|
|
930
|
+
}
|
|
931
|
+
detectedAgents.sort((left, right) => left.agent.localeCompare(right.agent));
|
|
932
|
+
return {
|
|
933
|
+
detectedAgents
|
|
934
|
+
};
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
// src/infer-ai-preset.ts
|
|
938
|
+
async function detectPrimeUiAiPresetCandidates(projectDirectory) {
|
|
939
|
+
const detection = await detectPrimeUiLocalAgentSetup(projectDirectory);
|
|
940
|
+
const candidates = detection.detectedAgents.filter((signal) => {
|
|
941
|
+
const preset = getPrimeUiSupportedAgentPreset(signal.agent);
|
|
942
|
+
const strongPaths = preset.presetInferencePaths ?? [];
|
|
943
|
+
return strongPaths.some(
|
|
944
|
+
(inferencePath) => signal.matchedPaths.includes(inferencePath)
|
|
945
|
+
);
|
|
946
|
+
}).map((signal) => getPrimeUiSupportedAgentPreset(signal.agent).aiPreset).filter((preset) => Boolean(preset));
|
|
947
|
+
return Array.from(new Set(candidates));
|
|
948
|
+
}
|
|
949
|
+
async function inferPrimeUiAiPreset(projectDirectory) {
|
|
950
|
+
const candidates = await detectPrimeUiAiPresetCandidates(projectDirectory);
|
|
951
|
+
return candidates.length === 1 ? candidates[0] : void 0;
|
|
952
|
+
}
|
|
953
|
+
export {
|
|
954
|
+
DEFAULT_PRIMEUI_AI_PRESET,
|
|
955
|
+
PRIMEUI_AGENT_SETUP_ERROR_CODES,
|
|
956
|
+
PRIMEUI_AI_PRESET_OPTIONS,
|
|
957
|
+
PRIMEUI_AI_PRESET_VALUES,
|
|
958
|
+
PRIMEUI_AI_SETUP_CHOICE_OPTIONS,
|
|
959
|
+
PRIMEUI_AI_SETUP_CHOICE_VALUES,
|
|
960
|
+
PRIMEUI_LOCAL_AI_ARTIFACT_PATHS,
|
|
961
|
+
PRIMEUI_MANAGED_AI_CLEANUP_PATHS,
|
|
962
|
+
PRIMEUI_SHARED_MCP_CONFIG_PATH,
|
|
963
|
+
PRIMEUI_SHARED_SKILLS_LOCK_PATH,
|
|
964
|
+
PRIMEUI_SHARED_VERIFICATION_SCRIPTS,
|
|
965
|
+
PRIMEUI_SUPPORTED_AGENT_VALUES,
|
|
966
|
+
PrimeUiAgentSetupError,
|
|
967
|
+
applyPrimeUiAiSetup,
|
|
968
|
+
buildPrimeUiClaudeSettings,
|
|
969
|
+
buildPrimeUiClaudeSettingsFileContent,
|
|
970
|
+
buildPrimeUiCodexConfigToml,
|
|
971
|
+
buildPrimeUiCursorCliConfig,
|
|
972
|
+
buildPrimeUiCursorCliConfigFileContent,
|
|
973
|
+
createPrimeUiAiSetupEnv,
|
|
974
|
+
detectPrimeUiAiPresetCandidates,
|
|
975
|
+
detectPrimeUiLocalAgentSetup,
|
|
976
|
+
getPrimeUiAgentPresetDirectory,
|
|
977
|
+
getPrimeUiAiAgent,
|
|
978
|
+
getPrimeUiInstalledSkillsDirectory,
|
|
979
|
+
getPrimeUiManagedConfigFileContents,
|
|
980
|
+
getPrimeUiManagedConfigFiles,
|
|
981
|
+
getPrimeUiManagedInstructionFileContents,
|
|
982
|
+
getPrimeUiManagedInstructionFiles,
|
|
983
|
+
getPrimeUiSupportedAgentPreset,
|
|
984
|
+
inferPrimeUiAiPreset,
|
|
985
|
+
isPrimeUiAiPreset,
|
|
986
|
+
isPrimeUiAiSetupChoice,
|
|
987
|
+
listPrimeUiAgentPresetFiles,
|
|
988
|
+
listPrimeUiAiSkillCollections,
|
|
989
|
+
listPrimeUiAiSkillRefs,
|
|
990
|
+
listPrimeUiAllowedMcpServers,
|
|
991
|
+
listPrimeUiAllowedShellCommands,
|
|
992
|
+
listPrimeUiClaudeAllowedPermissions,
|
|
993
|
+
listPrimeUiCursorAllowedPermissions,
|
|
994
|
+
listPrimeUiInstructionFilePaths,
|
|
995
|
+
listPrimeUiSupportedAgentPresets,
|
|
996
|
+
listPrimeUiSupportedAgents,
|
|
997
|
+
listPrimeUiVerificationScripts,
|
|
998
|
+
resolvePrimeUiMcpConfig,
|
|
999
|
+
shouldWritePrimeUiSharedMcpConfig,
|
|
1000
|
+
toPrimeUiAgentSetupError
|
|
1001
|
+
};
|
|
1002
|
+
//# sourceMappingURL=index.js.map
|