evolcore 0.0.35 → 0.0.36

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 (224) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +6 -0
  3. package/bin/install-codex-managed-hooks.mjs +20 -3
  4. package/dist/agents/baseagent-availability.js +1 -1
  5. package/dist/agents/baseagent.js +88 -0
  6. package/dist/agents/claude-runner.js +59 -12
  7. package/dist/agents/codex/app-server-client.js +18 -1
  8. package/dist/agents/codex-runner.js +262 -21
  9. package/dist/agents/ecagent-runner.js +47 -11
  10. package/dist/agents/gemini-runner.js +36 -12
  11. package/dist/aun/aid/client.js +4 -3
  12. package/dist/aun/aid/control-aid.js +270 -8
  13. package/dist/aun/aid/identity.js +6 -3
  14. package/dist/aun/aid/ownership-operation.js +58 -0
  15. package/dist/aun/aid/store.js +1 -0
  16. package/dist/aun/group/fs-download.js +67 -2
  17. package/dist/aun/group/history.js +20 -5
  18. package/dist/aun/group/operations.js +8 -2
  19. package/dist/aun/menu/client.js +39 -2
  20. package/dist/aun/menu/transport.js +1 -1
  21. package/dist/aun/msg/history.js +43 -4
  22. package/dist/aun/msg/managed-operation.js +30 -53
  23. package/dist/aun/msg/p2p.js +51 -15
  24. package/dist/aun/outbox.js +4 -0
  25. package/dist/channels/aun.js +260 -73
  26. package/dist/channels/daemon.js +6 -4
  27. package/dist/channels/feishu.js +3 -0
  28. package/dist/cli/agent-command.js +161 -223
  29. package/dist/cli/agent-create.js +190 -223
  30. package/dist/cli/agent.js +3 -1
  31. package/dist/cli/aid-bind-command.js +53 -0
  32. package/dist/cli/aun-commands.js +384 -91
  33. package/dist/cli/bench.js +1 -1
  34. package/dist/cli/cli-argv.js +74 -0
  35. package/dist/cli/daemon-commands.js +105 -74
  36. package/dist/cli/diag.js +1 -1
  37. package/dist/cli/fs-command.js +18 -19
  38. package/dist/cli/getmeta-command.js +159 -6
  39. package/dist/cli/index.js +6 -12
  40. package/dist/cli/init-channel.js +8 -55
  41. package/dist/cli/init.js +125 -218
  42. package/dist/cli/queue-command.js +11 -8
  43. package/dist/cli/restart-monitor.js +134 -48
  44. package/dist/cli/session-command.js +1 -1
  45. package/dist/cli/stats.js +7 -5
  46. package/dist/cli/thread-command.js +103 -30
  47. package/dist/cli/trigger-command.js +1 -1
  48. package/dist/cli/watch-msg-diag.js +1 -0
  49. package/dist/config/access-policy.js +2 -2
  50. package/dist/config/boot-log.js +14 -11
  51. package/dist/config/config-field-policy.js +9 -1
  52. package/dist/config/config-manager.js +176 -90
  53. package/dist/config/config-operation-service.js +7 -14
  54. package/dist/config/contact-book-store.js +142 -26
  55. package/dist/config/contact-book.js +4 -2
  56. package/dist/config/lifecycle.js +1 -1
  57. package/dist/config/owner-config.js +96 -0
  58. package/dist/config/peer-role-resolver.js +12 -18
  59. package/dist/config/providers-config.js +382 -0
  60. package/dist/config/providers-import.js +74 -0
  61. package/dist/config/providers-management.js +328 -0
  62. package/dist/config/providers.js +22 -0
  63. package/dist/config/resolved-config-op.js +17 -14
  64. package/dist/config/snapshot.js +28 -16
  65. package/dist/config-store.js +18 -14
  66. package/dist/core/agent-ipc-registration.js +21 -63
  67. package/dist/core/agent-runtime.js +16 -5
  68. package/dist/core/auth/agent-delegation.js +199 -25
  69. package/dist/core/auth/auth-gateway.js +44 -2
  70. package/dist/core/auth/authorization-denial.js +1 -1
  71. package/dist/core/auth/debug-context.js +2 -1
  72. package/dist/core/auth/delegation-authorization.js +2 -2
  73. package/dist/core/auth/delegation-diagnostics.js +4 -1
  74. package/dist/core/auth/operation-authorizer.js +10 -1
  75. package/dist/core/auth/operation-catalog.js +19 -1
  76. package/dist/core/bootstrap-service.js +43 -20
  77. package/dist/core/channel-loader.js +0 -1
  78. package/dist/core/channel-runtime.js +30 -4
  79. package/dist/core/command/agent-control.js +196 -37
  80. package/dist/core/command/cli-intent-parser.js +60 -4
  81. package/dist/core/command/command-handler.js +212 -60
  82. package/dist/core/command/connect-menu.js +1 -0
  83. package/dist/core/command/diag-service.js +5 -4
  84. package/dist/core/command/file-search.js +368 -0
  85. package/dist/core/command/menu-catalog.js +2 -1
  86. package/dist/core/command/menu-handler.js +292 -107
  87. package/dist/core/command/menu-protocol.js +23 -0
  88. package/dist/core/command/role-menu.js +7 -19
  89. package/dist/core/command/skill-slash.js +130 -25
  90. package/dist/core/command/slash-handler.js +101 -53
  91. package/dist/core/command/topic-slash.js +16 -5
  92. package/dist/core/daemon-bootstrap.js +7 -1
  93. package/dist/core/daemon-control.js +19 -1
  94. package/dist/core/daemon-lifecycle.js +2 -1
  95. package/dist/core/event-catalog.js +2 -0
  96. package/dist/core/evolagent-registry.js +13 -2
  97. package/dist/core/evolagent.js +3 -6
  98. package/dist/core/handoff/ipc-registration.js +2 -2
  99. package/dist/core/handoff/runtime.js +40 -6
  100. package/dist/core/handoff/store.js +1 -0
  101. package/dist/core/inference/text-inference.js +95 -6
  102. package/dist/core/ipc-registration.js +43 -24
  103. package/dist/core/memory/consolidation-context.js +4 -1
  104. package/dist/core/memory/consolidation.js +25 -14
  105. package/dist/core/message/aun-ipc-sender.js +296 -88
  106. package/dist/core/message/aun-request-registry.js +226 -0
  107. package/dist/core/message/create-status.js +33 -4
  108. package/dist/core/message/message-bridge.js +62 -13
  109. package/dist/core/message/message-log.js +0 -1
  110. package/dist/core/message/message-queue.js +4 -1
  111. package/dist/core/message/message-utils.js +8 -1
  112. package/dist/core/message/peer-mode.js +17 -9
  113. package/dist/core/message/response-engine.js +266 -124
  114. package/dist/core/message/retry-scheduler.js +11 -8
  115. package/dist/core/model/catalog-service.js +60 -18
  116. package/dist/core/model/model-catalog.js +112 -9
  117. package/dist/core/model/model-fallback.js +94 -26
  118. package/dist/core/ownership/owner-resolver.js +687 -0
  119. package/dist/core/permission/approval-gateway.js +196 -62
  120. package/dist/core/permission/ec-command-parser.js +138 -25
  121. package/dist/core/permission/filesystem-approval-scope.js +141 -0
  122. package/dist/core/permission/protected-paths.js +14 -1
  123. package/dist/core/permission/sandbox-runtime.js +171 -18
  124. package/dist/core/permission/tool-policy.js +13 -2
  125. package/dist/core/role/runtime-policy.js +3 -4
  126. package/dist/core/session/session-idle-monitor.js +10 -8
  127. package/dist/core/session/session-manager.js +72 -45
  128. package/dist/core/session/session-mapper.js +18 -7
  129. package/dist/core/session/session-renew.js +5 -4
  130. package/dist/core/session/session-title.js +2 -1
  131. package/dist/core/session/session-turn-coordinator.js +4 -2
  132. package/dist/core/skill/index-generator.js +2 -16
  133. package/dist/core/task/task-recovery-service.js +15 -2
  134. package/dist/core/thread/command-parser.js +28 -13
  135. package/dist/core/thread/index.js +1 -0
  136. package/dist/core/thread/ipc-operation.js +11 -8
  137. package/dist/core/thread/thread-operation.js +79 -44
  138. package/dist/core/thread/thread-route.js +54 -6
  139. package/dist/core/thread/thread-service.js +236 -45
  140. package/dist/core/thread/topic-id.js +248 -0
  141. package/dist/eck/kit-renderer.js +1 -1
  142. package/dist/eck/message-renderer.js +12 -2
  143. package/dist/index.js +50 -27
  144. package/dist/ipc.js +59 -6
  145. package/dist/paths.js +1 -0
  146. package/dist/product.js +1 -0
  147. package/dist/response-system/engines/v1/proactive-flow.js +10 -3
  148. package/dist/stats/db.js +8 -0
  149. package/dist/stats/writer.js +26 -4
  150. package/dist/trigger/authorization.js +48 -3
  151. package/dist/trigger/feedback.js +28 -10
  152. package/dist/trigger/ipc-service.js +86 -10
  153. package/dist/trigger/local-files.js +55 -23
  154. package/dist/trigger/scheduler.js +57 -11
  155. package/dist/trigger/system-definitions.js +1 -0
  156. package/dist/trigger/validation.js +44 -15
  157. package/dist/utils/aid-bind.js +17 -297
  158. package/dist/utils/avatar-upload.js +16 -4
  159. package/dist/utils/cross-platform.js +109 -34
  160. package/dist/utils/ecweb-supervisor.js +1 -1
  161. package/dist/utils/ecweb-utils.js +8 -1
  162. package/dist/utils/error-utils.js +44 -6
  163. package/dist/utils/instance-registry.js +12 -2
  164. package/dist/utils/npm-ops.js +102 -27
  165. package/dist/utils/package-version-info.js +72 -27
  166. package/dist/utils/restart-safety.js +50 -0
  167. package/dist/utils/upgrade-jobs.js +304 -0
  168. package/dist/utils/windows-autostart.js +17 -10
  169. package/kits/docs/INDEX.md +5 -0
  170. package/kits/docs/aun/ABILITY_CALLING.md +239 -0
  171. package/kits/docs/evolcore/INDEX.md +14 -3
  172. package/kits/docs/evolcore/agent-create.md +55 -141
  173. package/kits/docs/evolcore/agent.md +38 -16
  174. package/kits/docs/evolcore/aid.md +34 -0
  175. package/kits/docs/evolcore/config.md +20 -1
  176. package/kits/docs/evolcore/event.md +2 -2
  177. package/kits/docs/evolcore/fs.md +18 -2
  178. package/kits/docs/evolcore/group-collaboration.md +13 -246
  179. package/kits/docs/evolcore/group.md +2 -1
  180. package/kits/docs/evolcore/memory-consolidation-batches.md +1 -1
  181. package/kits/docs/evolcore/menu-protocol.md +65 -1
  182. package/kits/docs/evolcore/msg.md +64 -2
  183. package/kits/docs/evolcore/skill.md +86 -0
  184. package/kits/docs/evolcore/stats.md +6 -0
  185. package/kits/docs/evolcore/task.md +2 -0
  186. package/kits/docs/evolcore/thread-chain.md +145 -51
  187. package/kits/docs/evolcore/trigger.md +48 -3
  188. package/kits/eck_manifest.json +21 -0
  189. package/kits/eck_message_manifest.json +4 -4
  190. package/kits/migrations/migrate-role-config-v5.mjs +20 -7
  191. package/kits/rules/01-overview.md +2 -1
  192. package/kits/rules/03-identity.md +3 -1
  193. package/kits/rules/04-relation.md +1 -1
  194. package/kits/rules/07-memory-and-thread.md +1 -1
  195. package/kits/schemas/_meta.json +16 -1
  196. package/kits/schemas/agent-config.schema.13.json +44 -2
  197. package/kits/schemas/contact-book.schema.3.json +5 -0
  198. package/kits/schemas/daemon.schema.6.json +3 -1
  199. package/kits/schemas/daemon.schema.8.json +329 -0
  200. package/kits/schemas/defaults.schema.5.json +39 -3
  201. package/kits/schemas/providers.schema.1.json +76 -0
  202. package/kits/schemas/relation-config.schema.9.json +5 -1
  203. package/kits/skills/.switches.json +28 -0
  204. package/kits/skills/aid-ability/SKILL.md +214 -0
  205. package/kits/skills/ec-agent-create/SKILL.md +162 -0
  206. package/kits/skills/ec-group/SKILL.md +2 -1
  207. package/kits/skills/ec-group-collaboration/SKILL.md +228 -0
  208. package/kits/skills/ec-identity/SKILL.md +143 -0
  209. package/kits/skills/ec-skill/scripts/cli.mjs +36 -3
  210. package/kits/skills/ec-skill/scripts/skill.mjs +202 -15
  211. package/kits/skills/ec-trigger/SKILL.md +167 -0
  212. package/kits/skills/ec-trigger/references/examples.md +153 -0
  213. package/kits/skills/thread-ops/SKILL.md +108 -420
  214. package/kits/templates/message-fragments/thread-context.md +1 -2
  215. package/kits/templates/message-fragments/trigger-thread-check.md +1 -1
  216. package/kits/templates/roles/member.json +1 -1
  217. package/kits/templates/roles/visitor.json +1 -0
  218. package/kits/templates/system-fragments/bootstrap.md +1 -0
  219. package/kits/templates/system-fragments/channel.md +2 -1
  220. package/kits/templates/system-fragments/commands.md +5 -4
  221. package/kits/templates/system-fragments/identity.md +2 -0
  222. package/kits/templates/system-fragments/session.md +1 -1
  223. package/kits/templates/system-fragments/venue.md +1 -1
  224. package/package.json +4 -3
@@ -1,6 +1,6 @@
1
1
  # ec msg — 私聊消息命令
2
2
 
3
- 私聊场景下收发消息的命令集。触发词:回复/发消息/拉取/撤回/查在线。
3
+ 私聊场景下收发消息的命令集。触发词:回复/发消息/拉取/撤回/查在线/能力调用/请求等待/结果查询。
4
4
 
5
5
  ## Agent 会话中的 Shell 调用边界
6
6
 
@@ -36,8 +36,20 @@ ec msg send <from> <to> --link <url> [--title '<title>'] [--description '<desc>'
36
36
 
37
37
  # 自定义 payload(JSON)
38
38
  ec msg send <from> <to> --payload '<json>'
39
+
40
+ # 发送自定义 payload 并等待关联结果
41
+ ec msg send <from> <to> --payload '<json>' --return required --timeout 60s --format json
42
+
43
+ # 单向发送,不建立结果关联
44
+ ec msg send <from> <to> --payload '<json>' --return none
39
45
  ```
40
46
 
47
+ `--payload` 优先按 JSON 对象解析;为兼容 Windows 命令包装器,也接受“一层 JSON 字符串包裹 JSON 对象”的形式。
48
+ 最多额外解包一层,最终值必须是 JSON 对象;数组、普通字符串、数字、布尔值和 `null` 均会被拒绝。
49
+ 在当前 Windows PowerShell 托管环境中,调用 `ec.cmd` 时使用单引号包裹 JSON,并在 JSON 内每个
50
+ 双引号前加一个反斜杠,例如 `--payload '{\"type\":\"query\"}'`。反斜杠只用于命令行参数传递,
51
+ `ec` 收到的最终值仍必须是合法 JSON;工具协议所需的 JSON 转义由工具调用层完成。
52
+
41
53
  每一行都必须单独执行,且是该次 shell 调用中的唯一命令。
42
54
 
43
55
  发送相关选项:
@@ -49,10 +61,15 @@ ec msg send <from> <to> --payload '<json>'
49
61
  - `--content-type <mime>` — 显式覆盖 MIME(仅 `--file`)
50
62
  - `--text <说>` — 附件说明文字(仅 `--file`)
51
63
  - `--transcript <text>` — 语音转写(仅 `--as voice`)
64
+ - `--return none|required` — 是否建立通用请求/响应关联;`required` 会等待结果,默认不要求结果
65
+ - `--timeout <duration>` — `--return required` 的本地等待时间及 AUN volatile TTL,如 `30s`、`60s`、`2m`;未指定时默认 60 秒,最大 3600 秒
66
+ - `--format json` — 输出结构化发送回执和响应
52
67
 
53
68
  未指定 `--content-type` 时,附件 MIME 由 SDK 按实际字节识别、后缀回退,附件描述沿用上传后的类型。
54
69
  `--as` 控制消息展示类型,与 MIME 独立。
55
70
 
71
+ 托管会话中的附件源文件必须位于当前项目目录或当前会话 `$TMPDIR` 内;符号链接、硬链接、路径穿越和受保护路径会被拒绝。
72
+
56
73
  托管 Agent 通过 daemon 发送时,若发送方使用 `policyMode: contacts`,私聊普通出站只允许 Owner 或实际 `active` 联系人。无条目、`pending`、`declined` 会拒绝发送并提示:
57
74
 
58
75
  ```bash
@@ -67,10 +84,55 @@ ec contact unblock <target-aid> --self <self-aid>
67
84
 
68
85
  非托管环境的 `ec msg send` 是独立 AUN CLI 发送,不读取或要求 `agents/<aid>/config.json`,因此不会触发这套 Agent 联系人准入判断。
69
86
 
70
- 在 EvolCore 会话内,发送会经过当前 session 的 self/peer/role 鉴权。`visitor` 或 `member` 默认只允许回复当前对端;要联系当前对端以外的对象,必须通过话题路由:先 `ec thread list <对方AID>` 选话题(没有就 `ec thread create`),再用 `ec msg send '<text>' --thread <threadId> --check-every <时长>` 发送;from/to 由话题推断,无需手写。不带 `--thread` 直接改目标会被拒绝。完整话题路由操作序列见 `[memory-and-thread]` 段。没有成功 JSON 回执(含 `message_id`/`status`)不得声称已发送。
87
+ 在 EvolCore 会话内,发送会经过当前 session 的 self/peer/role 鉴权。`visitor` 或 `member` 默认只允许回复当前对端;要联系当前对端以外的对象,必须通过话题路由:先 `ec thread list <对方AID>` 选话题(没有就 `ec thread create`),再用 `ec msg send '<text>' --thread <threadId> --check-every <时长>` 发送;from/to 由话题推断,无需手写。不带 `--thread` 直接改目标会被拒绝。`--check-every` 到期后,系统会向**目标话题**投递一条【跨话题复查】通知(不新建会话),由目标话题侧的 agent 在自己的上下文里决定结束、调整周期或继续。完整话题路由操作序列见 `[memory-and-thread]` 段。没有成功 JSON 回执(含 `message_id`/`status`)不得声称已发送。
71
88
 
72
89
  成功输出:`✓ 已发送 <message_id> seq=<n> status=<status>`
73
90
 
91
+ ## 请求/响应等待与异步查询
92
+
93
+ `message_id` 和传输 `status` 只表示 AUN/daemon 接受了消息,不表示对端能力已经执行。
94
+ 需要业务结果时使用 `--return required`。返回 `request_state=completed` 且带 `response` 才表示
95
+ 已经收到关联结果;`failed` 表示传输失败;`pending` 或 `unknown` 表示本地无法在 deadline
96
+ 内确认执行状态,不能据此推断能力没有执行,也不能自动重发副作用消息。
97
+
98
+ 如果关联业务结果先到、传输失败回执后到,已完成结果保持成功并返回 response;迟到的传输诊断保留在 transport_error,且 retryable=false,不能因此重复执行请求。
99
+
100
+ `--return required` 不按普通持久消息发送。EvolCore 会把本地等待时间转换为顶层
101
+ `message.send.ttl`(秒,向上取整;默认 60 秒),因此 AUN 消息服务使用 volatile 内存通道,
102
+ 不写数据库/WAL,也不分配持久 `seq`。AUN volatile TTL 最大为 3600 秒,所以 required 请求的
103
+ `--timeout` 也不能超过 3600 秒。这个顶层传输 TTL 不会写入或改动业务 payload。
104
+
105
+ EvolCore 本地仍会保存请求关联记录,供 `ec msg request get` 查询迟到结果;这是调用方本地的
106
+ 请求索引,不是 AUN 服务端对消息正文的持久化。
107
+
108
+ 对于 `type=ability`,对端可能先返回 `role=ack`/`execution_state=pending`。这只会记录
109
+ 应用层已受理,等待不会结束;后续匹配同一 `call_id` 的 `role=result` 才会把请求置为
110
+ `completed`。AUN transport ACK 与 Ability ACK 都不是最终业务结果。
111
+
112
+ Ability payload 已有 `call_id` 时,EvolCore 使用它作为通用 transport request ID;不会无条件
113
+ 注入新的 `request_id`。只有普通请求既没有 `request_id` 也没有 `call_id` 时,才会生成并注入
114
+ `request_id`。`operation_id` 始终由业务协议管理。
115
+
116
+ 发送超时或返回 `pending` 后,可以使用 request ID 查询持久化状态:
117
+
118
+ ```bash
119
+ ec msg request get <self-aid> <request-id> --format json
120
+ ```
121
+
122
+ 查询必须由原始托管会话提供有效的 sessionId 和 delegationToken,且本端、关系、来源话题与请求登记上下文一致;跨话题目标仍须通过既有目标授权。知道 request ID 不代表有权查询,独立终端及缺少来源授权的旧记录不返回请求详情。查询是只读操作,不会重新发送消息,可以稍后重复查询。`--return none` 不建立请求记录,
123
+ 不能使用此命令查询其结果。发送命令在顶层返回 `request_id` / `request_state` / `response`;
124
+ 查询命令返回 `{ ok, request }`,状态和响应分别位于 `request.state` / `request.responsePayload`。
125
+
126
+ `pending` 是本地等待超时,不是终态,迟到结果仍可置为 `completed`;迟到 transport ACK 不得将已完成、失败或超时状态改回 `sent`。同一本端的 request_id/call_id 不能覆盖已登记的请求或别名,重复时返回 `REQUEST_ID_CONFLICT`,应使用新的关联 ID。
127
+
128
+ 同步等待依赖 daemon 的长连接入站订阅,因此当前只在 EvolCore 托管会话中可用。独立终端的
129
+ 短连接发送若指定 `--return required` 会返回 `REQUEST_WAIT_REQUIRES_DAEMON`,不会静默降级成
130
+ 单向发送;需要单向发送时显式使用 `--return none` 或省略 `--return`。
131
+
132
+ 若托管命令审批与 daemon 一次性授权未能绑定,JSON 输出会包含
133
+ `code=INVALID_DELEGATION`、`detail_code=APPROVED_COMMAND_UNAVAILABLE`、`retryable=false`、
134
+ `sent=false`。这表示 AUN 消息尚未发出,应停止并报告授权链路问题;不要提权、改身份或自动重发。
135
+
74
136
  > 正文写法:含空格/换行/特殊字符时用引号包起来;纯短词可不包,但多空格会被压成一个。
75
137
  > 正文恰好以 `--` 开头:带空格的(如 `"--file 是正文"`)会被正确识别为正文;
76
138
  > 若正文**精确等于**某个 flag 名(如要发送文本 `--encrypt`),用 `--` 分隔:
@@ -0,0 +1,86 @@
1
+ # ec skill — 技能管理
2
+
3
+ EC 技能系统允许 agent 通过 SKILL.md 文件扩展自身能力。
4
+
5
+ ## 加载技能(最常用)
6
+
7
+ ```bash
8
+ ec skill load <技能名> # 输出 SKILL.md 正文 + 技能根目录绝对路径
9
+ ec skill load <技能名> --with-frontmatter # 同上,附带 frontmatter 元数据
10
+ ec skill load <技能名> --source builtin # 指定来源(builtin|local),同名冲突时用
11
+ ```
12
+
13
+ 技能未启用时报错:`技能未启用: <name>`,需先 `ec skill enable <name>` 再加载。
14
+
15
+ 输出末尾会附带:
16
+ ```
17
+ ---
18
+ skillDir: <技能目录绝对路径>
19
+ ```
20
+ 脚本路径、references/ 等资源均以此为根。
21
+
22
+ ## 查路径
23
+
24
+ ```bash
25
+ ec skill path <技能名> # 输出 SKILL.md 完整绝对路径(含状态和时间戳)
26
+ ```
27
+
28
+ 同名技能(本机覆盖内置)时两行都输出,并标注建议路径。
29
+
30
+ ## 技能列表与详情
31
+
32
+ ```bash
33
+ ec skill list [--all] [--filter '<kw1,kw2>']... [--page <n>] [--limit <n>] [--json]
34
+ # 默认仅列启用;--all 全部;
35
+ # --filter 匹配技能名+描述(大小写不敏感),可多次出现,
36
+ # 组内逗号分隔为 OR,多组之间为 AND;
37
+ # --json 默认返回全部匹配项,显式给 --page/--limit 才分页;
38
+ # 超出 limit 条自动分页(默认 20),页脚给出翻页命令和 filter 提示
39
+ ec skill info <name> [--json] # 单个技能详情:路径、状态、三级开关、描述
40
+ ec skill where # 打印三级根目录(内置/本机/Agent)
41
+ ```
42
+
43
+ ## 启用与禁用
44
+
45
+ ```bash
46
+ ec skill enable <name> [--level agent|local] # 启用(默认 agent 级)
47
+ ec skill disable <name> [--level agent|local] # 禁用(默认 agent 级)
48
+ ```
49
+
50
+ - agent 级开关仅影响本 agent,需本 agent 的 owner 或 admin 权限
51
+ - local 级开关影响整机所有 agent,需 daemonowner 权限
52
+ - 群聊中一律拒绝写操作
53
+
54
+ ## 安装与删除
55
+
56
+ ```bash
57
+ ec skill install <目录|.zip|.md> [--force] [--enable] # 安装到本机级(默认禁用)
58
+ ec skill remove <name> # 删除本机级技能
59
+ ec skill create <name> [--desc '...'] [--enable] # 新建骨架(默认禁用)
60
+ ```
61
+
62
+ 内置技能(随包发布)不可删除,只能 disable。
63
+
64
+ ## 校验与刷新
65
+
66
+ ```bash
67
+ ec skill validate <name|路径> # 校验 SKILL.md 是否合规(name/description/kebab-case)
68
+ ec skill refresh <aid> # 重建该 agent 的技能索引(改完开关后执行)
69
+ ```
70
+
71
+ ## 三级结构
72
+
73
+ | 级别 | 位置 | 写权限 |
74
+ |------|------|--------|
75
+ | 内置级 | `$PACKAGE_ROOT/kits/skills/` | 只读,随包发布 |
76
+ | 本机级 | `$EVOLCORE_HOME/skills/` | daemonowner |
77
+ | Agent 级 | `$AGENT_DIR/skills/` | 本 agent 的 owner/admin |
78
+
79
+ Agent 级只放 `.switches.json`(开关),SKILL.md 在内置级或本机级。
80
+ 同名技能本机级覆盖内置级。
81
+
82
+ ## 权限边界
83
+
84
+ - 群聊中所有写操作一律拒绝(含 enable/disable/install/remove/create)
85
+ - `/skill` 斜杠命令(只读+refresh):群聊仅 admin+ 可用,refresh 私聊也需 admin+
86
+ - `ec skill load`/`path`/`list`/`info`/`where`:所有角色可用
@@ -64,6 +64,12 @@ ec stats --session <session-id> --last
64
64
  ec stats --rebuild
65
65
  ```
66
66
 
67
+ `--task-calls` and `--session-calls` show runner-reported model usage rows. For Codex, a row is a
68
+ degraded per-turn or subagent-thread aggregate, not an exact provider request count. When Codex
69
+ reports child-thread usage, it is included in the task token total and shown as a separate `subagent` row.
70
+
71
+ 子代理按已观察到的累计计数差额计入当前任务,不把历史 total 与 last 重复相加;无法取得累计基线时仅使用本次明确上报的 last,可能低估未观察到的早期调用。各行保留真实 provider thread 和已知模型,未知模型标为 unknown,不套用父模型价格。含子代理的 usage_events 按模型分别写入和计价,不再额外写一次父子总计;父任务完成回执等待子代理结束后生成。未知模型费用保持未知。
72
+
67
73
  ## 直接 SQL 查询
68
74
 
69
75
  ```bash
@@ -9,6 +9,8 @@ ec task resume <sessionId> --format json
9
9
 
10
10
  暂停任务会释放原有的工具门控。异常中断任务会把内部恢复提示排入同一会话,并继续原 baseagent 会话。命令只确认恢复请求已被可靠接纳,不会等待模型运行结束。
11
11
 
12
+ `__task-recovery` 自动恢复要求原错误事件和持久终态都明确为 `recoverable: true`;`false` 或缺失不自动重试。依赖缺失、权限或配置问题需先修复,之后可人工执行本命令;人工恢复不受该布尔字段限制,但仍遵守会话绑定、待审批、任务代际和取消等安全检查。
13
+
12
14
  恢复任务继承原任务的审批交互策略,而非因为自动恢复使用 Trigger 就禁止审批。普通会话(包括 Agent 间和群聊的 proactive 模式)允许申请审批;无人值守 Trigger 禁止申请审批。Handoff 回流同样继承发起任务的策略。继承策略不等于复用旧审批,新的待审批操作仍须发起新请求;缺少历史策略时,自动恢复和 Handoff 回流默认禁止审批,手动恢复默认允许申请。
13
15
 
14
16
  以下情况会安全结束而不创建新会话:任务已完成或正在运行、任务等待必要输入/审批、会话已删除、原 provider 会话文件不存在、渠道不可用,或任务状态已被更新。
@@ -2,7 +2,7 @@
2
2
 
3
3
  话题(Thread)是在私聊或群聊关系里切出的独立对话分支。一组对话可以同时推进多个话题,每个话题有自己的上下文、历史和生命周期,互不干扰。话题链(Thread Chain)则是跨会话、跨 agent 的协作机制:A 可以把一条任务"分支"到 B 的某个话题,B 也可以在自己的话题里继续工作,两者通过 `ec msg send --thread` 和 thread-inbox 上下文注入关联起来。
4
4
 
5
- 触发词:话题/thread/跨会话/委托/ec thread/话题链/summary/删除话题/thread-inbox/跨会话上下文。
5
+ 触发词:话题/thread/跨话题/委托/ec thread/话题链/summary/删除话题/thread-inbox/跨话题上下文/跨话题复查。
6
6
 
7
7
  ## 标准工作流
8
8
 
@@ -22,12 +22,12 @@ ec thread list <peer> --self <selfAid>
22
22
  ec thread list <peer> --self <selfAid> --page 2 --limit 10 --sort recent
23
23
 
24
24
  # 第五步:查看某话题的历史消息
25
- ec thread history <peer>/<threadId> --self <selfAid> --limit 20
25
+ ec thread history <threadId> --self <selfAid> --limit 20
26
26
 
27
27
  # 第六步:查看/写入 summary
28
- ec thread summary show <peer>/<threadId> --self <selfAid>
28
+ ec thread summary show <threadId> --self <selfAid>
29
29
  # 写入时必须带 --name(同时设标题);不想改名传 -(详见「话题摘要」一节)
30
- ec thread summary set <peer>/<threadId> '<摘要内容>' --name '<新标题>' --self <selfAid>
30
+ ec thread summary set <threadId> '<摘要内容>' --name '<新标题>' --self <selfAid>
31
31
  ```
32
32
 
33
33
  ## 什么时候用
@@ -38,7 +38,7 @@ ec thread summary set <peer>/<threadId> '<摘要内容>' --name '<新标题>' --
38
38
  - 想保存话题摘要(summary),供下次激活时快速恢复上下文
39
39
  - 整理完成或废弃的话题时(删除话题)
40
40
 
41
- 主会话(主对话,无 threadId)不能删除。话题是主会话之外额外创建的分支。
41
+ 主话题(该关系默认的对话,id 形如 `main:<aidA>:<aidB>`)不能删除。话题是主话题之外额外创建的分支。
42
42
 
43
43
  ## 基础操作
44
44
 
@@ -59,19 +59,19 @@ ec thread list <peer> --format json
59
59
  ### 查看话题详情
60
60
 
61
61
  ```bash
62
- ec thread show <peer>/<threadId>
62
+ ec thread show <threadId>
63
63
  ec thread show current # 当前任务所在话题
64
- ec thread show <peer> # 该对端的主会话
64
+ ec thread show main:<aidA>:<aidB> # 该对端的主话题(id 来自 ec thread list)
65
65
  ```
66
66
 
67
67
  ### 读取话题历史消息
68
68
 
69
69
  ```bash
70
- ec thread history <peer>/<threadId>
71
- ec thread history <peer>/<threadId> --limit 100
72
- ec thread history <peer>/<threadId> --after 1700000000000
73
- ec thread history <peer>/<threadId> --before 1700000000000
74
- ec thread history <peer>/<threadId> --format json
70
+ ec thread history <threadId>
71
+ ec thread history <threadId> --limit 100
72
+ ec thread history <threadId> --after 1700000000000
73
+ ec thread history <threadId> --before 1700000000000
74
+ ec thread history <threadId> --format json
75
75
  ```
76
76
 
77
77
  托管会话中可以直接用 `ec msg history --thread <id>`,from/to 会自动从运行时上下文推断:
@@ -94,17 +94,17 @@ ec thread create <peer> --name '项目A' --label 项目A --status in_progress
94
94
  ### 修改话题
95
95
 
96
96
  ```bash
97
- ec thread rename <peer>/<threadId> '新名称'
98
- ec thread rename <peer> '新名称' # 裸 peer 指主会话;等价于 <peer>/main
99
- ec thread label <peer>/<threadId> 重要
100
- ec thread label <peer>/<threadId> --clear # 清除标签
101
- ec thread status <peer>/<threadId> completed # pending|in_progress|completed|archived
97
+ ec thread rename <threadId> '新名称'
98
+ ec thread rename main:<aidA>:<aidB> '新名称' # 主话题改名
99
+ ec thread label <threadId> 重要
100
+ ec thread label <threadId> --clear # 清除标签
101
+ ec thread status <threadId> completed # pending|in_progress|completed|archived
102
102
  ```
103
103
 
104
- 主会话可以改名(落在会话存档的 `name` 字段),但**不能**打标签或改状态——label/status 只对子话题生效。
105
- `ec thread list` / `show` 里主会话的名称带 `[主会话] ` 前缀,该前缀只在展示层加,不是真实名字。
104
+ 主话题可以改名(落在会话存档的 `name` 字段),但**不能**打标签或改状态——label/status 只对话题生效。
105
+ `ec thread list` / `show` 里主话题的名称带 `[主话题] ` 前缀,该前缀只在展示层加,不是真实名字。
106
106
 
107
- `summary set ... --name` 对主会话同样生效,改名走与 `ec thread rename` 相同的路径。
107
+ `summary set ... --name` 对主话题同样生效,改名走与 `ec thread rename` 相同的路径。
108
108
 
109
109
  #### 名称长度
110
110
 
@@ -121,14 +121,14 @@ ec thread status <peer>/<threadId> completed # pending|in_progress|completed|
121
121
  ### 删除话题
122
122
 
123
123
  ```bash
124
- ec thread delete <peer>/<threadId> # 软删除:session 文件移入 _trash/,索引条目删除
124
+ ec thread delete <threadId> # 软删除:session 文件移入 _trash/,索引条目删除
125
125
  ```
126
126
 
127
- 删除后话题从索引中消失,`ec thread list` 不再显示。底层 session 文件通过 `unbindSession` 机制移入 `chatDir/_trash/`,与系统其他删除行为一致。不能删除正在处理中(busy)的话题,也不能删除主会话。
127
+ 删除后话题从索引中消失,`ec thread list` 不再显示。底层 session 文件通过 `unbindSession` 机制移入 `chatDir/_trash/`,与系统其他删除行为一致。不能删除正在处理中(busy)的话题,也不能删除主话题。
128
128
 
129
129
  删除时会自动取消该话题的所有关联 Trigger,防止 ghost wakeup。
130
130
 
131
- 删除后历史仍可通过 `ec thread history <peer>/<threadId>` 读取(直接读 messages.jsonl,不依赖索引)。
131
+ 删除后历史仍可通过 `ec thread history <threadId>` 读取(直接读 messages.jsonl,不依赖索引)。
132
132
 
133
133
  ## 跨会话发送(话题链核心)
134
134
 
@@ -141,21 +141,34 @@ ec msg send <from> <to> '<消息内容>' --thread <threadId>
141
141
  # 托管会话简化形式(from/to 自动从运行时上下文推断)
142
142
  ec msg send '<消息内容>' --thread <threadId>
143
143
 
144
- # 附带复查 Trigger(跨话题时必填;每 30m 唤醒本端回查)
144
+ # 附带跨话题复查(跨话题时必填;每 30m 向目标话题投递一次复查通知)
145
145
  ec msg send '<消息内容>' --thread <threadId> --check-every 30m
146
146
  ```
147
147
 
148
148
  注意事项:
149
149
 
150
- - `--thread` 指定的话题必须已存在于本端索引(`ec thread list` 可见),否则返回 `TOPIC_NOT_FOUND`
150
+ - `--thread` 必须是本端已存在的话题:话题查索引,主话题(`main:<selfAid>:<peerAid>`)查该关系的 active session。都不存在时返回 `TOPIC_NOT_FOUND`
151
+ - **主话题可以作为跨话题发送的目标**。例如:
152
+ ```bash
153
+ # A 向 B 的主会话发送消息(从 A 的某个话题跨过去)
154
+ ec msg send '请在主会话查看这个报告' --thread 'main:bob.aid:alice.aid'
155
+ ```
156
+ 主话题的 ID 可以从 `ec thread list <peer>` 的输出中获取(第一行就是主话题)
151
157
  - **跨话题发送时 `--check-every` 为必填项**,不指定会直接报错。取值如 `5m` / `30m` / `2h` / `1d`
152
158
  - 跨话题发送成功后,系统会在**本端**写一条 thread-inbox 记录。目标话题下次被唤醒时,
153
- 这条记录会以「⟵ 跨会话上下文 · 来源话题:xxx」的形式注入一次,然后删除
154
- - `--check-every` 会创建周期复查 Trigger(名称 `check-<目标>-from-<来源>-<唯一后缀>`,`kind=thread-check`),
155
- 每隔指定时长唤醒本端话题,提示回查目标话题与来源话题,直到显式
156
- `ec trigger cancel <triggerId>` 结束。**每次发送都新建一个 Trigger**,取消/调整用
157
- 返回的 `trigger_id`(形如 `trig_…`)——`ec trigger` 的定位标识是 **id 不是名称**
158
- - `--trigger-prompt "<text>"` 可选,用于替换复查 prompt 中的自定义段(默认给出通用的检查/决策指引)
159
+ 这条记录会以「‹跨话题上下文 · 来源话题:xxx›」的形式注入一次,然后删除
160
+ - `--check-every` 会创建**跨话题复查**(名称 `check-<目标>-from-<来源>-<唯一后缀>`,
161
+ `kind=cross-thread-review`,执行类型 `target_session`)。到期时**不新建会话**,
162
+ 而是向**目标话题**投递一条【跨话题复查】通知,由目标话题侧的 agent 在它自己的上下文里
163
+ 决定:结束复查、调整周期、或继续等待
164
+ - 通知内容:复查次数、来源话题(名称 + threadId)、当前话题、发送时间、已过时长、
165
+ 复查周期、Trigger id、原消息正文
166
+ - 结束/调整用返回的 `trigger_id`(形如 `trig_…`)——`ec trigger` 的定位标识是 **id 不是名称**
167
+ - **结束复查用 `ec trigger delete <id>`,不要用 `ec trigger cancel`**:cancel 只是 disable,
168
+ 定义和调度状态仍留在磁盘上,复查这种用完即弃的 Trigger 会积压成大量永不触发的死定义
169
+ - **每次发送都新建一个复查**;要延长周期请用 `ec trigger update <id> --every <时长>`,
170
+ 不要重发一条带 `--check-every` 的消息
171
+ - `--trigger-prompt "<text>"` 可选,用于替换通知正文中的用户段
159
172
 
160
173
  ### 跨会话委托的完整流程
161
174
 
@@ -166,19 +179,40 @@ ec msg send '<消息内容>' --thread <threadId> --check-every 30m
166
179
  ec msg send '请处理项目A的数据清洗' --thread thread-T2-xxxx --check-every 2h
167
180
  ```
168
181
 
169
- **B 接收时感知来源上下文:**
182
+ **A 收到 B 的回复时感知来源上下文:**
170
183
 
171
- B 的目标话题下次被唤醒时,prompt 开头会注入一条跨会话上下文,格式如下:
184
+ inbox 记录在发送方 A 本端。A 的目标话题 T2 下次被唤醒时(通常是 B 回复),prompt 开头会注入一条跨话题上下文,格式如下:
172
185
 
173
186
  ```
174
- ‹跨会话上下文 · 来源话题:thread-T1-xxxx · 对端:alice.agentid.cn · 发送于:2026-10-10 10:00›
175
- ⚠️ 来源话题在发送后已有 3 条新消息(10:01 - 10:15)—— 处理前建议先回查该话题的空洞期消息。
176
- 🔔 复查 Trigger:trig_1791765199642_5371c8ff(尚未触发/待处理)
187
+ ‹【跨话题上下文】来源话题:thread-T1-xxxx · 对端:alice.agentid.cn · 发送于:2026-10-10 10:00:00 +08:00 · 复查:trig_1791765199642_5371c8ff → self:bob.agentid.cn›
188
+ ⚠️ 来源话题在发送后已有 3 条新消息(2026-10-10 10:01:00 +08:00 - 2026-10-10 10:15:00 +08:00)—— 处理前建议先回查该话题的空洞期消息。
177
189
  【原消息内容】
178
190
  ```
179
191
 
180
- 注入只发生一次。之后 B 靠自身上下文记住"我从哪个话题跨过来的",可随时用
181
- `ec thread history <来源peer>/<来源话题>` 回查空洞期消息。
192
+ 信封头的 `复查:` 字段恒出现:有复查 Trigger 时是它的 id,没建成时显示 `无`。
193
+
194
+ 注入只发生一次。之后 A 靠自身上下文记住"我从哪个话题跨过来的",可随时用
195
+ `ec thread history <来源话题 id>` 回查空洞期消息(主话题的 id 是 `main:<a>:<b>`,
196
+ 通知里的「来源话题 ID」字段可直接使用)。
197
+
198
+ **复查通知到达时(目标话题内):**
199
+
200
+ ```
201
+ ‹【跨话题复查】来源话题:thread-1792370100339-5976-0a5c · 对端:alice.agentid.cn · 发送于:2026-10-19 08:18:42 +08:00 · 复查:trig_1792369122624_aa1c9068 → self:bob.agentid.cn›
202
+ 【跨话题复查】第 2 次
203
+
204
+ 来源话题:A 的项目讨论(对端 alice.agentid.cn)
205
+ 来源话题 ID:thread-1792370100339-5976-0a5c
206
+ 当前话题:C 的进度查询(对端 carol.agentid.cn)
207
+ 发送于:2026-10-19 08:18:42
208
+ 已过:5 分钟
209
+ 复查周期:5m(每 5m 提醒一次,直到处理)
210
+
211
+ Trigger:trig_1792369122624_aa1c9068
212
+
213
+ 原消息:
214
+ 项目当前进度如何?
215
+ ```
182
216
 
183
217
  ## 话题摘要(Summary)
184
218
 
@@ -187,21 +221,21 @@ daemon 不自动总结,需要 agent 主动写入。
187
221
 
188
222
  ```bash
189
223
  # 查看当前摘要(同时打印 coveredThroughTs 覆盖游标)
190
- ec thread summary show <peer>/<threadId>
224
+ ec thread summary show <threadId>
191
225
 
192
226
  # 写入摘要 —— --name 必填:同时把话题改成这个标题
193
- ec thread summary set <peer>/<threadId> '项目A需求已确认,正在开发登录模块' --name '项目A登录模块'
227
+ ec thread summary set <threadId> '项目A需求已确认,正在开发登录模块' --name '项目A登录模块'
194
228
  # 不想改话题名就显式传 -
195
- ec thread summary set <peer>/<threadId> '<摘要内容>' --name -
229
+ ec thread summary set <threadId> '<摘要内容>' --name -
196
230
 
197
231
  # 支持 CAS(乐观锁),防止并发覆盖
198
- ec thread summary set <peer>/<threadId> '新内容' --name - --if-rev 3
232
+ ec thread summary set <threadId> '新内容' --name - --if-rev 3
199
233
 
200
234
  # 查看历史版本
201
- ec thread summary log <peer>/<threadId>
235
+ ec thread summary log <threadId>
202
236
 
203
237
  # 清空当前摘要(历史版本保留)
204
- ec thread summary clear <peer>/<threadId>
238
+ ec thread summary clear <threadId>
205
239
  ```
206
240
 
207
241
  ### 覆盖游标与增量总结
@@ -213,16 +247,16 @@ ec thread summary clear <peer>/<threadId>
213
247
 
214
248
  ```bash
215
249
  # 1. 拿覆盖游标
216
- ec thread summary show <peer>/<threadId> # 输出中的 coveredThroughTs
250
+ ec thread summary show <threadId> # 输出中的 coveredThroughTs
217
251
 
218
252
  # 2. 读游标之后的增量(首次总结无游标时省略 --after,全量读)
219
- ec thread history <peer>/<threadId> --after <coveredThroughTs> --limit 50
253
+ ec thread history <threadId> --after <coveredThroughTs> --limit 50
220
254
 
221
255
  # 3. 增量较多时往回翻页(history 支持 before 逆序分页)
222
- ec thread history <peer>/<threadId> --before <本页最早一条的ts> --limit 50
256
+ ec thread history <threadId> --before <本页最早一条的ts> --limit 50
223
257
 
224
258
  # 4. 读完增量后写摘要,游标自动推进到当前最新一条
225
- ec thread summary set <peer>/<threadId> '新摘要' --name -
259
+ ec thread summary set <threadId> '新摘要' --name -
226
260
  ```
227
261
 
228
262
  **约束**:`summary set` 把游标设为**写入时刻话题的最新一条**,所以跨话题总结必须**先把增量读完再写**——
@@ -242,7 +276,7 @@ CAS 说明:`--if-rev <n>` 指定当前已知的版本号;若实际版本不
242
276
  data/threads/
243
277
  ├── index.json 话题索引
244
278
  ├── summaries/ 话题摘要(<sessionId>.summary.jsonl)
245
- └── inbox/ 跨会话上下文收件箱
279
+ └── inbox/ 跨话题上下文收件箱
246
280
  ```
247
281
 
248
282
  ```bash
@@ -259,8 +293,15 @@ ec thread check-index # 同 rebuild-index --check
259
293
  | 格式 | 含义 |
260
294
  |---|---|
261
295
  | `current` | 当前任务所在话题 |
262
- | `<peer>` | 该对端的主会话 |
263
- | `<peer>/<threadId>` | 指定话题,如 `bob.agentid.cn/thread-xxx-0001-aaaa` |
296
+ | `<threadId>` | 话题,如 `thread-1791028341906-0000-136a` |
297
+ | `main:<selfAid>:<peerAid>` | 主话题,**规范格式**,两端 AID 顺序可互换 |
298
+
299
+ `ec thread list` 打印的第一列就是可用的话题 ID,可直接复制进任何接受 `<ref>` 的参数。
300
+
301
+ **主话题说明**:
302
+ - 主话题不在话题索引中,但可以作为 `threadId` 参数使用
303
+ - 规范格式是 `main:<selfAid>:<peerAid>`(两端 AID 哪个在前都行,系统会自动识别)
304
+ - 主话题 id 只有在**当前本端是其中一端**时才能解析;它不跨本端传播——拿到别人的主话题 id 会失败,而不是猜一个对端
264
305
 
265
306
  ## 话题状态值
266
307
 
@@ -281,3 +322,56 @@ ec thread check-index # 同 rebuild-index --check
281
322
  | `SUMMARY_CAS_CONFLICT` | 摘要版本冲突 | 重新 `show` 获取最新 rev,再重试 |
282
323
  | `INVALID_NAME` | 话题名称不合法 | 名称不能为空 |
283
324
  | `NAME_TOO_LONG` | 话题名称超过 83 字符(正文 80 + 省略号) | 按报错里的当前长度缩写后重试 |
325
+
326
+ ## Trigger 配置中的话题 ID
327
+
328
+ 在 Trigger 配置的 `origin` 字段中,可以用 `threadId` 指定投递目标话题(包括主话题)。系统会根据 `threadId` 的格式**自动推导** `origin.session` 的值,无需手动填写。
329
+
330
+ ### 配置示例
331
+
332
+ **投递到主会话**:
333
+
334
+ ```json
335
+ {
336
+ "$schema_version": 4,
337
+ "agentAid": "bob.agentid.pub",
338
+ "name": "每日同步",
339
+ "source": {
340
+ "type": "cron",
341
+ "cron": "0 9 * * *"
342
+ },
343
+ "origin": {
344
+ "channel": "aun",
345
+ "peerId": "alice.agentid.cn",
346
+ "threadId": "main:bob.agentid.pub:alice.agentid.cn"
347
+ },
348
+ "execution": {
349
+ "agentSessionId": "compact-start",
350
+ "prompt": "今日同步报告"
351
+ }
352
+ }
353
+ ```
354
+
355
+ **投递到指定话题**:
356
+
357
+ ```json
358
+ {
359
+ "origin": {
360
+ "channel": "aun",
361
+ "peerId": "alice.agentid.cn",
362
+ "threadId": "thread-1792370100339-5976-0a5c"
363
+ }
364
+ }
365
+ ```
366
+
367
+ ### 自动推导规则
368
+
369
+ | `threadId` 格式 | 自动推导的 `session` | 说明 |
370
+ |---|---|---|
371
+ | `main:<a>:<b>` | `'main'` | 主会话 |
372
+ | `thread-...` | `'thread'` | 话题会话 |
373
+ | 空/未填 | `'main'` | 默认主会话 |
374
+
375
+ 如果手动填写了 `origin.session` 字段,系统会校验它是否与推导结果一致。不一致时配置解析会报错。
376
+
377
+ **推荐做法**:只填 `threadId`,让系统自动推导 `session` 字段。
@@ -10,7 +10,7 @@
10
10
 
11
11
  文件输入限制为 4 MiB,拒绝符号链接、junction、硬链接、路径逃逸、其他会话临时目录、密钥及其他 Agent 私有数据。普通定义导入必须属于当前 Agent;脚本只上传 `execution.script.path` 指定的单个文件,不允许覆盖 `trigger.json`、`active.json` 等管理状态。绝对 `--script-path` 会上传脚本内容并保存 Agent 内相对路径,不保留宿主绝对路径。`--help` / `-h` 在鉴权和文件读取前返回。
12
12
 
13
- 普通脚本 Trigger 按每次执行重新核验的 Agent 授权运行,复用主会话的权限模式与 H/L 路径保护:`readonly` 项目只读且禁止读取 L 类路径,`auto/request` 项目可写、L 类路径只读;认证 `owner + bypass` 关闭项目写入沙箱,但仍遮蔽 H 类路径并保护 L 类路径。网络默认开放,不需要网络权限配置;保留宿主 HOME、Git/SSH 与代理环境,清除 daemon 凭据、任务 delegation 和代码注入变量。`request` 的非交互脚本不能申请额外权限,越界操作直接失败,不自动升级。脚本使用只读快照和独立临时工作目录;快照位置不同于持久化 Trigger 目录,需要项目资源时按工作目录定位。Node `.js` 保留原 package 的模块类型。
13
+ 普通脚本 Trigger 按每次执行重新核验的 Agent 授权运行,复用主话题的权限模式与 H/L 路径保护:`readonly` 项目只读且禁止读取 L 类路径,`auto/request` 项目可写、L 类路径只读;认证 `owner + bypass` 关闭项目写入沙箱,但仍遮蔽 H 类路径并保护 L 类路径。网络默认开放,不需要网络权限配置;保留宿主 HOME、Git/SSH 与代理环境,清除 daemon 凭据、任务 delegation 和代码注入变量。`request` 的非交互脚本不能申请额外权限,越界操作直接失败,不自动升级。脚本使用只读快照和独立临时工作目录;快照位置不同于持久化 Trigger 目录,需要项目资源时按工作目录定位。Node `.js` 保留原 package 的模块类型。
14
14
 
15
15
  - Linux:需要可用的 `bubblewrap`,复用会话权限运行时的进程隔离和 H/L 路径保护,不隔离网络命名空间;受限模式将宿主根目录只读映射,按权限开放项目和当前 run 临时目录,完整保留系统依赖及 `/etc/alternatives` 链接。
16
16
  - Windows:需要支持受限读取策略的原生 Codex CLI,以及宿主已准备好的 elevated sandbox。每次启动前先用同一个临时 canary 验证“显式授权可读、撤回授权后拒绝读取”和当前 run 可写;只有权限拒绝才算通过,文件不存在、探针超时或取消均失败关闭。旧初始化、不支持的运行时或无法证明读取隔离时返回 `SCRIPT_SANDBOX_UNAVAILABLE`,不会启动用户脚本;托管任务不会自动提权、初始化沙箱或降级为宿主执行。
@@ -119,7 +119,7 @@ Trigger V3 第二阶段使用 `execution.type` 区分执行位置:
119
119
 
120
120
  `target-session` 把 `--prompt` 或 `--prompt-file` 的内容当作一条 trigger 来源消息投递进目标会话队列,并等待该会话处理完成。创建时必须显式指定 `--exec target-session`,不会再隐式选择该类型。
121
121
 
122
- `target-session` 在主会话/话题会话执行时,默认没有额外的总执行时限,沿用普通任务的 idle watchdog 和 `idleMonitor.maxExecutionTime`;不会因运行超过 30 分钟或 4 小时而被 Trigger 强制结束。独立 `trigger-session` 默认每次 attempt 的总时限为 30 分钟。两者均可用 `--execution-timeout 2h`(definition 中为 `execution.timeoutMs`,毫秒正整数)显式设置,已有的全局任务时限仍可更早生效。`update --execution-timeout default` 清除单个 Trigger 的覆盖;script 继续使用 `--script-timeout`。
122
+ `target-session` 在主话题/话题会话执行时,默认没有额外的总执行时限,沿用普通任务的 idle watchdog 和 `idleMonitor.maxExecutionTime`;不会因运行超过 30 分钟或 4 小时而被 Trigger 强制结束。独立 `trigger-session` 默认每次 attempt 的总时限为 30 分钟。两者均可用 `--execution-timeout 2h`(definition 中为 `execution.timeoutMs`,毫秒正整数)显式设置,已有的全局任务时限仍可更早生效。`update --execution-timeout default` 清除单个 Trigger 的覆盖;script 继续使用 `--script-timeout`。
123
123
 
124
124
  目标会话每 30 秒核对一次具体 attempt 的队列、runner 与持久化终态。正常运行、排队、暂停及等待审批/回答不会仅因没有文本输出被清理;确认执行状态缺失并持续至少 120 秒后,按 `orphaned_target_session` 失败收尾。丢失的终态事件优先从持久化任务状态补齐。会话查找/创建另有 30 秒基础设施时限,不计为任务执行超时。
125
125
 
@@ -135,8 +135,37 @@ Trigger V3 第二阶段使用 `execution.type` 区分执行位置:
135
135
 
136
136
  省略 `--trigger-thread` 时默认使用 `by-trigger`,同一个 trigger 复用同一条 trigger 会话;只有显式指定 `--trigger-thread per-run` 时,每次 run 才使用独立 trigger 会话。
137
137
 
138
- `script` 执行随 trigger 一起保存的脚本:
138
+ ### 跨话题复查(kind=cross-thread-review)
139
+
140
+ `ec msg send --thread <T2> --check-every 5m` 创建的复查用 `target_session` 执行:
141
+ 到期时**不创建 trigger 会话**,而是把渲染好的通知作为一条入站消息投进目标话题 T2
142
+ 的本地会话队列,由 T2 侧的 agent 在 T2 自己的上下文里决策。
143
+
144
+ ```json
145
+ {
146
+ "labels": {
147
+ "kind": "cross-thread-review",
148
+ "originThreadId": "<来源话题 threadId>",
149
+ "targetThreadId": "<目标话题 threadId>",
150
+ "checkEvery": "5m",
151
+ "firstSentAt": "<首次发送时间戳>",
152
+ "originalText": "<原消息正文>"
153
+ },
154
+ "execution": { "type": "target_session", "prompt": "<通知模板>", "onError": "retry", "noopSentinel": "[[NOOP]]" },
155
+ "feedback": {
156
+ "strategy": "target",
157
+ "target": { "channelKey": "<channelKey>", "channelId": "<目标对端>", "session": "thread", "threadId": "<T2>", "chatType": "private" }
158
+ }
159
+ }
160
+ ```
161
+
162
+ - 通知模板在触发时由 `renderTemplate` 渲染,可用 `{{run.number}}`(第几次)、
163
+ `{{run.elapsed}}`(已过多久)、`{{trigger.labels.*}}` 等变量。
164
+ - 这类投递在消息上带 `triggerMeta.reviewKind = 'cross-thread-review'`,执行身份取
165
+ **目标话题会话自身的对端**,而不是 `originPeerId`(来源话题的对端)。
166
+ - 设计见 `docs/thread-chain/cross-thread-review-design.md`。
139
167
 
168
+ `script` 执行随 trigger 一起保存的脚本:
140
169
  ```bash
141
170
  --exec script \
142
171
  --script-path scripts/check.js \
@@ -254,6 +283,19 @@ ec trigger rm <triggerId> # delete 的兼容别名
254
283
 
255
284
  `delete` 不需要先执行 `disable/cancel`;它内部会先清理 timer/event/schedule,再删除定义。
256
285
 
286
+ > **用完即弃的 Trigger(如跨话题复查)结束时应使用 `delete` 而不是 `cancel`**:`cancel` 只写
287
+ > `enabled: false`,定义会一直留在 `$EVOLCORE_HOME/agents/<aid>/triggers/` 下,长期积累成
288
+ > 大量永不触发的死定义。
289
+
290
+ ## 谁可以操作一条 Trigger
291
+
292
+ 操作主体由定义的 `operatorPeers` 决定:创建时写入 **origin 对端 + feedback 目标对端**,
293
+ 两者都能 `show / list / update / cancel / delete / enable / disable`。旧定义没有该字段时
294
+ 按同样规则现算,不需要迁移。
295
+
296
+ 身份口径:私聊取对端 AID(`peerId`),群聊取**群 AID**(`channelId`,即 `group_id`)。
297
+ 群会话里 `origin.peerId` 记录的是群内发言人,不作为操作主体身份。
298
+
257
299
  ## 局部更新
258
300
 
259
301
  `update` 是 patch 语义,只提交需要修改的字段;未指定字段(包括长 prompt)保持不变。`--prompt-file <path>` 只更新非 script trigger 的 prompt,不接受完整 definition。已有 script trigger 使用 `--script-file <path>` 原地替换脚本内容;脚本路径、runtime、args 和调度配置保持不变:
@@ -461,6 +503,8 @@ daemon 启动时会自动维护一个名为 `__task-recovery` 的系统 Trigger
461
503
 
462
504
  系统 Trigger 直接调用内部 task recovery service,复用异常任务的原 `sessionId`、Agent AID、provider 会话、task generation 及原对话路由。它不会发送一条伪造的“继续”消息,不创建替代会话,也不会因为 daemon-owned 而把目标 Agent 的普通会话权限提升为操作系统权限。手动 `/resume` 和 `ec task resume <sessionId>` 仍然是同一恢复入口的人工调用方式。
463
505
 
506
+ 自动恢复仅接受 `recoverable: true` 的 `task:error`;`false` 或缺失均不触发。该标记由报错端基于原始错误统一判定,同时写入错误消息、事件和任务终态,不按 sandbox/socat 文本在恢复层另设黑名单。恢复执行自身的失败也传递该标记,只有明确可重试时才使用有界退避;不可重试的失败保留失败审计但不继续重跑。历史终态缺少该字段时不自动恢复,修复环境后仍可人工 `/resume`。
507
+
464
508
  下面的 Trigger 覆盖当前 Agent 的所有会话;`agentAid` 过滤避免其它 Agent 的事件进入本 Trigger,`originTriggerId` 排除自身产生的恢复错误,避免递归触发:
465
509
 
466
510
  ```json
@@ -475,6 +519,7 @@ daemon 启动时会自动维护一个名为 `__task-recovery` 的系统 Trigger
475
519
  "filter": {
476
520
  "match": {
477
521
  "agentAid": "<aid>",
522
+ "recoverable": true,
478
523
  "originTriggerId": { "$exists": false }
479
524
  }
480
525
  }