Files
CamTalk/CLAUDE.md
2026-07-17 10:43:27 +08:00

129 lines
7.6 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.
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
CamTalk — 多模态实时 AI 视觉对话助手(摄像头 + 麦克风 + 视觉 + 语音 AI
> **文档优先原则:** 开发前先读 `docs/` 设计文档,以文档为准;若代码与文档不一致,优先更新文档(尤其接口文档)。详细设计见 `docs/01-13` 系列文档。**注意**`docs/Eino/` 框架文档内容庞大(~75 个文件),仅在需要了解 Eino Graph/节点/Callback 等框架细节时才读取。
## 常用命令
```bash
# === 前端frontend/ 目录)===
npm run dev # Vite 开发服务器http://localhost:5173代理 /ws 和 /api 到 :8080
npm run build # 生产构建tsc -b && vite build输出到 dist/
npm run lint # ESLint 代码检查
npm run preview # 预览生产构建
# === 后端backend/ 目录)===
go run ./cmd/server # 启动服务(监听 :8080启动时自动执行数据库迁移
golangci-lint run # Go 代码检查
# 后端测试
go test ./... # 单元测试
go test -tags=integration ./... # 集成测试(需要 PostgreSQL
go test -v -run TestXxx ./path/ # 运行单个测试
# === Docker 部署 ===
./deploy.sh build # 构建 Docker 镜像
./deploy.sh up # 启动服务4 容器frontend/backend/postgres/redis
./deploy.sh down # 停止服务
./deploy.sh logs # 查看日志(可加服务名:./deploy.sh logs backend
./deploy.sh status # 查看服务状态
```
## 架构
三层系统前端React + Vite→ Go 网关Gin + WebSocket + Eino Graph AI 编排)→ AI 服务DashScope LLM, MiMo STT/TTS
**AI 编排流水线**Eino Graph 7 节点 DAG`STT → History → ChatModel → Msg2Str → Splitter → TTS → Done`。LLM token 通过 Callback 实时推送TTS 逐句并行合成。
**会话存储**TieredManagerL1 Memory → L2 Redis → L3 PostgreSQL 三级存储30 分钟 TTLRedis 故障自动降级。
**鉴权**JWT 双 token 轮转Access 120min + Refresh 7d重放攻击检测DB hash 校验Redis 缓存装饰器。
## 技术栈
前端React 18 + TypeScript + ViteVAD@ricky0123/vad-webONNX Runtime国际化zh-CN / en-US / ja-JP
后端Go 1.25+, Gin, WebSocket, Viper, Zap, CloudWeGo Eino Graph
AIDashScope qwen3-vl-plus, MiMo ASR/TTS可切换 Deepgram/OpenAI TTS
存储PostgreSQL 15 + Redis 7
CI/CDGitea Actions`.gitea/workflows/deploy.yml`push main/v2 自动构建部署到自建 aliyun runner
前端测试:**暂无**package.json 无 test 脚本,无测试框架配置)
## 配置体系
配置优先级:**环境变量 > `config.{APP_ENV}.yaml` > `config.yaml` > 代码默认值**
配置文件位于 `backend/config/`
- `config.yaml` — 基础配置dev 默认值)
- `config.dev.yaml` — 开发环境覆盖(可选)
- `config.prod.yaml` — 生产环境覆盖(可选)
环境切换:`APP_ENV=dev|prod`dev 默认prod 启用限流 + 严格 CORS + Release 模式)
敏感信息API Key、JWT Secret、数据库密码**只能通过环境变量或 `.env` 文件注入**,不写入 YAML 配置文件。核心环境变量(参考 `backend/.env.example`
| 变量 | 说明 |
|------|------|
| `CAMTALK_AI_LLM_API_KEY` | LLM API KeyDashScope |
| `CAMTALK_AI_STT_API_KEY` | STT API KeyMiMo/Deepgram |
| `CAMTALK_AI_TTS_API_KEY` | TTS API KeyMiMo/OpenAI |
| `CAMTALK_AUTH_JWT_SECRET` | JWT 签名密钥 |
| `CAMTALK_STORAGE_DSN` | PostgreSQL 连接字符串 |
| `CAMTALK_REDIS_ADDR` | Redis 地址 |
| `CAMTALK_REDIS_PASSWORD` | Redis 密码 |
## 数据库迁移
迁移 SQL 文件位于 `backend/migrations/``001_*.up.sql` 等),通过 Go `//go:embed` 嵌入二进制(见 `backend/migrations/embed.go`)。应用启动时**自动执行**未应用的迁移,无需手动运行迁移命令。迁移通过 `schema_migrations` 表追踪执行状态。
回滚脚本为同目录下的 `*.down.sql` 文件,需手动执行。
## 协议与 API
**WebSocket**`ws://localhost:8080/ws?token=<jwt>&conversation_id=<uuid>`
- 客户端消息:`query`(图像/音频 Base64, `config`, `interrupt`, `ping`
- 服务端消息:`connected`, `stt_result`, `llm_chunk`, `llm_done`, `tts_audio`, `error`, `pong`
- 心跳:客户端 30s ping服务端 60s 超时断连;重连:指数退避 1s→30s
- 实现:`CamTalkWebSocket` 单例(`frontend/src/lib/websocket.ts`),订阅模式,自动重连
- WebSocket 地址自动从当前页面协议/主机推导,也可通过 `VITE_WS_URL` 环境变量显式指定(如 `wss://api.example.com/ws`
**REST API**`/api/auth/*`(注册/登录/刷新/登出),`/api/conversations/*`CRUD + 消息分页),`/api/scenarios/*`(用户自定义情景 CRUD`/api/health`
**错误码**`INVALID_MESSAGE`, `SESSION_NOT_FOUND`, `RATE_LIMITED`, `IMAGE_TOO_LARGE`, `LLM_TIMEOUT`, `STT/TTS/LLM_ERROR`, `INVALID_TOKEN`
## 关键文件路径
**后端核心**
- `backend/cmd/server/main.go` — 入口依赖注入与启动流程存储→AI 服务→Graph→路由→Server
- `backend/internal/eino/` — Eino Graph 编排层graph.go 构建、adapter.go 适配、callback.go 推送、state.go 状态、nodes_*.go 各节点实现)
- `backend/internal/session/tiered.go` — 三级会话存储TieredManager
- `backend/internal/store/` — 持久化层Repository 接口 + PG 实现 + Redis 缓存装饰器)
- Repository 模式:接口定义在 `user.go`/`session.go`/`message.go`PG 实现在 `*_pg.go`Redis 缓存装饰器在 `cached_user.go`
- `backend/internal/ws/handler.go` — WebSocket 连接管理(升级→认证→收发循环→清理)
- `backend/internal/ai/` — AI 服务抽象层llm/stt/tts 各子目录,统一 `Service` 接口)
- `backend/internal/auth/` — JWT/bcrypt/中间件
- `backend/internal/ratelimit/` — 令牌桶限流(内存/Redis 两种后端)
- `backend/migrations/` — 嵌入式 SQL 迁移文件embed.go + *.sql
**前端核心**
- `frontend/src/hooks/useVisionSession.ts` — 核心会话 Hook~500 行,编排整个采集→发送→接收→播放流程)
- `frontend/src/lib/websocket.ts` — WebSocket 客户端单例(心跳/重连/订阅模式)
- `frontend/src/lib/auth.tsx` — AuthProviderJWT 自动刷新 + React Context
- `frontend/src/lib/api.ts` — REST 客户端401 拦截 + token 刷新)
- `frontend/src/lib/ttsPlayer.ts` — 流式 TTS 音频播放队列
- `frontend/src/lib/i18n/` — 国际化zh-CN / en-US / ja-JP
- `frontend/src/components/` — UI 组件LandingPage/CameraManager/MicManager/WebSocketManager/ChatPanel/SessionSidebar/ConfigPanel/VideoPreview 等)
- `frontend/vite.config.ts` — VAD 模型文件自动复制 + ONNX WASM MIME 处理 + 代理配置
## 编码规范
- **Go**:标准规范,`context.Context` 超时控制,`sync.RWMutex` 并发保护,`json:"snake_case"` 标签,编译期接口检查 `var _ Interface = (*Impl)(nil)`
- **TypeScript**严格模式接口定义数据模型WebSocket 消息用可辨识联合类型(`type` 字段区分)
- **存储层模式**Repository 接口 + PostgreSQL 实现 + Redis 缓存装饰器(`CachedUserRepository` 包装模式)
- **CORS**:禁止后端代码/配置文件配置 CORS统一由代理层处理开发环境 Vite proxy生产环境 Nginx
- **提交信息**Conventional Commits中文描述`feat: 添加 WebSocket 心跳`
- **禁止自动 push**:除非用户明确要求
- **文档优先**:开发前先读 `docs/` 设计文档,代码与文档不一致时优先更新文档