commit c5b95489c75049dee80844b53e706be704929dfb from: leoshimo <56844000+leoshimo@users.noreply.github.com> date: Mon May 4 06:14:59 2026 UTC fix: gpt-5.5 commit - 80d01e8e19c1b9b7f13401442cd44218746a79ca commit + c5b95489c75049dee80844b53e706be704929dfb blob - c518f977566828fb20eba8b47b4db91a7070735b blob + e7752d5851ce6dd49241bb19fd098610f22b89ae --- src/cli.rs +++ src/cli.rs @@ -4,7 +4,7 @@ use std::time::Duration; use crate::openai::{Message, ReasoningEffort}; use clap::{ - arg, builder::PossibleValue, command, value_parser, ArgGroup, ArgMatches, Command, ValueEnum, + ArgGroup, ArgMatches, Command, ValueEnum, arg, builder::PossibleValue, command, value_parser, }; use derive_builder::Builder; @@ -14,7 +14,8 @@ pub struct Invocation { pub api_key: Option, pub messages: Vec, pub model: String, - pub temperature: f32, + #[builder(default)] + pub temperature: Option, pub output_format: OutputFormat, pub file: String, pub timeout: Duration, @@ -40,11 +41,10 @@ pub fn parse() -> Invocation { /// Top-level command fn cli() -> Command { command!() - .arg(arg!(model: -m --model "Sets model. See https://platform.openai.com/docs/models for model identifiers.").default_value("gpt-5")) + .arg(arg!(model: -m --model "Sets model. See https://platform.openai.com/docs/models for model identifiers.").default_value("gpt-5.5")) .arg( arg!(temperature: -t --temperature "Sets temperature") - .value_parser(value_parser!(f32)) - .default_value("0.0"), + .value_parser(value_parser!(f32)), ) .arg( arg!(timeout: -T --timeout "Sets timeout duration in seconds") @@ -92,9 +92,7 @@ impl From for Invocation { .expect("Models is required") .to_string(); - let temperature = *matches - .get_one::("temperature") - .expect("Temperature is required"); + let temperature = matches.get_one::("temperature").copied(); let timeout = matches .get_one::("timeout") @@ -272,7 +270,8 @@ mod test { Message::assistant("ROBOT"), Message::user("USER2"), ], - "system message is always brought to front, followed by assistant and user messages in order"); + "system message is always brought to front, followed by assistant and user messages in order" + ); Ok(()) } blob - 385cb933f50e88ff173b340a8a8252a807509bab blob + 076c7e1b35e95e97574dc4be3b457573adc05731 --- src/exec/chat.rs +++ src/exec/chat.rs @@ -1,9 +1,9 @@ //! Implements chat subcommand +use crate::Error; use crate::cli::{Invocation, OutputFormat}; use crate::openai::{self, FinishReason, Message, Reasoning, Response}; use crate::parse; -use crate::Error; use anyhow::{Context, Result}; use std::fs::File; @@ -81,7 +81,7 @@ fn show_response(dest: impl Write, args: &Invocation, return Err(Error::UnexpectedResponse(format!( "Unexpected number of choices in response: {:?}", resp - ))) + ))); } }; @@ -100,7 +100,7 @@ fn show_response(dest: impl Write, args: &Invocation, return Err(Error::UnexpectedResponse(format!( "Received unrecognized stop reason for choice: {:?}", choice - ))) + ))); } } @@ -196,7 +196,7 @@ mod test { .api_key(Some(String::default())) .messages(vec![]) .model(String::default()) - .temperature(1.0) + .temperature(Some(1.0)) .output_format(OutputFormat::Plaintext) .timeout(Duration::from_secs(10)) .file("-".to_string()) blob - e2497fbce7911cb9f73c40389e1cb841a474879b blob + e0e9bedd15e252c826cee3ae5507c2a1bba259a3 --- src/openai.rs +++ src/openai.rs @@ -9,7 +9,7 @@ use chrono::{DateTime, Utc}; use derive_builder::Builder; use reqwest::StatusCode; use serde::{Deserialize, Serialize}; -use serde_json::{json, Value}; +use serde_json::{Value, json}; /// Convienience Client for OpenAI Responses API pub struct Client { @@ -27,7 +27,8 @@ pub struct Client { pub struct ResponseRequest { model: String, messages: Vec, - temperature: f32, + #[builder(default)] + temperature: Option, timeout: Duration, #[builder(default)] reasoning: Option, @@ -191,7 +192,7 @@ impl Message { json!({ "role": self.role.as_str(), "content": [{ - "type": "text", + "type": "input_text", "text": self.content.clone(), }] }) @@ -223,16 +224,22 @@ impl ResponseRequest { let mut payload = json!({ "model": self.model, "input": input, - "temperature": self.temperature, }); + if let Some(temperature) = self.temperature + && let Some(obj) = payload.as_object_mut() + { + obj.insert("temperature".to_string(), json!(temperature)); + } + if let Some(reasoning) = &self.reasoning - && let Some(obj) = payload.as_object_mut() { - obj.insert( - "reasoning".to_string(), - serde_json::to_value(reasoning).expect("failed to serialize reasoning"), - ); - } + && let Some(obj) = payload.as_object_mut() + { + obj.insert( + "reasoning".to_string(), + serde_json::to_value(reasoning).expect("failed to serialize reasoning"), + ); + } payload } @@ -246,6 +253,7 @@ impl Response { #[derive(Debug, Deserialize)] struct ResponsesAPIResponse { + #[serde(rename = "created_at", alias = "created")] #[serde(with = "ts_seconds")] created: DateTime, model: String, @@ -419,7 +427,7 @@ mod test { let request = ResponseRequest::builder() .model("gpt-5".to_string()) .messages(vec![Message::user("Hello")]) - .temperature(0.0) + .temperature(Some(0.0)) .timeout(Duration::from_secs(30)) .reasoning(Some(Reasoning::from_effort(ReasoningEffort::High))) .build() @@ -429,6 +437,7 @@ mod test { assert_eq!(payload["reasoning"]["effort"], "high"); assert_eq!(payload["model"], "gpt-5"); + assert_eq!(payload["temperature"], 0.0); Ok(()) } @@ -438,7 +447,6 @@ mod test { let request = ResponseRequest::builder() .model("gpt-5".to_string()) .messages(vec![Message::user("Hello")]) - .temperature(0.0) .timeout(Duration::from_secs(30)) .build() .expect("request builds"); @@ -446,6 +454,7 @@ mod test { let payload = request.to_payload(); assert!(payload.get("reasoning").is_none()); + assert!(payload.get("temperature").is_none()); Ok(()) } blob - 05b4e04c7c77c264b5006ba51802f1006384b482 blob + b5bfc88ba906ba1e4d7e8addfd1917c584906417 --- tests/chat.rs +++ tests/chat.rs @@ -35,11 +35,11 @@ fn chat_user_message_from_flag() { .with_header("content-type", "application/json") .with_header("authorization", "Bearer ABCDE") .match_body(mockito::Matcher::PartialJson(json!({ - "model": "gpt-5", + "model": "gpt-5.5", "input": [{ "role": "user", "content": [{ - "type": "text", + "type": "input_text", "text": "Hello" }] }] @@ -48,7 +48,7 @@ fn chat_user_message_from_flag() { r#"{ "id": "resp_XXXXX", "created": 1688413145, - "model": "gpt-5", + "model": "gpt-5.5", "output": [{ "id": "msg_XXXXX", "type": "message", @@ -89,11 +89,11 @@ fn chat_user_message_from_stdin() { .with_header("content-type", "application/json") .with_header("authorization", "Bearer ABCDE") .match_body(mockito::Matcher::PartialJson(json!({ - "model": "gpt-5", + "model": "gpt-5.5", "input": [{ "role": "user", "content": [{ - "type": "text", + "type": "input_text", "text": "Hello" }] }] @@ -102,7 +102,7 @@ fn chat_user_message_from_stdin() { r#"{ "id": "resp_XXXXX", "created": 1688413145, - "model": "gpt-5", + "model": "gpt-5.5", "output": [{ "id": "msg_XXXXX", "type": "message", @@ -143,14 +143,14 @@ fn chat_with_reasoning_effort() { .with_header("content-type", "application/json") .with_header("authorization", "Bearer ABCDE") .match_body(mockito::Matcher::PartialJson(json!({ - "model": "gpt-5", + "model": "gpt-5.5", "reasoning": { "effort": "medium" }, "input": [{ "role": "user", "content": [{ - "type": "text", + "type": "input_text", "text": "Hello" }] }] @@ -159,7 +159,7 @@ fn chat_with_reasoning_effort() { r#"{ "id": "resp_XXXXX", "created": 1688413145, - "model": "gpt-5", + "model": "gpt-5.5", "output": [{ "id": "msg_XXXXX", "type": "message", @@ -205,41 +205,41 @@ fn chat_multiple_messages() { .with_header("content-type", "application/json") .with_header("authorization", "Bearer ABCDE") .match_body(mockito::Matcher::PartialJson(json!({ - "model": "gpt-5", + "model": "gpt-5.5", "input": [{ "role": "system", "content": [{ - "type": "text", + "type": "input_text", "text": "SYSTEM" }], }, { "role": "user", "content": [{ - "type": "text", + "type": "input_text", "text": "USER_1" }], }, { "role": "assistant", "content": [{ - "type": "text", + "type": "input_text", "text": "ASSI_1" }], }, { "role": "user", "content": [{ - "type": "text", + "type": "input_text", "text": "USER_2" }], }, { "role": "assistant", "content": [{ - "type": "text", + "type": "input_text", "text": "ASSI_2" }], }, { "role": "user", "content": [{ - "type": "text", + "type": "input_text", "text": "USER_STDIN" }], }] @@ -248,7 +248,7 @@ fn chat_multiple_messages() { r#"{ "id": "resp_XXXXX", "created": 1688413145, - "model": "gpt-5", + "model": "gpt-5.5", "output": [{ "id": "msg_XXXXX", "type": "message", @@ -294,11 +294,11 @@ fn chat_api_error() { .with_header("content-type", "application/json") .with_header("authorization", "Bearer ABCDE") .match_body(mockito::Matcher::PartialJson(json!({ - "model": "gpt-5", + "model": "gpt-5.5", "input": [{ "role": "user", "content": [{ - "type": "text", + "type": "input_text", "text": "USER" }], }], @@ -344,11 +344,11 @@ fn chat_user_message_from_file() { .with_header("content-type", "application/json") .with_header("authorization", "Bearer ABCDE") .match_body(mockito::Matcher::PartialJson(json!({ - "model": "gpt-5", + "model": "gpt-5.5", "input": [{ "role": "user", "content": [{ - "type": "text", + "type": "input_text", "text": "Hello from file" }], }], @@ -357,7 +357,7 @@ fn chat_user_message_from_file() { r#"{ "id": "resp_XXXXX", "created": 1688413145, - "model": "gpt-5", + "model": "gpt-5.5", "output": [{ "id": "msg_XXXXX", "type": "message",