Skip to content

Commit 40faf98

Browse files
authored
Merge pull request #3 from echoVic/refactor/zustand-migration
Refactor/zustand migration
2 parents 2efaac7 + 073bf7d commit 40faf98

128 files changed

Lines changed: 8507 additions & 5226 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/settings.local.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,9 @@
6363
"Bash(timeout 60 node:*)",
6464
"Bash(gtimeout 60 node:*)",
6565
"Bash(pnpm approve-builds:*)",
66-
"Bash(git reset:*)"
66+
"Bash(git reset:*)",
67+
"Bash(cloc:*)",
68+
"Bash(grep:*)"
6769
],
6870
"deny": [],
6971
"ask": [],

.github/workflows/ci.yml

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,11 @@ jobs:
2525
node-version: ${{ matrix.node-version }}
2626
cache: 'pnpm'
2727

28-
- name: Setup pnpm
29-
uses: pnpm/action-setup@v4
30-
with:
31-
version: 8
28+
- name: Enable corepack
29+
run: corepack enable
30+
31+
- name: Install pnpm
32+
run: corepack prepare pnpm@8 --activate
3233

3334
- name: Install dependencies
3435
run: pnpm install
@@ -59,10 +60,11 @@ jobs:
5960
node-version: '20.x'
6061
cache: 'pnpm'
6162

62-
- name: Setup pnpm
63-
uses: pnpm/action-setup@v4
64-
with:
65-
version: 8
63+
- name: Enable corepack
64+
run: corepack enable
65+
66+
- name: Install pnpm
67+
run: corepack prepare pnpm@8 --activate
6668

6769
- name: Install dependencies
6870
run: pnpm install
@@ -89,10 +91,11 @@ jobs:
8991
node-version: ${{ matrix.node-version }}
9092
cache: 'pnpm'
9193

92-
- name: Setup pnpm
93-
uses: pnpm/action-setup@v4
94-
with:
95-
version: 8
94+
- name: Enable corepack
95+
run: corepack enable
96+
97+
- name: Install pnpm
98+
run: corepack prepare pnpm@8 --activate
9699

97100
- name: Install dependencies
98101
run: pnpm install
@@ -105,4 +108,4 @@ jobs:
105108

106109
env:
107110
CI: true
108-
NODE_ENV: test
111+
NODE_ENV: test

