Skip to content

Commit c33d999

Browse files
authored
feat: AI SDK v6 support (#18433)
1 parent 7a7643c commit c33d999

36 files changed

+1290
-1155
lines changed

bun.lock

Lines changed: 63 additions & 183 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
"drizzle-kit": "1.0.0-beta.19-d95b7a4",
4747
"drizzle-orm": "1.0.0-beta.19-d95b7a4",
4848
"effect": "4.0.0-beta.37",
49-
"ai": "5.0.124",
49+
"ai": "6.0.138",
5050
"hono": "4.10.7",
5151
"hono-openapi": "1.1.2",
5252
"fuzzysort": "3.1.0",
@@ -113,8 +113,8 @@
113113
},
114114
"patchedDependencies": {
115115
"@standard-community/standard-openapi@0.2.9": "patches/@standard-community%2Fstandard-openapi@0.2.9.patch",
116-
"@openrouter/ai-sdk-provider@1.5.4": "patches/@openrouter%2Fai-sdk-provider@1.5.4.patch",
117-
"@ai-sdk/xai@2.0.51": "patches/@ai-sdk%2Fxai@2.0.51.patch",
118-
"solid-js@1.9.10": "patches/solid-js@1.9.10.patch"
116+
"solid-js@1.9.10": "patches/solid-js@1.9.10.patch",
117+
"@ai-sdk/provider-utils@4.0.21": "patches/@ai-sdk%2Fprovider-utils@4.0.21.patch",
118+
"@ai-sdk/anthropic@3.0.64": "patches/@ai-sdk%2Fanthropic@3.0.64.patch"
119119
}
120120
}

