evolcore 0.0.4 → 0.0.6

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 (332) hide show
  1. package/CHANGELOG.md +65 -3
  2. package/README.md +4 -12
  3. package/dist/agents/baseagent.js +39 -0
  4. package/dist/agents/claude-runner.js +10 -2
  5. package/dist/agents/codex-runner.js +37 -8
  6. package/dist/agents/ecagent-runner.js +1159 -0
  7. package/dist/agents/gemini-runner.js +4 -1
  8. package/dist/agents/runner-types.js +20 -4
  9. package/dist/aun/msg/history.js +32 -9
  10. package/dist/aun/outbox.js +4 -9
  11. package/dist/channels/aun.js +32 -6
  12. package/dist/channels/daemon.js +7 -4
  13. package/dist/channels/dingtalk.js +3 -5
  14. package/dist/channels/feishu.js +16 -108
  15. package/dist/channels/wechat.js +4 -4
  16. package/dist/channels/wecom.js +4 -6
  17. package/dist/cli/agent-command.js +1 -1
  18. package/dist/cli/agent.js +42 -11
  19. package/dist/cli/aun-commands.js +50 -3
  20. package/dist/cli/daemon-commands.js +127 -21
  21. package/dist/cli/data-command.js +132 -0
  22. package/dist/cli/index.js +11 -3
  23. package/dist/cli/init.js +116 -37
  24. package/dist/cli/net-check.js +9 -20
  25. package/dist/cli/restart-monitor.js +11 -2
  26. package/dist/cli/trigger-command.js +1 -1
  27. package/dist/cli/watch-msg.js +12 -25
  28. package/dist/config/access-policy-domain.js +0 -20
  29. package/dist/config/access-policy.js +5 -29
  30. package/dist/config/builtin-roles.js +3 -1
  31. package/dist/config/config-field-policy.js +1 -1
  32. package/dist/config/gateway-config.js +21 -4
  33. package/dist/config/resolved-config-op.js +10 -0
  34. package/dist/core/auth/operation-catalog.js +1 -1
  35. package/dist/core/command/command-handler.js +2 -2
  36. package/dist/core/command/connect-menu.js +20 -42
  37. package/dist/core/command/menu-handler.js +11 -9
  38. package/dist/core/command/role-menu.js +27 -0
  39. package/dist/core/command/slash-handler.js +18 -14
  40. package/dist/core/data-migration.js +1434 -0
  41. package/dist/core/handoff/store.js +14 -4
  42. package/dist/core/inference/text-inference.js +42 -1
  43. package/dist/core/message/inbound-admission.js +23 -13
  44. package/dist/core/message/pending-hints.js +1 -1
  45. package/dist/core/message/response-engine.js +406 -167
  46. package/dist/core/message/retry-scheduler.js +71 -0
  47. package/dist/core/model/model-catalog.js +7 -2
  48. package/dist/core/model/model-fallback.js +81 -0
  49. package/dist/core/protected-paths.js +41 -8
  50. package/dist/core/session/adapters/ecagent-session-file-adapter.js +112 -0
  51. package/dist/core/session/session-fs-store.js +300 -61
  52. package/dist/core/session/session-manager.js +225 -21
  53. package/dist/core/session/session-title.js +1 -0
  54. package/dist/core/session/session-turn-coordinator.js +8 -1
  55. package/dist/core/system-channels.js +1 -0
  56. package/dist/index.js +10 -9
  57. package/dist/paths.js +35 -27
  58. package/dist/trigger/feedback.js +16 -0
  59. package/dist/trigger/legacy-session-history.js +19 -0
  60. package/dist/trigger/manager.js +12 -1
  61. package/dist/trigger/parser.js +4 -2
  62. package/dist/trigger/scheduler.js +185 -15
  63. package/dist/trigger/session-lock.js +62 -0
  64. package/dist/trigger/state.js +64 -0
  65. package/dist/trigger/validation.js +32 -2
  66. package/dist/utils/aid-bind.js +1 -1
  67. package/dist/utils/cross-platform.js +8 -2
  68. package/dist/utils/error-utils.js +9 -0
  69. package/dist/utils/process-introspect.js +19 -3
  70. package/dist/utils/welcome.js +2 -3
  71. package/ecagent/LICENSE +21 -0
  72. package/ecagent/NOTICE +11 -0
  73. package/ecagent/README.md +61 -0
  74. package/ecagent/dist/agent-loop.d.ts +24 -0
  75. package/ecagent/dist/agent-loop.d.ts.map +1 -0
  76. package/ecagent/dist/agent-loop.js +547 -0
  77. package/ecagent/dist/agent-loop.js.map +1 -0
  78. package/ecagent/dist/agent.d.ts +127 -0
  79. package/ecagent/dist/agent.d.ts.map +1 -0
  80. package/ecagent/dist/agent.js +386 -0
  81. package/ecagent/dist/agent.js.map +1 -0
  82. package/ecagent/dist/harness/agent-harness.d.ts +95 -0
  83. package/ecagent/dist/harness/agent-harness.d.ts.map +1 -0
  84. package/ecagent/dist/harness/agent-harness.js +926 -0
  85. package/ecagent/dist/harness/agent-harness.js.map +1 -0
  86. package/ecagent/dist/harness/compaction/branch-summarization.d.ts +51 -0
  87. package/ecagent/dist/harness/compaction/branch-summarization.d.ts.map +1 -0
  88. package/ecagent/dist/harness/compaction/branch-summarization.js +174 -0
  89. package/ecagent/dist/harness/compaction/branch-summarization.js.map +1 -0
  90. package/ecagent/dist/harness/compaction/compaction.d.ts +95 -0
  91. package/ecagent/dist/harness/compaction/compaction.d.ts.map +1 -0
  92. package/ecagent/dist/harness/compaction/compaction.js +528 -0
  93. package/ecagent/dist/harness/compaction/compaction.js.map +1 -0
  94. package/ecagent/dist/harness/compaction/utils.d.ts +25 -0
  95. package/ecagent/dist/harness/compaction/utils.d.ts.map +1 -0
  96. package/ecagent/dist/harness/compaction/utils.js +131 -0
  97. package/ecagent/dist/harness/compaction/utils.js.map +1 -0
  98. package/ecagent/dist/harness/env/nodejs.d.ts +51 -0
  99. package/ecagent/dist/harness/env/nodejs.d.ts.map +1 -0
  100. package/ecagent/dist/harness/env/nodejs.js +513 -0
  101. package/ecagent/dist/harness/env/nodejs.js.map +1 -0
  102. package/ecagent/dist/harness/messages.d.ts +51 -0
  103. package/ecagent/dist/harness/messages.d.ts.map +1 -0
  104. package/ecagent/dist/harness/messages.js +102 -0
  105. package/ecagent/dist/harness/messages.js.map +1 -0
  106. package/ecagent/dist/harness/prompt-templates.d.ts +48 -0
  107. package/ecagent/dist/harness/prompt-templates.d.ts.map +1 -0
  108. package/ecagent/dist/harness/prompt-templates.js +230 -0
  109. package/ecagent/dist/harness/prompt-templates.js.map +1 -0
  110. package/ecagent/dist/harness/session/jsonl-repo.d.ts +26 -0
  111. package/ecagent/dist/harness/session/jsonl-repo.d.ts.map +1 -0
  112. package/ecagent/dist/harness/session/jsonl-repo.js +100 -0
  113. package/ecagent/dist/harness/session/jsonl-repo.js.map +1 -0
  114. package/ecagent/dist/harness/session/jsonl-storage.d.ts +34 -0
  115. package/ecagent/dist/harness/session/jsonl-storage.d.ts.map +1 -0
  116. package/ecagent/dist/harness/session/jsonl-storage.js +234 -0
  117. package/ecagent/dist/harness/session/jsonl-storage.js.map +1 -0
  118. package/ecagent/dist/harness/session/memory-repo.d.ts +18 -0
  119. package/ecagent/dist/harness/session/memory-repo.d.ts.map +1 -0
  120. package/ecagent/dist/harness/session/memory-repo.js +44 -0
  121. package/ecagent/dist/harness/session/memory-repo.js.map +1 -0
  122. package/ecagent/dist/harness/session/memory-storage.d.ts +25 -0
  123. package/ecagent/dist/harness/session/memory-storage.d.ts.map +1 -0
  124. package/ecagent/dist/harness/session/memory-storage.js +111 -0
  125. package/ecagent/dist/harness/session/memory-storage.js.map +1 -0
  126. package/ecagent/dist/harness/session/repo-utils.d.ts +11 -0
  127. package/ecagent/dist/harness/session/repo-utils.d.ts.map +1 -0
  128. package/ecagent/dist/harness/session/repo-utils.js +39 -0
  129. package/ecagent/dist/harness/session/repo-utils.js.map +1 -0
  130. package/ecagent/dist/harness/session/session.d.ts +47 -0
  131. package/ecagent/dist/harness/session/session.d.ts.map +1 -0
  132. package/ecagent/dist/harness/session/session.js +245 -0
  133. package/ecagent/dist/harness/session/session.js.map +1 -0
  134. package/ecagent/dist/harness/session/uuid.d.ts +2 -0
  135. package/ecagent/dist/harness/session/uuid.d.ts.map +1 -0
  136. package/ecagent/dist/harness/session/uuid.js +50 -0
  137. package/ecagent/dist/harness/session/uuid.js.map +1 -0
  138. package/ecagent/dist/harness/skills.d.ts +44 -0
  139. package/ecagent/dist/harness/skills.d.ts.map +1 -0
  140. package/ecagent/dist/harness/skills.js +311 -0
  141. package/ecagent/dist/harness/skills.js.map +1 -0
  142. package/ecagent/dist/harness/system-prompt.d.ts +3 -0
  143. package/ecagent/dist/harness/system-prompt.d.ts.map +1 -0
  144. package/ecagent/dist/harness/system-prompt.js +30 -0
  145. package/ecagent/dist/harness/system-prompt.js.map +1 -0
  146. package/ecagent/dist/harness/types.d.ts +619 -0
  147. package/ecagent/dist/harness/types.d.ts.map +1 -0
  148. package/ecagent/dist/harness/types.js +81 -0
  149. package/ecagent/dist/harness/types.js.map +1 -0
  150. package/ecagent/dist/harness/utils/shell-output.d.ts +14 -0
  151. package/ecagent/dist/harness/utils/shell-output.d.ts.map +1 -0
  152. package/ecagent/dist/harness/utils/shell-output.js +126 -0
  153. package/ecagent/dist/harness/utils/shell-output.js.map +1 -0
  154. package/ecagent/dist/harness/utils/truncate.d.ts +70 -0
  155. package/ecagent/dist/harness/utils/truncate.d.ts.map +1 -0
  156. package/ecagent/dist/harness/utils/truncate.js +290 -0
  157. package/ecagent/dist/harness/utils/truncate.js.map +1 -0
  158. package/ecagent/dist/index.d.ts +22 -0
  159. package/ecagent/dist/index.d.ts.map +1 -0
  160. package/ecagent/dist/index.js +27 -0
  161. package/ecagent/dist/index.js.map +1 -0
  162. package/ecagent/dist/node.d.ts +3 -0
  163. package/ecagent/dist/node.d.ts.map +1 -0
  164. package/ecagent/dist/node.js +3 -0
  165. package/ecagent/dist/node.js.map +1 -0
  166. package/ecagent/dist/proxy.d.ts +69 -0
  167. package/ecagent/dist/proxy.d.ts.map +1 -0
  168. package/ecagent/dist/proxy.js +278 -0
  169. package/ecagent/dist/proxy.js.map +1 -0
  170. package/ecagent/dist/runtime/api/lazy.d.ts +15 -0
  171. package/ecagent/dist/runtime/api/lazy.d.ts.map +1 -0
  172. package/ecagent/dist/runtime/api/lazy.js +59 -0
  173. package/ecagent/dist/runtime/api/lazy.js.map +1 -0
  174. package/ecagent/dist/runtime/api/pi-messages.d.ts +97 -0
  175. package/ecagent/dist/runtime/api/pi-messages.d.ts.map +1 -0
  176. package/ecagent/dist/runtime/api/pi-messages.js +307 -0
  177. package/ecagent/dist/runtime/api/pi-messages.js.map +1 -0
  178. package/ecagent/dist/runtime/api/pi-messages.lazy.d.ts +3 -0
  179. package/ecagent/dist/runtime/api/pi-messages.lazy.d.ts.map +1 -0
  180. package/ecagent/dist/runtime/api/pi-messages.lazy.js +3 -0
  181. package/ecagent/dist/runtime/api/pi-messages.lazy.js.map +1 -0
  182. package/ecagent/dist/runtime/auth/context.d.ts +7 -0
  183. package/ecagent/dist/runtime/auth/context.d.ts.map +1 -0
  184. package/ecagent/dist/runtime/auth/context.js +42 -0
  185. package/ecagent/dist/runtime/auth/context.js.map +1 -0
  186. package/ecagent/dist/runtime/auth/credential-store.d.ts +16 -0
  187. package/ecagent/dist/runtime/auth/credential-store.d.ts.map +1 -0
  188. package/ecagent/dist/runtime/auth/credential-store.js +39 -0
  189. package/ecagent/dist/runtime/auth/credential-store.js.map +1 -0
  190. package/ecagent/dist/runtime/auth/helpers.d.ts +20 -0
  191. package/ecagent/dist/runtime/auth/helpers.d.ts.map +1 -0
  192. package/ecagent/dist/runtime/auth/helpers.js +46 -0
  193. package/ecagent/dist/runtime/auth/helpers.js.map +1 -0
  194. package/ecagent/dist/runtime/auth/resolve.d.ts +26 -0
  195. package/ecagent/dist/runtime/auth/resolve.d.ts.map +1 -0
  196. package/ecagent/dist/runtime/auth/resolve.js +100 -0
  197. package/ecagent/dist/runtime/auth/resolve.js.map +1 -0
  198. package/ecagent/dist/runtime/auth/types.d.ts +180 -0
  199. package/ecagent/dist/runtime/auth/types.d.ts.map +1 -0
  200. package/ecagent/dist/runtime/auth/types.js +2 -0
  201. package/ecagent/dist/runtime/auth/types.js.map +1 -0
  202. package/ecagent/dist/runtime/compat.d.ts +28 -0
  203. package/ecagent/dist/runtime/compat.d.ts.map +1 -0
  204. package/ecagent/dist/runtime/compat.js +86 -0
  205. package/ecagent/dist/runtime/compat.js.map +1 -0
  206. package/ecagent/dist/runtime/index.d.ts +20 -0
  207. package/ecagent/dist/runtime/index.d.ts.map +1 -0
  208. package/ecagent/dist/runtime/index.js +17 -0
  209. package/ecagent/dist/runtime/index.js.map +1 -0
  210. package/ecagent/dist/runtime/models.d.ts +142 -0
  211. package/ecagent/dist/runtime/models.d.ts.map +1 -0
  212. package/ecagent/dist/runtime/models.js +245 -0
  213. package/ecagent/dist/runtime/models.js.map +1 -0
  214. package/ecagent/dist/runtime/oauth.d.ts +2 -0
  215. package/ecagent/dist/runtime/oauth.d.ts.map +1 -0
  216. package/ecagent/dist/runtime/oauth.js +2 -0
  217. package/ecagent/dist/runtime/oauth.js.map +1 -0
  218. package/ecagent/dist/runtime/providers/faux.d.ts +97 -0
  219. package/ecagent/dist/runtime/providers/faux.d.ts.map +1 -0
  220. package/ecagent/dist/runtime/providers/faux.js +395 -0
  221. package/ecagent/dist/runtime/providers/faux.js.map +1 -0
  222. package/ecagent/dist/runtime/types.d.ts +607 -0
  223. package/ecagent/dist/runtime/types.d.ts.map +1 -0
  224. package/ecagent/dist/runtime/types.js +2 -0
  225. package/ecagent/dist/runtime/types.js.map +1 -0
  226. package/ecagent/dist/runtime/utils/diagnostics.d.ts +19 -0
  227. package/ecagent/dist/runtime/utils/diagnostics.d.ts.map +1 -0
  228. package/ecagent/dist/runtime/utils/diagnostics.js +25 -0
  229. package/ecagent/dist/runtime/utils/diagnostics.js.map +1 -0
  230. package/ecagent/dist/runtime/utils/event-stream.d.ts +21 -0
  231. package/ecagent/dist/runtime/utils/event-stream.d.ts.map +1 -0
  232. package/ecagent/dist/runtime/utils/event-stream.js +77 -0
  233. package/ecagent/dist/runtime/utils/event-stream.js.map +1 -0
  234. package/ecagent/dist/runtime/utils/headers.d.ts +4 -0
  235. package/ecagent/dist/runtime/utils/headers.d.ts.map +1 -0
  236. package/ecagent/dist/runtime/utils/headers.js +18 -0
  237. package/ecagent/dist/runtime/utils/headers.js.map +1 -0
  238. package/ecagent/dist/runtime/utils/json-parse.d.ts +16 -0
  239. package/ecagent/dist/runtime/utils/json-parse.d.ts.map +1 -0
  240. package/ecagent/dist/runtime/utils/json-parse.js +113 -0
  241. package/ecagent/dist/runtime/utils/json-parse.js.map +1 -0
  242. package/ecagent/dist/runtime/utils/oauth/types.d.ts +64 -0
  243. package/ecagent/dist/runtime/utils/oauth/types.d.ts.map +1 -0
  244. package/ecagent/dist/runtime/utils/oauth/types.js +2 -0
  245. package/ecagent/dist/runtime/utils/oauth/types.js.map +1 -0
  246. package/ecagent/dist/runtime/utils/overflow.d.ts +58 -0
  247. package/ecagent/dist/runtime/utils/overflow.d.ts.map +1 -0
  248. package/ecagent/dist/runtime/utils/overflow.js +158 -0
  249. package/ecagent/dist/runtime/utils/overflow.js.map +1 -0
  250. package/ecagent/dist/runtime/utils/provider-env.d.ts +7 -0
  251. package/ecagent/dist/runtime/utils/provider-env.d.ts.map +1 -0
  252. package/ecagent/dist/runtime/utils/provider-env.js +44 -0
  253. package/ecagent/dist/runtime/utils/provider-env.js.map +1 -0
  254. package/ecagent/dist/runtime/utils/retry.d.ts +12 -0
  255. package/ecagent/dist/runtime/utils/retry.d.ts.map +1 -0
  256. package/ecagent/dist/runtime/utils/retry.js +90 -0
  257. package/ecagent/dist/runtime/utils/retry.js.map +1 -0
  258. package/ecagent/dist/runtime/utils/typebox-helpers.d.ts +17 -0
  259. package/ecagent/dist/runtime/utils/typebox-helpers.d.ts.map +1 -0
  260. package/ecagent/dist/runtime/utils/typebox-helpers.js +21 -0
  261. package/ecagent/dist/runtime/utils/typebox-helpers.js.map +1 -0
  262. package/ecagent/dist/runtime/utils/validation.d.ts +18 -0
  263. package/ecagent/dist/runtime/utils/validation.d.ts.map +1 -0
  264. package/ecagent/dist/runtime/utils/validation.js +269 -0
  265. package/ecagent/dist/runtime/utils/validation.js.map +1 -0
  266. package/ecagent/dist/types.d.ts +401 -0
  267. package/ecagent/dist/types.d.ts.map +1 -0
  268. package/ecagent/dist/types.js +2 -0
  269. package/ecagent/dist/types.js.map +1 -0
  270. package/ecagent/package.json +93 -0
  271. package/ecagent/src/agent-loop.ts +792 -0
  272. package/ecagent/src/agent.ts +575 -0
  273. package/ecagent/src/harness/agent-harness.ts +1029 -0
  274. package/ecagent/src/harness/compaction/branch-summarization.ts +261 -0
  275. package/ecagent/src/harness/compaction/compaction.ts +753 -0
  276. package/ecagent/src/harness/compaction/utils.ts +144 -0
  277. package/ecagent/src/harness/env/nodejs.ts +569 -0
  278. package/ecagent/src/harness/messages.ts +164 -0
  279. package/ecagent/src/harness/prompt-templates.ts +267 -0
  280. package/ecagent/src/harness/session/jsonl-repo.ts +179 -0
  281. package/ecagent/src/harness/session/jsonl-storage.ts +314 -0
  282. package/ecagent/src/harness/session/memory-repo.ts +50 -0
  283. package/ecagent/src/harness/session/memory-storage.ts +133 -0
  284. package/ecagent/src/harness/session/repo-utils.ts +51 -0
  285. package/ecagent/src/harness/session/session.ts +338 -0
  286. package/ecagent/src/harness/session/uuid.ts +54 -0
  287. package/ecagent/src/harness/skills.ts +375 -0
  288. package/ecagent/src/harness/system-prompt.ts +34 -0
  289. package/ecagent/src/harness/types.ts +838 -0
  290. package/ecagent/src/harness/utils/shell-output.ts +135 -0
  291. package/ecagent/src/harness/utils/truncate.ts +344 -0
  292. package/ecagent/src/index.ts +46 -0
  293. package/ecagent/src/node.ts +2 -0
  294. package/ecagent/src/proxy.ts +367 -0
  295. package/ecagent/src/runtime/api/lazy.ts +70 -0
  296. package/ecagent/src/runtime/api/pi-messages.lazy.ts +4 -0
  297. package/ecagent/src/runtime/api/pi-messages.ts +436 -0
  298. package/ecagent/src/runtime/auth/context.ts +45 -0
  299. package/ecagent/src/runtime/auth/credential-store.ts +47 -0
  300. package/ecagent/src/runtime/auth/helpers.ts +46 -0
  301. package/ecagent/src/runtime/auth/resolve.ts +141 -0
  302. package/ecagent/src/runtime/auth/types.ts +182 -0
  303. package/ecagent/src/runtime/compat.ts +158 -0
  304. package/ecagent/src/runtime/index.ts +31 -0
  305. package/ecagent/src/runtime/models.ts +452 -0
  306. package/ecagent/src/runtime/oauth.ts +1 -0
  307. package/ecagent/src/runtime/providers/faux.ts +538 -0
  308. package/ecagent/src/runtime/types.ts +718 -0
  309. package/ecagent/src/runtime/utils/diagnostics.ts +45 -0
  310. package/ecagent/src/runtime/utils/event-stream.ts +88 -0
  311. package/ecagent/src/runtime/utils/headers.ts +18 -0
  312. package/ecagent/src/runtime/utils/json-parse.ts +124 -0
  313. package/ecagent/src/runtime/utils/oauth/types.ts +79 -0
  314. package/ecagent/src/runtime/utils/overflow.ts +165 -0
  315. package/ecagent/src/runtime/utils/provider-env.ts +52 -0
  316. package/ecagent/src/runtime/utils/retry.ts +101 -0
  317. package/ecagent/src/runtime/utils/typebox-helpers.ts +24 -0
  318. package/ecagent/src/runtime/utils/validation.ts +310 -0
  319. package/ecagent/src/types.ts +430 -0
  320. package/ecagent/tsconfig.build.json +32 -0
  321. package/kits/docs/evolcore/config.md +4 -4
  322. package/kits/docs/evolcore/contact.md +2 -1
  323. package/kits/schemas/_meta.json +7 -4
  324. package/kits/schemas/agent-config.schema.10.json +370 -0
  325. package/kits/schemas/agent-config.schema.9.json +2 -12
  326. package/kits/schemas/defaults.schema.4.json +93 -0
  327. package/kits/schemas/relation-config.schema.8.json +69 -0
  328. package/kits/templates/roles/admin.json +1 -1
  329. package/package.json +22 -6
  330. package/skills/eclink/SKILL.md +70 -0
  331. package/skills/eclink/agents/openai.yaml +4 -0
  332. package/assets/.env.template +0 -4
