- 替换基础镜像为 `php:8.4.15-cli-alpine3.23`,重构依赖安装流程 - 切换包管理工具为 `apk`,添加必要系统库及扩展 - 更新 Composer 脚本及依赖映射 - 优化命令与环境变量配置,增强一致性与兼容性
9.3 KiB
9.3 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. 自然语言使用中文。
项目概述
这是一个基于 Laravel 12 + Octane + Docker 的 Agent Runtime Server (ARS),用于提供可部署的 Agent 运行时服务。核心特性包括:
- 兼容多种 Agent 模型
- Web 终端实时交互,支持断线重连
- 后台任务持续执行,重连后可续传会话
技术栈
- PHP: 8.2+
- Laravel Framework: 12.x
- Laravel Octane: 2.x (FrankenPHP)
- Laravel Horizon: 5.x (队列监控)
- Laravel Telescope: 5.x (调试工具)
- 数据库: PostgreSQL 16
- 缓存/队列: Redis 7
- 认证: JWT (php-open-source-saver/jwt-auth)
- 容器化: Docker Compose
核心架构
数据模型
ChatSession (会话)
session_id(UUID, 主键): 会话唯一标识session_name: 会话名称status: 会话状态 (OPEN/LOCKED/CLOSED)last_seq: 最后消息序号last_message_id: 最后消息ID
Message (消息)
message_id(UUID, 主键): 消息唯一标识session_id: 所属会话IDrole: 消息角色 (USER/AGENT/TOOL/SYSTEM)type: 消息类型 (user.prompt/agent.message/run.status等)content: 消息内容 (text)payload: 附加数据 (jsonb)seq: 会话内序号 (单调递增)reply_to: 回复的消息IDdedupe_key: 幂等去重键- 约束:
unique(session_id, seq)和unique(session_id, dedupe_key)
会话状态与门禁规则
- OPEN: 正常追加所有消息
- LOCKED: 拒绝
role=USER && type=user.prompt - CLOSED: 拒绝追加,例外允许
role=SYSTEM && type in [run.status, error] - 状态变更规则: CLOSED 状态的会话不能重新打开
Agent Run 执行流程
- 用户发送
user.prompt消息后自动触发,或通过 API 手动触发 RunDispatcher检查幂等性(基于trigger_message_id)- 检查会话是否已有 RUNNING 状态的 run(单会话单任务限制)
- 创建
run.status=RUNNING消息并派发AgentRunJob RunLoop执行 Agent 调用流程:ContextBuilder构建上下文AgentProviderInterface调用 Agent(当前为 DummyAgentProvider)CancelChecker检查取消信号OutputSink写入 agent.message
- 完成后写入
run.status=DONE/FAILED/CANCELED
实时消息推送 (SSE)
- 端点:
GET /api/sessions/{id}/sse?after_seq=123 - 机制:
- 先从数据库补发历史消息(seq > after_seq)
- 订阅 Redis 频道
session:{id}:messages监听新消息 - 支持
Last-Event-ID自动续传
- 事件格式: SSE event id 为消息 seq
服务层架构
-
ChatService: 会话和消息的核心业务逻辑
- 使用行锁 (
lockForUpdate) + 事务保证消息 seq 单调递增 - 通过
dedupe_key实现幂等性 - 消息追加后发布 Redis 事件用于 SSE 推送
- 使用行锁 (
-
RunDispatcher: Agent Run 调度器
- 检查 trigger_message_id 幂等性
- 确保同会话只有一个 RUNNING 状态的 run
-
RunLoop: Agent 执行循环
- 协调 ContextBuilder、AgentProvider、OutputSink、CancelChecker
-
OutputSink: 统一的消息写入接口
appendAgentMessage(): 写入 agent 回复appendRunStatus(): 写入 run 状态appendError(): 写入错误信息
常用开发命令
Docker 容器操作
# 构建并启动所有服务
docker compose build
docker compose up -d app horizon pgsql redis
# 停止服务
docker compose stop
# 查看日志
docker compose logs -f app
docker compose logs -f horizon
# 进入容器 shell
docker compose exec app bash
数据库操作
# 运行迁移
docker compose exec app php artisan migrate
# 回滚迁移
docker compose exec app php artisan migrate:rollback
# 刷新数据库(危险:删除所有表并重新迁移)
docker compose exec app php artisan migrate:fresh
# 运行 seeder
docker compose exec app php artisan db:seed
测试
# 运行所有测试
docker compose exec app php artisan test
# 运行特定测试套件
docker compose exec app php artisan test --testsuite=Feature
docker compose exec app php artisan test --testsuite=Unit
# 运行特定测试文件
docker compose exec app php artisan test tests/Feature/ChatSessionTest.php
# 运行特定测试方法(使用 filter)
docker compose exec app php artisan test --filter=testCreateSession
docker compose exec app php artisan test --filter=testAppendMessageWithDedupe
# 显示测试覆盖率
docker compose exec app php artisan test --coverage
代码质量
# 运行 Laravel Pint 格式化代码
docker compose exec app vendor/bin/pint
# 只检查格式问题(不修改)
docker compose exec app vendor/bin/pint --test
# 格式化脏文件(git 变更的文件)
docker compose exec app vendor/bin/pint --dirty
队列与任务
# 查看 Horizon 仪表板
# 访问 http://localhost:8000/horizon
# 手动运行队列 worker(开发调试用)
docker compose exec app php artisan queue:work
# 查看失败的任务
docker compose exec app php artisan queue:failed
# 重试失败的任务
docker compose exec app php artisan queue:retry all
开发调试
# 启动 Tinker REPL
docker compose exec app php artisan tinker
# 查看路由列表
docker compose exec app php artisan route:list
# 清除缓存
docker compose exec app php artisan cache:clear
docker compose exec app php artisan config:clear
docker compose exec app php artisan route:clear
# 查看实时日志(使用 Laravel Pail)
docker compose exec app php artisan pail
Artisan 生成器
# 生成 Model(推荐带选项一次性生成相关文件)
docker compose exec app php artisan make:model ChatSession -mfs
# -m: migration, -f: factory, -s: seeder
# 生成 Controller
docker compose exec app php artisan make:controller ChatSessionController
# 生成 Form Request(用于验证)
docker compose exec app php artisan make:request AppendMessageRequest
# 生成 Resource(API 响应格式化)
docker compose exec app php artisan make:resource ChatSessionResource
# 生成 Job
docker compose exec app php artisan make:job AgentRunJob
# 生成 Service 类
docker compose exec app php artisan make:class Services/ChatService
# 生成测试
docker compose exec app php artisan make:test ChatSessionTest --phpunit
docker compose exec app php artisan make:test ChatServiceTest --unit --phpunit
API 路由结构
所有 API 路由均在 /api/* 下,除登录和健康检查外均需 JWT 认证:
POST /api/login: 用户登录GET /api/health: 健康检查GET /api/me: 获取当前用户信息
用户管理
GET /api/users: 用户列表POST /api/users: 创建用户PUT /api/users/{user}: 更新用户POST /api/users/{user}/deactivate: 停用用户POST /api/users/{user}/activate: 激活用户
会话管理
POST /api/sessions: 创建会话GET /api/sessions: 会话列表(支持分页、状态过滤、关键词搜索)GET /api/sessions/{session_id}: 获取会话详情PATCH /api/sessions/{session_id}: 更新会话(重命名、状态变更)POST /api/sessions/{session_id}/archive: 归档会话(幂等,设为 CLOSED)
消息管理
POST /api/sessions/{session_id}/messages: 追加消息(支持幂等 dedupe_key)GET /api/sessions/{session_id}/messages: 获取消息列表(支持 after_seq 增量拉取)GET /api/sessions/{session_id}/messages/{message_id}: 获取单条消息
实时与 Agent Run
GET /api/sessions/{session_id}/sse: SSE 实时消息流POST /api/sessions/{session_id}/runs: 手动触发 Agent Run
开发注意事项
Laravel 12 新特性
- 无
app/Console/Kernel.php和app/Http/Kernel.php - 中间件、路由、异常处理在
bootstrap/app.php配置 - 服务提供者在
bootstrap/providers.php注册 - Commands 自动注册(无需手动注册)
数据库操作规范
- 消息追加必须使用
ChatService::appendMessage(),不要直接操作 Message 模型 - 会话状态变更必须通过
ChatService::updateSession() - 所有涉及 seq 递增的操作必须在事务 + 行锁中完成
测试规范
- 所有测试使用 PHPUnit(非 Pest)
- Feature 测试必须测试完整的 HTTP 请求流程
- 测试中使用 Factory 创建模型数据
- 修改代码后必须运行相关测试确保通过
队列配置
- 开发环境可使用同步队列:
.env中设置QUEUE_CONNECTION=sync - 生产环境使用 Redis 队列 + Horizon 监控
AgentRunJob在队列中异步执行
幂等性设计
- 所有可能重复调用的操作都使用
dedupe_key RunDispatcher通过trigger_message_id确保不会为同一 prompt 重复创建 run- SSE 通过
Last-Event-ID/after_seq支持断线续传
环境变量关键配置
# Octane 服务器
OCTANE_SERVER=frankenphp
# 数据库(PostgreSQL)
DB_CONNECTION=pgsql
DB_HOST=pgsql
DB_PORT=5432
DB_DATABASE=ars_backend
# Redis
REDIS_HOST=redis
REDIS_PORT=6379
# 队列
QUEUE_CONNECTION=redis # 或 sync(开发用)
# JWT 认证
JWT_SECRET=<生成的密钥>
AUTH_GUARD=api
# CORS
CORS_ALLOWED_ORIGINS=http://localhost:5173
相关文档
- API 详细文档:
docs/ChatSession/chat-session-api.md - OpenAPI 规范:
docs/ChatSession/chat-session-openapi.yaml - 用户管理文档:
docs/User/user-api.md