fix: gemini route, usage capture, search timeout, and trace finalization

- Add missing /v1/gemini POST route and handler
- Capture MitmEvent::Usage in gemini sync/streaming handlers
- Add retry counter (max 3) to search handler to prevent hang
- Add trace finalization at all gemini_sync channel exit points
- Fix UpstreamError trace outcome label
- Add timeout trace with error recording
- Dispatch Usage before ResponseComplete in SSE flush
This commit is contained in:
Nikketryhard
2026-02-18 01:31:18 -06:00
parent 48674f65da
commit 28d3296c87
11 changed files with 1480 additions and 221 deletions

View File

@@ -89,6 +89,8 @@ pub struct StreamingAccumulator {
pub grounding_metadata: Option<serde_json::Value>,
/// Buffer for reassembling lines split across TCP reads.
pub pending_data: String,
/// Thinking signature (base64 opaque blob) from non-function-call response parts.
pub thinking_signature: Option<String>,
}
impl StreamingAccumulator {
@@ -150,8 +152,12 @@ impl StreamingAccumulator {
.as_secs(),
});
}
// Capture non-thinking response text (skip thoughtSignature parts)
else if part.get("thoughtSignature").is_none() {
// Capture non-thinking response text
else {
// Capture thoughtSignature from response parts (not function call parts)
if let Some(sig) = part.get("thoughtSignature").and_then(|v| v.as_str()) {
self.thinking_signature = Some(sig.to_string());
}
if let Some(text) = part["text"].as_str() {
if !text.is_empty() {
self.response_text.push_str(text);
@@ -277,6 +283,7 @@ impl StreamingAccumulator {
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_secs(),
thinking_signature: self.thinking_signature,
}
}
}
@@ -302,6 +309,7 @@ fn extract_usage_from_message(msg: &Value) -> Option<ApiUsage> {
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_secs(),
thinking_signature: None,
})
}