packages/console/function/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
"@typescript/native-preview": "catalog:"
1818
},
1919
"dependencies": {
20-
"@ai-sdk/anthropic": "2.0.0",
21-
"@ai-sdk/openai": "2.0.2",
22-
"@ai-sdk/openai-compatible": "1.0.1",
20+
"@ai-sdk/anthropic": "3.0.64",
21+
"@ai-sdk/openai": "3.0.48",
22+
"@ai-sdk/openai-compatible": "2.0.37",
2323
"@hono/zod-validator": "catalog:",
2424
"@opencode-ai/console-core": "workspace:*",
2525
"@opencode-ai/console-resource": "workspace:*",

packages/opencode/package.json

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -68,25 +68,25 @@
6868
"@actions/core": "1.11.1",
6969
"@actions/github": "6.0.1",
7070
"@agentclientprotocol/sdk": "0.14.1",
71-
"@ai-sdk/amazon-bedrock": "3.0.82",
72-
"@ai-sdk/anthropic": "2.0.65",
73-
"@ai-sdk/azure": "2.0.91",
74-
"@ai-sdk/cerebras": "1.0.36",
75-
"@ai-sdk/cohere": "2.0.22",
76-
"@ai-sdk/deepinfra": "1.0.36",
77-
"@ai-sdk/gateway": "2.0.30",
78-
"@ai-sdk/google": "2.0.54",
79-
"@ai-sdk/google-vertex": "3.0.106",
80-
"@ai-sdk/groq": "2.0.34",
81-
"@ai-sdk/mistral": "2.0.27",
82-
"@ai-sdk/openai": "2.0.89",
83-
"@ai-sdk/openai-compatible": "1.0.32",
84-
"@ai-sdk/perplexity": "2.0.23",
85-
"@ai-sdk/provider": "2.0.1",
86-
"@ai-sdk/provider-utils": "3.0.21",
87-
"@ai-sdk/togetherai": "1.0.34",
88-
"@ai-sdk/vercel": "1.0.33",
89-
"@ai-sdk/xai": "2.0.51",
71+
"@ai-sdk/amazon-bedrock": "4.0.83",
72+
"@ai-sdk/anthropic": "3.0.64",
73+
"@ai-sdk/azure": "3.0.49",
74+
"@ai-sdk/cerebras": "2.0.41",
75+
"@ai-sdk/cohere": "3.0.27",
76+
"@ai-sdk/deepinfra": "2.0.41",
77+
"@ai-sdk/gateway": "3.0.80",
78+
"@ai-sdk/google": "3.0.53",
79+
"@ai-sdk/google-vertex": "4.0.95",
80+
"@ai-sdk/groq": "3.0.31",
81+
"@ai-sdk/mistral": "3.0.27",
82+
"@ai-sdk/openai": "3.0.48",
83+
"@ai-sdk/openai-compatible": "2.0.37",
84+
"@ai-sdk/perplexity": "3.0.26",
85+
"@ai-sdk/provider": "3.0.8",
86+
"@ai-sdk/provider-utils": "4.0.21",
87+
"@ai-sdk/togetherai": "2.0.41",
88+
"@ai-sdk/vercel": "2.0.39",
89+
"@ai-sdk/xai": "3.0.74",
9090
"@aws-sdk/credential-providers": "3.993.0",
9191
"@clack/prompts": "1.0.0-alpha.1",
9292
"@effect/platform-node": "catalog:",
@@ -100,7 +100,7 @@
100100
"@opencode-ai/script": "workspace:*",
101101
"@opencode-ai/sdk": "workspace:*",
102102
"@opencode-ai/util": "workspace:*",
103-
"@openrouter/ai-sdk-provider": "1.5.4",
103+
"@openrouter/ai-sdk-provider": "2.3.3",
104104
"@opentui/core": "0.1.90",
105105
"@opentui/solid": "0.1.90",
106106
"@parcel/watcher": "2.5.1",
@@ -110,7 +110,7 @@
110110
"@standard-schema/spec": "1.0.0",
111111
"@zip.js/zip.js": "2.7.62",
112112
"ai": "catalog:",
113-
"ai-gateway-provider": "2.3.1",
113+
"ai-gateway-provider": "3.1.2",
114114
"bonjour-service": "1.3.0",
115115
"bun-pty": "0.4.8",
116116
"chokidar": "4.0.3",
@@ -121,7 +121,7 @@
121121
"drizzle-orm": "catalog:",
122122
"effect": "catalog:",
123123
"fuzzysort": "3.1.0",
124-
"gitlab-ai-provider": "5.3.3",
124+
"gitlab-ai-provider": "6.0.0",
125125
"glob": "13.0.5",
126126
"google-auth-library": "10.5.0",
127127
"gray-matter": "4.0.3",

packages/opencode/src/provider/provider.ts

Lines changed: 56 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { BunProc } from "../bun"
99
import { Hash } from "../util/hash"
1010
import { Plugin } from "../plugin"
1111
import { NamedError } from "@opencode-ai/util/error"
12+
import { type LanguageModelV3 } from "@ai-sdk/provider"
1213
import { ModelsDev } from "./models"
1314
import { Auth } from "../auth"
1415
import { Env } from "../env"
@@ -28,7 +29,7 @@ import { createVertex } from "@ai-sdk/google-vertex"
2829
import { createVertexAnthropic } from "@ai-sdk/google-vertex/anthropic"
2930
import { createOpenAI } from "@ai-sdk/openai"
3031
import { createOpenAICompatible } from "@ai-sdk/openai-compatible"
31-
import { createOpenRouter, type LanguageModelV2 } from "@openrouter/ai-sdk-provider"
32+
import { createOpenRouter } from "@openrouter/ai-sdk-provider"
3233
import { createOpenaiCompatible as createGitHubCopilotOpenAICompatible } from "./sdk/copilot"
3334
import { createXai } from "@ai-sdk/xai"
3435
import { createMistral } from "@ai-sdk/mistral"
@@ -109,7 +110,11 @@ export namespace Provider {
109110
})
110111
}
111112

