ai: gemini: fix message marked done too early

This commit is contained in:
end-4
2025-06-02 18:34:44 +02:00
parent 9ddf4d2b2f
commit 2c113018d2
3 changed files with 24 additions and 13 deletions
@@ -145,7 +145,7 @@ int main(int argc, char* argv[]) {
Item { // Messages Item { // Messages
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
ListView { // Message list StyledListView { // Message list
id: messageListView id: messageListView
anchors.fill: parent anchors.fill: parent
spacing: 10 spacing: 10
@@ -187,7 +187,10 @@ int main(int argc, char* argv[]) {
} }
model: ScriptModel { model: ScriptModel {
values: Ai.messageIDs values: Ai.messageIDs.filter(id => {
const message = Ai.messageByID[id];
return message?.visibleToUser ?? true;
})
} }
delegate: AiMessage { delegate: AiMessage {
required property var modelData required property var modelData
+18 -11
View File
@@ -126,7 +126,7 @@ Singleton {
"api_format": "gemini", "api_format": "gemini",
"tools": [ "tools": [
{ {
"google_search": {} "google_search": ({})
}, },
] ]
}, },
@@ -374,9 +374,11 @@ Singleton {
function buildGeminiRequestData(model, messages) { function buildGeminiRequestData(model, messages) {
let baseData = { let baseData = {
"contents": messages.filter(message => (message.role != Ai.interfaceRole)).map(message => { "contents": messages.filter(message => (message.role != Ai.interfaceRole)).map(message => {
if (message.functionCall != undefined && message.functionCall.length > 0) { const geminiApiRoleName = (message.role === "assistant") ? "model" : message.role;
const usingSearch = model.tools[0].google_search != undefined
if (!usingSearch && message.functionCall != undefined && message.functionCall.length > 0) {
return { return {
"role": message.role, "role": geminiApiRoleName,
"parts": [{ "parts": [{
functionCall: { functionCall: {
"name": message.functionName, "name": message.functionName,
@@ -384,9 +386,9 @@ Singleton {
}] }]
} }
} }
if (message.functionResponse != undefined && message.functionResponse.length > 0) { if (!usingSearch && message.functionResponse != undefined && message.functionResponse.length > 0) {
return { return {
"role": message.role, "role": geminiApiRoleName,
"parts": [{ "parts": [{
functionResponse: { functionResponse: {
"name": message.functionName, "name": message.functionName,
@@ -396,7 +398,7 @@ Singleton {
} }
} }
return { return {
"role": message.role, "role": geminiApiRoleName,
"parts": [{ "parts": [{
text: message.content, text: message.content,
}] }]
@@ -481,10 +483,13 @@ Singleton {
} }
function parseGeminiBuffer() { function parseGeminiBuffer() {
console.log("BUFFER DATA: ", requester.geminiBuffer); // console.log("BUFFER DATA: ", requester.geminiBuffer);
try { try {
if (requester.geminiBuffer.length === 0) return; if (requester.geminiBuffer.length === 0) return;
const dataJson = JSON.parse(requester.geminiBuffer); const dataJson = JSON.parse(requester.geminiBuffer);
if (dataJson.candidates[0]?.finishReason) {
requester.markDone();
}
// Function call handling // Function call handling
if (dataJson.candidates[0]?.content?.parts[0]?.functionCall) { if (dataJson.candidates[0]?.content?.parts[0]?.functionCall) {
const functionCall = dataJson.candidates[0]?.content?.parts[0]?.functionCall; const functionCall = dataJson.candidates[0]?.content?.parts[0]?.functionCall;
@@ -531,7 +536,6 @@ Singleton {
} else if (line == "]") { } else if (line == "]") {
requester.geminiBuffer += line.slice(0, -1).trim(); requester.geminiBuffer += line.slice(0, -1).trim();
parseGeminiBuffer(); parseGeminiBuffer();
requester.markDone();
} else if (line.startsWith(",")) { // end of one entry } else if (line.startsWith(",")) { // end of one entry
parseGeminiBuffer(); parseGeminiBuffer();
} else { } else {
@@ -575,7 +579,9 @@ Singleton {
requester.message.content += newContent; requester.message.content += newContent;
if (dataJson.done) requester.markDone(); if (dataJson.done) {
requester.markDone();
}
} }
stdout: SplitParser { stdout: SplitParser {
@@ -604,8 +610,8 @@ Singleton {
} }
onExited: (exitCode, exitStatus) => { onExited: (exitCode, exitStatus) => {
requester.markDone();
if (requester.apiFormat == "gemini") requester.parseGeminiBuffer(); if (requester.apiFormat == "gemini") requester.parseGeminiBuffer();
else requester.markDone();
try { // to parse full response into json for error handling try { // to parse full response into json for error handling
// console.log("Full response: ", requester.message.content + "]"); // console.log("Full response: ", requester.message.content + "]");
@@ -635,8 +641,9 @@ Singleton {
"functionResponse": output, "functionResponse": output,
"thinking": false, "thinking": false,
"done": true, "done": true,
"visibleToUser": false,
}); });
console.log("Adding function output message: ", JSON.stringify(aiMessage)); // console.log("Adding function output message: ", JSON.stringify(aiMessage));
const id = idForMessage(aiMessage); const id = idForMessage(aiMessage);
root.messageIDs = [...root.messageIDs, id]; root.messageIDs = [...root.messageIDs, id];
root.messageByID[id] = aiMessage; root.messageByID[id] = aiMessage;
@@ -15,4 +15,5 @@ QtObject {
property string functionName property string functionName
property string functionCall property string functionCall
property string functionResponse property string functionResponse
property bool visibleToUser: true
} }