# AGENTS.md — 美家卡智影

> 本文档面向 AI Coding Agent。项目主要使用中文进行注释和界面文案，文档亦以中文撰写。

---

## 项目概述

**美家卡智影**是一款面向桌面端的 AI 视频创作应用，采用"Python 后端 API + Tauri 桌面前端"的混合架构。

- **产品标识**: `cn.meijiaka.ai-video` / `cn.meijiaka.ai-zy`
- **版本**: `1.6.7`
- **核心功能**: AI 脚本生成、AI 配音合成（TTS）、声音复刻、视频生成（Vidu）、视频字幕生成、压制成片（FFmpeg）、项目本地持久化

### 技术栈总览

| 层级 | 技术 |
|------|------|
| 后端框架 | FastAPI (Python 3.13, 异步) |
| 数据库 | PostgreSQL 15+ + SQLAlchemy 2.0 (asyncpg) |
| 缓存/队列 | Redis 7.x |
| 异步调度 | 自研 Async Engine（Slot Scheduler） |
| 桌面壳 | Tauri v2 (Rust) |
| 前端框架 | React 19 + TypeScript |
| 前端构建 | Vite 7 |
| 状态管理 | Zustand 5 + Immer 11 |
| 路由 | `react-router-dom` |
| 数据请求 | 自研智能路由客户端 + 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/             # 辅助脚本
├── .gitlab-ci.yml       # GitLab CI/CD 配置
└── AGENTS.md            # 本文档
```

### python-api/ 目录结构

```
python-api/
├── app/                    # 主应用代码
│   ├── api/v1/            # API 路由（按领域拆分：auth, script, voice, vidu, caption, tasks, upload, materials, system）
│   ├── 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, materials.json）
├── 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 / IPC 自动选择，camelCase ↔ snake_case 自动转换）
│   │   ├── generated/     # OpenAPI 生成的 TypeScript 类型
│   │   └── modules/       # 按领域拆分的 API 模块
│   ├── components/        # 可复用组件（PascalCase 文件夹）
│   ├── pages/             # 页面级组件（PascalCase 文件夹）
│   ├── store/             # Zustand 状态管理（含 __tests__）
│   ├── hooks/             # 自定义 React Hooks
│   ├── utils/             # 工具函数
│   ├── styles/            # CSS 变量与全局样式
│   └── __tests__/setup.ts # Vitest 全局 setup（mock localStorage / Tauri API）
├── src-tauri/             # Rust 后端源码
│   ├── src/
│   │   ├── main.rs        # 程序入口
│   │   ├── lib.rs         # Tauri Builder、Command 定义、公共类型
│   │   ├── ffmpeg_cmd.rs  # FFmpeg 命令封装
│   │   ├── video_processing.rs # 压制成片业务逻辑
│   │   ├── api_proxy.rs   # Python API 代理
│   │   ├── auth.rs        # 认证命令
│   │   ├── avatar_cache.rs # 头像缓存
│   │   ├── storage/       # 本地存储引擎（项目、认证、配置、头像等）
│   │   ├── commands/      # Tauri IPC 命令（按领域拆分）
│   │   └── 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 类型生成
npm run gen:api       # 根据 openapi.json 生成 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. **需要** → 将 endpoint 加入 `tauri-app/src/api/client.ts` 的 IPC 处理逻辑，并在 `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-asyncio（asyncio_mode: auto）
- **覆盖率**: pytest-cov
- **当前状态**: 后端尚无正式的 `tests/` 目录，测试用例待补充。

### 前端测试

- **框架**: Vitest（globals: true，environment: `jsdom`）
- **组件测试**: `@testing-library/react` + `@testing-library/jest-dom`
- **文件位置**:
  - 全局 setup: `src/__tests__/setup.ts`
  - Store 测试: `src/store/__tests__/*.test.tsx`
  - 组件/页面测试: 建议放在被测文件同目录或 `__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/**`。

### 部署流程

#### 测试环境（GitLab CI）

`.gitlab-ci.yml` 定义了 `deploy-backend` 任务：
1. 在部署服务器拉取代码（`master` 分支触发）。
2. 构建 api + scheduler 镜像（`docker-compose.test.yml`）。
3. 启动服务，健康检查 `curl http://localhost:8081/health`。
4. 清理 7 天前的旧镜像。

#### 生产环境

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`（用户/设备认证）
- **迁移注意**: 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 同步。
