frontmcp 1.0.0 → 1.0.1
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/package.json +2 -2
- package/src/commands/build/exec/cli-runtime/cli-bundler.js +2 -0
- package/src/commands/build/exec/cli-runtime/cli-bundler.js.map +1 -1
- package/src/commands/build/exec/cli-runtime/generate-cli-entry.js +37 -5
- package/src/commands/build/exec/cli-runtime/generate-cli-entry.js.map +1 -1
- package/src/commands/build/exec/cli-runtime/schema-extractor.d.ts +12 -0
- package/src/commands/build/exec/cli-runtime/schema-extractor.js +17 -1
- package/src/commands/build/exec/cli-runtime/schema-extractor.js.map +1 -1
- package/src/commands/build/exec/index.js +42 -1
- package/src/commands/build/exec/index.js.map +1 -1
- package/src/commands/build/index.js +9 -5
- package/src/commands/build/index.js.map +1 -1
- package/src/core/cli.js +4 -1
- package/src/core/cli.js.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "frontmcp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "FrontMCP command line interface",
|
|
5
5
|
"author": "AgentFront <info@agentfront.dev>",
|
|
6
6
|
"homepage": "https://docs.agentfront.dev",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@clack/prompts": "^0.10.0",
|
|
33
|
-
"@frontmcp/utils": "1.0.
|
|
33
|
+
"@frontmcp/utils": "1.0.1",
|
|
34
34
|
"commander": "^13.0.0",
|
|
35
35
|
"tslib": "^2.3.0",
|
|
36
36
|
"vectoriadb": "^2.1.3",
|
|
@@ -31,6 +31,7 @@ async function bundleCliWithEsbuild(cliEntryPath, outDir, config, options) {
|
|
|
31
31
|
// Only true native addons and optional peer deps stay external in self-contained mode
|
|
32
32
|
'better-sqlite3',
|
|
33
33
|
'fsevents',
|
|
34
|
+
'esbuild',
|
|
34
35
|
'@vercel/kv',
|
|
35
36
|
'@frontmcp/storage-sqlite',
|
|
36
37
|
'@enclave-vm/core',
|
|
@@ -41,6 +42,7 @@ async function bundleCliWithEsbuild(cliEntryPath, outDir, config, options) {
|
|
|
41
42
|
'@frontmcp/sdk',
|
|
42
43
|
'better-sqlite3',
|
|
43
44
|
'fsevents',
|
|
45
|
+
'esbuild',
|
|
44
46
|
'@vercel/kv',
|
|
45
47
|
'@frontmcp/storage-sqlite',
|
|
46
48
|
'@enclave-vm/core',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-bundler.js","sourceRoot":"","sources":["../../../../../../src/commands/build/exec/cli-runtime/cli-bundler.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAeH,
|
|
1
|
+
{"version":3,"file":"cli-bundler.js","sourceRoot":"","sources":["../../../../../../src/commands/build/exec/cli-runtime/cli-bundler.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAeH,oDAyEC;;AAtFD,mDAA6B;AAQ7B;;;;GAIG;AACI,KAAK,UAAU,oBAAoB,CACxC,YAAoB,EACpB,MAAc,EACd,MAA0B,EAC1B,OAAqC;IAErC,IAAI,OAAiC,CAAC;IACtC,IAAI,CAAC;QACH,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,wEAAwE,CACzE,CAAC;IACJ,CAAC;IAED,MAAM,aAAa,GAAG,GAAG,MAAM,CAAC,IAAI,gBAAgB,CAAC;IACrD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACpD,MAAM,aAAa,GAAG,OAAO,EAAE,aAAa,IAAI,KAAK,CAAC;IAEtD,uEAAuE;IACvE,gEAAgE;IAChE,MAAM,gBAAgB,GAAG,GAAG,MAAM,CAAC,IAAI,YAAY,CAAC;IAEpD,MAAM,QAAQ,GAAG,aAAa;QAC5B,CAAC,CAAC;YACE,sFAAsF;YACtF,gBAAgB;YAChB,UAAU;YACV,SAAS;YACT,YAAY;YACZ,0BAA0B;YAC1B,kBAAkB;YAClB,GAAG,CAAC,MAAM,CAAC,YAAY,EAAE,YAAY,IAAI,EAAE,CAAC;SAC7C;QACH,CAAC,CAAC;YACE,KAAK,gBAAgB,EAAE;YACvB,eAAe;YACf,gBAAgB;YAChB,UAAU;YACV,SAAS;YACT,YAAY;YACZ,0BAA0B;YAC1B,kBAAkB;YAClB,GAAG,CAAC,MAAM,CAAC,YAAY,EAAE,YAAY,IAAI,EAAE,CAAC;YAC5C,GAAG,CAAC,MAAM,CAAC,OAAO,EAAE,QAAQ,IAAI,EAAE,CAAC;SACpC,CAAC;IAEN,MAAM,OAAO,CAAC,KAAK,CAAC;QAClB,WAAW,EAAE,CAAC,YAAY,CAAC;QAC3B,MAAM,EAAE,IAAI;QACZ,QAAQ,EAAE,MAAM;QAChB,MAAM,EAAE,KAAK;QACb,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,IAAI,QAAQ;QAC1C,OAAO,EAAE,UAAU;QACnB,QAAQ;QACR,SAAS,EAAE,IAAI;QACf,WAAW,EAAE,IAAI;QACjB,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,IAAI,KAAK;QACvC,MAAM,EAAE;YACN,EAAE,EAAE,qBAAqB;SAC1B;QACD,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM;QAC9B,SAAS,EAAE,KAAK;QAChB,QAAQ,EAAE,SAAS;KACpB,CAAC,CAAC;IAEH,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IAErC,OAAO;QACL,UAAU;QACV,UAAU,EAAE,IAAI,CAAC,IAAI;KACtB,CAAC;AACJ,CAAC","sourcesContent":["/**\n * esbuild configuration for the CLI bundle.\n * Bundles the generated CLI entry point with commander.js inlined.\n */\n\nimport * as path from 'path';\nimport { FrontmcpExecConfig } from '../config';\n\nexport interface CliBundleResult {\n bundlePath: string;\n bundleSize: number;\n}\n\n/**\n * Bundle the generated CLI entry with esbuild.\n * Commander.js and runtime modules are inlined; the server bundle is external\n * unless selfContained mode is enabled (for SEA builds).\n */\nexport async function bundleCliWithEsbuild(\n cliEntryPath: string,\n outDir: string,\n config: FrontmcpExecConfig,\n options?: { selfContained?: boolean },\n): Promise<CliBundleResult> {\n let esbuild: typeof import('esbuild');\n try {\n esbuild = require('esbuild');\n } catch {\n throw new Error(\n 'esbuild is required for CLI builds. Install it: npm install -D esbuild',\n );\n }\n\n const cliBundleName = `${config.name}-cli.bundle.js`;\n const bundlePath = path.join(outDir, cliBundleName);\n const selfContained = options?.selfContained ?? false;\n\n // The server bundle is loaded via require() at runtime — keep external\n // unless selfContained mode where everything is inlined for SEA\n const serverBundleName = `${config.name}.bundle.js`;\n\n const external = selfContained\n ? [\n // Only true native addons and optional peer deps stay external in self-contained mode\n 'better-sqlite3',\n 'fsevents',\n 'esbuild',\n '@vercel/kv',\n '@frontmcp/storage-sqlite',\n '@enclave-vm/core',\n ...(config.dependencies?.nativeAddons || []),\n ]\n : [\n `./${serverBundleName}`,\n '@frontmcp/sdk',\n 'better-sqlite3',\n 'fsevents',\n 'esbuild',\n '@vercel/kv',\n '@frontmcp/storage-sqlite',\n '@enclave-vm/core',\n ...(config.dependencies?.nativeAddons || []),\n ...(config.esbuild?.external || []),\n ];\n\n await esbuild.build({\n entryPoints: [cliEntryPath],\n bundle: true,\n platform: 'node',\n format: 'cjs',\n target: config.esbuild?.target || 'node22',\n outfile: bundlePath,\n external,\n keepNames: true,\n treeShaking: true,\n minify: config.esbuild?.minify ?? false,\n banner: {\n js: '#!/usr/bin/env node',\n },\n define: config.esbuild?.define,\n sourcemap: false,\n logLevel: 'warning',\n });\n\n const fs = require('fs');\n const stat = fs.statSync(bundlePath);\n\n return {\n bundlePath,\n bundleSize: stat.size,\n };\n}\n"]}
|
|
@@ -110,6 +110,8 @@ ${hasOAuth ? "var oauthHelper = require('./oauth-helper');" : ''}
|
|
|
110
110
|
var APP_NAME = ${JSON.stringify(appName)};
|
|
111
111
|
var SCRIPT_DIR = __dirname;
|
|
112
112
|
var FRONTMCP_HOME = process.env.FRONTMCP_HOME || path.join(os.homedir(), '.frontmcp');
|
|
113
|
+
// Set app name for file logger (writes to ~/.frontmcp/logs/{appName}-{timestamp}.log)
|
|
114
|
+
process.env.FRONTMCP_APP_NAME = process.env.FRONTMCP_APP_NAME || APP_NAME;
|
|
113
115
|
${selfContained
|
|
114
116
|
? `// Self-contained: server bundle and SDK are inlined by esbuild
|
|
115
117
|
var SERVER_BUNDLE = '../${serverBundleFilename}';`
|
|
@@ -132,7 +134,10 @@ async function getClient() {
|
|
|
132
134
|
}
|
|
133
135
|
|
|
134
136
|
// Fallback: in-process connect (with CLI mode for faster init)
|
|
137
|
+
// Suppress @FrontMcp decorator bootstrap — we only need config metadata, not a running server.
|
|
138
|
+
process.env.FRONTMCP_SCHEMA_EXTRACT = '1';
|
|
135
139
|
var mod = require(${selfContained ? `'../${serverBundleFilename}'` : 'SERVER_BUNDLE'});
|
|
140
|
+
delete process.env.FRONTMCP_SCHEMA_EXTRACT;
|
|
136
141
|
var configOrClass = mod.default || mod;
|
|
137
142
|
var sdk = require('@frontmcp/sdk');
|
|
138
143
|
var connect = sdk.connect || sdk.direct.connect;${authRequired ? `
|
|
@@ -150,7 +155,22 @@ program
|
|
|
150
155
|
.name(${JSON.stringify(appName)})
|
|
151
156
|
.version(${JSON.stringify(appVersion)})
|
|
152
157
|
.description(${JSON.stringify(description || `${appName} CLI`)})
|
|
153
|
-
.option('--output <mode>', 'Output format: text or json', ${JSON.stringify(outputDefault)})
|
|
158
|
+
.option('--output <mode>', 'Output format: text or json', ${JSON.stringify(outputDefault)})
|
|
159
|
+
.option('--verbose', 'Enable verbose console logging (logs always go to ~/.frontmcp/logs/)')
|
|
160
|
+
.option('--log-dir <path>', 'Directory for log files (default: ~/.frontmcp/logs/)');
|
|
161
|
+
|
|
162
|
+
// Wire --verbose and --log-dir to env vars early (before any command action runs).
|
|
163
|
+
// Parse argv directly since commander hooks may not be available in all versions.
|
|
164
|
+
(function() {
|
|
165
|
+
var argv = process.argv;
|
|
166
|
+
if (argv.indexOf('--verbose') !== -1) {
|
|
167
|
+
process.env.FRONTMCP_CLI_VERBOSE = '1';
|
|
168
|
+
}
|
|
169
|
+
var logDirIdx = argv.indexOf('--log-dir');
|
|
170
|
+
if (logDirIdx !== -1 && argv[logDirIdx + 1]) {
|
|
171
|
+
process.env.FRONTMCP_LOG_DIR = argv[logDirIdx + 1];
|
|
172
|
+
}
|
|
173
|
+
})();
|
|
154
174
|
|
|
155
175
|
program.configureHelp({
|
|
156
176
|
sortSubcommands: false,
|
|
@@ -1110,13 +1130,20 @@ function generateInstallCommand(appName, nativeDeps, selfContained) {
|
|
|
1110
1130
|
console.log('Installing ${appName}...');
|
|
1111
1131
|
dirs.forEach(function(d) { fs.mkdirSync(d, { recursive: true }); });
|
|
1112
1132
|
|
|
1113
|
-
// Copy bundle files
|
|
1133
|
+
// Copy bundle files and skill content
|
|
1114
1134
|
var files = fs.readdirSync(SCRIPT_DIR).filter(function(f) {
|
|
1115
|
-
return f.endsWith('.js') || f.endsWith('.json')${selfContained ? " || f.endsWith('-bin')" : ''};
|
|
1135
|
+
return f.endsWith('.js') || f.endsWith('.json') || f.endsWith('.md')${selfContained ? " || f.endsWith('-bin')" : ''};
|
|
1116
1136
|
});
|
|
1117
1137
|
files.forEach(function(f) {
|
|
1118
1138
|
fs.copyFileSync(pathMod.join(SCRIPT_DIR, f), pathMod.join(appDir, f));
|
|
1119
1139
|
});
|
|
1140
|
+
// Copy skill content directories (only those that exist in the build output)
|
|
1141
|
+
var entries = fs.readdirSync(SCRIPT_DIR, { withFileTypes: true });
|
|
1142
|
+
entries.forEach(function(ent) {
|
|
1143
|
+
if (ent.isDirectory()) {
|
|
1144
|
+
fs.cpSync(pathMod.join(SCRIPT_DIR, ent.name), pathMod.join(appDir, ent.name), { recursive: true });
|
|
1145
|
+
}
|
|
1146
|
+
});
|
|
1120
1147
|
console.log(' Copied ' + files.length + ' files to ' + appDir);
|
|
1121
1148
|
|
|
1122
1149
|
// Install native deps
|
|
@@ -1335,9 +1362,14 @@ function generateFooter() {
|
|
|
1335
1362
|
console.error('Unknown command: ' + args[0]);
|
|
1336
1363
|
process.exitCode = 1;
|
|
1337
1364
|
});
|
|
1338
|
-
program.parseAsync(process.argv).
|
|
1365
|
+
program.parseAsync(process.argv).then(function() {
|
|
1366
|
+
// Use exitCode instead of process.exit() so long-running commands
|
|
1367
|
+
// (e.g., serve) keep the event loop alive while short-lived commands
|
|
1368
|
+
// exit naturally when the event loop drains.
|
|
1369
|
+
process.exitCode = process.exitCode || 0;
|
|
1370
|
+
}).catch(function(err) {
|
|
1339
1371
|
console.error('Fatal:', err.message || err);
|
|
1340
|
-
process.
|
|
1372
|
+
process.exitCode = 1;
|
|
1341
1373
|
});`;
|
|
1342
1374
|
}
|
|
1343
1375
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-cli-entry.js","sourceRoot":"","sources":["../../../../../../src/commands/build/exec/cli-runtime/generate-cli-entry.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAgCH,wDAMC;AAKD,4CA4CC;AAm0CD,sDAIC;AA35CD,yDAAwK;AACxK,+DAA4F;AAE/E,QAAA,iBAAiB,GAAG,IAAI,GAAG,CAAC;IACvC,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW;IAC7C,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ;IAC/C,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS;IAC/D,QAAQ,EAAE,KAAK,EAAE,UAAU;CAC5B,CAAC,CAAC;AAiBH;;;GAGG;AACH,SAAgB,sBAAsB,CAAC,QAAgB;IACrD,MAAM,OAAO,GAAG,IAAA,kCAAY,EAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC1D,IAAI,yBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QACnC,OAAO,EAAE,OAAO,EAAE,GAAG,OAAO,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;IAC1D,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;AACxC,CAAC;AAED;;GAEG;AACH,SAAgB,gBAAgB,CAAC,OAAwB;IACvD,MAAM,EACJ,OAAO,EACP,UAAU,EACV,WAAW,EACX,oBAAoB,EACpB,aAAa,EACb,MAAM,EACN,YAAY,EACZ,WAAW,EACX,YAAY,GACb,GAAG,OAAO,CAAC;IAEZ,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC;IAEzC,MAAM,aAAa,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CACvC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,oCAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CACxE,CAAC;IAEF,MAAM,aAAa,GAAG,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC;IAE9C,MAAM,QAAQ,GAAa;QACzB,cAAc,CAAC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,oBAAoB,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,CAAC;QAC7I,oBAAoB,CAAC,aAAa,EAAE,OAAO,CAAC;QAC5C,wBAAwB,CAAC,MAAM,CAAC;QAChC,wBAAwB,CAAC,MAAM,CAAC,iBAAiB,CAAC;QAClD,sBAAsB,CAAC,MAAM,CAAC,OAAO,CAAC;QACtC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,sBAAsB,EAAE,CAAC,CAAC,CAAC,EAAE;QACnD,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,mBAAmB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE;QACzD,YAAY,CAAC,SAAS,CAAC,CAAC,CAAC,wBAAwB,EAAE,CAAC,CAAC,CAAC,EAAE;QACxD,yBAAyB,EAAE;QAC3B,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC;YACjB,oBAAoB,CAAC,OAAO,EAAE,WAAW,CAAC;YAC1C,qBAAqB,CAAC,OAAO,CAAC;YAC9B,uBAAuB,EAAE;SAC1B,CAAC,CAAC,CAAC,EAAE,CAAC;QACP,oBAAoB,CAAC,oBAAoB,EAAE,aAAa,CAAC;QACzD,qBAAqB,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC;QAClD,sBAAsB,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,EAAE,aAAa,CAAC;QAClE,sBAAsB,CAAC,OAAO,EAAE,oBAAoB,EAAE,aAAa,CAAC;QACpE,cAAc,EAAE;KACjB,CAAC;IAEF,OAAO,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,cAAc,CACrB,OAAe,EACf,UAAkB,EAClB,WAAmB,EACnB,oBAA4B,EAC5B,aAAqB,EACrB,YAAqB,EACrB,YAAmC,EACnC,WAAyB,EACzB,aAAuB;IAEvB,MAAM,QAAQ,GAAG,CAAC,CAAC,WAAW,CAAC;IAE/B,0CAA0C;IAC1C,MAAM,aAAa,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,iEAAiE,CAAC,CAAC,CAAC,EAAE,CAAC;IACnH,MAAM,WAAW,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,4DAA4D,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1G,MAAM,gBAAgB,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC,CAAC,sEAAsE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9H,MAAM,WAAW,GAAG,YAAY,CAAC,CAAC,CAAC,6GAA6G,CAAC,CAAC,CAAC,EAAE,CAAC;IAEtJ,sCAAsC;IACtC,MAAM,YAAY,GAAa;QAC7B,mBAAmB;QACnB,iCAAiC;KAClC,CAAC;IACF,IAAI,YAAY,CAAC,MAAM;QAAE,YAAY,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACjE,IAAI,YAAY,CAAC,IAAI;QAAE,YAAY,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAC7D,IAAI,YAAY,CAAC,SAAS;QAAE,YAAY,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;IACvE,IAAI,YAAY;QAAE,YAAY,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IACxD,YAAY,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;IAC/C,YAAY,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IAExC,OAAO;EACP,aAAa,CAAC,CAAC,CAAC;;;;;wBAKM,IAAI,CAAC,SAAS,CAAC,KAAK,GAAG,oBAAoB,CAAC;;;;;;;;;;;;CAYnE,CAAC,CAAC,CAAC,EAAE;;;;;;EAMJ,YAAY,CAAC,CAAC,CAAC,0FAA0F,CAAC,CAAC,CAAC,EAAE;EAC9G,QAAQ,CAAC,CAAC,CAAC,8CAA8C,CAAC,CAAC,CAAC,EAAE;;iBAE/C,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;;;EAGtC,aAAa;QACX,CAAC,CAAC;0BACoB,oBAAoB,IAAI;QAC9C,CAAC,CAAC,6CAA6C,IAAI,CAAC,SAAS,CAAC,oBAAoB,CAAC,IAAI;;;;;;;;;;;;;;;;;;;sBAmBrE,aAAa,CAAC,CAAC,CAAC,OAAO,oBAAoB,GAAG,CAAC,CAAC,CAAC,eAAe;;;oDAGlC,YAAY,CAAC,CAAC,CAAC;;;;;uDAKZ,CAAC,CAAC,CAAC;2DACC;;;;;;UAMjD,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;aACpB,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;iBACtB,IAAI,CAAC,SAAS,CAAC,WAAW,IAAI,GAAG,OAAO,MAAM,CAAC;8DACF,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC;;;;;;EAMzF,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC;;;;;;kHAMwF,aAAa,GAAG,WAAW,GAAG,gBAAgB,GAAG,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sDA+BxH,CAAC;AACvD,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAsB,EAAE,OAAe;IACnE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,wDAAwD,CAAC;IAExF,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QAClC,MAAM,EAAE,OAAO,EAAE,GAAG,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtD,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACvB,MAAM,EAAE,OAAO,EAAE,GAAG,IAAA,uCAAiB,EAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACxD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,IAAA,wCAAkB,EAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEhF,OAAO;aACE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;iBACnB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC;EAC/C,WAAW;;;;;;QAML,kBAAkB,CAAC,IAAI,CAAC;2CACW,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;4CACxB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;;;;;;;qCAO7B,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;;;;;;MAMtD,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,OAAO,+BAA+B,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;AAChG,CAAC;AAED,SAAS,kBAAkB,CAAC,IAAmB;IAC7C,MAAM,KAAK,GAAI,IAAI,CAAC,WAAuC,CAAC,UAAiE,CAAC;IAC9H,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IAEtB,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE;QACnD,MAAM,UAAU,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;QACnC,MAAM,KAAK,GAAG,IAAA,kCAAY,EAAC,QAAQ,CAAC,CAAC;QACrC,6DAA6D;QAC7D,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;QAElC,oCAAoC;QACpC,IAAI,QAAQ,GAAG,UAAU,EAAE,IAAqC,CAAC;QACjE,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5B,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC;QACvE,CAAC;QAED,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC1B,OAAO,eAAe,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;qBAC5B,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,0BAA0B,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;+DAC7B,KAAK;QAC5D,CAAC;QACL,CAAC;QAED,OAAO,eAAe,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,yBAAyB,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,eAAe,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC;IACvI,CAAC,CAAC,CAAC;IAEH,OAAO,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AACnC,CAAC;AAED,SAAS,qBAAqB,CAAC,WAAoC;IACjE,MAAM,KAAK,GAAI,WAAuC,CAAC,UAAiE,CAAC;IACzH,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IAEtB,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE;QACnD,MAAM,UAAU,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;QACnC,MAAM,KAAK,GAAG,IAAA,kCAAY,EAAC,QAAQ,CAAC,CAAC;QACrC,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;QAElC,IAAI,QAAQ,GAAG,UAAU,EAAE,IAAqC,CAAC;QACjE,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5B,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC;QACvE,CAAC;QAED,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC1B,OAAO,eAAe,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;sBAC3B,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,0BAA0B,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;+DAC9B,KAAK;QAC5D,CAAC;QACL,CAAC;QAED,OAAO,eAAe,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,0BAA0B,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,eAAe,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC;IACxI,CAAC,CAAC,CAAC;IAEH,OAAO,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AACnC,CAAC;AAED,SAAS,wBAAwB,CAAC,OAAwB;IACxD,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAsCH,CAAC;AACP,CAAC;AAED,SAAS,wBAAwB,CAAC,SAAsC;IACtE,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,oCAAoC,CAAC;IAEtF,MAAM,WAAW,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACzC,MAAM,OAAO,GAAG,IAAA,kCAAY,EAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC3D,iDAAiD;QACjD,MAAM,UAAU,GAAG,qBAAqB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3D,MAAM,WAAW,GAAG,UAAU;aAC3B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,wBAAwB,IAAA,kCAAY,EAAC,CAAC,CAAC,mCAAmC,CAAC,IAAI,CAAC;aAC3F,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,MAAM,YAAY,GAAG,UAAU;aAC5B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACT,MAAM,KAAK,GAAG,YAAY,CAAC,IAAA,kCAAY,EAAC,CAAC,CAAC,CAAC,CAAC;YAC5C,OAAO,uBAAuB,CAAC,kCAAkC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC;QAC/F,CAAC,CAAC;aACD,IAAI,CAAC,UAAU,CAAC,CAAC;QAEpB,OAAO;aACE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;iBACnB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,IAAI,gCAAgC,IAAI,CAAC,WAAW,EAAE,CAAC;EACrG,WAAW;;;;;kBAKK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC;QAC1C,YAAY;;;;;;;;MAQd,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;EAyBP,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;AAC7B,CAAC;AAED,SAAS,sBAAsB,CAAC,OAA0B;IACxD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;QACzC,MAAM,OAAO,GAAG,IAAA,kCAAY,EAAC,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC7D,MAAM,UAAU,GAAG,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC;aACxC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACT,MAAM,IAAI,GAAG,KAAK,IAAA,kCAAY,EAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC;YACjD,MAAM,IAAI,GAAG,CAAC,CAAC,WAAW,IAAI,EAAE,CAAC;YACjC,OAAO,CAAC,CAAC,QAAQ;gBACf,CAAC,CAAC,sBAAsB,IAAI,OAAO,SAAS,CAAC,IAAI,CAAC,IAAI;gBACtD,CAAC,CAAC,cAAc,IAAI,OAAO,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;QACnD,CAAC,CAAC;aACD,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,OAAO;aACE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;iBACnB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC;EACvD,UAAU;;;;;;QAMJ,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACnC,MAAM,KAAK,GAAG,YAAY,CAAC,IAAA,kCAAY,EAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YACjD,OAAO,eAAe,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,yBAAyB,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC;QACrI,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC;4CACmB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC;;;;;;;MAOjE,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;EAyBP,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;AAC7B,CAAC;AAED,SAAS,sBAAsB;IAC7B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MA4EH,CAAC;AACP,CAAC;AAED,SAAS,mBAAmB,CAAC,IAAoB;IAC/C,sDAAsD;IACtD,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACtC,MAAM,UAAU,GAAG,IAAA,kCAAY,EAAC,GAAG,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAE7D,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;YACpB,MAAM,EAAE,OAAO,EAAE,GAAG,IAAA,uCAAiB,EAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACvD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,IAAA,wCAAkB,EAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChF,MAAM,UAAU,GAAG,qBAAqB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YAE1D,OAAO;aACA,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;iBACtB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,WAAW,IAAI,WAAW,GAAG,CAAC,IAAI,MAAM,CAAC;EAC3E,WAAW;;;;;;;QAOL,UAAU;6CAC2B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;MAe/D,CAAC;QACH,CAAC;QAED,uDAAuD;QACvD,OAAO;aACE,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;iBACtB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,WAAW,IAAI,WAAW,GAAG,CAAC,IAAI,MAAM,CAAC;;;;;;;;;;;6CAWhC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;MAe/D,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,0DAA0D;IAC1D,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;MA4Bf,CAAC;IAEL,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+BP,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC;;EAE3B,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;MA2B3B;;;;;;;;;;;;;;;;;;;MAmBA,CAAC;AACP,CAAC;AAED,SAAS,wBAAwB;IAC/B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MA4EH,CAAC;AACP,CAAC;AAED,SAAS,yBAAyB;IAChC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MA2EH,CAAC;AACP,CAAC;AAED,SAAS,oBAAoB,CAAC,OAAe,EAAE,WAAyB;IACtE,MAAM,SAAS,GAAG,WAAW,EAAE,SAAS,IAAI,EAAE,CAAC;IAC/C,MAAM,QAAQ,GAAG,WAAW,EAAE,QAAQ,IAAI,OAAO,CAAC;IAClD,MAAM,YAAY,GAAG,WAAW,EAAE,YAAY,IAAI,EAAE,CAAC;IACrD,MAAM,SAAS,GAAG,WAAW,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC;IACvD,MAAM,OAAO,GAAG,WAAW,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC;IACrD,MAAM,OAAO,GAAG,WAAW,EAAE,OAAO,IAAI,MAAM,CAAC;IAE/C,OAAO;;;oDAG2C,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;;8CAEvD,YAAY,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;;;wEAG7B,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;;;;;;;;;;oBAU7E,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;+BACb,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC;qBACtC,SAAS;mBACX,OAAO;mBACP,OAAO;;;;;;;;;;;;MAYpB,CAAC;AACP,CAAC;AAED,SAAS,qBAAqB,CAAC,QAAgB;IAC7C,OAAO;;;;;;;;;;;;;;;;;;MAkBH,CAAC;AACP,CAAC;AAED,SAAS,uBAAuB;IAC9B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAkDH,CAAC;AACP,CAAC;AAED,SAAS,oBAAoB,CAAC,oBAA4B,EAAE,aAAuB;IACjF,qGAAqG;IACrG,0EAA0E;IAC1E,MAAM,WAAW,GAAG,aAAa;QAC/B,CAAC,CAAC,WAAW,IAAI,CAAC,SAAS,CAAC,KAAK,GAAG,oBAAoB,CAAC,GAAG;QAC5D,CAAC,CAAC,iCAAiC,IAAI,CAAC,SAAS,CAAC,oBAAoB,CAAC,IAAI,CAAC;IAE9E,OAAO;;;;;gBAKO,WAAW;;;;;;;;;;;;;MAarB,CAAC;AACP,CAAC;AAED,SAAS,qBAAqB,CAC5B,OAAe,EACf,UAAgD;IAEhD,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,IAAI,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;QAC5B,KAAK,MAAM,GAAG,IAAI,UAAU,CAAC,IAAI,EAAE,CAAC;YAClC,MAAM,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,qCAAqC,GAAG,KAAK,CAAC,CAAC;QAC7F,CAAC;IACH,CAAC;IACD,IAAI,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC;QAC3B,KAAK,MAAM,GAAG,IAAI,UAAU,CAAC,GAAG,EAAE,CAAC;YACjC,MAAM,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,kCAAkC,GAAG,KAAK,CAAC,CAAC;QAC1F,CAAC;IACH,CAAC;IACD,IAAI,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC;QAC3B,KAAK,MAAM,GAAG,IAAI,UAAU,CAAC,GAAG,EAAE,CAAC;YACjC,MAAM,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,iCAAiC,GAAG,KAAK,CAAC,CAAC;QACzF,CAAC;IACH,CAAC;IAED,OAAO;;;;;;;;;;;;;;;;;;EAkBP,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;+DA4B2C,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;;;;;;;;;;;;;;;;;MAiBhF,CAAC;AACP,CAAC;AAED,SAAS,sBAAsB,CAC7B,OAAe,EACf,UAAgD,EAChD,aAAuB;IAEvB,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,IAAI,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;QAC5B,KAAK,MAAM,GAAG,IAAI,UAAU,CAAC,IAAI,EAAE,CAAC;YAClC,UAAU,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,0CAA0C,GAAG,wBAAwB,GAAG,KAAK,CAAC,CAAC;QACjI,CAAC;IACH,CAAC;IACD,IAAI,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC;QAC3B,KAAK,MAAM,GAAG,IAAI,UAAU,CAAC,GAAG,EAAE,CAAC;YACjC,UAAU,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,wCAAwC,GAAG,qBAAqB,GAAG,KAAK,CAAC,CAAC;QAC5H,CAAC;IACH,CAAC;IAED,OAAO;;;;;;;;;;;qDAW4C,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;;;8BAG9C,OAAO;;;;;uDAKkB,aAAa,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,EAAE;;;;;;;;;EASlG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC;;;;;;;;;;;;;2CAamB,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,UAAU,CAAC,CAAC,CAAC,GAAG,OAAO,gBAAgB,CAAC;;;;;;;;;kDAS1E,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;;;;;;;;sCAQnC,OAAO;;;;;;;;;;;;;uDAaU,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;;;;;;;;;;;;;;4CAclC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;;;;;+BAKpC,OAAO;MAChC,CAAC;AACP,CAAC;AAED,SAAS,sBAAsB,CAAC,OAAe,EAAE,oBAA4B,EAAE,aAAuB;IACpG,OAAO;;;;;;;;;;;;;;;;+CAgBsC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;;;;;;yCAM7B,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;;;;;;;;;;;;;yCAavB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;;;;EAI9D,aAAa,CAAC,CAAC,CAAC;;;;;;QAMV,CAAC,CAAC,CAAC;;sDAE2C,IAAI,CAAC,SAAS,CAAC,oBAAoB,CAAC;;;;;;QAMlF,sFAAsF;;;;;;;;;;;QAWtF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wDA8BgD,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;wDAoBvB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;wDAoBvB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;;;;;;;MAOzE,CAAC;AACP,CAAC;AAED,SAAS,cAAc;IACrB,OAAO;;;;;;;IAOL,CAAC;AACL,CAAC;AAED;;GAEG;AACH,SAAgB,qBAAqB,CAAC,WAAmB;IACvD,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IAClD,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IACxB,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,YAAY,CAAC,GAAW;IAC/B,OAAO,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AAC7D,CAAC;AAED,SAAS,SAAS,CAAC,CAAS;IAC1B,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACvD,CAAC","sourcesContent":["/**\n * Generates the CLI entry point TypeScript/JavaScript source code.\n * This creates a commander.js-based CLI where each MCP tool is a subcommand.\n */\n\nimport { CliConfig, OAuthConfig } from '../config';\nimport { ExtractedSchema, ExtractedTool, ExtractedPrompt, ExtractedResourceTemplate, ExtractedCapabilities, ExtractedJob, SYSTEM_TOOL_NAMES } from './schema-extractor';\nimport { schemaToCommander, generateOptionCode, camelToKebab } from './schema-to-commander';\n\nexport const RESERVED_COMMANDS = new Set([\n 'resource', 'template', 'prompt', 'subscribe',\n 'login', 'logout', 'connect', 'serve', 'daemon',\n 'doctor', 'install', 'uninstall', 'sessions', 'help', 'version',\n 'skills', 'job', 'workflow',\n]);\n\nexport interface CliEntryOptions {\n appName: string;\n appVersion: string;\n description: string;\n serverBundleFilename: string;\n outputDefault: 'text' | 'json';\n authRequired: boolean;\n excludeTools: string[];\n nativeDeps: NonNullable<CliConfig['nativeDeps']>;\n schema: ExtractedSchema;\n oauthConfig?: OAuthConfig;\n /** When true, generate static requires that esbuild can resolve (for SEA builds). */\n selfContained?: boolean;\n}\n\n/**\n * Resolve tool command name, appending '-tool' suffix if it conflicts with a built-in command.\n * Returns { cmdName, wasRenamed } so the caller can log a warning at build time.\n */\nexport function resolveToolCommandName(toolName: string): { cmdName: string; wasRenamed: boolean } {\n const cmdName = camelToKebab(toolName).replace(/_/g, '-');\n if (RESERVED_COMMANDS.has(cmdName)) {\n return { cmdName: `${cmdName}-tool`, wasRenamed: true };\n }\n return { cmdName, wasRenamed: false };\n}\n\n/**\n * Generate the CLI entry source code (CJS module).\n */\nexport function generateCliEntry(options: CliEntryOptions): string {\n const {\n appName,\n appVersion,\n description,\n serverBundleFilename,\n outputDefault,\n schema,\n excludeTools,\n oauthConfig,\n authRequired,\n } = options;\n\n const capabilities = schema.capabilities;\n\n const filteredTools = schema.tools.filter(\n (t) => !excludeTools.includes(t.name) && !SYSTEM_TOOL_NAMES.has(t.name),\n );\n\n const selfContained = !!options.selfContained;\n\n const sections: string[] = [\n generateHeader(appName, appVersion, description, serverBundleFilename, outputDefault, authRequired, capabilities, oauthConfig, selfContained),\n generateToolCommands(filteredTools, appName),\n generateResourceCommands(schema),\n generateTemplateCommands(schema.resourceTemplates),\n generatePromptCommands(schema.prompts),\n capabilities.skills ? generateSkillsCommands() : '',\n capabilities.jobs ? generateJobCommands(schema.jobs) : '',\n capabilities.workflows ? generateWorkflowCommands() : '',\n generateSubscribeCommands(),\n ...(authRequired ? [\n generateLoginCommand(appName, oauthConfig),\n generateLogoutCommand(appName),\n generateSessionCommands(),\n ] : []),\n generateServeCommand(serverBundleFilename, selfContained),\n generateDoctorCommand(appName, options.nativeDeps),\n generateInstallCommand(appName, options.nativeDeps, selfContained),\n generateDaemonCommands(appName, serverBundleFilename, selfContained),\n generateFooter(),\n ];\n\n return sections.filter(Boolean).join('\\n\\n');\n}\n\nfunction generateHeader(\n appName: string,\n appVersion: string,\n description: string,\n serverBundleFilename: string,\n outputDefault: string,\n authRequired: boolean,\n capabilities: ExtractedCapabilities,\n oauthConfig?: OAuthConfig,\n selfContained?: boolean,\n): string {\n const hasOAuth = !!oauthConfig;\n\n // Build the group routing map dynamically\n const skillsRouting = capabilities.skills ? `\\n else if (name === 'skills') groups['Skills'].push(sub);` : '';\n const jobsRouting = capabilities.jobs ? `\\n else if (name === 'job') groups['Jobs'].push(sub);` : '';\n const workflowsRouting = capabilities.workflows ? `\\n else if (name === 'workflow') groups['Workflows'].push(sub);` : '';\n const authRouting = authRequired ? `\\n else if (['login', 'logout', 'sessions', 'connect'].indexOf(name) !== -1) groups['Auth'].push(sub);` : '';\n\n // Build the groups object dynamically\n const groupEntries: string[] = [\n ` 'Tools': []`,\n ` 'Resources & Prompts': []`,\n ];\n if (capabilities.skills) groupEntries.push(` 'Skills': []`);\n if (capabilities.jobs) groupEntries.push(` 'Jobs': []`);\n if (capabilities.workflows) groupEntries.push(` 'Workflows': []`);\n if (authRequired) groupEntries.push(` 'Auth': []`);\n groupEntries.push(` 'Subscriptions': []`);\n groupEntries.push(` 'System': []`);\n\n return `'use strict';\n${selfContained ? `\n// SEA daemon mode: when spawned by 'daemon start', run the server directly\n// using the inlined (bundled) server code — no external requires needed.\nif (process.env.__FRONTMCP_DAEMON_MODE === '1') {\n require('reflect-metadata');\n var _dMod = require(${JSON.stringify('../' + serverBundleFilename)});\n var _dSdk = require('@frontmcp/sdk');\n var _FMI = _dSdk.FrontMcpInstance || _dSdk.default.FrontMcpInstance;\n var _raw = _dMod.default || _dMod;\n var _cfg = (typeof _raw === 'function' && typeof Reflect !== 'undefined' && Reflect.getMetadata)\n ? (Reflect.getMetadata('__frontmcp:config', _raw) || _raw) : _raw;\n var _sp = process.env.FRONTMCP_DAEMON_SOCKET;\n _FMI.runUnixSocket(Object.assign({}, _cfg, { socketPath: _sp }))\n .then(function() { console.log('Daemon listening on ' + _sp); })\n .catch(function(e) { console.error('Daemon failed:', e); process.exit(1); });\n return;\n}\n` : ''}\nvar { Command, Option } = require('commander');\nvar path = require('path');\nvar fs = require('fs');\nvar os = require('os');\nvar fmt = require('./output-formatter');\n${authRequired ? \"var sessions = require('./session-manager');\\nvar creds = require('./credential-store');\" : ''}\n${hasOAuth ? \"var oauthHelper = require('./oauth-helper');\" : ''}\n\nvar APP_NAME = ${JSON.stringify(appName)};\nvar SCRIPT_DIR = __dirname;\nvar FRONTMCP_HOME = process.env.FRONTMCP_HOME || path.join(os.homedir(), '.frontmcp');\n${selfContained\n ? `// Self-contained: server bundle and SDK are inlined by esbuild\nvar SERVER_BUNDLE = '../${serverBundleFilename}';`\n : `var SERVER_BUNDLE = path.join(SCRIPT_DIR, ${JSON.stringify(serverBundleFilename)});`}\n\nvar _client = null;\nasync function getClient() {\n if (_client) return _client;\n\n // Try daemon first — Unix socket HTTP (~5-15ms vs ~420ms in-process)\n var socketPath = path.join(FRONTMCP_HOME, 'sockets', APP_NAME + '.sock');\n if (fs.existsSync(socketPath)) {\n try {\n var daemonClient = require('./daemon-client');\n var dc = daemonClient.createDaemonClient(socketPath);\n await dc.ping();\n _client = dc;\n return _client;\n } catch (_) { /* daemon not available, fall through */ }\n }\n\n // Fallback: in-process connect (with CLI mode for faster init)\n var mod = require(${selfContained ? `'../${serverBundleFilename}'` : 'SERVER_BUNDLE'});\n var configOrClass = mod.default || mod;\n var sdk = require('@frontmcp/sdk');\n var connect = sdk.connect || sdk.direct.connect;${authRequired ? `\n var sessionName = sessions.getActiveSessionName();\n var store = creds.createCredentialStore();\n var credBlob = await store.get(sessionName);\n var connectOpts = credBlob ? { authToken: credBlob.token, mode: 'cli' } : { mode: 'cli' };\n _client = await connect(configOrClass, connectOpts);` : `\n _client = await connect(configOrClass, { mode: 'cli' });`}\n return _client;\n}\n\nvar program = new Command();\nprogram\n .name(${JSON.stringify(appName)})\n .version(${JSON.stringify(appVersion)})\n .description(${JSON.stringify(description || `${appName} CLI`)})\n .option('--output <mode>', 'Output format: text or json', ${JSON.stringify(outputDefault)});\n\nprogram.configureHelp({\n sortSubcommands: false,\n formatHelp: function(cmd, helper) {\n var groups = {\n${groupEntries.join(',\\n')}\n };\n var toolCmdNames = cmd._toolCommandNames || [];\n cmd.commands.forEach(function(sub) {\n var name = sub.name();\n if (toolCmdNames.indexOf(name) !== -1) groups['Tools'].push(sub);\n else if (['resource', 'template', 'prompt'].indexOf(name) !== -1) groups['Resources & Prompts'].push(sub);${skillsRouting}${jobsRouting}${workflowsRouting}${authRouting}\n else if (name === 'subscribe') groups['Subscriptions'].push(sub);\n else groups['System'].push(sub);\n });\n var termWidth = helper.padWidth(cmd, helper);\n var lines = [];\n lines.push('Usage: ' + helper.commandUsage(cmd));\n lines.push('');\n var desc = helper.commandDescription(cmd);\n if (desc) { lines.push(desc); lines.push(''); }\n var globalOpts = helper.formatHelp ? helper.visibleOptions(cmd) : [];\n if (globalOpts.length > 0) {\n lines.push('Options:');\n globalOpts.forEach(function(opt) {\n lines.push(' ' + helper.optionTerm(opt).padEnd(termWidth) + ' ' + helper.optionDescription(opt));\n });\n lines.push('');\n }\n Object.keys(groups).forEach(function(groupName) {\n var cmds = groups[groupName];\n if (cmds.length === 0) return;\n lines.push(groupName + ':');\n cmds.forEach(function(sub) {\n lines.push(' ' + helper.subcommandTerm(sub).padEnd(termWidth) + ' ' + helper.subcommandDescription(sub));\n });\n lines.push('');\n });\n return lines.join('\\\\n');\n }\n});\n\nprogram.action(function() { program.outputHelp(); });`;\n}\n\nfunction generateToolCommands(tools: ExtractedTool[], appName: string): string {\n if (tools.length === 0) return '// No tools extracted\\nprogram._toolCommandNames = [];';\n\n const cmdNames: string[] = [];\n const commands = tools.map((tool) => {\n const { cmdName } = resolveToolCommandName(tool.name);\n cmdNames.push(cmdName);\n const { options } = schemaToCommander(tool.inputSchema);\n const optionLines = options.map((o) => ` ${generateOptionCode(o)}`).join('\\n');\n\n return `program\n .command(${JSON.stringify(cmdName)})\n .description(${JSON.stringify(tool.description)})\n${optionLines}\n .action(async function(opts) {\n try {\n var client = await getClient();\n var args = {};\n var rawOpts = this.opts();\n ${generateArgMapping(tool)}\n var result = await client.callTool(${JSON.stringify(tool.name)}, args);\n var mode = program.opts().output || ${JSON.stringify('text')};\n console.log(fmt.formatToolResult(result, mode));\n } catch (err) {\n var meta = err && err._meta ? err._meta : (err && err.data && err.data._meta ? err.data._meta : null);\n if (meta && meta.authorization_required) {\n console.error('Authorization required' + (meta.app ? ' for ' + meta.app : ''));\n if (meta.auth_url) console.error('Authorize at: ' + meta.auth_url);\n console.error('Or run: ' + ${JSON.stringify(appName)} + ' login');\n } else {\n console.error('Error:', err.message || err);\n }\n process.exitCode = 1;\n }\n });`;\n });\n\n return `program._toolCommandNames = ${JSON.stringify(cmdNames)};\\n\\n${commands.join('\\n\\n')}`;\n}\n\nfunction generateArgMapping(tool: ExtractedTool): string {\n const props = (tool.inputSchema as Record<string, unknown>).properties as Record<string, Record<string, unknown>> | undefined;\n if (!props) return '';\n\n const mappings = Object.keys(props).map((propName) => {\n const propSchema = props[propName];\n const kebab = camelToKebab(propName);\n // Commander converts kebab-case flags to camelCase in opts()\n const camel = kebabToCamel(kebab);\n\n // Resolve type for object detection\n let propType = propSchema?.type as string | string[] | undefined;\n if (Array.isArray(propType)) {\n propType = propType.find((t: string) => t !== 'null') || propType[0];\n }\n\n if (propType === 'object') {\n return `if (rawOpts[${JSON.stringify(camel)}] !== undefined) {\n try { args[${JSON.stringify(propName)}] = JSON.parse(rawOpts[${JSON.stringify(camel)}]); }\n catch (_jsonErr) { console.error('Invalid JSON for --${kebab}'); process.exitCode = 1; return; }\n }`;\n }\n\n return `if (rawOpts[${JSON.stringify(camel)}] !== undefined) args[${JSON.stringify(propName)}] = rawOpts[${JSON.stringify(camel)}];`;\n });\n\n return mappings.join('\\n ');\n}\n\nfunction generateJobArgMapping(inputSchema: Record<string, unknown>): string {\n const props = (inputSchema as Record<string, unknown>).properties as Record<string, Record<string, unknown>> | undefined;\n if (!props) return '';\n\n const mappings = Object.keys(props).map((propName) => {\n const propSchema = props[propName];\n const kebab = camelToKebab(propName);\n const camel = kebabToCamel(kebab);\n\n let propType = propSchema?.type as string | string[] | undefined;\n if (Array.isArray(propType)) {\n propType = propType.find((t: string) => t !== 'null') || propType[0];\n }\n\n if (propType === 'object') {\n return `if (rawOpts[${JSON.stringify(camel)}] !== undefined) {\n try { input[${JSON.stringify(propName)}] = JSON.parse(rawOpts[${JSON.stringify(camel)}]); }\n catch (_jsonErr) { console.error('Invalid JSON for --${kebab}'); process.exitCode = 1; return; }\n }`;\n }\n\n return `if (rawOpts[${JSON.stringify(camel)}] !== undefined) input[${JSON.stringify(propName)}] = rawOpts[${JSON.stringify(camel)}];`;\n });\n\n return mappings.join('\\n ');\n}\n\nfunction generateResourceCommands(_schema: ExtractedSchema): string {\n return `var resourceCmd = program.command('resource').description('Resource operations');\n\nresourceCmd\n .command('list')\n .description('List available resources')\n .action(async function() {\n try {\n var client = await getClient();\n var result = await client.listResources();\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n var resources = result.resources || [];\n if (resources.length === 0) { console.log('No resources available.'); return; }\n resources.forEach(function(r) {\n console.log(' ' + r.uri + (r.description ? ' - ' + r.description : ''));\n });\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\nresourceCmd\n .command('read <uri>')\n .description('Read a resource by URI')\n .action(async function(uri) {\n try {\n var client = await getClient();\n var result = await client.readResource(uri);\n var mode = program.opts().output || 'text';\n console.log(fmt.formatResourceResult(result, mode));\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n}\n\nfunction generateTemplateCommands(templates: ExtractedResourceTemplate[]): string {\n if (!templates || templates.length === 0) return '// No resource templates extracted';\n\n const subcommands = templates.map((tmpl) => {\n const cmdName = camelToKebab(tmpl.name).replace(/_/g, '-');\n // Extract {param} placeholders from URI template\n const paramNames = extractTemplateParams(tmpl.uriTemplate);\n const optionLines = paramNames\n .map((p) => ` .requiredOption('--${camelToKebab(p)} <value>', 'Template parameter: ${p}')`)\n .join('\\n');\n\n const paramMapping = paramNames\n .map((p) => {\n const camel = kebabToCamel(camelToKebab(p));\n return `uri = uri.replace('{${p}}', encodeURIComponent(rawOpts[${JSON.stringify(camel)}]));`;\n })\n .join('\\n ');\n\n return `templateCmd\n .command(${JSON.stringify(cmdName)})\n .description(${JSON.stringify(tmpl.description || `Read resource from template: ${tmpl.uriTemplate}`)})\n${optionLines}\n .action(async function(opts) {\n try {\n var client = await getClient();\n var rawOpts = this.opts();\n var uri = ${JSON.stringify(tmpl.uriTemplate)};\n ${paramMapping}\n var result = await client.readResource(uri);\n var mode = program.opts().output || 'text';\n console.log(fmt.formatResourceResult(result, mode));\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n });\n\n return `var templateCmd = program.command('template').description('Resource template operations');\n\ntemplateCmd\n .command('list')\n .description('List available resource templates')\n .action(async function() {\n try {\n var client = await getClient();\n var result = await client.listResourceTemplates();\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n var templates = result.resourceTemplates || [];\n if (templates.length === 0) { console.log('No resource templates available.'); return; }\n templates.forEach(function(t) {\n console.log(' ' + t.uriTemplate + (t.description ? ' - ' + t.description : ''));\n });\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\n${subcommands.join('\\n\\n')}`;\n}\n\nfunction generatePromptCommands(prompts: ExtractedPrompt[]): string {\n const subcommands = prompts.map((prompt) => {\n const cmdName = camelToKebab(prompt.name).replace(/_/g, '-');\n const argOptions = (prompt.arguments || [])\n .map((a) => {\n const flag = `--${camelToKebab(a.name)} <value>`;\n const desc = a.description || '';\n return a.required\n ? ` .requiredOption('${flag}', '${escapeStr(desc)}')`\n : ` .option('${flag}', '${escapeStr(desc)}')`;\n })\n .join('\\n');\n\n return `promptCmd\n .command(${JSON.stringify(cmdName)})\n .description(${JSON.stringify(prompt.description || '')})\n${argOptions}\n .action(async function(opts) {\n try {\n var client = await getClient();\n var args = {};\n var rawOpts = this.opts();\n ${(prompt.arguments || []).map((a) => {\n const camel = kebabToCamel(camelToKebab(a.name));\n return `if (rawOpts[${JSON.stringify(camel)}] !== undefined) args[${JSON.stringify(a.name)}] = rawOpts[${JSON.stringify(camel)}];`;\n }).join('\\n ')}\n var result = await client.getPrompt(${JSON.stringify(prompt.name)}, args);\n var mode = program.opts().output || 'text';\n console.log(fmt.formatPromptResult(result, mode));\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n });\n\n return `var promptCmd = program.command('prompt').description('Prompt operations');\n\npromptCmd\n .command('list')\n .description('List available prompts')\n .action(async function() {\n try {\n var client = await getClient();\n var result = await client.listPrompts();\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n var prompts = result.prompts || [];\n if (prompts.length === 0) { console.log('No prompts available.'); return; }\n prompts.forEach(function(p) {\n console.log(' ' + p.name + (p.description ? ' - ' + p.description : ''));\n });\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\n${subcommands.join('\\n\\n')}`;\n}\n\nfunction generateSkillsCommands(): string {\n return `var skillsCmd = program.command('skills').description('Skill operations');\n\nskillsCmd\n .command('search [query]')\n .description('Search for skills')\n .action(async function(query) {\n try {\n var client = await getClient();\n var result = await client.searchSkills(query || '');\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n var skills = result.skills || result || [];\n if (Array.isArray(skills) && skills.length === 0) { console.log('No skills found.'); return; }\n if (Array.isArray(skills)) {\n skills.forEach(function(s) {\n console.log(' ' + (s.name || s.id || JSON.stringify(s)));\n });\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\nskillsCmd\n .command('load <ids...>')\n .description('Load skills by ID')\n .action(async function(ids) {\n try {\n var client = await getClient();\n var result = await client.loadSkills(ids);\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log('Loaded ' + ids.length + ' skill(s).');\n if (result && typeof result === 'object') {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\nskillsCmd\n .command('list')\n .description('List available skills')\n .action(async function() {\n try {\n var client = await getClient();\n var result = await client.listSkills();\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n var skills = result.skills || result || [];\n if (Array.isArray(skills) && skills.length === 0) { console.log('No skills available.'); return; }\n if (Array.isArray(skills)) {\n skills.forEach(function(s) {\n console.log(' ' + (s.name || s.id || JSON.stringify(s)));\n });\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n}\n\nfunction generateJobCommands(jobs: ExtractedJob[]): string {\n // Generate typed 'run' subcommands for each known job\n const runSubcommands = jobs.map((job) => {\n const jobCmdName = camelToKebab(job.name).replace(/_/g, '-');\n\n if (job.inputSchema) {\n const { options } = schemaToCommander(job.inputSchema);\n const optionLines = options.map((o) => ` ${generateOptionCode(o)}`).join('\\n');\n const argMapping = generateJobArgMapping(job.inputSchema);\n\n return `jobRunCmd\n .command(${JSON.stringify(jobCmdName)})\n .description(${JSON.stringify(job.description || `Run the ${job.name} job`)})\n${optionLines}\n .option('--background', 'Run in background mode')\n .action(async function(opts) {\n try {\n var client = await getClient();\n var input = {};\n var rawOpts = this.opts();\n ${argMapping}\n var result = await client.executeJob(${JSON.stringify(job.name)}, input, { background: !!rawOpts.background });\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n if (rawOpts.background && result && result.runId) {\n console.log('Job started. Run ID: ' + result.runId);\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n }\n\n // No inputSchema — fall back to generic --input <json>\n return `jobRunCmd\n .command(${JSON.stringify(jobCmdName)})\n .description(${JSON.stringify(job.description || `Run the ${job.name} job`)})\n .option('--input <json>', 'Job input as JSON string')\n .option('--background', 'Run in background mode')\n .action(async function(opts) {\n try {\n var client = await getClient();\n var input = {};\n if (opts.input) {\n try { input = JSON.parse(opts.input); }\n catch (_) { console.error('Invalid JSON for --input'); process.exitCode = 1; return; }\n }\n var result = await client.executeJob(${JSON.stringify(job.name)}, input, { background: !!opts.background });\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n if (opts.background && result && result.runId) {\n console.log('Job started. Run ID: ' + result.runId);\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n });\n\n // Generic fallback 'run' for jobs not known at build time\n const genericRun = `jobRunCmd\n .command('_run <name>')\n .description('Run a job by name (generic)')\n .option('--input <json>', 'Job input as JSON string')\n .option('--background', 'Run in background mode')\n .action(async function(name, opts) {\n try {\n var client = await getClient();\n var input = {};\n if (opts.input) {\n try { input = JSON.parse(opts.input); }\n catch (_) { console.error('Invalid JSON for --input'); process.exitCode = 1; return; }\n }\n var result = await client.executeJob(name, input, { background: !!opts.background });\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n if (opts.background && result && result.runId) {\n console.log('Job started. Run ID: ' + result.runId);\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n\n return `var jobCmd = program.command('job').description('Job operations');\n\njobCmd\n .command('list')\n .description('List available jobs')\n .action(async function() {\n try {\n var client = await getClient();\n var result = await client.listJobs();\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n var jobs = result.jobs || result || [];\n if (Array.isArray(jobs) && jobs.length === 0) { console.log('No jobs available.'); return; }\n if (Array.isArray(jobs)) {\n jobs.forEach(function(j) {\n console.log(' ' + (j.name || j.id || JSON.stringify(j)));\n });\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\nvar jobRunCmd = jobCmd.command('run').description('Run a job');\n\n${runSubcommands.join('\\n\\n')}\n\n${jobs.length > 0 ? genericRun : `jobRunCmd\n .argument('<name>', 'Job name')\n .option('--input <json>', 'Job input as JSON string')\n .option('--background', 'Run in background mode')\n .action(async function(name, opts) {\n try {\n var client = await getClient();\n var input = {};\n if (opts.input) {\n try { input = JSON.parse(opts.input); }\n catch (_) { console.error('Invalid JSON for --input'); process.exitCode = 1; return; }\n }\n var result = await client.executeJob(name, input, { background: !!opts.background });\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n if (opts.background && result && result.runId) {\n console.log('Job started. Run ID: ' + result.runId);\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`}\n\njobCmd\n .command('status <runId>')\n .description('Get the status of a job run')\n .action(async function(runId) {\n try {\n var client = await getClient();\n var result = await client.getJobStatus(runId);\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log('Status: ' + (result.status || JSON.stringify(result)));\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n}\n\nfunction generateWorkflowCommands(): string {\n return `var workflowCmd = program.command('workflow').description('Workflow operations');\n\nworkflowCmd\n .command('list')\n .description('List available workflows')\n .action(async function() {\n try {\n var client = await getClient();\n var result = await client.listWorkflows();\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n var workflows = result.workflows || result || [];\n if (Array.isArray(workflows) && workflows.length === 0) { console.log('No workflows available.'); return; }\n if (Array.isArray(workflows)) {\n workflows.forEach(function(w) {\n console.log(' ' + (w.name || w.id || JSON.stringify(w)));\n });\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\nworkflowCmd\n .command('run <name>')\n .description('Run a workflow by name')\n .option('--input <json>', 'Workflow input as JSON string')\n .option('--background', 'Run in background mode')\n .action(async function(name, opts) {\n try {\n var client = await getClient();\n var input = {};\n if (opts.input) {\n try { input = JSON.parse(opts.input); }\n catch (_) { console.error('Invalid JSON for --input'); process.exitCode = 1; return; }\n }\n var result = await client.executeWorkflow(name, input, { background: !!opts.background });\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n if (opts.background && result && result.runId) {\n console.log('Workflow started. Run ID: ' + result.runId);\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\nworkflowCmd\n .command('status <runId>')\n .description('Get the status of a workflow run')\n .action(async function(runId) {\n try {\n var client = await getClient();\n var result = await client.getWorkflowStatus(runId);\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log('Status: ' + (result.status || JSON.stringify(result)));\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n}\n\nfunction generateSubscribeCommands(): string {\n return `\n// Subscribe commands need push support (onNotification/onResourceUpdated).\n// Daemon HTTP cannot push, so we force in-process when daemon was used.\nasync function getSubscribeClient() {\n var client = await getClient();\n // If connected via daemon, the onNotification/onResourceUpdated are no-ops.\n // Reconnect via in-process for push support.\n if (client._isDaemon) {\n _client = null; // clear cached daemon client\n var mod = require(SERVER_BUNDLE);\n var configOrClass = mod.default || mod;\n var sdk = require('@frontmcp/sdk');\n var connect = sdk.connect || sdk.direct.connect;\n _client = await connect(configOrClass, { mode: 'cli' });\n return _client;\n }\n return client;\n}\n\nvar subscribeCmd = program.command('subscribe').description('Subscribe to updates');\n\nsubscribeCmd\n .command('resource <uri>')\n .description('Stream resource updates (Ctrl+C to stop)')\n .action(async function(uri) {\n try {\n var client = await getSubscribeClient();\n await client.subscribeResource(uri);\n var mode = program.opts().output || 'text';\n console.log('Subscribed to resource: ' + uri);\n console.log('Waiting for updates... (Ctrl+C to stop)\\\\n');\n client.onResourceUpdated(function(uri) {\n console.log(fmt.formatSubscriptionEvent({ type: 'resource_updated', uri: uri, timestamp: new Date().toISOString() }, mode));\n });\n process.on('SIGINT', async function() {\n console.log('\\\\nUnsubscribing...');\n try { await client.unsubscribeResource(uri); } catch (_) { /* ok */ }\n process.exit(0);\n });\n // Keep process alive — setInterval creates an active event loop handle\n // so Node.js won't exit even with InMemoryTransport (no persistent I/O)\n setInterval(function() {}, 2147483647);\n await new Promise(function() {});\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\nsubscribeCmd\n .command('notification <name>')\n .description('Stream notifications (Ctrl+C to stop)')\n .action(async function(name) {\n try {\n var client = await getSubscribeClient();\n var mode = program.opts().output || 'text';\n console.log('Listening for notification: ' + name);\n console.log('Waiting for events... (Ctrl+C to stop)\\\\n');\n client.onNotification(function(notification) {\n if (notification.method === name || name === '*') {\n console.log(fmt.formatSubscriptionEvent({ type: 'notification', method: notification.method, params: notification.params, timestamp: new Date().toISOString() }, mode));\n }\n });\n process.on('SIGINT', function() {\n console.log('\\\\nStopping...');\n process.exit(0);\n });\n // Keep process alive — setInterval creates an active event loop handle\n // so Node.js won't exit even with InMemoryTransport (no persistent I/O)\n setInterval(function() {}, 2147483647);\n await new Promise(function() {});\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n}\n\nfunction generateLoginCommand(appName: string, oauthConfig?: OAuthConfig): string {\n const serverUrl = oauthConfig?.serverUrl || '';\n const clientId = oauthConfig?.clientId || appName;\n const defaultScope = oauthConfig?.defaultScope || '';\n const portStart = oauthConfig?.portRange?.[0] ?? 17830;\n const portEnd = oauthConfig?.portRange?.[1] ?? 17850;\n const timeout = oauthConfig?.timeout ?? 120000;\n\n return `program\n .command('login')\n .description('Authenticate via OAuth')\n .option('--server <url>', 'Server URL for OAuth'${serverUrl ? `, ${JSON.stringify(serverUrl)}` : ''})\n .option('--session <name>', 'Session name', 'default')\n .option('--scope <scopes>', 'OAuth scopes'${defaultScope ? `, ${JSON.stringify(defaultScope)}` : ''})\n .option('--no-browser', 'Print URL instead of opening browser')\n .action(async function(opts) {\n var serverUrl = opts.server || process.env.FRONTMCP_SERVER_URL || ${JSON.stringify(serverUrl)};\n if (!serverUrl) {\n console.error('Server URL required. Use --server <url> or set FRONTMCP_SERVER_URL.');\n process.exitCode = 1;\n return;\n }\n try {\n var oauthHelper = require('./oauth-helper');\n var result = await oauthHelper.startOAuthLogin({\n serverUrl: serverUrl,\n clientId: ${JSON.stringify(clientId)},\n scope: opts.scope || ${JSON.stringify(defaultScope)},\n portStart: ${portStart},\n portEnd: ${portEnd},\n timeout: ${timeout},\n noBrowser: !opts.browser\n });\n var sessionName = opts.session || 'default';\n var store = creds.createCredentialStore();\n await store.set(sessionName, result);\n sessions.getOrCreateSession(sessionName);\n console.log('Logged in successfully. Session: ' + sessionName);\n } catch (err) {\n console.error('Login failed:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n}\n\nfunction generateLogoutCommand(_appName: string): string {\n return `program\n .command('logout')\n .description('Clear stored credentials')\n .option('--session <name>', 'Session to log out')\n .option('--all', 'Log out of all sessions')\n .action(async function(opts) {\n var store = creds.createCredentialStore();\n if (opts.all) {\n var allSessions = await store.list();\n for (var i = 0; i < allSessions.length; i++) {\n await store.delete(allSessions[i]);\n }\n console.log('Logged out of ' + allSessions.length + ' session(s).');\n } else {\n var sessionName = opts.session || sessions.getActiveSessionName();\n await store.delete(sessionName);\n console.log('Logged out of session: ' + sessionName);\n }\n });`;\n}\n\nfunction generateSessionCommands(): string {\n return `var sessionsCmd = program.command('sessions').description('Session management');\n\nsessionsCmd\n .command('list')\n .description('List all sessions')\n .action(function() {\n var list = sessions.listSessions();\n if (list.length === 0) { console.log('No sessions.'); return; }\n list.forEach(function(s) {\n var marker = s.isActive ? ' (active)' : '';\n console.log(' ' + s.name + marker + ' - last used: ' + s.lastUsedAt);\n });\n });\n\nsessionsCmd\n .command('switch <name>')\n .description('Switch to a named session')\n .action(function(name) {\n sessions.switchSession(name);\n console.log('Switched to session: ' + name);\n });\n\nsessionsCmd\n .command('delete <name>')\n .description('Delete a session')\n .action(async function(name) {\n var store = creds.createCredentialStore();\n await store.delete(name);\n sessions.deleteSession(name);\n console.log('Deleted session: ' + name);\n });\n\nprogram\n .command('connect')\n .description('Authenticate and store credentials')\n .option('--session <name>', 'Session name', 'default')\n .option('--token <token>', 'Auth token (or pass via stdin)')\n .action(async function(opts) {\n var sessionName = opts.session || 'default';\n var token = opts.token;\n if (!token) {\n console.log('Usage: ' + program.name() + ' connect --token <your-token>');\n console.log(' Or pipe token: echo \"tok_xxx\" | ' + program.name() + ' connect');\n process.exitCode = 1;\n return;\n }\n var store = creds.createCredentialStore();\n await store.set(sessionName, { token: token });\n sessions.getOrCreateSession(sessionName);\n console.log('Credentials stored for session: ' + sessionName);\n });`;\n}\n\nfunction generateServeCommand(serverBundleFilename: string, selfContained?: boolean): string {\n // In self-contained/SEA mode, use a static relative require that esbuild can resolve at bundle time.\n // In normal mode, use dynamic path.join for runtime resolution from disk.\n const requireExpr = selfContained\n ? `require(${JSON.stringify('../' + serverBundleFilename)})`\n : `require(path.join(SCRIPT_DIR, ${JSON.stringify(serverBundleFilename)}))`;\n\n return `program\n .command('serve')\n .description('Start the HTTP/SSE server')\n .option('-p, --port <port>', 'Port number', function(v) { return parseInt(v, 10); })\n .action(async function(opts) {\n var mod = ${requireExpr};\n if (opts.port) process.env.PORT = String(opts.port);\n // If the bundle exports a start() function (@FrontMcp-decorated class auto-bootstraps), use it\n if (typeof mod.start === 'function') { await mod.start(); return; }\n if (typeof mod.default?.start === 'function') { await mod.default.start(); return; }\n // Otherwise, bootstrap the plain config object via FrontMcpInstance\n var raw = mod.default || mod;\n var sdk = require('@frontmcp/sdk');\n var FrontMcpInstance = sdk.FrontMcpInstance || sdk.default.FrontMcpInstance;\n var config = (typeof raw === 'function' && typeof Reflect !== 'undefined' && Reflect.getMetadata)\n ? (Reflect.getMetadata('__frontmcp:config', raw) || raw) : raw;\n if (opts.port) config = Object.assign({}, config, { http: Object.assign({}, config.http || {}, { port: opts.port }) });\n await FrontMcpInstance.bootstrap(config);\n });`;\n}\n\nfunction generateDoctorCommand(\n appName: string,\n nativeDeps: NonNullable<CliConfig['nativeDeps']>,\n): string {\n const checks: string[] = [];\n\n if (nativeDeps.brew?.length) {\n for (const pkg of nativeDeps.brew) {\n checks.push(` { name: ${JSON.stringify(pkg)}, type: 'brew', check: 'brew list ${pkg}' }`);\n }\n }\n if (nativeDeps.apt?.length) {\n for (const pkg of nativeDeps.apt) {\n checks.push(` { name: ${JSON.stringify(pkg)}, type: 'apt', check: 'dpkg -l ${pkg}' }`);\n }\n }\n if (nativeDeps.npm?.length) {\n for (const pkg of nativeDeps.npm) {\n checks.push(` { name: ${JSON.stringify(pkg)}, type: 'npm', check: 'npm ls ${pkg}' }`);\n }\n }\n\n return `program\n .command('doctor')\n .description('Check system dependencies and configuration')\n .option('--fix', 'Attempt to install missing dependencies')\n .action(async function(opts) {\n var exec = require('child_process').execSync;\n var ok = true;\n\n // Check Node.js version\n var nodeMajor = parseInt(process.versions.node.split('.')[0], 10);\n if (nodeMajor >= 22) {\n console.log(' [ok] Node.js v' + process.versions.node);\n } else {\n console.log(' [!!] Node.js v' + process.versions.node + ' (>=22 required)');\n ok = false;\n }\n\n var deps = [\n${checks.join(',\\n')}\n ];\n\n for (var i = 0; i < deps.length; i++) {\n var dep = deps[i];\n try {\n exec(dep.check, { stdio: 'ignore' });\n console.log(' [ok] ' + dep.name + ' (' + dep.type + ')');\n } catch (_) {\n console.log(' [!!] ' + dep.name + ' (' + dep.type + ') - not found');\n ok = false;\n if (opts.fix) {\n try {\n var installCmd = dep.type === 'brew' ? 'brew install ' + dep.name\n : dep.type === 'apt' ? 'sudo apt-get install -y ' + dep.name\n : 'npm install ' + dep.name;\n console.log(' Installing: ' + installCmd);\n exec(installCmd, { stdio: 'inherit' });\n console.log(' [ok] Installed ' + dep.name);\n } catch (e) {\n console.log(' [!!] Failed to install ' + dep.name);\n }\n }\n }\n }\n\n // Check FRONTMCP_HOME directory\n var fs = require('fs');\n var appDir = require('path').join(FRONTMCP_HOME, 'apps', ${JSON.stringify(appName)});\n if (fs.existsSync(appDir)) {\n console.log(' [ok] App directory: ' + appDir);\n } else {\n console.log(' [!!] App directory not found: ' + appDir);\n ok = false;\n if (opts.fix) {\n fs.mkdirSync(appDir, { recursive: true });\n console.log(' [fixed] Created ' + appDir);\n }\n }\n\n if (ok) console.log('\\\\nAll checks passed.');\n else {\n console.log('\\\\nSome checks failed.' + (opts.fix ? '' : ' Run with --fix to attempt repairs.'));\n process.exitCode = 1;\n }\n });`;\n}\n\nfunction generateInstallCommand(\n appName: string,\n nativeDeps: NonNullable<CliConfig['nativeDeps']>,\n selfContained?: boolean,\n): string {\n const depEntries: string[] = [];\n if (nativeDeps.brew?.length) {\n for (const pkg of nativeDeps.brew) {\n depEntries.push(` { name: ${JSON.stringify(pkg)}, type: 'brew', install: 'brew install ${pkg}', check: 'brew list ${pkg}' }`);\n }\n }\n if (nativeDeps.npm?.length) {\n for (const pkg of nativeDeps.npm) {\n depEntries.push(` { name: ${JSON.stringify(pkg)}, type: 'npm', install: 'npm install ${pkg}', check: 'npm ls ${pkg}' }`);\n }\n }\n\n return `program\n .command('install')\n .description('Install to ~/.frontmcp/ and set up dependencies')\n .option('--prefix <path>', 'Installation prefix directory')\n .option('--bin-dir <path>', 'Directory for symlink (default: ~/.local/bin or /usr/local/bin)')\n .action(async function(opts) {\n var fs = require('fs');\n var pathMod = require('path');\n var os = require('os');\n var exec = require('child_process').execSync;\n var installBase = opts.prefix || FRONTMCP_HOME;\n var appDir = pathMod.join(installBase, 'apps', ${JSON.stringify(appName)});\n var dirs = ['', '/data', '/sessions', '/credentials'].map(function(s) { return appDir + s; });\n\n console.log('Installing ${appName}...');\n dirs.forEach(function(d) { fs.mkdirSync(d, { recursive: true }); });\n\n // Copy bundle files\n var files = fs.readdirSync(SCRIPT_DIR).filter(function(f) {\n return f.endsWith('.js') || f.endsWith('.json')${selfContained ? \" || f.endsWith('-bin')\" : ''};\n });\n files.forEach(function(f) {\n fs.copyFileSync(pathMod.join(SCRIPT_DIR, f), pathMod.join(appDir, f));\n });\n console.log(' Copied ' + files.length + ' files to ' + appDir);\n\n // Install native deps\n var deps = [\n${depEntries.join(',\\n')}\n ];\n for (var i = 0; i < deps.length; i++) {\n var dep = deps[i];\n try { exec(dep.check, { stdio: 'ignore' }); }\n catch (_) {\n console.log(' [' + (i + 1) + '/' + deps.length + '] Installing ' + dep.name + ' via ' + dep.type + '...');\n try { exec(dep.install, { stdio: 'inherit' }); }\n catch (e) { console.log(' Warning: Failed to install ' + dep.name); }\n }\n }\n\n // Set execute permission on the entry point\n var entryFile = pathMod.join(appDir, ${JSON.stringify(selfContained ? `${appName}-cli-bin` : `${appName}-cli.bundle.js`)});\n try { fs.chmodSync(entryFile, 0o755); } catch (_) { /* ok */ }\n\n // Create symlink\n var binDirs = opts.binDir ? [opts.binDir] : ['/usr/local/bin', pathMod.join(os.homedir(), '.local', 'bin')];\n var linked = false;\n for (var j = 0; j < binDirs.length && !linked; j++) {\n try {\n fs.mkdirSync(binDirs[j], { recursive: true });\n var linkPath = pathMod.join(binDirs[j], ${JSON.stringify(appName)});\n try { fs.unlinkSync(linkPath); } catch (_) { /* ok */ }\n fs.symlinkSync(entryFile, linkPath);\n console.log(' Symlinked: ' + linkPath);\n linked = true;\n } catch (_) { /* try next */ }\n }\n\n console.log('\\\\nInstalled. Run: ${appName} --help');\n });\n\nprogram\n .command('uninstall')\n .description('Remove from ~/.frontmcp/ and clean up')\n .option('--prefix <path>', 'Installation prefix directory')\n .option('--bin-dir <path>', 'Directory where symlink was created')\n .action(async function(opts) {\n var fs = require('fs');\n var pathMod = require('path');\n var os = require('os');\n var uninstallBase = opts.prefix || FRONTMCP_HOME;\n var appDir = pathMod.join(uninstallBase, 'apps', ${JSON.stringify(appName)});\n\n // Remove credentials (if auth is enabled)\n if (typeof creds !== 'undefined') {\n var store = creds.createCredentialStore();\n var credSessions = await store.list();\n for (var i = 0; i < credSessions.length; i++) {\n await store.delete(credSessions[i]);\n }\n }\n\n // Remove symlink\n var binDirs = opts.binDir ? [opts.binDir] : ['/usr/local/bin', pathMod.join(os.homedir(), '.local', 'bin')];\n binDirs.forEach(function(d) {\n try { fs.unlinkSync(pathMod.join(d, ${JSON.stringify(appName)})); } catch (_) { /* ok */ }\n });\n\n // Remove app directory\n fs.rmSync(appDir, { recursive: true, force: true });\n console.log('Uninstalled ${appName}.');\n });`;\n}\n\nfunction generateDaemonCommands(appName: string, serverBundleFilename: string, selfContained?: boolean): string {\n return `var daemonCmd = program.command('daemon').description('Daemon management');\n\ndaemonCmd\n .command('start')\n .description('Start as a background daemon (Unix socket)')\n .option('--idle-timeout <ms>', 'Auto-stop after idle period (ms, 0 to disable)', function(v) { return parseInt(v, 10); }, 300000)\n .action(async function(opts) {\n var { spawn } = require('child_process');\n var pathMod = require('path');\n var pidDir = pathMod.join(FRONTMCP_HOME, 'pids');\n var logDir = pathMod.join(FRONTMCP_HOME, 'logs');\n var socketDir = pathMod.join(FRONTMCP_HOME, 'sockets');\n fs.mkdirSync(pidDir, { recursive: true });\n fs.mkdirSync(logDir, { recursive: true });\n fs.mkdirSync(socketDir, { recursive: true });\n\n var socketPath = pathMod.join(socketDir, ${JSON.stringify(appName)} + '.sock');\n\n // Clean up stale socket file\n try { fs.unlinkSync(socketPath); } catch (_) { /* ok */ }\n\n // Check if already running\n var pidPath = pathMod.join(pidDir, ${JSON.stringify(appName)} + '.pid');\n try {\n var existing = JSON.parse(fs.readFileSync(pidPath, 'utf8'));\n process.kill(existing.pid, 0);\n console.log('Daemon already running (PID: ' + existing.pid + ').');\n return;\n } catch (_) { /* not running, proceed */ }\n\n var env = Object.assign({}, process.env, {\n FRONTMCP_DAEMON_SOCKET: socketPath,\n FRONTMCP_DAEMON_IDLE_TIMEOUT: String(opts.idleTimeout)\n });\n\n var logPath = pathMod.join(logDir, ${JSON.stringify(appName)} + '.log');\n var out = fs.openSync(logPath, 'a');\n var err = fs.openSync(logPath, 'a');\n\n${selfContained ? ` // SEA mode: spawn the binary itself in daemon mode — all code is inlined\n env.__FRONTMCP_DAEMON_MODE = '1';\n var child = spawn(process.execPath, [], {\n detached: true,\n stdio: ['ignore', out, err],\n env: env\n });` : ` // Start the daemon using runUnixSocket via a small wrapper script\n // Always use absolute path for the server bundle (SCRIPT_DIR resolves to __dirname at runtime)\n var serverBundlePath = pathMod.join(SCRIPT_DIR, ${JSON.stringify(serverBundleFilename)});\n var daemonScript = 'require(\"reflect-metadata\");' +\n 'var mod = require(' + JSON.stringify(serverBundlePath) + ');' +\n 'var sdk = require(\"@frontmcp/sdk\");' +\n 'var FrontMcpInstance = sdk.FrontMcpInstance || sdk.default.FrontMcpInstance;' +\n 'var raw = mod.default || mod;' +\n ${'// If the export is a @FrontMcp-decorated class, extract config via Reflect metadata'}\n 'var config = (typeof raw === \"function\" && typeof Reflect !== \"undefined\" && Reflect.getMetadata) ' +\n ' ? (Reflect.getMetadata(\"__frontmcp:config\", raw) || raw) : raw;' +\n 'FrontMcpInstance.runUnixSocket(Object.assign({}, config, { socketPath: ' + JSON.stringify(socketPath) + ' }))' +\n '.then(function() { console.log(\"Daemon listening on \" + ' + JSON.stringify(socketPath) + '); })' +\n '.catch(function(e) { console.error(\"Daemon failed:\", e); process.exit(1); });';\n\n var child = spawn('node', ['-e', daemonScript], {\n detached: true,\n stdio: ['ignore', out, err],\n env: env\n });`}\n\n fs.writeFileSync(pidPath, JSON.stringify({\n pid: child.pid,\n socketPath: socketPath,\n startedAt: new Date().toISOString()\n }));\n child.unref();\n\n // Wait for socket file to appear (max 5s)\n var waited = 0;\n while (!fs.existsSync(socketPath) && waited < 5000) {\n await new Promise(function(r) { setTimeout(r, 100); });\n waited += 100;\n }\n\n if (fs.existsSync(socketPath)) {\n console.log('Daemon started (PID: ' + child.pid + '). Socket: ' + socketPath);\n console.log('Logs: ' + logPath);\n } else {\n console.log('Daemon started (PID: ' + child.pid + ') but socket not yet available.');\n console.log('Check logs: ' + logPath);\n }\n });\n\ndaemonCmd\n .command('stop')\n .description('Stop the daemon')\n .action(function() {\n var pathMod = require('path');\n var pidPath = pathMod.join(FRONTMCP_HOME, 'pids', ${JSON.stringify(appName)} + '.pid');\n try {\n var data = JSON.parse(fs.readFileSync(pidPath, 'utf8'));\n process.kill(data.pid, 'SIGTERM');\n fs.unlinkSync(pidPath);\n // Clean up socket file\n if (data.socketPath) {\n try { fs.unlinkSync(data.socketPath); } catch (_) { /* ok */ }\n }\n console.log('Daemon stopped (PID: ' + data.pid + ').');\n } catch (e) {\n console.log('No running daemon found.');\n }\n });\n\ndaemonCmd\n .command('status')\n .description('Check daemon status')\n .action(function() {\n var pathMod = require('path');\n var pidPath = pathMod.join(FRONTMCP_HOME, 'pids', ${JSON.stringify(appName)} + '.pid');\n try {\n var data = JSON.parse(fs.readFileSync(pidPath, 'utf8'));\n try {\n process.kill(data.pid, 0);\n var socketStatus = data.socketPath && fs.existsSync(data.socketPath) ? ', socket: active' : '';\n console.log('Running (PID: ' + data.pid + ', started: ' + data.startedAt + socketStatus + ')');\n } catch (_) {\n console.log('Not running (stale PID file).');\n fs.unlinkSync(pidPath);\n }\n } catch (_) { console.log('Not running.'); }\n });\n\ndaemonCmd\n .command('logs')\n .description('Tail daemon logs')\n .option('-n, --lines <n>', 'Number of lines', function(v) { return parseInt(v, 10); }, 50)\n .action(function(opts) {\n var pathMod = require('path');\n var logPath = pathMod.join(FRONTMCP_HOME, 'logs', ${JSON.stringify(appName)} + '.log');\n try {\n var content = fs.readFileSync(logPath, 'utf8');\n var lines = content.split('\\\\n');\n var start = Math.max(0, lines.length - opts.lines);\n console.log(lines.slice(start).join('\\\\n'));\n } catch (_) { console.log('No logs found.'); }\n });`;\n}\n\nfunction generateFooter(): string {\n return `program.on('command:*', function(args) {\n console.error('Unknown command: ' + args[0]);\n process.exitCode = 1;\n});\nprogram.parseAsync(process.argv).catch(function(err) {\n console.error('Fatal:', err.message || err);\n process.exit(1);\n});`;\n}\n\n/**\n * Extract {param} placeholders from a URI template string.\n */\nexport function extractTemplateParams(uriTemplate: string): string[] {\n const matches = uriTemplate.match(/\\{([^}]+)\\}/g);\n if (!matches) return [];\n return matches.map((m) => m.slice(1, -1));\n}\n\nfunction kebabToCamel(str: string): string {\n return str.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n}\n\nfunction escapeStr(s: string): string {\n return s.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n}\n"]}
|
|
1
|
+
{"version":3,"file":"generate-cli-entry.js","sourceRoot":"","sources":["../../../../../../src/commands/build/exec/cli-runtime/generate-cli-entry.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Generates the CLI entry point TypeScript/JavaScript source code.\n * This creates a commander.js-based CLI where each MCP tool is a subcommand.\n */\n\nimport { CliConfig, OAuthConfig } from '../config';\nimport { ExtractedSchema, ExtractedTool, ExtractedPrompt, ExtractedResourceTemplate, ExtractedCapabilities, ExtractedJob, SYSTEM_TOOL_NAMES } from './schema-extractor';\nimport { schemaToCommander, generateOptionCode, camelToKebab } from './schema-to-commander';\n\nexport const RESERVED_COMMANDS = new Set([\n 'resource', 'template', 'prompt', 'subscribe',\n 'login', 'logout', 'connect', 'serve', 'daemon',\n 'doctor', 'install', 'uninstall', 'sessions', 'help', 'version',\n 'skills', 'job', 'workflow',\n]);\n\nexport interface CliEntryOptions {\n appName: string;\n appVersion: string;\n description: string;\n serverBundleFilename: string;\n outputDefault: 'text' | 'json';\n authRequired: boolean;\n excludeTools: string[];\n nativeDeps: NonNullable<CliConfig['nativeDeps']>;\n schema: ExtractedSchema;\n oauthConfig?: OAuthConfig;\n /** When true, generate static requires that esbuild can resolve (for SEA builds). */\n selfContained?: boolean;\n}\n\n/**\n * Resolve tool command name, appending '-tool' suffix if it conflicts with a built-in command.\n * Returns { cmdName, wasRenamed } so the caller can log a warning at build time.\n */\nexport function resolveToolCommandName(toolName: string): { cmdName: string; wasRenamed: boolean } {\n const cmdName = camelToKebab(toolName).replace(/_/g, '-');\n if (RESERVED_COMMANDS.has(cmdName)) {\n return { cmdName: `${cmdName}-tool`, wasRenamed: true };\n }\n return { cmdName, wasRenamed: false };\n}\n\n/**\n * Generate the CLI entry source code (CJS module).\n */\nexport function generateCliEntry(options: CliEntryOptions): string {\n const {\n appName,\n appVersion,\n description,\n serverBundleFilename,\n outputDefault,\n schema,\n excludeTools,\n oauthConfig,\n authRequired,\n } = options;\n\n const capabilities = schema.capabilities;\n\n const filteredTools = schema.tools.filter(\n (t) => !excludeTools.includes(t.name) && !SYSTEM_TOOL_NAMES.has(t.name),\n );\n\n const selfContained = !!options.selfContained;\n\n const sections: string[] = [\n generateHeader(appName, appVersion, description, serverBundleFilename, outputDefault, authRequired, capabilities, oauthConfig, selfContained),\n generateToolCommands(filteredTools, appName),\n generateResourceCommands(schema),\n generateTemplateCommands(schema.resourceTemplates),\n generatePromptCommands(schema.prompts),\n capabilities.skills ? generateSkillsCommands() : '',\n capabilities.jobs ? generateJobCommands(schema.jobs) : '',\n capabilities.workflows ? generateWorkflowCommands() : '',\n generateSubscribeCommands(),\n ...(authRequired ? [\n generateLoginCommand(appName, oauthConfig),\n generateLogoutCommand(appName),\n generateSessionCommands(),\n ] : []),\n generateServeCommand(serverBundleFilename, selfContained),\n generateDoctorCommand(appName, options.nativeDeps),\n generateInstallCommand(appName, options.nativeDeps, selfContained),\n generateDaemonCommands(appName, serverBundleFilename, selfContained),\n generateFooter(),\n ];\n\n return sections.filter(Boolean).join('\\n\\n');\n}\n\nfunction generateHeader(\n appName: string,\n appVersion: string,\n description: string,\n serverBundleFilename: string,\n outputDefault: string,\n authRequired: boolean,\n capabilities: ExtractedCapabilities,\n oauthConfig?: OAuthConfig,\n selfContained?: boolean,\n): string {\n const hasOAuth = !!oauthConfig;\n\n // Build the group routing map dynamically\n const skillsRouting = capabilities.skills ? `\\n else if (name === 'skills') groups['Skills'].push(sub);` : '';\n const jobsRouting = capabilities.jobs ? `\\n else if (name === 'job') groups['Jobs'].push(sub);` : '';\n const workflowsRouting = capabilities.workflows ? `\\n else if (name === 'workflow') groups['Workflows'].push(sub);` : '';\n const authRouting = authRequired ? `\\n else if (['login', 'logout', 'sessions', 'connect'].indexOf(name) !== -1) groups['Auth'].push(sub);` : '';\n\n // Build the groups object dynamically\n const groupEntries: string[] = [\n ` 'Tools': []`,\n ` 'Resources & Prompts': []`,\n ];\n if (capabilities.skills) groupEntries.push(` 'Skills': []`);\n if (capabilities.jobs) groupEntries.push(` 'Jobs': []`);\n if (capabilities.workflows) groupEntries.push(` 'Workflows': []`);\n if (authRequired) groupEntries.push(` 'Auth': []`);\n groupEntries.push(` 'Subscriptions': []`);\n groupEntries.push(` 'System': []`);\n\n return `'use strict';\n${selfContained ? `\n// SEA daemon mode: when spawned by 'daemon start', run the server directly\n// using the inlined (bundled) server code — no external requires needed.\nif (process.env.__FRONTMCP_DAEMON_MODE === '1') {\n require('reflect-metadata');\n var _dMod = require(${JSON.stringify('../' + serverBundleFilename)});\n var _dSdk = require('@frontmcp/sdk');\n var _FMI = _dSdk.FrontMcpInstance || _dSdk.default.FrontMcpInstance;\n var _raw = _dMod.default || _dMod;\n var _cfg = (typeof _raw === 'function' && typeof Reflect !== 'undefined' && Reflect.getMetadata)\n ? (Reflect.getMetadata('__frontmcp:config', _raw) || _raw) : _raw;\n var _sp = process.env.FRONTMCP_DAEMON_SOCKET;\n _FMI.runUnixSocket(Object.assign({}, _cfg, { socketPath: _sp }))\n .then(function() { console.log('Daemon listening on ' + _sp); })\n .catch(function(e) { console.error('Daemon failed:', e); process.exit(1); });\n return;\n}\n` : ''}\nvar { Command, Option } = require('commander');\nvar path = require('path');\nvar fs = require('fs');\nvar os = require('os');\nvar fmt = require('./output-formatter');\n${authRequired ? \"var sessions = require('./session-manager');\\nvar creds = require('./credential-store');\" : ''}\n${hasOAuth ? \"var oauthHelper = require('./oauth-helper');\" : ''}\n\nvar APP_NAME = ${JSON.stringify(appName)};\nvar SCRIPT_DIR = __dirname;\nvar FRONTMCP_HOME = process.env.FRONTMCP_HOME || path.join(os.homedir(), '.frontmcp');\n// Set app name for file logger (writes to ~/.frontmcp/logs/{appName}-{timestamp}.log)\nprocess.env.FRONTMCP_APP_NAME = process.env.FRONTMCP_APP_NAME || APP_NAME;\n${selfContained\n ? `// Self-contained: server bundle and SDK are inlined by esbuild\nvar SERVER_BUNDLE = '../${serverBundleFilename}';`\n : `var SERVER_BUNDLE = path.join(SCRIPT_DIR, ${JSON.stringify(serverBundleFilename)});`}\n\nvar _client = null;\nasync function getClient() {\n if (_client) return _client;\n\n // Try daemon first — Unix socket HTTP (~5-15ms vs ~420ms in-process)\n var socketPath = path.join(FRONTMCP_HOME, 'sockets', APP_NAME + '.sock');\n if (fs.existsSync(socketPath)) {\n try {\n var daemonClient = require('./daemon-client');\n var dc = daemonClient.createDaemonClient(socketPath);\n await dc.ping();\n _client = dc;\n return _client;\n } catch (_) { /* daemon not available, fall through */ }\n }\n\n // Fallback: in-process connect (with CLI mode for faster init)\n // Suppress @FrontMcp decorator bootstrap — we only need config metadata, not a running server.\n process.env.FRONTMCP_SCHEMA_EXTRACT = '1';\n var mod = require(${selfContained ? `'../${serverBundleFilename}'` : 'SERVER_BUNDLE'});\n delete process.env.FRONTMCP_SCHEMA_EXTRACT;\n var configOrClass = mod.default || mod;\n var sdk = require('@frontmcp/sdk');\n var connect = sdk.connect || sdk.direct.connect;${authRequired ? `\n var sessionName = sessions.getActiveSessionName();\n var store = creds.createCredentialStore();\n var credBlob = await store.get(sessionName);\n var connectOpts = credBlob ? { authToken: credBlob.token, mode: 'cli' } : { mode: 'cli' };\n _client = await connect(configOrClass, connectOpts);` : `\n _client = await connect(configOrClass, { mode: 'cli' });`}\n return _client;\n}\n\nvar program = new Command();\nprogram\n .name(${JSON.stringify(appName)})\n .version(${JSON.stringify(appVersion)})\n .description(${JSON.stringify(description || `${appName} CLI`)})\n .option('--output <mode>', 'Output format: text or json', ${JSON.stringify(outputDefault)})\n .option('--verbose', 'Enable verbose console logging (logs always go to ~/.frontmcp/logs/)')\n .option('--log-dir <path>', 'Directory for log files (default: ~/.frontmcp/logs/)');\n\n// Wire --verbose and --log-dir to env vars early (before any command action runs).\n// Parse argv directly since commander hooks may not be available in all versions.\n(function() {\n var argv = process.argv;\n if (argv.indexOf('--verbose') !== -1) {\n process.env.FRONTMCP_CLI_VERBOSE = '1';\n }\n var logDirIdx = argv.indexOf('--log-dir');\n if (logDirIdx !== -1 && argv[logDirIdx + 1]) {\n process.env.FRONTMCP_LOG_DIR = argv[logDirIdx + 1];\n }\n})();\n\nprogram.configureHelp({\n sortSubcommands: false,\n formatHelp: function(cmd, helper) {\n var groups = {\n${groupEntries.join(',\\n')}\n };\n var toolCmdNames = cmd._toolCommandNames || [];\n cmd.commands.forEach(function(sub) {\n var name = sub.name();\n if (toolCmdNames.indexOf(name) !== -1) groups['Tools'].push(sub);\n else if (['resource', 'template', 'prompt'].indexOf(name) !== -1) groups['Resources & Prompts'].push(sub);${skillsRouting}${jobsRouting}${workflowsRouting}${authRouting}\n else if (name === 'subscribe') groups['Subscriptions'].push(sub);\n else groups['System'].push(sub);\n });\n var termWidth = helper.padWidth(cmd, helper);\n var lines = [];\n lines.push('Usage: ' + helper.commandUsage(cmd));\n lines.push('');\n var desc = helper.commandDescription(cmd);\n if (desc) { lines.push(desc); lines.push(''); }\n var globalOpts = helper.formatHelp ? helper.visibleOptions(cmd) : [];\n if (globalOpts.length > 0) {\n lines.push('Options:');\n globalOpts.forEach(function(opt) {\n lines.push(' ' + helper.optionTerm(opt).padEnd(termWidth) + ' ' + helper.optionDescription(opt));\n });\n lines.push('');\n }\n Object.keys(groups).forEach(function(groupName) {\n var cmds = groups[groupName];\n if (cmds.length === 0) return;\n lines.push(groupName + ':');\n cmds.forEach(function(sub) {\n lines.push(' ' + helper.subcommandTerm(sub).padEnd(termWidth) + ' ' + helper.subcommandDescription(sub));\n });\n lines.push('');\n });\n return lines.join('\\\\n');\n }\n});\n\nprogram.action(function() { program.outputHelp(); });`;\n}\n\nfunction generateToolCommands(tools: ExtractedTool[], appName: string): string {\n if (tools.length === 0) return '// No tools extracted\\nprogram._toolCommandNames = [];';\n\n const cmdNames: string[] = [];\n const commands = tools.map((tool) => {\n const { cmdName } = resolveToolCommandName(tool.name);\n cmdNames.push(cmdName);\n const { options } = schemaToCommander(tool.inputSchema);\n const optionLines = options.map((o) => ` ${generateOptionCode(o)}`).join('\\n');\n\n return `program\n .command(${JSON.stringify(cmdName)})\n .description(${JSON.stringify(tool.description)})\n${optionLines}\n .action(async function(opts) {\n try {\n var client = await getClient();\n var args = {};\n var rawOpts = this.opts();\n ${generateArgMapping(tool)}\n var result = await client.callTool(${JSON.stringify(tool.name)}, args);\n var mode = program.opts().output || ${JSON.stringify('text')};\n console.log(fmt.formatToolResult(result, mode));\n } catch (err) {\n var meta = err && err._meta ? err._meta : (err && err.data && err.data._meta ? err.data._meta : null);\n if (meta && meta.authorization_required) {\n console.error('Authorization required' + (meta.app ? ' for ' + meta.app : ''));\n if (meta.auth_url) console.error('Authorize at: ' + meta.auth_url);\n console.error('Or run: ' + ${JSON.stringify(appName)} + ' login');\n } else {\n console.error('Error:', err.message || err);\n }\n process.exitCode = 1;\n }\n });`;\n });\n\n return `program._toolCommandNames = ${JSON.stringify(cmdNames)};\\n\\n${commands.join('\\n\\n')}`;\n}\n\nfunction generateArgMapping(tool: ExtractedTool): string {\n const props = (tool.inputSchema as Record<string, unknown>).properties as Record<string, Record<string, unknown>> | undefined;\n if (!props) return '';\n\n const mappings = Object.keys(props).map((propName) => {\n const propSchema = props[propName];\n const kebab = camelToKebab(propName);\n // Commander converts kebab-case flags to camelCase in opts()\n const camel = kebabToCamel(kebab);\n\n // Resolve type for object detection\n let propType = propSchema?.type as string | string[] | undefined;\n if (Array.isArray(propType)) {\n propType = propType.find((t: string) => t !== 'null') || propType[0];\n }\n\n if (propType === 'object') {\n return `if (rawOpts[${JSON.stringify(camel)}] !== undefined) {\n try { args[${JSON.stringify(propName)}] = JSON.parse(rawOpts[${JSON.stringify(camel)}]); }\n catch (_jsonErr) { console.error('Invalid JSON for --${kebab}'); process.exitCode = 1; return; }\n }`;\n }\n\n return `if (rawOpts[${JSON.stringify(camel)}] !== undefined) args[${JSON.stringify(propName)}] = rawOpts[${JSON.stringify(camel)}];`;\n });\n\n return mappings.join('\\n ');\n}\n\nfunction generateJobArgMapping(inputSchema: Record<string, unknown>): string {\n const props = (inputSchema as Record<string, unknown>).properties as Record<string, Record<string, unknown>> | undefined;\n if (!props) return '';\n\n const mappings = Object.keys(props).map((propName) => {\n const propSchema = props[propName];\n const kebab = camelToKebab(propName);\n const camel = kebabToCamel(kebab);\n\n let propType = propSchema?.type as string | string[] | undefined;\n if (Array.isArray(propType)) {\n propType = propType.find((t: string) => t !== 'null') || propType[0];\n }\n\n if (propType === 'object') {\n return `if (rawOpts[${JSON.stringify(camel)}] !== undefined) {\n try { input[${JSON.stringify(propName)}] = JSON.parse(rawOpts[${JSON.stringify(camel)}]); }\n catch (_jsonErr) { console.error('Invalid JSON for --${kebab}'); process.exitCode = 1; return; }\n }`;\n }\n\n return `if (rawOpts[${JSON.stringify(camel)}] !== undefined) input[${JSON.stringify(propName)}] = rawOpts[${JSON.stringify(camel)}];`;\n });\n\n return mappings.join('\\n ');\n}\n\nfunction generateResourceCommands(_schema: ExtractedSchema): string {\n return `var resourceCmd = program.command('resource').description('Resource operations');\n\nresourceCmd\n .command('list')\n .description('List available resources')\n .action(async function() {\n try {\n var client = await getClient();\n var result = await client.listResources();\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n var resources = result.resources || [];\n if (resources.length === 0) { console.log('No resources available.'); return; }\n resources.forEach(function(r) {\n console.log(' ' + r.uri + (r.description ? ' - ' + r.description : ''));\n });\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\nresourceCmd\n .command('read <uri>')\n .description('Read a resource by URI')\n .action(async function(uri) {\n try {\n var client = await getClient();\n var result = await client.readResource(uri);\n var mode = program.opts().output || 'text';\n console.log(fmt.formatResourceResult(result, mode));\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n}\n\nfunction generateTemplateCommands(templates: ExtractedResourceTemplate[]): string {\n if (!templates || templates.length === 0) return '// No resource templates extracted';\n\n const subcommands = templates.map((tmpl) => {\n const cmdName = camelToKebab(tmpl.name).replace(/_/g, '-');\n // Extract {param} placeholders from URI template\n const paramNames = extractTemplateParams(tmpl.uriTemplate);\n const optionLines = paramNames\n .map((p) => ` .requiredOption('--${camelToKebab(p)} <value>', 'Template parameter: ${p}')`)\n .join('\\n');\n\n const paramMapping = paramNames\n .map((p) => {\n const camel = kebabToCamel(camelToKebab(p));\n return `uri = uri.replace('{${p}}', encodeURIComponent(rawOpts[${JSON.stringify(camel)}]));`;\n })\n .join('\\n ');\n\n return `templateCmd\n .command(${JSON.stringify(cmdName)})\n .description(${JSON.stringify(tmpl.description || `Read resource from template: ${tmpl.uriTemplate}`)})\n${optionLines}\n .action(async function(opts) {\n try {\n var client = await getClient();\n var rawOpts = this.opts();\n var uri = ${JSON.stringify(tmpl.uriTemplate)};\n ${paramMapping}\n var result = await client.readResource(uri);\n var mode = program.opts().output || 'text';\n console.log(fmt.formatResourceResult(result, mode));\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n });\n\n return `var templateCmd = program.command('template').description('Resource template operations');\n\ntemplateCmd\n .command('list')\n .description('List available resource templates')\n .action(async function() {\n try {\n var client = await getClient();\n var result = await client.listResourceTemplates();\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n var templates = result.resourceTemplates || [];\n if (templates.length === 0) { console.log('No resource templates available.'); return; }\n templates.forEach(function(t) {\n console.log(' ' + t.uriTemplate + (t.description ? ' - ' + t.description : ''));\n });\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\n${subcommands.join('\\n\\n')}`;\n}\n\nfunction generatePromptCommands(prompts: ExtractedPrompt[]): string {\n const subcommands = prompts.map((prompt) => {\n const cmdName = camelToKebab(prompt.name).replace(/_/g, '-');\n const argOptions = (prompt.arguments || [])\n .map((a) => {\n const flag = `--${camelToKebab(a.name)} <value>`;\n const desc = a.description || '';\n return a.required\n ? ` .requiredOption('${flag}', '${escapeStr(desc)}')`\n : ` .option('${flag}', '${escapeStr(desc)}')`;\n })\n .join('\\n');\n\n return `promptCmd\n .command(${JSON.stringify(cmdName)})\n .description(${JSON.stringify(prompt.description || '')})\n${argOptions}\n .action(async function(opts) {\n try {\n var client = await getClient();\n var args = {};\n var rawOpts = this.opts();\n ${(prompt.arguments || []).map((a) => {\n const camel = kebabToCamel(camelToKebab(a.name));\n return `if (rawOpts[${JSON.stringify(camel)}] !== undefined) args[${JSON.stringify(a.name)}] = rawOpts[${JSON.stringify(camel)}];`;\n }).join('\\n ')}\n var result = await client.getPrompt(${JSON.stringify(prompt.name)}, args);\n var mode = program.opts().output || 'text';\n console.log(fmt.formatPromptResult(result, mode));\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n });\n\n return `var promptCmd = program.command('prompt').description('Prompt operations');\n\npromptCmd\n .command('list')\n .description('List available prompts')\n .action(async function() {\n try {\n var client = await getClient();\n var result = await client.listPrompts();\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n var prompts = result.prompts || [];\n if (prompts.length === 0) { console.log('No prompts available.'); return; }\n prompts.forEach(function(p) {\n console.log(' ' + p.name + (p.description ? ' - ' + p.description : ''));\n });\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\n${subcommands.join('\\n\\n')}`;\n}\n\nfunction generateSkillsCommands(): string {\n return `var skillsCmd = program.command('skills').description('Skill operations');\n\nskillsCmd\n .command('search [query]')\n .description('Search for skills')\n .action(async function(query) {\n try {\n var client = await getClient();\n var result = await client.searchSkills(query || '');\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n var skills = result.skills || result || [];\n if (Array.isArray(skills) && skills.length === 0) { console.log('No skills found.'); return; }\n if (Array.isArray(skills)) {\n skills.forEach(function(s) {\n console.log(' ' + (s.name || s.id || JSON.stringify(s)));\n });\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\nskillsCmd\n .command('load <ids...>')\n .description('Load skills by ID')\n .action(async function(ids) {\n try {\n var client = await getClient();\n var result = await client.loadSkills(ids);\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log('Loaded ' + ids.length + ' skill(s).');\n if (result && typeof result === 'object') {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\nskillsCmd\n .command('list')\n .description('List available skills')\n .action(async function() {\n try {\n var client = await getClient();\n var result = await client.listSkills();\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n var skills = result.skills || result || [];\n if (Array.isArray(skills) && skills.length === 0) { console.log('No skills available.'); return; }\n if (Array.isArray(skills)) {\n skills.forEach(function(s) {\n console.log(' ' + (s.name || s.id || JSON.stringify(s)));\n });\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n}\n\nfunction generateJobCommands(jobs: ExtractedJob[]): string {\n // Generate typed 'run' subcommands for each known job\n const runSubcommands = jobs.map((job) => {\n const jobCmdName = camelToKebab(job.name).replace(/_/g, '-');\n\n if (job.inputSchema) {\n const { options } = schemaToCommander(job.inputSchema);\n const optionLines = options.map((o) => ` ${generateOptionCode(o)}`).join('\\n');\n const argMapping = generateJobArgMapping(job.inputSchema);\n\n return `jobRunCmd\n .command(${JSON.stringify(jobCmdName)})\n .description(${JSON.stringify(job.description || `Run the ${job.name} job`)})\n${optionLines}\n .option('--background', 'Run in background mode')\n .action(async function(opts) {\n try {\n var client = await getClient();\n var input = {};\n var rawOpts = this.opts();\n ${argMapping}\n var result = await client.executeJob(${JSON.stringify(job.name)}, input, { background: !!rawOpts.background });\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n if (rawOpts.background && result && result.runId) {\n console.log('Job started. Run ID: ' + result.runId);\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n }\n\n // No inputSchema — fall back to generic --input <json>\n return `jobRunCmd\n .command(${JSON.stringify(jobCmdName)})\n .description(${JSON.stringify(job.description || `Run the ${job.name} job`)})\n .option('--input <json>', 'Job input as JSON string')\n .option('--background', 'Run in background mode')\n .action(async function(opts) {\n try {\n var client = await getClient();\n var input = {};\n if (opts.input) {\n try { input = JSON.parse(opts.input); }\n catch (_) { console.error('Invalid JSON for --input'); process.exitCode = 1; return; }\n }\n var result = await client.executeJob(${JSON.stringify(job.name)}, input, { background: !!opts.background });\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n if (opts.background && result && result.runId) {\n console.log('Job started. Run ID: ' + result.runId);\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n });\n\n // Generic fallback 'run' for jobs not known at build time\n const genericRun = `jobRunCmd\n .command('_run <name>')\n .description('Run a job by name (generic)')\n .option('--input <json>', 'Job input as JSON string')\n .option('--background', 'Run in background mode')\n .action(async function(name, opts) {\n try {\n var client = await getClient();\n var input = {};\n if (opts.input) {\n try { input = JSON.parse(opts.input); }\n catch (_) { console.error('Invalid JSON for --input'); process.exitCode = 1; return; }\n }\n var result = await client.executeJob(name, input, { background: !!opts.background });\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n if (opts.background && result && result.runId) {\n console.log('Job started. Run ID: ' + result.runId);\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n\n return `var jobCmd = program.command('job').description('Job operations');\n\njobCmd\n .command('list')\n .description('List available jobs')\n .action(async function() {\n try {\n var client = await getClient();\n var result = await client.listJobs();\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n var jobs = result.jobs || result || [];\n if (Array.isArray(jobs) && jobs.length === 0) { console.log('No jobs available.'); return; }\n if (Array.isArray(jobs)) {\n jobs.forEach(function(j) {\n console.log(' ' + (j.name || j.id || JSON.stringify(j)));\n });\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\nvar jobRunCmd = jobCmd.command('run').description('Run a job');\n\n${runSubcommands.join('\\n\\n')}\n\n${jobs.length > 0 ? genericRun : `jobRunCmd\n .argument('<name>', 'Job name')\n .option('--input <json>', 'Job input as JSON string')\n .option('--background', 'Run in background mode')\n .action(async function(name, opts) {\n try {\n var client = await getClient();\n var input = {};\n if (opts.input) {\n try { input = JSON.parse(opts.input); }\n catch (_) { console.error('Invalid JSON for --input'); process.exitCode = 1; return; }\n }\n var result = await client.executeJob(name, input, { background: !!opts.background });\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n if (opts.background && result && result.runId) {\n console.log('Job started. Run ID: ' + result.runId);\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`}\n\njobCmd\n .command('status <runId>')\n .description('Get the status of a job run')\n .action(async function(runId) {\n try {\n var client = await getClient();\n var result = await client.getJobStatus(runId);\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log('Status: ' + (result.status || JSON.stringify(result)));\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n}\n\nfunction generateWorkflowCommands(): string {\n return `var workflowCmd = program.command('workflow').description('Workflow operations');\n\nworkflowCmd\n .command('list')\n .description('List available workflows')\n .action(async function() {\n try {\n var client = await getClient();\n var result = await client.listWorkflows();\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n var workflows = result.workflows || result || [];\n if (Array.isArray(workflows) && workflows.length === 0) { console.log('No workflows available.'); return; }\n if (Array.isArray(workflows)) {\n workflows.forEach(function(w) {\n console.log(' ' + (w.name || w.id || JSON.stringify(w)));\n });\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\nworkflowCmd\n .command('run <name>')\n .description('Run a workflow by name')\n .option('--input <json>', 'Workflow input as JSON string')\n .option('--background', 'Run in background mode')\n .action(async function(name, opts) {\n try {\n var client = await getClient();\n var input = {};\n if (opts.input) {\n try { input = JSON.parse(opts.input); }\n catch (_) { console.error('Invalid JSON for --input'); process.exitCode = 1; return; }\n }\n var result = await client.executeWorkflow(name, input, { background: !!opts.background });\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n if (opts.background && result && result.runId) {\n console.log('Workflow started. Run ID: ' + result.runId);\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\nworkflowCmd\n .command('status <runId>')\n .description('Get the status of a workflow run')\n .action(async function(runId) {\n try {\n var client = await getClient();\n var result = await client.getWorkflowStatus(runId);\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log('Status: ' + (result.status || JSON.stringify(result)));\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n}\n\nfunction generateSubscribeCommands(): string {\n return `\n// Subscribe commands need push support (onNotification/onResourceUpdated).\n// Daemon HTTP cannot push, so we force in-process when daemon was used.\nasync function getSubscribeClient() {\n var client = await getClient();\n // If connected via daemon, the onNotification/onResourceUpdated are no-ops.\n // Reconnect via in-process for push support.\n if (client._isDaemon) {\n _client = null; // clear cached daemon client\n var mod = require(SERVER_BUNDLE);\n var configOrClass = mod.default || mod;\n var sdk = require('@frontmcp/sdk');\n var connect = sdk.connect || sdk.direct.connect;\n _client = await connect(configOrClass, { mode: 'cli' });\n return _client;\n }\n return client;\n}\n\nvar subscribeCmd = program.command('subscribe').description('Subscribe to updates');\n\nsubscribeCmd\n .command('resource <uri>')\n .description('Stream resource updates (Ctrl+C to stop)')\n .action(async function(uri) {\n try {\n var client = await getSubscribeClient();\n await client.subscribeResource(uri);\n var mode = program.opts().output || 'text';\n console.log('Subscribed to resource: ' + uri);\n console.log('Waiting for updates... (Ctrl+C to stop)\\\\n');\n client.onResourceUpdated(function(uri) {\n console.log(fmt.formatSubscriptionEvent({ type: 'resource_updated', uri: uri, timestamp: new Date().toISOString() }, mode));\n });\n process.on('SIGINT', async function() {\n console.log('\\\\nUnsubscribing...');\n try { await client.unsubscribeResource(uri); } catch (_) { /* ok */ }\n process.exit(0);\n });\n // Keep process alive — setInterval creates an active event loop handle\n // so Node.js won't exit even with InMemoryTransport (no persistent I/O)\n setInterval(function() {}, 2147483647);\n await new Promise(function() {});\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\nsubscribeCmd\n .command('notification <name>')\n .description('Stream notifications (Ctrl+C to stop)')\n .action(async function(name) {\n try {\n var client = await getSubscribeClient();\n var mode = program.opts().output || 'text';\n console.log('Listening for notification: ' + name);\n console.log('Waiting for events... (Ctrl+C to stop)\\\\n');\n client.onNotification(function(notification) {\n if (notification.method === name || name === '*') {\n console.log(fmt.formatSubscriptionEvent({ type: 'notification', method: notification.method, params: notification.params, timestamp: new Date().toISOString() }, mode));\n }\n });\n process.on('SIGINT', function() {\n console.log('\\\\nStopping...');\n process.exit(0);\n });\n // Keep process alive — setInterval creates an active event loop handle\n // so Node.js won't exit even with InMemoryTransport (no persistent I/O)\n setInterval(function() {}, 2147483647);\n await new Promise(function() {});\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n}\n\nfunction generateLoginCommand(appName: string, oauthConfig?: OAuthConfig): string {\n const serverUrl = oauthConfig?.serverUrl || '';\n const clientId = oauthConfig?.clientId || appName;\n const defaultScope = oauthConfig?.defaultScope || '';\n const portStart = oauthConfig?.portRange?.[0] ?? 17830;\n const portEnd = oauthConfig?.portRange?.[1] ?? 17850;\n const timeout = oauthConfig?.timeout ?? 120000;\n\n return `program\n .command('login')\n .description('Authenticate via OAuth')\n .option('--server <url>', 'Server URL for OAuth'${serverUrl ? `, ${JSON.stringify(serverUrl)}` : ''})\n .option('--session <name>', 'Session name', 'default')\n .option('--scope <scopes>', 'OAuth scopes'${defaultScope ? `, ${JSON.stringify(defaultScope)}` : ''})\n .option('--no-browser', 'Print URL instead of opening browser')\n .action(async function(opts) {\n var serverUrl = opts.server || process.env.FRONTMCP_SERVER_URL || ${JSON.stringify(serverUrl)};\n if (!serverUrl) {\n console.error('Server URL required. Use --server <url> or set FRONTMCP_SERVER_URL.');\n process.exitCode = 1;\n return;\n }\n try {\n var oauthHelper = require('./oauth-helper');\n var result = await oauthHelper.startOAuthLogin({\n serverUrl: serverUrl,\n clientId: ${JSON.stringify(clientId)},\n scope: opts.scope || ${JSON.stringify(defaultScope)},\n portStart: ${portStart},\n portEnd: ${portEnd},\n timeout: ${timeout},\n noBrowser: !opts.browser\n });\n var sessionName = opts.session || 'default';\n var store = creds.createCredentialStore();\n await store.set(sessionName, result);\n sessions.getOrCreateSession(sessionName);\n console.log('Logged in successfully. Session: ' + sessionName);\n } catch (err) {\n console.error('Login failed:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n}\n\nfunction generateLogoutCommand(_appName: string): string {\n return `program\n .command('logout')\n .description('Clear stored credentials')\n .option('--session <name>', 'Session to log out')\n .option('--all', 'Log out of all sessions')\n .action(async function(opts) {\n var store = creds.createCredentialStore();\n if (opts.all) {\n var allSessions = await store.list();\n for (var i = 0; i < allSessions.length; i++) {\n await store.delete(allSessions[i]);\n }\n console.log('Logged out of ' + allSessions.length + ' session(s).');\n } else {\n var sessionName = opts.session || sessions.getActiveSessionName();\n await store.delete(sessionName);\n console.log('Logged out of session: ' + sessionName);\n }\n });`;\n}\n\nfunction generateSessionCommands(): string {\n return `var sessionsCmd = program.command('sessions').description('Session management');\n\nsessionsCmd\n .command('list')\n .description('List all sessions')\n .action(function() {\n var list = sessions.listSessions();\n if (list.length === 0) { console.log('No sessions.'); return; }\n list.forEach(function(s) {\n var marker = s.isActive ? ' (active)' : '';\n console.log(' ' + s.name + marker + ' - last used: ' + s.lastUsedAt);\n });\n });\n\nsessionsCmd\n .command('switch <name>')\n .description('Switch to a named session')\n .action(function(name) {\n sessions.switchSession(name);\n console.log('Switched to session: ' + name);\n });\n\nsessionsCmd\n .command('delete <name>')\n .description('Delete a session')\n .action(async function(name) {\n var store = creds.createCredentialStore();\n await store.delete(name);\n sessions.deleteSession(name);\n console.log('Deleted session: ' + name);\n });\n\nprogram\n .command('connect')\n .description('Authenticate and store credentials')\n .option('--session <name>', 'Session name', 'default')\n .option('--token <token>', 'Auth token (or pass via stdin)')\n .action(async function(opts) {\n var sessionName = opts.session || 'default';\n var token = opts.token;\n if (!token) {\n console.log('Usage: ' + program.name() + ' connect --token <your-token>');\n console.log(' Or pipe token: echo \"tok_xxx\" | ' + program.name() + ' connect');\n process.exitCode = 1;\n return;\n }\n var store = creds.createCredentialStore();\n await store.set(sessionName, { token: token });\n sessions.getOrCreateSession(sessionName);\n console.log('Credentials stored for session: ' + sessionName);\n });`;\n}\n\nfunction generateServeCommand(serverBundleFilename: string, selfContained?: boolean): string {\n // In self-contained/SEA mode, use a static relative require that esbuild can resolve at bundle time.\n // In normal mode, use dynamic path.join for runtime resolution from disk.\n const requireExpr = selfContained\n ? `require(${JSON.stringify('../' + serverBundleFilename)})`\n : `require(path.join(SCRIPT_DIR, ${JSON.stringify(serverBundleFilename)}))`;\n\n return `program\n .command('serve')\n .description('Start the HTTP/SSE server')\n .option('-p, --port <port>', 'Port number', function(v) { return parseInt(v, 10); })\n .action(async function(opts) {\n var mod = ${requireExpr};\n if (opts.port) process.env.PORT = String(opts.port);\n // If the bundle exports a start() function (@FrontMcp-decorated class auto-bootstraps), use it\n if (typeof mod.start === 'function') { await mod.start(); return; }\n if (typeof mod.default?.start === 'function') { await mod.default.start(); return; }\n // Otherwise, bootstrap the plain config object via FrontMcpInstance\n var raw = mod.default || mod;\n var sdk = require('@frontmcp/sdk');\n var FrontMcpInstance = sdk.FrontMcpInstance || sdk.default.FrontMcpInstance;\n var config = (typeof raw === 'function' && typeof Reflect !== 'undefined' && Reflect.getMetadata)\n ? (Reflect.getMetadata('__frontmcp:config', raw) || raw) : raw;\n if (opts.port) config = Object.assign({}, config, { http: Object.assign({}, config.http || {}, { port: opts.port }) });\n await FrontMcpInstance.bootstrap(config);\n });`;\n}\n\nfunction generateDoctorCommand(\n appName: string,\n nativeDeps: NonNullable<CliConfig['nativeDeps']>,\n): string {\n const checks: string[] = [];\n\n if (nativeDeps.brew?.length) {\n for (const pkg of nativeDeps.brew) {\n checks.push(` { name: ${JSON.stringify(pkg)}, type: 'brew', check: 'brew list ${pkg}' }`);\n }\n }\n if (nativeDeps.apt?.length) {\n for (const pkg of nativeDeps.apt) {\n checks.push(` { name: ${JSON.stringify(pkg)}, type: 'apt', check: 'dpkg -l ${pkg}' }`);\n }\n }\n if (nativeDeps.npm?.length) {\n for (const pkg of nativeDeps.npm) {\n checks.push(` { name: ${JSON.stringify(pkg)}, type: 'npm', check: 'npm ls ${pkg}' }`);\n }\n }\n\n return `program\n .command('doctor')\n .description('Check system dependencies and configuration')\n .option('--fix', 'Attempt to install missing dependencies')\n .action(async function(opts) {\n var exec = require('child_process').execSync;\n var ok = true;\n\n // Check Node.js version\n var nodeMajor = parseInt(process.versions.node.split('.')[0], 10);\n if (nodeMajor >= 22) {\n console.log(' [ok] Node.js v' + process.versions.node);\n } else {\n console.log(' [!!] Node.js v' + process.versions.node + ' (>=22 required)');\n ok = false;\n }\n\n var deps = [\n${checks.join(',\\n')}\n ];\n\n for (var i = 0; i < deps.length; i++) {\n var dep = deps[i];\n try {\n exec(dep.check, { stdio: 'ignore' });\n console.log(' [ok] ' + dep.name + ' (' + dep.type + ')');\n } catch (_) {\n console.log(' [!!] ' + dep.name + ' (' + dep.type + ') - not found');\n ok = false;\n if (opts.fix) {\n try {\n var installCmd = dep.type === 'brew' ? 'brew install ' + dep.name\n : dep.type === 'apt' ? 'sudo apt-get install -y ' + dep.name\n : 'npm install ' + dep.name;\n console.log(' Installing: ' + installCmd);\n exec(installCmd, { stdio: 'inherit' });\n console.log(' [ok] Installed ' + dep.name);\n } catch (e) {\n console.log(' [!!] Failed to install ' + dep.name);\n }\n }\n }\n }\n\n // Check FRONTMCP_HOME directory\n var fs = require('fs');\n var appDir = require('path').join(FRONTMCP_HOME, 'apps', ${JSON.stringify(appName)});\n if (fs.existsSync(appDir)) {\n console.log(' [ok] App directory: ' + appDir);\n } else {\n console.log(' [!!] App directory not found: ' + appDir);\n ok = false;\n if (opts.fix) {\n fs.mkdirSync(appDir, { recursive: true });\n console.log(' [fixed] Created ' + appDir);\n }\n }\n\n if (ok) console.log('\\\\nAll checks passed.');\n else {\n console.log('\\\\nSome checks failed.' + (opts.fix ? '' : ' Run with --fix to attempt repairs.'));\n process.exitCode = 1;\n }\n });`;\n}\n\nfunction generateInstallCommand(\n appName: string,\n nativeDeps: NonNullable<CliConfig['nativeDeps']>,\n selfContained?: boolean,\n): string {\n const depEntries: string[] = [];\n if (nativeDeps.brew?.length) {\n for (const pkg of nativeDeps.brew) {\n depEntries.push(` { name: ${JSON.stringify(pkg)}, type: 'brew', install: 'brew install ${pkg}', check: 'brew list ${pkg}' }`);\n }\n }\n if (nativeDeps.npm?.length) {\n for (const pkg of nativeDeps.npm) {\n depEntries.push(` { name: ${JSON.stringify(pkg)}, type: 'npm', install: 'npm install ${pkg}', check: 'npm ls ${pkg}' }`);\n }\n }\n\n return `program\n .command('install')\n .description('Install to ~/.frontmcp/ and set up dependencies')\n .option('--prefix <path>', 'Installation prefix directory')\n .option('--bin-dir <path>', 'Directory for symlink (default: ~/.local/bin or /usr/local/bin)')\n .action(async function(opts) {\n var fs = require('fs');\n var pathMod = require('path');\n var os = require('os');\n var exec = require('child_process').execSync;\n var installBase = opts.prefix || FRONTMCP_HOME;\n var appDir = pathMod.join(installBase, 'apps', ${JSON.stringify(appName)});\n var dirs = ['', '/data', '/sessions', '/credentials'].map(function(s) { return appDir + s; });\n\n console.log('Installing ${appName}...');\n dirs.forEach(function(d) { fs.mkdirSync(d, { recursive: true }); });\n\n // Copy bundle files and skill content\n var files = fs.readdirSync(SCRIPT_DIR).filter(function(f) {\n return f.endsWith('.js') || f.endsWith('.json') || f.endsWith('.md')${selfContained ? \" || f.endsWith('-bin')\" : ''};\n });\n files.forEach(function(f) {\n fs.copyFileSync(pathMod.join(SCRIPT_DIR, f), pathMod.join(appDir, f));\n });\n // Copy skill content directories (only those that exist in the build output)\n var entries = fs.readdirSync(SCRIPT_DIR, { withFileTypes: true });\n entries.forEach(function(ent) {\n if (ent.isDirectory()) {\n fs.cpSync(pathMod.join(SCRIPT_DIR, ent.name), pathMod.join(appDir, ent.name), { recursive: true });\n }\n });\n console.log(' Copied ' + files.length + ' files to ' + appDir);\n\n // Install native deps\n var deps = [\n${depEntries.join(',\\n')}\n ];\n for (var i = 0; i < deps.length; i++) {\n var dep = deps[i];\n try { exec(dep.check, { stdio: 'ignore' }); }\n catch (_) {\n console.log(' [' + (i + 1) + '/' + deps.length + '] Installing ' + dep.name + ' via ' + dep.type + '...');\n try { exec(dep.install, { stdio: 'inherit' }); }\n catch (e) { console.log(' Warning: Failed to install ' + dep.name); }\n }\n }\n\n // Set execute permission on the entry point\n var entryFile = pathMod.join(appDir, ${JSON.stringify(selfContained ? `${appName}-cli-bin` : `${appName}-cli.bundle.js`)});\n try { fs.chmodSync(entryFile, 0o755); } catch (_) { /* ok */ }\n\n // Create symlink\n var binDirs = opts.binDir ? [opts.binDir] : ['/usr/local/bin', pathMod.join(os.homedir(), '.local', 'bin')];\n var linked = false;\n for (var j = 0; j < binDirs.length && !linked; j++) {\n try {\n fs.mkdirSync(binDirs[j], { recursive: true });\n var linkPath = pathMod.join(binDirs[j], ${JSON.stringify(appName)});\n try { fs.unlinkSync(linkPath); } catch (_) { /* ok */ }\n fs.symlinkSync(entryFile, linkPath);\n console.log(' Symlinked: ' + linkPath);\n linked = true;\n } catch (_) { /* try next */ }\n }\n\n console.log('\\\\nInstalled. Run: ${appName} --help');\n });\n\nprogram\n .command('uninstall')\n .description('Remove from ~/.frontmcp/ and clean up')\n .option('--prefix <path>', 'Installation prefix directory')\n .option('--bin-dir <path>', 'Directory where symlink was created')\n .action(async function(opts) {\n var fs = require('fs');\n var pathMod = require('path');\n var os = require('os');\n var uninstallBase = opts.prefix || FRONTMCP_HOME;\n var appDir = pathMod.join(uninstallBase, 'apps', ${JSON.stringify(appName)});\n\n // Remove credentials (if auth is enabled)\n if (typeof creds !== 'undefined') {\n var store = creds.createCredentialStore();\n var credSessions = await store.list();\n for (var i = 0; i < credSessions.length; i++) {\n await store.delete(credSessions[i]);\n }\n }\n\n // Remove symlink\n var binDirs = opts.binDir ? [opts.binDir] : ['/usr/local/bin', pathMod.join(os.homedir(), '.local', 'bin')];\n binDirs.forEach(function(d) {\n try { fs.unlinkSync(pathMod.join(d, ${JSON.stringify(appName)})); } catch (_) { /* ok */ }\n });\n\n // Remove app directory\n fs.rmSync(appDir, { recursive: true, force: true });\n console.log('Uninstalled ${appName}.');\n });`;\n}\n\nfunction generateDaemonCommands(appName: string, serverBundleFilename: string, selfContained?: boolean): string {\n return `var daemonCmd = program.command('daemon').description('Daemon management');\n\ndaemonCmd\n .command('start')\n .description('Start as a background daemon (Unix socket)')\n .option('--idle-timeout <ms>', 'Auto-stop after idle period (ms, 0 to disable)', function(v) { return parseInt(v, 10); }, 300000)\n .action(async function(opts) {\n var { spawn } = require('child_process');\n var pathMod = require('path');\n var pidDir = pathMod.join(FRONTMCP_HOME, 'pids');\n var logDir = pathMod.join(FRONTMCP_HOME, 'logs');\n var socketDir = pathMod.join(FRONTMCP_HOME, 'sockets');\n fs.mkdirSync(pidDir, { recursive: true });\n fs.mkdirSync(logDir, { recursive: true });\n fs.mkdirSync(socketDir, { recursive: true });\n\n var socketPath = pathMod.join(socketDir, ${JSON.stringify(appName)} + '.sock');\n\n // Clean up stale socket file\n try { fs.unlinkSync(socketPath); } catch (_) { /* ok */ }\n\n // Check if already running\n var pidPath = pathMod.join(pidDir, ${JSON.stringify(appName)} + '.pid');\n try {\n var existing = JSON.parse(fs.readFileSync(pidPath, 'utf8'));\n process.kill(existing.pid, 0);\n console.log('Daemon already running (PID: ' + existing.pid + ').');\n return;\n } catch (_) { /* not running, proceed */ }\n\n var env = Object.assign({}, process.env, {\n FRONTMCP_DAEMON_SOCKET: socketPath,\n FRONTMCP_DAEMON_IDLE_TIMEOUT: String(opts.idleTimeout)\n });\n\n var logPath = pathMod.join(logDir, ${JSON.stringify(appName)} + '.log');\n var out = fs.openSync(logPath, 'a');\n var err = fs.openSync(logPath, 'a');\n\n${selfContained ? ` // SEA mode: spawn the binary itself in daemon mode — all code is inlined\n env.__FRONTMCP_DAEMON_MODE = '1';\n var child = spawn(process.execPath, [], {\n detached: true,\n stdio: ['ignore', out, err],\n env: env\n });` : ` // Start the daemon using runUnixSocket via a small wrapper script\n // Always use absolute path for the server bundle (SCRIPT_DIR resolves to __dirname at runtime)\n var serverBundlePath = pathMod.join(SCRIPT_DIR, ${JSON.stringify(serverBundleFilename)});\n var daemonScript = 'require(\"reflect-metadata\");' +\n 'var mod = require(' + JSON.stringify(serverBundlePath) + ');' +\n 'var sdk = require(\"@frontmcp/sdk\");' +\n 'var FrontMcpInstance = sdk.FrontMcpInstance || sdk.default.FrontMcpInstance;' +\n 'var raw = mod.default || mod;' +\n ${'// If the export is a @FrontMcp-decorated class, extract config via Reflect metadata'}\n 'var config = (typeof raw === \"function\" && typeof Reflect !== \"undefined\" && Reflect.getMetadata) ' +\n ' ? (Reflect.getMetadata(\"__frontmcp:config\", raw) || raw) : raw;' +\n 'FrontMcpInstance.runUnixSocket(Object.assign({}, config, { socketPath: ' + JSON.stringify(socketPath) + ' }))' +\n '.then(function() { console.log(\"Daemon listening on \" + ' + JSON.stringify(socketPath) + '); })' +\n '.catch(function(e) { console.error(\"Daemon failed:\", e); process.exit(1); });';\n\n var child = spawn('node', ['-e', daemonScript], {\n detached: true,\n stdio: ['ignore', out, err],\n env: env\n });`}\n\n fs.writeFileSync(pidPath, JSON.stringify({\n pid: child.pid,\n socketPath: socketPath,\n startedAt: new Date().toISOString()\n }));\n child.unref();\n\n // Wait for socket file to appear (max 5s)\n var waited = 0;\n while (!fs.existsSync(socketPath) && waited < 5000) {\n await new Promise(function(r) { setTimeout(r, 100); });\n waited += 100;\n }\n\n if (fs.existsSync(socketPath)) {\n console.log('Daemon started (PID: ' + child.pid + '). Socket: ' + socketPath);\n console.log('Logs: ' + logPath);\n } else {\n console.log('Daemon started (PID: ' + child.pid + ') but socket not yet available.');\n console.log('Check logs: ' + logPath);\n }\n });\n\ndaemonCmd\n .command('stop')\n .description('Stop the daemon')\n .action(function() {\n var pathMod = require('path');\n var pidPath = pathMod.join(FRONTMCP_HOME, 'pids', ${JSON.stringify(appName)} + '.pid');\n try {\n var data = JSON.parse(fs.readFileSync(pidPath, 'utf8'));\n process.kill(data.pid, 'SIGTERM');\n fs.unlinkSync(pidPath);\n // Clean up socket file\n if (data.socketPath) {\n try { fs.unlinkSync(data.socketPath); } catch (_) { /* ok */ }\n }\n console.log('Daemon stopped (PID: ' + data.pid + ').');\n } catch (e) {\n console.log('No running daemon found.');\n }\n });\n\ndaemonCmd\n .command('status')\n .description('Check daemon status')\n .action(function() {\n var pathMod = require('path');\n var pidPath = pathMod.join(FRONTMCP_HOME, 'pids', ${JSON.stringify(appName)} + '.pid');\n try {\n var data = JSON.parse(fs.readFileSync(pidPath, 'utf8'));\n try {\n process.kill(data.pid, 0);\n var socketStatus = data.socketPath && fs.existsSync(data.socketPath) ? ', socket: active' : '';\n console.log('Running (PID: ' + data.pid + ', started: ' + data.startedAt + socketStatus + ')');\n } catch (_) {\n console.log('Not running (stale PID file).');\n fs.unlinkSync(pidPath);\n }\n } catch (_) { console.log('Not running.'); }\n });\n\ndaemonCmd\n .command('logs')\n .description('Tail daemon logs')\n .option('-n, --lines <n>', 'Number of lines', function(v) { return parseInt(v, 10); }, 50)\n .action(function(opts) {\n var pathMod = require('path');\n var logPath = pathMod.join(FRONTMCP_HOME, 'logs', ${JSON.stringify(appName)} + '.log');\n try {\n var content = fs.readFileSync(logPath, 'utf8');\n var lines = content.split('\\\\n');\n var start = Math.max(0, lines.length - opts.lines);\n console.log(lines.slice(start).join('\\\\n'));\n } catch (_) { console.log('No logs found.'); }\n });`;\n}\n\nfunction generateFooter(): string {\n return `program.on('command:*', function(args) {\n console.error('Unknown command: ' + args[0]);\n process.exitCode = 1;\n});\nprogram.parseAsync(process.argv).then(function() {\n // Use exitCode instead of process.exit() so long-running commands\n // (e.g., serve) keep the event loop alive while short-lived commands\n // exit naturally when the event loop drains.\n process.exitCode = process.exitCode || 0;\n}).catch(function(err) {\n console.error('Fatal:', err.message || err);\n process.exitCode = 1;\n});`;\n}\n\n/**\n * Extract {param} placeholders from a URI template string.\n */\nexport function extractTemplateParams(uriTemplate: string): string[] {\n const matches = uriTemplate.match(/\\{([^}]+)\\}/g);\n if (!matches) return [];\n return matches.map((m) => m.slice(1, -1));\n}\n\nfunction kebabToCamel(str: string): string {\n return str.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n}\n\nfunction escapeStr(s: string): string {\n return s.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n}\n"]}
|
|
@@ -39,6 +39,17 @@ export interface ExtractedCapabilities {
|
|
|
39
39
|
jobs: boolean;
|
|
40
40
|
workflows: boolean;
|
|
41
41
|
}
|
|
42
|
+
export interface ExtractedSkillAsset {
|
|
43
|
+
skillName: string;
|
|
44
|
+
baseDir?: string;
|
|
45
|
+
instructionFile?: string;
|
|
46
|
+
resourceDirs?: {
|
|
47
|
+
references?: string;
|
|
48
|
+
examples?: string;
|
|
49
|
+
scripts?: string;
|
|
50
|
+
assets?: string;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
42
53
|
export interface ExtractedSchema {
|
|
43
54
|
tools: ExtractedTool[];
|
|
44
55
|
resources: ExtractedResource[];
|
|
@@ -46,6 +57,7 @@ export interface ExtractedSchema {
|
|
|
46
57
|
prompts: ExtractedPrompt[];
|
|
47
58
|
jobs: ExtractedJob[];
|
|
48
59
|
capabilities: ExtractedCapabilities;
|
|
60
|
+
skillAssets: ExtractedSkillAsset[];
|
|
49
61
|
}
|
|
50
62
|
/** Known system tool names injected by SDK features (jobs, workflows). */
|
|
51
63
|
export declare const SYSTEM_TOOL_NAMES: Set<string>;
|
|
@@ -119,7 +119,23 @@ async function extractSchemas(bundlePath) {
|
|
|
119
119
|
// Jobs listing not available at build time
|
|
120
120
|
}
|
|
121
121
|
}
|
|
122
|
-
|
|
122
|
+
// Collect skill file assets for copying to dist
|
|
123
|
+
let skillAssets = [];
|
|
124
|
+
if (capabilities.skills && client.collectSkillAssets) {
|
|
125
|
+
try {
|
|
126
|
+
const manifest = await client.collectSkillAssets();
|
|
127
|
+
skillAssets = manifest.entries.map((e) => ({
|
|
128
|
+
skillName: e.skillName,
|
|
129
|
+
baseDir: e.baseDir,
|
|
130
|
+
instructionFile: e.instructionFile,
|
|
131
|
+
resourceDirs: e.resources,
|
|
132
|
+
}));
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
// Skill asset collection not available
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return { tools, resources, resourceTemplates, prompts, jobs, capabilities, skillAssets };
|
|
123
139
|
}
|
|
124
140
|
finally {
|
|
125
141
|
await client.close().catch(() => { });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-extractor.js","sourceRoot":"","sources":["../../../../../../src/commands/build/exec/cli-runtime/schema-extractor.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Build-time schema extraction.\n * After the server bundle is produced, boots a DirectClient via connect(),\n * extracts tool/resource/prompt schemas, and serializes them for CLI code generation.\n */\n\nexport interface ExtractedTool {\n name: string;\n description: string;\n inputSchema: Record<string, unknown>;\n}\n\nexport interface ExtractedResource {\n uri: string;\n name: string;\n description?: string;\n mimeType?: string;\n}\n\nexport interface ExtractedResourceTemplate {\n uriTemplate: string;\n name: string;\n description?: string;\n}\n\nexport interface ExtractedPrompt {\n name: string;\n description?: string;\n arguments?: Array<{\n name: string;\n description?: string;\n required?: boolean;\n }>;\n}\n\nexport interface ExtractedJob {\n name: string;\n description?: string;\n inputSchema?: Record<string, unknown>;\n tags?: string[];\n}\n\nexport interface ExtractedCapabilities {\n skills: boolean;\n jobs: boolean;\n workflows: boolean;\n}\n\nexport interface ExtractedSchema {\n tools: ExtractedTool[];\n resources: ExtractedResource[];\n resourceTemplates: ExtractedResourceTemplate[];\n prompts: ExtractedPrompt[];\n jobs: ExtractedJob[];\n capabilities: ExtractedCapabilities;\n}\n\n/** Known system tool names injected by SDK features (jobs, workflows). */\nexport const SYSTEM_TOOL_NAMES = new Set([\n 'list-jobs',\n 'execute-job',\n 'get-job-status',\n 'register-job',\n 'remove-job',\n 'list-workflows',\n 'execute-workflow',\n 'get-workflow-status',\n 'register-workflow',\n 'remove-workflow',\n]);\n\n/**\n * Extract schemas from a compiled server bundle.\n * Requires the bundle to export a FrontMcp-decorated class as default export\n * or a config object usable by connect().\n */\nexport async function extractSchemas(bundlePath: string): Promise<ExtractedSchema> {\n // Suppress @FrontMcp() decorator bootstrap — we only need metadata, not a running server\n const prev = process.env['FRONTMCP_SCHEMA_EXTRACT'];\n process.env['FRONTMCP_SCHEMA_EXTRACT'] = '1';\n\n let mod: Record<string, unknown>;\n try {\n mod = require(bundlePath);\n } finally {\n if (prev === undefined) {\n delete process.env['FRONTMCP_SCHEMA_EXTRACT'];\n } else {\n process.env['FRONTMCP_SCHEMA_EXTRACT'] = prev;\n }\n }\n\n const configOrClass = mod.default || mod;\n\n // Use @frontmcp/sdk connect() to boot in-memory client\n let connect: (config: unknown, options?: { mode?: string }) => Promise<unknown>;\n try {\n const sdk = require('@frontmcp/sdk');\n connect = sdk.connect || sdk.direct?.connect;\n if (!connect) {\n throw new Error('connect() not found in @frontmcp/sdk');\n }\n } catch {\n throw new Error(\n '@frontmcp/sdk is required for CLI schema extraction. Ensure it is installed.',\n );\n }\n\n const client = await connect(configOrClass, { mode: 'cli' }) as {\n listTools(): Promise<unknown>;\n listResources(): Promise<{ resources: Array<{ uri: string; name?: string; description?: string; mimeType?: string }> }>;\n listResourceTemplates?(): Promise<{ resourceTemplates: Array<{ uriTemplate: string; name?: string; description?: string }> }>;\n listPrompts(): Promise<{ prompts: Array<{ name: string; description?: string; arguments?: unknown[] }> }>;\n listJobs?(): Promise<{ jobs: Array<{ name: string; description?: string; inputSchema?: Record<string, unknown>; tags?: string[] }>; count: number }>;\n close(): Promise<void>;\n };\n\n try {\n const [toolsRaw, resourcesResult, promptsResult] = await Promise.all([\n client.listTools().catch(() => []),\n client.listResources().catch(() => ({ resources: [] })),\n client.listPrompts().catch(() => ({ prompts: [] })),\n ]);\n\n let resourceTemplates: ExtractedResourceTemplate[] = [];\n if (client.listResourceTemplates) {\n try {\n const templatesResult = await client.listResourceTemplates();\n resourceTemplates = (templatesResult.resourceTemplates || []).map((t) => ({\n uriTemplate: t.uriTemplate,\n name: t.name || t.uriTemplate,\n description: t.description,\n }));\n } catch {\n // Resource templates not supported\n }\n }\n\n // DirectClient.listTools() returns FormattedTools (array) directly,\n // not { tools: [...] } like the raw MCP client\n const toolsList = Array.isArray(toolsRaw)\n ? toolsRaw as Array<{ name: string; description?: string; inputSchema?: unknown }>\n : ((toolsRaw as { tools?: unknown[] })?.tools || []) as Array<{ name: string; description?: string; inputSchema?: unknown }>;\n\n const tools: ExtractedTool[] = toolsList.map((t) => ({\n name: t.name,\n description: t.description || '',\n inputSchema: (t.inputSchema as Record<string, unknown>) || { type: 'object', properties: {} },\n }));\n\n const resources: ExtractedResource[] = (resourcesResult.resources || []).map((r) => ({\n uri: r.uri,\n name: r.name || r.uri,\n description: r.description,\n mimeType: r.mimeType,\n }));\n\n const prompts: ExtractedPrompt[] = (promptsResult.prompts || []).map((p) => ({\n name: p.name,\n description: p.description,\n arguments: p.arguments as ExtractedPrompt['arguments'],\n }));\n\n const toolNameSet = new Set(tools.map((t) => t.name));\n const hasSkillsResources = resourceTemplates.some(\n (rt) => rt.uriTemplate.startsWith('skills://'),\n );\n const capabilities: ExtractedCapabilities = {\n skills: hasSkillsResources,\n jobs: toolNameSet.has('execute-job') || toolNameSet.has('get-job-status'),\n workflows: toolNameSet.has('execute-workflow') || toolNameSet.has('get-workflow-status'),\n };\n\n // Extract job schemas if jobs capability is available\n let jobs: ExtractedJob[] = [];\n if (capabilities.jobs && client.listJobs) {\n try {\n const jobsResult = await client.listJobs();\n jobs = (jobsResult.jobs || []).map((j) => ({\n name: j.name,\n description: j.description,\n inputSchema: j.inputSchema,\n tags: j.tags,\n }));\n } catch {\n // Jobs listing not available at build time\n }\n }\n\n return { tools, resources, resourceTemplates, prompts, jobs, capabilities };\n } finally {\n await client.close().catch(() => {});\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"schema-extractor.js","sourceRoot":"","sources":["../../../../../../src/commands/build/exec/cli-runtime/schema-extractor.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAqFH,wCAsIC;AAzJD,0EAA0E;AAC7D,QAAA,iBAAiB,GAAG,IAAI,GAAG,CAAC;IACvC,WAAW;IACX,aAAa;IACb,gBAAgB;IAChB,cAAc;IACd,YAAY;IACZ,gBAAgB;IAChB,kBAAkB;IAClB,qBAAqB;IACrB,mBAAmB;IACnB,iBAAiB;CAClB,CAAC,CAAC;AAEH;;;;GAIG;AACI,KAAK,UAAU,cAAc,CAAC,UAAkB;IACrD,yFAAyF;IACzF,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;IACpD,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,GAAG,GAAG,CAAC;IAE7C,IAAI,GAA4B,CAAC;IACjC,IAAI,CAAC;QACH,GAAG,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC5B,CAAC;YAAS,CAAC;QACT,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,OAAO,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;QAChD,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,GAAG,IAAI,CAAC;QAChD,CAAC;IACH,CAAC;IAED,MAAM,aAAa,GAAG,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC;IAEzC,uDAAuD;IACvD,IAAI,OAA2E,CAAC;IAChF,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;QACrC,OAAO,GAAG,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;QAC7C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,8EAA8E,CAC/E,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,aAAa,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAQ1D,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,CAAC,QAAQ,EAAE,eAAe,EAAE,aAAa,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACnE,MAAM,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC;YAClC,MAAM,CAAC,aAAa,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC;YACvD,MAAM,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;SACpD,CAAC,CAAC;QAEH,IAAI,iBAAiB,GAAgC,EAAE,CAAC;QACxD,IAAI,MAAM,CAAC,qBAAqB,EAAE,CAAC;YACjC,IAAI,CAAC;gBACH,MAAM,eAAe,GAAG,MAAM,MAAM,CAAC,qBAAqB,EAAE,CAAC;gBAC7D,iBAAiB,GAAG,CAAC,eAAe,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBACxE,WAAW,EAAE,CAAC,CAAC,WAAW;oBAC1B,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,WAAW;oBAC7B,WAAW,EAAE,CAAC,CAAC,WAAW;iBAC3B,CAAC,CAAC,CAAC;YACN,CAAC;YAAC,MAAM,CAAC;gBACP,mCAAmC;YACrC,CAAC;QACH,CAAC;QAED,oEAAoE;QACpE,+CAA+C;QAC/C,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;YACvC,CAAC,CAAC,QAAgF;YAClF,CAAC,CAAC,CAAE,QAAkC,EAAE,KAAK,IAAI,EAAE,CAAyE,CAAC;QAE/H,MAAM,KAAK,GAAoB,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACnD,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,WAAW,EAAE,CAAC,CAAC,WAAW,IAAI,EAAE;YAChC,WAAW,EAAG,CAAC,CAAC,WAAuC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE;SAC9F,CAAC,CAAC,CAAC;QAEJ,MAAM,SAAS,GAAwB,CAAC,eAAe,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACnF,GAAG,EAAE,CAAC,CAAC,GAAG;YACV,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG;YACrB,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,QAAQ,EAAE,CAAC,CAAC,QAAQ;SACrB,CAAC,CAAC,CAAC;QAEJ,MAAM,OAAO,GAAsB,CAAC,aAAa,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC3E,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,SAAS,EAAE,CAAC,CAAC,SAAyC;SACvD,CAAC,CAAC,CAAC;QAEJ,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACtD,MAAM,kBAAkB,GAAG,iBAAiB,CAAC,IAAI,CAC/C,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,UAAU,CAAC,WAAW,CAAC,CAC/C,CAAC;QACF,MAAM,YAAY,GAA0B;YAC1C,MAAM,EAAE,kBAAkB;YAC1B,IAAI,EAAE,WAAW,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,GAAG,CAAC,gBAAgB,CAAC;YACzE,SAAS,EAAE,WAAW,CAAC,GAAG,CAAC,kBAAkB,CAAC,IAAI,WAAW,CAAC,GAAG,CAAC,qBAAqB,CAAC;SACzF,CAAC;QAEF,sDAAsD;QACtD,IAAI,IAAI,GAAmB,EAAE,CAAC;QAC9B,IAAI,YAAY,CAAC,IAAI,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACzC,IAAI,CAAC;gBACH,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,QAAQ,EAAE,CAAC;gBAC3C,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBACzC,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,WAAW,EAAE,CAAC,CAAC,WAAW;oBAC1B,WAAW,EAAE,CAAC,CAAC,WAAW;oBAC1B,IAAI,EAAE,CAAC,CAAC,IAAI;iBACb,CAAC,CAAC,CAAC;YACN,CAAC;YAAC,MAAM,CAAC;gBACP,2CAA2C;YAC7C,CAAC;QACH,CAAC;QAED,gDAAgD;QAChD,IAAI,WAAW,GAA0B,EAAE,CAAC;QAC5C,IAAI,YAAY,CAAC,MAAM,IAAI,MAAM,CAAC,kBAAkB,EAAE,CAAC;YACrD,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,kBAAkB,EAAE,CAAC;gBACnD,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBACzC,SAAS,EAAE,CAAC,CAAC,SAAS;oBACtB,OAAO,EAAE,CAAC,CAAC,OAAO;oBAClB,eAAe,EAAE,CAAC,CAAC,eAAe;oBAClC,YAAY,EAAE,CAAC,CAAC,SAAgD;iBACjE,CAAC,CAAC,CAAC;YACN,CAAC;YAAC,MAAM,CAAC;gBACP,uCAAuC;YACzC,CAAC;QACH,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,iBAAiB,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC;IAC3F,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACvC,CAAC;AACH,CAAC","sourcesContent":["/**\n * Build-time schema extraction.\n * After the server bundle is produced, boots a DirectClient via connect(),\n * extracts tool/resource/prompt schemas, and serializes them for CLI code generation.\n */\n\nexport interface ExtractedTool {\n name: string;\n description: string;\n inputSchema: Record<string, unknown>;\n}\n\nexport interface ExtractedResource {\n uri: string;\n name: string;\n description?: string;\n mimeType?: string;\n}\n\nexport interface ExtractedResourceTemplate {\n uriTemplate: string;\n name: string;\n description?: string;\n}\n\nexport interface ExtractedPrompt {\n name: string;\n description?: string;\n arguments?: Array<{\n name: string;\n description?: string;\n required?: boolean;\n }>;\n}\n\nexport interface ExtractedJob {\n name: string;\n description?: string;\n inputSchema?: Record<string, unknown>;\n tags?: string[];\n}\n\nexport interface ExtractedCapabilities {\n skills: boolean;\n jobs: boolean;\n workflows: boolean;\n}\n\nexport interface ExtractedSkillAsset {\n skillName: string;\n baseDir?: string;\n instructionFile?: string;\n resourceDirs?: {\n references?: string;\n examples?: string;\n scripts?: string;\n assets?: string;\n };\n}\n\nexport interface ExtractedSchema {\n tools: ExtractedTool[];\n resources: ExtractedResource[];\n resourceTemplates: ExtractedResourceTemplate[];\n prompts: ExtractedPrompt[];\n jobs: ExtractedJob[];\n capabilities: ExtractedCapabilities;\n skillAssets: ExtractedSkillAsset[];\n}\n\n/** Known system tool names injected by SDK features (jobs, workflows). */\nexport const SYSTEM_TOOL_NAMES = new Set([\n 'list-jobs',\n 'execute-job',\n 'get-job-status',\n 'register-job',\n 'remove-job',\n 'list-workflows',\n 'execute-workflow',\n 'get-workflow-status',\n 'register-workflow',\n 'remove-workflow',\n]);\n\n/**\n * Extract schemas from a compiled server bundle.\n * Requires the bundle to export a FrontMcp-decorated class as default export\n * or a config object usable by connect().\n */\nexport async function extractSchemas(bundlePath: string): Promise<ExtractedSchema> {\n // Suppress @FrontMcp() decorator bootstrap — we only need metadata, not a running server\n const prev = process.env['FRONTMCP_SCHEMA_EXTRACT'];\n process.env['FRONTMCP_SCHEMA_EXTRACT'] = '1';\n\n let mod: Record<string, unknown>;\n try {\n mod = require(bundlePath);\n } finally {\n if (prev === undefined) {\n delete process.env['FRONTMCP_SCHEMA_EXTRACT'];\n } else {\n process.env['FRONTMCP_SCHEMA_EXTRACT'] = prev;\n }\n }\n\n const configOrClass = mod.default || mod;\n\n // Use @frontmcp/sdk connect() to boot in-memory client\n let connect: (config: unknown, options?: { mode?: string }) => Promise<unknown>;\n try {\n const sdk = require('@frontmcp/sdk');\n connect = sdk.connect || sdk.direct?.connect;\n if (!connect) {\n throw new Error('connect() not found in @frontmcp/sdk');\n }\n } catch {\n throw new Error(\n '@frontmcp/sdk is required for CLI schema extraction. Ensure it is installed.',\n );\n }\n\n const client = await connect(configOrClass, { mode: 'cli' }) as {\n listTools(): Promise<unknown>;\n listResources(): Promise<{ resources: Array<{ uri: string; name?: string; description?: string; mimeType?: string }> }>;\n listResourceTemplates?(): Promise<{ resourceTemplates: Array<{ uriTemplate: string; name?: string; description?: string }> }>;\n listPrompts(): Promise<{ prompts: Array<{ name: string; description?: string; arguments?: unknown[] }> }>;\n listJobs?(): Promise<{ jobs: Array<{ name: string; description?: string; inputSchema?: Record<string, unknown>; tags?: string[] }>; count: number }>;\n collectSkillAssets?(): Promise<{ entries: Array<{ skillName: string; baseDir?: string; instructionFile?: string; resources?: Record<string, string | undefined> }> }>;\n close(): Promise<void>;\n };\n\n try {\n const [toolsRaw, resourcesResult, promptsResult] = await Promise.all([\n client.listTools().catch(() => []),\n client.listResources().catch(() => ({ resources: [] })),\n client.listPrompts().catch(() => ({ prompts: [] })),\n ]);\n\n let resourceTemplates: ExtractedResourceTemplate[] = [];\n if (client.listResourceTemplates) {\n try {\n const templatesResult = await client.listResourceTemplates();\n resourceTemplates = (templatesResult.resourceTemplates || []).map((t) => ({\n uriTemplate: t.uriTemplate,\n name: t.name || t.uriTemplate,\n description: t.description,\n }));\n } catch {\n // Resource templates not supported\n }\n }\n\n // DirectClient.listTools() returns FormattedTools (array) directly,\n // not { tools: [...] } like the raw MCP client\n const toolsList = Array.isArray(toolsRaw)\n ? toolsRaw as Array<{ name: string; description?: string; inputSchema?: unknown }>\n : ((toolsRaw as { tools?: unknown[] })?.tools || []) as Array<{ name: string; description?: string; inputSchema?: unknown }>;\n\n const tools: ExtractedTool[] = toolsList.map((t) => ({\n name: t.name,\n description: t.description || '',\n inputSchema: (t.inputSchema as Record<string, unknown>) || { type: 'object', properties: {} },\n }));\n\n const resources: ExtractedResource[] = (resourcesResult.resources || []).map((r) => ({\n uri: r.uri,\n name: r.name || r.uri,\n description: r.description,\n mimeType: r.mimeType,\n }));\n\n const prompts: ExtractedPrompt[] = (promptsResult.prompts || []).map((p) => ({\n name: p.name,\n description: p.description,\n arguments: p.arguments as ExtractedPrompt['arguments'],\n }));\n\n const toolNameSet = new Set(tools.map((t) => t.name));\n const hasSkillsResources = resourceTemplates.some(\n (rt) => rt.uriTemplate.startsWith('skills://'),\n );\n const capabilities: ExtractedCapabilities = {\n skills: hasSkillsResources,\n jobs: toolNameSet.has('execute-job') || toolNameSet.has('get-job-status'),\n workflows: toolNameSet.has('execute-workflow') || toolNameSet.has('get-workflow-status'),\n };\n\n // Extract job schemas if jobs capability is available\n let jobs: ExtractedJob[] = [];\n if (capabilities.jobs && client.listJobs) {\n try {\n const jobsResult = await client.listJobs();\n jobs = (jobsResult.jobs || []).map((j) => ({\n name: j.name,\n description: j.description,\n inputSchema: j.inputSchema,\n tags: j.tags,\n }));\n } catch {\n // Jobs listing not available at build time\n }\n }\n\n // Collect skill file assets for copying to dist\n let skillAssets: ExtractedSkillAsset[] = [];\n if (capabilities.skills && client.collectSkillAssets) {\n try {\n const manifest = await client.collectSkillAssets();\n skillAssets = manifest.entries.map((e) => ({\n skillName: e.skillName,\n baseDir: e.baseDir,\n instructionFile: e.instructionFile,\n resourceDirs: e.resources as ExtractedSkillAsset['resourceDirs'],\n }));\n } catch {\n // Skill asset collection not available\n }\n }\n\n return { tools, resources, resourceTemplates, prompts, jobs, capabilities, skillAssets };\n } finally {\n await client.close().catch(() => {});\n }\n}\n"]}
|
|
@@ -116,6 +116,45 @@ async function buildExec(opts) {
|
|
|
116
116
|
console.log(`${(0, colors_1.c)('cyan', '[build:exec]')} capability: jobs`);
|
|
117
117
|
if (capabilities.workflows)
|
|
118
118
|
console.log(`${(0, colors_1.c)('cyan', '[build:exec]')} capability: workflows`);
|
|
119
|
+
// Copy skill content files into _skills/ directory with a manifest.
|
|
120
|
+
// Uses a flat structure to avoid path traversal issues when skills
|
|
121
|
+
// reference files outside their own directory (e.g., '../../../docs/guide.md').
|
|
122
|
+
if (schema.skillAssets.length > 0) {
|
|
123
|
+
const skillsDir = path.join(outDir, '_skills');
|
|
124
|
+
fs.mkdirSync(skillsDir, { recursive: true });
|
|
125
|
+
const manifest = {};
|
|
126
|
+
let copiedCount = 0;
|
|
127
|
+
for (const asset of schema.skillAssets) {
|
|
128
|
+
const entry = {};
|
|
129
|
+
// Copy instruction file
|
|
130
|
+
if (asset.instructionFile && fs.existsSync(asset.instructionFile)) {
|
|
131
|
+
const filename = path.basename(asset.instructionFile);
|
|
132
|
+
const dest = path.join(skillsDir, `${asset.skillName}--${filename}`);
|
|
133
|
+
fs.copyFileSync(asset.instructionFile, dest);
|
|
134
|
+
entry.instructions = `_skills/${asset.skillName}--${filename}`;
|
|
135
|
+
copiedCount++;
|
|
136
|
+
}
|
|
137
|
+
// Copy resource directories
|
|
138
|
+
if (asset.resourceDirs) {
|
|
139
|
+
for (const [key, dirPath] of Object.entries(asset.resourceDirs)) {
|
|
140
|
+
if (dirPath && fs.existsSync(dirPath) && fs.statSync(dirPath).isDirectory()) {
|
|
141
|
+
const destDir = path.join(skillsDir, `${asset.skillName}--${key}`);
|
|
142
|
+
fs.cpSync(dirPath, destDir, { recursive: true });
|
|
143
|
+
entry[key] = `_skills/${asset.skillName}--${key}`;
|
|
144
|
+
copiedCount++;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if (Object.keys(entry).length > 0) {
|
|
149
|
+
manifest[asset.skillName] = entry;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
// Write manifest so runtime can resolve paths
|
|
153
|
+
fs.writeFileSync(path.join(skillsDir, 'manifest.json'), JSON.stringify(manifest, null, 2));
|
|
154
|
+
if (copiedCount > 0) {
|
|
155
|
+
console.log(`${(0, colors_1.c)('green', '[build:exec]')} copied ${copiedCount} skill content file(s) to _skills/`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
119
158
|
// Log tool name conflicts
|
|
120
159
|
const cliConfig = config.cli || { enabled: true };
|
|
121
160
|
const excludeTools = cliConfig.excludeTools || [];
|
|
@@ -228,6 +267,7 @@ async function buildExec(opts) {
|
|
|
228
267
|
`install-${config.name}.sh`,
|
|
229
268
|
`${config.name}-bin`,
|
|
230
269
|
`${config.name}-cli-bin`,
|
|
270
|
+
'_skills',
|
|
231
271
|
]);
|
|
232
272
|
const allFiles = fs.readdirSync(outDir);
|
|
233
273
|
let cleaned = 0;
|
|
@@ -235,7 +275,8 @@ async function buildExec(opts) {
|
|
|
235
275
|
if (!keepFiles.has(file)) {
|
|
236
276
|
const filePath = path.join(outDir, file);
|
|
237
277
|
const stat = fs.statSync(filePath);
|
|
238
|
-
|
|
278
|
+
// Only clean intermediate compiled files; preserve .md and _skills/ directory
|
|
279
|
+
if (stat.isFile() && !file.endsWith('.md')) {
|
|
239
280
|
fs.unlinkSync(filePath);
|
|
240
281
|
cleaned++;
|
|
241
282
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/commands/build/exec/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * buildExec() orchestrator — produces a distributable bundle from a FrontMCP app.\n *\n * Output (server-only mode):\n * dist/{name}.bundle.js — esbuild single-file bundle\n * dist/{name}.manifest.json — app metadata (runtime reqs, setup questions)\n * dist/{name} — bash runner script\n * dist/install-{name}.sh — bash installer script\n *\n * Output (CLI mode, --cli flag):\n * All of the above, plus:\n * dist/{name}-cli.bundle.js — CLI executable bundle (commander.js)\n * dist/{name} — bash runner dispatches to CLI bundle\n */\n\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport { ParsedArgs } from '../../../core/args';\nimport { c } from '../../../core/colors';\nimport { resolveEntry } from '../../../shared/fs';\nimport { loadExecConfig, normalizeConfig } from './config';\nimport { bundleWithEsbuild, formatSize } from './esbuild-bundler';\nimport { generateManifest } from './manifest';\nimport { generateRunnerScript } from './runner-script';\nimport { generateInstallerScript } from './installer-script';\nimport { validateStepGraph } from './setup';\nimport { ensureDir, fileExists, runCmd } from '@frontmcp/utils';\nimport { REQUIRED_DECORATOR_FIELDS } from '../../../core/tsconfig';\n\nexport async function buildExec(opts: ParsedArgs & { cli?: boolean; sea?: boolean }): Promise<void> {\n const cwd = process.cwd();\n const outDir = path.resolve(cwd, opts.outDir || 'dist');\n\n console.log(`${c('cyan', '[build:exec]')} Building executable bundle...`);\n\n // 1. Load config\n const rawConfig = await loadExecConfig(cwd);\n const config = normalizeConfig(rawConfig);\n const cliEnabled = opts.cli || config.cli?.enabled;\n const seaEnabled = opts.sea || config.sea?.enabled;\n\n console.log(`${c('cyan', '[build:exec]')} name: ${config.name}`);\n console.log(`${c('cyan', '[build:exec]')} version: ${config.version}`);\n if (cliEnabled) {\n console.log(`${c('cyan', '[build:exec]')} CLI mode: enabled`);\n }\n if (seaEnabled) {\n console.log(`${c('cyan', '[build:exec]')} SEA mode: enabled (single executable)`);\n }\n\n // 2. Resolve entry\n const entry = await resolveEntry(cwd, config.entry || opts.entry);\n console.log(`${c('cyan', '[build:exec]')} entry: ${path.relative(cwd, entry)}`);\n\n // 3. Validate setup graph if present\n if (config.setup?.steps) {\n console.log(\n `${c('cyan', '[build:exec]')} validating setup questionnaire (${config.setup.steps.length} steps)...`,\n );\n const errors = validateStepGraph(config.setup.steps);\n const realErrors = errors.filter((e) => !e.startsWith('Warning:'));\n const warnings = errors.filter((e) => e.startsWith('Warning:'));\n\n for (const w of warnings) {\n console.log(`${c('yellow', '[build:exec]')} ${w}`);\n }\n if (realErrors.length > 0) {\n for (const e of realErrors) {\n console.error(`${c('red', '[build:exec]')} ${e}`);\n }\n throw new Error('Setup questionnaire has validation errors. Fix them before building.');\n }\n }\n\n // 4. Compile TypeScript\n console.log(`${c('cyan', '[build:exec]')} compiling TypeScript...`);\n await ensureDir(outDir);\n\n const tsconfigPath = path.join(cwd, 'tsconfig.json');\n const hasTsconfig = await fileExists(tsconfigPath);\n const tscArgs: string[] = ['-y', 'tsc'];\n\n if (hasTsconfig) {\n tscArgs.push('--project', tsconfigPath);\n } else {\n tscArgs.push(entry);\n tscArgs.push('--rootDir', path.dirname(entry));\n tscArgs.push('--experimentalDecorators', '--emitDecoratorMetadata');\n tscArgs.push('--target', REQUIRED_DECORATOR_FIELDS.target);\n }\n\n tscArgs.push('--module', 'commonjs');\n tscArgs.push('--outDir', outDir);\n tscArgs.push('--skipLibCheck');\n\n await runCmd('npx', tscArgs);\n console.log(`${c('green', '[build:exec]')} TypeScript compiled.`);\n\n // 5. Bundle with esbuild\n console.log(`${c('cyan', '[build:exec]')} bundling with esbuild...`);\n const compiledEntry = path.join(\n outDir,\n path.basename(entry).replace(/\\.tsx?$/, '.js'),\n );\n\n // Always build non-self-contained first (schema extraction needs host SDK)\n const bundleResult = await bundleWithEsbuild(compiledEntry, outDir, config);\n console.log(\n `${c('green', '[build:exec]')} bundle created: ${path.relative(cwd, bundleResult.bundlePath)} (${formatSize(bundleResult.bundleSize)})`,\n );\n\n // 6. Generate manifest\n const bundleFilename = `${config.name}.bundle.js`;\n const manifest = generateManifest(config, bundleFilename);\n\n // 7. CLI build step (if enabled)\n let cliBundlePath: string | undefined;\n if (cliEnabled) {\n console.log(`${c('cyan', '[build:exec]')} extracting schemas for CLI...`);\n\n const { extractSchemas, SYSTEM_TOOL_NAMES } = await import('./cli-runtime/schema-extractor.js');\n const { generateCliEntry, resolveToolCommandName } = await import('./cli-runtime/generate-cli-entry.js');\n const { generateOutputFormatterSource } = await import('./cli-runtime/output-formatter.js');\n const { generateSessionManagerSource } = await import('./cli-runtime/session-manager.js');\n const { generateCredentialStoreSource } = await import('./cli-runtime/credential-store.js');\n const { generateOAuthHelperSource } = await import('./cli-runtime/oauth-helper.js');\n const { generateDaemonClientSource } = await import('./cli-runtime/daemon-client.js');\n const { bundleCliWithEsbuild } = await import('./cli-runtime/cli-bundler.js');\n\n // Extract schemas from server bundle\n const schema = await extractSchemas(bundleResult.bundlePath);\n\n const capabilities = schema.capabilities;\n const userToolCount = schema.tools.filter(\n (t) => !SYSTEM_TOOL_NAMES.has(t.name),\n ).length;\n\n console.log(\n `${c('cyan', '[build:exec]')} extracted: ${schema.tools.length} tools (${userToolCount} user), ${schema.resources.length} resources, ${schema.resourceTemplates.length} templates, ${schema.prompts.length} prompts`,\n );\n if (capabilities.skills) console.log(`${c('cyan', '[build:exec]')} capability: skills`);\n if (capabilities.jobs) console.log(`${c('cyan', '[build:exec]')} capability: jobs`);\n if (capabilities.workflows) console.log(`${c('cyan', '[build:exec]')} capability: workflows`);\n\n // Log tool name conflicts\n const cliConfig = config.cli || { enabled: true };\n const excludeTools = cliConfig.excludeTools || [];\n schema.tools\n .filter((t) => !excludeTools.includes(t.name))\n .forEach((t) => {\n const { wasRenamed, cmdName } = resolveToolCommandName(t.name);\n if (wasRenamed) {\n console.log(\n `${c('yellow', '[build:exec]')} Tool \"${t.name}\" conflicts with built-in command, mapped to \"${cmdName}\"`,\n );\n }\n });\n\n // Generate runtime modules\n const outputDefault = cliConfig.outputDefault || 'text';\n const authRequired = cliConfig.authRequired ?? false;\n const nativeDeps = cliConfig.nativeDeps || {};\n const oauthConfig = cliConfig.oauth;\n\n // Write runtime modules to temp files for bundling\n const tempDir = path.join(outDir, '__cli_temp');\n fs.mkdirSync(tempDir, { recursive: true });\n\n fs.writeFileSync(\n path.join(tempDir, 'output-formatter.js'),\n generateOutputFormatterSource(),\n );\n fs.writeFileSync(\n path.join(tempDir, 'session-manager.js'),\n generateSessionManagerSource(config.name),\n );\n fs.writeFileSync(\n path.join(tempDir, 'credential-store.js'),\n generateCredentialStoreSource(config.name),\n );\n fs.writeFileSync(\n path.join(tempDir, 'oauth-helper.js'),\n generateOAuthHelperSource(config.name),\n );\n fs.writeFileSync(\n path.join(tempDir, 'daemon-client.js'),\n generateDaemonClientSource(),\n );\n\n // Generate CLI entry\n const cliEntrySource = generateCliEntry({\n appName: config.name,\n appVersion: config.version || '1.0.0',\n description: cliConfig.description || `${config.name} CLI`,\n serverBundleFilename: bundleFilename,\n outputDefault,\n authRequired,\n excludeTools,\n nativeDeps,\n schema,\n oauthConfig,\n selfContained: !!seaEnabled,\n });\n\n const cliEntryPath = path.join(tempDir, 'cli-entry.js');\n fs.writeFileSync(cliEntryPath, cliEntrySource);\n\n // Bundle CLI\n console.log(`${c('cyan', '[build:exec]')} bundling CLI...`);\n const cliResult = await bundleCliWithEsbuild(cliEntryPath, outDir, config, {\n selfContained: !!seaEnabled,\n });\n cliBundlePath = cliResult.bundlePath;\n console.log(\n `${c('green', '[build:exec]')} CLI bundle: ${path.relative(cwd, cliResult.bundlePath)} (${formatSize(cliResult.bundleSize)})`,\n );\n\n // Clean temp\n fs.rmSync(tempDir, { recursive: true, force: true });\n\n // Extend manifest with CLI metadata\n manifest.cli = {\n enabled: true,\n cliBundle: `${config.name}-cli.bundle.js`,\n outputDefault,\n authRequired,\n toolCount: userToolCount,\n resourceCount: schema.resources.length,\n templateCount: schema.resourceTemplates.length,\n promptCount: schema.prompts.length,\n oauthEnabled: !!oauthConfig,\n skillsEnabled: capabilities.skills || undefined,\n jobsEnabled: capabilities.jobs || undefined,\n workflowsEnabled: capabilities.workflows || undefined,\n };\n }\n\n // 8. Build SEA binaries if enabled\n let seaServerResult: { executablePath: string; executableSize: number } | undefined;\n let seaCliResult: { executablePath: string; executableSize: number } | undefined;\n if (seaEnabled) {\n const { buildSea } = await import('./sea-builder.js');\n\n // Rebuild server bundle as self-contained for SEA (inlines all deps)\n // Use a temp filename so the original non-self-contained bundle is preserved\n const seaTempName = `${config.name}.sea-temp`;\n console.log(`${c('cyan', '[build:sea]')} rebuilding server bundle (self-contained)...`);\n const seaBundle = await bundleWithEsbuild(compiledEntry, outDir, config, {\n selfContained: true,\n outputName: seaTempName,\n });\n\n console.log(`${c('cyan', '[build:sea]')} building server SEA binary...`);\n seaServerResult = await buildSea(seaBundle.bundlePath, outDir, config.name);\n // Clean up temp self-contained bundle\n fs.unlinkSync(seaBundle.bundlePath);\n console.log(\n `${c('green', '[build:sea]')} server binary: ${path.relative(cwd, seaServerResult.executablePath)} (${formatSize(seaServerResult.executableSize)})`,\n );\n\n if (cliBundlePath) {\n console.log(`${c('cyan', '[build:sea]')} building CLI SEA binary...`);\n seaCliResult = await buildSea(cliBundlePath, outDir, `${config.name}-cli`);\n console.log(\n `${c('green', '[build:sea]')} CLI binary: ${path.relative(cwd, seaCliResult.executablePath)} (${formatSize(seaCliResult.executableSize)})`,\n );\n }\n }\n\n // 9. Write manifest\n const manifestPath = path.join(outDir, `${config.name}.manifest.json`);\n fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), 'utf-8');\n console.log(\n `${c('green', '[build:exec]')} manifest: ${path.relative(cwd, manifestPath)}`,\n );\n\n // 10. Generate runner script (dispatches to CLI bundle or SEA binary)\n const runnerContent = generateRunnerScript(config, !!cliEnabled, !!seaEnabled);\n const runnerPath = path.join(outDir, config.name);\n fs.writeFileSync(runnerPath, runnerContent, { mode: 0o755 });\n console.log(\n `${c('green', '[build:exec]')} runner: ${path.relative(cwd, runnerPath)}`,\n );\n\n // 10. Generate installer script\n const installerContent = generateInstallerScript(config);\n const installerPath = path.join(outDir, `install-${config.name}.sh`);\n fs.writeFileSync(installerPath, installerContent, { mode: 0o755 });\n console.log(\n `${c('green', '[build:exec]')} installer: ${path.relative(cwd, installerPath)}`,\n );\n\n // 12. Clean up intermediate compiled files\n const keepFiles = new Set([\n `${config.name}.bundle.js`,\n `${config.name}-cli.bundle.js`,\n `${config.name}.manifest.json`,\n config.name,\n `install-${config.name}.sh`,\n `${config.name}-bin`,\n `${config.name}-cli-bin`,\n ]);\n\n const allFiles = fs.readdirSync(outDir);\n let cleaned = 0;\n for (const file of allFiles) {\n if (!keepFiles.has(file)) {\n const filePath = path.join(outDir, file);\n const stat = fs.statSync(filePath);\n if (stat.isFile()) {\n fs.unlinkSync(filePath);\n cleaned++;\n }\n }\n }\n if (cleaned > 0) {\n console.log(\n `${c('gray', '[build:exec]')} cleaned ${cleaned} intermediate file(s)`,\n );\n }\n\n // 13. Print summary\n console.log(`\\n${c('green', 'Executable build completed.')}`);\n console.log(`\\n${c('bold', 'Output:')}`);\n console.log(` ${path.relative(cwd, bundleResult.bundlePath)} ${c('gray', `(${formatSize(bundleResult.bundleSize)})`)}`);\n if (cliBundlePath) {\n const cliStat = fs.statSync(cliBundlePath);\n console.log(` ${path.relative(cwd, cliBundlePath)} ${c('gray', `(${formatSize(cliStat.size)})`)}`);\n }\n if (seaServerResult) {\n console.log(` ${path.relative(cwd, seaServerResult.executablePath)} ${c('gray', `(${formatSize(seaServerResult.executableSize)})`)}`);\n }\n if (seaCliResult) {\n console.log(` ${path.relative(cwd, seaCliResult.executablePath)} ${c('gray', `(${formatSize(seaCliResult.executableSize)})`)}`);\n }\n console.log(` ${path.relative(cwd, manifestPath)}`);\n console.log(` ${path.relative(cwd, runnerPath)}`);\n console.log(` ${path.relative(cwd, installerPath)}`);\n\n if (cliEnabled) {\n console.log(`\\n${c('gray', 'Run the CLI:')} ./${path.relative(cwd, runnerPath)} --help`);\n console.log(`${c('gray', 'Start server:')} ./${path.relative(cwd, runnerPath)} serve`);\n } else {\n console.log(`\\n${c('gray', 'Run the server:')} ./${path.relative(cwd, runnerPath)}`);\n }\n if (seaServerResult || seaCliResult) {\n console.log(`\\n${c('yellow', 'Note:')} SEA binaries are native executables. Run directly (not via bash).`);\n }\n console.log(`${c('gray', 'Install to system:')} bash ./${path.relative(cwd, installerPath)}`);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/commands/build/exec/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * buildExec() orchestrator — produces a distributable bundle from a FrontMCP app.\n *\n * Output (server-only mode):\n * dist/{name}.bundle.js — esbuild single-file bundle\n * dist/{name}.manifest.json — app metadata (runtime reqs, setup questions)\n * dist/{name} — bash runner script\n * dist/install-{name}.sh — bash installer script\n *\n * Output (CLI mode, --cli flag):\n * All of the above, plus:\n * dist/{name}-cli.bundle.js — CLI executable bundle (commander.js)\n * dist/{name} — bash runner dispatches to CLI bundle\n */\n\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport { ParsedArgs } from '../../../core/args';\nimport { c } from '../../../core/colors';\nimport { resolveEntry } from '../../../shared/fs';\nimport { loadExecConfig, normalizeConfig } from './config';\nimport { bundleWithEsbuild, formatSize } from './esbuild-bundler';\nimport { generateManifest } from './manifest';\nimport { generateRunnerScript } from './runner-script';\nimport { generateInstallerScript } from './installer-script';\nimport { validateStepGraph } from './setup';\nimport { ensureDir, fileExists, runCmd } from '@frontmcp/utils';\nimport { REQUIRED_DECORATOR_FIELDS } from '../../../core/tsconfig';\n\nexport async function buildExec(opts: ParsedArgs & { cli?: boolean; sea?: boolean }): Promise<void> {\n const cwd = process.cwd();\n const outDir = path.resolve(cwd, opts.outDir || 'dist');\n\n console.log(`${c('cyan', '[build:exec]')} Building executable bundle...`);\n\n // 1. Load config\n const rawConfig = await loadExecConfig(cwd);\n const config = normalizeConfig(rawConfig);\n const cliEnabled = opts.cli || config.cli?.enabled;\n const seaEnabled = opts.sea || config.sea?.enabled;\n\n console.log(`${c('cyan', '[build:exec]')} name: ${config.name}`);\n console.log(`${c('cyan', '[build:exec]')} version: ${config.version}`);\n if (cliEnabled) {\n console.log(`${c('cyan', '[build:exec]')} CLI mode: enabled`);\n }\n if (seaEnabled) {\n console.log(`${c('cyan', '[build:exec]')} SEA mode: enabled (single executable)`);\n }\n\n // 2. Resolve entry\n const entry = await resolveEntry(cwd, config.entry || opts.entry);\n console.log(`${c('cyan', '[build:exec]')} entry: ${path.relative(cwd, entry)}`);\n\n // 3. Validate setup graph if present\n if (config.setup?.steps) {\n console.log(\n `${c('cyan', '[build:exec]')} validating setup questionnaire (${config.setup.steps.length} steps)...`,\n );\n const errors = validateStepGraph(config.setup.steps);\n const realErrors = errors.filter((e) => !e.startsWith('Warning:'));\n const warnings = errors.filter((e) => e.startsWith('Warning:'));\n\n for (const w of warnings) {\n console.log(`${c('yellow', '[build:exec]')} ${w}`);\n }\n if (realErrors.length > 0) {\n for (const e of realErrors) {\n console.error(`${c('red', '[build:exec]')} ${e}`);\n }\n throw new Error('Setup questionnaire has validation errors. Fix them before building.');\n }\n }\n\n // 4. Compile TypeScript\n console.log(`${c('cyan', '[build:exec]')} compiling TypeScript...`);\n await ensureDir(outDir);\n\n const tsconfigPath = path.join(cwd, 'tsconfig.json');\n const hasTsconfig = await fileExists(tsconfigPath);\n const tscArgs: string[] = ['-y', 'tsc'];\n\n if (hasTsconfig) {\n tscArgs.push('--project', tsconfigPath);\n } else {\n tscArgs.push(entry);\n tscArgs.push('--rootDir', path.dirname(entry));\n tscArgs.push('--experimentalDecorators', '--emitDecoratorMetadata');\n tscArgs.push('--target', REQUIRED_DECORATOR_FIELDS.target);\n }\n\n tscArgs.push('--module', 'commonjs');\n tscArgs.push('--outDir', outDir);\n tscArgs.push('--skipLibCheck');\n\n await runCmd('npx', tscArgs);\n console.log(`${c('green', '[build:exec]')} TypeScript compiled.`);\n\n // 5. Bundle with esbuild\n console.log(`${c('cyan', '[build:exec]')} bundling with esbuild...`);\n const compiledEntry = path.join(\n outDir,\n path.basename(entry).replace(/\\.tsx?$/, '.js'),\n );\n\n // Always build non-self-contained first (schema extraction needs host SDK)\n const bundleResult = await bundleWithEsbuild(compiledEntry, outDir, config);\n console.log(\n `${c('green', '[build:exec]')} bundle created: ${path.relative(cwd, bundleResult.bundlePath)} (${formatSize(bundleResult.bundleSize)})`,\n );\n\n // 6. Generate manifest\n const bundleFilename = `${config.name}.bundle.js`;\n const manifest = generateManifest(config, bundleFilename);\n\n // 7. CLI build step (if enabled)\n let cliBundlePath: string | undefined;\n if (cliEnabled) {\n console.log(`${c('cyan', '[build:exec]')} extracting schemas for CLI...`);\n\n const { extractSchemas, SYSTEM_TOOL_NAMES } = await import('./cli-runtime/schema-extractor.js');\n const { generateCliEntry, resolveToolCommandName } = await import('./cli-runtime/generate-cli-entry.js');\n const { generateOutputFormatterSource } = await import('./cli-runtime/output-formatter.js');\n const { generateSessionManagerSource } = await import('./cli-runtime/session-manager.js');\n const { generateCredentialStoreSource } = await import('./cli-runtime/credential-store.js');\n const { generateOAuthHelperSource } = await import('./cli-runtime/oauth-helper.js');\n const { generateDaemonClientSource } = await import('./cli-runtime/daemon-client.js');\n const { bundleCliWithEsbuild } = await import('./cli-runtime/cli-bundler.js');\n\n // Extract schemas from server bundle\n const schema = await extractSchemas(bundleResult.bundlePath);\n\n const capabilities = schema.capabilities;\n const userToolCount = schema.tools.filter(\n (t) => !SYSTEM_TOOL_NAMES.has(t.name),\n ).length;\n\n console.log(\n `${c('cyan', '[build:exec]')} extracted: ${schema.tools.length} tools (${userToolCount} user), ${schema.resources.length} resources, ${schema.resourceTemplates.length} templates, ${schema.prompts.length} prompts`,\n );\n if (capabilities.skills) console.log(`${c('cyan', '[build:exec]')} capability: skills`);\n if (capabilities.jobs) console.log(`${c('cyan', '[build:exec]')} capability: jobs`);\n if (capabilities.workflows) console.log(`${c('cyan', '[build:exec]')} capability: workflows`);\n\n // Copy skill content files into _skills/ directory with a manifest.\n // Uses a flat structure to avoid path traversal issues when skills\n // reference files outside their own directory (e.g., '../../../docs/guide.md').\n if (schema.skillAssets.length > 0) {\n const skillsDir = path.join(outDir, '_skills');\n fs.mkdirSync(skillsDir, { recursive: true });\n\n const manifest: Record<string, { instructions?: string; references?: string; examples?: string; scripts?: string; assets?: string }> = {};\n let copiedCount = 0;\n\n for (const asset of schema.skillAssets) {\n const entry: (typeof manifest)[string] = {};\n\n // Copy instruction file\n if (asset.instructionFile && fs.existsSync(asset.instructionFile)) {\n const filename = path.basename(asset.instructionFile);\n const dest = path.join(skillsDir, `${asset.skillName}--${filename}`);\n fs.copyFileSync(asset.instructionFile, dest);\n entry.instructions = `_skills/${asset.skillName}--${filename}`;\n copiedCount++;\n }\n\n // Copy resource directories\n if (asset.resourceDirs) {\n for (const [key, dirPath] of Object.entries(asset.resourceDirs)) {\n if (dirPath && fs.existsSync(dirPath) && fs.statSync(dirPath).isDirectory()) {\n const destDir = path.join(skillsDir, `${asset.skillName}--${key}`);\n fs.cpSync(dirPath, destDir, { recursive: true });\n entry[key as keyof typeof entry] = `_skills/${asset.skillName}--${key}`;\n copiedCount++;\n }\n }\n }\n\n if (Object.keys(entry).length > 0) {\n manifest[asset.skillName] = entry;\n }\n }\n\n // Write manifest so runtime can resolve paths\n fs.writeFileSync(\n path.join(skillsDir, 'manifest.json'),\n JSON.stringify(manifest, null, 2),\n );\n\n if (copiedCount > 0) {\n console.log(`${c('green', '[build:exec]')} copied ${copiedCount} skill content file(s) to _skills/`);\n }\n }\n\n // Log tool name conflicts\n const cliConfig = config.cli || { enabled: true };\n const excludeTools = cliConfig.excludeTools || [];\n schema.tools\n .filter((t) => !excludeTools.includes(t.name))\n .forEach((t) => {\n const { wasRenamed, cmdName } = resolveToolCommandName(t.name);\n if (wasRenamed) {\n console.log(\n `${c('yellow', '[build:exec]')} Tool \"${t.name}\" conflicts with built-in command, mapped to \"${cmdName}\"`,\n );\n }\n });\n\n // Generate runtime modules\n const outputDefault = cliConfig.outputDefault || 'text';\n const authRequired = cliConfig.authRequired ?? false;\n const nativeDeps = cliConfig.nativeDeps || {};\n const oauthConfig = cliConfig.oauth;\n\n // Write runtime modules to temp files for bundling\n const tempDir = path.join(outDir, '__cli_temp');\n fs.mkdirSync(tempDir, { recursive: true });\n\n fs.writeFileSync(\n path.join(tempDir, 'output-formatter.js'),\n generateOutputFormatterSource(),\n );\n fs.writeFileSync(\n path.join(tempDir, 'session-manager.js'),\n generateSessionManagerSource(config.name),\n );\n fs.writeFileSync(\n path.join(tempDir, 'credential-store.js'),\n generateCredentialStoreSource(config.name),\n );\n fs.writeFileSync(\n path.join(tempDir, 'oauth-helper.js'),\n generateOAuthHelperSource(config.name),\n );\n fs.writeFileSync(\n path.join(tempDir, 'daemon-client.js'),\n generateDaemonClientSource(),\n );\n\n // Generate CLI entry\n const cliEntrySource = generateCliEntry({\n appName: config.name,\n appVersion: config.version || '1.0.0',\n description: cliConfig.description || `${config.name} CLI`,\n serverBundleFilename: bundleFilename,\n outputDefault,\n authRequired,\n excludeTools,\n nativeDeps,\n schema,\n oauthConfig,\n selfContained: !!seaEnabled,\n });\n\n const cliEntryPath = path.join(tempDir, 'cli-entry.js');\n fs.writeFileSync(cliEntryPath, cliEntrySource);\n\n // Bundle CLI\n console.log(`${c('cyan', '[build:exec]')} bundling CLI...`);\n const cliResult = await bundleCliWithEsbuild(cliEntryPath, outDir, config, {\n selfContained: !!seaEnabled,\n });\n cliBundlePath = cliResult.bundlePath;\n console.log(\n `${c('green', '[build:exec]')} CLI bundle: ${path.relative(cwd, cliResult.bundlePath)} (${formatSize(cliResult.bundleSize)})`,\n );\n\n // Clean temp\n fs.rmSync(tempDir, { recursive: true, force: true });\n\n // Extend manifest with CLI metadata\n manifest.cli = {\n enabled: true,\n cliBundle: `${config.name}-cli.bundle.js`,\n outputDefault,\n authRequired,\n toolCount: userToolCount,\n resourceCount: schema.resources.length,\n templateCount: schema.resourceTemplates.length,\n promptCount: schema.prompts.length,\n oauthEnabled: !!oauthConfig,\n skillsEnabled: capabilities.skills || undefined,\n jobsEnabled: capabilities.jobs || undefined,\n workflowsEnabled: capabilities.workflows || undefined,\n };\n }\n\n // 8. Build SEA binaries if enabled\n let seaServerResult: { executablePath: string; executableSize: number } | undefined;\n let seaCliResult: { executablePath: string; executableSize: number } | undefined;\n if (seaEnabled) {\n const { buildSea } = await import('./sea-builder.js');\n\n // Rebuild server bundle as self-contained for SEA (inlines all deps)\n // Use a temp filename so the original non-self-contained bundle is preserved\n const seaTempName = `${config.name}.sea-temp`;\n console.log(`${c('cyan', '[build:sea]')} rebuilding server bundle (self-contained)...`);\n const seaBundle = await bundleWithEsbuild(compiledEntry, outDir, config, {\n selfContained: true,\n outputName: seaTempName,\n });\n\n console.log(`${c('cyan', '[build:sea]')} building server SEA binary...`);\n seaServerResult = await buildSea(seaBundle.bundlePath, outDir, config.name);\n // Clean up temp self-contained bundle\n fs.unlinkSync(seaBundle.bundlePath);\n console.log(\n `${c('green', '[build:sea]')} server binary: ${path.relative(cwd, seaServerResult.executablePath)} (${formatSize(seaServerResult.executableSize)})`,\n );\n\n if (cliBundlePath) {\n console.log(`${c('cyan', '[build:sea]')} building CLI SEA binary...`);\n seaCliResult = await buildSea(cliBundlePath, outDir, `${config.name}-cli`);\n console.log(\n `${c('green', '[build:sea]')} CLI binary: ${path.relative(cwd, seaCliResult.executablePath)} (${formatSize(seaCliResult.executableSize)})`,\n );\n }\n }\n\n // 9. Write manifest\n const manifestPath = path.join(outDir, `${config.name}.manifest.json`);\n fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), 'utf-8');\n console.log(\n `${c('green', '[build:exec]')} manifest: ${path.relative(cwd, manifestPath)}`,\n );\n\n // 10. Generate runner script (dispatches to CLI bundle or SEA binary)\n const runnerContent = generateRunnerScript(config, !!cliEnabled, !!seaEnabled);\n const runnerPath = path.join(outDir, config.name);\n fs.writeFileSync(runnerPath, runnerContent, { mode: 0o755 });\n console.log(\n `${c('green', '[build:exec]')} runner: ${path.relative(cwd, runnerPath)}`,\n );\n\n // 10. Generate installer script\n const installerContent = generateInstallerScript(config);\n const installerPath = path.join(outDir, `install-${config.name}.sh`);\n fs.writeFileSync(installerPath, installerContent, { mode: 0o755 });\n console.log(\n `${c('green', '[build:exec]')} installer: ${path.relative(cwd, installerPath)}`,\n );\n\n // 12. Clean up intermediate compiled files\n const keepFiles = new Set([\n `${config.name}.bundle.js`,\n `${config.name}-cli.bundle.js`,\n `${config.name}.manifest.json`,\n config.name,\n `install-${config.name}.sh`,\n `${config.name}-bin`,\n `${config.name}-cli-bin`,\n '_skills',\n ]);\n\n const allFiles = fs.readdirSync(outDir);\n let cleaned = 0;\n for (const file of allFiles) {\n if (!keepFiles.has(file)) {\n const filePath = path.join(outDir, file);\n const stat = fs.statSync(filePath);\n // Only clean intermediate compiled files; preserve .md and _skills/ directory\n if (stat.isFile() && !file.endsWith('.md')) {\n fs.unlinkSync(filePath);\n cleaned++;\n }\n }\n }\n if (cleaned > 0) {\n console.log(\n `${c('gray', '[build:exec]')} cleaned ${cleaned} intermediate file(s)`,\n );\n }\n\n // 13. Print summary\n console.log(`\\n${c('green', 'Executable build completed.')}`);\n console.log(`\\n${c('bold', 'Output:')}`);\n console.log(` ${path.relative(cwd, bundleResult.bundlePath)} ${c('gray', `(${formatSize(bundleResult.bundleSize)})`)}`);\n if (cliBundlePath) {\n const cliStat = fs.statSync(cliBundlePath);\n console.log(` ${path.relative(cwd, cliBundlePath)} ${c('gray', `(${formatSize(cliStat.size)})`)}`);\n }\n if (seaServerResult) {\n console.log(` ${path.relative(cwd, seaServerResult.executablePath)} ${c('gray', `(${formatSize(seaServerResult.executableSize)})`)}`);\n }\n if (seaCliResult) {\n console.log(` ${path.relative(cwd, seaCliResult.executablePath)} ${c('gray', `(${formatSize(seaCliResult.executableSize)})`)}`);\n }\n console.log(` ${path.relative(cwd, manifestPath)}`);\n console.log(` ${path.relative(cwd, runnerPath)}`);\n console.log(` ${path.relative(cwd, installerPath)}`);\n\n if (cliEnabled) {\n console.log(`\\n${c('gray', 'Run the CLI:')} ./${path.relative(cwd, runnerPath)} --help`);\n console.log(`${c('gray', 'Start server:')} ./${path.relative(cwd, runnerPath)} serve`);\n } else {\n console.log(`\\n${c('gray', 'Run the server:')} ./${path.relative(cwd, runnerPath)}`);\n }\n if (seaServerResult || seaCliResult) {\n console.log(`\\n${c('yellow', 'Note:')} SEA binaries are native executables. Run directly (not via bash).`);\n }\n console.log(`${c('gray', 'Install to system:')} bash ./${path.relative(cwd, installerPath)}`);\n}\n"]}
|
|
@@ -90,28 +90,32 @@ const TARGET_TO_ADAPTER = {
|
|
|
90
90
|
*/
|
|
91
91
|
async function runBuild(opts) {
|
|
92
92
|
const target = opts.buildTarget ?? 'node';
|
|
93
|
+
// Each target outputs to dist/{target}/ for clean separation
|
|
94
|
+
const baseOutDir = path.resolve(process.cwd(), opts.outDir || 'dist');
|
|
95
|
+
const targetOutDir = path.join(baseOutDir, target);
|
|
96
|
+
const targetOpts = { ...opts, outDir: targetOutDir };
|
|
93
97
|
switch (target) {
|
|
94
98
|
case 'cli': {
|
|
95
99
|
const { buildExec } = await import('./exec/index.js');
|
|
96
|
-
return buildExec({ ...
|
|
100
|
+
return buildExec({ ...targetOpts, cli: true, sea: !opts.js });
|
|
97
101
|
}
|
|
98
102
|
case 'node': {
|
|
99
103
|
const { buildExec } = await import('./exec/index.js');
|
|
100
|
-
return buildExec(
|
|
104
|
+
return buildExec(targetOpts);
|
|
101
105
|
}
|
|
102
106
|
case 'sdk': {
|
|
103
107
|
const { buildSdk } = await import('./sdk/index.js');
|
|
104
|
-
return buildSdk(
|
|
108
|
+
return buildSdk(targetOpts);
|
|
105
109
|
}
|
|
106
110
|
case 'browser': {
|
|
107
111
|
const { buildBrowser } = await import('./browser/index.js');
|
|
108
|
-
return buildBrowser(
|
|
112
|
+
return buildBrowser(targetOpts);
|
|
109
113
|
}
|
|
110
114
|
case 'vercel':
|
|
111
115
|
case 'lambda':
|
|
112
116
|
case 'cloudflare': {
|
|
113
117
|
const adapter = TARGET_TO_ADAPTER[target];
|
|
114
|
-
return runAdapterBuild(
|
|
118
|
+
return runAdapterBuild(targetOpts, adapter);
|
|
115
119
|
}
|
|
116
120
|
default:
|
|
117
121
|
throw new Error(`Unknown build target: ${target}. Available: cli, node, sdk, browser, cloudflare, vercel, lambda`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/commands/build/index.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'path';\nimport { ParsedArgs } from '../../core/args';\nimport { c } from '../../core/colors';\nimport { ensureDir, fileExists, runCmd, writeJSON } from '@frontmcp/utils';\nimport { fsp, resolveEntry } from '../../shared/fs';\nimport { REQUIRED_DECORATOR_FIELDS } from '../../core/tsconfig';\nimport { ADAPTERS } from './adapters';\nimport { AdapterName } from './types';\nimport { bundleForServerless } from './bundler';\n\nfunction isTsLike(p: string): boolean {\n return /\\.tsx?$/i.test(p);\n}\n\n/**\n * Generate adapter-specific entry point and config files.\n */\nasync function generateAdapterFiles(\n adapter: AdapterName,\n outDir: string,\n entryBasename: string,\n cwd: string,\n): Promise<void> {\n const template = ADAPTERS[adapter];\n\n // Generate serverless setup file first (if adapter has one)\n // This file sets FRONTMCP_SERVERLESS=1 before any imports run\n if (template.getSetupTemplate) {\n const setupContent = template.getSetupTemplate();\n const setupPath = path.join(outDir, 'serverless-setup.js');\n await fsp.writeFile(setupPath, setupContent, 'utf8');\n console.log(c('green', ` Generated serverless setup at ${path.relative(cwd, setupPath)}`));\n }\n\n // Generate index.js entry point\n const mainModuleName = entryBasename.replace(/\\.tsx?$/, '.js');\n const entryContent = template.getEntryTemplate(`./${mainModuleName}`);\n\n // Skip if no entry template (e.g., node adapter)\n if (entryContent) {\n const entryPath = path.join(outDir, 'index.js');\n await fsp.writeFile(entryPath, entryContent, 'utf8');\n console.log(c('green', ` Generated ${adapter} entry at ${path.relative(cwd, entryPath)}`));\n }\n\n // Bundle if adapter requires it (creates single CJS file for serverless)\n if (template.shouldBundle && template.bundleOutput) {\n console.log(c('cyan', `[build] Bundling for ${adapter}...`));\n const entryPath = path.join(outDir, 'index.js');\n await bundleForServerless(entryPath, outDir, template.bundleOutput);\n console.log(c('green', ` Created bundle: ${template.bundleOutput}`));\n\n // Run post-bundle hook if defined (e.g., create Build Output API structure)\n if (template.postBundle) {\n console.log(c('cyan', `[build] Creating ${adapter} deployment structure...`));\n await template.postBundle(outDir, cwd, template.bundleOutput);\n console.log(c('green', ` Created deployment output structure`));\n }\n }\n\n // Generate config file if adapter has one (skip if already exists)\n if (template.getConfig && template.configFileName) {\n const configPath = path.join(cwd, template.configFileName);\n\n if (await fileExists(configPath)) {\n console.log(c('yellow', ` ${template.configFileName} already exists (skipping)`));\n } else {\n const configContent = template.getConfig(cwd);\n\n if (typeof configContent === 'string') {\n // Write as plain text (e.g., TOML for wrangler.toml)\n await fsp.writeFile(configPath, configContent, 'utf8');\n } else {\n // Write as JSON\n await writeJSON(configPath, configContent);\n }\n console.log(c('green', ` Generated ${template.configFileName}`));\n }\n }\n}\n\n/** Map target names to internal adapter names. */\nconst TARGET_TO_ADAPTER: Record<string, AdapterName> = {\n 'vercel': 'vercel',\n 'lambda': 'lambda',\n 'cloudflare': 'cloudflare',\n};\n\n/**\n * Build the FrontMCP server for a specific deployment target.\n *\n * @example\n * ```bash\n * frontmcp build --target node # Node.js server bundle\n * frontmcp build --target cli # CLI with SEA binary\n * frontmcp build --target cli --js # CLI without SEA\n * frontmcp build --target sdk # Library (CJS+ESM+types)\n * frontmcp build --target browser # Browser ESM bundle\n * frontmcp build --target vercel # Vercel serverless\n * frontmcp build --target lambda # AWS Lambda\n * frontmcp build --target cloudflare # Cloudflare Workers\n * ```\n */\nexport async function runBuild(opts: ParsedArgs): Promise<void> {\n const target = opts.buildTarget ?? 'node';\n\n switch (target) {\n case 'cli': {\n const { buildExec } = await import('./exec/index.js');\n return buildExec({ ...opts, cli: true, sea: !opts.js } as ParsedArgs & { cli: boolean; sea: boolean });\n }\n case 'node': {\n const { buildExec } = await import('./exec/index.js');\n return buildExec(opts);\n }\n case 'sdk': {\n const { buildSdk } = await import('./sdk/index.js');\n return buildSdk(opts);\n }\n case 'browser': {\n const { buildBrowser } = await import('./browser/index.js');\n return buildBrowser(opts);\n }\n case 'vercel':\n case 'lambda':\n case 'cloudflare': {\n const adapter = TARGET_TO_ADAPTER[target];\n return runAdapterBuild(opts, adapter);\n }\n default:\n throw new Error(`Unknown build target: ${target}. Available: cli, node, sdk, browser, cloudflare, vercel, lambda`);\n }\n}\n\n/**\n * Build using a deployment adapter (serverless platforms).\n */\nasync function runAdapterBuild(opts: ParsedArgs, adapter: AdapterName): Promise<void> {\n const cwd = process.cwd();\n const entry = await resolveEntry(cwd, opts.entry);\n const outDir = path.resolve(cwd, opts.outDir || 'dist');\n await ensureDir(outDir);\n\n const template = ADAPTERS[adapter];\n if (!template) {\n const available = Object.keys(ADAPTERS).join(', ');\n throw new Error(`Unknown adapter: ${adapter}. Available: ${available}`);\n }\n\n if (adapter === 'cloudflare') {\n console.log(\n c('yellow', 'Cloudflare Workers adapter is experimental. See docs for limitations.'),\n );\n }\n\n const moduleFormat = template.moduleFormat;\n\n console.log(`${c('cyan', '[build]')} entry: ${path.relative(cwd, entry)}`);\n console.log(`${c('cyan', '[build]')} outDir: ${path.relative(cwd, outDir)}`);\n console.log(`${c('cyan', '[build]')} target: ${adapter} (${moduleFormat})`);\n\n const tsconfigPath = path.join(cwd, 'tsconfig.json');\n const hasTsconfig = await fileExists(tsconfigPath);\n const args: string[] = ['-y', 'tsc'];\n\n if (hasTsconfig) {\n console.log(c('gray', `[build] tsconfig.json detected — compiling with project settings`));\n args.push('--project', tsconfigPath);\n } else {\n args.push(entry);\n args.push('--rootDir', path.dirname(entry));\n if (!isTsLike(entry)) {\n args.push('--allowJs');\n console.log(c('yellow', '[build] Entry is not TypeScript; enabling --allowJs'));\n }\n args.push('--experimentalDecorators', '--emitDecoratorMetadata');\n args.push('--target', REQUIRED_DECORATOR_FIELDS.target);\n }\n\n args.push('--module', moduleFormat);\n args.push('--outDir', outDir);\n args.push('--skipLibCheck');\n\n await runCmd('npx', args);\n\n if (adapter !== 'node') {\n console.log(c('cyan', `[build] Generating ${adapter} deployment files...`));\n const entryBasename = path.basename(entry);\n await generateAdapterFiles(adapter, outDir, entryBasename, cwd);\n }\n\n console.log(c('green', 'Build completed.'));\n console.log(c('gray', `Output placed in ${path.relative(cwd, outDir)}`));\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/commands/build/index.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'path';\nimport { ParsedArgs } from '../../core/args';\nimport { c } from '../../core/colors';\nimport { ensureDir, fileExists, runCmd, writeJSON } from '@frontmcp/utils';\nimport { fsp, resolveEntry } from '../../shared/fs';\nimport { REQUIRED_DECORATOR_FIELDS } from '../../core/tsconfig';\nimport { ADAPTERS } from './adapters';\nimport { AdapterName } from './types';\nimport { bundleForServerless } from './bundler';\n\nfunction isTsLike(p: string): boolean {\n return /\\.tsx?$/i.test(p);\n}\n\n/**\n * Generate adapter-specific entry point and config files.\n */\nasync function generateAdapterFiles(\n adapter: AdapterName,\n outDir: string,\n entryBasename: string,\n cwd: string,\n): Promise<void> {\n const template = ADAPTERS[adapter];\n\n // Generate serverless setup file first (if adapter has one)\n // This file sets FRONTMCP_SERVERLESS=1 before any imports run\n if (template.getSetupTemplate) {\n const setupContent = template.getSetupTemplate();\n const setupPath = path.join(outDir, 'serverless-setup.js');\n await fsp.writeFile(setupPath, setupContent, 'utf8');\n console.log(c('green', ` Generated serverless setup at ${path.relative(cwd, setupPath)}`));\n }\n\n // Generate index.js entry point\n const mainModuleName = entryBasename.replace(/\\.tsx?$/, '.js');\n const entryContent = template.getEntryTemplate(`./${mainModuleName}`);\n\n // Skip if no entry template (e.g., node adapter)\n if (entryContent) {\n const entryPath = path.join(outDir, 'index.js');\n await fsp.writeFile(entryPath, entryContent, 'utf8');\n console.log(c('green', ` Generated ${adapter} entry at ${path.relative(cwd, entryPath)}`));\n }\n\n // Bundle if adapter requires it (creates single CJS file for serverless)\n if (template.shouldBundle && template.bundleOutput) {\n console.log(c('cyan', `[build] Bundling for ${adapter}...`));\n const entryPath = path.join(outDir, 'index.js');\n await bundleForServerless(entryPath, outDir, template.bundleOutput);\n console.log(c('green', ` Created bundle: ${template.bundleOutput}`));\n\n // Run post-bundle hook if defined (e.g., create Build Output API structure)\n if (template.postBundle) {\n console.log(c('cyan', `[build] Creating ${adapter} deployment structure...`));\n await template.postBundle(outDir, cwd, template.bundleOutput);\n console.log(c('green', ` Created deployment output structure`));\n }\n }\n\n // Generate config file if adapter has one (skip if already exists)\n if (template.getConfig && template.configFileName) {\n const configPath = path.join(cwd, template.configFileName);\n\n if (await fileExists(configPath)) {\n console.log(c('yellow', ` ${template.configFileName} already exists (skipping)`));\n } else {\n const configContent = template.getConfig(cwd);\n\n if (typeof configContent === 'string') {\n // Write as plain text (e.g., TOML for wrangler.toml)\n await fsp.writeFile(configPath, configContent, 'utf8');\n } else {\n // Write as JSON\n await writeJSON(configPath, configContent);\n }\n console.log(c('green', ` Generated ${template.configFileName}`));\n }\n }\n}\n\n/** Map target names to internal adapter names. */\nconst TARGET_TO_ADAPTER: Record<string, AdapterName> = {\n 'vercel': 'vercel',\n 'lambda': 'lambda',\n 'cloudflare': 'cloudflare',\n};\n\n/**\n * Build the FrontMCP server for a specific deployment target.\n *\n * @example\n * ```bash\n * frontmcp build --target node # Node.js server bundle\n * frontmcp build --target cli # CLI with SEA binary\n * frontmcp build --target cli --js # CLI without SEA\n * frontmcp build --target sdk # Library (CJS+ESM+types)\n * frontmcp build --target browser # Browser ESM bundle\n * frontmcp build --target vercel # Vercel serverless\n * frontmcp build --target lambda # AWS Lambda\n * frontmcp build --target cloudflare # Cloudflare Workers\n * ```\n */\nexport async function runBuild(opts: ParsedArgs): Promise<void> {\n const target = opts.buildTarget ?? 'node';\n\n // Each target outputs to dist/{target}/ for clean separation\n const baseOutDir = path.resolve(process.cwd(), opts.outDir || 'dist');\n const targetOutDir = path.join(baseOutDir, target);\n const targetOpts = { ...opts, outDir: targetOutDir };\n\n switch (target) {\n case 'cli': {\n const { buildExec } = await import('./exec/index.js');\n return buildExec({ ...targetOpts, cli: true, sea: !opts.js } as ParsedArgs & { cli: boolean; sea: boolean });\n }\n case 'node': {\n const { buildExec } = await import('./exec/index.js');\n return buildExec(targetOpts);\n }\n case 'sdk': {\n const { buildSdk } = await import('./sdk/index.js');\n return buildSdk(targetOpts);\n }\n case 'browser': {\n const { buildBrowser } = await import('./browser/index.js');\n return buildBrowser(targetOpts);\n }\n case 'vercel':\n case 'lambda':\n case 'cloudflare': {\n const adapter = TARGET_TO_ADAPTER[target];\n return runAdapterBuild(targetOpts, adapter);\n }\n default:\n throw new Error(`Unknown build target: ${target}. Available: cli, node, sdk, browser, cloudflare, vercel, lambda`);\n }\n}\n\n/**\n * Build using a deployment adapter (serverless platforms).\n */\nasync function runAdapterBuild(opts: ParsedArgs, adapter: AdapterName): Promise<void> {\n const cwd = process.cwd();\n const entry = await resolveEntry(cwd, opts.entry);\n const outDir = path.resolve(cwd, opts.outDir || 'dist');\n await ensureDir(outDir);\n\n const template = ADAPTERS[adapter];\n if (!template) {\n const available = Object.keys(ADAPTERS).join(', ');\n throw new Error(`Unknown adapter: ${adapter}. Available: ${available}`);\n }\n\n if (adapter === 'cloudflare') {\n console.log(\n c('yellow', 'Cloudflare Workers adapter is experimental. See docs for limitations.'),\n );\n }\n\n const moduleFormat = template.moduleFormat;\n\n console.log(`${c('cyan', '[build]')} entry: ${path.relative(cwd, entry)}`);\n console.log(`${c('cyan', '[build]')} outDir: ${path.relative(cwd, outDir)}`);\n console.log(`${c('cyan', '[build]')} target: ${adapter} (${moduleFormat})`);\n\n const tsconfigPath = path.join(cwd, 'tsconfig.json');\n const hasTsconfig = await fileExists(tsconfigPath);\n const args: string[] = ['-y', 'tsc'];\n\n if (hasTsconfig) {\n console.log(c('gray', `[build] tsconfig.json detected — compiling with project settings`));\n args.push('--project', tsconfigPath);\n } else {\n args.push(entry);\n args.push('--rootDir', path.dirname(entry));\n if (!isTsLike(entry)) {\n args.push('--allowJs');\n console.log(c('yellow', '[build] Entry is not TypeScript; enabling --allowJs'));\n }\n args.push('--experimentalDecorators', '--emitDecoratorMetadata');\n args.push('--target', REQUIRED_DECORATOR_FIELDS.target);\n }\n\n args.push('--module', moduleFormat);\n args.push('--outDir', outDir);\n args.push('--skipLibCheck');\n\n await runCmd('npx', args);\n\n if (adapter !== 'node') {\n console.log(c('cyan', `[build] Generating ${adapter} deployment files...`));\n const entryBasename = path.basename(entry);\n await generateAdapterFiles(adapter, outDir, entryBasename, cwd);\n }\n\n console.log(c('green', 'Build completed.'));\n console.log(c('gray', `Output placed in ${path.relative(cwd, outDir)}`));\n}\n"]}
|
package/src/core/cli.js
CHANGED
|
@@ -13,10 +13,13 @@ async function main() {
|
|
|
13
13
|
try {
|
|
14
14
|
const program = (0, program_1.createProgram)();
|
|
15
15
|
await program.parseAsync(process.argv);
|
|
16
|
+
process.exitCode = 0;
|
|
17
|
+
return;
|
|
16
18
|
}
|
|
17
19
|
catch (err) {
|
|
18
20
|
console.error('\n' + (0, colors_1.c)('red', err instanceof Error ? err.stack || err.message : String(err)));
|
|
19
|
-
process.
|
|
21
|
+
process.exitCode = 1;
|
|
22
|
+
return;
|
|
20
23
|
}
|
|
21
24
|
}
|
|
22
25
|
main();
|
package/src/core/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../../src/core/cli.ts"],"names":[],"mappings":";;AACA;;;;;GAKG;;AAEH,uCAA0C;AAC1C,qCAA6B;AAE7B,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAA,uBAAa,GAAE,CAAC;QAChC,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../../src/core/cli.ts"],"names":[],"mappings":";;AACA;;;;;GAKG;;AAEH,uCAA0C;AAC1C,qCAA6B;AAE7B,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAA,uBAAa,GAAE,CAAC;QAChC,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACvC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,OAAO,CAAC,KAAK,CAAC,IAAI,GAAG,IAAA,UAAC,EAAC,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC9F,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC","sourcesContent":["#!/usr/bin/env node\n/**\n * frontmcp - FrontMCP command line interface\n *\n * Uses commander.js for argument parsing, command management, and\n * auto-generated help. Interactive TUI is handled by @clack/prompts.\n */\n\nimport { createProgram } from './program';\nimport { c } from './colors';\n\nasync function main(): Promise<void> {\n try {\n const program = createProgram();\n await program.parseAsync(process.argv);\n process.exitCode = 0;\n return;\n } catch (err: unknown) {\n console.error('\\n' + c('red', err instanceof Error ? err.stack || err.message : String(err)));\n process.exitCode = 1;\n return;\n }\n}\n\nmain();\n"]}
|