docs: add setup guides and error notification component

- Add OpenFang Kernel configuration guide (docs/setup/OPENFANG-SETUP.md)
- Add Chinese models configuration guide (docs/setup/chinese-models.md)
- Add quick start guide (docs/quick-start.md)
- Add quick start scripts for Windows and Linux/macOS
- Add ErrorNotification component for centralized error display

These additions help users:
- Quickly set up development environment
- Configure OpenFang backend correctly
- Configure Chinese LLM providers (GLM, Qwen, Kimi, MiniMax)
- See error notifications in a consistent UI

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
iven
2026-03-21 00:17:44 +08:00
parent c5d91cf9f0
commit d3a4de2480
6 changed files with 1931 additions and 0 deletions

View File

@@ -0,0 +1,271 @@
/**
* ErrorNotification Component
*
* Displays error notifications as toast-style messages.
* Integrates with the centralized error handling system.
*/
import { useState, useEffect, useCallback } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import {
X,
AlertCircle,
AlertTriangle,
Info,
Bug,
WifiOff,
ShieldAlert,
Clock,
ChevronDown,
ChevronUp,
} from 'lucide-react';
import {
getUndismissedErrors,
dismissError,
dismissAll,
type StoredError,
} from '../lib/error-handling';
import {
ErrorCategory,
ErrorSeverity,
formatErrorForToast,
} from '../lib/error-types';
interface ErrorNotificationProps {
/** Maximum number of visible notifications */
maxVisible?: number;
/** Position on screen */
position?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left';
/** Auto dismiss timeout in ms (0 = no auto dismiss) */
autoDismissMs?: number;
/** Additional CSS classes */
className?: string;
}
const categoryIcons: Record<ErrorCategory, typeof AlertCircle> = {
network: WifiOff,
authentication: ShieldAlert,
authorization: ShieldAlert,
validation: AlertTriangle,
configuration: AlertTriangle,
internal: Bug,
external: AlertCircle,
timeout: Clock,
unknown: AlertCircle,
};
const severityColors: Record<ErrorSeverity, {
bg: string;
border: string;
text: string;
icon: string;
}> = {
critical: {
bg: 'bg-red-50 dark:bg-red-900/20',
border: 'border-red-200 dark:border-red-800',
text: 'text-red-800 dark:text-red-200',
icon: 'text-red-500',
},
high: {
bg: 'bg-orange-50 dark:bg-orange-900/20',
border: 'border-orange-200 dark:border-orange-800',
text: 'text-orange-800 dark:text-orange-200',
icon: 'text-orange-500',
},
medium: {
bg: 'bg-yellow-50 dark:bg-yellow-900/20',
border: 'border-yellow-200 dark:border-yellow-800',
text: 'text-yellow-800 dark:text-yellow-200',
icon: 'text-yellow-500',
},
low: {
bg: 'bg-blue-50 dark:bg-blue-900/20',
border: 'border-blue-200 dark:border-blue-800',
text: 'text-blue-800 dark:text-blue-200',
icon: 'text-blue-500',
},
};
function ErrorItem({
error,
onDismiss,
autoDismissMs,
}: {
error: StoredError;
onDismiss: (id: string) => void;
autoDismissMs: number;
}) {
const [expanded, setExpanded] = useState(false);
const Icon = categoryIcons[error.category] || AlertCircle;
const colors = severityColors[error.severity] || severityColors.medium;
const { title, message } = formatErrorForToast(error);
// Auto dismiss
useEffect(() => {
if (autoDismissMs > 0 && error.severity !== 'critical') {
const timer = setTimeout(() => {
onDismiss(error.id);
}, autoDismissMs);
return () => clearTimeout(timer);
}
}, [autoDismissMs, error.id, error.severity, onDismiss]);
const hasDetails = error.stack || error.context;
return (
<motion.div
initial={{ opacity: 0, x: 300, scale: 0.9 }}
animate={{ opacity: 1, x: 0, scale: 1 }}
exit={{ opacity: 0, x: 300, scale: 0.9 }}
className={`
${colors.bg} ${colors.border} ${colors.text}
border rounded-lg shadow-lg p-4 min-w-[320px] max-w-[420px]
`}
>
<div className="flex items-start gap-3">
<Icon className={`w-5 h-5 mt-0.5 flex-shrink-0 ${colors.icon}`} />
<div className="flex-1 min-w-0">
<div className="flex items-start justify-between gap-2">
<h4 className="font-medium text-sm">{title}</h4>
<button
onClick={() => onDismiss(error.id)}
className="p-1 rounded hover:bg-black/10 dark:hover:bg-white/10 flex-shrink-0"
>
<X className="w-4 h-4" />
</button>
</div>
<p className="text-sm mt-1 opacity-90">{message}</p>
{hasDetails && (
<button
onClick={() => setExpanded(!expanded)}
className="flex items-center gap-1 text-xs mt-2 opacity-70 hover:opacity-100"
>
{expanded ? (
<>
<ChevronUp className="w-3 h-3" />
</>
) : (
<>
<ChevronDown className="w-3 h-3" />
</>
)}
</button>
)}
{expanded && hasDetails && (
<motion.div
initial={{ height: 0, opacity: 0 }}
animate={{ height: 'auto', opacity: 1 }}
exit={{ height: 0, opacity: 0 }}
className="mt-2 p-2 bg-black/5 dark:bg-white/5 rounded text-xs font-mono overflow-auto max-h-32"
>
{error.context && (
<div className="mb-1">
<span className="opacity-70">Context: </span>
{JSON.stringify(error.context, null, 2)}
</div>
)}
{error.stack && (
<pre className="whitespace-pre-wrap opacity-70">{error.stack}</pre>
)}
</motion.div>
)}
<div className="flex items-center gap-2 mt-2 text-xs opacity-60">
<span>{error.category}</span>
<span></span>
<span>{new Date(error.timestamp).toLocaleTimeString()}</span>
</div>
</div>
</div>
</motion.div>
);
}
export function ErrorNotification({
maxVisible = 3,
position = 'top-right',
autoDismissMs = 10000,
className = '',
}: ErrorNotificationProps) {
const [errors, setErrors] = useState<StoredError[]>([]);
// Poll for new errors
useEffect(() => {
const updateErrors = () => {
setErrors(getUndismissedErrors().slice(0, maxVisible));
};
updateErrors();
const interval = setInterval(updateErrors, 1000);
return () => clearInterval(interval);
}, [maxVisible]);
const handleDismiss = useCallback((id: string) => {
dismissError(id);
setErrors(prev => prev.filter(e => e.id !== id));
}, []);
const handleDismissAll = useCallback(() => {
dismissAll();
setErrors([]);
}, []);
const positionClasses: Record<string, string> = {
'top-right': 'top-4 right-4',
'top-left': 'top-4 left-4',
'bottom-right': 'bottom-4 right-4',
'bottom-left': 'bottom-4 left-4',
};
if (errors.length === 0) return null;
return (
<div
className={`fixed ${positionClasses[position]} z-50 flex flex-col gap-2 ${className}`}
>
<AnimatePresence mode="popLayout">
{errors.map(error => (
<ErrorItem
key={error.id}
error={error}
onDismiss={handleDismiss}
autoDismissMs={autoDismissMs}
/>
))}
</AnimatePresence>
{errors.length > 1 && (
<motion.button
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
onClick={handleDismissAll}
className="text-xs text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 text-center py-1"
>
({errors.length})
</motion.button>
)}
</div>
);
}
/**
* ErrorNotificationProvider - Include at app root
*/
export function ErrorNotificationProvider({
children,
}: {
children: React.ReactNode;
}) {
return (
<>
{children}
<ErrorNotification />
</>
);
}
export default ErrorNotification;

