From 1ae64981d823341ff4592aa6c3bd4441fdffd54c Mon Sep 17 00:00:00 2001 From: Illia Polosukhin Date: Tue, 3 Feb 2026 00:18:34 -0800 Subject: [PATCH] Improve NEAR AI response parsing for varying response formats - Add direct text field support on NearAiOutputItem - Accept both "output_text" and "text" content types - Join all content items instead of taking just the first - Better debug logging showing item.text field Co-Authored-By: Claude Opus 4.5 --- src/llm/nearai.rs | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/src/llm/nearai.rs b/src/llm/nearai.rs index 00516911..2bc3ee80 100644 --- a/src/llm/nearai.rs +++ b/src/llm/nearai.rs @@ -121,13 +121,23 @@ impl LlmProvider for NearAiProvider { tracing::debug!("NEAR AI response: {:?}", response); // Extract text from response output + // Try multiple formats since API response shape may vary let text = response .output .iter() .filter_map(|item| { - tracing::debug!("Processing output item: type={}", item.item_type); + tracing::debug!( + "Processing output item: type={}, text={:?}", + item.item_type, + item.text + ); if item.item_type == "message" { - item.content.as_ref().and_then(|contents| { + // First check for direct text field on item + if let Some(ref text) = item.text { + return Some(text.clone()); + } + // Then check content array + item.content.as_ref().map(|contents| { contents .iter() .filter_map(|c| { @@ -136,13 +146,14 @@ impl LlmProvider for NearAiProvider { c.content_type, c.text ); - if c.content_type == "output_text" { - c.text.clone() - } else { - None + // Accept various content types that might contain text + match c.content_type.as_str() { + "output_text" | "text" => c.text.clone(), + _ => None, } }) - .next() + .collect::>() + .join("") }) } else { None @@ -315,6 +326,9 @@ struct NearAiOutputItem { item_type: String, #[serde(default)] content: Option>, + // Direct text field (some response formats) + #[serde(default)] + text: Option, // For function calls #[serde(default)] name: Option,