mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-11 11:49:50 +08:00
fix(gateway): support claude_code cross-format Claude messages
This commit is contained in:
@@ -6,6 +6,7 @@ use crate::auth::{
|
||||
build_claude_passthrough_headers, build_complete_passthrough_headers_with_auth,
|
||||
build_openai_passthrough_headers, build_passthrough_headers, ensure_upstream_auth_header,
|
||||
};
|
||||
use crate::claude_code::build_claude_code_passthrough_headers;
|
||||
use crate::headers::force_identity_accept_encoding;
|
||||
use crate::rules::{
|
||||
apply_local_body_rules, apply_local_body_rules_with_request_headers,
|
||||
@@ -224,7 +225,23 @@ pub fn build_standard_provider_request_headers(
|
||||
) -> Option<StandardProviderRequestHeaders> {
|
||||
let uses_vertex_query_auth =
|
||||
uses_vertex_api_key_query_auth(input.transport, input.provider_api_format);
|
||||
let mut headers = if input.same_format {
|
||||
let is_claude_code_messages = input
|
||||
.transport
|
||||
.provider
|
||||
.provider_type
|
||||
.trim()
|
||||
.eq_ignore_ascii_case("claude_code")
|
||||
&& aether_ai_formats::normalize_api_format_alias(input.provider_api_format)
|
||||
== "claude:messages";
|
||||
let mut headers = if is_claude_code_messages {
|
||||
build_claude_code_passthrough_headers(
|
||||
input.headers,
|
||||
input.auth_header,
|
||||
input.auth_value,
|
||||
input.extra_headers,
|
||||
input.upstream_is_stream,
|
||||
)
|
||||
} else if input.same_format {
|
||||
build_complete_passthrough_headers_with_auth(
|
||||
input.headers,
|
||||
input.auth_header,
|
||||
@@ -473,6 +490,41 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn builds_claude_code_identity_headers_for_cross_format_messages() {
|
||||
let mut transport = sample_transport("claude:messages");
|
||||
transport.provider.provider_type = "claude_code".to_string();
|
||||
let resolved =
|
||||
build_standard_provider_request_headers(StandardProviderRequestHeadersInput {
|
||||
transport: &transport,
|
||||
provider_api_format: "claude:messages",
|
||||
same_format: false,
|
||||
headers: &HeaderMap::new(),
|
||||
auth_header: "authorization",
|
||||
auth_value: "Bearer oauth-token",
|
||||
extra_headers: &BTreeMap::new(),
|
||||
header_rules: None,
|
||||
provider_request_body: &json!({"model":"claude-opus-4-6"}),
|
||||
original_request_body: &json!({"model":"gpt-source"}),
|
||||
upstream_is_stream: true,
|
||||
})
|
||||
.expect("Claude Code headers should build");
|
||||
|
||||
assert_eq!(resolved.headers.get("x-app"), Some(&"cli".to_string()));
|
||||
assert!(resolved
|
||||
.headers
|
||||
.get("user-agent")
|
||||
.is_some_and(|value| value.starts_with("claude-cli/")));
|
||||
assert!(resolved
|
||||
.headers
|
||||
.get("anthropic-beta")
|
||||
.is_some_and(|value| value.contains("claude-code-20250219")));
|
||||
assert_eq!(
|
||||
resolved.headers.get("authorization"),
|
||||
Some(&"Bearer oauth-token".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn endpoint_header_rules_do_not_override_protected_authorization() {
|
||||
let mut transport = sample_transport("openai:responses");
|
||||
|
||||
Reference in New Issue
Block a user