evolcore 0.0.19 → 0.0.21
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 +43 -1
- package/README.md +60 -9
- package/bin/install-codex-managed-hooks.mjs +61 -0
- package/dist/agents/baseagent.js +10 -6
- package/dist/agents/claude-runner.js +383 -111
- package/dist/agents/codex-app-server-client.js +10 -2
- package/dist/agents/codex-runner.js +405 -137
- package/dist/agents/ecagent-runner.js +174 -63
- package/dist/agents/gemini-runner.js +130 -30
- package/dist/agents/request-identity.js +25 -0
- package/dist/agents/runner-types.js +19 -0
- package/dist/aun/aid/agentmd.js +66 -2
- package/dist/aun/aid/identity.js +4 -1
- package/dist/aun/aid/index.js +1 -1
- package/dist/aun/msg/group.js +86 -9
- package/dist/aun/msg/history.js +213 -36
- package/dist/aun/msg/managed-operation.js +58 -9
- package/dist/aun/msg/p2p.js +26 -11
- package/dist/aun/outbox.js +295 -68
- package/dist/aun/service-proxy.js +43 -25
- package/dist/channels/aun.js +1004 -273
- package/dist/channels/daemon.js +6 -1
- package/dist/cli/agent-command.js +4 -3
- package/dist/cli/agent.js +66 -56
- package/dist/cli/aun-commands.js +177 -42
- package/dist/cli/command-log.js +10 -11
- package/dist/cli/contact.js +1 -0
- package/dist/cli/daemon-commands.js +81 -121
- package/dist/cli/index.js +1 -0
- package/dist/cli/init.js +76 -24
- package/dist/cli/restart-monitor.js +3 -3
- package/dist/cli/task-context.js +46 -0
- package/dist/cli/trigger-command.js +1 -1
- package/dist/cli/watch-logs.js +10 -3
- package/dist/config/builtin-roles.js +1 -0
- package/dist/config/config-field-policy.js +16 -5
- package/dist/config/config-manager.js +226 -24
- package/dist/config/config-operation-service.js +1 -2
- package/dist/config/contact-operation-service.js +32 -1
- package/dist/config/contact-request-service.js +44 -0
- package/dist/config/daemon-services.js +186 -0
- package/dist/config/gateway-config.js +29 -16
- package/dist/config/lifecycle.js +16 -5
- package/dist/config/role-service.js +54 -3
- package/dist/config/schema-migration.js +550 -0
- package/dist/config-store.js +161 -12
- package/dist/core/agent-application-service.js +279 -0
- package/dist/core/audit/log-integrity.js +102 -0
- package/dist/core/auth/agent-delegation.js +31 -1
- package/dist/core/auth/auth-gateway.js +33 -4
- package/dist/core/auth/authorization-audit.js +155 -4
- package/dist/core/auth/operation-authorizer.js +41 -1
- package/dist/core/auth/operation-catalog.js +9 -1
- package/dist/core/bootstrap-messages.js +2 -2
- package/dist/core/bootstrap-service.js +27 -38
- package/dist/core/causation/aun-association.js +7 -4
- package/dist/core/channel-loader.js +0 -2
- package/dist/core/command/agent-control.js +56 -16
- package/dist/core/command/command-handler.js +290 -44
- package/dist/core/command/connect-menu.js +3 -4
- package/dist/core/command/group-menu.js +5 -7
- package/dist/core/command/menu-handler.js +279 -80
- package/dist/core/command/role-menu.js +21 -11
- package/dist/core/command/slash-gate.js +85 -18
- package/dist/core/command/slash-handler.js +350 -32
- package/dist/core/event-catalog.js +5 -0
- package/dist/core/evolagent.js +9 -4
- package/dist/core/handoff/dispatcher.js +4 -0
- package/dist/core/handoff/runtime.js +10 -0
- package/dist/core/handoff/store.js +32 -9
- package/dist/core/inference/text-inference.js +7 -15
- package/dist/core/message/im-renderer.js +83 -84
- package/dist/core/message/{inbound-admission.js → message-admission.js} +51 -1
- package/dist/core/message/message-bridge.js +124 -10
- package/dist/core/message/message-log.js +14 -7
- package/dist/core/message/message-queue.js +206 -16
- package/dist/core/message/message-utils.js +12 -5
- package/dist/core/message/response-engine.js +495 -72
- package/dist/core/message/send-receipt.js +1 -0
- package/dist/core/message/stream-debouncer.js +9 -2
- package/dist/core/model/model-catalog.js +23 -15
- package/dist/core/model/model-diagnostics.js +28 -10
- package/dist/core/permission/approval-gateway.js +180 -6
- package/dist/core/permission/ec-command-parser.js +465 -56
- package/dist/core/permission/mode.js +18 -3
- package/dist/core/{protected-paths.js → permission/protected-paths.js} +17 -5
- package/dist/core/permission/readonly-shell-query.js +263 -9
- package/dist/core/permission/sandbox-runtime.js +205 -13
- package/dist/core/permission/tool-policy.js +673 -62
- package/dist/core/relation/peer-identity.js +18 -0
- package/dist/core/session/session-fs-store.js +154 -5
- package/dist/core/session/session-manager.js +299 -30
- package/dist/core/session/session-renew.js +19 -12
- package/dist/core/session/session-turn-coordinator.js +11 -4
- package/dist/eck/kit-renderer.js +18 -9
- package/dist/index.js +283 -65
- package/dist/ipc.js +374 -24
- package/dist/paths.js +64 -7
- package/dist/response-system/context-builder.js +1 -7
- package/dist/trigger/anomaly-store.js +1 -0
- package/dist/trigger/feedback.js +56 -5
- package/dist/trigger/history.js +79 -4
- package/dist/trigger/legacy-session-history.js +2 -2
- package/dist/trigger/parser.js +3 -2
- package/dist/trigger/validation.js +6 -1
- package/dist/utils/atomic-write.js +27 -0
- package/dist/utils/ecweb-utils.js +16 -2
- package/dist/utils/error-utils.js +4 -1
- package/dist/utils/logger.js +21 -2
- package/dist/utils/process-tree-stats.js +24 -4
- package/dist/utils/process-tree-worker.js +31 -0
- package/dist/utils/project-path.js +1 -2
- package/dist/utils/stats.js +52 -18
- package/dist/utils/welcome.js +2 -2
- package/kits/docs/INDEX.md +1 -1
- package/kits/docs/evolcore/INDEX.md +1 -1
- package/kits/docs/evolcore/contact.md +7 -1
- package/kits/docs/evolcore/msg.md +16 -0
- package/kits/rules/01-overview.md +1 -1
- package/kits/rules/03-identity.md +1 -1
- package/kits/rules/05-venue.md +1 -1
- package/kits/schemas/_meta.json +10 -5
- package/kits/schemas/agent-config.schema.10.json +2 -1
- package/kits/schemas/agent-config.schema.11.json +421 -0
- package/kits/schemas/daemon.schema.5.json +135 -0
- package/kits/schemas/daemon.schema.6.json +131 -0
- package/kits/schemas/defaults.schema.5.json +119 -0
- package/kits/schemas/migrations/README.md +3 -1
- package/kits/schemas/relation-config.schema.8.json +13 -0
- package/kits/schemas/role-config.schema.1.json +1 -2
- package/kits/schemas/single-session.schema.3.json +32 -0
- package/kits/templates/roles/admin.json +1 -0
- package/kits/templates/roles/member.json +1 -0
- package/kits/templates/roles/visitor.json +1 -0
- package/package.json +7 -3
- package/skills/eclink/SKILL.md +2 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { resolveCommandPath } from '../../utils/cross-platform.js';
|
|
4
|
-
import { getExistingHClassMaskTargets, getExistingLClassReadOnlyTargets, isSameOrDescendant, } from '
|
|
4
|
+
import { getExistingHClassMaskTargets, getExistingLClassReadOnlyTargets, isSameOrDescendant, } from './protected-paths.js';
|
|
5
5
|
import { resolveRoot } from '../../paths.js';
|
|
6
6
|
let cachedBubblewrapPath;
|
|
7
7
|
let sandboxInitializationCircuit;
|
|
@@ -9,6 +9,7 @@ let sandboxCircuitNoticeAt = 0;
|
|
|
9
9
|
export const SANDBOX_INITIALIZATION_FAILED = 'sandbox_initialization_failed';
|
|
10
10
|
export const SANDBOX_INITIALIZATION_COOLDOWN_MS = 5 * 60 * 1000;
|
|
11
11
|
export const SANDBOX_CIRCUIT_NOTICE_INTERVAL_MS = 60 * 1000;
|
|
12
|
+
const SANDBOX_DIAGNOSTIC_TARGET_LIMIT = 256;
|
|
12
13
|
/** Open a process-wide fail-closed circuit after a confirmed host bootstrap failure. */
|
|
13
14
|
export function recordSandboxInitializationFailure(error, stderr = [], now = Date.now()) {
|
|
14
15
|
const detail = createSandboxInitializationError(error, stderr).message.slice(0, 512);
|
|
@@ -218,6 +219,163 @@ function pushMaskedDirectory(args, candidate) {
|
|
|
218
219
|
return;
|
|
219
220
|
args.push('--tmpfs', candidate);
|
|
220
221
|
}
|
|
222
|
+
function decodeMountInfoPath(value) {
|
|
223
|
+
// mountinfo escapes whitespace, backslashes, and newlines as octal bytes.
|
|
224
|
+
return value.replace(/\\([0-7]{3})/g, (_match, octal) => {
|
|
225
|
+
const code = Number.parseInt(octal, 8);
|
|
226
|
+
return Number.isNaN(code) ? _match : String.fromCharCode(code);
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
function readMountInfoForPaths(paths, priorityPaths = []) {
|
|
230
|
+
if (process.platform !== 'linux' || paths.length === 0)
|
|
231
|
+
return [];
|
|
232
|
+
let contents;
|
|
233
|
+
try {
|
|
234
|
+
contents = fs.readFileSync('/proc/self/mountinfo', 'utf8');
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
return [`mountinfo unavailable: ${error instanceof Error ? error.message : String(error)}`];
|
|
238
|
+
}
|
|
239
|
+
const wanted = paths.map(candidate => path.resolve(candidate));
|
|
240
|
+
const priority = priorityPaths.map(candidate => path.resolve(candidate));
|
|
241
|
+
const matches = [];
|
|
242
|
+
for (const [order, line] of contents.split(/\r?\n/).filter(Boolean).entries()) {
|
|
243
|
+
const mountPointField = line.split(' - ', 1)[0]?.split(' ')[4];
|
|
244
|
+
if (!mountPointField)
|
|
245
|
+
continue;
|
|
246
|
+
const mountPoint = path.resolve(decodeMountInfoPath(mountPointField));
|
|
247
|
+
if (!wanted.some(target => isSameOrDescendant(target, mountPoint)
|
|
248
|
+
|| isSameOrDescendant(mountPoint, target)))
|
|
249
|
+
continue;
|
|
250
|
+
const isPriority = priority.some(target => target === mountPoint);
|
|
251
|
+
const isPriorityAncestor = !isPriority && priority.some(target => isSameOrDescendant(target, mountPoint));
|
|
252
|
+
matches.push({ line, score: isPriority ? 0 : isPriorityAncestor ? 1 : 2, order });
|
|
253
|
+
}
|
|
254
|
+
return matches
|
|
255
|
+
.sort((left, right) => left.score - right.score || left.order - right.order)
|
|
256
|
+
.slice(0, 32)
|
|
257
|
+
.map(match => match.line);
|
|
258
|
+
}
|
|
259
|
+
function snapshotSandboxPath(candidate) {
|
|
260
|
+
const resolved = path.resolve(candidate);
|
|
261
|
+
try {
|
|
262
|
+
const stat = fs.lstatSync(resolved);
|
|
263
|
+
let kind = 'other';
|
|
264
|
+
if (stat.isFile())
|
|
265
|
+
kind = 'file';
|
|
266
|
+
else if (stat.isDirectory())
|
|
267
|
+
kind = 'directory';
|
|
268
|
+
else if (stat.isSymbolicLink())
|
|
269
|
+
kind = 'symlink';
|
|
270
|
+
let realpath;
|
|
271
|
+
try {
|
|
272
|
+
realpath = fs.realpathSync(resolved);
|
|
273
|
+
}
|
|
274
|
+
catch { }
|
|
275
|
+
return {
|
|
276
|
+
path: resolved,
|
|
277
|
+
exists: true,
|
|
278
|
+
kind,
|
|
279
|
+
dev: stat.dev,
|
|
280
|
+
ino: stat.ino,
|
|
281
|
+
mode: stat.mode & 0o7777,
|
|
282
|
+
uid: stat.uid,
|
|
283
|
+
gid: stat.gid,
|
|
284
|
+
nlink: stat.nlink,
|
|
285
|
+
size: stat.size,
|
|
286
|
+
mtimeMs: stat.mtimeMs,
|
|
287
|
+
ctimeMs: stat.ctimeMs,
|
|
288
|
+
...(realpath ? { realpath } : {}),
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
catch (error) {
|
|
292
|
+
const code = error.code;
|
|
293
|
+
return {
|
|
294
|
+
path: resolved,
|
|
295
|
+
exists: false,
|
|
296
|
+
...(code ? { error: code } : { error: error instanceof Error ? error.message : String(error) }),
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
/** Capture the host-side state used to construct an H-class guard. */
|
|
301
|
+
export function collectSandboxGuardDiagnostics(root = resolveRoot()) {
|
|
302
|
+
const absoluteRoot = path.resolve(root);
|
|
303
|
+
const candidates = [
|
|
304
|
+
path.join(absoluteRoot, 'data', 'causation-aun.json'),
|
|
305
|
+
path.join(absoluteRoot, 'data', 'causation-aun.json_'),
|
|
306
|
+
path.join(absoluteRoot, 'data', 'causation-aun.json__'),
|
|
307
|
+
];
|
|
308
|
+
let targets = [];
|
|
309
|
+
try {
|
|
310
|
+
targets = getExistingHClassMaskTargets(absoluteRoot).map(target => target.path);
|
|
311
|
+
}
|
|
312
|
+
catch { }
|
|
313
|
+
// Keep the causation file and its atomic-write sidecars first. The full H
|
|
314
|
+
// target list can grow with the number of agents and must not turn every
|
|
315
|
+
// launch into an unbounded log payload.
|
|
316
|
+
const paths = [...new Set([...candidates, ...targets])];
|
|
317
|
+
const selectedPaths = paths.slice(0, SANDBOX_DIAGNOSTIC_TARGET_LIMIT);
|
|
318
|
+
return {
|
|
319
|
+
root: absoluteRoot,
|
|
320
|
+
targetCount: paths.length,
|
|
321
|
+
targetsTruncated: paths.length > selectedPaths.length,
|
|
322
|
+
targets: selectedPaths.map(snapshotSandboxPath),
|
|
323
|
+
mountInfo: readMountInfoForPaths(selectedPaths, candidates),
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
/** Reduce path and mount diagnostics to metadata suitable for INFO logs. */
|
|
327
|
+
export function summarizeSandboxGuardDiagnostics(diagnostics) {
|
|
328
|
+
let existingTargetCount = 0;
|
|
329
|
+
let missingTargetCount = 0;
|
|
330
|
+
const targetKindCounts = {};
|
|
331
|
+
for (const target of diagnostics.targets) {
|
|
332
|
+
if (!target.exists) {
|
|
333
|
+
missingTargetCount += 1;
|
|
334
|
+
continue;
|
|
335
|
+
}
|
|
336
|
+
existingTargetCount += 1;
|
|
337
|
+
const kind = target.kind ?? 'unknown';
|
|
338
|
+
targetKindCounts[kind] = (targetKindCounts[kind] ?? 0) + 1;
|
|
339
|
+
}
|
|
340
|
+
return {
|
|
341
|
+
root: diagnostics.root,
|
|
342
|
+
targetCount: diagnostics.targetCount,
|
|
343
|
+
targetsTruncated: diagnostics.targetsTruncated,
|
|
344
|
+
existingTargetCount,
|
|
345
|
+
missingTargetCount,
|
|
346
|
+
targetKindCounts,
|
|
347
|
+
mountInfoCount: diagnostics.mountInfo.length,
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
/** Keep the exact mount portion of a bwrap argv while summarizing child argv. */
|
|
351
|
+
export function summarizeBubblewrapArgs(args) {
|
|
352
|
+
const separator = args.indexOf('--');
|
|
353
|
+
const mountArgs = [...args.slice(0, separator >= 0 ? separator : args.length)];
|
|
354
|
+
const child = separator >= 0 ? args.slice(separator + 1) : [];
|
|
355
|
+
return {
|
|
356
|
+
mountArgs,
|
|
357
|
+
...(child[0] ? { childCommand: child[0] } : {}),
|
|
358
|
+
childArgCount: Math.max(0, child.length - 1),
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
/** Keep only argument counts and option names for routine INFO logs. */
|
|
362
|
+
export function summarizeBubblewrapArgsForLog(args) {
|
|
363
|
+
const separator = args.indexOf('--');
|
|
364
|
+
const mountArgs = args.slice(0, separator >= 0 ? separator : args.length);
|
|
365
|
+
const child = separator >= 0 ? args.slice(separator + 1) : [];
|
|
366
|
+
const mountOptionCounts = {};
|
|
367
|
+
for (const arg of mountArgs) {
|
|
368
|
+
if (!arg.startsWith('--'))
|
|
369
|
+
continue;
|
|
370
|
+
mountOptionCounts[arg] = (mountOptionCounts[arg] ?? 0) + 1;
|
|
371
|
+
}
|
|
372
|
+
return {
|
|
373
|
+
mountArgCount: mountArgs.length,
|
|
374
|
+
mountOptionCounts,
|
|
375
|
+
...(child[0] ? { childCommand: child[0] } : {}),
|
|
376
|
+
childArgCount: Math.max(0, child.length - 1),
|
|
377
|
+
};
|
|
378
|
+
}
|
|
221
379
|
function appendRuntimeBackedEtcFiles(args) {
|
|
222
380
|
if (process.platform !== 'linux' || !fs.existsSync('/run'))
|
|
223
381
|
return;
|
|
@@ -285,6 +443,48 @@ function appendLClassReadOnlyBinds(args, root) {
|
|
|
285
443
|
args.push('--ro-bind', target.path, target.path);
|
|
286
444
|
}
|
|
287
445
|
}
|
|
446
|
+
export function ensureCodexManagedMountpoint(systemConfigDirectory = '/etc/codex', effectiveUid = typeof process.getuid === 'function' ? process.getuid() : undefined) {
|
|
447
|
+
let systemConfigStat;
|
|
448
|
+
try {
|
|
449
|
+
systemConfigStat = fs.lstatSync(systemConfigDirectory);
|
|
450
|
+
}
|
|
451
|
+
catch (error) {
|
|
452
|
+
if (error.code !== 'ENOENT') {
|
|
453
|
+
throw new Error(`Codex managed requirements mountpoint is unavailable: ${systemConfigDirectory} `
|
|
454
|
+
+ `could not be inspected (${error instanceof Error ? error.message : String(error)})`);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
if (!systemConfigStat && process.platform === 'linux' && effectiveUid === 0) {
|
|
458
|
+
let created = false;
|
|
459
|
+
try {
|
|
460
|
+
fs.mkdirSync(systemConfigDirectory, { mode: 0o755 });
|
|
461
|
+
created = true;
|
|
462
|
+
}
|
|
463
|
+
catch (error) {
|
|
464
|
+
if (error.code !== 'EEXIST') {
|
|
465
|
+
throw new Error(`Codex managed requirements mountpoint is unavailable: ${systemConfigDirectory} `
|
|
466
|
+
+ `could not be created by the root daemon (${error instanceof Error ? error.message : String(error)})`);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
if (created)
|
|
470
|
+
fs.chmodSync(systemConfigDirectory, 0o755);
|
|
471
|
+
try {
|
|
472
|
+
systemConfigStat = fs.lstatSync(systemConfigDirectory);
|
|
473
|
+
}
|
|
474
|
+
catch (error) {
|
|
475
|
+
throw new Error(`Codex managed requirements mountpoint is unavailable: ${systemConfigDirectory} `
|
|
476
|
+
+ `could not be verified after creation (${error instanceof Error ? error.message : String(error)})`);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
if (!systemConfigStat) {
|
|
480
|
+
throw new Error(`Codex managed requirements mountpoint is unavailable: ${systemConfigDirectory} `
|
|
481
|
+
+ 'must be created as a real directory during installation; run: sudo install -d -m 0755 /etc/codex');
|
|
482
|
+
}
|
|
483
|
+
if (!systemConfigStat.isDirectory() || systemConfigStat.isSymbolicLink()) {
|
|
484
|
+
throw new Error(`Codex managed requirements mountpoint is unsafe: ${systemConfigDirectory} `
|
|
485
|
+
+ 'must be a real directory');
|
|
486
|
+
}
|
|
487
|
+
}
|
|
288
488
|
export function buildHClassGuardCommand(executable, executableArgs, root = resolveRoot(), options = {}) {
|
|
289
489
|
const bubblewrapPath = resolveBubblewrapPath();
|
|
290
490
|
if (!bubblewrapPath)
|
|
@@ -306,18 +506,10 @@ export function buildHClassGuardCommand(executable, executableArgs, root = resol
|
|
|
306
506
|
}
|
|
307
507
|
const managedDirectory = path.dirname(requirements);
|
|
308
508
|
const systemConfigDirectory = '/etc/codex';
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
catch {
|
|
314
|
-
throw new Error(`Codex managed requirements mountpoint is unavailable: ${systemConfigDirectory} `
|
|
315
|
-
+ 'must be created as a real directory during installation');
|
|
316
|
-
}
|
|
317
|
-
if (!systemConfigStat.isDirectory() || systemConfigStat.isSymbolicLink()) {
|
|
318
|
-
throw new Error(`Codex managed requirements mountpoint is unsafe: ${systemConfigDirectory} `
|
|
319
|
-
+ 'must be a real directory');
|
|
320
|
-
}
|
|
509
|
+
// The npm lifecycle and public installer provision this path. Root-owned
|
|
510
|
+
// legacy daemons may repair only the missing-directory case; unsafe path
|
|
511
|
+
// types and unprivileged processes remain fail-closed.
|
|
512
|
+
ensureCodexManagedMountpoint(systemConfigDirectory);
|
|
321
513
|
// Keep the copied hook immutable even when a session uses bypass mode.
|
|
322
514
|
args.push('--ro-bind', managedDirectory, managedDirectory);
|
|
323
515
|
// The guard starts from a writable root so owner-bypass workspaces keep
|