Files
meijiaka-zy/AGENTS.md
T

409 lines
18 KiB
Markdown
Raw 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.
# AGENTS.md — 美家卡智影
> 本文档面向 AI Coding Agent。项目主要使用中文进行注释和界面文案,文档亦以中文撰写。
---
## 项目概述
**美家卡智影**是一款面向桌面端的 AI 视频创作应用,采用"Python 后端 API + Tauri 桌面前端"的混合架构。
- **产品标识**: `cn.meijiaka.ai-video` / `cn.meijiaka.ai-zy`
- **版本**: `1.9.1`
- **核心功能**: AI 脚本生成、AI 配音合成(TTS)、声音复刻、视频生成(Vidu)、视频字幕生成、压制成片(FFmpeg)、项目本地持久化
### 技术栈总览
| 层级 | 技术 |
|------|------|
| 后端框架 | FastAPI (Python 3.13, 异步) |
| 数据库 | PostgreSQL 15+ + SQLAlchemy 2.0 (asyncpg) |
| 缓存/队列 | Redis 7.x |
| 异步调度 | 自研 Async EngineSlot Scheduler |
| 桌面壳 | Tauri v2 (Rust) |
| 前端框架 | React 19 + TypeScript |
| 前端构建 | Vite 7 |
| 状态管理 | Zustand 5 + Immer 11 |
| 路由 | `react-router-dom` |
| 数据请求 | HTTP 客户端 (`src/api/client.ts`) + SWR |
| 测试(后端) | pytest + pytest-asyncio |
| 测试(前端) | Vitest 4 + jsdom + `@testing-library/react` |
| 部署 | Docker + Docker Compose + Nginx |
---
## 仓库结构
本仓库为 Monorepo,包含两个主要子项目:
```
.
├── python-api/ # Python 后端 API
├── tauri-app/ # Tauri 桌面前端
├── docs/ # 项目文档(架构设计、API 对接指南等)
├── scripts/ # 辅助脚本
├── .github/workflows/ # GitHub Actions CI/CD 配置
└── AGENTS.md # 本文档
```
### python-api/ 目录结构
```
python-api/
├── app/ # 主应用代码
│ ├── api/v1/ # API 路由(按领域拆分:auth, script, voice, vidu, caption, tasks, upload, materials, system, bgm_music, cover_background, image, points, update, events
│ ├── core/ # 核心工具(配置加载、安全、异常、Redis 客户端、健康检查)
│ ├── db/ # 数据库配置与会话管理
│ ├── models/ # SQLAlchemy ORM 模型(BaseModel 提供 UUID 主键 + 时间戳)
│ ├── schemas/ # Pydantic Schema(请求/响应校验)
│ ├── services/ # 业务逻辑层
│ ├── scheduler/ # Async Engine 异步任务调度(Slot Manager + Task Registry + Handlers
│ ├── ai/ # AI 模型封装(providers: volcengine, vidu, generic_llm
│ ├── crud/ # 数据库 CRUD 封装
│ ├── config.py # Pydantic Settings 配置管理
│ └── main.py # FastAPI 应用入口(含 lifespan 管理)
├── config/ # 运行时配置文件(platform-config.yaml, points-config.yaml
├── alembic/ # 数据库迁移脚本
├── nginx/ # Nginx 反向代理配置(含 acme.sh SSL 证书脚本)
├── Dockerfile # 多阶段构建镜像(builder + production
├── docker-compose.prod.yml # 生产环境编排
├── docker-compose.test.yml # 测试环境编排
├── pyproject.toml # Python 依赖与工具配置(black, ruff, mypy, pytest, bandit
├── requirements.lock # 锁定依赖(uv pip compile 生成)
├── uv.lock # uv 锁定文件
├── Makefile # 常用开发命令
└── .pre-commit-config.yaml # Git 钩子配置
```
### tauri-app/ 目录结构
```
tauri-app/
├── src/ # React 前端源码
│ ├── api/ # API 客户端与模块
│ │ ├── client.ts # HTTP 客户端(camelCase ↔ snake_case 自动转换)
│ │ └── modules/ # 按领域拆分的 API 模块
│ ├── components/ # 可复用组件(PascalCase 文件夹)
│ ├── pages/ # 页面级组件(PascalCase 文件夹)
│ ├── store/ # Zustand 状态管理
│ ├── hooks/ # 自定义 React Hooks
│ ├── utils/ # 工具函数
│ ├── styles/ # CSS 变量与全局样式
│ └── __tests__/setup.ts # Vitest 全局 setupmock localStorage / Tauri API
├── src-tauri/ # Rust 后端源码
│ ├── src/
│ │ ├── main.rs # 程序入口
│ │ ├── lib.rs # Tauri Builder、Command 定义、公共类型
│ │ ├── ffmpeg_cmd.rs # FFmpeg 命令封装
│ │ ├── video_processing.rs # 压制成片业务逻辑
│ │ ├── storage/ # 本地存储引擎(项目、认证、配置、头像等)
│ │ ├── commands/ # Tauri IPC 命令(按领域拆分:asset, auth_state, cover_avatar, file, product, project, video_compose, voice 等)
│ │ └── utils.rs # 通用工具
│ ├── Cargo.toml # Rust 依赖
│ ├── tauri.conf.json # Tauri 应用配置(窗口、CSP、打包、sidecar)
│ └── binaries/ # FFmpeg / ffprobe sidecar 二进制
├── package.json # Node 依赖与脚本
├── vite.config.ts # Vite 配置(端口 1420
├── vitest.config.ts # 测试配置
├── tsconfig.json # TypeScript 主配置(strict: true
├── eslint.config.js # ESLint 配置
├── .prettierrc # Prettier 配置
└── .stylelintrc.json # Stylelint 配置
```
---
## 运行时架构
采用**混合通信架构**
1. **纯数据 API**(脚本、TTS、字幕、视频生成、任务查询等)→ 前端通过 HTTP **直连 Python 后端**
- 脚本/TTS/字幕/视频生成统一走异步任务调度(`POST /tasks/{task_type}` + 轮询 `/tasks/{task_id}`),由 Scheduler 独立进程消费。
2. **需要本地系统能力**(FFmpeg 压制成片、文件系统读写、项目本地持久化、认证状态存储)→ 走 **Tauri IPC → Rust 层** 处理。
> 新增纯数据 API 时,**无需修改 Rust 代码**,直接在 `tauri-app/src/api/modules/` 下使用 `client.post/get` 调用即可。只有涉及本地系统能力的 API 才需要在 Rust 层新增 `#[tauri::command]`。
### 服务拓扑(生产/测试环境)
```
┌─────────────┐ HTTP ┌─────────────────┐
│ Tauri │ ────────────▶ │ Nginx (SSL) │
│ 桌面端 │ │ 反向代理 │
└─────────────┘ └────────┬────────┘
│ │
│ IPC (Rust) │
▼ ▼
┌─────────────┐ ┌─────────────────┐
│ FFmpeg │ │ FastAPI (8000) │
│ Sidecar │ │ - API 路由 │
│ 本地文件系统 │ │ - 业务逻辑 │
└─────────────┘ └────────┬────────┘
┌─────────────┼─────────────┐
▼ ▼ ▼
┌────────┐ ┌─────────┐ ┌──────────┐
│PostgreSQL│ │ Redis │ │ AI 服务商 │
└────────┘ └─────────┘ └──────────┘
┌───────────────┐
│ Async Engine │
│ Scheduler │
└───────────────┘
```
---
## 构建与开发命令
### 后端(python-api/
```bash
cd python-api
# 安装开发依赖(使用 uv
make dev
# 启动开发服务器
make run # uvicorn --reload --port 8000
# 启动异步调度器(另开终端)
make scheduler # python -m app.scheduler.main
# 代码质量
make lint # ruff check + mypy
make format # black + ruff --fix
make format-check # 检查格式(不修改)
make lint-semantic # 语义层禁词检查(防止供应商术语泄漏)
# 测试
make test # pytest -v
make test-cov # pytest + 覆盖率报告
# 安全扫描
make security # bandit + pip-audit
# CI 全量检查
make ci # format-check + lint + lint-semantic + test + security
# Docker 操作
make docker-run # 启动 api + scheduler(共享外部 db/redis
make docker-rebuild # 强制重建
make docker-stop # 停止(保留 db/redis
make docker-logs # 查看日志
# 数据库迁移
alembic revision --autogenerate -m "描述"
alembic upgrade head
```
### 前端(tauri-app/
```bash
cd tauri-app
# 前端开发服务器(Vite,端口 1420)
npm run dev
# 生产构建(tsc + vite build
npm run build
# Tauri 开发(启动 Rust + 前端)
npm run tauri dev
# Tauri 生产打包
npm run tauri build
# 测试
npm run test # Vitest
npm run test:ui # Vitest UI 模式
npm run test:coverage # 覆盖率
# 代码质量
npm run lint # ESLint
npm run lint:fix # ESLint --fix
npm run format # Prettier
npm run format:check # Prettier --check
npm run stylelint # Stylelint
npm run stylelint:fix # Stylelint --fix
# 注:当前项目未配置 OpenAPI 自动生成 TypeScript 类型的脚本
```
---
## 代码风格与约定
### 命名规范
| 类型 | 规范 | 示例 |
|------|------|------|
| 组件/页面文件夹 | PascalCase | `VideoCreation/`, `ErrorBoundary/` |
| Store/Hooks/API 文件 | camelCase | `authStore.ts`, `useProjectData.ts` |
| 类型/接口 | PascalCase | `ApiResponse<T>` |
| Python 模块/函数 | snake_case | `script_handler.py`, `get_settings()` |
| Python 类 | PascalCase | `AsyncEngine`, `BaseModel` |
| 常量 | UPPER_SNAKE_CASE | `PYTHON_API_BASE_URL` |
### 注释语言
- 项目内**统一使用中文注释**。
- 关键架构决策需在代码中以多行注释说明(参考 `python-api/app/scheduler/engine.py``tauri-app/src/api/client.ts` 顶部注释)。
### Python 代码质量
- **格式化**: black (line-length: 100)
- **检查**: ruff (select: E, F, I, N, W, UP, B, C4, SIM)
- **类型检查**: mypy(对 `app.schemas.*`, `app.crud.*`, `app.scheduler.handlers.*` 启用严格模式)
- **安全扫描**: bandit + pip-audit
- **依赖管理**: uv`requirements.lock` 必须与实际依赖同步,pre-commit 会检查)
### TypeScript 配置
- `strict: true` 已开启。
- `noUnusedLocals: true``noUnusedParameters: true` 已开启。
- `jsx: "react-jsx"`,无需手动引入 `React`
- 路径别名 `@/` 映射到 `./src`
### 状态管理约定(前端)
- 使用 **Zustand + Immer** 进行不可变更新。
- `projectStore` 使用自定义 `persist` 存储,将项目数据通过 Tauri IPC 持久化到本地文件系统(`app_config_dir/current_project.json`),而不是 localStorage。
- 其他 Store(如 `authStore``settingsStore`)使用 `localStorage` 做持久化。
### API 开发流程
1. **判断是否需要本地能力**(FFmpeg、文件系统、系统调用)。
2. **不需要** → 直接在 `tauri-app/src/api/modules/` 使用 `client.get/post/put/delete` 调用 Python HTTP API。
3. **需要** → 在 `tauri-app/src/api/modules/` 中通过 `@tauri-apps/api/core``invoke` 调用 Rust 命令,并在 `tauri-app/src-tauri/src/commands/``lib.rs` 中实现对应的 `#[tauri::command]` 处理器。
### 语义层防护网(后端)
Makefile 中 `lint-semantic` 目标会检查以下规则:
- API 层禁止使用 `element_id` 作为字段/参数名(应使用 `provider_element_id`)。
- Scheduler 层统一使用 `task` 命名(`TaskRegistry``task_id``task:` Redis key 前缀),禁止混用 `job`
---
## 测试说明
### 后端测试
- **框架**: pytest + pytest-asyncioasyncio_mode: auto
- **覆盖率**: pytest-cov
- **当前状态**: 后端尚无正式的 `tests/` 目录,测试用例待补充。
### 前端测试
- **框架**: Vitestglobals: trueenvironment: `jsdom`
- **组件测试**: `@testing-library/react` + `@testing-library/jest-dom`
- **文件位置**:
- 全局 setup: `src/__tests__/setup.ts`
- 组件/页面测试: 建议放在被测文件同目录或 `__tests__` 子目录中
- **Mock 策略**: `setup.ts` 中已全局 mock `localStorage``@tauri-apps/api/core``invoke` 方法、`window.__TAURI_INTERNALS__`。每个测试后自动调用 `vi.clearAllMocks()`
---
## 安全与部署
### 后端安全
- **JWT 认证**: `SECRET_KEY` 生产环境必须设置为强随机字符串(至少 32 位),否则应用启动时会抛出 `ValueError`
- **CORS**: 生产环境若包含 `localhost` 会触发 `RuntimeWarning`
- **依赖安全**: `aiohttp>=3.13.4``orjson>=3.11.0` 为强制最低版本(修复 CVE)。
- **输入验证**: 所有 API 入参通过 Pydantic Schema 校验。
- **数据库**: 使用参数化查询(SQLAlchemy ORM),无直接 SQL 拼接。
### 前端安全
- **CSP**: `tauri.conf.json` 中已配置 Content Security Policy。
- **Asset Protocol**: 已启用,范围限定在 `$APPLOCALDATA/**``$APPDATA/**``$APPCONFIG/**`
### 部署流程
#### 测试环境(GitHub Actions
`.github/workflows/` 存放 CI/CD 工作流:
- `release.yml`Tauri 桌面端 Release 打包工作流(按 tag 触发,支持 macOS / Windows 平台及 sidecar 二进制下载)。
- 后端 api + scheduler 的测试/生产部署目前通过手动执行 `docker-compose.test.yml` / `docker-compose.prod.yml` 完成。
#### 生产环境
1. 从环境变量或密钥管理注入配置。
2. `docker compose -f docker-compose.prod.yml up -d --build`
3. 外部提供 PostgreSQL 和 Redis(云数据库或自建集群)。
4. Nginx 反向代理 + acme.sh SSL 证书。
### 外部二进制与 Sidecar
- **FFmpeg / ffprobe** 作为 **sidecar** 打包到 Tauri 应用(`bundle.externalBin`)。
- Rust 层通过 `tauri_plugin_shell``sidecar("ffmpeg")` 调用。
- 合成过程中解析 FFmpeg stderr 中的 `time=` 字段,通过 Tauri Event 向前端发送进度。
---
## 环境变量(后端)
关键配置项见 `python-api/.env.example`
| 变量 | 说明 | 默认值 |
|------|------|--------|
| `DATABASE_URL` | PostgreSQL 连接字符串 | `postgresql+asyncpg://postgres:postgres@localhost:5432/meijiaka_zy` |
| `REDIS_HOST` / `REDIS_PORT` / `REDIS_DB` | Redis 连接信息 | `localhost:6379:0` |
| `SECRET_KEY` | JWT 签名密钥 | 必须修改 |
| `CORS_ORIGINS` | 允许的跨域来源 | `http://localhost:1420,...` |
| `VOLCENGINE_API_KEY` | 火山方舟 API Key | - |
| `VIDU_API_KEY` | Vidu API Key | - |
| `QINIU_ACCESS_KEY` / `QINIU_SECRET_KEY` | 七牛云存储密钥 | - |
| `APP_BASE_URL` | 应用公网地址(第三方回调用) | 按 ENV 自动推断 |
### 配置变更策略
> Python 的模块导入机制决定了**运行时热替换配置是反模式**FastAPI/Pydantic 官方不推荐。测试与生产环境统一遵循以下策略:
| 场景 | 做法 | 说明 |
|------|------|------|
| 数值/业务规则配置 | **代码常量** | 如 SMS 验证码位数、过期时间等,不走 `.env`,防止运维随意修改 |
| 环境配置(密钥、URL 等) | **`.env` 文件** | 变更后统一走 Docker 滚动重启,**所有环境均不支持热重载** |
| 更新方式 | **`docker compose up -d --build`** | 测试/生产完全一致:`docker-compose.test.yml``docker-compose.prod.yml` 保持相同的重启策略 |
**注意**`reload_settings()` 仅作为代码级工具保留(内部调试直接 import 调用),HTTP 接口已删除,测试与生产环境统一走 Docker 滚动重启更新配置。
---
## 数据库与迁移
- **ORM**: SQLAlchemy 2.0(异步,asyncpg 驱动)
- **迁移工具**: Alembic
- **基础模型**: `app.models.base.BaseModel` 提供 UUID 主键、`created_at``updated_at`
- **当前模型**: 包括 `User`(用户/设备认证)、`UserDevice``UserPoint``PointRechargeOrder``PointTransaction``BrollCategory``BrollMaterial``BrollTag``CoverBackground``BgmMusic``Update`
- **迁移注意**: Alembic 使用同步连接(psycopg2),会自动将 `+asyncpg` 替换掉。
---
## 异步任务调度(Async Engine
后端采用自研的**统一异步任务调度引擎**,核心概念:
- **TaskRegistry**: 基于 Redis 的任务注册表,维护 running / pending / finished 状态。
- **SlotManager**: 基于 Redis 的并发槽位管理,按 task_type 限制最大并发数,统一使用 `acquire_ctx` 上下文管理器。
- **AsyncHandler**: 各领域的异步任务处理器(`script`/`tts`/`subtitle`/`video`)。
- **Engine Tick**: 定时轮询所有 running 任务,批量查询状态、批量更新。
调度器需单独启动:`make scheduler``python -m app.scheduler.main`
---
## 给 Agent 的快速检查清单
在修改代码前,建议确认以下事项:
1. **新增 API 是否需要 Rust 层?** 不需要则只改前端 `src/api/modules/` 和后端 `app/api/v1/`
2. **修改 Store 后是否影响持久化?** `projectStore``partialize` 字段决定哪些状态会被保存到本地文件。
3. **新增组件是否遵循 PascalCase 文件夹约定?**
4. **后端代码是否触发语义层禁词?** 运行 `make lint-semantic`
5. **依赖变更后是否更新了 lock 文件?** 运行 `uv pip compile pyproject.toml -o requirements.lock`
6. **测试是否通过?** 前端运行 `npm run test`,后端运行 `make test`
7. **Tauri 配置变更后是否需要重新 `tauri dev`** 是的,`tauri.conf.json``Cargo.toml` 变更后需重启 Tauri 进程。
8. **修改 pyproject.toml 后 pre-commit 是否通过?** `requirements.lock` 必须与 pyproject.toml 同步。