fix(transcribe): show tool results by default with truncation

Remove the opts.include.output gate in render_entry_text so tool results
are always visible. Truncated to 200 chars by default; uncapped with
--verbose.

Closes claudbg-zy1p

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
main
Elijah Voigt 2 months ago
parent dbffc151fb
commit 1455859825

@ -1,10 +1,11 @@
---
# claudbg-zy1p
title: Tool results hidden by default in transcriptions — should show with truncation
status: todo
status: completed
type: bug
priority: normal
created_at: 2026-03-30T04:44:18Z
updated_at: 2026-03-30T04:44:18Z
updated_at: 2026-03-30T05:12:16Z
parent: claudbg-8vpb
---
@ -41,3 +42,7 @@ Also apply the same change to the `--verbose` path: when `opts.verbose` is true,
- `src/commands/sessions.rs``render_entry_text`, `ToolResult` branch (~line 113131)
- `src/commands/agents.rs``render_entry_text`, same branch (~line 7492)
## Summary of Changes
Removed opts.include.output gate in render_entry_text in both sessions.rs and agents.rs. Tool results now always shown, truncated at 200 chars by default, uncapped with --verbose.

@ -44,7 +44,7 @@ fn content_preview(entry: &crate::models::session::RawEntry, max_len: usize) ->
/// Render a single entry to stdout in human-readable text format.
///
/// Thinking blocks are shown only when `opts.include.thinking` is set.
/// Tool result blocks are shown only when `opts.include.output` is set.
/// Tool result blocks are always shown, truncated to 200 chars unless `opts.verbose`.
fn render_entry_text(entry: &crate::models::session::RawEntry, opts: &crate::cli::GlobalOpts) {
let Some(msg) = &entry.message else { return };
let role = msg.role.as_deref().unwrap_or("?");
@ -74,18 +74,20 @@ fn render_entry_text(entry: &crate::models::session::RawEntry, opts: &crate::cli
crate::models::session::ContentBlock::ToolResult {
content, is_error, ..
} => {
if opts.include.output {
let err_flag = if is_error.unwrap_or(false) {
" (error)"
} else {
""
};
let preview = content
.as_ref()
.and_then(|c| c.as_str().map(|s| s.to_string()))
.unwrap_or_else(|| {
content.as_ref().map(|c| c.to_string()).unwrap_or_default()
});
let err_flag = if is_error.unwrap_or(false) {
" (error)"
} else {
""
};
let preview = content
.as_ref()
.and_then(|c| c.as_str().map(|s| s.to_string()))
.unwrap_or_else(|| {
content.as_ref().map(|c| c.to_string()).unwrap_or_default()
});
if opts.verbose {
println!("[tool_result{err_flag}]: {preview}");
} else {
let boundary = preview.floor_char_boundary(200);
let short = &preview[..boundary];
println!("[tool_result{err_flag}]: {short}");
@ -696,9 +698,9 @@ mod tests {
render_entry_text(&entry, &opts); // must not panic
}
/// `render_entry_text` does not panic when tool results are present but gated off.
/// `render_entry_text` always shows tool results (truncated by default) without panicking.
#[test]
fn render_entry_text_tool_result_gated() {
fn render_entry_text_tool_result_always_shown() {
let entry = make_raw_entry(
"user",
"user",
@ -708,7 +710,7 @@ mod tests {
is_error: Some(false),
}]),
);
let opts = default_opts();
let opts = default_opts(); // verbose = false → truncated at 200 chars
render_entry_text(&entry, &opts); // must not panic
}
}

@ -83,7 +83,7 @@ fn content_preview(entry: &crate::models::session::RawEntry, max_len: usize) ->
/// Render a single entry to stdout in human-readable text format.
///
/// Thinking blocks are shown only when `opts.include.thinking` is set.
/// Tool result blocks are shown only when `opts.include.output` is set.
/// Tool result blocks are always shown, truncated to 200 chars unless `opts.verbose`.
fn render_entry_text(entry: &crate::models::session::RawEntry, opts: &crate::cli::GlobalOpts) {
let Some(msg) = &entry.message else { return };
let role = msg.role.as_deref().unwrap_or("?");
@ -113,18 +113,20 @@ fn render_entry_text(entry: &crate::models::session::RawEntry, opts: &crate::cli
crate::models::session::ContentBlock::ToolResult {
content, is_error, ..
} => {
if opts.include.output {
let err_flag = if is_error.unwrap_or(false) {
" (error)"
} else {
""
};
let preview = content
.as_ref()
.and_then(|c| c.as_str().map(|s| s.to_string()))
.unwrap_or_else(|| {
content.as_ref().map(|c| c.to_string()).unwrap_or_default()
});
let err_flag = if is_error.unwrap_or(false) {
" (error)"
} else {
""
};
let preview = content
.as_ref()
.and_then(|c| c.as_str().map(|s| s.to_string()))
.unwrap_or_else(|| {
content.as_ref().map(|c| c.to_string()).unwrap_or_default()
});
if opts.verbose {
println!("[tool_result{err_flag}]: {preview}");
} else {
let boundary = preview.floor_char_boundary(200);
let short = &preview[..boundary];
println!("[tool_result{err_flag}]: {short}");
@ -917,9 +919,9 @@ mod tests {
assert_eq!(result[2][0], "5-6");
}
/// `render_entry_text` does not print tool results when `include.output` is false.
/// `render_entry_text` always shows tool results (truncated by default) without panicking.
#[test]
fn render_entry_text_tool_result_gated() {
fn render_entry_text_tool_result_always_shown() {
let entry = make_raw_entry(
"user",
"user",
@ -929,7 +931,7 @@ mod tests {
is_error: Some(false),
}]),
);
let opts = default_opts(); // include.output = false
let opts = default_opts(); // verbose = false → truncated at 200 chars
render_entry_text(&entry, &opts); // must not panic
}
}

Loading…
Cancel
Save