BLADE.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ always respond in Chinese
2020
### 1. Agent 系统 (`src/agent/`)
2121
- **Agent.ts**: 核心 Agent 类,无状态设计,负责 LLM 交互和工具执行
2222
- **ExecutionEngine.ts**: 执行引擎,处理工具调用循环
23-
- **LoopDetectionService.ts**: 循环检测,防止无限循环
23+
- **Agent.ts**: Agentic Loop 主循环,使用 `maxTurns` + 硬性轮次上限 `SAFETY_LIMIT = 100` 防止无限循环(旧版 LoopDetectionService 已移除)
2424
- **subagents/**: 子 Agent 注册表,支持任务分解
2525

2626
### 2. Hook 系统 (`src/hooks/`)
@@ -242,4 +242,4 @@ src/
242242
├── tools/ # 工具系统
243243
├── ui/ # UI 组件
244244
└── utils/ # 工具函数
245-
```
245+
```

CLAUDE.md

Lines changed: 145 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ Root (blade-code)
2828
│ ├── security/ # 安全管理
2929
│ ├── services/ # 共享服务层
3030
│ ├── slash-commands/ # 内置斜杠命令
31-
│ ├── telemetry/ # 遥测和监控
31+
│ ├── telemetry/ # 遥测和监控(历史目录,当前实现中已不再使用)
3232
│ ├── tools/ # 工具系统
3333
│ │ ├── builtin/ # 内置工具(Read/Write/Bash等)
3434
│ │ ├── execution/ # 执行管道
@@ -96,7 +96,7 @@ Root (blade-code)
9696
- 静态工厂方法 `Agent.create()` 用于创建和初始化实例
9797
- 每次命令可创建新 Agent 实例(用完即弃)
9898
- 通过 `ExecutionEngine` 处理工具执行流程
99-
- 通过 `LoopDetectionService` 防止无限循环(三层检测机制
99+
- **安全保障**: 通过 `maxTurns` + 硬性轮次上限 `SAFETY_LIMIT = 100` 控制循环(已移除 LoopDetectionService,避免与系统提示冲突
100100

101101
- **SessionContext** ([src/ui/contexts/SessionContext.tsx](src/ui/contexts/SessionContext.tsx)): 会话状态管理
102102
- 维护全局唯一 `sessionId`
@@ -129,12 +129,6 @@ Root (blade-code)
129129
- Discovery → Permission (Zod验证+默认值) → Confirmation → Execution → Formatting
130130
- 事件驱动架构,支持监听各阶段事件
131131
- 自动记录执行历史
132-
- **LoopDetectionService** ([src/agent/LoopDetectionService.ts](src/agent/LoopDetectionService.ts)): 三层循环检测系统
133-
- **层1**: 工具调用循环检测(MD5 哈希 + 动态阈值)
134-
- **层2**: 内容循环检测(滑动窗口 + 动态相似度)
135-
- **层3**: LLM 智能检测(认知循环分析)
136-
- 支持白名单工具、Plan 模式跳过内容检测
137-
- 详见: [循环检测系统文档](docs/development/implementation/loop-detection-system.md)
138132
- **PromptBuilder** ([src/prompts/](src/prompts/)): 提示模板管理和构建
139133
- **ContextManager** ([src/context/ContextManager.ts](src/context/ContextManager.ts)): 上下文管理系统
140134
- **JSONL 格式**: 追加式存储,每行一个 JSON 对象
@@ -192,6 +186,149 @@ Blade 提供完整的 Markdown 渲染支持,包含以下组件:
192186
- 用户文档:[docs/public/guides/markdown-support.md](docs/public/guides/markdown-support.md)
193187
- 开发者文档:[docs/development/implementation/markdown-renderer.md](docs/development/implementation/markdown-renderer.md)
194188

189+
## State Management Architecture
190+
191+
### Zustand Store 设计
192+
193+
Blade 使用 **Zustand** 作为全局状态管理库,采用 **单一数据源 (SSOT)** 架构:
194+
195+
**核心原则**
196+
- **Store 是唯一读取源** - 所有组件和服务从 Store 读取状态
197+
- **vanilla.ts actions 是唯一写入入口** - 自动同步内存 + 持久化
198+
- **ConfigManager 仅用于 Bootstrap** - 初始化时加载配置文件
199+
- **ConfigService 负责持久化** - 运行时写入配置文件
200+
201+
**架构图**
202+
```
203+
Bootstrap (启动时):
204+
ConfigManager.initialize() → 返回 BladeConfig → Store.setConfig()
205+
206+
Runtime (运行时):
207+
UI/Agent → vanilla.ts actions → Store (内存SSOT)
208+
209+
ConfigService (持久化到 config.json/settings.json)
210+
```
211+
212+
### 状态管理最佳实践
213+
214+
**✅ 推荐:从 Store 读取**
215+
```typescript
216+
import { getConfig, getCurrentModel } from '../store/vanilla.js';
217+
218+
const config = getConfig(); // 读取完整配置
219+
const model = getCurrentModel(); // 读取当前模型
220+
```
221+
222+
**✅ 推荐:通过 actions 写入**
223+
```typescript
224+
import { configActions } from '../store/vanilla.js';
225+
226+
// 自动同步内存 + 持久化
227+
await configActions().addModel({...});
228+
await configActions().setPermissionMode('yolo');
229+
```
230+
231+
**❌ 避免:直接调用 ConfigManager**
232+
```typescript
233+
// ❌ 错误:绕过 Store,导致数据不一致
234+
const configManager = ConfigManager.getInstance();
235+
await configManager.addModel({...}); // Store 未更新!
236+
```
237+
238+
**React 组件订阅**
239+
```typescript
240+
// ✅ 使用选择器(精准订阅)
241+
import { useCurrentModel, usePermissionMode } from '../store/selectors/index.js';
242+
243+
const model = useCurrentModel();
244+
const mode = usePermissionMode();
245+
246+
// ✅ 组合选择器使用 useShallow 优化
247+
import { useShallow } from 'zustand/react/shallow';
248+
249+
const { field1, field2 } = useBladeStore(
250+
useShallow((state) => ({
251+
field1: state.slice.field1,
252+
field2: state.slice.field2,
253+
}))
254+
);
255+
```
256+
257+
### Store 初始化规则
258+
259+
**⚠️ 关键规则**:任何调用 `configActions()` 或读取 `getConfig()` 的代码前,必须确保 Store 已初始化。
260+
261+
**统一防御点(推荐)**
262+
```typescript
263+
import { ensureStoreInitialized } from '../store/vanilla.js';
264+
265+
// 在执行任何依赖 Store 的逻辑前
266+
await ensureStoreInitialized();
267+
```
268+
269+
**`ensureStoreInitialized()` 特性**
270+
-**幂等**:已初始化直接返回(性能无负担)
271+
-**并发安全**:同一时刻只初始化一次(共享 Promise)
272+
-**失败重试**:初始化失败后,下次调用会重新尝试
273+
-**明确报错**:初始化失败抛出详细错误信息
274+
275+
**已添加防御的路径**
276+
| 路径 | 防御点 | 说明 |
277+
|------|--------|------|
278+
| CLI 命令 | `middleware.ts` | 初始化失败会退出并报错 |
279+
| Slash Commands | `useCommandHandler.ts` | 执行前统一调用 `ensureStoreInitialized()` |
280+
| Agent 创建 | `Agent.create()` | 内置防御性检查 |
281+
| Config Actions | 各方法内部 | 检查 `if (!config) throw` |
282+
283+
**⚠️ 竞态风险**
284+
- UI 初始化过程中用户立即输入命令
285+
- 多个 slash command 并发执行
286+
- 非 UI 场景(测试/脚本/print mode)复用
287+
288+
**✅ 推荐模式**
289+
```typescript
290+
// Slash command 执行前
291+
if (isSlashCommand(command)) {
292+
await ensureStoreInitialized(); // 统一防御点
293+
const result = await executeSlashCommand(command, context);
294+
}
295+
296+
// CLI 子命令执行前
297+
export const myCommand: CommandModule = {
298+
handler: async (argv) => {
299+
await ensureStoreInitialized(); // 防御性检查
300+
const config = getConfig();
301+
// ... 使用 config
302+
}
303+
};
304+
```
305+
306+
**❌ 避免模式**
307+
```typescript
308+
// ❌ 错误:假设已初始化
309+
const config = getConfig();
310+
if (!config) {
311+
// 太迟了,某些路径可能已经踩坑
312+
}
313+
314+
// ❌ 错误:静默吞掉初始化失败
315+
try {
316+
await ensureStoreInitialized();
317+
} catch (error) {
318+
console.warn('初始化失败,继续执行'); // 危险!
319+
}
320+
```
321+
322+
### Store 初始化机制
323+
324+
三层初始化防护:
325+
326+
1. **UI 路径**`App.tsx` → useEffect 初始化 Store
327+
2. **CLI 路径**`middleware.ts` → loadConfiguration 初始化 Store
328+
3. **防御路径**`Agent.create()` → ensureStoreInitialized() 兜底
329+
330+
详见:[Store 与 Config 架构统一文档](docs/development/implementation/store-config-unification.md)
331+
195332
## Slash Commands
196333

197334
Blade 提供内置的斜杠命令系统,用于执行特定的系统操作。所有 slash 命令实现位于 [src/slash-commands/](src/slash-commands/)

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ src/
124124
├── security/ # 安全管理
125125
├── services/ # 核心服务
126126
├── slash-commands/ # 斜杠命令
127-
├── telemetry/ # 遥测系统
127+
├── telemetry/ # 遥测系统(历史目录,当前实现中已不再使用)
128128
├── tools/ # 工具系统
129129
├── ui/ # 用户界面
130130
├── utils/ # 工具函数

docs/archive/TOOL_SYSTEM_RENOVATION_PLAN_archived.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ packages/core/src/tools/
6363
├── types/ # 类型定义
6464
│ ├── ToolTypes.ts # 工具基础类型
6565
│ ├── ExecutionTypes.ts # 执行相关类型
66-
│ ├── SecurityTypes.ts # 安全相关类型
6766
│ └── McpTypes.ts # MCP相关类型
6867
├── base/ # 基础抽象类
6968
│ ├── BaseTool.ts # 工具基类
@@ -1001,4 +1000,4 @@ Claude Code 通过 MCP (Model Context Protocol) 支持的扩展工具:
10011000
3. **MCP深度集成**: DiscoveredMCPTool类,自动发现和注册
10021001
4. **富媒体支持**: 支持图片、音频等多媒体内容
10031002

1004-
这些详细信息为 Blade 工具系统的设计和实现提供了宝贵的参考。
1003+
这些详细信息为 Blade 工具系统的设计和实现提供了宝贵的参考。

docs/development/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,14 @@
1717

1818
## 💻 实现细节
1919

20+
- **[Store 与 Config 架构统一](implementation/store-config-unification.md)** 🆕 - 消除双轨数据源的重构总结
2021
- **[错误处理](implementation/error-handling.md)** - 错误处理机制
2122
- **[日志系统](implementation/logging-system.md)** - 日志系统实现
2223
- **[Markdown 渲染器](implementation/markdown-renderer.md)** ⭐ - 完整 Markdown 渲染系统
2324
- **[流式工具执行显示](implementation/streaming-tool-execution-display.md)** ⭐ - Claude Code 风格的工具执行流
25+
- **[循环检测系统](implementation/loop-detection-system.md)** - 三层循环检测机制
26+
- **[Subagents 系统](implementation/subagents-system.md)** - 子 Agent 架构
27+
- **[MCP 支持](implementation/mcp-support.md)** - Model Context Protocol 实现
2428

2529
## 📋 技术方案
2630

docs/development/api-reference.md

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
├── mcp/ # MCP 协议支持
1212
├── services/ # 核心业务服务
1313
├── tools/ # 工具系统
14-
├── telemetry/ # 遥测系统
14+
├── telemetry/ # 遥测系统(历史目录,当前实现中已移除)
1515
├── types/ # 共享类型定义
1616
└── utils/ # 通用工具函数
1717
```
@@ -251,13 +251,9 @@ interface BladeUnifiedConfig {
251251
}>;
252252
};
253253

254-
// 遥测配置
255-
telemetry?: {
256-
enabled?: boolean;
257-
target?: 'local' | 'remote';
258-
otlpEndpoint?: string;
259-
logPrompts?: boolean;
260-
};
254+
// 遥测配置(已废弃)
255+
// 早期版本中曾提供可配置的遥测开关和远程端点,当前实现中已移除内置遥测逻辑,
256+
// 如果需要埋点统计,推荐在宿主应用层自行集成。
261257

262258
// 使用配置
263259
usage: {

docs/development/architecture/components.md

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -220,27 +220,6 @@ class SecurityManager {
220220
- ⚠️ 风险评估系统
221221
- 🔒 敏感数据加密
222222

223-
## 📊 遥测系统
224-
225-
### Telemetry SDK
226-
指标收集和错误跟踪系统。
227-
228-
```typescript
229-
// src/telemetry/TelemetrySDK.ts
230-
class TelemetrySDK {
231-
trackEvent(event: string, properties?: any): void
232-
trackError(error: Error, context?: any): void
233-
trackMetric(name: string, value: number): void
234-
setUser(userId: string): void
235-
}
236-
```
237-
238-
**收集指标:**
239-
- 📈 使用统计数据
240-
- 🐛 错误和异常
241-
- ⚡ 性能指标
242-
- 👤 用户行为分析
243-
244223
## 🚨 错误处理
245224

246225
### Error System
@@ -369,4 +348,4 @@ Infrastructure (基础设施)
369348
370349
---
371350
372-
这种模块化的组件设计使 Blade Code 具有良好的可维护性和扩展性。🏗️✨
351+
这种模块化的组件设计使 Blade Code 具有良好的可维护性和扩展性。🏗️✨

0 commit comments

Comments
 (0)