mirror of
https://github.com/outbackdingo/optimclaw.git
synced 2026-08-25 14:53:34 +00:00
Handle NEAR AI plain text responses
The API sometimes returns plain text instead of JSON structure. Now we detect this and extract the text content directly. - Detect "Unexpected response format" errors with raw text - Parse as JSON string if quoted, otherwise use raw - Works for both complete() and complete_with_tools() Co-Authored-By: Claude Opus 4.5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.5
parent
2b2f0d56c6
commit
635aeb66a7
+70
-9
@@ -96,14 +96,19 @@ impl NearAiProvider {
|
||||
});
|
||||
}
|
||||
|
||||
serde_json::from_str(&response_text).map_err(|e| {
|
||||
tracing::error!("Failed to parse NEAR AI response: {}", e);
|
||||
tracing::error!("Response was: {}", response_text);
|
||||
LlmError::InvalidResponse {
|
||||
provider: "nearai".to_string(),
|
||||
reason: format!("JSON parse error: {}", e),
|
||||
// Try to parse as JSON, but the API might return plain text
|
||||
match serde_json::from_str::<R>(&response_text) {
|
||||
Ok(parsed) => Ok(parsed),
|
||||
Err(e) => {
|
||||
tracing::debug!("Response is not expected JSON format: {}", e);
|
||||
// If it's not valid JSON for our expected type, it might be a raw string response
|
||||
// We'll handle this in the caller
|
||||
Err(LlmError::InvalidResponse {
|
||||
provider: "nearai".to_string(),
|
||||
reason: format!("Unexpected response format. Raw: {}", response_text),
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,7 +126,35 @@ impl LlmProvider for NearAiProvider {
|
||||
tools: None,
|
||||
};
|
||||
|
||||
let response: NearAiResponse = self.send_request("responses", &request).await?;
|
||||
// Try to get structured response, fall back to raw text
|
||||
let response: NearAiResponse = match self.send_request("responses", &request).await {
|
||||
Ok(r) => r,
|
||||
Err(LlmError::InvalidResponse { reason, .. })
|
||||
if reason.starts_with("Unexpected response format. Raw: ") =>
|
||||
{
|
||||
// API returned plain text instead of JSON structure
|
||||
let raw_text = reason
|
||||
.strip_prefix("Unexpected response format. Raw: ")
|
||||
.unwrap_or("");
|
||||
|
||||
// Check if it's a JSON string (quoted)
|
||||
let text = if raw_text.starts_with('"') {
|
||||
serde_json::from_str::<String>(raw_text)
|
||||
.unwrap_or_else(|_| raw_text.to_string())
|
||||
} else {
|
||||
raw_text.to_string()
|
||||
};
|
||||
|
||||
tracing::info!("NEAR AI returned plain text response");
|
||||
return Ok(CompletionResponse {
|
||||
content: text,
|
||||
finish_reason: FinishReason::Stop,
|
||||
input_tokens: 0,
|
||||
output_tokens: 0,
|
||||
});
|
||||
}
|
||||
Err(e) => return Err(e),
|
||||
};
|
||||
|
||||
tracing::debug!("NEAR AI response: {:?}", response);
|
||||
|
||||
@@ -208,7 +241,35 @@ impl LlmProvider for NearAiProvider {
|
||||
tools: if tools.is_empty() { None } else { Some(tools) },
|
||||
};
|
||||
|
||||
let response: NearAiResponse = self.send_request("responses", &request).await?;
|
||||
// Try to get structured response, fall back to raw text
|
||||
let response: NearAiResponse = match self.send_request("responses", &request).await {
|
||||
Ok(r) => r,
|
||||
Err(LlmError::InvalidResponse { reason, .. })
|
||||
if reason.starts_with("Unexpected response format. Raw: ") =>
|
||||
{
|
||||
// API returned plain text instead of JSON structure
|
||||
let raw_text = reason
|
||||
.strip_prefix("Unexpected response format. Raw: ")
|
||||
.unwrap_or("");
|
||||
|
||||
let text = if raw_text.starts_with('"') {
|
||||
serde_json::from_str::<String>(raw_text)
|
||||
.unwrap_or_else(|_| raw_text.to_string())
|
||||
} else {
|
||||
raw_text.to_string()
|
||||
};
|
||||
|
||||
tracing::info!("NEAR AI returned plain text response (tool request)");
|
||||
return Ok(ToolCompletionResponse {
|
||||
content: Some(text),
|
||||
tool_calls: vec![],
|
||||
finish_reason: FinishReason::Stop,
|
||||
input_tokens: 0,
|
||||
output_tokens: 0,
|
||||
});
|
||||
}
|
||||
Err(e) => return Err(e),
|
||||
};
|
||||
|
||||
// Extract text and tool calls from response
|
||||
let mut text = String::new();
|
||||
|
||||
Reference in New Issue
Block a user