Commit 1992b76a by Archer Committed by GitHub

perf: openapi doc (#7025)

* perf: openapi doc

* fix: resolve openapi docs mdx build
parent 81b0cad5
......@@ -10,87 +10,86 @@ description: FastGPT OpenAPI Application Interface
![alt text](../../public/imgs/image-120.png)
## Log API
### Get Cumulative Run Results
### Get Application Overall Statistics
<Tabs items={["Request Example","Response Example","Parameters"]}>
<Tab value="Request Example">
<Tab value="Request Example">
```bash
curl --location --request GET 'https://cloud.fastgpt.cn/api/proApi/core/app/logs/getTotalData?appId=68c46a70d950e8850ae564ba' \
```bash
curl --location --request GET 'https://cloud.fastgpt.cn/api/proApi/core/app/logs/getTotalData?appId=68c46a70d950e8850ae564ba' \
--header 'Authorization: Bearer apikey'
```
</Tab>
<Tab value="Response Example">
```bash
{
"code": 200,
"statusText": "",
"message": "",
"data": {
"totalUsers": 0,
"totalChats": 0,
"totalPoints": 0
}
}
```
```
</Tab>
</Tab>
<Tab value="Parameters">
<Tab value="Response Example">
<div>
**Request Parameters:**
- appId: Application ID
```bash
{
"code": 200,
"statusText": "",
"message": "",
"data": {
"totalUsers": 0,
"totalChats": 0,
"totalPoints": 0
}
}
```
**Response Parameters:**
- totalUsers: Total number of users
- totalChats: Total number of conversations
- totalPoints: Total points consumed
</div>
</Tab>
</Tab>
<Tab value="Parameters">
**Request Parameters:**
- appId: Application ID
**Response Parameters:**
- totalUsers: Total number of users
- totalChats: Total number of conversations
- totalPoints: Total points consumed
</Tab>
</Tabs>
### Get Application Log Dashboard
### Get Application Chart Data
<Tabs items={["Request Example","Response Example","Parameters"]}>
<Tab value="Request Example">
```bash
```bash
curl --location --request POST 'https://cloud.fastgpt.cn/api/proApi/core/app/logs/getChartData' \
--header 'Authorization: Bearer apikey' \
--header 'Content-Type: application/json' \
--data-raw '{
"appId": "68c46a70d950e8850ae564ba",
"dateStart": "2025-09-19T16:00:00.000Z",
"dateEnd": "2025-09-27T15:59:59.999Z",
"offset": 1,
"source": [
"test",
"online",
"share",
"api",
"cronJob",
"team",
"feishu",
"official_account",
"wecom",
"mcp"
],
"userTimespan": "day",
"chatTimespan": "day",
"appTimespan": "day"
"appId": "68c46a70d950e8850ae564ba",
"dateStart": "2025-09-19T16:00:00.000Z",
"dateEnd": "2025-09-27T15:59:59.999Z",
"offset": 1,
"source": [
"test",
"online",
"share",
"api",
"cronJob",
"team",
"feishu",
"official_account",
"wecom",
"mcp"
],
"userTimespan": "day",
"chatTimespan": "day",
"appTimespan": "day"
}'
```
```
</Tab>
......@@ -156,14 +155,15 @@ curl --location --request POST 'https://cloud.fastgpt.cn/api/proApi/core/app/log
<Tab value="Parameters">
**Request Parameters:**
- appId: Application ID
- dateStart: Start time
- dateEnd: End time
- source: Log source
- offset: User retention offset
- userTimespan: User data timespan //day|week|month|quarter
- chatTimespan: Chat data timespan //day|week|month|quarter
- appTimespan: Application data timespan //day|week|month|quarter
- offset: User retention offset. The unit follows userTimespan
- userTimespan: User data timespan //day|week|month|quarter
- chatTimespan: Chat data timespan //day|week|month|quarter
- appTimespan: Application data timespan //day|week|month|quarter
**Response Parameters:**
......
......@@ -10,87 +10,86 @@ description: FastGPT OpenAPI 应用接口
![alt text](../../public/imgs/image-120.png)
## 日志接口
### 获取累积运行结果
### 获取应用总体数据统计
<Tabs items={["请求示例","响应示例","参数说明"]}>
<Tab value="请求示例">
<Tab value="请求示例">
```bash
curl --location --request GET 'https://cloud.fastgpt.cn/api/proApi/core/app/logs/getTotalData?appId=68c46a70d950e8850ae564ba' \
```bash
curl --location --request GET 'https://cloud.fastgpt.cn/api/proApi/core/app/logs/getTotalData?appId=68c46a70d950e8850ae564ba' \
--header 'Authorization: Bearer apikey'
```
</Tab>
<Tab value="响应示例">
```bash
{
"code": 200,
"statusText": "",
"message": "",
"data": {
"totalUsers": 0,
"totalChats": 0,
"totalPoints": 0
}
}
```
```
</Tab>
</Tab>
<Tab value="参数说明">
<Tab value="响应示例">
<div>
**入参:**
- appId: 应用Id
```bash
{
"code": 200,
"statusText": "",
"message": "",
"data": {
"totalUsers": 0,
"totalChats": 0,
"totalPoints": 0
}
}
```
**出参:**
- totalUsers: 累积使用用户数量
- totalChats: 累积对话数量
- totalPoints: 累积积分消耗
</div>
</Tab>
</Tab>
<Tab value="参数说明">
**入参:**
- appId: 应用 ID
**出参:**
- totalUsers: 累积使用用户数量
- totalChats: 累积对话数量
- totalPoints: 累积积分消耗
</Tab>
</Tabs>
### 获取应用日志看板
### 获取应用图表数据
<Tabs items={["请求示例","响应示例","参数说明"]}>
<Tab value="请求示例">
```bash
```bash
curl --location --request POST 'https://cloud.fastgpt.cn/api/proApi/core/app/logs/getChartData' \
--header 'Authorization: Bearer apikey' \
--header 'Content-Type: application/json' \
--data-raw '{
"appId": "68c46a70d950e8850ae564ba",
"dateStart": "2025-09-19T16:00:00.000Z",
"dateEnd": "2025-09-27T15:59:59.999Z",
"offset": 1,
"source": [
"test",
"online",
"share",
"api",
"cronJob",
"team",
"feishu",
"official_account",
"wecom",
"mcp"
],
"userTimespan": "day",
"chatTimespan": "day",
"appTimespan": "day"
"appId": "68c46a70d950e8850ae564ba",
"dateStart": "2025-09-19T16:00:00.000Z",
"dateEnd": "2025-09-27T15:59:59.999Z",
"offset": 1,
"source": [
"test",
"online",
"share",
"api",
"cronJob",
"team",
"feishu",
"official_account",
"wecom",
"mcp"
],
"userTimespan": "day",
"chatTimespan": "day",
"appTimespan": "day"
}'
```
```
</Tab>
......@@ -156,14 +155,15 @@ curl --location --request POST 'https://cloud.fastgpt.cn/api/proApi/core/app/log
<Tab value="参数说明">
**入参:**
- appId: 应用Id
- appId: 应用 ID
- dateStart: 开始时间
- dateEnd: 结束时间
- source: 日志来源
- offset: 用户留存偏移量
- userTimespan: 用户数据时间跨度 //day|week|month|quarter
- chatTimespan: 对话数据时间跨度 //day|week|month|quarter
- appTimespan: 应用数据时间跨度 //day|week|month|quarter
- offset: 用户留存偏移量,单位随 userTimespan 变化
- userTimespan: 用户数据时间跨度 //day|week|month|quarter
- chatTimespan: 对话数据时间跨度 //day|week|month|quarter
- appTimespan: 应用数据时间跨度 //day|week|month|quarter
**出参:**
......@@ -192,4 +192,4 @@ curl --location --request POST 'https://cloud.fastgpt.cn/api/proApi/core/app/log
</Tab>
</Tabs>
\ No newline at end of file
</Tabs>
......@@ -3,15 +3,22 @@ title: OpenAPI Introduction
description: FastGPT OpenAPI Introduction
---
## Automated API Documentation
## Latest OpenAPI Documentation
The automated API documentation covers all endpoints in the current version, regardless of whether they can be called via API Key.
All future endpoints will be auto-generated, with documentation continuously improved.
These are the FastGPT APIs published for external use. If you are integrating with FastGPT externally, use the endpoints in this documentation and authenticate with an API key.
- [China Mainland API Documentation](https://cloud.fastgpt.cn/openapi)
- [International API Documentation](https://cloud.fastgpt.io/openapi)
## Developer API Documentation
The developer API documentation covers all endpoints in the current version, regardless of whether they can be called via API key.
All future endpoints will be auto-generated, with documentation continuously improved.
- [China Mainland API Documentation](https://cloud.fastgpt.cn/devapidoc)
- [International API Documentation](https://cloud.fastgpt.io/devapidoc)
## Usage Guide
FastGPT OpenAPI lets you authenticate with an API Key to access FastGPT services and resources -- such as calling app chat endpoints, uploading knowledge base data, search testing, and more. For compatibility and security reasons, not all endpoints support API Key access.
......@@ -28,11 +35,10 @@ FastGPT has **2 types** of API Keys: a global key (cannot directly call app chat
We recommend using `app-specific keys` only for app or chat-related endpoints, and `global keys` for everything else.
| Global Key | App-Specific Key |
| --------------------- | --------------------- |
| Global Key | App-Specific Key |
| --------------------------------------- | --------------------------------------- |
| ![](../../public/imgs/fastgpt-api2.jpg) | ![](../../public/imgs/fastgpt-api1.jpg) |
## Basic Configuration
In OpenAPI, all endpoints authenticate via Header.Authorization.
......
......@@ -3,18 +3,25 @@ title: OpenAPI 介绍
description: FastGPT OpenAPI 介绍
---
## 自动化 API 文档
## 最新 OpenAPI 文档
自动化 API 文档为当前版本系统的所有接口,不区分是否可通过 API Key 调用。
后续所有接口都将做自动化生成,会逐步完善文档。
这部分接口是 FastGPT 对外提供 API 能力的文档,如果你是外部使用 FastGPT 需使用这个文档里的接口,并通过 apikey 鉴权。
- [中国大陆版 API 文档](https://cloud.fastgpt.cn/openapi)
- [国际版 API 文档](https://cloud.fastgpt.io/openapi)
## 开发者 API 文档
开发者 API 文档为当前版本系统的所有接口,不区分是否可通过 API Key 调用。
后续所有接口都将做自动化生成,会逐步完善文档。
- [中国大陆版 API 文档](https://cloud.fastgpt.cn/devapidoc)
- [国际版 API 文档](https://cloud.fastgpt.io/devapidoc)
## 使用说明
FasGPT OpenAPI 接口允许你使用 Api Key 进行鉴权,从而操作 FastGPT 上的相关服务和资源,例如:调用应用对话接口、上传知识库数据、搜索测试等等。出于兼容性和安全考虑,并不是所有的接口都允许通过 Api Key 访问。
FastGPT OpenAPI 接口允许你使用 API Key 进行鉴权,从而操作 FastGPT 上的相关服务和资源,例如:调用应用对话接口、上传知识库数据、搜索测试等等。出于兼容性和安全考虑,并不是所有的接口都允许通过 API Key 访问。
## 如何查看 BaseURL
......@@ -22,17 +29,16 @@ FasGPT OpenAPI 接口允许你使用 Api Key 进行鉴权,从而操作 FastGPT
![](../../public/imgs/fastgpt-api-baseurl.png)
## 如何获取 Api Key
## 如何获取 API Key
FastGPT 的 API Key **有 2 类**,一类是全局通用的 key (无法直接调用应用对话);一类是携带了 AppId 也就是有应用标记的 key (可直接调用应用对话)。
我们建议,仅操作应用或者对话的相关接口使用 `应用特定key`,其他接口使用 `通用key`。
| 通用key | 应用特定 key |
| --------------------- | --------------------- |
| 通用 key | 应用特定 key |
| --------------------------------------- | --------------------------------------- |
| ![](../../public/imgs/fastgpt-api2.jpg) | ![](../../public/imgs/fastgpt-api1.jpg) |
## 基本配置
OpenAPI 中,所有的接口都通过 Header.Authorization 进行鉴权。
......@@ -65,7 +71,7 @@ curl --location --request POST 'http://localhost:3000/api/v1/chat/completions' \
## 自定义用户 ID
`v4.8.13`后支持传入自定义的用户 ID, 并且存入历史记录中。
`v4.8.13` 后支持传入自定义的用户 ID, 并且存入历史记录中。
```sh
curl --location --request POST 'http://localhost:3000/api/v1/chat/completions' \
......
......@@ -145,16 +145,16 @@
"content/guide/workspace/team/invitation_link.mdx": "2026-05-07T15:06:40+08:00",
"content/guide/workspace/team/team_roles_permissions.en.mdx": "2026-05-07T15:06:40+08:00",
"content/guide/workspace/team/team_roles_permissions.mdx": "2026-05-07T15:06:40+08:00",
"content/openapi/app.en.mdx": "2026-04-26T21:08:47+08:00",
"content/openapi/app.mdx": "2026-04-26T21:08:47+08:00",
"content/openapi/chat.en.mdx": "2026-04-26T21:08:47+08:00",
"content/openapi/chat.mdx": "2026-04-26T21:08:47+08:00",
"content/openapi/dataset.en.mdx": "2026-05-07T15:06:40+08:00",
"content/openapi/dataset.mdx": "2026-05-07T15:06:40+08:00",
"content/openapi/app.en.mdx": "2026-05-29T19:08:31+08:00",
"content/openapi/app.mdx": "2026-05-29T19:08:31+08:00",
"content/openapi/chat.en.mdx": "2026-05-29T19:08:31+08:00",
"content/openapi/chat.mdx": "2026-05-29T19:08:31+08:00",
"content/openapi/dataset.en.mdx": "2026-05-29T19:08:31+08:00",
"content/openapi/dataset.mdx": "2026-05-29T19:08:31+08:00",
"content/openapi/index.en.mdx": "2026-04-26T21:08:47+08:00",
"content/openapi/index.mdx": "2026-04-26T21:08:47+08:00",
"content/openapi/intro.en.mdx": "2026-04-26T21:08:47+08:00",
"content/openapi/intro.mdx": "2026-04-26T21:08:47+08:00",
"content/openapi/intro.en.mdx": "2026-05-29T19:08:31+08:00",
"content/openapi/intro.mdx": "2026-05-29T19:08:31+08:00",
"content/openapi/share.en.mdx": "2026-04-26T21:08:47+08:00",
"content/openapi/share.mdx": "2026-04-26T21:08:47+08:00",
"content/self-host/config/env.en.mdx": "2026-05-27T12:17:46+08:00",
......@@ -280,8 +280,8 @@
"content/self-host/upgrading/4-15/4150.mdx": "2026-05-20T17:52:26+08:00",
"content/self-host/upgrading/4-15/41502.en.mdx": "2026-05-25T11:21:30+08:00",
"content/self-host/upgrading/4-15/41502.mdx": "2026-05-25T11:21:30+08:00",
"content/self-host/upgrading/4-15/41503.en.mdx": "2026-05-28T13:54:38+08:00",
"content/self-host/upgrading/4-15/41503.mdx": "2026-05-28T16:06:08+08:00",
"content/self-host/upgrading/4-15/41503.en.mdx": "2026-05-28T16:21:09+08:00",
"content/self-host/upgrading/4-15/41503.mdx": "2026-05-28T16:21:09+08:00",
"content/self-host/upgrading/outdated/40.en.mdx": "2026-04-26T21:08:47+08:00",
"content/self-host/upgrading/outdated/40.mdx": "2026-04-26T21:08:47+08:00",
"content/self-host/upgrading/outdated/41.en.mdx": "2026-04-26T21:08:47+08:00",
......
import { createDocument } from 'zod-openapi';
import { openAPIPaths } from '../path';
import type { OpenAPIPath } from '../type';
import { ApiKeyTagMap, ApiKeyTagNameMap, apiKeyTagGroups } from './tag';
type DefinedOpenAPIPath = NonNullable<OpenAPIPath>;
/**
* API key 文档只展示显式打了 ApiKeyTagMap 标签的 operation。
*
* 主文档继续保留原有业务标签;这里在生成 API key 专用文档时过滤并重写 tags,
* 避免没有开放的同模块接口被带入 /openapi。
*/
const pickApiKeyPathsByTags = (paths: DefinedOpenAPIPath) => {
const apiKeyTags = new Set<string>(Object.values(ApiKeyTagMap));
const pickedPaths: DefinedOpenAPIPath = {};
for (const [path, pathItem] of Object.entries(paths)) {
const pickedPathItem: NonNullable<DefinedOpenAPIPath[string]> = {};
for (const [method, operation] of Object.entries(pathItem ?? {})) {
const tags = (operation as { tags?: string[] } | undefined)?.tags ?? [];
const pickedTags = tags.filter((tag) => apiKeyTags.has(tag));
if (pickedTags.length > 0) {
pickedPathItem[method as keyof typeof pickedPathItem] = {
...(operation as object),
tags: [...new Set(pickedTags.map((tag) => ApiKeyTagNameMap[tag]))]
} as never;
}
}
if (Object.keys(pickedPathItem).length > 0) {
pickedPaths[path] = pickedPathItem;
}
}
return pickedPaths;
};
const apiKeyOpenAPIPaths = pickApiKeyPathsByTags(openAPIPaths);
export const apiDocOpenAPIDocument = createDocument({
openapi: '3.1.0',
info: {
title: 'FastGPT OpenAPI',
version: '0.1.0',
description: 'FastGPT 开放 API 文档,仅包含支持 API key 鉴权的接口。'
},
paths: apiKeyOpenAPIPaths,
servers: [{ url: '/api' }],
components: {
securitySchemes: {
ApiKeyAuth: {
type: 'http',
scheme: 'bearer',
bearerFormat: 'API Key',
description: '在 Authorization 请求头中传入 Bearer <apiKey>。'
}
}
},
security: [{ ApiKeyAuth: [] }],
'x-tagGroups': apiKeyTagGroups
});
export const ApiKeyTagMap = {
appLog: 'apiKey:appLog',
chatHistory: 'apiKey:chatHistory',
chatSession: 'apiKey:chatSession',
chat: 'apiKey:chat',
dataset: 'apiKey:dataset',
datasetCollection: 'apiKey:datasetCollection',
datasetCollectionCreate: 'apiKey:datasetCollectionCreate',
datasetData: 'apiKey:datasetData',
datasetDataIndex: 'apiKey:datasetDataIndex',
datasetOther: 'apiKey:datasetOther'
};
export const ApiKeyTagNameMap: Record<string, string> = {
[ApiKeyTagMap.appLog]: '应用日志',
[ApiKeyTagMap.chatHistory]: '历史记录管理',
[ApiKeyTagMap.chatSession]: '会话管理',
[ApiKeyTagMap.chat]: '对话管理',
[ApiKeyTagMap.dataset]: '知识库管理',
[ApiKeyTagMap.datasetCollection]: '集合管理',
[ApiKeyTagMap.datasetCollectionCreate]: '集合创建',
[ApiKeyTagMap.datasetData]: '数据管理',
[ApiKeyTagMap.datasetDataIndex]: '索引管理',
[ApiKeyTagMap.datasetOther]: '其他'
};
export const apiKeyTagGroups = [
{
name: '应用管理',
tags: [ApiKeyTagNameMap[ApiKeyTagMap.appLog]]
},
{
name: '应用对话',
tags: [
ApiKeyTagNameMap[ApiKeyTagMap.chatHistory],
ApiKeyTagNameMap[ApiKeyTagMap.chatSession],
ApiKeyTagNameMap[ApiKeyTagMap.chat]
]
},
{
name: '知识库',
tags: [
ApiKeyTagNameMap[ApiKeyTagMap.dataset],
ApiKeyTagNameMap[ApiKeyTagMap.datasetCollection],
ApiKeyTagNameMap[ApiKeyTagMap.datasetCollectionCreate],
ApiKeyTagNameMap[ApiKeyTagMap.datasetData],
ApiKeyTagNameMap[ApiKeyTagMap.datasetDataIndex],
ApiKeyTagNameMap[ApiKeyTagMap.datasetOther]
]
}
];
......@@ -191,7 +191,7 @@ export const GetChartDataBodySchema = z.object({
}),
offset: z.number().meta({
example: 1,
description: '时区偏移量'
description: '用户留存偏移量,单位随 userTimespan 变化'
}),
userTimespan: z.nativeEnum(AppLogTimespanEnum).meta({
example: AppLogTimespanEnum.day,
......
import type { OpenAPIPath } from '../../../type';
import { TagsMap } from '../../../tag';
import { ApiKeyTagMap } from '../../../apikey/tag';
import z from 'zod';
import {
GetAppChatLogsBodySchema,
......@@ -113,7 +114,7 @@ export const AppLogPath: OpenAPIPath = {
get: {
summary: '获取应用总体数据统计',
description: '获取应用的总体数据统计,包括总用户数、总对话数、总积分消耗',
tags: [TagsMap.appLog],
tags: [TagsMap.appLog, ApiKeyTagMap.appLog],
requestParams: {
query: GetTotalDataQuerySchema
},
......@@ -133,7 +134,7 @@ export const AppLogPath: OpenAPIPath = {
post: {
summary: '获取应用图表数据',
description: '获取应用的图表统计数据,包括用户数据、对话数据、应用数据的时序统计',
tags: [TagsMap.appLog],
tags: [TagsMap.appLog, ApiKeyTagMap.appLog],
requestBody: {
content: {
'application/json': {
......
import type { OpenAPIPath } from '../../../type';
import { TagsMap } from '../../../tag';
import { ApiKeyTagMap } from '../../../apikey/tag';
import { ChatTestPropsSchema, CompletionsPropsSchema, CompletionsResponseSchema } from './api';
/* =============== Request examples =============== */
......@@ -280,7 +281,7 @@ data: [DONE]`;
export const ChatCompletionPath: OpenAPIPath = {
'/v1/chat/completions': {
post: {
tags: [TagsMap.chatController],
tags: [TagsMap.chatController, ApiKeyTagMap.chat],
summary: '请求对话 Agent 和工作流',
description: `v1 对话接口兼容 GPT 的接口。如果你的项目使用的是标准的 GPT 官方接口,可以直接通过修改 BaseUrl 和 Authorization 来访问 FastGPT 应用。
......
import type { OpenAPIPath } from '../../../type';
import { TagsMap } from '../../../tag';
import { ApiKeyTagMap } from '../../../apikey/tag';
import {
StopV2ChatSchema,
StopV2ChatResponseSchema,
......@@ -10,9 +11,9 @@ import {
export const ChatControllerPath: OpenAPIPath = {
'/core/chat/init': {
get: {
summary: '初始化聊天',
description: '初始化聊天',
tags: [TagsMap.chatController],
summary: '获取会话框基本信息',
description: '',
tags: [TagsMap.chatController, ApiKeyTagMap.chatSession],
requestParams: {
query: InitChatQuerySchema
},
......
import type { OpenAPIPath } from '../../../type';
import { TagsMap } from '../../../tag';
import { ApiKeyTagMap } from '../../../apikey/tag';
import {
UpdateFeedbackReadStatusBodySchema,
UpdateFeedbackReadStatusResponseSchema,
......@@ -18,7 +19,7 @@ export const ChatFeedbackPath: OpenAPIPath = {
post: {
summary: '添加/更新用户反馈',
description: '用户对消息添加或更新好评/差评反馈',
tags: [TagsMap.chatFeedback],
tags: [TagsMap.chatFeedback, ApiKeyTagMap.chat],
requestBody: {
content: {
'application/json': {
......
import type { OpenAPIPath } from '../../../type';
import { TagsMap } from '../../../tag';
import { ApiKeyTagMap } from '../../../apikey/tag';
import {
GetHistoriesBodySchema,
GetHistoriesResponseSchema,
......@@ -15,9 +16,9 @@ import {
export const ChatHistoryPath: OpenAPIPath = {
'/core/chat/history/getHistories': {
post: {
summary: '获取对话历史列表',
description: '分页获取指定应用的对话历史记录',
tags: [TagsMap.chatHistory],
summary: '获取历史记录列表',
description: '分页获取指定应用的历史记录',
tags: [TagsMap.chatHistory, ApiKeyTagMap.chatHistory],
requestBody: {
content: {
'application/json': {
......@@ -27,7 +28,7 @@ export const ChatHistoryPath: OpenAPIPath = {
},
responses: {
200: {
description: '成功获取对话历史列表',
description: '成功获取历史记录列表',
content: {
'application/json': {
schema: GetHistoriesResponseSchema
......@@ -39,7 +40,7 @@ export const ChatHistoryPath: OpenAPIPath = {
},
'/core/chat/history/getHistoryStatus': {
post: {
summary: '批量获取对话状态(生成中/已读)',
summary: '批量获取历史记录状态(生成中/已读)',
description:
'按 chatId 列表返回 chatGenerateStatus、hasBeenRead、updateTime,用于侧栏轻量轮询同步',
tags: [TagsMap.chatHistory],
......@@ -64,7 +65,7 @@ export const ChatHistoryPath: OpenAPIPath = {
},
'/core/chat/history/markRead': {
post: {
summary: '标记对话已读',
summary: '标记历史记录已读',
description: '用户在本页看完回复后调用,同步 Mongo hasBeenRead',
tags: [TagsMap.chatHistory],
requestBody: {
......@@ -83,9 +84,9 @@ export const ChatHistoryPath: OpenAPIPath = {
},
'/core/chat/history/updateHistory': {
put: {
summary: '修改对话历史',
description: '修改对话历史的标题、自定义标题或置顶状态',
tags: [TagsMap.chatHistory],
summary: '修改历史记录',
description: '修改历史记录的标题、自定义标题或置顶状态',
tags: [TagsMap.chatHistory, ApiKeyTagMap.chatHistory],
requestBody: {
content: {
'application/json': {
......@@ -95,49 +96,45 @@ export const ChatHistoryPath: OpenAPIPath = {
},
responses: {
200: {
description: '成功修改对话历史'
description: '成功修改历史记录'
}
}
}
},
'/core/chat/history/delHistory': {
delete: {
summary: '删除单个对话历史',
description: '软删除指定的单个对话记录',
tags: [TagsMap.chatHistory],
requestBody: {
content: {
'application/json': {
schema: DelChatHistorySchema
}
}
summary: '删除单个历史记录',
description: '软删除指定的单个历史记录',
tags: [TagsMap.chatHistory, ApiKeyTagMap.chatHistory],
requestParams: {
query: DelChatHistorySchema
},
responses: {
200: {
description: '成功删除对话'
description: '成功删除历史记录'
}
}
}
},
'/core/chat/history/clearHistories': {
delete: {
summary: '清空应用对话历史',
description: '清空指定应用的所有对话记录(软删除)',
tags: [TagsMap.chatHistory],
summary: '清空应用历史记录',
description: '清空指定应用的所有历史记录(软删除)',
tags: [TagsMap.chatHistory, ApiKeyTagMap.chatHistory],
requestParams: {
query: ClearChatHistoriesSchema
},
responses: {
200: {
description: '成功清空对话历史'
description: '成功清空历史记录'
}
}
}
},
'/core/chat/history/batchDelete': {
post: {
summary: '批量删除对话历史',
description: '批量删除指定应用的多个对话记录(真实删除),需应用日志权限。',
summary: '批量删除历史记录',
description: '批量删除指定应用的多个历史记录(真实删除),需应用日志权限。',
tags: [TagsMap.chatHistory],
requestBody: {
content: {
......@@ -148,7 +145,7 @@ export const ChatHistoryPath: OpenAPIPath = {
},
responses: {
200: {
description: '成功删除对话'
description: '成功删除历史记录'
}
}
}
......
import { TagsMap } from '../../../tag';
import { ApiKeyTagMap } from '../../../apikey/tag';
import type { OpenAPIPath } from '../../../type';
import {
CreateApiCollectionBodySchema,
......@@ -22,7 +23,7 @@ export const DatasetCollectionCreatePath: OpenAPIPath = {
post: {
summary: '创建空集合/目录',
description: '创建空数据集合或者目录',
tags: [TagsMap.datasetCollectionCrteate],
tags: [TagsMap.datasetCollectionCrteate, ApiKeyTagMap.datasetCollectionCreate],
requestBody: {
content: {
'application/json': {
......@@ -92,7 +93,7 @@ export const DatasetCollectionCreatePath: OpenAPIPath = {
summary: '上传本地文件创建集合',
description:
'通过 multipart/form-data 上传文件,自动存储至 S3 后创建集合并触发训练。`file` 字段为二进制文件,`data` 字段为 JSON 序列化的集合参数对象',
tags: [TagsMap.datasetCollectionCrteate],
tags: [TagsMap.datasetCollectionCrteate, ApiKeyTagMap.datasetCollectionCreate],
requestBody: {
content: {
'multipart/form-data': {
......@@ -118,7 +119,7 @@ export const DatasetCollectionCreatePath: OpenAPIPath = {
post: {
summary: '通过链接创建集合',
description: '抓取指定 URL 内容创建集合并触发训练',
tags: [TagsMap.datasetCollectionCrteate],
tags: [TagsMap.datasetCollectionCrteate, ApiKeyTagMap.datasetCollectionCreate],
requestBody: {
content: {
'application/json': {
......@@ -141,7 +142,7 @@ export const DatasetCollectionCreatePath: OpenAPIPath = {
post: {
summary: '通过文本创建集合',
description: '将文本内容存储为文件后创建集合并触发训练',
tags: [TagsMap.datasetCollectionCrteate],
tags: [TagsMap.datasetCollectionCrteate, ApiKeyTagMap.datasetCollectionCreate],
requestBody: {
content: {
'application/json': {
......@@ -165,7 +166,7 @@ export const DatasetCollectionCreatePath: OpenAPIPath = {
summary: '通过 API 数据集创建集合(V1)',
description: '根据 apiFileId 从第三方 API 数据源拉取单个文件并创建集合',
deprecated: true,
tags: [TagsMap.datasetCollectionCrteate],
tags: [TagsMap.datasetCollectionCrteate, ApiKeyTagMap.datasetCollectionCreate],
requestBody: {
content: {
'application/json': {
......
import type { OpenAPIPath } from '../../../type';
import { TagsMap } from '../../../tag';
import { ApiKeyTagMap } from '../../../apikey/tag';
import {
DeleteCollectionBodySchema,
DeleteCollectionQuerySchema,
......@@ -22,7 +23,7 @@ export const DatasetCollectionPath: OpenAPIPath = {
delete: {
summary: '删除集合',
description: '删除一个或多个集合及其子集合,支持通过 query.id 或 body.collectionIds 指定',
tags: [TagsMap.datasetCollection],
tags: [TagsMap.datasetCollection, ApiKeyTagMap.datasetCollection],
requestParams: {
query: DeleteCollectionQuerySchema
},
......@@ -44,7 +45,7 @@ export const DatasetCollectionPath: OpenAPIPath = {
get: {
summary: '获取集合详情',
description: '获取集合详细信息,包括索引数量、错误数量、文件信息等',
tags: [TagsMap.datasetCollection],
tags: [TagsMap.datasetCollection, ApiKeyTagMap.datasetCollection],
requestParams: {
query: GetCollectionDetailQuerySchema
},
......@@ -59,7 +60,7 @@ export const DatasetCollectionPath: OpenAPIPath = {
post: {
summary: '获取集合列表(分页)',
description: '获取数据集集合列表,支持分页、搜索、标签过滤',
tags: [TagsMap.datasetCollection],
tags: [TagsMap.datasetCollection, ApiKeyTagMap.datasetCollection],
requestBody: {
content: {
'application/json': {
......@@ -97,7 +98,7 @@ export const DatasetCollectionPath: OpenAPIPath = {
post: {
summary: '更新数据集集合信息',
description: '更新数据集集合信息,支持通过集合ID或数据集ID+外部文件ID定位集合',
tags: [TagsMap.datasetCollection],
tags: [TagsMap.datasetCollection, ApiKeyTagMap.datasetCollection],
requestBody: {
content: {
'application/json': {
......
import type { OpenAPIPath } from '../../../type';
import { TagsMap } from '../../../tag';
import { ApiKeyTagMap } from '../../../apikey/tag';
import {
GetDatasetDataDetailQuerySchema,
UpdateDatasetDataBodySchema,
......@@ -25,7 +26,7 @@ export const DatasetDataPath: OpenAPIPath = {
post: {
summary: '获取数据列表',
description: '分页查询集合内的数据列表,支持关键词搜索,包含图片预览 URL',
tags: [TagsMap.datasetData],
tags: [TagsMap.datasetData, ApiKeyTagMap.datasetData],
requestBody: {
content: {
'application/json': {
......@@ -49,7 +50,7 @@ export const DatasetDataPath: OpenAPIPath = {
get: {
summary: '获取数据详情',
description: '获取单条数据集数据的详细信息,包括向量索引',
tags: [TagsMap.datasetData],
tags: [TagsMap.datasetData, ApiKeyTagMap.datasetData],
requestParams: {
query: GetDatasetDataDetailQuerySchema
},
......@@ -70,7 +71,7 @@ export const DatasetDataPath: OpenAPIPath = {
put: {
summary: '更新数据',
description: '更新数据集数据的 q、a 和向量索引,触发重新向量化',
tags: [TagsMap.datasetData],
tags: [TagsMap.datasetData, ApiKeyTagMap.datasetData],
requestBody: {
content: {
'application/json': {
......@@ -170,7 +171,7 @@ export const DatasetDataPath: OpenAPIPath = {
delete: {
summary: '删除数据',
description: '删除指定数据集数据,需要写权限',
tags: [TagsMap.datasetData],
tags: [TagsMap.datasetData, ApiKeyTagMap.datasetData],
requestParams: {
query: DeleteDatasetDataQuerySchema
},
......@@ -248,7 +249,7 @@ export const DatasetDataPath: OpenAPIPath = {
post: {
summary: '推送数据到训练队列',
description: '批量推送数据到训练队列,最多 200 条',
tags: [TagsMap.datasetData],
tags: [TagsMap.datasetData, ApiKeyTagMap.datasetData],
requestBody: {
content: {
'application/json': {
......
import type { OpenAPIPath } from '../../type';
import { TagsMap } from '../../tag';
import { ApiKeyTagMap } from '../../apikey/tag';
import { DatasetDataPath } from './data';
import { DatasetCollectionPath } from './collection';
import { ApiDatasetPath } from './apiDataset';
......@@ -25,7 +26,7 @@ export const DatasetPath: OpenAPIPath = {
post: {
summary: '创建知识库',
description: '创建新的知识库,支持多种类型(普通知识库、文件夹、网站知识库等)',
tags: [TagsMap.datasetCommon],
tags: [TagsMap.datasetCommon, ApiKeyTagMap.dataset],
requestBody: {
content: {
'application/json': {
......@@ -82,7 +83,7 @@ export const DatasetPath: OpenAPIPath = {
post: {
summary: '获取知识库列表',
description: '获取当前用户有权限访问的知识库列表,支持按类型和关键词筛选',
tags: [TagsMap.datasetCommon],
tags: [TagsMap.datasetCommon, ApiKeyTagMap.dataset],
requestBody: {
content: {
'application/json': {
......@@ -116,7 +117,7 @@ export const DatasetPath: OpenAPIPath = {
get: {
summary: '获取知识库详情',
description: '获取知识库详细信息,包括模型配置、权限和同步状态',
tags: [TagsMap.datasetCommon],
tags: [TagsMap.datasetCommon, ApiKeyTagMap.dataset],
requestParams: {
query: GetDatasetDetailQuerySchema
},
......@@ -131,7 +132,7 @@ export const DatasetPath: OpenAPIPath = {
delete: {
summary: '删除知识库',
description: '删除知识库及其所有子知识库,需要所有者权限',
tags: [TagsMap.datasetCommon],
tags: [TagsMap.datasetCommon, ApiKeyTagMap.dataset],
requestParams: {
query: DeleteDatasetQuerySchema
},
......@@ -185,7 +186,7 @@ export const DatasetPath: OpenAPIPath = {
summary: '搜索测试',
description:
'对知识库执行搜索测试,支持多种搜索模式、重排序、问题扩展和临时图片 key 检索。图片检索需先调用 /core/dataset/file/presignSearchTestImage 获取预签名上传 URL 和 temp/${teamId}/... key',
tags: [TagsMap.datasetCommon],
tags: [TagsMap.datasetCommon, ApiKeyTagMap.datasetOther],
requestBody: {
content: {
'application/json': {
......
import { createDocument } from 'zod-openapi';
import { ChatPath } from './core/chat';
import { TagsMap } from './tag';
import { PluginPath } from './core/plugin';
import { AppPath } from './core/app';
import { SupportPath } from './support';
import { DatasetPath } from './core/dataset';
import { AIPath } from './core/ai';
import { SkillPath } from './core/ai/skill';
import { openAPIPaths, openAPITagGroups } from './path';
import { ApiKeyTagMap } from './apikey/tag';
const openAPITagSet = new Set<string>(Object.values(ApiKeyTagMap));
const openAPIDocumentPaths = Object.fromEntries(
Object.entries(openAPIPaths).map(([path, pathItem]) => [
path,
Object.fromEntries(
Object.entries(pathItem ?? {}).map(([method, operation]) => {
const tags = (operation as { tags?: string[] } | undefined)?.tags;
return [
method,
tags
? {
...(operation as object),
// ApiKeyTagMap 只作为 /openapi 的筛选标记,不展示在全量开发者文档里。
tags: tags.filter((tag) => !openAPITagSet.has(tag))
}
: operation
];
})
)
])
) as typeof openAPIPaths;
export const openAPIDocument = createDocument({
openapi: '3.1.0',
......@@ -15,79 +33,7 @@ export const openAPIDocument = createDocument({
version: '0.1.0',
description: 'FastGPT API 文档'
},
paths: {
...AppPath,
...ChatPath,
...DatasetPath,
...PluginPath,
...SupportPath,
...AIPath,
...SkillPath
},
paths: openAPIDocumentPaths,
servers: [{ url: '/api' }],
'x-tagGroups': [
{
name: '我的应用/工具管理',
tags: [TagsMap.appCommon, TagsMap.mcpTools, TagsMap.httpTools, TagsMap.appPer]
},
{
name: 'Agent 应用',
tags: [TagsMap.appLog, TagsMap.publishChannel, TagsMap.mcpServer]
},
{
name: 'AI 相关',
tags: [TagsMap.aiSkill, TagsMap.sandbox, TagsMap.aiCommon]
},
{
name: '对话模块配置',
tags: [TagsMap.chatSetting, TagsMap.chatPage, TagsMap.chatInputGuide]
},
{
name: '对话模块使用',
tags: [
TagsMap.chatHistory,
TagsMap.chatFeedback,
TagsMap.chatFile,
TagsMap.chatRecord,
TagsMap.chatController
]
},
{
name: '知识库',
tags: [
TagsMap.datasetCommon,
TagsMap.datasetCollection,
TagsMap.datasetCollectionCrteate,
TagsMap.datasetData,
TagsMap.datasetFile,
TagsMap.datasetTraining,
TagsMap.datasetApiDataset
]
},
{
name: '插件系统',
tags: [TagsMap.pluginToolTag, TagsMap.pluginTeam]
},
{
name: '用户体系',
tags: [
TagsMap.userInform,
TagsMap.walletBill,
TagsMap.walletDiscountCoupon,
TagsMap.userLogin
]
},
{
name: '通用-辅助功能',
tags: [TagsMap.customDomain, TagsMap.apiKey]
},
{
name: '管理员-插件管理',
tags: [TagsMap.pluginAdmin, TagsMap.pluginMarketplace, TagsMap.pluginToolAdmin]
},
{
name: '系统接口',
tags: [TagsMap.helperBot]
}
]
'x-tagGroups': openAPITagGroups
});
import { AIPath } from './core/ai';
import { SkillPath } from './core/ai/skill';
import { AppPath } from './core/app';
import { ChatPath } from './core/chat';
import { DatasetPath } from './core/dataset';
import { PluginPath } from './core/plugin';
import { SupportPath } from './support';
import { TagsMap } from './tag';
import type { OpenAPIPath } from './type';
export const openAPIPaths: NonNullable<OpenAPIPath> = {
...AppPath,
...ChatPath,
...DatasetPath,
...PluginPath,
...SupportPath,
...AIPath,
...SkillPath
};
export const openAPITagGroups = [
{
name: '我的应用/工具管理',
tags: [TagsMap.appCommon, TagsMap.mcpTools, TagsMap.httpTools, TagsMap.appPer]
},
{
name: 'Agent 应用',
tags: [TagsMap.appLog, TagsMap.publishChannel, TagsMap.mcpServer]
},
{
name: 'AI 相关',
tags: [TagsMap.aiSkill, TagsMap.sandbox, TagsMap.aiCommon]
},
{
name: '对话模块配置',
tags: [TagsMap.chatSetting, TagsMap.chatPage, TagsMap.chatInputGuide]
},
{
name: '对话模块使用',
tags: [
TagsMap.chatHistory,
TagsMap.chatFeedback,
TagsMap.chatFile,
TagsMap.chatRecord,
TagsMap.chatController
]
},
{
name: '知识库',
tags: [
TagsMap.datasetCommon,
TagsMap.datasetCollection,
TagsMap.datasetCollectionCrteate,
TagsMap.datasetData,
TagsMap.datasetFile,
TagsMap.datasetTraining,
TagsMap.datasetApiDataset
]
},
{
name: '插件系统',
tags: [TagsMap.pluginToolTag, TagsMap.pluginTeam]
},
{
name: '用户体系',
tags: [TagsMap.userInform, TagsMap.walletBill, TagsMap.walletDiscountCoupon, TagsMap.userLogin]
},
{
name: '通用-辅助功能',
tags: [TagsMap.customDomain, TagsMap.apiKey]
},
{
name: '管理员-插件管理',
tags: [TagsMap.pluginAdmin, TagsMap.pluginMarketplace, TagsMap.pluginToolAdmin]
},
{
name: '系统接口',
tags: [TagsMap.helperBot]
}
];
const scalarApiReferenceCss = `
.sidebar-heading-link-method .sidebar-heading-type {
min-width: 42px;
height: 20px;
justify-content: center;
padding: 4px 8px;
border: 0;
border-radius: 999px;
font-size: 10px;
line-height: 1;
}
.sidebar-heading-type--get {
color: #1D6FE8;
background-color: #E8F1FF;
}
.sidebar-heading-type--post {
color: #0F8B57;
background-color: #E6F7EE;
}
.sidebar-heading-type--put,
.sidebar-heading-type--patch {
color: #B86B00;
background-color: #FFF1D8;
}
.sidebar-heading-type--delete {
color: #C93D3D;
background-color: #FDEAEA;
}
.sidebar-heading-type--options {
color: #7A55D9;
background-color: #F1ECFF;
}
.sidebar-heading-type--head,
.sidebar-heading-type--trace {
color: #5B6678;
background-color: #EEF1F5;
}
.dark-mode .sidebar-heading-type--get {
color: #8BBEFF;
background-color: rgba(58, 122, 210, 0.2);
}
.dark-mode .sidebar-heading-type--post {
color: #72DBA2;
background-color: rgba(28, 142, 86, 0.22);
}
.dark-mode .sidebar-heading-type--put,
.dark-mode .sidebar-heading-type--patch {
color: #F0B96A;
background-color: rgba(190, 115, 16, 0.22);
}
.dark-mode .sidebar-heading-type--delete {
color: #F48A8A;
background-color: rgba(190, 62, 62, 0.22);
}
.dark-mode .sidebar-heading-type--options {
color: #B7A3FF;
background-color: rgba(116, 86, 214, 0.24);
}
.dark-mode .sidebar-heading-type--head,
.dark-mode .sidebar-heading-type--trace {
color: #B5BFCE;
background-color: rgba(98, 111, 130, 0.24);
}
`;
export const getScalarOpenApiReferenceConfig = (url: string) =>
({
customCss: scalarApiReferenceCss,
hideDarkModeToggle: false,
hideClientButton: true,
showToolbar: 'never',
theme: 'default',
url
}) as const;
Subproject commit 85f61b2ddcc7b13b56a282c0c233284c50f2f759
Subproject commit f500e41b5c6dd29ab937b82267dd15749cd17201
......@@ -28,8 +28,9 @@ type AppPropsWithLayout = AppProps & {
};
const routesWithCustomHead = ['/chat', '/chat/share', '/app/detail', '/dataset/detail'];
const openAPIReferenceRoutes = ['/openapi', '/devapidoc'];
// 哪些路由不需要 Layout
const routesWithoutLayout = ['/openapi'];
const routesWithoutLayout = openAPIReferenceRoutes;
function App({ Component, pageProps }: AppPropsWithLayout) {
const { feConfigs, scripts, title } = useInitApp();
......@@ -59,7 +60,7 @@ function App({ Component, pageProps }: AppPropsWithLayout) {
const headDesc = appClientEnv.systemDescription || t('common:system_intro', { title });
const headIcon = getWebReqUrl(feConfigs?.favicon || appClientEnv.systemFavicon);
if (router.pathname === '/openapi') {
if (openAPIReferenceRoutes.includes(router.pathname)) {
return (
<>
{showHead && <NextHead title={title} desc={headDesc} icon={headIcon} />}
......@@ -72,7 +73,9 @@ function App({ Component, pageProps }: AppPropsWithLayout) {
<>
{showHead && <NextHead title={title} desc={headDesc} icon={headIcon} />}
{scripts?.map((item, i) => <Script key={i} strategy="lazyOnload" {...item}></Script>)}
{scripts?.map((item, i) => (
<Script key={i} strategy="lazyOnload" {...item}></Script>
))}
<QueryClientContext>
<SystemStoreContextProvider device={pageProps.deviceSize}>
......
......@@ -12,12 +12,7 @@ export async function handler(req: ApiRequestProps, res: NextApiResponse) {
req.query
);
const {
teamId: chatTeamId,
tmbId,
uid,
authType
} = await authChatCrud({
const { tmbId, uid, authType } = await authChatCrud({
req,
authToken: true,
authApiKey: true,
......
......@@ -11,10 +11,10 @@ export async function handler(req: ApiRequestProps, res: NextApiResponse) {
const { appId, chatId } = parseApiInput({ req, querySchema: DelChatHistorySchema }).query;
await authChatCrud({
...req.query,
req,
authToken: true,
authApiKey: true,
...req.query
authApiKey: true
});
await MongoChat.updateOne(
......
......@@ -11,10 +11,10 @@ export async function handler(req: ApiRequestProps, _res: ApiResponseType): Prom
const body = parseApiInput({ req, bodySchema: MarkChatReadBodySchema }).body;
await authChatCrud({
...body,
req,
authToken: true,
authApiKey: true,
...body,
per: WritePermissionVal
});
......
......@@ -14,10 +14,10 @@ export async function handler(req: ApiRequestProps, res: NextApiResponse) {
bodySchema: UpdateHistoryBodySchema
}).body;
await authChatCrud({
...req.body,
req,
authToken: true,
authApiKey: true,
...req.body,
per: WritePermissionVal
});
......
import type { NextApiRequest, NextApiResponse } from 'next';
import { openAPIDocument } from '@fastgpt/global/openapi';
export default function handler(req: NextApiRequest, res: NextApiResponse) {
res.status(200).json(openAPIDocument);
}
import type { NextApiRequest, NextApiResponse } from 'next';
import { openAPIDocument } from '@fastgpt/global/openapi';
import { apiDocOpenAPIDocument } from '@fastgpt/global/openapi/apikey';
export default function handler(req: NextApiRequest, res: NextApiResponse) {
res.status(200).json(openAPIDocument);
res.status(200).json(apiDocOpenAPIDocument);
}
import { Box } from '@chakra-ui/react';
import dynamic from 'next/dynamic';
import { getScalarOpenApiReferenceConfig } from '@fastgpt/global/openapi/reference';
// 动态加载 @scalar/api-reference-react,避免其 CSS side-effect 在 Node 端
// (next build 的 collecting page data 阶段) 被解析导致 ERR_UNKNOWN_FILE_EXTENSION。
const ApiReferenceReact = dynamic(
() => Promise.all([import('@scalar/api-reference-react')]).then(([mod]) => mod.ApiReferenceReact),
{ ssr: false }
);
function ApiDocPage() {
return (
<Box w="100vw" h="100vh" overflow="auto">
<ApiReferenceReact configuration={getScalarOpenApiReferenceConfig('/api/devapidoc.json')} />
</Box>
);
}
// 禁用静态生成
export async function getServerSideProps() {
return {
props: {}
};
}
export default ApiDocPage;
import { Box } from '@chakra-ui/react';
import dynamic from 'next/dynamic';
import { getScalarOpenApiReferenceConfig } from '@fastgpt/global/openapi/reference';
// 动态加载 @scalar/api-reference-react,避免其 CSS side-effect 在 Node 端
// (next build 的 collecting page data 阶段) 被解析导致 ERR_UNKNOWN_FILE_EXTENSION。
......@@ -11,14 +12,7 @@ const ApiReferenceReact = dynamic(
function OpenAPIPage() {
return (
<Box w="100vw" h="100vh" overflow="auto">
<ApiReferenceReact
configuration={{
hideDarkModeToggle: true,
hideClientButton: true,
theme: 'default',
url: '/api/openapi.json'
}}
/>
<ApiReferenceReact configuration={getScalarOpenApiReferenceConfig('/api/openapi.json')} />
</Box>
);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment