agenttaskflow 0.0.1 → 0.4.2

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.
Files changed (59) hide show
  1. package/README.md +262 -3
  2. package/dist/agent.d.ts +69 -0
  3. package/dist/agent.js +189 -0
  4. package/dist/agent.js.map +1 -0
  5. package/dist/cli.d.ts +2 -0
  6. package/dist/cli.js +54 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/connection.d.ts +37 -0
  9. package/dist/connection.js +313 -0
  10. package/dist/connection.js.map +1 -0
  11. package/dist/errors.d.ts +14 -0
  12. package/dist/errors.js +15 -0
  13. package/dist/errors.js.map +1 -0
  14. package/dist/events.d.ts +24 -0
  15. package/dist/events.js +60 -0
  16. package/dist/events.js.map +1 -0
  17. package/dist/flow.d.ts +10 -0
  18. package/dist/flow.js +32 -0
  19. package/dist/flow.js.map +1 -0
  20. package/dist/index.d.ts +6 -0
  21. package/dist/index.js +6 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/loader.d.ts +1 -0
  24. package/dist/loader.js +41 -0
  25. package/dist/loader.js.map +1 -0
  26. package/dist/runner.d.ts +1 -0
  27. package/dist/runner.js +13 -0
  28. package/dist/runner.js.map +1 -0
  29. package/dist/state.d.ts +17 -0
  30. package/dist/state.js +92 -0
  31. package/dist/state.js.map +1 -0
  32. package/dist/sync.d.ts +31 -0
  33. package/dist/sync.js +151 -0
  34. package/dist/sync.js.map +1 -0
  35. package/dist/transport.d.ts +33 -0
  36. package/dist/transport.js +211 -0
  37. package/dist/transport.js.map +1 -0
  38. package/dist/worker.d.ts +1 -0
  39. package/dist/worker.js +55 -0
  40. package/dist/worker.js.map +1 -0
  41. package/docs/validation.md +27 -0
  42. package/docs/workflow-authoring.md +80 -0
  43. package/examples/common.ts +9 -0
  44. package/examples/multi-fields.ts +45 -0
  45. package/examples/review.ts +24 -0
  46. package/examples/simple.ts +16 -0
  47. package/examples/smoke.ts +41 -0
  48. package/package.json +19 -6
  49. package/test/README.md +37 -0
  50. package/test/RESULTS.md +27 -0
  51. package/test/branches.ts +23 -0
  52. package/test/context.ts +18 -0
  53. package/test/correction.ts +20 -0
  54. package/test/loop.ts +30 -0
  55. package/test/modules.ts +12 -0
  56. package/test/multi-fields.ts +22 -0
  57. package/test/run.ts +55 -0
  58. package/test/shared.ts +15 -0
  59. package/index.js +0 -1
package/README.md CHANGED
@@ -1,5 +1,264 @@
1
- # agenttaskflow
1
+ # AgentTaskFlow
2
2
 
3
- Persistent task workflows inside your existing Claude Code or Codex session.
3
+ ## atf 命令行
4
4
 
