@faapi/faapi 6.32.0 → 6.34.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.
@@ -1,4 +1,4 @@
1
- import { E as LlmConfig, B as LlmComplete, ad as TaskRegistriesSnapshot, e as AgentMetadata, f as ToolMetadata, A as AgentCore, K as LogLevel } from './contextTypes-WKsf3cCE.js';
1
+ import { G as LlmConfig, D as LlmComplete, al as TaskRegistriesSnapshot, e as AgentMetadata, f as ToolMetadata, A as AgentCore, k as TaskClient, M as LogLevel } from './contextTypes-Bsc1ljvn.js';
2
2
  import 'node:http';
3
3
  import 'node:net';
4
4
 
@@ -79,9 +79,9 @@ declare function serializeError(err: unknown): SerializedWorkerError;
79
79
  * 同一解析来源,业务方安装即可用)。specifier 变量拼接避免主包静态依赖
80
80
  * `@faapi/agent`(与 loadTaskDriver 加载驱动子包同策略)。
81
81
  *
82
- * 降级路径(已记入 fallback.md):`@faapi/agent` 未安装/不可解析时 `console.warn`
83
- * 留痕并返回 `undefined`——taskCtx.llm 为 undefined,任务自身决定报错或旁路;
84
- * llms 未配置时不触发加载。
82
+ * 显式失败口径(不降级):llms 已配置但 `@faapi/agent` 不可解析(未安装/导出
83
+ * 缺失)→ 抛错(含安装指引),任务失败——配置声明了能力而环境不能交付属环境
84
+ * 错误,fail fast;llms 未配置时返回 `undefined`(能力不存在,非降级),任务照常执行。
85
85
  */
86
86
  declare function buildLlmChannel(llms?: Record<string, LlmConfig>): Promise<LlmComplete | undefined>;
87
87
  /**
@@ -90,9 +90,9 @@ declare function buildLlmChannel(llms?: Record<string, LlmConfig>): Promise<LlmC
90
90
  * sink 输出(语义与主包 createLogger 对齐:child scope `:` 合并、调用处 fields
91
91
  * 覆盖构造字段;格式化在宿主侧,不跨线程复制格式代码)。
92
92
  *
93
- * fields 含不可克隆值时丢弃 fields、保底 level/message/scope(降级已记入
94
- * fallback.md)——日志永不中断任务执行,与 progress 的"不可克隆按执行错误处理"
95
- * 不同。
93
+ * fields 含不可克隆值时按执行错误处理(与 progress 同语义,不降级)——一条日志的
94
+ * 字段失败终止任务执行:显式失败优于静默丢字段,业务侧将 fields 保持为可克隆
95
+ * 纯数据即可避免。
96
96
  */
