mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
[5 of 7] Replace OverrideTurnContext with ThreadSettings (#22508)
**Stack position:** [5 of 7] ## Summary This PR adds `Op::ThreadSettings`, a queued settings-only update mechanism for changing stored thread settings without starting a new turn. It also removes the legacy `Op::OverrideTurnContext` in the same layer, so reviewers can see the replacement and deletion together. ## Changes - Add `Op::ThreadSettings` for settings-only queued updates. - Emit `ThreadSettingsApplied` with the effective thread settings snapshot after core applies an update. - Route settings-only updates through the same submission queue as user input. - Migrate remaining `OverrideTurnContext` tests and callers to the queued `Op::ThreadSettings` path. - Delete `Op::OverrideTurnContext` from the core protocol and submission loop. This stack addresses #20656 and #22090. ## Stack 1. [1 of 7] [Add thread settings to UserInput](https://github.com/openai/codex/pull/23080) 2. [2 of 7] [Remove UserInputWithTurnContext](https://github.com/openai/codex/pull/23081) 3. [3 of 7] [Remove UserTurn](https://github.com/openai/codex/pull/23075) 4. [4 of 7] [Placeholder for OverrideTurnContext cleanup](https://github.com/openai/codex/pull/23087) 5. [5 of 7] [Replace OverrideTurnContext with ThreadSettings](https://github.com/openai/codex/pull/22508) (this PR) 6. [6 of 7] [Add app-server thread settings API](https://github.com/openai/codex/pull/22509) 7. [7 of 7] [Sync TUI thread settings](https://github.com/openai/codex/pull/22510)
This commit is contained in:
@@ -63,7 +63,9 @@ pub struct ThreadConfigSnapshot {
|
||||
pub profile_workspace_roots: Vec<AbsolutePathBuf>,
|
||||
pub ephemeral: bool,
|
||||
pub reasoning_effort: Option<ReasoningEffort>,
|
||||
pub reasoning_summary: Option<ReasoningSummary>,
|
||||
pub personality: Option<Personality>,
|
||||
pub collaboration_mode: CollaborationMode,
|
||||
pub session_source: SessionSource,
|
||||
pub thread_source: Option<ThreadSource>,
|
||||
}
|
||||
@@ -257,11 +259,19 @@ impl CodexThread {
|
||||
.await
|
||||
}
|
||||
|
||||
/// Validate persistent thread settings overrides without committing them.
|
||||
pub async fn validate_thread_settings_overrides(
|
||||
/// Preview persistent thread settings overrides without committing them.
|
||||
pub async fn preview_thread_settings_overrides(
|
||||
&self,
|
||||
overrides: CodexThreadSettingsOverrides,
|
||||
) -> ConstraintResult<()> {
|
||||
) -> ConstraintResult<ThreadConfigSnapshot> {
|
||||
let updates = self.thread_settings_update(overrides).await;
|
||||
self.codex.session.preview_settings(&updates).await
|
||||
}
|
||||
|
||||
async fn thread_settings_update(
|
||||
&self,
|
||||
overrides: CodexThreadSettingsOverrides,
|
||||
) -> SessionSettingsUpdate {
|
||||
let CodexThreadSettingsOverrides {
|
||||
cwd,
|
||||
workspace_roots,
|
||||
@@ -289,7 +299,7 @@ impl CodexThread {
|
||||
.with_updates(model, effort, /*developer_instructions*/ None)
|
||||
};
|
||||
|
||||
let updates = SessionSettingsUpdate {
|
||||
SessionSettingsUpdate {
|
||||
cwd,
|
||||
workspace_roots,
|
||||
profile_workspace_roots,
|
||||
@@ -304,8 +314,7 @@ impl CodexThread {
|
||||
service_tier,
|
||||
personality,
|
||||
..Default::default()
|
||||
};
|
||||
self.codex.session.validate_settings(&updates).await
|
||||
}
|
||||
}
|
||||
|
||||
/// Use sparingly: this is intended to be removed soon.
|
||||
|
||||
@@ -42,7 +42,9 @@ use codex_protocol::protocol::ReviewRequest;
|
||||
use codex_protocol::protocol::RolloutItem;
|
||||
use codex_protocol::protocol::ThreadMemoryMode;
|
||||
use codex_protocol::protocol::ThreadRolledBackEvent;
|
||||
use codex_protocol::protocol::ThreadSettingsAppliedEvent;
|
||||
use codex_protocol::protocol::ThreadSettingsOverrides;
|
||||
use codex_protocol::protocol::ThreadSettingsSnapshot;
|
||||
use codex_protocol::protocol::TurnAbortReason;
|
||||
use codex_protocol::protocol::WarningEvent;
|
||||
use codex_protocol::request_permissions::RequestPermissionsResponse;
|
||||
@@ -81,19 +83,6 @@ pub async fn realtime_conversation_list_voices(sess: &Session, sub_id: String) {
|
||||
.await;
|
||||
}
|
||||
|
||||
pub async fn override_turn_context(sess: &Session, sub_id: String, updates: SessionSettingsUpdate) {
|
||||
if let Err(err) = sess.update_settings(updates).await {
|
||||
sess.send_event_raw(Event {
|
||||
id: sub_id,
|
||||
msg: EventMsg::Error(ErrorEvent {
|
||||
message: err.to_string(),
|
||||
codex_error_info: Some(CodexErrorInfo::BadRequest),
|
||||
}),
|
||||
})
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn user_input_or_turn(sess: &Arc<Session>, sub_id: String, op: Op) {
|
||||
user_input_or_turn_inner(
|
||||
sess,
|
||||
@@ -104,36 +93,132 @@ pub async fn user_input_or_turn(sess: &Arc<Session>, sub_id: String, op: Op) {
|
||||
.await;
|
||||
}
|
||||
|
||||
pub async fn update_thread_settings(
|
||||
sess: &Arc<Session>,
|
||||
sub_id: String,
|
||||
thread_settings: ThreadSettingsOverrides,
|
||||
) {
|
||||
let updates = thread_settings_update(sess, thread_settings).await;
|
||||
let msg = match sess.update_settings(updates).await {
|
||||
Ok(()) => thread_settings_applied_event(sess).await,
|
||||
Err(err) => EventMsg::Error(ErrorEvent {
|
||||
message: format!("invalid thread settings override: {err}"),
|
||||
codex_error_info: Some(CodexErrorInfo::BadRequest),
|
||||
}),
|
||||
};
|
||||
sess.send_event_raw(Event { id: sub_id, msg }).await;
|
||||
}
|
||||
|
||||
async fn thread_settings_update(
|
||||
sess: &Session,
|
||||
thread_settings: ThreadSettingsOverrides,
|
||||
) -> SessionSettingsUpdate {
|
||||
let ThreadSettingsOverrides {
|
||||
cwd,
|
||||
workspace_roots,
|
||||
profile_workspace_roots,
|
||||
approval_policy,
|
||||
approvals_reviewer,
|
||||
sandbox_policy,
|
||||
permission_profile,
|
||||
active_permission_profile,
|
||||
windows_sandbox_level,
|
||||
model,
|
||||
effort,
|
||||
summary,
|
||||
service_tier,
|
||||
collaboration_mode,
|
||||
personality,
|
||||
} = thread_settings;
|
||||
let collaboration_mode = match collaboration_mode {
|
||||
Some(collaboration_mode) => collaboration_mode,
|
||||
None => {
|
||||
let state = sess.state.lock().await;
|
||||
// Model and reasoning effort live in CollaborationMode settings today, so
|
||||
// partial thread-settings updates refresh those fields on the active mode.
|
||||
state
|
||||
.session_configuration
|
||||
.collaboration_mode
|
||||
.with_updates(model, effort, /*developer_instructions*/ None)
|
||||
}
|
||||
};
|
||||
SessionSettingsUpdate {
|
||||
cwd,
|
||||
workspace_roots,
|
||||
profile_workspace_roots,
|
||||
approval_policy,
|
||||
approvals_reviewer,
|
||||
sandbox_policy,
|
||||
permission_profile,
|
||||
active_permission_profile,
|
||||
windows_sandbox_level,
|
||||
collaboration_mode: Some(collaboration_mode),
|
||||
reasoning_summary: summary,
|
||||
service_tier,
|
||||
personality,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
async fn thread_settings_applied_event(sess: &Session) -> EventMsg {
|
||||
let snapshot = {
|
||||
let state = sess.state.lock().await;
|
||||
state.session_configuration.thread_config_snapshot()
|
||||
};
|
||||
EventMsg::ThreadSettingsApplied(ThreadSettingsAppliedEvent {
|
||||
thread_settings: ThreadSettingsSnapshot {
|
||||
model: snapshot.model,
|
||||
model_provider_id: snapshot.model_provider_id,
|
||||
service_tier: snapshot.service_tier,
|
||||
approval_policy: snapshot.approval_policy,
|
||||
approvals_reviewer: snapshot.approvals_reviewer,
|
||||
permission_profile: snapshot.permission_profile,
|
||||
active_permission_profile: snapshot.active_permission_profile,
|
||||
cwd: snapshot.cwd,
|
||||
reasoning_effort: snapshot.reasoning_effort,
|
||||
reasoning_summary: snapshot.reasoning_summary,
|
||||
personality: snapshot.personality,
|
||||
collaboration_mode: snapshot.collaboration_mode,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) async fn user_input_or_turn_inner(
|
||||
sess: &Arc<Session>,
|
||||
sub_id: String,
|
||||
op: Op,
|
||||
mirror_user_text_to_realtime: Option<()>,
|
||||
) {
|
||||
let (items, updates, responsesapi_client_metadata) = match op {
|
||||
Op::UserInput {
|
||||
items,
|
||||
environments,
|
||||
final_output_json_schema,
|
||||
responsesapi_client_metadata,
|
||||
thread_settings,
|
||||
} => {
|
||||
let mut updates = if thread_settings == ThreadSettingsOverrides::default() {
|
||||
SessionSettingsUpdate::default()
|
||||
} else {
|
||||
thread_settings_update(sess, thread_settings).await
|
||||
};
|
||||
updates.final_output_json_schema = Some(final_output_json_schema);
|
||||
updates.environments = environments;
|
||||
(items, updates, responsesapi_client_metadata)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
let Op::UserInput {
|
||||
items,
|
||||
environments,
|
||||
final_output_json_schema,
|
||||
responsesapi_client_metadata,
|
||||
thread_settings,
|
||||
} = op
|
||||
else {
|
||||
unreachable!();
|
||||
};
|
||||
let emit_thread_settings_applied = thread_settings != ThreadSettingsOverrides::default();
|
||||
let mut updates = if emit_thread_settings_applied {
|
||||
thread_settings_update(sess, thread_settings).await
|
||||
} else {
|
||||
SessionSettingsUpdate::default()
|
||||
};
|
||||
updates.final_output_json_schema = Some(final_output_json_schema);
|
||||
updates.environments = environments;
|
||||
|
||||
let Ok(current_context) = sess.new_turn_with_sub_id(sub_id.clone(), updates).await else {
|
||||
// new_turn_with_sub_id already emits the error event.
|
||||
return;
|
||||
};
|
||||
if emit_thread_settings_applied {
|
||||
sess.send_event_raw(Event {
|
||||
id: sub_id.clone(),
|
||||
msg: thread_settings_applied_event(sess).await,
|
||||
})
|
||||
.await;
|
||||
}
|
||||
sess.maybe_emit_unknown_model_warning_for_turn(current_context.as_ref())
|
||||
.await;
|
||||
let accepted_items = match sess
|
||||
@@ -183,56 +268,6 @@ pub(super) async fn user_input_or_turn_inner(
|
||||
}
|
||||
}
|
||||
|
||||
async fn thread_settings_update(
|
||||
sess: &Session,
|
||||
thread_settings: ThreadSettingsOverrides,
|
||||
) -> SessionSettingsUpdate {
|
||||
let ThreadSettingsOverrides {
|
||||
cwd,
|
||||
workspace_roots,
|
||||
profile_workspace_roots,
|
||||
approval_policy,
|
||||
approvals_reviewer,
|
||||
sandbox_policy,
|
||||
permission_profile,
|
||||
active_permission_profile,
|
||||
windows_sandbox_level,
|
||||
model,
|
||||
effort,
|
||||
summary,
|
||||
service_tier,
|
||||
collaboration_mode,
|
||||
personality,
|
||||
} = thread_settings;
|
||||
let collaboration_mode = if let Some(collaboration_mode) = collaboration_mode {
|
||||
collaboration_mode
|
||||
} else {
|
||||
let state = sess.state.lock().await;
|
||||
// Model and reasoning effort live in CollaborationMode settings today, so
|
||||
// partial thread-settings updates refresh those fields on the active mode.
|
||||
state
|
||||
.session_configuration
|
||||
.collaboration_mode
|
||||
.with_updates(model, effort, /*developer_instructions*/ None)
|
||||
};
|
||||
SessionSettingsUpdate {
|
||||
cwd,
|
||||
workspace_roots,
|
||||
profile_workspace_roots,
|
||||
approval_policy,
|
||||
approvals_reviewer,
|
||||
sandbox_policy,
|
||||
permission_profile,
|
||||
active_permission_profile,
|
||||
windows_sandbox_level,
|
||||
collaboration_mode: Some(collaboration_mode),
|
||||
reasoning_summary: summary,
|
||||
service_tier,
|
||||
personality,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
async fn mirror_user_text_to_realtime(sess: &Arc<Session>, items: &[UserInput]) {
|
||||
let text = UserMessageItem::new(items).message();
|
||||
if text.is_empty() {
|
||||
@@ -729,54 +764,14 @@ pub(super) async fn submission_loop(
|
||||
realtime_conversation_list_voices(&sess, sub.id.clone()).await;
|
||||
false
|
||||
}
|
||||
Op::OverrideTurnContext {
|
||||
cwd,
|
||||
approval_policy,
|
||||
approvals_reviewer,
|
||||
sandbox_policy,
|
||||
permission_profile,
|
||||
windows_sandbox_level,
|
||||
model,
|
||||
effort,
|
||||
summary,
|
||||
service_tier,
|
||||
collaboration_mode,
|
||||
personality,
|
||||
} => {
|
||||
let collaboration_mode = if let Some(collab_mode) = collaboration_mode {
|
||||
collab_mode
|
||||
} else {
|
||||
let state = sess.state.lock().await;
|
||||
state.session_configuration.collaboration_mode.with_updates(
|
||||
model.clone(),
|
||||
effort,
|
||||
/*developer_instructions*/ None,
|
||||
)
|
||||
};
|
||||
override_turn_context(
|
||||
&sess,
|
||||
sub.id.clone(),
|
||||
SessionSettingsUpdate {
|
||||
cwd,
|
||||
approval_policy,
|
||||
approvals_reviewer,
|
||||
sandbox_policy,
|
||||
permission_profile,
|
||||
windows_sandbox_level,
|
||||
collaboration_mode: Some(collaboration_mode),
|
||||
reasoning_summary: summary,
|
||||
service_tier,
|
||||
personality,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.await;
|
||||
false
|
||||
}
|
||||
Op::UserInput { .. } => {
|
||||
user_input_or_turn(&sess, sub.id.clone(), sub.op).await;
|
||||
false
|
||||
}
|
||||
Op::ThreadSettings { thread_settings } => {
|
||||
update_thread_settings(&sess, sub.id.clone(), thread_settings).await;
|
||||
false
|
||||
}
|
||||
Op::InterAgentCommunication { communication } => {
|
||||
inter_agent_communication(&sess, sub.id.clone(), communication).await;
|
||||
false
|
||||
|
||||
@@ -1384,12 +1384,15 @@ impl Session {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn validate_settings(
|
||||
pub(crate) async fn preview_settings(
|
||||
&self,
|
||||
updates: &SessionSettingsUpdate,
|
||||
) -> ConstraintResult<()> {
|
||||
) -> ConstraintResult<ThreadConfigSnapshot> {
|
||||
let state = self.state.lock().await;
|
||||
state.session_configuration.apply(updates).map(|_| ())
|
||||
state
|
||||
.session_configuration
|
||||
.apply(updates)
|
||||
.map(|configuration| configuration.thread_config_snapshot())
|
||||
}
|
||||
|
||||
pub(crate) async fn set_session_startup_prewarm(
|
||||
|
||||
@@ -178,7 +178,9 @@ impl SessionConfiguration {
|
||||
profile_workspace_roots: self.profile_workspace_roots().to_vec(),
|
||||
ephemeral: self.original_config_do_not_use.ephemeral,
|
||||
reasoning_effort: self.collaboration_mode.reasoning_effort(),
|
||||
reasoning_summary: self.model_reasoning_summary,
|
||||
personality: self.personality,
|
||||
collaboration_mode: self.collaboration_mode.clone(),
|
||||
session_source: self.session_source.clone(),
|
||||
thread_source: self.thread_source,
|
||||
}
|
||||
|
||||
@@ -118,6 +118,7 @@ use codex_protocol::protocol::SkillScope;
|
||||
use codex_protocol::protocol::Submission;
|
||||
use codex_protocol::protocol::ThreadGoalStatus;
|
||||
use codex_protocol::protocol::ThreadRolledBackEvent;
|
||||
use codex_protocol::protocol::ThreadSettingsOverrides;
|
||||
use codex_protocol::protocol::TokenCountEvent;
|
||||
use codex_protocol::protocol::TokenUsage;
|
||||
use codex_protocol::protocol::TokenUsageInfo;
|
||||
@@ -2257,24 +2258,6 @@ async fn fork_startup_context_then_first_turn_diff_snapshot() -> anyhow::Result<
|
||||
developer_instructions: Some("Fork turn collaboration instructions.".to_string()),
|
||||
},
|
||||
};
|
||||
forked
|
||||
.thread
|
||||
.submit(Op::OverrideTurnContext {
|
||||
cwd: None,
|
||||
approval_policy: Some(AskForApproval::Never),
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: None,
|
||||
permission_profile: None,
|
||||
windows_sandbox_level: None,
|
||||
model: None,
|
||||
effort: None,
|
||||
summary: None,
|
||||
service_tier: None,
|
||||
collaboration_mode: Some(collaboration_mode),
|
||||
personality: None,
|
||||
})
|
||||
.await?;
|
||||
|
||||
forked
|
||||
.thread
|
||||
.submit(Op::UserInput {
|
||||
@@ -2285,7 +2268,11 @@ async fn fork_startup_context_then_first_turn_diff_snapshot() -> anyhow::Result<
|
||||
}],
|
||||
final_output_json_schema: None,
|
||||
responsesapi_client_metadata: None,
|
||||
thread_settings: Default::default(),
|
||||
thread_settings: ThreadSettingsOverrides {
|
||||
approval_policy: Some(AskForApproval::Never),
|
||||
collaboration_mode: Some(collaboration_mode),
|
||||
..Default::default()
|
||||
},
|
||||
})
|
||||
.await?;
|
||||
wait_for_event(&forked.thread, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
|
||||
@@ -2338,7 +2325,7 @@ async fn record_initial_history_forked_hydrates_previous_turn_settings() {
|
||||
let turn_id = previous_context_item
|
||||
.turn_id
|
||||
.clone()
|
||||
.expect("turn context should have turn_id");
|
||||
.expect("thread settings should have turn_id");
|
||||
let rollout_items = vec![
|
||||
RolloutItem::EventMsg(EventMsg::TurnStarted(
|
||||
codex_protocol::protocol::TurnStartedEvent {
|
||||
@@ -2521,14 +2508,14 @@ async fn thread_rollback_recomputes_previous_turn_settings_and_reference_context
|
||||
let first_turn_id = first_context_item
|
||||
.turn_id
|
||||
.clone()
|
||||
.expect("turn context should have turn_id");
|
||||
.expect("thread settings should have turn_id");
|
||||
let mut rolled_back_context_item = first_context_item.clone();
|
||||
rolled_back_context_item.turn_id = Some("rolled-back-turn".to_string());
|
||||
rolled_back_context_item.model = "rolled-back-model".to_string();
|
||||
let rolled_back_turn_id = rolled_back_context_item
|
||||
.turn_id
|
||||
.clone()
|
||||
.expect("turn context should have turn_id");
|
||||
.expect("thread settings should have turn_id");
|
||||
let turn_one_user = user_message("turn 1 user");
|
||||
let turn_one_assistant = assistant_message("turn 1 assistant");
|
||||
let turn_two_user = user_message("turn 2 user");
|
||||
@@ -2637,7 +2624,7 @@ async fn thread_rollback_restores_cleared_reference_context_item_after_compactio
|
||||
let first_turn_id = first_context_item
|
||||
.turn_id
|
||||
.clone()
|
||||
.expect("turn context should have turn_id");
|
||||
.expect("thread settings should have turn_id");
|
||||
let compact_turn_id = "compact-turn".to_string();
|
||||
let rolled_back_turn_id = "rolled-back-turn".to_string();
|
||||
let compacted_history = vec![
|
||||
@@ -4833,7 +4820,7 @@ async fn request_permissions_emits_event_when_granular_policy_allows_requests()
|
||||
let (session, mut turn_context, rx) = make_session_and_context_with_rx().await;
|
||||
*session.active_turn.lock().await = Some(ActiveTurn::default());
|
||||
Arc::get_mut(&mut turn_context)
|
||||
.expect("single turn context ref")
|
||||
.expect("single thread settings ref")
|
||||
.approval_policy
|
||||
.set(AskForApproval::Granular(GranularApprovalConfig {
|
||||
sandbox_approval: true,
|
||||
@@ -4911,7 +4898,7 @@ async fn request_permissions_response_materializes_session_cwd_grants_before_rec
|
||||
let (session, mut turn_context, rx) = make_session_and_context_with_rx().await;
|
||||
*session.active_turn.lock().await = Some(ActiveTurn::default());
|
||||
Arc::get_mut(&mut turn_context)
|
||||
.expect("single turn context ref")
|
||||
.expect("single thread settings ref")
|
||||
.approval_policy
|
||||
.set(AskForApproval::Granular(GranularApprovalConfig {
|
||||
sandbox_approval: true,
|
||||
@@ -5008,7 +4995,7 @@ async fn request_permissions_is_auto_denied_when_granular_policy_blocks_tool_req
|
||||
let (session, mut turn_context, rx) = make_session_and_context_with_rx().await;
|
||||
*session.active_turn.lock().await = Some(ActiveTurn::default());
|
||||
Arc::get_mut(&mut turn_context)
|
||||
.expect("single turn context ref")
|
||||
.expect("single thread settings ref")
|
||||
.approval_policy
|
||||
.set(AskForApproval::Granular(GranularApprovalConfig {
|
||||
sandbox_approval: true,
|
||||
@@ -5198,24 +5185,6 @@ fn submission_dispatch_span_uses_debug_for_realtime_audio() {
|
||||
|
||||
#[test]
|
||||
fn op_kind_for_input_and_context_ops() {
|
||||
assert_eq!(
|
||||
Op::OverrideTurnContext {
|
||||
cwd: None,
|
||||
approval_policy: None,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: None,
|
||||
permission_profile: None,
|
||||
windows_sandbox_level: None,
|
||||
model: None,
|
||||
effort: None,
|
||||
summary: None,
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
}
|
||||
.kind(),
|
||||
"override_turn_context"
|
||||
);
|
||||
assert_eq!(
|
||||
Op::UserInput {
|
||||
environments: None,
|
||||
@@ -5227,6 +5196,13 @@ fn op_kind_for_input_and_context_ops() {
|
||||
.kind(),
|
||||
"user_input"
|
||||
);
|
||||
assert_eq!(
|
||||
Op::ThreadSettings {
|
||||
thread_settings: ThreadSettingsOverrides::default(),
|
||||
}
|
||||
.kind(),
|
||||
"thread_settings"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -6798,7 +6774,7 @@ async fn build_initial_context_adds_multi_agent_v2_subagent_usage_hint_as_develo
|
||||
.session_configuration
|
||||
.session_source = session_source.clone();
|
||||
Arc::get_mut(&mut turn_context)
|
||||
.expect("turn context should not be shared")
|
||||
.expect("thread settings should not be shared")
|
||||
.session_source = session_source;
|
||||
|
||||
let initial_context = session.build_initial_context(turn_context.as_ref()).await;
|
||||
@@ -7064,7 +7040,7 @@ fn emit_thread_start_skill_metrics_records_description_truncated_chars_without_o
|
||||
#[tokio::test]
|
||||
async fn build_initial_context_emits_thread_start_skill_warning_on_repeated_builds() {
|
||||
let (session, turn_context, rx) = make_session_and_context_with_rx().await;
|
||||
let mut turn_context = Arc::into_inner(turn_context).expect("sole turn context owner");
|
||||
let mut turn_context = Arc::into_inner(turn_context).expect("sole thread settings owner");
|
||||
let mut outcome = SkillLoadOutcome::default();
|
||||
outcome.skills = vec![
|
||||
SkillMetadata {
|
||||
@@ -9890,7 +9866,7 @@ async fn rejects_escalated_permissions_when_policy_not_on_request() {
|
||||
// The rejection should not poison the non-escalated path for the same
|
||||
// command. Force DangerFullAccess so this check stays focused on approval
|
||||
// policy rather than platform-specific sandbox behavior.
|
||||
let turn_context_mut = Arc::get_mut(&mut turn_context).expect("unique turn context Arc");
|
||||
let turn_context_mut = Arc::get_mut(&mut turn_context).expect("unique thread settings Arc");
|
||||
turn_context_mut.permission_profile = PermissionProfile::Disabled;
|
||||
|
||||
let file_system_sandbox_policy = turn_context.file_system_sandbox_policy();
|
||||
|
||||
@@ -1476,6 +1476,7 @@ pub(super) fn realtime_text_for_event(msg: &EventMsg) -> Option<String> {
|
||||
| EventMsg::ContextCompacted(_)
|
||||
| EventMsg::ThreadRolledBack(_)
|
||||
| EventMsg::TurnStarted(_)
|
||||
| EventMsg::ThreadSettingsApplied(_)
|
||||
| EventMsg::TurnComplete(_)
|
||||
| EventMsg::TokenCount(_)
|
||||
| EventMsg::UserMessage(_)
|
||||
|
||||
Reference in New Issue
Block a user