mirror of
https://github.com/hanzoai/dev.git
synced 2026-10-25 03:32:32 +00:00
feat(auto-drive): forward cli_context to CLI prompt
This commit is contained in:
@@ -1625,6 +1625,7 @@ impl App<'_> {
|
||||
status,
|
||||
progress_past,
|
||||
progress_current,
|
||||
cli_context,
|
||||
cli_prompt,
|
||||
transcript,
|
||||
turn_config,
|
||||
@@ -1634,6 +1635,7 @@ impl App<'_> {
|
||||
status,
|
||||
progress_past,
|
||||
progress_current,
|
||||
cli_context,
|
||||
cli_prompt,
|
||||
transcript,
|
||||
turn_config,
|
||||
|
||||
@@ -155,6 +155,7 @@ pub(crate) enum AppEvent {
|
||||
status: AutoCoordinatorStatus,
|
||||
progress_past: Option<String>,
|
||||
progress_current: Option<String>,
|
||||
cli_context: Option<String>,
|
||||
cli_prompt: Option<String>,
|
||||
transcript: Vec<ResponseItem>,
|
||||
turn_config: Option<TurnConfig>,
|
||||
|
||||
@@ -508,6 +508,7 @@ struct AutoCoordinatorUiState {
|
||||
current_progress_past: Option<String>,
|
||||
current_progress_current: Option<String>,
|
||||
current_cli_prompt: Option<String>,
|
||||
current_cli_context: Option<String>,
|
||||
current_display_line: Option<String>,
|
||||
current_display_is_summary: bool,
|
||||
current_reasoning_title: Option<String>,
|
||||
@@ -11399,6 +11400,7 @@ impl ChatWidget<'_> {
|
||||
self.auto_state.current_progress_past = None;
|
||||
self.auto_state.current_progress_current = None;
|
||||
self.auto_state.current_cli_prompt = None;
|
||||
self.auto_state.current_cli_context = None;
|
||||
self.auto_state.current_display_line = None;
|
||||
self.auto_state.current_display_is_summary = false;
|
||||
self.auto_state.current_reasoning_title = None;
|
||||
@@ -11443,6 +11445,7 @@ impl ChatWidget<'_> {
|
||||
self.auto_state.current_progress_past = None;
|
||||
self.auto_state.current_progress_current = None;
|
||||
self.auto_state.current_cli_prompt = None;
|
||||
self.auto_state.current_cli_context = None;
|
||||
self.auto_state.last_broadcast_summary = None;
|
||||
self.auto_state.current_summary_index = None;
|
||||
self.auto_state.current_display_line = None;
|
||||
@@ -11462,6 +11465,7 @@ impl ChatWidget<'_> {
|
||||
status: AutoCoordinatorStatus,
|
||||
progress_past: Option<String>,
|
||||
progress_current: Option<String>,
|
||||
cli_context: Option<String>,
|
||||
cli_prompt: Option<String>,
|
||||
transcript: Vec<codex_protocol::models::ResponseItem>,
|
||||
turn_config: Option<TurnConfig>,
|
||||
@@ -11481,6 +11485,7 @@ impl ChatWidget<'_> {
|
||||
self.auto_state.current_progress_current = progress_current.clone();
|
||||
self.auto_state.last_decision_progress_past = progress_past.clone();
|
||||
self.auto_state.last_decision_progress_current = progress_current.clone();
|
||||
self.auto_state.current_cli_context = cli_context.clone();
|
||||
|
||||
let summary_text = Self::compose_progress_summary(&progress_current, &progress_past);
|
||||
self.auto_state.last_decision_summary = Some(summary_text.clone());
|
||||
@@ -11659,6 +11664,8 @@ impl ChatWidget<'_> {
|
||||
return;
|
||||
}
|
||||
|
||||
let full_prompt = self.auto_build_cli_message(&prompt);
|
||||
|
||||
self.auto_state.awaiting_submission = false;
|
||||
self.auto_state.waiting_for_response = true;
|
||||
self.auto_state.coordinator_waiting = false;
|
||||
@@ -11695,14 +11702,33 @@ impl ChatWidget<'_> {
|
||||
self.bottom_pane.update_status_text(String::new());
|
||||
self.bottom_pane.set_task_running(false);
|
||||
if preface.trim().is_empty() {
|
||||
self.submit_text_message(prompt);
|
||||
self.submit_text_message(full_prompt);
|
||||
} else {
|
||||
self.submit_text_message_with_preface(prompt, preface);
|
||||
self.submit_text_message_with_preface(full_prompt, preface);
|
||||
}
|
||||
self.auto_rebuild_live_ring();
|
||||
self.request_redraw();
|
||||
}
|
||||
|
||||
fn auto_build_cli_message(&self, prompt: &str) -> String {
|
||||
let context = self
|
||||
.auto_state
|
||||
.current_cli_context
|
||||
.as_deref()
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty());
|
||||
|
||||
if let Some(ctx) = context {
|
||||
if ctx.ends_with('\n') {
|
||||
format!("{ctx}{prompt}")
|
||||
} else {
|
||||
format!("{ctx}\n\n{prompt}")
|
||||
}
|
||||
} else {
|
||||
prompt.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
fn auto_pause_for_manual_edit(&mut self) {
|
||||
if !self.auto_state.active || !self.auto_state.awaiting_submission {
|
||||
return;
|
||||
@@ -11711,12 +11737,14 @@ impl ChatWidget<'_> {
|
||||
return;
|
||||
};
|
||||
|
||||
let full_prompt = self.auto_build_cli_message(&prompt);
|
||||
|
||||
self.auto_state.paused_for_manual_edit = true;
|
||||
self.auto_state.resume_after_manual_submit = true;
|
||||
self.auto_state.countdown_id = self.auto_state.countdown_id.wrapping_add(1);
|
||||
self.auto_state.seconds_remaining = AUTO_COUNTDOWN_SECONDS;
|
||||
self.clear_composer();
|
||||
self.insert_str(&prompt);
|
||||
self.insert_str(&full_prompt);
|
||||
self.bottom_pane.ensure_input_focus();
|
||||
self.bottom_pane.set_task_running(true);
|
||||
self.bottom_pane
|
||||
|
||||
@@ -109,6 +109,8 @@ struct CoordinatorDecision {
|
||||
#[serde(default)]
|
||||
progress_current: Option<String>,
|
||||
#[serde(default)]
|
||||
cli_context: Option<String>,
|
||||
#[serde(default)]
|
||||
cli_prompt: Option<String>,
|
||||
#[serde(default)]
|
||||
turn_config: Option<TurnConfig>,
|
||||
@@ -118,6 +120,7 @@ struct ParsedCoordinatorDecision {
|
||||
status: AutoCoordinatorStatus,
|
||||
progress_past: Option<String>,
|
||||
progress_current: Option<String>,
|
||||
cli_context: Option<String>,
|
||||
cli_prompt: Option<String>,
|
||||
response_items: Vec<ResponseItem>,
|
||||
turn_config: Option<TurnConfig>,
|
||||
@@ -284,6 +287,7 @@ fn run_auto_loop(
|
||||
status,
|
||||
progress_past,
|
||||
progress_current,
|
||||
cli_context,
|
||||
cli_prompt,
|
||||
response_items,
|
||||
turn_config,
|
||||
@@ -313,6 +317,7 @@ fn run_auto_loop(
|
||||
status,
|
||||
progress_past,
|
||||
progress_current,
|
||||
cli_context: cli_context.clone(),
|
||||
cli_prompt,
|
||||
transcript: response_items,
|
||||
turn_config: turn_config.clone(),
|
||||
@@ -373,6 +378,7 @@ fn run_auto_loop(
|
||||
status,
|
||||
progress_past,
|
||||
progress_current,
|
||||
cli_context,
|
||||
cli_prompt,
|
||||
transcript: response_items,
|
||||
turn_config: turn_config.clone(),
|
||||
@@ -390,6 +396,7 @@ fn run_auto_loop(
|
||||
status: AutoCoordinatorStatus::Failed,
|
||||
progress_past: None,
|
||||
progress_current: Some(format!("Coordinator error: {err}")),
|
||||
cli_context: None,
|
||||
cli_prompt: None,
|
||||
transcript: Vec::new(),
|
||||
turn_config: None,
|
||||
@@ -546,6 +553,11 @@ fn build_schema() -> Value {
|
||||
"maxLength": 100,
|
||||
"description": "A few words describing what is happening when the CLI performs the cli_prompt. Use current tense e.g. `Now updating documentation.`"
|
||||
},
|
||||
"cli_context": {
|
||||
"type": ["string", "null"],
|
||||
"minLength": 1,
|
||||
"description": "This context is background information given to the CLI which it doesn't already know. Generally only should be used at the start of a session if the auto session was started with a lot of background information. Ignored unless finish_status is 'continue'"
|
||||
},
|
||||
"cli_prompt": {
|
||||
"type": ["string", "null"],
|
||||
"minLength": 1,
|
||||
@@ -557,10 +569,18 @@ fn build_schema() -> Value {
|
||||
"read_only": { "type": "boolean", "description": "If true, this turn should not modify files." },
|
||||
"complexity": { "type": "string", "enum": ["low","medium","high"], "description": "Complexity estimate for this turn." }
|
||||
},
|
||||
"required": ["read_only", "complexity"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": ["finish_status", "progress_past", "progress_current", "cli_prompt"],
|
||||
"required": [
|
||||
"finish_status",
|
||||
"progress_past",
|
||||
"progress_current",
|
||||
"cli_context",
|
||||
"cli_prompt",
|
||||
"turn_config"
|
||||
],
|
||||
"additionalProperties": false
|
||||
})
|
||||
}
|
||||
@@ -618,6 +638,14 @@ fn request_coordinator_decision(
|
||||
let progress_past = clean_field(decision.progress_past);
|
||||
let progress_current = clean_field(decision.progress_current);
|
||||
|
||||
let cli_context = match status {
|
||||
AutoCoordinatorStatus::Continue => clean_field(decision.cli_context).map(|value| {
|
||||
let cleaned = strip_role_prefix(&value);
|
||||
cleaned.trim().to_string()
|
||||
}),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let cli_prompt = match status {
|
||||
AutoCoordinatorStatus::Continue => {
|
||||
let prompt_text = decision
|
||||
@@ -636,6 +664,7 @@ fn request_coordinator_decision(
|
||||
status,
|
||||
progress_past,
|
||||
progress_current,
|
||||
cli_context,
|
||||
cli_prompt,
|
||||
response_items,
|
||||
turn_config: decision.turn_config,
|
||||
|
||||
@@ -2012,6 +2012,7 @@ fn auto_decision_persists_summary_through_cli_cycle() {
|
||||
AutoCoordinatorStatus::Continue,
|
||||
Some("Reviewed failing integration tests.".to_string()),
|
||||
Some("Running tests now.".to_string()),
|
||||
None,
|
||||
Some("run tests".to_string()),
|
||||
Vec::new(),
|
||||
);
|
||||
@@ -2119,6 +2120,7 @@ fn auto_history_captures_raw_transcript() {
|
||||
AutoCoordinatorStatus::Continue,
|
||||
None,
|
||||
Some("Next".to_string()),
|
||||
None,
|
||||
Some("do thing".to_string()),
|
||||
transcript.clone(),
|
||||
);
|
||||
@@ -2126,6 +2128,29 @@ fn auto_history_captures_raw_transcript() {
|
||||
assert_eq!(chat.auto_history.raw_items(), transcript.as_slice());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn auto_cli_context_is_prefixed_before_prompt() {
|
||||
let (mut chat, _rx, _op_rx) = make_chatwidget_manual();
|
||||
chat.auto_state.active = true;
|
||||
chat.auto_state.awaiting_submission = true;
|
||||
chat.auto_state.current_cli_prompt = Some("Run diagnostics".to_string());
|
||||
chat.auto_state.current_cli_context = Some("Project background: mock services are offline.".to_string());
|
||||
|
||||
assert!(chat.pending_dispatched_user_messages.is_empty());
|
||||
|
||||
chat.auto_submit_prompt();
|
||||
|
||||
let sent = chat
|
||||
.pending_dispatched_user_messages
|
||||
.back()
|
||||
.cloned();
|
||||
|
||||
assert_eq!(
|
||||
sent.as_deref(),
|
||||
Some("Project background: mock services are offline.\n\nRun diagnostics")
|
||||
);
|
||||
}
|
||||
|
||||
fn pump_app_events(
|
||||
chat: &mut ChatWidget<'_>,
|
||||
rx: &std::sync::mpsc::Receiver<AppEvent>,
|
||||
|
||||
Reference in New Issue
Block a user