create-agentmark 1.0.1 → 1.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 +23 -8
- package/dist/index.js +43 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -72,18 +72,32 @@ interface CliArgs {
|
|
|
72
72
|
*/
|
|
73
73
|
apiUrl?: string;
|
|
74
74
|
overwrite?: boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Non-interactive mode for CI and coding agents: every prompt is replaced
|
|
77
|
+
* by its default (target folder per `defaultFolderName`, all IDE clients,
|
|
78
|
+
* keep an existing agentmark.json). Headless onboarding depends on this —
|
|
79
|
+
* without it the init blocks on a TTY no agent has.
|
|
80
|
+
*/
|
|
81
|
+
yes?: boolean;
|
|
82
|
+
help?: boolean;
|
|
75
83
|
}
|
|
76
84
|
declare const ALL_CLIENTS: readonly McpClient[];
|
|
77
85
|
declare const AGENTMARK_JSON: Record<string, unknown>;
|
|
78
86
|
declare const parseArgs: (argv?: string[]) => CliArgs;
|
|
79
87
|
declare const clientLabel: (id: string) => string;
|
|
80
88
|
/**
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
89
|
+
* The folder the interactive prompt would offer as its default: "." when
|
|
90
|
+
* cwd looks like an existing project (the common "wire AgentMark into my
|
|
91
|
+
* repo" case), a fresh folder name when cwd is empty (greenfield). `--yes`
|
|
92
|
+
* resolves to exactly this value, so a non-interactive run lands where an
|
|
93
|
+
* Enter-mashing interactive run would have.
|
|
94
|
+
*/
|
|
95
|
+
declare const defaultFolderName: (cwd?: string) => string;
|
|
96
|
+
/**
|
|
97
|
+
* Resolves the target folder via positional/flag arg, `--yes` default, or
|
|
98
|
+
* interactive prompt.
|
|
85
99
|
*/
|
|
86
|
-
declare const resolveTargetPath: (cliPath: string | undefined) => Promise<{
|
|
100
|
+
declare const resolveTargetPath: (cliPath: string | undefined, yes?: boolean) => Promise<{
|
|
87
101
|
targetPath: string;
|
|
88
102
|
isCurrentDir: boolean;
|
|
89
103
|
} | null>;
|
|
@@ -93,14 +107,15 @@ declare const resolveTargetPath: (cliPath: string | undefined) => Promise<{
|
|
|
93
107
|
* (Enter). Empty selection is equivalent to the old "Skip" option — the
|
|
94
108
|
* caller just writes nothing.
|
|
95
109
|
*/
|
|
96
|
-
declare const resolveClients: (cliClients: McpClient[] | undefined) => Promise<McpClient[]>;
|
|
110
|
+
declare const resolveClients: (cliClients: McpClient[] | undefined, yes?: boolean) => Promise<McpClient[]>;
|
|
97
111
|
/**
|
|
98
112
|
* agentmark.json is the only file we conflict on (the others — MCP config
|
|
99
113
|
* dirs, agentmark/, .gitkeep — are either additive or no-ops if present).
|
|
100
114
|
* Default to "skip" so we never silently clobber an existing project's
|
|
101
115
|
* config; `--overwrite` is the explicit opt-in for re-init scripts.
|
|
102
116
|
*/
|
|
103
|
-
declare const shouldWriteAgentmarkJson: (filePath: string, overwrite: boolean | undefined) => Promise<boolean>;
|
|
117
|
+
declare const shouldWriteAgentmarkJson: (filePath: string, overwrite: boolean | undefined, yes?: boolean) => Promise<boolean>;
|
|
118
|
+
declare const USAGE = "Usage: npm create agentmark [folder] [-- options]\n npx create-agentmark [folder] [options]\n\nSets up AgentMark in a new or existing project: writes agentmark.json,\ncreates the agentmark/ prompts directory, wires IDE MCP configs, and\ninstalls the AgentMark agent skill.\n\nOptions:\n [folder], --path <folder> Target directory. Default: \".\" inside an\n existing project, else \"my-agentmark-app\".\n --client <ids|all> IDE clients to wire MCP configs for, comma-\n separated: claude-code, cursor, vscode, zed.\n -y, --yes Non-interactive: accept the default for every\n prompt (folder default above, all IDE clients,\n keep an existing agentmark.json). For CI and\n coding agents.\n --overwrite Replace an existing agentmark.json with the\n default config.\n -h, --help Show this help.\n";
|
|
104
119
|
declare const main: () => Promise<void>;
|
|
105
120
|
|
|
106
|
-
export { AGENTMARK_JSON, ALL_CLIENTS, type CliArgs, clientLabel, main, parseArgs, resolveClients, resolveTargetPath, shouldWriteAgentmarkJson };
|
|
121
|
+
export { AGENTMARK_JSON, ALL_CLIENTS, type CliArgs, USAGE, clientLabel, defaultFolderName, main, parseArgs, resolveClients, resolveTargetPath, shouldWriteAgentmarkJson };
|
package/dist/index.js
CHANGED
|
@@ -228,6 +228,10 @@ var parseArgs = (argv = process.argv.slice(2)) => {
|
|
|
228
228
|
result.clients = [...result.clients ?? [], ...ids];
|
|
229
229
|
} else if (arg === "--overwrite") {
|
|
230
230
|
result.overwrite = true;
|
|
231
|
+
} else if (arg === "--yes" || arg === "-y") {
|
|
232
|
+
result.yes = true;
|
|
233
|
+
} else if (arg === "--help" || arg === "-h") {
|
|
234
|
+
result.help = true;
|
|
231
235
|
} else if (arg === "--api-url") {
|
|
232
236
|
const value = argv[++i];
|
|
233
237
|
if (!value || !/^https?:\/\//.test(value)) {
|
|
@@ -241,16 +245,18 @@ var parseArgs = (argv = process.argv.slice(2)) => {
|
|
|
241
245
|
return result;
|
|
242
246
|
};
|
|
243
247
|
var clientLabel = (id) => id === "vscode" ? "VS Code" : id === "zed" ? "Zed" : id === "cursor" ? "Cursor" : id === "claude-code" ? "Claude Code" : id;
|
|
244
|
-
var
|
|
248
|
+
var defaultFolderName = (cwd = process.cwd()) => fs3.existsSync(path3.join(cwd, "package.json")) || fs3.existsSync(path3.join(cwd, "pyproject.toml")) ? "." : "my-agentmark-app";
|
|
249
|
+
var resolveTargetPath = async (cliPath, yes) => {
|
|
245
250
|
let folderName = cliPath;
|
|
251
|
+
if (!folderName && yes) {
|
|
252
|
+
folderName = defaultFolderName();
|
|
253
|
+
}
|
|
246
254
|
if (!folderName) {
|
|
247
|
-
const cwd = process.cwd();
|
|
248
|
-
const cwdHasProject = fs3.existsSync(path3.join(cwd, "package.json")) || fs3.existsSync(path3.join(cwd, "pyproject.toml"));
|
|
249
255
|
const response = await prompts({
|
|
250
256
|
name: "folderName",
|
|
251
257
|
type: "text",
|
|
252
258
|
message: "Where would you like to set up AgentMark?",
|
|
253
|
-
initial:
|
|
259
|
+
initial: defaultFolderName()
|
|
254
260
|
});
|
|
255
261
|
folderName = response.folderName;
|
|
256
262
|
}
|
|
@@ -260,7 +266,7 @@ var resolveTargetPath = async (cliPath) => {
|
|
|
260
266
|
if (!isCurrentDir) fs3.ensureDirSync(targetPath);
|
|
261
267
|
return { targetPath, isCurrentDir };
|
|
262
268
|
};
|
|
263
|
-
var resolveClients = async (cliClients) => {
|
|
269
|
+
var resolveClients = async (cliClients, yes) => {
|
|
264
270
|
if (cliClients && cliClients.length > 0) {
|
|
265
271
|
for (const c of cliClients) {
|
|
266
272
|
if (!ALL_CLIENTS.includes(c)) {
|
|
@@ -269,6 +275,7 @@ var resolveClients = async (cliClients) => {
|
|
|
269
275
|
}
|
|
270
276
|
return cliClients;
|
|
271
277
|
}
|
|
278
|
+
if (yes) return [...ALL_CLIENTS];
|
|
272
279
|
const response = await prompts({
|
|
273
280
|
name: "clients",
|
|
274
281
|
type: "multiselect",
|
|
@@ -283,9 +290,10 @@ var resolveClients = async (cliClients) => {
|
|
|
283
290
|
});
|
|
284
291
|
return response.clients ?? [];
|
|
285
292
|
};
|
|
286
|
-
var shouldWriteAgentmarkJson = async (filePath, overwrite) => {
|
|
293
|
+
var shouldWriteAgentmarkJson = async (filePath, overwrite, yes) => {
|
|
287
294
|
if (!fs3.existsSync(filePath)) return true;
|
|
288
295
|
if (overwrite) return true;
|
|
296
|
+
if (yes) return false;
|
|
289
297
|
const { action } = await prompts({
|
|
290
298
|
type: "select",
|
|
291
299
|
name: "action",
|
|
@@ -298,19 +306,43 @@ var shouldWriteAgentmarkJson = async (filePath, overwrite) => {
|
|
|
298
306
|
});
|
|
299
307
|
return action === "overwrite";
|
|
300
308
|
};
|
|
309
|
+
var USAGE = `Usage: npm create agentmark [folder] [-- options]
|
|
310
|
+
npx create-agentmark [folder] [options]
|
|
311
|
+
|
|
312
|
+
Sets up AgentMark in a new or existing project: writes agentmark.json,
|
|
313
|
+
creates the agentmark/ prompts directory, wires IDE MCP configs, and
|
|
314
|
+
installs the AgentMark agent skill.
|
|
315
|
+
|
|
316
|
+
Options:
|
|
317
|
+
[folder], --path <folder> Target directory. Default: "." inside an
|
|
318
|
+
existing project, else "my-agentmark-app".
|
|
319
|
+
--client <ids|all> IDE clients to wire MCP configs for, comma-
|
|
320
|
+
separated: claude-code, cursor, vscode, zed.
|
|
321
|
+
-y, --yes Non-interactive: accept the default for every
|
|
322
|
+
prompt (folder default above, all IDE clients,
|
|
323
|
+
keep an existing agentmark.json). For CI and
|
|
324
|
+
coding agents.
|
|
325
|
+
--overwrite Replace an existing agentmark.json with the
|
|
326
|
+
default config.
|
|
327
|
+
-h, --help Show this help.
|
|
328
|
+
`;
|
|
301
329
|
var main = async () => {
|
|
302
330
|
const cliArgs = parseArgs();
|
|
303
|
-
|
|
331
|
+
if (cliArgs.help) {
|
|
332
|
+
console.log(USAGE);
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
const target = await resolveTargetPath(cliArgs.path, cliArgs.yes);
|
|
304
336
|
if (!target) {
|
|
305
337
|
console.log("Aborted.");
|
|
306
338
|
return;
|
|
307
339
|
}
|
|
308
340
|
const { targetPath } = target;
|
|
309
341
|
const projectInfo = detectProjectInfo(targetPath);
|
|
310
|
-
const clients = await resolveClients(cliArgs.clients);
|
|
342
|
+
const clients = await resolveClients(cliArgs.clients, cliArgs.yes);
|
|
311
343
|
console.log("");
|
|
312
344
|
const agentmarkJsonPath = path3.join(targetPath, "agentmark.json");
|
|
313
|
-
if (await shouldWriteAgentmarkJson(agentmarkJsonPath, cliArgs.overwrite)) {
|
|
345
|
+
if (await shouldWriteAgentmarkJson(agentmarkJsonPath, cliArgs.overwrite, cliArgs.yes)) {
|
|
314
346
|
fs3.writeJsonSync(agentmarkJsonPath, AGENTMARK_JSON, { spaces: 2 });
|
|
315
347
|
console.log("\u2705 agentmark.json");
|
|
316
348
|
} else {
|
|
@@ -370,7 +402,9 @@ if (isDirectlyInvoked()) {
|
|
|
370
402
|
export {
|
|
371
403
|
AGENTMARK_JSON,
|
|
372
404
|
ALL_CLIENTS,
|
|
405
|
+
USAGE,
|
|
373
406
|
clientLabel,
|
|
407
|
+
defaultFolderName,
|
|
374
408
|
main,
|
|
375
409
|
parseArgs,
|
|
376
410
|
resolveClients,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/utils/examples/mcp-config.ts","../src/utils/install-skill.ts","../src/utils/git-init.ts","../src/utils/project-detection.ts"],"sourcesContent":["import fs from \"fs-extra\";\nimport path from \"path\";\nimport prompts from \"prompts\";\nimport { pathToFileURL, fileURLToPath } from \"url\";\nimport { writeMcpConfig, type McpClient } from \"./utils/examples/mcp-config.js\";\nimport { installAgentmarkSkill } from \"./utils/install-skill.js\";\nimport { initGitRepo } from \"./utils/git-init.js\";\nimport { detectProjectInfo, isCurrentDirectory } from \"./utils/project-detection.js\";\n\n/**\n * `npm create agentmark` — minimal init.\n *\n * Scope is deliberately small. The CLI does NOT scaffold example code,\n * pick an LLM adapter, or handle login. Its job is:\n *\n * 1. Write `agentmark.json` (the SDK loader's config root)\n * 2. Create an empty `agentmark/` directory (where prompts go)\n * 3. Wire MCP configs for any IDE clients the user selects\n * 4. Install the AgentMark agent skill (`npx skills add agentmark-ai/skills`)\n * 5. Hand off to the AI tool: \"Open Claude Code / Cursor and say:\n * Set up AgentMark in this project.\"\n *\n * Everything else — framework detection, package install, code wiring,\n * first prompt — is the job of the `setup-and-integration` skill workflow,\n * which runs inside the user's IDE agent. That keeps integration adaptive\n * to whatever stack the user already has, instead of forcing a template.\n */\n\nexport interface CliArgs {\n path?: string;\n clients?: McpClient[];\n /**\n * Undocumented escape hatch for internal staging\n * (`https://api-stg.agentmark.co`) and rare self-hosters. Defaults to\n * `https://api.agentmark.co`. The `agentmark-local` MCP entry always\n * points at `http://localhost:9418` regardless of this flag.\n */\n apiUrl?: string;\n overwrite?: boolean;\n}\n\nexport const ALL_CLIENTS: readonly McpClient[] = [\"claude-code\", \"cursor\", \"vscode\", \"zed\"];\n\nexport const AGENTMARK_JSON: Record<string, unknown> = {\n $schema:\n \"https://raw.githubusercontent.com/agentmark-ai/agentmark/refs/heads/main/packages/cli/agentmark.schema.json\",\n version: \"2.0.0\",\n mdxVersion: \"1.0\",\n agentmarkPath: \".\",\n // Seed one model so the dashboard prompt editor isn't an empty dropdown on\n // first run. Add more with `npx agentmark pull-models` (writes provider/model\n // entries here) — see https://docs.agentmark.co/configure/model-schemas.\n builtInModels: [\"openai/gpt-5.5\"],\n};\n\nexport const parseArgs = (argv: string[] = process.argv.slice(2)): CliArgs => {\n const result: CliArgs = {};\n\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n if (arg === \"--path\") {\n result.path = argv[++i];\n } else if (arg === \"--client\") {\n const value = argv[++i];\n if (!value) throw new Error(\"--client requires a value\");\n const ids = value === \"all\"\n ? [...ALL_CLIENTS]\n : value.split(\",\").map((s) => s.trim()).filter(Boolean) as McpClient[];\n result.clients = [...(result.clients ?? []), ...ids];\n } else if (arg === \"--overwrite\") {\n result.overwrite = true;\n } else if (arg === \"--api-url\") {\n const value = argv[++i];\n if (!value || !/^https?:\\/\\//.test(value)) {\n throw new Error(`--api-url requires a full http(s) URL (got \"${value}\")`);\n }\n result.apiUrl = value;\n } else if (arg && !arg.startsWith(\"--\") && !result.path) {\n // Positional: folder name, matches `npx create-next-app my-app` shape.\n result.path = arg;\n }\n }\n\n return result;\n};\n\nexport const clientLabel = (id: string): string =>\n id === \"vscode\" ? \"VS Code\"\n : id === \"zed\" ? \"Zed\"\n : id === \"cursor\" ? \"Cursor\"\n : id === \"claude-code\" ? \"Claude Code\"\n : id;\n\n/**\n * Resolves the target folder via positional/flag arg or interactive prompt.\n * Default to \".\" when cwd looks like an existing project (the common case\n * for \"wire AgentMark into my repo\"); fall back to a fresh folder name when\n * cwd is empty (the greenfield case).\n */\nexport const resolveTargetPath = async (\n cliPath: string | undefined,\n): Promise<{ targetPath: string; isCurrentDir: boolean } | null> => {\n let folderName = cliPath;\n if (!folderName) {\n const cwd = process.cwd();\n const cwdHasProject =\n fs.existsSync(path.join(cwd, \"package.json\")) ||\n fs.existsSync(path.join(cwd, \"pyproject.toml\"));\n const response = await prompts({\n name: \"folderName\",\n type: \"text\",\n message: \"Where would you like to set up AgentMark?\",\n initial: cwdHasProject ? \".\" : \"my-agentmark-app\",\n });\n folderName = response.folderName;\n }\n if (!folderName) return null; // Ctrl+C / empty input\n\n const isCurrentDir = isCurrentDirectory(folderName);\n const targetPath = isCurrentDir ? process.cwd() : path.resolve(folderName);\n if (!isCurrentDir) fs.ensureDirSync(targetPath);\n return { targetPath, isCurrentDir };\n};\n\n/**\n * Resolves which IDE clients to wire MCP into. All 4 are pre-selected on\n * the prompt so the typical \"I use everything\" case is one keystroke\n * (Enter). Empty selection is equivalent to the old \"Skip\" option — the\n * caller just writes nothing.\n */\nexport const resolveClients = async (cliClients: McpClient[] | undefined): Promise<McpClient[]> => {\n if (cliClients && cliClients.length > 0) {\n for (const c of cliClients) {\n if (!ALL_CLIENTS.includes(c)) {\n throw new Error(`Invalid client \"${c}\". Valid: ${ALL_CLIENTS.join(\", \")}`);\n }\n }\n return cliClients;\n }\n const response = await prompts({\n name: \"clients\",\n type: \"multiselect\",\n message: \"Wire AgentMark MCP into which IDE clients?\",\n instructions: false,\n hint: \"Space to toggle. Enter to submit. Skip all = empty selection.\",\n choices: ALL_CLIENTS.map((id) => ({\n title: clientLabel(id),\n value: id,\n selected: true,\n })),\n });\n return (response.clients ?? []) as McpClient[];\n};\n\n/**\n * agentmark.json is the only file we conflict on (the others — MCP config\n * dirs, agentmark/, .gitkeep — are either additive or no-ops if present).\n * Default to \"skip\" so we never silently clobber an existing project's\n * config; `--overwrite` is the explicit opt-in for re-init scripts.\n */\nexport const shouldWriteAgentmarkJson = async (\n filePath: string,\n overwrite: boolean | undefined,\n): Promise<boolean> => {\n if (!fs.existsSync(filePath)) return true;\n if (overwrite) return true;\n const { action } = await prompts({\n type: \"select\",\n name: \"action\",\n message: \"agentmark.json already exists. What would you like to do?\",\n choices: [\n { title: \"Skip (keep existing)\", value: \"skip\" },\n { title: \"Overwrite with default config\", value: \"overwrite\" },\n ],\n initial: 0,\n });\n return action === \"overwrite\";\n};\n\nexport const main = async (): Promise<void> => {\n const cliArgs = parseArgs();\n\n const target = await resolveTargetPath(cliArgs.path);\n if (!target) {\n console.log(\"Aborted.\");\n return;\n }\n const { targetPath } = target;\n\n const projectInfo = detectProjectInfo(targetPath);\n const clients = await resolveClients(cliArgs.clients);\n\n console.log(\"\");\n\n // 1. agentmark.json — the SDK loader's config root\n const agentmarkJsonPath = path.join(targetPath, \"agentmark.json\");\n if (await shouldWriteAgentmarkJson(agentmarkJsonPath, cliArgs.overwrite)) {\n fs.writeJsonSync(agentmarkJsonPath, AGENTMARK_JSON, { spaces: 2 });\n console.log(\"✅ agentmark.json\");\n } else {\n console.log(\"⏭️ agentmark.json (kept existing)\");\n }\n\n // 2. agentmark/ — where prompts go. Empty + .gitkeep so the folder is\n // discoverable and version-controlled before the user adds anything.\n // Matches agentmarkPath: \".\" in agentmark.json.\n const agentmarkDirPath = path.join(targetPath, \"agentmark\");\n if (!fs.existsSync(agentmarkDirPath)) {\n fs.ensureDirSync(agentmarkDirPath);\n fs.writeFileSync(path.join(agentmarkDirPath, \".gitkeep\"), \"\");\n console.log(\"✅ agentmark/ (empty, ready for your .prompt.mdx files)\");\n } else {\n console.log(\"⏭️ agentmark/ (kept existing)\");\n }\n\n // 3. MCP wiring — one config file per selected IDE client\n for (const client of clients) {\n try {\n const result = writeMcpConfig(client, targetPath, { customApiUrl: cliArgs.apiUrl });\n if (result) {\n const rel = path.relative(targetPath, result.configPath) || result.configPath;\n console.log(`✅ MCP wired (${clientLabel(client)}): ${rel}`);\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.warn(`⚠️ Could not write MCP config for ${clientLabel(client)}: ${message}`);\n }\n }\n\n // 4. AgentMark agent skill (best-effort; logs its own status)\n installAgentmarkSkill(targetPath);\n\n // 5. git init — only if this is a greenfield folder\n if (!projectInfo.isExistingProject) {\n initGitRepo(targetPath);\n }\n\n // 6. Handoff to the AI tool. The integration logic lives in the skill\n // workflow (`setup-and-integration.md`), not here, so the rest of\n // onboarding adapts to whatever stack the user already has.\n console.log(\"\");\n console.log(\"✨ AgentMark is wired up.\");\n console.log(\"\");\n console.log(\" Next: open this project in Claude Code, Cursor, VS Code, or Zed and say:\");\n console.log(\"\");\n console.log(\" \\\"Set up AgentMark in this project.\\\"\");\n console.log(\"\");\n console.log(\" The AgentMark skill will detect your stack, propose the wiring against\");\n console.log(\" the docs MCP (https://docs.agentmark.co/mcp), and integrate adaptively.\");\n};\n\n/**\n * Run main() only when this module is invoked directly as the CLI entry —\n * NOT when imported by a test or another module.\n *\n * Both sides MUST be realpath'd before comparing. npm/npx invoke bins\n * through a `node_modules/.bin` SYMLINK, so `process.argv[1]` is the\n * symlink path while `import.meta.url` is the resolved real path — a naive\n * URL comparison never matches and the CLI exits 0 having done nothing.\n * That exact bug shipped in 1.0.0 and made `npm create agentmark` a silent\n * no-op for every user (macOS additionally symlinks /tmp, which is why\n * even \"direct\" invocations failed in temp dirs). Regression-pinned by\n * test/bin-invocation.test.ts, which runs the built bin through a symlink.\n */\nconst isDirectlyInvoked = (): boolean => {\n const entry = process.argv[1];\n if (!entry) return false;\n try {\n const entryReal = pathToFileURL(fs.realpathSync(entry)).href;\n const selfReal = pathToFileURL(fs.realpathSync(fileURLToPath(import.meta.url))).href;\n return entryReal === selfReal;\n } catch {\n // realpath can throw on exotic entries (deleted cwd, permissions);\n // treat as \"not the CLI entry\" rather than crashing an import.\n return false;\n }\n};\n\nif (isDirectlyInvoked()) {\n main().catch((error) => {\n console.error(\"Error:\", error);\n process.exit(1);\n });\n}\n","/**\n * Shared MCP-config builder for the scaffolders.\n *\n * Writes the project-local IDE config (mcp.json / settings.json) for\n * the four supported clients. Every scaffolded project gets THREE\n * MCP servers wired up by default:\n *\n * 1. `agentmark-docs` (remote HTTP) — read-only docs / reference,\n * hosted at `https://docs.agentmark.co/mcp`.\n *\n * 2. `agentmark` (stdio, `@agentmark-ai/mcp-server`) — AgentMark\n * Cloud surface. Defaults to `https://api.agentmark.co`; pass a\n * custom URL via `customApiUrl` (the undocumented `--api-url`\n * flag on the CLI) to point at a non-prod gateway (staging,\n * self-hosted).\n *\n * 3. `agentmark-local` (stdio, `@agentmark-ai/mcp-server`) — the\n * same MCP binary, pointed at the local `agentmark dev` server\n * (`http://localhost:9418`). The local dev server serves the\n * same OpenAPI contract under `/v1/openapi.json`, so the same\n * tool surface (`list_traces`, `get_trace`, …) is available\n * against local SQLite traces.\n *\n * Why both `agentmark` and `agentmark-local`: workflows like \"pull\n * failing traces from AgentMark Cloud, fix locally, re-verify against\n * `agentmark dev` traces\" need BOTH endpoints reachable in the same\n * conversation. MCP clients namespace tools by server name, so the\n * agent calls `agentmark/list_traces` for cloud and\n * `agentmark-local/list_traces` for local — same tool, explicit\n * destination.\n *\n * Auth chain is endpoint-agnostic:\n *\n * - `AGENTMARK_API_KEY` env (CI / dedicated agents) wins\n * - falls back to `~/.agentmark/auth.json` from\n * `agentmark login [--base-url <matching-endpoint>]`\n * - local dev calls are unauthenticated by design (the local dev\n * server doesn't validate auth headers)\n *\n * Shell `export AGENTMARK_API_URL=…` still wins at runtime when the\n * IDE inherits the shell — what we write here is the default for\n * cold-launched IDEs.\n */\n\nimport fs from \"fs-extra\";\nimport * as path from \"path\";\n\nexport type McpClient = \"vscode\" | \"zed\" | \"cursor\" | \"claude-code\" | \"skip\";\n\n/** URL the cloud-pointing `agentmark` MCP entry talks to by default. */\nconst CLOUD_API_URL = \"https://api.agentmark.co\";\n\n/** Local `agentmark dev` server URL — matches AGENTMARK_PORT default. */\nconst LOCAL_DEV_URL = \"http://localhost:9418\";\n\n/** The npm package id of the stdio MCP server (used for both entries). */\nconst MCP_SERVER_PACKAGE = \"@agentmark-ai/mcp-server\";\n\ninterface StdioServerEntry {\n command: string;\n args: string[];\n env?: Record<string, string>;\n type?: \"stdio\";\n}\n\ninterface RemoteServerEntry {\n url: string;\n type?: \"http\";\n}\n\n/**\n * Builds an stdio MCP server entry pointed at the given URL.\n *\n * - When the URL matches the MCP server's built-in default\n * (`https://api.agentmark.co`), the `env` block is omitted so a\n * future change to that default cleanly propagates to existing\n * scaffolded projects.\n * - For any other URL (custom `--api-url`, or the local dev URL),\n * we write `env: { AGENTMARK_API_URL: <url> }` explicitly.\n */\nfunction stdioEntry(apiUrl: string, includeType: boolean): StdioServerEntry {\n const entry: StdioServerEntry = {\n command: \"npx\",\n args: [\"-y\", MCP_SERVER_PACKAGE],\n };\n if (apiUrl !== CLOUD_API_URL) {\n entry.env = { AGENTMARK_API_URL: apiUrl };\n }\n if (includeType) entry.type = \"stdio\";\n return entry;\n}\n\ninterface WriteResult {\n /** Absolute or relative path to the file that was written. */\n configPath: string;\n}\n\nexport interface WriteMcpConfigOptions {\n /**\n * Arbitrary AgentMark gateway URL for the cloud-side `agentmark` MCP\n * entry. Defaults to `https://api.agentmark.co`. Escape hatch for\n * internal AgentMark engineers (staging) and self-hosters — NOT a\n * customer-facing option.\n */\n customApiUrl?: string;\n}\n\n/**\n * Writes the IDE-specific MCP config file with three servers wired up.\n * Idempotent: caller passes a fresh target dir per scaffold.\n */\nexport function writeMcpConfig(\n client: McpClient,\n targetPath: string,\n opts: WriteMcpConfigOptions = {},\n): WriteResult | null {\n if (client === \"skip\") return null;\n\n const cloudUrl = opts.customApiUrl ?? CLOUD_API_URL;\n const docsEntry: RemoteServerEntry = { url: \"https://docs.agentmark.co/mcp\" };\n\n if (client === \"vscode\") {\n const vscodeDir = path.join(targetPath, \".vscode\");\n fs.ensureDirSync(vscodeDir);\n const configPath = path.join(vscodeDir, \"mcp.json\");\n const config = {\n servers: {\n \"agentmark-docs\": docsEntry,\n \"agentmark\": stdioEntry(cloudUrl, /* includeType */ false),\n \"agentmark-local\": stdioEntry(LOCAL_DEV_URL, /* includeType */ false),\n },\n };\n fs.writeJsonSync(configPath, config, { spaces: 2 });\n return { configPath };\n }\n\n if (client === \"zed\") {\n const zedDir = path.join(targetPath, \".zed\");\n fs.ensureDirSync(zedDir);\n const configPath = path.join(zedDir, \"settings.json\");\n const config = {\n context_servers: {\n \"agentmark-docs\": docsEntry,\n \"agentmark\": stdioEntry(cloudUrl, /* includeType */ false),\n \"agentmark-local\": stdioEntry(LOCAL_DEV_URL, /* includeType */ false),\n },\n };\n fs.writeJsonSync(configPath, config, { spaces: 2 });\n return { configPath };\n }\n\n if (client === \"cursor\") {\n const cursorDir = path.join(targetPath, \".cursor\");\n fs.ensureDirSync(cursorDir);\n const configPath = path.join(cursorDir, \"mcp.json\");\n const config = {\n mcpServers: {\n \"agentmark-docs\": docsEntry,\n \"agentmark\": stdioEntry(cloudUrl, /* includeType */ false),\n \"agentmark-local\": stdioEntry(LOCAL_DEV_URL, /* includeType */ false),\n },\n };\n fs.writeJsonSync(configPath, config, { spaces: 2 });\n return { configPath };\n }\n\n if (client === \"claude-code\") {\n const configPath = path.join(targetPath, \".mcp.json\");\n const config = {\n mcpServers: {\n \"agentmark-docs\": { type: \"http\" as const, ...docsEntry },\n \"agentmark\": stdioEntry(cloudUrl, /* includeType */ true),\n \"agentmark-local\": stdioEntry(LOCAL_DEV_URL, /* includeType */ true),\n },\n };\n fs.writeJsonSync(configPath, config, { spaces: 2 });\n return { configPath };\n }\n\n return null;\n}\n","import { execFileSync } from \"child_process\";\n\n/**\n * Installs the AgentMark agent skill (https://github.com/agentmark-ai/skills)\n * into the freshly-scaffolded project. The vercel-labs/skills tool puts files\n * at `./.agents/skills/agentmark/` and symlinks them into per-tool paths\n * (Claude Code, Codex, Cursor, GitHub Copilot, +others) per the\n * agentskills.io 0.0.2 spec.\n *\n * Uses execFileSync (no shell) for safety. All arguments are hardcoded\n * literals; no user input is interpolated.\n *\n * Best-effort: if the install fails (no network, npx unavailable, etc.) we\n * log a warning and keep going. The skill is a nice-to-have on top of a\n * working AgentMark project, not a hard requirement.\n */\n/**\n * True when the helper should skip the network install. Set in test runs\n * so the OSS Parity CI suite doesn't hit `npx skills add` per scaffolder\n * test (each call clones the public skills repo, adding 10-30s/test).\n *\n * Detected via:\n * - VITEST=true (Vitest sets this automatically)\n * - NODE_ENV=test (broad convention; many runners set this)\n * - AGENTMARK_SKIP_SKILL_INSTALL=1 (explicit opt-out for any other context)\n */\nconst shouldSkip = (): boolean =>\n process.env.VITEST === \"true\" ||\n process.env.NODE_ENV === \"test\" ||\n process.env.AGENTMARK_SKIP_SKILL_INSTALL === \"1\";\n\nexport const installAgentmarkSkill = (targetPath: string): void => {\n if (shouldSkip()) {\n console.log(\"\\n⏭️ Skipping agent skill install (test environment detected).\");\n return;\n }\n try {\n console.log(\"\\n📚 Installing AgentMark agent skill...\");\n console.log(\" (teaches Claude Code / Codex / Cursor / Copilot how to use AgentMark)\");\n execFileSync(\n \"npx\",\n [\"--yes\", \"skills\", \"add\", \"agentmark-ai/skills\"],\n {\n cwd: targetPath,\n stdio: \"inherit\",\n },\n );\n console.log(\"✅ Agent skill installed at ./.agents/skills/agentmark/\");\n } catch (error) {\n console.warn(\n \"\\n⚠️ Could not install the AgentMark agent skill automatically.\",\n );\n console.warn(\" You can install it later with:\");\n console.warn(\" cd \" + targetPath);\n console.warn(\" npx skills add agentmark-ai/skills\");\n if (error instanceof Error) {\n console.warn(` Reason: ${error.message.split(\"\\n\")[0]}`);\n }\n }\n};\n","import { execSync } from \"child_process\";\n\n/**\n * Initialize a git repository and create an initial commit.\n *\n * Skips silently when:\n * - The target path is already inside a git repository\n * - git is not installed\n * - Any git command fails (non-fatal)\n */\nexport function initGitRepo(targetPath: string): boolean {\n try {\n // Check if git is available\n try {\n execSync(\"git --version\", { stdio: \"ignore\" });\n } catch {\n console.log(\"⚠️ git not found — skipping repository initialization\");\n return false;\n }\n\n // Check if already inside a git repo\n try {\n execSync(\"git rev-parse --is-inside-work-tree\", {\n cwd: targetPath,\n stdio: \"ignore\",\n });\n // Already in a git repo — skip\n return false;\n } catch {\n // Not in a git repo — proceed\n }\n\n execSync(\"git init\", { cwd: targetPath, stdio: \"ignore\" });\n execSync(\"git add -A\", { cwd: targetPath, stdio: \"ignore\" });\n execSync(\n 'git -c user.name=\"create-agentmark\" -c user.email=\"noreply\" commit -m \"Initial commit from create-agentmark\"',\n { cwd: targetPath, stdio: \"ignore\" },\n );\n\n console.log(\"✅ Initialized git repository with initial commit\");\n return true;\n } catch {\n console.log(\"⚠️ Could not initialize git repository\");\n return false;\n }\n}\n","/**\n * Project detection for the minimal `npm create agentmark` init flow.\n *\n * Two questions only: \"is this an existing project?\" (drives whether we\n * run `git init`) and \"does AgentMark already exist here?\" (drives the\n * `agentmark.json` conflict prompt). Everything else — language, package\n * manager, Python venv, conflict file inventory — lives in the skill\n * workflow now, which can ask the docs MCP for current guidance instead\n * of encoding heuristics into the CLI.\n */\n\nimport fs from 'fs-extra';\nimport path from 'path';\nimport type { ProjectInfo } from './types.js';\n\nconst TYPESCRIPT_INDICATORS = ['package.json', 'tsconfig.json', 'node_modules'] as const;\nconst PYTHON_INDICATORS = ['pyproject.toml', 'requirements.txt', 'setup.py', '.venv', 'venv'] as const;\n\n/** Any TypeScript/Node.js project marker present in the target directory. */\nexport function detectTypeScriptProject(targetPath: string): boolean {\n return TYPESCRIPT_INDICATORS.some((file) => fs.existsSync(path.join(targetPath, file)));\n}\n\n/** Any Python project marker present in the target directory. */\nexport function detectPythonProject(targetPath: string): boolean {\n return PYTHON_INDICATORS.some((file) => fs.existsSync(path.join(targetPath, file)));\n}\n\n/**\n * Combined detection. `isExistingProject` is true if either language's\n * markers are present; the init flow uses it only to decide whether to\n * run `git init`.\n */\nexport function detectProjectInfo(targetPath: string): ProjectInfo {\n return {\n isExistingProject: detectTypeScriptProject(targetPath) || detectPythonProject(targetPath),\n hasAgentmarkJson: fs.existsSync(path.join(targetPath, 'agentmark.json')),\n hasAgentmarkDir: fs.existsSync(path.join(targetPath, 'agentmark')),\n };\n}\n\n/**\n * True for any spelling of \"current directory\" the user might type at the\n * folder prompt. Used to skip mkdir/cd noise when the user wants to wire\n * AgentMark into the directory they're already in.\n */\nexport function isCurrentDirectory(folderName: string): boolean {\n return folderName === '.' || folderName === './' || folderName === '.\\\\';\n}\n"],"mappings":"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","names":["fs","path","fs","path","fs","path"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/utils/examples/mcp-config.ts","../src/utils/install-skill.ts","../src/utils/git-init.ts","../src/utils/project-detection.ts"],"sourcesContent":["import fs from \"fs-extra\";\nimport path from \"path\";\nimport prompts from \"prompts\";\nimport { pathToFileURL, fileURLToPath } from \"url\";\nimport { writeMcpConfig, type McpClient } from \"./utils/examples/mcp-config.js\";\nimport { installAgentmarkSkill } from \"./utils/install-skill.js\";\nimport { initGitRepo } from \"./utils/git-init.js\";\nimport { detectProjectInfo, isCurrentDirectory } from \"./utils/project-detection.js\";\n\n/**\n * `npm create agentmark` — minimal init.\n *\n * Scope is deliberately small. The CLI does NOT scaffold example code,\n * pick an LLM adapter, or handle login. Its job is:\n *\n * 1. Write `agentmark.json` (the SDK loader's config root)\n * 2. Create an empty `agentmark/` directory (where prompts go)\n * 3. Wire MCP configs for any IDE clients the user selects\n * 4. Install the AgentMark agent skill (`npx skills add agentmark-ai/skills`)\n * 5. Hand off to the AI tool: \"Open Claude Code / Cursor and say:\n * Set up AgentMark in this project.\"\n *\n * Everything else — framework detection, package install, code wiring,\n * first prompt — is the job of the `setup-and-integration` skill workflow,\n * which runs inside the user's IDE agent. That keeps integration adaptive\n * to whatever stack the user already has, instead of forcing a template.\n */\n\nexport interface CliArgs {\n path?: string;\n clients?: McpClient[];\n /**\n * Undocumented escape hatch for internal staging\n * (`https://api-stg.agentmark.co`) and rare self-hosters. Defaults to\n * `https://api.agentmark.co`. The `agentmark-local` MCP entry always\n * points at `http://localhost:9418` regardless of this flag.\n */\n apiUrl?: string;\n overwrite?: boolean;\n /**\n * Non-interactive mode for CI and coding agents: every prompt is replaced\n * by its default (target folder per `defaultFolderName`, all IDE clients,\n * keep an existing agentmark.json). Headless onboarding depends on this —\n * without it the init blocks on a TTY no agent has.\n */\n yes?: boolean;\n help?: boolean;\n}\n\nexport const ALL_CLIENTS: readonly McpClient[] = [\"claude-code\", \"cursor\", \"vscode\", \"zed\"];\n\nexport const AGENTMARK_JSON: Record<string, unknown> = {\n $schema:\n \"https://raw.githubusercontent.com/agentmark-ai/agentmark/refs/heads/main/packages/cli/agentmark.schema.json\",\n version: \"2.0.0\",\n mdxVersion: \"1.0\",\n agentmarkPath: \".\",\n // Seed one model so the dashboard prompt editor isn't an empty dropdown on\n // first run. Add more with `npx agentmark pull-models` (writes provider/model\n // entries here) — see https://docs.agentmark.co/configure/model-schemas.\n builtInModels: [\"openai/gpt-5.5\"],\n};\n\nexport const parseArgs = (argv: string[] = process.argv.slice(2)): CliArgs => {\n const result: CliArgs = {};\n\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n if (arg === \"--path\") {\n result.path = argv[++i];\n } else if (arg === \"--client\") {\n const value = argv[++i];\n if (!value) throw new Error(\"--client requires a value\");\n const ids = value === \"all\"\n ? [...ALL_CLIENTS]\n : value.split(\",\").map((s) => s.trim()).filter(Boolean) as McpClient[];\n result.clients = [...(result.clients ?? []), ...ids];\n } else if (arg === \"--overwrite\") {\n result.overwrite = true;\n } else if (arg === \"--yes\" || arg === \"-y\") {\n result.yes = true;\n } else if (arg === \"--help\" || arg === \"-h\") {\n result.help = true;\n } else if (arg === \"--api-url\") {\n const value = argv[++i];\n if (!value || !/^https?:\\/\\//.test(value)) {\n throw new Error(`--api-url requires a full http(s) URL (got \"${value}\")`);\n }\n result.apiUrl = value;\n } else if (arg && !arg.startsWith(\"--\") && !result.path) {\n // Positional: folder name, matches `npx create-next-app my-app` shape.\n result.path = arg;\n }\n }\n\n return result;\n};\n\nexport const clientLabel = (id: string): string =>\n id === \"vscode\" ? \"VS Code\"\n : id === \"zed\" ? \"Zed\"\n : id === \"cursor\" ? \"Cursor\"\n : id === \"claude-code\" ? \"Claude Code\"\n : id;\n\n/**\n * The folder the interactive prompt would offer as its default: \".\" when\n * cwd looks like an existing project (the common \"wire AgentMark into my\n * repo\" case), a fresh folder name when cwd is empty (greenfield). `--yes`\n * resolves to exactly this value, so a non-interactive run lands where an\n * Enter-mashing interactive run would have.\n */\nexport const defaultFolderName = (cwd: string = process.cwd()): string =>\n fs.existsSync(path.join(cwd, \"package.json\")) ||\n fs.existsSync(path.join(cwd, \"pyproject.toml\"))\n ? \".\"\n : \"my-agentmark-app\";\n\n/**\n * Resolves the target folder via positional/flag arg, `--yes` default, or\n * interactive prompt.\n */\nexport const resolveTargetPath = async (\n cliPath: string | undefined,\n yes?: boolean,\n): Promise<{ targetPath: string; isCurrentDir: boolean } | null> => {\n let folderName = cliPath;\n if (!folderName && yes) {\n folderName = defaultFolderName();\n }\n if (!folderName) {\n const response = await prompts({\n name: \"folderName\",\n type: \"text\",\n message: \"Where would you like to set up AgentMark?\",\n initial: defaultFolderName(),\n });\n folderName = response.folderName;\n }\n if (!folderName) return null; // Ctrl+C / empty input\n\n const isCurrentDir = isCurrentDirectory(folderName);\n const targetPath = isCurrentDir ? process.cwd() : path.resolve(folderName);\n if (!isCurrentDir) fs.ensureDirSync(targetPath);\n return { targetPath, isCurrentDir };\n};\n\n/**\n * Resolves which IDE clients to wire MCP into. All 4 are pre-selected on\n * the prompt so the typical \"I use everything\" case is one keystroke\n * (Enter). Empty selection is equivalent to the old \"Skip\" option — the\n * caller just writes nothing.\n */\nexport const resolveClients = async (\n cliClients: McpClient[] | undefined,\n yes?: boolean,\n): Promise<McpClient[]> => {\n if (cliClients && cliClients.length > 0) {\n for (const c of cliClients) {\n if (!ALL_CLIENTS.includes(c)) {\n throw new Error(`Invalid client \"${c}\". Valid: ${ALL_CLIENTS.join(\", \")}`);\n }\n }\n return cliClients;\n }\n // --yes mirrors the interactive default: all clients pre-selected.\n if (yes) return [...ALL_CLIENTS];\n const response = await prompts({\n name: \"clients\",\n type: \"multiselect\",\n message: \"Wire AgentMark MCP into which IDE clients?\",\n instructions: false,\n hint: \"Space to toggle. Enter to submit. Skip all = empty selection.\",\n choices: ALL_CLIENTS.map((id) => ({\n title: clientLabel(id),\n value: id,\n selected: true,\n })),\n });\n return (response.clients ?? []) as McpClient[];\n};\n\n/**\n * agentmark.json is the only file we conflict on (the others — MCP config\n * dirs, agentmark/, .gitkeep — are either additive or no-ops if present).\n * Default to \"skip\" so we never silently clobber an existing project's\n * config; `--overwrite` is the explicit opt-in for re-init scripts.\n */\nexport const shouldWriteAgentmarkJson = async (\n filePath: string,\n overwrite: boolean | undefined,\n yes?: boolean,\n): Promise<boolean> => {\n if (!fs.existsSync(filePath)) return true;\n if (overwrite) return true;\n // --yes takes the safe interactive default: keep the existing file.\n // Clobbering config is never a default; --overwrite is the explicit opt-in.\n if (yes) return false;\n const { action } = await prompts({\n type: \"select\",\n name: \"action\",\n message: \"agentmark.json already exists. What would you like to do?\",\n choices: [\n { title: \"Skip (keep existing)\", value: \"skip\" },\n { title: \"Overwrite with default config\", value: \"overwrite\" },\n ],\n initial: 0,\n });\n return action === \"overwrite\";\n};\n\nexport const USAGE = `Usage: npm create agentmark [folder] [-- options]\n npx create-agentmark [folder] [options]\n\nSets up AgentMark in a new or existing project: writes agentmark.json,\ncreates the agentmark/ prompts directory, wires IDE MCP configs, and\ninstalls the AgentMark agent skill.\n\nOptions:\n [folder], --path <folder> Target directory. Default: \".\" inside an\n existing project, else \"my-agentmark-app\".\n --client <ids|all> IDE clients to wire MCP configs for, comma-\n separated: claude-code, cursor, vscode, zed.\n -y, --yes Non-interactive: accept the default for every\n prompt (folder default above, all IDE clients,\n keep an existing agentmark.json). For CI and\n coding agents.\n --overwrite Replace an existing agentmark.json with the\n default config.\n -h, --help Show this help.\n`;\n\nexport const main = async (): Promise<void> => {\n const cliArgs = parseArgs();\n\n if (cliArgs.help) {\n console.log(USAGE);\n return;\n }\n\n const target = await resolveTargetPath(cliArgs.path, cliArgs.yes);\n if (!target) {\n console.log(\"Aborted.\");\n return;\n }\n const { targetPath } = target;\n\n const projectInfo = detectProjectInfo(targetPath);\n const clients = await resolveClients(cliArgs.clients, cliArgs.yes);\n\n console.log(\"\");\n\n // 1. agentmark.json — the SDK loader's config root\n const agentmarkJsonPath = path.join(targetPath, \"agentmark.json\");\n if (await shouldWriteAgentmarkJson(agentmarkJsonPath, cliArgs.overwrite, cliArgs.yes)) {\n fs.writeJsonSync(agentmarkJsonPath, AGENTMARK_JSON, { spaces: 2 });\n console.log(\"✅ agentmark.json\");\n } else {\n console.log(\"⏭️ agentmark.json (kept existing)\");\n }\n\n // 2. agentmark/ — where prompts go. Empty + .gitkeep so the folder is\n // discoverable and version-controlled before the user adds anything.\n // Matches agentmarkPath: \".\" in agentmark.json.\n const agentmarkDirPath = path.join(targetPath, \"agentmark\");\n if (!fs.existsSync(agentmarkDirPath)) {\n fs.ensureDirSync(agentmarkDirPath);\n fs.writeFileSync(path.join(agentmarkDirPath, \".gitkeep\"), \"\");\n console.log(\"✅ agentmark/ (empty, ready for your .prompt.mdx files)\");\n } else {\n console.log(\"⏭️ agentmark/ (kept existing)\");\n }\n\n // 3. MCP wiring — one config file per selected IDE client\n for (const client of clients) {\n try {\n const result = writeMcpConfig(client, targetPath, { customApiUrl: cliArgs.apiUrl });\n if (result) {\n const rel = path.relative(targetPath, result.configPath) || result.configPath;\n console.log(`✅ MCP wired (${clientLabel(client)}): ${rel}`);\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.warn(`⚠️ Could not write MCP config for ${clientLabel(client)}: ${message}`);\n }\n }\n\n // 4. AgentMark agent skill (best-effort; logs its own status)\n installAgentmarkSkill(targetPath);\n\n // 5. git init — only if this is a greenfield folder\n if (!projectInfo.isExistingProject) {\n initGitRepo(targetPath);\n }\n\n // 6. Handoff to the AI tool. The integration logic lives in the skill\n // workflow (`setup-and-integration.md`), not here, so the rest of\n // onboarding adapts to whatever stack the user already has.\n console.log(\"\");\n console.log(\"✨ AgentMark is wired up.\");\n console.log(\"\");\n console.log(\" Next: open this project in Claude Code, Cursor, VS Code, or Zed and say:\");\n console.log(\"\");\n console.log(\" \\\"Set up AgentMark in this project.\\\"\");\n console.log(\"\");\n console.log(\" The AgentMark skill will detect your stack, propose the wiring against\");\n console.log(\" the docs MCP (https://docs.agentmark.co/mcp), and integrate adaptively.\");\n};\n\n/**\n * Run main() only when this module is invoked directly as the CLI entry —\n * NOT when imported by a test or another module.\n *\n * Both sides MUST be realpath'd before comparing. npm/npx invoke bins\n * through a `node_modules/.bin` SYMLINK, so `process.argv[1]` is the\n * symlink path while `import.meta.url` is the resolved real path — a naive\n * URL comparison never matches and the CLI exits 0 having done nothing.\n * That exact bug shipped in 1.0.0 and made `npm create agentmark` a silent\n * no-op for every user (macOS additionally symlinks /tmp, which is why\n * even \"direct\" invocations failed in temp dirs). Regression-pinned by\n * test/bin-invocation.test.ts, which runs the built bin through a symlink.\n */\nconst isDirectlyInvoked = (): boolean => {\n const entry = process.argv[1];\n if (!entry) return false;\n try {\n const entryReal = pathToFileURL(fs.realpathSync(entry)).href;\n const selfReal = pathToFileURL(fs.realpathSync(fileURLToPath(import.meta.url))).href;\n return entryReal === selfReal;\n } catch {\n // realpath can throw on exotic entries (deleted cwd, permissions);\n // treat as \"not the CLI entry\" rather than crashing an import.\n return false;\n }\n};\n\nif (isDirectlyInvoked()) {\n main().catch((error) => {\n console.error(\"Error:\", error);\n process.exit(1);\n });\n}\n","/**\n * Shared MCP-config builder for the scaffolders.\n *\n * Writes the project-local IDE config (mcp.json / settings.json) for\n * the four supported clients. Every scaffolded project gets THREE\n * MCP servers wired up by default:\n *\n * 1. `agentmark-docs` (remote HTTP) — read-only docs / reference,\n * hosted at `https://docs.agentmark.co/mcp`.\n *\n * 2. `agentmark` (stdio, `@agentmark-ai/mcp-server`) — AgentMark\n * Cloud surface. Defaults to `https://api.agentmark.co`; pass a\n * custom URL via `customApiUrl` (the undocumented `--api-url`\n * flag on the CLI) to point at a non-prod gateway (staging,\n * self-hosted).\n *\n * 3. `agentmark-local` (stdio, `@agentmark-ai/mcp-server`) — the\n * same MCP binary, pointed at the local `agentmark dev` server\n * (`http://localhost:9418`). The local dev server serves the\n * same OpenAPI contract under `/v1/openapi.json`, so the same\n * tool surface (`list_traces`, `get_trace`, …) is available\n * against local SQLite traces.\n *\n * Why both `agentmark` and `agentmark-local`: workflows like \"pull\n * failing traces from AgentMark Cloud, fix locally, re-verify against\n * `agentmark dev` traces\" need BOTH endpoints reachable in the same\n * conversation. MCP clients namespace tools by server name, so the\n * agent calls `agentmark/list_traces` for cloud and\n * `agentmark-local/list_traces` for local — same tool, explicit\n * destination.\n *\n * Auth chain is endpoint-agnostic:\n *\n * - `AGENTMARK_API_KEY` env (CI / dedicated agents) wins\n * - falls back to `~/.agentmark/auth.json` from\n * `agentmark login [--base-url <matching-endpoint>]`\n * - local dev calls are unauthenticated by design (the local dev\n * server doesn't validate auth headers)\n *\n * Shell `export AGENTMARK_API_URL=…` still wins at runtime when the\n * IDE inherits the shell — what we write here is the default for\n * cold-launched IDEs.\n */\n\nimport fs from \"fs-extra\";\nimport * as path from \"path\";\n\nexport type McpClient = \"vscode\" | \"zed\" | \"cursor\" | \"claude-code\" | \"skip\";\n\n/** URL the cloud-pointing `agentmark` MCP entry talks to by default. */\nconst CLOUD_API_URL = \"https://api.agentmark.co\";\n\n/** Local `agentmark dev` server URL — matches AGENTMARK_PORT default. */\nconst LOCAL_DEV_URL = \"http://localhost:9418\";\n\n/** The npm package id of the stdio MCP server (used for both entries). */\nconst MCP_SERVER_PACKAGE = \"@agentmark-ai/mcp-server\";\n\ninterface StdioServerEntry {\n command: string;\n args: string[];\n env?: Record<string, string>;\n type?: \"stdio\";\n}\n\ninterface RemoteServerEntry {\n url: string;\n type?: \"http\";\n}\n\n/**\n * Builds an stdio MCP server entry pointed at the given URL.\n *\n * - When the URL matches the MCP server's built-in default\n * (`https://api.agentmark.co`), the `env` block is omitted so a\n * future change to that default cleanly propagates to existing\n * scaffolded projects.\n * - For any other URL (custom `--api-url`, or the local dev URL),\n * we write `env: { AGENTMARK_API_URL: <url> }` explicitly.\n */\nfunction stdioEntry(apiUrl: string, includeType: boolean): StdioServerEntry {\n const entry: StdioServerEntry = {\n command: \"npx\",\n args: [\"-y\", MCP_SERVER_PACKAGE],\n };\n if (apiUrl !== CLOUD_API_URL) {\n entry.env = { AGENTMARK_API_URL: apiUrl };\n }\n if (includeType) entry.type = \"stdio\";\n return entry;\n}\n\ninterface WriteResult {\n /** Absolute or relative path to the file that was written. */\n configPath: string;\n}\n\nexport interface WriteMcpConfigOptions {\n /**\n * Arbitrary AgentMark gateway URL for the cloud-side `agentmark` MCP\n * entry. Defaults to `https://api.agentmark.co`. Escape hatch for\n * internal AgentMark engineers (staging) and self-hosters — NOT a\n * customer-facing option.\n */\n customApiUrl?: string;\n}\n\n/**\n * Writes the IDE-specific MCP config file with three servers wired up.\n * Idempotent: caller passes a fresh target dir per scaffold.\n */\nexport function writeMcpConfig(\n client: McpClient,\n targetPath: string,\n opts: WriteMcpConfigOptions = {},\n): WriteResult | null {\n if (client === \"skip\") return null;\n\n const cloudUrl = opts.customApiUrl ?? CLOUD_API_URL;\n const docsEntry: RemoteServerEntry = { url: \"https://docs.agentmark.co/mcp\" };\n\n if (client === \"vscode\") {\n const vscodeDir = path.join(targetPath, \".vscode\");\n fs.ensureDirSync(vscodeDir);\n const configPath = path.join(vscodeDir, \"mcp.json\");\n const config = {\n servers: {\n \"agentmark-docs\": docsEntry,\n \"agentmark\": stdioEntry(cloudUrl, /* includeType */ false),\n \"agentmark-local\": stdioEntry(LOCAL_DEV_URL, /* includeType */ false),\n },\n };\n fs.writeJsonSync(configPath, config, { spaces: 2 });\n return { configPath };\n }\n\n if (client === \"zed\") {\n const zedDir = path.join(targetPath, \".zed\");\n fs.ensureDirSync(zedDir);\n const configPath = path.join(zedDir, \"settings.json\");\n const config = {\n context_servers: {\n \"agentmark-docs\": docsEntry,\n \"agentmark\": stdioEntry(cloudUrl, /* includeType */ false),\n \"agentmark-local\": stdioEntry(LOCAL_DEV_URL, /* includeType */ false),\n },\n };\n fs.writeJsonSync(configPath, config, { spaces: 2 });\n return { configPath };\n }\n\n if (client === \"cursor\") {\n const cursorDir = path.join(targetPath, \".cursor\");\n fs.ensureDirSync(cursorDir);\n const configPath = path.join(cursorDir, \"mcp.json\");\n const config = {\n mcpServers: {\n \"agentmark-docs\": docsEntry,\n \"agentmark\": stdioEntry(cloudUrl, /* includeType */ false),\n \"agentmark-local\": stdioEntry(LOCAL_DEV_URL, /* includeType */ false),\n },\n };\n fs.writeJsonSync(configPath, config, { spaces: 2 });\n return { configPath };\n }\n\n if (client === \"claude-code\") {\n const configPath = path.join(targetPath, \".mcp.json\");\n const config = {\n mcpServers: {\n \"agentmark-docs\": { type: \"http\" as const, ...docsEntry },\n \"agentmark\": stdioEntry(cloudUrl, /* includeType */ true),\n \"agentmark-local\": stdioEntry(LOCAL_DEV_URL, /* includeType */ true),\n },\n };\n fs.writeJsonSync(configPath, config, { spaces: 2 });\n return { configPath };\n }\n\n return null;\n}\n","import { execFileSync } from \"child_process\";\n\n/**\n * Installs the AgentMark agent skill (https://github.com/agentmark-ai/skills)\n * into the freshly-scaffolded project. The vercel-labs/skills tool puts files\n * at `./.agents/skills/agentmark/` and symlinks them into per-tool paths\n * (Claude Code, Codex, Cursor, GitHub Copilot, +others) per the\n * agentskills.io 0.0.2 spec.\n *\n * Uses execFileSync (no shell) for safety. All arguments are hardcoded\n * literals; no user input is interpolated.\n *\n * Best-effort: if the install fails (no network, npx unavailable, etc.) we\n * log a warning and keep going. The skill is a nice-to-have on top of a\n * working AgentMark project, not a hard requirement.\n */\n/**\n * True when the helper should skip the network install. Set in test runs\n * so the OSS Parity CI suite doesn't hit `npx skills add` per scaffolder\n * test (each call clones the public skills repo, adding 10-30s/test).\n *\n * Detected via:\n * - VITEST=true (Vitest sets this automatically)\n * - NODE_ENV=test (broad convention; many runners set this)\n * - AGENTMARK_SKIP_SKILL_INSTALL=1 (explicit opt-out for any other context)\n */\nconst shouldSkip = (): boolean =>\n process.env.VITEST === \"true\" ||\n process.env.NODE_ENV === \"test\" ||\n process.env.AGENTMARK_SKIP_SKILL_INSTALL === \"1\";\n\nexport const installAgentmarkSkill = (targetPath: string): void => {\n if (shouldSkip()) {\n console.log(\"\\n⏭️ Skipping agent skill install (test environment detected).\");\n return;\n }\n try {\n console.log(\"\\n📚 Installing AgentMark agent skill...\");\n console.log(\" (teaches Claude Code / Codex / Cursor / Copilot how to use AgentMark)\");\n execFileSync(\n \"npx\",\n [\"--yes\", \"skills\", \"add\", \"agentmark-ai/skills\"],\n {\n cwd: targetPath,\n stdio: \"inherit\",\n },\n );\n console.log(\"✅ Agent skill installed at ./.agents/skills/agentmark/\");\n } catch (error) {\n console.warn(\n \"\\n⚠️ Could not install the AgentMark agent skill automatically.\",\n );\n console.warn(\" You can install it later with:\");\n console.warn(\" cd \" + targetPath);\n console.warn(\" npx skills add agentmark-ai/skills\");\n if (error instanceof Error) {\n console.warn(` Reason: ${error.message.split(\"\\n\")[0]}`);\n }\n }\n};\n","import { execSync } from \"child_process\";\n\n/**\n * Initialize a git repository and create an initial commit.\n *\n * Skips silently when:\n * - The target path is already inside a git repository\n * - git is not installed\n * - Any git command fails (non-fatal)\n */\nexport function initGitRepo(targetPath: string): boolean {\n try {\n // Check if git is available\n try {\n execSync(\"git --version\", { stdio: \"ignore\" });\n } catch {\n console.log(\"⚠️ git not found — skipping repository initialization\");\n return false;\n }\n\n // Check if already inside a git repo\n try {\n execSync(\"git rev-parse --is-inside-work-tree\", {\n cwd: targetPath,\n stdio: \"ignore\",\n });\n // Already in a git repo — skip\n return false;\n } catch {\n // Not in a git repo — proceed\n }\n\n execSync(\"git init\", { cwd: targetPath, stdio: \"ignore\" });\n execSync(\"git add -A\", { cwd: targetPath, stdio: \"ignore\" });\n execSync(\n 'git -c user.name=\"create-agentmark\" -c user.email=\"noreply\" commit -m \"Initial commit from create-agentmark\"',\n { cwd: targetPath, stdio: \"ignore\" },\n );\n\n console.log(\"✅ Initialized git repository with initial commit\");\n return true;\n } catch {\n console.log(\"⚠️ Could not initialize git repository\");\n return false;\n }\n}\n","/**\n * Project detection for the minimal `npm create agentmark` init flow.\n *\n * Two questions only: \"is this an existing project?\" (drives whether we\n * run `git init`) and \"does AgentMark already exist here?\" (drives the\n * `agentmark.json` conflict prompt). Everything else — language, package\n * manager, Python venv, conflict file inventory — lives in the skill\n * workflow now, which can ask the docs MCP for current guidance instead\n * of encoding heuristics into the CLI.\n */\n\nimport fs from 'fs-extra';\nimport path from 'path';\nimport type { ProjectInfo } from './types.js';\n\nconst TYPESCRIPT_INDICATORS = ['package.json', 'tsconfig.json', 'node_modules'] as const;\nconst PYTHON_INDICATORS = ['pyproject.toml', 'requirements.txt', 'setup.py', '.venv', 'venv'] as const;\n\n/** Any TypeScript/Node.js project marker present in the target directory. */\nexport function detectTypeScriptProject(targetPath: string): boolean {\n return TYPESCRIPT_INDICATORS.some((file) => fs.existsSync(path.join(targetPath, file)));\n}\n\n/** Any Python project marker present in the target directory. */\nexport function detectPythonProject(targetPath: string): boolean {\n return PYTHON_INDICATORS.some((file) => fs.existsSync(path.join(targetPath, file)));\n}\n\n/**\n * Combined detection. `isExistingProject` is true if either language's\n * markers are present; the init flow uses it only to decide whether to\n * run `git init`.\n */\nexport function detectProjectInfo(targetPath: string): ProjectInfo {\n return {\n isExistingProject: detectTypeScriptProject(targetPath) || detectPythonProject(targetPath),\n hasAgentmarkJson: fs.existsSync(path.join(targetPath, 'agentmark.json')),\n hasAgentmarkDir: fs.existsSync(path.join(targetPath, 'agentmark')),\n };\n}\n\n/**\n * True for any spelling of \"current directory\" the user might type at the\n * folder prompt. Used to skip mkdir/cd noise when the user wants to wire\n * AgentMark into the directory they're already in.\n */\nexport function isCurrentDirectory(folderName: string): boolean {\n return folderName === '.' || folderName === './' || folderName === '.\\\\';\n}\n"],"mappings":";;;AAAA,OAAOA,SAAQ;AACf,OAAOC,WAAU;AACjB,OAAO,aAAa;AACpB,SAAS,eAAe,qBAAqB;;;ACyC7C,OAAO,QAAQ;AACf,YAAY,UAAU;AAKtB,IAAM,gBAAgB;AAGtB,IAAM,gBAAgB;AAGtB,IAAM,qBAAqB;AAwB3B,SAAS,WAAW,QAAgB,aAAwC;AAC1E,QAAM,QAA0B;AAAA,IAC9B,SAAS;AAAA,IACT,MAAM,CAAC,MAAM,kBAAkB;AAAA,EACjC;AACA,MAAI,WAAW,eAAe;AAC5B,UAAM,MAAM,EAAE,mBAAmB,OAAO;AAAA,EAC1C;AACA,MAAI,YAAa,OAAM,OAAO;AAC9B,SAAO;AACT;AAqBO,SAAS,eACd,QACA,YACA,OAA8B,CAAC,GACX;AACpB,MAAI,WAAW,OAAQ,QAAO;AAE9B,QAAM,WAAW,KAAK,gBAAgB;AACtC,QAAM,YAA+B,EAAE,KAAK,gCAAgC;AAE5E,MAAI,WAAW,UAAU;AACvB,UAAM,YAAiB,UAAK,YAAY,SAAS;AACjD,OAAG,cAAc,SAAS;AAC1B,UAAM,aAAkB,UAAK,WAAW,UAAU;AAClD,UAAM,SAAS;AAAA,MACb,SAAS;AAAA,QACP,kBAAkB;AAAA,QAClB,aAAa;AAAA,UAAW;AAAA;AAAA,UAA4B;AAAA,QAAK;AAAA,QACzD,mBAAmB;AAAA,UAAW;AAAA;AAAA,UAAiC;AAAA,QAAK;AAAA,MACtE;AAAA,IACF;AACA,OAAG,cAAc,YAAY,QAAQ,EAAE,QAAQ,EAAE,CAAC;AAClD,WAAO,EAAE,WAAW;AAAA,EACtB;AAEA,MAAI,WAAW,OAAO;AACpB,UAAM,SAAc,UAAK,YAAY,MAAM;AAC3C,OAAG,cAAc,MAAM;AACvB,UAAM,aAAkB,UAAK,QAAQ,eAAe;AACpD,UAAM,SAAS;AAAA,MACb,iBAAiB;AAAA,QACf,kBAAkB;AAAA,QAClB,aAAa;AAAA,UAAW;AAAA;AAAA,UAA4B;AAAA,QAAK;AAAA,QACzD,mBAAmB;AAAA,UAAW;AAAA;AAAA,UAAiC;AAAA,QAAK;AAAA,MACtE;AAAA,IACF;AACA,OAAG,cAAc,YAAY,QAAQ,EAAE,QAAQ,EAAE,CAAC;AAClD,WAAO,EAAE,WAAW;AAAA,EACtB;AAEA,MAAI,WAAW,UAAU;AACvB,UAAM,YAAiB,UAAK,YAAY,SAAS;AACjD,OAAG,cAAc,SAAS;AAC1B,UAAM,aAAkB,UAAK,WAAW,UAAU;AAClD,UAAM,SAAS;AAAA,MACb,YAAY;AAAA,QACV,kBAAkB;AAAA,QAClB,aAAa;AAAA,UAAW;AAAA;AAAA,UAA4B;AAAA,QAAK;AAAA,QACzD,mBAAmB;AAAA,UAAW;AAAA;AAAA,UAAiC;AAAA,QAAK;AAAA,MACtE;AAAA,IACF;AACA,OAAG,cAAc,YAAY,QAAQ,EAAE,QAAQ,EAAE,CAAC;AAClD,WAAO,EAAE,WAAW;AAAA,EACtB;AAEA,MAAI,WAAW,eAAe;AAC5B,UAAM,aAAkB,UAAK,YAAY,WAAW;AACpD,UAAM,SAAS;AAAA,MACb,YAAY;AAAA,QACV,kBAAkB,EAAE,MAAM,QAAiB,GAAG,UAAU;AAAA,QACxD,aAAa;AAAA,UAAW;AAAA;AAAA,UAA4B;AAAA,QAAI;AAAA,QACxD,mBAAmB;AAAA,UAAW;AAAA;AAAA,UAAiC;AAAA,QAAI;AAAA,MACrE;AAAA,IACF;AACA,OAAG,cAAc,YAAY,QAAQ,EAAE,QAAQ,EAAE,CAAC;AAClD,WAAO,EAAE,WAAW;AAAA,EACtB;AAEA,SAAO;AACT;;;ACpLA,SAAS,oBAAoB;AA0B7B,IAAM,aAAa,MACjB,QAAQ,IAAI,WAAW,UACvB,QAAQ,IAAI,aAAa,UACzB,QAAQ,IAAI,iCAAiC;AAExC,IAAM,wBAAwB,CAAC,eAA6B;AACjE,MAAI,WAAW,GAAG;AAChB,YAAQ,IAAI,2EAAiE;AAC7E;AAAA,EACF;AACA,MAAI;AACF,YAAQ,IAAI,iDAA0C;AACtD,YAAQ,IAAI,0EAA0E;AACtF;AAAA,MACE;AAAA,MACA,CAAC,SAAS,UAAU,OAAO,qBAAqB;AAAA,MAChD;AAAA,QACE,KAAK;AAAA,QACL,OAAO;AAAA,MACT;AAAA,IACF;AACA,YAAQ,IAAI,6DAAwD;AAAA,EACtE,SAAS,OAAO;AACd,YAAQ;AAAA,MACN;AAAA,IACF;AACA,YAAQ,KAAK,mCAAmC;AAChD,YAAQ,KAAK,aAAa,UAAU;AACpC,YAAQ,KAAK,yCAAyC;AACtD,QAAI,iBAAiB,OAAO;AAC1B,cAAQ,KAAK,cAAc,MAAM,QAAQ,MAAM,IAAI,EAAE,CAAC,CAAC,EAAE;AAAA,IAC3D;AAAA,EACF;AACF;;;AC3DA,SAAS,gBAAgB;AAUlB,SAAS,YAAY,YAA6B;AACvD,MAAI;AAEF,QAAI;AACF,eAAS,iBAAiB,EAAE,OAAO,SAAS,CAAC;AAAA,IAC/C,QAAQ;AACN,cAAQ,IAAI,uEAAwD;AACpE,aAAO;AAAA,IACT;AAGA,QAAI;AACF,eAAS,uCAAuC;AAAA,QAC9C,KAAK;AAAA,QACL,OAAO;AAAA,MACT,CAAC;AAED,aAAO;AAAA,IACT,QAAQ;AAAA,IAER;AAEA,aAAS,YAAY,EAAE,KAAK,YAAY,OAAO,SAAS,CAAC;AACzD,aAAS,cAAc,EAAE,KAAK,YAAY,OAAO,SAAS,CAAC;AAC3D;AAAA,MACE;AAAA,MACA,EAAE,KAAK,YAAY,OAAO,SAAS;AAAA,IACrC;AAEA,YAAQ,IAAI,uDAAkD;AAC9D,WAAO;AAAA,EACT,QAAQ;AACN,YAAQ,IAAI,mDAAyC;AACrD,WAAO;AAAA,EACT;AACF;;;AClCA,OAAOC,SAAQ;AACf,OAAOC,WAAU;AAGjB,IAAM,wBAAwB,CAAC,gBAAgB,iBAAiB,cAAc;AAC9E,IAAM,oBAAoB,CAAC,kBAAkB,oBAAoB,YAAY,SAAS,MAAM;AAGrF,SAAS,wBAAwB,YAA6B;AACnE,SAAO,sBAAsB,KAAK,CAAC,SAASD,IAAG,WAAWC,MAAK,KAAK,YAAY,IAAI,CAAC,CAAC;AACxF;AAGO,SAAS,oBAAoB,YAA6B;AAC/D,SAAO,kBAAkB,KAAK,CAAC,SAASD,IAAG,WAAWC,MAAK,KAAK,YAAY,IAAI,CAAC,CAAC;AACpF;AAOO,SAAS,kBAAkB,YAAiC;AACjE,SAAO;AAAA,IACL,mBAAmB,wBAAwB,UAAU,KAAK,oBAAoB,UAAU;AAAA,IACxF,kBAAkBD,IAAG,WAAWC,MAAK,KAAK,YAAY,gBAAgB,CAAC;AAAA,IACvE,iBAAiBD,IAAG,WAAWC,MAAK,KAAK,YAAY,WAAW,CAAC;AAAA,EACnE;AACF;AAOO,SAAS,mBAAmB,YAA6B;AAC9D,SAAO,eAAe,OAAO,eAAe,QAAQ,eAAe;AACrE;;;AJCO,IAAM,cAAoC,CAAC,eAAe,UAAU,UAAU,KAAK;AAEnF,IAAM,iBAA0C;AAAA,EACrD,SACE;AAAA,EACF,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,eAAe;AAAA;AAAA;AAAA;AAAA,EAIf,eAAe,CAAC,gBAAgB;AAClC;AAEO,IAAM,YAAY,CAAC,OAAiB,QAAQ,KAAK,MAAM,CAAC,MAAe;AAC5E,QAAM,SAAkB,CAAC;AAEzB,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,MAAM,KAAK,CAAC;AAClB,QAAI,QAAQ,UAAU;AACpB,aAAO,OAAO,KAAK,EAAE,CAAC;AAAA,IACxB,WAAW,QAAQ,YAAY;AAC7B,YAAM,QAAQ,KAAK,EAAE,CAAC;AACtB,UAAI,CAAC,MAAO,OAAM,IAAI,MAAM,2BAA2B;AACvD,YAAM,MAAM,UAAU,QAClB,CAAC,GAAG,WAAW,IACf,MAAM,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO;AACxD,aAAO,UAAU,CAAC,GAAI,OAAO,WAAW,CAAC,GAAI,GAAG,GAAG;AAAA,IACrD,WAAW,QAAQ,eAAe;AAChC,aAAO,YAAY;AAAA,IACrB,WAAW,QAAQ,WAAW,QAAQ,MAAM;AAC1C,aAAO,MAAM;AAAA,IACf,WAAW,QAAQ,YAAY,QAAQ,MAAM;AAC3C,aAAO,OAAO;AAAA,IAChB,WAAW,QAAQ,aAAa;AAC9B,YAAM,QAAQ,KAAK,EAAE,CAAC;AACtB,UAAI,CAAC,SAAS,CAAC,eAAe,KAAK,KAAK,GAAG;AACzC,cAAM,IAAI,MAAM,+CAA+C,KAAK,IAAI;AAAA,MAC1E;AACA,aAAO,SAAS;AAAA,IAClB,WAAW,OAAO,CAAC,IAAI,WAAW,IAAI,KAAK,CAAC,OAAO,MAAM;AAEvD,aAAO,OAAO;AAAA,IAChB;AAAA,EACF;AAEA,SAAO;AACT;AAEO,IAAM,cAAc,CAAC,OAC1B,OAAO,WAAW,YACd,OAAO,QAAQ,QACb,OAAO,WAAW,WAChB,OAAO,gBAAgB,gBACrB;AASL,IAAM,oBAAoB,CAAC,MAAc,QAAQ,IAAI,MAC1DC,IAAG,WAAWC,MAAK,KAAK,KAAK,cAAc,CAAC,KAC5CD,IAAG,WAAWC,MAAK,KAAK,KAAK,gBAAgB,CAAC,IAC1C,MACA;AAMC,IAAM,oBAAoB,OAC/B,SACA,QACkE;AAClE,MAAI,aAAa;AACjB,MAAI,CAAC,cAAc,KAAK;AACtB,iBAAa,kBAAkB;AAAA,EACjC;AACA,MAAI,CAAC,YAAY;AACf,UAAM,WAAW,MAAM,QAAQ;AAAA,MAC7B,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS,kBAAkB;AAAA,IAC7B,CAAC;AACD,iBAAa,SAAS;AAAA,EACxB;AACA,MAAI,CAAC,WAAY,QAAO;AAExB,QAAM,eAAe,mBAAmB,UAAU;AAClD,QAAM,aAAa,eAAe,QAAQ,IAAI,IAAIA,MAAK,QAAQ,UAAU;AACzE,MAAI,CAAC,aAAc,CAAAD,IAAG,cAAc,UAAU;AAC9C,SAAO,EAAE,YAAY,aAAa;AACpC;AAQO,IAAM,iBAAiB,OAC5B,YACA,QACyB;AACzB,MAAI,cAAc,WAAW,SAAS,GAAG;AACvC,eAAW,KAAK,YAAY;AAC1B,UAAI,CAAC,YAAY,SAAS,CAAC,GAAG;AAC5B,cAAM,IAAI,MAAM,mBAAmB,CAAC,aAAa,YAAY,KAAK,IAAI,CAAC,EAAE;AAAA,MAC3E;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,MAAI,IAAK,QAAO,CAAC,GAAG,WAAW;AAC/B,QAAM,WAAW,MAAM,QAAQ;AAAA,IAC7B,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,IACT,cAAc;AAAA,IACd,MAAM;AAAA,IACN,SAAS,YAAY,IAAI,CAAC,QAAQ;AAAA,MAChC,OAAO,YAAY,EAAE;AAAA,MACrB,OAAO;AAAA,MACP,UAAU;AAAA,IACZ,EAAE;AAAA,EACJ,CAAC;AACD,SAAQ,SAAS,WAAW,CAAC;AAC/B;AAQO,IAAM,2BAA2B,OACtC,UACA,WACA,QACqB;AACrB,MAAI,CAACA,IAAG,WAAW,QAAQ,EAAG,QAAO;AACrC,MAAI,UAAW,QAAO;AAGtB,MAAI,IAAK,QAAO;AAChB,QAAM,EAAE,OAAO,IAAI,MAAM,QAAQ;AAAA,IAC/B,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,IACT,SAAS;AAAA,MACP,EAAE,OAAO,wBAAwB,OAAO,OAAO;AAAA,MAC/C,EAAE,OAAO,iCAAiC,OAAO,YAAY;AAAA,IAC/D;AAAA,IACA,SAAS;AAAA,EACX,CAAC;AACD,SAAO,WAAW;AACpB;AAEO,IAAM,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAqBd,IAAM,OAAO,YAA2B;AAC7C,QAAM,UAAU,UAAU;AAE1B,MAAI,QAAQ,MAAM;AAChB,YAAQ,IAAI,KAAK;AACjB;AAAA,EACF;AAEA,QAAM,SAAS,MAAM,kBAAkB,QAAQ,MAAM,QAAQ,GAAG;AAChE,MAAI,CAAC,QAAQ;AACX,YAAQ,IAAI,UAAU;AACtB;AAAA,EACF;AACA,QAAM,EAAE,WAAW,IAAI;AAEvB,QAAM,cAAc,kBAAkB,UAAU;AAChD,QAAM,UAAU,MAAM,eAAe,QAAQ,SAAS,QAAQ,GAAG;AAEjE,UAAQ,IAAI,EAAE;AAGd,QAAM,oBAAoBC,MAAK,KAAK,YAAY,gBAAgB;AAChE,MAAI,MAAM,yBAAyB,mBAAmB,QAAQ,WAAW,QAAQ,GAAG,GAAG;AACrF,IAAAD,IAAG,cAAc,mBAAmB,gBAAgB,EAAE,QAAQ,EAAE,CAAC;AACjE,YAAQ,IAAI,uBAAkB;AAAA,EAChC,OAAO;AACL,YAAQ,IAAI,8CAAoC;AAAA,EAClD;AAKA,QAAM,mBAAmBC,MAAK,KAAK,YAAY,WAAW;AAC1D,MAAI,CAACD,IAAG,WAAW,gBAAgB,GAAG;AACpC,IAAAA,IAAG,cAAc,gBAAgB;AACjC,IAAAA,IAAG,cAAcC,MAAK,KAAK,kBAAkB,UAAU,GAAG,EAAE;AAC5D,YAAQ,IAAI,6DAAwD;AAAA,EACtE,OAAO;AACL,YAAQ,IAAI,0CAAgC;AAAA,EAC9C;AAGA,aAAW,UAAU,SAAS;AAC5B,QAAI;AACF,YAAM,SAAS,eAAe,QAAQ,YAAY,EAAE,cAAc,QAAQ,OAAO,CAAC;AAClF,UAAI,QAAQ;AACV,cAAM,MAAMA,MAAK,SAAS,YAAY,OAAO,UAAU,KAAK,OAAO;AACnE,gBAAQ,IAAI,qBAAgB,YAAY,MAAM,CAAC,MAAM,GAAG,EAAE;AAAA,MAC5D;AAAA,IACF,SAAS,KAAK;AACZ,YAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,cAAQ,KAAK,gDAAsC,YAAY,MAAM,CAAC,KAAK,OAAO,EAAE;AAAA,IACtF;AAAA,EACF;AAGA,wBAAsB,UAAU;AAGhC,MAAI,CAAC,YAAY,mBAAmB;AAClC,gBAAY,UAAU;AAAA,EACxB;AAKA,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,+BAA0B;AACtC,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,6EAA6E;AACzF,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,4CAA8C;AAC1D,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,2EAA2E;AACvF,UAAQ,IAAI,4EAA4E;AAC1F;AAeA,IAAM,oBAAoB,MAAe;AACvC,QAAM,QAAQ,QAAQ,KAAK,CAAC;AAC5B,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI;AACF,UAAM,YAAY,cAAcD,IAAG,aAAa,KAAK,CAAC,EAAE;AACxD,UAAM,WAAW,cAAcA,IAAG,aAAa,cAAc,YAAY,GAAG,CAAC,CAAC,EAAE;AAChF,WAAO,cAAc;AAAA,EACvB,QAAQ;AAGN,WAAO;AAAA,EACT;AACF;AAEA,IAAI,kBAAkB,GAAG;AACvB,OAAK,EAAE,MAAM,CAAC,UAAU;AACtB,YAAQ,MAAM,UAAU,KAAK;AAC7B,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACH;","names":["fs","path","fs","path","fs","path"]}
|