bug fixes

This commit is contained in:
jaberjaber23
2026-03-18 05:08:12 +03:00
parent f1ca52714d
commit 88bb55c8f2
3 changed files with 66 additions and 4 deletions
+16 -1
View File
@@ -1085,7 +1085,11 @@ impl OpenFangKernel {
|| disk_manifest.model.model
!= entry.manifest.model.model
|| disk_manifest.capabilities.tools
!= entry.manifest.capabilities.tools;
!= entry.manifest.capabilities.tools
|| disk_manifest.tool_allowlist
!= entry.manifest.tool_allowlist
|| disk_manifest.tool_blocklist
!= entry.manifest.tool_blocklist;
if changed {
info!(
agent = %name,
@@ -4738,6 +4742,17 @@ impl OpenFangKernel {
McpTransportEntry::Sse { url } => McpTransport::Sse { url: url.clone() },
};
// Resolve env vars from vault/dotenv before passing to MCP subprocess.
// The MCP spawn calls env_clear() then re-adds only whitelisted vars
// from std::env — so we must ensure they're in std::env first.
for var_name in &server_config.env {
if std::env::var(var_name).is_err() {
if let Some(val) = self.resolve_credential(var_name) {
std::env::set_var(var_name, &val);
}
}
}
let mcp_config = McpServerConfig {
name: server_config.name.clone(),
transport,
+39 -3
View File
@@ -244,7 +244,9 @@ pub async fn run_agent_loop(
}
// Build the messages for the LLM, filtering system messages
// System prompt goes into the separate `system` field
// System prompt goes into the separate `system` field.
// NOTE: We build llm_messages BEFORE stripping images so the LLM
// sees the full image data for the current turn.
let llm_messages: Vec<Message> = session
.messages
.iter()
@@ -252,6 +254,23 @@ pub async fn run_agent_loop(
.cloned()
.collect();
// Strip Image blocks from session to prevent base64 bloat.
// The LLM already received them via llm_messages above.
for msg in session.messages.iter_mut() {
if let MessageContent::Blocks(blocks) = &mut msg.content {
let had_images = blocks.iter().any(|b| matches!(b, ContentBlock::Image { .. }));
if had_images {
blocks.retain(|b| !matches!(b, ContentBlock::Image { .. }));
if blocks.is_empty() {
blocks.push(ContentBlock::Text {
text: "[Image processed]".to_string(),
provider_metadata: None,
});
}
}
}
}
// Validate and repair session history (drop orphans, merge consecutive)
let mut messages = crate::session_repair::validate_and_repair(&llm_messages);
@@ -421,7 +440,7 @@ pub async fn run_agent_loop(
// One-shot retry: if the LLM returns empty text with no tool use,
// try once more before accepting the empty result.
// Triggers on first call OR when input_tokens=0 (silently failed request).
if text.trim().is_empty() && response.tool_calls.is_empty() {
if text.trim().is_empty() && response.tool_calls.is_empty() && !response.has_any_content() {
let is_silent_failure =
response.usage.input_tokens == 0 && response.usage.output_tokens == 0;
if iteration == 0 || is_silent_failure {
@@ -1221,6 +1240,23 @@ pub async fn run_agent_loop_streaming(
.cloned()
.collect();
// Strip Image blocks from session to prevent base64 bloat.
// The LLM already received them via llm_messages above.
for msg in session.messages.iter_mut() {
if let MessageContent::Blocks(blocks) = &mut msg.content {
let had_images = blocks.iter().any(|b| matches!(b, ContentBlock::Image { .. }));
if had_images {
blocks.retain(|b| !matches!(b, ContentBlock::Image { .. }));
if blocks.is_empty() {
blocks.push(ContentBlock::Text {
text: "[Image processed]".to_string(),
provider_metadata: None,
});
}
}
}
}
// Validate and repair session history (drop orphans, merge consecutive)
let mut messages = crate::session_repair::validate_and_repair(&llm_messages);
@@ -1408,7 +1444,7 @@ pub async fn run_agent_loop_streaming(
// One-shot retry: if the LLM returns empty text with no tool use,
// try once more before accepting the empty result.
// Triggers on first call OR when input_tokens=0 (silently failed request).
if text.trim().is_empty() && response.tool_calls.is_empty() {
if text.trim().is_empty() && response.tool_calls.is_empty() && !response.has_any_content() {
let is_silent_failure =
response.usage.input_tokens == 0 && response.usage.output_tokens == 0;
if iteration == 0 || is_silent_failure {
+11
View File
@@ -93,6 +93,17 @@ impl CompletionResponse {
.collect::<Vec<_>>()
.join("")
}
/// Check if the response has any meaningful content (including Thinking blocks).
/// Used to distinguish true empty responses from thinking-only responses.
pub fn has_any_content(&self) -> bool {
self.content.iter().any(|block| match block {
ContentBlock::Text { text, .. } => !text.is_empty(),
ContentBlock::Thinking { thinking, .. } => !thinking.is_empty(),
ContentBlock::ToolUse { .. } | ContentBlock::Image { .. } => true,
_ => false,
})
}
}
/// Events emitted during streaming LLM completion.