From e73ec6d2d7e3a93f648195d04e3b9786f04913e5 Mon Sep 17 00:00:00 2001 From: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com> Date: Mon, 16 Mar 2026 11:46:41 -0700 Subject: [PATCH] feat(model): add provider fast mode toggle --- packages/app/src/components/prompt-input.tsx | 23 +++++++ .../app/src/components/prompt-input/submit.ts | 7 ++ packages/app/src/context/local.tsx | 42 +++++++++++- packages/app/src/context/model-fast.ts | 28 ++++++++ packages/app/src/i18n/en.ts | 4 ++ .../session/session-model-helpers.test.ts | 20 +++++- .../pages/session/use-session-commands.tsx | 8 +++ packages/app/src/testing/model-selection.ts | 5 +- .../cli/cmd/tui/component/prompt/index.tsx | 27 +++++++- .../src/cli/cmd/tui/context/local.tsx | 35 ++++++++++ packages/opencode/src/provider/fast.ts | 45 +++++++++++++ packages/opencode/src/provider/transform.ts | 5 ++ packages/opencode/src/session/compaction.ts | 1 + packages/opencode/src/session/llm.ts | 12 ++-- packages/opencode/src/session/message-v2.ts | 2 + packages/opencode/src/session/prompt.ts | 7 ++ .../opencode/test/provider/transform.test.ts | 64 +++++++++++++++++++ packages/sdk/js/src/v2/gen/sdk.gen.ts | 6 ++ packages/sdk/js/src/v2/gen/types.gen.ts | 5 ++ 19 files changed, 337 insertions(+), 9 deletions(-) create mode 100644 packages/app/src/context/model-fast.ts create mode 100644 packages/opencode/src/provider/fast.ts diff --git a/packages/app/src/components/prompt-input.tsx b/packages/app/src/components/prompt-input.tsx index b2553e4c02..3d8455f926 100644 --- a/packages/app/src/components/prompt-input.tsx +++ b/packages/app/src/components/prompt-input.tsx @@ -1023,6 +1023,10 @@ export const PromptInput: Component = (props) => { }) const variants = createMemo(() => ["default", ...local.model.variant.list()]) + const fast = createMemo(() => local.model.fast.available()) + const fastLabel = createMemo(() => + language.t(local.model.fast.current() ? "command.model.fast.disable" : "command.model.fast.enable"), + ) const accepting = createMemo(() => { const id = params.id if (!id) return permission.isAutoAcceptingDirectory(sdk.directory) @@ -1534,6 +1538,25 @@ export const PromptInput: Component = (props) => { /> + + + + + ({ id: Identifier.ascending("part"), type: "file" as const, @@ -122,6 +124,7 @@ export async function sendFollowupDraft(input: FollowupSendInput) { agent: input.draft.agent, model: input.draft.model, variant: input.draft.variant, + fast: input.draft.fast, } const add = () => @@ -156,6 +159,7 @@ export async function sendFollowupDraft(input: FollowupSendInput) { messageID, parts: requestParts, variant: input.draft.variant, + fast: input.draft.fast, }) return true } catch (err) { @@ -297,6 +301,7 @@ export function createPromptSubmit(input: PromptSubmitInput) { const currentModel = local.model.current() const currentAgent = local.agent.current() const variant = local.model.variant.current() + const fast = local.model.fast.current() if (!currentModel || !currentAgent) { showToast({ title: language.t("prompt.toast.modelAgentRequired.title"), @@ -398,6 +403,7 @@ export function createPromptSubmit(input: PromptSubmitInput) { agent, model, variant, + fast, } const clearInput = () => { @@ -461,6 +467,7 @@ export function createPromptSubmit(input: PromptSubmitInput) { agent, model: `${model.providerID}/${model.modelID}`, variant, + fast, parts: images.map((attachment) => ({ id: Identifier.ascending("part"), type: "file" as const, diff --git a/packages/app/src/context/local.tsx b/packages/app/src/context/local.tsx index bed7ecd15c..061ba643ee 100644 --- a/packages/app/src/context/local.tsx +++ b/packages/app/src/context/local.tsx @@ -8,6 +8,7 @@ import { useProviders } from "@/hooks/use-providers" import { modelEnabled, modelProbe } from "@/testing/model-selection" import { Persist, persisted } from "@/utils/persist" import { cycleModelVariant, getConfiguredAgentVariant, resolveModelVariant } from "./model-variant" +import * as Fast from "./model-fast" import { useSDK } from "./sdk" import { useSync } from "./sync" @@ -17,6 +18,7 @@ type State = { agent?: string model?: ModelKey variant?: string | null + fast?: boolean } type Saved = { @@ -79,10 +81,11 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ current?: string draft?: State last?: { - type: "agent" | "model" | "variant" + type: "agent" | "model" | "variant" | "fast" agent?: string model?: ModelKey | null variant?: string | null + fast?: boolean } }>({ current: list()[0]?.name, @@ -191,11 +194,13 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ agent: item.name, model: item.model, variant: item.variant ?? null, + fast: scope()?.fast, }) const next = { agent: item.name, model: item.model, variant: item.variant, + fast: scope()?.fast, } satisfies State const session = id() if (session) { @@ -249,6 +254,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ agent: agent.current()?.name, model: model ? { providerID: model.provider.id, modelID: model.id } : undefined, variant: selected(), + fast: !!scope()?.fast && Fast.enabled(model), } satisfies State } @@ -296,6 +302,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ agent: agent.current()?.name, model: item ?? null, variant: selected(), + fast: model.fast.current(), }) write({ model: item }) if (!item) return @@ -333,6 +340,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ agent: agent.current()?.name, model: model ? { providerID: model.provider.id, modelID: model.id } : null, variant: value ?? null, + fast: !!scope()?.fast && Fast.enabled(model), }) write({ variant: value ?? null }) }) @@ -349,6 +357,34 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ ) }, }, + fast: { + selected() { + return scope()?.fast === true + }, + current() { + return this.selected() && this.available() + }, + available() { + return Fast.enabled(current()) + }, + set(value: boolean) { + if (value && !this.available()) return + const model = current() + batch(() => { + setStore("last", { + type: "fast", + agent: agent.current()?.name, + model: model ? { providerID: model.provider.id, modelID: model.id } : null, + variant: selected(), + fast: value, + }) + write({ fast: value || undefined }) + }) + }, + toggle() { + this.set(!this.current()) + }, + }, } const result = { @@ -372,7 +408,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ handoff.set(handoffKey(dir, session), next) setStore("draft", undefined) }, - restore(msg: { sessionID: string; agent: string; model: ModelKey; variant?: string }) { + restore(msg: { sessionID: string; agent: string; model: ModelKey; variant?: string; fast?: boolean }) { const session = id() if (!session) return if (msg.sessionID !== session) return @@ -383,6 +419,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ agent: msg.agent, model: msg.model, variant: msg.variant ?? null, + fast: msg.fast === true, }) }, }, @@ -405,6 +442,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ } : undefined, variant: result.model.variant.current() ?? null, + fast: result.model.fast.current(), selected: result.model.variant.selected(), configured: result.model.variant.configured(), pick: scope(), diff --git a/packages/app/src/context/model-fast.ts b/packages/app/src/context/model-fast.ts new file mode 100644 index 0000000000..f140807569 --- /dev/null +++ b/packages/app/src/context/model-fast.ts @@ -0,0 +1,28 @@ +type Model = { + id: string + provider: { + id: string + } +} + +function lower(model: Model) { + return model.id.toLowerCase() +} + +export function kind(model: Model | undefined) { + if (!model) return + const id = lower(model) + if ( + model.provider.id === "anthropic" && + (id.includes("claude-opus-4-6") || id.includes("claude-opus-4.6") || id.includes("opus-4-6")) + ) { + return "claude" + } + if (model.provider.id === "openai" && id.includes("gpt-5.4")) { + return "codex" + } +} + +export function enabled(model: Model | undefined) { + return !!kind(model) +} diff --git a/packages/app/src/i18n/en.ts b/packages/app/src/i18n/en.ts index ad12e1e0de..7bdfe6bbf2 100644 --- a/packages/app/src/i18n/en.ts +++ b/packages/app/src/i18n/en.ts @@ -67,6 +67,10 @@ export const dict = { "command.agent.cycle.description": "Switch to the next agent", "command.agent.cycle.reverse": "Cycle agent backwards", "command.agent.cycle.reverse.description": "Switch to the previous agent", + "command.model.fast.label": "Fast", + "command.model.fast.enable": "Enable fast mode", + "command.model.fast.disable": "Disable fast mode", + "command.model.fast.description": "Toggle provider fast mode for supported Claude and Codex models", "command.model.variant.cycle": "Cycle thinking effort", "command.model.variant.cycle.description": "Switch to the next effort level", "command.prompt.mode.shell": "Shell", diff --git a/packages/app/src/pages/session/session-model-helpers.test.ts b/packages/app/src/pages/session/session-model-helpers.test.ts index 319db805d2..36494d19b9 100644 --- a/packages/app/src/pages/session/session-model-helpers.test.ts +++ b/packages/app/src/pages/session/session-model-helpers.test.ts @@ -2,7 +2,7 @@ import { describe, expect, test } from "bun:test" import type { UserMessage } from "@opencode-ai/sdk/v2" import { resetSessionModel, syncSessionModel } from "./session-model-helpers" -const message = (input?: Partial>) => +const message = (input?: Partial>) => ({ id: "msg", sessionID: "session", @@ -31,6 +31,24 @@ describe("syncSessionModel", () => { expect(calls).toEqual([message({ variant: "high" })]) }) + + test("restores fast mode from the last message", () => { + const calls: unknown[] = [] + + syncSessionModel( + { + session: { + restore(value) { + calls.push(value) + }, + reset() {}, + }, + }, + message({ fast: true }), + ) + + expect(calls).toEqual([message({ fast: true })]) + }) }) describe("resetSessionModel", () => { diff --git a/packages/app/src/pages/session/use-session-commands.tsx b/packages/app/src/pages/session/use-session-commands.tsx index 1a2e777f52..ed31a248d4 100644 --- a/packages/app/src/pages/session/use-session-commands.tsx +++ b/packages/app/src/pages/session/use-session-commands.tsx @@ -353,6 +353,14 @@ export const useSessionCommands = (actions: SessionCommandContext) => { slash: "model", onSelect: () => dialog.show(() => ), }), + modelCommand({ + id: "model.fast.toggle", + title: language.t(local.model.fast.current() ? "command.model.fast.disable" : "command.model.fast.enable"), + description: language.t("command.model.fast.description"), + slash: "fast", + disabled: !local.model.fast.available(), + onSelect: () => local.model.fast.toggle(), + }), mcpCommand({ id: "mcp.toggle", title: language.t("command.mcp.toggle"), diff --git a/packages/app/src/testing/model-selection.ts b/packages/app/src/testing/model-selection.ts index a5ea199ac1..2dae0e3454 100644 --- a/packages/app/src/testing/model-selection.ts +++ b/packages/app/src/testing/model-selection.ts @@ -7,20 +7,23 @@ type State = { agent?: string model?: ModelKey | null variant?: string | null + fast?: boolean } export type ModelProbeState = { dir?: string sessionID?: string last?: { - type: "agent" | "model" | "variant" + type: "agent" | "model" | "variant" | "fast" agent?: string model?: ModelKey | null variant?: string | null + fast?: boolean } agent?: string model?: (ModelKey & { name?: string }) | undefined variant?: string | null + fast?: boolean selected?: string | null configured?: string pick?: State diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx index c85426cc24..1685f0df6b 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx @@ -164,7 +164,8 @@ export function Prompt(props: PromptProps) { if (msg.agent && isPrimaryAgent) { local.agent.set(msg.agent) if (msg.model) local.model.set(msg.model) - if (msg.variant) local.model.variant.set(msg.variant) + local.model.variant.set(msg.variant) + local.model.fast.set(msg.fast === true) } } }) @@ -330,6 +331,19 @@ export function Prompt(props: PromptProps) { input.cursorOffset = Bun.stringWidth(content) }, }, + { + title: local.model.fast.current() ? "Disable fast mode" : "Enable fast mode", + value: "model.fast", + category: "Model", + enabled: local.model.fast.available(), + slash: { + name: "fast", + }, + onSelect: (dialog) => { + local.model.fast.toggle() + dialog.clear() + }, + }, { title: "Skills", value: "prompt.skills", @@ -586,6 +600,7 @@ export function Prompt(props: PromptProps) { // Capture mode before it gets reset const currentMode = store.mode const variant = local.model.variant.current() + const fast = local.model.fast.current() if (store.mode === "shell") { sdk.client.session.shell({ @@ -621,6 +636,7 @@ export function Prompt(props: PromptProps) { model: `${selectedModel.providerID}/${selectedModel.modelID}`, messageID, variant, + fast, parts: nonTextParts .filter((x) => x.type === "file") .map((x) => ({ @@ -637,6 +653,7 @@ export function Prompt(props: PromptProps) { agent: local.agent.current().name, model: selectedModel, variant, + fast, parts: [ { id: PartID.ascending(), @@ -765,6 +782,8 @@ export function Prompt(props: PromptProps) { return !!current }) + const showFast = createMemo(() => local.model.fast.current()) + const placeholderText = createMemo(() => { if (props.sessionID) return undefined if (store.mode === "shell") { @@ -1028,6 +1047,12 @@ export function Prompt(props: PromptProps) { {local.model.variant.current()} + + ยท + + fast + + diff --git a/packages/opencode/src/cli/cmd/tui/context/local.tsx b/packages/opencode/src/cli/cmd/tui/context/local.tsx index d93079f12a..5a15177075 100644 --- a/packages/opencode/src/cli/cmd/tui/context/local.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/local.tsx @@ -13,6 +13,7 @@ import { useArgs } from "./args" import { useSDK } from "./sdk" import { RGBA } from "@opentui/core" import { Filesystem } from "@/util/filesystem" +import * as Fast from "@/provider/fast" export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ name: "Local", @@ -112,12 +113,14 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ modelID: string }[] variant: Record + fast: Record }>({ ready: false, model: {}, recent: [], favorite: [], variant: {}, + fast: {}, }) const filePath = path.join(Global.Path.state, "model.json") @@ -135,6 +138,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ recent: modelStore.recent, favorite: modelStore.favorite, variant: modelStore.variant, + fast: modelStore.fast, }) } @@ -143,6 +147,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ if (Array.isArray(x.recent)) setModelStore("recent", x.recent) if (Array.isArray(x.favorite)) setModelStore("favorite", x.favorite) if (typeof x.variant === "object" && x.variant !== null) setModelStore("variant", x.variant) + if (typeof x.fast === "object" && x.fast !== null) setModelStore("fast", x.fast) }) .catch(() => {}) .finally(() => { @@ -358,6 +363,36 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ this.set(variants[index + 1]) }, }, + fast: { + selected() { + const m = currentModel() + if (!m) return false + const key = `${m.providerID}/${m.modelID}` + return modelStore.fast[key] === true + }, + current() { + return this.selected() && this.available() + }, + available() { + const m = currentModel() + if (!m) return false + const provider = sync.data.provider.find((x) => x.id === m.providerID) + const info = provider?.models[m.modelID] + if (!info) return false + return Fast.enabled(info, { codex: info.providerID === "openai" }) + }, + set(value: boolean) { + const m = currentModel() + if (!m) return + if (value && !this.available()) return + const key = `${m.providerID}/${m.modelID}` + setModelStore("fast", key, value || undefined) + save() + }, + toggle() { + this.set(!this.current()) + }, + }, } }) diff --git a/packages/opencode/src/provider/fast.ts b/packages/opencode/src/provider/fast.ts new file mode 100644 index 0000000000..a344a63ac4 --- /dev/null +++ b/packages/opencode/src/provider/fast.ts @@ -0,0 +1,45 @@ +type Model = { + providerID: string + api: { + id: string + npm: string + } +} + +function lower(model: Pick) { + return model.api.id.toLowerCase() +} + +type Input = { + codex?: boolean +} + +export function kind(model: Pick, input?: Input) { + const id = lower(model) + if ( + model.providerID === "anthropic" && + model.api.npm === "@ai-sdk/anthropic" && + (id.includes("claude-opus-4-6") || id.includes("claude-opus-4.6") || id.includes("opus-4-6")) + ) { + return "claude" + } + if ( + model.providerID === "openai" && + input?.codex === true && + model.api.npm === "@ai-sdk/openai" && + id.includes("gpt-5.4") + ) { + return "codex" + } +} + +export function enabled(model: Pick, input?: Input) { + return !!kind(model, input) +} + +export function options(model: Pick, input?: Input) { + const mode = kind(model, input) + if (mode === "claude") return { speed: "fast" } + if (mode === "codex") return { serviceTier: "priority" } + return {} +} diff --git a/packages/opencode/src/provider/transform.ts b/packages/opencode/src/provider/transform.ts index 05b9f031fe..75a8b0370d 100644 --- a/packages/opencode/src/provider/transform.ts +++ b/packages/opencode/src/provider/transform.ts @@ -6,6 +6,7 @@ import type { Provider } from "./provider" import type { ModelsDev } from "./models" import { iife } from "@/util/iife" import { Flag } from "@/flag/flag" +import * as Fast from "./fast" type Modality = NonNullable["input"][number] @@ -905,6 +906,10 @@ export namespace ProviderTransform { return { [key]: options } } + export function fast(model: Provider.Model, input?: { codex?: boolean }) { + return Fast.options(model, input) + } + export function maxOutputTokens(model: Provider.Model): number { return Math.min(model.limit.output, OUTPUT_TOKEN_MAX) || OUTPUT_TOKEN_MAX } diff --git a/packages/opencode/src/session/compaction.ts b/packages/opencode/src/session/compaction.ts index 8d934c05da..6342132d33 100644 --- a/packages/opencode/src/session/compaction.ts +++ b/packages/opencode/src/session/compaction.ts @@ -141,6 +141,7 @@ export namespace SessionCompaction { mode: "compaction", agent: "compaction", variant: userMessage.variant, + fast: userMessage.fast, summary: true, path: { cwd: Instance.directory, diff --git a/packages/opencode/src/session/llm.ts b/packages/opencode/src/session/llm.ts index 4e42fb0d2e..5479ee8bb2 100644 --- a/packages/opencode/src/session/llm.ts +++ b/packages/opencode/src/session/llm.ts @@ -101,11 +101,15 @@ export namespace LLM { sessionID: input.sessionID, providerOptions: provider.options, }) + const fast = ( + input.small || !input.user.fast ? {} : ProviderTransform.fast(input.model, { codex: isCodex }) + ) as Record const options: Record = pipe( - base, - mergeDeep(input.model.options), - mergeDeep(input.agent.options), - mergeDeep(variant), + base as Record, + mergeDeep(input.model.options as Record), + mergeDeep(input.agent.options as Record), + mergeDeep(variant as Record), + mergeDeep(fast), ) if (isCodex) { options.instructions = SystemPrompt.instructions() diff --git a/packages/opencode/src/session/message-v2.ts b/packages/opencode/src/session/message-v2.ts index 8e4babd619..23d4d901c6 100644 --- a/packages/opencode/src/session/message-v2.ts +++ b/packages/opencode/src/session/message-v2.ts @@ -369,6 +369,7 @@ export namespace MessageV2 { system: z.string().optional(), tools: z.record(z.string(), z.boolean()).optional(), variant: z.string().optional(), + fast: z.boolean().optional(), }).meta({ ref: "UserMessage", }) @@ -437,6 +438,7 @@ export namespace MessageV2 { }), structured: z.any().optional(), variant: z.string().optional(), + fast: z.boolean().optional(), finish: z.string().optional(), }).meta({ ref: "AssistantMessage", diff --git a/packages/opencode/src/session/prompt.ts b/packages/opencode/src/session/prompt.ts index 743537f598..5612d6ba81 100644 --- a/packages/opencode/src/session/prompt.ts +++ b/packages/opencode/src/session/prompt.ts @@ -111,6 +111,7 @@ export namespace SessionPrompt { format: MessageV2.Format.optional(), system: z.string().optional(), variant: z.string().optional(), + fast: z.boolean().optional(), parts: z.array( z.discriminatedUnion("type", [ MessageV2.TextPart.omit({ @@ -363,6 +364,7 @@ export namespace SessionPrompt { mode: task.agent, agent: task.agent, variant: lastUser.variant, + fast: lastUser.fast, path: { cwd: Instance.directory, root: Instance.worktree, @@ -575,6 +577,7 @@ export namespace SessionPrompt { mode: agent.name, agent: agent.name, variant: lastUser.variant, + fast: lastUser.fast, path: { cwd: Instance.directory, root: Instance.worktree, @@ -984,6 +987,7 @@ export namespace SessionPrompt { system: input.system, format: input.format, variant, + fast: input.fast, } using _ = defer(() => InstructionPrompt.clear(info.id)) @@ -1310,6 +1314,7 @@ export namespace SessionPrompt { model: input.model, messageID: input.messageID, variant: input.variant, + fast: input.fast, }, { message: info, @@ -1727,6 +1732,7 @@ NOTE: At any point in time through this workflow you should feel free to ask the arguments: z.string(), command: z.string(), variant: z.string().optional(), + fast: z.boolean().optional(), parts: z .array( z.discriminatedUnion("type", [ @@ -1884,6 +1890,7 @@ NOTE: At any point in time through this workflow you should feel free to ask the agent: userAgent, parts, variant: input.variant, + fast: input.fast, })) as MessageV2.WithParts Bus.publish(Command.Event.Executed, { diff --git a/packages/opencode/test/provider/transform.test.ts b/packages/opencode/test/provider/transform.test.ts index 917d357eaf..e5037e36b3 100644 --- a/packages/opencode/test/provider/transform.test.ts +++ b/packages/opencode/test/provider/transform.test.ts @@ -176,6 +176,70 @@ describe("ProviderTransform.options - gpt-5 textVerbosity", () => { }) }) +describe("ProviderTransform.fast", () => { + const createModel = (input: { providerID: string; modelID: string; npm: string }) => + ({ + id: input.modelID, + providerID: input.providerID, + api: { + id: input.modelID, + url: "https://example.com", + npm: input.npm, + }, + name: input.modelID, + capabilities: { + temperature: true, + reasoning: true, + attachment: true, + toolcall: true, + input: { text: true, audio: false, image: true, video: false, pdf: false }, + output: { text: true, audio: false, image: false, video: false, pdf: false }, + interleaved: false, + }, + cost: { input: 0, output: 0, cache: { read: 0, write: 0 } }, + limit: { context: 200000, output: 8192 }, + status: "active", + options: {}, + headers: {}, + }) as any + + test("uses speed fast for anthropic opus 4.6", () => { + const model = createModel({ + providerID: "anthropic", + modelID: "claude-opus-4-6", + npm: "@ai-sdk/anthropic", + }) + expect(ProviderTransform.fast(model)).toEqual({ speed: "fast" }) + }) + + test("uses priority service tier for openai gpt-5 codex models", () => { + const model = createModel({ + providerID: "openai", + modelID: "gpt-5.4", + npm: "@ai-sdk/openai", + }) + expect(ProviderTransform.fast(model, { codex: true })).toEqual({ serviceTier: "priority" }) + }) + + test("returns empty options for unsupported models", () => { + const model = createModel({ + providerID: "anthropic", + modelID: "claude-sonnet-4-6", + npm: "@ai-sdk/anthropic", + }) + expect(ProviderTransform.fast(model)).toEqual({}) + }) + + test("returns empty options for openai api mode", () => { + const model = createModel({ + providerID: "openai", + modelID: "gpt-5.4", + npm: "@ai-sdk/openai", + }) + expect(ProviderTransform.fast(model)).toEqual({}) + }) +}) + describe("ProviderTransform.options - gateway", () => { const sessionID = "test-session-123" diff --git a/packages/sdk/js/src/v2/gen/sdk.gen.ts b/packages/sdk/js/src/v2/gen/sdk.gen.ts index 27c188838b..97fa44f6f3 100644 --- a/packages/sdk/js/src/v2/gen/sdk.gen.ts +++ b/packages/sdk/js/src/v2/gen/sdk.gen.ts @@ -1841,6 +1841,7 @@ export class Session2 extends HeyApiClient { format?: OutputFormat system?: string variant?: string + fast?: boolean parts?: Array }, options?: Options, @@ -1861,6 +1862,7 @@ export class Session2 extends HeyApiClient { { in: "body", key: "format" }, { in: "body", key: "system" }, { in: "body", key: "variant" }, + { in: "body", key: "fast" }, { in: "body", key: "parts" }, ], }, @@ -1973,6 +1975,7 @@ export class Session2 extends HeyApiClient { format?: OutputFormat system?: string variant?: string + fast?: boolean parts?: Array }, options?: Options, @@ -1993,6 +1996,7 @@ export class Session2 extends HeyApiClient { { in: "body", key: "format" }, { in: "body", key: "system" }, { in: "body", key: "variant" }, + { in: "body", key: "fast" }, { in: "body", key: "parts" }, ], }, @@ -2026,6 +2030,7 @@ export class Session2 extends HeyApiClient { arguments?: string command?: string variant?: string + fast?: boolean parts?: Array<{ id?: string type: "file" @@ -2051,6 +2056,7 @@ export class Session2 extends HeyApiClient { { in: "body", key: "arguments" }, { in: "body", key: "command" }, { in: "body", key: "variant" }, + { in: "body", key: "fast" }, { in: "body", key: "parts" }, ], }, diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index 9ab71bd8f5..a03e82c493 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -238,6 +238,7 @@ export type UserMessage = { [key: string]: boolean } variant?: string + fast?: boolean } export type ProviderAuthError = { @@ -340,6 +341,7 @@ export type AssistantMessage = { } structured?: unknown variant?: string + fast?: boolean finish?: string } @@ -3284,6 +3286,7 @@ export type SessionPromptData = { format?: OutputFormat system?: string variant?: string + fast?: boolean parts: Array } path: { @@ -3484,6 +3487,7 @@ export type SessionPromptAsyncData = { format?: OutputFormat system?: string variant?: string + fast?: boolean parts: Array } path: { @@ -3526,6 +3530,7 @@ export type SessionCommandData = { arguments: string command: string variant?: string + fast?: boolean parts?: Array<{ id?: string type: "file"