evolcore 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (371) hide show
  1. package/CHANGELOG.md +813 -0
  2. package/LICENSE +21 -0
  3. package/MIGRATION-0.5.0.md +378 -0
  4. package/README.md +318 -14
  5. package/ROLE_ACCESS_CONTROL.md +174 -0
  6. package/assets/.env.template +4 -0
  7. package/assets/brand/evolcore/README.md +19 -0
  8. package/assets/brand/evolcore/evolcore-app-icon.png +0 -0
  9. package/assets/brand/evolcore/evolcore-app-icon.svg +13 -0
  10. package/assets/brand/evolcore/evolcore-brand-board.png +0 -0
  11. package/assets/brand/evolcore/evolcore-brand-board.svg +126 -0
  12. package/assets/brand/evolcore/evolcore-logo-kit.zip +0 -0
  13. package/assets/brand/evolcore/evolcore-logo-reverse.png +0 -0
  14. package/assets/brand/evolcore/evolcore-logo-reverse.svg +14 -0
  15. package/assets/brand/evolcore/evolcore-logo.png +0 -0
  16. package/assets/brand/evolcore/evolcore-logo.svg +14 -0
  17. package/assets/brand/evolcore/evolcore-mark.png +0 -0
  18. package/assets/brand/evolcore/evolcore-mark.svg +10 -0
  19. package/bin/ec-safe-output.js +161 -0
  20. package/bin/ec.js +29 -0
  21. package/dist/agents/baseagent.js +163 -0
  22. package/dist/agents/claude-runner.js +2385 -0
  23. package/dist/agents/codex-app-server-client.js +448 -0
  24. package/dist/agents/codex-runner.js +2639 -0
  25. package/dist/agents/gemini-runner.js +666 -0
  26. package/dist/agents/runner-types.js +75 -0
  27. package/dist/aun/aid/agentmd.js +216 -0
  28. package/dist/aun/aid/client.js +132 -0
  29. package/dist/aun/aid/control-aid.js +91 -0
  30. package/dist/aun/aid/identity.js +518 -0
  31. package/dist/aun/aid/index.js +4 -0
  32. package/dist/aun/aid/store.js +74 -0
  33. package/dist/aun/aid/types.js +1 -0
  34. package/dist/aun/aid/validation.js +21 -0
  35. package/dist/aun/group-identity.js +10 -0
  36. package/dist/aun/msg/group-index.js +6 -0
  37. package/dist/aun/msg/group.js +1231 -0
  38. package/dist/aun/msg/history.js +123 -0
  39. package/dist/aun/msg/index.js +5 -0
  40. package/dist/aun/msg/p2p.js +393 -0
  41. package/dist/aun/msg/payload-type.js +27 -0
  42. package/dist/aun/msg/upload.js +137 -0
  43. package/dist/aun/outbox.js +160 -0
  44. package/dist/aun/rpc/caller.js +42 -0
  45. package/dist/aun/rpc/connection.js +25 -0
  46. package/dist/aun/rpc/index.js +2 -0
  47. package/dist/aun/service-proxy.js +225 -0
  48. package/dist/aun/storage/download.js +29 -0
  49. package/dist/aun/storage/index.js +3 -0
  50. package/dist/aun/storage/manage.js +10 -0
  51. package/dist/aun/storage/upload.js +68 -0
  52. package/dist/channels/aun.js +4147 -0
  53. package/dist/channels/daemon.js +422 -0
  54. package/dist/channels/dingtalk.js +649 -0
  55. package/dist/channels/feishu.js +1789 -0
  56. package/dist/channels/qqbot.js +409 -0
  57. package/dist/channels/wechat.js +817 -0
  58. package/dist/channels/wecom.js +565 -0
  59. package/dist/cli/agent-command.js +641 -0
  60. package/dist/cli/agent.js +1059 -0
  61. package/dist/cli/aun-commands.js +1948 -0
  62. package/dist/cli/bench.js +1228 -0
  63. package/dist/cli/cli-argv.js +66 -0
  64. package/dist/cli/code-stats.js +329 -0
  65. package/dist/cli/command-log.js +82 -0
  66. package/dist/cli/config-selector.js +69 -0
  67. package/dist/cli/config.js +261 -0
  68. package/dist/cli/ctl-command.js +62 -0
  69. package/dist/cli/daemon-commands.js +2887 -0
  70. package/dist/cli/fs-command.js +1447 -0
  71. package/dist/cli/handoff-command.js +302 -0
  72. package/dist/cli/help.js +31 -0
  73. package/dist/cli/index.js +358 -0
  74. package/dist/cli/init-channel.js +1377 -0
  75. package/dist/cli/init.js +553 -0
  76. package/dist/cli/link-rules.js +240 -0
  77. package/dist/cli/model.js +590 -0
  78. package/dist/cli/net-check.js +723 -0
  79. package/dist/cli/queue-command.js +126 -0
  80. package/dist/cli/response.js +345 -0
  81. package/dist/cli/restart-monitor.js +456 -0
  82. package/dist/cli/stats.js +607 -0
  83. package/dist/cli/task-context.js +80 -0
  84. package/dist/cli/trigger-command.js +505 -0
  85. package/dist/cli/version.js +88 -0
  86. package/dist/cli/watch-logs.js +33 -0
  87. package/dist/cli/watch-msg.js +673 -0
  88. package/dist/config/boot-log.js +266 -0
  89. package/dist/config/builtin-role-templates.js +30 -0
  90. package/dist/config/builtin-roles.js +85 -0
  91. package/dist/config/config-batch-get.js +11 -0
  92. package/dist/config/config-field-policy.js +261 -0
  93. package/dist/config/config-manager.js +916 -0
  94. package/dist/config/config-operation-service.js +384 -0
  95. package/dist/config/contact-book.js +371 -0
  96. package/dist/config/gateway-config.js +858 -0
  97. package/dist/config/lifecycle.js +17 -0
  98. package/dist/config/mention-mode.js +27 -0
  99. package/dist/config/merge.js +161 -0
  100. package/dist/config/owner-policy.js +4 -0
  101. package/dist/config/peer-role-resolver.js +139 -0
  102. package/dist/config/resolved-config-op.js +483 -0
  103. package/dist/config/role-config-v4-startup.js +32 -0
  104. package/dist/config/role-config-v5-startup.js +27 -0
  105. package/dist/config/role-schema.js +105 -0
  106. package/dist/config/role-service.js +159 -0
  107. package/dist/config/role-store.js +204 -0
  108. package/dist/config/roles.js +55 -0
  109. package/dist/config/schema-registry.js +154 -0
  110. package/dist/config/snapshot.js +598 -0
  111. package/dist/config-store.js +503 -0
  112. package/dist/core/auth/agent-delegation.js +111 -0
  113. package/dist/core/auth/auth-gateway.js +166 -0
  114. package/dist/core/auth/authenticated-actor.js +6 -0
  115. package/dist/core/auth/authorization-audit.js +110 -0
  116. package/dist/core/auth/operation-authorizer.js +718 -0
  117. package/dist/core/auth/operation-catalog.js +675 -0
  118. package/dist/core/baseagent-loader.js +54 -0
  119. package/dist/core/bootstrap-service.js +175 -0
  120. package/dist/core/capability/capability-manager.js +316 -0
  121. package/dist/core/capability/providers/claude-capability-provider.js +176 -0
  122. package/dist/core/capability/providers/codex-capability-provider.js +148 -0
  123. package/dist/core/capability/providers/gemini-capability-provider.js +10 -0
  124. package/dist/core/capability/types.js +27 -0
  125. package/dist/core/causation/audit.js +103 -0
  126. package/dist/core/causation/aun-association.js +111 -0
  127. package/dist/core/causation/context.js +93 -0
  128. package/dist/core/causation/index.js +4 -0
  129. package/dist/core/causation/types.js +2 -0
  130. package/dist/core/channel-loader.js +277 -0
  131. package/dist/core/command/agent-control.js +616 -0
  132. package/dist/core/command/cli-intent-parser.js +225 -0
  133. package/dist/core/command/command-handler.js +1638 -0
  134. package/dist/core/command/menu-handler.js +3354 -0
  135. package/dist/core/command/menu-protocol.js +247 -0
  136. package/dist/core/command/role-menu.js +1524 -0
  137. package/dist/core/command/slash-gate.js +148 -0
  138. package/dist/core/command/slash-handler.js +3056 -0
  139. package/dist/core/daemon-file-cache.js +216 -0
  140. package/dist/core/event-bus.js +32 -0
  141. package/dist/core/event-catalog.js +740 -0
  142. package/dist/core/evolagent-registry.js +546 -0
  143. package/dist/core/evolagent.js +331 -0
  144. package/dist/core/handoff/dispatcher.js +229 -0
  145. package/dist/core/handoff/mutex.js +46 -0
  146. package/dist/core/handoff/runtime.js +324 -0
  147. package/dist/core/handoff/store.js +537 -0
  148. package/dist/core/handoff/types.js +12 -0
  149. package/dist/core/inference/text-inference.js +173 -0
  150. package/dist/core/interaction-registration.js +10 -0
  151. package/dist/core/interaction-router.js +278 -0
  152. package/dist/core/message/create-status.js +67 -0
  153. package/dist/core/message/im-renderer.js +657 -0
  154. package/dist/core/message/items-formatter.js +76 -0
  155. package/dist/core/message/logical-queue-bridge.js +123 -0
  156. package/dist/core/message/message-bridge.js +803 -0
  157. package/dist/core/message/message-cache.js +56 -0
  158. package/dist/core/message/message-log.js +339 -0
  159. package/dist/core/message/message-processor.js +4 -0
  160. package/dist/core/message/message-queue.js +1436 -0
  161. package/dist/core/message/message-utils.js +70 -0
  162. package/dist/core/message/peer-mode.js +105 -0
  163. package/dist/core/message/pending-hints.js +232 -0
  164. package/dist/core/message/response-depth.js +33 -0
  165. package/dist/core/message/response-engine.js +3776 -0
  166. package/dist/core/message/response-snapshot.js +83 -0
  167. package/dist/core/message/stream-debouncer.js +130 -0
  168. package/dist/core/message/stream-idle-monitor.js +124 -0
  169. package/dist/core/model/config-scope.js +162 -0
  170. package/dist/core/model/field-scope.js +78 -0
  171. package/dist/core/model/model-catalog.js +227 -0
  172. package/dist/core/model/model-diagnostics.js +182 -0
  173. package/dist/core/model/model-permission.js +90 -0
  174. package/dist/core/permission/approval-gateway.js +1017 -0
  175. package/dist/core/permission/ec-command-parser.js +347 -0
  176. package/dist/core/permission/execution-sandbox.js +16 -0
  177. package/dist/core/permission/index.js +6 -0
  178. package/dist/core/permission/mode.js +24 -0
  179. package/dist/core/permission/sandbox-runtime.js +265 -0
  180. package/dist/core/permission/tool-policy.js +987 -0
  181. package/dist/core/permission/unix-socket-policy.js +99 -0
  182. package/dist/core/protected-paths.js +330 -0
  183. package/dist/core/relation/peer-identity.js +222 -0
  184. package/dist/core/relation/peer-key.js +1 -0
  185. package/dist/core/role/runtime-policy.js +141 -0
  186. package/dist/core/session/adapters/claude-session-file-adapter.js +218 -0
  187. package/dist/core/session/adapters/codex-session-file-adapter.js +333 -0
  188. package/dist/core/session/adapters/gemini-session-file-adapter.js +181 -0
  189. package/dist/core/session/session-file-adapter.js +7 -0
  190. package/dist/core/session/session-file-health.js +45 -0
  191. package/dist/core/session/session-fs-store.js +232 -0
  192. package/dist/core/session/session-key.js +24 -0
  193. package/dist/core/session/session-manager.js +1587 -0
  194. package/dist/core/session/session-mapper.js +100 -0
  195. package/dist/core/session/session-renew.js +314 -0
  196. package/dist/core/session/session-title.js +128 -0
  197. package/dist/core/session/session-turn-coordinator.js +205 -0
  198. package/dist/core/session/session-turns.js +67 -0
  199. package/dist/core/system-channels.js +29 -0
  200. package/dist/eck/baseagent-caps.js +18 -0
  201. package/dist/eck/detect.js +47 -0
  202. package/dist/eck/group-rules-sync.js +345 -0
  203. package/dist/eck/init.js +77 -0
  204. package/dist/eck/kit-renderer.js +359 -0
  205. package/dist/eck/manifest-engine.js +446 -0
  206. package/dist/eck/message-renderer.js +199 -0
  207. package/dist/eck/rules-loader.js +28 -0
  208. package/dist/index.js +2870 -4
  209. package/dist/ipc.js +748 -0
  210. package/dist/paths.js +262 -0
  211. package/dist/product.js +18 -0
  212. package/dist/response-system/context-builder.js +71 -0
  213. package/dist/response-system/coordinator.js +117 -0
  214. package/dist/response-system/decision-executor.js +86 -0
  215. package/dist/response-system/engines/v1/index.js +21 -0
  216. package/dist/response-system/engines/v1/interactive-flow.js +27 -0
  217. package/dist/response-system/engines/v1/proactive-flow.js +137 -0
  218. package/dist/response-system/engines/v1/types.js +1 -0
  219. package/dist/response-system/extensions.js +41 -0
  220. package/dist/response-system/index.js +6 -0
  221. package/dist/response-system/modes/index.js +7 -0
  222. package/dist/response-system/modes/single-session/index.js +72 -0
  223. package/dist/response-system/queues/fifo-queue.js +44 -0
  224. package/dist/response-system/queues/index.js +6 -0
  225. package/dist/response-system/queues/lifo-queue.js +42 -0
  226. package/dist/response-system/queues/priority-queue.js +63 -0
  227. package/dist/response-system/registry.js +97 -0
  228. package/dist/response-system/resolver.js +37 -0
  229. package/dist/response-system/selector.js +23 -0
  230. package/dist/response-system/types.js +7 -0
  231. package/dist/stats/billing.js +151 -0
  232. package/dist/stats/budget.js +93 -0
  233. package/dist/stats/db.js +403 -0
  234. package/dist/stats/eck-vars.js +89 -0
  235. package/dist/stats/index.js +11 -0
  236. package/dist/stats/normalizer.js +80 -0
  237. package/dist/stats/price-resolver.js +138 -0
  238. package/dist/stats/query.js +763 -0
  239. package/dist/stats/role-budget.js +168 -0
  240. package/dist/stats/writer.js +151 -0
  241. package/dist/trigger/anomaly-store.js +258 -0
  242. package/dist/trigger/audit.js +152 -0
  243. package/dist/trigger/event-source.js +119 -0
  244. package/dist/trigger/feedback.js +685 -0
  245. package/dist/trigger/history.js +290 -0
  246. package/dist/trigger/manager.js +291 -0
  247. package/dist/trigger/parser.js +520 -0
  248. package/dist/trigger/patch.js +148 -0
  249. package/dist/trigger/scheduler.js +1600 -0
  250. package/dist/trigger/script-executor.js +155 -0
  251. package/dist/trigger/state.js +145 -0
  252. package/dist/trigger/types.js +1 -0
  253. package/dist/trigger/validation.js +621 -0
  254. package/dist/types.js +12 -0
  255. package/dist/utils/aid-bind.js +299 -0
  256. package/dist/utils/atomic-write.js +95 -0
  257. package/dist/utils/avatar-upload.js +123 -0
  258. package/dist/utils/cross-platform.js +297 -0
  259. package/dist/utils/ecweb-utils.js +73 -0
  260. package/dist/utils/error-dict.json +153 -0
  261. package/dist/utils/error-utils.js +349 -0
  262. package/dist/utils/instance-registry.js +437 -0
  263. package/dist/utils/locale.js +21 -0
  264. package/dist/utils/log-writer.js +224 -0
  265. package/dist/utils/logger.js +89 -0
  266. package/dist/utils/markdown-to-plain-text.js +20 -0
  267. package/dist/utils/media-cache.js +271 -0
  268. package/dist/utils/model-prices.jsonl +17 -0
  269. package/dist/utils/npm-ops.js +210 -0
  270. package/dist/utils/process-introspect.js +133 -0
  271. package/dist/utils/process-tree-stats.js +271 -0
  272. package/dist/utils/project-path.js +74 -0
  273. package/dist/utils/stats.js +410 -0
  274. package/dist/utils/tool-summary.js +284 -0
  275. package/dist/utils/welcome.js +268 -0
  276. package/kits/docs/GUIDE.md +20 -0
  277. package/kits/docs/INDEX.md +65 -0
  278. package/kits/docs/aun/CHEATSHEET.md +19 -0
  279. package/kits/docs/aun/SYNC_PROTOCOL.md +15 -0
  280. package/kits/docs/channels/aun.md +65 -0
  281. package/kits/docs/channels/feishu.md +56 -0
  282. package/kits/docs/context-assembly.md +366 -0
  283. package/kits/docs/eck_templates/GUIDE.template.md +22 -0
  284. package/kits/docs/eck_templates/INDEX.template.md +28 -0
  285. package/kits/docs/eck_templates/path-registry.template.md +33 -0
  286. package/kits/docs/eck_templates/runtime.template.md +19 -0
  287. package/kits/docs/evolcore/INDEX.md +66 -0
  288. package/kits/docs/evolcore/agent.md +69 -0
  289. package/kits/docs/evolcore/aid.md +49 -0
  290. package/kits/docs/evolcore/config.md +149 -0
  291. package/kits/docs/evolcore/ctl.md +46 -0
  292. package/kits/docs/evolcore/event.md +216 -0
  293. package/kits/docs/evolcore/fs-architecture.md +1215 -0
  294. package/kits/docs/evolcore/fs.md +101 -0
  295. package/kits/docs/evolcore/group-fs.md +17 -0
  296. package/kits/docs/evolcore/group-rules.md +226 -0
  297. package/kits/docs/evolcore/group.md +141 -0
  298. package/kits/docs/evolcore/model.md +47 -0
  299. package/kits/docs/evolcore/msg.md +130 -0
  300. package/kits/docs/evolcore/response.md +80 -0
  301. package/kits/docs/evolcore/rpc.md +35 -0
  302. package/kits/docs/evolcore/self-summary.md +29 -0
  303. package/kits/docs/evolcore/stats.md +70 -0
  304. package/kits/docs/evolcore/storage.md +49 -0
  305. package/kits/docs/evolcore/trigger.md +524 -0
  306. package/kits/docs/identity/AID_PROFILE_SPEC.md +26 -0
  307. package/kits/docs/identity/PATH_OPS.md +16 -0
  308. package/kits/docs/identity/ROLE_DETAIL.md +23 -0
  309. package/kits/docs/identity/identity-tools.md +26 -0
  310. package/kits/docs/path-registry.md +43 -0
  311. package/kits/docs/prompt-loading-architecture.md +266 -0
  312. package/kits/docs/venues/aun-group.md +45 -0
  313. package/kits/docs/venues/aun-private.md +10 -0
  314. package/kits/docs/venues/client-desktop.md +10 -0
  315. package/kits/docs/venues/client-mobile.md +10 -0
  316. package/kits/docs/venues/feishu-group.md +13 -0
  317. package/kits/docs/venues/feishu-private.md +9 -0
  318. package/kits/docs/venues/group.md +25 -0
  319. package/kits/docs/venues/private.md +10 -0
  320. package/kits/eck_manifest.auxiliary.json +43 -0
  321. package/kits/eck_manifest.json +191 -0
  322. package/kits/eck_message_manifest.json +63 -0
  323. package/kits/migrations/README-role-config-v4.md +32 -0
  324. package/kits/migrations/migrate-role-config-v4.mjs +623 -0
  325. package/kits/migrations/migrate-role-config-v5.mjs +346 -0
  326. package/kits/migrations/rename-config-file.mjs +99 -0
  327. package/kits/rules/01-overview.md +142 -0
  328. package/kits/rules/02-navigation.md +76 -0
  329. package/kits/rules/03-identity.md +34 -0
  330. package/kits/rules/04-relation.md +59 -0
  331. package/kits/rules/05-venue.md +44 -0
  332. package/kits/rules/06-channel.md +59 -0
  333. package/kits/schemas/_meta.json +29 -0
  334. package/kits/schemas/agent-config.schema.1.json +177 -0
  335. package/kits/schemas/agent-config.schema.2.json +239 -0
  336. package/kits/schemas/agent-config.schema.3.json +119 -0
  337. package/kits/schemas/agent-config.schema.4.json +208 -0
  338. package/kits/schemas/agent-config.schema.5.json +326 -0
  339. package/kits/schemas/contact-book.schema.1.json +36 -0
  340. package/kits/schemas/daemon.schema.1.json +90 -0
  341. package/kits/schemas/defaults.schema.1.json +81 -0
  342. package/kits/schemas/menu-exec-schema-commands.md +208 -0
  343. package/kits/schemas/migrations/README.md +28 -0
  344. package/kits/schemas/relation-config.schema.1.json +158 -0
  345. package/kits/schemas/relation-config.schema.2.json +73 -0
  346. package/kits/schemas/relation-config.schema.3.json +50 -0
  347. package/kits/schemas/relation-config.schema.4.json +47 -0
  348. package/kits/schemas/role-config.schema.1.json +200 -0
  349. package/kits/schemas/role-registry.schema.1.json +35 -0
  350. package/kits/schemas/single-session.schema.1.json +31 -0
  351. package/kits/templates/bootstrap-welcome.md +15 -0
  352. package/kits/templates/message-fragments/handoff-request-to-target.md +13 -0
  353. package/kits/templates/message-fragments/handoff-response-to-origin.md +10 -0
  354. package/kits/templates/message-fragments/inject-default.md +2 -0
  355. package/kits/templates/message-fragments/item.md +2 -0
  356. package/kits/templates/roles/admin.json +8 -0
  357. package/kits/templates/roles/member.json +40 -0
  358. package/kits/templates/roles/owner.json +8 -0
  359. package/kits/templates/roles/visitor.json +39 -0
  360. package/kits/templates/system-fragments/baseagent.md +14 -0
  361. package/kits/templates/system-fragments/bootstrap.md +16 -0
  362. package/kits/templates/system-fragments/channel.md +48 -0
  363. package/kits/templates/system-fragments/commands.md +26 -0
  364. package/kits/templates/system-fragments/identity.md +11 -0
  365. package/kits/templates/system-fragments/relation.md +19 -0
  366. package/kits/templates/system-fragments/session.md +53 -0
  367. package/kits/templates/system-fragments/venue.md +31 -0
  368. package/package.json +50 -15
  369. package/dist/index.d.ts +0 -7
  370. package/dist/index.d.ts.map +0 -1
  371. package/dist/index.js.map +0 -1
