evolcore 0.0.1 → 0.0.3

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 (379) hide show
  1. package/CHANGELOG.md +64 -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/bin/ec-safe-output.js +161 -0
  8. package/bin/ec.js +29 -0
  9. package/dist/agents/baseagent.js +163 -0
  10. package/dist/agents/claude-runner.js +2565 -0
  11. package/dist/agents/codex-app-server-client.js +448 -0
  12. package/dist/agents/codex-runner.js +2682 -0
  13. package/dist/agents/gemini-runner.js +666 -0
  14. package/dist/agents/runner-types.js +75 -0
  15. package/dist/aun/aid/agentmd.js +216 -0
  16. package/dist/aun/aid/client.js +132 -0
  17. package/dist/aun/aid/control-aid.js +91 -0
  18. package/dist/aun/aid/identity.js +518 -0
  19. package/dist/aun/aid/index.js +4 -0
  20. package/dist/aun/aid/store.js +74 -0
  21. package/dist/aun/aid/types.js +1 -0
  22. package/dist/aun/aid/validation.js +21 -0
  23. package/dist/aun/group-identity.js +10 -0
  24. package/dist/aun/msg/group-index.js +6 -0
  25. package/dist/aun/msg/group.js +1231 -0
  26. package/dist/aun/msg/history.js +123 -0
  27. package/dist/aun/msg/index.js +5 -0
  28. package/dist/aun/msg/p2p.js +393 -0
  29. package/dist/aun/msg/payload-type.js +27 -0
  30. package/dist/aun/msg/upload.js +137 -0
  31. package/dist/aun/outbox.js +168 -0
  32. package/dist/aun/rpc/caller.js +42 -0
  33. package/dist/aun/rpc/connection.js +25 -0
  34. package/dist/aun/rpc/index.js +2 -0
  35. package/dist/aun/service-proxy.js +225 -0
  36. package/dist/aun/storage/download.js +29 -0
  37. package/dist/aun/storage/index.js +3 -0
  38. package/dist/aun/storage/manage.js +10 -0
  39. package/dist/aun/storage/upload.js +68 -0
  40. package/dist/channels/aun.js +4164 -0
  41. package/dist/channels/contact-bind-code.js +134 -0
  42. package/dist/channels/daemon.js +422 -0
  43. package/dist/channels/dingtalk.js +1479 -0
  44. package/dist/channels/feishu.js +1865 -0
  45. package/dist/channels/qqbot.js +409 -0
  46. package/dist/channels/wechat.js +817 -0
  47. package/dist/channels/wecom-card.js +101 -0
  48. package/dist/channels/wecom-onboarding.js +82 -0
  49. package/dist/channels/wecom-state.js +191 -0
  50. package/dist/channels/wecom.js +1157 -0
  51. package/dist/cli/agent-command.js +642 -0
  52. package/dist/cli/agent.js +1059 -0
  53. package/dist/cli/aun-commands.js +2003 -0
  54. package/dist/cli/bench.js +1228 -0
  55. package/dist/cli/cli-argv.js +66 -0
  56. package/dist/cli/code-stats.js +329 -0
  57. package/dist/cli/command-log.js +82 -0
  58. package/dist/cli/config-selector.js +69 -0
  59. package/dist/cli/config.js +261 -0
  60. package/dist/cli/contact.js +71 -0
  61. package/dist/cli/ctl-command.js +62 -0
  62. package/dist/cli/daemon-commands.js +2750 -0
  63. package/dist/cli/fs-command.js +1447 -0
  64. package/dist/cli/handoff-command.js +302 -0
  65. package/dist/cli/help.js +35 -0
  66. package/dist/cli/index.js +374 -0
  67. package/dist/cli/init-channel.js +1372 -0
  68. package/dist/cli/init.js +590 -0
  69. package/dist/cli/link-rules.js +240 -0
  70. package/dist/cli/model.js +591 -0
  71. package/dist/cli/net-check.js +723 -0
  72. package/dist/cli/queue-command.js +150 -0
  73. package/dist/cli/raw-key-input.js +25 -0
  74. package/dist/cli/response.js +344 -0
  75. package/dist/cli/restart-monitor.js +480 -0
  76. package/dist/cli/stats.js +609 -0
  77. package/dist/cli/task-context.js +80 -0
  78. package/dist/cli/trigger-command.js +545 -0
  79. package/dist/cli/version.js +93 -0
  80. package/dist/cli/watch-logs.js +33 -0
  81. package/dist/cli/watch-msg.js +673 -0
  82. package/dist/config/boot-log.js +266 -0
  83. package/dist/config/builtin-role-templates.js +42 -0
  84. package/dist/config/builtin-roles.js +91 -0
  85. package/dist/config/config-batch-get.js +11 -0
  86. package/dist/config/config-field-policy.js +261 -0
  87. package/dist/config/config-manager.js +1120 -0
  88. package/dist/config/config-operation-service.js +384 -0
  89. package/dist/config/contact-alias.js +68 -0
  90. package/dist/config/contact-book-store.js +454 -0
  91. package/dist/config/contact-book-v2-startup.js +35 -0
  92. package/dist/config/contact-book.js +224 -0
  93. package/dist/config/contact-operation-service.js +110 -0
  94. package/dist/config/gateway-config.js +858 -0
  95. package/dist/config/lifecycle.js +17 -0
  96. package/dist/config/mention-mode.js +27 -0
  97. package/dist/config/merge.js +161 -0
  98. package/dist/config/owner-policy.js +4 -0
  99. package/dist/config/peer-role-resolver.js +218 -0
  100. package/dist/config/resolved-config-op.js +483 -0
  101. package/dist/config/role-config-v4-startup.js +32 -0
  102. package/dist/config/role-config-v5-startup.js +27 -0
  103. package/dist/config/role-ranks.js +18 -0
  104. package/dist/config/role-schema.js +105 -0
  105. package/dist/config/role-service.js +156 -0
  106. package/dist/config/role-store.js +215 -0
  107. package/dist/config/roles.js +64 -0
  108. package/dist/config/schema-registry.js +154 -0
  109. package/dist/config/snapshot.js +598 -0
  110. package/dist/config-store.js +501 -0
  111. package/dist/core/auth/agent-delegation.js +111 -0
  112. package/dist/core/auth/auth-gateway.js +166 -0
  113. package/dist/core/auth/authenticated-actor.js +6 -0
  114. package/dist/core/auth/authorization-audit.js +119 -0
  115. package/dist/core/auth/operation-authorizer.js +720 -0
  116. package/dist/core/auth/operation-catalog.js +731 -0
  117. package/dist/core/baseagent-loader.js +54 -0
  118. package/dist/core/bootstrap-service.js +175 -0
  119. package/dist/core/capability/capability-manager.js +316 -0
  120. package/dist/core/capability/providers/claude-capability-provider.js +176 -0
  121. package/dist/core/capability/providers/codex-capability-provider.js +148 -0
  122. package/dist/core/capability/providers/gemini-capability-provider.js +10 -0
  123. package/dist/core/capability/types.js +27 -0
  124. package/dist/core/causation/audit.js +103 -0
  125. package/dist/core/causation/aun-association.js +111 -0
  126. package/dist/core/causation/context.js +93 -0
  127. package/dist/core/causation/index.js +4 -0
  128. package/dist/core/causation/types.js +2 -0
  129. package/dist/core/channel-loader.js +277 -0
  130. package/dist/core/command/agent-control.js +616 -0
  131. package/dist/core/command/cli-intent-parser.js +225 -0
  132. package/dist/core/command/command-handler.js +1733 -0
  133. package/dist/core/command/connect-menu.js +374 -0
  134. package/dist/core/command/menu-handler.js +3452 -0
  135. package/dist/core/command/menu-protocol.js +247 -0
  136. package/dist/core/command/role-menu.js +1623 -0
  137. package/dist/core/command/slash-gate.js +148 -0
  138. package/dist/core/command/slash-handler.js +3066 -0
  139. package/dist/core/daemon-file-cache.js +222 -0
  140. package/dist/core/event-bus.js +32 -0
  141. package/dist/core/event-catalog.js +810 -0
  142. package/dist/core/evolagent-registry.js +545 -0
  143. package/dist/core/evolagent.js +342 -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 +659 -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 +874 -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 +1446 -0
  161. package/dist/core/message/message-utils.js +76 -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 +4020 -0
  166. package/dist/core/message/response-snapshot.js +83 -0
  167. package/dist/core/message/send-receipt.js +24 -0
  168. package/dist/core/message/stream-debouncer.js +139 -0
  169. package/dist/core/message/stream-idle-monitor.js +124 -0
  170. package/dist/core/model/config-scope.js +162 -0
  171. package/dist/core/model/field-scope.js +78 -0
  172. package/dist/core/model/model-catalog.js +227 -0
  173. package/dist/core/model/model-diagnostics.js +182 -0
  174. package/dist/core/model/model-permission.js +90 -0
  175. package/dist/core/permission/approval-gateway.js +1017 -0
  176. package/dist/core/permission/ec-command-parser.js +347 -0
  177. package/dist/core/permission/execution-sandbox.js +16 -0
  178. package/dist/core/permission/index.js +6 -0
  179. package/dist/core/permission/mode.js +24 -0
  180. package/dist/core/permission/sandbox-runtime.js +265 -0
  181. package/dist/core/permission/tool-policy.js +1019 -0
  182. package/dist/core/permission/unix-socket-policy.js +99 -0
  183. package/dist/core/protected-paths.js +332 -0
  184. package/dist/core/relation/peer-identity.js +222 -0
  185. package/dist/core/relation/peer-key.js +1 -0
  186. package/dist/core/role/runtime-policy.js +141 -0
  187. package/dist/core/session/adapters/claude-session-file-adapter.js +218 -0
  188. package/dist/core/session/adapters/codex-session-file-adapter.js +333 -0
  189. package/dist/core/session/adapters/gemini-session-file-adapter.js +181 -0
  190. package/dist/core/session/session-file-adapter.js +7 -0
  191. package/dist/core/session/session-file-health.js +45 -0
  192. package/dist/core/session/session-fs-store.js +273 -0
  193. package/dist/core/session/session-key.js +24 -0
  194. package/dist/core/session/session-manager.js +1643 -0
  195. package/dist/core/session/session-mapper.js +100 -0
  196. package/dist/core/session/session-renew.js +314 -0
  197. package/dist/core/session/session-title.js +128 -0
  198. package/dist/core/session/session-turn-coordinator.js +205 -0
  199. package/dist/core/session/session-turns.js +67 -0
  200. package/dist/core/system-channels.js +29 -0
  201. package/dist/eck/baseagent-caps.js +18 -0
  202. package/dist/eck/detect.js +47 -0
  203. package/dist/eck/group-rules-sync.js +345 -0
  204. package/dist/eck/init.js +77 -0
  205. package/dist/eck/kit-renderer.js +359 -0
  206. package/dist/eck/manifest-engine.js +446 -0
  207. package/dist/eck/message-renderer.js +199 -0
  208. package/dist/eck/rules-loader.js +28 -0
  209. package/dist/index.js +2926 -4
  210. package/dist/ipc.js +777 -0
  211. package/dist/paths.js +262 -0
  212. package/dist/product.js +18 -0
  213. package/dist/response-system/context-builder.js +71 -0
  214. package/dist/response-system/coordinator.js +117 -0
  215. package/dist/response-system/decision-executor.js +86 -0
  216. package/dist/response-system/engines/v1/index.js +21 -0
  217. package/dist/response-system/engines/v1/interactive-flow.js +27 -0
  218. package/dist/response-system/engines/v1/proactive-flow.js +137 -0
  219. package/dist/response-system/engines/v1/types.js +1 -0
  220. package/dist/response-system/extensions.js +41 -0
  221. package/dist/response-system/index.js +6 -0
  222. package/dist/response-system/modes/index.js +7 -0
  223. package/dist/response-system/modes/single-session/index.js +72 -0
  224. package/dist/response-system/queues/fifo-queue.js +44 -0
  225. package/dist/response-system/queues/index.js +6 -0
  226. package/dist/response-system/queues/lifo-queue.js +42 -0
  227. package/dist/response-system/queues/priority-queue.js +63 -0
  228. package/dist/response-system/registry.js +97 -0
  229. package/dist/response-system/resolver.js +37 -0
  230. package/dist/response-system/selector.js +23 -0
  231. package/dist/response-system/types.js +7 -0
  232. package/dist/stats/billing.js +163 -0
  233. package/dist/stats/budget.js +93 -0
  234. package/dist/stats/db.js +403 -0
  235. package/dist/stats/eck-vars.js +89 -0
  236. package/dist/stats/index.js +11 -0
  237. package/dist/stats/normalizer.js +80 -0
  238. package/dist/stats/price-resolver.js +138 -0
  239. package/dist/stats/query.js +763 -0
  240. package/dist/stats/role-budget.js +168 -0
  241. package/dist/stats/writer.js +151 -0
  242. package/dist/trigger/anomaly-store.js +258 -0
  243. package/dist/trigger/audit.js +152 -0
  244. package/dist/trigger/event-source.js +119 -0
  245. package/dist/trigger/feedback.js +685 -0
  246. package/dist/trigger/history.js +290 -0
  247. package/dist/trigger/manager.js +294 -0
  248. package/dist/trigger/parser.js +595 -0
  249. package/dist/trigger/patch.js +155 -0
  250. package/dist/trigger/scheduler.js +1602 -0
  251. package/dist/trigger/script-executor.js +155 -0
  252. package/dist/trigger/state.js +145 -0
  253. package/dist/trigger/types.js +1 -0
  254. package/dist/trigger/validation.js +634 -0
  255. package/dist/types.js +12 -0
  256. package/dist/utils/aid-bind.js +313 -0
  257. package/dist/utils/atomic-write.js +95 -0
  258. package/dist/utils/avatar-upload.js +123 -0
  259. package/dist/utils/cross-platform.js +297 -0
  260. package/dist/utils/ecweb-utils.js +73 -0
  261. package/dist/utils/error-dict.json +153 -0
  262. package/dist/utils/error-utils.js +349 -0
  263. package/dist/utils/instance-registry.js +444 -0
  264. package/dist/utils/locale.js +21 -0
  265. package/dist/utils/log-writer.js +270 -0
  266. package/dist/utils/logger.js +89 -0
  267. package/dist/utils/markdown-to-plain-text.js +20 -0
  268. package/dist/utils/media-cache.js +274 -0
  269. package/dist/utils/model-prices.jsonl +20 -0
  270. package/dist/utils/npm-ops.js +210 -0
  271. package/dist/utils/process-introspect.js +133 -0
  272. package/dist/utils/process-tree-stats.js +271 -0
  273. package/dist/utils/project-path.js +74 -0
  274. package/dist/utils/restart-safety.js +31 -0
  275. package/dist/utils/stats.js +410 -0
  276. package/dist/utils/system-memory.js +62 -0
  277. package/dist/utils/tool-summary.js +284 -0
  278. package/dist/utils/welcome.js +268 -0
  279. package/kits/docs/GUIDE.md +20 -0
  280. package/kits/docs/INDEX.md +66 -0
  281. package/kits/docs/aun/CHEATSHEET.md +19 -0
  282. package/kits/docs/aun/SYNC_PROTOCOL.md +15 -0
  283. package/kits/docs/channels/aun.md +65 -0
  284. package/kits/docs/channels/feishu.md +56 -0
  285. package/kits/docs/context-assembly.md +366 -0
  286. package/kits/docs/eck_templates/GUIDE.template.md +22 -0
  287. package/kits/docs/eck_templates/INDEX.template.md +28 -0
  288. package/kits/docs/eck_templates/path-registry.template.md +33 -0
  289. package/kits/docs/eck_templates/runtime.template.md +19 -0
  290. package/kits/docs/evolcore/INDEX.md +68 -0
  291. package/kits/docs/evolcore/agent.md +77 -0
  292. package/kits/docs/evolcore/aid.md +52 -0
  293. package/kits/docs/evolcore/config.md +149 -0
  294. package/kits/docs/evolcore/contact.md +57 -0
  295. package/kits/docs/evolcore/ctl.md +46 -0
  296. package/kits/docs/evolcore/event.md +216 -0
  297. package/kits/docs/evolcore/fs-architecture.md +1215 -0
  298. package/kits/docs/evolcore/fs.md +110 -0
  299. package/kits/docs/evolcore/group-fs.md +17 -0
  300. package/kits/docs/evolcore/group-rules.md +226 -0
  301. package/kits/docs/evolcore/group.md +150 -0
  302. package/kits/docs/evolcore/model.md +50 -0
  303. package/kits/docs/evolcore/msg.md +136 -0
  304. package/kits/docs/evolcore/response.md +75 -0
  305. package/kits/docs/evolcore/rpc.md +37 -0
  306. package/kits/docs/evolcore/self-summary.md +29 -0
  307. package/kits/docs/evolcore/stats.md +83 -0
  308. package/kits/docs/evolcore/storage.md +50 -0
  309. package/kits/docs/evolcore/trigger.md +539 -0
  310. package/kits/docs/identity/AID_PROFILE_SPEC.md +26 -0
  311. package/kits/docs/identity/PATH_OPS.md +16 -0
  312. package/kits/docs/identity/ROLE_DETAIL.md +23 -0
  313. package/kits/docs/identity/identity-tools.md +26 -0
  314. package/kits/docs/path-registry.md +43 -0
  315. package/kits/docs/prompt-loading-architecture.md +266 -0
  316. package/kits/docs/venues/aun-group.md +45 -0
  317. package/kits/docs/venues/aun-private.md +10 -0
  318. package/kits/docs/venues/client-desktop.md +10 -0
  319. package/kits/docs/venues/client-mobile.md +10 -0
  320. package/kits/docs/venues/feishu-group.md +13 -0
  321. package/kits/docs/venues/feishu-private.md +9 -0
  322. package/kits/docs/venues/group.md +25 -0
  323. package/kits/docs/venues/private.md +10 -0
  324. package/kits/eck_manifest.auxiliary.json +43 -0
  325. package/kits/eck_manifest.json +203 -0
  326. package/kits/eck_message_manifest.json +63 -0
  327. package/kits/migrations/README-role-config-v4.md +32 -0
  328. package/kits/migrations/migrate-contact-book-v2.mjs +747 -0
  329. package/kits/migrations/migrate-role-config-v4.mjs +623 -0
  330. package/kits/migrations/migrate-role-config-v5.mjs +346 -0
  331. package/kits/migrations/rename-config-file.mjs +99 -0
  332. package/kits/rules/01-overview.md +142 -0
  333. package/kits/rules/02-navigation.md +76 -0
  334. package/kits/rules/03-identity.md +34 -0
  335. package/kits/rules/04-relation.md +59 -0
  336. package/kits/rules/05-venue.md +44 -0
  337. package/kits/rules/06-channel.md +59 -0
  338. package/kits/schemas/_meta.json +32 -0
  339. package/kits/schemas/agent-config.schema.1.json +177 -0
  340. package/kits/schemas/agent-config.schema.2.json +239 -0
  341. package/kits/schemas/agent-config.schema.3.json +119 -0
  342. package/kits/schemas/agent-config.schema.4.json +208 -0
  343. package/kits/schemas/agent-config.schema.5.json +326 -0
  344. package/kits/schemas/agent-config.schema.6.json +322 -0
  345. package/kits/schemas/contact-book.schema.1.json +36 -0
  346. package/kits/schemas/contact-book.schema.2.json +43 -0
  347. package/kits/schemas/daemon.schema.1.json +90 -0
  348. package/kits/schemas/defaults.schema.1.json +81 -0
  349. package/kits/schemas/menu-exec-schema-commands.md +208 -0
  350. package/kits/schemas/migrations/README.md +28 -0
  351. package/kits/schemas/relation-config.schema.1.json +158 -0
  352. package/kits/schemas/relation-config.schema.2.json +73 -0
  353. package/kits/schemas/relation-config.schema.3.json +50 -0
  354. package/kits/schemas/relation-config.schema.4.json +47 -0
  355. package/kits/schemas/relation-config.schema.5.json +47 -0
  356. package/kits/schemas/role-config.schema.1.json +201 -0
  357. package/kits/schemas/role-registry.schema.1.json +35 -0
  358. package/kits/schemas/single-session.schema.1.json +31 -0
  359. package/kits/templates/bootstrap-welcome.md +15 -0
  360. package/kits/templates/message-fragments/handoff-request-to-target.md +13 -0
  361. package/kits/templates/message-fragments/handoff-response-to-origin.md +10 -0
  362. package/kits/templates/message-fragments/inject-default.md +2 -0
  363. package/kits/templates/message-fragments/item.md +2 -0
  364. package/kits/templates/roles/admin.json +9 -0
  365. package/kits/templates/roles/member.json +41 -0
  366. package/kits/templates/roles/owner.json +9 -0
  367. package/kits/templates/roles/visitor.json +40 -0
  368. package/kits/templates/system-fragments/baseagent.md +14 -0
  369. package/kits/templates/system-fragments/bootstrap.md +16 -0
  370. package/kits/templates/system-fragments/channel.md +48 -0
  371. package/kits/templates/system-fragments/commands.md +28 -0
  372. package/kits/templates/system-fragments/identity.md +11 -0
  373. package/kits/templates/system-fragments/relation.md +19 -0
  374. package/kits/templates/system-fragments/session.md +53 -0
  375. package/kits/templates/system-fragments/venue.md +31 -0
  376. package/package.json +50 -15
  377. package/dist/index.d.ts +0 -7
  378. package/dist/index.d.ts.map +0 -1
  379. package/dist/index.js.map +0 -1
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Agent Plugin System
3
+ *
4
+ * Per-EvolAgent runner instantiation: each (EvolAgent × baseagent) gets its
5
+ * own runner so that runtime state (model/effort/permissionMode/credentials)
6
+ * is fully isolated.
7
+ */
8
+ import { logger } from '../utils/logger.js';
9
+ /** Agent Loader — produces one runner per (EvolAgent × baseagent). */
10
+ export class AgentLoader {
11
+ plugins = new Map();
12
+ register(plugin) {
13
+ if (this.plugins.has(plugin.name)) {
14
+ throw new Error(`Agent plugin '${plugin.name}' already registered`);
15
+ }
16
+ this.plugins.set(plugin.name, plugin);
17
+ logger.debug(`Registered agent plugin: ${plugin.name}`);
18
+ }
19
+ /**
20
+ * Iterate over all EvolAgents in the registry × all registered plugins.
21
+ * Each successful (agent, plugin) pair yields one runner instance.
22
+ */
23
+ createAll(registry, callbacks) {
24
+ const instances = [];
25
+ const allAgents = registry.runnableAgents();
26
+ for (const agent of allAgents) {
27
+ instances.push(...this.createForAgent(agent, callbacks));
28
+ }
29
+ return instances;
30
+ }
31
+ /** Create runners for one EvolAgent, used by runtime hot-load. */
32
+ createForAgent(agent, callbacks) {
33
+ const instances = [];
34
+ for (const [pluginName, plugin] of this.plugins) {
35
+ if (!plugin.isEnabled(agent)) {
36
+ logger.debug(`Plugin '${pluginName}' disabled for agent '${agent.name}', skipping`);
37
+ continue;
38
+ }
39
+ try {
40
+ const instance = plugin.createAgent(agent, callbacks);
41
+ if (!instance) {
42
+ logger.debug(`Plugin '${pluginName}' returned null for agent '${agent.name}', skipping`);
43
+ continue;
44
+ }
45
+ instances.push(instance);
46
+ logger.info(`✓ Runner created: agent=${instance.evolagentName} baseagent=${instance.baseagent}`);
47
+ }
48
+ catch (error) {
49
+ logger.error(`✗ Failed to create runner for agent='${agent.name}' baseagent='${pluginName}':`, error);
50
+ }
51
+ }
52
+ return instances;
53
+ }
54
+ }
@@ -0,0 +1,175 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { randomBytes } from 'crypto';
4
+ import { kitsTemplatesDir, agentMdPath } from '../paths.js';
5
+ import { logger } from '../utils/logger.js';
6
+ import { loadAgent, saveAgent } from '../config-store.js';
7
+ import { normalizeAgentLifecycle, withLifecycleForWrite } from '../config/lifecycle.js';
8
+ import { renderTemplate } from '../eck/manifest-engine.js';
9
+ import { activeBaseagent } from './model/config-scope.js';
10
+ import { buildEnvelope } from './message/message-utils.js';
11
+ export class BootstrapService {
12
+ agentRegistry;
13
+ eventBus;
14
+ inFlight = new Set();
15
+ constructor(agentRegistry, eventBus) {
16
+ this.agentRegistry = agentRegistry;
17
+ this.eventBus = eventBus;
18
+ }
19
+ async tryStartBootstrap(ctx) {
20
+ const agent = ctx.agentAid
21
+ ? this.agentRegistry.get(ctx.agentAid)
22
+ : this.agentRegistry.resolveByChannel(ctx.channelKey);
23
+ const aid = agent?.aid || ctx.agentAid;
24
+ if (!aid)
25
+ return false;
26
+ const key = aid;
27
+ if (this.inFlight.has(key))
28
+ return false;
29
+ this.inFlight.add(key);
30
+ let lifecycleStarted = false;
31
+ const loadedConfig = agent?.config || loadAgent(aid);
32
+ if (!loadedConfig) {
33
+ this.inFlight.delete(key);
34
+ return false;
35
+ }
36
+ const config = normalizeAgentLifecycle(loadedConfig);
37
+ if (config.lifecycle !== 'created') {
38
+ this.inFlight.delete(key);
39
+ return false;
40
+ }
41
+ const channelType = ctx.channelType || this.channelTypeFromKey(ctx.channelKey);
42
+ const recipientId = ctx.recipientId || this.resolveConfiguredRecipient(config, ctx.channelKey, channelType);
43
+ if (!recipientId) {
44
+ this.inFlight.delete(key);
45
+ return false;
46
+ }
47
+ if (ctx.recipientId && recipientId !== ctx.recipientId) {
48
+ this.inFlight.delete(key);
49
+ return false;
50
+ }
51
+ const channelId = ctx.channelId || this.defaultChannelIdForConnection(channelType, recipientId);
52
+ if (!channelId) {
53
+ this.inFlight.delete(key);
54
+ return false;
55
+ }
56
+ try {
57
+ const agentName = this.resolveAgentDisplayName(aid);
58
+ const baseagent = this.resolveBaseagent(agent, aid);
59
+ await this.publishAgentMdIfSupported(ctx.adapter, aid, agentName);
60
+ this.setLifecycle(agent, aid, 'bootstrapping');
61
+ lifecycleStarted = true;
62
+ const text = this.renderWelcome({
63
+ agentAid: aid,
64
+ agentName,
65
+ ownerName: ctx.recipientName || recipientId,
66
+ channel: channelType || ctx.channelKey,
67
+ baseagent,
68
+ });
69
+ await ctx.adapter.send(buildEnvelope({
70
+ taskId: `bootstrap-${randomBytes(5).toString('hex')}`,
71
+ channel: ctx.adapter.channelKey || ctx.adapter.channelName,
72
+ channelId,
73
+ agentName: aid,
74
+ }), { kind: 'result.text', text, isFinal: true });
75
+ this.eventBus.publish({ type: 'agent:bootstrap-started', aid, channel: channelType || ctx.channelKey, timestamp: Date.now() });
76
+ await this.sendAunBindingCredentialIfSupported(ctx.adapter, recipientId, agentName, baseagent);
77
+ logger.info(`[Bootstrap] Started for ${aid} via ${ctx.channelKey} (${ctx.source})`);
78
+ return true;
79
+ }
80
+ catch (e) {
81
+ if (lifecycleStarted) {
82
+ try {
83
+ this.setLifecycle(agent, aid, 'created');
84
+ }
85
+ catch (rollbackErr) {
86
+ logger.warn(`[Bootstrap] Failed to roll back lifecycle for ${aid}: ${rollbackErr instanceof Error ? rollbackErr.message : String(rollbackErr)}`);
87
+ }
88
+ }
89
+ logger.warn(`[Bootstrap] Failed to start for ${aid} via ${ctx.channelKey}: ${e instanceof Error ? e.message : String(e)}`);
90
+ return false;
91
+ }
92
+ finally {
93
+ this.inFlight.delete(key);
94
+ }
95
+ }
96
+ setLifecycle(agent, aid, lifecycle) {
97
+ if (agent?.setLifecycle) {
98
+ agent.setLifecycle(lifecycle);
99
+ return;
100
+ }
101
+ const cfg = loadAgent(aid);
102
+ if (!cfg)
103
+ return;
104
+ saveAgent(withLifecycleForWrite(cfg, lifecycle));
105
+ }
106
+ resolveConfiguredRecipient(config, _channelKey, _channelType) {
107
+ return config.owners?.[0];
108
+ }
109
+ defaultChannelIdForConnection(channelType, recipientId) {
110
+ if (channelType === 'aun')
111
+ return recipientId;
112
+ if (channelType === 'feishu')
113
+ return recipientId;
114
+ return undefined;
115
+ }
116
+ channelTypeFromKey(channelKey) {
117
+ return this.parseChannelKey(channelKey)?.type;
118
+ }
119
+ parseChannelKey(channelKey) {
120
+ const parts = channelKey.split('#');
121
+ if (parts.length < 3)
122
+ return null;
123
+ return { type: parts[0], name: parts.slice(2).join('#') };
124
+ }
125
+ renderWelcome(vars) {
126
+ const templatePath = path.join(kitsTemplatesDir(), 'bootstrap-welcome.md');
127
+ const template = fs.existsSync(templatePath)
128
+ ? fs.readFileSync(templatePath, 'utf-8')
129
+ : '你好,我是 {{agentName}}。请帮我确认显示名、简介和标签。';
130
+ return renderTemplate(template, vars).trim();
131
+ }
132
+ resolveAgentDisplayName(aid) {
133
+ try {
134
+ const content = fs.readFileSync(agentMdPath(aid), 'utf-8');
135
+ const fm = content.match(/^---\n([\s\S]*?)\n---/)?.[1] || '';
136
+ const name = fm.match(/^name:\s*["']?(.+?)["']?\s*$/m)?.[1]?.trim();
137
+ if (name)
138
+ return name;
139
+ }
140
+ catch { }
141
+ return aid.split('.')[0];
142
+ }
143
+ resolveBaseagent(agent, aid) {
144
+ try {
145
+ return agent?.baseagent || activeBaseagent(aid);
146
+ }
147
+ catch {
148
+ return 'unknown';
149
+ }
150
+ }
151
+ async publishAgentMdIfSupported(adapter, aid, fallbackName) {
152
+ if (typeof adapter.uploadAgentMd !== 'function')
153
+ return;
154
+ const existing = fs.existsSync(agentMdPath(aid)) ? fs.readFileSync(agentMdPath(aid), 'utf-8') : '';
155
+ const content = existing.trim() || `---\naid: "${aid}"\nname: "${fallbackName}"\ntype: "codeagent"\nversion: "1.0.0"\ndescription: ""\ntags:\n - evolcore\n - ai-agent\n---\n`;
156
+ try {
157
+ await adapter.uploadAgentMd(content);
158
+ logger.info(`[Bootstrap] Published agent.md for ${aid}`);
159
+ }
160
+ catch (e) {
161
+ logger.warn(`[Bootstrap] Failed to publish agent.md for ${aid}: ${e instanceof Error ? e.message : String(e)}`);
162
+ }
163
+ }
164
+ async sendAunBindingCredentialIfSupported(adapter, owner, name, baseagent) {
165
+ const sendBinding = adapter._sendBindingCredential;
166
+ if (typeof sendBinding !== 'function')
167
+ return;
168
+ try {
169
+ await sendBinding(owner, name, baseagent);
170
+ }
171
+ catch (e) {
172
+ logger.warn(`[Bootstrap] Binding credential failed: ${e instanceof Error ? e.message : String(e)}`);
173
+ }
174
+ }
175
+ }
@@ -0,0 +1,316 @@
1
+ import { ConfigTarget, read, write } from '../../config/config-manager.js';
2
+ import { ClaudeCapabilityProvider } from './providers/claude-capability-provider.js';
3
+ import { CodexCapabilityProvider } from './providers/codex-capability-provider.js';
4
+ import { GeminiCapabilityProvider } from './providers/gemini-capability-provider.js';
5
+ import { CAPABILITY_TYPES, isCapabilityType, normalizeCapabilityTypeConfig, resolveCapabilityEnabled, } from './types.js';
6
+ const PROVIDERS = {
7
+ claude: new ClaudeCapabilityProvider(),
8
+ codex: new CodexCapabilityProvider(),
9
+ gemini: new GeminiCapabilityProvider(),
10
+ };
11
+ export { CAPABILITY_TYPES, isCapabilityType, resolveCapabilityEnabled };
12
+ function defaultTypeConfig() {
13
+ return { mode: 'inherit', overrides: {} };
14
+ }
15
+ function resolveBaseagent(input) {
16
+ return input.baseagent
17
+ || input.sessionBaseagent
18
+ || input.config?.active_baseagent
19
+ || 'claude';
20
+ }
21
+ export function resolveCapabilityContext(input) {
22
+ const aid = input.aid || input.config?.aid;
23
+ if (!aid)
24
+ return { error: '当前 channel 无绑定 agent', code: 'FORBIDDEN' };
25
+ const projectPath = input.config?.projects?.defaultPath || input.projectPath || input.sessionProjectPath || null;
26
+ if (!projectPath)
27
+ return { error: '无法解析当前 agent projectPath', code: 'NO_PROJECT' };
28
+ return {
29
+ aid,
30
+ baseagent: resolveBaseagent(input),
31
+ projectPath,
32
+ };
33
+ }
34
+ export function getProvider(baseagent) {
35
+ return PROVIDERS[baseagent] ?? {
36
+ baseagent,
37
+ getSupport: () => ({ mode: 'inherit', canUpdate: false, reason: `baseagent ${baseagent} 尚未支持 capability 管理` }),
38
+ discover: async () => [],
39
+ };
40
+ }
41
+ export function getAgentCapabilityConfig(config, baseagent, type) {
42
+ const root = (config?.capabilities ?? {});
43
+ return normalizeCapabilityTypeConfig(root[baseagent]?.[type]);
44
+ }
45
+ export function queryCapabilityTypes(ctx, config, onlyType) {
46
+ const provider = getProvider(ctx.baseagent);
47
+ const types = onlyType ? [onlyType] : [...CAPABILITY_TYPES];
48
+ const capabilities = {};
49
+ for (const type of types) {
50
+ const policy = getAgentCapabilityConfig(config, ctx.baseagent, type);
51
+ const support = provider.getSupport(type);
52
+ capabilities[type] = { ...support, mode: policy.mode };
53
+ }
54
+ return {
55
+ scope: 'project',
56
+ projectPath: ctx.projectPath,
57
+ baseagent: ctx.baseagent,
58
+ capabilities,
59
+ };
60
+ }
61
+ export async function listCapabilityOptions(ctx, config, type) {
62
+ const provider = getProvider(ctx.baseagent);
63
+ const policy = getAgentCapabilityConfig(config, ctx.baseagent, type);
64
+ const discovered = await provider.discover(ctx, type);
65
+ return discovered
66
+ .map(item => ({
67
+ value: item.id,
68
+ label: item.label || item.id,
69
+ desc: item.desc,
70
+ source: item.source ?? 'unknown',
71
+ status: item.status,
72
+ enabled: resolveCapabilityEnabled(policy, item.id),
73
+ override: policy.overrides[item.id] ?? null,
74
+ runtimeEnabled: item.runtimeEnabled,
75
+ }))
76
+ .sort((a, b) => a.label.localeCompare(b.label));
77
+ }
78
+ function ensureMutableCapabilityConfig(config, baseagent, type) {
79
+ const root = (config.capabilities ??= {});
80
+ const base = (root[baseagent] ??= {});
81
+ const current = normalizeCapabilityTypeConfig(base[type]);
82
+ base[type] = current;
83
+ return current;
84
+ }
85
+ export function updateCapabilityPolicy(aid, baseagent, type, value, name) {
86
+ const provider = getProvider(baseagent);
87
+ const support = provider.getSupport(type);
88
+ if (!support.canUpdate) {
89
+ throw Object.assign(new Error(support.reason || '当前 baseagent 不支持 capability 更新'), { code: 'NOT_SUPPORTED' });
90
+ }
91
+ const sel = { self: aid };
92
+ const config = read(ConfigTarget.Agent, sel) ?? { aid, channels: [] };
93
+ const target = ensureMutableCapabilityConfig(config, baseagent, type);
94
+ if (name) {
95
+ if (value !== 'enabled' && value !== 'disabled' && value !== 'inherit') {
96
+ throw Object.assign(new Error('单项级 value 只能是 enabled / disabled / inherit'), { code: 'INVALID_ARGS' });
97
+ }
98
+ if (value === 'inherit')
99
+ delete target.overrides[name];
100
+ else
101
+ target.overrides[name] = value;
102
+ write(ConfigTarget.Agent, config, sel);
103
+ return { type, name, override: value === 'inherit' ? null : value, saved: true };
104
+ }
105
+ if (value !== 'inherit' && value !== 'all' && value !== 'none') {
106
+ throw Object.assign(new Error('类型级 value 只能是 inherit / all / none'), { code: 'INVALID_ARGS' });
107
+ }
108
+ target.mode = value;
109
+ write(ConfigTarget.Agent, config, sel);
110
+ return { type, mode: value, saved: true };
111
+ }
112
+ function mergeJsonObject(target, source) {
113
+ for (const [key, value] of Object.entries(source)) {
114
+ const current = target[key];
115
+ if (value
116
+ && typeof value === 'object'
117
+ && !Array.isArray(value)
118
+ && current
119
+ && typeof current === 'object'
120
+ && !Array.isArray(current)) {
121
+ target[key] = mergeJsonObject({ ...current }, value);
122
+ }
123
+ else {
124
+ target[key] = value;
125
+ }
126
+ }
127
+ return target;
128
+ }
129
+ function resolveCapabilityIds(policy, catalog) {
130
+ const ids = new Set();
131
+ if (policy.mode === 'all') {
132
+ for (const item of catalog)
133
+ ids.add(item.id);
134
+ }
135
+ else if (policy.mode === 'none') {
136
+ for (const [id, override] of Object.entries(policy.overrides)) {
137
+ if (override === 'enabled')
138
+ ids.add(id);
139
+ }
140
+ return [...ids];
141
+ }
142
+ else {
143
+ for (const item of catalog)
144
+ ids.add(item.id);
145
+ }
146
+ for (const [id, override] of Object.entries(policy.overrides)) {
147
+ if (override === 'enabled')
148
+ ids.add(id);
149
+ else
150
+ ids.delete(id);
151
+ }
152
+ if (policy.mode === 'inherit' && Object.keys(policy.overrides).length === 0)
153
+ return null;
154
+ return [...ids];
155
+ }
156
+ async function discoverCatalogForPolicy(provider, ctx, config, baseagent) {
157
+ const catalog = {};
158
+ for (const type of CAPABILITY_TYPES) {
159
+ const policy = getAgentCapabilityConfig(config, baseagent, type);
160
+ if (policy.mode !== 'inherit' || Object.keys(policy.overrides).length > 0) {
161
+ try {
162
+ catalog[type] = await provider.discover(ctx, type);
163
+ }
164
+ catch {
165
+ catalog[type] = [];
166
+ }
167
+ }
168
+ }
169
+ return catalog;
170
+ }
171
+ export async function resolveClaudeCapabilityRunOptionsForProject(config, projectPath, baseagent = 'claude') {
172
+ const provider = getProvider(baseagent);
173
+ const ctx = { aid: config?.aid ?? '', baseagent, projectPath };
174
+ const catalog = {};
175
+ for (const type of CAPABILITY_TYPES) {
176
+ const policy = getAgentCapabilityConfig(config, baseagent, type);
177
+ if (policy.mode !== 'inherit' || Object.keys(policy.overrides).length > 0) {
178
+ try {
179
+ catalog[type] = await provider.discover(ctx, type);
180
+ }
181
+ catch {
182
+ catalog[type] = [];
183
+ }
184
+ }
185
+ }
186
+ return resolveClaudeCapabilityRunOptions(config, baseagent, catalog);
187
+ }
188
+ export function resolveClaudeCapabilityRunOptions(config, baseagent = 'claude', catalog = {}) {
189
+ const skill = getAgentCapabilityConfig(config, baseagent, 'skill');
190
+ const mcp = getAgentCapabilityConfig(config, baseagent, 'mcp');
191
+ const plugin = getAgentCapabilityConfig(config, baseagent, 'plugin');
192
+ const options = {};
193
+ const settings = {};
194
+ const enabledSkills = Object.entries(skill.overrides).filter(([, v]) => v === 'enabled').map(([id]) => id);
195
+ if (skill.mode === 'all') {
196
+ options.skills = 'all';
197
+ }
198
+ else if (skill.mode === 'none') {
199
+ options.skills = enabledSkills;
200
+ }
201
+ const skillOverrides = {};
202
+ for (const [id, value] of Object.entries(skill.overrides)) {
203
+ skillOverrides[id] = value === 'enabled' ? 'on' : 'off';
204
+ }
205
+ if (Object.keys(skillOverrides).length > 0)
206
+ settings.skillOverrides = skillOverrides;
207
+ const mcpCatalog = catalog.mcp ?? [];
208
+ const selectedMcpIds = resolveCapabilityIds(mcp, mcpCatalog);
209
+ const mcpServers = {};
210
+ const deniedMcpServerIds = new Set();
211
+ for (const [id, override] of Object.entries(mcp.overrides)) {
212
+ if (override === 'disabled')
213
+ deniedMcpServerIds.add(id);
214
+ }
215
+ for (const item of mcpCatalog) {
216
+ const enabled = selectedMcpIds === null
217
+ ? item.runtimeEnabled !== false
218
+ : selectedMcpIds.includes(item.id);
219
+ if (!enabled) {
220
+ deniedMcpServerIds.add(item.id);
221
+ continue;
222
+ }
223
+ if (!item.data || typeof item.data !== 'object' || Array.isArray(item.data))
224
+ continue;
225
+ mcpServers[item.id] = { ...item.data };
226
+ }
227
+ if (Object.keys(mcpServers).length > 0)
228
+ options.mcpServers = mcpServers;
229
+ if (mcp.mode === 'none') {
230
+ settings.allowedMcpServers = Object.entries(mcp.overrides)
231
+ .filter(([, override]) => override === 'enabled')
232
+ .map(([serverName]) => ({ serverName }));
233
+ }
234
+ if (deniedMcpServerIds.size > 0) {
235
+ settings.deniedMcpServers = [...deniedMcpServerIds].map(serverName => ({ serverName }));
236
+ }
237
+ const enabledPlugins = {};
238
+ if (plugin.mode === 'all') {
239
+ for (const item of catalog.plugin ?? []) {
240
+ enabledPlugins[item.id] = true;
241
+ }
242
+ }
243
+ if (plugin.mode === 'none') {
244
+ for (const item of catalog.plugin ?? []) {
245
+ enabledPlugins[item.id] = false;
246
+ }
247
+ }
248
+ for (const [id, value] of Object.entries(plugin.overrides)) {
249
+ enabledPlugins[id] = value === 'enabled';
250
+ }
251
+ if (Object.keys(enabledPlugins).length > 0)
252
+ settings.enabledPlugins = enabledPlugins;
253
+ if (Object.keys(settings).length > 0)
254
+ options.settings = settings;
255
+ return options;
256
+ }
257
+ export async function resolveCodexCapabilityThreadConfigForProject(config, projectPath, baseagent = 'codex') {
258
+ const provider = getProvider(baseagent);
259
+ const ctx = { aid: config?.aid ?? '', baseagent, projectPath };
260
+ const catalog = await discoverCatalogForPolicy(provider, ctx, config, baseagent);
261
+ return resolveCodexCapabilityThreadConfig(config, baseagent, catalog);
262
+ }
263
+ export function resolveCodexCapabilityThreadConfig(config, baseagent = 'codex', catalog = {}) {
264
+ const out = {};
265
+ const skill = getAgentCapabilityConfig(config, baseagent, 'skill');
266
+ const mcp = getAgentCapabilityConfig(config, baseagent, 'mcp');
267
+ const plugin = getAgentCapabilityConfig(config, baseagent, 'plugin');
268
+ const skillEntries = [];
269
+ const skillCatalog = catalog.skill ?? [];
270
+ if (skill.mode === 'none') {
271
+ for (const item of skillCatalog)
272
+ skillEntries.push({ name: item.id, enabled: false });
273
+ }
274
+ for (const [name, override] of Object.entries(skill.overrides)) {
275
+ const existing = skillEntries.find(entry => entry.name === name);
276
+ if (existing)
277
+ existing.enabled = override === 'enabled';
278
+ else
279
+ skillEntries.push({ name, enabled: override === 'enabled' });
280
+ }
281
+ if (skillEntries.length > 0) {
282
+ mergeJsonObject(out, { skills: { config: skillEntries } });
283
+ }
284
+ const mcpCatalog = catalog.mcp ?? [];
285
+ const selectedMcpIds = resolveCapabilityIds(mcp, mcpCatalog);
286
+ if (selectedMcpIds) {
287
+ const entries = Object.fromEntries(mcpCatalog
288
+ .filter(item => item.data && typeof item.data === 'object' && !Array.isArray(item.data))
289
+ .map(item => [item.id, {
290
+ ...item.data,
291
+ enabled: selectedMcpIds.includes(item.id),
292
+ }]));
293
+ for (const [id, override] of Object.entries(mcp.overrides)) {
294
+ if (override === 'disabled' && !(id in entries))
295
+ entries[id] = { enabled: false };
296
+ }
297
+ mergeJsonObject(out, { mcp_servers: entries });
298
+ }
299
+ const pluginCatalog = catalog.plugin ?? [];
300
+ const pluginConfig = {};
301
+ if (plugin.mode === 'all') {
302
+ for (const item of pluginCatalog)
303
+ pluginConfig[item.id] = { enabled: true };
304
+ }
305
+ else if (plugin.mode === 'none') {
306
+ for (const item of pluginCatalog)
307
+ pluginConfig[item.id] = { enabled: false };
308
+ }
309
+ for (const [id, override] of Object.entries(plugin.overrides)) {
310
+ pluginConfig[id] = { enabled: override === 'enabled' };
311
+ }
312
+ if (Object.keys(pluginConfig).length > 0) {
313
+ mergeJsonObject(out, { plugins: pluginConfig });
314
+ }
315
+ return out;
316
+ }