Skip to main content

cc_lb_plugin_wire/v1/
common.rs

1extern crate alloc;
2
3use alloc::{string::String, vec::Vec};
4use serde::{Deserialize, Serialize};
5
6#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
7#[serde(deny_unknown_fields)]
8pub struct HeaderWire {
9    pub name: String,
10    pub value_base64: String,
11}
12
13impl HeaderWire {
14    pub fn dry_run_sample() -> Self {
15        Self {
16            name: String::from("x-cc-lb-dry-run"),
17            value_base64: String::new(),
18        }
19    }
20}
21
22#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
23#[serde(deny_unknown_fields)]
24pub struct Principal {
25    pub id: String,
26    pub kind: String,
27    pub claims: serde_json::Map<String, serde_json::Value>,
28}
29
30impl Principal {
31    pub fn dry_run_sample() -> Self {
32        Self {
33            id: String::from("dry-run-principal"),
34            kind: String::from("api_key"),
35            claims: serde_json::Map::new(),
36        }
37    }
38}
39
40#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
41#[serde(deny_unknown_fields)]
42pub struct RequestWire {
43    pub request_id: String,
44    pub headers: Vec<HeaderWire>,
45    pub method: String,
46    pub path: String,
47    pub query: Option<String>,
48    pub body_base64: String,
49}
50
51impl RequestWire {
52    pub fn dry_run_sample() -> Self {
53        Self {
54            request_id: String::from("dry-run-request"),
55            headers: Vec::new(),
56            method: String::from("POST"),
57            path: String::from("/v1/messages"),
58            query: None,
59            body_base64: String::new(),
60        }
61    }
62}
63
64#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
65#[serde(deny_unknown_fields)]
66pub struct RateLimitObservationWire {
67    pub kind: String,
68    pub window: String,
69    pub limit: Option<u64>,
70    pub remaining: Option<u64>,
71    pub reset: Option<String>,
72}
73
74impl RateLimitObservationWire {
75    pub fn dry_run_sample() -> Self {
76        Self {
77            kind: String::from("requests"),
78            window: String::from("dry-run"),
79            limit: None,
80            remaining: None,
81            reset: None,
82        }
83    }
84}
85
86#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
87#[serde(rename_all = "snake_case")]
88#[serde(deny_unknown_fields)]
89pub struct SubscriptionQuotaCandidateSnapshotWire {
90    pub window: String,
91    pub source: String,
92    pub data_state: String,
93    pub utilization: Option<f64>,
94    pub status: Option<String>,
95    pub resets_at_unix_secs: Option<u64>,
96    pub surpassed_threshold: Option<bool>,
97    pub representative_claim: Option<String>,
98    pub disabled_reason: Option<String>,
99    pub observed_at_unix_millis: Option<u64>,
100    pub age_secs: Option<u64>,
101}
102
103impl SubscriptionQuotaCandidateSnapshotWire {
104    pub fn dry_run_sample() -> Self {
105        Self {
106            window: String::from("5h"),
107            source: String::from("missing"),
108            data_state: String::from("missing"),
109            utilization: None,
110            status: None,
111            resets_at_unix_secs: None,
112            surpassed_threshold: None,
113            representative_claim: None,
114            disabled_reason: None,
115            observed_at_unix_millis: None,
116            age_secs: None,
117        }
118    }
119}
120
121#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
122#[serde(deny_unknown_fields)]
123pub struct CandidateWire {
124    pub upstream_id: String,
125    pub name: String,
126    pub kind: String,
127    pub observed_rate_limits: Vec<RateLimitObservationWire>,
128    pub subscription_quotas: Vec<SubscriptionQuotaCandidateSnapshotWire>,
129    pub observed_at_unix_secs: u64,
130}
131
132impl CandidateWire {
133    pub fn dry_run_sample() -> Self {
134        Self {
135            upstream_id: String::from("00000000-0000-0000-0000-000000000000"),
136            name: String::from("dry-run-upstream"),
137            kind: String::from("anthropic_api_key"),
138            observed_rate_limits: Vec::new(),
139            subscription_quotas: Vec::new(),
140            observed_at_unix_secs: 0,
141        }
142    }
143}
144
145#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
146#[serde(rename_all = "snake_case", tag = "kind")]
147#[serde(deny_unknown_fields)]
148pub enum UpstreamWire {
149    AnthropicDirect,
150}
151
152impl UpstreamWire {
153    pub fn dry_run_sample() -> Self {
154        Self::AnthropicDirect
155    }
156}
157
158#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
159#[serde(rename_all = "snake_case", tag = "kind")]
160#[serde(deny_unknown_fields)]
161pub enum DialectBinding {
162    #[serde(rename = "self")]
163    SelfReferenced,
164}
165
166impl DialectBinding {
167    pub fn dry_run_sample() -> Self {
168        Self::SelfReferenced
169    }
170}
171
172#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
173#[serde(deny_unknown_fields)]
174pub struct ShapedRequestWire {
175    pub url: String,
176    pub method: String,
177    pub headers: Vec<HeaderWire>,
178    pub body_base64: String,
179}
180
181impl ShapedRequestWire {
182    pub fn dry_run_sample() -> Self {
183        Self {
184            url: String::from("https://api.anthropic.com/v1/messages"),
185            method: String::from("POST"),
186            headers: Vec::new(),
187            body_base64: String::new(),
188        }
189    }
190}
191
192#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
193#[serde(rename_all = "snake_case")]
194#[serde(deny_unknown_fields)]
195pub enum UpstreamErrorCategory {
196    Unauthorized,
197    Retryable,
198    Failed,
199}
200
201impl UpstreamErrorCategory {
202    pub fn dry_run_sample() -> Self {
203        Self::Unauthorized
204    }
205}
206
207#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
208#[serde(deny_unknown_fields)]
209pub struct UpstreamErrorWire {
210    pub status: u16,
211    pub body_base64: Option<String>,
212    pub category: UpstreamErrorCategory,
213}
214
215impl UpstreamErrorWire {
216    pub fn dry_run_sample() -> Self {
217        Self {
218            status: 401,
219            body_base64: None,
220            category: UpstreamErrorCategory::dry_run_sample(),
221        }
222    }
223}
224
225#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
226#[serde(rename_all = "snake_case", tag = "kind")]
227#[serde(deny_unknown_fields)]
228pub enum ObserveEventWire {
229    RequestStarted {
230        request_id: String,
231        downstream_user_agent: Option<String>,
232    },
233    AuthnComplete {
234        principal_id: String,
235        principal_kind: String,
236    },
237    UpstreamChosen {
238        upstream: UpstreamWire,
239    },
240    Chunk {
241        batch_index: u64,
242        event_count: usize,
243        total_bytes: usize,
244    },
245    RequestFinished {
246        status: u16,
247        input_tokens: Option<u64>,
248        output_tokens: Option<u64>,
249        cache_creation_input_tokens: Option<u64>,
250        cache_read_input_tokens: Option<u64>,
251        duration_ms: u64,
252    },
253    Error {
254        code: String,
255        message: String,
256        source: String,
257    },
258}
259
260impl ObserveEventWire {
261    pub fn dry_run_sample() -> Self {
262        Self::RequestStarted {
263            request_id: String::from("dry-run-request"),
264            downstream_user_agent: None,
265        }
266    }
267}