fix(gemini): resolve 400 stream errors and improve client compatibility
- Filter out empty text parts in Gemini requests to avoid 400 errors. - Inject 'assistant' role into the first streaming chunk for better compatibility with clients like opencode. - Fallback to tool_call_id for Gemini function responses when name is missing.
This commit is contained in:
@@ -200,12 +200,14 @@ impl GeminiProvider {
|
||||
if msg.role == "system" {
|
||||
for part in msg.content {
|
||||
if let ContentPart::Text { text } = part {
|
||||
system_parts.push(GeminiPart {
|
||||
text: Some(text),
|
||||
inline_data: None,
|
||||
function_call: None,
|
||||
function_response: None,
|
||||
});
|
||||
if !text.trim().is_empty() {
|
||||
system_parts.push(GeminiPart {
|
||||
text: Some(text),
|
||||
inline_data: None,
|
||||
function_call: None,
|
||||
function_response: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
@@ -230,7 +232,8 @@ impl GeminiProvider {
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
let name = msg.name.clone().unwrap_or_default();
|
||||
// Gemini function response MUST have a name. Fallback to tool_call_id if name is missing.
|
||||
let name = msg.name.clone().or_else(|| msg.tool_call_id.clone()).unwrap_or_else(|| "unknown_function".to_string());
|
||||
let response_value = serde_json::from_str::<Value>(&text_content)
|
||||
.unwrap_or_else(|_| serde_json::json!({ "result": text_content }));
|
||||
|
||||
@@ -249,7 +252,7 @@ impl GeminiProvider {
|
||||
// Include text content if present
|
||||
for p in &msg.content {
|
||||
if let ContentPart::Text { text } = p {
|
||||
if !text.is_empty() {
|
||||
if !text.trim().is_empty() {
|
||||
parts.push(GeminiPart {
|
||||
text: Some(text.clone()),
|
||||
inline_data: None,
|
||||
@@ -279,12 +282,14 @@ impl GeminiProvider {
|
||||
for part in msg.content {
|
||||
match part {
|
||||
ContentPart::Text { text } => {
|
||||
parts.push(GeminiPart {
|
||||
text: Some(text),
|
||||
inline_data: None,
|
||||
function_call: None,
|
||||
function_response: None,
|
||||
});
|
||||
if !text.trim().is_empty() {
|
||||
parts.push(GeminiPart {
|
||||
text: Some(text),
|
||||
inline_data: None,
|
||||
function_call: None,
|
||||
function_response: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
ContentPart::Image(image_input) => {
|
||||
let (base64_data, mime_type) = image_input
|
||||
|
||||
Reference in New Issue
Block a user