Skip to content

Commit 3c5b83d

Browse files
echobtfactorydroid
andauthored
refactor: centralize HTTP client and extract TUI handlers for better modularity (#436)
- Centralize HTTP client creation in cortex-common::http_client - cortex-engine::api_client now re-exports from cortex-common - Eliminates duplicated HTTP client factory code - Extract auth handlers to cortex-tui/src/runner/auth_handlers.rs - Login flow (device code OAuth) - Logout functionality - Account info loading - Browser URL opening helper - Extract billing handlers to cortex-tui/src/runner/billing_handlers.rs - Billing status fetching - Usage breakdown queries - Billing data parsing These changes improve code organization and reduce the massive event_loop.rs file (11k+ lines) by moving handlers into dedicated modules. This follows Rust best practices for module organization and makes the codebase easier to navigate and maintain. Co-authored-by: Droid Agent <droid@factory.ai>
1 parent 1fd31c5 commit 3c5b83d

4 files changed

Lines changed: 597 additions & 63 deletions

File tree

cortex-engine/src/api_client.rs

Lines changed: 18 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
//! - `create_client_with_timeout(duration)` - Custom timeout
1212
//!
1313
//! All clients include: User-Agent, tcp_nodelay, and proper error handling.
14+
//!
15+
//! Note: This module re-exports and wraps functions from `cortex_common::http_client`
16+
//! with appropriate error types for cortex-engine.
1417
1518
use std::collections::HashMap;
1619
use std::time::Duration;
@@ -20,58 +23,35 @@ use serde::{Deserialize, Serialize, de::DeserializeOwned};
2023

2124
use crate::error::{CortexError, Result};
2225

23-
// ============================================================================
24-
// Global HTTP Client Constants
25-
// ============================================================================
26-
27-
/// User-Agent string for all HTTP requests
28-
pub const USER_AGENT: &str = concat!("cortex-cli/", env!("CARGO_PKG_VERSION"));
29-
30-
/// Default timeout for standard API requests (30 seconds)
31-
pub const DEFAULT_TIMEOUT: Duration = Duration::from_secs(30);
32-
33-
/// Extended timeout for LLM streaming requests (5 minutes)
34-
pub const STREAMING_TIMEOUT: Duration = Duration::from_secs(300);
35-
36-
/// Short timeout for health checks (5 seconds)
37-
pub const HEALTH_CHECK_TIMEOUT: Duration = Duration::from_secs(5);
26+
// Re-export constants from cortex-common
27+
pub use cortex_common::http_client::{
28+
DEFAULT_TIMEOUT, HEALTH_CHECK_TIMEOUT, STREAMING_TIMEOUT, USER_AGENT,
29+
};
3830

3931
/// Default connection timeout (10 seconds)
4032
pub const DEFAULT_CONNECT_TIMEOUT: Duration = Duration::from_secs(10);
4133

4234
// ============================================================================
43-
// Global HTTP Client Factory Functions
35+
// Global HTTP Client Factory Functions (wrapping cortex-common)
4436
// ============================================================================
4537

4638
/// Creates an HTTP client with default configuration (30s timeout).
4739
///
4840
/// Includes: User-Agent, tcp_nodelay, 30s timeout.
49-
///
50-
/// # Example
51-
/// ```ignore
52-
/// let client = create_default_client()?;
53-
/// let resp = client.get("https://api.example.com/data").send().await?;
54-
/// ```
5541
pub fn create_default_client() -> Result<Client> {
56-
create_client_with_timeout(DEFAULT_TIMEOUT)
42+
cortex_common::http_client::create_default_client().map_err(|e| CortexError::Internal(e))
5743
}
5844

5945
/// Creates an HTTP client for LLM streaming (5min timeout).
6046
///
6147
/// Use this for endpoints that stream responses (SSE, chunked transfer).
62-
///
63-
/// # Example
64-
/// ```ignore
65-
/// let client = create_streaming_client()?;
66-
/// let resp = client.post("https://api.example.com/chat").send().await?;
67-
/// ```
6848
pub fn create_streaming_client() -> Result<Client> {
69-
create_client_with_timeout(STREAMING_TIMEOUT)
49+
cortex_common::http_client::create_streaming_client().map_err(|e| CortexError::Internal(e))
7050
}
7151

7252
/// Creates an HTTP client for health checks (5s timeout).
7353
pub fn create_health_check_client() -> Result<Client> {
74-
create_client_with_timeout(HEALTH_CHECK_TIMEOUT)
54+
cortex_common::http_client::create_health_check_client().map_err(|e| CortexError::Internal(e))
7555
}
7656

7757
/// Creates an HTTP client with a custom timeout.
@@ -81,13 +61,8 @@ pub fn create_health_check_client() -> Result<Client> {
8161
/// - tcp_nodelay: true (for lower latency)
8262
/// - Specified timeout (applies to both connect and overall request)
8363
pub fn create_client_with_timeout(timeout: Duration) -> Result<Client> {
84-
Client::builder()
85-
.user_agent(USER_AGENT)
86-
.timeout(timeout)
87-
.connect_timeout(timeout) // Apply timeout to TCP connection phase as well (#2710)
88-
.tcp_nodelay(true)
89-
.build()
90-
.map_err(|e| CortexError::Internal(format!("Failed to build HTTP client: {e}")))
64+
cortex_common::http_client::create_client_with_timeout(timeout)
65+
.map_err(|e| CortexError::Internal(e))
9166
}
9267

9368
/// Creates an HTTP client with separate connect and response timeouts.
@@ -115,43 +90,23 @@ pub fn create_client_with_timeouts(
11590
///
11691
/// Use this when you need to customize the client further before building.
11792
/// Note: The timeout is applied to both the TCP connection phase and the overall request.
118-
///
119-
/// # Example
120-
/// ```ignore
121-
/// let client = create_client_builder()
122-
/// .redirect(reqwest::redirect::Policy::none())
123-
/// .build()?;
124-
/// ```
12593
pub fn create_client_builder() -> reqwest::ClientBuilder {
126-
Client::builder()
127-
.user_agent(USER_AGENT)
128-
.timeout(DEFAULT_TIMEOUT)
129-
.connect_timeout(DEFAULT_TIMEOUT) // Apply timeout to TCP connection phase as well
130-
.tcp_nodelay(true)
94+
cortex_common::http_client::create_client_builder()
13195
}
13296

13397
// ============================================================================
134-
// Blocking Client Factory (for sync code)
98+
// Blocking Client Factory (wrapping cortex-common)
13599
// ============================================================================
136100

137101
/// Creates a blocking HTTP client with default configuration.
138102
pub fn create_blocking_client() -> Result<reqwest::blocking::Client> {
139-
reqwest::blocking::Client::builder()
140-
.user_agent(USER_AGENT)
141-
.timeout(DEFAULT_TIMEOUT)
142-
.connect_timeout(DEFAULT_TIMEOUT) // Apply timeout to TCP connection phase as well
143-
.build()
144-
.map_err(|e| CortexError::Internal(format!("Failed to build blocking HTTP client: {e}")))
103+
cortex_common::http_client::create_blocking_client().map_err(|e| CortexError::Internal(e))
145104
}
146105

147106
/// Creates a blocking HTTP client with custom timeout.
148107
pub fn create_blocking_client_with_timeout(timeout: Duration) -> Result<reqwest::blocking::Client> {
149-
reqwest::blocking::Client::builder()
150-
.user_agent(USER_AGENT)
151-
.timeout(timeout)
152-
.connect_timeout(timeout) // Apply timeout to TCP connection phase as well
153-
.build()
154-
.map_err(|e| CortexError::Internal(format!("Failed to build blocking HTTP client: {e}")))
108+
cortex_common::http_client::create_blocking_client_with_timeout(timeout)
109+
.map_err(|e| CortexError::Internal(e))
155110
}
156111

157112
// ============================================================================

0 commit comments

Comments
 (0)