@faapi/faapi 6.26.0 → 6.27.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.
@@ -80,7 +80,7 @@ interface AgentCore {
80
80
  systemPrompt?: string;
81
81
  /**
82
82
  * 系统提示词文件路径(config 块字面量提取),相对产物 resources 目录
83
- * (`<dist>/resources/`,即 `ctx.resourcesDir`),与 `systemPrompt` 互斥
83
+ * (`<dist>/resources/`,运行时经免传参 `readResource` 读取),与 `systemPrompt` 互斥
84
84
  * (都声明构建期抛错,二选一必填)
85
85
  *
86
86
  * 运行时每次 run 读文件内容作为 systemPrompt——dev 改 prompt 文件经 watcher
@@ -364,9 +364,8 @@ interface TaskWorkerOptions {
364
364
  taskCtx: {
365
365
  config: unknown;
366
366
  /**
367
- * 产物 resources 目录绝对路径(纯字符串可结构化克隆)——两处用途:经
368
- * workerData 传给入口在任务模块求值前播种全局读取根 + 挂到 worker 内的
369
- * taskCtx(业务方了解/拼接资源位置)
367
+ * 产物 resources 目录绝对路径(纯字符串可结构化克隆)——经 workerData
368
+ * 传给入口在任务模块求值前播种全局读取根(内部字段,不进业务 taskCtx)
370
369
  */
371
370
  resourcesDir?: string;
372
371
  job: {
@@ -628,14 +627,6 @@ interface TaskContext {
628
627
  signal: AbortSignal;
629
628
  /** faapi.config.ts 全量配置(含自定义业务配置) */
630
629
  config: unknown;
631
- /**
632
- * 产物 resources 目录绝对路径(`<rootDir>/<dist>/resources`)
633
- *
634
- * 任务读静态文件(prompt 模板等)用:`fs.readFile(path.join(taskCtx.resourcesDir, 'x.md'))`。
635
- * 进程内与隔离执行两条路径均注入(隔离为纯字符串,可结构化克隆);
636
- * 直接构造 TaskContext 的测试/自定义执行器可不传。
637
- */
638
- resourcesDir?: string;
639
630
  job: {
640
631
  id: string;
641
632
  name: string;
@@ -736,8 +727,10 @@ interface TaskQueueDeps {
736
727
  /** faapi.config.ts 全量配置,透传给 run 的 TaskContext.config */
737
728
  config?: unknown;
738
729
  /**
739
- * 产物 resources 目录绝对路径——注入两条执行路径的 TaskContext.resourcesDir;
740
- * 缺省不注入(直接构造队列的测试/嵌入场景)
730
+ * 产物 resources 目录绝对路径——**内部字段**,仅作隔离 worker 读取根播种的
731
+ * 数据源(经 workerData 传入 workerEntry,不进业务可见的 TaskContext——
732
+ * 任务读资源统一走免传参 `readResource`);缺省不播种(直接构造队列的
733
+ * 测试/嵌入场景,readResource 未绑定即显式抛错)
741
734
  */
742
735
  resourcesDir?: string;
743
736
  /**
@@ -1051,15 +1044,6 @@ interface FaapiContext {
1051
1044
  cookies: Record<string, string>;
1052
1045
  /** 配置文件中的自定义业务配置(类型可通过 declare module '@faapi/faapi' 增强 FaapiContextConfig) */
1053
1046
  config: FaapiContextConfig;
1054
- /**
1055
- * 运行时资源根目录绝对路径(<rootDir>/<dist>/resources)
1056
- *
1057
- * `src/resources/` 经 dev/build 复制进产物后的位置。数据字段——读取统一走
1058
- * 免传参的 `readResource('prompts/foo.md')`(app 启动时绑定,见
1059
- * src/utils/readResource.md),本字段供业务方了解/拼接资源位置。
1060
- * HTTP/WS 请求链路恒有值;testing 直调(createTestContext)未传时为 undefined。
1061
- */
1062
- resourcesDir?: string;
1063
1047
  /**
1064
1048
  * 设置响应状态码
1065
1049
  */
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { A as AppRegistries, F as FaapiContext, T as TaskClient, L as LogConfig, a as TaskFailedHandler, b as TaskQueueDeps, c as TaskQueue, d as TaskDriver, e as TaskRegistry, f as TaskManifest, g as ToolMetadata, h as AgentCore, i as AgentMetadata, C as CreateLoggerOptions, j as Logger } from './contextTypes-gYf84EXF.js';
2
- export { k as AgentHandleFactory, l as AgentHandleStore, m as AgentPathMeta, n as AgentRegistry, o as AgentToolDescriptor, p as FaapiContextConfig, q as FaapiTaskMeta, r as FailOptions, s as LogEntry, t as LogLevel, u as LogSink, S as SkillRegistry, v as SseEvent, w as SseOptions, x as SseWriter, y as TaskContext, z as TaskDriverJob, B as TaskDriverProcess, D as TaskDriverRecord, E as TaskFailedInfo, G as TaskJob, H as TaskJobStatus, I as TaskMetadata, J as TaskModule, K as TaskRegistriesSnapshot, M as TaskRegistriesView, N as ToolCore, O as ToolPathMeta, P as ToolRegistry, Q as createAppRegistries, R as createTaskRegistriesView, U as createTaskRegistry } from './contextTypes-gYf84EXF.js';
3
- import { F as FaapiMiddleware, R as RouteManifest, C as CorsOptions, H as HelmetOptions, I as InjectorMap, W as WsRouteManifest } from './routeTypes-DlD6nnbT.js';
4
- export { a as Injector, b as RouteInfo, c as RouteInputSchema, d as RouteOutputSchema, e as RouteParamSchema, f as cors, h as helmet } from './routeTypes-DlD6nnbT.js';
1
+ import { A as AppRegistries, F as FaapiContext, T as TaskClient, L as LogConfig, a as TaskFailedHandler, b as TaskQueueDeps, c as TaskQueue, d as TaskDriver, e as TaskRegistry, f as TaskManifest, g as ToolMetadata, h as AgentCore, i as AgentMetadata, C as CreateLoggerOptions, j as Logger } from './contextTypes-CBE86AO2.js';
2
+ export { k as AgentHandleFactory, l as AgentHandleStore, m as AgentPathMeta, n as AgentRegistry, o as AgentToolDescriptor, p as FaapiContextConfig, q as FaapiTaskMeta, r as FailOptions, s as LogEntry, t as LogLevel, u as LogSink, S as SkillRegistry, v as SseEvent, w as SseOptions, x as SseWriter, y as TaskContext, z as TaskDriverJob, B as TaskDriverProcess, D as TaskDriverRecord, E as TaskFailedInfo, G as TaskJob, H as TaskJobStatus, I as TaskMetadata, J as TaskModule, K as TaskRegistriesSnapshot, M as TaskRegistriesView, N as ToolCore, O as ToolPathMeta, P as ToolRegistry, Q as createAppRegistries, R as createTaskRegistriesView, U as createTaskRegistry } from './contextTypes-CBE86AO2.js';
3
+ import { F as FaapiMiddleware, R as RouteManifest, C as CorsOptions, H as HelmetOptions, I as InjectorMap, W as WsRouteManifest } from './routeTypes-DVSnH0jk.js';
4
+ export { a as Injector, b as RouteInfo, c as RouteInputSchema, d as RouteOutputSchema, e as RouteParamSchema, f as cors, h as helmet } from './routeTypes-DVSnH0jk.js';
5
5
  import * as node_http from 'node:http';
6
6
  import { Server, IncomingMessage, ServerResponse } from 'node:http';
7
7
  import { Socket } from 'node:net';
@@ -50,14 +50,6 @@ type UpgradeHandler = (req: IncomingMessage, socket: Socket, head: Buffer) => vo
50
50
  interface PluginContext {
51
51
  /** 项目根目录 */
52
52
  rootDir: string;
53
- /**
54
- * 产物 resources 目录绝对路径(`<rootDir>/<dist>/resources`)
55
- *
56
- * `src/resources/` 经 dev/build 复制进产物后的位置——插件 setup 时读静态
57
- * 资源用;`@faapi/agent` 插件据此注入 AgentDeps(agent config 的
58
- * systemPromptFile 相对此目录解析)。
59
- */
60
- resourcesDir: string;
61
53
  /** app 级注册表(tool/agent/skill/agentHandle 实例,随 app 生命周期) */
62
54
  registries: AppRegistries;
63
55
  /** 当前路由清单(setup 时的快照,reloadRoutes 后不会更新;需最新路由用 getRoutes()) */
@@ -261,13 +253,6 @@ interface TaskConfig {
261
253
  interface LifecycleContext {
262
254
  /** 项目根目录 */
263
255
  rootDir: string;
264
- /**
265
- * 运行时资源根目录绝对路径(<rootDir>/<dist>/resources)
266
- *
267
- * `src/resources/` 经 dev/build 复制进产物后的位置,onReady 中预加载
268
- * prompt 模板等静态文件时定位用(`path.join(resourcesDir, 'prompts/foo.md')`)。
269
- */
270
- resourcesDir: string;
271
256
  /** 当前路由清单 */
272
257
  routes: RouteManifest;
273
258
  /** 服务器实例(onBoot 钩子触发时已创建但未监听,`listening === false`) */
@@ -860,13 +845,6 @@ interface WsContext {
860
845
  headers: Headers;
861
846
  /** 业务配置(来自 faapi.config.ts) */
862
847
  config: Record<string, unknown>;
863
- /**
864
- * 运行时资源根目录绝对路径(<rootDir>/<dist>/resources)
865
- *
866
- * 与 HTTP FaapiContext 同源(握手 ctx 是 FaapiContext 的结构子集),handler
867
- * 的 WS 回调里读静态文件用。testing 直调未传时为 undefined。
868
- */
869
- resourcesDir?: string;
870
848
  /** 中间件塞入的用户信息(鉴权等) */
871
849
  user?: unknown;
872
850
  /** 允许通过 declare module 扩展 */
package/dist/index.js CHANGED
@@ -2224,7 +2224,6 @@ async function runTaskInWorker(options) {
2224
2224
  payload,
2225
2225
  taskCtx: {
2226
2226
  config: safeConfig(taskCtx.config),
2227
- resourcesDir: taskCtx.resourcesDir,
2228
2227
  job: taskCtx.job
2229
2228
  },
2230
2229
  registries: options.registries,
@@ -2607,7 +2606,6 @@ function createTaskQueue(deps) {
2607
2606
  const taskCtx = {
2608
2607
  signal: job.signal,
2609
2608
  config: deps.config,
2610
- resourcesDir: deps.resourcesDir,
2611
2609
  job: { id: job.id, name: job.name, attempt: job.attempt },
2612
2610
  registries: registriesView,
2613
2611
  log: createLogger(`task:${job.name}`, {
@@ -4296,7 +4294,7 @@ import {
4296
4294
  import { createSecureServer as createHttp2SecureServer } from "http2";
4297
4295
  import { readFileSync } from "fs";
4298
4296
  import { Readable as Readable2 } from "stream";
4299
- import path21 from "path";
4297
+ import path20 from "path";
4300
4298
 
4301
4299
  // src/router/matchRoute.ts
4302
4300
  var httpIndexCache = /* @__PURE__ */ new WeakMap();
@@ -4917,18 +4915,10 @@ function formatSetCookie(name, value, options) {
4917
4915
  if (options?.sameSite) cookie += `; SameSite=${options.sameSite}`;
4918
4916
  return cookie;
4919
4917
  }
4920
- function createContext(request, params, config = {}, ip = "", registries, resourcesDir) {
4921
- return createContextFromUrl(
4922
- request,
4923
- new URL(request.url),
4924
- params,
4925
- config,
4926
- ip,
4927
- registries,
4928
- resourcesDir
4929
- );
4918
+ function createContext(request, params, config = {}, ip = "", registries) {
4919
+ return createContextFromUrl(request, new URL(request.url), params, config, ip, registries);
4930
4920
  }
4931
- function createContextFromUrl(request, url, params, config = {}, ip = "", registries, resourcesDir) {
4921
+ function createContextFromUrl(request, url, params, config = {}, ip = "", registries) {
4932
4922
  const meta = { headers: {}, setCookies: [] };
4933
4923
  const parsedCookies = parseCookies(request.headers.get("cookie") ?? "");
4934
4924
  const cookiesObj = {};
@@ -4956,9 +4946,6 @@ function createContextFromUrl(request, url, params, config = {}, ip = "", regist
4956
4946
  ua: request.headers.get("user-agent") ?? "",
4957
4947
  cookies: cookiesObj,
4958
4948
  config,
4959
- // 运行时资源根目录(HTTP/WS 链路由 createServer/handleWsUpgrade 传入;
4960
- // testing 直调未传时为 undefined,见 contextTypes.resourcesDir 注释)
4961
- resourcesDir,
4962
4949
  meta,
4963
4950
  setStatus(status) {
4964
4951
  meta.status = status;
@@ -5776,17 +5763,9 @@ function etag(options = {}) {
5776
5763
  }
5777
5764
 
5778
5765
  // src/server/handleWsUpgrade.ts
5779
- import fs17 from "fs";
5766
+ import fs16 from "fs";
5780
5767
  import { WebSocketServer, WebSocket } from "ws";
5781
- import path20 from "path";
5782
-
5783
- // src/cli/copyResources.ts
5784
5768
  import path19 from "path";
5785
- import fs16 from "fs";
5786
- var RESOURCES_OUTPUT_DIR = "resources";
5787
- function resolveResourcesDir(rootDir, dist) {
5788
- return path19.resolve(rootDir, dist, RESOURCES_OUTPUT_DIR);
5789
- }
5790
5769
 
5791
5770
  // src/server/serverUtils.ts
5792
5771
  function nodeHttpToWebHeaders(req) {
@@ -5926,7 +5905,7 @@ async function loadWsHandler(filePath, ctx, rootDir) {
5926
5905
  const dist = getDevDist();
5927
5906
  if (dist) {
5928
5907
  const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
5929
- if (sourcePath && fs17.existsSync(sourcePath)) {
5908
+ if (sourcePath && fs16.existsSync(sourcePath)) {
5930
5909
  await ensureCompiled(sourcePath, rootDir, dist);
5931
5910
  }
5932
5911
  }
@@ -6024,7 +6003,6 @@ function attachWebSocket(options) {
6024
6003
  trustedProxy = false,
6025
6004
  registries
6026
6005
  } = options;
6027
- const resourcesDir = resolveResourcesDir(rootDir, dist);
6028
6006
  const wss = new WebSocketServer({ noServer: true });
6029
6007
  server.on("upgrade", async (req, socket, head) => {
6030
6008
  try {
@@ -6056,19 +6034,12 @@ function attachWebSocket(options) {
6056
6034
  const host = req.headers.host ?? "localhost";
6057
6035
  const fullUrl = new URL(`http://${host}${req.url ?? "/"}`);
6058
6036
  const request = new Request(fullUrl.toString(), { method: "GET", headers });
6059
- const ctx = createContext(
6060
- request,
6061
- params,
6062
- config,
6063
- getClientIp(req, trustedProxy),
6064
- registries,
6065
- resourcesDir
6066
- );
6037
+ const ctx = createContext(request, params, config, getClientIp(req, trustedProxy), registries);
6067
6038
  const meta = ctx.meta;
6068
6039
  let upgraded = false;
6069
6040
  const finalHandler = async () => {
6070
6041
  const schemaPath = getRuntimeSchemaPath(route.filePath, dist, rootDir);
6071
- if (fs17.existsSync(schemaPath)) {
6042
+ if (fs16.existsSync(schemaPath)) {
6072
6043
  if (isDevOnDemandEnabled()) {
6073
6044
  const devDist = getDevDist();
6074
6045
  if (devDist) {
@@ -6107,7 +6078,7 @@ function attachWebSocket(options) {
6107
6078
  }
6108
6079
  let handlers;
6109
6080
  try {
6110
- const absoluteFilePath = path20.resolve(rootDir, route.filePath);
6081
+ const absoluteFilePath = path19.resolve(rootDir, route.filePath);
6111
6082
  handlers = await loadWsHandler(absoluteFilePath, ctx, rootDir);
6112
6083
  } catch (err) {
6113
6084
  const reason = err instanceof Error ? err.message : String(err);
@@ -6267,7 +6238,6 @@ function createServer(options) {
6267
6238
  trustedProxy = false
6268
6239
  } = options;
6269
6240
  const routesRef = { current: routes, wsCurrent: wsRoutes ?? [] };
6270
- const resourcesDir = resolveResourcesDir(rootDir, dist);
6271
6241
  const configMiddlewares = [];
6272
6242
  if (compressionOption) {
6273
6243
  const compOpts = typeof compressionOption === "object" ? compressionOption : {};
@@ -6314,8 +6284,7 @@ function createServer(options) {
6314
6284
  bodyLimit,
6315
6285
  trustedProxy,
6316
6286
  registries,
6317
- routesRef.wsCurrent,
6318
- resourcesDir
6287
+ routesRef.wsCurrent
6319
6288
  ).catch((err) => {
6320
6289
  console.error("[faapi] Request pipeline failed after error response attempt:", err);
6321
6290
  try {
@@ -6341,7 +6310,7 @@ function createServer(options) {
6341
6310
  });
6342
6311
  return { server, routesRef };
6343
6312
  }
6344
- function prepareRequest(req, request, url, config, trustedProxy, registries, preMatched, resourcesDir) {
6313
+ function prepareRequest(req, request, url, config, trustedProxy, registries, preMatched) {
6345
6314
  const method = request.method.toUpperCase();
6346
6315
  const urlPath = url.pathname;
6347
6316
  const ctx = createContextFromUrl(
@@ -6350,8 +6319,7 @@ function prepareRequest(req, request, url, config, trustedProxy, registries, pre
6350
6319
  preMatched?.params ?? {},
6351
6320
  config,
6352
6321
  getClientIp(req, trustedProxy),
6353
- registries,
6354
- resourcesDir
6322
+ registries
6355
6323
  );
6356
6324
  const meta = ctx.meta;
6357
6325
  return { request, url, ctx, meta, method, urlPath };
@@ -6370,7 +6338,7 @@ function getRoutePaths(route, rootDir, dist) {
6370
6338
  let cached = routePathCache.get(route);
6371
6339
  if (!cached) {
6372
6340
  cached = {
6373
- absFilePath: path21.resolve(rootDir, route.filePath),
6341
+ absFilePath: path20.resolve(rootDir, route.filePath),
6374
6342
  schemaPath: getRuntimeSchemaPath(route.filePath, dist, rootDir)
6375
6343
  };
6376
6344
  routePathCache.set(route, cached);
@@ -6493,7 +6461,7 @@ async function sendErrorResponse(err, meta, res, onError, ctx) {
6493
6461
  }
6494
6462
  }
6495
6463
  }
6496
- async function handleRequest(routes, rootDir, dist, req, res, outerMiddlewares, onError, config, globalInjectors, bodyLimit, trustedProxy, registries, wsRoutes, resourcesDir) {
6464
+ async function handleRequest(routes, rootDir, dist, req, res, outerMiddlewares, onError, config, globalInjectors, bodyLimit, trustedProxy, registries, wsRoutes) {
6497
6465
  let meta = { headers: {}, setCookies: [] };
6498
6466
  let ctx;
6499
6467
  let sseEarlySent = false;
@@ -6513,8 +6481,7 @@ async function handleRequest(routes, rootDir, dist, req, res, outerMiddlewares,
6513
6481
  config,
6514
6482
  trustedProxy,
6515
6483
  registries,
6516
- preMatched,
6517
- resourcesDir
6484
+ preMatched
6518
6485
  );
6519
6486
  ctx = prepared.ctx;
6520
6487
  meta = prepared.meta;
@@ -6590,8 +6557,8 @@ function applyPluginWrappers(server, handlerWrappers, upgradeWrappers) {
6590
6557
  }
6591
6558
 
6592
6559
  // src/cli/generateRoutes.ts
6593
- import fs18 from "fs";
6594
- import path22 from "path";
6560
+ import fs17 from "fs";
6561
+ import path21 from "path";
6595
6562
  async function hydrateRoutes(manifest) {
6596
6563
  const hydrateRoute = (serialized) => ({
6597
6564
  method: serialized.method,
@@ -6635,18 +6602,18 @@ function createIdleTaskDriver() {
6635
6602
  }
6636
6603
 
6637
6604
  // src/cli/loadPlugins.ts
6638
- import path24 from "path";
6639
- import fs20 from "fs";
6605
+ import path23 from "path";
6606
+ import fs19 from "fs";
6640
6607
  import { pathToFileURL as pathToFileURL3 } from "url";
6641
6608
 
6642
6609
  // src/cli/compileConfig.ts
6643
- import path23 from "path";
6644
- import fs19 from "fs";
6610
+ import path22 from "path";
6611
+ import fs18 from "fs";
6645
6612
  async function compileProjectModules(entryPoints, rootDir, dist) {
6646
6613
  const { insideFiles, outsideFiles } = await collectRelativeImports(entryPoints, rootDir);
6647
6614
  const esbuild = await import("esbuild");
6648
6615
  const aliasPlugins = buildAliasPlugins(rootDir);
6649
- const absDist = path23.resolve(rootDir, dist);
6616
+ const absDist = path22.resolve(rootDir, dist);
6650
6617
  await esbuild.build({
6651
6618
  entryPoints: [...entryPoints, ...outsideFiles],
6652
6619
  outdir: absDist,
@@ -6660,7 +6627,7 @@ async function compileProjectModules(entryPoints, rootDir, dist) {
6660
6627
  logLevel: "silent"
6661
6628
  });
6662
6629
  if (insideFiles.length > 0) {
6663
- const appOutbase = path23.resolve(rootDir, "src");
6630
+ const appOutbase = path22.resolve(rootDir, "src");
6664
6631
  await esbuild.build({
6665
6632
  entryPoints: insideFiles,
6666
6633
  outdir: absDist,
@@ -6741,30 +6708,30 @@ async function loadPlugins(declarations, ctx, rootDir, dist) {
6741
6708
  var TS_EXTS = /\.(ts|tsx|mts|cts)$/;
6742
6709
  var JS_EXTS = /\.(js|mjs|cjs|jsx)$/;
6743
6710
  function resolveLocalPluginSource(specifier, baseDir) {
6744
- const base = path24.isAbsolute(specifier) ? specifier : path24.resolve(baseDir, specifier);
6745
- if ((TS_EXTS.test(base) || JS_EXTS.test(base)) && fs20.existsSync(base)) return base;
6711
+ const base = path23.isAbsolute(specifier) ? specifier : path23.resolve(baseDir, specifier);
6712
+ if ((TS_EXTS.test(base) || JS_EXTS.test(base)) && fs19.existsSync(base)) return base;
6746
6713
  for (const ext of [".ts", ".js"]) {
6747
- if (fs20.existsSync(base + ext)) return base + ext;
6714
+ if (fs19.existsSync(base + ext)) return base + ext;
6748
6715
  }
6749
6716
  for (const indexExt of ["/index.ts", "/index.js"]) {
6750
- if (fs20.existsSync(base + indexExt)) return base + indexExt;
6717
+ if (fs19.existsSync(base + indexExt)) return base + indexExt;
6751
6718
  }
6752
6719
  return null;
6753
6720
  }
6754
6721
  function mirrorProductPath(sourcePath, baseDir, distDir) {
6755
- let rel = path24.relative(baseDir, sourcePath).replace(/\\/g, "/");
6722
+ let rel = path23.relative(baseDir, sourcePath).replace(/\\/g, "/");
6756
6723
  if (rel.startsWith("src/")) rel = rel.slice(4);
6757
- return path24.resolve(distDir, rel.replace(TS_EXTS, ".js"));
6724
+ return path23.resolve(distDir, rel.replace(TS_EXTS, ".js"));
6758
6725
  }
6759
6726
  async function importPluginModule(specifier, baseDir, dist) {
6760
6727
  const isRelative = specifier.startsWith("./") || specifier.startsWith("../");
6761
- if (!isRelative && !path24.isAbsolute(specifier)) {
6728
+ if (!isRelative && !path23.isAbsolute(specifier)) {
6762
6729
  return import(specifier);
6763
6730
  }
6764
- const distDir = dist ? path24.resolve(baseDir, dist) : null;
6731
+ const distDir = dist ? path23.resolve(baseDir, dist) : null;
6765
6732
  const sourcePath = resolveLocalPluginSource(specifier, baseDir);
6766
6733
  const productPath = sourcePath && distDir ? mirrorProductPath(sourcePath, baseDir, distDir) : null;
6767
- if (productPath !== null && fs20.existsSync(productPath) && (sourcePath === null || isProductFresh(sourcePath, productPath))) {
6734
+ if (productPath !== null && fs19.existsSync(productPath) && (sourcePath === null || isProductFresh(sourcePath, productPath))) {
6768
6735
  return import(pathToFileURL3(productPath).href);
6769
6736
  }
6770
6737
  if (sourcePath && TS_EXTS.test(sourcePath)) {
@@ -6773,13 +6740,13 @@ async function importPluginModule(specifier, baseDir, dist) {
6773
6740
  `Local plugin "${specifier}" has no up-to-date build artifact (dist is stale or missing). Run "faapi build" first, or use "faapi dev" for on-demand compilation.`
6774
6741
  );
6775
6742
  }
6776
- const relFromRoot = path24.relative(baseDir, sourcePath).replace(/\\/g, "/");
6743
+ const relFromRoot = path23.relative(baseDir, sourcePath).replace(/\\/g, "/");
6777
6744
  if (relFromRoot.startsWith("src/")) {
6778
6745
  await ensureCompiled(sourcePath, baseDir, dist);
6779
6746
  } else {
6780
6747
  await compileProjectModules([sourcePath], baseDir, dist);
6781
6748
  }
6782
- if (productPath && fs20.existsSync(productPath)) {
6749
+ if (productPath && fs19.existsSync(productPath)) {
6783
6750
  return import(pathToFileURL3(productPath).href);
6784
6751
  }
6785
6752
  }
@@ -6791,7 +6758,7 @@ async function importPluginModule(specifier, baseDir, dist) {
6791
6758
  `${specifier}/index.ts`,
6792
6759
  `${specifier}.js`,
6793
6760
  `${specifier}/index.js`
6794
- ].map((c) => path24.isAbsolute(c) ? c : path24.join(baseDir, c));
6761
+ ].map((c) => path23.isAbsolute(c) ? c : path23.join(baseDir, c));
6795
6762
  throw new Error(
6796
6763
  `Cannot find local plugin "${specifier}" (resolved from ${baseDir}). Expected one of:
6797
6764
  ${candidates.join("\n ")}
@@ -6816,11 +6783,11 @@ function resolveDeclaration(decl) {
6816
6783
  }
6817
6784
 
6818
6785
  // src/cli/manifestLoader.ts
6819
- import fs21 from "fs";
6820
- import path27 from "path";
6786
+ import fs20 from "fs";
6787
+ import path26 from "path";
6821
6788
 
6822
6789
  // src/cli/generateAgentArtifacts.ts
6823
- import path25 from "path";
6790
+ import path24 from "path";
6824
6791
 
6825
6792
  // src/ast/extractAgentMetadata.ts
6826
6793
  import ts11 from "typescript";
@@ -7137,9 +7104,9 @@ function validateAgentList(metadata) {
7137
7104
  }
7138
7105
  async function generateAgentArtifacts(agents, rootDir, dist) {
7139
7106
  const metadata = [];
7140
- const programByFile = createPrograms(agents.map((m) => path25.resolve(rootDir, m.filePath)));
7107
+ const programByFile = createPrograms(agents.map((m) => path24.resolve(rootDir, m.filePath)));
7141
7108
  for (const manifest of agents) {
7142
- const absPath = path25.resolve(rootDir, manifest.filePath);
7109
+ const absPath = path24.resolve(rootDir, manifest.filePath);
7143
7110
  const program = programByFile.get(absPath);
7144
7111
  const result = extractAgentMetadata(program, absPath, {
7145
7112
  name: manifest.name,
@@ -7154,14 +7121,14 @@ async function generateAgentArtifacts(agents, rootDir, dist) {
7154
7121
  }
7155
7122
  validateAgentList(metadata);
7156
7123
  const serialized = serializeAgents(metadata, dist);
7157
- const agentsPath = path25.resolve(rootDir, dist, AGENTS_FILE);
7124
+ const agentsPath = path24.resolve(rootDir, dist, AGENTS_FILE);
7158
7125
  await writeAgentsModule(serialized, agentsPath);
7159
7126
  return metadata;
7160
7127
  }
7161
7128
 
7162
7129
  // src/cli/generateTaskArtifacts.ts
7163
7130
  init_generateZodArtifacts();
7164
- import path26 from "path";
7131
+ import path25 from "path";
7165
7132
  init_createProgram();
7166
7133
  init_atomicWrite();
7167
7134
  init_extractHandlerTypes();
@@ -7199,7 +7166,7 @@ function collectTaskSchemaSources(tasks, rootDir) {
7199
7166
  const tasksByFile = /* @__PURE__ */ new Map();
7200
7167
  for (const task of tasks) {
7201
7168
  if (!task.inputTypeName) continue;
7202
- const absPath = path26.resolve(rootDir, task.filePath);
7169
+ const absPath = path25.resolve(rootDir, task.filePath);
7203
7170
  let list = tasksByFile.get(absPath);
7204
7171
  if (!list) {
7205
7172
  list = [];
@@ -7256,9 +7223,9 @@ function generateTaskSchemaFileSource(sources, resolveType, helpersImportPath) {
7256
7223
  async function generateTaskArtifacts(manifests, rootDir, dist) {
7257
7224
  const metadata = [];
7258
7225
  if (manifests.length > 0) {
7259
- const programByFile = createPrograms(manifests.map((m) => path26.resolve(rootDir, m.filePath)));
7226
+ const programByFile = createPrograms(manifests.map((m) => path25.resolve(rootDir, m.filePath)));
7260
7227
  for (const manifest of manifests) {
7261
- const absPath = path26.resolve(rootDir, manifest.filePath);
7228
+ const absPath = path25.resolve(rootDir, manifest.filePath);
7262
7229
  const result = extractToolMetadata(programByFile.get(absPath), absPath, "run", {
7263
7230
  name: manifest.name,
7264
7231
  filePath: manifest.filePath
@@ -7269,7 +7236,7 @@ async function generateTaskArtifacts(manifests, rootDir, dist) {
7269
7236
  }
7270
7237
  }
7271
7238
  const serialized = serializeTasks(manifests, dist);
7272
- const tasksPath = path26.resolve(rootDir, dist, TASKS_FILE);
7239
+ const tasksPath = path25.resolve(rootDir, dist, TASKS_FILE);
7273
7240
  await writeTasksModule(serialized, tasksPath);
7274
7241
  if (metadata.length === 0) {
7275
7242
  return hydrateTasks(serialized);
@@ -7291,8 +7258,8 @@ async function generateTaskArtifacts(manifests, rootDir, dist) {
7291
7258
  var TOOLS_FILE2 = "faapi-tools.js";
7292
7259
  var AGENTS_FILE2 = "faapi-agents.js";
7293
7260
  async function loadAndHydrateTools(rootDir, dist, registries = defaultRegistries) {
7294
- const toolsPath = path27.resolve(rootDir, dist, TOOLS_FILE2);
7295
- if (!fs21.existsSync(toolsPath)) {
7261
+ const toolsPath = path26.resolve(rootDir, dist, TOOLS_FILE2);
7262
+ if (!fs20.existsSync(toolsPath)) {
7296
7263
  return [];
7297
7264
  }
7298
7265
  const serialized = await importWithCacheBust(toolsPath);
@@ -7301,8 +7268,8 @@ async function loadAndHydrateTools(rootDir, dist, registries = defaultRegistries
7301
7268
  return hydrated;
7302
7269
  }
7303
7270
  async function loadAndHydrateAgents(rootDir, dist, registries = defaultRegistries) {
7304
- const agentsPath = path27.resolve(rootDir, dist, AGENTS_FILE2);
7305
- if (!fs21.existsSync(agentsPath)) {
7271
+ const agentsPath = path26.resolve(rootDir, dist, AGENTS_FILE2);
7272
+ if (!fs20.existsSync(agentsPath)) {
7306
7273
  return [];
7307
7274
  }
7308
7275
  const serialized = await importWithCacheBust(agentsPath);
@@ -7317,8 +7284,8 @@ function getTaskDriverOptions(config) {
7317
7284
  return void 0;
7318
7285
  }
7319
7286
  async function loadAndHydrateTasks(rootDir, dist, registries = defaultRegistries) {
7320
- const tasksPath = path27.resolve(rootDir, dist, TASKS_FILE);
7321
- if (!fs21.existsSync(tasksPath)) {
7287
+ const tasksPath = path26.resolve(rootDir, dist, TASKS_FILE);
7288
+ if (!fs20.existsSync(tasksPath)) {
7322
7289
  return [];
7323
7290
  }
7324
7291
  const serialized = await importWithCacheBust(tasksPath);
@@ -7449,6 +7416,14 @@ function performInject(server, injectOpts) {
7449
7416
  });
7450
7417
  }
7451
7418
 
7419
+ // src/cli/copyResources.ts
7420
+ import path27 from "path";
7421
+ import fs21 from "fs";
7422
+ var RESOURCES_OUTPUT_DIR = "resources";
7423
+ function resolveResourcesDir(rootDir, dist) {
7424
+ return path27.resolve(rootDir, dist, RESOURCES_OUTPUT_DIR);
7425
+ }
7426
+
7452
7427
  // src/cli/createAppCore.ts
7453
7428
  var DEFAULT_DIST = "dist";
7454
7429
  var DEFAULT_PORT = 3e3;
@@ -7580,7 +7555,6 @@ async function createAppBase(options) {
7580
7555
  config?.plugins,
7581
7556
  {
7582
7557
  rootDir,
7583
- resourcesDir,
7584
7558
  registries,
7585
7559
  routes: sorted,
7586
7560
  getRoutes: () => sorted,
@@ -7611,8 +7585,7 @@ async function createAppBase(options) {
7611
7585
  routes: sorted,
7612
7586
  server,
7613
7587
  registries,
7614
- tasks: taskQueue,
7615
- resourcesDir
7588
+ tasks: taskQueue
7616
7589
  });
7617
7590
  console.log("- onBoot hook executed");
7618
7591
  } catch (err) {
@@ -7647,8 +7620,7 @@ async function createAppBase(options) {
7647
7620
  routes: sorted,
7648
7621
  server,
7649
7622
  registries,
7650
- tasks: taskQueue,
7651
- resourcesDir
7623
+ tasks: taskQueue
7652
7624
  });
7653
7625
  console.log("- onReady hook executed");
7654
7626
  }
@@ -7672,8 +7644,7 @@ async function createAppBase(options) {
7672
7644
  routes: sorted,
7673
7645
  server,
7674
7646
  registries,
7675
- tasks: taskQueue,
7676
- resourcesDir
7647
+ tasks: taskQueue
7677
7648
  });
7678
7649
  }
7679
7650
  registries.tool.clear();