112-
const BUNDLED_PROVIDERS: Record<string, (options: any) => SDK> = {
113+
type BundledSDK = {
114+
languageModel(modelId: string): LanguageModelV3
115+
}
116+
117+
const BUNDLED_PROVIDERS: Record<string, (options: any) => BundledSDK> = {
113118
"@ai-sdk/amazon-bedrock": createAmazonBedrock,
114119
"@ai-sdk/anthropic": createAnthropic,
115120
"@ai-sdk/azure": createAzure,
@@ -130,7 +135,6 @@ export namespace Provider {
130135
"@ai-sdk/perplexity": createPerplexity,
131136
"@ai-sdk/vercel": createVercel,
132137
"gitlab-ai-provider": createGitLab,
133-
// @ts-ignore (TODO: kill this code so we dont have to maintain it)
134138
"@ai-sdk/github-copilot": createGitHubCopilotOpenAICompatible,
135139
}
136140

@@ -591,7 +595,12 @@ export namespace Provider {
591595

592596
if (!result.models.length) {
593597
log.info("gitlab model discovery skipped: no models found", {
594-
project: result.project ? { id: result.project.id, path: result.project.pathWithNamespace } : null,
598+
project: result.project
599+
? {
600+
id: result.project.id,
601+
path: result.project.pathWithNamespace,
602+
}
603+
: null,
595604
})
596605
return {}
597606
}
@@ -619,8 +628,20 @@ export namespace Provider {
619628
reasoning: true,
620629
attachment: true,
621630
toolcall: true,
622-
input: { text: true, audio: false, image: true, video: false, pdf: true },
623-
output: { text: true, audio: false, image: false, video: false, pdf: false },
631+
input: {
632+
text: true,
633+
audio: false,
634+
image: true,
635+
video: false,
636+
pdf: true,
637+
},
638+
output: {
639+
text: true,
640+
audio: false,
641+
image: false,
642+
video: false,
643+
pdf: false,
644+
},
624645
interleaved: false,
625646
},
626647
release_date: "",
@@ -930,17 +951,17 @@ export namespace Provider {
930951
}
931952

932953
const providers: Record<ProviderID, Info> = {} as Record<ProviderID, Info>
933-
const languages = new Map<string, LanguageModelV2>()
954+
const languages = new Map<string, LanguageModelV3>()
934955
const modelLoaders: {
935956
[providerID: string]: CustomModelLoader
936957
} = {}
937958
const varsLoaders: {
938959
[providerID: string]: CustomVarsLoader
939960
} = {}
961+
const sdk = new Map<string, BundledSDK>()
940962
const discoveryLoaders: {
941963
[providerID: string]: CustomDiscoverModels
942964
} = {}
943-
const sdk = new Map<string, SDK>()
944965

945966
log.info("init")
946967

@@ -1232,7 +1253,13 @@ export namespace Provider {
12321253
...model.headers,
12331254
}
12341255

1235-
const key = Hash.fast(JSON.stringify({ providerID: model.providerID, npm: model.api.npm, options }))
1256+
const key = Hash.fast(
1257+
JSON.stringify({
1258+
providerID: model.providerID,
1259+
npm: model.api.npm,
1260+
options,
1261+
}),
1262+
)
12361263
const existing = s.sdk.get(key)
12371264
if (existing) return existing
12381265

@@ -1285,7 +1312,10 @@ export namespace Provider {
12851312

12861313
const bundledFn = BUNDLED_PROVIDERS[model.api.npm]
12871314
if (bundledFn) {
1288-
log.info("using bundled provider", { providerID: model.providerID, pkg: model.api.npm })
1315+
log.info("using bundled provider", {
1316+
providerID: model.providerID,
1317+
pkg: model.api.npm,
1318+
})
12891319
const loaded = bundledFn({
12901320
name: model.providerID,
12911321
...options,
@@ -1325,22 +1355,28 @@ export namespace Provider {
13251355
const provider = s.providers[providerID]
13261356
if (!provider) {
13271357
const availableProviders = Object.keys(s.providers)
1328-
const matches = fuzzysort.go(providerID, availableProviders, { limit: 3, threshold: -10000 })
1358+
const matches = fuzzysort.go(providerID, availableProviders, {
1359+
limit: 3,
1360+
threshold: -10000,
1361+
})
13291362
const suggestions = matches.map((m) => m.target)
13301363
throw new ModelNotFoundError({ providerID, modelID, suggestions })
13311364
}
13321365

13331366
const info = provider.models[modelID]
13341367
if (!info) {
13351368
const availableModels = Object.keys(provider.models)
1336-
const matches = fuzzysort.go(modelID, availableModels, { limit: 3, threshold: -10000 })
1369+
const matches = fuzzysort.go(modelID, availableModels, {
1370+
limit: 3,
1371+
threshold: -10000,
1372+
})
13371373
const suggestions = matches.map((m) => m.target)
13381374
throw new ModelNotFoundError({ providerID, modelID, suggestions })
13391375
}
13401376
return info
13411377
}
13421378

1343-
export async function getLanguage(model: Model): Promise<LanguageModelV2> {
1379+
export async function getLanguage(model: Model): Promise<LanguageModelV3> {
13441380
const s = await state()
13451381
const key = `${model.providerID}/${model.id}`
13461382
if (s.models.has(key)) return s.models.get(key)!
@@ -1350,7 +1386,10 @@ export namespace Provider {
13501386

13511387
try {
13521388
const language = s.modelLoaders[model.providerID]
1353-
? await s.modelLoaders[model.providerID](sdk, model.api.id, { ...provider.options, ...model.options })
1389+
? await s.modelLoaders[model.providerID](sdk, model.api.id, {
1390+
...provider.options,
1391+
...model.options,
1392+
})
13541393
: sdk.languageModel(model.api.id)
13551394
s.models.set(key, language)
13561395
return language
@@ -1457,9 +1496,9 @@ export namespace Provider {
14571496
if (cfg.model) return parseModel(cfg.model)
14581497

14591498
const providers = await list()
1460-
const recent = (await Filesystem.readJson<{ recent?: { providerID: ProviderID; modelID: ModelID }[] }>(
1461-
path.join(Global.Path.state, "model.json"),
1462-
)
1499+
const recent = (await Filesystem.readJson<{
1500+
recent?: { providerID: ProviderID; modelID: ModelID }[]
1501+
}>(path.join(Global.Path.state, "model.json"))
14631502
.then((x) => (Array.isArray(x.recent) ? x.recent : []))
14641503
.catch(() => [])) as { providerID: ProviderID; modelID: ModelID }[]
14651504
for (const entry of recent) {

packages/opencode/src/provider/sdk/copilot/chat/convert-to-openai-compatible-chat-messages.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
import {
2-
type LanguageModelV2Prompt,
3-
type SharedV2ProviderMetadata,
2+
type LanguageModelV3Prompt,
3+
type SharedV3ProviderOptions,
44
UnsupportedFunctionalityError,
55
} from "@ai-sdk/provider"
66
import type { OpenAICompatibleChatPrompt } from "./openai-compatible-api-types"
77
import { convertToBase64 } from "@ai-sdk/provider-utils"
88

9-
function getOpenAIMetadata(message: { providerOptions?: SharedV2ProviderMetadata }) {
9+
function getOpenAIMetadata(message: { providerOptions?: SharedV3ProviderOptions }) {
1010
return message?.providerOptions?.copilot ?? {}
1111
}
1212

13-
export function convertToOpenAICompatibleChatMessages(prompt: LanguageModelV2Prompt): OpenAICompatibleChatPrompt {
13+
export function convertToOpenAICompatibleChatMessages(prompt: LanguageModelV3Prompt): OpenAICompatibleChatPrompt {
1414
const messages: OpenAICompatibleChatPrompt = []
1515
for (const { role, content, ...message } of prompt) {
1616
const metadata = getOpenAIMetadata({ ...message })
@@ -127,6 +127,9 @@ export function convertToOpenAICompatibleChatMessages(prompt: LanguageModelV2Pro
127127

128128
case "tool": {
129129
for (const toolResponse of content) {
130+
if (toolResponse.type === "tool-approval-response") {
131+
continue
132+
}
130133
const output = toolResponse.output
131134

132135
let contentValue: string
@@ -135,6 +138,9 @@ export function convertToOpenAICompatibleChatMessages(prompt: LanguageModelV2Pro
135138
case "error-text":
136139
contentValue = output.value
137140
break
141+
case "execution-denied":
142+
contentValue = output.reason ?? "Tool execution denied."
143+
break
138144
case "content":
139145
case "json":
140146
case "error-json":

packages/opencode/src/provider/sdk/copilot/chat/map-openai-compatible-finish-reason.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
import type { LanguageModelV2FinishReason } from "@ai-sdk/provider"
1+
import type { LanguageModelV3FinishReason } from "@ai-sdk/provider"
22

3-
export function mapOpenAICompatibleFinishReason(finishReason: string | null | undefined): LanguageModelV2FinishReason {
3+
export function mapOpenAICompatibleFinishReason(
4+
finishReason: string | null | undefined,
5+
): LanguageModelV3FinishReason["unified"] {
46
switch (finishReason) {
57
case "stop":
68
return "stop"
@@ -12,6 +14,6 @@ export function mapOpenAICompatibleFinishReason(finishReason: string | null | un
1214
case "tool_calls":
1315
return "tool-calls"
1416
default:
15-
return "unknown"
17+
return "other"
1618
}
1719
}

0 commit comments

Comments
 (0)