@faapi/faapi 6.23.0 → 6.24.0
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 +364 -333
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +13 -51
- package/dist/index.js +118 -127
- package/dist/index.js.map +1 -1
- package/dist/{routeTypes-CJV5M90s.d.ts → routeTypes-D1swYDVC.d.ts} +41 -19
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2046,14 +2046,14 @@ var ValidationError = class extends FaapiError {
|
|
|
2046
2046
|
issues;
|
|
2047
2047
|
};
|
|
2048
2048
|
var RouteNotFoundError = class extends FaapiError {
|
|
2049
|
-
constructor(
|
|
2050
|
-
super("ROUTE_NOT_FOUND", `Route not found: ${
|
|
2049
|
+
constructor(path31) {
|
|
2050
|
+
super("ROUTE_NOT_FOUND", `Route not found: ${path31}`, 404);
|
|
2051
2051
|
this.name = "RouteNotFoundError";
|
|
2052
2052
|
}
|
|
2053
2053
|
};
|
|
2054
2054
|
var MethodNotAllowedError = class extends FaapiError {
|
|
2055
|
-
constructor(method,
|
|
2056
|
-
super("METHOD_NOT_ALLOWED", `Method ${method} not allowed for ${
|
|
2055
|
+
constructor(method, path31, allowedMethods) {
|
|
2056
|
+
super("METHOD_NOT_ALLOWED", `Method ${method} not allowed for ${path31}`, 405);
|
|
2057
2057
|
this.allowedMethods = allowedMethods;
|
|
2058
2058
|
this.name = "MethodNotAllowedError";
|
|
2059
2059
|
}
|
|
@@ -2362,7 +2362,11 @@ async function runTaskInWorker(options) {
|
|
|
2362
2362
|
worker.postMessage({
|
|
2363
2363
|
type: "run",
|
|
2364
2364
|
payload,
|
|
2365
|
-
taskCtx: {
|
|
2365
|
+
taskCtx: {
|
|
2366
|
+
config: safeConfig(taskCtx.config),
|
|
2367
|
+
resourcesDir: taskCtx.resourcesDir,
|
|
2368
|
+
job: taskCtx.job
|
|
2369
|
+
},
|
|
2366
2370
|
registries: options.registries,
|
|
2367
2371
|
log: options.log
|
|
2368
2372
|
});
|
|
@@ -2712,6 +2716,7 @@ function createTaskQueue(deps) {
|
|
|
2712
2716
|
payload: job.payload,
|
|
2713
2717
|
taskCtx: {
|
|
2714
2718
|
config: deps.config,
|
|
2719
|
+
resourcesDir: deps.resourcesDir,
|
|
2715
2720
|
job: { id: job.id, name: job.name, attempt: job.attempt }
|
|
2716
2721
|
},
|
|
2717
2722
|
registries: snapshotRegistries(),
|
|
@@ -2742,6 +2747,7 @@ function createTaskQueue(deps) {
|
|
|
2742
2747
|
const taskCtx = {
|
|
2743
2748
|
signal: job.signal,
|
|
2744
2749
|
config: deps.config,
|
|
2750
|
+
resourcesDir: deps.resourcesDir,
|
|
2745
2751
|
job: { id: job.id, name: job.name, attempt: job.attempt },
|
|
2746
2752
|
registries: registriesView,
|
|
2747
2753
|
log: createLogger(`task:${job.name}`, {
|
|
@@ -3086,7 +3092,7 @@ function listSkills() {
|
|
|
3086
3092
|
return defaultRegistries.skill.list();
|
|
3087
3093
|
}
|
|
3088
3094
|
|
|
3089
|
-
// src/loader/
|
|
3095
|
+
// src/loader/loadToolModule.ts
|
|
3090
3096
|
import fs12 from "fs";
|
|
3091
3097
|
|
|
3092
3098
|
// src/loader/resolveExports.ts
|
|
@@ -3737,52 +3743,13 @@ function getDevDist() {
|
|
|
3737
3743
|
return state.distDir;
|
|
3738
3744
|
}
|
|
3739
3745
|
|
|
3740
|
-
// src/loader/loadAgentModule.ts
|
|
3741
|
-
async function loadAgentModule(filePath, hasRun, rootDir) {
|
|
3742
|
-
if (isDevOnDemandEnabled() && rootDir) {
|
|
3743
|
-
const dist = getDevDist();
|
|
3744
|
-
if (dist) {
|
|
3745
|
-
const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
|
|
3746
|
-
if (sourcePath && fs12.existsSync(sourcePath)) {
|
|
3747
|
-
try {
|
|
3748
|
-
await ensureCompiled(sourcePath, rootDir, dist);
|
|
3749
|
-
} catch (compileErr) {
|
|
3750
|
-
const reason = compileErr instanceof Error ? compileErr.message : String(compileErr);
|
|
3751
|
-
throw new Error(`Failed to compile agent module "${sourcePath}": ${reason}`, {
|
|
3752
|
-
cause: compileErr
|
|
3753
|
-
});
|
|
3754
|
-
}
|
|
3755
|
-
}
|
|
3756
|
-
}
|
|
3757
|
-
}
|
|
3758
|
-
let module;
|
|
3759
|
-
try {
|
|
3760
|
-
module = await importWithCacheBust(filePath, isDevOnDemandEnabled());
|
|
3761
|
-
} catch (err) {
|
|
3762
|
-
const reason = err instanceof Error ? err.message : String(err);
|
|
3763
|
-
throw new Error(`Failed to load agent module "${filePath}": ${reason}`, { cause: err });
|
|
3764
|
-
}
|
|
3765
|
-
let run;
|
|
3766
|
-
if (hasRun) {
|
|
3767
|
-
const runExport = resolveExport(module, "run");
|
|
3768
|
-
if (typeof runExport !== "function") {
|
|
3769
|
-
throw new Error(
|
|
3770
|
-
`Agent module "${filePath}" does not export a valid "run" function (hasRun=true). Expected a function, got ${runExport === void 0 ? "undefined" : typeof runExport}.`
|
|
3771
|
-
);
|
|
3772
|
-
}
|
|
3773
|
-
run = runExport;
|
|
3774
|
-
}
|
|
3775
|
-
return { run };
|
|
3776
|
-
}
|
|
3777
|
-
|
|
3778
3746
|
// src/loader/loadToolModule.ts
|
|
3779
|
-
import fs13 from "fs";
|
|
3780
3747
|
async function loadToolModule(filePath, functionName, rootDir) {
|
|
3781
3748
|
if (isDevOnDemandEnabled() && rootDir) {
|
|
3782
3749
|
const dist = getDevDist();
|
|
3783
3750
|
if (dist) {
|
|
3784
3751
|
const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
|
|
3785
|
-
if (sourcePath &&
|
|
3752
|
+
if (sourcePath && fs12.existsSync(sourcePath)) {
|
|
3786
3753
|
try {
|
|
3787
3754
|
await ensureCompiled(sourcePath, rootDir, dist);
|
|
3788
3755
|
} catch (compileErr) {
|
|
@@ -4254,15 +4221,15 @@ function helmet(options = {}) {
|
|
|
4254
4221
|
|
|
4255
4222
|
// src/config/loadConfig.ts
|
|
4256
4223
|
import path16 from "path";
|
|
4257
|
-
import
|
|
4224
|
+
import fs13 from "fs";
|
|
4258
4225
|
var CONFIG_PRODUCT_FILE = "faapi-config.js";
|
|
4259
4226
|
async function loadConfig(rootDir, dist) {
|
|
4260
4227
|
const configProductPath = path16.resolve(rootDir, dist, CONFIG_PRODUCT_FILE);
|
|
4261
|
-
if (
|
|
4228
|
+
if (fs13.existsSync(configProductPath)) {
|
|
4262
4229
|
const module = await importWithCacheBust(configProductPath);
|
|
4263
4230
|
return module.default ?? {};
|
|
4264
4231
|
}
|
|
4265
|
-
const hasSourceConfig =
|
|
4232
|
+
const hasSourceConfig = fs13.existsSync(path16.join(rootDir, "faapi.config.ts")) || fs13.existsSync(path16.join(rootDir, "faapi.config.js"));
|
|
4266
4233
|
if (hasSourceConfig) {
|
|
4267
4234
|
throw new Error(
|
|
4268
4235
|
`[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`
|
|
@@ -4272,7 +4239,7 @@ async function loadConfig(rootDir, dist) {
|
|
|
4272
4239
|
}
|
|
4273
4240
|
|
|
4274
4241
|
// src/cli/loadEnv.ts
|
|
4275
|
-
import
|
|
4242
|
+
import fs14 from "fs";
|
|
4276
4243
|
import path17 from "path";
|
|
4277
4244
|
function resolveEnv() {
|
|
4278
4245
|
return process.env.NODE_ENV || "development";
|
|
@@ -4341,8 +4308,8 @@ function loadEnv(rootDir) {
|
|
|
4341
4308
|
const merged = {};
|
|
4342
4309
|
for (const file of files) {
|
|
4343
4310
|
const filePath = path17.join(rootDir, file);
|
|
4344
|
-
if (!
|
|
4345
|
-
const content =
|
|
4311
|
+
if (!fs14.existsSync(filePath)) continue;
|
|
4312
|
+
const content = fs14.readFileSync(filePath, "utf-8");
|
|
4346
4313
|
const parsed = parseEnvFile(content, merged);
|
|
4347
4314
|
Object.assign(merged, parsed);
|
|
4348
4315
|
}
|
|
@@ -4354,7 +4321,7 @@ function loadEnv(rootDir) {
|
|
|
4354
4321
|
}
|
|
4355
4322
|
|
|
4356
4323
|
// src/cli/createAppCore.ts
|
|
4357
|
-
import
|
|
4324
|
+
import fs21 from "fs";
|
|
4358
4325
|
import path27 from "path";
|
|
4359
4326
|
|
|
4360
4327
|
// src/router/sortRoutes.ts
|
|
@@ -4461,25 +4428,25 @@ function getWsIndex(routes) {
|
|
|
4461
4428
|
wsIndexCache.set(routes, index);
|
|
4462
4429
|
return index;
|
|
4463
4430
|
}
|
|
4464
|
-
function matchRoute(routes, method,
|
|
4431
|
+
function matchRoute(routes, method, path31) {
|
|
4465
4432
|
const index = getHttpIndex(routes);
|
|
4466
4433
|
const upper = method.toUpperCase();
|
|
4467
|
-
const hit = matchByMethod(index, upper,
|
|
4434
|
+
const hit = matchByMethod(index, upper, path31);
|
|
4468
4435
|
if (hit) return hit;
|
|
4469
4436
|
if (upper === "HEAD") {
|
|
4470
|
-
return matchByMethod(index, "GET",
|
|
4437
|
+
return matchByMethod(index, "GET", path31);
|
|
4471
4438
|
}
|
|
4472
4439
|
return null;
|
|
4473
4440
|
}
|
|
4474
|
-
function matchByMethod(index, method,
|
|
4475
|
-
const staticHit = index.static.get(`${method}|${
|
|
4441
|
+
function matchByMethod(index, method, path31) {
|
|
4442
|
+
const staticHit = index.static.get(`${method}|${path31}`);
|
|
4476
4443
|
if (staticHit) {
|
|
4477
4444
|
return { route: staticHit, params: {} };
|
|
4478
4445
|
}
|
|
4479
4446
|
if (index.dynamics.length === 0) {
|
|
4480
4447
|
return null;
|
|
4481
4448
|
}
|
|
4482
|
-
const pathSegments =
|
|
4449
|
+
const pathSegments = path31.split("/").filter(Boolean);
|
|
4483
4450
|
for (const entry of index.dynamics) {
|
|
4484
4451
|
const route = entry.route;
|
|
4485
4452
|
if (route.method !== method) {
|
|
@@ -4492,31 +4459,31 @@ function matchByMethod(index, method, path32) {
|
|
|
4492
4459
|
}
|
|
4493
4460
|
return null;
|
|
4494
4461
|
}
|
|
4495
|
-
function matchWsRoute(wsRoutes,
|
|
4462
|
+
function matchWsRoute(wsRoutes, path31) {
|
|
4496
4463
|
const index = getWsIndex(wsRoutes);
|
|
4497
|
-
const staticHit = index.static.get(
|
|
4464
|
+
const staticHit = index.static.get(path31);
|
|
4498
4465
|
if (staticHit) {
|
|
4499
4466
|
return { route: staticHit, params: {} };
|
|
4500
4467
|
}
|
|
4501
4468
|
for (const route of index.dynamics) {
|
|
4502
|
-
const params = matchDynamicPath(route.urlPath,
|
|
4469
|
+
const params = matchDynamicPath(route.urlPath, path31, route.paramNames, route.isCatchAll);
|
|
4503
4470
|
if (params !== null) {
|
|
4504
4471
|
return { route, params };
|
|
4505
4472
|
}
|
|
4506
4473
|
}
|
|
4507
4474
|
return null;
|
|
4508
4475
|
}
|
|
4509
|
-
function findAllowedMethods(routes,
|
|
4476
|
+
function findAllowedMethods(routes, path31) {
|
|
4510
4477
|
const index = getHttpIndex(routes);
|
|
4511
4478
|
const methods = /* @__PURE__ */ new Set();
|
|
4512
|
-
const staticMethods = index.methodsByStaticPath.get(
|
|
4479
|
+
const staticMethods = index.methodsByStaticPath.get(path31);
|
|
4513
4480
|
if (staticMethods) {
|
|
4514
4481
|
for (const method of staticMethods) {
|
|
4515
4482
|
methods.add(method);
|
|
4516
4483
|
}
|
|
4517
4484
|
}
|
|
4518
4485
|
if (index.dynamics.length > 0) {
|
|
4519
|
-
const pathSegments =
|
|
4486
|
+
const pathSegments = path31.split("/").filter(Boolean);
|
|
4520
4487
|
for (const entry of index.dynamics) {
|
|
4521
4488
|
const params = matchSegments(
|
|
4522
4489
|
entry.segments,
|
|
@@ -4534,10 +4501,10 @@ function findAllowedMethods(routes, path32) {
|
|
|
4534
4501
|
}
|
|
4535
4502
|
return Array.from(methods);
|
|
4536
4503
|
}
|
|
4537
|
-
function matchDynamicPath(pattern,
|
|
4504
|
+
function matchDynamicPath(pattern, path31, paramNames, isCatchAll) {
|
|
4538
4505
|
return matchSegments(
|
|
4539
4506
|
pattern.split("/").filter(Boolean),
|
|
4540
|
-
|
|
4507
|
+
path31.split("/").filter(Boolean),
|
|
4541
4508
|
paramNames,
|
|
4542
4509
|
isCatchAll
|
|
4543
4510
|
);
|
|
@@ -5676,9 +5643,9 @@ async function validateInput(schemaPath, method, inputType, input) {
|
|
|
5676
5643
|
function mapZodIssues(error) {
|
|
5677
5644
|
return error.issues.map((issue) => {
|
|
5678
5645
|
const code = mapZodCode(issue);
|
|
5679
|
-
const
|
|
5646
|
+
const path31 = issue.path.map(String).join(".") || "";
|
|
5680
5647
|
return {
|
|
5681
|
-
path:
|
|
5648
|
+
path: path31,
|
|
5682
5649
|
code,
|
|
5683
5650
|
expected: issue.expected ?? mapExpectedFromMessage(issue.message),
|
|
5684
5651
|
received: issue.received ?? mapReceivedFromMessage(issue.message),
|
|
@@ -5899,13 +5866,13 @@ function etag(options = {}) {
|
|
|
5899
5866
|
}
|
|
5900
5867
|
|
|
5901
5868
|
// src/server/handleWsUpgrade.ts
|
|
5902
|
-
import
|
|
5869
|
+
import fs16 from "fs";
|
|
5903
5870
|
import { WebSocketServer, WebSocket } from "ws";
|
|
5904
5871
|
import path19 from "path";
|
|
5905
5872
|
|
|
5906
5873
|
// src/cli/copyResources.ts
|
|
5907
5874
|
import path18 from "path";
|
|
5908
|
-
import
|
|
5875
|
+
import fs15 from "fs";
|
|
5909
5876
|
var RESOURCES_OUTPUT_DIR = "resources";
|
|
5910
5877
|
function resolveResourcesDir(rootDir, dist) {
|
|
5911
5878
|
return path18.resolve(rootDir, dist, RESOURCES_OUTPUT_DIR);
|
|
@@ -6049,7 +6016,7 @@ async function loadWsHandler(filePath, ctx, rootDir) {
|
|
|
6049
6016
|
const dist = getDevDist();
|
|
6050
6017
|
if (dist) {
|
|
6051
6018
|
const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
|
|
6052
|
-
if (sourcePath &&
|
|
6019
|
+
if (sourcePath && fs16.existsSync(sourcePath)) {
|
|
6053
6020
|
await ensureCompiled(sourcePath, rootDir, dist);
|
|
6054
6021
|
}
|
|
6055
6022
|
}
|
|
@@ -6191,7 +6158,7 @@ function attachWebSocket(options) {
|
|
|
6191
6158
|
let upgraded = false;
|
|
6192
6159
|
const finalHandler = async () => {
|
|
6193
6160
|
const schemaPath = getRuntimeSchemaPath(route.filePath, dist, rootDir);
|
|
6194
|
-
if (
|
|
6161
|
+
if (fs16.existsSync(schemaPath)) {
|
|
6195
6162
|
if (isDevOnDemandEnabled()) {
|
|
6196
6163
|
const devDist = getDevDist();
|
|
6197
6164
|
if (devDist) {
|
|
@@ -6713,7 +6680,7 @@ function applyPluginWrappers(server, handlerWrappers, upgradeWrappers) {
|
|
|
6713
6680
|
}
|
|
6714
6681
|
|
|
6715
6682
|
// src/cli/generateRoutes.ts
|
|
6716
|
-
import
|
|
6683
|
+
import fs17 from "fs";
|
|
6717
6684
|
import path21 from "path";
|
|
6718
6685
|
async function hydrateRoutes(manifest) {
|
|
6719
6686
|
const hydrateRoute = (serialized) => ({
|
|
@@ -6759,12 +6726,12 @@ function createIdleTaskDriver() {
|
|
|
6759
6726
|
|
|
6760
6727
|
// src/cli/loadPlugins.ts
|
|
6761
6728
|
import path23 from "path";
|
|
6762
|
-
import
|
|
6729
|
+
import fs19 from "fs";
|
|
6763
6730
|
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
6764
6731
|
|
|
6765
6732
|
// src/cli/compileConfig.ts
|
|
6766
6733
|
import path22 from "path";
|
|
6767
|
-
import
|
|
6734
|
+
import fs18 from "fs";
|
|
6768
6735
|
async function compileProjectModules(entryPoints, rootDir, dist) {
|
|
6769
6736
|
const { insideFiles, outsideFiles } = await collectRelativeImports(entryPoints, rootDir);
|
|
6770
6737
|
const esbuild = await import("esbuild");
|
|
@@ -6865,12 +6832,12 @@ var TS_EXTS = /\.(ts|tsx|mts|cts)$/;
|
|
|
6865
6832
|
var JS_EXTS = /\.(js|mjs|cjs|jsx)$/;
|
|
6866
6833
|
function resolveLocalPluginSource(specifier, baseDir) {
|
|
6867
6834
|
const base = path23.isAbsolute(specifier) ? specifier : path23.resolve(baseDir, specifier);
|
|
6868
|
-
if ((TS_EXTS.test(base) || JS_EXTS.test(base)) &&
|
|
6835
|
+
if ((TS_EXTS.test(base) || JS_EXTS.test(base)) && fs19.existsSync(base)) return base;
|
|
6869
6836
|
for (const ext of [".ts", ".js"]) {
|
|
6870
|
-
if (
|
|
6837
|
+
if (fs19.existsSync(base + ext)) return base + ext;
|
|
6871
6838
|
}
|
|
6872
6839
|
for (const indexExt of ["/index.ts", "/index.js"]) {
|
|
6873
|
-
if (
|
|
6840
|
+
if (fs19.existsSync(base + indexExt)) return base + indexExt;
|
|
6874
6841
|
}
|
|
6875
6842
|
return null;
|
|
6876
6843
|
}
|
|
@@ -6887,7 +6854,7 @@ async function importPluginModule(specifier, baseDir, dist) {
|
|
|
6887
6854
|
const distDir = dist ? path23.resolve(baseDir, dist) : null;
|
|
6888
6855
|
const sourcePath = resolveLocalPluginSource(specifier, baseDir);
|
|
6889
6856
|
const productPath = sourcePath && distDir ? mirrorProductPath(sourcePath, baseDir, distDir) : null;
|
|
6890
|
-
if (productPath !== null &&
|
|
6857
|
+
if (productPath !== null && fs19.existsSync(productPath) && (sourcePath === null || isProductFresh(sourcePath, productPath))) {
|
|
6891
6858
|
return import(pathToFileURL3(productPath).href);
|
|
6892
6859
|
}
|
|
6893
6860
|
if (sourcePath && TS_EXTS.test(sourcePath)) {
|
|
@@ -6902,7 +6869,7 @@ async function importPluginModule(specifier, baseDir, dist) {
|
|
|
6902
6869
|
} else {
|
|
6903
6870
|
await compileProjectModules([sourcePath], baseDir, dist);
|
|
6904
6871
|
}
|
|
6905
|
-
if (productPath &&
|
|
6872
|
+
if (productPath && fs19.existsSync(productPath)) {
|
|
6906
6873
|
return import(pathToFileURL3(productPath).href);
|
|
6907
6874
|
}
|
|
6908
6875
|
}
|
|
@@ -6939,7 +6906,7 @@ function resolveDeclaration(decl) {
|
|
|
6939
6906
|
}
|
|
6940
6907
|
|
|
6941
6908
|
// src/cli/manifestLoader.ts
|
|
6942
|
-
import
|
|
6909
|
+
import fs20 from "fs";
|
|
6943
6910
|
import path26 from "path";
|
|
6944
6911
|
|
|
6945
6912
|
// src/cli/generateAgentArtifacts.ts
|
|
@@ -6951,12 +6918,21 @@ init_resolveTypeNode();
|
|
|
6951
6918
|
function extractAgentMetadata(program, filePath, pathMeta) {
|
|
6952
6919
|
const sourceFile = program.getSourceFile(filePath);
|
|
6953
6920
|
if (!sourceFile) return null;
|
|
6921
|
+
const runOwner = findRunExportOwner(sourceFile);
|
|
6922
|
+
if (runOwner) {
|
|
6923
|
+
throw SchemaExtractionError.at(
|
|
6924
|
+
runOwner,
|
|
6925
|
+
"run",
|
|
6926
|
+
"agent \u81EA\u5B9A\u4E49 run \u5DF2\u79FB\u9664\u2014\u2014agent \u7EDF\u4E00\u4E3A\u58F0\u660E\u5F0F\u6267\u884C\uFF08config + \u9ED8\u8BA4 reactLoop\uFF09\u3002\u7F16\u6392\u573A\u666F\u8BF7\u6CE8\u518C tool\uFF08src/tools/ \u4E0B\u5BFC\u51FA\u51FD\u6570\uFF0C\u6709 schema/trace/\u9274\u6743\u94A9\u5B50\uFF09\uFF0C\u591A agent \u534F\u4F5C\u7528 config.agents \u58F0\u660E sub-agent",
|
|
6927
|
+
sourceFile
|
|
6928
|
+
);
|
|
6929
|
+
}
|
|
6954
6930
|
const configFound = findConfigExport(sourceFile);
|
|
6955
6931
|
if (!configFound) {
|
|
6956
6932
|
throw SchemaExtractionError.at(
|
|
6957
6933
|
sourceFile,
|
|
6958
6934
|
"config.systemPrompt",
|
|
6959
|
-
"agent \u5FC5\u586B\u2014\u2014\u8BF7\u5728 config \u5757\u58F0\u660E\
|
|
6935
|
+
"agent \u5FC5\u586B\u2014\u2014\u8BF7\u5728 config \u5757\u58F0\u660E systemPrompt\uFF08\u5B57\u7B26\u4E32\u5B57\u9762\u91CF\u3001\u65E0\u63D2\u503C\u6A21\u677F\u5B57\u7B26\u4E32\u6216\u5176 + \u62FC\u63A5\uFF09\u6216 systemPromptFile\uFF08\u76F8\u5BF9 resources \u76EE\u5F55\u7684\u8DEF\u5F84\u5B57\u9762\u91CF\uFF09\u4E8C\u9009\u4E00",
|
|
6960
6936
|
sourceFile
|
|
6961
6937
|
);
|
|
6962
6938
|
}
|
|
@@ -6972,16 +6948,13 @@ function extractAgentMetadata(program, filePath, pathMeta) {
|
|
|
6972
6948
|
const jsDoc = getJSDocFromNode(configFound.jsDocOwner);
|
|
6973
6949
|
const description = extractDescription(jsDoc);
|
|
6974
6950
|
const agentNameOverride = extractJSDocTagValue(jsDoc, "agent");
|
|
6975
|
-
const { systemPrompt, tools, agents, model, maxTurns, inputDescription } = extractConfigFields(
|
|
6976
|
-
objectLiteral,
|
|
6977
|
-
sourceFile
|
|
6978
|
-
);
|
|
6951
|
+
const { systemPrompt, systemPromptFile, tools, agents, model, maxTurns, inputDescription } = extractConfigFields(objectLiteral, sourceFile);
|
|
6979
6952
|
return {
|
|
6980
6953
|
name: agentNameOverride ?? pathMeta.name,
|
|
6981
6954
|
description,
|
|
6982
6955
|
filePath: pathMeta.filePath,
|
|
6983
|
-
hasRun: pathMeta.hasRun,
|
|
6984
6956
|
systemPrompt,
|
|
6957
|
+
systemPromptFile,
|
|
6985
6958
|
tools,
|
|
6986
6959
|
agents,
|
|
6987
6960
|
model,
|
|
@@ -6989,6 +6962,25 @@ function extractAgentMetadata(program, filePath, pathMeta) {
|
|
|
6989
6962
|
inputDescription
|
|
6990
6963
|
};
|
|
6991
6964
|
}
|
|
6965
|
+
function findRunExportOwner(sourceFile) {
|
|
6966
|
+
let result = null;
|
|
6967
|
+
ts11.forEachChild(sourceFile, (node) => {
|
|
6968
|
+
if (result) return;
|
|
6969
|
+
if (ts11.isFunctionDeclaration(node) && hasExportModifier(node) && node.name?.text === "run") {
|
|
6970
|
+
result = node;
|
|
6971
|
+
return;
|
|
6972
|
+
}
|
|
6973
|
+
if (ts11.isVariableStatement(node) && hasExportModifier(node)) {
|
|
6974
|
+
for (const decl of node.declarationList.declarations) {
|
|
6975
|
+
if (ts11.isIdentifier(decl.name) && decl.name.text === "run") {
|
|
6976
|
+
result = node;
|
|
6977
|
+
return;
|
|
6978
|
+
}
|
|
6979
|
+
}
|
|
6980
|
+
}
|
|
6981
|
+
});
|
|
6982
|
+
return result;
|
|
6983
|
+
}
|
|
6992
6984
|
function findConfigExport(sourceFile) {
|
|
6993
6985
|
let result = null;
|
|
6994
6986
|
ts11.forEachChild(sourceFile, (node) => {
|
|
@@ -7031,6 +7023,7 @@ function getReturnObjectLiteral(fn) {
|
|
|
7031
7023
|
}
|
|
7032
7024
|
function extractConfigFields(objLit, sourceFile) {
|
|
7033
7025
|
let systemPrompt;
|
|
7026
|
+
let systemPromptFile;
|
|
7034
7027
|
let tools;
|
|
7035
7028
|
let agents;
|
|
7036
7029
|
let model;
|
|
@@ -7054,6 +7047,9 @@ function extractConfigFields(objLit, sourceFile) {
|
|
|
7054
7047
|
case "systemPrompt":
|
|
7055
7048
|
systemPrompt = requireStringValue(prop, "systemPrompt", sourceFile);
|
|
7056
7049
|
break;
|
|
7050
|
+
case "systemPromptFile":
|
|
7051
|
+
systemPromptFile = requireStringValue(prop, "systemPromptFile", sourceFile);
|
|
7052
|
+
break;
|
|
7057
7053
|
case "tools":
|
|
7058
7054
|
tools = requireStringArrayValue(prop, "tools", sourceFile);
|
|
7059
7055
|
break;
|
|
@@ -7073,20 +7069,28 @@ function extractConfigFields(objLit, sourceFile) {
|
|
|
7073
7069
|
throw SchemaExtractionError.at(
|
|
7074
7070
|
prop,
|
|
7075
7071
|
`config.${propName}`,
|
|
7076
|
-
"\u672A\u77E5 config \u5B57\u6BB5\u2014\u2014\u4EC5\u652F\u6301 systemPrompt / tools / agents / model / maxTurns / inputDescription",
|
|
7072
|
+
"\u672A\u77E5 config \u5B57\u6BB5\u2014\u2014\u4EC5\u652F\u6301 systemPrompt / systemPromptFile / tools / agents / model / maxTurns / inputDescription",
|
|
7077
7073
|
sourceFile
|
|
7078
7074
|
);
|
|
7079
7075
|
}
|
|
7080
7076
|
}
|
|
7081
|
-
if (systemPrompt
|
|
7077
|
+
if (systemPrompt !== void 0 && systemPromptFile !== void 0) {
|
|
7078
|
+
throw SchemaExtractionError.at(
|
|
7079
|
+
objLit,
|
|
7080
|
+
"config.systemPrompt",
|
|
7081
|
+
"systemPrompt \u4E0E systemPromptFile \u4E92\u65A5\u2014\u2014\u5185\u8054\u7CFB\u7EDF\u63D0\u793A\u8BCD\u4E0E resources \u6587\u4EF6\u4E8C\u9009\u4E00",
|
|
7082
|
+
sourceFile
|
|
7083
|
+
);
|
|
7084
|
+
}
|
|
7085
|
+
if (systemPrompt === void 0 && systemPromptFile === void 0) {
|
|
7082
7086
|
throw SchemaExtractionError.at(
|
|
7083
7087
|
objLit,
|
|
7084
7088
|
"config.systemPrompt",
|
|
7085
|
-
"agent \u5FC5\u586B\u2014\u2014\u8BF7\u5728 config \u5757\u58F0\u660E\
|
|
7089
|
+
"agent \u5FC5\u586B\u2014\u2014\u8BF7\u5728 config \u5757\u58F0\u660E systemPrompt\uFF08\u5B57\u7B26\u4E32\u5B57\u9762\u91CF\u3001\u65E0\u63D2\u503C\u6A21\u677F\u5B57\u7B26\u4E32\u6216\u5176 + \u62FC\u63A5\uFF09\u6216 systemPromptFile\uFF08\u76F8\u5BF9 resources \u76EE\u5F55\u7684\u8DEF\u5F84\u5B57\u9762\u91CF\uFF09\u4E8C\u9009\u4E00",
|
|
7086
7090
|
sourceFile
|
|
7087
7091
|
);
|
|
7088
7092
|
}
|
|
7089
|
-
return { systemPrompt, tools, agents, model, maxTurns, inputDescription };
|
|
7093
|
+
return { systemPrompt, systemPromptFile, tools, agents, model, maxTurns, inputDescription };
|
|
7090
7094
|
}
|
|
7091
7095
|
function getPropertyName(name) {
|
|
7092
7096
|
if (ts11.isIdentifier(name)) return name.text;
|
|
@@ -7169,8 +7173,8 @@ function serializeAgents(agents, dist = "dist") {
|
|
|
7169
7173
|
return agents.map((a) => ({
|
|
7170
7174
|
name: a.name,
|
|
7171
7175
|
description: a.description,
|
|
7172
|
-
hasRun: a.hasRun,
|
|
7173
7176
|
systemPrompt: a.systemPrompt,
|
|
7177
|
+
systemPromptFile: a.systemPromptFile,
|
|
7174
7178
|
tools: a.tools,
|
|
7175
7179
|
agents: a.agents,
|
|
7176
7180
|
model: a.model,
|
|
@@ -7190,8 +7194,8 @@ function hydrateAgents(manifest) {
|
|
|
7190
7194
|
name: a.name,
|
|
7191
7195
|
description: a.description ?? void 0,
|
|
7192
7196
|
filePath: a.filePath,
|
|
7193
|
-
hasRun: a.hasRun,
|
|
7194
7197
|
systemPrompt: a.systemPrompt ?? void 0,
|
|
7198
|
+
systemPromptFile: a.systemPromptFile ?? void 0,
|
|
7195
7199
|
tools: a.tools ?? void 0,
|
|
7196
7200
|
agents: a.agents ?? void 0,
|
|
7197
7201
|
model: a.model ?? void 0,
|
|
@@ -7229,8 +7233,7 @@ async function generateAgentArtifacts(agents, rootDir, dist) {
|
|
|
7229
7233
|
const program = programByFile.get(absPath);
|
|
7230
7234
|
const result = extractAgentMetadata(program, absPath, {
|
|
7231
7235
|
name: manifest.name,
|
|
7232
|
-
filePath: manifest.filePath
|
|
7233
|
-
hasRun: manifest.hasRun
|
|
7236
|
+
filePath: manifest.filePath
|
|
7234
7237
|
});
|
|
7235
7238
|
if (!result) {
|
|
7236
7239
|
throw new Error(
|
|
@@ -7379,7 +7382,7 @@ var TOOLS_FILE2 = "faapi-tools.js";
|
|
|
7379
7382
|
var AGENTS_FILE2 = "faapi-agents.js";
|
|
7380
7383
|
async function loadAndHydrateTools(rootDir, dist, registries = defaultRegistries) {
|
|
7381
7384
|
const toolsPath = path26.resolve(rootDir, dist, TOOLS_FILE2);
|
|
7382
|
-
if (!
|
|
7385
|
+
if (!fs20.existsSync(toolsPath)) {
|
|
7383
7386
|
return [];
|
|
7384
7387
|
}
|
|
7385
7388
|
const serialized = await importWithCacheBust(toolsPath);
|
|
@@ -7389,7 +7392,7 @@ async function loadAndHydrateTools(rootDir, dist, registries = defaultRegistries
|
|
|
7389
7392
|
}
|
|
7390
7393
|
async function loadAndHydrateAgents(rootDir, dist, registries = defaultRegistries) {
|
|
7391
7394
|
const agentsPath = path26.resolve(rootDir, dist, AGENTS_FILE2);
|
|
7392
|
-
if (!
|
|
7395
|
+
if (!fs20.existsSync(agentsPath)) {
|
|
7393
7396
|
return [];
|
|
7394
7397
|
}
|
|
7395
7398
|
const serialized = await importWithCacheBust(agentsPath);
|
|
@@ -7405,7 +7408,7 @@ function getTaskDriverOptions(config) {
|
|
|
7405
7408
|
}
|
|
7406
7409
|
async function loadAndHydrateTasks(rootDir, dist, registries = defaultRegistries) {
|
|
7407
7410
|
const tasksPath = path26.resolve(rootDir, dist, TASKS_FILE);
|
|
7408
|
-
if (!
|
|
7411
|
+
if (!fs20.existsSync(tasksPath)) {
|
|
7409
7412
|
return [];
|
|
7410
7413
|
}
|
|
7411
7414
|
const serialized = await importWithCacheBust(tasksPath);
|
|
@@ -7582,8 +7585,7 @@ function logStartupSummary(routes, wsRoutes, tools, agents, taskMetas, p) {
|
|
|
7582
7585
|
if (agents.length > 0) {
|
|
7583
7586
|
console.log(`- Loaded ${agents.length} agent(s):`);
|
|
7584
7587
|
for (const agent of agents) {
|
|
7585
|
-
|
|
7586
|
-
console.log(` ${agent.name} [${exports}] ${agent.filePath}`);
|
|
7588
|
+
console.log(` ${agent.name} ${agent.filePath}`);
|
|
7587
7589
|
}
|
|
7588
7590
|
}
|
|
7589
7591
|
if (taskMetas.length > 0) {
|
|
@@ -7599,7 +7601,7 @@ async function createAppBase(options) {
|
|
|
7599
7601
|
const dist = options?.dist ?? process.env.FAAPI_DIST ?? DEFAULT_DIST;
|
|
7600
7602
|
const resourcesDir = resolveResourcesDir(rootDir, dist);
|
|
7601
7603
|
const routesPath = path27.resolve(rootDir, dist, ROUTES_FILE);
|
|
7602
|
-
if (!
|
|
7604
|
+
if (!fs21.existsSync(routesPath)) {
|
|
7603
7605
|
throw new Error(
|
|
7604
7606
|
`[faapi] ${dist}/${ROUTES_FILE} \u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u6267\u884C \`faapi build\`\uFF08\u6216 \`faapi dev\`\uFF09\u751F\u6210\u4EA7\u7269\u3002`
|
|
7605
7607
|
);
|
|
@@ -7620,6 +7622,7 @@ async function createAppBase(options) {
|
|
|
7620
7622
|
registry: registries.task,
|
|
7621
7623
|
rootDir,
|
|
7622
7624
|
config,
|
|
7625
|
+
resourcesDir,
|
|
7623
7626
|
registries: createTaskRegistriesView(registries),
|
|
7624
7627
|
driver: taskDriver,
|
|
7625
7628
|
onFailed: config?.task?.onFailed
|
|
@@ -7661,6 +7664,7 @@ async function createAppBase(options) {
|
|
|
7661
7664
|
config?.plugins,
|
|
7662
7665
|
{
|
|
7663
7666
|
rootDir,
|
|
7667
|
+
resourcesDir,
|
|
7664
7668
|
registries,
|
|
7665
7669
|
routes: sorted,
|
|
7666
7670
|
getRoutes: () => sorted,
|
|
@@ -7815,21 +7819,21 @@ async function createAppBase(options) {
|
|
|
7815
7819
|
}
|
|
7816
7820
|
|
|
7817
7821
|
// src/cli/createDevApp.ts
|
|
7818
|
-
import
|
|
7822
|
+
import path30 from "path";
|
|
7819
7823
|
|
|
7820
7824
|
// src/router/scanRoutes.ts
|
|
7821
7825
|
import fg3 from "fast-glob";
|
|
7822
7826
|
import path28 from "path";
|
|
7823
|
-
import
|
|
7827
|
+
import fs22 from "fs";
|
|
7824
7828
|
|
|
7825
7829
|
// src/router/constants.ts
|
|
7826
7830
|
var HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
|
|
7827
7831
|
var HTTP_METHOD_SET = new Set(HTTP_METHODS);
|
|
7828
7832
|
|
|
7829
7833
|
// src/utils/normalizePath.ts
|
|
7830
|
-
function normalizePath(
|
|
7831
|
-
if (!
|
|
7832
|
-
let result =
|
|
7834
|
+
function normalizePath(path31) {
|
|
7835
|
+
if (!path31) return "";
|
|
7836
|
+
let result = path31.replace(/\\/g, "/");
|
|
7833
7837
|
result = result.replace(/\/+/g, "/");
|
|
7834
7838
|
result = result.replace(/\/+$/, "");
|
|
7835
7839
|
if (result && !result.startsWith("/")) {
|
|
@@ -7900,7 +7904,7 @@ function collectMiddlewarePaths(routeFilePath, rootDir, dist) {
|
|
|
7900
7904
|
const mwJsPath = path28.join(currentDir, "middlewares.js");
|
|
7901
7905
|
const absTsPath = path28.resolve(rootDir, mwTsPath);
|
|
7902
7906
|
const absJsPath = path28.resolve(rootDir, mwJsPath);
|
|
7903
|
-
const absMwPath =
|
|
7907
|
+
const absMwPath = fs22.existsSync(absTsPath) ? absTsPath : fs22.existsSync(absJsPath) ? absJsPath : null;
|
|
7904
7908
|
if (absMwPath) {
|
|
7905
7909
|
const relMwPath = path28.relative(rootDir, absMwPath);
|
|
7906
7910
|
const prodAbsPath = path28.resolve(rootDir, toProdFilePath(relMwPath, dist));
|
|
@@ -7910,7 +7914,7 @@ function collectMiddlewarePaths(routeFilePath, rootDir, dist) {
|
|
|
7910
7914
|
for (const ext of [".ts", ".js"]) {
|
|
7911
7915
|
const mwPath = path28.join(currentDir, `middlewares${ext}`);
|
|
7912
7916
|
const absMwPath = path28.resolve(rootDir, mwPath);
|
|
7913
|
-
if (
|
|
7917
|
+
if (fs22.existsSync(absMwPath)) {
|
|
7914
7918
|
paths.push(absMwPath);
|
|
7915
7919
|
break;
|
|
7916
7920
|
}
|
|
@@ -7949,7 +7953,7 @@ async function scanRoutes(rootDir, patterns, dist) {
|
|
|
7949
7953
|
const mwPaths = collectMiddlewarePaths(normalizedFile, rootDir);
|
|
7950
7954
|
middlewareBundle = await loadMergedMiddlewares(mwPaths);
|
|
7951
7955
|
}
|
|
7952
|
-
const source = await
|
|
7956
|
+
const source = await fs22.promises.readFile(absPath, "utf8").catch(() => "");
|
|
7953
7957
|
const exportNames = extractExportsFromSource(source);
|
|
7954
7958
|
const methods = HTTP_METHODS.filter((m) => exportNames.has(m));
|
|
7955
7959
|
for (const method of methods) {
|
|
@@ -7986,7 +7990,7 @@ async function scanRoutes(rootDir, patterns, dist) {
|
|
|
7986
7990
|
// src/tools/scanTools.ts
|
|
7987
7991
|
import fg4 from "fast-glob";
|
|
7988
7992
|
import path29 from "path";
|
|
7989
|
-
import
|
|
7993
|
+
import fs23 from "fs";
|
|
7990
7994
|
var TOOL_PATTERNS = ["src/tools/**/*.ts"];
|
|
7991
7995
|
var TOOL_EXPORT_RE = new RegExp(
|
|
7992
7996
|
String.raw`export\s+(?:async\s+)?(?:function\s+|const\s+)([A-Za-z_$][\w$]*)\s*(?:\(|=)`,
|
|
@@ -8037,7 +8041,7 @@ async function scanTools(rootDir, patterns) {
|
|
|
8037
8041
|
continue;
|
|
8038
8042
|
}
|
|
8039
8043
|
const absPath = path29.resolve(rootDir, normalizedFile);
|
|
8040
|
-
const source = await
|
|
8044
|
+
const source = await fs23.promises.readFile(absPath, "utf8").catch(() => "");
|
|
8041
8045
|
const exportNames = extractToolExportsFromSource(source);
|
|
8042
8046
|
const namespace = filePathToToolNamespace(normalizedFile);
|
|
8043
8047
|
for (const fnName of exportNames) {
|
|
@@ -8061,10 +8065,7 @@ async function scanTools(rootDir, patterns) {
|
|
|
8061
8065
|
|
|
8062
8066
|
// src/agents/scanAgents.ts
|
|
8063
8067
|
import fg5 from "fast-glob";
|
|
8064
|
-
import path30 from "path";
|
|
8065
|
-
import fs25 from "fs";
|
|
8066
8068
|
var DEFAULT_AGENT_PATTERNS = ["src/agents/**/handler.ts"];
|
|
8067
|
-
var RUN_EXPORT_RE = /export\s+(?:async\s+)?(?:function\s+|const\s+)run\b/;
|
|
8068
8069
|
function extractAgentNameFromPath(filePath) {
|
|
8069
8070
|
const normalized = filePath.replace(/\\/g, "/");
|
|
8070
8071
|
const match = normalized.match(/(?:^|\/)agents\/(.+)\/handler\.ts$/);
|
|
@@ -8075,11 +8076,6 @@ function extractAgentNameFromPath(filePath) {
|
|
|
8075
8076
|
}
|
|
8076
8077
|
return match[1].replace(/\//g, ".");
|
|
8077
8078
|
}
|
|
8078
|
-
function detectAgentExports(source) {
|
|
8079
|
-
return {
|
|
8080
|
-
hasRun: RUN_EXPORT_RE.test(source)
|
|
8081
|
-
};
|
|
8082
|
-
}
|
|
8083
8079
|
async function scanAgents(rootDir, patterns) {
|
|
8084
8080
|
const files = await fg5(patterns, {
|
|
8085
8081
|
cwd: rootDir,
|
|
@@ -8094,9 +8090,6 @@ async function scanAgents(rootDir, patterns) {
|
|
|
8094
8090
|
if (fileName !== "handler.ts" && fileName !== "handler.js") {
|
|
8095
8091
|
continue;
|
|
8096
8092
|
}
|
|
8097
|
-
const absPath = path30.resolve(rootDir, normalizedFile);
|
|
8098
|
-
const source = await fs25.promises.readFile(absPath, "utf8").catch(() => "");
|
|
8099
|
-
const { hasRun } = detectAgentExports(source);
|
|
8100
8093
|
const name = extractAgentNameFromPath(normalizedFile);
|
|
8101
8094
|
const prevFile = seen.get(name);
|
|
8102
8095
|
if (prevFile) {
|
|
@@ -8107,8 +8100,7 @@ async function scanAgents(rootDir, patterns) {
|
|
|
8107
8100
|
seen.set(name, normalizedFile);
|
|
8108
8101
|
agents.push({
|
|
8109
8102
|
name,
|
|
8110
|
-
filePath: normalizedFile
|
|
8111
|
-
hasRun
|
|
8103
|
+
filePath: normalizedFile
|
|
8112
8104
|
});
|
|
8113
8105
|
}
|
|
8114
8106
|
return agents;
|
|
@@ -8166,7 +8158,7 @@ async function createDevApp(options) {
|
|
|
8166
8158
|
if (!suppressProgramInvalidation) invalidateProgramCache();
|
|
8167
8159
|
const tasks = await scanTasks(ctx.rootDir, TASK_PATTERNS);
|
|
8168
8160
|
for (const task of tasks) {
|
|
8169
|
-
await ensureCompiled(
|
|
8161
|
+
await ensureCompiled(path30.resolve(ctx.rootDir, task.filePath), ctx.rootDir, ctx.dist);
|
|
8170
8162
|
}
|
|
8171
8163
|
await generateTaskArtifacts(tasks, ctx.rootDir, ctx.dist);
|
|
8172
8164
|
ctx.taskQueue.invalidateModules();
|
|
@@ -8232,7 +8224,6 @@ export {
|
|
|
8232
8224
|
hydrateSkillRegistry,
|
|
8233
8225
|
invalidateProgramCache,
|
|
8234
8226
|
listSkills,
|
|
8235
|
-
loadAgentModule,
|
|
8236
8227
|
loadConfig,
|
|
8237
8228
|
loadEnv,
|
|
8238
8229
|
loadTaskDriver,
|