@@ -15,16 +15,17 @@ import fs from 'fs';
15
15
  import path from 'path';
16
16
  import { resolvePaths } from '../paths.js';
17
17
  import { saveDefaultsSafe, saveAgent } from '../config-store.js';
18
- import { resolveAnthropicConfig, resolveOpenaiConfig } from '../agents/baseagent.js';
18
+ import { resolveAnthropicConfig, resolveEcagentConfig, resolveOpenaiConfig } from '../agents/baseagent.js';
19
19
  import { resolvePriceRow } from '../stats/billing.js';
20
20
  import { ipcQuery } from '../ipc.js';
21
21
  import { logger } from '../utils/logger.js';
22
22
  /** 已知 baseagent 类型(网关可管理范围)。 */
23
- const GATEWAY_TYPES = ['claude', 'codex', 'gemini'];
23
+ const GATEWAY_TYPES = ['claude', 'codex', 'gemini', 'ecagent'];
24
24
  const DISPLAY_NAMES = {
25
25
  claude: 'Claude',
26
26
  codex: 'Codex (OpenAI)',
27
27
  gemini: 'Gemini',
28
+ ecagent: 'ecagent (EvolCore)',
28
29
  };
29
30
  // ── 掩码 ──
30
31
  const ENV_PREFIX = '$ENV:';
