mirror of
https://github.com/hanzoai/dev.git
synced 2026-10-25 03:32:32 +00:00
feat(tui/auto_drive): export rendered history for coordinator
This commit is contained in:
@@ -1264,6 +1264,12 @@ enum SystemPlacement {
|
|||||||
PrePromptInCurrent,
|
PrePromptInCurrent,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
enum AutoDriveRole {
|
||||||
|
User,
|
||||||
|
Assistant,
|
||||||
|
}
|
||||||
|
|
||||||
impl ChatWidget<'_> {
|
impl ChatWidget<'_> {
|
||||||
const MAX_UNDO_CONVERSATION_MESSAGES: usize = 8;
|
const MAX_UNDO_CONVERSATION_MESSAGES: usize = 8;
|
||||||
const MAX_UNDO_PREVIEW_CHARS: usize = 160;
|
const MAX_UNDO_PREVIEW_CHARS: usize = 160;
|
||||||
@@ -3543,6 +3549,26 @@ impl ChatWidget<'_> {
|
|||||||
rows.join("\n")
|
rows.join("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn auto_drive_role_for_kind(kind: HistoryCellType) -> Option<AutoDriveRole> {
|
||||||
|
use AutoDriveRole::{Assistant, User};
|
||||||
|
match kind {
|
||||||
|
HistoryCellType::User => Some(Assistant),
|
||||||
|
HistoryCellType::Assistant
|
||||||
|
| HistoryCellType::Reasoning
|
||||||
|
| HistoryCellType::Error
|
||||||
|
| HistoryCellType::Exec { .. }
|
||||||
|
| HistoryCellType::Tool { .. }
|
||||||
|
| HistoryCellType::Patch { .. }
|
||||||
|
| HistoryCellType::PlanUpdate
|
||||||
|
| HistoryCellType::BackgroundEvent
|
||||||
|
| HistoryCellType::Notice
|
||||||
|
| HistoryCellType::Diff
|
||||||
|
| HistoryCellType::Plain
|
||||||
|
| HistoryCellType::Image => Some(User),
|
||||||
|
HistoryCellType::AnimatedWelcome | HistoryCellType::Loading => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn auto_drive_cell_text(cell: &dyn HistoryCell) -> Option<String> {
|
fn auto_drive_cell_text(cell: &dyn HistoryCell) -> Option<String> {
|
||||||
let text = Self::auto_drive_lines_to_string(cell.display_lines());
|
let text = Self::auto_drive_lines_to_string(cell.display_lines());
|
||||||
if text.trim().is_empty() {
|
if text.trim().is_empty() {
|
||||||
@@ -3658,31 +3684,12 @@ impl ChatWidget<'_> {
|
|||||||
pub(crate) fn export_auto_drive_items(&self) -> Vec<codex_protocol::models::ResponseItem> {
|
pub(crate) fn export_auto_drive_items(&self) -> Vec<codex_protocol::models::ResponseItem> {
|
||||||
let mut items = Vec::new();
|
let mut items = Vec::new();
|
||||||
for cell in &self.history_cells {
|
for cell in &self.history_cells {
|
||||||
match cell.kind() {
|
let Some(role) = Self::auto_drive_role_for_kind(cell.kind()) else {
|
||||||
HistoryCellType::User => {
|
continue;
|
||||||
if let Some(text) = Self::auto_drive_cell_text(cell.as_ref()) {
|
};
|
||||||
if let Some(item) = Self::auto_drive_make_assistant_message(text) {
|
|
||||||
items.push(item);
|
let text = match cell.kind() {
|
||||||
}
|
HistoryCellType::Reasoning => Self::auto_drive_cell_text(cell.as_ref()).map(|text| (text, true)),
|
||||||
}
|
|
||||||
}
|
|
||||||
HistoryCellType::Assistant => {
|
|
||||||
if let Some(text) = Self::auto_drive_cell_text(cell.as_ref()) {
|
|
||||||
if let Some(item) = Self::auto_drive_make_user_message(text) {
|
|
||||||
items.push(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
HistoryCellType::Reasoning => {
|
|
||||||
if let Some(text) = Self::auto_drive_cell_text(cell.as_ref()) {
|
|
||||||
use codex_protocol::models::{ContentItem, ResponseItem};
|
|
||||||
items.push(ResponseItem::Message {
|
|
||||||
id: Some("auto-drive-reasoning".to_string()),
|
|
||||||
role: "user".to_string(),
|
|
||||||
content: vec![ContentItem::InputText { text }],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
HistoryCellType::PlanUpdate => {
|
HistoryCellType::PlanUpdate => {
|
||||||
if let Some(plan) = cell.as_any().downcast_ref::<PlanUpdateCell>() {
|
if let Some(plan) = cell.as_any().downcast_ref::<PlanUpdateCell>() {
|
||||||
let state = plan.state();
|
let state = plan.state();
|
||||||
@@ -3711,22 +3718,45 @@ impl ChatWidget<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let text = lines.join("\n");
|
let text = lines.join("\n");
|
||||||
if let Some(item) = Self::auto_drive_make_user_message(text) {
|
Some((text, false))
|
||||||
items.push(item);
|
} else {
|
||||||
}
|
Self::auto_drive_cell_text(cell.as_ref()).map(|text| (text, false))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HistoryCellType::Diff => {
|
HistoryCellType::Diff => {
|
||||||
if let Some(diff_cell) = cell.as_any().downcast_ref::<DiffCell>() {
|
if let Some(diff_cell) = cell.as_any().downcast_ref::<DiffCell>() {
|
||||||
if let Some(summary) = Self::auto_drive_diff_summary(diff_cell.record()) {
|
Self::auto_drive_diff_summary(diff_cell.record()).map(|text| (text, false))
|
||||||
if let Some(item) = Self::auto_drive_make_user_message(summary) {
|
} else {
|
||||||
items.push(item);
|
Self::auto_drive_cell_text(cell.as_ref()).map(|text| (text, false))
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => Self::auto_drive_cell_text(cell.as_ref()).map(|text| (text, false)),
|
||||||
}
|
};
|
||||||
|
|
||||||
|
let Some((text, is_reasoning)) = text else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let item = if is_reasoning {
|
||||||
|
codex_protocol::models::ResponseItem::Message {
|
||||||
|
id: Some("auto-drive-reasoning".to_string()),
|
||||||
|
role: "user".to_string(),
|
||||||
|
content: vec![codex_protocol::models::ContentItem::InputText { text }],
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
match role {
|
||||||
|
AutoDriveRole::Assistant => match Self::auto_drive_make_assistant_message(text) {
|
||||||
|
Some(item) => item,
|
||||||
|
None => continue,
|
||||||
|
},
|
||||||
|
AutoDriveRole::User => match Self::auto_drive_make_user_message(text) {
|
||||||
|
Some(item) => item,
|
||||||
|
None => continue,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
items.push(item);
|
||||||
}
|
}
|
||||||
items
|
items
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,12 +11,17 @@ use crate::app_event::{
|
|||||||
};
|
};
|
||||||
use crate::app_event_sender::AppEventSender;
|
use crate::app_event_sender::AppEventSender;
|
||||||
use crate::history::state::{
|
use crate::history::state::{
|
||||||
|
ArgumentValue,
|
||||||
ExecStatus,
|
ExecStatus,
|
||||||
ExploreEntryStatus,
|
ExploreEntryStatus,
|
||||||
HistoryDomainRecord,
|
HistoryDomainRecord,
|
||||||
HistoryId,
|
HistoryId,
|
||||||
HistoryRecord,
|
HistoryRecord,
|
||||||
HistoryState,
|
HistoryState,
|
||||||
|
ToolArgument,
|
||||||
|
ToolCallState,
|
||||||
|
ToolResultPreview,
|
||||||
|
ToolStatus,
|
||||||
};
|
};
|
||||||
use crate::slash_command::SlashCommand;
|
use crate::slash_command::SlashCommand;
|
||||||
use super::auto_coordinator::AutoCoordinatorHandle;
|
use super::auto_coordinator::AutoCoordinatorHandle;
|
||||||
@@ -3663,6 +3668,24 @@ fn export_auto_drive_items_includes_cli_outputs() {
|
|||||||
let diff = "diff --git a/foo.rs b/foo.rs\n--- a/foo.rs\n+++ b/foo.rs\n@@ -1 +1,2 @@\n-println!(\"old\");\n+println!(\"new\");\n+println!(\"extra\");\n";
|
let diff = "diff --git a/foo.rs b/foo.rs\n--- a/foo.rs\n+++ b/foo.rs\n@@ -1 +1,2 @@\n-println!(\"old\");\n+println!(\"new\");\n+println!(\"extra\");\n";
|
||||||
chat.add_diff_output(diff.to_string());
|
chat.add_diff_output(diff.to_string());
|
||||||
|
|
||||||
|
let tool_state = ToolCallState {
|
||||||
|
id: HistoryId::ZERO,
|
||||||
|
call_id: Some("tool-1".to_string()),
|
||||||
|
status: ToolStatus::Success,
|
||||||
|
title: "Run formatter".to_string(),
|
||||||
|
duration: None,
|
||||||
|
arguments: vec![ToolArgument {
|
||||||
|
name: "command".to_string(),
|
||||||
|
value: ArgumentValue::Text("just fmt".to_string()),
|
||||||
|
}],
|
||||||
|
result_preview: Some(ToolResultPreview {
|
||||||
|
lines: vec!["Formatted 12 files".to_string()],
|
||||||
|
truncated: false,
|
||||||
|
}),
|
||||||
|
error_message: None,
|
||||||
|
};
|
||||||
|
chat.history_push(history_cell::ToolCallCell::new(tool_state));
|
||||||
|
|
||||||
let items = chat.export_auto_drive_items();
|
let items = chat.export_auto_drive_items();
|
||||||
|
|
||||||
let coordinator = items
|
let coordinator = items
|
||||||
@@ -3707,6 +3730,12 @@ fn export_auto_drive_items_includes_cli_outputs() {
|
|||||||
.map(|text| text.contains("Files changed") && text.contains("foo.rs"))
|
.map(|text| text.contains("Files changed") && text.contains("foo.rs"))
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
}), "diff summary present");
|
}), "diff summary present");
|
||||||
|
|
||||||
|
assert!(items.iter().any(|item| {
|
||||||
|
message_text(item)
|
||||||
|
.map(|text| text.contains("Run formatter") && text.contains("Formatted 12 files"))
|
||||||
|
.unwrap_or(false)
|
||||||
|
}), "tool call output present");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in New Issue
Block a user