- 添加常见开发模式指南(API 端点、数据库字段、自定义 Agent、多语言内容) - 新增故障排除部分,涵盖常见问题和调试技巧 - 改进 GET /api/discovery/tasks 端点,支持通过查询参数传递 API key - 更新环境变量示例,使用更安全的 API key 格式
15 KiB
项目发现工作流 (Project Discovery Workflow)
本文档详细说明了 AI 项目自动发现和收录的完整工作流程。
📋 工作流概览
┌─────────────────────────────────────────────────────────────────┐
│ 项目发现完整流程 │
└─────────────────────────────────────────────────────────────────┘
1. n8n 自动化平台
│
├─ 定期抓取 GitHub/Twitter/HackerNews 等平台
├─ 筛选符合条件的项目链接
│
▼
2. 调用去重检查 API (推荐)
POST /api/discovery/check-duplicates
│
├─ 检查 URL 是否已存在任务
├─ 检查 URL 对应项目是否已收录
├─ 过滤出需要创建的 URL
│
▼
3. 调用创建任务 API
POST /api/discovery/tasks
│
├─ 存入 ProjectDiscoveryTask 表
├─ 状态: PENDING
│
▼
4. 手动触发本地命令 (定期执行)
/discover-projects
│
├─ 通过 curl 获取待处理任务
├─ 调用 Content Explorer Agent
│ ├─ 使用 agent-browser 探索项目
│ ├─ 提取项目信息 (README, 代码结构等)
│ ├─ 生成结构化 JSON 数据
│ └─ 应用内容质量标准
│
├─ 调用 API Submitter Agent
│ ├─ 批量标记任务为 IN_PROGRESS
│ ├─ 提交探索数据到完成 API
│ └─ 自动重试失败的提交
│
▼
5. 完成任务并入库
POST /api/discovery/tasks/{id}/complete
│
├─ 验证数据格式 (Zod Schema)
├─ 多级去重检测 (GitHub/Website URL)
├─ 创建或更新 Project
├─ 创建 Tag 和关联关系
├─ 创建 ExternalLink
│
├─ 更新任务状态: COMPLETED/FAILED
│
▼
6. 数据已入库,可在前台展示
🔄 详细步骤说明
步骤 1: n8n 自动收集项目链接
平台: n8n 自动化平台 (独立部署)
工作内容:
- 定期抓取 GitHub Trending、Twitter、HackerNews 等平台
- 根据关键词筛选 AI 相关项目
- 提取项目的基本信息 (名称、链接、简介等)
输出数据格式:
{
"sourceUrl": "https://github.com/langchain-ai/langchain",
"sourceType": "github_trending" // 或 "twitter", "hackernews" 等
}
步骤 2: 调用创建任务 API
API 端点: POST /api/discovery/tasks
调用示例:
curl -X POST https://your-domain.com/api/discovery/tasks \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"apiKey": "YOUR_API_KEY",
"tasks": [
{
"sourceUrl": "https://github.com/langchain-ai/langchain",
"sourceType": "github_trending"
},
{
"sourceUrl": "https://github.com/openai/openai-quickstart-python",
"sourceType": "github_trending"
}
]
}'
数据库变更:
- 在
ProjectDiscoveryTask表中插入新记录 status=PENDINGsourceUrl和sourceType来自 n8ncreatedAt= 当前时间
步骤 2.5: 调用去重检查 API(推荐)
API 端点: POST /api/discovery/check-duplicates
调用示例:
curl -X POST https://your-domain.com/api/discovery/check-duplicates \
-H "Content-Type: application/json" \
-d '{
"apiKey": "YOUR_API_KEY",
"urls": [
"https://github.com/langchain-ai/langchain",
"https://github.com/openai/openai-quickstart-python"
]
}'
返回结果:
{
"success": true,
"results": [
{
"url": "https://github.com/langchain-ai/langchain",
"shouldCreate": false,
"reason": "Task already exists with status PENDING",
"existingTask": {
"id": "cmxxxxx",
"status": "PENDING",
"sourceUrl": "https://github.com/langchain-ai/langchain",
"createdAt": "2025-01-18T10:00:00Z",
"projectId": null
}
},
{
"url": "https://github.com/openai/openai-quickstart-python",
"shouldCreate": true,
"reason": "No existing task or project found"
}
],
"stats": {
"total": 2,
"shouldCreate": 1,
"duplicate": 1
}
}
去重逻辑(按优先级):
-
优先级 1: 检查是否有 PENDING/IN_PROGRESS 的相同 URL 任务
- 如果存在 →
shouldCreate: false - 原因:任务已在处理中,避免重复探索
- 如果存在 →
-
优先级 2: 检查是否有 COMPLETED/FAILED 的相同 URL 任务
- 如果存在 →
shouldCreate: false - 原因:任务已探索过,无需重复
- 如果存在 →
-
优先级 3: 检查 URL 对应的项目是否已存在(通过 ExternalLink)
- 如果存在 →
shouldCreate: false - 原因:项目已通过其他来源收录
- 如果存在 →
-
默认: 允许创建新任务
shouldCreate: true
n8n 集成建议:
// n8n Workflow 示例
const checkResponse = await fetch('https://your-domain.com/api/discovery/check-duplicates', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
apiKey: 'YOUR_API_KEY',
urls: collectedUrls // 从上一步收集的 URL 列表
})
})
const { results, stats } = await checkResponse.json()
// 过滤出应该创建任务的 URL
const urlsToCreate = results
.filter(r => r.shouldCreate)
.map(r => r.url)
// 只为不重复的 URL 创建任务
if (urlsToCreate.length > 0) {
await fetch('https://your-domain.com/api/discovery/tasks', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
apiKey: 'YOUR_API_KEY',
tasks: urlsToCreate.map(url => ({
sourceUrl: url,
sourceType: 'github_trending'
}))
})
})
}
console.log(`创建 ${urlsToCreate.length} 个新任务,跳过 ${stats.duplicate} 个重复任务`)
步骤 3: 手动触发本地命令
执行环境: 本地开发环境 (Local Development)
执行命令:
# 处理默认 10 个任务 (每批 3 个)
/discover-projects
# 处理指定数量的任务
/discover-projects 20
# 自定义批次大小
/discover-projects 9 --batch=2
# 处理所有待处理任务
/discover-projects all --batch=5
命令执行流程:
- 通过 curl 调用
GET /api/discovery/tasks?status=PENDING&limit=N - 获取待处理的任务列表
- 分批处理 (默认每批 3 个任务)
- 为每个任务启动 Content Explorer Agent
步骤 3.1: Content Explorer Agent (项目探索)
Agent 定义: .claude/agents/content-explorer-agent.md
核心能力:
- 使用
agent-browser子任务并行探索 GitHub 项目 - 访问项目主页、README、代码结构
- 提取项目元数据 (名称、描述、标签、链接等)
- 生成符合
ProjectInputSchema的 JSON 数据
内容质量标准 (参考: .claude/schemas/project-content-template.md):
- ✅ 描述: 客观说明功能、突出价值、避免营销术语、10-500字
- ✅ 内容: 从 README 提取并重新组织、符合中文表达习惯
- ✅ 链接: 必须包含 GITHUB 链接、所有链接可访问
- ✅ 标签: 1-10 个标签、按技术/应用/状态分类
- ✅ 动态数据: Star/Fork 等动态数据不写入内容,使用 GitHub Badge
输出数据格式:
{
"name": "LangChain",
"nameEn": "LangChain",
"description": "开发由 LLM 驱动的应用程序的框架,提供文档加载、文本分割、向量存储等核心组件",
"descriptionEn": "Framework for developing applications powered by language models",
"content": "## 核心功能\n\n- 文档加载: 支持 PDF、TXT、网页等多种格式\n- 文本分割: 智能分割长文本\n...",
"tags": [
{ "name": "LLM", "nameEn": "Large Language Model" },
{ "name": "框架", "nameEn": "Framework" }
],
"links": [
{ "type": "GITHUB", "url": "https://github.com/langchain-ai/langchain", "title": "GitHub 仓库" },
{ "type": "WEBSITE", "url": "https://python.langchain.com", "title": "官方文档" }
],
"status": "ACTIVE"
}
步骤 3.2: API Submitter Agent (数据提交)
Agent 定义: .claude/agents/api-submitter-agent.md
核心能力:
- 批量标记任务为
IN_PROGRESS - 调用
POST /api/discovery/tasks/{id}/complete提交数据 - 自动重试失败的提交 (指数退避,最多 3 次)
- 处理部分成功/失败情况
提交流程:
1. PATCH /api/discovery/tasks/{id} → status=IN_PROGRESS
↓
2. POST /api/discovery/tasks/{id}/complete → 提交探索数据
↓
3. 检查响应
├─ 成功 → 标记任务完成
├─ 失败 → 重试 (最多 3 次)
└─ 最终失败 → 记录错误信息
步骤 4: 完成任务并入库
API 端点: POST /api/discovery/tasks/{id}/complete
处理逻辑 (参考: src/app/api/discovery/tasks/[id]/complete/route.ts):
- 验证数据格式: 使用
ProjectInputSchema验证 - 多级去重检测:
- 优先级 1: GitHub URL 精确匹配
- 优先级 2: Website URL 精确匹配
- 优先级 3: slug 匹配
- 创建或更新项目:
- 如果存在重复项目 → 更新所有字段、标签、链接
- 如果不存在 → 创建新项目
- 更新任务状态:
- 成功 →
COMPLETED - 失败 →
FAILED(记录错误信息)
- 成功 →
数据库变更:
Project表: 创建或更新记录Tag表: Upsert 标签ProjectTag表: 创建关联关系ExternalLink表: 创建或更新链接ProjectDiscoveryTask表: 更新status、projectId、completedAt
🗂️ 数据模型关系
ProjectDiscoveryTask (任务表)
├─ id: String (主键)
├─ status: TaskStatus (PENDING/IN_PROGRESS/COMPLETED/FAILED)
├─ sourceUrl: String (n8n 提供的原始 URL)
├─ sourceType: String (github_trending/twitter/hackernews)
├─ explorationData: Json (Agent 探索结果)
├─ explorationSummary: String (探索摘要)
├─ projectId: String (关联到 Project.id)
├─ errorMessage: String (失败原因)
└─ createdAt/startedAt/completedAt: DateTime
Project (项目表) ← 通过 projectId 关联
├─ id, name, nameEn, slug
├─ description, descriptionEn
├─ content, contentEn
├─ status (ACTIVE/ARCHIVED)
└─ 关联: tags, links, discoveryTasks
Tag (标签表)
└─ 通过 ProjectTag 多对多关联
ExternalLink (外部链接表)
└─ 通过 projectId 一对多关联
🔧 环境配置
环境变量
# .env.local (本地开发)
WEBHOOK_API_KEY=sk_live_your_secure_api_key_min_32_chars # 用于调用完成 API
# 生产环境 (Vercel Dashboard 配置)
DATABASE_URL=postgres://...
WEBHOOK_API_KEY=sk_live_your_secure_api_key_min_32_chars
依赖服务
-
n8n 平台:
- 独立部署 (自托管或云服务)
- 配置定时工作流 (Workflow)
- 存储
WEBHOOK_API_KEY用于 API 调用
-
本地开发环境:
- Node.js 18+
- pnpm 包管理器
- Claude Code CLI (支持斜杠命令)
-
生产环境:
- Vercel (Next.js 部署)
- Neon PostgreSQL (数据库)
📊 执行监控
查看待处理任务
# 查询待处理任务数量
curl https://your-domain.com/api/discovery/tasks?status=PENDING&limit=100
# 查询进行中的任务
curl https://your-domain.com/api/discovery/tasks?status=IN_PROGRESS
# 查询失败的任务 (需要重试)
curl https://your-domain.com/api/discovery/tasks?status=FAILED
重试失败任务
# 手动重试失败的任务
/discover-projects 10 --status=FAILED
🎯 质量保障
内容质量标准 (详细参考: .claude/schemas/project-content-template.md)
-
描述要求:
- 清晰说明项目的核心功能
- 突出项目的独特价值
- 避免使用营销术语 ("最好"、"第一"、"革命性" 等)
- 字数控制在 10-500 字
-
内容要求:
- 从项目 README 提取并重新组织
- 避免机械翻译,符合中文表达习惯
- 支持 Markdown 格式
- 动态数据 (Star/Fork) 不写入内容
-
链接要求:
- 必须包含 GITHUB 链接
- 所有链接必须可访问
- 链接类型必须正确 (WEBSITE/GITHUB/HUGGINGFACE/PAPER)
-
标签要求:
- 1-10 个标签
- 按技术栈/应用领域/开发状态分类
- 中英文对应
数据验证
所有提交的数据必须通过 ProjectInputSchema 验证 (详见 src/lib/validations.ts):
ProjectInputSchema {
name: string (1-200字符, 必填)
description: string (10-500字符, 必填)
tags: Tag[] (1-10个, 必填)
links: ExternalLink[] (1-10个, 必填)
nameEn?: string (1-200字符)
descriptionEn?: string
content?: string (Markdown, 最多10000字符)
contentEn?: string
status?: "ACTIVE" | "ARCHIVED"
source?: string
}
🚀 快速开始
第一次使用
-
配置 n8n 工作流:
- 创建新的 n8n Workflow
- 配置定时触发器 (如每天凌晨 2 点)
- 添加 HTTP Request 节点调用
POST /api/discovery/tasks
-
本地执行命令:
# 启动开发服务器 (如果未运行) pnpm dev # 执行项目发现命令 /discover-projects -
查看结果:
- 访问 https://your-domain.com 查看新收录的项目
- 检查数据库确认数据正确性
日常维护
-
定期执行命令 (建议每天 1-2 次):
/discover-projects 20 -
监控失败任务:
- 检查
status=FAILED的任务 - 分析错误原因 (网络问题、数据格式等)
- 必要时手动重试
- 检查
-
优化内容质量:
- 随机抽查已收录项目的描述和内容
- 调整 Agent 的提示词以提升质量
🔍 故障排查
常见问题
-
任务长时间处于 IN_PROGRESS 状态:
- 可能原因: Agent 探索超时、网络问题
- 解决方案: 手动更新任务状态为 PENDING 后重试
-
大量任务失败:
- 检查
errorMessage字段 - 常见原因: 数据格式不正确、URL 无法访问、API Key 错误
- 检查
-
重复项目被创建:
- 检查去重逻辑是否正常工作
- 确认
ExternalLink表的索引idx_link_type_url存在
-
n8n 无法调用 API:
- 检查
WEBHOOK_API_KEY是否正确配置 - 确认 API 端点可访问
- 查看 n8n 执行日志
- 检查
📚 相关文档
- API 参考:
docs/api-reference.md - 数据模型:
prisma/schema.prisma - 验证规则:
src/lib/validations.ts - Agent 定义:
.claude/agents/content-explorer-agent.md - Agent 定义:
.claude/agents/api-submitter-agent.md - 内容质量标准:
.claude/schemas/project-content-template.md - 项目主文档:
CLAUDE.md
📝 更新日志
- 2025-01-18: 创建文档,记录完整的项目发现工作流