mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
71e4c6fa17
## Summary - rename the core codex module root to session/mod.rs without using #[path] - move the codex module directory and tests under core/src/session - remove session/mod.rs reexports so call sites use explicit child module paths ## Testing - cargo test -p codex-core --lib - cargo check -p codex-core --tests - just fmt - just fix -p codex-core - git diff --check
165 lines
7.5 KiB
Rust
165 lines
7.5 KiB
Rust
use super::turn_context::image_generation_tool_auth_allowed;
|
||
use super::*;
|
||
|
||
/// Spawn a review thread using the given prompt.
|
||
pub(super) async fn spawn_review_thread(
|
||
sess: Arc<Session>,
|
||
config: Arc<Config>,
|
||
parent_turn_context: Arc<TurnContext>,
|
||
sub_id: String,
|
||
resolved: crate::review_prompts::ResolvedReviewRequest,
|
||
) {
|
||
let model = config
|
||
.review_model
|
||
.clone()
|
||
.unwrap_or_else(|| parent_turn_context.model_info.slug.clone());
|
||
let review_model_info = sess
|
||
.services
|
||
.models_manager
|
||
.get_model_info(&model, &config.to_models_manager_config())
|
||
.await;
|
||
// For reviews, disable web_search and view_image regardless of global settings.
|
||
let mut review_features = sess.features.clone();
|
||
let _ = review_features.disable(Feature::WebSearchRequest);
|
||
let _ = review_features.disable(Feature::WebSearchCached);
|
||
let review_web_search_mode = WebSearchMode::Disabled;
|
||
let tools_config = ToolsConfig::new(&ToolsConfigParams {
|
||
model_info: &review_model_info,
|
||
available_models: &sess
|
||
.services
|
||
.models_manager
|
||
.list_models(RefreshStrategy::OnlineIfUncached)
|
||
.await,
|
||
features: &review_features,
|
||
image_generation_tool_auth_allowed: image_generation_tool_auth_allowed(Some(
|
||
sess.services.auth_manager.as_ref(),
|
||
)),
|
||
web_search_mode: Some(review_web_search_mode),
|
||
session_source: parent_turn_context.session_source.clone(),
|
||
sandbox_policy: parent_turn_context.sandbox_policy.get(),
|
||
windows_sandbox_level: parent_turn_context.windows_sandbox_level,
|
||
})
|
||
.with_unified_exec_shell_mode_for_session(
|
||
crate::tools::spec::tool_user_shell_type(sess.services.user_shell.as_ref()),
|
||
sess.services.shell_zsh_path.as_ref(),
|
||
sess.services.main_execve_wrapper_exe.as_ref(),
|
||
)
|
||
.with_web_search_config(/*web_search_config*/ None)
|
||
.with_allow_login_shell(config.permissions.allow_login_shell)
|
||
.with_has_environment(parent_turn_context.environment.is_some())
|
||
.with_spawn_agent_usage_hint(config.multi_agent_v2.usage_hint_enabled)
|
||
.with_spawn_agent_usage_hint_text(config.multi_agent_v2.usage_hint_text.clone())
|
||
.with_hide_spawn_agent_metadata(config.multi_agent_v2.hide_spawn_agent_metadata)
|
||
.with_agent_type_description(crate::agent::role::spawn_tool_spec::build(
|
||
&config.agent_roles,
|
||
));
|
||
|
||
let review_prompt = resolved.prompt.clone();
|
||
let provider = parent_turn_context.provider.clone();
|
||
let auth_manager = parent_turn_context.auth_manager.clone();
|
||
let model_info = review_model_info.clone();
|
||
|
||
// Build per‑turn client with the requested model/family.
|
||
let mut per_turn_config = (*config).clone();
|
||
per_turn_config.model = Some(model.clone());
|
||
per_turn_config.features = review_features.clone();
|
||
if let Err(err) = per_turn_config.web_search_mode.set(review_web_search_mode) {
|
||
let fallback_value = per_turn_config.web_search_mode.value();
|
||
tracing::warn!(
|
||
error = %err,
|
||
?review_web_search_mode,
|
||
?fallback_value,
|
||
"review web_search_mode is disallowed by requirements; keeping constrained value"
|
||
);
|
||
}
|
||
|
||
let session_telemetry = parent_turn_context
|
||
.session_telemetry
|
||
.clone()
|
||
.with_model(model.as_str(), review_model_info.slug.as_str());
|
||
let auth_manager_for_context = auth_manager.clone();
|
||
let provider_for_context = provider.clone();
|
||
let session_telemetry_for_context = session_telemetry.clone();
|
||
let reasoning_effort = per_turn_config.model_reasoning_effort;
|
||
let reasoning_summary = per_turn_config
|
||
.model_reasoning_summary
|
||
.unwrap_or(model_info.default_reasoning_summary);
|
||
let session_source = parent_turn_context.session_source.clone();
|
||
|
||
let per_turn_config = Arc::new(per_turn_config);
|
||
let review_turn_id = sub_id.to_string();
|
||
let turn_metadata_state = Arc::new(TurnMetadataState::new(
|
||
sess.conversation_id.to_string(),
|
||
&session_source,
|
||
review_turn_id.clone(),
|
||
parent_turn_context.cwd.clone(),
|
||
parent_turn_context.sandbox_policy.get(),
|
||
parent_turn_context.windows_sandbox_level,
|
||
));
|
||
|
||
let review_turn_context = TurnContext {
|
||
sub_id: review_turn_id,
|
||
trace_id: current_span_trace_id(),
|
||
realtime_active: parent_turn_context.realtime_active,
|
||
config: per_turn_config,
|
||
auth_manager: auth_manager_for_context,
|
||
model_info: model_info.clone(),
|
||
session_telemetry: session_telemetry_for_context,
|
||
provider: provider_for_context,
|
||
reasoning_effort,
|
||
reasoning_summary,
|
||
session_source,
|
||
environment: parent_turn_context.environment.clone(),
|
||
tools_config,
|
||
features: parent_turn_context.features.clone(),
|
||
ghost_snapshot: parent_turn_context.ghost_snapshot.clone(),
|
||
current_date: parent_turn_context.current_date.clone(),
|
||
timezone: parent_turn_context.timezone.clone(),
|
||
app_server_client_name: parent_turn_context.app_server_client_name.clone(),
|
||
developer_instructions: None,
|
||
user_instructions: None,
|
||
compact_prompt: parent_turn_context.compact_prompt.clone(),
|
||
collaboration_mode: parent_turn_context.collaboration_mode.clone(),
|
||
personality: parent_turn_context.personality,
|
||
approval_policy: parent_turn_context.approval_policy.clone(),
|
||
sandbox_policy: parent_turn_context.sandbox_policy.clone(),
|
||
file_system_sandbox_policy: parent_turn_context.file_system_sandbox_policy.clone(),
|
||
network_sandbox_policy: parent_turn_context.network_sandbox_policy,
|
||
network: parent_turn_context.network.clone(),
|
||
windows_sandbox_level: parent_turn_context.windows_sandbox_level,
|
||
shell_environment_policy: parent_turn_context.shell_environment_policy.clone(),
|
||
cwd: parent_turn_context.cwd.clone(),
|
||
final_output_json_schema: None,
|
||
codex_self_exe: parent_turn_context.codex_self_exe.clone(),
|
||
codex_linux_sandbox_exe: parent_turn_context.codex_linux_sandbox_exe.clone(),
|
||
tool_call_gate: Arc::new(ReadinessFlag::new()),
|
||
js_repl: Arc::clone(&sess.js_repl),
|
||
dynamic_tools: parent_turn_context.dynamic_tools.clone(),
|
||
truncation_policy: model_info.truncation_policy.into(),
|
||
turn_metadata_state,
|
||
turn_skills: TurnSkillsContext::new(parent_turn_context.turn_skills.outcome.clone()),
|
||
turn_timing_state: Arc::new(TurnTimingState::default()),
|
||
};
|
||
|
||
// Seed the child task with the review prompt as the initial user message.
|
||
let input: Vec<UserInput> = vec![UserInput::Text {
|
||
text: review_prompt,
|
||
// Review prompt is synthesized; no UI element ranges to preserve.
|
||
text_elements: Vec::new(),
|
||
}];
|
||
let tc = Arc::new(review_turn_context);
|
||
tc.turn_metadata_state.spawn_git_enrichment_task();
|
||
// TODO(ccunningham): Review turns currently rely on `spawn_task` for TurnComplete but do not
|
||
// emit a parent TurnStarted. Consider giving review a full parent turn lifecycle
|
||
// (TurnStarted + TurnComplete) for consistency with other standalone tasks.
|
||
sess.spawn_task(tc.clone(), input, ReviewTask::new()).await;
|
||
|
||
// Announce entering review mode so UIs can switch modes.
|
||
let review_request = ReviewRequest {
|
||
target: resolved.target,
|
||
user_facing_hint: Some(resolved.user_facing_hint),
|
||
};
|
||
sess.send_event(&tc, EventMsg::EnteredReviewMode(review_request))
|
||
.await;
|
||
}
|