移除 .claude 目录下的项目发现系统组件: - content-explorer-agent(项目内容探索专家) - api-submitter-agent(API 提交专家) - discover-projects 命令 - project-content-template 模板 同时更新配置和文档: - settings.json 添加代理配置 - api-reference.md 完善项目发现系统 API 说明 Co-Authored-By: Claude <noreply@anthropic.com>
1050 lines
24 KiB
Markdown
1050 lines
24 KiB
Markdown
# API 接口文档
|
||
|
||
> AI 项目导航站对外提供的 REST API 接口文档
|
||
|
||
## 目录
|
||
|
||
- [1. 概述](#1-概述)
|
||
- [2. 认证方式](#2-认证方式)
|
||
- [3. 接口列表](#3-接口列表)
|
||
- [3.1 创建/更新项目 (Webhook)](#31-创建更新项目-webhook)
|
||
- [3.2 获取项目详情](#32-获取项目详情)
|
||
- [3.3 删除项目](#33-删除项目)
|
||
- [3.4 项目发现系统 API](#34-项目发现系统-api)
|
||
- [3.5 去重检查 API](#35-去重检查-api)
|
||
- [4. 数据模型](#4-数据模型)
|
||
- [5. 错误码](#5-错误码)
|
||
|
||
---
|
||
|
||
## 1. 概述
|
||
|
||
### 1.1 Base URL
|
||
|
||
```
|
||
生产环境: https://your-domain.com
|
||
开发环境: http://localhost:3000
|
||
```
|
||
|
||
### 1.2 响应格式
|
||
|
||
所有接口返回 JSON 格式数据:
|
||
|
||
```typescript
|
||
// 成功响应
|
||
{
|
||
"success": true,
|
||
"data": { ... },
|
||
"message": "操作成功"
|
||
}
|
||
|
||
// 错误响应
|
||
{
|
||
"success": false,
|
||
"error": "错误类型",
|
||
"details": ["详细错误信息1", "详细错误信息2"]
|
||
}
|
||
```
|
||
|
||
### 1.3 通用请求头
|
||
|
||
```
|
||
Content-Type: application/json
|
||
x-api-key: your-api-key-here # 需要认证的接口
|
||
```
|
||
|
||
---
|
||
|
||
## 2. 认证方式
|
||
|
||
### API Key 认证
|
||
|
||
所有 API 接口均使用 API Key 进行认证。API Key 通过请求头 `x-api-key` 传递。
|
||
|
||
```bash
|
||
# 设置环境变量
|
||
WEBHOOK_API_KEY=your-secret-api-key
|
||
|
||
# 请求示例
|
||
curl -X POST https://your-domain.com/api/webhook/projects \
|
||
-H "Content-Type: application/json" \
|
||
-H "x-api-key: your-secret-api-key" \
|
||
-d '...'
|
||
```
|
||
|
||
**注意事项**:
|
||
- API Key 需要在服务端环境变量中配置 `WEBHOOK_API_KEY`
|
||
- 请妥善保管 API Key,不要在客户端代码中暴露
|
||
- 建议定期轮换 API Key
|
||
|
||
---
|
||
|
||
## 3. 接口列表
|
||
|
||
### 3.1 创建/更新项目 (Webhook)
|
||
|
||
批量创建或更新项目数据。支持多级去重策略自动识别已存在的项目。
|
||
|
||
#### 3.1.1 接口信息
|
||
|
||
```
|
||
POST /api/webhook/projects
|
||
```
|
||
|
||
#### 3.1.2 请求参数
|
||
|
||
**Headers**:
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| x-api-key | string | 是 | API 密钥 |
|
||
| Content-Type | string | 是 | 必须为 `application/json` |
|
||
|
||
**Body**:
|
||
|
||
```typescript
|
||
{
|
||
apiKey: string; // API 密钥(与 header x-api-key 二选一)
|
||
projects: ProjectInput[]; // 项目数组(1-100个)
|
||
}
|
||
```
|
||
|
||
**ProjectInput 类型**:
|
||
|
||
```typescript
|
||
{
|
||
// 基础信息(必填)
|
||
name: string; // 中文名称 (1-200 字符)
|
||
nameEn?: string; // 英文名称(可选,1-200 字符)
|
||
description: string; // 中文描述 (10-500 字符)
|
||
descriptionEn?: string; // 英文描述(可选,10-500 字符)
|
||
|
||
// 内容(可选)
|
||
content?: string; // 中文内容(Markdown 格式,最大 10000 字符)
|
||
contentEn?: string; // 英文内容(Markdown 格式,最大 10000 字符)
|
||
|
||
// 状态(可选)
|
||
status?: "ACTIVE" | "ARCHIVED"; // 默认: "ACTIVE"
|
||
source?: string; // 数据来源标识
|
||
|
||
// 关联(必填)
|
||
tags: Array<{ // 标签数组(1-10个)
|
||
name: string; // 标签名
|
||
nameEn?: string; // 英文标签名(可选)
|
||
}>;
|
||
links: Array<{ // 外部链接数组(1-10个)
|
||
type: "WEBSITE" | "GITHUB" | "HUGGINGFACE" | "PAPER";
|
||
url: string; // 链接 URL
|
||
title?: string; // 链接标题(可选)
|
||
}>;
|
||
}
|
||
```
|
||
|
||
#### 3.1.3 多级去重策略
|
||
|
||
Webhook 会按以下优先级识别已存在的项目:
|
||
|
||
1. **GitHub URL 精确匹配**(最准确)
|
||
2. **Website URL 精确匹配**
|
||
3. **slug 匹配**(兜底)
|
||
|
||
如果找到已存在的项目,将执行更新操作:
|
||
- 更新所有项目字段
|
||
- 替换所有标签(删除旧的,创建新的)
|
||
- 替换所有链接(删除旧的,创建新的)
|
||
|
||
#### 3.1.4 请求示例
|
||
|
||
```bash
|
||
curl -X POST https://your-domain.com/api/webhook/projects \
|
||
-H "Content-Type: application/json" \
|
||
-H "x-api-key: your-api-key" \
|
||
-d '{
|
||
"apiKey": "your-api-key",
|
||
"projects": [
|
||
{
|
||
"name": "LangChain",
|
||
"nameEn": "LangChain",
|
||
"description": "开发由语言模型驱动的应用程序框架",
|
||
"descriptionEn": "Developing applications powered by language models",
|
||
"content": "# LangChain\n\nLangChain 是一个...",
|
||
"contentEn": "# LangChain\n\nLangChain is a...",
|
||
"status": "ACTIVE",
|
||
"source": "GITHUB",
|
||
"tags": [
|
||
{ "name": "LLM", "nameEn": "Large Language Model" },
|
||
{ "name": "Python", "nameEn": "Python" },
|
||
{ "name": "开发框架", "nameEn": "Development Framework" }
|
||
],
|
||
"links": [
|
||
{
|
||
"type": "GITHUB",
|
||
"url": "https://github.com/langchain-ai/langchain",
|
||
"title": "GitHub 仓库"
|
||
},
|
||
{
|
||
"type": "WEBSITE",
|
||
"url": "https://langchain.com",
|
||
"title": "官方网站"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}'
|
||
```
|
||
|
||
#### 3.1.5 响应示例
|
||
|
||
**成功响应** (200 OK):
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"processed": 1,
|
||
"created": 0,
|
||
"updated": 1,
|
||
"failed": 0,
|
||
"errors": []
|
||
}
|
||
```
|
||
|
||
**错误响应** (400 Bad Request):
|
||
|
||
```json
|
||
{
|
||
"success": false,
|
||
"error": "Validation error",
|
||
"details": [
|
||
"tags: Field must contain at least 1 element",
|
||
"links: Field must contain at most 10 elements"
|
||
]
|
||
}
|
||
```
|
||
|
||
**认证失败** (401 Unauthorized):
|
||
|
||
```json
|
||
{
|
||
"success": false,
|
||
"error": "Unauthorized",
|
||
"details": ["Invalid or missing API Key"]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 3.2 获取项目详情
|
||
|
||
根据项目的 slug 获取项目详细信息。
|
||
|
||
#### 3.2.1 接口信息
|
||
|
||
```
|
||
GET /api/projects/:slug
|
||
```
|
||
|
||
#### 3.2.2 路径参数
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| slug | string | 是 | 项目的唯一标识符 |
|
||
|
||
#### 3.2.3 请求示例
|
||
|
||
```bash
|
||
curl -X GET https://your-domain.com/api/projects/langchain \
|
||
-H "Content-Type: application/json"
|
||
```
|
||
|
||
#### 3.2.4 响应示例
|
||
|
||
**成功响应** (200 OK):
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"data": {
|
||
"id": "clx1234567890",
|
||
"name": "LangChain",
|
||
"nameEn": "LangChain",
|
||
"slug": "langchain",
|
||
"description": "开发由语言模型驱动的应用程序框架",
|
||
"descriptionEn": "Developing applications powered by language models",
|
||
"content": "# LangChain\n\nLangChain 是一个...",
|
||
"contentEn": "# LangChain\n\nLangChain is a...",
|
||
"status": "ACTIVE",
|
||
"source": "GITHUB",
|
||
"createdAt": "2024-01-01T00:00:00.000Z",
|
||
"updatedAt": "2024-01-15T00:00:00.000Z",
|
||
"links": [
|
||
{
|
||
"id": "link123",
|
||
"type": "GITHUB",
|
||
"url": "https://github.com/langchain-ai/langchain",
|
||
"title": "GitHub 仓库"
|
||
}
|
||
],
|
||
"tags": [
|
||
{
|
||
"id": "tag123",
|
||
"name": "LLM",
|
||
"nameEn": "Large Language Model",
|
||
"slug": "large-language-model"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
**项目不存在** (404 Not Found):
|
||
|
||
```json
|
||
{
|
||
"success": false,
|
||
"error": "Not Found",
|
||
"details": ["Project with slug \"nonexistent\" not found"]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 3.3 删除项目
|
||
|
||
根据项目的 slug 删除项目及其所有关联数据。
|
||
|
||
#### 3.3.1 接口信息
|
||
|
||
```
|
||
DELETE /api/projects/:slug
|
||
```
|
||
|
||
#### 3.3.2 路径参数
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| slug | string | 是 | 项目的唯一标识符 |
|
||
|
||
#### 3.3.3 请求头
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| x-api-key | string | 是 | API 密钥 |
|
||
| Content-Type | string | 是 | 必须为 `application/json` |
|
||
|
||
#### 3.3.4 级联删除说明
|
||
|
||
由于数据库配置了 `onDelete: Cascade`,删除项目时会自动删除:
|
||
|
||
- ✅ 该项目的所有外部链接(`ExternalLink`)
|
||
- ✅ 该项目的所有标签关联(`ProjectTag`)
|
||
- ❌ Tag 本身不会被删除(只删除项目与标签的关联关系)
|
||
|
||
#### 3.3.5 请求示例
|
||
|
||
```bash
|
||
curl -X DELETE https://your-domain.com/api/projects/langchain \
|
||
-H "Content-Type: application/json" \
|
||
-H "x-api-key: your-api-key"
|
||
```
|
||
|
||
#### 3.3.6 响应示例
|
||
|
||
**成功响应** (200 OK):
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"message": "Project deleted successfully",
|
||
"data": {
|
||
"project": {
|
||
"id": "clx1234567890",
|
||
"name": "LangChain",
|
||
"nameEn": "LangChain",
|
||
"slug": "langchain"
|
||
},
|
||
"deleted": {
|
||
"linksCount": 2,
|
||
"tagsCount": 3
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
**项目不存在** (404 Not Found):
|
||
|
||
```json
|
||
{
|
||
"success": false,
|
||
"error": "Not Found",
|
||
"details": ["Project with slug \"nonexistent\" not found"]
|
||
}
|
||
```
|
||
|
||
**认证失败** (401 Unauthorized):
|
||
|
||
```json
|
||
{
|
||
"success": false,
|
||
"error": "Unauthorized",
|
||
"details": ["Invalid or missing API Key"]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 3.4 项目发现系统 API
|
||
|
||
项目发现系统用于自动化探索和收录 AI 项目,支持任务创建、状态追踪和项目提交。
|
||
|
||
#### 3.4.1 创建探索任务
|
||
|
||
批量创建新的项目探索任务。
|
||
|
||
```
|
||
POST /api/discovery/tasks
|
||
```
|
||
|
||
**请求体**:
|
||
|
||
```typescript
|
||
{
|
||
apiKey: string; // API 密钥
|
||
tasks: Array<{
|
||
sourceUrl: string; // 探索目标 URL (GitHub 仓库链接等)
|
||
sourceType?: string; // 来源类型,默认 "manual"
|
||
}>; // 1-50 个任务
|
||
}
|
||
```
|
||
|
||
**响应示例** (200 OK):
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"created": 5,
|
||
"skipped": 2,
|
||
"total": 7
|
||
}
|
||
```
|
||
|
||
**去重逻辑**:
|
||
- 如果 `sourceUrl` 已存在任务,自动跳过并计入 `skipped`
|
||
|
||
---
|
||
|
||
#### 3.4.2 获取任务列表
|
||
|
||
获取待处理或指定状态的探索任务列表。
|
||
|
||
```
|
||
GET /api/discovery/tasks?status=PENDING&limit=10&offset=0
|
||
```
|
||
|
||
**查询参数**:
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| status | string | 否 | 筛选状态: PENDING/IN_PROGRESS/COMPLETED/FAILED |
|
||
| limit | number | 否 | 每页数量,默认 10,最大 100 |
|
||
| offset | number | 否 | 偏移量,默认 0 |
|
||
|
||
**请求头**:
|
||
|
||
```
|
||
x-api-key: your-api-key
|
||
```
|
||
|
||
**响应示例** (200 OK):
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"tasks": [
|
||
{
|
||
"id": "clx1234567890",
|
||
"sourceUrl": "https://github.com/user/repo",
|
||
"sourceType": "manual",
|
||
"status": "PENDING",
|
||
"createdAt": "2024-01-15T00:00:00.000Z",
|
||
"startedAt": null,
|
||
"completedAt": null,
|
||
"projectId": null,
|
||
"explorationData": null,
|
||
"explorationSummary": null,
|
||
"errorMessage": null,
|
||
"retryCount": 0
|
||
}
|
||
],
|
||
"total": 25,
|
||
"hasMore": true
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### 3.4.3 获取任务详情
|
||
|
||
获取单个探索任务的详细信息。
|
||
|
||
```
|
||
GET /api/discovery/tasks/:id
|
||
```
|
||
|
||
**无需认证** (只读端点)
|
||
|
||
**响应示例** (200 OK):
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"task": {
|
||
"id": "clx1234567890",
|
||
"sourceUrl": "https://github.com/user/repo",
|
||
"sourceType": "manual",
|
||
"status": "COMPLETED",
|
||
"createdAt": "2024-01-15T00:00:00.000Z",
|
||
"startedAt": "2024-01-15T00:01:00.000Z",
|
||
"completedAt": "2024-01-15T00:05:00.000Z",
|
||
"projectId": "clx0987654321",
|
||
"explorationData": { ... },
|
||
"explorationSummary": "LangChain 是一个 LLM 应用开发框架...",
|
||
"errorMessage": null,
|
||
"retryCount": 0
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### 3.4.4 更新任务状态
|
||
|
||
更新探索任务的状态和相关信息。
|
||
|
||
```
|
||
PATCH /api/discovery/tasks/:id
|
||
```
|
||
|
||
**请求体**:
|
||
|
||
```typescript
|
||
{
|
||
apiKey: string;
|
||
status: 'PENDING' | 'IN_PROGRESS' | 'COMPLETED' | 'FAILED';
|
||
explorationData?: Record<string, unknown>; // 探索结果数据 (JSON)
|
||
explorationSummary?: string; // 探索摘要,最大 1000 字符
|
||
errorMessage?: string; // 错误信息,最大 2000 字符
|
||
}
|
||
```
|
||
|
||
**状态转换规则**:
|
||
|
||
| 当前状态 | 允许转换到 |
|
||
|----------|------------|
|
||
| PENDING | IN_PROGRESS |
|
||
| IN_PROGRESS | COMPLETED, FAILED |
|
||
| COMPLETED | (终态,不可转换) |
|
||
| FAILED | PENDING (允许重试) |
|
||
|
||
**响应示例** (200 OK):
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"task": {
|
||
"id": "clx1234567890",
|
||
"status": "IN_PROGRESS",
|
||
"startedAt": "2024-01-15T00:01:00.000Z",
|
||
...
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### 3.4.5 完成任务并提交项目
|
||
|
||
完成探索并提交项目数据(自动创建或更新项目)。
|
||
|
||
```
|
||
POST /api/discovery/tasks/:id/complete
|
||
```
|
||
|
||
**请求体**:
|
||
|
||
```typescript
|
||
{
|
||
apiKey: string;
|
||
explorationData: ProjectInput; // 符合 ProjectInputSchema 的项目数据
|
||
}
|
||
```
|
||
|
||
**功能说明**:
|
||
- 验证 `explorationData` 格式
|
||
- 多级去重策略识别已存在项目(GitHub URL → Website URL → slug)
|
||
- 使用事务确保任务状态更新和项目创建/更新的原子性
|
||
- 成功时任务状态更新为 COMPLETED,关联 projectId
|
||
- 失败时任务状态更新为 FAILED,记录错误信息
|
||
|
||
**响应示例** (200 OK):
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"taskId": "clx1234567890",
|
||
"projectId": "clx0987654321",
|
||
"action": "created",
|
||
"duration": 1234
|
||
}
|
||
```
|
||
|
||
**错误响应** (400 Bad Request):
|
||
|
||
```json
|
||
{
|
||
"success": false,
|
||
"error": "Invalid exploration data format",
|
||
"details": [
|
||
"tags: Field must contain at least 1 element",
|
||
"links: Field must contain at least 1 element"
|
||
]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### 3.4.6 检查任务去重
|
||
|
||
在创建任务前检查 URL 是否应该创建新任务。
|
||
|
||
```
|
||
POST /api/discovery/check-duplicates
|
||
```
|
||
|
||
**请求体**:
|
||
|
||
```typescript
|
||
{
|
||
apiKey: string;
|
||
urls: string[]; // 1-100 个 URL
|
||
sourceType?: string; // 可选来源标识
|
||
}
|
||
```
|
||
|
||
**去重优先级**:
|
||
1. PENDING/IN_PROGRESS 任务 → 不创建(任务处理中)
|
||
2. COMPLETED/FAILED 任务 → 不创建(已探索过)
|
||
3. 已存在的项目(通过 ExternalLink)→ 不创建(已收录)
|
||
4. 无任何记录 → 允许创建
|
||
|
||
**响应示例** (200 OK):
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"results": [
|
||
{
|
||
"url": "https://github.com/langchain-ai/langchain",
|
||
"shouldCreate": false,
|
||
"reason": "Task already completed",
|
||
"existingTask": {
|
||
"id": "clx123",
|
||
"status": "COMPLETED",
|
||
"sourceUrl": "https://github.com/langchain-ai/langchain",
|
||
"createdAt": "2024-01-15T00:00:00.000Z",
|
||
"projectId": "clx456"
|
||
},
|
||
"existingProject": {
|
||
"id": "clx456",
|
||
"name": "LangChain",
|
||
"slug": "langchain"
|
||
}
|
||
}
|
||
],
|
||
"stats": {
|
||
"total": 10,
|
||
"shouldCreate": 5,
|
||
"duplicate": 5
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 3.5 去重检查 API
|
||
|
||
检查项目是否已存在(用于提交前的预检查)。
|
||
|
||
#### 3.5.1 检查项目去重
|
||
|
||
根据 URL 或 slug 检查项目是否已存在。
|
||
|
||
```
|
||
POST /api/webhook/check-duplicates
|
||
```
|
||
|
||
**请求体**:
|
||
|
||
```typescript
|
||
{
|
||
apiKey: string;
|
||
projects: Array<{
|
||
githubUrl?: string;
|
||
huggingfaceUrl?: string;
|
||
websiteUrl?: string;
|
||
slug?: string;
|
||
}>;
|
||
}
|
||
```
|
||
|
||
**匹配优先级**:
|
||
1. GitHub URL 精确匹配
|
||
2. Hugging Face URL 精确匹配
|
||
3. Website URL 精确匹配
|
||
4. slug 匹配(兜底)
|
||
|
||
**响应示例** (200 OK):
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"results": [
|
||
{
|
||
"githubUrl": "https://github.com/langchain-ai/langchain",
|
||
"exists": true,
|
||
"matchType": "GITHUB_URL",
|
||
"projectId": "clx456",
|
||
"projectName": "LangChain"
|
||
},
|
||
{
|
||
"websiteUrl": "https://newproject.com",
|
||
"exists": false,
|
||
"matchType": "NONE"
|
||
}
|
||
],
|
||
"stats": {
|
||
"total": 2,
|
||
"exists": 1,
|
||
"new": 1,
|
||
"breakdown": {
|
||
"githubUrl": 1,
|
||
"huggingfaceUrl": 0,
|
||
"websiteUrl": 0,
|
||
"slug": 0
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 4. 数据模型
|
||
|
||
### 4.1 Project 状态枚举
|
||
|
||
```typescript
|
||
enum ProjectStatus {
|
||
ACTIVE = "ACTIVE", // 活跃项目
|
||
ARCHIVED = "ARCHIVED" // 已归档项目
|
||
}
|
||
```
|
||
|
||
### 4.2 链接类型枚举
|
||
|
||
```typescript
|
||
enum LinkType {
|
||
WEBSITE = "WEBSITE", // 官方网站
|
||
GITHUB = "GITHUB", // GitHub 仓库
|
||
HUGGINGFACE = "HUGGINGFACE", // Hugging Face 模型/数据集
|
||
PAPER = "PAPER" // 论文链接
|
||
}
|
||
```
|
||
|
||
### 4.3 完整项目模型
|
||
|
||
```typescript
|
||
interface Project {
|
||
id: string; // 项目唯一 ID(cuid 格式)
|
||
name: string; // 中文名称 (1-200 字符)
|
||
nameEn: string | null; // 英文名称
|
||
slug: string; // URL 友好标识符(唯一)
|
||
description: string; // 中文描述 (10-500 字符)
|
||
descriptionEn: string | null;// 英文描述
|
||
content: string | null; // 中文内容(Markdown,最大 10000 字符)
|
||
contentEn: string | null; // 英文内容(Markdown,最大 10000 字符)
|
||
status: ProjectStatus; // 项目状态
|
||
source: string | null; // 数据来源
|
||
createdAt: Date; // 创建时间
|
||
updatedAt: Date; // 更新时间
|
||
|
||
// 关联数据
|
||
tags: Tag[]; // 标签数组
|
||
links: ExternalLink[]; // 外部链接数组
|
||
}
|
||
```
|
||
|
||
### 4.4 Tag 模型
|
||
|
||
```typescript
|
||
interface Tag {
|
||
id: string; // 标签唯一 ID
|
||
name: string; // 中文名称(唯一)
|
||
nameEn: string | null; // 英文名称
|
||
slug: string; // URL 友好标识符(唯一)
|
||
createdAt: Date; // 创建时间
|
||
}
|
||
```
|
||
|
||
### 4.5 ExternalLink 模型
|
||
|
||
```typescript
|
||
interface ExternalLink {
|
||
id: string; // 链接唯一 ID
|
||
type: LinkType; // 链接类型
|
||
url: string; // 链接 URL
|
||
title: string | null; // 链接标题
|
||
projectId: string; // 所属项目 ID
|
||
}
|
||
```
|
||
|
||
### 4.6 ProjectDiscoveryTask 模型
|
||
|
||
```typescript
|
||
interface ProjectDiscoveryTask {
|
||
id: string; // 任务唯一 ID (cuid 格式)
|
||
sourceUrl: string; // 探索目标 URL
|
||
sourceType: string; // 来源类型 (如 "manual", "github-trending")
|
||
status: TaskStatus; // 任务状态
|
||
createdAt: Date; // 创建时间
|
||
startedAt: Date | null; // 开始处理时间
|
||
completedAt: Date | null; // 完成时间
|
||
projectId: string | null; // 关联的项目 ID (完成后)
|
||
explorationData: JsonValue | null; // 探索结果数据 (JSON)
|
||
explorationSummary: string | null; // 探索摘要
|
||
errorMessage: string | null; // 错误信息
|
||
retryCount: number; // 重试次数
|
||
lastRetryAt: Date | null; // 最后重试时间
|
||
}
|
||
```
|
||
|
||
### 4.7 TaskStatus 状态枚举
|
||
|
||
```typescript
|
||
enum TaskStatus {
|
||
PENDING = 'PENDING', // 待处理
|
||
IN_PROGRESS = 'IN_PROGRESS', // 处理中
|
||
COMPLETED = 'COMPLETED', // 已完成
|
||
FAILED = 'FAILED' // 失败
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 5. 错误码
|
||
|
||
### 5.1 HTTP 状态码
|
||
|
||
| 状态码 | 说明 | 示例场景 |
|
||
|--------|------|----------|
|
||
| 200 OK | 请求成功 | 成功获取/创建/更新/删除数据 |
|
||
| 400 Bad Request | 请求参数错误 | 必填字段缺失、字段格式错误 |
|
||
| 401 Unauthorized | 认证失败 | API Key 无效或缺失 |
|
||
| 404 Not Found | 资源不存在 | 请求的项目 slug 不存在 |
|
||
| 500 Internal Server Error | 服务器内部错误 | 数据库连接失败、程序异常 |
|
||
|
||
### 5.2 业务错误类型
|
||
|
||
| 错误类型 | 说明 | 处理建议 |
|
||
|----------|------|----------|
|
||
| Validation error | 数据验证失败 | 检查请求体字段是否符合要求 |
|
||
| Unauthorized | API Key 无效 | 检查 API Key 是否正确 |
|
||
| Not Found | 资源不存在 | 确认 slug 是否正确 |
|
||
| Internal server error | 服务器错误 | 联系技术支持或稍后重试 |
|
||
|
||
### 5.3 验证规则
|
||
|
||
#### 项目数据验证
|
||
|
||
```typescript
|
||
// 必填字段
|
||
- name: 非空字符串,长度 1-200
|
||
- description: 非空字符串,长度 10-500
|
||
- tags: 数组,长度 1-10,每个 tag.name 非空
|
||
- links: 数组,长度 1-10,每个 link.url 和 link.type 非空
|
||
|
||
// 可选字段
|
||
- nameEn: 字符串,长度 1-200
|
||
- descriptionEn: 字符串,长度 10-500
|
||
- content/contentEn: 文本类型,支持 Markdown,最大 10000 字符
|
||
- status: 枚举值 "ACTIVE" 或 "ARCHIVED",默认 "ACTIVE"
|
||
- source: 字符串,标识数据来源
|
||
|
||
// URL 格式
|
||
- links[*].url: 必须是有效的 HTTP/HTTPS URL
|
||
- links[*].type: 必须是 LinkType 枚举值之一
|
||
```
|
||
|
||
#### Webhook 批量操作限制
|
||
|
||
```typescript
|
||
// 批量操作
|
||
- projects: 数组,长度 1-100
|
||
- apiKey: 必须与环境变量 WEBHOOK_API_KEY 匹配
|
||
```
|
||
|
||
---
|
||
|
||
## 6. 使用示例
|
||
|
||
### 6.1 完整的工作流示例
|
||
|
||
```javascript
|
||
// 1. 创建/更新项目
|
||
const createResponse = await fetch('https://your-domain.com/api/webhook/projects', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'x-api-key': 'your-api-key'
|
||
},
|
||
body: JSON.stringify({
|
||
apiKey: 'your-api-key',
|
||
projects: [{
|
||
name: 'My AI Project',
|
||
nameEn: 'My AI Project',
|
||
description: '一个创新的 AI 项目',
|
||
descriptionEn: 'An innovative AI project',
|
||
status: 'ACTIVE',
|
||
source: 'MANUAL',
|
||
tags: [
|
||
{ name: 'AI', nameEn: 'Artificial Intelligence' },
|
||
{ name: '机器学习', nameEn: 'Machine Learning' }
|
||
],
|
||
links: [
|
||
{ type: 'GITHUB', url: 'https://github.com/user/project', title: 'GitHub' },
|
||
{ type: 'WEBSITE', url: 'https://project.com', title: 'Website' }
|
||
]
|
||
}]
|
||
})
|
||
});
|
||
|
||
const createResult = await createResponse.json();
|
||
console.log('创建结果:', createResult);
|
||
// { success: true, processed: 1, created: 1, updated: 0, failed: 0, errors: [] }
|
||
|
||
// 2. 获取项目详情
|
||
const slug = 'my-ai-project'; // 根据 nameEn 自动生成
|
||
const getResponse = await fetch(`https://your-domain.com/api/projects/${slug}`);
|
||
const getResult = await getResponse.json();
|
||
console.log('项目详情:', getResult.data);
|
||
|
||
// 3. 删除项目
|
||
const deleteResponse = await fetch(`https://your-domain.com/api/projects/${slug}`, {
|
||
method: 'DELETE',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'x-api-key': 'your-api-key'
|
||
}
|
||
});
|
||
const deleteResult = await deleteResponse.json();
|
||
console.log('删除结果:', deleteResult);
|
||
```
|
||
|
||
### 6.2 批量创建项目示例
|
||
|
||
```javascript
|
||
const projects = [
|
||
{
|
||
name: '项目 A',
|
||
nameEn: 'Project A',
|
||
description: '项目 A 的描述',
|
||
descriptionEn: 'Description of Project A',
|
||
tags: [{ name: '分类1' }],
|
||
links: [{ type: 'GITHUB', url: 'https://github.com/user/a' }]
|
||
},
|
||
{
|
||
name: '项目 B',
|
||
nameEn: 'Project B',
|
||
description: '项目 B 的描述',
|
||
descriptionEn: 'Description of Project B',
|
||
tags: [{ name: '分类2' }],
|
||
links: [{ type: 'GITHUB', url: 'https://github.com/user/b' }]
|
||
}
|
||
];
|
||
|
||
const response = await fetch('https://your-domain.com/api/webhook/projects', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'x-api-key': 'your-api-key'
|
||
},
|
||
body: JSON.stringify({
|
||
apiKey: 'your-api-key',
|
||
projects: projects
|
||
})
|
||
});
|
||
|
||
const result = await response.json();
|
||
console.log('批量创建结果:', result);
|
||
// { success: true, processed: 2, created: 2, updated: 0, failed: 0, errors: [] }
|
||
```
|
||
|
||
---
|
||
|
||
## 7. 注意事项
|
||
|
||
### 7.1 Slug 生成规则
|
||
|
||
项目 slug 根据以下规则自动生成:
|
||
|
||
1. 优先使用 `nameEn`(英文)
|
||
2. 如果 `nameEn` 不存在,使用 `name`(中文)
|
||
3. 转换为小写
|
||
4. 空格替换为连字符 `-`
|
||
5. 移除特殊字符
|
||
|
||
示例:
|
||
- `nameEn: "LangChain"` → `slug: "langchain"`
|
||
- `name: "大语言模型"` → `slug: "大语言模型"` (会进行拼音转换)
|
||
|
||
### 7.2 标签去重
|
||
|
||
- 标签的 `name` 字段在数据库中是唯一的
|
||
- 如果创建已存在的标签,会自动复用现有标签
|
||
- 标签的 `slug` 也是唯一的,会根据 `nameEn` 或 `name` 自动生成
|
||
|
||
### 7.3 链接去重
|
||
|
||
- 同一个项目不能有重复的 URL
|
||
- 通过 `projectId` + `url` 的组合保证唯一性
|
||
|
||
### 7.4 更新策略
|
||
|
||
- Webhook 使用 **替换策略** 更新标签和链接
|
||
- 不是增量更新,而是完全替换
|
||
- 更新时会删除旧的标签/链接关联,创建新的
|
||
|
||
---
|
||
|
||
## 8. 附录
|
||
|
||
### 8.1 环境变量配置
|
||
|
||
```bash
|
||
# .env
|
||
WEBHOOK_API_KEY=your-secret-api-key-here
|
||
DATABASE_URL=postgresql://user:password@host:5432/dbname?sslmode=require
|
||
```
|
||
|
||
### 8.2 相关文档
|
||
|
||
- [数据库 Schema](../prisma/schema.prisma)
|
||
- [数据验证规则](../src/lib/validations.ts)
|
||
- [数据新增流程设计](./data-ingestion-flow.md)
|
||
- [项目发现系统](../.claude/commands/discover-projects.md)
|
||
- [Discovery Service](../src/app/api/discovery/lib/discovery-service.ts)
|
||
|
||
---
|
||
|
||
**文档版本**: v2.0.0
|
||
**最后更新**: 2025-01-20
|
||
**维护者**: AI 项目导航站团队
|