Centralize g3 status message formatting
Extract a new g3_status module in g3-cli that provides consistent formatting for all 'g3:' prefixed system status messages. Key changes: - Add G3Status struct with methods for progress, done, failed, error, etc. - Add Status enum with Done, Failed, Error, Resolved, Insufficient, NoChanges - Add ThinResult struct in g3-core for semantic thinning data - Update UiWriter trait with print_thin_result() method - Refactor context thinning to return ThinResult instead of formatted strings - Update all callers to use the new centralized formatting - Session resume/decline messages now use G3Status - Compaction status messages now use G3Status This maintains clean separation of concerns: g3-core emits semantic data, g3-cli handles all terminal formatting and colors.
This commit is contained in:
@@ -274,7 +274,7 @@ impl UiWriter for TrackingUiWriter {
|
||||
fn print_context_status(&self, _message: &str) {}
|
||||
fn print_g3_progress(&self, _message: &str) {}
|
||||
fn print_g3_status(&self, _message: &str, _status: &str) {}
|
||||
fn print_context_thinning(&self, _message: &str) {}
|
||||
fn print_thin_result(&self, _result: &g3_core::ThinResult) {}
|
||||
|
||||
fn print_tool_header(&self, _tool_name: &str, _tool_args: Option<&serde_json::Value>) {
|
||||
// Count each tool call
|
||||
|
||||
@@ -69,14 +69,13 @@ fn test_thin_context_basic() {
|
||||
|
||||
// Trigger thinning at 50%
|
||||
context.used_tokens = 5000;
|
||||
let (summary, _chars_saved) = context.thin_context(None);
|
||||
let result = context.thin_context(None);
|
||||
|
||||
println!("Thinning summary: {}", summary);
|
||||
println!("Thinning result: {:?}", result);
|
||||
|
||||
// Should show the new format with percentage change
|
||||
assert!(summary.contains("g3:"), "Summary was: {}", summary);
|
||||
assert!(summary.contains("thinning context"));
|
||||
assert!(summary.contains("[done]"));
|
||||
// Should have made changes
|
||||
assert!(result.had_changes, "Expected thinning to make changes");
|
||||
assert!(result.chars_saved > 0, "Expected chars to be saved");
|
||||
|
||||
// Check that the large tool results were replaced
|
||||
let first_third_end = context.conversation_history.len() / 3;
|
||||
@@ -127,14 +126,13 @@ fn test_thin_write_file_tool_calls() {
|
||||
|
||||
// Trigger thinning at 50%
|
||||
context.used_tokens = 5000;
|
||||
let (summary, _chars_saved) = context.thin_context(None);
|
||||
let result = context.thin_context(None);
|
||||
|
||||
println!("Thinning summary: {}", summary);
|
||||
println!("Thinning result: {:?}", result);
|
||||
|
||||
// Should show the new format with percentage change
|
||||
assert!(summary.contains("g3:"));
|
||||
assert!(summary.contains("thinning context"));
|
||||
assert!(summary.contains("[done]"));
|
||||
// Should have made changes
|
||||
assert!(result.had_changes, "Expected thinning to make changes");
|
||||
assert!(result.chars_saved > 0, "Expected chars to be saved");
|
||||
|
||||
// Check that the large content was replaced with a file reference
|
||||
let first_third_end = context.conversation_history.len() / 3;
|
||||
@@ -189,14 +187,13 @@ fn test_thin_str_replace_tool_calls() {
|
||||
|
||||
// Trigger thinning at 50%
|
||||
context.used_tokens = 5000;
|
||||
let (summary, _chars_saved) = context.thin_context(None);
|
||||
let result = context.thin_context(None);
|
||||
|
||||
println!("Thinning summary: {}", summary);
|
||||
println!("Thinning result: {:?}", result);
|
||||
|
||||
// Should show the new format with percentage change
|
||||
assert!(summary.contains("g3:"));
|
||||
assert!(summary.contains("thinning context"));
|
||||
assert!(summary.contains("[done]"));
|
||||
// Should have made changes
|
||||
assert!(result.had_changes, "Expected thinning to make changes");
|
||||
assert!(result.chars_saved > 0, "Expected chars to be saved");
|
||||
|
||||
// Check that the large diff was replaced with a file reference
|
||||
let first_third_end = context.conversation_history.len() / 3;
|
||||
@@ -225,12 +222,12 @@ fn test_thin_context_no_large_results() {
|
||||
}
|
||||
|
||||
context.used_tokens = 5000;
|
||||
let (summary, _chars_saved) = context.thin_context(None);
|
||||
let result = context.thin_context(None);
|
||||
|
||||
// Should report no large results found
|
||||
assert!(summary.contains("g3:"));
|
||||
assert!(summary.contains("thinning context"));
|
||||
assert!(summary.contains("[no changes]"));
|
||||
// Should report no changes (no large results found)
|
||||
assert!(!result.had_changes, "Expected no changes");
|
||||
assert_eq!(result.chars_saved, 0, "Expected no chars saved");
|
||||
assert_eq!(result.leaned_count, 0, "Expected no messages thinned");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -256,11 +253,10 @@ fn test_thin_context_only_affects_first_third() {
|
||||
}
|
||||
|
||||
context.used_tokens = 5000;
|
||||
let (summary, _chars_saved) = context.thin_context(None);
|
||||
let result = context.thin_context(None);
|
||||
|
||||
// Should show the new format with percentage change
|
||||
assert!(summary.contains("g3:"));
|
||||
assert!(summary.contains("[done]"));
|
||||
// Should have made changes
|
||||
assert!(result.had_changes, "Expected thinning to make changes");
|
||||
|
||||
// Check that messages after the first third are NOT thinned
|
||||
let first_third_end = context.conversation_history.len() / 3;
|
||||
|
||||
@@ -30,9 +30,9 @@ fn test_todo_read_results_not_thinned() {
|
||||
|
||||
// Trigger thinning at 50%
|
||||
context.used_tokens = 5000;
|
||||
let (summary, _chars_saved) = context.thin_context(None);
|
||||
let result = context.thin_context(None);
|
||||
|
||||
println!("Thinning summary: {}", summary);
|
||||
println!("Thinning result: {:?}", result);
|
||||
|
||||
// Check that the TODO result was NOT thinned
|
||||
let first_third_end = context.conversation_history.len() / 3;
|
||||
@@ -87,9 +87,9 @@ fn test_todo_write_results_not_thinned() {
|
||||
|
||||
// Trigger thinning at 50%
|
||||
context.used_tokens = 5000;
|
||||
let (summary, _chars_saved) = context.thin_context(None);
|
||||
let result = context.thin_context(None);
|
||||
|
||||
println!("Thinning summary: {}", summary);
|
||||
println!("Thinning result: {:?}", result);
|
||||
|
||||
// Check that the TODO write result was NOT thinned
|
||||
let first_third_end = context.conversation_history.len() / 3;
|
||||
@@ -135,14 +135,13 @@ fn test_non_todo_results_still_thinned() {
|
||||
|
||||
// Trigger thinning at 50%
|
||||
context.used_tokens = 5000;
|
||||
let (summary, _chars_saved) = context.thin_context(None);
|
||||
let result = context.thin_context(None);
|
||||
|
||||
println!("Thinning summary: {}", summary);
|
||||
println!("Thinning result: {:?}", result);
|
||||
|
||||
// Should show the new format with percentage change (indicating thinning happened)
|
||||
assert!(summary.contains("g3:"), "Non-TODO results should be thinned");
|
||||
assert!(summary.contains("thinning context"));
|
||||
assert!(summary.contains("[done]"));
|
||||
// Should have made changes (non-TODO results should be thinned)
|
||||
assert!(result.had_changes, "Non-TODO results should be thinned");
|
||||
assert!(result.chars_saved > 0, "Expected chars to be saved");
|
||||
|
||||
// Check that the result was actually thinned
|
||||
let first_third_end = context.conversation_history.len() / 3;
|
||||
@@ -184,7 +183,7 @@ fn test_todo_read_with_spaces_in_tool_name() {
|
||||
|
||||
// Trigger thinning
|
||||
context.used_tokens = 5000;
|
||||
let (_summary, _chars_saved) = context.thin_context(None);
|
||||
let _result = context.thin_context(None);
|
||||
|
||||
// Verify TODO result was not thinned
|
||||
let first_third_end = context.conversation_history.len() / 3;
|
||||
|
||||
@@ -54,7 +54,7 @@ impl UiWriter for MockUiWriter {
|
||||
}
|
||||
fn print_g3_progress(&self, _message: &str) {}
|
||||
fn print_g3_status(&self, _message: &str, _status: &str) {}
|
||||
fn print_context_thinning(&self, _message: &str) {}
|
||||
fn print_thin_result(&self, _result: &g3_core::ThinResult) {}
|
||||
fn print_tool_header(&self, _tool_name: &str, _tool_args: Option<&serde_json::Value>) {}
|
||||
fn print_tool_arg(&self, _key: &str, _value: &str) {}
|
||||
fn print_tool_output_header(&self) {}
|
||||
|
||||
Reference in New Issue
Block a user