From 997b00034435440d412f955e05e53f09bae83f9e Mon Sep 17 00:00:00 2001 From: Adam Malczewski Date: Sat, 23 May 2026 19:07:21 +0900 Subject: feat: google gemini provider, adaptive thinking for opus 4.7, model search filter - Added Google (Gemini) as a provider: add-key UI, env var resolution via resolveApiKey, usage tracking via native models endpoint + gemini.google.com cookie scraping - @ai-sdk/anthropic upgraded to v3 (adaptive thinking support) with LanguageModelV1 cast for ai v4 compat - Claude Opus 4.7 uses adaptive thinking (type: adaptive); all other models keep explicit budget tokens - Model selector modal: search filter with space matching dash/underscore - Copy button: all tool results truncated at 300 chars - Sidebar layout fix: Claude Reset panel removed from flex-1 fill to prevent overlap --- packages/core/src/agent/agent.ts | 44 +++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 16 deletions(-) (limited to 'packages/core/src/agent') diff --git a/packages/core/src/agent/agent.ts b/packages/core/src/agent/agent.ts index bf9b22f..24de59d 100644 --- a/packages/core/src/agent/agent.ts +++ b/packages/core/src/agent/agent.ts @@ -1,6 +1,6 @@ import { realpathSync } from "node:fs"; import { dirname, isAbsolute, relative, resolve } from "node:path"; -import type { CoreMessage } from "ai"; +import type { CoreMessage, LanguageModelV1 } from "ai"; import { streamText } from "ai"; import { buildBillingHeaderValue, SYSTEM_IDENTITY } from "../credentials/claude.js"; import { createProvider, prefixToolName, unprefixToolName } from "../llm/provider.js"; @@ -260,28 +260,40 @@ export class Agent { const effort = options?.reasoningEffort ?? this.config.reasoningEffort ?? "max"; // Build stream text options + const rawModel = providerFactory(this.config.model); + const model = rawModel as unknown as LanguageModelV1; const streamOptions: Parameters[0] = { - model: providerFactory(this.config.model), + model, system: systemPrompt, messages: toCoreMessages(stepMessages, isAnthropic), tools, }; if (isAnthropic && effort !== "none") { - const budgetTokens = - effort === "max" - ? 16000 - : effort === "high" - ? 10000 - : effort === "medium" - ? 5000 - : effort === "low" - ? 2000 - : 0; - streamOptions.providerOptions = { - anthropic: { thinking: { type: "enabled" as const, budgetTokens } }, - }; - streamOptions.maxTokens = budgetTokens + 8000; + const modelId = this.config.model; + const isOpus47 = modelId === "claude-opus-4-7"; + + if (isOpus47) { + // Opus 4.7 only supports adaptive thinking + streamOptions.providerOptions = { + anthropic: { thinking: { type: "adaptive" as const } }, + }; + } else { + const budgetTokens = + effort === "max" + ? 16000 + : effort === "high" + ? 10000 + : effort === "medium" + ? 5000 + : effort === "low" + ? 2000 + : 0; + streamOptions.providerOptions = { + anthropic: { thinking: { type: "enabled" as const, budgetTokens } }, + }; + streamOptions.maxTokens = budgetTokens + 8000; + } } else if (!isAnthropic && effort !== "none") { streamOptions.providerOptions = { openaiCompatible: { reasoningEffort: effort } }; } -- cgit v1.2.3