From c4bc994cab1987757a5ef0b748494aff5724f5ad Mon Sep 17 00:00:00 2001 From: Hare Date: Fri, 1 May 2026 23:55:26 +0900 Subject: [PATCH] =?UTF-8?q?fix(llm-worker):=20openai=5Fresponses=E3=81=AEr?= =?UTF-8?q?ole=E3=81=AE=E6=9C=80=E6=96=B0=E3=81=AE=E6=8A=95=E5=BD=B1?= =?UTF-8?q?=E3=82=92=E5=8F=8D=E6=98=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scheme/openai_responses/request.rs | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/crates/llm-worker/src/llm_client/scheme/openai_responses/request.rs b/crates/llm-worker/src/llm_client/scheme/openai_responses/request.rs index 886a57c5..55d2df4e 100644 --- a/crates/llm-worker/src/llm_client/scheme/openai_responses/request.rs +++ b/crates/llm-worker/src/llm_client/scheme/openai_responses/request.rs @@ -68,7 +68,11 @@ pub(crate) struct ReasoningConfig { #[derive(Debug, Serialize)] #[serde(tag = "type", rename_all = "snake_case")] pub(crate) enum InputItem { - /// 会話メッセージ。user / assistant / system のいずれか。 + /// 会話メッセージ。user / assistant / developer のいずれか。 + /// `Role::System` items は `developer` として投影する(ChatGPT + /// backend が `role: "system"` を拒否するため。Codex CLI も + /// system 相当の挿入には DeveloperInstructions = `role: "developer"` + /// を使う)。 Message { role: &'static str, content: Vec, @@ -104,7 +108,7 @@ pub(crate) enum InputItem { #[derive(Debug, Serialize)] #[serde(tag = "type", rename_all = "snake_case")] pub(crate) enum InputContent { - /// user / system 側のテキスト + /// user / developer 側のテキスト InputText { text: String }, /// assistant 側のテキスト OutputText { text: String }, @@ -230,7 +234,7 @@ fn convert_items_to_input(items: &[Item]) -> Vec { match role { Role::User => ("user", |t| InputContent::InputText { text: t }), Role::Assistant => ("assistant", |t| InputContent::OutputText { text: t }), - Role::System => ("system", |t| InputContent::InputText { text: t }), + Role::System => ("developer", |t| InputContent::InputText { text: t }), }; let parts: Vec = content .iter() @@ -387,6 +391,28 @@ mod tests { } } + #[test] + fn system_role_item_is_projected_as_developer() { + // ChatGPT backend (codex-oauth) は input[] の `role: "system"` を + // "System messages are not allowed" で 400 拒否する。in-conversation + // な system note (notify / fs_view auto-read / compaction summary) は + // `role: "developer"` として投影し、両 backend で受理されるようにする。 + let scheme = OpenAIResponsesScheme::new(); + let req = Request::new() + .user("hi") + .item(Item::system_message("[notify] hello")); + let body = scheme.build_request("gpt-5", &req, &cap_with_reasoning()); + match &body.input[1] { + InputItem::Message { role, content } => { + assert_eq!(*role, "developer"); + assert!( + matches!(&content[0], InputContent::InputText { text } if text == "[notify] hello"), + ); + } + _ => panic!("expected message"), + } + } + #[test] fn assistant_message_uses_output_text() { let scheme = OpenAIResponsesScheme::new();