Files
qiming/qiming-rcoder/CLAUDE.md
2026-06-01 13:54:52 +08:00

11 KiB
Raw Permalink Blame History

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

项目概述

RCoder 是一个基于 ACP (Agent Client Protocol) 的 AI 驱动开发平台,使用 Rust 构建。该项目采用微服务架构,集成了 Docker 容器化部署、高性能反向代理和多种 AI 代理支持。

核心架构

工作空间结构

  • Workspace: 使用 Cargo workspace 管理多个 crate
  • 主要 crate: rcoder (主应用), agent_runner (代理运行时), shared_types (共享类型), docker_manager (容器管理), pingora-proxy (反向代理)

容器化架构设计

项目采用动态容器化架构,每个项目对应一个独立的 Docker 容器:

  • RCoder 主服务: HTTP API 服务 + 容器管理 + gRPC 客户端
  • Agent Runner 容器: 每个项目独立的 AI 代理运行环境 + gRPC 服务器
  • Pingora 代理: 高性能反向代理服务,支持端口路由

通信架构gRPC

RCoder 和 Agent Runner 之间使用 gRPC 进行内部通信,提供类型安全和高性能:

外部客户端 (HTTP/SSE)
    ↓
RCoder (HTTP API Server)
    ↓ gRPC (Chat, CancelSession, SubscribeProgress)
Agent Runner (gRPC Server in Docker)
    ↓ Server Streaming (实时进度事件)
RCoder (转换为 SSE)
    ↓
外部客户端 (SSE)

核心 RPC 方法

  • Chat: 发送聊天请求到 agent_runner
  • SubscribeProgress: Server Streaming实时推送进度事件
  • CancelSession: 取消正在执行的会话
  • GetStatus: 查询 Agent 状态

Proto 定义位置: crates/shared_types/proto/agent.proto

核心组件

  • DockerManager: 全局容器管理器,负责容器生命周期
  • ContainerManager: 项目级别的容器创建和管理
  • ProxyAgentManager: ACP 代理管理器,处理代理生命周期
  • AppState: 应用状态管理,使用 DashMap 进行并发访问
  • GrpcChannelPool: gRPC 连接池,基于 DashMap 实现高效连接复用
  • AgentServiceImpl: agent_runner 的 gRPC 服务实现

开发命令

基础构建和运行

# 构建所有 crates
cargo build --release

# 运行主服务 (默认端口 8087)
cargo run --bin rcoder

# 运行特定端口
cargo run --bin rcoder -- --port 8080 --enable-proxy

# 使用 Makefile (推荐)
make build          # 本地编译
make install        # 安装到 ~/.cargo/bin
make dev-build      # Docker 镜像构建
make dev-up         # 启动开发容器

开发环境命令

# 启动开发模式容器
make dev-build      # 首次:构建 Docker 镜像
make dev-up         # 启动容器
make dev-restart    # 代码修改后重启容器

# 查看容器日志
make dev-logs

# 停止开发容器
make dev-down

测试和质量检查

# 运行所有测试
cargo test

# 运行特定 crate 测试
cargo test -p rcoder
cargo test -p docker_manager

# 代码质量
cargo fmt           # 格式化代码
cargo clippy         # 代码检查
cargo tree           # 查看依赖树

Docker 开发命令

# 构建 Docker 镜像
make docker-build

# 完整开发流程 (推荐)
make dev-build && make dev-up

# 更新镜像标签
make update-image-tag

重要技术细节

