codex_helper_core/proxy/
mod.rs1use std::collections::HashMap;
2use std::sync::{Arc, Mutex};
3use std::time::Duration;
4
5use reqwest::Client;
6
7mod admin;
8mod api_responses;
9mod attempt_execution;
10mod attempt_failures;
11mod attempt_health;
12mod attempt_request;
13mod attempt_response;
14mod attempt_selection;
15mod attempt_target;
16mod attempt_transport;
17mod auth_resolution;
18mod classify;
19mod client_identity;
20mod control_plane;
21mod control_plane_manifest;
22mod control_plane_routes;
23mod control_plane_service;
24mod entrypoint;
25mod failure_summary;
26mod headers;
27mod healthcheck_api;
28mod http_debug;
29mod passive_health;
30mod persisted_registry_api;
31mod profile_defaults;
32mod provider_execution;
33mod provider_orchestration;
34mod providers_api;
35mod request_body;
36mod request_context;
37mod request_failures;
38mod request_preparation;
39mod request_routing;
40mod response_finalization;
41mod retry;
42mod route_affinity;
43mod route_attempts;
44mod route_executor_runtime;
45mod route_executor_shadow;
46mod route_metadata;
47mod route_provenance;
48mod router_setup;
49mod routing_plan;
50mod runtime_admin_api;
51mod runtime_config;
52mod selected_upstream_request;
53mod service_core;
54mod session_overrides;
55mod stations_api;
56mod stream;
57mod target_builder;
58#[cfg(test)]
59mod tests;
60
61use crate::filter::RequestFilter;
62use crate::lb::LbState;
63use crate::state::{ProviderBalanceSnapshot, ProxyState};
64use crate::usage_providers::UsageProviderRefreshSummary;
65
66pub use self::admin::{
67 admin_base_url_from_proxy_base_url, admin_loopback_addr_for_proxy_port,
68 admin_port_for_proxy_port, local_admin_base_url_for_proxy_port, local_proxy_base_url,
69};
70pub use self::api_responses::{ProfilesResponse, ReloadResult, RuntimeStatusResponse};
71pub use self::entrypoint::handle_proxy;
72pub use self::persisted_registry_api::PersistedRoutingUpsertRequest;
73pub use self::router_setup::{
74 admin_listener_router, proxy_only_router, proxy_only_router_with_admin_base_url, router,
75};
76use self::runtime_config::RuntimeConfig;
77
78pub const ADMIN_TOKEN_ENV_VAR: &str = "CODEX_HELPER_ADMIN_TOKEN";
79pub const ADMIN_TOKEN_HEADER: &str = "x-codex-helper-admin-token";
80pub const CLIENT_NAME_HEADER: &str = "x-codex-helper-client-name";
81pub const ADMIN_PORT_OFFSET: u16 = 1000;
82
83#[cfg(test)]
84const AUTH_FILE_CACHE_MIN_CHECK_INTERVAL: Duration = Duration::from_millis(20);
85#[cfg(not(test))]
86const AUTH_FILE_CACHE_MIN_CHECK_INTERVAL: Duration = Duration::from_millis(800);
87
88#[cfg(test)]
89fn codex_auth_json_value(key: &str) -> Option<String> {
90 auth_resolution::codex_auth_json_value(key)
91}
92
93#[cfg(test)]
94fn claude_settings_env_value(key: &str) -> Option<String> {
95 auth_resolution::claude_settings_env_value(key)
96}
97
98#[derive(Clone)]
100pub struct ProxyService {
101 pub client: Client,
102 config: Arc<RuntimeConfig>,
103 pub service_name: &'static str,
104 lb_states: Arc<Mutex<HashMap<String, LbState>>>,
105 filter: RequestFilter,
106 state: Arc<ProxyState>,
107}
108
109#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
110pub struct ProviderBalanceRefreshResponse {
111 pub service_name: String,
112 pub refresh: UsageProviderRefreshSummary,
113 pub provider_balances: HashMap<String, Vec<ProviderBalanceSnapshot>>,
114}
115
116#[derive(Debug, Clone)]
117pub struct ProxyControlError {
118 status: axum::http::StatusCode,
119 message: String,
120}
121
122impl ProxyControlError {
123 pub fn new(status: axum::http::StatusCode, message: impl Into<String>) -> Self {
124 Self {
125 status,
126 message: message.into(),
127 }
128 }
129
130 pub fn status(&self) -> axum::http::StatusCode {
131 self.status
132 }
133
134 pub fn message(&self) -> &str {
135 self.message.as_str()
136 }
137
138 pub fn into_http_error(self) -> (axum::http::StatusCode, String) {
139 (self.status, self.message)
140 }
141}
142
143impl std::fmt::Display for ProxyControlError {
144 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
145 write!(f, "status={}, {}", self.status, self.message)
146 }
147}
148
149impl std::error::Error for ProxyControlError {}
150
151impl From<(axum::http::StatusCode, String)> for ProxyControlError {
152 fn from((status, message): (axum::http::StatusCode, String)) -> Self {
153 Self::new(status, message)
154 }
155}