mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
Forward thread originators from standalone extensions (#33677)
## Why Standalone web search and image requests need to preserve the trusted, thread-scoped originator used for billing attribution. ## What changed - Seed extension data with the resolved thread originator and recognize `codex_work_cca` and `chatgpt_cca` service names as originators. - Forward non-default originators from the web search and image generation extensions with the shared originator-header helper. ## Testing - Cover originator resolution, header validation, and forwarding for web search, image generation, and image editing. GitOrigin-RevId: 165dace8e4d24e4bd92f234bff5ec77a21a7ff6e
This commit is contained in:
1 parent
71448a29e7
commit
78ba047bda
16 files changed
+248
-44
No files matched your search
@@ -127,6 +127,26 @@ pub fn originator() -> Originator {
|
||||
get_originator_value(/*provided*/ None)
|
||||
}
|
||||
|
||||
/// Adds a valid, non-default thread originator override to request headers.
|
||||
///
|
||||
/// The default client already supplies the process originator. Thread-scoped callers should use
|
||||
/// this helper to override that value only when the thread originator differs.
|
||||
pub fn add_originator_header(headers: &mut HeaderMap, originator_value: &str) {
|
||||
let default_originator = originator();
|
||||
if originator_value == default_originator.value.as_str() {
|
||||
return;
|
||||
}
|
||||
|
||||
match HeaderValue::from_str(originator_value) {
|
||||
Ok(header_value) => {
|
||||
headers.insert("originator", header_value);
|
||||
}
|
||||
Err(err) => {
|
||||
tracing::warn!("ignoring invalid thread originator header value: {err}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_first_party_originator(originator_value: &str) -> bool {
|
||||
originator_value == DEFAULT_ORIGINATOR
|
||||
|| originator_value == "codex-tui"
|
||||
|
||||
@@ -67,6 +67,54 @@ fn is_first_party_chat_originator_matches_known_values() {
|
||||
assert_eq!(is_first_party_chat_originator("codex_vscode"), false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_originator_header_inserts_non_default_originator() {
|
||||
let default_originator = originator();
|
||||
let thread_originator = if default_originator.value == "chatgpt_cca" {
|
||||
"codex_work_cca"
|
||||
} else {
|
||||
"chatgpt_cca"
|
||||
};
|
||||
let mut headers = HeaderMap::new();
|
||||
|
||||
add_originator_header(&mut headers, thread_originator);
|
||||
|
||||
assert_eq!(
|
||||
headers
|
||||
.get("originator")
|
||||
.and_then(|value| value.to_str().ok()),
|
||||
Some(thread_originator)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_originator_header_preserves_provider_default() {
|
||||
let default_originator = originator();
|
||||
let mut headers = HeaderMap::new();
|
||||
headers.insert(
|
||||
"originator",
|
||||
HeaderValue::from_static("provider-originator"),
|
||||
);
|
||||
|
||||
add_originator_header(&mut headers, &default_originator.value);
|
||||
|
||||
assert_eq!(
|
||||
headers
|
||||
.get("originator")
|
||||
.and_then(|value| value.to_str().ok()),
|
||||
Some("provider-originator")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_originator_header_omits_invalid_originator() {
|
||||
let mut headers = HeaderMap::new();
|
||||
|
||||
add_originator_header(&mut headers, "invalid\noriginator");
|
||||
|
||||
assert!(headers.is_empty());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_client_sets_default_headers() {
|
||||
skip_if_no_network!();
|
||||
|
||||
Reference in new issue
Block a user