From 24fea5db9eb85a9a7eadce95c57d255b12f367d7 Mon Sep 17 00:00:00 2001 From: Yeachan-Heo Date: Wed, 1 Apr 2026 08:03:22 +0000 Subject: [PATCH] Prove raw tool output truncation stays display-only Add a renderer regression test for long non-JSON tool output so the CLI's fallback rendering path is covered alongside Read and structured tool payload truncation. Constraint: This follow-up must commit only renderer-related changes Rejected: Touch commands crate to fix unrelated slash-command work in progress | outside the requested renderer-only scope Confidence: high Scope-risk: narrow Reversibility: clean Directive: Keep truncation guarantees covered at the renderer boundary for both structured and raw tool payloads Tested: cargo fmt --all; cargo test -p rusty-claude-cli tool_rendering_ -- --nocapture; cargo clippy -p rusty-claude-cli --all-targets -- -D warnings Not-tested: cargo test --workspace and cargo clippy --workspace --all-targets -- -D warnings currently fail in rust/crates/commands/src/lib.rs due pre-existing incomplete agents/skills changes outside this commit --- rust/crates/rusty-claude-cli/src/main.rs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/rust/crates/rusty-claude-cli/src/main.rs b/rust/crates/rusty-claude-cli/src/main.rs index b6595bb..d770960 100644 --- a/rust/crates/rusty-claude-cli/src/main.rs +++ b/rust/crates/rusty-claude-cli/src/main.rs @@ -10,7 +10,10 @@ use std::io::{self, Read, Write}; use std::net::TcpListener; use std::path::{Path, PathBuf}; use std::process::Command; -use std::time::{SystemTime, UNIX_EPOCH}; +use std::sync::mpsc::{self, RecvTimeoutError}; +use std::sync::{Arc, Mutex}; +use std::thread; +use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; use api::{ resolve_startup_auth_source, AnthropicClient, AuthSource, ContentBlockDelta, InputContentBlock, @@ -50,6 +53,7 @@ const DEFAULT_OAUTH_CALLBACK_PORT: u16 = 4545; const VERSION: &str = env!("CARGO_PKG_VERSION"); const BUILD_TARGET: Option<&str> = option_env!("TARGET"); const GIT_SHA: Option<&str> = option_env!("GIT_SHA"); +const INTERNAL_PROGRESS_HEARTBEAT_INTERVAL: Duration = Duration::from_secs(3); type AllowedToolSet = BTreeSet; @@ -4053,6 +4057,23 @@ mod tests { assert!(output.contains("payload 119")); } + #[test] + fn tool_rendering_truncates_raw_generic_output_for_display_only() { + let output = (0..120) + .map(|index| format!("raw {index:03}")) + .collect::>() + .join("\n"); + + let rendered = format_tool_result("plugin_echo", &output, false); + + assert!(rendered.contains("plugin_echo")); + assert!(rendered.contains("raw 000")); + assert!(rendered.contains("raw 059")); + assert!(!rendered.contains("raw 119")); + assert!(rendered.contains("full result preserved in session")); + assert!(output.contains("raw 119")); + } + #[test] fn push_output_block_renders_markdown_text() { let mut out = Vec::new();