mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-07 01:47:47 +08:00
780 lines
22 KiB
Rust
780 lines
22 KiB
Rust
use std::collections::BTreeMap;
|
|
|
|
use super::{
|
|
apply_codex_openai_responses_identity_headers, apply_codex_openai_responses_special_body_edits,
|
|
apply_codex_openai_special_headers, codex_model_capabilities,
|
|
};
|
|
use crate::ai_serving::planner::standard::{
|
|
build_cross_format_openai_responses_request_body, build_local_openai_responses_request_body,
|
|
};
|
|
use http::{HeaderMap, HeaderValue};
|
|
use serde_json::json;
|
|
|
|
#[test]
|
|
fn search_uses_live_codex_model_catalog_capabilities() {
|
|
let metadata = crate::ai_serving::build_codex_model_catalog_metadata(&[json!({
|
|
"slug": "gpt-search-custom",
|
|
"default_reasoning_level": "low",
|
|
"supported_reasoning_levels": [
|
|
{"effort": "low"},
|
|
{"effort": "max"}
|
|
],
|
|
"supports_parallel_tool_calls": true
|
|
})]);
|
|
|
|
let capabilities = codex_model_capabilities(
|
|
"codex",
|
|
"openai:search",
|
|
"gpt-search-custom",
|
|
"gpt-search-custom",
|
|
Some(&metadata),
|
|
)
|
|
.expect("Search should resolve capabilities from the Codex model catalog");
|
|
|
|
assert_eq!(
|
|
capabilities.default_reasoning_effort.as_deref(),
|
|
Some("low")
|
|
);
|
|
assert_eq!(
|
|
capabilities.supported_reasoning_efforts,
|
|
vec!["low".to_string(), "max".to_string()]
|
|
);
|
|
assert!(codex_model_capabilities(
|
|
"codex",
|
|
"openai:chat",
|
|
"gpt-search-custom",
|
|
"gpt-search-custom",
|
|
Some(&metadata),
|
|
)
|
|
.is_none());
|
|
}
|
|
|
|
#[test]
|
|
fn applies_codex_defaults_when_body_rules_do_not_handle_fields() {
|
|
let mut body = json!({
|
|
"model": "gpt-5.4",
|
|
"max_output_tokens": 128,
|
|
"temperature": 0.3,
|
|
"top_p": 0.9,
|
|
"metadata": {"client": "desktop"},
|
|
"store": true
|
|
});
|
|
|
|
apply_codex_openai_responses_special_body_edits(
|
|
&mut body,
|
|
"codex",
|
|
"openai:responses",
|
|
None,
|
|
None,
|
|
);
|
|
|
|
assert!(body.get("max_output_tokens").is_none());
|
|
assert!(body.get("temperature").is_none());
|
|
assert!(body.get("top_p").is_none());
|
|
assert!(body.get("metadata").is_none());
|
|
assert_eq!(body["store"], false);
|
|
assert!(body.get("instructions").is_none());
|
|
assert_eq!(body["include"], json!(["reasoning.encrypted_content"]));
|
|
assert_eq!(body["parallel_tool_calls"], true);
|
|
assert_eq!(body["reasoning"]["effort"], "medium");
|
|
assert!(body["reasoning"].get("summary").is_none());
|
|
}
|
|
|
|
#[test]
|
|
fn local_openai_responses_codex_body_wraps_string_input_for_backend() {
|
|
let body = json!({
|
|
"model": "gpt-5",
|
|
"input": "hello"
|
|
});
|
|
|
|
let provider_request_body = build_local_openai_responses_request_body(
|
|
&body,
|
|
"gpt-5-upstream",
|
|
false,
|
|
false,
|
|
"codex",
|
|
"openai:responses",
|
|
None,
|
|
Some("key-123"),
|
|
&HeaderMap::new(),
|
|
false,
|
|
)
|
|
.expect("codex local openai responses body should build");
|
|
|
|
assert_eq!(
|
|
provider_request_body["input"],
|
|
json!([{
|
|
"type": "message",
|
|
"role": "user",
|
|
"content": [{
|
|
"type": "input_text",
|
|
"text": "hello"
|
|
}]
|
|
}])
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn strips_store_for_compact_even_when_body_rules_handle_it() {
|
|
let body_rules = json!([
|
|
{"action":"set","path":"store","value":true},
|
|
{"action":"set","path":"instructions","value":"Keep custom"},
|
|
{"action":"set","path":"metadata","value":{"client":"desktop","mode":"custom"}},
|
|
{"action":"set","path":"top_p","value":0.5}
|
|
]);
|
|
let mut body = json!({
|
|
"model": "gpt-5.4",
|
|
"max_output_tokens": 128,
|
|
"metadata": {"client": "desktop", "mode": "custom"},
|
|
"store": true,
|
|
"instructions": "Keep custom",
|
|
"top_p": 0.5
|
|
});
|
|
|
|
apply_codex_openai_responses_special_body_edits(
|
|
&mut body,
|
|
"codex",
|
|
"openai:responses:compact",
|
|
Some(&body_rules),
|
|
None,
|
|
);
|
|
|
|
assert!(body.get("max_output_tokens").is_none());
|
|
assert!(body.get("store").is_none());
|
|
assert_eq!(body["instructions"], "Keep custom");
|
|
assert!(body.get("metadata").is_none());
|
|
assert!(body.get("top_p").is_none());
|
|
assert_eq!(body["parallel_tool_calls"], true);
|
|
assert!(body.as_object().is_some_and(|object| {
|
|
object.keys().all(|field| {
|
|
matches!(
|
|
field.as_str(),
|
|
"model"
|
|
| "input"
|
|
| "instructions"
|
|
| "tools"
|
|
| "parallel_tool_calls"
|
|
| "reasoning"
|
|
| "service_tier"
|
|
| "prompt_cache_key"
|
|
| "text"
|
|
)
|
|
})
|
|
}));
|
|
}
|
|
|
|
#[test]
|
|
fn does_not_synthesize_prompt_cache_key_from_api_key_identity() {
|
|
let mut body = json!({
|
|
"model": "gpt-5",
|
|
"input": "hello",
|
|
});
|
|
|
|
apply_codex_openai_responses_special_body_edits(
|
|
&mut body,
|
|
"codex",
|
|
"openai:responses",
|
|
None,
|
|
Some("key-123"),
|
|
);
|
|
|
|
assert!(body.get("prompt_cache_key").is_none());
|
|
}
|
|
|
|
#[test]
|
|
fn adapts_generic_prompt_cache_key_to_codex_native_identity() {
|
|
let mut body = json!({
|
|
"model": "gpt-5",
|
|
"input": "hello",
|
|
"prompt_cache_key": "ltm-pc-v2-5557e02f5c9b447a97673ba330dbe77a",
|
|
});
|
|
|
|
apply_codex_openai_responses_special_body_edits(
|
|
&mut body,
|
|
"codex",
|
|
"openai:responses",
|
|
None,
|
|
Some("key-123"),
|
|
);
|
|
|
|
let expected_identity = "d9c5d122-7c1c-5fb1-ba9d-656062eda44e";
|
|
assert_eq!(body["prompt_cache_key"], expected_identity);
|
|
assert_eq!(body["client_metadata"]["session_id"], expected_identity);
|
|
assert_eq!(body["client_metadata"]["thread_id"], expected_identity);
|
|
}
|
|
|
|
#[test]
|
|
fn preserves_native_codex_cache_identity_and_metadata() {
|
|
let mut body = json!({
|
|
"model": "gpt-5",
|
|
"input": "hello",
|
|
"prompt_cache_key": "guardian:parent-thread",
|
|
"client_metadata": {
|
|
"session_id": "native-session",
|
|
"thread_id": "native-thread",
|
|
"turn_id": "native-turn"
|
|
}
|
|
});
|
|
let expected = body.clone();
|
|
|
|
apply_codex_openai_responses_special_body_edits(
|
|
&mut body,
|
|
"codex",
|
|
"openai:responses",
|
|
None,
|
|
Some("key-123"),
|
|
);
|
|
|
|
assert_eq!(body["prompt_cache_key"], expected["prompt_cache_key"]);
|
|
assert_eq!(body["client_metadata"], expected["client_metadata"]);
|
|
}
|
|
|
|
#[test]
|
|
fn preserves_uuid_prompt_cache_key_while_completing_codex_identity() {
|
|
let identity = "172c39e6-c0a0-5a70-8b63-e0f8e0d185a3";
|
|
let mut body = json!({
|
|
"model": "gpt-5.6-luna",
|
|
"input": "hello",
|
|
"prompt_cache_key": identity
|
|
});
|
|
|
|
apply_codex_openai_responses_special_body_edits(
|
|
&mut body,
|
|
"codex",
|
|
"openai:responses",
|
|
None,
|
|
None,
|
|
);
|
|
|
|
assert_eq!(body["prompt_cache_key"], identity);
|
|
assert_eq!(body["client_metadata"]["session_id"], identity);
|
|
assert_eq!(body["client_metadata"]["thread_id"], identity);
|
|
}
|
|
|
|
#[test]
|
|
fn keeps_codex_prompt_cache_domains_distinct() {
|
|
let mut first = json!({
|
|
"model": "gpt-5.6-luna",
|
|
"input": "hello",
|
|
"prompt_cache_key": "tenant-a"
|
|
});
|
|
let mut second = json!({
|
|
"model": "gpt-5.6-luna",
|
|
"input": "hello",
|
|
"prompt_cache_key": "tenant-b"
|
|
});
|
|
|
|
for body in [&mut first, &mut second] {
|
|
apply_codex_openai_responses_special_body_edits(
|
|
body,
|
|
"codex",
|
|
"openai:responses",
|
|
None,
|
|
None,
|
|
);
|
|
}
|
|
|
|
assert_ne!(first["prompt_cache_key"], second["prompt_cache_key"]);
|
|
assert_eq!(
|
|
first["prompt_cache_key"],
|
|
first["client_metadata"]["session_id"]
|
|
);
|
|
assert_eq!(
|
|
second["prompt_cache_key"],
|
|
second["client_metadata"]["session_id"]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn completes_partial_and_null_codex_client_metadata() {
|
|
let mut partial = json!({
|
|
"model": "gpt-5.6-luna",
|
|
"input": "hello",
|
|
"prompt_cache_key": "generic-affinity",
|
|
"client_metadata": {
|
|
"thread_id": "native-thread",
|
|
"caller": "sdk"
|
|
}
|
|
});
|
|
let mut null_metadata = json!({
|
|
"model": "gpt-5.6-luna",
|
|
"input": "hello",
|
|
"prompt_cache_key": "generic-affinity",
|
|
"client_metadata": null
|
|
});
|
|
let mut null_session = json!({
|
|
"model": "gpt-5.6-luna",
|
|
"input": "hello",
|
|
"prompt_cache_key": "generic-affinity",
|
|
"client_metadata": {
|
|
"session_id": null,
|
|
"thread_id": null,
|
|
"caller": "sdk"
|
|
}
|
|
});
|
|
|
|
for body in [&mut partial, &mut null_metadata, &mut null_session] {
|
|
apply_codex_openai_responses_special_body_edits(
|
|
body,
|
|
"codex",
|
|
"openai:responses",
|
|
None,
|
|
None,
|
|
);
|
|
}
|
|
|
|
assert_eq!(partial["client_metadata"]["thread_id"], "native-thread");
|
|
assert_eq!(partial["client_metadata"]["caller"], "sdk");
|
|
assert_eq!(
|
|
partial["client_metadata"]["session_id"],
|
|
partial["prompt_cache_key"]
|
|
);
|
|
assert_eq!(
|
|
null_metadata["client_metadata"]["session_id"],
|
|
null_metadata["prompt_cache_key"]
|
|
);
|
|
assert_eq!(
|
|
null_metadata["client_metadata"]["thread_id"],
|
|
null_metadata["prompt_cache_key"]
|
|
);
|
|
assert_eq!(
|
|
null_session["client_metadata"]["session_id"],
|
|
null_session["prompt_cache_key"]
|
|
);
|
|
assert_eq!(
|
|
null_session["client_metadata"]["thread_id"],
|
|
null_session["prompt_cache_key"]
|
|
);
|
|
assert_eq!(null_session["client_metadata"]["caller"], "sdk");
|
|
}
|
|
|
|
#[test]
|
|
fn leaves_malformed_codex_client_metadata_unchanged() {
|
|
let mut body = json!({
|
|
"model": "gpt-5.6-luna",
|
|
"input": "hello",
|
|
"prompt_cache_key": "generic-affinity",
|
|
"client_metadata": "invalid"
|
|
});
|
|
let mut malformed_fields = json!({
|
|
"model": "gpt-5.6-luna",
|
|
"input": "hello",
|
|
"prompt_cache_key": "generic-affinity",
|
|
"client_metadata": {
|
|
"session_id": 42,
|
|
"thread_id": ""
|
|
}
|
|
});
|
|
let expected_malformed_metadata = malformed_fields["client_metadata"].clone();
|
|
|
|
for candidate in [&mut body, &mut malformed_fields] {
|
|
apply_codex_openai_responses_special_body_edits(
|
|
candidate,
|
|
"codex",
|
|
"openai:responses",
|
|
None,
|
|
None,
|
|
);
|
|
}
|
|
|
|
assert_eq!(body["prompt_cache_key"], "generic-affinity");
|
|
assert_eq!(body["client_metadata"], "invalid");
|
|
assert_eq!(malformed_fields["prompt_cache_key"], "generic-affinity");
|
|
assert_eq!(
|
|
malformed_fields["client_metadata"],
|
|
expected_malformed_metadata
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn limits_prompt_cache_identity_adaptation_to_codex_responses_family() {
|
|
let original = json!({
|
|
"model": "gpt-5.6-luna",
|
|
"input": "hello",
|
|
"prompt_cache_key": "generic-affinity"
|
|
});
|
|
let mut standard_openai = original.clone();
|
|
let mut codex_compact = original.clone();
|
|
|
|
apply_codex_openai_responses_special_body_edits(
|
|
&mut standard_openai,
|
|
"openai",
|
|
"openai:responses",
|
|
None,
|
|
None,
|
|
);
|
|
apply_codex_openai_responses_special_body_edits(
|
|
&mut codex_compact,
|
|
"codex",
|
|
"openai:responses:compact",
|
|
None,
|
|
None,
|
|
);
|
|
|
|
assert_eq!(standard_openai, original);
|
|
assert_ne!(codex_compact["prompt_cache_key"], "generic-affinity");
|
|
assert!(codex_compact.get("client_metadata").is_none());
|
|
}
|
|
|
|
#[test]
|
|
fn chat_to_codex_responses_adapts_prompt_cache_identity_end_to_end() {
|
|
let body = json!({
|
|
"model": "gpt-5.6-luna",
|
|
"messages": [{"role": "user", "content": "hello"}],
|
|
"prompt_cache_key": "ltm-pc-v2-5557e02f5c9b447a97673ba330dbe77a"
|
|
});
|
|
|
|
let provider_request_body = build_cross_format_openai_responses_request_body(
|
|
&body,
|
|
"gpt-5.6-luna",
|
|
"openai:chat",
|
|
"openai:responses",
|
|
true,
|
|
false,
|
|
"codex",
|
|
None,
|
|
None,
|
|
&HeaderMap::new(),
|
|
false,
|
|
)
|
|
.expect("chat to Codex Responses request should build");
|
|
|
|
let expected_identity = "d9c5d122-7c1c-5fb1-ba9d-656062eda44e";
|
|
assert_eq!(provider_request_body["prompt_cache_key"], expected_identity);
|
|
assert_eq!(
|
|
provider_request_body["client_metadata"]["session_id"],
|
|
expected_identity
|
|
);
|
|
assert_eq!(
|
|
provider_request_body["client_metadata"]["thread_id"],
|
|
expected_identity
|
|
);
|
|
|
|
let mut provider_request_headers = BTreeMap::new();
|
|
apply_codex_openai_special_headers(
|
|
&mut provider_request_headers,
|
|
&provider_request_body,
|
|
&HeaderMap::new(),
|
|
"codex",
|
|
"openai:responses",
|
|
Some("trace-codex-cache-identity"),
|
|
None,
|
|
);
|
|
apply_codex_openai_responses_identity_headers(
|
|
&mut provider_request_headers,
|
|
&provider_request_body,
|
|
"codex",
|
|
"openai:responses",
|
|
);
|
|
assert_eq!(
|
|
provider_request_headers
|
|
.get("session-id")
|
|
.map(String::as_str),
|
|
Some(expected_identity)
|
|
);
|
|
assert_eq!(
|
|
provider_request_headers
|
|
.get("thread-id")
|
|
.map(String::as_str),
|
|
Some(expected_identity)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn projects_uuid_prompt_cache_identity_into_missing_session_headers() {
|
|
let mut headers = BTreeMap::new();
|
|
let body = json!({
|
|
"model": "gpt-5",
|
|
"prompt_cache_key": "172c39e6-c0a0-5a70-8b63-e0f8e0d185a3",
|
|
});
|
|
|
|
apply_codex_openai_special_headers(
|
|
&mut headers,
|
|
&body,
|
|
&HeaderMap::new(),
|
|
"codex",
|
|
"openai:responses",
|
|
Some("trace-codex-123"),
|
|
Some(r#"{"account_id":"acc-123","is_fedramp":true}"#),
|
|
);
|
|
apply_codex_openai_responses_identity_headers(&mut headers, &body, "codex", "openai:responses");
|
|
assert_eq!(
|
|
headers.get("chatgpt-account-id"),
|
|
Some(&"acc-123".to_string())
|
|
);
|
|
assert_eq!(headers.get("x-client-request-id"), None);
|
|
assert_eq!(
|
|
headers.get("user-agent").map(String::as_str),
|
|
Some(aether_ai_formats::CODEX_CLIENT_USER_AGENT)
|
|
);
|
|
assert_eq!(headers.get("originator"), Some(&"codex_cli_rs".to_string()));
|
|
assert!(!headers.contains_key("version"));
|
|
assert_eq!(headers.get("x-openai-fedramp"), Some(&"true".to_string()));
|
|
assert_eq!(
|
|
headers.get("session-id").map(String::as_str),
|
|
Some("172c39e6-c0a0-5a70-8b63-e0f8e0d185a3")
|
|
);
|
|
assert_eq!(
|
|
headers.get("thread-id").map(String::as_str),
|
|
Some("172c39e6-c0a0-5a70-8b63-e0f8e0d185a3")
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn projects_native_codex_metadata_for_non_uuid_cache_overrides() {
|
|
let mut headers = BTreeMap::new();
|
|
let body = json!({
|
|
"model": "gpt-5.6-luna",
|
|
"prompt_cache_key": "guardian:parent-thread",
|
|
"client_metadata": {
|
|
"session_id": "019f687b-8e92-7842-9631-d5bf0dba0a3b",
|
|
"thread_id": "019f6d20-1111-7222-8333-444455556666"
|
|
}
|
|
});
|
|
|
|
apply_codex_openai_special_headers(
|
|
&mut headers,
|
|
&body,
|
|
&HeaderMap::new(),
|
|
"codex",
|
|
"openai:responses",
|
|
None,
|
|
None,
|
|
);
|
|
apply_codex_openai_responses_identity_headers(&mut headers, &body, "codex", "openai:responses");
|
|
|
|
assert_eq!(
|
|
headers.get("session-id").map(String::as_str),
|
|
Some("019f687b-8e92-7842-9631-d5bf0dba0a3b")
|
|
);
|
|
assert_eq!(
|
|
headers.get("thread-id").map(String::as_str),
|
|
Some("019f6d20-1111-7222-8333-444455556666")
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn leaves_non_native_cache_keys_out_of_identity_headers() {
|
|
let mut headers = BTreeMap::new();
|
|
let body = json!({
|
|
"model": "gpt-5.6-luna",
|
|
"prompt_cache_key": "generic-cache-key"
|
|
});
|
|
|
|
apply_codex_openai_special_headers(
|
|
&mut headers,
|
|
&body,
|
|
&HeaderMap::new(),
|
|
"codex",
|
|
"openai:responses",
|
|
None,
|
|
None,
|
|
);
|
|
apply_codex_openai_responses_identity_headers(&mut headers, &body, "codex", "openai:responses");
|
|
|
|
assert!(!headers.contains_key("session-id"));
|
|
assert!(!headers.contains_key("thread-id"));
|
|
}
|
|
|
|
#[test]
|
|
fn leaves_malformed_native_metadata_out_of_identity_headers() {
|
|
let mut headers = BTreeMap::new();
|
|
let body = json!({
|
|
"model": "gpt-5.6-luna",
|
|
"prompt_cache_key": "172c39e6-c0a0-5a70-8b63-e0f8e0d185a3",
|
|
"client_metadata": {
|
|
"session_id": 42,
|
|
"thread_id": ""
|
|
}
|
|
});
|
|
|
|
apply_codex_openai_responses_identity_headers(&mut headers, &body, "codex", "openai:responses");
|
|
|
|
assert!(!headers.contains_key("session-id"));
|
|
assert!(!headers.contains_key("thread-id"));
|
|
}
|
|
|
|
#[test]
|
|
fn injects_only_codex_client_headers_for_images_requests() {
|
|
let mut headers = BTreeMap::new();
|
|
apply_codex_openai_special_headers(
|
|
&mut headers,
|
|
&json!({
|
|
"model": "gpt-image-2",
|
|
"prompt": "draw a city"
|
|
}),
|
|
&HeaderMap::new(),
|
|
"codex",
|
|
"openai:image",
|
|
Some("trace-codex-image-123"),
|
|
Some(r#"{"account_id":"acc-123","is_fedramp":true}"#),
|
|
);
|
|
assert_eq!(
|
|
headers.get("chatgpt-account-id"),
|
|
Some(&"acc-123".to_string())
|
|
);
|
|
assert_eq!(
|
|
headers.get("user-agent").map(String::as_str),
|
|
Some(aether_ai_formats::CODEX_CLIENT_USER_AGENT)
|
|
);
|
|
assert_eq!(headers.get("originator"), Some(&"codex_cli_rs".to_string()));
|
|
assert!(!headers.contains_key("version"));
|
|
assert_eq!(headers.get("x-openai-fedramp"), Some(&"true".to_string()));
|
|
for name in ["x-client-request-id", "session-id", "thread-id"] {
|
|
assert!(
|
|
!headers.contains_key(name),
|
|
"unexpected Images header: {name}"
|
|
);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn preserves_client_context_headers_and_enforces_codex_provider_identity() {
|
|
let mut headers = BTreeMap::new();
|
|
headers.insert(
|
|
"x-client-request-id".to_string(),
|
|
"kept-by-rule-request".to_string(),
|
|
);
|
|
headers.insert("session-id".to_string(), "kept-by-rule-session".to_string());
|
|
headers.insert("thread-id".to_string(), "kept-by-rule-thread".to_string());
|
|
headers.insert(
|
|
"chatgpt-account-id".to_string(),
|
|
"configured-spoof".to_string(),
|
|
);
|
|
headers.insert(
|
|
"x-openai-fedramp".to_string(),
|
|
"configured-false".to_string(),
|
|
);
|
|
headers.insert(
|
|
"User-Agent".to_string(),
|
|
"AsyncOpenAI/Python 2.44.0".to_string(),
|
|
);
|
|
headers.insert("ORIGINATOR".to_string(), "sdk-client".to_string());
|
|
let body = json!({
|
|
"model": "gpt-5",
|
|
"prompt_cache_key": "172c39e6-c0a0-5a70-8b63-e0f8e0d185a3",
|
|
});
|
|
let mut original_headers = HeaderMap::new();
|
|
original_headers.insert(
|
|
"x-client-request-id",
|
|
HeaderValue::from_static("user-specified-request"),
|
|
);
|
|
original_headers.insert(
|
|
"session-id",
|
|
HeaderValue::from_static("user-specified-session"),
|
|
);
|
|
original_headers.insert(
|
|
"thread-id",
|
|
HeaderValue::from_static("user-specified-thread"),
|
|
);
|
|
original_headers.insert(
|
|
"user-agent",
|
|
HeaderValue::from_static("user-specified-agent"),
|
|
);
|
|
original_headers.insert(
|
|
"originator",
|
|
HeaderValue::from_static("user-specified-originator"),
|
|
);
|
|
original_headers.insert("version", HeaderValue::from_static("user-version"));
|
|
original_headers.insert("x-openai-fedramp", HeaderValue::from_static("user-fedramp"));
|
|
original_headers.insert(
|
|
"chatgpt-account-id",
|
|
HeaderValue::from_static("user-account"),
|
|
);
|
|
|
|
apply_codex_openai_special_headers(
|
|
&mut headers,
|
|
&body,
|
|
&original_headers,
|
|
"codex",
|
|
"openai:responses",
|
|
Some("trace-codex-123"),
|
|
Some(r#"{"account_id":"acc-123","is_fedramp":true}"#),
|
|
);
|
|
apply_codex_openai_responses_identity_headers(&mut headers, &body, "codex", "openai:responses");
|
|
|
|
assert_eq!(
|
|
headers.get("x-client-request-id"),
|
|
Some(&"kept-by-rule-request".to_string())
|
|
);
|
|
assert_eq!(
|
|
headers.get("user-agent").map(String::as_str),
|
|
Some(aether_ai_formats::CODEX_CLIENT_USER_AGENT)
|
|
);
|
|
assert_eq!(headers.get("originator"), Some(&"codex_cli_rs".to_string()));
|
|
assert_eq!(
|
|
headers
|
|
.keys()
|
|
.filter(|name| name.eq_ignore_ascii_case("user-agent"))
|
|
.count(),
|
|
1
|
|
);
|
|
assert_eq!(
|
|
headers
|
|
.keys()
|
|
.filter(|name| name.eq_ignore_ascii_case("originator"))
|
|
.count(),
|
|
1
|
|
);
|
|
assert!(!headers.contains_key("version"));
|
|
assert_eq!(
|
|
headers.get("chatgpt-account-id"),
|
|
Some(&"acc-123".to_string())
|
|
);
|
|
assert_eq!(headers.get("x-openai-fedramp"), Some(&"true".to_string()));
|
|
assert_eq!(
|
|
headers.get("session-id"),
|
|
Some(&"kept-by-rule-session".to_string())
|
|
);
|
|
assert_eq!(
|
|
headers.get("thread-id"),
|
|
Some(&"kept-by-rule-thread".to_string())
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn compact_projects_uuid_prompt_cache_identity_into_session_headers() {
|
|
let mut headers = BTreeMap::new();
|
|
let body = json!({
|
|
"model": "gpt-5",
|
|
"prompt_cache_key": "172c39e6-c0a0-5a70-8b63-e0f8e0d185a3",
|
|
});
|
|
|
|
apply_codex_openai_special_headers(
|
|
&mut headers,
|
|
&body,
|
|
&HeaderMap::new(),
|
|
"codex",
|
|
"openai:responses:compact",
|
|
Some("trace-codex-compact-123"),
|
|
Some(r#"{"account_id":"acc-123","is_fedramp":true}"#),
|
|
);
|
|
apply_codex_openai_responses_identity_headers(
|
|
&mut headers,
|
|
&body,
|
|
"codex",
|
|
"openai:responses:compact",
|
|
);
|
|
|
|
assert_eq!(
|
|
headers.get("chatgpt-account-id"),
|
|
Some(&"acc-123".to_string())
|
|
);
|
|
assert_eq!(headers.get("x-client-request-id"), None);
|
|
assert_eq!(
|
|
headers.get("user-agent").map(String::as_str),
|
|
Some(aether_ai_formats::CODEX_CLIENT_USER_AGENT)
|
|
);
|
|
assert_eq!(headers.get("originator"), Some(&"codex_cli_rs".to_string()));
|
|
assert!(!headers.contains_key("version"));
|
|
assert_eq!(headers.get("x-openai-fedramp"), Some(&"true".to_string()));
|
|
assert_eq!(
|
|
headers.get("session-id").map(String::as_str),
|
|
Some("172c39e6-c0a0-5a70-8b63-e0f8e0d185a3")
|
|
);
|
|
assert_eq!(
|
|
headers.get("thread-id").map(String::as_str),
|
|
Some("172c39e6-c0a0-5a70-8b63-e0f8e0d185a3")
|
|
);
|
|
}
|