evolcore 0.0.25 → 0.0.27

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 (304) hide show
  1. package/CHANGELOG.md +632 -565
  2. package/LICENSE +21 -21
  3. package/README.md +455 -455
  4. package/bin/codex-managed-acl.ps1 +203 -160
  5. package/bin/codex-managed-hook.mjs +208 -208
  6. package/bin/ec-safe-output.js +327 -327
  7. package/bin/ec.js +40 -29
  8. package/bin/install-codex-managed-hooks.mjs +582 -555
  9. package/dist/agents/baseagent-availability.js +68 -0
  10. package/dist/agents/baseagent.js +96 -46
  11. package/dist/agents/claude-runner.js +172 -33
  12. package/dist/agents/codex/app-server-client.js +76 -31
  13. package/dist/agents/codex/catalog.js +1 -1
  14. package/dist/agents/codex/diagnostics.js +34 -1
  15. package/dist/agents/codex-runner.js +434 -446
  16. package/dist/agents/ecagent-runner.js +174 -34
  17. package/dist/agents/gemini-runner.js +8 -7
  18. package/dist/agents/runner-types.js +75 -19
  19. package/dist/aun/aid/agentmd.js +151 -36
  20. package/dist/aun/aid/client.js +1 -1
  21. package/dist/aun/aid/control-aid.js +180 -1
  22. package/dist/aun/aid/identity.js +4 -4
  23. package/dist/aun/aid/index.js +1 -1
  24. package/dist/aun/aid/store.js +17 -13
  25. package/dist/aun/group/history.js +303 -0
  26. package/dist/aun/group/identity.js +43 -0
  27. package/dist/aun/group/index.js +5 -0
  28. package/dist/aun/{msg/group.js → group/operations.js} +162 -39
  29. package/dist/aun/{menu-client.js → menu/client.js} +85 -6
  30. package/dist/aun/menu/index.js +2 -0
  31. package/dist/aun/menu/transport.js +49 -0
  32. package/dist/aun/msg/index.js +2 -1
  33. package/dist/aun/msg/managed-operation.js +85 -19
  34. package/dist/aun/msg/mention-schema.js +51 -0
  35. package/dist/aun/msg/p2p.js +19 -9
  36. package/dist/aun/msg/upload.js +43 -80
  37. package/dist/aun/outbox.js +29 -7
  38. package/dist/aun/rpc/client.js +1 -0
  39. package/dist/aun/storage/client.js +39 -50
  40. package/dist/channels/aun.js +842 -318
  41. package/dist/channels/daemon.js +10 -6
  42. package/dist/cli/agent-command.js +212 -89
  43. package/dist/cli/agent-create.js +626 -11
  44. package/dist/cli/agent.js +125 -13
  45. package/dist/cli/aun-commands.js +487 -337
  46. package/dist/cli/bench.js +20 -20
  47. package/dist/cli/config.js +55 -33
  48. package/dist/cli/contact.js +72 -15
  49. package/dist/cli/ctl-command.js +24 -24
  50. package/dist/cli/daemon-commands.js +140 -63
  51. package/dist/cli/diag.js +31 -0
  52. package/dist/cli/fs-command.js +70 -70
  53. package/dist/cli/handoff-command.js +46 -14
  54. package/dist/cli/index.js +91 -79
  55. package/dist/cli/init.js +34 -1
  56. package/dist/cli/link-rules.js +21 -21
  57. package/dist/cli/managed-command-guard.js +5 -1
  58. package/dist/cli/menu-client.js +51 -32
  59. package/dist/cli/model.js +3 -3
  60. package/dist/cli/net-check.js +22 -22
  61. package/dist/cli/queue-command.js +31 -31
  62. package/dist/cli/response.js +32 -32
  63. package/dist/cli/restart-monitor.js +103 -42
  64. package/dist/cli/stats.js +51 -51
  65. package/dist/cli/task-command.js +59 -0
  66. package/dist/cli/task-context.js +97 -49
  67. package/dist/cli/trigger-command.js +74 -64
  68. package/dist/config/builtin-roles.js +11 -0
  69. package/dist/config/config-field-policy.js +11 -0
  70. package/dist/config/config-manager.js +32 -4
  71. package/dist/config/config-operation-service.js +160 -0
  72. package/dist/config/contact-book-store.js +1 -1
  73. package/dist/config/contact-book.js +1 -1
  74. package/dist/config/contact-operation-service.js +97 -8
  75. package/dist/config/peer-role-resolver.js +1 -1
  76. package/dist/config/resolved-config-op.js +30 -7
  77. package/dist/config-store.js +1 -1
  78. package/dist/core/agent-application-service.js +7 -1
  79. package/dist/core/audit/event-key.js +17 -2
  80. package/dist/core/audit/log-integrity.js +34 -8
  81. package/dist/core/auth/agent-delegation.js +48 -14
  82. package/dist/core/auth/auth-gateway.js +2 -0
  83. package/dist/core/auth/authorization-audit.js +53 -49
  84. package/dist/core/auth/operation-authorizer.js +90 -7
  85. package/dist/core/auth/operation-catalog.js +145 -4
  86. package/dist/core/auth/remote-access-store.js +155 -10
  87. package/dist/core/bootstrap-messages.js +66 -7
  88. package/dist/core/bootstrap-service.js +111 -20
  89. package/dist/core/command/agent-control.js +88 -7
  90. package/dist/core/command/agent-storage-menu.js +443 -0
  91. package/dist/core/command/cli-intent-parser.js +19 -0
  92. package/dist/core/command/command-handler.js +159 -65
  93. package/dist/core/command/data-root-resolver.js +273 -0
  94. package/dist/core/command/diag-service.js +118 -0
  95. package/dist/core/command/group-menu.js +7 -2
  96. package/dist/core/command/menu-catalog.js +46 -7
  97. package/dist/core/command/menu-handler.js +392 -100
  98. package/dist/core/command/menu-protocol.js +45 -6
  99. package/dist/core/command/menu-token-store.js +41 -8
  100. package/dist/core/command/role-menu.js +2 -2
  101. package/dist/core/command/slash-gate.js +34 -4
  102. package/dist/core/command/slash-handler.js +123 -43
  103. package/dist/core/event-catalog.js +4 -0
  104. package/dist/core/evolagent-registry.js +28 -2
  105. package/dist/core/group/invite-service.js +924 -0
  106. package/dist/core/handoff/runtime.js +205 -27
  107. package/dist/core/handoff/store.js +193 -4
  108. package/dist/core/interaction-router.js +22 -8
  109. package/dist/core/message/im-renderer.js +146 -34
  110. package/dist/core/message/message-bridge.js +163 -20
  111. package/dist/core/message/message-log.js +5 -3
  112. package/dist/core/message/message-queue.js +99 -41
  113. package/dist/core/message/message-utils.js +1 -0
  114. package/dist/core/message/response-engine.js +755 -144
  115. package/dist/core/model/catalog-service.js +79 -49
  116. package/dist/core/model/context-window-suffix.js +33 -0
  117. package/dist/core/model/model-catalog.js +1 -1
  118. package/dist/core/model/model-permission.js +12 -3
  119. package/dist/core/permission/approval-gateway.js +36 -3
  120. package/dist/core/permission/ec-command-parser.js +112 -41
  121. package/dist/core/permission/protected-paths.js +134 -16
  122. package/dist/core/permission/sandbox-runtime.js +108 -17
  123. package/dist/core/permission/tool-error-code.js +15 -0
  124. package/dist/core/permission/tool-policy.js +9 -8
  125. package/dist/core/relation/peer-identity.js +57 -6
  126. package/dist/core/relation/shared-data.js +106 -0
  127. package/dist/core/role/runtime-policy.js +64 -0
  128. package/dist/core/runtime-lock.js +10 -26
  129. package/dist/core/session/runner-task-history.js +170 -0
  130. package/dist/core/session/session-manager.js +34 -6
  131. package/dist/core/session/session-mapper.js +41 -0
  132. package/dist/core/session/session-turn-coordinator.js +37 -7
  133. package/dist/core/session/session-turns.js +48 -7
  134. package/dist/core/task/task-recovery-service.js +176 -0
  135. package/dist/core/task/task-resume-operation.js +32 -0
  136. package/dist/eck/group-rules-sync.js +5 -3
  137. package/dist/eck/kit-renderer.js +1 -0
  138. package/dist/index.js +588 -217
  139. package/dist/ipc.js +193 -15
  140. package/dist/paths.js +17 -4
  141. package/dist/product.js +2 -0
  142. package/dist/response-system/engines/v1/proactive-flow.js +59 -2
  143. package/dist/stats/billing.js +41 -15
  144. package/dist/stats/db.js +159 -159
  145. package/dist/stats/eck-vars.js +9 -9
  146. package/dist/stats/price-resolver.js +28 -10
  147. package/dist/stats/query.js +139 -139
  148. package/dist/stats/role-budget.js +6 -6
  149. package/dist/stats/writer.js +51 -51
  150. package/dist/trigger/event-source.js +19 -0
  151. package/dist/trigger/feedback.js +233 -40
  152. package/dist/trigger/parser.js +55 -5
  153. package/dist/trigger/patch.js +9 -0
  154. package/dist/trigger/scheduler.js +30 -4
  155. package/dist/trigger/validation.js +20 -3
  156. package/dist/utils/cross-platform.js +30 -1
  157. package/dist/utils/ecweb-utils.js +1 -0
  158. package/dist/utils/error-dict.json +160 -160
  159. package/dist/utils/error-utils.js +61 -2
  160. package/dist/utils/evolcore-version.js +129 -0
  161. package/dist/utils/logger.js +26 -14
  162. package/dist/utils/macos-autostart.js +22 -22
  163. package/dist/utils/model-prices.jsonl +23 -23
  164. package/dist/utils/npm-ops.js +176 -35
  165. package/dist/utils/tool-summary.js +59 -3
  166. package/dist/utils/welcome.js +196 -23
  167. package/ecagent/LICENSE +21 -21
  168. package/ecagent/NOTICE +11 -11
  169. package/ecagent/README.md +61 -61
  170. package/ecagent/dist/harness/agent-harness.js +3 -0
  171. package/ecagent/dist/harness/compaction/branch-summarization.js +30 -30
  172. package/ecagent/dist/harness/compaction/compaction.js +83 -83
  173. package/ecagent/dist/harness/messages.js +7 -7
  174. package/ecagent/dist/harness/session/jsonl-storage.js +21 -2
  175. package/kits/docs/GUIDE.md +20 -20
  176. package/kits/docs/INDEX.md +60 -66
  177. package/kits/docs/aun/CHEATSHEET.md +19 -19
  178. package/kits/docs/aun/SYNC_PROTOCOL.md +15 -15
  179. package/kits/docs/channels/aun.md +69 -56
  180. package/kits/docs/channels/feishu.md +56 -56
  181. package/kits/docs/context-assembly.md +379 -367
  182. package/kits/docs/eck_templates/GUIDE.template.md +22 -22
  183. package/kits/docs/eck_templates/INDEX.template.md +28 -28
  184. package/kits/docs/eck_templates/path-registry.template.md +33 -33
  185. package/kits/docs/eck_templates/runtime.template.md +19 -19
  186. package/kits/docs/evolcore/INDEX.md +76 -71
  187. package/kits/docs/evolcore/agent-create.md +202 -165
  188. package/kits/docs/evolcore/agent.md +99 -67
  189. package/kits/docs/evolcore/aid.md +68 -60
  190. package/kits/docs/evolcore/codex-windows-sandbox.md +146 -146
  191. package/kits/docs/evolcore/config.md +241 -195
  192. package/kits/docs/evolcore/contact.md +75 -68
  193. package/kits/docs/evolcore/ctl.md +46 -46
  194. package/kits/docs/evolcore/event.md +216 -216
  195. package/kits/docs/evolcore/fs-architecture.md +1215 -1215
  196. package/kits/docs/evolcore/fs.md +110 -110
  197. package/kits/docs/evolcore/group-collaboration.md +244 -244
  198. package/kits/docs/evolcore/group-fs.md +17 -17
  199. package/kits/docs/evolcore/group-rules.md +251 -251
  200. package/kits/docs/evolcore/group.md +267 -152
  201. package/kits/docs/evolcore/menu-client.md +58 -34
  202. package/kits/docs/evolcore/model.md +50 -50
  203. package/kits/docs/evolcore/msg.md +169 -165
  204. package/kits/docs/evolcore/response.md +75 -75
  205. package/kits/docs/evolcore/rpc.md +37 -37
  206. package/kits/docs/evolcore/self-summary.md +29 -29
  207. package/kits/docs/evolcore/stats.md +83 -83
  208. package/kits/docs/evolcore/storage.md +53 -50
  209. package/kits/docs/evolcore/task.md +14 -0
  210. package/kits/docs/evolcore/trigger.md +623 -575
  211. package/kits/docs/identity/AID_PROFILE_SPEC.md +26 -26
  212. package/kits/docs/identity/PATH_OPS.md +16 -16
  213. package/kits/docs/identity/ROLE_DETAIL.md +25 -25
  214. package/kits/docs/identity/identity-tools.md +26 -26
  215. package/kits/docs/path-registry.md +62 -62
  216. package/kits/docs/prompt-loading-architecture.md +269 -269
  217. package/kits/docs/venues/aun-group.md +45 -45
  218. package/kits/docs/venues/aun-private.md +10 -10
  219. package/kits/docs/venues/client-desktop.md +10 -10
  220. package/kits/docs/venues/client-mobile.md +10 -10
  221. package/kits/docs/venues/feishu-group.md +13 -13
  222. package/kits/docs/venues/feishu-private.md +9 -9
  223. package/kits/docs/venues/group.md +42 -25
  224. package/kits/docs/venues/private.md +10 -10
  225. package/kits/eck_manifest.auxiliary.json +43 -43
  226. package/kits/eck_manifest.json +217 -190
  227. package/kits/eck_message_manifest.json +74 -74
  228. package/kits/migrations/README-role-config-v4.md +32 -32
  229. package/kits/migrations/migrate-contact-book-v2.mjs +748 -748
  230. package/kits/migrations/migrate-role-config-v4.mjs +614 -614
  231. package/kits/migrations/migrate-role-config-v5.mjs +365 -365
  232. package/kits/migrations/rename-config-file.mjs +99 -99
  233. package/kits/rules/01-overview.md +166 -162
  234. package/kits/rules/02-navigation.md +96 -96
  235. package/kits/rules/03-identity.md +36 -36
  236. package/kits/rules/04-relation.md +76 -75
  237. package/kits/rules/05-venue.md +60 -60
  238. package/kits/rules/06-channel.md +65 -63
  239. package/kits/schemas/_meta.json +53 -53
  240. package/kits/schemas/agent-config.schema.1.json +177 -177
  241. package/kits/schemas/agent-config.schema.10.json +395 -395
  242. package/kits/schemas/agent-config.schema.11.json +421 -421
  243. package/kits/schemas/agent-config.schema.12.json +451 -427
  244. package/kits/schemas/agent-config.schema.2.json +239 -239
  245. package/kits/schemas/agent-config.schema.3.json +119 -119
  246. package/kits/schemas/agent-config.schema.4.json +208 -208
  247. package/kits/schemas/agent-config.schema.5.json +326 -326
  248. package/kits/schemas/agent-config.schema.6.json +322 -322
  249. package/kits/schemas/agent-config.schema.7.json +303 -303
  250. package/kits/schemas/agent-config.schema.8.json +304 -304
  251. package/kits/schemas/agent-config.schema.9.json +364 -364
  252. package/kits/schemas/contact-book.schema.1.json +36 -36
  253. package/kits/schemas/contact-book.schema.2.json +43 -43
  254. package/kits/schemas/contact-book.schema.3.json +67 -67
  255. package/kits/schemas/daemon.schema.1.json +91 -91
  256. package/kits/schemas/daemon.schema.2.json +101 -101
  257. package/kits/schemas/daemon.schema.3.json +123 -123
  258. package/kits/schemas/daemon.schema.4.json +136 -136
  259. package/kits/schemas/daemon.schema.5.json +135 -135
  260. package/kits/schemas/daemon.schema.6.json +131 -131
  261. package/kits/schemas/defaults.schema.1.json +81 -81
  262. package/kits/schemas/defaults.schema.2.json +85 -85
  263. package/kits/schemas/defaults.schema.3.json +73 -73
  264. package/kits/schemas/defaults.schema.4.json +107 -107
  265. package/kits/schemas/defaults.schema.5.json +119 -119
  266. package/kits/schemas/menu-exec-schema-commands.md +208 -208
  267. package/kits/schemas/migrations/README.md +30 -30
  268. package/kits/schemas/relation-config.schema.1.json +158 -158
  269. package/kits/schemas/relation-config.schema.2.json +73 -73
  270. package/kits/schemas/relation-config.schema.3.json +50 -50
  271. package/kits/schemas/relation-config.schema.4.json +47 -47
  272. package/kits/schemas/relation-config.schema.5.json +47 -47
  273. package/kits/schemas/relation-config.schema.6.json +46 -46
  274. package/kits/schemas/relation-config.schema.7.json +59 -59
  275. package/kits/schemas/relation-config.schema.8.json +103 -103
  276. package/kits/schemas/role-config.schema.1.json +215 -201
  277. package/kits/schemas/role-registry.schema.1.json +35 -35
  278. package/kits/schemas/single-session.schema.1.json +31 -31
  279. package/kits/schemas/single-session.schema.2.json +57 -57
  280. package/kits/schemas/single-session.schema.3.json +32 -32
  281. package/kits/templates/bootstrap-welcome.md +17 -17
  282. package/kits/templates/message-fragments/handoff-context-to-target.md +9 -9
  283. package/kits/templates/message-fragments/handoff-request-to-target.md +19 -19
  284. package/kits/templates/message-fragments/handoff-response-to-origin.md +9 -9
  285. package/kits/templates/message-fragments/inject-default.md +2 -2
  286. package/kits/templates/message-fragments/item.md +2 -2
  287. package/kits/templates/roles/admin.json +92 -92
  288. package/kits/templates/roles/member.json +101 -96
  289. package/kits/templates/roles/owner.json +9 -9
  290. package/kits/templates/roles/visitor.json +90 -85
  291. package/kits/templates/system-fragments/baseagent.md +14 -14
  292. package/kits/templates/system-fragments/bootstrap.md +53 -34
  293. package/kits/templates/system-fragments/channel.md +28 -64
  294. package/kits/templates/system-fragments/commands.md +36 -28
  295. package/kits/templates/system-fragments/group-unread-history.md +7 -0
  296. package/kits/templates/system-fragments/identity.md +13 -13
  297. package/kits/templates/system-fragments/relation.md +19 -19
  298. package/kits/templates/system-fragments/reply.md +56 -0
  299. package/kits/templates/system-fragments/session.md +59 -59
  300. package/kits/templates/system-fragments/venue.md +31 -31
  301. package/package.json +104 -98
  302. package/dist/aun/group-identity.js +0 -9
  303. /package/dist/aun/{group-fs-download.js → group/fs-download.js} +0 -0
  304. /package/dist/aun/{msg/group-index.js → group/index-rpc.js} +0 -0
