replace /prompts with a rotating placeholder (#2314)
This commit is contained in:
2
codex-rs/Cargo.lock
generated
2
codex-rs/Cargo.lock
generated
@@ -930,7 +930,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"path-clean",
|
||||
"pretty_assertions",
|
||||
"rand 0.8.5",
|
||||
"rand 0.9.2",
|
||||
"ratatui",
|
||||
"ratatui-image",
|
||||
"regex-lite",
|
||||
|
||||
@@ -75,6 +75,7 @@ tui-markdown = "0.3.3"
|
||||
unicode-segmentation = "1.12.0"
|
||||
unicode-width = "0.1"
|
||||
uuid = "1"
|
||||
rand = "0.9"
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
libc = "0.2"
|
||||
@@ -84,5 +85,5 @@ libc = "0.2"
|
||||
chrono = { version = "0.4", features = ["serde"] }
|
||||
insta = "1.43.1"
|
||||
pretty_assertions = "1"
|
||||
rand = "0.8"
|
||||
rand = "0.9"
|
||||
vt100 = "0.16.2"
|
||||
|
||||
@@ -416,11 +416,6 @@ impl App<'_> {
|
||||
widget.add_status_output();
|
||||
}
|
||||
}
|
||||
SlashCommand::Prompts => {
|
||||
if let AppState::Chat { widget } = &mut self.app_state {
|
||||
widget.add_prompts_output();
|
||||
}
|
||||
}
|
||||
#[cfg(debug_assertions)]
|
||||
SlashCommand::TestApproval => {
|
||||
use codex_core::protocol::EventMsg;
|
||||
|
||||
@@ -98,6 +98,7 @@ mod tests {
|
||||
app_event_tx: AppEventSender::new(tx_raw2),
|
||||
has_input_focus: true,
|
||||
enhanced_keys_supported: false,
|
||||
placeholder_text: "Ask Codex to do anything".to_string(),
|
||||
});
|
||||
assert_eq!(CancellationEvent::Handled, view.on_ctrl_c(&mut pane));
|
||||
assert!(view.queue.is_empty());
|
||||
|
||||
@@ -31,7 +31,6 @@ use crate::bottom_pane::textarea::TextAreaState;
|
||||
use codex_file_search::FileMatch;
|
||||
use std::cell::RefCell;
|
||||
|
||||
const BASE_PLACEHOLDER_TEXT: &str = "Ask Codex to do anything";
|
||||
/// If the pasted content exceeds this number of characters, replace it with a
|
||||
/// placeholder in the UI.
|
||||
const LARGE_PASTE_CHAR_THRESHOLD: usize = 1000;
|
||||
@@ -61,6 +60,7 @@ pub(crate) struct ChatComposer {
|
||||
pending_pastes: Vec<(String, String)>,
|
||||
token_usage_info: Option<TokenUsageInfo>,
|
||||
has_focus: bool,
|
||||
placeholder_text: String,
|
||||
}
|
||||
|
||||
/// Popup state – at most one can be visible at any time.
|
||||
@@ -75,6 +75,7 @@ impl ChatComposer {
|
||||
has_input_focus: bool,
|
||||
app_event_tx: AppEventSender,
|
||||
enhanced_keys_supported: bool,
|
||||
placeholder_text: String,
|
||||
) -> Self {
|
||||
let use_shift_enter_hint = enhanced_keys_supported;
|
||||
|
||||
@@ -91,6 +92,7 @@ impl ChatComposer {
|
||||
pending_pastes: Vec::new(),
|
||||
token_usage_info: None,
|
||||
has_focus: has_input_focus,
|
||||
placeholder_text,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -712,7 +714,7 @@ impl WidgetRef for &ChatComposer {
|
||||
let mut state = self.textarea_state.borrow_mut();
|
||||
StatefulWidgetRef::render_ref(&(&self.textarea), textarea_rect, buf, &mut state);
|
||||
if self.textarea.text().is_empty() {
|
||||
Line::from(BASE_PLACEHOLDER_TEXT)
|
||||
Line::from(self.placeholder_text.as_str())
|
||||
.style(Style::default().dim())
|
||||
.render_ref(textarea_rect.inner(Margin::new(1, 0)), buf);
|
||||
}
|
||||
@@ -885,7 +887,8 @@ mod tests {
|
||||
|
||||
let (tx, _rx) = std::sync::mpsc::channel();
|
||||
let sender = AppEventSender::new(tx);
|
||||
let mut composer = ChatComposer::new(true, sender, false);
|
||||
let mut composer =
|
||||
ChatComposer::new(true, sender, false, "Ask Codex to do anything".to_string());
|
||||
|
||||
let needs_redraw = composer.handle_paste("hello".to_string());
|
||||
assert!(needs_redraw);
|
||||
@@ -908,7 +911,8 @@ mod tests {
|
||||
|
||||
let (tx, _rx) = std::sync::mpsc::channel();
|
||||
let sender = AppEventSender::new(tx);
|
||||
let mut composer = ChatComposer::new(true, sender, false);
|
||||
let mut composer =
|
||||
ChatComposer::new(true, sender, false, "Ask Codex to do anything".to_string());
|
||||
|
||||
let large = "x".repeat(LARGE_PASTE_CHAR_THRESHOLD + 10);
|
||||
let needs_redraw = composer.handle_paste(large.clone());
|
||||
@@ -937,7 +941,8 @@ mod tests {
|
||||
let large = "y".repeat(LARGE_PASTE_CHAR_THRESHOLD + 1);
|
||||
let (tx, _rx) = std::sync::mpsc::channel();
|
||||
let sender = AppEventSender::new(tx);
|
||||
let mut composer = ChatComposer::new(true, sender, false);
|
||||
let mut composer =
|
||||
ChatComposer::new(true, sender, false, "Ask Codex to do anything".to_string());
|
||||
|
||||
composer.handle_paste(large);
|
||||
assert_eq!(composer.pending_pastes.len(), 1);
|
||||
@@ -973,7 +978,12 @@ mod tests {
|
||||
|
||||
for (name, input) in test_cases {
|
||||
// Create a fresh composer for each test case
|
||||
let mut composer = ChatComposer::new(true, sender.clone(), false);
|
||||
let mut composer = ChatComposer::new(
|
||||
true,
|
||||
sender.clone(),
|
||||
false,
|
||||
"Ask Codex to do anything".to_string(),
|
||||
);
|
||||
|
||||
if let Some(text) = input {
|
||||
composer.handle_paste(text);
|
||||
@@ -1011,7 +1021,8 @@ mod tests {
|
||||
|
||||
let (tx, rx) = std::sync::mpsc::channel();
|
||||
let sender = AppEventSender::new(tx);
|
||||
let mut composer = ChatComposer::new(true, sender, false);
|
||||
let mut composer =
|
||||
ChatComposer::new(true, sender, false, "Ask Codex to do anything".to_string());
|
||||
|
||||
// Type the slash command.
|
||||
for ch in [
|
||||
@@ -1054,7 +1065,8 @@ mod tests {
|
||||
|
||||
let (tx, rx) = std::sync::mpsc::channel();
|
||||
let sender = AppEventSender::new(tx);
|
||||
let mut composer = ChatComposer::new(true, sender, false);
|
||||
let mut composer =
|
||||
ChatComposer::new(true, sender, false, "Ask Codex to do anything".to_string());
|
||||
|
||||
for ch in ['/', 'm', 'e', 'n', 't', 'i', 'o', 'n'] {
|
||||
let _ = composer.handle_key_event(KeyEvent::new(KeyCode::Char(ch), KeyModifiers::NONE));
|
||||
@@ -1093,7 +1105,8 @@ mod tests {
|
||||
|
||||
let (tx, _rx) = std::sync::mpsc::channel();
|
||||
let sender = AppEventSender::new(tx);
|
||||
let mut composer = ChatComposer::new(true, sender, false);
|
||||
let mut composer =
|
||||
ChatComposer::new(true, sender, false, "Ask Codex to do anything".to_string());
|
||||
|
||||
// Define test cases: (paste content, is_large)
|
||||
let test_cases = [
|
||||
@@ -1166,7 +1179,8 @@ mod tests {
|
||||
|
||||
let (tx, _rx) = std::sync::mpsc::channel();
|
||||
let sender = AppEventSender::new(tx);
|
||||
let mut composer = ChatComposer::new(true, sender, false);
|
||||
let mut composer =
|
||||
ChatComposer::new(true, sender, false, "Ask Codex to do anything".to_string());
|
||||
|
||||
// Define test cases: (content, is_large)
|
||||
let test_cases = [
|
||||
@@ -1232,7 +1246,8 @@ mod tests {
|
||||
|
||||
let (tx, _rx) = std::sync::mpsc::channel();
|
||||
let sender = AppEventSender::new(tx);
|
||||
let mut composer = ChatComposer::new(true, sender, false);
|
||||
let mut composer =
|
||||
ChatComposer::new(true, sender, false, "Ask Codex to do anything".to_string());
|
||||
|
||||
// Define test cases: (cursor_position_from_end, expected_pending_count)
|
||||
let test_cases = [
|
||||
|
||||
@@ -58,6 +58,7 @@ pub(crate) struct BottomPaneParams {
|
||||
pub(crate) app_event_tx: AppEventSender,
|
||||
pub(crate) has_input_focus: bool,
|
||||
pub(crate) enhanced_keys_supported: bool,
|
||||
pub(crate) placeholder_text: String,
|
||||
}
|
||||
|
||||
impl BottomPane<'_> {
|
||||
@@ -69,6 +70,7 @@ impl BottomPane<'_> {
|
||||
params.has_input_focus,
|
||||
params.app_event_tx.clone(),
|
||||
enhanced_keys_supported,
|
||||
params.placeholder_text,
|
||||
),
|
||||
active_view: None,
|
||||
app_event_tx: params.app_event_tx,
|
||||
@@ -352,6 +354,7 @@ mod tests {
|
||||
app_event_tx: tx,
|
||||
has_input_focus: true,
|
||||
enhanced_keys_supported: false,
|
||||
placeholder_text: "Ask Codex to do anything".to_string(),
|
||||
});
|
||||
pane.push_approval_request(exec_request());
|
||||
assert_eq!(CancellationEvent::Handled, pane.on_ctrl_c());
|
||||
@@ -369,6 +372,7 @@ mod tests {
|
||||
app_event_tx: tx,
|
||||
has_input_focus: true,
|
||||
enhanced_keys_supported: false,
|
||||
placeholder_text: "Ask Codex to do anything".to_string(),
|
||||
});
|
||||
|
||||
// Create an approval modal (active view).
|
||||
@@ -397,6 +401,7 @@ mod tests {
|
||||
app_event_tx: tx.clone(),
|
||||
has_input_focus: true,
|
||||
enhanced_keys_supported: false,
|
||||
placeholder_text: "Ask Codex to do anything".to_string(),
|
||||
});
|
||||
|
||||
// Start a running task so the status indicator replaces the composer.
|
||||
@@ -446,6 +451,7 @@ mod tests {
|
||||
app_event_tx: tx,
|
||||
has_input_focus: true,
|
||||
enhanced_keys_supported: false,
|
||||
placeholder_text: "Ask Codex to do anything".to_string(),
|
||||
});
|
||||
|
||||
// Begin a task: show initial status.
|
||||
@@ -477,6 +483,7 @@ mod tests {
|
||||
app_event_tx: tx,
|
||||
has_input_focus: true,
|
||||
enhanced_keys_supported: false,
|
||||
placeholder_text: "Ask Codex to do anything".to_string(),
|
||||
});
|
||||
|
||||
// Activate spinner (status view replaces composer) with no live ring.
|
||||
@@ -528,6 +535,7 @@ mod tests {
|
||||
app_event_tx: tx,
|
||||
has_input_focus: true,
|
||||
enhanced_keys_supported: false,
|
||||
placeholder_text: "Ask Codex to do anything".to_string(),
|
||||
});
|
||||
|
||||
pane.set_task_running(true);
|
||||
|
||||
@@ -932,33 +932,33 @@ mod tests {
|
||||
use rand::prelude::*;
|
||||
|
||||
fn rand_grapheme(rng: &mut rand::rngs::StdRng) -> String {
|
||||
let r: u8 = rng.gen_range(0..100);
|
||||
let r: u8 = rng.random_range(0..100);
|
||||
match r {
|
||||
0..=4 => "\n".to_string(),
|
||||
5..=12 => " ".to_string(),
|
||||
13..=35 => (rng.gen_range(b'a'..=b'z') as char).to_string(),
|
||||
36..=45 => (rng.gen_range(b'A'..=b'Z') as char).to_string(),
|
||||
46..=52 => (rng.gen_range(b'0'..=b'9') as char).to_string(),
|
||||
13..=35 => (rng.random_range(b'a'..=b'z') as char).to_string(),
|
||||
36..=45 => (rng.random_range(b'A'..=b'Z') as char).to_string(),
|
||||
46..=52 => (rng.random_range(b'0'..=b'9') as char).to_string(),
|
||||
53..=65 => {
|
||||
// Some emoji (wide graphemes)
|
||||
let choices = ["👍", "😊", "🐍", "🚀", "🧪", "🌟"];
|
||||
choices[rng.gen_range(0..choices.len())].to_string()
|
||||
choices[rng.random_range(0..choices.len())].to_string()
|
||||
}
|
||||
66..=75 => {
|
||||
// CJK wide characters
|
||||
let choices = ["漢", "字", "測", "試", "你", "好", "界", "编", "码"];
|
||||
choices[rng.gen_range(0..choices.len())].to_string()
|
||||
choices[rng.random_range(0..choices.len())].to_string()
|
||||
}
|
||||
76..=85 => {
|
||||
// Combining mark sequences
|
||||
let base = ["e", "a", "o", "n", "u"][rng.gen_range(0..5)];
|
||||
let base = ["e", "a", "o", "n", "u"][rng.random_range(0..5)];
|
||||
let marks = ["\u{0301}", "\u{0308}", "\u{0302}", "\u{0303}"];
|
||||
format!("{}{}", base, marks[rng.gen_range(0..marks.len())])
|
||||
format!("{base}{}", marks[rng.random_range(0..marks.len())])
|
||||
}
|
||||
86..=92 => {
|
||||
// Some non-latin single codepoints (Greek, Cyrillic, Hebrew)
|
||||
let choices = ["Ω", "β", "Ж", "ю", "ש", "م", "ह"];
|
||||
choices[rng.gen_range(0..choices.len())].to_string()
|
||||
choices[rng.random_range(0..choices.len())].to_string()
|
||||
}
|
||||
_ => {
|
||||
// ZWJ sequences (single graphemes but multi-codepoint)
|
||||
@@ -967,7 +967,7 @@ mod tests {
|
||||
"👨\u{200D}💻", // man technologist
|
||||
"🏳️\u{200D}🌈", // rainbow flag
|
||||
];
|
||||
choices[rng.gen_range(0..choices.len())].to_string()
|
||||
choices[rng.random_range(0..choices.len())].to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1447,7 +1447,7 @@ mod tests {
|
||||
let mut elem_texts: Vec<String> = Vec::new();
|
||||
let mut next_elem_id: usize = 0;
|
||||
// Start with a random base string
|
||||
let base_len = rng.gen_range(0..30);
|
||||
let base_len = rng.random_range(0..30);
|
||||
let mut base = String::new();
|
||||
for _ in 0..base_len {
|
||||
base.push_str(&rand_grapheme(&mut rng));
|
||||
@@ -1457,26 +1457,26 @@ mod tests {
|
||||
let mut boundaries: Vec<usize> = vec![0];
|
||||
boundaries.extend(ta.text().char_indices().map(|(i, _)| i).skip(1));
|
||||
boundaries.push(ta.text().len());
|
||||
let init = boundaries[rng.gen_range(0..boundaries.len())];
|
||||
let init = boundaries[rng.random_range(0..boundaries.len())];
|
||||
ta.set_cursor(init);
|
||||
|
||||
let mut width: u16 = rng.gen_range(1..=12);
|
||||
let mut height: u16 = rng.gen_range(1..=4);
|
||||
let mut width: u16 = rng.random_range(1..=12);
|
||||
let mut height: u16 = rng.random_range(1..=4);
|
||||
|
||||
for _step in 0..200 {
|
||||
// Mostly stable width/height, occasionally change
|
||||
if rng.gen_bool(0.1) {
|
||||
width = rng.gen_range(1..=12);
|
||||
if rng.random_bool(0.1) {
|
||||
width = rng.random_range(1..=12);
|
||||
}
|
||||
if rng.gen_bool(0.1) {
|
||||
height = rng.gen_range(1..=4);
|
||||
if rng.random_bool(0.1) {
|
||||
height = rng.random_range(1..=4);
|
||||
}
|
||||
|
||||
// Pick an operation
|
||||
match rng.gen_range(0..18) {
|
||||
match rng.random_range(0..18) {
|
||||
0 => {
|
||||
// insert small random string at cursor
|
||||
let len = rng.gen_range(0..6);
|
||||
let len = rng.random_range(0..6);
|
||||
let mut s = String::new();
|
||||
for _ in 0..len {
|
||||
s.push_str(&rand_grapheme(&mut rng));
|
||||
@@ -1488,14 +1488,14 @@ mod tests {
|
||||
let mut b: Vec<usize> = vec![0];
|
||||
b.extend(ta.text().char_indices().map(|(i, _)| i).skip(1));
|
||||
b.push(ta.text().len());
|
||||
let i1 = rng.gen_range(0..b.len());
|
||||
let i2 = rng.gen_range(0..b.len());
|
||||
let i1 = rng.random_range(0..b.len());
|
||||
let i2 = rng.random_range(0..b.len());
|
||||
let (start, end) = if b[i1] <= b[i2] {
|
||||
(b[i1], b[i2])
|
||||
} else {
|
||||
(b[i2], b[i1])
|
||||
};
|
||||
let insert_len = rng.gen_range(0..=4);
|
||||
let insert_len = rng.random_range(0..=4);
|
||||
let mut s = String::new();
|
||||
for _ in 0..insert_len {
|
||||
s.push_str(&rand_grapheme(&mut rng));
|
||||
@@ -1520,8 +1520,8 @@ mod tests {
|
||||
);
|
||||
}
|
||||
}
|
||||
2 => ta.delete_backward(rng.gen_range(0..=3)),
|
||||
3 => ta.delete_forward(rng.gen_range(0..=3)),
|
||||
2 => ta.delete_backward(rng.random_range(0..=3)),
|
||||
3 => ta.delete_forward(rng.random_range(0..=3)),
|
||||
4 => ta.delete_backward_word(),
|
||||
5 => ta.kill_to_beginning_of_line(),
|
||||
6 => ta.kill_to_end_of_line(),
|
||||
@@ -1534,7 +1534,7 @@ mod tests {
|
||||
13 => {
|
||||
// Insert an element with a unique sentinel payload
|
||||
let payload =
|
||||
format!("[[EL#{}:{}]]", next_elem_id, rng.gen_range(1000..9999));
|
||||
format!("[[EL#{}:{}]]", next_elem_id, rng.random_range(1000..9999));
|
||||
next_elem_id += 1;
|
||||
ta.insert_element(&payload);
|
||||
elem_texts.push(payload);
|
||||
@@ -1545,7 +1545,7 @@ mod tests {
|
||||
if let Some(start) = ta.text().find(&payload) {
|
||||
let end = start + payload.len();
|
||||
if end - start > 2 {
|
||||
let pos = rng.gen_range(start + 1..end - 1);
|
||||
let pos = rng.random_range(start + 1..end - 1);
|
||||
let ins = rand_grapheme(&mut rng);
|
||||
ta.insert_str_at(pos, &ins);
|
||||
}
|
||||
@@ -1558,8 +1558,8 @@ mod tests {
|
||||
if let Some(start) = ta.text().find(&payload) {
|
||||
let end = start + payload.len();
|
||||
// Create an intersecting range [start-δ, end-δ2)
|
||||
let mut s = start.saturating_sub(rng.gen_range(0..=2));
|
||||
let mut e = (end + rng.gen_range(0..=2)).min(ta.text().len());
|
||||
let mut s = start.saturating_sub(rng.random_range(0..=2));
|
||||
let mut e = (end + rng.random_range(0..=2)).min(ta.text().len());
|
||||
// Align to char boundaries to satisfy String::replace_range contract
|
||||
let txt = ta.text();
|
||||
while s > 0 && !txt.is_char_boundary(s) {
|
||||
@@ -1571,7 +1571,7 @@ mod tests {
|
||||
if s < e {
|
||||
// Small replacement text
|
||||
let mut srep = String::new();
|
||||
for _ in 0..rng.gen_range(0..=2) {
|
||||
for _ in 0..rng.random_range(0..=2) {
|
||||
srep.push_str(&rand_grapheme(&mut rng));
|
||||
}
|
||||
ta.replace_range(s..e, &srep);
|
||||
@@ -1585,7 +1585,7 @@ mod tests {
|
||||
if let Some(start) = ta.text().find(&payload) {
|
||||
let end = start + payload.len();
|
||||
if end - start > 2 {
|
||||
let pos = rng.gen_range(start + 1..end - 1);
|
||||
let pos = rng.random_range(start + 1..end - 1);
|
||||
ta.set_cursor(pos);
|
||||
}
|
||||
}
|
||||
@@ -1593,7 +1593,7 @@ mod tests {
|
||||
}
|
||||
_ => {
|
||||
// Jump to word boundaries
|
||||
if rng.gen_bool(0.5) {
|
||||
if rng.random_bool(0.5) {
|
||||
let p = ta.beginning_of_previous_word();
|
||||
ta.set_cursor(p);
|
||||
} else {
|
||||
|
||||
@@ -28,6 +28,7 @@ use codex_core::protocol::TurnDiffEvent;
|
||||
use codex_protocol::parse_command::ParsedCommand;
|
||||
use crossterm::event::KeyEvent;
|
||||
use crossterm::event::KeyEventKind;
|
||||
use rand::Rng;
|
||||
use ratatui::buffer::Buffer;
|
||||
use ratatui::layout::Constraint;
|
||||
use ratatui::layout::Layout;
|
||||
@@ -494,6 +495,8 @@ impl ChatWidget<'_> {
|
||||
initial_images: Vec<PathBuf>,
|
||||
enhanced_keys_supported: bool,
|
||||
) -> Self {
|
||||
let mut rng = rand::rng();
|
||||
let placeholder = EXAMPLE_PROMPTS[rng.random_range(0..EXAMPLE_PROMPTS.len())].to_string();
|
||||
let codex_op_tx = spawn_agent(config.clone(), app_event_tx.clone(), conversation_manager);
|
||||
|
||||
Self {
|
||||
@@ -503,6 +506,7 @@ impl ChatWidget<'_> {
|
||||
app_event_tx,
|
||||
has_input_focus: true,
|
||||
enhanced_keys_supported,
|
||||
placeholder_text: placeholder,
|
||||
}),
|
||||
active_exec_cell: None,
|
||||
config: config.clone(),
|
||||
@@ -680,10 +684,6 @@ impl ChatWidget<'_> {
|
||||
));
|
||||
}
|
||||
|
||||
pub(crate) fn add_prompts_output(&mut self) {
|
||||
self.add_to_history(&history_cell::new_prompts_output());
|
||||
}
|
||||
|
||||
/// Forward file-search results to the bottom pane.
|
||||
pub(crate) fn apply_file_search_result(&mut self, query: String, matches: Vec<FileMatch>) {
|
||||
self.bottom_pane.on_file_search_result(query, matches);
|
||||
@@ -764,6 +764,15 @@ impl WidgetRef for &ChatWidget<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
const EXAMPLE_PROMPTS: [&str; 6] = [
|
||||
"Explain this codebase",
|
||||
"Summarize recent commits",
|
||||
"Implement {feature}",
|
||||
"Find and fix a bug in @filename",
|
||||
"Write tests for @filename",
|
||||
"Improve documentation in @filename",
|
||||
];
|
||||
|
||||
fn add_token_usage(current_usage: &TokenUsage, new_usage: &TokenUsage) -> TokenUsage {
|
||||
let cached_input_tokens = match (
|
||||
current_usage.cached_input_tokens,
|
||||
|
||||
@@ -124,6 +124,7 @@ fn make_chatwidget_manual() -> (
|
||||
app_event_tx: app_event_tx.clone(),
|
||||
has_input_focus: true,
|
||||
enhanced_keys_supported: false,
|
||||
placeholder_text: "Ask Codex to do anything".to_string(),
|
||||
});
|
||||
let widget = ChatWidget {
|
||||
app_event_tx,
|
||||
|
||||
@@ -170,7 +170,6 @@ pub(crate) fn new_session_info(
|
||||
Line::from(format!(" /init - {}", SlashCommand::Init.description()).dim()),
|
||||
Line::from(format!(" /status - {}", SlashCommand::Status.description()).dim()),
|
||||
Line::from(format!(" /diff - {}", SlashCommand::Diff.description()).dim()),
|
||||
Line::from(format!(" /prompts - {}", SlashCommand::Prompts.description()).dim()),
|
||||
Line::from("".dim()),
|
||||
];
|
||||
PlainHistoryCell { lines }
|
||||
@@ -635,21 +634,6 @@ pub(crate) fn new_status_output(
|
||||
PlainHistoryCell { lines }
|
||||
}
|
||||
|
||||
pub(crate) fn new_prompts_output() -> PlainHistoryCell {
|
||||
let lines: Vec<Line<'static>> = vec![
|
||||
Line::from("/prompts".magenta()),
|
||||
Line::from(""),
|
||||
Line::from(" 1. Explain this codebase"),
|
||||
Line::from(" 2. Summarize recent commits"),
|
||||
Line::from(" 3. Implement {feature}"),
|
||||
Line::from(" 4. Find and fix a bug in @filename"),
|
||||
Line::from(" 5. Write tests for @filename"),
|
||||
Line::from(" 6. Improve documentation in @filename"),
|
||||
Line::from(""),
|
||||
];
|
||||
PlainHistoryCell { lines }
|
||||
}
|
||||
|
||||
pub(crate) fn new_error_event(message: String) -> PlainHistoryCell {
|
||||
let lines: Vec<Line<'static>> = vec![vec!["🖐 ".red().bold(), message.into()].into(), "".into()];
|
||||
PlainHistoryCell { lines }
|
||||
|
||||
@@ -18,7 +18,6 @@ pub enum SlashCommand {
|
||||
Diff,
|
||||
Mention,
|
||||
Status,
|
||||
Prompts,
|
||||
Logout,
|
||||
Quit,
|
||||
#[cfg(debug_assertions)]
|
||||
@@ -36,7 +35,6 @@ impl SlashCommand {
|
||||
SlashCommand::Diff => "show git diff (including untracked files)",
|
||||
SlashCommand::Mention => "mention a file",
|
||||
SlashCommand::Status => "show current session configuration and token usage",
|
||||
SlashCommand::Prompts => "show example prompts",
|
||||
SlashCommand::Logout => "log out of Codex",
|
||||
#[cfg(debug_assertions)]
|
||||
SlashCommand::TestApproval => "test approval request",
|
||||
|
||||
Reference in New Issue
Block a user