ai-query对接新版freesun-agent接口的分支
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

184 lines
7.7 KiB

'use strict';
const superAgent = require('../controllers/superAgent');
const superAgentProtocol = require('../controllers/superAgentProtocol');
const Busboy = require('busboy');
const fs = require('fs');
const os = require('os');
const path = require('path');
const UPLOAD_FILE_SIZE_LIMIT = 100 * 1024 * 1024;
/**
* 功能:解析 SuperAgent 文件上传请求
* 场景:浏览器 multipart 上传中文文件名时,必须让 busboy 按 UTF-8 解析 filename 参数
* 入参:
* - ctx Koa上下文
* - next 后续控制器
* 出参:
* - 写入 ctx.file 和 ctx.request.body,保持 controller 读取方式稳定
* 注意:
* - multer 当前版本没有把 defParamCharset 透传给 busboy,所以这里直接使用 busboy 根治中文文件名乱码
* - 临时文件由 controller 在转发上游后统一删除
*/
const parseSuperAgentUploadFile = async (ctx, next) => {
const requestBody = Object.create(null);
let tempFilePath = "";
let uploadedFile = null;
try {
await new Promise((resolve, reject) => {
let parseError = null;
let writeFileTask = Promise.resolve();
const busboy = Busboy({
headers: ctx.req.headers,
defParamCharset: 'utf8',
limits: {
files: 1,
fileSize: UPLOAD_FILE_SIZE_LIMIT,
},
});
busboy.on('field', (fieldName, value) => {
requestBody[fieldName] = value;
});
busboy.on('file', (fieldName, fileStream, fileInfo) => {
const originalName = fileInfo.filename || 'upload.bin';
const tempFileName = `super-agent-${Date.now()}-${Math.random().toString(16).slice(2)}`;
const filePath = path.join(os.tmpdir(), tempFileName);
const writeStream = fs.createWriteStream(filePath);
let fileSize = 0;
tempFilePath = filePath;
fileStream.on('data', (chunk) => {
fileSize += chunk.length;
});
fileStream.on('limit', () => {
parseError = new Error('文件大小不能超过100MB');
});
writeFileTask = new Promise((resolveWrite, rejectWrite) => {
writeStream.on('finish', () => {
uploadedFile = {
fieldname: fieldName,
originalname: originalName,
encoding: fileInfo.encoding,
mimetype: fileInfo.mimeType,
path: filePath,
size: fileSize,
};
resolveWrite();
});
writeStream.on('error', rejectWrite);
fileStream.on('error', rejectWrite);
});
fileStream.pipe(writeStream);
});
busboy.on('filesLimit', () => {
parseError = new Error('一次只能上传一个文件');
});
busboy.on('error', reject);
busboy.on('finish', async () => {
try {
await writeFileTask;
if (parseError) {
reject(parseError);
return;
}
resolve();
} catch (error) {
reject(error);
}
});
ctx.req.pipe(busboy);
});
ctx.file = uploadedFile;
ctx.request.file = uploadedFile;
ctx.request.body = requestBody;
await next();
} catch (error) {
if (tempFilePath) {
fs.promises.unlink(tempFilePath).catch(() => {});
}
throw error;
}
};
module.exports = function (app, router, conf) {
const { tenderUserAuth } = app.middlewares;
// SuperAgent v2 useStream 协议路由;与旧聊天接口并行保留,不做协议回退。
router.get('/super-agent/threads/:threadId/state', tenderUserAuth, superAgentProtocol.getState, { content: '获取SuperAgent v2线程状态', visible: true });
router.post('/super-agent/threads/:threadId/history', tenderUserAuth, superAgentProtocol.getHistory, { content: '获取SuperAgent v2线程历史', visible: true });
router.post('/super-agent/threads/:threadId/commands', tenderUserAuth, superAgentProtocol.sendCommand, { content: '发送SuperAgent v2线程命令', visible: true });
router.post('/super-agent/threads/:threadId/stream/events', tenderUserAuth, superAgentProtocol.streamEvents, { content: '订阅SuperAgent v2线程事件', visible: true });
router.post('/super-agent/threads/:threadId/runs/:runId/cancel', tenderUserAuth, superAgentProtocol.cancelRun, { content: '取消SuperAgent v2运行', visible: true });
// 获取SuperAgent会话列表
router.get('/api/sessions', superAgent.listSessions, { content: '获取SuperAgent任务列表', visible: true });
// 创建SuperAgent任务
router.post('/api/sessions', superAgent.createSession, { content: '创建SuperAgent任务', visible: true });
// 获取侧栏树(folders + root sessions)
router.get('/api/sidebar', superAgent.getSidebar, { content: '获取SuperAgent侧栏树', visible: true });
// 创建文件夹
router.post('/api/folders', superAgent.createFolder, { content: '创建SuperAgent文件夹', visible: true });
// 更新文件夹(代理 PUT,上游 PATCH)
router.put('/api/folders/:folderId', superAgent.updateFolder, { content: '更新SuperAgent文件夹', visible: true });
// 删除文件夹
router.delete('/api/folders/:folderId', superAgent.deleteFolder, { content: '删除SuperAgent文件夹', visible: true });
// 更新会话(folder_id / title / sort_order;代理 PUT,上游 PATCH)
router.put('/api/sessions/:sessionId', superAgent.patchSession, { content: '更新SuperAgent任务', visible: true });
// 获取SuperAgent会话历史消息
router.get('/api/sessions/:sessionId/history', superAgent.getSessionHistory, { content: '获取SuperAgent任务历史消息', visible: true });
// 获取SuperAgent会话状态
router.get('/api/sessions/:sessionId/state', superAgent.getSessionState, { content: '获取SuperAgent任务状态', visible: true });
// 获取SuperAgent兼容章节列表
router.get('/api/sessions/:sessionId/sections', superAgent.getSessionSections, { content: '获取SuperAgent章节列表', visible: true });
// 获取SuperAgent会话章节内容
router.get('/api/sessions/:sessionId/sections/:sectionId', superAgent.getSessionSection, { content: '获取SuperAgent章节内容', visible: true });
// 更新SuperAgent会话章节内容
router.put('/api/sessions/:sessionId/sections/:sectionId', superAgent.updateSessionSection, { content: '更新SuperAgent章节内容', visible: true });
// 下载当前会话生成的完整DOCX
router.get('/api/sessions/:sessionId/download', superAgent.downloadSessionFile, { content: '下载SuperAgent会话生成文件', visible: true });
// 删除SuperAgent会话
router.delete('/api/sessions/:sessionId', superAgent.deleteSession, { content: '删除SuperAgent任务', visible: true });
// 取消SuperAgent任务执行
router.post('/api/sessions/:sessionId/cancel', superAgent.cancelSession, { content: '取消SuperAgent任务执行', visible: true });
// 上传SuperAgent文件
router.post('/api/upload', parseSuperAgentUploadFile, superAgent.uploadFile, { content: '上传SuperAgent附件', visible: true });
// 发送SuperAgent聊天消息(SSE流式响应)
router.post('/api/chat', superAgent.sendChat, { content: '发送SuperAgent流式消息', visible: true });
// 回传checkpoint确认结果
router.post('/api/checkpoint/respond', superAgent.respondCheckpoint, { content: '回传checkpoint确认结果', visible: true });
// 下载文件
router.get('/api/download', superAgent.downloadFile, { content: '下载SuperAgent文件', visible: true });
};