Skip to content
Merged
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 38 additions & 0 deletions crates/aisix-gateway/src/bridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,25 @@ pub struct BridgeContext {
pub provider_key: std::sync::Arc<ProviderKey>,
/// Deadline for the entire upstream call. Bridges are expected to
/// honour this by cancelling any in-flight HTTP request.
///
/// On a streaming dispatch this is the **streaming** budget, which
/// bounds the connect phase and the gap between chunks rather than
/// the whole completion. A bridge that answers a streaming request
/// with a non-streaming upstream leg must use
/// [`non_streaming_deadline`](Self::non_streaming_deadline) instead.
pub deadline: Option<Duration>,
/// The end-to-end budget for a non-streaming upstream call, carried
/// alongside `deadline` on streaming dispatches.
///
/// A structured-output request on the synthetic-tool route cannot be
/// streamed — the JSON only exists once the tool call is complete —
/// so those bridges run the upstream leg non-streaming and render
/// the result as chunks. Measured against the streaming budget, a
/// completion that takes longer than one chunk gap is supposed to
/// would be cut off; this is the budget that call is actually
/// entitled to. `None` on a non-streaming dispatch, where `deadline`
/// already is it.
pub non_streaming_deadline: Option<Duration>,
/// The authenticated caller, for `${request.api_key.*}` header
/// templates. Default (all-empty) on calls with no caller behind
/// them — a background job poll, an internal embedding lookup.
Expand Down Expand Up @@ -160,6 +178,7 @@ impl BridgeContext {
model,
provider_key,
deadline: None,
non_streaming_deadline: None,
caller: CallerIdentity::default(),
client_headers: None,
model_id: String::new(),
Expand All @@ -172,6 +191,25 @@ impl BridgeContext {
self
}

/// Record the end-to-end budget a non-streaming call would have got,
/// for the streaming dispatches whose `deadline` is the smaller
/// streaming budget. See
/// [`non_streaming_deadline`](Self::non_streaming_deadline).
pub fn with_non_streaming_deadline(mut self, deadline: Option<Duration>) -> Self {
self.non_streaming_deadline = deadline;
self
}

/// The deadline an upstream leg that is *not* streaming should run
/// under, whichever kind of dispatch this context came from.
pub fn non_streaming_ctx(&self) -> Self {
let mut ctx = self.clone();
if let Some(deadline) = self.non_streaming_deadline {
ctx.deadline = Some(deadline);
}
ctx
}

/// Attach the caller identity and inbound headers the outbound-header
/// pipeline reads. Dispatch paths with a real client request call this;
/// leaving it off means no client header is ever forwarded and
Expand Down
10 changes: 10 additions & 0 deletions crates/aisix-gateway/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
//! that dispatches `ChatFormat` to the right `Bridge`.
//! - [`sse`] — a provider-agnostic SSE line decoder. Bridges that stream
//! over SSE feed it raw bytes and pull typed events back out.
//! - [`structured_output`] — the `response_format` translation pieces
//! every bridge shares: the synthetic JSON tool and its reverse
//! translation, the fake stream that carries it, and the two schema
//! normalisations.
//! - [`credential`] — cache keys for credential-derived upstream tokens.
//! - [`upstream_http`] — connection-layer settings every provider client
//! shares (connect timeout, TCP keepalive, pool expiry) plus the
Expand All @@ -28,6 +32,7 @@ pub mod chat;
pub mod credential;
pub mod hub;
pub mod sse;
pub mod structured_output;
pub mod upstream_headers;
pub mod upstream_http;
pub mod upstream_tls;
Expand All @@ -46,6 +51,11 @@ pub use chat::{
pub use credential::credential_fingerprint;
pub use hub::{upstream_protocol, Hub, UPSTREAM_PROTOCOL_UNKNOWN};
pub use sse::{SseDecoder, SseEvent};
pub use structured_output::{
apply_schema_limits, close_object_schemas, json_schema_from_response_format,
response_into_fake_stream_chunks, seal_object_schemas, unwrap_json_tool_call, SchemaLimits,
ANTHROPIC_SCHEMA_LIMITS, GEMINI_OPENAPI_SCHEMA_LIMITS, JSON_TOOL_DESCRIPTION, JSON_TOOL_NAME,
};
pub use upstream_headers::{
apply_request_headers, client_header_forwardable, header_forward_blocked,
resolve_default_headers, resolve_extra_headers, CallerIdentity, ForwardedClientHeaders,
Expand Down
Loading