fix(responses): replay DeepSeek opaque reasoning state

This commit is contained in:
ZheFox
2026-08-20 00:40:48 +08:00
parent d21d8ce9f5
commit bef282cfee
22 changed files with 516 additions and 51 deletions
@@ -145,6 +145,7 @@ pub use rules::{
pub use same_format_provider::{
build_same_format_provider_headers, build_same_format_provider_request_body,
build_same_format_provider_request_body_with_compatibility_report,
build_same_format_provider_request_body_with_compatibility_report_and_reasoning_replay_policy,
build_same_format_provider_upstream_url, classify_same_format_provider_request_behavior,
classify_same_format_provider_request_behavior_for_operation,
enforce_same_format_provider_api_operation_body_policy,
@@ -207,15 +207,32 @@ pub fn classify_same_format_provider_request_behavior_for_operation(
pub fn build_same_format_provider_request_body(
input: SameFormatProviderRequestBodyInput<'_>,
) -> Option<Value> {
build_same_format_provider_request_body_inner(input, None)
build_same_format_provider_request_body_inner(
input,
None,
aether_ai_formats::OpenAiResponsesReasoningReplayPolicy::OpenAiItemIds,
)
}
pub fn build_same_format_provider_request_body_with_compatibility_report(
input: SameFormatProviderRequestBodyInput<'_>,
) -> Option<SameFormatProviderRequestBodyOutput> {
build_same_format_provider_request_body_with_compatibility_report_and_reasoning_replay_policy(
input,
aether_ai_formats::OpenAiResponsesReasoningReplayPolicy::OpenAiItemIds,
)
}
pub fn build_same_format_provider_request_body_with_compatibility_report_and_reasoning_replay_policy(
input: SameFormatProviderRequestBodyInput<'_>,
reasoning_replay_policy: aether_ai_formats::OpenAiResponsesReasoningReplayPolicy,
) -> Option<SameFormatProviderRequestBodyOutput> {
let mut compatibility_edits = Vec::new();
let body =
build_same_format_provider_request_body_inner(input, Some(&mut compatibility_edits))?;
let body = build_same_format_provider_request_body_inner(
input,
Some(&mut compatibility_edits),
reasoning_replay_policy,
)?;
Some(SameFormatProviderRequestBodyOutput {
body,
compatibility_edits,
@@ -239,6 +256,7 @@ pub fn enforce_same_format_provider_api_operation_body_policy(
fn build_same_format_provider_request_body_inner(
input: SameFormatProviderRequestBodyInput<'_>,
mut compatibility_edits: Option<&mut Vec<SameFormatProviderCompatibilityEdit>>,
reasoning_replay_policy: aether_ai_formats::OpenAiResponsesReasoningReplayPolicy,
) -> Option<Value> {
if let Some(kiro_auth_config) = input.kiro_auth_config {
let body = build_kiro_provider_request_body(
@@ -437,9 +455,10 @@ fn build_same_format_provider_request_body_inner(
);
}
let stripped_reasoning_items =
aether_ai_formats::strip_incompatible_openai_responses_reasoning_items(
aether_ai_formats::strip_incompatible_openai_responses_reasoning_items_with_policy(
&mut provider_request_body,
input.provider_api_format,
reasoning_replay_policy,
);
if stripped_reasoning_items > 0 {
record_compatibility_edit(
@@ -466,7 +485,7 @@ fn build_same_format_provider_request_body_inner(
) {
return None;
}
if aether_ai_formats::finalize_openai_provider_request(
if aether_ai_formats::finalize_openai_provider_request_with_codex_model_capabilities_and_reasoning_replay_policy(
&mut provider_request_body,
aether_ai_formats::OpenAiProviderRequestFinalization {
source_api_format: input.provider_api_format,
@@ -478,6 +497,8 @@ fn build_same_format_provider_request_body_inner(
upstream_is_stream: input.upstream_is_stream,
require_body_stream_field,
},
None,
reasoning_replay_policy,
)
.is_err()
{
@@ -2099,6 +2120,74 @@ mod tests {
}));
}
#[test]
fn same_format_responses_body_preserves_deepseek_opaque_reasoning_replay() {
let reasoning_items = (0..66)
.map(|index| {
json!({
"type": "reasoning",
"encrypted_content": format!("opaque-deepseek-state-{index}"),
"content": [{
"type": "reasoning_text",
"text": format!("provider thinking state {index}")
}]
})
})
.chain(std::iter::once(json!({
"type": "message",
"role": "user",
"content": "continue"
})))
.collect::<Vec<_>>();
let request_body = json!({
"model": "deepseek-v4-flash",
"input": reasoning_items
});
let input = SameFormatProviderRequestBodyInput {
body_json: &request_body,
mapped_model: "deepseek-v4-flash",
client_api_format: "openai:responses",
provider_api_format: "openai:responses",
source_model: Some("deepseek-v4-flash"),
family: SameFormatProviderFamily::Standard,
body_rules: None,
request_headers: None,
upstream_is_stream: false,
force_body_stream_field: false,
kiro_auth_config: None,
is_claude_code: false,
enable_model_directives: false,
};
let deepseek =
build_same_format_provider_request_body_with_compatibility_report_and_reasoning_replay_policy(
input,
aether_ai_formats::OpenAiResponsesReasoningReplayPolicy::DeepSeekOpaque,
)
.expect("DeepSeek same-format Responses body should build");
let strict = build_same_format_provider_request_body_with_compatibility_report(input)
.expect("strict same-format Responses body should build");
assert_eq!(
deepseek.body["input"]
.as_array()
.expect("DeepSeek input array")
.iter()
.filter(|item| item["type"] == "reasoning")
.count(),
66
);
assert_eq!(
strict.body["input"]
.as_array()
.expect("strict input array")
.iter()
.filter(|item| item["type"] == "reasoning")
.count(),
0
);
}
#[test]
fn same_format_stream_policy_wins_after_body_rules() {
let body_rules = json!([