evolcore 0.0.37 → 0.0.39

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 (37) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/agents/codex-runner.js +3 -3
  3. package/dist/aun/aid/agentmd.js +21 -0
  4. package/dist/aun/aid/client.js +1 -1
  5. package/dist/aun/aid/ownership-operation.js +34 -9
  6. package/dist/cli/agent-create.js +7 -2
  7. package/dist/cli/agent.js +30 -37
  8. package/dist/cli/aid-bind-command.js +12 -1
  9. package/dist/cli/aun-commands.js +31 -23
  10. package/dist/cli/config.js +15 -18
  11. package/dist/cli/contact.js +9 -12
  12. package/dist/cli/ctl-command.js +3 -3
  13. package/dist/cli/diag.js +7 -3
  14. package/dist/cli/fs-command.js +5 -4
  15. package/dist/cli/handoff-command.js +11 -11
  16. package/dist/cli/help.js +18 -0
  17. package/dist/cli/init-channel.js +2 -1
  18. package/dist/cli/memory-command.js +14 -13
  19. package/dist/cli/model.js +5 -4
  20. package/dist/cli/queue-command.js +3 -3
  21. package/dist/cli/response.js +5 -4
  22. package/dist/cli/skill-command.js +13 -13
  23. package/dist/cli/task-command.js +3 -3
  24. package/dist/cli/thread-command.js +5 -3
  25. package/dist/cli/trigger-command.js +3 -3
  26. package/dist/cli/version.js +6 -2
  27. package/dist/core/auth/operation-catalog.js +1 -1
  28. package/dist/core/bootstrap-service.js +20 -12
  29. package/dist/core/command/cli-intent-parser.js +5 -2
  30. package/dist/core/command/command-handler.js +13 -4
  31. package/dist/core/command/menu-handler.js +2 -2
  32. package/dist/core/ownership/owner-resolver.js +121 -2
  33. package/dist/core/permission/protected-paths.js +51 -0
  34. package/dist/utils/npm-ops.js +22 -6
  35. package/dist/utils/welcome.js +18 -24
  36. package/kits/docs/evolcore/aid.md +33 -0
  37. package/package.json +3 -3
package/CHANGELOG.md CHANGED
@@ -5,6 +5,28 @@
5
5
 
6
6
  ## Unreleased
7
7
 
8
+ ## 0.0.39 (2026-10-24)
9
+
10
+ ### Ownership 与 Agent 初始化
11
+
12
+ - 支持通过 `ec aid bind status` 查看经 SDK 验证的 Ownership 邀约,并按具体操作 ID 接受或拒绝。
13
+ - 按绑定任务上下文校验审批结果,避免处理不相关或已失效的邀约。
14
+ - Bootstrap 会验证本地 `agent.md`;已验签的名片不再重复发布,无效或未签名内容会阻止不安全的重发。
15
+ - 更新 AUN Owner 欢迎文案,更清晰地介绍 Agent 可提供的帮助与个性化设置。
16
+
17
+ ### 权限与兼容性
18
+
19
+ - 优化 Codex 在 Linux 上的文件权限规则,减少被父目录拒绝规则覆盖的冗余子规则,同时保留必要的读写例外。
20
+ - 将 AUN SDK 最低兼容版本提升至 `0.5.23`,以支持 Ownership 邀约审批。
21
+ - 改进 daemon IPC 连接失败诊断,相关命令现在会保留具体的连接错误信息。
22
+
23
+ ## 0.0.38 (2026-10-24)
24
+
25
+ ### npm 升级稳定性
26
+
27
+ - 修复 npm 升级在 registry 元数据暂未同步时误报目标版本不存在的问题。
28
+ - 改进升级失败诊断,保留 npm 错误码和具体错误信息,便于定位网络、权限和版本解析问题。
29
+
8
30
  ## 0.0.37 (2026-10-24)
9
31
 
10
32
  ### 升级与重启稳定性
@@ -6,7 +6,7 @@ import { requestDangerousCommandPermission } from '../core/permission/approval-g
6
6
  import { checkReadonly, checkDangerousCommand, evaluateToolPreflight } from '../core/permission/tool-policy.js';
7
7
  import { isShellToolName } from '../core/permission/tool-canonical.js';
8
8
  import { normalizeExecutionPermissionMode, normalizePermissionMode, resolvePhaseOneExecutionSandbox } from '../core/permission/mode.js';
9
- import { assertWindowsCodexFilesystemRuleBudget, buildCodexProtectedFilesystemRules, getExistingRelationAttachmentDirs, isSameOrDescendant, resolveProtectedCandidate, } from '../core/permission/protected-paths.js';
9
+ import { assertWindowsCodexFilesystemRuleBudget, buildCodexProtectedFilesystemRules, compactCodexLinuxFilesystemRules, getExistingRelationAttachmentDirs, isSameOrDescendant, resolveProtectedCandidate, } from '../core/permission/protected-paths.js';
10
10
  import { CODEX_THREAD_ACTIVE_WRITER, CodexAppServerClient, } from './codex/app-server-client.js';
11
11
  import { resolveOpenaiConfig, resolveCodexCliPath, resolveCodexPowerShellShimPath, } from './baseagent.js';
