mirror of
https://github.com/openai/codex.git
synced 2026-11-03 16:23:51 +00:00
## What changed - Display `Blocked` goal statuses as “stalled” in the goal menu and goal status footer. - Update the goal menu snapshot and footer formatting test expectations. GitOrigin-RevId: f3d8212d939f0d76354048231346328972226274
144 lines
5.1 KiB
Rust
144 lines
5.1 KiB
Rust
//! Goal summary for the bare `/goal` command.
|
|
|
|
use super::*;
|
|
use crate::goal_display::format_goal_elapsed_seconds;
|
|
use crate::goal_files;
|
|
use crate::status::format_tokens_compact;
|
|
|
|
impl ChatWidget {
|
|
pub(crate) fn show_goal_summary(&mut self, goal: AppThreadGoal) {
|
|
self.add_plain_history_lines(goal_summary_lines(&goal));
|
|
}
|
|
|
|
pub(crate) fn show_goal_edit_prompt(&mut self, thread_id: ThreadId, goal: AppThreadGoal) {
|
|
let tx = self.app_event_tx.clone();
|
|
let status = edited_goal_status(goal.status);
|
|
let token_budget = goal.token_budget;
|
|
let view = CustomPromptView::new(
|
|
"Edit goal".to_string(),
|
|
"Type a goal objective and press Enter".to_string(),
|
|
goal.objective,
|
|
/*context_label*/ None,
|
|
Box::new(move |objective: String| {
|
|
tx.send(AppEvent::SetThreadGoalDraft {
|
|
thread_id,
|
|
draft: goal_files::GoalDraft {
|
|
objective,
|
|
..Default::default()
|
|
},
|
|
mode: crate::app_event::ThreadGoalSetMode::UpdateExisting {
|
|
status,
|
|
token_budget,
|
|
},
|
|
});
|
|
}),
|
|
);
|
|
self.bottom_pane.show_view(Box::new(view));
|
|
}
|
|
|
|
pub(crate) fn show_resume_paused_goal_prompt(
|
|
&mut self,
|
|
thread_id: ThreadId,
|
|
objective: String,
|
|
) {
|
|
let resume_actions: Vec<SelectionAction> = vec![Box::new(move |tx| {
|
|
tx.send(AppEvent::SetThreadGoalStatus {
|
|
thread_id,
|
|
status: AppThreadGoalStatus::Active,
|
|
});
|
|
})];
|
|
self.show_selection_view(SelectionViewParams {
|
|
title: Some("Resume paused goal?".to_string()),
|
|
subtitle: Some(format!("Goal: {objective}")),
|
|
footer_hint: Some(standard_popup_hint_line()),
|
|
initial_selected_idx: Some(0),
|
|
items: vec![
|
|
SelectionItem {
|
|
name: "Resume goal".to_string(),
|
|
description: Some("Mark it active and continue when idle".to_string()),
|
|
actions: resume_actions,
|
|
dismiss_on_select: true,
|
|
..Default::default()
|
|
},
|
|
SelectionItem {
|
|
name: "Leave paused".to_string(),
|
|
description: Some("Keep it paused; use /goal resume later".to_string()),
|
|
dismiss_on_select: true,
|
|
..Default::default()
|
|
},
|
|
],
|
|
..Default::default()
|
|
});
|
|
}
|
|
|
|
pub(crate) fn on_thread_goal_cleared(&mut self, thread_id: &str) {
|
|
if self
|
|
.thread_id
|
|
.is_some_and(|active_thread_id| active_thread_id.to_string() == thread_id)
|
|
{
|
|
self.current_goal_status = None;
|
|
self.update_collaboration_mode_indicator();
|
|
}
|
|
}
|
|
}
|
|
|
|
fn goal_summary_lines(goal: &AppThreadGoal) -> Vec<Line<'static>> {
|
|
let mut lines = vec![
|
|
Line::from("Goal".bold()),
|
|
Line::from(vec![
|
|
"Status: ".dim(),
|
|
goal_status_label(goal.status).to_string().into(),
|
|
]),
|
|
Line::from(vec!["Objective: ".dim(), goal.objective.clone().into()]),
|
|
Line::from(vec![
|
|
"Time used: ".dim(),
|
|
format_goal_elapsed_seconds(goal.time_used_seconds).into(),
|
|
]),
|
|
Line::from(vec![
|
|
"Tokens used: ".dim(),
|
|
format_tokens_compact(goal.tokens_used).into(),
|
|
]),
|
|
];
|
|
if let Some(token_budget) = goal.token_budget {
|
|
lines.push(Line::from(vec![
|
|
"Token budget: ".dim(),
|
|
format_tokens_compact(token_budget).into(),
|
|
]));
|
|
}
|
|
let command_hint = match goal.status {
|
|
AppThreadGoalStatus::Active => "Commands: /goal edit, /goal pause, /goal clear",
|
|
AppThreadGoalStatus::Paused
|
|
| AppThreadGoalStatus::Blocked
|
|
| AppThreadGoalStatus::UsageLimited => "Commands: /goal edit, /goal resume, /goal clear",
|
|
AppThreadGoalStatus::BudgetLimited | AppThreadGoalStatus::Complete => {
|
|
"Commands: /goal edit, /goal clear"
|
|
}
|
|
};
|
|
lines.push(Line::default());
|
|
lines.push(Line::from(command_hint.dim()));
|
|
lines
|
|
}
|
|
|
|
fn goal_status_label(status: AppThreadGoalStatus) -> &'static str {
|
|
match status {
|
|
AppThreadGoalStatus::Active => "active",
|
|
AppThreadGoalStatus::Paused => "paused",
|
|
AppThreadGoalStatus::Blocked => "stalled",
|
|
AppThreadGoalStatus::UsageLimited => "usage limited",
|
|
AppThreadGoalStatus::BudgetLimited => "limited by budget",
|
|
AppThreadGoalStatus::Complete => "complete",
|
|
}
|
|
}
|
|
|
|
fn edited_goal_status(status: AppThreadGoalStatus) -> AppThreadGoalStatus {
|
|
match status {
|
|
AppThreadGoalStatus::Active => AppThreadGoalStatus::Active,
|
|
AppThreadGoalStatus::Paused
|
|
| AppThreadGoalStatus::Blocked
|
|
| AppThreadGoalStatus::UsageLimited => status,
|
|
AppThreadGoalStatus::BudgetLimited | AppThreadGoalStatus::Complete => {
|
|
AppThreadGoalStatus::Active
|
|
}
|
|
}
|
|
}
|