evolcore 0.0.29 → 0.0.30
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 +7 -0
- package/dist/agents/codex-runner.js +61 -14
- package/dist/aun/aid/agentmd.js +224 -19
- package/dist/aun/aid/index.js +2 -1
- package/dist/aun/aid/managed-operation.js +70 -4
- package/dist/aun/group/index.js +1 -0
- package/dist/{core → aun}/group/invite-service.js +4 -4
- package/dist/channels/daemon.js +1 -1
- package/dist/cli/agent-command.js +7 -7
- package/dist/cli/aun-commands.js +97 -37
- package/dist/cli/data-command.js +2 -1
- package/dist/cli/managed-command-guard.js +2 -2
- package/dist/cli/model.js +1 -1
- package/dist/cli/response.js +1 -1
- package/dist/cli/trigger-command.js +52 -29
- package/dist/config/boot-log.js +95 -1
- package/dist/config/builtin-roles.js +1 -0
- package/dist/config/peer-role-resolver.js +21 -0
- package/dist/core/agent-ipc-registration.js +409 -0
- package/dist/core/agent-runtime.js +435 -0
- package/dist/core/auth/delegation-authorization.js +58 -0
- package/dist/core/auth/operation-catalog.js +8 -0
- package/dist/core/bootstrap-service.js +65 -1
- package/dist/core/channel-runtime.js +435 -0
- package/dist/core/command/command-handler.js +4 -1
- package/dist/core/daemon-bootstrap.js +151 -0
- package/dist/core/daemon-control.js +205 -0
- package/dist/core/daemon-lifecycle.js +225 -0
- package/dist/core/data-migration.js +4 -1
- package/dist/core/handoff/ipc-registration.js +156 -0
- package/dist/core/ipc-registration.js +457 -0
- package/dist/core/memory/consolidation-trigger.js +8 -0
- package/dist/core/memory/consolidation.js +838 -0
- package/dist/core/message/aun-ipc-sender.js +226 -0
- package/dist/core/message/outbound.js +165 -0
- package/dist/core/permission/approval-gateway.js +13 -0
- package/dist/core/permission/ec-command-parser.js +80 -35
- package/dist/core/permission/sandbox-runtime.js +23 -2
- package/dist/core/permission/tool-error-code.js +1 -0
- package/dist/core/permission/tool-policy.js +61 -24
- package/dist/core/session/session-idle-monitor.js +17 -0
- package/dist/index.js +352 -4841
- package/dist/ipc.js +2 -1
- package/dist/stats/db.js +24 -0
- package/dist/stats/index.js +1 -1
- package/dist/stats/writer.js +25 -1
- package/dist/trigger/application-service.js +157 -0
- package/dist/trigger/authorization.js +371 -0
- package/dist/trigger/ipc-service.js +406 -0
- package/dist/trigger/local-files.js +133 -0
- package/dist/trigger/manager.js +235 -22
- package/dist/trigger/scheduler.js +30 -5
- package/dist/trigger/script-executor.js +176 -39
- package/dist/trigger/script-sandbox.js +458 -0
- package/dist/trigger/system-definitions.js +188 -0
- package/dist/trigger/validation.js +0 -3
- package/dist/utils/aid-bind.js +1 -1
- package/dist/utils/evolcore-version.js +74 -0
- package/dist/utils/logger.js +16 -0
- package/kits/docs/evolcore/INDEX.md +1 -1
- package/kits/docs/evolcore/aid.md +9 -1
- package/kits/docs/evolcore/model.md +3 -2
- package/kits/docs/evolcore/rpc.md +4 -0
- package/kits/docs/evolcore/trigger.md +15 -1
- package/kits/schemas/relation-config.schema.9.json +1 -1
- package/kits/templates/system-fragments/commands.md +0 -1
- package/package.json +1 -1
- package/dist/core/memory/launch-consolidation.js +0 -395
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { spawn } from 'child_process';
|
|
2
|
+
import { buildTriggerScriptLaunch } from './script-sandbox.js';
|
|
2
3
|
import { previewText, resolveScriptPath, sha256, } from './validation.js';
|
|
4
|
+
const MAX_SCRIPT_OUTPUT_BYTES = 1 * 1024 * 1024;
|
|
3
5
|
export class TriggerScriptExecutor {
|
|
4
6
|
async execute(input) {
|
|
5
7
|
const script = input.trigger.execution.type === 'script'
|
|
@@ -19,6 +21,9 @@ export class TriggerScriptExecutor {
|
|
|
19
21
|
},
|
|
20
22
|
};
|
|
21
23
|
}
|
|
24
|
+
if (input.signal?.aborted) {
|
|
25
|
+
return this.errorResult(Date.now(), Buffer.alloc(0), Buffer.alloc(0), 'SCRIPT_ABORTED', 'script was aborted', 130);
|
|
26
|
+
}
|
|
22
27
|
const scriptAbs = resolveScriptPath(input.triggerDir, script.path);
|
|
23
28
|
const timeoutMs = script.timeoutMs ?? 30_000;
|
|
24
29
|
const scriptArgs = Array.isArray(script.args) ? script.args.map(arg => String(arg)) : [];
|
|
@@ -38,72 +43,157 @@ export class TriggerScriptExecutor {
|
|
|
38
43
|
},
|
|
39
44
|
args: script.args ?? {},
|
|
40
45
|
};
|
|
41
|
-
|
|
46
|
+
let launch;
|
|
47
|
+
try {
|
|
48
|
+
launch = buildTriggerScriptLaunch({
|
|
49
|
+
trigger: input.trigger,
|
|
50
|
+
triggerDir: input.triggerDir,
|
|
51
|
+
scriptPath: scriptAbs,
|
|
52
|
+
scriptArgs,
|
|
53
|
+
projectPath: input.projectPath,
|
|
54
|
+
executionAuthorization: input.executionAuthorization,
|
|
55
|
+
});
|
|
56
|
+
await launch.prepare?.(input.signal);
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
try {
|
|
60
|
+
launch?.cleanup?.();
|
|
61
|
+
}
|
|
62
|
+
catch { }
|
|
63
|
+
if (input.signal?.aborted) {
|
|
64
|
+
return this.errorResult(Date.now(), Buffer.alloc(0), Buffer.alloc(0), 'SCRIPT_ABORTED', 'script was aborted', 130);
|
|
65
|
+
}
|
|
66
|
+
return this.errorResult(Date.now(), Buffer.alloc(0), Buffer.alloc(0), 'SCRIPT_SANDBOX_UNAVAILABLE', error?.message || String(error), 126);
|
|
67
|
+
}
|
|
68
|
+
return await this.spawnProcess(launch, JSON.stringify(payload), timeoutMs, input.signal);
|
|
42
69
|
}
|
|
43
|
-
spawnProcess(
|
|
70
|
+
spawnProcess(launch, stdin, timeoutMs, signal) {
|
|
44
71
|
const startedAt = Date.now();
|
|
72
|
+
if (signal?.aborted) {
|
|
73
|
+
try {
|
|
74
|
+
launch.cleanup?.();
|
|
75
|
+
}
|
|
76
|
+
catch { }
|
|
77
|
+
return Promise.resolve(this.errorResult(startedAt, Buffer.alloc(0), Buffer.alloc(0), 'SCRIPT_ABORTED', 'script was aborted', 130));
|
|
78
|
+
}
|
|
45
79
|
return new Promise((resolve) => {
|
|
46
80
|
let stdout = Buffer.alloc(0);
|
|
47
81
|
let stderr = Buffer.alloc(0);
|
|
48
82
|
let settled = false;
|
|
49
83
|
let timedOut = false;
|
|
50
84
|
let aborted = false;
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
85
|
+
let outputLimitReached = false;
|
|
86
|
+
let terminationTimer;
|
|
87
|
+
let child;
|
|
88
|
+
let timer;
|
|
89
|
+
const finish = (result) => {
|
|
90
|
+
if (settled)
|
|
91
|
+
return;
|
|
92
|
+
settled = true;
|
|
93
|
+
clearTimeout(timer);
|
|
94
|
+
if (terminationTimer)
|
|
95
|
+
clearTimeout(terminationTimer);
|
|
96
|
+
signal?.removeEventListener('abort', abortHandler);
|
|
97
|
+
try {
|
|
98
|
+
launch.cleanup?.();
|
|
99
|
+
}
|
|
100
|
+
catch { }
|
|
101
|
+
resolve(result);
|
|
102
|
+
};
|
|
58
103
|
const abortHandler = () => {
|
|
59
104
|
aborted = true;
|
|
60
|
-
child
|
|
61
|
-
setTimeout(() => {
|
|
62
|
-
if (!settled)
|
|
63
|
-
child.kill('SIGKILL');
|
|
64
|
-
}, 2_000).unref();
|
|
105
|
+
terminateProcessTree(child, true);
|
|
65
106
|
};
|
|
107
|
+
try {
|
|
108
|
+
child = spawn(launch.command, launch.args, {
|
|
109
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
110
|
+
shell: false,
|
|
111
|
+
windowsHide: process.platform === 'win32',
|
|
112
|
+
windowsVerbatimArguments: launch.windowsVerbatimArguments,
|
|
113
|
+
cwd: launch.cwd,
|
|
114
|
+
env: launch.env,
|
|
115
|
+
detached: process.platform !== 'win32',
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
try {
|
|
120
|
+
launch.cleanup?.();
|
|
121
|
+
}
|
|
122
|
+
catch { }
|
|
123
|
+
resolve(this.errorResult(startedAt, stdout, stderr, 'SCRIPT_SPAWN_ERROR', error?.message || String(error), 127));
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
if (!child.stdout || !child.stderr || !child.stdin) {
|
|
127
|
+
terminateProcessTree(child, true);
|
|
128
|
+
try {
|
|
129
|
+
launch.cleanup?.();
|
|
130
|
+
}
|
|
131
|
+
catch { }
|
|
132
|
+
resolve(this.errorResult(startedAt, stdout, stderr, 'SCRIPT_SPAWN_ERROR', 'script process pipes are unavailable', 127));
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
const childStdout = child.stdout;
|
|
136
|
+
const childStderr = child.stderr;
|
|
137
|
+
const childStdin = child.stdin;
|
|
66
138
|
if (signal) {
|
|
67
139
|
if (signal.aborted)
|
|
68
140
|
abortHandler();
|
|
69
141
|
else
|
|
70
142
|
signal.addEventListener('abort', abortHandler, { once: true });
|
|
71
143
|
}
|
|
72
|
-
const
|
|
73
|
-
timedOut
|
|
74
|
-
|
|
75
|
-
|
|
144
|
+
const requestTermination = (reason) => {
|
|
145
|
+
if (timedOut || outputLimitReached || aborted)
|
|
146
|
+
return;
|
|
147
|
+
if (reason === 'timeout')
|
|
148
|
+
timedOut = true;
|
|
149
|
+
if (reason === 'output')
|
|
150
|
+
outputLimitReached = true;
|
|
151
|
+
terminateProcessTree(child, false);
|
|
152
|
+
terminationTimer = setTimeout(() => {
|
|
76
153
|
if (!settled)
|
|
77
|
-
child
|
|
78
|
-
},
|
|
79
|
-
|
|
154
|
+
terminateProcessTree(child, true);
|
|
155
|
+
}, 1_000);
|
|
156
|
+
terminationTimer.unref();
|
|
157
|
+
};
|
|
158
|
+
timer = setTimeout(() => requestTermination('timeout'), timeoutMs);
|
|
80
159
|
timer.unref();
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
160
|
+
const appendOutput = (target, chunk) => {
|
|
161
|
+
const remaining = MAX_SCRIPT_OUTPUT_BYTES - stdout.length - stderr.length;
|
|
162
|
+
if (remaining <= 0) {
|
|
163
|
+
requestTermination('output');
|
|
85
164
|
return;
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
165
|
+
}
|
|
166
|
+
const accepted = chunk.subarray(0, remaining);
|
|
167
|
+
if (target === 'stdout')
|
|
168
|
+
stdout = Buffer.concat([stdout, accepted]);
|
|
169
|
+
else
|
|
170
|
+
stderr = Buffer.concat([stderr, accepted]);
|
|
171
|
+
if (accepted.length < chunk.length) {
|
|
172
|
+
requestTermination('output');
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
childStdout.on('data', (chunk) => appendOutput('stdout', Buffer.from(chunk)));
|
|
176
|
+
childStderr.on('data', (chunk) => appendOutput('stderr', Buffer.from(chunk)));
|
|
177
|
+
child.on('error', (err) => {
|
|
178
|
+
finish(this.errorResult(startedAt, stdout, stderr, 'SCRIPT_SPAWN_ERROR', err.message, 127));
|
|
90
179
|
});
|
|
91
180
|
child.on('close', (code, closeSignal) => {
|
|
92
181
|
if (settled)
|
|
93
182
|
return;
|
|
94
|
-
settled = true;
|
|
95
|
-
clearTimeout(timer);
|
|
96
|
-
signal?.removeEventListener('abort', abortHandler);
|
|
97
183
|
if (aborted) {
|
|
98
|
-
|
|
184
|
+
finish(this.errorResult(startedAt, stdout, stderr, 'SCRIPT_ABORTED', 'script was aborted', code ?? 130));
|
|
99
185
|
return;
|
|
100
186
|
}
|
|
101
187
|
if (timedOut) {
|
|
102
|
-
|
|
188
|
+
finish(this.errorResult(startedAt, stdout, stderr, 'SCRIPT_TIMEOUT', `script timed out after ${timeoutMs}ms`, code ?? 124));
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
if (outputLimitReached) {
|
|
192
|
+
finish(this.errorResult(startedAt, stdout, stderr, 'SCRIPT_OUTPUT_LIMIT', `script output exceeded ${MAX_SCRIPT_OUTPUT_BYTES} bytes`, code ?? 1));
|
|
103
193
|
return;
|
|
104
194
|
}
|
|
105
|
-
if (
|
|
106
|
-
|
|
195
|
+
if (code !== 0) {
|
|
196
|
+
finish(this.errorResult(startedAt, stdout, stderr, 'SCRIPT_EXIT_NON_ZERO', `script exited with code ${code ?? `signal ${closeSignal}`}`, code ?? 1));
|
|
107
197
|
return;
|
|
108
198
|
}
|
|
109
199
|
const text = stdout.toString('utf-8').trim();
|
|
@@ -115,10 +205,10 @@ export class TriggerScriptExecutor {
|
|
|
115
205
|
}
|
|
116
206
|
}
|
|
117
207
|
catch (err) {
|
|
118
|
-
|
|
208
|
+
finish(this.errorResult(startedAt, stdout, stderr, 'SCRIPT_RESULT_PARSE_ERROR', err?.message || String(err), 1));
|
|
119
209
|
return;
|
|
120
210
|
}
|
|
121
|
-
|
|
211
|
+
finish({
|
|
122
212
|
exitCode: 0,
|
|
123
213
|
durationMs: Date.now() - startedAt,
|
|
124
214
|
stdoutBytes: stdout.length,
|
|
@@ -130,7 +220,8 @@ export class TriggerScriptExecutor {
|
|
|
130
220
|
result,
|
|
131
221
|
});
|
|
132
222
|
});
|
|
133
|
-
|
|
223
|
+
childStdin.on('error', () => { });
|
|
224
|
+
childStdin.end(stdin);
|
|
134
225
|
});
|
|
135
226
|
}
|
|
136
227
|
errorResult(startedAt, stdout, stderr, code, message, exitCode) {
|
|
@@ -154,3 +245,49 @@ export class TriggerScriptExecutor {
|
|
|
154
245
|
};
|
|
155
246
|
}
|
|
156
247
|
}
|
|
248
|
+
function terminateProcessTree(child, force) {
|
|
249
|
+
if (!child.pid)
|
|
250
|
+
return;
|
|
251
|
+
if (process.platform === 'win32') {
|
|
252
|
+
const taskkill = process.env.SystemRoot
|
|
253
|
+
? `${process.env.SystemRoot}\\System32\\taskkill.exe`
|
|
254
|
+
: 'taskkill.exe';
|
|
255
|
+
const args = ['/pid', String(child.pid), '/t', ...(force ? ['/f'] : [])];
|
|
256
|
+
const killer = spawn(taskkill, args, {
|
|
257
|
+
stdio: 'ignore',
|
|
258
|
+
windowsHide: true,
|
|
259
|
+
});
|
|
260
|
+
killer.on('error', () => {
|
|
261
|
+
try {
|
|
262
|
+
child.kill('SIGKILL');
|
|
263
|
+
}
|
|
264
|
+
catch { }
|
|
265
|
+
});
|
|
266
|
+
killer.on('close', code => {
|
|
267
|
+
if (force || code === 0)
|
|
268
|
+
return;
|
|
269
|
+
const forceKiller = spawn(taskkill, ['/pid', String(child.pid), '/t', '/f'], {
|
|
270
|
+
stdio: 'ignore',
|
|
271
|
+
windowsHide: true,
|
|
272
|
+
});
|
|
273
|
+
forceKiller.on('error', () => {
|
|
274
|
+
try {
|
|
275
|
+
child.kill('SIGKILL');
|
|
276
|
+
}
|
|
277
|
+
catch { }
|
|
278
|
+
});
|
|
279
|
+
forceKiller.unref();
|
|
280
|
+
});
|
|
281
|
+
killer.unref();
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
try {
|
|
285
|
+
process.kill(-(child.pid), force ? 'SIGKILL' : 'SIGTERM');
|
|
286
|
+
}
|
|
287
|
+
catch {
|
|
288
|
+
try {
|
|
289
|
+
child.kill(force ? 'SIGKILL' : 'SIGTERM');
|
|
290
|
+
}
|
|
291
|
+
catch { }
|
|
292
|
+
}
|
|
293
|
+
}
|