link0518
中转
8f02d2f
import tokenManager from '../auth/token_manager.js';
import config from '../config/config.js';
export async function generateAssistantResponse(requestBody, callback) {
const token = await tokenManager.getToken();
if (!token) {
throw new Error('没有可用的token,请运行 npm run login 获取token');
}
const url = config.api.url;
const response = await fetch(url, {
method: 'POST',
headers: {
'Host': config.api.host,
'User-Agent': config.api.userAgent,
'Authorization': `Bearer ${token.access_token}`,
'Content-Type': 'application/json',
'Accept-Encoding': 'gzip'
},
body: JSON.stringify(requestBody)
});
if (!response.ok) {
const errorText = await response.text();
if (response.status === 403) {
tokenManager.disableCurrentToken(token);
throw new Error(`该账号没有使用权限,已自动禁用。错误详情: ${errorText}`);
}
throw new Error(`API请求失败 (${response.status}): ${errorText}`);
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
let thinkingStarted = false;
let toolCalls = [];
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
const lines = chunk.split('\n').filter(line => line.startsWith('data: '));
for (const line of lines) {
const jsonStr = line.slice(6);
try {
const data = JSON.parse(jsonStr);
const parts = data.response?.candidates?.[0]?.content?.parts;
if (parts) {
for (const part of parts) {
if (part.thought === true) {
if (!thinkingStarted) {
callback({ type: 'thinking', content: '<think>\n' });
thinkingStarted = true;
}
callback({ type: 'thinking', content: part.text || '' });
} else if (part.text !== undefined) {
if (thinkingStarted) {
callback({ type: 'thinking', content: '\n</think>\n' });
thinkingStarted = false;
}
let content = part.text || '';
if (part.thought_signature) {
content += `\n<!-- thought_signature: ${part.thought_signature} -->`;
}
if (part.inlineData) {
const mimeType = part.inlineData.mimeType;
const data = part.inlineData.data;
content += `\n![Generated Image](data:${mimeType};base64,${data})`;
}
if (content) {
callback({ type: 'text', content: content });
}
} else if (part.functionCall) {
toolCalls.push({
id: part.functionCall.id,
type: 'function',
function: {
name: part.functionCall.name,
arguments: JSON.stringify(part.functionCall.args)
}
});
}
}
}
// 当遇到 finishReason 时,发送所有收集的工具调用
if (data.response?.candidates?.[0]?.finishReason && toolCalls.length > 0) {
if (thinkingStarted) {
callback({ type: 'thinking', content: '\n</think>\n' });
thinkingStarted = false;
}
callback({ type: 'tool_calls', tool_calls: toolCalls });
toolCalls = [];
}
} catch (e) {
// 忽略解析错误
}
}
}
}
export async function getAvailableModels() {
const token = await tokenManager.getToken();
if (!token) {
throw new Error('没有可用的token,请运行 npm run login 获取token');
}
const response = await fetch(config.api.modelsUrl, {
method: 'POST',
headers: {
'Host': config.api.host,
'User-Agent': config.api.userAgent,
'Authorization': `Bearer ${token.access_token}`,
'Content-Type': 'application/json',
'Accept-Encoding': 'gzip'
},
body: JSON.stringify({})
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`获取模型列表失败 (${response.status}): ${errorText}`);
}
const responseText = await response.text();
let data;
try {
data = JSON.parse(responseText);
} catch (e) {
throw new Error(`JSON解析失败: ${e.message}. 原始响应: ${responseText.substring(0, 200)}`);
}
return {
object: 'list',
data: Object.keys(data.models).map(id => ({
id,
object: 'model',
created: Math.floor(Date.now() / 1000),
owned_by: 'google'
}))
};
}