@@ -0,0 +1,277 @@
1
+ /**
2
+ * Channel Plugin System
3
+ *
4
+ * Provides a lightweight plugin interface for channel integration.
5
+ * Plugins are responsible for creating channel instances only.
6
+ * The main service (index.ts) handles registration and message flow wiring.
7
+ */
8
+ import { logger } from '../utils/logger.js';
9
+ // ── Shared helpers for plugins ─────────────────────────────────────────────
10
+ /** Resolve showActivities for a single instance (instance overrides default). */
11
+ export function resolveShowActivities(inst) {
12
+ return inst.showActivities ?? 'all';
13
+ }
14
+ /**
15
+ * showMiddleResult / showIdleMonitor 策略。
16
+ * show_activities 只对 interactive 私聊中间输出有意义:
17
+ * all → 文本 + activity;text → 仅文本;none → 全部静默。
18
+ */
19
+ export function middleOutputModePolicy(mode, chatType, _identity) {
20
+ if (chatType !== 'private')
21
+ return 'none';
22
+ return mode;
23
+ }
24
+ export function showActivitiesPolicy(mode, chatType, _identity) {
25
+ return middleOutputModePolicy(mode, chatType, _identity) !== 'none';
26
+ }
27
+ // ── ChannelLoader ──────────────────────────────────────────────────────────
28
+ export class ChannelLoader {
29
+ plugins = new Map();
30
+ register(plugin) {
31
+ if (this.plugins.has(plugin.name)) {
32
+ throw new Error(`Channel plugin '${plugin.name}' already registered`);
33
+ }
34
+ this.plugins.set(plugin.name, plugin);
35
+ logger.debug(`Registered channel plugin: ${plugin.name}`);
36
+ }
37
+ /** Look up a registered plugin by channel type (used by reload hooks). */
38
+ getPlugin(type) {
39
+ return this.plugins.get(type);
40
+ }
41
+ /**
42
+ * Create all runtime channels for an agent directly from its config.channels[].
43
+ * AUN is always created implicitly from agent.aid (no explicit entry required).
44
+ */
45
+ async createForAgent(agent) {
46
+ const ctx = {
47
+ agentName: agent.aid,
48
+ defaultProjectPath: agent.config.projects?.defaultPath ?? process.cwd(),
49
+ debug: agent.config.debug,
50
+ };
51
+ // Build the full list of config instances to create.
52
+ // AUN is synthesised from agent.aid; any explicit aun entry in channels[] is skipped.
53
+ const aunEffName = agent.effectiveChannelName('aun', 'main');
54
+ const aunInst = {
55
+ type: 'aun',
56
+ name: aunEffName,
57
+ aid: agent.aid,
58
+ owner: agent.getOwner(aunEffName),
59
+ enabled: true,
60
+ };
61
+ const configInsts = [aunInst];
62
+ for (const inst of agent.config.channels) {
63
+ if (inst.type === 'aun')
64
+ continue;
65
+ const effName = agent.effectiveChannelName(inst.type, inst.name);
66
+ configInsts.push({ ...inst, name: effName });
67
+ }
68
+ return this._buildInstances(configInsts, ctx);
69
+ }
70
+ /** Build runtime instances for a list of config instances + context. */
71
+ async _buildInstances(configInsts, ctx) {
72
+ const result = [];
73
+ for (const inst of configInsts) {
74
+ const plugin = this.plugins.get(inst.type);
75
+ if (!plugin) {
76
+ logger.debug(`No plugin for channel type '${inst.type}', skipping`);
77
+ continue;
78
+ }
79
+ try {
80
+ const runtime = await plugin.createInstance(inst, ctx);
81
+ if (runtime) {
82
+ result.push(runtime);
83
+ logger.info(`✓ Channel '${inst.name}' (${inst.type}) created`);
84
+ }
85
+ else {
86
+ logger.info(`Channel '${inst.name}' (${inst.type}) disabled or invalid credentials, skipping`);
87
+ }
88
+ }
89
+ catch (err) {
90
+ logger.error(`✗ Failed to create channel '${inst.name}' (${inst.type}):`, err);
91
+ }
92
+ }
93
+ return result;
94
+ }
95
+ async connectAll(instances, { concurrency = 3, intervalMs = 50, onConnected, onFailed } = {}) {
96
+ const connected = [];
97
+ const failed = [];
98
+ const inflight = new Set();
99
+ for (const inst of instances) {
100
+ while (inflight.size >= concurrency) {
101
+ await Promise.race(inflight);
102
+ }
103
+ const task = (async () => {
104
+ try {
105
+ await inst.connect();
106
+ connected.push(inst.adapter.channelName);
107
+ // Fire callback without blocking the connection pipeline
108
+ if (onConnected) {
109
+ Promise.resolve(onConnected(inst)).catch((callbackErr) => {
110
+ logger.warn(`[connectAll] ${inst.adapter.channelName} onConnected callback failed: ${callbackErr}`);
111
+ });
112
+ }
113
+ }
114
+ catch (e) {
115
+ failed.push({ name: inst.adapter.channelName, error: e });
116
+ logger.warn(`[connectAll] ${inst.adapter.channelName} connect failed: ${e}`);
117
+ // Fire callback without blocking the connection pipeline
118
+ if (onFailed) {
119
+ Promise.resolve(onFailed(inst, e)).catch((callbackErr) => {
120
+ logger.warn(`[connectAll] ${inst.adapter.channelName} onFailed callback failed: ${callbackErr}`);
121
+ });
122
+ }
123
+ }
124
+ })();
125
+ const tracked = task.finally(() => { inflight.delete(tracked); });
126
+ inflight.add(tracked);
127
+ if (intervalMs > 0) {
128
+ await new Promise(r => setTimeout(r, intervalMs));
129
+ }
130
+ }
131
+ await Promise.allSettled(inflight);
132
+ if (failed.length > 0) {
133
+ logger.warn(`[connectAll] ${failed.length} channel(s) failed initial connect (will retry in background): ${failed.map(f => f.name).join(', ')}`);
134
+ }
135
+ return connected;
136
+ }
137
+ async disconnectAll(instances) {
138
+ await Promise.allSettled(instances.map(inst => inst.disconnect()));
139
+ }
140
+ }
141
+ const SEP = '#';
142
+ export function formatChannelKey(k) {
143
+ if (k.selfAID.includes(SEP)) {
144
+ throw new Error(`Invalid selfAID (contains '#'): ${k.selfAID}`);
145
+ }
146
+ return `${k.type}${SEP}${k.selfAID}${SEP}${k.name}`;
147
+ }
148
+ export function parseChannelKey(key) {
149
+ const parts = key.split(SEP);
150
+ if (parts.length !== 3) {
151
+ throw new Error(`Invalid channel key (expected 3 segments separated by '#'): ${key}`);
152
+ }
153
+ const [type, selfAID, name] = parts;
154
+ if (!type || !selfAID || !name) {
155
+ throw new Error(`Invalid channel key (empty segment): ${key}`);
156
+ }
157
+ return { type, selfAID, name };
158
+ }
159
+ export function tryParseChannelKey(key) {
160
+ try {
161
+ return parseChannelKey(key);
162
+ }
163
+ catch {
164
+ return null;
165
+ }
166
+ }
167
+ export function isValidChannelName(name) {
168
+ return typeof name === 'string' && name.length > 0 && !name.includes(SEP);
169
+ }
170
+ export function buildReloadHooks(deps) {
171
+ const { channelLoader, channelInstances, registerChannelInstance, unregisterChannelInstance, messageQueue, handoffRuntime, onChannelStarted, onChannelConnected } = deps;
172
+ const drainDelayMs = deps.drainDelayMs ?? 500;
173
+ const drainTimeoutMs = deps.drainTimeoutMs ?? 30000;
174
+ return {
175
+ async prepareHandoffReload(aid) {
176
+ if (!handoffRuntime)
177
+ return;
178
+ logger.info(`[Reload] Pausing Handoff dispatcher for agent: ${aid}`);
179
+ handoffRuntime.pauseAgent(aid);
180
+ await handoffRuntime.drainAgent(aid, drainTimeoutMs);
181
+ },
182
+ async completeHandoffReload(aid) {
183
+ if (!handoffRuntime)
184
+ return;
185
+ try {
186
+ await handoffRuntime.recover([aid]);
187
+ }
188
+ finally {
189
+ handoffRuntime.resumeAgent(aid);
190
+ }
191
+ logger.info(`[Reload] Resumed Handoff dispatcher for agent: ${aid}`);
192
+ },
193
+ async drainChannel(channelName) {
194
+ logger.info(`[Reload] Draining channel: ${channelName}`);
195
+ if (messageQueue) {
196
+ const pollMs = 100;
197
+ const start = Date.now();
198
+ while (messageQueue.isChannelProcessing(channelName)) {
199
+ if (Date.now() - start > drainTimeoutMs) {
200
+ logger.warn(`[Reload] Drain timeout (${drainTimeoutMs}ms) for channel: ${channelName}, proceeding anyway`);
201
+ return;
202
+ }
203
+ await new Promise(r => setTimeout(r, pollMs));
204
+ }
205
+ logger.info(`[Reload] Drain complete: ${channelName}`);
206
+ }
207
+ else if (drainDelayMs > 0) {
208
+ await new Promise(r => setTimeout(r, drainDelayMs));
209
+ }
210
+ },
211
+ async disconnectChannel(channelName) {
212
+ const inst = channelInstances.find(i => i.adapter.channelName === channelName);
213
+ if (!inst) {
214
+ logger.warn(`[Reload] Channel ${channelName} not found, skipping disconnect`);
215
+ return;
216
+ }
217
+ try {
218
+ await inst.disconnect();
219
+ const idx = channelInstances.indexOf(inst);
220
+ if (idx >= 0)
221
+ channelInstances.splice(idx, 1);
222
+ // 从 core 各 map 注销,避免死实例残留在 /status「未归属渠道」、菜单路由和 adapter 查找里
223
+ unregisterChannelInstance?.(channelName);
224
+ logger.info(`[Reload] Disconnected channel: ${channelName}`);
225
+ }
226
+ catch (e) {
227
+ logger.error(`[Reload] Failed to disconnect ${channelName}: ${e}`);
228
+ throw e;
229
+ }
230
+ },
231
+ async startChannel(agent, channelName) {
232
+ // The implicit AUN channel is synthesised from agent.aid (not in config.channels[]).
233
+ // Reconstruct it the same way createForAgent does before falling back to config scan.
234
+ const aid = agent.aid ?? agent.config?.aid;
235
+ const aunEffName = agent.effectiveChannelName?.('aun', 'main') ?? 'aun-main';
236
+ const isImplicitAun = channelName === aunEffName;
237
+ // Find config instance: implicit AUN gets a synthetic entry; others scan channels[].
238
+ const cfgInst = isImplicitAun
239
+ ? { type: 'aun', name: aunEffName, aid, enabled: true }
240
+ : (() => {
241
+ const agentChannels = agent.config?.channels ?? [];
242
+ return agentChannels.find((i) => {
243
+ const effName = agent.effectiveChannelName?.(i.type, i.name) ?? i.name;
244
+ return effName === channelName;
245
+ }) ?? null;
246
+ })();
247
+ if (!cfgInst) {
248
+ const msg = `[Reload] Channel ${channelName} not found in agent config`;
249
+ logger.error(msg);
250
+ throw new Error(msg);
251
+ }
252
+ const ctx = {
253
+ agentName: agent.aid ?? agent.config?.aid,
254
+ defaultProjectPath: agent.config?.projects?.defaultPath ?? process.cwd(),
255
+ debug: agent.config?.debug,
256
+ };
257
+ const plugin = channelLoader.getPlugin(cfgInst.type);
258
+ if (!plugin)
259
+ throw new Error(`[Reload] No plugin for channel type '${cfgInst.type}'`);
260
+ const effInst = { ...cfgInst, name: channelName };
261
+ const newInst = await plugin.createInstance(effInst, ctx);
262
+ if (!newInst) {
263
+ // createInstance returns null for a disabled / invalid-credential channel.
264
+ // Not an error: skip it. Throwing here would propagate to reload(), which
265
+ // turns it into agent error state and takes down every healthy channel too.
266
+ logger.warn(`[Reload] Channel ${channelName} (${cfgInst.type}) disabled or invalid credentials, skipping`);
267
+ return;
268
+ }
269
+ registerChannelInstance(newInst);
270
+ onChannelStarted?.(newInst);
271
+ await newInst.connect();
272
+ channelInstances.push(newInst);
273
+ await onChannelConnected?.(newInst);
274
+ logger.info(`[Reload] Started channel: ${channelName}`);
275
+ },
276
+ };
277
+ }