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
@@ -1,4 +1,7 @@
1
1
  import { BaseagentRunnerUnavailableError } from '../../agents/runner-types.js';
2
+ import { loadedBaseagentIds } from '../../agents/baseagent-availability.js';
3
+ import { parseMenuClientArgs } from '../../cli/menu-client.js';
4
+ import { ensureSessionRuntimeDir } from '../../cli/task-context.js';
2
5
  import { renderCommandCardAsText } from '../interaction-router.js';
3
6
  import { buildEnvelope, deliveryTargetFromSession, isInteractionSendAccepted, replyContextFromSession, sendInteractionPayload } from '../message/message-utils.js';
4
7
  import { resolvePaths, getPackageRoot } from '../../paths.js';
@@ -7,6 +10,7 @@ import { logger } from '../../utils/logger.js';
7
10
  import { resolvePeerRoleDetail, roleToSessionIdentity } from '../../config/peer-role-resolver.js';
8
11
  import { isManagementRole } from '../../config/builtin-roles.js';
9
12
  import { formatPeerKey } from '../relation/peer-identity.js';
13
+ import { sameGroupAid } from '../../aun/group/index.js';
10
14
  import crypto from 'crypto';
11
15
  import path from 'path';
12
16
  import fs from 'fs';
@@ -17,13 +21,13 @@ import { tryParseChannelKey } from '../channel-loader.js';
17
21
  import { displaySessionTitle } from '../session/session-title.js';
18
22
  import { buildSessionTurnList } from '../session/session-turns.js';
19
23
  import { resolveConfigCommand } from '../../config/resolved-config-op.js';
20
- import { AUTHENTICATED_CONFIG_ROLE_ENV, executeResolvedConfigCommand } from '../../config/config-operation-service.js';
24
+ import { AUTHENTICATED_CONFIG_ROLE_ENV, executeResolvedConfigCommandAsync } from '../../config/config-operation-service.js';
21
25
  import { splitConfigBatchGetArgv } from '../../cli/cli-argv.js';
22
26
  import { auditCommandAuthorization, auditFullAccessEvent, hashArgv } from '../auth/authorization-audit.js';
23
27
  import { executeResolvedContactCommand, resolveContactCommand } from '../../config/contact-operation-service.js';
24
28
  import { hasTrustedFullAccessDelegation, trustedExecutionIdentityInput } from '../auth/agent-delegation.js';
25
29
  import { executeManagedAidOperation, ManagedAidOperationError, managedAidShowViewForRole, resolveManagedAidOperation, } from '../../aun/aid/managed-operation.js';
26
- import { executeManagedGroupOperation, isManagedGroupRelationRead, ManagedGroupOperationError, resolveManagedGroupOperation, executeManagedMsgOperation, ManagedMsgOperationError, resolveManagedMsgOperation, executeManagedFsOperation, ManagedFsOperationError, resolveManagedFsOperation, } from '../../aun/msg/managed-operation.js';
30
+ import { executeManagedGroupOperation, isManagedGroupRelationRead, isManagedGroupRelationWrite, ManagedGroupOperationError, resolveManagedGroupOperation, executeManagedMsgOperation, ManagedMsgOperationError, resolveManagedMsgOperation, executeManagedFsOperation, ManagedFsOperationError, resolveManagedFsOperation, } from '../../aun/msg/managed-operation.js';
27
31
  import { authorizeOperation, buildAuthSubject } from '../auth/auth-gateway.js';
28
32
  import { isHClassPath, isLClassPath, isSameOrDescendant } from '../permission/protected-paths.js';
29
33
  import { validateModelSelectionForRole } from '../model/model-permission.js';
