evolcore 0.0.31 → 0.0.32
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 +11 -0
- package/dist/agents/codex-runner.js +28 -5
- package/dist/agents/ecagent-runner.js +4 -0
- package/dist/agents/gemini-runner.js +4 -0
- package/dist/aun/aid/store.js +0 -81
- package/dist/aun/group/fs-download.js +1 -10
- package/dist/aun/msg/managed-operation.js +130 -32
- package/dist/aun/service-proxy.js +12 -18
- package/dist/aun/storage/index.js +29 -0
- package/dist/channels/aun.js +10 -135
- package/dist/cli/agent-command.js +6 -7
- package/dist/cli/agent-create.js +43 -24
- package/dist/cli/agent.js +15 -69
- package/dist/cli/aun-commands.js +149 -5
- package/dist/cli/ctl-command.js +1 -2
- package/dist/cli/daemon-commands.js +1 -1
- package/dist/cli/diag.js +2 -2
- package/dist/cli/handoff-command.js +15 -5
- package/dist/cli/memory-command.js +85 -11
- package/dist/cli/model.js +14 -138
- package/dist/cli/queue-command.js +46 -0
- package/dist/cli/response.js +5 -54
- package/dist/cli/skill-command.js +9 -3
- package/dist/cli/stats.js +10 -4
- package/dist/cli/task-command.js +1 -0
- package/dist/cli/task-context.js +15 -0
- package/dist/cli/trigger-command.js +73 -49
- package/dist/config/builtin-roles.js +8 -7
- package/dist/core/agent-ipc-registration.js +65 -22
- package/dist/core/auth/agent-delegation.js +17 -1
- package/dist/core/auth/delegation-authorization.js +1 -0
- package/dist/core/auth/operation-catalog.js +11 -3
- package/dist/core/command/command-handler.js +164 -21
- package/dist/core/command/diag-service.js +5 -1
- package/dist/core/handoff/ipc-registration.js +38 -0
- package/dist/core/ipc-registration.js +71 -7
- package/dist/core/message/aun-ipc-sender.js +48 -4
- package/dist/core/message/message-queue.js +131 -3
- package/dist/core/message/response-engine.js +30 -2
- package/dist/core/permission/sandbox-runtime.js +14 -1
- package/dist/core/task/task-recovery-service.js +2 -0
- package/dist/core/task/task-resume-operation.js +11 -0
- package/dist/index.js +2 -2
- package/dist/ipc.js +146 -8
- package/dist/trigger/authorization.js +2 -1
- package/dist/trigger/ipc-service.js +49 -35
- package/dist/trigger/script-sandbox.js +58 -77
- package/kits/docs/AUTHORING.md +1 -1
- package/kits/docs/channels/aun.md +8 -0
- package/kits/docs/evolcore/INDEX.md +2 -2
- package/kits/docs/evolcore/task.md +2 -0
- package/kits/docs/evolcore/trigger.md +2 -2
- package/kits/rules/01-overview.md +0 -9
- package/kits/rules/06-channel.md +7 -1
- package/kits/templates/system-fragments/commands.md +1 -1
- package/package.json +1 -1
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
1
|
import { getEventCatalog } from '../core/event-catalog.js';
|
|
4
2
|
import { authorizeOperation, canApprovePersistentFullAccessTrigger, isCrossAgentTriggerOperationAllowed, } from '../core/auth/auth-gateway.js';
|
|
5
3
|
import { auditFullAccessEvent } from '../core/auth/authorization-audit.js';
|
|
6
4
|
import { assertTriggerLocalFileAuthority, daemonPrivilegedTriggerReason, } from './authorization.js';
|
|
7
|
-
import { decodeTriggerScriptFile
|
|
5
|
+
import { decodeTriggerScriptFile } from './local-files.js';
|
|
8
6
|
import { applyTriggerPatch } from './patch.js';
|
|
9
7
|
import { definitionRevision, normalizeTriggerDefinition, splitScriptCommand } from './validation.js';
|
|
10
8
|
export function createTriggerBaseagentResolver({ daemonTriggerOwnerAid, getAgentName, getDaemonAgentName, agentMap, }) {
|
|
@@ -51,6 +49,9 @@ export function materializeTriggerCreateBaseagent(input, agentAid, dependencies)
|
|
|
51
49
|
}
|
|
52
50
|
export function createTriggerIpcExecutor(dependencies) {
|
|
53
51
|
return async (cmd) => {
|
|
52
|
+
let approvedActor;
|
|
53
|
+
let approvedAgentAid;
|
|
54
|
+
let approvedOperation;
|
|
54
55
|
const schedulerFor = (agentAid) => {
|
|
55
56
|
const scheduler = dependencies.getScheduler(agentAid);
|
|
56
57
|
if (!scheduler)
|
|
@@ -102,7 +103,10 @@ export function createTriggerIpcExecutor(dependencies) {
|
|
|
102
103
|
return { ...definition, authorizedBy };
|
|
103
104
|
};
|
|
104
105
|
const authorizeTrigger = async (agentAid, operation, triggerId, contextOnly = false) => {
|
|
105
|
-
|
|
106
|
+
if (approvedActor && (agentAid !== approvedAgentAid || operation !== approvedOperation)) {
|
|
107
|
+
throw new Error('Trigger operation does not match its approved argv');
|
|
108
|
+
}
|
|
109
|
+
const actor = approvedActor ?? await dependencies.authenticateActor(agentAid, cmd.actorSessionId, cmd.delegationToken, cmd.delegationCommandHash, cmd.controlToken, contextOnly);
|
|
106
110
|
if (actor.permissionMode === 'readonly' && !actor.fullAccess
|
|
107
111
|
&& !['trigger.list', 'trigger.show', 'trigger.history', 'trigger.eventCatalog'].includes(operation)) {
|
|
108
112
|
throw new Error('readonly tasks cannot modify or run Triggers');
|
|
@@ -160,38 +164,48 @@ export function createTriggerIpcExecutor(dependencies) {
|
|
|
160
164
|
}
|
|
161
165
|
return actor;
|
|
162
166
|
};
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
167
|
+
if (cmd.type === 'trigger.op') {
|
|
168
|
+
if (!Array.isArray(cmd.argv) || cmd.argv.some((value) => typeof value !== 'string')
|
|
169
|
+
|| typeof cmd.actorSessionId !== 'string' || !cmd.actorSessionId) {
|
|
170
|
+
throw new Error('Managed Trigger requires argv and actorSessionId');
|
|
171
|
+
}
|
|
172
|
+
const session = await dependencies.getSessionById(cmd.actorSessionId);
|
|
173
|
+
if (!session?.selfAID)
|
|
174
|
+
throw new Error('Trigger actor session is unavailable');
|
|
175
|
+
const { resolveTriggerCommandArgv, buildTriggerCreateRequest, buildTriggerUpdateRequest } = await import('../cli/trigger-command.js');
|
|
176
|
+
const argv = cmd.argv;
|
|
177
|
+
const command = resolveTriggerCommandArgv(argv, session.selfAID);
|
|
178
|
+
cmd = { ...command, actorSessionId: cmd.actorSessionId, delegationToken: cmd.delegationToken,
|
|
179
|
+
delegationCommandHash: cmd.delegationCommandHash };
|
|
180
|
+
approvedAgentAid = requireAgent(command.agentAid);
|
|
181
|
+
approvedOperation = command.type;
|
|
182
|
+
approvedActor = await authorizeTrigger(approvedAgentAid, approvedOperation, command.triggerId);
|
|
183
|
+
const args = argv.slice(2);
|
|
184
|
+
const usesFiles = args.some(value => ['--file', '--prompt-file', '--script-path', '--script-file']
|
|
185
|
+
.some(flag => value === flag || value.startsWith(`${flag}=`)));
|
|
186
|
+
if (usesFiles)
|
|
187
|
+
assertTriggerLocalFileAuthority(approvedActor);
|
|
188
|
+
const fileScope = approvedActor.fullAccess ? undefined : {
|
|
189
|
+
selfAid: approvedAgentAid, projectPath: session.projectPath,
|
|
190
|
+
sessionRuntimeDir: approvedActor.sessionRuntimeDir, cwd: session.projectPath,
|
|
191
|
+
};
|
|
192
|
+
if (command.type === 'trigger.create') {
|
|
193
|
+
const parsed = await buildTriggerCreateRequest(args, fileScope, approvedAgentAid);
|
|
194
|
+
if (parsed.definition?.agentAid !== approvedAgentAid)
|
|
195
|
+
throw new Error('Imported Trigger does not match the authorized Agent');
|
|
196
|
+
cmd = { ...cmd, ...parsed };
|
|
197
|
+
}
|
|
198
|
+
else if (command.type === 'trigger.update') {
|
|
199
|
+
cmd = { ...cmd, ...await buildTriggerUpdateRequest(args, fileScope, approvedAgentAid) };
|
|
200
|
+
}
|
|
201
|
+
else if (usesFiles) {
|
|
202
|
+
throw new Error('File inputs are only valid for Trigger create/update');
|
|
194
203
|
}
|
|
204
|
+
}
|
|
205
|
+
else if (cmd.actorSessionId) {
|
|
206
|
+
throw new Error('Managed callers must use trigger.op with approved argv');
|
|
207
|
+
}
|
|
208
|
+
switch (cmd.type) {
|
|
195
209
|
case 'trigger.list': {
|
|
196
210
|
const agentAid = requireAgent(cmd.agentAid);
|
|
197
211
|
const actor = await authorizeTrigger(agentAid, 'trigger.list');
|
|
@@ -6,28 +6,16 @@ import { pathToFileURL } from 'node:url';
|
|
|
6
6
|
import { spawn } from 'node:child_process';
|
|
7
7
|
import { resolveCodexCliPath } from '../agents/baseagent.js';
|
|
8
8
|
import { ensureSessionRuntimeDir } from '../cli/task-context.js';
|
|
9
|
-
import { resolveBubblewrapPath } from '../core/permission/sandbox-runtime.js';
|
|
10
|
-
import {
|
|
9
|
+
import { buildBubblewrapCommand, buildHClassGuardCommand, resolveBubblewrapPath, } from '../core/permission/sandbox-runtime.js';
|
|
10
|
+
import { resolvePhaseOneExecutionSandbox } from '../core/permission/mode.js';
|
|
11
|
+
import { sanitizeShellExecutionEnvironment } from '../core/permission/shell-environment.js';
|
|
12
|
+
import { buildCodexProtectedFilesystemRules, classifyProtectedPath, getExistingRelationAttachmentDirs, isSameOrDescendant, } from '../core/permission/protected-paths.js';
|
|
11
13
|
import { resolveRoot } from '../paths.js';
|
|
12
14
|
import { buildCliLaunchCommand, killProcess, resolveCommandPath } from '../utils/cross-platform.js';
|
|
13
15
|
import { TRIGGER_LOCAL_FILE_LIMIT } from './local-files.js';
|
|
14
|
-
const SAFE_ENVIRONMENT_KEYS = [
|
|
15
|
-
'ComSpec', 'COMSPEC', 'LANG', 'LC_ALL', 'OS', 'PATH', 'PATHEXT',
|
|
16
|
-
'ProgramData', 'ProgramFiles', 'ProgramFiles(x86)', 'ProgramW6432',
|
|
17
|
-
'SystemDrive', 'SystemRoot', 'WINDIR',
|
|
18
|
-
];
|
|
19
|
-
const SYSTEM_READ_ROOTS = ['/usr/bin', '/usr/lib', '/usr/lib64', '/usr/local/bin', '/usr/local/lib', '/usr/share/locale', '/usr/share/zoneinfo', '/bin', '/sbin', '/lib', '/lib64'];
|
|
20
|
-
const SYSTEM_READ_FILES = ['/etc/ld.so.cache', '/etc/localtime', '/etc/passwd', '/etc/group'];
|
|
21
|
-
const CONTROL_DIRECTORY_NAMES = ['agents', 'AIDs', 'aids', 'data', 'CA', '.snapshots', 'logs', 'backups'];
|
|
22
16
|
const WINDOWS_SANDBOX_SETUP_VERSION = 5;
|
|
23
|
-
const
|
|
17
|
+
const SCRIPT_ENVIRONMENT_EXCLUDES = [
|
|
24
18
|
'CODEX_HOME',
|
|
25
|
-
'EVOLCORE_DELEGATION_TOKEN',
|
|
26
|
-
'EVOLCORE_CODEX_SESSION_TOKEN',
|
|
27
|
-
'EVOLCORE_TASK_RUNTIME_CONTEXT',
|
|
28
|
-
'EVOLCORE_INSTANCE_SOCKET',
|
|
29
|
-
'EVOLCORE_DAEMON_SOCKET',
|
|
30
|
-
'EVOLCORE_IPC_SOCKET',
|
|
31
19
|
'OPENAI_API_KEY',
|
|
32
20
|
'CODEX_API_KEY',
|
|
33
21
|
'ANTHROPIC_API_KEY',
|
|
@@ -48,6 +36,8 @@ export function buildTriggerScriptLaunch(input) {
|
|
|
48
36
|
if (!authorization.permissionMode || authorization.permissionMode === 'fullaccess') {
|
|
49
37
|
throw new Error('scoped Trigger execution requires an effective non-fullaccess permission mode');
|
|
50
38
|
}
|
|
39
|
+
const sandboxDecision = resolvePhaseOneExecutionSandbox(authorization.permissionMode, authorization.role);
|
|
40
|
+
const readonly = sandboxDecision.permissionMode === 'readonly';
|
|
51
41
|
if (process.platform !== 'linux' && process.platform !== 'win32') {
|
|
52
42
|
throw new Error('scoped Trigger script isolation is unavailable on this host');
|
|
53
43
|
}
|
|
@@ -108,9 +98,12 @@ export function buildTriggerScriptLaunch(input) {
|
|
|
108
98
|
fs.writeFileSync(scriptPath, scriptBytes, { flag: 'wx', mode: 0o400 });
|
|
109
99
|
preserveNodeModuleType(runtime, input.scriptPath, snapshotDir);
|
|
110
100
|
const env = buildSandboxEnvironment(workDir);
|
|
111
|
-
const blockedPaths = protectedScriptPaths(root, input.trigger.agentAid);
|
|
112
101
|
const scriptArgs = [scriptPath, ...input.scriptArgs];
|
|
113
102
|
if (windowsBackend) {
|
|
103
|
+
const filesystem = buildCodexProtectedFilesystemRules(root, {
|
|
104
|
+
selfAid: input.trigger.agentAid,
|
|
105
|
+
denyLClassRead: readonly,
|
|
106
|
+
});
|
|
114
107
|
const systemRoot = process.env.SystemRoot || process.env.WINDIR || 'C:\\Windows';
|
|
115
108
|
const readRoots = [
|
|
116
109
|
path.join(systemRoot, 'System32'),
|
|
@@ -122,25 +115,37 @@ export function buildTriggerScriptLaunch(input) {
|
|
|
122
115
|
snapshotDir,
|
|
123
116
|
].filter(value => fs.existsSync(value));
|
|
124
117
|
const entries = [
|
|
125
|
-
{ path: { type: 'special', value: { kind: 'root' } },
|
|
118
|
+
{ path: { type: 'special', value: { kind: 'root' } },
|
|
119
|
+
access: sandboxDecision.state === 'off' ? 'write' : 'read' },
|
|
126
120
|
...readRoots.map(value => filesystemEntry(value, 'read')),
|
|
127
|
-
filesystemEntry(projectPath,
|
|
121
|
+
filesystemEntry(projectPath, readonly ? 'read' : 'write'),
|
|
122
|
+
filesystemEntry(snapshotDir, 'read'),
|
|
128
123
|
filesystemEntry(workDir, 'write'),
|
|
129
|
-
|
|
124
|
+
filesystemEntry(windowsBackend.home, 'deny'),
|
|
125
|
+
...Object.entries(filesystem).flatMap(([value, access]) => typeof access === 'number' ? [] : [{
|
|
126
|
+
path: /[*?[\]]/.test(value)
|
|
127
|
+
? { type: 'glob_pattern', pattern: value }
|
|
128
|
+
: { type: 'path', path: value },
|
|
129
|
+
access,
|
|
130
|
+
}]),
|
|
131
|
+
...getExistingRelationAttachmentDirs(root, {
|
|
132
|
+
selfAid: input.trigger.agentAid,
|
|
133
|
+
onlyOtherAgents: true,
|
|
134
|
+
}).map(value => filesystemEntry(value, 'deny')),
|
|
130
135
|
];
|
|
131
136
|
const sandboxState = JSON.stringify({
|
|
132
137
|
permissionProfile: {
|
|
133
138
|
type: 'managed',
|
|
134
|
-
file_system: { type: 'restricted', entries },
|
|
135
|
-
network: '
|
|
139
|
+
file_system: { type: 'restricted', entries, glob_scan_max_depth: filesystem.glob_scan_max_depth },
|
|
140
|
+
network: 'enabled',
|
|
136
141
|
},
|
|
137
142
|
sandboxCwd: pathToFileURL(projectPath).href,
|
|
138
143
|
});
|
|
139
144
|
if (sandboxState.length > 20_000)
|
|
140
145
|
throw new Error('scoped Windows Trigger filesystem policy exceeds the command-line budget');
|
|
141
|
-
const shellEnvironmentPolicy = `shell_environment_policy={inherit="all",exclude=${JSON.stringify(
|
|
146
|
+
const shellEnvironmentPolicy = `shell_environment_policy={inherit="all",exclude=${JSON.stringify(getScriptEnvironmentExcludes())},include_only=[],set={}}`;
|
|
142
147
|
const sandboxArgs = [
|
|
143
|
-
'sandbox', '--sandbox-state-json', sandboxState,
|
|
148
|
+
'sandbox', '--sandbox-state-json', sandboxState,
|
|
144
149
|
'-c', 'windows.sandbox="elevated"',
|
|
145
150
|
'-c', shellEnvironmentPolicy,
|
|
146
151
|
];
|
|
@@ -154,40 +159,26 @@ export function buildTriggerScriptLaunch(input) {
|
|
|
154
159
|
launch.prepare = signal => verifyWindowsReadIsolation(launch, sandboxArgs, runDir, workDir, signal);
|
|
155
160
|
return launch;
|
|
156
161
|
}
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
args.push('--ro-bind', value, value);
|
|
178
|
-
args.push(authorization.permissionMode === 'readonly' ? '--ro-bind' : '--bind', projectPath, projectPath);
|
|
179
|
-
for (const value of blockedPaths) {
|
|
180
|
-
if (!visibleRoots.some(directory => isSameOrDescendant(value, directory)) || !fs.existsSync(value))
|
|
181
|
-
continue;
|
|
182
|
-
const stat = fs.lstatSync(value);
|
|
183
|
-
if (stat.isDirectory())
|
|
184
|
-
args.push('--tmpfs', value, '--remount-ro', value);
|
|
185
|
-
else
|
|
186
|
-
args.push('--ro-bind', '/dev/null', value);
|
|
187
|
-
}
|
|
188
|
-
args.push('--ro-bind', runDir, runDir, '--bind', workDir, workDir, '--remount-ro', '/');
|
|
189
|
-
args.push('--chdir', projectPath, '--', runtime, ...scriptArgs);
|
|
190
|
-
return { command: bubblewrap, args, cwd: projectPath, env, cleanup };
|
|
162
|
+
const launch = sandboxDecision.state === 'off'
|
|
163
|
+
? buildHClassGuardCommand(runtime, scriptArgs, root, { selfAid: input.trigger.agentAid })
|
|
164
|
+
: buildBubblewrapCommand(runtime, scriptArgs, {
|
|
165
|
+
projectPath,
|
|
166
|
+
projectWritable: !readonly,
|
|
167
|
+
root,
|
|
168
|
+
selfAid: input.trigger.agentAid,
|
|
169
|
+
exposeDaemonIpc: false,
|
|
170
|
+
denyLClassRead: readonly,
|
|
171
|
+
});
|
|
172
|
+
if (!launch)
|
|
173
|
+
throw new Error('bubblewrap is required for scoped Trigger script isolation');
|
|
174
|
+
const separator = launch.args.indexOf('--');
|
|
175
|
+
if (separator < 0)
|
|
176
|
+
throw new Error('bubblewrap launch is missing its command separator');
|
|
177
|
+
const runMountArgs = ['--ro-bind', runDir, runDir, '--bind', workDir, workDir];
|
|
178
|
+
if (!launch.args.slice(0, separator).includes('--chdir'))
|
|
179
|
+
runMountArgs.push('--chdir', projectPath);
|
|
180
|
+
launch.args.splice(separator, 0, ...runMountArgs);
|
|
181
|
+
return { ...launch, cwd: projectPath, env, cleanup };
|
|
191
182
|
}
|
|
192
183
|
catch (error) {
|
|
193
184
|
cleanup();
|
|
@@ -331,30 +322,20 @@ function preserveNodeModuleType(runtime, scriptPath, snapshotDir) {
|
|
|
331
322
|
}
|
|
332
323
|
function buildSandboxEnvironment(workDir) {
|
|
333
324
|
const env = {};
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
if (
|
|
325
|
+
const excluded = new Set(getScriptEnvironmentExcludes().map(key => key.toUpperCase()));
|
|
326
|
+
for (const [key, value] of Object.entries(sanitizeShellExecutionEnvironment(process.env))) {
|
|
327
|
+
if (!excluded.has(key.toUpperCase())
|
|
328
|
+
&& typeof value === 'string')
|
|
337
329
|
env[key] = value;
|
|
338
330
|
}
|
|
339
|
-
const homeDir = process.platform === 'win32' ? path.join(workDir, 'home') : workDir;
|
|
340
|
-
if (homeDir !== workDir)
|
|
341
|
-
fs.mkdirSync(homeDir, { mode: 0o700 });
|
|
342
331
|
return {
|
|
343
|
-
...env,
|
|
344
|
-
APPDATA: path.join(workDir, 'appdata'), LOCALAPPDATA: path.join(workDir, 'localappdata'),
|
|
332
|
+
...env,
|
|
345
333
|
TMPDIR: workDir, TEMP: workDir, TMP: workDir, EVOLCORE_TRIGGER_SANDBOX: '1',
|
|
346
334
|
};
|
|
347
335
|
}
|
|
348
|
-
function
|
|
349
|
-
const
|
|
350
|
-
|
|
351
|
-
...directoryRoots,
|
|
352
|
-
...getExistingHClassMaskTargets(root, { selfAid }).map(target => target.path),
|
|
353
|
-
...getExistingLClassReadOnlyTargets(root, { selfAid }).map(target => target.path),
|
|
354
|
-
path.join(root, 'daemon.json'), path.join(root, '.env'), path.join(root, '.device_id'),
|
|
355
|
-
path.join(root, '.lock'), path.join(root, 'daemon.pid'),
|
|
356
|
-
];
|
|
357
|
-
return [...new Set(targets)].filter(candidate => (directoryRoots.includes(candidate) || !directoryRoots.some(directory => isSameOrDescendant(candidate, directory))));
|
|
336
|
+
function getScriptEnvironmentExcludes() {
|
|
337
|
+
const dynamic = Object.keys(process.env).filter(key => key.toUpperCase().startsWith('EVOLCORE_'));
|
|
338
|
+
return [...new Set([...SCRIPT_ENVIRONMENT_EXCLUDES, ...dynamic])];
|
|
358
339
|
}
|
|
359
340
|
function filesystemEntry(value, access) {
|
|
360
341
|
return { path: { type: 'path', path: path.resolve(value) }, access };
|
package/kits/docs/AUTHORING.md
CHANGED
|
@@ -111,7 +111,7 @@ ECK 的 manifest 机制决定了**不同位置的内容有不同的成本量级*
|
|
|
111
111
|
|
|
112
112
|
写入 `rules/` 前自问:**这条信息如果不注入,agent 会在多少比例的对话里做错事?**
|
|
113
113
|
|
|
114
|
-
- 每轮都需要(如"
|
|
114
|
+
- 每轮都需要(如"不得停止或重启承载当前会话的 EvolCore 实例")→ 进 `rules/`
|
|
115
115
|
- 偶发场景才需要(如"Menu 消息有哪些字段")→ 留 `docs/`,靠 `INDEX.md` 触发词按需命中
|
|
116
116
|
|
|
117
117
|
答不上来就别进 `rules/`。最常见的隐性浪费是把偶发查阅的内容塞进规则文件,之后每轮对话都在白烧 token。
|
|
@@ -42,6 +42,14 @@ AUN keystore seed 由 EvolCore 使用固定应用值管理,不再提供配置
|
|
|
42
42
|
|
|
43
43
|
> Gateway 不在配置里手填:连接时从 AID 自动发现(见下)。Keystore 默认落在 `$EVOLCORE_HOME`。
|
|
44
44
|
|
|
45
|
+
## SDK 同步边界
|
|
46
|
+
|
|
47
|
+
`@agentunion/fastaun` 管理消息/群消息的 A/T/H 水位、ACK、Push/Tail/Forward、Gap Fill、多页同步、重连恢复和 Pull Gate。EvolCore 只消费公开消息/撤回/同步事件,负责业务路由、持久化和 `(namespace, message_id)` 应用幂等;`seq` 只用于顺序、诊断和日志。菜单、普通文本、volatile 消息和应用去重记录均不能用来推导或回写 SDK 游标。
|
|
48
|
+
|
|
49
|
+
不得访问或 monkey patch SDK 私有成员,包括 `_seqTracker`、`_pullV2`、`_pullGroupV2`、`_publishAppEvent`、`_dispatcher`、`_identity`、`_auth`、`_tokenStore`、`_v2E2EE`。需要补同步、确认消息或调试时,应先检查 SDK 公开 API;缺少能力应向 SDK 增补公开契约,而不是在渠道适配层改写同步状态。显式查询使用公开 RPC/facade 与独立 slot,不得推进 daemon 消费游标。
|
|
50
|
+
|
|
51
|
+
`fastaun 0.5.18` 公开 `sender_device_id`,但隐藏发送方 slot。EvolCore 的菜单 token 当前仅按设备绑定,不声称具备同设备多 slot 隔离。
|
|
52
|
+
|
|
45
53
|
## 特有机制
|
|
46
54
|
|
|
47
55
|
- **隐式创建**:aun 渠道由顶层 `aid` 派生,无独立配置实例;这是它与飞书等渠道最大的不同。
|
|
@@ -14,14 +14,14 @@
|
|
|
14
14
|
2. **不确定有没有命令**时,直接 `ec <猜测的子命令> --help` 试一下(如 `ec stats --help`)
|
|
15
15
|
3. **已知场景需求**(如"要给对端发消息")→ 看下方分类表 → 定位到对应命令集
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
生命周期保护仅针对承载当前会话的 EvolCore 实例;其他实例按用户授权和目标端权限处理,不限管理通道。完整规则见 `$KITS_RULES/06-channel.md`。
|
|
18
18
|
|
|
19
19
|
## 服务运维类(本地,无需 AUN)
|
|
20
20
|
|
|
21
21
|
| 命令 | 用途 | 触发词 |
|
|
22
22
|
|------|------|--------|
|
|
23
23
|
| `ec --version` / `-v` / `-V` | 查看版本号 | 版本 |
|
|
24
|
-
| `ec restart` |
|
|
24
|
+
| `ec restart` | 重启目标 daemon(承载当前托管会话的实例受生命周期保护) | 重启 |
|
|
25
25
|
| `ec status` | 查看运行状态、进程、会话、渠道连接 | 状态/查看状态 |
|
|
26
26
|
| `ec logs` | 查看日志(`--level` `--module` `--raw` `--no-color`) | 日志/查看日志 |
|
|
27
27
|
| `ec diagnose` | 诊断启动环境 | 诊断/环境诊断 |
|
|
@@ -9,6 +9,8 @@ ec task resume <sessionId> --format json
|
|
|
9
9
|
|
|
10
10
|
暂停任务会释放原有的工具门控。异常中断任务会把内部恢复提示排入同一会话,并继续原 baseagent 会话。命令只确认恢复请求已被可靠接纳,不会等待模型运行结束。
|
|
11
11
|
|
|
12
|
+
恢复任务继承原任务的审批交互策略,而非因为自动恢复使用 Trigger 就禁止审批。普通会话(包括 Agent 间和群聊的 proactive 模式)允许申请审批;无人值守 Trigger 禁止申请审批。Handoff 回流同样继承发起任务的策略。继承策略不等于复用旧审批,新的待审批操作仍须发起新请求;缺少历史策略时,自动恢复和 Handoff 回流默认禁止审批,手动恢复默认允许申请。
|
|
13
|
+
|
|
12
14
|
以下情况会安全结束而不创建新会话:任务已完成或正在运行、任务等待必要输入/审批、会话已删除、原 provider 会话文件不存在、渠道不可用,或任务状态已被更新。
|
|
13
15
|
|
|
14
16
|
独立 CLI 必须通过 daemon 的本地 control token。托管任务使用当前任务 delegation token,并需要 Agent 管理权限;普通 Agent 只能恢复当前 Agent 的会话,daemon scope 才能恢复其它 Agent 的会话。
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
|
|
11
11
|
文件输入限制为 4 MiB,拒绝符号链接、junction、硬链接、路径逃逸、其他会话临时目录、密钥及其他 Agent 私有数据。普通定义导入必须属于当前 Agent;脚本只上传 `execution.script.path` 指定的单个文件,不允许覆盖 `trigger.json`、`active.json` 等管理状态。绝对 `--script-path` 会上传脚本内容并保存 Agent 内相对路径,不保留宿主绝对路径。`--help` / `-h` 在鉴权和文件读取前返回。
|
|
12
12
|
|
|
13
|
-
普通脚本 Trigger 按每次执行重新核验的 Agent
|
|
13
|
+
普通脚本 Trigger 按每次执行重新核验的 Agent 授权运行,复用主会话的权限模式与 H/L 路径保护:`readonly` 项目只读且禁止读取 L 类路径,`auto/request` 项目可写、L 类路径只读;认证 `owner + bypass` 关闭项目写入沙箱,但仍遮蔽 H 类路径并保护 L 类路径。网络默认开放,不需要网络权限配置;保留宿主 HOME、Git/SSH 与代理环境,清除 daemon 凭据、任务 delegation 和代码注入变量。`request` 的非交互脚本不能申请额外权限,越界操作直接失败,不自动升级。脚本使用只读快照和独立临时工作目录;快照位置不同于持久化 Trigger 目录,需要项目资源时按工作目录定位。Node `.js` 保留原 package 的模块类型。
|
|
14
14
|
|
|
15
|
-
- Linux:需要可用的 `bubblewrap
|
|
15
|
+
- Linux:需要可用的 `bubblewrap`,复用会话权限运行时的进程隔离和 H/L 路径保护,不隔离网络命名空间;受限模式将宿主根目录只读映射,按权限开放项目和当前 run 临时目录,完整保留系统依赖及 `/etc/alternatives` 链接。
|
|
16
16
|
- Windows:需要支持受限读取策略的原生 Codex CLI,以及宿主已准备好的 elevated sandbox。每次启动前先用同一个临时 canary 验证“显式授权可读、撤回授权后拒绝读取”和当前 run 可写;只有权限拒绝才算通过,文件不存在、探针超时或取消均失败关闭。旧初始化、不支持的运行时或无法证明读取隔离时返回 `SCRIPT_SANDBOX_UNAVAILABLE`,不会启动用户脚本;托管任务不会自动提权、初始化沙箱或降级为宿主执行。
|
|
17
17
|
- 其他平台:当前普通脚本执行失败关闭,不提供未隔离的回退。
|
|
18
18
|
|
|
@@ -6,15 +6,6 @@ ECK 的总览:前置概念和框架结构。
|
|
|
6
6
|
|
|
7
7
|
Base agent 是提供推理与生成能力的底层智能,规范值有 `claude`(Claude Code)、`codex`(Codex)、`gemini`(Gemini CLI)、`ecagent`(EvolCore 内置基座)四类。你就是当前会话的 base agent;具体是哪一类以 `[baseagent]` 段注入的 `baseAgentName` 为准,不要默认自己是 Claude Code。
|
|
8
8
|
|
|
9
|
-
### 外部 Coding Agent Skills 边界
|
|
10
|
-
|
|
11
|
-
当前会话由 EvolCore 托管时,不加载、不读取、不执行工作区之外的 coding-agent `SKILL.md`,包括
|
|
12
|
-
`/home/evolcore/skills/eclink/SKILL.md`。该类 skill 只服务于独立运行、未接入 EvolCore 会话上下文的
|
|
13
|
-
Codex/Claude Code 等独立工具实例。EvolCore 会话必须遵循本 ECK、daemon IPC 和渠道适配层提供的通信与权限路径。
|
|
14
|
-
|
|
15
|
-
尤其不要在 EvolCore 会话中因为看到 AUN/agent 间通信需求,就自行读取 `eclink` skill 或直接拼接 shell
|
|
16
|
-
命令调用 `ec`;发送必须经过当前会话的 delegated sender,以便锁定 self/peer、角色、审计和回执。
|
|
17
|
-
|
|
18
9
|
## AUN 是什么
|
|
19
10
|
|
|
20
11
|
AUN(Agent Union Network)是 agent 间安全通信的网络协议,SDK 的 npm 包名 `@agentunion/fastaun`。
|
package/kits/rules/06-channel.md
CHANGED
|
@@ -45,7 +45,13 @@
|
|
|
45
45
|
**完整命令集目录(含分类、触发词、适用场景)**:`$KITS_DOCS/evolcore/INDEX.md`。
|
|
46
46
|
单个命令集的详细用法按需 Read 对应文档。
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
### 当前托管实例的生命周期保护
|
|
49
|
+
|
|
50
|
+
托管 Agent 不得自行停止、重启或替换承载当前会话的 EvolCore 实例,包括针对该实例的 `ec stop`、`ec restart`、`ec restart-monitor` 和会启动替代进程的 `ec start`。限制以实际目标实例为准,不按命令名称、是否同主机或调用通道一概判定;`fullaccess` 不解除自身实例保护。
|
|
51
|
+
|
|
52
|
+
其他 EvolCore 实例(包括同主机的独立实例和远程实例)不属于上述保护范围,操作仍须获得用户授权并满足目标端权限。SSH、受鉴权 API 或其他获准的管理通道均可使用,不限定为 SSH;通过回连、代理或端口转发实际操作自身实例,仍受上述限制。无法确认目标是否为自身实例时,应先核实,不得仅凭“远程”调用形式认定允许。
|
|
53
|
+
|
|
54
|
+
修改承载当前会话的 EvolCore 源码后,Agent 只负责构建并报告需要宿主重启;`ec agent reload` 只重载配置/persona/memory,不重载源码。
|
|
49
55
|
|
|
50
56
|
共同约定:
|
|
51
57
|
- 以自己的 AID 为发送者
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[commands] 当前场景可用命令集(前缀 ec,以自己 AID 为发送者;完整用法 Read 对应文档)
|
|
2
2
|
遇到明确触发词(费用/用量/统计/创建agent/建群/查群/群聊协作/任务分派等)优先查 INDEX.md 或直接试对应 ec 命令
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
生命周期保护仅针对承载当前会话的 EvolCore 实例;其他实例按用户授权和目标端权限处理,不限管理通道。完整规则见 `$KITS_RULES/06-channel.md`。
|
|
5
5
|
|
|
6
6
|
ec memory 记忆写入与整理(note 写入/修改/撤销/查看;consolidate 触发整理;何时写见 [memory] 段) $KITS_DOCS/evolcore/memory.md
|
|
7
7
|
ec ctl 当前会话工具(主动发消息/文件、重命名、队列、项目路径、会话状态) $KITS_DOCS/evolcore/ctl.md
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "evolcore",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.32",
|
|
4
4
|
"description": "AI Agent gateway connecting Claude, Codex, Gemini, and the bundled ecagent runner to messaging channels with multi-project session management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|