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.
- package/CHANGELOG.md +22 -0
- package/dist/agents/codex-runner.js +3 -3
- package/dist/aun/aid/agentmd.js +21 -0
- package/dist/aun/aid/client.js +1 -1
- package/dist/aun/aid/ownership-operation.js +34 -9
- package/dist/cli/agent-create.js +7 -2
- package/dist/cli/agent.js +30 -37
- package/dist/cli/aid-bind-command.js +12 -1
- package/dist/cli/aun-commands.js +31 -23
- package/dist/cli/config.js +15 -18
- package/dist/cli/contact.js +9 -12
- package/dist/cli/ctl-command.js +3 -3
- package/dist/cli/diag.js +7 -3
- package/dist/cli/fs-command.js +5 -4
- package/dist/cli/handoff-command.js +11 -11
- package/dist/cli/help.js +18 -0
- package/dist/cli/init-channel.js +2 -1
- package/dist/cli/memory-command.js +14 -13
- package/dist/cli/model.js +5 -4
- package/dist/cli/queue-command.js +3 -3
- package/dist/cli/response.js +5 -4
- package/dist/cli/skill-command.js +13 -13
- package/dist/cli/task-command.js +3 -3
- package/dist/cli/thread-command.js +5 -3
- package/dist/cli/trigger-command.js +3 -3
- package/dist/cli/version.js +6 -2
- package/dist/core/auth/operation-catalog.js +1 -1
- package/dist/core/bootstrap-service.js +20 -12
- package/dist/core/command/cli-intent-parser.js +5 -2
- package/dist/core/command/command-handler.js +13 -4
- package/dist/core/command/menu-handler.js +2 -2
- package/dist/core/ownership/owner-resolver.js +121 -2
- package/dist/core/permission/protected-paths.js +51 -0
- package/dist/utils/npm-ops.js +22 -6
- package/dist/utils/welcome.js +18 -24
- package/kits/docs/evolcore/aid.md +33 -0
- package/package.json +3 -3
package/dist/cli/fs-command.js
CHANGED
|
@@ -3,7 +3,7 @@ import path from 'path';
|
|
|
3
3
|
import { TextDecoder } from 'util';
|
|
4
4
|
import { getArgValue, isHelpFlag, wantsHelp } from './help.js';
|
|
5
5
|
import { agentmdGet, getAidStore, isValidAid, loadClient, SLOT } from '../aun/aid/index.js';
|
|
6
|
-
import {
|
|
6
|
+
import { daemonUnavailableMessage, queryDaemon } from './help.js';
|
|
7
7
|
import { resolvePaths } from '../paths.js';
|
|
8
8
|
import { AGENT_DELEGATION_TOKEN_ENV, readDelegationCredential } from '../core/auth/agent-delegation.js';
|
|
9
9
|
import { DEFAULT_FS_CAT_BYTES, MAX_FS_CAT_BYTES, FsReadBudgetError, downloadGroupFsBytes, readPersonalFsBytesWithinBudget, } from '../aun/group/fs-download.js';
|
|
@@ -222,14 +222,15 @@ async function runManagedFs(args, formatJson) {
|
|
|
222
222
|
fail('NO_SESSION', 'EVOLCORE_SESSION_ID is not set');
|
|
223
223
|
if (!delegationToken)
|
|
224
224
|
fail('DELEGATION_REQUIRED', `${AGENT_DELEGATION_TOKEN_ENV} is not set for the active task`);
|
|
225
|
-
const response = await
|
|
225
|
+
const { response, transportError } = await queryDaemon(resolvePaths().socket, {
|
|
226
226
|
type: 'fs.op',
|
|
227
227
|
argv: ['fs', ...args],
|
|
228
228
|
sessionId,
|
|
229
229
|
delegationToken,
|
|
230
230
|
}, 30_000);
|
|
231
|
-
if (!response)
|
|
232
|
-
return fail('DAEMON_UNAVAILABLE', 'Unable to connect to the evolcore daemon');
|
|
231
|
+
if (!response) {
|
|
232
|
+
return fail('DAEMON_UNAVAILABLE', daemonUnavailableMessage(transportError, 'Unable to connect to the evolcore daemon'));
|
|
233
|
+
}
|
|
233
234
|
if (!response.ok || !response.result)
|
|
234
235
|
fail(String(response.code || 'FS_OPERATION_FAILED'), response.error || 'Filesystem operation failed');
|
|
235
236
|
const result = response.result;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import { resolvePaths } from '../paths.js';
|
|
3
|
-
import {
|
|
3
|
+
import { daemonUnavailableMessage, queryDaemon } from './help.js';
|
|
4
4
|
import { HANDOFF_QUERY_DEFAULT_LIMIT, HANDOFF_QUERY_MAX_LIMIT, HANDOFF_STATES } from '../core/handoff/types.js';
|
|
5
5
|
import { HANDOFF_ID_RE } from '../core/handoff/store.js';
|
|
6
6
|
import { isHelpFlag, wantsHelp } from './help.js';
|
|
@@ -191,7 +191,7 @@ Commands:
|
|
|
191
191
|
process.exitCode = 1;
|
|
192
192
|
return;
|
|
193
193
|
}
|
|
194
|
-
const result = await
|
|
194
|
+
const { response: result, transportError } = await queryDaemon(resolvePaths().socket, {
|
|
195
195
|
type: 'handoff-return',
|
|
196
196
|
argv: ['handoff', ...args],
|
|
197
197
|
sessionId: process.env.EVOLCORE_SESSION_ID,
|
|
@@ -200,7 +200,7 @@ Commands:
|
|
|
200
200
|
delegationToken: readDelegationCredential(),
|
|
201
201
|
}, 5000);
|
|
202
202
|
if (!result) {
|
|
203
|
-
console.error('
|
|
203
|
+
console.error(`✗ ${daemonUnavailableMessage(transportError, 'daemon 暂时不可用')}`);
|
|
204
204
|
process.exitCode = 1;
|
|
205
205
|
return;
|
|
206
206
|
}
|
|
@@ -222,7 +222,7 @@ Commands:
|
|
|
222
222
|
process.exitCode = 1;
|
|
223
223
|
return;
|
|
224
224
|
}
|
|
225
|
-
const result = await
|
|
225
|
+
const { response: result, transportError } = await queryDaemon(resolvePaths().socket, {
|
|
226
226
|
type: 'handoff-recover-return',
|
|
227
227
|
argv: ['handoff', ...args],
|
|
228
228
|
sessionId: process.env.EVOLCORE_SESSION_ID,
|
|
@@ -231,7 +231,7 @@ Commands:
|
|
|
231
231
|
delegationToken: readDelegationCredential(),
|
|
232
232
|
}, 5000);
|
|
233
233
|
if (!result) {
|
|
234
|
-
console.error('
|
|
234
|
+
console.error(`✗ ${daemonUnavailableMessage(transportError, 'daemon 暂时不可用')}`);
|
|
235
235
|
process.exitCode = 1;
|
|
236
236
|
return;
|
|
237
237
|
}
|
|
@@ -245,13 +245,13 @@ Commands:
|
|
|
245
245
|
process.exitCode = 1;
|
|
246
246
|
return;
|
|
247
247
|
}
|
|
248
|
-
const result = await
|
|
248
|
+
const { response: result, transportError } = await queryDaemon(resolvePaths().socket, {
|
|
249
249
|
type: 'handoff-status', sessionId: process.env.EVOLCORE_SESSION_ID, handoffId,
|
|
250
250
|
argv: ['handoff', ...args],
|
|
251
251
|
delegationToken: readDelegationCredential(),
|
|
252
252
|
}, 5000);
|
|
253
253
|
if (!result) {
|
|
254
|
-
console.error('
|
|
254
|
+
console.error(`✗ ${daemonUnavailableMessage(transportError, 'daemon 暂时不可用')}`);
|
|
255
255
|
process.exitCode = 1;
|
|
256
256
|
return;
|
|
257
257
|
}
|
|
@@ -273,7 +273,7 @@ Commands:
|
|
|
273
273
|
process.exitCode = 1;
|
|
274
274
|
return;
|
|
275
275
|
}
|
|
276
|
-
const result = await
|
|
276
|
+
const { response: result, transportError } = await queryDaemon(resolvePaths().socket, {
|
|
277
277
|
type: 'handoff-list',
|
|
278
278
|
argv: ['handoff', ...args],
|
|
279
279
|
sessionId: process.env.EVOLCORE_SESSION_ID,
|
|
@@ -284,7 +284,7 @@ Commands:
|
|
|
284
284
|
delegationToken: readDelegationCredential(),
|
|
285
285
|
}, 5000);
|
|
286
286
|
if (!result) {
|
|
287
|
-
console.error('
|
|
287
|
+
console.error(`✗ ${daemonUnavailableMessage(transportError, 'daemon 暂时不可用')}`);
|
|
288
288
|
process.exitCode = 1;
|
|
289
289
|
return;
|
|
290
290
|
}
|
|
@@ -318,7 +318,7 @@ Commands:
|
|
|
318
318
|
process.exitCode = 1;
|
|
319
319
|
return;
|
|
320
320
|
}
|
|
321
|
-
const result = await
|
|
321
|
+
const { response: result, transportError } = await queryDaemon(resolvePaths().socket, {
|
|
322
322
|
type: 'handoff-trace',
|
|
323
323
|
argv: ['handoff', ...args],
|
|
324
324
|
sessionId: process.env.EVOLCORE_SESSION_ID,
|
|
@@ -328,7 +328,7 @@ Commands:
|
|
|
328
328
|
delegationToken: readDelegationCredential(),
|
|
329
329
|
}, 5000);
|
|
330
330
|
if (!result) {
|
|
331
|
-
console.error('
|
|
331
|
+
console.error(`✗ ${daemonUnavailableMessage(transportError, 'daemon 暂时不可用')}`);
|
|
332
332
|
process.exitCode = 1;
|
|
333
333
|
return;
|
|
334
334
|
}
|
package/dist/cli/help.js
CHANGED
|
@@ -11,7 +11,25 @@
|
|
|
11
11
|
* - 单层命令(如 cmdLinkRules、cmdAid 的具体 sub 处理块内)用 wantsHelp(args),
|
|
12
12
|
* 支持 option 风格帮助,同时不把 `--` 后的正文误判为帮助。
|
|
13
13
|
*/
|
|
14
|
+
import { IpcTransportError, ipcQuery } from '../ipc.js';
|
|
14
15
|
const HELP_TOKENS = new Set(['help', '--help', '-h']);
|
|
16
|
+
/** Query a daemon-backed command while preserving concrete transport failures. */
|
|
17
|
+
export async function queryDaemon(socketPath, command, timeoutMs = 3000) {
|
|
18
|
+
try {
|
|
19
|
+
return {
|
|
20
|
+
response: await ipcQuery(socketPath, command, timeoutMs, { throwOnError: true }),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
if (error instanceof IpcTransportError) {
|
|
25
|
+
return { response: null, transportError: error };
|
|
26
|
+
}
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export function daemonUnavailableMessage(transportError, fallback) {
|
|
31
|
+
return transportError?.message ?? fallback;
|
|
32
|
+
}
|
|
15
33
|
export function isHelpFlag(token) {
|
|
16
34
|
return token !== undefined && HELP_TOKENS.has(token);
|
|
17
35
|
}
|
package/dist/cli/init-channel.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import readline from 'readline';
|
|
9
9
|
import { cmdAidBind } from './aid-bind-command.js';
|
|
10
10
|
import { getOwners } from '../core/ownership/owner-resolver.js';
|
|
11
|
+
import { MAIN_CLI_BIN } from '../product.js';
|
|
11
12
|
import crypto from 'crypto';
|
|
12
13
|
import { selectInstance } from './init.js';
|
|
13
14
|
import { loadAllAgents, loadAgent, loadDaemonConfig } from '../config-store.js';
|
|
@@ -695,7 +696,7 @@ export async function cmdInitWechat() {
|
|
|
695
696
|
// ==================== AUN ====================
|
|
696
697
|
export async function cmdInitAun() {
|
|
697
698
|
console.log('AUN 协议 Owner 统一使用 ec aid bind <ownerAid> [--subject <subjectAid>]');
|
|
698
|
-
console.log(
|
|
699
|
+
console.log(`状态查询: ${MAIN_CLI_BIN} aid bind status [--subject <subjectAid>];邀约审批: ${MAIN_CLI_BIN} aid bind accept|reject <operationId>。`);
|
|
699
700
|
}
|
|
700
701
|
async function pickAunOwnerBindTarget(rl, daemonAid) {
|
|
701
702
|
const { agents } = loadAllAgents();
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import fs from 'node:fs';
|
|
15
15
|
import { resolvePaths } from '../paths.js';
|
|
16
|
-
import {
|
|
16
|
+
import { daemonUnavailableMessage, queryDaemon } from './help.js';
|
|
17
17
|
import { isHelpFlag, wantsHelp, getArgValue } from './help.js';
|
|
18
18
|
import { readDelegationCredential } from '../core/auth/agent-delegation.js';
|
|
19
19
|
import { canonicalizeEvolcoreCommandArgv } from '../core/permission/ec-command-parser.js';
|
|
@@ -337,7 +337,7 @@ async function cmdMemoryNoteCreate(args, json) {
|
|
|
337
337
|
if (!content)
|
|
338
338
|
failWithUsage(json, '必须提供记忆内容(content)', USAGE.note);
|
|
339
339
|
const { socketPath, ...session } = requireManagedSession('ec memory note', flags, json);
|
|
340
|
-
const result = await
|
|
340
|
+
const result = await queryDaemon(socketPath, {
|
|
341
341
|
type: 'memory.note', argv: ['memory', 'note', ...args], ...session, slug, content, tags,
|
|
342
342
|
speakers: speakers && speakers.length > 0 ? speakers : undefined,
|
|
343
343
|
}, 15_000);
|
|
@@ -359,7 +359,7 @@ async function cmdMemoryNoteUpdate(args, json) {
|
|
|
359
359
|
failWithUsage(json, '至少提供一项要改的内容(--slug / --tags / 正文)', USAGE.noteUpdate);
|
|
360
360
|
}
|
|
361
361
|
const { socketPath, ...session } = requireManagedSession('ec memory note update', flags, json);
|
|
362
|
-
const result = await
|
|
362
|
+
const result = await queryDaemon(socketPath, {
|
|
363
363
|
type: 'memory.note.update', argv: ['memory', 'note', 'update', ...args], ...session, slug,
|
|
364
364
|
newSlug, tags, tagsProvided: tagsRaw !== undefined,
|
|
365
365
|
content: content || undefined,
|
|
@@ -375,7 +375,7 @@ async function cmdMemoryNoteDrop(args, json) {
|
|
|
375
375
|
if (!slug)
|
|
376
376
|
failWithUsage(json, '必须提供要撤销的 slug', USAGE.noteDrop);
|
|
377
377
|
const { socketPath, ...session } = requireManagedSession('ec memory note drop', flags, json);
|
|
378
|
-
const result = await
|
|
378
|
+
const result = await queryDaemon(socketPath, {
|
|
379
379
|
type: 'memory.note.drop', argv: ['memory', 'note', 'drop', ...args], ...session, slug,
|
|
380
380
|
}, 15_000);
|
|
381
381
|
reportResult(result, json, (r) => {
|
|
@@ -385,7 +385,7 @@ async function cmdMemoryNoteDrop(args, json) {
|
|
|
385
385
|
async function cmdMemoryNoteList(args, json) {
|
|
386
386
|
const { flags } = parseCliArgs(args, [], json);
|
|
387
387
|
const { socketPath, ...session } = requireManagedSession('ec memory note list', flags, json);
|
|
388
|
-
const result = await
|
|
388
|
+
const result = await queryDaemon(socketPath, {
|
|
389
389
|
type: 'memory.note.list', argv: ['memory', 'note', 'list', ...args], ...session,
|
|
390
390
|
}, 15_000);
|
|
391
391
|
reportResult(result, json, (r) => {
|
|
@@ -430,7 +430,7 @@ async function cmdMemoryCreate(args, json) {
|
|
|
430
430
|
failWithUsage(json, '--peer 只在 --scope relation 时有效', USAGE.create);
|
|
431
431
|
}
|
|
432
432
|
const { socketPath, ...session } = requireManagedSession('ec memory create', flags, json);
|
|
433
|
-
const result = await
|
|
433
|
+
const result = await queryDaemon(socketPath, {
|
|
434
434
|
type: 'memory.create', argv: ['memory', 'create', ...args], ...session, scope, slug, description: desc,
|
|
435
435
|
content,
|
|
436
436
|
tags: parseTags(tagsRaw),
|
|
@@ -456,7 +456,7 @@ async function cmdMemoryConsolidatedUpdate(args, json) {
|
|
|
456
456
|
if (tagsRaw === undefined && !touch)
|
|
457
457
|
failWithUsage(json, '至少提供 --tags 或 --touch', USAGE.update);
|
|
458
458
|
const { socketPath, ...session } = requireManagedSession('ec memory update', flags, json);
|
|
459
|
-
const result = await
|
|
459
|
+
const result = await queryDaemon(socketPath, {
|
|
460
460
|
type: 'memory.update', argv: ['memory', 'update', ...args], ...session, filePath,
|
|
461
461
|
tags: parseTags(tagsRaw), touch,
|
|
462
462
|
}, 15_000);
|
|
@@ -469,7 +469,7 @@ async function cmdMemoryArchive(args, json) {
|
|
|
469
469
|
if (positional.length === 0)
|
|
470
470
|
failWithUsage(json, '必须提供至少一个要归档的文件路径', USAGE.archive);
|
|
471
471
|
const { socketPath, ...session } = requireManagedSession('ec memory archive', flags, json);
|
|
472
|
-
const result = await
|
|
472
|
+
const result = await queryDaemon(socketPath, {
|
|
473
473
|
type: 'memory.archive', argv: ['memory', 'archive', ...args], ...session, filePaths: positional,
|
|
474
474
|
}, 15_000);
|
|
475
475
|
reportResult(result, json, (r) => {
|
|
@@ -496,7 +496,7 @@ async function cmdMemoryDemote(args, json) {
|
|
|
496
496
|
fail(json, 'INVALID_ARGUMENT', '--scope 必须是 agent 或 owner', { text: '--scope 必须是 agent 或 owner' });
|
|
497
497
|
}
|
|
498
498
|
const { socketPath, ...session } = requireManagedSession('ec memory demote', flags, json);
|
|
499
|
-
const result = await
|
|
499
|
+
const result = await queryDaemon(socketPath, {
|
|
500
500
|
type: 'memory.demote', argv: ['memory', 'demote', ...args], ...session, slug, scope,
|
|
501
501
|
}, 15_000);
|
|
502
502
|
reportResult(result, json, (r) => {
|
|
@@ -528,7 +528,7 @@ async function cmdMemoryConsolidate(args, json) {
|
|
|
528
528
|
// JSON 模式下 stdout 只留结果对象
|
|
529
529
|
if (!json)
|
|
530
530
|
console.log(`正在触发记忆整理(mode=${mode})...`);
|
|
531
|
-
const result = await
|
|
531
|
+
const result = await queryDaemon(socketPath, {
|
|
532
532
|
type: 'memory.consolidate', argv: ['memory', 'consolidate', ...args], ...session, mode,
|
|
533
533
|
}, 30_000);
|
|
534
534
|
reportResult(result, json, (r) => {
|
|
@@ -551,10 +551,11 @@ async function cmdMemoryConsolidate(args, json) {
|
|
|
551
551
|
}
|
|
552
552
|
// ── 结果输出 ───────────────────────────────────────────────────────────────
|
|
553
553
|
function reportResult(result, json, ok) {
|
|
554
|
-
if (!result) {
|
|
555
|
-
|
|
554
|
+
if (!result.response) {
|
|
555
|
+
const message = daemonUnavailableMessage(result.transportError, '无法连接 evolcore 服务');
|
|
556
|
+
fail(json, 'DAEMON_UNAVAILABLE', message, { text: `错误: ${message}` });
|
|
556
557
|
}
|
|
557
|
-
const r = result;
|
|
558
|
+
const r = result.response;
|
|
558
559
|
if (!r.ok) {
|
|
559
560
|
const message = r.error || '操作失败';
|
|
560
561
|
fail(json, r.code || 'MEMORY_OPERATION_FAILED', message, { text: message });
|
package/dist/cli/model.js
CHANGED
|
@@ -16,7 +16,7 @@ import { resolveEffectiveFieldWithSource } from '../config/config-manager.js';
|
|
|
16
16
|
import { getCatalog, getModelInfo, catalogEfforts, resolveCatalogModel, assertCatalogSelectable } from '../core/model/model-catalog.js';
|
|
17
17
|
import { constrainResolvedModelForRole, filterModelsForRole, validateModelSelectionForRole, } from '../core/model/model-permission.js';
|
|
18
18
|
import { resolvePaths } from '../paths.js';
|
|
19
|
-
import {
|
|
19
|
+
import { daemonUnavailableMessage, queryDaemon } from './help.js';
|
|
20
20
|
import { parsePeerKey } from '../core/relation/peer-identity.js';
|
|
21
21
|
import { resolvePeerRoleDetail } from '../config/peer-role-resolver.js';
|
|
22
22
|
import { AGENT_DELEGATION_TOKEN_ENV, readDelegationCredential } from '../core/auth/agent-delegation.js';
|
|
@@ -50,11 +50,12 @@ async function runManagedCliOperation(args, formatJson, timeoutMs = 10_000) {
|
|
|
50
50
|
const delegationToken = readDelegationCredential();
|
|
51
51
|
if (!delegationToken)
|
|
52
52
|
fail(formatJson, 'DELEGATION_REQUIRED', `${AGENT_DELEGATION_TOKEN_ENV} 未设置`);
|
|
53
|
-
const response = await
|
|
53
|
+
const { response, transportError } = await queryDaemon(resolvePaths().socket, {
|
|
54
54
|
type: 'ctl', argv: args, sessionId, delegationToken,
|
|
55
55
|
}, timeoutMs);
|
|
56
|
-
if (!response)
|
|
57
|
-
fail(formatJson, 'DAEMON_UNAVAILABLE', '无法连接 evolcore 服务');
|
|
56
|
+
if (!response) {
|
|
57
|
+
fail(formatJson, 'DAEMON_UNAVAILABLE', daemonUnavailableMessage(transportError, '无法连接 evolcore 服务'));
|
|
58
|
+
}
|
|
58
59
|
if (!response.ok)
|
|
59
60
|
fail(formatJson, response.code || 'CTL_FAILED', response.error || '命令执行失败');
|
|
60
61
|
printCtlResult({ text: response.result || '', data: response.data }, formatJson);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { resolvePaths } from '../paths.js';
|
|
2
|
-
import {
|
|
2
|
+
import { daemonUnavailableMessage, queryDaemon } from './help.js';
|
|
3
3
|
import { readDelegationCredential } from '../core/auth/agent-delegation.js';
|
|
4
4
|
import { getArgValue, isHelpFlag, wantsHelp } from './help.js';
|
|
5
5
|
import { canonicalizeEvolcoreCommandArgv } from '../core/permission/ec-command-parser.js';
|
|
@@ -94,7 +94,7 @@ JSON 时间字段:
|
|
|
94
94
|
: undefined;
|
|
95
95
|
const socketPath = resolvePaths().socket;
|
|
96
96
|
const managed = process.env.EVOLCORE_SESSION_ID;
|
|
97
|
-
const result = await
|
|
97
|
+
const { response: result, transportError } = await queryDaemon(socketPath, managed ? {
|
|
98
98
|
type: 'queue.op',
|
|
99
99
|
argv: ['queue', ...args],
|
|
100
100
|
agent,
|
|
@@ -115,7 +115,7 @@ JSON 时间字段:
|
|
|
115
115
|
before,
|
|
116
116
|
});
|
|
117
117
|
if (!result) {
|
|
118
|
-
console.error('
|
|
118
|
+
console.error(`错误: ${daemonUnavailableMessage(transportError, '无法连接 evolcore 服务')}`);
|
|
119
119
|
process.exit(1);
|
|
120
120
|
}
|
|
121
121
|
const r = result;
|
package/dist/cli/response.js
CHANGED
|
@@ -15,7 +15,7 @@ import { readField, writeField, determineFieldScope, normalizePeer, ModelScopeEr
|
|
|
15
15
|
import { readFieldWithSource, resolveAgentConfig, ConfigTarget } from '../config/config-manager.js';
|
|
16
16
|
import { ResponseModeRegistry } from '../response-system/registry.js';
|
|
17
17
|
import { registerBuiltinModes } from '../response-system/modes/index.js';
|
|
18
|
-
import {
|
|
18
|
+
import { daemonUnavailableMessage, queryDaemon } from './help.js';
|
|
19
19
|
import { resolvePaths } from '../paths.js';
|
|
20
20
|
import { AGENT_DELEGATION_TOKEN_ENV, readDelegationCredential } from '../core/auth/agent-delegation.js';
|
|
21
21
|
const RESPONSE_MODE_FIELD = 'responseMode';
|
|
@@ -64,11 +64,12 @@ async function runManagedResponse(args, formatJson) {
|
|
|
64
64
|
fail(formatJson, 'NO_SESSION', 'EVOLCORE_SESSION_ID is not set');
|
|
65
65
|
if (!delegationToken)
|
|
66
66
|
fail(formatJson, 'DELEGATION_REQUIRED', `${AGENT_DELEGATION_TOKEN_ENV} is not set`);
|
|
67
|
-
const response = await
|
|
67
|
+
const { response, transportError } = await queryDaemon(resolvePaths().socket, {
|
|
68
68
|
type: 'ctl', argv: ['response', ...args], sessionId, delegationToken,
|
|
69
69
|
}, 10_000);
|
|
70
|
-
if (!response)
|
|
71
|
-
fail(formatJson, 'DAEMON_UNAVAILABLE', 'Unable to connect to the evolcore daemon');
|
|
70
|
+
if (!response) {
|
|
71
|
+
fail(formatJson, 'DAEMON_UNAVAILABLE', daemonUnavailableMessage(transportError, 'Unable to connect to the evolcore daemon'));
|
|
72
|
+
}
|
|
72
73
|
if (!response.ok)
|
|
73
74
|
fail(formatJson, response.code || 'CTL_FAILED', response.error || 'response operation failed');
|
|
74
75
|
emit(formatJson, response.data ?? { ok: true, result: response.result }, () => response.result || 'ok');
|
|
@@ -22,7 +22,7 @@ import path from 'path';
|
|
|
22
22
|
import { spawn } from 'child_process';
|
|
23
23
|
import { getPackageRoot, agentDir, resolvePaths } from '../paths.js';
|
|
24
24
|
import { readTaskRuntimeContextFromEnv } from './task-context.js';
|
|
25
|
-
import {
|
|
25
|
+
import { daemonUnavailableMessage, queryDaemon } from './help.js';
|
|
26
26
|
import { readDelegationCredential } from '../core/auth/agent-delegation.js';
|
|
27
27
|
import { authorizeLocalCommand, TASK_RUNTIME_CONTEXT_ENV } from './task-context.js';
|
|
28
28
|
import { canonicalizeEvolcoreCommandArgv } from '../core/permission/ec-command-parser.js';
|
|
@@ -87,17 +87,17 @@ async function cmdSkillRefresh(args) {
|
|
|
87
87
|
process.exitCode = 1;
|
|
88
88
|
return;
|
|
89
89
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
90
|
+
const { response, transportError } = await queryDaemon(resolvePaths().socket, {
|
|
91
|
+
type: 'skill.refresh',
|
|
92
|
+
aid,
|
|
93
|
+
argv,
|
|
94
|
+
...(sessionId ? { sessionId, delegationToken } : {}),
|
|
95
|
+
}, 30_000);
|
|
96
|
+
if (transportError) {
|
|
97
|
+
if (asJson)
|
|
98
|
+
console.log(JSON.stringify({ ok: false, code: 'DAEMON_UNAVAILABLE', error: transportError.message }, null, 2));
|
|
99
|
+
else
|
|
100
|
+
console.error(`❌ 刷新失败 (DAEMON_UNAVAILABLE): ${transportError.message}`);
|
|
101
101
|
process.exitCode = 1;
|
|
102
102
|
return;
|
|
103
103
|
}
|
|
@@ -109,7 +109,7 @@ async function cmdSkillRefresh(args) {
|
|
|
109
109
|
}
|
|
110
110
|
if (!response?.ok) {
|
|
111
111
|
const code = response?.code ?? (response ? 'FAILED' : 'DAEMON_UNAVAILABLE');
|
|
112
|
-
console.error(`❌ 刷新失败 (${code}): ${response?.error ?? '无法连接 evolcore daemon'}`);
|
|
112
|
+
console.error(`❌ 刷新失败 (${code}): ${response?.error ?? daemonUnavailableMessage(transportError, '无法连接 evolcore daemon')}`);
|
|
113
113
|
if (response?.data?.nextStep)
|
|
114
114
|
console.error(` ${response.data.nextStep}`);
|
|
115
115
|
process.exitCode = 1;
|
package/dist/cli/task-command.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { resolvePaths } from '../paths.js';
|
|
2
|
-
import {
|
|
2
|
+
import { daemonUnavailableMessage, queryDaemon } from './help.js';
|
|
3
3
|
import { readDelegationCredential } from '../core/auth/agent-delegation.js';
|
|
4
4
|
import { wantsHelp } from './help.js';
|
|
5
5
|
const TASK_HELP = `用法: ec task resume <sessionId> [--format json]
|
|
@@ -39,14 +39,14 @@ export async function cmdTask(args) {
|
|
|
39
39
|
printError('DELEGATION_REQUIRED', '托管任务缺少 delegation token');
|
|
40
40
|
return;
|
|
41
41
|
}
|
|
42
|
-
const result = await
|
|
42
|
+
const { response: result, transportError } = await queryDaemon(resolvePaths().socket, {
|
|
43
43
|
type: 'task.resume',
|
|
44
44
|
argv: ['task', ...args],
|
|
45
45
|
targetSessionId,
|
|
46
46
|
...(sessionId ? { sessionId, delegationToken } : {}),
|
|
47
47
|
}, 10_000);
|
|
48
48
|
if (!result) {
|
|
49
|
-
printError('IPC_UNAVAILABLE', '无法连接 EvolCore 服务;请查询任务状态后再决定是否重试');
|
|
49
|
+
printError('IPC_UNAVAILABLE', daemonUnavailableMessage(transportError, '无法连接 EvolCore 服务;请查询任务状态后再决定是否重试'));
|
|
50
50
|
return;
|
|
51
51
|
}
|
|
52
52
|
if (json)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { resolvePaths } from '../paths.js';
|
|
2
|
-
import {
|
|
2
|
+
import { daemonUnavailableMessage, queryDaemon } from './help.js';
|
|
3
3
|
import { readDelegationCredential } from '../core/auth/agent-delegation.js';
|
|
4
4
|
import { canonicalizeEvolcoreCommandArgv } from '../core/permission/ec-command-parser.js';
|
|
5
5
|
import { isMainSessionThreadId, resolveThreadRef } from '../core/thread/topic-id.js';
|
|
@@ -91,7 +91,7 @@ async function sendThreadOp(req, commandArgv) {
|
|
|
91
91
|
const cred = readDelegationCredential();
|
|
92
92
|
const { socket } = resolvePaths();
|
|
93
93
|
const invokingSessionId = process.env.EVOLCORE_SESSION_ID;
|
|
94
|
-
const result = await
|
|
94
|
+
const { response: result, transportError } = await queryDaemon(socket, {
|
|
95
95
|
...req,
|
|
96
96
|
type: 'thread.op',
|
|
97
97
|
argv: commandArgv,
|
|
@@ -99,7 +99,9 @@ async function sendThreadOp(req, commandArgv) {
|
|
|
99
99
|
sessionId: invokingSessionId,
|
|
100
100
|
}, 10000);
|
|
101
101
|
if (!result)
|
|
102
|
-
return {
|
|
102
|
+
return {
|
|
103
|
+
ok: false, code: 'DAEMON_UNAVAILABLE', error: daemonUnavailableMessage(transportError, 'daemon 暂时不可用'),
|
|
104
|
+
};
|
|
103
105
|
return result;
|
|
104
106
|
}
|
|
105
107
|
function printResult(data, jsonFormat) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { resolvePaths } from '../paths.js';
|
|
4
|
-
import {
|
|
4
|
+
import { daemonUnavailableMessage, queryDaemon } from './help.js';
|
|
5
5
|
import { isHelpFlag, wantsHelp } from './help.js';
|
|
6
6
|
import { readDelegationCredential } from '../core/auth/agent-delegation.js';
|
|
7
7
|
import { readTaskRuntimeContextFromEnv } from './task-context.js';
|
|
@@ -642,9 +642,9 @@ async function request(cmd, timeoutMs = 10_000) {
|
|
|
642
642
|
}
|
|
643
643
|
catch { }
|
|
644
644
|
}
|
|
645
|
-
const res = await
|
|
645
|
+
const { response: res, transportError } = await queryDaemon(resolvePaths().socket, actorSessionId ? { ...cmd, actorSessionId, delegationToken } : delegationToken ? { ...cmd, delegationToken } : { ...cmd, controlToken }, timeoutMs);
|
|
646
646
|
if (!res)
|
|
647
|
-
throw new Error('
|
|
647
|
+
throw new Error(`错误: ${daemonUnavailableMessage(transportError, '无法连接 evolcore 服务')}`);
|
|
648
648
|
if (res.ok === false || res.error)
|
|
649
649
|
throw new Error(res.error || 'trigger command failed');
|
|
650
650
|
return res;
|
package/dist/cli/version.js
CHANGED
|
@@ -6,6 +6,7 @@ import path from 'path';
|
|
|
6
6
|
import { fileURLToPath } from 'url';
|
|
7
7
|
import { MAIN_PACKAGE_NAME, PRODUCT_DISPLAY_NAME, WEB_PACKAGE_NAME } from '../product.js';
|
|
8
8
|
import { getArgValue, wantsHelp } from './help.js';
|
|
9
|
+
import { resolveGlobalPkg } from '../utils/npm-ops.js';
|
|
9
10
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
10
11
|
const PACKAGE_ROOT = path.resolve(__dirname, '../..');
|
|
11
12
|
const RESET = '\x1b[0m';
|
|
@@ -54,8 +55,11 @@ export function handleVersion(args) {
|
|
|
54
55
|
const mainPkg = readPkgJson(PACKAGE_ROOT);
|
|
55
56
|
const mainEntry = path.join(PACKAGE_ROOT, 'dist', 'cli', 'index.js');
|
|
56
57
|
const mainTs = getFileModTime(mainEntry);
|
|
57
|
-
//
|
|
58
|
-
|
|
58
|
+
// EC Web may be in the repository (dev mode) or nested under the globally
|
|
59
|
+
// installed EvolCore package. Use the shared resolver so both layouts report
|
|
60
|
+
// the actual installed package instead of `?`.
|
|
61
|
+
const ecwebInstalled = resolveGlobalPkg(WEB_PACKAGE_NAME);
|
|
62
|
+
const ecwebDir = ecwebInstalled ? path.dirname(ecwebInstalled.path) : path.join(PACKAGE_ROOT, 'ecweb');
|
|
59
63
|
const ecwebPkg = readPkgJson(ecwebDir);
|
|
60
64
|
const ecwebEntry = path.join(ecwebDir, 'dist', 'index.js');
|
|
61
65
|
const ecwebTs = getFileModTime(ecwebEntry);
|
|
@@ -1123,7 +1123,7 @@ const OPERATIONS = [
|
|
|
1123
1123
|
},
|
|
1124
1124
|
{
|
|
1125
1125
|
id: 'ec.aid.bind', category: 'write-agent', dangerous: true, defaultScopes: ['agent'],
|
|
1126
|
-
description: 'Request a protocol Owner binding using the subject SDK client', sources: ['agent-tool', 'menu.cli'],
|
|
1126
|
+
description: 'Request or decide a protocol Owner binding using the subject SDK client', sources: ['agent-tool', 'menu.cli'],
|
|
1127
1127
|
},
|
|
1128
1128
|
{
|
|
1129
1129
|
id: 'ec.aid.bind.status', category: 'read', dangerous: false, defaultScopes: ['agent'],
|
|
@@ -3,8 +3,8 @@ import { ownerResolver, OWNERSHIP_AUTHORIZATION_MAX_AGE_MS } from './ownership/o
|
|
|
3
3
|
import fs from 'fs';
|
|
4
4
|
import path from 'path';
|
|
5
5
|
import { randomBytes } from 'crypto';
|
|
6
|
-
import { kitsTemplatesDir,
|
|
7
|
-
import { buildInitialAgentMd, resolveAgentDisplayName } from '../aun/aid/agentmd.js';
|
|
6
|
+
import { kitsTemplatesDir, resolvePaths } from '../paths.js';
|
|
7
|
+
import { buildInitialAgentMd, resolveAgentDisplayName, verifyLocalAgentMd } from '../aun/aid/agentmd.js';
|
|
8
8
|
import { logger } from '../utils/logger.js';
|
|
9
9
|
import { readAgentWelcomeTemplate } from '../utils/welcome.js';
|
|
10
10
|
import { loadAgent, saveAgent } from '../config-store.js';
|
|
@@ -308,7 +308,13 @@ export class BootstrapService {
|
|
|
308
308
|
return false;
|
|
309
309
|
}
|
|
310
310
|
if (starting) {
|
|
311
|
-
|
|
311
|
+
// AUN creation/binding has already published agent.md, and the fresh
|
|
312
|
+
// Owner consensus above requires it. A normal upload here re-signs the
|
|
313
|
+
// approved original while the Owner may still be confirming its hash
|
|
314
|
+
// and ETag. Sending a welcome must not mutate that binding evidence.
|
|
315
|
+
if (channelType !== 'aun') {
|
|
316
|
+
await this.publishAgentMdIfSupported(ctx.adapter, aid, agentName);
|
|
317
|
+
}
|
|
312
318
|
this.setLifecycle(agent, aid, 'bootstrapping');
|
|
313
319
|
lifecycleStarted = true;
|
|
314
320
|
}
|
|
@@ -546,18 +552,20 @@ export class BootstrapService {
|
|
|
546
552
|
async publishAgentMdIfSupported(adapter, aid, fallbackName) {
|
|
547
553
|
if (typeof adapter.uploadAgentMd !== 'function')
|
|
548
554
|
return;
|
|
549
|
-
const
|
|
550
|
-
|
|
555
|
+
const verification = await verifyLocalAgentMd(aid);
|
|
556
|
+
if (verification.status === 'verified') {
|
|
557
|
+
logger.info(`[Bootstrap] Preserving verified local agent.md for ${aid}; upload skipped`);
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
if (verification.status !== 'missing') {
|
|
561
|
+
throw new Error(`Local agent.md cannot be safely republished for ${aid}: ${verification.reason ?? verification.status}`);
|
|
562
|
+
}
|
|
563
|
+
const content = buildInitialAgentMd({
|
|
551
564
|
aid,
|
|
552
565
|
name: fallbackName,
|
|
553
566
|
type: 'agent',
|
|
554
567
|
});
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
logger.info(`[Bootstrap] Published agent.md for ${aid}`);
|
|
558
|
-
}
|
|
559
|
-
catch (e) {
|
|
560
|
-
logger.warn(`[Bootstrap] Failed to publish agent.md for ${aid}: ${e instanceof Error ? e.message : String(e)}`);
|
|
561
|
-
}
|
|
568
|
+
await adapter.uploadAgentMd(content);
|
|
569
|
+
logger.info(`[Bootstrap] Published initial agent.md for ${aid}`);
|
|
562
570
|
}
|
|
563
571
|
}
|
|
@@ -243,11 +243,14 @@ function parseAidCommand(argv, source, defaultSelfAid) {
|
|
|
243
243
|
try {
|
|
244
244
|
const command = parseOwnershipCommand(argv.slice(1));
|
|
245
245
|
const subjectAid = command.subjectAid ?? defaultSelfAid;
|
|
246
|
-
|
|
246
|
+
const isMutation = command.action !== 'status';
|
|
247
|
+
return recognized(isMutation ? 'ec.aid.bind' : 'ec.aid.bind.status', 'agent', source, {
|
|
247
248
|
...(subjectAid ? { self: subjectAid } : {}),
|
|
248
249
|
...(command.subjectAid ? { subjectAid: command.subjectAid } : {}),
|
|
249
250
|
...(command.action === 'bind' ? { ownerAid: command.ownerAid } : {}),
|
|
250
|
-
|
|
251
|
+
...(command.action === 'accept' || command.action === 'reject'
|
|
252
|
+
? { decision: command.action, operationId: command.operationId } : {}),
|
|
253
|
+
}, argv, isMutation);
|
|
251
254
|
}
|
|
252
255
|
catch (error) {
|
|
253
256
|
return raw(source, argv, error instanceof Error ? error.message : 'Invalid aid bind command');
|
|
@@ -2196,8 +2196,9 @@ export class CommandHandler {
|
|
|
2196
2196
|
const command = parseOwnershipCommand(argv);
|
|
2197
2197
|
const targetAid = command.subjectAid ?? grant.selfAid;
|
|
2198
2198
|
ownerResolver.assertLocalSubject(targetAid);
|
|
2199
|
-
|
|
2200
|
-
|
|
2199
|
+
const isMutation = command.action !== 'status';
|
|
2200
|
+
if (isMutation && !['request', 'bypass'].includes(grant.permissionMode ?? '')) {
|
|
2201
|
+
return { ok: false, code: 'NOT_ALLOWED', error: 'Binding changes and decisions require a request or bypass task' };
|
|
2201
2202
|
}
|
|
2202
2203
|
await refreshOwnershipForAuthorization(targetAid);
|
|
2203
2204
|
let conversationId;
|
|
@@ -2215,12 +2216,20 @@ export class CommandHandler {
|
|
|
2215
2216
|
if (targetAid !== grant.selfAid && !subject.isDaemonOwner) {
|
|
2216
2217
|
return { ok: false, code: 'SCOPE_MISMATCH', error: 'A different local subject requires the current daemon Owner' };
|
|
2217
2218
|
}
|
|
2218
|
-
if (!subject.isDaemonOwner && (
|
|
2219
|
+
if (!subject.isDaemonOwner && (isMutation ? subject.role !== 'owner' : !isManagementRole(subject.role))) {
|
|
2219
2220
|
return { ok: false, code: 'OWNER_REQUIRED', error: 'Ownership binding requires the subject Owner or daemon Owner; first daemon binding uses the local CLI' };
|
|
2220
2221
|
}
|
|
2221
2222
|
const decision = await authorizeFreshOperation({
|
|
2222
2223
|
source: 'agent-tool', subject,
|
|
2223
|
-
intent: {
|
|
2224
|
+
intent: {
|
|
2225
|
+
operation: isMutation ? 'ec.aid.bind' : 'ec.aid.bind.status', scope: 'agent', source: 'agent-tool',
|
|
2226
|
+
args: {
|
|
2227
|
+
self: targetAid,
|
|
2228
|
+
...(command.action === 'bind' ? { ownerAid: command.ownerAid } : {}),
|
|
2229
|
+
...(command.action === 'accept' || command.action === 'reject'
|
|
2230
|
+
? { decision: command.action, operationId: command.operationId } : {}),
|
|
2231
|
+
},
|
|
2232
|
+
},
|
|
2224
2233
|
auditMetadata: { taskId: grant.taskId, messageId: grant.messageId },
|
|
2225
2234
|
});
|
|
2226
2235
|
if (!decision.allow)
|
|
@@ -4691,8 +4691,8 @@ export async function execMenuAction(cmd, action, args, channel, channelId, user
|
|
|
4691
4691
|
}
|
|
4692
4692
|
catch (error) {
|
|
4693
4693
|
const failure = ownershipFailure(error);
|
|
4694
|
-
const code = ['INVALID_ARGUMENT', 'INVALID_AID', 'INVALID_OWNER'].includes(failure.code) ? 'INVALID_ARGUMENT'
|
|
4695
|
-
: ['SUBJECT_REQUIRED', 'SUBJECT_UNAVAILABLE'].includes(failure.code) ? 'NOT_FOUND'
|
|
4694
|
+
const code = ['INVALID_ARGUMENT', 'INVALID_AID', 'INVALID_OWNER', 'INVALID_OPERATION'].includes(failure.code) ? 'INVALID_ARGUMENT'
|
|
4695
|
+
: ['SUBJECT_REQUIRED', 'SUBJECT_UNAVAILABLE', 'REQUEST_NOT_FOUND', 'not_found'].includes(failure.code) ? 'NOT_FOUND'
|
|
4696
4696
|
: ['OWNER_ALREADY_BOUND', 'BIND_CONFLICT', 'BIND_UNCERTAIN', 'CONSENSUS_REQUIRED', 'CLIENT_REPLACED', 'conflict', 'owner_locked'].includes(failure.code)
|
|
4697
4697
|
? 'CONFLICT' : 'INTERNAL_ERROR';
|
|
4698
4698
|
rawExecution = { error: failure.error, code, data: failure };
|