@sidecar-ai/cli 0.1.0-alpha.10 → 0.1.0-alpha.4
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 +405 -895
- 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 existsSync6, 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 path19 from "path";
|
|
8
8
|
import { createInterface as createInterface2 } from "readline/promises";
|
|
9
|
-
import { fileURLToPath, pathToFileURL
|
|
9
|
+
import { fileURLToPath, pathToFileURL } from "url";
|
|
10
10
|
import { cwd, exit, stdin as stdin2, stdout as stdout2 } from "process";
|
|
11
|
-
import { tsImport
|
|
11
|
+
import { tsImport } 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:
|
|
69
|
+
structuredContent: input.structuredContent,
|
|
70
70
|
content: normalizeRequiredContent(input.content),
|
|
71
|
-
_meta:
|
|
71
|
+
_meta: 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:
|
|
115
|
+
structuredContent: value.structuredContent,
|
|
116
116
|
content: value.content ?? [],
|
|
117
|
-
_meta:
|
|
117
|
+
_meta: value._meta,
|
|
118
118
|
isError: value.isError
|
|
119
119
|
});
|
|
120
120
|
}
|
|
@@ -453,24 +453,10 @@ 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
|
-
}
|
|
470
456
|
|
|
471
457
|
// packages/compiler/src/analyze.ts
|
|
472
458
|
import { readdir } from "fs/promises";
|
|
473
|
-
import
|
|
459
|
+
import path4 from "path";
|
|
474
460
|
import {
|
|
475
461
|
Node as Node4,
|
|
476
462
|
SyntaxKind as SyntaxKind2
|
|
@@ -637,7 +623,14 @@ function devSidecarTypePaths() {
|
|
|
637
623
|
import {
|
|
638
624
|
Node as Node2
|
|
639
625
|
} from "ts-morph";
|
|
640
|
-
function getParamsSchema(
|
|
626
|
+
function getParamsSchema(definition, execute) {
|
|
627
|
+
const explicitParams = definition.getProperty("params");
|
|
628
|
+
if (explicitParams && Node2.isPropertyAssignment(explicitParams)) {
|
|
629
|
+
const inferred = getSchemaFromZodProperty(explicitParams);
|
|
630
|
+
if (inferred) {
|
|
631
|
+
return inferred;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
641
634
|
const [params] = execute.getParameters();
|
|
642
635
|
if (!params) {
|
|
643
636
|
return emptyObjectSchema();
|
|
@@ -658,6 +651,74 @@ function getOutputSchema(definition, execute) {
|
|
|
658
651
|
}
|
|
659
652
|
return typeToJsonSchema(returnType);
|
|
660
653
|
}
|
|
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
|
+
}
|
|
661
722
|
function typeToJsonSchema(type, description) {
|
|
662
723
|
const withoutUndefined = removeUndefined(type);
|
|
663
724
|
const schema = typeToJsonSchemaInner(withoutUndefined);
|
|
@@ -803,103 +864,11 @@ function schemaDescription(symbol) {
|
|
|
803
864
|
}).find((comment) => comment.trim().length > 0);
|
|
804
865
|
}
|
|
805
866
|
|
|
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
|
-
|
|
896
867
|
// packages/compiler/src/widgets.ts
|
|
897
868
|
import { createHash } from "crypto";
|
|
898
|
-
import { existsSync as
|
|
869
|
+
import { existsSync as existsSync2 } from "fs";
|
|
899
870
|
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
900
|
-
import
|
|
901
|
-
import path4 from "path";
|
|
902
|
-
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
871
|
+
import path3 from "path";
|
|
903
872
|
import { build as esbuild } from "esbuild";
|
|
904
873
|
import postcss from "postcss";
|
|
905
874
|
import {
|
|
@@ -907,30 +876,28 @@ import {
|
|
|
907
876
|
SyntaxKind
|
|
908
877
|
} from "ts-morph";
|
|
909
878
|
var CLAUDE_FONT_RESOURCE_DOMAIN = "https://assets.claude.ai";
|
|
910
|
-
|
|
911
|
-
async function buildWidgets(rootDir, outDir, tools, config = void 0) {
|
|
879
|
+
async function buildWidgets(rootDir, outDir, tools) {
|
|
912
880
|
const widgets = tools.filter(
|
|
913
881
|
(entry) => Boolean(entry.widget)
|
|
914
882
|
);
|
|
915
883
|
if (!widgets.length) {
|
|
916
884
|
return;
|
|
917
885
|
}
|
|
918
|
-
const cacheDir =
|
|
886
|
+
const cacheDir = path3.join(rootDir, ".sidecar", "cache", "widgets");
|
|
919
887
|
await mkdir(cacheDir, { recursive: true });
|
|
920
888
|
const appStyle = await prepareAppStyle(rootDir, cacheDir);
|
|
921
|
-
const configure = await loadWidgetBundlerHook(rootDir, cacheDir, config?.configure);
|
|
922
889
|
for (const entry of widgets) {
|
|
923
|
-
const sourceFile =
|
|
890
|
+
const sourceFile = path3.join(rootDir, entry.widget.sourceFile);
|
|
924
891
|
const safeId = safePathSegment(entry.id);
|
|
925
|
-
const entryFile =
|
|
926
|
-
const importPath = toImportSpecifier(
|
|
892
|
+
const entryFile = path3.join(cacheDir, `${safeId}.entry.tsx`);
|
|
893
|
+
const importPath = toImportSpecifier(path3.dirname(entryFile), sourceFile);
|
|
927
894
|
await writeFile(
|
|
928
895
|
entryFile,
|
|
929
896
|
`import React from "react";
|
|
930
897
|
import { createRoot } from "react-dom/client";
|
|
931
898
|
import { SidecarWidgetRoot } from "@sidecar-ai/react";
|
|
932
899
|
import "@sidecar-ai/native/styles.css";
|
|
933
|
-
${appStyle ? `import ${JSON.stringify(toImportSpecifier(
|
|
900
|
+
${appStyle ? `import ${JSON.stringify(toImportSpecifier(path3.dirname(entryFile), appStyle))};` : ""}
|
|
934
901
|
import Component from ${JSON.stringify(importPath)};
|
|
935
902
|
|
|
936
903
|
createRoot(document.getElementById("root")!).render(
|
|
@@ -938,219 +905,64 @@ createRoot(document.getElementById("root")!).render(
|
|
|
938
905
|
);
|
|
939
906
|
`
|
|
940
907
|
);
|
|
941
|
-
const
|
|
908
|
+
const bundled = await esbuild({
|
|
942
909
|
absWorkingDir: rootDir,
|
|
943
|
-
alias:
|
|
910
|
+
alias: devSidecarBundleAliases(rootDir),
|
|
944
911
|
bundle: true,
|
|
945
|
-
define: {
|
|
946
|
-
"process.env.NODE_ENV": JSON.stringify("production")
|
|
947
|
-
},
|
|
948
912
|
entryPoints: [entryFile],
|
|
949
913
|
format: "iife",
|
|
950
914
|
jsx: "automatic",
|
|
951
|
-
minify:
|
|
915
|
+
minify: false,
|
|
952
916
|
nodePaths: [
|
|
953
|
-
|
|
954
|
-
|
|
917
|
+
path3.join(rootDir, "node_modules"),
|
|
918
|
+
path3.join(process.cwd(), "node_modules")
|
|
955
919
|
],
|
|
956
920
|
outfile: "widget.js",
|
|
957
921
|
platform: "browser",
|
|
958
922
|
sourcemap: false,
|
|
959
923
|
write: false
|
|
960
924
|
});
|
|
961
|
-
const
|
|
962
|
-
const
|
|
963
|
-
rootDir,
|
|
964
|
-
outDir,
|
|
965
|
-
entryFile,
|
|
966
|
-
widget: {
|
|
967
|
-
toolId: entry.id,
|
|
968
|
-
toolName: entry.name,
|
|
969
|
-
target: entry.target,
|
|
970
|
-
sourceFile: entry.widget.sourceFile
|
|
971
|
-
},
|
|
972
|
-
esbuildOptions: mergeWidgetBuildOptions(baseOptions, staticOptions)
|
|
973
|
-
}) : void 0;
|
|
974
|
-
const bundled = await esbuild(enforceWidgetBuildInvariants(
|
|
975
|
-
mergeWidgetBuildOptions(baseOptions, staticOptions, configuredOptions),
|
|
976
|
-
{ rootDir, entryFile }
|
|
977
|
-
));
|
|
978
|
-
const outputFiles = bundled.outputFiles ?? [];
|
|
979
|
-
const javascript = outputFiles.find((file) => file.path.endsWith(".js"))?.text ?? "";
|
|
980
|
-
const css = outputFiles.filter((file) => file.path.endsWith(".css")).map((file) => file.text).join("\n");
|
|
925
|
+
const javascript = bundled.outputFiles.find((file) => file.path.endsWith(".js"))?.text ?? "";
|
|
926
|
+
const css = bundled.outputFiles.filter((file) => file.path.endsWith(".css")).map((file) => file.text).join("\n");
|
|
981
927
|
const html = renderWidgetHtml(entry.name, javascript, css);
|
|
982
928
|
const hash = createHash("sha256").update(html).digest("hex").slice(0, 12);
|
|
983
|
-
const outputDir =
|
|
984
|
-
const outputFile =
|
|
929
|
+
const outputDir = path3.join(outDir, "public", "widgets", safeId);
|
|
930
|
+
const outputFile = path3.join(outputDir, `widget.${hash}.html`);
|
|
985
931
|
const resourceUri = `ui://${safeId}/widget.${hash}.html`;
|
|
986
932
|
await mkdir(outputDir, { recursive: true });
|
|
987
933
|
await writeFile(outputFile, html);
|
|
988
934
|
entry.widget.resourceUri = resourceUri;
|
|
989
935
|
entry.widget.resourceMeta = widgetResourceMeta(entry.widget.options, entry.target);
|
|
990
|
-
entry.widget.outputFile =
|
|
936
|
+
entry.widget.outputFile = path3.relative(outDir, outputFile);
|
|
991
937
|
entry.descriptor._meta = mergeWidgetMeta(entry.descriptor._meta, widgetMeta(resourceUri, entry.widget.options, entry.target));
|
|
992
938
|
}
|
|
993
939
|
}
|
|
994
|
-
function widgetBuildOptionsFromConfig(rootDir, config) {
|
|
995
|
-
const esbuildConfig = config?.esbuild;
|
|
996
|
-
if (!esbuildConfig) {
|
|
997
|
-
return void 0;
|
|
998
|
-
}
|
|
999
|
-
return {
|
|
1000
|
-
alias: normalizeAliases(rootDir, esbuildConfig.alias),
|
|
1001
|
-
conditions: esbuildConfig.conditions,
|
|
1002
|
-
define: esbuildConfig.define,
|
|
1003
|
-
external: esbuildConfig.external,
|
|
1004
|
-
jsx: esbuildConfig.jsx,
|
|
1005
|
-
jsxImportSource: esbuildConfig.jsxImportSource,
|
|
1006
|
-
loader: esbuildConfig.loader,
|
|
1007
|
-
mainFields: esbuildConfig.mainFields
|
|
1008
|
-
};
|
|
1009
|
-
}
|
|
1010
|
-
async function loadWidgetBundlerHook(rootDir, cacheDir, hookPath) {
|
|
1011
|
-
if (!hookPath) {
|
|
1012
|
-
return void 0;
|
|
1013
|
-
}
|
|
1014
|
-
const sourcePath = path4.resolve(rootDir, hookPath);
|
|
1015
|
-
const relative = path4.relative(rootDir, sourcePath);
|
|
1016
|
-
if (relative.startsWith("..") || path4.isAbsolute(relative)) {
|
|
1017
|
-
throw new Error(`Widget bundler hook must stay inside the project root: ${hookPath}`);
|
|
1018
|
-
}
|
|
1019
|
-
if (!existsSync3(sourcePath)) {
|
|
1020
|
-
throw new Error(`Widget bundler hook not found: ${hookPath}`);
|
|
1021
|
-
}
|
|
1022
|
-
const outputFile = path4.join(cacheDir, `widget-bundler.${contentHash(hookPath)}.mjs`);
|
|
1023
|
-
await esbuild({
|
|
1024
|
-
absWorkingDir: rootDir,
|
|
1025
|
-
alias: devSidecarBundleAliases(rootDir),
|
|
1026
|
-
bundle: true,
|
|
1027
|
-
entryPoints: [sourcePath],
|
|
1028
|
-
format: "esm",
|
|
1029
|
-
nodePaths: [
|
|
1030
|
-
path4.join(rootDir, "node_modules"),
|
|
1031
|
-
path4.join(process.cwd(), "node_modules")
|
|
1032
|
-
],
|
|
1033
|
-
outfile: outputFile,
|
|
1034
|
-
packages: "external",
|
|
1035
|
-
platform: "node",
|
|
1036
|
-
target: "node20"
|
|
1037
|
-
});
|
|
1038
|
-
const module = await import(`${pathToFileURL2(outputFile).href}?t=${Date.now()}`);
|
|
1039
|
-
if (typeof module.default !== "function") {
|
|
1040
|
-
throw new Error(`Widget bundler hook must default-export a function: ${hookPath}`);
|
|
1041
|
-
}
|
|
1042
|
-
return module.default;
|
|
1043
|
-
}
|
|
1044
|
-
async function configureWidgetBuild(hook, input) {
|
|
1045
|
-
const result = await hook(input);
|
|
1046
|
-
if (!result) {
|
|
1047
|
-
return void 0;
|
|
1048
|
-
}
|
|
1049
|
-
if (typeof result === "object" && "esbuildOptions" in result) {
|
|
1050
|
-
return result.esbuildOptions;
|
|
1051
|
-
}
|
|
1052
|
-
return result;
|
|
1053
|
-
}
|
|
1054
|
-
function mergeWidgetBuildOptions(...options) {
|
|
1055
|
-
const merged = {};
|
|
1056
|
-
for (const option of options) {
|
|
1057
|
-
if (!option) {
|
|
1058
|
-
continue;
|
|
1059
|
-
}
|
|
1060
|
-
const previousAlias = merged.alias;
|
|
1061
|
-
const previousDefine = merged.define;
|
|
1062
|
-
const previousLoader = merged.loader;
|
|
1063
|
-
const previousExternal = merged.external;
|
|
1064
|
-
const previousNodePaths = merged.nodePaths;
|
|
1065
|
-
const previousPlugins = merged.plugins;
|
|
1066
|
-
Object.assign(merged, option);
|
|
1067
|
-
merged.alias = { ...previousAlias ?? {}, ...option.alias ?? {} };
|
|
1068
|
-
merged.define = { ...previousDefine ?? {}, ...option.define ?? {} };
|
|
1069
|
-
merged.loader = { ...previousLoader ?? {}, ...option.loader ?? {} };
|
|
1070
|
-
merged.external = uniqueStrings([...previousExternal ?? [], ...option.external ?? []]);
|
|
1071
|
-
merged.nodePaths = uniqueStrings([...previousNodePaths ?? [], ...option.nodePaths ?? []]);
|
|
1072
|
-
merged.plugins = [...previousPlugins ?? [], ...option.plugins ?? []];
|
|
1073
|
-
}
|
|
1074
|
-
return merged;
|
|
1075
|
-
}
|
|
1076
|
-
function enforceWidgetBuildInvariants(options, required) {
|
|
1077
|
-
const aliases = required ? { ...options.alias ?? {}, ...reactSingletonAliases(required.rootDir) } : options.alias;
|
|
1078
|
-
return {
|
|
1079
|
-
...options,
|
|
1080
|
-
absWorkingDir: required?.rootDir ?? options.absWorkingDir,
|
|
1081
|
-
alias: aliases,
|
|
1082
|
-
bundle: true,
|
|
1083
|
-
entryPoints: required ? [required.entryFile] : options.entryPoints,
|
|
1084
|
-
format: "iife",
|
|
1085
|
-
outfile: "widget.js",
|
|
1086
|
-
platform: "browser",
|
|
1087
|
-
write: false
|
|
1088
|
-
};
|
|
1089
|
-
}
|
|
1090
|
-
function sidecarWidgetAliases(rootDir) {
|
|
1091
|
-
return {
|
|
1092
|
-
...devSidecarBundleAliases(rootDir) ?? {},
|
|
1093
|
-
...reactSingletonAliases(rootDir)
|
|
1094
|
-
};
|
|
1095
|
-
}
|
|
1096
|
-
function reactSingletonAliases(rootDir) {
|
|
1097
|
-
return {
|
|
1098
|
-
react: resolveProjectModule(rootDir, "react"),
|
|
1099
|
-
"react/jsx-runtime": resolveProjectModule(rootDir, "react/jsx-runtime"),
|
|
1100
|
-
"react/jsx-dev-runtime": resolveProjectModule(rootDir, "react/jsx-dev-runtime"),
|
|
1101
|
-
"react-dom": resolveProjectModule(rootDir, "react-dom"),
|
|
1102
|
-
"react-dom/client": resolveProjectModule(rootDir, "react-dom/client"),
|
|
1103
|
-
"react-dom/server": resolveProjectModule(rootDir, "react-dom/server")
|
|
1104
|
-
};
|
|
1105
|
-
}
|
|
1106
|
-
function resolveProjectModule(rootDir, specifier) {
|
|
1107
|
-
return requireFromCompiler.resolve(specifier, {
|
|
1108
|
-
paths: [rootDir, process.cwd()]
|
|
1109
|
-
});
|
|
1110
|
-
}
|
|
1111
|
-
function normalizeAliases(rootDir, aliases) {
|
|
1112
|
-
if (!aliases) {
|
|
1113
|
-
return void 0;
|
|
1114
|
-
}
|
|
1115
|
-
return Object.fromEntries(
|
|
1116
|
-
Object.entries(aliases).map(([key, value]) => [
|
|
1117
|
-
key,
|
|
1118
|
-
value.startsWith(".") ? path4.resolve(rootDir, value) : value
|
|
1119
|
-
])
|
|
1120
|
-
);
|
|
1121
|
-
}
|
|
1122
|
-
function uniqueStrings(values) {
|
|
1123
|
-
return [...new Set(values)];
|
|
1124
|
-
}
|
|
1125
|
-
function contentHash(value) {
|
|
1126
|
-
return createHash("sha256").update(value).digest("hex").slice(0, 12);
|
|
1127
|
-
}
|
|
1128
940
|
function devSidecarBundleAliases(rootDir) {
|
|
1129
941
|
const repoRoot = findSidecarRepoRoot(rootDir) ?? findSidecarRepoRoot(process.cwd());
|
|
1130
942
|
if (!repoRoot) {
|
|
1131
943
|
return void 0;
|
|
1132
944
|
}
|
|
1133
|
-
const reactEntry =
|
|
1134
|
-
if (!
|
|
945
|
+
const reactEntry = path3.join(repoRoot, "packages", "react", "src", "index.ts");
|
|
946
|
+
if (!existsSync2(reactEntry)) {
|
|
1135
947
|
return void 0;
|
|
1136
948
|
}
|
|
1137
949
|
return {
|
|
1138
|
-
"sidecar-ai":
|
|
1139
|
-
"@sidecar-ai/client":
|
|
1140
|
-
"@sidecar-ai/core":
|
|
950
|
+
"sidecar-ai": path3.join(repoRoot, "packages", "sidecar-ai", "src", "index.ts"),
|
|
951
|
+
"@sidecar-ai/client": path3.join(repoRoot, "packages", "client", "src", "index.ts"),
|
|
952
|
+
"@sidecar-ai/core": path3.join(repoRoot, "packages", "core", "src", "index.ts"),
|
|
1141
953
|
"@sidecar-ai/react": reactEntry,
|
|
1142
|
-
"@sidecar-ai/native":
|
|
1143
|
-
"@sidecar-ai/native/components":
|
|
1144
|
-
"@sidecar-ai/native/styles.css":
|
|
954
|
+
"@sidecar-ai/native": path3.join(repoRoot, "packages", "native", "src", "index.ts"),
|
|
955
|
+
"@sidecar-ai/native/components": path3.join(repoRoot, "packages", "native", "src", "components", "index.tsx"),
|
|
956
|
+
"@sidecar-ai/native/styles.css": path3.join(repoRoot, "packages", "native", "src", "styles.css")
|
|
1145
957
|
};
|
|
1146
958
|
}
|
|
1147
959
|
function findSidecarRepoRoot(startDir) {
|
|
1148
|
-
let current =
|
|
960
|
+
let current = path3.resolve(startDir);
|
|
1149
961
|
while (true) {
|
|
1150
|
-
if (
|
|
962
|
+
if (existsSync2(path3.join(current, "packages", "core", "src", "index.ts"))) {
|
|
1151
963
|
return current;
|
|
1152
964
|
}
|
|
1153
|
-
const parent =
|
|
965
|
+
const parent = path3.dirname(current);
|
|
1154
966
|
if (parent === current) {
|
|
1155
967
|
return void 0;
|
|
1156
968
|
}
|
|
@@ -1158,13 +970,13 @@ function findSidecarRepoRoot(startDir) {
|
|
|
1158
970
|
}
|
|
1159
971
|
}
|
|
1160
972
|
async function prepareAppStyle(rootDir, cacheDir) {
|
|
1161
|
-
const sourceFile =
|
|
1162
|
-
if (!
|
|
973
|
+
const sourceFile = path3.join(rootDir, "style.css");
|
|
974
|
+
if (!existsSync2(sourceFile)) {
|
|
1163
975
|
return void 0;
|
|
1164
976
|
}
|
|
1165
977
|
const source = await readFile(sourceFile, "utf8");
|
|
1166
978
|
const css = await processAppStyle(source, sourceFile);
|
|
1167
|
-
const outputFile =
|
|
979
|
+
const outputFile = path3.join(cacheDir, "style.css");
|
|
1168
980
|
await writeFile(outputFile, css);
|
|
1169
981
|
return outputFile;
|
|
1170
982
|
}
|
|
@@ -1176,7 +988,7 @@ async function processAppStyle(source, from) {
|
|
|
1176
988
|
const plugins = [];
|
|
1177
989
|
if (cssSource.includes("@tailwind")) {
|
|
1178
990
|
const tailwind = await import("@tailwindcss/postcss");
|
|
1179
|
-
plugins.push(tailwind.default({ base:
|
|
991
|
+
plugins.push(tailwind.default({ base: path3.dirname(from) }));
|
|
1180
992
|
}
|
|
1181
993
|
const autoprefixer = await import("autoprefixer");
|
|
1182
994
|
plugins.push(autoprefixer.default());
|
|
@@ -1190,13 +1002,13 @@ function needsPostcss(source) {
|
|
|
1190
1002
|
return /@import\s+["']tailwindcss["']|@tailwind|@source|@theme|@plugin/.test(source);
|
|
1191
1003
|
}
|
|
1192
1004
|
function findWidget(rootDir, toolFile, id, target = "mcp", toolVariant = "shared") {
|
|
1193
|
-
const selected = selectWidgetFile(
|
|
1005
|
+
const selected = selectWidgetFile(path3.dirname(toolFile), target, toolVariant);
|
|
1194
1006
|
if (!selected) {
|
|
1195
1007
|
return void 0;
|
|
1196
1008
|
}
|
|
1197
1009
|
const safeId = safePathSegment(id);
|
|
1198
1010
|
return {
|
|
1199
|
-
sourceFile:
|
|
1011
|
+
sourceFile: path3.relative(rootDir, selected.filePath),
|
|
1200
1012
|
variant: selected.variant,
|
|
1201
1013
|
resourceUri: `ui://${safeId}/widget.html`
|
|
1202
1014
|
};
|
|
@@ -1231,8 +1043,7 @@ function widgetMeta(resourceUri, options = {}, target = "mcp") {
|
|
|
1231
1043
|
const standard = {
|
|
1232
1044
|
ui: {
|
|
1233
1045
|
resourceUri
|
|
1234
|
-
}
|
|
1235
|
-
"ui/resourceUri": resourceUri
|
|
1046
|
+
}
|
|
1236
1047
|
};
|
|
1237
1048
|
if (target !== "chatgpt") {
|
|
1238
1049
|
return standard;
|
|
@@ -1379,17 +1190,17 @@ function readStringArrayProperty(definition, propertyName) {
|
|
|
1379
1190
|
}
|
|
1380
1191
|
function selectWidgetFile(directory, target, toolVariant) {
|
|
1381
1192
|
if (toolVariant === "openai") {
|
|
1382
|
-
const filePath =
|
|
1383
|
-
return
|
|
1193
|
+
const filePath = path3.join(directory, "widget.openai.tsx");
|
|
1194
|
+
return existsSync2(filePath) ? { filePath, variant: "openai" } : void 0;
|
|
1384
1195
|
}
|
|
1385
1196
|
if (toolVariant === "anthropic") {
|
|
1386
|
-
const filePath =
|
|
1387
|
-
return
|
|
1197
|
+
const filePath = path3.join(directory, "widget.anthropic.tsx");
|
|
1198
|
+
return existsSync2(filePath) ? { filePath, variant: "anthropic" } : void 0;
|
|
1388
1199
|
}
|
|
1389
1200
|
const candidates = target === "chatgpt" || target === "claude" || target === "mcp" ? [{ name: "widget.tsx", variant: "shared" }] : [];
|
|
1390
1201
|
for (const candidate of candidates) {
|
|
1391
|
-
const filePath =
|
|
1392
|
-
if (
|
|
1202
|
+
const filePath = path3.join(directory, candidate.name);
|
|
1203
|
+
if (existsSync2(filePath)) {
|
|
1393
1204
|
return { filePath, variant: candidate.variant };
|
|
1394
1205
|
}
|
|
1395
1206
|
}
|
|
@@ -1440,23 +1251,17 @@ function stripUndefined3(value) {
|
|
|
1440
1251
|
// packages/compiler/src/analyze.ts
|
|
1441
1252
|
async function analyzeProjectTools(rootDir, options = {}) {
|
|
1442
1253
|
const target = options.target ?? "mcp";
|
|
1443
|
-
const toolFiles = await findToolFiles(
|
|
1254
|
+
const toolFiles = await findToolFiles(path4.join(rootDir, "server"), target);
|
|
1444
1255
|
if (toolFiles.length === 0) {
|
|
1445
1256
|
return [];
|
|
1446
1257
|
}
|
|
1447
1258
|
const project = createProject(rootDir);
|
|
1448
1259
|
const authScopes = readAuthScopeCatalog(project, rootDir);
|
|
1449
|
-
|
|
1450
|
-
candidate,
|
|
1451
|
-
sourceFile: project.addSourceFileAtPath(candidate.filePath)
|
|
1452
|
-
}));
|
|
1453
|
-
const runtimeInputSchemas = await readRuntimeInputSchemas(rootDir, sources);
|
|
1454
|
-
return sources.map(
|
|
1455
|
-
({ candidate, sourceFile }) => analyzeToolFile(sourceFile, rootDir, {
|
|
1260
|
+
return toolFiles.map(
|
|
1261
|
+
(candidate) => analyzeToolFile(project.addSourceFileAtPath(candidate.filePath), rootDir, {
|
|
1456
1262
|
target,
|
|
1457
1263
|
variant: candidate.variant,
|
|
1458
|
-
authScopes
|
|
1459
|
-
inputSchema: runtimeInputSchemas.get(candidate.filePath)
|
|
1264
|
+
authScopes
|
|
1460
1265
|
})
|
|
1461
1266
|
);
|
|
1462
1267
|
}
|
|
@@ -1465,7 +1270,7 @@ function analyzeToolFile(sourceFile, rootDir, options = {}) {
|
|
|
1465
1270
|
const variant = options.variant ?? "shared";
|
|
1466
1271
|
const definition = findToolDefinition(sourceFile);
|
|
1467
1272
|
const absoluteFile = sourceFile.getFilePath();
|
|
1468
|
-
const directory =
|
|
1273
|
+
const directory = path4.basename(path4.dirname(absoluteFile));
|
|
1469
1274
|
const name = getRequiredStringProperty(definition, "name", sourceFile);
|
|
1470
1275
|
const id = getOptionalStringProperty(definition, "id") ?? toMachineName(directory);
|
|
1471
1276
|
const description = getRequiredStringProperty(
|
|
@@ -1478,7 +1283,7 @@ function analyzeToolFile(sourceFile, rootDir, options = {}) {
|
|
|
1478
1283
|
const hosts = readHosts(definition);
|
|
1479
1284
|
const auth = readAuthPolicy(definition, options.authScopes ?? {});
|
|
1480
1285
|
const execute = getExecuteFunction(definition, sourceFile);
|
|
1481
|
-
const inputSchema =
|
|
1286
|
+
const inputSchema = getParamsSchema(definition, execute);
|
|
1482
1287
|
const outputSchema = getOutputSchema(definition, execute);
|
|
1483
1288
|
const descriptor = createToolDescriptor({
|
|
1484
1289
|
name,
|
|
@@ -1496,7 +1301,7 @@ function analyzeToolFile(sourceFile, rootDir, options = {}) {
|
|
|
1496
1301
|
validateWidgetHierarchy(sourceFile, absoluteFile, target, variant);
|
|
1497
1302
|
const widget = findWidget(rootDir, absoluteFile, id, target, variant);
|
|
1498
1303
|
if (widget) {
|
|
1499
|
-
const widgetFile =
|
|
1304
|
+
const widgetFile = path4.join(rootDir, widget.sourceFile);
|
|
1500
1305
|
const project = sourceFile.getProject();
|
|
1501
1306
|
const widgetSourceFile = project.getSourceFile(widgetFile) ?? project.addSourceFileAtPath(widgetFile);
|
|
1502
1307
|
widget.options = {
|
|
@@ -1507,7 +1312,7 @@ function analyzeToolFile(sourceFile, rootDir, options = {}) {
|
|
|
1507
1312
|
descriptor._meta = mergeWidgetMeta(descriptor._meta, widgetMeta(widget.resourceUri, widget.options, target));
|
|
1508
1313
|
}
|
|
1509
1314
|
return {
|
|
1510
|
-
sourceFile:
|
|
1315
|
+
sourceFile: path4.relative(rootDir, absoluteFile),
|
|
1511
1316
|
variant,
|
|
1512
1317
|
target,
|
|
1513
1318
|
directory,
|
|
@@ -1522,26 +1327,6 @@ function analyzeToolFile(sourceFile, rootDir, options = {}) {
|
|
|
1522
1327
|
descriptor
|
|
1523
1328
|
};
|
|
1524
1329
|
}
|
|
1525
|
-
async function readRuntimeInputSchemas(rootDir, sources) {
|
|
1526
|
-
const schemas = /* @__PURE__ */ new Map();
|
|
1527
|
-
await Promise.all(sources.map(async ({ candidate, sourceFile }) => {
|
|
1528
|
-
const definition = findToolDefinition(sourceFile);
|
|
1529
|
-
if (!definitionHasRuntimeParams(definition)) {
|
|
1530
|
-
return;
|
|
1531
|
-
}
|
|
1532
|
-
const schema = await readRuntimeToolInputSchema(rootDir, candidate.filePath);
|
|
1533
|
-
if (schema) {
|
|
1534
|
-
schemas.set(candidate.filePath, schema);
|
|
1535
|
-
}
|
|
1536
|
-
}));
|
|
1537
|
-
return schemas;
|
|
1538
|
-
}
|
|
1539
|
-
function definitionHasRuntimeParams(definition) {
|
|
1540
|
-
if (definition.getProperty("params")) {
|
|
1541
|
-
return true;
|
|
1542
|
-
}
|
|
1543
|
-
return Boolean(getWithParamsCall(definition));
|
|
1544
|
-
}
|
|
1545
1330
|
function readAuthPolicy(definition, authScopes) {
|
|
1546
1331
|
const initializer = readObjectProperty2(definition, "auth");
|
|
1547
1332
|
if (!initializer) {
|
|
@@ -1558,7 +1343,7 @@ function readAuthPolicy(definition, authScopes) {
|
|
|
1558
1343
|
return { authenticated: true };
|
|
1559
1344
|
}
|
|
1560
1345
|
function readAuthScopeCatalog(project, rootDir) {
|
|
1561
|
-
const authPath =
|
|
1346
|
+
const authPath = path4.join(rootDir, "auth.ts");
|
|
1562
1347
|
if (!existsSyncSafe(authPath)) {
|
|
1563
1348
|
return {};
|
|
1564
1349
|
}
|
|
@@ -1640,12 +1425,12 @@ function isNamedCall(call, name) {
|
|
|
1640
1425
|
return callee === name || callee.endsWith(`.${name}`);
|
|
1641
1426
|
}
|
|
1642
1427
|
function validateWidgetHierarchy(sourceFile, toolFile, target, variant) {
|
|
1643
|
-
const directory =
|
|
1428
|
+
const directory = path4.dirname(toolFile);
|
|
1644
1429
|
const platformWidget = target === "chatgpt" ? "widget.openai.tsx" : target === "claude" ? "widget.anthropic.tsx" : void 0;
|
|
1645
1430
|
if (!platformWidget || variant !== "shared") {
|
|
1646
1431
|
return;
|
|
1647
1432
|
}
|
|
1648
|
-
if (existsSyncSafe(
|
|
1433
|
+
if (existsSyncSafe(path4.join(directory, platformWidget))) {
|
|
1649
1434
|
const expectedTool = target === "chatgpt" ? "tool.openai.ts" : "tool.anthropic.ts";
|
|
1650
1435
|
throw new CompilerError(
|
|
1651
1436
|
sourceFile,
|
|
@@ -1660,7 +1445,7 @@ async function findToolFiles(serverDir, target) {
|
|
|
1660
1445
|
const entries = await readdir(serverDir, { withFileTypes: true });
|
|
1661
1446
|
const files = [];
|
|
1662
1447
|
for (const entry of entries) {
|
|
1663
|
-
const entryPath =
|
|
1448
|
+
const entryPath = path4.join(serverDir, entry.name);
|
|
1664
1449
|
if (entry.isDirectory()) {
|
|
1665
1450
|
const candidate = selectToolFile(entryPath, target);
|
|
1666
1451
|
if (candidate) {
|
|
@@ -1679,7 +1464,7 @@ function selectToolFile(directory, target) {
|
|
|
1679
1464
|
{ name: "tool.ts", variant: "shared" }
|
|
1680
1465
|
] : [{ name: "tool.ts", variant: "shared" }];
|
|
1681
1466
|
for (const candidate of candidates) {
|
|
1682
|
-
const filePath =
|
|
1467
|
+
const filePath = path4.join(directory, candidate.name);
|
|
1683
1468
|
if (existsSyncSafe(filePath)) {
|
|
1684
1469
|
return { filePath, variant: candidate.variant };
|
|
1685
1470
|
}
|
|
@@ -1715,32 +1500,16 @@ function getExecuteFunction(definition, sourceFile) {
|
|
|
1715
1500
|
return property;
|
|
1716
1501
|
}
|
|
1717
1502
|
if (Node4.isPropertyAssignment(property)) {
|
|
1718
|
-
const initializer =
|
|
1503
|
+
const initializer = property.getInitializer();
|
|
1719
1504
|
if (initializer && (Node4.isArrowFunction(initializer) || Node4.isFunctionExpression(initializer))) {
|
|
1720
1505
|
return initializer;
|
|
1721
1506
|
}
|
|
1722
|
-
const withParamsCall = getWithParamsCall(definition);
|
|
1723
|
-
const wrappedExecute = unwrapExpression(withParamsCall?.getArguments()[1]);
|
|
1724
|
-
if (wrappedExecute && (Node4.isArrowFunction(wrappedExecute) || Node4.isFunctionExpression(wrappedExecute))) {
|
|
1725
|
-
return wrappedExecute;
|
|
1726
|
-
}
|
|
1727
1507
|
}
|
|
1728
1508
|
throw new CompilerError(
|
|
1729
1509
|
sourceFile,
|
|
1730
1510
|
"execute must be a method, function expression, or arrow function."
|
|
1731
1511
|
);
|
|
1732
1512
|
}
|
|
1733
|
-
function getWithParamsCall(definition) {
|
|
1734
|
-
const property = definition.getProperty("execute");
|
|
1735
|
-
if (!property || !Node4.isPropertyAssignment(property)) {
|
|
1736
|
-
return void 0;
|
|
1737
|
-
}
|
|
1738
|
-
const initializer = unwrapExpression(property.getInitializer());
|
|
1739
|
-
if (!initializer || !Node4.isCallExpression(initializer)) {
|
|
1740
|
-
return void 0;
|
|
1741
|
-
}
|
|
1742
|
-
return isNamedCall(initializer, "withParams") ? initializer : void 0;
|
|
1743
|
-
}
|
|
1744
1513
|
function getRequiredStringProperty(definition, propertyName, sourceFile) {
|
|
1745
1514
|
const value = getOptionalStringProperty(definition, propertyName);
|
|
1746
1515
|
if (value === void 0 || !value.trim()) {
|
|
@@ -1896,16 +1665,16 @@ function readStringArrayProperty2(definition, propertyName) {
|
|
|
1896
1665
|
|
|
1897
1666
|
// packages/compiler/src/build.ts
|
|
1898
1667
|
import { mkdir as mkdir9, writeFile as writeFile9 } from "fs/promises";
|
|
1899
|
-
import
|
|
1668
|
+
import path18 from "path";
|
|
1900
1669
|
|
|
1901
1670
|
// packages/compiler/src/config.ts
|
|
1902
|
-
import
|
|
1671
|
+
import path5 from "path";
|
|
1903
1672
|
import {
|
|
1904
1673
|
Node as Node5,
|
|
1905
1674
|
SyntaxKind as SyntaxKind3
|
|
1906
1675
|
} from "ts-morph";
|
|
1907
1676
|
function analyzeProjectConfig(rootDir) {
|
|
1908
|
-
const configPath =
|
|
1677
|
+
const configPath = path5.join(rootDir, "sidecar.config.ts");
|
|
1909
1678
|
if (!existsSyncSafe(configPath)) {
|
|
1910
1679
|
return defaultCompilerConfig();
|
|
1911
1680
|
}
|
|
@@ -1917,13 +1686,6 @@ function analyzeProjectConfig(rootDir) {
|
|
|
1917
1686
|
return defaultCompilerConfig();
|
|
1918
1687
|
}
|
|
1919
1688
|
return {
|
|
1920
|
-
build: {
|
|
1921
|
-
target: readTargetNested(definition, "build", "target"),
|
|
1922
|
-
host: readHostNested(definition, "build", "host"),
|
|
1923
|
-
outDir: readStringNested(definition, "build", "outDir"),
|
|
1924
|
-
plugins: readBooleanNested(definition, "build", "plugins"),
|
|
1925
|
-
widgets: readWidgetBuildConfig(definition)
|
|
1926
|
-
},
|
|
1927
1689
|
resources: {
|
|
1928
1690
|
subscribe: readBooleanNested(definition, "resources", "subscribe") ?? false,
|
|
1929
1691
|
listChanged: readBooleanNested(definition, "resources", "listChanged") ?? false
|
|
@@ -1935,52 +1697,13 @@ function analyzeProjectConfig(rootDir) {
|
|
|
1935
1697
|
listChanged: readBooleanNested(definition, "tools", "listChanged") ?? false
|
|
1936
1698
|
},
|
|
1937
1699
|
pagination: {
|
|
1938
|
-
pageSize: readNumberNested(definition, "pagination", "pageSize") ??
|
|
1700
|
+
pageSize: readNumberNested(definition, "pagination", "pageSize") ?? 10,
|
|
1939
1701
|
hasOverride: hasProperty(readObjectProperty3(definition, "pagination"), "override")
|
|
1940
1702
|
}
|
|
1941
1703
|
};
|
|
1942
1704
|
}
|
|
1943
|
-
function readWidgetBuildConfig(definition) {
|
|
1944
|
-
const widgets = readObjectProperty3(readObjectProperty3(definition, "build"), "widgets");
|
|
1945
|
-
if (!widgets) {
|
|
1946
|
-
return void 0;
|
|
1947
|
-
}
|
|
1948
|
-
const config = {};
|
|
1949
|
-
const configure = readStringProperty3(widgets, "configure");
|
|
1950
|
-
const esbuild3 = readWidgetEsbuildConfig(widgets);
|
|
1951
|
-
if (configure) config.configure = configure;
|
|
1952
|
-
if (esbuild3) config.esbuild = esbuild3;
|
|
1953
|
-
return Object.keys(config).length ? config : void 0;
|
|
1954
|
-
}
|
|
1955
|
-
function readWidgetEsbuildConfig(widgets) {
|
|
1956
|
-
const esbuild3 = readObjectProperty3(widgets, "esbuild");
|
|
1957
|
-
if (!esbuild3) {
|
|
1958
|
-
return void 0;
|
|
1959
|
-
}
|
|
1960
|
-
const config = {};
|
|
1961
|
-
const alias = readStringRecordProperty(esbuild3, "alias");
|
|
1962
|
-
const define = readStringRecordProperty(esbuild3, "define");
|
|
1963
|
-
const external = readStringArrayProperty3(esbuild3, "external");
|
|
1964
|
-
const loader = readStringRecordProperty(esbuild3, "loader");
|
|
1965
|
-
const conditions = readStringArrayProperty3(esbuild3, "conditions");
|
|
1966
|
-
const mainFields = readStringArrayProperty3(esbuild3, "mainFields");
|
|
1967
|
-
const jsx = readStringProperty3(esbuild3, "jsx");
|
|
1968
|
-
const jsxImportSource = readStringProperty3(esbuild3, "jsxImportSource");
|
|
1969
|
-
if (alias) config.alias = alias;
|
|
1970
|
-
if (define) config.define = define;
|
|
1971
|
-
if (external) config.external = external;
|
|
1972
|
-
if (loader) config.loader = loader;
|
|
1973
|
-
if (conditions) config.conditions = conditions;
|
|
1974
|
-
if (mainFields) config.mainFields = mainFields;
|
|
1975
|
-
if (jsx === "automatic" || jsx === "transform" || jsx === "preserve") {
|
|
1976
|
-
config.jsx = jsx;
|
|
1977
|
-
}
|
|
1978
|
-
if (jsxImportSource) config.jsxImportSource = jsxImportSource;
|
|
1979
|
-
return Object.keys(config).length ? config : void 0;
|
|
1980
|
-
}
|
|
1981
1705
|
function defaultCompilerConfig() {
|
|
1982
1706
|
return {
|
|
1983
|
-
build: {},
|
|
1984
1707
|
resources: {
|
|
1985
1708
|
subscribe: false,
|
|
1986
1709
|
listChanged: false
|
|
@@ -1992,26 +1715,11 @@ function defaultCompilerConfig() {
|
|
|
1992
1715
|
listChanged: false
|
|
1993
1716
|
},
|
|
1994
1717
|
pagination: {
|
|
1995
|
-
pageSize:
|
|
1718
|
+
pageSize: 10,
|
|
1996
1719
|
hasOverride: false
|
|
1997
1720
|
}
|
|
1998
1721
|
};
|
|
1999
1722
|
}
|
|
2000
|
-
function readTargetNested(definition, section, propertyName) {
|
|
2001
|
-
const value = readStringNested(definition, section, propertyName);
|
|
2002
|
-
return value === "mcp" || value === "chatgpt" || value === "claude" ? value : void 0;
|
|
2003
|
-
}
|
|
2004
|
-
function readHostNested(definition, section, propertyName) {
|
|
2005
|
-
const value = readStringNested(definition, section, propertyName);
|
|
2006
|
-
return value === "node" || value === "vercel" ? value : void 0;
|
|
2007
|
-
}
|
|
2008
|
-
function readStringNested(definition, section, propertyName) {
|
|
2009
|
-
const object = readObjectProperty3(definition, section);
|
|
2010
|
-
if (!object) {
|
|
2011
|
-
return void 0;
|
|
2012
|
-
}
|
|
2013
|
-
return readStringProperty3(object, propertyName);
|
|
2014
|
-
}
|
|
2015
1723
|
function readBooleanNested(definition, section, propertyName) {
|
|
2016
1724
|
const object = readObjectProperty3(definition, section);
|
|
2017
1725
|
if (!object) {
|
|
@@ -2042,9 +1750,6 @@ function readNumberNested(definition, section, propertyName) {
|
|
|
2042
1750
|
return initializer && Node5.isNumericLiteral(initializer) ? Number(initializer.getLiteralText()) : void 0;
|
|
2043
1751
|
}
|
|
2044
1752
|
function readObjectProperty3(definition, propertyName) {
|
|
2045
|
-
if (!definition) {
|
|
2046
|
-
return void 0;
|
|
2047
|
-
}
|
|
2048
1753
|
const property = definition.getProperty(propertyName);
|
|
2049
1754
|
if (!property || !Node5.isPropertyAssignment(property)) {
|
|
2050
1755
|
return void 0;
|
|
@@ -2052,79 +1757,38 @@ function readObjectProperty3(definition, propertyName) {
|
|
|
2052
1757
|
const initializer = unwrapExpression(property.getInitializer());
|
|
2053
1758
|
return initializer && Node5.isObjectLiteralExpression(initializer) ? initializer : void 0;
|
|
2054
1759
|
}
|
|
2055
|
-
function readStringProperty3(definition, propertyName) {
|
|
2056
|
-
const property = definition.getProperty(propertyName);
|
|
2057
|
-
if (!property || !Node5.isPropertyAssignment(property)) {
|
|
2058
|
-
return void 0;
|
|
2059
|
-
}
|
|
2060
|
-
const initializer = unwrapExpression(property.getInitializer());
|
|
2061
|
-
return initializer && Node5.isStringLiteral(initializer) ? initializer.getLiteralText() : void 0;
|
|
2062
|
-
}
|
|
2063
|
-
function readStringArrayProperty3(definition, propertyName) {
|
|
2064
|
-
const property = definition.getProperty(propertyName);
|
|
2065
|
-
if (!property || !Node5.isPropertyAssignment(property)) {
|
|
2066
|
-
return void 0;
|
|
2067
|
-
}
|
|
2068
|
-
const initializer = unwrapExpression(property.getInitializer());
|
|
2069
|
-
if (!initializer || !Node5.isArrayLiteralExpression(initializer)) {
|
|
2070
|
-
return void 0;
|
|
2071
|
-
}
|
|
2072
|
-
const values = initializer.getElements().map((element) => {
|
|
2073
|
-
const unwrapped = unwrapExpression(element);
|
|
2074
|
-
return unwrapped && Node5.isStringLiteral(unwrapped) ? unwrapped.getLiteralText() : void 0;
|
|
2075
|
-
});
|
|
2076
|
-
return values.every((value) => value !== void 0) ? values : void 0;
|
|
2077
|
-
}
|
|
2078
|
-
function readStringRecordProperty(definition, propertyName) {
|
|
2079
|
-
const object = readObjectProperty3(definition, propertyName);
|
|
2080
|
-
if (!object) {
|
|
2081
|
-
return void 0;
|
|
2082
|
-
}
|
|
2083
|
-
const record = {};
|
|
2084
|
-
for (const property of object.getProperties()) {
|
|
2085
|
-
if (!Node5.isPropertyAssignment(property)) {
|
|
2086
|
-
return void 0;
|
|
2087
|
-
}
|
|
2088
|
-
const initializer = unwrapExpression(property.getInitializer());
|
|
2089
|
-
if (!initializer || !Node5.isStringLiteral(initializer)) {
|
|
2090
|
-
return void 0;
|
|
2091
|
-
}
|
|
2092
|
-
record[property.getName().replace(/^["']|["']$/g, "")] = initializer.getLiteralText();
|
|
2093
|
-
}
|
|
2094
|
-
return record;
|
|
2095
|
-
}
|
|
2096
1760
|
function hasProperty(definition, propertyName) {
|
|
2097
1761
|
return Boolean(definition?.getProperty(propertyName));
|
|
2098
1762
|
}
|
|
2099
1763
|
|
|
2100
1764
|
// packages/compiler/src/diagnostics.ts
|
|
2101
|
-
import { existsSync as
|
|
1765
|
+
import { existsSync as existsSync3 } from "fs";
|
|
2102
1766
|
import { readFile as readFile2 } from "fs/promises";
|
|
2103
|
-
import
|
|
1767
|
+
import path6 from "path";
|
|
2104
1768
|
async function collectProjectDiagnostics(rootDir, input) {
|
|
2105
1769
|
const diagnostics = [];
|
|
2106
1770
|
const tools = Array.isArray(input) ? input : input.tools;
|
|
2107
1771
|
const resources = Array.isArray(input) ? [] : input.resources ?? [];
|
|
2108
1772
|
const prompts = Array.isArray(input) ? [] : input.prompts ?? [];
|
|
2109
1773
|
const config = Array.isArray(input) ? void 0 : input.config;
|
|
2110
|
-
const hasAuthConfig =
|
|
1774
|
+
const hasAuthConfig = existsSync3(path6.join(rootDir, "auth.ts"));
|
|
2111
1775
|
for (const entry of tools) {
|
|
2112
|
-
const toolPath =
|
|
1776
|
+
const toolPath = path6.join(rootDir, entry.sourceFile);
|
|
2113
1777
|
const toolSource = await readFile2(toolPath, "utf8");
|
|
2114
|
-
diagnostics.push(...diagnoseToolSource(entry, toolSource, hasAuthConfig));
|
|
1778
|
+
diagnostics.push(...diagnoseToolSource(rootDir, entry, toolSource, hasAuthConfig));
|
|
2115
1779
|
if (entry.widget) {
|
|
2116
|
-
const widgetPath =
|
|
1780
|
+
const widgetPath = path6.join(rootDir, entry.widget.sourceFile);
|
|
2117
1781
|
const widgetSource = await readFile2(widgetPath, "utf8");
|
|
2118
1782
|
diagnostics.push(...diagnoseWidgetSource(rootDir, entry, widgetSource));
|
|
2119
1783
|
}
|
|
2120
1784
|
}
|
|
2121
1785
|
for (const entry of resources) {
|
|
2122
|
-
const resourcePath =
|
|
1786
|
+
const resourcePath = path6.join(rootDir, entry.sourceFile);
|
|
2123
1787
|
const resourceSource = await readFile2(resourcePath, "utf8");
|
|
2124
1788
|
diagnostics.push(...diagnoseResourceSource(entry, resourceSource));
|
|
2125
1789
|
}
|
|
2126
1790
|
for (const entry of prompts) {
|
|
2127
|
-
const promptPath =
|
|
1791
|
+
const promptPath = path6.join(rootDir, entry.sourceFile);
|
|
2128
1792
|
const promptSource = await readFile2(promptPath, "utf8");
|
|
2129
1793
|
diagnostics.push(...diagnosePromptSource(entry, promptSource));
|
|
2130
1794
|
}
|
|
@@ -2139,7 +1803,7 @@ function formatDiagnostic(diagnostic) {
|
|
|
2139
1803
|
hint: ${diagnostic.hint}` : "";
|
|
2140
1804
|
return `${location} - ${diagnostic.severity} ${diagnostic.code}: ${diagnostic.message}${hint}`;
|
|
2141
1805
|
}
|
|
2142
|
-
function diagnoseToolSource(entry, source, hasAuthConfig) {
|
|
1806
|
+
function diagnoseToolSource(rootDir, entry, source, hasAuthConfig) {
|
|
2143
1807
|
const diagnostics = [];
|
|
2144
1808
|
const toolLocation = locate(source, "tool({");
|
|
2145
1809
|
if (!entry.description.trim().startsWith("Use this when")) {
|
|
@@ -2356,21 +2020,21 @@ function isIgnored(source, code) {
|
|
|
2356
2020
|
|
|
2357
2021
|
// packages/compiler/src/generated.ts
|
|
2358
2022
|
import { mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
|
|
2359
|
-
import
|
|
2023
|
+
import path7 from "path";
|
|
2360
2024
|
async function writeGeneratedTypes(rootDir, tools) {
|
|
2361
|
-
const generatedDir =
|
|
2025
|
+
const generatedDir = path7.join(rootDir, ".sidecar", "generated");
|
|
2362
2026
|
await mkdir2(generatedDir, { recursive: true });
|
|
2363
2027
|
const appCallableTools = tools.filter(isAppCallable);
|
|
2364
2028
|
const methodNames = uniqueMethodNames(appCallableTools.map((entry) => toIdentifier(entry.id)));
|
|
2365
2029
|
const imports = appCallableTools.map(
|
|
2366
|
-
(entry, index) => `import type tool${index} from ${JSON.stringify(toImportSpecifier(generatedDir,
|
|
2030
|
+
(entry, index) => `import type tool${index} from ${JSON.stringify(toImportSpecifier(generatedDir, path7.join(rootDir, entry.sourceFile), { extension: "js" }))};`
|
|
2367
2031
|
).join("\n");
|
|
2368
2032
|
const ids = appCallableTools.map((entry, index) => ` ${methodNames[index]}: ${JSON.stringify(entry.id)}`).join(",\n");
|
|
2369
2033
|
const toolTypes = appCallableTools.map(
|
|
2370
|
-
(
|
|
2034
|
+
(entry, index) => ` ${methodNames[index]}(params: ToolParams<typeof tool${index}>): Promise<ToolOutput<typeof tool${index}>>;`
|
|
2371
2035
|
).join("\n");
|
|
2372
2036
|
await writeFile2(
|
|
2373
|
-
|
|
2037
|
+
path7.join(generatedDir, "tools.ts"),
|
|
2374
2038
|
`/**
|
|
2375
2039
|
* Generated Sidecar widget tool client.
|
|
2376
2040
|
*
|
|
@@ -2420,13 +2084,13 @@ function uniqueMethodNames(names) {
|
|
|
2420
2084
|
|
|
2421
2085
|
// packages/compiler/src/identity.ts
|
|
2422
2086
|
import { readFile as readFile3 } from "fs/promises";
|
|
2423
|
-
import
|
|
2087
|
+
import path8 from "path";
|
|
2424
2088
|
async function loadProjectIdentity(rootDir) {
|
|
2425
|
-
const packageJson = await readOptionalJson(
|
|
2089
|
+
const packageJson = await readOptionalJson(path8.join(rootDir, "package.json"));
|
|
2426
2090
|
const configText = await readOptionalText(
|
|
2427
|
-
|
|
2091
|
+
path8.join(rootDir, "sidecar.config.ts")
|
|
2428
2092
|
);
|
|
2429
|
-
const name = readConfigString(configText, "name") ?? packageJson?.name ??
|
|
2093
|
+
const name = readConfigString(configText, "name") ?? packageJson?.name ?? path8.basename(rootDir);
|
|
2430
2094
|
const version = readConfigString(configText, "version") ?? packageJson?.version ?? "0.0.0-dev";
|
|
2431
2095
|
const description = readConfigString(configText, "description") ?? packageJson?.description ?? `${name} Sidecar app.`;
|
|
2432
2096
|
return {
|
|
@@ -2460,32 +2124,32 @@ function readConfigString(configText, key) {
|
|
|
2460
2124
|
|
|
2461
2125
|
// packages/compiler/src/plugins.ts
|
|
2462
2126
|
import { mkdir as mkdir7, writeFile as writeFile7 } from "fs/promises";
|
|
2463
|
-
import
|
|
2127
|
+
import path14 from "path";
|
|
2464
2128
|
|
|
2465
2129
|
// packages/compiler/src/plugin-components/agents.ts
|
|
2466
2130
|
import { mkdir as mkdir3, readdir as readdir2, readFile as readFile4, writeFile as writeFile3 } from "fs/promises";
|
|
2467
|
-
import
|
|
2131
|
+
import path9 from "path";
|
|
2468
2132
|
async function emitClaudeAgents(rootDir, destination) {
|
|
2469
|
-
const source =
|
|
2133
|
+
const source = path9.join(rootDir, "agents");
|
|
2470
2134
|
if (!existsSyncSafe(source)) {
|
|
2471
2135
|
return;
|
|
2472
2136
|
}
|
|
2473
2137
|
const entries = await readdir2(source, { withFileTypes: true });
|
|
2474
2138
|
const agentDirs = entries.filter(
|
|
2475
|
-
(entry) => entry.isDirectory() && existsSyncSafe(
|
|
2139
|
+
(entry) => entry.isDirectory() && existsSyncSafe(path9.join(source, entry.name, "agent.ts"))
|
|
2476
2140
|
);
|
|
2477
2141
|
if (!agentDirs.length) {
|
|
2478
2142
|
return;
|
|
2479
2143
|
}
|
|
2480
2144
|
await mkdir3(destination, { recursive: true });
|
|
2481
2145
|
for (const entry of agentDirs) {
|
|
2482
|
-
const sourceText = await readFile4(
|
|
2146
|
+
const sourceText = await readFile4(path9.join(source, entry.name, "agent.ts"), "utf8");
|
|
2483
2147
|
const markdown = parseClaudeAgent(
|
|
2484
2148
|
sourceText,
|
|
2485
2149
|
entry.name
|
|
2486
2150
|
);
|
|
2487
2151
|
const agentName = readObjectString(sourceText, "name") ?? entry.name;
|
|
2488
|
-
await writeFile3(
|
|
2152
|
+
await writeFile3(path9.join(destination, `${safeFileStem(agentName)}.md`), markdown);
|
|
2489
2153
|
}
|
|
2490
2154
|
}
|
|
2491
2155
|
function parseClaudeAgent(source, fallbackName) {
|
|
@@ -2514,41 +2178,41 @@ ${prompt.trim()}
|
|
|
2514
2178
|
|
|
2515
2179
|
// packages/compiler/src/plugin-components/commands.ts
|
|
2516
2180
|
import { cp, lstat, mkdir as mkdir4, readdir as readdir3, readFile as readFile5, writeFile as writeFile4 } from "fs/promises";
|
|
2517
|
-
import
|
|
2181
|
+
import path10 from "path";
|
|
2518
2182
|
async function copyCommands(rootDir, destination) {
|
|
2519
|
-
const source =
|
|
2183
|
+
const source = path10.join(rootDir, "commands");
|
|
2520
2184
|
if (!existsSyncSafe(source)) {
|
|
2521
2185
|
return;
|
|
2522
2186
|
}
|
|
2523
2187
|
await mkdir4(destination, { recursive: true });
|
|
2524
2188
|
const entries = await readdir3(source, { withFileTypes: true });
|
|
2525
2189
|
for (const entry of entries) {
|
|
2526
|
-
const sourcePath =
|
|
2190
|
+
const sourcePath = path10.join(source, entry.name);
|
|
2527
2191
|
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
2528
2192
|
if (await safeCommandCopyFilter(sourcePath)) {
|
|
2529
|
-
await cp(sourcePath,
|
|
2193
|
+
await cp(sourcePath, path10.join(destination, safeFileStem(entry.name.replace(/\.md$/, "")) + ".md"));
|
|
2530
2194
|
}
|
|
2531
2195
|
continue;
|
|
2532
2196
|
}
|
|
2533
2197
|
if (!entry.isDirectory()) {
|
|
2534
2198
|
continue;
|
|
2535
2199
|
}
|
|
2536
|
-
const dynamicCommand =
|
|
2200
|
+
const dynamicCommand = path10.join(sourcePath, "command.ts");
|
|
2537
2201
|
if (existsSyncSafe(dynamicCommand)) {
|
|
2538
2202
|
const sourceText = await readFile5(dynamicCommand, "utf8");
|
|
2539
2203
|
const markdown = parseDynamicCommand(sourceText, entry.name);
|
|
2540
2204
|
const commandName = readObjectString(sourceText, "name") ?? entry.name;
|
|
2541
|
-
await writeFile4(
|
|
2205
|
+
await writeFile4(path10.join(destination, `${safeFileStem(commandName)}.md`), markdown);
|
|
2542
2206
|
continue;
|
|
2543
2207
|
}
|
|
2544
|
-
await cp(sourcePath,
|
|
2208
|
+
await cp(sourcePath, path10.join(destination, entry.name), {
|
|
2545
2209
|
recursive: true,
|
|
2546
2210
|
filter: safeCommandCopyFilter
|
|
2547
2211
|
});
|
|
2548
2212
|
}
|
|
2549
2213
|
}
|
|
2550
2214
|
async function safeCommandCopyFilter(sourcePath) {
|
|
2551
|
-
const basename =
|
|
2215
|
+
const basename = path10.basename(sourcePath);
|
|
2552
2216
|
if (basename === ".env" || basename.startsWith(".env.") || basename === "node_modules" || basename === ".git") {
|
|
2553
2217
|
return false;
|
|
2554
2218
|
}
|
|
@@ -2577,32 +2241,32 @@ ${Object.entries(frontmatter).map(([key, value]) => `${key}: ${yamlScalar(value)
|
|
|
2577
2241
|
|
|
2578
2242
|
// packages/compiler/src/plugin-components/hooks.ts
|
|
2579
2243
|
import { mkdir as mkdir5, readdir as readdir4, readFile as readFile6, writeFile as writeFile5 } from "fs/promises";
|
|
2580
|
-
import
|
|
2244
|
+
import path11 from "path";
|
|
2581
2245
|
import {
|
|
2582
2246
|
Node as Node6,
|
|
2583
2247
|
Project as Project2,
|
|
2584
2248
|
SyntaxKind as SyntaxKind4
|
|
2585
2249
|
} from "ts-morph";
|
|
2586
2250
|
async function copyHooks(rootDir, destination) {
|
|
2587
|
-
const source =
|
|
2251
|
+
const source = path11.join(rootDir, "hooks");
|
|
2588
2252
|
if (!existsSyncSafe(source)) {
|
|
2589
2253
|
return;
|
|
2590
2254
|
}
|
|
2591
2255
|
const entries = await readdir4(source, { withFileTypes: true });
|
|
2592
2256
|
const hookDirs = entries.filter(
|
|
2593
|
-
(entry) => entry.isDirectory() && existsSyncSafe(
|
|
2257
|
+
(entry) => entry.isDirectory() && existsSyncSafe(path11.join(source, entry.name, "hook.ts"))
|
|
2594
2258
|
);
|
|
2595
2259
|
if (!hookDirs.length) {
|
|
2596
2260
|
return;
|
|
2597
2261
|
}
|
|
2598
2262
|
const config = {};
|
|
2599
2263
|
for (const entry of hookDirs) {
|
|
2600
|
-
const filePath =
|
|
2264
|
+
const filePath = path11.join(source, entry.name, "hook.ts");
|
|
2601
2265
|
mergeHooks(config, parseHookFile(await readFile6(filePath, "utf8"), entry.name));
|
|
2602
2266
|
}
|
|
2603
2267
|
await mkdir5(destination, { recursive: true });
|
|
2604
2268
|
await writeFile5(
|
|
2605
|
-
|
|
2269
|
+
path11.join(destination, "hooks.json"),
|
|
2606
2270
|
`${JSON.stringify(config, null, 2)}
|
|
2607
2271
|
`
|
|
2608
2272
|
);
|
|
@@ -2629,7 +2293,7 @@ function parseHookFile(source, fallbackName) {
|
|
|
2629
2293
|
throw new Error(`hooks/${fallbackName}/hook.ts must default-export hook({ ... }) or hooks({ ... }).`);
|
|
2630
2294
|
}
|
|
2631
2295
|
function parseHookDefinition(definition, fallbackName) {
|
|
2632
|
-
const event =
|
|
2296
|
+
const event = readStringProperty3(definition, "event");
|
|
2633
2297
|
if (!event) {
|
|
2634
2298
|
throw new Error(`hooks/${fallbackName}/hook.ts must declare an event string.`);
|
|
2635
2299
|
}
|
|
@@ -2639,7 +2303,7 @@ function parseHookDefinition(definition, fallbackName) {
|
|
|
2639
2303
|
}
|
|
2640
2304
|
return {
|
|
2641
2305
|
event,
|
|
2642
|
-
matcher:
|
|
2306
|
+
matcher: readStringProperty3(definition, "matcher"),
|
|
2643
2307
|
run: hooks
|
|
2644
2308
|
};
|
|
2645
2309
|
}
|
|
@@ -2659,7 +2323,7 @@ function parseHooksDefinition(definition, fallbackName) {
|
|
|
2659
2323
|
throw new Error(`hooks/${fallbackName}/hook.ts event "${event}" entries must be objects.`);
|
|
2660
2324
|
}
|
|
2661
2325
|
return stripUndefined2({
|
|
2662
|
-
matcher:
|
|
2326
|
+
matcher: readStringProperty3(entry, "matcher"),
|
|
2663
2327
|
hooks: readHookArray(entry, "run", fallbackName)
|
|
2664
2328
|
});
|
|
2665
2329
|
});
|
|
@@ -2682,7 +2346,7 @@ function parseHookHandlers(handlers, fallbackName) {
|
|
|
2682
2346
|
}
|
|
2683
2347
|
function parseHookHandler(handler, fallbackName) {
|
|
2684
2348
|
if (Node6.isObjectLiteralExpression(handler)) {
|
|
2685
|
-
const type =
|
|
2349
|
+
const type = readStringProperty3(handler, "type");
|
|
2686
2350
|
if (type !== "command" && type !== "http") {
|
|
2687
2351
|
throw new Error(`hooks/${fallbackName}/hook.ts hook handlers need type "command" or "http".`);
|
|
2688
2352
|
}
|
|
@@ -2732,7 +2396,7 @@ function objectLiteralToRecord(object) {
|
|
|
2732
2396
|
}
|
|
2733
2397
|
return stripUndefined2(record);
|
|
2734
2398
|
}
|
|
2735
|
-
function
|
|
2399
|
+
function readStringProperty3(object, propertyName) {
|
|
2736
2400
|
const property = object.getProperty(propertyName);
|
|
2737
2401
|
if (!property || !Node6.isPropertyAssignment(property)) {
|
|
2738
2402
|
return void 0;
|
|
@@ -2776,7 +2440,7 @@ function mergeHooks(target, source) {
|
|
|
2776
2440
|
|
|
2777
2441
|
// packages/compiler/src/plugin-components/passthrough.ts
|
|
2778
2442
|
import { cp as cp2, lstat as lstat2 } from "fs/promises";
|
|
2779
|
-
import
|
|
2443
|
+
import path12 from "path";
|
|
2780
2444
|
async function copyClaudePassthroughDirectories(rootDir, pluginDir) {
|
|
2781
2445
|
for (const directory of [
|
|
2782
2446
|
"assets",
|
|
@@ -2785,18 +2449,18 @@ async function copyClaudePassthroughDirectories(rootDir, pluginDir) {
|
|
|
2785
2449
|
"output-styles",
|
|
2786
2450
|
"themes"
|
|
2787
2451
|
]) {
|
|
2788
|
-
const source =
|
|
2452
|
+
const source = path12.join(rootDir, directory);
|
|
2789
2453
|
if (!existsSyncSafe(source)) {
|
|
2790
2454
|
continue;
|
|
2791
2455
|
}
|
|
2792
|
-
await cp2(source,
|
|
2456
|
+
await cp2(source, path12.join(pluginDir, directory), {
|
|
2793
2457
|
recursive: true,
|
|
2794
2458
|
filter: safePluginCopyFilter
|
|
2795
2459
|
});
|
|
2796
2460
|
}
|
|
2797
2461
|
}
|
|
2798
2462
|
async function safePluginCopyFilter(sourcePath) {
|
|
2799
|
-
const basename =
|
|
2463
|
+
const basename = path12.basename(sourcePath);
|
|
2800
2464
|
if (basename === "node_modules" || basename === ".git" || basename === ".env" || basename.startsWith(".env.")) {
|
|
2801
2465
|
return false;
|
|
2802
2466
|
}
|
|
@@ -2805,11 +2469,11 @@ async function safePluginCopyFilter(sourcePath) {
|
|
|
2805
2469
|
}
|
|
2806
2470
|
|
|
2807
2471
|
// packages/compiler/src/plugin-components/skills.ts
|
|
2808
|
-
import { existsSync as
|
|
2472
|
+
import { existsSync as existsSync4 } from "fs";
|
|
2809
2473
|
import { cp as cp3, lstat as lstat3, mkdir as mkdir6, readdir as readdir5, readFile as readFile7, writeFile as writeFile6 } from "fs/promises";
|
|
2810
|
-
import
|
|
2474
|
+
import path13 from "path";
|
|
2811
2475
|
async function copySkills(rootDir, destination) {
|
|
2812
|
-
const source =
|
|
2476
|
+
const source = path13.join(rootDir, "skills");
|
|
2813
2477
|
if (!existsSyncSafe(source)) {
|
|
2814
2478
|
return;
|
|
2815
2479
|
}
|
|
@@ -2819,27 +2483,27 @@ async function copySkills(rootDir, destination) {
|
|
|
2819
2483
|
if (!entry.isDirectory()) {
|
|
2820
2484
|
continue;
|
|
2821
2485
|
}
|
|
2822
|
-
const sourceDir =
|
|
2823
|
-
const destinationDir =
|
|
2824
|
-
const staticSkill =
|
|
2825
|
-
const dynamicSkill =
|
|
2486
|
+
const sourceDir = path13.join(source, entry.name);
|
|
2487
|
+
const destinationDir = path13.join(destination, entry.name);
|
|
2488
|
+
const staticSkill = path13.join(sourceDir, "SKILL.md");
|
|
2489
|
+
const dynamicSkill = path13.join(sourceDir, "skill.ts");
|
|
2826
2490
|
await mkdir6(destinationDir, { recursive: true });
|
|
2827
|
-
if (
|
|
2491
|
+
if (existsSync4(staticSkill)) {
|
|
2828
2492
|
await cp3(sourceDir, destinationDir, {
|
|
2829
2493
|
recursive: true,
|
|
2830
|
-
filter: async (sourcePath) => !sourcePath.endsWith(`${
|
|
2494
|
+
filter: async (sourcePath) => !sourcePath.endsWith(`${path13.sep}skill.ts`) && await safeSkillCopyFilter(sourcePath)
|
|
2831
2495
|
});
|
|
2832
|
-
} else if (
|
|
2496
|
+
} else if (existsSync4(dynamicSkill)) {
|
|
2833
2497
|
const generated = parseDynamicSkill(
|
|
2834
2498
|
await readFile7(dynamicSkill, "utf8"),
|
|
2835
2499
|
entry.name
|
|
2836
2500
|
);
|
|
2837
|
-
await writeFile6(
|
|
2501
|
+
await writeFile6(path13.join(destinationDir, "SKILL.md"), generated);
|
|
2838
2502
|
}
|
|
2839
2503
|
}
|
|
2840
2504
|
}
|
|
2841
2505
|
async function safeSkillCopyFilter(sourcePath) {
|
|
2842
|
-
const basename =
|
|
2506
|
+
const basename = path13.basename(sourcePath);
|
|
2843
2507
|
if (basename === ".env" || basename.startsWith(".env.") || basename === "node_modules" || basename === ".git") {
|
|
2844
2508
|
return false;
|
|
2845
2509
|
}
|
|
@@ -2865,25 +2529,25 @@ async function buildPluginPackages(rootDir, outRoot, manifest) {
|
|
|
2865
2529
|
await buildClaudePlugin(rootDir, outRoot, identity, manifest);
|
|
2866
2530
|
}
|
|
2867
2531
|
async function buildClaudePlugin(rootDir, outRoot, identity, manifest) {
|
|
2868
|
-
const pluginDir =
|
|
2869
|
-
await mkdir7(
|
|
2870
|
-
await copySkills(rootDir,
|
|
2871
|
-
await copyCommands(rootDir,
|
|
2872
|
-
await copyHooks(rootDir,
|
|
2873
|
-
await emitClaudeAgents(rootDir,
|
|
2532
|
+
const pluginDir = path14.join(outRoot, "claude-plugin");
|
|
2533
|
+
await mkdir7(path14.join(pluginDir, ".claude-plugin"), { recursive: true });
|
|
2534
|
+
await copySkills(rootDir, path14.join(pluginDir, "skills"));
|
|
2535
|
+
await copyCommands(rootDir, path14.join(pluginDir, "commands"));
|
|
2536
|
+
await copyHooks(rootDir, path14.join(pluginDir, "hooks"));
|
|
2537
|
+
await emitClaudeAgents(rootDir, path14.join(pluginDir, "agents"));
|
|
2874
2538
|
await copyClaudePassthroughDirectories(rootDir, pluginDir);
|
|
2875
|
-
await writeJson(
|
|
2539
|
+
await writeJson(path14.join(pluginDir, ".claude-plugin", "plugin.json"), {
|
|
2876
2540
|
name: identity.slug,
|
|
2877
2541
|
version: identity.version,
|
|
2878
2542
|
description: identity.description,
|
|
2879
2543
|
displayName: identity.name,
|
|
2880
2544
|
installationPreference: "available"
|
|
2881
2545
|
});
|
|
2882
|
-
await writeJson(
|
|
2546
|
+
await writeJson(path14.join(pluginDir, "version.json"), {
|
|
2883
2547
|
version: identity.version,
|
|
2884
2548
|
generatedBy: "sidecar"
|
|
2885
2549
|
});
|
|
2886
|
-
await writeJson(
|
|
2550
|
+
await writeJson(path14.join(pluginDir, ".mcp.json"), {
|
|
2887
2551
|
mcpServers: {
|
|
2888
2552
|
[identity.slug]: {
|
|
2889
2553
|
type: "http",
|
|
@@ -2891,7 +2555,7 @@ async function buildClaudePlugin(rootDir, outRoot, identity, manifest) {
|
|
|
2891
2555
|
}
|
|
2892
2556
|
}
|
|
2893
2557
|
});
|
|
2894
|
-
await writeJson(
|
|
2558
|
+
await writeJson(path14.join(pluginDir, "settings.json"), {
|
|
2895
2559
|
sidecar: {
|
|
2896
2560
|
tools: manifest.tools.map((entry) => entry.id),
|
|
2897
2561
|
resources: manifest.resources.map((entry) => entry.uri),
|
|
@@ -2899,7 +2563,7 @@ async function buildClaudePlugin(rootDir, outRoot, identity, manifest) {
|
|
|
2899
2563
|
}
|
|
2900
2564
|
});
|
|
2901
2565
|
await writeFile7(
|
|
2902
|
-
|
|
2566
|
+
path14.join(pluginDir, "README.md"),
|
|
2903
2567
|
`# ${identity.name} Claude Plugin
|
|
2904
2568
|
|
|
2905
2569
|
This package was generated by Sidecar.
|
|
@@ -2913,7 +2577,7 @@ Claude/Cowork plugin-specific components such as skills, slash commands, agents,
|
|
|
2913
2577
|
);
|
|
2914
2578
|
}
|
|
2915
2579
|
async function writeJson(filePath, value) {
|
|
2916
|
-
await mkdir7(
|
|
2580
|
+
await mkdir7(path14.dirname(filePath), { recursive: true });
|
|
2917
2581
|
await writeFile7(
|
|
2918
2582
|
filePath,
|
|
2919
2583
|
`${JSON.stringify(stripUndefined2(value), null, 2)}
|
|
@@ -2923,13 +2587,13 @@ async function writeJson(filePath, value) {
|
|
|
2923
2587
|
|
|
2924
2588
|
// packages/compiler/src/prompts.ts
|
|
2925
2589
|
import { readdir as readdir6 } from "fs/promises";
|
|
2926
|
-
import
|
|
2590
|
+
import path15 from "path";
|
|
2927
2591
|
import {
|
|
2928
2592
|
Node as Node7,
|
|
2929
2593
|
SyntaxKind as SyntaxKind5
|
|
2930
2594
|
} from "ts-morph";
|
|
2931
2595
|
async function analyzeProjectPrompts(rootDir) {
|
|
2932
|
-
const promptFiles = await findPromptFiles(
|
|
2596
|
+
const promptFiles = await findPromptFiles(path15.join(rootDir, "prompts"));
|
|
2933
2597
|
if (promptFiles.length === 0) {
|
|
2934
2598
|
return [];
|
|
2935
2599
|
}
|
|
@@ -2941,7 +2605,7 @@ async function analyzeProjectPrompts(rootDir) {
|
|
|
2941
2605
|
function analyzePromptFile(sourceFile, rootDir) {
|
|
2942
2606
|
const definition = findPromptDefinition(sourceFile);
|
|
2943
2607
|
const absoluteFile = sourceFile.getFilePath();
|
|
2944
|
-
const directory =
|
|
2608
|
+
const directory = path15.basename(path15.dirname(absoluteFile));
|
|
2945
2609
|
const name = getOptionalStringProperty2(definition, "name") ?? safePathSegment(directory);
|
|
2946
2610
|
const title = getRequiredStringProperty2(definition, "title", sourceFile);
|
|
2947
2611
|
const description = getOptionalStringProperty2(definition, "description");
|
|
@@ -2957,7 +2621,7 @@ function analyzePromptFile(sourceFile, rootDir) {
|
|
|
2957
2621
|
throw new CompilerError(sourceFile, "prompt({ ... }) must include a run method.");
|
|
2958
2622
|
}
|
|
2959
2623
|
return {
|
|
2960
|
-
sourceFile:
|
|
2624
|
+
sourceFile: path15.relative(rootDir, absoluteFile),
|
|
2961
2625
|
directory,
|
|
2962
2626
|
name,
|
|
2963
2627
|
title,
|
|
@@ -2976,7 +2640,7 @@ async function findPromptFiles(promptsDir) {
|
|
|
2976
2640
|
if (!entry.isDirectory()) {
|
|
2977
2641
|
continue;
|
|
2978
2642
|
}
|
|
2979
|
-
const filePath =
|
|
2643
|
+
const filePath = path15.join(promptsDir, entry.name, "prompt.ts");
|
|
2980
2644
|
if (existsSyncSafe(filePath)) {
|
|
2981
2645
|
files.push(filePath);
|
|
2982
2646
|
}
|
|
@@ -3098,7 +2762,7 @@ function readIcons(definition) {
|
|
|
3098
2762
|
return [{
|
|
3099
2763
|
src,
|
|
3100
2764
|
mimeType: getOptionalStringProperty2(object, "mimeType"),
|
|
3101
|
-
sizes:
|
|
2765
|
+
sizes: readStringArrayProperty3(object, "sizes")
|
|
3102
2766
|
}];
|
|
3103
2767
|
});
|
|
3104
2768
|
return icons.length ? icons : void 0;
|
|
@@ -3111,7 +2775,7 @@ function readObjectProperty4(definition, propertyName) {
|
|
|
3111
2775
|
const initializer = unwrapExpression(property.getInitializer());
|
|
3112
2776
|
return initializer && Node7.isObjectLiteralExpression(initializer) ? initializer : void 0;
|
|
3113
2777
|
}
|
|
3114
|
-
function
|
|
2778
|
+
function readStringArrayProperty3(definition, propertyName) {
|
|
3115
2779
|
const property = definition.getProperty(propertyName);
|
|
3116
2780
|
if (!property || !Node7.isPropertyAssignment(property)) {
|
|
3117
2781
|
return void 0;
|
|
@@ -3125,13 +2789,13 @@ function readStringArrayProperty4(definition, propertyName) {
|
|
|
3125
2789
|
|
|
3126
2790
|
// packages/compiler/src/resources.ts
|
|
3127
2791
|
import { readdir as readdir7 } from "fs/promises";
|
|
3128
|
-
import
|
|
2792
|
+
import path16 from "path";
|
|
3129
2793
|
import {
|
|
3130
2794
|
Node as Node8,
|
|
3131
2795
|
SyntaxKind as SyntaxKind6
|
|
3132
2796
|
} from "ts-morph";
|
|
3133
2797
|
async function analyzeProjectResources(rootDir) {
|
|
3134
|
-
const resourceFiles = await findResourceFiles(
|
|
2798
|
+
const resourceFiles = await findResourceFiles(path16.join(rootDir, "resources"));
|
|
3135
2799
|
if (resourceFiles.length === 0) {
|
|
3136
2800
|
return [];
|
|
3137
2801
|
}
|
|
@@ -3143,7 +2807,7 @@ async function analyzeProjectResources(rootDir) {
|
|
|
3143
2807
|
function analyzeResourceFile(sourceFile, rootDir) {
|
|
3144
2808
|
const definition = findResourceDefinition(sourceFile);
|
|
3145
2809
|
const absoluteFile = sourceFile.getFilePath();
|
|
3146
|
-
const directory =
|
|
2810
|
+
const directory = path16.basename(path16.dirname(absoluteFile));
|
|
3147
2811
|
const defaultUri = `sidecar://resources/${safePathSegment(directory)}`;
|
|
3148
2812
|
const name = getRequiredStringProperty3(definition, "name", sourceFile);
|
|
3149
2813
|
const uri = getOptionalStringProperty3(definition, "uri") ?? defaultUri;
|
|
@@ -3161,7 +2825,7 @@ function analyzeResourceFile(sourceFile, rootDir) {
|
|
|
3161
2825
|
throw new CompilerError(sourceFile, "resource({ ... }) must include a read method.");
|
|
3162
2826
|
}
|
|
3163
2827
|
return {
|
|
3164
|
-
sourceFile:
|
|
2828
|
+
sourceFile: path16.relative(rootDir, absoluteFile),
|
|
3165
2829
|
directory,
|
|
3166
2830
|
uri,
|
|
3167
2831
|
name,
|
|
@@ -3184,7 +2848,7 @@ async function findResourceFiles(resourcesDir) {
|
|
|
3184
2848
|
if (!entry.isDirectory()) {
|
|
3185
2849
|
continue;
|
|
3186
2850
|
}
|
|
3187
|
-
const filePath =
|
|
2851
|
+
const filePath = path16.join(resourcesDir, entry.name, "resource.ts");
|
|
3188
2852
|
if (existsSyncSafe(filePath)) {
|
|
3189
2853
|
files.push(filePath);
|
|
3190
2854
|
}
|
|
@@ -3263,7 +2927,7 @@ function readAnnotations2(definition) {
|
|
|
3263
2927
|
return void 0;
|
|
3264
2928
|
}
|
|
3265
2929
|
const annotations = {};
|
|
3266
|
-
const audience =
|
|
2930
|
+
const audience = readStringArrayProperty4(initializer, "audience")?.filter((value) => value === "user" || value === "assistant");
|
|
3267
2931
|
const priority = getOptionalNumberProperty(initializer, "priority");
|
|
3268
2932
|
const lastModified = getOptionalStringProperty3(initializer, "lastModified");
|
|
3269
2933
|
if (audience?.length) annotations.audience = audience;
|
|
@@ -3292,7 +2956,7 @@ function readIcons2(definition) {
|
|
|
3292
2956
|
return [{
|
|
3293
2957
|
src,
|
|
3294
2958
|
mimeType: getOptionalStringProperty3(object, "mimeType"),
|
|
3295
|
-
sizes:
|
|
2959
|
+
sizes: readStringArrayProperty4(object, "sizes")
|
|
3296
2960
|
}];
|
|
3297
2961
|
});
|
|
3298
2962
|
return icons.length ? icons : void 0;
|
|
@@ -3305,7 +2969,7 @@ function readObjectProperty5(definition, propertyName) {
|
|
|
3305
2969
|
const initializer = unwrapExpression(property.getInitializer());
|
|
3306
2970
|
return initializer && Node8.isObjectLiteralExpression(initializer) ? initializer : void 0;
|
|
3307
2971
|
}
|
|
3308
|
-
function
|
|
2972
|
+
function readStringArrayProperty4(definition, propertyName) {
|
|
3309
2973
|
const property = definition.getProperty(propertyName);
|
|
3310
2974
|
if (!property || !Node8.isPropertyAssignment(property)) {
|
|
3311
2975
|
return void 0;
|
|
@@ -3318,21 +2982,19 @@ function readStringArrayProperty5(definition, propertyName) {
|
|
|
3318
2982
|
}
|
|
3319
2983
|
|
|
3320
2984
|
// packages/compiler/src/server-output.ts
|
|
3321
|
-
import { existsSync as
|
|
2985
|
+
import { existsSync as existsSync5 } from "fs";
|
|
3322
2986
|
import { mkdir as mkdir8, rm, writeFile as writeFile8 } from "fs/promises";
|
|
3323
|
-
import
|
|
2987
|
+
import path17 from "path";
|
|
3324
2988
|
import { build as esbuild2 } from "esbuild";
|
|
3325
2989
|
var SERVER_ENTRYPOINT = "server/index.js";
|
|
3326
|
-
var
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
async function buildServerOutput(rootDir, outDir, manifest, identity, host = "node", options = {}) {
|
|
3330
|
-
const cacheDir = path18.join(rootDir, ".sidecar", "cache", "server");
|
|
2990
|
+
var VERCEL_ENTRYPOINT = "api/sidecar.js";
|
|
2991
|
+
async function buildServerOutput(rootDir, outDir, manifest, identity, host = "node") {
|
|
2992
|
+
const cacheDir = path17.join(rootDir, ".sidecar", "cache", "server");
|
|
3331
2993
|
await mkdir8(cacheDir, { recursive: true });
|
|
3332
|
-
const entryFile =
|
|
2994
|
+
const entryFile = path17.join(cacheDir, "index.ts");
|
|
3333
2995
|
await writeFile8(entryFile, renderServerEntry(rootDir, entryFile, manifest, identity));
|
|
3334
|
-
const serverFile =
|
|
3335
|
-
await mkdir8(
|
|
2996
|
+
const serverFile = path17.join(outDir, SERVER_ENTRYPOINT);
|
|
2997
|
+
await mkdir8(path17.dirname(serverFile), { recursive: true });
|
|
3336
2998
|
await esbuild2({
|
|
3337
2999
|
absWorkingDir: rootDir,
|
|
3338
3000
|
alias: sidecarBundleAliases(rootDir),
|
|
@@ -3346,30 +3008,26 @@ const require = __sidecarCreateRequire(import.meta.url);`
|
|
|
3346
3008
|
legalComments: "none",
|
|
3347
3009
|
minify: false,
|
|
3348
3010
|
nodePaths: [
|
|
3349
|
-
|
|
3350
|
-
|
|
3011
|
+
path17.join(rootDir, "node_modules"),
|
|
3012
|
+
path17.join(process.cwd(), "node_modules")
|
|
3351
3013
|
],
|
|
3352
3014
|
outfile: serverFile,
|
|
3353
3015
|
platform: "node",
|
|
3354
3016
|
sourcemap: false,
|
|
3355
3017
|
target: "node20"
|
|
3356
3018
|
});
|
|
3357
|
-
await writeFile8(
|
|
3019
|
+
await writeFile8(path17.join(outDir, "package.json"), renderServerPackage(identity));
|
|
3358
3020
|
if (host === "vercel") {
|
|
3359
|
-
|
|
3360
|
-
await
|
|
3361
|
-
await
|
|
3362
|
-
await writeFile8(path18.join(outDir, VERCEL_HANDLER_FILE), renderVercelEntrypoint());
|
|
3363
|
-
await writeFile8(path18.join(outDir, ".vc-config.json"), renderVercelFunctionConfig());
|
|
3364
|
-
await mkdir8(vercelOutputDir, { recursive: true });
|
|
3365
|
-
await writeFile8(path18.join(vercelOutputDir, "config.json"), renderVercelOutputConfig());
|
|
3021
|
+
await mkdir8(path17.join(outDir, "api"), { recursive: true });
|
|
3022
|
+
await writeFile8(path17.join(outDir, VERCEL_ENTRYPOINT), renderVercelEntrypoint());
|
|
3023
|
+
await writeFile8(path17.join(outDir, "vercel.json"), renderVercelConfig());
|
|
3366
3024
|
} else {
|
|
3367
|
-
await rm(
|
|
3368
|
-
await rm(
|
|
3025
|
+
await rm(path17.join(outDir, "api"), { recursive: true, force: true });
|
|
3026
|
+
await rm(path17.join(outDir, "vercel.json"), { force: true });
|
|
3369
3027
|
}
|
|
3370
3028
|
}
|
|
3371
3029
|
function renderServerEntry(rootDir, entryFile, manifest, identity) {
|
|
3372
|
-
const entryDir =
|
|
3030
|
+
const entryDir = path17.dirname(entryFile);
|
|
3373
3031
|
const tools = manifest.tools;
|
|
3374
3032
|
const resources = manifest.resources;
|
|
3375
3033
|
const prompts = manifest.prompts;
|
|
@@ -3382,17 +3040,17 @@ function renderServerEntry(rootDir, entryFile, manifest, identity) {
|
|
|
3382
3040
|
`import { isSidecarPrompt, isSidecarResource, isSidecarTool } from "@sidecar-ai/core";`,
|
|
3383
3041
|
`import { isSidecarProxy } from "@sidecar-ai/server/proxy";`,
|
|
3384
3042
|
...tools.map(
|
|
3385
|
-
(entry, index) => `import tool${index} from ${JSON.stringify(toImportSpecifier(entryDir,
|
|
3043
|
+
(entry, index) => `import tool${index} from ${JSON.stringify(toImportSpecifier(entryDir, path17.join(rootDir, entry.sourceFile)))};`
|
|
3386
3044
|
),
|
|
3387
3045
|
...resources.map(
|
|
3388
|
-
(entry, index) => `import resource${index} from ${JSON.stringify(toImportSpecifier(entryDir,
|
|
3046
|
+
(entry, index) => `import resource${index} from ${JSON.stringify(toImportSpecifier(entryDir, path17.join(rootDir, entry.sourceFile)))};`
|
|
3389
3047
|
),
|
|
3390
3048
|
...prompts.map(
|
|
3391
|
-
(entry, index) => `import prompt${index} from ${JSON.stringify(toImportSpecifier(entryDir,
|
|
3049
|
+
(entry, index) => `import prompt${index} from ${JSON.stringify(toImportSpecifier(entryDir, path17.join(rootDir, entry.sourceFile)))};`
|
|
3392
3050
|
),
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3051
|
+
existsSync5(path17.join(rootDir, "auth.ts")) ? `import authExport from ${JSON.stringify(toImportSpecifier(entryDir, path17.join(rootDir, "auth.ts")))};` : `const authExport = undefined;`,
|
|
3052
|
+
existsSync5(path17.join(rootDir, "proxy.ts")) ? `import proxyExport from ${JSON.stringify(toImportSpecifier(entryDir, path17.join(rootDir, "proxy.ts")))};` : `const proxyExport = undefined;`,
|
|
3053
|
+
existsSync5(path17.join(rootDir, "sidecar.config.ts")) ? `import configExport from ${JSON.stringify(toImportSpecifier(entryDir, path17.join(rootDir, "sidecar.config.ts")))};` : `const configExport = undefined;`
|
|
3396
3054
|
].join("\n");
|
|
3397
3055
|
return `${imports}
|
|
3398
3056
|
|
|
@@ -3503,7 +3161,7 @@ function unwrapRuntimeDefault(value) {
|
|
|
3503
3161
|
value &&
|
|
3504
3162
|
typeof value === "object" &&
|
|
3505
3163
|
"default" in value &&
|
|
3506
|
-
Object.keys(value).
|
|
3164
|
+
Object.keys(value).length === 1
|
|
3507
3165
|
) {
|
|
3508
3166
|
return unwrapRuntimeDefault(value.default);
|
|
3509
3167
|
}
|
|
@@ -3563,29 +3221,23 @@ function renderServerPackage(identity) {
|
|
|
3563
3221
|
`;
|
|
3564
3222
|
}
|
|
3565
3223
|
function renderVercelEntrypoint() {
|
|
3566
|
-
return `export { default } from "
|
|
3567
|
-
`;
|
|
3568
|
-
}
|
|
3569
|
-
function renderVercelFunctionConfig() {
|
|
3570
|
-
return `${JSON.stringify({
|
|
3571
|
-
runtime: "nodejs22.x",
|
|
3572
|
-
handler: VERCEL_HANDLER_FILE,
|
|
3573
|
-
launcherType: "Nodejs",
|
|
3574
|
-
shouldAddHelpers: true,
|
|
3575
|
-
supportsResponseStreaming: true,
|
|
3576
|
-
maxDuration: 300
|
|
3577
|
-
}, null, 2)}
|
|
3224
|
+
return `export { default } from "../server/index.js";
|
|
3578
3225
|
`;
|
|
3579
3226
|
}
|
|
3580
|
-
function
|
|
3227
|
+
function renderVercelConfig() {
|
|
3581
3228
|
return `${JSON.stringify({
|
|
3582
|
-
|
|
3583
|
-
routes: [
|
|
3229
|
+
rewrites: [
|
|
3584
3230
|
{
|
|
3585
|
-
|
|
3586
|
-
|
|
3231
|
+
source: "/(.*)",
|
|
3232
|
+
destination: "/api/sidecar"
|
|
3587
3233
|
}
|
|
3588
|
-
]
|
|
3234
|
+
],
|
|
3235
|
+
functions: {
|
|
3236
|
+
"api/sidecar.js": {
|
|
3237
|
+
includeFiles: "public/**",
|
|
3238
|
+
maxDuration: 300
|
|
3239
|
+
}
|
|
3240
|
+
}
|
|
3589
3241
|
}, null, 2)}
|
|
3590
3242
|
`;
|
|
3591
3243
|
}
|
|
@@ -3595,35 +3247,35 @@ function sidecarBundleAliases(rootDir) {
|
|
|
3595
3247
|
return void 0;
|
|
3596
3248
|
}
|
|
3597
3249
|
return {
|
|
3598
|
-
"sidecar-ai":
|
|
3599
|
-
"@sidecar-ai/auth":
|
|
3600
|
-
"@sidecar-ai/core":
|
|
3601
|
-
"@sidecar-ai/server":
|
|
3602
|
-
"@sidecar-ai/server/proxy":
|
|
3603
|
-
"@sidecar-ai/client":
|
|
3604
|
-
"@sidecar-ai/react":
|
|
3605
|
-
"@sidecar-ai/native":
|
|
3606
|
-
"@sidecar-ai/native/components":
|
|
3607
|
-
"@sidecar-ai/openai":
|
|
3608
|
-
"@sidecar-ai/openai/components":
|
|
3609
|
-
"@sidecar-ai/openai/official":
|
|
3610
|
-
"@sidecar-ai/anthropic":
|
|
3611
|
-
"@sidecar-ai/anthropic/agent":
|
|
3612
|
-
"@sidecar-ai/anthropic/command":
|
|
3613
|
-
"@sidecar-ai/anthropic/components":
|
|
3614
|
-
"@sidecar-ai/anthropic/hooks":
|
|
3615
|
-
"@sidecar-ai/anthropic/mcp":
|
|
3616
|
-
"@sidecar-ai/anthropic/plugin":
|
|
3617
|
-
"@sidecar-ai/anthropic/skill":
|
|
3250
|
+
"sidecar-ai": path17.join(repoRoot, "packages", "sidecar-ai", "src", "index.ts"),
|
|
3251
|
+
"@sidecar-ai/auth": path17.join(repoRoot, "packages", "auth", "src", "index.ts"),
|
|
3252
|
+
"@sidecar-ai/core": path17.join(repoRoot, "packages", "core", "src", "index.ts"),
|
|
3253
|
+
"@sidecar-ai/server": path17.join(repoRoot, "packages", "server", "src", "index.ts"),
|
|
3254
|
+
"@sidecar-ai/server/proxy": path17.join(repoRoot, "packages", "server", "src", "proxy.ts"),
|
|
3255
|
+
"@sidecar-ai/client": path17.join(repoRoot, "packages", "client", "src", "index.ts"),
|
|
3256
|
+
"@sidecar-ai/react": path17.join(repoRoot, "packages", "react", "src", "index.ts"),
|
|
3257
|
+
"@sidecar-ai/native": path17.join(repoRoot, "packages", "native", "src", "index.ts"),
|
|
3258
|
+
"@sidecar-ai/native/components": path17.join(repoRoot, "packages", "native", "src", "components", "index.tsx"),
|
|
3259
|
+
"@sidecar-ai/openai": path17.join(repoRoot, "packages", "openai", "src", "index.ts"),
|
|
3260
|
+
"@sidecar-ai/openai/components": path17.join(repoRoot, "packages", "openai", "src", "components.tsx"),
|
|
3261
|
+
"@sidecar-ai/openai/official": path17.join(repoRoot, "packages", "openai", "src", "official.ts"),
|
|
3262
|
+
"@sidecar-ai/anthropic": path17.join(repoRoot, "packages", "anthropic", "src", "index.ts"),
|
|
3263
|
+
"@sidecar-ai/anthropic/agent": path17.join(repoRoot, "packages", "anthropic", "src", "agent.ts"),
|
|
3264
|
+
"@sidecar-ai/anthropic/command": path17.join(repoRoot, "packages", "anthropic", "src", "command.ts"),
|
|
3265
|
+
"@sidecar-ai/anthropic/components": path17.join(repoRoot, "packages", "anthropic", "src", "components.tsx"),
|
|
3266
|
+
"@sidecar-ai/anthropic/hooks": path17.join(repoRoot, "packages", "anthropic", "src", "hooks.ts"),
|
|
3267
|
+
"@sidecar-ai/anthropic/mcp": path17.join(repoRoot, "packages", "anthropic", "src", "mcp.ts"),
|
|
3268
|
+
"@sidecar-ai/anthropic/plugin": path17.join(repoRoot, "packages", "anthropic", "src", "plugin.ts"),
|
|
3269
|
+
"@sidecar-ai/anthropic/skill": path17.join(repoRoot, "packages", "anthropic", "src", "skill.ts")
|
|
3618
3270
|
};
|
|
3619
3271
|
}
|
|
3620
3272
|
function findSidecarRepoRoot2(startDir) {
|
|
3621
|
-
let current =
|
|
3273
|
+
let current = path17.resolve(startDir);
|
|
3622
3274
|
while (true) {
|
|
3623
|
-
if (
|
|
3275
|
+
if (existsSync5(path17.join(current, "packages", "core", "src", "index.ts"))) {
|
|
3624
3276
|
return current;
|
|
3625
3277
|
}
|
|
3626
|
-
const parent =
|
|
3278
|
+
const parent = path17.dirname(current);
|
|
3627
3279
|
if (parent === current) {
|
|
3628
3280
|
return void 0;
|
|
3629
3281
|
}
|
|
@@ -3633,11 +3285,10 @@ function findSidecarRepoRoot2(startDir) {
|
|
|
3633
3285
|
|
|
3634
3286
|
// packages/compiler/src/build.ts
|
|
3635
3287
|
async function buildProject(options) {
|
|
3636
|
-
const rootDir =
|
|
3288
|
+
const rootDir = path18.resolve(options.rootDir);
|
|
3289
|
+
const target = options.target ?? "mcp";
|
|
3290
|
+
const host = options.host ?? "node";
|
|
3637
3291
|
const config = analyzeProjectConfig(rootDir);
|
|
3638
|
-
const target = options.target ?? config.build.target ?? "mcp";
|
|
3639
|
-
const host = options.host ?? config.build.host ?? "node";
|
|
3640
|
-
const plugins = options.plugins ?? config.build.plugins ?? false;
|
|
3641
3292
|
const tools = await analyzeProjectTools(rootDir, { target });
|
|
3642
3293
|
const resources = await analyzeProjectResources(rootDir);
|
|
3643
3294
|
const resourceTemplates = [];
|
|
@@ -3653,9 +3304,8 @@ async function buildProject(options) {
|
|
|
3653
3304
|
if (errors.length) {
|
|
3654
3305
|
throw new Error(errors.map(formatDiagnostic).join("\n"));
|
|
3655
3306
|
}
|
|
3656
|
-
const outDir = resolveInsideRoot(rootDir, options.outDir ??
|
|
3657
|
-
|
|
3658
|
-
await buildWidgets(rootDir, runtimeOutDir, tools, config.build.widgets);
|
|
3307
|
+
const outDir = resolveInsideRoot(rootDir, options.outDir ?? "out/mcp");
|
|
3308
|
+
await buildWidgets(rootDir, outDir, tools);
|
|
3659
3309
|
const manifest = {
|
|
3660
3310
|
version: 1,
|
|
3661
3311
|
target,
|
|
@@ -3669,47 +3319,24 @@ async function buildProject(options) {
|
|
|
3669
3319
|
prompts,
|
|
3670
3320
|
diagnostics
|
|
3671
3321
|
};
|
|
3672
|
-
await mkdir9(
|
|
3322
|
+
await mkdir9(outDir, { recursive: true });
|
|
3673
3323
|
await writeFile9(
|
|
3674
|
-
|
|
3324
|
+
path18.join(outDir, "manifest.sidecar.json"),
|
|
3675
3325
|
`${JSON.stringify(manifest, null, 2)}
|
|
3676
3326
|
`
|
|
3677
3327
|
);
|
|
3678
|
-
await writeFile9(
|
|
3328
|
+
await writeFile9(path18.join(outDir, "README.md"), renderMcpReadme(manifest));
|
|
3679
3329
|
await writeGeneratedTypes(rootDir, tools);
|
|
3680
|
-
await buildServerOutput(rootDir,
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
if (plugins) {
|
|
3684
|
-
await buildPluginPackages(rootDir, resolvePluginOutputBase(rootDir, outDir, host), manifest);
|
|
3330
|
+
await buildServerOutput(rootDir, outDir, manifest, identity, host);
|
|
3331
|
+
if (options.plugins) {
|
|
3332
|
+
await buildPluginPackages(rootDir, path18.dirname(outDir), manifest);
|
|
3685
3333
|
}
|
|
3686
3334
|
return manifest;
|
|
3687
3335
|
}
|
|
3688
|
-
function defaultBuildOutDir(host, target) {
|
|
3689
|
-
if (host === "vercel") {
|
|
3690
|
-
return ".vercel/output";
|
|
3691
|
-
}
|
|
3692
|
-
return `out/${target}`;
|
|
3693
|
-
}
|
|
3694
|
-
function resolveRuntimeOutputDir(outDir, host) {
|
|
3695
|
-
if (host === "vercel") {
|
|
3696
|
-
return path19.join(outDir, VERCEL_FUNCTION_DIR);
|
|
3697
|
-
}
|
|
3698
|
-
return outDir;
|
|
3699
|
-
}
|
|
3700
|
-
function resolvePluginOutputBase(rootDir, outDir, host) {
|
|
3701
|
-
if (host === "vercel" && isVercelBuildOutputDir(outDir)) {
|
|
3702
|
-
return path19.join(rootDir, "out");
|
|
3703
|
-
}
|
|
3704
|
-
return path19.dirname(outDir);
|
|
3705
|
-
}
|
|
3706
|
-
function isVercelBuildOutputDir(outDir) {
|
|
3707
|
-
return path19.basename(outDir) === "output" && path19.basename(path19.dirname(outDir)) === ".vercel";
|
|
3708
|
-
}
|
|
3709
3336
|
function resolveInsideRoot(rootDir, output) {
|
|
3710
|
-
const resolved =
|
|
3711
|
-
const relative =
|
|
3712
|
-
if (relative.startsWith("..") ||
|
|
3337
|
+
const resolved = path18.resolve(rootDir, output);
|
|
3338
|
+
const relative = path18.relative(rootDir, resolved);
|
|
3339
|
+
if (relative.startsWith("..") || path18.isAbsolute(relative)) {
|
|
3713
3340
|
throw new Error(`Build output must stay inside the project root: ${output}`);
|
|
3714
3341
|
}
|
|
3715
3342
|
return resolved;
|
|
@@ -3762,7 +3389,7 @@ Set \`PORT\` or \`SIDECAR_PORT\` to choose the listen port. Hosted/authenticated
|
|
|
3762
3389
|
function renderVercelReadmeSection() {
|
|
3763
3390
|
return `## Deploy To Vercel
|
|
3764
3391
|
|
|
3765
|
-
This output
|
|
3392
|
+
This output includes a Vercel Function shim at \`api/sidecar.js\` and a \`vercel.json\` rewrite that sends Streamable HTTP traffic to \`/mcp\`. Deploy this output directory with Vercel and set \`SIDECAR_MCP_URL\` to the public \`https://.../mcp\` URL.
|
|
3766
3393
|
`;
|
|
3767
3394
|
}
|
|
3768
3395
|
|
|
@@ -4064,7 +3691,7 @@ var SidecarMcpServer = class {
|
|
|
4064
3691
|
/** Returns the server-chosen page size for all built-in list pagination. */
|
|
4065
3692
|
pageSize() {
|
|
4066
3693
|
const configured = this.options.pagination?.pageSize;
|
|
4067
|
-
return configured && configured > 0 ? Math.floor(configured) :
|
|
3694
|
+
return configured && configured > 0 ? Math.floor(configured) : 10;
|
|
4068
3695
|
}
|
|
4069
3696
|
/** Executes a tool after request-level and tool-level auth checks. */
|
|
4070
3697
|
async callTool(request, context) {
|
|
@@ -4173,7 +3800,6 @@ var SidecarMcpServer = class {
|
|
|
4173
3800
|
});
|
|
4174
3801
|
}
|
|
4175
3802
|
return {
|
|
4176
|
-
_meta: resource._meta,
|
|
4177
3803
|
contents: [
|
|
4178
3804
|
{
|
|
4179
3805
|
uri,
|
|
@@ -4273,11 +3899,6 @@ function createSidecarHttpHandler(options) {
|
|
|
4273
3899
|
const streamHub = createSseHub();
|
|
4274
3900
|
const mcp = createSidecarMcpServer(options);
|
|
4275
3901
|
return async (request, response) => {
|
|
4276
|
-
const pathname = request.url?.split("?")[0];
|
|
4277
|
-
const requestLog = createHttpRequestLog(request, pathname);
|
|
4278
|
-
response.once("finish", () => {
|
|
4279
|
-
logHttpRequest(requestLog, response.statusCode);
|
|
4280
|
-
});
|
|
4281
3902
|
if (isRejectedOrigin(request, options.allowedOrigins)) {
|
|
4282
3903
|
response.writeHead(403, { "content-type": "application/json" });
|
|
4283
3904
|
response.end(JSON.stringify({ error: "forbidden_origin" }));
|
|
@@ -4289,17 +3910,16 @@ function createSidecarHttpHandler(options) {
|
|
|
4289
3910
|
response.end(proxyResult.body ?? "");
|
|
4290
3911
|
return;
|
|
4291
3912
|
}
|
|
3913
|
+
const pathname = request.url?.split("?")[0];
|
|
4292
3914
|
if (options.auth && request.method === "GET" && isProtectedResourceMetadataPath(pathname, endpoint)) {
|
|
4293
3915
|
response.writeHead(200, { "content-type": "application/json" });
|
|
4294
3916
|
response.end(JSON.stringify(options.auth.metadata()));
|
|
4295
3917
|
return;
|
|
4296
3918
|
}
|
|
4297
|
-
if (options.auth && request.method === "GET" && pathname === "/.well-known/oauth-authorization-server") {
|
|
4298
|
-
await proxyAuthorizationServerMetadata(options.auth, response);
|
|
4299
|
-
return;
|
|
4300
|
-
}
|
|
4301
3919
|
if (request.method === "GET" && pathname === endpoint) {
|
|
4302
3920
|
try {
|
|
3921
|
+
validateProtocolVersion(request);
|
|
3922
|
+
validateGetHeaders(request);
|
|
4303
3923
|
const fetchRequest = toFetchRequest(request, options.publicUrl ?? options.auth?.resource);
|
|
4304
3924
|
if (options.auth) {
|
|
4305
3925
|
const authSession = await authorizeHttpRequest(options.auth, fetchRequest, response);
|
|
@@ -4307,8 +3927,6 @@ function createSidecarHttpHandler(options) {
|
|
|
4307
3927
|
return;
|
|
4308
3928
|
}
|
|
4309
3929
|
}
|
|
4310
|
-
validateProtocolVersion(request);
|
|
4311
|
-
validateGetHeaders(request);
|
|
4312
3930
|
streamHub.open(response);
|
|
4313
3931
|
} catch (error) {
|
|
4314
3932
|
const status = error instanceof JsonRpcHttpError ? error.status : 400;
|
|
@@ -4337,11 +3955,6 @@ function createSidecarHttpHandler(options) {
|
|
|
4337
3955
|
return;
|
|
4338
3956
|
}
|
|
4339
3957
|
try {
|
|
4340
|
-
const fetchRequest = toFetchRequest(request, options.publicUrl ?? options.auth?.resource);
|
|
4341
|
-
const authSession = options.auth ? await authorizeHttpRequest(options.auth, fetchRequest, response) : void 0;
|
|
4342
|
-
if (options.auth && authSession === AUTH_RESPONSE_SENT) {
|
|
4343
|
-
return;
|
|
4344
|
-
}
|
|
4345
3958
|
validateProtocolVersion(request);
|
|
4346
3959
|
validatePostHeaders(request);
|
|
4347
3960
|
const body = await readJson(request, maxBodyBytes);
|
|
@@ -4354,6 +3967,11 @@ function createSidecarHttpHandler(options) {
|
|
|
4354
3967
|
return;
|
|
4355
3968
|
}
|
|
4356
3969
|
const rpcRequest = assertJsonRpcRequest(body);
|
|
3970
|
+
const fetchRequest = toFetchRequest(request, options.publicUrl ?? options.auth?.resource);
|
|
3971
|
+
const authSession = options.auth ? await authorizeHttpRequest(options.auth, fetchRequest, response) : void 0;
|
|
3972
|
+
if (options.auth && authSession === AUTH_RESPONSE_SENT) {
|
|
3973
|
+
return;
|
|
3974
|
+
}
|
|
4357
3975
|
if (rpcRequest.id !== void 0 && hasProgressToken(rpcRequest)) {
|
|
4358
3976
|
const stream = createSseStream(response, { supportsRequestProgress: true });
|
|
4359
3977
|
const payload2 = await mcp.handle(rpcRequest, {
|
|
@@ -4445,73 +4063,6 @@ function escapeRegExp(value) {
|
|
|
4445
4063
|
function isProtectedResourceMetadataPath(pathname, endpoint) {
|
|
4446
4064
|
return pathname === "/.well-known/oauth-protected-resource" || pathname === `/.well-known/oauth-protected-resource${endpoint}`;
|
|
4447
4065
|
}
|
|
4448
|
-
function createHttpRequestLog(request, pathname) {
|
|
4449
|
-
return {
|
|
4450
|
-
method: request.method,
|
|
4451
|
-
path: pathname,
|
|
4452
|
-
host: truncateHeader(singleHeader(request.headers.host)),
|
|
4453
|
-
accept: truncateHeader(singleHeader(request.headers.accept)),
|
|
4454
|
-
contentType: truncateHeader(singleHeader(request.headers["content-type"])),
|
|
4455
|
-
contentLength: truncateHeader(singleHeader(request.headers["content-length"])),
|
|
4456
|
-
mcpProtocolVersion: truncateHeader(singleHeader(request.headers["mcp-protocol-version"])),
|
|
4457
|
-
origin: truncateHeader(singleHeader(request.headers.origin)),
|
|
4458
|
-
userAgent: truncateHeader(singleHeader(request.headers["user-agent"])),
|
|
4459
|
-
authorization: request.headers.authorization ? "present" : "absent",
|
|
4460
|
-
cookie: request.headers.cookie ? "present" : "absent"
|
|
4461
|
-
};
|
|
4462
|
-
}
|
|
4463
|
-
function logHttpRequest(metadata, status) {
|
|
4464
|
-
const debug = process.env.SIDECAR_DEBUG === "1" || process.env.SIDECAR_LOG_LEVEL === "debug";
|
|
4465
|
-
if (!debug && status < 400) {
|
|
4466
|
-
return;
|
|
4467
|
-
}
|
|
4468
|
-
const message = JSON.stringify({
|
|
4469
|
-
event: "sidecar.mcp.http",
|
|
4470
|
-
status,
|
|
4471
|
-
...stripUndefined4(metadata)
|
|
4472
|
-
});
|
|
4473
|
-
if (status >= 500) {
|
|
4474
|
-
console.error(message);
|
|
4475
|
-
} else if (status >= 400) {
|
|
4476
|
-
console.warn(message);
|
|
4477
|
-
} else {
|
|
4478
|
-
console.info(message);
|
|
4479
|
-
}
|
|
4480
|
-
}
|
|
4481
|
-
function singleHeader(value) {
|
|
4482
|
-
return Array.isArray(value) ? value.join(", ") : value;
|
|
4483
|
-
}
|
|
4484
|
-
function truncateHeader(value) {
|
|
4485
|
-
if (!value) {
|
|
4486
|
-
return void 0;
|
|
4487
|
-
}
|
|
4488
|
-
return value.length > 240 ? `${value.slice(0, 237)}...` : value;
|
|
4489
|
-
}
|
|
4490
|
-
async function proxyAuthorizationServerMetadata(auth, response) {
|
|
4491
|
-
const [authorizationServer] = auth.authorizationServers;
|
|
4492
|
-
if (!authorizationServer) {
|
|
4493
|
-
response.writeHead(404, { "content-type": "application/json" });
|
|
4494
|
-
response.end(JSON.stringify({ error: "authorization_server_not_configured" }));
|
|
4495
|
-
return;
|
|
4496
|
-
}
|
|
4497
|
-
try {
|
|
4498
|
-
const url = new URL("/.well-known/oauth-authorization-server", authorizationServer);
|
|
4499
|
-
const upstream = await fetch(url, { headers: { accept: "application/json" } });
|
|
4500
|
-
const body = await upstream.text();
|
|
4501
|
-
response.writeHead(upstream.ok ? 200 : 502, {
|
|
4502
|
-
"content-type": upstream.headers.get("content-type") ?? "application/json"
|
|
4503
|
-
});
|
|
4504
|
-
response.end(body);
|
|
4505
|
-
} catch (error) {
|
|
4506
|
-
console.warn(JSON.stringify({
|
|
4507
|
-
event: "sidecar.mcp.authorization_metadata_proxy_failed",
|
|
4508
|
-
authorizationServer,
|
|
4509
|
-
message: error instanceof Error ? error.message : "Unknown error"
|
|
4510
|
-
}));
|
|
4511
|
-
response.writeHead(502, { "content-type": "application/json" });
|
|
4512
|
-
response.end(JSON.stringify({ error: "authorization_metadata_unavailable" }));
|
|
4513
|
-
}
|
|
4514
|
-
}
|
|
4515
4066
|
var JsonRpcError = class extends Error {
|
|
4516
4067
|
constructor(code, message, data) {
|
|
4517
4068
|
super(message);
|
|
@@ -4861,44 +4412,44 @@ function validateAgainstSchema(schema, value, message, options = {}) {
|
|
|
4861
4412
|
}
|
|
4862
4413
|
return value;
|
|
4863
4414
|
}
|
|
4864
|
-
function schemaFailure(schema, value,
|
|
4865
|
-
if (schema.anyOf?.length && !schema.anyOf.some((entry) => !schemaFailure(entry, value,
|
|
4866
|
-
return `${
|
|
4415
|
+
function schemaFailure(schema, value, path20) {
|
|
4416
|
+
if (schema.anyOf?.length && !schema.anyOf.some((entry) => !schemaFailure(entry, value, path20))) {
|
|
4417
|
+
return `${path20} must match one anyOf schema.`;
|
|
4867
4418
|
}
|
|
4868
|
-
if (schema.oneOf?.length && schema.oneOf.filter((entry) => !schemaFailure(entry, value,
|
|
4869
|
-
return `${
|
|
4419
|
+
if (schema.oneOf?.length && schema.oneOf.filter((entry) => !schemaFailure(entry, value, path20)).length !== 1) {
|
|
4420
|
+
return `${path20} must match exactly one oneOf schema.`;
|
|
4870
4421
|
}
|
|
4871
4422
|
if (schema.allOf?.length) {
|
|
4872
4423
|
for (const entry of schema.allOf) {
|
|
4873
|
-
const failure = schemaFailure(entry, value,
|
|
4424
|
+
const failure = schemaFailure(entry, value, path20);
|
|
4874
4425
|
if (failure) return failure;
|
|
4875
4426
|
}
|
|
4876
4427
|
}
|
|
4877
4428
|
if (schema.const !== void 0 && value !== schema.const) {
|
|
4878
|
-
return `${
|
|
4429
|
+
return `${path20} must equal ${JSON.stringify(schema.const)}.`;
|
|
4879
4430
|
}
|
|
4880
4431
|
if (schema.enum && !schema.enum.some((entry) => JSON.stringify(entry) === JSON.stringify(value))) {
|
|
4881
|
-
return `${
|
|
4432
|
+
return `${path20} must be one of the declared enum values.`;
|
|
4882
4433
|
}
|
|
4883
4434
|
if (schema.type) {
|
|
4884
4435
|
const types = Array.isArray(schema.type) ? schema.type : [schema.type];
|
|
4885
4436
|
if (!types.some((type) => matchesJsonSchemaType(type, value))) {
|
|
4886
|
-
return `${
|
|
4437
|
+
return `${path20} must be ${types.join(" or ")}.`;
|
|
4887
4438
|
}
|
|
4888
4439
|
}
|
|
4889
4440
|
if (schema.type === "object" || schema.properties || schema.required) {
|
|
4890
4441
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
4891
|
-
return `${
|
|
4442
|
+
return `${path20} must be an object.`;
|
|
4892
4443
|
}
|
|
4893
4444
|
const record = value;
|
|
4894
4445
|
for (const required of schema.required ?? []) {
|
|
4895
4446
|
if (!(required in record)) {
|
|
4896
|
-
return `${
|
|
4447
|
+
return `${path20}.${required} is required.`;
|
|
4897
4448
|
}
|
|
4898
4449
|
}
|
|
4899
4450
|
for (const [key, propertySchema] of Object.entries(schema.properties ?? {})) {
|
|
4900
4451
|
if (key in record) {
|
|
4901
|
-
const failure = schemaFailure(propertySchema, record[key], `${
|
|
4452
|
+
const failure = schemaFailure(propertySchema, record[key], `${path20}.${key}`);
|
|
4902
4453
|
if (failure) return failure;
|
|
4903
4454
|
}
|
|
4904
4455
|
}
|
|
@@ -4906,12 +4457,12 @@ function schemaFailure(schema, value, path21) {
|
|
|
4906
4457
|
if (schema.additionalProperties === false) {
|
|
4907
4458
|
const extra = Object.keys(record).find((key) => !allowed.has(key));
|
|
4908
4459
|
if (extra) {
|
|
4909
|
-
return `${
|
|
4460
|
+
return `${path20}.${extra} is not allowed.`;
|
|
4910
4461
|
}
|
|
4911
4462
|
} else if (schema.additionalProperties && typeof schema.additionalProperties === "object") {
|
|
4912
4463
|
for (const [key, entry] of Object.entries(record)) {
|
|
4913
4464
|
if (!allowed.has(key)) {
|
|
4914
|
-
const failure = schemaFailure(schema.additionalProperties, entry, `${
|
|
4465
|
+
const failure = schemaFailure(schema.additionalProperties, entry, `${path20}.${key}`);
|
|
4915
4466
|
if (failure) return failure;
|
|
4916
4467
|
}
|
|
4917
4468
|
}
|
|
@@ -4919,38 +4470,29 @@ function schemaFailure(schema, value, path21) {
|
|
|
4919
4470
|
}
|
|
4920
4471
|
if (schema.type === "array" || schema.items) {
|
|
4921
4472
|
if (!Array.isArray(value)) {
|
|
4922
|
-
return `${
|
|
4923
|
-
}
|
|
4924
|
-
if (schema.minItems !== void 0 && value.length < schema.minItems) {
|
|
4925
|
-
return `${path21} must contain at least ${schema.minItems} items.`;
|
|
4926
|
-
}
|
|
4927
|
-
if (schema.maxItems !== void 0 && value.length > schema.maxItems) {
|
|
4928
|
-
return `${path21} must contain at most ${schema.maxItems} items.`;
|
|
4473
|
+
return `${path20} must be an array.`;
|
|
4929
4474
|
}
|
|
4930
4475
|
if (schema.items) {
|
|
4931
4476
|
for (const [index, entry] of value.entries()) {
|
|
4932
|
-
const failure = schemaFailure(schema.items, entry, `${
|
|
4477
|
+
const failure = schemaFailure(schema.items, entry, `${path20}[${index}]`);
|
|
4933
4478
|
if (failure) return failure;
|
|
4934
4479
|
}
|
|
4935
4480
|
}
|
|
4936
4481
|
}
|
|
4937
4482
|
if (typeof value === "string") {
|
|
4938
4483
|
if (schema.minLength !== void 0 && value.length < schema.minLength) {
|
|
4939
|
-
return `${
|
|
4484
|
+
return `${path20} is shorter than ${schema.minLength}.`;
|
|
4940
4485
|
}
|
|
4941
4486
|
if (schema.maxLength !== void 0 && value.length > schema.maxLength) {
|
|
4942
|
-
return `${
|
|
4943
|
-
}
|
|
4944
|
-
if (schema.pattern !== void 0 && !new RegExp(schema.pattern).test(value)) {
|
|
4945
|
-
return `${path21} must match pattern ${schema.pattern}.`;
|
|
4487
|
+
return `${path20} is longer than ${schema.maxLength}.`;
|
|
4946
4488
|
}
|
|
4947
4489
|
}
|
|
4948
4490
|
if (typeof value === "number") {
|
|
4949
4491
|
if (schema.minimum !== void 0 && value < schema.minimum) {
|
|
4950
|
-
return `${
|
|
4492
|
+
return `${path20} is less than ${schema.minimum}.`;
|
|
4951
4493
|
}
|
|
4952
4494
|
if (schema.maximum !== void 0 && value > schema.maximum) {
|
|
4953
|
-
return `${
|
|
4495
|
+
return `${path20} is greater than ${schema.maximum}.`;
|
|
4954
4496
|
}
|
|
4955
4497
|
}
|
|
4956
4498
|
return void 0;
|
|
@@ -5128,11 +4670,11 @@ import { stdin, stdout } from "process";
|
|
|
5128
4670
|
async function startTunnel(options) {
|
|
5129
4671
|
const provider = await resolveProvider(options.provider);
|
|
5130
4672
|
const localUrl = `http://127.0.0.1:${options.port}`;
|
|
5131
|
-
const
|
|
4673
|
+
const path20 = options.path ?? "/mcp";
|
|
5132
4674
|
if (provider === "cloudflared") {
|
|
5133
|
-
return startCloudflared(localUrl,
|
|
4675
|
+
return startCloudflared(localUrl, path20, options.timeoutMs);
|
|
5134
4676
|
}
|
|
5135
|
-
return startWrangler(localUrl,
|
|
4677
|
+
return startWrangler(localUrl, path20, options.timeoutMs);
|
|
5136
4678
|
}
|
|
5137
4679
|
async function validateTunnelEndpoint(options) {
|
|
5138
4680
|
const timeoutMs = options.timeoutMs ?? 1e4;
|
|
@@ -5256,7 +4798,7 @@ function assertNpxAvailable() {
|
|
|
5256
4798
|
throw new Error(tunnelInstallMessage("wrangler"));
|
|
5257
4799
|
}
|
|
5258
4800
|
}
|
|
5259
|
-
async function startCloudflared(localUrl,
|
|
4801
|
+
async function startCloudflared(localUrl, path20, timeoutMs = 2e4) {
|
|
5260
4802
|
const child = spawn("cloudflared", ["tunnel", "--url", localUrl, "--no-autoupdate"], {
|
|
5261
4803
|
stdio: ["ignore", "pipe", "pipe"]
|
|
5262
4804
|
});
|
|
@@ -5264,13 +4806,13 @@ async function startCloudflared(localUrl, path21, timeoutMs = 2e4) {
|
|
|
5264
4806
|
return {
|
|
5265
4807
|
provider: "cloudflared",
|
|
5266
4808
|
publicUrl,
|
|
5267
|
-
mcpUrl: appendPath(publicUrl,
|
|
4809
|
+
mcpUrl: appendPath(publicUrl, path20),
|
|
5268
4810
|
close() {
|
|
5269
4811
|
child.kill("SIGTERM");
|
|
5270
4812
|
}
|
|
5271
4813
|
};
|
|
5272
4814
|
}
|
|
5273
|
-
async function startWrangler(localUrl,
|
|
4815
|
+
async function startWrangler(localUrl, path20, timeoutMs = 2e4) {
|
|
5274
4816
|
const child = spawn("npx", ["--yes", "wrangler", "tunnel", "quick-start", localUrl], {
|
|
5275
4817
|
stdio: ["ignore", "pipe", "pipe"]
|
|
5276
4818
|
});
|
|
@@ -5278,7 +4820,7 @@ async function startWrangler(localUrl, path21, timeoutMs = 2e4) {
|
|
|
5278
4820
|
return {
|
|
5279
4821
|
provider: "wrangler",
|
|
5280
4822
|
publicUrl,
|
|
5281
|
-
mcpUrl: appendPath(publicUrl,
|
|
4823
|
+
mcpUrl: appendPath(publicUrl, path20),
|
|
5282
4824
|
close() {
|
|
5283
4825
|
child.kill("SIGTERM");
|
|
5284
4826
|
}
|
|
@@ -5539,8 +5081,8 @@ function runInherited(command, args) {
|
|
|
5539
5081
|
});
|
|
5540
5082
|
});
|
|
5541
5083
|
}
|
|
5542
|
-
function appendPath(origin,
|
|
5543
|
-
return `${origin.replace(/\/+$/, "")}/${
|
|
5084
|
+
function appendPath(origin, path20) {
|
|
5085
|
+
return `${origin.replace(/\/+$/, "")}/${path20.replace(/^\/+/, "")}`;
|
|
5544
5086
|
}
|
|
5545
5087
|
function isRecord3(value) {
|
|
5546
5088
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
@@ -5552,27 +5094,26 @@ async function main(argv) {
|
|
|
5552
5094
|
const rootDir = readOption(argv, "--cwd") ?? cwd();
|
|
5553
5095
|
switch (command) {
|
|
5554
5096
|
case "build": {
|
|
5555
|
-
const target =
|
|
5556
|
-
const host =
|
|
5557
|
-
const outDir = readOption(argv, "--out")
|
|
5558
|
-
const plugins =
|
|
5097
|
+
const target = readTarget(argv);
|
|
5098
|
+
const host = readHost(argv);
|
|
5099
|
+
const outDir = readOption(argv, "--out") ?? `out/${target}`;
|
|
5100
|
+
const plugins = argv.includes("--plugins");
|
|
5559
5101
|
const strict = argv.includes("--strict");
|
|
5560
5102
|
const manifest = await buildProject({ rootDir, host, outDir, plugins, strict, target });
|
|
5561
|
-
const resolvedOutDir = outDir ?? manifest.config.build.outDir ?? defaultBuildOutDir2(manifest.host, manifest.target);
|
|
5562
5103
|
printDiagnostics(manifest.diagnostics ?? []);
|
|
5563
5104
|
if (strict && manifest.diagnostics?.length) {
|
|
5564
5105
|
exit(1);
|
|
5565
5106
|
}
|
|
5566
5107
|
console.log(
|
|
5567
|
-
`Built ${manifest.tools.length} ${
|
|
5108
|
+
`Built ${manifest.tools.length} ${target} tool${manifest.tools.length === 1 ? "" : "s"}, ${manifest.resources.length} resource${manifest.resources.length === 1 ? "" : "s"}, and ${manifest.prompts.length} prompt${manifest.prompts.length === 1 ? "" : "s"} to ${outDir}.`
|
|
5568
5109
|
);
|
|
5569
|
-
console.log(`Host runtime: ${
|
|
5570
|
-
if (
|
|
5571
|
-
console.log(`Vercel MCP function: ${
|
|
5110
|
+
console.log(`Host runtime: ${host}`);
|
|
5111
|
+
if (host === "vercel") {
|
|
5112
|
+
console.log(`Vercel MCP function: ${path19.join(outDir, VERCEL_ENTRYPOINT)}`);
|
|
5572
5113
|
} else {
|
|
5573
|
-
console.log(`Hostable MCP server: ${
|
|
5114
|
+
console.log(`Hostable MCP server: ${path19.join(outDir, SERVER_ENTRYPOINT)}`);
|
|
5574
5115
|
}
|
|
5575
|
-
if (plugins
|
|
5116
|
+
if (plugins) {
|
|
5576
5117
|
console.log("Built claude-plugin package.");
|
|
5577
5118
|
}
|
|
5578
5119
|
return;
|
|
@@ -5702,7 +5243,7 @@ async function main(argv) {
|
|
|
5702
5243
|
console.log(`Sidecar
|
|
5703
5244
|
|
|
5704
5245
|
Usage:
|
|
5705
|
-
sidecar build [--cwd <dir>] [--target mcp|chatgpt|claude] [--host node|vercel] [--out <dir>] [--plugins
|
|
5246
|
+
sidecar build [--cwd <dir>] [--target mcp|chatgpt|claude] [--host node|vercel] [--out <dir>] [--plugins] [--strict]
|
|
5706
5247
|
sidecar check [--cwd <dir>] [--target mcp|chatgpt|claude] [--strict]
|
|
5707
5248
|
sidecar dev [--cwd <dir>] [--target mcp|chatgpt|claude] [--port <port>] [--tunnel [cloudflared|wrangler]]
|
|
5708
5249
|
sidecar inspect [--cwd <dir>] [--target mcp|chatgpt|claude]
|
|
@@ -5710,54 +5251,23 @@ Usage:
|
|
|
5710
5251
|
`);
|
|
5711
5252
|
}
|
|
5712
5253
|
}
|
|
5713
|
-
function defaultBuildOutDir2(host, target) {
|
|
5714
|
-
if (host === "vercel") {
|
|
5715
|
-
return ".vercel/output";
|
|
5716
|
-
}
|
|
5717
|
-
return `out/${target}`;
|
|
5718
|
-
}
|
|
5719
5254
|
function readTarget(argv) {
|
|
5720
|
-
const target =
|
|
5721
|
-
return target;
|
|
5722
|
-
}
|
|
5723
|
-
function readOptionalTarget(argv) {
|
|
5724
|
-
const target = readOption(argv, "--target");
|
|
5725
|
-
if (!target) {
|
|
5726
|
-
return void 0;
|
|
5727
|
-
}
|
|
5255
|
+
const target = readOption(argv, "--target") ?? "mcp";
|
|
5728
5256
|
if (target === "mcp" || target === "chatgpt" || target === "claude") {
|
|
5729
5257
|
return target;
|
|
5730
5258
|
}
|
|
5731
5259
|
throw new Error(`Unsupported Sidecar target "${target}". Expected mcp, chatgpt, or claude.`);
|
|
5732
5260
|
}
|
|
5733
|
-
function
|
|
5734
|
-
const host = readOption(argv, "--host");
|
|
5735
|
-
if (!host) {
|
|
5736
|
-
return void 0;
|
|
5737
|
-
}
|
|
5261
|
+
function readHost(argv) {
|
|
5262
|
+
const host = readOption(argv, "--host") ?? "node";
|
|
5738
5263
|
if (host === "node" || host === "vercel") {
|
|
5739
5264
|
return host;
|
|
5740
5265
|
}
|
|
5741
5266
|
throw new Error(`Unsupported Sidecar host "${host}". Expected node or vercel.`);
|
|
5742
5267
|
}
|
|
5743
|
-
function detectHostFromEnvironment() {
|
|
5744
|
-
if (process.env.VERCEL === "1") {
|
|
5745
|
-
return "vercel";
|
|
5746
|
-
}
|
|
5747
|
-
return void 0;
|
|
5748
|
-
}
|
|
5749
|
-
function readOptionalPlugins(argv) {
|
|
5750
|
-
if (argv.includes("--plugins")) {
|
|
5751
|
-
return true;
|
|
5752
|
-
}
|
|
5753
|
-
if (argv.includes("--no-plugins")) {
|
|
5754
|
-
return false;
|
|
5755
|
-
}
|
|
5756
|
-
return void 0;
|
|
5757
|
-
}
|
|
5758
5268
|
async function previewComponents(options) {
|
|
5759
|
-
const cliDir =
|
|
5760
|
-
const css = await readFile8(
|
|
5269
|
+
const cliDir = path19.dirname(fileURLToPath(import.meta.url));
|
|
5270
|
+
const css = await readFile8(path19.join(cliDir, "../../native/src/styles.css"), "utf8").catch(() => readFile8(path19.join(process.cwd(), "packages/native/src/styles.css"), "utf8")).catch(() => "");
|
|
5761
5271
|
const html = renderComponentPreviewHtml(
|
|
5762
5272
|
options.host,
|
|
5763
5273
|
options.compare,
|
|
@@ -5797,10 +5307,10 @@ async function previewComponents(options) {
|
|
|
5797
5307
|
server.close();
|
|
5798
5308
|
}
|
|
5799
5309
|
async function writeComponentApproval(rootDir, approval) {
|
|
5800
|
-
const dir =
|
|
5310
|
+
const dir = path19.join(rootDir, ".sidecar", "approvals");
|
|
5801
5311
|
await mkdir10(dir, { recursive: true });
|
|
5802
5312
|
await writeFile10(
|
|
5803
|
-
|
|
5313
|
+
path19.join(dir, `components.${approval.host}.json`),
|
|
5804
5314
|
`${JSON.stringify(approval, null, 2)}
|
|
5805
5315
|
`
|
|
5806
5316
|
);
|
|
@@ -6152,71 +5662,71 @@ function printDiagnostics(diagnostics) {
|
|
|
6152
5662
|
}
|
|
6153
5663
|
}
|
|
6154
5664
|
async function loadRuntimeAuth(rootDir) {
|
|
6155
|
-
const authPath =
|
|
6156
|
-
if (!
|
|
5665
|
+
const authPath = path19.join(rootDir, "auth.ts");
|
|
5666
|
+
if (!existsSync6(authPath)) {
|
|
6157
5667
|
return void 0;
|
|
6158
5668
|
}
|
|
6159
|
-
const parentURL =
|
|
6160
|
-
const tsconfigPath =
|
|
6161
|
-
const tsconfig =
|
|
6162
|
-
const module = await
|
|
5669
|
+
const parentURL = pathToFileURL(path19.join(rootDir, "sidecar.config.ts")).href;
|
|
5670
|
+
const tsconfigPath = path19.join(rootDir, "tsconfig.json");
|
|
5671
|
+
const tsconfig = existsSync6(tsconfigPath) ? tsconfigPath : false;
|
|
5672
|
+
const module = await tsImport(pathToFileURL(authPath).href, {
|
|
6163
5673
|
parentURL,
|
|
6164
5674
|
tsconfig
|
|
6165
5675
|
});
|
|
6166
|
-
const defaultExport =
|
|
5676
|
+
const defaultExport = unwrapRuntimeDefault(module.default);
|
|
6167
5677
|
if (!isSidecarAuth(defaultExport)) {
|
|
6168
5678
|
throw new Error("auth.ts must default-export auth({ ... }) from sidecar-ai.");
|
|
6169
5679
|
}
|
|
6170
5680
|
return defaultExport;
|
|
6171
5681
|
}
|
|
6172
5682
|
async function loadRuntimeProxy(rootDir) {
|
|
6173
|
-
const proxyPath =
|
|
6174
|
-
if (!
|
|
5683
|
+
const proxyPath = path19.join(rootDir, "proxy.ts");
|
|
5684
|
+
if (!existsSync6(proxyPath)) {
|
|
6175
5685
|
return void 0;
|
|
6176
5686
|
}
|
|
6177
|
-
const parentURL =
|
|
6178
|
-
const tsconfigPath =
|
|
6179
|
-
const tsconfig =
|
|
6180
|
-
const module = await
|
|
5687
|
+
const parentURL = pathToFileURL(path19.join(rootDir, "sidecar.config.ts")).href;
|
|
5688
|
+
const tsconfigPath = path19.join(rootDir, "tsconfig.json");
|
|
5689
|
+
const tsconfig = existsSync6(tsconfigPath) ? tsconfigPath : false;
|
|
5690
|
+
const module = await tsImport(pathToFileURL(proxyPath).href, {
|
|
6181
5691
|
parentURL,
|
|
6182
5692
|
tsconfig
|
|
6183
5693
|
});
|
|
6184
|
-
const defaultExport =
|
|
5694
|
+
const defaultExport = unwrapRuntimeDefault(module.default);
|
|
6185
5695
|
if (!isSidecarProxy(defaultExport)) {
|
|
6186
5696
|
throw new Error("proxy.ts must default-export proxy({ ... }) from @sidecar-ai/server/proxy.");
|
|
6187
5697
|
}
|
|
6188
5698
|
return defaultExport;
|
|
6189
5699
|
}
|
|
6190
5700
|
async function loadRuntimeConfig(rootDir) {
|
|
6191
|
-
const configPath =
|
|
6192
|
-
if (!
|
|
5701
|
+
const configPath = path19.join(rootDir, "sidecar.config.ts");
|
|
5702
|
+
if (!existsSync6(configPath)) {
|
|
6193
5703
|
return void 0;
|
|
6194
5704
|
}
|
|
6195
|
-
const parentURL =
|
|
6196
|
-
const tsconfigPath =
|
|
6197
|
-
const tsconfig =
|
|
6198
|
-
const module = await
|
|
5705
|
+
const parentURL = pathToFileURL(configPath).href;
|
|
5706
|
+
const tsconfigPath = path19.join(rootDir, "tsconfig.json");
|
|
5707
|
+
const tsconfig = existsSync6(tsconfigPath) ? tsconfigPath : false;
|
|
5708
|
+
const module = await tsImport(pathToFileURL(configPath).href, {
|
|
6199
5709
|
parentURL,
|
|
6200
5710
|
tsconfig
|
|
6201
5711
|
});
|
|
6202
|
-
const defaultExport =
|
|
5712
|
+
const defaultExport = unwrapRuntimeDefault(module.default);
|
|
6203
5713
|
if (!defaultExport || typeof defaultExport !== "object") {
|
|
6204
5714
|
throw new Error("sidecar.config.ts must default-export defineConfig({ ... }) from sidecar-ai.");
|
|
6205
5715
|
}
|
|
6206
5716
|
return defaultExport;
|
|
6207
5717
|
}
|
|
6208
5718
|
async function loadRuntimeTools(rootDir, entries) {
|
|
6209
|
-
const parentURL =
|
|
6210
|
-
const tsconfigPath =
|
|
6211
|
-
const tsconfig =
|
|
5719
|
+
const parentURL = pathToFileURL(path19.join(rootDir, "sidecar.config.ts")).href;
|
|
5720
|
+
const tsconfigPath = path19.join(rootDir, "tsconfig.json");
|
|
5721
|
+
const tsconfig = existsSync6(tsconfigPath) ? tsconfigPath : false;
|
|
6212
5722
|
const loaded = [];
|
|
6213
5723
|
for (const entry of entries) {
|
|
6214
|
-
const sourcePath =
|
|
6215
|
-
const module = await
|
|
5724
|
+
const sourcePath = path19.join(rootDir, entry.sourceFile);
|
|
5725
|
+
const module = await tsImport(pathToFileURL(sourcePath).href, {
|
|
6216
5726
|
parentURL,
|
|
6217
5727
|
tsconfig
|
|
6218
5728
|
});
|
|
6219
|
-
const defaultExport =
|
|
5729
|
+
const defaultExport = unwrapRuntimeDefault(module.default);
|
|
6220
5730
|
if (!isSidecarTool(defaultExport)) {
|
|
6221
5731
|
throw new Error(`${entry.sourceFile} did not default-export a Sidecar tool.`);
|
|
6222
5732
|
}
|
|
@@ -6243,7 +5753,7 @@ async function loadResources(rootDir, outDir, manifest) {
|
|
|
6243
5753
|
if (!entry.widget?.outputFile) {
|
|
6244
5754
|
continue;
|
|
6245
5755
|
}
|
|
6246
|
-
const text = await readFile8(
|
|
5756
|
+
const text = await readFile8(path19.join(rootDir, outDir, entry.widget.outputFile), "utf8");
|
|
6247
5757
|
resources.push({
|
|
6248
5758
|
uri: entry.widget.resourceUri,
|
|
6249
5759
|
name: entry.name,
|
|
@@ -6253,16 +5763,16 @@ async function loadResources(rootDir, outDir, manifest) {
|
|
|
6253
5763
|
_meta: entry.widget.resourceMeta
|
|
6254
5764
|
});
|
|
6255
5765
|
}
|
|
6256
|
-
const parentURL =
|
|
6257
|
-
const tsconfigPath =
|
|
6258
|
-
const tsconfig =
|
|
5766
|
+
const parentURL = pathToFileURL(path19.join(rootDir, "sidecar.config.ts")).href;
|
|
5767
|
+
const tsconfigPath = path19.join(rootDir, "tsconfig.json");
|
|
5768
|
+
const tsconfig = existsSync6(tsconfigPath) ? tsconfigPath : false;
|
|
6259
5769
|
for (const entry of manifest.resources) {
|
|
6260
|
-
const sourcePath =
|
|
6261
|
-
const module = await
|
|
5770
|
+
const sourcePath = path19.join(rootDir, entry.sourceFile);
|
|
5771
|
+
const module = await tsImport(pathToFileURL(sourcePath).href, {
|
|
6262
5772
|
parentURL,
|
|
6263
5773
|
tsconfig
|
|
6264
5774
|
});
|
|
6265
|
-
const defaultExport =
|
|
5775
|
+
const defaultExport = unwrapRuntimeDefault(module.default);
|
|
6266
5776
|
if (!isSidecarResource(defaultExport)) {
|
|
6267
5777
|
throw new Error(`${entry.sourceFile} did not default-export a Sidecar resource.`);
|
|
6268
5778
|
}
|
|
@@ -6275,17 +5785,17 @@ async function loadResources(rootDir, outDir, manifest) {
|
|
|
6275
5785
|
return resources;
|
|
6276
5786
|
}
|
|
6277
5787
|
async function loadRuntimePrompts(rootDir, manifest) {
|
|
6278
|
-
const parentURL =
|
|
6279
|
-
const tsconfigPath =
|
|
6280
|
-
const tsconfig =
|
|
5788
|
+
const parentURL = pathToFileURL(path19.join(rootDir, "sidecar.config.ts")).href;
|
|
5789
|
+
const tsconfigPath = path19.join(rootDir, "tsconfig.json");
|
|
5790
|
+
const tsconfig = existsSync6(tsconfigPath) ? tsconfigPath : false;
|
|
6281
5791
|
const loaded = [];
|
|
6282
5792
|
for (const entry of manifest.prompts) {
|
|
6283
|
-
const sourcePath =
|
|
6284
|
-
const module = await
|
|
5793
|
+
const sourcePath = path19.join(rootDir, entry.sourceFile);
|
|
5794
|
+
const module = await tsImport(pathToFileURL(sourcePath).href, {
|
|
6285
5795
|
parentURL,
|
|
6286
5796
|
tsconfig
|
|
6287
5797
|
});
|
|
6288
|
-
const defaultExport =
|
|
5798
|
+
const defaultExport = unwrapRuntimeDefault(module.default);
|
|
6289
5799
|
if (!isSidecarPrompt(defaultExport)) {
|
|
6290
5800
|
throw new Error(`${entry.sourceFile} did not default-export a Sidecar prompt.`);
|
|
6291
5801
|
}
|
|
@@ -6296,9 +5806,9 @@ async function loadRuntimePrompts(rootDir, manifest) {
|
|
|
6296
5806
|
}
|
|
6297
5807
|
return loaded;
|
|
6298
5808
|
}
|
|
6299
|
-
function
|
|
6300
|
-
if (value && typeof value === "object" && "default" in value && Object.keys(value).
|
|
6301
|
-
return
|
|
5809
|
+
function unwrapRuntimeDefault(value) {
|
|
5810
|
+
if (value && typeof value === "object" && "default" in value && Object.keys(value).length === 1) {
|
|
5811
|
+
return unwrapRuntimeDefault(value.default);
|
|
6302
5812
|
}
|
|
6303
5813
|
return value;
|
|
6304
5814
|
}
|
|
@@ -6332,7 +5842,7 @@ function isDirectRun() {
|
|
|
6332
5842
|
return false;
|
|
6333
5843
|
}
|
|
6334
5844
|
const entryPath = realpathSync.native(entry);
|
|
6335
|
-
return import.meta.url ===
|
|
5845
|
+
return import.meta.url === pathToFileURL(entryPath).href;
|
|
6336
5846
|
}
|
|
6337
5847
|
if (isDirectRun()) {
|
|
6338
5848
|
main(process.argv).catch((error) => {
|