@keyou007/agent-bot 0.1.12 → 0.1.13-alpha.1

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 (91) hide show
  1. package/.env.example +2 -2
  2. package/CHANGELOG.md +18 -0
  3. package/README.md +32 -13
  4. package/README.zh.md +32 -13
  5. package/config.example.yaml +0 -24
  6. package/dist/cli/AgentPrerequisites.js +262 -0
  7. package/dist/cli/AgentPrerequisites.js.map +1 -0
  8. package/dist/cli/DefaultAgentSelection.js +47 -0
  9. package/dist/cli/DefaultAgentSelection.js.map +1 -0
  10. package/dist/cli/Initializer.js +165 -2
  11. package/dist/cli/Initializer.js.map +1 -1
  12. package/dist/cli/ServerStarter.js +17 -2
  13. package/dist/cli/ServerStarter.js.map +1 -1
  14. package/dist/cli/controlProtocol.js.map +1 -1
  15. package/dist/cli/help.js +16 -6
  16. package/dist/cli/help.js.map +1 -1
  17. package/dist/cli.js +233 -4
  18. package/dist/cli.js.map +1 -1
  19. package/dist/codex/AppServerConnection.js +3 -3
  20. package/dist/codex/AppServerConnection.js.map +1 -1
  21. package/dist/codex/CodexProcessManager.js +4 -4
  22. package/dist/codex/CodexProcessManager.js.map +1 -1
  23. package/dist/codex/CodexRuntime.js +28 -16
  24. package/dist/codex/CodexRuntime.js.map +1 -1
  25. package/dist/commands/CommandRouter.js +5 -0
  26. package/dist/commands/CommandRouter.js.map +1 -1
  27. package/dist/config/FeishuUserOpenIdStore.js +76 -0
  28. package/dist/config/FeishuUserOpenIdStore.js.map +1 -0
  29. package/dist/config/loadConfig.js +3 -24
  30. package/dist/config/loadConfig.js.map +1 -1
  31. package/dist/console/ConsoleConnector.js +2 -2
  32. package/dist/console/ConsoleConnector.js.map +1 -1
  33. package/dist/feishu/CardRenderer.js +90 -30
  34. package/dist/feishu/CardRenderer.js.map +1 -1
  35. package/dist/index.js +104 -24
  36. package/dist/index.js.map +1 -1
  37. package/dist/presentation/turnGraph.js +36 -0
  38. package/dist/presentation/turnGraph.js.map +1 -0
  39. package/dist/proxy/ProxySessionController.js +321 -98
  40. package/dist/proxy/ProxySessionController.js.map +1 -1
  41. package/dist/runtime/AcpRuntimeAdapter.js +3 -2
  42. package/dist/runtime/AcpRuntimeAdapter.js.map +1 -1
  43. package/dist/startup/StartupNotifier.js +16 -7
  44. package/dist/startup/StartupNotifier.js.map +1 -1
  45. package/dist/startup/startFeishu.js +2 -2
  46. package/dist/startup/startFeishu.js.map +1 -1
  47. package/dist/state/StateStore.js +169 -0
  48. package/dist/state/StateStore.js.map +1 -1
  49. package/dist/state/migrations.js +21 -0
  50. package/dist/state/migrations.js.map +1 -1
  51. package/dist/supervision/SafeRestartNotifier.js +46 -3
  52. package/dist/supervision/SafeRestartNotifier.js.map +1 -1
  53. package/dist/supervision/SafeRestartScheduler.js +65 -6
  54. package/dist/supervision/SafeRestartScheduler.js.map +1 -1
  55. package/dist/supervision/replacementSupervisor.js +27 -2
  56. package/dist/supervision/replacementSupervisor.js.map +1 -1
  57. package/dist/supervisor.js +27 -2
  58. package/dist/supervisor.js.map +1 -1
  59. package/docs/technical-reference.md +42 -20
  60. package/docs/technical-reference.zh.md +42 -20
  61. package/npm-shrinkwrap.json +2 -2
  62. package/package.json +7 -3
  63. package/skills/agent-bot/SKILL.md +21 -9
  64. package/src/cli/AgentPrerequisites.ts +377 -0
  65. package/src/cli/DefaultAgentSelection.ts +56 -0
  66. package/src/cli/Initializer.ts +204 -3
  67. package/src/cli/ServerStarter.ts +25 -2
  68. package/src/cli/controlProtocol.ts +6 -1
  69. package/src/cli/help.ts +16 -6
  70. package/src/cli.ts +350 -5
  71. package/src/codex/AppServerConnection.ts +3 -3
  72. package/src/codex/CodexProcessManager.ts +4 -4
  73. package/src/codex/CodexRuntime.ts +38 -18
  74. package/src/commands/CommandRouter.ts +4 -0
  75. package/src/commands/commandTypes.ts +1 -0
  76. package/src/config/FeishuUserOpenIdStore.ts +81 -0
  77. package/src/config/loadConfig.ts +3 -24
  78. package/src/console/ConsoleConnector.ts +2 -2
  79. package/src/feishu/CardRenderer.ts +117 -30
  80. package/src/index.ts +162 -22
  81. package/src/presentation/turnGraph.ts +48 -0
  82. package/src/proxy/ProxySessionController.ts +375 -107
  83. package/src/runtime/AcpRuntimeAdapter.ts +3 -1
  84. package/src/startup/StartupNotifier.ts +23 -7
  85. package/src/startup/startFeishu.ts +3 -2
  86. package/src/state/StateStore.ts +221 -0
  87. package/src/state/migrations.ts +21 -0
  88. package/src/supervision/SafeRestartNotifier.ts +53 -4
  89. package/src/supervision/SafeRestartScheduler.ts +78 -7
  90. package/src/supervision/replacementSupervisor.ts +27 -1
  91. package/src/supervisor.ts +33 -2
@@ -9,7 +9,7 @@
9
9
  Agent Bot 是基于 Node.js 22+、ESM 和 TypeScript 的应用,主要组件如下:
10
10
 
11
11
  - Supervisor 负责常驻服务和 worker 自动重启
12
- - Worker 启动 Codex/ACP Runtime、飞书传输、Console 传输、本地控制服务和 SQLite
12
+ - Worker 启动配置的 Agent Runtime、飞书传输、Console 传输、本地控制服务和 SQLite
13
13
  - 飞书事件和 Console 输入统一进入任务控制器
