mirror of
https://github.com/openai/codex.git
synced 2026-11-05 20:10:33 +00:00
Fix backtrack to restore collaboration mode and keep developer instructions in sync
This commit is contained in:
@@ -2911,6 +2911,7 @@ mod tests {
|
||||
message: text.to_string(),
|
||||
text_elements,
|
||||
local_image_paths,
|
||||
collaboration_mode: None,
|
||||
}) as Arc<dyn HistoryCell>
|
||||
};
|
||||
let agent_cell = |text: &str| -> Arc<dyn HistoryCell> {
|
||||
|
||||
@@ -38,6 +38,7 @@ use codex_core::protocol::ErrorEvent;
|
||||
use codex_core::protocol::EventMsg;
|
||||
use codex_core::protocol::Op;
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::config_types::CollaborationModeMask;
|
||||
use codex_protocol::user_input::TextElement;
|
||||
use color_eyre::eyre::Result;
|
||||
use crossterm::event::KeyCode;
|
||||
@@ -84,6 +85,8 @@ pub(crate) struct BacktrackSelection {
|
||||
pub(crate) text_elements: Vec<TextElement>,
|
||||
/// Local image paths associated with the selected user message.
|
||||
pub(crate) local_image_paths: Vec<PathBuf>,
|
||||
/// Collaboration mode active when the selected message was sent.
|
||||
pub(crate) collaboration_mode: Option<CollaborationModeMask>,
|
||||
}
|
||||
|
||||
/// An in-flight rollback requested from core.
|
||||
@@ -203,6 +206,10 @@ impl App {
|
||||
return;
|
||||
}
|
||||
|
||||
let collaboration_override = selection
|
||||
.collaboration_mode
|
||||
.clone()
|
||||
.and_then(|mask| self.chat_widget.set_collaboration_mask_from_history(mask));
|
||||
let prefill = selection.prefill.clone();
|
||||
let text_elements = selection.text_elements.clone();
|
||||
let local_image_paths = selection.local_image_paths.clone();
|
||||
@@ -211,6 +218,21 @@ impl App {
|
||||
thread_id: self.chat_widget.thread_id(),
|
||||
});
|
||||
self.chat_widget.submit_op(Op::ThreadRollback { num_turns });
|
||||
if let Some(collaboration_mode) = collaboration_override
|
||||
&& self.chat_widget.thread_id().is_some()
|
||||
{
|
||||
self.chat_widget.submit_op(Op::OverrideTurnContext {
|
||||
cwd: None,
|
||||
approval_policy: None,
|
||||
sandbox_policy: None,
|
||||
windows_sandbox_level: None,
|
||||
model: None,
|
||||
effort: None,
|
||||
summary: None,
|
||||
collaboration_mode: Some(collaboration_mode),
|
||||
personality: None,
|
||||
});
|
||||
}
|
||||
if !prefill.is_empty() || !text_elements.is_empty() || !local_image_paths.is_empty() {
|
||||
self.chat_widget
|
||||
.set_composer_text(prefill, text_elements, local_image_paths);
|
||||
@@ -487,7 +509,7 @@ impl App {
|
||||
return None;
|
||||
}
|
||||
|
||||
let (prefill, text_elements, local_image_paths) =
|
||||
let (prefill, text_elements, local_image_paths, collaboration_mode) =
|
||||
nth_user_position(&self.transcript_cells, nth_user_message)
|
||||
.and_then(|idx| self.transcript_cells.get(idx))
|
||||
.and_then(|cell| cell.as_any().downcast_ref::<UserHistoryCell>())
|
||||
@@ -496,15 +518,17 @@ impl App {
|
||||
cell.message.clone(),
|
||||
cell.text_elements.clone(),
|
||||
cell.local_image_paths.clone(),
|
||||
cell.collaboration_mode.clone(),
|
||||
)
|
||||
})
|
||||
.unwrap_or_else(|| (String::new(), Vec::new(), Vec::new()));
|
||||
.unwrap_or_else(|| (String::new(), Vec::new(), Vec::new(), None));
|
||||
|
||||
Some(BacktrackSelection {
|
||||
nth_user_message,
|
||||
prefill,
|
||||
text_elements,
|
||||
local_image_paths,
|
||||
collaboration_mode,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -574,6 +598,7 @@ mod tests {
|
||||
message: "first user".to_string(),
|
||||
text_elements: Vec::new(),
|
||||
local_image_paths: Vec::new(),
|
||||
collaboration_mode: None,
|
||||
}) as Arc<dyn HistoryCell>,
|
||||
Arc::new(AgentMessageCell::new(vec![Line::from("assistant")], true))
|
||||
as Arc<dyn HistoryCell>,
|
||||
@@ -592,6 +617,7 @@ mod tests {
|
||||
message: "first".to_string(),
|
||||
text_elements: Vec::new(),
|
||||
local_image_paths: Vec::new(),
|
||||
collaboration_mode: None,
|
||||
}) as Arc<dyn HistoryCell>,
|
||||
Arc::new(AgentMessageCell::new(vec![Line::from("after")], false))
|
||||
as Arc<dyn HistoryCell>,
|
||||
@@ -622,6 +648,7 @@ mod tests {
|
||||
message: "first".to_string(),
|
||||
text_elements: Vec::new(),
|
||||
local_image_paths: Vec::new(),
|
||||
collaboration_mode: None,
|
||||
}) as Arc<dyn HistoryCell>,
|
||||
Arc::new(AgentMessageCell::new(vec![Line::from("between")], false))
|
||||
as Arc<dyn HistoryCell>,
|
||||
@@ -629,6 +656,7 @@ mod tests {
|
||||
message: "second".to_string(),
|
||||
text_elements: Vec::new(),
|
||||
local_image_paths: Vec::new(),
|
||||
collaboration_mode: None,
|
||||
}) as Arc<dyn HistoryCell>,
|
||||
Arc::new(AgentMessageCell::new(vec![Line::from("tail")], false))
|
||||
as Arc<dyn HistoryCell>,
|
||||
|
||||
@@ -3350,6 +3350,7 @@ impl ChatWidget {
|
||||
text,
|
||||
text_elements,
|
||||
local_image_paths,
|
||||
self.active_collaboration_mask.clone(),
|
||||
));
|
||||
}
|
||||
|
||||
@@ -3639,6 +3640,7 @@ impl ChatWidget {
|
||||
event.message,
|
||||
event.text_elements,
|
||||
event.local_images,
|
||||
None,
|
||||
));
|
||||
}
|
||||
|
||||
@@ -5513,6 +5515,18 @@ impl ChatWidget {
|
||||
self.request_redraw();
|
||||
}
|
||||
|
||||
pub(crate) fn set_collaboration_mask_from_history(
|
||||
&mut self,
|
||||
mask: CollaborationModeMask,
|
||||
) -> Option<CollaborationMode> {
|
||||
if !self.collaboration_modes_enabled() {
|
||||
return None;
|
||||
}
|
||||
let next_mode = self.current_collaboration_mode.apply_mask(&mask);
|
||||
self.set_collaboration_mask(mask);
|
||||
Some(next_mode)
|
||||
}
|
||||
|
||||
fn connectors_enabled(&self) -> bool {
|
||||
self.config.features.enabled(Feature::Apps)
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ use codex_core::protocol::SessionConfiguredEvent;
|
||||
use codex_core::web_search::web_search_detail;
|
||||
use codex_otel::RuntimeMetricsSummary;
|
||||
use codex_protocol::account::PlanType;
|
||||
use codex_protocol::config_types::CollaborationModeMask;
|
||||
use codex_protocol::mcp::Resource;
|
||||
use codex_protocol::mcp::ResourceTemplate;
|
||||
use codex_protocol::models::WebSearchAction;
|
||||
@@ -168,6 +169,7 @@ pub(crate) struct UserHistoryCell {
|
||||
pub text_elements: Vec<TextElement>,
|
||||
#[allow(dead_code)]
|
||||
pub local_image_paths: Vec<PathBuf>,
|
||||
pub collaboration_mode: Option<CollaborationModeMask>,
|
||||
}
|
||||
|
||||
/// Build logical lines for a user message with styled text elements.
|
||||
@@ -1018,11 +1020,13 @@ pub(crate) fn new_user_prompt(
|
||||
message: String,
|
||||
text_elements: Vec<TextElement>,
|
||||
local_image_paths: Vec<PathBuf>,
|
||||
collaboration_mode: Option<CollaborationModeMask>,
|
||||
) -> UserHistoryCell {
|
||||
UserHistoryCell {
|
||||
message,
|
||||
text_elements,
|
||||
local_image_paths,
|
||||
collaboration_mode,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3311,6 +3315,7 @@ mod tests {
|
||||
message: msg.to_string(),
|
||||
text_elements: Vec::new(),
|
||||
local_image_paths: Vec::new(),
|
||||
collaboration_mode: None,
|
||||
};
|
||||
|
||||
// Small width to force wrapping more clearly. Effective wrap width is width-2 due to the ▌ prefix and trailing space.
|
||||
|
||||
Reference in New Issue
Block a user