From 9b65c72a94a411dd8b529482932db0f5692f03d6 Mon Sep 17 00:00:00 2001 From: Gujiassh Date: Mon, 23 Mar 2026 18:50:35 +0900 Subject: [PATCH] Fix Vertex AI tool response roles Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- lib/ruby_llm/providers/vertexai/chat.rb | 8 ++++ spec/ruby_llm/providers/vertex_ai_spec.rb | 45 +++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/lib/ruby_llm/providers/vertexai/chat.rb b/lib/ruby_llm/providers/vertexai/chat.rb index c059d39e6..d0ae68ee3 100644 --- a/lib/ruby_llm/providers/vertexai/chat.rb +++ b/lib/ruby_llm/providers/vertexai/chat.rb @@ -8,6 +8,14 @@ module Chat def completion_url "projects/#{@config.vertexai_project_id}/locations/#{@config.vertexai_location}/publishers/google/models/#{@model}:generateContent" # rubocop:disable Layout/LineLength end + + def render_payload(messages, **kwargs) + payload = super + payload[:contents] = payload[:contents].map do |content| + content[:role] == 'function' ? content.merge(role: 'user') : content + end + payload + end end end end diff --git a/spec/ruby_llm/providers/vertex_ai_spec.rb b/spec/ruby_llm/providers/vertex_ai_spec.rb index 22e82749f..0cb71c3d2 100644 --- a/spec/ruby_llm/providers/vertex_ai_spec.rb +++ b/spec/ruby_llm/providers/vertex_ai_spec.rb @@ -36,4 +36,49 @@ end end end + + describe '#render_payload' do + let(:location) { 'us-central1' } + let(:model) do + instance_double(RubyLLM::Model::Info, id: 'gemini-2.5-pro', max_tokens: nil, metadata: {}) + end + + it 'normalizes tool response content roles to user' do + tool_message = instance_double( + RubyLLM::Message, + role: :tool, + tool_call_id: 'call_1', + content: 'tool output' + ) + user_message = instance_double( + RubyLLM::Message, + role: :user, + tool_call?: false, + tool_result?: false, + content: 'prompt' + ) + + payload = provider.send(:render_payload, [tool_message, user_message], tools: {}, temperature: nil, model: model) + + expect(payload[:contents]).to eq( + [ + { + role: 'user', + parts: [ + { + functionResponse: { + name: 'call_1', + response: { + name: 'call_1', + content: [{ text: 'tool output' }] + } + } + } + ] + }, + { role: 'user', parts: [{ text: 'prompt' }] } + ] + ) + end + end end