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
@@ -0,0 +1,248 @@
1
+ /**
2
+ * 话题身份。
3
+ *
4
+ * 话题是双边的:同一个话题在本端和对端各有一个会话。话题在创建时获得一个
5
+ * 双方共享的全局唯一 id(`thread-…`),因此 id 自身就能定位话题。主话题没有
6
+ * 创建动作、没有生成 id,它的身份完全由"本端 + 对端"这条关系决定,所以用
7
+ * 两个 AID 拼成一个与话题并列的 id:
8
+ *
9
+ * main:<aidA>:<aidB>
10
+ *
11
+ * 两端各自算出的字符串必须一致,因此格式化时按字典序排序;解析时两种顺序
12
+ * 都接受并归一到规范顺序,即 `main:<对端>:<本端>` 与 `main:<本端>:<对端>`
13
+ * 等价。
14
+ *
15
+ * 主话题 id 是**身份**,不是线上字段:信封本身已钉死收发双方,发出去只会让
16
+ * 对端凭空建出一个叫 `main:…` 的话题。它只用于本端寻址、持久化与展示。
17
+ */
18
+ export const MAIN_TOPIC_PREFIX = 'main:';
19
+ /**
20
+ * AID 段:不含 `:` 与 `/`,至少两级域名。
21
+ *
22
+ * 不能用 `isValidAid`:它要求三级以上,而群 AID(`g-xxx.agentid.cn`)只有两级。
23
+ * 话题的对端既可能是私聊 AID 也可能是群 AID,这里只做结构校验。
24
+ */
25
+ function isTopicAidSegment(value) {
26
+ const labels = value.split('.');
27
+ if (labels.length < 2)
28
+ return false;
29
+ return labels.every(label => /^[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?$/.test(label));
30
+ }
31
+ /** 统一输入形态:去空白与 `@` 前缀。不做域名展开、不改大小写。 */
32
+ export function normalizeTopicAid(value) {
33
+ return String(value ?? '').trim().replace(/^@/, '');
34
+ }
35
+ /**
36
+ * 由关系两端生成规范主话题 id。
37
+ *
38
+ * 排序保证两端独立计算得到同一个字符串;这也是"换个位置就一致"的实现方式,
39
+ * 而不是依赖调用方传对顺序。
40
+ */
41
+ export function formatMainTopicId(aidA, aidB) {
42
+ const a = normalizeTopicAid(aidA);
43
+ const b = normalizeTopicAid(aidB);
44
+ if (!isTopicAidSegment(a) || !isTopicAidSegment(b)) {
45
+ throw new Error(`Invalid AID for main topic: ${JSON.stringify(aidA)}, ${JSON.stringify(aidB)}`);
46
+ }
47
+ const [lo, hi] = a <= b ? [a, b] : [b, a];
48
+ return `${MAIN_TOPIC_PREFIX}${lo}:${hi}`;
49
+ }
50
+ export function isMainTopicId(value) {
51
+ if (typeof value !== 'string' || !value.startsWith(MAIN_TOPIC_PREFIX))
52
+ return false;
53
+ const parts = value.slice(MAIN_TOPIC_PREFIX.length).split(':');
54
+ return parts.length === 2 && parts.every(isTopicAidSegment);
55
+ }
56
+ /** 解析主话题 id;两种书写顺序都接受,返回去重后的两端(不保证顺序)。 */
57
+ export function parseMainTopicId(value) {
58
+ if (!isMainTopicId(value))
59
+ return undefined;
60
+ const [aidA, aidB] = value.slice(MAIN_TOPIC_PREFIX.length).split(':');
61
+ return { aidA, aidB };
62
+ }
63
+ /**
64
+ * 主话题 id 是否属于 `self`,是则返回对端。
65
+ *
66
+ * 这是主话题唯一的合法性判据:会话两端之外的人拿到这个 id 必须失败关闭,
67
+ * 不能"猜一个对端"。
68
+ */
69
+ export function mainTopicPeer(topicId, selfAid) {
70
+ const parsed = parseMainTopicId(topicId);
71
+ if (!parsed)
72
+ return undefined;
73
+ const self = normalizeTopicAid(selfAid);
74
+ if (parsed.aidA === self)
75
+ return parsed.aidB;
76
+ if (parsed.aidB === self)
77
+ return parsed.aidA;
78
+ return undefined;
79
+ }
80
+ /** 校验并归一到规范顺序;不是主话题 id 或含非法段时返回 undefined。 */
81
+ export function canonicalizeMainTopicId(value) {
82
+ const parsed = parseMainTopicId(value);
83
+ if (!parsed)
84
+ return undefined;
85
+ return formatMainTopicId(parsed.aidA, parsed.aidB);
86
+ }
87
+ /**
88
+ * 宽松版:任一侧不是合法 AID 段时返回 undefined 而不是抛错。
89
+ *
90
+ * 会话文件读取路径会碰到内部对端(`bg:` / `trigger:` / `daemon:` 等)与
91
+ * 非 AUN 渠道,那里不能因为拼不出主话题 id 就中断读取。
92
+ */
93
+ export function safeFormatMainTopicId(aidA, aidB) {
94
+ if (!aidA || !aidB)
95
+ return undefined;
96
+ try {
97
+ return formatMainTopicId(aidA, aidB);
98
+ }
99
+ catch {
100
+ return undefined;
101
+ }
102
+ }
103
+ /**
104
+ * 该 threadId 是否表示"主话题"(本端会话视角)。
105
+ *
106
+ * `''` 是历史落盘形态,`'main'` 是更早的哨兵值,`main:<a>:<b>` 是现行规范形态。
107
+ * 三者都表示主话题;任何需要区分"主话题 / 话题"的地方都必须用它,不能再用
108
+ * 真假判断——规范形态非空,真假判断会把主话题当成话题。
109
+ */
110
+ export function isMainSessionThreadId(value) {
111
+ if (value === undefined || value === null || value === '')
112
+ return true;
113
+ if (typeof value !== 'string')
114
+ return false;
115
+ return value === 'main' || isMainTopicId(value);
116
+ }
117
+ /** 该 threadId 是否表示话题(真正独立的话题会话)。同时作为类型谓词使用。 */
118
+ export function isTopicThreadId(value) {
119
+ return typeof value === 'string' && value !== '' && !isMainSessionThreadId(value);
120
+ }
121
+ /** 别名:旧代码中广泛使用的 isSubTopicThreadId,语义与 isTopicThreadId 完全一致。 */
122
+ export const isSubTopicThreadId = isTopicThreadId;
123
+ /**
124
+ * 把任意 threadId 形态(`''` / null / `'main'` / `main:<a>:<b>` / 话题 id)归一。
125
+ *
126
+ * `selfAid` / `peerId` 用于给历史形态(空串、`'main'`)补出规范主话题 id;
127
+ * 原值已是规范主话题 id 时以原值为准(归一到规范顺序)。
128
+ */
129
+ export function classifyThreadId(value, selfAid, peerId) {
130
+ if (isTopicThreadId(value))
131
+ return { kind: 'topic', threadId: value };
132
+ if (typeof value === 'string' && isMainTopicId(value)) {
133
+ return { kind: 'main', topicId: canonicalizeMainTopicId(value) };
134
+ }
135
+ return { kind: 'main', topicId: safeFormatMainTopicId(selfAid, peerId) };
136
+ }
137
+ /** switch 穷尽兜底:新增 kind 而调用方未处理时编译失败。 */
138
+ export function assertNeverThreadKind(value) {
139
+ throw new Error(`Unhandled thread kind: ${JSON.stringify(value)}`);
140
+ }
141
+ export function sessionThreadKind(session) {
142
+ return classifyThreadId(session.rawThreadId, session.selfAID, session.channelId);
143
+ }
144
+ /** 话题会话返回话题 id,主会话返回 undefined。用于线上 thread_id、话题屏障、getThreadSession 等话题专属路径。 */
145
+ export function sessionTopicThreadId(session) {
146
+ if (!session)
147
+ return undefined;
148
+ const k = sessionThreadKind(session);
149
+ return k.kind === 'topic' ? k.threadId : undefined;
150
+ }
151
+ /** 本端身份:话题返回话题 id,主会话返回规范主话题 id(拼不出时 undefined)。用于日志、展示、localTopicId。 */
152
+ export function sessionLocalTopicId(session) {
153
+ if (!session)
154
+ return undefined;
155
+ const k = sessionThreadKind(session);
156
+ return k.kind === 'topic' ? k.threadId : k.topicId;
157
+ }
158
+ // 两者都返回 boolean 而非类型谓词:谓词会把 false 分支收窄成 never,
159
+ // 而"不是话题"的会话仍是会话。需要非空收窄时调用方自己写 `s && isMainSession(s)`。
160
+ export function isTopicSession(session) {
161
+ return sessionTopicThreadId(session) !== undefined;
162
+ }
163
+ /** 非空且为主会话。session 为空时返回 false(不是"话题"也不是"主会话")。 */
164
+ export function isMainSession(session) {
165
+ return !!session && !isTopicSession(session);
166
+ }
167
+ /**
168
+ * 解析话题引用。
169
+ *
170
+ * 规范形态只有两种:`main:<aid>:<aid>` 与裸 `thread-…`。
171
+ * 裸 `main` 一律拒绝——没有对端就无法确定发给谁,系统不做"默认当前对端"的补全。
172
+ * 历史写法 `<peer>/<id>` 仍可解析(它已在多处命令中存在),但主话题的
173
+ * `<peer>/main` 从未实现过,直接拒绝并指向新形态。
174
+ *
175
+ * 裸值是按形态区分的:形如 AID(至少两级、只含域名安全字符)的值视为**主话题的对端**,
176
+ * 解析成 `main:<该AID>:<self>`;其他裸值是话题 id。这个歧义无法彻底消除,但两种
177
+ * 形态的字符集不重叠(话题 id 是 `thread-…`,不含点),按 AID 结构判断是安全的。
178
+ */
179
+ export function resolveThreadRef(ref, selfAid) {
180
+ const raw = String(ref ?? '').trim();
181
+ if (!raw)
182
+ return { kind: 'current' };
183
+ if (raw === 'current')
184
+ return { kind: 'current' };
185
+ if (isMainTopicId(raw)) {
186
+ const peer = mainTopicPeer(raw, selfAid);
187
+ if (!peer) {
188
+ return {
189
+ kind: 'invalid',
190
+ error: `主话题 ${raw} 不属于当前本端 ${normalizeTopicAid(selfAid)}——主话题 id 由本端与对端共同构成`,
191
+ };
192
+ }
193
+ const topicId = canonicalizeMainTopicId(raw) ?? raw;
194
+ return { kind: 'main', topicId, peer };
195
+ }
196
+ if (raw === 'main') {
197
+ return {
198
+ kind: 'invalid',
199
+ error: '裸 main 不是可用的话题 id:主话题必须写明双方,形如 main:<对端AID>:<本端AID>',
200
+ };
201
+ }
202
+ const slash = raw.lastIndexOf('/');
203
+ if (slash >= 0) {
204
+ const peer = raw.slice(0, slash);
205
+ const rest = raw.slice(slash + 1);
206
+ if (rest === 'main') {
207
+ return {
208
+ kind: 'invalid',
209
+ error: `<对端>/main 不是话题 id:主话题请用 main:<对端AID>:<本端AID>(如 ec thread list 输出所示)`,
210
+ };
211
+ }
212
+ if (!peer || !rest) {
213
+ return { kind: 'invalid', error: `无效的话题引用: ${raw}` };
214
+ }
215
+ return { kind: 'thread', threadId: rest, peer };
216
+ }
217
+ // 裸对端 AID → 该关系的主话题(`ec thread rename <peer>` 等历史写法的语义)。
218
+ // self 缺失时无法拼出主话题 id,仍按话题 id 处理,由调用方报"不存在"。
219
+ const self = normalizeTopicAid(selfAid);
220
+ if (self && isTopicAidSegment(raw)) {
221
+ const topicId = formatMainTopicId(self, raw);
222
+ return { kind: 'main', topicId, peer: raw };
223
+ }
224
+ return { kind: 'thread', threadId: raw };
225
+ }
226
+ /**
227
+ * history 类命令 `--thread` 值的归一:接受 `ec thread list` 打印的展示形态 `<peer>/<id>`,
228
+ * 剥掉对端前缀后返回裸 id;其余值原样返回(裸话题 id、`main:<a>:<b>`、`all` 等由调用方
229
+ * 各自校验)。写了前缀时 `samePeer` 必须认可它与本次查询的对端一致,否则拒绝——
230
+ * 不能拿别的对端的话题引用去读当前对端的历史。
231
+ */
232
+ export function normalizeThreadOptionValue(value, samePeer) {
233
+ const raw = value.trim();
234
+ const slash = raw.lastIndexOf('/');
235
+ if (slash < 0)
236
+ return { ok: true, threadId: raw };
237
+ const peer = raw.slice(0, slash).replace(/^@/, '');
238
+ const threadId = raw.slice(slash + 1);
239
+ if (!peer || !threadId)
240
+ return { ok: false, error: `无效的话题引用: ${raw}` };
241
+ if (threadId === 'main') {
242
+ return { ok: false, error: `<对端>/main 不是话题 id:主话题请用 main:<对端AID>:<本端AID>` };
243
+ }
244
+ if (samePeer && !samePeer(peer)) {
245
+ return { ok: false, error: `话题引用 ${raw} 的对端与查询对象不一致` };
246
+ }
247
+ return { ok: true, threadId, peer };
248
+ }
@@ -233,7 +233,7 @@ const PARAM_DESCRIPTIONS = {
233
233
  VENUES_DIR: '当前 agent 环境数据目录',
234
234
  selfAid: '当前 agent 的 AID',
235
235
  selfName: '当前 agent 的显示名',
236
- lifecycle: '当前 agent 生命周期(created/bootstrapping/active)',
236
+ lifecycle: '当前 agent 生命周期(created/ownerpending/bootstrapping/active)',
237
237
  isBootstrapping: '当前 agent 是否处于 bootstrap 首次设定阶段',
238
238
  hasPersona: '是否有 persona 内容',
239
239
  hasWorkingMemory: '是否有 working memory',
@@ -133,7 +133,7 @@ function renderOneItem(item, sessionVars, sessionCache, contentSentinel) {
133
133
  injectTime: isOwnerHint
134
134
  ? formatLocalTime(item.injectTime ?? item.timestamp ?? Date.now(), sessionVars.timezone ? String(sessionVars.timezone) : undefined)
135
135
  : undefined,
136
- // T4: 跨会话上下文(thread-inbox 注入)
136
+ // T4: 跨话题上下文(thread-inbox 注入)
137
137
  isThreadContext,
138
138
  threadContextOriginThreadId: item.threadContext?.originThreadId,
139
139
  threadContextOriginPeer: item.threadContext?.originPeer,
@@ -153,7 +153,9 @@ function renderOneItem(item, sessionVars, sessionCache, contentSentinel) {
153
153
  const tz = sessionVars.timezone ? String(sessionVars.timezone) : undefined;
154
154
  return `${formatLocalTime(g.firstTimestamp, tz)} - ${formatLocalTime(g.lastTimestamp, tz)}`;
155
155
  })(),
156
- threadContextTriggerId: item.threadContext?.triggerId,
156
+ // 信封头的"复查"字段恒出现:复查 Trigger 没建成时显示"无",不能整行省略——
157
+ // 省略时 agent 无从察觉复查缺失(2026-10-20 复查全部静默创建失败即如此)。
158
+ threadContextTriggerId: item.threadContext?.triggerId ?? '无',
157
159
  // T9: trigger 消息专属信封变量
158
160
  isTriggerMsg,
159
161
  triggerMsgId: isTriggerMsg ? item.triggerInfo?.triggerId : undefined,
@@ -161,6 +163,14 @@ function renderOneItem(item, sessionVars, sessionCache, contentSentinel) {
161
163
  triggerMsgFireTime: isTriggerMsg && item.triggerInfo?.fireTime !== undefined
162
164
  ? formatLocalTime(item.triggerInfo.fireTime, sessionVars.timezone ? String(sessionVars.timezone) : undefined)
163
165
  : undefined,
166
+ // 跨话题复查信封的"发送于":原消息首次发送时间(labels.firstSentAt,ms 字符串),
167
+ // 与跨话题上下文信封的"发送于"同义、同格式。
168
+ triggerMsgFirstSentTime: (() => {
169
+ const ms = isTriggerMsg ? Number(item.triggerInfo?.labels?.firstSentAt) : NaN;
170
+ return Number.isFinite(ms) && ms > 0
171
+ ? formatLocalTime(ms, sessionVars.timezone ? String(sessionVars.timezone) : undefined)
172
+ : undefined;
173
+ })(),
164
174
  // T10: labels 路由 key(默认 'default')+ 动态展开 triggerMsgLabel_<key>
165
175
  triggerMsgKind: isTriggerMsg ? (item.triggerInfo?.labels?.kind ?? 'default') : undefined,
166
176
  ...(isTriggerMsg && item.triggerInfo?.labels
package/dist/index.js CHANGED
@@ -14,10 +14,12 @@ import { CodexSessionFileAdapter } from './core/session/adapters/codex-session-f
14
14
  import { GeminiSessionFileAdapter } from './core/session/adapters/gemini-session-file-adapter.js';
15
15
  import { EcagentSessionFileAdapter } from './core/session/adapters/ecagent-session-file-adapter.js';
16
16
  import { loadDefaults, loadAllAgents, migrateIdentitiesIfNeeded, loadDaemonConfig, initializeEckSnapshotsConfig } from './config-store.js';
17
+ import { inspectClaudeSandboxDependencies, formatClaudeSandboxDependencies } from './core/permission/sandbox-runtime.js';
17
18
  import { migrateRelationSharedDirectories } from './core/relation/shared-data.js';
18
19
  import { DEFAULT_ECWEB_PORT, ecwebService } from './config/daemon-services.js';
19
- import { ConfigTarget, onConfigWrite, shouldFailFastForMissingOwners } from './config/config-manager.js';
20
+ import { ConfigTarget, onConfigWrite } from './config/config-manager.js';
20
21
  import { expirePendingContactRequests } from './config/contact-request-service.js';
22
+ import { synchronizeOwnershipContactsSync } from './config/contact-book-store.js';
21
23
  import { createSessionIdentityResolver } from './config/peer-role-resolver.js';
22
24
  import { initializeStartupConfig, prepareStartupConfig, recordStartupConfig } from './config/boot-log.js';
23
25
  import { CONFIG_SCHEMA_VERSION } from './types.js';
@@ -43,6 +45,7 @@ import { readFastaunVersion, readInstalledEvolcoreVersion, reportEvolcoreStartup
43
45
  import { recoverAllRoleMutationsSync } from './core/command/role-menu.js';
44
46
  import { HandoffRuntime } from './core/handoff/runtime.js';
45
47
  import { startDaemonControlAid } from './core/daemon-control.js';
48
+ import { ownerResolver, getDaemonOwners } from './core/ownership/owner-resolver.js';
46
49
  import { cleanupStartupHandoffs, recoverStartupHandoffs, resumePendingSessions, createDaemonShutdown, daemonConversationTotalExecutionMs, daemonConversationWatchdogMs, daemonIdleTimeoutMs, } from './core/daemon-lifecycle.js';
47
50
  import { BootstrapService, createBootstrapCompletionHandler, createBootstrapOwnerBoundHandler } from './core/bootstrap-service.js';
48
51
  import { MessageCache } from './core/message/message-cache.js';
@@ -188,17 +191,19 @@ async function main() {
188
191
  loadKitManifest();
189
192
  // 加载配置(新结构:defaults.json + per-agent config.json)
190
193
  const defaults = loadDefaults() ?? { $schema_version: CONFIG_SCHEMA_VERSION };
191
- let processLevelOwners = daemonCfg.owners ?? [];
192
- const bindBootstrapMode = process.env.EVOLCORE_BIND_BOOTSTRAP === '1';
193
- if (processLevelOwners.length === 0 && shouldFailFastForMissingOwners()) {
194
- throw new Error('daemon.json.owners is required when EVOLCORE_REQUIRE_OWNERS=1');
194
+ const sandboxDependencies = inspectClaudeSandboxDependencies();
195
+ if (sandboxDependencies.status === 'missing') {
196
+ logger.warn(`[ClaudeSandbox] ${formatClaudeSandboxDependencies(sandboxDependencies)}`);
195
197
  }
196
- // 进程级 menu 操作(/system /agent)鉴权:owners 来自 daemon.json 顶层。
197
- // owners 为空时这些操作一律 FORBIDDEN,启动时提示如何配置。
198
- if (processLevelOwners.length === 0) {
199
- logger.warn('[startup] daemon.json.owners 未配置:进程级 menu 操作(/system /agent)将一律拒绝。' +
200
- '如需远程管理,请在 daemon.json 配置 owners: [<你的 AID>]');
198
+ if (daemonCfg.aid) {
199
+ ownerResolver.setDaemonAid(daemonCfg.aid);
200
+ ownerResolver.setConfiguredOwners(daemonCfg.aid, [
201
+ daemonCfg.owner,
202
+ ...(daemonCfg.owners ?? []),
203
+ ].filter((owner) => typeof owner === 'string'));
201
204
  }
205
+ const processLevelOwners = getDaemonOwners;
206
+ const bindBootstrapMode = process.env.EVOLCORE_BIND_BOOTSTRAP === '1';
202
207
  const paths = resolvePaths();
203
208
  // ECWeb has one lifecycle owner: the daemon. The CLI may have started an
204
209
  // instance just before spawning us; the supervisor adopts it when healthy,
@@ -333,16 +338,29 @@ async function main() {
333
338
  receiverAid: daemonCfg.aid,
334
339
  getAvailableBaseagents: detectAvailableBaseagents,
335
340
  getUptimeSeconds: () => Math.floor(process.uptime()),
336
- onDaemonOwnersUpdated: (owners) => { processLevelOwners = owners; },
337
- onAgentOwnerUpdated: createBootstrapOwnerBoundHandler({
338
- getService: () => bootstrapService,
339
- agentRegistry,
340
- channelInstances,
341
- eventBus,
342
- }),
343
341
  })
344
342
  : null;
345
343
  bindService?.startCleanup();
344
+ const onProtocolOwnerBound = createBootstrapOwnerBoundHandler({
345
+ getService: () => bootstrapService, agentRegistry, channelInstances, eventBus,
346
+ });
347
+ let initializationServiceForOwnerRecovery;
348
+ const stopOwnerNotifications = ownerResolver.onChange((subjectAid, ownerAid) => {
349
+ permissionGateway.revalidatePendingApprovals(subjectAid);
350
+ if (agentRegistry.get(subjectAid)) {
351
+ try {
352
+ synchronizeOwnershipContactsSync(subjectAid);
353
+ }
354
+ catch (error) {
355
+ logger.warn(`[ownership] Contact role synchronization failed: self=${subjectAid} error=${error instanceof Error ? error.message : String(error)}`);
356
+ }
357
+ }
358
+ if (!ownerAid)
359
+ return;
360
+ initializationServiceForOwnerRecovery?.resumeForOwner(subjectAid, ownerAid);
361
+ onProtocolOwnerBound(subjectAid, ownerAid);
362
+ });
363
+ onShutdown(() => { stopOwnerNotifications(); ownerResolver.stop(); });
346
364
  const agentDelegationRegistry = new AgentDelegationRegistry();
347
365
  // Replace any inherited marker from a parent/previous daemon before child
348
366
  // runners or in-process IPC clients are created.
@@ -424,7 +442,7 @@ async function main() {
424
442
  processor.setMessageQueue(messageQueue);
425
443
  const handoffQueueTtlMs = daemonIdleTimeoutMs(globalSettings);
426
444
  const taskExecutionTtlMs = daemonConversationTotalExecutionMs(globalSettings);
427
- const handoffRuntime = new HandoffRuntime(sessionManager, messageQueue, createAunHandoffSender(sessionManager, channelInstances), undefined, { queueTtlMs: handoffQueueTtlMs });
445
+ const handoffRuntime = new HandoffRuntime(sessionManager, messageQueue, createAunHandoffSender(sessionManager, channelInstances, sessionId => responseEngine.getOutboundDebug(sessionId)), undefined, { queueTtlMs: handoffQueueTtlMs });
428
446
  responseEngine.setHandoffRuntime(handoffRuntime);
429
447
  cmdHandler.setHandoffRuntime(handoffRuntime);
430
448
  // Trigger runtime: daemon-level script + feedback scheduler.
@@ -471,12 +489,13 @@ async function main() {
471
489
  projectPath: primaryAgent?.projectPath || process.cwd(),
472
490
  };
473
491
  cmdHandler.setDaemonTriggerOwner(daemonTriggerOwner.aid, daemonChannel.channelName);
492
+ responseEngine.setDaemonTriggerOwner(daemonTriggerOwner.aid);
474
493
  const getTriggerChannel = createTriggerChannelResolver({ agentRegistry, channelInstances, daemonChannel, daemonTriggerOwner });
475
494
  const triggerAuthorizationDependencies = {
476
495
  agentDelegationRegistry,
477
496
  daemonTriggerOwner,
478
497
  getAgent: (agentAid) => agentRegistry.get(agentAid),
479
- getDaemonOwners: () => loadDaemonConfig().owners ?? [],
498
+ getDaemonOwners,
480
499
  getTriggerChannel,
481
500
  sessionManager,
482
501
  triggerControlToken,
@@ -490,7 +509,7 @@ async function main() {
490
509
  });
491
510
  };
492
511
  const authorizeTriggerExecution = (definition) => (authorizeTriggerRun(definition, {
493
- getDaemonOwners: () => loadDaemonConfig().owners ?? [],
512
+ getDaemonOwners,
494
513
  }));
495
514
  const authenticatedTriggerActor = (agentAid, actorSessionId, delegationToken, delegationCommandHash, controlToken, contextOnly = false) => authenticateTriggerActor(triggerAuthorizationDependencies, agentAid, actorSessionId, delegationToken, delegationCommandHash, controlToken, contextOnly);
496
515
  const sendConsolidationFeedback = createConsolidationFeedbackSender((agentAid, channelKey) => {
@@ -549,7 +568,7 @@ async function main() {
549
568
  return !!inst && inst.channel.getStatus?.().connected === true;
550
569
  };
551
570
  cmdHandler.setAgentStorageClientResolver(createAgentStorageClientResolver(channelInstances));
552
- const msgBridge = new MessageBridge(defaultProjectPath, sessionManager, processor, messageQueue, cmdHandler, eventBus, primaryAgent?.config.debounce, () => processLevelOwners);
571
+ const msgBridge = new MessageBridge(defaultProjectPath, sessionManager, processor, messageQueue, cmdHandler, eventBus, primaryAgent?.config.debounce, processLevelOwners);
553
572
  msgBridge.setAgentRegistry(agentRegistry);
554
573
  msgBridge.setInteractionRouter(interactionRouter);
555
574
  msgBridge.setGroupInviteReviewService(groupInviteReviewService);
@@ -629,7 +648,7 @@ async function main() {
629
648
  // A failed bind (for example, a stale Windows named pipe) must abort startup
630
649
  // without creating a second AUN session that can kick the old daemon.
631
650
  let controlChannel;
632
- const diagService = new DiagService(() => ({ controlAid: loadDaemonConfig().aid, owners: loadDaemonConfig().owners ?? [] }), async (to, text) => {
651
+ const diagService = new DiagService(() => ({ controlAid: loadDaemonConfig().aid, owners: getDaemonOwners() }), async (to, text) => {
633
652
  if (!controlChannel)
634
653
  throw new Error('Control AID channel is unavailable');
635
654
  const result = await controlChannel.sendDaemonMsg({ to, payload: { type: 'text', text }, encrypt: true });
@@ -647,7 +666,7 @@ async function main() {
647
666
  runtimeIsDist,
648
667
  runtimeBuildIdentity,
649
668
  diskDistDir,
650
- getProcessOwners: () => processLevelOwners,
669
+ getProcessOwners: processLevelOwners,
651
670
  getAgentRuntimeState: () => agentRuntimeState,
652
671
  getAgentRuntimeError: () => agentRuntimeError,
653
672
  daemonAid: daemonCfg.aid,
@@ -722,7 +741,10 @@ async function main() {
722
741
  resync: coreResyncAgents,
723
742
  create: async (options) => {
724
743
  const { agentCreateNonInteractive } = await import('./cli/agent-create.js');
725
- return await agentCreateNonInteractive(options, { hotLoadAgent: coreHotLoadAgent });
744
+ return await agentCreateNonInteractive(options, {
745
+ hotLoadAgent: coreHotLoadAgent,
746
+ bindOwnerAgent: (aid, ownerAid) => ownerResolver.bind(aid, ownerAid),
747
+ });
726
748
  },
727
749
  aunAids: () => channelInstances.flatMap(instance => {
728
750
  if (instance.channelType !== 'aun')
@@ -739,9 +761,10 @@ async function main() {
739
761
  hotLoad: coreHotLoadAgent,
740
762
  activate: completeAgentBootstrap,
741
763
  });
764
+ initializationServiceForOwnerRecovery = agentInitializationService;
742
765
  agentApplicationService.setInitializationService(agentInitializationService);
743
766
  cmdHandler.setAgentApplicationService(agentApplicationService);
744
- ipcServer.setRemoteAccessOwnerProvider(() => processLevelOwners[0]);
767
+ ipcServer.setRemoteAccessOwnerProvider(() => processLevelOwners()[0]);
745
768
  cmdHandler.setDaemonMonitorProvider(() => ipcServer.getMonitorSnapshot().snapshot);
746
769
  ipcServer.setShutdownExecutor(async (reason) => {
747
770
  if (!shutdown) {
@@ -781,7 +804,7 @@ async function main() {
781
804
  },
782
805
  bindService,
783
806
  diagService,
784
- getProcessOwners: () => loadDaemonConfig().owners ?? [],
807
+ getProcessOwners: getDaemonOwners,
785
808
  getControlAidState: () => controlChannel?.getAidState?.(),
786
809
  daemonAid: daemonCfg.aid,
787
810
  triggerControlToken,
@@ -836,7 +859,7 @@ async function main() {
836
859
  cmdHandler,
837
860
  bindService,
838
861
  diagService,
839
- getProcessOwners: () => loadDaemonConfig().owners ?? [],
862
+ getProcessOwners: getDaemonOwners,
840
863
  });
841
864
  // 统一 channel:health 跨通道通知(仅 auth_error)
842
865
  registerChannelHealthNotifications({ eventBus, channelInstances, agentRegistry });
package/dist/ipc.js CHANGED
@@ -23,6 +23,8 @@ import { remoteAccessService } from './core/auth/remote-access-store.js';
23
23
  import { setModelCatalogDaemonOwner } from './core/model/model-catalog.js';
24
24
  import { RUNTIME_ENVIRONMENT_NAMES, setRuntimeEnvironmentOverride } from './config/runtime-env.js';
25
25
  import { MAIN_CLI_BIN } from './product.js';
26
+ import { ownerResolver } from './core/ownership/owner-resolver.js';
27
+ import { parseOwnershipCommand, executeOwnershipCommand, ownershipFailure } from './aun/aid/ownership-operation.js';
26
28
  import { delegationDiagnosticMessage, withDelegationDiagnosticContext, } from './core/auth/delegation-diagnostics.js';
27
29
  const isWindows = process.platform === 'win32';
28
30
  const isNamedPipe = (p) => isWindows && p.toLowerCase().startsWith('\\\\.\\pipe\\');
@@ -83,7 +85,7 @@ const MEMORY_COMMAND_ENDPOINTS = new Set([
83
85
  'memory.create', 'memory.update', 'memory.archive', 'memory.demote', 'memory.consolidate',
84
86
  ]);
85
87
  const DELEGATED_ARGV_ENDPOINTS = new Set([
86
- 'agent.op', 'config.op', 'contact.op', 'aid.op', 'group.op', 'msg.op', 'fs.op',
88
+ 'agent.op', 'config.op', 'contact.op', 'aid.op', 'aid.ownership', 'group.op', 'msg.op', 'fs.op',
87
89
  'ctl', 'diag', 'menu-client.request', 'task.resume', 'queue.op', 'storage.auth', 'storage.upload',
88
90
  'trigger.op', 'skill.refresh', 'thread.op', 'local-command-context', 'evolagent.bootstrapComplete', ...MEMORY_COMMAND_ENDPOINTS,
89
91
  'handoff-return', 'handoff-recover-return', 'handoff-status', 'handoff-list', 'handoff-trace',
@@ -114,6 +116,8 @@ function requiresLocalControlToken(cmd) {
114
116
  return true;
115
117
  if (type === 'debug-issue-token')
116
118
  return true;
119
+ if (type === 'aid.ownership')
120
+ return !sessionId || !delegated;
117
121
  if (type === 'skill.refresh' || type === 'thread.op')
118
122
  return !sessionId || !delegated;
119
123
  return ['evolagent.bootstrapComplete', 'diag', 'handoff-status', 'handoff-list', 'handoff-trace', 'task.resume'].includes(type)
@@ -198,6 +202,7 @@ export class IpcServer {
198
202
  systemSessionCommandGate;
199
203
  codexPreToolUseExecutor;
200
204
  aunMsgSender;
205
+ aunRequestGetExecutor;
201
206
  diagExecutor;
202
207
  menuClientExecutor;
203
208
  handoffReturnExecutor;
@@ -206,6 +211,7 @@ export class IpcServer {
206
211
  handoffListExecutor;
207
212
  handoffTraceExecutor;
208
213
  bindExecutor;
214
+ aidOwnershipExecutor;
209
215
  configOperationExecutor;
210
216
  contactOperationExecutor;
211
217
  aidOperationExecutor;
@@ -508,6 +514,9 @@ export class IpcServer {
508
514
  setAunMsgSender(sender) {
509
515
  this.aunMsgSender = sender;
510
516
  }
517
+ setAunRequestGetExecutor(executor) {
518
+ this.aunRequestGetExecutor = executor;
519
+ }
511
520
  hasAunMsgSender() {
512
521
  return this.aunMsgSender !== undefined;
513
522
  }
@@ -538,6 +547,9 @@ export class IpcServer {
538
547
  setBindExecutor(executor) {
539
548
  this.bindExecutor = executor;
540
549
  }
550
+ setAidOwnershipExecutor(executor) {
551
+ this.aidOwnershipExecutor = executor;
552
+ }
541
553
  /** Inject DingTalk contact binding-code executor. */
542
554
  setDingtalkContactBindExecutor(executor) {
543
555
  this.dingtalkContactBindExecutor = executor;
@@ -1088,7 +1100,13 @@ export class IpcServer {
1088
1100
  return { ok: false, error: 'Invalid model catalog scope' };
1089
1101
  }
1090
1102
  try {
1091
- const { getLocalCatalog } = await import('./core/model/model-catalog.js');
1103
+ const { getLocalCatalog, getLocalProviderCatalog } = await import('./core/model/model-catalog.js');
1104
+ if (cmd.providerId !== undefined || cmd.serviceType !== undefined) {
1105
+ if (typeof cmd.providerId !== 'string' || typeof cmd.serviceType !== 'string' || cmd.self !== undefined) {
1106
+ return { ok: false, error: 'Invalid provider catalog scope' };
1107
+ }
1108
+ return { ok: true, snapshot: await getLocalProviderCatalog(cmd.providerId, cmd.serviceType, cmd.refresh === true) };
1109
+ }
1092
1110
  return { ok: true, snapshot: await getLocalCatalog(cmd.self, cmd.baseagent, cmd.refresh === true) };
1093
1111
  }
1094
1112
  catch {
@@ -1191,6 +1209,23 @@ export class IpcServer {
1191
1209
  return { ok: false, error: 'bind executor not configured' };
1192
1210
  return this.bindExecutor.cancel(cmd.taskId);
1193
1211
  }
1212
+ case 'aid.ownership': {
1213
+ if (!Array.isArray(cmd.argv) || cmd.argv.some((value) => typeof value !== 'string')) {
1214
+ return { ok: false, code: 'INVALID_ARGUMENT', error: 'Ownership argv is required' };
1215
+ }
1216
+ if (cmd.sessionId || cmd.delegationToken) {
1217
+ if (!this.aidOwnershipExecutor)
1218
+ return { ok: false, code: 'DELEGATION_REQUIRED', error: 'Managed ownership is unavailable' };
1219
+ return this.aidOwnershipExecutor(cmd.argv, cmd.sessionId, cmd.delegationToken, cmd.delegationCommandHash);
1220
+ }
1221
+ try {
1222
+ const command = parseOwnershipCommand(cmd.argv);
1223
+ return { ok: true, state: await executeOwnershipCommand(command, ownerResolver.getDaemonAid()) };
1224
+ }
1225
+ catch (error) {
1226
+ return ownershipFailure(error);
1227
+ }
1228
+ }
1194
1229
  case 'dingtalk.contact-bind.register': {
1195
1230
  if (!this.dingtalkContactBindExecutor) {
1196
1231
  return { ok: false, error: 'dingtalk contact bind executor not configured' };
@@ -1476,6 +1511,21 @@ export class IpcServer {
1476
1511
  }
1477
1512
  return this.debugIssueTokenExecutor({ sessionId: cmd.sessionId });
1478
1513
  }
1514
+ case 'aun-msg-request-get': {
1515
+ if (!this.aunRequestGetExecutor)
1516
+ return { ok: false, code: 'NOT_CONFIGURED', error: 'AUN request registry is not configured' };
1517
+ if (typeof cmd.aid !== 'string' || !cmd.aid)
1518
+ return { ok: false, code: 'INVALID_REQUEST', error: 'missing aid' };
1519
+ if (typeof cmd.requestId !== 'string' || !cmd.requestId)
1520
+ return { ok: false, code: 'INVALID_REQUEST', error: 'missing requestId' };
1521
+ return this.aunRequestGetExecutor({
1522
+ aid: cmd.aid,
1523
+ requestId: cmd.requestId,
1524
+ sessionId: typeof cmd.sessionId === 'string' ? cmd.sessionId : undefined,
1525
+ delegationToken: typeof cmd.delegationToken === 'string' ? cmd.delegationToken : undefined,
1526
+ delegationCommandHash: typeof cmd.delegationCommandHash === 'string' ? cmd.delegationCommandHash : undefined,
1527
+ });
1528
+ }
1479
1529
  case 'aun-msg-send': {
1480
1530
  if (cmd.argv !== undefined) {
1481
1531
  if (!this.aunMsgSender)
@@ -1529,7 +1579,7 @@ export class IpcServer {
1529
1579
  }
1530
1580
  : undefined;
1531
1581
  try {
1532
- const normalizedPayload = payload && Object.prototype.hasOwnProperty.call(payload, 'mentions')
1582
+ const normalizedPayload = cmd.rawPayload !== true && payload && Object.prototype.hasOwnProperty.call(payload, 'mentions')
1533
1583
  ? { ...payload, mentions: normalizeAunMentionEntries(payload.mentions) }
1534
1584
  : payload;
1535
1585
  return await this.aunMsgSender({
@@ -1537,6 +1587,7 @@ export class IpcServer {
1537
1587
  to: cmd.to,
1538
1588
  scope: cmd.scope === 'group' ? 'group' : 'msg',
1539
1589
  payload: normalizedPayload,
1590
+ rawPayload: cmd.rawPayload === true,
1540
1591
  file,
1541
1592
  mentions: Object.prototype.hasOwnProperty.call(cmd, 'mentions')
1542
1593
  ? normalizeAunMentionEntries(cmd.mentions)
@@ -1546,6 +1597,8 @@ export class IpcServer {
1546
1597
  handoffContext: cmd.handoffContext,
1547
1598
  originSessionId: typeof cmd.originSessionId === 'string' ? cmd.originSessionId : undefined,
1548
1599
  originMessageId: typeof cmd.originMessageId === 'string' ? cmd.originMessageId : undefined,
1600
+ returnPolicy: cmd.returnPolicy === 'required' ? 'required' : cmd.returnPolicy === 'none' ? 'none' : undefined,
1601
+ timeoutMs: typeof cmd.timeoutMs === 'number' && Number.isFinite(cmd.timeoutMs) ? cmd.timeoutMs : undefined,
1549
1602
  delegationToken: typeof cmd.delegationToken === 'string' ? cmd.delegationToken : undefined,
1550
1603
  delegationCommandHash: typeof cmd.delegationCommandHash === 'string' ? cmd.delegationCommandHash : undefined,
1551
1604
  log,
@@ -1765,7 +1818,7 @@ export class IpcServer {
1765
1818
  if (disabled)
1766
1819
  return disabled;
1767
1820
  const ownerAid = taskCtx.selfAid
1768
- ? this.agentRegistry?.get(taskCtx.selfAid)?.config?.owners?.[0]
1821
+ ? ownerResolver.primaryOwner(taskCtx.selfAid)
1769
1822
  : undefined;
1770
1823
  const { launchConsolidation } = await import('./core/memory/consolidation.js');
1771
1824
  if (!this.consolidationLaunchExecutor) {
@@ -2412,7 +2465,7 @@ export class IpcServer {
2412
2465
  if (disabled)
2413
2466
  return { error: disabled };
2414
2467
  const ownerAid = taskCtx.selfAid
2415
- ? this.agentRegistry?.get(taskCtx.selfAid)?.config?.owners?.[0]
2468
+ ? ownerResolver.primaryOwner(taskCtx.selfAid)
2416
2469
  : undefined;
2417
2470
  if (allowed === 'owner' && !ownerAid) {
2418
2471
  return { error: { ok: false, code: 'INVALID_REQUEST', error: '当前 agent 未配置 owner' } };
@@ -2481,7 +2534,7 @@ export class IpcServer {
2481
2534
  try {
2482
2535
  if (!this.consolidationLaunchExecutor)
2483
2536
  return;
2484
- const ownerAid = this.agentRegistry?.get(selfAid)?.config?.owners?.[0];
2537
+ const ownerAid = ownerResolver.primaryOwner(selfAid);
2485
2538
  await this.consolidationLaunchExecutor({
2486
2539
  taskCtx,
2487
2540
  mode: 'forget',
package/dist/paths.js CHANGED
@@ -34,6 +34,7 @@ export function resolvePaths() {
34
34
  outboxDir: path.join(root, 'data', 'outbox'),
35
35
  dataDir: path.join(root, 'data'),
36
36
  claudeModelCache: path.join(root, 'data', 'claude-model-cache.json'),
37
+ providersConfig: path.join(root, 'providers.json'),
37
38
  logs: path.join(root, 'logs'),
38
39
  agentsDir,
39
40
  lineStats: path.join(root, 'logs', 'line-stats.log'),