evolcore 0.0.22 → 0.0.23

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 (75) hide show
  1. package/AGENTS.md +62 -0
  2. package/CHANGELOG.md +24 -14
  3. package/README.md +2 -0
  4. package/bin/codex-managed-acl.ps1 +155 -0
  5. package/bin/install-codex-managed-hooks.mjs +373 -95
  6. package/dist/agents/baseagent-availability.js +48 -0
  7. package/dist/agents/baseagent.js +1 -1
  8. package/dist/agents/claude-runner.js +30 -226
  9. package/dist/agents/{codex-app-server-client.js → codex/app-server-client.js} +73 -13
  10. package/dist/{utils/codex-app-server-registry.js → agents/codex/app-server-registry.js} +2 -2
  11. package/dist/agents/codex/catalog.js +70 -0
  12. package/dist/agents/codex/diagnostics.js +154 -0
  13. package/dist/agents/codex-runner.js +407 -139
  14. package/dist/agents/ecagent-runner.js +10 -31
  15. package/dist/agents/gemini-runner.js +2 -6
  16. package/dist/aun/aid/store.js +2 -0
  17. package/dist/aun/menu-client.js +272 -0
  18. package/dist/aun/msg/group.js +65 -4
  19. package/dist/aun/msg/index.js +1 -1
  20. package/dist/aun/msg/managed-operation.js +51 -4
  21. package/dist/aun/rpc/client.js +8 -1
  22. package/dist/channels/aun.js +31 -1
  23. package/dist/channels/wechat.js +81 -10
  24. package/dist/cli/aun-commands.js +48 -4
  25. package/dist/cli/command-log.js +21 -2
  26. package/dist/cli/daemon-commands.js +142 -45
  27. package/dist/cli/index.js +20 -0
  28. package/dist/cli/init.js +2 -10
  29. package/dist/cli/menu-client.js +95 -0
  30. package/dist/cli/model.js +23 -8
  31. package/dist/cli/task-context.js +12 -2
  32. package/dist/cli/trigger-command.js +9 -1
  33. package/dist/config/schema-migration.js +14 -2
  34. package/dist/core/auth/agent-delegation.js +10 -7
  35. package/dist/core/auth/authorization-audit.js +4 -0
  36. package/dist/core/auth/operation-catalog.js +4 -0
  37. package/dist/core/auth/remote-access-store.js +135 -0
  38. package/dist/core/command/command-handler.js +41 -5
  39. package/dist/core/command/daemon-diagnostics.js +448 -0
  40. package/dist/core/command/menu-catalog.js +3 -0
  41. package/dist/core/command/menu-handler.js +141 -33
  42. package/dist/core/command/menu-protocol.js +119 -0
  43. package/dist/core/command/slash-gate.js +3 -3
  44. package/dist/core/command/slash-handler.js +42 -22
  45. package/dist/core/message/message-queue.js +20 -15
  46. package/dist/core/message/response-engine.js +74 -73
  47. package/dist/core/model/catalog-service.js +308 -0
  48. package/dist/core/model/model-catalog.js +124 -334
  49. package/dist/core/model/model-diagnostics.js +4 -5
  50. package/dist/core/model/model-fallback.js +9 -16
  51. package/dist/core/model/model-permission.js +1 -1
  52. package/dist/core/permission/approval-gateway.js +16 -1
  53. package/dist/core/permission/protected-paths.js +63 -4
  54. package/dist/core/permission/sandbox-runtime.js +4 -2
  55. package/dist/core/permission/tool-policy.js +244 -25
  56. package/dist/core/runtime-lock.js +13 -8
  57. package/dist/index.js +40 -29
  58. package/dist/ipc.js +123 -81
  59. package/dist/trigger/manager.js +3 -1
  60. package/dist/trigger/parser.js +77 -13
  61. package/dist/trigger/patch.js +104 -1
  62. package/dist/utils/ecweb-supervisor.js +11 -2
  63. package/dist/utils/ecweb-utils.js +8 -26
  64. package/dist/utils/error-utils.js +7 -0
  65. package/dist/utils/npm-ops.js +47 -15
  66. package/kits/docs/evolcore/INDEX.md +1 -0
  67. package/kits/docs/evolcore/agent-create.md +13 -0
  68. package/kits/docs/evolcore/group-collaboration.md +7 -2
  69. package/kits/docs/evolcore/menu-client.md +34 -0
  70. package/kits/migrations/migrate-contact-book-v2.mjs +9 -1
  71. package/kits/migrations/migrate-role-config-v4.mjs +11 -5
  72. package/kits/migrations/migrate-role-config-v5.mjs +8 -2
  73. package/kits/templates/roles/visitor.json +1 -0
  74. package/kits/templates/system-fragments/bootstrap.md +8 -1
  75. package/package.json +11 -3
