Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,13 @@ because the official backend rejects any deviation with HTTP 400.

The compatibility layer has two independent stages.

Stage A runs only for an OpenAI-official parent request that belongs to a
MultiRouter with at least one enabled third-party or ownership-ambiguous route.
It removes only `parameters.properties.message.encrypted` from the non-reserved
Stage A runs for any Codex parent request that belongs to a MultiRouter with at
least one enabled third-party or ownership-ambiguous route. It removes only
`parameters.properties.message.encrypted` from the non-reserved
`agents.spawn_agent`, `agents.send_message`, and `agents.followup_task` schemas.
It handles both top-level `tools` and Responses Lite `additional_tools`, including
nested namespace containers. It never changes `collaboration.*`, unrelated
functions, unrelated `encrypted` fields, third-party parent requests, or pure
official routers.
functions, unrelated `encrypted` fields, or pure official routers.

Stage B runs only after the effective child route is known to be third-party. It
projects every plaintext `agent_message` into a standard Responses
Expand Down Expand Up @@ -53,11 +52,10 @@ retain OpenAI encryption.
## Acceptance

- Reserved `collaboration.*` schemas are byte/schema preserving.
- Mixed-router official parents produce plaintext arguments only for `agents.*`.
- Mixed-router parents produce plaintext arguments only for `agents.*`.
- Top-level tools and Lite `additional_tools` behave identically.
- Third-party child inputs contain ordinary user messages with readable payloads.
- Opaque child ciphertext returns an explicit compatibility error.
- OpenAI-to-OpenAI remains encrypted.
- Pure OpenAI-to-OpenAI routers remain encrypted.
- OpenAI-to-Qwen and OpenAI-to-DeepSeek children return a unique nonce plus real
tool output in live tests after a full CCSwitchMulti and Codex restart.

34 changes: 19 additions & 15 deletions src-tauri/src/proxy/forwarder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2551,7 +2551,6 @@ impl RequestForwarder {
if should_make_codex_v2_agents_plaintext(
app_type,
codex_router_provider,
normalize_codex_oauth_responses,
) {
let changed = super::providers::openai_compat::make_codex_v2_agents_messages_plaintext(
&mut request_body,
Expand Down Expand Up @@ -7150,10 +7149,8 @@ fn codex_provider_has_routing_config(provider: &Provider) -> bool {
fn should_make_codex_v2_agents_plaintext(
app_type: &AppType,
router_provider: &Provider,
official_oauth_request: bool,
) -> bool {
matches!(app_type, AppType::Codex)
&& official_oauth_request
&& super::providers::codex_multirouter_needs_plaintext_v2_collaboration(router_provider)
}

Expand Down Expand Up @@ -8385,7 +8382,7 @@ mod tests {
}

#[test]
fn agents_plaintext_rewrite_requires_codex_mixed_router_and_official_parent() {
fn agents_plaintext_rewrite_applies_to_any_codex_mixed_router() {
let mut mixed = test_provider_with_type(None);
mixed.settings_config = json!({
"codexRouting": {
Expand All @@ -8398,18 +8395,11 @@ mod tests {
});
assert!(should_make_codex_v2_agents_plaintext(
&AppType::Codex,
&mixed,
true
));
assert!(!should_make_codex_v2_agents_plaintext(
&AppType::Codex,
&mixed,
false
&mixed
));
assert!(!should_make_codex_v2_agents_plaintext(
&AppType::Claude,
&mixed,
true
&mixed
));

let mut official_only = test_provider_with_type(None);
Expand All @@ -8424,8 +8414,22 @@ mod tests {
});
assert!(!should_make_codex_v2_agents_plaintext(
&AppType::Codex,
&official_only,
true
&official_only
));

let mut third_party_only = test_provider_with_type(None);
third_party_only.settings_config = json!({
"codexRouting": {
"enabled": true,
"routes": [{
"enabled": true,
"upstream": {"auth": {"source": "provider_config"}}
}]
}
});
assert!(should_make_codex_v2_agents_plaintext(
&AppType::Codex,
&third_party_only
));
}

Expand Down
Loading
Loading