Commit d398c9cd by Archer Committed by GitHub

fix: openapi (#6121)

* fix: openapi

* fix: openapi

* fix: default maxResponse load

* fix: default maxResponse load

* doc
parent 5231f428
...@@ -17,6 +17,7 @@ description: 'FastGPT V4.14.5 更新说明' ...@@ -17,6 +17,7 @@ description: 'FastGPT V4.14.5 更新说明'
1. MCP 工具创建时,使用自定义鉴权头会报错。 1. MCP 工具创建时,使用自定义鉴权头会报错。
2. 获取对话日志列表时,如果用户头像为空,会抛错。 2. 获取对话日志列表时,如果用户头像为空,会抛错。
3. chatAgent 未开启问题优化时,前端 UI 显示开启。 3. chatAgent 未开启问题优化时,前端 UI 显示开启。
4. 加载默认模型时,maxTokens 字段未赋值,导致模型最大响应值配置为空。
## 插件 ## 插件
...@@ -120,7 +120,7 @@ ...@@ -120,7 +120,7 @@
"document/content/docs/upgrading/4-14/4142.mdx": "2025-11-18T19:27:14+08:00", "document/content/docs/upgrading/4-14/4142.mdx": "2025-11-18T19:27:14+08:00",
"document/content/docs/upgrading/4-14/4143.mdx": "2025-11-26T20:52:05+08:00", "document/content/docs/upgrading/4-14/4143.mdx": "2025-11-26T20:52:05+08:00",
"document/content/docs/upgrading/4-14/4144.mdx": "2025-12-16T14:56:04+08:00", "document/content/docs/upgrading/4-14/4144.mdx": "2025-12-16T14:56:04+08:00",
"document/content/docs/upgrading/4-14/4145.mdx": "2025-12-18T11:09:13+08:00", "document/content/docs/upgrading/4-14/4145.mdx": "2025-12-18T23:25:48+08:00",
"document/content/docs/upgrading/4-8/40.mdx": "2025-08-02T19:38:37+08:00", "document/content/docs/upgrading/4-8/40.mdx": "2025-08-02T19:38:37+08:00",
"document/content/docs/upgrading/4-8/41.mdx": "2025-08-02T19:38:37+08:00", "document/content/docs/upgrading/4-8/41.mdx": "2025-08-02T19:38:37+08:00",
"document/content/docs/upgrading/4-8/42.mdx": "2025-08-02T19:38:37+08:00", "document/content/docs/upgrading/4-8/42.mdx": "2025-08-02T19:38:37+08:00",
......
import { z } from 'zod'; import { z } from 'zod';
export const PaginationSchema = z.object({ export const PaginationSchema = z.object({
pageSize: z.union([z.number(), z.string()]).optional(), pageSize: z.union([z.number(), z.string()]).optional().describe('每页条数'),
offset: z.union([z.number(), z.string()]).optional(), offset: z.union([z.number(), z.string()]).optional().describe('偏移量(与页码二选一)'),
pageNum: z.union([z.number(), z.string()]).optional() pageNum: z.union([z.number(), z.string()]).optional().describe('页码(与偏移量二选一)')
}); });
export type PaginationType = z.infer<typeof PaginationSchema>; export type PaginationType = z.infer<typeof PaginationSchema>;
......
import type { OutLinkChatAuthType } from '../../support/permission/chat/type'; import type { OutLinkChatAuthType } from '../../../support/permission/chat/type';
import { OutLinkChatAuthSchema } from '../../support/permission/chat/type'; import { OutLinkChatAuthSchema } from '../../../support/permission/chat/type';
import { ObjectIdSchema } from '../../common/type/mongo'; import { ObjectIdSchema } from '../../../common/type/mongo';
import z from 'zod'; import z from 'zod';
export const PresignChatFileGetUrlSchema = z export const PresignChatFileGetUrlSchema = z
.object({ .object({
key: z.string().min(1), key: z.string().min(1).describe('文件key'),
appId: ObjectIdSchema, appId: ObjectIdSchema.describe('应用ID'),
outLinkAuthData: OutLinkChatAuthSchema.optional() outLinkAuthData: OutLinkChatAuthSchema.optional().describe('外链鉴权数据')
}) })
.meta({ .meta({
description: '获取对话文件预览链接',
example: { example: {
key: '1234567890', key: '1234567890',
appId: '1234567890', appId: '1234567890',
...@@ -20,19 +19,16 @@ export const PresignChatFileGetUrlSchema = z ...@@ -20,19 +19,16 @@ export const PresignChatFileGetUrlSchema = z
} }
} }
}); });
export type PresignChatFileGetUrlParams = z.infer<typeof PresignChatFileGetUrlSchema> & { export type PresignChatFileGetUrlParams = z.infer<typeof PresignChatFileGetUrlSchema>;
outLinkAuthData?: OutLinkChatAuthType;
};
export const PresignChatFilePostUrlSchema = z export const PresignChatFilePostUrlSchema = z
.object({ .object({
filename: z.string().min(1), filename: z.string().min(1).describe('文件名'),
appId: ObjectIdSchema, appId: ObjectIdSchema.describe('应用ID'),
chatId: ObjectIdSchema, chatId: z.string().min(1).describe('对话ID'),
outLinkAuthData: OutLinkChatAuthSchema.optional() outLinkAuthData: OutLinkChatAuthSchema.optional().describe('外链鉴权数据')
}) })
.meta({ .meta({
description: '获取上传对话文件预签名 URL',
example: { example: {
filename: '1234567890', filename: '1234567890',
appId: '1234567890', appId: '1234567890',
...@@ -43,26 +39,4 @@ export const PresignChatFilePostUrlSchema = z ...@@ -43,26 +39,4 @@ export const PresignChatFilePostUrlSchema = z
} }
} }
}); });
export type PresignChatFilePostUrlParams = z.infer<typeof PresignChatFilePostUrlSchema> & { export type PresignChatFilePostUrlParams = z.infer<typeof PresignChatFilePostUrlSchema>;
outLinkAuthData?: OutLinkChatAuthType;
};
export const UpdateChatFeedbackSchema = z
.object({
appId: z.string().min(1),
chatId: z.string().min(1),
dataId: z.string().min(1),
userBadFeedback: z.string().optional(),
userGoodFeedback: z.string().optional()
})
.meta({
description: '更新对话反馈',
example: {
appId: '1234567890',
chatId: '1234567890',
dataId: '1234567890',
userBadFeedback: '1234567890',
userGoodFeedback: '1234567890'
}
});
export type UpdateChatFeedbackProps = z.infer<typeof UpdateChatFeedbackSchema>;
...@@ -14,120 +14,120 @@ import { ...@@ -14,120 +14,120 @@ import {
} from './api'; } from './api';
export const ChatFeedbackPath: OpenAPIPath = { export const ChatFeedbackPath: OpenAPIPath = {
'/core/chat/feedback/updateFeedbackReadStatus': { '/core/chat/feedback/updateUserFeedback': {
post: { post: {
summary: '更新反馈阅读状态', summary: '添加/更新用户反馈',
description: '标记指定消息的反馈为已读或未读状态', description: '用户对消息添加或更新好评/差评反馈',
tags: [TagsMap.chatFeedback], tags: [TagsMap.chatFeedback],
requestBody: { requestBody: {
content: { content: {
'application/json': { 'application/json': {
schema: UpdateFeedbackReadStatusBodySchema schema: UpdateUserFeedbackBodySchema
} }
} }
}, },
responses: { responses: {
200: { 200: {
description: '成功更新反馈阅读状态', description: '成功更新用户反馈',
content: { content: {
'application/json': { 'application/json': {
schema: UpdateFeedbackReadStatusResponseSchema schema: UpdateUserFeedbackResponseSchema
} }
} }
} }
} }
} }
}, },
'/core/chat/feedback/adminUpdate': { '/core/chat/feedback/getFeedbackRecordIds': {
post: { post: {
summary: '管理员标注反馈', summary: '获取反馈记录ID列表',
description: '管理员为指定消息添加或更新标注反馈,包含数据集关联信息', description: '根据反馈类型和已读状态,获取符合条件的消息ID列表',
tags: [TagsMap.chatFeedback], tags: [TagsMap.chatFeedback],
requestBody: { requestBody: {
content: { content: {
'application/json': { 'application/json': {
schema: AdminUpdateFeedbackBodySchema schema: GetFeedbackRecordIdsBodySchema
} }
} }
}, },
responses: { responses: {
200: { 200: {
description: '成功更新管理员反馈标注', description: '成功获取反馈记录ID列表',
content: { content: {
'application/json': { 'application/json': {
schema: AdminUpdateFeedbackResponseSchema schema: GetFeedbackRecordIdsResponseSchema
} }
} }
} }
} }
} }
}, },
'/core/chat/feedback/closeCustom': { '/core/chat/feedback/updateFeedbackReadStatus': {
post: { post: {
summary: '关闭自定义反馈', summary: '应用管理员-更新反馈阅读状态',
description: '删除或关闭指定索引位置的自定义反馈条目', description: '标记指定消息的反馈为已读或未读状态',
tags: [TagsMap.chatFeedback], tags: [TagsMap.chatFeedback],
requestBody: { requestBody: {
content: { content: {
'application/json': { 'application/json': {
schema: CloseCustomFeedbackBodySchema schema: UpdateFeedbackReadStatusBodySchema
} }
} }
}, },
responses: { responses: {
200: { 200: {
description: '成功关闭自定义反馈', description: '成功更新反馈阅读状态',
content: { content: {
'application/json': { 'application/json': {
schema: CloseCustomFeedbackResponseSchema schema: UpdateFeedbackReadStatusResponseSchema
} }
} }
} }
} }
} }
}, },
'/core/chat/feedback/updateUserFeedback': { '/core/chat/feedback/adminUpdate': {
post: { post: {
summary: '更新用户反馈', summary: '应用管理员-标注反馈',
description: '用户对消息添加或更新好评/差评反馈', description: '管理员为指定消息添加或更新标注反馈,包含数据集关联信息',
tags: [TagsMap.chatFeedback], tags: [TagsMap.chatFeedback],
requestBody: { requestBody: {
content: { content: {
'application/json': { 'application/json': {
schema: UpdateUserFeedbackBodySchema schema: AdminUpdateFeedbackBodySchema
} }
} }
}, },
responses: { responses: {
200: { 200: {
description: '成功更新用户反馈', description: '成功更新管理员反馈标注',
content: { content: {
'application/json': { 'application/json': {
schema: UpdateUserFeedbackResponseSchema schema: AdminUpdateFeedbackResponseSchema
} }
} }
} }
} }
} }
}, },
'/core/chat/feedback/getFeedbackRecordIds': { '/core/chat/feedback/closeCustom': {
post: { post: {
summary: '获取反馈记录ID列表', summary: '应用管理员-关闭自定义反馈',
description: '根据反馈类型和已读状态,获取符合条件的消息ID列表', description: '删除或关闭指定索引位置的自定义反馈条目',
tags: [TagsMap.chatFeedback], tags: [TagsMap.chatFeedback],
requestBody: { requestBody: {
content: { content: {
'application/json': { 'application/json': {
schema: GetFeedbackRecordIdsBodySchema schema: CloseCustomFeedbackBodySchema
} }
} }
}, },
responses: { responses: {
200: { 200: {
description: '成功获取反馈记录ID列表', description: '成功关闭自定义反馈',
content: { content: {
'application/json': { 'application/json': {
schema: GetFeedbackRecordIdsResponseSchema schema: CloseCustomFeedbackResponseSchema
} }
} }
} }
......
...@@ -5,18 +5,14 @@ import { ChatSourceEnum } from '../../../../core/chat/constants'; ...@@ -5,18 +5,14 @@ import { ChatSourceEnum } from '../../../../core/chat/constants';
import { PaginationSchema, PaginationResponseSchema } from '../../../api'; import { PaginationSchema, PaginationResponseSchema } from '../../../api';
// Get chat histories schema // Get chat histories schema
export const GetHistoriesBodySchema = PaginationSchema.and( export const GetHistoriesBodySchema = PaginationSchema.extend(OutLinkChatAuthSchema.shape).extend({
OutLinkChatAuthSchema.and( appId: z.string().optional().describe('应用ID'),
z.object({ source: z.enum(ChatSourceEnum).optional().describe('对话来源'),
appId: z.string().optional().describe('应用ID'), startCreateTime: z.string().optional().describe('创建时间开始'),
source: z.enum(ChatSourceEnum).optional().describe('对话来源'), endCreateTime: z.string().optional().describe('创建时间结束'),
startCreateTime: z.string().optional().describe('创建时间开始'), startUpdateTime: z.string().optional().describe('更新时间开始'),
endCreateTime: z.string().optional().describe('创建时间结束'), endUpdateTime: z.string().optional().describe('更新时间结束')
startUpdateTime: z.string().optional().describe('更新时间开始'), });
endUpdateTime: z.string().optional().describe('更新时间结束')
})
)
);
export type GetHistoriesBodyType = z.infer<typeof GetHistoriesBodySchema>; export type GetHistoriesBodyType = z.infer<typeof GetHistoriesBodySchema>;
export const GetHistoriesResponseSchema = PaginationResponseSchema( export const GetHistoriesResponseSchema = PaginationResponseSchema(
z.object({ z.object({
...@@ -43,20 +39,16 @@ export const UpdateHistoryBodySchema = OutLinkChatAuthSchema.and( ...@@ -43,20 +39,16 @@ export const UpdateHistoryBodySchema = OutLinkChatAuthSchema.and(
export type UpdateHistoryBodyType = z.infer<typeof UpdateHistoryBodySchema>; export type UpdateHistoryBodyType = z.infer<typeof UpdateHistoryBodySchema>;
// Delete single chat history schema // Delete single chat history schema
export const DelChatHistorySchema = OutLinkChatAuthSchema.and( export const DelChatHistorySchema = OutLinkChatAuthSchema.extend({
z.object({ appId: ObjectIdSchema.describe('应用ID'),
appId: ObjectIdSchema.describe('应用ID'), chatId: z.string().min(1).describe('对话ID')
chatId: z.string().min(1).describe('对话ID') });
})
);
export type DelChatHistoryType = z.infer<typeof DelChatHistorySchema>; export type DelChatHistoryType = z.infer<typeof DelChatHistorySchema>;
// Clear all chat histories schema // Clear all chat histories schema
export const ClearChatHistoriesSchema = OutLinkChatAuthSchema.and( export const ClearChatHistoriesSchema = OutLinkChatAuthSchema.extend({
z.object({ appId: ObjectIdSchema.describe('应用ID')
appId: ObjectIdSchema.describe('应用ID') });
})
);
export type ClearChatHistoriesType = z.infer<typeof ClearChatHistoriesSchema>; export type ClearChatHistoriesType = z.infer<typeof ClearChatHistoriesSchema>;
// Batch delete chat histories schema (for log manager) // Batch delete chat histories schema (for log manager)
......
...@@ -5,7 +5,7 @@ import { ChatFeedbackPath } from './feedback/index'; ...@@ -5,7 +5,7 @@ import { ChatFeedbackPath } from './feedback/index';
import { ChatHistoryPath } from './history/index'; import { ChatHistoryPath } from './history/index';
import { z } from 'zod'; import { z } from 'zod';
import { CreatePostPresignedUrlResultSchema } from '../../../../service/common/s3/type'; import { CreatePostPresignedUrlResultSchema } from '../../../../service/common/s3/type';
import { PresignChatFileGetUrlSchema, PresignChatFilePostUrlSchema } from '../../../core/chat/api'; import { PresignChatFileGetUrlSchema, PresignChatFilePostUrlSchema } from './api';
import { TagsMap } from '../../tag'; import { TagsMap } from '../../tag';
export const ChatPath: OpenAPIPath = { export const ChatPath: OpenAPIPath = {
...@@ -14,48 +14,48 @@ export const ChatPath: OpenAPIPath = { ...@@ -14,48 +14,48 @@ export const ChatPath: OpenAPIPath = {
...ChatFeedbackPath, ...ChatFeedbackPath,
...ChatHistoryPath, ...ChatHistoryPath,
'/core/chat/presignChatFileGetUrl': { '/core/chat/presignChatFilePostUrl': {
post: { post: {
summary: '获取对话文件预签名 URL', summary: '获取文件上传 URL',
description: '获取对话文件的预签名 URL', description: '获取文件上传 URL',
tags: [TagsMap.chatPage], tags: [TagsMap.chatPage],
requestBody: { requestBody: {
content: { content: {
'application/json': { 'application/json': {
schema: PresignChatFileGetUrlSchema schema: PresignChatFilePostUrlSchema
} }
} }
}, },
responses: { responses: {
200: { 200: {
description: '成功获取对话文件预签名 URL', description: '成功上传对话文件预签名 URL',
content: { content: {
'application/json': { 'application/json': {
schema: z.string() schema: CreatePostPresignedUrlResultSchema
} }
} }
} }
} }
} }
}, },
'/core/chat/presignChatFilePostUrl': { '/core/chat/presignChatFileGetUrl': {
post: { post: {
summary: '上传对话文件预签名 URL', summary: '获取文件预览地址',
description: '上传对话文件的预签名 URL', description: '获取文件预览地址',
tags: [TagsMap.chatPage], tags: [TagsMap.chatPage],
requestBody: { requestBody: {
content: { content: {
'application/json': { 'application/json': {
schema: PresignChatFilePostUrlSchema schema: PresignChatFileGetUrlSchema
} }
} }
}, },
responses: { responses: {
200: { 200: {
description: '成功上传对话文件预签名 URL', description: '成功获取对话文件预签名 URL',
content: { content: {
'application/json': { 'application/json': {
schema: CreatePostPresignedUrlResultSchema schema: z.string()
} }
} }
} }
......
...@@ -12,5 +12,5 @@ export const TeamChatAuthSchema = z.object({ ...@@ -12,5 +12,5 @@ export const TeamChatAuthSchema = z.object({
}); });
export type TeamChatAuthProps = z.infer<typeof TeamChatAuthSchema>; export type TeamChatAuthProps = z.infer<typeof TeamChatAuthSchema>;
export const OutLinkChatAuthSchema = ShareChatAuthSchema.and(TeamChatAuthSchema); export const OutLinkChatAuthSchema = ShareChatAuthSchema.extend(TeamChatAuthSchema.shape);
export type OutLinkChatAuthProps = z.infer<typeof OutLinkChatAuthSchema>; export type OutLinkChatAuthProps = z.infer<typeof OutLinkChatAuthSchema>;
...@@ -140,9 +140,13 @@ export const loadSystemModels = async (init = false, language = 'en') => { ...@@ -140,9 +140,13 @@ export const loadSystemModels = async (init = false, language = 'en') => {
type: dbModel?.metadata?.type || model.type, type: dbModel?.metadata?.type || model.type,
isCustom: false, isCustom: false,
...(model.type === ModelTypeEnum.llm && {
maxResponse: model.maxTokens || 4000
}),
...(model.type === ModelTypeEnum.llm && dbModel?.metadata?.type === ModelTypeEnum.llm ...(model.type === ModelTypeEnum.llm && dbModel?.metadata?.type === ModelTypeEnum.llm
? { ? {
maxResponse: dbModel?.metadata?.maxResponse ?? model.maxTokens ?? 1000, maxResponse: dbModel?.metadata?.maxResponse ?? model.maxTokens ?? 4000,
defaultConfig: mergeObject(model.defaultConfig, dbModel?.metadata?.defaultConfig), defaultConfig: mergeObject(model.defaultConfig, dbModel?.metadata?.defaultConfig),
fieldMap: mergeObject(model.fieldMap, dbModel?.metadata?.fieldMap), fieldMap: mergeObject(model.fieldMap, dbModel?.metadata?.fieldMap),
maxTokens: undefined maxTokens: undefined
......
...@@ -2,7 +2,7 @@ import type { ApiRequestProps } from '@fastgpt/service/type/next'; ...@@ -2,7 +2,7 @@ import type { ApiRequestProps } from '@fastgpt/service/type/next';
import { NextAPI } from '@/service/middleware/entry'; import { NextAPI } from '@/service/middleware/entry';
import { getS3ChatSource } from '@fastgpt/service/common/s3/sources/chat'; import { getS3ChatSource } from '@fastgpt/service/common/s3/sources/chat';
import { authChatCrud } from '@/service/support/permission/auth/chat'; import { authChatCrud } from '@/service/support/permission/auth/chat';
import type { PresignChatFileGetUrlParams } from '@fastgpt/global/core/chat/api'; import type { PresignChatFileGetUrlParams } from '@fastgpt/global/openapi/core/chat/api';
async function handler(req: ApiRequestProps<PresignChatFileGetUrlParams>): Promise<string> { async function handler(req: ApiRequestProps<PresignChatFileGetUrlParams>): Promise<string> {
const { key, appId, outLinkAuthData } = req.body; const { key, appId, outLinkAuthData } = req.body;
......
...@@ -5,7 +5,7 @@ import { getS3ChatSource } from '@fastgpt/service/common/s3/sources/chat'; ...@@ -5,7 +5,7 @@ import { getS3ChatSource } from '@fastgpt/service/common/s3/sources/chat';
import { authChatCrud } from '@/service/support/permission/auth/chat'; import { authChatCrud } from '@/service/support/permission/auth/chat';
import { authFrequencyLimit } from '@/service/common/frequencyLimit/api'; import { authFrequencyLimit } from '@/service/common/frequencyLimit/api';
import { addSeconds } from 'date-fns'; import { addSeconds } from 'date-fns';
import type { PresignChatFilePostUrlParams } from '@fastgpt/global/core/chat/api'; import type { PresignChatFilePostUrlParams } from '@fastgpt/global/openapi/core/chat/api';
const authUploadLimit = (tmbId: string) => { const authUploadLimit = (tmbId: string) => {
if (!global.feConfigs.uploadFileMaxAmount) return; if (!global.feConfigs.uploadFileMaxAmount) return;
......
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