forked from Shinonome/dots-hyprland
Rearrange for tidier structure (#2212)
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
import QtQuick
|
||||
|
||||
ApiStrategy {
|
||||
property bool isReasoning: false
|
||||
|
||||
function buildEndpoint(model: AiModel): string {
|
||||
// console.log("[AI] Endpoint: " + model.endpoint);
|
||||
return model.endpoint;
|
||||
}
|
||||
|
||||
function buildRequestData(model: AiModel, messages, systemPrompt: string, temperature: real, tools: list<var>, filePath: string) {
|
||||
let baseData = {
|
||||
"model": model.model,
|
||||
"messages": [
|
||||
{role: "system", content: systemPrompt},
|
||||
...messages.map(message => {
|
||||
return {
|
||||
"role": message.role,
|
||||
"content": message.rawContent,
|
||||
}
|
||||
}),
|
||||
],
|
||||
"stream": true,
|
||||
"tools": tools,
|
||||
"temperature": temperature,
|
||||
};
|
||||
return model.extraParams ? Object.assign({}, baseData, model.extraParams) : baseData;
|
||||
}
|
||||
|
||||
function buildAuthorizationHeader(apiKeyEnvVarName: string): string {
|
||||
return `-H "Authorization: Bearer \$\{${apiKeyEnvVarName}\}"`;
|
||||
}
|
||||
|
||||
function parseResponseLine(line, message) {
|
||||
// Remove 'data: ' prefix if present and trim whitespace
|
||||
let cleanData = line.trim();
|
||||
if (cleanData.startsWith("data:")) {
|
||||
cleanData = cleanData.slice(5).trim();
|
||||
}
|
||||
|
||||
// console.log("[AI] OpenAI: Data:", cleanData);
|
||||
|
||||
// Handle special cases
|
||||
if (!cleanData || cleanData.startsWith(":")) return {};
|
||||
if (cleanData === "[DONE]") {
|
||||
return { finished: true };
|
||||
}
|
||||
|
||||
// Real stuff
|
||||
try {
|
||||
const dataJson = JSON.parse(cleanData);
|
||||
let newContent = "";
|
||||
|
||||
const responseContent = dataJson.choices[0]?.delta?.content || dataJson.message?.content;
|
||||
const responseReasoning = dataJson.choices[0]?.delta?.reasoning || dataJson.choices[0]?.delta?.reasoning_content;
|
||||
|
||||
if (responseContent && responseContent.length > 0) {
|
||||
if (isReasoning) {
|
||||
isReasoning = false;
|
||||
const endBlock = "\n\n</think>\n\n";
|
||||
message.content += endBlock;
|
||||
message.rawContent += endBlock;
|
||||
}
|
||||
newContent = responseContent;
|
||||
} else if (responseReasoning && responseReasoning.length > 0) {
|
||||
if (!isReasoning) {
|
||||
isReasoning = true;
|
||||
const startBlock = "\n\n<think>\n\n";
|
||||
message.rawContent += startBlock;
|
||||
message.content += startBlock;
|
||||
}
|
||||
newContent = responseReasoning;
|
||||
}
|
||||
|
||||
message.content += newContent;
|
||||
message.rawContent += newContent;
|
||||
|
||||
// Usage metadata
|
||||
if (dataJson.usage) {
|
||||
return {
|
||||
tokenUsage: {
|
||||
input: dataJson.usage.prompt_tokens ?? -1,
|
||||
output: dataJson.usage.completion_tokens ?? -1,
|
||||
total: dataJson.usage.total_tokens ?? -1
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (dataJson.done) {
|
||||
return { finished: true };
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
console.log("[AI] OpenAI: Could not parse line: ", e);
|
||||
message.rawContent += line;
|
||||
message.content += line;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
function onRequestFinished(message) {
|
||||
// OpenAI format doesn't need special finish handling
|
||||
return {};
|
||||
}
|
||||
|
||||
function reset() {
|
||||
isReasoning = false;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user