@@ -4,10 +4,47 @@ import { parseDocument } from 'yaml';
4
4
  import { getAidStore, loadAid, SLOT } from './store.js';
5
5
  import { agentMdPath, aidLocalDir, resolveRoot } from '../../paths.js';
6
6
  export const DEFAULT_AGENT_DESCRIPTION = 'EvolCore AI agent.';
7
+ /**
8
+ * AUN 主体类型白名单。没有 `ai` / `codeagent` 这类取值:使用大模型且没有
9
+ * 专用主体类型的服务程序默认归为 `agent`。新建 AID 未指定类型时使用 DEFAULT_AGENT_TYPE。
10
+ */
11
+ export const AGENT_TYPES = ['human', 'agent', 'group', 'service', 'device', 'org', 'host'];
12
+ export const DEFAULT_AGENT_TYPE = 'agent';
13
+ /**
14
+ * 归一化主体类型:大小写不敏感,统一收敛为白名单里的小写形式。
15
+ * `--type AGENT` / `Agent` 都接受,最终写进 agent.md 的一律是小写 `agent`。
16
+ * 返回 undefined 表示输入不是可识别的类型(交由 validateAgentType 报错)。
17
+ */
18
+ export function normalizeAgentType(type) {
19
+ if (typeof type !== 'string')
20
+ return undefined;
21
+ const lowered = type.trim().toLowerCase();
22
+ return AGENT_TYPES.includes(lowered) ? lowered : undefined;
23
+ }
24
+ /** Return a human-readable validation error for a type value, or null when valid. */
25
+ export function validateAgentType(type) {
26
+ if (typeof type !== 'string' || !type.trim())
27
+ return 'must be a non-empty string';
28
+ if (!normalizeAgentType(type))
29
+ return `must be one of ${AGENT_TYPES.join(', ')}`;
30
+ return null;
31
+ }
32
+ /**
33
+ * agent.md 的尺寸与字段上限,取值必须与 fastaun 的 agent-md-schema 保持一致,
34
+ * 否则本地校验通过、上传时才被 SDK 拒绝(失败点后移且提示不同)。
35
+ * 参考 @agentunion/fastaun dist/agent-md-schema.js。
36
+ */
37
+ export const AGENT_MD_MAX_PAYLOAD_BYTES = 4096;
38
+ export const AGENT_DESCRIPTION_MAX_LENGTH = 100;
39
+ export const AGENT_AVATAR_MAX_LENGTH = 256;
40
+ /** 按 Unicode 码点计数——与 SDK 的 Array.from(value).length 对齐(代理对算一个字符)。 */
41
+ function codePointLength(value) {
42
+ return Array.from(value).length;
43
+ }
7
44
  export const AGENT_TAG_MIN_COUNT = 3;
