Compare commits

...
Author SHA1 Message Date
Kit Langton 5bcf62cea0 feat(ai): support Gemini thinking levels 2026-07-21 14:35:41 -04:00
2 changed files with 21 additions and 0 deletions
+7
View File
@@ -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<Schema.Schema.Type<typeof GeminiThinkingConfig>["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
+14
View File
@@ -36,6 +36,20 @@ describe("Gemini route", () => {
}),
)
it.effect("prepares thinking level", () =>
Effect.gen(function* () {
const prepared = yield* LLMClient.prepare<Gemini.GeminiBody>(
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<Gemini.GeminiBody>(