evolcore 0.0.24 → 0.0.25
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 +578 -561
- package/LICENSE +21 -21
- package/README.md +455 -455
- package/bin/codex-managed-acl.ps1 +160 -160
- package/bin/codex-managed-hook.mjs +208 -208
- package/bin/ec-safe-output.js +327 -327
- package/bin/ec.js +29 -29
- package/bin/install-codex-managed-hooks.mjs +555 -555
- package/dist/agents/claude-runner.js +4 -1
- package/dist/agents/codex-runner.js +7 -4
- package/dist/agents/ecagent-runner.js +14 -13
- package/dist/agents/gemini-runner.js +22 -2
- package/dist/aun/aid/agentmd.js +56 -4
- package/dist/aun/aid/index.js +1 -0
- package/dist/aun/aid/managed-operation.js +53 -1
- package/dist/aun/storage/client.js +4 -1
- package/dist/aun/storage/index.js +1 -1
- package/dist/cli/agent-command.js +186 -87
- package/dist/cli/agent-create.js +42 -4
- package/dist/cli/agent.js +103 -1
- package/dist/cli/aun-commands.js +360 -294
- package/dist/cli/bench.js +20 -20
- package/dist/cli/config.js +20 -20
- package/dist/cli/contact.js +10 -10
- package/dist/cli/ctl-command.js +22 -22
- package/dist/cli/daemon-commands.js +15 -15
- package/dist/cli/fs-command.js +67 -67
- package/dist/cli/handoff-command.js +7 -7
- package/dist/cli/index.js +77 -77
- package/dist/cli/link-rules.js +21 -21
- package/dist/cli/menu-client.js +11 -11
- package/dist/cli/net-check.js +22 -22
- package/dist/cli/queue-command.js +29 -29
- package/dist/cli/response.js +30 -30
- package/dist/cli/restart-monitor.js +30 -30
- package/dist/cli/stats.js +51 -51
- package/dist/cli/trigger-command.js +56 -56
- package/dist/config/builtin-roles.js +1 -0
- package/dist/config/config-manager.js +15 -0
- package/dist/config/config-operation-service.js +20 -3
- package/dist/config/resolved-config-op.js +39 -1
- package/dist/core/auth/operation-authorizer.js +62 -4
- package/dist/core/auth/operation-catalog.js +16 -0
- package/dist/core/command/agent-control.js +54 -25
- package/dist/core/command/cli-intent-parser.js +18 -0
- package/dist/core/command/command-handler.js +91 -16
- package/dist/core/command/menu-catalog.js +1 -0
- package/dist/core/command/menu-handler.js +41 -5
- package/dist/core/command/menu-protocol.js +1 -0
- package/dist/core/command/slash-handler.js +9 -9
- package/dist/core/event-catalog.js +5 -0
- package/dist/core/evolagent.js +3 -3
- package/dist/core/message/response-engine.js +12 -6
- package/dist/core/permission/tool-policy.js +45 -6
- package/dist/index.js +209 -162
- package/dist/stats/db.js +159 -159
- package/dist/stats/eck-vars.js +9 -9
- package/dist/stats/query.js +139 -139
- package/dist/stats/role-budget.js +6 -6
- package/dist/stats/writer.js +51 -51
- package/dist/utils/avatar-upload.js +282 -23
- package/dist/utils/error-dict.json +160 -160
- package/dist/utils/macos-autostart.js +22 -22
- package/dist/utils/model-prices.jsonl +23 -23
- package/dist/utils/welcome.js +22 -22
- package/ecagent/LICENSE +21 -21
- package/ecagent/NOTICE +11 -11
- package/ecagent/README.md +61 -61
- 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/kits/docs/GUIDE.md +20 -20
- package/kits/docs/INDEX.md +66 -66
- package/kits/docs/aun/CHEATSHEET.md +19 -19
- package/kits/docs/aun/SYNC_PROTOCOL.md +15 -15
- package/kits/docs/channels/aun.md +56 -56
- package/kits/docs/channels/feishu.md +56 -56
- package/kits/docs/context-assembly.md +365 -364
- 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 +71 -69
- package/kits/docs/evolcore/agent-create.md +170 -156
- package/kits/docs/evolcore/agent.md +83 -73
- package/kits/docs/evolcore/aid.md +64 -62
- package/kits/docs/evolcore/codex-windows-sandbox.md +146 -0
- package/kits/docs/evolcore/config.md +195 -195
- package/kits/docs/evolcore/contact.md +68 -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 +243 -243
- package/kits/docs/evolcore/group-fs.md +17 -17
- package/kits/docs/evolcore/group-rules.md +251 -251
- package/kits/docs/evolcore/group.md +152 -152
- package/kits/docs/evolcore/menu-client.md +34 -34
- package/kits/docs/evolcore/model.md +50 -50
- package/kits/docs/evolcore/msg.md +165 -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 +50 -50
- package/kits/docs/evolcore/trigger.md +575 -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 +270 -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 +25 -25
- package/kits/docs/venues/private.md +10 -10
- package/kits/eck_manifest.auxiliary.json +43 -43
- package/kits/eck_manifest.json +195 -183
- 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 +162 -162
- package/kits/rules/02-navigation.md +96 -96
- package/kits/rules/03-identity.md +39 -37
- package/kits/rules/04-relation.md +75 -75
- package/kits/rules/05-venue.md +60 -60
- package/kits/rules/06-channel.md +63 -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 +427 -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 +201 -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 +96 -84
- package/kits/templates/roles/member.json +97 -96
- package/kits/templates/roles/owner.json +9 -9
- package/kits/templates/roles/visitor.json +86 -85
- package/kits/templates/system-fragments/baseagent.md +14 -14
- package/kits/templates/system-fragments/bootstrap.md +38 -29
- package/kits/templates/system-fragments/channel.md +64 -64
- package/kits/templates/system-fragments/commands.md +28 -28
- package/kits/templates/system-fragments/identity.md +13 -13
- package/kits/templates/system-fragments/relation.md +19 -19
- package/kits/templates/system-fragments/session.md +59 -59
- package/kits/templates/system-fragments/venue.md +31 -31
- package/package.json +98 -98
- package/skills/eclink/SKILL.md +0 -84
- package/skills/eclink/agents/openai.yaml +0 -4
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
2
|
import { getArgValue, isHelpFlag, wantsHelp } from './help.js';
|
|
3
3
|
import { isHostChinese } from '../utils/locale.js';
|
|
4
|
+
import { readTaskRuntimeContextFromEnv } from './task-context.js';
|
|
4
5
|
function formatTimeAgo(ms) {
|
|
5
6
|
const sec = Math.floor(ms / 1000);
|
|
6
7
|
if (sec < 60)
|
|
@@ -25,7 +26,7 @@ function formatBytes(bytes) {
|
|
|
25
26
|
export async function cmdAgent(args) {
|
|
26
27
|
const sub = args[0];
|
|
27
28
|
const formatJson = getArgValue(args, '--format') === 'json';
|
|
28
|
-
const commands = new Set(['list', 'show', 'new', 'enable', 'disable', 'get', 'set', 'rename', 'ready', 'reload', 'delete']);
|
|
29
|
+
const commands = new Set(['list', 'show', 'new', 'enable', 'disable', 'get', 'set', 'persona', 'rename', 'ready', 'reload', 'delete']);
|
|
29
30
|
if (sub === 'create') {
|
|
30
31
|
const error = { ok: false, code: 'INVALID_COMMAND', error: '`ec agent create` is not a command; use `ec agent new`.' };
|
|
31
32
|
if (formatJson)
|
|
@@ -36,41 +37,45 @@ export async function cmdAgent(args) {
|
|
|
36
37
|
return;
|
|
37
38
|
}
|
|
38
39
|
if (!sub || isHelpFlag(sub) || (wantsHelp(args) && !commands.has(sub))) {
|
|
39
|
-
console.log(`用法: ec agent <command>
|
|
40
|
-
|
|
41
|
-
Commands:
|
|
42
|
-
list 列出所有 agent
|
|
43
|
-
show <aid> 查看 agent 详情(身份 + 配置 + 连接 + 会话 + 路径)
|
|
44
|
-
new [aid] 交互式创建 agent
|
|
45
|
-
new <aid> --non-interactive ... 非交互式创建
|
|
46
|
-
enable <aid> 启用 agent
|
|
47
|
-
disable <aid> 停用 agent
|
|
48
|
-
get <aid> <key> 读取单个配置字段(支持点路径)
|
|
40
|
+
console.log(`用法: ec agent <command>
|
|
41
|
+
|
|
42
|
+
Commands:
|
|
43
|
+
list 列出所有 agent
|
|
44
|
+
show <aid> 查看 agent 详情(身份 + 配置 + 连接 + 会话 + 路径)
|
|
45
|
+
new [aid] 交互式创建 agent
|
|
46
|
+
new <aid> --non-interactive ... 非交互式创建
|
|
47
|
+
enable <aid> 启用 agent
|
|
48
|
+
disable <aid> 停用 agent
|
|
49
|
+
get <aid> <key> 读取单个配置字段(支持点路径)
|
|
49
50
|
set <aid> <key> <val> 修改单个配置字段(支持点路径)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
ec agent
|
|
64
|
-
ec agent
|
|
51
|
+
persona show 查看当前 Agent 的 persona.md
|
|
52
|
+
persona --text <text> 用文本设置当前 Agent 的 persona.md
|
|
53
|
+
persona --file <path> 用 .md/.txt 文件设置当前 Agent 的 persona.md
|
|
54
|
+
rename <aid> <name> 修改 agent.md 中的显示名称
|
|
55
|
+
ready <aid> 标记 bootstrap 完成,进入 active 状态
|
|
56
|
+
reload [aid] 热重载配置(无参数=全量 resync)
|
|
57
|
+
delete <aid> [--purge] 删除 agent
|
|
58
|
+
|
|
59
|
+
Options:
|
|
60
|
+
--format json 输出 JSON 格式
|
|
61
|
+
--help, -h 各子命令均支持,查看详细用法
|
|
62
|
+
|
|
63
|
+
示例:
|
|
64
|
+
ec agent list
|
|
65
|
+
ec agent show mybot.agentid.pub
|
|
66
|
+
ec agent new mybot.agentid.pub
|
|
67
|
+
ec agent enable mybot.agentid.pub
|
|
68
|
+
ec agent get mybot.agentid.pub active_baseagent
|
|
65
69
|
ec agent set mybot.agentid.pub active_baseagent codex
|
|
66
|
-
ec agent
|
|
67
|
-
ec agent
|
|
70
|
+
ec agent persona --text "你是一名严谨的诊断工程师。"
|
|
71
|
+
ec agent rename mybot.agentid.pub "New Name"
|
|
72
|
+
ec agent ready mybot.agentid.pub
|
|
68
73
|
ec agent delete mybot.agentid.pub --purge`);
|
|
69
74
|
return;
|
|
70
75
|
}
|
|
71
|
-
const { agentList, agentShow, agentCreateInteractive, agentCreateNonInteractive, agentReload, agentEnable, agentDisable, agentGet, agentSet, agentRename, agentDelete, agentReady, runManagedAgentOperation, } = await import('./agent.js');
|
|
72
|
-
const { parseAgentOwnerArgs, resolveAgentCreatePlan, validateAgentCreatePlan } = await import('./agent-create.js');
|
|
73
|
-
if (process.env.EVOLCORE_SESSION_ID && !wantsHelp(args) && !new Set(['get', 'set', 'ready']).has(sub)) {
|
|
76
|
+
const { agentList, agentShow, agentCreateInteractive, agentCreateNonInteractive, agentReload, agentEnable, agentDisable, agentGet, agentSet, agentPersona, agentRename, agentDelete, agentReady, runManagedAgentOperation, } = await import('./agent.js');
|
|
77
|
+
const { parseAgentOwnerArgs, parseAgentTags, resolveAgentCreatePlan, validateAgentCreatePlan } = await import('./agent-create.js');
|
|
78
|
+
if (process.env.EVOLCORE_SESSION_ID && !wantsHelp(args) && !new Set(['get', 'set', 'persona', 'ready']).has(sub)) {
|
|
74
79
|
if (sub === 'new' && !args.includes('--non-interactive')) {
|
|
75
80
|
const error = {
|
|
76
81
|
ok: false,
|
|
@@ -132,8 +137,8 @@ Options:
|
|
|
132
137
|
// --- list ---
|
|
133
138
|
if (sub === 'list') {
|
|
134
139
|
if (wantsHelp(args)) {
|
|
135
|
-
console.log(`用法: ec agent list [--format json]
|
|
136
|
-
|
|
140
|
+
console.log(`用法: ec agent list [--format json]
|
|
141
|
+
|
|
137
142
|
列出所有 agent,显示名称、状态、渠道、项目、基座、最后活跃时间。`);
|
|
138
143
|
return;
|
|
139
144
|
}
|
|
@@ -203,26 +208,27 @@ Options:
|
|
|
203
208
|
// --- new ---
|
|
204
209
|
if (sub === 'new') {
|
|
205
210
|
if (wantsHelp(args)) {
|
|
206
|
-
console.log(`用法: ec agent new [aid] 交互式创建
|
|
207
|
-
ec agent new <aid> --non-interactive [选项]
|
|
208
|
-
|
|
209
|
-
非交互模式选项:
|
|
210
|
-
--project <path> 默认: 当前目录
|
|
211
|
-
--baseagent <claude|codex|gemini|ecagent>
|
|
212
|
-
默认: defaults 配置,否则检测本机可用基座
|
|
211
|
+
console.log(`用法: ec agent new [aid] 交互式创建
|
|
212
|
+
ec agent new <aid> --non-interactive [选项]
|
|
213
|
+
|
|
214
|
+
非交互模式选项:
|
|
215
|
+
--project <path> 默认: 当前目录
|
|
216
|
+
--baseagent <claude|codex|gemini|ecagent>
|
|
217
|
+
默认: defaults 配置,否则检测本机可用基座
|
|
213
218
|
--owner <aid> 默认: daemon.json 第一个 owner
|
|
214
219
|
--owners <json-array> 多个 Owner;与 --owner 互斥
|
|
215
220
|
--handoff <context> 当前任务的 Bootstrap 上下文
|
|
216
|
-
--name <display-name> 默认: package.json name,否则目录名
|
|
221
|
+
--name <display-name> 默认: package.json name,否则目录名
|
|
217
222
|
--description <text> 默认: package.json description,否则使用 EvolCore 默认描述
|
|
218
|
-
--
|
|
219
|
-
--
|
|
220
|
-
--
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
ec agent new mybot.agentid.pub
|
|
225
|
-
ec agent new mybot.agentid.pub --non-interactive
|
|
223
|
+
--tags <json-array> 3 到 6 个标签,例如 '["coding","diagnostics","logs"]'
|
|
224
|
+
--dry-run 只预览最终参数,不注册 AID、不写文件
|
|
225
|
+
--force 覆盖已有 config.json
|
|
226
|
+
--format json 输出 JSON
|
|
227
|
+
|
|
228
|
+
示例:
|
|
229
|
+
ec agent new mybot.agentid.pub
|
|
230
|
+
ec agent new mybot.agentid.pub --non-interactive
|
|
231
|
+
ec agent new mybot.agentid.pub --non-interactive --dry-run --format json
|
|
226
232
|
ec agent new mybot.agentid.pub --non-interactive --project ../project --baseagent claude`);
|
|
227
233
|
return;
|
|
228
234
|
}
|
|
@@ -259,6 +265,19 @@ Options:
|
|
|
259
265
|
process.exitCode = 1;
|
|
260
266
|
return;
|
|
261
267
|
}
|
|
268
|
+
let tags;
|
|
269
|
+
try {
|
|
270
|
+
tags = parseAgentTags(getArg('--tags'));
|
|
271
|
+
}
|
|
272
|
+
catch (error) {
|
|
273
|
+
const result = { ok: false, error: error instanceof Error ? error.message : String(error) };
|
|
274
|
+
if (formatJson)
|
|
275
|
+
console.log(JSON.stringify(result));
|
|
276
|
+
else
|
|
277
|
+
console.error(`❌ ${result.error}`);
|
|
278
|
+
process.exitCode = 1;
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
262
281
|
const plan = resolveAgentCreatePlan({
|
|
263
282
|
aid: name,
|
|
264
283
|
project: getArg('--project'),
|
|
@@ -267,6 +286,7 @@ Options:
|
|
|
267
286
|
handoff: getArg('--handoff'),
|
|
268
287
|
name: getArg('--name'),
|
|
269
288
|
description: getArg('--description'),
|
|
289
|
+
tags,
|
|
270
290
|
force: args.includes('--force'),
|
|
271
291
|
});
|
|
272
292
|
const validationError = validateAgentCreatePlan(plan);
|
|
@@ -304,6 +324,7 @@ Options:
|
|
|
304
324
|
owners: plan.owners,
|
|
305
325
|
name: plan.name,
|
|
306
326
|
description: plan.description,
|
|
327
|
+
tags: plan.tags,
|
|
307
328
|
force: args.includes('--force'),
|
|
308
329
|
});
|
|
309
330
|
if (!result.ok) {
|
|
@@ -399,11 +420,11 @@ Options:
|
|
|
399
420
|
// --- reload ---
|
|
400
421
|
if (sub === 'reload') {
|
|
401
422
|
if (wantsHelp(args)) {
|
|
402
|
-
console.log(`用法: ec agent reload [aid] [--force] [--format json]
|
|
403
|
-
|
|
404
|
-
热重载 agent 配置。
|
|
405
|
-
无参数 全量 resync(扫磁盘,新增上线、删除下线、修改热更新)
|
|
406
|
-
<aid> 仅热重载指定 agent
|
|
423
|
+
console.log(`用法: ec agent reload [aid] [--force] [--format json]
|
|
424
|
+
|
|
425
|
+
热重载 agent 配置。
|
|
426
|
+
无参数 全量 resync(扫磁盘,新增上线、删除下线、修改热更新)
|
|
427
|
+
<aid> 仅热重载指定 agent
|
|
407
428
|
--force 中断目标 Agent 的运行中任务并清空排队任务后重载(仅与 <aid> 同用)`);
|
|
408
429
|
return;
|
|
409
430
|
}
|
|
@@ -435,9 +456,9 @@ Options:
|
|
|
435
456
|
// --- enable ---
|
|
436
457
|
if (sub === 'enable') {
|
|
437
458
|
if (wantsHelp(args)) {
|
|
438
|
-
console.log(`用法: ec agent enable <aid> [--force] [--format json]
|
|
439
|
-
|
|
440
|
-
启用 agent。若服务运行中会热重载,否则下次 ec start 时生效。
|
|
459
|
+
console.log(`用法: ec agent enable <aid> [--force] [--format json]
|
|
460
|
+
|
|
461
|
+
启用 agent。若服务运行中会热重载,否则下次 ec start 时生效。
|
|
441
462
|
--force 中断目标 Agent 的运行中任务并清空排队任务后重载`);
|
|
442
463
|
return;
|
|
443
464
|
}
|
|
@@ -467,9 +488,9 @@ Options:
|
|
|
467
488
|
// --- disable ---
|
|
468
489
|
if (sub === 'disable') {
|
|
469
490
|
if (wantsHelp(args)) {
|
|
470
|
-
console.log(`用法: ec agent disable <aid> [--force] [--format json]
|
|
471
|
-
|
|
472
|
-
停用 agent。若服务运行中会热重载离线,否则在配置中标记为禁用。
|
|
491
|
+
console.log(`用法: ec agent disable <aid> [--force] [--format json]
|
|
492
|
+
|
|
493
|
+
停用 agent。若服务运行中会热重载离线,否则在配置中标记为禁用。
|
|
473
494
|
--force 中断目标 Agent 的运行中任务并清空排队任务后重载`);
|
|
474
495
|
return;
|
|
475
496
|
}
|
|
@@ -497,16 +518,94 @@ Options:
|
|
|
497
518
|
return;
|
|
498
519
|
}
|
|
499
520
|
// --- get ---
|
|
500
|
-
if (sub === '
|
|
521
|
+
if (sub === 'persona') {
|
|
501
522
|
if (wantsHelp(args)) {
|
|
502
|
-
console.log(`用法: ec agent
|
|
523
|
+
console.log(`用法: ec agent persona show [--format json]
|
|
524
|
+
ec agent persona --text <text> [--format json]
|
|
525
|
+
ec agent persona --file <path> [--format json]
|
|
503
526
|
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
527
|
+
读取或设置当前 Agent 的 persona.md。--file 只接受 .md/.txt 文本文件。`);
|
|
528
|
+
return;
|
|
529
|
+
}
|
|
530
|
+
const formatSuffix = args.length >= 3
|
|
531
|
+
&& args.at(-2) === '--format'
|
|
532
|
+
&& args.at(-1) === 'json';
|
|
533
|
+
const commandArgs = formatSuffix ? args.slice(0, -2) : args;
|
|
534
|
+
const personaArgs = commandArgs.slice(1);
|
|
535
|
+
const invalid = (error) => {
|
|
536
|
+
const result = { ok: false, code: 'INVALID_ARGS', error };
|
|
537
|
+
if (formatJson)
|
|
538
|
+
console.log(JSON.stringify(result));
|
|
539
|
+
else
|
|
540
|
+
console.error(`❌ ${result.error}`);
|
|
541
|
+
process.exitCode = 1;
|
|
542
|
+
return;
|
|
543
|
+
};
|
|
544
|
+
if (!formatSuffix && args.includes('--format')) {
|
|
545
|
+
invalid('persona 仅支持末尾的 --format json');
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
548
|
+
let text;
|
|
549
|
+
let file;
|
|
550
|
+
if (personaArgs.length === 1 && personaArgs[0] === 'show') {
|
|
551
|
+
// show is the only read form; no payload is accepted.
|
|
552
|
+
}
|
|
553
|
+
else if (personaArgs.length === 2 && personaArgs[0] === '--text') {
|
|
554
|
+
text = personaArgs[1];
|
|
555
|
+
if (text === undefined) {
|
|
556
|
+
invalid('persona --text 缺少参数');
|
|
557
|
+
return;
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
else if (personaArgs.length === 2 && personaArgs[0] === '--file') {
|
|
561
|
+
file = personaArgs[1];
|
|
562
|
+
if (!file || file.startsWith('-')) {
|
|
563
|
+
invalid('persona --file 缺少有效路径');
|
|
564
|
+
return;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
else {
|
|
568
|
+
invalid('用法: ec agent persona show | --text <text> | --file <path>');
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
const taskAid = process.env.EVOLCORE_SESSION_ID ? (readTaskRuntimeContextFromEnv()?.selfAid || '') : '';
|
|
572
|
+
const aid = taskAid || process.env.EVOLCORE_SELF_AID || '';
|
|
573
|
+
if (!aid) {
|
|
574
|
+
const result = { ok: false, code: 'INVALID_ARGS', error: '无法确定当前 Agent AID' };
|
|
575
|
+
if (formatJson)
|
|
576
|
+
console.log(JSON.stringify(result));
|
|
577
|
+
else
|
|
578
|
+
console.error(`❌ ${result.error}`);
|
|
579
|
+
process.exitCode = 1;
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
582
|
+
const result = await agentPersona(aid, { text, file });
|
|
583
|
+
if (!result.ok) {
|
|
584
|
+
if (formatJson)
|
|
585
|
+
console.log(JSON.stringify(result));
|
|
586
|
+
else
|
|
587
|
+
console.error(`❌ ${result.error}`);
|
|
588
|
+
process.exitCode = 1;
|
|
589
|
+
return;
|
|
590
|
+
}
|
|
591
|
+
if (formatJson)
|
|
592
|
+
console.log(JSON.stringify(result, null, 2));
|
|
593
|
+
else if (result.saved)
|
|
594
|
+
console.log(`✓ ${aid} persona.md 已保存`);
|
|
595
|
+
else
|
|
596
|
+
console.log(result.content ?? '(persona.md 不存在)');
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
599
|
+
if (sub === 'get') {
|
|
600
|
+
if (wantsHelp(args)) {
|
|
601
|
+
console.log(`用法: ec agent get <aid> <key> [--format json]
|
|
602
|
+
|
|
603
|
+
读取单个配置字段。key 支持点路径,如 "channels.aun.enabled"。
|
|
604
|
+
托管任务通过 daemon 统一鉴权;无会话的本机 CLI 走控制面。
|
|
605
|
+
|
|
606
|
+
示例:
|
|
607
|
+
ec agent get mybot.agentid.pub active_baseagent
|
|
608
|
+
ec agent get mybot.agentid.pub observable
|
|
510
609
|
ec agent get mybot.agentid.pub channels.aun.enabled`);
|
|
511
610
|
return;
|
|
512
611
|
}
|
|
@@ -538,15 +637,15 @@ Options:
|
|
|
538
637
|
// --- set ---
|
|
539
638
|
if (sub === 'set') {
|
|
540
639
|
if (wantsHelp(args)) {
|
|
541
|
-
console.log(`用法: ec agent set <aid> <key> <value> [--format json]
|
|
542
|
-
|
|
543
|
-
修改单个配置字段。key 支持点路径。本机控制面会尝试热重载;托管任务如需重载须另行执行 agent reload。
|
|
544
|
-
托管任务通过 daemon 统一鉴权;无会话的本机 CLI 走控制面。
|
|
545
|
-
|
|
546
|
-
示例:
|
|
547
|
-
ec agent set mybot.agentid.pub active_baseagent codex
|
|
548
|
-
ec agent set mybot.agentid.pub observable true
|
|
549
|
-
ec agent set mybot.agentid.pub observable false
|
|
640
|
+
console.log(`用法: ec agent set <aid> <key> <value> [--format json]
|
|
641
|
+
|
|
642
|
+
修改单个配置字段。key 支持点路径。本机控制面会尝试热重载;托管任务如需重载须另行执行 agent reload。
|
|
643
|
+
托管任务通过 daemon 统一鉴权;无会话的本机 CLI 走控制面。
|
|
644
|
+
|
|
645
|
+
示例:
|
|
646
|
+
ec agent set mybot.agentid.pub active_baseagent codex
|
|
647
|
+
ec agent set mybot.agentid.pub observable true
|
|
648
|
+
ec agent set mybot.agentid.pub observable false
|
|
550
649
|
ec agent set mybot.agentid.pub channels.aun.enabled true`);
|
|
551
650
|
return;
|
|
552
651
|
}
|
|
@@ -578,8 +677,8 @@ Options:
|
|
|
578
677
|
// --- ready ---
|
|
579
678
|
if (sub === 'ready') {
|
|
580
679
|
if (wantsHelp(args)) {
|
|
581
|
-
console.log(`用法: ec agent ready <aid> [--format json]
|
|
582
|
-
|
|
680
|
+
console.log(`用法: ec agent ready <aid> [--format json]
|
|
681
|
+
|
|
583
682
|
标记 agent bootstrap 已完成,将 lifecycle 切换为 active。该命令允许 agent 在工具调用中自报完成。`);
|
|
584
683
|
return;
|
|
585
684
|
}
|
|
@@ -609,10 +708,10 @@ Options:
|
|
|
609
708
|
// --- delete ---
|
|
610
709
|
if (sub === 'delete') {
|
|
611
710
|
if (wantsHelp(args)) {
|
|
612
|
-
console.log(`用法: ec agent delete <aid> [--purge] [--format json]
|
|
613
|
-
|
|
614
|
-
删除 agent 的配置。
|
|
615
|
-
--purge 同时清除该 agent 的会话、消息、日志等运行时数据
|
|
711
|
+
console.log(`用法: ec agent delete <aid> [--purge] [--format json]
|
|
712
|
+
|
|
713
|
+
删除 agent 的配置。
|
|
714
|
+
--purge 同时清除该 agent 的会话、消息、日志等运行时数据
|
|
616
715
|
默认 仅删除 config.json,运行时数据保留`);
|
|
617
716
|
return;
|
|
618
717
|
}
|
|
@@ -643,8 +742,8 @@ Options:
|
|
|
643
742
|
// --- show ---
|
|
644
743
|
if (sub === 'show') {
|
|
645
744
|
if (wantsHelp(args)) {
|
|
646
|
-
console.log(`用法: ec agent show <aid> [--format json]
|
|
647
|
-
|
|
745
|
+
console.log(`用法: ec agent show <aid> [--format json]
|
|
746
|
+
|
|
648
747
|
查看 agent 详情:身份、配置、连接状态、会话路径等。`);
|
|
649
748
|
return;
|
|
650
749
|
}
|
|
@@ -673,8 +772,8 @@ Options:
|
|
|
673
772
|
// --- rename ---
|
|
674
773
|
if (sub === 'rename') {
|
|
675
774
|
if (wantsHelp(args)) {
|
|
676
|
-
console.log(`用法: ec agent rename <aid> <name> [--format json]
|
|
677
|
-
|
|
775
|
+
console.log(`用法: ec agent rename <aid> <name> [--format json]
|
|
776
|
+
|
|
678
777
|
修改本地 AIDs/<aid>/agent.md 中的 name 字段。`);
|
|
679
778
|
return;
|
|
680
779
|
}
|
package/dist/cli/agent-create.js
CHANGED
|
@@ -12,7 +12,27 @@ import { resolveEcagentConfig } from '../agents/baseagent.js';
|
|
|
12
12
|
import { AUTO_BASEAGENT_CANDIDATES, BASEAGENT_CANDIDATES, detectAvailableBaseagents, } from '../agents/baseagent-availability.js';
|
|
13
13
|
import { agentProjectRootFromDefaults, deriveAgentProjectPath } from '../utils/project-path.js';
|
|
14
14
|
import { isValidAid } from '../aun/aid/validation.js';
|
|
15
|
-
import { DEFAULT_AGENT_DESCRIPTION } from '../aun/aid/agentmd.js';
|
|
15
|
+
import { AGENT_TAG_MAX_COUNT, AGENT_TAG_MIN_COUNT, DEFAULT_AGENT_DESCRIPTION, validateAgentTags, } from '../aun/aid/agentmd.js';
|
|
16
|
+
export function parseAgentTags(raw) {
|
|
17
|
+
if (raw === undefined)
|
|
18
|
+
return undefined;
|
|
19
|
+
let parsed;
|
|
20
|
+
try {
|
|
21
|
+
parsed = JSON.parse(raw);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
throw new Error('--tags must be a JSON array of 3 to 6 valid tags');
|
|
25
|
+
}
|
|
26
|
+
if (!Array.isArray(parsed))
|
|
27
|
+
throw new Error('--tags must be a JSON array of 3 to 6 valid tags');
|
|
28
|
+
const tags = parsed.map(value => typeof value === 'string' ? value.trim() : value);
|
|
29
|
+
const tagErrors = validateAgentTags(tags, { minCount: AGENT_TAG_MIN_COUNT, maxCount: AGENT_TAG_MAX_COUNT });
|
|
30
|
+
if (tagErrors.length > 0)
|
|
31
|
+
throw new Error(`--tags ${tagErrors.join('; ')}`);
|
|
32
|
+
// Duplicate labels are harmless at the wire level, but should not consume
|
|
33
|
+
// the advertised 3-6 tag budget or produce duplicate frontmatter entries.
|
|
34
|
+
return [...new Set(tags)];
|
|
35
|
+
}
|
|
16
36
|
export function validateAgentOwnerOptions(options) {
|
|
17
37
|
if (options.owner !== undefined && options.owners !== undefined) {
|
|
18
38
|
return 'Options --owner and --owners are mutually exclusive';
|
|
@@ -120,7 +140,7 @@ export function resolveAgentCreatePlan(options) {
|
|
|
120
140
|
const description = options.description?.trim() || metadata.description || DEFAULT_AGENT_DESCRIPTION;
|
|
121
141
|
const configExists = isValidAid(aid) && fs.existsSync(path.join(resolvePaths().agentsDir, aid, 'config.json'));
|
|
122
142
|
return {
|
|
123
|
-
aid, project, baseagent, owner, owners, handoff: options.handoff, name, description,
|
|
143
|
+
aid, project, baseagent, owner, owners, handoff: options.handoff, name, description, tags: options.tags,
|
|
124
144
|
force: options.force === true, configExists, baseagentSource, ownerSource,
|
|
125
145
|
nameSource: options.name?.trim() ? 'argument' : metadata.name ? 'package' : 'directory',
|
|
126
146
|
descriptionSource: options.description?.trim() ? 'argument' : metadata.description ? 'package' : 'default',
|
|
@@ -134,6 +154,11 @@ export function validateAgentCreatePlan(plan) {
|
|
|
134
154
|
return `Invalid AID "${plan.aid}": must be a valid multi-level domain (e.g. mybot.agentid.pub)`;
|
|
135
155
|
if (plan.configExists && !plan.force)
|
|
136
156
|
return `Agent "${plan.aid}" already exists (use --force to overwrite)`;
|
|
157
|
+
if (plan.tags !== undefined) {
|
|
158
|
+
const tagErrors = validateAgentTags(plan.tags, { minCount: AGENT_TAG_MIN_COUNT, maxCount: AGENT_TAG_MAX_COUNT });
|
|
159
|
+
if (tagErrors.length > 0)
|
|
160
|
+
return `Invalid tags: ${tagErrors.join('; ')}`;
|
|
161
|
+
}
|
|
137
162
|
if (!plan.baseagent)
|
|
138
163
|
return 'No usable baseagent detected. Pass --baseagent or configure a baseagent in agents/defaults.json.';
|
|
139
164
|
if (!BASEAGENT_CANDIDATES.includes(plan.baseagent)) {
|
|
@@ -305,6 +330,14 @@ export async function agentCreateInteractive(opts = {}) {
|
|
|
305
330
|
const defaultName = aid.split('.')[0];
|
|
306
331
|
const agentName = (await ask(`Display name [${defaultName}]: `)).trim() || defaultName;
|
|
307
332
|
const agentDescription = (await ask('Description (optional): ')).trim() || '';
|
|
333
|
+
const tagInput = (await ask('Tags (3-6, comma separated; optional): ')).trim();
|
|
334
|
+
let agentTags;
|
|
335
|
+
if (tagInput) {
|
|
336
|
+
agentTags = [...new Set(tagInput.split(/[,,\s]+/).map(tag => tag.trim()).filter(Boolean))];
|
|
337
|
+
const tagErrors = validateAgentTags(agentTags, { minCount: AGENT_TAG_MIN_COUNT, maxCount: AGENT_TAG_MAX_COUNT });
|
|
338
|
+
if (tagErrors.length > 0)
|
|
339
|
+
return { ok: false, error: `Invalid tags: ${tagErrors.join('; ')}` };
|
|
340
|
+
}
|
|
308
341
|
if (ownRl)
|
|
309
342
|
rl.close();
|
|
310
343
|
saveAgent(withStaticOwner({ $schema_version: CONFIG_SCHEMA_VERSION, aid, enabled: true, lifecycle: 'created', channels: [], projects: { defaultPath: projectPath } }, owner));
|
|
@@ -313,7 +346,7 @@ export async function agentCreateInteractive(opts = {}) {
|
|
|
313
346
|
ensureAgentDirSkeleton(aid);
|
|
314
347
|
let agentmdUploaded = false;
|
|
315
348
|
try {
|
|
316
|
-
const content = buildInitialAgentMd({ aid, name: agentName, description: agentDescription });
|
|
349
|
+
const content = buildInitialAgentMd({ aid, name: agentName, description: agentDescription, tags: agentTags });
|
|
317
350
|
const aunPath = process.env.AUN_HOME || defaultAunPath();
|
|
318
351
|
let lastError;
|
|
319
352
|
for (let attempt = 1; attempt <= 3; attempt++) {
|
|
@@ -411,6 +444,11 @@ export async function agentCreateNonInteractive(opts, runtime = {}) {
|
|
|
411
444
|
const ownerError = validateAgentOwnerOptions(opts);
|
|
412
445
|
if (ownerError)
|
|
413
446
|
return failValidating(ownerError);
|
|
447
|
+
if (opts.tags !== undefined) {
|
|
448
|
+
const tagErrors = validateAgentTags(opts.tags, { minCount: AGENT_TAG_MIN_COUNT, maxCount: AGENT_TAG_MAX_COUNT });
|
|
449
|
+
if (tagErrors.length > 0)
|
|
450
|
+
return failValidating(`Invalid tags: ${tagErrors.join('; ')}`);
|
|
451
|
+
}
|
|
414
452
|
if (!isValidAid(opts.aid))
|
|
415
453
|
return failValidating(`Invalid AID "${opts.aid}": must be a valid multi-level domain (e.g. mybot.agentid.pub)`);
|
|
416
454
|
const agentDirPath = path.join(p.agentsDir, opts.aid);
|
|
@@ -484,7 +522,7 @@ export async function agentCreateNonInteractive(opts, runtime = {}) {
|
|
|
484
522
|
opts.onPhase?.('uploading_agentmd', 'begin');
|
|
485
523
|
let agentmdUploaded = false;
|
|
486
524
|
try {
|
|
487
|
-
const content = buildInitialAgentMd({ aid: opts.aid, name: opts.name, description: opts.description });
|
|
525
|
+
const content = buildInitialAgentMd({ aid: opts.aid, name: opts.name, description: opts.description, tags: opts.tags });
|
|
488
526
|
const aunPath = process.env.AUN_HOME || defaultAunPath();
|
|
489
527
|
let lastError;
|
|
490
528
|
for (let attempt = 1; attempt <= 3; attempt++) {
|
package/dist/cli/agent.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import { resolvePaths, agentMdPath as getAgentMdPathFromPaths, aunPath as defaultAunPath } from '../paths.js';
|
|
3
|
+
import { resolvePaths, agentMdPath as getAgentMdPathFromPaths, agentPersonalDir, aunPath as defaultAunPath } from '../paths.js';
|
|
4
4
|
import { loadDefaults, loadAllAgents, loadAgent, saveAgent, ensureAgentDirSkeleton } from '../config-store.js';
|
|
5
5
|
import { initConfigManager } from '../config/config-manager.js';
|
|
6
6
|
import { resolveConfigCommand } from '../config/resolved-config-op.js';
|
|
@@ -12,6 +12,7 @@ import { agentProjectRootFromDefaults, deriveAgentProjectPath } from '../utils/p
|
|
|
12
12
|
import { isValidChannelName } from '../core/channel-loader.js';
|
|
13
13
|
import { AGENT_DELEGATION_TOKEN_ENV } from '../core/auth/agent-delegation.js';
|
|
14
14
|
import { readTaskRuntimeContextFromEnv } from './task-context.js';
|
|
15
|
+
import { isHClassPath, isLClassPath, isSameOrDescendant } from '../core/permission/protected-paths.js';
|
|
15
16
|
export { agentCreateInteractive, agentCreateNonInteractive, parseAgentOwnerArgs, resolveAgentCreatePlan, validateAgentCreatePlan, validateAgentOwnerOptions, } from './agent-create.js';
|
|
16
17
|
/** Route agent lifecycle commands from a managed task through daemon IPC. */
|
|
17
18
|
export async function runManagedAgentOperation(argv) {
|
|
@@ -456,6 +457,107 @@ export async function agentSet(aid, key, rawValue, options = {}) {
|
|
|
456
457
|
catch { }
|
|
457
458
|
return { ok: true, aid, key, value, reloaded };
|
|
458
459
|
}
|
|
460
|
+
export const AGENT_PERSONA_MAX_BYTES = 64 * 1024;
|
|
461
|
+
function validatePersonaContent(content) {
|
|
462
|
+
if (content.includes('\0'))
|
|
463
|
+
return 'persona 只能包含文本内容';
|
|
464
|
+
if (Buffer.byteLength(content, 'utf8') > AGENT_PERSONA_MAX_BYTES) {
|
|
465
|
+
return `persona 不能超过 ${AGENT_PERSONA_MAX_BYTES} bytes`;
|
|
466
|
+
}
|
|
467
|
+
return null;
|
|
468
|
+
}
|
|
469
|
+
function readPersonaSource(file) {
|
|
470
|
+
const resolved = path.resolve(file);
|
|
471
|
+
if (!/\.(?:md|txt)$/i.test(resolved)) {
|
|
472
|
+
return { ok: false, code: 'INVALID_ARGS', error: '--file 只接受 .md 或 .txt 文本文件' };
|
|
473
|
+
}
|
|
474
|
+
try {
|
|
475
|
+
const stat = fs.statSync(resolved);
|
|
476
|
+
if (!stat.isFile())
|
|
477
|
+
return { ok: false, code: 'INVALID_ARGS', error: `--file 必须指向普通文件: ${resolved}` };
|
|
478
|
+
const content = fs.readFileSync(resolved, 'utf8');
|
|
479
|
+
const error = validatePersonaContent(content);
|
|
480
|
+
return error ? { ok: false, code: 'INVALID_ARGS', error } : { ok: true, content };
|
|
481
|
+
}
|
|
482
|
+
catch (e) {
|
|
483
|
+
return { ok: false, code: 'READ_FAILED', error: `无法读取 --file: ${e?.message || e}` };
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
/** Read or replace the current Agent's personal/persona.md. */
|
|
487
|
+
export async function agentPersona(aid, options = {}) {
|
|
488
|
+
if (options.text !== undefined && options.file !== undefined)
|
|
489
|
+
return { ok: false, code: 'INVALID_ARGS', error: '--text 与 --file 不能同时使用' };
|
|
490
|
+
const managedSession = !!process.env.EVOLCORE_SESSION_ID && !options.trustedLocal;
|
|
491
|
+
let text = options.text;
|
|
492
|
+
if (options.file !== undefined) {
|
|
493
|
+
if (managedSession) {
|
|
494
|
+
const resolved = path.resolve(options.file);
|
|
495
|
+
const projectRoot = path.resolve(process.cwd());
|
|
496
|
+
const tempRoot = process.env.TMPDIR?.trim() && path.isAbsolute(process.env.TMPDIR)
|
|
497
|
+
? path.resolve(process.env.TMPDIR)
|
|
498
|
+
: undefined;
|
|
499
|
+
const allowed = isSameOrDescendant(resolved, projectRoot)
|
|
500
|
+
|| (!!tempRoot && isSameOrDescendant(resolved, tempRoot));
|
|
501
|
+
if (!allowed || isHClassPath(resolved) || isLClassPath(resolved)) {
|
|
502
|
+
return { ok: false, code: 'INVALID_ARGS', error: '--file 必须位于当前项目或会话 $TMPDIR,且不能读取 EvolCore 受保护路径' };
|
|
503
|
+
}
|
|
504
|
+
try {
|
|
505
|
+
const stat = fs.lstatSync(resolved);
|
|
506
|
+
if (stat.isSymbolicLink() || !stat.isFile()) {
|
|
507
|
+
return { ok: false, code: 'INVALID_ARGS', error: '--file 必须指向当前项目或会话 $TMPDIR 内的普通文件' };
|
|
508
|
+
}
|
|
509
|
+
const realPath = fs.realpathSync(resolved);
|
|
510
|
+
const realProjectRoot = fs.realpathSync(projectRoot);
|
|
511
|
+
const realTempRoot = tempRoot ? fs.realpathSync(tempRoot) : undefined;
|
|
512
|
+
const realAllowed = isSameOrDescendant(realPath, realProjectRoot)
|
|
513
|
+
|| (!!realTempRoot && isSameOrDescendant(realPath, realTempRoot));
|
|
514
|
+
if (!realAllowed || isHClassPath(realPath) || isLClassPath(realPath)) {
|
|
515
|
+
return { ok: false, code: 'INVALID_ARGS', error: '--file 解析后越出允许目录或命中 EvolCore 受保护路径' };
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
catch (e) {
|
|
519
|
+
return { ok: false, code: 'READ_FAILED', error: `无法校验 --file: ${e?.message || e}` };
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
const source = readPersonaSource(options.file);
|
|
523
|
+
if (!source.ok)
|
|
524
|
+
return source;
|
|
525
|
+
text = source.content;
|
|
526
|
+
}
|
|
527
|
+
if (text !== undefined) {
|
|
528
|
+
const error = validatePersonaContent(text);
|
|
529
|
+
if (error)
|
|
530
|
+
return { ok: false, code: 'INVALID_ARGS', error };
|
|
531
|
+
}
|
|
532
|
+
const managedArgs = options.text !== undefined
|
|
533
|
+
? ['persona', '--text', text]
|
|
534
|
+
: options.file !== undefined
|
|
535
|
+
? ['persona', '--text', text]
|
|
536
|
+
: ['persona', 'show'];
|
|
537
|
+
if (managedSession) {
|
|
538
|
+
const managed = await runManagedAgentOperation(managedArgs);
|
|
539
|
+
if (!managed.ok)
|
|
540
|
+
return managed;
|
|
541
|
+
return { ok: true, aid, content: managed.content ?? null, ...(managed.path ? { path: managed.path } : {}), ...(managed.saved ? { saved: true } : {}) };
|
|
542
|
+
}
|
|
543
|
+
const personaPath = path.join(agentPersonalDir(aid), 'persona.md');
|
|
544
|
+
if (text === undefined) {
|
|
545
|
+
try {
|
|
546
|
+
return { ok: true, aid, content: fs.existsSync(personaPath) ? fs.readFileSync(personaPath, 'utf8') : null, path: personaPath };
|
|
547
|
+
}
|
|
548
|
+
catch (e) {
|
|
549
|
+
return { ok: false, code: 'READ_FAILED', error: e?.message || String(e) };
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
try {
|
|
553
|
+
fs.mkdirSync(path.dirname(personaPath), { recursive: true });
|
|
554
|
+
fs.writeFileSync(personaPath, text, 'utf8');
|
|
555
|
+
return { ok: true, aid, content: text, path: personaPath, saved: true };
|
|
556
|
+
}
|
|
557
|
+
catch (e) {
|
|
558
|
+
return { ok: false, code: 'WRITE_FAILED', error: e?.message || String(e) };
|
|
559
|
+
}
|
|
560
|
+
}
|
|
459
561
|
/**
|
|
460
562
|
* Add or overwrite a channel instance on a per-agent config.
|
|
461
563
|
*
|