8
45
  export const AGENT_TAG_MAX_COUNT = 6;
9
46
  export const AGENT_TAG_MAX_LENGTH = 50;
10
- const AGENT_TAG_PATTERN = /^[\p{L}\p{N}]+$/u;
47
+ const AGENT_TAG_PATTERN = /^[\p{L}\p{N}-]+$/u;
11
48
  /** Return a human-readable validation error for one tag, or null when valid. */
12
49
  export function validateAgentTag(tag) {
13
50
  if (typeof tag !== 'string' || !tag.trim())
@@ -17,7 +54,7 @@ export function validateAgentTag(tag) {
17
54
  return `must be at most ${AGENT_TAG_MAX_LENGTH} characters`;
18
55
  }
19
56
  if (!AGENT_TAG_PATTERN.test(normalized)) {
20
- return 'must contain only Unicode letters and numbers';
57
+ return 'must contain only Unicode letters, numbers, and hyphens';
21
58
  }
22
59
  return null;
23
60
  }
@@ -49,6 +86,12 @@ export function validateAgentTags(tags, options = {}) {
49
86
  }
50
87
  return errors;
51
88
  }
89
+ function resolveAgentMdAunPath(opts) {
90
+ return opts?.aunPath ?? opts?.store?.aunPath ?? resolveRoot();
91
+ }
92
+ // A process can host agents that deliberately use different AUN keystore
93
+ // roots. Keep their display-name state separate so one root cannot shadow the
94
+ // other with a same-named AID.
52
95
  const displayNameCache = new Map();
