@sidecar-ai/cli 0.1.0-alpha.4 → 0.1.0-alpha.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +138 -42
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -1686,6 +1686,12 @@ function analyzeProjectConfig(rootDir) {
|
|
|
1686
1686
|
return defaultCompilerConfig();
|
|
1687
1687
|
}
|
|
1688
1688
|
return {
|
|
1689
|
+
build: {
|
|
1690
|
+
target: readTargetNested(definition, "build", "target"),
|
|
1691
|
+
host: readHostNested(definition, "build", "host"),
|
|
1692
|
+
outDir: readStringNested(definition, "build", "outDir"),
|
|
1693
|
+
plugins: readBooleanNested(definition, "build", "plugins")
|
|
1694
|
+
},
|
|
1689
1695
|
resources: {
|
|
1690
1696
|
subscribe: readBooleanNested(definition, "resources", "subscribe") ?? false,
|
|
1691
1697
|
listChanged: readBooleanNested(definition, "resources", "listChanged") ?? false
|
|
@@ -1704,6 +1710,7 @@ function analyzeProjectConfig(rootDir) {
|
|
|
1704
1710
|
}
|
|
1705
1711
|
function defaultCompilerConfig() {
|
|
1706
1712
|
return {
|
|
1713
|
+
build: {},
|
|
1707
1714
|
resources: {
|
|
1708
1715
|
subscribe: false,
|
|
1709
1716
|
listChanged: false
|
|
@@ -1720,6 +1727,26 @@ function defaultCompilerConfig() {
|
|
|
1720
1727
|
}
|
|
1721
1728
|
};
|
|
1722
1729
|
}
|
|
1730
|
+
function readTargetNested(definition, section, propertyName) {
|
|
1731
|
+
const value = readStringNested(definition, section, propertyName);
|
|
1732
|
+
return value === "mcp" || value === "chatgpt" || value === "claude" ? value : void 0;
|
|
1733
|
+
}
|
|
1734
|
+
function readHostNested(definition, section, propertyName) {
|
|
1735
|
+
const value = readStringNested(definition, section, propertyName);
|
|
1736
|
+
return value === "node" || value === "vercel" ? value : void 0;
|
|
1737
|
+
}
|
|
1738
|
+
function readStringNested(definition, section, propertyName) {
|
|
1739
|
+
const object = readObjectProperty3(definition, section);
|
|
1740
|
+
if (!object) {
|
|
1741
|
+
return void 0;
|
|
1742
|
+
}
|
|
1743
|
+
const property = object.getProperty(propertyName);
|
|
1744
|
+
if (!property || !Node5.isPropertyAssignment(property)) {
|
|
1745
|
+
return void 0;
|
|
1746
|
+
}
|
|
1747
|
+
const initializer = unwrapExpression(property.getInitializer());
|
|
1748
|
+
return initializer && Node5.isStringLiteral(initializer) ? initializer.getLiteralText() : void 0;
|
|
1749
|
+
}
|
|
1723
1750
|
function readBooleanNested(definition, section, propertyName) {
|
|
1724
1751
|
const object = readObjectProperty3(definition, section);
|
|
1725
1752
|
if (!object) {
|
|
@@ -2987,8 +3014,10 @@ import { mkdir as mkdir8, rm, writeFile as writeFile8 } from "fs/promises";
|
|
|
2987
3014
|
import path17 from "path";
|
|
2988
3015
|
import { build as esbuild2 } from "esbuild";
|
|
2989
3016
|
var SERVER_ENTRYPOINT = "server/index.js";
|
|
2990
|
-
var
|
|
2991
|
-
|
|
3017
|
+
var VERCEL_FUNCTION_DIR = "functions/api/sidecar.func";
|
|
3018
|
+
var VERCEL_ENTRYPOINT = `${VERCEL_FUNCTION_DIR}/index.js`;
|
|
3019
|
+
var VERCEL_HANDLER_FILE = "index.js";
|
|
3020
|
+
async function buildServerOutput(rootDir, outDir, manifest, identity, host = "node", options = {}) {
|
|
2992
3021
|
const cacheDir = path17.join(rootDir, ".sidecar", "cache", "server");
|
|
2993
3022
|
await mkdir8(cacheDir, { recursive: true });
|
|
2994
3023
|
const entryFile = path17.join(cacheDir, "index.ts");
|
|
@@ -3018,9 +3047,13 @@ const require = __sidecarCreateRequire(import.meta.url);`
|
|
|
3018
3047
|
});
|
|
3019
3048
|
await writeFile8(path17.join(outDir, "package.json"), renderServerPackage(identity));
|
|
3020
3049
|
if (host === "vercel") {
|
|
3021
|
-
|
|
3022
|
-
await
|
|
3023
|
-
await
|
|
3050
|
+
const vercelOutputDir = options.vercelOutputDir ?? outDir;
|
|
3051
|
+
await rm(path17.join(vercelOutputDir, "api"), { recursive: true, force: true });
|
|
3052
|
+
await rm(path17.join(vercelOutputDir, "vercel.json"), { force: true });
|
|
3053
|
+
await writeFile8(path17.join(outDir, VERCEL_HANDLER_FILE), renderVercelEntrypoint());
|
|
3054
|
+
await writeFile8(path17.join(outDir, ".vc-config.json"), renderVercelFunctionConfig());
|
|
3055
|
+
await mkdir8(vercelOutputDir, { recursive: true });
|
|
3056
|
+
await writeFile8(path17.join(vercelOutputDir, "config.json"), renderVercelOutputConfig());
|
|
3024
3057
|
} else {
|
|
3025
3058
|
await rm(path17.join(outDir, "api"), { recursive: true, force: true });
|
|
3026
3059
|
await rm(path17.join(outDir, "vercel.json"), { force: true });
|
|
@@ -3221,23 +3254,29 @@ function renderServerPackage(identity) {
|
|
|
3221
3254
|
`;
|
|
3222
3255
|
}
|
|
3223
3256
|
function renderVercelEntrypoint() {
|
|
3224
|
-
return `export { default } from "
|
|
3257
|
+
return `export { default } from "./server/index.js";
|
|
3225
3258
|
`;
|
|
3226
3259
|
}
|
|
3227
|
-
function
|
|
3260
|
+
function renderVercelFunctionConfig() {
|
|
3228
3261
|
return `${JSON.stringify({
|
|
3229
|
-
|
|
3262
|
+
runtime: "nodejs22.x",
|
|
3263
|
+
handler: VERCEL_HANDLER_FILE,
|
|
3264
|
+
launcherType: "Nodejs",
|
|
3265
|
+
shouldAddHelpers: true,
|
|
3266
|
+
supportsResponseStreaming: true,
|
|
3267
|
+
maxDuration: 300
|
|
3268
|
+
}, null, 2)}
|
|
3269
|
+
`;
|
|
3270
|
+
}
|
|
3271
|
+
function renderVercelOutputConfig() {
|
|
3272
|
+
return `${JSON.stringify({
|
|
3273
|
+
version: 3,
|
|
3274
|
+
routes: [
|
|
3230
3275
|
{
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
}
|
|
3234
|
-
],
|
|
3235
|
-
functions: {
|
|
3236
|
-
"api/sidecar.js": {
|
|
3237
|
-
includeFiles: "public/**",
|
|
3238
|
-
maxDuration: 300
|
|
3276
|
+
src: "/(.*)",
|
|
3277
|
+
dest: "/api/sidecar"
|
|
3239
3278
|
}
|
|
3240
|
-
|
|
3279
|
+
]
|
|
3241
3280
|
}, null, 2)}
|
|
3242
3281
|
`;
|
|
3243
3282
|
}
|
|
@@ -3286,9 +3325,10 @@ function findSidecarRepoRoot2(startDir) {
|
|
|
3286
3325
|
// packages/compiler/src/build.ts
|
|
3287
3326
|
async function buildProject(options) {
|
|
3288
3327
|
const rootDir = path18.resolve(options.rootDir);
|
|
3289
|
-
const target = options.target ?? "mcp";
|
|
3290
|
-
const host = options.host ?? "node";
|
|
3291
3328
|
const config = analyzeProjectConfig(rootDir);
|
|
3329
|
+
const target = options.target ?? config.build.target ?? "mcp";
|
|
3330
|
+
const host = options.host ?? config.build.host ?? "node";
|
|
3331
|
+
const plugins = options.plugins ?? config.build.plugins ?? false;
|
|
3292
3332
|
const tools = await analyzeProjectTools(rootDir, { target });
|
|
3293
3333
|
const resources = await analyzeProjectResources(rootDir);
|
|
3294
3334
|
const resourceTemplates = [];
|
|
@@ -3304,8 +3344,9 @@ async function buildProject(options) {
|
|
|
3304
3344
|
if (errors.length) {
|
|
3305
3345
|
throw new Error(errors.map(formatDiagnostic).join("\n"));
|
|
3306
3346
|
}
|
|
3307
|
-
const outDir = resolveInsideRoot(rootDir, options.outDir ??
|
|
3308
|
-
|
|
3347
|
+
const outDir = resolveInsideRoot(rootDir, options.outDir ?? config.build.outDir ?? defaultBuildOutDir(host, target));
|
|
3348
|
+
const runtimeOutDir = resolveRuntimeOutputDir(outDir, host);
|
|
3349
|
+
await buildWidgets(rootDir, runtimeOutDir, tools);
|
|
3309
3350
|
const manifest = {
|
|
3310
3351
|
version: 1,
|
|
3311
3352
|
target,
|
|
@@ -3319,20 +3360,43 @@ async function buildProject(options) {
|
|
|
3319
3360
|
prompts,
|
|
3320
3361
|
diagnostics
|
|
3321
3362
|
};
|
|
3322
|
-
await mkdir9(
|
|
3363
|
+
await mkdir9(runtimeOutDir, { recursive: true });
|
|
3323
3364
|
await writeFile9(
|
|
3324
|
-
path18.join(
|
|
3365
|
+
path18.join(runtimeOutDir, "manifest.sidecar.json"),
|
|
3325
3366
|
`${JSON.stringify(manifest, null, 2)}
|
|
3326
3367
|
`
|
|
3327
3368
|
);
|
|
3328
|
-
await writeFile9(path18.join(
|
|
3369
|
+
await writeFile9(path18.join(runtimeOutDir, "README.md"), renderMcpReadme(manifest));
|
|
3329
3370
|
await writeGeneratedTypes(rootDir, tools);
|
|
3330
|
-
await buildServerOutput(rootDir,
|
|
3331
|
-
|
|
3332
|
-
|
|
3371
|
+
await buildServerOutput(rootDir, runtimeOutDir, manifest, identity, host, {
|
|
3372
|
+
vercelOutputDir: outDir
|
|
3373
|
+
});
|
|
3374
|
+
if (plugins) {
|
|
3375
|
+
await buildPluginPackages(rootDir, resolvePluginOutputBase(rootDir, outDir, host), manifest);
|
|
3333
3376
|
}
|
|
3334
3377
|
return manifest;
|
|
3335
3378
|
}
|
|
3379
|
+
function defaultBuildOutDir(host, target) {
|
|
3380
|
+
if (host === "vercel") {
|
|
3381
|
+
return ".vercel/output";
|
|
3382
|
+
}
|
|
3383
|
+
return `out/${target}`;
|
|
3384
|
+
}
|
|
3385
|
+
function resolveRuntimeOutputDir(outDir, host) {
|
|
3386
|
+
if (host === "vercel") {
|
|
3387
|
+
return path18.join(outDir, VERCEL_FUNCTION_DIR);
|
|
3388
|
+
}
|
|
3389
|
+
return outDir;
|
|
3390
|
+
}
|
|
3391
|
+
function resolvePluginOutputBase(rootDir, outDir, host) {
|
|
3392
|
+
if (host === "vercel" && isVercelBuildOutputDir(outDir)) {
|
|
3393
|
+
return path18.join(rootDir, "out");
|
|
3394
|
+
}
|
|
3395
|
+
return path18.dirname(outDir);
|
|
3396
|
+
}
|
|
3397
|
+
function isVercelBuildOutputDir(outDir) {
|
|
3398
|
+
return path18.basename(outDir) === "output" && path18.basename(path18.dirname(outDir)) === ".vercel";
|
|
3399
|
+
}
|
|
3336
3400
|
function resolveInsideRoot(rootDir, output) {
|
|
3337
3401
|
const resolved = path18.resolve(rootDir, output);
|
|
3338
3402
|
const relative = path18.relative(rootDir, resolved);
|
|
@@ -3389,7 +3453,7 @@ Set \`PORT\` or \`SIDECAR_PORT\` to choose the listen port. Hosted/authenticated
|
|
|
3389
3453
|
function renderVercelReadmeSection() {
|
|
3390
3454
|
return `## Deploy To Vercel
|
|
3391
3455
|
|
|
3392
|
-
This output
|
|
3456
|
+
This output uses Vercel's Build Output API. The MCP function is emitted at \`${VERCEL_FUNCTION_DIR}\`, and \`config.json\` routes Streamable HTTP traffic to it. Set \`SIDECAR_MCP_URL\` to the public \`https://.../mcp\` URL in Vercel.
|
|
3393
3457
|
`;
|
|
3394
3458
|
}
|
|
3395
3459
|
|
|
@@ -5094,26 +5158,27 @@ async function main(argv) {
|
|
|
5094
5158
|
const rootDir = readOption(argv, "--cwd") ?? cwd();
|
|
5095
5159
|
switch (command) {
|
|
5096
5160
|
case "build": {
|
|
5097
|
-
const target =
|
|
5098
|
-
const host =
|
|
5099
|
-
const outDir = readOption(argv, "--out")
|
|
5100
|
-
const plugins = argv
|
|
5161
|
+
const target = readOptionalTarget(argv);
|
|
5162
|
+
const host = readOptionalHost(argv) ?? detectHostFromEnvironment();
|
|
5163
|
+
const outDir = readOption(argv, "--out");
|
|
5164
|
+
const plugins = readOptionalPlugins(argv);
|
|
5101
5165
|
const strict = argv.includes("--strict");
|
|
5102
5166
|
const manifest = await buildProject({ rootDir, host, outDir, plugins, strict, target });
|
|
5167
|
+
const resolvedOutDir = outDir ?? manifest.config.build.outDir ?? defaultBuildOutDir2(manifest.host, manifest.target);
|
|
5103
5168
|
printDiagnostics(manifest.diagnostics ?? []);
|
|
5104
5169
|
if (strict && manifest.diagnostics?.length) {
|
|
5105
5170
|
exit(1);
|
|
5106
5171
|
}
|
|
5107
5172
|
console.log(
|
|
5108
|
-
`Built ${manifest.tools.length} ${target} tool${manifest.tools.length === 1 ? "" : "s"}, ${manifest.resources.length} resource${manifest.resources.length === 1 ? "" : "s"}, and ${manifest.prompts.length} prompt${manifest.prompts.length === 1 ? "" : "s"} to ${
|
|
5173
|
+
`Built ${manifest.tools.length} ${manifest.target} tool${manifest.tools.length === 1 ? "" : "s"}, ${manifest.resources.length} resource${manifest.resources.length === 1 ? "" : "s"}, and ${manifest.prompts.length} prompt${manifest.prompts.length === 1 ? "" : "s"} to ${resolvedOutDir}.`
|
|
5109
5174
|
);
|
|
5110
|
-
console.log(`Host runtime: ${host}`);
|
|
5111
|
-
if (host === "vercel") {
|
|
5112
|
-
console.log(`Vercel MCP function: ${path19.join(
|
|
5175
|
+
console.log(`Host runtime: ${manifest.host}`);
|
|
5176
|
+
if (manifest.host === "vercel") {
|
|
5177
|
+
console.log(`Vercel MCP function: ${path19.join(resolvedOutDir, VERCEL_ENTRYPOINT)}`);
|
|
5113
5178
|
} else {
|
|
5114
|
-
console.log(`Hostable MCP server: ${path19.join(
|
|
5179
|
+
console.log(`Hostable MCP server: ${path19.join(resolvedOutDir, SERVER_ENTRYPOINT)}`);
|
|
5115
5180
|
}
|
|
5116
|
-
if (plugins) {
|
|
5181
|
+
if (plugins ?? manifest.config.build.plugins) {
|
|
5117
5182
|
console.log("Built claude-plugin package.");
|
|
5118
5183
|
}
|
|
5119
5184
|
return;
|
|
@@ -5243,7 +5308,7 @@ async function main(argv) {
|
|
|
5243
5308
|
console.log(`Sidecar
|
|
5244
5309
|
|
|
5245
5310
|
Usage:
|
|
5246
|
-
sidecar build [--cwd <dir>] [--target mcp|chatgpt|claude] [--host node|vercel] [--out <dir>] [--plugins] [--strict]
|
|
5311
|
+
sidecar build [--cwd <dir>] [--target mcp|chatgpt|claude] [--host node|vercel] [--out <dir>] [--plugins|--no-plugins] [--strict]
|
|
5247
5312
|
sidecar check [--cwd <dir>] [--target mcp|chatgpt|claude] [--strict]
|
|
5248
5313
|
sidecar dev [--cwd <dir>] [--target mcp|chatgpt|claude] [--port <port>] [--tunnel [cloudflared|wrangler]]
|
|
5249
5314
|
sidecar inspect [--cwd <dir>] [--target mcp|chatgpt|claude]
|
|
@@ -5251,20 +5316,51 @@ Usage:
|
|
|
5251
5316
|
`);
|
|
5252
5317
|
}
|
|
5253
5318
|
}
|
|
5319
|
+
function defaultBuildOutDir2(host, target) {
|
|
5320
|
+
if (host === "vercel") {
|
|
5321
|
+
return ".vercel/output";
|
|
5322
|
+
}
|
|
5323
|
+
return `out/${target}`;
|
|
5324
|
+
}
|
|
5254
5325
|
function readTarget(argv) {
|
|
5255
|
-
const target =
|
|
5326
|
+
const target = readOptionalTarget(argv) ?? "mcp";
|
|
5327
|
+
return target;
|
|
5328
|
+
}
|
|
5329
|
+
function readOptionalTarget(argv) {
|
|
5330
|
+
const target = readOption(argv, "--target");
|
|
5331
|
+
if (!target) {
|
|
5332
|
+
return void 0;
|
|
5333
|
+
}
|
|
5256
5334
|
if (target === "mcp" || target === "chatgpt" || target === "claude") {
|
|
5257
5335
|
return target;
|
|
5258
5336
|
}
|
|
5259
5337
|
throw new Error(`Unsupported Sidecar target "${target}". Expected mcp, chatgpt, or claude.`);
|
|
5260
5338
|
}
|
|
5261
|
-
function
|
|
5262
|
-
const host = readOption(argv, "--host")
|
|
5339
|
+
function readOptionalHost(argv) {
|
|
5340
|
+
const host = readOption(argv, "--host");
|
|
5341
|
+
if (!host) {
|
|
5342
|
+
return void 0;
|
|
5343
|
+
}
|
|
5263
5344
|
if (host === "node" || host === "vercel") {
|
|
5264
5345
|
return host;
|
|
5265
5346
|
}
|
|
5266
5347
|
throw new Error(`Unsupported Sidecar host "${host}". Expected node or vercel.`);
|
|
5267
5348
|
}
|
|
5349
|
+
function detectHostFromEnvironment() {
|
|
5350
|
+
if (process.env.VERCEL === "1") {
|
|
5351
|
+
return "vercel";
|
|
5352
|
+
}
|
|
5353
|
+
return void 0;
|
|
5354
|
+
}
|
|
5355
|
+
function readOptionalPlugins(argv) {
|
|
5356
|
+
if (argv.includes("--plugins")) {
|
|
5357
|
+
return true;
|
|
5358
|
+
}
|
|
5359
|
+
if (argv.includes("--no-plugins")) {
|
|
5360
|
+
return false;
|
|
5361
|
+
}
|
|
5362
|
+
return void 0;
|
|
5363
|
+
}
|
|
5268
5364
|
async function previewComponents(options) {
|
|
5269
5365
|
const cliDir = path19.dirname(fileURLToPath(import.meta.url));
|
|
5270
5366
|
const css = await readFile8(path19.join(cliDir, "../../native/src/styles.css"), "utf8").catch(() => readFile8(path19.join(process.cwd(), "packages/native/src/styles.css"), "utf8")).catch(() => "");
|