调整 Docker 环境与依赖配置:

- 替换基础镜像为 `php:8.4.15-cli-alpine3.23`,重构依赖安装流程
- 切换包管理工具为 `apk`,添加必要系统库及扩展
- 更新 Composer 脚本及依赖映射
- 优化命令与环境变量配置,增强一致性与兼容性
This commit is contained in:
2025-12-17 17:13:37 +08:00
parent ced95c02cb
commit fa00da5966
6 changed files with 272 additions and 169 deletions

View File

@@ -1,9 +1,12 @@
{
"mcpServers": {
"laravel-boost": {
"command": "docker compose run app",
"command": "docker",
"args": [
"vendor/bin/sail",
"compose",
"exec",
"app",
"php",
"artisan",
"boost:mcp"
]

411
CLAUDE.md
View File

@@ -1,228 +1,317 @@
<laravel-boost-guidelines>
=== foundation rules ===
# 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`: 所属会话ID
- `role`: 消息角色 (USER/AGENT/TOOL/SYSTEM)
- `type`: 消息类型 (user.prompt/agent.message/run.status等)
- `content`: 消息内容 (text)
- `payload`: 附加数据 (jsonb)
- `seq`: 会话内序号 (单调递增)
- `reply_to`: 回复的消息ID
- `dedupe_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 状态的会话不能重新打开
# Laravel Boost Guidelines
### Agent Run 执行流程
The Laravel Boost guidelines are specifically curated by Laravel maintainers for this application. These guidelines should be followed closely to enhance the user's satisfaction building Laravel applications.
1. 用户发送 `user.prompt` 消息后自动触发,或通过 API 手动触发
2. `RunDispatcher` 检查幂等性(基于 `trigger_message_id`
3. 检查会话是否已有 RUNNING 状态的 run单会话单任务限制
4. 创建 `run.status=RUNNING` 消息并派发 `AgentRunJob`
5. `RunLoop` 执行 Agent 调用流程:
- `ContextBuilder` 构建上下文
- `AgentProviderInterface` 调用 Agent当前为 DummyAgentProvider
- `CancelChecker` 检查取消信号
- `OutputSink` 写入 agent.message
6. 完成后写入 `run.status=DONE/FAILED/CANCELED`
## Foundational Context
This application is a Laravel application and its main Laravel ecosystems package & versions are below. You are an expert with them all. Ensure you abide by these specific packages & versions.
### 实时消息推送 (SSE)
- php - 8.3.28
- laravel/framework (LARAVEL) - v12
- laravel/horizon (HORIZON) - v5
- laravel/octane (OCTANE) - v2
- laravel/prompts (PROMPTS) - v0
- laravel/telescope (TELESCOPE) - v5
- laravel/mcp (MCP) - v0
- laravel/pint (PINT) - v1
- laravel/sail (SAIL) - v1
- phpunit/phpunit (PHPUNIT) - v11
- **端点**: `GET /api/sessions/{id}/sse?after_seq=123`
- **机制**:
1. 先从数据库补发历史消息seq > after_seq
2. 订阅 Redis 频道 `session:{id}:messages` 监听新消息
3. 支持 `Last-Event-ID` 自动续传
- **事件格式**: SSE event id 为消息 seq
## Conventions
- You must follow all existing code conventions used in this application. When creating or editing a file, check sibling files for the correct structure, approach, naming.
- Use descriptive names for variables and methods. For example, `isRegisteredForDiscounts`, not `discount()`.
- Check for existing components to reuse before writing a new one.
### 服务层架构
## Verification Scripts
- Do not create verification scripts or tinker when tests cover that functionality and prove it works. Unit and feature tests are more important.
- **ChatService**: 会话和消息的核心业务逻辑
- 使用行锁 (`lockForUpdate`) + 事务保证消息 seq 单调递增
- 通过 `dedupe_key` 实现幂等性
- 消息追加后发布 Redis 事件用于 SSE 推送
## Application Structure & Architecture
- Stick to existing directory structure - don't create new base folders without approval.
- Do not change the application's dependencies without approval.
- **RunDispatcher**: Agent Run 调度器
- 检查 trigger_message_id 幂等性
- 确保同会话只有一个 RUNNING 状态的 run
## Frontend Bundling
- If the user doesn't see a frontend change reflected in the UI, it could mean they need to run `vendor/bin/sail npm run build`, `vendor/bin/sail npm run dev`, or `vendor/bin/sail composer run dev`. Ask them.
- **RunLoop**: Agent 执行循环
- 协调 ContextBuilder、AgentProvider、OutputSink、CancelChecker
## Replies
- Be concise in your explanations - focus on what's important rather than explaining obvious details.
- **OutputSink**: 统一的消息写入接口
- `appendAgentMessage()`: 写入 agent 回复
- `appendRunStatus()`: 写入 run 状态
- `appendError()`: 写入错误信息
## Documentation Files
- You must only create documentation files if explicitly requested by the user.
## 常用开发命令
### Docker 容器操作
=== boost rules ===
```bash
# 构建并启动所有服务
docker compose build
docker compose up -d app horizon pgsql redis
## Laravel Boost
- Laravel Boost is an MCP server that comes with powerful tools designed specifically for this application. Use them.
# 停止服务
docker compose stop
## Artisan
- Use the `list-artisan-commands` tool when you need to call an Artisan command to double check the available parameters.
# 查看日志
docker compose logs -f app
docker compose logs -f horizon
## URLs
- Whenever you share a project URL with the user you should use the `get-absolute-url` tool to ensure you're using the correct scheme, domain / IP, and port.
# 进入容器 shell
docker compose exec app bash
```
## Tinker / Debugging
- You should use the `tinker` tool when you need to execute PHP to debug code or query Eloquent models directly.
- Use the `database-query` tool when you only need to read from the database.
### 数据库操作
## Reading Browser Logs With the `browser-logs` Tool
- You can read browser logs, errors, and exceptions using the `browser-logs` tool from Boost.
- Only recent browser logs will be useful - ignore old logs.
```bash
# 运行迁移
docker compose exec app php artisan migrate
## Searching Documentation (Critically Important)
- Boost comes with a powerful `search-docs` tool you should use before any other approaches. This tool automatically passes a list of installed packages and their versions to the remote Boost API, so it returns only version-specific documentation specific for the user's circumstance. You should pass an array of packages to filter on if you know you need docs for particular packages.
- The 'search-docs' tool is perfect for all Laravel related packages, including Laravel, Inertia, Livewire, Filament, Tailwind, Pest, Nova, Nightwatch, etc.
- You must use this tool to search for Laravel-ecosystem documentation before falling back to other approaches.
- Search the documentation before making code changes to ensure we are taking the correct approach.
- Use multiple, broad, simple, topic based queries to start. For example: `['rate limiting', 'routing rate limiting', 'routing']`.
- Do not add package names to queries - package information is already shared. For example, use `test resource table`, not `filament 4 test resource table`.
# 回滚迁移
docker compose exec app php artisan migrate:rollback
### Available Search Syntax
- You can and should pass multiple queries at once. The most relevant results will be returned first.
# 刷新数据库(危险:删除所有表并重新迁移)
docker compose exec app php artisan migrate:fresh
1. Simple Word Searches with auto-stemming - query=authentication - finds 'authenticate' and 'auth'
2. Multiple Words (AND Logic) - query=rate limit - finds knowledge containing both "rate" AND "limit"
3. Quoted Phrases (Exact Position) - query="infinite scroll" - Words must be adjacent and in that order
4. Mixed Queries - query=middleware "rate limit" - "middleware" AND exact phrase "rate limit"
5. Multiple Queries - queries=["authentication", "middleware"] - ANY of these terms
# 运行 seeder
docker compose exec app php artisan db:seed
```
### 测试
=== php rules ===
```bash
# 运行所有测试
docker compose exec app php artisan test
## PHP
# 运行特定测试套件
docker compose exec app php artisan test --testsuite=Feature
docker compose exec app php artisan test --testsuite=Unit
- Always use curly braces for control structures, even if it has one line.
# 运行特定测试文件
docker compose exec app php artisan test tests/Feature/ChatSessionTest.php
### Constructors
- Use PHP 8 constructor property promotion in `__construct()`.
- <code-snippet>public function __construct(public GitHub $github) { }</code-snippet>
- Do not allow empty `__construct()` methods with zero parameters.
# 运行特定测试方法(使用 filter
docker compose exec app php artisan test --filter=testCreateSession
docker compose exec app php artisan test --filter=testAppendMessageWithDedupe
### Type Declarations
- Always use explicit return type declarations for methods and functions.
- Use appropriate PHP type hints for method parameters.
# 显示测试覆盖率
docker compose exec app php artisan test --coverage
```
<code-snippet name="Explicit Return Types and Method Params" lang="php">
protected function isAccessible(User $user, ?string $path = null): bool
{
...
}
</code-snippet>
### 代码质量
## Comments
- Prefer PHPDoc blocks over comments. Never use comments within the code itself unless there is something _very_ complex going on.
```bash
# 运行 Laravel Pint 格式化代码
docker compose exec app vendor/bin/pint
## PHPDoc Blocks
- Add useful array shape type definitions for arrays when appropriate.
# 只检查格式问题(不修改)
docker compose exec app vendor/bin/pint --test
## Enums
- Typically, keys in an Enum should be TitleCase. For example: `FavoritePerson`, `BestLake`, `Monthly`.
# 格式化脏文件git 变更的文件)
docker compose exec app vendor/bin/pint --dirty
```
### 队列与任务
=== sail rules ===
```bash
# 查看 Horizon 仪表板
# 访问 http://localhost:8000/horizon
## Laravel Sail
# 手动运行队列 worker开发调试用
docker compose exec app php artisan queue:work
- This project runs inside Laravel Sail's Docker containers. You MUST execute all commands through Sail.
- Start services using `vendor/bin/sail up -d` and stop them with `vendor/bin/sail stop`.
- Open the application in the browser by running `vendor/bin/sail open`.
- Always prefix PHP, Artisan, Composer, and Node commands** with `vendor/bin/sail`. Examples:
- Run Artisan Commands: `vendor/bin/sail artisan migrate`
- Install Composer packages: `vendor/bin/sail composer install`
- Execute node commands: `vendor/bin/sail npm run dev`
- Execute PHP scripts: `vendor/bin/sail php [script]`
- View all available Sail commands by running `vendor/bin/sail` without arguments.
# 查看失败的任务
docker compose exec app php artisan queue:failed
# 重试失败的任务
docker compose exec app php artisan queue:retry all
```
=== tests rules ===
### 开发调试
## Test Enforcement
```bash
# 启动 Tinker REPL
docker compose exec app php artisan tinker
- Every change must be programmatically tested. Write a new test or update an existing test, then run the affected tests to make sure they pass.
- Run the minimum number of tests needed to ensure code quality and speed. Use `vendor/bin/sail artisan test` with a specific filename or filter.
# 查看路由列表
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/core rules ===
# 查看实时日志(使用 Laravel Pail
docker compose exec app php artisan pail
```
## Do Things the Laravel Way
### Artisan 生成器
- Use `vendor/bin/sail artisan make:` commands to create new files (i.e. migrations, controllers, models, etc.). You can list available Artisan commands using the `list-artisan-commands` tool.
- If you're creating a generic PHP class, use `vendor/bin/sail artisan make:class`.
- Pass `--no-interaction` to all Artisan commands to ensure they work without user input. You should also pass the correct `--options` to ensure correct behavior.
```bash
# 生成 Model推荐带选项一次性生成相关文件
docker compose exec app php artisan make:model ChatSession -mfs
# -m: migration, -f: factory, -s: seeder
### Database
- Always use proper Eloquent relationship methods with return type hints. Prefer relationship methods over raw queries or manual joins.
- Use Eloquent models and relationships before suggesting raw database queries
- Avoid `DB::`; prefer `Model::query()`. Generate code that leverages Laravel's ORM capabilities rather than bypassing them.
- Generate code that prevents N+1 query problems by using eager loading.
- Use Laravel's query builder for very complex database operations.
# 生成 Controller
docker compose exec app php artisan make:controller ChatSessionController
### Model Creation
- When creating new models, create useful factories and seeders for them too. Ask the user if they need any other things, using `list-artisan-commands` to check the available options to `vendor/bin/sail artisan make:model`.
# 生成 Form Request用于验证
docker compose exec app php artisan make:request AppendMessageRequest
### APIs & Eloquent Resources
- For APIs, default to using Eloquent API Resources and API versioning unless existing API routes do not, then you should follow existing application convention.
# 生成 ResourceAPI 响应格式化)
docker compose exec app php artisan make:resource ChatSessionResource
### Controllers & Validation
- Always create Form Request classes for validation rather than inline validation in controllers. Include both validation rules and custom error messages.
- Check sibling Form Requests to see if the application uses array or string based validation rules.
# 生成 Job
docker compose exec app php artisan make:job AgentRunJob
### Queues
- Use queued jobs for time-consuming operations with the `ShouldQueue` interface.
# 生成 Service 类
docker compose exec app php artisan make:class Services/ChatService
### Authentication & Authorization
- Use Laravel's built-in authentication and authorization features (gates, policies, Sanctum, etc.).
# 生成测试
docker compose exec app php artisan make:test ChatSessionTest --phpunit
docker compose exec app php artisan make:test ChatServiceTest --unit --phpunit
```
### URL Generation
- When generating links to other pages, prefer named routes and the `route()` function.
## API 路由结构
### Configuration
- Use environment variables only in configuration files - never use the `env()` function directly outside of config files. Always use `config('app.name')`, not `env('APP_NAME')`.
所有 API 路由均在 `/api/*` 下,除登录和健康检查外均需 JWT 认证:
### Testing
- When creating models for tests, use the factories for the models. Check if the factory has custom states that can be used before manually setting up the model.
- Faker: Use methods such as `$this->faker->word()` or `fake()->randomDigit()`. Follow existing conventions whether to use `$this->faker` or `fake()`.
- When creating tests, make use of `vendor/bin/sail artisan make:test [options] {name}` to create a feature test, and pass `--unit` to create a unit test. Most tests should be feature tests.
- `POST /api/login`: 用户登录
- `GET /api/health`: 健康检查
- `GET /api/me`: 获取当前用户信息
### Vite Error
- If you receive an "Illuminate\Foundation\ViteException: Unable to locate file in Vite manifest" error, you can run `vendor/bin/sail npm run build` or ask the user to run `vendor/bin/sail npm run dev` or `vendor/bin/sail composer run dev`.
### 用户管理
- `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
=== laravel/v12 rules ===
### 消息管理
- `POST /api/sessions/{session_id}/messages`: 追加消息(支持幂等 dedupe_key
- `GET /api/sessions/{session_id}/messages`: 获取消息列表(支持 after_seq 增量拉取)
- `GET /api/sessions/{session_id}/messages/{message_id}`: 获取单条消息
## Laravel 12
### 实时与 Agent Run
- `GET /api/sessions/{session_id}/sse`: SSE 实时消息流
- `POST /api/sessions/{session_id}/runs`: 手动触发 Agent Run
- Use the `search-docs` tool to get version specific documentation.
- Since Laravel 11, Laravel has a new streamlined file structure which this project uses.
## 开发注意事项
### Laravel 12 Structure
- No middleware files in `app/Http/Middleware/`.
- `bootstrap/app.php` is the file to register middleware, exceptions, and routing files.
- `bootstrap/providers.php` contains application specific service providers.
- **No app\Console\Kernel.php** - use `bootstrap/app.php` or `routes/console.php` for console configuration.
- **Commands auto-register** - files in `app/Console/Commands/` are automatically available and do not require manual registration.
### Laravel 12 新特性
- `app/Console/Kernel.php` `app/Http/Kernel.php`
- 中间件、路由、异常处理在 `bootstrap/app.php` 配置
- 服务提供者在 `bootstrap/providers.php` 注册
- Commands 自动注册(无需手动注册)
### Database
- When modifying a column, the migration must include all of the attributes that were previously defined on the column. Otherwise, they will be dropped and lost.
- Laravel 11 allows limiting eagerly loaded records natively, without external packages: `$query->latest()->limit(10);`.
### 数据库操作规范
- 消息追加必须使用 `ChatService::appendMessage()`,不要直接操作 Message 模型
- 会话状态变更必须通过 `ChatService::updateSession()`
- 所有涉及 seq 递增的操作必须在事务 + 行锁中完成
### Models
- Casts can and likely should be set in a `casts()` method on a model rather than the `$casts` property. Follow existing conventions from other models.
### 测试规范
- 所有测试使用 PHPUnit非 Pest
- Feature 测试必须测试完整的 HTTP 请求流程
- 测试中使用 Factory 创建模型数据
- 修改代码后必须运行相关测试确保通过
### 队列配置
- 开发环境可使用同步队列:`.env` 中设置 `QUEUE_CONNECTION=sync`
- 生产环境使用 Redis 队列 + Horizon 监控
- `AgentRunJob` 在队列中异步执行
=== pint/core rules ===
### 幂等性设计
- 所有可能重复调用的操作都使用 `dedupe_key`
- `RunDispatcher` 通过 `trigger_message_id` 确保不会为同一 prompt 重复创建 run
- SSE 通过 `Last-Event-ID` / `after_seq` 支持断线续传
## Laravel Pint Code Formatter
## 环境变量关键配置
- You must run `vendor/bin/sail bin pint --dirty` before finalizing changes to ensure your code matches the project's expected style.
- Do not run `vendor/bin/sail bin pint --test`, simply run `vendor/bin/sail bin pint` to fix any formatting issues.
```bash
# Octane 服务器
OCTANE_SERVER=frankenphp
# 数据库PostgreSQL
DB_CONNECTION=pgsql
DB_HOST=pgsql
DB_PORT=5432
DB_DATABASE=ars_backend
=== phpunit/core rules ===
# Redis
REDIS_HOST=redis
REDIS_PORT=6379
# 队列
QUEUE_CONNECTION=redis # 或 sync开发用
## PHPUnit Core
# JWT 认证
JWT_SECRET=<生成的密钥>
AUTH_GUARD=api
- This application uses PHPUnit for testing. All tests must be written as PHPUnit classes. Use `vendor/bin/sail artisan make:test --phpunit {name}` to create a new test.
- If you see a test using "Pest", convert it to PHPUnit.
- Every time a test has been updated, run that singular test.
- When the tests relating to your feature are passing, ask the user if they would like to also run the entire test suite to make sure everything is still passing.
- Tests should test all of the happy paths, failure paths, and weird paths.
- You must not remove any tests or test files from the tests directory without approval. These are not temporary or helper files, these are core to the application.
### Running Tests
- Run the minimal number of tests, using an appropriate filter, before finalizing.
- To run all tests: `vendor/bin/sail artisan test`.
- To run all tests in a file: `vendor/bin/sail artisan test tests/Feature/ExampleTest.php`.
- To filter on a particular test name: `vendor/bin/sail artisan test --filter=testName` (recommended after making a change to a related file).
</laravel-boost-guidelines>
# 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`

View File

@@ -1,23 +1,33 @@
FROM dunglas/frankenphp:1-php8.2
FROM php:8.4.15-cli-alpine3.23
WORKDIR /app
# System packages and PHP extensions required by Laravel/Octane
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
RUN apk update \
&& apk add --no-cache \
git \
unzip \
libzip-dev \
libpq-dev \
zlib1g-dev \
postgresql-dev \
zlib-dev \
libpq \
icu-dev \
gcc \
g++ \
make \
autoconf \
libc-dev \
pkgconfig \
&& docker-php-ext-install \
pcntl \
zip \
pdo_mysql \
pdo_pgsql \
intl \
&& pecl install redis \
&& docker-php-ext-enable redis \
&& rm -rf /var/lib/apt/lists/*
pdo_pgsql \
&& rm -rf /var/cache/apk/*
# Composer for dependency management
COPY --from=composer:2 /usr/bin/composer /usr/local/bin/composer

View File

@@ -30,5 +30,6 @@
<env name="PULSE_ENABLED" value="false"/>
<env name="TELESCOPE_ENABLED" value="false"/>
<env name="NIGHTWATCH_ENABLED" value="false"/>
<env name="JWT_SECRET" value="testing_jwt_secret_for_unit_tests_32_chars_min"/>
</php>
</phpunit>