@sidecar-ai/compiler 0.1.0-alpha.6 → 0.1.0-alpha.7

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
@@ -1,6 +1,12 @@
1
1
  // packages/core/src/index.ts
2
+ var toolBrand = /* @__PURE__ */ Symbol.for("sidecar.tool");
2
3
  var toolResultBrand = /* @__PURE__ */ Symbol.for("sidecar.toolResult");
3
4
  var resourceResultBrand = /* @__PURE__ */ Symbol.for("sidecar.resourceResult");
5
+ function isSidecarTool(value) {
6
+ return Boolean(
7
+ value && typeof value === "object" && (value[toolBrand] || value.kind === "sidecar.tool")
8
+ );
9
+ }
4
10
  var toolResult = Object.assign(
5
11
  createToolResult,
6
12
  {
@@ -27,9 +33,9 @@ var resourceResult = Object.assign(
27
33
  );
28
34
  function createToolResult(input) {
29
35
  const resultEnvelope = stripUndefined({
30
- structuredContent: input.structuredContent,
36
+ structuredContent: stripJsonUndefined(input.structuredContent),
31
37
  content: normalizeRequiredContent(input.content),
32
- _meta: input.meta,
38
+ _meta: stripJsonUndefined(input.meta),
33
39
  isError: input.isError
34
40
  });
35
41
  Object.defineProperty(resultEnvelope, toolResultBrand, {
@@ -271,10 +277,24 @@ function isReadonlyArray(value) {
271
277
  function stripUndefined(value) {
272
278
  return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== void 0));
273
279
  }
280
+ function stripJsonUndefined(value) {
281
+ if (value === void 0) {
282
+ return void 0;
283
+ }
284
+ if (Array.isArray(value)) {
285
+ return value.map((entry) => stripJsonUndefined(entry)).filter((entry) => entry !== void 0);
286
+ }
287
+ if (!value || typeof value !== "object") {
288
+ return value;
289
+ }
290
+ return Object.fromEntries(
291
+ Object.entries(value).map(([key, entry]) => [key, stripJsonUndefined(entry)]).filter(([, entry]) => entry !== void 0)
292
+ );
293
+ }
274
294
 
275
295
  // packages/compiler/src/analyze.ts
276
296
  import { readdir } from "fs/promises";
277
- import path4 from "path";
297
+ import path5 from "path";
278
298
  import {
279
299
  Node as Node4,
280
300
  SyntaxKind as SyntaxKind2
@@ -441,14 +461,7 @@ function devSidecarTypePaths() {
441
461
  import {
442
462
  Node as Node2
443
463
  } from "ts-morph";
444
- function getParamsSchema(definition, execute) {
445
- const explicitParams = definition.getProperty("params");
446
- if (explicitParams && Node2.isPropertyAssignment(explicitParams)) {
447
- const inferred = getSchemaFromZodProperty(explicitParams);
448
- if (inferred) {
449
- return inferred;
450
- }
451
- }
464
+ function getParamsSchema(_definition, execute) {
452
465
  const [params] = execute.getParameters();
453
466
  if (!params) {
454
467
  return emptyObjectSchema();
@@ -469,74 +482,6 @@ function getOutputSchema(definition, execute) {
469
482
  }
470
483
  return typeToJsonSchema(returnType);
471
484
  }
472
- function getSchemaFromZodProperty(property) {
473
- const initializer = property.getInitializer();
474
- if (!initializer) {
475
- return void 0;
476
- }
477
- if (Node2.isCallExpression(initializer) && initializer.getExpression().getText().endsWith(".object")) {
478
- const [shape] = initializer.getArguments();
479
- if (shape && Node2.isObjectLiteralExpression(shape)) {
480
- return zodObjectLiteralToSchema(shape);
481
- }
482
- }
483
- return void 0;
484
- }
485
- function zodObjectLiteralToSchema(shape) {
486
- const properties = {};
487
- const required = [];
488
- for (const property of shape.getProperties()) {
489
- if (!Node2.isPropertyAssignment(property)) {
490
- continue;
491
- }
492
- const name = property.getName().replace(/^["']|["']$/g, "");
493
- const initializer = property.getInitializer();
494
- if (!initializer) {
495
- continue;
496
- }
497
- const propertySchema = zodExpressionToSchema(initializer);
498
- properties[name] = propertySchema.schema;
499
- if (!propertySchema.optional) {
500
- required.push(name);
501
- }
502
- }
503
- return {
504
- type: "object",
505
- properties,
506
- required,
507
- additionalProperties: false
508
- };
509
- }
510
- function zodExpressionToSchema(expression) {
511
- const text = expression.getText();
512
- const optional = /\.optional\(\)/.test(text) || /\.default\(/.test(text);
513
- const schema = {};
514
- if (/z\.string\(\)/.test(text)) {
515
- schema.type = "string";
516
- } else if (/z\.number\(\)/.test(text)) {
517
- schema.type = "number";
518
- } else if (/z\.boolean\(\)/.test(text)) {
519
- schema.type = "boolean";
520
- } else if (/z\.array\(/.test(text)) {
521
- schema.type = "array";
522
- schema.items = {};
523
- } else {
524
- schema.type = "object";
525
- }
526
- const min = text.match(/\.min\((\d+)/);
527
- const max = text.match(/\.max\((\d+)/);
528
- if (schema.type === "string") {
529
- if (min) schema.minLength = Number(min[1]);
530
- if (max) schema.maxLength = Number(max[1]);
531
- } else {
532
- if (min) schema.minimum = Number(min[1]);
533
- if (max) schema.maximum = Number(max[1]);
534
- }
535
- if (/\.int\(\)/.test(text)) {
536
- schema.type = "integer";
537
- }
538
- return { schema, optional };
539
- }
540
485
  function typeToJsonSchema(type, description) {
541
486
  const withoutUndefined = removeUndefined(type);
542
487
  const schema = typeToJsonSchemaInner(withoutUndefined);
@@ -682,11 +627,102 @@ function schemaDescription(symbol) {
682
627
  }).find((comment) => comment.trim().length > 0);
683
628
  }
684
629
 
630
+ // packages/compiler/src/runtime-schema.ts
631
+ import { existsSync as existsSync2 } from "fs";
632
+ import path3 from "path";
633
+ import { pathToFileURL } from "url";
634
+ import { tsImport } from "tsx/esm/api";
635
+ async function readRuntimeToolInputSchema(rootDir, sourcePath) {
636
+ let sidecarTool;
637
+ try {
638
+ sidecarTool = await importRuntimeTool(rootDir, sourcePath);
639
+ } catch (error) {
640
+ warnRuntimeSchemaFallback(sourcePath, error);
641
+ return void 0;
642
+ }
643
+ if (!sidecarTool.params) {
644
+ return void 0;
645
+ }
646
+ try {
647
+ return await paramsToJsonSchema(sidecarTool.params);
648
+ } catch (error) {
649
+ warnRuntimeSchemaFallback(sourcePath, error);
650
+ return void 0;
651
+ }
652
+ }
653
+ async function importRuntimeTool(rootDir, sourcePath) {
654
+ const module = await tsImport(pathToFileURL(sourcePath).href, {
655
+ parentURL: runtimeParentUrl(rootDir),
656
+ tsconfig: runtimeTsconfig(rootDir)
657
+ });
658
+ const defaultExport = unwrapRuntimeDefault(module.default);
659
+ if (!isSidecarTool(defaultExport)) {
660
+ throw new Error(`${path3.relative(rootDir, sourcePath)} must default-export tool({ ... }).`);
661
+ }
662
+ return defaultExport;
663
+ }
664
+ async function paramsToJsonSchema(params) {
665
+ const instanceConverter = readInstanceConverter(params);
666
+ if (instanceConverter) {
667
+ return ensureJsonSchema(instanceConverter({ io: "input" }));
668
+ }
669
+ if (isZodMiniSchema(params)) {
670
+ const zod = await import("zod/v4-mini");
671
+ if (typeof zod.toJSONSchema === "function") {
672
+ return ensureJsonSchema(zod.toJSONSchema(params, { io: "input" }));
673
+ }
674
+ }
675
+ return void 0;
676
+ }
677
+ function readInstanceConverter(params) {
678
+ if (!params || typeof params !== "object") {
679
+ return void 0;
680
+ }
681
+ const record = params;
682
+ const converter = record.toJSONSchema ?? record.toJsonSchema;
683
+ return typeof converter === "function" ? converter.bind(params) : void 0;
684
+ }
685
+ function isZodMiniSchema(params) {
686
+ return Boolean(params && typeof params === "object" && "_zod" in params);
687
+ }
688
+ function ensureJsonSchema(value) {
689
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
690
+ return void 0;
691
+ }
692
+ return value;
693
+ }
694
+ function runtimeParentUrl(rootDir) {
695
+ const configPath = path3.join(rootDir, "sidecar.config.ts");
696
+ return pathToFileURL(existsSync2(configPath) ? configPath : rootDir).href;
697
+ }
698
+ function runtimeTsconfig(rootDir) {
699
+ const projectTsconfig = path3.join(rootDir, "tsconfig.json");
700
+ if (existsSync2(projectTsconfig)) {
701
+ return projectTsconfig;
702
+ }
703
+ const repoTsconfig = path3.join(process.cwd(), "tsconfig.json");
704
+ const repoCore = path3.join(process.cwd(), "packages", "core", "src", "index.ts");
705
+ return existsSyncSafe(repoTsconfig) && existsSyncSafe(repoCore) ? repoTsconfig : false;
706
+ }
707
+ function unwrapRuntimeDefault(value) {
708
+ if (value && typeof value === "object" && "default" in value && Object.keys(value).every((key) => key === "default" || key === "__esModule")) {
709
+ return unwrapRuntimeDefault(value.default);
710
+ }
711
+ return value;
712
+ }
713
+ function warnRuntimeSchemaFallback(sourcePath, error) {
714
+ const message = error instanceof Error ? error.message : String(error);
715
+ console.warn(
716
+ `[sidecar] Could not convert runtime params schema for ${sourcePath}; falling back to TypeScript parameter inference. ${message}`
717
+ );
718
+ }
719
+
685
720
  // packages/compiler/src/widgets.ts
686
721
  import { createHash } from "crypto";
687
- import { existsSync as existsSync2 } from "fs";
722
+ import { existsSync as existsSync3 } from "fs";
688
723
  import { mkdir, readFile, writeFile } from "fs/promises";
689
- import path3 from "path";
724
+ import path4 from "path";
725
+ import { pathToFileURL as pathToFileURL2 } from "url";
690
726
  import { build as esbuild } from "esbuild";
691
727
  import postcss from "postcss";
692
728
  import {
@@ -694,28 +730,29 @@ import {
694
730
  SyntaxKind
695
731
  } from "ts-morph";
696
732
  var CLAUDE_FONT_RESOURCE_DOMAIN = "https://assets.claude.ai";
697
- async function buildWidgets(rootDir, outDir, tools) {
733
+ async function buildWidgets(rootDir, outDir, tools, config = void 0) {
698
734
  const widgets = tools.filter(
699
735
  (entry) => Boolean(entry.widget)
700
736
  );
701
737
  if (!widgets.length) {
702
738
  return;
703
739
  }
704
- const cacheDir = path3.join(rootDir, ".sidecar", "cache", "widgets");
740
+ const cacheDir = path4.join(rootDir, ".sidecar", "cache", "widgets");
705
741
  await mkdir(cacheDir, { recursive: true });
706
742
  const appStyle = await prepareAppStyle(rootDir, cacheDir);
743
+ const configure = await loadWidgetBundlerHook(rootDir, cacheDir, config?.configure);
707
744
  for (const entry of widgets) {
708
- const sourceFile = path3.join(rootDir, entry.widget.sourceFile);
745
+ const sourceFile = path4.join(rootDir, entry.widget.sourceFile);
709
746
  const safeId = safePathSegment(entry.id);
710
- const entryFile = path3.join(cacheDir, `${safeId}.entry.tsx`);
711
- const importPath = toImportSpecifier(path3.dirname(entryFile), sourceFile);
747
+ const entryFile = path4.join(cacheDir, `${safeId}.entry.tsx`);
748
+ const importPath = toImportSpecifier(path4.dirname(entryFile), sourceFile);
712
749
  await writeFile(
713
750
  entryFile,
714
751
  `import React from "react";
715
752
  import { createRoot } from "react-dom/client";
716
753
  import { SidecarWidgetRoot } from "@sidecar-ai/react";
717
754
  import "@sidecar-ai/native/styles.css";
718
- ${appStyle ? `import ${JSON.stringify(toImportSpecifier(path3.dirname(entryFile), appStyle))};` : ""}
755
+ ${appStyle ? `import ${JSON.stringify(toImportSpecifier(path4.dirname(entryFile), appStyle))};` : ""}
719
756
  import Component from ${JSON.stringify(importPath)};
720
757
 
721
758
  createRoot(document.getElementById("root")!).render(
@@ -723,7 +760,7 @@ createRoot(document.getElementById("root")!).render(
723
760
  );
724
761
  `
725
762
  );
726
- const bundled = await esbuild({
763
+ const baseOptions = enforceWidgetBuildInvariants({
727
764
  absWorkingDir: rootDir,
728
765
  alias: devSidecarBundleAliases(rootDir),
729
766
  bundle: true,
@@ -732,55 +769,184 @@ createRoot(document.getElementById("root")!).render(
732
769
  jsx: "automatic",
733
770
  minify: false,
734
771
  nodePaths: [
735
- path3.join(rootDir, "node_modules"),
736
- path3.join(process.cwd(), "node_modules")
772
+ path4.join(rootDir, "node_modules"),
773
+ path4.join(process.cwd(), "node_modules")
737
774
  ],
738
775
  outfile: "widget.js",
739
776
  platform: "browser",
740
777
  sourcemap: false,
741
778
  write: false
742
779
  });
743
- const javascript = bundled.outputFiles.find((file) => file.path.endsWith(".js"))?.text ?? "";
744
- const css = bundled.outputFiles.filter((file) => file.path.endsWith(".css")).map((file) => file.text).join("\n");
780
+ const staticOptions = widgetBuildOptionsFromConfig(rootDir, config);
781
+ const configuredOptions = configure ? await configureWidgetBuild(configure, {
782
+ rootDir,
783
+ outDir,
784
+ entryFile,
785
+ widget: {
786
+ toolId: entry.id,
787
+ toolName: entry.name,
788
+ target: entry.target,
789
+ sourceFile: entry.widget.sourceFile
790
+ },
791
+ esbuildOptions: mergeWidgetBuildOptions(baseOptions, staticOptions)
792
+ }) : void 0;
793
+ const bundled = await esbuild(enforceWidgetBuildInvariants(
794
+ mergeWidgetBuildOptions(baseOptions, staticOptions, configuredOptions),
795
+ { rootDir, entryFile }
796
+ ));
797
+ const outputFiles = bundled.outputFiles ?? [];
798
+ const javascript = outputFiles.find((file) => file.path.endsWith(".js"))?.text ?? "";
799
+ const css = outputFiles.filter((file) => file.path.endsWith(".css")).map((file) => file.text).join("\n");
745
800
  const html = renderWidgetHtml(entry.name, javascript, css);
746
801
  const hash = createHash("sha256").update(html).digest("hex").slice(0, 12);
747
- const outputDir = path3.join(outDir, "public", "widgets", safeId);
748
- const outputFile = path3.join(outputDir, `widget.${hash}.html`);
802
+ const outputDir = path4.join(outDir, "public", "widgets", safeId);
803
+ const outputFile = path4.join(outputDir, `widget.${hash}.html`);
749
804
  const resourceUri = `ui://${safeId}/widget.${hash}.html`;
750
805
  await mkdir(outputDir, { recursive: true });
751
806
  await writeFile(outputFile, html);
752
807
  entry.widget.resourceUri = resourceUri;
753
808
  entry.widget.resourceMeta = widgetResourceMeta(entry.widget.options, entry.target);
754
- entry.widget.outputFile = path3.relative(outDir, outputFile);
809
+ entry.widget.outputFile = path4.relative(outDir, outputFile);
755
810
  entry.descriptor._meta = mergeWidgetMeta(entry.descriptor._meta, widgetMeta(resourceUri, entry.widget.options, entry.target));
756
811
  }
757
812
  }
813
+ function widgetBuildOptionsFromConfig(rootDir, config) {
814
+ const esbuildConfig = config?.esbuild;
815
+ if (!esbuildConfig) {
816
+ return void 0;
817
+ }
818
+ return {
819
+ alias: normalizeAliases(rootDir, esbuildConfig.alias),
820
+ conditions: esbuildConfig.conditions,
821
+ define: esbuildConfig.define,
822
+ external: esbuildConfig.external,
823
+ jsx: esbuildConfig.jsx,
824
+ jsxImportSource: esbuildConfig.jsxImportSource,
825
+ loader: esbuildConfig.loader,
826
+ mainFields: esbuildConfig.mainFields
827
+ };
828
+ }
829
+ async function loadWidgetBundlerHook(rootDir, cacheDir, hookPath) {
830
+ if (!hookPath) {
831
+ return void 0;
832
+ }
833
+ const sourcePath = path4.resolve(rootDir, hookPath);
834
+ const relative = path4.relative(rootDir, sourcePath);
835
+ if (relative.startsWith("..") || path4.isAbsolute(relative)) {
836
+ throw new Error(`Widget bundler hook must stay inside the project root: ${hookPath}`);
837
+ }
838
+ if (!existsSync3(sourcePath)) {
839
+ throw new Error(`Widget bundler hook not found: ${hookPath}`);
840
+ }
841
+ const outputFile = path4.join(cacheDir, `widget-bundler.${contentHash(hookPath)}.mjs`);
842
+ await esbuild({
843
+ absWorkingDir: rootDir,
844
+ alias: devSidecarBundleAliases(rootDir),
845
+ bundle: true,
846
+ entryPoints: [sourcePath],
847
+ format: "esm",
848
+ nodePaths: [
849
+ path4.join(rootDir, "node_modules"),
850
+ path4.join(process.cwd(), "node_modules")
851
+ ],
852
+ outfile: outputFile,
853
+ packages: "external",
854
+ platform: "node",
855
+ target: "node20"
856
+ });
857
+ const module = await import(`${pathToFileURL2(outputFile).href}?t=${Date.now()}`);
858
+ if (typeof module.default !== "function") {
859
+ throw new Error(`Widget bundler hook must default-export a function: ${hookPath}`);
860
+ }
861
+ return module.default;
862
+ }
863
+ async function configureWidgetBuild(hook, input) {
864
+ const result = await hook(input);
865
+ if (!result) {
866
+ return void 0;
867
+ }
868
+ if (typeof result === "object" && "esbuildOptions" in result) {
869
+ return result.esbuildOptions;
870
+ }
871
+ return result;
872
+ }
873
+ function mergeWidgetBuildOptions(...options) {
874
+ const merged = {};
875
+ for (const option of options) {
876
+ if (!option) {
877
+ continue;
878
+ }
879
+ const previousAlias = merged.alias;
880
+ const previousDefine = merged.define;
881
+ const previousLoader = merged.loader;
882
+ const previousExternal = merged.external;
883
+ const previousNodePaths = merged.nodePaths;
884
+ const previousPlugins = merged.plugins;
885
+ Object.assign(merged, option);
886
+ merged.alias = { ...previousAlias ?? {}, ...option.alias ?? {} };
887
+ merged.define = { ...previousDefine ?? {}, ...option.define ?? {} };
888
+ merged.loader = { ...previousLoader ?? {}, ...option.loader ?? {} };
889
+ merged.external = uniqueStrings([...previousExternal ?? [], ...option.external ?? []]);
890
+ merged.nodePaths = uniqueStrings([...previousNodePaths ?? [], ...option.nodePaths ?? []]);
891
+ merged.plugins = [...previousPlugins ?? [], ...option.plugins ?? []];
892
+ }
893
+ return merged;
894
+ }
895
+ function enforceWidgetBuildInvariants(options, required) {
896
+ return {
897
+ ...options,
898
+ absWorkingDir: required?.rootDir ?? options.absWorkingDir,
899
+ bundle: true,
900
+ entryPoints: required ? [required.entryFile] : options.entryPoints,
901
+ format: "iife",
902
+ outfile: "widget.js",
903
+ platform: "browser",
904
+ write: false
905
+ };
906
+ }
907
+ function normalizeAliases(rootDir, aliases) {
908
+ if (!aliases) {
909
+ return void 0;
910
+ }
911
+ return Object.fromEntries(
912
+ Object.entries(aliases).map(([key, value]) => [
913
+ key,
914
+ value.startsWith(".") ? path4.resolve(rootDir, value) : value
915
+ ])
916
+ );
917
+ }
918
+ function uniqueStrings(values) {
919
+ return [...new Set(values)];
920
+ }
921
+ function contentHash(value) {
922
+ return createHash("sha256").update(value).digest("hex").slice(0, 12);
923
+ }
758
924
  function devSidecarBundleAliases(rootDir) {
759
925
  const repoRoot = findSidecarRepoRoot(rootDir) ?? findSidecarRepoRoot(process.cwd());
760
926
  if (!repoRoot) {
761
927
  return void 0;
762
928
  }
763
- const reactEntry = path3.join(repoRoot, "packages", "react", "src", "index.ts");
764
- if (!existsSync2(reactEntry)) {
929
+ const reactEntry = path4.join(repoRoot, "packages", "react", "src", "index.ts");
930
+ if (!existsSync3(reactEntry)) {
765
931
  return void 0;
766
932
  }
767
933
  return {
768
- "sidecar-ai": path3.join(repoRoot, "packages", "sidecar-ai", "src", "index.ts"),
769
- "@sidecar-ai/client": path3.join(repoRoot, "packages", "client", "src", "index.ts"),
770
- "@sidecar-ai/core": path3.join(repoRoot, "packages", "core", "src", "index.ts"),
934
+ "sidecar-ai": path4.join(repoRoot, "packages", "sidecar-ai", "src", "index.ts"),
935
+ "@sidecar-ai/client": path4.join(repoRoot, "packages", "client", "src", "index.ts"),
936
+ "@sidecar-ai/core": path4.join(repoRoot, "packages", "core", "src", "index.ts"),
771
937
  "@sidecar-ai/react": reactEntry,
772
- "@sidecar-ai/native": path3.join(repoRoot, "packages", "native", "src", "index.ts"),
773
- "@sidecar-ai/native/components": path3.join(repoRoot, "packages", "native", "src", "components", "index.tsx"),
774
- "@sidecar-ai/native/styles.css": path3.join(repoRoot, "packages", "native", "src", "styles.css")
938
+ "@sidecar-ai/native": path4.join(repoRoot, "packages", "native", "src", "index.ts"),
939
+ "@sidecar-ai/native/components": path4.join(repoRoot, "packages", "native", "src", "components", "index.tsx"),
940
+ "@sidecar-ai/native/styles.css": path4.join(repoRoot, "packages", "native", "src", "styles.css")
775
941
  };
776
942
  }
777
943
  function findSidecarRepoRoot(startDir) {
778
- let current = path3.resolve(startDir);
944
+ let current = path4.resolve(startDir);
779
945
  while (true) {
780
- if (existsSync2(path3.join(current, "packages", "core", "src", "index.ts"))) {
946
+ if (existsSync3(path4.join(current, "packages", "core", "src", "index.ts"))) {
781
947
  return current;
782
948
  }
783
- const parent = path3.dirname(current);
949
+ const parent = path4.dirname(current);
784
950
  if (parent === current) {
785
951
  return void 0;
786
952
  }
@@ -788,13 +954,13 @@ function findSidecarRepoRoot(startDir) {
788
954
  }
789
955
  }
790
956
  async function prepareAppStyle(rootDir, cacheDir) {
791
- const sourceFile = path3.join(rootDir, "style.css");
792
- if (!existsSync2(sourceFile)) {
957
+ const sourceFile = path4.join(rootDir, "style.css");
958
+ if (!existsSync3(sourceFile)) {
793
959
  return void 0;
794
960
  }
795
961
  const source = await readFile(sourceFile, "utf8");
796
962
  const css = await processAppStyle(source, sourceFile);
797
- const outputFile = path3.join(cacheDir, "style.css");
963
+ const outputFile = path4.join(cacheDir, "style.css");
798
964
  await writeFile(outputFile, css);
799
965
  return outputFile;
800
966
  }
@@ -806,7 +972,7 @@ async function processAppStyle(source, from) {
806
972
  const plugins = [];
807
973
  if (cssSource.includes("@tailwind")) {
808
974
  const tailwind = await import("@tailwindcss/postcss");
809
- plugins.push(tailwind.default({ base: path3.dirname(from) }));
975
+ plugins.push(tailwind.default({ base: path4.dirname(from) }));
810
976
  }
811
977
  const autoprefixer = await import("autoprefixer");
812
978
  plugins.push(autoprefixer.default());
@@ -820,13 +986,13 @@ function needsPostcss(source) {
820
986
  return /@import\s+["']tailwindcss["']|@tailwind|@source|@theme|@plugin/.test(source);
821
987
  }
822
988
  function findWidget(rootDir, toolFile, id, target = "mcp", toolVariant = "shared") {
823
- const selected = selectWidgetFile(path3.dirname(toolFile), target, toolVariant);
989
+ const selected = selectWidgetFile(path4.dirname(toolFile), target, toolVariant);
824
990
  if (!selected) {
825
991
  return void 0;
826
992
  }
827
993
  const safeId = safePathSegment(id);
828
994
  return {
829
- sourceFile: path3.relative(rootDir, selected.filePath),
995
+ sourceFile: path4.relative(rootDir, selected.filePath),
830
996
  variant: selected.variant,
831
997
  resourceUri: `ui://${safeId}/widget.html`
832
998
  };
@@ -1008,17 +1174,17 @@ function readStringArrayProperty(definition, propertyName) {
1008
1174
  }
1009
1175
  function selectWidgetFile(directory, target, toolVariant) {
1010
1176
  if (toolVariant === "openai") {
1011
- const filePath = path3.join(directory, "widget.openai.tsx");
1012
- return existsSync2(filePath) ? { filePath, variant: "openai" } : void 0;
1177
+ const filePath = path4.join(directory, "widget.openai.tsx");
1178
+ return existsSync3(filePath) ? { filePath, variant: "openai" } : void 0;
1013
1179
  }
1014
1180
  if (toolVariant === "anthropic") {
1015
- const filePath = path3.join(directory, "widget.anthropic.tsx");
1016
- return existsSync2(filePath) ? { filePath, variant: "anthropic" } : void 0;
1181
+ const filePath = path4.join(directory, "widget.anthropic.tsx");
1182
+ return existsSync3(filePath) ? { filePath, variant: "anthropic" } : void 0;
1017
1183
  }
1018
1184
  const candidates = target === "chatgpt" || target === "claude" || target === "mcp" ? [{ name: "widget.tsx", variant: "shared" }] : [];
1019
1185
  for (const candidate of candidates) {
1020
- const filePath = path3.join(directory, candidate.name);
1021
- if (existsSync2(filePath)) {
1186
+ const filePath = path4.join(directory, candidate.name);
1187
+ if (existsSync3(filePath)) {
1022
1188
  return { filePath, variant: candidate.variant };
1023
1189
  }
1024
1190
  }
@@ -1069,17 +1235,23 @@ function stripUndefined3(value) {
1069
1235
  // packages/compiler/src/analyze.ts
1070
1236
  async function analyzeProjectTools(rootDir, options = {}) {
1071
1237
  const target = options.target ?? "mcp";
1072
- const toolFiles = await findToolFiles(path4.join(rootDir, "server"), target);
1238
+ const toolFiles = await findToolFiles(path5.join(rootDir, "server"), target);
1073
1239
  if (toolFiles.length === 0) {
1074
1240
  return [];
1075
1241
  }
1076
1242
  const project = createProject(rootDir);
1077
1243
  const authScopes = readAuthScopeCatalog(project, rootDir);
1078
- return toolFiles.map(
1079
- (candidate) => analyzeToolFile(project.addSourceFileAtPath(candidate.filePath), rootDir, {
1244
+ const sources = toolFiles.map((candidate) => ({
1245
+ candidate,
1246
+ sourceFile: project.addSourceFileAtPath(candidate.filePath)
1247
+ }));
1248
+ const runtimeInputSchemas = await readRuntimeInputSchemas(rootDir, sources);
1249
+ return sources.map(
1250
+ ({ candidate, sourceFile }) => analyzeToolFile(sourceFile, rootDir, {
1080
1251
  target,
1081
1252
  variant: candidate.variant,
1082
- authScopes
1253
+ authScopes,
1254
+ inputSchema: runtimeInputSchemas.get(candidate.filePath)
1083
1255
  })
1084
1256
  );
1085
1257
  }
@@ -1088,7 +1260,7 @@ function analyzeToolFile(sourceFile, rootDir, options = {}) {
1088
1260
  const variant = options.variant ?? "shared";
1089
1261
  const definition = findToolDefinition(sourceFile);
1090
1262
  const absoluteFile = sourceFile.getFilePath();
1091
- const directory = path4.basename(path4.dirname(absoluteFile));
1263
+ const directory = path5.basename(path5.dirname(absoluteFile));
1092
1264
  const name = getRequiredStringProperty(definition, "name", sourceFile);
1093
1265
  const id = getOptionalStringProperty(definition, "id") ?? toMachineName(directory);
1094
1266
  const description = getRequiredStringProperty(
@@ -1101,7 +1273,7 @@ function analyzeToolFile(sourceFile, rootDir, options = {}) {
1101
1273
  const hosts = readHosts(definition);
1102
1274
  const auth = readAuthPolicy(definition, options.authScopes ?? {});
1103
1275
  const execute = getExecuteFunction(definition, sourceFile);
1104
- const inputSchema = getParamsSchema(definition, execute);
1276
+ const inputSchema = options.inputSchema ?? getParamsSchema(definition, execute);
1105
1277
  const outputSchema = getOutputSchema(definition, execute);
1106
1278
  const descriptor = createToolDescriptor({
1107
1279
  name,
@@ -1119,7 +1291,7 @@ function analyzeToolFile(sourceFile, rootDir, options = {}) {
1119
1291
  validateWidgetHierarchy(sourceFile, absoluteFile, target, variant);
1120
1292
  const widget = findWidget(rootDir, absoluteFile, id, target, variant);
1121
1293
  if (widget) {
1122
- const widgetFile = path4.join(rootDir, widget.sourceFile);
1294
+ const widgetFile = path5.join(rootDir, widget.sourceFile);
1123
1295
  const project = sourceFile.getProject();
1124
1296
  const widgetSourceFile = project.getSourceFile(widgetFile) ?? project.addSourceFileAtPath(widgetFile);
1125
1297
  widget.options = {
@@ -1130,7 +1302,7 @@ function analyzeToolFile(sourceFile, rootDir, options = {}) {
1130
1302
  descriptor._meta = mergeWidgetMeta(descriptor._meta, widgetMeta(widget.resourceUri, widget.options, target));
1131
1303
  }
1132
1304
  return {
1133
- sourceFile: path4.relative(rootDir, absoluteFile),
1305
+ sourceFile: path5.relative(rootDir, absoluteFile),
1134
1306
  variant,
1135
1307
  target,
1136
1308
  directory,
@@ -1145,6 +1317,26 @@ function analyzeToolFile(sourceFile, rootDir, options = {}) {
1145
1317
  descriptor
1146
1318
  };
1147
1319
  }
1320
+ async function readRuntimeInputSchemas(rootDir, sources) {
1321
+ const schemas = /* @__PURE__ */ new Map();
1322
+ await Promise.all(sources.map(async ({ candidate, sourceFile }) => {
1323
+ const definition = findToolDefinition(sourceFile);
1324
+ if (!definitionHasRuntimeParams(definition)) {
1325
+ return;
1326
+ }
1327
+ const schema = await readRuntimeToolInputSchema(rootDir, candidate.filePath);
1328
+ if (schema) {
1329
+ schemas.set(candidate.filePath, schema);
1330
+ }
1331
+ }));
1332
+ return schemas;
1333
+ }
1334
+ function definitionHasRuntimeParams(definition) {
1335
+ if (definition.getProperty("params")) {
1336
+ return true;
1337
+ }
1338
+ return Boolean(getWithParamsCall(definition));
1339
+ }
1148
1340
  function readAuthPolicy(definition, authScopes) {
1149
1341
  const initializer = readObjectProperty2(definition, "auth");
1150
1342
  if (!initializer) {
@@ -1161,7 +1353,7 @@ function readAuthPolicy(definition, authScopes) {
1161
1353
  return { authenticated: true };
1162
1354
  }
1163
1355
  function readAuthScopeCatalog(project, rootDir) {
1164
- const authPath = path4.join(rootDir, "auth.ts");
1356
+ const authPath = path5.join(rootDir, "auth.ts");
1165
1357
  if (!existsSyncSafe(authPath)) {
1166
1358
  return {};
1167
1359
  }
@@ -1243,12 +1435,12 @@ function isNamedCall(call, name) {
1243
1435
  return callee === name || callee.endsWith(`.${name}`);
1244
1436
  }
1245
1437
  function validateWidgetHierarchy(sourceFile, toolFile, target, variant) {
1246
- const directory = path4.dirname(toolFile);
1438
+ const directory = path5.dirname(toolFile);
1247
1439
  const platformWidget = target === "chatgpt" ? "widget.openai.tsx" : target === "claude" ? "widget.anthropic.tsx" : void 0;
1248
1440
  if (!platformWidget || variant !== "shared") {
1249
1441
  return;
1250
1442
  }
1251
- if (existsSyncSafe(path4.join(directory, platformWidget))) {
1443
+ if (existsSyncSafe(path5.join(directory, platformWidget))) {
1252
1444
  const expectedTool = target === "chatgpt" ? "tool.openai.ts" : "tool.anthropic.ts";
1253
1445
  throw new CompilerError(
1254
1446
  sourceFile,
@@ -1263,7 +1455,7 @@ async function findToolFiles(serverDir, target) {
1263
1455
  const entries = await readdir(serverDir, { withFileTypes: true });
1264
1456
  const files = [];
1265
1457
  for (const entry of entries) {
1266
- const entryPath = path4.join(serverDir, entry.name);
1458
+ const entryPath = path5.join(serverDir, entry.name);
1267
1459
  if (entry.isDirectory()) {
1268
1460
  const candidate = selectToolFile(entryPath, target);
1269
1461
  if (candidate) {
@@ -1282,7 +1474,7 @@ function selectToolFile(directory, target) {
1282
1474
  { name: "tool.ts", variant: "shared" }
1283
1475
  ] : [{ name: "tool.ts", variant: "shared" }];
1284
1476
  for (const candidate of candidates) {
1285
- const filePath = path4.join(directory, candidate.name);
1477
+ const filePath = path5.join(directory, candidate.name);
1286
1478
  if (existsSyncSafe(filePath)) {
1287
1479
  return { filePath, variant: candidate.variant };
1288
1480
  }
@@ -1318,16 +1510,32 @@ function getExecuteFunction(definition, sourceFile) {
1318
1510
  return property;
1319
1511
  }
1320
1512
  if (Node4.isPropertyAssignment(property)) {
1321
- const initializer = property.getInitializer();
1513
+ const initializer = unwrapExpression(property.getInitializer());
1322
1514
  if (initializer && (Node4.isArrowFunction(initializer) || Node4.isFunctionExpression(initializer))) {
1323
1515
  return initializer;
1324
1516
  }
1517
+ const withParamsCall = getWithParamsCall(definition);
1518
+ const wrappedExecute = unwrapExpression(withParamsCall?.getArguments()[1]);
1519
+ if (wrappedExecute && (Node4.isArrowFunction(wrappedExecute) || Node4.isFunctionExpression(wrappedExecute))) {
1520
+ return wrappedExecute;
1521
+ }
1325
1522
  }
1326
1523
  throw new CompilerError(
1327
1524
  sourceFile,
1328
1525
  "execute must be a method, function expression, or arrow function."
1329
1526
  );
1330
1527
  }
1528
+ function getWithParamsCall(definition) {
1529
+ const property = definition.getProperty("execute");
1530
+ if (!property || !Node4.isPropertyAssignment(property)) {
1531
+ return void 0;
1532
+ }
1533
+ const initializer = unwrapExpression(property.getInitializer());
1534
+ if (!initializer || !Node4.isCallExpression(initializer)) {
1535
+ return void 0;
1536
+ }
1537
+ return isNamedCall(initializer, "withParams") ? initializer : void 0;
1538
+ }
1331
1539
  function getRequiredStringProperty(definition, propertyName, sourceFile) {
1332
1540
  const value = getOptionalStringProperty(definition, propertyName);
1333
1541
  if (value === void 0 || !value.trim()) {
@@ -1483,16 +1691,16 @@ function readStringArrayProperty2(definition, propertyName) {
1483
1691
 
1484
1692
  // packages/compiler/src/build.ts
1485
1693
  import { mkdir as mkdir9, writeFile as writeFile9 } from "fs/promises";
1486
- import path18 from "path";
1694
+ import path19 from "path";
1487
1695
 
1488
1696
  // packages/compiler/src/config.ts
1489
- import path5 from "path";
1697
+ import path6 from "path";
1490
1698
  import {
1491
1699
  Node as Node5,
1492
1700
  SyntaxKind as SyntaxKind3
1493
1701
  } from "ts-morph";
1494
1702
  function analyzeProjectConfig(rootDir) {
1495
- const configPath = path5.join(rootDir, "sidecar.config.ts");
1703
+ const configPath = path6.join(rootDir, "sidecar.config.ts");
1496
1704
  if (!existsSyncSafe(configPath)) {
1497
1705
  return defaultCompilerConfig();
1498
1706
  }
@@ -1508,7 +1716,8 @@ function analyzeProjectConfig(rootDir) {
1508
1716
  target: readTargetNested(definition, "build", "target"),
1509
1717
  host: readHostNested(definition, "build", "host"),
1510
1718
  outDir: readStringNested(definition, "build", "outDir"),
1511
- plugins: readBooleanNested(definition, "build", "plugins")
1719
+ plugins: readBooleanNested(definition, "build", "plugins"),
1720
+ widgets: readWidgetBuildConfig(definition)
1512
1721
  },
1513
1722
  resources: {
1514
1723
  subscribe: readBooleanNested(definition, "resources", "subscribe") ?? false,
@@ -1526,6 +1735,44 @@ function analyzeProjectConfig(rootDir) {
1526
1735
  }
1527
1736
  };
1528
1737
  }
1738
+ function readWidgetBuildConfig(definition) {
1739
+ const widgets = readObjectProperty3(readObjectProperty3(definition, "build"), "widgets");
1740
+ if (!widgets) {
1741
+ return void 0;
1742
+ }
1743
+ const config = {};
1744
+ const configure = readStringProperty3(widgets, "configure");
1745
+ const esbuild3 = readWidgetEsbuildConfig(widgets);
1746
+ if (configure) config.configure = configure;
1747
+ if (esbuild3) config.esbuild = esbuild3;
1748
+ return Object.keys(config).length ? config : void 0;
1749
+ }
1750
+ function readWidgetEsbuildConfig(widgets) {
1751
+ const esbuild3 = readObjectProperty3(widgets, "esbuild");
1752
+ if (!esbuild3) {
1753
+ return void 0;
1754
+ }
1755
+ const config = {};
1756
+ const alias = readStringRecordProperty(esbuild3, "alias");
1757
+ const define = readStringRecordProperty(esbuild3, "define");
1758
+ const external = readStringArrayProperty3(esbuild3, "external");
1759
+ const loader = readStringRecordProperty(esbuild3, "loader");
1760
+ const conditions = readStringArrayProperty3(esbuild3, "conditions");
1761
+ const mainFields = readStringArrayProperty3(esbuild3, "mainFields");
1762
+ const jsx = readStringProperty3(esbuild3, "jsx");
1763
+ const jsxImportSource = readStringProperty3(esbuild3, "jsxImportSource");
1764
+ if (alias) config.alias = alias;
1765
+ if (define) config.define = define;
1766
+ if (external) config.external = external;
1767
+ if (loader) config.loader = loader;
1768
+ if (conditions) config.conditions = conditions;
1769
+ if (mainFields) config.mainFields = mainFields;
1770
+ if (jsx === "automatic" || jsx === "transform" || jsx === "preserve") {
1771
+ config.jsx = jsx;
1772
+ }
1773
+ if (jsxImportSource) config.jsxImportSource = jsxImportSource;
1774
+ return Object.keys(config).length ? config : void 0;
1775
+ }
1529
1776
  function defaultCompilerConfig() {
1530
1777
  return {
1531
1778
  build: {},
@@ -1558,12 +1805,7 @@ function readStringNested(definition, section, propertyName) {
1558
1805
  if (!object) {
1559
1806
  return void 0;
1560
1807
  }
1561
- const property = object.getProperty(propertyName);
1562
- if (!property || !Node5.isPropertyAssignment(property)) {
1563
- return void 0;
1564
- }
1565
- const initializer = unwrapExpression(property.getInitializer());
1566
- return initializer && Node5.isStringLiteral(initializer) ? initializer.getLiteralText() : void 0;
1808
+ return readStringProperty3(object, propertyName);
1567
1809
  }
1568
1810
  function readBooleanNested(definition, section, propertyName) {
1569
1811
  const object = readObjectProperty3(definition, section);
@@ -1595,6 +1837,9 @@ function readNumberNested(definition, section, propertyName) {
1595
1837
  return initializer && Node5.isNumericLiteral(initializer) ? Number(initializer.getLiteralText()) : void 0;
1596
1838
  }
1597
1839
  function readObjectProperty3(definition, propertyName) {
1840
+ if (!definition) {
1841
+ return void 0;
1842
+ }
1598
1843
  const property = definition.getProperty(propertyName);
1599
1844
  if (!property || !Node5.isPropertyAssignment(property)) {
1600
1845
  return void 0;
@@ -1602,38 +1847,79 @@ function readObjectProperty3(definition, propertyName) {
1602
1847
  const initializer = unwrapExpression(property.getInitializer());
1603
1848
  return initializer && Node5.isObjectLiteralExpression(initializer) ? initializer : void 0;
1604
1849
  }
1850
+ function readStringProperty3(definition, propertyName) {
1851
+ const property = definition.getProperty(propertyName);
1852
+ if (!property || !Node5.isPropertyAssignment(property)) {
1853
+ return void 0;
1854
+ }
1855
+ const initializer = unwrapExpression(property.getInitializer());
1856
+ return initializer && Node5.isStringLiteral(initializer) ? initializer.getLiteralText() : void 0;
1857
+ }
1858
+ function readStringArrayProperty3(definition, propertyName) {
1859
+ const property = definition.getProperty(propertyName);
1860
+ if (!property || !Node5.isPropertyAssignment(property)) {
1861
+ return void 0;
1862
+ }
1863
+ const initializer = unwrapExpression(property.getInitializer());
1864
+ if (!initializer || !Node5.isArrayLiteralExpression(initializer)) {
1865
+ return void 0;
1866
+ }
1867
+ const values = initializer.getElements().map((element) => {
1868
+ const unwrapped = unwrapExpression(element);
1869
+ return unwrapped && Node5.isStringLiteral(unwrapped) ? unwrapped.getLiteralText() : void 0;
1870
+ });
1871
+ return values.every((value) => value !== void 0) ? values : void 0;
1872
+ }
1873
+ function readStringRecordProperty(definition, propertyName) {
1874
+ const object = readObjectProperty3(definition, propertyName);
1875
+ if (!object) {
1876
+ return void 0;
1877
+ }
1878
+ const record = {};
1879
+ for (const property of object.getProperties()) {
1880
+ if (!Node5.isPropertyAssignment(property)) {
1881
+ return void 0;
1882
+ }
1883
+ const initializer = unwrapExpression(property.getInitializer());
1884
+ if (!initializer || !Node5.isStringLiteral(initializer)) {
1885
+ return void 0;
1886
+ }
1887
+ record[property.getName().replace(/^["']|["']$/g, "")] = initializer.getLiteralText();
1888
+ }
1889
+ return record;
1890
+ }
1605
1891
  function hasProperty(definition, propertyName) {
1606
1892
  return Boolean(definition?.getProperty(propertyName));
1607
1893
  }
1608
1894
 
1609
1895
  // packages/compiler/src/diagnostics.ts
1610
- import { existsSync as existsSync3 } from "fs";
1896
+ import { existsSync as existsSync4 } from "fs";
1611
1897
  import { readFile as readFile2 } from "fs/promises";
1612
- import path6 from "path";
1898
+ import path7 from "path";
1613
1899
  async function collectProjectDiagnostics(rootDir, input) {
1614
1900
  const diagnostics = [];
1615
1901
  const tools = Array.isArray(input) ? input : input.tools;
1616
1902
  const resources = Array.isArray(input) ? [] : input.resources ?? [];
1617
1903
  const prompts = Array.isArray(input) ? [] : input.prompts ?? [];
1618
1904
  const config = Array.isArray(input) ? void 0 : input.config;
1619
- const hasAuthConfig = existsSync3(path6.join(rootDir, "auth.ts"));
1905
+ const hasAuthConfig = existsSync4(path7.join(rootDir, "auth.ts"));
1620
1906
  for (const entry of tools) {
1621
- const toolPath = path6.join(rootDir, entry.sourceFile);
1907
+ const toolPath = path7.join(rootDir, entry.sourceFile);
1622
1908
  const toolSource = await readFile2(toolPath, "utf8");
1623
- diagnostics.push(...diagnoseToolSource(rootDir, entry, toolSource, hasAuthConfig));
1909
+ diagnostics.push(...diagnoseToolSource(entry, toolSource, hasAuthConfig));
1624
1910
  if (entry.widget) {
1625
- const widgetPath = path6.join(rootDir, entry.widget.sourceFile);
1911
+ const widgetPath = path7.join(rootDir, entry.widget.sourceFile);
1626
1912
  const widgetSource = await readFile2(widgetPath, "utf8");
1627
1913
  diagnostics.push(...diagnoseWidgetSource(rootDir, entry, widgetSource));
1628
1914
  }
1629
1915
  }
1630
1916
  for (const entry of resources) {
1631
- const resourcePath = path6.join(rootDir, entry.sourceFile);
1917
+ const resourcePath = path7.join(rootDir, entry.sourceFile);
1632
1918
  const resourceSource = await readFile2(resourcePath, "utf8");
1633
1919
  diagnostics.push(...diagnoseResourceSource(entry, resourceSource));
1634
1920
  }
1635
1921
  for (const entry of prompts) {
1636
- const promptPath = path6.join(rootDir, entry.sourceFile);
1922
+ const promptPath = path7.join(rootDir, entry.sourceFile);
1637
1923
  const promptSource = await readFile2(promptPath, "utf8");
1638
1924
  diagnostics.push(...diagnosePromptSource(entry, promptSource));
1639
1925
  }
@@ -1648,7 +1934,7 @@ function formatDiagnostic(diagnostic) {
1648
1934
  hint: ${diagnostic.hint}` : "";
1649
1935
  return `${location} - ${diagnostic.severity} ${diagnostic.code}: ${diagnostic.message}${hint}`;
1650
1936
  }
1651
- function diagnoseToolSource(rootDir, entry, source, hasAuthConfig) {
1937
+ function diagnoseToolSource(entry, source, hasAuthConfig) {
1652
1938
  const diagnostics = [];
1653
1939
  const toolLocation = locate(source, "tool({");
1654
1940
  if (!entry.description.trim().startsWith("Use this when")) {
@@ -1865,21 +2151,21 @@ function isIgnored(source, code) {
1865
2151
 
1866
2152
  // packages/compiler/src/generated.ts
1867
2153
  import { mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
1868
- import path7 from "path";
2154
+ import path8 from "path";
1869
2155
  async function writeGeneratedTypes(rootDir, tools) {
1870
- const generatedDir = path7.join(rootDir, ".sidecar", "generated");
2156
+ const generatedDir = path8.join(rootDir, ".sidecar", "generated");
1871
2157
  await mkdir2(generatedDir, { recursive: true });
1872
2158
  const appCallableTools = tools.filter(isAppCallable);
1873
2159
  const methodNames = uniqueMethodNames(appCallableTools.map((entry) => toIdentifier(entry.id)));
1874
2160
  const imports = appCallableTools.map(
1875
- (entry, index) => `import type tool${index} from ${JSON.stringify(toImportSpecifier(generatedDir, path7.join(rootDir, entry.sourceFile), { extension: "js" }))};`
2161
+ (entry, index) => `import type tool${index} from ${JSON.stringify(toImportSpecifier(generatedDir, path8.join(rootDir, entry.sourceFile), { extension: "js" }))};`
1876
2162
  ).join("\n");
1877
2163
  const ids = appCallableTools.map((entry, index) => ` ${methodNames[index]}: ${JSON.stringify(entry.id)}`).join(",\n");
1878
2164
  const toolTypes = appCallableTools.map(
1879
- (entry, index) => ` ${methodNames[index]}(params: ToolParams<typeof tool${index}>): Promise<ToolOutput<typeof tool${index}>>;`
2165
+ (_entry, index) => ` ${methodNames[index]}(params: ToolParams<typeof tool${index}>): Promise<ToolOutput<typeof tool${index}>>;`
1880
2166
  ).join("\n");
1881
2167
  await writeFile2(
1882
- path7.join(generatedDir, "tools.ts"),
2168
+ path8.join(generatedDir, "tools.ts"),
1883
2169
  `/**
1884
2170
  * Generated Sidecar widget tool client.
1885
2171
  *
@@ -1929,13 +2215,13 @@ function uniqueMethodNames(names) {
1929
2215
 
1930
2216
  // packages/compiler/src/identity.ts
1931
2217
  import { readFile as readFile3 } from "fs/promises";
1932
- import path8 from "path";
2218
+ import path9 from "path";
1933
2219
  async function loadProjectIdentity(rootDir) {
1934
- const packageJson = await readOptionalJson(path8.join(rootDir, "package.json"));
2220
+ const packageJson = await readOptionalJson(path9.join(rootDir, "package.json"));
1935
2221
  const configText = await readOptionalText(
1936
- path8.join(rootDir, "sidecar.config.ts")
2222
+ path9.join(rootDir, "sidecar.config.ts")
1937
2223
  );
1938
- const name = readConfigString(configText, "name") ?? packageJson?.name ?? path8.basename(rootDir);
2224
+ const name = readConfigString(configText, "name") ?? packageJson?.name ?? path9.basename(rootDir);
1939
2225
  const version = readConfigString(configText, "version") ?? packageJson?.version ?? "0.0.0-dev";
1940
2226
  const description = readConfigString(configText, "description") ?? packageJson?.description ?? `${name} Sidecar app.`;
1941
2227
  return {
@@ -1969,32 +2255,32 @@ function readConfigString(configText, key) {
1969
2255
 
1970
2256
  // packages/compiler/src/plugins.ts
1971
2257
  import { mkdir as mkdir7, writeFile as writeFile7 } from "fs/promises";
1972
- import path14 from "path";
2258
+ import path15 from "path";
1973
2259
 
1974
2260
  // packages/compiler/src/plugin-components/agents.ts
1975
2261
  import { mkdir as mkdir3, readdir as readdir2, readFile as readFile4, writeFile as writeFile3 } from "fs/promises";
1976
- import path9 from "path";
2262
+ import path10 from "path";
1977
2263
  async function emitClaudeAgents(rootDir, destination) {
1978
- const source = path9.join(rootDir, "agents");
2264
+ const source = path10.join(rootDir, "agents");
1979
2265
  if (!existsSyncSafe(source)) {
1980
2266
  return;
1981
2267
  }
1982
2268
  const entries = await readdir2(source, { withFileTypes: true });
1983
2269
  const agentDirs = entries.filter(
1984
- (entry) => entry.isDirectory() && existsSyncSafe(path9.join(source, entry.name, "agent.ts"))
2270
+ (entry) => entry.isDirectory() && existsSyncSafe(path10.join(source, entry.name, "agent.ts"))
1985
2271
  );
1986
2272
  if (!agentDirs.length) {
1987
2273
  return;
1988
2274
  }
1989
2275
  await mkdir3(destination, { recursive: true });
1990
2276
  for (const entry of agentDirs) {
1991
- const sourceText = await readFile4(path9.join(source, entry.name, "agent.ts"), "utf8");
2277
+ const sourceText = await readFile4(path10.join(source, entry.name, "agent.ts"), "utf8");
1992
2278
  const markdown = parseClaudeAgent(
1993
2279
  sourceText,
1994
2280
  entry.name
1995
2281
  );
1996
2282
  const agentName = readObjectString(sourceText, "name") ?? entry.name;
1997
- await writeFile3(path9.join(destination, `${safeFileStem(agentName)}.md`), markdown);
2283
+ await writeFile3(path10.join(destination, `${safeFileStem(agentName)}.md`), markdown);
1998
2284
  }
1999
2285
  }
2000
2286
  function parseClaudeAgent(source, fallbackName) {
@@ -2023,41 +2309,41 @@ ${prompt.trim()}
2023
2309
 
2024
2310
  // packages/compiler/src/plugin-components/commands.ts
2025
2311
  import { cp, lstat, mkdir as mkdir4, readdir as readdir3, readFile as readFile5, writeFile as writeFile4 } from "fs/promises";
2026
- import path10 from "path";
2312
+ import path11 from "path";
2027
2313
  async function copyCommands(rootDir, destination) {
2028
- const source = path10.join(rootDir, "commands");
2314
+ const source = path11.join(rootDir, "commands");
2029
2315
  if (!existsSyncSafe(source)) {
2030
2316
  return;
2031
2317
  }
2032
2318
  await mkdir4(destination, { recursive: true });
2033
2319
  const entries = await readdir3(source, { withFileTypes: true });
2034
2320
  for (const entry of entries) {
2035
- const sourcePath = path10.join(source, entry.name);
2321
+ const sourcePath = path11.join(source, entry.name);
2036
2322
  if (entry.isFile() && entry.name.endsWith(".md")) {
2037
2323
  if (await safeCommandCopyFilter(sourcePath)) {
2038
- await cp(sourcePath, path10.join(destination, safeFileStem(entry.name.replace(/\.md$/, "")) + ".md"));
2324
+ await cp(sourcePath, path11.join(destination, safeFileStem(entry.name.replace(/\.md$/, "")) + ".md"));
2039
2325
  }
2040
2326
  continue;
2041
2327
  }
2042
2328
  if (!entry.isDirectory()) {
2043
2329
  continue;
2044
2330
  }
2045
- const dynamicCommand = path10.join(sourcePath, "command.ts");
2331
+ const dynamicCommand = path11.join(sourcePath, "command.ts");
2046
2332
  if (existsSyncSafe(dynamicCommand)) {
2047
2333
  const sourceText = await readFile5(dynamicCommand, "utf8");
2048
2334
  const markdown = parseDynamicCommand(sourceText, entry.name);
2049
2335
  const commandName = readObjectString(sourceText, "name") ?? entry.name;
2050
- await writeFile4(path10.join(destination, `${safeFileStem(commandName)}.md`), markdown);
2336
+ await writeFile4(path11.join(destination, `${safeFileStem(commandName)}.md`), markdown);
2051
2337
  continue;
2052
2338
  }
2053
- await cp(sourcePath, path10.join(destination, entry.name), {
2339
+ await cp(sourcePath, path11.join(destination, entry.name), {
2054
2340
  recursive: true,
2055
2341
  filter: safeCommandCopyFilter
2056
2342
  });
2057
2343
  }
2058
2344
  }
2059
2345
  async function safeCommandCopyFilter(sourcePath) {
2060
- const basename = path10.basename(sourcePath);
2346
+ const basename = path11.basename(sourcePath);
2061
2347
  if (basename === ".env" || basename.startsWith(".env.") || basename === "node_modules" || basename === ".git") {
2062
2348
  return false;
2063
2349
  }
@@ -2086,32 +2372,32 @@ ${Object.entries(frontmatter).map(([key, value]) => `${key}: ${yamlScalar(value)
2086
2372
 
2087
2373
  // packages/compiler/src/plugin-components/hooks.ts
2088
2374
  import { mkdir as mkdir5, readdir as readdir4, readFile as readFile6, writeFile as writeFile5 } from "fs/promises";
2089
- import path11 from "path";
2375
+ import path12 from "path";
2090
2376
  import {
2091
2377
  Node as Node6,
2092
2378
  Project as Project2,
2093
2379
  SyntaxKind as SyntaxKind4
2094
2380
  } from "ts-morph";
2095
2381
  async function copyHooks(rootDir, destination) {
2096
- const source = path11.join(rootDir, "hooks");
2382
+ const source = path12.join(rootDir, "hooks");
2097
2383
  if (!existsSyncSafe(source)) {
2098
2384
  return;
2099
2385
  }
2100
2386
  const entries = await readdir4(source, { withFileTypes: true });
2101
2387
  const hookDirs = entries.filter(
2102
- (entry) => entry.isDirectory() && existsSyncSafe(path11.join(source, entry.name, "hook.ts"))
2388
+ (entry) => entry.isDirectory() && existsSyncSafe(path12.join(source, entry.name, "hook.ts"))
2103
2389
  );
2104
2390
  if (!hookDirs.length) {
2105
2391
  return;
2106
2392
  }
2107
2393
  const config = {};
2108
2394
  for (const entry of hookDirs) {
2109
- const filePath = path11.join(source, entry.name, "hook.ts");
2395
+ const filePath = path12.join(source, entry.name, "hook.ts");
2110
2396
  mergeHooks(config, parseHookFile(await readFile6(filePath, "utf8"), entry.name));
2111
2397
  }
2112
2398
  await mkdir5(destination, { recursive: true });
2113
2399
  await writeFile5(
2114
- path11.join(destination, "hooks.json"),
2400
+ path12.join(destination, "hooks.json"),
2115
2401
  `${JSON.stringify(config, null, 2)}
2116
2402
  `
2117
2403
  );
@@ -2138,7 +2424,7 @@ function parseHookFile(source, fallbackName) {
2138
2424
  throw new Error(`hooks/${fallbackName}/hook.ts must default-export hook({ ... }) or hooks({ ... }).`);
2139
2425
  }
2140
2426
  function parseHookDefinition(definition, fallbackName) {
2141
- const event = readStringProperty3(definition, "event");
2427
+ const event = readStringProperty4(definition, "event");
2142
2428
  if (!event) {
2143
2429
  throw new Error(`hooks/${fallbackName}/hook.ts must declare an event string.`);
2144
2430
  }
@@ -2148,7 +2434,7 @@ function parseHookDefinition(definition, fallbackName) {
2148
2434
  }
2149
2435
  return {
2150
2436
  event,
2151
- matcher: readStringProperty3(definition, "matcher"),
2437
+ matcher: readStringProperty4(definition, "matcher"),
2152
2438
  run: hooks
2153
2439
  };
2154
2440
  }
@@ -2168,7 +2454,7 @@ function parseHooksDefinition(definition, fallbackName) {
2168
2454
  throw new Error(`hooks/${fallbackName}/hook.ts event "${event}" entries must be objects.`);
2169
2455
  }
2170
2456
  return stripUndefined2({
2171
- matcher: readStringProperty3(entry, "matcher"),
2457
+ matcher: readStringProperty4(entry, "matcher"),
2172
2458
  hooks: readHookArray(entry, "run", fallbackName)
2173
2459
  });
2174
2460
  });
@@ -2191,7 +2477,7 @@ function parseHookHandlers(handlers, fallbackName) {
2191
2477
  }
2192
2478
  function parseHookHandler(handler, fallbackName) {
2193
2479
  if (Node6.isObjectLiteralExpression(handler)) {
2194
- const type = readStringProperty3(handler, "type");
2480
+ const type = readStringProperty4(handler, "type");
2195
2481
  if (type !== "command" && type !== "http") {
2196
2482
  throw new Error(`hooks/${fallbackName}/hook.ts hook handlers need type "command" or "http".`);
2197
2483
  }
@@ -2241,7 +2527,7 @@ function objectLiteralToRecord(object) {
2241
2527
  }
2242
2528
  return stripUndefined2(record);
2243
2529
  }
2244
- function readStringProperty3(object, propertyName) {
2530
+ function readStringProperty4(object, propertyName) {
2245
2531
  const property = object.getProperty(propertyName);
2246
2532
  if (!property || !Node6.isPropertyAssignment(property)) {
2247
2533
  return void 0;
@@ -2285,7 +2571,7 @@ function mergeHooks(target, source) {
2285
2571
 
2286
2572
  // packages/compiler/src/plugin-components/passthrough.ts
2287
2573
  import { cp as cp2, lstat as lstat2 } from "fs/promises";
2288
- import path12 from "path";
2574
+ import path13 from "path";
2289
2575
  async function copyClaudePassthroughDirectories(rootDir, pluginDir) {
2290
2576
  for (const directory of [
2291
2577
  "assets",
@@ -2294,18 +2580,18 @@ async function copyClaudePassthroughDirectories(rootDir, pluginDir) {
2294
2580
  "output-styles",
2295
2581
  "themes"
2296
2582
  ]) {
2297
- const source = path12.join(rootDir, directory);
2583
+ const source = path13.join(rootDir, directory);
2298
2584
  if (!existsSyncSafe(source)) {
2299
2585
  continue;
2300
2586
  }
2301
- await cp2(source, path12.join(pluginDir, directory), {
2587
+ await cp2(source, path13.join(pluginDir, directory), {
2302
2588
  recursive: true,
2303
2589
  filter: safePluginCopyFilter
2304
2590
  });
2305
2591
  }
2306
2592
  }
2307
2593
  async function safePluginCopyFilter(sourcePath) {
2308
- const basename = path12.basename(sourcePath);
2594
+ const basename = path13.basename(sourcePath);
2309
2595
  if (basename === "node_modules" || basename === ".git" || basename === ".env" || basename.startsWith(".env.")) {
2310
2596
  return false;
2311
2597
  }
@@ -2314,11 +2600,11 @@ async function safePluginCopyFilter(sourcePath) {
2314
2600
  }
2315
2601
 
2316
2602
  // packages/compiler/src/plugin-components/skills.ts
2317
- import { existsSync as existsSync4 } from "fs";
2603
+ import { existsSync as existsSync5 } from "fs";
2318
2604
  import { cp as cp3, lstat as lstat3, mkdir as mkdir6, readdir as readdir5, readFile as readFile7, writeFile as writeFile6 } from "fs/promises";
2319
- import path13 from "path";
2605
+ import path14 from "path";
2320
2606
  async function copySkills(rootDir, destination) {
2321
- const source = path13.join(rootDir, "skills");
2607
+ const source = path14.join(rootDir, "skills");
2322
2608
  if (!existsSyncSafe(source)) {
2323
2609
  return;
2324
2610
  }
@@ -2328,27 +2614,27 @@ async function copySkills(rootDir, destination) {
2328
2614
  if (!entry.isDirectory()) {
2329
2615
  continue;
2330
2616
  }
2331
- const sourceDir = path13.join(source, entry.name);
2332
- const destinationDir = path13.join(destination, entry.name);
2333
- const staticSkill = path13.join(sourceDir, "SKILL.md");
2334
- const dynamicSkill = path13.join(sourceDir, "skill.ts");
2617
+ const sourceDir = path14.join(source, entry.name);
2618
+ const destinationDir = path14.join(destination, entry.name);
2619
+ const staticSkill = path14.join(sourceDir, "SKILL.md");
2620
+ const dynamicSkill = path14.join(sourceDir, "skill.ts");
2335
2621
  await mkdir6(destinationDir, { recursive: true });
2336
- if (existsSync4(staticSkill)) {
2622
+ if (existsSync5(staticSkill)) {
2337
2623
  await cp3(sourceDir, destinationDir, {
2338
2624
  recursive: true,
2339
- filter: async (sourcePath) => !sourcePath.endsWith(`${path13.sep}skill.ts`) && await safeSkillCopyFilter(sourcePath)
2625
+ filter: async (sourcePath) => !sourcePath.endsWith(`${path14.sep}skill.ts`) && await safeSkillCopyFilter(sourcePath)
2340
2626
  });
2341
- } else if (existsSync4(dynamicSkill)) {
2627
+ } else if (existsSync5(dynamicSkill)) {
2342
2628
  const generated = parseDynamicSkill(
2343
2629
  await readFile7(dynamicSkill, "utf8"),
2344
2630
  entry.name
2345
2631
  );
2346
- await writeFile6(path13.join(destinationDir, "SKILL.md"), generated);
2632
+ await writeFile6(path14.join(destinationDir, "SKILL.md"), generated);
2347
2633
  }
2348
2634
  }
2349
2635
  }
2350
2636
  async function safeSkillCopyFilter(sourcePath) {
2351
- const basename = path13.basename(sourcePath);
2637
+ const basename = path14.basename(sourcePath);
2352
2638
  if (basename === ".env" || basename.startsWith(".env.") || basename === "node_modules" || basename === ".git") {
2353
2639
  return false;
2354
2640
  }
@@ -2374,25 +2660,25 @@ async function buildPluginPackages(rootDir, outRoot, manifest) {
2374
2660
  await buildClaudePlugin(rootDir, outRoot, identity, manifest);
2375
2661
  }
2376
2662
  async function buildClaudePlugin(rootDir, outRoot, identity, manifest) {
2377
- const pluginDir = path14.join(outRoot, "claude-plugin");
2378
- await mkdir7(path14.join(pluginDir, ".claude-plugin"), { recursive: true });
2379
- await copySkills(rootDir, path14.join(pluginDir, "skills"));
2380
- await copyCommands(rootDir, path14.join(pluginDir, "commands"));
2381
- await copyHooks(rootDir, path14.join(pluginDir, "hooks"));
2382
- await emitClaudeAgents(rootDir, path14.join(pluginDir, "agents"));
2663
+ const pluginDir = path15.join(outRoot, "claude-plugin");
2664
+ await mkdir7(path15.join(pluginDir, ".claude-plugin"), { recursive: true });
2665
+ await copySkills(rootDir, path15.join(pluginDir, "skills"));
2666
+ await copyCommands(rootDir, path15.join(pluginDir, "commands"));
2667
+ await copyHooks(rootDir, path15.join(pluginDir, "hooks"));
2668
+ await emitClaudeAgents(rootDir, path15.join(pluginDir, "agents"));
2383
2669
  await copyClaudePassthroughDirectories(rootDir, pluginDir);
2384
- await writeJson(path14.join(pluginDir, ".claude-plugin", "plugin.json"), {
2670
+ await writeJson(path15.join(pluginDir, ".claude-plugin", "plugin.json"), {
2385
2671
  name: identity.slug,
2386
2672
  version: identity.version,
2387
2673
  description: identity.description,
2388
2674
  displayName: identity.name,
2389
2675
  installationPreference: "available"
2390
2676
  });
2391
- await writeJson(path14.join(pluginDir, "version.json"), {
2677
+ await writeJson(path15.join(pluginDir, "version.json"), {
2392
2678
  version: identity.version,
2393
2679
  generatedBy: "sidecar"
2394
2680
  });
2395
- await writeJson(path14.join(pluginDir, ".mcp.json"), {
2681
+ await writeJson(path15.join(pluginDir, ".mcp.json"), {
2396
2682
  mcpServers: {
2397
2683
  [identity.slug]: {
2398
2684
  type: "http",
@@ -2400,7 +2686,7 @@ async function buildClaudePlugin(rootDir, outRoot, identity, manifest) {
2400
2686
  }
2401
2687
  }
2402
2688
  });
2403
- await writeJson(path14.join(pluginDir, "settings.json"), {
2689
+ await writeJson(path15.join(pluginDir, "settings.json"), {
2404
2690
  sidecar: {
2405
2691
  tools: manifest.tools.map((entry) => entry.id),
2406
2692
  resources: manifest.resources.map((entry) => entry.uri),
@@ -2408,7 +2694,7 @@ async function buildClaudePlugin(rootDir, outRoot, identity, manifest) {
2408
2694
  }
2409
2695
  });
2410
2696
  await writeFile7(
2411
- path14.join(pluginDir, "README.md"),
2697
+ path15.join(pluginDir, "README.md"),
2412
2698
  `# ${identity.name} Claude Plugin
2413
2699
 
2414
2700
  This package was generated by Sidecar.
@@ -2422,7 +2708,7 @@ Claude/Cowork plugin-specific components such as skills, slash commands, agents,
2422
2708
  );
2423
2709
  }
2424
2710
  async function writeJson(filePath, value) {
2425
- await mkdir7(path14.dirname(filePath), { recursive: true });
2711
+ await mkdir7(path15.dirname(filePath), { recursive: true });
2426
2712
  await writeFile7(
2427
2713
  filePath,
2428
2714
  `${JSON.stringify(stripUndefined2(value), null, 2)}
@@ -2432,13 +2718,13 @@ async function writeJson(filePath, value) {
2432
2718
 
2433
2719
  // packages/compiler/src/prompts.ts
2434
2720
  import { readdir as readdir6 } from "fs/promises";
2435
- import path15 from "path";
2721
+ import path16 from "path";
2436
2722
  import {
2437
2723
  Node as Node7,
2438
2724
  SyntaxKind as SyntaxKind5
2439
2725
  } from "ts-morph";
2440
2726
  async function analyzeProjectPrompts(rootDir) {
2441
- const promptFiles = await findPromptFiles(path15.join(rootDir, "prompts"));
2727
+ const promptFiles = await findPromptFiles(path16.join(rootDir, "prompts"));
2442
2728
  if (promptFiles.length === 0) {
2443
2729
  return [];
2444
2730
  }
@@ -2450,7 +2736,7 @@ async function analyzeProjectPrompts(rootDir) {
2450
2736
  function analyzePromptFile(sourceFile, rootDir) {
2451
2737
  const definition = findPromptDefinition(sourceFile);
2452
2738
  const absoluteFile = sourceFile.getFilePath();
2453
- const directory = path15.basename(path15.dirname(absoluteFile));
2739
+ const directory = path16.basename(path16.dirname(absoluteFile));
2454
2740
  const name = getOptionalStringProperty2(definition, "name") ?? safePathSegment(directory);
2455
2741
  const title = getRequiredStringProperty2(definition, "title", sourceFile);
2456
2742
  const description = getOptionalStringProperty2(definition, "description");
@@ -2466,7 +2752,7 @@ function analyzePromptFile(sourceFile, rootDir) {
2466
2752
  throw new CompilerError(sourceFile, "prompt({ ... }) must include a run method.");
2467
2753
  }
2468
2754
  return {
2469
- sourceFile: path15.relative(rootDir, absoluteFile),
2755
+ sourceFile: path16.relative(rootDir, absoluteFile),
2470
2756
  directory,
2471
2757
  name,
2472
2758
  title,
@@ -2485,7 +2771,7 @@ async function findPromptFiles(promptsDir) {
2485
2771
  if (!entry.isDirectory()) {
2486
2772
  continue;
2487
2773
  }
2488
- const filePath = path15.join(promptsDir, entry.name, "prompt.ts");
2774
+ const filePath = path16.join(promptsDir, entry.name, "prompt.ts");
2489
2775
  if (existsSyncSafe(filePath)) {
2490
2776
  files.push(filePath);
2491
2777
  }
@@ -2607,7 +2893,7 @@ function readIcons(definition) {
2607
2893
  return [{
2608
2894
  src,
2609
2895
  mimeType: getOptionalStringProperty2(object, "mimeType"),
2610
- sizes: readStringArrayProperty3(object, "sizes")
2896
+ sizes: readStringArrayProperty4(object, "sizes")
2611
2897
  }];
2612
2898
  });
2613
2899
  return icons.length ? icons : void 0;
@@ -2620,7 +2906,7 @@ function readObjectProperty4(definition, propertyName) {
2620
2906
  const initializer = unwrapExpression(property.getInitializer());
2621
2907
  return initializer && Node7.isObjectLiteralExpression(initializer) ? initializer : void 0;
2622
2908
  }
2623
- function readStringArrayProperty3(definition, propertyName) {
2909
+ function readStringArrayProperty4(definition, propertyName) {
2624
2910
  const property = definition.getProperty(propertyName);
2625
2911
  if (!property || !Node7.isPropertyAssignment(property)) {
2626
2912
  return void 0;
@@ -2634,13 +2920,13 @@ function readStringArrayProperty3(definition, propertyName) {
2634
2920
 
2635
2921
  // packages/compiler/src/resources.ts
2636
2922
  import { readdir as readdir7 } from "fs/promises";
2637
- import path16 from "path";
2923
+ import path17 from "path";
2638
2924
  import {
2639
2925
  Node as Node8,
2640
2926
  SyntaxKind as SyntaxKind6
2641
2927
  } from "ts-morph";
2642
2928
  async function analyzeProjectResources(rootDir) {
2643
- const resourceFiles = await findResourceFiles(path16.join(rootDir, "resources"));
2929
+ const resourceFiles = await findResourceFiles(path17.join(rootDir, "resources"));
2644
2930
  if (resourceFiles.length === 0) {
2645
2931
  return [];
2646
2932
  }
@@ -2652,7 +2938,7 @@ async function analyzeProjectResources(rootDir) {
2652
2938
  function analyzeResourceFile(sourceFile, rootDir) {
2653
2939
  const definition = findResourceDefinition(sourceFile);
2654
2940
  const absoluteFile = sourceFile.getFilePath();
2655
- const directory = path16.basename(path16.dirname(absoluteFile));
2941
+ const directory = path17.basename(path17.dirname(absoluteFile));
2656
2942
  const defaultUri = `sidecar://resources/${safePathSegment(directory)}`;
2657
2943
  const name = getRequiredStringProperty3(definition, "name", sourceFile);
2658
2944
  const uri = getOptionalStringProperty3(definition, "uri") ?? defaultUri;
@@ -2670,7 +2956,7 @@ function analyzeResourceFile(sourceFile, rootDir) {
2670
2956
  throw new CompilerError(sourceFile, "resource({ ... }) must include a read method.");
2671
2957
  }
2672
2958
  return {
2673
- sourceFile: path16.relative(rootDir, absoluteFile),
2959
+ sourceFile: path17.relative(rootDir, absoluteFile),
2674
2960
  directory,
2675
2961
  uri,
2676
2962
  name,
@@ -2693,7 +2979,7 @@ async function findResourceFiles(resourcesDir) {
2693
2979
  if (!entry.isDirectory()) {
2694
2980
  continue;
2695
2981
  }
2696
- const filePath = path16.join(resourcesDir, entry.name, "resource.ts");
2982
+ const filePath = path17.join(resourcesDir, entry.name, "resource.ts");
2697
2983
  if (existsSyncSafe(filePath)) {
2698
2984
  files.push(filePath);
2699
2985
  }
@@ -2772,7 +3058,7 @@ function readAnnotations2(definition) {
2772
3058
  return void 0;
2773
3059
  }
2774
3060
  const annotations = {};
2775
- const audience = readStringArrayProperty4(initializer, "audience")?.filter((value) => value === "user" || value === "assistant");
3061
+ const audience = readStringArrayProperty5(initializer, "audience")?.filter((value) => value === "user" || value === "assistant");
2776
3062
  const priority = getOptionalNumberProperty(initializer, "priority");
2777
3063
  const lastModified = getOptionalStringProperty3(initializer, "lastModified");
2778
3064
  if (audience?.length) annotations.audience = audience;
@@ -2801,7 +3087,7 @@ function readIcons2(definition) {
2801
3087
  return [{
2802
3088
  src,
2803
3089
  mimeType: getOptionalStringProperty3(object, "mimeType"),
2804
- sizes: readStringArrayProperty4(object, "sizes")
3090
+ sizes: readStringArrayProperty5(object, "sizes")
2805
3091
  }];
2806
3092
  });
2807
3093
  return icons.length ? icons : void 0;
@@ -2814,7 +3100,7 @@ function readObjectProperty5(definition, propertyName) {
2814
3100
  const initializer = unwrapExpression(property.getInitializer());
2815
3101
  return initializer && Node8.isObjectLiteralExpression(initializer) ? initializer : void 0;
2816
3102
  }
2817
- function readStringArrayProperty4(definition, propertyName) {
3103
+ function readStringArrayProperty5(definition, propertyName) {
2818
3104
  const property = definition.getProperty(propertyName);
2819
3105
  if (!property || !Node8.isPropertyAssignment(property)) {
2820
3106
  return void 0;
@@ -2827,21 +3113,21 @@ function readStringArrayProperty4(definition, propertyName) {
2827
3113
  }
2828
3114
 
2829
3115
  // packages/compiler/src/server-output.ts
2830
- import { existsSync as existsSync5 } from "fs";
3116
+ import { existsSync as existsSync6 } from "fs";
2831
3117
  import { mkdir as mkdir8, rm, writeFile as writeFile8 } from "fs/promises";
2832
- import path17 from "path";
3118
+ import path18 from "path";
2833
3119
  import { build as esbuild2 } from "esbuild";
2834
3120
  var SERVER_ENTRYPOINT = "server/index.js";
2835
3121
  var VERCEL_FUNCTION_DIR = "functions/api/sidecar.func";
2836
3122
  var VERCEL_ENTRYPOINT = `${VERCEL_FUNCTION_DIR}/index.js`;
2837
3123
  var VERCEL_HANDLER_FILE = "index.js";
2838
3124
  async function buildServerOutput(rootDir, outDir, manifest, identity, host = "node", options = {}) {
2839
- const cacheDir = path17.join(rootDir, ".sidecar", "cache", "server");
3125
+ const cacheDir = path18.join(rootDir, ".sidecar", "cache", "server");
2840
3126
  await mkdir8(cacheDir, { recursive: true });
2841
- const entryFile = path17.join(cacheDir, "index.ts");
3127
+ const entryFile = path18.join(cacheDir, "index.ts");
2842
3128
  await writeFile8(entryFile, renderServerEntry(rootDir, entryFile, manifest, identity));
2843
- const serverFile = path17.join(outDir, SERVER_ENTRYPOINT);
2844
- await mkdir8(path17.dirname(serverFile), { recursive: true });
3129
+ const serverFile = path18.join(outDir, SERVER_ENTRYPOINT);
3130
+ await mkdir8(path18.dirname(serverFile), { recursive: true });
2845
3131
  await esbuild2({
2846
3132
  absWorkingDir: rootDir,
2847
3133
  alias: sidecarBundleAliases(rootDir),
@@ -2855,30 +3141,30 @@ const require = __sidecarCreateRequire(import.meta.url);`
2855
3141
  legalComments: "none",
2856
3142
  minify: false,
2857
3143
  nodePaths: [
2858
- path17.join(rootDir, "node_modules"),
2859
- path17.join(process.cwd(), "node_modules")
3144
+ path18.join(rootDir, "node_modules"),
3145
+ path18.join(process.cwd(), "node_modules")
2860
3146
  ],
2861
3147
  outfile: serverFile,
2862
3148
  platform: "node",
2863
3149
  sourcemap: false,
2864
3150
  target: "node20"
2865
3151
  });
2866
- await writeFile8(path17.join(outDir, "package.json"), renderServerPackage(identity));
3152
+ await writeFile8(path18.join(outDir, "package.json"), renderServerPackage(identity));
2867
3153
  if (host === "vercel") {
2868
3154
  const vercelOutputDir = options.vercelOutputDir ?? outDir;
2869
- await rm(path17.join(vercelOutputDir, "api"), { recursive: true, force: true });
2870
- await rm(path17.join(vercelOutputDir, "vercel.json"), { force: true });
2871
- await writeFile8(path17.join(outDir, VERCEL_HANDLER_FILE), renderVercelEntrypoint());
2872
- await writeFile8(path17.join(outDir, ".vc-config.json"), renderVercelFunctionConfig());
3155
+ await rm(path18.join(vercelOutputDir, "api"), { recursive: true, force: true });
3156
+ await rm(path18.join(vercelOutputDir, "vercel.json"), { force: true });
3157
+ await writeFile8(path18.join(outDir, VERCEL_HANDLER_FILE), renderVercelEntrypoint());
3158
+ await writeFile8(path18.join(outDir, ".vc-config.json"), renderVercelFunctionConfig());
2873
3159
  await mkdir8(vercelOutputDir, { recursive: true });
2874
- await writeFile8(path17.join(vercelOutputDir, "config.json"), renderVercelOutputConfig());
3160
+ await writeFile8(path18.join(vercelOutputDir, "config.json"), renderVercelOutputConfig());
2875
3161
  } else {
2876
- await rm(path17.join(outDir, "api"), { recursive: true, force: true });
2877
- await rm(path17.join(outDir, "vercel.json"), { force: true });
3162
+ await rm(path18.join(outDir, "api"), { recursive: true, force: true });
3163
+ await rm(path18.join(outDir, "vercel.json"), { force: true });
2878
3164
  }
2879
3165
  }
2880
3166
  function renderServerEntry(rootDir, entryFile, manifest, identity) {
2881
- const entryDir = path17.dirname(entryFile);
3167
+ const entryDir = path18.dirname(entryFile);
2882
3168
  const tools = manifest.tools;
2883
3169
  const resources = manifest.resources;
2884
3170
  const prompts = manifest.prompts;
@@ -2891,17 +3177,17 @@ function renderServerEntry(rootDir, entryFile, manifest, identity) {
2891
3177
  `import { isSidecarPrompt, isSidecarResource, isSidecarTool } from "@sidecar-ai/core";`,
2892
3178
  `import { isSidecarProxy } from "@sidecar-ai/server/proxy";`,
2893
3179
  ...tools.map(
2894
- (entry, index) => `import tool${index} from ${JSON.stringify(toImportSpecifier(entryDir, path17.join(rootDir, entry.sourceFile)))};`
3180
+ (entry, index) => `import tool${index} from ${JSON.stringify(toImportSpecifier(entryDir, path18.join(rootDir, entry.sourceFile)))};`
2895
3181
  ),
2896
3182
  ...resources.map(
2897
- (entry, index) => `import resource${index} from ${JSON.stringify(toImportSpecifier(entryDir, path17.join(rootDir, entry.sourceFile)))};`
3183
+ (entry, index) => `import resource${index} from ${JSON.stringify(toImportSpecifier(entryDir, path18.join(rootDir, entry.sourceFile)))};`
2898
3184
  ),
2899
3185
  ...prompts.map(
2900
- (entry, index) => `import prompt${index} from ${JSON.stringify(toImportSpecifier(entryDir, path17.join(rootDir, entry.sourceFile)))};`
3186
+ (entry, index) => `import prompt${index} from ${JSON.stringify(toImportSpecifier(entryDir, path18.join(rootDir, entry.sourceFile)))};`
2901
3187
  ),
2902
- existsSync5(path17.join(rootDir, "auth.ts")) ? `import authExport from ${JSON.stringify(toImportSpecifier(entryDir, path17.join(rootDir, "auth.ts")))};` : `const authExport = undefined;`,
2903
- existsSync5(path17.join(rootDir, "proxy.ts")) ? `import proxyExport from ${JSON.stringify(toImportSpecifier(entryDir, path17.join(rootDir, "proxy.ts")))};` : `const proxyExport = undefined;`,
2904
- existsSync5(path17.join(rootDir, "sidecar.config.ts")) ? `import configExport from ${JSON.stringify(toImportSpecifier(entryDir, path17.join(rootDir, "sidecar.config.ts")))};` : `const configExport = undefined;`
3188
+ existsSync6(path18.join(rootDir, "auth.ts")) ? `import authExport from ${JSON.stringify(toImportSpecifier(entryDir, path18.join(rootDir, "auth.ts")))};` : `const authExport = undefined;`,
3189
+ existsSync6(path18.join(rootDir, "proxy.ts")) ? `import proxyExport from ${JSON.stringify(toImportSpecifier(entryDir, path18.join(rootDir, "proxy.ts")))};` : `const proxyExport = undefined;`,
3190
+ existsSync6(path18.join(rootDir, "sidecar.config.ts")) ? `import configExport from ${JSON.stringify(toImportSpecifier(entryDir, path18.join(rootDir, "sidecar.config.ts")))};` : `const configExport = undefined;`
2905
3191
  ].join("\n");
2906
3192
  return `${imports}
2907
3193
 
@@ -3012,7 +3298,7 @@ function unwrapRuntimeDefault(value) {
3012
3298
  value &&
3013
3299
  typeof value === "object" &&
3014
3300
  "default" in value &&
3015
- Object.keys(value).length === 1
3301
+ Object.keys(value).every((key) => key === "default" || key === "__esModule")
3016
3302
  ) {
3017
3303
  return unwrapRuntimeDefault(value.default);
3018
3304
  }
@@ -3104,35 +3390,35 @@ function sidecarBundleAliases(rootDir) {
3104
3390
  return void 0;
3105
3391
  }
3106
3392
  return {
3107
- "sidecar-ai": path17.join(repoRoot, "packages", "sidecar-ai", "src", "index.ts"),
3108
- "@sidecar-ai/auth": path17.join(repoRoot, "packages", "auth", "src", "index.ts"),
3109
- "@sidecar-ai/core": path17.join(repoRoot, "packages", "core", "src", "index.ts"),
3110
- "@sidecar-ai/server": path17.join(repoRoot, "packages", "server", "src", "index.ts"),
3111
- "@sidecar-ai/server/proxy": path17.join(repoRoot, "packages", "server", "src", "proxy.ts"),
3112
- "@sidecar-ai/client": path17.join(repoRoot, "packages", "client", "src", "index.ts"),
3113
- "@sidecar-ai/react": path17.join(repoRoot, "packages", "react", "src", "index.ts"),
3114
- "@sidecar-ai/native": path17.join(repoRoot, "packages", "native", "src", "index.ts"),
3115
- "@sidecar-ai/native/components": path17.join(repoRoot, "packages", "native", "src", "components", "index.tsx"),
3116
- "@sidecar-ai/openai": path17.join(repoRoot, "packages", "openai", "src", "index.ts"),
3117
- "@sidecar-ai/openai/components": path17.join(repoRoot, "packages", "openai", "src", "components.tsx"),
3118
- "@sidecar-ai/openai/official": path17.join(repoRoot, "packages", "openai", "src", "official.ts"),
3119
- "@sidecar-ai/anthropic": path17.join(repoRoot, "packages", "anthropic", "src", "index.ts"),
3120
- "@sidecar-ai/anthropic/agent": path17.join(repoRoot, "packages", "anthropic", "src", "agent.ts"),
3121
- "@sidecar-ai/anthropic/command": path17.join(repoRoot, "packages", "anthropic", "src", "command.ts"),
3122
- "@sidecar-ai/anthropic/components": path17.join(repoRoot, "packages", "anthropic", "src", "components.tsx"),
3123
- "@sidecar-ai/anthropic/hooks": path17.join(repoRoot, "packages", "anthropic", "src", "hooks.ts"),
3124
- "@sidecar-ai/anthropic/mcp": path17.join(repoRoot, "packages", "anthropic", "src", "mcp.ts"),
3125
- "@sidecar-ai/anthropic/plugin": path17.join(repoRoot, "packages", "anthropic", "src", "plugin.ts"),
3126
- "@sidecar-ai/anthropic/skill": path17.join(repoRoot, "packages", "anthropic", "src", "skill.ts")
3393
+ "sidecar-ai": path18.join(repoRoot, "packages", "sidecar-ai", "src", "index.ts"),
3394
+ "@sidecar-ai/auth": path18.join(repoRoot, "packages", "auth", "src", "index.ts"),
3395
+ "@sidecar-ai/core": path18.join(repoRoot, "packages", "core", "src", "index.ts"),
3396
+ "@sidecar-ai/server": path18.join(repoRoot, "packages", "server", "src", "index.ts"),
3397
+ "@sidecar-ai/server/proxy": path18.join(repoRoot, "packages", "server", "src", "proxy.ts"),
3398
+ "@sidecar-ai/client": path18.join(repoRoot, "packages", "client", "src", "index.ts"),
3399
+ "@sidecar-ai/react": path18.join(repoRoot, "packages", "react", "src", "index.ts"),
3400
+ "@sidecar-ai/native": path18.join(repoRoot, "packages", "native", "src", "index.ts"),
3401
+ "@sidecar-ai/native/components": path18.join(repoRoot, "packages", "native", "src", "components", "index.tsx"),
3402
+ "@sidecar-ai/openai": path18.join(repoRoot, "packages", "openai", "src", "index.ts"),
3403
+ "@sidecar-ai/openai/components": path18.join(repoRoot, "packages", "openai", "src", "components.tsx"),
3404
+ "@sidecar-ai/openai/official": path18.join(repoRoot, "packages", "openai", "src", "official.ts"),
3405
+ "@sidecar-ai/anthropic": path18.join(repoRoot, "packages", "anthropic", "src", "index.ts"),
3406
+ "@sidecar-ai/anthropic/agent": path18.join(repoRoot, "packages", "anthropic", "src", "agent.ts"),
3407
+ "@sidecar-ai/anthropic/command": path18.join(repoRoot, "packages", "anthropic", "src", "command.ts"),
3408
+ "@sidecar-ai/anthropic/components": path18.join(repoRoot, "packages", "anthropic", "src", "components.tsx"),
3409
+ "@sidecar-ai/anthropic/hooks": path18.join(repoRoot, "packages", "anthropic", "src", "hooks.ts"),
3410
+ "@sidecar-ai/anthropic/mcp": path18.join(repoRoot, "packages", "anthropic", "src", "mcp.ts"),
3411
+ "@sidecar-ai/anthropic/plugin": path18.join(repoRoot, "packages", "anthropic", "src", "plugin.ts"),
3412
+ "@sidecar-ai/anthropic/skill": path18.join(repoRoot, "packages", "anthropic", "src", "skill.ts")
3127
3413
  };
3128
3414
  }
3129
3415
  function findSidecarRepoRoot2(startDir) {
3130
- let current = path17.resolve(startDir);
3416
+ let current = path18.resolve(startDir);
3131
3417
  while (true) {
3132
- if (existsSync5(path17.join(current, "packages", "core", "src", "index.ts"))) {
3418
+ if (existsSync6(path18.join(current, "packages", "core", "src", "index.ts"))) {
3133
3419
  return current;
3134
3420
  }
3135
- const parent = path17.dirname(current);
3421
+ const parent = path18.dirname(current);
3136
3422
  if (parent === current) {
3137
3423
  return void 0;
3138
3424
  }
@@ -3142,7 +3428,7 @@ function findSidecarRepoRoot2(startDir) {
3142
3428
 
3143
3429
  // packages/compiler/src/build.ts
3144
3430
  async function buildProject(options) {
3145
- const rootDir = path18.resolve(options.rootDir);
3431
+ const rootDir = path19.resolve(options.rootDir);
3146
3432
  const config = analyzeProjectConfig(rootDir);
3147
3433
  const target = options.target ?? config.build.target ?? "mcp";
3148
3434
  const host = options.host ?? config.build.host ?? "node";
@@ -3164,7 +3450,7 @@ async function buildProject(options) {
3164
3450
  }
3165
3451
  const outDir = resolveInsideRoot(rootDir, options.outDir ?? config.build.outDir ?? defaultBuildOutDir(host, target));
3166
3452
  const runtimeOutDir = resolveRuntimeOutputDir(outDir, host);
3167
- await buildWidgets(rootDir, runtimeOutDir, tools);
3453
+ await buildWidgets(rootDir, runtimeOutDir, tools, config.build.widgets);
3168
3454
  const manifest = {
3169
3455
  version: 1,
3170
3456
  target,
@@ -3180,11 +3466,11 @@ async function buildProject(options) {
3180
3466
  };
3181
3467
  await mkdir9(runtimeOutDir, { recursive: true });
3182
3468
  await writeFile9(
3183
- path18.join(runtimeOutDir, "manifest.sidecar.json"),
3469
+ path19.join(runtimeOutDir, "manifest.sidecar.json"),
3184
3470
  `${JSON.stringify(manifest, null, 2)}
3185
3471
  `
3186
3472
  );
3187
- await writeFile9(path18.join(runtimeOutDir, "README.md"), renderMcpReadme(manifest));
3473
+ await writeFile9(path19.join(runtimeOutDir, "README.md"), renderMcpReadme(manifest));
3188
3474
  await writeGeneratedTypes(rootDir, tools);
3189
3475
  await buildServerOutput(rootDir, runtimeOutDir, manifest, identity, host, {
3190
3476
  vercelOutputDir: outDir
@@ -3202,23 +3488,23 @@ function defaultBuildOutDir(host, target) {
3202
3488
  }
3203
3489
  function resolveRuntimeOutputDir(outDir, host) {
3204
3490
  if (host === "vercel") {
3205
- return path18.join(outDir, VERCEL_FUNCTION_DIR);
3491
+ return path19.join(outDir, VERCEL_FUNCTION_DIR);
3206
3492
  }
3207
3493
  return outDir;
3208
3494
  }
3209
3495
  function resolvePluginOutputBase(rootDir, outDir, host) {
3210
3496
  if (host === "vercel" && isVercelBuildOutputDir(outDir)) {
3211
- return path18.join(rootDir, "out");
3497
+ return path19.join(rootDir, "out");
3212
3498
  }
3213
- return path18.dirname(outDir);
3499
+ return path19.dirname(outDir);
3214
3500
  }
3215
3501
  function isVercelBuildOutputDir(outDir) {
3216
- return path18.basename(outDir) === "output" && path18.basename(path18.dirname(outDir)) === ".vercel";
3502
+ return path19.basename(outDir) === "output" && path19.basename(path19.dirname(outDir)) === ".vercel";
3217
3503
  }
3218
3504
  function resolveInsideRoot(rootDir, output) {
3219
- const resolved = path18.resolve(rootDir, output);
3220
- const relative = path18.relative(rootDir, resolved);
3221
- if (relative.startsWith("..") || path18.isAbsolute(relative)) {
3505
+ const resolved = path19.resolve(rootDir, output);
3506
+ const relative = path19.relative(rootDir, resolved);
3507
+ if (relative.startsWith("..") || path19.isAbsolute(relative)) {
3222
3508
  throw new Error(`Build output must stay inside the project root: ${output}`);
3223
3509
  }
3224
3510
  return resolved;