@sidecar-ai/cli 0.1.0-alpha.5 → 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,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // packages/cli/src/index.ts
4
- import { existsSync as existsSync6, realpathSync } from "fs";
4
+ import { existsSync as existsSync7, realpathSync } from "fs";
5
5
  import { mkdir as mkdir10, readFile as readFile8, writeFile as writeFile10 } from "fs/promises";
6
6
  import { createServer as createServer2 } from "http";
7
- import path19 from "path";
7
+ import path20 from "path";
8
8
  import { createInterface as createInterface2 } from "readline/promises";
9
- import { fileURLToPath, pathToFileURL } from "url";
9
+ import { fileURLToPath, pathToFileURL as pathToFileURL3 } from "url";
10
10
  import { cwd, exit, stdin as stdin2, stdout as stdout2 } from "process";
11
- import { tsImport } from "tsx/esm/api";
11
+ import { tsImport as tsImport2 } from "tsx/esm/api";
12
12
 
13
13
  // packages/auth/src/core.ts
14
14
  var authBrand = /* @__PURE__ */ Symbol.for("sidecar.auth");
@@ -66,9 +66,9 @@ var resourceResult = Object.assign(
66
66
  );
67
67
  function createToolResult(input) {
68
68
  const resultEnvelope = stripUndefined({
69
- structuredContent: input.structuredContent,
69
+ structuredContent: stripJsonUndefined(input.structuredContent),
70
70
  content: normalizeRequiredContent(input.content),
71
- _meta: input.meta,
71
+ _meta: stripJsonUndefined(input.meta),
72
72
  isError: input.isError
73
73
  });
74
74
  Object.defineProperty(resultEnvelope, toolResultBrand, {
@@ -112,9 +112,9 @@ function normalizeToolResult(value) {
112
112
  );
113
113
  }
114
114
  return stripUndefined({
115
- structuredContent: value.structuredContent,
115
+ structuredContent: stripJsonUndefined(value.structuredContent),
116
116
  content: value.content ?? [],
117
- _meta: value._meta,
117
+ _meta: stripJsonUndefined(value._meta),
118
118
  isError: value.isError
119
119
  });
120
120
  }
@@ -453,10 +453,24 @@ function normalizePromptResult(value, defaultDescription) {
453
453
  function stripUndefined(value) {
454
454
  return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== void 0));
455
455
  }
456
+ function stripJsonUndefined(value) {
457
+ if (value === void 0) {
458
+ return void 0;
459
+ }
460
+ if (Array.isArray(value)) {
461
+ return value.map((entry) => stripJsonUndefined(entry)).filter((entry) => entry !== void 0);
462
+ }
463
+ if (!value || typeof value !== "object") {
464
+ return value;
465
+ }
466
+ return Object.fromEntries(
467
+ Object.entries(value).map(([key, entry]) => [key, stripJsonUndefined(entry)]).filter(([, entry]) => entry !== void 0)
468
+ );
469
+ }
456
470
 
457
471
  // packages/compiler/src/analyze.ts
458
472
  import { readdir } from "fs/promises";