53
96
  const displayNamePending = new Map();
54
97
  const displayNameRevision = new Map();
@@ -64,9 +107,13 @@ export function parseAgentDisplayName(content) {
64
107
  const name = frontmatter.match(/^name:\s*["']?(.+?)["']?\s*$/m)?.[1]?.trim();
65
108
  return name || undefined;
66
109
  }
67
- function readLocalAgentDisplayName(aid) {
110
+ function displayNameKey(aid, aunPath) {
111
+ const root = path.resolve(aunPath ?? resolveRoot());
112
+ return `${root}\u0000${aid.toLowerCase()}`;
113
+ }
114
+ function readLocalAgentDisplayName(aid, aunPath) {
68
115
  try {
69
- return parseAgentDisplayName(fs.readFileSync(agentMdPath(aid), 'utf-8'));
116
+ return parseAgentDisplayName(fs.readFileSync(agentMdPath(aid, aunPath), 'utf-8'));
70
117
  }
71
118
  catch {
72
119
  return undefined;
@@ -77,60 +124,87 @@ function readLocalAgentDisplayName(aid) {
77
124
  * Local content is returned immediately; a missing value starts one shared
78
125
  * background refresh and remains undefined until a later lookup.
79
126
  */
80
- export function resolveAgentDisplayName(aid) {
127
+ export function resolveAgentDisplayName(aid, opts) {
81
128
  const normalizedAid = normalizeAid(aid);
82
129
  if (!normalizedAid)
83
130
  return undefined;
84
- const cached = displayNameCache.get(normalizedAid);
131
+ const aunPath = resolveAgentMdAunPath(opts);
132
+ const key = displayNameKey(normalizedAid, aunPath);
133
+ const cached = displayNameCache.get(key);
85
134
  if (cached)
86
135
  return cached;
87
- const localName = readLocalAgentDisplayName(normalizedAid);
136
+ const localName = readLocalAgentDisplayName(normalizedAid, aunPath);
88
137
  if (localName) {
89
- displayNameCache.set(normalizedAid, localName);
138
+ displayNameCache.set(key, localName);
90
139
  return localName;
91
140
  }
92
- void refreshAgentDisplayName(normalizedAid);
141
+ void refreshAgentDisplayName(normalizedAid, opts);
93
142
  return undefined;
94
143
  }
95
144
  /** Fetch agent.md once and update the shared display-name cache. */
96
- export function refreshAgentDisplayName(aid) {
145
+ export function refreshAgentDisplayName(aid, opts) {
97
146
  const normalizedAid = normalizeAid(aid);
98
147
  if (!normalizedAid)
99
148
  return Promise.resolve(undefined);
100
- const existing = displayNamePending.get(normalizedAid);
149
+ const aunPath = resolveAgentMdAunPath(opts);
150
+ const key = displayNameKey(normalizedAid, aunPath);
151
+ const existing = displayNamePending.get(key);
101
152
  if (existing)
102
153
  return existing;
103
- const revision = displayNameRevision.get(normalizedAid) ?? 0;
154
+ const revision = displayNameRevision.get(key) ?? 0;
104
155
  let pending;
105
- pending = agentmdGet(normalizedAid)
156
+ pending = agentmdGet(normalizedAid, { aunPath, store: opts?.store })
106
157
  .then(content => {
107
158
  const name = typeof content === 'string' ? parseAgentDisplayName(content) : undefined;
108
- if ((displayNameRevision.get(normalizedAid) ?? 0) !== revision)
159
+ if ((displayNameRevision.get(key) ?? 0) !== revision)
109
160
  return undefined;
110
161
  if (name)
111
- displayNameCache.set(normalizedAid, name);
162
+ displayNameCache.set(key, name);
112
163
  return name;
113
164
  })
114
165
  .catch(() => undefined)
115
166
  .finally(() => {
116
- if (displayNamePending.get(normalizedAid) === pending) {
117
- displayNamePending.delete(normalizedAid);
167
+ if (displayNamePending.get(key) === pending) {
168
+ displayNamePending.delete(key);
118
169
  }
119
170
  });
120
- displayNamePending.set(normalizedAid, pending);
171
+ displayNamePending.set(key, pending);
121
172
  return pending;
122
173
  }
123
- export function invalidateAgentDisplayName(aid) {
174
+ export function invalidateAgentDisplayName(aid, aunPath) {
124
175
  const normalizedAid = normalizeAid(aid);
125
176
  if (!normalizedAid)
126
177
  return;
127
- displayNameCache.delete(normalizedAid);
128
- displayNamePending.delete(normalizedAid);
129
- displayNameRevision.set(normalizedAid, (displayNameRevision.get(normalizedAid) ?? 0) + 1);
178
+ if (aunPath !== undefined) {
179
+ const key = displayNameKey(normalizedAid, aunPath);
180
+ displayNameCache.delete(key);
181
+ displayNamePending.delete(key);
182
+ displayNameRevision.set(key, (displayNameRevision.get(key) ?? 0) + 1);
183
+ return;
184
+ }
185
+ const suffix = `\u0000${normalizedAid.toLowerCase()}`;
186
+ const keys = new Set([
187
+ ...displayNameCache.keys(),
188
+ ...displayNamePending.keys(),
189
+ ...displayNameRevision.keys(),
190
+ ]);
191
+ for (const key of keys) {
192
+ if (!key.endsWith(suffix))
193
+ continue;
194
+ displayNameCache.delete(key);
195
+ displayNamePending.delete(key);
196
+ displayNameRevision.set(key, (displayNameRevision.get(key) ?? 0) + 1);
197
+ }
130
198
  }
131
199
  export function buildInitialAgentMd(opts) {
132
200
  const agentName = opts.name?.trim() || opts.aid.split('.')[0];
133
- const agentType = opts.type || 'ai';
201
+ // 未指定类型时用 DEFAULT_AGENT_TYPE(agent);指定了就必须落在 AGENT_TYPES 白名单内。
202
+ // 大小写不敏感,写进 agent.md 的一律是归一化后的小写形式。
203
+ const requestedType = opts.type?.trim() || DEFAULT_AGENT_TYPE;
204
+ const typeError = validateAgentType(requestedType);
205
+ if (typeError)
206
+ throw new Error(`Invalid agent.md type: ${typeError}`);
207
+ const agentType = normalizeAgentType(requestedType) ?? DEFAULT_AGENT_TYPE;
134
208
  const description = opts.description?.trim() || DEFAULT_AGENT_DESCRIPTION;
135
209
  const rawTags = opts.tags?.length ? opts.tags : ['evolcore'];
136
210
  const tagErrors = validateAgentTags(rawTags);
@@ -155,8 +229,9 @@ function yamlDoubleQuote(value) {
155
229
  export function validateAgentMdFrontmatter(content, expectedAid) {
156
230
  const errors = [];
157
231
  const payload = stripAgentMdSignature(content);
158
- if (Buffer.byteLength(payload, 'utf8') > 4 * 1024) {
159
- errors.push('agent.md must not exceed 4KB before the signature block');
232
+ const payloadBytes = Buffer.byteLength(payload, 'utf8');
233
+ if (payloadBytes > AGENT_MD_MAX_PAYLOAD_BYTES) {
234
+ errors.push(`agent.md frontmatter and body must not exceed ${AGENT_MD_MAX_PAYLOAD_BYTES} bytes before the signature block (current: ${payloadBytes} bytes)`);
160
235
  }
161
236
  const frontmatter = payload.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/)?.[1];
162
237
  if (!frontmatter)
@@ -185,15 +260,44 @@ export function validateAgentMdFrontmatter(content, expectedAid) {
185
260
  requiredString('name');
186
261
  requiredString('type');
187
262
  const version = requiredString('version');
188
- const description = requiredString('description');
263
+ // description 是可选字段(fastaun ≥0.5.13 起不再要求非空):缺失或空串都合法,
264
+ // 仅在实际提供时校验类型与长度,与 SDK 的 agent-md-schema 保持一致。
265
+ const rawDescription = values.description;
266
+ let description;
267
+ if (rawDescription !== undefined && rawDescription !== null) {
268
+ if (typeof rawDescription !== 'string') {
269
+ errors.push('agent.md frontmatter description must be a string');
270
+ }
271
+ else {
272
+ description = rawDescription.trim();
273
+ }
274
+ }
189
275
  if (expectedAid && aid && aid !== expectedAid) {
190
276
  errors.push(`agent.md frontmatter aid must match upload target ${expectedAid}`);
191
277
  }
192
278
  if (version && !/^\d+\.\d+\.\d+$/.test(version)) {
193
279
  errors.push('agent.md frontmatter version must use major.minor.patch format');
194
280
  }
195
- if (description && description.length > 100) {
196
- errors.push('agent.md frontmatter description must be at most 100 characters');
281
+ // 长度按 Unicode 码点计、且对未 trim 的原值计数——与 SDK 完全一致,
282
+ // 否则含 emoji 或尾随空格的名片会本地放行、上传才被拒。
283
+ if (typeof rawDescription === 'string') {
284
+ const length = codePointLength(rawDescription);
285
+ if (length > AGENT_DESCRIPTION_MAX_LENGTH) {
286
+ errors.push(`agent.md frontmatter description must be at most ${AGENT_DESCRIPTION_MAX_LENGTH} characters (current: ${length})`);
287
+ }
288
+ }
289
+ // avatar:SDK 有 256 字符上限,本地此前完全没校验。
290
+ const rawAvatar = values.avatar;
291
+ if (rawAvatar !== undefined && rawAvatar !== null) {
292
+ if (typeof rawAvatar !== 'string') {
293
+ errors.push('agent.md frontmatter avatar must be a string');
294
+ }
295
+ else {
296
+ const length = codePointLength(rawAvatar);
297
+ if (length > AGENT_AVATAR_MAX_LENGTH) {
298
+ errors.push(`agent.md frontmatter avatar must be at most ${AGENT_AVATAR_MAX_LENGTH} characters (current: ${length})`);
299
+ }
300
+ }
197
301
  }
198
302
  if (values.tags !== undefined) {
199
303
  const tagErrors = validateAgentTags(values.tags);
@@ -281,10 +385,10 @@ function verifyLocal(store, aid, content) {
281
385
  }
282
386
  }
283
387
  export async function agentmdGet(aid, opts) {
284
- const aunPath = opts?.aunPath ?? resolveRoot();
388
+ const aunPath = resolveAgentMdAunPath(opts);
285
389
  const store = opts?.store ?? await getAidStore({ slotId: SLOT.cli, aunPath });
286
390
  const ownStore = !opts?.store;
287
- const localPath = agentMdPath(aid);
391
+ const localPath = agentMdPath(aid, aunPath);
288
392
  try {
289
393
  let content;
290
394
  let verification;
@@ -294,6 +398,14 @@ export async function agentmdGet(aid, opts) {
294
398
  verification = normalizeVerification(r.data.verification);
295
399
  }
296
400
  else {
401
+ if (opts?.remoteOnly) {
402
+ const code = String(r.error?.code ?? '');
403
+ const message = String(r.error?.message ?? r.error);
404
+ if (code === 'AGENTMD_NOT_FOUND' || /not found|404|missing/i.test(message)) {
405
+ throw Object.assign(new Error(`agent.md not found for ${aid}`), { code: 'AGENTMD_NOT_FOUND' });
406
+ }
407
+ throw new Error(`Remote agent.md verification unavailable for ${aid}`);
408
+ }
297
409
  // Network/fetch failed — fall back to local file.
298
410
  if (!fs.existsSync(localPath)) {
299
411
  throw new Error(`fetch agent.md failed for ${aid}: ${r.error.message}`);
@@ -326,10 +438,10 @@ export async function agentmdPut(content, opts) {
326
438
  if (!validation.valid) {
327
439
  throw new Error(`invalid agent.md frontmatter: ${validation.errors.join('; ')}`);
328
440
  }
329
- const aunPath = opts.aunPath ?? resolveRoot();
441
+ const aunPath = resolveAgentMdAunPath(opts);
330
442
  const store = opts.store ?? await getAidStore({ slotId: SLOT.cli, aunPath });
331
443
  const ownStore = !opts.store;
332
- const dir = aidLocalDir(opts.aid);
444
+ const dir = aidLocalDir(opts.aid, aunPath);
333
445
  const filePath = path.join(dir, 'agent.md');
334
446
  const existed = fs.existsSync(filePath);
335
447
  // 先写本地文件(与旧行为一致:本地内容更新应在上传失败时仍保留)
@@ -370,10 +482,10 @@ export async function agentmdPut(content, opts) {
370
482
  * so a freshly-built store reports local_found=false and will fetch.
371
483
  */
372
484
  export async function agentmdSync(aid, opts) {
373
- const aunPath = opts?.aunPath ?? resolveRoot();
485
+ const aunPath = resolveAgentMdAunPath(opts);
374
486
  const store = opts?.store ?? await getAidStore({ slotId: SLOT.cli, aunPath });
375
487
  const ownStore = !opts?.store;
376
- const localPath = agentMdPath(aid);
488
+ const localPath = agentMdPath(aid, aunPath);
377
489
  try {
378
490
  // AIDStore owns the agent.md consistency API in fastaun 0.5.x. Keep this
379
491
  // runtime guard because callers and test doubles can still accidentally
@@ -382,9 +494,11 @@ export async function agentmdSync(aid, opts) {
382
494
  if (typeof candidate.checkAgentMd !== 'function' || typeof candidate.downloadAgentMd !== 'function') {
383
495
  throw new TypeError('invalid AIDStore: checkAgentMd/downloadAgentMd unavailable');
384
496
  }
385
- const check = await store.checkAgentMd(aid, 30);
497
+ // A change event can describe Last-Modified alone. Bypass the SDK's
498
+ // independent freshness cache when Core knows its snapshot is stale.
499
+ const check = opts?.forceRefresh ? undefined : await store.checkAgentMd(aid, opts?.ttlDays ?? 30);
386
500
  // In sync (cache fresh) — return local file content with cached verification status.
387
- if (check.ok && !check.data.needs_update && check.data.local_found) {
501
+ if (check?.ok && !check.data.needs_update && check.data.local_found) {
388
502
  const content = fs.existsSync(localPath) ? fs.readFileSync(localPath, 'utf-8') : undefined;
389
503
  const verification = check.data.verify_status
390
504
  ? normalizeVerification({ status: check.data.verify_status, reason: check.data.verify_error || undefined })
@@ -395,6 +509,7 @@ export async function agentmdSync(aid, opts) {
395
509
  // SDK's downloadAgentMd persists to disk internally (AgentMdManager.saveRecord → writeContent).
396
510
  const fetched = await store.downloadAgentMd(aid);
397
511
  if (fetched.ok) {
512
+ invalidateAgentDisplayName(aid);
398
513
  return { changed: true, content: fetched.data.content, verification: normalizeVerification(fetched.data.verification) };
399
514
  }
400
515
  // Fetch failed (network) — fall back to local file if present.
@@ -39,7 +39,7 @@ export function suppressSdkLogs() {
39
39
  };
40
40
  }
41
41
  // ==================== SDK package ====================
42
- export const MIN_AUN_CORE_SDK = [0, 5, 6];
42
+ export const MIN_AUN_CORE_SDK = [0, 5, 17];
43
43
  export const AUN_CORE_SDK_PKG = '@agentunion/fastaun';
44
44
  function compareVersion(a, min) {
45
45
  const parts = a.split('.').map(n => parseInt(n, 10));
@@ -1,10 +1,183 @@
1
1
  import crypto from 'crypto';
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import { parseDocument } from 'yaml';
2
5
  import { aidCreate } from './index.js';
3
6
  import { DEFAULT_AID_DOMAIN, normalizeAidDomain } from './domain.js';
4
7
  import { getAidStore, SLOT } from './store.js';
8
+ import { validateAgentMdDocument, verifyAgentMdUpload } from '@agentunion/fastaun';
9
+ import { agentMdPath, resolvePaths } from '../../paths.js';
10
+ import { PeerIdentityCache } from '../../core/relation/peer-identity.js';
11
+ import { agentmdPut, buildInitialAgentMd, invalidateAgentDisplayName, stripAgentMdSignature } from './agentmd.js';
5
12
  import { logger } from '../../utils/logger.js';
6
13
  const MAX_ATTEMPTS = 5;
7
14
  export { DEFAULT_AID_DOMAIN } from './domain.js';
15
+ /** Human-facing platform label used in the control AID's agent.md name. */
16
+ export function controlHostPlatformLabel(platform = process.platform) {
17
+ switch (String(platform).trim().toLowerCase()) {
18
+ case 'win32':
19
+ case 'windows':
20
+ return 'Win';
21
+ case 'linux':
22
+ return 'Linux';
23
+ case 'darwin':
24
+ case 'macos':
25
+ case 'mac':
26
+ return 'MacOS';
27
+ default: {
28
+ const value = String(platform).trim();
29
+ return value ? `${value[0].toUpperCase()}${value.slice(1)}` : 'Host';
30
+ }
31
+ }
32
+ }
33
+ /** Build the stable display name for a daemon/control AID. */
34
+ export function buildControlAgentName(aid, platform = process.platform) {
35
+ const normalized = String(aid ?? '').trim().replace(/^@/, '');
36
+ const prefix = normalized.split('.', 1)[0] || normalized || 'unknown';
37
+ return `${controlHostPlatformLabel(platform)}主机-${prefix}`;
38
+ }
39
+ const CONTROL_AGENT_DESCRIPTION = 'EvolCore daemon host.';
40
+ const CONTROL_AGENT_TAGS = ['evolcore', 'control', 'host'];
41
+ const controlAgentMdPending = new Map();
42
+ function readJsonFile(filePath) {
43
+ try {
44
+ const value = JSON.parse(fs.readFileSync(filePath, 'utf8'));
45
+ return value && typeof value === 'object' && !Array.isArray(value)
46
+ ? value
47
+ : undefined;
48
+ }
49
+ catch {
50
+ return undefined;
51
+ }
52
+ }
53
+ function hasCanonicalControlFrontmatter(content, aid, name, aunRoot) {
54
+ try {
55
+ // A frontmatter-only match is insufficient here: an unsigned or malformed
56
+ // local card must be republished so the SDK can produce a valid signature.
57
+ validateAgentMdDocument(content, { expectedAid: aid, requireSignature: true });
58
+ const payload = stripAgentMdSignature(content);
59
+ const frontmatter = payload.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/)?.[1];
60
+ if (!frontmatter)
61
+ return false;
62
+ const document = parseDocument(frontmatter);
63
+ if (document.errors.length > 0)
64
+ return false;
65
+ const fields = document.toJS();
66
+ if (!fields || typeof fields !== 'object' || Array.isArray(fields))
67
+ return false;
68
+ const values = fields;
69
+ const canonical = typeof values.aid === 'string'
70
+ && values.aid.trim().toLowerCase() === aid.toLowerCase()
71
+ && typeof values.name === 'string'
72
+ && values.name.trim() === name
73
+ && typeof values.type === 'string'
74
+ && values.type.trim().toLowerCase() === 'host';
75
+ if (!canonical)
76
+ return false;
77
+ // The SDK validator checks that a signature block is well formed, but it
78
+ // deliberately does not verify the signature against the local cert.
79
+ // A damaged or stale control card must be republished, otherwise peers
80
+ // continue to reject it even though the frontmatter looks canonical.
81
+ const certPath = path.join(aunRoot, 'AIDs', aid, 'public', 'cert.pem');
82
+ const certPem = fs.readFileSync(certPath, 'utf8');
83
+ verifyAgentMdUpload(content, certPem, aid);
84
+ return true;
85
+ }
86
+ catch {
87
+ return false;
88
+ }
89
+ }
90
+ function clearControlAgentPeerCaches(aid, root = resolvePaths().root) {
91
+ const agentsDir = path.join(root, 'agents');
92
+ // A first-run installation may not have created any EvolCore agent yet.
93
+ // There is no cache to clear in that state, and ENOENT is not a warning.
94
+ if (!fs.existsSync(agentsDir))
95
+ return;
96
+ try {
97
+ for (const entry of fs.readdirSync(agentsDir, { withFileTypes: true })) {
98
+ if (!entry.isDirectory())
99
+ continue;
100
+ PeerIdentityCache.clear('aun', aid, path.join(agentsDir, entry.name));
101
+ }
102
+ }
103
+ catch (error) {
104
+ logger.warn(`[control-aid] 清理旧身份缓存失败(不影响名片发布): ${error instanceof Error ? error.message : String(error)}`);
105
+ }
106
+ }
107
+ /**
108
+ * Ensure a daemon/control AID has a signed host agent.md.
109
+ *
110
+ * Registration in fastaun creates a default `type: agent` card. This helper
111
+ * upgrades that card, supplements cards missing on older installations, and
112
+ * is idempotent once the local card is canonical. Upload errors are allowed to
113
+ * propagate to the caller so startup can log them without becoming blocked.
114
+ */
115
+ export async function ensureControlAgentMd(aid, opts = {}) {
116
+ const normalizedAid = String(aid ?? '').trim().replace(/^@/, '');
117
+ if (!normalizedAid)
118
+ throw new Error('control AID is required');
119
+ const aunRoot = opts.aunPath ?? opts.store?.aunPath ?? resolvePaths().root;
120
+ const cacheRoot = opts.cacheRoot ?? resolvePaths().root;
121
+ const pendingKey = path.resolve(aunRoot) + '\u0000' + normalizedAid.toLowerCase();
122
+ const pending = controlAgentMdPending.get(pendingKey);
123
+ if (pending)
124
+ return pending;
125
+ const run = (async () => {
126
+ const name = buildControlAgentName(normalizedAid, opts.platform);
127
+ const localPath = agentMdPath(normalizedAid, aunRoot);
128
+ const metadataPath = path.join(path.dirname(localPath), 'agentmd.json');
129
+ let existing;
130
+ try {
131
+ existing = fs.readFileSync(localPath, 'utf8');
132
+ }
133
+ catch { /* missing */ }
134
+ const metadata = readJsonFile(metadataPath);
135
+ const remoteMissing = String(metadata?.remote_status ?? '').trim().toLowerCase() === 'missing';
136
+ const needsPublish = !existing || !hasCanonicalControlFrontmatter(existing, normalizedAid, name, aunRoot) || remoteMissing;
137
+ if (!needsPublish)
138
+ return { aid: normalizedAid, name, published: false };
139
+ const content = buildInitialAgentMd({
140
+ aid: normalizedAid,
141
+ name,
142
+ type: 'host',
143
+ description: CONTROL_AGENT_DESCRIPTION,
144
+ tags: CONTROL_AGENT_TAGS,
145
+ });
146
+ try {
147
+ await agentmdPut(content, { aid: normalizedAid, store: opts.store, aunPath: aunRoot });
148
+ }
149
+ catch (error) {
150
+ // agentmdPut intentionally keeps edits to an existing card on failure;
151
+ // a control-card migration must restore the old card so a transient
152
+ // gateway failure cannot make the local state look successfully migrated.
153
+ try {
154
+ if (existing !== undefined) {
155
+ fs.mkdirSync(path.dirname(localPath), { recursive: true });
156
+ fs.writeFileSync(localPath, existing, 'utf8');
157
+ }
158
+ else {
159
+ fs.unlinkSync(localPath);
160
+ }
161
+ }
162
+ catch { /* preserve the original upload error */ }
163
+ throw error;
164
+ }
165
+ // The upload changes the control AID's display name. Drop the process-wide
166
+ // name cache so subsequent context/status rendering cannot keep the legacy
167
+ // `agent` name until the normal TTL refresh.
168
+ invalidateAgentDisplayName(normalizedAid);
169
+ clearControlAgentPeerCaches(normalizedAid, cacheRoot);
170
+ return { aid: normalizedAid, name, published: true };
171
+ })();
172
+ controlAgentMdPending.set(pendingKey, run);
173
+ try {
174
+ return await run;
175
+ }
176
+ finally {
177
+ if (controlAgentMdPending.get(pendingKey) === run)
178
+ controlAgentMdPending.delete(pendingKey);
179
+ }
180
+ }
8
181
  function environmentValue(name) {
9
182
  if (!Object.prototype.hasOwnProperty.call(process.env, name))
10
183
  return undefined;
@@ -66,7 +239,7 @@ async function candidateExists(store, candidate) {
66
239
  * 查重通过但注册失败时也换候选重试,覆盖查重与注册之间的竞态。
67
240
  * - 查重走 GET 证书(见 candidateExists;不拉 agent.md,控制 AID 本就不传 agent.md)
68
241
  * - fail-fast:查重探测失败(网关不可达)立即抛错,不掩盖成"均冲突"
69
- * - agent.md 不上传:aidCreate 仅注册身份 + 写私钥,不调 agentmdPut
242
+ * - 注册后补发控制主机 agent.md;失败只告警,不丢弃已经注册的 AID
70
243
  */
71
244
  export async function generateControlAid(aidDomain) {
72
245
  const finalAidDomain = aidDomain === undefined
@@ -83,6 +256,12 @@ export async function generateControlAid(aidDomain) {
83
256
  }
84
257
  try {
85
258
  const created = await aidCreate(candidate);
259
+ try {
260
+ await ensureControlAgentMd(created.aid, { store: created.store });
261
+ }
262
+ catch (e) {
263
+ logger.warn(`[control-aid] ${created.aid} agent.md 发布失败(控制面可继续,后续启动会重试): ${e instanceof Error ? e.message : String(e)}`);
264
+ }
86
265
  // 清理 aidCreate 内部另开的 client/store——关闭失败不可丢弃已注册的 AID(否则下次 init
87
266
  // 会把它当冲突,白白消耗一次重试)。close 异常降级为 warn。
88
267
  try {
@@ -76,7 +76,7 @@ export function aidList(aunPath) {
76
76
  canSign: hasPrivateKey && hasCert && !certExpired && keyMatchesCert === true,
77
77
  }),
78
78
  hasPrivateKey,
79
- hasAgentMd: fs.existsSync(agentMdPath(e.name)),
79
+ hasAgentMd: fs.existsSync(agentMdPath(e.name, root)),
80
80
  hasCert,
81
81
  certExpired,
82
82
  keyMatchesCert,
@@ -114,7 +114,7 @@ export async function verifySignAbility(aid, opts) {
114
114
  // signAgentMd validates the same frontmatter contract as a published agent.md.
115
115
  // Keep the probe minimal, but make it a valid document so self-checks do not
116
116
  // reject otherwise healthy identities before exercising sign + verify.
117
- const probe = `---\naid: "${aid}"\nname: "probe"\ntype: "ai"\nversion: "1.0.0"\ndescription: "Local signing self-check"\ntags:\n - evolcore\n---\n`;
117
+ const probe = `---\naid: "${aid}"\nname: "probe"\ntype: "agent"\nversion: "1.0.0"\ndescription: "Local signing self-check"\ntags:\n - evolcore\n---\n`;
118
118
  const signRes = aidObj.signAgentMd(probe);
119
119
  if (!signRes.ok) {
120
120
  return { ok: false, reason: `sign failed: ${String(signRes.error?.message || signRes.error?.code).slice(0, 120)}` };
@@ -265,7 +265,7 @@ export async function aidShow(aid, opts) {
265
265
  const aunPath = opts?.aunPath ?? defaultAunPath();
266
266
  const aidDir = path.join(aunPath, 'AIDs', aid);
267
267
  const hasPrivateKey = fs.existsSync(path.join(aidDir, 'private'));
268
- const hasAgentMd = fs.existsSync(agentMdPath(aid));
268
+ const hasAgentMd = fs.existsSync(agentMdPath(aid, aunPath));
269
269
  let certExpiresAt = null;
270
270
  let certSubject = null;
271
271
  let certExpired = false;
@@ -323,7 +323,7 @@ export async function aidShow(aid, opts) {
323
323
  }
324
324
  if (hasAgentMd) {
325
325
  try {
326
- const content = fs.readFileSync(agentMdPath(aid), 'utf-8');
326
+ const content = fs.readFileSync(agentMdPath(aid, aunPath), 'utf-8');
327
327
  if (!content.includes('AUN-SIGNATURE')) {
328
328
  agentMdSignature = 'unsigned';
329
329
  }
@@ -1,5 +1,5 @@
1
1
  export { AGENT_TAG_MIN_COUNT, AGENT_TAG_MAX_COUNT, AGENT_TAG_MAX_LENGTH, validateAgentTag, validateAgentTags, } from './agentmd.js';
2
2
  export { isValidAid, aidList, aidListVerified, aidCreate, aidShow, aidDelete, aidLookup, verifySignAbility, probePkiRecoverability, appendAidLifecycle, readAidLifecycle } from './identity.js';
3
- export { DEFAULT_AGENT_DESCRIPTION, buildInitialAgentMd, validateAgentMdFrontmatter, agentmdGet, agentmdPut, agentmdSync, invalidateAgentDisplayName, parseAgentDisplayName, refreshAgentDisplayName, resolveAgentDisplayName, stripAgentMdSignature, updateAgentMdFrontmatterAvatar, updateAgentMdFrontmatterName, } from './agentmd.js';
3
+ export { AGENT_TYPES, DEFAULT_AGENT_DESCRIPTION, DEFAULT_AGENT_TYPE, normalizeAgentType, validateAgentType, buildInitialAgentMd, validateAgentMdFrontmatter, agentmdGet, agentmdPut, agentmdSync, invalidateAgentDisplayName, parseAgentDisplayName, refreshAgentDisplayName, resolveAgentDisplayName, stripAgentMdSignature, updateAgentMdFrontmatterAvatar, updateAgentMdFrontmatterName, } from './agentmd.js';
4
4
  export { MIN_AUN_CORE_SDK, AUN_CORE_SDK_PKG, isAunSdkVersionOk, resolveAunCoreSdkPkg, ensureAunSdk, isAunSdkReady, downloadCaRoot, suppressSdkLogs, } from './client.js';
5
5
  export { getAidStore, loadClient, loadAid, AidLoadError, SLOT } from './store.js';
@@ -80,10 +80,10 @@ export async function loadClient(store, aid) {
80
80
  /**
81
81
  * Enable bounded multi-page group pulls for the long-lived daemon client.
82
82
  *
83
- * The SDK's background realtime recovery path intentionally passes
84
- * `maxPages=1`; for a daemon this can strand a backlog after a tail sync.
85
- * This adapter only expands that sentinel value and leaves all other pull
86
- * options unchanged. It is isolated to the client that explicitly opts in.
83
+ * Older SDK recovery paths used `maxPages=1`; for a daemon that can strand a
84
+ * backlog after a tail sync. SDK 0.5.15 normally chooses a larger recovery
85
+ * window, but this adapter still expands an explicit single-page request and
86
+ * keeps older clients safe. It is isolated to the client that opts in.
87
87
  */
88
88
  export function enableFullGroupPullPagination(client) {
89
89
  const target = client;
@@ -110,13 +110,12 @@ export function enableFullGroupPullPagination(client) {
110
110
  /**
111
111
  * Make SDK pull delivery wait until EvolCore's application handlers finish.
112
112
  *
113
- * fastaun 0.5.13 publishes message events with dispatcher.enqueue(), then
114
- * advances its sequence tracker immediately. That is a transport watermark,
115
- * so a daemon restart can acknowledge a message before the application has
116
- * durably claimed it. The SDK keeps _publishAppEvent private, but the public
117
- * client is intentionally adapted here in one place: preserve the SDK's
118
- * normal publication path and wait for its dispatcher queue for pulled
119
- * message events before the pull operation commits the sequence.
113
+ * fastaun publishes message events asynchronously, while the sequence tracker
114
+ * is a transport watermark. A daemon restart can therefore acknowledge a
115
+ * pulled message before the application has durably claimed it. SDK 0.5.15
116
+ * split protocol and application queues; prefer its application-only flush so
117
+ * an unrelated protocol event cannot delay the pull commit. Older SDKs fall
118
+ * back to the combined flush method.
120
119
  */
121
120
  export function enableReliableMessageDelivery(client) {
122
121
  const target = client;
@@ -124,7 +123,12 @@ export function enableReliableMessageDelivery(client) {
124
123
  return false;
125
124
  const publish = target._publishAppEvent;
126
125
  const dispatcher = target._dispatcher;
127
- if (typeof publish !== 'function' || !dispatcher || typeof dispatcher.flush !== 'function')
126
+ const flushApplication = typeof dispatcher?.flushApplication === 'function'
127
+ ? dispatcher.flushApplication.bind(dispatcher)
128
+ : typeof dispatcher?.flush === 'function'
129
+ ? dispatcher.flush.bind(dispatcher)
130
+ : undefined;
131
+ if (typeof publish !== 'function' || !flushApplication)
128
132
  return false;
129
133
  const wrappedPublish = async function (event, payload, source, ...rest) {
130
134
  const result = await publish.call(this, event, payload, source, ...rest);
@@ -135,7 +139,7 @@ export function enableReliableMessageDelivery(client) {
135
139
  && source !== 'push'
136
140
  && source !== 'inline-push';
137
141
  if (reliable)
138
- await dispatcher.flush();
142
+ await flushApplication();
139
143
  return result;
140
144
  };
141
145
  Object.defineProperty(target, RELIABLE_MESSAGE_DELIVERY_PATCH, {