Share dynamic tool specifications across turn snapshots (#55261)

## What changed

Store dynamic tool specifications in an `Arc<[DynamicToolSpec]>` so session configuration and turn snapshots share the list fixed at thread startup instead of copying it on each clone.

Keep the `dynamic_tools()` accessor returning a `Vec<DynamicToolSpec>`, but copy the specifications after releasing the session state lock.

GitOrigin-RevId: 092c5f9ea6cc390d948c27cd11340aeb12bd6037
This commit is contained in:
Charlie Marsh
2026-10-19 11:35:08 +00:00
committed by copyberry
parent 9032fc7683
commit c0ce901923
4 changed files with 17 additions and 13 deletions
+1 -1
View File
@@ -950,7 +950,7 @@ impl Session {
parent_thread_id,
thread_source,
originator,
dynamic_tools,
dynamic_tools: Arc::from(dynamic_tools),
user_shell_override,
};
session_configuration
+8 -4
View File
@@ -163,7 +163,8 @@ pub(crate) struct SessionConfiguration {
pub(super) thread_source: Option<ThreadSource>,
/// Effective originator used for this thread's Responses requests and analytics events.
pub(super) originator: String,
pub(super) dynamic_tools: Vec<DynamicToolSpec>,
/// Fixed at thread startup and shared with turn snapshots.
pub(super) dynamic_tools: Arc<[DynamicToolSpec]>,
pub(super) user_shell_override: Option<shell::Shell>,
}
@@ -678,8 +679,11 @@ impl Session {
}
pub(crate) async fn dynamic_tools(&self) -> Vec<DynamicToolSpec> {
let state = self.state.lock().await;
state.session_configuration.dynamic_tools.clone()
let dynamic_tools = {
let state = self.state.lock().await;
Arc::clone(&state.session_configuration.dynamic_tools)
};
dynamic_tools.to_vec()
}
pub(crate) async fn responses_metadata(
@@ -1066,7 +1070,7 @@ impl Session {
text: session_configuration.base_instructions.clone(),
provenance: base_instructions_provenance.clone(),
},
dynamic_tools: session_configuration.dynamic_tools.clone(),
dynamic_tools: session_configuration.dynamic_tools.to_vec(),
selected_capability_roots: selected_capability_roots.clone(),
multi_agent_version: initial_multi_agent_version,
history_mode: session_configuration.history_mode,
+7 -7
View File
@@ -4516,7 +4516,7 @@ async fn set_rate_limits_retains_previous_credits() {
parent_thread_id: None,
thread_source: None,
originator: "test_originator".to_string(),
dynamic_tools: Vec::new(),
dynamic_tools: Arc::default(),
user_shell_override: None,
};
@@ -4639,7 +4639,7 @@ async fn set_rate_limits_updates_plan_type_when_present() {
parent_thread_id: None,
thread_source: None,
originator: "test_originator".to_string(),
dynamic_tools: Vec::new(),
dynamic_tools: Arc::default(),
user_shell_override: None,
};
@@ -5263,7 +5263,7 @@ pub(crate) async fn make_session_configuration_for_tests() -> SessionConfigurati
parent_thread_id: None,
thread_source: None,
originator: "test_originator".to_string(),
dynamic_tools: Vec::new(),
dynamic_tools: Arc::default(),
user_shell_override: None,
}
}
@@ -6836,7 +6836,7 @@ pub(crate) async fn make_session_and_context() -> (Session, TurnContext) {
parent_thread_id: None,
thread_source: None,
originator: "test_originator".to_string(),
dynamic_tools: Vec::new(),
dynamic_tools: Arc::default(),
user_shell_override: None,
};
let session_telemetry = session_telemetry(
@@ -7156,7 +7156,7 @@ async fn make_session_with_config_and_rx(
parent_thread_id: None,
thread_source: None,
originator: "test_originator".to_string(),
dynamic_tools: Vec::new(),
dynamic_tools: Arc::default(),
user_shell_override: None,
};
@@ -7291,7 +7291,7 @@ async fn make_session_with_history_source_and_agent_control_and_rx(
parent_thread_id: None,
thread_source: None,
originator: "test_originator".to_string(),
dynamic_tools: Vec::new(),
dynamic_tools: Arc::default(),
user_shell_override: None,
};
@@ -9104,7 +9104,7 @@ where
parent_thread_id: None,
thread_source: None,
originator: "test_originator".to_string(),
dynamic_tools,
dynamic_tools: Arc::from(dynamic_tools),
user_shell_override: None,
};
let session_telemetry = session_telemetry(
+1 -1
View File
@@ -368,7 +368,7 @@ pub struct TurnContext {
pub(crate) windows_sandbox_level: WindowsSandboxLevel,
pub(crate) available_models: Vec<ModelPreset>,
pub(crate) final_output_json_schema: Option<Value>,
pub(crate) dynamic_tools: Vec<DynamicToolSpec>,
pub(crate) dynamic_tools: Arc<[DynamicToolSpec]>,
pub(crate) turn_metadata_state: Arc<TurnMetadataState>,
pub(crate) extension_data: Arc<codex_extension_api::ExtensionData>,
pub(crate) turn_timing_state: Arc<TurnTimingState>,