@@ -362,7 +363,7 @@ function buildPatch(type, patch) {
362
363
  else
363
364
  return { error: 'apiKey 仅接受 "$ENV:NAME" 环境变量引用,不接受明文' };
364
365
  }
365
- if (type === 'claude' || type === 'codex') {
366
+ if (type === 'claude' || type === 'codex' || type === 'ecagent') {
366
367
  if (patch.effort !== undefined)
367
368
  f.effort = String(patch.effort).trim() || undefined;
368
369
  }
@@ -383,6 +384,16 @@ function buildPatch(type, patch) {
383
384
  if (patch.location !== undefined)
384
385
  f.location = String(patch.location).trim() || undefined;
385
386
  }
387
+ if (type === 'ecagent') {
388
+ for (const key of ['timeoutMs', 'maxRetries', 'maxRetryDelayMs']) {
389
+ if (patch[key] !== undefined) {
390
+ const value = Number(patch[key]);
391
+ if (!Number.isFinite(value) || value < 0)
392
+ return { error: `${key} 必须是非负数字` };
393
+ f[key] = value;
394
+ }
395
+ }
396
+ }
386
397
  return { fields: f };
387
398
  }
388
399
  /** 触发 reload:defaults 改动影响全部 agent(resync),单 agent 改动只 reload 它。 */
