@faapi/faapi 6.31.0 → 6.33.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/testing.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { F as FaapiContext } from './contextTypes-BKQsSVMv.js';
2
- import { F as FaapiMiddleware, I as InjectorMap, R as RouteManifest, W as WsRouteManifest, C as CorsOptions, H as HelmetOptions } from './routeTypes-Cc0P3CcU.js';
1
+ import { g as FaapiContext, F as FaapiMiddleware, w as InjectorMap, R as RouteManifest, W as WsRouteManifest, r as CorsOptions, H as HelmetOptions } from './contextTypes-D1ORxB1P.js';
3
2
  import { Server } from 'node:http';
4
3
  import { WebSocket } from 'ws';
4
+ import 'node:net';
5
5
 
6
6
  /**
7
7
  * 测试专用:从选项对象创建 FaapiContext,免去手写 `new Request(url)` 的样板代码
package/dist/testing.js CHANGED
@@ -429,11 +429,7 @@ function formatEntry(entry) {
429
429
  const plain = Object.fromEntries(
430
430
  Object.entries(entry.fields).map(([k, v]) => [k, serializeFieldValue(v)])
431
431
  );
432
- try {
433
- line += ` ${JSON.stringify(plain)}`;
434
- } catch (err) {
435
- line += ` [unserializable fields: ${err instanceof Error ? err.message : String(err)}]`;
436
- }
432
+ line += ` ${stringifyJson(plain)}`;
437
433
  }
438
434
  return line;
439
435
  }
@@ -947,6 +943,8 @@ var PARAM_TYPE_MAP = {
947
943
  // 任务子系统:TaskClient(入队/查询)
948
944
  log: "log",
949
945
  // 请求级日志器(ctx.log 同一实例:scope http,自动带 requestId 等字段)
946
+ llm: "llm",
947
+ // 轻量 LLM 补全通道(@faapi/agent 插件注册到 registries.llm;未加载时 undefined)
950
948
  // raw 系:恒原始输入(无 schema、无校验、管线永不转换),与 query/params/body
951
949
  // 的「校验转换后」口径二分互补
952
950
  rawQuery: "rawQuery",
@@ -1190,6 +1188,20 @@ function createAgentHandleStore() {
1190
1188
  }
1191
1189
  };
1192
1190
  }
1191
+ function createLlmChannelStore() {
1192
+ let current = null;
1193
+ return {
1194
+ register(channel) {
1195
+ current = channel;
1196
+ },
1197
+ get() {
1198
+ return current ?? void 0;
1199
+ },
1200
+ clear() {
1201
+ current = null;
1202
+ }
1203
+ };
1204
+ }
1193
1205
  function createTaskHandleStore() {
1194
1206
  let currentFactory = null;
1195
1207
  return {
@@ -1212,7 +1224,8 @@ function createAppRegistries() {
1212
1224
  const task = createTaskRegistry();
1213
1225
  const agentHandle = createAgentHandleStore();
1214
1226
  const taskHandle = createTaskHandleStore();
1215
- return { tool, agent, skill, task, agentHandle, taskHandle };
1227
+ const llm = createLlmChannelStore();
1228
+ return { tool, agent, skill, task, agentHandle, taskHandle, llm };
1216
1229
  }
1217
1230
  var defaultRegistries = createAppRegistries();
1218
1231
 
@@ -1276,6 +1289,10 @@ function getBuiltinInjectionValue(type, ctx, body) {
1276
1289
  // 任务子系统:注入 TaskClient(入队/查询);未注册工厂(无 app 编排)时 undefined
1277
1290
  case "tasks":
1278
1291
  return ctx.registries ? ctx.registries.taskHandle.get(ctx) : void 0;
1292
+ // 轻量 LLM 补全通道:@faapi/agent 插件注册到 registries.llm;与请求上下文无关,
1293
+ // get 无参。插件未加载(或编程式直调 ctx 无 registries)时 undefined
1294
+ case "llm":
1295
+ return ctx.registries ? ctx.registries.llm.get() : void 0;
1279
1296
  // 请求级日志器:与 ctx.log 同一实例(scope http,自动带 requestId/method/path 字段)
1280
1297
  case "log":
1281
1298
  return ctx.log;
@@ -1499,38 +1516,30 @@ function setCachedMiddlewares(absPath, bundle) {
1499
1516
  middlewareCache.set(absPath, bundle);
1500
1517
  }
1501
1518
  async function loadMiddlewaresFile(filePath) {
1502
- let module;
1503
- try {
1504
- module = await importWithCacheBust(filePath);
1505
- } catch (err) {
1506
- console.error(
1507
- `[faapi] Failed to load middlewares from ${filePath}:`,
1508
- err instanceof Error ? err.stack ?? err.message : err
1509
- );
1510
- return { middlewares: [], injectors: {} };
1511
- }
1519
+ const module = await importWithCacheBust(filePath);
1512
1520
  const middlewares = module.default ?? module.middlewares ?? [];
1513
1521
  if (!Array.isArray(middlewares)) {
1514
- console.warn(`[faapi] middlewares.ts \u5E94\u5BFC\u51FA\u6570\u7EC4\uFF0C\u5DF2\u5FFD\u7565: ${filePath}`);
1515
- return { middlewares: [], injectors: {} };
1522
+ throw new TypeError(
1523
+ `[faapi] middlewares.ts must export an array (default or named "middlewares"): ${filePath}`
1524
+ );
1516
1525
  }
1517
- const validMiddlewares = middlewares.filter((m) => {
1526
+ const validMiddlewares = [];
1527
+ for (const m of middlewares) {
1518
1528
  if (typeof m !== "function") {
1519
- console.warn(`[faapi] \u65E0\u6548\u7684\u4E2D\u95F4\u4EF6\u9879\uFF08\u5E94\u4E3A\u51FD\u6570\uFF09\uFF0C\u5DF2\u5FFD\u7565: ${typeof m}`);
1520
- return false;
1529
+ throw new TypeError(
1530
+ `[faapi] every middleware must be a function, got ${typeof m}: ${filePath}`
1531
+ );
1521
1532
  }
1522
- return true;
1523
- });
1533
+ validMiddlewares.push(m);
1534
+ }
1524
1535
  const injectors = module.injectors ?? {};
1525
1536
  if (typeof injectors !== "object" || injectors === null) {
1526
- console.warn(`[faapi] injectors \u5E94\u5BFC\u51FA\u5BF9\u8C61\uFF0C\u5DF2\u5FFD\u7565: ${filePath}`);
1527
- return { middlewares: validMiddlewares, injectors: {} };
1537
+ throw new TypeError(`[faapi] "injectors" export must be an object: ${filePath}`);
1528
1538
  }
1529
1539
  const validInjectors = {};
1530
1540
  for (const [name, injector] of Object.entries(injectors)) {
1531
1541
  if (typeof injector !== "function") {
1532
- console.warn(`[faapi] \u6CE8\u5165\u5668 ${name} \u5E94\u4E3A\u51FD\u6570\uFF0C\u5DF2\u5FFD\u7565`);
1533
- continue;
1542
+ throw new TypeError(`[faapi] injector "${name}" must be a function: ${filePath}`);
1534
1543
  }
1535
1544
  validInjectors[name] = injector;
1536
1545
  }
@@ -1545,10 +1554,16 @@ async function loadMergedMiddlewares(middlewarePaths) {
1545
1554
  if (bundle === void 0) {
1546
1555
  let loading = inFlight.get(absMwPath);
1547
1556
  if (!loading) {
1548
- loading = loadMiddlewaresFile(absMwPath).then((result) => {
1549
- setCachedMiddlewares(absMwPath, result);
1550
- return result;
1551
- });
1557
+ loading = loadMiddlewaresFile(absMwPath).then(
1558
+ (result) => {
1559
+ setCachedMiddlewares(absMwPath, result);
1560
+ return result;
1561
+ },
1562
+ (err) => {
1563
+ inFlight.delete(absMwPath);
1564
+ throw err;
1565
+ }
1566
+ );
1552
1567
  inFlight.set(absMwPath, loading);
1553
1568
  }
1554
1569
  bundle = await loading;
@@ -3732,11 +3747,7 @@ async function ensureMiddlewaresCompiled(middlewarePaths, rootDir) {
3732
3747
  if (!dist) return;
3733
3748
  for (const mwPath of middlewarePaths) {
3734
3749
  const sourcePath = prodPathToSourcePath(mwPath, rootDir, dist);
3735
- try {
3736
- await ensureCompiled(sourcePath, rootDir, dist);
3737
- } catch (err) {
3738
- console.error(`[faapi] Failed to compile middleware source ${sourcePath}:`, err);
3739
- }
3750
+ await ensureCompiled(sourcePath, rootDir, dist);
3740
3751
  }
3741
3752
  }
3742
3753
  function prodSourcePathToProductPath(sourceAbsPath, rootDir, dist) {
@@ -5256,7 +5267,8 @@ async function sendErrorResponse(err, meta, res, onError, ctx) {
5256
5267
  if (onError && ctx) {
5257
5268
  try {
5258
5269
  await onError(err, ctx);
5259
- } catch {
5270
+ } catch (hookErr) {
5271
+ console.error("[faapi] lifecycle onError hook threw:", hookErr);
5260
5272
  }
5261
5273
  }
5262
5274
  }