97
97
  declare function createTaskLogger(level?: LogLevel, scope?: string, fields?: Record<string, unknown>): {
98
98
  debug: (m: string, f?: Record<string, unknown>) => void;
@@ -101,5 +101,26 @@ declare function createTaskLogger(level?: LogLevel, scope?: string, fields?: Rec
101
101
  error: (m: string, f?: Record<string, unknown>) => void;
102
102
  child: (cs: string) => /*elided*/ any;
103
103
  };
104
+ /**
105
+ * 隔离任务 taskCtx.tasks 代理工厂(worker 侧)
106
+ *
107
+ * 全方法经 `{ type: 'tasks-call', seq, method, args }` 消息回传宿主执行,宿主以
108
+ * `{ type: 'tasks-result', seq, ok, value | error }` 回传——按 seq 匹配挂起调用。
109
+ * 参数与返回值须可结构化克隆(不可克隆按调用错误抛出,与 progress/log 同口径,
110
+ * 不静默);挂起的调用随任务超时两段式取消(terminate)一并终止,无独立超时。
111
+ *
112
+ * 纯函数形态(send/handleMessage 注入):真实 worker 传 parentPort.postMessage,
113
+ * 单测直接构造(与 buildRegistriesView 同款可测性)。
114
+ */
115
+ declare function buildTasksProxy(send: (msg: Record<string, unknown>) => void): {
116
+ proxy: TaskClient;
117
+ handleMessage: (msg: {
118
+ type?: string;
119
+ seq?: number;
120
+ ok?: boolean;
121
+ value?: unknown;
122
+ error?: SerializedWorkerError;
123
+ }) => boolean;
124
+ };
104
125
 
105
- export { type SerializedWorkerError, type WorkerEntryData, buildLlmChannel, buildRegistriesView, createTaskLogger, serializeError };
126
+ export { type SerializedWorkerError, type WorkerEntryData, buildLlmChannel, buildRegistriesView, buildTasksProxy, createTaskLogger, serializeError };
@@ -68,24 +68,24 @@ var LOG_RANK = { debug: 0, info: 1, warn: 2, error: 3 };
68
68
  async function buildLlmChannel(llms) {
69
69
  if (!llms || Object.keys(llms).length === 0) return void 0;
70
70
  const specifier = "@faapi/agent";
71
+ let mod;
71
72
  try {
72
- const mod = await import(
73
+ mod = await import(
73
74
  /* @vite-ignore */
74
75
  specifier
75
76
  );
76
- if (typeof mod.createLightComplete !== "function") {
77
- console.warn(
78
- "[faapi] @faapi/agent resolved but does not export createLightComplete() \u2014 taskCtx.llm unavailable (check package version)"
79
- );
80
- return void 0;
81
- }
82
- return mod.createLightComplete({ llms });
83
- } catch {
84
- console.warn(
85
- "[faapi] agent.llms is configured but @faapi/agent is not resolvable in the task worker \u2014 install @faapi/agent to enable taskCtx.llm (task execution continues)"
77
+ } catch (err) {
78
+ throw new Error(
79
+ `[faapi] agent.llms is configured but @faapi/agent is not resolvable in the task worker \u2014 install @faapi/agent to enable taskCtx.llm (${err instanceof Error ? err.message : String(err)})`,
80
+ { cause: err }
81
+ );
82
+ }
83
+ if (typeof mod.createLightComplete !== "function") {
84
+ throw new Error(
85
+ "[faapi] @faapi/agent resolved but does not export createLightComplete() \u2014 taskCtx.llm unavailable (check package version)"
86
86
  );
87
- return void 0;
88
87
  }
88
+ return mod.createLightComplete({ llms });
89
89
  }
90
90
  function createTaskLogger(level, scope, fields) {
91
91
  const make = (suffix) => {
@@ -99,9 +99,11 @@ function createTaskLogger(level, scope, fields) {
99
99
  }
100
100
  try {
101
101
  parentPort?.postMessage({ type: "log", entry });
102
- } catch {
103
- entry.fields = { warning: "log fields not cloneable across worker boundary, dropped" };
104
- parentPort?.postMessage({ type: "log", entry });
102
+ } catch (err) {
103
+ throw new Error(
104
+ `task log fields are not cloneable across the worker boundary: ${err instanceof Error ? err.message : String(err)}. Keep log fields plain data (strings / numbers / plain objects).`,
105
+ { cause: err }
106
+ );
105
107
  }
106
108
  };
107
109
  return {
@@ -114,17 +116,63 @@ function createTaskLogger(level, scope, fields) {
114
116
  };
115
117
  return make(void 0);
116
118
  }
119
+ function buildTasksProxy(send) {
120
+ let seq = 0;
121
+ const pending = /* @__PURE__ */ new Map();
122
+ const call = (method, args) => new Promise((resolve, reject) => {
123
+ const s = ++seq;
124
+ pending.set(s, { resolve, reject, method });
125
+ try {
126
+ send({ type: "tasks-call", seq: s, method, args });
127
+ } catch (err) {
128
+ pending.delete(s);
129
+ reject(
130
+ new Error(
131
+ `taskCtx.tasks.${method} arguments are not cloneable across the worker boundary: ${err instanceof Error ? err.message : String(err)}. Keep arguments plain data (strings / numbers / plain objects).`,
132
+ { cause: err }
133
+ )
134
+ );
135
+ }
136
+ });
137
+ return {
138
+ proxy: {
139
+ enqueue: (name, payload, opts) => call("enqueue", [name, payload, opts]),
140
+ enqueueGroup: (name, payloads, opts) => call("enqueueGroup", [name, payloads, opts]),
141
+ getGroup: (groupId) => call("getGroup", [groupId]),
142
+ list: (name) => call("list", [name]),
143
+ listQueued: (name) => call("listQueued", [name]),
144
+ cancel: (name, id) => call("cancel", [name, id]),
145
+ retry: (name, id) => call("retry", [name, id])
146
+ },
147
+ handleMessage: (msg) => {
148
+ if (msg?.type !== "tasks-result") return false;
149
+ const entry = msg.seq !== void 0 ? pending.get(msg.seq) : void 0;
150
+ if (!entry) return true;
151
+ pending.delete(msg.seq);
152
+ if (msg.ok) {
153
+ entry.resolve(msg.value);
154
+ } else {
155
+ const err = new Error(msg.error?.message ?? `taskCtx.tasks.${entry.method} failed`);
156
+ if (msg.error?.name !== void 0) err.name = msg.error.name;
157
+ entry.reject(err);
158
+ }
159
+ return true;
160
+ }
161
+ };
162
+ }
117
163
  function bootstrap() {
118
164
  if (!parentPort) return;
119
165
  const data = workerData;
120
166
  if (data.resourcesDir) {
121
167
  globalThis[/* @__PURE__ */ Symbol.for("faapi.resources.dir")] = data.resourcesDir;
122
168
  }
169
+ const tasksProxy = buildTasksProxy((msg) => parentPort?.postMessage(msg));
123
170
  let controller = null;
124
171
  let modulePromise = null;
125
172
  parentPort.on(
126
173
  "message",
127
174
  (msg) => {
175
+ if (tasksProxy.handleMessage(msg)) return;
128
176
  if (msg?.type === "abort") {
129
177
  controller?.abort(new Error(msg.reason));
130
178
  return;
@@ -156,6 +204,7 @@ function bootstrap() {
156
204
  const result = await run(payload, {
157
205
  ...taskCtx,
158
206
  signal: controller.signal,
207
+ tasks: tasksProxy.proxy,
159
208
  registries,
160
209
  llm,
161
210
  progress,
@@ -166,12 +215,12 @@ function bootstrap() {
166
215
  const serialized = serializeError(err);
167
216
  try {
168
217
  parentPort?.postMessage({ type: "error", error: serialized });
169
- } catch {
218
+ } catch (cloneErr) {
170
219
  parentPort?.postMessage({
171
220
  type: "error",
172
221
  error: {
173
222
  name: serialized.name,
174
- message: serialized.message,
223
+ message: `task error props are not cloneable (custom enumerable properties of the thrown error cannot cross the worker boundary): ${serialized.name}: ${serialized.message}. Clone failure: ${cloneErr instanceof Error ? cloneErr.message : String(cloneErr)}. Make error props plain data (string codes / numbers), not functions or class instances.`,
175
224
  stack: serialized.stack,
176
225
  props: {}
177
226
  }
@@ -186,6 +235,7 @@ bootstrap();
186
235
  export {
187
236
  buildLlmChannel,
188
237
  buildRegistriesView,
238
+ buildTasksProxy,
189
239
  createTaskLogger,
190
240
  serializeError
191
241
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/task/workerEntry.ts"],"sourcesContent":["import { parentPort, workerData } from 'node:worker_threads';\nimport type { TaskRegistriesSnapshot } from './taskTypes';\nimport type { LlmComplete } from '../injection/llmTypes';\nimport type { LlmConfig } from '../config/configTypes';\nimport type { LogEntry, LogLevel } from '../logger/loggerTypes';\n\n/**\n * 任务隔离 worker 的真实入口文件(tsup 独立入口 → dist/workerEntry.js)\n *\n * 为什么是独立文件而不是宿主生成的 data URL:data URL 模块无法解析裸说明符\n * ('@faapi/faapi'),framework 侧 helper 只能以字符串模板内联(typecheck 覆盖\n * 不到、需对照测试锚定漂移),且求值顺序需人肉控制;真实入口文件是隔离执行的\n * 通行形态(vitest / bullmq / piscina 同款)——入口自身的语句先于对用户任务\n * 模块的动态 import 执行,\"读取根播种先于任务模块求值\"由结构保证。\n *\n * 本文件自包含:值导入仅 node:worker_threads,其余全部 type-only(类型剥离后\n * 擦除)——vitest 场景宿主会回退到 src 源文件直跑(resolveWorkerEntryUrl,见\n * taskWorker.ts),无相对导入链才无扩展名解析问题。读取根经 globalThis +\n * Symbol.for 承载而非模块状态:入口 bundle 与 index bundle 是两份代码副本,\n * globalThis 是唯一跨副本共享面(symbol key 与 utils/readResource 的\n * 'faapi.resources.dir' 一致,两处字面量需同步,readResource.test.ts 契约测试\n * 锚定)。主线程 import 本模块仅取导出的纯函数(bootstrap 被 parentPort 守卫),\n * 真实 worker 由 taskWorker.ts 创建。\n */\n\n/** workerData 契约(taskWorker.ts 构造 worker 时传入) */\nexport interface WorkerEntryData {\n /** 任务产物模块 file:// URL(首次 run 消息时动态 import) */\n moduleUrl: string;\n /** 产物 resources 目录绝对路径(缺省不播种——readResource 未绑定即显式抛错) */\n resourcesDir?: string;\n}\n\n/**\n * sub-agent 派发工具名前缀(与 injection/subAgentToolName.ts 的 SUB_AGENT_TOOL_PREFIX\n * 同步——本文件自包含不可值导入,taskWorker.test.ts 断言完整派发名锚定漂移)。\n * 快照内的 agent 名来自文件注册表(scanAgents 构建期已校验字符集),直拼即合法。\n */\nconst SUB_AGENT_TOOL_PREFIX = 'agent-';\n\n/** worker 错误回传负载(serializeError 的产物,宿主 reviveError 重建) */\nexport interface SerializedWorkerError {\n name: string;\n message: string;\n stack: string | undefined;\n props: Record<string, unknown>;\n}\n\n/**\n * worker 内重建注册表只读视图(语义与宿主 createTaskRegistriesView 一致:\n * 不存在的 tool/agent 名静默跳过、resolveAgentTools 按解析后 name 去重)\n *\n * 快照为纯数据(函数闭包不可跨线程),视图在 worker 内重建。\n */\nexport function buildRegistriesView(snapshot?: TaskRegistriesSnapshot) {\n const agents = new Map((snapshot?.agents ?? []).map((a) => [a.name, a] as const));\n const tools = new Map((snapshot?.tools ?? []).map((t) => [t.name, t] as const));\n const skills = new Map((snapshot?.skills ?? []).map((s) => [s.name, s] as const));\n return {\n agent: {\n getAgent: (name: string) => agents.get(name),\n getAgentEntry: (name: string) => agents.get(name),\n listAgents: () => Array.from(agents.values()),\n asTool: (name: string) => {\n const agent = agents.get(name);\n if (!agent) return undefined;\n return {\n kind: 'agent' as const,\n name: `${SUB_AGENT_TOOL_PREFIX}${agent.name}`,\n agentName: agent.name,\n description: agent.description,\n metadata: agent,\n };\n },\n resolveAgentTools: (name: string) => {\n const agent = agents.get(name);\n const result = new Map<string, TaskRegistriesSnapshot['tools'][number]>();\n if (agent?.tools) {\n for (const toolName of agent.tools) {\n const resolved = tools.get(toolName);\n if (resolved) result.set(resolved.name, resolved);\n }\n }\n return Array.from(result.values());\n },\n resolveSubAgents: (name: string) => {\n const agent = agents.get(name);\n const result: TaskRegistriesSnapshot['agents'] = [];\n if (agent?.agents) {\n for (const subName of agent.agents) {\n const sub = agents.get(subName);\n if (sub) result.push(sub);\n }\n }\n return result;\n },\n },\n tool: {\n get: (name: string) => tools.get(name),\n list: () => Array.from(tools.values()),\n },\n skill: {\n get: (name: string) => skills.get(name),\n list: () => Array.from(skills.values()),\n },\n };\n}\n\n/**\n * worker 内错误序列化(错误保真):Error 按 `{ name, message, stack, props }` 回传——\n * `props` 收集自定义可枚举属性(业务错误类的 code/statusCode 等),宿主侧 reviveError\n * 重建时回填;非 Error 值按 String(err) 归一。结构化克隆只保 message(name/自定义\n * 属性丢失、stack 重新生成),不序列化就无法跨线程保真。\n */\nexport function serializeError(err: unknown): SerializedWorkerError {\n if (err instanceof Error) {\n const props: Record<string, unknown> = {};\n for (const key of Object.keys(err)) {\n props[key] = (err as unknown as Record<string, unknown>)[key];\n }\n return { name: err.name, message: err.message, stack: err.stack, props };\n }\n return { name: 'Error', message: String(err), stack: undefined, props: {} };\n}\n\nconst LOG_RANK: Record<LogLevel, number> = { debug: 0, info: 1, warn: 2, error: 3 };\n\n/**\n * worker 内重建轻量 LLM 补全通道(隔离任务路径)\n *\n * channel 是函数闭包不可跨线程;`agent.llms` 是纯数据——postMessage 传入后在本\n * 函数内动态加载 `@faapi/agent` 重建实例(与 task.ts 内 import '@faapi/agent'\n * 同一解析来源,业务方安装即可用)。specifier 变量拼接避免主包静态依赖\n * `@faapi/agent`(与 loadTaskDriver 加载驱动子包同策略)。\n *\n * 降级路径(已记入 fallback.md):`@faapi/agent` 未安装/不可解析时 `console.warn`\n * 留痕并返回 `undefined`——taskCtx.llm 为 undefined,任务自身决定报错或旁路;\n * llms 未配置时不触发加载。\n */\nexport async function buildLlmChannel(\n llms?: Record<string, LlmConfig>,\n): Promise<LlmComplete | undefined> {\n if (!llms || Object.keys(llms).length === 0) return undefined;\n const specifier = '@faapi/' + 'agent';\n try {\n const mod = (await import(/* @vite-ignore */ specifier)) as {\n createLightComplete?: (deps: { llms: Record<string, LlmConfig> }) => LlmComplete;\n };\n if (typeof mod.createLightComplete !== 'function') {\n console.warn(\n '[faapi] @faapi/agent resolved but does not export createLightComplete() — taskCtx.llm unavailable (check package version)',\n );\n return undefined;\n }\n return mod.createLightComplete({ llms });\n } catch {\n console.warn(\n '[faapi] agent.llms is configured but @faapi/agent is not resolvable in the task worker — install @faapi/agent to enable taskCtx.llm (task execution continues)',\n );\n return undefined;\n }\n}\n\n/**\n * 任务日志器:级别预过滤(level 为 undefined 时不过滤——宿主文件管道默认全量)+\n * scope/fields 组装,条目作为纯数据经 `{ type: 'log' }` 消息回传宿主、由宿主统一\n * sink 输出(语义与主包 createLogger 对齐:child scope `:` 合并、调用处 fields\n * 覆盖构造字段;格式化在宿主侧,不跨线程复制格式代码)。\n *\n * fields 含不可克隆值时丢弃 fields、保底 level/message/scope(降级已记入\n * fallback.md)——日志永不中断任务执行,与 progress 的\"不可克隆按执行错误处理\"\n * 不同。\n */\nexport function createTaskLogger(\n level?: LogLevel,\n scope?: string,\n fields?: Record<string, unknown>,\n) {\n const make = (suffix?: string) => {\n const write = (lvl: LogLevel, message: string, callFields?: Record<string, unknown>) => {\n if (level !== undefined && LOG_RANK[lvl] < LOG_RANK[level]) return;\n const entry: LogEntry = { level: lvl, message, time: new Date().toISOString() };\n const fullScope =\n suffix === undefined ? scope : scope === undefined ? suffix : `${scope}:${suffix}`;\n if (fullScope !== undefined) entry.scope = fullScope;\n if (fields !== undefined || callFields !== undefined) {\n entry.fields = { ...fields, ...callFields };\n }\n try {\n parentPort?.postMessage({ type: 'log', entry });\n } catch {\n entry.fields = { warning: 'log fields not cloneable across worker boundary, dropped' };\n parentPort?.postMessage({ type: 'log', entry });\n }\n };\n return {\n debug: (m: string, f?: Record<string, unknown>) => write('debug', m, f),\n info: (m: string, f?: Record<string, unknown>) => write('info', m, f),\n warn: (m: string, f?: Record<string, unknown>) => write('warn', m, f),\n error: (m: string, f?: Record<string, unknown>) => write('error', m, f),\n child: (cs: string) => make(suffix === undefined ? cs : `${suffix}:${cs}`),\n };\n };\n return make(undefined);\n}\n\n/**\n * worker 侧 bootstrap:播种读取根 + 桥接 run 消息\n *\n * 仅在 worker 线程执行(主线程 import 本模块时 parentPort 为空,只取上面的纯\n * 函数)。任务模块在首次 run 消息时才动态 import(modulePromise 缓存)——播种\n * 语句先于它执行,任务模块顶层代码(top-level await 调用 readResource)读到\n * 的绑定必然已就位。\n */\nfunction bootstrap(): void {\n if (!parentPort) return;\n const data = workerData as WorkerEntryData;\n\n // 播种全局 readResource 读取根(缺省不播种——直接构造队列的测试/嵌入场景,\n // readResource 未绑定即显式抛错)\n if (data.resourcesDir) {\n (globalThis as Record<symbol, string | undefined>)[Symbol.for('faapi.resources.dir')] =\n data.resourcesDir;\n }\n\n let controller: AbortController | null = null;\n let modulePromise: Promise<{ run?: (payload: unknown, taskCtx: unknown) => unknown }> | null =\n null;\n\n parentPort.on(\n 'message',\n (msg: {\n type?: string;\n reason?: string;\n payload?: unknown;\n taskCtx?: Record<string, unknown>;\n registries?: TaskRegistriesSnapshot;\n llms?: Record<string, LlmConfig>;\n log?: { level?: LogLevel; scope?: string; fields?: Record<string, unknown> };\n }) => {\n if (msg?.type === 'abort') {\n controller?.abort(new Error(msg.reason));\n return;\n }\n if (msg?.type !== 'run') return;\n controller = new AbortController();\n const { payload, taskCtx } = msg;\n void (async () => {\n try {\n modulePromise ??= import(data.moduleUrl);\n const mod = await modulePromise;\n const run = mod.run;\n if (typeof run !== 'function') {\n parentPort?.postMessage({\n type: 'error',\n error: {\n name: 'Error',\n message: 'Task module has no run export',\n stack: undefined,\n props: {},\n },\n });\n return;\n }\n const registries = buildRegistriesView(msg.registries);\n const progress = (value: unknown) => parentPort?.postMessage({ type: 'progress', value });\n const taskLog = msg.log\n ? createTaskLogger(msg.log.level, msg.log.scope, msg.log.fields)\n : undefined;\n // 轻量补全通道:llms 快照在 worker 内重建(不可解析时 undefined,warn 留痕)\n const llm = await buildLlmChannel(msg.llms);\n const result = await run(payload, {\n ...taskCtx,\n signal: controller!.signal,\n registries,\n llm,\n progress,\n log: taskLog,\n });\n parentPort?.postMessage({ type: 'done', result });\n } catch (err) {\n const serialized = serializeError(err);\n try {\n parentPort?.postMessage({ type: 'error', error: serialized });\n } catch {\n // props 含不可克隆值(函数等)时丢弃 props,保底 name/message/stack\n parentPort?.postMessage({\n type: 'error',\n error: {\n name: serialized.name,\n message: serialized.message,\n stack: serialized.stack,\n props: {},\n },\n });\n }\n }\n })();\n },\n );\n}\n\nbootstrap();\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/task/workerEntry.ts"],"sourcesContent":["import { parentPort, workerData } from 'node:worker_threads';\nimport type { TaskRegistriesSnapshot, TaskClient } from './taskTypes';\nimport type { LlmComplete } from '../injection/llmTypes';\nimport type { LlmConfig } from '../config/configTypes';\nimport type { LogEntry, LogLevel } from '../logger/loggerTypes';\n\n/**\n * 任务隔离 worker 的真实入口文件(tsup 独立入口 → dist/workerEntry.js)\n *\n * 为什么是独立文件而不是宿主生成的 data URL:data URL 模块无法解析裸说明符\n * ('@faapi/faapi'),framework 侧 helper 只能以字符串模板内联(typecheck 覆盖\n * 不到、需对照测试锚定漂移),且求值顺序需人肉控制;真实入口文件是隔离执行的\n * 通行形态(vitest / bullmq / piscina 同款)——入口自身的语句先于对用户任务\n * 模块的动态 import 执行,\"读取根播种先于任务模块求值\"由结构保证。\n *\n * 本文件自包含:值导入仅 node:worker_threads,其余全部 type-only(类型剥离后\n * 擦除)——vitest 场景宿主会回退到 src 源文件直跑(resolveWorkerEntryUrl,见\n * taskWorker.ts),无相对导入链才无扩展名解析问题。读取根经 globalThis +\n * Symbol.for 承载而非模块状态:入口 bundle 与 index bundle 是两份代码副本,\n * globalThis 是唯一跨副本共享面(symbol key 与 utils/readResource 的\n * 'faapi.resources.dir' 一致,两处字面量需同步,readResource.test.ts 契约测试\n * 锚定)。主线程 import 本模块仅取导出的纯函数(bootstrap 被 parentPort 守卫),\n * 真实 worker 由 taskWorker.ts 创建。\n */\n\n/** workerData 契约(taskWorker.ts 构造 worker 时传入) */\nexport interface WorkerEntryData {\n /** 任务产物模块 file:// URL(首次 run 消息时动态 import) */\n moduleUrl: string;\n /** 产物 resources 目录绝对路径(缺省不播种——readResource 未绑定即显式抛错) */\n resourcesDir?: string;\n}\n\n/**\n * sub-agent 派发工具名前缀(与 injection/subAgentToolName.ts 的 SUB_AGENT_TOOL_PREFIX\n * 同步——本文件自包含不可值导入,taskWorker.test.ts 断言完整派发名锚定漂移)。\n * 快照内的 agent 名来自文件注册表(scanAgents 构建期已校验字符集),直拼即合法。\n */\nconst SUB_AGENT_TOOL_PREFIX = 'agent-';\n\n/** worker 错误回传负载(serializeError 的产物,宿主 reviveError 重建) */\nexport interface SerializedWorkerError {\n name: string;\n message: string;\n stack: string | undefined;\n props: Record<string, unknown>;\n}\n\n/**\n * worker 内重建注册表只读视图(语义与宿主 createTaskRegistriesView 一致:\n * 不存在的 tool/agent 名静默跳过、resolveAgentTools 按解析后 name 去重)\n *\n * 快照为纯数据(函数闭包不可跨线程),视图在 worker 内重建。\n */\nexport function buildRegistriesView(snapshot?: TaskRegistriesSnapshot) {\n const agents = new Map((snapshot?.agents ?? []).map((a) => [a.name, a] as const));\n const tools = new Map((snapshot?.tools ?? []).map((t) => [t.name, t] as const));\n const skills = new Map((snapshot?.skills ?? []).map((s) => [s.name, s] as const));\n return {\n agent: {\n getAgent: (name: string) => agents.get(name),\n getAgentEntry: (name: string) => agents.get(name),\n listAgents: () => Array.from(agents.values()),\n asTool: (name: string) => {\n const agent = agents.get(name);\n if (!agent) return undefined;\n return {\n kind: 'agent' as const,\n name: `${SUB_AGENT_TOOL_PREFIX}${agent.name}`,\n agentName: agent.name,\n description: agent.description,\n metadata: agent,\n };\n },\n resolveAgentTools: (name: string) => {\n const agent = agents.get(name);\n const result = new Map<string, TaskRegistriesSnapshot['tools'][number]>();\n if (agent?.tools) {\n for (const toolName of agent.tools) {\n const resolved = tools.get(toolName);\n if (resolved) result.set(resolved.name, resolved);\n }\n }\n return Array.from(result.values());\n },\n resolveSubAgents: (name: string) => {\n const agent = agents.get(name);\n const result: TaskRegistriesSnapshot['agents'] = [];\n if (agent?.agents) {\n for (const subName of agent.agents) {\n const sub = agents.get(subName);\n if (sub) result.push(sub);\n }\n }\n return result;\n },\n },\n tool: {\n get: (name: string) => tools.get(name),\n list: () => Array.from(tools.values()),\n },\n skill: {\n get: (name: string) => skills.get(name),\n list: () => Array.from(skills.values()),\n },\n };\n}\n\n/**\n * worker 内错误序列化(错误保真):Error 按 `{ name, message, stack, props }` 回传——\n * `props` 收集自定义可枚举属性(业务错误类的 code/statusCode 等),宿主侧 reviveError\n * 重建时回填;非 Error 值按 String(err) 归一。结构化克隆只保 message(name/自定义\n * 属性丢失、stack 重新生成),不序列化就无法跨线程保真。\n */\nexport function serializeError(err: unknown): SerializedWorkerError {\n if (err instanceof Error) {\n const props: Record<string, unknown> = {};\n for (const key of Object.keys(err)) {\n props[key] = (err as unknown as Record<string, unknown>)[key];\n }\n return { name: err.name, message: err.message, stack: err.stack, props };\n }\n return { name: 'Error', message: String(err), stack: undefined, props: {} };\n}\n\nconst LOG_RANK: Record<LogLevel, number> = { debug: 0, info: 1, warn: 2, error: 3 };\n\n/**\n * worker 内重建轻量 LLM 补全通道(隔离任务路径)\n *\n * channel 是函数闭包不可跨线程;`agent.llms` 是纯数据——postMessage 传入后在本\n * 函数内动态加载 `@faapi/agent` 重建实例(与 task.ts 内 import '@faapi/agent'\n * 同一解析来源,业务方安装即可用)。specifier 变量拼接避免主包静态依赖\n * `@faapi/agent`(与 loadTaskDriver 加载驱动子包同策略)。\n *\n * 显式失败口径(不降级):llms 已配置但 `@faapi/agent` 不可解析(未安装/导出\n * 缺失)→ 抛错(含安装指引),任务失败——配置声明了能力而环境不能交付属环境\n * 错误,fail fast;llms 未配置时返回 `undefined`(能力不存在,非降级),任务照常执行。\n */\nexport async function buildLlmChannel(\n llms?: Record<string, LlmConfig>,\n): Promise<LlmComplete | undefined> {\n if (!llms || Object.keys(llms).length === 0) return undefined;\n const specifier = '@faapi/' + 'agent';\n let mod: {\n createLightComplete?: (deps: { llms: Record<string, LlmConfig> }) => LlmComplete;\n };\n try {\n mod = (await import(/* @vite-ignore */ specifier)) as typeof mod;\n } catch (err) {\n throw new Error(\n '[faapi] agent.llms is configured but @faapi/agent is not resolvable in the task worker — ' +\n `install @faapi/agent to enable taskCtx.llm (${err instanceof Error ? err.message : String(err)})`,\n { cause: err },\n );\n }\n if (typeof mod.createLightComplete !== 'function') {\n throw new Error(\n '[faapi] @faapi/agent resolved but does not export createLightComplete() — ' +\n 'taskCtx.llm unavailable (check package version)',\n );\n }\n return mod.createLightComplete({ llms });\n}\n\n/**\n * 任务日志器:级别预过滤(level 为 undefined 时不过滤——宿主文件管道默认全量)+\n * scope/fields 组装,条目作为纯数据经 `{ type: 'log' }` 消息回传宿主、由宿主统一\n * sink 输出(语义与主包 createLogger 对齐:child scope `:` 合并、调用处 fields\n * 覆盖构造字段;格式化在宿主侧,不跨线程复制格式代码)。\n *\n * fields 含不可克隆值时按执行错误处理(与 progress 同语义,不降级)——一条日志的\n * 字段失败终止任务执行:显式失败优于静默丢字段,业务侧将 fields 保持为可克隆\n * 纯数据即可避免。\n */\nexport function createTaskLogger(\n level?: LogLevel,\n scope?: string,\n fields?: Record<string, unknown>,\n) {\n const make = (suffix?: string) => {\n const write = (lvl: LogLevel, message: string, callFields?: Record<string, unknown>) => {\n if (level !== undefined && LOG_RANK[lvl] < LOG_RANK[level]) return;\n const entry: LogEntry = { level: lvl, message, time: new Date().toISOString() };\n const fullScope =\n suffix === undefined ? scope : scope === undefined ? suffix : `${scope}:${suffix}`;\n if (fullScope !== undefined) entry.scope = fullScope;\n if (fields !== undefined || callFields !== undefined) {\n entry.fields = { ...fields, ...callFields };\n }\n try {\n parentPort?.postMessage({ type: 'log', entry });\n } catch (err) {\n throw new Error(\n `task log fields are not cloneable across the worker boundary: ` +\n `${err instanceof Error ? err.message : String(err)}. ` +\n 'Keep log fields plain data (strings / numbers / plain objects).',\n { cause: err },\n );\n }\n };\n return {\n debug: (m: string, f?: Record<string, unknown>) => write('debug', m, f),\n info: (m: string, f?: Record<string, unknown>) => write('info', m, f),\n warn: (m: string, f?: Record<string, unknown>) => write('warn', m, f),\n error: (m: string, f?: Record<string, unknown>) => write('error', m, f),\n child: (cs: string) => make(suffix === undefined ? cs : `${suffix}:${cs}`),\n };\n };\n return make(undefined);\n}\n\n/**\n * 隔离任务 taskCtx.tasks 代理工厂(worker 侧)\n *\n * 全方法经 `{ type: 'tasks-call', seq, method, args }` 消息回传宿主执行,宿主以\n * `{ type: 'tasks-result', seq, ok, value | error }` 回传——按 seq 匹配挂起调用。\n * 参数与返回值须可结构化克隆(不可克隆按调用错误抛出,与 progress/log 同口径,\n * 不静默);挂起的调用随任务超时两段式取消(terminate)一并终止,无独立超时。\n *\n * 纯函数形态(send/handleMessage 注入):真实 worker 传 parentPort.postMessage,\n * 单测直接构造(与 buildRegistriesView 同款可测性)。\n */\nexport function buildTasksProxy(send: (msg: Record<string, unknown>) => void): {\n proxy: TaskClient;\n handleMessage: (msg: {\n type?: string;\n seq?: number;\n ok?: boolean;\n value?: unknown;\n error?: SerializedWorkerError;\n }) => boolean;\n} {\n let seq = 0;\n const pending = new Map<\n number,\n { resolve: (value: unknown) => void; reject: (err: Error) => void; method: string }\n >();\n\n const call = (method: string, args: unknown[]): Promise<unknown> =>\n new Promise((resolve, reject) => {\n const s = ++seq;\n pending.set(s, { resolve, reject, method });\n try {\n send({ type: 'tasks-call', seq: s, method, args });\n } catch (err) {\n pending.delete(s);\n reject(\n new Error(\n `taskCtx.tasks.${method} arguments are not cloneable across the worker boundary: ` +\n `${err instanceof Error ? err.message : String(err)}. ` +\n 'Keep arguments plain data (strings / numbers / plain objects).',\n { cause: err },\n ),\n );\n }\n });\n\n return {\n proxy: {\n enqueue: (name, payload, opts) =>\n call('enqueue', [name, payload, opts]) as ReturnType<TaskClient['enqueue']>,\n enqueueGroup: (name, payloads, opts) =>\n call('enqueueGroup', [name, payloads, opts]) as ReturnType<TaskClient['enqueueGroup']>,\n getGroup: (groupId) => call('getGroup', [groupId]) as ReturnType<TaskClient['getGroup']>,\n list: (name) => call('list', [name]) as unknown as ReturnType<TaskClient['list']>,\n listQueued: (name) =>\n call('listQueued', [name]) as unknown as ReturnType<TaskClient['listQueued']>,\n cancel: (name, id) => call('cancel', [name, id]) as ReturnType<TaskClient['cancel']>,\n retry: (name, id) => call('retry', [name, id]) as ReturnType<TaskClient['retry']>,\n },\n handleMessage: (msg) => {\n if (msg?.type !== 'tasks-result') return false;\n const entry = msg.seq !== undefined ? pending.get(msg.seq) : undefined;\n if (!entry) return true; // 迟到/未知 seq(取消终止后到达)——忽略\n pending.delete(msg.seq!);\n if (msg.ok) {\n entry.resolve(msg.value);\n } else {\n const err = new Error(msg.error?.message ?? `taskCtx.tasks.${entry.method} failed`);\n if (msg.error?.name !== undefined) err.name = msg.error.name;\n entry.reject(err);\n }\n return true;\n },\n };\n}\n\n/**\n * worker 侧 bootstrap:播种读取根 + 桥接 run 消息\n *\n * 仅在 worker 线程执行(主线程 import 本模块时 parentPort 为空,只取上面的纯\n * 函数)。任务模块在首次 run 消息时才动态 import(modulePromise 缓存)——播种\n * 语句先于它执行,任务模块顶层代码(top-level await 调用 readResource)读到\n * 的绑定必然已就位。\n */\nfunction bootstrap(): void {\n if (!parentPort) return;\n const data = workerData as WorkerEntryData;\n\n // 播种全局 readResource 读取根(缺省不播种——直接构造队列的测试/嵌入场景,\n // readResource 未绑定即显式抛错)\n if (data.resourcesDir) {\n (globalThis as Record<symbol, string | undefined>)[Symbol.for('faapi.resources.dir')] =\n data.resourcesDir;\n }\n\n // taskCtx.tasks 代理:全方法经消息回传宿主(onTasksCall 分派到队列本体)\n const tasksProxy = buildTasksProxy((msg) => parentPort?.postMessage(msg));\n\n let controller: AbortController | null = null;\n let modulePromise: Promise<{ run?: (payload: unknown, taskCtx: unknown) => unknown }> | null =\n null;\n\n parentPort.on(\n 'message',\n (msg: {\n type?: string;\n reason?: string;\n payload?: unknown;\n /** 隔离任务仅含 job——worker 线程不接收进程 config */\n taskCtx?: { job?: { id: string; name: string; attempt: number } };\n registries?: TaskRegistriesSnapshot;\n llms?: Record<string, LlmConfig>;\n log?: { level?: LogLevel; scope?: string; fields?: Record<string, unknown> };\n }) => {\n if (tasksProxy.handleMessage(msg as Parameters<typeof tasksProxy.handleMessage>[0])) return;\n if (msg?.type === 'abort') {\n controller?.abort(new Error(msg.reason));\n return;\n }\n if (msg?.type !== 'run') return;\n controller = new AbortController();\n const { payload, taskCtx } = msg;\n void (async () => {\n try {\n modulePromise ??= import(data.moduleUrl);\n const mod = await modulePromise;\n const run = mod.run;\n if (typeof run !== 'function') {\n parentPort?.postMessage({\n type: 'error',\n error: {\n name: 'Error',\n message: 'Task module has no run export',\n stack: undefined,\n props: {},\n },\n });\n return;\n }\n const registries = buildRegistriesView(msg.registries);\n const progress = (value: unknown) => parentPort?.postMessage({ type: 'progress', value });\n const taskLog = msg.log\n ? createTaskLogger(msg.log.level, msg.log.scope, msg.log.fields)\n : undefined;\n // 轻量补全通道:llms 快照在 worker 内重建(不可解析时 undefined,warn 留痕)\n const llm = await buildLlmChannel(msg.llms);\n const result = await run(payload, {\n ...taskCtx,\n signal: controller!.signal,\n tasks: tasksProxy.proxy,\n registries,\n llm,\n progress,\n log: taskLog,\n });\n parentPort?.postMessage({ type: 'done', result });\n } catch (err) {\n const serialized = serializeError(err);\n try {\n parentPort?.postMessage({ type: 'error', error: serialized });\n } catch (cloneErr) {\n // props 含不可克隆值(函数等):任务显式失败,不静默丢属性——宿主必须\n // 知道错误的自定义属性无法跨线程传递(错误信息含原 name/message 与修复指引)\n parentPort?.postMessage({\n type: 'error',\n error: {\n name: serialized.name,\n message:\n `task error props are not cloneable (custom enumerable properties of the ` +\n `thrown error cannot cross the worker boundary): ${serialized.name}: ` +\n `${serialized.message}. Clone failure: ` +\n `${cloneErr instanceof Error ? cloneErr.message : String(cloneErr)}. ` +\n 'Make error props plain data (string codes / numbers), not functions or class instances.',\n stack: serialized.stack,\n props: {},\n },\n });\n }\n }\n })();\n },\n );\n}\n\nbootstrap();\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@faapi/faapi",
3
- "version": "6.32.0",
3
+ "version": "6.34.0",
4
4
  "description": "函数即接口 - Function as API",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",