@@ -98,6 +102,14 @@ export class CommandHandler {
98
102
  sessionManager;
99
103
  messageCache;
100
104
  eventBus;
105
+ agentStorageClientResolver;
106
+ groupInviteDecisionResolver;
107
+ setAgentStorageClientResolver(resolver) {
108
+ this.agentStorageClientResolver = resolver;
109
+ }
110
+ setGroupInviteDecisionResolver(resolver) {
111
+ this.groupInviteDecisionResolver = resolver;
112
+ }
101
113
  adapters = new Map();
102
114
  policies = new Map();
103
115
  channelObjects = new Map(); // name → actual channel instance (for /check)
@@ -123,6 +135,43 @@ export class CommandHandler {
123
135
  daemonMonitorProvider;
124
136
  agentDelegationRegistry;
125
137
  handoffRuntime;
138
+ diagService;
139
+ setDiagService(service) { this.diagService = service; }
140
+ async handleMenuClientOperation(argv, sessionId, delegationToken, delegationCommandHash, send) {
141
+ const validation = this.agentDelegationRegistry?.validate(delegationToken, sessionId, delegationCommandHash);
142
+ if (!validation?.ok)
143
+ return { ok: false, code: validation?.code ?? 'DELEGATION_REQUIRED', error: validation?.reason ?? 'Task delegation is required' };
144
+ const grant = validation.grant;
145
+ const session = await this.sessionManager.getSessionById(sessionId);
146
+ if (!session || session.selfAID !== grant.selfAid || argv[0] !== 'request' || argv[1] !== grant.selfAid)
147
+ return { ok: false, code: 'SCOPE_MISMATCH', error: 'Menu requests must use the current Agent identity and session' };
148
+ try {
149
+ const channelId = parsePeerKey(grant.peerKey).channelId;
150
+ const subject = buildAuthSubject({ selfAid: grant.selfAid, actorId: grant.actorId, channel: grant.channel,
151
+ channelType: grant.channelType, channelId, chatType: grant.chatType, conversationId: channelId,
152
+ processOwners: [], ...trustedExecutionIdentityInput(grant) });
153
+ const decision = authorizeOperation({ source: 'agent-tool', subject,
154
+ intent: { operation: 'ec.menu.request', scope: 'relation', source: 'agent-tool', args: { self: grant.selfAid, peer: argv[2], targetId: argv[2] } },
155
+ auditMetadata: { taskId: grant.taskId, sessionId, messageId: grant.messageId } });
156
+ if (!decision.allow)
157
+ return { ok: false, code: decision.code, error: decision.reason };
158
+ const options = parseMenuClientArgs(argv, file => {
159
+ const target = fs.realpathSync(path.resolve(session.projectPath, file));
160
+ const roots = [session.projectPath, this.getManagedSessionTempDir(session)].filter((v) => !!v)
161
+ .map(root => fs.realpathSync(root));
162
+ if (!roots.some(root => isSameOrDescendant(target, root)) || isHClassPath(target) || isLClassPath(target))
163
+ throw new Error('Menu request file must be an unprotected file in the project or session TMPDIR');
164
+ const stat = fs.statSync(target);
165
+ if (!stat.isFile() || stat.nlink > 1 || stat.size > 128 * 1024)
166
+ throw new Error('Menu request file must be a regular file of at most 128 KiB');
167
+ return fs.readFileSync(target, 'utf8');
168
+ });
169
+ return { ok: true, response: await send(options) };
170
+ }
171
+ catch (error) {
172
+ return { ok: false, code: error.code ?? 'MENU_REQUEST_FAILED', error: error.message };
173
+ }
174
+ }
126
175
  contactRequestSubmitter;
127
176
  /**
128
177
  * Get the runner for a (channel, baseagent) pair.
@@ -170,19 +219,11 @@ export class CommandHandler {
170
219
  throw new BaseagentRunnerUnavailableError('<unknown>', requestedBaseagent || '<missing>', []);
171
220
  }
172
221
  getAvailableBaseagentsForOwner(evolName) {
173
- const prefix = `${evolName}::`;
174
- return [...this.agentMap.keys()]
175
- .filter(key => key.startsWith(prefix))
176
- .map(key => key.slice(prefix.length));
222
+ return loadedBaseagentIds(this.agentMap.keys(), evolName);
177
223
  }
178
- /** Return the runner-owned temporary root for a managed session, if any. */
224
+ /** Return the stable temporary root for a managed session, if available. */
179
225
  getManagedSessionTempDir(session) {
180
- try {
181
- return this.getAgent(session.channel, session.baseagent).getManagedTempDir?.(session.id);
182
- }
183
- catch {
184
- return undefined;
185
- }
226
+ return ensureSessionRuntimeDir(session.id);
186
227
  }
187
228
  formatBaseagentUnavailable(error) {
188
229
  const available = error.availableBaseagents.length ? error.availableBaseagents.join(', ') : '(none)';
@@ -198,21 +239,10 @@ export class CommandHandler {
198
239
  getAvailableBaseagents(channel) {
199
240
  const owner = this.agentRegistry?.resolveByChannel(channel);
200
241
  if (!owner) {
201
- const result = new Set();
202
- for (const key of this.agentMap.keys()) {
203
- const idx = key.indexOf('::');
204
- result.add(idx >= 0 ? key.slice(idx + 2) : key);
205
- }
206
- return [...result];
242
+ return loadedBaseagentIds(this.agentMap.keys());
207
243
  }
208
244
  const evolName = owner.name || '<unknown>';
209
- const prefix = `${evolName}::`;
210
- const result = [];
211
- for (const key of this.agentMap.keys()) {
212
- if (key.startsWith(prefix))
213
- result.push(key.slice(prefix.length));
214
- }
215
- return result;
245
+ return loadedBaseagentIds(this.agentMap.keys(), evolName);
216
246
  }
217
247
  /** Extract the baseagent component from `primaryRunnerKey` (e.g. `aid::claude` → `claude`). */
218
248
  parseDefaultBaseagent() {
@@ -403,6 +433,8 @@ export class CommandHandler {
403
433
  primaryFeedbackTarget(definition) {
404
434
  if (definition.feedback.strategy === 'target')
405
435
  return definition.feedback.target;
436
+ if (definition.feedback.strategy === 'event_session')
437
+ return undefined;
406
438
  if (!definition.origin)
407
439
  return undefined;
408
440
  return {
@@ -587,10 +619,16 @@ export class CommandHandler {
587
619
  if (!isAdmin && parsed.feedbackStrategy === 'target' && !sameFeedbackTarget(target, origin)) {
588
620
  return { error: '无权限:非 admin 只能把 trigger 投递到来源会话' };
589
621
  }
622
+ if (!isAdmin && parsed.feedbackStrategy === 'event_session') {
623
+ return { error: '无权限:只有 owner/admin 可以使用事件来源会话' };
624
+ }
590
625
  const source = this.triggerSourceFromSchedule(parsed.scheduleType, parsed.scheduleValue);
591
626
  if (parsed.timezone && source.type === 'cron') {
592
627
  source.timezone = parsed.timezone;
593
628
  }
629
+ if (parsed.eventFilter !== undefined && source.type === 'event') {
630
+ source.filter = parsed.eventFilter;
631
+ }
594
632
  const script = parsed.scriptPath ? {
595
633
  path: parsed.scriptPath,
596
634
  runtime: parsed.scriptRuntime,
@@ -650,6 +688,7 @@ export class CommandHandler {
650
688
  baseagent: executionBaseagent,
651
689
  } : {}),
652
690
  model: parsed.model,
691
+ timeoutMs: parsed.executionTimeoutMs,
653
692
  effort: parsed.effort,
654
693
  ...(permissionMode !== undefined ? { permissionMode } : {}),
655
694
  onError: 'retry',
@@ -809,23 +848,36 @@ export class CommandHandler {
809
848
  * 通用降级应答入口:按 (sessionId, fallbackCommand) 查找 pending interaction 并路由。
810
849
  * 返回 { matched: true } 表示已处理,调用方直接返回 result。
811
850
  */
812
- async handleInteractionFallback(command, args, sessionId, userId) {
851
+ async handleInteractionFallback(command, args, sessionId, userId, channelKey) {
813
852
  if (!this.interactionRouter)
814
853
  return { matched: false };
815
- const pendingId = this.interactionRouter.findPendingByCommand(sessionId, command);
854
+ const candidates = this.interactionRouter.getPending(sessionId, command);
855
+ const explicitId = args.split(/\s+/, 1)[0];
856
+ if (explicitId.startsWith('aq-') && !candidates.includes(explicitId)) {
857
+ return { matched: true, result: '⚠️ 该问题不存在、已回答或已过期,请使用当前问题卡片。' };
858
+ }
859
+ const pendingId = candidates.includes(explicitId)
860
+ ? explicitId : this.interactionRouter.findPendingByCommand(sessionId, command);
816
861
  if (!pendingId)
817
862
  return { matched: false };
863
+ if (explicitId !== pendingId && candidates.length > 1) {
864
+ return { matched: true, result: `有多个待回答问题,请使用 /ask <问题ID> <回答>:\n${candidates.join('\n')}` };
865
+ }
866
+ const answer = explicitId === pendingId ? args.slice(explicitId.length).trim() : args.trim();
867
+ if (!answer)
868
+ return { matched: true, result: `请使用 /ask ${pendingId} <回答>` };
818
869
  const initiatorId = this.interactionRouter.getInitiator(pendingId);
819
870
  if (initiatorId && initiatorId !== userId) {
820
871
  return { matched: true, result: '⚠️ 仅卡片发起者可应答' };
821
872
  }
822
- const handled = this.interactionRouter.handle({
873
+ const handled = await this.interactionRouter.handleAsync({
823
874
  type: 'interaction.response',
824
875
  id: pendingId,
825
- action: args,
876
+ action: answer,
826
877
  operatorId: userId,
878
+ ...(channelKey ? { channelKey } : {}),
827
879
  });
828
- return { matched: true, result: handled ? '✓ 已回答' : '⚠️ 无法验证应答者身份' };
880
+ return { matched: true, result: handled ? '✓ 已回答' : '⚠️ 回答未被接受,请检查选项或问题是否仍有效。' };
829
881
  }
830
882
  setProcessor(processor) {
831
883
  this.processor = processor;
@@ -965,6 +1017,7 @@ export class CommandHandler {
965
1017
  const item = {
966
1018
  value: s.threadId,
967
1019
  label: displayName,
1020
+ lable: s.lable || null,
968
1021
  };
969
1022
  if (s.agentSessionId) {
970
1023
  item.agentSessionId = s.agentSessionId;
@@ -983,16 +1036,17 @@ export class CommandHandler {
983
1036
  getMenuItems(role, chatType = 'private', scope = 'agent', authSubject) {
984
1037
  return menuGetMenuItems.call(this, role, chatType, scope, authSubject);
985
1038
  }
986
- async getMenuCatalog(channel, channelId, subject, request, channelScope = 'agent') {
1039
+ async getMenuCatalog(channel, channelId, subject, request, channelScope = 'agent', paircodeAllowed) {
987
1040
  return await getMenuCatalog({
988
1041
  subject,
989
1042
  channelType: this.resolveChannelType(channel),
990
1043
  channelScope,
991
1044
  channelId,
992
1045
  request,
1046
+ ...(paircodeAllowed === undefined ? {} : { paircodeAllowed }),
993
1047
  });
994
1048
  }
995
- async execMenuValueBatch(channel, channelId, subject, args, request, channelScope = 'agent') {
1049
+ async execMenuValueBatch(channel, channelId, subject, args, request, channelScope = 'agent', transportReplyContext) {
996
1050
  validateMenuValueBatchArgs(args);
997
1051
  return await execMenuValueBatch({
998
1052
  subject,
@@ -1003,12 +1057,12 @@ export class CommandHandler {
1003
1057
  items: args?.items,
1004
1058
  schemaVersion: args?.schemaVersion,
1005
1059
  consistency: args?.consistency,
1006
- execQuery: async (cmd, resolvedChannelId, queryArgs, context) => this.execMenuQuery(cmd, channel, resolvedChannelId, context.subject.actorId, queryArgs, context.subject.chatType, context.subject.fromControlChannel, context.subject.identity, context.subject, channelScope === 'control' ? 'control' : 'menu'),
1060
+ execQuery: async (cmd, resolvedChannelId, queryArgs, context) => this.execMenuQuery(cmd, channel, resolvedChannelId, context.subject.actorId, queryArgs, context.subject.chatType, context.subject.fromControlChannel, context.subject.identity, context.subject, channelScope === 'control' ? 'control' : 'menu', resolvedChannelId === channelId ? transportReplyContext : undefined),
1007
1061
  });
1008
1062
  }
1009
1063
  /** 动态子菜单:根据 cmd 路径返回选项列表(供 menu.query + cmd 使用) */
1010
- async getSubMenuItems(cmd, channel, channelId, userId, args, overrideIdentity, explicitChatType, fromControlChannel = false, authSubject, source = 'menu') {
1011
- return await menuGetSubMenuItems.call(this, cmd, channel, channelId, userId, args, overrideIdentity, explicitChatType, fromControlChannel, authSubject, source);
1064
+ async getSubMenuItems(cmd, channel, channelId, userId, args, overrideIdentity, explicitChatType, fromControlChannel = false, authSubject, source = 'menu', transportReplyContext) {
1065
+ return await menuGetSubMenuItems.call(this, cmd, channel, channelId, userId, args, overrideIdentity, explicitChatType, fromControlChannel, authSubject, source, transportReplyContext);
1012
1066
  }
1013
1067
  // ── Menu Protocol exec ────────────────────────────────────────────────
1014
1068
  async loadMenuContext(channel, channelId) {
@@ -1020,8 +1074,8 @@ export class CommandHandler {
1020
1074
  return s ? null : { error: '当前无活跃会话', code: 'NO_ACTIVE_SESSION' };
1021
1075
  }
1022
1076
  /** menu.query — 查询当前值。 */
1023
- async execMenuQuery(cmd, channel, channelId, userId, args, explicitChatType, fromControlChannel = false, overrideIdentity, authSubject, source = 'menu') {
1024
- return await menuExecMenuQuery.call(this, cmd, channel, channelId, userId, args, explicitChatType, fromControlChannel, overrideIdentity, authSubject, source);
1077
+ async execMenuQuery(cmd, channel, channelId, userId, args, explicitChatType, fromControlChannel = false, overrideIdentity, authSubject, source = 'menu', transportReplyContext) {
1078
+ return await menuExecMenuQuery.call(this, cmd, channel, channelId, userId, args, explicitChatType, fromControlChannel, overrideIdentity, authSubject, source, transportReplyContext);
1025
1079
  }
1026
1080
  /** menu.update — 写入新值。 */
1027
1081
  async execMenuUpdate(cmd, value, channel, channelId, userId, overrideIdentity, fromControlChannel = false, args, authSubject, source = 'menu', transportReplyContext) {
@@ -1176,9 +1230,9 @@ export class CommandHandler {
1176
1230
  /**
1177
1231
  * 主命令处理入口
1178
1232
  */
1179
- async handle(content, channel, channelId, sendMessage, userId, threadId, chatType, source, messageId, selfAID, overrideIdentity, authSubject, replyContext) {
1233
+ async handle(content, channel, channelId, sendMessage, userId, threadId, chatType, source, messageId, selfAID, overrideIdentity, authSubject, replyContext, enforceGroupSlashPolicy = false) {
1180
1234
  try {
1181
- const result = await this._handleInternal(content, channel, channelId, sendMessage, userId, threadId, chatType, source, messageId, selfAID, overrideIdentity, authSubject, replyContext);
1235
+ const result = await this._handleInternal(content, channel, channelId, sendMessage, userId, threadId, chatType, source, messageId, selfAID, overrideIdentity, authSubject, replyContext, enforceGroupSlashPolicy);
1182
1236
  // Lifecycle commands are control-plane operations. Their replies must
1183
1237
  // use notification payloads so other agents in a group do not treat the
1184
1238
  // text as ordinary model input. Normalize guard-path replies here too,
@@ -1210,8 +1264,10 @@ export class CommandHandler {
1210
1264
  throw error;
1211
1265
  }
1212
1266
  }
1213
- async _handleInternal(content, channel, channelId, sendMessage, userId, threadId, chatType, source, messageId, selfAID, overrideIdentity, authSubject, replyContext) {
1214
- return await handleSlashCommand.call(this, content, channel, channelId, sendMessage, userId, threadId, chatType, source, messageId, selfAID, overrideIdentity, authSubject, replyContext);
1267
+ async _handleInternal(content, channel, channelId, sendMessage, userId, threadId, chatType, source, messageId, selfAID, overrideIdentity, authSubject, replyContext,
1268
+ // Menu and delegated CLI operations reuse this implementation without the chat-only policy.
1269
+ applyGroupSlashPolicy = false) {
1270
+ return await handleSlashCommand.call(this, content, channel, channelId, sendMessage, userId, threadId, chatType, source, messageId, selfAID, overrideIdentity, authSubject, replyContext, applyGroupSlashPolicy);
1215
1271
  }
1216
1272
  async handleTriggerCommand(scheduler, content, channel, channelId, peerId, isAdmin, messageId, chatType, threadId, isDaemonOwner = false, canApprovePersistentFullAccess = isDaemonOwner) {
1217
1273
  if (content === '/trigger') {
@@ -1399,17 +1455,17 @@ export class CommandHandler {
1399
1455
  const nextStr = reg.trigger.nextFireAt ? new Date(reg.trigger.nextFireAt).toLocaleString() : '未计算';
1400
1456
  return `✅ 触发器已注册:**${reg.trigger.name}**\n下次触发:${nextStr}`;
1401
1457
  }
1402
- return `❌ 未知子命令。用法:
1403
- /trigger — 查看活跃触发器
1404
- /trigger list [--all] — 查看所有触发器
1405
- /trigger create <参数> — 创建触发器(set 为兼容别名)
1406
- /trigger update <名称|ID> <参数> — 修改触发器
1407
- 常用参数:--delay/--at/--cron/--every、--prompt、--description、--model、--effort、--permission(省略则继承;update 可用 inherit 清除覆盖)、--feedback、--target-channel/--target-channel-id、--trigger-thread、--baseagent、--on-error、--retry-attempts/--retry-backoff、--script-runtime/--script-args/--script-timeout
1408
- /trigger enable <名称|ID> — 启用触发器
1409
- /trigger disable <名称|ID> — 暂停触发器
1410
- /trigger show <名称|ID> — 查看触发器详情
1411
- /trigger run <名称|ID> [--dry-run] — 手动触发
1412
- /trigger cancel <名称|ID> — 禁用触发器(disable 的兼容别名)
1458
+ return `❌ 未知子命令。用法:
1459
+ /trigger — 查看活跃触发器
1460
+ /trigger list [--all] — 查看所有触发器
1461
+ /trigger create <参数> — 创建触发器(set 为兼容别名)
1462
+ /trigger update <名称|ID> <参数> — 修改触发器
1463
+ 常用参数:--delay/--at/--cron/--every、--prompt、--description、--model、--effort、--permission(省略则继承;update 可用 inherit 清除覆盖)、--feedback、--target-channel/--target-channel-id、--trigger-thread、--baseagent、--on-error、--retry-attempts/--retry-backoff、--script-runtime/--script-args/--script-timeout
1464
+ /trigger enable <名称|ID> — 启用触发器
1465
+ /trigger disable <名称|ID> — 暂停触发器
1466
+ /trigger show <名称|ID> — 查看触发器详情
1467
+ /trigger run <名称|ID> [--dry-run] — 手动触发
1468
+ /trigger cancel <名称|ID> — 禁用触发器(disable 的兼容别名)
1413
1469
  /trigger delete <名称|ID> — 删除触发器`;
1414
1470
  }
1415
1471
  async handleTrigger(content, channel, channelId, peerId, isAdmin, messageId, chatType, threadId, isDaemonOwner = false, canApprovePersistentFullAccess = isDaemonOwner) {
@@ -1472,6 +1528,9 @@ export class CommandHandler {
1472
1528
  updated = deescalated;
1473
1529
  }
1474
1530
  const target = this.primaryFeedbackTarget(updated);
1531
+ if (!isAdmin && updated.feedback.strategy === 'event_session') {
1532
+ return { ok: false, error: '无权限:只有 owner/admin 可以使用事件来源会话' };
1533
+ }
1475
1534
  if (!isAdmin && target && !sameFeedbackTarget(target, definition.origin)) {
1476
1535
  return { ok: false, error: '无权限:非 admin 只能把 trigger 投递到来源会话' };
1477
1536
  }
@@ -1677,8 +1736,9 @@ export class CommandHandler {
1677
1736
  buildCtlReplyContext(session) {
1678
1737
  const ctx = { delivery: deliveryTargetFromSession(session) };
1679
1738
  const meta = session.metadata;
1680
- if (meta?.replyContext?.threadId)
1681
- ctx.threadId = meta.replyContext.threadId;
1739
+ const threadId = session.threadId || meta?.replyContext?.threadId;
1740
+ if (threadId)
1741
+ ctx.threadId = threadId;
1682
1742
  if (meta?.replyContext?.peerId)
1683
1743
  ctx.peerId = meta.replyContext.peerId;
1684
1744
  if (!ctx.peerId && meta?.peerId)
@@ -1759,7 +1819,7 @@ export class CommandHandler {
1759
1819
  processOwners: loadDaemonConfig().owners ?? [],
1760
1820
  ...trustedExecutionIdentityInput(grant),
1761
1821
  });
1762
- const executeOne = (fieldArgv) => {
1822
+ const executeOne = async (fieldArgv) => {
1763
1823
  const resolved = resolveConfigCommand(fieldArgv, {
1764
1824
  defaultRelation: { self: grant.selfAid, peerKey: grant.peerKey },
1765
1825
  });
@@ -1780,6 +1840,7 @@ export class CommandHandler {
1780
1840
  dangerous: resolved.command.dangerous,
1781
1841
  },
1782
1842
  resolvedConfigCommand: resolved.command,
1843
+ allowExplicitRelationTarget: true,
1783
1844
  auditMetadata: {
1784
1845
  argvHash: hashArgv(resolved.command.canonicalArgv),
1785
1846
  taskId: grant.taskId,
@@ -1788,22 +1849,35 @@ export class CommandHandler {
1788
1849
  });
1789
1850
  if (!decision.allow)
1790
1851
  return { ok: false, code: decision.code, error: decision.reason };
1791
- return executeResolvedConfigCommand(resolved.command, { role: subject.role });
1852
+ const roleContext = {
1853
+ self: grant.selfAid,
1854
+ actorRole: subject.role,
1855
+ actorRoleSource: subject.roleSource,
1856
+ actorAllowAccess: subject.allowAccess,
1857
+ actorAid: grant.actorId,
1858
+ isDaemonOwner: subject.isDaemonOwner,
1859
+ fromControlChannel: subject.fromControlChannel,
1860
+ chatType: grant.chatType,
1861
+ };
1862
+ return await executeResolvedConfigCommandAsync(resolved.command, {
1863
+ role: subject.role,
1864
+ roleContext,
1865
+ });
1792
1866
  };
1793
1867
  const batch = splitConfigBatchGetArgv(argv);
1794
1868
  if (batch && batch.fields.length > 1) {
1795
- const results = batch.fields.map(field => {
1796
- const result = executeOne(['config', 'get', field, ...batch.rest]);
1869
+ const results = await Promise.all(batch.fields.map(async (field) => {
1870
+ const result = await executeOne(['config', 'get', field, ...batch.rest]);
1797
1871
  if (!result.ok)
1798
1872
  return { ok: false, field, code: result.code, error: result.error };
1799
1873
  if (result.subcommand !== 'get') {
1800
1874
  return { ok: false, field, code: 'UNEXPECTED_RESULT', error: `config get ${field} produced a non-get result` };
1801
1875
  }
1802
1876
  return result;
1803
- });
1877
+ }));
1804
1878
  return { ok: true, result: { ok: true, subcommand: 'batch-get', results } };
1805
1879
  }
1806
- const result = executeOne(argv);
1880
+ const result = await executeOne(argv);
1807
1881
  return result.ok
1808
1882
  ? { ok: true, result }
1809
1883
  : { ok: false, code: result.code, error: result.error, ...(result.data !== undefined ? { data: result.data } : {}) };
@@ -1827,7 +1901,8 @@ export class CommandHandler {
1827
1901
  catch {
1828
1902
  return { ok: false, code: 'INVALID_DELEGATION', error: 'Delegation contains an invalid relation key' };
1829
1903
  }
1830
- const resolved = resolveContactCommand(argv);
1904
+ const resolvedArgv = argv.includes('--self') ? argv : [...argv, '--self', grant.selfAid];
1905
+ const resolved = resolveContactCommand(resolvedArgv);
1831
1906
  if (!resolved.ok)
1832
1907
  return { ok: false, code: resolved.code, error: resolved.reason };
1833
1908
  if (resolved.command.selfAid !== grant.selfAid && !hasTrustedFullAccessDelegation(grant)) {
@@ -2124,7 +2199,8 @@ export class CommandHandler {
2124
2199
  const managementRole = isManagementRole(subject.role) || subject.dataScope === 'daemon';
2125
2200
  if (subject.dataScope !== 'daemon'
2126
2201
  && !managementRole
2127
- && (grant.channelType !== 'aun' || !isManagedGroupRelationRead(parsed.command))) {
2202
+ && (grant.channelType !== 'aun'
2203
+ || !(isManagedGroupRelationRead(parsed.command) || isManagedGroupRelationWrite(parsed.command)))) {
2128
2204
  return { ok: false, code: 'ROLE_ACCESS_DENIED', error: `Role ${subject.role} cannot manage Agent group membership or settings` };
2129
2205
  }
2130
2206
  if ((parsed.command.kind === 'dissolve' || parsed.command.kind === 'owner')
@@ -2156,6 +2232,21 @@ export class CommandHandler {
2156
2232
  });
2157
2233
  if (!decision.allow)
2158
2234
  return { ok: false, code: decision.code, error: decision.reason };
2235
+ if (parsed.command.kind === 'accept-invite' || parsed.command.kind === 'reject-invite') {
2236
+ if (subject.role !== 'owner' || grant.channelType !== 'aun' || grant.chatType !== 'private'
2237
+ || parsed.command.from !== grantSelfAid || !this.groupInviteDecisionResolver) {
2238
+ return { ok: false, code: 'ROLE_ACCESS_DENIED', error: 'Targeted invitation decisions require the current Agent Owner' };
2239
+ }
2240
+ try {
2241
+ const result = await this.groupInviteDecisionResolver(grantSelfAid, grant.actorId, parsed.command.inviteId, parsed.command.kind === 'accept-invite' ? 'accept' : 'reject');
2242
+ return result.accepted
2243
+ ? { ok: true, result: { ok: true, status: result.status, group_id: result.groupId, message: result.text } }
2244
+ : { ok: false, code: 'GROUP_INVITE_DECISION_REJECTED', error: result.text };
2245
+ }
2246
+ catch (error) {
2247
+ return { ok: false, code: 'GROUP_INVITE_DECISION_FAILED', error: error instanceof Error ? error.message : String(error) };
2248
+ }
2249
+ }
2159
2250
  let rulesContent;
2160
2251
  if (parsed.command.kind === 'rules.set') {
2161
2252
  const filePath = String(parsed.command.filePath || '');
@@ -2210,7 +2301,10 @@ export class CommandHandler {
2210
2301
  }
2211
2302
  }
2212
2303
  try {
2213
- return { ok: true, result: await executeManagedGroupOperation(parsed.command, rulesContent) };
2304
+ return { ok: true, result: await executeManagedGroupOperation(parsed.command, rulesContent, {
2305
+ defaultThread: grant.chatType === 'group' && conversationId === parsed.command.groupId
2306
+ ? session.threadId || 'main' : 'all',
2307
+ }) };
2214
2308
  }
2215
2309
  catch (error) {
2216
2310
  return {
@@ -2407,7 +2501,7 @@ export class CommandHandler {
2407
2501
  return { ok: false, code: 'INVALID_DELEGATION', error: 'Delegation contains an invalid relation key' };
2408
2502
  }
2409
2503
  if (!hasTrustedFullAccessDelegation(grant)
2410
- && ((parsed.command.actorAid && parsed.command.actorAid !== actorAid) || parsed.command.groupId !== currentGroup)) {
2504
+ && ((parsed.command.actorAid && parsed.command.actorAid !== actorAid) || !sameGroupAid(parsed.command.groupId, currentGroup))) {
2411
2505
  return { ok: false, code: 'SCOPE_MISMATCH', error: 'Only the current AUN group can be targeted' };
2412
2506
  }
2413
2507
  parsed.command.actorAid = hasTrustedFullAccessDelegation(grant)