release(v0.2.0): streaming, MCP protocol, Browser Hand, security enhancements

## Major Features

### Streaming Response System
- Implement LlmDriver trait with `stream()` method returning async Stream
- Add SSE parsing for Anthropic and OpenAI API streaming
- Integrate Tauri event system for frontend streaming (`stream:chunk` events)
- Add StreamChunk types: Delta, ToolStart, ToolEnd, Complete, Error

### MCP Protocol Implementation
- Add MCP JSON-RPC 2.0 types (mcp_types.rs)
- Implement stdio-based MCP transport (mcp_transport.rs)
- Support tool discovery, execution, and resource operations

### Browser Hand Implementation
- Complete browser automation with Playwright-style actions
- Support Navigate, Click, Type, Scrape, Screenshot, Wait actions
- Add educational Hands: Whiteboard, Slideshow, Speech, Quiz

### Security Enhancements
- Implement command whitelist/blacklist for shell_exec tool
- Add SSRF protection with private IP blocking
- Create security.toml configuration file

## Test Improvements
- Fix test import paths (security-utils, setup)
- Fix vi.mock hoisting issues with vi.hoisted()
- Update test expectations for validateUrl and sanitizeFilename
- Add getUnsupportedLocalGatewayStatus mock

## Documentation Updates
- Update architecture documentation
- Improve configuration reference
- Add quick-start guide updates

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
iven
2026-03-24 03:24:24 +08:00
parent e49ba4460b
commit 3ff08faa56
78 changed files with 29575 additions and 1682 deletions

View File

@@ -0,0 +1,164 @@
# 修复 LLM API 404 错误
## 问题描述
用户在对话时收到错误:
```
Chat failed: LLM error: API error 404 Not Found: {"error":{"message":"The requested resource was not found","type":"resource_not_found_error"}}
```
## 根因分析
### 1. 模型别名未被解析(主要原因)
**数据流问题:**
- 前端 `chatStore.ts:194` 默认模型是 `'glm-5'`
- 配置文件 `config.toml:131` 定义了别名映射 `"glm-5" = "zhipu/glm-4-plus"`
- **但是后端 `kernel.rs` 没有解析这个别名**,直接把 `'glm-5'` 发送给API
- 智谱API不认识 `'glm-5'`返回404
### 2. 模型ID格式问题
配置文件使用带provider前缀的格式 `"zhipu/glm-4-plus"`,但:
- 智谱API只认识 `"glm-4-plus"`(不带前缀)
- `openai.rs:140` 直接传递模型ID不做任何处理
### 3. 多处配置不一致
| 位置 | 默认Provider | 默认Model |
|------|-------------|-----------|
| `config.rs:84-88` | `"qwen"` | `"qwen-plus"` |
| `config.toml:115-116` | `"zhipu"` | `"glm-4-plus"` |
| `chatStore.ts:194` | - | `'glm-5'` (别名) |
| `loop_runner.rs:38` | - | `"claude-sonnet-4-20250514"` (硬编码) |
### 4. Kimi Base URL错误
`config.rs:92` 使用 `https://api.kimi.com/coding/v1`,正确应该是 `https://api.moonshot.cn/v1`
## 修复方案
### 修复1: 在Kernel中添加模型别名解析
**文件**: `crates/zclaw-kernel/src/kernel.rs`
`send_message``send_message_stream` 方法中,解析模型别名:
```rust
// 在 send_message 方法中约第119行
// 添加模型别名解析函数
fn resolve_model_alias(model: &str, aliases: &HashMap<String, String>) -> String {
aliases.get(model).map(|s| s.as_str()).unwrap_or(model).to_string()
}
// 然后在确定模型后,检查是否是别名
let model = resolve_model_alias(model, &self.config.model_aliases);
```
### 修复2: 在KernelConfig中添加模型别名配置
**文件**: `crates/zclaw-kernel/src/config.rs`
1. 添加模型别名字段:
```rust
/// Model aliases (e.g., "glm-5" -> "zhipu/glm-4-plus")
#[serde(default)]
pub model_aliases: HashMap<String, String>,
```
2. 修正Kimi Base URL
```rust
fn default_kimi_base_url() -> String {
"https://api.moonshot.cn/v1".to_string() // 修正
}
```
### 修复3: 在OpenAIDriver中规范化模型ID
**文件**: `crates/zclaw-runtime/src/driver/openai.rs`
`build_api_request` 方法中去除provider前缀
```rust
fn normalize_model_id(model: &str) -> String {
// 如果模型ID包含 "/",取最后一部分
// 例如 "zhipu/glm-4-plus" -> "glm-4-plus"
if model.contains('/') {
model.split('/').last().unwrap_or(model).to_string()
} else {
model.to_string()
}
}
```
### 修复4: 统一默认配置
**文件**: `crates/zclaw-kernel/src/config.rs`
将默认provider和model改为与config.toml一致
```rust
fn default_provider() -> String {
"zhipu".to_string()
}
fn default_model() -> String {
"glm-4-plus".to_string()
}
```
### 修复5: 移除loop_runner.rs中的硬编码默认值
**文件**: `crates/zclaw-runtime/src/loop_runner.rs`
第38行的硬编码模型应该移除使用传入的配置
```rust
// 移除硬编码,改为空字符串或从配置获取
model: String::new(), // 必须通过 with_model() 设置
```
## 关键文件
| 文件 | 修改内容 |
|------|----------|
| [config.rs](crates/zclaw-kernel/src/config.rs) | 添加model_aliases字段、修正Kimi URL、统一默认配置 |
| [kernel.rs](crates/zclaw-kernel/src/kernel.rs) | 添加模型别名解析逻辑 |
| [openai.rs](crates/zclaw-runtime/src/driver/openai.rs) | 添加模型ID规范化去除provider前缀 |
| [loop_runner.rs](crates/zclaw-runtime/src/loop_runner.rs) | 移除硬编码默认模型 |
## 问题场景确认
用户使用**智谱 GLM** 模型时遇到404错误
- 前端默认 `currentModel: 'glm-5'`
- 配置别名 `"glm-5" = "zhipu/glm-4-plus"`
- 后端未解析别名,直接发送 `'glm-5'` 给API
- 智谱API返回404
## 验证步骤
1. **单元测试**
```bash
cargo test -p zclaw-kernel --lib config::tests
cargo test -p zclaw-runtime --lib driver::openai::tests
```
2. **集成测试**
```bash
cargo test -p zclaw-kernel
```
3. **手动验证智谱GLM**
- 启动桌面应用:`pnpm start:dev`
- 在"模型与API"设置中配置智谱API Key
- 选择 `glm-5` 或 `glm-4-plus` 模型
- 发送消息验证不再出现404错误
- 检查日志确认:
- 模型别名 `'glm-5'` 被解析为 `'zhipu/glm-4-plus'`
- provider前缀被去除发送给API的是 `'glm-4-plus'`
## 实现顺序
1. **config.rs** - 添加model_aliases字段和修正Kimi URL
2. **openai.rs** - 添加模型ID规范化函数
3. **kernel.rs** - 添加别名解析逻辑
4. **loop_runner.rs** - 移除硬编码
5. **测试验证**