1pub mod error;
12pub mod handler;
13pub mod middleware;
14#[allow(clippy::needless_for_each)]
15pub mod openapi;
16pub mod router;
17pub mod usage;
18pub(crate) mod util;
19
20pub use byokey_provider::VersionStore;
21pub use error::ApiError;
22pub use handler::amp::threads::AmpThreadIndex;
23pub use openapi::ApiDoc;
24pub use router::make_router;
25pub use usage::{UsageRecorder, UsageStats};
26
27use arc_swap::ArcSwap;
28use byokey_auth::AuthManager;
29use byokey_provider::DeviceProfileCache;
30use byokey_types::{RateLimitStore, UsageStore};
31use std::sync::Arc;
32
33pub struct AppState {
35 pub config: Arc<ArcSwap<byokey_config::Config>>,
38 pub auth: Arc<AuthManager>,
40 pub http: rquest::Client,
42 pub usage: Arc<UsageRecorder>,
44 pub ratelimits: Arc<RateLimitStore>,
46 pub device_profiles: Arc<DeviceProfileCache>,
48 pub amp_threads: Arc<AmpThreadIndex>,
50 pub versions: VersionStore,
52}
53
54impl AppState {
55 pub fn new(
60 config: Arc<ArcSwap<byokey_config::Config>>,
61 auth: Arc<AuthManager>,
62 usage_store: Option<Arc<dyn UsageStore>>,
63 versions: VersionStore,
64 ) -> Arc<Self> {
65 Self::with_thread_index(config, auth, usage_store, versions, {
66 let idx = Arc::new(AmpThreadIndex::build());
67 idx.watch();
68 idx
69 })
70 }
71
72 pub fn with_thread_index(
74 config: Arc<ArcSwap<byokey_config::Config>>,
75 auth: Arc<AuthManager>,
76 usage_store: Option<Arc<dyn UsageStore>>,
77 versions: VersionStore,
78 amp_threads: Arc<AmpThreadIndex>,
79 ) -> Arc<Self> {
80 let snapshot = config.load();
81 let http = build_http_client(snapshot.proxy_url.as_deref());
82 Arc::new(Self {
83 config,
84 auth,
85 http,
86 usage: Arc::new(UsageRecorder::new(usage_store)),
87 ratelimits: Arc::new(RateLimitStore::new()),
88 device_profiles: Arc::new(DeviceProfileCache::new()),
89 amp_threads,
90 versions,
91 })
92 }
93}
94
95fn build_http_client(proxy_url: Option<&str>) -> rquest::Client {
97 if let Some(url) = proxy_url {
98 match rquest::Proxy::all(url) {
99 Ok(proxy) => {
100 return rquest::Client::builder()
101 .proxy(proxy)
102 .build()
103 .unwrap_or_else(|_| rquest::Client::new());
104 }
105 Err(e) => {
106 tracing::warn!(url = url, error = %e, "invalid proxy_url, using direct connection");
107 }
108 }
109 }
110 rquest::Client::new()
111}