Luxx/assets/ARCHITECTURE.md

1092 lines
30 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Luxx 项目架构
## 技术栈
- **框架**: FastAPI 0.109+
- **数据库**: SQLAlchemy 2.0+ (同步模式)
- **认证**: JWT (PyJWT)
- **HTTP客户端**: httpx, requests
- **配置**: YAML (PyYAML)
- **代码执行**: Python 原生执行
- **网页爬虫**:
- `httpx` - HTTP 客户端
- `beautifulsoup4` - HTML 解析
- `lxml` - XML/HTML 解析器
## 目录结构
```
luxx/
├── __init__.py # FastAPI 应用工厂
├── config.py # 配置管理YAML
├── database.py # 数据库连接
├── models.py # ORM 模型
├── routes/ # API 路由层
│ ├── __init__.py # 路由聚合
│ ├── auth.py # 认证 (登录/注册)
│ ├── agents.py # Agent 模板管理 (CRUD)
│ ├── chat_rooms.py # 聊天室管理 (多 Agent 协作)
│ ├── conversations.py # 会话管理 (CRUD)
│ ├── messages.py # 消息处理 (流式/同步)
│ ├── providers.py # LLM 提供商管理
│ ├── agents.py # Agent 模板管理 (CRUD)
│ └── tools.py # 工具管理
├── services/ # 服务层
│ ├── __init__.py # 服务导出
│ ├── chat.py # 聊天服务门面
│ ├── chat_room.py # 多 Agent 聊天室编排器
│ ├── agentic_loop.py # Agentic Loop 执行器
│ ├── stream_context.py # 流式状态管理
│ ├── events.py # SSE 事件工具
│ ├── llm_response.py # LLM 响应数据类
│ ├── task.py # 任务系统 (Task/TaskGraph/TaskService)
│ ├── llm_client.py # LLM 客户端
│ └── llm_adapters/ # LLM API 适配器
│ ├── __init__.py # 适配器导出
│ ├── base.py # ProviderAdapter 基类
│ ├── openai_adapter.py # OpenAI/DeepSeek/GLM 适配器
│ └── anthropic_adapter.py # Anthropic Claude 适配器
├── tools/ # 工具系统
│ ├── __init__.py # 工具注册入口
│ ├── core.py # 核心类 (ToolRegistry, ToolDefinition, ToolResult, ToolContext)
│ ├── factory.py # @tool 装饰器
│ ├── executor.py # 工具执行器 (缓存/并行)
│ ├── services.py # 工具服务层
│ └── builtin/ # 内置工具
│ ├── __init__.py # 工具注册入口
│ ├── code.py # 代码执行 (python_execute, python_eval)
│ ├── crawler.py # 网页爬虫 (web_search, web_fetch, batch_fetch)
│ ├── data.py # 数据处理 (process_data)
│ ├── file.py # 文件操作 (file_read, file_write, file_list, file_exists, file_grep)
│ └── shell.py # Shell 命令 (shell_execute)
└── utils/ # 工具函数
├── __init__.py
└── helpers.py # 密码哈希、ID生成、响应封装
run.py # 应用入口文件
config.yaml # 配置文件
```
## 核心组件
### 1. 应用工厂 (`__init__.py`)
FastAPI 应用入口,使用 lifespan 管理生命周期:
- 启动:初始化数据库、注册内置工具、创建默认管理员用户
- 关闭:清理资源
```python
# 默认管理员账号
username: admin
password: admin123
```
### 2. 配置管理 (`config.py`)
使用 YAML 文件管理配置:
- 配置文件:`config.yaml`
- 环境变量替换:`${VAR_NAME}`
- 单例模式全局访问
- 默认值支持
```yaml
# config.yaml 示例
app:
secret_key: ${APP_SECRET_KEY}
debug: true
host: 0.0.0.0
port: 8000
database:
type: sqlite
url: sqlite:///./chat.db
workspace:
root: ./workspaces # 用户工作空间根目录
auto_create: true # 自动创建用户目录
llm:
provider: deepseek
api_key: ${DEEPSEEK_API_KEY}
api_url: https://api.deepseek.com/v1
tools:
enable_cache: true
cache_ttl: 300
max_workers: 4
max_iterations: 10
logging:
level: INFO
```
**工作空间隔离机制:**
- 每个用户的工作空间路径基于 `user_id` 的 SHA256 哈希值
- 格式:`{workspace_root}/{hash_of_user_id}`
- 所有文件操作必须在用户工作空间内,防止路径穿越攻击
```
### 3. 数据库 (`database.py`)
- SQLAlchemy 同步支持
- SQLite 默认数据库
- 依赖注入获取会话
### 4. ORM 模型 (`models.py`)
```mermaid
erDiagram
USER {
int id PK
string username UK
string email UK
string password_hash
string role
int permission_level "1=READ_ONLY, 2=WRITE, 3=EXECUTE, 4=ADMIN"
string workspace_path "用户工作空间路径"
boolean is_active
datetime created_at
}
USER_SETTINGS {
int id PK
int user_id FK UK
int default_provider_id FK "optional"
float temperature
int max_tokens
boolean thinking_enabled
text system_prompt
datetime created_at
datetime updated_at
}
PROJECT {
string id PK
int user_id FK
string name
text description
datetime created_at
datetime updated_at
}
CONVERSATION {
string id PK
int user_id FK
int provider_id FK "optional"
string project_id FK "optional"
string title
string model
text system_prompt
float temperature
int max_tokens
boolean thinking_enabled
datetime created_at
datetime updated_at
}
MESSAGE {
string id PK
string conversation_id FK "optional"
string room_id FK "optional"
string role
longtext content "JSON 格式"
int token_count
text usage "JSON 格式"
string sender_name "聊天室: 发送者名称"
string sender_color "聊天室: 发送者颜色"
int round_number "聊天室: 轮次编号"
datetime created_at
}
LLM_PROVIDER {
int id PK
int user_id FK
string name
string provider_type
string base_url
string api_key
string default_model
int max_tokens
boolean is_default
boolean enabled
datetime created_at
datetime updated_at
}
AGENT {
int id PK
int user_id FK
string name
string role
int provider_id FK "optional"
string model
text system_prompt
string color
datetime created_at
datetime updated_at
}
CHAT_ROOM {
string id PK
int user_id FK
string title
text task
string status "idle/running/paused/completed/error"
int max_rounds
int current_round
datetime created_at
datetime updated_at
}
ROOM_AGENT {
int id PK
string room_id FK
int agent_id FK "optional"
string name
string role
int provider_id FK "optional"
string model
text system_prompt
string color
int turn_order
}
USER ||--|| USER_SETTINGS : "has"
USER ||--o{ PROJECT : "has"
USER ||--o{ CONVERSATION : "has"
USER ||--o{ LLM_PROVIDER : "configures"
USER ||--o{ AGENT : "creates"
USER ||--o{ CHAT_ROOM : "creates"
PROJECT ||--o{ CONVERSATION : "contains"
LLM_PROVIDER ||--o{ CONVERSATION : "uses"
LLM_PROVIDER ||--o{ AGENT : "used_by"
LLM_PROVIDER ||--o{ ROOM_AGENT : "used_by"
CONVERSATION ||--o{ MESSAGE : "has"
CHAT_ROOM ||--o{ MESSAGE : "has"
CHAT_ROOM ||--o{ ROOM_AGENT : "contains"
AGENT ||--o{ ROOM_AGENT : "linked_to"
```
**用户权限级别 (permission_level)**
| 级别 | 名称 | 说明 |
|------|------|------|
| 1 | READ_ONLY | 只读权限 |
| 2 | WRITE | 写入权限(文件写入) |
| 3 | EXECUTE | 执行权限代码执行、Shell命令 |
| 4 | ADMIN | 管理员权限 |
### Message Content JSON 结构
`content` 字段统一使用 JSON 格式存储:
**User 消息:**
```json
{
"text": "用户输入的文本内容",
"attachments": [
{"name": "utils.py", "extension": "py", "content": "..."}
]
}
```
**Assistant 消息:**
```json
{
"steps": [
{"id": "step-0", "index": 0, "type": "thinking", "content": "..."},
{"id": "step-1", "index": 1, "type": "text", "content": "..."},
{"id": "step-2", "index": 2, "type": "tool_call", "id_ref": "call_xxx", "name": "...", "arguments": "..."},
{"id": "step-3", "index": 3, "type": "tool_result", "id_ref": "call_xxx", "name": "...", "content": "...", "success": true}
]
}
```
`steps` 字段是**唯一数据源**,按 `index` 顺序排列。thinking、text、tool_call、tool_result 可以在多轮迭代中穿插出现。
**注意**`text` 和 `content` 字段通过解析 `steps` 中所有 `type: "text"` 的内容动态计算得出。
### 5. 工具系统
```mermaid
classDiagram
class ToolDefinition {
+str name
+str description
+dict parameters
+Callable handler
+str category
+CommandPermission required_permission
+to_openai_format() dict
}
class ToolContext {
+int user_id
+str username
+str workspace
+int user_permission_level
}
class CommandPermission {
<<enumeration>>
READ_ONLY = 1
WRITE = 2
EXECUTE = 3
ADMIN = 4
}
class ToolResult {
+bool success
+Any data
+str error
+to_dict() dict
+ok(data) ToolResult$
+fail(error) ToolResult$
}
class ToolRegistry {
+_tools: Dict
+register(tool) void
+get(name) ToolDefinition?
+list_all() List~dict~
+list_by_category(category) List~dict~
+execute(name, arguments, context) dict
+remove(name) bool
}
class ToolExecutor {
+enable_cache: bool
+cache_ttl: int
+max_workers: int
+_cache: Dict
+_call_history: List
+process_tool_calls(tool_calls, context) list
+process_tool_calls_parallel(tool_calls, context) list
+clear_cache() void
+get_history(limit) List
}
```
#### 内置工具
**代码执行 (code.py)**
| 工具 | 功能 | 权限 |
|------|------|------|
| `python_execute` | 执行 Python 代码 | EXECUTE |
| `python_eval` | 计算表达式 | EXECUTE |
**文件操作 (file.py)**
| 工具 | 功能 | 权限 |
|------|------|------|
| `file_read` | 读取文件内容 | READ_ONLY |
| `file_write` | 写入文件内容 | WRITE |
| `file_list` | 列出目录内容 | READ_ONLY |
| `file_exists` | 检查文件是否存在 | READ_ONLY |
| `file_grep` | 正则搜索文件内容 | READ_ONLY |
**Shell 命令 (shell.py)**
| 工具 | 功能 | 权限 |
|------|------|------|
| `shell_execute` | 执行 Shell 命令 | EXECUTE |
**网页爬虫 (crawler.py)**
| 工具 | 功能 | 权限 |
|------|------|------|
| `web_search` | DuckDuckGo HTML 搜索 | READ_ONLY |
| `web_fetch` | 网页抓取 | READ_ONLY |
| `batch_fetch` | 批量并发抓取 | READ_ONLY |
**数据处理 (data.py)**
| 工具 | 功能 | 权限 |
|------|------|------|
| `process_data` | JSON 转换、格式化 | READ_ONLY |
#### 权限检查机制
工具执行时自动检查用户权限:
```
工具要求的权限 <= 用户拥有的权限 → 允许执行
工具要求的权限 > 用户拥有的权限 → 拒绝执行
```
#### 工具开发规范
所有工具必须遵循统一的开发规范,确保错误处理和返回格式一致。
**核心原则:装饰器自动处理一切,工具函数只写业务逻辑**
```python
from luxx.tools.factory import tool
@tool(
name="my_tool",
description="工具描述",
parameters={...},
required_params=["arg1"], # 自动验证
category="my_category"
)
def my_tool(arguments: dict):
# 业务逻辑 - 只管返回数据
data = fetch_data(arguments["arg1"])
return {"items": data, "count": len(data)}
# 或者直接抛出异常(装饰器自动捕获并转换)
if invalid:
raise ValueError("Invalid input")
```
**装饰器自动处理:**
1. 必需参数验证(`required_params`
2. 所有异常捕获和转换
3. 结果格式统一包装
**返回格式转换**
| 工具函数返回/抛出 | 装饰器转换为 |
|-------------------|-------------|
| `return {"result": "ok"}` | `{"success": true, "data": {...}, "error": null}` |
| `raise ValueError("msg")` | `{"success": false, "data": null, "error": "ValueError: msg"}` |
| `raise Exception()` | `{"success": false, "data": null, "error": "..."}` |
**工具调用流程**
```
LLM 请求
ToolRegistry.execute(name, args)
@tool 装饰器
├─ 验证 required_params
├─ 执行工具函数 (try-except 包裹)
├─ 捕获异常 → 转换为 error
├─ 包装返回格式
└─ 返回 ToolResult
ToolExecutor 返回结果
前端 ProcessBlock 显示
```
### 6. 服务层
#### LLM 适配器 (`services/llm_adapters/`)
适配器模式统一处理不同 LLM API 格式:
```mermaid
classDiagram
class ProviderAdapter {
<<abstract>>
+str provider_type
+build_request() tuple
+parse_stream_chunk() AsyncGenerator
+parse_response() Dict
+supports_thinking() bool
+supports_tools() bool
}
class OpenAIAdapter {
+str provider_type = "openai"
+build_request() tuple
+parse_stream_chunk() AsyncGenerator
+parse_response() Dict
+supports_tools() bool
}
class AnthropicAdapter {
+str provider_type = "anthropic"
+build_request() tuple
+parse_stream_chunk() AsyncGenerator
+parse_response() Dict
+supports_thinking() bool
+supports_tools() bool
}
ProviderAdapter <|-- OpenAIAdapter
ProviderAdapter <|-- AnthropicAdapter
```
**支持的功能对比:**
| 适配器 | 工具调用 | Thinking/Reasoning | 流式响应 |
|--------|----------|-------------------|----------|
| OpenAI | ✅ | ✅ (DeepSeek) | ✅ |
| Anthropic | ✅ | ✅ | ✅ |
#### LLM 响应数据类 (`services/llm_response.py`)
```python
class StepType:
"""步骤类型常量"""
THINKING = "thinking"
TEXT = "text"
TOOL_CALL = "tool_call"
TOOL_RESULT = "tool_result"
@dataclass
class Step:
"""单个步骤 - 用于存储和传输"""
id: str
index: int
type: str # thinking, text, tool_call, tool_result
content: str = ""
name: str = "" # tool_call/tool_result
arguments: str = "" # tool_call
id_ref: str = "" # tool_result
success: bool = True
@dataclass
class ParsedDelta:
"""LLM 流式响应增量"""
thinking: str = "" # 思考内容(增量)
text: str = "" # 文本内容(增量)
tool_call: Optional[Dict] = None # 单个工具调用
usage: Dict[str, int] = {} # Token 用量
is_complete: bool = False
```
#### ChatService (`services/chat.py`)
核心聊天服务:
- Agentic Loop 迭代执行(最多 10 轮)
- 流式 SSE 响应
- 工具调用编排(并行执行)
- 消息历史管理
- Token 用量追踪
- 工作空间上下文传递
#### AgenticLoop (`services/agentic_loop.py`)
执行 Agentic Loop 的核心循环:
- 调用 LLM 获取响应(流式)
- 解析 ParsedDelta更新步骤状态
- 管理 thinking/text/tool_call/tool_result 步骤
- 工具并行执行
- 最大迭代次数10
```python
# 执行流程
async for delta in llm.stream_call(...):
events = self._process_delta(delta, context, total_usage)
yield from events
# 工具调用时
tool_results = self.tool_executor.process_tool_calls_parallel(...)
messages.append({"role": "assistant", ...})
messages.extend(tool_results)
```
#### StreamContext (`services/stream_context.py`)
流式状态管理:
- 追踪当前步骤类型和索引
- 累积 thinking 和 text 内容
- 管理 tool_calls 列表和 tool_results
- 生成 SSE 事件
- 构建完整消息内容
#### LLMClient (`services/llm_client.py`)
LLM API 客户端:
- 多提供商OpenAI、DeepSeek、Anthropic
- 自动适配器选择
- 流式/同步调用
- 错误处理和重试
- Token 计数
### 7. 任务系统 (`services/task.py`)
用于自主任务执行和计划管理:
```mermaid
classDiagram
class Task {
+str id
+str name
+str goal
+TaskStatus status
+List~Step~ steps
+str metadata
+get_step() Step?
+is_complete() bool
}
class Step {
+str id
+str name
+str goal
+List~str~ depends_on
+StepStatus status
+Dict tool_calls
}
class TaskGraph {
+topological_sort() List~Step~
+get_ready_steps() List~Step~
+get_parallel_levels() List~List~Step~~
+detect_cycles() List~List~str~~
+validate() tuple
}
class TaskService {
+create_task() Task
+get_task() Task
+update_task_status() Task
+add_steps() List~Step~
+set_steps_from_plan() List~Step~
+build_graph() TaskGraph
}
class Planner {
+plan() List~Dict~
+plan_sync() List~Dict~
}
Task "1" o-- "*" Step
TaskService ..> TaskGraph
Planner ..> TaskService
```
**任务状态 (TaskStatus) - 五状态模型:**
- `PENDING` - 待处理/就绪
- `RUNNING` - 运行中
- `BLOCK` - 阻塞
- `TERMINATED` - 终止
- `COMPLETED` - 完成
**步骤状态 (StepStatus)**
- `PENDING` - 待执行
- `RUNNING` - 执行中
- `COMPLETED` - 已完成
- `FAILED` - 失败
- `SKIPPED` - 跳过
**TaskGraph 功能:**
- `topological_sort()` - 拓扑排序获取执行顺序
- `get_ready_steps()` - 获取就绪步骤(依赖已满足)
- `get_parallel_levels()` - 获取并行执行层级
- `detect_cycles()` - 检测循环依赖
- `validate()` - 验证图结构
**Planner 功能:**
- 调用 LLM 自动分解目标为步骤
- 支持上下文(可用工具、约束条件)
- 返回结构化步骤列表
### 8. 任务执行服务 (`services/task_executor.py`)
将 Task/Plan 集成到 Agent 执行流程:
```mermaid
classDiagram
class TaskExecutorService {
+llm: LLMClient
+generate_plan() List~Dict~
+create_task_with_plan() Task
+get_execution_plan() Dict
}
class AgentWithPlan {
+chat_service
+execute_with_plan() AsyncGenerator
}
TaskExecutorService --> TaskService
AgentWithPlan --> TaskExecutorService
AgentWithPlan --> ChatService
```
**执行流程:**
1. 用户输入目标 → AgentWithPlan 接收
2. TaskExecutorService.generate_plan() 调用 LLM 分解目标
3. 创建 Task 并设置步骤
4. 按 TaskGraph 拓扑顺序执行每个步骤
5. 每个步骤作为独立 Agent 对话执行
6. 步骤完成后更新状态,继续下一个
**SSE 事件:**
- `planning` - 计划生成中
- `plan_created` - 计划已创建
- `step_start` - 步骤开始
- `step_complete` - 步骤完成
- `task_complete` - 任务完成
### 7. 认证系统 (`routes/auth.py`)
- JWT Bearer Token
- Bcrypt 密码哈希
- 用户注册/登录
### 8. Agent 系统 (`routes/agents.py`, `models.py`)
Agent 是独立的可复用 AI 助手模板,可以在聊天室中使用:
```mermaid
classDiagram
class Agent {
+int id
+int user_id
+str name
+str role
+int provider_id
+str model
+str system_prompt
+str color
+to_dict() dict
}
class LLMProvider {
+int id
+str name
+str api_key
+str default_model
}
Agent --> LLMProvider : uses
```
**Agent 字段说明:**
| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | int | Agent 唯一标识 |
| `user_id` | int | 所属用户 ID |
| `name` | string | Agent 显示名称 |
| `role` | string | Agent 角色描述(如"后端开发" |
| `provider_id` | int | 使用的 LLM 提供商 |
| `model` | string | 模型名称 |
| `system_prompt` | string | 系统提示词 |
| `color` | string | 显示颜色Hex |
### 9. 聊天室系统 (`routes/chat_rooms.py`, `services/chat_room.py`)
聊天室支持多个 Agent 同时参与讨论,协作完成复杂任务:
```mermaid
classDiagram
class ChatRoom {
+str id
+int user_id
+str title
+str task
+str status
+int max_rounds
+int current_round
+List~RoomAgent~ agents
}
class RoomAgent {
+int id
+str room_id
+int agent_id
+str name
+str role
+str model
+str system_prompt
+str color
+int turn_order
}
class ChatRoomOrchestrator {
-Dict~str, Task~ _running_rooms
+is_running(room_id) bool
+cancel(room_id) void
+run_room(room_id) AsyncGenerator
}
ChatRoom "1" o-- "*" RoomAgent : contains
ChatRoomOrchestrator ..> ChatRoom : orchestrates
ChatRoomOrchestrator ..> RoomAgent : executes
```
**聊天室状态:**
| 状态 | 说明 |
|------|------|
| `idle` | 空闲,未开始 |
| `running` | 运行中 |
| `paused` | 已暂停(被手动停止) |
| `completed` | 已完成(达到最大轮次) |
| `error` | 错误(执行出错) |
**聊天室执行流程:**
```
1. 用户调用 /chat-rooms/{id}/start
2. ChatRoomOrchestrator.run_room() 被调用
3. 按 turn_order 顺序执行每个 Agent 的发言轮次
4. 每个 Agent 根据历史消息和系统提示生成回复
5. SSE 流式推送消息块 (message_chunk)
6. 消息结束时推送 message_end
7. 一轮结束后推送 round_end
8. 达到 max_rounds 或被停止时结束
```
**SSE 事件流:**
```
room_started → round_start → (message_start → message_chunk* → message_end → message) × N_agents
→ round_end → (重复下一轮) → room_completed
```
### 10. API 路由
| 路由 | 方法 | 说明 |
|------|------|------|
| `/auth/register` | POST | 用户注册 |
| `/auth/login` | POST | 用户登录 |
| `/auth/logout` | POST | 用户登出 |
| `/auth/me` | GET | 当前用户信息 |
| `/auth/users` | GET | 用户列表(管理员) |
| `/auth/users/{user_id}` | PUT | 更新用户权限 |
| `/conversations` | GET | 会话列表(分页) |
| `/conversations` | POST | 创建会话 |
| `/conversations/{id}` | GET | 会话详情 |
| `/conversations/{id}` | PUT | 更新会话 |
| `/conversations/{id}` | DELETE | 删除会话 |
| `/messages` | GET | 消息列表 |
| `/messages` | POST | 发送消息(同步) |
| `/messages/stream` | POST | 发送消息(流式 SSE |
| `/messages/{id}` | DELETE | 删除消息 |
| `/providers` | GET | LLM 提供商列表 |
| `/providers` | POST | 创建提供商 |
| `/providers/{id}` | GET | 提供商详情 |
| `/providers/{id}` | PUT | 更新提供商 |
| `/providers/{id}` | DELETE | 删除提供商 |
| `/providers/{id}/test` | POST | 测试提供商连接 |
| `/agents` | GET | Agent 列表 |
| `/agents` | POST | 创建 Agent |
| `/agents/{id}` | GET | Agent 详情 |
| `/agents/{id}` | PUT | 更新 Agent |
| `/agents/{id}` | DELETE | 删除 Agent |
| `/chat-rooms` | GET | 聊天室列表 |
| `/chat-rooms` | POST | 创建聊天室 |
| `/chat-rooms/{id}` | GET | 聊天室详情 |
| `/chat-rooms/{id}` | PUT | 更新聊天室 |
| `/chat-rooms/{id}` | DELETE | 删除聊天室 |
| `/chat-rooms/{id}/start` | POST | 启动聊天室 |
| `/chat-rooms/{id}/stop` | POST | 停止聊天室 |
| `/chat-rooms/{id}/reset` | POST | 重置聊天室 |
| `/chat-rooms/{id}/messages` | GET | 聊天室消息 |
| `/chat-rooms/{id}/agents` | POST | 添加 Agent |
| `/chat-rooms/{id}/agents/{agent_id}` | PUT | 更新 Agent |
| `/chat-rooms/{id}/agents/{agent_id}` | DELETE | 移除 Agent |
| `/tools` | GET | 可用工具列表 |
| `/tools/{name}` | GET | 工具详情 |
| `/tools/{name}/execute` | POST | 执行工具 |
| `/tasks` | GET | 任务列表 |
| `/tasks` | POST | 创建任务 |
| `/tasks/{id}` | GET | 任务详情 |
| `/tasks/{id}` | PUT | 更新任务 |
| `/tasks/{id}` | DELETE | 删除任务 |
| `/tasks/{id}/steps` | POST | 添加步骤 |
| `/tasks/{id}/steps/{step_id}` | PUT | 更新步骤 |
| `/tasks/{id}/graph` | GET | 获取任务图 |
| `/tasks/{id}/ready-steps` | GET | 获取就绪步骤 |
| `/tasks/{id}/execute` | POST | 执行任务 |
| `/tasks/{id}/export` | GET | 导出任务 |
| `/tasks/import` | POST | 导入任务 |
| `/health` | GET | 健康检查 |
| `/` | GET | 服务信息 |
## 数据流
### 消息处理流程
```mermaid
sequenceDiagram
participant Client
participant API as POST /messages/stream
participant CS as ChatService
participant AL as AgenticLoop
participant Parser as LLMResponseParser
participant LLM as LLM API
participant TE as ToolExecutor
Client->>API: POST {content, tools, thinking_enabled}
API->>CS: stream_response()
CS->>AL: execute()
loop MAX_ITERATIONS (10)
AL->>LLM: stream_call(messages, tools)
LLM-->>AL: SSE Stream
AL->>Parser: parse_chunk()
Parser-->>AL: ParsedDelta {thinking, text, tool_calls}
alt tool_calls
AL->>TE: process_tool_calls_parallel()
TE-->>AL: tool_results
AL->>AL: 追加到 messages
end
end
AL->>CS: done event
CS->>CS: _save_message()
CS->>API: SSE Stream
API-->>Client: 流式响应
```
## SSE 事件
### 普通会话 SSE 事件
| 事件 | 说明 |
|------|------|
| `process_step` | 结构化步骤thinking/text/tool_call/tool_result携带 `id`、`index` 确保渲染顺序 |
| `done` | 响应完成,携带 message_id、token_count、usage |
| `error` | 错误信息 |
### 聊天室 SSE 事件
| 事件 | 说明 |
|------|------|
| `room_started` | 聊天室启动,携带 room_id 和 task |
| `round_start` | 回合开始,携带 round 和 max_rounds |
| `message_start` | 消息开始,携带 msg_id、sender_name、sender_color、round_number |
| `message_chunk` | 消息内容增量,携带 content 和 accumulated |
| `message_end` | 消息结束,携带 msg_id、content、token_count |
| `message` | 完整消息(用于存储和显示) |
| `round_end` | 回合结束 |
| `room_completed` | 聊天室完成 |
| `room_paused` | 聊天室暂停 |
| `agent_error` | Agent 执行错误 |
| `error` | 通用错误 |
### process_step 事件格式
```json
{"type": "process_step", "step": {"id": "step-0", "index": 0, "type": "thinking", "content": "..."}}
{"type": "process_step", "step": {"id": "step-1", "index": 1, "type": "text", "content": "回复文本..."}}
{"type": "process_step", "step": {"id": "step-2", "index": 2, "type": "tool_call", "id_ref": "call_abc", "name": "web_search", "arguments": "{\"query\": \"...\"}"}}
{"type": "process_step", "step": {"id": "step-3", "index": 3, "type": "tool_result", "id_ref": "call_abc", "name": "web_search", "content": "{...}", "success": true}}
```
| 字段 | 说明 |
|------|------|
| `id` | 步骤唯一标识(格式 `step-{index}` |
| `index` | 步骤序号,确保按正确顺序显示 |
| `type` | 步骤类型:`thinking` / `text` / `tool_call` / `tool_result` |
| `id_ref` | 工具调用引用 ID仅 tool_call/tool_result |
| `name` | 工具名称(仅 tool_call/tool_result |
| `arguments` | 工具调用参数 JSON 字符串(仅 tool_call |
| `content` | 内容thinking 的思考内容、text 的文本、tool_result 的返回结果) |
| `success` | 工具执行是否成功(仅 tool_result |
### done 事件格式
```json
{"type": "done", "message_id": "uuid", "token_count": 1234, "usage": {"prompt_tokens": 100, "completion_tokens": 200, "total_tokens": 300}}
```
## 配置示例
### config.yaml
```yaml
app:
secret_key: ${APP_SECRET_KEY}
debug: true
host: 0.0.0.0
port: 8000
database:
type: sqlite
url: sqlite:///./chat.db
workspace:
root: ./workspaces # 用户工作空间根目录
auto_create: true # 自动创建用户工作空间
llm:
provider: deepseek
api_key: ${DEEPSEEK_API_KEY}
api_url: https://api.deepseek.com/v1
tools:
enable_cache: true
cache_ttl: 300
max_workers: 4
max_iterations: 10
logging:
level: INFO
```
## 环境变量
| 变量 | 说明 | 示例 |
|------|------|------|
| `APP_SECRET_KEY` | 应用密钥 | `your-secret-key` |
| `DEEPSEEK_API_KEY` | DeepSeek API | `sk-xxxx` |
| `DATABASE_URL` | 数据库连接 | `sqlite:///./chat.db` |
## LLM 适配器配置
### OpenAI 兼容 (DeepSeek/GLM 等)
```yaml
llm:
provider: openai
api_key: ${API_KEY}
api_url: https://api.deepseek.com/v1 # 或其他兼容端点
```
### Anthropic Claude
```yaml
llm:
provider: anthropic
api_key: ${ANTHROPIC_API_KEY}
api_url: https://api.anthropic.com/v1
```
## 项目结构说明
### 入口文件
- `run.py` - 启动 Uvicorn 服务器
### 响应格式
所有 API 统一使用响应封装:
```json
// 成功
{"success": true, "data": {...}, "message": "操作成功"}
// 错误
{"success": false, "error": "错误信息", "code": 404}
```
### 工具缓存机制
ToolExecutor 支持结果缓存:
- TTL: 5 分钟(可配置)
- 缓存 Key: `{tool_name}:{sorted_arguments_json}`
- 调用历史记录最近 1000 条
### 流式响应特点
1. 实时返回 thinking_content模型思考过程
2. 实时返回 text 增量更新
3. 工具调用并行执行,结果批量返回
4. 最终 `done` 事件包含完整 message_id 和 token 用量
### 工作空间隔离
每个用户的工作空间完全隔离:
- 用户目录基于 user_id 的 SHA256 哈希生成
- 所有文件操作强制在用户工作空间内
- 支持权限级别控制文件操作能力
### MessageBuilder
用于构建发送给 LLM 的消息列表:
- `add_system()` - 添加系统消息
- `add_user()` - 添加用户消息JSON 格式)
- `add_assistant()` - 添加助手消息
- `add_tool_result()` - 添加工具结果消息
- `extract_text()` - 从 JSON 内容中提取文本