Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/opencode/src/cli/cmd/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export const ModelsCommand = cmd({
}

if (args.provider) {
const provider = providers[args.provider]
const provider = providers[ProviderID.make(args.provider)]
if (!provider) {
UI.error(`Provider not found: ${args.provider}`)
return
Expand Down
2 changes: 1 addition & 1 deletion packages/opencode/src/provider/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -839,7 +839,7 @@ export namespace Provider {
return true
}

const providers: { [providerID: string]: Info } = {}
const providers: Record<ProviderID, Info> = {} as Record<ProviderID, Info>
const languages = new Map<string, LanguageModelV2>()
const modelLoaders: {
[providerID: string]: CustomModelLoader
Expand Down
1 change: 1 addition & 0 deletions packages/opencode/src/provider/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export const ProviderID = providerIdSchema.pipe(
azure: schema.makeUnsafe("azure"),
openrouter: schema.makeUnsafe("openrouter"),
mistral: schema.makeUnsafe("mistral"),
gitlab: schema.makeUnsafe("gitlab"),
})),
)

Expand Down
20 changes: 0 additions & 20 deletions packages/opencode/src/util/eventloop.ts

This file was deleted.

41 changes: 21 additions & 20 deletions packages/opencode/test/provider/amazon-bedrock.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { test, expect, describe } from "bun:test"
import path from "path"
import { unlink } from "fs/promises"

import { ProviderID } from "../../src/provider/schema"
import { tmpdir } from "../fixture/fixture"
import { Instance } from "../../src/project/instance"
import { Provider } from "../../src/provider/provider"
Expand Down Expand Up @@ -35,8 +36,8 @@ test("Bedrock: config region takes precedence over AWS_REGION env var", async ()
},
fn: async () => {
const providers = await Provider.list()
expect(providers["amazon-bedrock"]).toBeDefined()
expect(providers["amazon-bedrock"].options?.region).toBe("eu-west-1")
expect(providers[ProviderID.amazonBedrock]).toBeDefined()
expect(providers[ProviderID.amazonBedrock].options?.region).toBe("eu-west-1")
},
})
})
Expand All @@ -60,8 +61,8 @@ test("Bedrock: falls back to AWS_REGION env var when no config region", async ()
},
fn: async () => {
const providers = await Provider.list()
expect(providers["amazon-bedrock"]).toBeDefined()
expect(providers["amazon-bedrock"].options?.region).toBe("eu-west-1")
expect(providers[ProviderID.amazonBedrock]).toBeDefined()
expect(providers[ProviderID.amazonBedrock].options?.region).toBe("eu-west-1")
},
})
})
Expand Down Expand Up @@ -116,8 +117,8 @@ test("Bedrock: loads when bearer token from auth.json is present", async () => {
},
fn: async () => {
const providers = await Provider.list()
expect(providers["amazon-bedrock"]).toBeDefined()
expect(providers["amazon-bedrock"].options?.region).toBe("eu-west-1")
expect(providers[ProviderID.amazonBedrock]).toBeDefined()
expect(providers[ProviderID.amazonBedrock].options?.region).toBe("eu-west-1")
},
})
} finally {
Expand Down Expand Up @@ -161,8 +162,8 @@ test("Bedrock: config profile takes precedence over AWS_PROFILE env var", async
},
fn: async () => {
const providers = await Provider.list()
expect(providers["amazon-bedrock"]).toBeDefined()
expect(providers["amazon-bedrock"].options?.region).toBe("us-east-1")
expect(providers[ProviderID.amazonBedrock]).toBeDefined()
expect(providers[ProviderID.amazonBedrock].options?.region).toBe("us-east-1")
},
})
})
Expand Down Expand Up @@ -192,8 +193,8 @@ test("Bedrock: includes custom endpoint in options when specified", async () =>
},
fn: async () => {
const providers = await Provider.list()
expect(providers["amazon-bedrock"]).toBeDefined()
expect(providers["amazon-bedrock"].options?.endpoint).toBe(
expect(providers[ProviderID.amazonBedrock]).toBeDefined()
expect(providers[ProviderID.amazonBedrock].options?.endpoint).toBe(
"https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com",
)
},
Expand Down Expand Up @@ -228,8 +229,8 @@ test("Bedrock: autoloads when AWS_WEB_IDENTITY_TOKEN_FILE is present", async ()
},
fn: async () => {
const providers = await Provider.list()
expect(providers["amazon-bedrock"]).toBeDefined()
expect(providers["amazon-bedrock"].options?.region).toBe("us-east-1")
expect(providers[ProviderID.amazonBedrock]).toBeDefined()
expect(providers[ProviderID.amazonBedrock].options?.region).toBe("us-east-1")
},
})
})
Expand Down Expand Up @@ -268,9 +269,9 @@ test("Bedrock: model with us. prefix should not be double-prefixed", async () =>
},
fn: async () => {
const providers = await Provider.list()
expect(providers["amazon-bedrock"]).toBeDefined()
expect(providers[ProviderID.amazonBedrock]).toBeDefined()
// The model should exist with the us. prefix
expect(providers["amazon-bedrock"].models["us.anthropic.claude-opus-4-5-20251101-v1:0"]).toBeDefined()
expect(providers[ProviderID.amazonBedrock].models["us.anthropic.claude-opus-4-5-20251101-v1:0"]).toBeDefined()
},
})
})
Expand Down Expand Up @@ -305,8 +306,8 @@ test("Bedrock: model with global. prefix should not be prefixed", async () => {
},
fn: async () => {
const providers = await Provider.list()
expect(providers["amazon-bedrock"]).toBeDefined()
expect(providers["amazon-bedrock"].models["global.anthropic.claude-opus-4-5-20251101-v1:0"]).toBeDefined()
expect(providers[ProviderID.amazonBedrock]).toBeDefined()
expect(providers[ProviderID.amazonBedrock].models["global.anthropic.claude-opus-4-5-20251101-v1:0"]).toBeDefined()
},
})
})
Expand Down Expand Up @@ -341,8 +342,8 @@ test("Bedrock: model with eu. prefix should not be double-prefixed", async () =>
},
fn: async () => {
const providers = await Provider.list()
expect(providers["amazon-bedrock"]).toBeDefined()
expect(providers["amazon-bedrock"].models["eu.anthropic.claude-opus-4-5-20251101-v1:0"]).toBeDefined()
expect(providers[ProviderID.amazonBedrock]).toBeDefined()
expect(providers[ProviderID.amazonBedrock].models["eu.anthropic.claude-opus-4-5-20251101-v1:0"]).toBeDefined()
},
})
})
Expand Down Expand Up @@ -377,9 +378,9 @@ test("Bedrock: model without prefix in US region should get us. prefix added", a
},
fn: async () => {
const providers = await Provider.list()
expect(providers["amazon-bedrock"]).toBeDefined()
expect(providers[ProviderID.amazonBedrock]).toBeDefined()
// Non-prefixed model should still be registered
expect(providers["amazon-bedrock"].models["anthropic.claude-opus-4-5-20251101-v1:0"]).toBeDefined()
expect(providers[ProviderID.amazonBedrock].models["anthropic.claude-opus-4-5-20251101-v1:0"]).toBeDefined()
},
})
})
Expand Down
35 changes: 18 additions & 17 deletions packages/opencode/test/provider/gitlab-duo.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { test, expect } from "bun:test"
import path from "path"