12
12
  import { logger } from '../utils/logger.js';
@@ -1428,7 +1428,7 @@ export class CodexRunner {
1428
1428
  onlyOtherAgents: true,
1429
1429
  }))
1430
1430
  relationAttachmentDenies[directory] = 'deny';
1431
- const filesystem = {
1431
+ const filesystem = compactCodexLinuxFilesystemRules({
1432
1432
  ...buildCodexProtectedFilesystemRules(resolveRoot(), {
1433
1433
  selfAid: this.resolvedConfig.agentAid,
1434
1434
  denyLClassRead: mode === 'readonly',
@@ -1455,7 +1455,7 @@ export class CodexRunner {
1455
1455
  [path.join(managedTempDir, 'locks')]: 'write',
1456
1456
  [path.join(managedTempDir, 'locks') + '/**']: 'write',
1457
1457
  } : {}),
1458
- };
1458
+ });
1459
1459
  // Codex resolves this complete profile before serializing the Windows
1460
1460
  // helper payload. Check after all runner-owned additions, not merely the
1461
1461
  // protected-path base projection, so Git and managed-temp rules cannot
@@ -538,6 +538,27 @@ function verifyLocal(store, aid, content) {
538
538
  return { status: 'invalid', reason: `certificate not available: ${String(e?.message || e).slice(0, 100)}` };
539
539
  }
540
540
  }
541
+ /** Verify a locally stored agent.md without contacting the AUN gateway. */
542
+ export async function verifyLocalAgentMd(aid, opts = {}) {
543
+ const aunPath = resolveAgentMdAunPath(opts);
544
+ const localPath = agentMdPath(aid, aunPath);
545
+ if (!fs.existsSync(localPath))
546
+ return { status: 'missing' };
547
+ const store = opts.store ?? await getAidStore({ slotId: SLOT.cli, aunPath });
548
+ const ownStore = !opts.store;
549
+ try {
550
+ const content = fs.readFileSync(localPath, 'utf-8');
551
+ const result = verifyLocal(store, aid, content);
552
+ return { status: result.status, ...(result.reason ? { reason: result.reason } : {}) };
553
+ }
554
+ finally {
555
+ if (ownStore)
556
+ try {
557
+ store.close();
558
+ }
559
+ catch { /* ignore */ }
560
+ }
561
+ }
541
562
  export async function agentmdGet(aid, opts) {
542
563
  const aunPath = resolveAgentMdAunPath(opts);
543
564
  const store = opts?.store ?? await getAidStore({ slotId: SLOT.cli, aunPath });
@@ -39,7 +39,7 @@ export function suppressSdkLogs() {
39
39
  };
40
40
  }
41
41
  // ==================== SDK package ====================
42
- export const MIN_AUN_CORE_SDK = [0, 5, 22];
42
+ export const MIN_AUN_CORE_SDK = [0, 5, 23];
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,6 +1,8 @@
1
1
  import { isValidAid } from './validation.js';
2
2
  import { ownerResolver, OwnershipError } from '../../core/ownership/owner-resolver.js';
3
3
  import { logger } from '../../utils/logger.js';
4
+ import { MAIN_CLI_BIN } from '../../product.js';
5
+ const OWNERSHIP_OPERATION_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
4
6
  export function ownershipFailure(error) {
5
7
  const details = error && typeof error === 'object' ? error : {};
6
8
  return {
@@ -14,22 +16,42 @@ export function ownershipFailure(error) {
14
16
  export function parseOwnershipCommand(argv) {
15
17
  const args = argv[0] === 'aid' ? argv.slice(1) : [...argv];
16
18
  if (args[0] !== 'bind' || !args[1]) {
17
- throw new OwnershipError('INVALID_ARGUMENT', 'Use ec aid bind <ownerAid> or ec aid bind status');
19
+ throw new OwnershipError('INVALID_ARGUMENT', `Use ${MAIN_CLI_BIN} aid bind <ownerAid>, status, accept, or reject`);
18
20
  }
19
- const action = args[1] === 'status' ? 'status' : 'bind';
21
+ const action = ['status', 'accept', 'reject'].includes(args[1]) ? args[1] : 'bind';
20
22
  if (action === 'bind' && !isValidAid(args[1]))
21
23
  throw new OwnershipError('INVALID_AID', 'A valid owner AID is required');
24
+ if ((action === 'accept' || action === 'reject') && !OWNERSHIP_OPERATION_ID.test(args[2] ?? '')) {
25
+ throw new OwnershipError('INVALID_OPERATION', 'A valid ownership operation ID is required');
26
+ }
22
27
  let subjectAid;
28
+ let reason;
23
29
  let formatSeen = false;
24
- for (let index = 2; index < args.length; index += 2) {
25
- if (args[index] === '--subject' && !subjectAid && isValidAid(args[index + 1] ?? ''))
26
- subjectAid = args[index + 1];
27
- else if (args[index] === '--format' && args[index + 1] === 'json' && !formatSeen)
30
+ const positionalEnd = action === 'bind' || action === 'status' ? 2 : 3;
31
+ for (let index = positionalEnd; index < args.length; index += 2) {
32
+ const flag = args[index];
33
+ const value = args[index + 1];
34
+ if (flag === '--subject' && !subjectAid && isValidAid(value ?? '')) {
35
+ subjectAid = value;
36
+ }
37
+ else if (flag === '--format' && value === 'json' && !formatSeen) {
28
38
  formatSeen = true;
29
- else
30
- throw new OwnershipError('INVALID_ARGUMENT', 'Only one --subject <subjectAid> and --format json are supported');
39
+ }
40
+ else if (flag === '--reason' && action === 'reject' && reason === undefined
41
+ && value !== undefined && !value.startsWith('--')) {
42
+ reason = value;
43
+ }
44
+ else {
45
+ throw new OwnershipError('INVALID_ARGUMENT', 'Supported options are --subject <subjectAid>, --reason <text>, and --format json');
46
+ }
31
47
  }
32
- return action === 'status' ? { action, subjectAid } : { action, subjectAid, ownerAid: args[1] };
48
+ if (action === 'status')
49
+ return { action, subjectAid };
50
+ if (action === 'accept')
51
+ return { action, operationId: args[2], subjectAid };
52
+ if (action === 'reject')
53
+ return { action, operationId: args[2], ...(reason !== undefined ? { reason } : {}), subjectAid };
54
+ return { action, subjectAid, ownerAid: args[1] };
33
55
  }
34
56
  export async function executeOwnershipCommand(command, defaultSubjectAid) {
35
57
  const subjectAid = command.subjectAid ?? defaultSubjectAid;
@@ -39,6 +61,9 @@ export async function executeOwnershipCommand(command, defaultSubjectAid) {
39
61
  ownerResolver.assertLocalSubject(subjectAid);
40
62
  return ownerResolver.refresh(subjectAid);
41
63
  }
64
+ if (command.action === 'accept' || command.action === 'reject') {
65
+ return ownerResolver.decide(subjectAid, command.operationId, command.action, command.action === 'reject' ? command.reason : undefined);
66
+ }
42
67
  logger.info(`[ownership] bind requested subject=${subjectAid} owner=${command.ownerAid}`);
43
68
  try {
44
69
  ownerResolver.assertLocalSubject(subjectAid);
@@ -6,6 +6,7 @@ import { parse } from 'yaml';
6
6
  import { resolvePaths, aunPath as defaultAunPath, agentConfig, agentDataDir, agentPersonalDir, aidLocalDir, agentMdPath } from '../paths.js';
7
7
  import { loadDefaults, loadAgent, saveAgent, ensureAgentDirSkeleton } from '../config-store.js';
8
8
  import { ConfigTarget, write as cfgWrite, ensureFile as cfgEnsure, read as cfgRead } from '../config/config-manager.js';
9
+ import { daemonUnavailableMessage, queryDaemon } from './help.js';
9
10
  import { ipcQuery } from '../ipc.js';
10
11
  import { CONFIG_SCHEMA_VERSION } from '../types.js';
11
12
  import { ensureInitialRoleRegistry } from '../config/role-service.js';
@@ -1220,9 +1221,13 @@ export async function runInitializationCommand(args) {
1220
1221
  return initializationCommandResult(result);
1221
1222
  }
1222
1223
  const request = async (poll) => {
1223
- return await ipcQuery(resolvePaths().socket, {
1224
+ const { response, transportError } = await queryDaemon(resolvePaths().socket, {
1224
1225
  type: 'evolagent.initialize', argv, poll,
1225
- }, 10_000) ?? { ok: false, code: 'DAEMON_UNAVAILABLE', error: 'Initialization requires a running daemon' };
1226
+ }, 10_000);
1227
+ return response ?? {
1228
+ ok: false, code: 'DAEMON_UNAVAILABLE',
1229
+ error: daemonUnavailableMessage(transportError, 'Initialization requires a running daemon'),
1230
+ };
1226
1231
  };
1227
1232
  let result = await request(false);
1228
1233
  if (parsed.dryRun)
package/dist/cli/agent.js CHANGED
@@ -8,6 +8,7 @@ import { initConfigManager } from '../config/config-manager.js';
8
8
  import { resolveConfigCommand } from '../config/resolved-config-op.js';
9
9
  import { executeResolvedConfigCommandAsync } from '../config/config-operation-service.js';
10
10
  import { ipcQuery, IpcTransportError } from '../ipc.js';
11
+ import { daemonUnavailableMessage, queryDaemon } from './help.js';
11
12
  import { CONFIG_SCHEMA_VERSION } from '../types.js';
12
13
  import { ensureInitialRoleRegistry } from '../config/role-service.js';
13
14
  import { agentProjectRootFromDefaults, deriveAgentProjectPath } from '../utils/project-path.js';
@@ -30,22 +31,20 @@ export async function runManagedAgentOperation(argv, timeoutMs = 60_000) {
30
31
  if (!delegationToken) {
31
32
  return { ok: false, code: 'DELEGATION_REQUIRED', error: `${AGENT_DELEGATION_TOKEN_ENV} is not set for the active task` };
32
33
  }
33
- try {
34
- const response = await ipcQuery(resolvePaths().socket, {
35
- type: 'agent.op',
36
- argv: ['agent', ...argv],
37
- sessionId,
38
- delegationToken,
39
- }, timeoutMs);
40
- if (!response)
41
- return { ok: false, code: 'DAEMON_UNAVAILABLE', error: 'Unable to connect to the evolcore daemon' };
42
- if (!response.ok)
43
- return { ok: false, code: response.code, error: response.error || 'agent operation failed', ...(response.data ? { data: response.data } : {}) };
44
- return response.result ?? { ok: true, ...(response.data ?? {}) };
45
- }
46
- catch (error) {
47
- return { ok: false, code: 'DAEMON_UNAVAILABLE', error: error instanceof Error ? error.message : String(error) };
48
- }
34
+ const { response, transportError } = await queryDaemon(resolvePaths().socket, {
35
+ type: 'agent.op',
36
+ argv: ['agent', ...argv],
37
+ sessionId,
38
+ delegationToken,
39
+ }, timeoutMs);
40
+ if (!response)
41
+ return {
42
+ ok: false, code: 'DAEMON_UNAVAILABLE',
43
+ error: daemonUnavailableMessage(transportError, 'Unable to connect to the evolcore daemon'),
44
+ };
45
+ if (!response.ok)
46
+ return { ok: false, code: response.code, error: response.error || 'agent operation failed', ...(response.data ? { data: response.data } : {}) };
47
+ return response.result ?? { ok: true, ...(response.data ?? {}) };
49
48
  }
50
49
  function getAgentMdPath(aid) {
51
50
  return getAgentMdPathFromPaths(aid);
@@ -761,29 +760,23 @@ export async function agentReady(aid, commandArgs) {
761
760
  };
762
761
  }
763
762
  const p = resolvePaths();
764
- try {
765
- const delegationToken = managedSessionId ? readDelegationCredential() : undefined;
766
- if (managedSessionId && !delegationToken) {
767
- return { ok: false, code: 'DELEGATION_REQUIRED', error: `${AGENT_DELEGATION_TOKEN_ENV} is not set for the active task` };
768
- }
769
- const result = await ipcQuery(p.socket, {
770
- type: 'evolagent.bootstrapComplete',
771
- aid,
772
- ...(managedSessionId ? { argv: ['agent', ...(commandArgs ?? ['ready', aid])] } : {}),
773
- ...(managedSessionId ? { sessionId: managedSessionId, delegationToken } : {}),
774
- }, 30_000);
775
- if (!result)
776
- return { ok: false, code: 'DAEMON_UNAVAILABLE', error: 'Unable to connect to the EvolCore daemon; agent ready requires daemon IPC' };
777
- if (!result.ok) {
778
- return { ok: false, code: result.code, error: result.error || 'Failed to complete bootstrap' };
779
- }
780
- return { ...result, ok: true, aid, reloaded: result.reloaded === true };
763
+ const delegationToken = managedSessionId ? readDelegationCredential() : undefined;
764
+ if (managedSessionId && !delegationToken) {
765
+ return { ok: false, code: 'DELEGATION_REQUIRED', error: `${AGENT_DELEGATION_TOKEN_ENV} is not set for the active task` };
781
766
  }
782
- catch (e) {
767
+ const { response: result, transportError } = await queryDaemon(p.socket, {
768
+ type: 'evolagent.bootstrapComplete',
769
+ aid,
770
+ ...(managedSessionId ? { argv: ['agent', ...(commandArgs ?? ['ready', aid])] } : {}),
771
+ ...(managedSessionId ? { sessionId: managedSessionId, delegationToken } : {}),
772
+ }, 30_000);
773
+ if (!result)
783
774
  return {
784
- ok: false,
785
- code: 'DAEMON_UNAVAILABLE',
786
- error: e instanceof Error ? e.message : 'Unable to connect to the EvolCore daemon',
775
+ ok: false, code: 'DAEMON_UNAVAILABLE',
776
+ error: daemonUnavailableMessage(transportError, 'Unable to connect to the EvolCore daemon; agent ready requires daemon IPC'),
787
777
  };
778
+ if (!result.ok) {
779
+ return { ok: false, code: result.code, error: result.error || 'Failed to complete bootstrap' };
788
780
  }
781
+ return { ...result, ok: true, aid, reloaded: result.reloaded === true };
789
782
  }
@@ -2,9 +2,15 @@ import { ipcQuery } from '../ipc.js';
2
2
  import { resolvePaths } from '../paths.js';
3
3
  import { parseOwnershipCommand, ownershipFailure } from '../aun/aid/ownership-operation.js';
4
4
  import { readDelegationCredential } from '../core/auth/agent-delegation.js';
5
+ import { MAIN_CLI_BIN } from '../product.js';
5
6
  export async function cmdAidBind(args) {
6
7
  if (args.includes('--help') || args.includes('-h')) {
7
- console.log('用法: ec aid bind <ownerAid> [--subject <subjectAid>] [--format json]\nec aid bind status [--subject <subjectAid>] [--format json]');
8
+ console.log([
9
+ `用法: ${MAIN_CLI_BIN} aid bind <ownerAid> [--subject <subjectAid>] [--format json]`,
10
+ `${MAIN_CLI_BIN} aid bind status [--subject <subjectAid>] [--format json]`,
11
+ `${MAIN_CLI_BIN} aid bind accept <operationId> [--subject <subjectAid>] [--format json]`,
12
+ `${MAIN_CLI_BIN} aid bind reject <operationId> [--reason <text>] [--subject <subjectAid>] [--format json]`,
13
+ ].join('\n'));
8
14
  return;
9
15
  }
10
16
  const formatJson = args.includes('--format') && args[args.indexOf('--format') + 1] === 'json';
@@ -32,6 +38,11 @@ export async function cmdAidBind(args) {
32
38
  console.log(`运行态同步: ${state.synchronization.status}`);
33
39
  if (state.task)
34
40
  console.log(`绑定任务: ${state.task.operation_id} (${state.task.status}/${state.task.step})`);
41
+ if (state.decisionTask)
42
+ console.log(`审批任务: ${state.decisionTask.operation_id} (${state.decisionTask.status}/${state.decisionTask.step})`);
43
+ for (const request of state.requests ?? []) {
44
+ console.log(`待确认邀约: ${request.operation_id} (sub=${request.sub_aid}, owner=${request.owner_aid}, 本端=${request.local_role})`);
45
+ }
35
46
  if (state.requestedOwnerAid)
36
47
  console.log(`请求绑定: ${state.requestedOwnerAid}`);
37
48
  if (state.requestStatus)
@@ -4,7 +4,7 @@ import crypto from 'crypto';
4
4
  import { agentMdPath, resolvePaths, resolveRoot } from '../paths.js';
5
5
  import { isExplicitGroupId, normalizeGroupAid, sameGroupAid } from '../aun/group/index.js';
6
6
  import { getArgValue, isHelpFlag, wantsHelp } from './help.js';
7
- import { ipcQuery } from '../ipc.js';
7
+ import { daemonUnavailableMessage, queryDaemon } from './help.js';
8
8
  import { isValidAid as validSendAid } from '../aun/aid/validation.js';
9
9
  import { AGENT_DELEGATION_TOKEN_ENV, readDelegationCredential } from '../core/auth/agent-delegation.js';
10
10
  import { isManagementRole } from '../config/builtin-roles.js';
@@ -137,14 +137,15 @@ async function runManagedAid(args, formatJson) {
137
137
  if (requiresSelfAid && runtime?.selfAid && parsed.command.aid !== runtime.selfAid.replace(/^@/, '')) {
138
138
  failManagedAid(formatJson, 'SCOPE_MISMATCH', `托管任务只能操作当前 self AID:${runtime.selfAid}`);
139
139
  }
140
- const response = await ipcQuery(resolvePaths().socket, {
140
+ const { response, transportError } = await queryDaemon(resolvePaths().socket, {
141
141
  type: 'aid.op',
142
142
  argv: ['aid', ...args],
143
143
  sessionId,
144
144
  delegationToken,
145
145
  }, 30_000);
146
- if (!response)
147
- failManagedAid(formatJson, 'DAEMON_UNAVAILABLE', 'Unable to connect to the evolcore daemon');
146
+ if (!response) {
147
+ failManagedAid(formatJson, 'DAEMON_UNAVAILABLE', daemonUnavailableMessage(transportError, 'Unable to connect to the evolcore daemon'));
148
+ }
148
149
  if (!response.ok || !response.result) {
149
150
  const error = response.error || 'AID operation failed';
150
151
  const aid = args[0] === 'agentmd' ? args[2] : args[1];
@@ -220,14 +221,15 @@ async function runManagedGroup(args, formatJson) {
220
221
  failManagedGroup(formatJson, parsed.code, parsed.reason);
221
222
  const runtime = await readBestTaskRuntimeContext();
222
223
  validateManagedGroupScope(parsed.command.from, parsed.command.groupId, runtime, formatJson);
223
- const response = await ipcQuery(resolvePaths().socket, {
224
+ const { response, transportError } = await queryDaemon(resolvePaths().socket, {
224
225
  type: 'group.op',
225
226
  argv: ['group', ...args],
226
227
  sessionId,
227
228
  delegationToken,
228
229
  }, 60_000);
229
- if (!response)
230
- failManagedGroup(formatJson, 'DAEMON_UNAVAILABLE', 'Unable to connect to the evolcore daemon');
230
+ if (!response) {
231
+ failManagedGroup(formatJson, 'DAEMON_UNAVAILABLE', daemonUnavailableMessage(transportError, 'Unable to connect to the evolcore daemon'));
232
+ }
231
233
  if (!response.ok || !response.result) {
232
234
  failManagedGroup(formatJson, response.code || 'GROUP_OPERATION_FAILED', response.error || 'Group operation failed');
233
235
  }
@@ -277,14 +279,15 @@ async function runManagedMsg(args, formatJson) {
277
279
  failManagedGroup(formatJson, 'SCOPE_MISMATCH', `只能读取当前 AUN 私聊对端:${runtime.channelId}`);
278
280
  }
279
281
  }
280
- const response = await ipcQuery(resolvePaths().socket, {
282
+ const { response, transportError } = await queryDaemon(resolvePaths().socket, {
281
283
  type: 'msg.op',
282
284
  argv: ['msg', ...args],
283
285
  sessionId,
284
286
  delegationToken,
285
287
  }, 30_000);
286
- if (!response)
287
- failManagedGroup(formatJson, 'DAEMON_UNAVAILABLE', 'Unable to connect to the evolcore daemon');
288
+ if (!response) {
289
+ failManagedGroup(formatJson, 'DAEMON_UNAVAILABLE', daemonUnavailableMessage(transportError, 'Unable to connect to the evolcore daemon'));
290
+ }
288
291
  if (!response.ok || !response.result) {
289
292
  failManagedGroup(formatJson, response.code || 'MSG_OPERATION_FAILED', response.error || 'Msg operation failed');
290
293
  }
@@ -469,6 +472,8 @@ Commands:
469
472
  avatar <aid> --file <path> | --url <https-url> 上传头像并更新 agent.md
470
473
  bind <ownerAid> [--subject <subjectAid>] 发起 Ownership 2.1 绑定
471
474
  bind status [--subject <subjectAid>] 核验协议 Owner、任务和同步状态
475
+ bind accept <operationId> [--subject <subjectAid>] 接受绑定邀约
476
+ bind reject <operationId> [--reason <text>] [--subject <subjectAid>] 拒绝绑定邀约
472
477
 
473
478
  Options:
474
479
  --format json 输出 JSON 格式
@@ -1159,7 +1164,7 @@ Options:
1159
1164
  console.error('用法: ec storage upload <aid> <local-file> <remote-path> [--public]');
1160
1165
  process.exit(1);
1161
1166
  }
1162
- const result = await ipcQuery(resolvePaths().socket, {
1167
+ const { response: result, transportError } = await queryDaemon(resolvePaths().socket, {
1163
1168
  type: 'storage.upload',
1164
1169
  argv: ['storage', ...args],
1165
1170
  aid,
@@ -1169,8 +1174,9 @@ Options:
1169
1174
  sessionId: process.env.EVOLCORE_SESSION_ID,
1170
1175
  delegationToken,
1171
1176
  }, null);
1172
- if (!result)
1173
- failManagedGroup(formatJson, 'DAEMON_UNAVAILABLE', 'Unable to connect to the evolcore daemon');
1177
+ if (!result) {
1178
+ failManagedGroup(formatJson, 'DAEMON_UNAVAILABLE', daemonUnavailableMessage(transportError, 'Unable to connect to the evolcore daemon'));
1179
+ }
1174
1180
  if (!result.ok)
1175
1181
  failManagedGroup(formatJson, result.code || 'STORAGE_UPLOAD_FAILED', result.error || 'Storage upload failed');
1176
1182
  if (formatJson)
@@ -1185,11 +1191,12 @@ Options:
1185
1191
  }
1186
1192
  return;
1187
1193
  }
1188
- const authorization = await ipcQuery(resolvePaths().socket, {
1194
+ const { response: authorization, transportError } = await queryDaemon(resolvePaths().socket, {
1189
1195
  type: 'storage.auth', argv: ['storage', ...args], operation, aid, sessionId: process.env.EVOLCORE_SESSION_ID, delegationToken,
1190
1196
  }, 10_000);
1191
- if (!authorization)
1192
- failManagedGroup(formatJson, 'DAEMON_UNAVAILABLE', 'Unable to connect to the evolcore daemon');
1197
+ if (!authorization) {
1198
+ failManagedGroup(formatJson, 'DAEMON_UNAVAILABLE', daemonUnavailableMessage(transportError, 'Unable to connect to the evolcore daemon'));
1199
+ }
1193
1200
  if (!authorization.ok)
1194
1201
  failManagedGroup(formatJson, authorization.code || 'STORAGE_AUTH_FAILED', authorization.error || 'Storage operation denied');
1195
1202
  if (sub === 'ls') {
@@ -1531,7 +1538,7 @@ async function applyCrossThreadSendEffects(input) {
1531
1538
  originThreadName,
1532
1539
  targetThreadName,
1533
1540
  });
1534
- const triggerRes = await ipcQuery(resolvePaths().socket, {
1541
+ const { response: triggerRes, transportError } = await queryDaemon(resolvePaths().socket, {
1535
1542
  type: 'trigger.create',
1536
1543
  definition: triggerDef,
1537
1544
  files: [],
@@ -1543,7 +1550,7 @@ async function applyCrossThreadSendEffects(input) {
1543
1550
  delegationToken: readDelegationCredential(),
1544
1551
  }, 30_000);
1545
1552
  if (!triggerRes?.ok) {
1546
- process.stderr.write(`⚠ Trigger 创建失败: ${triggerRes?.error ?? 'unknown'}(inbox 仍会写入)\n`);
1553
+ process.stderr.write(`⚠ Trigger 创建失败: ${triggerRes?.error ?? daemonUnavailableMessage(transportError, 'unknown')}(inbox 仍会写入)\n`);
1547
1554
  }
1548
1555
  else {
1549
1556
  // 以 daemon 落盘的结果为准(definition 已带 id,正常应与预设值相同;
@@ -1691,13 +1698,13 @@ Options:
1691
1698
  console.error(`request status is limited to the delegated self AID: ${runtime.selfAid}`);
1692
1699
  process.exit(1);
1693
1700
  }
1694
- const result = await ipcQuery(resolvePaths().socket, {
1701
+ const { response: result, transportError } = await queryDaemon(resolvePaths().socket, {
1695
1702
  type: 'aun-msg-request-get', aid, requestId,
1696
1703
  sessionId: process.env.EVOLCORE_SESSION_ID,
1697
1704
  delegationToken: readDelegationCredential(),
1698
1705
  }, 10_000);
1699
1706
  if (!result) {
1700
- console.error('unable to connect to the EvolCore daemon');
1707
+ console.error(daemonUnavailableMessage(transportError, 'unable to connect to the EvolCore daemon'));
1701
1708
  process.exit(1);
1702
1709
  }
1703
1710
  if (formatJson)
@@ -3388,12 +3395,13 @@ async function runManagedSend(argv, formatJson) {
3388
3395
  if (!delegationToken)
3389
3396
  failManagedGroup(formatJson, 'DELEGATION_REQUIRED', 'Managed send requires delegation');
3390
3397
  const runtime = await readBestTaskRuntimeContext();
3391
- const result = await ipcQuery(resolvePaths().socket, {
3398
+ const { response: result, transportError } = await queryDaemon(resolvePaths().socket, {
3392
3399
  type: 'aun-msg-send', argv, delegationToken,
3393
3400
  originSessionId: process.env.EVOLCORE_SESSION_ID, originMessageId: runtime?.messageId,
3394
3401
  }, null);
3395
- if (!result)
3396
- failManagedGroup(formatJson, 'AUN_DAEMON_UNAVAILABLE', 'Unable to connect to the EvolCore daemon');
3402
+ if (!result) {
3403
+ failManagedGroup(formatJson, 'AUN_DAEMON_UNAVAILABLE', daemonUnavailableMessage(transportError, 'Unable to connect to the EvolCore daemon'));
3404
+ }
3397
3405
  if (!result.ok)
3398
3406
  failManagedGroup(formatJson, result.code ?? 'AUN_SEND_FAILED', `${result.error ?? 'Send failed'}${result.request_id ? ` request_id=${result.request_id}` : ''}`, {
3399
3407
  ...(typeof result.detail_code === 'string' ? { detail_code: result.detail_code } : {}),
@@ -2,7 +2,7 @@ import { isHelpFlag, wantsHelp, getArgValue } from './help.js';
2
2
  import { initConfigManager } from '../config/config-manager.js';
3
3
  import { resolveConfigCommand } from '../config/resolved-config-op.js';
4
4
  import { AUTHENTICATED_CONFIG_ROLE_ENV, executeResolvedConfigCommandAsync, } from '../config/config-operation-service.js';
5
- import { ipcQuery } from '../ipc.js';
5
+ import { daemonUnavailableMessage, queryDaemon } from './help.js';
6
6
  import { resolvePaths } from '../paths.js';
7
7
  import { AGENT_DELEGATION_TOKEN_ENV, readDelegationCredential } from '../core/auth/agent-delegation.js';
8
8
  import { splitConfigBatchGetArgv } from './cli-argv.js';
@@ -135,23 +135,19 @@ function managedSession(formatJson) {
135
135
  return { sessionId, delegationToken };
136
136
  }
137
137
  async function managedConfigQuery(args, sessionId, delegationToken) {
138
- try {
139
- return await ipcQuery(resolvePaths().socket, {
140
- type: 'config.op',
141
- argv: ['config', ...args],
142
- sessionId,
143
- delegationToken,
144
- }, 10_000);
145
- }
146
- catch {
147
- return null;
148
- }
138
+ return queryDaemon(resolvePaths().socket, {
139
+ type: 'config.op',
140
+ argv: ['config', ...args],
141
+ sessionId,
142
+ delegationToken,
143
+ }, 10_000);
149
144
  }
150
145
  async function runManagedConfig(args, formatJson) {
151
146
  const { sessionId, delegationToken } = managedSession(formatJson);
152
- const response = await managedConfigQuery(args, sessionId, delegationToken);
153
- if (!response)
154
- fail(formatJson, 'DAEMON_UNAVAILABLE', 'Unable to connect to the evolcore daemon');
147
+ const { response, transportError } = await managedConfigQuery(args, sessionId, delegationToken);
148
+ if (!response) {
149
+ fail(formatJson, 'DAEMON_UNAVAILABLE', daemonUnavailableMessage(transportError, 'Unable to connect to the evolcore daemon'));
150
+ }
155
151
  if (!response.ok || !response.result) {
156
152
  fail(formatJson, response.code || 'CONFIG_AUTH_FAILED', response.error || 'config operation failed', response.data);
157
153
  }
@@ -197,9 +193,10 @@ async function runDirectBatchGet(fields, rest, formatJson) {
197
193
  }
198
194
  async function runManagedBatchGet(fields, rest, formatJson) {
199
195
  const { sessionId, delegationToken } = managedSession(formatJson);
200
- const response = await managedConfigQuery(['get', ...fields, ...rest], sessionId, delegationToken);
201
- if (!response)
202
- fail(formatJson, 'DAEMON_UNAVAILABLE', 'Unable to connect to the evolcore daemon');
196
+ const { response, transportError } = await managedConfigQuery(['get', ...fields, ...rest], sessionId, delegationToken);
197
+ if (!response) {
198
+ fail(formatJson, 'DAEMON_UNAVAILABLE', daemonUnavailableMessage(transportError, 'Unable to connect to the evolcore daemon'));
199
+ }
203
200
  if (!response.ok || !response.result) {
204
201
  fail(formatJson, response.code || 'CONFIG_AUTH_FAILED', response.error || 'config operation failed', response.data);
205
202
  }
@@ -1,7 +1,7 @@
1
1
  import { resolvePaths } from '../paths.js';
2
2
  import { loadAllAgents } from '../config-store.js';
3
3
  import { executeResolvedContactCommand, resolveContactCommand, } from '../config/contact-operation-service.js';
4
- import { ipcQuery } from '../ipc.js';
4
+ import { daemonUnavailableMessage, queryDaemon } from './help.js';
5
5
  import { AGENT_DELEGATION_TOKEN_ENV, readDelegationCredential } from '../core/auth/agent-delegation.js';
6
6
  import { getArgValue, isHelpFlag, wantsHelp } from './help.js';
7
7
  export async function cmdContact(args) {
@@ -48,18 +48,15 @@ async function runManaged(args, json) {
48
48
  const delegationToken = readDelegationCredential();
49
49
  if (!delegationToken)
50
50
  fail(`${AGENT_DELEGATION_TOKEN_ENV} is not set for the active task`, 'DELEGATION_REQUIRED');
51
- let response = null;
52
- try {
53
- response = await ipcQuery(resolvePaths().socket, {
54
- type: 'contact.op',
55
- argv: ['contact', ...args],
56
- sessionId,
57
- delegationToken,
58
- }, 10_000);
51
+ const { response, transportError } = await queryDaemon(resolvePaths().socket, {
52
+ type: 'contact.op',
53
+ argv: ['contact', ...args],
54
+ sessionId,
55
+ delegationToken,
56
+ }, 10_000);
57
+ if (!response) {
58
+ fail(daemonUnavailableMessage(transportError, 'Unable to connect to the evolcore daemon'), 'DAEMON_UNAVAILABLE');
59
59
  }
60
- catch { }
61
- if (!response)
62
- fail('Unable to connect to the evolcore daemon', 'DAEMON_UNAVAILABLE');
63
60
  if (!response.ok || !response.result) {
64
61
  fail(response.error || 'contact operation failed', response.code || 'CONTACT_AUTH_FAILED', response.data);
65
62
  }
@@ -1,5 +1,5 @@
1
1
  import { resolvePaths } from '../paths.js';
2
- import { ipcQuery } from '../ipc.js';
2
+ import { daemonUnavailableMessage, queryDaemon } from './help.js';
3
3
  import { isHelpFlag, wantsHelp } from './help.js';
4
4
  import { readDelegationCredential } from '../core/auth/agent-delegation.js';
5
5
  // ==================== Ctl ====================
@@ -44,14 +44,14 @@ export async function cmdCtl(args) {
44
44
  process.exit(1);
45
45
  }
46
46
  const socketPath = resolvePaths().socket;
47
- const result = await ipcQuery(socketPath, {
47
+ const { response: result, transportError } = await queryDaemon(socketPath, {
48
48
  type: 'ctl',
49
49
  argv: ['ctl', ...args],
50
50
  sessionId,
51
51
  delegationToken: readDelegationCredential(),
52
52
  }, 10_000);
53
53
  if (!result) {
54
- console.error('错误: 无法连接 evolcore 服务');
54
+ console.error(`错误: ${daemonUnavailableMessage(transportError, '无法连接 evolcore 服务')}`);
55
55
  process.exit(1);
56
56
  }
57
57
  const ctlResult = result;
package/dist/cli/diag.js CHANGED
@@ -1,4 +1,4 @@
1
- import { ipcQuery } from '../ipc.js';
1
+ import { daemonUnavailableMessage, queryDaemon } from './help.js';
2
2
  import { resolvePaths } from '../paths.js';
3
3
  import { readDelegationCredential } from '../core/auth/agent-delegation.js';
4
4
  import { parseDiagArgs } from '../core/command/diag-service.js';
@@ -13,13 +13,17 @@ export async function cmdDiag(args) {
13
13
  let result;
14
14
  try {
15
15
  parseDiagArgs(args);
16
- result = await ipcQuery(resolvePaths().socket, {
16
+ const { response, transportError } = await queryDaemon(resolvePaths().socket, {
17
17
  type: 'diag', argv,
18
18
  ...(process.env.EVOLCORE_SESSION_ID ? {
19
19
  sessionId: process.env.EVOLCORE_SESSION_ID,
20
20
  delegationToken: readDelegationCredential(),
21
21
  } : {}),
22
- }, 30_000) ?? { ok: false, code: 'DAEMON_UNAVAILABLE', message: 'daemon 未返回结果,请检查其运行状态;发送结果尚未确认' };
22
+ }, 30_000);
23
+ result = response ?? {
24
+ ok: false, code: 'DAEMON_UNAVAILABLE',
25
+ message: daemonUnavailableMessage(transportError, 'daemon 未返回结果,请检查其运行状态;发送结果尚未确认'),
26
+ };
23
27
  }
24
28
  catch (error) {
25
29
  result = { ok: false, code: 'INVALID_ARGUMENT', message: error.message };