diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..9946d37 Binary files /dev/null and b/.DS_Store differ diff --git a/.gitea/workflows/web-deploy.yml b/.gitea/workflows/web-deploy.yml new file mode 100644 index 0000000..54f5536 --- /dev/null +++ b/.gitea/workflows/web-deploy.yml @@ -0,0 +1,44 @@ +name: Web Console Deploy (Vue 3 + Vite) +on: + push: + branches: + - main + paths: + - 'web/**' + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: 获取代码 + uses: actions/checkout@v4 + + - name: 安装 Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + cache-dependency-path: web/package-lock.json + + - name: 安装依赖并打包 + run: | + cd web + npm install + npm run build + + - name: 准备部署文件夹 + run: | + mkdir -p deploy_web + cp -r web/dist/* deploy_web/ + + - name: 部署静态文件到服务器 + uses: up9cloud/action-rsync@master + env: + USER: root + HOST: 144.24.60.0 + KEY: ${{secrets.USAARMLOGIN_SSH_KEY}} + ARGS: -avz --delete + SSH_ARGS: "-p 22 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" + SOURCE: ./deploy_web/ + TARGET: /var/admin/InsightReply/web + VERBOSE: true diff --git a/README.md b/README.md new file mode 100644 index 0000000..4c60697 --- /dev/null +++ b/README.md @@ -0,0 +1,112 @@ +# InsightReply 🚀 + +InsightReply 是一款专为独立开发者与数字游民设计的 **AI 驱动 X (Twitter) 自动化营销套件**。 +它通过高可用爬虫监控社媒热点,利用大语言模型(如 Gemini、OpenAI)提取互动风格,并自动在浏览器拓展层或管理后台生成极具转化率的爆款回复。 + +--- + +## 🗂️ 核心架构 + +InsightReply 采用现代化解耦的三端架构: + +1. **`/server` (后端主脑)** + - 核心语言:Golang 1.22 + GORM + Chi Router + - 数据库:PostgreSQL 14+ + - 功能模块:Nitter 高可用爬虫引擎、多模态 AI 接入层、策略派发与遥测统计引擎。 +2. **`/web` (SaaS 管理控制台)** + - 核心选型:Vue 3 + Vite + Tailwind 玻璃态美学 + - 功能模块:数据指标大盘、策略雷达与组合词配置、生成表现记录仪表板。 +3. **`/extension` (Chrome 浏览器助手)** + - 核心选型:CRXJS + Vue 3 + - 功能模块:侵入 X 原生界面,一键触发 AI 分析、克隆高赞评论语言风格。 + +--- + +## 🛠️ 本地开发指南 (Local Development) + +### 1. 启动 PostgreSQL 数据库 + +### 2. 配置与启动后端 (Go Server) +```bash +cd server + +# 复制环境变量模板并填入真实的 Key (特别是数据库与大模型 Key) +cp .env.example .env + +# 获取依赖并运行 +go mod tidy +go run cmd/server/main.go +# 默认后端将运行在 http://localhost:8080 +``` + +### 3. 配置与启动 Web 后台控制台 (Vue) +```bash +cd web +npm install + +# 确保 web/.env 中的 VITE_API_BASE_URL=http://localhost:8080/api/v1 +# (本地环境直连,已配置完成) +npm run dev +# 访问 http://localhost:5173 +``` + +### 4. 配置与编译 Chrome 扩展 (Extension) +```bash +cd extension +npm install + +# 确保 extension/.env 中的 VITE_API_BASE_URL=http://localhost:8080/api/v1 +npm run dev +``` +打开 Chrome -> `chrome://extensions/` -> 开启「开发者模式」 -> 点击「加载已解压的扩展程序」 -> 选择 `extension/dist` 目录进入调试。 + +--- + +## 🚀 生产部署指南 (Production Deployment) + +本系统采用原生 **Docker Compose 后端 + 本地 Caddy 高性能网关反代 + 自动化 Gitea Actions CI/CD**。 + +### 0. 准备与环境变量隔离 +1. **对于 `/web`**:生产环境已自动配置为相对路径:`VITE_API_BASE_URL=/api/v1`。无需变动。 +2. **对于 `/extension`**:修改 `extension/.env.production`,写入**你服务器真实的 Caddy HTTPS 域名绝对路径**: +```env +# extension/.env.production +VITE_API_BASE_URL=https://insight.buildapp.eu.org/api/v1 +``` + +### 1. 服务器环境准备 +服务器需提前安装 `docker`, `docker-compose`, 与 `caddy`。 + +### 2. 部署后端 Docker (包含日志持久化映射) +在服务器的 `/var/admin/InsightReply/server` 目录下放置你真实的 `.env` 配置文件。随后执行启动指令,后端将在 Docker 隔离网内暴露出 `8009` 端口供本地宿主机 Caddy 本地调用。 + +```bash +cd /var/admin/InsightReply/server +docker-compose up -d --build +``` +> 此时应用的全局运行日志将自动映射并写入由于宿主机的 `/root/logs/InsightReply.log` 内以供探查。 + +### 3. Caddyfile 反向代理与 SSL 自动签发 +在宿主机中编辑 `/etc/caddy/Caddyfile`,配置以下动静分离策略: + +```caddyfile +# 将此处替换为您的真实商用域名 +insight.buildapp.eu.org { + + # [后端路由] 代理所有 API 请求到 Go Docker 的透传端口 + handle /api/* { + reverse_proxy insight.buildapp.eu.org + } + + # [前端路由] 静态托管来自 CI/CD 发行的 Vue 3 制品,并支持 SPA 默认寻址 + handle { + root * /var/admin/InsightReply/web + try_files {path} {path}/ /index.html + file_server + } +} +``` +配置完成后使用 `caddy reload` 重载规则并等待几十秒完成 Let's Encrypt 等机构的安全加密证书签发。 + +### 4. 配置自动化 CI/CD +所有的部署流水线配置均存放在 `.gitea/workflows` 目录下,支持推送 `main` 分支时利用 Rsync 执行秒级增量部署及无缝重启。 diff --git a/docs/API.md b/docs/API.md new file mode 100644 index 0000000..d28522f --- /dev/null +++ b/docs/API.md @@ -0,0 +1,506 @@ +# InsightReply API 接口文档 + +> **Base URL**:`https:///api/v1` +> **认证方式**:Bearer Token (JWT) +> **内容类型**:`application/json` + +--- + +## 通用响应格式 + +### 成功响应 +```json +{ + "code": 200, + "message": "success", + "data": { ... } +} +``` + +### 错误响应 +```json +{ + "code": 4001, + "message": "具体的错误描述", + "data": null +} +``` + +### HTTP Status Code 规范 + +| HTTP Status | 使用场景 | +|-------------|---------| +| `200 OK` | 正常响应 | +| `201 Created` | 资源创建成功 | +| `400 Bad Request` | 请求参数错误 (对应 code 4xxx) | +| `401 Unauthorized` | 未认证或 Token 过期 | +| `403 Forbidden` | 权限不足(如 Free 用户访问 Pro 功能) | +| `429 Too Many Requests` | 触发 Rate Limit | +| `500 Internal Server Error` | 服务端异常 (对应 code 5xxx) | +| `502 Bad Gateway` | 上游服务(如 LLM)不可用 | + +### 业务错误码速查表 + +| Code | 含义 | +|------|------| +| `4001` | 请求体解析失败 / 参数缺失 | +| `4002` | 必填字段为空 | +| `4003` | 权限不足(Tier 限制) | +| `4004` | 资源不存在 | +| `4005` | Rate Limit 超限 | +| `4010` | 未认证 / Token 无效 | +| `4011` | Token 已过期 | +| `5001` | 数据库读写错误 | +| `5002` | LLM 调用失败 | +| `5003` | 外部服务超时 | + +--- + +## 认证相关 + +### POST `/auth/register` — 用户注册 + +**请求体**: +```json +{ + "email": "user@example.com", + "password": "securePassword123" +} +``` + +**成功响应**: +```json +{ + "code": 201, + "message": "success", + "data": { + "user_id": "uuid-xxxx", + "access_token": "eyJhbG...", + "refresh_token": "eyJhbG..." + } +} +``` + +--- + +### POST `/auth/login` — 用户登录 + +**请求体**: +```json +{ + "email": "user@example.com", + "password": "securePassword123" +} +``` + +**成功响应**: +```json +{ + "code": 200, + "message": "success", + "data": { + "access_token": "eyJhbG...", + "refresh_token": "eyJhbG...", + "user": { + "id": "uuid-xxxx", + "email": "user@example.com", + "subscription_tier": "Free", + "identity_label": "独立开发者" + } + } +} +``` + +--- + +### POST `/auth/refresh` — 刷新 Token + +**请求体**: +```json +{ + "refresh_token": "eyJhbG..." +} +``` + +--- + +## AI 评论生成 (需认证) + +### POST `/ai/generate` — 生成评论 + +**请求头**: +``` +Authorization: Bearer +``` + +**请求体**: +```json +{ + "tweet_content": "AI agents are going to replace 80% of SaaS tools in the next 2 years.", + "strategy": "all", + "identity": "AI 创始人", + "language": "en", + "max_length": 280 +} +``` + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| `tweet_content` | string | ✅ | 目标推文原文 | +| `strategy` | string | ❌ | `cognitive_upgrade` / `contrarian` / `data_supplement` / `empathy` / `founder_exp` / `all`(默认 `all`) | +| `identity` | string | ❌ | 用户身份标签,默认使用用户 Profile 中的设置 | +| `language` | string | ❌ | 输出语言,`en` / `zh` / `auto`(默认 `auto`,跟随原推文语言) | +| `max_length` | int | ❌ | 最大字符数,默认 280 | + +**成功响应**: +```json +{ + "code": 200, + "message": "success", + "data": { + "tweet_id": "optional-if-known", + "replies": [ + { + "strategy": "cognitive_upgrade", + "label": "认知升级型", + "candidates": [ + "Most people are thinking about this wrong. The real shift isn't agents replacing SaaS — it's agents making SaaS invisible. The UI layer vanishes, but the data layer matters more than ever.", + "Hot take: agents won't replace SaaS. They'll rebuild it. Every workflow tool becomes an agent orchestrator. The winners know this already." + ] + }, + { + "strategy": "contrarian", + "label": "反向观点型", + "candidates": ["..."] + } + ], + "usage": { + "prompt_tokens": 320, + "completion_tokens": 580, + "total_tokens": 900 + } + } +} +``` + +--- + +## 用户配置 (需认证) + +### GET `/users/me` — 获取当前用户信息 + +**成功响应**: +```json +{ + "code": 200, + "message": "success", + "data": { + "id": "uuid-xxxx", + "email": "user@example.com", + "subscription_tier": "Pro", + "identity_label": "AI 创始人", + "daily_usage": { "generate": 5, "limit": -1 }, + "created_at": "2026-02-01T00:00:00Z" + } +} +``` + +### PUT `/users/me/preferences` — 更新用户偏好 + +**请求体 (可增量更新)**: +```json +{ + "identity_label": "SaaS Builder", + "language_preference": "zh" +} +``` + +--- + +## 监控配置 (需认证) + +### POST `/monitors/keywords` — 添加关键词监控 + +**请求体**: +```json +{ + "keyword": "AI agent" +} +``` + +### GET `/monitors/keywords` — 获取关键词列表 + +### DELETE `/monitors/keywords/{id}` — 删除关键词 + +### POST `/monitors/accounts` — 添加账号监控 + +**请求体**: +```json +{ + "x_handle": "sama" +} +``` + +### GET `/monitors/accounts` — 获取监控账号列表 + +### DELETE `/monitors/accounts/{id}` — 删除监控账号 + +--- + +## 用户可配置系统 API (需认证) + +### GET `/users/me/product_profiles` — 获取用户产品档案 + +**成功响应**: +```json +{ + "code": 200, + "message": "success", + "data": { + "product_name": "InsightReply", + "tagline": "AI-powered audience engagement", + "domain": "SaaS", + "key_features": "[\"Multi-LLM\", \"Custom Strategies\"]", + "target_users": "Founders, Indie Hackers", + "product_url": "https://insightreply.example.com", + "competitors": "[\"ReplyGuy\", \"TweetHunter\"]", + "relevance_keywords": "[\"marketing\", \"twitter growth\"]", + "custom_context": "We focus on high-quality, non-spammy replies", + "default_llm_provider": "anthropic", + "default_llm_model": "claude-3-5-haiku-latest" + } +} +``` + +### PUT `/users/me/product_profiles` — 更新用户产品档案 + +**请求体**: +接受与 GET 响应相同的 JSON 字段结构。 + +--- + +### GET `/users/me/strategies` — 获取自定义策略列表 + +**成功响应**: +```json +{ + "code": 200, + "message": "success", + "data": [ + { + "id": "uuid-xxx", + "strategy_key": "funny", + "label": "幽默调侃型", + "icon": "🤣", + "description": "Make the reader laugh.", + "prompt_template": "Reply to this with a witty joke: {tweet_content}", + "few_shot_examples": "[]", + "sort_order": 1 + } + ] +} +``` + +### POST `/users/me/strategies` — 创建自定义策略 +**请求体** 接受与 GET 列表中单项内容相同的结构(无需提供 id)。 + +### DELETE `/users/me/strategies/{id}` — 删除自定义策略 + +--- + +### GET `/monitors/competitors` — 获取竞品监控列表 + +**成功响应**: +```json +{ + "code": 200, + "message": "success", + "data": [ + { + "id": "uuid-xxx", + "brand_name": "CompetitorA", + "x_handle": "@compa" + } + ] +} +``` + +### POST `/monitors/competitors` — 添加竞品监控 +**请求体**: +```json +{ + "brand_name": "CompetitorA", + "x_handle": "@compa" +} +``` + +### DELETE `/monitors/competitors/{id}` — 删除竞品监控 + +> 用户可定义自己正在推广的产品信息,系统会将其注入 Prompt,生成与产品领域高度关联的评论。 + +### GET `/users/me/product` — 获取产品档案 + +**成功响应**: +```json +{ + "code": 200, + "message": "success", + "data": { + "product_name": "SwiftBiu", + "tagline": "AI-powered short video creation tool", + "domain": "AI Video Creation", + "key_features": ["视频生成", "多语言配音", "AI 脚本"], + "target_users": "内容创作者, 独立开发者, 出海团队", + "product_url": "https://apps.apple.com/app/swiftbiu", + "competitors": ["CapCut", "Descript", "Opus Clip"], + "relevance_keywords": ["short video", "content creation", "AI dubbing", "video editing"], + "custom_context": "We focus on multi-language video creation for global creators.", + "default_llm_provider": "anthropic", + "default_llm_model": "claude-3-5-haiku-latest" + } +} +``` + +### PUT `/users/me/product` — 更新产品档案 + +**请求体**:(所有字段可选,只传需要更新的字段) +```json +{ + "product_name": "SwiftBiu", + "tagline": "AI-powered short video creation tool", + "domain": "AI Video Creation", + "key_features": ["视频生成", "多语言配音", "AI 脚本"], + "competitors": ["CapCut", "Descript"], + "relevance_keywords": ["short video", "content creation"], + "custom_context": "任意自定义的上下文信息,会被注入到生成 Prompt 中", + "default_llm_provider": "anthropic", + "default_llm_model": "claude-3-5-haiku-latest" // 支持前端列表选择,或用户手动输入自定义模型(如接入代理时的自有模型) +} +``` + +--- + +## 自定义策略 (需认证) + +> 除系统内置的 5 种策略外,用户可创建自己的评论策略模板。 + +### GET `/users/me/strategies` — 获取策略列表(含系统内置 + 用户自定义) + +**成功响应**: +```json +{ + "code": 200, + "message": "success", + "data": { + "builtin": [ + { "strategy_key": "cognitive_upgrade", "label": "认知升级型", "icon": "🧠" }, + { "strategy_key": "contrarian", "label": "反向观点型", "icon": "🔥" } + ], + "custom": [ + { + "id": "uuid-xxx", + "strategy_key": "builder_story", + "label": "创始人实战型", + "icon": "🚀", + "description": "以自身产品经验为论据,自然关联到我的产品", + "prompt_template": "用 {identity} 的身份,基于 {product_name} 的开发经验,对这条推文写一条有洞察力的评论...", + "few_shot_examples": ["We faced this exact problem building SwiftBiu..."] + } + ] + } +} +``` + +### POST `/users/me/strategies` — 创建自定义策略 + +**请求体**: +```json +{ + "strategy_key": "builder_story", + "label": "创始人实战型", + "icon": "🚀", + "description": "以自身产品经验为论据,自然关联到产品", + "prompt_template": "用 {identity} 的身份,基于 {product_name} 的开发经验...", + "few_shot_examples": [ + "We faced this exact problem building SwiftBiu. What worked for us was..." + ] +} +``` + +### PUT `/users/me/strategies/{id}` — 更新自定义策略 + +### DELETE `/users/me/strategies/{id}` — 删除自定义策略 + +--- + +## 竞品监控 (需认证) + +### POST `/monitors/competitors` — 添加竞品监控 + +**请求体**: +```json +{ + "brand_name": "CapCut", + "x_handle": "CapCut" +} +``` + +### GET `/monitors/competitors` — 获取竞品监控列表 + +### DELETE `/monitors/competitors/{id}` — 删除竞品监控 + +--- + +## 系统 (无需认证) + +### GET `/sys/config/llms` — 获取支持的 LLM 模型列表 + +> 用于前端渲染「重写 AI 引擎」的下拉菜单,由后端统一从环境变量 (`OPENAI_AVAILABLE_MODELS` 等) 下发。 + +**成功响应**: +```json +{ + "code": 200, + "message": "success", + "data": { + "providers": [ + { + "id": "openai", + "name": "OpenAI (或兼容接口)", + "models": ["gpt-4o", "gpt-4o-mini", "o1-mini"] + }, + { + "id": "anthropic", + "name": "Anthropic Claude", + "models": ["claude-3-5-sonnet-latest", "claude-3-5-haiku-latest"] + }, + { + "id": "deepseek", + "name": "DeepSeek", + "models": ["deepseek-chat", "deepseek-reasoner"] + }, + { + "id": "gemini", + "name": "Google Gemini", + "models": ["gemini-2.5-flash", "gemini-2.5-pro"] + } + ] + } +} +``` + +### GET `/health` — 健康检查 + +**成功响应**: +```json +{ + "code": 200, + "message": "ok", + "data": { + "status": "healthy", + "db": "connected", + "version": "1.0.0", + "uptime": "2h30m" + } +} +``` diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md new file mode 100644 index 0000000..bd27676 --- /dev/null +++ b/docs/ARCHITECTURE.md @@ -0,0 +1,189 @@ +# InsightReply 系统架构 (Architecture Overview) + +> 本文档描述 InsightReply 的整体技术架构、各组件职责与数据流。 + +--- + +## 一、架构全景图 + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ 用户浏览器 (Chrome / Edge) │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ X (Twitter) 页面 │ │ +│ │ ┌──────────────┐ ┌──────────────────────────────┐ │ │ +│ │ │ Content │ │ InsightReply Sidebar │ │ │ +│ │ │ Script │───▶│ (Shadow DOM 隔离) │ │ │ +│ │ │ - DOM 感知 │ │ - 策略选择 │ │ │ +│ │ │ - 按钮注入 │ │ - 评论展示 │ │ │ +│ │ │ - 数据提取 │ │ - 一键复制 │ │ │ +│ │ └──────────────┘ └──────────┬───────────────────┘ │ │ +│ └───────────────────────────────────┼─────────────────────┘ │ +│ │ chrome.runtime │ +│ ┌───────────────────────────────────┼─────────────────────┐ │ +│ │ Background Service Worker │ │ +│ │ - 消息中转 │ │ +│ │ - JWT Token 管理 │ │ +│ │ - API 请求代理 │ │ +│ └───────────────────────────────────┼─────────────────────┘ │ +└──────────────────────────────────────┼──────────────────────────┘ + │ HTTPS + ▼ +┌──────────────────────────────────────────────────────────────────┐ +│ Nginx / Caddy (TLS 终结) │ +└──────────────────────────────────────┬───────────────────────────┘ + │ + ▼ +┌──────────────────────────────────────────────────────────────────┐ +│ Go 后端服务 (Docker Container) │ +│ │ +│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │ +│ │ Handler │─▶│ Service │─▶│Repository│─▶│ PostgreSQL │ │ +│ │ (HTTP) │ │ (BizLogic│ │ (GORM) │ │ (Tailscale) │ │ +│ └──────────┘ └────┬─────┘ └──────────┘ └──────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌──────────────┐ │ +│ │ LLM Gateway │──▶ OpenAI / Claude / DeepSeek │ +│ │ (Timeout + │ │ +│ │ Breaker + │ │ +│ │ Retry) │ │ +│ └──────────────┘ │ +│ │ +│ ┌──────────────────────────────────────────────────────────┐ │ +│ │ Radar Scheduler (定时任务) │ │ +│ │ - Asynq (Redis Queue) │ │ +│ │ - Nitter Scraper │ │ +│ │ - 热度计算引擎 │ │ +│ └──────────────────────────────────────────────────────────┘ │ +└──────────────────────────────────────────────────────────────────┘ +``` + +--- + +## 二、分层架构 (Clean Architecture) + +``` +cmd/server/main.go ← 入口:配置加载、依赖注入、路由注册 +│ +├── internal/handler/ ← 表现层:HTTP 请求解析 → 调用 Service → 返回 JSON +│ ├── ai_handler.go +│ ├── user_handler.go +│ └── common.go ← 统一 Response 工具函数 +│ +├── internal/service/ ← 业务层:核心逻辑(LLM 调用、热度计算、权限校验) +│ ├── ai_service.go +│ └── user_service.go +│ +├── internal/repository/ ← 数据层:封装所有 SQL / GORM 操作 +│ └── user_repository.go +│ +├── internal/model/ ← 数据模型:Go struct 定义 +│ └── user.go +│ +├── config/ ← 配置读取(环境变量 → 结构体) +├── pkg/ ← 跨模块共享工具包 +└── prompts/ ← Prompt 模板文件 (规划中) +``` + +**调用链规则**:`Handler → Service → Repository`,严禁跨层调用。 + +--- + +## 三、数据流 + +### 3.1 核心链路:用户生成评论 + +```mermaid +sequenceDiagram + participant U as 用户 (X 页面) + participant CS as Content Script + participant BG as Background SW + participant API as Go 后端 + participant LLM as OpenAI + + U->>CS: 点击 Insight 按钮 + CS->>CS: 提取推文 DOM 数据 + CS->>BG: chrome.runtime.sendMessage + BG->>API: POST /ai/generate (带 JWT) + API->>API: 验证 Token + Rate Limit + API->>LLM: ChatCompletion (含 Prompt) + LLM-->>API: 生成结果 + API-->>BG: JSON 响应 (10 条候选) + BG-->>CS: sendResponse + CS->>U: Sidebar 展示评论 + U->>U: 选择 → 一键复制 → 粘贴发布 +``` + +### 3.2 雷达链路:后台监控推文 *(规划中)* + +```mermaid +sequenceDiagram + participant SCH as Scheduler + participant Q as Asynq (Redis) + participant SC as Scraper Worker + participant NIT as Nitter 实例 + participant DB as PostgreSQL + + SCH->>Q: 定时投放抓取任务 + Q->>SC: 消费任务 + SC->>SC: Jitter 延迟 (1-5s) + SC->>NIT: HTTP GET (指纹轮换) + alt 正常响应 + NIT-->>SC: HTML + SC->>SC: goquery 解析 + SC->>DB: Batch UPSERT tweets + SC->>DB: 计算 heat_score + else 429/503 + SC->>SC: 触发 Circuit Breaker + SC->>Q: 指数退避后重新入队 + end +``` + +--- + +## 四、部署架构 + +``` + Internet + │ + ┌────────┴────────┐ + │ Nginx / Caddy │ ← TLS + 反代 → :8080 + └────────┬────────┘ + │ + ┌──────────────────┼──────────────────┐ + │ Oracle ARM VPS │ + │ 144.24.60.0 │ + │ │ + │ ┌────────────────────────────┐ │ + │ │ Docker │ │ + │ │ ├── insight-reply-server │ │ + │ │ └── (未来: redis) │ │ + │ └────────────────────────────┘ │ + │ │ + └──────────────────┼──────────────────┘ + │ Tailscale VPN + ▼ + ┌────────────────┐ + │ PostgreSQL │ + │ 100.64.0.5 │ + └────────────────┘ +``` + +--- + +## 五、技术栈一览 + +| 层级 | 技术 | 版本 | +|------|------|------| +| **前端插件** | Vue 3 + Composition API | 3.5 | +| **样式** | Tailwind CSS | v4 | +| **打包** | Vite + CRXJS | 7.x | +| **后端** | Go (chi router) | 1.24 | +| **ORM** | GORM + pgx | 1.31 | +| **数据库** | PostgreSQL | 15+ | +| **LLM** | OpenAI (go-openai) | GPT-4o Mini | +| **任务队列** *(规划)* | Asynq (Redis) | - | +| **容器** | Docker + Docker Compose | 24.x | +| **CI/CD** | Gitea Actions | - | +| **VPN** | Tailscale | - | diff --git a/docs/DEPLOYMENT.md b/docs/DEPLOYMENT.md index f42839f..f96b80a 100644 --- a/docs/DEPLOYMENT.md +++ b/docs/DEPLOYMENT.md @@ -14,15 +14,21 @@ **触发条件**:当推送代码到 `main` 分支,且 `server/**` 目录有变更时触发。 **执行流程**: -1. **获取代码并安装 Go 1.22 环境**。 +1. **获取代码并安装 Go 1.24 环境**。 2. **交叉编译**:在 Runner 上编译出适用于 Linux ARM64 的可执行文件 `server_bin`。 3. **准备部署包**:将可执行文件、`Dockerfile`、`docker-compose.yml` 收集到部署文件夹。 -4. **Rsync 同步**:将文件同步到生产服务器 (`144.24.60.0`) 的 `/var/admin/InsightReply/server/` 目录下。 +4. **Rsync 同步**:将文件同步到生产服务器的 `/var/admin/InsightReply/server/` 目录下。 5. **平滑重启服务**:通过 SSH 远程执行 `docker-compose up -d --build`,实现不宕机更新。 +> [!WARNING] +> **Rsync 安全提醒**:`--delete` 参数会删除目标目录中不在源端的文件。务必配合 `--exclude` 排除 `.env` 和日志文件: +> ```yaml +> ARGS: -avz --delete --exclude '.env' --exclude '*.log' +> ``` + **服务器端准备工作**: * 必须在目标服务器上安装 Docker 和 Docker Compose。 -* (可选)如果在服务端需要提供环境变量给容器,请在 `/var/admin/InsightReply/server/` 目录下创建一个 `.env` 文件。 +* 在 `/var/admin/InsightReply/server/` 目录下创建 `.env` 文件(参考 `server/.env.example`)。 --- @@ -34,20 +40,123 @@ 1. **获取代码并安装 Node.js 20 环境**。 2. **依赖与构建**:执行 `npm install` 与 `npm run build`,编译 Vite/Vue 产物。 3. **打包产物**:将生成的 `dist` 目录打包为 `insight-reply-extension.zip`。 -4. **Gitea Artifacts**:将生成的 zip 包上传为当前构建的 Artifacts。 - *(后续需要上架 Chrome Web Store 时,可在此流程增加 API 上传步骤。)* +4. **Gitea Release**:将生成的 zip 包发布到 Gitea Release。 + +> [!TIP] +> 后续需要上架 Chrome Web Store 时,可在此流程增加 Chrome Web Store API 上传步骤。 --- -### 3. 多环境与全局发布 (规划中) -随着产品演进,当需要打 Tag 发版(如发布 `v1.0.0`)时,我们可以添加一个新的工作流: -**触发条件**:当推送符合 `v*` 规则的 Tag 时触发。 -**预期行为**:利用 Gitea Release 机制,自动附带当次的前后端编译产物,作为固定资产留存。 +### 3. 版本管理与发布策略 + +| 发布类型 | 触发条件 | 行为 | +|---------|---------|------| +| **持续部署** | `push main` + 路径过滤 | 自动部署到生产/构建扩展 | +| **正式发版** *(规划中)* | 推送 `v*` Tag | 创建 Gitea Release + 编译产物附件 | + +**推荐版本号规则**: +- 后端:`v1.0.0`、`v1.1.0`、`v1.1.1`(语义化版本) +- 扩展:同步跟随后端大版本,`manifest.json` 中的 `version` 对齐 + +--- + +## 🔧 Docker 运维规范 + +### 容器配置要点 + +```yaml +# docker-compose.yml 推荐配置 +services: + insight-reply-server: + build: . + container_name: insight-reply-server + restart: always + ports: + - "8080:8080" + env_file: + - .env + healthcheck: + test: ["CMD", "wget", "--spider", "-q", "http://localhost:8080/api/v1/health"] + interval: 30s + timeout: 5s + retries: 3 + start_period: 10s + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + networks: + - insight_network +``` + +> [!IMPORTANT] +> **Healthcheck 说明**:当健康检查连续失败 3 次后,Docker 会将容器标记为 `unhealthy`。配合 `restart: always` 可自动恢复。 + +### Dockerfile 优化建议 + +```dockerfile +FROM alpine:latest + +RUN apk --no-cache add ca-certificates tzdata wget + +ENV TZ=Asia/Shanghai + +WORKDIR /app + +COPY server_bin . +RUN chmod +x server_bin + +EXPOSE 8080 + +HEALTHCHECK --interval=30s --timeout=5s \ + CMD wget --spider -q http://localhost:8080/api/v1/health || exit 1 + +CMD ["./server_bin"] +``` + +--- + +## 🌐 HTTPS 配置 (反向代理) + +生产环境必须使用 HTTPS。推荐使用 **Caddy** 自动签发 Let's Encrypt 证书: + +``` +# Caddyfile 示例 +api.insightreply.com { + reverse_proxy localhost:8080 +} +``` + +或使用 Nginx: +```nginx +server { + listen 443 ssl; + server_name api.insightreply.com; + + ssl_certificate /etc/ssl/certs/cert.pem; + ssl_certificate_key /etc/ssl/private/key.pem; + + location / { + proxy_pass http://127.0.0.1:8080; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} +``` + +--- ## 🔑 凭证管理 (Secrets) 要使自动化部署正常运行,请在此 Gitea 仓库的 `Settings -> Actions -> Secrets` 中配置以下环境变量: -* `USAARMLOGIN_SSH_KEY`: 用于连接到部署目标服务器 (`144.24.60.0`) 的 SSH 私钥。 + +| Secret 名称 | 用途 | +|-------------|------| +| `USAARMLOGIN_SSH_KEY` | SSH 私钥,用于连接部署目标服务器 | +| `GITEA_TOKEN` | Gitea API Token,用于发布 Release | --- @@ -64,6 +173,26 @@ docker-compose ps # 查看应用最新日志 docker-compose logs -f insight-reply-server +# 查看最近 100 行日志 +docker-compose logs --tail 100 insight-reply-server + # 重启应用服务 docker-compose restart insight-reply-server + +# 强制重新构建并启动 +docker-compose up -d --build + +# 进入容器内部排查 +docker exec -it insight-reply-server sh ``` + +--- + +## 📊 监控与告警 *(规划中)* + +| 维度 | 方案 | +|------|------| +| **应用日志** | Docker JSON 日志 + 未来接入 Loki 或 Datadog | +| **健康检查** | Docker healthcheck + Uptime Kuma | +| **APM** | 后续考虑接入 Sentry Go SDK | +| **成本监控** | `api_usage_logs` 表追踪 Token 消耗 | diff --git a/docs/DEVELOPMENT_PLAN.md b/docs/DEVELOPMENT_PLAN.md index d5ee2e9..1ca54df 100644 --- a/docs/DEVELOPMENT_PLAN.md +++ b/docs/DEVELOPMENT_PLAN.md @@ -1,31 +1,67 @@ # InsightReply 开发任务分解版 -基于 PRD(v1.0),我们将开发任务划分为以下核心模块与阶段,适合在 Notion/Jira 等任务管理系统中作为 Epic/Story 录入。 +基于 PRD(v1.0)与产品功能路线图,我们将开发任务划分为以下核心模块与阶段,适合在 Notion/Jira 等任务管理系统中作为 Epic/Story 录入。 + +> 📌 功能完善度的详细分析与竞品对比见 → [`PRODUCT_ROADMAP.md`](./PRODUCT_ROADMAP.md) + +> **状态标签说明**:🟢 已完成 | 🟡 进行中 | ⚪ 未开始 --- ## 🏁 第一阶段:核心 MVP(预计耗时 2-4 周) -**核心目标**:跑通“获取推文 -> 生成多策略评论 -> 一键复制”的核心业务流。 +**核心目标**:跑通"获取推文 -> 生成多策略评论 -> 一键复制"的核心业务流。 ### Epic 1: 项目基础设施搭建 -- [ ] **前端框架初始化**:搭建浏览器插件(Chrome Extension)基础模版,使用 Vue 3 + Tailwind CSS,并配置打包工具(如 Plasmo 或 Vite)。 -- [ ] **后端架构选型与初始化**:创建 Go (Golang) 后端服务基础框架。 -- [ ] **数据库初始化**:设计并创建基础表结构(Users, MonitoredKeywords, Tweets, GeneratedReplies)。 -- [ ] **LLM API 接入**:申请并联通 OpenAI (GPT-4) 或其他大模型 API,建立接口通信链路。 +- [x] 🟢 **前端框架初始化**:搭建浏览器插件(Chrome Extension)基础模版,使用 Vue 3 + Tailwind CSS v4,配置 Vite + CRXJS 打包工具。 +- [x] 🟢 **后端架构选型与初始化**:创建 Go (Golang) 后端服务基础框架(chi 路由 + GORM + Clean Architecture 分层)。 +- [x] 🟢 **数据库初始化**:设计并创建基础表结构(Users, MonitoredKeywords, Tweets, GeneratedReplies)。 +- [x] 🟢 **LLM API 接入**:联通 OpenAI GPT-4o Mini API,建立接口通信链路。 +- [x] 🟢 **CI/CD 流水线**:搭建 Gitea Actions 自动部署(后端 Docker + 前端打包发布)。 ### Epic 2: 浏览器插件核心开发 -- [ ] **UI 侧边栏/弹窗实现**:在 X(Twitter)页面注入前端组件,展示 InsightReply 面板。 -- [ ] **推文内容提取**:获取当前浏览中的相关推文文本内容及上下文。 -- [ ] **手动生成交互**:用户手动点击“生成”,调用后端接口返回评论建议。 -- [ ] **结果呈现与复制**:展示返回的备选评论,支持“一键复制”操作。 +- [x] 🟢 **UI 侧边栏实现**:在 X(Twitter)页面注入前端组件(Shadow DOM 隔离),展示 InsightReply 面板。 +- [x] 🟢 **推文内容提取**:Content Script 使用 MutationObserver 监听 DOM,提取推文文本、作者、互动数据。 +- [x] 🟢 **手动生成交互**:用户点击"Insight"按钮 → Background → Go API → LLM → 返回结果。 +- [x] 🟢 **结果呈现与复制**:展示备选评论,支持一键复制操作。 ### Epic 3: 评论生成引擎(基础版) -- [ ] **提示词(Prompt)工程调优**:编写可稳定生成 5 种不同属性(认知升级型、反向观点型、数据补充型、共鸣型、创始人经验型)的底层提示词。 -- [ ] **身份预设支持**:支持基础的用户预设身份(如 AI 创始人/SaaS Builder),与推文内容一同传入 LLM。 +- [x] 🟢 **基础 Prompt 工程**:实现单条评论生成(支持策略与身份参数传入)。 +- [ ] ⚪ **多策略批量生成**:一次生成 5 种策略(认知升级型、反向观点型、数据补充型、共鸣型、创始人经验型)× 2 条备选。 +- [ ] ⚪ **Prompt 深度优化**:引入 Hook+Position+Insight+Brevity 结构公式、Few-shot 示例、语言控制、Token 消耗追踪。 +- [ ] ⚪ **Prompt 模板化管理**:建立 `prompts/` 目录,每个策略独立模板文件。 -### Epic 4: 基础关键词监控 -- [ ] **监控规则配置**:前端/后台页面支持用户录入最初的几个核心关键词。 -- [ ] **定时拉取脚本**:服务端定时通过 API/规则 拉取匹配关键词的相关推文缓存于数据库。 +### Epic 4: 高可用后台监控系统 (Nitter Scraping) +- [x] ✅ **监控规则配置**:提供 API 允许用户录入核心监控关键词与目标账号。 +- [x] ✅ **高可用采集引擎 (Scraper)**:基于 `goquery` 解析自建 Nitter (`https://x.beenglish.eu.org/`) 的 DOM 获取数据。 +- [x] ✅ **防封禁反风控 (Anti-Ban)**:实现请求抖动 (Jitter)、User-Agent 轮换与隔离会话 (Session Isolation)。 +- [x] ✅ **熔断降级机制 (Circuit Breaker)**:在 Nitter 被限流报 429/503 时自动暂停抓取,触发指数退避 (Exponential Backoff)。 + +### Epic 11: 工程基础设施加固 *(新增)* +- [x] ✅ **JWT 认证中间件**:为 `/api/v1` 路由添加 Bearer Token 认证,绑定用户身份。 +- [x] ✅ **Rate Limiting**:按用户 subscription_tier 分级限流(Free: 10次/天, Pro: 无限)。 +- [x] ✅ **CORS 配置**:添加 `go-chi/cors` 中间件,白名单 Chrome 扩展 Origin。 +- [x] ✅ **Multi-LLM 路由与韧性设计**:支持 OpenAI / Anthropic / DeepSeek / Gemini 多模型动态路由,为调用添加 Timeout(30s)、Circuit Breaker(`sony/gobreaker`)、指数退避重试。 +- [x] ✅ **Graceful Shutdown**:使用 `signal.NotifyContext` 实现平滑关停。 +- [x] ✅ **健康检查**:添加 `/health` 端点 + Docker healthcheck。 +- [x] ✅ **DB Migration 机制**:引入 `golang-migrate/migrate`,建立 `migrations/` 目录。 +- [x] ✅ **单元测试骨架**:覆盖 Handler/Service 层核心路径 + CI 自动运行测试。 +- [x] ✅ **环境变量规范化**:API 地址、LLM Provider 等全部走环境变量或配置文件。 + +### Epic 12: 用户体验与功能完善 *(新增 — 来自产品评审)* +- [x] ✅ **多条备选评论 (P0)**:单次返回 3 种策略 × 1 条 = 3 条备选,Sidebar 改为卡片列表式展示;记录用户策略偏好。 +- [x] ✅ **用户 Onboarding 流程 (P0)**:首次使用 3 步引导 → 身份标签 / 偏好语言 / 风格倾向 → 存入 `chrome.storage.sync` + 后端用户表。 +- [x] ✅ **前端热度标签 (P1)**:Content Script 基于 DOM 互动数注入 🔥 Trending / ⚡ Rising 徽章,帮用户判断评论时机。 +- [x] ✅ **评论历史 Tab (P1)**:扩展 Popup 新增 History Tab,本地存储最近 50 条记录,支持搜索和策略筛选。 +- [x] ✅ **Quote Tweet 生成 (P1)**:新增第 6 种策略「引用评论型」,生成可独立发帖的引用转发内容。 +- [x] ✅ **错误边界与离线处理**:API 失败时显示重试按钮 + 明确错误提示,后端不可达时给出离线提示。 + +### Epic 15: 用户可配置系统 *(新增 — 可扩展性设计)* +> 所有与用户场景相关的能力均通过用户自定义设置实现,系统不硬编码任何特定产品/领域/策略,确保可扩展性。 +- [x] ✅ **产品档案 (Product Profile)**:用户可配置产品名、领域、功能、竞品、相关关键词等;系统自动注入 Prompt 上下文。 +- [x] ✅ **自定义策略模板 (Custom Strategies)**:除内置 5 种策略外,用户可创建私有策略(含 Prompt 模板 + Few-shot 示例);前端 Sidebar 动态合并展示。 +- [x] ✅ **竞品监控 (Competitor Monitoring)**:用户添加竞品品牌名/X 账号,雷达自动监控竞品讨论推文。 +- [x] ✅ **推文相关性评分 (Relevance Scoring)**:Content Script 基于产品档案中的 `relevance_keywords` 做前端轻量匹配,高相关推文旁标注 🎯 标签。 +- [x] ✅ **Profile 优化提醒**:用户复制评论后弹出 Tip,提醒确保 X Bio 和 Pin Tweet 包含产品信息。 --- @@ -33,18 +69,25 @@ **核心目标**:实现对账号的定点监控、推文的热度初步计算,并让评论策略更完善。 ### Epic 5: 账号与组合监控 -- [ ] **账号监控功能**:实现对重点账号的定点监控配置(支持实时抓取)。 -- [ ] **多规则组合过滤**:支持指定账号 + 关键词、AND/OR 多条件的交叉过滤搜索。 +- [x] ✅ **账号监控功能**:实现对重点账号的定点监控配置(支持实时抓取)。 +- [x] ✅ **多规则组合过滤**:支持指定账号 + 关键词、AND/OR 多条件的交叉过滤搜索 API。 -### Epic 6: 热度评分系统 -- [ ] **热度指标采集**:获取推文的点赞、转发、评论数量的变化速率。 -- [ ] **热度公式落地**:实现 `热度 = 点赞增长率*0.4 + 转发增长率*0.3 + 评论增长率*0.3` 算法。 -- [ ] **增强因子计算**:接入账号蓝V标识识别、粉丝数权重计算和热搜趋势匹配。 -- [ ] **阈值提醒机制**:当分析出的推文热度超过设定阈值,出现在插件的“高潜爆款候选列”中。 +### Epic 6: 数据飞轮与快照引擎 (Data Flywheel) +- [x] ✅ **快照入库 (UPSERT 逻辑)**:抓取的推文以 `x_tweet_id` 为唯一键存入 `tweets` 表,更新转评赞数据。 +- [x] ✅ **动态热度算法 (Heat Score)**:计算两次抓取的增量(Delta Likes/Retweets/Replies),运用公式计算当前热度分 `heat_score`。 +- [x] ✅ **动态智能抓取频率 (Smart Crawling)**:热度飙升的推文升至 `high` 队列,长时间沉默推文降级至 `low` 队列。 +- [x] ✅ **高潜商机面板 (Hot Opportunities)**:提供 `GET /tweets/hot` 并在插件内实现商机大赏面板。 -### Epic 7: Web 端管理后台 -- [ ] **Web 界面开发**:Nuxt.js / Vue 3 等前端框架搭建完整数据看板。 -- [ ] **策略调整与历史记录**:用户可查看所有生成过的历史评论,调整个人细分风格标签库。 +### Epic 7: 独立 Web 管理控制台 (SaaS 面板) +- [x] ✅ **基础设施 (P2)**:使用 Vue 3 (或 React) + Vite 搭建独立的管理页面,支持账号密码与 JWT 独立登录体系。 +- [x] ✅ **Web 界面开发**:Vite / Vue 3 前端框架搭建完整数据看板,暗黑玻璃态美学 UI (Dashboard / Radar / History)。 +- [x] ✅ **策略与历史接入**:实现了 /api/v1/replies 分析回溯接口,与监控拦截热点推文分发墙 (Pinterest Layout)。 + +### Epic 13: 性能数据追踪与个人风格学习 (AI Style Engine) +- [x] ✅ **动作埋点与入库**:前端点击“Copy”时,POST `/api/v1/replies/record` 存入 `generated_replies`。若为野生帖子,则静默补全伪造的关联 `Tweet` 防止外键错误。 +- [x] ✅ **性能回查 Worker**:新增 `PerformanceWorker`,独立线程每 30 分钟轮询 24 小时前已拷贝但未检验成效的回复。通过 Nitter `/i/status/id` 结构爬取目标原帖楼层并使用字符串相似度算法寻找目标回复并采集点赞量。 +- [x] ✅ **自动 AI 风格反推**:点赞突增 > 10 的神级评论,将会独立喂入 OpenAI / Anthropic,提取指令(Tone/Structure/Jargon),固化至 `user_style_profiles.tone_preference` 供给日后的推文任务强制学习。注入风格画像。 +- [ ] ⚪ **评论时机智能提醒 (P3)**:后端监控到高潜推文时,通过 Chrome Notification 推送 → 点击跳转 → Sidebar 预加载备选评论。 --- @@ -52,13 +95,17 @@ **核心目标**:验证效果以形成数据反馈,推出付费订阅,强化护城河。 ### Epic 8: 商业化支付与权限系统 -- [ ] **支付系统接入**:集成 Stripe 等主流订阅支付平台。 -- [ ] **多级版本控制**:根据 Free/Pro/Premium 版本,对“生成次数限制”“监控关键词上限”“账号数量”进行鉴权与隔离。 +- [ ] ⚪ **支付系统接入**:集成 Stripe 等主流订阅支付平台。 +- [ ] ⚪ **多级版本控制**:根据 Free/Pro/Premium 版本,对"生成次数限制""监控关键词上限""账号数量"进行鉴权与隔离。 ### Epic 9: 评论效果数据反馈(V2) -- [ ] **社交数据回拨检测**:定期查询用户发布评论后的真实点赞、回复数据。 -- [ ] **用户表现看板**:在 Web 后台提供“最有效互动风格”“最佳发帖时间”的数据可视化分析图表。 +- [ ] ⚪ **社交数据回拨检测**:定期查询用户发布评论后的真实点赞、回复数据。 +- [ ] ⚪ **用户表现看板**:在 Web 后台提供"最有效互动风格""最佳发帖时间"的数据可视化分析图表。 ### Epic 10: AI 模型个性化学习 -- [ ] **风格反馈微调**:针对高频点赞的回复风格,优化该用户的专属 Prompt。 -- [ ] **长期资产构建**:落地行业趋势资料包与垂直知识库,辅以 RAG 技术提高生成内容的深度。 +- [ ] ⚪ **风格反馈微调**:针对高频点赞的回复风格,优化该用户的专属 Prompt。 +- [ ] ⚪ **长期资产构建**:落地行业趋势资料包与垂直知识库,辅以 RAG 技术提高生成内容的深度。 + +### Epic 14: 增长与传播引擎 *(新增)* +- [ ] ⚪ **效果排行 & 成就系统**:每周评论表现报告 + 成就徽章(Viral Reply、Growth Streak 等)。 +- [ ] ⚪ **社交裂变入口**:Free 版评论卡片底部 "Generated by InsightReply" 水印(Pro 可去除)+ 评论表现分享图。 diff --git a/docs/IMPLEMENTATION_PLAN.md b/docs/IMPLEMENTATION_PLAN.md new file mode 100644 index 0000000..0a576ec --- /dev/null +++ b/docs/IMPLEMENTATION_PLAN.md @@ -0,0 +1,554 @@ +# InsightReply 实施计划 (Implementation Plan) + +> 本文档记录了 InsightReply 各模块的具体技术实现方案,是 `DEVELOPMENT_PLAN.md`(做什么)的落地补充(怎么做)。 +> 功能完善度的产品策略分析见 → [`PRODUCT_ROADMAP.md`](./PRODUCT_ROADMAP.md) + +--- + +## 一、数据抓取策略 (Data Acquisition Strategy) + +InsightReply 采用 **"前端主动感知 + 后端规则引擎"** 的双模式来实现数据抓取: + +### 1. 插件端交互式抓取 (User-Driven) +* **触发场景**:用户在 X (Twitter) 上浏览推文时,想针对某条推文生成评论。 +* **实现逻辑**:Content Script 直接从浏览器 DOM 中提取当前选定推文的作者、正文、互动数 (Like/Reply)。 +* **优点**:零延迟,无需后端预先抓取该推文,即看即得。 + +### 2. 后端雷达监控抓取 (System-Driven / Radar) +* **方案选型对比**: + +| 方案 | 代表 | 优点 | 缺点 | 月费 | +|------|------|------|------|------| +| 付费 SaaS | Apify / RapidAPI | 即插即用,免维护 | 按次计费 | $30-$100+ | +| 自建开源 | **Nitter + Camoufox** | 几乎免费 | 技术门槛高 | 仅服务器费 | + +* **最终选型**:自建 Nitter 开源方案。 +* **Nitter 实例地址**:`https://x.beenglish.eu.org/` + +--- + +## 二、浏览器插件技术实现 (Extension Architecture) + +### 1. Content Script 与 UI 注入 +* **Content Script (`src/content/index.ts`)**:监听页面 URL 变化,使用 `MutationObserver` 实时检测新加载的推文 DOM 节点。 +* **Shadow DOM 注入**:在推文操作栏注入"Insight"入口按钮。点击后展示主面板,面板挂载在 Shadow DOM 内,确保与 Twitter 原生样式完全隔离。 +* **Background Service Worker**:作为中转站,处理与后端 Go API 的通信和认证。 + +### 2. UI 设计规范 (ui-ux-pro-max) +* **暗黑毛玻璃风格**:主色调 `#0A0A0A` ~ `#171717`,浮动面板使用 `backdrop-filter: blur()`。 +* **品牌渐变色**:紫蓝渐变 `#8B5CF6` → `#3B82F6`,用于 CTA 按钮和高亮标签。 +* **字体**:优先使用 `Inter` / `Geist` / `SF Pro` 等现代无衬线字体。 +* **微动画**:所有状态切换配 `ease-in-out` 过渡(`200ms-300ms`)。 + +### 3. 技术栈规范 +* **Tailwind CSS v4**:所有间距、颜色从 Design Tokens 读取,禁止硬编码内联样式。 +* **Vue 3 Composition API**:高频 UI 元素(`Button`, `Card`, `Badge`)封装为基础组件。 +* **`cn()` 工具函数**:基于 `clsx` + `tailwind-merge` 统一处理动态 Class 冲突。 +* **轻量化打包**:禁止引入完整组件库,采用按需加载。 + +### 4. Content Script 性能优化策略 *(新增)* + +> 在 Twitter 重型 SPA 中,粗暴监听全文档 DOM 变更会产生严重性能问题。 + +* **收缩监听范围**:将 `MutationObserver` 的 `observe` 目标从 `document.body` 收缩到 `main[role="main"]` 或 Timeline 容器。 +* **防抖扫描**:`scanTweets()` 加入 `requestIdleCallback` 或 `debounce(200ms)`,避免高频回调。 +* **已处理标记**:通过 `WeakSet` 记录已注入按钮的推文节点,避免重复扫描。 +* **多选择器 Fallback**:Twitter 的 `data-testid` 属性随时可能变更,已处理推文选择器应支持多层 Fallback: + ```typescript + const TWEET_SELECTORS = [ + 'article[data-testid="tweet"]', + 'article[role="article"]', + 'div[data-testid="cellInnerDiv"] article' + ]; + ``` + +--- + +## 三、高可用后台抓取系统 (Industry Radar - Enterprise Architecture) + +考虑到系统的**稳定性、安全性和反风控 (Anti-Ban)**,自建 Nitter 之上的抓取系统设计为一套健壮的企业级爬虫架构。 + +### 1. 终极反风控与防封禁策略 (Anti-Ban Mechanisms) + +| 机制 | 说明 | +|------|------| +| **请求抖动 (Jitter)** | 每次请求间加入 `1s-5s` 强随机延迟,严禁整点并发 | +| **熔断降级 (Circuit Breaker)** | Nitter 连续返回 429/503 时自动暂停 30 分钟 | +| **Fallback 节点池** | 主节点熔断时自动切换到备用 Nitter 实例 | +| **指纹轮换 (Fingerprint Rotation)** | 同步轮换 UA + `Sec-Ch-Ua` + `Accept-Language` 等全套 Header | +| **会话隔离 (Session Isolation)** | 每个采集任务独立 Cookie Jar,避免跨任务身份串联 | + +### 2. 高可用采集架构 (Scraper & Queue) +* **异步任务队列**:基于 Redis 的 `Asynq`,解耦"触发"与"执行",控制最大并发数。 +* **指数退避重试 (Exponential Backoff)**:失败后按 1min → 3min → 10min 递增重试间隔。 +* **采集器健壮性**: + * `goquery` 解析找不到元素时记录 Warn,返回部分数据,**绝不 Panic**。 + * 关键报错时 **Dump HTML 快照**到日志表,方便排查 Nitter DOM 结构变更。 + +### 3. 数据计算与存储层 + +* **批量 Upsert**:使用 `ON CONFLICT DO UPDATE` 策略,降低 IO 压力,防止死锁。 +* **热度公式**: + ``` + heat_score = (Like增量 × 0.4) + (RT增量 × 0.3) + (Reply增量 × 0.3) + ``` +* **动态智能抓取频率 (Smart Crawling)**: + * 🔥 热度飙升的推文 → **高频队列**(每 15 分钟抓一次) + * 🧊 24 小时无新动态 → **低频队列**(每 4 小时抓一次) + * 极大节省抓取资源,显著降低被封概率。 + +--- + +## 四、后端安全与认证体系 *(新增)* + +### 1. JWT 认证方案 + +所有 `/api/v1` 路由(除 `/auth/*` 外)必须经过 JWT 认证中间件。 + +* **技术选型**:`go-chi/jwtauth` + HMAC-SHA256 签名。 +* **Token 结构**: + ```json + { + "sub": "user-uuid", + "tier": "Pro", + "exp": 1709164800 + } + ``` +* **刷新策略**:Access Token 有效期 24h,Refresh Token 有效期 30d,存于 `chrome.storage.local`。 + +### 2. Rate Limiting(分级限流) + +| Tier | 评论生成 | 监控关键词 | 监控账号 | +|------|---------|-----------|---------| +| Free | 10 次/天 | 3 个 | 3 个 | +| Pro | 无限 | 20 个 | 20 个 | +| Premium | 无限 | 50 个 | 50 个 | + +* **实现方案**:基于 Redis 的滑动窗口计数器,Key 格式:`ratelimit:{user_id}:{action}:{window}`。 +* **中间件挂载**:在 chi Router 中通过 `r.Use(RateLimitMiddleware)` 全局或分路由挂载。 + +### 3. CORS 配置 + +```go +r.Use(cors.Handler(cors.Options{ + AllowedOrigins: []string{"chrome-extension://*", "https://x.com", "https://twitter.com"}, + AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}, + AllowedHeaders: []string{"Authorization", "Content-Type"}, + AllowCredentials: true, + MaxAge: 300, +})) +``` + +--- + +## 五、LLM 服务韧性设计 *(新增)* + +### 1. 调用链路防护 + +``` +请求 → Timeout Guard (30s) → Circuit Breaker → Retry (max 2) → OpenAI API +``` + +* **Timeout**:`context.WithTimeout(ctx, 30*time.Second)` 包裹每次 LLM 调用。 +* **Circuit Breaker**:使用 `sony/gobreaker`,连续 5 次失败后半开,每 60s 试探一次恢复。 +* **指数退避重试**:仅对 5xx / Timeout 重试,4xx(如 quota exceeded)立即失败。 + +### 2. 多模型动态路由与 Fallback + +系统重构为 **多 Provider 支持 (OpenAI / Anthropic / DeepSeek / Gemini)**,以应对不同用户的专属模型偏好和单一 Provider 宕机时的容灾。同时支持**代理接口与自定义模型**。 + +**路由与配置设计**: +1. **环境变量驱动 (ENV)**:管理员可通过配置 `OPENAI_BASE_URL` 改写接口地址(完美兼容 Groq、vLLM、Ollama 等任意 OpenAI 兼容代理)。 +2. **可用模型下发**:通过 `OPENAI_AVAILABLE_MODELS="gpt-4o,gpt-4o-mini"` 配置白名单,后端通过 `GET /sys/config/llms` 统一向前端下发。 +3. **前端交互 (`default_llm_model`)**:前端展示为**「可输入的下拉列表 (Combobox)」**,用户既可从系统下发的列表中点选,也支持手动输入任意字符串,实现完全自定义。 +4. **故障转移 (Fallback)**:当前尝试的 Provider 返回 5xx 时,按兜底顺序切换:`Anthropic → OpenAI → Gemini → DeepSeek`。 + +**统一适配器抽象**: +建立统一的 `LLMProvider` 接口,抹平各平台 API 结构差异,内部集成对应 SDK: +- OpenAI (含兼容代理): `sashabaranov/go-openai` (支持通过 Builder 传入 BaseURL) +- Anthropic: 直接构造 REST API 请求 +- DeepSeek: 兼容 OpenAI SDK,基于 `DEEPSEEK_BASE_URL` 重连 +- Gemini: `google.golang.org/api/generativelanguage/v1beta` + +### 3. Token 成本审计 + +每次 LLM 调用记录 `prompt_tokens + completion_tokens`,写入 `api_usage_logs` 表: +```sql +INSERT INTO api_usage_logs (user_id, provider, model, prompt_tokens, completion_tokens, cost_usd) +VALUES ($1, $2, $3, $4, $5, $6); +``` + +--- + +## 六、Prompt 工程规范 *(新增)* + +### 1. 策略模板结构 + +每个评论策略维护独立的 Prompt 模板文件,存放于 `server/prompts/` 目录: + +``` +server/prompts/ +├── system.txt # 全局 System Prompt +├── cognitive_upgrade.txt # 认知升级型 +├── contrarian.txt # 反向观点型 +├── data_supplement.txt # 数据补充型 +├── empathy.txt # 共鸣型 +└── founder_exp.txt # 创始人经验型 +``` + +### 2. Prompt 结构公式 (必须遵守) + +``` +[System Prompt] +- 角色定义:专业社交媒体表达顾问 +- 输出约束:字数、语言、格式 + +[User Prompt] +- 用户身份标签:{identity} +- 目标推文:{tweet_content} +- 策略指令:{strategy_specific_instruction} +- 结构公式:Hook + Position + Insight + Brevity +- Few-shot 示例:2-3 条高质量参考 + +[Constraints] +- 不超过 280 字符 (或用户指定长度) +- 语言:与原推文一致,或用户指定 +- 语气与身份匹配 +- 禁止引号包裹 +``` + +### 3. 批量生成规范 + +API 单次返回 5 种策略 × 2 条备选 = **10 条候选评论**: +* 方案 A:单次 LLM 调用,Prompt 中要求 JSON 数组输出 +* 方案 B:5 组并发调用,每组 n=2 +* **推荐方案 A**,减少 API 调用次数 + +--- + +## 七、后端 Go 接口规范 + +* 采用 RESTful 标准。 +* 所有接口返回统一 JSON 结构: + ```json + { + "code": 200, + "message": "success", + "data": {} + } + ``` +* 错误码体系:`4xxx` 为客户端错误,`5xxx` 为服务端错误。 +* 详细接口文档见 → [`docs/API.md`](./API.md) + +--- + +## 八、环境变量与配置管理 *(新增)* + +所有运行时配置统一通过环境变量注入,**禁止硬编码**。 + +| 变量名 | 说明 | 示例 | +|-------|------|------| +| `DATABASE_URL` | PostgreSQL 连接串 | `postgres://user:pass@host:5432/db` | +| `OPENAI_API_KEY` | OpenAI API Key | `sk-...` | +| `JWT_SECRET` | JWT 签名密钥 | 随机 32+ 字符串 | +| `SERVER_PORT` | 服务端口 | `8080` | +| `CORS_ORIGINS` | 允许的跨域来源 | `chrome-extension://*` | +| `LOG_LEVEL` | 日志级别 | `info` / `debug` / `warn` | +| `LLM_TIMEOUT_SEC` | LLM 调用超时秒数 | `30` | + +模板文件 → [`server/.env.example`](../server/.env.example) + +--- + +## 九、验证计划 (Verification Plan) + +| # | 验证项 | 方法 | +|---|--------|------| +| 1 | 防封控链路 | 模拟 100 并发请求,验证熔断 + Jitter 能正确拦截 | +| 2 | HTML 解析容错 | 模拟账号冻结/推文被删等异常页面,确认不会 Panic | +| 3 | Shadow DOM 隔离 | 在 X 深色/浅色模式下验证插件样式不被污染 | +| 4 | 端到端生成链路 | 插件点击 → Background → Go API → LLM → 返回结果 | +| 5 | JWT 认证 *(新增)* | 无 Token / 过期 Token / 非法 Token 拒绝访问 | +| 6 | Rate Limiting *(新增)* | Free 用户超 10 次/天后返回 429 | +| 7 | LLM 韧性 *(新增)* | 模拟 OpenAI 超时 / 5xx,验证熔断降级 + 重试 | +| 8 | Graceful Shutdown *(新增)* | 发送 SIGTERM,验证在途请求完成后才退出 | +| 9 | Onboarding 流程 *(新增)* | 首次打开插件触发引导,设置存入 chrome.storage + 后端 | +| 10 | 多条备选评论 *(新增)* | 验证返回 3 条备选,Sidebar 卡片式展示正确 | +| 11 | 热度标签 *(新增)* | 在高互动推文旁正确显示 🔥/⚡ 标签 | +| 12 | 效果追踪闭环 *(新增)* | 复制评论 → 24h 后回查 → 互动数据写入 DB | + +--- + +## 十、用户 Onboarding 实现方案 *(新增)* + +### 1. 流程设计 + +首次安装/首次打开插件时,检测 `chrome.storage.sync` 中是否存在 `onboarding_completed` 标志。若无,显示 3 步引导: + +```typescript +// background/index.ts +chrome.runtime.onInstalled.addListener(({ reason }) => { + if (reason === 'install') { + chrome.storage.sync.set({ onboarding_completed: false }); + } +}); +``` + +### 2. 数据存储 + +| 字段 | 存储位置 | 说明 | +|------|---------|------| +| `identity_label` | `chrome.storage.sync` + `users` 表 | 身份标签 | +| `language_preference` | `chrome.storage.sync` + `users` 表 | 偏好语言 | +| `tone_preference` | `chrome.storage.sync` + `user_style_profiles` 表 | 风格倾向 | +| `onboarding_completed` | `chrome.storage.sync` | 是否已完成引导 | + +### 3. 与生成链路的集成 + +用户设置完成后,每次生成评论时自动读取 `chrome.storage.sync` 中的偏好,附加到 `GENERATE_REPLY` 消息中: + +```typescript +// 改造 Sidebar.vue 的 generate() +const prefs = await chrome.storage.sync.get(['identity_label', 'language_preference', 'tone_preference']); +chrome.runtime.sendMessage({ + type: 'GENERATE_REPLY', + payload: { + tweetContent: props.tweetData.content, + strategy: 'all', + identity: prefs.identity_label, + language: prefs.language_preference, + tone: prefs.tone_preference + } +}); +``` + +--- + +## 十一、前端热度标签实现方案 *(新增)* + +### 1. 判断逻辑 + +```typescript +interface HeatLevel { + label: string; + emoji: string; + className: string; +} + +const getHeatLevel = (likes: number, minutesAgo: number): HeatLevel | null => { + if (likes > 1000 && minutesAgo < 120) { + return { label: 'Trending', emoji: '🔥', className: 'heat-trending' }; + } + if (likes > 100 && minutesAgo < 60) { + return { label: 'Rising', emoji: '⚡', className: 'heat-rising' }; + } + return null; +}; +``` + +### 2. 注入位置 + +在 `injectInsightButton()` 函数中,紧挨 Insight 按钮旁边注入热度标签: +* 🔥 Trending:红色渐变 Badge (`background: linear-gradient(135deg, #ef4444, #f97316)`) +* ⚡ Rising:黄色渐变 Badge (`background: linear-gradient(135deg, #f59e0b, #eab308)`) + +### 3. 时间计算 + +从推文 DOM 中的 `