Skip to main content

Channel

Trait Channel 

Source
pub trait Channel: Send + Sync {
Show 22 methods // Required methods fn id(&self) -> &'static str; fn provider_family(&self) -> Provider; fn routing_table(&self) -> RouteList; fn prepare( &self, ctx: PrepareCtx<'_>, ) -> Result<PreparedRequest, ChannelError>; // Provided methods fn metadata(&self) -> ChannelMetadata { ... } fn classify( &self, status: StatusCode, headers: &HeaderMap, _body: &Bytes, ) -> Disposition { ... } fn credential_wide_auth(&self) -> bool { ... } fn cookie_login_requires_browser(&self) -> bool { ... } fn refresh_requires_browser(&self, _secret: &Value) -> bool { ... } fn shares_account_quota(&self, _upstream_model_id: &str) -> bool { ... } fn shape_request( &self, body: Bytes, _headers: &mut HeaderMap, _ctx: &ShapeCtx<'_>, ) -> Bytes { ... } fn shape_response(&self, body: Bytes, _ctx: &ShapeCtx<'_>) -> Bytes { ... } fn bundled_models(&self) -> Option<Bytes> { ... } fn credential_models(&self, _secret: &Value) -> Option<Bytes> { ... } fn stream_decoder(&self) -> Option<Box<dyn ChannelStreamDecoder>> { ... } fn needs_refresh(&self, _secret: &Value) -> bool { ... } fn refresh<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, _client: &'life1 Arc<dyn UpstreamClient>, _ctx: RefreshCtx<'life2>, ) -> Pin<Box<dyn Future<Output = Result<Value, ChannelError>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait { ... } fn transport(&self) -> TransportKind { ... } fn prepare_usage_request( &self, _secret: &Value, _settings: &Value, ) -> Result<Option<Request<Bytes>>, ChannelError> { ... } fn parse_usage( &self, _status: StatusCode, _headers: &HeaderMap, _body: &Bytes, ) -> Option<UsageSnapshot> { ... } fn prepare_rate_limit_reset_credit_request( &self, _secret: &Value, _settings: &Value, _idempotency_key: &str, ) -> Result<Option<Request<Bytes>>, ChannelError> { ... } fn parse_rate_limit_reset_credit( &self, _status: StatusCode, _headers: &HeaderMap, _body: &Bytes, ) -> Option<RateLimitResetCreditConsumeResponse> { ... }
}
Expand description

Pure upstream access adapter (§6.3). Implementors provide id, provider_family, routing_table and prepare; the rest have sensible defaults.

Required Methods§

Source

fn id(&self) -> &'static str

Stable channel id used as the registry key (matches Provider.channel).

Source

fn provider_family(&self) -> Provider

The provider family this channel’s upstream belongs to (billing/usage).

Source

fn routing_table(&self) -> RouteList

The channel’s explicit routing surface (ported from its capabilities).

Source

fn prepare(&self, ctx: PrepareCtx<'_>) -> Result<PreparedRequest, ChannelError>

Inject auth, resolve endpoint + method, set an ABSOLUTE upstream URL. Pure access — no transform/rules, no body mutation. Moves ctx.body in.

Provided Methods§

Source

fn metadata(&self) -> ChannelMetadata

Metadata for runtime discovery and generic configuration UIs.

Source

fn classify( &self, status: StatusCode, headers: &HeaderMap, _body: &Bytes, ) -> Disposition

Map an upstream response to the 5-state Disposition. Default is the generic HTTP-status mapping; override only for provider-specific signals. For streaming, body is empty (status + headers suffice).

Source

fn credential_wide_auth(&self) -> bool

Whether a model-bound auth rejection (401/402/403) kills the WHOLE credential rather than only the exact (credential, model) pair. true for subscription-account channels (codex, claudecode) whose token is account-wide. Default: model-scoped.

Source

fn cookie_login_requires_browser(&self) -> bool

Whether first-time cookie exchange must use the native browser profile.

Source

fn refresh_requires_browser(&self, _secret: &Value) -> bool

Whether refreshing this secret must use the native browser profile.

Source

fn shares_account_quota(&self, _upstream_model_id: &str) -> bool

Whether this model draws from the channel’s account-wide MAIN quota pool. The main limit governs the whole account, so a 429 here cools the WHOLE credential (separate-limit models included). Models with an ADDITIONAL scoped limit on top of the main pool (codex spark, claude fable) return false: their own 429 means only the scoped limit is hit and stays model-scoped. Default: false (per-model quota, api-key channels).

Source

fn shape_request( &self, body: Bytes, _headers: &mut HeaderMap, _ctx: &ShapeCtx<'_>, ) -> Bytes

Channel-specific REQUEST-body shaping (整形): runs after protocol transform + process rules, before prepare. Pure field hygiene (strip unsupported fields, cap/rename, role/tools normalize, remove header tokens). Default: identity.

Source

fn shape_response(&self, body: Bytes, _ctx: &ShapeCtx<'_>) -> Bytes

Channel-specific RESPONSE-body shaping (整形) on the raw buffered upstream body, before protocol transform. Operation-aware via ctx so a channel can reshape model lists, fix non-standard fields, unwrap envelopes, etc. Runs on ALL statuses (error bodies included). Default: identity.

Source

fn bundled_models(&self) -> Option<Bytes>

A channel-bundled static model catalogue, for channels whose upstream exposes no model-list endpoint (e.g. vertexexpress). When Some, the admin model-pull returns it directly — no credential / upstream call. The body is in the channel family’s canonical model-list wire shape. Default: none.

Source

fn credential_models(&self, _secret: &Value) -> Option<Bytes>

A credential-scoped model catalogue discovered while authenticating or refreshing the secret. Unlike bundled_models, this hook is evaluated only after the credential has been decrypted and refreshed, so account-specific catalogues can be returned without an extra upstream model-list request. Default: none.

Source

fn stream_decoder(&self) -> Option<Box<dyn ChannelStreamDecoder>>

Optional channel-specific stream decoder (envelope unwrap / binary → SSE), applied to the raw upstream byte stream before any protocol transform. Default: none (passthrough).

Source

fn needs_refresh(&self, _secret: &Value) -> bool

Whether the DECRYPTED secret must be refreshed before use (e.g. OAuth access token near expiry). Default: never.

Source

fn refresh<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, _client: &'life1 Arc<dyn UpstreamClient>, _ctx: RefreshCtx<'life2>, ) -> Pin<Box<dyn Future<Output = Result<Value, ChannelError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Refresh the credential against the provider, returning the new PLAINTEXT secret Value. The pipeline re-seals + persists + publishes — the channel never touches cipher/persistence (purity §6.3). Default: unsupported.

Source

fn transport(&self) -> TransportKind

Source

fn prepare_usage_request( &self, _secret: &Value, _settings: &Value, ) -> Result<Option<Request<Bytes>>, ChannelError>

Build a request to this channel’s per-credential upstream usage / quota endpoint, given an already-fresh decrypted secret and provider settings. None (the default) means the channel exposes no usage endpoint (api-key / vertex channels). The driver sends it through the credential’s resolved client (same proxy + TLS profile as traffic) and feeds the response to parse_usage. Pure access: no persistence, no body shaping beyond what the endpoint needs.

Source

fn parse_usage( &self, _status: StatusCode, _headers: &HeaderMap, _body: &Bytes, ) -> Option<UsageSnapshot>

Parse this channel’s usage-endpoint response into the normalized UsageSnapshot. Called only with the response to the request from prepare_usage_request. None on a non-success status or an unparseable body.

Source

fn prepare_rate_limit_reset_credit_request( &self, _secret: &Value, _settings: &Value, _idempotency_key: &str, ) -> Result<Option<Request<Bytes>>, ChannelError>

Build a request to consume one earned rate-limit reset credit. Only channels whose upstream exposes this account action return a request.

Source

fn parse_rate_limit_reset_credit( &self, _status: StatusCode, _headers: &HeaderMap, _body: &Bytes, ) -> Option<RateLimitResetCreditConsumeResponse>

Parse the response from prepare_rate_limit_reset_credit_request.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§