[codex] cover session extension HTTP state [ci changed_files]

This commit is contained in:
Cooper Gamble
2026-06-03 09:54:48 +00:00
parent 5e52e5215f
commit 2fbbd204b4
11 changed files with 77 additions and 12 deletions
+2
View File
@@ -3053,6 +3053,7 @@ dependencies = [
"codex-core",
"codex-extension-api",
"codex-features",
"codex-http-state",
"codex-login",
"codex-model-provider",
"codex-model-provider-info",
@@ -4197,6 +4198,7 @@ dependencies = [
"codex-core",
"codex-extension-api",
"codex-features",
"codex-http-state",
"codex-login",
"codex-model-provider",
"codex-model-provider-info",
+7
View File
@@ -321,6 +321,13 @@ impl AgentControl {
.services
.model_client
.set_http_state_surface(surface);
new_thread
.thread
.codex
.session
.services
.thread_extension_data
.insert(surface);
}
parent_thread
.codex
+20
View File
@@ -1597,6 +1597,16 @@ async fn spawn_thread_subagent_inherits_parent_http_state_surface() {
)
.await
.expect("parent client info should update");
assert_eq!(
parent_thread
.codex
.session
.services
.thread_extension_data
.get::<HttpStateSurface>()
.as_deref(),
Some(&HttpStateSurface::CodexDesktop)
);
let child_thread_id = harness
.control
@@ -1628,6 +1638,16 @@ async fn spawn_thread_subagent_inherits_parent_http_state_surface() {
.http_state_surface(),
Some(HttpStateSurface::CodexDesktop)
);
assert_eq!(
child_thread
.codex
.session
.services
.thread_extension_data
.get::<HttpStateSurface>()
.as_deref(),
Some(&HttpStateSurface::CodexDesktop)
);
}
#[tokio::test]
+6
View File
@@ -795,6 +795,12 @@ impl Codex {
.services
.model_client
.set_app_server_client_name(app_server_client_name.as_deref());
if let Some(http_state_surface) = self.session.services.model_client.http_state_surface() {
self.session
.services
.thread_extension_data
.insert(http_state_surface);
}
self.session
.update_settings(SessionSettingsUpdate {
app_server_client_name,
+1
View File
@@ -971,6 +971,7 @@ impl Session {
codex_extension_api::ExtensionData::new(session_id.to_string());
let thread_extension_data =
codex_extension_api::ExtensionData::new(thread_id.to_string());
thread_extension_data.insert(http_state_surface);
for contributor in extensions.thread_lifecycle_contributors() {
contributor.on_thread_start(codex_extension_api::ThreadStartInput {
config: config.as_ref(),
+1
View File
@@ -18,6 +18,7 @@ codex-api = { workspace = true }
codex-core = { workspace = true }
codex-extension-api = { workspace = true }
codex-features = { workspace = true }
codex-http-state = { workspace = true }
codex-login = { workspace = true }
codex-model-provider = { workspace = true }
codex-model-provider-info = { workspace = true }
+17 -7
View File
@@ -3,19 +3,25 @@ use codex_api::ImageGenerationRequest;
use codex_api::ImageResponse;
use codex_api::ImagesClient;
use codex_api::ReqwestTransport;
use codex_http_state::HttpStateContext;
use codex_login::default_client::build_reqwest_client;
use codex_model_provider::SharedModelProvider;
use codex_model_provider::with_native_integrity_state;
use http::HeaderMap;
#[derive(Clone)]
pub(crate) struct CodexImagesBackend {
provider: SharedModelProvider,
http_state: Option<HttpStateContext>,
}
impl CodexImagesBackend {
/// Creates a backend that sends image requests through the active model provider.
pub(crate) fn new(provider: SharedModelProvider) -> Self {
Self { provider }
pub(crate) fn new(provider: SharedModelProvider, http_state: Option<HttpStateContext>) -> Self {
Self {
provider,
http_state,
}
}
/// Resolves the provider and auth required for the current image API request.
@@ -25,11 +31,15 @@ impl CodexImagesBackend {
.api_provider()
.await
.map_err(|err| err.to_string())?;
let auth = self
.provider
.api_auth()
.await
.map_err(|err| err.to_string())?;
let auth = self.provider.auth().await;
let auth = with_native_integrity_state(
self.provider
.api_auth()
.await
.map_err(|err| err.to_string())?,
auth.as_ref(),
self.http_state.clone(),
);
Ok(ImagesClient::new(
ReqwestTransport::new(build_reqwest_client()),
provider,
@@ -10,6 +10,8 @@ use codex_extension_api::ToolCall;
use codex_extension_api::ToolContributor;
use codex_extension_api::ToolExecutor;
use codex_features::Feature;
use codex_http_state::HttpStateContext;
use codex_http_state::HttpStateSurface;
use codex_login::AuthManager;
use codex_model_provider::create_model_provider;
use codex_model_provider_info::ModelProviderInfo;
@@ -78,6 +80,9 @@ impl ToolContributor for ImageGenerationExtension {
vec![Arc::new(ImageGenerationTool::new(CodexImagesBackend::new(
create_model_provider(config.provider.clone(), Some(self.auth_manager.clone())),
thread_store.get::<HttpStateSurface>().map(|surface| {
HttpStateContext::new(self.auth_manager.codex_home().to_path_buf(), *surface)
}),
)))]
}
}
+1
View File
@@ -18,6 +18,7 @@ codex-api = { workspace = true }
codex-core = { workspace = true }
codex-extension-api = { workspace = true }
codex-features = { workspace = true }
codex-http-state = { workspace = true }
codex-login = { workspace = true }
codex-model-provider = { workspace = true }
codex-model-provider-info = { workspace = true }
+5
View File
@@ -14,6 +14,8 @@ use codex_extension_api::ThreadLifecycleContributor;
use codex_extension_api::ThreadStartInput;
use codex_extension_api::ToolContributor;
use codex_features::Feature;
use codex_http_state::HttpStateContext;
use codex_http_state::HttpStateSurface;
use codex_login::AuthManager;
use codex_model_provider::create_model_provider;
use codex_model_provider_info::ModelProviderInfo;
@@ -121,6 +123,9 @@ impl ToolContributor for WebSearchExtension {
config.provider.clone(),
Some(self.auth_manager.clone()),
),
http_state: thread_store.get::<HttpStateSurface>().map(|surface| {
HttpStateContext::new(self.auth_manager.codex_home().to_path_buf(), *surface)
}),
settings: config.settings.clone(),
})]
}
+12 -5
View File
@@ -14,8 +14,10 @@ use codex_extension_api::ToolName;
use codex_extension_api::ToolOutput;
use codex_extension_api::ToolSpec;
use codex_extension_api::parse_tool_input_schema_without_compaction;
use codex_http_state::HttpStateContext;
use codex_login::default_client::build_reqwest_client;
use codex_model_provider::SharedModelProvider;
use codex_model_provider::with_native_integrity_state;
use codex_protocol::items::WebSearchItem;
use codex_protocol::models::WebSearchAction;
use codex_tools::ResponsesApiNamespace;
@@ -36,6 +38,7 @@ const WEB_RUN_DESCRIPTION: &str = include_str!("../web_run_description.md");
pub(crate) struct WebSearchTool {
pub(crate) session_id: String,
pub(crate) provider: SharedModelProvider,
pub(crate) http_state: Option<HttpStateContext>,
pub(crate) settings: SearchSettings,
}
@@ -82,11 +85,15 @@ impl ToolExecutor<ToolCall> for WebSearchTool {
.api_provider()
.await
.map_err(|err| FunctionCallError::Fatal(err.to_string()))?;
let auth = self
.provider
.api_auth()
.await
.map_err(|err| FunctionCallError::Fatal(err.to_string()))?;
let auth = self.provider.auth().await;
let auth = with_native_integrity_state(
self.provider
.api_auth()
.await
.map_err(|err| FunctionCallError::Fatal(err.to_string()))?,
auth.as_ref(),
self.http_state.clone(),
);
let client = SearchClient::new(
ReqwestTransport::new(build_reqwest_client()),
provider,