mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-08 18:37:46 +08:00
fix(responses): replay DeepSeek opaque reasoning state
This commit is contained in:
@@ -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!([
|
||||
|
||||
Reference in New Issue
Block a user