mirror of
https://github.com/openai/codex.git
synced 2026-02-01 22:47:52 +00:00
Persist collaboration mode masks in history
This commit is contained in:
@@ -69,7 +69,9 @@ impl<'a> ChatRequestBuilder<'a> {
|
||||
last_emitted_role = Some("assistant")
|
||||
}
|
||||
ResponseItem::FunctionCallOutput { .. } => last_emitted_role = Some("tool"),
|
||||
ResponseItem::Reasoning { .. } | ResponseItem::Other => {}
|
||||
ResponseItem::Reasoning { .. }
|
||||
| ResponseItem::CollaborationModeUpdate { .. }
|
||||
| ResponseItem::Other => {}
|
||||
ResponseItem::CustomToolCall { .. } => {}
|
||||
ResponseItem::CustomToolCallOutput { .. } => {}
|
||||
ResponseItem::WebSearchCall { .. } => {}
|
||||
@@ -284,6 +286,7 @@ impl<'a> ChatRequestBuilder<'a> {
|
||||
}
|
||||
ResponseItem::Reasoning { .. }
|
||||
| ResponseItem::WebSearchCall { .. }
|
||||
| ResponseItem::CollaborationModeUpdate { .. }
|
||||
| ResponseItem::Other
|
||||
| ResponseItem::Compaction { .. } => {
|
||||
continue;
|
||||
|
||||
@@ -40,7 +40,6 @@ use async_channel::Receiver;
|
||||
use async_channel::Sender;
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::approvals::ExecPolicyAmendment;
|
||||
use codex_protocol::config_types::ModeKind;
|
||||
use codex_protocol::config_types::Settings;
|
||||
use codex_protocol::config_types::WebSearchMode;
|
||||
use codex_protocol::dynamic_tools::DynamicToolResponse;
|
||||
@@ -203,6 +202,8 @@ use crate::windows_sandbox::WindowsSandboxLevelExt;
|
||||
use codex_async_utils::OrCancelExt;
|
||||
use codex_otel::OtelManager;
|
||||
use codex_protocol::config_types::CollaborationMode;
|
||||
use codex_protocol::config_types::CollaborationModeMask;
|
||||
use codex_protocol::config_types::ModeKind;
|
||||
use codex_protocol::config_types::Personality;
|
||||
use codex_protocol::config_types::ReasoningSummary as ReasoningSummaryConfig;
|
||||
use codex_protocol::config_types::WindowsSandboxLevel;
|
||||
@@ -1365,6 +1366,26 @@ impl Session {
|
||||
}
|
||||
}
|
||||
|
||||
fn collaboration_mode_mask_from_mode(mode: &CollaborationMode) -> CollaborationModeMask {
|
||||
CollaborationModeMask {
|
||||
name: Self::collaboration_mode_name(mode.mode).to_string(),
|
||||
mode: Some(mode.mode),
|
||||
model: Some(mode.model().to_string()),
|
||||
reasoning_effort: Some(mode.reasoning_effort()),
|
||||
developer_instructions: Some(mode.settings.developer_instructions.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
fn collaboration_mode_name(kind: ModeKind) -> &'static str {
|
||||
match kind {
|
||||
ModeKind::Plan => "Plan",
|
||||
ModeKind::Code => "Code",
|
||||
ModeKind::PairProgramming => "Pair Programming",
|
||||
ModeKind::Execute => "Execute",
|
||||
ModeKind::Custom => "Custom",
|
||||
}
|
||||
}
|
||||
|
||||
fn build_settings_update_items(
|
||||
&self,
|
||||
previous_context: Option<&Arc<TurnContext>>,
|
||||
@@ -1383,6 +1404,13 @@ impl Session {
|
||||
{
|
||||
update_items.push(permissions_item);
|
||||
}
|
||||
if let Some(next_mode) = next_collaboration_mode {
|
||||
if previous_collaboration_mode != next_mode {
|
||||
update_items.push(ResponseItem::CollaborationModeUpdate {
|
||||
mask: Self::collaboration_mode_mask_from_mode(next_mode),
|
||||
});
|
||||
}
|
||||
}
|
||||
if let Some(collaboration_mode_item) = self.build_collaboration_mode_update_item(
|
||||
previous_collaboration_mode,
|
||||
next_collaboration_mode,
|
||||
@@ -1891,6 +1919,9 @@ impl Session {
|
||||
state.session_configuration.base_instructions.clone(),
|
||||
)
|
||||
};
|
||||
items.push(ResponseItem::CollaborationModeUpdate {
|
||||
mask: Self::collaboration_mode_mask_from_mode(&collaboration_mode),
|
||||
});
|
||||
if let Some(collab_instructions) =
|
||||
DeveloperInstructions::from_collaboration_mode(&collaboration_mode)
|
||||
{
|
||||
@@ -3120,6 +3151,9 @@ mod handlers {
|
||||
|
||||
fn last_collaboration_mask(items: &[ResponseItem]) -> Option<CollaborationModeMask> {
|
||||
items.iter().rev().find_map(|item| {
|
||||
if let ResponseItem::CollaborationModeUpdate { mask } = item {
|
||||
return Some(mask.clone());
|
||||
}
|
||||
let ResponseItem::Message { role, content, .. } = item else {
|
||||
return None;
|
||||
};
|
||||
|
||||
@@ -59,7 +59,9 @@ impl ContextManager {
|
||||
for item in items {
|
||||
let item_ref = item.deref();
|
||||
let is_ghost_snapshot = matches!(item_ref, ResponseItem::GhostSnapshot { .. });
|
||||
if !is_api_message(item_ref) && !is_ghost_snapshot {
|
||||
let is_collaboration_mode_update =
|
||||
matches!(item_ref, ResponseItem::CollaborationModeUpdate { .. });
|
||||
if !is_api_message(item_ref) && !is_ghost_snapshot && !is_collaboration_mode_update {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -72,8 +74,12 @@ impl ContextManager {
|
||||
/// normalization and drop un-suited items.
|
||||
pub(crate) fn for_prompt(mut self) -> Vec<ResponseItem> {
|
||||
self.normalize_history();
|
||||
self.items
|
||||
.retain(|item| !matches!(item, ResponseItem::GhostSnapshot { .. }));
|
||||
self.items.retain(|item| {
|
||||
!matches!(
|
||||
item,
|
||||
ResponseItem::GhostSnapshot { .. } | ResponseItem::CollaborationModeUpdate { .. }
|
||||
)
|
||||
});
|
||||
self.items
|
||||
}
|
||||
|
||||
@@ -94,7 +100,8 @@ impl ContextManager {
|
||||
|
||||
let items_tokens = self.items.iter().fold(0i64, |acc, item| {
|
||||
acc + match item {
|
||||
ResponseItem::GhostSnapshot { .. } => 0,
|
||||
ResponseItem::GhostSnapshot { .. }
|
||||
| ResponseItem::CollaborationModeUpdate { .. } => 0,
|
||||
ResponseItem::Reasoning {
|
||||
encrypted_content: Some(content),
|
||||
..
|
||||
@@ -301,6 +308,7 @@ impl ContextManager {
|
||||
| ResponseItem::CustomToolCall { .. }
|
||||
| ResponseItem::Compaction { .. }
|
||||
| ResponseItem::GhostSnapshot { .. }
|
||||
| ResponseItem::CollaborationModeUpdate { .. }
|
||||
| ResponseItem::Other => item.clone(),
|
||||
}
|
||||
}
|
||||
@@ -320,6 +328,7 @@ fn is_api_message(message: &ResponseItem) -> bool {
|
||||
| ResponseItem::WebSearchCall { .. }
|
||||
| ResponseItem::Compaction { .. } => true,
|
||||
ResponseItem::GhostSnapshot { .. } => false,
|
||||
ResponseItem::CollaborationModeUpdate { .. } => false,
|
||||
ResponseItem::Other => false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ pub(crate) fn should_persist_response_item(item: &ResponseItem) -> bool {
|
||||
| ResponseItem::CustomToolCall { .. }
|
||||
| ResponseItem::CustomToolCallOutput { .. }
|
||||
| ResponseItem::WebSearchCall { .. }
|
||||
| ResponseItem::CollaborationModeUpdate { .. }
|
||||
| ResponseItem::GhostSnapshot { .. }
|
||||
| ResponseItem::Compaction { .. } => true,
|
||||
ResponseItem::Other => false,
|
||||
|
||||
@@ -545,6 +545,7 @@ impl OtelManager {
|
||||
ResponseItem::CustomToolCall { .. } => "custom_tool_call".into(),
|
||||
ResponseItem::CustomToolCallOutput { .. } => "custom_tool_call_output".into(),
|
||||
ResponseItem::WebSearchCall { .. } => "web_search_call".into(),
|
||||
ResponseItem::CollaborationModeUpdate { .. } => "collaboration_mode_update".into(),
|
||||
ResponseItem::GhostSnapshot { .. } => "ghost_snapshot".into(),
|
||||
ResponseItem::Compaction { .. } => "compaction".into(),
|
||||
ResponseItem::Other => "other".into(),
|
||||
|
||||
@@ -11,6 +11,7 @@ use serde::ser::Serializer;
|
||||
use ts_rs::TS;
|
||||
|
||||
use crate::config_types::CollaborationMode;
|
||||
use crate::config_types::CollaborationModeMask;
|
||||
use crate::config_types::SandboxMode;
|
||||
use crate::protocol::AskForApproval;
|
||||
use crate::protocol::COLLABORATION_MODE_CLOSE_TAG;
|
||||
@@ -86,6 +87,9 @@ pub enum ResponseItem {
|
||||
#[ts(optional)]
|
||||
end_turn: Option<bool>,
|
||||
},
|
||||
CollaborationModeUpdate {
|
||||
mask: CollaborationModeMask,
|
||||
},
|
||||
Reasoning {
|
||||
#[serde(default, skip_serializing)]
|
||||
#[ts(skip)]
|
||||
|
||||
Reference in New Issue
Block a user