459
- import path4 from "path";
473
+ import path5 from "path";
460
474
  import {
461
475
  Node as Node4,
462
476
  SyntaxKind as SyntaxKind2
@@ -623,14 +637,7 @@ function devSidecarTypePaths() {
623
637
  import {
624
638
  Node as Node2
625
639
  } from "ts-morph";
626
- function getParamsSchema(definition, execute) {
627
- const explicitParams = definition.getProperty("params");
628
- if (explicitParams && Node2.isPropertyAssignment(explicitParams)) {
629
- const inferred = getSchemaFromZodProperty(explicitParams);
630
- if (inferred) {
631
- return inferred;
632
- }
633
- }
640
+ function getParamsSchema(_definition, execute) {
634
641
  const [params] = execute.getParameters();
635
642
  if (!params) {
636
643
  return emptyObjectSchema();
@@ -651,74 +658,6 @@ function getOutputSchema(definition, execute) {
651
658
  }
652
659
  return typeToJsonSchema(returnType);
653
660
  }
654
- function getSchemaFromZodProperty(property) {
655
- const initializer = property.getInitializer();
656
- if (!initializer) {
657
- return void 0;
658
- }
659
- if (Node2.isCallExpression(initializer) && initializer.getExpression().getText().endsWith(".object")) {
660
- const [shape] = initializer.getArguments();
661
- if (shape && Node2.isObjectLiteralExpression(shape)) {
662
- return zodObjectLiteralToSchema(shape);
663
- }
664
- }
665
- return void 0;
666
- }
667
- function zodObjectLiteralToSchema(shape) {
668
- const properties = {};
669
- const required = [];
670
- for (const property of shape.getProperties()) {
671
- if (!Node2.isPropertyAssignment(property)) {
672
- continue;
673
- }
674
- const name = property.getName().replace(/^["']|["']$/g, "");
675
- const initializer = property.getInitializer();
676
- if (!initializer) {
677
- continue;
678
- }
679
- const propertySchema = zodExpressionToSchema(initializer);
680
- properties[name] = propertySchema.schema;
681
- if (!propertySchema.optional) {
682
- required.push(name);
683
- }
684
- }
685
- return {
686
- type: "object",
687
- properties,
688
- required,
689
- additionalProperties: false
690
- };
691
- }
692
- function zodExpressionToSchema(expression) {
693
- const text = expression.getText();
694
- const optional = /\.optional\(\)/.test(text) || /\.default\(/.test(text);
695
- const schema = {};
696
- if (/z\.string\(\)/.test(text)) {
697
- schema.type = "string";
698
- } else if (/z\.number\(\)/.test(text)) {
699
- schema.type = "number";
700
- } else if (/z\.boolean\(\)/.test(text)) {
701
- schema.type = "boolean";
702
- } else if (/z\.array\(/.test(text)) {
703
- schema.type = "array";
704
- schema.items = {};
705
- } else {
706
- schema.type = "object";
707
- }
708
- const min = text.match(/\.min\((\d+)/);
709
- const max = text.match(/\.max\((\d+)/);
710
- if (schema.type === "string") {
711
- if (min) schema.minLength = Number(min[1]);
712
- if (max) schema.maxLength = Number(max[1]);
713
- } else {
714
- if (min) schema.minimum = Number(min[1]);
715
- if (max) schema.maximum = Number(max[1]);
716
- }
717
- if (/\.int\(\)/.test(text)) {
718
- schema.type = "integer";
719
- }
720
- return { schema, optional };
721
- }
722
661
  function typeToJsonSchema(type, description) {
723
662
  const withoutUndefined = removeUndefined(type);
724
663
  const schema = typeToJsonSchemaInner(withoutUndefined);
@@ -864,11 +803,102 @@ function schemaDescription(symbol) {
864
803
  }).find((comment) => comment.trim().length > 0);
865
804
  }
866
805
 
806
+ // packages/compiler/src/runtime-schema.ts
807
+ import { existsSync as existsSync2 } from "fs";
808
+ import path3 from "path";
809
+ import { pathToFileURL } from "url";
810
+ import { tsImport } from "tsx/esm/api";
811
+ async function readRuntimeToolInputSchema(rootDir, sourcePath) {
812
+ let sidecarTool;
813
+ try {
814
+ sidecarTool = await importRuntimeTool(rootDir, sourcePath);
815
+ } catch (error) {
816
+ warnRuntimeSchemaFallback(sourcePath, error);
817
+ return void 0;
818
+ }
819
+ if (!sidecarTool.params) {
820
+ return void 0;
821
+ }
822
+ try {
823
+ return await paramsToJsonSchema(sidecarTool.params);
824
+ } catch (error) {
825
+ warnRuntimeSchemaFallback(sourcePath, error);
826
+ return void 0;
827
+ }
828
+ }
829
+ async function importRuntimeTool(rootDir, sourcePath) {
830
+ const module = await tsImport(pathToFileURL(sourcePath).href, {
831
+ parentURL: runtimeParentUrl(rootDir),
832
+ tsconfig: runtimeTsconfig(rootDir)
833
+ });
834
+ const defaultExport = unwrapRuntimeDefault(module.default);
835
+ if (!isSidecarTool(defaultExport)) {
836
+ throw new Error(`${path3.relative(rootDir, sourcePath)} must default-export tool({ ... }).`);
837
+ }
838
+ return defaultExport;
839
+ }
840
+ async function paramsToJsonSchema(params) {
841
+ const instanceConverter = readInstanceConverter(params);
842
+ if (instanceConverter) {
843
+ return ensureJsonSchema(instanceConverter({ io: "input" }));
844
+ }
845
+ if (isZodMiniSchema(params)) {
846
+ const zod = await import("zod/v4-mini");
847
+ if (typeof zod.toJSONSchema === "function") {
848
+ return ensureJsonSchema(zod.toJSONSchema(params, { io: "input" }));
849
+ }
850
+ }
851
+ return void 0;
852
+ }
853
+ function readInstanceConverter(params) {
854
+ if (!params || typeof params !== "object") {
855
+ return void 0;
856
+ }
857
+ const record = params;
858
+ const converter = record.toJSONSchema ?? record.toJsonSchema;
859
+ return typeof converter === "function" ? converter.bind(params) : void 0;
860
+ }
861
+ function isZodMiniSchema(params) {
862
+ return Boolean(params && typeof params === "object" && "_zod" in params);
863
+ }
864
+ function ensureJsonSchema(value) {
865
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
866
+ return void 0;
867
+ }
868
+ return value;
869
+ }
870
+ function runtimeParentUrl(rootDir) {
871
+ const configPath = path3.join(rootDir, "sidecar.config.ts");
872
+ return pathToFileURL(existsSync2(configPath) ? configPath : rootDir).href;
873
+ }
874
+ function runtimeTsconfig(rootDir) {
875
+ const projectTsconfig = path3.join(rootDir, "tsconfig.json");
876
+ if (existsSync2(projectTsconfig)) {
877
+ return projectTsconfig;
878
+ }
879
+ const repoTsconfig = path3.join(process.cwd(), "tsconfig.json");
880
+ const repoCore = path3.join(process.cwd(), "packages", "core", "src", "index.ts");
881
+ return existsSyncSafe(repoTsconfig) && existsSyncSafe(repoCore) ? repoTsconfig : false;
882
+ }
883
+ function unwrapRuntimeDefault(value) {
884
+ if (value && typeof value === "object" && "default" in value && Object.keys(value).every((key) => key === "default" || key === "__esModule")) {
885
+ return unwrapRuntimeDefault(value.default);
886
+ }
887
+ return value;
888
+ }
889
+ function warnRuntimeSchemaFallback(sourcePath, error) {
890
+ const message = error instanceof Error ? error.message : String(error);
891
+ console.warn(
892
+ `[sidecar] Could not convert runtime params schema for ${sourcePath}; falling back to TypeScript parameter inference. ${message}`
893
+ );
894
+ }
895
+
867
896
  // packages/compiler/src/widgets.ts
868
897
  import { createHash } from "crypto";
869
- import { existsSync as existsSync2 } from "fs";
898
+ import { existsSync as existsSync3 } from "fs";
870
899
  import { mkdir, readFile, writeFile } from "fs/promises";
871
- import path3 from "path";
900
+ import path4 from "path";
901
+ import { pathToFileURL as pathToFileURL2 } from "url";
872
902
  import { build as esbuild } from "esbuild";
873
903
  import postcss from "postcss";
874
904
  import {
@@ -876,28 +906,29 @@ import {
876
906
  SyntaxKind
877
907
  } from "ts-morph";
878
908
  var CLAUDE_FONT_RESOURCE_DOMAIN = "https://assets.claude.ai";
879
- async function buildWidgets(rootDir, outDir, tools) {
909
+ async function buildWidgets(rootDir, outDir, tools, config = void 0) {
880
910
  const widgets = tools.filter(
881
911
  (entry) => Boolean(entry.widget)
882
912
  );
883
913
  if (!widgets.length) {
884
914
  return;
885
915
  }
886
- const cacheDir = path3.join(rootDir, ".sidecar", "cache", "widgets");
916
+ const cacheDir = path4.join(rootDir, ".sidecar", "cache", "widgets");
887
917
  await mkdir(cacheDir, { recursive: true });
888
918
  const appStyle = await prepareAppStyle(rootDir, cacheDir);
919
+ const configure = await loadWidgetBundlerHook(rootDir, cacheDir, config?.configure);
889
920
  for (const entry of widgets) {
890
- const sourceFile = path3.join(rootDir, entry.widget.sourceFile);
921
+ const sourceFile = path4.join(rootDir, entry.widget.sourceFile);
891
922
  const safeId = safePathSegment(entry.id);
892
- const entryFile = path3.join(cacheDir, `${safeId}.entry.tsx`);
893
- const importPath = toImportSpecifier(path3.dirname(entryFile), sourceFile);
923
+ const entryFile = path4.join(cacheDir, `${safeId}.entry.tsx`);
924
+ const importPath = toImportSpecifier(path4.dirname(entryFile), sourceFile);
894
925
  await writeFile(
895
926
  entryFile,
896
927
  `import React from "react";
897
928
  import { createRoot } from "react-dom/client";
898
929
  import { SidecarWidgetRoot } from "@sidecar-ai/react";
899
930
  import "@sidecar-ai/native/styles.css";
900
- ${appStyle ? `import ${JSON.stringify(toImportSpecifier(path3.dirname(entryFile), appStyle))};` : ""}
931
+ ${appStyle ? `import ${JSON.stringify(toImportSpecifier(path4.dirname(entryFile), appStyle))};` : ""}
901
932
  import Component from ${JSON.stringify(importPath)};
902
933
 
903
934
  createRoot(document.getElementById("root")!).render(
@@ -905,7 +936,7 @@ createRoot(document.getElementById("root")!).render(
905
936
  );
906
937
  `
907
938
  );
908
- const bundled = await esbuild({
939
+ const baseOptions = enforceWidgetBuildInvariants({
909
940
  absWorkingDir: rootDir,
910
941
  alias: devSidecarBundleAliases(rootDir),
911
942
  bundle: true,
@@ -914,55 +945,184 @@ createRoot(document.getElementById("root")!).render(
914
945
  jsx: "automatic",
915
946
  minify: false,
916
947
  nodePaths: [
917
- path3.join(rootDir, "node_modules"),
918
- path3.join(process.cwd(), "node_modules")
948
+ path4.join(rootDir, "node_modules"),
949
+ path4.join(process.cwd(), "node_modules")
919
950
  ],
920
951
  outfile: "widget.js",
921
952
  platform: "browser",
922
953
  sourcemap: false,
923
954
  write: false
924
955
  });
925
- const javascript = bundled.outputFiles.find((file) => file.path.endsWith(".js"))?.text ?? "";
926
- const css = bundled.outputFiles.filter((file) => file.path.endsWith(".css")).map((file) => file.text).join("\n");
956
+ const staticOptions = widgetBuildOptionsFromConfig(rootDir, config);
957
+ const configuredOptions = configure ? await configureWidgetBuild(configure, {
958
+ rootDir,
959
+ outDir,
960
+ entryFile,
961
+ widget: {
962
+ toolId: entry.id,
963
+ toolName: entry.name,
964
+ target: entry.target,
965
+ sourceFile: entry.widget.sourceFile
966
+ },
967
+ esbuildOptions: mergeWidgetBuildOptions(baseOptions, staticOptions)
968
+ }) : void 0;
969
+ const bundled = await esbuild(enforceWidgetBuildInvariants(
970
+ mergeWidgetBuildOptions(baseOptions, staticOptions, configuredOptions),
971
+ { rootDir, entryFile }
972
+ ));
973
+ const outputFiles = bundled.outputFiles ?? [];
974
+ const javascript = outputFiles.find((file) => file.path.endsWith(".js"))?.text ?? "";
975
+ const css = outputFiles.filter((file) => file.path.endsWith(".css")).map((file) => file.text).join("\n");
927
976
  const html = renderWidgetHtml(entry.name, javascript, css);
928
977
  const hash = createHash("sha256").update(html).digest("hex").slice(0, 12);
929
- const outputDir = path3.join(outDir, "public", "widgets", safeId);
930
- const outputFile = path3.join(outputDir, `widget.${hash}.html`);
978
+ const outputDir = path4.join(outDir, "public", "widgets", safeId);
979
+ const outputFile = path4.join(outputDir, `widget.${hash}.html`);
931
980
  const resourceUri = `ui://${safeId}/widget.${hash}.html`;
932
981
  await mkdir(outputDir, { recursive: true });
933
982
  await writeFile(outputFile, html);
934
983
  entry.widget.resourceUri = resourceUri;
935
984
  entry.widget.resourceMeta = widgetResourceMeta(entry.widget.options, entry.target);
936
- entry.widget.outputFile = path3.relative(outDir, outputFile);
985
+ entry.widget.outputFile = path4.relative(outDir, outputFile);
937
986
  entry.descriptor._meta = mergeWidgetMeta(entry.descriptor._meta, widgetMeta(resourceUri, entry.widget.options, entry.target));
938
987
  }
939
988
  }
989
+ function widgetBuildOptionsFromConfig(rootDir, config) {
990
+ const esbuildConfig = config?.esbuild;
991
+ if (!esbuildConfig) {
992
+ return void 0;
993
+ }
994
+ return {
995
+ alias: normalizeAliases(rootDir, esbuildConfig.alias),
996
+ conditions: esbuildConfig.conditions,
997
+ define: esbuildConfig.define,
998
+ external: esbuildConfig.external,
999
+ jsx: esbuildConfig.jsx,
1000
+ jsxImportSource: esbuildConfig.jsxImportSource,
1001
+ loader: esbuildConfig.loader,
1002
+ mainFields: esbuildConfig.mainFields
1003
+ };
1004
+ }
1005
+ async function loadWidgetBundlerHook(rootDir, cacheDir, hookPath) {
1006
+ if (!hookPath) {
1007
+ return void 0;
1008
+ }
1009
+ const sourcePath = path4.resolve(rootDir, hookPath);
1010
+ const relative = path4.relative(rootDir, sourcePath);
1011
+ if (relative.startsWith("..") || path4.isAbsolute(relative)) {
1012
+ throw new Error(`Widget bundler hook must stay inside the project root: ${hookPath}`);
1013
+ }
1014
+ if (!existsSync3(sourcePath)) {
1015
+ throw new Error(`Widget bundler hook not found: ${hookPath}`);
1016
+ }
1017
+ const outputFile = path4.join(cacheDir, `widget-bundler.${contentHash(hookPath)}.mjs`);
1018
+ await esbuild({
1019
+ absWorkingDir: rootDir,
1020
+ alias: devSidecarBundleAliases(rootDir),
1021
+ bundle: true,
1022
+ entryPoints: [sourcePath],
1023
+ format: "esm",
1024
+ nodePaths: [
1025
+ path4.join(rootDir, "node_modules"),
1026
+ path4.join(process.cwd(), "node_modules")
1027
+ ],
1028
+ outfile: outputFile,
1029
+ packages: "external",
1030
+ platform: "node",
1031
+ target: "node20"
1032
+ });
1033
+ const module = await import(`${pathToFileURL2(outputFile).href}?t=${Date.now()}`);
1034
+ if (typeof module.default !== "function") {
1035
+ throw new Error(`Widget bundler hook must default-export a function: ${hookPath}`);
1036
+ }
1037
+ return module.default;
1038
+ }
1039
+ async function configureWidgetBuild(hook, input) {
1040
+ const result = await hook(input);
1041
+ if (!result) {
1042
+ return void 0;
1043
+ }
1044
+ if (typeof result === "object" && "esbuildOptions" in result) {
1045
+ return result.esbuildOptions;
1046
+ }
1047
+ return result;
1048
+ }
1049
+ function mergeWidgetBuildOptions(...options) {
1050
+ const merged = {};
1051
+ for (const option of options) {
1052
+ if (!option) {
1053
+ continue;
1054
+ }
1055
+ const previousAlias = merged.alias;
1056
+ const previousDefine = merged.define;
1057
+ const previousLoader = merged.loader;
1058
+ const previousExternal = merged.external;
1059
+ const previousNodePaths = merged.nodePaths;
1060
+ const previousPlugins = merged.plugins;
1061
+ Object.assign(merged, option);
1062
+ merged.alias = { ...previousAlias ?? {}, ...option.alias ?? {} };
1063
+ merged.define = { ...previousDefine ?? {}, ...option.define ?? {} };
1064
+ merged.loader = { ...previousLoader ?? {}, ...option.loader ?? {} };
1065
+ merged.external = uniqueStrings([...previousExternal ?? [], ...option.external ?? []]);
1066
+ merged.nodePaths = uniqueStrings([...previousNodePaths ?? [], ...option.nodePaths ?? []]);
1067
+ merged.plugins = [...previousPlugins ?? [], ...option.plugins ?? []];
1068
+ }
1069
+ return merged;
1070
+ }
1071
+ function enforceWidgetBuildInvariants(options, required) {
1072
+ return {
1073
+ ...options,
1074
+ absWorkingDir: required?.rootDir ?? options.absWorkingDir,
1075
+ bundle: true,
1076
+ entryPoints: required ? [required.entryFile] : options.entryPoints,
1077
+ format: "iife",
1078
+ outfile: "widget.js",
1079
+ platform: "browser",
1080
+ write: false
1081
+ };
1082
+ }
1083
+ function normalizeAliases(rootDir, aliases) {
1084
+ if (!aliases) {
1085
+ return void 0;
1086
+ }
1087
+ return Object.fromEntries(
1088
+ Object.entries(aliases).map(([key, value]) => [
1089
+ key,
1090
+ value.startsWith(".") ? path4.resolve(rootDir, value) : value
1091
+ ])
1092
+ );
1093
+ }
1094
+ function uniqueStrings(values) {
1095
+ return [...new Set(values)];
1096
+ }
1097
+ function contentHash(value) {
1098
+ return createHash("sha256").update(value).digest("hex").slice(0, 12);
1099
+ }
940
1100
  function devSidecarBundleAliases(rootDir) {
941
1101
  const repoRoot = findSidecarRepoRoot(rootDir) ?? findSidecarRepoRoot(process.cwd());
942
1102
  if (!repoRoot) {
943
1103
  return void 0;
944
1104
  }
945
- const reactEntry = path3.join(repoRoot, "packages", "react", "src", "index.ts");
946
- if (!existsSync2(reactEntry)) {
1105
+ const reactEntry = path4.join(repoRoot, "packages", "react", "src", "index.ts");
1106
+ if (!existsSync3(reactEntry)) {
947
1107
  return void 0;
948
1108
  }
949
1109
  return {
950
- "sidecar-ai": path3.join(repoRoot, "packages", "sidecar-ai", "src", "index.ts"),
951
- "@sidecar-ai/client": path3.join(repoRoot, "packages", "client", "src", "index.ts"),
952
- "@sidecar-ai/core": path3.join(repoRoot, "packages", "core", "src", "index.ts"),
1110
+ "sidecar-ai": path4.join(repoRoot, "packages", "sidecar-ai", "src", "index.ts"),
1111
+ "@sidecar-ai/client": path4.join(repoRoot, "packages", "client", "src", "index.ts"),
1112
+ "@sidecar-ai/core": path4.join(repoRoot, "packages", "core", "src", "index.ts"),
953
1113
  "@sidecar-ai/react": reactEntry,
954
- "@sidecar-ai/native": path3.join(repoRoot, "packages", "native", "src", "index.ts"),
955
- "@sidecar-ai/native/components": path3.join(repoRoot, "packages", "native", "src", "components", "index.tsx"),
956
- "@sidecar-ai/native/styles.css": path3.join(repoRoot, "packages", "native", "src", "styles.css")
1114
+ "@sidecar-ai/native": path4.join(repoRoot, "packages", "native", "src", "index.ts"),
1115
+ "@sidecar-ai/native/components": path4.join(repoRoot, "packages", "native", "src", "components", "index.tsx"),
1116
+ "@sidecar-ai/native/styles.css": path4.join(repoRoot, "packages", "native", "src", "styles.css")
957
1117
  };
958
1118
  }
959
1119
  function findSidecarRepoRoot(startDir) {
960
- let current = path3.resolve(startDir);
1120
+ let current = path4.resolve(startDir);
961
1121
  while (true) {
962
- if (existsSync2(path3.join(current, "packages", "core", "src", "index.ts"))) {
1122
+ if (existsSync3(path4.join(current, "packages", "core", "src", "index.ts"))) {
963
1123
  return current;
964
1124
  }
965
- const parent = path3.dirname(current);
1125
+ const parent = path4.dirname(current);
966
1126
  if (parent === current) {
967
1127
  return void 0;
968
1128
  }
@@ -970,13 +1130,13 @@ function findSidecarRepoRoot(startDir) {
970
1130
  }
971
1131
  }
972
1132
  async function prepareAppStyle(rootDir, cacheDir) {
973
- const sourceFile = path3.join(rootDir, "style.css");
974
- if (!existsSync2(sourceFile)) {
1133
+ const sourceFile = path4.join(rootDir, "style.css");
1134
+ if (!existsSync3(sourceFile)) {
975
1135
  return void 0;
976
1136
  }
977
1137
  const source = await readFile(sourceFile, "utf8");
978
1138
  const css = await processAppStyle(source, sourceFile);
979
- const outputFile = path3.join(cacheDir, "style.css");
1139
+ const outputFile = path4.join(cacheDir, "style.css");
980
1140
  await writeFile(outputFile, css);
981
1141
  return outputFile;
982
1142
  }
@@ -988,7 +1148,7 @@ async function processAppStyle(source, from) {
988
1148
  const plugins = [];
989
1149
  if (cssSource.includes("@tailwind")) {
990
1150
  const tailwind = await import("@tailwindcss/postcss");
991
- plugins.push(tailwind.default({ base: path3.dirname(from) }));
1151
+ plugins.push(tailwind.default({ base: path4.dirname(from) }));
992
1152
  }
993
1153
  const autoprefixer = await import("autoprefixer");
994
1154
  plugins.push(autoprefixer.default());
@@ -1002,13 +1162,13 @@ function needsPostcss(source) {
1002
1162
  return /@import\s+["']tailwindcss["']|@tailwind|@source|@theme|@plugin/.test(source);
1003
1163
  }
1004
1164
  function findWidget(rootDir, toolFile, id, target = "mcp", toolVariant = "shared") {
1005
- const selected = selectWidgetFile(path3.dirname(toolFile), target, toolVariant);
1165
+ const selected = selectWidgetFile(path4.dirname(toolFile), target, toolVariant);
1006
1166
  if (!selected) {
1007
1167
  return void 0;
1008
1168
  }
1009
1169
  const safeId = safePathSegment(id);
1010
1170
  return {
1011
- sourceFile: path3.relative(rootDir, selected.filePath),
1171
+ sourceFile: path4.relative(rootDir, selected.filePath),
1012
1172
  variant: selected.variant,
1013
1173
  resourceUri: `ui://${safeId}/widget.html`
1014
1174
  };
@@ -1190,17 +1350,17 @@ function readStringArrayProperty(definition, propertyName) {
1190
1350
  }
1191
1351
  function selectWidgetFile(directory, target, toolVariant) {
1192
1352
  if (toolVariant === "openai") {
1193
- const filePath = path3.join(directory, "widget.openai.tsx");
1194
- return existsSync2(filePath) ? { filePath, variant: "openai" } : void 0;
1353
+ const filePath = path4.join(directory, "widget.openai.tsx");
1354
+ return existsSync3(filePath) ? { filePath, variant: "openai" } : void 0;
1195
1355
  }
1196
1356
  if (toolVariant === "anthropic") {
1197
- const filePath = path3.join(directory, "widget.anthropic.tsx");
1198
- return existsSync2(filePath) ? { filePath, variant: "anthropic" } : void 0;
1357
+ const filePath = path4.join(directory, "widget.anthropic.tsx");
1358
+ return existsSync3(filePath) ? { filePath, variant: "anthropic" } : void 0;
1199
1359
  }
1200
1360
  const candidates = target === "chatgpt" || target === "claude" || target === "mcp" ? [{ name: "widget.tsx", variant: "shared" }] : [];
1201
1361
  for (const candidate of candidates) {
1202
- const filePath = path3.join(directory, candidate.name);
1203
- if (existsSync2(filePath)) {
1362
+ const filePath = path4.join(directory, candidate.name);
1363
+ if (existsSync3(filePath)) {
1204
1364
  return { filePath, variant: candidate.variant };
1205
1365
  }
1206
1366
  }
@@ -1251,17 +1411,23 @@ function stripUndefined3(value) {
1251
1411
  // packages/compiler/src/analyze.ts
1252
1412
  async function analyzeProjectTools(rootDir, options = {}) {
1253
1413
  const target = options.target ?? "mcp";
1254
- const toolFiles = await findToolFiles(path4.join(rootDir, "server"), target);
1414
+ const toolFiles = await findToolFiles(path5.join(rootDir, "server"), target);
1255
1415
  if (toolFiles.length === 0) {
1256
1416
  return [];
1257
1417
  }
1258
1418
  const project = createProject(rootDir);
1259
1419
  const authScopes = readAuthScopeCatalog(project, rootDir);
1260
- return toolFiles.map(
1261
- (candidate) => analyzeToolFile(project.addSourceFileAtPath(candidate.filePath), rootDir, {
1420
+ const sources = toolFiles.map((candidate) => ({
1421
+ candidate,
1422
+ sourceFile: project.addSourceFileAtPath(candidate.filePath)
1423
+ }));
1424
+ const runtimeInputSchemas = await readRuntimeInputSchemas(rootDir, sources);
1425
+ return sources.map(
1426
+ ({ candidate, sourceFile }) => analyzeToolFile(sourceFile, rootDir, {
1262
1427
  target,
1263
1428
  variant: candidate.variant,
1264
- authScopes
1429
+ authScopes,
1430
+ inputSchema: runtimeInputSchemas.get(candidate.filePath)
1265
1431
  })
1266
1432
  );
1267
1433
  }
@@ -1270,7 +1436,7 @@ function analyzeToolFile(sourceFile, rootDir, options = {}) {
1270
1436
  const variant = options.variant ?? "shared";
1271
1437
  const definition = findToolDefinition(sourceFile);
1272
1438
  const absoluteFile = sourceFile.getFilePath();
1273
- const directory = path4.basename(path4.dirname(absoluteFile));
1439
+ const directory = path5.basename(path5.dirname(absoluteFile));
1274
1440
  const name = getRequiredStringProperty(definition, "name", sourceFile);
1275
1441
  const id = getOptionalStringProperty(definition, "id") ?? toMachineName(directory);
1276
1442
  const description = getRequiredStringProperty(
@@ -1283,7 +1449,7 @@ function analyzeToolFile(sourceFile, rootDir, options = {}) {
1283
1449
  const hosts = readHosts(definition);
1284
1450
  const auth = readAuthPolicy(definition, options.authScopes ?? {});
1285
1451
  const execute = getExecuteFunction(definition, sourceFile);
1286
- const inputSchema = getParamsSchema(definition, execute);
1452
+ const inputSchema = options.inputSchema ?? getParamsSchema(definition, execute);
1287
1453
  const outputSchema = getOutputSchema(definition, execute);
1288
1454
  const descriptor = createToolDescriptor({
1289
1455
  name,
@@ -1301,7 +1467,7 @@ function analyzeToolFile(sourceFile, rootDir, options = {}) {
1301
1467
  validateWidgetHierarchy(sourceFile, absoluteFile, target, variant);
1302
1468
  const widget = findWidget(rootDir, absoluteFile, id, target, variant);
1303
1469
  if (widget) {
1304
- const widgetFile = path4.join(rootDir, widget.sourceFile);
1470
+ const widgetFile = path5.join(rootDir, widget.sourceFile);
1305
1471
  const project = sourceFile.getProject();
1306
1472
  const widgetSourceFile = project.getSourceFile(widgetFile) ?? project.addSourceFileAtPath(widgetFile);
1307
1473
  widget.options = {
@@ -1312,7 +1478,7 @@ function analyzeToolFile(sourceFile, rootDir, options = {}) {
1312
1478
  descriptor._meta = mergeWidgetMeta(descriptor._meta, widgetMeta(widget.resourceUri, widget.options, target));
1313
1479
  }
1314
1480
  return {
1315
- sourceFile: path4.relative(rootDir, absoluteFile),
1481
+ sourceFile: path5.relative(rootDir, absoluteFile),
1316
1482
  variant,
1317
1483
  target,
1318
1484
  directory,
@@ -1327,6 +1493,26 @@ function analyzeToolFile(sourceFile, rootDir, options = {}) {
1327
1493
  descriptor
1328
1494
  };
1329
1495
  }
1496
+ async function readRuntimeInputSchemas(rootDir, sources) {
1497
+ const schemas = /* @__PURE__ */ new Map();
1498
+ await Promise.all(sources.map(async ({ candidate, sourceFile }) => {
1499
+ const definition = findToolDefinition(sourceFile);
1500
+ if (!definitionHasRuntimeParams(definition)) {
1501
+ return;
1502
+ }
1503
+ const schema = await readRuntimeToolInputSchema(rootDir, candidate.filePath);
1504
+ if (schema) {
1505
+ schemas.set(candidate.filePath, schema);
1506
+ }
1507
+ }));
1508
+ return schemas;
1509
+ }
1510
+ function definitionHasRuntimeParams(definition) {
1511
+ if (definition.getProperty("params")) {
1512
+ return true;
1513
+ }
1514
+ return Boolean(getWithParamsCall(definition));
1515
+ }
1330
1516
  function readAuthPolicy(definition, authScopes) {
1331
1517
  const initializer = readObjectProperty2(definition, "auth");
1332
1518
  if (!initializer) {
@@ -1343,7 +1529,7 @@ function readAuthPolicy(definition, authScopes) {
1343
1529
  return { authenticated: true };
1344
1530
  }
1345
1531
  function readAuthScopeCatalog(project, rootDir) {
1346
- const authPath = path4.join(rootDir, "auth.ts");
1532
+ const authPath = path5.join(rootDir, "auth.ts");
1347
1533
  if (!existsSyncSafe(authPath)) {
1348
1534
  return {};
1349
1535
  }
@@ -1425,12 +1611,12 @@ function isNamedCall(call, name) {
1425
1611
  return callee === name || callee.endsWith(`.${name}`);
1426
1612
  }
1427
1613
  function validateWidgetHierarchy(sourceFile, toolFile, target, variant) {
1428
- const directory = path4.dirname(toolFile);
1614
+ const directory = path5.dirname(toolFile);
1429
1615
  const platformWidget = target === "chatgpt" ? "widget.openai.tsx" : target === "claude" ? "widget.anthropic.tsx" : void 0;
1430
1616
  if (!platformWidget || variant !== "shared") {
1431
1617
  return;
1432
1618
  }
1433
- if (existsSyncSafe(path4.join(directory, platformWidget))) {
1619
+ if (existsSyncSafe(path5.join(directory, platformWidget))) {
1434
1620
  const expectedTool = target === "chatgpt" ? "tool.openai.ts" : "tool.anthropic.ts";
1435
1621
  throw new CompilerError(
1436
1622
  sourceFile,
@@ -1445,7 +1631,7 @@ async function findToolFiles(serverDir, target) {
1445
1631
  const entries = await readdir(serverDir, { withFileTypes: true });
1446
1632
  const files = [];
1447
1633
  for (const entry of entries) {
1448
- const entryPath = path4.join(serverDir, entry.name);
1634
+ const entryPath = path5.join(serverDir, entry.name);
1449
1635
  if (entry.isDirectory()) {
1450
1636
  const candidate = selectToolFile(entryPath, target);
1451
1637
  if (candidate) {
@@ -1464,7 +1650,7 @@ function selectToolFile(directory, target) {
1464
1650
  { name: "tool.ts", variant: "shared" }
1465
1651
  ] : [{ name: "tool.ts", variant: "shared" }];
1466
1652
  for (const candidate of candidates) {
1467
- const filePath = path4.join(directory, candidate.name);
1653
+ const filePath = path5.join(directory, candidate.name);
1468
1654
  if (existsSyncSafe(filePath)) {
1469
1655
  return { filePath, variant: candidate.variant };
1470
1656
  }
@@ -1500,16 +1686,32 @@ function getExecuteFunction(definition, sourceFile) {
1500
1686
  return property;
1501
1687
  }
1502
1688
  if (Node4.isPropertyAssignment(property)) {
1503
- const initializer = property.getInitializer();
1689
+ const initializer = unwrapExpression(property.getInitializer());
1504
1690
  if (initializer && (Node4.isArrowFunction(initializer) || Node4.isFunctionExpression(initializer))) {
1505
1691
  return initializer;
1506
1692
  }
1693
+ const withParamsCall = getWithParamsCall(definition);
1694
+ const wrappedExecute = unwrapExpression(withParamsCall?.getArguments()[1]);
1695
+ if (wrappedExecute && (Node4.isArrowFunction(wrappedExecute) || Node4.isFunctionExpression(wrappedExecute))) {
1696
+ return wrappedExecute;
1697
+ }
1507
1698
  }
1508
1699
  throw new CompilerError(
1509
1700
  sourceFile,
1510
1701
  "execute must be a method, function expression, or arrow function."
1511
1702
  );
1512
1703
  }
1704
+ function getWithParamsCall(definition) {
1705
+ const property = definition.getProperty("execute");
1706
+ if (!property || !Node4.isPropertyAssignment(property)) {
1707
+ return void 0;
1708
+ }
1709
+ const initializer = unwrapExpression(property.getInitializer());
1710
+ if (!initializer || !Node4.isCallExpression(initializer)) {
1711
+ return void 0;
1712
+ }
1713
+ return isNamedCall(initializer, "withParams") ? initializer : void 0;
1714
+ }
1513
1715
  function getRequiredStringProperty(definition, propertyName, sourceFile) {
1514
1716
  const value = getOptionalStringProperty(definition, propertyName);
1515
1717
  if (value === void 0 || !value.trim()) {
@@ -1665,16 +1867,16 @@ function readStringArrayProperty2(definition, propertyName) {
1665
1867
 
1666
1868
  // packages/compiler/src/build.ts
1667
1869
  import { mkdir as mkdir9, writeFile as writeFile9 } from "fs/promises";
1668
- import path18 from "path";
1870
+ import path19 from "path";
1669
1871
 
1670
1872
  // packages/compiler/src/config.ts
1671
- import path5 from "path";
1873
+ import path6 from "path";
1672
1874
  import {
1673
1875
  Node as Node5,
1674
1876
  SyntaxKind as SyntaxKind3
1675
1877
  } from "ts-morph";
1676
1878
  function analyzeProjectConfig(rootDir) {
1677
- const configPath = path5.join(rootDir, "sidecar.config.ts");
1879
+ const configPath = path6.join(rootDir, "sidecar.config.ts");
1678
1880
  if (!existsSyncSafe(configPath)) {
1679
1881
  return defaultCompilerConfig();
1680
1882
  }
@@ -1690,7 +1892,8 @@ function analyzeProjectConfig(rootDir) {
1690
1892
  target: readTargetNested(definition, "build", "target"),
1691
1893
  host: readHostNested(definition, "build", "host"),
1692
1894
  outDir: readStringNested(definition, "build", "outDir"),
1693
- plugins: readBooleanNested(definition, "build", "plugins")
1895
+ plugins: readBooleanNested(definition, "build", "plugins"),
1896
+ widgets: readWidgetBuildConfig(definition)
1694
1897
  },
1695
1898
  resources: {
1696
1899
  subscribe: readBooleanNested(definition, "resources", "subscribe") ?? false,
@@ -1708,6 +1911,44 @@ function analyzeProjectConfig(rootDir) {
1708
1911
  }
1709
1912
  };
1710
1913
  }
1914
+ function readWidgetBuildConfig(definition) {
1915
+ const widgets = readObjectProperty3(readObjectProperty3(definition, "build"), "widgets");
1916
+ if (!widgets) {
1917
+ return void 0;
1918
+ }
1919
+ const config = {};
1920
+ const configure = readStringProperty3(widgets, "configure");
1921
+ const esbuild3 = readWidgetEsbuildConfig(widgets);
1922
+ if (configure) config.configure = configure;
1923
+ if (esbuild3) config.esbuild = esbuild3;
1924
+ return Object.keys(config).length ? config : void 0;
1925
+ }
1926
+ function readWidgetEsbuildConfig(widgets) {
1927
+ const esbuild3 = readObjectProperty3(widgets, "esbuild");
1928
+ if (!esbuild3) {
1929
+ return void 0;
1930
+ }
1931
+ const config = {};
1932
+ const alias = readStringRecordProperty(esbuild3, "alias");
1933
+ const define = readStringRecordProperty(esbuild3, "define");
1934
+ const external = readStringArrayProperty3(esbuild3, "external");
1935
+ const loader = readStringRecordProperty(esbuild3, "loader");
1936
+ const conditions = readStringArrayProperty3(esbuild3, "conditions");
1937
+ const mainFields = readStringArrayProperty3(esbuild3, "mainFields");
1938
+ const jsx = readStringProperty3(esbuild3, "jsx");
1939
+ const jsxImportSource = readStringProperty3(esbuild3, "jsxImportSource");
1940
+ if (alias) config.alias = alias;
1941
+ if (define) config.define = define;
1942
+ if (external) config.external = external;
1943
+ if (loader) config.loader = loader;
1944
+ if (conditions) config.conditions = conditions;
1945
+ if (mainFields) config.mainFields = mainFields;
1946
+ if (jsx === "automatic" || jsx === "transform" || jsx === "preserve") {
1947
+ config.jsx = jsx;
1948
+ }
1949
+ if (jsxImportSource) config.jsxImportSource = jsxImportSource;
1950
+ return Object.keys(config).length ? config : void 0;
1951
+ }
1711
1952
  function defaultCompilerConfig() {
1712
1953
  return {
1713
1954
  build: {},
@@ -1740,12 +1981,7 @@ function readStringNested(definition, section, propertyName) {
1740
1981
  if (!object) {
1741
1982
  return void 0;
1742
1983
  }
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;
1984
+ return readStringProperty3(object, propertyName);
1749
1985
  }
1750
1986
  function readBooleanNested(definition, section, propertyName) {
1751
1987
  const object = readObjectProperty3(definition, section);
@@ -1777,6 +2013,9 @@ function readNumberNested(definition, section, propertyName) {
1777
2013
  return initializer && Node5.isNumericLiteral(initializer) ? Number(initializer.getLiteralText()) : void 0;
1778
2014
  }
1779
2015
  function readObjectProperty3(definition, propertyName) {
2016
+ if (!definition) {
2017
+ return void 0;
2018
+ }
1780
2019
  const property = definition.getProperty(propertyName);
1781
2020
  if (!property || !Node5.isPropertyAssignment(property)) {
1782
2021
  return void 0;
@@ -1784,38 +2023,79 @@ function readObjectProperty3(definition, propertyName) {
1784
2023
  const initializer = unwrapExpression(property.getInitializer());
1785
2024
  return initializer && Node5.isObjectLiteralExpression(initializer) ? initializer : void 0;
1786
2025
  }
2026
+ function readStringProperty3(definition, propertyName) {
2027
+ const property = definition.getProperty(propertyName);
2028
+ if (!property || !Node5.isPropertyAssignment(property)) {
2029
+ return void 0;
2030
+ }
2031
+ const initializer = unwrapExpression(property.getInitializer());
2032
+ return initializer && Node5.isStringLiteral(initializer) ? initializer.getLiteralText() : void 0;
2033
+ }
2034
+ function readStringArrayProperty3(definition, propertyName) {
2035
+ const property = definition.getProperty(propertyName);
2036
+ if (!property || !Node5.isPropertyAssignment(property)) {
2037
+ return void 0;
2038
+ }
2039
+ const initializer = unwrapExpression(property.getInitializer());
2040
+ if (!initializer || !Node5.isArrayLiteralExpression(initializer)) {
2041
+ return void 0;
2042
+ }
2043
+ const values = initializer.getElements().map((element) => {
2044
+ const unwrapped = unwrapExpression(element);
2045
+ return unwrapped && Node5.isStringLiteral(unwrapped) ? unwrapped.getLiteralText() : void 0;
2046
+ });
2047
+ return values.every((value) => value !== void 0) ? values : void 0;
2048
+ }
2049
+ function readStringRecordProperty(definition, propertyName) {
2050
+ const object = readObjectProperty3(definition, propertyName);
2051
+ if (!object) {
2052
+ return void 0;
2053
+ }
2054
+ const record = {};
2055
+ for (const property of object.getProperties()) {
2056
+ if (!Node5.isPropertyAssignment(property)) {
2057
+ return void 0;
2058
+ }
2059
+ const initializer = unwrapExpression(property.getInitializer());
2060
+ if (!initializer || !Node5.isStringLiteral(initializer)) {
2061
+ return void 0;
2062
+ }
2063
+ record[property.getName().replace(/^["']|["']$/g, "")] = initializer.getLiteralText();
2064
+ }
2065
+ return record;
2066
+ }
1787
2067
  function hasProperty(definition, propertyName) {
1788
2068
  return Boolean(definition?.getProperty(propertyName));
1789
2069
  }
1790
2070
 
1791
2071
  // packages/compiler/src/diagnostics.ts
1792
- import { existsSync as existsSync3 } from "fs";
2072
+ import { existsSync as existsSync4 } from "fs";
1793
2073
  import { readFile as readFile2 } from "fs/promises";
1794
- import path6 from "path";
2074
+ import path7 from "path";
1795
2075
  async function collectProjectDiagnostics(rootDir, input) {
1796
2076
  const diagnostics = [];
1797
2077
  const tools = Array.isArray(input) ? input : input.tools;
1798
2078
  const resources = Array.isArray(input) ? [] : input.resources ?? [];
1799
2079
  const prompts = Array.isArray(input) ? [] : input.prompts ?? [];
1800
2080
  const config = Array.isArray(input) ? void 0 : input.config;
1801
- const hasAuthConfig = existsSync3(path6.join(rootDir, "auth.ts"));
2081
+ const hasAuthConfig = existsSync4(path7.join(rootDir, "auth.ts"));
1802
2082
  for (const entry of tools) {
1803
- const toolPath = path6.join(rootDir, entry.sourceFile);
2083
+ const toolPath = path7.join(rootDir, entry.sourceFile);
1804
2084
  const toolSource = await readFile2(toolPath, "utf8");
1805
- diagnostics.push(...diagnoseToolSource(rootDir, entry, toolSource, hasAuthConfig));
2085
+ diagnostics.push(...diagnoseToolSource(entry, toolSource, hasAuthConfig));
1806
2086
  if (entry.widget) {
1807
- const widgetPath = path6.join(rootDir, entry.widget.sourceFile);
2087
+ const widgetPath = path7.join(rootDir, entry.widget.sourceFile);
1808
2088
  const widgetSource = await readFile2(widgetPath, "utf8");
1809
2089
  diagnostics.push(...diagnoseWidgetSource(rootDir, entry, widgetSource));
1810
2090
  }
1811
2091
  }
1812
2092
  for (const entry of resources) {
1813
- const resourcePath = path6.join(rootDir, entry.sourceFile);
2093
+ const resourcePath = path7.join(rootDir, entry.sourceFile);
1814
2094
  const resourceSource = await readFile2(resourcePath, "utf8");
1815
2095
  diagnostics.push(...diagnoseResourceSource(entry, resourceSource));
1816
2096
  }
1817
2097
  for (const entry of prompts) {
1818
- const promptPath = path6.join(rootDir, entry.sourceFile);
2098
+ const promptPath = path7.join(rootDir, entry.sourceFile);
1819
2099
  const promptSource = await readFile2(promptPath, "utf8");
1820
2100
  diagnostics.push(...diagnosePromptSource(entry, promptSource));
1821
2101
  }
@@ -1830,7 +2110,7 @@ function formatDiagnostic(diagnostic) {
1830
2110
  hint: ${diagnostic.hint}` : "";
1831
2111
  return `${location} - ${diagnostic.severity} ${diagnostic.code}: ${diagnostic.message}${hint}`;
1832
2112
  }
1833
- function diagnoseToolSource(rootDir, entry, source, hasAuthConfig) {
2113
+ function diagnoseToolSource(entry, source, hasAuthConfig) {
1834
2114
  const diagnostics = [];
1835
2115
  const toolLocation = locate(source, "tool({");
1836
2116
  if (!entry.description.trim().startsWith("Use this when")) {
@@ -2047,21 +2327,21 @@ function isIgnored(source, code) {
2047
2327
 
2048
2328
  // packages/compiler/src/generated.ts
2049
2329
  import { mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
2050
- import path7 from "path";
2330
+ import path8 from "path";
2051
2331
  async function writeGeneratedTypes(rootDir, tools) {
2052
- const generatedDir = path7.join(rootDir, ".sidecar", "generated");
2332
+ const generatedDir = path8.join(rootDir, ".sidecar", "generated");
2053
2333
  await mkdir2(generatedDir, { recursive: true });
2054
2334
  const appCallableTools = tools.filter(isAppCallable);
2055
2335
  const methodNames = uniqueMethodNames(appCallableTools.map((entry) => toIdentifier(entry.id)));
2056
2336
  const imports = appCallableTools.map(
2057
- (entry, index) => `import type tool${index} from ${JSON.stringify(toImportSpecifier(generatedDir, path7.join(rootDir, entry.sourceFile), { extension: "js" }))};`
2337
+ (entry, index) => `import type tool${index} from ${JSON.stringify(toImportSpecifier(generatedDir, path8.join(rootDir, entry.sourceFile), { extension: "js" }))};`
2058
2338
  ).join("\n");
2059
2339
  const ids = appCallableTools.map((entry, index) => ` ${methodNames[index]}: ${JSON.stringify(entry.id)}`).join(",\n");
2060
2340
  const toolTypes = appCallableTools.map(
2061
- (entry, index) => ` ${methodNames[index]}(params: ToolParams<typeof tool${index}>): Promise<ToolOutput<typeof tool${index}>>;`
2341
+ (_entry, index) => ` ${methodNames[index]}(params: ToolParams<typeof tool${index}>): Promise<ToolOutput<typeof tool${index}>>;`
2062
2342
  ).join("\n");
2063
2343
  await writeFile2(
2064
- path7.join(generatedDir, "tools.ts"),
2344
+ path8.join(generatedDir, "tools.ts"),
2065
2345
  `/**
2066
2346
  * Generated Sidecar widget tool client.
2067
2347
  *
@@ -2111,13 +2391,13 @@ function uniqueMethodNames(names) {
2111
2391
 
2112
2392
  // packages/compiler/src/identity.ts
2113
2393
  import { readFile as readFile3 } from "fs/promises";
2114
- import path8 from "path";
2394
+ import path9 from "path";
2115
2395
  async function loadProjectIdentity(rootDir) {
2116
- const packageJson = await readOptionalJson(path8.join(rootDir, "package.json"));
2396
+ const packageJson = await readOptionalJson(path9.join(rootDir, "package.json"));
2117
2397
  const configText = await readOptionalText(
2118
- path8.join(rootDir, "sidecar.config.ts")
2398
+ path9.join(rootDir, "sidecar.config.ts")
2119
2399
  );
2120
- const name = readConfigString(configText, "name") ?? packageJson?.name ?? path8.basename(rootDir);
2400
+ const name = readConfigString(configText, "name") ?? packageJson?.name ?? path9.basename(rootDir);
2121
2401
  const version = readConfigString(configText, "version") ?? packageJson?.version ?? "0.0.0-dev";
2122
2402
  const description = readConfigString(configText, "description") ?? packageJson?.description ?? `${name} Sidecar app.`;
2123
2403
  return {
@@ -2151,32 +2431,32 @@ function readConfigString(configText, key) {
2151
2431
 
2152
2432
  // packages/compiler/src/plugins.ts
2153
2433
  import { mkdir as mkdir7, writeFile as writeFile7 } from "fs/promises";
2154
- import path14 from "path";
2434
+ import path15 from "path";
2155
2435
 
2156
2436
  // packages/compiler/src/plugin-components/agents.ts
2157
2437
  import { mkdir as mkdir3, readdir as readdir2, readFile as readFile4, writeFile as writeFile3 } from "fs/promises";
2158
- import path9 from "path";
2438
+ import path10 from "path";
2159
2439
  async function emitClaudeAgents(rootDir, destination) {
2160
- const source = path9.join(rootDir, "agents");
2440
+ const source = path10.join(rootDir, "agents");
2161
2441
  if (!existsSyncSafe(source)) {
2162
2442
  return;
2163
2443
  }
2164
2444
  const entries = await readdir2(source, { withFileTypes: true });
2165
2445
  const agentDirs = entries.filter(
2166
- (entry) => entry.isDirectory() && existsSyncSafe(path9.join(source, entry.name, "agent.ts"))
2446
+ (entry) => entry.isDirectory() && existsSyncSafe(path10.join(source, entry.name, "agent.ts"))
2167
2447
  );
2168
2448
  if (!agentDirs.length) {
2169
2449
  return;
2170
2450
  }
2171
2451
  await mkdir3(destination, { recursive: true });
2172
2452
  for (const entry of agentDirs) {
2173
- const sourceText = await readFile4(path9.join(source, entry.name, "agent.ts"), "utf8");
2453
+ const sourceText = await readFile4(path10.join(source, entry.name, "agent.ts"), "utf8");
2174
2454
  const markdown = parseClaudeAgent(
2175
2455
  sourceText,
2176
2456
  entry.name
2177
2457
  );
2178
2458
  const agentName = readObjectString(sourceText, "name") ?? entry.name;
2179
- await writeFile3(path9.join(destination, `${safeFileStem(agentName)}.md`), markdown);
2459
+ await writeFile3(path10.join(destination, `${safeFileStem(agentName)}.md`), markdown);
2180
2460
  }
2181
2461
  }
2182
2462
  function parseClaudeAgent(source, fallbackName) {
@@ -2205,41 +2485,41 @@ ${prompt.trim()}
2205
2485
 
2206
2486
  // packages/compiler/src/plugin-components/commands.ts
2207
2487
  import { cp, lstat, mkdir as mkdir4, readdir as readdir3, readFile as readFile5, writeFile as writeFile4 } from "fs/promises";
2208
- import path10 from "path";
2488
+ import path11 from "path";
2209
2489
  async function copyCommands(rootDir, destination) {
2210
- const source = path10.join(rootDir, "commands");
2490
+ const source = path11.join(rootDir, "commands");
2211
2491
  if (!existsSyncSafe(source)) {
2212
2492
  return;
2213
2493
  }
2214
2494
  await mkdir4(destination, { recursive: true });
2215
2495
  const entries = await readdir3(source, { withFileTypes: true });
2216
2496
  for (const entry of entries) {
2217
- const sourcePath = path10.join(source, entry.name);
2497
+ const sourcePath = path11.join(source, entry.name);
2218
2498
  if (entry.isFile() && entry.name.endsWith(".md")) {
2219
2499
  if (await safeCommandCopyFilter(sourcePath)) {
2220
- await cp(sourcePath, path10.join(destination, safeFileStem(entry.name.replace(/\.md$/, "")) + ".md"));
2500
+ await cp(sourcePath, path11.join(destination, safeFileStem(entry.name.replace(/\.md$/, "")) + ".md"));
2221
2501
  }
2222
2502
  continue;
2223
2503
  }
2224
2504
  if (!entry.isDirectory()) {
2225
2505
  continue;
2226
2506
  }
2227
- const dynamicCommand = path10.join(sourcePath, "command.ts");
2507
+ const dynamicCommand = path11.join(sourcePath, "command.ts");
2228
2508
  if (existsSyncSafe(dynamicCommand)) {
2229
2509
  const sourceText = await readFile5(dynamicCommand, "utf8");
2230
2510
  const markdown = parseDynamicCommand(sourceText, entry.name);
2231
2511
  const commandName = readObjectString(sourceText, "name") ?? entry.name;
2232
- await writeFile4(path10.join(destination, `${safeFileStem(commandName)}.md`), markdown);
2512
+ await writeFile4(path11.join(destination, `${safeFileStem(commandName)}.md`), markdown);
2233
2513
  continue;
2234
2514
  }
2235
- await cp(sourcePath, path10.join(destination, entry.name), {
2515
+ await cp(sourcePath, path11.join(destination, entry.name), {
2236
2516
  recursive: true,
2237
2517
  filter: safeCommandCopyFilter
2238
2518
  });
2239
2519
  }
2240
2520
  }
2241
2521
  async function safeCommandCopyFilter(sourcePath) {
2242
- const basename = path10.basename(sourcePath);
2522
+ const basename = path11.basename(sourcePath);
2243
2523
  if (basename === ".env" || basename.startsWith(".env.") || basename === "node_modules" || basename === ".git") {
2244
2524
  return false;
2245
2525
  }
@@ -2268,32 +2548,32 @@ ${Object.entries(frontmatter).map(([key, value]) => `${key}: ${yamlScalar(value)
2268
2548
 
2269
2549
  // packages/compiler/src/plugin-components/hooks.ts
2270
2550
  import { mkdir as mkdir5, readdir as readdir4, readFile as readFile6, writeFile as writeFile5 } from "fs/promises";
2271
- import path11 from "path";
2551
+ import path12 from "path";
2272
2552
  import {
2273
2553
  Node as Node6,
2274
2554
  Project as Project2,
2275
2555
  SyntaxKind as SyntaxKind4
2276
2556
  } from "ts-morph";
2277
2557
  async function copyHooks(rootDir, destination) {
2278
- const source = path11.join(rootDir, "hooks");
2558
+ const source = path12.join(rootDir, "hooks");
2279
2559
  if (!existsSyncSafe(source)) {
2280
2560
  return;
2281
2561
  }
2282
2562
  const entries = await readdir4(source, { withFileTypes: true });
2283
2563
  const hookDirs = entries.filter(
2284
- (entry) => entry.isDirectory() && existsSyncSafe(path11.join(source, entry.name, "hook.ts"))
2564
+ (entry) => entry.isDirectory() && existsSyncSafe(path12.join(source, entry.name, "hook.ts"))
2285
2565
  );
2286
2566
  if (!hookDirs.length) {
2287
2567
  return;
2288
2568
  }
2289
2569
  const config = {};
2290
2570
  for (const entry of hookDirs) {
2291
- const filePath = path11.join(source, entry.name, "hook.ts");
2571
+ const filePath = path12.join(source, entry.name, "hook.ts");
2292
2572
  mergeHooks(config, parseHookFile(await readFile6(filePath, "utf8"), entry.name));
2293
2573
  }
2294
2574
  await mkdir5(destination, { recursive: true });
2295
2575
  await writeFile5(
2296
- path11.join(destination, "hooks.json"),
2576
+ path12.join(destination, "hooks.json"),
2297
2577
  `${JSON.stringify(config, null, 2)}
2298
2578
  `
2299
2579
  );
@@ -2320,7 +2600,7 @@ function parseHookFile(source, fallbackName) {
2320
2600
  throw new Error(`hooks/${fallbackName}/hook.ts must default-export hook({ ... }) or hooks({ ... }).`);
2321
2601
  }
2322
2602
  function parseHookDefinition(definition, fallbackName) {
2323
- const event = readStringProperty3(definition, "event");
2603
+ const event = readStringProperty4(definition, "event");
2324
2604
  if (!event) {
2325
2605
  throw new Error(`hooks/${fallbackName}/hook.ts must declare an event string.`);
2326
2606
  }
@@ -2330,7 +2610,7 @@ function parseHookDefinition(definition, fallbackName) {
2330
2610
  }
2331
2611
  return {
2332
2612
  event,
2333
- matcher: readStringProperty3(definition, "matcher"),
2613
+ matcher: readStringProperty4(definition, "matcher"),
2334
2614
  run: hooks
2335
2615
  };
2336
2616
  }
@@ -2350,7 +2630,7 @@ function parseHooksDefinition(definition, fallbackName) {
2350
2630
  throw new Error(`hooks/${fallbackName}/hook.ts event "${event}" entries must be objects.`);
2351
2631
  }
2352
2632
  return stripUndefined2({
2353
- matcher: readStringProperty3(entry, "matcher"),
2633
+ matcher: readStringProperty4(entry, "matcher"),
2354
2634
  hooks: readHookArray(entry, "run", fallbackName)
2355
2635
  });
2356
2636
  });
@@ -2373,7 +2653,7 @@ function parseHookHandlers(handlers, fallbackName) {
2373
2653
  }
2374
2654
  function parseHookHandler(handler, fallbackName) {
2375
2655
  if (Node6.isObjectLiteralExpression(handler)) {
2376
- const type = readStringProperty3(handler, "type");
2656
+ const type = readStringProperty4(handler, "type");
2377
2657
  if (type !== "command" && type !== "http") {
2378
2658
  throw new Error(`hooks/${fallbackName}/hook.ts hook handlers need type "command" or "http".`);
2379
2659
  }
@@ -2423,7 +2703,7 @@ function objectLiteralToRecord(object) {
2423
2703
  }
2424
2704
  return stripUndefined2(record);
2425
2705
  }
2426
- function readStringProperty3(object, propertyName) {
2706
+ function readStringProperty4(object, propertyName) {
2427
2707
  const property = object.getProperty(propertyName);
2428
2708
  if (!property || !Node6.isPropertyAssignment(property)) {
2429
2709
  return void 0;
@@ -2467,7 +2747,7 @@ function mergeHooks(target, source) {
2467
2747
 
2468
2748
  // packages/compiler/src/plugin-components/passthrough.ts
2469
2749
  import { cp as cp2, lstat as lstat2 } from "fs/promises";
2470
- import path12 from "path";
2750
+ import path13 from "path";
2471
2751
  async function copyClaudePassthroughDirectories(rootDir, pluginDir) {
2472
2752
  for (const directory of [
2473
2753
  "assets",
@@ -2476,18 +2756,18 @@ async function copyClaudePassthroughDirectories(rootDir, pluginDir) {
2476
2756
  "output-styles",
2477
2757
  "themes"
2478
2758
  ]) {
2479
- const source = path12.join(rootDir, directory);
2759
+ const source = path13.join(rootDir, directory);
2480
2760
  if (!existsSyncSafe(source)) {
2481
2761
  continue;
2482
2762
  }
2483
- await cp2(source, path12.join(pluginDir, directory), {
2763
+ await cp2(source, path13.join(pluginDir, directory), {
2484
2764
  recursive: true,
2485
2765
  filter: safePluginCopyFilter
2486
2766
  });
2487
2767
  }
2488
2768
  }
2489
2769
  async function safePluginCopyFilter(sourcePath) {
2490
- const basename = path12.basename(sourcePath);
2770
+ const basename = path13.basename(sourcePath);
2491
2771
  if (basename === "node_modules" || basename === ".git" || basename === ".env" || basename.startsWith(".env.")) {
2492
2772
  return false;
2493
2773
  }
@@ -2496,11 +2776,11 @@ async function safePluginCopyFilter(sourcePath) {
2496
2776
  }
2497
2777
 
2498
2778
  // packages/compiler/src/plugin-components/skills.ts
2499
- import { existsSync as existsSync4 } from "fs";
2779
+ import { existsSync as existsSync5 } from "fs";
2500
2780
  import { cp as cp3, lstat as lstat3, mkdir as mkdir6, readdir as readdir5, readFile as readFile7, writeFile as writeFile6 } from "fs/promises";
2501
- import path13 from "path";
2781
+ import path14 from "path";
2502
2782
  async function copySkills(rootDir, destination) {
2503
- const source = path13.join(rootDir, "skills");
2783
+ const source = path14.join(rootDir, "skills");
2504
2784
  if (!existsSyncSafe(source)) {
2505
2785
  return;
2506
2786
  }
@@ -2510,27 +2790,27 @@ async function copySkills(rootDir, destination) {
2510
2790
  if (!entry.isDirectory()) {
2511
2791
  continue;
2512
2792
  }
2513
- const sourceDir = path13.join(source, entry.name);
2514
- const destinationDir = path13.join(destination, entry.name);
2515
- const staticSkill = path13.join(sourceDir, "SKILL.md");
2516
- const dynamicSkill = path13.join(sourceDir, "skill.ts");
2793
+ const sourceDir = path14.join(source, entry.name);
2794
+ const destinationDir = path14.join(destination, entry.name);
2795
+ const staticSkill = path14.join(sourceDir, "SKILL.md");
2796
+ const dynamicSkill = path14.join(sourceDir, "skill.ts");
2517
2797
  await mkdir6(destinationDir, { recursive: true });
2518
- if (existsSync4(staticSkill)) {
2798
+ if (existsSync5(staticSkill)) {
2519
2799
  await cp3(sourceDir, destinationDir, {
2520
2800
  recursive: true,
2521
- filter: async (sourcePath) => !sourcePath.endsWith(`${path13.sep}skill.ts`) && await safeSkillCopyFilter(sourcePath)
2801
+ filter: async (sourcePath) => !sourcePath.endsWith(`${path14.sep}skill.ts`) && await safeSkillCopyFilter(sourcePath)
2522
2802
  });
2523
- } else if (existsSync4(dynamicSkill)) {
2803
+ } else if (existsSync5(dynamicSkill)) {
2524
2804
  const generated = parseDynamicSkill(
2525
2805
  await readFile7(dynamicSkill, "utf8"),
2526
2806
  entry.name
2527
2807
  );
2528
- await writeFile6(path13.join(destinationDir, "SKILL.md"), generated);
2808
+ await writeFile6(path14.join(destinationDir, "SKILL.md"), generated);
2529
2809
  }
2530
2810
  }
2531
2811
  }
2532
2812
  async function safeSkillCopyFilter(sourcePath) {
2533
- const basename = path13.basename(sourcePath);
2813
+ const basename = path14.basename(sourcePath);
2534
2814
  if (basename === ".env" || basename.startsWith(".env.") || basename === "node_modules" || basename === ".git") {
2535
2815
  return false;
2536
2816
  }
@@ -2556,25 +2836,25 @@ async function buildPluginPackages(rootDir, outRoot, manifest) {
2556
2836
  await buildClaudePlugin(rootDir, outRoot, identity, manifest);
2557
2837
  }
2558
2838
  async function buildClaudePlugin(rootDir, outRoot, identity, manifest) {
2559
- const pluginDir = path14.join(outRoot, "claude-plugin");
2560
- await mkdir7(path14.join(pluginDir, ".claude-plugin"), { recursive: true });
2561
- await copySkills(rootDir, path14.join(pluginDir, "skills"));
2562
- await copyCommands(rootDir, path14.join(pluginDir, "commands"));
2563
- await copyHooks(rootDir, path14.join(pluginDir, "hooks"));
2564
- await emitClaudeAgents(rootDir, path14.join(pluginDir, "agents"));
2839
+ const pluginDir = path15.join(outRoot, "claude-plugin");
2840
+ await mkdir7(path15.join(pluginDir, ".claude-plugin"), { recursive: true });
2841
+ await copySkills(rootDir, path15.join(pluginDir, "skills"));
2842
+ await copyCommands(rootDir, path15.join(pluginDir, "commands"));
2843
+ await copyHooks(rootDir, path15.join(pluginDir, "hooks"));
2844
+ await emitClaudeAgents(rootDir, path15.join(pluginDir, "agents"));
2565
2845
  await copyClaudePassthroughDirectories(rootDir, pluginDir);
2566
- await writeJson(path14.join(pluginDir, ".claude-plugin", "plugin.json"), {
2846
+ await writeJson(path15.join(pluginDir, ".claude-plugin", "plugin.json"), {
2567
2847
  name: identity.slug,
2568
2848
  version: identity.version,
2569
2849
  description: identity.description,
2570
2850
  displayName: identity.name,
2571
2851
  installationPreference: "available"
2572
2852
  });
2573
- await writeJson(path14.join(pluginDir, "version.json"), {
2853
+ await writeJson(path15.join(pluginDir, "version.json"), {
2574
2854
  version: identity.version,
2575
2855
  generatedBy: "sidecar"
2576
2856
  });
2577
- await writeJson(path14.join(pluginDir, ".mcp.json"), {
2857
+ await writeJson(path15.join(pluginDir, ".mcp.json"), {
2578
2858
  mcpServers: {
2579
2859
  [identity.slug]: {
2580
2860
  type: "http",
@@ -2582,7 +2862,7 @@ async function buildClaudePlugin(rootDir, outRoot, identity, manifest) {
2582
2862
  }
2583
2863
  }
2584
2864
  });
2585
- await writeJson(path14.join(pluginDir, "settings.json"), {
2865
+ await writeJson(path15.join(pluginDir, "settings.json"), {
2586
2866
  sidecar: {
2587
2867
  tools: manifest.tools.map((entry) => entry.id),
2588
2868
  resources: manifest.resources.map((entry) => entry.uri),
@@ -2590,7 +2870,7 @@ async function buildClaudePlugin(rootDir, outRoot, identity, manifest) {
2590
2870
  }
2591
2871
  });
2592
2872
  await writeFile7(
2593
- path14.join(pluginDir, "README.md"),
2873
+ path15.join(pluginDir, "README.md"),
2594
2874
  `# ${identity.name} Claude Plugin
2595
2875
 
2596
2876
  This package was generated by Sidecar.
@@ -2604,7 +2884,7 @@ Claude/Cowork plugin-specific components such as skills, slash commands, agents,
2604
2884
  );
2605
2885
  }
2606
2886
  async function writeJson(filePath, value) {
2607
- await mkdir7(path14.dirname(filePath), { recursive: true });
2887
+ await mkdir7(path15.dirname(filePath), { recursive: true });
2608
2888
  await writeFile7(
2609
2889
  filePath,
2610
2890
  `${JSON.stringify(stripUndefined2(value), null, 2)}
@@ -2614,13 +2894,13 @@ async function writeJson(filePath, value) {
2614
2894
 
2615
2895
  // packages/compiler/src/prompts.ts
2616
2896
  import { readdir as readdir6 } from "fs/promises";
2617
- import path15 from "path";
2897
+ import path16 from "path";
2618
2898
  import {
2619
2899
  Node as Node7,
2620
2900
  SyntaxKind as SyntaxKind5
2621
2901
  } from "ts-morph";
2622
2902
  async function analyzeProjectPrompts(rootDir) {
2623
- const promptFiles = await findPromptFiles(path15.join(rootDir, "prompts"));
2903
+ const promptFiles = await findPromptFiles(path16.join(rootDir, "prompts"));
2624
2904
  if (promptFiles.length === 0) {
2625
2905
  return [];
2626
2906
  }
@@ -2632,7 +2912,7 @@ async function analyzeProjectPrompts(rootDir) {
2632
2912
  function analyzePromptFile(sourceFile, rootDir) {
2633
2913
  const definition = findPromptDefinition(sourceFile);
2634
2914
  const absoluteFile = sourceFile.getFilePath();
2635
- const directory = path15.basename(path15.dirname(absoluteFile));
2915
+ const directory = path16.basename(path16.dirname(absoluteFile));
2636
2916
  const name = getOptionalStringProperty2(definition, "name") ?? safePathSegment(directory);
2637
2917
  const title = getRequiredStringProperty2(definition, "title", sourceFile);
2638
2918
  const description = getOptionalStringProperty2(definition, "description");
@@ -2648,7 +2928,7 @@ function analyzePromptFile(sourceFile, rootDir) {
2648
2928
  throw new CompilerError(sourceFile, "prompt({ ... }) must include a run method.");
2649
2929
  }
2650
2930
  return {
2651
- sourceFile: path15.relative(rootDir, absoluteFile),
2931
+ sourceFile: path16.relative(rootDir, absoluteFile),
2652
2932
  directory,
2653
2933
  name,
2654
2934
  title,
@@ -2667,7 +2947,7 @@ async function findPromptFiles(promptsDir) {
2667
2947
  if (!entry.isDirectory()) {
2668
2948
  continue;
2669
2949
  }
2670
- const filePath = path15.join(promptsDir, entry.name, "prompt.ts");
2950
+ const filePath = path16.join(promptsDir, entry.name, "prompt.ts");
2671
2951
  if (existsSyncSafe(filePath)) {
2672
2952
  files.push(filePath);
2673
2953
  }
@@ -2789,7 +3069,7 @@ function readIcons(definition) {
2789
3069
  return [{
2790
3070
  src,
2791
3071
  mimeType: getOptionalStringProperty2(object, "mimeType"),
2792
- sizes: readStringArrayProperty3(object, "sizes")
3072
+ sizes: readStringArrayProperty4(object, "sizes")
2793
3073
  }];
2794
3074
  });
2795
3075
  return icons.length ? icons : void 0;
@@ -2802,7 +3082,7 @@ function readObjectProperty4(definition, propertyName) {
2802
3082
  const initializer = unwrapExpression(property.getInitializer());
2803
3083
  return initializer && Node7.isObjectLiteralExpression(initializer) ? initializer : void 0;
2804
3084
  }
2805
- function readStringArrayProperty3(definition, propertyName) {
3085
+ function readStringArrayProperty4(definition, propertyName) {
2806
3086
  const property = definition.getProperty(propertyName);
2807
3087
  if (!property || !Node7.isPropertyAssignment(property)) {
2808
3088
  return void 0;
@@ -2816,13 +3096,13 @@ function readStringArrayProperty3(definition, propertyName) {
2816
3096
 
2817
3097
  // packages/compiler/src/resources.ts
2818
3098
  import { readdir as readdir7 } from "fs/promises";
2819
- import path16 from "path";
3099
+ import path17 from "path";
2820
3100
  import {
2821
3101
  Node as Node8,
2822
3102
  SyntaxKind as SyntaxKind6
2823
3103
  } from "ts-morph";
2824
3104
  async function analyzeProjectResources(rootDir) {
2825
- const resourceFiles = await findResourceFiles(path16.join(rootDir, "resources"));
3105
+ const resourceFiles = await findResourceFiles(path17.join(rootDir, "resources"));
2826
3106
  if (resourceFiles.length === 0) {
2827
3107
  return [];
2828
3108
  }
@@ -2834,7 +3114,7 @@ async function analyzeProjectResources(rootDir) {
2834
3114
  function analyzeResourceFile(sourceFile, rootDir) {
2835
3115
  const definition = findResourceDefinition(sourceFile);
2836
3116
  const absoluteFile = sourceFile.getFilePath();
2837
- const directory = path16.basename(path16.dirname(absoluteFile));
3117
+ const directory = path17.basename(path17.dirname(absoluteFile));
2838
3118
  const defaultUri = `sidecar://resources/${safePathSegment(directory)}`;
2839
3119
  const name = getRequiredStringProperty3(definition, "name", sourceFile);
2840
3120
  const uri = getOptionalStringProperty3(definition, "uri") ?? defaultUri;
@@ -2852,7 +3132,7 @@ function analyzeResourceFile(sourceFile, rootDir) {
2852
3132
  throw new CompilerError(sourceFile, "resource({ ... }) must include a read method.");
2853
3133
  }
2854
3134
  return {
2855
- sourceFile: path16.relative(rootDir, absoluteFile),
3135
+ sourceFile: path17.relative(rootDir, absoluteFile),
2856
3136
  directory,
2857
3137
  uri,
2858
3138
  name,
@@ -2875,7 +3155,7 @@ async function findResourceFiles(resourcesDir) {
2875
3155
  if (!entry.isDirectory()) {
2876
3156
  continue;
2877
3157
  }
2878
- const filePath = path16.join(resourcesDir, entry.name, "resource.ts");
3158
+ const filePath = path17.join(resourcesDir, entry.name, "resource.ts");
2879
3159
  if (existsSyncSafe(filePath)) {
2880
3160
  files.push(filePath);
2881
3161
  }
@@ -2954,7 +3234,7 @@ function readAnnotations2(definition) {
2954
3234
  return void 0;
2955
3235
  }
2956
3236
  const annotations = {};
2957
- const audience = readStringArrayProperty4(initializer, "audience")?.filter((value) => value === "user" || value === "assistant");
3237
+ const audience = readStringArrayProperty5(initializer, "audience")?.filter((value) => value === "user" || value === "assistant");
2958
3238
  const priority = getOptionalNumberProperty(initializer, "priority");
2959
3239
  const lastModified = getOptionalStringProperty3(initializer, "lastModified");
2960
3240
  if (audience?.length) annotations.audience = audience;
@@ -2983,7 +3263,7 @@ function readIcons2(definition) {
2983
3263
  return [{
2984
3264
  src,
2985
3265
  mimeType: getOptionalStringProperty3(object, "mimeType"),
2986
- sizes: readStringArrayProperty4(object, "sizes")
3266
+ sizes: readStringArrayProperty5(object, "sizes")
2987
3267
  }];
2988
3268
  });
2989
3269
  return icons.length ? icons : void 0;
@@ -2996,7 +3276,7 @@ function readObjectProperty5(definition, propertyName) {
2996
3276
  const initializer = unwrapExpression(property.getInitializer());
2997
3277
  return initializer && Node8.isObjectLiteralExpression(initializer) ? initializer : void 0;
2998
3278
  }
2999
- function readStringArrayProperty4(definition, propertyName) {
3279
+ function readStringArrayProperty5(definition, propertyName) {
3000
3280
  const property = definition.getProperty(propertyName);
3001
3281
  if (!property || !Node8.isPropertyAssignment(property)) {
3002
3282
  return void 0;
@@ -3009,21 +3289,21 @@ function readStringArrayProperty4(definition, propertyName) {
3009
3289
  }
3010
3290
 
3011
3291
  // packages/compiler/src/server-output.ts
3012
- import { existsSync as existsSync5 } from "fs";
3292
+ import { existsSync as existsSync6 } from "fs";
3013
3293
  import { mkdir as mkdir8, rm, writeFile as writeFile8 } from "fs/promises";
3014
- import path17 from "path";
3294
+ import path18 from "path";
3015
3295
  import { build as esbuild2 } from "esbuild";
3016
3296
  var SERVER_ENTRYPOINT = "server/index.js";
3017
3297
  var VERCEL_FUNCTION_DIR = "functions/api/sidecar.func";
3018
3298
  var VERCEL_ENTRYPOINT = `${VERCEL_FUNCTION_DIR}/index.js`;
3019
3299
  var VERCEL_HANDLER_FILE = "index.js";
3020
3300
  async function buildServerOutput(rootDir, outDir, manifest, identity, host = "node", options = {}) {
3021
- const cacheDir = path17.join(rootDir, ".sidecar", "cache", "server");
3301
+ const cacheDir = path18.join(rootDir, ".sidecar", "cache", "server");
3022
3302
  await mkdir8(cacheDir, { recursive: true });
3023
- const entryFile = path17.join(cacheDir, "index.ts");
3303
+ const entryFile = path18.join(cacheDir, "index.ts");
3024
3304
  await writeFile8(entryFile, renderServerEntry(rootDir, entryFile, manifest, identity));
3025
- const serverFile = path17.join(outDir, SERVER_ENTRYPOINT);
3026
- await mkdir8(path17.dirname(serverFile), { recursive: true });
3305
+ const serverFile = path18.join(outDir, SERVER_ENTRYPOINT);
3306
+ await mkdir8(path18.dirname(serverFile), { recursive: true });
3027
3307
  await esbuild2({
3028
3308
  absWorkingDir: rootDir,
3029
3309
  alias: sidecarBundleAliases(rootDir),
@@ -3037,30 +3317,30 @@ const require = __sidecarCreateRequire(import.meta.url);`
3037
3317
  legalComments: "none",
3038
3318
  minify: false,
3039
3319
  nodePaths: [
3040
- path17.join(rootDir, "node_modules"),
3041
- path17.join(process.cwd(), "node_modules")
3320
+ path18.join(rootDir, "node_modules"),
3321
+ path18.join(process.cwd(), "node_modules")
3042
3322
  ],
3043
3323
  outfile: serverFile,
3044
3324
  platform: "node",
3045
3325
  sourcemap: false,
3046
3326
  target: "node20"
3047
3327
  });
3048
- await writeFile8(path17.join(outDir, "package.json"), renderServerPackage(identity));
3328
+ await writeFile8(path18.join(outDir, "package.json"), renderServerPackage(identity));
3049
3329
  if (host === "vercel") {
3050
3330
  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());
3331
+ await rm(path18.join(vercelOutputDir, "api"), { recursive: true, force: true });
3332
+ await rm(path18.join(vercelOutputDir, "vercel.json"), { force: true });
3333
+ await writeFile8(path18.join(outDir, VERCEL_HANDLER_FILE), renderVercelEntrypoint());
3334
+ await writeFile8(path18.join(outDir, ".vc-config.json"), renderVercelFunctionConfig());
3055
3335
  await mkdir8(vercelOutputDir, { recursive: true });
3056
- await writeFile8(path17.join(vercelOutputDir, "config.json"), renderVercelOutputConfig());
3336
+ await writeFile8(path18.join(vercelOutputDir, "config.json"), renderVercelOutputConfig());
3057
3337
  } else {
3058
- await rm(path17.join(outDir, "api"), { recursive: true, force: true });
3059
- await rm(path17.join(outDir, "vercel.json"), { force: true });
3338
+ await rm(path18.join(outDir, "api"), { recursive: true, force: true });
3339
+ await rm(path18.join(outDir, "vercel.json"), { force: true });
3060
3340
  }
3061
3341
  }
3062
3342
  function renderServerEntry(rootDir, entryFile, manifest, identity) {
3063
- const entryDir = path17.dirname(entryFile);
3343
+ const entryDir = path18.dirname(entryFile);
3064
3344
  const tools = manifest.tools;
3065
3345
  const resources = manifest.resources;
3066
3346
  const prompts = manifest.prompts;
@@ -3073,17 +3353,17 @@ function renderServerEntry(rootDir, entryFile, manifest, identity) {
3073
3353
  `import { isSidecarPrompt, isSidecarResource, isSidecarTool } from "@sidecar-ai/core";`,
3074
3354
  `import { isSidecarProxy } from "@sidecar-ai/server/proxy";`,
3075
3355
  ...tools.map(
3076
- (entry, index) => `import tool${index} from ${JSON.stringify(toImportSpecifier(entryDir, path17.join(rootDir, entry.sourceFile)))};`
3356
+ (entry, index) => `import tool${index} from ${JSON.stringify(toImportSpecifier(entryDir, path18.join(rootDir, entry.sourceFile)))};`
3077
3357
  ),
3078
3358
  ...resources.map(
3079
- (entry, index) => `import resource${index} from ${JSON.stringify(toImportSpecifier(entryDir, path17.join(rootDir, entry.sourceFile)))};`
3359
+ (entry, index) => `import resource${index} from ${JSON.stringify(toImportSpecifier(entryDir, path18.join(rootDir, entry.sourceFile)))};`
3080
3360
  ),
3081
3361
  ...prompts.map(
3082
- (entry, index) => `import prompt${index} from ${JSON.stringify(toImportSpecifier(entryDir, path17.join(rootDir, entry.sourceFile)))};`
3362
+ (entry, index) => `import prompt${index} from ${JSON.stringify(toImportSpecifier(entryDir, path18.join(rootDir, entry.sourceFile)))};`
3083
3363
  ),
3084
- existsSync5(path17.join(rootDir, "auth.ts")) ? `import authExport from ${JSON.stringify(toImportSpecifier(entryDir, path17.join(rootDir, "auth.ts")))};` : `const authExport = undefined;`,
3085
- existsSync5(path17.join(rootDir, "proxy.ts")) ? `import proxyExport from ${JSON.stringify(toImportSpecifier(entryDir, path17.join(rootDir, "proxy.ts")))};` : `const proxyExport = undefined;`,
3086
- existsSync5(path17.join(rootDir, "sidecar.config.ts")) ? `import configExport from ${JSON.stringify(toImportSpecifier(entryDir, path17.join(rootDir, "sidecar.config.ts")))};` : `const configExport = undefined;`
3364
+ existsSync6(path18.join(rootDir, "auth.ts")) ? `import authExport from ${JSON.stringify(toImportSpecifier(entryDir, path18.join(rootDir, "auth.ts")))};` : `const authExport = undefined;`,
3365
+ existsSync6(path18.join(rootDir, "proxy.ts")) ? `import proxyExport from ${JSON.stringify(toImportSpecifier(entryDir, path18.join(rootDir, "proxy.ts")))};` : `const proxyExport = undefined;`,
3366
+ existsSync6(path18.join(rootDir, "sidecar.config.ts")) ? `import configExport from ${JSON.stringify(toImportSpecifier(entryDir, path18.join(rootDir, "sidecar.config.ts")))};` : `const configExport = undefined;`
3087
3367
  ].join("\n");
3088
3368
  return `${imports}
3089
3369
 
@@ -3194,7 +3474,7 @@ function unwrapRuntimeDefault(value) {
3194
3474
  value &&
3195
3475
  typeof value === "object" &&
3196
3476
  "default" in value &&
3197
- Object.keys(value).length === 1
3477
+ Object.keys(value).every((key) => key === "default" || key === "__esModule")
3198
3478
  ) {
3199
3479
  return unwrapRuntimeDefault(value.default);
3200
3480
  }
@@ -3286,35 +3566,35 @@ function sidecarBundleAliases(rootDir) {
3286
3566
  return void 0;
3287
3567
  }
3288
3568
  return {
3289
- "sidecar-ai": path17.join(repoRoot, "packages", "sidecar-ai", "src", "index.ts"),
3290
- "@sidecar-ai/auth": path17.join(repoRoot, "packages", "auth", "src", "index.ts"),
3291
- "@sidecar-ai/core": path17.join(repoRoot, "packages", "core", "src", "index.ts"),
3292
- "@sidecar-ai/server": path17.join(repoRoot, "packages", "server", "src", "index.ts"),
3293
- "@sidecar-ai/server/proxy": path17.join(repoRoot, "packages", "server", "src", "proxy.ts"),
3294
- "@sidecar-ai/client": path17.join(repoRoot, "packages", "client", "src", "index.ts"),
3295
- "@sidecar-ai/react": path17.join(repoRoot, "packages", "react", "src", "index.ts"),
3296
- "@sidecar-ai/native": path17.join(repoRoot, "packages", "native", "src", "index.ts"),
3297
- "@sidecar-ai/native/components": path17.join(repoRoot, "packages", "native", "src", "components", "index.tsx"),
3298
- "@sidecar-ai/openai": path17.join(repoRoot, "packages", "openai", "src", "index.ts"),
3299
- "@sidecar-ai/openai/components": path17.join(repoRoot, "packages", "openai", "src", "components.tsx"),
3300
- "@sidecar-ai/openai/official": path17.join(repoRoot, "packages", "openai", "src", "official.ts"),
3301
- "@sidecar-ai/anthropic": path17.join(repoRoot, "packages", "anthropic", "src", "index.ts"),
3302
- "@sidecar-ai/anthropic/agent": path17.join(repoRoot, "packages", "anthropic", "src", "agent.ts"),
3303
- "@sidecar-ai/anthropic/command": path17.join(repoRoot, "packages", "anthropic", "src", "command.ts"),
3304
- "@sidecar-ai/anthropic/components": path17.join(repoRoot, "packages", "anthropic", "src", "components.tsx"),
3305
- "@sidecar-ai/anthropic/hooks": path17.join(repoRoot, "packages", "anthropic", "src", "hooks.ts"),
3306
- "@sidecar-ai/anthropic/mcp": path17.join(repoRoot, "packages", "anthropic", "src", "mcp.ts"),
3307
- "@sidecar-ai/anthropic/plugin": path17.join(repoRoot, "packages", "anthropic", "src", "plugin.ts"),
3308
- "@sidecar-ai/anthropic/skill": path17.join(repoRoot, "packages", "anthropic", "src", "skill.ts")
3569
+ "sidecar-ai": path18.join(repoRoot, "packages", "sidecar-ai", "src", "index.ts"),
3570
+ "@sidecar-ai/auth": path18.join(repoRoot, "packages", "auth", "src", "index.ts"),
3571
+ "@sidecar-ai/core": path18.join(repoRoot, "packages", "core", "src", "index.ts"),
3572
+ "@sidecar-ai/server": path18.join(repoRoot, "packages", "server", "src", "index.ts"),
3573
+ "@sidecar-ai/server/proxy": path18.join(repoRoot, "packages", "server", "src", "proxy.ts"),
3574
+ "@sidecar-ai/client": path18.join(repoRoot, "packages", "client", "src", "index.ts"),
3575
+ "@sidecar-ai/react": path18.join(repoRoot, "packages", "react", "src", "index.ts"),
3576
+ "@sidecar-ai/native": path18.join(repoRoot, "packages", "native", "src", "index.ts"),
3577
+ "@sidecar-ai/native/components": path18.join(repoRoot, "packages", "native", "src", "components", "index.tsx"),
3578
+ "@sidecar-ai/openai": path18.join(repoRoot, "packages", "openai", "src", "index.ts"),
3579
+ "@sidecar-ai/openai/components": path18.join(repoRoot, "packages", "openai", "src", "components.tsx"),
3580
+ "@sidecar-ai/openai/official": path18.join(repoRoot, "packages", "openai", "src", "official.ts"),
3581
+ "@sidecar-ai/anthropic": path18.join(repoRoot, "packages", "anthropic", "src", "index.ts"),
3582
+ "@sidecar-ai/anthropic/agent": path18.join(repoRoot, "packages", "anthropic", "src", "agent.ts"),
3583
+ "@sidecar-ai/anthropic/command": path18.join(repoRoot, "packages", "anthropic", "src", "command.ts"),
3584
+ "@sidecar-ai/anthropic/components": path18.join(repoRoot, "packages", "anthropic", "src", "components.tsx"),
3585
+ "@sidecar-ai/anthropic/hooks": path18.join(repoRoot, "packages", "anthropic", "src", "hooks.ts"),
3586
+ "@sidecar-ai/anthropic/mcp": path18.join(repoRoot, "packages", "anthropic", "src", "mcp.ts"),
3587
+ "@sidecar-ai/anthropic/plugin": path18.join(repoRoot, "packages", "anthropic", "src", "plugin.ts"),
3588
+ "@sidecar-ai/anthropic/skill": path18.join(repoRoot, "packages", "anthropic", "src", "skill.ts")
3309
3589
  };
3310
3590
  }
3311
3591
  function findSidecarRepoRoot2(startDir) {
3312
- let current = path17.resolve(startDir);
3592
+ let current = path18.resolve(startDir);
3313
3593
  while (true) {
3314
- if (existsSync5(path17.join(current, "packages", "core", "src", "index.ts"))) {
3594
+ if (existsSync6(path18.join(current, "packages", "core", "src", "index.ts"))) {
3315
3595
  return current;
3316
3596
  }
3317
- const parent = path17.dirname(current);
3597
+ const parent = path18.dirname(current);
3318
3598
  if (parent === current) {
3319
3599
  return void 0;
3320
3600
  }
@@ -3324,7 +3604,7 @@ function findSidecarRepoRoot2(startDir) {
3324
3604
 
3325
3605
  // packages/compiler/src/build.ts
3326
3606
  async function buildProject(options) {
3327
- const rootDir = path18.resolve(options.rootDir);
3607
+ const rootDir = path19.resolve(options.rootDir);
3328
3608
  const config = analyzeProjectConfig(rootDir);
3329
3609
  const target = options.target ?? config.build.target ?? "mcp";
3330
3610
  const host = options.host ?? config.build.host ?? "node";
@@ -3346,7 +3626,7 @@ async function buildProject(options) {
3346
3626
  }
3347
3627
  const outDir = resolveInsideRoot(rootDir, options.outDir ?? config.build.outDir ?? defaultBuildOutDir(host, target));
3348
3628
  const runtimeOutDir = resolveRuntimeOutputDir(outDir, host);
3349
- await buildWidgets(rootDir, runtimeOutDir, tools);
3629
+ await buildWidgets(rootDir, runtimeOutDir, tools, config.build.widgets);
3350
3630
  const manifest = {
3351
3631
  version: 1,
3352
3632
  target,
@@ -3362,11 +3642,11 @@ async function buildProject(options) {
3362
3642
  };
3363
3643
  await mkdir9(runtimeOutDir, { recursive: true });
3364
3644
  await writeFile9(
3365
- path18.join(runtimeOutDir, "manifest.sidecar.json"),
3645
+ path19.join(runtimeOutDir, "manifest.sidecar.json"),
3366
3646
  `${JSON.stringify(manifest, null, 2)}
3367
3647
  `
3368
3648
  );
3369
- await writeFile9(path18.join(runtimeOutDir, "README.md"), renderMcpReadme(manifest));
3649
+ await writeFile9(path19.join(runtimeOutDir, "README.md"), renderMcpReadme(manifest));
3370
3650
  await writeGeneratedTypes(rootDir, tools);
3371
3651
  await buildServerOutput(rootDir, runtimeOutDir, manifest, identity, host, {
3372
3652
  vercelOutputDir: outDir
@@ -3384,23 +3664,23 @@ function defaultBuildOutDir(host, target) {
3384
3664
  }
3385
3665
  function resolveRuntimeOutputDir(outDir, host) {
3386
3666
  if (host === "vercel") {
3387
- return path18.join(outDir, VERCEL_FUNCTION_DIR);
3667
+ return path19.join(outDir, VERCEL_FUNCTION_DIR);
3388
3668
  }
3389
3669
  return outDir;
3390
3670
  }
3391
3671
  function resolvePluginOutputBase(rootDir, outDir, host) {
3392
3672
  if (host === "vercel" && isVercelBuildOutputDir(outDir)) {
3393
- return path18.join(rootDir, "out");
3673
+ return path19.join(rootDir, "out");
3394
3674
  }
3395
- return path18.dirname(outDir);
3675
+ return path19.dirname(outDir);
3396
3676
  }
3397
3677
  function isVercelBuildOutputDir(outDir) {
3398
- return path18.basename(outDir) === "output" && path18.basename(path18.dirname(outDir)) === ".vercel";
3678
+ return path19.basename(outDir) === "output" && path19.basename(path19.dirname(outDir)) === ".vercel";
3399
3679
  }
3400
3680
  function resolveInsideRoot(rootDir, output) {
3401
- const resolved = path18.resolve(rootDir, output);
3402
- const relative = path18.relative(rootDir, resolved);
3403
- if (relative.startsWith("..") || path18.isAbsolute(relative)) {
3681
+ const resolved = path19.resolve(rootDir, output);
3682
+ const relative = path19.relative(rootDir, resolved);
3683
+ if (relative.startsWith("..") || path19.isAbsolute(relative)) {
3404
3684
  throw new Error(`Build output must stay inside the project root: ${output}`);
3405
3685
  }
3406
3686
  return resolved;
@@ -3963,6 +4243,11 @@ function createSidecarHttpHandler(options) {
3963
4243
  const streamHub = createSseHub();
3964
4244
  const mcp = createSidecarMcpServer(options);
3965
4245
  return async (request, response) => {
4246
+ const pathname = request.url?.split("?")[0];
4247
+ const requestLog = createHttpRequestLog(request, pathname);
4248
+ response.once("finish", () => {
4249
+ logHttpRequest(requestLog, response.statusCode);
4250
+ });
3966
4251
  if (isRejectedOrigin(request, options.allowedOrigins)) {
3967
4252
  response.writeHead(403, { "content-type": "application/json" });
3968
4253
  response.end(JSON.stringify({ error: "forbidden_origin" }));
@@ -3974,16 +4259,17 @@ function createSidecarHttpHandler(options) {
3974
4259
  response.end(proxyResult.body ?? "");
3975
4260
  return;
3976
4261
  }
3977
- const pathname = request.url?.split("?")[0];
3978
4262
  if (options.auth && request.method === "GET" && isProtectedResourceMetadataPath(pathname, endpoint)) {
3979
4263
  response.writeHead(200, { "content-type": "application/json" });
3980
4264
  response.end(JSON.stringify(options.auth.metadata()));
3981
4265
  return;
3982
4266
  }
4267
+ if (options.auth && request.method === "GET" && pathname === "/.well-known/oauth-authorization-server") {
4268
+ await proxyAuthorizationServerMetadata(options.auth, response);
4269
+ return;
4270
+ }
3983
4271
  if (request.method === "GET" && pathname === endpoint) {
3984
4272
  try {
3985
- validateProtocolVersion(request);
3986
- validateGetHeaders(request);
3987
4273
  const fetchRequest = toFetchRequest(request, options.publicUrl ?? options.auth?.resource);
3988
4274
  if (options.auth) {
3989
4275
  const authSession = await authorizeHttpRequest(options.auth, fetchRequest, response);
@@ -3991,6 +4277,8 @@ function createSidecarHttpHandler(options) {
3991
4277
  return;
3992
4278
  }
3993
4279
  }
4280
+ validateProtocolVersion(request);
4281
+ validateGetHeaders(request);
3994
4282
  streamHub.open(response);
3995
4283
  } catch (error) {
3996
4284
  const status = error instanceof JsonRpcHttpError ? error.status : 400;
@@ -4019,6 +4307,11 @@ function createSidecarHttpHandler(options) {
4019
4307
  return;
4020
4308
  }
4021
4309
  try {
4310
+ const fetchRequest = toFetchRequest(request, options.publicUrl ?? options.auth?.resource);
4311
+ const authSession = options.auth ? await authorizeHttpRequest(options.auth, fetchRequest, response) : void 0;
4312
+ if (options.auth && authSession === AUTH_RESPONSE_SENT) {
4313
+ return;
4314
+ }
4022
4315
  validateProtocolVersion(request);
4023
4316
  validatePostHeaders(request);
4024
4317
  const body = await readJson(request, maxBodyBytes);
@@ -4031,11 +4324,6 @@ function createSidecarHttpHandler(options) {
4031
4324
  return;
4032
4325
  }
4033
4326
  const rpcRequest = assertJsonRpcRequest(body);
4034
- const fetchRequest = toFetchRequest(request, options.publicUrl ?? options.auth?.resource);
4035
- const authSession = options.auth ? await authorizeHttpRequest(options.auth, fetchRequest, response) : void 0;
4036
- if (options.auth && authSession === AUTH_RESPONSE_SENT) {
4037
- return;
4038
- }
4039
4327
  if (rpcRequest.id !== void 0 && hasProgressToken(rpcRequest)) {
4040
4328
  const stream = createSseStream(response, { supportsRequestProgress: true });
4041
4329
  const payload2 = await mcp.handle(rpcRequest, {
@@ -4127,6 +4415,73 @@ function escapeRegExp(value) {
4127
4415
  function isProtectedResourceMetadataPath(pathname, endpoint) {
4128
4416
  return pathname === "/.well-known/oauth-protected-resource" || pathname === `/.well-known/oauth-protected-resource${endpoint}`;
4129
4417
  }
4418
+ function createHttpRequestLog(request, pathname) {
4419
+ return {
4420
+ method: request.method,
4421
+ path: pathname,
4422
+ host: truncateHeader(singleHeader(request.headers.host)),
4423
+ accept: truncateHeader(singleHeader(request.headers.accept)),
4424
+ contentType: truncateHeader(singleHeader(request.headers["content-type"])),
4425
+ contentLength: truncateHeader(singleHeader(request.headers["content-length"])),
4426
+ mcpProtocolVersion: truncateHeader(singleHeader(request.headers["mcp-protocol-version"])),
4427
+ origin: truncateHeader(singleHeader(request.headers.origin)),
4428
+ userAgent: truncateHeader(singleHeader(request.headers["user-agent"])),
4429
+ authorization: request.headers.authorization ? "present" : "absent",
4430
+ cookie: request.headers.cookie ? "present" : "absent"
4431
+ };
4432
+ }
4433
+ function logHttpRequest(metadata, status) {
4434
+ const debug = process.env.SIDECAR_DEBUG === "1" || process.env.SIDECAR_LOG_LEVEL === "debug";
4435
+ if (!debug && status < 400) {
4436
+ return;
4437
+ }
4438
+ const message = JSON.stringify({
4439
+ event: "sidecar.mcp.http",
4440
+ status,
4441
+ ...stripUndefined4(metadata)
4442
+ });
4443
+ if (status >= 500) {
4444
+ console.error(message);
4445
+ } else if (status >= 400) {
4446
+ console.warn(message);
4447
+ } else {
4448
+ console.info(message);
4449
+ }
4450
+ }
4451
+ function singleHeader(value) {
4452
+ return Array.isArray(value) ? value.join(", ") : value;
4453
+ }
4454
+ function truncateHeader(value) {
4455
+ if (!value) {
4456
+ return void 0;
4457
+ }
4458
+ return value.length > 240 ? `${value.slice(0, 237)}...` : value;
4459
+ }
4460
+ async function proxyAuthorizationServerMetadata(auth, response) {
4461
+ const [authorizationServer] = auth.authorizationServers;
4462
+ if (!authorizationServer) {
4463
+ response.writeHead(404, { "content-type": "application/json" });
4464
+ response.end(JSON.stringify({ error: "authorization_server_not_configured" }));
4465
+ return;
4466
+ }
4467
+ try {
4468
+ const url = new URL("/.well-known/oauth-authorization-server", authorizationServer);
4469
+ const upstream = await fetch(url, { headers: { accept: "application/json" } });
4470
+ const body = await upstream.text();
4471
+ response.writeHead(upstream.ok ? 200 : 502, {
4472
+ "content-type": upstream.headers.get("content-type") ?? "application/json"
4473
+ });
4474
+ response.end(body);
4475
+ } catch (error) {
4476
+ console.warn(JSON.stringify({
4477
+ event: "sidecar.mcp.authorization_metadata_proxy_failed",
4478
+ authorizationServer,
4479
+ message: error instanceof Error ? error.message : "Unknown error"
4480
+ }));
4481
+ response.writeHead(502, { "content-type": "application/json" });
4482
+ response.end(JSON.stringify({ error: "authorization_metadata_unavailable" }));
4483
+ }
4484
+ }
4130
4485
  var JsonRpcError = class extends Error {
4131
4486
  constructor(code, message, data) {
4132
4487
  super(message);
@@ -4476,44 +4831,44 @@ function validateAgainstSchema(schema, value, message, options = {}) {
4476
4831
  }
4477
4832
  return value;
4478
4833
  }
4479
- function schemaFailure(schema, value, path20) {
4480
- if (schema.anyOf?.length && !schema.anyOf.some((entry) => !schemaFailure(entry, value, path20))) {
4481
- return `${path20} must match one anyOf schema.`;
4834
+ function schemaFailure(schema, value, path21) {
4835
+ if (schema.anyOf?.length && !schema.anyOf.some((entry) => !schemaFailure(entry, value, path21))) {
4836
+ return `${path21} must match one anyOf schema.`;
4482
4837
  }
4483
- if (schema.oneOf?.length && schema.oneOf.filter((entry) => !schemaFailure(entry, value, path20)).length !== 1) {
4484
- return `${path20} must match exactly one oneOf schema.`;
4838
+ if (schema.oneOf?.length && schema.oneOf.filter((entry) => !schemaFailure(entry, value, path21)).length !== 1) {
4839
+ return `${path21} must match exactly one oneOf schema.`;
4485
4840
  }
4486
4841
  if (schema.allOf?.length) {
4487
4842
  for (const entry of schema.allOf) {
4488
- const failure = schemaFailure(entry, value, path20);
4843
+ const failure = schemaFailure(entry, value, path21);
4489
4844
  if (failure) return failure;
4490
4845
  }
4491
4846
  }
4492
4847
  if (schema.const !== void 0 && value !== schema.const) {
4493
- return `${path20} must equal ${JSON.stringify(schema.const)}.`;
4848
+ return `${path21} must equal ${JSON.stringify(schema.const)}.`;
4494
4849
  }
4495
4850
  if (schema.enum && !schema.enum.some((entry) => JSON.stringify(entry) === JSON.stringify(value))) {
4496
- return `${path20} must be one of the declared enum values.`;
4851
+ return `${path21} must be one of the declared enum values.`;
4497
4852
  }
4498
4853
  if (schema.type) {
4499
4854
  const types = Array.isArray(schema.type) ? schema.type : [schema.type];
4500
4855
  if (!types.some((type) => matchesJsonSchemaType(type, value))) {
4501
- return `${path20} must be ${types.join(" or ")}.`;
4856
+ return `${path21} must be ${types.join(" or ")}.`;
4502
4857
  }
4503
4858
  }
4504
4859
  if (schema.type === "object" || schema.properties || schema.required) {
4505
4860
  if (!value || typeof value !== "object" || Array.isArray(value)) {
4506
- return `${path20} must be an object.`;
4861
+ return `${path21} must be an object.`;
4507
4862
  }
4508
4863
  const record = value;
4509
4864
  for (const required of schema.required ?? []) {
4510
4865
  if (!(required in record)) {
4511
- return `${path20}.${required} is required.`;
4866
+ return `${path21}.${required} is required.`;
4512
4867
  }
4513
4868
  }
4514
4869
  for (const [key, propertySchema] of Object.entries(schema.properties ?? {})) {
4515
4870
  if (key in record) {
4516
- const failure = schemaFailure(propertySchema, record[key], `${path20}.${key}`);
4871
+ const failure = schemaFailure(propertySchema, record[key], `${path21}.${key}`);
4517
4872
  if (failure) return failure;
4518
4873
  }
4519
4874
  }
@@ -4521,12 +4876,12 @@ function schemaFailure(schema, value, path20) {
4521
4876
  if (schema.additionalProperties === false) {
4522
4877
  const extra = Object.keys(record).find((key) => !allowed.has(key));
4523
4878
  if (extra) {
4524
- return `${path20}.${extra} is not allowed.`;
4879
+ return `${path21}.${extra} is not allowed.`;
4525
4880
  }
4526
4881
  } else if (schema.additionalProperties && typeof schema.additionalProperties === "object") {
4527
4882
  for (const [key, entry] of Object.entries(record)) {
4528
4883
  if (!allowed.has(key)) {
4529
- const failure = schemaFailure(schema.additionalProperties, entry, `${path20}.${key}`);
4884
+ const failure = schemaFailure(schema.additionalProperties, entry, `${path21}.${key}`);
4530
4885
  if (failure) return failure;
4531
4886
  }
4532
4887
  }
@@ -4534,29 +4889,38 @@ function schemaFailure(schema, value, path20) {
4534
4889
  }
4535
4890
  if (schema.type === "array" || schema.items) {
4536
4891
  if (!Array.isArray(value)) {
4537
- return `${path20} must be an array.`;
4892
+ return `${path21} must be an array.`;
4893
+ }
4894
+ if (schema.minItems !== void 0 && value.length < schema.minItems) {
4895
+ return `${path21} must contain at least ${schema.minItems} items.`;
4896
+ }
4897
+ if (schema.maxItems !== void 0 && value.length > schema.maxItems) {
4898
+ return `${path21} must contain at most ${schema.maxItems} items.`;
4538
4899
  }
4539
4900
  if (schema.items) {
4540
4901
  for (const [index, entry] of value.entries()) {
4541
- const failure = schemaFailure(schema.items, entry, `${path20}[${index}]`);
4902
+ const failure = schemaFailure(schema.items, entry, `${path21}[${index}]`);
4542
4903
  if (failure) return failure;
4543
4904
  }
4544
4905
  }
4545
4906
  }
4546
4907
  if (typeof value === "string") {
4547
4908
  if (schema.minLength !== void 0 && value.length < schema.minLength) {
4548
- return `${path20} is shorter than ${schema.minLength}.`;
4909
+ return `${path21} is shorter than ${schema.minLength}.`;
4549
4910
  }
4550
4911
  if (schema.maxLength !== void 0 && value.length > schema.maxLength) {
4551
- return `${path20} is longer than ${schema.maxLength}.`;
4912
+ return `${path21} is longer than ${schema.maxLength}.`;
4913
+ }
4914
+ if (schema.pattern !== void 0 && !new RegExp(schema.pattern).test(value)) {
4915
+ return `${path21} must match pattern ${schema.pattern}.`;
4552
4916
  }
4553
4917
  }
4554
4918
  if (typeof value === "number") {
4555
4919
  if (schema.minimum !== void 0 && value < schema.minimum) {
4556
- return `${path20} is less than ${schema.minimum}.`;
4920
+ return `${path21} is less than ${schema.minimum}.`;
4557
4921
  }
4558
4922
  if (schema.maximum !== void 0 && value > schema.maximum) {
4559
- return `${path20} is greater than ${schema.maximum}.`;
4923
+ return `${path21} is greater than ${schema.maximum}.`;
4560
4924
  }
4561
4925
  }
4562
4926
  return void 0;
@@ -4734,11 +5098,11 @@ import { stdin, stdout } from "process";
4734
5098
  async function startTunnel(options) {
4735
5099
  const provider = await resolveProvider(options.provider);
4736
5100
  const localUrl = `http://127.0.0.1:${options.port}`;
4737
- const path20 = options.path ?? "/mcp";
5101
+ const path21 = options.path ?? "/mcp";
4738
5102
  if (provider === "cloudflared") {
4739
- return startCloudflared(localUrl, path20, options.timeoutMs);
5103
+ return startCloudflared(localUrl, path21, options.timeoutMs);
4740
5104
  }
4741
- return startWrangler(localUrl, path20, options.timeoutMs);
5105
+ return startWrangler(localUrl, path21, options.timeoutMs);
4742
5106
  }
4743
5107
  async function validateTunnelEndpoint(options) {
4744
5108
  const timeoutMs = options.timeoutMs ?? 1e4;
@@ -4862,7 +5226,7 @@ function assertNpxAvailable() {
4862
5226
  throw new Error(tunnelInstallMessage("wrangler"));
4863
5227
  }
4864
5228
  }
4865
- async function startCloudflared(localUrl, path20, timeoutMs = 2e4) {
5229
+ async function startCloudflared(localUrl, path21, timeoutMs = 2e4) {
4866
5230
  const child = spawn("cloudflared", ["tunnel", "--url", localUrl, "--no-autoupdate"], {
4867
5231
  stdio: ["ignore", "pipe", "pipe"]
4868
5232
  });
@@ -4870,13 +5234,13 @@ async function startCloudflared(localUrl, path20, timeoutMs = 2e4) {
4870
5234
  return {
4871
5235
  provider: "cloudflared",
4872
5236
  publicUrl,
4873
- mcpUrl: appendPath(publicUrl, path20),
5237
+ mcpUrl: appendPath(publicUrl, path21),
4874
5238
  close() {
4875
5239
  child.kill("SIGTERM");
4876
5240
  }
4877
5241
  };
4878
5242
  }
4879
- async function startWrangler(localUrl, path20, timeoutMs = 2e4) {
5243
+ async function startWrangler(localUrl, path21, timeoutMs = 2e4) {
4880
5244
  const child = spawn("npx", ["--yes", "wrangler", "tunnel", "quick-start", localUrl], {
4881
5245
  stdio: ["ignore", "pipe", "pipe"]
4882
5246
  });
@@ -4884,7 +5248,7 @@ async function startWrangler(localUrl, path20, timeoutMs = 2e4) {
4884
5248
  return {
4885
5249
  provider: "wrangler",
4886
5250
  publicUrl,
4887
- mcpUrl: appendPath(publicUrl, path20),
5251
+ mcpUrl: appendPath(publicUrl, path21),
4888
5252
  close() {
4889
5253
  child.kill("SIGTERM");
4890
5254
  }
@@ -5145,8 +5509,8 @@ function runInherited(command, args) {
5145
5509
  });
5146
5510
  });
5147
5511
  }
5148
- function appendPath(origin, path20) {
5149
- return `${origin.replace(/\/+$/, "")}/${path20.replace(/^\/+/, "")}`;
5512
+ function appendPath(origin, path21) {
5513
+ return `${origin.replace(/\/+$/, "")}/${path21.replace(/^\/+/, "")}`;
5150
5514
  }
5151
5515
  function isRecord3(value) {
5152
5516
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
@@ -5174,9 +5538,9 @@ async function main(argv) {
5174
5538
  );
5175
5539
  console.log(`Host runtime: ${manifest.host}`);
5176
5540
  if (manifest.host === "vercel") {
5177
- console.log(`Vercel MCP function: ${path19.join(resolvedOutDir, VERCEL_ENTRYPOINT)}`);
5541
+ console.log(`Vercel MCP function: ${path20.join(resolvedOutDir, VERCEL_ENTRYPOINT)}`);
5178
5542
  } else {
5179
- console.log(`Hostable MCP server: ${path19.join(resolvedOutDir, SERVER_ENTRYPOINT)}`);
5543
+ console.log(`Hostable MCP server: ${path20.join(resolvedOutDir, SERVER_ENTRYPOINT)}`);
5180
5544
  }
5181
5545
  if (plugins ?? manifest.config.build.plugins) {
5182
5546
  console.log("Built claude-plugin package.");
@@ -5362,8 +5726,8 @@ function readOptionalPlugins(argv) {
5362
5726
  return void 0;
5363
5727
  }
5364
5728
  async function previewComponents(options) {
5365
- const cliDir = path19.dirname(fileURLToPath(import.meta.url));
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(() => "");
5729
+ const cliDir = path20.dirname(fileURLToPath(import.meta.url));
5730
+ const css = await readFile8(path20.join(cliDir, "../../native/src/styles.css"), "utf8").catch(() => readFile8(path20.join(process.cwd(), "packages/native/src/styles.css"), "utf8")).catch(() => "");
5367
5731
  const html = renderComponentPreviewHtml(
5368
5732
  options.host,
5369
5733
  options.compare,
@@ -5403,10 +5767,10 @@ async function previewComponents(options) {
5403
5767
  server.close();
5404
5768
  }
5405
5769
  async function writeComponentApproval(rootDir, approval) {
5406
- const dir = path19.join(rootDir, ".sidecar", "approvals");
5770
+ const dir = path20.join(rootDir, ".sidecar", "approvals");
5407
5771
  await mkdir10(dir, { recursive: true });
5408
5772
  await writeFile10(
5409
- path19.join(dir, `components.${approval.host}.json`),
5773
+ path20.join(dir, `components.${approval.host}.json`),
5410
5774
  `${JSON.stringify(approval, null, 2)}
5411
5775
  `
5412
5776
  );
@@ -5758,71 +6122,71 @@ function printDiagnostics(diagnostics) {
5758
6122
  }
5759
6123
  }
5760
6124
  async function loadRuntimeAuth(rootDir) {
5761
- const authPath = path19.join(rootDir, "auth.ts");
5762
- if (!existsSync6(authPath)) {
6125
+ const authPath = path20.join(rootDir, "auth.ts");
6126
+ if (!existsSync7(authPath)) {
5763
6127
  return void 0;
5764
6128
  }
5765
- const parentURL = pathToFileURL(path19.join(rootDir, "sidecar.config.ts")).href;
5766
- const tsconfigPath = path19.join(rootDir, "tsconfig.json");
5767
- const tsconfig = existsSync6(tsconfigPath) ? tsconfigPath : false;
5768
- const module = await tsImport(pathToFileURL(authPath).href, {
6129
+ const parentURL = pathToFileURL3(path20.join(rootDir, "sidecar.config.ts")).href;
6130
+ const tsconfigPath = path20.join(rootDir, "tsconfig.json");
6131
+ const tsconfig = existsSync7(tsconfigPath) ? tsconfigPath : false;
6132
+ const module = await tsImport2(pathToFileURL3(authPath).href, {
5769
6133
  parentURL,
5770
6134
  tsconfig
5771
6135
  });
5772
- const defaultExport = unwrapRuntimeDefault(module.default);
6136
+ const defaultExport = unwrapRuntimeDefault2(module.default);
5773
6137
  if (!isSidecarAuth(defaultExport)) {
5774
6138
  throw new Error("auth.ts must default-export auth({ ... }) from sidecar-ai.");
5775
6139
  }
5776
6140
  return defaultExport;
5777
6141
  }
5778
6142
  async function loadRuntimeProxy(rootDir) {
5779
- const proxyPath = path19.join(rootDir, "proxy.ts");
5780
- if (!existsSync6(proxyPath)) {
6143
+ const proxyPath = path20.join(rootDir, "proxy.ts");
6144
+ if (!existsSync7(proxyPath)) {
5781
6145
  return void 0;
5782
6146
  }
5783
- const parentURL = pathToFileURL(path19.join(rootDir, "sidecar.config.ts")).href;
5784
- const tsconfigPath = path19.join(rootDir, "tsconfig.json");
5785
- const tsconfig = existsSync6(tsconfigPath) ? tsconfigPath : false;
5786
- const module = await tsImport(pathToFileURL(proxyPath).href, {
6147
+ const parentURL = pathToFileURL3(path20.join(rootDir, "sidecar.config.ts")).href;
6148
+ const tsconfigPath = path20.join(rootDir, "tsconfig.json");
6149
+ const tsconfig = existsSync7(tsconfigPath) ? tsconfigPath : false;
6150
+ const module = await tsImport2(pathToFileURL3(proxyPath).href, {
5787
6151
  parentURL,
5788
6152
  tsconfig
5789
6153
  });
5790
- const defaultExport = unwrapRuntimeDefault(module.default);
6154
+ const defaultExport = unwrapRuntimeDefault2(module.default);
5791
6155
  if (!isSidecarProxy(defaultExport)) {
5792
6156
  throw new Error("proxy.ts must default-export proxy({ ... }) from @sidecar-ai/server/proxy.");
5793
6157
  }
5794
6158
  return defaultExport;
5795
6159
  }
5796
6160
  async function loadRuntimeConfig(rootDir) {
5797
- const configPath = path19.join(rootDir, "sidecar.config.ts");
5798
- if (!existsSync6(configPath)) {
6161
+ const configPath = path20.join(rootDir, "sidecar.config.ts");
6162
+ if (!existsSync7(configPath)) {
5799
6163
  return void 0;
5800
6164
  }
5801
- const parentURL = pathToFileURL(configPath).href;
5802
- const tsconfigPath = path19.join(rootDir, "tsconfig.json");
5803
- const tsconfig = existsSync6(tsconfigPath) ? tsconfigPath : false;
5804
- const module = await tsImport(pathToFileURL(configPath).href, {
6165
+ const parentURL = pathToFileURL3(configPath).href;
6166
+ const tsconfigPath = path20.join(rootDir, "tsconfig.json");
6167
+ const tsconfig = existsSync7(tsconfigPath) ? tsconfigPath : false;
6168
+ const module = await tsImport2(pathToFileURL3(configPath).href, {
5805
6169
  parentURL,
5806
6170
  tsconfig
5807
6171
  });
5808
- const defaultExport = unwrapRuntimeDefault(module.default);
6172
+ const defaultExport = unwrapRuntimeDefault2(module.default);
5809
6173
  if (!defaultExport || typeof defaultExport !== "object") {
5810
6174
  throw new Error("sidecar.config.ts must default-export defineConfig({ ... }) from sidecar-ai.");
5811
6175
  }
5812
6176
  return defaultExport;
5813
6177
  }
5814
6178
  async function loadRuntimeTools(rootDir, entries) {
5815
- const parentURL = pathToFileURL(path19.join(rootDir, "sidecar.config.ts")).href;
5816
- const tsconfigPath = path19.join(rootDir, "tsconfig.json");
5817
- const tsconfig = existsSync6(tsconfigPath) ? tsconfigPath : false;
6179
+ const parentURL = pathToFileURL3(path20.join(rootDir, "sidecar.config.ts")).href;
6180
+ const tsconfigPath = path20.join(rootDir, "tsconfig.json");
6181
+ const tsconfig = existsSync7(tsconfigPath) ? tsconfigPath : false;
5818
6182
  const loaded = [];
5819
6183
  for (const entry of entries) {
5820
- const sourcePath = path19.join(rootDir, entry.sourceFile);
5821
- const module = await tsImport(pathToFileURL(sourcePath).href, {
6184
+ const sourcePath = path20.join(rootDir, entry.sourceFile);
6185
+ const module = await tsImport2(pathToFileURL3(sourcePath).href, {
5822
6186
  parentURL,
5823
6187
  tsconfig
5824
6188
  });
5825
- const defaultExport = unwrapRuntimeDefault(module.default);
6189
+ const defaultExport = unwrapRuntimeDefault2(module.default);
5826
6190
  if (!isSidecarTool(defaultExport)) {
5827
6191
  throw new Error(`${entry.sourceFile} did not default-export a Sidecar tool.`);
5828
6192
  }
@@ -5849,7 +6213,7 @@ async function loadResources(rootDir, outDir, manifest) {
5849
6213
  if (!entry.widget?.outputFile) {
5850
6214
  continue;
5851
6215
  }
5852
- const text = await readFile8(path19.join(rootDir, outDir, entry.widget.outputFile), "utf8");
6216
+ const text = await readFile8(path20.join(rootDir, outDir, entry.widget.outputFile), "utf8");
5853
6217
  resources.push({
5854
6218
  uri: entry.widget.resourceUri,
5855
6219
  name: entry.name,
@@ -5859,16 +6223,16 @@ async function loadResources(rootDir, outDir, manifest) {
5859
6223
  _meta: entry.widget.resourceMeta
5860
6224
  });
5861
6225
  }
5862
- const parentURL = pathToFileURL(path19.join(rootDir, "sidecar.config.ts")).href;
5863
- const tsconfigPath = path19.join(rootDir, "tsconfig.json");
5864
- const tsconfig = existsSync6(tsconfigPath) ? tsconfigPath : false;
6226
+ const parentURL = pathToFileURL3(path20.join(rootDir, "sidecar.config.ts")).href;
6227
+ const tsconfigPath = path20.join(rootDir, "tsconfig.json");
6228
+ const tsconfig = existsSync7(tsconfigPath) ? tsconfigPath : false;
5865
6229
  for (const entry of manifest.resources) {
5866
- const sourcePath = path19.join(rootDir, entry.sourceFile);
5867
- const module = await tsImport(pathToFileURL(sourcePath).href, {
6230
+ const sourcePath = path20.join(rootDir, entry.sourceFile);
6231
+ const module = await tsImport2(pathToFileURL3(sourcePath).href, {
5868
6232
  parentURL,
5869
6233
  tsconfig
5870
6234
  });
5871
- const defaultExport = unwrapRuntimeDefault(module.default);
6235
+ const defaultExport = unwrapRuntimeDefault2(module.default);
5872
6236
  if (!isSidecarResource(defaultExport)) {
5873
6237
  throw new Error(`${entry.sourceFile} did not default-export a Sidecar resource.`);
5874
6238
  }
@@ -5881,17 +6245,17 @@ async function loadResources(rootDir, outDir, manifest) {
5881
6245
  return resources;
5882
6246
  }
5883
6247
  async function loadRuntimePrompts(rootDir, manifest) {
5884
- const parentURL = pathToFileURL(path19.join(rootDir, "sidecar.config.ts")).href;
5885
- const tsconfigPath = path19.join(rootDir, "tsconfig.json");
5886
- const tsconfig = existsSync6(tsconfigPath) ? tsconfigPath : false;
6248
+ const parentURL = pathToFileURL3(path20.join(rootDir, "sidecar.config.ts")).href;
6249
+ const tsconfigPath = path20.join(rootDir, "tsconfig.json");
6250
+ const tsconfig = existsSync7(tsconfigPath) ? tsconfigPath : false;
5887
6251
  const loaded = [];
5888
6252
  for (const entry of manifest.prompts) {
5889
- const sourcePath = path19.join(rootDir, entry.sourceFile);
5890
- const module = await tsImport(pathToFileURL(sourcePath).href, {
6253
+ const sourcePath = path20.join(rootDir, entry.sourceFile);
6254
+ const module = await tsImport2(pathToFileURL3(sourcePath).href, {
5891
6255
  parentURL,
5892
6256
  tsconfig
5893
6257
  });
5894
- const defaultExport = unwrapRuntimeDefault(module.default);
6258
+ const defaultExport = unwrapRuntimeDefault2(module.default);
5895
6259
  if (!isSidecarPrompt(defaultExport)) {
5896
6260
  throw new Error(`${entry.sourceFile} did not default-export a Sidecar prompt.`);
5897
6261
  }
@@ -5902,9 +6266,9 @@ async function loadRuntimePrompts(rootDir, manifest) {
5902
6266
  }
5903
6267
  return loaded;
5904
6268
  }
5905
- function unwrapRuntimeDefault(value) {
5906
- if (value && typeof value === "object" && "default" in value && Object.keys(value).length === 1) {
5907
- return unwrapRuntimeDefault(value.default);
6269
+ function unwrapRuntimeDefault2(value) {
6270
+ if (value && typeof value === "object" && "default" in value && Object.keys(value).every((key) => key === "default" || key === "__esModule")) {
6271
+ return unwrapRuntimeDefault2(value.default);
5908
6272
  }
5909
6273
  return value;
5910
6274
  }
@@ -5938,7 +6302,7 @@ function isDirectRun() {
5938
6302
  return false;
5939
6303
  }
5940
6304
  const entryPath = realpathSync.native(entry);
5941
- return import.meta.url === pathToFileURL(entryPath).href;
6305
+ return import.meta.url === pathToFileURL3(entryPath).href;
5942
6306
  }
5943
6307
  if (isDirectRun()) {
5944
6308
  main(process.argv).catch((error) => {