feat: add model directive management

This commit is contained in:
fawney19
2026-05-03 14:48:25 +08:00
parent fe27fb17fb
commit c4ea042eb4
53 changed files with 2654 additions and 181 deletions
@@ -4,8 +4,8 @@ use crate::ai_serving::transport::apply_standard_provider_request_body_rules;
use crate::ai_serving::{
apply_codex_openai_responses_special_body_edits,
apply_openai_responses_compact_special_body_edits,
build_cross_format_openai_chat_request_body as surface_build_cross_format_openai_chat_request_body,
build_local_openai_chat_request_body as surface_build_local_openai_chat_request_body,
build_cross_format_openai_chat_request_body_with_model_directives as surface_build_cross_format_openai_chat_request_body,
build_local_openai_chat_request_body_with_model_directives as surface_build_local_openai_chat_request_body,
GatewayProviderTransportSnapshot,
};
@@ -14,9 +14,14 @@ pub(crate) fn build_local_openai_chat_request_body(
mapped_model: &str,
upstream_is_stream: bool,
body_rules: Option<&Value>,
enable_model_directives: bool,
) -> Option<Value> {
let provider_request_body =
surface_build_local_openai_chat_request_body(body_json, mapped_model, upstream_is_stream)?;
let provider_request_body = surface_build_local_openai_chat_request_body(
body_json,
mapped_model,
upstream_is_stream,
enable_model_directives,
)?;
apply_standard_provider_request_body_rules(provider_request_body, body_rules, body_json)
}
@@ -35,12 +40,14 @@ pub(crate) fn build_cross_format_openai_chat_request_body(
upstream_is_stream: bool,
body_rules: Option<&Value>,
user_api_key_id: Option<&str>,
enable_model_directives: bool,
) -> Option<Value> {
let provider_request_body = surface_build_cross_format_openai_chat_request_body(
body_json,
mapped_model,
provider_api_format,
upstream_is_stream,
enable_model_directives,
)?;
let mut provider_request_body =
apply_standard_provider_request_body_rules(provider_request_body, body_rules, body_json)?;
@@ -4,8 +4,8 @@ use crate::ai_serving::transport::apply_standard_provider_request_body_rules;
use crate::ai_serving::{
apply_codex_openai_responses_special_body_edits,
apply_openai_responses_compact_special_body_edits,
build_cross_format_openai_responses_request_body as surface_build_cross_format_openai_responses_request_body,
build_local_openai_responses_request_body as surface_build_local_openai_responses_request_body,
build_cross_format_openai_responses_request_body_with_model_directives as surface_build_cross_format_openai_responses_request_body,
build_local_openai_responses_request_body_with_model_directives as surface_build_local_openai_responses_request_body,
GatewayProviderTransportSnapshot,
};
@@ -17,11 +17,13 @@ pub(crate) fn build_local_openai_responses_request_body(
provider_api_format: &str,
body_rules: Option<&Value>,
user_api_key_id: Option<&str>,
enable_model_directives: bool,
) -> Option<Value> {
let provider_request_body = surface_build_local_openai_responses_request_body(
body_json,
mapped_model,
require_streaming,
enable_model_directives,
)?;
let mut provider_request_body =
apply_standard_provider_request_body_rules(provider_request_body, body_rules, body_json)?;
@@ -48,6 +50,7 @@ pub(crate) fn build_cross_format_openai_responses_request_body(
provider_type: &str,
body_rules: Option<&Value>,
user_api_key_id: Option<&str>,
enable_model_directives: bool,
) -> Option<Value> {
let provider_request_body = surface_build_cross_format_openai_responses_request_body(
body_json,
@@ -55,6 +58,7 @@ pub(crate) fn build_cross_format_openai_responses_request_body(
client_api_format,
provider_api_format,
upstream_is_stream,
enable_model_directives,
)?;
let mut provider_request_body =
apply_standard_provider_request_body_rules(provider_request_body, body_rules, body_json)?;
@@ -90,6 +90,7 @@ fn builds_openai_chat_cross_format_request_body_from_openai_responses_source() {
"openai",
None,
None,
false,
)
.expect("openai responses to openai chat body should build");
@@ -123,6 +124,7 @@ fn local_openai_responses_wrapper_preserves_body_order_after_edits() {
"openai:responses",
None,
Some("key-123"),
false,
)
.expect("local openai responses body should build");
@@ -160,12 +162,41 @@ fn local_openai_responses_compact_wrapper_strips_store_for_same_format_requests(
"openai:responses:compact",
None,
None,
false,
)
.expect("local openai compact body should build");
assert!(provider_request_body.get("store").is_none());
}
#[test]
fn local_openai_responses_wrapper_applies_model_directive_before_body_rules() {
let body_json = json!({
"model": "gpt-5.4-max",
"input": "hello",
"reasoning": {"effort": "low", "summary": "auto"}
});
let body_rules = json!([
{"action":"set","path":"metadata.override_seen","value":true}
]);
let provider_request_body = build_local_openai_responses_request_body(
&body_json,
"gpt-5.4",
false,
"openai",
"openai:responses",
Some(&body_rules),
None,
true,
)
.expect("local openai responses body should build");
assert_eq!(provider_request_body["reasoning"]["effort"], "xhigh");
assert_eq!(provider_request_body["reasoning"]["summary"], "auto");
assert_eq!(provider_request_body["metadata"]["override_seen"], true);
}
#[test]
fn local_openai_responses_upstream_url_preserves_codex_base_path() {
let request = Request::builder()
@@ -205,6 +236,7 @@ fn strips_metadata_for_codex_openai_responses_requests() {
"codex",
None,
None,
false,
)
.expect("claude cli to codex request should build");
@@ -237,6 +269,7 @@ fn applies_codex_defaults_unless_body_rules_handle_the_field() {
"codex",
Some(&body_rules),
None,
false,
)
.expect("claude cli to codex request should build");
@@ -264,6 +297,7 @@ fn injects_codex_prompt_cache_key_for_openai_responses_cross_format_requests() {
"codex",
None,
Some("key-123"),
false,
)
.expect("claude cli to codex request should build");
@@ -291,6 +325,7 @@ fn injects_codex_prompt_cache_key_for_openai_chat_cross_format_requests() {
false,
None,
Some("key-123"),
false,
)
.expect("openai chat to codex request should build");