Fix extra newlines before tool calls in JSON filter
The JSON tool call filter was outputting newlines immediately as they were encountered. When the LLM output contained multiple newlines before a tool call, each newline was output before the tool call JSON was detected and suppressed, leaving orphaned blank lines in the output. Changes: - Add pending_newlines field to FilterState to buffer newlines at line start - First newline after content is output immediately, subsequent ones buffered - When tool call confirmed, pending_newlines cleared (suppressing extra blanks) - When not a tool call, pending_newlines output with the buffer - Add flush_json_tool_filter() to flush pending content at end of streaming - Update tests to reflect new behavior - Add tests for newline suppression behavior
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
//! These tests hammer the filter with malformed JSON, partial tool calls,
|
||||
//! edge cases, and adversarial inputs to ensure robustness.
|
||||
|
||||
use g3_cli::filter_json::{filter_json_tool_calls, reset_json_tool_state};
|
||||
use g3_cli::filter_json::{filter_json_tool_calls, flush_json_tool_filter, reset_json_tool_state};
|
||||
|
||||
// ============================================================================
|
||||
// Malformed JSON Tests
|
||||
@@ -478,7 +478,9 @@ fn test_empty_input() {
|
||||
#[test]
|
||||
fn test_just_newline() {
|
||||
reset_json_tool_state();
|
||||
assert_eq!(filter_json_tool_calls("\n"), "\n");
|
||||
let result = filter_json_tool_calls("\n");
|
||||
let flushed = flush_json_tool_filter();
|
||||
assert_eq!(format!("{}{}", result, flushed), "\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -211,7 +211,8 @@ After"#;
|
||||
{"tool": "final_output", "args": {"summary": "Task completed successfully"}}"#;
|
||||
|
||||
let result = filter_json_tool_calls(input);
|
||||
let expected = "\n";
|
||||
// Leading newline before tool call at start of input is suppressed
|
||||
let expected = "";
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
|
||||
@@ -509,13 +510,13 @@ End"#;
|
||||
|
||||
let result = filter_json_tool_calls(input);
|
||||
|
||||
// The tool call starts on its own line after the read_file output,
|
||||
// so it should be filtered out. Only the read_file output should remain.
|
||||
// The tool call starts on its own line after the read_file output.
|
||||
// The tool call is filtered out, and extra newlines before it are suppressed.
|
||||
// Only one newline remains (the line ending after "1ms").
|
||||
let expected = r#"┌─ read_file | ./crates/g3-cli/src/ui_writer_impl.rs [13000..13300]
|
||||
│ }
|
||||
│ (11 lines)
|
||||
└─ ⚡️ 1ms
|
||||
|
||||
"#;
|
||||
assert_eq!(
|
||||
result, expected,
|
||||
@@ -538,9 +539,10 @@ End"#;
|
||||
let result = filter_json_tool_calls(input);
|
||||
|
||||
// The shell tool call starts at line beginning, so it should be filtered out
|
||||
// Only the surrounding text should remain
|
||||
// Note: The tool call is on its own line, so filtering leaves an empty line
|
||||
let expected = "Let me create a test case:\n\n\n\nDone.";
|
||||
// Only the surrounding text should remain.
|
||||
// Extra newlines before the tool call are suppressed (one blank line before
|
||||
// becomes just the line ending), but newlines after are preserved.
|
||||
let expected = "Let me create a test case:\n\n\nDone.";
|
||||
|
||||
assert_eq!(
|
||||
result, expected,
|
||||
|
||||
Reference in New Issue
Block a user