14
14
  - 展示层为每个 turn 维护一张进度卡,并单独发送 Markdown 最终回答
15
15
  - App Server Agent 通过 stdio 连接 App Server,其他 Agent 使用 ACP
@@ -22,7 +22,7 @@ Agent Bot 是基于 Node.js 22+、ESM 和 TypeScript 的应用,主要组件如
22
22
  | `src/cli/` | 初始化、应用创建、配置审计及服务/任务命令 |
23
23
  | `src/feishu/` | 飞书长连接事件、API、卡片、图片和上下文键 |
24
24
  | `src/runtime/` | 通用 Runtime 抽象 |
25
- | `src/codex/` | Codex App Server 协议集成 |
25
+ | `src/codex/` | Codex、TraeX 及兼容 Agent 的 App Server 协议集成 |
26
26
  | `src/acp/` | ACP 进程与 JSON-RPC 集成 |
27
27
  | `src/proxy/` | 任务、turn、steering、队列、分支和命令执行 |
28
28
  | `src/presentation/` | Turn 状态归并和出站路由 |
@@ -58,13 +58,22 @@ CLI 通过 Node.js 国际化能力读取系统 Locale。以 `zh` 开头的 Local
58
58
 
59
59
  ## 初始化
60
60
 
61
+ 初始化开始阶段,`agentbot init` 会并行检查目前支持的 Codex 和 TraeX CLI,并显示各自已安装的版本。Codex 与最新稳定版 `@openai/codex` 比较,TraeX 与 Alpha 通道比较。未安装或版本较旧的 Agent 会汇总到一个编号列表,并显示准确的安装或升级命令。交互式用户可以输入用逗号或空格分隔的操作编号、输入 `all`,或直接回车跳过维护;所选命令按顺序执行并继承终端输入输出,跳过或失败的操作都会记录结果,初始化继续。非交互式终端只显示供手动执行的命令。使用 `--json` 时,进度与询问写入 stderr,最终 `agents` 数组记录检测和辅助执行结果。Codex 升级会先执行 `codex update`,旧版 updater 失败时回退到当前 npm 包安装命令。
62
+
63
+ 版本与维护检查完成后,交互式 `init` 会要求用户输入编号或标准名选择默认 Agent。自定义 Agent 无需版本检测即可选择;Codex 或 TraeX CLI 仍缺失时,对应 Agent 不会进入候选列表。当前默认 Agent 仍可选择时,直接回车即可确认。所选标准名通过保留注释的 YAML 原子更新写入 `defaults.agent`。非交互式调用无法询问,因此保留已有且仍在配置中的默认 Agent;没有有效默认值时会失败并提示改用交互式终端。JSON 结果通过 `defaultAgent.name` 和 `defaultAgent.status`(`selected` 或 `existing`)报告选择状态。
64
+
61
65
  目标文件不存在时,`agentbot init` 会复制随包提供的 `config.example.yaml` 和 `.env.example`,创建数据和日志目录,并在平台支持时把 `.env` 权限限制为 POSIX `0600`。
62
66
 
67
+ `config.yaml` 已存在时,`init` 会把当前版本随包提供的 `config.example.yaml` 作为配置升级模板。它会解析两个 YAML 文件并递归补齐缺失的映射项,同时保留已有标量值、序列、注释和自定义配置。已有的 `agents` 映射视为用户配置:不会重新加入用户已删除的模板 Agent,但会为同名 Agent 补齐缺失字段。缺失的 `defaults.agent` 不会被推断,避免静默改变当前默认 Agent。YAML 无效时会直接报错,不会覆盖原文件;发生变更时通过原子替换写入,再次执行保持幂等。需要完全使用当前模板重新生成配置时,请使用 `--reset`。
68
+
69
+ `.env` 已存在时,`init` 会追加随包 `.env.example` 中存在、但当前文件缺少的有效赋值。已有值、注释、顺序和换行风格保持不变,注释状态的可选变量不会被自动启用。更新同样通过原子替换写入,并保持幂等。
70
+
63
71
  凭据处理规则:
64
72
 
65
73
  - 进程环境变量优先于 `~/.agent-bot/.env`
66
74
  - `FEISHU_APP_ID` 和 `FEISHU_APP_SECRET` 必须同时存在
67
75
  - 一键注册还会把授权用户的 `open_id` 保存为 `FEISHU_USER_OPEN_ID`
76
+ - 已有应用凭据但缺少用户 Open ID 时,第一条发送者为有效 `ou_` 标识的私聊消息会把该用户原子写入 Profile 的 `.env`;群消息和后续用户都不会覆盖它
68
77
  - 除非使用 `--reconfigure-feishu`,完整凭据不会被替换
69
78
  - 缺少凭据或只有一项时会重新创建应用
70
79
  - 新创建的凭据经过 fsync、原子替换写入 `.env`,并在配置权限前读回校验
@@ -92,7 +101,7 @@ https://open.feishu.cn/app/<appId>/auth?q=im%3Amessage.group_msg&op_from=openapi
92
101
 
93
102
  `agentbot --profile <目录> init --reset` 会完整重置显式指定的 Profile。执行前必须先停止该 Profile 的 Server。命令会把当前 `config.yaml`、`.env`、`data/` 和 `logs/` 移入 `<profile>/.reset-backups/` 下唯一的时间戳目录,从随包模板创建干净的新文件和目录,再继续正常初始化。已有重置备份及其他无关文件会保留。备份中可能含有旧 App Secret 和会话数据,应妥善保护 Profile 目录。远端旧飞书应用不会被删除。`--reset --skip-feishu` 可创建干净的 Console-only Profile,`--reset` 不能与 `--reconfigure-feishu` 同时使用。
94
103
 
95
- 飞书初始化成功后,CLI 会先释放初始化锁,再通过与 `agentbot server start` 相同的就绪检查流程启动后台 Supervisor,并等待最多 45 秒,直到 Worker 连接飞书并进入就绪状态。如果当前 Profile 的服务已经运行,不会创建第二个 Supervisor。`--skip-feishu` 会跳过自动启动;`--json` 会把结果写入 `server.status`,不会混入非 JSON 文本。
104
+ 飞书初始化成功后,CLI 会先释放初始化锁,再通过与 `agentbot server start` 相同的就绪检查流程启动后台 Supervisor,并等待最多 45 秒,直到 Worker 连接飞书并进入就绪状态。如果当前 Profile 的服务已经运行,不会创建第二个 Supervisor,而是安排安全重启,在活动任务和最终结果投递完成后加载当前安装的代码及更新后的配置;JSON 结果将其表示为 `server.status: "restart-scheduled"`。`--skip-feishu` 会跳过自动启动;`--json` 会把结果写入 `server.status`,不会混入非 JSON 文本。
96
105
 
