Merge branch 'dev' of https://github.com/sst/opencode into dev

This commit is contained in:
David Hill
2025-10-31 16:03:36 +00:00
3 changed files with 62 additions and 21 deletions

View File

@@ -35,7 +35,7 @@ export namespace ModelsDev {
}) })
.optional(), .optional(),
experimental: z.boolean().optional(), experimental: z.boolean().optional(),
status: z.enum(["alpha", "beta"]).optional(), status: z.enum(["alpha", "beta", "deprecated"]).optional(),
options: z.record(z.string(), z.any()), options: z.record(z.string(), z.any()),
headers: z.record(z.string(), z.string()).optional(), headers: z.record(z.string(), z.string()).optional(),
provider: z.object({ npm: z.string() }).optional(), provider: z.object({ npm: z.string() }).optional(),

View File

@@ -78,12 +78,18 @@ export namespace Provider {
} }
}, },
"amazon-bedrock": async () => { "amazon-bedrock": async () => {
if (!process.env["AWS_PROFILE"] && !process.env["AWS_ACCESS_KEY_ID"] && !process.env["AWS_BEARER_TOKEN_BEDROCK"]) if (
!process.env["AWS_PROFILE"] &&
!process.env["AWS_ACCESS_KEY_ID"] &&
!process.env["AWS_BEARER_TOKEN_BEDROCK"]
)
return { autoload: false } return { autoload: false }
const region = process.env["AWS_REGION"] ?? "us-east-1" const region = process.env["AWS_REGION"] ?? "us-east-1"
const { fromNodeProviderChain } = await import(await BunProc.install("@aws-sdk/credential-providers")) const { fromNodeProviderChain } = await import(
await BunProc.install("@aws-sdk/credential-providers")
)
return { return {
autoload: true, autoload: true,
options: { options: {
@@ -118,9 +124,13 @@ export namespace Provider {
"eu-south-1", "eu-south-1",
"eu-south-2", "eu-south-2",
].some((r) => region.includes(r)) ].some((r) => region.includes(r))
const modelRequiresPrefix = ["claude", "nova-lite", "nova-micro", "llama3", "pixtral"].some((m) => const modelRequiresPrefix = [
modelID.includes(m), "claude",
) "nova-lite",
"nova-micro",
"llama3",
"pixtral",
].some((m) => modelID.includes(m))
if (regionRequiresPrefix && modelRequiresPrefix) { if (regionRequiresPrefix && modelRequiresPrefix) {
modelID = `${regionPrefix}.${modelID}` modelID = `${regionPrefix}.${modelID}`
} }
@@ -130,13 +140,15 @@ export namespace Provider {
const isAustraliaRegion = ["ap-southeast-2", "ap-southeast-4"].includes(region) const isAustraliaRegion = ["ap-southeast-2", "ap-southeast-4"].includes(region)
if ( if (
isAustraliaRegion && isAustraliaRegion &&
["anthropic.claude-sonnet-4-5", "anthropic.claude-haiku"].some((m) => modelID.includes(m)) ["anthropic.claude-sonnet-4-5", "anthropic.claude-haiku"].some((m) =>
modelID.includes(m),
)
) { ) {
regionPrefix = "au" regionPrefix = "au"
modelID = `${regionPrefix}.${modelID}` modelID = `${regionPrefix}.${modelID}`
} else { } else {
const modelRequiresPrefix = ["claude", "nova-lite", "nova-micro", "nova-pro"].some((m) => const modelRequiresPrefix = ["claude", "nova-lite", "nova-micro", "nova-pro"].some(
modelID.includes(m), (m) => modelID.includes(m),
) )
if (modelRequiresPrefix) { if (modelRequiresPrefix) {
regionPrefix = "apac" regionPrefix = "apac"
@@ -174,8 +186,12 @@ export namespace Provider {
} }
}, },
"google-vertex": async () => { "google-vertex": async () => {
const project = process.env["GOOGLE_CLOUD_PROJECT"] ?? process.env["GCP_PROJECT"] ?? process.env["GCLOUD_PROJECT"] const project =
const location = process.env["GOOGLE_CLOUD_LOCATION"] ?? process.env["VERTEX_LOCATION"] ?? "us-east5" process.env["GOOGLE_CLOUD_PROJECT"] ??
process.env["GCP_PROJECT"] ??
process.env["GCLOUD_PROJECT"]
const location =
process.env["GOOGLE_CLOUD_LOCATION"] ?? process.env["VERTEX_LOCATION"] ?? "us-east5"
const autoload = Boolean(project) const autoload = Boolean(project)
if (!autoload) return { autoload: false } if (!autoload) return { autoload: false }
return { return {
@@ -191,8 +207,12 @@ export namespace Provider {
} }
}, },
"google-vertex-anthropic": async () => { "google-vertex-anthropic": async () => {
const project = process.env["GOOGLE_CLOUD_PROJECT"] ?? process.env["GCP_PROJECT"] ?? process.env["GCLOUD_PROJECT"] const project =
const location = process.env["GOOGLE_CLOUD_LOCATION"] ?? process.env["VERTEX_LOCATION"] ?? "us-east5" process.env["GOOGLE_CLOUD_PROJECT"] ??
process.env["GCP_PROJECT"] ??
process.env["GCLOUD_PROJECT"]
const location =
process.env["GOOGLE_CLOUD_LOCATION"] ?? process.env["VERTEX_LOCATION"] ?? "us-east5"
const autoload = Boolean(project) const autoload = Boolean(project)
if (!autoload) return { autoload: false } if (!autoload) return { autoload: false }
return { return {
@@ -223,7 +243,13 @@ export namespace Provider {
} = {} } = {}
const models = new Map< const models = new Map<
string, string,
{ providerID: string; modelID: string; info: ModelsDev.Model; language: LanguageModel; npm?: string } {
providerID: string
modelID: string
info: ModelsDev.Model
language: LanguageModel
npm?: string
}
>() >()
const sdk = new Map<number, SDK>() const sdk = new Map<number, SDK>()
// Maps `${provider}/${key}` to the providers actual model ID for custom aliases. // Maps `${provider}/${key}` to the providers actual model ID for custom aliases.
@@ -355,7 +381,10 @@ export namespace Provider {
const auth = await Auth.get(providerID) const auth = await Auth.get(providerID)
if (!auth) continue if (!auth) continue
if (!plugin.auth.loader) continue if (!plugin.auth.loader) continue
const options = await plugin.auth.loader(() => Auth.get(providerID) as any, database[plugin.auth.provider]) const options = await plugin.auth.loader(
() => Auth.get(providerID) as any,
database[plugin.auth.provider],
)
mergeProvider(plugin.auth.provider, options ?? {}, "custom") mergeProvider(plugin.auth.provider, options ?? {}, "custom")
} }
@@ -370,12 +399,15 @@ export namespace Provider {
// Filter out blacklisted models // Filter out blacklisted models
.filter( .filter(
([modelID]) => ([modelID]) =>
modelID !== "gpt-5-chat-latest" && !(providerID === "openrouter" && modelID === "openai/gpt-5-chat"), modelID !== "gpt-5-chat-latest" &&
!(providerID === "openrouter" && modelID === "openai/gpt-5-chat"),
) )
// Filter out experimental models // Filter out experimental models
.filter( .filter(
([, model]) => ([, model]) =>
(!model.experimental && model.status !== "alpha") || Flag.OPENCODE_ENABLE_EXPERIMENTAL_MODELS, ((!model.experimental && model.status !== "alpha") ||
Flag.OPENCODE_ENABLE_EXPERIMENTAL_MODELS) &&
model.status !== "deprecated",
), ),
) )
provider.info.models = filteredModels provider.info.models = filteredModels
@@ -421,7 +453,9 @@ export namespace Provider {
// In addition, Bun's dynamic import logic does not support subpath imports, // In addition, Bun's dynamic import logic does not support subpath imports,
// so we patch the import path to load directly from `dist`. // so we patch the import path to load directly from `dist`.
const modPath = const modPath =
provider.id === "google-vertex-anthropic" ? `${installedPath}/dist/anthropic/index.mjs` : installedPath provider.id === "google-vertex-anthropic"
? `${installedPath}/dist/anthropic/index.mjs`
: installedPath
const mod = await import(modPath) const mod = await import(modPath)
if (options["timeout"] !== undefined && options["timeout"] !== null) { if (options["timeout"] !== undefined && options["timeout"] !== null) {
// Only override fetch if user explicitly sets timeout // Only override fetch if user explicitly sets timeout
@@ -518,7 +552,14 @@ export namespace Provider {
const provider = await state().then((state) => state.providers[providerID]) const provider = await state().then((state) => state.providers[providerID])
if (!provider) return if (!provider) return
let priority = ["claude-haiku-4-5", "claude-haiku-4.5", "3-5-haiku", "3.5-haiku", "gemini-2.5-flash", "gpt-5-nano"] let priority = [
"claude-haiku-4-5",
"claude-haiku-4.5",
"3-5-haiku",
"3.5-haiku",
"gemini-2.5-flash",
"gpt-5-nano",
]
// claude-haiku-4.5 is considered a premium model in github copilot, we shouldn't use premium requests for title gen // claude-haiku-4.5 is considered a premium model in github copilot, we shouldn't use premium requests for title gen
if (providerID === "github-copilot") { if (providerID === "github-copilot") {
priority = priority.filter((m) => m !== "claude-haiku-4.5") priority = priority.filter((m) => m !== "claude-haiku-4.5")

View File

@@ -426,7 +426,7 @@ export type Config = {
output: Array<"text" | "audio" | "image" | "video" | "pdf"> output: Array<"text" | "audio" | "image" | "video" | "pdf">
} }
experimental?: boolean experimental?: boolean
status?: "alpha" | "beta" status?: "alpha" | "beta" | "deprecated"
options?: { options?: {
[key: string]: unknown [key: string]: unknown
} }
@@ -990,7 +990,7 @@ export type Model = {
output: Array<"text" | "audio" | "image" | "video" | "pdf"> output: Array<"text" | "audio" | "image" | "video" | "pdf">
} }
experimental?: boolean experimental?: boolean
status?: "alpha" | "beta" status?: "alpha" | "beta" | "deprecated"
options: { options: {
[key: string]: unknown [key: string]: unknown
} }