evolcore 0.0.11 → 0.0.12

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 (102) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/bin/codex-managed-hook.mjs +80 -0
  3. package/dist/agents/claude-runner.js +35 -2
  4. package/dist/agents/codex-app-server-client.js +120 -14
  5. package/dist/agents/codex-runner.js +273 -35
  6. package/dist/agents/ecagent-runner.js +36 -4
  7. package/dist/agents/gemini-runner.js +1 -0
  8. package/dist/aun/aid/client.js +11 -21
  9. package/dist/aun/aid/managed-operation.js +107 -0
  10. package/dist/aun/msg/group.js +81 -12
  11. package/dist/aun/msg/managed-operation.js +804 -0
  12. package/dist/aun/msg/mention-schema.js +20 -0
  13. package/dist/aun/msg/p2p.js +7 -0
  14. package/dist/channels/aun.js +288 -108
  15. package/dist/channels/daemon.js +13 -0
  16. package/dist/cli/agent-command.js +56 -8
  17. package/dist/cli/agent.js +170 -6
  18. package/dist/cli/aun-commands.js +270 -69
  19. package/dist/cli/bench.js +12 -3
  20. package/dist/cli/daemon-commands.js +31 -31
  21. package/dist/cli/fs-command.js +60 -0
  22. package/dist/cli/handoff-command.js +3 -0
  23. package/dist/cli/index.js +30 -2
  24. package/dist/cli/managed-command-guard.js +41 -0
  25. package/dist/cli/model.js +11 -4
  26. package/dist/cli/queue-command.js +11 -1
  27. package/dist/cli/response.js +71 -0
  28. package/dist/cli/restart-monitor.js +4 -18
  29. package/dist/cli/trigger-command.js +4 -0
  30. package/dist/config/builtin-roles.js +4 -0
  31. package/dist/config/contact-book-store.js +11 -3
  32. package/dist/config/contact-request-service.js +161 -15
  33. package/dist/config/mention-mode.js +8 -24
  34. package/dist/core/auth/agent-delegation.js +0 -1
  35. package/dist/core/auth/operation-authorizer.js +30 -7
  36. package/dist/core/auth/operation-catalog.js +187 -25
  37. package/dist/core/bootstrap-messages.js +18 -0
  38. package/dist/core/bootstrap-service.js +63 -4
  39. package/dist/core/capability/providers/claude-capability-provider.js +9 -31
  40. package/dist/core/capability/providers/codex-capability-provider.js +4 -15
  41. package/dist/core/capability/skill-discovery.js +55 -0
  42. package/dist/core/channel-loader.js +1 -1
  43. package/dist/core/command/cli-intent-parser.js +9 -0
  44. package/dist/core/command/command-handler.js +467 -6
  45. package/dist/core/command/connect-menu.js +15 -0
  46. package/dist/core/command/group-menu.js +4 -4
  47. package/dist/core/command/menu-catalog.js +366 -0
  48. package/dist/core/command/menu-handler.js +147 -35
  49. package/dist/core/command/menu-protocol.js +71 -0
  50. package/dist/core/command/slash-gate.js +5 -2
  51. package/dist/core/command/slash-handler.js +41 -21
  52. package/dist/core/daemon-file-cache.js +2 -1
  53. package/dist/core/data-migration.js +9 -2
  54. package/dist/core/evolagent.js +4 -2
  55. package/dist/core/handoff/dispatcher.js +5 -2
  56. package/dist/core/handoff/runtime.js +145 -21
  57. package/dist/core/handoff/store.js +24 -0
  58. package/dist/core/handoff/types.js +1 -0
  59. package/dist/core/message/logical-queue-bridge.js +1 -0
  60. package/dist/core/message/mention-schema.js +126 -0
  61. package/dist/core/message/message-bridge.js +236 -78
  62. package/dist/core/message/message-log.js +1 -0
  63. package/dist/core/message/message-queue.js +1 -0
  64. package/dist/core/message/response-engine.js +54 -36
  65. package/dist/core/permission/ec-command-parser.js +156 -10
  66. package/dist/core/permission/sandbox-runtime.js +22 -1
  67. package/dist/core/permission/tool-policy.js +73 -30
  68. package/dist/core/protected-paths.js +7 -2
  69. package/dist/core/session/session-manager.js +21 -2
  70. package/dist/eck/manifest-engine.js +39 -13
  71. package/dist/index.js +384 -98
  72. package/dist/ipc.js +218 -9
  73. package/dist/response-system/coordinator.js +6 -4
  74. package/dist/response-system/engines/v1/proactive-flow.js +26 -8
  75. package/dist/response-system/modes/single-session/index.js +14 -1
  76. package/dist/response-system/selector.js +6 -5
  77. package/dist/trigger/anomaly-store.js +4 -0
  78. package/dist/trigger/script-executor.js +1 -0
  79. package/dist/utils/codex-app-server-registry.js +90 -0
  80. package/dist/utils/codex-cli.js +5 -1
  81. package/dist/utils/cross-platform.js +15 -0
  82. package/dist/utils/npm-ops.js +5 -12
  83. package/dist/utils/tool-summary.js +11 -0
  84. package/kits/docs/channels/aun.md +1 -1
  85. package/kits/docs/context-assembly.md +2 -2
  86. package/kits/docs/evolcore/agent.md +11 -6
  87. package/kits/docs/evolcore/aid.md +14 -0
  88. package/kits/docs/prompt-loading-architecture.md +1 -2
  89. package/kits/docs/venues/group.md +1 -1
  90. package/kits/eck_manifest.json +0 -12
  91. package/kits/rules/04-relation.md +1 -1
  92. package/kits/rules/05-venue.md +2 -2
  93. package/kits/schemas/single-session.schema.1.json +3 -3
  94. package/kits/schemas/single-session.schema.2.json +3 -3
  95. package/kits/templates/roles/admin.json +22 -0
  96. package/kits/templates/roles/member.json +27 -0
  97. package/kits/templates/roles/visitor.json +33 -3
  98. package/kits/templates/system-fragments/bootstrap.md +1 -1
  99. package/kits/templates/system-fragments/channel.md +1 -1
  100. package/kits/templates/system-fragments/session.md +1 -1
  101. package/package.json +2 -2
  102. package/dist/core/command/evol-menu-version-gate.js +0 -39