97
106
  ## 飞书应用要求
98
107
 
@@ -142,6 +151,13 @@ agents:
142
151
  args: ["app-server", "--enable", "goals", "--listen", "stdio://"]
143
152
  env: {}
144
153
 
154
+ traex:
155
+ kind: "app-server"
156
+ title: "TraeX"
157
+ command: "traex"
158
+ args: ["app-server", "--listen", "stdio://"]
159
+ env: {}
160
+
145
161
  defaults:
146
162
  agent: "codex"
147
163
  cwd: "."
@@ -156,7 +172,7 @@ logging:
156
172
 
157
173
  `feishu.respondToAllGroupMessages` 默认为 `true`。设为 `false` 后,未 @ 当前机器人的群消息会被忽略;Worker 启动时会解析机器人的 Open ID,因此 @ 其他成员不会误触发。私聊始终正常处理。无论该运行时配置如何,初始化都会申请接收全部群消息的权限,之后切换配置无需再次授权。
158
174
 
159
- `agentbot server start` 要求同时配置飞书 `appId` 和 `appSecret`。Worker 启动 SDK 长连接时不读取 SDK 日志或私有连接状态,随后通过发送启动状态卡片检查出站能力。每张启动卡片都会显示从已安装包元数据读取的 Agent Bot 版本。通知通常发往已知私聊和最近活跃的群聊;数据库里尚无已知会话时,改用 `feishu.userOpenId`,按 `open_id` 私聊发送。存在通知目标时,至少一张卡片发送成功后 Server 才报告就绪,单个目标发送失败仍相互隔离。如果既没有已知会话,也没有 `feishu.userOpenId`,启动会跳过出站检查并继续。缺少凭据时仍会启动失败并提示先初始化。`agentbot console` 是明确的纯本地入口,不需要飞书凭据。
175
+ `agentbot server start` 要求同时配置飞书 `appId` 和 `appSecret`。Worker 启动 SDK 长连接时不读取 SDK 日志或私有连接状态,随后通过发送启动状态卡片检查出站能力。每张启动卡片都会显示从已安装包元数据读取的 Agent Bot 版本。每次启动都会向所有已知私聊发送卡片,不受最近活跃时间影响;同时向本次 Worker 启动前 1 分钟内活跃的非话题群聊发送卡片。安全重启后,还会向所有已加入本次重启通知范围的群发送,不受活跃时间限制;话题路由会折算为所属普通群,因此话题会话永远不会成为启动卡目标。数据库里尚无符合条件的会话时,改用 `feishu.userOpenId`,按 `open_id` 私聊发送。存在通知目标时,至少一张卡片发送成功后 Server 才报告就绪,单个目标发送失败仍相互隔离。如果既没有已知会话,也没有 `feishu.userOpenId`,启动会跳过出站检查并继续;之后收到的第一条私聊消息可以补全用户 Open ID,供后续启动通知和 CLI 建群使用。缺少凭据时仍会启动失败并提示先初始化。`agentbot console` 是明确的纯本地入口,不需要飞书凭据。
160
176
 
161
177
  必须至少配置一个 Agent,`defaults.agent` 必须指向已配置的 Agent。
162
178
 
@@ -187,7 +203,7 @@ AGENT_BOT=1
187
203
 
188
204
  命令、卡片回调、进度卡和最终回答都保留在来源路由。
189
205
 
190
- 从已映射的用户消息、进度卡或最终回答创建飞书话题时,会从其关联的已完成 Codex turn 创建分支。无法可靠确定已完成来源 turn 时会直接失败,不会选择任意分支点。
206
+ 从已映射的用户消息、进度卡或最终回答创建飞书话题时,会从其关联的已完成 App Server turn 创建分支。无法可靠确定已完成来源 turn 时会直接失败,不会选择任意分支点。
191
207
 
192
208
  `/forkgroup` 会根据话题状态选择来源。话题尚未绑定任务,或者已绑定任务但尚未完成过自己的 turn 时,直接从话题原始锚点 turn fork,不创建中间话题任务。话题任务完成过 turn 后,使用本地持久化的最近完成 turn;更晚的执行中 turn 不会阻塞命令,也不会成为 fork 点。
193
209
 
@@ -198,7 +214,7 @@ Agent Bot 会在每个 `thread/fork` 请求中默认发送实验性的 `excludeT
198
214
  ## Turn 与消息行为
199
215
 
200
216
  - 路由没有当前任务时,普通文本会自动创建任务
201
- - Codex turn 活跃时收到的文字通过 steering 追加
217
+ - App Server turn 活跃时收到的文字通过 steering 追加
202
218
  - Steering 与 turn 完成发生竞态时,文字变为下一条排队请求
203
219
  - `/nosteer` 始终创建持久化 FIFO 队列项
204
220
  - 队列卡操作可以取消单个待执行项
@@ -207,25 +223,27 @@ Agent Bot 会在每个 `thread/fork` 请求中默认发送实验性的 `excludeT
207
223
 
208
224
  每个 turn 只有一张进度卡。普通更新最多每两秒一次,关键更新最短间隔 500 毫秒。完成时先把进度卡更新为终态,再单独发送 Markdown 最终回答。
209
225
 
226
+ 成功完成的思考卡片包含 `Reset` 操作,其作用提示紧跟在按钮下方。`/turns` 卡片把相同的作用提示放在最上方,然后按时间倒序显示当前任务的已完成 turn,每页 10 条。每次 `turn_started` 都会把前一个已完成 turn 保存为父节点;现有任务会结合快照时间和 `session_reset_to_turn` 审计记录回填,因此历史 Reset 后的第一轮会指向所选 turn,而不是时间上相邻的废弃路径。渲染器先基于完整历史计算 lane,再切分页面,从而跨分页正确显示延续和合并;内容缩进到第二列,状态或操作位于第三列。当前对话位置显示“当前”标记,其余 turn 提供 `Reset` 按钮。翻页和成功的 Reset 都会更新同一张卡片、保持与打开卡片时的任务绑定,并把“当前”标记移动到所选 turn;成功提示会用 Prompt 摘要、完成时间和 Turn ID 标明目标轮次。Agent Bot 会持久化每个 turn 原本所属的 App Server thread,从所选 turn fork,并替换当前任务的远端 thread 绑定;本地任务 ID、标题、Agent、项目目录、运行设置和聊天路由保持不变。所选 turn 之后已经完成的快照不会被删除,因此卡片会同时显示旧路径保留的轮次和 Reset 后新分支产生的轮次。当前任务仍在执行时会拒绝 Reset,本地文件修改也不会被回退。
227
+
210
228
  完成持久化消息去重占位后,Agent Bot 会等待 `OnIt` 表情添加成功,再进行聊天信息持久化、图片下载、队列等待、命令执行或 Runtime 调用。Turn 成功、失败或取消时分别替换为 `DONE`、`ERROR` 或 `CrossMark`。表情操作失败会记录日志,但不会阻塞任务。
211
229
 
212
- 富文本图片会下载到输入图片缓存,并以 `localImage` 传给 Codex。纯图片消息使用默认 Prompt `请查看这张图片`。ACP Runtime 不支持图片输入时会明确报错。
230
+ 富文本图片会下载到输入图片缓存,并以 `localImage` 传给 App Server。纯图片消息使用默认 Prompt `请查看这张图片`。ACP Runtime 不支持图片输入时会明确报错。
213
231
 
214
- ## 任务、项目与外部 Codex 工作
232
+ ## 任务、项目与外部 App Server 工作
215
233
 
216
- `/sessions` 通过 `thread/list` 读取 Codex 任务,可发现同一 `CODEX_HOME` 下由 Codex Desktop、CLI、Agent Bot 或其他 App Server 客户端创建的任务。
234
+ `/sessions` 通过 `thread/list` 读取每个已配置 App Server Agent 的任务。对于 Codex,可发现同一 `CODEX_HOME` 下由 Codex Desktop、CLI、Agent Bot 或其他 App Server 客户端创建的任务;其他 Agent 通过同一协议暴露各自的任务存储。多 Agent 任务合并并全局排序后,每页显示 5 个;`Previous` 和 `Next` 会替换当前卡片内容而不是继续追加任务,同时保留搜索条件和全局任务序号。
217
235
 
218
236
  每个任务条目都提供 `NewGroup` 和 `ForkGroup` 回调。回调数据保留所选任务 ID 与来源上下文,并使用飞书操作者的 `open_id` 邀请用户进入新群。`NewGroup` 解析所选任务的项目和执行设置;`ForkGroup` 解析该任务最新可用的已完成 turn。
219
237
 
220
238
  CLI 通过 `agentbot task newgroup <任务> [标题] [--agent <标准名>] [--dir <目录> | --nodir]` 和 `agentbot task forkgroup <任务> [标题]` 提供相同的指定任务操作。两个命令都要求 Server 正在运行,并通过当前 Profile 的本地控制端点发送稳定的本地任务 ID。CLI 进程没有飞书操作者,因此 Server 会邀请 `feishu.userOpenId`,该值由初始化保存为 `FEISHU_USER_OPEN_ID`。NewGroup 默认继承指定任务的 Agent 和执行设置;`--agent <标准名>` 可选择另一个已配置的 Runtime,同时继续继承来源项目形态,并省略执行设置以采用目标 Runtime 自己的默认值。ForkGroup 使用来源任务最新可用的已完成 turn,并让来源任务的活动 turn 继续执行。两类控制响应都包含新群、群上下文、来源任务和新任务;`--json` 会输出不做本地化的结构化结果。
221
239
 
222
- ## Codex Provider 设置
240
+ ## App Server Provider 设置
223
241
 
224
- Provider 是任务级设置,以 `model_provider` 与模型、思考强度和权限模式一起持久化。任务明确继承或选择 Provider 时,Agent Bot 通过 `thread/start`、`thread/resume` 和 `thread/fork` 传递 `modelProvider`。全新任务没有可继承 Provider 时,Agent Bot 省略该参数,由 Codex App Server 使用 Codex 配置中生效的 `model_provider`,再从 thread 响应中读取实际 Provider 并保存。
242
+ Provider 是任务级设置,以 `model_provider` 与模型、思考强度和权限模式一起持久化。任务明确继承或选择 Provider 时,Agent Bot 通过 `thread/start`、`thread/resume` 和 `thread/fork` 传递 `modelProvider`。全新任务没有可继承 Provider 时,Agent Bot 省略该参数,由所选 App Server Agent 使用自身生效的默认值,再从 thread 响应中读取实际 Provider 并保存。
225
243
 
226
244
  `/provider`、`/model`、`/thinking` 和 `/permissions` 打开同一张 Card 2.0 运行设置卡片,并激活对应的 tab。四个命令都拒绝参数,tab 切换和设置修改只通过卡片回调完成。Provider 选项来自 App Server 的 `config/read`;切换 Provider 时使用当前兼容的模型、思考强度和权限模式恢复 thread。模型、思考强度和权限选择会立即更新对应设置、就地刷新同一张卡片,并从下一次请求生效。
227
245
 
228
- Agent Bot 内部保留本地路由键以关联飞书卡片和投递状态,但对用户展示 Codex 任务 ID。没有明确用户操作时,不会续写、steer、停止或分支其他客户端正在运行的 Codex 工作。
246
+ Agent Bot 内部保留本地路由键以关联飞书卡片和投递状态,但对用户展示所属 App Server 的任务 ID。没有明确用户操作时,不会续写、steer、停止或分支其他客户端正在运行的 Agent 工作。
229
247
 
230
248
  项目规则:
231
249
 
@@ -242,13 +260,13 @@ Agent Bot 内部保留本地路由键以关联飞书卡片和投递状态,但
242
260
  SQLite 保存:
243
261
 
244
262
  - 每条路由的当前任务和上一个任务
245
- - 本地任务标识与 Codex task/thread 标识
263
+ - 本地任务标识与 App Server task/thread 标识
246
264
  - 模型、思考强度和权限模式
247
265
  - 排队 Prompt
248
266
  - 进度快照和消息绑定
249
267
  - 最终消息投递记录
250
268
 
