@sidecar-ai/cli 0.1.0-alpha.6 → 0.1.0-alpha.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +659 -370
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
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
|
|
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
|
|
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
|
|
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(
|
|
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
|
|
898
|
+
import { existsSync as existsSync3 } from "fs";
|
|
870
899
|
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
871
|
-
import
|
|
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 =
|
|
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 =
|
|
921
|
+
const sourceFile = path4.join(rootDir, entry.widget.sourceFile);
|
|
891
922
|
const safeId = safePathSegment(entry.id);
|
|
892
|
-
const entryFile =
|
|
893
|
-
const importPath = toImportSpecifier(
|
|
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(
|
|
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
|
|
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
|
-
|
|
918
|
-
|
|
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
|
|
926
|
-
const
|
|
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 =
|
|
930
|
-
const outputFile =
|
|
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 =
|
|
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 =
|
|
946
|
-
if (!
|
|
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":
|
|
951
|
-
"@sidecar-ai/client":
|
|
952
|
-
"@sidecar-ai/core":
|
|
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":
|
|
955
|
-
"@sidecar-ai/native/components":
|
|
956
|
-
"@sidecar-ai/native/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 =
|
|
1120
|
+
let current = path4.resolve(startDir);
|
|
961
1121
|
while (true) {
|
|
962
|
-
if (
|
|
1122
|
+
if (existsSync3(path4.join(current, "packages", "core", "src", "index.ts"))) {
|
|
963
1123
|
return current;
|
|
964
1124
|
}
|
|
965
|
-
const parent =
|
|
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 =
|
|
974
|
-
if (!
|
|
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 =
|
|
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:
|
|
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(
|
|
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:
|
|
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 =
|
|
1194
|
-
return
|
|
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 =
|
|
1198
|
-
return
|
|
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 =
|
|
1203
|
-
if (
|
|
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(
|
|
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
|
-
|
|
1261
|
-
|
|
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 =
|
|
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 =
|
|
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:
|
|
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 =
|
|
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 =
|
|
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(
|
|
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 =
|
|
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 =
|
|
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
|
|
1870
|
+
import path19 from "path";
|
|
1669
1871
|
|
|
1670
1872
|
// packages/compiler/src/config.ts
|
|
1671
|
-
import
|
|
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 =
|
|
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
|
-
|
|
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
|
|
2072
|
+
import { existsSync as existsSync4 } from "fs";
|
|
1793
2073
|
import { readFile as readFile2 } from "fs/promises";
|
|
1794
|
-
import
|
|
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 =
|
|
2081
|
+
const hasAuthConfig = existsSync4(path7.join(rootDir, "auth.ts"));
|
|
1802
2082
|
for (const entry of tools) {
|
|
1803
|
-
const toolPath =
|
|
2083
|
+
const toolPath = path7.join(rootDir, entry.sourceFile);
|
|
1804
2084
|
const toolSource = await readFile2(toolPath, "utf8");
|
|
1805
|
-
diagnostics.push(...diagnoseToolSource(
|
|
2085
|
+
diagnostics.push(...diagnoseToolSource(entry, toolSource, hasAuthConfig));
|
|
1806
2086
|
if (entry.widget) {
|
|
1807
|
-
const widgetPath =
|
|
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 =
|
|
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 =
|
|
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(
|
|
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
|
|
2330
|
+
import path8 from "path";
|
|
2051
2331
|
async function writeGeneratedTypes(rootDir, tools) {
|
|
2052
|
-
const generatedDir =
|
|
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,
|
|
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
|
-
(
|
|
2341
|
+
(_entry, index) => ` ${methodNames[index]}(params: ToolParams<typeof tool${index}>): Promise<ToolOutput<typeof tool${index}>>;`
|
|
2062
2342
|
).join("\n");
|
|
2063
2343
|
await writeFile2(
|
|
2064
|
-
|
|
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
|
|
2394
|
+
import path9 from "path";
|
|
2115
2395
|
async function loadProjectIdentity(rootDir) {
|
|
2116
|
-
const packageJson = await readOptionalJson(
|
|
2396
|
+
const packageJson = await readOptionalJson(path9.join(rootDir, "package.json"));
|
|
2117
2397
|
const configText = await readOptionalText(
|
|
2118
|
-
|
|
2398
|
+
path9.join(rootDir, "sidecar.config.ts")
|
|
2119
2399
|
);
|
|
2120
|
-
const name = readConfigString(configText, "name") ?? packageJson?.name ??
|
|
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
|
|
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
|
|
2438
|
+
import path10 from "path";
|
|
2159
2439
|
async function emitClaudeAgents(rootDir, destination) {
|
|
2160
|
-
const source =
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
2488
|
+
import path11 from "path";
|
|
2209
2489
|
async function copyCommands(rootDir, destination) {
|
|
2210
|
-
const source =
|
|
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 =
|
|
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,
|
|
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 =
|
|
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(
|
|
2512
|
+
await writeFile4(path11.join(destination, `${safeFileStem(commandName)}.md`), markdown);
|
|
2233
2513
|
continue;
|
|
2234
2514
|
}
|
|
2235
|
-
await cp(sourcePath,
|
|
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 =
|
|
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
|
|
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 =
|
|
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(
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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:
|
|
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:
|
|
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 =
|
|
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
|
|
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
|
|
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 =
|
|
2759
|
+
const source = path13.join(rootDir, directory);
|
|
2480
2760
|
if (!existsSyncSafe(source)) {
|
|
2481
2761
|
continue;
|
|
2482
2762
|
}
|
|
2483
|
-
await cp2(source,
|
|
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 =
|
|
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
|
|
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
|
|
2781
|
+
import path14 from "path";
|
|
2502
2782
|
async function copySkills(rootDir, destination) {
|
|
2503
|
-
const source =
|
|
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 =
|
|
2514
|
-
const destinationDir =
|
|
2515
|
-
const staticSkill =
|
|
2516
|
-
const dynamicSkill =
|
|
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 (
|
|
2798
|
+
if (existsSync5(staticSkill)) {
|
|
2519
2799
|
await cp3(sourceDir, destinationDir, {
|
|
2520
2800
|
recursive: true,
|
|
2521
|
-
filter: async (sourcePath) => !sourcePath.endsWith(`${
|
|
2801
|
+
filter: async (sourcePath) => !sourcePath.endsWith(`${path14.sep}skill.ts`) && await safeSkillCopyFilter(sourcePath)
|
|
2522
2802
|
});
|
|
2523
|
-
} else if (
|
|
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(
|
|
2808
|
+
await writeFile6(path14.join(destinationDir, "SKILL.md"), generated);
|
|
2529
2809
|
}
|
|
2530
2810
|
}
|
|
2531
2811
|
}
|
|
2532
2812
|
async function safeSkillCopyFilter(sourcePath) {
|
|
2533
|
-
const basename =
|
|
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 =
|
|
2560
|
-
await mkdir7(
|
|
2561
|
-
await copySkills(rootDir,
|
|
2562
|
-
await copyCommands(rootDir,
|
|
2563
|
-
await copyHooks(rootDir,
|
|
2564
|
-
await emitClaudeAgents(rootDir,
|
|
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(
|
|
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(
|
|
2853
|
+
await writeJson(path15.join(pluginDir, "version.json"), {
|
|
2574
2854
|
version: identity.version,
|
|
2575
2855
|
generatedBy: "sidecar"
|
|
2576
2856
|
});
|
|
2577
|
-
await writeJson(
|
|
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(
|
|
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
|
-
|
|
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(
|
|
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
|
|
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(
|
|
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 =
|
|
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:
|
|
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 =
|
|
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:
|
|
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
|
|
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
|
|
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(
|
|
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 =
|
|
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:
|
|
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 =
|
|
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 =
|
|
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:
|
|
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
|
|
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
|
|
3292
|
+
import { existsSync as existsSync6 } from "fs";
|
|
3013
3293
|
import { mkdir as mkdir8, rm, writeFile as writeFile8 } from "fs/promises";
|
|
3014
|
-
import
|
|
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 =
|
|
3301
|
+
const cacheDir = path18.join(rootDir, ".sidecar", "cache", "server");
|
|
3022
3302
|
await mkdir8(cacheDir, { recursive: true });
|
|
3023
|
-
const entryFile =
|
|
3303
|
+
const entryFile = path18.join(cacheDir, "index.ts");
|
|
3024
3304
|
await writeFile8(entryFile, renderServerEntry(rootDir, entryFile, manifest, identity));
|
|
3025
|
-
const serverFile =
|
|
3026
|
-
await mkdir8(
|
|
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
|
-
|
|
3041
|
-
|
|
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(
|
|
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(
|
|
3052
|
-
await rm(
|
|
3053
|
-
await writeFile8(
|
|
3054
|
-
await writeFile8(
|
|
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(
|
|
3336
|
+
await writeFile8(path18.join(vercelOutputDir, "config.json"), renderVercelOutputConfig());
|
|
3057
3337
|
} else {
|
|
3058
|
-
await rm(
|
|
3059
|
-
await rm(
|
|
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 =
|
|
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,
|
|
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,
|
|
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,
|
|
3362
|
+
(entry, index) => `import prompt${index} from ${JSON.stringify(toImportSpecifier(entryDir, path18.join(rootDir, entry.sourceFile)))};`
|
|
3083
3363
|
),
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
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).
|
|
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":
|
|
3290
|
-
"@sidecar-ai/auth":
|
|
3291
|
-
"@sidecar-ai/core":
|
|
3292
|
-
"@sidecar-ai/server":
|
|
3293
|
-
"@sidecar-ai/server/proxy":
|
|
3294
|
-
"@sidecar-ai/client":
|
|
3295
|
-
"@sidecar-ai/react":
|
|
3296
|
-
"@sidecar-ai/native":
|
|
3297
|
-
"@sidecar-ai/native/components":
|
|
3298
|
-
"@sidecar-ai/openai":
|
|
3299
|
-
"@sidecar-ai/openai/components":
|
|
3300
|
-
"@sidecar-ai/openai/official":
|
|
3301
|
-
"@sidecar-ai/anthropic":
|
|
3302
|
-
"@sidecar-ai/anthropic/agent":
|
|
3303
|
-
"@sidecar-ai/anthropic/command":
|
|
3304
|
-
"@sidecar-ai/anthropic/components":
|
|
3305
|
-
"@sidecar-ai/anthropic/hooks":
|
|
3306
|
-
"@sidecar-ai/anthropic/mcp":
|
|
3307
|
-
"@sidecar-ai/anthropic/plugin":
|
|
3308
|
-
"@sidecar-ai/anthropic/skill":
|
|
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 =
|
|
3592
|
+
let current = path18.resolve(startDir);
|
|
3313
3593
|
while (true) {
|
|
3314
|
-
if (
|
|
3594
|
+
if (existsSync6(path18.join(current, "packages", "core", "src", "index.ts"))) {
|
|
3315
3595
|
return current;
|
|
3316
3596
|
}
|
|
3317
|
-
const parent =
|
|
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 =
|
|
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
|
-
|
|
3645
|
+
path19.join(runtimeOutDir, "manifest.sidecar.json"),
|
|
3366
3646
|
`${JSON.stringify(manifest, null, 2)}
|
|
3367
3647
|
`
|
|
3368
3648
|
);
|
|
3369
|
-
await writeFile9(
|
|
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
|
|
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
|
|
3673
|
+
return path19.join(rootDir, "out");
|
|
3394
3674
|
}
|
|
3395
|
-
return
|
|
3675
|
+
return path19.dirname(outDir);
|
|
3396
3676
|
}
|
|
3397
3677
|
function isVercelBuildOutputDir(outDir) {
|
|
3398
|
-
return
|
|
3678
|
+
return path19.basename(outDir) === "output" && path19.basename(path19.dirname(outDir)) === ".vercel";
|
|
3399
3679
|
}
|
|
3400
3680
|
function resolveInsideRoot(rootDir, output) {
|
|
3401
|
-
const resolved =
|
|
3402
|
-
const relative =
|
|
3403
|
-
if (relative.startsWith("..") ||
|
|
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;
|
|
@@ -4551,44 +4831,44 @@ function validateAgainstSchema(schema, value, message, options = {}) {
|
|
|
4551
4831
|
}
|
|
4552
4832
|
return value;
|
|
4553
4833
|
}
|
|
4554
|
-
function schemaFailure(schema, value,
|
|
4555
|
-
if (schema.anyOf?.length && !schema.anyOf.some((entry) => !schemaFailure(entry, value,
|
|
4556
|
-
return `${
|
|
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.`;
|
|
4557
4837
|
}
|
|
4558
|
-
if (schema.oneOf?.length && schema.oneOf.filter((entry) => !schemaFailure(entry, value,
|
|
4559
|
-
return `${
|
|
4838
|
+
if (schema.oneOf?.length && schema.oneOf.filter((entry) => !schemaFailure(entry, value, path21)).length !== 1) {
|
|
4839
|
+
return `${path21} must match exactly one oneOf schema.`;
|
|
4560
4840
|
}
|
|
4561
4841
|
if (schema.allOf?.length) {
|
|
4562
4842
|
for (const entry of schema.allOf) {
|
|
4563
|
-
const failure = schemaFailure(entry, value,
|
|
4843
|
+
const failure = schemaFailure(entry, value, path21);
|
|
4564
4844
|
if (failure) return failure;
|
|
4565
4845
|
}
|
|
4566
4846
|
}
|
|
4567
4847
|
if (schema.const !== void 0 && value !== schema.const) {
|
|
4568
|
-
return `${
|
|
4848
|
+
return `${path21} must equal ${JSON.stringify(schema.const)}.`;
|
|
4569
4849
|
}
|
|
4570
4850
|
if (schema.enum && !schema.enum.some((entry) => JSON.stringify(entry) === JSON.stringify(value))) {
|
|
4571
|
-
return `${
|
|
4851
|
+
return `${path21} must be one of the declared enum values.`;
|
|
4572
4852
|
}
|
|
4573
4853
|
if (schema.type) {
|
|
4574
4854
|
const types = Array.isArray(schema.type) ? schema.type : [schema.type];
|
|
4575
4855
|
if (!types.some((type) => matchesJsonSchemaType(type, value))) {
|
|
4576
|
-
return `${
|
|
4856
|
+
return `${path21} must be ${types.join(" or ")}.`;
|
|
4577
4857
|
}
|
|
4578
4858
|
}
|
|
4579
4859
|
if (schema.type === "object" || schema.properties || schema.required) {
|
|
4580
4860
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
4581
|
-
return `${
|
|
4861
|
+
return `${path21} must be an object.`;
|
|
4582
4862
|
}
|
|
4583
4863
|
const record = value;
|
|
4584
4864
|
for (const required of schema.required ?? []) {
|
|
4585
4865
|
if (!(required in record)) {
|
|
4586
|
-
return `${
|
|
4866
|
+
return `${path21}.${required} is required.`;
|
|
4587
4867
|
}
|
|
4588
4868
|
}
|
|
4589
4869
|
for (const [key, propertySchema] of Object.entries(schema.properties ?? {})) {
|
|
4590
4870
|
if (key in record) {
|
|
4591
|
-
const failure = schemaFailure(propertySchema, record[key], `${
|
|
4871
|
+
const failure = schemaFailure(propertySchema, record[key], `${path21}.${key}`);
|
|
4592
4872
|
if (failure) return failure;
|
|
4593
4873
|
}
|
|
4594
4874
|
}
|
|
@@ -4596,12 +4876,12 @@ function schemaFailure(schema, value, path20) {
|
|
|
4596
4876
|
if (schema.additionalProperties === false) {
|
|
4597
4877
|
const extra = Object.keys(record).find((key) => !allowed.has(key));
|
|
4598
4878
|
if (extra) {
|
|
4599
|
-
return `${
|
|
4879
|
+
return `${path21}.${extra} is not allowed.`;
|
|
4600
4880
|
}
|
|
4601
4881
|
} else if (schema.additionalProperties && typeof schema.additionalProperties === "object") {
|
|
4602
4882
|
for (const [key, entry] of Object.entries(record)) {
|
|
4603
4883
|
if (!allowed.has(key)) {
|
|
4604
|
-
const failure = schemaFailure(schema.additionalProperties, entry, `${
|
|
4884
|
+
const failure = schemaFailure(schema.additionalProperties, entry, `${path21}.${key}`);
|
|
4605
4885
|
if (failure) return failure;
|
|
4606
4886
|
}
|
|
4607
4887
|
}
|
|
@@ -4609,29 +4889,38 @@ function schemaFailure(schema, value, path20) {
|
|
|
4609
4889
|
}
|
|
4610
4890
|
if (schema.type === "array" || schema.items) {
|
|
4611
4891
|
if (!Array.isArray(value)) {
|
|
4612
|
-
return `${
|
|
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.`;
|
|
4613
4899
|
}
|
|
4614
4900
|
if (schema.items) {
|
|
4615
4901
|
for (const [index, entry] of value.entries()) {
|
|
4616
|
-
const failure = schemaFailure(schema.items, entry, `${
|
|
4902
|
+
const failure = schemaFailure(schema.items, entry, `${path21}[${index}]`);
|
|
4617
4903
|
if (failure) return failure;
|
|
4618
4904
|
}
|
|
4619
4905
|
}
|
|
4620
4906
|
}
|
|
4621
4907
|
if (typeof value === "string") {
|
|
4622
4908
|
if (schema.minLength !== void 0 && value.length < schema.minLength) {
|
|
4623
|
-
return `${
|
|
4909
|
+
return `${path21} is shorter than ${schema.minLength}.`;
|
|
4624
4910
|
}
|
|
4625
4911
|
if (schema.maxLength !== void 0 && value.length > schema.maxLength) {
|
|
4626
|
-
return `${
|
|
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}.`;
|
|
4627
4916
|
}
|
|
4628
4917
|
}
|
|
4629
4918
|
if (typeof value === "number") {
|
|
4630
4919
|
if (schema.minimum !== void 0 && value < schema.minimum) {
|
|
4631
|
-
return `${
|
|
4920
|
+
return `${path21} is less than ${schema.minimum}.`;
|
|
4632
4921
|
}
|
|
4633
4922
|
if (schema.maximum !== void 0 && value > schema.maximum) {
|
|
4634
|
-
return `${
|
|
4923
|
+
return `${path21} is greater than ${schema.maximum}.`;
|
|
4635
4924
|
}
|
|
4636
4925
|
}
|
|
4637
4926
|
return void 0;
|
|
@@ -4809,11 +5098,11 @@ import { stdin, stdout } from "process";
|
|
|
4809
5098
|
async function startTunnel(options) {
|
|
4810
5099
|
const provider = await resolveProvider(options.provider);
|
|
4811
5100
|
const localUrl = `http://127.0.0.1:${options.port}`;
|
|
4812
|
-
const
|
|
5101
|
+
const path21 = options.path ?? "/mcp";
|
|
4813
5102
|
if (provider === "cloudflared") {
|
|
4814
|
-
return startCloudflared(localUrl,
|
|
5103
|
+
return startCloudflared(localUrl, path21, options.timeoutMs);
|
|
4815
5104
|
}
|
|
4816
|
-
return startWrangler(localUrl,
|
|
5105
|
+
return startWrangler(localUrl, path21, options.timeoutMs);
|
|
4817
5106
|
}
|
|
4818
5107
|
async function validateTunnelEndpoint(options) {
|
|
4819
5108
|
const timeoutMs = options.timeoutMs ?? 1e4;
|
|
@@ -4937,7 +5226,7 @@ function assertNpxAvailable() {
|
|
|
4937
5226
|
throw new Error(tunnelInstallMessage("wrangler"));
|
|
4938
5227
|
}
|
|
4939
5228
|
}
|
|
4940
|
-
async function startCloudflared(localUrl,
|
|
5229
|
+
async function startCloudflared(localUrl, path21, timeoutMs = 2e4) {
|
|
4941
5230
|
const child = spawn("cloudflared", ["tunnel", "--url", localUrl, "--no-autoupdate"], {
|
|
4942
5231
|
stdio: ["ignore", "pipe", "pipe"]
|
|
4943
5232
|
});
|
|
@@ -4945,13 +5234,13 @@ async function startCloudflared(localUrl, path20, timeoutMs = 2e4) {
|
|
|
4945
5234
|
return {
|
|
4946
5235
|
provider: "cloudflared",
|
|
4947
5236
|
publicUrl,
|
|
4948
|
-
mcpUrl: appendPath(publicUrl,
|
|
5237
|
+
mcpUrl: appendPath(publicUrl, path21),
|
|
4949
5238
|
close() {
|
|
4950
5239
|
child.kill("SIGTERM");
|
|
4951
5240
|
}
|
|
4952
5241
|
};
|
|
4953
5242
|
}
|
|
4954
|
-
async function startWrangler(localUrl,
|
|
5243
|
+
async function startWrangler(localUrl, path21, timeoutMs = 2e4) {
|
|
4955
5244
|
const child = spawn("npx", ["--yes", "wrangler", "tunnel", "quick-start", localUrl], {
|
|
4956
5245
|
stdio: ["ignore", "pipe", "pipe"]
|
|
4957
5246
|
});
|
|
@@ -4959,7 +5248,7 @@ async function startWrangler(localUrl, path20, timeoutMs = 2e4) {
|
|
|
4959
5248
|
return {
|
|
4960
5249
|
provider: "wrangler",
|
|
4961
5250
|
publicUrl,
|
|
4962
|
-
mcpUrl: appendPath(publicUrl,
|
|
5251
|
+
mcpUrl: appendPath(publicUrl, path21),
|
|
4963
5252
|
close() {
|
|
4964
5253
|
child.kill("SIGTERM");
|
|
4965
5254
|
}
|
|
@@ -5220,8 +5509,8 @@ function runInherited(command, args) {
|
|
|
5220
5509
|
});
|
|
5221
5510
|
});
|
|
5222
5511
|
}
|
|
5223
|
-
function appendPath(origin,
|
|
5224
|
-
return `${origin.replace(/\/+$/, "")}/${
|
|
5512
|
+
function appendPath(origin, path21) {
|
|
5513
|
+
return `${origin.replace(/\/+$/, "")}/${path21.replace(/^\/+/, "")}`;
|
|
5225
5514
|
}
|
|
5226
5515
|
function isRecord3(value) {
|
|
5227
5516
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
@@ -5249,9 +5538,9 @@ async function main(argv) {
|
|
|
5249
5538
|
);
|
|
5250
5539
|
console.log(`Host runtime: ${manifest.host}`);
|
|
5251
5540
|
if (manifest.host === "vercel") {
|
|
5252
|
-
console.log(`Vercel MCP function: ${
|
|
5541
|
+
console.log(`Vercel MCP function: ${path20.join(resolvedOutDir, VERCEL_ENTRYPOINT)}`);
|
|
5253
5542
|
} else {
|
|
5254
|
-
console.log(`Hostable MCP server: ${
|
|
5543
|
+
console.log(`Hostable MCP server: ${path20.join(resolvedOutDir, SERVER_ENTRYPOINT)}`);
|
|
5255
5544
|
}
|
|
5256
5545
|
if (plugins ?? manifest.config.build.plugins) {
|
|
5257
5546
|
console.log("Built claude-plugin package.");
|
|
@@ -5437,8 +5726,8 @@ function readOptionalPlugins(argv) {
|
|
|
5437
5726
|
return void 0;
|
|
5438
5727
|
}
|
|
5439
5728
|
async function previewComponents(options) {
|
|
5440
|
-
const cliDir =
|
|
5441
|
-
const css = await readFile8(
|
|
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(() => "");
|
|
5442
5731
|
const html = renderComponentPreviewHtml(
|
|
5443
5732
|
options.host,
|
|
5444
5733
|
options.compare,
|
|
@@ -5478,10 +5767,10 @@ async function previewComponents(options) {
|
|
|
5478
5767
|
server.close();
|
|
5479
5768
|
}
|
|
5480
5769
|
async function writeComponentApproval(rootDir, approval) {
|
|
5481
|
-
const dir =
|
|
5770
|
+
const dir = path20.join(rootDir, ".sidecar", "approvals");
|
|
5482
5771
|
await mkdir10(dir, { recursive: true });
|
|
5483
5772
|
await writeFile10(
|
|
5484
|
-
|
|
5773
|
+
path20.join(dir, `components.${approval.host}.json`),
|
|
5485
5774
|
`${JSON.stringify(approval, null, 2)}
|
|
5486
5775
|
`
|
|
5487
5776
|
);
|
|
@@ -5833,71 +6122,71 @@ function printDiagnostics(diagnostics) {
|
|
|
5833
6122
|
}
|
|
5834
6123
|
}
|
|
5835
6124
|
async function loadRuntimeAuth(rootDir) {
|
|
5836
|
-
const authPath =
|
|
5837
|
-
if (!
|
|
6125
|
+
const authPath = path20.join(rootDir, "auth.ts");
|
|
6126
|
+
if (!existsSync7(authPath)) {
|
|
5838
6127
|
return void 0;
|
|
5839
6128
|
}
|
|
5840
|
-
const parentURL =
|
|
5841
|
-
const tsconfigPath =
|
|
5842
|
-
const tsconfig =
|
|
5843
|
-
const module = await
|
|
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, {
|
|
5844
6133
|
parentURL,
|
|
5845
6134
|
tsconfig
|
|
5846
6135
|
});
|
|
5847
|
-
const defaultExport =
|
|
6136
|
+
const defaultExport = unwrapRuntimeDefault2(module.default);
|
|
5848
6137
|
if (!isSidecarAuth(defaultExport)) {
|
|
5849
6138
|
throw new Error("auth.ts must default-export auth({ ... }) from sidecar-ai.");
|
|
5850
6139
|
}
|
|
5851
6140
|
return defaultExport;
|
|
5852
6141
|
}
|
|
5853
6142
|
async function loadRuntimeProxy(rootDir) {
|
|
5854
|
-
const proxyPath =
|
|
5855
|
-
if (!
|
|
6143
|
+
const proxyPath = path20.join(rootDir, "proxy.ts");
|
|
6144
|
+
if (!existsSync7(proxyPath)) {
|
|
5856
6145
|
return void 0;
|
|
5857
6146
|
}
|
|
5858
|
-
const parentURL =
|
|
5859
|
-
const tsconfigPath =
|
|
5860
|
-
const tsconfig =
|
|
5861
|
-
const module = await
|
|
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, {
|
|
5862
6151
|
parentURL,
|
|
5863
6152
|
tsconfig
|
|
5864
6153
|
});
|
|
5865
|
-
const defaultExport =
|
|
6154
|
+
const defaultExport = unwrapRuntimeDefault2(module.default);
|
|
5866
6155
|
if (!isSidecarProxy(defaultExport)) {
|
|
5867
6156
|
throw new Error("proxy.ts must default-export proxy({ ... }) from @sidecar-ai/server/proxy.");
|
|
5868
6157
|
}
|
|
5869
6158
|
return defaultExport;
|
|
5870
6159
|
}
|
|
5871
6160
|
async function loadRuntimeConfig(rootDir) {
|
|
5872
|
-
const configPath =
|
|
5873
|
-
if (!
|
|
6161
|
+
const configPath = path20.join(rootDir, "sidecar.config.ts");
|
|
6162
|
+
if (!existsSync7(configPath)) {
|
|
5874
6163
|
return void 0;
|
|
5875
6164
|
}
|
|
5876
|
-
const parentURL =
|
|
5877
|
-
const tsconfigPath =
|
|
5878
|
-
const tsconfig =
|
|
5879
|
-
const module = await
|
|
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, {
|
|
5880
6169
|
parentURL,
|
|
5881
6170
|
tsconfig
|
|
5882
6171
|
});
|
|
5883
|
-
const defaultExport =
|
|
6172
|
+
const defaultExport = unwrapRuntimeDefault2(module.default);
|
|
5884
6173
|
if (!defaultExport || typeof defaultExport !== "object") {
|
|
5885
6174
|
throw new Error("sidecar.config.ts must default-export defineConfig({ ... }) from sidecar-ai.");
|
|
5886
6175
|
}
|
|
5887
6176
|
return defaultExport;
|
|
5888
6177
|
}
|
|
5889
6178
|
async function loadRuntimeTools(rootDir, entries) {
|
|
5890
|
-
const parentURL =
|
|
5891
|
-
const tsconfigPath =
|
|
5892
|
-
const tsconfig =
|
|
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;
|
|
5893
6182
|
const loaded = [];
|
|
5894
6183
|
for (const entry of entries) {
|
|
5895
|
-
const sourcePath =
|
|
5896
|
-
const module = await
|
|
6184
|
+
const sourcePath = path20.join(rootDir, entry.sourceFile);
|
|
6185
|
+
const module = await tsImport2(pathToFileURL3(sourcePath).href, {
|
|
5897
6186
|
parentURL,
|
|
5898
6187
|
tsconfig
|
|
5899
6188
|
});
|
|
5900
|
-
const defaultExport =
|
|
6189
|
+
const defaultExport = unwrapRuntimeDefault2(module.default);
|
|
5901
6190
|
if (!isSidecarTool(defaultExport)) {
|
|
5902
6191
|
throw new Error(`${entry.sourceFile} did not default-export a Sidecar tool.`);
|
|
5903
6192
|
}
|
|
@@ -5924,7 +6213,7 @@ async function loadResources(rootDir, outDir, manifest) {
|
|
|
5924
6213
|
if (!entry.widget?.outputFile) {
|
|
5925
6214
|
continue;
|
|
5926
6215
|
}
|
|
5927
|
-
const text = await readFile8(
|
|
6216
|
+
const text = await readFile8(path20.join(rootDir, outDir, entry.widget.outputFile), "utf8");
|
|
5928
6217
|
resources.push({
|
|
5929
6218
|
uri: entry.widget.resourceUri,
|
|
5930
6219
|
name: entry.name,
|
|
@@ -5934,16 +6223,16 @@ async function loadResources(rootDir, outDir, manifest) {
|
|
|
5934
6223
|
_meta: entry.widget.resourceMeta
|
|
5935
6224
|
});
|
|
5936
6225
|
}
|
|
5937
|
-
const parentURL =
|
|
5938
|
-
const tsconfigPath =
|
|
5939
|
-
const tsconfig =
|
|
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;
|
|
5940
6229
|
for (const entry of manifest.resources) {
|
|
5941
|
-
const sourcePath =
|
|
5942
|
-
const module = await
|
|
6230
|
+
const sourcePath = path20.join(rootDir, entry.sourceFile);
|
|
6231
|
+
const module = await tsImport2(pathToFileURL3(sourcePath).href, {
|
|
5943
6232
|
parentURL,
|
|
5944
6233
|
tsconfig
|
|
5945
6234
|
});
|
|
5946
|
-
const defaultExport =
|
|
6235
|
+
const defaultExport = unwrapRuntimeDefault2(module.default);
|
|
5947
6236
|
if (!isSidecarResource(defaultExport)) {
|
|
5948
6237
|
throw new Error(`${entry.sourceFile} did not default-export a Sidecar resource.`);
|
|
5949
6238
|
}
|
|
@@ -5956,17 +6245,17 @@ async function loadResources(rootDir, outDir, manifest) {
|
|
|
5956
6245
|
return resources;
|
|
5957
6246
|
}
|
|
5958
6247
|
async function loadRuntimePrompts(rootDir, manifest) {
|
|
5959
|
-
const parentURL =
|
|
5960
|
-
const tsconfigPath =
|
|
5961
|
-
const tsconfig =
|
|
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;
|
|
5962
6251
|
const loaded = [];
|
|
5963
6252
|
for (const entry of manifest.prompts) {
|
|
5964
|
-
const sourcePath =
|
|
5965
|
-
const module = await
|
|
6253
|
+
const sourcePath = path20.join(rootDir, entry.sourceFile);
|
|
6254
|
+
const module = await tsImport2(pathToFileURL3(sourcePath).href, {
|
|
5966
6255
|
parentURL,
|
|
5967
6256
|
tsconfig
|
|
5968
6257
|
});
|
|
5969
|
-
const defaultExport =
|
|
6258
|
+
const defaultExport = unwrapRuntimeDefault2(module.default);
|
|
5970
6259
|
if (!isSidecarPrompt(defaultExport)) {
|
|
5971
6260
|
throw new Error(`${entry.sourceFile} did not default-export a Sidecar prompt.`);
|
|
5972
6261
|
}
|
|
@@ -5977,9 +6266,9 @@ async function loadRuntimePrompts(rootDir, manifest) {
|
|
|
5977
6266
|
}
|
|
5978
6267
|
return loaded;
|
|
5979
6268
|
}
|
|
5980
|
-
function
|
|
5981
|
-
if (value && typeof value === "object" && "default" in value && Object.keys(value).
|
|
5982
|
-
return
|
|
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);
|
|
5983
6272
|
}
|
|
5984
6273
|
return value;
|
|
5985
6274
|
}
|
|
@@ -6013,7 +6302,7 @@ function isDirectRun() {
|
|
|
6013
6302
|
return false;
|
|
6014
6303
|
}
|
|
6015
6304
|
const entryPath = realpathSync.native(entry);
|
|
6016
|
-
return import.meta.url ===
|
|
6305
|
+
return import.meta.url === pathToFileURL3(entryPath).href;
|
|
6017
6306
|
}
|
|
6018
6307
|
if (isDirectRun()) {
|
|
6019
6308
|
main(process.argv).catch((error) => {
|