添加支持utools.ai

This commit is contained in:
fofolee 2025-04-23 23:09:36 +08:00
parent 3fb17dcd99
commit d1b117186f

View File

@ -17,6 +17,7 @@ window.aiResponseParser = (content) => {
const API_TYPES = { const API_TYPES = {
OPENAI: "openai", OPENAI: "openai",
OLLAMA: "ollama", OLLAMA: "ollama",
UTOOLS: "utools",
}; };
// 角色提示词 // 角色提示词
@ -151,21 +152,6 @@ function buildRequestData(content, apiConfig) {
}; };
} }
// 处理普通响应
function parseResponse(response, apiType) {
if (apiType === API_TYPES.OPENAI) {
if (!response.data.choices || !response.data.choices[0]) {
throw new Error("OpenAI 响应格式错误");
}
return response.data.choices[0].message.content;
} else {
if (!response.data.message) {
throw new Error("Ollama 响应格式错误");
}
return response.data.message.content;
}
}
// 处理模型列表响应 // 处理模型列表响应
function parseModelsResponse(response, apiType) { function parseModelsResponse(response, apiType) {
if (apiType === API_TYPES.OPENAI) { if (apiType === API_TYPES.OPENAI) {
@ -209,8 +195,38 @@ async function handleOllamaStreamResponse(line, onStream) {
} }
} }
let reasoning_content_start = false;
// 处理 uTools AI 流式响应
async function handleUToolsAIStreamResponse(response, onStream) {
if (response.reasoning_content) {
if (!reasoning_content_start) {
reasoning_content_start = true;
onStream("<think>", false);
}
onStream(response.reasoning_content, false);
}
if (response.content) {
if (reasoning_content_start) {
reasoning_content_start = false;
onStream("</think>", false);
}
onStream(response.content, false);
}
}
// 处理流式响应 // 处理流式响应
async function handleStreamResponse(response, apiConfig, onStream) { async function handleStreamResponse(response, apiConfig, onStream) {
// 处理 uTools AI 响应
if (apiConfig.apiType === API_TYPES.UTOOLS) {
try {
await handleUToolsAIStreamResponse(response, onStream);
return { success: true };
} catch (error) {
throw error;
}
}
// 处理其他 API 的流式响应
const reader = response.body.getReader(); const reader = response.body.getReader();
const decoder = new TextDecoder(); const decoder = new TextDecoder();
let buffer = ""; let buffer = "";
@ -283,24 +299,27 @@ async function chat(content, apiConfig, options = {}) {
} = options; } = options;
// 验证必要参数 // 验证必要参数
if (apiConfig.apiType === API_TYPES.UTOOLS) {
if (!content.prompt || !apiConfig.model) {
throw new Error("模型名称和提示词不能为空");
}
} else {
if (!apiConfig.apiUrl) {
throw new Error("API地址不能为空");
}
if (!apiConfig.apiUrl || !content.prompt || !apiConfig.model) { if (!apiConfig.apiUrl || !content.prompt || !apiConfig.model) {
throw new Error("API地址、模型名称和提示词不能为空"); throw new Error("API地址、模型名称和提示词不能为空");
} }
}
// 构建请求URL和配置 let controller;
const url = buildApiUrl(
apiConfig.apiUrl,
API_ENDPOINTS[apiConfig.apiType].chat
);
const config = buildRequestConfig(apiConfig);
const requestData = buildRequestData(content, apiConfig);
// 显示进度条 // 显示进度条
const processBar = showProcessBar const processBar = showProcessBar
? await quickcommand.showProcessBar({ ? await quickcommand.showProcessBar({
text: "AI思考中...", text: "AI思考中...",
onClose: () => { onClose: () => {
if (controller) { if (typeof controller !== "undefined") {
controller.abort(); controller.abort();
} }
}, },
@ -327,11 +346,65 @@ async function chat(content, apiConfig, options = {}) {
onStream(chunk, isDone); onStream(chunk, isDone);
}; };
// 统一使用 fetch 处理请求 // 处理 uTools AI 请求
const controller = new AbortController(); if (apiConfig.apiType === API_TYPES.UTOOLS) {
try {
const messages = buildRequestData(content, apiConfig).messages;
controller = utools.ai(
{
model: apiConfig.model,
messages: messages,
},
(chunk) => {
handleUToolsAIStreamResponse(chunk, streamHandler);
}
);
onFetch(controller);
await controller;
// 在流式响应完全结束后,发送一个空字符串表示结束
streamHandler("", true);
// 完成时更新进度条并关闭
if (processBar) {
quickcommand.updateProcessBar(
{
text: "AI响应完成",
complete: true,
},
processBar
);
}
return {
success: true,
result: fullResponse,
};
} catch (error) {
if (error.name === "AbortError") {
return {
success: false,
error: "请求已取消",
cancelled: true,
};
}
throw error;
}
}
// 统一使用 fetch 处理其他 API 请求
controller = new AbortController();
onFetch(controller); onFetch(controller);
const url = buildApiUrl(
apiConfig.apiUrl,
API_ENDPOINTS[apiConfig.apiType].chat
);
const config = buildRequestConfig(apiConfig);
const requestData = (content, apiConfig);
const response = await fetch(url, { const response = await fetch(url, {
method: "POST", method: "POST",
headers: config.headers, headers: config.headers,