251
- 启动时,Agent Bot 通过 `thread/read` 将持久化的活动工作与 Codex 状态校准。Turn 标识变化、收到终态通知或控制请求失败时也会重新校准。
269
+ 启动时,Agent Bot 通过 `thread/read` 将持久化的活动工作与其所属 App Server 状态校准。Turn 标识变化、收到终态通知或控制请求失败时也会重新校准。
252
270
 
253
271
  最终消息投递账本用于避免重复发送成功回答。App Server 请求使用有限超时,避免阻塞的请求永久占用消息路由。会话生命周期请求允许 60 秒,因为兼容的第三方 Agent 完成 `thread/start` 可能需要超过 30 秒;控制请求仍使用更短的超时。
254
272
 
@@ -275,15 +293,19 @@ Supervisor、Worker、替换 Supervisor 和 Console Worker 默认启用 Node fat
275
293
 
276
294
  飞书 `/restart` 命令默认使用这条安全重启路径;`/restart --force` 会立即重启,并可能中断正在执行的任务。该命令拒绝其他所有参数。新消息会重置静默计时,CLI 的 `--immediate` 和 `--force` 也会跳过这些检查。退出码 `75` 表示主动 worker 重启。
277
295
 
296
+ 待执行的安全重启计划会收集每一个触发它的精确会话路由。收到任何用户消息时,包括斜杠命令,都会把所属基础私聊或群聊标为活跃;每次状态更新还会加入此前 1 分钟内活跃的所有已知会话。每个已加入的会话都会收到各自的状态卡片和真正开始重启前的提示,而且即使之后超过 1 分钟未活跃,也会一直保留到本次计划结束。同一路由会去重;如果话题路由最初缺少消息锚点,后续带锚点的触发会补全它。话题请求会保留原消息 ID,并通过话题回复发送,避免重启状态落到群主会话;话题中的最近活动记在所属普通群,只有显式从话题触发时才向该话题本身发送。后续请求也会更新重启原因。替换进程前,Agent Bot 会提取并去重所有已加入路由所属的普通群,经替换 Supervisor 传给 Worker,再把这些群加入服务级启动卡目标。Supervisor 会保留该列表,直到 Worker 连续稳定运行 60 秒,避免启动阶段异常退出并重新拉起时丢失必发群。
297
+
298
+ 当 CLI 重启属于某个具体任务时,使用 `agentbot server restart --task <任务>`。任务序号、完整 ID 和不冲突的 ID 前缀会在发送控制请求前解析。未传 `--task` 时,只有所有运行中任务都属于同一个会话,Server 才会自动推断安全重启状态的发送目标;如果同时有多个运行中的会话,请求会被拒绝。没有运行中任务的本地 CLI 重启没有等待状态所属会话。
299
+
278
300
  首次安全重启状态卡会延迟 3 秒发送,让任务最终回答尽可能先到达;延迟期间的状态变化会合并到首张卡片。该延迟不阻塞调度器轮询,真正关闭前会立即 flush 尚未发送的卡片。
279
301
 
280
- 等待中的安全重启状态卡底部带有 `Cancel` 操作。回调会携带调度器单调递增的计划 ID,因此旧卡片不会取消较新的重启。取消成功后,所有已发送的状态卡都会原地更新并移除按钮;调度器进入不可逆的正在重启阶段后也不再显示该按钮。
302
+ 等待中的安全重启状态卡底部带有 `Cancel` 操作。回调会携带调度器单调递增的计划 ID,因此旧卡片不会取消较新的重启。取消成功后,所有已加入会话中的状态卡都会原地更新并移除按钮;调度器进入不可逆的正在重启阶段后也不再显示该按钮。
281
303
 
282
304
  本地控制服务负责修改任务、执行指定任务的 NewGroup 和 ForkGroup,以及请求服务重启;只读任务查询直接访问 SQLite。
283
305
 
284
306
  ## 权限模式
285
307
 
286
- - `auto`:Codex 使用 `approvalPolicy=never` 和 `danger-full-access`
308
+ - `auto`:App Server Agent 使用 `approvalPolicy=never` 和 `danger-full-access`
287
309
  - `confirm`:通过卡片提供单次允许、会话允许、拒绝和取消任务操作
288
310
 
289
311
  创建或分支任务时,会按适用场景继承模型、思考强度、权限模式和项目形态。
@@ -312,18 +334,18 @@ CLI 随包发布 `npm-shrinkwrap.json`,以固定传递运行依赖;直接运
312
334
  - `prepack` 清理并构建 `dist/`,然后检查 tarball 清单
313
335
  - `npm run package:smoke` 打包项目、在临时目录安装 tarball、运行 CLI,并执行仅 Console 的初始化
314
336
 
315
- 在干净工作树中准备下一个 patch 版本:
337
+ 在干净工作树中准备下一个 Alpha 版本:
316
338
 
317
339
  ```powershell
318
340
  npm run release
319
341
  git add package.json npm-shrinkwrap.json CHANGELOG.md
320
- git commit -m "release: v0.1.1"
342
+ git commit -m "release: v0.1.13-alpha.0"
321
343
  git push origin master
322
344
  ```
323
345
 
324
- `npm run release` 默认递增 patch 版本,并把当前 `Unreleased` 条目归档到带日期的版本小节。可以使用 `npm run release -- minor`、`npm run release -- major` 或 `npm run release -- 0.2.0` 指定其他稳定版本。工作树不干净或 `Unreleased` 没有内容时,命令会拒绝修改文件。
346
+ `npm run release` 现在默认使用 Alpha 通道:稳定版 `0.1.12` 会变为 `0.1.13-alpha.0`,当前版本 `0.1.13-alpha.0` 会变为 `0.1.13-alpha.1`。`npm run release:alpha` 是对应的显式命令。`npm run release:stable` 会把当前 Alpha 提升为相同核心版本的稳定版;当前已经是稳定版时则递增 patch。仍可通过 `npm run release -- <version>` 使用 `patch`、`minor`、`major`,或指定完整的稳定版及 `-alpha.N` 版本。每次发布都会把当前 `Unreleased` 条目归档到带日期的版本小节。工作树不干净或 `Unreleased` 没有内容时,命令会拒绝修改文件。
325
347
 
