@faapi/faapi 6.29.0 → 6.30.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.d.ts CHANGED
@@ -480,15 +480,6 @@ interface AgentConfig {
480
480
  * 详见 `@faapi/agent` 的 [trace](../../agent/src/trace.md) 文档。
481
481
  */
482
482
  enableTracing?: boolean;
483
- /**
484
- * 执行守卫(authHooks,见 @faapi/agent 的 authHooks 文档)
485
- *
486
- * 每次 tool / sub-agent 执行前调用(`agent.x` 名称为 sub-agent 递归)。
487
- * 三种返回:`void` 放行;`{ error }` 拒绝(不执行,error 回传 LLM 调整策略);
488
- * `{ args }` 改写后放行(多租户场景强制注入可信值,不信 LLM 传入的标识参数)。
489
- *
490
- * 典型用法:中间件解析 `ctx.workspace` 后在此校验/强制改写 `args.workspaceId`。
491
- */
492
483
  /**
493
484
  * 发送给 LLM 的历史 token 预算(近似估算,未设置 = 不裁剪)
494
485
  *
@@ -498,7 +489,20 @@ interface AgentConfig {
498
489
  * reactLoop 文档历史裁剪章节。
499
490
  */
500
491
  maxHistoryTokens?: number;
501
- beforeToolCall?: (name: string, args: Record<string, unknown>, ctx: FaapiContext | undefined) => void | {
492
+ /**
493
+ * 执行守卫(authHooks,见 @faapi/agent 的 authHooks 文档)
494
+ *
495
+ * 每次 tool / sub-agent 执行前调用(`agent-x` 派发名称为 sub-agent 递归)。
496
+ * 三种返回:`void` 放行;`{ error }` 拒绝(不执行,error 回传 LLM 调整策略);
497
+ * `{ args }` 改写后放行(多租户场景强制注入可信值,不信 LLM 传入的标识参数)。
498
+ *
499
+ * ctx 为请求上下文透传(`Partial<FaapiContext>`,框架零读取):HTTP 请求是完整
500
+ * ctx,任务内组装 Agent 时业务方显式传窄对象(如鉴权硬闸需要的
501
+ * `{ currentUserId }`),编程式直调为 undefined。
502
+ *
503
+ * 典型用法:中间件解析 `ctx.workspace` 后在此校验/强制改写 `args.workspaceId`。
504
+ */
505
+ beforeToolCall?: (name: string, args: Record<string, unknown>, ctx: Partial<FaapiContext> | undefined) => void | {
502
506
  error: string;
503
507
  } | {
504
508
  args: Record<string, unknown>;
@@ -507,7 +511,7 @@ interface AgentConfig {
507
511
  * 审计钩子(authHooks):tool / sub-agent 成功返回后调用,返回值忽略。
508
512
  * 用于日志/审计/计量;异常路径不调用。
509
513
  */
510
- afterToolCall?: (name: string, args: Record<string, unknown>, result: unknown, ctx: FaapiContext | undefined) => void;
514
+ afterToolCall?: (name: string, args: Record<string, unknown>, result: unknown, ctx: Partial<FaapiContext> | undefined) => void;
511
515
  /**
512
516
  * 可见性过滤(authHooks):LLM 可见 tools 清单组装完成后调用,
513
517
  * 返回过滤后的数组(含 agent-as-tool 项)。每次 agent.run / stream 生效——
@@ -523,7 +527,7 @@ interface AgentConfig {
523
527
  description?: string;
524
528
  parameters?: Record<string, unknown>;
525
529
  };
526
- }>, ctx: FaapiContext | undefined) => Array<{
530
+ }>, ctx: Partial<FaapiContext> | undefined) => Array<{
527
531
  type: 'function';
528
532
  function: {
529
533
  name: string;
package/dist/index.js CHANGED
@@ -2864,6 +2864,34 @@ var CONCURRENCY_RE = new RegExp(`(?:^|\\n)\\s*concurrency:\\s*${NUM_LITERAL}`);
2864
2864
  var RETRIES_RE = new RegExp(`(?:^|\\n)\\s*retries:\\s*${NUM_LITERAL}`);
2865
2865
  var TIMEOUT_MS_RE = new RegExp(`(?:^|\\n)\\s*timeoutMs:\\s*${NUM_LITERAL}`);
2866
2866
  var GRACE_MS_RE = new RegExp(`(?:^|\\n)\\s*graceMs:\\s*${NUM_LITERAL}`);
2867
+ var NUMERIC_META_FIELDS = ["concurrency", "retries", "timeoutMs", "graceMs"];
2868
+ var STRING_META_FIELDS = ["cron"];
2869
+ var ALL_META_FIELDS = [...NUMERIC_META_FIELDS, ...STRING_META_FIELDS];
2870
+ function detectIgnoredMetaFields(source, strictHit) {
2871
+ const declared = /* @__PURE__ */ new Set();
2872
+ for (const line of source.split("\n")) {
2873
+ const trimmed = line.trim();
2874
+ if (trimmed.startsWith("//")) continue;
2875
+ for (const field of ALL_META_FIELDS) {
2876
+ if (new RegExp(`\\b${field}\\s*:`).test(trimmed)) declared.add(field);
2877
+ }
2878
+ }
2879
+ return ALL_META_FIELDS.filter((field) => declared.has(field) && !strictHit[field]);
2880
+ }
2881
+ function warnIgnoredMetaFields(name, fields) {
2882
+ for (const field of fields) {
2883
+ if (STRING_META_FIELDS.includes(field)) {
2884
+ console.warn(
2885
+ `[faapi] Task "${name}" declares "${field}" but its value is not a string literal \u2014 the declaration was ignored and the task will not be cron-scheduled. Meta values are extracted from source code without importing it, so only literal values are recognized: use a quoted literal (cron: '0 3 * * *'), not an expression or a dynamic value.`
2886
+ );
2887
+ } else {
2888
+ const consequence = field === "timeoutMs" ? " and the task will run in-process with no timeout" : "";
2889
+ console.warn(
2890
+ `[faapi] Task "${name}" declares "${field}" but its value is not a numeric literal \u2014 the declaration was ignored${consequence}. Meta values are extracted from source code without importing it, so only literal values are recognized (underscores allowed, e.g. 1_800_000); expressions like 30 * 60_000 or dynamic values are not supported.`
2891
+ );
2892
+ }
2893
+ }
2894
+ }
2867
2895
  function parseNumericLiteral(raw) {
2868
2896
  return Number(raw.replace(/_/g, ""));
2869
2897
  }
@@ -2925,6 +2953,14 @@ async function scanTasks(rootDir, patterns) {
2925
2953
  manifest.timeoutMs = value;
2926
2954
  }
2927
2955
  if (graceMs !== void 0) manifest.graceMs = parseNumericLiteral(graceMs);
2956
+ const strictHit = {
2957
+ cron: cron !== void 0,
2958
+ concurrency: concurrency !== void 0,
2959
+ retries: retries !== void 0,
2960
+ timeoutMs: timeoutMs !== void 0,
2961
+ graceMs: graceMs !== void 0
2962
+ };
2963
+ warnIgnoredMetaFields(name, detectIgnoredMetaFields(source, strictHit));
2928
2964
  tasks.push(manifest);
2929
2965
  }
2930
2966
  return tasks.sort((a, b) => a.name.localeCompare(b.name));