diff --git a/packages/ai/src/protocols/gemini.ts b/packages/ai/src/protocols/gemini.ts index 82a69b059e..82759f0eec 100644 --- a/packages/ai/src/protocols/gemini.ts +++ b/packages/ai/src/protocols/gemini.ts @@ -93,8 +93,10 @@ const GeminiToolConfig = Schema.Struct({ const GeminiThinkingConfig = Schema.Struct({ thinkingBudget: Schema.optional(Schema.Number), + thinkingLevel: Schema.optional(Schema.Literals(["minimal", "low", "medium", "high"])), includeThoughts: Schema.optional(Schema.Boolean), }) +type GeminiThinkingLevel = NonNullable["thinkingLevel"]> const GeminiGenerationConfig = Schema.Struct({ maxOutputTokens: Schema.optional(Schema.Number), @@ -289,11 +291,16 @@ const lowerMessages = Effect.fn("Gemini.lowerMessages")(function* (request: LLMR const geminiOptions = (request: LLMRequest) => request.providerOptions?.gemini +const isThinkingLevel = (value: unknown): value is GeminiThinkingLevel => + value === "minimal" || value === "low" || value === "medium" || value === "high" + const thinkingConfig = (request: LLMRequest) => { const value = geminiOptions(request)?.thinkingConfig if (!ProviderShared.isRecord(value)) return undefined + const thinkingLevel = value.thinkingLevel const result = { thinkingBudget: typeof value.thinkingBudget === "number" ? value.thinkingBudget : undefined, + thinkingLevel: isThinkingLevel(thinkingLevel) ? thinkingLevel : undefined, includeThoughts: typeof value.includeThoughts === "boolean" ? value.includeThoughts : undefined, } return Object.values(result).some((item) => item !== undefined) ? result : undefined diff --git a/packages/ai/test/provider/gemini.test.ts b/packages/ai/test/provider/gemini.test.ts index 1dc253c0ea..291f86c8f9 100644 --- a/packages/ai/test/provider/gemini.test.ts +++ b/packages/ai/test/provider/gemini.test.ts @@ -36,6 +36,20 @@ describe("Gemini route", () => { }), ) + it.effect("prepares thinking level", () => + Effect.gen(function* () { + const prepared = yield* LLMClient.prepare( + LLM.request({ + model, + prompt: "Say hello.", + providerOptions: { gemini: { thinkingConfig: { thinkingLevel: "minimal" } } }, + }), + ) + + expect(prepared.body.generationConfig).toEqual({ thinkingConfig: { thinkingLevel: "minimal" } }) + }), + ) + it.effect("lowers chronological system updates to wrapped user text in order", () => Effect.gen(function* () { const prepared = yield* LLMClient.prepare(