@sidecar-ai/compiler 0.1.0-alpha.10 → 0.1.0-alpha.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -5
- package/dist/index.js +290 -605
- package/dist/index.js.map +1 -1
- package/package.json +3 -4
package/dist/index.js
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
// packages/core/src/index.ts
|
|
2
|
-
var toolBrand = /* @__PURE__ */ Symbol.for("sidecar.tool");
|
|
3
2
|
var toolResultBrand = /* @__PURE__ */ Symbol.for("sidecar.toolResult");
|
|
4
3
|
var resourceResultBrand = /* @__PURE__ */ Symbol.for("sidecar.resourceResult");
|
|
5
|
-
function isSidecarTool(value) {
|
|
6
|
-
return Boolean(
|
|
7
|
-
value && typeof value === "object" && (value[toolBrand] || value.kind === "sidecar.tool")
|
|
8
|
-
);
|
|
9
|
-
}
|
|
10
4
|
var toolResult = Object.assign(
|
|
11
5
|
createToolResult,
|
|
12
6
|
{
|
|
@@ -33,9 +27,9 @@ var resourceResult = Object.assign(
|
|
|
33
27
|
);
|
|
34
28
|
function createToolResult(input) {
|
|
35
29
|
const resultEnvelope = stripUndefined({
|
|
36
|
-
structuredContent:
|
|
30
|
+
structuredContent: input.structuredContent,
|
|
37
31
|
content: normalizeRequiredContent(input.content),
|
|
38
|
-
_meta:
|
|
32
|
+
_meta: input.meta,
|
|
39
33
|
isError: input.isError
|
|
40
34
|
});
|
|
41
35
|
Object.defineProperty(resultEnvelope, toolResultBrand, {
|
|
@@ -277,24 +271,10 @@ function isReadonlyArray(value) {
|
|
|
277
271
|
function stripUndefined(value) {
|
|
278
272
|
return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== void 0));
|
|
279
273
|
}
|
|
280
|
-
function stripJsonUndefined(value) {
|
|
281
|
-
if (value === void 0) {
|
|
282
|
-
return void 0;
|
|
283
|
-
}
|
|
284
|
-
if (Array.isArray(value)) {
|
|
285
|
-
return value.map((entry) => stripJsonUndefined(entry)).filter((entry) => entry !== void 0);
|
|
286
|
-
}
|
|
287
|
-
if (!value || typeof value !== "object") {
|
|
288
|
-
return value;
|
|
289
|
-
}
|
|
290
|
-
return Object.fromEntries(
|
|
291
|
-
Object.entries(value).map(([key, entry]) => [key, stripJsonUndefined(entry)]).filter(([, entry]) => entry !== void 0)
|
|
292
|
-
);
|
|
293
|
-
}
|
|
294
274
|
|
|
295
275
|
// packages/compiler/src/analyze.ts
|
|
296
276
|
import { readdir } from "fs/promises";
|
|
297
|
-
import
|
|
277
|
+
import path4 from "path";
|
|
298
278
|
import {
|
|
299
279
|
Node as Node4,
|
|
300
280
|
SyntaxKind as SyntaxKind2
|
|
@@ -461,7 +441,14 @@ function devSidecarTypePaths() {
|
|
|
461
441
|
import {
|
|
462
442
|
Node as Node2
|
|
463
443
|
} from "ts-morph";
|
|
464
|
-
function getParamsSchema(
|
|
444
|
+
function getParamsSchema(definition, execute) {
|
|
445
|
+
const explicitParams = definition.getProperty("params");
|
|
446
|
+
if (explicitParams && Node2.isPropertyAssignment(explicitParams)) {
|
|
447
|
+
const inferred = getSchemaFromZodProperty(explicitParams);
|
|
448
|
+
if (inferred) {
|
|
449
|
+
return inferred;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
465
452
|
const [params] = execute.getParameters();
|
|
466
453
|
if (!params) {
|
|
467
454
|
return emptyObjectSchema();
|
|
@@ -482,6 +469,74 @@ function getOutputSchema(definition, execute) {
|
|
|
482
469
|
}
|
|
483
470
|
return typeToJsonSchema(returnType);
|
|
484
471
|
}
|
|
472
|
+
function getSchemaFromZodProperty(property) {
|
|
473
|
+
const initializer = property.getInitializer();
|
|
474
|
+
if (!initializer) {
|
|
475
|
+
return void 0;
|
|
476
|
+
}
|
|
477
|
+
if (Node2.isCallExpression(initializer) && initializer.getExpression().getText().endsWith(".object")) {
|
|
478
|
+
const [shape] = initializer.getArguments();
|
|
479
|
+
if (shape && Node2.isObjectLiteralExpression(shape)) {
|
|
480
|
+
return zodObjectLiteralToSchema(shape);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
return void 0;
|
|
484
|
+
}
|
|
485
|
+
function zodObjectLiteralToSchema(shape) {
|
|
486
|
+
const properties = {};
|
|
487
|
+
const required = [];
|
|
488
|
+
for (const property of shape.getProperties()) {
|
|
489
|
+
if (!Node2.isPropertyAssignment(property)) {
|
|
490
|
+
continue;
|
|
491
|
+
}
|
|
492
|
+
const name = property.getName().replace(/^["']|["']$/g, "");
|
|
493
|
+
const initializer = property.getInitializer();
|
|
494
|
+
if (!initializer) {
|
|
495
|
+
continue;
|
|
496
|
+
}
|
|
497
|
+
const propertySchema = zodExpressionToSchema(initializer);
|
|
498
|
+
properties[name] = propertySchema.schema;
|
|
499
|
+
if (!propertySchema.optional) {
|
|
500
|
+
required.push(name);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
return {
|
|
504
|
+
type: "object",
|
|
505
|
+
properties,
|
|
506
|
+
required,
|
|
507
|
+
additionalProperties: false
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
function zodExpressionToSchema(expression) {
|
|
511
|
+
const text = expression.getText();
|
|
512
|
+
const optional = /\.optional\(\)/.test(text) || /\.default\(/.test(text);
|
|
513
|
+
const schema = {};
|
|
514
|
+
if (/z\.string\(\)/.test(text)) {
|
|
515
|
+
schema.type = "string";
|
|
516
|
+
} else if (/z\.number\(\)/.test(text)) {
|
|
517
|
+
schema.type = "number";
|
|
518
|
+
} else if (/z\.boolean\(\)/.test(text)) {
|
|
519
|
+
schema.type = "boolean";
|
|
520
|
+
} else if (/z\.array\(/.test(text)) {
|
|
521
|
+
schema.type = "array";
|
|
522
|
+
schema.items = {};
|
|
523
|
+
} else {
|
|
524
|
+
schema.type = "object";
|
|
525
|
+
}
|
|
526
|
+
const min = text.match(/\.min\((\d+)/);
|
|
527
|
+
const max = text.match(/\.max\((\d+)/);
|
|
528
|
+
if (schema.type === "string") {
|
|
529
|
+
if (min) schema.minLength = Number(min[1]);
|
|
530
|
+
if (max) schema.maxLength = Number(max[1]);
|
|
531
|
+
} else {
|
|
532
|
+
if (min) schema.minimum = Number(min[1]);
|
|
533
|
+
if (max) schema.maximum = Number(max[1]);
|
|
534
|
+
}
|
|
535
|
+
if (/\.int\(\)/.test(text)) {
|
|
536
|
+
schema.type = "integer";
|
|
537
|
+
}
|
|
538
|
+
return { schema, optional };
|
|
539
|
+
}
|
|
485
540
|
function typeToJsonSchema(type, description) {
|
|
486
541
|
const withoutUndefined = removeUndefined(type);
|
|
487
542
|
const schema = typeToJsonSchemaInner(withoutUndefined);
|
|
@@ -627,103 +682,11 @@ function schemaDescription(symbol) {
|
|
|
627
682
|
}).find((comment) => comment.trim().length > 0);
|
|
628
683
|
}
|
|
629
684
|
|
|
630
|
-
// packages/compiler/src/runtime-schema.ts
|
|
631
|
-
import { existsSync as existsSync2 } from "fs";
|
|
632
|
-
import path3 from "path";
|
|
633
|
-
import { pathToFileURL } from "url";
|
|
634
|
-
import { tsImport } from "tsx/esm/api";
|
|
635
|
-
async function readRuntimeToolInputSchema(rootDir, sourcePath) {
|
|
636
|
-
let sidecarTool;
|
|
637
|
-
try {
|
|
638
|
-
sidecarTool = await importRuntimeTool(rootDir, sourcePath);
|
|
639
|
-
} catch (error) {
|
|
640
|
-
warnRuntimeSchemaFallback(sourcePath, error);
|
|
641
|
-
return void 0;
|
|
642
|
-
}
|
|
643
|
-
if (!sidecarTool.params) {
|
|
644
|
-
return void 0;
|
|
645
|
-
}
|
|
646
|
-
try {
|
|
647
|
-
return await paramsToJsonSchema(sidecarTool.params);
|
|
648
|
-
} catch (error) {
|
|
649
|
-
warnRuntimeSchemaFallback(sourcePath, error);
|
|
650
|
-
return void 0;
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
async function importRuntimeTool(rootDir, sourcePath) {
|
|
654
|
-
const module = await tsImport(pathToFileURL(sourcePath).href, {
|
|
655
|
-
parentURL: runtimeParentUrl(rootDir),
|
|
656
|
-
tsconfig: runtimeTsconfig(rootDir)
|
|
657
|
-
});
|
|
658
|
-
const defaultExport = unwrapRuntimeDefault(module.default);
|
|
659
|
-
if (!isSidecarTool(defaultExport)) {
|
|
660
|
-
throw new Error(`${path3.relative(rootDir, sourcePath)} must default-export tool({ ... }).`);
|
|
661
|
-
}
|
|
662
|
-
return defaultExport;
|
|
663
|
-
}
|
|
664
|
-
async function paramsToJsonSchema(params) {
|
|
665
|
-
const instanceConverter = readInstanceConverter(params);
|
|
666
|
-
if (instanceConverter) {
|
|
667
|
-
return ensureJsonSchema(instanceConverter({ io: "input" }));
|
|
668
|
-
}
|
|
669
|
-
if (isZodMiniSchema(params)) {
|
|
670
|
-
const zod = await import("zod/v4-mini");
|
|
671
|
-
if (typeof zod.toJSONSchema === "function") {
|
|
672
|
-
return ensureJsonSchema(zod.toJSONSchema(params, { io: "input" }));
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
return void 0;
|
|
676
|
-
}
|
|
677
|
-
function readInstanceConverter(params) {
|
|
678
|
-
if (!params || typeof params !== "object") {
|
|
679
|
-
return void 0;
|
|
680
|
-
}
|
|
681
|
-
const record = params;
|
|
682
|
-
const converter = record.toJSONSchema ?? record.toJsonSchema;
|
|
683
|
-
return typeof converter === "function" ? converter.bind(params) : void 0;
|
|
684
|
-
}
|
|
685
|
-
function isZodMiniSchema(params) {
|
|
686
|
-
return Boolean(params && typeof params === "object" && "_zod" in params);
|
|
687
|
-
}
|
|
688
|
-
function ensureJsonSchema(value) {
|
|
689
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
690
|
-
return void 0;
|
|
691
|
-
}
|
|
692
|
-
return value;
|
|
693
|
-
}
|
|
694
|
-
function runtimeParentUrl(rootDir) {
|
|
695
|
-
const configPath = path3.join(rootDir, "sidecar.config.ts");
|
|
696
|
-
return pathToFileURL(existsSync2(configPath) ? configPath : rootDir).href;
|
|
697
|
-
}
|
|
698
|
-
function runtimeTsconfig(rootDir) {
|
|
699
|
-
const projectTsconfig = path3.join(rootDir, "tsconfig.json");
|
|
700
|
-
if (existsSync2(projectTsconfig)) {
|
|
701
|
-
return projectTsconfig;
|
|
702
|
-
}
|
|
703
|
-
const repoTsconfig = path3.join(process.cwd(), "tsconfig.json");
|
|
704
|
-
const repoCore = path3.join(process.cwd(), "packages", "core", "src", "index.ts");
|
|
705
|
-
return existsSyncSafe(repoTsconfig) && existsSyncSafe(repoCore) ? repoTsconfig : false;
|
|
706
|
-
}
|
|
707
|
-
function unwrapRuntimeDefault(value) {
|
|
708
|
-
if (value && typeof value === "object" && "default" in value && Object.keys(value).every((key) => key === "default" || key === "__esModule")) {
|
|
709
|
-
return unwrapRuntimeDefault(value.default);
|
|
710
|
-
}
|
|
711
|
-
return value;
|
|
712
|
-
}
|
|
713
|
-
function warnRuntimeSchemaFallback(sourcePath, error) {
|
|
714
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
715
|
-
console.warn(
|
|
716
|
-
`[sidecar] Could not convert runtime params schema for ${sourcePath}; falling back to TypeScript parameter inference. ${message}`
|
|
717
|
-
);
|
|
718
|
-
}
|
|
719
|
-
|
|
720
685
|
// packages/compiler/src/widgets.ts
|
|
721
686
|
import { createHash } from "crypto";
|
|
722
|
-
import { existsSync as
|
|
687
|
+
import { existsSync as existsSync2 } from "fs";
|
|
723
688
|
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
724
|
-
import
|
|
725
|
-
import path4 from "path";
|
|
726
|
-
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
689
|
+
import path3 from "path";
|
|
727
690
|
import { build as esbuild } from "esbuild";
|
|
728
691
|
import postcss from "postcss";
|
|
729
692
|
import {
|
|
@@ -731,30 +694,28 @@ import {
|
|
|
731
694
|
SyntaxKind
|
|
732
695
|
} from "ts-morph";
|
|
733
696
|
var CLAUDE_FONT_RESOURCE_DOMAIN = "https://assets.claude.ai";
|
|
734
|
-
|
|
735
|
-
async function buildWidgets(rootDir, outDir, tools, config = void 0) {
|
|
697
|
+
async function buildWidgets(rootDir, outDir, tools) {
|
|
736
698
|
const widgets = tools.filter(
|
|
737
699
|
(entry) => Boolean(entry.widget)
|
|
738
700
|
);
|
|
739
701
|
if (!widgets.length) {
|
|
740
702
|
return;
|
|
741
703
|
}
|
|
742
|
-
const cacheDir =
|
|
704
|
+
const cacheDir = path3.join(rootDir, ".sidecar", "cache", "widgets");
|
|
743
705
|
await mkdir(cacheDir, { recursive: true });
|
|
744
706
|
const appStyle = await prepareAppStyle(rootDir, cacheDir);
|
|
745
|
-
const configure = await loadWidgetBundlerHook(rootDir, cacheDir, config?.configure);
|
|
746
707
|
for (const entry of widgets) {
|
|
747
|
-
const sourceFile =
|
|
708
|
+
const sourceFile = path3.join(rootDir, entry.widget.sourceFile);
|
|
748
709
|
const safeId = safePathSegment(entry.id);
|
|
749
|
-
const entryFile =
|
|
750
|
-
const importPath = toImportSpecifier(
|
|
710
|
+
const entryFile = path3.join(cacheDir, `${safeId}.entry.tsx`);
|
|
711
|
+
const importPath = toImportSpecifier(path3.dirname(entryFile), sourceFile);
|
|
751
712
|
await writeFile(
|
|
752
713
|
entryFile,
|
|
753
714
|
`import React from "react";
|
|
754
715
|
import { createRoot } from "react-dom/client";
|
|
755
716
|
import { SidecarWidgetRoot } from "@sidecar-ai/react";
|
|
756
717
|
import "@sidecar-ai/native/styles.css";
|
|
757
|
-
${appStyle ? `import ${JSON.stringify(toImportSpecifier(
|
|
718
|
+
${appStyle ? `import ${JSON.stringify(toImportSpecifier(path3.dirname(entryFile), appStyle))};` : ""}
|
|
758
719
|
import Component from ${JSON.stringify(importPath)};
|
|
759
720
|
|
|
760
721
|
createRoot(document.getElementById("root")!).render(
|
|
@@ -762,219 +723,64 @@ createRoot(document.getElementById("root")!).render(
|
|
|
762
723
|
);
|
|
763
724
|
`
|
|
764
725
|
);
|
|
765
|
-
const
|
|
726
|
+
const bundled = await esbuild({
|
|
766
727
|
absWorkingDir: rootDir,
|
|
767
|
-
alias:
|
|
728
|
+
alias: devSidecarBundleAliases(rootDir),
|
|
768
729
|
bundle: true,
|
|
769
|
-
define: {
|
|
770
|
-
"process.env.NODE_ENV": JSON.stringify("production")
|
|
771
|
-
},
|
|
772
730
|
entryPoints: [entryFile],
|
|
773
731
|
format: "iife",
|
|
774
732
|
jsx: "automatic",
|
|
775
|
-
minify:
|
|
733
|
+
minify: false,
|
|
776
734
|
nodePaths: [
|
|
777
|
-
|
|
778
|
-
|
|
735
|
+
path3.join(rootDir, "node_modules"),
|
|
736
|
+
path3.join(process.cwd(), "node_modules")
|
|
779
737
|
],
|
|
780
738
|
outfile: "widget.js",
|
|
781
739
|
platform: "browser",
|
|
782
740
|
sourcemap: false,
|
|
783
741
|
write: false
|
|
784
742
|
});
|
|
785
|
-
const
|
|
786
|
-
const
|
|
787
|
-
rootDir,
|
|
788
|
-
outDir,
|
|
789
|
-
entryFile,
|
|
790
|
-
widget: {
|
|
791
|
-
toolId: entry.id,
|
|
792
|
-
toolName: entry.name,
|
|
793
|
-
target: entry.target,
|
|
794
|
-
sourceFile: entry.widget.sourceFile
|
|
795
|
-
},
|
|
796
|
-
esbuildOptions: mergeWidgetBuildOptions(baseOptions, staticOptions)
|
|
797
|
-
}) : void 0;
|
|
798
|
-
const bundled = await esbuild(enforceWidgetBuildInvariants(
|
|
799
|
-
mergeWidgetBuildOptions(baseOptions, staticOptions, configuredOptions),
|
|
800
|
-
{ rootDir, entryFile }
|
|
801
|
-
));
|
|
802
|
-
const outputFiles = bundled.outputFiles ?? [];
|
|
803
|
-
const javascript = outputFiles.find((file) => file.path.endsWith(".js"))?.text ?? "";
|
|
804
|
-
const css = outputFiles.filter((file) => file.path.endsWith(".css")).map((file) => file.text).join("\n");
|
|
743
|
+
const javascript = bundled.outputFiles.find((file) => file.path.endsWith(".js"))?.text ?? "";
|
|
744
|
+
const css = bundled.outputFiles.filter((file) => file.path.endsWith(".css")).map((file) => file.text).join("\n");
|
|
805
745
|
const html = renderWidgetHtml(entry.name, javascript, css);
|
|
806
746
|
const hash = createHash("sha256").update(html).digest("hex").slice(0, 12);
|
|
807
|
-
const outputDir =
|
|
808
|
-
const outputFile =
|
|
747
|
+
const outputDir = path3.join(outDir, "public", "widgets", safeId);
|
|
748
|
+
const outputFile = path3.join(outputDir, `widget.${hash}.html`);
|
|
809
749
|
const resourceUri = `ui://${safeId}/widget.${hash}.html`;
|
|
810
750
|
await mkdir(outputDir, { recursive: true });
|
|
811
751
|
await writeFile(outputFile, html);
|
|
812
752
|
entry.widget.resourceUri = resourceUri;
|
|
813
753
|
entry.widget.resourceMeta = widgetResourceMeta(entry.widget.options, entry.target);
|
|
814
|
-
entry.widget.outputFile =
|
|
754
|
+
entry.widget.outputFile = path3.relative(outDir, outputFile);
|
|
815
755
|
entry.descriptor._meta = mergeWidgetMeta(entry.descriptor._meta, widgetMeta(resourceUri, entry.widget.options, entry.target));
|
|
816
756
|
}
|
|
817
757
|
}
|
|
818
|
-
function widgetBuildOptionsFromConfig(rootDir, config) {
|
|
819
|
-
const esbuildConfig = config?.esbuild;
|
|
820
|
-
if (!esbuildConfig) {
|
|
821
|
-
return void 0;
|
|
822
|
-
}
|
|
823
|
-
return {
|
|
824
|
-
alias: normalizeAliases(rootDir, esbuildConfig.alias),
|
|
825
|
-
conditions: esbuildConfig.conditions,
|
|
826
|
-
define: esbuildConfig.define,
|
|
827
|
-
external: esbuildConfig.external,
|
|
828
|
-
jsx: esbuildConfig.jsx,
|
|
829
|
-
jsxImportSource: esbuildConfig.jsxImportSource,
|
|
830
|
-
loader: esbuildConfig.loader,
|
|
831
|
-
mainFields: esbuildConfig.mainFields
|
|
832
|
-
};
|
|
833
|
-
}
|
|
834
|
-
async function loadWidgetBundlerHook(rootDir, cacheDir, hookPath) {
|
|
835
|
-
if (!hookPath) {
|
|
836
|
-
return void 0;
|
|
837
|
-
}
|
|
838
|
-
const sourcePath = path4.resolve(rootDir, hookPath);
|
|
839
|
-
const relative = path4.relative(rootDir, sourcePath);
|
|
840
|
-
if (relative.startsWith("..") || path4.isAbsolute(relative)) {
|
|
841
|
-
throw new Error(`Widget bundler hook must stay inside the project root: ${hookPath}`);
|
|
842
|
-
}
|
|
843
|
-
if (!existsSync3(sourcePath)) {
|
|
844
|
-
throw new Error(`Widget bundler hook not found: ${hookPath}`);
|
|
845
|
-
}
|
|
846
|
-
const outputFile = path4.join(cacheDir, `widget-bundler.${contentHash(hookPath)}.mjs`);
|
|
847
|
-
await esbuild({
|
|
848
|
-
absWorkingDir: rootDir,
|
|
849
|
-
alias: devSidecarBundleAliases(rootDir),
|
|
850
|
-
bundle: true,
|
|
851
|
-
entryPoints: [sourcePath],
|
|
852
|
-
format: "esm",
|
|
853
|
-
nodePaths: [
|
|
854
|
-
path4.join(rootDir, "node_modules"),
|
|
855
|
-
path4.join(process.cwd(), "node_modules")
|
|
856
|
-
],
|
|
857
|
-
outfile: outputFile,
|
|
858
|
-
packages: "external",
|
|
859
|
-
platform: "node",
|
|
860
|
-
target: "node20"
|
|
861
|
-
});
|
|
862
|
-
const module = await import(`${pathToFileURL2(outputFile).href}?t=${Date.now()}`);
|
|
863
|
-
if (typeof module.default !== "function") {
|
|
864
|
-
throw new Error(`Widget bundler hook must default-export a function: ${hookPath}`);
|
|
865
|
-
}
|
|
866
|
-
return module.default;
|
|
867
|
-
}
|
|
868
|
-
async function configureWidgetBuild(hook, input) {
|
|
869
|
-
const result = await hook(input);
|
|
870
|
-
if (!result) {
|
|
871
|
-
return void 0;
|
|
872
|
-
}
|
|
873
|
-
if (typeof result === "object" && "esbuildOptions" in result) {
|
|
874
|
-
return result.esbuildOptions;
|
|
875
|
-
}
|
|
876
|
-
return result;
|
|
877
|
-
}
|
|
878
|
-
function mergeWidgetBuildOptions(...options) {
|
|
879
|
-
const merged = {};
|
|
880
|
-
for (const option of options) {
|
|
881
|
-
if (!option) {
|
|
882
|
-
continue;
|
|
883
|
-
}
|
|
884
|
-
const previousAlias = merged.alias;
|
|
885
|
-
const previousDefine = merged.define;
|
|
886
|
-
const previousLoader = merged.loader;
|
|
887
|
-
const previousExternal = merged.external;
|
|
888
|
-
const previousNodePaths = merged.nodePaths;
|
|
889
|
-
const previousPlugins = merged.plugins;
|
|
890
|
-
Object.assign(merged, option);
|
|
891
|
-
merged.alias = { ...previousAlias ?? {}, ...option.alias ?? {} };
|
|
892
|
-
merged.define = { ...previousDefine ?? {}, ...option.define ?? {} };
|
|
893
|
-
merged.loader = { ...previousLoader ?? {}, ...option.loader ?? {} };
|
|
894
|
-
merged.external = uniqueStrings([...previousExternal ?? [], ...option.external ?? []]);
|
|
895
|
-
merged.nodePaths = uniqueStrings([...previousNodePaths ?? [], ...option.nodePaths ?? []]);
|
|
896
|
-
merged.plugins = [...previousPlugins ?? [], ...option.plugins ?? []];
|
|
897
|
-
}
|
|
898
|
-
return merged;
|
|
899
|
-
}
|
|
900
|
-
function enforceWidgetBuildInvariants(options, required) {
|
|
901
|
-
const aliases = required ? { ...options.alias ?? {}, ...reactSingletonAliases(required.rootDir) } : options.alias;
|
|
902
|
-
return {
|
|
903
|
-
...options,
|
|
904
|
-
absWorkingDir: required?.rootDir ?? options.absWorkingDir,
|
|
905
|
-
alias: aliases,
|
|
906
|
-
bundle: true,
|
|
907
|
-
entryPoints: required ? [required.entryFile] : options.entryPoints,
|
|
908
|
-
format: "iife",
|
|
909
|
-
outfile: "widget.js",
|
|
910
|
-
platform: "browser",
|
|
911
|
-
write: false
|
|
912
|
-
};
|
|
913
|
-
}
|
|
914
|
-
function sidecarWidgetAliases(rootDir) {
|
|
915
|
-
return {
|
|
916
|
-
...devSidecarBundleAliases(rootDir) ?? {},
|
|
917
|
-
...reactSingletonAliases(rootDir)
|
|
918
|
-
};
|
|
919
|
-
}
|
|
920
|
-
function reactSingletonAliases(rootDir) {
|
|
921
|
-
return {
|
|
922
|
-
react: resolveProjectModule(rootDir, "react"),
|
|
923
|
-
"react/jsx-runtime": resolveProjectModule(rootDir, "react/jsx-runtime"),
|
|
924
|
-
"react/jsx-dev-runtime": resolveProjectModule(rootDir, "react/jsx-dev-runtime"),
|
|
925
|
-
"react-dom": resolveProjectModule(rootDir, "react-dom"),
|
|
926
|
-
"react-dom/client": resolveProjectModule(rootDir, "react-dom/client"),
|
|
927
|
-
"react-dom/server": resolveProjectModule(rootDir, "react-dom/server")
|
|
928
|
-
};
|
|
929
|
-
}
|
|
930
|
-
function resolveProjectModule(rootDir, specifier) {
|
|
931
|
-
return requireFromCompiler.resolve(specifier, {
|
|
932
|
-
paths: [rootDir, process.cwd()]
|
|
933
|
-
});
|
|
934
|
-
}
|
|
935
|
-
function normalizeAliases(rootDir, aliases) {
|
|
936
|
-
if (!aliases) {
|
|
937
|
-
return void 0;
|
|
938
|
-
}
|
|
939
|
-
return Object.fromEntries(
|
|
940
|
-
Object.entries(aliases).map(([key, value]) => [
|
|
941
|
-
key,
|
|
942
|
-
value.startsWith(".") ? path4.resolve(rootDir, value) : value
|
|
943
|
-
])
|
|
944
|
-
);
|
|
945
|
-
}
|
|
946
|
-
function uniqueStrings(values) {
|
|
947
|
-
return [...new Set(values)];
|
|
948
|
-
}
|
|
949
|
-
function contentHash(value) {
|
|
950
|
-
return createHash("sha256").update(value).digest("hex").slice(0, 12);
|
|
951
|
-
}
|
|
952
758
|
function devSidecarBundleAliases(rootDir) {
|
|
953
759
|
const repoRoot = findSidecarRepoRoot(rootDir) ?? findSidecarRepoRoot(process.cwd());
|
|
954
760
|
if (!repoRoot) {
|
|
955
761
|
return void 0;
|
|
956
762
|
}
|
|
957
|
-
const reactEntry =
|
|
958
|
-
if (!
|
|
763
|
+
const reactEntry = path3.join(repoRoot, "packages", "react", "src", "index.ts");
|
|
764
|
+
if (!existsSync2(reactEntry)) {
|
|
959
765
|
return void 0;
|
|
960
766
|
}
|
|
961
767
|
return {
|
|
962
|
-
"sidecar-ai":
|
|
963
|
-
"@sidecar-ai/client":
|
|
964
|
-
"@sidecar-ai/core":
|
|
768
|
+
"sidecar-ai": path3.join(repoRoot, "packages", "sidecar-ai", "src", "index.ts"),
|
|
769
|
+
"@sidecar-ai/client": path3.join(repoRoot, "packages", "client", "src", "index.ts"),
|
|
770
|
+
"@sidecar-ai/core": path3.join(repoRoot, "packages", "core", "src", "index.ts"),
|
|
965
771
|
"@sidecar-ai/react": reactEntry,
|
|
966
|
-
"@sidecar-ai/native":
|
|
967
|
-
"@sidecar-ai/native/components":
|
|
968
|
-
"@sidecar-ai/native/styles.css":
|
|
772
|
+
"@sidecar-ai/native": path3.join(repoRoot, "packages", "native", "src", "index.ts"),
|
|
773
|
+
"@sidecar-ai/native/components": path3.join(repoRoot, "packages", "native", "src", "components", "index.tsx"),
|
|
774
|
+
"@sidecar-ai/native/styles.css": path3.join(repoRoot, "packages", "native", "src", "styles.css")
|
|
969
775
|
};
|
|
970
776
|
}
|
|
971
777
|
function findSidecarRepoRoot(startDir) {
|
|
972
|
-
let current =
|
|
778
|
+
let current = path3.resolve(startDir);
|
|
973
779
|
while (true) {
|
|
974
|
-
if (
|
|
780
|
+
if (existsSync2(path3.join(current, "packages", "core", "src", "index.ts"))) {
|
|
975
781
|
return current;
|
|
976
782
|
}
|
|
977
|
-
const parent =
|
|
783
|
+
const parent = path3.dirname(current);
|
|
978
784
|
if (parent === current) {
|
|
979
785
|
return void 0;
|
|
980
786
|
}
|
|
@@ -982,13 +788,13 @@ function findSidecarRepoRoot(startDir) {
|
|
|
982
788
|
}
|
|
983
789
|
}
|
|
984
790
|
async function prepareAppStyle(rootDir, cacheDir) {
|
|
985
|
-
const sourceFile =
|
|
986
|
-
if (!
|
|
791
|
+
const sourceFile = path3.join(rootDir, "style.css");
|
|
792
|
+
if (!existsSync2(sourceFile)) {
|
|
987
793
|
return void 0;
|
|
988
794
|
}
|
|
989
795
|
const source = await readFile(sourceFile, "utf8");
|
|
990
796
|
const css = await processAppStyle(source, sourceFile);
|
|
991
|
-
const outputFile =
|
|
797
|
+
const outputFile = path3.join(cacheDir, "style.css");
|
|
992
798
|
await writeFile(outputFile, css);
|
|
993
799
|
return outputFile;
|
|
994
800
|
}
|
|
@@ -1000,7 +806,7 @@ async function processAppStyle(source, from) {
|
|
|
1000
806
|
const plugins = [];
|
|
1001
807
|
if (cssSource.includes("@tailwind")) {
|
|
1002
808
|
const tailwind = await import("@tailwindcss/postcss");
|
|
1003
|
-
plugins.push(tailwind.default({ base:
|
|
809
|
+
plugins.push(tailwind.default({ base: path3.dirname(from) }));
|
|
1004
810
|
}
|
|
1005
811
|
const autoprefixer = await import("autoprefixer");
|
|
1006
812
|
plugins.push(autoprefixer.default());
|
|
@@ -1014,13 +820,13 @@ function needsPostcss(source) {
|
|
|
1014
820
|
return /@import\s+["']tailwindcss["']|@tailwind|@source|@theme|@plugin/.test(source);
|
|
1015
821
|
}
|
|
1016
822
|
function findWidget(rootDir, toolFile, id, target = "mcp", toolVariant = "shared") {
|
|
1017
|
-
const selected = selectWidgetFile(
|
|
823
|
+
const selected = selectWidgetFile(path3.dirname(toolFile), target, toolVariant);
|
|
1018
824
|
if (!selected) {
|
|
1019
825
|
return void 0;
|
|
1020
826
|
}
|
|
1021
827
|
const safeId = safePathSegment(id);
|
|
1022
828
|
return {
|
|
1023
|
-
sourceFile:
|
|
829
|
+
sourceFile: path3.relative(rootDir, selected.filePath),
|
|
1024
830
|
variant: selected.variant,
|
|
1025
831
|
resourceUri: `ui://${safeId}/widget.html`
|
|
1026
832
|
};
|
|
@@ -1055,8 +861,7 @@ function widgetMeta(resourceUri, options = {}, target = "mcp") {
|
|
|
1055
861
|
const standard = {
|
|
1056
862
|
ui: {
|
|
1057
863
|
resourceUri
|
|
1058
|
-
}
|
|
1059
|
-
"ui/resourceUri": resourceUri
|
|
864
|
+
}
|
|
1060
865
|
};
|
|
1061
866
|
if (target !== "chatgpt") {
|
|
1062
867
|
return standard;
|
|
@@ -1203,17 +1008,17 @@ function readStringArrayProperty(definition, propertyName) {
|
|
|
1203
1008
|
}
|
|
1204
1009
|
function selectWidgetFile(directory, target, toolVariant) {
|
|
1205
1010
|
if (toolVariant === "openai") {
|
|
1206
|
-
const filePath =
|
|
1207
|
-
return
|
|
1011
|
+
const filePath = path3.join(directory, "widget.openai.tsx");
|
|
1012
|
+
return existsSync2(filePath) ? { filePath, variant: "openai" } : void 0;
|
|
1208
1013
|
}
|
|
1209
1014
|
if (toolVariant === "anthropic") {
|
|
1210
|
-
const filePath =
|
|
1211
|
-
return
|
|
1015
|
+
const filePath = path3.join(directory, "widget.anthropic.tsx");
|
|
1016
|
+
return existsSync2(filePath) ? { filePath, variant: "anthropic" } : void 0;
|
|
1212
1017
|
}
|
|
1213
1018
|
const candidates = target === "chatgpt" || target === "claude" || target === "mcp" ? [{ name: "widget.tsx", variant: "shared" }] : [];
|
|
1214
1019
|
for (const candidate of candidates) {
|
|
1215
|
-
const filePath =
|
|
1216
|
-
if (
|
|
1020
|
+
const filePath = path3.join(directory, candidate.name);
|
|
1021
|
+
if (existsSync2(filePath)) {
|
|
1217
1022
|
return { filePath, variant: candidate.variant };
|
|
1218
1023
|
}
|
|
1219
1024
|
}
|
|
@@ -1264,23 +1069,17 @@ function stripUndefined3(value) {
|
|
|
1264
1069
|
// packages/compiler/src/analyze.ts
|
|
1265
1070
|
async function analyzeProjectTools(rootDir, options = {}) {
|
|
1266
1071
|
const target = options.target ?? "mcp";
|
|
1267
|
-
const toolFiles = await findToolFiles(
|
|
1072
|
+
const toolFiles = await findToolFiles(path4.join(rootDir, "server"), target);
|
|
1268
1073
|
if (toolFiles.length === 0) {
|
|
1269
1074
|
return [];
|
|
1270
1075
|
}
|
|
1271
1076
|
const project = createProject(rootDir);
|
|
1272
1077
|
const authScopes = readAuthScopeCatalog(project, rootDir);
|
|
1273
|
-
|
|
1274
|
-
candidate,
|
|
1275
|
-
sourceFile: project.addSourceFileAtPath(candidate.filePath)
|
|
1276
|
-
}));
|
|
1277
|
-
const runtimeInputSchemas = await readRuntimeInputSchemas(rootDir, sources);
|
|
1278
|
-
return sources.map(
|
|
1279
|
-
({ candidate, sourceFile }) => analyzeToolFile(sourceFile, rootDir, {
|
|
1078
|
+
return toolFiles.map(
|
|
1079
|
+
(candidate) => analyzeToolFile(project.addSourceFileAtPath(candidate.filePath), rootDir, {
|
|
1280
1080
|
target,
|
|
1281
1081
|
variant: candidate.variant,
|
|
1282
|
-
authScopes
|
|
1283
|
-
inputSchema: runtimeInputSchemas.get(candidate.filePath)
|
|
1082
|
+
authScopes
|
|
1284
1083
|
})
|
|
1285
1084
|
);
|
|
1286
1085
|
}
|
|
@@ -1289,7 +1088,7 @@ function analyzeToolFile(sourceFile, rootDir, options = {}) {
|
|
|
1289
1088
|
const variant = options.variant ?? "shared";
|
|
1290
1089
|
const definition = findToolDefinition(sourceFile);
|
|
1291
1090
|
const absoluteFile = sourceFile.getFilePath();
|
|
1292
|
-
const directory =
|
|
1091
|
+
const directory = path4.basename(path4.dirname(absoluteFile));
|
|
1293
1092
|
const name = getRequiredStringProperty(definition, "name", sourceFile);
|
|
1294
1093
|
const id = getOptionalStringProperty(definition, "id") ?? toMachineName(directory);
|
|
1295
1094
|
const description = getRequiredStringProperty(
|
|
@@ -1302,7 +1101,7 @@ function analyzeToolFile(sourceFile, rootDir, options = {}) {
|
|
|
1302
1101
|
const hosts = readHosts(definition);
|
|
1303
1102
|
const auth = readAuthPolicy(definition, options.authScopes ?? {});
|
|
1304
1103
|
const execute = getExecuteFunction(definition, sourceFile);
|
|
1305
|
-
const inputSchema =
|
|
1104
|
+
const inputSchema = getParamsSchema(definition, execute);
|
|
1306
1105
|
const outputSchema = getOutputSchema(definition, execute);
|
|
1307
1106
|
const descriptor = createToolDescriptor({
|
|
1308
1107
|
name,
|
|
@@ -1320,7 +1119,7 @@ function analyzeToolFile(sourceFile, rootDir, options = {}) {
|
|
|
1320
1119
|
validateWidgetHierarchy(sourceFile, absoluteFile, target, variant);
|
|
1321
1120
|
const widget = findWidget(rootDir, absoluteFile, id, target, variant);
|
|
1322
1121
|
if (widget) {
|
|
1323
|
-
const widgetFile =
|
|
1122
|
+
const widgetFile = path4.join(rootDir, widget.sourceFile);
|
|
1324
1123
|
const project = sourceFile.getProject();
|
|
1325
1124
|
const widgetSourceFile = project.getSourceFile(widgetFile) ?? project.addSourceFileAtPath(widgetFile);
|
|
1326
1125
|
widget.options = {
|
|
@@ -1331,7 +1130,7 @@ function analyzeToolFile(sourceFile, rootDir, options = {}) {
|
|
|
1331
1130
|
descriptor._meta = mergeWidgetMeta(descriptor._meta, widgetMeta(widget.resourceUri, widget.options, target));
|
|
1332
1131
|
}
|
|
1333
1132
|
return {
|
|
1334
|
-
sourceFile:
|
|
1133
|
+
sourceFile: path4.relative(rootDir, absoluteFile),
|
|
1335
1134
|
variant,
|
|
1336
1135
|
target,
|
|
1337
1136
|
directory,
|
|
@@ -1346,26 +1145,6 @@ function analyzeToolFile(sourceFile, rootDir, options = {}) {
|
|
|
1346
1145
|
descriptor
|
|
1347
1146
|
};
|
|
1348
1147
|
}
|
|
1349
|
-
async function readRuntimeInputSchemas(rootDir, sources) {
|
|
1350
|
-
const schemas = /* @__PURE__ */ new Map();
|
|
1351
|
-
await Promise.all(sources.map(async ({ candidate, sourceFile }) => {
|
|
1352
|
-
const definition = findToolDefinition(sourceFile);
|
|
1353
|
-
if (!definitionHasRuntimeParams(definition)) {
|
|
1354
|
-
return;
|
|
1355
|
-
}
|
|
1356
|
-
const schema = await readRuntimeToolInputSchema(rootDir, candidate.filePath);
|
|
1357
|
-
if (schema) {
|
|
1358
|
-
schemas.set(candidate.filePath, schema);
|
|
1359
|
-
}
|
|
1360
|
-
}));
|
|
1361
|
-
return schemas;
|
|
1362
|
-
}
|
|
1363
|
-
function definitionHasRuntimeParams(definition) {
|
|
1364
|
-
if (definition.getProperty("params")) {
|
|
1365
|
-
return true;
|
|
1366
|
-
}
|
|
1367
|
-
return Boolean(getWithParamsCall(definition));
|
|
1368
|
-
}
|
|
1369
1148
|
function readAuthPolicy(definition, authScopes) {
|
|
1370
1149
|
const initializer = readObjectProperty2(definition, "auth");
|
|
1371
1150
|
if (!initializer) {
|
|
@@ -1382,7 +1161,7 @@ function readAuthPolicy(definition, authScopes) {
|
|
|
1382
1161
|
return { authenticated: true };
|
|
1383
1162
|
}
|
|
1384
1163
|
function readAuthScopeCatalog(project, rootDir) {
|
|
1385
|
-
const authPath =
|
|
1164
|
+
const authPath = path4.join(rootDir, "auth.ts");
|
|
1386
1165
|
if (!existsSyncSafe(authPath)) {
|
|
1387
1166
|
return {};
|
|
1388
1167
|
}
|
|
@@ -1464,12 +1243,12 @@ function isNamedCall(call, name) {
|
|
|
1464
1243
|
return callee === name || callee.endsWith(`.${name}`);
|
|
1465
1244
|
}
|
|
1466
1245
|
function validateWidgetHierarchy(sourceFile, toolFile, target, variant) {
|
|
1467
|
-
const directory =
|
|
1246
|
+
const directory = path4.dirname(toolFile);
|
|
1468
1247
|
const platformWidget = target === "chatgpt" ? "widget.openai.tsx" : target === "claude" ? "widget.anthropic.tsx" : void 0;
|
|
1469
1248
|
if (!platformWidget || variant !== "shared") {
|
|
1470
1249
|
return;
|
|
1471
1250
|
}
|
|
1472
|
-
if (existsSyncSafe(
|
|
1251
|
+
if (existsSyncSafe(path4.join(directory, platformWidget))) {
|
|
1473
1252
|
const expectedTool = target === "chatgpt" ? "tool.openai.ts" : "tool.anthropic.ts";
|
|
1474
1253
|
throw new CompilerError(
|
|
1475
1254
|
sourceFile,
|
|
@@ -1484,7 +1263,7 @@ async function findToolFiles(serverDir, target) {
|
|
|
1484
1263
|
const entries = await readdir(serverDir, { withFileTypes: true });
|
|
1485
1264
|
const files = [];
|
|
1486
1265
|
for (const entry of entries) {
|
|
1487
|
-
const entryPath =
|
|
1266
|
+
const entryPath = path4.join(serverDir, entry.name);
|
|
1488
1267
|
if (entry.isDirectory()) {
|
|
1489
1268
|
const candidate = selectToolFile(entryPath, target);
|
|
1490
1269
|
if (candidate) {
|
|
@@ -1503,7 +1282,7 @@ function selectToolFile(directory, target) {
|
|
|
1503
1282
|
{ name: "tool.ts", variant: "shared" }
|
|
1504
1283
|
] : [{ name: "tool.ts", variant: "shared" }];
|
|
1505
1284
|
for (const candidate of candidates) {
|
|
1506
|
-
const filePath =
|
|
1285
|
+
const filePath = path4.join(directory, candidate.name);
|
|
1507
1286
|
if (existsSyncSafe(filePath)) {
|
|
1508
1287
|
return { filePath, variant: candidate.variant };
|
|
1509
1288
|
}
|
|
@@ -1539,32 +1318,16 @@ function getExecuteFunction(definition, sourceFile) {
|
|
|
1539
1318
|
return property;
|
|
1540
1319
|
}
|
|
1541
1320
|
if (Node4.isPropertyAssignment(property)) {
|
|
1542
|
-
const initializer =
|
|
1321
|
+
const initializer = property.getInitializer();
|
|
1543
1322
|
if (initializer && (Node4.isArrowFunction(initializer) || Node4.isFunctionExpression(initializer))) {
|
|
1544
1323
|
return initializer;
|
|
1545
1324
|
}
|
|
1546
|
-
const withParamsCall = getWithParamsCall(definition);
|
|
1547
|
-
const wrappedExecute = unwrapExpression(withParamsCall?.getArguments()[1]);
|
|
1548
|
-
if (wrappedExecute && (Node4.isArrowFunction(wrappedExecute) || Node4.isFunctionExpression(wrappedExecute))) {
|
|
1549
|
-
return wrappedExecute;
|
|
1550
|
-
}
|
|
1551
1325
|
}
|
|
1552
1326
|
throw new CompilerError(
|
|
1553
1327
|
sourceFile,
|
|
1554
1328
|
"execute must be a method, function expression, or arrow function."
|
|
1555
1329
|
);
|
|
1556
1330
|
}
|
|
1557
|
-
function getWithParamsCall(definition) {
|
|
1558
|
-
const property = definition.getProperty("execute");
|
|
1559
|
-
if (!property || !Node4.isPropertyAssignment(property)) {
|
|
1560
|
-
return void 0;
|
|
1561
|
-
}
|
|
1562
|
-
const initializer = unwrapExpression(property.getInitializer());
|
|
1563
|
-
if (!initializer || !Node4.isCallExpression(initializer)) {
|
|
1564
|
-
return void 0;
|
|
1565
|
-
}
|
|
1566
|
-
return isNamedCall(initializer, "withParams") ? initializer : void 0;
|
|
1567
|
-
}
|
|
1568
1331
|
function getRequiredStringProperty(definition, propertyName, sourceFile) {
|
|
1569
1332
|
const value = getOptionalStringProperty(definition, propertyName);
|
|
1570
1333
|
if (value === void 0 || !value.trim()) {
|
|
@@ -1720,16 +1483,16 @@ function readStringArrayProperty2(definition, propertyName) {
|
|
|
1720
1483
|
|
|
1721
1484
|
// packages/compiler/src/build.ts
|
|
1722
1485
|
import { mkdir as mkdir9, writeFile as writeFile9 } from "fs/promises";
|
|
1723
|
-
import
|
|
1486
|
+
import path18 from "path";
|
|
1724
1487
|
|
|
1725
1488
|
// packages/compiler/src/config.ts
|
|
1726
|
-
import
|
|
1489
|
+
import path5 from "path";
|
|
1727
1490
|
import {
|
|
1728
1491
|
Node as Node5,
|
|
1729
1492
|
SyntaxKind as SyntaxKind3
|
|
1730
1493
|
} from "ts-morph";
|
|
1731
1494
|
function analyzeProjectConfig(rootDir) {
|
|
1732
|
-
const configPath =
|
|
1495
|
+
const configPath = path5.join(rootDir, "sidecar.config.ts");
|
|
1733
1496
|
if (!existsSyncSafe(configPath)) {
|
|
1734
1497
|
return defaultCompilerConfig();
|
|
1735
1498
|
}
|
|
@@ -1745,8 +1508,7 @@ function analyzeProjectConfig(rootDir) {
|
|
|
1745
1508
|
target: readTargetNested(definition, "build", "target"),
|
|
1746
1509
|
host: readHostNested(definition, "build", "host"),
|
|
1747
1510
|
outDir: readStringNested(definition, "build", "outDir"),
|
|
1748
|
-
plugins: readBooleanNested(definition, "build", "plugins")
|
|
1749
|
-
widgets: readWidgetBuildConfig(definition)
|
|
1511
|
+
plugins: readBooleanNested(definition, "build", "plugins")
|
|
1750
1512
|
},
|
|
1751
1513
|
resources: {
|
|
1752
1514
|
subscribe: readBooleanNested(definition, "resources", "subscribe") ?? false,
|
|
@@ -1759,49 +1521,11 @@ function analyzeProjectConfig(rootDir) {
|
|
|
1759
1521
|
listChanged: readBooleanNested(definition, "tools", "listChanged") ?? false
|
|
1760
1522
|
},
|
|
1761
1523
|
pagination: {
|
|
1762
|
-
pageSize: readNumberNested(definition, "pagination", "pageSize") ??
|
|
1524
|
+
pageSize: readNumberNested(definition, "pagination", "pageSize") ?? 10,
|
|
1763
1525
|
hasOverride: hasProperty(readObjectProperty3(definition, "pagination"), "override")
|
|
1764
1526
|
}
|
|
1765
1527
|
};
|
|
1766
1528
|
}
|
|
1767
|
-
function readWidgetBuildConfig(definition) {
|
|
1768
|
-
const widgets = readObjectProperty3(readObjectProperty3(definition, "build"), "widgets");
|
|
1769
|
-
if (!widgets) {
|
|
1770
|
-
return void 0;
|
|
1771
|
-
}
|
|
1772
|
-
const config = {};
|
|
1773
|
-
const configure = readStringProperty3(widgets, "configure");
|
|
1774
|
-
const esbuild3 = readWidgetEsbuildConfig(widgets);
|
|
1775
|
-
if (configure) config.configure = configure;
|
|
1776
|
-
if (esbuild3) config.esbuild = esbuild3;
|
|
1777
|
-
return Object.keys(config).length ? config : void 0;
|
|
1778
|
-
}
|
|
1779
|
-
function readWidgetEsbuildConfig(widgets) {
|
|
1780
|
-
const esbuild3 = readObjectProperty3(widgets, "esbuild");
|
|
1781
|
-
if (!esbuild3) {
|
|
1782
|
-
return void 0;
|
|
1783
|
-
}
|
|
1784
|
-
const config = {};
|
|
1785
|
-
const alias = readStringRecordProperty(esbuild3, "alias");
|
|
1786
|
-
const define = readStringRecordProperty(esbuild3, "define");
|
|
1787
|
-
const external = readStringArrayProperty3(esbuild3, "external");
|
|
1788
|
-
const loader = readStringRecordProperty(esbuild3, "loader");
|
|
1789
|
-
const conditions = readStringArrayProperty3(esbuild3, "conditions");
|
|
1790
|
-
const mainFields = readStringArrayProperty3(esbuild3, "mainFields");
|
|
1791
|
-
const jsx = readStringProperty3(esbuild3, "jsx");
|
|
1792
|
-
const jsxImportSource = readStringProperty3(esbuild3, "jsxImportSource");
|
|
1793
|
-
if (alias) config.alias = alias;
|
|
1794
|
-
if (define) config.define = define;
|
|
1795
|
-
if (external) config.external = external;
|
|
1796
|
-
if (loader) config.loader = loader;
|
|
1797
|
-
if (conditions) config.conditions = conditions;
|
|
1798
|
-
if (mainFields) config.mainFields = mainFields;
|
|
1799
|
-
if (jsx === "automatic" || jsx === "transform" || jsx === "preserve") {
|
|
1800
|
-
config.jsx = jsx;
|
|
1801
|
-
}
|
|
1802
|
-
if (jsxImportSource) config.jsxImportSource = jsxImportSource;
|
|
1803
|
-
return Object.keys(config).length ? config : void 0;
|
|
1804
|
-
}
|
|
1805
1529
|
function defaultCompilerConfig() {
|
|
1806
1530
|
return {
|
|
1807
1531
|
build: {},
|
|
@@ -1816,7 +1540,7 @@ function defaultCompilerConfig() {
|
|
|
1816
1540
|
listChanged: false
|
|
1817
1541
|
},
|
|
1818
1542
|
pagination: {
|
|
1819
|
-
pageSize:
|
|
1543
|
+
pageSize: 10,
|
|
1820
1544
|
hasOverride: false
|
|
1821
1545
|
}
|
|
1822
1546
|
};
|
|
@@ -1834,7 +1558,12 @@ function readStringNested(definition, section, propertyName) {
|
|
|
1834
1558
|
if (!object) {
|
|
1835
1559
|
return void 0;
|
|
1836
1560
|
}
|
|
1837
|
-
|
|
1561
|
+
const property = object.getProperty(propertyName);
|
|
1562
|
+
if (!property || !Node5.isPropertyAssignment(property)) {
|
|
1563
|
+
return void 0;
|
|
1564
|
+
}
|
|
1565
|
+
const initializer = unwrapExpression(property.getInitializer());
|
|
1566
|
+
return initializer && Node5.isStringLiteral(initializer) ? initializer.getLiteralText() : void 0;
|
|
1838
1567
|
}
|
|
1839
1568
|
function readBooleanNested(definition, section, propertyName) {
|
|
1840
1569
|
const object = readObjectProperty3(definition, section);
|
|
@@ -1866,9 +1595,6 @@ function readNumberNested(definition, section, propertyName) {
|
|
|
1866
1595
|
return initializer && Node5.isNumericLiteral(initializer) ? Number(initializer.getLiteralText()) : void 0;
|
|
1867
1596
|
}
|
|
1868
1597
|
function readObjectProperty3(definition, propertyName) {
|
|
1869
|
-
if (!definition) {
|
|
1870
|
-
return void 0;
|
|
1871
|
-
}
|
|
1872
1598
|
const property = definition.getProperty(propertyName);
|
|
1873
1599
|
if (!property || !Node5.isPropertyAssignment(property)) {
|
|
1874
1600
|
return void 0;
|
|
@@ -1876,79 +1602,38 @@ function readObjectProperty3(definition, propertyName) {
|
|
|
1876
1602
|
const initializer = unwrapExpression(property.getInitializer());
|
|
1877
1603
|
return initializer && Node5.isObjectLiteralExpression(initializer) ? initializer : void 0;
|
|
1878
1604
|
}
|
|
1879
|
-
function readStringProperty3(definition, propertyName) {
|
|
1880
|
-
const property = definition.getProperty(propertyName);
|
|
1881
|
-
if (!property || !Node5.isPropertyAssignment(property)) {
|
|
1882
|
-
return void 0;
|
|
1883
|
-
}
|
|
1884
|
-
const initializer = unwrapExpression(property.getInitializer());
|
|
1885
|
-
return initializer && Node5.isStringLiteral(initializer) ? initializer.getLiteralText() : void 0;
|
|
1886
|
-
}
|
|
1887
|
-
function readStringArrayProperty3(definition, propertyName) {
|
|
1888
|
-
const property = definition.getProperty(propertyName);
|
|
1889
|
-
if (!property || !Node5.isPropertyAssignment(property)) {
|
|
1890
|
-
return void 0;
|
|
1891
|
-
}
|
|
1892
|
-
const initializer = unwrapExpression(property.getInitializer());
|
|
1893
|
-
if (!initializer || !Node5.isArrayLiteralExpression(initializer)) {
|
|
1894
|
-
return void 0;
|
|
1895
|
-
}
|
|
1896
|
-
const values = initializer.getElements().map((element) => {
|
|
1897
|
-
const unwrapped = unwrapExpression(element);
|
|
1898
|
-
return unwrapped && Node5.isStringLiteral(unwrapped) ? unwrapped.getLiteralText() : void 0;
|
|
1899
|
-
});
|
|
1900
|
-
return values.every((value) => value !== void 0) ? values : void 0;
|
|
1901
|
-
}
|
|
1902
|
-
function readStringRecordProperty(definition, propertyName) {
|
|
1903
|
-
const object = readObjectProperty3(definition, propertyName);
|
|
1904
|
-
if (!object) {
|
|
1905
|
-
return void 0;
|
|
1906
|
-
}
|
|
1907
|
-
const record = {};
|
|
1908
|
-
for (const property of object.getProperties()) {
|
|
1909
|
-
if (!Node5.isPropertyAssignment(property)) {
|
|
1910
|
-
return void 0;
|
|
1911
|
-
}
|
|
1912
|
-
const initializer = unwrapExpression(property.getInitializer());
|
|
1913
|
-
if (!initializer || !Node5.isStringLiteral(initializer)) {
|
|
1914
|
-
return void 0;
|
|
1915
|
-
}
|
|
1916
|
-
record[property.getName().replace(/^["']|["']$/g, "")] = initializer.getLiteralText();
|
|
1917
|
-
}
|
|
1918
|
-
return record;
|
|
1919
|
-
}
|
|
1920
1605
|
function hasProperty(definition, propertyName) {
|
|
1921
1606
|
return Boolean(definition?.getProperty(propertyName));
|
|
1922
1607
|
}
|
|
1923
1608
|
|
|
1924
1609
|
// packages/compiler/src/diagnostics.ts
|
|
1925
|
-
import { existsSync as
|
|
1610
|
+
import { existsSync as existsSync3 } from "fs";
|
|
1926
1611
|
import { readFile as readFile2 } from "fs/promises";
|
|
1927
|
-
import
|
|
1612
|
+
import path6 from "path";
|
|
1928
1613
|
async function collectProjectDiagnostics(rootDir, input) {
|
|
1929
1614
|
const diagnostics = [];
|
|
1930
1615
|
const tools = Array.isArray(input) ? input : input.tools;
|
|
1931
1616
|
const resources = Array.isArray(input) ? [] : input.resources ?? [];
|
|
1932
1617
|
const prompts = Array.isArray(input) ? [] : input.prompts ?? [];
|
|
1933
1618
|
const config = Array.isArray(input) ? void 0 : input.config;
|
|
1934
|
-
const hasAuthConfig =
|
|
1619
|
+
const hasAuthConfig = existsSync3(path6.join(rootDir, "auth.ts"));
|
|
1935
1620
|
for (const entry of tools) {
|
|
1936
|
-
const toolPath =
|
|
1621
|
+
const toolPath = path6.join(rootDir, entry.sourceFile);
|
|
1937
1622
|
const toolSource = await readFile2(toolPath, "utf8");
|
|
1938
|
-
diagnostics.push(...diagnoseToolSource(entry, toolSource, hasAuthConfig));
|
|
1623
|
+
diagnostics.push(...diagnoseToolSource(rootDir, entry, toolSource, hasAuthConfig));
|
|
1939
1624
|
if (entry.widget) {
|
|
1940
|
-
const widgetPath =
|
|
1625
|
+
const widgetPath = path6.join(rootDir, entry.widget.sourceFile);
|
|
1941
1626
|
const widgetSource = await readFile2(widgetPath, "utf8");
|
|
1942
1627
|
diagnostics.push(...diagnoseWidgetSource(rootDir, entry, widgetSource));
|
|
1943
1628
|
}
|
|
1944
1629
|
}
|
|
1945
1630
|
for (const entry of resources) {
|
|
1946
|
-
const resourcePath =
|
|
1631
|
+
const resourcePath = path6.join(rootDir, entry.sourceFile);
|
|
1947
1632
|
const resourceSource = await readFile2(resourcePath, "utf8");
|
|
1948
1633
|
diagnostics.push(...diagnoseResourceSource(entry, resourceSource));
|
|
1949
1634
|
}
|
|
1950
1635
|
for (const entry of prompts) {
|
|
1951
|
-
const promptPath =
|
|
1636
|
+
const promptPath = path6.join(rootDir, entry.sourceFile);
|
|
1952
1637
|
const promptSource = await readFile2(promptPath, "utf8");
|
|
1953
1638
|
diagnostics.push(...diagnosePromptSource(entry, promptSource));
|
|
1954
1639
|
}
|
|
@@ -1963,7 +1648,7 @@ function formatDiagnostic(diagnostic) {
|
|
|
1963
1648
|
hint: ${diagnostic.hint}` : "";
|
|
1964
1649
|
return `${location} - ${diagnostic.severity} ${diagnostic.code}: ${diagnostic.message}${hint}`;
|
|
1965
1650
|
}
|
|
1966
|
-
function diagnoseToolSource(entry, source, hasAuthConfig) {
|
|
1651
|
+
function diagnoseToolSource(rootDir, entry, source, hasAuthConfig) {
|
|
1967
1652
|
const diagnostics = [];
|
|
1968
1653
|
const toolLocation = locate(source, "tool({");
|
|
1969
1654
|
if (!entry.description.trim().startsWith("Use this when")) {
|
|
@@ -2180,21 +1865,21 @@ function isIgnored(source, code) {
|
|
|
2180
1865
|
|
|
2181
1866
|
// packages/compiler/src/generated.ts
|
|
2182
1867
|
import { mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
|
|
2183
|
-
import
|
|
1868
|
+
import path7 from "path";
|
|
2184
1869
|
async function writeGeneratedTypes(rootDir, tools) {
|
|
2185
|
-
const generatedDir =
|
|
1870
|
+
const generatedDir = path7.join(rootDir, ".sidecar", "generated");
|
|
2186
1871
|
await mkdir2(generatedDir, { recursive: true });
|
|
2187
1872
|
const appCallableTools = tools.filter(isAppCallable);
|
|
2188
1873
|
const methodNames = uniqueMethodNames(appCallableTools.map((entry) => toIdentifier(entry.id)));
|
|
2189
1874
|
const imports = appCallableTools.map(
|
|
2190
|
-
(entry, index) => `import type tool${index} from ${JSON.stringify(toImportSpecifier(generatedDir,
|
|
1875
|
+
(entry, index) => `import type tool${index} from ${JSON.stringify(toImportSpecifier(generatedDir, path7.join(rootDir, entry.sourceFile), { extension: "js" }))};`
|
|
2191
1876
|
).join("\n");
|
|
2192
1877
|
const ids = appCallableTools.map((entry, index) => ` ${methodNames[index]}: ${JSON.stringify(entry.id)}`).join(",\n");
|
|
2193
1878
|
const toolTypes = appCallableTools.map(
|
|
2194
|
-
(
|
|
1879
|
+
(entry, index) => ` ${methodNames[index]}(params: ToolParams<typeof tool${index}>): Promise<ToolOutput<typeof tool${index}>>;`
|
|
2195
1880
|
).join("\n");
|
|
2196
1881
|
await writeFile2(
|
|
2197
|
-
|
|
1882
|
+
path7.join(generatedDir, "tools.ts"),
|
|
2198
1883
|
`/**
|
|
2199
1884
|
* Generated Sidecar widget tool client.
|
|
2200
1885
|
*
|
|
@@ -2244,13 +1929,13 @@ function uniqueMethodNames(names) {
|
|
|
2244
1929
|
|
|
2245
1930
|
// packages/compiler/src/identity.ts
|
|
2246
1931
|
import { readFile as readFile3 } from "fs/promises";
|
|
2247
|
-
import
|
|
1932
|
+
import path8 from "path";
|
|
2248
1933
|
async function loadProjectIdentity(rootDir) {
|
|
2249
|
-
const packageJson = await readOptionalJson(
|
|
1934
|
+
const packageJson = await readOptionalJson(path8.join(rootDir, "package.json"));
|
|
2250
1935
|
const configText = await readOptionalText(
|
|
2251
|
-
|
|
1936
|
+
path8.join(rootDir, "sidecar.config.ts")
|
|
2252
1937
|
);
|
|
2253
|
-
const name = readConfigString(configText, "name") ?? packageJson?.name ??
|
|
1938
|
+
const name = readConfigString(configText, "name") ?? packageJson?.name ?? path8.basename(rootDir);
|
|
2254
1939
|
const version = readConfigString(configText, "version") ?? packageJson?.version ?? "0.0.0-dev";
|
|
2255
1940
|
const description = readConfigString(configText, "description") ?? packageJson?.description ?? `${name} Sidecar app.`;
|
|
2256
1941
|
return {
|
|
@@ -2284,32 +1969,32 @@ function readConfigString(configText, key) {
|
|
|
2284
1969
|
|
|
2285
1970
|
// packages/compiler/src/plugins.ts
|
|
2286
1971
|
import { mkdir as mkdir7, writeFile as writeFile7 } from "fs/promises";
|
|
2287
|
-
import
|
|
1972
|
+
import path14 from "path";
|
|
2288
1973
|
|
|
2289
1974
|
// packages/compiler/src/plugin-components/agents.ts
|
|
2290
1975
|
import { mkdir as mkdir3, readdir as readdir2, readFile as readFile4, writeFile as writeFile3 } from "fs/promises";
|
|
2291
|
-
import
|
|
1976
|
+
import path9 from "path";
|
|
2292
1977
|
async function emitClaudeAgents(rootDir, destination) {
|
|
2293
|
-
const source =
|
|
1978
|
+
const source = path9.join(rootDir, "agents");
|
|
2294
1979
|
if (!existsSyncSafe(source)) {
|
|
2295
1980
|
return;
|
|
2296
1981
|
}
|
|
2297
1982
|
const entries = await readdir2(source, { withFileTypes: true });
|
|
2298
1983
|
const agentDirs = entries.filter(
|
|
2299
|
-
(entry) => entry.isDirectory() && existsSyncSafe(
|
|
1984
|
+
(entry) => entry.isDirectory() && existsSyncSafe(path9.join(source, entry.name, "agent.ts"))
|
|
2300
1985
|
);
|
|
2301
1986
|
if (!agentDirs.length) {
|
|
2302
1987
|
return;
|
|
2303
1988
|
}
|
|
2304
1989
|
await mkdir3(destination, { recursive: true });
|
|
2305
1990
|
for (const entry of agentDirs) {
|
|
2306
|
-
const sourceText = await readFile4(
|
|
1991
|
+
const sourceText = await readFile4(path9.join(source, entry.name, "agent.ts"), "utf8");
|
|
2307
1992
|
const markdown = parseClaudeAgent(
|
|
2308
1993
|
sourceText,
|
|
2309
1994
|
entry.name
|
|
2310
1995
|
);
|
|
2311
1996
|
const agentName = readObjectString(sourceText, "name") ?? entry.name;
|
|
2312
|
-
await writeFile3(
|
|
1997
|
+
await writeFile3(path9.join(destination, `${safeFileStem(agentName)}.md`), markdown);
|
|
2313
1998
|
}
|
|
2314
1999
|
}
|
|
2315
2000
|
function parseClaudeAgent(source, fallbackName) {
|
|
@@ -2338,41 +2023,41 @@ ${prompt.trim()}
|
|
|
2338
2023
|
|
|
2339
2024
|
// packages/compiler/src/plugin-components/commands.ts
|
|
2340
2025
|
import { cp, lstat, mkdir as mkdir4, readdir as readdir3, readFile as readFile5, writeFile as writeFile4 } from "fs/promises";
|
|
2341
|
-
import
|
|
2026
|
+
import path10 from "path";
|
|
2342
2027
|
async function copyCommands(rootDir, destination) {
|
|
2343
|
-
const source =
|
|
2028
|
+
const source = path10.join(rootDir, "commands");
|
|
2344
2029
|
if (!existsSyncSafe(source)) {
|
|
2345
2030
|
return;
|
|
2346
2031
|
}
|
|
2347
2032
|
await mkdir4(destination, { recursive: true });
|
|
2348
2033
|
const entries = await readdir3(source, { withFileTypes: true });
|
|
2349
2034
|
for (const entry of entries) {
|
|
2350
|
-
const sourcePath =
|
|
2035
|
+
const sourcePath = path10.join(source, entry.name);
|
|
2351
2036
|
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
2352
2037
|
if (await safeCommandCopyFilter(sourcePath)) {
|
|
2353
|
-
await cp(sourcePath,
|
|
2038
|
+
await cp(sourcePath, path10.join(destination, safeFileStem(entry.name.replace(/\.md$/, "")) + ".md"));
|
|
2354
2039
|
}
|
|
2355
2040
|
continue;
|
|
2356
2041
|
}
|
|
2357
2042
|
if (!entry.isDirectory()) {
|
|
2358
2043
|
continue;
|
|
2359
2044
|
}
|
|
2360
|
-
const dynamicCommand =
|
|
2045
|
+
const dynamicCommand = path10.join(sourcePath, "command.ts");
|
|
2361
2046
|
if (existsSyncSafe(dynamicCommand)) {
|
|
2362
2047
|
const sourceText = await readFile5(dynamicCommand, "utf8");
|
|
2363
2048
|
const markdown = parseDynamicCommand(sourceText, entry.name);
|
|
2364
2049
|
const commandName = readObjectString(sourceText, "name") ?? entry.name;
|
|
2365
|
-
await writeFile4(
|
|
2050
|
+
await writeFile4(path10.join(destination, `${safeFileStem(commandName)}.md`), markdown);
|
|
2366
2051
|
continue;
|
|
2367
2052
|
}
|
|
2368
|
-
await cp(sourcePath,
|
|
2053
|
+
await cp(sourcePath, path10.join(destination, entry.name), {
|
|
2369
2054
|
recursive: true,
|
|
2370
2055
|
filter: safeCommandCopyFilter
|
|
2371
2056
|
});
|
|
2372
2057
|
}
|
|
2373
2058
|
}
|
|
2374
2059
|
async function safeCommandCopyFilter(sourcePath) {
|
|
2375
|
-
const basename =
|
|
2060
|
+
const basename = path10.basename(sourcePath);
|
|
2376
2061
|
if (basename === ".env" || basename.startsWith(".env.") || basename === "node_modules" || basename === ".git") {
|
|
2377
2062
|
return false;
|
|
2378
2063
|
}
|
|
@@ -2401,32 +2086,32 @@ ${Object.entries(frontmatter).map(([key, value]) => `${key}: ${yamlScalar(value)
|
|
|
2401
2086
|
|
|
2402
2087
|
// packages/compiler/src/plugin-components/hooks.ts
|
|
2403
2088
|
import { mkdir as mkdir5, readdir as readdir4, readFile as readFile6, writeFile as writeFile5 } from "fs/promises";
|
|
2404
|
-
import
|
|
2089
|
+
import path11 from "path";
|
|
2405
2090
|
import {
|
|
2406
2091
|
Node as Node6,
|
|
2407
2092
|
Project as Project2,
|
|
2408
2093
|
SyntaxKind as SyntaxKind4
|
|
2409
2094
|
} from "ts-morph";
|
|
2410
2095
|
async function copyHooks(rootDir, destination) {
|
|
2411
|
-
const source =
|
|
2096
|
+
const source = path11.join(rootDir, "hooks");
|
|
2412
2097
|
if (!existsSyncSafe(source)) {
|
|
2413
2098
|
return;
|
|
2414
2099
|
}
|
|
2415
2100
|
const entries = await readdir4(source, { withFileTypes: true });
|
|
2416
2101
|
const hookDirs = entries.filter(
|
|
2417
|
-
(entry) => entry.isDirectory() && existsSyncSafe(
|
|
2102
|
+
(entry) => entry.isDirectory() && existsSyncSafe(path11.join(source, entry.name, "hook.ts"))
|
|
2418
2103
|
);
|
|
2419
2104
|
if (!hookDirs.length) {
|
|
2420
2105
|
return;
|
|
2421
2106
|
}
|
|
2422
2107
|
const config = {};
|
|
2423
2108
|
for (const entry of hookDirs) {
|
|
2424
|
-
const filePath =
|
|
2109
|
+
const filePath = path11.join(source, entry.name, "hook.ts");
|
|
2425
2110
|
mergeHooks(config, parseHookFile(await readFile6(filePath, "utf8"), entry.name));
|
|
2426
2111
|
}
|
|
2427
2112
|
await mkdir5(destination, { recursive: true });
|
|
2428
2113
|
await writeFile5(
|
|
2429
|
-
|
|
2114
|
+
path11.join(destination, "hooks.json"),
|
|
2430
2115
|
`${JSON.stringify(config, null, 2)}
|
|
2431
2116
|
`
|
|
2432
2117
|
);
|
|
@@ -2453,7 +2138,7 @@ function parseHookFile(source, fallbackName) {
|
|
|
2453
2138
|
throw new Error(`hooks/${fallbackName}/hook.ts must default-export hook({ ... }) or hooks({ ... }).`);
|
|
2454
2139
|
}
|
|
2455
2140
|
function parseHookDefinition(definition, fallbackName) {
|
|
2456
|
-
const event =
|
|
2141
|
+
const event = readStringProperty3(definition, "event");
|
|
2457
2142
|
if (!event) {
|
|
2458
2143
|
throw new Error(`hooks/${fallbackName}/hook.ts must declare an event string.`);
|
|
2459
2144
|
}
|
|
@@ -2463,7 +2148,7 @@ function parseHookDefinition(definition, fallbackName) {
|
|
|
2463
2148
|
}
|
|
2464
2149
|
return {
|
|
2465
2150
|
event,
|
|
2466
|
-
matcher:
|
|
2151
|
+
matcher: readStringProperty3(definition, "matcher"),
|
|
2467
2152
|
run: hooks
|
|
2468
2153
|
};
|
|
2469
2154
|
}
|
|
@@ -2483,7 +2168,7 @@ function parseHooksDefinition(definition, fallbackName) {
|
|
|
2483
2168
|
throw new Error(`hooks/${fallbackName}/hook.ts event "${event}" entries must be objects.`);
|
|
2484
2169
|
}
|
|
2485
2170
|
return stripUndefined2({
|
|
2486
|
-
matcher:
|
|
2171
|
+
matcher: readStringProperty3(entry, "matcher"),
|
|
2487
2172
|
hooks: readHookArray(entry, "run", fallbackName)
|
|
2488
2173
|
});
|
|
2489
2174
|
});
|
|
@@ -2506,7 +2191,7 @@ function parseHookHandlers(handlers, fallbackName) {
|
|
|
2506
2191
|
}
|
|
2507
2192
|
function parseHookHandler(handler, fallbackName) {
|
|
2508
2193
|
if (Node6.isObjectLiteralExpression(handler)) {
|
|
2509
|
-
const type =
|
|
2194
|
+
const type = readStringProperty3(handler, "type");
|
|
2510
2195
|
if (type !== "command" && type !== "http") {
|
|
2511
2196
|
throw new Error(`hooks/${fallbackName}/hook.ts hook handlers need type "command" or "http".`);
|
|
2512
2197
|
}
|
|
@@ -2556,7 +2241,7 @@ function objectLiteralToRecord(object) {
|
|
|
2556
2241
|
}
|
|
2557
2242
|
return stripUndefined2(record);
|
|
2558
2243
|
}
|
|
2559
|
-
function
|
|
2244
|
+
function readStringProperty3(object, propertyName) {
|
|
2560
2245
|
const property = object.getProperty(propertyName);
|
|
2561
2246
|
if (!property || !Node6.isPropertyAssignment(property)) {
|
|
2562
2247
|
return void 0;
|
|
@@ -2600,7 +2285,7 @@ function mergeHooks(target, source) {
|
|
|
2600
2285
|
|
|
2601
2286
|
// packages/compiler/src/plugin-components/passthrough.ts
|
|
2602
2287
|
import { cp as cp2, lstat as lstat2 } from "fs/promises";
|
|
2603
|
-
import
|
|
2288
|
+
import path12 from "path";
|
|
2604
2289
|
async function copyClaudePassthroughDirectories(rootDir, pluginDir) {
|
|
2605
2290
|
for (const directory of [
|
|
2606
2291
|
"assets",
|
|
@@ -2609,18 +2294,18 @@ async function copyClaudePassthroughDirectories(rootDir, pluginDir) {
|
|
|
2609
2294
|
"output-styles",
|
|
2610
2295
|
"themes"
|
|
2611
2296
|
]) {
|
|
2612
|
-
const source =
|
|
2297
|
+
const source = path12.join(rootDir, directory);
|
|
2613
2298
|
if (!existsSyncSafe(source)) {
|
|
2614
2299
|
continue;
|
|
2615
2300
|
}
|
|
2616
|
-
await cp2(source,
|
|
2301
|
+
await cp2(source, path12.join(pluginDir, directory), {
|
|
2617
2302
|
recursive: true,
|
|
2618
2303
|
filter: safePluginCopyFilter
|
|
2619
2304
|
});
|
|
2620
2305
|
}
|
|
2621
2306
|
}
|
|
2622
2307
|
async function safePluginCopyFilter(sourcePath) {
|
|
2623
|
-
const basename =
|
|
2308
|
+
const basename = path12.basename(sourcePath);
|
|
2624
2309
|
if (basename === "node_modules" || basename === ".git" || basename === ".env" || basename.startsWith(".env.")) {
|
|
2625
2310
|
return false;
|
|
2626
2311
|
}
|
|
@@ -2629,11 +2314,11 @@ async function safePluginCopyFilter(sourcePath) {
|
|
|
2629
2314
|
}
|
|
2630
2315
|
|
|
2631
2316
|
// packages/compiler/src/plugin-components/skills.ts
|
|
2632
|
-
import { existsSync as
|
|
2317
|
+
import { existsSync as existsSync4 } from "fs";
|
|
2633
2318
|
import { cp as cp3, lstat as lstat3, mkdir as mkdir6, readdir as readdir5, readFile as readFile7, writeFile as writeFile6 } from "fs/promises";
|
|
2634
|
-
import
|
|
2319
|
+
import path13 from "path";
|
|
2635
2320
|
async function copySkills(rootDir, destination) {
|
|
2636
|
-
const source =
|
|
2321
|
+
const source = path13.join(rootDir, "skills");
|
|
2637
2322
|
if (!existsSyncSafe(source)) {
|
|
2638
2323
|
return;
|
|
2639
2324
|
}
|
|
@@ -2643,27 +2328,27 @@ async function copySkills(rootDir, destination) {
|
|
|
2643
2328
|
if (!entry.isDirectory()) {
|
|
2644
2329
|
continue;
|
|
2645
2330
|
}
|
|
2646
|
-
const sourceDir =
|
|
2647
|
-
const destinationDir =
|
|
2648
|
-
const staticSkill =
|
|
2649
|
-
const dynamicSkill =
|
|
2331
|
+
const sourceDir = path13.join(source, entry.name);
|
|
2332
|
+
const destinationDir = path13.join(destination, entry.name);
|
|
2333
|
+
const staticSkill = path13.join(sourceDir, "SKILL.md");
|
|
2334
|
+
const dynamicSkill = path13.join(sourceDir, "skill.ts");
|
|
2650
2335
|
await mkdir6(destinationDir, { recursive: true });
|
|
2651
|
-
if (
|
|
2336
|
+
if (existsSync4(staticSkill)) {
|
|
2652
2337
|
await cp3(sourceDir, destinationDir, {
|
|
2653
2338
|
recursive: true,
|
|
2654
|
-
filter: async (sourcePath) => !sourcePath.endsWith(`${
|
|
2339
|
+
filter: async (sourcePath) => !sourcePath.endsWith(`${path13.sep}skill.ts`) && await safeSkillCopyFilter(sourcePath)
|
|
2655
2340
|
});
|
|
2656
|
-
} else if (
|
|
2341
|
+
} else if (existsSync4(dynamicSkill)) {
|
|
2657
2342
|
const generated = parseDynamicSkill(
|
|
2658
2343
|
await readFile7(dynamicSkill, "utf8"),
|
|
2659
2344
|
entry.name
|
|
2660
2345
|
);
|
|
2661
|
-
await writeFile6(
|
|
2346
|
+
await writeFile6(path13.join(destinationDir, "SKILL.md"), generated);
|
|
2662
2347
|
}
|
|
2663
2348
|
}
|
|
2664
2349
|
}
|
|
2665
2350
|
async function safeSkillCopyFilter(sourcePath) {
|
|
2666
|
-
const basename =
|
|
2351
|
+
const basename = path13.basename(sourcePath);
|
|
2667
2352
|
if (basename === ".env" || basename.startsWith(".env.") || basename === "node_modules" || basename === ".git") {
|
|
2668
2353
|
return false;
|
|
2669
2354
|
}
|
|
@@ -2689,25 +2374,25 @@ async function buildPluginPackages(rootDir, outRoot, manifest) {
|
|
|
2689
2374
|
await buildClaudePlugin(rootDir, outRoot, identity, manifest);
|
|
2690
2375
|
}
|
|
2691
2376
|
async function buildClaudePlugin(rootDir, outRoot, identity, manifest) {
|
|
2692
|
-
const pluginDir =
|
|
2693
|
-
await mkdir7(
|
|
2694
|
-
await copySkills(rootDir,
|
|
2695
|
-
await copyCommands(rootDir,
|
|
2696
|
-
await copyHooks(rootDir,
|
|
2697
|
-
await emitClaudeAgents(rootDir,
|
|
2377
|
+
const pluginDir = path14.join(outRoot, "claude-plugin");
|
|
2378
|
+
await mkdir7(path14.join(pluginDir, ".claude-plugin"), { recursive: true });
|
|
2379
|
+
await copySkills(rootDir, path14.join(pluginDir, "skills"));
|
|
2380
|
+
await copyCommands(rootDir, path14.join(pluginDir, "commands"));
|
|
2381
|
+
await copyHooks(rootDir, path14.join(pluginDir, "hooks"));
|
|
2382
|
+
await emitClaudeAgents(rootDir, path14.join(pluginDir, "agents"));
|
|
2698
2383
|
await copyClaudePassthroughDirectories(rootDir, pluginDir);
|
|
2699
|
-
await writeJson(
|
|
2384
|
+
await writeJson(path14.join(pluginDir, ".claude-plugin", "plugin.json"), {
|
|
2700
2385
|
name: identity.slug,
|
|
2701
2386
|
version: identity.version,
|
|
2702
2387
|
description: identity.description,
|
|
2703
2388
|
displayName: identity.name,
|
|
2704
2389
|
installationPreference: "available"
|
|
2705
2390
|
});
|
|
2706
|
-
await writeJson(
|
|
2391
|
+
await writeJson(path14.join(pluginDir, "version.json"), {
|
|
2707
2392
|
version: identity.version,
|
|
2708
2393
|
generatedBy: "sidecar"
|
|
2709
2394
|
});
|
|
2710
|
-
await writeJson(
|
|
2395
|
+
await writeJson(path14.join(pluginDir, ".mcp.json"), {
|
|
2711
2396
|
mcpServers: {
|
|
2712
2397
|
[identity.slug]: {
|
|
2713
2398
|
type: "http",
|
|
@@ -2715,7 +2400,7 @@ async function buildClaudePlugin(rootDir, outRoot, identity, manifest) {
|
|
|
2715
2400
|
}
|
|
2716
2401
|
}
|
|
2717
2402
|
});
|
|
2718
|
-
await writeJson(
|
|
2403
|
+
await writeJson(path14.join(pluginDir, "settings.json"), {
|
|
2719
2404
|
sidecar: {
|
|
2720
2405
|
tools: manifest.tools.map((entry) => entry.id),
|
|
2721
2406
|
resources: manifest.resources.map((entry) => entry.uri),
|
|
@@ -2723,7 +2408,7 @@ async function buildClaudePlugin(rootDir, outRoot, identity, manifest) {
|
|
|
2723
2408
|
}
|
|
2724
2409
|
});
|
|
2725
2410
|
await writeFile7(
|
|
2726
|
-
|
|
2411
|
+
path14.join(pluginDir, "README.md"),
|
|
2727
2412
|
`# ${identity.name} Claude Plugin
|
|
2728
2413
|
|
|
2729
2414
|
This package was generated by Sidecar.
|
|
@@ -2737,7 +2422,7 @@ Claude/Cowork plugin-specific components such as skills, slash commands, agents,
|
|
|
2737
2422
|
);
|
|
2738
2423
|
}
|
|
2739
2424
|
async function writeJson(filePath, value) {
|
|
2740
|
-
await mkdir7(
|
|
2425
|
+
await mkdir7(path14.dirname(filePath), { recursive: true });
|
|
2741
2426
|
await writeFile7(
|
|
2742
2427
|
filePath,
|
|
2743
2428
|
`${JSON.stringify(stripUndefined2(value), null, 2)}
|
|
@@ -2747,13 +2432,13 @@ async function writeJson(filePath, value) {
|
|
|
2747
2432
|
|
|
2748
2433
|
// packages/compiler/src/prompts.ts
|
|
2749
2434
|
import { readdir as readdir6 } from "fs/promises";
|
|
2750
|
-
import
|
|
2435
|
+
import path15 from "path";
|
|
2751
2436
|
import {
|
|
2752
2437
|
Node as Node7,
|
|
2753
2438
|
SyntaxKind as SyntaxKind5
|
|
2754
2439
|
} from "ts-morph";
|
|
2755
2440
|
async function analyzeProjectPrompts(rootDir) {
|
|
2756
|
-
const promptFiles = await findPromptFiles(
|
|
2441
|
+
const promptFiles = await findPromptFiles(path15.join(rootDir, "prompts"));
|
|
2757
2442
|
if (promptFiles.length === 0) {
|
|
2758
2443
|
return [];
|
|
2759
2444
|
}
|
|
@@ -2765,7 +2450,7 @@ async function analyzeProjectPrompts(rootDir) {
|
|
|
2765
2450
|
function analyzePromptFile(sourceFile, rootDir) {
|
|
2766
2451
|
const definition = findPromptDefinition(sourceFile);
|
|
2767
2452
|
const absoluteFile = sourceFile.getFilePath();
|
|
2768
|
-
const directory =
|
|
2453
|
+
const directory = path15.basename(path15.dirname(absoluteFile));
|
|
2769
2454
|
const name = getOptionalStringProperty2(definition, "name") ?? safePathSegment(directory);
|
|
2770
2455
|
const title = getRequiredStringProperty2(definition, "title", sourceFile);
|
|
2771
2456
|
const description = getOptionalStringProperty2(definition, "description");
|
|
@@ -2781,7 +2466,7 @@ function analyzePromptFile(sourceFile, rootDir) {
|
|
|
2781
2466
|
throw new CompilerError(sourceFile, "prompt({ ... }) must include a run method.");
|
|
2782
2467
|
}
|
|
2783
2468
|
return {
|
|
2784
|
-
sourceFile:
|
|
2469
|
+
sourceFile: path15.relative(rootDir, absoluteFile),
|
|
2785
2470
|
directory,
|
|
2786
2471
|
name,
|
|
2787
2472
|
title,
|
|
@@ -2800,7 +2485,7 @@ async function findPromptFiles(promptsDir) {
|
|
|
2800
2485
|
if (!entry.isDirectory()) {
|
|
2801
2486
|
continue;
|
|
2802
2487
|
}
|
|
2803
|
-
const filePath =
|
|
2488
|
+
const filePath = path15.join(promptsDir, entry.name, "prompt.ts");
|
|
2804
2489
|
if (existsSyncSafe(filePath)) {
|
|
2805
2490
|
files.push(filePath);
|
|
2806
2491
|
}
|
|
@@ -2922,7 +2607,7 @@ function readIcons(definition) {
|
|
|
2922
2607
|
return [{
|
|
2923
2608
|
src,
|
|
2924
2609
|
mimeType: getOptionalStringProperty2(object, "mimeType"),
|
|
2925
|
-
sizes:
|
|
2610
|
+
sizes: readStringArrayProperty3(object, "sizes")
|
|
2926
2611
|
}];
|
|
2927
2612
|
});
|
|
2928
2613
|
return icons.length ? icons : void 0;
|
|
@@ -2935,7 +2620,7 @@ function readObjectProperty4(definition, propertyName) {
|
|
|
2935
2620
|
const initializer = unwrapExpression(property.getInitializer());
|
|
2936
2621
|
return initializer && Node7.isObjectLiteralExpression(initializer) ? initializer : void 0;
|
|
2937
2622
|
}
|
|
2938
|
-
function
|
|
2623
|
+
function readStringArrayProperty3(definition, propertyName) {
|
|
2939
2624
|
const property = definition.getProperty(propertyName);
|
|
2940
2625
|
if (!property || !Node7.isPropertyAssignment(property)) {
|
|
2941
2626
|
return void 0;
|
|
@@ -2949,13 +2634,13 @@ function readStringArrayProperty4(definition, propertyName) {
|
|
|
2949
2634
|
|
|
2950
2635
|
// packages/compiler/src/resources.ts
|
|
2951
2636
|
import { readdir as readdir7 } from "fs/promises";
|
|
2952
|
-
import
|
|
2637
|
+
import path16 from "path";
|
|
2953
2638
|
import {
|
|
2954
2639
|
Node as Node8,
|
|
2955
2640
|
SyntaxKind as SyntaxKind6
|
|
2956
2641
|
} from "ts-morph";
|
|
2957
2642
|
async function analyzeProjectResources(rootDir) {
|
|
2958
|
-
const resourceFiles = await findResourceFiles(
|
|
2643
|
+
const resourceFiles = await findResourceFiles(path16.join(rootDir, "resources"));
|
|
2959
2644
|
if (resourceFiles.length === 0) {
|
|
2960
2645
|
return [];
|
|
2961
2646
|
}
|
|
@@ -2967,7 +2652,7 @@ async function analyzeProjectResources(rootDir) {
|
|
|
2967
2652
|
function analyzeResourceFile(sourceFile, rootDir) {
|
|
2968
2653
|
const definition = findResourceDefinition(sourceFile);
|
|
2969
2654
|
const absoluteFile = sourceFile.getFilePath();
|
|
2970
|
-
const directory =
|
|
2655
|
+
const directory = path16.basename(path16.dirname(absoluteFile));
|
|
2971
2656
|
const defaultUri = `sidecar://resources/${safePathSegment(directory)}`;
|
|
2972
2657
|
const name = getRequiredStringProperty3(definition, "name", sourceFile);
|
|
2973
2658
|
const uri = getOptionalStringProperty3(definition, "uri") ?? defaultUri;
|
|
@@ -2985,7 +2670,7 @@ function analyzeResourceFile(sourceFile, rootDir) {
|
|
|
2985
2670
|
throw new CompilerError(sourceFile, "resource({ ... }) must include a read method.");
|
|
2986
2671
|
}
|
|
2987
2672
|
return {
|
|
2988
|
-
sourceFile:
|
|
2673
|
+
sourceFile: path16.relative(rootDir, absoluteFile),
|
|
2989
2674
|
directory,
|
|
2990
2675
|
uri,
|
|
2991
2676
|
name,
|
|
@@ -3008,7 +2693,7 @@ async function findResourceFiles(resourcesDir) {
|
|
|
3008
2693
|
if (!entry.isDirectory()) {
|
|
3009
2694
|
continue;
|
|
3010
2695
|
}
|
|
3011
|
-
const filePath =
|
|
2696
|
+
const filePath = path16.join(resourcesDir, entry.name, "resource.ts");
|
|
3012
2697
|
if (existsSyncSafe(filePath)) {
|
|
3013
2698
|
files.push(filePath);
|
|
3014
2699
|
}
|
|
@@ -3087,7 +2772,7 @@ function readAnnotations2(definition) {
|
|
|
3087
2772
|
return void 0;
|
|
3088
2773
|
}
|
|
3089
2774
|
const annotations = {};
|
|
3090
|
-
const audience =
|
|
2775
|
+
const audience = readStringArrayProperty4(initializer, "audience")?.filter((value) => value === "user" || value === "assistant");
|
|
3091
2776
|
const priority = getOptionalNumberProperty(initializer, "priority");
|
|
3092
2777
|
const lastModified = getOptionalStringProperty3(initializer, "lastModified");
|
|
3093
2778
|
if (audience?.length) annotations.audience = audience;
|
|
@@ -3116,7 +2801,7 @@ function readIcons2(definition) {
|
|
|
3116
2801
|
return [{
|
|
3117
2802
|
src,
|
|
3118
2803
|
mimeType: getOptionalStringProperty3(object, "mimeType"),
|
|
3119
|
-
sizes:
|
|
2804
|
+
sizes: readStringArrayProperty4(object, "sizes")
|
|
3120
2805
|
}];
|
|
3121
2806
|
});
|
|
3122
2807
|
return icons.length ? icons : void 0;
|
|
@@ -3129,7 +2814,7 @@ function readObjectProperty5(definition, propertyName) {
|
|
|
3129
2814
|
const initializer = unwrapExpression(property.getInitializer());
|
|
3130
2815
|
return initializer && Node8.isObjectLiteralExpression(initializer) ? initializer : void 0;
|
|
3131
2816
|
}
|
|
3132
|
-
function
|
|
2817
|
+
function readStringArrayProperty4(definition, propertyName) {
|
|
3133
2818
|
const property = definition.getProperty(propertyName);
|
|
3134
2819
|
if (!property || !Node8.isPropertyAssignment(property)) {
|
|
3135
2820
|
return void 0;
|
|
@@ -3142,21 +2827,21 @@ function readStringArrayProperty5(definition, propertyName) {
|
|
|
3142
2827
|
}
|
|
3143
2828
|
|
|
3144
2829
|
// packages/compiler/src/server-output.ts
|
|
3145
|
-
import { existsSync as
|
|
2830
|
+
import { existsSync as existsSync5 } from "fs";
|
|
3146
2831
|
import { mkdir as mkdir8, rm, writeFile as writeFile8 } from "fs/promises";
|
|
3147
|
-
import
|
|
2832
|
+
import path17 from "path";
|
|
3148
2833
|
import { build as esbuild2 } from "esbuild";
|
|
3149
2834
|
var SERVER_ENTRYPOINT = "server/index.js";
|
|
3150
2835
|
var VERCEL_FUNCTION_DIR = "functions/api/sidecar.func";
|
|
3151
2836
|
var VERCEL_ENTRYPOINT = `${VERCEL_FUNCTION_DIR}/index.js`;
|
|
3152
2837
|
var VERCEL_HANDLER_FILE = "index.js";
|
|
3153
2838
|
async function buildServerOutput(rootDir, outDir, manifest, identity, host = "node", options = {}) {
|
|
3154
|
-
const cacheDir =
|
|
2839
|
+
const cacheDir = path17.join(rootDir, ".sidecar", "cache", "server");
|
|
3155
2840
|
await mkdir8(cacheDir, { recursive: true });
|
|
3156
|
-
const entryFile =
|
|
2841
|
+
const entryFile = path17.join(cacheDir, "index.ts");
|
|
3157
2842
|
await writeFile8(entryFile, renderServerEntry(rootDir, entryFile, manifest, identity));
|
|
3158
|
-
const serverFile =
|
|
3159
|
-
await mkdir8(
|
|
2843
|
+
const serverFile = path17.join(outDir, SERVER_ENTRYPOINT);
|
|
2844
|
+
await mkdir8(path17.dirname(serverFile), { recursive: true });
|
|
3160
2845
|
await esbuild2({
|
|
3161
2846
|
absWorkingDir: rootDir,
|
|
3162
2847
|
alias: sidecarBundleAliases(rootDir),
|
|
@@ -3170,30 +2855,30 @@ const require = __sidecarCreateRequire(import.meta.url);`
|
|
|
3170
2855
|
legalComments: "none",
|
|
3171
2856
|
minify: false,
|
|
3172
2857
|
nodePaths: [
|
|
3173
|
-
|
|
3174
|
-
|
|
2858
|
+
path17.join(rootDir, "node_modules"),
|
|
2859
|
+
path17.join(process.cwd(), "node_modules")
|
|
3175
2860
|
],
|
|
3176
2861
|
outfile: serverFile,
|
|
3177
2862
|
platform: "node",
|
|
3178
2863
|
sourcemap: false,
|
|
3179
2864
|
target: "node20"
|
|
3180
2865
|
});
|
|
3181
|
-
await writeFile8(
|
|
2866
|
+
await writeFile8(path17.join(outDir, "package.json"), renderServerPackage(identity));
|
|
3182
2867
|
if (host === "vercel") {
|
|
3183
2868
|
const vercelOutputDir = options.vercelOutputDir ?? outDir;
|
|
3184
|
-
await rm(
|
|
3185
|
-
await rm(
|
|
3186
|
-
await writeFile8(
|
|
3187
|
-
await writeFile8(
|
|
2869
|
+
await rm(path17.join(vercelOutputDir, "api"), { recursive: true, force: true });
|
|
2870
|
+
await rm(path17.join(vercelOutputDir, "vercel.json"), { force: true });
|
|
2871
|
+
await writeFile8(path17.join(outDir, VERCEL_HANDLER_FILE), renderVercelEntrypoint());
|
|
2872
|
+
await writeFile8(path17.join(outDir, ".vc-config.json"), renderVercelFunctionConfig());
|
|
3188
2873
|
await mkdir8(vercelOutputDir, { recursive: true });
|
|
3189
|
-
await writeFile8(
|
|
2874
|
+
await writeFile8(path17.join(vercelOutputDir, "config.json"), renderVercelOutputConfig());
|
|
3190
2875
|
} else {
|
|
3191
|
-
await rm(
|
|
3192
|
-
await rm(
|
|
2876
|
+
await rm(path17.join(outDir, "api"), { recursive: true, force: true });
|
|
2877
|
+
await rm(path17.join(outDir, "vercel.json"), { force: true });
|
|
3193
2878
|
}
|
|
3194
2879
|
}
|
|
3195
2880
|
function renderServerEntry(rootDir, entryFile, manifest, identity) {
|
|
3196
|
-
const entryDir =
|
|
2881
|
+
const entryDir = path17.dirname(entryFile);
|
|
3197
2882
|
const tools = manifest.tools;
|
|
3198
2883
|
const resources = manifest.resources;
|
|
3199
2884
|
const prompts = manifest.prompts;
|
|
@@ -3206,17 +2891,17 @@ function renderServerEntry(rootDir, entryFile, manifest, identity) {
|
|
|
3206
2891
|
`import { isSidecarPrompt, isSidecarResource, isSidecarTool } from "@sidecar-ai/core";`,
|
|
3207
2892
|
`import { isSidecarProxy } from "@sidecar-ai/server/proxy";`,
|
|
3208
2893
|
...tools.map(
|
|
3209
|
-
(entry, index) => `import tool${index} from ${JSON.stringify(toImportSpecifier(entryDir,
|
|
2894
|
+
(entry, index) => `import tool${index} from ${JSON.stringify(toImportSpecifier(entryDir, path17.join(rootDir, entry.sourceFile)))};`
|
|
3210
2895
|
),
|
|
3211
2896
|
...resources.map(
|
|
3212
|
-
(entry, index) => `import resource${index} from ${JSON.stringify(toImportSpecifier(entryDir,
|
|
2897
|
+
(entry, index) => `import resource${index} from ${JSON.stringify(toImportSpecifier(entryDir, path17.join(rootDir, entry.sourceFile)))};`
|
|
3213
2898
|
),
|
|
3214
2899
|
...prompts.map(
|
|
3215
|
-
(entry, index) => `import prompt${index} from ${JSON.stringify(toImportSpecifier(entryDir,
|
|
2900
|
+
(entry, index) => `import prompt${index} from ${JSON.stringify(toImportSpecifier(entryDir, path17.join(rootDir, entry.sourceFile)))};`
|
|
3216
2901
|
),
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
2902
|
+
existsSync5(path17.join(rootDir, "auth.ts")) ? `import authExport from ${JSON.stringify(toImportSpecifier(entryDir, path17.join(rootDir, "auth.ts")))};` : `const authExport = undefined;`,
|
|
2903
|
+
existsSync5(path17.join(rootDir, "proxy.ts")) ? `import proxyExport from ${JSON.stringify(toImportSpecifier(entryDir, path17.join(rootDir, "proxy.ts")))};` : `const proxyExport = undefined;`,
|
|
2904
|
+
existsSync5(path17.join(rootDir, "sidecar.config.ts")) ? `import configExport from ${JSON.stringify(toImportSpecifier(entryDir, path17.join(rootDir, "sidecar.config.ts")))};` : `const configExport = undefined;`
|
|
3220
2905
|
].join("\n");
|
|
3221
2906
|
return `${imports}
|
|
3222
2907
|
|
|
@@ -3327,7 +3012,7 @@ function unwrapRuntimeDefault(value) {
|
|
|
3327
3012
|
value &&
|
|
3328
3013
|
typeof value === "object" &&
|
|
3329
3014
|
"default" in value &&
|
|
3330
|
-
Object.keys(value).
|
|
3015
|
+
Object.keys(value).length === 1
|
|
3331
3016
|
) {
|
|
3332
3017
|
return unwrapRuntimeDefault(value.default);
|
|
3333
3018
|
}
|
|
@@ -3419,35 +3104,35 @@ function sidecarBundleAliases(rootDir) {
|
|
|
3419
3104
|
return void 0;
|
|
3420
3105
|
}
|
|
3421
3106
|
return {
|
|
3422
|
-
"sidecar-ai":
|
|
3423
|
-
"@sidecar-ai/auth":
|
|
3424
|
-
"@sidecar-ai/core":
|
|
3425
|
-
"@sidecar-ai/server":
|
|
3426
|
-
"@sidecar-ai/server/proxy":
|
|
3427
|
-
"@sidecar-ai/client":
|
|
3428
|
-
"@sidecar-ai/react":
|
|
3429
|
-
"@sidecar-ai/native":
|
|
3430
|
-
"@sidecar-ai/native/components":
|
|
3431
|
-
"@sidecar-ai/openai":
|
|
3432
|
-
"@sidecar-ai/openai/components":
|
|
3433
|
-
"@sidecar-ai/openai/official":
|
|
3434
|
-
"@sidecar-ai/anthropic":
|
|
3435
|
-
"@sidecar-ai/anthropic/agent":
|
|
3436
|
-
"@sidecar-ai/anthropic/command":
|
|
3437
|
-
"@sidecar-ai/anthropic/components":
|
|
3438
|
-
"@sidecar-ai/anthropic/hooks":
|
|
3439
|
-
"@sidecar-ai/anthropic/mcp":
|
|
3440
|
-
"@sidecar-ai/anthropic/plugin":
|
|
3441
|
-
"@sidecar-ai/anthropic/skill":
|
|
3107
|
+
"sidecar-ai": path17.join(repoRoot, "packages", "sidecar-ai", "src", "index.ts"),
|
|
3108
|
+
"@sidecar-ai/auth": path17.join(repoRoot, "packages", "auth", "src", "index.ts"),
|
|
3109
|
+
"@sidecar-ai/core": path17.join(repoRoot, "packages", "core", "src", "index.ts"),
|
|
3110
|
+
"@sidecar-ai/server": path17.join(repoRoot, "packages", "server", "src", "index.ts"),
|
|
3111
|
+
"@sidecar-ai/server/proxy": path17.join(repoRoot, "packages", "server", "src", "proxy.ts"),
|
|
3112
|
+
"@sidecar-ai/client": path17.join(repoRoot, "packages", "client", "src", "index.ts"),
|
|
3113
|
+
"@sidecar-ai/react": path17.join(repoRoot, "packages", "react", "src", "index.ts"),
|
|
3114
|
+
"@sidecar-ai/native": path17.join(repoRoot, "packages", "native", "src", "index.ts"),
|
|
3115
|
+
"@sidecar-ai/native/components": path17.join(repoRoot, "packages", "native", "src", "components", "index.tsx"),
|
|
3116
|
+
"@sidecar-ai/openai": path17.join(repoRoot, "packages", "openai", "src", "index.ts"),
|
|
3117
|
+
"@sidecar-ai/openai/components": path17.join(repoRoot, "packages", "openai", "src", "components.tsx"),
|
|
3118
|
+
"@sidecar-ai/openai/official": path17.join(repoRoot, "packages", "openai", "src", "official.ts"),
|
|
3119
|
+
"@sidecar-ai/anthropic": path17.join(repoRoot, "packages", "anthropic", "src", "index.ts"),
|
|
3120
|
+
"@sidecar-ai/anthropic/agent": path17.join(repoRoot, "packages", "anthropic", "src", "agent.ts"),
|
|
3121
|
+
"@sidecar-ai/anthropic/command": path17.join(repoRoot, "packages", "anthropic", "src", "command.ts"),
|
|
3122
|
+
"@sidecar-ai/anthropic/components": path17.join(repoRoot, "packages", "anthropic", "src", "components.tsx"),
|
|
3123
|
+
"@sidecar-ai/anthropic/hooks": path17.join(repoRoot, "packages", "anthropic", "src", "hooks.ts"),
|
|
3124
|
+
"@sidecar-ai/anthropic/mcp": path17.join(repoRoot, "packages", "anthropic", "src", "mcp.ts"),
|
|
3125
|
+
"@sidecar-ai/anthropic/plugin": path17.join(repoRoot, "packages", "anthropic", "src", "plugin.ts"),
|
|
3126
|
+
"@sidecar-ai/anthropic/skill": path17.join(repoRoot, "packages", "anthropic", "src", "skill.ts")
|
|
3442
3127
|
};
|
|
3443
3128
|
}
|
|
3444
3129
|
function findSidecarRepoRoot2(startDir) {
|
|
3445
|
-
let current =
|
|
3130
|
+
let current = path17.resolve(startDir);
|
|
3446
3131
|
while (true) {
|
|
3447
|
-
if (
|
|
3132
|
+
if (existsSync5(path17.join(current, "packages", "core", "src", "index.ts"))) {
|
|
3448
3133
|
return current;
|
|
3449
3134
|
}
|
|
3450
|
-
const parent =
|
|
3135
|
+
const parent = path17.dirname(current);
|
|
3451
3136
|
if (parent === current) {
|
|
3452
3137
|
return void 0;
|
|
3453
3138
|
}
|
|
@@ -3457,7 +3142,7 @@ function findSidecarRepoRoot2(startDir) {
|
|
|
3457
3142
|
|
|
3458
3143
|
// packages/compiler/src/build.ts
|
|
3459
3144
|
async function buildProject(options) {
|
|
3460
|
-
const rootDir =
|
|
3145
|
+
const rootDir = path18.resolve(options.rootDir);
|
|
3461
3146
|
const config = analyzeProjectConfig(rootDir);
|
|
3462
3147
|
const target = options.target ?? config.build.target ?? "mcp";
|
|
3463
3148
|
const host = options.host ?? config.build.host ?? "node";
|
|
@@ -3479,7 +3164,7 @@ async function buildProject(options) {
|
|
|
3479
3164
|
}
|
|
3480
3165
|
const outDir = resolveInsideRoot(rootDir, options.outDir ?? config.build.outDir ?? defaultBuildOutDir(host, target));
|
|
3481
3166
|
const runtimeOutDir = resolveRuntimeOutputDir(outDir, host);
|
|
3482
|
-
await buildWidgets(rootDir, runtimeOutDir, tools
|
|
3167
|
+
await buildWidgets(rootDir, runtimeOutDir, tools);
|
|
3483
3168
|
const manifest = {
|
|
3484
3169
|
version: 1,
|
|
3485
3170
|
target,
|
|
@@ -3495,11 +3180,11 @@ async function buildProject(options) {
|
|
|
3495
3180
|
};
|
|
3496
3181
|
await mkdir9(runtimeOutDir, { recursive: true });
|
|
3497
3182
|
await writeFile9(
|
|
3498
|
-
|
|
3183
|
+
path18.join(runtimeOutDir, "manifest.sidecar.json"),
|
|
3499
3184
|
`${JSON.stringify(manifest, null, 2)}
|
|
3500
3185
|
`
|
|
3501
3186
|
);
|
|
3502
|
-
await writeFile9(
|
|
3187
|
+
await writeFile9(path18.join(runtimeOutDir, "README.md"), renderMcpReadme(manifest));
|
|
3503
3188
|
await writeGeneratedTypes(rootDir, tools);
|
|
3504
3189
|
await buildServerOutput(rootDir, runtimeOutDir, manifest, identity, host, {
|
|
3505
3190
|
vercelOutputDir: outDir
|
|
@@ -3517,23 +3202,23 @@ function defaultBuildOutDir(host, target) {
|
|
|
3517
3202
|
}
|
|
3518
3203
|
function resolveRuntimeOutputDir(outDir, host) {
|
|
3519
3204
|
if (host === "vercel") {
|
|
3520
|
-
return
|
|
3205
|
+
return path18.join(outDir, VERCEL_FUNCTION_DIR);
|
|
3521
3206
|
}
|
|
3522
3207
|
return outDir;
|
|
3523
3208
|
}
|
|
3524
3209
|
function resolvePluginOutputBase(rootDir, outDir, host) {
|
|
3525
3210
|
if (host === "vercel" && isVercelBuildOutputDir(outDir)) {
|
|
3526
|
-
return
|
|
3211
|
+
return path18.join(rootDir, "out");
|
|
3527
3212
|
}
|
|
3528
|
-
return
|
|
3213
|
+
return path18.dirname(outDir);
|
|
3529
3214
|
}
|
|
3530
3215
|
function isVercelBuildOutputDir(outDir) {
|
|
3531
|
-
return
|
|
3216
|
+
return path18.basename(outDir) === "output" && path18.basename(path18.dirname(outDir)) === ".vercel";
|
|
3532
3217
|
}
|
|
3533
3218
|
function resolveInsideRoot(rootDir, output) {
|
|
3534
|
-
const resolved =
|
|
3535
|
-
const relative =
|
|
3536
|
-
if (relative.startsWith("..") ||
|
|
3219
|
+
const resolved = path18.resolve(rootDir, output);
|
|
3220
|
+
const relative = path18.relative(rootDir, resolved);
|
|
3221
|
+
if (relative.startsWith("..") || path18.isAbsolute(relative)) {
|
|
3537
3222
|
throw new Error(`Build output must stay inside the project root: ${output}`);
|
|
3538
3223
|
}
|
|
3539
3224
|
return resolved;
|