5
- This package name is reserved. The first release is coming soon.
5
+ 包名是 `agenttaskflow`,命令名是 **`atf`**。npm 上的 `atf` 已是另一个 CSS 工具,不能用 `npm install -g atf` 安装本项目。
6
+
7
+ 本地安装当前开发版本(Node.js 22.15+):
8
+
9
+ ```bash
10
+ cd /Users/maple/workbench/agenttaskflow
11
+ nvm use
12
+ npm run build
13
+ npm install -g .
14
+ atf examples/simple.ts
15
+ atf examples/multi-fields.ts
16
+ atf examples/smoke.ts --command cxh --rounds 5
17
+ ```
18
+
19
+ 从 npm 安装:`npm install -g agenttaskflow`(需要 Node.js 22.15+)。
20
+
21
+ `atf 文件.ts` 执行普通 TS/JS 文件,保留当前工作目录,文件名之后的参数原样交给流程。支持相对 import、顶层 await 和导出的 `main(args)` 入口;`main` 若存在会在文件加载完成后调用一次。直接调用 `flow(...)` 的现有脚本无需改写。不做类型检查,需要时运行项目自己的 `tsc`。执行器通过 esbuild 编译 TS,没有新造流程语言。
22
+
23
+ 独立文件可以直接 `import { flow } from 'agenttaskflow'`;优先使用项目本地依赖,找不到时回退到 atf 安装中的 AgentTaskFlow 和 Zod。其它业务依赖仍由项目正常安装。`atf --help` 查看用法,`atf --version` 查看版本。
24
+
25
+ 用普通 TypeScript 脚本控制 Codex 和 Claude Code。**没有 DSL、没有 `.flow` 文件、没有自定义语法。默认同步 API 不需要 `async/await`。**
26
+
27
+ `step()` 等当前步骤完成后返回结果。一次 flow 只启动一个 CLI 进程,循环、分支和格式补答都复用它。终端按顺序显示:**当前步骤 → 实际输入 → agent 实时输出 → 完成/失败**。
28
+
29
+ ```ts
30
+ import { flow } from 'agenttaskflow';
31
+
32
+ flow('cxh', step => {
33
+ // 先生成方案。
34
+ step('设计一个本地待办工具,只给方案,不修改文件。');
35
+
36
+ // 审查通过才继续,最多三轮。
37
+ for (let i = 0; i < 3; i++) {
38
+ if (step.check('方案是否满足全部要求?')) break;
39
+ if (i === 2) throw new Error('三轮后仍未通过');
40
+ step('根据审查意见修订方案');
41
+ }
42
+
43
+ // 汇总已经通过审查的方案。
44
+ step('总结最终方案');
45
+ });
46
+ ```
47
+
48
+ 不需要声明类型、schema、async/await,也不用手动启动和关闭。步骤名称自动取提示词第一行。完整示例见 `examples/simple.ts`,在项目目录执行 `npm run simple`。
49
+
50
+ 需要一次返回多个字段时,运行 `npm run multi-fields`(使用 cxh)。`examples/multi-fields.ts` 演示通过 `step.data` 获取 `passed`、`score`、`problems`、`suggestion` 四个字段,打印结果并按审查意见修订,最多三轮。提示词直接写在示例文件中。
51
+
52
+ 更多可运行流程位于 `test/`,说明见 `test/README.md`。执行 `npm run flows -- --list` 列出流程,`npm run flows -- branches loop` 测试指定流程,`npm run flows -- all` 依次运行全部六个真实 agent 测试。
53
+
54
+ | 调用 | 返回值 |
55
+ | --- | --- |
56
+ | `step('执行任务')` | 回答文本 |
57
+ | `step.check('是否满足要求?')` | `true` / `false` |
58
+ | `step.choose('评估风险', ['low', 'high'])` | 选项之一 |
59
+ | `step.data('提取结果', schema)` | 自定义结构化结果 |
60
+
61
+ `check` 和 `choose` 自动要求结构化输出、校验并在格式错误时提示补答。它们返回模型的判断;涉及文件、测试等可核实事实时,还应由脚本验证实际证据。配置 Claude Code 使用 `flow({ provider: 'claude', command: 'claude' }, step => { /* 流程 */ })`。
62
+
63
+ ## 直接运行
64
+
65
+ 需要 Node.js 22+,以及已经安装、登录的 Codex 或 Claude Code CLI。
66
+
67
+ ```bash
68
+ cd /Users/maple/workbench/agenttaskflow
69
+ nvm use
70
+ npm run smoke -- --provider codex --command cxh --rounds 5
71
+ ```
72
+
73
+ 等价于直接执行普通 TypeScript:
74
+
75
+ ```bash
76
+ npx tsx examples/smoke.ts --provider codex --command cxh --rounds 5
77
+ ```
78
+
79
+ Claude Code:
80
+
81
+ ```bash
82
+ npm run smoke -- --provider claude --command claude --rounds 5
83
+ ```
84
+
85
+ 本地依赖和构建产物已准备好。新检出环境执行 `npm install && npm run build`。
86
+
87
+ 示例先交给 agent 一个随机标记,然后五次回忆。后续输入不再携带标记,脚本检查标记、轮数和 PID。每一轮会调用真实模型,但不要求 agent 读写业务文件。
88
+
89
+ 首次启动 `cxh` 仍可能花时间:包装脚本会预热后端,本机 Node 加载也可能较慢。**默认只预热一次,不会每一步重来。** 示例每步超时默认 600 秒,可用 `--timeout 600` 调整;每 15 秒显示等待状态。若已确认后端就绪,可以使用包装脚本自己的 `CXH_NO_WARM=1` 开关,这不等于修复后端问题。
90
+
91
+ ## 需要更多控制时
92
+
93
+ 需要自定义步骤名、详细结果或 checkpoint 时,使用 `withAgent`。它与 `flow` 使用同一套会话和执行能力:
94
+
95
+ ```ts
96
+ import { z } from 'zod';
97
+ import { withAgent } from 'agenttaskflow';
98
+
99
+ const REVIEW = `审查当前方案。返回 verdict(pass 或 revise)和 reason。`;
100
+ const REVISE = `根据上一轮审查意见修订方案,并报告真实修改。`;
101
+ const Review = z.strictObject({
102
+ verdict: z.enum(['pass', 'revise']),
103
+ reason: z.string(),
104
+ });
105
+
106
+ withAgent({ command: 'cxh' }, agent => {
107
+ // 先生成方案,让后续审查使用同一个上下文。
108
+ agent.run('设计一个本地待办工具,只给方案,不修改文件。', { name: '生成方案' });
109
+
110
+ // 审查通过就结束;否则修订,最多三轮。
111
+ for (let round = 1; round <= 3; round++) {
112
+ const result = agent.run(REVIEW, { name: `审查 ${round}`, schema: Review });
113
+ if (result.verdict === 'pass') break;
114
+ if (round === 3) throw new Error('三轮后仍未通过');
115
+ agent.run(REVISE, { name: `修订 ${round}` });
116
+ }
117
+ });
118
+ ```
119
+
120
+ `withAgent` 在正常结束或抛错后关闭进程。也可以手动管理:
121
+
122
+ ```ts
123
+ import { Agent } from 'agenttaskflow';
124
+
125
+ const agent = new Agent({ command: 'cxh' });
126
+ try {
127
+ const answer = agent.run('说明你的任务', { name: '开始' });
128
+ console.log(answer); // string,不是 Promise
129
+ } finally {
130
+ agent.close();
131
+ }
132
+ ```
133
+
134
+ 业务流程由 TypeScript 的 `if/else`、`for/while`、函数、`try/catch`、`import` 控制,不使用 `next` 变量模拟 goto。
135
+
136
+ **提示词直接写在 `.ts` 文件中的字符串常量或函数里。共享内容放到公共 `.ts` 模块,用正常 import 复用。不要把各种文字拆成一堆小文本文件,不要让 agent 每一步去读提示词文件。** 主流程每个阶段前加一句说明目的的注释。
137
+
138
+ ## 命令和配置
139
+
140
+ ```ts
141
+ new Agent({ provider: 'codex', command: 'cxh' });
142
+ new Agent({ provider: 'codex', command: ['/path/to/cx', 'fixed-argument'] });
143
+ new Agent({ provider: 'claude', command: 'claude', cwd: '/path/to/project' });
144
+ ```
145
+
146
+ `provider` 是协议,`command` 是可执行命令或 argv 数组。不会从 `cxh` 名字猜测协议,也不会把字符串当 shell 代码执行。alias/function 需要用户提供可执行包装脚本,通过 `"$@"` 原样转发参数。
147
+
148
+ 示例命令行的固定参数用重复的 `--command-arg VALUE` 传入。一般 `cxh` 不需要额外参数。
149
+
150
+ | 配置 | 默认值 | 作用 |
151
+ | --- | --- | --- |
152
+ | `provider` | `codex` | `codex` 或 `claude` |
153
+ | `command` | provider 对应名称 | 自定义命令或 argv |
154
+ | `cwd` | 当前目录 | agent 工作目录 |
155
+ | `timeoutMs` | `3600000` | 每步总超时,包含补答;示例设为 600000 |
156
+ | `idleTimeoutMs` | 不启用 | stdout/stderr 无新输出超时 |
157
+ | `progressIntervalMs` | `15000` | 等待提示间隔,设 null 关闭 |
158
+ | `maxCorrections` | `2` | 格式不合格时最多补答次数 |
159
+ | `nativeSchema` | `false` | 显式启用时向 Codex 发送原生 outputSchema;默认只约束最终回答并在本地校验,避免兼容后端限制工具调用 |
160
+ | `display` | `new Console()` | 设 false 关闭终端展示 |
161
+ | `onEvent` | 无 | 接收事件的同步回调 |
162
+ | `extraArgs` | `[]` | 模型等 CLI 选项;会话和协议参数由库管理 |
163
+ | `env` | `{}` | 合并到子进程环境的显式变量 |
164
+ | `runId` | 自动生成 | 显式恢复同一逻辑运行 |
165
+ | `workflowVersion` | `1` | 流程版本,修改流程时递增 |
166
+ | `stateDir` | `<cwd>/.agenttaskflow` | 状态与日志目录 |
167
+ | `sessionId` | 无 | 首次打开时绑定已有外部会话 |
168
+
169
+ 调用 `agent.run(prompt, { name, schema })`。不提供 schema 就返回字符串;提供 Zod schema 后返回其推导出的类型。建议使用 `z.strictObject`、枚举和明确字段。`z.number()` 不会把数字字符串当数字,但用户显式使用 `z.coerce` 时遵循该 schema 的规则。
170
+
171
+ ## 常驻会话与结果校验
172
+
173
+ Codex 只启动一次 `app-server`,初始化并创建/续接一个 thread,再逐轮发送 `turn/start`。Claude Code 只启动一次双向 `stream-json` 进程,持续发送 user 消息。`agent.pid` 在多步之间保持不变。
174
+
175
+ Codex 的 schema 随轮次变化。Claude 常驻模式用每一步的 prompt 约束格式,在本地验证,避免进程级固定 schema 限制不同步骤。即使 `nativeSchema: false`,仍发送 prompt 格式要求并本地校验。
176
+
177
+ 正常完成但输出不符合 schema 时,在**同一进程、同一会话**发送补答 prompt,明确不要重复已完成操作;补答次数耗尽后抛出 `ResultValidationError`。自定义 Zod refinement 在调用方执行,也能触发补答。schema 必须可以转换为 JSON Schema;异步 refinement 请使用适合的异步业务逻辑,不在默认同步 API 中执行。
178
+
179
+ 进程失败、通信异常或超时不会自动重启或重发任务。完成依赖当前轮次的明确完成事件,不等待进程退出,也不靠“几秒没有输出”猜测。Codex 过滤 thread/turn ID,防止旧轮次的延迟事件成为新答案。
180
+
181
+ CLI 的既有权限设置仍然生效。库不主动添加跳过权限检查的参数。若 CLI 要求宿主批准工具或回答其他交互请求,本版会拒绝未经批准的动作并报错,不静默授权。
182
+
183
+ ## 同步 API 为什么还能实时显示
184
+
185
+ 流程线程在 `run()` 中等待,独立工作线程继续处理 agent 的输入输出。事件会在等待期间交给调用方展示,故不需要流程作者写 async/await。默认 Console 使用直接写入终端的方式,隐藏的协议事件不会把流式文字切成多行。
186
+
187
+ 这不会把所有 JavaScript API 变成同步 API:你自己调用 `fetch()` 等仍应遵循它们的接口。默认同步方式适合独立的顺序工作流;Web 服务、GUI、同一主线程需要同时处理其他工作时使用可选异步 API:
188
+
189
+ ```ts
190
+ import { withAsyncAgent } from 'agenttaskflow';
191
+
192
+ await withAsyncAgent({ command: 'cxh' }, async agent => {
193
+ const answer = await agent.run('hello');
194
+ });
195
+ ```
196
+
197
+ 同步事件回调不能重新调用当前 Agent 方法,否则会形成嵌套等待。回调请保持简短。显示回调异常会在当前请求处理结束后抛出;不要把显示回调当作任务取消接口。异步 API 可传 `AbortSignal`。
198
+
199
+ `close()` 会关闭连接并清理进程。macOS/Linux 有独立生命周期监视进程,工作流被 Ctrl+C 或意外退出时清理对应 agent 进程组。Windows 未验证,仅直接子进程清理,不保证完整后代清理。
200
+
201
+ 同步模式下普通主线程 timer/Promise 回调不会在阻塞等待中执行;进程通信、超时和锁的心跳在工作线程运行。不要安装一个依赖主线程继续执行才能生效的 SIGINT 处理器来代替默认 Ctrl+C。
202
+
203
+ ## 显式 checkpoint
204
+
205
+ ```ts
206
+ withAgent({ command: 'cxh', runId: 'research-001', workflowVersion: 'v1' }, agent => {
207
+ const inputs = { topic: 'example', promptVersion: 1 };
208
+ let state = agent.loadCheckpoint<{ answer: string }>('outline', inputs);
209
+ if (!state) {
210
+ const answer = agent.run('生成提纲', { name: '提纲' });
211
+ state = { answer };
212
+ agent.saveCheckpoint('outline', state, inputs);
213
+ }
214
+ console.log(state.answer);
215
+ });
216
+ ```
217
+
218
+ 同一个 runId 自动读取保存的会话 ID。工作目录、命令、provider、显式环境、额外参数或流程版本变化时,拒绝复用旧状态;checkpoint 输入变化也会拒绝复用。
219
+
220
+ **不恢复 TypeScript 的调用栈,不自动跳过任何 run,不自动重放任务。** 恢复位置由普通 TypeScript 判断。中断前外部操作可能已完成,应先检查产物再决定重做。
221
+
222
+ 同一运行使用跨进程锁,正常 close 释放;进程崩溃留下的锁在停止心跳至少 30 秒后才可被下一次调用识别为过期。不要手动删除仍在使用的锁。不同 run 可以使用不同 agent 并发,不能主动操纵同一个外部 session。
223
+
224
+ ## 日志与排错
225
+
226
+ 交互终端中,步骤标题为紫色粗体,输入为青色并带边框,agent 回答为绿色,运行状态淡化显示,警告为黄色,失败为红色。重定向到文件时默认不带颜色;设置 `NO_COLOR=1` 可禁用,或通过 `new Console({ color: false })` 关闭。
227
+
228
+ ```ts
229
+ import { Console } from 'agenttaskflow';
230
+ new Agent({ command: 'cxh', display: new Console({ showInputs: false }) });
231
+ ```
232
+
233
+ 默认 `.agenttaskflow/<runId>/`:
234
+
235
+ ```text
236
+ state.json 配置指纹、会话 ID、checkpoint
237
+ steps/<stepId>/status.json 步骤状态、结果或错误
238
+ steps/<stepId>/events.jsonl 原始事件与规范化事件、时间戳
239
+ steps/<stepId>/0.input.txt 实际发送的输入;补答递增编号
240
+ steps/<stepId>/0.output.txt 当前回答
241
+ steps/<stepId>/schema.json 结果 schema(如有)
242
+ ```
243
+
244
+ 进程突然退出可能留下 `running` 记录,它不证明任务还在运行,也不证明未产生副作用。需要结合 CLI/产物核实。
245
+
246
+ 错误导出:`AgentTaskFlowError`、`AgentProcessError`、`ProtocolError`、`AgentTimeoutError`、`ResultValidationError`、`StateError`、`CancelledError`。
247
+
248
+ 日志含提示词和工具输出,可能包含业务数据;不要提交运行目录。provider 自身的上下文窗口和压缩机制仍然有效,不保证无限记忆。
249
+
250
+ ## 开发和归档
251
+
252
+ ```bash
253
+ npm run check
254
+ npm test
255
+ npm pack --dry-run
256
+ ```
257
+
258
+ - `src/`:TypeScript 库。
259
+ - `examples/`:普通 TypeScript 流程,无自定义解释器。
260
+ - `docs/workflow-authoring.md`:其他 agent 编写流程的指南。
261
+ - `archive/python-v0.2.0/`:完整 Python 实现、测试、文档、环境和运行记录。
262
+ - `archive/agentflow/`:更早的 DSL/终端版完整归档。
263
+
264
+ 旧版全部保留;当前 npm 发布包只包含 dist、示例和文档,不包含归档或运行数据。现有 `explore/docs/flow` 研究流程未迁移。
@@ -0,0 +1,69 @@
1
+ import { z } from 'zod';
2
+ import { type Provider } from './connection.js';
3
+ import { Console, type EventSink } from './events.js';
4
+ export interface AgentOptions {
5
+ provider?: Provider;
6
+ command?: string | string[];
7
+ cwd?: string;
8
+ extraArgs?: string[];
9
+ env?: NodeJS.ProcessEnv;
10
+ timeoutMs?: number;
11
+ idleTimeoutMs?: number;
12
+ progressIntervalMs?: number | null;
13
+ maxCorrections?: number;
14
+ nativeSchema?: boolean;
15
+ display?: Console | EventSink | false;
16
+ onEvent?: EventSink;
17
+ runId?: string;
18
+ sessionId?: string;
19
+ stateDir?: string;
20
+ workflowVersion?: string;
21
+ signal?: AbortSignal;
22
+ }
23
+ export interface RunOptions<S extends z.ZodType = z.ZodType> {
24
+ name?: string;
25
+ schema?: S;
26
+ signal?: AbortSignal;
27
+ }
28
+ export interface ResultCodec {
29
+ jsonSchema: unknown;
30
+ validate(value: unknown): Promise<{
31
+ success: boolean;
32
+ data?: unknown;
33
+ issues?: unknown;
34
+ }>;
35
+ }
36
+ /** A single persistent agent session. Control flow belongs entirely to TypeScript. */
37
+ export declare class Agent {
38
+ readonly runId: string;
39
+ readonly provider: Provider;
40
+ readonly cwd: string;
41
+ private options;
42
+ private state?;
43
+ private connection?;
44
+ private closed;
45
+ private tail;
46
+ private closePromise?;
47
+ private lifetime;
48
+ private command;
49
+ private display;
50
+ constructor(options?: AgentOptions);
51
+ get pid(): number | undefined;
52
+ get sessionId(): string | undefined;
53
+ private store;
54
+ saveCheckpoint(key: string, value: unknown, input: unknown): void;
55
+ loadCheckpoint<T = unknown>(key: string, input: unknown): T | undefined;
56
+ run<S extends z.ZodType>(prompt: string, options: RunOptions<S> & {
57
+ schema: S;
58
+ }): Promise<z.output<S>>;
59
+ run(prompt: string, options?: RunOptions & {
60
+ schema?: undefined;
61
+ }): Promise<string>;
62
+ /** Internal bridge for the synchronous facade; validators execute on its caller thread. */
63
+ runValidated(prompt: string, options: RunOptions, codec: ResultCodec): Promise<unknown>;
64
+ private execute;
65
+ close(): Promise<void>;
66
+ private shutdown;
67
+ [Symbol.asyncDispose](): Promise<void>;
68
+ }
69
+ export declare function withAgent<T>(options: AgentOptions, workflow: (agent: Agent) => Promise<T>): Promise<T>;
package/dist/agent.js ADDED
@@ -0,0 +1,189 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { appendFileSync, existsSync, mkdirSync, statSync, writeFileSync } from 'node:fs';
3
+ import { join, resolve } from 'node:path';
4
+ import { z } from 'zod';
5
+ import { Connection } from './connection.js';
6
+ import { AgentTimeoutError, CancelledError, ResultValidationError, StateError } from './errors.js';
7
+ import { Console } from './events.js';
8
+ import { State, writeJson } from './state.js';
9
+ /** A single persistent agent session. Control flow belongs entirely to TypeScript. */
10
+ export class Agent {
11
+ runId;
12
+ provider;
13
+ cwd;
14
+ options;
15
+ state;
16
+ connection;
17
+ closed = false;
18
+ tail = Promise.resolve();
19
+ closePromise;
20
+ lifetime = new AbortController();
21
+ command;
22
+ display;
23
+ constructor(options = {}) {
24
+ this.options = { ...options, extraArgs: [...(options.extraArgs ?? [])], env: { ...options.env } };
25
+ this.provider = options.provider ?? 'codex';
26
+ if (!['codex', 'claude'].includes(this.provider))
27
+ throw new TypeError('provider must be codex or claude');
28
+ this.command = typeof options.command === 'string' ? [options.command] : [...(options.command ?? [this.provider])];
29
+ if (!this.command.length || this.command.some(v => !v || typeof v !== 'string' || v.includes('\0'))) {
30
+ throw new TypeError('command must be an executable name or argv array');
31
+ }
32
+ const reserved = ['--resume', '--continue', '--last', '--session-id', '--ephemeral', '--no-session-persistence',
33
+ '--output-format', '--input-format', '--json', '--json-schema', '--output-schema', '--listen', '--stdio',
34
+ '--permission-prompt-tool', '--permission-prompts'];
35
+ if (options.extraArgs?.some(a => reserved.includes(a.split('=')[0])))
36
+ throw new TypeError('Session/protocol flags are managed by AgentTaskFlow');
37
+ for (const value of [options.timeoutMs, options.idleTimeoutMs, options.progressIntervalMs]) {
38
+ if (value != null && (!Number.isFinite(value) || value <= 0))
39
+ throw new TypeError('Timeout/interval must be positive');
40
+ }
41
+ if (options.maxCorrections != null && (!Number.isInteger(options.maxCorrections) || options.maxCorrections < 0)) {
42
+ throw new TypeError('maxCorrections must be a nonnegative integer');
43
+ }
44
+ this.cwd = resolve(options.cwd ?? '.');
45
+ if (!existsSync(this.cwd) || !statSync(this.cwd).isDirectory())
46
+ throw new TypeError(`Workspace missing: ${this.cwd}`);
47
+ this.runId = options.runId ?? randomUUID();
48
+ if (!/^[A-Za-z0-9_-]{1,128}$/.test(this.runId))
49
+ throw new TypeError('Invalid runId');
50
+ this.display = options.display === false ? false : typeof options.display === 'function' ? options.display : (options.display ?? new Console()).emit;
51
+ }
52
+ get pid() { return this.connection?.pid; }
53
+ get sessionId() { return this.state?.sessionId ?? this.options.sessionId; }
54
+ store() {
55
+ if (this.closed)
56
+ throw new StateError('Agent is closed');
57
+ if (!this.state) {
58
+ this.state = new State(resolve(this.options.stateDir ?? join(this.cwd, '.agenttaskflow')), this.runId, {
59
+ provider: this.provider, command: this.command, cwd: this.cwd, extraArgs: this.options.extraArgs,
60
+ env: this.options.env, workflowVersion: this.options.workflowVersion ?? '1',
61
+ });
62
+ try {
63
+ if (this.options.sessionId)
64
+ this.state.bind(this.options.sessionId);
65
+ }
66
+ catch (error) {
67
+ this.state.close();
68
+ this.state = undefined;
69
+ throw error;
70
+ }
71
+ }
72
+ this.state.assertOwned();
73
+ return this.state;
74
+ }
75
+ saveCheckpoint(key, value, input) { this.store().saveCheckpoint(key, value, input); }
76
+ loadCheckpoint(key, input) { return this.store().loadCheckpoint(key, input); }
77
+ run(prompt, options = {}) {
78
+ if (typeof prompt !== 'string' || !prompt.trim())
79
+ return Promise.reject(new TypeError('prompt must be nonempty text'));
80
+ // One queue per Agent; independent Agents may run concurrently.
81
+ const task = this.tail.then(() => this.execute(prompt, options));
82
+ this.tail = task.then(() => { }, () => { });
83
+ return task;
84
+ }
85
+ /** Internal bridge for the synchronous facade; validators execute on its caller thread. */
86
+ runValidated(prompt, options, codec) {
87
+ const task = this.tail.then(() => this.execute(prompt, { ...options, codec }));
88
+ this.tail = task.then(() => { }, () => { });
89
+ return task;
90
+ }
91
+ async execute(prompt, options) {
92
+ const state = this.store();
93
+ const stepId = randomUUID(), name = options.name ?? 'step';
94
+ const directory = join(state.directory, 'steps', stepId);
95
+ mkdirSync(directory, { recursive: true, mode: 0o700 });
96
+ const statusFile = join(directory, 'status.json');
97
+ let attempt = 0;
98
+ const emit = event => {
99
+ const enriched = { ...event, timestamp: new Date().toISOString(), provider: this.provider,
100
+ runId: this.runId, stepId, stepName: name, attempt };
101
+ appendFileSync(join(directory, 'events.jsonl'), JSON.stringify(enriched) + '\n', { mode: 0o600 });
102
+ if (this.display)
103
+ this.display(enriched);
104
+ this.options.onEvent?.(enriched);
105
+ };
106
+ const record = (status, detail = {}) => writeJson(statusFile, { stepId, name, status, ...detail });
107
+ record('running');
108
+ const began = Date.now();
109
+ const timeoutMs = this.options.timeoutMs ?? 3_600_000;
110
+ const signals = [this.lifetime.signal, this.options.signal, options.signal].filter((s) => Boolean(s));
111
+ const signal = AbortSignal.any(signals);
112
+ try {
113
+ emit({ kind: 'step_started', text: name });
114
+ const schema = options.schema ? z.toJSONSchema(options.schema) : options.codec?.jsonSchema;
115
+ if (schema)
116
+ writeJson(join(directory, 'schema.json'), schema);
117
+ let input = prompt + (schema ? '\n\nExecute this step using tools as needed before answering. The JSON requirement applies only to your final answer, not to tool calls or intermediate work. After completing the work, return one JSON object matching the schema, without Markdown fences. Report actual results; do not invent success.\n' + JSON.stringify(schema) : '');
118
+ for (attempt = 0; attempt <= (this.options.maxCorrections ?? 2); attempt++) {
119
+ state.assertOwned();
120
+ writeFileSync(join(directory, `${attempt}.input.txt`), input, { mode: 0o600 });
121
+ emit({ kind: 'input', text: input });
122
+ this.connection ??= new Connection({ provider: this.provider, command: this.command, cwd: this.cwd,
123
+ extraArgs: this.options.extraArgs ?? [], env: { ...process.env, ...this.options.env }, sessionId: state.sessionId });
124
+ const remaining = timeoutMs - (Date.now() - began);
125
+ if (remaining <= 0) {
126
+ await this.connection.close();
127
+ throw new AgentTimeoutError('Step timeout');
128
+ }
129
+ const answer = await this.connection.run(input, this.options.nativeSchema === true ? schema : undefined, emit, id => state.bind(id), { timeoutMs: remaining, idleTimeoutMs: this.options.idleTimeoutMs,
130
+ progressIntervalMs: this.options.progressIntervalMs === undefined ? 15_000 : this.options.progressIntervalMs, signal });
131
+ writeFileSync(join(directory, `${attempt}.output.txt`), answer.hasStructured ? JSON.stringify(answer.structured) : answer.text, { mode: 0o600 });
132
+ if (!options.schema && !options.codec) {
133
+ record('completed', { result: answer.text });
134
+ emit({ kind: 'step_completed', text: name });
135
+ return answer.text;
136
+ }
137
+ let parsed;
138
+ let problem;
139
+ try {
140
+ parsed = answer.hasStructured ? answer.structured : JSON.parse(answer.text);
141
+ }
142
+ catch {
143
+ problem = 'Final answer is not valid JSON';
144
+ }
145
+ const validated = problem ? undefined : options.codec ? await options.codec.validate(parsed) : options.schema.safeParse(parsed);
146
+ if (validated?.success) {
147
+ record('completed', { result: validated.data });
148
+ emit({ kind: 'step_completed', text: name });
149
+ return validated.data;
150
+ }
151
+ problem ??= JSON.stringify(validated && !validated.success ? ('error' in validated ? validated.error.issues : validated.issues) : 'Invalid result');
152
+ if (attempt === (this.options.maxCorrections ?? 2))
153
+ throw new ResultValidationError(`${name}: invalid result after ${attempt + 1} answers. Logs: ${directory}\n${problem}`);
154
+ emit({ kind: 'correction', text: `${name}:请求第 ${attempt + 1} 次补答` });
155
+ input = 'Your previous final answer is invalid. Do not repeat completed actions. Use the work already performed in this conversation. Return ONLY a JSON object matching the schema.\nValidation errors:\n' + problem + '\nSchema:\n' + JSON.stringify(schema);
156
+ }
157
+ throw new ResultValidationError('No valid result');
158
+ }
159
+ catch (error) {
160
+ const interrupted = error instanceof CancelledError || error instanceof AgentTimeoutError;
161
+ record(interrupted ? 'interrupted' : 'failed', { error: String(error) });
162
+ emit({ kind: interrupted ? 'step_interrupted' : 'step_failed', text: `${name}: ${String(error)}` });
163
+ throw error;
164
+ }
165
+ }
166
+ close() { return this.closePromise ??= this.shutdown(); }
167
+ async shutdown() {
168
+ this.closed = true;
169
+ this.lifetime.abort();
170
+ await this.tail;
171
+ try {
172
+ await this.connection?.close();
173
+ }
174
+ finally {
175
+ this.state?.close();
176
+ }
177
+ }
178
+ async [Symbol.asyncDispose]() { await this.close(); }
179
+ }
180
+ export async function withAgent(options, workflow) {
181
+ const agent = new Agent(options);
182
+ try {
183
+ return await workflow(agent);
184
+ }
185
+ finally {
186
+ await agent.close();
187
+ }
188
+ }
189
+ //# sourceMappingURL=agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env node
2
+ import { spawn } from 'node:child_process';
3
+ import { resolve } from 'node:path';
4
+ import { statSync, readFileSync } from 'node:fs';
5
+ import { fileURLToPath } from 'node:url';
6
+ import { constants } from 'node:os';
7
+ const args = process.argv.slice(2);
8
+ if (!args.length || ['--help', '-h'].includes(args[0])) {
9
+ console.log(`用法:atf <文件.ts|文件.js> [传给流程的参数...]
10
+
11
+ 例如:
12
+ atf examples/simple.ts
13
+ atf examples/smoke.ts --command cxh --rounds 5
14
+ atf /path/to/pilot.ts --project projects/my-project --command cxh
15
+
16
+ 执行普通 TypeScript/JavaScript;支持相对 import。
17
+ 文件可直接调用 flow,也可导出 main(args),由 atf 在加载后调用。
18
+ --version 显示版本
19
+ --help 显示帮助`);
20
+ }
21
+ else if (['--version', '-v'].includes(args[0])) {
22
+ console.log(JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version);
23
+ }
24
+ else {
25
+ const [major, minor] = process.versions.node.split('.').map(Number);
26
+ if (major < 22 || (major === 22 && minor < 15)) {
27
+ console.error('atf 需要 Node.js 22.15+。');
28
+ process.exitCode = 1;
29
+ }
30
+ else {
31
+ const file = resolve(args[0]);
32
+ try {
33
+ if (!statSync(file).isFile())
34
+ throw new Error('路径不是文件');
35
+ const child = spawn(process.execPath, [
36
+ '--import', fileURLToPath(new URL('./loader.js', import.meta.url)),
37
+ fileURLToPath(new URL('./runner.js', import.meta.url)), file, ...args.slice(1),
38
+ ], { stdio: 'inherit' });
39
+ const signals = ['SIGINT', 'SIGTERM', 'SIGHUP'];
40
+ // 同终端进程组的 Ctrl+C 也会传给子进程;转发确保单独终止 atf 时不遗留工作流。
41
+ const handlers = signals.map(signal => { const handler = () => child.kill(signal); process.on(signal, handler); return handler; });
42
+ child.once('error', error => { console.error(`atf: ${error.message}`); process.exitCode = 1; });
43
+ child.once('exit', (code, signal) => {
44
+ signals.forEach((name, i) => process.off(name, handlers[i]));
45
+ process.exitCode = code ?? (signal ? 128 + constants.signals[signal] : 1);
46
+ });
47
+ }
48
+ catch (error) {
49
+ console.error(`atf: 无法执行 ${file}: ${error.message}`);
50
+ process.exitCode = 1;
51
+ }
52
+ }
53
+ }
54
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import type { EventSink } from './events.js';
2
+ import { Transport } from './transport.js';
3
+ export type Provider = 'codex' | 'claude';
4
+ export interface ConnectionOptions {
5
+ provider: Provider;
6
+ command: string[];
7
+ cwd: string;
8
+ extraArgs: string[];
9
+ env: NodeJS.ProcessEnv;
10
+ sessionId?: string;
11
+ }
12
+ export interface TurnResult {
13
+ text: string;
14
+ structured?: unknown;
15
+ hasStructured: boolean;
16
+ }
17
+ export declare class Connection {
18
+ private options;
19
+ readonly transport: Transport;
20
+ private ready;
21
+ private counter;
22
+ private pending;
23
+ private sessionId?;
24
+ constructor(options: ConnectionOptions);
25
+ get pid(): number | undefined;
26
+ close(): Promise<void>;
27
+ private read;
28
+ private stash;
29
+ private rpc;
30
+ private initialize;
31
+ run(prompt: string, schema: unknown, emit: EventSink, bind: (id: string) => void, limits: {
32
+ timeoutMs: number;
33
+ idleTimeoutMs?: number;
34
+ progressIntervalMs: number | null;
35
+ signal?: AbortSignal;
36
+ }): Promise<TurnResult>;
37
+ }