diff --git a/src/providers/google-vertex-ai/chatComplete.ts b/src/providers/google-vertex-ai/chatComplete.ts index 7f1d08116..94dd87b0d 100644 --- a/src/providers/google-vertex-ai/chatComplete.ts +++ b/src/providers/google-vertex-ai/chatComplete.ts @@ -261,39 +261,20 @@ export const VertexGoogleChatCompleteConfig: ProviderConfig = { ) ) return; - const firstMessage = params.messages?.[0] || null; - if (!firstMessage) return; - - if ( - SYSTEM_MESSAGE_ROLES.includes(firstMessage.role) && - typeof firstMessage.content === "string" - ) { - return { - parts: [ - { - text: firstMessage.content, - }, - ], - role: "system", - }; - } - - if ( - SYSTEM_MESSAGE_ROLES.includes(firstMessage.role) && - typeof firstMessage.content === "object" && - firstMessage.content?.[0]?.text - ) { - return { - parts: [ - { - text: firstMessage.content?.[0].text, - }, - ], - role: "system", - }; - } - - return; + // contents skips every system message, so all of them go here. + const parts = (params.messages ?? []) + .filter((message) => + SYSTEM_MESSAGE_ROLES.includes(message.role), + ) + .flatMap((message) => + typeof message.content === "string" + ? [{ text: message.content }] + : (message.content ?? []) + .filter((part) => part.text) + .map((part) => ({ text: part.text })), + ); + if (!parts.length) return; + return { parts, role: "system" }; }, }, ], diff --git a/tests/unit/src/services/transformToProviderRequest.node.ts b/tests/unit/src/services/transformToProviderRequest.node.ts index b768fdd31..5d6d1c067 100644 --- a/tests/unit/src/services/transformToProviderRequest.node.ts +++ b/tests/unit/src/services/transformToProviderRequest.node.ts @@ -1,6 +1,11 @@ import assert from 'node:assert/strict'; import { describe, it } from 'node:test'; -import { AZURE_OPEN_AI, BEDROCK, OPEN_AI } from '../../../../src/globals'; +import { + AZURE_OPEN_AI, + BEDROCK, + GOOGLE_VERTEX_AI, + OPEN_AI, +} from '../../../../src/globals'; import { BedrockConverseAnthropicChatCompletionsParams } from '../../../../src/providers/bedrock/chatComplete'; import { Params } from '../../../../src/types/requestBody'; import { transformToProviderRequest } from '../../../../src/services/transformToProviderRequest'; @@ -153,3 +158,30 @@ describe('Claude Converse parameters', () => { assert.equal('additionalModelRequestFields' in request, false); }); }); + +describe('Vertex Gemini system messages', () => { + it('sends every system message and text part as systemInstruction', () => { + const request = chatRequest(GOOGLE_VERTEX_AI, { + model: 'gemini-3-flash-preview', + messages: [ + { role: 'system', content: 'Answer in German.' }, + { + role: 'system', + content: [ + { type: 'text', text: 'Be brief.' }, + { type: 'text', text: 'End with BANANE.' }, + ], + }, + { role: 'user', content: 'Name a colour.' }, + ], + }); + assert.deepEqual(request.systemInstruction, { + parts: [ + { text: 'Answer in German.' }, + { text: 'Be brief.' }, + { text: 'End with BANANE.' }, + ], + role: 'system', + }); + }); +});