@@ -485,6 +496,10 @@ function resolveGatewayCreds(scope, type) {
485
496
  const r = resolveAnthropicConfig(synth, expanded);
486
497
  return { baseUrl: r.baseUrl, apiKey: r.apiKey };
487
498
  }
499
+ else if (type === 'ecagent') {
500
+ const r = resolveEcagentConfig(synth, expanded);
501
+ return { baseUrl: r.baseUrl, apiKey: r.apiKey };
502
+ }
488
503
  return { error: 'gemini 暂不支持 HTTP 探测(CLI 后端)', code: 'NOT_SUPPORTED' };
489
504
  }
490
505
  catch (e) {
@@ -507,7 +522,9 @@ export async function gatewayTest(args) {
507
522
  try {
508
523
  const controller = new AbortController();
509
524
  const timer = setTimeout(() => controller.abort(), 5000);
510
- const resp = await fetch(`${baseUrl.replace(/\/+$/, '')}/v1/models`, {
525
+ const base = baseUrl.replace(/\/+$/, '');
526
+ const modelsUrl = base.endsWith('/v1') ? `${base}/models` : `${base}/v1/models`;
527
+ const resp = await fetch(modelsUrl, {
511
528
  headers: apiKey ? { Authorization: `Bearer ${apiKey}` } : {},
512
529
  signal: controller.signal,
513
530
  });
@@ -110,6 +110,16 @@ function resolveFieldCommand(argv, subcommand, options = {}) {
110
110
  reason: 'Agent role policies are managed through the role policy editor',
111
111
  };
112
112
  }
113
+ const canContainFallbackModels = field === 'baseagents'
114
+ || /^baseagents\.[^.]+$/.test(field)
115
+ || /^baseagents\.[^.]+\.fallbackModels(?:\.|$)/.test(field);
116
+ if (subcommand !== 'get' && canContainFallbackModels) {
117
+ return {
118
+ ok: false,
119
+ code: 'DEFAULTS_FILE_ONLY',
120
+ reason: 'fallbackModels is configured only by editing agents/defaults.json',
121
+ };
122
+ }
113
123
  const fieldRule = resolveConfigFieldRule(field);
114
124
  if (subcommand !== 'get' && fieldRule.class === 'safe-readonly-object') {
115
125
  return {
@@ -397,7 +397,7 @@ const OPERATIONS = [
397
397
  category: 'write-agent',
398
398
  dangerous: false,
399
399
  defaultScopes: ['agent'],
400
- description: 'Manage contacts, contact requests, and allowed group channels',
400
+ description: 'Manage contacts and contact requests',
401
401
  sources: ['menu', 'ecweb', 'control'],
402
402
  },
403
403
  {
@@ -803,10 +803,10 @@ export class CommandHandler {
803
803
  };
804
804
  if (s.agentSessionId) {
805
805
  item.agentSessionId = s.agentSessionId;
806
- const fileInfo = this.sessionManager.getSessionFileInfo(s.projectPath, s.agentSessionId, s.baseagent);
806
+ const fileInfo = this.sessionManager.getSessionFileInfo(s.projectPath, s.agentSessionId, s.baseagent, s.selfAID);
807
807
  if (fileInfo.turns)
808
808
  item.turns = fileInfo.turns;
809
- const firstMsg = this.sessionManager.readSessionFirstMessage(s.projectPath, s.agentSessionId, s.baseagent);
809
+ const firstMsg = this.sessionManager.readSessionFirstMessage(s.projectPath, s.agentSessionId, s.baseagent, s.selfAID);
810
810
  if (firstMsg)
811
811
  item.preview = firstMsg.length > 80 ? firstMsg.slice(0, 80) + '...' : firstMsg;
812
812
  }
@@ -1,6 +1,6 @@
1
- import { roleMenuQuery, roleMenuUpdate, } from './role-menu.js';
1
+ import { roleMenuQuery, roleMenuGroupCount, roleMenuUpdate, } from './role-menu.js';
2
2
  import { getContactSnapshot, resolveContactView } from '../../config/contact-book.js';
3
- import { listConfiguredChannelKeys, mutateAccessPolicy, readAccessPolicySnapshot, } from '../../config/access-policy.js';
3
+ import { mutateAccessPolicy, readAccessPolicySnapshot, } from '../../config/access-policy.js';
4
4
  import { expirePendingContactRequests, mutateContactWithOperation, reviewContactRequest, } from '../../config/contact-request-service.js';
5
5
  import { formatPeerKey, parsePeerKey } from '../relation/peer-identity.js';
6
6
  /**
@@ -13,8 +13,8 @@ import { formatPeerKey, parsePeerKey } from '../relation/peer-identity.js';
13
13
  * 群组不落 contact.json(contact book 只接受个人 AID,group 会被拒绝)。
14
14
  * - 联系人与申请(view=contacts / contact,add / block / unblock / review)→ 直接读写
15
15
  * Contact Book v3;contact.json 是当前状态和 pending 版本的唯一事实来源。
16
- * - 访问设置(view=access / option=allowedGroupChannels / resource=<access field>)→
17
- * 查询策略、列举群聊渠道候选项并逐字段写入 Agent config.json 的 access 字段。
16
+ * - 访问设置(view=access / resource=<access field>)→
17
+ * 查询和写入 Agent config.json 的 access 字段。
18
18
  */
19
19
  const MENU_NAME = 'connect';
20
20
  const DEFAULT_PAGE_SIZE = 50;
@@ -31,8 +31,6 @@ export function connectMenuOperation(kind, args, value) {
31
31
  if (kind === 'action')
32
32
  return 'connect.write';
33
33
  const resource = String(args?.resource ?? '');
34
- if (resource === 'allowedGroupChannels')
35
- return 'connect.write';
36
34
  if (resource === 'policyMode' || resource === 'requestLimit') {
37
35
  return 'connect.access.write';
38
36
  }
@@ -55,7 +53,7 @@ export async function handleConnectMenu(req, context) {
55
53
  }
56
54
  try {
57
55
  if (req.subtype === 'options')
58
- return await handleOptions(self, req.args);
56
+ return await handleOptions(self, req.args, context);
59
57
  if (req.subtype === 'query')
60
58
  return await handleQuery(req, self, context);
61
59
  if (req.subtype === 'update')
@@ -69,26 +67,24 @@ export async function handleConnectMenu(req, context) {
69
67
  return fail('INVALID_ARGUMENT', `Unknown subtype: ${req.subtype}`);
70
68
  }
71
69
  // ── Options ──
72
- async function handleOptions(self, args) {
70
+ async function handleOptions(self, args, context) {
73
71
  const option = String(args?.option ?? '').trim();
74
72
  if (option) {
75
- if (option !== 'allowedGroupChannels') {
76
- return fail('NOT_SUPPORTED', `Unknown connect option: ${option}`);
77
- }
78
- const selected = new Set(readAccessPolicySnapshot(self).policy.allowedGroupChannels);
79
- return ok({
80
- options: listConfiguredChannelKeys(self).map(channelKey => ({
81
- option: channelKey,
82
- label: channelKey,
83
- selected: selected.has(channelKey),
84
- })),
85
- });
73
+ return fail('NOT_SUPPORTED', `Unknown connect option: ${option}`);
86
74
  }
87
75
  await expirePendingContactRequests(self);
88
76
  const snapshot = getContactSnapshot(self);
89
77
  const contactCount = snapshot.contacts.size;
90
78
  const blockedCount = snapshot.blockedIndex.size;
91
79
  const pendingCount = [...snapshot.contacts.values()].filter(entry => entry.status === 'pending').length;
80
+ let groupsDescription = '查看所在群组(数量暂不可用)';
81
+ try {
82
+ const groupCount = await roleMenuGroupCount(context);
83
+ groupsDescription = `查看所在群组(${groupCount} 个)`;
84
+ }
85
+ catch {
86
+ // Keep the root menu available when AUN group directory is disabled or unavailable.
87
+ }
92
88
  return ok({
93
89
  options: [
94
90
  {
@@ -99,12 +95,12 @@ async function handleOptions(self, args) {
99
95
  {
100
96
  option: 'groups',
101
97
  label: '群组列表',
102
- description: '查看所在群组',
98
+ description: groupsDescription,
103
99
  },
104
100
  {
105
101
  option: 'access',
106
102
  label: '访问设置',
107
- description: '设置私聊准入模式与允许群聊的渠道',
103
+ description: '设置消息准入模式和准入控制消息限额',
108
104
  },
109
105
  ],
110
106
  });
@@ -268,15 +264,11 @@ async function handleAction(req, self, context) {
268
264
  }
269
265
  function isAccessUpdateResource(resource) {
270
266
  return resource === 'policyMode'
271
- || resource === 'allowedGroupChannels'
272
267
  || resource === 'requestLimit';
273
268
  }
274
269
  function updateAccessResource(req, context, resource) {
275
270
  const args = req.args ?? {};
276
- if (resource === 'allowedGroupChannels')
277
- requireAdminContext(context);
278
- else
279
- requireOwnerContext(context);
271
+ requireOwnerContext(context);
280
272
  if (req.value === undefined || !req.value.trim()) {
281
273
  return fail('INVALID_ARGUMENT', 'value is required');
282
274
  }
@@ -284,15 +276,8 @@ function updateAccessResource(req, context, resource) {
284
276
  const expectedAccessRevision = requireAccessRevision(args);
285
277
  const decoded = decodeAccessUpdateValue(req.value);
286
278
  if (resource === 'policyMode') {
287
- if (typeof decoded !== 'string' || !['open', 'contacts', 'owners-only'].includes(decoded)) {
288
- return fail('INVALID_ARGUMENT', 'policyMode must be open, contacts, or owners-only');
289
- }
290
- }
291
- else if (resource === 'allowedGroupChannels') {
292
- if (!Array.isArray(decoded)
293
- || !decoded.every(value => typeof value === 'string' && value.length > 0)
294
- || new Set(decoded).size !== decoded.length) {
295
- return fail('INVALID_ARGUMENT', 'allowedGroupChannels must be a JSON string array');
279
+ if (typeof decoded !== 'string' || !['open', 'contacts', 'owners'].includes(decoded)) {
280
+ return fail('INVALID_ARGUMENT', 'policyMode must be open, contacts, or owners');
296
281
  }
297
282
  }
298
283
  else {
@@ -452,16 +437,12 @@ function errorCode(error) {
452
437
  return 'INTERNAL_ERROR';
453
438
  if (code === 'access_policy_owner_required')
454
439
  return 'PERMISSION_DENIED';
455
- if (code === 'access_policy_manager_required')
456
- return 'PERMISSION_DENIED';
457
440
  if (code === 'access_policy_revision_conflict')
458
441
  return 'CONFLICT';
459
442
  if (code === 'access_policy_temporarily_unavailable')
460
443
  return 'TEMPORARILY_UNAVAILABLE';
461
444
  if (code === 'restricted_mode_without_owner')
462
445
  return 'NOT_ALLOWED';
463
- if (code === 'unknown_group_access_channel')
464
- return 'INVALID_ARGUMENT';
465
446
  if (code === 'invalid_access_policy')
466
447
  return 'INTERNAL_ERROR';
467
448
  return typeof code === 'string' ? code : 'INTERNAL_ERROR';
@@ -538,9 +519,6 @@ function accessPolicyWithUpdate(current, resource, decoded) {
538
519
  if (resource === 'policyMode') {
539
520
  return { ...current, policyMode: decoded };
540
521
  }
541
- if (resource === 'allowedGroupChannels') {
542
- return { ...current, allowedGroupChannels: [...decoded] };
543
- }
544
522
  const requestLimit = decoded;
545
523
  return {
546
524
  ...current,
@@ -4,7 +4,7 @@ import { modelMatches } from '../model/model-catalog.js';
4
4
  import { constrainResolvedModelForRole, filterModelsForRole, validateModelSelectionForRole } from '../model/model-permission.js';
5
5
  import { hasModelSwitcher } from '../../agents/runner-types.js';
6
6
  import { getCodexEfforts } from '../../agents/codex-runner.js';
7
- import { resolvePaths, getPackageRoot } from '../../paths.js';
7
+ import { resolvePaths, getPackageRoot, daemonControlDir } from '../../paths.js';
8
8
  import { buildEnvelope } from '../message/message-utils.js';
9
9
  import path from 'path';
10
10
  import fs from 'fs';
@@ -1038,6 +1038,8 @@ function buildRoleMenuContext(owner, channel, subject) {
1038
1038
  return {
1039
1039
  self,
1040
1040
  actorRole: subject.role,
1041
+ actorRoleSource: subject.roleSource,
1042
+ actorAllowAccess: subject.allowAccess,
1041
1043
  actorAid: subject.actorId,
1042
1044
  chatType: subject.chatType,
1043
1045
  aunAvailable,
@@ -1537,10 +1539,10 @@ export async function getSubMenuItems(cmd, channel, channelId, userId, args, ove
1537
1539
  };
1538
1540
  if (s.agentSessionId) {
1539
1541
  item.agentSessionId = s.agentSessionId;
1540
- const fileInfo = this.sessionManager.getSessionFileInfo(s.projectPath, s.agentSessionId, s.baseagent);
1542
+ const fileInfo = this.sessionManager.getSessionFileInfo(s.projectPath, s.agentSessionId, s.baseagent, s.selfAID);
1541
1543
  if (fileInfo.turns)
1542
1544
  item.turns = fileInfo.turns;
1543
- const firstMsg = this.sessionManager.readSessionFirstMessage(s.projectPath, s.agentSessionId, s.baseagent);
1545
+ const firstMsg = this.sessionManager.readSessionFirstMessage(s.projectPath, s.agentSessionId, s.baseagent, s.selfAID);
1544
1546
  if (firstMsg)
1545
1547
  item.preview = firstMsg.length > 80 ? firstMsg.slice(0, 80) + '…' : firstMsg;
1546
1548
  }
@@ -1903,7 +1905,7 @@ export async function execMenuQuery(cmd, channel, channelId, userId, args, expli
1903
1905
  }
1904
1906
  let turns = 0;
1905
1907
  if (session.agentSessionId) {
1906
- const fileInfo = this.sessionManager.getSessionFileInfo(session.projectPath, session.agentSessionId, session.baseagent);
1908
+ const fileInfo = this.sessionManager.getSessionFileInfo(session.projectPath, session.agentSessionId, session.baseagent, session.selfAID);
1907
1909
  turns = fileInfo.turns;
1908
1910
  }
1909
1911
  const data = {
@@ -1950,7 +1952,7 @@ export async function execMenuQuery(cmd, channel, channelId, userId, args, expli
1950
1952
  }
1951
1953
  let turns = 0;
1952
1954
  if (topic.agentSessionId) {
1953
- turns = this.sessionManager.getSessionFileInfo(topic.projectPath, topic.agentSessionId, topic.baseagent).turns;
1955
+ turns = this.sessionManager.getSessionFileInfo(topic.projectPath, topic.agentSessionId, topic.baseagent, topic.selfAID).turns;
1954
1956
  }
1955
1957
  const data = {
1956
1958
  threadId: topic.threadId,
@@ -2878,7 +2880,7 @@ export async function execMenuAction(cmd, action, args, channel, channelId, user
2878
2880
  return { error: `无效 targetSession: ${targetSession}`, code: 'INVALID_ARGS' };
2879
2881
  }
2880
2882
  const triggerThread = args.triggerThread;
2881
- if (triggerThread !== undefined && triggerThread !== 'per_run' && triggerThread !== 'by_trigger') {
2883
+ if (triggerThread !== undefined && triggerThread !== 'per_run' && triggerThread !== 'by_run' && triggerThread !== 'by_trigger') {
2882
2884
  return { error: `无效 triggerThread: ${triggerThread}`, code: 'INVALID_ARGS' };
2883
2885
  }
2884
2886
  const parsed = {
@@ -3269,9 +3271,9 @@ export async function execMenuAction(cmd, action, args, channel, channelId, user
3269
3271
  const suppressRealRestart = shouldSuppressRealRestart();
3270
3272
  if (!suppressRealRestart) {
3271
3273
  const restartInfo = { channel, channelId, timestamp: Date.now() };
3272
- const dataDir = resolvePaths().dataDir;
3273
- fs.mkdirSync(dataDir, { recursive: true });
3274
- fs.writeFileSync(path.join(dataDir, 'restart-pending.json'), JSON.stringify(restartInfo));
3274
+ const controlDir = daemonControlDir();
3275
+ fs.mkdirSync(controlDir, { recursive: true });
3276
+ fs.writeFileSync(path.join(controlDir, 'restart-pending.json'), JSON.stringify(restartInfo));
3275
3277
  const { spawn } = await import('child_process');
3276
3278
  spawn('node', [path.join(getPackageRoot(), 'dist', 'cli', 'index.js'), 'restart-monitor'], {
3277
3279
  detached: true,
@@ -156,6 +156,22 @@ export async function roleMenuQuery(context, args) {
156
156
  view: view || null,
157
157
  });
158
158
  }
159
+ /**
160
+ * Read the current joined-group count without materializing the full group list.
161
+ * Used by Connect's root options description; failures are handled by the caller
162
+ * so a transient AUN directory outage does not hide the rest of the menu.
163
+ */
164
+ export async function roleMenuGroupCount(context) {
165
+ assertRequest(context, { self: context.self });
166
+ assertAunDirectory(context);
167
+ const result = await roleDirectory(context).listGroups({ from: context.self, size: 1 });
168
+ if (!result.ok) {
169
+ throw roleError('TEMPORARILY_UNAVAILABLE', result.error || 'Unable to list joined groups', context.self, {
170
+ kind: 'target_source_unavailable', targetType: 'group',
171
+ });
172
+ }
173
+ return Math.max(Number(result.total) || 0, result.items.length);
174
+ }
159
175
  export async function roleMenuUpdate(context, args, rawValue) {
160
176
  assertRequest(context, args);
161
177
  const value = parseUpdateValue(rawValue, context.self);
@@ -769,6 +785,7 @@ async function targetSnapshot(context, args, policyRevision) {
769
785
  target,
770
786
  relationRevision: relation?.revision ?? null,
771
787
  ...targetRoleView(self, target, relation?.config ?? null),
788
+ ...(target.kind === 'group' ? { requesterRole: requesterRoleResult(context) } : {}),
772
789
  relationConfig: relationConfigView(context, target, relation?.config ?? null),
773
790
  };
774
791
  }
@@ -1141,6 +1158,16 @@ function relationConfigView(context, target, config) {
1141
1158
  function roleResult(roleId, source, self) {
1142
1159
  return { roleId, source: roleId ? source : 'none', allowAccess: roleId ? checkRoleAccess(roleId, self) : false };
1143
1160
  }
1161
+ function requesterRoleResult(context) {
1162
+ const roleId = isManagementRole(context.actorRole) ? context.actorRole : null;
1163
+ return {
1164
+ roleId,
1165
+ source: roleId ? context.actorRoleSource ?? 'authenticated' : 'none',
1166
+ allowAccess: roleId
1167
+ ? context.actorAllowAccess ?? checkRoleAccess(roleId, context.self)
1168
+ : false,
1169
+ };
1170
+ }
1144
1171
  function readAgent(self) {
1145
1172
  const agent = read(ConfigTarget.Agent, { self }, { cache: false });
1146
1173
  if (!agent)
@@ -1,7 +1,7 @@
1
1
  import { hasModelSwitcher, hasPermissionController } from '../../agents/runner-types.js';
2
2
  import { getCodexEfforts } from '../../agents/codex-runner.js';
3
3
  import { buildEnvelope } from '../message/message-utils.js';
4
- import { resolvePaths, getPackageRoot } from '../../paths.js';
4
+ import { resolvePaths, getPackageRoot, daemonControlDir } from '../../paths.js';
5
5
  import { logger } from '../../utils/logger.js';
6
6
  import { shouldSuppressRealRestart } from '../../utils/restart-safety.js';
7
7
  import crypto from 'crypto';
@@ -2104,7 +2104,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
2104
2104
  // 获取会话文件信息并同步 name
2105
2105
  let sessionTurns = 0;
2106
2106
  if (session.agentSessionId) {
2107
- const fileInfo = this.sessionManager.getSessionFileInfo(session.projectPath, session.agentSessionId, session.baseagent);
2107
+ const fileInfo = this.sessionManager.getSessionFileInfo(session.projectPath, session.agentSessionId, session.baseagent, session.selfAID);
2108
2108
  sessionTurns = fileInfo.turns;
2109
2109
  if (fileInfo.title && fileInfo.title !== session.name) {
2110
2110
  await this.sessionManager.renameSession(session.id, fileInfo.title);
@@ -2482,9 +2482,9 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
2482
2482
  ...(replyContext?.replyToMessageId ? { rootId: replyContext.replyToMessageId } : {}),
2483
2483
  };
2484
2484
  if (!suppressRealRestart) {
2485
- const dataDir = resolvePaths().dataDir;
2486
- fs.mkdirSync(dataDir, { recursive: true });
2487
- fs.writeFileSync(path.join(dataDir, 'restart-pending.json'), JSON.stringify(restartInfo));
2485
+ const controlDir = daemonControlDir();
2486
+ fs.mkdirSync(controlDir, { recursive: true });
2487
+ fs.writeFileSync(path.join(controlDir, 'restart-pending.json'), JSON.stringify(restartInfo));
2488
2488
  const { spawn } = await import('child_process');
2489
2489
  spawn('node', [path.join(getPackageRoot(), 'dist', 'cli', 'index.js'), 'restart-monitor'], {
2490
2490
  detached: true,
@@ -2531,9 +2531,9 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
2531
2531
  // 文本确认流程
2532
2532
  if (sessionsWithMessages.length > 0) {
2533
2533
  const restartKey = `${channel}-${channelId}`;
2534
- const dataDir = resolvePaths().dataDir;
2535
- fs.mkdirSync(dataDir, { recursive: true });
2536
- const restartConfirmFile = path.join(dataDir, `restart-confirm-${restartKey}.json`);
2534
+ const controlDir = daemonControlDir();
2535
+ fs.mkdirSync(controlDir, { recursive: true });
2536
+ const restartConfirmFile = path.join(controlDir, `restart-confirm-${restartKey}.json`);
2537
2537
  if (fs.existsSync(restartConfirmFile)) {
2538
2538
  const confirmInfo = JSON.parse(fs.readFileSync(restartConfirmFile, 'utf-8'));
2539
2539
  const now = Date.now();
@@ -2740,7 +2740,9 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
2740
2740
  if (!canImportCli) {
2741
2741
  return { kind: 'command.error', text: '❌ 当前无权查看 CLI 会话' };
2742
2742
  }
2743
- const orphanCliSessions = await this.sessionManager.listImportableCliSessions(session.projectPath, session.baseagent);
2743
+ const orphanCliSessions = session.baseagent === 'ecagent'
2744
+ ? await this.sessionManager.listImportableCliSessions(session.projectPath, session.baseagent, session.selfAID)
2745
+ : await this.sessionManager.listImportableCliSessions(session.projectPath, session.baseagent);
2744
2746
  if (orphanCliSessions.length === 0) {
2745
2747
  return { kind: 'command.result', text: `当前项目 ${path.basename(session.projectPath)} 没有未导入的 CLI 会话` };
2746
2748
  }
@@ -2790,7 +2792,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
2790
2792
  const currentProjectSessions = sessions.filter((s) => s.projectPath === session.projectPath && s.baseagent === session.baseagent && !s.threadId);
2791
2793
  // 从 SDK 同步会话名称(发现 CLI 改名)
2792
2794
  try {
2793
- const sdkSessions = await this.sessionManager.listSdkSessions(session.projectPath, session.baseagent);
2795
+ const sdkSessions = await this.sessionManager.listSdkSessions(session.projectPath, session.baseagent, session.selfAID);
2794
2796
  for (const sdkSession of sdkSessions) {
2795
2797
  if (!sdkSession.title)
2796
2798
  continue;
@@ -2816,7 +2818,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
2816
2818
  displayIndex++;
2817
2819
  const name = displaySessionTitle(s.name, '(未命名)');
2818
2820
  const idleTime = formatIdleTime(Date.now() - s.updatedAt);
2819
- const fileMissing = !!(s.agentSessionId && !this.sessionManager.checkSessionFileExists(s.projectPath, s.agentSessionId, s.baseagent));
2821
+ const fileMissing = !!(s.agentSessionId && !this.sessionManager.checkSessionFileExists(s.projectPath, s.agentSessionId, s.baseagent, s.selfAID));
2820
2822
  let status = '[空闲]';
2821
2823
  if (fileMissing) {
2822
2824
  status = '[会话文件缺失]';
@@ -2933,10 +2935,12 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
2933
2935
  }
2934
2936
  for (const projectPath of projectPaths) {
2935
2937
  const currentBaseagent = session?.baseagent || this.primaryRunnerKey;
2936
- const cliSessions = await this.sessionManager.listImportableCliSessions(projectPath, currentBaseagent);
2938
+ const cliSessions = currentBaseagent === 'ecagent'
2939
+ ? await this.sessionManager.listImportableCliSessions(projectPath, currentBaseagent, selfAID ?? session?.selfAID)
2940
+ : await this.sessionManager.listImportableCliSessions(projectPath, currentBaseagent);
2937
2941
  const cliSession = cliSessions.find((c) => c.uuid.startsWith(sessionName));
2938
2942
  if (cliSession) {
2939
- const imported = await this.sessionManager.importCliSession(channel, channelId, projectPath, cliSession.uuid, currentBaseagent);
2943
+ const imported = await this.sessionManager.importCliSession(channel, channelId, projectPath, cliSession.uuid, currentBaseagent, selfAID ?? session?.selfAID);
2940
2944
  this.eventBus.publish({ type: 'session:imported', sessionId: imported.id, agentSessionId: cliSession.uuid, projectPath });
2941
2945
  const projectName = this.getProjectName(projectPath);
2942
2946
  return { kind: 'command.result', text: `✓ 已导入 CLI 会话: ${displaySessionTitle(imported.name, '(未命名)')}\n 项目: ${projectName}\n 将继续之前的对话历史` };
@@ -2947,7 +2951,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
2947
2951
  return { kind: 'command.error', text: `❌ 会话不存在: ${sessionName}\n使用 /s 查看可用会话` };
2948
2952
  }
2949
2953
  const lastInput = targetSession.agentSessionId
2950
- ? this.sessionManager.readSessionLastUserMessage(targetSession.projectPath, targetSession.agentSessionId, targetSession.baseagent)
2954
+ ? this.sessionManager.readSessionLastUserMessage(targetSession.projectPath, targetSession.agentSessionId, targetSession.baseagent, targetSession.selfAID)
2951
2955
  : null;
2952
2956
  const lastInputLine = lastInput ? `\n 最后输入: "${lastInput}"` : '';
2953
2957
  if (!session) {