| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- import { test, expect, mock } from "bun:test"
- import path from "path"
- // === Mocks ===
- // These mocks are required because Provider.list() triggers:
- // 1. BunProc.install("@aws-sdk/credential-providers") - in bedrock custom loader
- // 2. Plugin.list() which calls BunProc.install() for default plugins
- // Without mocks, these would attempt real package installations that timeout in tests.
- mock.module("../../src/bun/index", () => ({
- BunProc: {
- install: async (pkg: string, _version?: string) => {
- // Return package name without version for mocking
- const lastAtIndex = pkg.lastIndexOf("@")
- return lastAtIndex > 0 ? pkg.substring(0, lastAtIndex) : pkg
- },
- run: async () => {
- throw new Error("BunProc.run should not be called in tests")
- },
- which: () => process.execPath,
- InstallFailedError: class extends Error {},
- },
- }))
- mock.module("@aws-sdk/credential-providers", () => ({
- fromNodeProviderChain: () => async () => ({
- accessKeyId: "mock-access-key-id",
- secretAccessKey: "mock-secret-access-key",
- }),
- }))
- const mockPlugin = () => ({})
- mock.module("opencode-copilot-auth", () => ({ default: mockPlugin }))
- mock.module("opencode-anthropic-auth", () => ({ default: mockPlugin }))
- mock.module("@gitlab/opencode-gitlab-auth", () => ({ default: mockPlugin }))
- // Import after mocks are set up
- const { tmpdir } = await import("../fixture/fixture")
- const { Instance } = await import("../../src/project/instance")
- const { Provider } = await import("../../src/provider/provider")
- const { Env } = await import("../../src/env")
- const { Global } = await import("../../src/global")
- test("Bedrock: config region takes precedence over AWS_REGION env var", async () => {
- await using tmp = await tmpdir({
- init: async (dir) => {
- await Bun.write(
- path.join(dir, "opencode.json"),
- JSON.stringify({
- $schema: "https://opencode.ai/config.json",
- provider: {
- "amazon-bedrock": {
- options: {
- region: "eu-west-1",
- },
- },
- },
- }),
- )
- },
- })
- await Instance.provide({
- directory: tmp.path,
- init: async () => {
- Env.set("AWS_REGION", "us-east-1")
- Env.set("AWS_PROFILE", "default")
- },
- fn: async () => {
- const providers = await Provider.list()
- expect(providers["amazon-bedrock"]).toBeDefined()
- expect(providers["amazon-bedrock"].options?.region).toBe("eu-west-1")
- },
- })
- })
- test("Bedrock: falls back to AWS_REGION env var when no config region", async () => {
- await using tmp = await tmpdir({
- init: async (dir) => {
- await Bun.write(
- path.join(dir, "opencode.json"),
- JSON.stringify({
- $schema: "https://opencode.ai/config.json",
- }),
- )
- },
- })
- await Instance.provide({
- directory: tmp.path,
- init: async () => {
- Env.set("AWS_REGION", "eu-west-1")
- Env.set("AWS_PROFILE", "default")
- },
- fn: async () => {
- const providers = await Provider.list()
- expect(providers["amazon-bedrock"]).toBeDefined()
- expect(providers["amazon-bedrock"].options?.region).toBe("eu-west-1")
- },
- })
- })
- test("Bedrock: loads when bearer token from auth.json is present", async () => {
- await using tmp = await tmpdir({
- init: async (dir) => {
- await Bun.write(
- path.join(dir, "opencode.json"),
- JSON.stringify({
- $schema: "https://opencode.ai/config.json",
- provider: {
- "amazon-bedrock": {
- options: {
- region: "eu-west-1",
- },
- },
- },
- }),
- )
- },
- })
- const authPath = path.join(Global.Path.data, "auth.json")
- await Bun.write(
- authPath,
- JSON.stringify({
- "amazon-bedrock": {
- type: "api",
- key: "test-bearer-token",
- },
- }),
- )
- await Instance.provide({
- directory: tmp.path,
- init: async () => {
- Env.set("AWS_PROFILE", "")
- Env.set("AWS_ACCESS_KEY_ID", "")
- Env.set("AWS_BEARER_TOKEN_BEDROCK", "")
- },
- fn: async () => {
- const providers = await Provider.list()
- expect(providers["amazon-bedrock"]).toBeDefined()
- expect(providers["amazon-bedrock"].options?.region).toBe("eu-west-1")
- },
- })
- })
- test("Bedrock: config profile takes precedence over AWS_PROFILE env var", async () => {
- await using tmp = await tmpdir({
- init: async (dir) => {
- await Bun.write(
- path.join(dir, "opencode.json"),
- JSON.stringify({
- $schema: "https://opencode.ai/config.json",
- provider: {
- "amazon-bedrock": {
- options: {
- profile: "my-custom-profile",
- region: "us-east-1",
- },
- },
- },
- }),
- )
- },
- })
- await Instance.provide({
- directory: tmp.path,
- init: async () => {
- Env.set("AWS_PROFILE", "default")
- Env.set("AWS_ACCESS_KEY_ID", "test-key-id")
- },
- fn: async () => {
- const providers = await Provider.list()
- expect(providers["amazon-bedrock"]).toBeDefined()
- expect(providers["amazon-bedrock"].options?.region).toBe("us-east-1")
- },
- })
- })
- test("Bedrock: includes custom endpoint in options when specified", async () => {
- await using tmp = await tmpdir({
- init: async (dir) => {
- await Bun.write(
- path.join(dir, "opencode.json"),
- JSON.stringify({
- $schema: "https://opencode.ai/config.json",
- provider: {
- "amazon-bedrock": {
- options: {
- endpoint: "https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com",
- },
- },
- },
- }),
- )
- },
- })
- await Instance.provide({
- directory: tmp.path,
- init: async () => {
- Env.set("AWS_PROFILE", "default")
- },
- fn: async () => {
- const providers = await Provider.list()
- expect(providers["amazon-bedrock"]).toBeDefined()
- expect(providers["amazon-bedrock"].options?.endpoint).toBe(
- "https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com",
- )
- },
- })
- })
|