evolcore 0.0.18 → 0.0.20

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.
Files changed (51) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +2 -0
  3. package/bin/install-codex-managed-hooks.mjs +61 -0
  4. package/dist/agents/claude-runner.js +4 -3
  5. package/dist/agents/codex-runner.js +25 -20
  6. package/dist/agents/ecagent-runner.js +3 -2
  7. package/dist/aun/aid/agentmd.js +7 -0
  8. package/dist/aun/msg/group.js +14 -3
  9. package/dist/aun/msg/p2p.js +21 -11
  10. package/dist/aun/outbox.js +144 -19
  11. package/dist/channels/aun.js +621 -211
  12. package/dist/cli/daemon-commands.js +41 -8
  13. package/dist/cli/index.js +1 -0
  14. package/dist/cli/init.js +55 -15
  15. package/dist/cli/restart-monitor.js +3 -3
  16. package/dist/config/aun-gateway-config.js +2 -0
  17. package/dist/config/config-manager.js +92 -8
  18. package/dist/config/config-operation-service.js +1 -2
  19. package/dist/config/gateway-config.js +9 -7
  20. package/dist/config/lifecycle.js +16 -5
  21. package/dist/config-store.js +13 -6
  22. package/dist/core/auth/authorization-audit.js +5 -2
  23. package/dist/core/bootstrap-messages.js +2 -2
  24. package/dist/core/bootstrap-service.js +21 -36
  25. package/dist/core/channel-loader.js +0 -2
  26. package/dist/core/data-migration.js +10 -4
  27. package/dist/core/evolagent.js +5 -4
  28. package/dist/core/message/message-bridge.js +6 -11
  29. package/dist/core/message/response-engine.js +62 -6
  30. package/dist/core/permission/ec-command-parser.js +203 -24
  31. package/dist/core/permission/sandbox-runtime.js +46 -12
  32. package/dist/core/permission/tool-policy.js +116 -47
  33. package/dist/core/relation/peer-identity.js +18 -0
  34. package/dist/eck/kit-renderer.js +17 -8
  35. package/dist/index.js +30 -19
  36. package/dist/ipc.js +6 -1
  37. package/dist/paths.js +0 -3
  38. package/dist/utils/stats.js +52 -18
  39. package/dist/utils/welcome.js +2 -2
  40. package/kits/docs/path-registry.md +1 -1
  41. package/kits/rules/01-overview.md +1 -1
  42. package/kits/rules/02-navigation.md +2 -2
  43. package/kits/rules/03-identity.md +1 -1
  44. package/kits/rules/05-venue.md +1 -1
  45. package/kits/schemas/_meta.json +7 -4
  46. package/kits/schemas/agent-config.schema.10.json +2 -1
  47. package/kits/schemas/agent-config.schema.11.json +408 -0
  48. package/kits/schemas/daemon.schema.5.json +136 -0
  49. package/kits/schemas/defaults.schema.5.json +107 -0
  50. package/package.json +2 -1
  51. package/dist/core/message/pause-controller.js +0 -53