326
- 推送完成后无需再执行本地发布命令。本仓库自身对 `master` 的 push 通过 CI 后,`publish.yml` 会查询 npm 中的包版本:版本已存在时正常跳过;发现尚未发布的稳定版本时,要求 `CHANGELOG.md` 存在匹配小节,并在发布前再次执行完整验证和包安装 smoke test。npm 接受新包后,workflow 自动创建对应的 `v<包版本>` GitHub Release。
348
+ 推送完成后无需再执行本地发布命令。本仓库自身对 `master` 的 push 通过 CI 后,`publish.yml` 会查询 npm 中的包版本:版本已存在时正常跳过;发现尚未发布的稳定版或 Alpha 版时,要求 `CHANGELOG.md` 存在匹配小节,并在发布前再次执行完整验证和包安装 smoke test。Alpha 版发布到 npm 的 `alpha` dist-tag,并创建 GitHub prerelease;稳定版发布到 `latest`,并创建普通 GitHub Release。
327
349
 
328
350
  需要补跑时,可以在 **GitHub Actions → Publish to npm → Run workflow** 中选择 `master` 手动执行。Pull Request、外部 fork、CI 失败以及其他分支的 push 都不能进入发布 job。
329
351
 
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@keyou007/agent-bot",
3
- "version": "0.1.12",
3
+ "version": "0.1.13-alpha.1",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@keyou007/agent-bot",
9
- "version": "0.1.12",
9
+ "version": "0.1.13-alpha.1",
10
10
  "license": "GPL-3.0-only",
11
11
  "dependencies": {
12
12
  "@agentclientprotocol/sdk": "1.2.1",
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@keyou007/agent-bot",
3
- "version": "0.1.12",
3
+ "version": "0.1.13-alpha.1",
4
4
  "type": "module",
5
- "description": "Using Codex in Lark/Feishu feels just like using native Codex.",
5
+ "description": "Use Codex, TraeX, and compatible coding agents from Lark/Feishu.",
6
6
  "license": "GPL-3.0-only",
7
7
  "repository": {
8
8
  "type": "git",
@@ -15,6 +15,8 @@
15
15
  "keywords": [
16
16
  "agent",
17
17
  "codex",
18
+ "traex",
19
+ "app-server",
18
20
  "acp",
19
21
  "feishu",
20
22
  "lark",
@@ -57,7 +59,9 @@
57
59
  "prepublishOnly": "npm run verify",
58
60
  "package:check": "npm run prepack",
59
61
  "package:smoke": "node scripts/smoke-package.mjs",
60
- "release": "node scripts/prepare-release.mjs"
62
+ "release": "node scripts/prepare-release.mjs",
63
+ "release:alpha": "node scripts/prepare-release.mjs alpha",
64
+ "release:stable": "node scripts/prepare-release.mjs stable"
61
65
  },
62
66
  "dependencies": {
63
67
  "@agentclientprotocol/sdk": "1.2.1",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: agent-bot
3
- description: Initialize Agent Bot, detect and work safely inside its runtime, and manage the local service and its Codex or ACP sessions through the agentbot CLI. Use when an agent needs to adapt its behavior while running under Agent Bot, or when a user asks to initialize, inspect, start, safely restart, immediately restart, or stop Agent Bot; open its console UI; list, inspect, stop, rename, or send a prompt to tasks; create or fork Lark groups from tasks; check a scheduled restart; or troubleshoot the bot without manually killing worker processes.
3
+ description: Initialize Agent Bot, detect and work safely inside its runtime, and manage the local service and its App Server or ACP sessions through the agentbot CLI. Use when an agent needs to adapt its behavior while running under Agent Bot, or when a user asks to initialize, inspect, start, safely restart, immediately restart, or stop Agent Bot; open its console UI; list, inspect, stop, rename, or send a prompt to tasks; create or fork Lark groups from tasks; check a scheduled restart; or troubleshoot the bot without manually killing worker processes.
4
4
  ---
5
5
 
6
6
  # Agent Bot
@@ -9,7 +9,7 @@ Use the `agentbot` command as the supported control surface for Agent Bot. The l
9
9
 
10
10
  ## Detect the Agent Bot runtime
11
11
 
12
- Agent Bot injects `AGENT_BOT=1` into every Codex and ACP agent process it starts. Test for the exact value `1`:
12
+ Agent Bot injects `AGENT_BOT=1` into every configured Agent process it starts. Test for the exact value `1`:
13
13
 
14
14
  ```powershell
15
15
  if ($env:AGENT_BOT -eq "1") { "running in Agent Bot" }
@@ -46,8 +46,16 @@ Run initialization once after installing or linking the CLI:
46
46
  agentbot init
47
47
  ```
48
48
 
49
+ Initialization detects the supported Codex and TraeX CLIs and reports each installed version. Missing or outdated Agents are presented in one numbered maintenance list with their exact commands. In an interactive terminal, the user may enter comma-separated action numbers, `all`, or press Enter to skip maintenance. A failed maintenance command or the absence of an interactive terminal does not block the remaining initialization. Do not select maintenance actions on the user's behalf without permission. Agent Bot uses the latest stable Codex release and the TraeX Alpha channel for these checks.
50
+
51
+ After the maintenance choice, interactive initialization requires the user to select the default Agent by number or standard name. It lists configured custom Agents and installed supported Agents, omits Codex or TraeX when that CLI is still missing, and writes the selected standard name to `defaults.agent` in `config.yaml`. If the current default remains available, an empty answer explicitly confirms it. Always relay the choices and let the user decide. A non-interactive invocation keeps an already configured default; it fails with an instruction to rerun interactively when no valid default exists. With `--json`, read the result from `defaultAgent.name` and `defaultAgent.status`.
52
+
49
53
  Initialization creates the Agent Bot home, `config.yaml`, `.env`, `data/`, and `logs/` from the bundled examples. If Feishu credentials are absent, it starts Feishu one-click app registration, prints a QR code followed by its authorization URL, waits for the user to approve the request, and stores the returned app ID and secret in `.env`. It then audits the app's currently published tenant permissions, event subscriptions, and callbacks. Core and optional missing items produce separate configuration challenges. Core configuration is polled until ready, except that the manually configured all-group-message permission may be explicitly skipped with `Y`. For optional configuration, the CLI prints the QR code followed by the authorization URL and immediately waits up to five minutes for activation. The only terminal choice is also `Y`, which skips optional authorization and continues initialization.
50
54
 
55
+ An existing app may have complete credentials but no `FEISHU_USER_OPEN_ID`. In that state, ask the user to send the bot a direct message. Agent Bot atomically persists the first valid private-chat sender to the Profile `.env`; group messages and later users cannot replace it. This identity is needed for startup-notification fallback and CLI-created group invitations.
56
+
57
+ Rerun `agentbot init` after upgrading Agent Bot. It non-destructively upgrades an existing `config.yaml` by adding settings missing from the current bundled template while preserving user values, comments, custom Agents, and intentionally omitted template Agents. It also appends active variables missing from the bundled `.env.example` without changing existing values, comments, line endings, or enabling commented optional variables. It repeats the Agent version checks and Feishu configuration audit. If the selected Profile server is already running, initialization schedules a safe restart so the current installed code and refreshed configuration take effect after active work finishes. Invalid YAML is left untouched and reported as an error. Use `init --reset` only for an explicitly requested full Profile reset.
58
+
51
59
  Core messaging configuration includes `im:message.group_msg`, not merely the narrower group-mention scope. Accept `im:message.group_msg:readonly` when an existing app version reports that alias. Feishu cannot add `im:message.group_msg` through the one-click launcher, so Agent Bot excludes it from `addons` and prints a QR code plus a direct filtered Developer Console permission-page URL. The user should add the permission manually, publish the app version, and complete tenant approval if required. Entering `Y` skips only this permission wait and continues with a partial configuration; the bot then cannot respond to ordinary group messages that do not mention it.
52
60
 
53
61
  Initialization always requests all-user group-message delivery. The runtime option `feishu.respondToAllGroupMessages` controls whether Agent Bot uses it: the default `true` responds to ordinary group messages, while `false` requires a mention of the current bot. Private messages are unaffected.
@@ -93,12 +101,14 @@ Use these commands:
93
101
  ```powershell
94
102
  agentbot server start
95
103
  agentbot server status
96
- agentbot server restart --reason "reason for restart"
104
+ agentbot server restart --task <current-task-id> --reason "reason for restart"
97
105
  agentbot server stop
98
106
  ```
99
107
 
100
108
  Treat `server restart` as the normal restart path. It schedules a safe restart and waits for active tasks, pending final-message delivery, and a quiet inbound-message window. The first safe-restart status card is delayed by three seconds so the active task's final response can usually be delivered first; this presentation delay does not postpone scheduler polling. While the restart is pending, its status card has a bottom `Cancel` button that conditionally cancels that exact schedule and updates the card in place.
101
109
 
110
+ When scheduling from an Agent Bot-hosted task, pass `--task <current-task-id>`. This adds the task's exact Lark conversation, including its topic, to the pending restart's notification set. Every conversation that triggers the same pending restart plus every conversation active during the previous minute receives its own status card and restarting acknowledgement. Once enrolled, a route remains in the set until that restart ends; repeated routes are deduplicated. Resolve the current ID with `agentbot task list --status running` when necessary. If `--task` is omitted, the Server infers a target only when all running tasks belong to one conversation and rejects the request when multiple running conversations make ownership ambiguous. Startup cards are service-wide notices: every known private chat receives one on every startup, groups receive one when active in the previous minute or enrolled for the current safe restart, and topic routes receive the card in their parent group rather than inside the topic.
111
+
102
112
  On Windows, initial start, safe or immediate replacement, and every crash-driven Worker launch reload the latest Machine and User environment variables. After changing `PATH` or installing a CLI shim, finish the current work and use the normal restart path. Agent Bot keeps `AGENT_BOT_*` and `FEISHU_*` process-local so Profile selection and bot credentials do not leak between isolated instances.
103
113
 
104
114
  In Feishu, `/restart` schedules the same safe restart. Use `/restart --force` only when the user explicitly accepts interruption; the command accepts no other arguments.
@@ -131,7 +141,7 @@ agentbot task newgroup <number-or-task-id> [title] [--agent <standard-name>] [--
131
141
  agentbot task forkgroup <number-or-task-id> [title] [--json]
132
142
  ```
133
143
 
134
- Task IDs may be supplied in full or as an unambiguous prefix. Use `task stop` to ask the running worker to send the Codex Interrupt signal; leave child-process lifecycle management to Codex.
144
+ Task IDs may be supplied in full or as an unambiguous prefix. Use `task stop` to ask the running worker to send the App Server Interrupt signal; leave child-process lifecycle management to the selected Agent.
135
145
 
136
146
  Use `task chat <number-or-task-id>` to read the Feishu chat ID associated with a task from local routing state. Plain output is only the chat ID for scripting. Add `--json` to include the stable task ID, complete context key, and the thread ID for a topic-bound task. This read-only command does not require the Agent Bot server to be running.
137
147
 
@@ -174,17 +184,19 @@ Use `/agent` in Feishu to open the unified execution-settings card on its Agent
174
184
 
175
185
  Use `/newgroup [title] [--dir <cwd> | --nodir]` in Feishu to create a private group named `[agent] [project directory] <title>`, invite the command sender, and immediately create and bind a new task in that group. `/new` and `/newgroup` share the same project options: an explicit `--dir` overrides the inherited project directory, while `--nodir` forces a Projectless App Server task; reject using both together. Resolve `~`, `~/...`, and `~\...` from the current user's home directory for both commands. Projectless groups omit the project segment and use `[agent] <title>`. The new task inherits the source chat's current task project directory when neither option is present, plus its model, reasoning effort, and permission mode without interrupting or switching the source task. When the source chat has no current task, use the selected agent and its runtime defaults. An explicit title becomes both the group suffix and the task title. When the title is omitted, use task title `新任务` and group name `[agent] [project directory] 新任务 (mm-dd)`, or `[agent] 新任务 (mm-dd)` for Projectless; an explicit title never gets a date suffix. Every new group gets a deterministic scheme-C Identicon avatar: Latin project names display their first word, Chinese names display up to their first four characters, and the normalized full project path hashes into the palette and symmetric node pattern. Projectless groups use the title as the stable seed. Replace the user's home-directory prefix with `~`. The bracketed project-directory value is limited to 15 characters. Longer paths keep the final two directories when they fit, otherwise keep the final directory, truncating the tail only when the final directory itself is overlong. Use `\` on Windows and `/` on macOS/Linux. Do not automatically send a Sessions or Status card to the new group. A later `/new --dir <cwd>` or `/new --nodir` in the group may explicitly replace the inherited project shape.
176
186
 
177
- Provider is part of the same inherited execution-settings group as model, reasoning effort, and permission mode. Preserve all four across `/new`, `/newgroup`, `/fork`, `/forkgroup`, and the matching `/sessions` actions. New tasks with no inherited Provider must leave it unset so Codex App Server uses the default from Codex configuration. New-group welcome messages report all four settings.
187
+ Provider is part of the same inherited execution-settings group as model, reasoning effort, and permission mode. Preserve all four across `/new`, `/newgroup`, `/fork`, `/forkgroup`, and the matching `/sessions` actions. New tasks with no inherited Provider must leave it unset so the selected App Server Agent uses its own default configuration. New-group welcome messages report all four settings.
178
188
 
179
189
  Group names created by `/newgroup` and `/forkgroup` are capped at 60 displayed characters. When the generated name would exceed that limit, truncate only the title portion in the Feishu group name; preserve the underlying Agent Bot task title.
180
190
 
181
- Use `/forkgroup [title]` in Feishu to fork the current position into a newly created private group. In a Feishu thread, use the thread's original anchor turn when the thread has no bound task or its bound task has not completed a turn of its own. Once the bound thread task has completed a turn, use its latest locally persisted completed turn; exclude any newer active turn without interrupting it. Resolve this source before generic thread initialization so an unbound thread does not create an intermediate task. Outside a thread, fork the current Codex task's latest available completed turn. Agent Bot invites the command sender and binds the fork as the new group's current task, but does not automatically send a Sessions or Status card there. The new-group welcome message reports the forked task's model, reasoning effort, and permission type. An explicit title is used directly. Without an explicit title, both the forked task and group name use the same persistent `source title(分支 N)` sequence as `/fork`. `/forkgroup` does not add a date suffix.
191
+ Use `/forkgroup [title]` in Feishu to fork the current position into a newly created private group. In a Feishu thread, use the thread's original anchor turn when the thread has no bound task or its bound task has not completed a turn of its own. Once the bound thread task has completed a turn, use its latest locally persisted completed turn; exclude any newer active turn without interrupting it. Resolve this source before generic thread initialization so an unbound thread does not create an intermediate task. Outside a thread, fork the current App Server task's latest available completed turn. Agent Bot invites the command sender and binds the fork as the new group's current task, but does not automatically send a Sessions or Status card there. The new-group welcome message reports the forked task's model, reasoning effort, and permission type. An explicit title is used directly. Without an explicit title, both the forked task and group name use the same persistent `source title(分支 N)` sequence as `/fork`. `/forkgroup` does not add a date suffix.
182
192
 
183
193
  Use `/new [title] --nodir` to force a new App Server Projectless task even when the current task belongs to a project. `--nodir` and `--dir <cwd>` are mutually exclusive; omitting both preserves the normal project-shape inheritance behavior.
184
194
 
185
- Every task in the Feishu `/sessions` card has `New`, `NewGroup`, `Fork`, and `ForkGroup` actions. `New` inherits the source task's project directory, model, reasoning effort, and permission mode, creates a new task, and switches the current chat to it without stopping or forking the source task. `NewGroup` applies the same inheritance in a newly created private group. `Fork` switches the current chat to a branch, while `ForkGroup` binds the branch to a newly created private group; both fork actions use the selected task's latest available completed turn without interrupting an active turn.
195
+ The Feishu `/sessions` card shows five tasks per page and updates the same card through `Previous` and `Next`; it never expands earlier pages into one long card. Every task has `New`, `NewGroup`, `Fork`, and `ForkGroup` actions. `New` inherits the source task's project directory, model, reasoning effort, and permission mode, creates a new task, and switches the current chat to it without stopping or forking the source task. `NewGroup` applies the same inheritance in a newly created private group. `Fork` switches the current chat to a branch, while `ForkGroup` binds the branch to a newly created private group; both fork actions use the selected task's latest available completed turn without interrupting an active turn.
196
+
197
+ Use `/fork [number-or-task-id]` in Feishu to branch from the current or specified App Server task and switch to the new branch. If the source task is running, Agent Bot forks from its latest completed turn and leaves the active turn running; it rejects only when the task has no completed turn yet. Every fork request sends `excludeTurns: true` to the App Server so the response omits populated turns without removing turns from the forked history. Older App Servers that explicitly reject this experimental field are retried once without it; ambiguous failures such as timeouts or disconnects are not retried.
186
198
 
187
- Use `/fork [number-or-task-id]` in Feishu to branch from the current or specified Codex task and switch to the new branch. If the source task is running, Agent Bot forks from its latest completed turn and leaves the active turn running; it rejects only when the task has no completed turn yet. Every fork request sends `excludeTurns: true` to Codex App Server so the response omits populated turns without removing turns from the forked history. Older App Servers that explicitly reject this experimental field are retried once without it; ambiguous failures such as timeouts or disconnects are not retried.
199
+ Successfully completed Feishu thinking cards include a bottom `Reset` action followed by its compact warning. `/turns` opens the current task's completed-turn history with the Reset-effect warning at the top and 10 turns per page. It renders each entry as an indented numbered node in a commit graph whose lanes follow persisted parent turns, including Reset branches and merges across page boundaries. A successful Reset refreshes that card in place, moves the current marker to the selected turn, and sends a confirmation containing the target Prompt summary, completion time, and Turn ID. Reset forks the selected turn's original App Server thread through that turn and replaces the current task's remote thread binding in place, preserving the local task ID, title, Agent, project directory, execution settings, and chat route. Completed snapshots after the selected point remain visible together with later turns from the new branch. Reset is available only when the card still belongs to the current task and the task is idle. It restores conversation context only and never reverts local files.
188
200
 
189
201
  Status cards include a `Refresh` action that reads the latest task state and updates the same card in place without switching tasks or sending another card.
190
202
 
@@ -207,7 +219,7 @@ Use `--context <key>` or `--status <status>` to narrow `task list`. Use `--profi
207
219
  After changing Agent Bot code, run the relevant tests, typecheck, and build. If a running service must pick up the result, schedule:
208
220
 
209
221
  ```powershell
210
- agentbot server restart --reason "brief description of the completed change"
222
+ agentbot server restart --task <current-task-id> --reason "brief description of the completed change"
211
223
  ```
212
224
 
213
225
  Do not replace the worker immediately while a task is active. A later incoming task must not cancel the pending safe restart; allow the scheduler to wait until the service becomes safely idle again.