package/AGENTS.md ADDED
@@ -0,0 +1,62 @@
1
+ # AGENTS.md
2
+
3
+ EvolCore 仓库的通用 AI agent 指引。与 CLAUDE.md 并列,供 Codex、Gemini CLI 等非 Claude base agent 使用。内容保持一致,修改时两边同步。
4
+
5
+ ## 这是什么
6
+
7
+ EvolCore(npm 包 `evolcore`,CLI `ec`)运行在 base agent(Claude Code / Codex / Gemini)之上,为其接入 AUN 网络与各 IM 渠道,并提供身份、关系、环境感知与持久记忆。仓库内含两个子包:`ecweb/`(`ec-web`,Web 控制台)、`ecagent/`(agent harness)。
8
+
9
+ **运行时行为去哪查**(先查 ECK,别凭记忆答):
10
+
11
+ | 需要什么 | 去哪 |
12
+ |---|---|
13
+ | `ec` 全部命令集(含触发词) | `kits/docs/evolcore/INDEX.md` |
14
+ | 上下文组装 / manifest / 运行时变量 | `kits/docs/context-assembly.md` |
15
+ | 身份、关系、环境、渠道、路径注册表 | `kits/rules/`(每会话全量加载)+ `kits/docs/INDEX.md` |
16
+
17
+ ## 开发命令
18
+
19
+ | 目的 | 命令 |
20
+ |---|---|
21
+ | 热重载开发 | `npm run dev` |
22
+ | 构建(含 ecweb 子包) | `npm run build` |
23
+ | 全量测试(会先 build) | `npm test` |
24
+ | 单文件测试(迭代时用这个) | `npx vitest run tests/unit/<name>.test.ts` |
25
+ | 监听模式 | `npm run test:watch` |
26
+
27
+ 改了 `src/` 必须 `npm run build` + `ec restart` 才生效。`ec agent reload` 只重载配置/persona/memory,**不重载源码**。
28
+
29
+ ## 本机运行形态(重要)
30
+
31
+ `resolveRoot()`(`src/paths.ts`)解析顺序:`EVOLCORE_HOME` → cwd 下存在 `agents/defaults.json` 则取 cwd → `~/.evolcore`。
32
+
33
+ 本机 `/home/evolcore` 既是包根也是运行时数据根(dev 模式),所以仓库里的 `data/`、`agents/`、`logs/`、`backups/`、`eck/` 是**线上真实数据**:不要清空或批量重写,提交前确认 diff 里没有混进会话文件。测试已自动隔离到临时 `EVOLCORE_HOME`(`tests/global-setup.ts` + `tests/setup.ts`),新测试沿用该机制,不要自己指向真实 root。
34
+
35
+ ## 硬约束
36
+
37
+ - **ESM**:`"type": "module"`,所有相对 import 必须带 `.js` 后缀(即使源文件是 `.ts`)。
38
+ - **命名边界**:产品名 / CLI 名 / 数据目录名 / 环境变量一律从 `src/product.ts` 取常量(`MAIN_CLI_BIN`、`RUNTIME_HOME_ENV`、`DAEMON_CONFIG_FILENAME` …)。仓库里仍有 evolclaw 时代的残留字符串,新代码不要跟着写死,也不要顺手做全局改名。
39
+ - **跨平台**:进程与路径能力走 `src/utils/cross-platform.ts`(`isProcessRunning` / `killProcess` / `findProcesses` / `commandExists` / `tailFile` / `onShutdown` / `isMainScript`);路径一律 `path.join`;入口判断用 `isMainScript(import.meta.url)`,不要拼 `file://${process.argv[1]}`。
40
+ - **执行外部命令**:用 `execFile` 系列,不要用 `execSync` 拼字符串(安全 hook 会拦)。
41
+ - **别改死代码**:`src/core/message/_archived/` 是留档,改了不生效。响应主流程在 `src/core/message/response-engine.ts`;`message-processor.ts` 只是它的类型门面(27 行)。
42
+ - **SDK 会话文件**:`{projectPath}/.claude/` 下的 JSONL 由 SDK 管理,只读不写;续接会话走 resume/sessionId。
43
+ - **代码风格**:`docs/DEV_GUIDELINES.md`(2 空格、单引号、分号、文件名 kebab-case)。
44
+
45
+ ## docs/ 的性质
46
+
47
+ `docs/` 有 300+ 个文件,绝大多数是历史设计稿和阶段性报告,**相当一部分已与源码不符**。查实现以源码为准,docs 只当线索;引用某个结论前先核对当前代码。
48
+
49
+ ### 功能设计文档命名规范
50
+
51
+ 功能设计/方案文档必须在**文档头部**标注以下信息:
52
+
53
+ ```
54
+ > 状态:[draft] | [wip] | [done]
55
+ > 创建:YYYY-MM-DD
56
+ ```
57
+
58
+ - `[draft]` — 规划了但尚未开始开发
59
+ - `[wip]` — 部分阶段完成,还有后续阶段未实施
60
+ - `[done]` — 已全部落地(含主动取消的范围,需在正文中注明)
61
+
62
+ 判断依据:文档状态必须与 `src/`、`ecweb/src/` 中的实际实现一致。引用文档结论前先核源码。
package/CHANGELOG.md CHANGED
@@ -3,7 +3,30 @@
3
3
  本文件记录 EvolCore 的重要变更。EvolClaw 版本线的历史记录已归档至
4
4
  [`docs/_archive/CHANGELOG-evolclaw.md`](docs/_archive/CHANGELOG-evolclaw.md)。
5
5
 
6
- ## 0.0.22 (2026-09-05)
6
+ ## 0.0.23 (2026-09-08)
7
+
8
+ ### 会话、Trigger 与 Codex 运行时
9
+
10
+ - 完善 Codex 子代理的上下文继承、权限传递和任务生命周期收敛,并贯通工具调用标识与授权审计。
11
+ - 为受信任的 root Fullaccess Claude 会话显式设置沙箱标记,并限制复杂 PowerShell carrier 的摘要解包范围。
12
+ - 确保 daemon Trigger 在错误已经渲染后仍发送明确终态,并传播中断生命周期元数据、统一中断结果分类。
13
+ - 完善话题续接、会话后端身份校验和跨客户端线程释放,降低重启、续接与并发操作造成的旧任务串入风险。
14
+
15
+ ### Windows、AUN 与配置安全
16
+
17
+ - 统一 Windows IPC 端点路径规范和跨进程命名管道连接,修复实例 socket 路径在不同运行入口间不一致的问题。
18
+ - 修复 Windows 配置与联系人数据的锁竞争,支持安全识别并回收损坏或遗留锁文件。
19
+ - 强化 Windows Shell 签名信任校验,在允许受信任命令执行的同时收紧受管命令边界。
20
+ - 增加受保护的 AUN Menu 客户端和 daemon 诊断入口,补充 E2EE 请求校验、EC Web token 授权与日志查询边界。
21
+ - 校验并恢复 WeChat 增量同步游标,遇到无效游标时隔离本地状态并自动重试。
22
+ - 升级 `@agentunion/fastaun` 至 `0.5.13`;`ec group invite` 改用定向邀请生命周期,并新增邀请类型与接受/拒绝/撤回命令。
23
+
24
+ ### EC Web 与监控
25
+
26
+ - 完善 EC Web 认证恢复、Trigger 管理和操作授权审计上下文。
27
+ - EC Web Monitor 按客户端订阅生命周期启停进程树采样,避免无订阅时持续采集。
28
+
29
+ ## 0.0.22 (2026-09-04)
7
30
 
8
31
  ### 话题续接与触发任务
9
32
 
@@ -32,19 +55,6 @@
32
55
  - 修复 Windows Codex managed hook 的动态 IPC 校验与安装配置,统一 proactive hook 可用性检查并保持 H-class/L-class 保护边界。
33
56
  - 修正 Codex Windows 文件系统 glob 规则,改善受管临时目录和锁目录的跨平台匹配。
34
57
  - 统一 BaseAgent 请求地址和身份请求头传递,完善 Codex 会话启动、重连与错误诊断。
35
- - 完善 Codex 子代理的上下文继承、权限传递和任务生命周期收敛,并贯通工具调用标识与授权审计。
36
- - 为受信任的 root Fullaccess Claude 会话显式设置沙箱标记,并限制复杂 PowerShell carrier 的摘要解包范围。
37
-
38
- ### Windows IPC 与运行稳定性
39
-
40
- - 统一 Windows IPC 端点路径规范和跨进程命名管道连接,修复实例 socket 路径在不同运行入口间不一致的问题。
41
- - 修复 Windows 配置与联系人数据的锁竞争,支持安全识别并回收损坏或遗留锁文件。
42
- - 强化 Windows Shell 签名信任校验,在允许受信任命令执行的同时收紧受管命令边界。
43
-
44
- ### Trigger 与监控收敛
45
-
46
- - 确保 daemon Trigger 在错误已经渲染后仍发送明确终态,并传播中断生命周期元数据、统一中断结果分类。
47
- - EC Web Monitor 按订阅生命周期启停进程树采样,避免无订阅时持续采集。
48
58
 
49
59
  ## 0.0.21 (2026-09-03)
50
60
 
package/README.md CHANGED
@@ -105,6 +105,8 @@ npm install -g evolcore
105
105
 
106
106
  Linux 全局安装会在 `postinstall` 阶段准备 Codex 受管运行所需的真实目录 `/etc/codex`。如果当前 npm 全局目录属于普通用户且该系统目录尚不存在,请先执行 `sudo install -d -m 0755 /etc/codex`,再重新安装。
107
107
 
