mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
4454e1411b
## Why `TurnContext::cwd` and `TurnContext::resolve_path` are being phased out in favor of using the selected turn environment cwd directly. Deprecating both APIs makes any new direct dependency visible while preserving the existing migration path for current callers. ## What Changed - Marked `TurnContext::cwd` and `TurnContext::resolve_path` as deprecated with guidance to use the selected turn environment cwd instead. - Added exact `#[allow(deprecated)]` suppressions at each existing direct usage site, including tests, rather than adding crate-wide suppression. - Kept the change behavior-preserving: current cwd reads, writes, and path resolution continue to use the same values. ## Verification - `just fmt` - `cargo check -p codex-core` - `cargo check -p codex-core --tests` - `git diff --check`
244 lines
7.9 KiB
Rust
244 lines
7.9 KiB
Rust
use crate::context::CollaborationModeInstructions;
|
|
use crate::context::ContextualUserFragment;
|
|
use crate::context::EnvironmentContext;
|
|
use crate::context::ModelSwitchInstructions;
|
|
use crate::context::PermissionsInstructions;
|
|
use crate::context::PersonalitySpecInstructions;
|
|
use crate::context::RealtimeEndInstructions;
|
|
use crate::context::RealtimeStartInstructions;
|
|
use crate::context::RealtimeStartWithInstructions;
|
|
use crate::session::PreviousTurnSettings;
|
|
use crate::session::turn_context::TurnContext;
|
|
use crate::shell::Shell;
|
|
use codex_execpolicy::Policy;
|
|
use codex_features::Feature;
|
|
use codex_protocol::config_types::Personality;
|
|
use codex_protocol::models::ContentItem;
|
|
use codex_protocol::models::ResponseItem;
|
|
use codex_protocol::openai_models::ModelInfo;
|
|
use codex_protocol::protocol::TurnContextItem;
|
|
|
|
fn build_environment_update_item(
|
|
previous: Option<&TurnContextItem>,
|
|
next: &TurnContext,
|
|
shell: &Shell,
|
|
) -> Option<ResponseItem> {
|
|
if !next.config.include_environment_context {
|
|
return None;
|
|
}
|
|
|
|
let prev = previous?;
|
|
let prev_context = EnvironmentContext::from_turn_context_item(prev, shell.name().to_string());
|
|
let next_context = EnvironmentContext::from_turn_context(next, shell);
|
|
if prev_context.equals_except_shell(&next_context) {
|
|
return None;
|
|
}
|
|
|
|
Some(ContextualUserFragment::into(
|
|
EnvironmentContext::diff_from_turn_context_item(prev, &next_context),
|
|
))
|
|
}
|
|
|
|
fn build_permissions_update_item(
|
|
previous: Option<&TurnContextItem>,
|
|
next: &TurnContext,
|
|
exec_policy: &Policy,
|
|
) -> Option<String> {
|
|
if !next.config.include_permissions_instructions {
|
|
return None;
|
|
}
|
|
|
|
let prev = previous?;
|
|
if prev.permission_profile() == next.permission_profile()
|
|
&& prev.approval_policy == next.approval_policy.value()
|
|
{
|
|
return None;
|
|
}
|
|
|
|
Some(
|
|
PermissionsInstructions::from_permission_profile(
|
|
&next.permission_profile,
|
|
next.approval_policy.value(),
|
|
next.config.approvals_reviewer,
|
|
exec_policy,
|
|
#[allow(deprecated)]
|
|
&next.cwd,
|
|
next.features.enabled(Feature::ExecPermissionApprovals),
|
|
next.features.enabled(Feature::RequestPermissionsTool),
|
|
)
|
|
.render(),
|
|
)
|
|
}
|
|
|
|
fn build_collaboration_mode_update_item(
|
|
previous: Option<&TurnContextItem>,
|
|
next: &TurnContext,
|
|
) -> Option<String> {
|
|
if !next.config.include_collaboration_mode_instructions {
|
|
return None;
|
|
}
|
|
|
|
let prev = previous?;
|
|
if prev.collaboration_mode.as_ref() != Some(&next.collaboration_mode) {
|
|
// If the next mode has empty developer instructions, this returns None and we emit no
|
|
// update, so prior collaboration instructions remain in the prompt history.
|
|
Some(
|
|
CollaborationModeInstructions::from_collaboration_mode(&next.collaboration_mode)?
|
|
.render(),
|
|
)
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
|
|
pub(crate) fn build_realtime_update_item(
|
|
previous: Option<&TurnContextItem>,
|
|
previous_turn_settings: Option<&PreviousTurnSettings>,
|
|
next: &TurnContext,
|
|
) -> Option<String> {
|
|
match (
|
|
previous.and_then(|item| item.realtime_active),
|
|
next.realtime_active,
|
|
) {
|
|
(Some(true), false) => Some(RealtimeEndInstructions::new("inactive").render()),
|
|
(Some(false), true) | (None, true) => Some(
|
|
if let Some(instructions) = next
|
|
.config
|
|
.experimental_realtime_start_instructions
|
|
.as_deref()
|
|
{
|
|
RealtimeStartWithInstructions::new(instructions).render()
|
|
} else {
|
|
RealtimeStartInstructions.render()
|
|
},
|
|
),
|
|
(Some(true), true) | (Some(false), false) => None,
|
|
(None, false) => previous_turn_settings
|
|
.and_then(|settings| settings.realtime_active)
|
|
.filter(|realtime_active| *realtime_active)
|
|
.map(|_| RealtimeEndInstructions::new("inactive").render()),
|
|
}
|
|
}
|
|
|
|
pub(crate) fn build_initial_realtime_item(
|
|
previous: Option<&TurnContextItem>,
|
|
previous_turn_settings: Option<&PreviousTurnSettings>,
|
|
next: &TurnContext,
|
|
) -> Option<String> {
|
|
build_realtime_update_item(previous, previous_turn_settings, next)
|
|
}
|
|
|
|
fn build_personality_update_item(
|
|
previous: Option<&TurnContextItem>,
|
|
next: &TurnContext,
|
|
personality_feature_enabled: bool,
|
|
) -> Option<String> {
|
|
if !personality_feature_enabled {
|
|
return None;
|
|
}
|
|
let previous = previous?;
|
|
if next.model_info.slug != previous.model {
|
|
return None;
|
|
}
|
|
|
|
if let Some(personality) = next.personality
|
|
&& next.personality != previous.personality
|
|
{
|
|
let model_info = &next.model_info;
|
|
let personality_message = personality_message_for(model_info, personality);
|
|
personality_message.map(|message| PersonalitySpecInstructions::new(message).render())
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
|
|
pub(crate) fn personality_message_for(
|
|
model_info: &ModelInfo,
|
|
personality: Personality,
|
|
) -> Option<String> {
|
|
model_info
|
|
.model_messages
|
|
.as_ref()
|
|
.and_then(|spec| spec.get_personality_message(Some(personality)))
|
|
.filter(|message| !message.is_empty())
|
|
}
|
|
|
|
pub(crate) fn build_model_instructions_update_item(
|
|
previous_turn_settings: Option<&PreviousTurnSettings>,
|
|
next: &TurnContext,
|
|
) -> Option<String> {
|
|
let previous_turn_settings = previous_turn_settings?;
|
|
if previous_turn_settings.model == next.model_info.slug {
|
|
return None;
|
|
}
|
|
|
|
let model_instructions = next.model_info.get_model_instructions(next.personality);
|
|
if model_instructions.is_empty() {
|
|
return None;
|
|
}
|
|
|
|
Some(ModelSwitchInstructions::new(model_instructions).render())
|
|
}
|
|
|
|
pub(crate) fn build_developer_update_item(text_sections: Vec<String>) -> Option<ResponseItem> {
|
|
build_text_message("developer", text_sections)
|
|
}
|
|
|
|
pub(crate) fn build_contextual_user_message(text_sections: Vec<String>) -> Option<ResponseItem> {
|
|
build_text_message("user", text_sections)
|
|
}
|
|
|
|
fn build_text_message(role: &str, text_sections: Vec<String>) -> Option<ResponseItem> {
|
|
if text_sections.is_empty() {
|
|
return None;
|
|
}
|
|
|
|
let content = text_sections
|
|
.into_iter()
|
|
.map(|text| ContentItem::InputText { text })
|
|
.collect();
|
|
|
|
Some(ResponseItem::Message {
|
|
id: None,
|
|
role: role.to_string(),
|
|
content,
|
|
phase: None,
|
|
})
|
|
}
|
|
|
|
pub(crate) fn build_settings_update_items(
|
|
previous: Option<&TurnContextItem>,
|
|
previous_turn_settings: Option<&PreviousTurnSettings>,
|
|
next: &TurnContext,
|
|
shell: &Shell,
|
|
exec_policy: &Policy,
|
|
personality_feature_enabled: bool,
|
|
) -> Vec<ResponseItem> {
|
|
// TODO(ccunningham): build_settings_update_items still does not cover every
|
|
// model-visible item emitted by build_initial_context. Persist the remaining
|
|
// inputs or add explicit replay events so fork/resume can diff everything
|
|
// deterministically.
|
|
let contextual_user_message = build_environment_update_item(previous, next, shell);
|
|
let developer_update_sections = [
|
|
// Keep model-switch instructions first so model-specific guidance is read before
|
|
// any other context diffs on this turn.
|
|
build_model_instructions_update_item(previous_turn_settings, next),
|
|
build_permissions_update_item(previous, next, exec_policy),
|
|
build_collaboration_mode_update_item(previous, next),
|
|
build_realtime_update_item(previous, previous_turn_settings, next),
|
|
build_personality_update_item(previous, next, personality_feature_enabled),
|
|
]
|
|
.into_iter()
|
|
.flatten()
|
|
.collect();
|
|
|
|
let mut items = Vec::with_capacity(2);
|
|
if let Some(developer_message) = build_developer_update_item(developer_update_sections) {
|
|
items.push(developer_message);
|
|
}
|
|
if let Some(contextual_user_message) = contextual_user_message {
|
|
items.push(contextual_user_message);
|
|
}
|
|
items
|
|
}
|