evolcore 0.0.7 → 0.0.8

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/dist/ipc.js CHANGED
@@ -247,6 +247,8 @@ export class IpcServer {
247
247
  return roots;
248
248
  }
249
249
  start() {
250
+ if (this.server)
251
+ return Promise.resolve();
250
252
  // Remove stale socket file (Unix only — named pipes auto-cleanup on process exit)
251
253
  if (!isNamedPipe(this.socketPath)) {
252
254
  try {
@@ -0,0 +1,39 @@
1
+ import { execFileSync } from 'child_process';
2
+ import { isWindows, resolveCommandPath } from './cross-platform.js';
3
+ /**
4
+ * Resolve the installed Codex CLI entrypoint. npm creates a `.cmd` shim on
5
+ * Windows, which is not the same executable as the extensionless Unix shim.
6
+ */
7
+ export function resolveCodexCliPath() {
8
+ return resolveCommandPath('codex');
9
+ }
10
+ /**
11
+ * Build a child-process invocation that works for npm's Windows command shim.
12
+ * The options are injectable so platform-specific behavior can be tested on
13
+ * non-Windows CI hosts.
14
+ */
15
+ export function resolveCodexLaunchCommand(args, options = {}) {
16
+ const windows = options.isWindows ?? isWindows;
17
+ const commandPath = options.commandPath !== undefined
18
+ ? options.commandPath
19
+ : resolveCodexCliPath();
20
+ if (!commandPath)
21
+ return null;
22
+ if (windows && /\.(cmd|bat)$/i.test(commandPath)) {
23
+ return {
24
+ command: options.comSpec ?? process.env.ComSpec ?? 'cmd.exe',
25
+ args: ['/d', '/s', '/c', commandPath, ...args],
26
+ };
27
+ }
28
+ return { command: commandPath, args };
29
+ }
30
+ /** Execute a Codex CLI command using the resolved npm shim/path. */
31
+ export function execCodexCliSync(args, options) {
32
+ const commandPath = resolveCodexCliPath();
33
+ if (!commandPath)
34
+ throw new Error('Codex CLI not found');
35
+ const launchCommand = resolveCodexLaunchCommand(args, { commandPath });
36
+ if (!launchCommand)
37
+ throw new Error('Codex CLI not found');
38
+ return execFileSync(launchCommand.command, launchCommand.args, options);
39
+ }
@@ -3,7 +3,7 @@ import { fileURLToPath } from 'url';
3
3
  import { execFileSync, execFile, spawn, spawnSync } from 'child_process';
4
4
  import { promisify } from 'util';
5
5
  import fs from 'fs';
6
- import { getProcessStartTime } from './process-introspect.js';
6
+ import { getProcessStartTime, parseCimDate } from './process-introspect.js';
7
7
  const execFileAsync = promisify(execFile);
8
8
  export const isWindows = process.platform === 'win32';
9
9
  const ENCODE_PATH_MAX = 200;
@@ -38,6 +38,10 @@ export function encodePath(projectPath) {
38
38
  * Cross-platform process liveness check.
39
39
  */
40
40
  export function isProcessRunning(pid) {
41
+ if (!Number.isInteger(pid) || pid <= 0)
42
+ return false;
43
+ if (isWindows)
44
+ return isWindowsProcessRunning(pid);
41
45
  try {
42
46
  process.kill(pid, 0);
43
47
  return true;
@@ -47,23 +51,65 @@ export function isProcessRunning(pid) {
47
51
  return e.code === 'EPERM';
48
52
  }
49
53
  }
54
+ function isWindowsProcessRunning(pid) {
55
+ try {
56
+ const result = spawnSync('tasklist', ['/FI', `PID eq ${pid}`, '/FO', 'CSV', '/NH'], { encoding: 'utf-8', timeout: 3000, stdio: ['ignore', 'pipe', 'ignore'], windowsHide: true });
57
+ if (result.status === 0 && new RegExp(`,"${pid}",`, 'i').test(result.stdout || ''))
58
+ return true;
59
+ }
60
+ catch { }
61
+ // Keep a conservative fallback for restricted Windows environments where
62
+ // tasklist is unavailable. A failed probe must never be treated as proof of
63
+ // process exit by lifecycle code.
64
+ try {
65
+ process.kill(pid, 0);
66
+ return true;
67
+ }
68
+ catch (e) {
69
+ return e?.code === 'EPERM';
70
+ }
71
+ }
50
72
  /**
51
73
  * Cross-platform process termination.
52
74
  */
53
75
  export function killProcess(pid, force = false) {
54
- if (isWindows && force) {
76
+ if (!Number.isInteger(pid) || pid <= 0)
77
+ return false;
78
+ if (isWindows) {
55
79
  try {
56
- spawnSync('taskkill', ['/PID', String(pid), '/F'], { windowsHide: true });
80
+ const args = ['/PID', String(pid), '/T'];
81
+ if (force)
82
+ args.push('/F');
83
+ const result = spawnSync('taskkill', args, {
84
+ encoding: 'utf-8',
85
+ timeout: 10_000,
86
+ stdio: ['ignore', 'pipe', 'pipe'],
87
+ windowsHide: true,
88
+ });
89
+ return result.status === 0 || !isProcessRunning(pid);
57
90
  }
58
- catch { }
59
- }
60
- else {
61
- try {
62
- process.kill(pid, force ? 'SIGKILL' : 'SIGTERM');
91
+ catch {
92
+ return !isProcessRunning(pid);
63
93
  }
64
- catch { }
94
+ }
95
+ try {
96
+ process.kill(pid, force ? 'SIGKILL' : 'SIGTERM');
97
+ return true;
98
+ }
99
+ catch {
100
+ return !isProcessRunning(pid);
65
101
  }
66
102
  }
103
+ /** Wait until a process has really disappeared from the host process table. */
104
+ export async function waitForProcessExit(pid, timeoutMs = 10_000, intervalMs = 250) {
105
+ const deadline = Date.now() + timeoutMs;
106
+ while (Date.now() < deadline) {
107
+ if (!isProcessRunning(pid))
108
+ return true;
109
+ await new Promise(resolve => setTimeout(resolve, intervalMs));
110
+ }
111
+ return !isProcessRunning(pid);
112
+ }
67
113
  /**
68
114
  * Cross-platform process search by command line pattern.
69
115
  * Returns list of matching PIDs.
@@ -71,11 +117,37 @@ export function killProcess(pid, force = false) {
71
117
  export function findProcesses(pattern) {
72
118
  try {
73
119
  if (isWindows) {
74
- const result = spawnSync('wmic', ['process', 'where', `CommandLine like '%${pattern}%'`, 'get', 'ProcessId'], { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true });
75
- const output = result.stdout || '';
76
- return output.split('\n')
77
- .map(line => parseInt(line.trim(), 10))
78
- .filter(pid => !isNaN(pid) && pid !== process.pid);
120
+ // WMI LIKE is wildcard matching, not JavaScript regex matching. Query a
121
+ // stable literal anchor first, then apply the requested regex locally.
122
+ const anchor = windowsProcessSearchAnchor(pattern);
123
+ const escapedAnchor = anchor.replace(/'/g, "''");
124
+ const script = `$a='${escapedAnchor}'; Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -and $_.CommandLine -like ('*' + $a + '*') } | Select-Object ProcessId,CommandLine | ConvertTo-Json -Compress`;
125
+ const result = spawnSync('powershell', ['-NoProfile', '-Command', script], { encoding: null, timeout: 8000, stdio: ['ignore', 'pipe', 'ignore'], windowsHide: true });
126
+ const raw = decodeWindowsOutput(result.stdout).trim();
127
+ if (raw) {
128
+ const parsed = JSON.parse(raw);
129
+ const rows = !parsed ? [] : Array.isArray(parsed) ? parsed : [parsed];
130
+ const matcherCandidates = [pattern, pattern.replace(/\\\\/g, '\\')]
131
+ .filter((value, index, values) => values.indexOf(value) === index)
132
+ .map((value) => {
133
+ try {
134
+ return new RegExp(value, 'i');
135
+ }
136
+ catch {
137
+ return null;
138
+ }
139
+ })
140
+ .filter((value) => value !== null);
141
+ return rows
142
+ .filter(row => Number.isInteger(row.ProcessId) && row.ProcessId !== process.pid)
143
+ .filter(row => {
144
+ const commandLine = row.CommandLine || '';
145
+ const normalized = commandLine.replace(/\\/g, '/');
146
+ return matcherCandidates.some(matcher => matcher.test(commandLine) || matcher.test(normalized));
147
+ })
148
+ .map(row => row.ProcessId);
149
+ }
150
+ return [];
79
151
  }
80
152
  else {
81
153
  const output = execFileSync('pgrep', ['-f', pattern], { encoding: 'utf-8' }).trim();
@@ -86,6 +158,10 @@ export function findProcesses(pattern) {
86
158
  return [];
87
159
  }
88
160
  }
161
+ function windowsProcessSearchAnchor(pattern) {
162
+ const tokens = pattern.match(/[A-Za-z0-9][A-Za-z0-9._-]{2,}/g) || [];
163
+ return tokens.sort((a, b) => b.length - a.length)[0] || pattern;
164
+ }
89
165
  /**
90
166
  * Cross-platform: find PIDs listening on a TCP port.
91
167
  * Used to clean up stale/orphaned listeners (e.g. manually-spawned ecweb
@@ -124,13 +200,35 @@ export function findProcessByPort(port) {
124
200
  export function getProcessInfo(pid) {
125
201
  try {
126
202
  if (isWindows) {
203
+ // WMIC was removed from recent Windows installations. Prefer the
204
+ // supported CIM API and keep WMIC as a compatibility fallback.
205
+ const psScript = `(Get-CimInstance Win32_Process -Filter 'ProcessId=${pid}' | Select-Object WorkingSetSize,CreationDate | ConvertTo-Json -Compress)`;
206
+ const ps = spawnSync('powershell', ['-NoProfile', '-Command', psScript], {
207
+ encoding: null, timeout: 5000, stdio: ['ignore', 'pipe', 'ignore'], windowsHide: true,
208
+ });
209
+ const raw = decodeWindowsOutput(ps.stdout).trim();
210
+ if (raw) {
211
+ const processInfo = JSON.parse(raw);
212
+ const memory = Number(processInfo.WorkingSetSize);
213
+ const createdAt = processInfo.CreationDate
214
+ ? parseCimDate(processInfo.CreationDate) ?? parseDateString(processInfo.CreationDate)
215
+ : null;
216
+ return {
217
+ ...(Number.isFinite(memory) && memory > 0 ? { memory: String(Math.round(memory / 1024)) } : {}),
218
+ ...(createdAt !== null ? { uptime: formatUptime(Math.max(0, Math.floor((Date.now() - createdAt) / 1000))) } : {}),
219
+ };
220
+ }
127
221
  const result = spawnSync('wmic', ['process', 'where', `ProcessId=${pid}`, 'get', 'WorkingSetSize,CreationDate'], { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true });
128
222
  const output = result.stdout || '';
129
223
  const lines = output.trim().split('\n').filter(l => l.trim());
130
224
  if (lines.length >= 2) {
131
225
  const parts = lines[1].trim().split(/\s+/);
132
226
  const memKB = parts[1] ? Math.round(parseInt(parts[1], 10) / 1024) : undefined;
133
- return { memory: memKB ? `${memKB}` : undefined };
227
+ const createdAt = parts[0] ? parseCimDate(parts[0]) ?? parseDateString(parts[0]) : null;
228
+ return {
229
+ ...(memKB ? { memory: `${memKB}` } : {}),
230
+ ...(createdAt !== null ? { uptime: formatUptime(Math.max(0, Math.floor((Date.now() - createdAt) / 1000))) } : {}),
231
+ };
134
232
  }
135
233
  }
136
234
  else {
@@ -167,6 +265,37 @@ function formatUptime(totalSeconds) {
167
265
  parts.push(`${seconds}s`);
168
266
  return parts.join(' ');
169
267
  }
268
+ function parseDateString(value) {
269
+ const microsoftJsonDate = value.match(/^\\?\/Date\(([-+]?\d+)\)\\?\/$/);
270
+ if (microsoftJsonDate)
271
+ return Number(microsoftJsonDate[1]);
272
+ const parsed = Date.parse(value);
273
+ return Number.isNaN(parsed) ? null : parsed;
274
+ }
275
+ /** Decode PowerShell output consistently across Windows 5.1 and pwsh. */
276
+ function decodeWindowsOutput(value) {
277
+ if (!value)
278
+ return '';
279
+ const bytes = Buffer.isBuffer(value) ? value : Buffer.from(value);
280
+ if (bytes.length >= 2 && bytes[0] === 0xff && bytes[1] === 0xfe) {
281
+ return bytes.subarray(2).toString('utf16le');
282
+ }
283
+ if (bytes.length >= 2 && bytes[0] === 0xfe && bytes[1] === 0xff) {
284
+ const swapped = Buffer.allocUnsafe(bytes.length - 2);
285
+ for (let i = 2; i + 1 < bytes.length; i += 2) {
286
+ swapped[i - 2] = bytes[i + 1];
287
+ swapped[i - 1] = bytes[i];
288
+ }
289
+ return swapped.toString('utf16le');
290
+ }
291
+ const utf8 = bytes.toString('utf8').replace(/^\uFEFF/, '');
292
+ if (utf8.includes('\u0000')) {
293
+ const utf16 = bytes.toString('utf16le').replace(/^\uFEFF/, '');
294
+ if (utf16.includes('{') || utf16.includes('[') || utf16.includes('CommandLine'))
295
+ return utf16;
296
+ }
297
+ return utf8;
298
+ }
170
299
  /**
171
300
  * Cross-platform command existence check.
172
301
  */
@@ -178,7 +307,7 @@ export function commandExists(cmd) {
178
307
  let exists = false;
179
308
  try {
180
309
  if (isWindows) {
181
- const r = spawnSync('where', [cmd], { encoding: 'utf-8', stdio: 'pipe', windowsHide: true });
310
+ const r = spawnSync('where.exe', [cmd], { encoding: 'utf-8', stdio: 'pipe', windowsHide: true });
182
311
  exists = r.status === 0;
183
312
  }
184
313
  else {
@@ -194,7 +323,7 @@ export function commandExists(cmd) {
194
323
  }
195
324
  /**
196
325
  * 解析命令的真实可执行文件绝对路径。
197
- * Windows: `where` 会列出全部同名文件(npm 全局 bin 同时生成无后缀 sh 包装、.cmd、.ps1),
326
+ * Windows: `where.exe` 会列出全部同名文件(npm 全局 bin 同时生成无后缀 sh 包装、.cmd、.ps1),
198
327
  * 其中无后缀的那个是 Unix sh 脚本,Windows 无法直接 spawn(ENOENT)。
199
328
  * 因此优先选 PATHEXT 可执行后缀(.cmd/.exe/.bat/.com),都没有才退回首行。
200
329
  * 失败返回 null。不缓存——刚安装的命令需要重新探测。
@@ -202,7 +331,7 @@ export function commandExists(cmd) {
202
331
  export function resolveCommandPath(cmd) {
203
332
  try {
204
333
  if (isWindows) {
205
- const r = spawnSync('where', [cmd], { encoding: 'utf-8', stdio: 'pipe', windowsHide: true });
334
+ const r = spawnSync('where.exe', [cmd], { encoding: 'utf-8', stdio: 'pipe', windowsHide: true });
206
335
  if (r.status !== 0 || !r.stdout)
207
336
  return null;
208
337
  const candidates = r.stdout.split(/\r?\n/).map(s => s.trim()).filter(Boolean);
@@ -350,12 +350,20 @@ export function findOrphanProcesses() {
350
350
  // 1. 已登记 PID(自己 HOME 下的 main + 自己进程)
351
351
  const known = new Set([process.pid]);
352
352
  const status = scanInstances();
353
- for (const m of status.mains)
354
- known.add(m.record.pid);
355
- for (const m of status.restartMonitors)
356
- known.add(m.record.pid);
353
+ for (const m of status.mains) {
354
+ if (m.alive)
355
+ known.add(m.record.pid);
356
+ }
357
+ for (const m of status.restartMonitors) {
358
+ if (m.alive)
359
+ known.add(m.record.pid);
360
+ }
357
361
  // 2. 系统中所有跑 dist/index.js 的 node 进程
358
- const candidates = findProcesses('node.*dist/index.js');
362
+ // Use a stable filename anchor for the Windows CIM query. The full path
363
+ // regex contains escaped separators and is applied after command lines have
364
+ // been fetched; embedding it in the CIM pre-filter can silently miss a
365
+ // backslash-delimited `dist\\index.js` command on some PowerShell builds.
366
+ const candidates = findProcesses('index\\.js');
359
367
  const orphans = [];
360
368
  for (const pid of candidates) {
361
369
  if (known.has(pid))
@@ -395,11 +403,21 @@ export function killOrphans(orphans) {
395
403
  }
396
404
  function readCmdline(pid) {
397
405
  if (isWindows) {
406
+ // WMIC is removed from recent Windows installations. Keep it as the
407
+ // first probe for older hosts, then use the supported CIM API when it is
408
+ // unavailable or returns no row.
398
409
  try {
399
410
  const result = spawnSync('wmic', ['process', 'where', `ProcessId=${pid}`, 'get', 'CommandLine', '/value'], { encoding: 'utf-8', timeout: 3000, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true });
400
411
  const out = result.stdout || '';
401
412
  const m = out.match(/CommandLine=([^\r\n]+)/);
402
- return m ? m[1].trim() : '';
413
+ if (m?.[1]?.trim())
414
+ return m[1].trim();
415
+ }
416
+ catch { }
417
+ try {
418
+ const script = `(Get-CimInstance Win32_Process -Filter 'ProcessId=${pid}').CommandLine`;
419
+ const result = spawnSync('powershell', ['-NoProfile', '-Command', script], { encoding: null, timeout: 5000, stdio: ['ignore', 'pipe', 'ignore'], windowsHide: true });
420
+ return decodeWindowsOutput(result.stdout).trim();
403
421
  }
404
422
  catch {
405
423
  return '';
@@ -422,6 +440,25 @@ function readCmdline(pid) {
422
440
  }
423
441
  }
424
442
  }
443
+ function decodeWindowsOutput(value) {
444
+ if (!value)
445
+ return '';
446
+ const bytes = Buffer.isBuffer(value) ? value : Buffer.from(value);
447
+ if (bytes.length >= 2 && bytes[0] === 0xff && bytes[1] === 0xfe)
448
+ return bytes.subarray(2).toString('utf16le');
449
+ if (bytes.length >= 2 && bytes[0] === 0xfe && bytes[1] === 0xff) {
450
+ const swapped = Buffer.allocUnsafe(bytes.length - 2);
451
+ for (let i = 2; i + 1 < bytes.length; i += 2) {
452
+ swapped[i - 2] = bytes[i + 1];
453
+ swapped[i - 1] = bytes[i];
454
+ }
455
+ return swapped.toString('utf16le');
456
+ }
457
+ const utf8 = bytes.toString('utf8').replace(/^\uFEFF/, '');
458
+ if (utf8.includes('\u0000'))
459
+ return bytes.toString('utf16le').replace(/^\uFEFF/, '');
460
+ return utf8;
461
+ }
425
462
  function readProcessEnvironment(pid) {
426
463
  // Linux: /proc/<pid>/environ
427
464
  if (!isWindows && process.platform !== 'darwin') {
@@ -115,12 +115,12 @@ function winPowerShellCreationDate(pid) {
115
115
  const result = spawnSync('powershell', [
116
116
  '-NoProfile',
117
117
  '-Command',
118
- `(Get-CimInstance Win32_Process -Filter 'ProcessId=${pid}').CreationDate`,
118
+ `(Get-CimInstance Win32_Process -Filter 'ProcessId=${pid}').CreationDate.ToUniversalTime().ToString('o')`,
119
119
  ], { encoding: 'utf-8', timeout: 8000, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true });
120
120
  const out = result.stdout?.trim();
121
121
  if (!out)
122
122
  return null;
123
- return parseCimDate(out);
123
+ return parseCimDate(out) ?? parseDateString(out);
124
124
  }
125
125
  function winWmicCreationDate(pid) {
126
126
  const result = spawnSync('wmic', ['process', 'where', `ProcessId=${pid}`, 'get', 'CreationDate', '/value'], { encoding: 'utf-8', timeout: 5000, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true });
@@ -128,7 +128,11 @@ function winWmicCreationDate(pid) {
128
128
  const m = out.match(/CreationDate=([^\r\n]+)/);
129
129
  if (!m)
130
130
  return null;
131
- return parseCimDate(m[1].trim());
131
+ return parseCimDate(m[1].trim()) ?? parseDateString(m[1].trim());
132
+ }
133
+ function parseDateString(value) {
134
+ const parsed = Date.parse(value);
135
+ return Number.isNaN(parsed) ? null : parsed;
132
136
  }
133
137
  /**
134
138
  * 解析 CIM/WMI 日期格式:yyyyMMddHHmmss.ffffff±TZZZ
@@ -14,8 +14,9 @@ AUN(Agent Union Network)是 agent 间安全通信的网络协议,SDK 的 n
14
14
 
15
15
  AID(Agent Identifier)是主体在 AUN 网络中的唯一身份标识,格式为 `{name}.{issuer}`(如 `alice.agentid.pub`)。任何拥有域名的组织都可以作为 Issuer 签发 AID——去中心化,无需中央权威。AID 同时也是通信地址:身份即入口。
16
16
 
17
- > 本机 evolcore 新建 AID 时的默认 issuer 是 `agentid.pub`(`src/aun/aid/control-aid.ts` 的
18
- > `resolveControlIssuer()`,可用 `EVOLCORE_ISSUER` 覆盖)。文档里出现的 `xxx.aid.pub` 是旧例子。
17
+ > 本机 evolcore 自动生成控制 AID 时的默认 AID domain 是 `agentid.cn`(`src/aun/aid/control-aid.ts` 的
18
+ > `resolveControlAidDomain()`;可用 `daemon.json.aun.defaultAidDomain` `EVOLCORE_AID_DOMAIN` 覆盖)。
19
+ > 已存在的 AID 保持原域名不变;`EVOLCORE_ISSUER` 仍作为废弃兼容别名支持。
19
20
 
20
21
  访问 `https://{aid}` 可获取该主体的个人主页。
21
22
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemas": {
3
- "daemon": { "currentVersion": 3 },
3
+ "daemon": { "currentVersion": 4 },
4
4
  "defaults": { "currentVersion": 4 },
5
5
  "agent-config": { "currentVersion": 10 },
6
6
  "relation-config": { "currentVersion": 8 },
@@ -34,6 +34,7 @@
34
34
  { "schema": "relation-config", "version": 6, "date": "2026-07-27", "description": "remove relation Session Renew effort; auxiliary inference is response-mode owned" },
35
35
  { "schema": "single-session", "version": 2, "date": "2026-07-27", "description": "add optional baseagent-aware auxiliaryModel and auxiliaryEffort without factory defaults" },
36
36
  { "schema": "daemon", "version": 3, "date": "2026-07-29", "description": "make daemon.json the exclusive source for all process debug settings" },
37
+ { "schema": "daemon", "version": 4, "date": "2026-08-04", "description": "add configurable default AID domain for generated identities" },
37
38
  { "schema": "defaults", "version": 3, "date": "2026-07-29", "description": "remove debug from the Agent configuration inheritance chain" },
38
39
  { "schema": "agent-config", "version": 8, "date": "2026-07-29", "description": "reject Agent-level debug because debug is process-owned" },
39
40
  { "schema": "agent-config", "version": 9, "date": "2026-07-29", "description": "add owner-controlled AUN group rules loading and Agent message access policy" },
@@ -0,0 +1,132 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "daemon.schema.4.json",
4
+ "title": "ProcessConfig v4 (daemon.json)",
5
+ "description": "进程级配置:daemon 自身运行配置,链外独立作用域,不进覆盖链。",
6
+ "x-logical-name": "daemon",
7
+ "x-scope": "process",
8
+ "type": "object",
9
+ "additionalProperties": false,
10
+ "properties": {
11
+ "$schema_version": { "type": "number", "const": 4, "default": 4, "x-merge": "scalar" },
12
+ "aid": { "type": "string", "description": "daemon 默认身份 AID", "x-merge": "scalar" },
13
+ "owners": {
14
+ "type": "array",
15
+ "items": { "type": "string" },
16
+ "description": "进程控制面鉴权名单(谁能远程管 daemon)",
17
+ "x-merge": "list"
18
+ },
19
+ "debug": {
20
+ "type": "object",
21
+ "description": "进程级调试配置;唯一合法来源为 daemon.json,不参与 Agent 覆盖链",
22
+ "x-merge": "dict",
23
+ "additionalProperties": false,
24
+ "properties": {
25
+ "logLevel": {
26
+ "type": "string",
27
+ "enum": ["DEBUG", "INFO", "WARN", "ERROR"],
28
+ "description": "daemon 日志级别"
29
+ },
30
+ "flusherDiag": {
31
+ "type": "boolean",
32
+ "description": "是否启用消息 flusher 诊断"
33
+ },
34
+ "aunTrace": {
35
+ "type": "boolean",
36
+ "description": "是否记录 AUN 协议 trace"
37
+ },
38
+ "aunSdkLog": {
39
+ "type": "boolean",
40
+ "description": "是否启用 AUN SDK 调试日志"
41
+ },
42
+ "upmsg": {
43
+ "type": "boolean",
44
+ "description": "是否向 Agent owner 发送 daemon 上线通知"
45
+ },
46
+ "eckSnapshots": {
47
+ "type": "boolean",
48
+ "default": false,
49
+ "description": "是否写入可能包含敏感上下文的 ECK 旁路调试快照"
50
+ }
51
+ }
52
+ },
53
+ "tunnel": {
54
+ "type": "object",
55
+ "description": "内网穿透配置",
56
+ "x-merge": "dict",
57
+ "properties": {
58
+ "targets": { "type": "array", "description": "穿透目标列表", "items": { "type": "object" } }
59
+ }
60
+ },
61
+ "aun": {
62
+ "type": "object",
63
+ "description": "AUN 进程配置",
64
+ "x-merge": "dict",
65
+ "properties": {
66
+ "encryptionSeed": { "type": ["string", "null"], "description": "已废弃兼容字段;EvolCore 固定使用内置值,检测到其他值时拒绝启动并提示联系管理人员" },
67
+ "gatewayUrl": {
68
+ "type": "string",
69
+ "description": "控制 AID 使用的显式 AUN WebSocket 网关;省略时由 SDK 缓存和 AID 发现决定"
70
+ },
71
+ "defaultAidDomain": {
72
+ "type": "string",
73
+ "pattern": "^[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?(?:\\.[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?)+$",
74
+ "description": "自动生成控制 AID 与 benchmark AID 使用的后缀域名;不影响已有 AID"
75
+ },
76
+ "minEvolVersion": {
77
+ "type": "string",
78
+ "pattern": "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$",
79
+ "description": "AUN Menu 允许的最低 Evol 客户端版本;省略时不限制"
80
+ },
81
+ "menuTokenRequired": {
82
+ "type": "boolean",
83
+ "default": false,
84
+ "description": "是否要求普通 AUN Menu 请求携带有效 menu_token;默认 false"
85
+ }
86
+ }
87
+ },
88
+ "serviceProxy": {
89
+ "type": "object",
90
+ "description": "AUN Service Proxy:把一个本地 HTTP/WS 服务暴露到 AUN 网络",
91
+ "x-merge": "dict",
92
+ "properties": {
93
+ "enabled": { "type": "boolean", "description": "是否启用 Service Proxy" },
94
+ "services": { "type": "array", "description": "暴露到 AUN 的本地服务列表", "items": { "type": "object" } }
95
+ }
96
+ },
97
+ "configSnapshots": {
98
+ "type": "boolean",
99
+ "default": true,
100
+ "description": "是否自动维护配置快照、启动日志和自检回落",
101
+ "x-merge": "scalar"
102
+ },
103
+ "idleMonitor": {
104
+ "type": "object",
105
+ "description": "流式输出空闲监控配置",
106
+ "x-merge": "dict",
107
+ "properties": {
108
+ "enabled": { "type": "boolean", "default": true, "description": "是否启用空闲监控" },
109
+ "timeout": { "type": "number", "default": 120, "description": "空闲超时秒数" },
110
+ "retryAttemptTimeout": { "type": "number", "description": "API 重试尝试连续无事件时的超时秒数;未设置时继承 timeout" },
111
+ "maxExecutionTime": { "type": "number", "default": 3600, "description": "单个任务总执行时限(秒),等待审批期间仍继续计时" }
112
+ }
113
+ },
114
+ "ecweb": {
115
+ "type": "object",
116
+ "description": "web 控制台开关/端口",
117
+ "x-merge": "dict",
118
+ "properties": {
119
+ "enabled": { "type": "boolean", "description": "是否启用 web 控制台" },
120
+ "port": { "type": "number", "description": "web 控制台监听端口" }
121
+ }
122
+ },
123
+ "watch": {
124
+ "type": "object",
125
+ "description": "日志监听配置",
126
+ "x-merge": "dict",
127
+ "properties": {
128
+ "logTypes": { "type": "array", "description": "要监听的日志类型", "items": { "type": "string" } }
129
+ }
130
+ }
131
+ }
132
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "evolcore",
3
- "version": "0.0.7",
3
+ "version": "0.0.8",
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",