@faapi/faapi 3.1.0 → 3.2.1
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/cli/index.js +497 -361
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +45 -12
- package/dist/index.js +406 -266
- package/dist/index.js.map +1 -1
- package/dist/testing.js +305 -172
- package/dist/testing.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10,35 +10,107 @@ var __export = (target, all) => {
|
|
|
10
10
|
|
|
11
11
|
// src/ast/createProgram.ts
|
|
12
12
|
import ts from "typescript";
|
|
13
|
+
import fs from "fs";
|
|
14
|
+
import path from "path";
|
|
13
15
|
function invalidateProgramCache() {
|
|
14
16
|
programCache.clear();
|
|
17
|
+
tsConfigCache.clear();
|
|
18
|
+
}
|
|
19
|
+
function findTsConfig(filePath) {
|
|
20
|
+
let dir = path.dirname(filePath);
|
|
21
|
+
const root = path.parse(dir).root;
|
|
22
|
+
while (true) {
|
|
23
|
+
const candidate = path.join(dir, "tsconfig.json");
|
|
24
|
+
if (fs.existsSync(candidate)) {
|
|
25
|
+
return candidate;
|
|
26
|
+
}
|
|
27
|
+
if (dir === root) return null;
|
|
28
|
+
const parent = path.dirname(dir);
|
|
29
|
+
if (parent === dir) return null;
|
|
30
|
+
dir = parent;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function parseTsConfig(tsconfigPath) {
|
|
34
|
+
const cached = tsConfigCache.get(tsconfigPath);
|
|
35
|
+
if (cached) return cached;
|
|
36
|
+
const result = { fileNames: [] };
|
|
37
|
+
try {
|
|
38
|
+
const configFile = ts.readConfigFile(tsconfigPath, (p) => fs.readFileSync(p, "utf-8"));
|
|
39
|
+
if (configFile.error) {
|
|
40
|
+
tsConfigCache.set(tsconfigPath, result);
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
const config = configFile.config ?? {};
|
|
44
|
+
const basePath = path.dirname(tsconfigPath);
|
|
45
|
+
const parsed = ts.parseJsonConfigFileContent(
|
|
46
|
+
config,
|
|
47
|
+
ts.sys,
|
|
48
|
+
basePath,
|
|
49
|
+
/* existingOptions */
|
|
50
|
+
void 0,
|
|
51
|
+
tsconfigPath
|
|
52
|
+
);
|
|
53
|
+
result.fileNames = parsed.fileNames;
|
|
54
|
+
if (parsed.options.module !== void 0) {
|
|
55
|
+
result.module = parsed.options.module;
|
|
56
|
+
}
|
|
57
|
+
if (parsed.options.moduleResolution !== void 0) {
|
|
58
|
+
result.moduleResolution = parsed.options.moduleResolution;
|
|
59
|
+
}
|
|
60
|
+
} catch {
|
|
61
|
+
}
|
|
62
|
+
tsConfigCache.set(tsconfigPath, result);
|
|
63
|
+
return result;
|
|
15
64
|
}
|
|
16
65
|
function createProgram(filePath) {
|
|
17
66
|
const cached = programCache.get(filePath);
|
|
18
67
|
if (cached) {
|
|
19
68
|
return cached;
|
|
20
69
|
}
|
|
21
|
-
const
|
|
70
|
+
const options = {
|
|
22
71
|
strict: true,
|
|
23
72
|
target: ts.ScriptTarget.ES2022,
|
|
24
73
|
module: ts.ModuleKind.NodeNext,
|
|
25
74
|
moduleResolution: ts.ModuleResolutionKind.NodeNext,
|
|
26
75
|
skipLibCheck: true,
|
|
27
76
|
noEmit: true
|
|
28
|
-
}
|
|
77
|
+
};
|
|
78
|
+
let rootNames = [filePath];
|
|
79
|
+
const tsconfigPath = findTsConfig(filePath);
|
|
80
|
+
if (tsconfigPath) {
|
|
81
|
+
const tsOptions = parseTsConfig(tsconfigPath);
|
|
82
|
+
if (tsOptions.module !== void 0) {
|
|
83
|
+
options.module = tsOptions.module;
|
|
84
|
+
}
|
|
85
|
+
if (tsOptions.moduleResolution !== void 0) {
|
|
86
|
+
options.moduleResolution = tsOptions.moduleResolution;
|
|
87
|
+
}
|
|
88
|
+
if (tsOptions.fileNames.length > 0) {
|
|
89
|
+
if (!tsOptions.fileNames.includes(filePath)) {
|
|
90
|
+
rootNames = [filePath, ...tsOptions.fileNames];
|
|
91
|
+
} else {
|
|
92
|
+
rootNames = tsOptions.fileNames;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const program = ts.createProgram(rootNames, options);
|
|
29
97
|
programCache.set(filePath, program);
|
|
30
98
|
return program;
|
|
31
99
|
}
|
|
32
|
-
var programCache;
|
|
100
|
+
var programCache, tsConfigCache;
|
|
33
101
|
var init_createProgram = __esm({
|
|
34
102
|
"src/ast/createProgram.ts"() {
|
|
35
103
|
"use strict";
|
|
36
104
|
programCache = /* @__PURE__ */ new Map();
|
|
105
|
+
tsConfigCache = /* @__PURE__ */ new Map();
|
|
37
106
|
}
|
|
38
107
|
});
|
|
39
108
|
|
|
40
109
|
// src/ast/resolveTypeNode.ts
|
|
41
110
|
import ts2 from "typescript";
|
|
111
|
+
function setProgramContext(program) {
|
|
112
|
+
currentProgram = program;
|
|
113
|
+
}
|
|
42
114
|
function resolveTypeNode(typeNode, checker, visited = /* @__PURE__ */ new Set()) {
|
|
43
115
|
const kind = typeNode.kind;
|
|
44
116
|
switch (kind) {
|
|
@@ -351,11 +423,69 @@ function resolveTypeReference(typeNode, checker, visited = /* @__PURE__ */ new S
|
|
|
351
423
|
if (ts2.isEnumDeclaration(declaration)) {
|
|
352
424
|
return resolveEnumDeclaration(declaration);
|
|
353
425
|
}
|
|
426
|
+
if (ts2.isImportSpecifier(declaration) || ts2.isImportClause(declaration)) {
|
|
427
|
+
const resolved = resolveImportAlias(typeNode, symbol, checker, visited);
|
|
428
|
+
if (resolved) return resolved;
|
|
429
|
+
}
|
|
354
430
|
}
|
|
355
431
|
}
|
|
356
432
|
}
|
|
357
433
|
throw new SchemaExtractionError(typeNode.getText(), `\u65E0\u6CD5\u89E3\u6790\u7684\u5F15\u7528\u7C7B\u578B "${typeName}"`);
|
|
358
434
|
}
|
|
435
|
+
function resolveImportAlias(typeNode, symbol, checker, visited) {
|
|
436
|
+
const typeName = typeNode.typeName.getText();
|
|
437
|
+
try {
|
|
438
|
+
const aliased = checker.getAliasedSymbol(symbol);
|
|
439
|
+
if (aliased && aliased.declarations && aliased.declarations.length > 0) {
|
|
440
|
+
const decl = aliased.declarations[0];
|
|
441
|
+
if (ts2.isInterfaceDeclaration(decl)) {
|
|
442
|
+
return resolveInterfaceDeclaration(decl, checker, visited);
|
|
443
|
+
}
|
|
444
|
+
if (ts2.isTypeAliasDeclaration(decl)) {
|
|
445
|
+
return resolveTypeNode(decl.type, checker, visited);
|
|
446
|
+
}
|
|
447
|
+
if (ts2.isEnumDeclaration(decl)) {
|
|
448
|
+
return resolveEnumDeclaration(decl);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
} catch {
|
|
452
|
+
}
|
|
453
|
+
const program = currentProgram;
|
|
454
|
+
if (!program) return null;
|
|
455
|
+
const allSFs = program.getSourceFiles();
|
|
456
|
+
for (const sourceFile of allSFs) {
|
|
457
|
+
if (sourceFile.fileName.includes("/node_modules/") || sourceFile.fileName.includes("typescript/lib/")) {
|
|
458
|
+
continue;
|
|
459
|
+
}
|
|
460
|
+
const found = findTopLevelDecl(sourceFile, typeName);
|
|
461
|
+
if (found) {
|
|
462
|
+
if (found.kind === "interface") {
|
|
463
|
+
return resolveInterfaceDeclaration(found.node, checker, visited);
|
|
464
|
+
}
|
|
465
|
+
if (found.kind === "typeAlias") {
|
|
466
|
+
return resolveTypeNode(found.node.type, checker, visited);
|
|
467
|
+
}
|
|
468
|
+
if (found.kind === "enum") {
|
|
469
|
+
return resolveEnumDeclaration(found.node);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
return null;
|
|
474
|
+
}
|
|
475
|
+
function findTopLevelDecl(sourceFile, typeName) {
|
|
476
|
+
let found = null;
|
|
477
|
+
ts2.forEachChild(sourceFile, (node) => {
|
|
478
|
+
if (found) return;
|
|
479
|
+
if (ts2.isInterfaceDeclaration(node) && node.name.text === typeName) {
|
|
480
|
+
found = { kind: "interface", node };
|
|
481
|
+
} else if (ts2.isTypeAliasDeclaration(node) && node.name.text === typeName) {
|
|
482
|
+
found = { kind: "typeAlias", node };
|
|
483
|
+
} else if (ts2.isEnumDeclaration(node) && node.name.text === typeName) {
|
|
484
|
+
found = { kind: "enum", node };
|
|
485
|
+
}
|
|
486
|
+
});
|
|
487
|
+
return found;
|
|
488
|
+
}
|
|
359
489
|
function resolveEnumDeclaration(node) {
|
|
360
490
|
const members = [];
|
|
361
491
|
let nextNumericValue = 0;
|
|
@@ -534,10 +664,11 @@ function validateConstraints(constraints, type, fieldName) {
|
|
|
534
664
|
}
|
|
535
665
|
}
|
|
536
666
|
}
|
|
537
|
-
var SchemaExtractionError, NUMBER_CONSTRAINT_KINDS, LENGTH_CONSTRAINT_KINDS, STRING_FORMAT_CONSTRAINT_KINDS;
|
|
667
|
+
var currentProgram, SchemaExtractionError, NUMBER_CONSTRAINT_KINDS, LENGTH_CONSTRAINT_KINDS, STRING_FORMAT_CONSTRAINT_KINDS;
|
|
538
668
|
var init_resolveTypeNode = __esm({
|
|
539
669
|
"src/ast/resolveTypeNode.ts"() {
|
|
540
670
|
"use strict";
|
|
671
|
+
currentProgram = null;
|
|
541
672
|
SchemaExtractionError = class extends Error {
|
|
542
673
|
constructor(typeText, reason, options) {
|
|
543
674
|
super(`\u65E0\u6CD5\u89E3\u6790\u7C7B\u578B "${typeText}": ${reason}`, options);
|
|
@@ -577,80 +708,90 @@ function extractTypeInfo(program, filePath, typeName) {
|
|
|
577
708
|
const sourceFile = program.getSourceFile(filePath);
|
|
578
709
|
if (!sourceFile) return null;
|
|
579
710
|
const checker = program.getTypeChecker();
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
711
|
+
setProgramContext(program);
|
|
712
|
+
try {
|
|
713
|
+
let result = null;
|
|
714
|
+
ts3.forEachChild(sourceFile, (node) => {
|
|
715
|
+
if (result) return;
|
|
716
|
+
if (ts3.isInterfaceDeclaration(node) && node.name.text === typeName) {
|
|
717
|
+
const visited = /* @__PURE__ */ new Set();
|
|
718
|
+
visited.add(typeName);
|
|
719
|
+
const runtimeType = withFileContext(
|
|
720
|
+
filePath,
|
|
721
|
+
typeName,
|
|
722
|
+
() => resolveInterfaceDeclaration(node, checker, visited)
|
|
723
|
+
);
|
|
724
|
+
result = {
|
|
725
|
+
name: typeName,
|
|
726
|
+
properties: runtimeType.kind === "object" ? runtimeType.properties : [],
|
|
727
|
+
runtimeType
|
|
728
|
+
};
|
|
729
|
+
return;
|
|
730
|
+
}
|
|
731
|
+
if (ts3.isTypeAliasDeclaration(node) && node.name.text === typeName) {
|
|
732
|
+
const visited = /* @__PURE__ */ new Set();
|
|
733
|
+
visited.add(typeName);
|
|
734
|
+
const runtimeType = withFileContext(
|
|
735
|
+
filePath,
|
|
736
|
+
typeName,
|
|
737
|
+
() => resolveTypeNode(node.type, checker, visited)
|
|
738
|
+
);
|
|
739
|
+
result = {
|
|
740
|
+
name: typeName,
|
|
741
|
+
properties: runtimeType.kind === "object" ? runtimeType.properties : [],
|
|
742
|
+
runtimeType
|
|
743
|
+
};
|
|
744
|
+
return;
|
|
745
|
+
}
|
|
746
|
+
});
|
|
747
|
+
return result;
|
|
748
|
+
} finally {
|
|
749
|
+
setProgramContext(null);
|
|
750
|
+
}
|
|
615
751
|
}
|
|
616
752
|
function extractAllTypes(program, filePath) {
|
|
617
753
|
const sourceFile = program.getSourceFile(filePath);
|
|
618
754
|
if (!sourceFile) return /* @__PURE__ */ new Map();
|
|
619
755
|
const checker = program.getTypeChecker();
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
756
|
+
setProgramContext(program);
|
|
757
|
+
try {
|
|
758
|
+
const result = /* @__PURE__ */ new Map();
|
|
759
|
+
ts3.forEachChild(sourceFile, (node) => {
|
|
760
|
+
if (ts3.isInterfaceDeclaration(node)) {
|
|
761
|
+
const visited = /* @__PURE__ */ new Set();
|
|
762
|
+
visited.add(node.name.text);
|
|
763
|
+
const runtimeType = withFileContext(
|
|
764
|
+
filePath,
|
|
765
|
+
node.name.text,
|
|
766
|
+
() => resolveInterfaceDeclaration(node, checker, visited)
|
|
767
|
+
);
|
|
768
|
+
result.set(node.name.text, {
|
|
769
|
+
name: node.name.text,
|
|
770
|
+
properties: runtimeType.kind === "object" ? runtimeType.properties : [],
|
|
771
|
+
runtimeType
|
|
772
|
+
});
|
|
773
|
+
return;
|
|
774
|
+
}
|
|
775
|
+
if (ts3.isTypeAliasDeclaration(node)) {
|
|
776
|
+
const visited = /* @__PURE__ */ new Set();
|
|
777
|
+
visited.add(node.name.text);
|
|
778
|
+
const runtimeType = withFileContext(
|
|
779
|
+
filePath,
|
|
780
|
+
node.name.text,
|
|
781
|
+
() => resolveTypeNode(node.type, checker, visited)
|
|
782
|
+
);
|
|
783
|
+
result.set(node.name.text, {
|
|
784
|
+
name: node.name.text,
|
|
785
|
+
properties: runtimeType.kind === "object" ? runtimeType.properties : [],
|
|
786
|
+
runtimeType
|
|
787
|
+
});
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
790
|
+
});
|
|
791
|
+
return result;
|
|
792
|
+
} finally {
|
|
793
|
+
setProgramContext(null);
|
|
794
|
+
}
|
|
654
795
|
}
|
|
655
796
|
function withFileContext(filePath, typeName, fn) {
|
|
656
797
|
try {
|
|
@@ -851,11 +992,11 @@ var init_analyzeInjection = __esm({
|
|
|
851
992
|
});
|
|
852
993
|
|
|
853
994
|
// src/cli/collectRouteSchemaSources.ts
|
|
854
|
-
import
|
|
995
|
+
import path2 from "path";
|
|
855
996
|
function collectRouteSchemaSources(routes, rootDir) {
|
|
856
997
|
const methodsByFile = /* @__PURE__ */ new Map();
|
|
857
998
|
for (const route of routes) {
|
|
858
|
-
const filePath = rootDir ?
|
|
999
|
+
const filePath = rootDir ? path2.resolve(rootDir, route.filePath) : route.filePath;
|
|
859
1000
|
let entry = methodsByFile.get(filePath);
|
|
860
1001
|
if (!entry) {
|
|
861
1002
|
entry = { urlPath: route.urlPath, methods: /* @__PURE__ */ new Set() };
|
|
@@ -1223,8 +1364,8 @@ __export(generateSchemaFiles_exports, {
|
|
|
1223
1364
|
getRuntimeSchemaPath: () => getRuntimeSchemaPath,
|
|
1224
1365
|
getSchemaOutputPath: () => getSchemaOutputPath
|
|
1225
1366
|
});
|
|
1226
|
-
import
|
|
1227
|
-
import
|
|
1367
|
+
import path6 from "path";
|
|
1368
|
+
import fs5 from "fs/promises";
|
|
1228
1369
|
function getSchemaOutputPath(sourceFile, dist, rootDir) {
|
|
1229
1370
|
let rel = sourceFile.replace(/\\/g, "/");
|
|
1230
1371
|
if (rel.startsWith("src/")) {
|
|
@@ -1232,7 +1373,7 @@ function getSchemaOutputPath(sourceFile, dist, rootDir) {
|
|
|
1232
1373
|
}
|
|
1233
1374
|
const idx = rel.lastIndexOf("/");
|
|
1234
1375
|
const relDir = idx >= 0 ? rel.slice(0, idx) : "";
|
|
1235
|
-
return
|
|
1376
|
+
return path6.resolve(rootDir, dist, relDir, "zod.js");
|
|
1236
1377
|
}
|
|
1237
1378
|
function getRuntimeSchemaPath(filePath, dist, rootDir) {
|
|
1238
1379
|
let rel = filePath.replace(/\\/g, "/");
|
|
@@ -1243,7 +1384,7 @@ function getRuntimeSchemaPath(filePath, dist, rootDir) {
|
|
|
1243
1384
|
}
|
|
1244
1385
|
const idx = rel.lastIndexOf("/");
|
|
1245
1386
|
const relDir = idx >= 0 ? rel.slice(0, idx) : "";
|
|
1246
|
-
return
|
|
1387
|
+
return path6.resolve(rootDir, dist, relDir, "zod.js");
|
|
1247
1388
|
}
|
|
1248
1389
|
function getHelpersImportPath(relDir) {
|
|
1249
1390
|
if (!relDir) return `./${HELPERS_FILENAME}`;
|
|
@@ -1293,7 +1434,7 @@ async function generateSchemaFiles(routes, rootDir, dist) {
|
|
|
1293
1434
|
}
|
|
1294
1435
|
const fileEntries = [];
|
|
1295
1436
|
for (const [filePath, fileSources] of sourcesByFile) {
|
|
1296
|
-
const relFile =
|
|
1437
|
+
const relFile = path6.relative(rootDir, filePath).replace(/\\/g, "/");
|
|
1297
1438
|
const outputPath = getSchemaOutputPath(relFile, dist, rootDir);
|
|
1298
1439
|
const allTypes = allTypesByFile.get(filePath) ?? /* @__PURE__ */ new Map();
|
|
1299
1440
|
let relForDir = relFile;
|
|
@@ -1308,7 +1449,7 @@ async function generateSchemaFiles(routes, rootDir, dist) {
|
|
|
1308
1449
|
}
|
|
1309
1450
|
const allSourceCode = fileEntries.map((e) => e.source).join("\n");
|
|
1310
1451
|
if (usesCoerceHelpers(allSourceCode)) {
|
|
1311
|
-
const helpersPath =
|
|
1452
|
+
const helpersPath = path6.resolve(rootDir, dist, HELPERS_FILENAME);
|
|
1312
1453
|
await writeSchemaFile(helpersPath, generateHelpersFileSource());
|
|
1313
1454
|
}
|
|
1314
1455
|
await Promise.all(
|
|
@@ -1316,8 +1457,8 @@ async function generateSchemaFiles(routes, rootDir, dist) {
|
|
|
1316
1457
|
);
|
|
1317
1458
|
}
|
|
1318
1459
|
async function writeSchemaFile(outputPath, source) {
|
|
1319
|
-
await
|
|
1320
|
-
await
|
|
1460
|
+
await fs5.mkdir(path6.dirname(outputPath), { recursive: true });
|
|
1461
|
+
await fs5.writeFile(outputPath, source, "utf-8");
|
|
1321
1462
|
}
|
|
1322
1463
|
var init_generateSchemaFiles = __esm({
|
|
1323
1464
|
"src/cli/generateSchemaFiles.ts"() {
|
|
@@ -1350,53 +1491,27 @@ function getTool(name) {
|
|
|
1350
1491
|
return registry.get(name);
|
|
1351
1492
|
}
|
|
1352
1493
|
|
|
1353
|
-
// src/injection/skillRegistry.ts
|
|
1354
|
-
var registry2 = /* @__PURE__ */ new Map();
|
|
1355
|
-
function hydrateSkillRegistry(skills) {
|
|
1356
|
-
const next = /* @__PURE__ */ new Map();
|
|
1357
|
-
for (const skill of skills) {
|
|
1358
|
-
next.set(skill.name, skill);
|
|
1359
|
-
}
|
|
1360
|
-
registry2 = next;
|
|
1361
|
-
}
|
|
1362
|
-
function clearSkillRegistry() {
|
|
1363
|
-
registry2 = /* @__PURE__ */ new Map();
|
|
1364
|
-
}
|
|
1365
|
-
function upsertSkill(core) {
|
|
1366
|
-
registry2.set(core.name, core);
|
|
1367
|
-
}
|
|
1368
|
-
function removeSkill(name) {
|
|
1369
|
-
registry2.delete(name);
|
|
1370
|
-
}
|
|
1371
|
-
function getSkill(name) {
|
|
1372
|
-
return registry2.get(name);
|
|
1373
|
-
}
|
|
1374
|
-
function listSkills() {
|
|
1375
|
-
return Array.from(registry2.values());
|
|
1376
|
-
}
|
|
1377
|
-
|
|
1378
1494
|
// src/injection/agentRegistry.ts
|
|
1379
|
-
var
|
|
1495
|
+
var registry2 = /* @__PURE__ */ new Map();
|
|
1380
1496
|
function hydrateAgentRegistry(agents) {
|
|
1381
1497
|
const next = /* @__PURE__ */ new Map();
|
|
1382
1498
|
for (const agent of agents) {
|
|
1383
1499
|
next.set(agent.name, agent);
|
|
1384
1500
|
}
|
|
1385
|
-
|
|
1501
|
+
registry2 = next;
|
|
1386
1502
|
}
|
|
1387
1503
|
function clearAgentRegistry() {
|
|
1388
|
-
|
|
1504
|
+
registry2 = /* @__PURE__ */ new Map();
|
|
1389
1505
|
}
|
|
1390
1506
|
function getAgent(name) {
|
|
1391
|
-
return
|
|
1507
|
+
return registry2.get(name);
|
|
1392
1508
|
}
|
|
1393
1509
|
function getAgentEntry(name) {
|
|
1394
|
-
return
|
|
1510
|
+
return registry2.get(name);
|
|
1395
1511
|
}
|
|
1396
1512
|
function listAgents() {
|
|
1397
1513
|
const merged = /* @__PURE__ */ new Map();
|
|
1398
|
-
for (const agent of
|
|
1399
|
-
for (const skill of listSkills()) merged.set(skill.name, skill);
|
|
1514
|
+
for (const agent of registry2.values()) merged.set(agent.name, agent);
|
|
1400
1515
|
return Array.from(merged.values());
|
|
1401
1516
|
}
|
|
1402
1517
|
function resolveAgentTools(name) {
|
|
@@ -1422,8 +1537,33 @@ function resolveSubAgents(name) {
|
|
|
1422
1537
|
return result;
|
|
1423
1538
|
}
|
|
1424
1539
|
|
|
1540
|
+
// src/injection/skillRegistry.ts
|
|
1541
|
+
var registry3 = /* @__PURE__ */ new Map();
|
|
1542
|
+
function hydrateSkillRegistry(skills) {
|
|
1543
|
+
const next = /* @__PURE__ */ new Map();
|
|
1544
|
+
for (const skill of skills) {
|
|
1545
|
+
next.set(skill.name, skill);
|
|
1546
|
+
}
|
|
1547
|
+
registry3 = next;
|
|
1548
|
+
}
|
|
1549
|
+
function clearSkillRegistry() {
|
|
1550
|
+
registry3 = /* @__PURE__ */ new Map();
|
|
1551
|
+
}
|
|
1552
|
+
function upsertSkill(core) {
|
|
1553
|
+
registry3.set(core.name, core);
|
|
1554
|
+
}
|
|
1555
|
+
function removeSkill(name) {
|
|
1556
|
+
registry3.delete(name);
|
|
1557
|
+
}
|
|
1558
|
+
function getSkill(name) {
|
|
1559
|
+
return registry3.get(name);
|
|
1560
|
+
}
|
|
1561
|
+
function listSkills() {
|
|
1562
|
+
return Array.from(registry3.values());
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1425
1565
|
// src/loader/loadAgentModule.ts
|
|
1426
|
-
import
|
|
1566
|
+
import fs7 from "fs";
|
|
1427
1567
|
|
|
1428
1568
|
// src/loader/resolveExports.ts
|
|
1429
1569
|
function resolveExport(module, exportName) {
|
|
@@ -1469,17 +1609,17 @@ async function importWithCacheBust(filePath, bustViteCache = false) {
|
|
|
1469
1609
|
}
|
|
1470
1610
|
|
|
1471
1611
|
// src/cli/compileOnDemand.ts
|
|
1472
|
-
import
|
|
1473
|
-
import
|
|
1612
|
+
import path7 from "path";
|
|
1613
|
+
import fs6 from "fs";
|
|
1474
1614
|
|
|
1475
1615
|
// src/cli/compileDevRoutes.ts
|
|
1476
|
-
import
|
|
1477
|
-
import
|
|
1616
|
+
import path5 from "path";
|
|
1617
|
+
import fs4 from "fs";
|
|
1478
1618
|
import fg from "fast-glob";
|
|
1479
1619
|
|
|
1480
1620
|
// src/cli/aliasPlugin.ts
|
|
1481
|
-
import
|
|
1482
|
-
import
|
|
1621
|
+
import path4 from "path";
|
|
1622
|
+
import fs3 from "fs";
|
|
1483
1623
|
|
|
1484
1624
|
// src/utils/resolveAlias.ts
|
|
1485
1625
|
function resolveAlias(specifier, config) {
|
|
@@ -1506,11 +1646,11 @@ function resolveAlias(specifier, config) {
|
|
|
1506
1646
|
|
|
1507
1647
|
// src/utils/readTsconfig.ts
|
|
1508
1648
|
import ts6 from "typescript";
|
|
1509
|
-
import
|
|
1510
|
-
import
|
|
1649
|
+
import path3 from "path";
|
|
1650
|
+
import fs2 from "fs";
|
|
1511
1651
|
function readTsconfig(rootDir) {
|
|
1512
|
-
const tsconfigPath =
|
|
1513
|
-
if (!
|
|
1652
|
+
const tsconfigPath = path3.resolve(rootDir, "tsconfig.json");
|
|
1653
|
+
if (!fs2.existsSync(tsconfigPath)) return null;
|
|
1514
1654
|
const configFile = ts6.readConfigFile(tsconfigPath, ts6.sys.readFile);
|
|
1515
1655
|
if (configFile.error || !configFile.config) return null;
|
|
1516
1656
|
const parsed = ts6.parseJsonConfigFileContent(configFile.config, ts6.sys, rootDir);
|
|
@@ -1519,7 +1659,7 @@ function readTsconfig(rootDir) {
|
|
|
1519
1659
|
if (!rawPaths) return null;
|
|
1520
1660
|
const paths = {};
|
|
1521
1661
|
for (const [pattern, targets] of Object.entries(rawPaths)) {
|
|
1522
|
-
paths[pattern] = targets.map((t) =>
|
|
1662
|
+
paths[pattern] = targets.map((t) => path3.resolve(baseUrl, t));
|
|
1523
1663
|
}
|
|
1524
1664
|
return { baseUrl, paths };
|
|
1525
1665
|
}
|
|
@@ -1532,29 +1672,29 @@ function toProdExtension(filePath) {
|
|
|
1532
1672
|
return filePath;
|
|
1533
1673
|
}
|
|
1534
1674
|
function toProdImportPath(sourceFile, importer) {
|
|
1535
|
-
const importerDir =
|
|
1536
|
-
let rel =
|
|
1537
|
-
rel = rel.split(
|
|
1675
|
+
const importerDir = path4.dirname(importer);
|
|
1676
|
+
let rel = path4.relative(importerDir, sourceFile);
|
|
1677
|
+
rel = rel.split(path4.sep).join("/");
|
|
1538
1678
|
if (!rel.startsWith(".")) rel = "./" + rel;
|
|
1539
1679
|
return toProdExtension(rel);
|
|
1540
1680
|
}
|
|
1541
1681
|
function toRealPath(p) {
|
|
1542
1682
|
try {
|
|
1543
|
-
return
|
|
1683
|
+
return fs3.realpathSync(p);
|
|
1544
1684
|
} catch {
|
|
1545
1685
|
return p;
|
|
1546
1686
|
}
|
|
1547
1687
|
}
|
|
1548
1688
|
function isInsideDir(filePath, dir) {
|
|
1549
|
-
const rel =
|
|
1550
|
-
return rel !== "" && !rel.startsWith("..") && !
|
|
1689
|
+
const rel = path4.relative(dir, filePath);
|
|
1690
|
+
return rel !== "" && !rel.startsWith("..") && !path4.isAbsolute(rel);
|
|
1551
1691
|
}
|
|
1552
1692
|
var APP_DIR = "src";
|
|
1553
1693
|
function toStrippedProdImportPath(sourceFile, rootDir) {
|
|
1554
|
-
const appDirAbs = toRealPath(
|
|
1694
|
+
const appDirAbs = toRealPath(path4.resolve(rootDir, APP_DIR));
|
|
1555
1695
|
const sourceReal = toRealPath(sourceFile);
|
|
1556
|
-
let rel =
|
|
1557
|
-
rel = rel.split(
|
|
1696
|
+
let rel = path4.relative(appDirAbs, sourceReal);
|
|
1697
|
+
rel = rel.split(path4.sep).join("/");
|
|
1558
1698
|
if (!rel.startsWith(".")) rel = "./" + rel;
|
|
1559
1699
|
return toProdExtension(rel);
|
|
1560
1700
|
}
|
|
@@ -1569,34 +1709,34 @@ var INDEX_EXTS = [
|
|
|
1569
1709
|
"/index.cjs"
|
|
1570
1710
|
];
|
|
1571
1711
|
function resolveRelativeSpecifier(importer, specifier) {
|
|
1572
|
-
const importerDir =
|
|
1573
|
-
const base =
|
|
1712
|
+
const importerDir = path4.dirname(importer);
|
|
1713
|
+
const base = path4.resolve(importerDir, specifier);
|
|
1574
1714
|
if (PROD_EXTS.some((ext) => specifier.endsWith(ext))) {
|
|
1575
|
-
return
|
|
1715
|
+
return fs3.existsSync(base) ? base : null;
|
|
1576
1716
|
}
|
|
1577
1717
|
if (/\.(ts|tsx|jsx)$/.test(specifier)) {
|
|
1578
|
-
return
|
|
1718
|
+
return fs3.existsSync(base) ? base : null;
|
|
1579
1719
|
}
|
|
1580
1720
|
for (const ext of SOURCE_EXTS) {
|
|
1581
1721
|
const file = base + ext;
|
|
1582
|
-
if (
|
|
1722
|
+
if (fs3.existsSync(file)) return file;
|
|
1583
1723
|
}
|
|
1584
1724
|
for (const indexExt of INDEX_EXTS) {
|
|
1585
1725
|
const file = base + indexExt;
|
|
1586
|
-
if (
|
|
1726
|
+
if (fs3.existsSync(file)) return file;
|
|
1587
1727
|
}
|
|
1588
1728
|
return null;
|
|
1589
1729
|
}
|
|
1590
1730
|
function createAliasPlugin(config, options) {
|
|
1591
1731
|
const SPEC_RE = /(\bfrom\s*|import\s*\(\s*)(['"])([^'"]+)\2/g;
|
|
1592
|
-
const appDirAbs = options?.rootDir ? toRealPath(
|
|
1732
|
+
const appDirAbs = options?.rootDir ? toRealPath(path4.resolve(options.rootDir, APP_DIR)) : null;
|
|
1593
1733
|
return {
|
|
1594
1734
|
name: "faapi-alias",
|
|
1595
1735
|
setup(build) {
|
|
1596
1736
|
build.onLoad({ filter: /\.(ts|tsx|js|jsx|mjs|cjs)$/ }, (args) => {
|
|
1597
1737
|
let source;
|
|
1598
1738
|
try {
|
|
1599
|
-
source =
|
|
1739
|
+
source = fs3.readFileSync(args.path, "utf8");
|
|
1600
1740
|
} catch {
|
|
1601
1741
|
return void 0;
|
|
1602
1742
|
}
|
|
@@ -1629,7 +1769,7 @@ function createAliasPlugin(config, options) {
|
|
|
1629
1769
|
for (const candidate of candidates) {
|
|
1630
1770
|
for (const ext of SOURCE_EXTS) {
|
|
1631
1771
|
const file = candidate + ext;
|
|
1632
|
-
if (
|
|
1772
|
+
if (fs3.existsSync(file)) {
|
|
1633
1773
|
modified = true;
|
|
1634
1774
|
if (appDirAbs && importerOutsideAppDir && isInsideDir(file, appDirAbs)) {
|
|
1635
1775
|
return `${prefix}${quote}${toStrippedProdImportPath(
|
|
@@ -1642,7 +1782,7 @@ function createAliasPlugin(config, options) {
|
|
|
1642
1782
|
}
|
|
1643
1783
|
for (const indexExt of INDEX_EXTS) {
|
|
1644
1784
|
const file = candidate + indexExt;
|
|
1645
|
-
if (
|
|
1785
|
+
if (fs3.existsSync(file)) {
|
|
1646
1786
|
modified = true;
|
|
1647
1787
|
if (appDirAbs && importerOutsideAppDir && isInsideDir(file, appDirAbs)) {
|
|
1648
1788
|
return `${prefix}${quote}${toStrippedProdImportPath(
|
|
@@ -1680,11 +1820,11 @@ async function compileDevRoutes(options) {
|
|
|
1680
1820
|
if (entryPoints.length === 0) {
|
|
1681
1821
|
return { compiledFiles: [] };
|
|
1682
1822
|
}
|
|
1683
|
-
const absDist =
|
|
1684
|
-
await
|
|
1823
|
+
const absDist = path5.resolve(rootDir, dist);
|
|
1824
|
+
await fs4.promises.mkdir(absDist, { recursive: true });
|
|
1685
1825
|
const plugins = buildAliasPlugins(rootDir);
|
|
1686
1826
|
const esbuild = await import("esbuild");
|
|
1687
|
-
const outbase =
|
|
1827
|
+
const outbase = path5.resolve(rootDir, APP_DIR2);
|
|
1688
1828
|
const result = await esbuild.build({
|
|
1689
1829
|
entryPoints,
|
|
1690
1830
|
outdir: absDist,
|
|
@@ -1701,10 +1841,10 @@ async function compileDevRoutes(options) {
|
|
|
1701
1841
|
if (result.outputFiles) {
|
|
1702
1842
|
await Promise.all(
|
|
1703
1843
|
result.outputFiles.map(async (file) => {
|
|
1704
|
-
await
|
|
1844
|
+
await fs4.promises.mkdir(path5.dirname(file.path), { recursive: true });
|
|
1705
1845
|
const tmp = `${file.path}.tmp-${process.pid}-${Math.random().toString(36).slice(2)}`;
|
|
1706
|
-
await
|
|
1707
|
-
await
|
|
1846
|
+
await fs4.promises.writeFile(tmp, file.contents);
|
|
1847
|
+
await fs4.promises.rename(tmp, file.path);
|
|
1708
1848
|
})
|
|
1709
1849
|
);
|
|
1710
1850
|
}
|
|
@@ -1716,8 +1856,8 @@ init_generateSchemaFiles();
|
|
|
1716
1856
|
init_generateSchemaFiles();
|
|
1717
1857
|
function isProductFresh(sourceAbsPath, productAbsPath) {
|
|
1718
1858
|
try {
|
|
1719
|
-
const srcStat =
|
|
1720
|
-
const prodStat =
|
|
1859
|
+
const srcStat = fs6.statSync(sourceAbsPath);
|
|
1860
|
+
const prodStat = fs6.statSync(productAbsPath);
|
|
1721
1861
|
return prodStat.mtimeMs >= srcStat.mtimeMs;
|
|
1722
1862
|
} catch {
|
|
1723
1863
|
return false;
|
|
@@ -1748,7 +1888,7 @@ async function ensureCompiled(sourceAbsPath, rootDir, dist) {
|
|
|
1748
1888
|
if (state.compiledFiles.has(sourceAbsPath)) {
|
|
1749
1889
|
return false;
|
|
1750
1890
|
}
|
|
1751
|
-
if (!
|
|
1891
|
+
if (!fs6.existsSync(sourceAbsPath)) {
|
|
1752
1892
|
return false;
|
|
1753
1893
|
}
|
|
1754
1894
|
const productPath = prodSourcePathToProductPath(sourceAbsPath, rootDir, dist);
|
|
@@ -1774,11 +1914,11 @@ async function ensureCompiled(sourceAbsPath, rootDir, dist) {
|
|
|
1774
1914
|
}
|
|
1775
1915
|
}
|
|
1776
1916
|
function prodSourcePathToProductPath(sourceAbsPath, rootDir, dist) {
|
|
1777
|
-
const rel =
|
|
1917
|
+
const rel = path7.relative(rootDir, sourceAbsPath).replace(/\\/g, "/");
|
|
1778
1918
|
if (!rel.startsWith("src/")) return null;
|
|
1779
1919
|
const relWithoutSrc = rel.slice(4);
|
|
1780
1920
|
const jsRel = relWithoutSrc.replace(/\.ts$/, ".js");
|
|
1781
|
-
return
|
|
1921
|
+
return path7.resolve(rootDir, dist, jsRel);
|
|
1782
1922
|
}
|
|
1783
1923
|
function clearGeneratedSchemas() {
|
|
1784
1924
|
state.generatedSchemas.clear();
|
|
@@ -1794,9 +1934,9 @@ async function ensureSchemaGenerated(schemaPath, routeFilePath, routes, rootDir,
|
|
|
1794
1934
|
if (state.generatedSchemas.has(schemaPath)) {
|
|
1795
1935
|
return false;
|
|
1796
1936
|
}
|
|
1797
|
-
const prodAbsPath =
|
|
1937
|
+
const prodAbsPath = path7.resolve(rootDir, routeFilePath);
|
|
1798
1938
|
const sourceAbsPath = prodPathToSourcePath(prodAbsPath, rootDir, dist);
|
|
1799
|
-
if (!
|
|
1939
|
+
if (!fs6.existsSync(sourceAbsPath)) {
|
|
1800
1940
|
return false;
|
|
1801
1941
|
}
|
|
1802
1942
|
if (isProductFresh(sourceAbsPath, schemaPath)) {
|
|
@@ -1807,7 +1947,7 @@ async function ensureSchemaGenerated(schemaPath, routeFilePath, routes, rootDir,
|
|
|
1807
1947
|
if (fileRoutes.length === 0) {
|
|
1808
1948
|
return false;
|
|
1809
1949
|
}
|
|
1810
|
-
const sourceRelPath =
|
|
1950
|
+
const sourceRelPath = path7.relative(rootDir, sourceAbsPath).replace(/\\/g, "/");
|
|
1811
1951
|
const sourceRoutes = fileRoutes.map((r) => ({ ...r, filePath: sourceRelPath }));
|
|
1812
1952
|
const generatePromise = (async () => {
|
|
1813
1953
|
await generateSchemaFiles(sourceRoutes, rootDir, dist);
|
|
@@ -1828,22 +1968,22 @@ async function deleteSchemaFiles(routes, rootDir, dist) {
|
|
|
1828
1968
|
if (deleted.has(schemaPath)) continue;
|
|
1829
1969
|
deleted.add(schemaPath);
|
|
1830
1970
|
try {
|
|
1831
|
-
await
|
|
1971
|
+
await fs6.promises.unlink(schemaPath);
|
|
1832
1972
|
} catch {
|
|
1833
1973
|
}
|
|
1834
1974
|
}
|
|
1835
1975
|
}
|
|
1836
1976
|
function prodPathToSourcePath(prodAbsPath, rootDir, dist) {
|
|
1837
|
-
const rel =
|
|
1977
|
+
const rel = path7.relative(rootDir, prodAbsPath).replace(/\\/g, "/");
|
|
1838
1978
|
let relWithoutDist = rel;
|
|
1839
1979
|
if (relWithoutDist.startsWith(`${dist}/`)) {
|
|
1840
1980
|
relWithoutDist = relWithoutDist.slice(dist.length + 1);
|
|
1841
1981
|
}
|
|
1842
1982
|
const srcRel = `src/${relWithoutDist}`;
|
|
1843
1983
|
const tsRel = srcRel.replace(/\.js$/, ".ts");
|
|
1844
|
-
const tsAbs =
|
|
1845
|
-
if (
|
|
1846
|
-
return
|
|
1984
|
+
const tsAbs = path7.resolve(rootDir, tsRel);
|
|
1985
|
+
if (fs6.existsSync(tsAbs)) return tsAbs;
|
|
1986
|
+
return path7.resolve(rootDir, srcRel);
|
|
1847
1987
|
}
|
|
1848
1988
|
function isDevOnDemandEnabled() {
|
|
1849
1989
|
return state.enabled;
|
|
@@ -1858,7 +1998,7 @@ async function loadAgentModule(filePath, hasRun, rootDir) {
|
|
|
1858
1998
|
const dist = getDevDist();
|
|
1859
1999
|
if (dist) {
|
|
1860
2000
|
const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
|
|
1861
|
-
if (sourcePath &&
|
|
2001
|
+
if (sourcePath && fs7.existsSync(sourcePath)) {
|
|
1862
2002
|
try {
|
|
1863
2003
|
await ensureCompiled(sourcePath, rootDir, dist);
|
|
1864
2004
|
} catch (compileErr) {
|
|
@@ -1891,13 +2031,13 @@ async function loadAgentModule(filePath, hasRun, rootDir) {
|
|
|
1891
2031
|
}
|
|
1892
2032
|
|
|
1893
2033
|
// src/loader/loadToolModule.ts
|
|
1894
|
-
import
|
|
2034
|
+
import fs8 from "fs";
|
|
1895
2035
|
async function loadToolModule(filePath, functionName, rootDir) {
|
|
1896
2036
|
if (isDevOnDemandEnabled() && rootDir) {
|
|
1897
2037
|
const dist = getDevDist();
|
|
1898
2038
|
if (dist) {
|
|
1899
2039
|
const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
|
|
1900
|
-
if (sourcePath &&
|
|
2040
|
+
if (sourcePath && fs8.existsSync(sourcePath)) {
|
|
1901
2041
|
try {
|
|
1902
2042
|
await ensureCompiled(sourcePath, rootDir, dist);
|
|
1903
2043
|
} catch (compileErr) {
|
|
@@ -1929,8 +2069,8 @@ async function loadToolModule(filePath, functionName, rootDir) {
|
|
|
1929
2069
|
import { existsSync as existsSync2 } from "fs";
|
|
1930
2070
|
|
|
1931
2071
|
// src/cli/generateToolArtifacts.ts
|
|
1932
|
-
import
|
|
1933
|
-
import
|
|
2072
|
+
import path8 from "path";
|
|
2073
|
+
import fs9 from "fs/promises";
|
|
1934
2074
|
import { existsSync } from "fs";
|
|
1935
2075
|
|
|
1936
2076
|
// src/ast/extractToolMetadata.ts
|
|
@@ -2025,7 +2165,7 @@ function getToolSchemaOutputPath(sourceFile, dist, rootDir) {
|
|
|
2025
2165
|
}
|
|
2026
2166
|
const idx = rel.lastIndexOf("/");
|
|
2027
2167
|
const relDir = idx >= 0 ? rel.slice(0, idx) : "";
|
|
2028
|
-
return
|
|
2168
|
+
return path8.resolve(rootDir, dist, relDir, "zod.js");
|
|
2029
2169
|
}
|
|
2030
2170
|
function getRuntimeToolSchemaPath(filePath, dist, rootDir) {
|
|
2031
2171
|
let rel = filePath.replace(/\\/g, "/");
|
|
@@ -2036,7 +2176,7 @@ function getRuntimeToolSchemaPath(filePath, dist, rootDir) {
|
|
|
2036
2176
|
}
|
|
2037
2177
|
const idx = rel.lastIndexOf("/");
|
|
2038
2178
|
const relDir = idx >= 0 ? rel.slice(0, idx) : "";
|
|
2039
|
-
return
|
|
2179
|
+
return path8.resolve(rootDir, dist, relDir, "zod.js");
|
|
2040
2180
|
}
|
|
2041
2181
|
function toProdFilePath(filePath, dist) {
|
|
2042
2182
|
let rel = filePath.replace(/\\/g, "/");
|
|
@@ -2056,12 +2196,12 @@ function serializeTools(tools, dist = "dist") {
|
|
|
2056
2196
|
}));
|
|
2057
2197
|
}
|
|
2058
2198
|
async function writeToolsModule(manifest, outputPath) {
|
|
2059
|
-
const dir =
|
|
2060
|
-
await
|
|
2199
|
+
const dir = path8.dirname(outputPath);
|
|
2200
|
+
await fs9.mkdir(dir, { recursive: true });
|
|
2061
2201
|
const content = `// \u81EA\u52A8\u751F\u6210,\u8BF7\u52FF\u624B\u52A8\u7F16\u8F91(faapi build/dev \u4EA7\u7269)
|
|
2062
2202
|
export const tools = ${JSON.stringify(manifest, null, 2)};
|
|
2063
2203
|
`;
|
|
2064
|
-
await
|
|
2204
|
+
await fs9.writeFile(outputPath, content, "utf-8");
|
|
2065
2205
|
}
|
|
2066
2206
|
function hydrateTools(manifest) {
|
|
2067
2207
|
return manifest.map((t) => ({
|
|
@@ -2076,7 +2216,7 @@ function collectToolSchemaSources(tools, rootDir) {
|
|
|
2076
2216
|
const toolsByFile = /* @__PURE__ */ new Map();
|
|
2077
2217
|
for (const tool of tools) {
|
|
2078
2218
|
if (!tool.inputTypeName) continue;
|
|
2079
|
-
const absPath =
|
|
2219
|
+
const absPath = path8.resolve(rootDir, tool.filePath);
|
|
2080
2220
|
let list = toolsByFile.get(absPath);
|
|
2081
2221
|
if (!list) {
|
|
2082
2222
|
list = [];
|
|
@@ -2138,15 +2278,15 @@ function generateToolSchemaFileSource(sources, allTypes, helpersImportPath) {
|
|
|
2138
2278
|
}
|
|
2139
2279
|
async function maybeGenerateHelpers(allSourceCode, distDir) {
|
|
2140
2280
|
if (!usesCoerceHelpers(allSourceCode)) return;
|
|
2141
|
-
const helpersPath =
|
|
2281
|
+
const helpersPath = path8.resolve(distDir, HELPERS_FILENAME);
|
|
2142
2282
|
if (existsSync(helpersPath)) return;
|
|
2143
|
-
await
|
|
2144
|
-
await
|
|
2283
|
+
await fs9.mkdir(path8.dirname(helpersPath), { recursive: true });
|
|
2284
|
+
await fs9.writeFile(helpersPath, generateHelpersFileSource(), "utf-8");
|
|
2145
2285
|
}
|
|
2146
2286
|
async function generateToolArtifacts(tools, rootDir, dist, options) {
|
|
2147
2287
|
const metadata = [];
|
|
2148
2288
|
for (const manifest of tools) {
|
|
2149
|
-
const absPath =
|
|
2289
|
+
const absPath = path8.resolve(rootDir, manifest.filePath);
|
|
2150
2290
|
const program = createProgram(absPath);
|
|
2151
2291
|
const result = extractToolMetadata(program, absPath, manifest.functionName, {
|
|
2152
2292
|
name: manifest.name,
|
|
@@ -2157,7 +2297,7 @@ async function generateToolArtifacts(tools, rootDir, dist, options) {
|
|
|
2157
2297
|
}
|
|
2158
2298
|
}
|
|
2159
2299
|
const serialized = serializeTools(metadata, dist);
|
|
2160
|
-
const toolsPath =
|
|
2300
|
+
const toolsPath = path8.resolve(rootDir, dist, TOOLS_FILE);
|
|
2161
2301
|
await writeToolsModule(serialized, toolsPath);
|
|
2162
2302
|
if (options?.skipSchema) {
|
|
2163
2303
|
return metadata;
|
|
@@ -2180,7 +2320,7 @@ async function generateToolArtifacts(tools, rootDir, dist, options) {
|
|
|
2180
2320
|
}
|
|
2181
2321
|
const fileEntries = [];
|
|
2182
2322
|
for (const [filePath, fileSources] of sourcesByFile) {
|
|
2183
|
-
const relFile =
|
|
2323
|
+
const relFile = path8.relative(rootDir, filePath).replace(/\\/g, "/");
|
|
2184
2324
|
const outputPath = getToolSchemaOutputPath(relFile, dist, rootDir);
|
|
2185
2325
|
const allTypes = allTypesByFile.get(filePath) ?? /* @__PURE__ */ new Map();
|
|
2186
2326
|
let relForDir = relFile;
|
|
@@ -2194,7 +2334,7 @@ async function generateToolArtifacts(tools, rootDir, dist, options) {
|
|
|
2194
2334
|
fileEntries.push({ outputPath, source });
|
|
2195
2335
|
}
|
|
2196
2336
|
const allSourceCode = fileEntries.map((e) => e.source).join("\n");
|
|
2197
|
-
const distDir =
|
|
2337
|
+
const distDir = path8.resolve(rootDir, dist);
|
|
2198
2338
|
await maybeGenerateHelpers(allSourceCode, distDir);
|
|
2199
2339
|
await Promise.all(
|
|
2200
2340
|
fileEntries.map(({ outputPath, source }) => writeToolSchemaFile(outputPath, source))
|
|
@@ -2202,8 +2342,8 @@ async function generateToolArtifacts(tools, rootDir, dist, options) {
|
|
|
2202
2342
|
return metadata;
|
|
2203
2343
|
}
|
|
2204
2344
|
async function writeToolSchemaFile(outputPath, source) {
|
|
2205
|
-
await
|
|
2206
|
-
await
|
|
2345
|
+
await fs9.mkdir(path8.dirname(outputPath), { recursive: true });
|
|
2346
|
+
await fs9.writeFile(outputPath, source, "utf-8");
|
|
2207
2347
|
}
|
|
2208
2348
|
|
|
2209
2349
|
// src/loader/loadToolSchema.ts
|
|
@@ -2403,16 +2543,16 @@ function helmet(options = {}) {
|
|
|
2403
2543
|
}
|
|
2404
2544
|
|
|
2405
2545
|
// src/config/loadConfig.ts
|
|
2406
|
-
import
|
|
2407
|
-
import
|
|
2546
|
+
import path9 from "path";
|
|
2547
|
+
import fs10 from "fs";
|
|
2408
2548
|
var CONFIG_PRODUCT_FILE = "faapi-config.js";
|
|
2409
2549
|
async function loadConfig(rootDir, dist) {
|
|
2410
|
-
const configProductPath =
|
|
2411
|
-
if (
|
|
2550
|
+
const configProductPath = path9.resolve(rootDir, dist, CONFIG_PRODUCT_FILE);
|
|
2551
|
+
if (fs10.existsSync(configProductPath)) {
|
|
2412
2552
|
const module = await importWithCacheBust(configProductPath);
|
|
2413
2553
|
return module.default ?? {};
|
|
2414
2554
|
}
|
|
2415
|
-
const hasSourceConfig =
|
|
2555
|
+
const hasSourceConfig = fs10.existsSync(path9.join(rootDir, "faapi.config.ts")) || fs10.existsSync(path9.join(rootDir, "faapi.config.js"));
|
|
2416
2556
|
if (hasSourceConfig) {
|
|
2417
2557
|
throw new Error(
|
|
2418
2558
|
`[faapi] ${dist}/${CONFIG_PRODUCT_FILE} \u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u6267\u884C \`faapi build\`\uFF08\u6216 \`faapi dev\`\uFF09\u751F\u6210\u4EA7\u7269\u3002`
|
|
@@ -2422,8 +2562,8 @@ async function loadConfig(rootDir, dist) {
|
|
|
2422
2562
|
}
|
|
2423
2563
|
|
|
2424
2564
|
// src/cli/loadEnv.ts
|
|
2425
|
-
import
|
|
2426
|
-
import
|
|
2565
|
+
import fs11 from "fs";
|
|
2566
|
+
import path10 from "path";
|
|
2427
2567
|
function resolveEnv() {
|
|
2428
2568
|
return process.env.NODE_ENV || "development";
|
|
2429
2569
|
}
|
|
@@ -2489,9 +2629,9 @@ function loadEnv(rootDir) {
|
|
|
2489
2629
|
const files = getEnvFiles(env);
|
|
2490
2630
|
const merged = {};
|
|
2491
2631
|
for (const file of files) {
|
|
2492
|
-
const filePath =
|
|
2493
|
-
if (!
|
|
2494
|
-
const content =
|
|
2632
|
+
const filePath = path10.join(rootDir, file);
|
|
2633
|
+
if (!fs11.existsSync(filePath)) continue;
|
|
2634
|
+
const content = fs11.readFileSync(filePath, "utf-8");
|
|
2495
2635
|
const parsed = parseEnvFile(content, merged);
|
|
2496
2636
|
Object.assign(merged, parsed);
|
|
2497
2637
|
}
|
|
@@ -2528,14 +2668,14 @@ var ValidationError = class extends FaapiError {
|
|
|
2528
2668
|
issues;
|
|
2529
2669
|
};
|
|
2530
2670
|
var RouteNotFoundError = class extends FaapiError {
|
|
2531
|
-
constructor(
|
|
2532
|
-
super("ROUTE_NOT_FOUND", `Route not found: ${
|
|
2671
|
+
constructor(path19) {
|
|
2672
|
+
super("ROUTE_NOT_FOUND", `Route not found: ${path19}`, 404);
|
|
2533
2673
|
this.name = "RouteNotFoundError";
|
|
2534
2674
|
}
|
|
2535
2675
|
};
|
|
2536
2676
|
var MethodNotAllowedError = class extends FaapiError {
|
|
2537
|
-
constructor(method,
|
|
2538
|
-
super("METHOD_NOT_ALLOWED", `Method ${method} not allowed for ${
|
|
2677
|
+
constructor(method, path19, allowedMethods) {
|
|
2678
|
+
super("METHOD_NOT_ALLOWED", `Method ${method} not allowed for ${path19}`, 405);
|
|
2539
2679
|
this.allowedMethods = allowedMethods;
|
|
2540
2680
|
this.name = "MethodNotAllowedError";
|
|
2541
2681
|
}
|
|
@@ -2561,8 +2701,8 @@ var PayloadTooLargeError = class extends FaapiError {
|
|
|
2561
2701
|
};
|
|
2562
2702
|
|
|
2563
2703
|
// src/cli/createAppCore.ts
|
|
2564
|
-
import
|
|
2565
|
-
import
|
|
2704
|
+
import fs16 from "fs";
|
|
2705
|
+
import path15 from "path";
|
|
2566
2706
|
import { PassThrough, Readable as Readable3 } from "stream";
|
|
2567
2707
|
|
|
2568
2708
|
// src/router/sortRoutes.ts
|
|
@@ -2615,45 +2755,45 @@ import {
|
|
|
2615
2755
|
import { createSecureServer as createHttp2SecureServer } from "http2";
|
|
2616
2756
|
import { readFileSync } from "fs";
|
|
2617
2757
|
import { Readable as Readable2 } from "stream";
|
|
2618
|
-
import
|
|
2758
|
+
import path12 from "path";
|
|
2619
2759
|
|
|
2620
2760
|
// src/router/matchRoute.ts
|
|
2621
|
-
function matchRoute(routes, method,
|
|
2761
|
+
function matchRoute(routes, method, path19) {
|
|
2622
2762
|
for (const route of routes) {
|
|
2623
2763
|
if (route.method !== method) {
|
|
2624
2764
|
continue;
|
|
2625
2765
|
}
|
|
2626
2766
|
if (!route.isDynamic) {
|
|
2627
|
-
if (route.urlPath ===
|
|
2767
|
+
if (route.urlPath === path19) {
|
|
2628
2768
|
return { route, params: {} };
|
|
2629
2769
|
}
|
|
2630
2770
|
continue;
|
|
2631
2771
|
}
|
|
2632
|
-
const params = matchDynamicPath(route.urlPath,
|
|
2772
|
+
const params = matchDynamicPath(route.urlPath, path19, route.paramNames, route.isCatchAll);
|
|
2633
2773
|
if (params !== null) {
|
|
2634
2774
|
return { route, params };
|
|
2635
2775
|
}
|
|
2636
2776
|
}
|
|
2637
2777
|
return null;
|
|
2638
2778
|
}
|
|
2639
|
-
function matchWsRoute(wsRoutes,
|
|
2779
|
+
function matchWsRoute(wsRoutes, path19) {
|
|
2640
2780
|
for (const route of wsRoutes) {
|
|
2641
2781
|
if (!route.isDynamic) {
|
|
2642
|
-
if (route.urlPath ===
|
|
2782
|
+
if (route.urlPath === path19) {
|
|
2643
2783
|
return { route, params: {} };
|
|
2644
2784
|
}
|
|
2645
2785
|
continue;
|
|
2646
2786
|
}
|
|
2647
|
-
const params = matchDynamicPath(route.urlPath,
|
|
2787
|
+
const params = matchDynamicPath(route.urlPath, path19, route.paramNames, route.isCatchAll);
|
|
2648
2788
|
if (params !== null) {
|
|
2649
2789
|
return { route, params };
|
|
2650
2790
|
}
|
|
2651
2791
|
}
|
|
2652
2792
|
return null;
|
|
2653
2793
|
}
|
|
2654
|
-
function matchDynamicPath(pattern,
|
|
2794
|
+
function matchDynamicPath(pattern, path19, paramNames, isCatchAll) {
|
|
2655
2795
|
const patternSegments = pattern.split("/").filter(Boolean);
|
|
2656
|
-
const pathSegments =
|
|
2796
|
+
const pathSegments = path19.split("/").filter(Boolean);
|
|
2657
2797
|
if (isCatchAll) {
|
|
2658
2798
|
const nonCatchAllCount = patternSegments.length - 1;
|
|
2659
2799
|
if (pathSegments.length <= nonCatchAllCount) {
|
|
@@ -2699,7 +2839,7 @@ function matchDynamicPath(pattern, path18, paramNames, isCatchAll) {
|
|
|
2699
2839
|
}
|
|
2700
2840
|
|
|
2701
2841
|
// src/loader/loadRouteModule.ts
|
|
2702
|
-
import
|
|
2842
|
+
import fs12 from "fs";
|
|
2703
2843
|
|
|
2704
2844
|
// src/loader/validateRouteModule.ts
|
|
2705
2845
|
function validateRouteModule(value, method, filePath) {
|
|
@@ -2716,7 +2856,7 @@ async function loadRouteModule(filePath, method, rootDir) {
|
|
|
2716
2856
|
const dist = getDevDist();
|
|
2717
2857
|
if (dist) {
|
|
2718
2858
|
const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
|
|
2719
|
-
if (sourcePath &&
|
|
2859
|
+
if (sourcePath && fs12.existsSync(sourcePath)) {
|
|
2720
2860
|
try {
|
|
2721
2861
|
await ensureCompiled(sourcePath, rootDir, dist);
|
|
2722
2862
|
} catch (compileErr) {
|
|
@@ -3471,9 +3611,9 @@ async function validateInput(schemaPath, method, inputType, input) {
|
|
|
3471
3611
|
function mapZodIssues(error) {
|
|
3472
3612
|
return error.issues.map((issue) => {
|
|
3473
3613
|
const code = mapZodCode(issue.code, issue.message);
|
|
3474
|
-
const
|
|
3614
|
+
const path19 = issue.path.map(String).join(".") || "";
|
|
3475
3615
|
return {
|
|
3476
|
-
path:
|
|
3616
|
+
path: path19,
|
|
3477
3617
|
code,
|
|
3478
3618
|
expected: issue.expected ?? mapExpectedFromMessage(issue.message),
|
|
3479
3619
|
received: issue.received ?? mapReceivedFromMessage(issue.message),
|
|
@@ -3535,9 +3675,9 @@ function getClientIp(req) {
|
|
|
3535
3675
|
}
|
|
3536
3676
|
|
|
3537
3677
|
// src/server/handleWsUpgrade.ts
|
|
3538
|
-
import
|
|
3678
|
+
import fs13 from "fs";
|
|
3539
3679
|
import { WebSocketServer, WebSocket } from "ws";
|
|
3540
|
-
import
|
|
3680
|
+
import path11 from "path";
|
|
3541
3681
|
|
|
3542
3682
|
// src/server/serverUtils.ts
|
|
3543
3683
|
function nodeHttpToWebHeaders(req) {
|
|
@@ -3663,7 +3803,7 @@ async function loadWsHandler(filePath, ctx, rootDir) {
|
|
|
3663
3803
|
const dist = getDevDist();
|
|
3664
3804
|
if (dist) {
|
|
3665
3805
|
const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
|
|
3666
|
-
if (sourcePath &&
|
|
3806
|
+
if (sourcePath && fs13.existsSync(sourcePath)) {
|
|
3667
3807
|
await ensureCompiled(sourcePath, rootDir, dist);
|
|
3668
3808
|
}
|
|
3669
3809
|
}
|
|
@@ -3743,7 +3883,7 @@ function attachWebSocket(options) {
|
|
|
3743
3883
|
const finalHandler = async () => {
|
|
3744
3884
|
let handlers;
|
|
3745
3885
|
try {
|
|
3746
|
-
const absoluteFilePath =
|
|
3886
|
+
const absoluteFilePath = path11.resolve(rootDir, route.filePath);
|
|
3747
3887
|
handlers = await loadWsHandler(absoluteFilePath, ctx, rootDir);
|
|
3748
3888
|
} catch (err) {
|
|
3749
3889
|
const reason = err instanceof Error ? err.message : String(err);
|
|
@@ -3868,15 +4008,15 @@ function limitStreamSize(stream, maxSize) {
|
|
|
3868
4008
|
}
|
|
3869
4009
|
});
|
|
3870
4010
|
}
|
|
3871
|
-
function findAllowedMethods(routes,
|
|
4011
|
+
function findAllowedMethods(routes, path19) {
|
|
3872
4012
|
const methods = /* @__PURE__ */ new Set();
|
|
3873
4013
|
for (const route of routes) {
|
|
3874
|
-
if (route.urlPath ===
|
|
4014
|
+
if (route.urlPath === path19) {
|
|
3875
4015
|
methods.add(route.method);
|
|
3876
4016
|
continue;
|
|
3877
4017
|
}
|
|
3878
4018
|
if (route.isDynamic) {
|
|
3879
|
-
const params = matchDynamicPath(route.urlPath,
|
|
4019
|
+
const params = matchDynamicPath(route.urlPath, path19, route.paramNames, route.isCatchAll);
|
|
3880
4020
|
if (params !== null) {
|
|
3881
4021
|
methods.add(route.method);
|
|
3882
4022
|
}
|
|
@@ -3968,7 +4108,7 @@ function createRoutePipeline(opts) {
|
|
|
3968
4108
|
const match = resolveRouteOrThrow(routes, method, urlPath);
|
|
3969
4109
|
ctx.params = match.params;
|
|
3970
4110
|
const { route } = match;
|
|
3971
|
-
const absoluteFilePath =
|
|
4111
|
+
const absoluteFilePath = path12.resolve(rootDir, route.filePath);
|
|
3972
4112
|
const routeModule = await loadRouteModule(absoluteFilePath, route.method, rootDir);
|
|
3973
4113
|
const input = await resolveInput(route.method, request);
|
|
3974
4114
|
const inputType = getInputTypeForMethod(route.method);
|
|
@@ -4065,8 +4205,8 @@ function applyPluginWrappers(server, handlerWrappers, upgradeWrappers) {
|
|
|
4065
4205
|
}
|
|
4066
4206
|
|
|
4067
4207
|
// src/cli/generateRoutes.ts
|
|
4068
|
-
import
|
|
4069
|
-
import
|
|
4208
|
+
import fs14 from "fs";
|
|
4209
|
+
import path13 from "path";
|
|
4070
4210
|
async function hydrateRoutes(manifest) {
|
|
4071
4211
|
const hydrateRoute = (serialized) => ({
|
|
4072
4212
|
method: serialized.method,
|
|
@@ -4091,8 +4231,8 @@ async function hydrateRoutes(manifest) {
|
|
|
4091
4231
|
}
|
|
4092
4232
|
|
|
4093
4233
|
// src/cli/generateAgentArtifacts.ts
|
|
4094
|
-
import
|
|
4095
|
-
import
|
|
4234
|
+
import path14 from "path";
|
|
4235
|
+
import fs15 from "fs/promises";
|
|
4096
4236
|
|
|
4097
4237
|
// src/ast/extractAgentMetadata.ts
|
|
4098
4238
|
import ts8 from "typescript";
|
|
@@ -4306,12 +4446,12 @@ function serializeAgents(agents, dist = "dist") {
|
|
|
4306
4446
|
}));
|
|
4307
4447
|
}
|
|
4308
4448
|
async function writeAgentsModule(manifest, outputPath) {
|
|
4309
|
-
const dir =
|
|
4310
|
-
await
|
|
4449
|
+
const dir = path14.dirname(outputPath);
|
|
4450
|
+
await fs15.mkdir(dir, { recursive: true });
|
|
4311
4451
|
const content = `// \u81EA\u52A8\u751F\u6210,\u8BF7\u52FF\u624B\u52A8\u7F16\u8F91(faapi build/dev \u4EA7\u7269)
|
|
4312
4452
|
export const agents = ${JSON.stringify(manifest, null, 2)};
|
|
4313
4453
|
`;
|
|
4314
|
-
await
|
|
4454
|
+
await fs15.writeFile(outputPath, content, "utf-8");
|
|
4315
4455
|
}
|
|
4316
4456
|
function hydrateAgents(manifest) {
|
|
4317
4457
|
return manifest.map((a) => ({
|
|
@@ -4329,7 +4469,7 @@ function hydrateAgents(manifest) {
|
|
|
4329
4469
|
async function generateAgentArtifacts(agents, rootDir, dist) {
|
|
4330
4470
|
const metadata = [];
|
|
4331
4471
|
for (const manifest of agents) {
|
|
4332
|
-
const absPath =
|
|
4472
|
+
const absPath = path14.resolve(rootDir, manifest.filePath);
|
|
4333
4473
|
const program = createProgram(absPath);
|
|
4334
4474
|
const result = extractAgentMetadata(program, absPath, {
|
|
4335
4475
|
name: manifest.name,
|
|
@@ -4341,7 +4481,7 @@ async function generateAgentArtifacts(agents, rootDir, dist) {
|
|
|
4341
4481
|
}
|
|
4342
4482
|
}
|
|
4343
4483
|
const serialized = serializeAgents(metadata, dist);
|
|
4344
|
-
const agentsPath =
|
|
4484
|
+
const agentsPath = path14.resolve(rootDir, dist, AGENTS_FILE);
|
|
4345
4485
|
await writeAgentsModule(serialized, agentsPath);
|
|
4346
4486
|
return metadata;
|
|
4347
4487
|
}
|
|
@@ -4413,8 +4553,8 @@ var TOOLS_FILE2 = "faapi-tools.js";
|
|
|
4413
4553
|
var AGENTS_FILE2 = "faapi-agents.js";
|
|
4414
4554
|
var PATTERNS = ["src/api/**/*.ts"];
|
|
4415
4555
|
async function loadAndHydrateTools(rootDir, dist) {
|
|
4416
|
-
const toolsPath =
|
|
4417
|
-
if (!
|
|
4556
|
+
const toolsPath = path15.resolve(rootDir, dist, TOOLS_FILE2);
|
|
4557
|
+
if (!fs16.existsSync(toolsPath)) {
|
|
4418
4558
|
return [];
|
|
4419
4559
|
}
|
|
4420
4560
|
const serialized = await importWithCacheBust(toolsPath);
|
|
@@ -4423,8 +4563,8 @@ async function loadAndHydrateTools(rootDir, dist) {
|
|
|
4423
4563
|
return hydrated;
|
|
4424
4564
|
}
|
|
4425
4565
|
async function loadAndHydrateAgents(rootDir, dist) {
|
|
4426
|
-
const agentsPath =
|
|
4427
|
-
if (!
|
|
4566
|
+
const agentsPath = path15.resolve(rootDir, dist, AGENTS_FILE2);
|
|
4567
|
+
if (!fs16.existsSync(agentsPath)) {
|
|
4428
4568
|
return [];
|
|
4429
4569
|
}
|
|
4430
4570
|
const serialized = await importWithCacheBust(agentsPath);
|
|
@@ -4471,8 +4611,8 @@ function isFaapiConfigKey(key) {
|
|
|
4471
4611
|
async function createAppBase(options) {
|
|
4472
4612
|
const rootDir = options?.rootDir ?? process.cwd();
|
|
4473
4613
|
const dist = options?.dist ?? process.env.FAAPI_DIST ?? DEFAULT_DIST;
|
|
4474
|
-
const routesPath =
|
|
4475
|
-
if (!
|
|
4614
|
+
const routesPath = path15.resolve(rootDir, dist, ROUTES_FILE);
|
|
4615
|
+
if (!fs16.existsSync(routesPath)) {
|
|
4476
4616
|
throw new Error(
|
|
4477
4617
|
`[faapi] ${dist}/${ROUTES_FILE} \u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u6267\u884C \`faapi build\`\uFF08\u6216 \`faapi dev\`\uFF09\u751F\u6210\u4EA7\u7269\u3002`
|
|
4478
4618
|
);
|
|
@@ -4693,17 +4833,17 @@ async function createAppBase(options) {
|
|
|
4693
4833
|
|
|
4694
4834
|
// src/router/scanRoutes.ts
|
|
4695
4835
|
import fg2 from "fast-glob";
|
|
4696
|
-
import
|
|
4697
|
-
import
|
|
4836
|
+
import path16 from "path";
|
|
4837
|
+
import fs17 from "fs";
|
|
4698
4838
|
|
|
4699
4839
|
// src/router/constants.ts
|
|
4700
4840
|
var HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
|
|
4701
4841
|
var HTTP_METHOD_SET = new Set(HTTP_METHODS);
|
|
4702
4842
|
|
|
4703
4843
|
// src/utils/normalizePath.ts
|
|
4704
|
-
function normalizePath(
|
|
4705
|
-
if (!
|
|
4706
|
-
let result =
|
|
4844
|
+
function normalizePath(path19) {
|
|
4845
|
+
if (!path19) return "";
|
|
4846
|
+
let result = path19.replace(/\\/g, "/");
|
|
4707
4847
|
result = result.replace(/\/+/g, "/");
|
|
4708
4848
|
result = result.replace(/\/+$/, "");
|
|
4709
4849
|
if (result && !result.startsWith("/")) {
|
|
@@ -4764,34 +4904,34 @@ function extractExportsFromSource(source) {
|
|
|
4764
4904
|
return names;
|
|
4765
4905
|
}
|
|
4766
4906
|
function collectMiddlewarePaths(routeFilePath, rootDir, dist) {
|
|
4767
|
-
const routeDir =
|
|
4768
|
-
const resolvedRoot =
|
|
4907
|
+
const routeDir = path16.dirname(routeFilePath);
|
|
4908
|
+
const resolvedRoot = path16.resolve(rootDir);
|
|
4769
4909
|
const paths = [];
|
|
4770
|
-
let currentDir =
|
|
4910
|
+
let currentDir = path16.resolve(rootDir, routeDir);
|
|
4771
4911
|
while (true) {
|
|
4772
4912
|
if (dist) {
|
|
4773
|
-
const mwTsPath =
|
|
4774
|
-
const mwJsPath =
|
|
4775
|
-
const absTsPath =
|
|
4776
|
-
const absJsPath =
|
|
4777
|
-
const absMwPath =
|
|
4913
|
+
const mwTsPath = path16.join(currentDir, "middlewares.ts");
|
|
4914
|
+
const mwJsPath = path16.join(currentDir, "middlewares.js");
|
|
4915
|
+
const absTsPath = path16.resolve(rootDir, mwTsPath);
|
|
4916
|
+
const absJsPath = path16.resolve(rootDir, mwJsPath);
|
|
4917
|
+
const absMwPath = fs17.existsSync(absTsPath) ? absTsPath : fs17.existsSync(absJsPath) ? absJsPath : null;
|
|
4778
4918
|
if (absMwPath) {
|
|
4779
|
-
const relMwPath =
|
|
4780
|
-
const prodAbsPath =
|
|
4919
|
+
const relMwPath = path16.relative(rootDir, absMwPath);
|
|
4920
|
+
const prodAbsPath = path16.resolve(rootDir, toProdFilePath3(relMwPath, dist));
|
|
4781
4921
|
paths.push(prodAbsPath);
|
|
4782
4922
|
}
|
|
4783
4923
|
} else {
|
|
4784
4924
|
for (const ext of [".ts", ".js"]) {
|
|
4785
|
-
const mwPath =
|
|
4786
|
-
const absMwPath =
|
|
4787
|
-
if (
|
|
4925
|
+
const mwPath = path16.join(currentDir, `middlewares${ext}`);
|
|
4926
|
+
const absMwPath = path16.resolve(rootDir, mwPath);
|
|
4927
|
+
if (fs17.existsSync(absMwPath)) {
|
|
4788
4928
|
paths.push(absMwPath);
|
|
4789
4929
|
break;
|
|
4790
4930
|
}
|
|
4791
4931
|
}
|
|
4792
4932
|
}
|
|
4793
4933
|
if (currentDir === resolvedRoot) break;
|
|
4794
|
-
const parentDir =
|
|
4934
|
+
const parentDir = path16.dirname(currentDir);
|
|
4795
4935
|
if (parentDir === currentDir) break;
|
|
4796
4936
|
currentDir = parentDir;
|
|
4797
4937
|
}
|
|
@@ -4818,7 +4958,7 @@ async function scanRoutes(rootDir, patterns, dist) {
|
|
|
4818
4958
|
const normalizedFile = file.replace(/\\/g, "/");
|
|
4819
4959
|
const fileName = normalizedFile.split("/").pop();
|
|
4820
4960
|
if (fileName === "handler.ts" || fileName === "handler.js") {
|
|
4821
|
-
const absPath =
|
|
4961
|
+
const absPath = path16.resolve(rootDir, normalizedFile);
|
|
4822
4962
|
const urlPath = filePathToUrlPath(normalizedFile);
|
|
4823
4963
|
const paramNames = extractParamNames(urlPath);
|
|
4824
4964
|
const isDynamic = paramNames.length > 0;
|
|
@@ -4831,7 +4971,7 @@ async function scanRoutes(rootDir, patterns, dist) {
|
|
|
4831
4971
|
const mwPaths = collectMiddlewarePaths(normalizedFile, rootDir);
|
|
4832
4972
|
middlewareBundle = await loadMergedMiddlewares(mwPaths);
|
|
4833
4973
|
}
|
|
4834
|
-
const source = await
|
|
4974
|
+
const source = await fs17.promises.readFile(absPath, "utf8").catch(() => "");
|
|
4835
4975
|
const exportNames = extractExportsFromSource(source);
|
|
4836
4976
|
const methods = HTTP_METHODS.filter((m) => exportNames.has(m));
|
|
4837
4977
|
for (const method of methods) {
|
|
@@ -4867,8 +5007,8 @@ async function scanRoutes(rootDir, patterns, dist) {
|
|
|
4867
5007
|
|
|
4868
5008
|
// src/tools/scanTools.ts
|
|
4869
5009
|
import fg3 from "fast-glob";
|
|
4870
|
-
import
|
|
4871
|
-
import
|
|
5010
|
+
import path17 from "path";
|
|
5011
|
+
import fs18 from "fs";
|
|
4872
5012
|
var TOOL_PATTERNS = ["src/tools/**/*.ts"];
|
|
4873
5013
|
var TOOL_EXPORT_RE = new RegExp(
|
|
4874
5014
|
String.raw`export\s+(?:async\s+)?(?:function\s+|const\s+)([A-Za-z_$][\w$]*)\s*(?:\(|=)`,
|
|
@@ -4918,8 +5058,8 @@ async function scanTools(rootDir, patterns) {
|
|
|
4918
5058
|
if (fileName !== "handler.ts" && fileName !== "handler.js") {
|
|
4919
5059
|
continue;
|
|
4920
5060
|
}
|
|
4921
|
-
const absPath =
|
|
4922
|
-
const source = await
|
|
5061
|
+
const absPath = path17.resolve(rootDir, normalizedFile);
|
|
5062
|
+
const source = await fs18.promises.readFile(absPath, "utf8").catch(() => "");
|
|
4923
5063
|
const exportNames = extractToolExportsFromSource(source);
|
|
4924
5064
|
const namespace = filePathToToolNamespace(normalizedFile);
|
|
4925
5065
|
for (const fnName of exportNames) {
|
|
@@ -4943,8 +5083,8 @@ async function scanTools(rootDir, patterns) {
|
|
|
4943
5083
|
|
|
4944
5084
|
// src/agents/scanAgents.ts
|
|
4945
5085
|
import fg4 from "fast-glob";
|
|
4946
|
-
import
|
|
4947
|
-
import
|
|
5086
|
+
import path18 from "path";
|
|
5087
|
+
import fs19 from "fs";
|
|
4948
5088
|
var DEFAULT_AGENT_PATTERNS = ["src/agents/*/handler.ts"];
|
|
4949
5089
|
var RUN_EXPORT_RE = /export\s+(?:async\s+)?(?:function\s+|const\s+)run\b/;
|
|
4950
5090
|
function extractAgentNameFromPath(filePath) {
|
|
@@ -4976,8 +5116,8 @@ async function scanAgents(rootDir, patterns) {
|
|
|
4976
5116
|
if (fileName !== "handler.ts" && fileName !== "handler.js") {
|
|
4977
5117
|
continue;
|
|
4978
5118
|
}
|
|
4979
|
-
const absPath =
|
|
4980
|
-
const source = await
|
|
5119
|
+
const absPath = path18.resolve(rootDir, normalizedFile);
|
|
5120
|
+
const source = await fs19.promises.readFile(absPath, "utf8").catch(() => "");
|
|
4981
5121
|
const { hasRun } = detectAgentExports(source);
|
|
4982
5122
|
const name = extractAgentNameFromPath(normalizedFile);
|
|
4983
5123
|
const prevFile = seen.get(name);
|