@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 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 VERCEL_ENTRYPOINT = "api/sidecar.js";
2991
- async function buildServerOutput(rootDir, outDir, manifest, identity, host = "node") {
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
- await mkdir8(path17.join(outDir, "api"), { recursive: true });
3022
- await writeFile8(path17.join(outDir, VERCEL_ENTRYPOINT), renderVercelEntrypoint());
3023
- await writeFile8(path17.join(outDir, "vercel.json"), renderVercelConfig());
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 "../server/index.js";
3257
+ return `export { default } from "./server/index.js";
3225
3258
  `;
3226
3259
  }
3227
- function renderVercelConfig() {
3260
+ function renderVercelFunctionConfig() {
3228
3261
  return `${JSON.stringify({
3229
- rewrites: [
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
- source: "/(.*)",
3232
- destination: "/api/sidecar"
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 ?? "out/mcp");
3308
- await buildWidgets(rootDir, outDir, tools);
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(outDir, { recursive: true });
3363
+ await mkdir9(runtimeOutDir, { recursive: true });
3323
3364
  await writeFile9(
3324
- path18.join(outDir, "manifest.sidecar.json"),
3365
+ path18.join(runtimeOutDir, "manifest.sidecar.json"),
3325
3366
  `${JSON.stringify(manifest, null, 2)}
3326
3367
  `
3327
3368
  );
3328
- await writeFile9(path18.join(outDir, "README.md"), renderMcpReadme(manifest));
3369
+ await writeFile9(path18.join(runtimeOutDir, "README.md"), renderMcpReadme(manifest));
3329
3370
  await writeGeneratedTypes(rootDir, tools);
3330
- await buildServerOutput(rootDir, outDir, manifest, identity, host);
3331
- if (options.plugins) {
3332
- await buildPluginPackages(rootDir, path18.dirname(outDir), manifest);
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 includes a Vercel Function shim at \`api/sidecar.js\` and a \`vercel.json\` rewrite that sends Streamable HTTP traffic to \`/mcp\`. Deploy this output directory with Vercel and set \`SIDECAR_MCP_URL\` to the public \`https://.../mcp\` URL.
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 = readTarget(argv);
5098
- const host = readHost(argv);
5099
- const outDir = readOption(argv, "--out") ?? `out/${target}`;
5100
- const plugins = argv.includes("--plugins");
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 ${outDir}.`
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(outDir, VERCEL_ENTRYPOINT)}`);
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(outDir, SERVER_ENTRYPOINT)}`);
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 = readOption(argv, "--target") ?? "mcp";
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 readHost(argv) {
5262
- const host = readOption(argv, "--host") ?? "node";
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(() => "");