@@ -6,6 +6,21 @@ import fs from 'fs';
6
6
  import { getProcessStartTime, parseCimDate } from './process-introspect.js';
7
7
  const execFileAsync = promisify(execFile);
8
8
  export const isWindows = process.platform === 'win32';
9
+ /**
10
+ * Start a detached EvolCore Node process without creating a console window on
11
+ * Windows. The child is unref'd here so callers cannot accidentally keep the
12
+ * parent process alive while a lifecycle task is running.
13
+ */
14
+ export function spawnDetachedNode(args, env = {}) {
15
+ const child = spawn(process.execPath, [...args], {
16
+ detached: true,
17
+ stdio: 'ignore',
18
+ windowsHide: isWindows,
19
+ env: { ...process.env, ...env },
20
+ });
21
+ child.unref();
22
+ return child;
23
+ }
9
24
  const ENCODE_PATH_MAX = 200;
10
25
  function encodePathHash(s) {
11
26
  let h = 0;
@@ -20,7 +20,7 @@ export async function npmInstallGlobal(pkg) {
20
20
  // Windows: run via cmd /c to avoid shell:true deprecation warning on Node 22.
21
21
  // Unix: npm directly, no shell needed.
22
22
  if (isWindows) {
23
- cmd = 'cmd';
23
+ cmd = process.env.ComSpec || path.join(process.env.SystemRoot || 'C:\\Windows', 'System32', 'cmd.exe');
24
24
  args = ['/c', 'npm', 'install', '-g', pkg];
25
25
  }
26
26
  else {
@@ -28,14 +28,14 @@ export async function npmInstallGlobal(pkg) {
28
28
  args = ['install', '-g', pkg];
29
29
  }
30
30
  try {
31
- await execFileAsync(cmd, args, { timeout: 180000 });
31
+ await execFileAsync(cmd, args, { timeout: 180000, windowsHide: isWindows });
32
32
  }
33
33
  catch (e) {
34
34
  if (e.stderr?.includes('EACCES') || e.message?.includes('EACCES')) {
35
35
  if (isWindows) {
36
36
  throw new Error('权限不足。请以管理员身份运行 PowerShell 或 CMD,然后重试');
37
37
  }
38
- await execFileAsync('sudo', ['npm', 'install', '-g', pkg], { timeout: 180000 });
38
+ await execFileAsync('sudo', ['npm', 'install', '-g', pkg], { timeout: 180000, windowsHide: false });
39
39
  }
40
40
  else {
41
41
  throw e;
@@ -103,7 +103,7 @@ export function resolveGlobalPkg(pkgName) {
103
103
  // 避免 "args 数组 + shell:true" 组合触发 Node DeprecationWarning,且无注入风险。
104
104
  const npmCmd = isWindows ? 'npm.cmd' : 'npm';
105
105
  const globalRoot = execSync(`${npmCmd} root -g`, {
106
- encoding: 'utf-8', timeout: 10000,
106
+ encoding: 'utf-8', timeout: 10000, windowsHide: true,
107
107
  }).trim();
108
108
  const pkgPath = path.join(globalRoot, ...pkgName.split('/'), 'package.json');
109
109
  if (fs.existsSync(pkgPath)) {
@@ -171,7 +171,7 @@ export async function tryUpgrade() {
171
171
  /**
172
172
  * 通用全局包升级流程:检查 → 比较 → 安装(失败重试一次)。
173
173
  * 仅在包已安装时检查升级,未安装则跳过(resolveFn 返回 null)。
174
- * fastaun / EC Web 等独立全局包共用此逻辑。
174
+ * 用于 EC Web 等真正独立于 EvolCore 的全局包。
175
175
  */
176
176
  export async function tryUpgradeGlobalPkg(resolveInstalled, pkgName) {
177
177
  if (isLinkedInstall()) {
@@ -201,10 +201,3 @@ export async function tryUpgradeGlobalPkg(resolveInstalled, pkgName) {
201
201
  }
202
202
  return { status: 'failed', from: localVer, to: remoteVer, error: lastError };
203
203
  }
204
- /**
205
- * AUN SDK 升级流程:检查 → 比较 → 安装
206
- * 仅在 SDK 已安装时检查升级,未安装则跳过。
207
- */
208
- export async function tryUpgradeAunSdk(resolveAunCoreSdkPkg, AUN_CORE_SDK_PKG) {
209
- return tryUpgradeGlobalPkg(resolveAunCoreSdkPkg, AUN_CORE_SDK_PKG);
210
- }
@@ -63,6 +63,17 @@ export function summarizeToolInput(toolName, input) {
63
63
  || input.url
64
64
  || '';
65
65
  }
66
+ /**
67
+ * Audit-safe tool summary. Keep the useful operation shape while masking
68
+ * credentials commonly embedded in shell commands or tool arguments.
69
+ */
70
+ export function summarizeToolInputForAudit(toolName, input) {
71
+ return summarizeToolInput(toolName, input)
72
+ .replace(/\b([A-Z0-9_]*(?:TOKEN|KEY|SECRET|PASSWORD|CREDENTIAL)[A-Z0-9_]*)\s*=\s*(?:"[^"]*"|'[^']*'|\S+)/gi, '$1=[REDACTED]')
73
+ .replace(/\b(authorization\s*:\s*Bearer\s+)[^\s"',;]+/gi, '$1[REDACTED]')
74
+ .replace(/\b(api[_-]?key|access[_-]?token|refresh[_-]?token|password|secret|authorization|cookie)\s*([=:])\s*(?:"[^"]*"|'[^']*'|\S+)/gi, '$1$2[REDACTED]')
75
+ .replace(/\bBearer\s+[^\s,;]+/gi, 'Bearer [REDACTED]');
76
+ }
66
77
  const EDIT_PREVIEW_MAX_LINES = 14;
67
78
  const EDIT_PREVIEW_CONTEXT_LINES = 2;
68
79
  const EDIT_PREVIEW_INLINE_GAP_LINES = 4;
@@ -52,5 +52,5 @@ AUN keystore seed 由 EvolCore 使用固定应用值管理,不再提供配置
52
52
  - **E2EE 加密**:可选端到端加密,回复默认跟随对端消息加密状态(密文回密文,明文回明文);keystore seed 由 EvolCore 固定管理。
53
53
  - **断线重连**:SDK 内置退避策略自动重连。实时连接状态用 `ec watch aid` 查看(`ec aid` 是身份/证书管理,不显示连接状态)。
54
54
  - **群 ID 格式**:当前协议规范使用 `g-{slug}.issuer-domain` canonical 形式,输入也可接受本域简写 `g-{slug}` 或兼容形式 `g-{slug}@issuer-domain`。历史会话里可能仍出现 `group.{issuer}/{group_no}` 一类旧格式,运行时需兼容读取。
55
- - **群分发模式**:`dispatch_mode=broadcast|mention` 是群级配置,只决定哪些群消息进入 Agent LLM 上下文,不影响 AUN 协议层投递;被过滤消息仍应本地存档。
55
+ - **群 @ 处理策略**:`mention_mode=disabled|mention-only` 是群级配置,只决定哪些群消息进入 Agent LLM 上下文,不影响 AUN 协议层投递;被过滤消息仍应本地存档。
56
56
  - **身份体系**:对端以 AID 标识,关系层 peerKey 形如 `aun#alice.aid.pub`。
@@ -163,6 +163,7 @@ manifest 是 `{ "$schema_version": 1, "sections": [...] }`。每个 section:
163
163
 
164
164
  - 覆盖文件含 `"mode": "replace"` → **完全替换**,只用覆盖文件的 sections。
165
165
  - 否则 **patch 合并**:以 `id` 为键,覆盖文件里同 id 的字段浅合并进基础 section(`{...base, ...override}`),新 id 追加。
166
+ - 旧 patch 中的 `relation-group-profile` 已废弃并会被忽略;群与私聊 profile 统一通过 `peer-profile` 配置,避免同一文件重复加载。`mode: "replace"` 不做此兼容处理。
166
167
 
167
168
  合并后统一按 `order` 升序排序。改某段行为(如关掉某层、调顺序、换条件)优先用覆盖文件,不动基础 manifest。
168
169
 
@@ -295,7 +296,6 @@ coding 场景(无 channel/无身份)下,`chatType`、`channel`、`selfAid`
295
296
  | 40 | venue-fragment | fragment | chatType≠null | ✓ |
296
297
  | 41 | venue-chattype | `$KITS_DOCS/venues/{{chatType}}.md` | chatType≠null | ✗ |
297
298
  | 42 | venue-channel-chattype | `$KITS_DOCS/venues/{{channel}}-{{chatType}}.md` | chatType≠null | ✗ |
298
- | 43 | relation-group-profile | `$RELATIONS_DIR/{{peerKey}}/profile.md` | groupId≠null | ✗ |
299
299
  | 44 | venue-client | `$KITS_DOCS/venues/client-{{clientType}}.md` | clientType≠null | ✗ |
300
300
  | 50 | channel-layer | fragment | channel≠null | ✓ |
301
301
  | 55 | commands | fragment | channel≠null | ✓ |
@@ -322,7 +322,7 @@ $KITS_DOCS/venues/ 通用环境文档(随包发布,只读
322
322
  ```
323
323
 
324
324
  > **注意**:具体群/私聊实例的 profile 数据落**关系层** `$RELATIONS_DIR/<peerKey>/profile.md`,
325
- > `relation-group-profile` 段注入,不在 venues 目录。
325
+ > 统一由 `peer-profile` 段注入,不在 venues 目录;群不会再通过另一个 section 重复加载。
326
326
 
327
327
  ## 输出结构
328
328
 
@@ -17,9 +17,10 @@ ec agent <aid>
17
17
  ec agent new [aid]
18
18
 
19
19
  # 创建 agent(非交互式,自动化场景)
20
- ec agent new <aid> --non-interactive --project <绝对路径> \
21
- [--baseagent claude|codex|gemini] [--owner <aid>] \
22
- [--name "<显示名>"] [--description "<text>"] [--force]
20
+ ec agent new <aid> --non-interactive \
21
+ [--project <路径>] [--baseagent claude|codex|gemini|ecagent] \
22
+ [--owner <aid>] [--name "<显示名>"] [--description "<text>"] \
23
+ [--dry-run] [--force]
23
24
 
24
25
  # 启用 / 停用
25
26
  ec agent enable <aid>
@@ -44,9 +45,13 @@ ec agent delete <aid> [--purge]
44
45
 
45
46
  ## 非交互创建必填项
46
47
 
47
- `ec agent new <aid> --non-interactive` 时:
48
- - 必填:`--project <absolute path>`
49
- - 可选:`--baseagent`(默认 PATH 中第一个可用项)、`--owner`、`--name`、`--description`、`--force`(覆盖已有 config.json
48
+ `ec agent new <aid> --non-interactive` 时,只有 `<aid>` 必填:
49
+ - `--project` 缺省为当前目录,并自动转为绝对路径。
50
+ - `--baseagent` 优先使用 `agents/defaults.json`,否则检测本机可用基座。
51
+ - `--owner` 缺省使用 `daemon.json` 的第一个 owner;未配置时省略。
52
+ - `--name` / `--description` 缺省读取当前项目 `package.json`,再回退到目录名 / 空描述。
53
+ - `--dry-run` 只输出最终创建计划,不注册 AID、不写配置、不上传 `agent.md`。
54
+ - `--force` 覆盖已有 `config.json`;AID 密钥保留。
50
55
 
51
56
  ## 头像更新
52
57
 
@@ -2,6 +2,20 @@
2
2
 
3
3
  管理本地 AID 身份(证书、私钥、agent.md 名片),以及远程探测对端 AID。触发词:身份/证书/名片/探测对端/创建身份。
4
4
 
5
+ ## 运行边界
6
+
7
+ 本页列出独立终端中 `ec aid` 的完整 CLI 能力。在 EvolCore 托管 Agent 会话中,为防止会话枚举、创建、删除或切换身份,只允许当前 self AID 上的以下精确命令:
8
+
9
+ ```bash
10
+ ec aid show <当前 self AID> [--format json]
11
+ ec aid lookup <当前 self AID> [--format json]
12
+ ec aid agentmd get <当前 self AID> [--format json]
13
+ # 仅 request / bypass
14
+ ec aid agentmd put <当前 self AID> [--format json]
15
+ ```
16
+
17
+ 仅允许不带选项的基本形式,或在末尾附加一组完整的 `--format json`;不能使用 `--aun-path`、未知选项、管道、重定向或其他 AID。`show`、`lookup` 和 `agentmd get` 是 self-scoped 查询,可在所有 `permissionMode` 执行;`agentmd put` 会发布远端名片,属于写操作,仅允许 `request`、`bypass`,`readonly`、`auto` 和未知模式均拒绝。该身份范围边界早于模式审批,`bypass` 也不能跨越当前 self AID。`show` 会对自身身份做本地签名/验签自检,但不输出私钥;`lookup` 只探测已知的自身 AID;`get` 不改变身份或远端数据,但会下载并验签自身公开名片,同时刷新本地 AID 缓存。`list`、其他 AID 的 `show/lookup/agentmd get/put` 以及 `new/delete` 均拒绝。独立终端不受此托管会话限制。
18
+
5
19
  ## 子命令
6
20
 
7
21
  ```bash
@@ -69,7 +69,7 @@
69
69
  | **vars 粒度** | 会话级(一次构造,整批复用) | item 级(每条叠加 peerName/now/images) |
70
70
  | **模板空行** | 删除(stripBlankLines=true,紧凑) | 保留(stripBlankLines=false,消息多段) |
71
71
  | **content 注入** | N/A | 哨兵末步字面量注入(防二次解析) |
72
- | **缓存** | per-sessionId(跨消息复用文件内容) | per-renderMessageBody 调用(局部) |
72
+ | **缓存** | 随包 `kits/` 文件跨 session 缓存到 reload;personal/relations 等运行时文件按 mtime 刷新 | 随包模板缓存到 reload,消息数据不缓存 |
73
73
  | **debug 输出** | `eck-debug/context-*.md` `fragments-*.md` `manifest-*.md` `vars-*.json` | `eck-debug/msg-render-*.md` |
74
74
 
75
75
  ---
@@ -109,7 +109,6 @@
109
109
  | 40 | venue-fragment | chatType≠null | ✓ | 环境层 fragment |
110
110
  | 41 | venue-chattype | chatType≠null | ✗ | `venues/{{chatType}}.md` |
111
111
  | 42 | venue-channel-chattype | chatType≠null | ✗ | `venues/{{channel}}-{{chatType}}.md` |
112
- | 43 | venue-group-profile | groupId≠null | ✗ | 群 venue profile.md |
113
112
  | 44 | venue-client | clientType≠null | ✗ | `venues/client-{{clientType}}.md` |
114
113
  | 50 | channel-layer | channel≠null | ✓ | 渠道层 fragment |
115
114
  | 55 | commands | channel≠null | ✓ | 命令集能力卡 |
@@ -5,7 +5,7 @@
5
5
  ## 行为准则
6
6
  - `mentionMode: mention-only` — 仅响应明确 @ 自己的消息
7
7
  - `mentionMode: disabled` — 所有消息可见,自主判断是否参与。这不是叫你每条都回,而是你可以像真人一样:感兴趣的接话,不感兴趣的就跳过。回得短一点、快一点,让对话流动起来,不要一个人长篇大论堵住别人的空间
8
- - 查看 venue 档案(venue-group-profile)了解本群文化与策略
8
+ - 查看关系档案(peer-profile)了解本群文化与策略
9
9
  - 如果上下文中出现“群规则”,它来自当前群资源空间的本地同步缓存;群规则优先于通用群聊指引
10
10
  - 群发言会被多人看到,谨言慎行
11
11
  - 具体渠道(AUN/飞书/微信等)的群聊特有指引见对应渠道文档
@@ -127,18 +127,6 @@
127
127
  ] },
128
128
  "description": "渠道+场景文档(如 feishu-group)"
129
129
  },
130
- {
131
- "id": "relation-group-profile",
132
- "type": "file",
133
- "file": "$RELATIONS_DIR/{{peerKey}}/profile.md",
134
- "order": 43,
135
- "needsInjection": false,
136
- "when": { "and": [
137
- { "var": "groupId", "neq": null },
138
- { "var": "lifecycle", "neq": "bootstrapping" }
139
- ] },
140
- "description": "具体群关系文档"
141
- },
142
130
  {
143
131
  "id": "relation-group-rules",
144
132
  "type": "file",
@@ -39,7 +39,7 @@ relations/
39
39
 
40
40
  | 条目 | 真实状态 |
41
41
  |------|----------|
42
- | `<peerKey>/profile.md` | manifest 声明了加载槽(`peer-profile`、`relation-group-profile`,缺失即跳过),但**没有任何代码写它**,磁盘上零文件。你可以手写一份,它会被加载 |
42
+ | `<peerKey>/profile.md` | manifest 通过统一的 `peer-profile` 槽加载(缺失即跳过),群聊和私聊不再重复声明;目前**没有任何代码写它**,可以手写一份供上下文加载 |
43
43
  | `_index/name_<name>.json` 名字反查索引 | 目录会被创建,但**无任何读写代码**,磁盘上全是空目录。"已知 name 反查 peerKey" 这条路走不通 |
44
44
  | `<peerKey>/history.jsonl` | 关系层无此实现(同名文件都属于 handoff / trigger / CC 自己的历史) |
45
45
  | `_trash/` | 只创建目录,没有 merge/split 重定向逻辑 |
@@ -5,7 +5,7 @@
5
5
  | 变量 | 取值 | 说明 |
6
6
  |------|------|------|
7
7
  | `chatType` | `private` / `group` / null | null = 无渠道的本地 coding 会话 |
8
- | `mentionMode` | `mention-only` / `disabled` | 群内响应策略;取 agent/relation 配置,缺省时由服务器 `dispatchMode` 翻译(mention→mention-only,broadcast→disabled) |
8
+ | `mentionMode` | `mention-only` / `disabled` | 群内响应策略;取 agent/relation 配置,缺省时使用群服务器下发的 `mention_mode` |
9
9
  | `clientType` | `desktop` / `web` / `mobile` | 有值时额外加载客户端场景文档 |
10
10
  | `permissionMode` | readonly/auto/request/bypass | 当前生效权限模式 |
11
11
  | `venueUid` | 恒为 undefined | 声明了但源码固定不填,模板有 `{{?}}` 守卫所以永不渲染——**不要依赖它** |
@@ -39,7 +39,7 @@
39
39
  ## Venue 类型抽象
40
40
 
41
41
  环境层关注的是**类型**,而非具体实例。类型只有 `private` 和 `group` 两种(即 `chatType` 的两个非空取值)——
42
- 没有 `broadcast` 这个 venue 类型,`broadcast` 是**群分发模式** `dispatchMode` 的取值之一(另一个是 `mention`)。
42
+ 没有 `broadcast` 这个 venue 类型;群响应策略统一由 `mentionMode` 表达。
43
43
 
44
44
  "张三所在的 team-alpha 这个**具体群**"不属于环境层,它是关系层的对端实例,数据落 `relations/<peerKey>/`。
45
45
 
@@ -11,10 +11,10 @@
11
11
  "type": "boolean",
12
12
  "enum": [true, false],
13
13
  "default": true,
14
- "description": "proactive 首工具表态检查(仅 chatmode=proactive 生效):首个工具调用前必须先向对端表态,否则拦截。",
14
+ "description": "proactive 首个本地工具表态检查(仅 chatmode=proactive 生效):首个可被 PreToolUse 覆盖的本地工具必须是当前会话精确对应的 ec msg/group send,否则拦截;WebSearch、图像生成、浏览器和 Computer Use 等 hosted 工具不进入此硬拒绝边界。",
15
15
  "x-enumDescriptions": {
16
- "true": "启用:首工具前必须先发送消息或文件",
17
- "false": "禁用:允许直接调用工具"
16
+ "true": "启用:首个 hook 可覆盖的本地工具必须是精确会话 send",
17
+ "false": "禁用:不执行 proactive 首个本地工具 send 检查"
18
18
  }
19
19
  },
20
20
  "tool_use_reminder": {
@@ -34,10 +34,10 @@
34
34
  "type": "boolean",
35
35
  "enum": [true, false],
36
36
  "default": true,
37
- "description": "proactive 首工具表态检查(仅 chatmode=proactive 生效):首个工具调用前必须先向对端表态,否则拦截。",
37
+ "description": "proactive 首个本地工具表态检查(仅 chatmode=proactive 生效):首个可被 PreToolUse 覆盖的本地工具必须是当前会话精确对应的 ec msg/group send,否则拦截;WebSearch、图像生成、浏览器和 Computer Use 等 hosted 工具不进入此硬拒绝边界。",
38
38
  "x-enumDescriptions": {
39
- "true": "启用:首工具前必须先发送消息或文件",
40
- "false": "禁用:允许直接调用工具"
39
+ "true": "启用:首个 hook 可覆盖的本地工具必须是精确会话 send",
40
+ "false": "禁用:不执行 proactive 首个本地工具 send 检查"
41
41
  }
42
42
  },
43
43
  "tool_use_reminder": {
@@ -27,11 +27,21 @@
27
27
  "role.revoke": { "allow": true, "scopes": ["agent"] },
28
28
  "role.policy.read": { "allow": true, "scopes": ["agent"] },
29
29
  "role.relation.read": { "allow": true, "scopes": ["agent"] },
30
+ "agent.baseagent.update": {
31
+ "allow": true,
32
+ "scopes": ["agent"],
33
+ "constraints": { "requireAgentOwner": true, "targetCurrentAgentOnly": true }
34
+ },
30
35
  "observable.current": {
31
36
  "allow": true,
32
37
  "scopes": ["agent"],
33
38
  "constraints": { "requireAgentOwner": true }
34
39
  },
40
+ "observable.update": {
41
+ "allow": true,
42
+ "scopes": ["agent"],
43
+ "constraints": { "requireAgentOwner": true, "targetCurrentAgentOnly": true }
44
+ },
35
45
  "config.get": { "allow": true, "scopes": ["agent", "relation"] },
36
46
  "config.set": { "allow": true, "scopes": ["agent", "relation"] },
37
47
  "config.unset": { "allow": true, "scopes": ["agent", "relation"] },
@@ -41,6 +51,18 @@
41
51
  "scopes": ["agent"],
42
52
  "constraints": { "requireAgentAdmin": true }
43
53
  },
54
+ "ec.aid.show": {
55
+ "allow": true,
56
+ "dangerous": true,
57
+ "scopes": ["agent"],
58
+ "constraints": { "targetCurrentAgentOnly": true, "requireAgentAdmin": true }
59
+ },
60
+ "ec.aid.agentmd.put": {
61
+ "allow": true,
62
+ "dangerous": true,
63
+ "scopes": ["agent"],
64
+ "constraints": { "targetCurrentAgentOnly": true, "requireAgentAdmin": true }
65
+ },
44
66
  "*": { "allow": true },
45
67
  "agent.reload": {
46
68
  "allow": true,
@@ -53,8 +53,35 @@
53
53
  "trigger.*": { "allow": true, "scopes": ["relation"], "constraints": { "ownPeerOnly": true, "targetCurrentAgentOnly": true } },
54
54
  "ec.msg.send": { "allow": true, "constraints": { "ownPeerOnly": true } },
55
55
  "ec.msg.file": { "allow": true, "constraints": { "ownPeerOnly": true } },
56
+ "ec.msg.history": { "allow": true, "scopes": ["relation"], "constraints": { "privateOnly": true, "currentRelationOnly": true, "targetCurrentAgentOnly": true } },
57
+ "ec.msg.online": { "allow": true, "scopes": ["relation"], "constraints": { "privateOnly": true, "currentRelationOnly": true, "targetCurrentAgentOnly": true } },
58
+ "ec.version": { "allow": true },
59
+ "ec.aid.show": { "allow": true, "dangerous": true, "scopes": ["relation"], "constraints": { "targetCurrentAgentOnly": true } },
60
+ "ec.aid.lookup": { "allow": true, "scopes": ["relation"], "constraints": { "targetCurrentAgentOnly": true } },
61
+ "ec.aid.agentmd.get": { "allow": true, "scopes": ["relation"], "constraints": { "targetCurrentAgentOnly": true } },
62
+ "ec.aid.agentmd.put": { "allow": false },
63
+ "ec.fs.ls": { "allow": true, "scopes": ["relation"], "constraints": { "groupOnly": true, "currentRelationOnly": true, "targetCurrentAgentOnly": true } },
64
+ "ec.fs.stat": { "allow": true, "scopes": ["relation"], "constraints": { "groupOnly": true, "currentRelationOnly": true, "targetCurrentAgentOnly": true } },
65
+ "ec.fs.lstat": { "allow": true, "scopes": ["relation"], "constraints": { "groupOnly": true, "currentRelationOnly": true, "targetCurrentAgentOnly": true } },
66
+ "ec.fs.cat": { "allow": true, "scopes": ["relation"], "constraints": { "groupOnly": true, "currentRelationOnly": true, "targetCurrentAgentOnly": true } },
67
+ "ec.fs.find": { "allow": true, "scopes": ["relation"], "constraints": { "groupOnly": true, "currentRelationOnly": true, "targetCurrentAgentOnly": true } },
68
+ "ec.fs.df": { "allow": true, "scopes": ["relation"], "constraints": { "groupOnly": true, "currentRelationOnly": true, "targetCurrentAgentOnly": true } },
69
+ "ec.handoff.status": { "allow": true, "scopes": ["relation"], "constraints": { "currentRelationOnly": true, "targetCurrentAgentOnly": true } },
70
+ "ec.handoff.list": { "allow": true, "scopes": ["relation"], "constraints": { "currentRelationOnly": true, "targetCurrentAgentOnly": true } },
71
+ "ec.handoff.trace": { "allow": true, "scopes": ["relation"], "constraints": { "currentRelationOnly": true, "targetCurrentAgentOnly": true } },
72
+ "ec.handoff.return": { "allow": true, "scopes": ["relation"], "constraints": { "currentRelationOnly": true, "targetCurrentAgentOnly": true } },
73
+ "ec.queue.*": { "allow": false },
56
74
  "ec.group.send": { "allow": true, "constraints": { "groupOnly": true, "currentRelationOnly": true } },
57
75
  "ec.group.file": { "allow": true, "constraints": { "groupOnly": true, "currentRelationOnly": true } },
76
+ "ec.group.info": { "allow": true, "scopes": ["relation"], "constraints": { "groupOnly": true, "currentRelationOnly": true, "targetCurrentAgentOnly": true } },
77
+ "ec.group.pull": { "allow": true, "scopes": ["relation"], "constraints": { "groupOnly": true, "currentRelationOnly": true, "targetCurrentAgentOnly": true } },
78
+ "ec.group.members": { "allow": true, "scopes": ["relation"], "constraints": { "groupOnly": true, "currentRelationOnly": true, "targetCurrentAgentOnly": true } },
79
+ "ec.group.online": { "allow": true, "scopes": ["relation"], "constraints": { "groupOnly": true, "currentRelationOnly": true, "targetCurrentAgentOnly": true } },
80
+ "ec.group.rules.get": { "allow": true, "scopes": ["relation"], "constraints": { "groupOnly": true, "currentRelationOnly": true, "targetCurrentAgentOnly": true } },
81
+ "ec.group.rules.read": { "allow": true, "scopes": ["relation"], "constraints": { "groupOnly": true, "currentRelationOnly": true, "targetCurrentAgentOnly": true } },
82
+ "ec.ctl.send": { "allow": true, "scopes": ["relation"], "constraints": { "ownPeerOnly": true, "currentRelationOnly": true, "targetCurrentAgentOnly": true } },
83
+ "ec.ctl.file": { "allow": true, "scopes": ["relation"], "constraints": { "ownPeerOnly": true, "currentRelationOnly": true, "targetCurrentAgentOnly": true } },
84
+ "ec.ctl.queue.*": { "allow": true, "scopes": ["relation"], "constraints": { "ownPeerOnly": true, "currentRelationOnly": true, "targetCurrentAgentOnly": true } },
58
85
  "ec.ctl.*": { "allow": false },
59
86
  "cli.exec.raw": { "allow": false, "dangerous": true },
60
87
  "dangerous:*": { "allow": false, "dangerous": true }
@@ -20,7 +20,11 @@
20
20
  "config.get": { "allow": true, "scopes": ["relation"], "constraints": { "currentRelationOnly": true, "targetCurrentAgentOnly": true, "configFieldPolicy": "behavior-read" } },
21
21
  "model.list": { "allow": true, "scopes": ["relation"], "constraints": { "ownPeerOnly": true, "targetCurrentAgentOnly": true } },
22
22
  "model.current": { "allow": true, "scopes": ["relation"], "constraints": { "ownPeerOnly": true, "targetCurrentAgentOnly": true } },
23
- "model.use": { "allow": true, "scopes": ["relation"], "constraints": { "ownPeerOnly": true, "targetCurrentAgentOnly": true } },
23
+ "model.info": { "allow": true, "scopes": ["relation"], "constraints": { "ownPeerOnly": true, "targetCurrentAgentOnly": true } },
24
+ "model.use": { "allow": false },
25
+ "model.effort": { "allow": false },
26
+ "model.reset": { "allow": false },
27
+ "model.check": { "allow": false },
24
28
  "permission.current": { "allow": true, "scopes": ["relation"], "constraints": { "ownPeerOnly": true, "targetCurrentAgentOnly": true } },
25
29
  "permission.answer": { "allow": true, "scopes": ["relation"], "constraints": { "ownPeerOnly": true, "targetCurrentAgentOnly": true } },
26
30
  "chatmode.current": { "allow": true, "scopes": ["relation"], "constraints": { "ownPeerOnly": true, "targetCurrentAgentOnly": true } },
@@ -32,9 +36,18 @@
32
36
  "group.mentionmode.update": { "allow": false },
33
37
  "group.rulespolicy.current": { "allow": true, "scopes": ["relation"], "constraints": { "groupOnly": true, "currentRelationOnly": true, "targetCurrentAgentOnly": true } },
34
38
  "group.rulespolicy.update": { "allow": false },
35
- "trigger.*": { "allow": true, "scopes": ["relation"], "constraints": { "ownPeerOnly": true, "targetCurrentAgentOnly": true } },
39
+ "trigger.list": { "allow": true, "scopes": ["relation"], "constraints": { "ownPeerOnly": true, "targetCurrentAgentOnly": true } },
40
+ "trigger.show": { "allow": true, "scopes": ["relation"], "constraints": { "ownPeerOnly": true, "targetCurrentAgentOnly": true } },
41
+ "trigger.history": { "allow": true, "scopes": ["relation"], "constraints": { "ownPeerOnly": true, "targetCurrentAgentOnly": true } },
42
+ "trigger.eventCatalog": { "allow": true, "scopes": ["relation"], "constraints": { "ownPeerOnly": true, "targetCurrentAgentOnly": true } },
43
+ "trigger.create": { "allow": false },
44
+ "trigger.update": { "allow": false },
45
+ "trigger.setEnabled": { "allow": false },
46
+ "trigger.cancel": { "allow": false },
47
+ "trigger.delete": { "allow": false },
48
+ "trigger.run": { "allow": false },
36
49
  "session.list": { "allow": true, "scopes": ["relation"], "constraints": { "ownPeerOnly": true } },
37
- "session.current": { "allow": true, "scopes": ["relation"], "constraints": { "ownPeerOnly": true } },
50
+ "session.current": { "allow": true, "scopes": ["relation"], "constraints": { "ownPeerOnly": true, "targetCurrentAgentOnly": true } },
38
51
  "session.topic.current": { "allow": true, "scopes": ["relation"], "constraints": { "ownPeerOnly": true } },
39
52
  "session.topic.list": { "allow": true, "scopes": ["relation"], "constraints": { "ownPeerOnly": true } },
40
53
  "project.current": { "allow": true, "scopes": ["relation"], "constraints": { "ownPeerOnly": true, "targetCurrentAgentOnly": true } },
@@ -43,8 +56,25 @@
43
56
  "capability.read": { "allow": true, "scopes": ["agent"], "constraints": { "targetCurrentAgentOnly": true } },
44
57
  "ec.msg.send": { "allow": true, "scopes": ["relation"], "constraints": { "ownPeerOnly": true, "privateOnly": true } },
45
58
  "ec.msg.file": { "allow": false },
59
+ "ec.msg.history": { "allow": false },
60
+ "ec.msg.online": { "allow": false },
61
+ "ec.version": { "allow": true },
62
+ "ec.aid.show": { "allow": false },
63
+ "ec.aid.lookup": { "allow": true, "scopes": ["relation"], "constraints": { "targetCurrentAgentOnly": true } },
64
+ "ec.aid.agentmd.get": { "allow": false },
65
+ "ec.aid.agentmd.put": { "allow": false },
66
+ "ec.fs.*": { "allow": false },
67
+ "ec.handoff.*": { "allow": false },
68
+ "ec.queue.*": { "allow": false },
69
+ "storage.*": { "allow": false },
46
70
  "ec.group.send": { "allow": true, "scopes": ["relation"], "constraints": { "groupOnly": true, "currentRelationOnly": true } },
47
71
  "ec.group.file": { "allow": false },
72
+ "ec.group.info": { "allow": true, "scopes": ["relation"], "constraints": { "groupOnly": true, "currentRelationOnly": true, "targetCurrentAgentOnly": true } },
73
+ "ec.group.pull": { "allow": false },
74
+ "ec.group.members": { "allow": false },
75
+ "ec.group.online": { "allow": false },
76
+ "ec.group.rules.get": { "allow": true, "scopes": ["relation"], "constraints": { "groupOnly": true, "currentRelationOnly": true, "targetCurrentAgentOnly": true } },
77
+ "ec.group.rules.read": { "allow": true, "scopes": ["relation"], "constraints": { "groupOnly": true, "currentRelationOnly": true, "targetCurrentAgentOnly": true } },
48
78
  "ec.ctl.*": { "allow": false },
49
79
  "cli.exec.raw": { "allow": false, "dangerous": true },
50
80
  "dangerous:*": { "allow": false, "dangerous": true }
@@ -17,6 +17,6 @@ phase: bootstrapping
17
17
  5. owner 明确确认后,只编辑本地 agent.md(`$EVOLCORE_HOME/AIDs/{{selfAid}}/agent.md`)YAML frontmatter 中的 `name`、`description`、`tags`,保留其它字段和正文,并检查 YAML 与字段格式有效。
18
18
  6. 调用 `ec aid agentmd put {{selfAid}}` 签名并发布 agent.md。只有命令明确成功后,才调用 `ec agent ready {{selfAid}}` 完成 bootstrap。
19
19
  7. 任一步骤失败时,不调用 ready,不盲目重复尝试;说明具体失败原因并在修正后继续。
20
- 8. `ec agent ready {{selfAid}}` 必须是 bootstrap 的最后一个操作。成功后不要再生成一段完成说明,系统会发送正式欢迎消息。
20
+ 8. `ec agent ready {{selfAid}}` 必须是 bootstrap 的最后一个操作。成功后系统会结束当前 bootstrap 上下文、创建全新的主会话并发送正式欢迎消息;不要再生成一段完成说明,也不要在旧上下文中继续处理任务。
21
21
 
22
22
  完成前不要承诺已经进入正常工作状态,也不要尝试与上述流程无关的文件修改、网络通信或系统配置操作。
@@ -22,7 +22,7 @@ chatMode: {{chatMode}} # interactive=同步对话 / proactive=主动推送
22
22
  # 设计意图:避免 agent↔agent 无限循环;某一方不再发送 → 对话自然终止。
23
23
  # 拿不到 self-aid 时可用 ec ctl send "<text>"(自动继承当前 AID 和对端)。
24
24
  # Shell 调用边界:每次工具调用只能执行一条完整的 ec 命令。
25
- # 禁止拼接 command -vec aid、&&、||、;、|、重定向、子 shell、bash -lc/sh -c 或其它脚本。
25
+ # 禁止拼接 command -v。`ec aid` 仅允许对 {{selfAid}} 精确执行 show、lookup、agentmd get;仅 request/bypass 可执行 agentmd put。可选后缀仅限 --format json;禁止 &&、||、;、|、重定向、子 shell、bash -lc/sh -c 或其它脚本。
26
26
  # 不要先做 CLI 探测;直接执行下方的单条 ec 命令,读取 JSON/回执后再决定下一步。
27
27
  # 工具审批拒绝时原样报告并停止,不要通过追加其它命令或提权重试绕过审批。
28
28
  {{/}}
@@ -44,7 +44,7 @@ readonly: true — 禁止写入项目目录及临时目录;如需生成文件
44
44
  # - 每 {{proactiveToolReportInterval}} 次非发送工具调用后,必须先用发送命令汇报当前进展和下一步,否则后续非发送工具会被拒绝
45
45
  {{/}}
46
46
  # 命令速查:
47
- # 每次工具调用只执行一条完整的 ec 命令;禁止 command -vec aid、&&、||、;、|、重定向、子 shell、bash -lc/sh -c 或其它脚本与其串联。
47
+ # 每次工具调用只执行一条完整的 ec 命令;禁止 command -v。`ec aid` 仅允许对 {{selfAid}} 精确执行 show、lookup、agentmd get;仅 request/bypass 可执行 agentmd put。可选后缀仅限 --format json;禁止 &&、||、;、|、重定向、子 shell、bash -lc/sh -c 或其它脚本与其串联。
48
48
  # 审批拒绝时原样报告并停止;必须收到包含 message_id/status 的成功回执后才能声称已发送。
49
49
  {{?chatType=group}}
50
50
  # ec group send {{selfAid}} {{groupId}} "<text>" [--return none|required] [--file <path>] [--mention <aid>]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "evolcore",
3
- "version": "0.0.11",
3
+ "version": "0.0.12",
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",
@@ -44,7 +44,7 @@
44
44
  "prepublishOnly": "npm test"
45
45
  },
46
46
  "dependencies": {
47
- "@agentunion/fastaun": "^0.5.4",
47
+ "@agentunion/fastaun": "0.5.6",
48
48
  "@anthropic-ai/claude-agent-sdk": "0.3.220",
49
49
  "@modelcontextprotocol/sdk": "^1.29.0",
50
50
  "ajv": "^8.20.0",
@@ -1,39 +0,0 @@
1
- import { loadDaemonConfig } from '../../config-store.js';
2
- import { readInstalledEvolcoreVersion } from '../../utils/evolcore-version.js';
3
- import { compareStableSemver, parseStableSemver } from '../../utils/stable-semver.js';
4
- export function evaluateEvolMenuVersionGate(input) {
5
- const minimum = loadDaemonConfig().aun?.minEvolVersion;
6
- if (!minimum)
7
- return null;
8
- const minimumVersion = parseStableSemver(minimum);
9
- if (!minimumVersion) {
10
- throw new Error('daemon.json.aun.minEvolVersion must use stable X.Y.Z format');
11
- }
12
- const received = input.protectedHeaders?.evol_version;
13
- const receivedVersion = input.encrypted ? parseStableSemver(received) : null;
14
- if (!receivedVersion || compareStableSemver(receivedVersion, minimumVersion) < 0) {
15
- return {
16
- code: 'UPGRADE_REQUIRED',
17
- message: `Evol ${minimum} or later is required`,
18
- data: {
19
- minimum,
20
- received: receivedVersion ? received : null,
21
- },
22
- };
23
- }
24
- return null;
25
- }
26
- export function isEvolMenuVersionGateEnabled() {
27
- return loadDaemonConfig().aun?.minEvolVersion !== undefined;
28
- }
29
- /** Token may be issued while disabled, but only this flag makes it an access requirement. */
30
- export function isAunMenuTokenRequired() {
31
- return loadDaemonConfig().aun?.menuTokenRequired === true;
32
- }
33
- export function evolMenuResponseTransportMetadata() {
34
- return {
35
- // Clear inherited request state so AUNChannel applies daemon aun.defaultEncrypt.
36
- encrypted: undefined,
37
- protectedHeaders: { ec_version: readInstalledEvolcoreVersion() },
38
- };
39
- }