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,66 @@
1
+ export function normalizeCliArgv(argv) {
2
+ if (argv[0] === 'ec' && argv[1])
3
+ return argv.slice(1);
4
+ return argv;
5
+ }
6
+ export function validateCliArgv(value) {
7
+ if (!Array.isArray(value) || value.length === 0)
8
+ return { ok: false, reason: 'args.argv must be a non-empty string array' };
9
+ if (value.length > 64)
10
+ return { ok: false, reason: 'args.argv exceeds the 64 argument limit' };
11
+ if (value.some(arg => typeof arg !== 'string'))
12
+ return { ok: false, reason: 'args.argv entries must be strings' };
13
+ const argv = value;
14
+ if (argv.some(arg => arg.length > 4 * 1024))
15
+ return { ok: false, reason: 'args.argv entry exceeds 4096 characters' };
16
+ if (argv.some(arg => arg.includes('\0')))
17
+ return { ok: false, reason: 'args.argv entries must not contain NUL' };
18
+ if (argv.reduce((total, arg) => total + arg.length, 0) > 16 * 1024) {
19
+ return { ok: false, reason: 'args.argv exceeds the 16 KiB total limit' };
20
+ }
21
+ return { ok: true, argv };
22
+ }
23
+ export function parseLegacyCliCommand(command) {
24
+ const argv = [];
25
+ let current = '';
26
+ let quote = null;
27
+ let escaped = false;
28
+ for (const char of command) {
29
+ if (escaped) {
30
+ current += char;
31
+ escaped = false;
32
+ continue;
33
+ }
34
+ if (char === '\\') {
35
+ escaped = true;
36
+ continue;
37
+ }
38
+ if (quote) {
39
+ if (char === quote)
40
+ quote = null;
41
+ else
42
+ current += char;
43
+ continue;
44
+ }
45
+ if (char === "'" || char === '"') {
46
+ quote = char;
47
+ continue;
48
+ }
49
+ if (/\s/.test(char)) {
50
+ if (current) {
51
+ argv.push(current);
52
+ current = '';
53
+ }
54
+ continue;
55
+ }
56
+ if ('|&;<>()$`'.includes(char)) {
57
+ return { ok: false, reason: 'args.command contains a forbidden shell operator' };
58
+ }
59
+ current += char;
60
+ }
61
+ if (escaped || quote)
62
+ return { ok: false, reason: 'args.command contains an incomplete escape or quote' };
63
+ if (current)
64
+ argv.push(current);
65
+ return validateCliArgv(argv);
66
+ }
@@ -0,0 +1,329 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ const SOURCE_EXTENSIONS = new Set([
4
+ '.ts', '.tsx', '.mts', '.cts',
5
+ '.js', '.jsx', '.mjs', '.cjs',
6
+ ]);
7
+ const SECTION_DEFINITIONS = [
8
+ { key: 'core', label: '核心模块' },
9
+ { key: 'agents', label: 'Agent 模块' },
10
+ { key: 'channels', label: '渠道适配' },
11
+ { key: 'utils', label: '工具库' },
12
+ { key: 'cli', label: 'CLI' },
13
+ { key: 'aun', label: 'AUN 协议' },
14
+ { key: 'trigger', label: 'Trigger 系统' },
15
+ { key: 'config', label: '配置系统' },
16
+ { key: 'stats', label: '统计系统' },
17
+ { key: 'eck', label: 'ECK' },
18
+ { key: 'response', label: '响应系统' },
19
+ { key: 'ecweb', label: 'ECWeb' },
20
+ { key: 'other', label: '其他源码目录' },
21
+ { key: 'entry', label: '根入口文件' },
22
+ ];
23
+ const V2_SECTION_KEYS = [
24
+ 'core', 'agents', 'channels', 'utils', 'cli', 'aun',
25
+ 'subsystems', 'eck', 'response', 'other', 'entry', 'bin',
26
+ ];
27
+ const V3_SECTION_KEYS = [
28
+ 'core', 'agents', 'channels', 'utils', 'cli', 'aun',
29
+ 'trigger', 'config', 'stats', 'eck', 'response', 'other', 'entry', 'bin',
30
+ ];
31
+ const TOP_LEVEL_SECTION = {
32
+ core: 'core',
33
+ agents: 'agents',
34
+ channels: 'channels',
35
+ utils: 'utils',
36
+ cli: 'cli',
37
+ aun: 'aun',
38
+ trigger: 'trigger',
39
+ config: 'config',
40
+ stats: 'stats',
41
+ eck: 'eck',
42
+ 'response-system': 'response',
43
+ };
44
+ const COMBINING_MARK_RE = /\p{Mark}/u;
45
+ function isWideCodePoint(codePoint) {
46
+ return codePoint >= 0x1100 && (codePoint <= 0x115f
47
+ || codePoint === 0x2329
48
+ || codePoint === 0x232a
49
+ || (codePoint >= 0x2e80 && codePoint <= 0x303e)
50
+ || (codePoint >= 0x3040 && codePoint <= 0xa4cf && codePoint !== 0x303f)
51
+ || (codePoint >= 0xac00 && codePoint <= 0xd7a3)
52
+ || (codePoint >= 0xf900 && codePoint <= 0xfaff)
53
+ || (codePoint >= 0xfe10 && codePoint <= 0xfe19)
54
+ || (codePoint >= 0xfe30 && codePoint <= 0xfe6f)
55
+ || (codePoint >= 0xff00 && codePoint <= 0xff60)
56
+ || (codePoint >= 0xffe0 && codePoint <= 0xffe6)
57
+ || (codePoint >= 0x1b000 && codePoint <= 0x1b001)
58
+ || (codePoint >= 0x1f200 && codePoint <= 0x1f251)
59
+ || (codePoint >= 0x20000 && codePoint <= 0x3fffd));
60
+ }
61
+ function displayWidth(value) {
62
+ let width = 0;
63
+ for (const char of value) {
64
+ const codePoint = char.codePointAt(0);
65
+ if (codePoint === 0
66
+ || codePoint < 0x20
67
+ || (codePoint >= 0x7f && codePoint < 0xa0)
68
+ || codePoint === 0x200d
69
+ || (codePoint >= 0xfe00 && codePoint <= 0xfe0f)
70
+ || COMBINING_MARK_RE.test(char))
71
+ continue;
72
+ width += isWideCodePoint(codePoint) ? 2 : 1;
73
+ }
74
+ return width;
75
+ }
76
+ function padDisplayEnd(value, targetWidth) {
77
+ return value + ' '.repeat(Math.max(0, targetWidth - displayWidth(value)));
78
+ }
79
+ function isSourceFile(fileName) {
80
+ return SOURCE_EXTENSIONS.has(path.extname(fileName).toLowerCase());
81
+ }
82
+ function countFileLines(filePath) {
83
+ const content = fs.readFileSync(filePath, 'utf-8');
84
+ if (content.length === 0)
85
+ return 0;
86
+ const newlines = content.match(/\n/g)?.length ?? 0;
87
+ return newlines + (content.endsWith('\n') ? 0 : 1);
88
+ }
89
+ function walkSourceFiles(dir) {
90
+ if (!fs.existsSync(dir))
91
+ return [];
92
+ const files = [];
93
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
94
+ const full = path.join(dir, entry.name);
95
+ if (entry.isDirectory()) {
96
+ files.push(...walkSourceFiles(full));
97
+ }
98
+ else if (entry.isFile() && isSourceFile(entry.name)) {
99
+ files.push(full);
100
+ }
101
+ }
102
+ return files;
103
+ }
104
+ function resolveSourceRoot(pkgRoot) {
105
+ const direct = path.join(pkgRoot, 'src');
106
+ if (fs.existsSync(direct))
107
+ return { packageDir: pkgRoot, sourceDir: direct };
108
+ const parent = path.resolve(pkgRoot, '..');
109
+ const sibling = path.join(parent, 'src');
110
+ if (fs.existsSync(sibling))
111
+ return { packageDir: parent, sourceDir: sibling };
112
+ return { packageDir: pkgRoot, sourceDir: direct };
113
+ }
114
+ /**
115
+ * Scan EvolCore and ECWeb source files. Classification happens after discovery,
116
+ * so a newly added main-package src directory or root source file is still
117
+ * included even when it has not been assigned a named section yet.
118
+ */
119
+ export function collectCodeStats(pkgRoot) {
120
+ const { packageDir, sourceDir } = resolveSourceRoot(pkgRoot);
121
+ const sections = new Map(SECTION_DEFINITIONS.map(def => [def.key, { ...def, lines: 0, files: 0 }]));
122
+ const otherDirectories = new Set();
123
+ const scannedFiles = [];
124
+ for (const file of walkSourceFiles(sourceDir)) {
125
+ const relative = path.relative(sourceDir, file);
126
+ const parts = relative.split(path.sep);
127
+ let sectionKey;
128
+ if (parts.length === 1) {
129
+ sectionKey = 'entry';
130
+ }
131
+ else {
132
+ sectionKey = TOP_LEVEL_SECTION[parts[0]] ?? 'other';
133
+ if (sectionKey === 'other')
134
+ otherDirectories.add(parts[0]);
135
+ }
136
+ const section = sections.get(sectionKey);
137
+ section.lines += countFileLines(file);
138
+ section.files++;
139
+ scannedFiles.push(path.relative(packageDir, file));
140
+ }
141
+ const ecwebSourceDir = path.join(packageDir, 'ecweb', 'src');
142
+ for (const file of walkSourceFiles(ecwebSourceDir)) {
143
+ const section = sections.get('ecweb');
144
+ section.lines += countFileLines(file);
145
+ section.files++;
146
+ scannedFiles.push(path.relative(packageDir, file));
147
+ }
148
+ const sectionList = SECTION_DEFINITIONS.map(def => sections.get(def.key));
149
+ return {
150
+ sourceDir,
151
+ sections: sectionList,
152
+ totalLines: sectionList.reduce((sum, section) => sum + section.lines, 0),
153
+ totalFiles: sectionList.reduce((sum, section) => sum + section.files, 0),
154
+ scannedFiles: scannedFiles.sort(),
155
+ otherDirectories: [...otherDirectories].sort(),
156
+ };
157
+ }
158
+ function parseHistoryLine(line) {
159
+ const parts = line.split('\t');
160
+ const currentTotalIndex = SECTION_DEFINITIONS.length + 2;
161
+ if (parts[1] === 'v4' && parts.length >= currentTotalIndex + 3) {
162
+ const values = {};
163
+ SECTION_DEFINITIONS.forEach((def, index) => {
164
+ values[def.key] = Number.parseInt(parts[index + 2], 10) || 0;
165
+ });
166
+ return {
167
+ time: parts[0],
168
+ values,
169
+ total: Number.parseInt(parts[currentTotalIndex], 10) || 0,
170
+ files: Number.parseInt(parts[currentTotalIndex + 1], 10) || 0,
171
+ delta: parts[currentTotalIndex + 2],
172
+ version: 4,
173
+ };
174
+ }
175
+ if (parts[1] === 'v3' && parts.length >= 19) {
176
+ const values = {};
177
+ V3_SECTION_KEYS.forEach((key, index) => {
178
+ values[key] = Number.parseInt(parts[index + 2], 10) || 0;
179
+ });
180
+ return {
181
+ time: parts[0],
182
+ values,
183
+ total: Number.parseInt(parts[16], 10) || 0,
184
+ files: Number.parseInt(parts[17], 10) || 0,
185
+ delta: parts[18],
186
+ version: 3,
187
+ };
188
+ }
189
+ if (parts[1] === 'v2' && parts.length >= 17) {
190
+ const values = {};
191
+ V2_SECTION_KEYS.forEach((key, index) => {
192
+ values[key] = Number.parseInt(parts[index + 2], 10) || 0;
193
+ });
194
+ return {
195
+ time: parts[0],
196
+ values,
197
+ total: Number.parseInt(parts[14], 10) || 0,
198
+ files: Number.parseInt(parts[15], 10) || 0,
199
+ delta: parts[16],
200
+ version: 2,
201
+ };
202
+ }
203
+ // Legacy TSV formats, newest first:
204
+ // 11 columns: time core agents channels utils cli aun sys entry total delta
205
+ // 10 columns: time core agents channels utils cli aun entry total delta
206
+ // 8 columns: time core agents channels utils entry total delta
207
+ // 7 columns: time core agents channels utils entry total
208
+ // 6 columns: time core channels utils entry total
209
+ const values = {};
210
+ let totalIndex;
211
+ let deltaIndex;
212
+ if (parts.length >= 11) {
213
+ [values.core, values.agents, values.channels, values.utils, values.cli, values.aun, values.subsystems, values.entry]
214
+ = [parts[1], parts[2], parts[3], parts[4], parts[5], parts[6], parts[7], parts[8]].map(Number);
215
+ totalIndex = 9;
216
+ deltaIndex = 10;
217
+ }
218
+ else if (parts.length >= 10) {
219
+ [values.core, values.agents, values.channels, values.utils, values.cli, values.aun, values.entry]
220
+ = [parts[1], parts[2], parts[3], parts[4], parts[5], parts[6], parts[7]].map(Number);
221
+ totalIndex = 8;
222
+ deltaIndex = 9;
223
+ }
224
+ else if (parts.length >= 8) {
225
+ [values.core, values.agents, values.channels, values.utils, values.entry]
226
+ = [parts[1], parts[2], parts[3], parts[4], parts[5]].map(Number);
227
+ totalIndex = 6;
228
+ deltaIndex = 7;
229
+ }
230
+ else if (parts.length >= 7) {
231
+ [values.core, values.agents, values.channels, values.utils, values.entry]
232
+ = [parts[1], parts[2], parts[3], parts[4], parts[5]].map(Number);
233
+ totalIndex = 6;
234
+ }
235
+ else if (parts.length >= 6) {
236
+ [values.core, values.channels, values.utils, values.entry]
237
+ = [parts[1], parts[2], parts[3], parts[4]].map(Number);
238
+ totalIndex = 5;
239
+ }
240
+ else {
241
+ return null;
242
+ }
243
+ const total = Number.parseInt(parts[totalIndex], 10);
244
+ if (!Number.isFinite(total))
245
+ return null;
246
+ return {
247
+ time: parts[0],
248
+ values,
249
+ total,
250
+ delta: deltaIndex === undefined ? undefined : parts[deltaIndex],
251
+ version: 1,
252
+ };
253
+ }
254
+ function historyRecords(statsFile) {
255
+ if (!fs.existsSync(statsFile))
256
+ return [];
257
+ return fs.readFileSync(statsFile, 'utf-8')
258
+ .split('\n')
259
+ .filter(Boolean)
260
+ .map(parseHistoryLine)
261
+ .filter((record) => record !== null);
262
+ }
263
+ function appendHistory(statsFile, stats, previous) {
264
+ const values = Object.fromEntries(stats.sections.map(section => [section.key, section.lines]));
265
+ const unchanged = previous?.version === 4
266
+ && previous.files === stats.totalFiles
267
+ && SECTION_DEFINITIONS.every(def => previous.values[def.key] === values[def.key]);
268
+ if (unchanged)
269
+ return;
270
+ const now = new Date();
271
+ const pad = (n) => String(n).padStart(2, '0');
272
+ const timestamp = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`;
273
+ const delta = stats.totalLines - (previous?.total ?? 0);
274
+ const fields = [
275
+ timestamp,
276
+ 'v4',
277
+ ...SECTION_DEFINITIONS.map(def => values[def.key]),
278
+ stats.totalLines,
279
+ stats.totalFiles,
280
+ delta >= 0 ? `+${delta}` : String(delta),
281
+ ];
282
+ fs.mkdirSync(path.dirname(statsFile), { recursive: true });
283
+ fs.appendFileSync(statsFile, `${fields.join('\t')}\n`);
284
+ }
285
+ function showHistory(records) {
286
+ if (records.length < 2)
287
+ return;
288
+ console.log('\n==================================================');
289
+ console.log('历史记录(最近 10 次)');
290
+ console.log('==================================================');
291
+ console.log(`${'Time'.padEnd(19)} ${'Files'.padStart(7)} ${'Total'.padStart(8)} ${'Delta'.padStart(8)}`);
292
+ console.log('--------------------------------------------------');
293
+ let previousTotal = null;
294
+ for (const record of records.slice(-10)) {
295
+ const inferredDelta = previousTotal === null ? '-' : record.total - previousTotal;
296
+ const delta = record.delta ?? (typeof inferredDelta === 'number' && inferredDelta >= 0 ? `+${inferredDelta}` : String(inferredDelta));
297
+ console.log(`${record.time.padEnd(19)} ${String(record.files ?? '-').padStart(7)} ${String(record.total).padStart(8)} ${delta.padStart(8)}`);
298
+ previousTotal = record.total;
299
+ }
300
+ console.log('==================================================');
301
+ }
302
+ export function printCodeStats(pkgRoot, logDir) {
303
+ console.log('\n[launcher] 正在统计代码行数...\n');
304
+ const stats = collectCodeStats(pkgRoot);
305
+ const statsFile = path.join(logDir, 'line-stats.log');
306
+ console.log('==================================================');
307
+ console.log('EvolCore 代码统计');
308
+ console.log('==================================================');
309
+ const rows = stats.sections
310
+ .filter(section => section.key !== 'other' || section.files > 0)
311
+ .map(section => {
312
+ const suffix = section.key === 'other' && stats.otherDirectories.length > 0
313
+ ? ` (${stats.otherDirectories.join(', ')})`
314
+ : '';
315
+ return { section, label: `${section.label}${suffix}:` };
316
+ });
317
+ const labelWidth = Math.max(24, ...rows.map(row => displayWidth(row.label)));
318
+ for (const { section, label } of rows) {
319
+ console.log(`${padDisplayEnd(label, labelWidth)} ${String(section.lines).padStart(8)} 行 ${String(section.files).padStart(4)} 文件`);
320
+ }
321
+ console.log('--------------------------------------------------');
322
+ console.log(`${padDisplayEnd('总计:', labelWidth)} ${String(stats.totalLines).padStart(8)} 行 ${String(stats.totalFiles).padStart(4)} 文件`);
323
+ console.log(`扫描范围: src + ecweb/src (${SOURCE_EXTENSIONS.size} 种源码扩展名)`);
324
+ console.log('==================================================');
325
+ const records = historyRecords(statsFile);
326
+ appendHistory(statsFile, stats, records.at(-1));
327
+ showHistory(historyRecords(statsFile));
328
+ return stats;
329
+ }
@@ -0,0 +1,82 @@
1
+ /**
2
+ * 命令集执行日志 —— 每执行一条 `ec` 命令追加一行 JSONL。日志按天切分(一天一个文件,
3
+ * 文件名 commands-YYYYMMDD.jsonl)。
4
+ *
5
+ * 挂在唯一 choke-point(src/cli/index.ts 的 main() 第一行),所有子命令必经,
6
+ * 无需改动任何具体命令集代码。
7
+ *
8
+ * 两级落盘:
9
+ * - 汇总日志 $EVOLCORE_HOME/logs/commands-YYYYMMDD.jsonl:所有命令(不论有无 AID)都记
10
+ * 一份,一处看全貌;记录带 selfAid,按 agent 过滤一行 grep 即可。
11
+ * - per-agent 日志 agents/<aid>/logs/commands-YYYYMMDD.jsonl:能同步解析出 self-AID 时
12
+ * 额外再记一份,便于单独查看某个 agent。
13
+ *
14
+ * 原则:日志写失败静默降级,绝不影响命令执行(沿用 log-writer.ts 的取舍)。
15
+ */
16
+ import fs from 'fs';
17
+ import path from 'path';
18
+ import { agentLogsDir, resolvePaths } from '../paths.js';
19
+ import { getArgValue } from './help.js';
20
+ import { readTaskRuntimeContextFromEnv } from './task-context.js';
21
+ /**
22
+ * 同步解析当前执行者 self-AID(零延迟,绝不走 IPC)。
23
+ * 优先级:--as <aid> > EVOLCORE_SELF_AID > runtime context 里的 selfAid。
24
+ */
25
+ function resolveSelfAid(args) {
26
+ return (getArgValue(args, '--as') ||
27
+ process.env.EVOLCORE_SELF_AID ||
28
+ readTaskRuntimeContextFromEnv()?.selfAid);
29
+ }
30
+ /**
31
+ * 记录一条命令执行。同步、best-effort。
32
+ * @param cmd 子命令(args[0],缺省时为 'start')
33
+ * @param args 完整 argv 原样
34
+ */
35
+ export function logCliCommand(cmd, args) {
36
+ const selfAid = resolveSelfAid(args);
37
+ const line = JSON.stringify({
38
+ ts: localTimestamp(),
39
+ cmd,
40
+ // 完整命令行,可直接拷贝执行(含 ec 前缀,含空格的参数自动加引号)
41
+ command: `ec ${args.map(shellQuote).join(' ')}`,
42
+ selfAid: selfAid || undefined,
43
+ sessionId: process.env.EVOLCORE_SESSION_ID || undefined,
44
+ }) + '\n';
45
+ const fileName = `commands-${dayTag()}.jsonl`;
46
+ // 汇总日志:所有命令(不论有无 AID)都记一份,一处看全貌。
47
+ appendLine(resolvePaths().logs, fileName, line);
48
+ // per-agent 日志:有 AID 时再额外记一份到该 agent 自己的 logs/,便于单独查看。
49
+ if (selfAid)
50
+ appendLine(agentLogsDir(selfAid), fileName, line);
51
+ }
52
+ /** 本地时间字符串 YYYY-MM-DD HH:mm:ss(不含时区偏移,直接可读)。 */
53
+ function localTimestamp() {
54
+ const d = new Date();
55
+ const pad = (n) => String(n).padStart(2, '0');
56
+ return (`${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ` +
57
+ `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`);
58
+ }
59
+ /** 拼命令行时给单个参数按需加引号:含空格/引号/特殊字符才包一层单引号。 */
60
+ function shellQuote(arg) {
61
+ if (arg === '')
62
+ return "''";
63
+ if (/^[A-Za-z0-9_@%+=:,./-]+$/.test(arg))
64
+ return arg;
65
+ return `'${arg.replace(/'/g, `'\\''`)}'`;
66
+ }
67
+ /** 本地日期 tag YYYYMMDD,用于日志文件按天切分(一天一个文件)。 */
68
+ function dayTag() {
69
+ const d = new Date();
70
+ const pad = (n) => String(n).padStart(2, '0');
71
+ return `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}`;
72
+ }
73
+ /** 追加一行到 <dir>/<fileName>,best-effort——写失败静默降级,绝不影响命令执行。 */
74
+ function appendLine(dir, fileName, line) {
75
+ try {
76
+ fs.mkdirSync(dir, { recursive: true });
77
+ fs.appendFileSync(path.join(dir, fileName), line);
78
+ }
79
+ catch {
80
+ // 日志不能影响业务
81
+ }
82
+ }
@@ -0,0 +1,69 @@
1
+ import { normalizePeer, ModelScopeError } from '../core/model/config-scope.js';
2
+ export function parseConfigSelector(args, options) {
3
+ let self;
4
+ let peerRaw;
5
+ let isDefault = false;
6
+ let isProcess = false;
7
+ const seen = new Set();
8
+ for (let i = 0; i < args.length; i++) {
9
+ const arg = args[i];
10
+ if (arg === '--self' || arg === '--peer') {
11
+ if (seen.has(arg))
12
+ return { ok: false, code: 'SELECTOR_CONFLICT', reason: `Duplicate selector: ${arg}` };
13
+ seen.add(arg);
14
+ const value = args[i + 1];
15
+ if (!value || value.startsWith('-')) {
16
+ return { ok: false, code: 'MISSING_FLAG_VALUE', reason: `${arg} requires a value` };
17
+ }
18
+ if (arg === '--self')
19
+ self = value;
20
+ else
21
+ peerRaw = value;
22
+ i += 1;
23
+ continue;
24
+ }
25
+ if (arg === '--default') {
26
+ if (seen.has('--default'))
27
+ return { ok: false, code: 'SELECTOR_CONFLICT', reason: 'Duplicate selector: --default' };
28
+ seen.add('--default');
29
+ isDefault = true;
30
+ continue;
31
+ }
32
+ if (arg === '--process' || arg === '--daemon') {
33
+ if (seen.has('--process'))
34
+ return { ok: false, code: 'SELECTOR_CONFLICT', reason: 'Duplicate process selector' };
35
+ seen.add('--process');
36
+ isProcess = true;
37
+ }
38
+ }
39
+ if (isProcess && (self || peerRaw !== undefined || isDefault)) {
40
+ return { ok: false, code: 'SELECTOR_CONFLICT', reason: '--process cannot be combined with --self/--peer/--default' };
41
+ }
42
+ if (isDefault && (self || peerRaw !== undefined)) {
43
+ return { ok: false, code: 'SELECTOR_CONFLICT', reason: '--default cannot be combined with --self/--peer' };
44
+ }
45
+ if (peerRaw !== undefined && !self) {
46
+ return { ok: false, code: 'PEER_WITHOUT_SELF', reason: '--peer requires --self' };
47
+ }
48
+ if (isProcess)
49
+ return { ok: true, scope: 'process' };
50
+ if (isDefault)
51
+ return { ok: true, scope: 'defaults' };
52
+ if (self) {
53
+ if (peerRaw !== undefined) {
54
+ try {
55
+ return { ok: true, scope: 'relation', self, peerKey: normalizePeer(peerRaw) };
56
+ }
57
+ catch (error) {
58
+ if (error instanceof ModelScopeError)
59
+ return { ok: false, code: error.code, reason: error.message };
60
+ throw error;
61
+ }
62
+ }
63
+ return { ok: true, scope: 'agent', self };
64
+ }
65
+ if (options.requireSelector) {
66
+ return { ok: false, code: 'SELECTOR_REQUIRED', reason: 'A config selector is required' };
67
+ }
68
+ return { ok: true, scope: 'agent' };
69
+ }