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.
- package/CHANGELOG.md +632 -565
- package/LICENSE +21 -21
- package/README.md +455 -455
- package/bin/codex-managed-acl.ps1 +203 -160
- package/bin/codex-managed-hook.mjs +208 -208
- package/bin/ec-safe-output.js +327 -327
- package/bin/ec.js +40 -29
- package/bin/install-codex-managed-hooks.mjs +582 -555
- package/dist/agents/baseagent-availability.js +68 -0
- package/dist/agents/baseagent.js +96 -46
- package/dist/agents/claude-runner.js +172 -33
- package/dist/agents/codex/app-server-client.js +76 -31
- package/dist/agents/codex/catalog.js +1 -1
- package/dist/agents/codex/diagnostics.js +34 -1
- package/dist/agents/codex-runner.js +434 -446
- package/dist/agents/ecagent-runner.js +174 -34
- package/dist/agents/gemini-runner.js +8 -7
- package/dist/agents/runner-types.js +75 -19
- package/dist/aun/aid/agentmd.js +151 -36
- package/dist/aun/aid/client.js +1 -1
- package/dist/aun/aid/control-aid.js +180 -1
- package/dist/aun/aid/identity.js +4 -4
- package/dist/aun/aid/index.js +1 -1
- package/dist/aun/aid/store.js +17 -13
- package/dist/aun/group/history.js +303 -0
- package/dist/aun/group/identity.js +43 -0
- package/dist/aun/group/index.js +5 -0
- package/dist/aun/{msg/group.js → group/operations.js} +162 -39
- package/dist/aun/{menu-client.js → menu/client.js} +85 -6
- package/dist/aun/menu/index.js +2 -0
- package/dist/aun/menu/transport.js +49 -0
- package/dist/aun/msg/index.js +2 -1
- package/dist/aun/msg/managed-operation.js +85 -19
- package/dist/aun/msg/mention-schema.js +51 -0
- package/dist/aun/msg/p2p.js +19 -9
- package/dist/aun/msg/upload.js +43 -80
- package/dist/aun/outbox.js +29 -7
- package/dist/aun/rpc/client.js +1 -0
- package/dist/aun/storage/client.js +39 -50
- package/dist/channels/aun.js +842 -318
- package/dist/channels/daemon.js +10 -6
- package/dist/cli/agent-command.js +212 -89
- package/dist/cli/agent-create.js +626 -11
- package/dist/cli/agent.js +125 -13
- package/dist/cli/aun-commands.js +487 -337
- package/dist/cli/bench.js +20 -20
- package/dist/cli/config.js +55 -33
- package/dist/cli/contact.js +72 -15
- package/dist/cli/ctl-command.js +24 -24
- package/dist/cli/daemon-commands.js +140 -63
- package/dist/cli/diag.js +31 -0
- package/dist/cli/fs-command.js +70 -70
- package/dist/cli/handoff-command.js +46 -14
- package/dist/cli/index.js +91 -79
- package/dist/cli/init.js +34 -1
- package/dist/cli/link-rules.js +21 -21
- package/dist/cli/managed-command-guard.js +5 -1
- package/dist/cli/menu-client.js +51 -32
- package/dist/cli/model.js +3 -3
- package/dist/cli/net-check.js +22 -22
- package/dist/cli/queue-command.js +31 -31
- package/dist/cli/response.js +32 -32
- package/dist/cli/restart-monitor.js +103 -42
- package/dist/cli/stats.js +51 -51
- package/dist/cli/task-command.js +59 -0
- package/dist/cli/task-context.js +97 -49
- package/dist/cli/trigger-command.js +74 -64
- package/dist/config/builtin-roles.js +11 -0
- package/dist/config/config-field-policy.js +11 -0
- package/dist/config/config-manager.js +32 -4
- package/dist/config/config-operation-service.js +160 -0
- package/dist/config/contact-book-store.js +1 -1
- package/dist/config/contact-book.js +1 -1
- package/dist/config/contact-operation-service.js +97 -8
- package/dist/config/peer-role-resolver.js +1 -1
- package/dist/config/resolved-config-op.js +30 -7
- package/dist/config-store.js +1 -1
- package/dist/core/agent-application-service.js +7 -1
- package/dist/core/audit/event-key.js +17 -2
- package/dist/core/audit/log-integrity.js +34 -8
- package/dist/core/auth/agent-delegation.js +48 -14
- package/dist/core/auth/auth-gateway.js +2 -0
- package/dist/core/auth/authorization-audit.js +53 -49
- package/dist/core/auth/operation-authorizer.js +90 -7
- package/dist/core/auth/operation-catalog.js +145 -4
- package/dist/core/auth/remote-access-store.js +155 -10
- package/dist/core/bootstrap-messages.js +66 -7
- package/dist/core/bootstrap-service.js +111 -20
- package/dist/core/command/agent-control.js +88 -7
- package/dist/core/command/agent-storage-menu.js +443 -0
- package/dist/core/command/cli-intent-parser.js +19 -0
- package/dist/core/command/command-handler.js +159 -65
- package/dist/core/command/data-root-resolver.js +273 -0
- package/dist/core/command/diag-service.js +118 -0
- package/dist/core/command/group-menu.js +7 -2
- package/dist/core/command/menu-catalog.js +46 -7
- package/dist/core/command/menu-handler.js +392 -100
- package/dist/core/command/menu-protocol.js +45 -6
- package/dist/core/command/menu-token-store.js +41 -8
- package/dist/core/command/role-menu.js +2 -2
- package/dist/core/command/slash-gate.js +34 -4
- package/dist/core/command/slash-handler.js +123 -43
- package/dist/core/event-catalog.js +4 -0
- package/dist/core/evolagent-registry.js +28 -2
- package/dist/core/group/invite-service.js +924 -0
- package/dist/core/handoff/runtime.js +205 -27
- package/dist/core/handoff/store.js +193 -4
- package/dist/core/interaction-router.js +22 -8
- package/dist/core/message/im-renderer.js +146 -34
- package/dist/core/message/message-bridge.js +163 -20
- package/dist/core/message/message-log.js +5 -3
- package/dist/core/message/message-queue.js +99 -41
- package/dist/core/message/message-utils.js +1 -0
- package/dist/core/message/response-engine.js +755 -144
- package/dist/core/model/catalog-service.js +79 -49
- package/dist/core/model/context-window-suffix.js +33 -0
- package/dist/core/model/model-catalog.js +1 -1
- package/dist/core/model/model-permission.js +12 -3
- package/dist/core/permission/approval-gateway.js +36 -3
- package/dist/core/permission/ec-command-parser.js +112 -41
- package/dist/core/permission/protected-paths.js +134 -16
- package/dist/core/permission/sandbox-runtime.js +108 -17
- package/dist/core/permission/tool-error-code.js +15 -0
- package/dist/core/permission/tool-policy.js +9 -8
- package/dist/core/relation/peer-identity.js +57 -6
- package/dist/core/relation/shared-data.js +106 -0
- package/dist/core/role/runtime-policy.js +64 -0
- package/dist/core/runtime-lock.js +10 -26
- package/dist/core/session/runner-task-history.js +170 -0
- package/dist/core/session/session-manager.js +34 -6
- package/dist/core/session/session-mapper.js +41 -0
- package/dist/core/session/session-turn-coordinator.js +37 -7
- package/dist/core/session/session-turns.js +48 -7
- package/dist/core/task/task-recovery-service.js +176 -0
- package/dist/core/task/task-resume-operation.js +32 -0
- package/dist/eck/group-rules-sync.js +5 -3
- package/dist/eck/kit-renderer.js +1 -0
- package/dist/index.js +588 -217
- package/dist/ipc.js +193 -15
- package/dist/paths.js +17 -4
- package/dist/product.js +2 -0
- package/dist/response-system/engines/v1/proactive-flow.js +59 -2
- package/dist/stats/billing.js +41 -15
- package/dist/stats/db.js +159 -159
- package/dist/stats/eck-vars.js +9 -9
- package/dist/stats/price-resolver.js +28 -10
- package/dist/stats/query.js +139 -139
- package/dist/stats/role-budget.js +6 -6
- package/dist/stats/writer.js +51 -51
- package/dist/trigger/event-source.js +19 -0
- package/dist/trigger/feedback.js +233 -40
- package/dist/trigger/parser.js +55 -5
- package/dist/trigger/patch.js +9 -0
- package/dist/trigger/scheduler.js +30 -4
- package/dist/trigger/validation.js +20 -3
- package/dist/utils/cross-platform.js +30 -1
- package/dist/utils/ecweb-utils.js +1 -0
- package/dist/utils/error-dict.json +160 -160
- package/dist/utils/error-utils.js +61 -2
- package/dist/utils/evolcore-version.js +129 -0
- package/dist/utils/logger.js +26 -14
- package/dist/utils/macos-autostart.js +22 -22
- package/dist/utils/model-prices.jsonl +23 -23
- package/dist/utils/npm-ops.js +176 -35
- package/dist/utils/tool-summary.js +59 -3
- package/dist/utils/welcome.js +196 -23
- package/ecagent/LICENSE +21 -21
- package/ecagent/NOTICE +11 -11
- package/ecagent/README.md +61 -61
- package/ecagent/dist/harness/agent-harness.js +3 -0
- package/ecagent/dist/harness/compaction/branch-summarization.js +30 -30
- package/ecagent/dist/harness/compaction/compaction.js +83 -83
- package/ecagent/dist/harness/messages.js +7 -7
- package/ecagent/dist/harness/session/jsonl-storage.js +21 -2
- package/kits/docs/GUIDE.md +20 -20
- package/kits/docs/INDEX.md +60 -66
- package/kits/docs/aun/CHEATSHEET.md +19 -19
- package/kits/docs/aun/SYNC_PROTOCOL.md +15 -15
- package/kits/docs/channels/aun.md +69 -56
- package/kits/docs/channels/feishu.md +56 -56
- package/kits/docs/context-assembly.md +379 -367
- package/kits/docs/eck_templates/GUIDE.template.md +22 -22
- package/kits/docs/eck_templates/INDEX.template.md +28 -28
- package/kits/docs/eck_templates/path-registry.template.md +33 -33
- package/kits/docs/eck_templates/runtime.template.md +19 -19
- package/kits/docs/evolcore/INDEX.md +76 -71
- package/kits/docs/evolcore/agent-create.md +202 -165
- package/kits/docs/evolcore/agent.md +99 -67
- package/kits/docs/evolcore/aid.md +68 -60
- package/kits/docs/evolcore/codex-windows-sandbox.md +146 -146
- package/kits/docs/evolcore/config.md +241 -195
- package/kits/docs/evolcore/contact.md +75 -68
- package/kits/docs/evolcore/ctl.md +46 -46
- package/kits/docs/evolcore/event.md +216 -216
- package/kits/docs/evolcore/fs-architecture.md +1215 -1215
- package/kits/docs/evolcore/fs.md +110 -110
- package/kits/docs/evolcore/group-collaboration.md +244 -244
- package/kits/docs/evolcore/group-fs.md +17 -17
- package/kits/docs/evolcore/group-rules.md +251 -251
- package/kits/docs/evolcore/group.md +267 -152
- package/kits/docs/evolcore/menu-client.md +58 -34
- package/kits/docs/evolcore/model.md +50 -50
- package/kits/docs/evolcore/msg.md +169 -165
- package/kits/docs/evolcore/response.md +75 -75
- package/kits/docs/evolcore/rpc.md +37 -37
- package/kits/docs/evolcore/self-summary.md +29 -29
- package/kits/docs/evolcore/stats.md +83 -83
- package/kits/docs/evolcore/storage.md +53 -50
- package/kits/docs/evolcore/task.md +14 -0
- package/kits/docs/evolcore/trigger.md +623 -575
- package/kits/docs/identity/AID_PROFILE_SPEC.md +26 -26
- package/kits/docs/identity/PATH_OPS.md +16 -16
- package/kits/docs/identity/ROLE_DETAIL.md +25 -25
- package/kits/docs/identity/identity-tools.md +26 -26
- package/kits/docs/path-registry.md +62 -62
- package/kits/docs/prompt-loading-architecture.md +269 -269
- package/kits/docs/venues/aun-group.md +45 -45
- package/kits/docs/venues/aun-private.md +10 -10
- package/kits/docs/venues/client-desktop.md +10 -10
- package/kits/docs/venues/client-mobile.md +10 -10
- package/kits/docs/venues/feishu-group.md +13 -13
- package/kits/docs/venues/feishu-private.md +9 -9
- package/kits/docs/venues/group.md +42 -25
- package/kits/docs/venues/private.md +10 -10
- package/kits/eck_manifest.auxiliary.json +43 -43
- package/kits/eck_manifest.json +217 -190
- package/kits/eck_message_manifest.json +74 -74
- package/kits/migrations/README-role-config-v4.md +32 -32
- package/kits/migrations/migrate-contact-book-v2.mjs +748 -748
- package/kits/migrations/migrate-role-config-v4.mjs +614 -614
- package/kits/migrations/migrate-role-config-v5.mjs +365 -365
- package/kits/migrations/rename-config-file.mjs +99 -99
- package/kits/rules/01-overview.md +166 -162
- package/kits/rules/02-navigation.md +96 -96
- package/kits/rules/03-identity.md +36 -36
- package/kits/rules/04-relation.md +76 -75
- package/kits/rules/05-venue.md +60 -60
- package/kits/rules/06-channel.md +65 -63
- package/kits/schemas/_meta.json +53 -53
- package/kits/schemas/agent-config.schema.1.json +177 -177
- package/kits/schemas/agent-config.schema.10.json +395 -395
- package/kits/schemas/agent-config.schema.11.json +421 -421
- package/kits/schemas/agent-config.schema.12.json +451 -427
- package/kits/schemas/agent-config.schema.2.json +239 -239
- package/kits/schemas/agent-config.schema.3.json +119 -119
- package/kits/schemas/agent-config.schema.4.json +208 -208
- package/kits/schemas/agent-config.schema.5.json +326 -326
- package/kits/schemas/agent-config.schema.6.json +322 -322
- package/kits/schemas/agent-config.schema.7.json +303 -303
- package/kits/schemas/agent-config.schema.8.json +304 -304
- package/kits/schemas/agent-config.schema.9.json +364 -364
- package/kits/schemas/contact-book.schema.1.json +36 -36
- package/kits/schemas/contact-book.schema.2.json +43 -43
- package/kits/schemas/contact-book.schema.3.json +67 -67
- package/kits/schemas/daemon.schema.1.json +91 -91
- package/kits/schemas/daemon.schema.2.json +101 -101
- package/kits/schemas/daemon.schema.3.json +123 -123
- package/kits/schemas/daemon.schema.4.json +136 -136
- package/kits/schemas/daemon.schema.5.json +135 -135
- package/kits/schemas/daemon.schema.6.json +131 -131
- package/kits/schemas/defaults.schema.1.json +81 -81
- package/kits/schemas/defaults.schema.2.json +85 -85
- package/kits/schemas/defaults.schema.3.json +73 -73
- package/kits/schemas/defaults.schema.4.json +107 -107
- package/kits/schemas/defaults.schema.5.json +119 -119
- package/kits/schemas/menu-exec-schema-commands.md +208 -208
- package/kits/schemas/migrations/README.md +30 -30
- package/kits/schemas/relation-config.schema.1.json +158 -158
- package/kits/schemas/relation-config.schema.2.json +73 -73
- package/kits/schemas/relation-config.schema.3.json +50 -50
- package/kits/schemas/relation-config.schema.4.json +47 -47
- package/kits/schemas/relation-config.schema.5.json +47 -47
- package/kits/schemas/relation-config.schema.6.json +46 -46
- package/kits/schemas/relation-config.schema.7.json +59 -59
- package/kits/schemas/relation-config.schema.8.json +103 -103
- package/kits/schemas/role-config.schema.1.json +215 -201
- package/kits/schemas/role-registry.schema.1.json +35 -35
- package/kits/schemas/single-session.schema.1.json +31 -31
- package/kits/schemas/single-session.schema.2.json +57 -57
- package/kits/schemas/single-session.schema.3.json +32 -32
- package/kits/templates/bootstrap-welcome.md +17 -17
- package/kits/templates/message-fragments/handoff-context-to-target.md +9 -9
- package/kits/templates/message-fragments/handoff-request-to-target.md +19 -19
- package/kits/templates/message-fragments/handoff-response-to-origin.md +9 -9
- package/kits/templates/message-fragments/inject-default.md +2 -2
- package/kits/templates/message-fragments/item.md +2 -2
- package/kits/templates/roles/admin.json +92 -92
- package/kits/templates/roles/member.json +101 -96
- package/kits/templates/roles/owner.json +9 -9
- package/kits/templates/roles/visitor.json +90 -85
- package/kits/templates/system-fragments/baseagent.md +14 -14
- package/kits/templates/system-fragments/bootstrap.md +53 -34
- package/kits/templates/system-fragments/channel.md +28 -64
- package/kits/templates/system-fragments/commands.md +36 -28
- package/kits/templates/system-fragments/group-unread-history.md +7 -0
- package/kits/templates/system-fragments/identity.md +13 -13
- package/kits/templates/system-fragments/relation.md +19 -19
- package/kits/templates/system-fragments/reply.md +56 -0
- package/kits/templates/system-fragments/session.md +59 -59
- package/kits/templates/system-fragments/venue.md +31 -31
- package/package.json +104 -98
- package/dist/aun/group-identity.js +0 -9
- /package/dist/aun/{group-fs-download.js → group/fs-download.js} +0 -0
- /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,
|
|
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
|
-
|
|
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
|
|
224
|
+
/** Return the stable temporary root for a managed session, if available. */
|
|
179
225
|
getManagedSessionTempDir(session) {
|
|
180
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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.
|
|
873
|
+
const handled = await this.interactionRouter.handleAsync({
|
|
823
874
|
type: 'interaction.response',
|
|
824
875
|
id: pendingId,
|
|
825
|
-
action:
|
|
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
|
-
|
|
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
|
-
|
|
1681
|
-
|
|
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
|
-
|
|
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
|
|
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'
|
|
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
|
|
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)
|