mirror of
https://github.com/openai/codex.git
synced 2026-11-05 20:10:33 +00:00
progress
This commit is contained in:
@@ -51,6 +51,7 @@ use crate::session::CodexSpawnOk;
|
||||
use crate::session::SUBMISSION_CHANNEL_CAPACITY;
|
||||
use crate::session::emit_subagent_session_started;
|
||||
use crate::session::session::Session;
|
||||
use crate::session::step_context::StepContext;
|
||||
use crate::session::turn_context::TurnContext;
|
||||
use codex_login::AuthManager;
|
||||
use codex_models_manager::manager::SharedModelsManager;
|
||||
@@ -79,6 +80,7 @@ pub(crate) async fn run_codex_thread_interactive(
|
||||
models_manager: SharedModelsManager,
|
||||
parent_session: Arc<Session>,
|
||||
parent_ctx: Arc<TurnContext>,
|
||||
step_context: Arc<StepContext>,
|
||||
cancel_token: CancellationToken,
|
||||
subagent_source: SubAgentSource,
|
||||
initial_history: Option<InitialHistory>,
|
||||
@@ -157,6 +159,7 @@ pub(crate) async fn run_codex_thread_interactive(
|
||||
// routing them to the parent session for decisions.
|
||||
let parent_session_clone = Arc::clone(&parent_session);
|
||||
let parent_ctx_clone = Arc::clone(&parent_ctx);
|
||||
let step_context_clone = Arc::clone(&step_context);
|
||||
let codex_for_events = Arc::clone(&codex);
|
||||
// Cache the child call's MCP metadata at begin time. The later legacy
|
||||
// RequestUserInput approval event only carries a call_id and question metadata.
|
||||
@@ -168,6 +171,7 @@ pub(crate) async fn run_codex_thread_interactive(
|
||||
tx_sub,
|
||||
parent_session_clone,
|
||||
parent_ctx_clone,
|
||||
step_context_clone,
|
||||
pending_mcp_invocations,
|
||||
cancel_token_events,
|
||||
)
|
||||
@@ -200,6 +204,7 @@ pub(crate) async fn run_codex_thread_one_shot(
|
||||
input: Vec<UserInput>,
|
||||
parent_session: Arc<Session>,
|
||||
parent_ctx: Arc<TurnContext>,
|
||||
step_context: Arc<StepContext>,
|
||||
cancel_token: CancellationToken,
|
||||
subagent_source: SubAgentSource,
|
||||
final_output_json_schema: Option<Value>,
|
||||
@@ -214,6 +219,7 @@ pub(crate) async fn run_codex_thread_one_shot(
|
||||
models_manager,
|
||||
parent_session,
|
||||
parent_ctx,
|
||||
step_context,
|
||||
child_cancel.clone(),
|
||||
subagent_source,
|
||||
initial_history,
|
||||
@@ -279,6 +285,7 @@ async fn forward_events(
|
||||
tx_sub: Sender<Event>,
|
||||
parent_session: Arc<Session>,
|
||||
parent_ctx: Arc<TurnContext>,
|
||||
step_context: Arc<StepContext>,
|
||||
pending_mcp_invocations: Arc<Mutex<HashMap<String, PendingMcpInvocation>>>,
|
||||
cancel_token: CancellationToken,
|
||||
) {
|
||||
@@ -315,6 +322,7 @@ async fn forward_events(
|
||||
id,
|
||||
&parent_session,
|
||||
&parent_ctx,
|
||||
Arc::clone(&step_context),
|
||||
event,
|
||||
&cancel_token,
|
||||
)
|
||||
@@ -329,6 +337,7 @@ async fn forward_events(
|
||||
id,
|
||||
&parent_session,
|
||||
&parent_ctx,
|
||||
Arc::clone(&step_context),
|
||||
event,
|
||||
&cancel_token,
|
||||
)
|
||||
@@ -342,6 +351,7 @@ async fn forward_events(
|
||||
&codex,
|
||||
&parent_session,
|
||||
&parent_ctx,
|
||||
&step_context,
|
||||
event,
|
||||
&cancel_token,
|
||||
)
|
||||
@@ -356,6 +366,7 @@ async fn forward_events(
|
||||
id,
|
||||
&parent_session,
|
||||
&parent_ctx,
|
||||
Arc::clone(&step_context),
|
||||
&pending_mcp_invocations,
|
||||
event,
|
||||
&cancel_token,
|
||||
@@ -493,6 +504,7 @@ async fn handle_exec_approval(
|
||||
turn_id: String,
|
||||
parent_session: &Arc<Session>,
|
||||
parent_ctx: &Arc<TurnContext>,
|
||||
step_context: Arc<StepContext>,
|
||||
event: ExecApprovalRequestEvent,
|
||||
cancel_token: &CancellationToken,
|
||||
) {
|
||||
@@ -515,6 +527,7 @@ async fn handle_exec_approval(
|
||||
let review_rx = spawn_approval_request_review(
|
||||
Arc::clone(parent_session),
|
||||
Arc::clone(parent_ctx),
|
||||
step_context,
|
||||
new_guardian_review_id(),
|
||||
GuardianApprovalRequest::Shell {
|
||||
id: call_id.clone(),
|
||||
@@ -578,6 +591,7 @@ async fn handle_patch_approval(
|
||||
_id: String,
|
||||
parent_session: &Arc<Session>,
|
||||
parent_ctx: &Arc<TurnContext>,
|
||||
step_context: Arc<StepContext>,
|
||||
event: ApplyPatchApprovalRequestEvent,
|
||||
cancel_token: &CancellationToken,
|
||||
) {
|
||||
@@ -628,6 +642,7 @@ async fn handle_patch_approval(
|
||||
let review_rx = spawn_approval_request_review(
|
||||
Arc::clone(parent_session),
|
||||
Arc::clone(parent_ctx),
|
||||
step_context,
|
||||
new_guardian_review_id(),
|
||||
GuardianApprovalRequest::ApplyPatch {
|
||||
id: approval_id.clone(),
|
||||
@@ -680,6 +695,7 @@ async fn handle_request_user_input(
|
||||
id: String,
|
||||
parent_session: &Arc<Session>,
|
||||
parent_ctx: &Arc<TurnContext>,
|
||||
step_context: Arc<StepContext>,
|
||||
pending_mcp_invocations: &Arc<Mutex<HashMap<String, PendingMcpInvocation>>>,
|
||||
event: RequestUserInputEvent,
|
||||
cancel_token: &CancellationToken,
|
||||
@@ -687,6 +703,7 @@ async fn handle_request_user_input(
|
||||
if let Some(response) = maybe_auto_review_mcp_request_user_input(
|
||||
parent_session,
|
||||
parent_ctx,
|
||||
step_context,
|
||||
pending_mcp_invocations,
|
||||
&event,
|
||||
cancel_token,
|
||||
@@ -723,6 +740,7 @@ async fn handle_request_user_input(
|
||||
async fn maybe_auto_review_mcp_request_user_input(
|
||||
parent_session: &Arc<Session>,
|
||||
parent_ctx: &Arc<TurnContext>,
|
||||
step_context: Arc<StepContext>,
|
||||
pending_mcp_invocations: &Arc<Mutex<HashMap<String, PendingMcpInvocation>>>,
|
||||
event: &RequestUserInputEvent,
|
||||
cancel_token: &CancellationToken,
|
||||
@@ -750,6 +768,7 @@ async fn maybe_auto_review_mcp_request_user_input(
|
||||
let review_rx = spawn_approval_request_review(
|
||||
Arc::clone(parent_session),
|
||||
Arc::clone(parent_ctx),
|
||||
step_context,
|
||||
new_guardian_review_id(),
|
||||
build_guardian_mcp_tool_review_request(&event.call_id, &invocation, metadata.as_ref()),
|
||||
/*retry_reason*/ None,
|
||||
@@ -796,6 +815,7 @@ async fn handle_request_permissions(
|
||||
codex: &Codex,
|
||||
parent_session: &Arc<Session>,
|
||||
parent_ctx: &Arc<TurnContext>,
|
||||
step_context: &Arc<StepContext>,
|
||||
event: RequestPermissionsEvent,
|
||||
cancel_token: &CancellationToken,
|
||||
) {
|
||||
@@ -811,6 +831,7 @@ async fn handle_request_permissions(
|
||||
});
|
||||
let response_fut = parent_session.request_permissions_for_cwd(
|
||||
parent_ctx,
|
||||
step_context,
|
||||
call_id.clone(),
|
||||
args,
|
||||
cwd,
|
||||
|
||||
@@ -15,6 +15,7 @@ use crate::responses_metadata::CompactionTurnMetadata;
|
||||
#[cfg(test)]
|
||||
use crate::session::PreviousTurnSettings;
|
||||
use crate::session::session::Session;
|
||||
use crate::session::step_context::StepContext;
|
||||
use crate::session::turn::get_last_assistant_message_from_turn;
|
||||
use crate::session::turn_context::TurnContext;
|
||||
use crate::util::backoff;
|
||||
@@ -70,13 +71,18 @@ pub(crate) enum InitialContextInjection {
|
||||
pub(crate) async fn build_compaction_initial_context(
|
||||
sess: &Session,
|
||||
turn_context: &TurnContext,
|
||||
step_context: &StepContext,
|
||||
initial_context_injection: &InitialContextInjection,
|
||||
) -> (Vec<ResponseItem>, Option<Arc<WorldState>>) {
|
||||
// Return the rendered state with its items so history and its baseline stay identical.
|
||||
match initial_context_injection {
|
||||
InitialContextInjection::BeforeLastUserMessage(world_state) => {
|
||||
let items = sess
|
||||
.build_initial_context_with_world_state(turn_context, world_state.as_ref())
|
||||
.build_initial_context_with_world_state(
|
||||
turn_context,
|
||||
world_state.as_ref(),
|
||||
step_context,
|
||||
)
|
||||
.await;
|
||||
(items, Some(Arc::clone(world_state)))
|
||||
}
|
||||
@@ -91,6 +97,7 @@ pub(crate) fn should_use_remote_compact_task(provider: &ModelProviderInfo) -> bo
|
||||
pub(crate) async fn run_inline_auto_compact_task(
|
||||
sess: Arc<Session>,
|
||||
turn_context: Arc<TurnContext>,
|
||||
step_context: Arc<StepContext>,
|
||||
initial_context_injection: InitialContextInjection,
|
||||
reason: CompactionReason,
|
||||
phase: CompactionPhase,
|
||||
@@ -110,6 +117,7 @@ pub(crate) async fn run_inline_auto_compact_task(
|
||||
run_compact_task_inner(
|
||||
sess,
|
||||
turn_context,
|
||||
step_context,
|
||||
input,
|
||||
initial_context_injection,
|
||||
CompactionTrigger::Auto,
|
||||
@@ -123,6 +131,7 @@ pub(crate) async fn run_inline_auto_compact_task(
|
||||
pub(crate) async fn run_compact_task(
|
||||
sess: Arc<Session>,
|
||||
turn_context: Arc<TurnContext>,
|
||||
step_context: Arc<StepContext>,
|
||||
input: Vec<UserInput>,
|
||||
) -> CodexResult<()> {
|
||||
let start_event = EventMsg::TurnStarted(TurnStartedEvent {
|
||||
@@ -130,12 +139,13 @@ pub(crate) async fn run_compact_task(
|
||||
trace_id: turn_context.trace_id.clone(),
|
||||
started_at: turn_context.turn_timing_state.started_at_unix_secs().await,
|
||||
model_context_window: turn_context.model_context_window(),
|
||||
collaboration_mode_kind: turn_context.collaboration_mode.mode,
|
||||
collaboration_mode_kind: turn_context.mode,
|
||||
});
|
||||
sess.send_event(&turn_context, start_event).await;
|
||||
run_compact_task_inner(
|
||||
sess.clone(),
|
||||
turn_context,
|
||||
step_context,
|
||||
input,
|
||||
InitialContextInjection::DoNotInject,
|
||||
CompactionTrigger::Manual,
|
||||
@@ -149,6 +159,7 @@ pub(crate) async fn run_compact_task(
|
||||
async fn run_compact_task_inner(
|
||||
sess: Arc<Session>,
|
||||
turn_context: Arc<TurnContext>,
|
||||
step_context: Arc<StepContext>,
|
||||
input: Vec<UserInput>,
|
||||
initial_context_injection: InitialContextInjection,
|
||||
trigger: CompactionTrigger,
|
||||
@@ -185,6 +196,7 @@ async fn run_compact_task_inner(
|
||||
let result = run_compact_task_inner_impl(
|
||||
Arc::clone(&sess),
|
||||
Arc::clone(&turn_context),
|
||||
step_context,
|
||||
input,
|
||||
initial_context_injection,
|
||||
compaction_metadata,
|
||||
@@ -220,6 +232,7 @@ async fn run_compact_task_inner(
|
||||
async fn run_compact_task_inner_impl(
|
||||
sess: Arc<Session>,
|
||||
turn_context: Arc<TurnContext>,
|
||||
step_context: Arc<StepContext>,
|
||||
input: Vec<UserInput>,
|
||||
initial_context_injection: InitialContextInjection,
|
||||
compaction_metadata: CompactionTurnMetadata,
|
||||
@@ -262,6 +275,7 @@ async fn run_compact_task_inner_impl(
|
||||
let attempt_result = drain_to_completed(
|
||||
&sess,
|
||||
turn_context.as_ref(),
|
||||
step_context.as_ref(),
|
||||
&mut client_session,
|
||||
&responses_metadata,
|
||||
&prompt,
|
||||
@@ -336,6 +350,7 @@ async fn run_compact_task_inner_impl(
|
||||
let (initial_context, world_state_baseline) = build_compaction_initial_context(
|
||||
sess.as_ref(),
|
||||
turn_context.as_ref(),
|
||||
step_context.as_ref(),
|
||||
&initial_context_injection,
|
||||
)
|
||||
.await;
|
||||
@@ -346,7 +361,7 @@ async fn run_compact_task_inner_impl(
|
||||
let reference_context_item = match initial_context_injection {
|
||||
InitialContextInjection::DoNotInject => None,
|
||||
InitialContextInjection::BeforeLastUserMessage(_) => {
|
||||
Some(turn_context.to_turn_context_item())
|
||||
Some(turn_context.to_turn_context_item(&step_context))
|
||||
}
|
||||
};
|
||||
let compacted_item = CompactedItem {
|
||||
@@ -661,6 +676,7 @@ fn build_compacted_history_with_limit(
|
||||
async fn drain_to_completed(
|
||||
sess: &Session,
|
||||
turn_context: &TurnContext,
|
||||
step_context: &StepContext,
|
||||
client_session: &mut ModelClientSession,
|
||||
responses_metadata: &CodexResponsesMetadata,
|
||||
prompt: &Prompt,
|
||||
@@ -670,7 +686,7 @@ async fn drain_to_completed(
|
||||
prompt,
|
||||
&turn_context.model_info,
|
||||
&turn_context.session_telemetry,
|
||||
turn_context.reasoning_effort.clone(),
|
||||
step_context.effective_reasoning_effort(),
|
||||
turn_context.reasoning_summary,
|
||||
turn_context.config.service_tier.clone(),
|
||||
responses_metadata,
|
||||
|
||||
@@ -81,7 +81,7 @@ pub(crate) async fn run_remote_compact_task(
|
||||
trace_id: turn_context.trace_id.clone(),
|
||||
started_at: turn_context.turn_timing_state.started_at_unix_secs().await,
|
||||
model_context_window: turn_context.model_context_window(),
|
||||
collaboration_mode_kind: turn_context.collaboration_mode.mode,
|
||||
collaboration_mode_kind: turn_context.mode,
|
||||
});
|
||||
sess.send_event(&turn_context, start_event).await;
|
||||
|
||||
@@ -260,6 +260,7 @@ async fn run_remote_compact_task_inner_impl(
|
||||
let (new_history, world_state_baseline) = process_compacted_history(
|
||||
sess.as_ref(),
|
||||
compaction_turn_context.as_ref(),
|
||||
step_context.as_ref(),
|
||||
new_history,
|
||||
&initial_context_injection,
|
||||
)
|
||||
@@ -268,7 +269,7 @@ async fn run_remote_compact_task_inner_impl(
|
||||
let reference_context_item = match initial_context_injection {
|
||||
InitialContextInjection::DoNotInject => None,
|
||||
InitialContextInjection::BeforeLastUserMessage(_) => {
|
||||
Some(compaction_turn_context.to_turn_context_item())
|
||||
Some(compaction_turn_context.to_turn_context_item(step_context))
|
||||
}
|
||||
};
|
||||
let compacted_item = CompactedItem {
|
||||
@@ -304,14 +305,20 @@ async fn run_remote_compact_task_inner_impl(
|
||||
pub(crate) async fn process_compacted_history(
|
||||
sess: &Session,
|
||||
turn_context: &TurnContext,
|
||||
step_context: &StepContext,
|
||||
mut compacted_history: Vec<ResponseItem>,
|
||||
initial_context_injection: &InitialContextInjection,
|
||||
) -> (Vec<ResponseItem>, Option<Arc<WorldState>>) {
|
||||
// Mid-turn compaction is the only path that must inject initial context above the last user
|
||||
// message in the replacement history. Pre-turn compaction instead injects context after the
|
||||
// compaction item, but mid-turn compaction keeps the compaction item last for model training.
|
||||
let (initial_context, world_state_baseline) =
|
||||
build_compaction_initial_context(sess, turn_context, initial_context_injection).await;
|
||||
let (initial_context, world_state_baseline) = build_compaction_initial_context(
|
||||
sess,
|
||||
turn_context,
|
||||
step_context,
|
||||
initial_context_injection,
|
||||
)
|
||||
.await;
|
||||
|
||||
compacted_history.retain(should_keep_compacted_history_item);
|
||||
(
|
||||
|
||||
@@ -87,7 +87,7 @@ pub(super) async fn run_remote_compact_attempt(
|
||||
&turn_context.model_info,
|
||||
turn_state,
|
||||
CompactConversationRequestSettings {
|
||||
effort: turn_context.reasoning_effort.clone(),
|
||||
effort: step_context.effective_reasoning_effort().clone(),
|
||||
summary: turn_context.reasoning_summary,
|
||||
service_tier: if sess.services.auth_manager.auth_mode() == Some(AuthMode::ApiKey) {
|
||||
None
|
||||
|
||||
@@ -92,7 +92,7 @@ pub(crate) async fn run_remote_compact_task(
|
||||
trace_id: turn_context.trace_id.clone(),
|
||||
started_at: turn_context.turn_timing_state.started_at_unix_secs().await,
|
||||
model_context_window: turn_context.model_context_window(),
|
||||
collaboration_mode_kind: turn_context.collaboration_mode.mode,
|
||||
collaboration_mode_kind: turn_context.mode,
|
||||
});
|
||||
sess.send_event(&turn_context, start_event).await;
|
||||
|
||||
@@ -284,6 +284,7 @@ async fn run_remote_compact_task_inner_impl(
|
||||
let (new_history, world_state_baseline) = process_compacted_history(
|
||||
sess.as_ref(),
|
||||
compaction_turn_context.as_ref(),
|
||||
step_context.as_ref(),
|
||||
compacted_history,
|
||||
&initial_context_injection,
|
||||
)
|
||||
@@ -292,7 +293,7 @@ async fn run_remote_compact_task_inner_impl(
|
||||
let reference_context_item = match initial_context_injection {
|
||||
InitialContextInjection::DoNotInject => None,
|
||||
InitialContextInjection::BeforeLastUserMessage(_) => {
|
||||
Some(compaction_turn_context.to_turn_context_item())
|
||||
Some(compaction_turn_context.to_turn_context_item(step_context))
|
||||
}
|
||||
};
|
||||
let compacted_item = CompactedItem {
|
||||
@@ -330,6 +331,7 @@ struct RemoteCompactionV2Output {
|
||||
async fn run_remote_compaction_request_v2(
|
||||
sess: &Session,
|
||||
turn_context: &TurnContext,
|
||||
step_context: &StepContext,
|
||||
client_session: &mut ModelClientSession,
|
||||
prompt: &Prompt,
|
||||
responses_metadata: &CodexResponsesMetadata,
|
||||
@@ -346,7 +348,7 @@ async fn run_remote_compaction_request_v2(
|
||||
prompt,
|
||||
&turn_context.model_info,
|
||||
&turn_context.session_telemetry,
|
||||
turn_context.reasoning_effort.clone(),
|
||||
step_context.effective_reasoning_effort(),
|
||||
turn_context.reasoning_summary,
|
||||
turn_context.config.service_tier.clone(),
|
||||
responses_metadata,
|
||||
|
||||
@@ -102,6 +102,7 @@ pub(super) async fn run_remote_compact_v2_attempt(
|
||||
let compaction_output_result = run_remote_compaction_request_v2(
|
||||
sess,
|
||||
turn_context.as_ref(),
|
||||
step_context.as_ref(),
|
||||
client_session,
|
||||
&prompt,
|
||||
&responses_metadata,
|
||||
|
||||
@@ -24,6 +24,7 @@ use codex_protocol::protocol::TurnStartedEvent;
|
||||
/// observe the same lifecycle as local or remote compaction.
|
||||
pub(crate) async fn run_manual_compact_task(
|
||||
sess: Arc<Session>,
|
||||
step_context: Arc<StepContext>,
|
||||
turn_context: Arc<TurnContext>,
|
||||
) -> CodexResult<()> {
|
||||
let start_event = EventMsg::TurnStarted(TurnStartedEvent {
|
||||
@@ -31,14 +32,20 @@ pub(crate) async fn run_manual_compact_task(
|
||||
trace_id: turn_context.trace_id.clone(),
|
||||
started_at: turn_context.turn_timing_state.started_at_unix_secs().await,
|
||||
model_context_window: turn_context.model_context_window(),
|
||||
collaboration_mode_kind: turn_context.collaboration_mode.mode,
|
||||
collaboration_mode_kind: turn_context.mode,
|
||||
});
|
||||
sess.send_event(&turn_context, start_event).await;
|
||||
|
||||
// Manual compaction runs outside run_turn, so it captures its own current step.
|
||||
let step_context = sess.capture_step_context(Arc::clone(&turn_context)).await;
|
||||
let world_state = Arc::new(sess.build_world_state_for_step(&step_context).await);
|
||||
run_compact_task_inner(&sess, &turn_context, world_state, CompactionTrigger::Manual).await
|
||||
run_compact_task_inner(
|
||||
&sess,
|
||||
&turn_context,
|
||||
&step_context,
|
||||
world_state,
|
||||
CompactionTrigger::Manual,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Runs token-budget inline auto-compaction as a normal compaction lifecycle.
|
||||
@@ -58,12 +65,20 @@ pub(crate) async fn run_inline_auto_compact_task(
|
||||
Arc::new(sess.build_world_state_for_step(&step_context).await)
|
||||
}
|
||||
};
|
||||
run_compact_task_inner(&sess, turn_context, world_state, CompactionTrigger::Auto).await
|
||||
run_compact_task_inner(
|
||||
&sess,
|
||||
turn_context,
|
||||
&step_context,
|
||||
world_state,
|
||||
CompactionTrigger::Auto,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn run_compact_task_inner(
|
||||
sess: &Arc<Session>,
|
||||
turn_context: &Arc<TurnContext>,
|
||||
step_context: &Arc<StepContext>,
|
||||
world_state: Arc<WorldState>,
|
||||
trigger: CompactionTrigger,
|
||||
) -> CodexResult<()> {
|
||||
@@ -76,7 +91,7 @@ async fn run_compact_task_inner(
|
||||
let compaction_item = TurnItem::ContextCompaction(ContextCompactionItem::new());
|
||||
sess.emit_turn_item_started(turn_context, &compaction_item)
|
||||
.await;
|
||||
sess.start_new_context_window(turn_context.as_ref(), world_state)
|
||||
sess.start_new_context_window(turn_context.as_ref(), world_state, step_context.as_ref())
|
||||
.await;
|
||||
sess.emit_turn_item_completed(turn_context, compaction_item)
|
||||
.await;
|
||||
|
||||
@@ -9,6 +9,7 @@ use crate::context::RealtimeEndInstructions;
|
||||
use crate::context::RealtimeStartInstructions;
|
||||
use crate::context::RealtimeStartWithInstructions;
|
||||
use crate::session::PreviousTurnSettings;
|
||||
use crate::session::step_context::StepContext;
|
||||
use crate::session::turn_context::TurnContext;
|
||||
use codex_execpolicy::Policy;
|
||||
use codex_features::Feature;
|
||||
@@ -70,13 +71,11 @@ fn build_collaboration_mode_update_item(
|
||||
}
|
||||
|
||||
let prev = previous?;
|
||||
if prev.collaboration_mode.as_ref() != Some(&next.collaboration_mode) {
|
||||
let collaboration_mode = next.collaboration_mode();
|
||||
if prev.collaboration_mode.as_ref() != Some(&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(),
|
||||
)
|
||||
Some(CollaborationModeInstructions::from_collaboration_mode(&collaboration_mode)?.render())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -85,8 +84,10 @@ fn build_collaboration_mode_update_item(
|
||||
fn build_multi_agent_mode_update_item(
|
||||
previous: Option<&TurnContextItem>,
|
||||
next: &TurnContext,
|
||||
step_context: &StepContext,
|
||||
) -> Option<String> {
|
||||
let effective_multi_agent_mode = crate::session::multi_agents::effective_multi_agent_mode(next);
|
||||
let effective_multi_agent_mode =
|
||||
crate::session::multi_agents::effective_multi_agent_mode(next, step_context);
|
||||
let previous = previous?;
|
||||
if previous.multi_agent_mode == effective_multi_agent_mode {
|
||||
return None;
|
||||
@@ -241,6 +242,7 @@ pub(crate) fn build_settings_update_items(
|
||||
previous: Option<&TurnContextItem>,
|
||||
previous_turn_settings: Option<&PreviousTurnSettings>,
|
||||
next: &TurnContext,
|
||||
step_context: &StepContext,
|
||||
exec_policy: &Policy,
|
||||
personality_feature_enabled: bool,
|
||||
) -> Vec<ResponseItem> {
|
||||
@@ -254,7 +256,7 @@ pub(crate) fn build_settings_update_items(
|
||||
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_multi_agent_mode_update_item(previous, next),
|
||||
build_multi_agent_mode_update_item(previous, next, step_context),
|
||||
build_realtime_update_item(previous, previous_turn_settings, next),
|
||||
build_personality_update_item(previous, next, personality_feature_enabled),
|
||||
]
|
||||
|
||||
@@ -25,6 +25,7 @@ use tokio::time::sleep_until;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
use crate::session::session::Session;
|
||||
use crate::session::step_context::StepContext;
|
||||
use crate::session::turn_context::TurnContext;
|
||||
use crate::turn_timing::now_unix_timestamp_ms;
|
||||
use crate::util::backoff;
|
||||
@@ -275,6 +276,7 @@ pub(crate) async fn record_guardian_denial_for_test(
|
||||
async fn run_guardian_review(
|
||||
session: Arc<Session>,
|
||||
turn: Arc<TurnContext>,
|
||||
step_context: Arc<StepContext>,
|
||||
review_id: String,
|
||||
request: GuardianApprovalRequest,
|
||||
retry_reason: Option<String>,
|
||||
@@ -359,6 +361,7 @@ async fn run_guardian_review(
|
||||
let (outcome, analytics_result) = Box::pin(run_guardian_review_session_with_retry(
|
||||
session.clone(),
|
||||
turn.clone(),
|
||||
step_context.clone(),
|
||||
request,
|
||||
retry_reason.clone(),
|
||||
schema,
|
||||
@@ -594,6 +597,7 @@ async fn run_guardian_review(
|
||||
pub(crate) async fn review_approval_request(
|
||||
session: &Arc<Session>,
|
||||
turn: &Arc<TurnContext>,
|
||||
step_context: Arc<StepContext>,
|
||||
review_id: String,
|
||||
request: GuardianApprovalRequest,
|
||||
retry_reason: Option<String>,
|
||||
@@ -603,6 +607,7 @@ pub(crate) async fn review_approval_request(
|
||||
Box::pin(run_guardian_review(
|
||||
Arc::clone(session),
|
||||
Arc::clone(turn),
|
||||
step_context,
|
||||
review_id,
|
||||
request,
|
||||
retry_reason,
|
||||
@@ -615,6 +620,7 @@ pub(crate) async fn review_approval_request(
|
||||
pub(crate) async fn review_approval_request_with_cancel(
|
||||
session: &Arc<Session>,
|
||||
turn: &Arc<TurnContext>,
|
||||
step_context: Arc<StepContext>,
|
||||
review_id: String,
|
||||
request: GuardianApprovalRequest,
|
||||
retry_reason: Option<String>,
|
||||
@@ -624,6 +630,7 @@ pub(crate) async fn review_approval_request_with_cancel(
|
||||
run_guardian_review(
|
||||
Arc::clone(session),
|
||||
Arc::clone(turn),
|
||||
step_context,
|
||||
review_id,
|
||||
request,
|
||||
retry_reason,
|
||||
@@ -636,6 +643,7 @@ pub(crate) async fn review_approval_request_with_cancel(
|
||||
pub(crate) fn spawn_approval_request_review(
|
||||
session: Arc<Session>,
|
||||
turn: Arc<TurnContext>,
|
||||
step_context: Arc<StepContext>,
|
||||
review_id: String,
|
||||
request: GuardianApprovalRequest,
|
||||
retry_reason: Option<String>,
|
||||
@@ -654,6 +662,7 @@ pub(crate) fn spawn_approval_request_review(
|
||||
let decision = runtime.block_on(review_approval_request_with_cancel(
|
||||
&session,
|
||||
&turn,
|
||||
step_context,
|
||||
review_id,
|
||||
request,
|
||||
retry_reason,
|
||||
@@ -678,6 +687,7 @@ pub(super) struct GuardianReviewSessionConfig {
|
||||
pub(super) async fn guardian_review_session_config(
|
||||
session: &Session,
|
||||
turn: &TurnContext,
|
||||
step_context: &StepContext,
|
||||
) -> anyhow::Result<GuardianReviewSessionConfig> {
|
||||
let network_proxy = session.services.network_proxy.load_full();
|
||||
let live_network_config = match network_proxy.as_ref() {
|
||||
@@ -722,7 +732,8 @@ pub(super) async fn guardian_review_session_config(
|
||||
.supported_reasoning_levels
|
||||
.iter()
|
||||
.any(|preset| preset.effort == codex_protocol::openai_models::ReasoningEffort::Low),
|
||||
turn.reasoning_effort
|
||||
step_context
|
||||
.reasoning_effort
|
||||
.clone()
|
||||
.or_else(|| turn.model_info.default_reasoning_level.clone()),
|
||||
);
|
||||
@@ -768,13 +779,19 @@ pub(super) async fn guardian_review_session_config(
|
||||
async fn run_guardian_review_session_before_deadline(
|
||||
session: Arc<Session>,
|
||||
turn: Arc<TurnContext>,
|
||||
step_context: Arc<StepContext>,
|
||||
request: GuardianApprovalRequest,
|
||||
retry_reason: Option<String>,
|
||||
schema: serde_json::Value,
|
||||
external_cancel: Option<CancellationToken>,
|
||||
deadline: Instant,
|
||||
) -> (GuardianReviewOutcome, GuardianReviewAnalyticsResult) {
|
||||
let session_config = match guardian_review_session_config(session.as_ref(), turn.as_ref()).await
|
||||
let session_config = match guardian_review_session_config(
|
||||
session.as_ref(),
|
||||
turn.as_ref(),
|
||||
step_context.as_ref(),
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(session_config) => session_config,
|
||||
Err(err) => {
|
||||
@@ -790,6 +807,7 @@ async fn run_guardian_review_session_before_deadline(
|
||||
.run_review(GuardianReviewSessionParams {
|
||||
parent_session: Arc::clone(&session),
|
||||
parent_turn: turn.clone(),
|
||||
step_context,
|
||||
spawn_config: session_config.spawn_config,
|
||||
request,
|
||||
retry_reason,
|
||||
@@ -862,6 +880,7 @@ async fn run_guardian_review_session_before_deadline(
|
||||
pub(super) async fn run_guardian_review_session_with_retry(
|
||||
session: Arc<Session>,
|
||||
turn: Arc<TurnContext>,
|
||||
step_context: Arc<StepContext>,
|
||||
request: GuardianApprovalRequest,
|
||||
retry_reason: Option<String>,
|
||||
schema: serde_json::Value,
|
||||
@@ -875,6 +894,7 @@ pub(super) async fn run_guardian_review_session_with_retry(
|
||||
let (outcome, mut analytics_result) = run_guardian_review_session_before_deadline(
|
||||
Arc::clone(&session),
|
||||
Arc::clone(&turn),
|
||||
Arc::clone(&step_context),
|
||||
request.clone(),
|
||||
retry_reason.clone(),
|
||||
schema.clone(),
|
||||
|
||||
@@ -44,6 +44,7 @@ use crate::context::ContextualUserFragment;
|
||||
use crate::context::GuardianFollowupReviewReminder;
|
||||
use crate::session::Codex;
|
||||
use crate::session::session::Session;
|
||||
use crate::session::step_context::StepContext;
|
||||
use crate::session::turn_context::TurnContext;
|
||||
use codex_config::types::McpServerConfig;
|
||||
use codex_features::Feature;
|
||||
@@ -75,6 +76,7 @@ pub(crate) enum GuardianReviewSessionOutcome {
|
||||
pub(crate) struct GuardianReviewSessionParams {
|
||||
pub(crate) parent_session: Arc<Session>,
|
||||
pub(crate) parent_turn: Arc<TurnContext>,
|
||||
pub(crate) step_context: Arc<StepContext>,
|
||||
pub(crate) spawn_config: Config,
|
||||
pub(crate) request: GuardianApprovalRequest,
|
||||
pub(crate) retry_reason: Option<String>,
|
||||
@@ -296,12 +298,14 @@ impl GuardianReviewSessionManager {
|
||||
&self,
|
||||
parent_session: Arc<Session>,
|
||||
parent_turn: Arc<TurnContext>,
|
||||
step_context: Arc<StepContext>,
|
||||
) -> BoxFuture<'_, anyhow::Result<()>> {
|
||||
// Boxing breaks the Session::new -> Guardian -> Session::new future recursion.
|
||||
Box::pin(async move {
|
||||
let spawn_config = guardian_review_session_config(&parent_session, &parent_turn)
|
||||
.await?
|
||||
.spawn_config;
|
||||
let spawn_config =
|
||||
guardian_review_session_config(&parent_session, &parent_turn, &step_context)
|
||||
.await?
|
||||
.spawn_config;
|
||||
let reuse_key = GuardianReviewSessionReuseKey::from_spawn_config(
|
||||
&spawn_config,
|
||||
parent_session.user_instructions().await,
|
||||
@@ -311,6 +315,7 @@ impl GuardianReviewSessionManager {
|
||||
let review_session = spawn_guardian_review_session(
|
||||
&parent_session,
|
||||
&parent_turn,
|
||||
Arc::clone(&step_context),
|
||||
spawn_config,
|
||||
reuse_key,
|
||||
spawn_cancel_token.clone(),
|
||||
@@ -396,6 +401,7 @@ impl GuardianReviewSessionManager {
|
||||
Box::pin(spawn_guardian_review_session(
|
||||
¶ms.parent_session,
|
||||
¶ms.parent_turn,
|
||||
Arc::clone(¶ms.step_context),
|
||||
params.spawn_config.clone(),
|
||||
next_reuse_key.clone(),
|
||||
spawn_cancel_token.clone(),
|
||||
@@ -607,6 +613,7 @@ impl GuardianReviewSessionManager {
|
||||
Box::pin(spawn_guardian_review_session(
|
||||
¶ms.parent_session,
|
||||
¶ms.parent_turn,
|
||||
Arc::clone(¶ms.step_context),
|
||||
fork_config,
|
||||
reuse_key,
|
||||
spawn_cancel_token.clone(),
|
||||
@@ -649,6 +656,7 @@ impl GuardianReviewSessionManager {
|
||||
async fn spawn_guardian_review_session(
|
||||
parent_session: &Arc<Session>,
|
||||
parent_turn: &Arc<TurnContext>,
|
||||
step_context: Arc<StepContext>,
|
||||
spawn_config: Config,
|
||||
reuse_key: GuardianReviewSessionReuseKey,
|
||||
cancel_token: CancellationToken,
|
||||
@@ -668,6 +676,7 @@ async fn spawn_guardian_review_session(
|
||||
parent_session.services.models_manager.clone(),
|
||||
Arc::clone(parent_session),
|
||||
Arc::clone(parent_turn),
|
||||
step_context,
|
||||
cancel_token.clone(),
|
||||
SubAgentSource::Other(GUARDIAN_REVIEWER_NAME.to_string()),
|
||||
initial_history,
|
||||
@@ -1217,9 +1226,13 @@ mod tests {
|
||||
)
|
||||
.expect("guardian config");
|
||||
|
||||
let turn = Arc::new(turn);
|
||||
let step_context = StepContext::for_test(Arc::clone(&turn));
|
||||
|
||||
GuardianReviewSessionParams {
|
||||
parent_session: Arc::new(session),
|
||||
parent_turn: Arc::new(turn),
|
||||
parent_turn: Arc::clone(&turn),
|
||||
step_context,
|
||||
spawn_config,
|
||||
request: GuardianApprovalRequest::Shell {
|
||||
id: "shell-1".to_string(),
|
||||
|
||||
@@ -395,7 +395,7 @@ async fn handle_approved_mcp_tool_call(
|
||||
let result = async {
|
||||
let rewritten_arguments = rewrite?;
|
||||
let request_meta =
|
||||
build_mcp_tool_call_request_meta(turn_context, &server, call_id, metadata);
|
||||
build_mcp_tool_call_request_meta(step_context, &server, call_id, metadata);
|
||||
execute_mcp_tool_call(
|
||||
sess,
|
||||
step_context,
|
||||
@@ -1081,18 +1081,19 @@ async fn custom_mcp_tool_approval_mode(
|
||||
}
|
||||
|
||||
fn build_mcp_tool_call_request_meta(
|
||||
turn_context: &TurnContext,
|
||||
step_context: &StepContext,
|
||||
server: &str,
|
||||
call_id: &str,
|
||||
metadata: Option<&McpToolApprovalMetadata>,
|
||||
) -> Option<serde_json::Value> {
|
||||
let turn_context = step_context.turn.as_ref();
|
||||
let mut request_meta = serde_json::Map::new();
|
||||
|
||||
if let Some(turn_metadata) = turn_context
|
||||
.turn_metadata_state
|
||||
.current_meta_value_for_mcp_request(McpTurnMetadataContext {
|
||||
model: turn_context.model_info.slug.as_str(),
|
||||
reasoning_effort: turn_context.effective_reasoning_effort(),
|
||||
reasoning_effort: step_context.effective_reasoning_effort(),
|
||||
})
|
||||
{
|
||||
request_meta.insert(
|
||||
@@ -1274,6 +1275,7 @@ async fn maybe_request_mcp_tool_approval(
|
||||
let decision = review_approval_request(
|
||||
sess,
|
||||
turn_context,
|
||||
Arc::clone(step_context),
|
||||
review_id.clone(),
|
||||
build_guardian_mcp_tool_review_request(call_id, invocation, metadata),
|
||||
/*retry_reason*/ None,
|
||||
|
||||
@@ -86,7 +86,7 @@ impl Session {
|
||||
let turn_context = self
|
||||
.new_default_turn_with_sub_id(uuid::Uuid::new_v4().to_string())
|
||||
.await;
|
||||
if turn_context.collaboration_mode.mode == ModeKind::Plan {
|
||||
if turn_context.mode == ModeKind::Plan {
|
||||
self.clear_reserved_idle_turn(&turn_state).await;
|
||||
self.maybe_start_turn_for_pending_work().await;
|
||||
return Err(TryStartTurnIfIdleError::new(
|
||||
|
||||
@@ -588,11 +588,12 @@ async fn review_guardian_mcp_elicitation(
|
||||
session: Arc<Session>,
|
||||
request: ElicitationReviewRequest,
|
||||
) -> anyhow::Result<Option<ElicitationResponse>> {
|
||||
let Some((turn_context, _cancellation_token)) =
|
||||
session.active_turn_context_and_cancellation_token().await
|
||||
let Some((step_context, _cancellation_token)) =
|
||||
session.active_step_context_and_cancellation_token().await
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
let turn_context = Arc::clone(&step_context.turn);
|
||||
|
||||
let approvals_reviewer = crate::connectors::mcp_approvals_reviewer(
|
||||
turn_context.config.as_ref(),
|
||||
@@ -624,6 +625,7 @@ async fn review_guardian_mcp_elicitation(
|
||||
let decision = crate::guardian::review_approval_request(
|
||||
&session,
|
||||
&turn_context,
|
||||
step_context,
|
||||
review_id.clone(),
|
||||
guardian_request,
|
||||
/*retry_reason*/ None,
|
||||
|
||||
@@ -344,7 +344,6 @@ use codex_protocol::config_types::WindowsSandboxLevel;
|
||||
use codex_protocol::models::LocalImagePreparation;
|
||||
use codex_protocol::models::ResponseInputItem;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use codex_protocol::openai_models::ReasoningEffort as ReasoningEffortConfig;
|
||||
use codex_protocol::protocol::ApplyPatchApprovalRequestEvent;
|
||||
use codex_protocol::protocol::AskForApproval;
|
||||
use codex_protocol::protocol::CodexErrorInfo;
|
||||
@@ -1730,6 +1729,7 @@ impl Session {
|
||||
&self,
|
||||
reference_context_item: Option<&TurnContextItem>,
|
||||
current_context: &TurnContext,
|
||||
step_context: &StepContext,
|
||||
) -> Vec<ResponseItem> {
|
||||
// TODO: Make context updates a pure diff of persisted previous/current TurnContextItem
|
||||
// state so replay/backtracking is deterministic. Runtime inputs that affect model-visible
|
||||
@@ -1744,6 +1744,7 @@ impl Session {
|
||||
reference_context_item,
|
||||
previous_turn_settings.as_ref(),
|
||||
current_context,
|
||||
step_context,
|
||||
exec_policy.as_ref(),
|
||||
self.features.enabled(Feature::Personality),
|
||||
)
|
||||
@@ -2033,6 +2034,27 @@ impl Session {
|
||||
))
|
||||
}
|
||||
|
||||
pub(crate) async fn set_active_step_context(&self, step_context: Arc<StepContext>) {
|
||||
let mut active = self.active_turn.lock().await;
|
||||
let Some(task) = active.as_mut().and_then(|turn| turn.task.as_mut()) else {
|
||||
return;
|
||||
};
|
||||
if task.turn_context.sub_id == step_context.turn.sub_id {
|
||||
task.step_context = Some(step_context);
|
||||
}
|
||||
}
|
||||
|
||||
async fn active_step_context_and_cancellation_token(
|
||||
&self,
|
||||
) -> Option<(Arc<StepContext>, CancellationToken)> {
|
||||
let active = self.active_turn.lock().await;
|
||||
let task = active.as_ref()?.task.as_ref()?;
|
||||
Some((
|
||||
Arc::clone(task.step_context.as_ref()?),
|
||||
task.cancellation_token.child_token(),
|
||||
))
|
||||
}
|
||||
|
||||
pub(crate) async fn record_execpolicy_amendment_message(
|
||||
&self,
|
||||
sub_id: &str,
|
||||
@@ -2268,6 +2290,7 @@ impl Session {
|
||||
pub(crate) async fn request_permissions_for_environment(
|
||||
self: &Arc<Self>,
|
||||
turn_context: &Arc<TurnContext>,
|
||||
step_context: &Arc<StepContext>,
|
||||
call_id: String,
|
||||
args: RequestPermissionsArgs,
|
||||
environment: TurnEnvironmentSelection,
|
||||
@@ -2326,6 +2349,7 @@ impl Session {
|
||||
let review_rx = crate::guardian::spawn_approval_request_review(
|
||||
session,
|
||||
turn,
|
||||
step_context.clone(),
|
||||
review_id,
|
||||
request,
|
||||
/*retry_reason*/ None,
|
||||
@@ -2436,6 +2460,7 @@ impl Session {
|
||||
pub(crate) async fn request_permissions_for_cwd(
|
||||
self: &Arc<Self>,
|
||||
turn_context: &Arc<TurnContext>,
|
||||
step_context: &Arc<StepContext>,
|
||||
call_id: String,
|
||||
args: RequestPermissionsArgs,
|
||||
cwd: AbsolutePathBuf,
|
||||
@@ -2460,6 +2485,7 @@ impl Session {
|
||||
environment.cwd = PathUri::from_abs_path(&cwd);
|
||||
self.request_permissions_for_environment(
|
||||
turn_context,
|
||||
step_context,
|
||||
call_id,
|
||||
args,
|
||||
environment,
|
||||
@@ -3165,9 +3191,9 @@ impl Session {
|
||||
&self,
|
||||
turn_context: &TurnContext,
|
||||
world_state: &WorldState,
|
||||
step_context: &StepContext,
|
||||
) -> Vec<ResponseItem> {
|
||||
let mcp = self.services.latest_mcp_runtime();
|
||||
self.build_initial_context_with_world_state_and_mcp(turn_context, world_state, &mcp)
|
||||
self.build_initial_context_with_world_state_and_mcp(turn_context, world_state, step_context)
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -3175,8 +3201,9 @@ impl Session {
|
||||
&self,
|
||||
turn_context: &TurnContext,
|
||||
world_state: &WorldState,
|
||||
mcp: &McpRuntimeSnapshot,
|
||||
step_context: &StepContext,
|
||||
) -> Vec<ResponseItem> {
|
||||
let mcp = step_context.mcp.as_ref();
|
||||
let mut developer_sections = Vec::<String>::with_capacity(8);
|
||||
let mut contextual_user_sections = Vec::<String>::with_capacity(2);
|
||||
let mut separate_developer_sections = Vec::<String>::new();
|
||||
@@ -3447,7 +3474,9 @@ impl Session {
|
||||
{
|
||||
items.push(usage_hint_message);
|
||||
}
|
||||
if let Some(multi_agent_mode) = multi_agents::effective_multi_agent_mode(turn_context) {
|
||||
if let Some(multi_agent_mode) =
|
||||
multi_agents::effective_multi_agent_mode(turn_context, step_context)
|
||||
{
|
||||
items.push(ContextualUserFragment::into(
|
||||
MultiAgentModeInstructions::new(multi_agent_mode),
|
||||
));
|
||||
@@ -3516,6 +3545,7 @@ impl Session {
|
||||
&self,
|
||||
turn_context: &TurnContext,
|
||||
world_state: Arc<WorldState>,
|
||||
step_context: &StepContext,
|
||||
) -> u64 {
|
||||
let window = {
|
||||
let mut state = self.state.lock().await;
|
||||
@@ -3523,9 +3553,13 @@ impl Session {
|
||||
};
|
||||
let (window_number, window_ids) = window;
|
||||
let context_items = self
|
||||
.build_initial_context_with_world_state(turn_context, world_state.as_ref())
|
||||
.build_initial_context_with_world_state(
|
||||
turn_context,
|
||||
world_state.as_ref(),
|
||||
step_context,
|
||||
)
|
||||
.await;
|
||||
let turn_context_item = turn_context.to_turn_context_item();
|
||||
let turn_context_item = turn_context.to_turn_context_item(step_context);
|
||||
self.replace_compacted_history(
|
||||
turn_context,
|
||||
context_items,
|
||||
@@ -3573,7 +3607,7 @@ impl Session {
|
||||
let state = self.state.lock().await;
|
||||
state.reference_context_item()
|
||||
};
|
||||
let turn_context_item = turn_context.to_turn_context_item();
|
||||
let turn_context_item = turn_context.to_turn_context_item(step_context);
|
||||
let turn_context_changed = reference_context_item.as_ref() != Some(&turn_context_item);
|
||||
let should_inject_full_context = reference_context_item.is_none();
|
||||
let world_state = Arc::new(self.build_world_state_for_step(step_context).await);
|
||||
@@ -3583,7 +3617,7 @@ impl Session {
|
||||
.build_initial_context_with_world_state_and_mcp(
|
||||
turn_context,
|
||||
world_state.as_ref(),
|
||||
step_context.mcp.as_ref(),
|
||||
step_context,
|
||||
)
|
||||
.await;
|
||||
let snapshot = world_state.snapshot();
|
||||
@@ -3600,7 +3634,11 @@ impl Session {
|
||||
// Steady-state path: append only built-in context diffs here; turn-scoped extension
|
||||
// context is added below.
|
||||
let mut context_items = self
|
||||
.build_settings_update_items(reference_context_item.as_ref(), turn_context)
|
||||
.build_settings_update_items(
|
||||
reference_context_item.as_ref(),
|
||||
turn_context,
|
||||
step_context,
|
||||
)
|
||||
.await;
|
||||
let (world_state_items, world_state_item) = {
|
||||
let mut state = self.state.lock().await;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::config::MultiAgentV2Config;
|
||||
use crate::session::step_context::StepContext;
|
||||
use crate::session::turn_context::TurnContext;
|
||||
use codex_protocol::config_types::MultiAgentMode;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
@@ -36,7 +37,10 @@ fn configured_usage_hint_text_for_source<'a>(
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn effective_multi_agent_mode(turn_context: &TurnContext) -> Option<MultiAgentMode> {
|
||||
pub(crate) fn effective_multi_agent_mode(
|
||||
turn_context: &TurnContext,
|
||||
step_context: &StepContext,
|
||||
) -> Option<MultiAgentMode> {
|
||||
if turn_context.multi_agent_version != MultiAgentVersion::V2 {
|
||||
return None;
|
||||
}
|
||||
@@ -49,7 +53,7 @@ pub(crate) fn effective_multi_agent_mode(turn_context: &TurnContext) -> Option<M
|
||||
.multi_agent_mode_hint_text
|
||||
{
|
||||
Some(hint_text) => MultiAgentMode::Custom(hint_text.clone()),
|
||||
None => match turn_context.effective_reasoning_effort() {
|
||||
None => match step_context.effective_reasoning_effort() {
|
||||
Some(ReasoningEffort::Ultra) => MultiAgentMode::Proactive,
|
||||
_ => MultiAgentMode::ExplicitRequestOnly,
|
||||
},
|
||||
|
||||
@@ -70,7 +70,6 @@ pub(super) async fn spawn_review_thread(
|
||||
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.clone();
|
||||
let reasoning_summary = per_turn_config
|
||||
.model_reasoning_summary
|
||||
.unwrap_or(model_info.default_reasoning_summary);
|
||||
@@ -114,7 +113,6 @@ pub(super) async fn spawn_review_thread(
|
||||
model_info: model_info.clone(),
|
||||
session_telemetry: session_telemetry_for_context,
|
||||
provider: provider_for_context,
|
||||
reasoning_effort,
|
||||
reasoning_summary,
|
||||
session_source,
|
||||
parent_thread_id: parent_turn_context.parent_thread_id,
|
||||
@@ -126,7 +124,10 @@ pub(super) async fn spawn_review_thread(
|
||||
timezone: parent_turn_context.timezone.clone(),
|
||||
app_server_client_name: parent_turn_context.app_server_client_name.clone(),
|
||||
developer_instructions: None,
|
||||
collaboration_mode: parent_turn_context.collaboration_mode.clone(),
|
||||
mode: parent_turn_context.mode,
|
||||
collaboration_mode_developer_instructions: parent_turn_context
|
||||
.collaboration_mode_developer_instructions
|
||||
.clone(),
|
||||
multi_agent_version: MultiAgentVersion::Disabled,
|
||||
personality: parent_turn_context.personality,
|
||||
approval_policy: parent_turn_context.approval_policy.clone(),
|
||||
|
||||
@@ -179,7 +179,7 @@ async fn record_initial_history_resumed_bare_turn_context_does_not_hydrate_previ
|
||||
model: previous_model.to_string(),
|
||||
comp_hash: None,
|
||||
personality: turn_context.personality,
|
||||
collaboration_mode: Some(turn_context.collaboration_mode.clone()),
|
||||
collaboration_mode: Some(turn_context.collaboration_mode()),
|
||||
multi_agent_version: None,
|
||||
multi_agent_mode: None,
|
||||
realtime_active: Some(turn_context.realtime_active),
|
||||
@@ -225,7 +225,7 @@ async fn record_initial_history_resumed_hydrates_previous_turn_settings_from_lif
|
||||
model: previous_model.to_string(),
|
||||
comp_hash: Some("comp-hash-a".to_string()),
|
||||
personality: turn_context.personality,
|
||||
collaboration_mode: Some(turn_context.collaboration_mode.clone()),
|
||||
collaboration_mode: Some(turn_context.collaboration_mode()),
|
||||
multi_agent_version: None,
|
||||
multi_agent_mode: None,
|
||||
realtime_active: Some(turn_context.realtime_active),
|
||||
@@ -1259,7 +1259,7 @@ async fn record_initial_history_resumed_turn_context_after_compaction_reestablis
|
||||
model: previous_model.to_string(),
|
||||
comp_hash: None,
|
||||
personality: turn_context.personality,
|
||||
collaboration_mode: Some(turn_context.collaboration_mode.clone()),
|
||||
collaboration_mode: Some(turn_context.collaboration_mode()),
|
||||
multi_agent_version: None,
|
||||
multi_agent_mode: None,
|
||||
realtime_active: Some(turn_context.realtime_active),
|
||||
@@ -1345,7 +1345,7 @@ async fn record_initial_history_resumed_turn_context_after_compaction_reestablis
|
||||
model: previous_model.to_string(),
|
||||
comp_hash: None,
|
||||
personality: turn_context.personality,
|
||||
collaboration_mode: Some(turn_context.collaboration_mode.clone()),
|
||||
collaboration_mode: Some(turn_context.collaboration_mode()),
|
||||
multi_agent_version: None,
|
||||
multi_agent_mode: None,
|
||||
realtime_active: Some(turn_context.realtime_active),
|
||||
@@ -1376,7 +1376,7 @@ async fn record_initial_history_resumed_aborted_turn_without_id_clears_active_tu
|
||||
model: previous_model.to_string(),
|
||||
comp_hash: None,
|
||||
personality: turn_context.personality,
|
||||
collaboration_mode: Some(turn_context.collaboration_mode.clone()),
|
||||
collaboration_mode: Some(turn_context.collaboration_mode()),
|
||||
multi_agent_version: None,
|
||||
multi_agent_mode: None,
|
||||
realtime_active: Some(turn_context.realtime_active),
|
||||
@@ -1502,7 +1502,7 @@ async fn record_initial_history_resumed_unmatched_abort_preserves_active_turn_fo
|
||||
model: current_model.to_string(),
|
||||
comp_hash: None,
|
||||
personality: turn_context.personality,
|
||||
collaboration_mode: Some(turn_context.collaboration_mode.clone()),
|
||||
collaboration_mode: Some(turn_context.collaboration_mode()),
|
||||
multi_agent_version: None,
|
||||
multi_agent_mode: None,
|
||||
realtime_active: Some(turn_context.realtime_active),
|
||||
@@ -1623,7 +1623,7 @@ async fn record_initial_history_resumed_trailing_incomplete_turn_compaction_clea
|
||||
model: previous_model.to_string(),
|
||||
comp_hash: None,
|
||||
personality: turn_context.personality,
|
||||
collaboration_mode: Some(turn_context.collaboration_mode.clone()),
|
||||
collaboration_mode: Some(turn_context.collaboration_mode()),
|
||||
multi_agent_version: None,
|
||||
multi_agent_mode: None,
|
||||
realtime_active: Some(turn_context.realtime_active),
|
||||
@@ -1790,7 +1790,7 @@ async fn record_initial_history_resumed_replaced_incomplete_compacted_turn_clear
|
||||
model: previous_model.to_string(),
|
||||
comp_hash: None,
|
||||
personality: turn_context.personality,
|
||||
collaboration_mode: Some(turn_context.collaboration_mode.clone()),
|
||||
collaboration_mode: Some(turn_context.collaboration_mode()),
|
||||
multi_agent_version: None,
|
||||
multi_agent_mode: None,
|
||||
realtime_active: Some(turn_context.realtime_active),
|
||||
|
||||
@@ -12,6 +12,7 @@ use tokio::sync::OnceCell;
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct StepContext {
|
||||
pub(crate) turn: Arc<TurnContext>,
|
||||
pub(crate) reasoning_effort: Option<codex_protocol::openai_models::ReasoningEffort>,
|
||||
pub(crate) environments: TurnEnvironmentSnapshot,
|
||||
/// Capability roots bound to ready environments in this exact step.
|
||||
pub(crate) selected_capability_roots: Vec<ResolvedSelectedCapabilityRoot>,
|
||||
@@ -24,6 +25,24 @@ pub(crate) struct StepContext {
|
||||
}
|
||||
|
||||
impl StepContext {
|
||||
pub(crate) fn effective_reasoning_effort(
|
||||
&self,
|
||||
) -> Option<codex_protocol::openai_models::ReasoningEffort> {
|
||||
if self.turn.model_info.supports_reasoning_summaries {
|
||||
self.reasoning_effort
|
||||
.clone()
|
||||
.or_else(|| self.turn.model_info.default_reasoning_level.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn effective_reasoning_effort_for_tracing(&self) -> String {
|
||||
self.effective_reasoning_effort()
|
||||
.map(|effort| effort.to_string())
|
||||
.unwrap_or_else(|| "default".to_string())
|
||||
}
|
||||
|
||||
pub(crate) fn new(
|
||||
turn: Arc<TurnContext>,
|
||||
environments: TurnEnvironmentSnapshot,
|
||||
@@ -31,8 +50,10 @@ impl StepContext {
|
||||
mcp: Arc<McpRuntimeSnapshot>,
|
||||
loaded_agents_md: Option<Arc<LoadedAgentsMd>>,
|
||||
) -> Self {
|
||||
let reasoning_effort = turn.config.model_reasoning_effort.clone();
|
||||
Self {
|
||||
turn,
|
||||
reasoning_effort,
|
||||
environments,
|
||||
selected_capability_roots,
|
||||
mcp,
|
||||
|
||||
@@ -2523,7 +2523,7 @@ async fn turn_start_lifecycle_exposes_turn_metadata_and_token_baseline() {
|
||||
thread_level_id: session.thread_id.to_string(),
|
||||
turn_level_id: turn_context.sub_id.clone(),
|
||||
turn_id: turn_context.sub_id.clone(),
|
||||
collaboration_mode: turn_context.collaboration_mode.clone(),
|
||||
collaboration_mode: turn_context.collaboration_mode(),
|
||||
token_usage_at_turn_start,
|
||||
saw_session_store: true,
|
||||
saw_thread_store: true,
|
||||
@@ -3089,7 +3089,7 @@ async fn record_initial_history_forked_hydrates_previous_turn_settings() {
|
||||
model: previous_model.to_string(),
|
||||
comp_hash: None,
|
||||
personality: turn_context.personality,
|
||||
collaboration_mode: Some(turn_context.collaboration_mode.clone()),
|
||||
collaboration_mode: Some(turn_context.collaboration_mode()),
|
||||
multi_agent_version: None,
|
||||
multi_agent_mode: None,
|
||||
realtime_active: Some(turn_context.realtime_active),
|
||||
|
||||
@@ -166,6 +166,8 @@ pub(crate) async fn run_turn(
|
||||
|
||||
// run_turn owns the step used to seed context and make the first sampling request.
|
||||
let first_step_context = sess.capture_step_context(Arc::clone(&turn_context)).await;
|
||||
sess.set_active_step_context(Arc::clone(&first_step_context))
|
||||
.await;
|
||||
// Keep the exact model-visible state used by this turn and its inline compactions.
|
||||
let (mut world_state, display_roots) = tokio::join!(
|
||||
sess.record_context_updates_and_set_reference_context_item(first_step_context.as_ref()),
|
||||
@@ -204,7 +206,8 @@ pub(crate) async fn run_turn(
|
||||
.await;
|
||||
}
|
||||
|
||||
track_turn_resolved_config_analytics(&sess, &turn_context, &input).await;
|
||||
track_turn_resolved_config_analytics(&sess, &turn_context, &input, first_step_context.clone())
|
||||
.await;
|
||||
|
||||
let mut last_agent_message: Option<String> = None;
|
||||
let mut stop_hook_active = false;
|
||||
@@ -247,7 +250,12 @@ pub(crate) async fn run_turn(
|
||||
// Capture once so context, advertised tools, and tool calls share one request view.
|
||||
let step_context = match next_step_context.take() {
|
||||
Some(step_context) => step_context,
|
||||
None => sess.capture_step_context(Arc::clone(&turn_context)).await,
|
||||
None => {
|
||||
let step_context = sess.capture_step_context(Arc::clone(&turn_context)).await;
|
||||
sess.set_active_step_context(Arc::clone(&step_context))
|
||||
.await;
|
||||
step_context
|
||||
}
|
||||
};
|
||||
let sampling_request_result: CodexResult<_> = async {
|
||||
super::time_reminder::maybe_record_current_time_reminder(
|
||||
@@ -744,6 +752,7 @@ async fn track_turn_resolved_config_analytics(
|
||||
sess: &Session,
|
||||
turn_context: &TurnContext,
|
||||
input: &[TurnInput],
|
||||
first_step_context: Arc<StepContext>,
|
||||
) {
|
||||
let thread_config = {
|
||||
let state = sess.state.lock().await;
|
||||
@@ -777,7 +786,7 @@ async fn track_turn_resolved_config_analytics(
|
||||
permission_profile: turn_context.permission_profile(),
|
||||
#[allow(deprecated)]
|
||||
permission_profile_cwd: turn_context.cwd.to_path_buf(),
|
||||
reasoning_effort: turn_context.reasoning_effort.clone(),
|
||||
reasoning_effort: first_step_context.reasoning_effort.clone(),
|
||||
reasoning_summary: Some(turn_context.reasoning_summary),
|
||||
service_tier: turn_context
|
||||
.config
|
||||
@@ -787,7 +796,7 @@ async fn track_turn_resolved_config_analytics(
|
||||
approval_policy: turn_context.approval_policy.value(),
|
||||
approvals_reviewer: turn_context.config.approvals_reviewer,
|
||||
sandbox_network_access: turn_context.network_sandbox_policy().is_enabled(),
|
||||
collaboration_mode: turn_context.collaboration_mode.mode,
|
||||
collaboration_mode: turn_context.mode,
|
||||
personality: turn_context.personality,
|
||||
workspace_kind: turn_context.turn_metadata_state.workspace_kind(),
|
||||
is_first_turn,
|
||||
@@ -808,6 +817,8 @@ async fn run_pre_sampling_compact(
|
||||
if token_status.token_limit_reached {
|
||||
// Pre-turn compaction runs before run_turn creates the normal sampling step.
|
||||
let step_context = sess.capture_step_context(Arc::clone(turn_context)).await;
|
||||
sess.set_active_step_context(Arc::clone(&step_context))
|
||||
.await;
|
||||
run_auto_compact(
|
||||
sess,
|
||||
step_context,
|
||||
@@ -1020,6 +1031,7 @@ async fn run_auto_compact(
|
||||
run_inline_auto_compact_task(
|
||||
Arc::clone(sess),
|
||||
Arc::clone(turn_context),
|
||||
Arc::clone(&step_context),
|
||||
initial_context_injection,
|
||||
reason,
|
||||
phase,
|
||||
@@ -1158,6 +1170,7 @@ async fn run_sampling_request(
|
||||
tool_runtime.clone(),
|
||||
Arc::clone(&sess),
|
||||
Arc::clone(&turn_context),
|
||||
step_context.clone(),
|
||||
Arc::clone(&turn_store),
|
||||
client_session,
|
||||
responses_metadata,
|
||||
@@ -1928,6 +1941,7 @@ async fn try_run_sampling_request(
|
||||
tool_runtime: ToolCallRuntime,
|
||||
sess: Arc<Session>,
|
||||
turn_context: Arc<TurnContext>,
|
||||
step_context: Arc<StepContext>,
|
||||
turn_store: Arc<codex_extension_api::ExtensionData>,
|
||||
client_session: &mut ModelClientSession,
|
||||
responses_metadata: &CodexResponsesMetadata,
|
||||
@@ -1939,7 +1953,7 @@ async fn try_run_sampling_request(
|
||||
model = turn_context.model_info.slug.clone(),
|
||||
approval_policy = turn_context.approval_policy.value(),
|
||||
sandbox_policy = &turn_context.sandbox_policy(),
|
||||
effort = turn_context.reasoning_effort,
|
||||
effort = step_context.effective_reasoning_effort_for_tracing(),
|
||||
auth_mode = sess.services.auth_manager.auth_mode(),
|
||||
features = sess.features.enabled_features(),
|
||||
);
|
||||
@@ -1959,7 +1973,7 @@ async fn try_run_sampling_request(
|
||||
prompt,
|
||||
&turn_context.model_info,
|
||||
&turn_context.session_telemetry,
|
||||
turn_context.reasoning_effort.clone(),
|
||||
step_context.effective_reasoning_effort(),
|
||||
turn_context.reasoning_summary,
|
||||
turn_context.config.service_tier.clone(),
|
||||
responses_metadata,
|
||||
@@ -1979,8 +1993,8 @@ async fn try_run_sampling_request(
|
||||
)> = None;
|
||||
let mut should_emit_turn_diff = false;
|
||||
let mut should_emit_token_count = false;
|
||||
let reasoning_effort = turn_context.effective_reasoning_effort_for_tracing();
|
||||
let plan_mode = turn_context.collaboration_mode.mode == ModeKind::Plan;
|
||||
let reasoning_effort = step_context.effective_reasoning_effort_for_tracing();
|
||||
let plan_mode = turn_context.mode == ModeKind::Plan;
|
||||
let mut assistant_message_stream_parsers = AssistantMessageStreamParsers::new(plan_mode);
|
||||
let mut plan_mode_state = plan_mode.then(|| PlanModeStreamState::new(&turn_context.sub_id));
|
||||
let defer_streamed_turn_items_for_contributors =
|
||||
|
||||
@@ -108,7 +108,6 @@ pub struct TurnContext {
|
||||
pub(crate) model_info: ModelInfo,
|
||||
pub(crate) session_telemetry: SessionTelemetry,
|
||||
pub(crate) provider: SharedModelProvider,
|
||||
pub(crate) reasoning_effort: Option<ReasoningEffortConfig>,
|
||||
pub(crate) reasoning_summary: ReasoningSummaryConfig,
|
||||
pub(crate) session_source: SessionSource,
|
||||
pub(crate) parent_thread_id: Option<ThreadId>,
|
||||
@@ -123,7 +122,8 @@ pub struct TurnContext {
|
||||
pub(crate) timezone: Option<String>,
|
||||
pub(crate) app_server_client_name: Option<String>,
|
||||
pub(crate) developer_instructions: Option<String>,
|
||||
pub(crate) collaboration_mode: CollaborationMode,
|
||||
pub(crate) mode: ModeKind,
|
||||
pub(crate) collaboration_mode_developer_instructions: Option<String>,
|
||||
pub(crate) multi_agent_version: MultiAgentVersion,
|
||||
pub(crate) personality: Option<Personality>,
|
||||
pub(crate) approval_policy: Constrained<AskForApproval>,
|
||||
@@ -149,6 +149,17 @@ enum TurnMultiAgentRuntime {
|
||||
}
|
||||
|
||||
impl TurnContext {
|
||||
pub(crate) fn collaboration_mode(&self) -> CollaborationMode {
|
||||
CollaborationMode {
|
||||
mode: self.mode,
|
||||
settings: Settings {
|
||||
model: self.model_info.slug.clone(),
|
||||
reasoning_effort: self.config.model_reasoning_effort.clone(),
|
||||
developer_instructions: self.collaboration_mode_developer_instructions.clone(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn permission_profile(&self) -> PermissionProfile {
|
||||
self.permission_profile.clone()
|
||||
}
|
||||
@@ -169,22 +180,6 @@ impl TurnContext {
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn effective_reasoning_effort(&self) -> Option<ReasoningEffortConfig> {
|
||||
if self.model_info.supports_reasoning_summaries {
|
||||
self.reasoning_effort
|
||||
.clone()
|
||||
.or_else(|| self.model_info.default_reasoning_level.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn effective_reasoning_effort_for_tracing(&self) -> String {
|
||||
self.effective_reasoning_effort()
|
||||
.map(|effort| effort.to_string())
|
||||
.unwrap_or_else(|| "default".to_string())
|
||||
}
|
||||
|
||||
pub(crate) fn model_context_window(&self) -> Option<i64> {
|
||||
let effective_context_window_percent = self.model_info.effective_context_window_percent;
|
||||
self.model_info
|
||||
@@ -220,29 +215,24 @@ impl TurnContext {
|
||||
.iter()
|
||||
.map(|preset| preset.effort.clone())
|
||||
.collect::<Vec<_>>();
|
||||
let reasoning_effort = if let Some(current_reasoning_effort) = self.reasoning_effort.clone()
|
||||
{
|
||||
if supported_reasoning_levels.contains(¤t_reasoning_effort) {
|
||||
Some(current_reasoning_effort)
|
||||
let reasoning_effort =
|
||||
if let Some(current_reasoning_effort) = self.config.model_reasoning_effort.clone() {
|
||||
if supported_reasoning_levels.contains(¤t_reasoning_effort) {
|
||||
Some(current_reasoning_effort)
|
||||
} else {
|
||||
supported_reasoning_levels
|
||||
.get(supported_reasoning_levels.len().saturating_sub(1) / 2)
|
||||
.cloned()
|
||||
.or_else(|| model_info.default_reasoning_level.clone())
|
||||
}
|
||||
} else {
|
||||
supported_reasoning_levels
|
||||
.get(supported_reasoning_levels.len().saturating_sub(1) / 2)
|
||||
.cloned()
|
||||
.or_else(|| model_info.default_reasoning_level.clone())
|
||||
}
|
||||
} else {
|
||||
supported_reasoning_levels
|
||||
.get(supported_reasoning_levels.len().saturating_sub(1) / 2)
|
||||
.cloned()
|
||||
.or_else(|| model_info.default_reasoning_level.clone())
|
||||
};
|
||||
};
|
||||
config.model_reasoning_effort = reasoning_effort.clone();
|
||||
|
||||
let collaboration_mode = self.collaboration_mode.with_updates(
|
||||
Some(model.clone()),
|
||||
Some(reasoning_effort.clone()),
|
||||
/*developer_instructions*/ None,
|
||||
);
|
||||
let available_models = models_manager
|
||||
.list_models(RefreshStrategy::OnlineIfUncached)
|
||||
.await;
|
||||
@@ -259,7 +249,6 @@ impl TurnContext {
|
||||
.clone()
|
||||
.with_model(model.as_str(), model_info.slug.as_str()),
|
||||
provider: self.provider.clone(),
|
||||
reasoning_effort,
|
||||
reasoning_summary: self.reasoning_summary,
|
||||
session_source: self.session_source.clone(),
|
||||
parent_thread_id: self.parent_thread_id,
|
||||
@@ -271,7 +260,10 @@ impl TurnContext {
|
||||
timezone: self.timezone.clone(),
|
||||
app_server_client_name: self.app_server_client_name.clone(),
|
||||
developer_instructions: self.developer_instructions.clone(),
|
||||
collaboration_mode,
|
||||
mode: self.mode,
|
||||
collaboration_mode_developer_instructions: self
|
||||
.collaboration_mode_developer_instructions
|
||||
.clone(),
|
||||
multi_agent_version: self.multi_agent_version,
|
||||
personality: self.personality,
|
||||
approval_policy: self.approval_policy.clone(),
|
||||
@@ -350,7 +342,7 @@ impl TurnContext {
|
||||
.then_some(file_system_sandbox_policy)
|
||||
}
|
||||
|
||||
pub(crate) fn to_turn_context_item(&self) -> TurnContextItem {
|
||||
pub(crate) fn to_turn_context_item(&self, step_context: &StepContext) -> TurnContextItem {
|
||||
let workspace_roots = self.config.effective_workspace_roots();
|
||||
#[allow(deprecated)]
|
||||
let cwd = self.cwd.clone();
|
||||
@@ -368,11 +360,18 @@ impl TurnContext {
|
||||
model: self.model_info.slug.clone(),
|
||||
comp_hash: self.model_info.comp_hash.clone(),
|
||||
personality: self.personality,
|
||||
collaboration_mode: Some(self.collaboration_mode.clone()),
|
||||
collaboration_mode: Some(CollaborationMode {
|
||||
mode: self.mode,
|
||||
settings: Settings {
|
||||
model: self.model_info.slug.clone(),
|
||||
reasoning_effort: step_context.reasoning_effort.clone(),
|
||||
developer_instructions: self.collaboration_mode_developer_instructions.clone(),
|
||||
},
|
||||
}),
|
||||
multi_agent_version: Some(self.multi_agent_version),
|
||||
multi_agent_mode: super::multi_agents::effective_multi_agent_mode(self),
|
||||
multi_agent_mode: super::multi_agents::effective_multi_agent_mode(self, step_context),
|
||||
realtime_active: Some(self.realtime_active),
|
||||
effort: self.reasoning_effort.clone(),
|
||||
effort: step_context.effective_reasoning_effort(),
|
||||
summary: ReasoningSummaryConfig::Auto,
|
||||
}
|
||||
}
|
||||
@@ -485,7 +484,7 @@ impl Session {
|
||||
sub_id: String,
|
||||
skills_snapshot: HostSkillsSnapshot,
|
||||
) -> TurnContext {
|
||||
let reasoning_effort = session_configuration.collaboration_mode.reasoning_effort();
|
||||
let collaboration_mode = &session_configuration.collaboration_mode;
|
||||
let reasoning_summary = session_configuration
|
||||
.model_reasoning_summary
|
||||
.unwrap_or(model_info.default_reasoning_summary);
|
||||
@@ -537,7 +536,6 @@ impl Session {
|
||||
model_info,
|
||||
session_telemetry: session_telemetry_for_context,
|
||||
provider: provider_for_context,
|
||||
reasoning_effort,
|
||||
reasoning_summary,
|
||||
session_source,
|
||||
parent_thread_id: session_configuration.parent_thread_id,
|
||||
@@ -549,7 +547,11 @@ impl Session {
|
||||
timezone: Some(timezone),
|
||||
app_server_client_name: session_configuration.app_server_client_name.clone(),
|
||||
developer_instructions: session_configuration.developer_instructions.clone(),
|
||||
collaboration_mode: session_configuration.collaboration_mode.clone(),
|
||||
mode: collaboration_mode.mode,
|
||||
collaboration_mode_developer_instructions: collaboration_mode
|
||||
.settings
|
||||
.developer_instructions
|
||||
.clone(),
|
||||
multi_agent_version,
|
||||
personality: session_configuration.personality,
|
||||
approval_policy: session_configuration.approval_policy.clone(),
|
||||
|
||||
@@ -251,13 +251,21 @@ async fn schedule_startup_prewarm_inner(
|
||||
prewarm_started_at.elapsed(),
|
||||
/*status*/ None,
|
||||
);
|
||||
let step_context = session
|
||||
.capture_step_context(Arc::clone(&startup_turn_context))
|
||||
.await;
|
||||
if routes_approval_to_guardian(&startup_turn_context) {
|
||||
let guardian_session = Arc::clone(&session);
|
||||
let guardian_parent_turn = Arc::clone(&startup_turn_context);
|
||||
let guardian_step_context = Arc::clone(&step_context);
|
||||
drop(tokio::spawn(async move {
|
||||
if let Err(err) = guardian_session
|
||||
.guardian_review_session
|
||||
.initialize(Arc::clone(&guardian_session), guardian_parent_turn)
|
||||
.initialize(
|
||||
Arc::clone(&guardian_session),
|
||||
guardian_parent_turn,
|
||||
guardian_step_context,
|
||||
)
|
||||
.await
|
||||
{
|
||||
warn!("failed to initialize guardian review session: {err:#}");
|
||||
@@ -267,9 +275,6 @@ async fn schedule_startup_prewarm_inner(
|
||||
let startup_cancellation_token = CancellationToken::new();
|
||||
let built_tools_started_at = Instant::now();
|
||||
// Startup prewarm runs before run_turn and needs its own tool-building snapshot.
|
||||
let step_context = session
|
||||
.capture_step_context(Arc::clone(&startup_turn_context))
|
||||
.await;
|
||||
let startup_router = built_tools(
|
||||
session.as_ref(),
|
||||
step_context.as_ref(),
|
||||
@@ -310,7 +315,7 @@ async fn schedule_startup_prewarm_inner(
|
||||
&startup_prompt,
|
||||
&startup_turn_context.model_info,
|
||||
&startup_turn_context.session_telemetry,
|
||||
startup_turn_context.reasoning_effort.clone(),
|
||||
step_context.effective_reasoning_effort(),
|
||||
startup_turn_context.reasoning_summary,
|
||||
startup_turn_context.config.service_tier.clone(),
|
||||
&responses_metadata,
|
||||
|
||||
@@ -20,6 +20,7 @@ use tokio::sync::oneshot;
|
||||
|
||||
use crate::agent::control::AgentExecutionGuard;
|
||||
use crate::session::TurnInputQueue;
|
||||
use crate::session::step_context::StepContext;
|
||||
use crate::session::turn_context::TurnContext;
|
||||
use crate::tasks::AnySessionTask;
|
||||
use codex_protocol::models::AdditionalPermissionProfile;
|
||||
@@ -76,6 +77,7 @@ pub(crate) struct RunningTask {
|
||||
pub(crate) cancellation_token: CancellationToken,
|
||||
pub(crate) handle: AbortOnDropHandle<()>,
|
||||
pub(crate) turn_context: Arc<TurnContext>,
|
||||
pub(crate) step_context: Option<Arc<StepContext>>,
|
||||
pub(crate) turn_extension_data: Arc<ExtensionData>,
|
||||
pub(crate) _agent_execution_guard: Option<AgentExecutionGuard>,
|
||||
// Timer recorded when the task drops to capture the full turn duration.
|
||||
|
||||
@@ -214,7 +214,7 @@ pub(crate) async fn record_completed_response_item_with_finalized_facts(
|
||||
|| {
|
||||
completed_item_defers_mailbox_delivery_to_next_turn(
|
||||
item,
|
||||
turn_context.collaboration_mode.mode == ModeKind::Plan,
|
||||
turn_context.mode == ModeKind::Plan,
|
||||
)
|
||||
},
|
||||
|facts| facts.defers_mailbox_delivery_to_next_turn,
|
||||
@@ -408,7 +408,7 @@ pub(crate) async fn handle_output_item_done(
|
||||
previously_active_item: Option<TurnItem>,
|
||||
) -> Result<OutputItemResult> {
|
||||
let mut output = OutputItemResult::default();
|
||||
let plan_mode = ctx.turn_context.collaboration_mode.mode == ModeKind::Plan;
|
||||
let plan_mode = ctx.turn_context.mode == ModeKind::Plan;
|
||||
|
||||
match ToolRouter::build_tool_call(item.clone()) {
|
||||
// The model emitted a tool call; log it, persist the item immediately, and queue the tool execution.
|
||||
|
||||
@@ -32,8 +32,13 @@ impl SessionTask for CompactTask {
|
||||
_cancellation_token: CancellationToken,
|
||||
) -> SessionTaskResult {
|
||||
let session = session.clone_session();
|
||||
let step_context = session.capture_step_context(Arc::clone(&ctx)).await;
|
||||
session
|
||||
.set_active_step_context(Arc::clone(&step_context))
|
||||
.await;
|
||||
if ctx.config.features.enabled(Feature::TokenBudget) {
|
||||
crate::compact_token_budget::run_manual_compact_task(session, ctx).await?;
|
||||
crate::compact_token_budget::run_manual_compact_task(session, step_context, ctx)
|
||||
.await?;
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
@@ -73,7 +78,7 @@ impl SessionTask for CompactTask {
|
||||
// Compaction prompt is synthesized; no UI element ranges to preserve.
|
||||
text_elements: Vec::new(),
|
||||
}];
|
||||
crate::compact::run_compact_task(session.clone(), ctx, input).await
|
||||
crate::compact::run_compact_task(session.clone(), ctx, step_context, input).await
|
||||
};
|
||||
if let Err(err @ CodexErr::TurnAborted) = result {
|
||||
return Err(err);
|
||||
|
||||
@@ -12,11 +12,12 @@ impl Session {
|
||||
turn_context: &TurnContext,
|
||||
token_usage_at_turn_start: &TokenUsage,
|
||||
) {
|
||||
let collaboration_mode = turn_context.collaboration_mode();
|
||||
for contributor in self.services.extensions.turn_lifecycle_contributors() {
|
||||
contributor
|
||||
.on_turn_start(codex_extension_api::TurnStartInput {
|
||||
turn_id: turn_context.sub_id.as_str(),
|
||||
collaboration_mode: &turn_context.collaboration_mode,
|
||||
collaboration_mode: &collaboration_mode,
|
||||
token_usage_at_turn_start,
|
||||
session_store: &self.services.session_extension_data,
|
||||
thread_store: &self.services.thread_extension_data,
|
||||
|
||||
@@ -383,7 +383,12 @@ impl Session {
|
||||
let task_cancellation_token = cancellation_token.child_token();
|
||||
// Task-owned turn spans keep a core-owned span open for the
|
||||
// full task lifecycle after the submission dispatch span ends.
|
||||
let reasoning_effort = turn_context.effective_reasoning_effort_for_tracing();
|
||||
let reasoning_effort = turn_context
|
||||
.config
|
||||
.model_reasoning_effort
|
||||
.as_ref()
|
||||
.map(ToString::to_string)
|
||||
.unwrap_or_else(|| "default".to_string());
|
||||
let task_span = info_span!(
|
||||
"turn",
|
||||
otel.name = span_name,
|
||||
@@ -443,6 +448,7 @@ impl Session {
|
||||
task,
|
||||
cancellation_token,
|
||||
turn_context: Arc::clone(&turn_context),
|
||||
step_context: None,
|
||||
turn_extension_data,
|
||||
_agent_execution_guard: agent_execution_guard,
|
||||
_timer: timer,
|
||||
|
||||
@@ -52,7 +52,7 @@ impl SessionTask for RegularTask {
|
||||
trace_id: ctx.trace_id.clone(),
|
||||
started_at: ctx.turn_timing_state.started_at_unix_secs().await,
|
||||
model_context_window: ctx.model_context_window(),
|
||||
collaboration_mode_kind: ctx.collaboration_mode.mode,
|
||||
collaboration_mode_kind: ctx.mode,
|
||||
});
|
||||
sess.send_event(ctx.as_ref(), event).await;
|
||||
sess.set_server_reasoning_included(/*included*/ false).await;
|
||||
|
||||
@@ -22,6 +22,7 @@ use crate::codex_delegate::run_codex_thread_one_shot;
|
||||
use crate::config::Constrained;
|
||||
use crate::session::TurnInput;
|
||||
use crate::session::session::Session;
|
||||
use crate::session::step_context::StepContext;
|
||||
use crate::session::turn_context::TurnContext;
|
||||
use crate::state::TaskKind;
|
||||
use codex_features::Feature;
|
||||
@@ -70,11 +71,13 @@ impl SessionTask for ReviewTask {
|
||||
}
|
||||
}
|
||||
|
||||
let step_context = session.session.capture_step_context(Arc::clone(&ctx)).await;
|
||||
// Start sub-codex conversation and get the receiver for events.
|
||||
let output = match start_review_conversation(
|
||||
session.clone(),
|
||||
ctx.clone(),
|
||||
user_input,
|
||||
step_context,
|
||||
cancellation_token.clone(),
|
||||
)
|
||||
.await
|
||||
@@ -97,6 +100,7 @@ async fn start_review_conversation(
|
||||
session: Arc<SessionTaskContext>,
|
||||
ctx: Arc<TurnContext>,
|
||||
input: Vec<UserInput>,
|
||||
step_context: Arc<StepContext>,
|
||||
cancellation_token: CancellationToken,
|
||||
) -> Option<async_channel::Receiver<Event>> {
|
||||
let config = ctx.config.clone();
|
||||
@@ -129,6 +133,7 @@ async fn start_review_conversation(
|
||||
input,
|
||||
session.clone_session(),
|
||||
ctx.clone(),
|
||||
step_context,
|
||||
cancellation_token,
|
||||
SubAgentSource::Review,
|
||||
/*final_output_json_schema*/ None,
|
||||
|
||||
@@ -120,7 +120,7 @@ pub(crate) async fn execute_user_shell_command(
|
||||
trace_id: turn_context.trace_id.clone(),
|
||||
started_at: turn_context.turn_timing_state.started_at_unix_secs().await,
|
||||
model_context_window: turn_context.model_context_window(),
|
||||
collaboration_mode_kind: turn_context.collaboration_mode.mode,
|
||||
collaboration_mode_kind: turn_context.mode,
|
||||
});
|
||||
session.send_event(turn_context.as_ref(), event).await;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ use crate::agent::status::is_final;
|
||||
use crate::config::Config;
|
||||
use crate::function_tool::FunctionCallError;
|
||||
use crate::session::session::Session;
|
||||
use crate::session::step_context::StepContext;
|
||||
use crate::session::turn_context::TurnContext;
|
||||
use crate::tools::handlers::multi_agents::build_agent_spawn_config;
|
||||
use crate::tools::handlers::parse_arguments;
|
||||
@@ -108,6 +109,7 @@ fn required_state_db(
|
||||
async fn build_runner_options(
|
||||
session: &Arc<Session>,
|
||||
turn: &Arc<TurnContext>,
|
||||
step_context: &StepContext,
|
||||
requested_concurrency: Option<usize>,
|
||||
) -> Result<JobRunnerOptions, FunctionCallError> {
|
||||
let multi_agent_version = turn.multi_agent_version;
|
||||
@@ -124,7 +126,7 @@ async fn build_runner_options(
|
||||
}
|
||||
let max_concurrency = normalize_concurrency(requested_concurrency, agent_max_threads);
|
||||
let base_instructions = session.get_base_instructions().await;
|
||||
let spawn_config = build_agent_spawn_config(&base_instructions, turn.as_ref())?;
|
||||
let spawn_config = build_agent_spawn_config(&base_instructions, turn.as_ref(), step_context)?;
|
||||
Ok(JobRunnerOptions {
|
||||
max_concurrency,
|
||||
spawn_config,
|
||||
|
||||
@@ -36,6 +36,7 @@ impl SpawnAgentsOnCsvHandler {
|
||||
let ToolInvocation {
|
||||
session,
|
||||
turn,
|
||||
step_context,
|
||||
payload,
|
||||
..
|
||||
} = invocation;
|
||||
@@ -49,7 +50,7 @@ impl SpawnAgentsOnCsvHandler {
|
||||
}
|
||||
};
|
||||
|
||||
handle(session, turn, arguments)
|
||||
handle(session, turn, step_context, arguments)
|
||||
.await
|
||||
.map(boxed_tool_output)
|
||||
}
|
||||
@@ -69,6 +70,7 @@ impl CoreToolRuntime for SpawnAgentsOnCsvHandler {
|
||||
pub async fn handle(
|
||||
session: Arc<Session>,
|
||||
turn: Arc<TurnContext>,
|
||||
step_context: Arc<StepContext>,
|
||||
arguments: String,
|
||||
) -> Result<FunctionToolOutput, FunctionCallError> {
|
||||
let args: SpawnAgentsOnCsvArgs = parse_arguments(arguments.as_str())?;
|
||||
@@ -182,7 +184,14 @@ pub async fn handle(
|
||||
})?;
|
||||
|
||||
let requested_concurrency = args.max_concurrency.or(args.max_workers);
|
||||
let options = match build_runner_options(&session, &turn, requested_concurrency).await {
|
||||
let options = match build_runner_options(
|
||||
&session,
|
||||
&turn,
|
||||
step_context.as_ref(),
|
||||
requested_concurrency,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(options) => options,
|
||||
Err(err) => {
|
||||
let error_message = err.to_string();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use super::*;
|
||||
use crate::agent::next_thread_spawn_depth;
|
||||
use crate::session::session::Session;
|
||||
use crate::session::step_context::StepContext;
|
||||
use crate::session::turn_context::TurnContext;
|
||||
use crate::tools::handlers::multi_agents_spec::create_resume_agent_tool;
|
||||
use codex_tools::ToolSpec;
|
||||
@@ -35,6 +36,7 @@ async fn handle_resume_agent(
|
||||
let ToolInvocation {
|
||||
session,
|
||||
turn,
|
||||
step_context,
|
||||
payload,
|
||||
call_id,
|
||||
..
|
||||
@@ -88,6 +90,7 @@ async fn handle_resume_agent(
|
||||
match Box::pin(try_resume_closed_agent(
|
||||
&session,
|
||||
&turn,
|
||||
step_context.as_ref(),
|
||||
receiver_thread_id,
|
||||
child_depth,
|
||||
))
|
||||
@@ -188,10 +191,11 @@ impl ToolOutput for ResumeAgentResult {
|
||||
async fn try_resume_closed_agent(
|
||||
session: &Arc<Session>,
|
||||
turn: &Arc<TurnContext>,
|
||||
step_context: &StepContext,
|
||||
receiver_thread_id: ThreadId,
|
||||
child_depth: i32,
|
||||
) -> Result<(), FunctionCallError> {
|
||||
let config = build_agent_resume_config(turn.as_ref())?;
|
||||
let config = build_agent_resume_config(turn.as_ref(), step_context)?;
|
||||
Box::pin(session.services.agent_control.resume_agent_from_rollout(
|
||||
config,
|
||||
receiver_thread_id,
|
||||
|
||||
@@ -34,6 +34,7 @@ impl Handler {
|
||||
let ToolInvocation {
|
||||
session,
|
||||
turn,
|
||||
step_context,
|
||||
payload,
|
||||
call_id,
|
||||
..
|
||||
@@ -48,7 +49,7 @@ impl Handler {
|
||||
.agent_control
|
||||
.get_agent_metadata(receiver_thread_id);
|
||||
if receiver_agent.is_some() {
|
||||
let resume_config = build_agent_resume_config(turn.as_ref())?;
|
||||
let resume_config = build_agent_resume_config(turn.as_ref(), step_context.as_ref())?;
|
||||
session
|
||||
.services
|
||||
.agent_control
|
||||
|
||||
@@ -48,6 +48,7 @@ async fn handle_spawn_agent(
|
||||
let ToolInvocation {
|
||||
session,
|
||||
turn,
|
||||
step_context,
|
||||
payload,
|
||||
call_id,
|
||||
..
|
||||
@@ -86,8 +87,11 @@ async fn handle_spawn_agent(
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
let mut config =
|
||||
build_agent_spawn_config(&session.get_base_instructions().await, turn.as_ref())?;
|
||||
let mut config = build_agent_spawn_config(
|
||||
&session.get_base_instructions().await,
|
||||
turn.as_ref(),
|
||||
step_context.as_ref(),
|
||||
)?;
|
||||
if let Some(service_tier) = args.service_tier.as_ref() {
|
||||
config.service_tier = Some(service_tier.clone());
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ use crate::config::DEFAULT_MULTI_AGENT_V2_MIN_WAIT_TIMEOUT_MS;
|
||||
use crate::config::HARD_MAX_MULTI_AGENT_V2_TIMEOUT_MS;
|
||||
use crate::function_tool::FunctionCallError;
|
||||
use crate::session::session::Session;
|
||||
use crate::session::step_context::StepContext;
|
||||
use crate::session::turn_context::TurnContext;
|
||||
use crate::tools::context::FunctionToolOutput;
|
||||
use crate::tools::context::ToolOutput;
|
||||
@@ -161,28 +162,32 @@ pub(crate) fn parse_collab_input(
|
||||
pub(crate) fn build_agent_spawn_config(
|
||||
base_instructions: &BaseInstructions,
|
||||
turn: &TurnContext,
|
||||
step_context: &StepContext,
|
||||
) -> Result<Config, FunctionCallError> {
|
||||
let mut config = build_agent_shared_config(turn)?;
|
||||
let mut config = build_agent_shared_config(turn, step_context)?;
|
||||
config.base_instructions = Some(base_instructions.text.clone());
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
pub(crate) fn build_agent_resume_config(turn: &TurnContext) -> Result<Config, FunctionCallError> {
|
||||
let mut config = build_agent_shared_config(turn)?;
|
||||
pub(crate) fn build_agent_resume_config(
|
||||
turn: &TurnContext,
|
||||
step_context: &StepContext,
|
||||
) -> Result<Config, FunctionCallError> {
|
||||
let mut config = build_agent_shared_config(turn, step_context)?;
|
||||
// For resume, keep base instructions sourced from rollout/session metadata.
|
||||
config.base_instructions = None;
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
fn build_agent_shared_config(turn: &TurnContext) -> Result<Config, FunctionCallError> {
|
||||
fn build_agent_shared_config(
|
||||
turn: &TurnContext,
|
||||
step_context: &StepContext,
|
||||
) -> Result<Config, FunctionCallError> {
|
||||
let base_config = turn.config.clone();
|
||||
let mut config = (*base_config).clone();
|
||||
config.model = Some(turn.model_info.slug.clone());
|
||||
config.model_provider = turn.provider.info().clone();
|
||||
config.model_reasoning_effort = turn
|
||||
.reasoning_effort
|
||||
.clone()
|
||||
.or_else(|| turn.model_info.default_reasoning_level.clone());
|
||||
config.model_reasoning_effort = step_context.effective_reasoning_effort().clone();
|
||||
config.model_reasoning_summary = Some(turn.reasoning_summary);
|
||||
config.developer_instructions = turn.developer_instructions.clone();
|
||||
apply_spawn_agent_runtime_overrides(&mut config, turn)?;
|
||||
|
||||
@@ -67,6 +67,7 @@ pub(crate) async fn handle_message_string_tool(
|
||||
let ToolInvocation {
|
||||
session,
|
||||
turn,
|
||||
step_context,
|
||||
call_id,
|
||||
..
|
||||
} = invocation;
|
||||
@@ -89,7 +90,7 @@ pub(crate) async fn handle_message_string_tool(
|
||||
let receiver_agent_path = receiver_agent.agent_path.clone().ok_or_else(|| {
|
||||
FunctionCallError::RespondToModel("target agent is missing an agent_path".to_string())
|
||||
})?;
|
||||
let resume_config = build_agent_resume_config(turn.as_ref())?;
|
||||
let resume_config = build_agent_resume_config(turn.as_ref(), step_context.as_ref())?;
|
||||
session
|
||||
.services
|
||||
.agent_control
|
||||
|
||||
@@ -43,6 +43,7 @@ async fn handle_spawn_agent(
|
||||
let ToolInvocation {
|
||||
session,
|
||||
turn,
|
||||
step_context,
|
||||
payload,
|
||||
call_id,
|
||||
..
|
||||
@@ -59,8 +60,11 @@ async fn handle_spawn_agent(
|
||||
let message = message_content(args.message)?;
|
||||
let session_source = turn.session_source.clone();
|
||||
let child_depth = next_thread_spawn_depth(&session_source);
|
||||
let mut config =
|
||||
build_agent_spawn_config(&session.get_base_instructions().await, turn.as_ref())?;
|
||||
let mut config = build_agent_spawn_config(
|
||||
&session.get_base_instructions().await,
|
||||
turn.as_ref(),
|
||||
step_context.as_ref(),
|
||||
)?;
|
||||
if let Some(service_tier) = args.service_tier.as_ref() {
|
||||
config.service_tier = Some(service_tier.clone());
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ impl PlanHandler {
|
||||
}
|
||||
};
|
||||
|
||||
if turn.collaboration_mode.mode == ModeKind::Plan {
|
||||
if turn.mode == ModeKind::Plan {
|
||||
return Err(FunctionCallError::RespondToModel(
|
||||
"update_plan is a TODO/checklist tool and is not allowed in Plan mode".to_string(),
|
||||
));
|
||||
|
||||
@@ -95,6 +95,7 @@ impl RequestPermissionsHandler {
|
||||
let response = session
|
||||
.request_permissions_for_environment(
|
||||
&turn,
|
||||
&step_context,
|
||||
call_id,
|
||||
args,
|
||||
turn_environment.selection(),
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
use crate::sandboxing::ExecOptions;
|
||||
use crate::sandboxing::SandboxPermissions;
|
||||
use crate::session::session::Session;
|
||||
use crate::session::step_context::StepContext;
|
||||
use crate::session::turn_context::TurnContext;
|
||||
use crate::state::SessionServices;
|
||||
use crate::tools::hook_names::HookToolName;
|
||||
@@ -384,6 +385,7 @@ pub(crate) trait Sandboxable {
|
||||
pub(crate) struct ToolCtx {
|
||||
pub session: Arc<Session>,
|
||||
pub turn: Arc<TurnContext>,
|
||||
pub step_context: Arc<StepContext>,
|
||||
pub call_id: String,
|
||||
pub tool_name: ToolName,
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
set working-directory := "codex-rs"
|
||||
set positional-arguments
|
||||
set positional-arguments := true
|
||||
|
||||
export JUST_SHELL := justfile_directory() / "scripts/just-shell.py"
|
||||
|
||||
set shell := ["python3", "-c", 'import os, runpy; runpy.run_path(os.environ["JUST_SHELL"], run_name="__main__")']
|
||||
set windows-shell := ["python", "-c", 'import os, runpy; runpy.run_path(os.environ["JUST_SHELL"], run_name="__main__")']
|
||||
|
||||
rust_min_stack := "8388608" # 8 MiB
|
||||
rust_min_stack := "8388608"
|
||||
python := if os_family() == "windows" { "python" } else { "python3" }
|
||||
|
||||
# Display help
|
||||
@@ -12,7 +14,9 @@ help:
|
||||
just -l
|
||||
|
||||
# `codex`
|
||||
|
||||
alias c := codex
|
||||
|
||||
codex *args:
|
||||
cargo run --bin codex -- {args}
|
||||
|
||||
@@ -76,6 +80,7 @@ install:
|
||||
#
|
||||
# Run `cargo install --locked cargo-nextest` if you don't have it installed.
|
||||
# Prefer this for routine local runs. Workspace crate features are banned, so
|
||||
|
||||
# there should be no need to add `--all-features`.
|
||||
[unix]
|
||||
test *args:
|
||||
@@ -86,6 +91,7 @@ test *args:
|
||||
$env:RUST_MIN_STACK = "{{ rust_min_stack }}"; $env:NEXTEST_PROFILE = "local"; cargo nextest run --no-fail-fast @($args | Select-Object -Skip 1)
|
||||
|
||||
# Run from the repository root so scripts that resolve paths from `cwd` see
|
||||
|
||||
# the same layout they use in GitHub Actions.
|
||||
[no-cd]
|
||||
test-github-scripts:
|
||||
@@ -101,6 +107,7 @@ bench-smoke:
|
||||
|
||||
# Build and run Codex from source using Bazel.
|
||||
# On Unix, use `[no-cd]` and `--run_under="cd $PWD &&"` to ensure Bazel runs
|
||||
|
||||
# the command in the current working directory.
|
||||
[no-cd]
|
||||
[unix]
|
||||
|
||||
Reference in New Issue
Block a user