mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-08-28 05:27:41 +00:00
Merge pull request #796 from fabro-sh/codex/twin-openai-unknown-fields
Some checks are pending
Rust / Format (push) Waiting to run
Rust / Clippy (push) Waiting to run
Rust / Generated Docs (push) Waiting to run
Rust / Test (Linux) (push) Waiting to run
Rust / Test (macOS) (push) Waiting to run
TypeScript / Typecheck (push) Waiting to run
TypeScript / Test (push) Waiting to run
TypeScript / Build (push) Waiting to run
Some checks are pending
Rust / Format (push) Waiting to run
Rust / Clippy (push) Waiting to run
Rust / Generated Docs (push) Waiting to run
Rust / Test (Linux) (push) Waiting to run
Rust / Test (macOS) (push) Waiting to run
TypeScript / Typecheck (push) Waiting to run
TypeScript / Test (push) Waiting to run
TypeScript / Build (push) Waiting to run
fix(twin-openai): accept unknown chat fields
This commit is contained in:
commit
79168d3a27
3 changed files with 24 additions and 8 deletions
|
|
@ -38,6 +38,9 @@ Supported `/v1/chat/completions` fields:
|
|||
- `stop`
|
||||
- reasoning-bearing assistant content
|
||||
|
||||
Unknown top-level fields are accepted and ignored. The twin does not simulate the behavior of
|
||||
fields that are not listed above.
|
||||
|
||||
Structured output subset:
|
||||
|
||||
- object roots
|
||||
|
|
|
|||
|
|
@ -526,8 +526,10 @@ pub fn normalize_whitespace(input: &str) -> String {
|
|||
input.split_whitespace().collect::<Vec<_>>().join(" ")
|
||||
}
|
||||
|
||||
/// Accepts all known OpenAI Chat Completions API fields. Unknown top-level
|
||||
/// fields are ignored via `#[serde(flatten)]` so the twin stays compatible as
|
||||
/// clients add request options.
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct ChatCompletionsRequest {
|
||||
pub model: String,
|
||||
pub messages: Vec<ChatMessage>,
|
||||
|
|
@ -539,6 +541,13 @@ pub struct ChatCompletionsRequest {
|
|||
pub tool_choice: Option<Value>,
|
||||
pub response_format: Option<ChatResponseFormat>,
|
||||
pub stop: Option<Value>,
|
||||
/// Catch-all for fields the twin doesn't use (temperature, top_p, etc.)
|
||||
#[allow(
|
||||
dead_code,
|
||||
reason = "Serde captures unknown request fields for forward compatibility."
|
||||
)]
|
||||
#[serde(flatten)]
|
||||
extra: Map<String, Value>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
|
|
|
|||
|
|
@ -369,20 +369,24 @@ async fn chat_completions_reject_reasoning_parts_on_non_assistant_messages() {
|
|||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn chat_completions_reject_unknown_top_level_fields() {
|
||||
async fn chat_completions_accept_unknown_top_level_fields() {
|
||||
let server = common::spawn_server().await.expect("server should start");
|
||||
|
||||
let response = server
|
||||
.post_chat(json!({
|
||||
let (status, chunks) = server
|
||||
.post_chat_stream(json!({
|
||||
"model": "gpt-test",
|
||||
"messages": [{ "role": "user", "content": "hello" }],
|
||||
"unexpected_field": true
|
||||
"stream": true,
|
||||
"temperature": 0.7,
|
||||
"top_p": 0.9,
|
||||
"prompt_cache_key": "conversation-123"
|
||||
}))
|
||||
.await;
|
||||
|
||||
assert_eq!(response.status(), 400);
|
||||
let body = response.json::<serde_json::Value>().await.expect("json");
|
||||
assert_eq!(body["error"]["type"], "invalid_request_error");
|
||||
assert_eq!(status, 200);
|
||||
let transcript =
|
||||
common::parse_sse_transcript(chunks.join("").as_bytes()).expect("valid SSE transcript");
|
||||
assert!(transcript.done);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue