evolcore 0.0.21 → 0.0.23
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/AGENTS.md +62 -0
- package/CHANGELOG.md +53 -0
- package/README.md +2 -0
- package/bin/codex-managed-acl.ps1 +155 -0
- package/bin/codex-managed-hook.mjs +3 -0
- package/bin/install-codex-managed-hooks.mjs +376 -96
- package/dist/agents/baseagent-availability.js +48 -0
- package/dist/agents/baseagent.js +1 -1
- package/dist/agents/claude-runner.js +44 -226
- package/dist/agents/{codex-app-server-client.js → codex/app-server-client.js} +103 -17
- package/dist/{utils/codex-app-server-registry.js → agents/codex/app-server-registry.js} +2 -2
- package/dist/agents/codex/catalog.js +70 -0
- package/dist/agents/codex/diagnostics.js +154 -0
- package/dist/agents/codex-runner.js +1292 -219
- package/dist/agents/ecagent-runner.js +10 -31
- package/dist/agents/gemini-runner.js +2 -6
- package/dist/aun/aid/store.js +2 -0
- package/dist/aun/menu-client.js +272 -0
- package/dist/aun/msg/group.js +65 -4
- package/dist/aun/msg/index.js +1 -1
- package/dist/aun/msg/managed-operation.js +51 -4
- package/dist/aun/outbox.js +7 -0
- package/dist/aun/rpc/client.js +8 -1
- package/dist/channels/aun.js +240 -36
- package/dist/channels/wechat.js +81 -10
- package/dist/cli/aun-commands.js +48 -4
- package/dist/cli/command-log.js +21 -2
- package/dist/cli/daemon-commands.js +169 -51
- package/dist/cli/index.js +20 -0
- package/dist/cli/init.js +2 -10
- package/dist/cli/menu-client.js +95 -0
- package/dist/cli/model.js +23 -8
- package/dist/cli/task-context.js +16 -2
- package/dist/cli/trigger-command.js +22 -5
- package/dist/config/config-field-policy.js +3 -0
- package/dist/config/config-manager.js +32 -5
- package/dist/config/contact-book-store.js +25 -3
- package/dist/config/schema-migration.js +14 -2
- package/dist/core/auth/agent-delegation.js +15 -0
- package/dist/core/auth/auth-gateway.js +8 -0
- package/dist/core/auth/authorization-audit.js +70 -6
- package/dist/core/auth/operation-catalog.js +4 -0
- package/dist/core/auth/remote-access-store.js +135 -0
- package/dist/core/bootstrap-messages.js +8 -0
- package/dist/core/bootstrap-service.js +93 -25
- package/dist/core/command/command-handler.js +62 -5
- package/dist/core/command/daemon-diagnostics.js +448 -0
- package/dist/core/command/menu-catalog.js +3 -0
- package/dist/core/command/menu-handler.js +150 -33
- package/dist/core/command/menu-protocol.js +120 -1
- package/dist/core/command/slash-gate.js +3 -3
- package/dist/core/command/slash-handler.js +83 -40
- package/dist/core/data-migration.js +11 -1
- package/dist/core/event-catalog.js +32 -0
- package/dist/core/handoff/runtime.js +23 -3
- package/dist/core/message/im-renderer.js +7 -3
- package/dist/core/message/message-bridge.js +60 -2
- package/dist/core/message/message-log.js +33 -0
- package/dist/core/message/message-queue.js +41 -15
- package/dist/core/message/response-engine.js +246 -114
- package/dist/core/model/catalog-service.js +308 -0
- package/dist/core/model/model-catalog.js +124 -334
- package/dist/core/model/model-diagnostics.js +4 -5
- package/dist/core/model/model-fallback.js +9 -16
- package/dist/core/model/model-permission.js +1 -1
- package/dist/core/permission/approval-gateway.js +16 -1
- package/dist/core/permission/ec-command-parser.js +272 -70
- package/dist/core/permission/protected-paths.js +74 -14
- package/dist/core/permission/sandbox-runtime.js +4 -2
- package/dist/core/permission/tool-error-code.js +12 -0
- package/dist/core/permission/tool-policy.js +290 -30
- package/dist/core/runtime-lock.js +13 -8
- package/dist/core/session/session-manager.js +30 -0
- package/dist/core/session/session-renew.js +18 -1
- package/dist/core/session/session-turn-coordinator.js +5 -1
- package/dist/index.js +104 -34
- package/dist/ipc.js +218 -96
- package/dist/paths.js +18 -0
- package/dist/response-system/engines/v1/proactive-flow.js +7 -2
- package/dist/stats/price-resolver.js +4 -0
- package/dist/trigger/feedback.js +14 -2
- package/dist/trigger/manager.js +3 -1
- package/dist/trigger/parser.js +86 -13
- package/dist/trigger/patch.js +104 -1
- package/dist/trigger/scheduler.js +20 -3
- package/dist/utils/ecweb-supervisor.js +11 -2
- package/dist/utils/ecweb-utils.js +8 -26
- package/dist/utils/error-utils.js +7 -0
- package/dist/utils/logger.js +9 -4
- package/dist/utils/npm-ops.js +47 -15
- package/dist/utils/tool-summary.js +59 -0
- package/dist/utils/windows-shell-trust.js +201 -0
- package/kits/docs/evolcore/INDEX.md +3 -2
- package/kits/docs/evolcore/agent-create.md +159 -0
- package/kits/docs/evolcore/agent.md +6 -0
- package/kits/docs/evolcore/group-collaboration.md +256 -0
- package/kits/docs/evolcore/group-rules.md +1 -19
- package/kits/docs/evolcore/group.md +3 -1
- package/kits/docs/evolcore/menu-client.md +34 -0
- package/kits/docs/evolcore/trigger.md +6 -3
- package/kits/docs/prompt-loading-architecture.md +6 -0
- package/kits/eck_message_manifest.json +6 -6
- package/kits/migrations/migrate-contact-book-v2.mjs +9 -1
- package/kits/migrations/migrate-role-config-v4.mjs +11 -5
- package/kits/migrations/migrate-role-config-v5.mjs +8 -2
- package/kits/schemas/_meta.json +3 -2
- package/kits/schemas/agent-config.schema.12.json +427 -0
- package/kits/templates/message-fragments/item.md +1 -1
- package/kits/templates/roles/visitor.json +1 -0
- package/kits/templates/system-fragments/bootstrap.md +10 -2
- package/kits/templates/system-fragments/commands.md +2 -2
- package/package.json +11 -3
|
@@ -5,6 +5,65 @@
|
|
|
5
5
|
* Edit 工具的摘要为 diff 风格预览(支持 old/new_string 与 unified diff 两种输入)。
|
|
6
6
|
*/
|
|
7
7
|
import fs from 'fs';
|
|
8
|
+
import { parseLiteralShellArgv, resolveCodexShellCarrierString, } from '../core/permission/ec-command-parser.js';
|
|
9
|
+
const DISPLAY_POSIX_SHELLS = new Set(['bash', 'sh']);
|
|
10
|
+
const DISPLAY_POWERSHELLS = new Set(['pwsh', 'pwsh.exe', 'powershell', 'powershell.exe']);
|
|
11
|
+
const DISPLAY_CMD_SHELLS = new Set(['cmd', 'cmd.exe']);
|
|
12
|
+
const DISPLAY_CMD_INERT_SWITCHES = new Set(['/d', '/s', '/q', '/a', '/u']);
|
|
13
|
+
function executableBasename(value) {
|
|
14
|
+
if (typeof value !== 'string')
|
|
15
|
+
return '';
|
|
16
|
+
return value.replaceAll('\\', '/').split('/').at(-1)?.toLowerCase() ?? '';
|
|
17
|
+
}
|
|
18
|
+
/** Display-only fallback for valid Codex carriers installed outside standard paths. */
|
|
19
|
+
function summarizeDisplayCarrierArgv(argv) {
|
|
20
|
+
if (argv.length === 3) {
|
|
21
|
+
const executable = executableBasename(argv[0]);
|
|
22
|
+
const switchName = argv[1]?.toLowerCase();
|
|
23
|
+
if (DISPLAY_POSIX_SHELLS.has(executable) && switchName === '-lc')
|
|
24
|
+
return argv[2];
|
|
25
|
+
if (DISPLAY_POWERSHELLS.has(executable) && switchName === '-command')
|
|
26
|
+
return argv[2];
|
|
27
|
+
}
|
|
28
|
+
if (argv.length >= 3 && DISPLAY_CMD_SHELLS.has(executableBasename(argv[0]))) {
|
|
29
|
+
const executeIndex = argv.slice(1, -1).findIndex(value => value.toLowerCase() === '/c');
|
|
30
|
+
if (executeIndex >= 0 && executeIndex + 1 === argv.length - 2) {
|
|
31
|
+
const switches = argv.slice(1, executeIndex + 1);
|
|
32
|
+
if (switches.every(value => DISPLAY_CMD_INERT_SWITCHES.has(value.toLowerCase()))) {
|
|
33
|
+
return argv.at(-1);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
/** Remove Codex app-server's fixed shell carrier from display-only arguments. */
|
|
40
|
+
function displayShellCommand(command) {
|
|
41
|
+
if (typeof command !== 'string' || !command)
|
|
42
|
+
return undefined;
|
|
43
|
+
const parsedArgv = parseLiteralShellArgv(command);
|
|
44
|
+
const display = parsedArgv ? summarizeDisplayCarrierArgv(parsedArgv) : undefined;
|
|
45
|
+
if (display !== undefined)
|
|
46
|
+
return display;
|
|
47
|
+
// The nested PowerShell body is not POSIX shell syntax and can contain
|
|
48
|
+
// quotes, variables, redirects, and statement composition. Use the strict
|
|
49
|
+
// carrier parser only for PowerShell commands that the argv projection
|
|
50
|
+
// cannot parse; ordinary `bash -c` commands must remain unchanged.
|
|
51
|
+
const carrier = resolveCodexShellCarrierString(command);
|
|
52
|
+
return carrier?.dialect === 'powershell' ? carrier.command : undefined;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Build the tool arguments projected into activity/thought payloads.
|
|
56
|
+
* Execution, permission checks, and audit logging keep using the original
|
|
57
|
+
* input; only the human-facing Shell command is de-wrapped here.
|
|
58
|
+
*/
|
|
59
|
+
export function toolInputForDisplay(toolName, input) {
|
|
60
|
+
if (!input || toolName !== 'Shell')
|
|
61
|
+
return input;
|
|
62
|
+
const command = displayShellCommand(input.command);
|
|
63
|
+
if (!command || command === input.command)
|
|
64
|
+
return input;
|
|
65
|
+
return { ...input, command };
|
|
66
|
+
}
|
|
8
67
|
/**
|
|
9
68
|
* 工具输入摘要(提取工具调用的可读描述,供权限审批和消息展示使用)
|
|
10
69
|
*/
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { spawnSync } from 'node:child_process';
|
|
4
|
+
const MAX_CACHE_ENTRIES = 128;
|
|
5
|
+
const signatureCache = new Map();
|
|
6
|
+
/**
|
|
7
|
+
* The signer name is checked only after Authenticode reports a trusted chain.
|
|
8
|
+
* Keep this list deliberately small: an unsigned or unknown Bash distribution
|
|
9
|
+
* must not enter the privileged EC command path.
|
|
10
|
+
*/
|
|
11
|
+
const MICROSOFT_PUBLISHER_RE = /(?:^|[,;]\s*)CN=Microsoft (?:Corporation|Windows(?: [^,;]+)?)(?:[,;]|$)/i;
|
|
12
|
+
const MICROSOFT_ORG_RE = /(?:^|[,;]\s*)O=Microsoft Corporation(?:[,;]|$)/i;
|
|
13
|
+
const BASH_PUBLISHER_RES = [
|
|
14
|
+
/(?:^|[,;]\s*)(?:CN|O)=Git for Windows(?:[,;]|$)/i,
|
|
15
|
+
/(?:^|[,;]\s*)(?:CN|O)=The Git Development Community(?:[,;]|$)/i,
|
|
16
|
+
// Git for Windows binaries are currently signed by project maintainer
|
|
17
|
+
// Johannes Schindelin rather than a certificate named after the project.
|
|
18
|
+
/(?:^|[,;]\s*)(?:CN|O)=Johannes Schindelin(?:[,;]|$)/i,
|
|
19
|
+
/(?:^|[,;]\s*)(?:CN|O)=Red Hat,? Inc\.(?:[,;]|$)/i,
|
|
20
|
+
/(?:^|[,;]\s*)(?:CN|O)=MSYS2(?:[,;]|$)/i,
|
|
21
|
+
];
|
|
22
|
+
function isValidStatus(status) {
|
|
23
|
+
return typeof status === 'string' && status.trim().toLowerCase() === 'valid';
|
|
24
|
+
}
|
|
25
|
+
/** Pure signature policy, separately testable without a Windows host. */
|
|
26
|
+
export function isTrustedShellSignature(kind, evidence) {
|
|
27
|
+
if (!isValidStatus(evidence.status) || typeof evidence.subject !== 'string')
|
|
28
|
+
return false;
|
|
29
|
+
const subject = evidence.subject.trim();
|
|
30
|
+
if (kind === 'cmd' || kind === 'powershell') {
|
|
31
|
+
return MICROSOFT_PUBLISHER_RE.test(subject) && MICROSOFT_ORG_RE.test(subject);
|
|
32
|
+
}
|
|
33
|
+
return (MICROSOFT_PUBLISHER_RE.test(subject) && MICROSOFT_ORG_RE.test(subject))
|
|
34
|
+
|| BASH_PUBLISHER_RES.some(pattern => pattern.test(subject));
|
|
35
|
+
}
|
|
36
|
+
function windowsSystemRoot() {
|
|
37
|
+
return process.env.SystemRoot || process.env.WINDIR || 'C:\\Windows';
|
|
38
|
+
}
|
|
39
|
+
function systemPowerShellPath() {
|
|
40
|
+
return path.win32.join(windowsSystemRoot(), 'System32', 'WindowsPowerShell', 'v1.0', 'powershell.exe');
|
|
41
|
+
}
|
|
42
|
+
function systemPowerShellModulePath() {
|
|
43
|
+
return path.win32.join(windowsSystemRoot(), 'System32', 'WindowsPowerShell', 'v1.0', 'Modules');
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Windows PowerShell 5.1 must load its own Security module. A caller's
|
|
47
|
+
* PSModulePath can put PowerShell 7's module ahead of it; that module is not
|
|
48
|
+
* compatible with 5.1 and makes Get-AuthenticodeSignature fail to load.
|
|
49
|
+
*/
|
|
50
|
+
function systemPowerShellEnvironment() {
|
|
51
|
+
const env = { ...process.env };
|
|
52
|
+
for (const key of Object.keys(env)) {
|
|
53
|
+
if (key.toLowerCase() === 'psmodulepath')
|
|
54
|
+
delete env[key];
|
|
55
|
+
}
|
|
56
|
+
env.PSModulePath = systemPowerShellModulePath();
|
|
57
|
+
return env;
|
|
58
|
+
}
|
|
59
|
+
function systemWherePath() {
|
|
60
|
+
return path.win32.join(windowsSystemRoot(), 'System32', 'where.exe');
|
|
61
|
+
}
|
|
62
|
+
function isAbsoluteWindowsPath(value) {
|
|
63
|
+
return path.win32.isAbsolute(value) || /^\\\\[^\\/]+[\\/][^\\/]+/.test(value);
|
|
64
|
+
}
|
|
65
|
+
function resolveBareShellExecutable(executable, kind) {
|
|
66
|
+
const name = executable.toLowerCase().replace(/\.exe$/i, '');
|
|
67
|
+
if (kind === 'cmd' && name === 'cmd') {
|
|
68
|
+
return path.win32.join(windowsSystemRoot(), 'System32', 'cmd.exe');
|
|
69
|
+
}
|
|
70
|
+
if (kind === 'powershell' && name === 'powershell') {
|
|
71
|
+
return systemPowerShellPath();
|
|
72
|
+
}
|
|
73
|
+
const result = spawnSync(systemWherePath(), [`${name}.exe`], {
|
|
74
|
+
encoding: 'utf8',
|
|
75
|
+
timeout: 3000,
|
|
76
|
+
windowsHide: true,
|
|
77
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
78
|
+
});
|
|
79
|
+
if (result.status !== 0)
|
|
80
|
+
return undefined;
|
|
81
|
+
const first = String(result.stdout || '')
|
|
82
|
+
.split(/\r?\n/)
|
|
83
|
+
.map(line => line.trim())
|
|
84
|
+
.find(Boolean);
|
|
85
|
+
return first || undefined;
|
|
86
|
+
}
|
|
87
|
+
function resolveShellPath(executable, kind) {
|
|
88
|
+
if (!executable)
|
|
89
|
+
return undefined;
|
|
90
|
+
// Codex can keep its POSIX carrier spelling on Windows (for example
|
|
91
|
+
// `/bin/bash`). It is a logical shell name, not a Windows root-relative
|
|
92
|
+
// filesystem path, so resolve it through the trusted Windows PATH lookup.
|
|
93
|
+
if (executable.startsWith('/') && !executable.startsWith('//')) {
|
|
94
|
+
const basename = path.posix.basename(executable);
|
|
95
|
+
return resolveBareShellExecutable(basename, kind);
|
|
96
|
+
}
|
|
97
|
+
if (isAbsoluteWindowsPath(executable))
|
|
98
|
+
return executable;
|
|
99
|
+
return resolveBareShellExecutable(executable, kind);
|
|
100
|
+
}
|
|
101
|
+
function isAppExecutionAliasPath(value) {
|
|
102
|
+
return /[\\/]AppData[\\/]Local[\\/]Microsoft[\\/]WindowsApps[\\/]/i.test(value);
|
|
103
|
+
}
|
|
104
|
+
function shellQuote(value) {
|
|
105
|
+
return `'${value.replaceAll("'", "''")}'`;
|
|
106
|
+
}
|
|
107
|
+
function probeAuthenticode(filePath) {
|
|
108
|
+
const script = [
|
|
109
|
+
'$ErrorActionPreference = "Stop"',
|
|
110
|
+
`$p = ${shellQuote(filePath)}`,
|
|
111
|
+
'$item = Get-Item -LiteralPath $p -Force',
|
|
112
|
+
'if ($item.PSIsContainer) { exit 17 }',
|
|
113
|
+
'$sig = Get-AuthenticodeSignature -LiteralPath $item.FullName',
|
|
114
|
+
'[pscustomobject]@{',
|
|
115
|
+
' status = [string]$sig.Status',
|
|
116
|
+
' subject = if ($sig.SignerCertificate) { [string]$sig.SignerCertificate.Subject } else { "" }',
|
|
117
|
+
' issuer = if ($sig.SignerCertificate) { [string]$sig.SignerCertificate.Issuer } else { "" }',
|
|
118
|
+
'} | ConvertTo-Json -Compress',
|
|
119
|
+
].join('\n');
|
|
120
|
+
const result = spawnSync(systemPowerShellPath(), [
|
|
121
|
+
'-NoLogo', '-NoProfile', '-NonInteractive', '-Command', script,
|
|
122
|
+
], {
|
|
123
|
+
encoding: 'utf8',
|
|
124
|
+
env: systemPowerShellEnvironment(),
|
|
125
|
+
timeout: 5000,
|
|
126
|
+
windowsHide: true,
|
|
127
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
128
|
+
});
|
|
129
|
+
if (result.status !== 0 || result.error || !String(result.stdout || '').trim())
|
|
130
|
+
return undefined;
|
|
131
|
+
try {
|
|
132
|
+
const parsed = JSON.parse(String(result.stdout));
|
|
133
|
+
return {
|
|
134
|
+
status: typeof parsed.status === 'string' ? parsed.status : undefined,
|
|
135
|
+
subject: typeof parsed.subject === 'string' ? parsed.subject : undefined,
|
|
136
|
+
issuer: typeof parsed.issuer === 'string' ? parsed.issuer : undefined,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
return undefined;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
function cacheKey(filePath) {
|
|
144
|
+
try {
|
|
145
|
+
return fs.realpathSync.native(filePath).toLowerCase();
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
return filePath.replaceAll('\\', '/').toLowerCase();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Verify the concrete executable selected by Codex. Non-Windows callers keep
|
|
153
|
+
* the existing parser behavior; only Windows enters the Authenticode path.
|
|
154
|
+
*/
|
|
155
|
+
export function isTrustedWindowsShellExecutable(executable, kind) {
|
|
156
|
+
if (process.platform !== 'win32')
|
|
157
|
+
return true;
|
|
158
|
+
const resolved = resolveShellPath(executable, kind);
|
|
159
|
+
if (!resolved)
|
|
160
|
+
return false;
|
|
161
|
+
let finalPath = resolved;
|
|
162
|
+
try {
|
|
163
|
+
finalPath = fs.realpathSync.native(resolved);
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
// Keep the original path for the signature probe; the stat/probe below
|
|
167
|
+
// will fail closed if the executable is not accessible.
|
|
168
|
+
}
|
|
169
|
+
// If realpath could not escape an App Execution Alias, do not authenticate
|
|
170
|
+
// the alias stub itself. A resolved WindowsApps package binary is allowed
|
|
171
|
+
// and is checked below like any other signed executable.
|
|
172
|
+
if (isAppExecutionAliasPath(finalPath))
|
|
173
|
+
return false;
|
|
174
|
+
let stat;
|
|
175
|
+
try {
|
|
176
|
+
stat = fs.statSync(finalPath);
|
|
177
|
+
if (!stat.isFile())
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
const key = cacheKey(finalPath);
|
|
184
|
+
const previous = signatureCache.get(key);
|
|
185
|
+
if (previous && previous.size === stat.size && previous.mtimeMs === stat.mtimeMs) {
|
|
186
|
+
return previous.trusted;
|
|
187
|
+
}
|
|
188
|
+
const trusted = isTrustedShellSignature(kind, probeAuthenticode(finalPath) ?? {});
|
|
189
|
+
signatureCache.set(key, { size: stat.size, mtimeMs: stat.mtimeMs, trusted });
|
|
190
|
+
while (signatureCache.size > MAX_CACHE_ENTRIES) {
|
|
191
|
+
const oldest = signatureCache.keys().next().value;
|
|
192
|
+
if (!oldest)
|
|
193
|
+
break;
|
|
194
|
+
signatureCache.delete(oldest);
|
|
195
|
+
}
|
|
196
|
+
return trusted;
|
|
197
|
+
}
|
|
198
|
+
/** Test hook: clear cached signature decisions after a fixture is replaced. */
|
|
199
|
+
export function clearWindowsShellTrustCache() {
|
|
200
|
+
signatureCache.clear();
|
|
201
|
+
}
|
|
@@ -29,14 +29,15 @@
|
|
|
29
29
|
| 命令集 | 用途 | 触发词 | 适用场景 | 文档 |
|
|
30
30
|
|--------|------|--------|----------|------|
|
|
31
31
|
| `ec msg` | 私聊收发消息 | 回复/发消息/拉取/撤回/查在线 | 有对端(peerId) | `msg.md` |
|
|
32
|
-
| `ec group` | 群聊收发与群管理 |
|
|
32
|
+
| `ec group` | 群聊收发与群管理 | 群发/建群/邀请/踢人/退群/群成员/角色/封禁/规则/协作 | 群聊(groupId) | `group.md`;完整协作流程见 `group-collaboration.md` |
|
|
33
33
|
| `ec group rules` | 群规则文件发布与上下文注入 | 群规则/工作流程/职责分工/rules.md/发布规则 | AUN 群聊(groupId) | `group-rules.md` |
|
|
34
34
|
| `ec aid` | AID 身份管理 | 身份/证书/名片/探测对端 | 任意有渠道场景 | `aid.md` |
|
|
35
35
|
| `ec fs` | AUN 文件系统统一入口 | 上传/下载/看文件/列目录/删文件/配额/群空间 | 任意有渠道场景 | `fs.md` |
|
|
36
36
|
| `ec storage` | 文件存储底层调试入口 | storage 调试/旧命令/底层上传下载 | 任意有渠道场景 | `storage.md` |
|
|
37
|
-
| `ec agent` | EvolAgent 生命周期 | 创建/启停/热重载/改配置 | 管理员(owner/admin) | `agent.md` |
|
|
37
|
+
| `ec agent` | EvolAgent 生命周期 | 创建/启停/热重载/改配置 | 管理员(owner/admin) | `agent.md`;完整创建与 Bootstrap 见 `agent-create.md` |
|
|
38
38
|
| `ec contact` | Contact Book 与访问控制 | 申请添加、拉黑/解除拉黑、查拉黑 | Agent 当前私聊可申请添加;管理写操作按角色限制 | `contact.md` |
|
|
39
39
|
| `ec rpc` | 底层 AUN RPC(逃生通道) | 直接调协议方法 | 高级/兜底 | `rpc.md` |
|
|
40
|
+
| `ec menu-client` | 远程 Daemon Menu 请求 | 远程诊断/daemon 日志/监控/原始配置 | 非托管 eclink/运维主机 | `menu-client.md` |
|
|
40
41
|
|
|
41
42
|
## 会话自管理类(不连 AUN,操作当前会话)
|
|
42
43
|
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# 创建 EvolAgent:从创建到 Bootstrap 完成
|
|
2
|
+
|
|
3
|
+
本手册用于创建一个能正常工作的 EvolAgent。创建者负责创建和观察状态;新 Agent 在自己的 Bootstrap 会话中完成首次设定。不要把创建流水线完成误认为 Agent 已激活。
|
|
4
|
+
|
|
5
|
+
### AID 与 Owner 约定
|
|
6
|
+
|
|
7
|
+
- AID 必须是 `{name}.{issuer}`,例如 `helper.agentid.cn`;不要使用四级域名(如 `helper.team.agentid.cn`),也不要把显示名当作 AID。
|
|
8
|
+
- `--owner` 填写需求提出者或实际责任 Owner 的完整 AID,而不是默认填写当前执行者。创建者只是代办创建流程时,仍应保留需求提出者的 Owner 权限。
|
|
9
|
+
|
|
10
|
+
## 生命周期与完成标准
|
|
11
|
+
|
|
12
|
+
```text
|
|
13
|
+
ec agent new
|
|
14
|
+
↓
|
|
15
|
+
created
|
|
16
|
+
↓ channel 可以联系 Owner,或 Owner 首次入站
|
|
17
|
+
bootstrapping
|
|
18
|
+
↓ 新 Agent 发布 agent.md,并执行 ec agent ready
|
|
19
|
+
active
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
只有 `lifecycle=active` 才表示 Agent 已完成创建流程并可正常处理普通任务。
|
|
23
|
+
|
|
24
|
+
## 1. 创建者创建 Agent
|
|
25
|
+
|
|
26
|
+
多个 Agent 必须串行创建和观察。不要并行启动多个 `ec agent new`:证书、热加载和 Bootstrap 会竞争连接与资源,容易造成超时、锁等待或把失败误判为未创建。
|
|
27
|
+
|
|
28
|
+
在独立终端可以使用交互模式:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
ec agent new helper.agentid.pub
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
在 EvolCore 托管 Agent 会话等自动化环境中,必须使用非交互模式:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
ec agent new helper.agentid.pub --non-interactive \
|
|
38
|
+
--project /home/user/helper-project \
|
|
39
|
+
--baseagent codex \
|
|
40
|
+
--owner owner.agentid.pub \
|
|
41
|
+
--name "Helper" \
|
|
42
|
+
--description "协助处理项目开发任务"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
建议先用 dry-run 检查最终参数:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
ec agent new helper.agentid.pub --non-interactive \
|
|
49
|
+
--project /home/user/helper-project \
|
|
50
|
+
--baseagent codex \
|
|
51
|
+
--owner owner.agentid.pub \
|
|
52
|
+
--name "Helper" \
|
|
53
|
+
--description "协助处理项目开发任务" \
|
|
54
|
+
--dry-run --format json
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
创建时会注册 AID、写入 Agent 配置、生成并尝试发布初始 `agent.md`,然后尝试热加载。配置写盘时 `lifecycle` 初始为 `created`;channel 很快触发 Bootstrap 时,查询结果也可能已经是 `bootstrapping`:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
ec agent get helper.agentid.pub lifecycle
|
|
61
|
+
ec agent show helper.agentid.pub
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
如果是 menu 创建,`accepted=true` 只表示请求已受理。继续轮询 `createProgress.status` 直到 `ready` 或 `failed`。这里的 `createProgress.status=ready` **只表示后台创建流水线结束,不等于 `lifecycle=active`**。
|
|
65
|
+
|
|
66
|
+
创建者应维护一个最小状态账本(可放在当前任务记录中),每个 Agent 至少记录:`aid`、需求 Owner、项目路径、创建请求是否受理、`createProgress.status`、`lifecycle`、本地 `agent.md` 是否存在/字段是否完整、名片是否已发布、最近错误、下一步和最后检查时间。重启或超时恢复时先按账本逐项核对实际状态,再决定续做,不按“上次命令是否返回”推断结果。
|
|
67
|
+
|
|
68
|
+
## 2. 触发 Bootstrap
|
|
69
|
+
|
|
70
|
+
当任一已启用 channel 可以联系 Owner 时,系统会向 Owner 发送固定的 Bootstrap 首条消息,并把生命周期从 `created` 切换为 `bootstrapping`。
|
|
71
|
+
|
|
72
|
+
部分 channel 不能在连接时主动定位 Owner。这种情况下 Agent 会保持 `created`;Owner 需要先在该 channel 向新 Agent 发送一条消息,系统获得回复上下文后再启动 Bootstrap。
|
|
73
|
+
|
|
74
|
+
`created` 状态下 Base Agent 不处理普通消息。`bootstrapping` 状态下只加载 Bootstrap 专属提示词,不加载正常的 ECK 规则、人格、记忆或命令能力卡。
|
|
75
|
+
|
|
76
|
+
## 3. Owner 与新 Agent 确认名片信息
|
|
77
|
+
|
|
78
|
+
以下步骤发生在**新 Agent 自己的 Bootstrap 会话**中,不由创建者代替执行。
|
|
79
|
+
|
|
80
|
+
新 Agent 先读取系统注入路径指向的本地 `agent.md`,把其中格式有效的字段作为现有候选值:
|
|
81
|
+
|
|
82
|
+
- `name`:简短清晰的显示名
|
|
83
|
+
- `description`:一句到两句话描述职责或定位
|
|
84
|
+
- `tags`:3 到 6 个非空标签
|
|
85
|
+
|
|
86
|
+
交互规则:
|
|
87
|
+
|
|
88
|
+
1. 已有有效值时,新 Agent 简短回显并询问保持还是修改,不要求 Owner 重新输入。
|
|
89
|
+
2. 空值、占位值或格式错误的字段按缺失处理;`tags` 不足 3 个或超过 6 个也不合格。
|
|
90
|
+
3. 只有 Owner 明确提供、修改、选择或确认的内容才可作为最终值。不得从普通任务、示例文字或顺带提及的内容中推断。
|
|
91
|
+
4. 信息缺失、冲突或含义不清时,只追问对应部分,保留此前已明确的内容。
|
|
92
|
+
5. 三项齐全后,新 Agent 必须回显整组最终值,并再次请求 Owner 明确确认。
|
|
93
|
+
|
|
94
|
+
例如,Owner 可以回复:
|
|
95
|
+
|
|
96
|
+
```text
|
|
97
|
+
名称用 Helper;简介是“协助维护和开发项目”;标签用 coding、maintenance、typescript。请按这些值设置。
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
新 Agent 应回显这三个最终值并等待确认。Owner 再明确回复“确认”后,才能修改和发布名片。
|
|
101
|
+
|
|
102
|
+
Bootstrap 完成前,新 Agent 不处理普通任务,也不执行与本流程无关的工具或命令。如果 Owner 要求跳过、先工作或同时交办普通任务,新 Agent 应说明必须先完成首次设定,并继续确认缺失字段。
|
|
103
|
+
|
|
104
|
+
## 4. 新 Agent 修改并发布自己的 agent.md
|
|
105
|
+
|
|
106
|
+
Owner 明确确认最终值后,新 Agent 才能编辑系统提示词中 `agentMdPath` 指向的本地文件,并且:
|
|
107
|
+
|
|
108
|
+
- 只修改 YAML frontmatter 中的 `name`、`description`、`tags`。
|
|
109
|
+
- 保留其他 frontmatter 字段、Markdown 正文和文件结构。
|
|
110
|
+
- 修改后检查 YAML 合法,且三个字段满足上述格式要求。
|
|
111
|
+
|
|
112
|
+
然后由新 Agent 使用自己的 AID 签名并发布:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
ec aid agentmd put helper.agentid.pub
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
只有命令明确成功后才能继续。若发布失败,不得执行 `ready`;应向 Owner 说明具体错误,修正后再继续,不要盲目重复。
|
|
119
|
+
|
|
120
|
+
## 5. 新 Agent 完成 Bootstrap
|
|
121
|
+
|
|
122
|
+
发布成功后,新 Agent 执行整个 Bootstrap 的最后一个操作:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
ec agent ready helper.agentid.pub
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
托管任务只能对自身 AID 执行 `ready`,不能替其他 Agent 完成 Bootstrap。只有处于 `bootstrapping` 时,`ready` 才会完成状态切换;仍为 `created` 时会失败,已经是 `active` 时重复调用则保持 `active`。
|
|
129
|
+
|
|
130
|
+
`ready` 成功后,系统会:
|
|
131
|
+
|
|
132
|
+
1. 将 `lifecycle` 切换为 `active`。
|
|
133
|
+
2. 结束当前 Bootstrap 上下文。
|
|
134
|
+
3. 创建全新的主会话。
|
|
135
|
+
4. 发送正式欢迎消息。
|
|
136
|
+
|
|
137
|
+
新 Agent 在 `ready` 成功后不要从旧 Bootstrap 上下文再输出一段完成说明,也不要继续处理先前夹带的普通任务;后续工作从新主会话开始。
|
|
138
|
+
|
|
139
|
+
## 6. 创建者验收
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
ec agent get helper.agentid.pub lifecycle
|
|
143
|
+
# 应输出 active
|
|
144
|
+
|
|
145
|
+
ec agent show helper.agentid.pub
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
验证其它 Agent 的生命周期、配置和创建进度统一使用 `ec agent get/show/list`;`ec aid` 只用于身份、证书和名片操作,不要用 `ec aid` 代替 Agent 状态验证。
|
|
149
|
+
|
|
150
|
+
验收标准:
|
|
151
|
+
|
|
152
|
+
- `lifecycle` 为 `active`。
|
|
153
|
+
- `agent.md` 已成功签名发布。
|
|
154
|
+
- 系统已创建新的主会话并发送正式欢迎消息。
|
|
155
|
+
- 新 Agent 能在新主会话中处理普通任务。
|
|
156
|
+
|
|
157
|
+
如果仍为 `created`,检查 channel 是否已能联系 Owner,必要时由 Owner 主动发送首条消息。如果仍为 `bootstrapping`,回到新 Agent 的 Bootstrap 会话完成字段确认、名片发布和 `ready`,不要由创建者直接绕过引导。
|
|
158
|
+
|
|
159
|
+
失败重试前必须先执行状态检查:若本地 `agent.md` 已存在且远端名片已发布,只向该 Agent 发送 `ready`/续做指令,让它在自己的 Bootstrap 会话中完成收尾;不要重复创建、重复改名片或重复发布。仅在确认创建记录不存在且名片未发布时,才重新发起创建。
|
|
@@ -53,6 +53,12 @@ ec agent delete <aid> [--purge]
|
|
|
53
53
|
- `--dry-run` 只输出最终创建计划,不注册 AID、不写配置、不上传 `agent.md`。
|
|
54
54
|
- `--force` 覆盖已有 `config.json`;AID 密钥保留。
|
|
55
55
|
|
|
56
|
+
## 创建 Agent
|
|
57
|
+
|
|
58
|
+
`ec agent new` 成功不代表新 Agent 已能处理普通任务。新 Agent 还必须完成 Bootstrap,并由自身执行 `ec agent ready <aid>` 进入 `active`。
|
|
59
|
+
|
|
60
|
+
完整的创建、Bootstrap、名片发布和验收示例见:`$KITS_DOCS/evolcore/agent-create.md`。
|
|
61
|
+
|
|
56
62
|
## 头像更新
|
|
57
63
|
|
|
58
64
|
头像上传通过 menu 协议暴露,不是 `ec agent` CLI 子命令:
|