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,176 @@
1
+ import fs from 'fs';
2
+ import os from 'os';
3
+ import path from 'path';
4
+ import { execFileSync } from 'child_process';
5
+ function readJson(file) {
6
+ try {
7
+ if (!fs.existsSync(file))
8
+ return null;
9
+ return JSON.parse(fs.readFileSync(file, 'utf-8'));
10
+ }
11
+ catch {
12
+ return null;
13
+ }
14
+ }
15
+ function listDirectories(dir) {
16
+ try {
17
+ if (!fs.existsSync(dir))
18
+ return [];
19
+ return fs.readdirSync(dir, { withFileTypes: true })
20
+ .filter(entry => entry.isDirectory())
21
+ .map(entry => entry.name);
22
+ }
23
+ catch {
24
+ return [];
25
+ }
26
+ }
27
+ function readSkillDescription(skillDir) {
28
+ const file = path.join(skillDir, 'SKILL.md');
29
+ try {
30
+ const text = fs.readFileSync(file, 'utf-8');
31
+ const firstBodyLine = text.split(/\r?\n/)
32
+ .map(line => line.trim())
33
+ .find(line => line && !line.startsWith('#') && !line.startsWith('---') && !line.includes(':'));
34
+ return firstBodyLine ? firstBodyLine.slice(0, 180) : undefined;
35
+ }
36
+ catch {
37
+ return undefined;
38
+ }
39
+ }
40
+ function describeMcpSpec(spec) {
41
+ const command = typeof spec?.command === 'string' ? spec.command : undefined;
42
+ if (command)
43
+ return `stdio: ${path.basename(command)}`;
44
+ const rawUrl = typeof spec?.url === 'string' ? spec.url : typeof spec?.serverUrl === 'string' ? spec.serverUrl : undefined;
45
+ if (!rawUrl)
46
+ return undefined;
47
+ try {
48
+ const url = new URL(rawUrl);
49
+ return `remote: ${url.origin}${url.pathname}`;
50
+ }
51
+ catch {
52
+ return 'remote';
53
+ }
54
+ }
55
+ function discoverSkills(projectPath) {
56
+ const roots = [
57
+ { dir: path.join(projectPath, '.claude', 'skills'), source: 'project' },
58
+ { dir: path.join(os.homedir(), '.claude', 'skills'), source: 'user' },
59
+ ];
60
+ const seen = new Set();
61
+ const items = [];
62
+ for (const root of roots) {
63
+ for (const name of listDirectories(root.dir)) {
64
+ if (seen.has(name))
65
+ continue;
66
+ seen.add(name);
67
+ items.push({
68
+ id: name,
69
+ label: name,
70
+ desc: readSkillDescription(path.join(root.dir, name)),
71
+ source: root.source,
72
+ });
73
+ }
74
+ }
75
+ return items;
76
+ }
77
+ function readMcpServers(projectPath) {
78
+ const candidates = [
79
+ { file: path.join(projectPath, '.mcp.json'), source: 'project' },
80
+ { file: path.join(projectPath, '.claude', 'mcp.json'), source: 'project' },
81
+ { file: path.join(os.homedir(), '.claude', 'mcp.json'), source: 'user' },
82
+ ];
83
+ const seen = new Set();
84
+ const items = [];
85
+ for (const candidate of candidates) {
86
+ const config = readJson(candidate.file);
87
+ const servers = config?.mcpServers;
88
+ if (!servers || typeof servers !== 'object')
89
+ continue;
90
+ for (const [name, spec] of Object.entries(servers)) {
91
+ if (seen.has(name))
92
+ continue;
93
+ seen.add(name);
94
+ items.push({
95
+ id: name,
96
+ label: name,
97
+ desc: describeMcpSpec(spec),
98
+ source: candidate.source,
99
+ status: 'configured',
100
+ runtimeEnabled: true,
101
+ data: spec && typeof spec === 'object' && !Array.isArray(spec) ? { ...spec } : undefined,
102
+ });
103
+ }
104
+ }
105
+ return items;
106
+ }
107
+ function discoverPlugins(projectPath) {
108
+ const settingsFiles = [
109
+ { file: path.join(projectPath, '.claude', 'settings.json'), source: 'project' },
110
+ { file: path.join(projectPath, '.claude', 'settings.local.json'), source: 'project' },
111
+ { file: path.join(os.homedir(), '.claude', 'settings.json'), source: 'user' },
112
+ ];
113
+ const seen = new Set();
114
+ const items = [];
115
+ for (const candidate of settingsFiles) {
116
+ const settings = readJson(candidate.file);
117
+ const plugins = settings?.enabledPlugins;
118
+ if (!plugins || typeof plugins !== 'object')
119
+ continue;
120
+ for (const [id, enabled] of Object.entries(plugins)) {
121
+ if (seen.has(id))
122
+ continue;
123
+ seen.add(id);
124
+ items.push({
125
+ id,
126
+ label: id,
127
+ source: candidate.source,
128
+ status: enabled === false ? 'disabled' : 'configured',
129
+ runtimeEnabled: enabled !== false,
130
+ });
131
+ }
132
+ }
133
+ return items;
134
+ }
135
+ async function discoverPluginsFromCli() {
136
+ try {
137
+ const output = execFileSync('claude', ['plugin', 'list', '--json'], {
138
+ encoding: 'utf-8',
139
+ timeout: 3000,
140
+ stdio: ['ignore', 'pipe', 'pipe'],
141
+ });
142
+ const parsed = JSON.parse(output);
143
+ const list = Array.isArray(parsed) ? parsed : Array.isArray(parsed?.installed) ? parsed.installed : [];
144
+ return list.map((entry) => {
145
+ const id = String(entry.id ?? entry.name ?? entry.pluginId ?? '').trim();
146
+ return id ? {
147
+ id,
148
+ label: String(entry.name ?? entry.label ?? id),
149
+ desc: typeof entry.description === 'string' ? entry.description : undefined,
150
+ source: 'plugin',
151
+ status: entry.enabled === false ? 'disabled' : 'installed',
152
+ runtimeEnabled: entry.enabled !== false,
153
+ } : null;
154
+ }).filter(Boolean);
155
+ }
156
+ catch {
157
+ return [];
158
+ }
159
+ }
160
+ export class ClaudeCapabilityProvider {
161
+ baseagent = 'claude';
162
+ getSupport(type) {
163
+ void type;
164
+ return { mode: 'inherit', canUpdate: true };
165
+ }
166
+ async discover(ctx, type) {
167
+ if (type === 'skill')
168
+ return discoverSkills(ctx.projectPath);
169
+ if (type === 'mcp')
170
+ return readMcpServers(ctx.projectPath);
171
+ const fromSettings = discoverPlugins(ctx.projectPath);
172
+ if (fromSettings.length > 0)
173
+ return fromSettings;
174
+ return await discoverPluginsFromCli();
175
+ }
176
+ }
@@ -0,0 +1,148 @@
1
+ import fs from 'fs';
2
+ import os from 'os';
3
+ import path from 'path';
4
+ import { execFileSync } from 'child_process';
5
+ function listDirectories(dir) {
6
+ try {
7
+ if (!fs.existsSync(dir))
8
+ return [];
9
+ return fs.readdirSync(dir, { withFileTypes: true })
10
+ .filter(entry => entry.isDirectory())
11
+ .map(entry => entry.name);
12
+ }
13
+ catch {
14
+ return [];
15
+ }
16
+ }
17
+ function discoverSkills(ctx) {
18
+ const roots = [
19
+ { dir: path.join(ctx.projectPath, '.codex', 'skills'), source: 'project' },
20
+ { dir: path.join(os.homedir(), '.codex', 'skills'), source: 'user' },
21
+ { dir: path.join(os.homedir(), '.codex', 'skills', '.system'), source: 'system' },
22
+ ];
23
+ const seen = new Set();
24
+ const out = [];
25
+ for (const root of roots) {
26
+ for (const id of listDirectories(root.dir)) {
27
+ if (seen.has(id))
28
+ continue;
29
+ seen.add(id);
30
+ out.push({ id, label: id, source: root.source });
31
+ }
32
+ }
33
+ return out;
34
+ }
35
+ function runCodexJson(args) {
36
+ try {
37
+ const output = execFileSync('codex', args, {
38
+ encoding: 'utf-8',
39
+ timeout: 3000,
40
+ stdio: ['ignore', 'pipe', 'pipe'],
41
+ });
42
+ return JSON.parse(output);
43
+ }
44
+ catch {
45
+ return null;
46
+ }
47
+ }
48
+ function describeMcpEntry(entry) {
49
+ const command = typeof entry.command === 'string' ? entry.command : undefined;
50
+ if (command)
51
+ return `stdio: ${path.basename(command)}`;
52
+ const rawUrl = typeof entry.url === 'string' ? entry.url : typeof entry.serverUrl === 'string' ? entry.serverUrl : undefined;
53
+ if (!rawUrl)
54
+ return undefined;
55
+ try {
56
+ const url = new URL(rawUrl);
57
+ return `remote: ${url.origin}${url.pathname}`;
58
+ }
59
+ catch {
60
+ return 'remote';
61
+ }
62
+ }
63
+ function normalizeMcpServerConfig(entry) {
64
+ if (!entry || typeof entry !== 'object')
65
+ return undefined;
66
+ const config = {};
67
+ for (const key of [
68
+ 'command',
69
+ 'args',
70
+ 'env',
71
+ 'cwd',
72
+ 'url',
73
+ 'serverUrl',
74
+ 'bearer_token_env_var',
75
+ 'bearerTokenEnvVar',
76
+ 'http_headers',
77
+ 'httpHeaders',
78
+ 'startup_timeout_sec',
79
+ 'startupTimeoutSec',
80
+ 'startup_timeout_ms',
81
+ 'startupTimeoutMs',
82
+ 'enabled_tools',
83
+ 'enabledTools',
84
+ 'disabled_tools',
85
+ 'disabledTools',
86
+ 'tools',
87
+ 'scope',
88
+ 'oauth',
89
+ 'oauth_resource',
90
+ 'oauthResource',
91
+ ]) {
92
+ if (entry[key] !== undefined)
93
+ config[key] = entry[key];
94
+ }
95
+ return Object.keys(config).length > 0 ? config : undefined;
96
+ }
97
+ function discoverMcp() {
98
+ const parsed = runCodexJson(['mcp', 'list', '--json']);
99
+ const list = Array.isArray(parsed) ? parsed : Array.isArray(parsed?.servers) ? parsed.servers : [];
100
+ return list.map((entry) => {
101
+ const id = String(entry.name ?? entry.id ?? '').trim();
102
+ if (!id)
103
+ return null;
104
+ return {
105
+ id,
106
+ label: String(entry.label ?? entry.name ?? id),
107
+ desc: describeMcpEntry(entry),
108
+ source: entry.source === 'project' ? 'project' : 'user',
109
+ status: String(entry.status ?? 'configured'),
110
+ runtimeEnabled: entry.enabled !== false,
111
+ data: normalizeMcpServerConfig(entry),
112
+ };
113
+ }).filter(Boolean);
114
+ }
115
+ function discoverPlugins() {
116
+ const parsed = runCodexJson(['plugin', 'list', '--json']);
117
+ const installed = Array.isArray(parsed) ? parsed : Array.isArray(parsed?.installed) ? parsed.installed : [];
118
+ return installed.map((entry) => {
119
+ const id = String(entry.id ?? entry.name ?? entry.pluginId ?? '').trim();
120
+ if (!id)
121
+ return null;
122
+ return {
123
+ id,
124
+ label: String(entry.name ?? entry.label ?? id),
125
+ desc: typeof entry.description === 'string' ? entry.description : undefined,
126
+ source: 'plugin',
127
+ status: entry.enabled === false ? 'disabled' : 'installed',
128
+ runtimeEnabled: entry.enabled !== false,
129
+ };
130
+ }).filter(Boolean);
131
+ }
132
+ export class CodexCapabilityProvider {
133
+ baseagent = 'codex';
134
+ getSupport(type) {
135
+ void type;
136
+ return {
137
+ mode: 'inherit',
138
+ canUpdate: true,
139
+ };
140
+ }
141
+ async discover(ctx, type) {
142
+ if (type === 'skill')
143
+ return discoverSkills(ctx);
144
+ if (type === 'mcp')
145
+ return discoverMcp();
146
+ return discoverPlugins();
147
+ }
148
+ }
@@ -0,0 +1,10 @@
1
+ export class GeminiCapabilityProvider {
2
+ baseagent = 'gemini';
3
+ getSupport(type) {
4
+ void type;
5
+ return { mode: 'inherit', canUpdate: false, reason: 'Gemini capability 管理尚未接入' };
6
+ }
7
+ async discover(_ctx, _type) {
8
+ return [];
9
+ }
10
+ }
@@ -0,0 +1,27 @@
1
+ export const CAPABILITY_TYPES = ['skill', 'mcp', 'plugin'];
2
+ export function isCapabilityType(value) {
3
+ return typeof value === 'string' && CAPABILITY_TYPES.includes(value);
4
+ }
5
+ export function normalizeCapabilityTypeConfig(value) {
6
+ const mode = value?.mode;
7
+ const overrides = value?.overrides && typeof value.overrides === 'object'
8
+ ? value.overrides
9
+ : {};
10
+ return {
11
+ mode: mode === 'all' || mode === 'none' || mode === 'inherit' ? mode : 'inherit',
12
+ overrides: { ...overrides },
13
+ };
14
+ }
15
+ export function resolveCapabilityEnabled(config, id) {
16
+ const normalized = normalizeCapabilityTypeConfig(config);
17
+ const override = normalized.overrides[id];
18
+ if (override === 'enabled')
19
+ return true;
20
+ if (override === 'disabled')
21
+ return false;
22
+ if (normalized.mode === 'all')
23
+ return true;
24
+ if (normalized.mode === 'none')
25
+ return false;
26
+ return 'inherit';
27
+ }
@@ -0,0 +1,103 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { resolvePaths } from '../../paths.js';
4
+ import { LogWriter } from '../../utils/log-writer.js';
5
+ let writer;
6
+ function auditWriter() {
7
+ writer ??= new LogWriter({
8
+ baseName: 'causation-spans',
9
+ logDir: resolvePaths().logs,
10
+ rotation: 'daily',
11
+ retention: { days: 7 },
12
+ });
13
+ return writer;
14
+ }
15
+ function writeAuditRecord(record) {
16
+ try {
17
+ auditWriter().write(JSON.stringify(record));
18
+ }
19
+ catch {
20
+ }
21
+ }
22
+ export function recordCausationSpan(context, type, options = {}) {
23
+ const record = {
24
+ version: 1,
25
+ traceId: context.traceId,
26
+ spanId: context.spanId,
27
+ parentSpanId: context.parentSpanId,
28
+ type,
29
+ timestamp: options.timestamp ?? Date.now(),
30
+ status: options.status,
31
+ refs: options.refs,
32
+ reason: options.reason,
33
+ };
34
+ writeAuditRecord(record);
35
+ }
36
+ export function recordCausationLink(record) {
37
+ writeAuditRecord({
38
+ version: 1,
39
+ ...record,
40
+ timestamp: record.timestamp ?? Date.now(),
41
+ });
42
+ }
43
+ export function queryCausationTrace(traceId) {
44
+ const records = readAuditRecords();
45
+ const spans = records
46
+ .filter(isSpanRecord)
47
+ .filter(record => record.traceId === traceId)
48
+ .sort((left, right) => left.timestamp - right.timestamp);
49
+ const spanIds = new Set(spans.map(record => record.spanId));
50
+ const links = records
51
+ .filter(isLinkRecord)
52
+ .filter(record => spanIds.has(record.spanId) || record.linkedTraceId === traceId)
53
+ .sort((left, right) => left.timestamp - right.timestamp);
54
+ return { traceId, spans, links };
55
+ }
56
+ function readAuditRecords() {
57
+ const logDir = resolvePaths().logs;
58
+ let files;
59
+ try {
60
+ files = fs.readdirSync(logDir)
61
+ .filter(file => file === 'causation-spans.log' || /^causation-spans-\d{8}\.log$/.test(file))
62
+ .map(file => path.join(logDir, file));
63
+ }
64
+ catch {
65
+ return [];
66
+ }
67
+ const records = [];
68
+ for (const file of files) {
69
+ let lines;
70
+ try {
71
+ lines = fs.readFileSync(file, 'utf8').split('\n');
72
+ }
73
+ catch {
74
+ continue;
75
+ }
76
+ for (const line of lines) {
77
+ if (!line)
78
+ continue;
79
+ try {
80
+ const parsed = JSON.parse(line);
81
+ if (isSpanRecord(parsed) || isLinkRecord(parsed))
82
+ records.push(parsed);
83
+ }
84
+ catch {
85
+ }
86
+ }
87
+ }
88
+ return records;
89
+ }
90
+ function isSpanRecord(value) {
91
+ return typeof value.traceId === 'string'
92
+ && typeof value.spanId === 'string'
93
+ && typeof value.type === 'string';
94
+ }
95
+ function isLinkRecord(value) {
96
+ return value.relation === 'batch_input'
97
+ && typeof value.linkedTraceId === 'string'
98
+ && typeof value.linkedSpanId === 'string';
99
+ }
100
+ export function resetCausationAuditForTests() {
101
+ writer?.close();
102
+ writer = undefined;
103
+ }
@@ -0,0 +1,111 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { resolvePaths } from '../../paths.js';
4
+ import { atomicReadJson, atomicWriteJson } from '../../utils/atomic-write.js';
5
+ import { cloneCausation, normalizeCausation } from './context.js';
6
+ const DEFAULT_TTL_MS = 30 * 60 * 1000;
7
+ const associations = new Map();
8
+ let loaded = false;
9
+ function associationFile() {
10
+ return path.join(resolvePaths().dataDir, 'causation-aun.json');
11
+ }
12
+ function ensureLoaded() {
13
+ if (loaded)
14
+ return;
15
+ loaded = true;
16
+ let raw;
17
+ try {
18
+ raw = atomicReadJson(associationFile());
19
+ }
20
+ catch {
21
+ return;
22
+ }
23
+ if (!Array.isArray(raw))
24
+ return;
25
+ for (const item of raw) {
26
+ if (!item || typeof item !== 'object' || Array.isArray(item))
27
+ continue;
28
+ const record = item;
29
+ const causation = normalizeCausation(record.causation);
30
+ if (typeof record.messageId !== 'string'
31
+ || typeof record.fromAid !== 'string'
32
+ || typeof record.toAid !== 'string'
33
+ || typeof record.expiresAt !== 'number'
34
+ || record.expiresAt <= Date.now()
35
+ || !causation)
36
+ continue;
37
+ associations.set(record.messageId, {
38
+ fromAid: record.fromAid,
39
+ toAid: record.toAid,
40
+ causation,
41
+ expiresAt: record.expiresAt,
42
+ });
43
+ }
44
+ }
45
+ function persist() {
46
+ try {
47
+ if (associations.size === 0) {
48
+ removeAssociationFiles();
49
+ return;
50
+ }
51
+ atomicWriteJson(associationFile(), [...associations].map(([messageId, association]) => ({
52
+ messageId,
53
+ ...association,
54
+ })));
55
+ }
56
+ catch {
57
+ }
58
+ }
59
+ export function registerAunCausation(associationId, fromAid, toAid, causation, ttlMs = DEFAULT_TTL_MS) {
60
+ ensureLoaded();
61
+ cleanupExpiredAunCausation();
62
+ const normalized = normalizeCausation(causation);
63
+ if (!associationId || !fromAid || !toAid || !normalized)
64
+ return false;
65
+ associations.set(associationId, {
66
+ fromAid,
67
+ toAid,
68
+ causation: cloneCausation(normalized),
69
+ expiresAt: Date.now() + Math.max(1, ttlMs),
70
+ });
71
+ persist();
72
+ return true;
73
+ }
74
+ export function consumeAunCausation(associationId, fromAid, toAid) {
75
+ ensureLoaded();
76
+ cleanupExpiredAunCausation();
77
+ const association = associations.get(associationId);
78
+ if (!association)
79
+ return undefined;
80
+ if (association.fromAid !== fromAid || association.toAid !== toAid)
81
+ return undefined;
82
+ associations.delete(associationId);
83
+ persist();
84
+ return cloneCausation(association.causation);
85
+ }
86
+ export function cleanupExpiredAunCausation(now = Date.now()) {
87
+ ensureLoaded();
88
+ let changed = false;
89
+ for (const [messageId, association] of associations) {
90
+ if (association.expiresAt <= now) {
91
+ associations.delete(messageId);
92
+ changed = true;
93
+ }
94
+ }
95
+ if (changed)
96
+ persist();
97
+ }
98
+ export function clearAunCausationForTests() {
99
+ associations.clear();
100
+ loaded = true;
101
+ try {
102
+ removeAssociationFiles();
103
+ }
104
+ catch { }
105
+ }
106
+ function removeAssociationFiles() {
107
+ const file = associationFile();
108
+ fs.rmSync(file, { force: true });
109
+ fs.rmSync(`${file}_`, { force: true });
110
+ fs.rmSync(`${file}__`, { force: true });
111
+ }
@@ -0,0 +1,93 @@
1
+ import crypto from 'crypto';
2
+ import { CAUSATION_VERSION, MAX_TRIGGER_CAUSATION_DEPTH, } from './types.js';
3
+ const ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;
4
+ function newId(prefix) {
5
+ return `${prefix}_${crypto.randomUUID().replace(/-/g, '')}`;
6
+ }
7
+ function validId(value) {
8
+ return typeof value === 'string' && ID_PATTERN.test(value);
9
+ }
10
+ export function cloneCausation(context) {
11
+ return {
12
+ version: CAUSATION_VERSION,
13
+ traceId: context.traceId,
14
+ spanId: context.spanId,
15
+ ...(context.parentSpanId ? { parentSpanId: context.parentSpanId } : {}),
16
+ ...(context.trigger ? { trigger: { path: context.trigger.path.map(node => ({ ...node })) } } : {}),
17
+ };
18
+ }
19
+ export function normalizeCausation(value) {
20
+ if (!value || typeof value !== 'object' || Array.isArray(value))
21
+ return undefined;
22
+ const raw = value;
23
+ if (raw.version !== CAUSATION_VERSION || !validId(raw.traceId) || !validId(raw.spanId))
24
+ return undefined;
25
+ if (raw.parentSpanId !== undefined && !validId(raw.parentSpanId))
26
+ return undefined;
27
+ let trigger;
28
+ if (raw.trigger !== undefined) {
29
+ if (!raw.trigger || typeof raw.trigger !== 'object' || Array.isArray(raw.trigger))
30
+ return undefined;
31
+ const path = raw.trigger.path;
32
+ if (!Array.isArray(path) || path.length === 0 || path.length > MAX_TRIGGER_CAUSATION_DEPTH)
33
+ return undefined;
34
+ const normalizedPath = [];
35
+ for (const node of path) {
36
+ if (!node || typeof node !== 'object' || Array.isArray(node))
37
+ return undefined;
38
+ const record = node;
39
+ if (!validId(record.triggerId) || !validId(record.runId))
40
+ return undefined;
41
+ normalizedPath.push({ triggerId: record.triggerId, runId: record.runId });
42
+ }
43
+ trigger = { path: normalizedPath };
44
+ }
45
+ return {
46
+ version: CAUSATION_VERSION,
47
+ traceId: raw.traceId,
48
+ spanId: raw.spanId,
49
+ ...(raw.parentSpanId ? { parentSpanId: raw.parentSpanId } : {}),
50
+ ...(trigger ? { trigger } : {}),
51
+ };
52
+ }
53
+ export function createRootCausation() {
54
+ return {
55
+ version: CAUSATION_VERSION,
56
+ traceId: newId('trace'),
57
+ spanId: newId('span'),
58
+ };
59
+ }
60
+ export function deriveCausation(parent) {
61
+ const normalized = normalizeCausation(parent);
62
+ if (!normalized)
63
+ return createRootCausation();
64
+ return {
65
+ version: CAUSATION_VERSION,
66
+ traceId: normalized.traceId,
67
+ spanId: newId('span'),
68
+ parentSpanId: normalized.spanId,
69
+ ...(normalized.trigger ? { trigger: { path: normalized.trigger.path.map(node => ({ ...node })) } } : {}),
70
+ };
71
+ }
72
+ export function enterTrigger(parent, triggerId, runId) {
73
+ const normalized = normalizeCausation(parent);
74
+ const existingPath = normalized?.trigger?.path ?? [];
75
+ const matched = existingPath.find(node => node.triggerId === triggerId);
76
+ if (matched)
77
+ return { ok: false, reason: 'causation_cycle', matched };
78
+ if (existingPath.length >= MAX_TRIGGER_CAUSATION_DEPTH) {
79
+ return { ok: false, reason: 'causation_depth_exceeded' };
80
+ }
81
+ const causation = normalized ? deriveCausation(normalized) : createRootCausation();
82
+ causation.trigger = {
83
+ path: [...existingPath.map(node => ({ ...node })), { triggerId, runId }],
84
+ };
85
+ return { ok: true, causation };
86
+ }
87
+ export function formatTriggerPath(context, nextTriggerId) {
88
+ const path = normalizeCausation(context)?.trigger?.path ?? [];
89
+ const formatted = path.map(node => `${node.triggerId}/${node.runId}`);
90
+ if (nextTriggerId)
91
+ formatted.push(nextTriggerId);
92
+ return formatted.join(' -> ');
93
+ }
@@ -0,0 +1,4 @@
1
+ export * from './types.js';
2
+ export * from './context.js';
3
+ export * from './audit.js';
4
+ export * from './aun-association.js';
@@ -0,0 +1,2 @@
1
+ export const CAUSATION_VERSION = 1;
2
+ export const MAX_TRIGGER_CAUSATION_DEPTH = 16;