mirror of
https://github.com/DayuanJiang/next-ai-draw-io.git
synced 2026-10-07 02:07:47 +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
91 lines
3.0 KiB
TypeScript
91 lines
3.0 KiB
TypeScript
import { wrapLanguageModel } from "ai"
|
|
import { rejectionText } from "@/lib/output-token-limit"
|
|
|
|
type WrappedModel = ReturnType<typeof wrapLanguageModel>
|
|
|
|
/**
|
|
* Claude 4.7 and later answer a non-default temperature, top_p or top_k,
|
|
* and the extended thinking budget (thinking type "enabled"), with a 400.
|
|
* TEMPERATURE and the *_THINKING_BUDGET_TOKENS settings send exactly these.
|
|
*/
|
|
const DEPRECATED_PARAM =
|
|
/`?(?:temperature|top_p|top_k)`? is deprecated for this model|"?thinking\.type\.enabled"? is not supported/i
|
|
|
|
interface CallParams {
|
|
temperature?: number
|
|
topP?: number
|
|
topK?: number
|
|
providerOptions?: Record<string, Record<string, unknown> | undefined>
|
|
}
|
|
|
|
/** Drop a thinking config of type "enabled" stored under key, if any. */
|
|
function withoutEnabledThinking(
|
|
options: Record<string, unknown> | undefined,
|
|
key: string,
|
|
): Record<string, unknown> | undefined {
|
|
const config = options?.[key] as { type?: string } | undefined
|
|
if (config?.type !== "enabled") return options
|
|
const { [key]: _, ...rest } = options as Record<string, unknown>
|
|
return rest
|
|
}
|
|
|
|
/**
|
|
* The params without the settings newer Claude models reject, or null when
|
|
* the error is about something else or there is nothing to drop. The model
|
|
* then runs with its own default sampling and thinking.
|
|
*/
|
|
export function withoutDeprecatedParams<T extends CallParams>(
|
|
error: unknown,
|
|
params: T,
|
|
): T | null {
|
|
const text = rejectionText(error)
|
|
if (!text || !DEPRECATED_PARAM.test(text)) return null
|
|
|
|
const { temperature, topP, topK, ...rest } = params
|
|
const options = params.providerOptions
|
|
const anthropic = withoutEnabledThinking(options?.anthropic, "thinking")
|
|
const bedrock = withoutEnabledThinking(options?.bedrock, "reasoningConfig")
|
|
const changed =
|
|
temperature !== undefined ||
|
|
topP !== undefined ||
|
|
topK !== undefined ||
|
|
anthropic !== options?.anthropic ||
|
|
bedrock !== options?.bedrock
|
|
if (!changed) return null
|
|
|
|
return {
|
|
...rest,
|
|
...(options && {
|
|
providerOptions: {
|
|
...options,
|
|
...(anthropic && { anthropic }),
|
|
...(bedrock && { bedrock }),
|
|
},
|
|
}),
|
|
} as T
|
|
}
|
|
|
|
/** Retry the stream once without the settings newer Claude models reject. */
|
|
export function withDeprecatedParamsFallback(
|
|
model: WrappedModel,
|
|
): WrappedModel {
|
|
return wrapLanguageModel({
|
|
model,
|
|
middleware: {
|
|
specificationVersion: "v3",
|
|
async wrapStream({ doStream, params, model: inner }) {
|
|
try {
|
|
return await doStream()
|
|
} catch (error) {
|
|
const retry = withoutDeprecatedParams(error, params)
|
|
if (!retry) throw error
|
|
console.warn(
|
|
"[model params] Rejected sampling or thinking settings, retrying with the model defaults",
|
|
)
|
|
return await inner.doStream(retry)
|
|
}
|
|
},
|
|
},
|
|
})
|
|
}
|