mirror of
https://github.com/DayuanJiang/next-ai-draw-io.git
synced 2026-10-08 10:47:48 +08:00
- Update ai to 6.0.300 and the @ai-sdk providers to their latest v6-line versions. @ai-sdk/anthropic 3.0.47 did not know claude-opus-4-7/4-8 and capped their output at 32000 tokens; 3.0.127 allows 128000 - Drop the fine-grained-tool-streaming beta header for the Anthropic API: the provider now streams tool input per tool (eager_input_streaming) - Claude 4.7 and later reject a non-default temperature/top_p/top_k and the extended thinking budget with a 400. A middleware retries once without them, so TEMPERATURE and *_THINKING_BUDGET_TOKENS no longer break those models - Prompt caching also reaches Claude on the Anthropic API and OpenRouter; before, only Bedrock got a cache marker - GOOGLE_TOP_K and GOOGLE_TOP_P never reached Gemini: they were sent as Google provider options, which drops them. They are call settings now. GOOGLE_CANDIDATE_COUNT and GOOGLE_REASONING_EFFORT, which the provider does not support, are removed - Add @ai-sdk/openai-compatible as a direct dependency
63 lines
2.1 KiB
TypeScript
63 lines
2.1 KiB
TypeScript
// @vitest-environment node
|
|
import { generateText } from "ai"
|
|
import { afterEach, describe, expect, it, vi } from "vitest"
|
|
import { getAIModel } from "@/lib/ai-providers"
|
|
|
|
const ENV = ["GOOGLE_GENERATIVE_AI_API_KEY", "GOOGLE_TOP_K", "GOOGLE_TOP_P"]
|
|
const saved = Object.fromEntries(ENV.map((k) => [k, process.env[k]]))
|
|
|
|
afterEach(() => {
|
|
for (const k of ENV) {
|
|
if (saved[k] === undefined) delete process.env[k]
|
|
else process.env[k] = saved[k]
|
|
}
|
|
vi.unstubAllGlobals()
|
|
})
|
|
|
|
/** Send one request through the real Google provider and return its body */
|
|
async function googleRequestBody() {
|
|
let body: any
|
|
vi.stubGlobal(
|
|
"fetch",
|
|
vi.fn(async (_url: string, init: RequestInit) => {
|
|
body = JSON.parse(init.body as string)
|
|
return new Response(
|
|
JSON.stringify({
|
|
candidates: [
|
|
{
|
|
content: { role: "model", parts: [{ text: "ok" }] },
|
|
finishReason: "STOP",
|
|
},
|
|
],
|
|
}),
|
|
{ headers: { "content-type": "application/json" } },
|
|
)
|
|
}),
|
|
)
|
|
const { model } = getAIModel({
|
|
provider: "google",
|
|
modelId: "gemini-2.5-flash",
|
|
})
|
|
await generateText({ model, prompt: "hi", maxRetries: 0 })
|
|
return body
|
|
}
|
|
|
|
describe("Google sampling settings", () => {
|
|
it("sends GOOGLE_TOP_K and GOOGLE_TOP_P in the generation config", async () => {
|
|
process.env.GOOGLE_GENERATIVE_AI_API_KEY = "test-key"
|
|
process.env.GOOGLE_TOP_K = "40"
|
|
process.env.GOOGLE_TOP_P = "0.9"
|
|
const body = await googleRequestBody()
|
|
expect(body.generationConfig).toMatchObject({ topK: 40, topP: 0.9 })
|
|
})
|
|
|
|
it("sends neither when they are not set", async () => {
|
|
process.env.GOOGLE_GENERATIVE_AI_API_KEY = "test-key"
|
|
delete process.env.GOOGLE_TOP_K
|
|
delete process.env.GOOGLE_TOP_P
|
|
const body = await googleRequestBody()
|
|
expect(body.generationConfig?.topK).toBeUndefined()
|
|
expect(body.generationConfig?.topP).toBeUndefined()
|
|
})
|
|
})
|