evolcore 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +83 -0
- package/README.md +45 -10
- package/bin/ec-safe-output.js +89 -24
- package/dist/agents/baseagent.js +46 -0
- package/dist/agents/claude-runner.js +1 -31
- package/dist/agents/codex-app-server-client.js +68 -0
- package/dist/agents/codex-runner.js +157 -5
- package/dist/agents/runner-types.js +2 -2
- package/dist/aun/aid/agentmd.js +79 -0
- package/dist/aun/aid/encryption-seed-policy.js +29 -0
- package/dist/aun/aid/index.js +1 -1
- package/dist/aun/aid/store.js +2 -5
- package/dist/channels/aun.js +220 -112
- package/dist/channels/daemon.js +18 -4
- package/dist/channels/dingtalk.js +52 -137
- package/dist/channels/feishu.js +56 -4
- package/dist/channels/qqbot.js +23 -1
- package/dist/channels/wechat.js +303 -155
- package/dist/channels/wecom.js +383 -7
- package/dist/cli/aun-commands.js +11 -11
- package/dist/cli/daemon-commands.js +46 -15
- package/dist/cli/handoff-command.js +2 -1
- package/dist/cli/init-channel.js +185 -67
- package/dist/cli/init.js +49 -27
- package/dist/cli/trigger-command.js +92 -11
- package/dist/config/access-policy-domain.js +18 -0
- package/dist/config/access-policy.js +110 -0
- package/dist/config/builtin-role-templates.js +27 -14
- package/dist/config/builtin-roles.js +25 -6
- package/dist/config/config-field-policy.js +17 -5
- package/dist/config/config-manager.js +198 -22
- package/dist/config/config-operation-service.js +35 -38
- package/dist/config/contact-bind-code.js +274 -0
- package/dist/config/contact-book-store.js +173 -5
- package/dist/config/contact-book.js +32 -0
- package/dist/config/contact-operation-service.js +9 -3
- package/dist/config/contact-request-service.js +331 -0
- package/dist/config/peer-role-resolver.js +3 -1
- package/dist/config/schema-registry.js +49 -24
- package/dist/config-store.js +14 -2
- package/dist/core/auth/agent-delegation.js +105 -11
- package/dist/core/auth/authorization-audit.js +6 -0
- package/dist/core/auth/operation-authorizer.js +8 -0
- package/dist/core/auth/operation-catalog.js +51 -3
- package/dist/core/auth/trigger-authorization.js +15 -0
- package/dist/core/bootstrap-service.js +2 -9
- package/dist/core/channel-loader.js +6 -2
- package/dist/core/command/command-handler.js +10 -13
- package/dist/core/command/connect-menu.js +229 -26
- package/dist/core/command/evol-menu-version-gate.js +38 -0
- package/dist/core/command/group-menu.js +421 -0
- package/dist/core/command/menu-handler.js +269 -85
- package/dist/core/command/menu-protocol.js +8 -2
- package/dist/core/command/menu-token-store.js +102 -0
- package/dist/core/command/role-menu.js +16 -0
- package/dist/core/command/slash-gate.js +1 -1
- package/dist/core/command/slash-handler.js +158 -31
- package/dist/core/daemon-file-cache.js +28 -0
- package/dist/core/event-catalog.js +29 -0
- package/dist/core/evolagent-registry.js +4 -39
- package/dist/core/handoff/runtime.js +162 -37
- package/dist/core/handoff/store.js +46 -2
- package/dist/core/handoff/types.js +1 -0
- package/dist/core/inference/text-inference.js +16 -74
- package/dist/core/message/file-markers.js +7 -0
- package/dist/core/message/im-renderer.js +18 -14
- package/dist/core/message/inbound-admission.js +134 -0
- package/dist/core/message/message-bridge.js +616 -74
- package/dist/core/message/message-log.js +1 -0
- package/dist/core/message/message-queue.js +185 -10
- package/dist/core/message/peer-mode.js +7 -8
- package/dist/core/message/response-engine.js +381 -79
- package/dist/core/permission/approval-gateway.js +17 -10
- package/dist/core/permission/ec-command-parser.js +101 -46
- package/dist/core/permission/tool-policy.js +69 -24
- package/dist/core/protected-paths.js +36 -11
- package/dist/core/session/session-fs-store.js +19 -4
- package/dist/core/session/session-manager.js +232 -4
- package/dist/core/session/session-mapper.js +2 -0
- package/dist/core/session/session-renew.js +125 -69
- package/dist/core/session/session-turn-coordinator.js +5 -1
- package/dist/eck/kit-renderer.js +12 -1
- package/dist/eck/message-renderer.js +79 -1
- package/dist/index.js +224 -89
- package/dist/ipc.js +81 -4
- package/dist/paths.js +3 -0
- package/dist/response-system/config-resolver.js +29 -0
- package/dist/response-system/coordinator.js +8 -32
- package/dist/response-system/engines/v1/proactive-flow.js +1 -1
- package/dist/response-system/index.js +1 -0
- package/dist/response-system/modes/single-session/index.js +7 -4
- package/dist/trigger/parser.js +55 -15
- package/dist/trigger/patch.js +4 -1
- package/dist/trigger/scheduler.js +441 -39
- package/dist/utils/cross-platform.js +8 -2
- package/dist/utils/error-dict.json +7 -0
- package/dist/utils/evolcore-version.js +21 -0
- package/dist/utils/logger.js +2 -2
- package/dist/utils/process-introspect.js +19 -3
- package/dist/utils/stable-semver.js +21 -0
- package/dist/utils/stats.js +33 -9
- package/kits/docs/channels/aun.md +4 -13
- package/kits/docs/evolcore/INDEX.md +1 -1
- package/kits/docs/evolcore/config.md +47 -2
- package/kits/docs/evolcore/contact.md +8 -3
- package/kits/docs/evolcore/group-rules.md +46 -4
- package/kits/docs/evolcore/group.md +4 -4
- package/kits/docs/evolcore/msg.md +5 -5
- package/kits/docs/evolcore/trigger.md +25 -8
- package/kits/docs/path-registry.md +36 -17
- package/kits/eck_message_manifest.json +12 -1
- package/kits/migrations/migrate-contact-book-v2.mjs +7 -0
- package/kits/rules/01-overview.md +17 -7
- package/kits/rules/02-navigation.md +38 -18
- package/kits/rules/03-identity.md +28 -24
- package/kits/rules/04-relation.md +44 -28
- package/kits/rules/05-venue.md +31 -15
- package/kits/rules/06-channel.md +11 -7
- package/kits/schemas/_meta.json +18 -7
- package/kits/schemas/agent-config.schema.7.json +303 -0
- package/kits/schemas/agent-config.schema.8.json +304 -0
- package/kits/schemas/agent-config.schema.9.json +364 -0
- package/kits/schemas/contact-book.schema.3.json +67 -0
- package/kits/schemas/daemon.schema.1.json +3 -2
- package/kits/schemas/daemon.schema.2.json +101 -0
- package/kits/schemas/daemon.schema.3.json +123 -0
- package/kits/schemas/defaults.schema.2.json +85 -0
- package/kits/schemas/defaults.schema.3.json +73 -0
- package/kits/schemas/relation-config.schema.6.json +46 -0
- package/kits/schemas/relation-config.schema.7.json +59 -0
- package/kits/schemas/single-session.schema.2.json +57 -0
- package/kits/templates/message-fragments/handoff-context-to-target.md +9 -0
- package/kits/templates/message-fragments/handoff-request-to-target.md +14 -8
- package/kits/templates/message-fragments/handoff-response-to-origin.md +5 -6
- package/kits/templates/roles/admin.json +46 -0
- package/kits/templates/roles/member.json +4 -0
- package/kits/templates/roles/visitor.json +4 -0
- package/kits/templates/system-fragments/channel.md +12 -2
- package/kits/templates/system-fragments/identity.md +3 -1
- package/kits/templates/system-fragments/relation.md +1 -1
- package/kits/templates/system-fragments/session.md +6 -2
- package/package.json +4 -2
- package/MIGRATION-0.5.0.md +0 -378
- package/ROLE_ACCESS_CONTROL.md +0 -174
- package/dist/channels/contact-bind-code.js +0 -134
- package/dist/channels/wecom-card.js +0 -101
- package/dist/channels/wecom-onboarding.js +0 -82
- package/dist/channels/wecom-state.js +0 -191
package/MIGRATION-0.5.0.md
DELETED
|
@@ -1,378 +0,0 @@
|
|
|
1
|
-
# Evolcore 0.5.0 迁移指南
|
|
2
|
-
|
|
3
|
-
> 版本:0.5.0
|
|
4
|
-
> 发布日期:2026-06-19
|
|
5
|
-
> 重大变更:配置系统 v3 重构 + 类型系统简化
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## 概述
|
|
10
|
-
|
|
11
|
-
0.5.0 版本对配置系统进行了重大重构,主要变更:
|
|
12
|
-
|
|
13
|
-
1. **删除 behavior.json** - 所有参数统一在 config.json
|
|
14
|
-
2. **删除 BehaviorConfig 类型** - 统一使用 AgentConfig/EffectiveAgentConfig
|
|
15
|
-
3. **删除 MergedAgentConfig 类型** - 统一使用 EffectiveAgentConfig
|
|
16
|
-
4. **简化覆盖链** - defaults → agent/config → relation/config
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
## 破坏性变更
|
|
21
|
-
|
|
22
|
-
### 1. behavior.json 已删除
|
|
23
|
-
|
|
24
|
-
**变更说明**:
|
|
25
|
-
- ❌ 不再有 `agents/<aid>/behavior.json`
|
|
26
|
-
- ❌ 不再有 `agents/<aid>/relations/<peerKey>/preferences.json`
|
|
27
|
-
- ✅ 所有参数统一在 `config.json`
|
|
28
|
-
|
|
29
|
-
**迁移步骤**:
|
|
30
|
-
|
|
31
|
-
#### 如果你有自定义的 behavior.json:
|
|
32
|
-
|
|
33
|
-
**原文件结构**:
|
|
34
|
-
```
|
|
35
|
-
agents/mybot.agent/
|
|
36
|
-
├── config.json # 身份、凭证、渠道
|
|
37
|
-
└── behavior.json # 模型、对话模式、权限
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
**新文件结构**:
|
|
41
|
-
```
|
|
42
|
-
agents/mybot.agent/
|
|
43
|
-
└── config.json # 所有参数统一
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
**手动合并示例**:
|
|
47
|
-
|
|
48
|
-
```json
|
|
49
|
-
// 原 config.json(身份信息)
|
|
50
|
-
{
|
|
51
|
-
"aid": "mybot.agent",
|
|
52
|
-
"owners": ["admin.user"],
|
|
53
|
-
"channels": [...]
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// 原 behavior.json(行为参数)
|
|
57
|
-
{
|
|
58
|
-
"active_baseagent": "claude",
|
|
59
|
-
"baseagents": {
|
|
60
|
-
"claude": { "model": "opus-4.8", "effort": "high" }
|
|
61
|
-
},
|
|
62
|
-
"chatmode": { "private": "proactive" }
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// 合并后的 config.json
|
|
66
|
-
{
|
|
67
|
-
"aid": "mybot.agent",
|
|
68
|
-
"owners": ["admin.user"],
|
|
69
|
-
"channels": [...],
|
|
70
|
-
"active_baseagent": "claude",
|
|
71
|
-
"baseagents": {
|
|
72
|
-
"claude": { "model": "opus-4.8", "effort": "high" }
|
|
73
|
-
},
|
|
74
|
-
"chatmode": { "private": "proactive" }
|
|
75
|
-
}
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
**自动迁移**:
|
|
79
|
-
- 启动时会自动检测并合并 behavior.json 到 config.json
|
|
80
|
-
- 迁移后 behavior.json 会被重命名为 `.migrated-to-config`
|
|
81
|
-
|
|
82
|
-
#### 如果你有关系级 preferences.json:
|
|
83
|
-
|
|
84
|
-
**原路径**:`agents/<aid>/relations/<peerKey>/preferences.json`
|
|
85
|
-
|
|
86
|
-
**新路径**:`agents/<aid>/relations/<peerKey>/config.json`
|
|
87
|
-
|
|
88
|
-
**迁移**:
|
|
89
|
-
- 自动迁移,将 preferences.json 合并到 config.json
|
|
90
|
-
- 原文件重命名为 `.migrated-to-config`
|
|
91
|
-
|
|
92
|
-
---
|
|
93
|
-
|
|
94
|
-
### 2. BehaviorConfig 类型已删除
|
|
95
|
-
|
|
96
|
-
**变更说明**:
|
|
97
|
-
- ❌ `BehaviorConfig` 接口已删除
|
|
98
|
-
- ✅ 使用 `AgentConfig`(存储层)或 `EffectiveAgentConfig`(运行时)
|
|
99
|
-
|
|
100
|
-
**如果你的代码引用了 BehaviorConfig**:
|
|
101
|
-
|
|
102
|
-
```typescript
|
|
103
|
-
// ❌ 旧代码
|
|
104
|
-
import type { BehaviorConfig } from 'evolcore/types';
|
|
105
|
-
|
|
106
|
-
function updateBehavior(config: BehaviorConfig) {
|
|
107
|
-
// ...
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// ✅ 新代码(完整配置)
|
|
111
|
-
import type { AgentConfig } from 'evolcore/types';
|
|
112
|
-
|
|
113
|
-
function updateBehavior(config: AgentConfig) {
|
|
114
|
-
// ...
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// ✅ 新代码(只需要部分字段)
|
|
118
|
-
import type { AgentConfig } from 'evolcore/types';
|
|
119
|
-
|
|
120
|
-
function updateBehavior(config: Partial<AgentConfig>) {
|
|
121
|
-
// ...
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// ✅ 新代码(运行时合并结果)
|
|
125
|
-
import type { EffectiveAgentConfig } from 'evolcore/types';
|
|
126
|
-
|
|
127
|
-
function getBehavior(): EffectiveAgentConfig {
|
|
128
|
-
// ...
|
|
129
|
-
}
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
**常见场景替换表**:
|
|
133
|
-
|
|
134
|
-
| 原用途 | 旧类型 | 新类型 |
|
|
135
|
-
|--------|--------|--------|
|
|
136
|
-
| 读取 agent 配置 | `BehaviorConfig` | `AgentConfig` |
|
|
137
|
-
| 读取关系级配置 | `BehaviorConfig` | `RelationConfig` |
|
|
138
|
-
| 运行时合并结果 | `BehaviorConfig` | `EffectiveAgentConfig` |
|
|
139
|
-
| 部分配置更新 | `Partial<BehaviorConfig>` | `Partial<AgentConfig>` |
|
|
140
|
-
| 只需要特定字段 | `Pick<BehaviorConfig, 'model' \| 'chatmode'>` | `Pick<AgentConfig, 'model' \| 'chatmode'>` |
|
|
141
|
-
|
|
142
|
-
---
|
|
143
|
-
|
|
144
|
-
### 3. MergedAgentConfig 类型已删除
|
|
145
|
-
|
|
146
|
-
**变更说明**:
|
|
147
|
-
- ❌ `MergedAgentConfig` 类型已删除
|
|
148
|
-
- ✅ 使用 `EffectiveAgentConfig`
|
|
149
|
-
|
|
150
|
-
**如果你的代码引用了 MergedAgentConfig**:
|
|
151
|
-
|
|
152
|
-
```typescript
|
|
153
|
-
// ❌ 旧代码
|
|
154
|
-
import type { MergedAgentConfig } from 'evolcore/types';
|
|
155
|
-
|
|
156
|
-
function processConfig(config: MergedAgentConfig) {
|
|
157
|
-
// ...
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// ✅ 新代码
|
|
161
|
-
import type { EffectiveAgentConfig } from 'evolcore/types';
|
|
162
|
-
|
|
163
|
-
function processConfig(config: EffectiveAgentConfig) {
|
|
164
|
-
// ...
|
|
165
|
-
}
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
**说明**:
|
|
169
|
-
- `MergedAgentConfig` 曾是 `AgentConfig & BehaviorConfig` 的合并类型
|
|
170
|
-
- v3 重构后简化为 `EffectiveAgentConfig` 的别名
|
|
171
|
-
- 现在直接使用 `EffectiveAgentConfig` 更清晰
|
|
172
|
-
|
|
173
|
-
---
|
|
174
|
-
|
|
175
|
-
### 4. mergeForAgent() 已弃用
|
|
176
|
-
|
|
177
|
-
**变更说明**:
|
|
178
|
-
- ⚠️ `mergeForAgent()` 标记为 `@deprecated`
|
|
179
|
-
- ✅ 使用 `ConfigManager.resolveEffective()`
|
|
180
|
-
|
|
181
|
-
**如果你的代码调用了 mergeForAgent**:
|
|
182
|
-
|
|
183
|
-
```typescript
|
|
184
|
-
// ❌ 旧代码
|
|
185
|
-
import { mergeForAgent, loadAgent, loadDefaults } from 'evolcore';
|
|
186
|
-
|
|
187
|
-
const agent = loadAgent('mybot.agent');
|
|
188
|
-
const defaults = loadDefaults();
|
|
189
|
-
const merged = mergeForAgent(agent, defaults);
|
|
190
|
-
|
|
191
|
-
// ✅ 新代码
|
|
192
|
-
import { resolveEffective } from 'evolcore/config/config-manager';
|
|
193
|
-
|
|
194
|
-
const effective = resolveEffective({ self: 'mybot.agent' });
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
**说明**:
|
|
198
|
-
- `mergeForAgent()` 仍可用但已弃用,计划 v2.2 删除
|
|
199
|
-
- `resolveEffective()` 是唯一的合并入口,支持完整覆盖链
|
|
200
|
-
|
|
201
|
-
---
|
|
202
|
-
|
|
203
|
-
## 新功能
|
|
204
|
-
|
|
205
|
-
### 1. 统一的配置覆盖链
|
|
206
|
-
|
|
207
|
-
**覆盖链(优先级从低到高)**:
|
|
208
|
-
```
|
|
209
|
-
defaults → agent/config → relation/config
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
**示例**:
|
|
213
|
-
|
|
214
|
-
```typescript
|
|
215
|
-
import { resolveEffective } from 'evolcore/config/config-manager';
|
|
216
|
-
|
|
217
|
-
// Agent 级配置
|
|
218
|
-
const agentConfig = resolveEffective({
|
|
219
|
-
self: 'mybot.agent'
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
// 关系级配置(针对特定用户)
|
|
223
|
-
const relationConfig = resolveEffective({
|
|
224
|
-
self: 'mybot.agent',
|
|
225
|
-
peerKey: 'user123.user@channel'
|
|
226
|
-
});
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
### 2. 角色级覆盖(新增)
|
|
230
|
-
|
|
231
|
-
**在 config.json 中定义角色**:
|
|
232
|
-
|
|
233
|
-
```json
|
|
234
|
-
{
|
|
235
|
-
"aid": "mybot.agent",
|
|
236
|
-
"active_baseagent": "claude",
|
|
237
|
-
"baseagents": {
|
|
238
|
-
"claude": { "model": "sonnet-4.6" }
|
|
239
|
-
},
|
|
240
|
-
"roles": {
|
|
241
|
-
"power-user": {
|
|
242
|
-
"baseagents": {
|
|
243
|
-
"claude": { "model": "opus-4.8", "effort": "high" }
|
|
244
|
-
},
|
|
245
|
-
"permissionMode": "owner"
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
**运行时解析**:
|
|
252
|
-
|
|
253
|
-
```typescript
|
|
254
|
-
import { resolveEffective } from 'evolcore/config/config-manager';
|
|
255
|
-
|
|
256
|
-
// 普通用户
|
|
257
|
-
const normalConfig = resolveEffective({
|
|
258
|
-
self: 'mybot.agent',
|
|
259
|
-
peerKey: 'user1.user@channel'
|
|
260
|
-
});
|
|
261
|
-
// → model: "sonnet-4.6"
|
|
262
|
-
|
|
263
|
-
// Power user
|
|
264
|
-
const powerConfig = resolveEffective({
|
|
265
|
-
self: 'mybot.agent',
|
|
266
|
-
peerKey: 'user2.user@channel',
|
|
267
|
-
role: 'power-user'
|
|
268
|
-
});
|
|
269
|
-
// → model: "opus-4.8", effort: "high"
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
---
|
|
273
|
-
|
|
274
|
-
## 非破坏性变更
|
|
275
|
-
|
|
276
|
-
### 1. 配置文件格式兼容
|
|
277
|
-
|
|
278
|
-
**旧格式仍然支持**:
|
|
279
|
-
- 如果只有 config.json(身份字段),仍然有效
|
|
280
|
-
- 如果有 behavior.json,会自动合并
|
|
281
|
-
- 如果有 preferences.json,会自动迁移
|
|
282
|
-
|
|
283
|
-
### 2. API 保持兼容
|
|
284
|
-
|
|
285
|
-
**这些函数签名未变**:
|
|
286
|
-
- `loadAgent(aid)` - 返回 AgentConfig
|
|
287
|
-
- `loadDefaults()` - 返回 DefaultsConfig
|
|
288
|
-
- `loadAllAgents()` - 返回 AgentConfig[]
|
|
289
|
-
|
|
290
|
-
**这些属性未变**:
|
|
291
|
-
- `EvolAgent.config` - 返回运行时配置(类型从 MergedAgentConfig 改为 EffectiveAgentConfig,字段不变)
|
|
292
|
-
- `AgentInfo.config` - 同上
|
|
293
|
-
|
|
294
|
-
---
|
|
295
|
-
|
|
296
|
-
## 检查清单
|
|
297
|
-
|
|
298
|
-
迁移到 0.5.0 时,检查以下内容:
|
|
299
|
-
|
|
300
|
-
### 配置文件
|
|
301
|
-
|
|
302
|
-
- [ ] 确认 behavior.json 已自动合并到 config.json
|
|
303
|
-
- [ ] 确认 preferences.json 已自动迁移到 config.json
|
|
304
|
-
- [ ] 检查 config.json 是否包含所有必要字段
|
|
305
|
-
|
|
306
|
-
### TypeScript 代码
|
|
307
|
-
|
|
308
|
-
- [ ] 将 `BehaviorConfig` 替换为 `AgentConfig` 或 `EffectiveAgentConfig`
|
|
309
|
-
- [ ] 将 `MergedAgentConfig` 替换为 `EffectiveAgentConfig`
|
|
310
|
-
- [ ] 将 `mergeForAgent()` 替换为 `resolveEffective()`
|
|
311
|
-
- [ ] 运行 TypeScript 编译检查类型错误
|
|
312
|
-
|
|
313
|
-
### 运行时测试
|
|
314
|
-
|
|
315
|
-
- [ ] 启动 agent,确认配置正确加载
|
|
316
|
-
- [ ] 测试模型切换功能
|
|
317
|
-
- [ ] 测试对话模式切换
|
|
318
|
-
- [ ] 测试关系级配置覆盖
|
|
319
|
-
|
|
320
|
-
---
|
|
321
|
-
|
|
322
|
-
## 常见问题
|
|
323
|
-
|
|
324
|
-
### Q1: 我的 behavior.json 会丢失吗?
|
|
325
|
-
|
|
326
|
-
**A**: 不会。
|
|
327
|
-
- 自动迁移会合并到 config.json
|
|
328
|
-
- 原 behavior.json 重命名为 `.migrated-to-config`
|
|
329
|
-
- 如果合并失败,会保留原文件并记录错误日志
|
|
330
|
-
|
|
331
|
-
### Q2: 我需要手动更新配置文件吗?
|
|
332
|
-
|
|
333
|
-
**A**: 不需要。
|
|
334
|
-
- 启动时自动检测并迁移
|
|
335
|
-
- 迁移成功后自动保存
|
|
336
|
-
- 只需确认迁移日志无错误
|
|
337
|
-
|
|
338
|
-
### Q3: 类型错误如何修复?
|
|
339
|
-
|
|
340
|
-
**A**: 按上述替换表修改:
|
|
341
|
-
```typescript
|
|
342
|
-
// BehaviorConfig → AgentConfig / EffectiveAgentConfig
|
|
343
|
-
// MergedAgentConfig → EffectiveAgentConfig
|
|
344
|
-
```
|
|
345
|
-
|
|
346
|
-
### Q4: mergeForAgent() 什么时候会删除?
|
|
347
|
-
|
|
348
|
-
**A**: 计划 v2.2 删除。
|
|
349
|
-
- 当前版本仍可用(已弃用)
|
|
350
|
-
- 建议尽快迁移到 `resolveEffective()`
|
|
351
|
-
|
|
352
|
-
### Q5: 如何回退到旧版本?
|
|
353
|
-
|
|
354
|
-
**A**:
|
|
355
|
-
```bash
|
|
356
|
-
npm install evolcore@0.4.x
|
|
357
|
-
```
|
|
358
|
-
- 如果已迁移,需要手动还原配置文件
|
|
359
|
-
- 建议迁移前备份 agents/ 目录
|
|
360
|
-
|
|
361
|
-
---
|
|
362
|
-
|
|
363
|
-
## 获取帮助
|
|
364
|
-
|
|
365
|
-
如果遇到迁移问题:
|
|
366
|
-
|
|
367
|
-
1. **查看日志**:`~/.evolcore/logs/boot.log`
|
|
368
|
-
2. **查看文档**:`docs/config/`
|
|
369
|
-
3. **提交 Issue**:https://github.com/your-org/evolcore/issues
|
|
370
|
-
|
|
371
|
-
---
|
|
372
|
-
|
|
373
|
-
## 相关文档
|
|
374
|
-
|
|
375
|
-
- [配置系统概览](docs/config/01-overview.md)
|
|
376
|
-
- [合并规则](docs/config/02-merge-rules.md)
|
|
377
|
-
- [配置 Schema](docs/config/03-schema.md)
|
|
378
|
-
- [BehaviorConfig 删除报告](docs/config/behaviorconfig-mergedconfig-removal-completion.md)
|
package/ROLE_ACCESS_CONTROL.md
DELETED
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
# 角色访问控制功能实现总结
|
|
2
|
-
|
|
3
|
-
## 新增功能
|
|
4
|
-
|
|
5
|
-
### 1. 默认角色 (defaultRole)
|
|
6
|
-
- **位置**: 全局配置 (`roles.json` 顶层字段)
|
|
7
|
-
- **默认值**: `'anonymous'`
|
|
8
|
-
- **语义**: 对端 AID 首次访问时,若不在 `owners/admins/members` 名单中,使用此角色作为兜底
|
|
9
|
-
- **UI**: ecweb 角色定义页面顶部下拉选择器,change 时自动保存
|
|
10
|
-
|
|
11
|
-
### 2. 是否允许访问 (allowAccess)
|
|
12
|
-
- **位置**: 每个角色定义的顶层字段 (与 `description`/`permissions` 同级)
|
|
13
|
-
- **默认值**:
|
|
14
|
-
- `anonymous`: `false` (拒绝访问)
|
|
15
|
-
- 其他角色 (`owner/admin/member/guest`): `true` (允许访问)
|
|
16
|
-
- **语义**: 当角色的 `allowAccess=false` 时,该角色用户访问 agent 会被直接拦截
|
|
17
|
-
- **拦截行为**: 返回系统错误消息 "暂无权限访问本 agent,请联系 agent 管理员授权访问"
|
|
18
|
-
- **UI**: ecweb 角色编辑/新建弹窗中,描述下方的下拉选择器 (允许 true / 拒绝 false)
|
|
19
|
-
|
|
20
|
-
## 实现架构
|
|
21
|
-
|
|
22
|
-
### Backend 改动
|
|
23
|
-
|
|
24
|
-
#### 1. Schema 升级 (v1 → v2)
|
|
25
|
-
- `kits/schemas/roles.schema.2.json` — 新增 `defaultRole` (top-level) 和 `allowAccess` (per-role)
|
|
26
|
-
- `kits/schemas/_meta.json` — currentVersion 更新为 2
|
|
27
|
-
- **迁移逻辑** (`src/config/config-manager.ts`):
|
|
28
|
-
- `migrateRolesV1toV2()` — 直接升版本号,新字段由 merge 时从 builtin 补全 (overlay 模式)
|
|
29
|
-
|
|
30
|
-
#### 2. 类型定义 (`src/types.ts`)
|
|
31
|
-
```typescript
|
|
32
|
-
export interface RolesConfig {
|
|
33
|
-
$schema_version: number;
|
|
34
|
-
defaultRole?: string; // 新增
|
|
35
|
-
roles: Record<string, RoleDefinition>;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export interface RoleDefinition {
|
|
39
|
-
description: string;
|
|
40
|
-
allowAccess?: boolean; // 新增
|
|
41
|
-
permissions: Record<string, FieldPermission>;
|
|
42
|
-
}
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
#### 3. 内置配置 (`src/config/roles.ts`)
|
|
46
|
-
- `getBuiltinRolesConfig()` 升级为 `$schema_version: 2`
|
|
47
|
-
- 添加 `defaultRole: 'anonymous'`
|
|
48
|
-
- 每个角色添加 `allowAccess` 字段 (owner/admin/member/guest 为 `true`, anonymous 为 `false`)
|
|
49
|
-
|
|
50
|
-
#### 4. 角色解析器 (`src/config/role-resolver.ts`)
|
|
51
|
-
- `resolveUserRole()` 返回类型改为 `string` (支持自定义角色名)
|
|
52
|
-
- 移除 `isAuthenticated()` 判断,改为直接使用 `getDefaultRole()` 作为兜底
|
|
53
|
-
- **新增** `getDefaultRole()` — 从 roles.json 读取 `defaultRole` 字段
|
|
54
|
-
- **新增** `checkRoleAccess(role: string): boolean` — 读取该角色的 `allowAccess` 配置
|
|
55
|
-
|
|
56
|
-
#### 5. 合并/Diff 逻辑 (`src/config/roles-merge.ts`)
|
|
57
|
-
- `mergeRolesConfig()` — 合并 `defaultRole` (overlay 优先) 和每个角色的 `allowAccess`
|
|
58
|
-
- `diffRolesConfig()` — 比对 `defaultRole` 和 `allowAccess`,仅写入改动
|
|
59
|
-
|
|
60
|
-
#### 6. 访问控制拦截 (`src/core/message/response-engine.ts`)
|
|
61
|
-
- `processMessage()` 入口处,在 `resolveSession()` 之后立即检查
|
|
62
|
-
- 调用 `checkRoleAccess(userRole)`,为 `false` 时:
|
|
63
|
-
1. 记录 warn 日志
|
|
64
|
-
2. 通过 `adapter.send()` 回复 `system.error` 类型消息
|
|
65
|
-
3. `return` 终止处理,不进入后续流程
|
|
66
|
-
|
|
67
|
-
### Frontend 改动 (ecweb)
|
|
68
|
-
|
|
69
|
-
#### 1. HTML 结构 (`ecweb/src/static/index.html`)
|
|
70
|
-
- 新增 `.role-default-selector` 区块 (在 header 和 grid 之间)
|
|
71
|
-
- 包含 `<select id="default-role-select">` 和提示文案
|
|
72
|
-
|
|
73
|
-
#### 2. JavaScript (`ecweb/src/static/app.js`)
|
|
74
|
-
- `renderRoleDefinitions()` — 调用 `renderDefaultRoleSelector(data)` 填充下拉框
|
|
75
|
-
- **新增** `renderDefaultRoleSelector()`:
|
|
76
|
-
- 填充所有角色为选项
|
|
77
|
-
- 绑定 `onchange` 事件 → 读取完整配置 → 更新 `defaultRole` → PUT 写回
|
|
78
|
-
- `showRoleEditModal()` / `showNewRoleModal()` — 在 description 后添加 `allowAccess` 下拉
|
|
79
|
-
- `saveRoleEdit()` — 收集 `allowAccess` 值 (转为真布尔), 写入 `updates` 对象
|
|
80
|
-
|
|
81
|
-
#### 3. CSS (`ecweb/src/static/style.css`)
|
|
82
|
-
- 新增 `.role-default-selector` / `.role-default-label` 样式
|
|
83
|
-
- 原有按钮样式已是黑边框黑字 (`var(--fg)` / `var(--border)`),无需修改
|
|
84
|
-
|
|
85
|
-
## 配置示例
|
|
86
|
-
|
|
87
|
-
### roles.json (用户 overlay)
|
|
88
|
-
```json
|
|
89
|
-
{
|
|
90
|
-
"$schema_version": 2,
|
|
91
|
-
"defaultRole": "guest",
|
|
92
|
-
"roles": {
|
|
93
|
-
"anonymous": {
|
|
94
|
-
"description": "匿名用户,完全未认证,极度受限",
|
|
95
|
-
"allowAccess": false
|
|
96
|
-
},
|
|
97
|
-
"guest": {
|
|
98
|
-
"description": "访客,只读权限,有身份但未授权",
|
|
99
|
-
"allowAccess": true
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
### 内置基线 (builtin)
|
|
106
|
-
```javascript
|
|
107
|
-
{
|
|
108
|
-
$schema_version: 2,
|
|
109
|
-
defaultRole: 'anonymous',
|
|
110
|
-
roles: {
|
|
111
|
-
owner: { allowAccess: true, ... },
|
|
112
|
-
admin: { allowAccess: true, ... },
|
|
113
|
-
member: { allowAccess: true, ... },
|
|
114
|
-
guest: { allowAccess: true, ... },
|
|
115
|
-
anonymous: { allowAccess: false, ... }
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
## 升级路径
|
|
121
|
-
|
|
122
|
-
1. **v1 → v2 自动迁移**:
|
|
123
|
-
- 读取 v1 roles.json 时,`migrateRolesV1toV2()` 自动升版本号
|
|
124
|
-
- `defaultRole` 和 `allowAccess` 字段从 builtin 继承 (overlay 为空时)
|
|
125
|
-
- 原有用户改动 (permissions/description) 完整保留
|
|
126
|
-
|
|
127
|
-
2. **向后兼容**:
|
|
128
|
-
- `defaultRole` 缺失时默认 `'anonymous'` (原有行为)
|
|
129
|
-
- `allowAccess` 缺失时默认 `true` (除 anonymous 为 `false`)
|
|
130
|
-
- 旧代码不读这两个字段时,功能降级但不报错
|
|
131
|
-
|
|
132
|
-
## 测试要点
|
|
133
|
-
|
|
134
|
-
1. **默认角色生效**:
|
|
135
|
-
- 清空某 agent 的 owners/admins/members
|
|
136
|
-
- 对端 AID 访问时,角色应为 `roles.json` 中的 `defaultRole`
|
|
137
|
-
|
|
138
|
-
2. **访问控制拦截**:
|
|
139
|
-
- 设置某角色 `allowAccess: false`
|
|
140
|
-
- 将用户加入该角色 (如 guest)
|
|
141
|
-
- 用户访问时应收到 "暂无权限" 系统错误,后续流程不触发
|
|
142
|
-
|
|
143
|
-
3. **ecweb UI**:
|
|
144
|
-
- 默认角色下拉能正常切换并保存
|
|
145
|
-
- 编辑角色时,`allowAccess` 下拉能正确读取/保存
|
|
146
|
-
- 保存按钮为黑边框黑字 (非白色)
|
|
147
|
-
|
|
148
|
-
4. **Schema 迁移**:
|
|
149
|
-
- 备份旧 roles.json (v1)
|
|
150
|
-
- 启动新版本,读取时自动升级为 v2
|
|
151
|
-
- 原有改动不丢失,新字段从 builtin 补全
|
|
152
|
-
|
|
153
|
-
## 文件清单
|
|
154
|
-
|
|
155
|
-
### Backend
|
|
156
|
-
- `kits/schemas/roles.schema.2.json` (新增)
|
|
157
|
-
- `kits/schemas/_meta.json` (修改 - 版本号)
|
|
158
|
-
- `src/types.ts` (修改 - RolesConfig/RoleDefinition)
|
|
159
|
-
- `src/config/roles.ts` (修改 - builtin 配置)
|
|
160
|
-
- `src/config/role-resolver.ts` (修改 - 添加 checkRoleAccess)
|
|
161
|
-
- `src/config/roles-merge.ts` (修改 - merge/diff 逻辑)
|
|
162
|
-
- `src/config/config-manager.ts` (修改 - 迁移函数)
|
|
163
|
-
- `src/core/message/response-engine.ts` (修改 - 访问拦截)
|
|
164
|
-
|
|
165
|
-
### Frontend (ecweb)
|
|
166
|
-
- `ecweb/src/static/index.html` (修改 - 默认角色选择器)
|
|
167
|
-
- `ecweb/src/static/app.js` (修改 - render/save 逻辑)
|
|
168
|
-
- `ecweb/src/static/style.css` (修改 - 样式)
|
|
169
|
-
|
|
170
|
-
---
|
|
171
|
-
|
|
172
|
-
**实现完成时间**: 2026-06-25
|
|
173
|
-
**Schema 版本**: roles v2
|
|
174
|
-
**向后兼容**: ✅ (v1 自动迁移,字段缺失时使用默认值)
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
import { randomInt } from 'crypto';
|
|
2
|
-
import { isValidAid } from '../aun/aid/validation.js';
|
|
3
|
-
import { bindContactAlias } from '../config/contact-book.js';
|
|
4
|
-
export const CONTACT_BIND_CODE_TTL_MS = 10 * 60 * 1000;
|
|
5
|
-
export const CONTACT_BIND_MAX_FAILED_ATTEMPTS = 5;
|
|
6
|
-
/** In-memory, one-time channel identity proof used before writing a Contact alias. */
|
|
7
|
-
export class ContactBindCodeRegistry {
|
|
8
|
-
options;
|
|
9
|
-
pending = new Map();
|
|
10
|
-
constructor(options) {
|
|
11
|
-
this.options = options;
|
|
12
|
-
}
|
|
13
|
-
register(req) {
|
|
14
|
-
const selfAid = String(req.selfAid || '').trim();
|
|
15
|
-
const channelName = String(req.channelName || '').trim();
|
|
16
|
-
const primaryId = String(req.primaryId || '').trim();
|
|
17
|
-
const now = req.now ?? Date.now();
|
|
18
|
-
const code = req.code ? String(req.code).trim() : generateBindCode();
|
|
19
|
-
if (!isValidAid(selfAid))
|
|
20
|
-
return { ok: false, error: `invalid selfAid: ${req.selfAid}` };
|
|
21
|
-
if (!channelName)
|
|
22
|
-
return { ok: false, error: 'missing channelName' };
|
|
23
|
-
if (!isValidAid(primaryId))
|
|
24
|
-
return { ok: false, error: `invalid primaryId: ${req.primaryId}` };
|
|
25
|
-
if (!/^\d{6}$/.test(code))
|
|
26
|
-
return { ok: false, error: 'binding code must be 6 digits' };
|
|
27
|
-
const key = pendingBindKey(selfAid, channelName);
|
|
28
|
-
const replaced = this.pending.has(key);
|
|
29
|
-
const item = {
|
|
30
|
-
selfAid,
|
|
31
|
-
channelName,
|
|
32
|
-
primaryId,
|
|
33
|
-
code,
|
|
34
|
-
createdAt: now,
|
|
35
|
-
expiresAt: now + CONTACT_BIND_CODE_TTL_MS,
|
|
36
|
-
failedAttempts: 0,
|
|
37
|
-
maxFailedAttempts: CONTACT_BIND_MAX_FAILED_ATTEMPTS,
|
|
38
|
-
};
|
|
39
|
-
this.pending.set(key, item);
|
|
40
|
-
return { ok: true, code, expiresAt: item.expiresAt, replaced };
|
|
41
|
-
}
|
|
42
|
-
handle(ctx) {
|
|
43
|
-
if (ctx.channelType !== this.options.channelType)
|
|
44
|
-
return { handled: false };
|
|
45
|
-
const selfAid = String(ctx.selfAid || '').trim();
|
|
46
|
-
const channelName = String(ctx.channelName || '').trim();
|
|
47
|
-
if (!selfAid || !channelName)
|
|
48
|
-
return { handled: false };
|
|
49
|
-
const key = pendingBindKey(selfAid, channelName);
|
|
50
|
-
const item = this.pending.get(key);
|
|
51
|
-
if (!item)
|
|
52
|
-
return { handled: false };
|
|
53
|
-
const now = ctx.now ?? Date.now();
|
|
54
|
-
if (now >= item.expiresAt) {
|
|
55
|
-
this.pending.delete(key);
|
|
56
|
-
return {
|
|
57
|
-
handled: true,
|
|
58
|
-
status: 'expired',
|
|
59
|
-
remainingAttempts: 0,
|
|
60
|
-
reply: `${this.options.displayName}身份绑定码已超时,本次绑定失败。请重新执行 ${this.options.initCommand} 并再次绑定。`,
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
if (ctx.chatType !== 'private')
|
|
64
|
-
return { handled: false };
|
|
65
|
-
const input = String(ctx.content ?? '').trim();
|
|
66
|
-
if (!/^\d{6}$/.test(input)) {
|
|
67
|
-
return {
|
|
68
|
-
handled: true,
|
|
69
|
-
status: 'format',
|
|
70
|
-
reply: '请直接发送 6 位数字绑定码。',
|
|
71
|
-
remainingAttempts: item.maxFailedAttempts - item.failedAttempts,
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
if (input !== item.code) {
|
|
75
|
-
item.failedAttempts += 1;
|
|
76
|
-
const remaining = Math.max(0, item.maxFailedAttempts - item.failedAttempts);
|
|
77
|
-
if (remaining === 0) {
|
|
78
|
-
this.pending.delete(key);
|
|
79
|
-
return {
|
|
80
|
-
handled: true,
|
|
81
|
-
status: 'failed',
|
|
82
|
-
remainingAttempts: 0,
|
|
83
|
-
reply: `绑定码无效,本次${this.options.displayName}身份绑定失败。请重新执行 ${this.options.initCommand} 并再次绑定。`,
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
return {
|
|
87
|
-
handled: true,
|
|
88
|
-
status: 'wrong-code',
|
|
89
|
-
remainingAttempts: remaining,
|
|
90
|
-
reply: '绑定码错误,请重新发送 6 位数字绑定码。',
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
const actorId = String(ctx.actorId || '').trim();
|
|
94
|
-
if (!actorId) {
|
|
95
|
-
return {
|
|
96
|
-
handled: true,
|
|
97
|
-
status: 'missing-actor',
|
|
98
|
-
remainingAttempts: item.maxFailedAttempts - item.failedAttempts,
|
|
99
|
-
reply: `无法识别当前${this.options.displayName}发送者身份,未建立绑定。请重新发送绑定码或重新执行绑定流程。`,
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
try {
|
|
103
|
-
bindContactAlias(item.selfAid, item.primaryId, this.options.channelType, actorId, item.channelName);
|
|
104
|
-
this.pending.delete(key);
|
|
105
|
-
return {
|
|
106
|
-
handled: true,
|
|
107
|
-
status: 'bound',
|
|
108
|
-
reply: `${this.options.displayName}身份绑定成功:${item.channelName}:${encodeURIComponent(actorId)} -> ${item.primaryId}`,
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
catch (error) {
|
|
112
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
113
|
-
return {
|
|
114
|
-
handled: true,
|
|
115
|
-
status: 'write-failed',
|
|
116
|
-
remainingAttempts: item.maxFailedAttempts - item.failedAttempts,
|
|
117
|
-
reply: `${this.options.displayName}身份绑定写入失败:${message}`,
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
get(selfAid, channelName) {
|
|
122
|
-
const item = this.pending.get(pendingBindKey(selfAid, channelName));
|
|
123
|
-
return item ? { ...item } : null;
|
|
124
|
-
}
|
|
125
|
-
clear() {
|
|
126
|
-
this.pending.clear();
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
function generateBindCode() {
|
|
130
|
-
return String(randomInt(0, 1_000_000)).padStart(6, '0');
|
|
131
|
-
}
|
|
132
|
-
function pendingBindKey(selfAid, channelName) {
|
|
133
|
-
return `${String(selfAid || '').trim()}\u0000${String(channelName || '').trim()}`;
|
|
134
|
-
}
|