gRPC 通信架构

  • 使用 Tonic 0.14.2 实现 gRPC 服务端和客户端
  • Proto 文件使用 Protobuf oneof 实现类型安全的事件系统,完全消除 JSON 序列化
  • GrpcChannelPool 基于 DashMap 提供高效的连接复用
  • Server Streaming 用于实时推送进度事件(替代轮询)
  • HTTP 回退机制gRPC 失败时自动回退到 HTTP兼容性保障
  • gRPC 默认端口:50051(定义在 shared_types::GRPC_DEFAULT_PORT

关键文件

  • crates/shared_types/proto/agent.proto - Proto 定义
  • crates/rcoder/src/grpc/channel_pool.rs - 连接池
  • crates/rcoder/src/grpc/chat_client.rs - gRPC 客户端
  • crates/agent_runner/src/grpc/agent_service_impl.rs - gRPC 服务实现

ACP 协议集成

  • 使用 agent-client-protocol = "0.6"agent_client_protocol = "0.4" 实现多版本兼容
  • AgentSideConnection 和 ClientSideConnection 未实现 Send trait
  • 必须在 LocalSet 和 spawn_local 中使用这些连接
  • 参考示例目录: /Volumes/soddy/git_workspace/rcoder/tmp/agent-client-protocol/rust/examples

并发模型和状态管理

  • 使用 DashMap 替代 Arc<RwLock<HashMap>> 以获得更好的性能
  • 使用写时复制 (CoW) 模式进行状态更新
  • 主应用使用 #[tokio::main(flavor = "current_thread")]
  • ACP 操作必须在 LocalSet 中执行以支持 spawn_local

Docker 容器动态创建

  • 多级隔离架构: 支持三种隔离级别
    • project (默认): 每个项目对应一个独立的 Docker 容器
    • tenant: 租户级隔离,同一租户共享容器
    • space: 空间级隔离,同一空间共享容器
  • 容器复用: 通过 pod_id 字段实现跨用户容器复用
  • 自动架构检测: 根据 OS 和 ARCH 自动选择合适的镜像
  • 内部网络通信: 容器间通过 Docker 内部网络直接通信,无需端口映射
  • 路径自动解析: 自动检测容器内路径到宿主机路径的映射

容器工作空间路径

隔离类型 RCoder 路径 Computer 路径
project /app/project_workspace/{project_id} /app/computer-project-workspace/{user_id}/{project_id}
tenant/space /app/project_workspace/{tenant_id}/{space_id}/{project_id} /app/computer-project-workspace/{tenant_id}/{space_id}/{project_id}

配置系统

多层级配置优先级 (从高到低):

  1. 命令行参数 - --port, --projects-dir, --enable-proxy
  2. 环境变量 - RCODER_PORT, DOCKER_SOCKET_PATH, RCODER_DOCKER_IMAGE_*
  3. 配置文件 - config.yml (自动生成)
  4. 默认配置 - 代码中的默认值

环境配置

核心环境变量

# 服务配置
RCODER_PORT=8087                           # 服务端口
RUST_LOG=debug                            # 日志级别

# Docker 配置
DOCKER_SOCKET_PATH=/var/run/docker.sock     # Docker socket 路径
RCODER_DOCKER_IMAGE=custom/image          # 自定义镜像
RCODER_DOCKER_IMAGE_ARM64=arm64/image     # ARM64 专用镜像
RCODER_DOCKER_IMAGE_AMD64=amd64/image     # AMD64 专用镜像

# 代理配置
ANTHROPIC_API_KEY=sk-xxx                 # Claude API 密钥
COMPOSE_PROJECT_NAME=rcoder                 # Docker Compose 项目名

开发环境要求

  • Rust 1.75+ (2024 Edition)
  • Docker 和 Docker Compose
  • Claude Code CLI (可选)

API 接口

核心端点

  • POST /chat: 发送聊天消息到 AI 代理 (支持 pod_id, tenant_id, space_id, isolation_type 多租户参数)
  • POST /computer/chat: Computer Agent 聊天接口 (支持多租户参数)
  • GET /agent/progress/{session_id}: SSE 进度流,接收实时通知
  • POST /agent/session/cancel: 取消正在执行的任务
  • POST /agent/stop: 停止 Agent
  • GET /agent/status/{project_id}: 查询 Agent 状态
  • POST /pod/ensure: 确保容器存在,支持多租户参数
  • POST /pod/restart: 重启容器,支持多租户参数
  • GET /health: 健康检查

Pingora 反向代理

  • GET /proxy/{port}/{path}: 端口路由到指定后端服务
  • GET /proxy/status: 查看代理服务状态
  • GET /proxy/stats: 查看代理统计信息

响应格式

所有 API 响应都使用统一的 HttpResult 格式:

struct HttpResult<T> {
    success: bool,
    data: Option<T>,
    code: String,        // 业务错误码
    message: String,     // 错误描述
    tid: Option<String>, // 追踪ID
}

特殊注意事项

禁止事项

  1. 禁止使用模拟响应逻辑 - 所有 AI 调用必须真实执行
  2. 禁止编写 unsafe 代码 - 项目要求内存安全
  3. AgentSideConnection 必须在 LocalSet 中使用 - 由于未实现 Send trait
  4. ** Always Response in 中文** - 所有响应必须使用中文

Docker 容器管理

  • 容器名称格式: rcoder-agent-{project_id}rcoder-agent-{pod_id} (当 pod_id 提供时)
  • 镜像选择策略: 通用镜像 > 架构特定镜像 > 默认回退镜像
  • 网络模式: 优先使用内部网络,支持 host 网络模式
  • 安全配置: 自动移除 NET_RAW 和 NET_ADMIN 权限

性能优化

  • 使用 DashMap 进行并发访问,避免 RwLock 竞争
  • 实现写时复制 (CoW) 模式,减少不必要的内存分配
  • 使用 MPMC 架构处理多个 AI 请求
  • 通过内部网络进行容器间通信,避免宿主机端口映射

错误处理

  • 使用 anyhow 进行错误传播
  • 使用 HttpResult 统一 API 响应格式
  • 实现完整的错误追踪和日志记录

调试和开发

日志配置

# 启用详细日志
RUST_LOG=debug cargo run --bin rcoder

# 特定模块日志
RUST_LOG=rcoder=debug,tower_http=debug cargo run

# 在容器中启用调试
RUST_LOG=debug make dev-up

容器调试

# 查看容器状态
docker ps | grep rcoder

# 查看容器日志
make dev-logs

# 进入容器调试
docker exec -it <container_id> /bin/bash

网络调试

# 检查容器网络
docker network ls
docker network inspect rcoder_agent-network

# 测试容器间连通性
docker exec <container1> ping <container2_ip>

开发工作流程

  1. 首次开发环境设置:

    make dev-build      # 构建 Docker 镜像
    make dev-up         # 启动开发容器
    
  2. 日常开发:

    # 修改代码后
    make dev-restart    # 重新编译并重启容器
    
  3. 测试新功能:

    # 直接运行
    cargo run --bin rcoder -- --port 8080
    
    # 或使用容器
    make dev-up
    curl -X POST http://localhost:8087/chat -d '{"prompt":"hello"}'
    
  4. 调试问题:

    # 查看详细日志
    make dev-logs
    RUST_LOG=debug make dev-restart
    

关键代码模式

ACP 协议集成模式

// 正确的 LocalSet 使用模式
let local_set = LocalSet::new();
local_set.run_until(async move {
    let (client_conn, handle_io) = ClientSideConnection::new(
        client, outgoing, incoming, |fut| {
            tokio::task::spawn_local(fut);
        }
    );
    tokio::task::spawn_local(handle_io);
    // ... 处理逻辑
}).await;

DashMap 高效使用模式

// 使用 entry API 避免多次锁获取
let entry = state.project_and_agent_map.entry(project_id.clone());
match entry {
    dashmap::mapref::entry::Entry::Occupied(mut occupied) => {
        // 只在需要更新时进行写时复制
        if needs_update {
            let mut mutable_info = (**occupied.get()).clone();
            mutable_info.update_field(value);
            occupied.insert(Arc::new(mutable_info));
        }
    }
    dashmap::mapref::entry::Entry::Vacant(vacant) => {
        // 创建新条目
        let new_info = ProjectAndContainerInfo::new(project_id);
        vacant.insert(Arc::new(new_info));
    }
}

Docker 容器创建模式

// 容器配置模式
let container_config = DockerContainerConfig {
    project_id: project_id.clone(),
    image: get_docker_image_from_config(image, arm64_image, amd64_image, default_image),
    host_path: resolve_container_path_to_host(&project_path).await?,
    container_path: project_path.clone(),
    port_bindings: HashMap::new(), // 内部网络,无需端口映射
    network_name: Some(network_name),
    // ... 其他配置
};