@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/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(path32) {
2050
- super("ROUTE_NOT_FOUND", `Route not found: ${path32}`, 404);
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, path32, allowedMethods) {
2056
- super("METHOD_NOT_ALLOWED", `Method ${method} not allowed for ${path32}`, 405);
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: { config: safeConfig(taskCtx.config), job: taskCtx.job },
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/loadAgentModule.ts
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 && fs13.existsSync(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 fs14 from "fs";
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 (fs14.existsSync(configProductPath)) {
4228
+ if (fs13.existsSync(configProductPath)) {
4262
4229
  const module = await importWithCacheBust(configProductPath);
4263
4230
  return module.default ?? {};
4264
4231
  }
4265
- const hasSourceConfig = fs14.existsSync(path16.join(rootDir, "faapi.config.ts")) || fs14.existsSync(path16.join(rootDir, "faapi.config.js"));
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 fs15 from "fs";
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 (!fs15.existsSync(filePath)) continue;
4345
- const content = fs15.readFileSync(filePath, "utf-8");
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 fs22 from "fs";
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, path32) {
4431
+ function matchRoute(routes, method, path31) {
4465
4432
  const index = getHttpIndex(routes);
4466
4433
  const upper = method.toUpperCase();
4467
- const hit = matchByMethod(index, upper, path32);
4434
+ const hit = matchByMethod(index, upper, path31);
4468
4435
  if (hit) return hit;
4469
4436
  if (upper === "HEAD") {
4470
- return matchByMethod(index, "GET", path32);
4437
+ return matchByMethod(index, "GET", path31);
4471
4438
  }
4472
4439
  return null;
4473
4440
  }
4474
- function matchByMethod(index, method, path32) {
4475
- const staticHit = index.static.get(`${method}|${path32}`);
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 = path32.split("/").filter(Boolean);
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, path32) {
4462
+ function matchWsRoute(wsRoutes, path31) {
4496
4463
  const index = getWsIndex(wsRoutes);
4497
- const staticHit = index.static.get(path32);
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, path32, route.paramNames, route.isCatchAll);
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, path32) {
4476
+ function findAllowedMethods(routes, path31) {
4510
4477
  const index = getHttpIndex(routes);
4511
4478
  const methods = /* @__PURE__ */ new Set();
4512
- const staticMethods = index.methodsByStaticPath.get(path32);
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 = path32.split("/").filter(Boolean);
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, path32, paramNames, isCatchAll) {
4504
+ function matchDynamicPath(pattern, path31, paramNames, isCatchAll) {
4538
4505
  return matchSegments(
4539
4506
  pattern.split("/").filter(Boolean),
4540
- path32.split("/").filter(Boolean),
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 path32 = issue.path.map(String).join(".") || "";
5646
+ const path31 = issue.path.map(String).join(".") || "";
5680
5647
  return {
5681
- path: path32,
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 fs17 from "fs";
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 fs16 from "fs";
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 && fs17.existsSync(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 (fs17.existsSync(schemaPath)) {
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 fs18 from "fs";
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 fs20 from "fs";
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 fs19 from "fs";
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)) && fs20.existsSync(base)) return 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 (fs20.existsSync(base + ext)) return base + ext;
6837
+ if (fs19.existsSync(base + ext)) return base + ext;
6871
6838
  }
6872
6839
  for (const indexExt of ["/index.ts", "/index.js"]) {
6873
- if (fs20.existsSync(base + indexExt)) return base + indexExt;
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 && fs20.existsSync(productPath) && (sourcePath === null || isProductFresh(sourcePath, productPath))) {
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 && fs20.existsSync(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 fs21 from "fs";
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\u7CFB\u7EDF\u63D0\u793A\u8BCD\uFF08\u5B57\u7B26\u4E32\u5B57\u9762\u91CF\u3001\u65E0\u63D2\u503C\u6A21\u677F\u5B57\u7B26\u4E32\u6216\u5176 + \u62FC\u63A5\uFF09",
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 === void 0) {
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\u7CFB\u7EDF\u63D0\u793A\u8BCD\uFF08\u5B57\u7B26\u4E32\u5B57\u9762\u91CF\u3001\u65E0\u63D2\u503C\u6A21\u677F\u5B57\u7B26\u4E32\u6216\u5176 + \u62FC\u63A5\uFF09",
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 (!fs21.existsSync(toolsPath)) {
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 (!fs21.existsSync(agentsPath)) {
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 (!fs21.existsSync(tasksPath)) {
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
- const exports = agent.hasRun ? "run" : "-";
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 (!fs22.existsSync(routesPath)) {
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 path31 from "path";
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 fs23 from "fs";
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(path32) {
7831
- if (!path32) return "";
7832
- let result = path32.replace(/\\/g, "/");
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 = fs23.existsSync(absTsPath) ? absTsPath : fs23.existsSync(absJsPath) ? absJsPath : null;
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 (fs23.existsSync(absMwPath)) {
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 fs23.promises.readFile(absPath, "utf8").catch(() => "");
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 fs24 from "fs";
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 fs24.promises.readFile(absPath, "utf8").catch(() => "");
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(path31.resolve(ctx.rootDir, task.filePath), ctx.rootDir, ctx.dist);
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,