import { ProviderID } from "../../src/provider/schema"
import { tmpdir } from "../fixture/fixture"
import { Instance } from "../../src/project/instance"
import { Provider } from "../../src/provider/provider"
Expand All @@ -25,8 +26,8 @@ test("GitLab Duo: loads provider with API key from environment", async () => {
},
fn: async () => {
const providers = await Provider.list()
expect(providers["gitlab"]).toBeDefined()
expect(providers["gitlab"].key).toBe("test-gitlab-token")
expect(providers[ProviderID.gitlab]).toBeDefined()
expect(providers[ProviderID.gitlab].key).toBe("test-gitlab-token")
},
})
})
Expand Down Expand Up @@ -57,8 +58,8 @@ test("GitLab Duo: config instanceUrl option sets baseURL", async () => {
},
fn: async () => {
const providers = await Provider.list()
expect(providers["gitlab"]).toBeDefined()
expect(providers["gitlab"].options?.instanceUrl).toBe("https://gitlab.example.com")
expect(providers[ProviderID.gitlab]).toBeDefined()
expect(providers[ProviderID.gitlab].options?.instanceUrl).toBe("https://gitlab.example.com")
},
})
})
Expand Down Expand Up @@ -95,7 +96,7 @@ test("GitLab Duo: loads with OAuth token from auth.json", async () => {
},
fn: async () => {
const providers = await Provider.list()
expect(providers["gitlab"]).toBeDefined()
expect(providers[ProviderID.gitlab]).toBeDefined()
},
})
})
Expand Down Expand Up @@ -130,8 +131,8 @@ test("GitLab Duo: loads with Personal Access Token from auth.json", async () =>
},
fn: async () => {
const providers = await Provider.list()
expect(providers["gitlab"]).toBeDefined()
expect(providers["gitlab"].key).toBe("glpat-test-pat-token")
expect(providers[ProviderID.gitlab]).toBeDefined()
expect(providers[ProviderID.gitlab].key).toBe("glpat-test-pat-token")
},
})
})
Expand Down Expand Up @@ -162,8 +163,8 @@ test("GitLab Duo: supports self-hosted instance configuration", async () => {
},
fn: async () => {
const providers = await Provider.list()
expect(providers["gitlab"]).toBeDefined()
expect(providers["gitlab"].options?.instanceUrl).toBe("https://gitlab.company.internal")
expect(providers[ProviderID.gitlab]).toBeDefined()
expect(providers[ProviderID.gitlab].options?.instanceUrl).toBe("https://gitlab.company.internal")
},
})
})
Expand Down Expand Up @@ -193,7 +194,7 @@ test("GitLab Duo: config apiKey takes precedence over environment variable", asy
},
fn: async () => {
const providers = await Provider.list()
expect(providers["gitlab"]).toBeDefined()
expect(providers[ProviderID.gitlab]).toBeDefined()
},
})
})
Expand All @@ -216,8 +217,8 @@ test("GitLab Duo: includes context-1m beta header in aiGatewayHeaders", async ()
},
fn: async () => {
const providers = await Provider.list()
expect(providers["gitlab"]).toBeDefined()
expect(providers["gitlab"].options?.aiGatewayHeaders?.["anthropic-beta"]).toContain("context-1m-2025-08-07")
expect(providers[ProviderID.gitlab]).toBeDefined()
expect(providers[ProviderID.gitlab].options?.aiGatewayHeaders?.["anthropic-beta"]).toContain("context-1m-2025-08-07")
},
})
})
Expand Down Expand Up @@ -250,9 +251,9 @@ test("GitLab Duo: supports feature flags configuration", async () => {
},
fn: async () => {
const providers = await Provider.list()
expect(providers["gitlab"]).toBeDefined()
expect(providers["gitlab"].options?.featureFlags).toBeDefined()
expect(providers["gitlab"].options?.featureFlags?.duo_agent_platform_agentic_chat).toBe(true)
expect(providers[ProviderID.gitlab]).toBeDefined()
expect(providers[ProviderID.gitlab].options?.featureFlags).toBeDefined()
expect(providers[ProviderID.gitlab].options?.featureFlags?.duo_agent_platform_agentic_chat).toBe(true)
},
})
})
Expand All @@ -275,8 +276,8 @@ test("GitLab Duo: has multiple agentic chat models available", async () => {
},
fn: async () => {
const providers = await Provider.list()
expect(providers["gitlab"]).toBeDefined()
const models = Object.keys(providers["gitlab"].models)
expect(providers[ProviderID.gitlab]).toBeDefined()
const models = Object.keys(providers[ProviderID.gitlab].models)
expect(models.length).toBeGreaterThan(0)
expect(models).toContain("duo-chat-haiku-4-5")
expect(models).toContain("duo-chat-sonnet-4-5")
Expand Down
Loading
Loading