233
docs/quick-start.md Normal file
View File

@@ -0,0 +1,233 @@
# ZCLAW 快速启动指南
> 5 分钟内启动 ZCLAW 开发环境
---
## 前置要求
| 工具 | 最低版本 | 检查命令 |
|------|----------|----------|
| Node.js | 18.x | `node -v` |
| pnpm | 8.x | `pnpm -v` |
| Rust | 1.70+ | `rustc --version` |
| OpenFang | - | `openfang --version` |
---
## 快速启动
### Windows 用户
```powershell
# 在项目根目录执行
.\scripts\quick-start-dev.ps1
```
### Linux/macOS 用户
```bash
# 在项目根目录执行
./scripts/quick-start.sh
```
---
## 手动启动步骤
### 1. 安装依赖
```bash
# 根目录依赖
pnpm install
# 桌面端依赖
cd desktop && pnpm install && cd ..
```
### 2. 启动 OpenFang 后端
```bash
# 方法 A: 使用 CLI
openfang start
# 方法 B: 使用 pnpm 脚本
pnpm gateway:start
```
验证后端运行:
```bash
curl http://127.0.0.1:50051/api/health
# 应返回: {"status":"ok"}
```
### 3. 启动开发环境
```bash
# 方法 A: 一键启动(推荐)
pnpm start:dev
# 方法 B: 仅启动桌面端(需要后端已运行)
pnpm desktop
# 方法 C: 分开启动
# 终端 1 - 启动 Gateway
pnpm dev
# 终端 2 - 启动桌面端
pnpm desktop
```
---
## 测试环境启动
### 单元测试
```bash
# 运行所有单元测试
pnpm test
# 监听模式
pnpm test:watch
# 桌面端测试
cd desktop && pnpm test
```
### E2E 测试
```bash
# 运行 E2E 测试
pnpm test:e2e
# 带界面运行
cd desktop && pnpm test:e2e:ui
```
---
## 开发端口说明
| 服务 | 端口 | 说明 |
|------|------|------|
| OpenFang 后端 | 50051 | API 和 WebSocket 服务 |
| Vite 开发服务器 | 1420 | 前端热重载 |
| Tauri 窗口 | - | 桌面应用窗口 |
---
## 常见问题排查
### Q1: 端口被占用
**症状**: `Port 1420 is already in use``Port 50051 is already in use`
**解决**:
```powershell
# Windows - 查找并终止进程
netstat -ano | findstr "1420"
taskkill /PID <PID> /F
# Linux/macOS
lsof -i :1420
kill -9 <PID>
```
### Q2: 后端连接失败
**症状**: `Network Error``Connection refused`
**排查步骤**:
```bash
# 1. 检查后端是否运行
curl http://127.0.0.1:50051/api/health
# 2. 检查端口监听
netstat -ano | findstr "50051"
# 3. 重启后端
openfang restart
```
### Q3: API Key 未配置
**症状**: `Missing API key: No LLM provider configured`
**解决**:
```bash
# 编辑配置文件
# Windows: %USERPROFILE%\.openfang\.env
# Linux/macOS: ~/.openfang/.env
# 添加 API Key
echo "ZHIPU_API_KEY=your_key" >> ~/.openfang/.env
# 重启后端
openfang restart
```
### Q4: Tauri 编译失败
**症状**: Rust 编译错误
**解决**:
```bash
# 更新 Rust
rustup update
# 清理并重新构建
cd desktop/src-tauri
cargo clean
cargo build
```
### Q5: 依赖安装失败
**症状**: pnpm install 报错
**解决**:
```bash
# 清理缓存
pnpm store prune
# 删除 node_modules 重新安装
rm -rf node_modules desktop/node_modules
pnpm install
```
---
## 验证清单
启动成功后,验证以下功能:
- [ ] 后端健康检查通过: `curl http://127.0.0.1:50051/api/health`
- [ ] 桌面端窗口正常显示
- [ ] 可以发送消息并获得响应
- [ ] 可以切换 Agent
- [ ] 可以查看设置页面
---
## 停止服务
```bash
# 停止所有服务
pnpm start:stop
# 或手动停止
# Ctrl+C 终止运行中的进程
```
---
## 相关文档
- [完整开发文档](./DEVELOPMENT.md)
- [故障排查指南](./knowledge-base/troubleshooting.md)
- [配置说明](./knowledge-base/configuration.md)
---
**最后更新**: 2026-03-21

View File

@@ -0,0 +1,512 @@
# OpenFang Kernel 配置指南
> 本文档帮助你正确配置 OpenFang Kernel作为 ZCLAW 的后端执行引擎。
## 概述
OpenFang 是一个用 Rust 构建的生产级 Agent 操作系统Agent Operating System。与传统的聊天机器人框架不同OpenFang 采用"主动执行"范式Agent 能够按计划自主唤醒、完成任务并报告结果,而无需用户持续提示。
### 核心特性
- **高性能**:冷启动 < 200ms空闲内存 ~40MB
- **Hands 机制**7 个预构建的自主能力包即插即用
- **40+ 渠道适配器**支持 TelegramDiscord飞书钉钉等
- **27+ LLM 提供商**包括中文模型智谱通义千问KimiMiniMax
- **16 层安全防护**WASM 沙箱Merkle 审计追踪Ed25519 签名等
---
## 前置要求
### 系统要求
| 要求 | 最低配置 | 推荐配置 |
|------|----------|----------|
| **操作系统** | Windows 10 / macOS 10.15 / Linux | Windows 11 / macOS 13+ / Ubuntu 22.04+ |
| **CPU 架构** | x86_64 ARM64 | x86_64 |
| **内存** | 64MB | 256MB+ |
| **磁盘空间** | 100MB | 500MB+ |
### 依赖项
OpenFang 是一个独立的单二进制文件~32MB无外部依赖但以下工具可能对某些功能必要
- **FFmpeg**视频处理 Hand (Clip) 需要
- **yt-dlp**YouTube 视频下载需要
---
## 安装步骤
### 方式一:官方安装脚本(推荐)
#### Windows
```powershell
# 使用 PowerShell
iwr -useb https://openfang.sh/install.ps1 | iex
```
#### macOS / Linux
```bash
curl -fsSL https://openfang.sh/install.sh | bash
```
### 方式二:手动下载
1. 访问 [GitHub Releases](https://github.com/RightNow-AI/openfang/releases)
2. 下载对应平台的二进制文件
3. 将文件放入 PATH 目录
#### Windows
```powershell
# 下载后移动到用户目录
move openfang.exe C:\Users\<你的用户名>\.local\bin\
```
#### macOS / Linux
```bash
chmod +x openfang
sudo mv openfang /usr/local/bin/
```
### 方式三:从源码编译
```bash
git clone https://github.com/RightNow-AI/openfang.git
cd openfang
cargo build --release
# 编译产物位于 target/release/openfang
```
---
## 配置说明
### 1. 初始化配置
首次使用需要初始化配置文件
```bash
openfang init
```
这将在 `~/.openfang/` 目录下创建以下结构
```
~/.openfang/
├── config.toml # 主配置文件
├── openfang.db # SQLite 数据库
├── data/ # 数据目录
│ ├── agents/ # Agent 配置
│ ├── skills/ # 自定义技能
│ └── hands/ # Hand 配置
└── logs/ # 日志文件
```
### 2. 配置文件结构
编辑 `~/.openfang/config.toml`
```toml
# OpenFang 主配置文件
[general]
# 默认语言
language = "zh-CN"
# 日志级别: trace, debug, info, warn, error
log_level = "info"
# 数据目录
data_dir = "~/.openfang/data"
[model]
# 默认模型提供商
provider = "zhipu"
# 默认模型
model = "glm-4-flash"
# API Key 环境变量名(不直接写 Key
api_key_env = "ZHIPU_API_KEY"
# 可选:自定义 API 端点
# base_url = "https://open.bigmodel.cn/api/paas/v4"
[api]
# API 服务端口
port = 50051
# 绑定地址0.0.0.0 允许外部访问)
bind = "127.0.0.1"
# 启用 OpenAI 兼容 API
openai_compat = true
[security]
# 启用能力门控
capability_gates = true
# 启用审计追踪
audit_trail = true
# 启用 WASM 沙箱
wasm_sandbox = true
[memory]
# 会话保留天数
session_retention_days = 30
# 向量嵌入模型
embedding_model = "text-embedding-3-small"
```
### 3. 配置 API Key
**重要**永远不要在配置文件中直接写入 API Key使用环境变量
#### Windows (PowerShell)
```powershell
# 临时设置(当前会话)
$env:ZHIPU_API_KEY = "your-api-key-here"
$env:DASHSCOPE_API_KEY = "your-dashscope-key" # 通义千问
$env:MOONSHOT_API_KEY = "your-moonshot-key" # Kimi
# 永久设置(写入配置文件)
[Environment]::SetEnvironmentVariable("ZHIPU_API_KEY", "your-api-key", "User")
```
#### macOS / Linux
```bash
# 临时设置(当前会话)
export ZHIPU_API_KEY="your-api-key-here"
export DASHSCOPE_API_KEY="your-dashscope-key"
export MOONSHOT_API_KEY="your-moonshot-key"
# 永久设置(写入 shell 配置文件)
echo 'export ZHIPU_API_KEY="your-api-key"' >> ~/.bashrc
source ~/.bashrc
```
### 4. 配置中文模型
`config.toml` 中配置中文模型提供商
```toml
# 智谱 GLM
[model.zhipu]
provider = "zhipu"
model = "glm-4-flash"
api_key_env = "ZHIPU_API_KEY"
base_url = "https://open.bigmodel.cn/api/paas/v4"
# 通义千问
[model.qwen]
provider = "openai-compat"
model = "qwen-turbo"
api_key_env = "DASHSCOPE_API_KEY"
base_url = "https://dashscope.aliyuncs.com/compatible-mode/v1"
# Kimi (Moonshot)
[model.kimi]
provider = "openai-compat"
model = "moonshot-v1-8k"
api_key_env = "MOONSHOT_API_KEY"
base_url = "https://api.moonshot.cn/v1"
# MiniMax
[model.minimax]
provider = "openai-compat"
model = "abab6.5-chat"
api_key_env = "MINIMAX_API_KEY"
base_url = "https://api.minimax.chat/v1"
```
### 5. 启动服务
#### 前台运行(调试用)
```bash
openfang start
```
#### 后台守护进程
```bash
# 启动守护进程
openfang daemon start
# 查看状态
openfang status
# 停止守护进程
openfang daemon stop
```
#### 检查健康状态
```bash
openfang doctor
```
---
## 与 ZCLAW 集成
### 配置 ZCLAW 连接 OpenFang
编辑 ZCLAW 配置文件 `~/.zclaw/config.toml`
```toml
[gateway]
# OpenFang API 端点
endpoint = "http://127.0.0.1:50051"
# WebSocket 端点
ws_endpoint = "ws://127.0.0.1:50051/ws"
# 连接超时(秒)
timeout = 30
[model]
# 使用 OpenFang 的模型路由
use_gateway_routing = true
```
### 验证连接
```bash
# 启动 OpenFang
openfang start
# 在另一个终端启动 ZCLAW
cd desktop && pnpm tauri dev
```
---
## 常见问题
### 1. 端口被占用
**错误信息**`Address already in use: 0.0.0.0:50051`
**解决方案**
```bash
# 查找占用端口的进程
# Windows
netstat -ano | findstr :50051
# macOS / Linux
lsof -i :50051
# 修改配置文件中的端口
[api]
port = 50052
```
### 2. API Key 无效
**错误信息**`Authentication failed` `Invalid API key`
**排查步骤**
1. 确认环境变量已设置
```bash
# Windows
echo $env:ZHIPU_API_KEY
# macOS / Linux
echo $ZHIPU_API_KEY
```
2. 确认 API Key 格式正确(无多余空格或引号)
3. 确认 API Key 未过期
### 3. 内存不足
**错误信息**`Out of memory` 或系统卡顿
**解决方案**
1. 关闭不必要的服务
2. 降低并发 Agent 数量
3. 增加系统交换空间
### 4. 模型调用失败
**错误信息**`Model not found` 或 `Provider error`
**排查步骤**
1. 检查模型名称是否正确
2. 确认 API 端点可访问
3. 检查网络连接和代理设置
```bash
# 测试 API 连通性
curl -I https://open.bigmodel.cn/api/paas/v4/models
```
### 5. 中文乱码
**解决方案**
确保系统 locale 设置正确:
```bash
# Windows
chcp 65001
# macOS / Linux
export LANG=zh_CN.UTF-8
```
### 6. 从 OpenClaw 迁移
如果你之前使用 OpenClaw可以使用迁移工具
```bash
# 迁移所有内容:代理、记忆、技能、配置
openfang migrate --from openclaw
# 从特定路径迁移
openfang migrate --from openclaw --path ~/.openclaw
# 先试运行查看变更
openfang migrate --from openclaw --dry-run
```
---
## 进阶配置
### 配置 Hands
Hands 是 OpenFang 的核心创新,每个 Hand 是一个预构建的自主能力包:
```toml
# ~/.openfang/data/hands/researcher.toml
[hand]
name = "researcher"
description = "深度研究助手"
enabled = true
[hand.schedule]
# 执行模式continuous, periodic, manual
mode = "manual"
# 定时执行cron 表达式)
# cron = "0 9 * * *" # 每天早上 9 点
[hand.config]
# 最大搜索深度
max_depth = 5
# 输出格式
output_format = "markdown"
# 引用格式
citation_style = "apa"
```
### 配置 MCP 服务器
```toml
# ~/.openfang/config.toml
[[mcp_servers]]
name = "filesystem"
command = "mcp-filesystem"
args = ["--root", "/path/to/allowed/dir"]
[[mcp_servers]]
name = "postgres"
command = "mcp-postgres"
env = { DATABASE_URL = "postgresql://localhost/mydb" }
```
### 配置渠道适配器
```toml
# ~/.openfang/config.toml
[[channels]]
type = "feishu"
enabled = true
[channels.config]
app_id = "cli_xxx"
app_secret_env = "FEISHU_APP_SECRET"
# 加密密钥(可选)
encrypt_key_env = "FEISHU_ENCRYPT_KEY"
```
---
## 性能调优
### 内存优化
```toml
[memory]
# 会话压缩阈值token 数)
compaction_threshold = 80000
# 保留最近消息数
keep_recent = 20
# 向量嵌入缓存大小
embedding_cache_size = 1000
```
### 并发优化
```toml
[runtime]
# 最大并发工具调用
max_concurrent_tools = 10
# 工具执行超时(秒)
tool_timeout = 60
# Agent 循环最大迭代
max_iterations = 50
```
---
## 日志与监控
### 查看日志
```bash
# 实时日志
openfang logs -f
# 按级别过滤
openfang logs --level error
# 按时间范围
openfang logs --since "2024-01-01" --until "2024-01-02"
```
### 监控指标
```bash
# 系统状态
openfang status
# 详细健康检查
openfang doctor --verbose
# 使用统计
openfang usage --daily
```
---
## 相关链接
- [OpenFang 官方文档](https://openfang.sh/)
- [GitHub 仓库](https://github.com/RightNow-AI/openfang)
- [中文模型配置](./chinese-models.md)
- [ZCLAW 主文档](../../README.md)
---
## 获取帮助
- **命令行帮助**`openfang --help` 或 `openfang <command> --help`
- **GitHub Issues**https://github.com/RightNow-AI/openfang/issues
- **社区讨论**https://deepseek.club/t/topic/996

View File

@@ -0,0 +1,472 @@
# 中文模型配置指南
> 本文档详细介绍 OpenFang Kernel 支持的中文大语言模型,以及如何获取和配置 API Key。
---
## 支持的中文模型
OpenFang 通过 OpenAI 兼容 API 支持所有主流中文模型提供商:
| 提供商 | 模型系列 | 特点 | 定价 |
|--------|----------|------|------|
| **智谱 AI** | GLM-4 | 国产领先,多模态支持 | 免费 + 付费 |
| **阿里云** | 通义千问 (Qwen) | 性价比高,企业级 | 按量计费 |
| **月之暗面** | Kimi | 长上下文200K | 按量计费 |
| **MiniMax** | 海螺 AI | 语音能力强 | 按量计费 |
| **百度** | 文心一言 | 企业应用广泛 | 按量计费 |
| **DeepSeek** | DeepSeek | 编程能力强,低价 | 极低价格 |
| **百川智能** | Baichuan | 中文优化 | 按量计费 |
| **上海 AI Lab** | 书生浦语 | 开源模型 | 免费 |
---
## 1. 智谱 GLM
### 模型列表
| 模型 | 上下文 | 特点 | 适用场景 |
|------|--------|------|----------|
| `glm-4-flash` | 128K | 快速响应,免费额度 | 日常对话、快速问答 |
| `glm-4` | 128K | 旗舰模型 | 复杂任务、推理 |
| `glm-4-plus` | 128K | 增强版 | 专业应用 |
| `glm-4-air` | 128K | 轻量版 | 简单任务 |
| `glm-4v` | 8K | 多模态(图像理解) | 图像分析 |
| `glm-4-long` | 1M | 超长上下文 | 长文档处理 |
### API Key 获取
1. 访问 [智谱开放平台](https://open.bigmodel.cn/)
2. 注册/登录账号
3. 进入「API Keys」页面
4. 点击「创建 API Key」
**免费额度**:新用户赠送 1000 万 tokens
### 配置示例
```toml
[model.zhipu]
provider = "zhipu"
model = "glm-4-flash"
api_key_env = "ZHIPU_API_KEY"
base_url = "https://open.bigmodel.cn/api/paas/v4"
```
```bash
# 设置环境变量
export ZHIPU_API_KEY="your-zhipu-api-key"
```
---
## 2. 通义千问 (Qwen)
### 模型列表
| 模型 | 上下文 | 特点 | 适用场景 |
|------|--------|------|----------|
| `qwen-turbo` | 8K | 快速版 | 快速问答 |
| `qwen-plus` | 32K | 增强版 | 复杂任务 |
| `qwen-max` | 32K | 旗舰版 | 高质量输出 |
| `qwen-max-longcontext` | 200K | 长上下文 | 长文档 |
| `qwen-vl-plus` | 8K | 多模态 | 图像理解 |
| `qwen-vl-max` | 8K | 多模态增强 | 高精度图像 |
### API Key 获取
1. 访问 [阿里云百炼](https://dashscope.console.aliyun.com/)
2. 登录阿里云账号
3. 开通「灵积模型服务」
4. 获取 API Key
**免费额度**:部分模型有免费试用
### 配置示例
```toml
[model.qwen]
provider = "openai-compat"
model = "qwen-turbo"
api_key_env = "DASHSCOPE_API_KEY"
base_url = "https://dashscope.aliyuncs.com/compatible-mode/v1"
```
```bash
# 设置环境变量
export DASHSCOPE_API_KEY="your-dashscope-api-key"
```
---
## 3. Kimi (Moonshot)
### 模型列表
| 模型 | 上下文 | 特点 | 适用场景 |
|------|--------|------|----------|
| `moonshot-v1-8k` | 8K | 基础版 | 日常对话 |
| `moonshot-v1-32k` | 32K | 长上下文 | 中等文档 |
| `moonshot-v1-128k` | 128K | 超长上下文 | 长文档分析 |
### API Key 获取
1. 访问 [Moonshot AI 开放平台](https://platform.moonshot.cn/)
2. 注册/登录账号
3. 进入「API Key 管理」
4. 创建新的 API Key
**免费额度**:新用户赠送 15 元体验金
### 配置示例
```toml
[model.kimi]
provider = "openai-compat"
model = "moonshot-v1-8k"
api_key_env = "MOONSHOT_API_KEY"
base_url = "https://api.moonshot.cn/v1"
```
```bash
# 设置环境变量
export MOONSHOT_API_KEY="your-moonshot-api-key"
```
---
## 4. MiniMax
### 模型列表
| 模型 | 上下文 | 特点 | 适用场景 |
|------|--------|------|----------|
| `abab6.5-chat` | 8K | 旗舰对话 | 通用对话 |
| `abab6.5s-chat` | 8K | 快速版 | 快速响应 |
| `abab6.5g-chat` | 8K | 通用版 | 平衡场景 |
| `abab5.5-chat` | 16K | 经典版 | 日常使用 |
| `abab5.5s-chat` | 16K | 轻量版 | 简单任务 |
### API Key 获取
1. 访问 [MiniMax 开放平台](https://www.minimaxi.com/)
2. 注册/登录账号
3. 进入「账户管理」->「API Key」
4. 创建 API Key
**注意**MiniMax 需要同时配置 Group ID
### 配置示例
```toml
[model.minimax]
provider = "openai-compat"
model = "abab6.5-chat"
api_key_env = "MINIMAX_API_KEY"
base_url = "https://api.minimax.chat/v1"
[model.minimax.headers]
# MiniMax 需要 Group ID
"x-minimax-group-id" = "your-group-id"
```
```bash
# 设置环境变量
export MINIMAX_API_KEY="your-minimax-api-key"
```
---
## 5. DeepSeek
### 模型列表
| 模型 | 上下文 | 特点 | 适用场景 |
|------|--------|------|----------|
| `deepseek-chat` | 64K | 通用对话 | 日常使用 |
| `deepseek-coder` | 16K | 代码专精 | 编程任务 |
| `deepseek-reasoner` | 64K | 深度推理 | 复杂推理 |
### API Key 获取
1. 访问 [DeepSeek 开放平台](https://platform.deepseek.com/)
2. 注册/登录账号
3. 进入「API Keys」页面
4. 创建 API Key
**定价优势**:极低价格,性价比高
### 配置示例
```toml
[model.deepseek]
provider = "openai-compat"
model = "deepseek-chat"
api_key_env = "DEEPSEEK_API_KEY"
base_url = "https://api.deepseek.com"
```
```bash
# 设置环境变量
export DEEPSEEK_API_KEY="your-deepseek-api-key"
```
---
## 6. 百度文心一言
### 模型列表
| 模型 | 上下文 | 特点 | 适用场景 |
|------|--------|------|----------|
| `ernie-4.0-8k` | 8K | 旗舰版 | 复杂任务 |
| `ernie-3.5-8k` | 8K | 标准版 | 日常使用 |
| `ernie-speed-8k` | 8K | 快速版 | 快速响应 |
| `ernie-lite-8k` | 8K | 轻量版 | 简单任务 |
### API Key 获取
1. 访问 [百度智能云千帆平台](https://console.bce.baidu.com/qianfan/)
2. 登录百度账号
3. 创建应用,获取 API Key 和 Secret Key
**注意**:文心一言使用 access_token 认证,需要额外处理
### 配置示例
```toml
[model.wenxin]
provider = "openai-compat"
model = "ernie-4.0-8k"
api_key_env = "WENXIN_ACCESS_TOKEN"
base_url = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions"
```
---
## 7. 百川智能
### 模型列表
| 模型 | 上下文 | 特点 | 适用场景 |
|------|--------|------|----------|
| `Baichuan4` | 128K | 旗舰版 | 复杂任务 |
| `Baichuan3-Turbo` | 32K | 快速版 | 日常使用 |
| `Baichuan3-Turbo-128k` | 128K | 长上下文 | 长文档 |
### API Key 获取
1. 访问 [百川智能开放平台](https://platform.baichuan-ai.com/)
2. 注册/登录账号
3. 获取 API Key
### 配置示例
```toml
[model.baichuan]
provider = "openai-compat"
model = "Baichuan4"
api_key_env = "BAICHUAN_API_KEY"
base_url = "https://api.baichuan-ai.com/v1"
```
---
## 8. 本地模型 (Ollama)
如果你想在本地运行开源中文模型:
### 支持的开源模型
| 模型 | 参数量 | 内存需求 | 特点 |
|------|--------|----------|------|
| `qwen2:7b` | 7B | 8GB | 通用对话 |
| `qwen2:14b` | 14B | 16GB | 高质量输出 |
| `glm4:9b` | 9B | 12GB | 智谱开源版 |
| `deepseek-coder:6.7b` | 6.7B | 8GB | 代码专精 |
### 安装 Ollama
```bash
# macOS / Linux
curl -fsSL https://ollama.com/install.sh | sh
# Windows
# 访问 https://ollama.com/download 下载安装包
```
### 下载模型
```bash
# 下载通义千问
ollama pull qwen2:7b
# 下载 GLM4
ollama pull glm4:9b
```
### 配置示例
```toml
[model.ollama]
provider = "openai-compat"
model = "qwen2:7b"
base_url = "http://localhost:11434/v1"
# 本地模型无需 API Key
api_key_env = ""
```
---
## 多模型配置
OpenFang 支持同时配置多个模型,并自动路由:
```toml
# ~/.openfang/config.toml
[model]
# 默认模型
provider = "zhipu"
model = "glm-4-flash"
# 备选模型
[[model.alternates]]
name = "coding"
provider = "deepseek"
model = "deepseek-coder"
api_key_env = "DEEPSEEK_API_KEY"
[[model.alternates]]
name = "long-context"
provider = "kimi"
model = "moonshot-v1-128k"
api_key_env = "MOONSHOT_API_KEY"
[[model.alternates]]
name = "local"
provider = "openai-compat"
model = "qwen2:7b"
base_url = "http://localhost:11434/v1"
# 模型路由规则
[model.routing]
# 编程任务使用 DeepSeek Coder
coding = ["deepseek-coder", "glm-4"]
# 长文档使用 Kimi
long_context = ["moonshot-v1-128k", "glm-4-long"]
# 快速响应使用 Flash 或本地模型
fast = ["glm-4-flash", "qwen2:7b"]
```
---
## 价格对比
| 模型 | 输入价格 (元/百万 tokens) | 输出价格 (元/百万 tokens) |
|------|---------------------------|---------------------------|
| GLM-4-Flash | 免费 | 免费 |
| GLM-4 | 100 | 100 |
| 通义千问-Turbo | 2 | 6 |
| 通义千问-Max | 40 | 120 |
| Kimi-8K | 12 | 12 |
| DeepSeek-Chat | 1 | 2 |
| DeepSeek-Coder | 1 | 2 |
*价格仅供参考,以官方最新公告为准*
---
## 最佳实践
### 1. 模型选择建议
| 场景 | 推荐模型 | 理由 |
|------|----------|------|
| 日常对话 | GLM-4-Flash | 免费且速度快 |
| 编程任务 | DeepSeek-Coder | 专业代码能力 |
| 长文档分析 | Kimi-128K | 超长上下文 |
| 复杂推理 | GLM-4 / Qwen-Max | 高质量输出 |
| 离线使用 | Ollama + Qwen2 | 本地运行 |
### 2. API Key 安全
- 永远不要在代码或配置文件中硬编码 API Key
- 使用环境变量存储敏感信息
- 定期轮换 API Key
- 为不同项目使用不同的 API Key
- 设置 API Key 使用额度限制
### 3. 成本控制
```toml
[metering]
# 每日最大花费(美元)
daily_budget = 5.0
# 每个 Agent 每小时最大 tokens
hourly_token_limit = 100000
# 超限行为reject拒绝或 downgrade降级
on_limit = "downgrade"
# 降级到的模型
fallback_model = "glm-4-flash"
```
---
## 常见问题
### Q: 如何测试 API Key 是否有效?
```bash
# 使用 curl 测试智谱 API
curl -X POST https://open.bigmodel.cn/api/paas/v4/chat/completions \
-H "Authorization: Bearer $ZHIPU_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "glm-4-flash", "messages": [{"role": "user", "content": "你好"}]}'
```
### Q: 多个模型如何切换?
在 Agent 配置中指定:
```toml
[agent.my-agent]
[model]
provider = "deepseek"
model = "deepseek-coder"
```
### Q: 如何查看用量?
```bash
# 查看今日用量
openfang usage --today
# 查看本月用量
openfang usage --month
# 按模型分组
openfang usage --group-by model
```
### Q: API Key 泄露了怎么办?
1. 立即在对应平台撤销泄露的 Key
2. 生成新的 API Key
3. 更新环境变量
4. 检查账单是否有异常使用
---
## 相关链接
- [智谱开放平台](https://open.bigmodel.cn/)
- [阿里云百炼](https://dashscope.console.aliyun.com/)
- [Moonshot 平台](https://platform.moonshot.cn/)
- [MiniMax 开放平台](https://www.minimaxi.com/)
- [DeepSeek 平台](https://platform.deepseek.com/)
- [Ollama 官网](https://ollama.com/)
---
*最后更新2026 年 3 月*

225
scripts/quick-start-dev.ps1 Normal file
View File

@@ -0,0 +1,225 @@
#Requires -Version 5.1
<#
.SYNOPSIS
ZCLAW 开发环境快速启动脚本
.DESCRIPTION
检查依赖、启动后端服务、启动桌面端开发环境
.PARAMETER SkipBackend
跳过后端启动(假设后端已运行)
.PARAMETER DesktopOnly
仅启动桌面端
.PARAMETER Stop
停止所有服务
.EXAMPLE
.\scripts\quick-start-dev.ps1
.\scripts\quick-start-dev.ps1 -SkipBackend
.\scripts\quick-start-dev.ps1 -Stop
#>
param(
[switch]$SkipBackend,
[switch]$DesktopOnly,
[switch]$Stop
)
$ErrorActionPreference = "Stop"
$ProjectRoot = $PSScriptRoot | Split-Path -Parent
# 颜色输出函数
function Write-Step {
param([string]$Message)
Write-Host "`n[STEP] $Message" -ForegroundColor Cyan
}
function Write-Success {
param([string]$Message)
Write-Host "[OK] $Message" -ForegroundColor Green
}
function Write-Warning {
param([string]$Message)
Write-Host "[WARN] $Message" -ForegroundColor Yellow
}
function Write-Error {
param([string]$Message)
Write-Host "[ERROR] $Message" -ForegroundColor Red
}
# 停止服务
if ($Stop) {
Write-Step "停止所有服务..."
# 停止 OpenFang
$openfang = Get-Process -Name "openfang" -ErrorAction SilentlyContinue
if ($openfang) {
Stop-Process -Name "openfang" -Force -ErrorAction SilentlyContinue
Write-Success "OpenFang 已停止"
}
# 停止 Vite
$vite = Get-Process -Name "node" -ErrorAction SilentlyContinue | Where-Object { $_.MainWindowTitle -like "*vite*" -or $_.CommandLine -like "*vite*" }
if ($vite) {
$vite | Stop-Process -Force -ErrorAction SilentlyContinue
Write-Success "Vite 进程已停止"
}
# 调用项目的停止脚本
$stopScript = Join-Path $ProjectRoot "start-all.ps1"
if (Test-Path $stopScript) {
& $stopScript -Stop
}
Write-Success "所有服务已停止"
exit 0
}
Write-Host "========================================" -ForegroundColor Cyan
Write-Host " ZCLAW Development Quick Start" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
# 1. 检查 Node.js
Write-Step "检查 Node.js..."
try {
$nodeVersion = node -v
if ($nodeVersion -match "v(\d+)") {
$majorVersion = [int]$Matches[1]
if ($majorVersion -lt 18) {
Write-Error "Node.js 版本过低: $nodeVersion (需要 18+)"
Write-Host "请从 https://nodejs.org 安装最新版本"
exit 1
}
Write-Success "Node.js $nodeVersion"
}
} catch {
Write-Error "未找到 Node.js请从 https://nodejs.org 安装"
exit 1
}
# 2. 检查 pnpm
Write-Step "检查 pnpm..."
try {
$pnpmVersion = pnpm -v
Write-Success "pnpm $pnpmVersion"
} catch {
Write-Warning "未找到 pnpm正在安装..."
npm install -g pnpm
if ($LASTEXITCODE -ne 0) {
Write-Error "pnpm 安装失败"
exit 1
}
Write-Success "pnpm 安装完成"
}
# 3. 检查依赖安装
Write-Step "检查依赖..."
$nodeModules = Join-Path $ProjectRoot "node_modules"
$desktopModules = Join-Path $ProjectRoot "desktop\node_modules"
if (-not (Test-Path $nodeModules)) {
Write-Host "安装根目录依赖..."
Push-Location $ProjectRoot
pnpm install
Pop-Location
}
if (-not (Test-Path $desktopModules)) {
Write-Host "安装桌面端依赖..."
Push-Location (Join-Path $ProjectRoot "desktop")
pnpm install
Pop-Location
}
Write-Success "依赖已就绪"
# 4. 检查/启动后端
if (-not $SkipBackend -and -not $DesktopOnly) {
Write-Step "检查后端服务..."
$backendRunning = $false
try {
$response = Invoke-WebRequest -Uri "http://127.0.0.1:50051/api/health" -TimeoutSec 2 -UseBasicParsing -ErrorAction SilentlyContinue
if ($response.StatusCode -eq 200) {
$backendRunning = $true
Write-Success "后端服务已运行"
}
} catch {
# 后端未运行
}
if (-not $backendRunning) {
Write-Host "启动 OpenFang 后端..."
# 尝试多种方式启动
$started = $false
# 方式 1: 使用 openfang CLI
try {
$openfangCmd = Get-Command "openfang" -ErrorAction SilentlyContinue
if ($openfangCmd) {
Start-Process -FilePath "openfang" -ArgumentList "start" -NoNewWindow
$started = $true
}
} catch {}
# 方式 2: 使用 pnpm 脚本
if (-not $started) {
$startScript = Join-Path $ProjectRoot "start-all.ps1"
if (Test-Path $startScript) {
Start-Process -FilePath "powershell" -ArgumentList "-ExecutionPolicy", "Bypass", "-File", $startScript -NoNewWindow
$started = $true
}
}
if (-not $started) {
Write-Error "无法启动后端服务"
Write-Host "请手动启动 OpenFang:"
Write-Host " openfang start"
Write-Host " 或运行 start-all.ps1"
exit 1
}
# 等待后端启动
Write-Host "等待后端启动..."
$retries = 0
$maxRetries = 15
while ($retries -lt $maxRetries) {
Start-Sleep -Seconds 1
try {
$response = Invoke-WebRequest -Uri "http://127.0.0.1:50051/api/health" -TimeoutSec 2 -UseBasicParsing -ErrorAction SilentlyContinue
if ($response.StatusCode -eq 200) {
Write-Success "后端服务启动成功"
break
}
} catch {}
$retries++
Write-Host "." -NoNewline
}
if ($retries -ge $maxRetries) {
Write-Error "后端启动超时"
Write-Host "请检查 OpenFang 是否正确安装"
exit 1
}
}
}
# 5. 启动开发环境
Write-Step "启动开发环境..."
Push-Location $ProjectRoot
if ($DesktopOnly) {
Write-Host "仅启动桌面端..."
pnpm desktop
} else {
Write-Host "启动完整开发环境..."
pnpm start:dev
}
Pop-Location

218
scripts/quick-start.sh Normal file
View File

@@ -0,0 +1,218 @@
#!/bin/bash
#
# ZCLAW Development Quick Start Script
#
# Usage:
# ./scripts/quick-start.sh [options]
#
# Options:
# --skip-backend Skip backend startup (assume already running)
# --desktop-only Start desktop only
# --stop Stop all services
# --help Show this help message
#
set -e
PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
SKIP_BACKEND=false
DESKTOP_ONLY=false
STOP_SERVICES=false
# Parse arguments
for arg in "$@"; do
case $arg in
--skip-backend)
SKIP_BACKEND=true
shift
;;
--desktop-only)
DESKTOP_ONLY=true
shift
;;
--stop)
STOP_SERVICES=true
shift
;;
--help)
echo "ZCLAW Development Quick Start Script"
echo ""
echo "Usage: $0 [options]"
echo ""
echo "Options:"
echo " --skip-backend Skip backend startup"
echo " --desktop-only Start desktop only"
echo " --stop Stop all services"
echo " --help Show this help"
exit 0
;;
*)
echo "Unknown option: $arg"
exit 1
;;
esac
done
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# Output functions
step() {
echo -e "\n${CYAN}[STEP]${NC} $1"
}
success() {
echo -e "${GREEN}[OK]${NC} $1"
}
warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# Stop services
if [ "$STOP_SERVICES" = true ]; then
step "Stopping all services..."
# Kill OpenFang processes
pkill -f "openfang" 2>/dev/null || true
# Kill Vite processes
pkill -f "vite" 2>/dev/null || true
# Kill Tauri processes
pkill -f "tauri" 2>/dev/null || true
success "All services stopped"
exit 0
fi
echo -e "${CYAN}========================================${NC}"
echo -e "${CYAN} ZCLAW Development Quick Start${NC}"
echo -e "${CYAN}========================================${NC}"
# 1. Check Node.js
step "Checking Node.js..."
if ! command -v node &> /dev/null; then
error "Node.js not found"
echo "Please install from https://nodejs.org"
exit 1
fi
NODE_VERSION=$(node -v | sed 's/v//')
MAJOR_VERSION=$(echo "$NODE_VERSION" | cut -d. -f1)
if [ "$MAJOR_VERSION" -lt 18 ]; then
error "Node.js version too low: v$NODE_VERSION (requires 18+)"
echo "Please upgrade from https://nodejs.org"
exit 1
fi
success "Node.js $(node -v)"
# 2. Check pnpm
step "Checking pnpm..."
if ! command -v pnpm &> /dev/null; then
warn "pnpm not found, installing..."
npm install -g pnpm
if [ $? -ne 0 ]; then
error "Failed to install pnpm"
exit 1
fi
fi
success "pnpm $(pnpm -v)"
# 3. Check and install dependencies
step "Checking dependencies..."
if [ ! -d "$PROJECT_ROOT/node_modules" ]; then
echo "Installing root dependencies..."
cd "$PROJECT_ROOT"
pnpm install
fi
if [ ! -d "$PROJECT_ROOT/desktop/node_modules" ]; then
echo "Installing desktop dependencies..."
cd "$PROJECT_ROOT/desktop"
pnpm install
fi
success "Dependencies ready"
# 4. Check/Start backend
if [ "$SKIP_BACKEND" = false ] && [ "$DESKTOP_ONLY" = false ]; then
step "Checking backend service..."
BACKEND_RUNNING=false
if curl -s --connect-timeout 2 "http://127.0.0.1:50051/api/health" > /dev/null 2>&1; then
BACKEND_RUNNING=true
success "Backend service already running"
fi
if [ "$BACKEND_RUNNING" = false ]; then
echo "Starting OpenFang backend..."
STARTED=false
# Method 1: Use openfang CLI
if command -v openfang &> /dev/null; then
openfang start &
STARTED=true
fi
# Method 2: Use the project's start script
if [ "$STARTED" = false ] && [ -f "$PROJECT_ROOT/start-all.sh" ]; then
"$PROJECT_ROOT/start-all.sh" &
STARTED=true
fi
if [ "$STARTED" = false ]; then
error "Cannot start backend service"
echo "Please start OpenFang manually:"
echo " openfang start"
exit 1
fi
# Wait for backend
echo "Waiting for backend to start..."
RETRIES=0
MAX_RETRIES=15
while [ $RETRIES -lt $MAX_RETRIES ]; do
sleep 1
if curl -s --connect-timeout 2 "http://127.0.0.1:50051/api/health" > /dev/null 2>&1; then
success "Backend started successfully"
break
fi
RETRIES=$((RETRIES + 1))
printf "."
done
if [ $RETRIES -ge $MAX_RETRIES ]; then
error "Backend startup timeout"
echo "Please check if OpenFang is properly installed"
exit 1
fi
fi
fi
# 5. Start development environment
step "Starting development environment..."
cd "$PROJECT_ROOT"
if [ "$DESKTOP_ONLY" = true ]; then
echo "Starting desktop only..."
pnpm desktop
else
echo "Starting full development environment..."
pnpm start:dev
fi