auto mode and message fix
This commit is contained in:
@@ -859,6 +859,7 @@ async fn run_autonomous(
|
|||||||
show_code: bool,
|
show_code: bool,
|
||||||
max_turns: usize,
|
max_turns: usize,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
let start_time = std::time::Instant::now();
|
||||||
let output = SimpleOutput::new();
|
let output = SimpleOutput::new();
|
||||||
|
|
||||||
output.print("🤖 G3 AI Coding Agent - Autonomous Mode");
|
output.print("🤖 G3 AI Coding Agent - Autonomous Mode");
|
||||||
@@ -875,6 +876,26 @@ async fn run_autonomous(
|
|||||||
" {}/requirements.md",
|
" {}/requirements.md",
|
||||||
project.workspace().display()
|
project.workspace().display()
|
||||||
));
|
));
|
||||||
|
|
||||||
|
// Generate final report even for early exit
|
||||||
|
let elapsed = start_time.elapsed();
|
||||||
|
let context_window = agent.get_context_window();
|
||||||
|
|
||||||
|
output.print(&format!("\n{}", "=".repeat(60)));
|
||||||
|
output.print("📊 AUTONOMOUS MODE SESSION REPORT");
|
||||||
|
output.print(&"=".repeat(60));
|
||||||
|
|
||||||
|
output.print(&format!("⏱️ Total Duration: {:.2}s", elapsed.as_secs_f64()));
|
||||||
|
output.print(&format!("🔄 Turns Taken: 0/{}", max_turns));
|
||||||
|
output.print(&format!("📝 Final Status: ⚠️ NO REQUIREMENTS FILE"));
|
||||||
|
|
||||||
|
output.print("\n📈 Token Usage Statistics:");
|
||||||
|
output.print(&format!(" • Used Tokens: {}", context_window.used_tokens));
|
||||||
|
output.print(&format!(" • Total Available: {}", context_window.total_tokens));
|
||||||
|
output.print(&format!(" • Cumulative Tokens: {}", context_window.cumulative_tokens));
|
||||||
|
output.print(&format!(" • Usage Percentage: {:.1}%", context_window.percentage_used()));
|
||||||
|
output.print(&"=".repeat(60));
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -883,6 +904,26 @@ async fn run_autonomous(
|
|||||||
Some(content) => content,
|
Some(content) => content,
|
||||||
None => {
|
None => {
|
||||||
output.print("❌ Error: Could not read requirements.md");
|
output.print("❌ Error: Could not read requirements.md");
|
||||||
|
|
||||||
|
// Generate final report even for early exit
|
||||||
|
let elapsed = start_time.elapsed();
|
||||||
|
let context_window = agent.get_context_window();
|
||||||
|
|
||||||
|
output.print(&format!("\n{}", "=".repeat(60)));
|
||||||
|
output.print("📊 AUTONOMOUS MODE SESSION REPORT");
|
||||||
|
output.print(&"=".repeat(60));
|
||||||
|
|
||||||
|
output.print(&format!("⏱️ Total Duration: {:.2}s", elapsed.as_secs_f64()));
|
||||||
|
output.print(&format!("🔄 Turns Taken: 0/{}", max_turns));
|
||||||
|
output.print(&format!("📝 Final Status: ⚠️ CANNOT READ REQUIREMENTS"));
|
||||||
|
|
||||||
|
output.print("\n📈 Token Usage Statistics:");
|
||||||
|
output.print(&format!(" • Used Tokens: {}", context_window.used_tokens));
|
||||||
|
output.print(&format!(" • Total Available: {}", context_window.total_tokens));
|
||||||
|
output.print(&format!(" • Cumulative Tokens: {}", context_window.cumulative_tokens));
|
||||||
|
output.print(&format!(" • Usage Percentage: {:.1}%", context_window.percentage_used()));
|
||||||
|
output.print(&"=".repeat(60));
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -947,6 +988,26 @@ async fn run_autonomous(
|
|||||||
// Check if this is a panic (unrecoverable)
|
// Check if this is a panic (unrecoverable)
|
||||||
if e.to_string().contains("panic") {
|
if e.to_string().contains("panic") {
|
||||||
output.print(&format!("💥 Player panic detected: {}", e));
|
output.print(&format!("💥 Player panic detected: {}", e));
|
||||||
|
|
||||||
|
// Generate final report even for panic
|
||||||
|
let elapsed = start_time.elapsed();
|
||||||
|
let context_window = agent.get_context_window();
|
||||||
|
|
||||||
|
output.print(&format!("\n{}", "=".repeat(60)));
|
||||||
|
output.print("📊 AUTONOMOUS MODE SESSION REPORT");
|
||||||
|
output.print(&"=".repeat(60));
|
||||||
|
|
||||||
|
output.print(&format!("⏱️ Total Duration: {:.2}s", elapsed.as_secs_f64()));
|
||||||
|
output.print(&format!("🔄 Turns Taken: {}/{}", turn, max_turns));
|
||||||
|
output.print(&format!("📝 Final Status: 💥 PLAYER PANIC"));
|
||||||
|
|
||||||
|
output.print("\n📈 Token Usage Statistics:");
|
||||||
|
output.print(&format!(" • Used Tokens: {}", context_window.used_tokens));
|
||||||
|
output.print(&format!(" • Total Available: {}", context_window.total_tokens));
|
||||||
|
output.print(&format!(" • Cumulative Tokens: {}", context_window.cumulative_tokens));
|
||||||
|
output.print(&format!(" • Usage Percentage: {:.1}%", context_window.percentage_used()));
|
||||||
|
output.print(&"=".repeat(60));
|
||||||
|
|
||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1048,6 +1109,26 @@ Remember: Be thorough in your review but concise in your feedback. APPROVE if th
|
|||||||
// Check if this is a panic (unrecoverable)
|
// Check if this is a panic (unrecoverable)
|
||||||
if e.to_string().contains("panic") {
|
if e.to_string().contains("panic") {
|
||||||
output.print(&format!("💥 Coach panic detected: {}", e));
|
output.print(&format!("💥 Coach panic detected: {}", e));
|
||||||
|
|
||||||
|
// Generate final report even for panic
|
||||||
|
let elapsed = start_time.elapsed();
|
||||||
|
let context_window = agent.get_context_window();
|
||||||
|
|
||||||
|
output.print(&format!("\n{}", "=".repeat(60)));
|
||||||
|
output.print("📊 AUTONOMOUS MODE SESSION REPORT");
|
||||||
|
output.print(&"=".repeat(60));
|
||||||
|
|
||||||
|
output.print(&format!("⏱️ Total Duration: {:.2}s", elapsed.as_secs_f64()));
|
||||||
|
output.print(&format!("🔄 Turns Taken: {}/{}", turn, max_turns));
|
||||||
|
output.print(&format!("📝 Final Status: 💥 COACH PANIC"));
|
||||||
|
|
||||||
|
output.print("\n📈 Token Usage Statistics:");
|
||||||
|
output.print(&format!(" • Used Tokens: {}", context_window.used_tokens));
|
||||||
|
output.print(&format!(" • Total Available: {}", context_window.total_tokens));
|
||||||
|
output.print(&format!(" • Cumulative Tokens: {}", context_window.cumulative_tokens));
|
||||||
|
output.print(&format!(" • Usage Percentage: {:.1}%", context_window.percentage_used()));
|
||||||
|
output.print(&"=".repeat(60));
|
||||||
|
|
||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1127,6 +1208,33 @@ Remember: Be thorough in your review but concise in your feedback. APPROVE if th
|
|||||||
output.print("🔄 Coach provided feedback for next iteration");
|
output.print("🔄 Coach provided feedback for next iteration");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate final report
|
||||||
|
let elapsed = start_time.elapsed();
|
||||||
|
let context_window = agent.get_context_window();
|
||||||
|
|
||||||
|
output.print(&format!("\n{}", "=".repeat(60)));
|
||||||
|
output.print("📊 AUTONOMOUS MODE SESSION REPORT");
|
||||||
|
output.print(&"=".repeat(60));
|
||||||
|
|
||||||
|
output.print(&format!("⏱️ Total Duration: {:.2}s", elapsed.as_secs_f64()));
|
||||||
|
output.print(&format!("🔄 Turns Taken: {}/{}", turn, max_turns));
|
||||||
|
output.print(&format!("📝 Final Status: {}",
|
||||||
|
if implementation_approved {
|
||||||
|
"✅ APPROVED"
|
||||||
|
} else if turn >= max_turns {
|
||||||
|
"⏰ MAX TURNS REACHED"
|
||||||
|
} else {
|
||||||
|
"⚠️ INCOMPLETE"
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
output.print("\n📈 Token Usage Statistics:");
|
||||||
|
output.print(&format!(" • Used Tokens: {}", context_window.used_tokens));
|
||||||
|
output.print(&format!(" • Total Available: {}", context_window.total_tokens));
|
||||||
|
output.print(&format!(" • Cumulative Tokens: {}", context_window.cumulative_tokens));
|
||||||
|
output.print(&format!(" • Usage Percentage: {:.1}%", context_window.percentage_used()));
|
||||||
|
output.print(&"=".repeat(60));
|
||||||
|
|
||||||
if implementation_approved {
|
if implementation_approved {
|
||||||
output.print("\n🎉 Autonomous mode completed successfully");
|
output.print("\n🎉 Autonomous mode completed successfully");
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1399,6 +1399,10 @@ The tool will execute immediately and you'll receive the result (success or erro
|
|||||||
for tool_call in completed_tools {
|
for tool_call in completed_tools {
|
||||||
debug!("Processing completed tool call: {:?}", tool_call);
|
debug!("Processing completed tool call: {:?}", tool_call);
|
||||||
|
|
||||||
|
// Track what we've already displayed before getting new text
|
||||||
|
// This prevents re-displaying old content after tool execution
|
||||||
|
let already_displayed_chars = current_response.chars().count();
|
||||||
|
|
||||||
// Get the text content accumulated so far
|
// Get the text content accumulated so far
|
||||||
let text_content = parser.get_text_content();
|
let text_content = parser.get_text_content();
|
||||||
|
|
||||||
@@ -1414,14 +1418,18 @@ The tool will execute immediately and you'll receive the result (success or erro
|
|||||||
let final_display_content = filtered_content.trim();
|
let final_display_content = filtered_content.trim();
|
||||||
|
|
||||||
// Display any new content before tool execution
|
// Display any new content before tool execution
|
||||||
|
// We need to skip what was already shown (tracked in current_response)
|
||||||
|
// but also account for the fact that parser.text_buffer accumulates
|
||||||
|
// across iterations and is never cleared until reset()
|
||||||
let new_content =
|
let new_content =
|
||||||
if current_response.len() <= final_display_content.len() {
|
if current_response.len() <= final_display_content.len() {
|
||||||
let chars_already_shown = current_response.chars().count();
|
// Only show content that hasn't been displayed yet
|
||||||
final_display_content
|
final_display_content
|
||||||
.chars()
|
.chars()
|
||||||
.skip(chars_already_shown)
|
.skip(already_displayed_chars)
|
||||||
.collect::<String>()
|
.collect::<String>()
|
||||||
} else {
|
} else {
|
||||||
|
// Nothing new to display
|
||||||
String::new()
|
String::new()
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1432,6 +1440,8 @@ The tool will execute immediately and you'll receive the result (success or erro
|
|||||||
}
|
}
|
||||||
self.ui_writer.print_agent_response(&new_content);
|
self.ui_writer.print_agent_response(&new_content);
|
||||||
self.ui_writer.flush();
|
self.ui_writer.flush();
|
||||||
|
// Update current_response to track what we've displayed
|
||||||
|
current_response.push_str(&new_content);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute the tool with formatted output
|
// Execute the tool with formatted output
|
||||||
@@ -1592,6 +1602,11 @@ The tool will execute immediately and you'll receive the result (success or erro
|
|||||||
|
|
||||||
// Reset parser for next iteration
|
// Reset parser for next iteration
|
||||||
parser.reset();
|
parser.reset();
|
||||||
|
// Clear current_response for next iteration to prevent buffered text
|
||||||
|
// from being incorrectly displayed after tool execution
|
||||||
|
current_response.clear();
|
||||||
|
// Reset response_started flag for next iteration
|
||||||
|
response_started = false;
|
||||||
break; // Break out of current stream to start a new one
|
break; // Break out of current stream to start a new one
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1971,8 +1986,22 @@ The tool will execute immediately and you'll receive the result (success or erro
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract the requested portion
|
// Extract the requested portion, ensuring we're at char boundaries
|
||||||
let partial_content = &content[start..end];
|
// Find the nearest valid char boundaries
|
||||||
|
let start_boundary = if start == 0 {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
content.char_indices()
|
||||||
|
.find(|(i, _)| *i >= start)
|
||||||
|
.map(|(i, _)| i)
|
||||||
|
.unwrap_or(start)
|
||||||
|
};
|
||||||
|
let end_boundary = content.char_indices()
|
||||||
|
.find(|(i, _)| *i >= end)
|
||||||
|
.map(|(i, _)| i)
|
||||||
|
.unwrap_or(content.len());
|
||||||
|
|
||||||
|
let partial_content = &content[start_boundary..end_boundary];
|
||||||
let line_count = partial_content.lines().count();
|
let line_count = partial_content.lines().count();
|
||||||
let total_lines = content.lines().count();
|
let total_lines = content.lines().count();
|
||||||
|
|
||||||
@@ -1980,7 +2009,7 @@ The tool will execute immediately and you'll receive the result (success or erro
|
|||||||
if start_char.is_some() || end_char.is_some() {
|
if start_char.is_some() || end_char.is_some() {
|
||||||
Ok(format!(
|
Ok(format!(
|
||||||
"📄 File content (chars {}-{}, {} lines of {} total):\n{}",
|
"📄 File content (chars {}-{}, {} lines of {} total):\n{}",
|
||||||
start, end, line_count, total_lines, partial_content
|
start_boundary, end_boundary, line_count, total_lines, partial_content
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
Ok(format!(
|
Ok(format!(
|
||||||
@@ -2587,8 +2616,22 @@ pub fn apply_unified_diff_to_string(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract the region we're going to modify (whole file if no bounds provided)
|
// Extract the region we're going to modify, ensuring we're at char boundaries
|
||||||
let mut region_content = content_norm[search_start..search_end].to_string();
|
// Find the nearest valid char boundaries
|
||||||
|
let start_boundary = if search_start == 0 {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
content_norm.char_indices()
|
||||||
|
.find(|(i, _)| *i >= search_start)
|
||||||
|
.map(|(i, _)| i)
|
||||||
|
.unwrap_or(search_start)
|
||||||
|
};
|
||||||
|
let end_boundary = content_norm.char_indices()
|
||||||
|
.find(|(i, _)| *i >= search_end)
|
||||||
|
.map(|(i, _)| i)
|
||||||
|
.unwrap_or(content_norm.len());
|
||||||
|
|
||||||
|
let mut region_content = content_norm[start_boundary..end_boundary].to_string();
|
||||||
|
|
||||||
// Apply hunks in order
|
// Apply hunks in order
|
||||||
for (idx, (old_block, new_block)) in hunks.iter().enumerate() {
|
for (idx, (old_block, new_block)) in hunks.iter().enumerate() {
|
||||||
@@ -2611,7 +2654,7 @@ pub fn apply_unified_diff_to_string(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let range_note = if start_char.is_some() || end_char.is_some() {
|
let range_note = if start_char.is_some() || end_char.is_some() {
|
||||||
format!(" (within character range {}:{})", search_start, search_end)
|
format!(" (within character range {}:{})", start_boundary, end_boundary)
|
||||||
} else {
|
} else {
|
||||||
String::new()
|
String::new()
|
||||||
};
|
};
|
||||||
@@ -2627,9 +2670,9 @@ pub fn apply_unified_diff_to_string(
|
|||||||
|
|
||||||
// Reconstruct the full content with the modified region
|
// Reconstruct the full content with the modified region
|
||||||
let mut result = String::with_capacity(content_norm.len() + region_content.len());
|
let mut result = String::with_capacity(content_norm.len() + region_content.len());
|
||||||
result.push_str(&content_norm[..search_start]);
|
result.push_str(&content_norm[..start_boundary]);
|
||||||
result.push_str(®ion_content);
|
result.push_str(®ion_content);
|
||||||
result.push_str(&content_norm[search_end..]);
|
result.push_str(&content_norm[end_boundary..]);
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user