108
+ Windows 的 npm 安装和升级不会修改机器级 Codex 配置。首次使用 Codex 托管 Hook 需运行上面的 PowerShell 安装器,并批准 Hook 部署步骤的管理员授权;部署完成后,只要 npm 包位置和 Node.js 路径不变,普通 npm 升级无需再次部署。更换 npm prefix 或 Node.js 路径后需重新部署,详见 [Windows Codex 托管 Hook](docs/evolcore-install-script.md#windows-codex-托管-hook)。
109
+
108
110
  > **Windows 用户**:首次运行前可能需要执行 `Set-ExecutionPolicy RemoteSigned -Scope CurrentUser`
109
111
 
110
112
  **从源码安装**:
@@ -0,0 +1,155 @@
1
+ param([Parameter(Mandatory = $true)][string]$Request)
2
+
3
+ # Called by the Node installer. Paths and security descriptors are data, never
4
+ # interpolated into PowerShell source. Use Windows PowerShell's built-in .NET ACL API.
5
+ $ErrorActionPreference = 'Stop'
6
+ # A parent pwsh session can export its incompatible PowerShell 7 modules.
7
+ # This helper always runs in Windows PowerShell 5.1.
8
+ $env:PSModulePath = Join-Path $PSHOME 'Modules'
9
+ [Console]::OutputEncoding = New-Object System.Text.UTF8Encoding($false)
10
+
11
+ function Get-Descriptor([string]$Target) {
12
+ return (Get-Acl -LiteralPath $Target).GetSecurityDescriptorSddlForm(
13
+ [Security.AccessControl.AccessControlSections]'Access,Owner,Group')
14
+ }
15
+
16
+ function Set-Descriptor([string]$Target, [string]$Sddl) {
17
+ $acl = Get-Acl -LiteralPath $Target
18
+ $acl.SetSecurityDescriptorSddlForm($Sddl, [Security.AccessControl.AccessControlSections]'Access,Owner,Group')
19
+ Set-Acl -LiteralPath $Target -AclObject $acl
20
+ }
21
+
22
+ function Add-Grant($Acl, [string]$Sid, [Security.AccessControl.FileSystemRights]$Rights, [bool]$Directory) {
23
+ $inheritance = if ($Directory) { [Security.AccessControl.InheritanceFlags]'ContainerInherit,ObjectInherit' } else { [Security.AccessControl.InheritanceFlags]::None }
24
+ $rule = New-Object Security.AccessControl.FileSystemAccessRule(
25
+ (New-Object Security.Principal.SecurityIdentifier($Sid)), $Rights, $inheritance,
26
+ [Security.AccessControl.PropagationFlags]::None, [Security.AccessControl.AccessControlType]::Allow)
27
+ $Acl.AddAccessRule($rule)
28
+ }
29
+
30
+ function Initialize-AccessProbe {
31
+ # An elevated process reading the file is not evidence that a normal process
32
+ # can read it. Evaluate the DACL with its UAC linked token when available.
33
+ Add-Type -TypeDefinition @'
34
+ using System;
35
+ using System.Runtime.InteropServices;
36
+ using System.Security.Principal;
37
+ public static class EvolCoreAclProbe {
38
+ [StructLayout(LayoutKind.Sequential)]
39
+ struct Mapping { public uint Read, Write, Execute, All; }
40
+ [DllImport("advapi32.dll", SetLastError=true)]
41
+ static extern bool GetTokenInformation(IntPtr token, int type, out IntPtr linked, int size, out int returned);
42
+ [DllImport("advapi32.dll", SetLastError=true)]
43
+ static extern bool DuplicateToken(IntPtr token, int level, out IntPtr duplicate);
44
+ [DllImport("advapi32.dll", SetLastError=true)]
45
+ static extern bool AccessCheck(byte[] descriptor, IntPtr token, uint desired,
46
+ ref Mapping mapping, byte[] privileges, ref uint length, out uint granted, out bool allowed);
47
+ [DllImport("kernel32.dll")] static extern bool CloseHandle(IntPtr handle);
48
+ public static string TokenKind;
49
+ public static long Granted(byte[] descriptor) {
50
+ using (var identity = WindowsIdentity.GetCurrent()) {
51
+ var principal = new WindowsPrincipal(identity);
52
+ IntPtr token = identity.Token, linked = IntPtr.Zero, duplicate = IntPtr.Zero;
53
+ try {
54
+ if (identity.IsSystem || principal.IsInRole(WindowsBuiltInRole.Administrator)) {
55
+ int size;
56
+ if (!GetTokenInformation(token, 19, out linked, IntPtr.Size, out size)) {
57
+ TokenKind = "unavailable";
58
+ return -1;
59
+ }
60
+ token = linked;
61
+ TokenKind = "linked-token";
62
+ } else { TokenKind = "current-token"; }
63
+ if (!DuplicateToken(token, 2, out duplicate))
64
+ throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
65
+ var mapping = new Mapping { Read=0x120089, Write=0x120116, Execute=0x1200a0, All=0x1f01ff };
66
+ uint length=1024, granted;
67
+ bool allowed;
68
+ if (!AccessCheck(descriptor, duplicate, 0x02000000, ref mapping,
69
+ new byte[length], ref length, out granted, out allowed))
70
+ throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
71
+ return allowed ? granted : 0;
72
+ } finally {
73
+ if (duplicate != IntPtr.Zero) CloseHandle(duplicate);
74
+ if (linked != IntPtr.Zero) CloseHandle(linked);
75
+ }
76
+ }
77
+ }
78
+ }
79
+ '@
80
+ }
81
+
82
+ function Verify-Access($Entry) {
83
+ $target = [string]$Entry.path
84
+ $acl = Get-Acl -LiteralPath $target
85
+ $read = [long][Security.AccessControl.FileSystemRights]::ReadAndExecute
86
+ $write = [long][Security.AccessControl.FileSystemRights]'Write,Delete,DeleteSubdirectoriesAndFiles,ChangePermissions,TakeOwnership'
87
+ if ($Entry.protected) {
88
+ $grants = @{}
89
+ foreach ($rule in $acl.GetAccessRules($true, $true, [Security.Principal.SecurityIdentifier])) {
90
+ if (($rule.PropagationFlags -band [Security.AccessControl.PropagationFlags]::InheritOnly) -ne 0) { continue }
91
+ $sid = $rule.IdentityReference.Value
92
+ $rights = [long]$rule.FileSystemRights
93
+ if ($sid -in @('S-1-1-0','S-1-5-11','S-1-5-32-545')) {
94
+ if ($rule.AccessControlType -eq 'Allow' -and ($rights -band $write) -ne 0) {
95
+ throw "Unsafe write permission on ${target}: $sid has $($rule.FileSystemRights). Existing policy was not removed."
96
+ }
97
+ if ($rule.AccessControlType -eq 'Deny' -and ($rights -band $read) -ne 0) {
98
+ throw "Read permission denied on ${target}: $sid. Existing policy was not removed."
99
+ }
100
+ }
101
+ if ($rule.AccessControlType -eq 'Allow') { $grants[$sid] = ([long]$grants[$sid]) -bor $rights }
102
+ }
103
+ foreach ($sid in @('S-1-5-18','S-1-5-32-544','S-1-5-32-545')) {
104
+ $required = if ($sid -eq 'S-1-5-32-545') { $read } else { [long][Security.AccessControl.FileSystemRights]::FullControl }
105
+ if ((([long]$grants[$sid]) -band $required) -ne $required) { throw "Missing required access on ${target}: $sid" }
106
+ }
107
+ }
108
+ $granted = [EvolCoreAclProbe]::Granted($acl.GetSecurityDescriptorBinaryForm())
109
+ if ($granted -ge 0) {
110
+ $required = if ($Entry.execute) { $read } else { [long][Security.AccessControl.FileSystemRights]::Read }
111
+ if (($granted -band $required) -ne $required) { throw "Normal-token read/execute access denied: $target" }
112
+ if ($Entry.protected -and ($granted -band $write) -ne 0) { throw "Normal token can modify the protected file or its ACL: $target" }
113
+ }
114
+ return @{ path = $target; userProbe = [EvolCoreAclProbe]::TokenKind }
115
+ }
116
+
117
+ try {
118
+ $payload = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($Request)) | ConvertFrom-Json
119
+ $result = switch ($payload.action) {
120
+ 'preflight' {
121
+ $principal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
122
+ if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
123
+ throw 'Machine-wide Codex hook provisioning requires an elevated Windows installer. npm installation does not require this step.'
124
+ }
125
+ @{ elevated = $true }
126
+ }
127
+ 'snapshot' { @{ sddl = (Get-Descriptor $payload.path) } }
128
+ 'prepare' {
129
+ $target = [string]$payload.path
130
+ if ($payload.reference) {
131
+ # Same-directory staging preserves the shared configuration's owner,
132
+ # inherited policy and custom administrator ACEs. Never reset its ACL.
133
+ Set-Descriptor $target (Get-Descriptor $payload.reference)
134
+ } else {
135
+ $flags = if ($payload.directory) { 'OICI' } else { '' }
136
+ Set-Descriptor $target "O:BAG:BAD:P(A;${flags};FA;;;SY)(A;${flags};FA;;;BA)(A;${flags};FRFX;;;BU)"
137
+ }
138
+ $acl = Get-Acl -LiteralPath $target
139
+ Add-Grant $acl 'S-1-5-18' 'FullControl' ([bool]$payload.directory)
140
+ Add-Grant $acl 'S-1-5-32-544' 'FullControl' ([bool]$payload.directory)
141
+ Add-Grant $acl 'S-1-5-32-545' 'ReadAndExecute' ([bool]$payload.directory)
142
+ Set-Acl -LiteralPath $target -AclObject $acl
143
+ @{ prepared = $true }
144
+ }
145
+ 'verify' {
146
+ Initialize-AccessProbe
147
+ @($payload.entries | ForEach-Object { Verify-Access $_ })
148
+ }
149
+ default { throw "Unknown ACL operation: $($payload.action)" }
150
+ }
151
+ ConvertTo-Json -InputObject $result -Depth 8 -Compress
152
+ } catch {
153
+ [Console]::Error.WriteLine("[evolcore] ACL $($payload.action) failed for $($payload.path): $($_.Exception.Message)")
154
+ exit 1
155
+ }