package/dist/index.js CHANGED
@@ -490,7 +490,6 @@ async function runBindBootstrapDaemon(daemonCfg) {
490
490
  agentName: daemonCfg.aid,
491
491
  channelName: 'control',
492
492
  pureIdentity: true,
493
- gatewayUrl: daemonCfg.aun?.gatewayUrl,
494
493
  defaultEncrypt: daemonCfg.aun?.defaultEncrypt,
495
494
  aunTrace: daemonCfg.debug?.aunTrace,
496
495
  aunSdkLog: daemonCfg.debug?.aunSdkLog,
@@ -734,6 +733,7 @@ async function main() {
734
733
  console.error(`[EvolCore] 包路径: ${pkgRoot}`);
735
734
  console.error(`[EvolCore] 代码时间: ${latestMtime ? fmtTime(latestMtime) : '?'}`);
736
735
  }
736
+ console.error('[EvolCore] ✓ Version info printed');
737
737
  // 过滤飞书 SDK 的 info 日志
738
738
  const originalLog = console.log;
739
739
  const originalInfo = console.info;
@@ -751,12 +751,16 @@ async function main() {
751
751
  return;
752
752
  originalInfo(...args);
753
753
  };
754
+ console.error('[EvolCore] ✓ Console filter installed');
754
755
  logger.info(`EvolCore v${readEvolcoreVersion()} starting... (fastaun v${readFastaunVersion()})`);
756
+ console.error('[EvolCore] ✓ Logger initialized');
755
757
  // 确保数据目录存在
756
758
  ensureDataDirs();
759
+ console.error('[EvolCore] ✓ Data dirs ensured');
757
760
  // AUN keystore seed is an EvolCore application constant. A custom value can
758
761
  // make existing identities unreadable, so fail before migrations, snapshots,
759
762
  // instance registration, and service startup.
763
+ console.error('[EvolCore] ✓ Checking AUN encryption seed...');
760
764
  try {
761
765
  assertAunEncryptionSeedPolicy(loadDaemonConfig().aun?.encryptionSeed, process.env.AUN_ENCRYPTION_SEED);
762
766
  }
@@ -766,6 +770,7 @@ async function main() {
766
770
  console.error(msg);
767
771
  process.exit(1);
768
772
  }
773
+ console.error('[EvolCore] ✓ AUN encryption seed validated');
769
774
  // .env 文件已在模块顶部加载,此处不再重复加载
770
775
  // ── 单实例保护(pre-check + post-write self-check)──
771
776
  // pre-check:发现已有活 main 直接退出,避免起任何副作用
@@ -2246,8 +2251,11 @@ async function main() {
2246
2251
  // Register every IPC executor/provider before exposing the endpoint. The
2247
2252
  // function declaration is hoisted, while its invocation remains here so a
2248
2253
  // failed bind still aborts before any AUN connection is attempted.
2254
+ console.error('[EvolCore] ✓ Configuring IPC...');
2249
2255
  configureIpc();
2256
+ console.error('[EvolCore] ✓ Starting IPC server...');
2250
2257
  await ipcServer.start();
2258
+ console.error('[EvolCore] ✓ IPC server started');
2251
2259
  // ── 连接所有渠道(后台首连,AUN/任意渠道故障不阻塞 daemon 主流程)──
2252
2260
  logger.info(`🚀 EvolCore core is ready; connecting ${channelInstances.length} channel(s) in background`);
2253
2261
  const connectAllPromise = channelLoader.connectAll(channelInstances, {
@@ -2296,7 +2304,6 @@ async function main() {
2296
2304
  agentName: daemonCfg.aid,
2297
2305
  channelName: 'control',
2298
2306
  pureIdentity: true,
2299
- gatewayUrl: daemonCfg.aun?.gatewayUrl,
2300
2307
  defaultEncrypt: daemonCfg.aun?.defaultEncrypt,
2301
2308
  aunTrace: daemonCfg.debug?.aunTrace,
2302
2309
  aunSdkLog: daemonCfg.debug?.aunSdkLog,
@@ -2341,7 +2348,7 @@ async function main() {
2341
2348
  ...(response.name ? { name: response.name } : {}),
2342
2349
  };
2343
2350
  try {
2344
- await controlChannel.sendStructured(opts.channelId, timedResponse, menuResponseContext());
2351
+ await controlChannel.sendStructuredOrThrow(opts.channelId, timedResponse, menuResponseContext());
2345
2352
  logMenuRequestCompleted(request, timedResponse, menuFlowContext, { delivery: 'sent' });
2346
2353
  menuCompletionLogged = true;
2347
2354
  }
@@ -2361,7 +2368,7 @@ async function main() {
2361
2368
  // 用 sendStructured 直发 typed payload(payload.type='bind.response'),
2362
2369
  // 不能用 sendMessage——它会把内容包成 {type:'text', text:...},App 无法识别。
2363
2370
  // encrypted 跟随入站请求:bind.response 与 bind.request 的加密/明文对称。
2364
- await controlChannel.sendStructured(opts.channelId, response, controlReplyContext(opts));
2371
+ await controlChannel.sendStructuredOrThrow(opts.channelId, response, controlReplyContext(opts));
2365
2372
  }
2366
2373
  return;
2367
2374
  }
@@ -3375,21 +3382,25 @@ async function main() {
3375
3382
  }
3376
3383
  };
3377
3384
  ipcServer.setStatsProvider(() => statsCollector.getSnapshot());
3378
- ipcServer.setAgentStatsProvider(() => agentRegistry.list().map((agent) => {
3379
- const snap = statsCollector.getSnapshot(agent.aid);
3380
- return {
3381
- aid: agent.aid,
3382
- received: snap.lastHour.received,
3383
- sent: snap.lastHour.sent,
3384
- completed: snap.lastHour.completed,
3385
- errors: snap.lastHour.errors,
3386
- interrupts: snap.lastHour.interrupts,
3387
- avgResponseMs: snap.lastHour.avgResponseMs,
3388
- processing: messageQueue.getProcessingCountByAgent(agent.aid),
3389
- queued: messageQueue.getQueueLengthByAgent(agent.aid),
3390
- muted: messageQueue.isAgentMuted(agent.aid),
3391
- };
3392
- }));
3385
+ ipcServer.setAgentStatsProvider(() => {
3386
+ const agents = agentRegistry.list();
3387
+ const snapshots = statsCollector.getSnapshots(agents.map(agent => agent.aid));
3388
+ return agents.map((agent) => {
3389
+ const snap = snapshots.get(agent.aid);
3390
+ return {
3391
+ aid: agent.aid,
3392
+ received: snap.lastHour.received,
3393
+ sent: snap.lastHour.sent,
3394
+ completed: snap.lastHour.completed,
3395
+ errors: snap.lastHour.errors,
3396
+ interrupts: snap.lastHour.interrupts,
3397
+ avgResponseMs: snap.lastHour.avgResponseMs,
3398
+ processing: messageQueue.getProcessingCountByAgent(agent.aid),
3399
+ queued: messageQueue.getQueueLengthByAgent(agent.aid),
3400
+ muted: messageQueue.isAgentMuted(agent.aid),
3401
+ };
3402
+ });
3403
+ });
3393
3404
  // Queue snapshot & action (for ec queue --agent CLI)
3394
3405
  ipcServer.setQueueSnapshotProvider((params) => {
3395
3406
  const handle = agentRegistry.get(params.agent);
package/dist/ipc.js CHANGED
@@ -435,7 +435,12 @@ export class IpcServer {
435
435
  }
436
436
  }
437
437
  case 'ping':
438
- return { pong: true, pid: process.pid, protocolVersion: 1 };
438
+ return {
439
+ pong: true,
440
+ pid: process.pid,
441
+ protocolVersion: 1,
442
+ uptime: Math.round(process.uptime() * 1000),
443
+ };
439
444
  case 'shutdown': {
440
445
  if (!this.shutdownExecutor)
441
446
  return { ok: false, error: 'shutdown executor not configured' };
package/dist/paths.js CHANGED
@@ -11,9 +11,6 @@ export function resolveRoot() {
11
11
  if (process.env[RUNTIME_HOME_ENV]) {
12
12
  _root = process.env[RUNTIME_HOME_ENV];
13
13
  }
14
- else if (fs.existsSync(path.join(process.cwd(), 'agents', 'defaults.json'))) {
15
- _root = process.cwd();
16
- }
17
14
  else {
18
15
  _root = path.join(os.homedir(), DEFAULT_RUNTIME_HOME_DIRNAME);
19
16
  }
@@ -59,19 +59,11 @@ export class StatsCollector {
59
59
  recordEvent(record) {
60
60
  this.events.push(record);
61
61
  }
62
- /**
63
- * 获取统计快照。可选 agentName 过滤:未传则全局;传入则只统计该 agent。
64
- * 自动裁剪 >1h 的事件。
65
- */
66
- getSnapshot(agentName) {
67
- const now = Date.now();
62
+ trimExpiredEvents(now) {
68
63
  const cutoff = now - this.HOUR_MS;
69
- // 裁剪过期事件
70
64
  this.events = this.events.filter(e => e.timestamp >= cutoff);
71
- // 聚合统计(可按 agent 过滤)
72
- const filtered = agentName === undefined
73
- ? this.events
74
- : this.events.filter(e => (e.agentName ?? '<unknown>') === agentName);
65
+ }
66
+ buildSnapshot(events, recentErrors, now) {
75
67
  let received = 0;
76
68
  let sent = 0;
77
69
  let completed = 0;
@@ -82,7 +74,7 @@ export class StatsCollector {
82
74
  let interrupts = 0;
83
75
  let totalDuration = 0;
84
76
  let durationCount = 0;
85
- for (const event of filtered) {
77
+ for (const event of events) {
86
78
  switch (event.type) {
87
79
  case 'received':
88
80
  received++;
@@ -114,10 +106,6 @@ export class StatsCollector {
114
106
  break;
115
107
  }
116
108
  }
117
- // 最近错误:按 agent 过滤(与上面一致),取前 20 条
118
- const recentErrors = (agentName === undefined
119
- ? this.recentErrors
120
- : this.recentErrors.filter(e => (e.agentName ?? '<unknown>') === agentName)).slice(0, 20);
121
109
  return {
122
110
  uptimeMs: now - this.startTime,
123
111
  lastHour: {
@@ -129,11 +117,57 @@ export class StatsCollector {
129
117
  toolErrors,
130
118
  toolErrorsByName,
131
119
  interrupts,
132
- avgResponseMs: durationCount > 0 ? totalDuration / durationCount : 0
120
+ avgResponseMs: durationCount > 0 ? totalDuration / durationCount : 0,
133
121
  },
134
- recentErrors,
122
+ recentErrors: recentErrors.slice(0, 20),
135
123
  };
136
124
  }
125
+ /**
126
+ * 获取统计快照。可选 agentName 过滤:未传则全局;传入则只统计该 agent。
127
+ * 自动裁剪 >1h 的事件。
128
+ */
129
+ getSnapshot(agentName) {
130
+ const now = Date.now();
131
+ this.trimExpiredEvents(now);
132
+ // 聚合统计(可按 agent 过滤)
133
+ const filtered = agentName === undefined
134
+ ? this.events
135
+ : this.events.filter(e => (e.agentName ?? '<unknown>') === agentName);
136
+ // 最近错误:按 agent 过滤(与上面一致),取前 20 条
137
+ const recentErrors = (agentName === undefined
138
+ ? this.recentErrors
139
+ : this.recentErrors.filter(e => (e.agentName ?? '<unknown>') === agentName));
140
+ return this.buildSnapshot(filtered, recentErrors, now);
141
+ }
142
+ /**
143
+ * 一次扫描生成多个 Agent 的统计快照。用于高频 IPC 看板,避免对每个
144
+ * Agent 都重新过滤最近一小时的全部事件。
145
+ */
146
+ getSnapshots(agentNames) {
147
+ const now = Date.now();
148
+ this.trimExpiredEvents(now);
149
+ const buckets = new Map();
150
+ const recentErrorBuckets = new Map();
151
+ for (const agentName of new Set(agentNames)) {
152
+ buckets.set(agentName, []);
153
+ recentErrorBuckets.set(agentName, []);
154
+ }
155
+ for (const event of this.events) {
156
+ const bucket = buckets.get(event.agentName ?? '<unknown>');
157
+ if (bucket)
158
+ bucket.push(event);
159
+ }
160
+ for (const error of this.recentErrors) {
161
+ const bucket = recentErrorBuckets.get(error.agentName ?? '<unknown>');
162
+ if (bucket)
163
+ bucket.push(error);
164
+ }
165
+ const snapshots = new Map();
166
+ for (const [agentName, events] of buckets) {
167
+ snapshots.set(agentName, this.buildSnapshot(events, recentErrorBuckets.get(agentName) ?? [], now));
168
+ }
169
+ return snapshots;
170
+ }
137
171
  }
138
172
  export class AidStatsCollector {
139
173
  entries = new Map();
@@ -10,7 +10,7 @@
10
10
  import fs from 'fs';
11
11
  import { channelStatePath } from '../paths.js';
12
12
  import { loadAgent, saveAgent } from '../config-store.js';
13
- import { withLifecycleForWrite } from '../config/lifecycle.js';
13
+ import { resolveAgentLifecycle, withLifecycleForWrite } from '../config/lifecycle.js';
14
14
  import { logger } from './logger.js';
15
15
  // ============================================================================
16
16
  // 欢迎消息生成
@@ -166,7 +166,7 @@ export class FirstInteractionWelcomeManager {
166
166
  // 懒加载并缓存 initialized 状态(避免每条消息都读取磁盘)
167
167
  if (this.initializedCache === null) {
168
168
  const agentConfig = loadAgent(this.agentAid);
169
- this.initializedCache = agentConfig?.lifecycle === 'active';
169
+ this.initializedCache = !!agentConfig && resolveAgentLifecycle(agentConfig) === 'active';
170
170
  }
171
171
  // Agent 已初始化 → 所有用户都不需要欢迎消息
172
172
  if (this.initializedCache) {
@@ -7,7 +7,7 @@
7
7
 
8
8
  | 名称 | 含义 | 来源 |
9
9
  |------|------|------|
10
- | `$EVOLCORE_HOME` | evolcore 用户数据根 | `resolveRoot()`:环境变量 `EVOLCORE_HOME` → cwd 下有 `agents/defaults.json` 则取 cwd → `~/.evolcore` |
10
+ | `$EVOLCORE_HOME` | evolcore 用户数据根 | `resolveRoot()`:环境变量 `EVOLCORE_HOME` → `~/.evolcore` |
11
11
  | `$PACKAGE_ROOT` | evolcore 包根目录 | `getPackageRoot()`,由 `import.meta` 推出(不是 `require.resolve`) |
12
12
  | `$CURRENT_PROJECT` | 当前工作目录 | 会话的 projectPath |
13
13
 
@@ -140,7 +140,7 @@ evolcore 收到每条消息时,由**声明式 manifest** 决定加载哪些上
140
140
  | group(群聊) | rules + 身份层(**无 preferences**)+ 关系层(群)+ 环境层 + 渠道层 + 会话层 + baseagent |
141
141
  | bootstrapping | 仅 bootstrap 引导(不加载 rules、身份、关系、环境、渠道、会话、baseagent 或完整 commands 段) |
142
142
 
143
- > 常规段(包括 rules、session、baseagent)都要求 `lifecycle=active`。生命周期缺失或非法时,
143
+ > 常规段(包括 rules、session、baseagent)都要求 `lifecycle=active`。生命周期缺失按 `active` 处理;非法时,
144
144
  > Manifest 不加载任何常规段;agent-owned turn 也不会直接落入普通 runner。
145
145
 
146
146
  三份 manifest 各管一段:`kits/eck_manifest.json`(system prompt 默认)、
@@ -6,7 +6,7 @@
6
6
 
7
7
  | 路径 | 含义 |
8
8
  |------|------|
9
- | `$EVOLCORE_HOME` | 用户数据根。解析顺序:`EVOLCORE_HOME` 环境变量 → cwd 下有 `agents/defaults.json` 则取 cwd → `~/.evolcore`(第二步意味着**包根和数据根可能是同一个目录**) |
9
+ | `$EVOLCORE_HOME` | 用户数据根。解析顺序:`EVOLCORE_HOME` 环境变量 → `~/.evolcore` |
10
10
  | `$PACKAGE_ROOT` | evolcore 包根目录(由 `getPackageRoot()` 从 `import.meta` 推出) |
11
11
  | `$CURRENT_PROJECT` | 当前工作目录 |
12
12
 
@@ -82,7 +82,7 @@ agent 级索引范围:`$CURRENT_PROJECT` + `$AGENT_DIR`。
82
82
  ## Bootstrap(独立使用 ECK 时)
83
83
 
84
84
  无 evolcore 动态注入时,路径确定顺序:
85
- 1. `$EVOLCORE_HOME`:环境变量 → cwd 下有 `agents/defaults.json` 则取 cwd → `~/.evolcore`
85
+ 1. `$EVOLCORE_HOME`:环境变量 → `~/.evolcore`
86
86
  2. `$PACKAGE_ROOT`:evolcore 安装目录(dev 模式下可能与上一步同一个目录)
87
87
  3. 按上面的派生规则构造其余路径
88
88
 
@@ -29,7 +29,7 @@
29
29
 
30
30
  ## 人格与行为规范怎么生效
31
31
 
32
- - **注入条件**是 `chatType ≠ null` 且 `lifecycle = active`(即明确处于正常运行阶段的渠道会话),不是"有没有注入 AID"。生命周期变量缺失时失败关闭,不注入身份层;本地 coding 模式也不注入。
32
+ - **注入条件**是 `chatType ≠ null` 且 `lifecycle = active`(即处于正常运行阶段的渠道会话),不是"有没有注入 AID"。生命周期变量缺失时按 `active` 处理;非法生命周期仍失败关闭。本地 coding 模式也不注入。
33
33
  - persona.md 由 evolcore **自动前置**进 system prompt,你不需要主动 Read。
34
34
  - persona.md 缺失时**没有默认人格兜底**,只是这一段不出现;行为约束改由 `kits/rules/` + `roles/` 权限定义承担。
35
35
  - 改完 persona.md 后 `ec agent reload` 生效(mtime 门控缓存)。
@@ -21,7 +21,7 @@
21
21
  | group | `chatType = group` 且 `lifecycle = active` | 同 private,但**无 preferences**;`groupId` 有值加群 profile,`groupRulesPath` 有值加群规则 | 自主模式,`mentionMode` 决定是否响应 |
22
22
  | bootstrapping | `lifecycle = bootstrapping` | 仅 bootstrap 引导(所有常规段均落选) | 初始化引导 |
23
23
 
24
- > coding 场景在 agent 明确 `active` 时才加载 `session` 与 `baseagent`;生命周期缺失或非法时按 fail-closed 处理。
24
+ > coding 场景在 agent `active` 时加载 `session` 与 `baseagent`;生命周期缺失按 `active` 处理,非法时按 fail-closed 处理。
25
25
 
26
26
  ## 数据位置
27
27
 
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemas": {
3
- "daemon": { "currentVersion": 4 },
4
- "defaults": { "currentVersion": 4 },
5
- "agent-config": { "currentVersion": 10 },
3
+ "daemon": { "currentVersion": 5 },
4
+ "defaults": { "currentVersion": 5 },
5
+ "agent-config": { "currentVersion": 11 },
6
6
  "relation-config": { "currentVersion": 8 },
7
7
  "contact-book": { "currentVersion": 3 },
8
8
  "single-session": { "currentVersion": 2 },
@@ -42,6 +42,9 @@
42
42
  { "schema": "contact-book", "version": 3, "date": "2026-07-29", "description": "add versioned contact requests and declined status" },
43
43
  { "schema": "defaults", "version": 4, "date": "2026-08-02", "description": "add defaults-only fallback model chain" },
44
44
  { "schema": "agent-config", "version": 10, "date": "2026-08-02", "description": "reject Agent-level fallback model chain" },
45
- { "schema": "relation-config", "version": 8, "date": "2026-08-02", "description": "reject relation-level fallback model chain" }
45
+ { "schema": "relation-config", "version": 8, "date": "2026-08-02", "description": "reject relation-level fallback model chain" },
46
+ { "schema": "daemon", "version": 5, "date": "2026-08-27", "description": "remove EvolCore AUN gateway override" },
47
+ { "schema": "defaults", "version": 5, "date": "2026-08-27", "description": "remove EvolCore AUN gateway override" },
48
+ { "schema": "agent-config", "version": 11, "date": "2026-08-27", "description": "remove EvolCore AUN gateway override" }
46
49
  ]
47
50
  }
@@ -61,13 +61,14 @@
61
61
  },
62
62
  "lifecycle": {
63
63
  "type": "string",
64
+ "default": "active",
64
65
  "enum": [
65
66
  "created",
66
67
  "bootstrapping",
67
68
  "active"
68
69
  ],
69
70
  "x-merge": "scalar",
70
- "description": "agent 生命周期状态",
71
+ "description": "agent 生命周期状态;缺失时按 active 处理",
71
72
  "x-enumDescriptions": {
72
73
  "created": "已创建,尚未进入引导流程",
73
74
  "bootstrapping": "引导中(初始化配置/身份)",