Speed up targeted opencode tests
Reduce avoidable setup costs in slow opencode tests while preserving reviewed coverage and recording the benchmark evidence for follow-up test-suite work.
This commit is contained in:
@@ -3,6 +3,7 @@ import { mkdir, unlink } from "fs/promises"
|
||||
import path from "path"
|
||||
|
||||
import { disposeAllInstances, tmpdir, withTestInstance } from "../fixture/fixture"
|
||||
import { markPluginDependenciesReady } from "../fixture/plugin"
|
||||
import { Global } from "@opencode-ai/core/global"
|
||||
import type { InstanceContext } from "../../src/project/instance-context"
|
||||
import { Plugin } from "../../src/plugin/index"
|
||||
@@ -31,12 +32,12 @@ function rememberEnv(k: string) {
|
||||
const set = (ctx: InstanceContext, k: string, v: string) => {
|
||||
rememberEnv(k)
|
||||
process.env[k] = v
|
||||
return env.runSync((svc) => svc.set(k, v).pipe(Effect.provideService(InstanceRef, ctx)))
|
||||
return env.runPromise((svc) => svc.set(k, v).pipe(Effect.provideService(InstanceRef, ctx)))
|
||||
}
|
||||
const remove = (ctx: InstanceContext, k: string) => {
|
||||
rememberEnv(k)
|
||||
delete process.env[k]
|
||||
return env.runSync((svc) => svc.remove(k).pipe(Effect.provideService(InstanceRef, ctx)))
|
||||
return env.runPromise((svc) => svc.remove(k).pipe(Effect.provideService(InstanceRef, ctx)))
|
||||
}
|
||||
|
||||
afterEach(async () => {
|
||||
@@ -96,14 +97,6 @@ async function defaultModel(ctx: InstanceContext) {
|
||||
return run(ctx, (provider) => provider.defaultModel())
|
||||
}
|
||||
|
||||
async function markPluginDependenciesReady(dir: string) {
|
||||
await mkdir(path.join(dir, "node_modules"), { recursive: true })
|
||||
await Bun.write(
|
||||
path.join(dir, "package-lock.json"),
|
||||
JSON.stringify({ packages: { "": { dependencies: { "@opencode-ai/plugin": "0.0.0" } } } }),
|
||||
)
|
||||
}
|
||||
|
||||
function paid(providers: Awaited<ReturnType<typeof list>>) {
|
||||
const item = providers[ProviderID.make("opencode")]
|
||||
expect(item).toBeDefined()
|
||||
@@ -149,7 +142,7 @@ test("provider loaded from env variable", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
const providers = await list(ctx)
|
||||
expect(providers[ProviderID.anthropic]).toBeDefined()
|
||||
// Provider should retain its connection source even if custom loaders
|
||||
@@ -202,7 +195,7 @@ test("disabled_providers excludes provider", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
const providers = await list(ctx)
|
||||
expect(providers[ProviderID.anthropic]).toBeUndefined()
|
||||
},
|
||||
@@ -224,8 +217,8 @@ test("enabled_providers restricts to only listed providers", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
set(ctx, "OPENAI_API_KEY", "test-openai-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "OPENAI_API_KEY", "test-openai-key")
|
||||
const providers = await list(ctx)
|
||||
expect(providers[ProviderID.anthropic]).toBeDefined()
|
||||
expect(providers[ProviderID.openai]).toBeUndefined()
|
||||
@@ -252,7 +245,7 @@ test("model whitelist filters models for provider", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
const providers = await list(ctx)
|
||||
expect(providers[ProviderID.anthropic]).toBeDefined()
|
||||
const models = Object.keys(providers[ProviderID.anthropic].models)
|
||||
@@ -281,7 +274,7 @@ test("model blacklist excludes specific models", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
const providers = await list(ctx)
|
||||
expect(providers[ProviderID.anthropic]).toBeDefined()
|
||||
const models = Object.keys(providers[ProviderID.anthropic].models)
|
||||
@@ -314,7 +307,7 @@ test("custom model alias via config", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
const providers = await list(ctx)
|
||||
expect(providers[ProviderID.anthropic]).toBeDefined()
|
||||
expect(providers[ProviderID.anthropic].models["my-alias"]).toBeDefined()
|
||||
@@ -469,7 +462,7 @@ test("env variable takes precedence, config merges options", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "env-api-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "env-api-key")
|
||||
const providers = await list(ctx)
|
||||
expect(providers[ProviderID.anthropic]).toBeDefined()
|
||||
// Config options should be merged
|
||||
@@ -493,7 +486,7 @@ test("getModel returns model for valid provider/model", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
const model = await getModel(ProviderID.anthropic, ModelID.make("claude-sonnet-4-20250514"), ctx)
|
||||
expect(model).toBeDefined()
|
||||
expect(String(model.providerID)).toBe("anthropic")
|
||||
@@ -518,7 +511,7 @@ test("getModel throws ModelNotFoundError for invalid model", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
expect(getModel(ProviderID.anthropic, ModelID.make("nonexistent-model"), ctx)).rejects.toThrow()
|
||||
},
|
||||
})
|
||||
@@ -569,7 +562,7 @@ test("defaultModel returns first available model when no config set", async () =
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
const model = await defaultModel(ctx)
|
||||
expect(model.providerID).toBeDefined()
|
||||
expect(model.modelID).toBeDefined()
|
||||
@@ -592,7 +585,7 @@ test("defaultModel respects config model setting", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
const model = await defaultModel(ctx)
|
||||
expect(String(model.providerID)).toBe("anthropic")
|
||||
expect(String(model.modelID)).toBe("claude-sonnet-4-20250514")
|
||||
@@ -725,7 +718,7 @@ test("closest finds model by partial match", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
const result = await closest(ProviderID.anthropic, ["sonnet-4"], ctx)
|
||||
expect(result).toBeDefined()
|
||||
expect(String(result?.providerID)).toBe("anthropic")
|
||||
@@ -778,7 +771,7 @@ test("getModel uses realIdByKey for aliased models", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
const providers = await list(ctx)
|
||||
expect(providers[ProviderID.anthropic].models["my-sonnet"]).toBeDefined()
|
||||
|
||||
@@ -891,7 +884,7 @@ test("model inherits properties from existing database model", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
const providers = await list(ctx)
|
||||
const model = providers[ProviderID.anthropic].models["claude-sonnet-4-20250514"]
|
||||
expect(model.name).toBe("Custom Name for Sonnet")
|
||||
@@ -917,7 +910,7 @@ test("disabled_providers prevents loading even with env var", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "OPENAI_API_KEY", "test-openai-key")
|
||||
await set(ctx, "OPENAI_API_KEY", "test-openai-key")
|
||||
const providers = await list(ctx)
|
||||
expect(providers[ProviderID.openai]).toBeUndefined()
|
||||
},
|
||||
@@ -939,8 +932,8 @@ test("enabled_providers with empty array allows no providers", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
set(ctx, "OPENAI_API_KEY", "test-openai-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "OPENAI_API_KEY", "test-openai-key")
|
||||
const providers = await list(ctx)
|
||||
expect(Object.keys(providers).length).toBe(0)
|
||||
},
|
||||
@@ -967,7 +960,7 @@ test("whitelist and blacklist can be combined", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
const providers = await list(ctx)
|
||||
expect(providers[ProviderID.anthropic]).toBeDefined()
|
||||
const models = Object.keys(providers[ProviderID.anthropic].models)
|
||||
@@ -1074,7 +1067,7 @@ test("getSmallModel returns appropriate small model", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
const model = await getSmallModel(ProviderID.anthropic, ctx)
|
||||
expect(model).toBeDefined()
|
||||
expect(model?.id).toContain("haiku")
|
||||
@@ -1097,7 +1090,7 @@ test("getSmallModel respects config small_model override", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
const model = await getSmallModel(ProviderID.anthropic, ctx)
|
||||
expect(model).toBeDefined()
|
||||
expect(String(model?.providerID)).toBe("anthropic")
|
||||
@@ -1121,7 +1114,7 @@ test("getSmallModel ignores invalid config small_model", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
expect(await getSmallModel(ProviderID.anthropic, ctx)).toBeUndefined()
|
||||
},
|
||||
})
|
||||
@@ -1164,8 +1157,8 @@ test("multiple providers can be configured simultaneously", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-anthropic-key")
|
||||
set(ctx, "OPENAI_API_KEY", "test-openai-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-anthropic-key")
|
||||
await set(ctx, "OPENAI_API_KEY", "test-openai-key")
|
||||
const providers = await list(ctx)
|
||||
expect(providers[ProviderID.anthropic]).toBeDefined()
|
||||
expect(providers[ProviderID.openai]).toBeDefined()
|
||||
@@ -1241,7 +1234,7 @@ test("model alias name defaults to alias key when id differs", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
const providers = await list(ctx)
|
||||
expect(providers[ProviderID.anthropic].models["sonnet"].name).toBe("sonnet")
|
||||
},
|
||||
@@ -1279,7 +1272,7 @@ test("provider with multiple env var options only includes apiKey when single en
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "MULTI_ENV_KEY_1", "test-key")
|
||||
await set(ctx, "MULTI_ENV_KEY_1", "test-key")
|
||||
const providers = await list(ctx)
|
||||
expect(providers[ProviderID.make("multi-env")]).toBeDefined()
|
||||
// When multiple env options exist, key should NOT be auto-set
|
||||
@@ -1319,7 +1312,7 @@ test("provider with single env var includes apiKey automatically", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "SINGLE_ENV_KEY", "my-api-key")
|
||||
await set(ctx, "SINGLE_ENV_KEY", "my-api-key")
|
||||
const providers = await list(ctx)
|
||||
expect(providers[ProviderID.make("single-env")]).toBeDefined()
|
||||
// Single env option should auto-set key
|
||||
@@ -1354,7 +1347,7 @@ test("model cost overrides existing cost values", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
const providers = await list(ctx)
|
||||
const model = providers[ProviderID.anthropic].models["claude-sonnet-4-20250514"]
|
||||
expect(model.cost.input).toBe(999)
|
||||
@@ -1431,9 +1424,9 @@ test("disabled_providers and enabled_providers interaction", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-anthropic")
|
||||
set(ctx, "OPENAI_API_KEY", "test-openai")
|
||||
set(ctx, "GOOGLE_GENERATIVE_AI_API_KEY", "test-google")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-anthropic")
|
||||
await set(ctx, "OPENAI_API_KEY", "test-openai")
|
||||
await set(ctx, "GOOGLE_GENERATIVE_AI_API_KEY", "test-google")
|
||||
const providers = await list(ctx)
|
||||
// anthropic: in enabled, not in disabled = allowed
|
||||
expect(providers[ProviderID.anthropic]).toBeDefined()
|
||||
@@ -1588,7 +1581,7 @@ test("provider env fallback - second env var used if first missing", async () =>
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
// Only set fallback, not primary
|
||||
set(ctx, "FALLBACK_KEY", "fallback-api-key")
|
||||
await set(ctx, "FALLBACK_KEY", "fallback-api-key")
|
||||
const providers = await list(ctx)
|
||||
// Provider should load because fallback env var is set
|
||||
expect(providers[ProviderID.make("fallback-env")]).toBeDefined()
|
||||
@@ -1610,7 +1603,7 @@ test("getModel returns consistent results", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
const model1 = await getModel(ProviderID.anthropic, ModelID.make("claude-sonnet-4-20250514"), ctx)
|
||||
const model2 = await getModel(ProviderID.anthropic, ModelID.make("claude-sonnet-4-20250514"), ctx)
|
||||
expect(model1.providerID).toEqual(model2.providerID)
|
||||
@@ -1669,7 +1662,7 @@ test("ModelNotFoundError includes suggestions for typos", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
try {
|
||||
await getModel(ProviderID.anthropic, ModelID.make("claude-sonet-4"), ctx) // typo: sonet instead of sonnet
|
||||
expect(true).toBe(false) // Should not reach here
|
||||
@@ -1695,7 +1688,7 @@ test("ModelNotFoundError for provider includes suggestions", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
try {
|
||||
await getModel(ProviderID.make("antropic"), ModelID.make("claude-sonnet-4"), ctx) // typo: antropic
|
||||
expect(true).toBe(false) // Should not reach here
|
||||
@@ -1721,7 +1714,7 @@ test("ModelNotFoundError suggests catalog models for unloaded providers", async
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
remove(ctx, "OPENCODE_API_KEY")
|
||||
await remove(ctx, "OPENCODE_API_KEY")
|
||||
try {
|
||||
await getModel(ProviderID.opencode, ModelID.make("claude-haiku-fake-model"), ctx)
|
||||
throw new Error("expected model lookup to fail")
|
||||
@@ -1767,7 +1760,7 @@ test("getProvider returns provider info", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
const provider = await getProvider(ProviderID.anthropic, ctx)
|
||||
expect(provider).toBeDefined()
|
||||
expect(String(provider?.id)).toBe("anthropic")
|
||||
@@ -1789,7 +1782,7 @@ test("closest returns undefined when no partial match found", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
const result = await closest(ProviderID.anthropic, ["nonexistent-xyz-model"], ctx)
|
||||
expect(result).toBeUndefined()
|
||||
},
|
||||
@@ -1810,7 +1803,7 @@ test("closest checks multiple query terms in order", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
// First term won't match, second will
|
||||
const result = await closest(ProviderID.anthropic, ["nonexistent", "haiku"], ctx)
|
||||
expect(result).toBeDefined()
|
||||
@@ -1880,7 +1873,7 @@ test("provider options are deeply merged", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
const providers = await list(ctx)
|
||||
// Custom options should be merged
|
||||
expect(providers[ProviderID.anthropic].options.timeout).toBe(30000)
|
||||
@@ -2010,7 +2003,7 @@ test("custom model inherits npm package from models.dev provider config", async
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "OPENAI_API_KEY", "test-api-key")
|
||||
await set(ctx, "OPENAI_API_KEY", "test-api-key")
|
||||
const providers = await list(ctx)
|
||||
const model = providers[ProviderID.openai].models["my-custom-model"]
|
||||
expect(model).toBeDefined()
|
||||
@@ -2043,7 +2036,7 @@ test("custom model inherits api.url from models.dev provider", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "OPENROUTER_API_KEY", "test-api-key")
|
||||
await set(ctx, "OPENROUTER_API_KEY", "test-api-key")
|
||||
const providers = await list(ctx)
|
||||
expect(providers[ProviderID.openrouter]).toBeDefined()
|
||||
|
||||
@@ -2174,7 +2167,7 @@ test("model variants are generated for reasoning models", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
const providers = await list(ctx)
|
||||
// Claude sonnet 4 has reasoning capability
|
||||
const model = providers[ProviderID.anthropic].models["claude-sonnet-4-20250514"]
|
||||
@@ -2210,7 +2203,7 @@ test("model variants can be disabled via config", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
const providers = await list(ctx)
|
||||
const model = providers[ProviderID.anthropic].models["claude-sonnet-4-20250514"]
|
||||
expect(model.variants).toBeDefined()
|
||||
@@ -2251,7 +2244,7 @@ test("model variants can be customized via config", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
const providers = await list(ctx)
|
||||
const model = providers[ProviderID.anthropic].models["claude-sonnet-4-20250514"]
|
||||
expect(model.variants!["high"]).toBeDefined()
|
||||
@@ -2288,7 +2281,7 @@ test("disabled key is stripped from variant config", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
const providers = await list(ctx)
|
||||
const model = providers[ProviderID.anthropic].models["claude-sonnet-4-20250514"]
|
||||
expect(model.variants!["max"]).toBeDefined()
|
||||
@@ -2324,7 +2317,7 @@ test("all variants can be disabled via config", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
const providers = await list(ctx)
|
||||
const model = providers[ProviderID.anthropic].models["claude-sonnet-4-20250514"]
|
||||
expect(model.variants).toBeDefined()
|
||||
@@ -2360,7 +2353,7 @@ test("variant config merges with generated variants", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
|
||||
const providers = await list(ctx)
|
||||
const model = providers[ProviderID.anthropic].models["claude-sonnet-4-20250514"]
|
||||
expect(model.variants!["high"]).toBeDefined()
|
||||
@@ -2396,7 +2389,7 @@ test("variants filtered in second pass for database models", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "OPENAI_API_KEY", "test-api-key")
|
||||
await set(ctx, "OPENAI_API_KEY", "test-api-key")
|
||||
const providers = await list(ctx)
|
||||
const model = providers[ProviderID.openai].models["gpt-5"]
|
||||
expect(model.variants).toBeDefined()
|
||||
@@ -2498,7 +2491,7 @@ test("Google Vertex: retains baseURL for custom proxy", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "GOOGLE_APPLICATION_CREDENTIALS", "test-creds")
|
||||
await set(ctx, "GOOGLE_APPLICATION_CREDENTIALS", "test-creds")
|
||||
const providers = await list(ctx)
|
||||
expect(providers[ProviderID.make("vertex-proxy")]).toBeDefined()
|
||||
expect(providers[ProviderID.make("vertex-proxy")].options.baseURL).toBe("https://my-proxy.com/v1")
|
||||
@@ -2541,7 +2534,7 @@ test("Google Vertex: supports OpenAI compatible models", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "GOOGLE_APPLICATION_CREDENTIALS", "test-creds")
|
||||
await set(ctx, "GOOGLE_APPLICATION_CREDENTIALS", "test-creds")
|
||||
const providers = await list(ctx)
|
||||
const model = providers[ProviderID.make("vertex-openai")].models["gpt-4"]
|
||||
|
||||
@@ -2565,9 +2558,9 @@ test("cloudflare-ai-gateway loads with env variables", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "CLOUDFLARE_ACCOUNT_ID", "test-account")
|
||||
set(ctx, "CLOUDFLARE_GATEWAY_ID", "test-gateway")
|
||||
set(ctx, "CLOUDFLARE_API_TOKEN", "test-token")
|
||||
await set(ctx, "CLOUDFLARE_ACCOUNT_ID", "test-account")
|
||||
await set(ctx, "CLOUDFLARE_GATEWAY_ID", "test-gateway")
|
||||
await set(ctx, "CLOUDFLARE_API_TOKEN", "test-token")
|
||||
const providers = await list(ctx)
|
||||
expect(providers[ProviderID.make("cloudflare-ai-gateway")]).toBeDefined()
|
||||
},
|
||||
@@ -2595,9 +2588,9 @@ test("cloudflare-ai-gateway forwards config metadata options", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "CLOUDFLARE_ACCOUNT_ID", "test-account")
|
||||
set(ctx, "CLOUDFLARE_GATEWAY_ID", "test-gateway")
|
||||
set(ctx, "CLOUDFLARE_API_TOKEN", "test-token")
|
||||
await set(ctx, "CLOUDFLARE_ACCOUNT_ID", "test-account")
|
||||
await set(ctx, "CLOUDFLARE_GATEWAY_ID", "test-gateway")
|
||||
await set(ctx, "CLOUDFLARE_API_TOKEN", "test-token")
|
||||
const providers = await list(ctx)
|
||||
expect(providers[ProviderID.make("cloudflare-ai-gateway")]).toBeDefined()
|
||||
expect(providers[ProviderID.make("cloudflare-ai-gateway")].options.metadata).toEqual({
|
||||
@@ -2673,8 +2666,10 @@ test("plugin config providers persist after instance dispose", async () => {
|
||||
test("plugin config enabled and disabled providers are honored", async () => {
|
||||
await using tmp = await tmpdir({
|
||||
init: async (dir) => {
|
||||
const root = path.join(dir, ".opencode", "plugin")
|
||||
const configDir = path.join(dir, ".opencode")
|
||||
const root = path.join(configDir, "plugin")
|
||||
await mkdir(root, { recursive: true })
|
||||
await markPluginDependenciesReady(configDir)
|
||||
await Bun.write(
|
||||
path.join(root, "provider-filter.ts"),
|
||||
[
|
||||
@@ -2696,8 +2691,8 @@ test("plugin config enabled and disabled providers are honored", async () => {
|
||||
await withTestInstance({
|
||||
directory: tmp.path,
|
||||
fn: async (ctx) => {
|
||||
set(ctx, "ANTHROPIC_API_KEY", "test-anthropic-key")
|
||||
set(ctx, "OPENAI_API_KEY", "test-openai-key")
|
||||
await set(ctx, "ANTHROPIC_API_KEY", "test-anthropic-key")
|
||||
await set(ctx, "OPENAI_API_KEY", "test-openai-key")
|
||||
const providers = await list(ctx)
|
||||
expect(providers[ProviderID.anthropic]).toBeDefined()
|
||||
expect(providers[ProviderID.openai]).toBeUndefined()
|
||||
|
||||
Reference in New Issue
Block a user