From 29b92c032911de9bae76d08781b70bb231387d99 Mon Sep 17 00:00:00 2001 From: Andreas Wachs Date: Tue, 28 Apr 2026 11:05:02 +0200 Subject: [PATCH 1/3] chore: add .worktrees to .gitignore Co-Authored-By: ForgeCode --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index ae359692b2..a6dbf8c4ca 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,4 @@ jobs/** node_modules/ bench/__pycache__ .ai/ +.worktrees/ From 115faa8a80632b110bc088b1fdebf4962bbbc1a7 Mon Sep 17 00:00:00 2001 From: Andreas Wachs Date: Wed, 29 Apr 2026 09:17:31 +0200 Subject: [PATCH 2/3] fix: apply MergeSystemMessages transformer to all OpenAI-compatible providers Some OpenAI-compatible endpoints (e.g., custom/local providers) require the system message to be at the beginning of the messages array. Previously, the MergeSystemMessages transformer was only applied to NVIDIA providers. This change applies the transformer to all providers with OpenAI or OpenCode response types, ensuring system messages are properly merged and positioned at the start for any OpenAI-compatible endpoint. Co-Authored-By: Claude Opus 4.5 --- .../forge_app/src/dto/openai/transformers/pipeline.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/crates/forge_app/src/dto/openai/transformers/pipeline.rs b/crates/forge_app/src/dto/openai/transformers/pipeline.rs index ccffc56d97..765e2a7f9c 100644 --- a/crates/forge_app/src/dto/openai/transformers/pipeline.rs +++ b/crates/forge_app/src/dto/openai/transformers/pipeline.rs @@ -22,6 +22,7 @@ use super::tool_choice::SetToolChoice; use super::trim_tool_call_ids::TrimToolCallIds; use super::when_model::when_model; use super::zai_reasoning::SetZaiThinking; +use crate::domain::ProviderResponse; use crate::dto::openai::{Request, ToolChoice}; /// Pipeline for transforming requests based on the provider type @@ -82,8 +83,13 @@ impl Transformer for ProviderPipeline<'_> { let xai_compat = MakeXaiCompat.when(move |_| provider.id == ProviderId::XAI); - let ensure_system_first = - MergeSystemMessages.when(move |_| provider.id == ProviderId::NVIDIA); + // Apply to all OpenAI-compatible providers to ensure system messages are first + let ensure_system_first = MergeSystemMessages.when(move |_| { + matches!( + provider.response, + Some(ProviderResponse::OpenAI) | Some(ProviderResponse::OpenCode) + ) + }); let trim_tool_call_ids = TrimToolCallIds.when(move |_| provider.id == ProviderId::OPENAI); From 4a526b346139b0b996c918c2258b594561053b1f Mon Sep 17 00:00:00 2001 From: Andreas Wachs Date: Wed, 29 Apr 2026 09:22:11 +0200 Subject: [PATCH 3/3] fix: apply MergeSystemMessages only to NVIDIA and custom providers Avoid applying to known built-in OpenAI-compatible providers to prevent degrading their caching behaviour. Custom (non-built-in) providers commonly require system messages at the start of the messages array. Co-Authored-By: Claude Sonnet 4.6 --- .../forge_app/src/dto/openai/transformers/pipeline.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/crates/forge_app/src/dto/openai/transformers/pipeline.rs b/crates/forge_app/src/dto/openai/transformers/pipeline.rs index 765e2a7f9c..1e7f449f3a 100644 --- a/crates/forge_app/src/dto/openai/transformers/pipeline.rs +++ b/crates/forge_app/src/dto/openai/transformers/pipeline.rs @@ -22,7 +22,6 @@ use super::tool_choice::SetToolChoice; use super::trim_tool_call_ids::TrimToolCallIds; use super::when_model::when_model; use super::zai_reasoning::SetZaiThinking; -use crate::domain::ProviderResponse; use crate::dto::openai::{Request, ToolChoice}; /// Pipeline for transforming requests based on the provider type @@ -83,12 +82,11 @@ impl Transformer for ProviderPipeline<'_> { let xai_compat = MakeXaiCompat.when(move |_| provider.id == ProviderId::XAI); - // Apply to all OpenAI-compatible providers to ensure system messages are first + // Apply to NVIDIA and custom (non-built-in) providers to ensure system messages are + // first. Built-in providers are excluded to avoid degrading their caching behaviour. let ensure_system_first = MergeSystemMessages.when(move |_| { - matches!( - provider.response, - Some(ProviderResponse::OpenAI) | Some(ProviderResponse::OpenCode) - ) + provider.id == ProviderId::NVIDIA + || !ProviderId::built_in_providers().contains(&provider.id) }); let trim_tool_call_ids = TrimToolCallIds.when(move |_| provider.id == ProviderId::OPENAI);