From 950303ced53bd31aaf76116f09571d44e52f8367 Mon Sep 17 00:00:00 2001 From: congsh Date: Thu, 5 Feb 2026 16:21:25 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E6=9B=B4=E6=96=B0=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=92=8C=E6=B8=85=E7=90=86=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CLAUDE.md | 276 ++++++++ Dockerfile | 2 +- PoC总结.md | 263 -------- PoC验证.md | 1090 ------------------------------- README.md | 251 +------ docker-compose.yml | 14 +- src/minenasai/gateway/server.py | 5 +- 7 files changed, 287 insertions(+), 1614 deletions(-) create mode 100644 CLAUDE.md delete mode 100644 PoC总结.md delete mode 100644 PoC验证.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..99cdec6 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,276 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## 开发命令 + +### 安装与设置 + +```bash +# 安装依赖(包含开发工具) +pip install -e ".[dev]" + +# 安装 pre-commit 钩子 +pre-commit install + +# 复制环境变量模板 +cp .env.example .env +# 编辑 .env 文件,填入至少一个 LLM API Key +``` + +### 代码质量 + +```bash +# 格式化代码 +ruff format src tests + +# 检查代码规范 +ruff check src tests + +# 类型检查 +mypy src +``` + +### 测试 + +```bash +# 运行所有测试 +pytest + +# 带覆盖率报告 +pytest --cov=minenasai + +# 运行单个测试文件 +pytest tests/test_core.py -v + +# 运行特定测试 +pytest tests/test_core.py::test_config_load -v +``` + +### 运行服务 + +```bash +# Gateway 服务(主服务) +python -m uvicorn minenasai.gateway.server:app --port 8000 + +# Web TUI 服务(另一个终端) +python -m uvicorn minenasai.webtui.server:app --port 8080 +``` + +### Docker 部署 + +```bash +# 构建并启动所有服务 +docker-compose up -d + +# 查看日志 +docker-compose logs -f gateway + +# 停止服务 +docker-compose down +``` + +## 项目架构 + +### 核心设计 + +MineNASAI 是一个基于 NAS 的智能个人 AI 助理,采用智能路由架构,根据任务复杂度自动选择最优处理方式: + +1. **简单任务** → 快速执行通道(Python 沙箱) +2. **中等复杂度** → Agent 执行(多 LLM API) +3. **复杂任务** → Web TUI(SSH + 深度编程) + +### 模块结构 + +``` +src/minenasai/ +├── core/ # 核心基础设施 +│ ├── config.py # 配置管理(支持环境变量覆盖) +│ ├── logging.py # 结构化日志(structlog) +│ ├── database.py # 数据库(aiosqlite) +│ ├── monitoring.py # 健康检查与监控指标 +│ └── cache.py # 缓存与限流 +│ +├── gateway/ # Gateway 服务(FastAPI) +│ ├── server.py # 主服务器 +│ ├── router.py # 智能路由器(任务复杂度评估) +│ ├── protocol/ # WebSocket 消息协议 +│ └── channels/ # 通讯渠道(企业微信/飞书) +│ +├── llm/ # LLM 集成层 +│ ├── manager.py # LLM 管理器(统一接口) +│ ├── base.py # 基础抽象 +│ └── clients/ # 各提供商客户端 +│ ├── anthropic.py # Claude(需代理) +│ ├── deepseek.py # DeepSeek(国内) +│ ├── zhipu.py # 智谱(国内) +│ ├── minimax.py # MiniMax(国内) +│ ├── moonshot.py # Moonshot(国内) +│ ├── openai_compat.py # OpenAI 兼容接口 +│ └── gemini.py # Gemini(需代理) +│ +├── agent/ # Agent 运行时 +│ ├── runtime.py # Agent 执行引擎 +│ ├── permissions.py # 权限与危险等级管理 +│ ├── tool_registry.py # 工具注册中心 +│ └── tools/ # 内置工具 +│ +├── webtui/ # Web TUI 服务 +│ ├── server.py # TUI FastAPI 服务器 +│ ├── auth.py # 会话认证 +│ └── ssh_manager.py # SSH 连接管理 +│ +└── scheduler/ # 定时任务 + └── cron.py # Cron 调度器 +``` + +### 配置系统 + +配置加载优先级:**环境变量 > 配置文件 > 默认值** + +- 配置文件:`config/config.json5`(JSON5 格式,支持注释) +- 环境变量前缀:`MINENASAI_`(嵌套配置使用 `__` 分隔) +- 示例: + - `MINENASAI_LLM__DEFAULT_PROVIDER=anthropic` + - `MINENASAI_PROXY__HTTP=http://127.0.0.1:7890` + +关键配置项: +- `router.mode`: 路由模式(`agent` 或 `heuristic`) +- `llm.default_provider`: 默认 LLM 提供商 +- `proxy.enabled`: 是否启用代理(境外 API 需要) + +### 智能路由器 + +位置:[gateway/router.py](src/minenasai/gateway/router.py) + +根据以下因素评估任务复杂度: +- 文本长度 +- 关键词匹配(简单/复杂/工具关键词) +- 代码块检测 +- 多步骤指令检测 + +支持命令前缀覆盖: +- `/快速` 或 `/简单` → 强制快速执行 +- `/深度`、`/复杂` 或 `/tui` → 强制 Web TUI + +## 编码规范 + +### 通用规范 + +- **必须使用中文进行交流和注释** +- 文件编码:UTF-8 +- Python 3.11+ +- 使用类型注解(type hints) +- Docstring 使用中文简洁说明 +- 函数添加必要注释 + +### Git 提交规范 + +使用中文提交信息: +- `feat: 添加xxx功能` +- `fix: 修复xxx问题` +- `docs: 更新文档` +- `refactor: 重构xxx` +- `test: 添加测试` + +### 文档规范 + +**重要:避免过度文档化** + +- 仅在明确需要时生成文档 +- 文档必须使用中文命名 +- 代码优先,文档次之 +- 先实现 MVP,再迭代优化 + +文档命名规范: +- 设计文档:`设计-[主题].md` +- 技术方案:`方案-[主题].md` +- 问题记录:`问题-[描述].md` +- 进度跟踪:`进度.md` + +## LLM 提供商 + +### 境内 API(无需代理) + +- **DeepSeek**: `deepseek-chat` +- **智谱**: `glm-4-flash` +- **MiniMax**: `abab6.5s-chat` +- **Moonshot**: `moonshot-v1-8k` + +### 境外 API(需要代理) + +- **Anthropic Claude**: `claude-sonnet-4-20250514` +- **OpenAI**: `gpt-4o` +- **Google Gemini**: `gemini-2.0-flash` + +### 代理配置 + +境外 API 需要配置代理(在 `.env` 中): +```bash +MINENASAI_PROXY__ENABLED=true +MINENASAI_PROXY__HTTP=http://127.0.0.1:7890 +MINENASAI_PROXY__HTTPS=http://127.0.0.1:7890 +``` + +系统支持自动检测常见代理端口(7890, 7891, 1080, 1087, 10808) + +## 测试 + +当前测试覆盖(131 tests): +- `test_core.py`: 配置、日志(9 tests) +- `test_gateway.py`: 协议、路由(14 tests) +- `test_llm.py`: LLM 客户端(10 tests) +- `test_monitoring.py`: 监控、健康检查(17 tests) +- `test_cache.py`: 缓存、限流(21 tests) +- `test_permissions.py`: 权限、工具注册(17 tests) +- `test_scheduler.py`: Cron 调度(15 tests) +- `test_tools.py`: 内置工具(14 tests) +- `test_webtui.py`: Web TUI(14 tests) + +## API 端点 + +| 端点 | 说明 | +|------|------| +| `/health` | 完整健康检查 | +| `/health/live` | 存活检查(K8s) | +| `/health/ready` | 就绪检查(K8s) | +| `/metrics` | 监控指标 | +| `/ws` | WebSocket 消息通道 | +| `/api/agents` | Agent 列表 | +| `/api/sessions` | 会话列表 | +| `/webhook/wework` | 企业微信回调 | +| `/webhook/feishu` | 飞书回调 | + +## 常见任务 + +### 添加新的 LLM 客户端 + +1. 在 `src/minenasai/llm/clients/` 创建新文件 +2. 继承 `BaseLLMClient`([llm/base.py](src/minenasai/llm/base.py)) +3. 实现 `chat()` 方法 +4. 在 `llm/manager.py` 注册客户端 +5. 在 `core/config.py` 添加配置字段 +6. 在 `.env.example` 添加环境变量模板 + +### 添加新的通讯渠道 + +1. 在 `src/minenasai/gateway/channels/` 创建新文件 +2. 继承 `BaseChannel`([channels/base.py](src/minenasai/gateway/channels/base.py)) +3. 实现 `send_message()` 和 `verify_signature()` 方法 +4. 在 `config/config.json5` 添加渠道配置 +5. 在 Gateway 服务器注册 webhook 路由 + +### 添加新的 Agent 工具 + +1. 在 `src/minenasai/agent/tools/` 创建或扩展工具文件 +2. 工具函数需要包含类型注解和中文 docstring +3. 在 `agent/tool_registry.py` 注册工具 +4. 在 `config/config.json5` 配置权限级别 + +## 注意事项 + +- 维护 `进度.md` 文件记录关键进展 +- 重大技术决策需要记录理由 +- 遇到问题优先查看现有代码和文档 +- 不确定时先问,再动手 +- 所有代码必须通过 ruff 和 mypy 检查后再提交 diff --git a/Dockerfile b/Dockerfile index a4c9bac..9d7ef9f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ && rm -rf /var/lib/apt/lists/* # 复制项目文件 -COPY pyproject.toml ./ +COPY pyproject.toml README.md ./ COPY src/ ./src/ # 安装依赖到虚拟环境 diff --git a/PoC总结.md b/PoC总结.md deleted file mode 100644 index d19ee0a..0000000 --- a/PoC总结.md +++ /dev/null @@ -1,263 +0,0 @@ -# MineNASAI - PoC 验证总结 - -**日期**: 2025-02-04 -**状态**: PoC 验证完成 - ---- - -## PoC 验证结果 - -### PoC 1: Claude Code CLI 集成 - -**状态**: ⚠️ 部分可行 - -**测试结果**: -- ✅ Claude CLI 已安装(版本 2.1.31) -- ✅ Claude CLI 在命令行可正常运行 - ```bash - claude -p "今天上海温度" # 正常返回结果 - ``` -- ❌ Python `subprocess` 集成失败 - - 进程卡住不返回 - - 可能原因:缓冲问题、进程通信问题 - -**影响**: -- 核心功能(编程能力)依赖CLI,但集成有技术难度 -- 需要寻找替代方案或深入解决subprocess问题 - -**建议方案**: -1. **使用 Anthropic API**(最可靠) - - 优点:稳定、可控、易集成 - - 缺点:失去CLI的IDE集成能力 - -2. **混合方案**(推荐) - - 简单任务:使用API - - 复杂编程:在TUI中手动调用CLI - - 务实且风险低 - -3. **继续研究CLI集成** - - 深入调试subprocess问题 - - 尝试文件重定向、异步IO等方案 - - 时间成本高,不确定性大 - ---- - -### PoC 2: 智能路由算法 - -**状态**: ✅ 验证通过 - -**测试结果**: -- ✅ 启发式规则准确率: **85.7%** (6/7) -- ✅ 超过70%门槛 -- ✅ 响应速度快(< 1ms) - -**测试用例**: -| 用例 | 消息 | 预期 | 实际 | 结果 | -|------|------|------|------|------| -| 1 | NAS状态? | fast | fast | ✅ | -| 2 | 搜索最新的Python教程 | fast | fast | ✅ | -| 3 | 实现一个Web服务 | deep | deep | ✅ | -| 4 | 重构这个模块 | deep | deep | ✅ | -| 5 | 修改配置文件中的端口 | medium | medium | ✅ | -| 6 | 添加一个新的API端点 | medium | medium | ✅ | -| 7 | 长文本分析任务 | medium | deep | ❌ | - -**结论**: -- 启发式规则足够应对大部分场景 -- 可后续优化规则或引入LLM增强 - ---- - -### PoC 3: MCP Server 加载 - -**状态**: ⚠️ 测试未完成 - -**遇到问题**: -- Node.js 和 npx 已安装 -- MCP Server 进程启动后无响应 -- 可能原因:协议通信、进程管理问题 - -**建议**: -- MCP Server集成复杂度较高 -- 可作为Phase 2或更后期的功能 -- 先用内置工具和API实现MVP - ---- - -## 总体评估 - -### 可行性结论 - -✅ **项目整体可行**,但需要调整技术方案 - -| 组件 | 可行性 | 风险 | 建议 | -|------|--------|------|------| -| Claude CLI | ⚠️ 部分 | 高 | 改用API或混合方案 | -| 智能路由 | ✅ 可行 | 低 | 启发式规则足够 | -| MCP Server | ⚠️ 待定 | 中 | 延后或简化 | -| 其他组件 | ✅ 可行 | 低 | 技术栈成熟 | - ---- - -## 推荐技术方案调整 - -### 方案A: 使用 Anthropic API(推荐) - -**修改内容**: -- Agent运行时直接使用 `anthropic` SDK -- 去掉 Claude CLI 桥接模块 -- TUI仅用于监控和管理 - -**优点**: -- ✅ 稳定可靠 -- ✅ 开发速度快 -- ✅ 易于测试和调试 -- ✅ 完整的工具调用支持 - -**缺点**: -- ❌ 失去CLI的特殊能力(如IDE集成) -- ❌ 无法利用Claude Code的高级功能 - -**影响**: -- Phase 3(Claude CLI集成)工作量大幅减少 -- 整体开发周期缩短约2周 - ---- - -### 方案B: 混合方案(平衡) - -**实现方式**: -1. **日常任务**:使用 Anthropic API - - 企业微信/飞书消息处理 - - 简单查询和对话 - - 工具调用 - -2. **复杂编程**:手动调用 Claude CLI - - 在TUI中提供CLI快捷入口 - - 用户主动选择使用CLI模式 - - 结果可回传到知识库 - -**优点**: -- ✅ 保留CLI的编程能力 -- ✅ API部分稳定可靠 -- ✅ 用户可按需选择 - -**缺点**: -- ⚠️ 体验不够无缝 -- ⚠️ 需要手动切换 - ---- - -### 方案C: Web TUI集成(用户建议 ✅ 推荐) - -**实现方式**: -1. **简单任务**:使用 Anthropic API - - 企业微信/飞书消息处理 - - 日常查询、简单操作 - - API稳定高效 - -2. **复杂编程任务**:Web TUI + SSH + Claude CLI - ``` - 消息提示 "请在Web TUI处理" - ↓ - 用户打开Web终端页面 - ↓ - xterm.js显示终端界面 - ↓ - WebSocket连接后端 - ↓ - paramiko SSH连接localhost - ↓ - 直接运行 claude 命令 - ↓ - 用户在浏览器中与Claude交互 - ``` - -**核心优势**: -- ✅ **完全避开subprocess问题** - 不做进程间通信 -- ✅ **保留CLI完整能力** - 用户直接操作,无限制 -- ✅ **实现简单** - xterm.js成熟稳定 -- ✅ **体验自然** - 像使用SSH工具一样 -- ✅ **权限隔离** - SSH本身就是隔离机制 -- ✅ **跨平台** - 浏览器即可访问 - -**技术栈**: -- 前端:xterm.js(Web终端模拟器) -- 通信:WebSocket(双向I/O) -- 后端:paramiko(Python SSH库) -- 连接:SSH localhost - -**影响**: -- Phase 3工作量适中(约5-7天) -- 无subprocess调试成本 -- 用户体验最优 - ---- - -## 下一步建议 - -### 立即行动 - -1. **✅ 采用方案C(Web TUI集成)** - - 简单任务用Anthropic API - - 复杂任务用Web TUI + SSH + Claude CLI - - 避免所有subprocess问题 - - 保留完整CLI能力 - -2. **开始 Phase 0: 项目初始化** - - 创建项目结构 - - 配置开发环境 - - 设置依赖管理 - -3. **✅ 设计文档已更新** - - 技术栈已调整 - - Phase 3为Web TUI集成 - - 时间估算已优化 - -### 风险管理 - -**已降低的风险**: -- ✅ 智能路由效果 → 85.7%准确率,风险低 -- ✅ Python技术栈 → 成熟可靠 - -**需要关注的风险**: -- ⚠️ MCP Server集成 → 建议延后 -- ⚠️ 性能优化 → 需要后期压力测试 - ---- - -## 资源和时间重估 - -### 方案C(Web TUI集成)✅ 采用 - -| Phase | 原估算 | 新估算 | 变化 | 说明 | -|-------|--------|--------|------|------| -| Phase 0 | 2-3天 | 2-3天 | 不变 | 项目初始化 | -| Phase 1 | 14-21天 | 14-21天 | 不变 | Gateway + 通讯 | -| Phase 2 | 14-21天 | **10-14天** | ⬇️ 简化 | 暂不做MCP/RAG | -| Phase 3 | 12-17天 | **7-10天** | ⬇️ 减少 | Web TUI + API | -| Phase 4 | 10-14天 | 10-14天 | 不变 | 高级特性 | -| Phase 5 | 7-10天 | 7-10天 | 不变 | 生产就绪 | - -**新总计**: 52-81天(优化约7-12天) - -**技术债务降低**: -- ❌ 无subprocess调试成本 -- ❌ 无MCP集成复杂度(可选) -- ❌ 无RAG初期成本(可选) -- ✅ Web TUI成熟方案 - ---- - -## 附录:PoC 验证文件 - -- `poc/router_test/poc_2_heuristic.py` - 智能路由测试(✅ 通过) -- `poc/claude_cli_test/poc_1_basic.py` - CLI基础测试(⚠️ 问题) -- `poc/mcp_test/poc_3_basic.py` - MCP连接测试(⚠️ 未完成) - ---- - -**PoC验证完成时间**: 2025-02-04 16:55 -**方案确定时间**: 2025-02-04 17:10 -**采用方案**: ✅ 方案C - Web TUI集成 -**下一步**: 开始Phase 0项目初始化 diff --git a/PoC验证.md b/PoC验证.md deleted file mode 100644 index 1071409..0000000 --- a/PoC验证.md +++ /dev/null @@ -1,1090 +0,0 @@ -# MineNASAI - PoC 验证计划 - -**创建日期**: 2025-02-04 -**目标**: 验证3个关键技术的可行性 -**预计时间**: 2-3天 - ---- - -## 验证目标 - -### 为什么需要 PoC? - -在投入大量时间开发之前,我们需要验证以下关键技术的可行性: - -1. **Claude Code CLI 集成** (最高优先级) - - 风险:子进程管理、输出解析复杂 - - 影响:这是核心功能,如果不可行需要重新设计 - -2. **智能路由算法** - - 风险:路由准确度不足 - - 影响:影响用户体验和资源利用率 - -3. **MCP Server 加载** - - 风险:MCP协议不熟悉、进程通信复杂 - - 影响:工具扩展能力的基础 - ---- - -## PoC 1: Claude Code CLI 集成 - -### 目标 -验证可以通过 Python 子进程调用 Claude Code CLI,并正确解析其输出。 - -### 验证内容 -- [ ] 子进程启动和管理 -- [ ] 实时输出流捕获 -- [ ] ANSI 转义序列处理 -- [ ] 交互式输入处理 -- [ ] 超时和资源限制 -- [ ] 错误处理和恢复 - -### 实施步骤 - -#### 步骤1: 环境准备 - -```bash -# 1. 确保已安装 Claude Code CLI -# 如果没有,访问: https://docs.anthropic.com/claude/docs/claude-code - -# 2. 验证 CLI 可用 -claude --version - -# 3. 测试基本调用 -claude "print hello world in python" - -# 4. 创建 PoC 工作目录 -mkdir -p poc/claude_cli_test -cd poc/claude_cli_test -``` - -#### 步骤2: 基础子进程调用 (poc_1_basic.py) - -```python -"""PoC 1.1: Basic Claude CLI subprocess call.""" -import subprocess -import sys - -def test_basic_call(): - """测试基本的 CLI 调用.""" - print("=== PoC 1.1: Basic CLI Call ===\n") - - # 简单命令 - cmd = ["claude", "print hello world in python"] - - print(f"执行命令: {' '.join(cmd)}") - print("-" * 60) - - try: - # 使用 subprocess.run - result = subprocess.run( - cmd, - capture_output=True, - text=True, - timeout=30, - ) - - print("STDOUT:") - print(result.stdout) - print("\nSTDERR:") - print(result.stderr) - print(f"\n退出码: {result.returncode}") - - if result.returncode == 0: - print("\n✅ 基础调用成功!") - return True - else: - print("\n❌ 命令执行失败") - return False - - except subprocess.TimeoutExpired: - print("\n❌ 命令超时") - return False - except Exception as e: - print(f"\n❌ 异常: {e}") - return False - - -if __name__ == "__main__": - success = test_basic_call() - sys.exit(0 if success else 1) -``` - -**验收标准**: -- [ ] 脚本可以成功调用 Claude CLI -- [ ] 可以捕获完整输出 -- [ ] 超时机制生效 - -**运行测试**: -```bash -python poc_1_basic.py -``` - ---- - -#### 步骤3: 实时输出流捕获 (poc_1_streaming.py) - -```python -"""PoC 1.2: Real-time output streaming.""" -import subprocess -import sys -import select -import os - - -def test_streaming_output(): - """测试实时输出流捕获.""" - print("=== PoC 1.2: Streaming Output ===\n") - - cmd = ["claude", "count to 10 with 1 second delays in python"] - - print(f"执行命令: {' '.join(cmd)}") - print("-" * 60) - - try: - # 使用 Popen 进行流式输出 - process = subprocess.Popen( - cmd, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - text=True, - bufsize=1, # 行缓冲 - ) - - print("实时输出:") - - # 实时读取输出 - while True: - # 检查进程是否结束 - if process.poll() is not None: - break - - # 读取一行输出 - line = process.stdout.readline() - if line: - print(f"[OUT] {line.rstrip()}") - - # 读取错误输出 - # 注意: stderr 需要非阻塞读取或使用 select - - # 获取剩余输出 - remaining_out, remaining_err = process.communicate() - if remaining_out: - print(remaining_out) - - print(f"\n退出码: {process.returncode}") - - if process.returncode == 0: - print("\n✅ 流式输出捕获成功!") - return True - else: - print("\n❌ 进程执行失败") - return False - - except Exception as e: - print(f"\n❌ 异常: {e}") - return False - - -if __name__ == "__main__": - success = test_streaming_output() - sys.exit(0 if success else 1) -``` - -**验收标准**: -- [ ] 可以实时捕获输出(不是等待结束) -- [ ] 输出不会丢失 -- [ ] 可以正确检测进程结束 - -**运行测试**: -```bash -python poc_1_streaming.py -``` - ---- - -#### 步骤4: PTY 伪终端处理 (poc_1_pty.py) - -```python -"""PoC 1.3: PTY pseudo-terminal for interactive handling.""" -import pty -import os -import sys -import select -import subprocess - - -def test_pty_terminal(): - """测试 PTY 伪终端处理.""" - print("=== PoC 1.3: PTY Terminal ===\n") - - cmd = ["claude", "create a simple python calculator"] - - print(f"执行命令: {' '.join(cmd)}") - print("-" * 60) - - try: - # 创建 PTY - master, slave = pty.openpty() - - # 启动进程 - process = subprocess.Popen( - cmd, - stdin=slave, - stdout=slave, - stderr=slave, - close_fds=True, - ) - - os.close(slave) # 子进程已继承,关闭父进程的副本 - - print("实时输出 (PTY):") - output_buffer = [] - - # 读取输出 - while True: - # 检查进程是否结束 - if process.poll() is not None: - break - - # 使用 select 进行非阻塞读取 - r, w, e = select.select([master], [], [], 0.1) - - if master in r: - try: - data = os.read(master, 1024) - if data: - text = data.decode('utf-8', errors='replace') - print(text, end='') - output_buffer.append(text) - except OSError: - break - - os.close(master) - - print(f"\n\n退出码: {process.returncode}") - print(f"总输出长度: {len(''.join(output_buffer))} 字符") - - if process.returncode == 0: - print("\n✅ PTY 终端处理成功!") - return True - else: - print("\n❌ 进程执行失败") - return False - - except Exception as e: - print(f"\n❌ 异常: {e}") - import traceback - traceback.print_exc() - return False - - -if __name__ == "__main__": - success = test_pty_terminal() - sys.exit(0 if success else 1) -``` - -**验收标准**: -- [ ] PTY 可以正确创建 -- [ ] 可以处理交互式输出 -- [ ] ANSI 转义序列正确显示 - -**运行测试**: -```bash -python poc_1_pty.py -``` - ---- - -#### 步骤5: 完整集成示例 (poc_1_full.py) - -```python -"""PoC 1.4: Full Claude CLI integration.""" -import asyncio -import pty -import os -import select -import subprocess -from dataclasses import dataclass -from typing import Optional - - -@dataclass -class CLIResult: - """CLI execution result.""" - exit_code: int - output: str - error: Optional[str] = None - duration_ms: int = 0 - - -class ClaudeCLI: - """Claude CLI wrapper.""" - - def __init__(self, timeout: int = 300): - """Initialize CLI wrapper.""" - self.timeout = timeout - - async def execute(self, prompt: str, workspace: str = ".") -> CLIResult: - """ - Execute Claude CLI command. - - Args: - prompt: 任务提示 - workspace: 工作目录 - - Returns: - CLIResult with output - """ - import time - start_time = time.time() - - cmd = ["claude", prompt] - - try: - # 创建 PTY - master, slave = pty.openpty() - - # 启动进程 - process = subprocess.Popen( - cmd, - stdin=slave, - stdout=slave, - stderr=slave, - cwd=workspace, - close_fds=True, - ) - - os.close(slave) - - # 收集输出 - output_buffer = [] - - # 读取输出 (带超时) - timeout_time = start_time + self.timeout - - while True: - # 检查超时 - if time.time() > timeout_time: - process.kill() - raise TimeoutError(f"Command timeout after {self.timeout}s") - - # 检查进程是否结束 - if process.poll() is not None: - break - - # 非阻塞读取 - r, w, e = select.select([master], [], [], 0.1) - - if master in r: - try: - data = os.read(master, 4096) - if data: - text = data.decode('utf-8', errors='replace') - output_buffer.append(text) - except OSError: - break - - os.close(master) - - duration_ms = int((time.time() - start_time) * 1000) - output = ''.join(output_buffer) - - return CLIResult( - exit_code=process.returncode, - output=output, - duration_ms=duration_ms, - ) - - except TimeoutError as e: - return CLIResult( - exit_code=-1, - output=''.join(output_buffer), - error=str(e), - duration_ms=int((time.time() - start_time) * 1000), - ) - except Exception as e: - return CLIResult( - exit_code=-1, - output='', - error=str(e), - duration_ms=int((time.time() - start_time) * 1000), - ) - - -async def test_full_integration(): - """测试完整集成.""" - print("=== PoC 1.4: Full Integration ===\n") - - cli = ClaudeCLI(timeout=60) - - # 测试用例1: 简单任务 - print("测试1: 简单Python脚本") - print("-" * 60) - - result = await cli.execute("create a hello world python script") - - print(f"输出:\n{result.output}") - print(f"\n退出码: {result.exit_code}") - print(f"耗时: {result.duration_ms}ms") - - if result.exit_code == 0: - print("✅ 测试1通过") - else: - print(f"❌ 测试1失败: {result.error}") - return False - - # 测试用例2: 需要多步骤的任务 - print("\n\n测试2: 多步骤任务") - print("-" * 60) - - result = await cli.execute( - "create a simple REST API with FastAPI that has a hello endpoint" - ) - - print(f"输出:\n{result.output[:500]}...") # 只显示前500字符 - print(f"\n退出码: {result.exit_code}") - print(f"耗时: {result.duration_ms}ms") - - if result.exit_code == 0: - print("✅ 测试2通过") - else: - print(f"❌ 测试2失败: {result.error}") - return False - - print("\n" + "=" * 60) - print("✅ 完整集成验证通过!") - print("=" * 60) - - return True - - -if __name__ == "__main__": - success = asyncio.run(test_full_integration()) - import sys - sys.exit(0 if success else 1) -``` - -**验收标准**: -- [ ] 封装类可以正常工作 -- [ ] 支持异步调用 -- [ ] 超时控制有效 -- [ ] 错误处理完善 -- [ ] 可以处理简单和复杂任务 - -**运行测试**: -```bash -python poc_1_full.py -``` - ---- - -### PoC 1 总结 - -完成上述5个步骤后,填写以下清单: - -**验证结果**: -- [ ] 基础调用可行 -- [ ] 流式输出捕获可行 -- [ ] PTY终端处理可行 -- [ ] 完整集成验证通过 -- [ ] 性能可接受 (大多数任务 < 1分钟) - -**发现的问题**: -1. -2. -3. - -**需要的改进**: -1. -2. -3. - -**结论**: -- [ ] ✅ 可行,建议使用 PTY + asyncio 方案 -- [ ] ⚠️ 部分可行,需要调整设计 -- [ ] ❌ 不可行,需要备选方案 - ---- - -## PoC 2: 智能路由算法 - -### 目标 -验证路由算法可以合理地将任务分类为 fast/medium/deep 三种模式。 - -### 验证内容 -- [ ] 启发式规则准确度 -- [ ] LLM-based 路由可行性 -- [ ] 用户指令覆盖 -- [ ] 路由性能 (响应时间) - -### 实施步骤 - -#### 步骤1: 启发式规则测试 (poc_2_heuristic.py) - -```python -"""PoC 2.1: Heuristic routing rules.""" -from dataclasses import dataclass -from typing import Literal - - -@dataclass -class RoutingDecision: - """Routing decision.""" - mode: Literal["fast", "medium", "deep"] - reason: str - confidence: float # 0.0 - 1.0 - - -class HeuristicRouter: - """Heuristic-based router.""" - - def __init__(self): - """Initialize rules.""" - self.rules = { - "fast_keywords": ["状态", "查询", "搜索", "是什么", "?", "?"], - "deep_keywords": ["实现", "开发", "编写", "重构", "优化", "设计", "创建"], - "medium_keywords": ["修改", "更新", "添加", "删除"], - } - - def evaluate(self, message: str) -> RoutingDecision: - """Evaluate routing decision.""" - message_lower = message.lower() - length = len(message) - - # 规则1: 短消息 + 查询关键词 -> fast - if length < 50 and any(kw in message_lower for kw in self.rules["fast_keywords"]): - return RoutingDecision( - mode="fast", - reason="短消息且包含查询关键词", - confidence=0.9, - ) - - # 规则2: 包含开发关键词 -> deep - deep_count = sum(1 for kw in self.rules["deep_keywords"] if kw in message_lower) - if deep_count >= 1: - return RoutingDecision( - mode="deep", - reason=f"包含 {deep_count} 个开发关键词", - confidence=0.7 + min(deep_count * 0.1, 0.2), - ) - - # 规则3: 中等长度 + 修改关键词 -> medium - if 50 <= length <= 200 and any(kw in message_lower for kw in self.rules["medium_keywords"]): - return RoutingDecision( - mode="medium", - reason="中等长度且包含修改关键词", - confidence=0.6, - ) - - # 规则4: 长消息 -> medium/deep - if length > 200: - return RoutingDecision( - mode="medium", - reason="消息较长,可能需要多步处理", - confidence=0.5, - ) - - # 默认: medium - return RoutingDecision( - mode="medium", - reason="默认中等复杂度", - confidence=0.4, - ) - - -def test_heuristic_router(): - """测试启发式路由.""" - print("=== PoC 2.1: Heuristic Router ===\n") - - router = HeuristicRouter() - - # 测试用例 - test_cases = [ - ("NAS状态?", "fast"), - ("搜索最新的Python教程", "fast"), - ("实现一个Web服务", "deep"), - ("重构这个模块", "deep"), - ("修改配置文件中的端口", "medium"), - ("添加一个新的API端点", "medium"), - ("这是一段很长的描述,我需要你帮我分析一下这个系统的架构,然后给出优化建议,包括性能、安全性和可维护性等多个方面", "medium"), - ] - - correct = 0 - total = len(test_cases) - - print(f"测试用例数: {total}\n") - - for i, (message, expected) in enumerate(test_cases, 1): - decision = router.evaluate(message) - is_correct = decision.mode == expected - correct += is_correct - - status = "✅" if is_correct else "❌" - print(f"{status} 用例 {i}:") - print(f" 消息: {message}") - print(f" 预期: {expected}") - print(f" 实际: {decision.mode} (置信度: {decision.confidence:.2f})") - print(f" 理由: {decision.reason}") - print() - - accuracy = correct / total - print("=" * 60) - print(f"准确率: {accuracy:.1%} ({correct}/{total})") - print("=" * 60) - - if accuracy >= 0.7: - print("\n✅ 启发式规则准确度可接受 (>= 70%)") - return True - else: - print(f"\n⚠️ 准确度较低 ({accuracy:.1%}), 建议优化规则或使用LLM") - return False - - -if __name__ == "__main__": - import sys - success = test_heuristic_router() - sys.exit(0 if success else 1) -``` - -**验收标准**: -- [ ] 准确率 >= 70% -- [ ] 置信度评分合理 -- [ ] 响应时间 < 10ms - -**运行测试**: -```bash -python poc_2_heuristic.py -``` - ---- - -#### 步骤2: LLM 路由测试 (poc_2_llm.py) - -```python -"""PoC 2.2: LLM-based routing.""" -import asyncio -import os -from anthropic import AsyncAnthropic - - -class LLMRouter: - """LLM-based router using Claude Haiku.""" - - def __init__(self, api_key: str): - """Initialize with API key.""" - self.client = AsyncAnthropic(api_key=api_key) - self.model = "claude-3-5-haiku-20241022" - - async def evaluate(self, message: str) -> dict: - """Evaluate using Claude Haiku.""" - system_prompt = """ -你是一个智能路由助手。分析用户消息,判断任务复杂度: - -- **fast**: 简单查询,不需要复杂工具 (<1000 tokens) - 例如: "NAS状态?", "搜索xxx", "是什么" - -- **medium**: 中等任务,需要少量工具调用 (<5000 tokens) - 例如: "修改配置", "添加功能", "更新文档" - -- **deep**: 复杂任务,需要编程或多步骤处理 (>5000 tokens) - 例如: "实现xxx", "重构xxx", "设计xxx" - -返回 JSON 格式: -{ - "mode": "fast|medium|deep", - "reason": "判断理由", - "confidence": 0.0-1.0 -} -""" - - try: - response = await self.client.messages.create( - model=self.model, - max_tokens=200, - system=system_prompt, - messages=[ - {"role": "user", "content": f"分析这个任务: {message}"} - ] - ) - - # 解析响应 - import json - text = response.content[0].text - - # 尝试提取JSON - if "{" in text and "}" in text: - json_str = text[text.find("{"):text.rfind("}")+1] - result = json.loads(json_str) - return result - else: - # 降级到启发式 - return {"mode": "medium", "reason": "LLM解析失败", "confidence": 0.5} - - except Exception as e: - print(f"LLM路由失败: {e}") - return {"mode": "medium", "reason": f"错误: {e}", "confidence": 0.0} - - -async def test_llm_router(): - """测试LLM路由.""" - print("=== PoC 2.2: LLM Router ===\n") - - # 检查API密钥 - api_key = os.getenv("ANTHROPIC_API_KEY") - if not api_key: - print("⚠️ 未设置 ANTHROPIC_API_KEY,跳过LLM测试") - return True - - router = LLMRouter(api_key) - - # 测试用例 - test_cases = [ - ("NAS状态?", "fast"), - ("实现一个Web服务", "deep"), - ("修改配置文件中的端口", "medium"), - ] - - print(f"测试用例数: {len(test_cases)}\n") - - for i, (message, expected) in enumerate(test_cases, 1): - print(f"用例 {i}: {message}") - result = await router.evaluate(message) - - is_correct = result["mode"] == expected - status = "✅" if is_correct else "❌" - - print(f" {status} 预期: {expected}, 实际: {result['mode']}") - print(f" 理由: {result.get('reason', 'N/A')}") - print(f" 置信度: {result.get('confidence', 0):.2f}") - print() - - print("✅ LLM路由可行(需要API费用)") - return True - - -if __name__ == "__main__": - success = asyncio.run(test_llm_router()) - import sys - sys.exit(0 if success else 1) -``` - -**验收标准**: -- [ ] LLM可以正确分类 -- [ ] 响应时间可接受 (< 2秒) -- [ ] API费用在预算内 - -**运行测试**: -```bash -export ANTHROPIC_API_KEY="your-api-key" -python poc_2_llm.py -``` - ---- - -### PoC 2 总结 - -**验证结果**: -- [ ] 启发式规则准确度: ____% -- [ ] LLM路由准确度: ____% -- [ ] LLM平均响应时间: ___ ms -- [ ] 单次LLM路由成本: $_____ - -**结论**: -- [ ] ✅ 启发式规则足够,先用规则 -- [ ] ✅ 启发式 + LLM混合(低置信度时调用LLM) -- [ ] ⚠️ 仅使用LLM(成本和延迟较高) - ---- - -## PoC 3: MCP Server 加载 - -### 目标 -验证可以动态加载和调用 MCP Server。 - -### 验证内容 -- [ ] MCP Server 发现和启动 -- [ ] MCP 协议通信 (stdio/sse) -- [ ] 工具调用和结果解析 -- [ ] 进程生命周期管理 - -### 实施步骤 - -#### 步骤1: 基础MCP连接 (poc_3_basic.py) - -```python -"""PoC 3.1: Basic MCP server connection.""" -import asyncio -import subprocess -import json - - -async def test_mcp_connection(): - """测试 MCP Server 连接.""" - print("=== PoC 3.1: MCP Connection ===\n") - - # 使用官方 filesystem MCP server - cmd = ["npx", "-y", "@modelcontextprotocol/server-filesystem", "/tmp"] - - print(f"启动 MCP Server: {' '.join(cmd)}") - print("-" * 60) - - try: - # 启动进程 - process = subprocess.Popen( - cmd, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - text=True, - ) - - # 发送 initialize 请求 - initialize_request = { - "jsonrpc": "2.0", - "id": 1, - "method": "initialize", - "params": { - "protocolVersion": "0.1.0", - "capabilities": {}, - "clientInfo": { - "name": "poc-test", - "version": "0.1.0" - } - } - } - - print("发送 initialize 请求...") - process.stdin.write(json.dumps(initialize_request) + "\n") - process.stdin.flush() - - # 读取响应 - response_line = process.stdout.readline() - response = json.loads(response_line) - - print(f"收到响应: {json.dumps(response, indent=2)}") - - if "result" in response: - print("\n✅ MCP 连接成功!") - print(f"Server capabilities: {response['result'].get('capabilities', {})}") - - # 清理 - process.terminate() - process.wait(timeout=5) - return True - else: - print(f"\n❌ 初始化失败: {response.get('error')}") - process.terminate() - return False - - except Exception as e: - print(f"\n❌ 异常: {e}") - import traceback - traceback.print_exc() - return False - - -if __name__ == "__main__": - success = asyncio.run(test_mcp_connection()) - import sys - sys.exit(0 if success else 1) -``` - -**验收标准**: -- [ ] MCP Server可以启动 -- [ ] initialize握手成功 -- [ ] 可以正确解析响应 - -**运行测试**: -```bash -python poc_3_basic.py -``` - ---- - -#### 步骤2: 工具调用测试 (poc_3_tools.py) - -```python -"""PoC 3.2: MCP tool calling.""" -import asyncio -import subprocess -import json - - -async def test_mcp_tools(): - """测试 MCP 工具调用.""" - print("=== PoC 3.2: MCP Tools ===\n") - - cmd = ["npx", "-y", "@modelcontextprotocol/server-filesystem", "/tmp"] - - try: - process = subprocess.Popen( - cmd, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - text=True, - ) - - # Initialize - initialize_request = { - "jsonrpc": "2.0", - "id": 1, - "method": "initialize", - "params": { - "protocolVersion": "0.1.0", - "capabilities": {}, - "clientInfo": {"name": "poc-test", "version": "0.1.0"} - } - } - - process.stdin.write(json.dumps(initialize_request) + "\n") - process.stdin.flush() - response = json.loads(process.stdout.readline()) - print(f"✓ Initialized") - - # List tools - list_tools_request = { - "jsonrpc": "2.0", - "id": 2, - "method": "tools/list", - "params": {} - } - - print("\n列出可用工具...") - process.stdin.write(json.dumps(list_tools_request) + "\n") - process.stdin.flush() - response = json.loads(process.stdout.readline()) - - if "result" in response: - tools = response["result"].get("tools", []) - print(f"✓ 找到 {len(tools)} 个工具:") - for tool in tools: - print(f" - {tool['name']}: {tool.get('description', 'N/A')}") - - # 测试调用一个工具 (read_file) - if tools: - print("\n测试调用工具...") - - # 创建测试文件 - test_file = "/tmp/mcp_test.txt" - with open(test_file, "w") as f: - f.write("Hello MCP!") - - call_tool_request = { - "jsonrpc": "2.0", - "id": 3, - "method": "tools/call", - "params": { - "name": "read_file", - "arguments": {"path": test_file} - } - } - - process.stdin.write(json.dumps(call_tool_request) + "\n") - process.stdin.flush() - response = json.loads(process.stdout.readline()) - - if "result" in response: - print(f"✓ 工具调用成功: {response['result']}") - print("\n✅ MCP 工具调用验证通过!") - - process.terminate() - return True - else: - print(f"❌ 工具调用失败: {response.get('error')}") - - process.terminate() - return False - - except Exception as e: - print(f"\n❌ 异常: {e}") - import traceback - traceback.print_exc() - return False - - -if __name__ == "__main__": - success = asyncio.run(test_mcp_tools()) - import sys - sys.exit(0 if success else 1) -``` - -**验收标准**: -- [ ] 可以列出工具 -- [ ] 可以调用工具 -- [ ] 结果解析正确 - -**运行测试**: -```bash -python poc_3_tools.py -``` - ---- - -### PoC 3 总结 - -**验证结果**: -- [ ] MCP Server 可以启动 -- [ ] 协议通信正常 -- [ ] 工具调用成功 -- [ ] 进程管理可控 - -**发现的问题**: -1. -2. - -**结论**: -- [ ] ✅ MCP 集成可行 -- [ ] ⚠️ 需要解决的问题: -- [ ] ❌ 不可行,需要替代方案 - ---- - -## 总体结论 - -完成所有 PoC 后,填写总体评估: - -### PoC 验证总结 - -| PoC | 状态 | 结论 | 备注 | -|-----|------|------|------| -| Claude CLI 集成 | ⏸️ | - | - | -| 智能路由算法 | ⏸️ | - | - | -| MCP Server 加载 | ⏸️ | - | - | - -### 风险评估更新 - -原有风险的验证结果: - -1. **Claude CLI集成复杂** (原风险等级: 高) - - PoC 结果: ____ - - 新风险等级: ____ - - 建议: ____ - -2. **智能路由效果不佳** (原风险等级: 中) - - PoC 结果: ____ - - 新风险等级: ____ - - 建议: ____ - -3. **MCP Server不稳定** (原风险等级: 中) - - PoC 结果: ____ - - 新风险等级: ____ - - 建议: ____ - -### 下一步建议 - -基于 PoC 结果: - -- [ ] ✅ 所有验证通过,可以开始 Phase 0 正式开发 -- [ ] ⚠️ 部分通过,需要调整设计后开发 -- [ ] ❌ 关键技术不可行,需要重新规划 - -具体行动: -1. -2. -3. - ---- - -**文档结束** diff --git a/README.md b/README.md index 60c6f63..4cd918c 100644 --- a/README.md +++ b/README.md @@ -1,250 +1 @@ -# MineNASAI - -基于 NAS 的智能个人 AI 助理,支持企业微信/飞书通讯,集成多 LLM 编程能力。 - -[![Python](https://img.shields.io/badge/Python-3.11+-blue.svg)](https://python.org) -[![Tests](https://img.shields.io/badge/Tests-131%20passed-green.svg)](tests/) -[![License](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) - -## 特性 - -- **多 LLM 支持**: Anthropic Claude、OpenAI、DeepSeek、智谱、MiniMax、Moonshot、Gemini -- **多渠道通讯**: 企业微信、飞书接入 -- **智能路由**: 自动识别任务复杂度,选择最优处理方式 -- **双界面模式**: - - 通讯工具:日常交互、简单任务 - - Web TUI:深度编程、复杂项目 -- **安全隔离**: Python 沙箱执行、权限分级、确认机制 -- **生产就绪**: 健康检查、监控指标、Docker 部署 -- **可扩展**: 工具注册中心、Cron 定时任务 - -## 快速开始 - -### 环境要求 - -- Python 3.11+ -- Redis (可选,用于任务队列) -- SSH 服务 (Web TUI 需要) - -### 安装 - -```bash -# 克隆项目 -git clone http://jiulu-gameplay.com.cn:13001/congsh/MineNasAI.git -cd MineNasAI - -# 创建虚拟环境 -python -m venv .venv -.venv\Scripts\activate # Windows -# source .venv/bin/activate # Linux/macOS - -# 安装依赖 -pip install -e ".[dev]" - -# 安装 pre-commit 钩子 -pre-commit install -``` - -### 配置 - -```bash -# 复制环境变量模板 -cp .env.example .env - -# 编辑 .env 文件,填入 API Key -# MINENASAI_ANTHROPIC_API_KEY=sk-ant-xxxxx -# MINENASAI_DEEPSEEK_API_KEY=sk-xxxxx -``` - -### 运行 - -```bash -# 启动 Gateway 服务 -python -m uvicorn minenasai.gateway.server:app --port 8000 - -# 启动 Web TUI 服务(另一个终端) -python -m uvicorn minenasai.webtui.server:app --port 8080 -``` - -### Docker 部署 - -```bash -# 构建并启动 -docker-compose up -d - -# 查看日志 -docker-compose logs -f gateway - -# 停止服务 -docker-compose down -``` - -## 项目结构 - -``` -MineNasAI/ -├── src/minenasai/ -│ ├── core/ # 核心模块 -│ │ ├── config.py # 配置管理 -│ │ ├── logging.py # 日志系统 -│ │ ├── database.py # 数据库 -│ │ ├── monitoring.py # 监控与健康检查 -│ │ └── cache.py # 缓存与限流 -│ ├── gateway/ # Gateway 服务 -│ │ ├── protocol/ # 消息协议 -│ │ ├── router.py # 智能路由 -│ │ ├── server.py # FastAPI 服务 -│ │ └── channels/ # 通讯渠道 -│ ├── llm/ # LLM 集成 -│ │ ├── base.py # 基础接口 -│ │ ├── manager.py # LLM 管理器 -│ │ └── clients/ # 各提供商客户端 -│ ├── agent/ # Agent 运行时 -│ │ ├── runtime.py # Agent 执行 -│ │ ├── permissions.py # 权限管理 -│ │ ├── tool_registry.py # 工具注册 -│ │ └── tools/ # 内置工具 -│ ├── scheduler/ # 定时任务 -│ │ └── cron.py # Cron 调度器 -│ └── webtui/ # Web TUI -│ ├── server.py # TUI 服务器 -│ ├── auth.py # 认证管理 -│ ├── ssh_manager.py # SSH 管理 -│ └── static/ # 前端文件 -├── tests/ # 测试用例 (131 tests) -├── config/ # 配置模板 -├── Dockerfile # Docker 构建 -└── docker-compose.yml # 容器编排 -``` - -## 架构概述 - -``` -┌─────────────────────────────────────────────────────────────┐ -│ 通讯接入层 (Channels) │ -│ 企业微信Bot 飞书Bot Web UI │ -└────────────────────────────┬────────────────────────────────┘ - │ -┌────────────────────────────┴────────────────────────────────┐ -│ Gateway 服务 (FastAPI) │ -│ WebSocket协议 / 监控指标 / 健康检查 / CORS │ -└────────────────────────────┬────────────────────────────────┘ - │ -┌────────────────────────────┴────────────────────────────────┐ -│ 智能路由层 (SmartRouter) │ -│ 任务复杂度评估 / 单/多Agent决策 │ -└────────────────────────────┬────────────────────────────────┘ - │ - ┌───────────────────┼───────────────────┐ - ↓ ↓ ↓ - ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ - │ 快速执行通道 │ │ 多 LLM │ │ Web TUI │ - │ Python沙箱 │ │ API │ │ SSH+Claude │ - └─────────────┘ └─────────────┘ └─────────────┘ - │ - ┌───────────────────┼───────────────────┐ - ↓ ↓ ↓ - Anthropic Claude DeepSeek/智谱 OpenAI/Gemini -``` - -## 支持的 LLM 提供商 - -| 提供商 | 模型示例 | 区域 | 代理 | -|--------|----------|------|------| -| Anthropic | claude-sonnet-4-20250514 | 境外 | 需要 | -| OpenAI | gpt-4o | 境外 | 需要 | -| Google | gemini-2.0-flash | 境外 | 需要 | -| DeepSeek | deepseek-chat | 国内 | 不需要 | -| 智谱 | glm-4-flash | 国内 | 不需要 | -| MiniMax | abab6.5s-chat | 国内 | 不需要 | -| Moonshot | moonshot-v1-8k | 国内 | 不需要 | - -## API 端点 - -| 端点 | 方法 | 说明 | -|------|------|------| -| `/` | GET | 服务状态 | -| `/health` | GET | 完整健康检查 | -| `/health/live` | GET | 存活检查 (K8s) | -| `/health/ready` | GET | 就绪检查 (K8s) | -| `/metrics` | GET | 监控指标 | -| `/ws` | WebSocket | 消息通道 | -| `/api/agents` | GET | Agent 列表 | -| `/api/sessions` | GET | 会话列表 | - -## 开发 - -### 代码规范 - -```bash -# 格式化代码 -ruff format src tests - -# 检查代码 -ruff check src tests - -# 类型检查 -mypy src -``` - -### 测试 - -```bash -# 运行所有测试 -pytest - -# 带覆盖率 -pytest --cov=minenasai - -# 详细输出 -pytest -v --tb=short -``` - -### 当前测试覆盖 - -- **test_core.py**: 配置、日志 (9 tests) -- **test_gateway.py**: 协议、路由 (14 tests) -- **test_llm.py**: LLM 客户端 (10 tests) -- **test_monitoring.py**: 监控、健康检查 (17 tests) -- **test_cache.py**: 缓存、限流 (21 tests) -- **test_permissions.py**: 权限、工具注册 (17 tests) -- **test_scheduler.py**: Cron 调度 (15 tests) -- **test_tools.py**: 内置工具 (14 tests) -- **test_webtui.py**: Web TUI (14 tests) - -## 配置说明 - -配置文件: `config/config.json5` - -主要配置项: - -| 配置项 | 说明 | 默认值 | -|--------|------|--------| -| `gateway.port` | Gateway 端口 | 8000 | -| `webtui.port` | Web TUI 端口 | 8080 | -| `llm.default_provider` | 默认 LLM 提供商 | anthropic | -| `llm.default_model` | 默认模型 | claude-sonnet-4-20250514 | -| `proxy.enabled` | 是否启用代理 | false | -| `router.mode` | 路由模式 | agent | - -## 环境变量 - -```bash -# LLM API Keys -MINENASAI_ANTHROPIC_API_KEY=sk-ant-xxx -MINENASAI_OPENAI_API_KEY=sk-xxx -MINENASAI_DEEPSEEK_API_KEY=sk-xxx -MINENASAI_ZHIPU_API_KEY=xxx -MINENASAI_MINIMAX_API_KEY=xxx -MINENASAI_MOONSHOT_API_KEY=sk-xxx -MINENASAI_GEMINI_API_KEY=xxx - -# 代理设置 (境外 API) -MINENASAI_PROXY_ENABLED=true -MINENASAI_PROXY_HTTP=http://127.0.0.1:7890 -MINENASAI_PROXY_HTTPS=http://127.0.0.1:7890 -``` - -## 许可证 - -MIT License +# MineNasAI diff --git a/docker-compose.yml b/docker-compose.yml index 97ef20a..cd6a142 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -30,9 +30,9 @@ services: - MINENASAI_PROXY_HTTP=${PROXY_HTTP:-} - MINENASAI_PROXY_HTTPS=${PROXY_HTTPS:-} volumes: - - minenasai-data:/app/data - - minenasai-logs:/app/logs - - ./config:/app/config:ro + - /volume2/docker/mineNasAi/data:/app/data + - /volume2/docker/mineNasAi/logs:/app/logs + - /volume2/docker/mineNasAi/config:/app/config:ro healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/health/live"] interval: 30s @@ -59,8 +59,8 @@ services: - MINENASAI_WEBTUI_HOST=0.0.0.0 - MINENASAI_WEBTUI_PORT=8080 volumes: - - minenasai-data:/app/data - - minenasai-logs:/app/logs + - /volume2/docker/mineNasAi/data:/app/data + - /volume2/docker/mineNasAi/logs:/app/logs command: ["python", "-m", "uvicorn", "minenasai.webtui.server:app", "--host", "0.0.0.0", "--port", "8080"] networks: - minenasai-network @@ -87,10 +87,6 @@ services: # ==================== 数据卷 ==================== volumes: - minenasai-data: - driver: local - minenasai-logs: - driver: local redis-data: driver: local diff --git a/src/minenasai/gateway/server.py b/src/minenasai/gateway/server.py index 91ffa32..927b781 100644 --- a/src/minenasai/gateway/server.py +++ b/src/minenasai/gateway/server.py @@ -88,7 +88,7 @@ async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]: setup_logging(settings.logging) # 设置监控 - setup_monitoring(app) + # setup_monitoring(app) moved to module level to avoid "Cannot add middleware after application has started" # 注册健康检查 health_checker = get_health_checker() @@ -124,6 +124,9 @@ app.add_middleware( allow_headers=["*"], ) +# 设置监控 (必须在应用启动前添加中间件) +setup_monitoring(app) + @app.get("/") async def root() -> dict[str, str]: