Parser debug logging to /tmp/poc-{agent_name}.log

Logs full response text when no tool calls detected, tool call
bodies when found. Per-agent log files for debugging subconscious
agent parsing issues.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
Kent Overstreet 2026-04-08 17:39:55 -04:00
parent 473909db47
commit d4d661df5b

View file

@ -490,7 +490,10 @@ impl ResponseParser {
let (tx, rx) = tokio::sync::mpsc::unbounded_channel(); let (tx, rx) = tokio::sync::mpsc::unbounded_channel();
let handle = tokio::spawn(async move { let handle = tokio::spawn(async move {
let mut parser = self; let mut parser = self;
let debug = std::env::var("POC_DEBUG").is_ok(); let agent_name = agent.state.lock().await.provenance.clone();
let log_path = format!("/tmp/poc-{}.log", agent_name);
let mut log_file = std::fs::OpenOptions::new()
.create(true).append(true).open(&log_path).ok();
let mut full_text = String::new(); let mut full_text = String::new();
while let Some(event) = stream.recv().await { while let Some(event) = stream.recv().await {
match event { match event {
@ -498,10 +501,12 @@ impl ResponseParser {
full_text.push_str(&text); full_text.push_str(&text);
let mut ctx = agent.context.lock().await; let mut ctx = agent.context.lock().await;
let calls = parser.feed_token(&text, id, &mut ctx); let calls = parser.feed_token(&text, id, &mut ctx);
if !calls.is_empty() && debug { if !calls.is_empty() {
if let Some(ref mut f) = log_file {
use std::io::Write;
for c in &calls { for c in &calls {
eprintln!("[parser] tool_call: {} args={}", let _ = writeln!(f, "tool_call: {} args={}", c.name, &c.arguments[..c.arguments.len().min(200)]);
c.name, &c.arguments[..c.arguments.len().min(80)]); }
} }
} }
for call in calls { for call in calls {
@ -509,20 +514,21 @@ impl ResponseParser {
} }
} }
super::api::StreamToken::Done { usage } => { super::api::StreamToken::Done { usage } => {
if debug { if let Some(ref mut f) = log_file {
use std::io::Write;
let tc_count = full_text.matches("<tool_call>").count(); let tc_count = full_text.matches("<tool_call>").count();
eprintln!("[parser] done: {} chars, {} <tool_call> tags", let _ = writeln!(f, "done: {} chars, {} <tool_call> tags",
full_text.len(), tc_count); full_text.len(), tc_count);
if tc_count > 0 { if tc_count == 0 && full_text.len() > 0 {
// Log the raw text around tool calls for debugging let _ = writeln!(f, "full text:\n{}", &full_text[..full_text.len().min(2000)]);
}
for (i, part) in full_text.split("<tool_call>").enumerate() { for (i, part) in full_text.split("<tool_call>").enumerate() {
if i > 0 { if i > 0 {
eprintln!("[parser] tool_call text: {}...", let _ = writeln!(f, "tool_call body: {}...",
&part[..part.len().min(200)]); &part[..part.len().min(200)]);
} }
} }
} }
}
if let Some(u) = usage { if let Some(u) = usage {
agent.state.lock().await.last_prompt_tokens = u.prompt_tokens; agent.state.lock().await.last_prompt_tokens = u.prompt_tokens;
} }