diff --git a/packages/opencode/test/provider/provider.test.ts b/packages/opencode/test/provider/provider.test.ts index fb18b4457f..544e04c536 100644 --- a/packages/opencode/test/provider/provider.test.ts +++ b/packages/opencode/test/provider/provider.test.ts @@ -228,81 +228,65 @@ it.instance( }, ) -test("custom model alias via config", 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: { - anthropic: { - models: { - "my-alias": { - id: "claude-sonnet-4-20250514", - name: "My Custom Alias", - }, - }, +it.instance( + "custom model alias via config", + Effect.gen(function* () { + yield* setProcessEnv("ANTHROPIC_API_KEY", "test-api-key") + const providers = yield* Provider.Service.use((provider) => provider.list()) + expect(providers[ProviderID.anthropic]).toBeDefined() + expect(providers[ProviderID.anthropic].models["my-alias"]).toBeDefined() + expect(providers[ProviderID.anthropic].models["my-alias"].name).toBe("My Custom Alias") + }), + { + config: { + provider: { + anthropic: { + models: { + "my-alias": { + id: "claude-sonnet-4-20250514", + name: "My Custom Alias", }, }, - }), - ) + }, + }, }, - }) - await withTestInstance({ - directory: tmp.path, - fn: async (ctx) => { - 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() - expect(providers[ProviderID.anthropic].models["my-alias"].name).toBe("My Custom Alias") - }, - }) -}) + }, +) -test("custom provider with npm package", 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: { - "custom-provider": { - name: "Custom Provider", - npm: "@ai-sdk/openai-compatible", - api: "https://api.custom.com/v1", - env: ["CUSTOM_API_KEY"], - models: { - "custom-model": { - name: "Custom Model", - tool_call: true, - limit: { - context: 128000, - output: 4096, - }, - }, - }, - options: { - apiKey: "custom-key", +it.instance( + "custom provider with npm package", + Effect.gen(function* () { + const providers = yield* Provider.Service.use((provider) => provider.list()) + expect(providers[ProviderID.make("custom-provider")]).toBeDefined() + expect(providers[ProviderID.make("custom-provider")].name).toBe("Custom Provider") + expect(providers[ProviderID.make("custom-provider")].models["custom-model"]).toBeDefined() + }), + { + config: { + provider: { + "custom-provider": { + name: "Custom Provider", + npm: "@ai-sdk/openai-compatible", + api: "https://api.custom.com/v1", + env: ["CUSTOM_API_KEY"], + models: { + "custom-model": { + name: "Custom Model", + tool_call: true, + limit: { + context: 128000, + output: 4096, }, }, }, - }), - ) + options: { + apiKey: "custom-key", + }, + }, + }, }, - }) - await withTestInstance({ - directory: tmp.path, - fn: async (ctx) => { - const providers = await list(ctx) - expect(providers[ProviderID.make("custom-provider")]).toBeDefined() - expect(providers[ProviderID.make("custom-provider")].name).toBe("Custom Provider") - expect(providers[ProviderID.make("custom-provider")].models["custom-model"]).toBeDefined() - }, - }) -}) + }, +) it.instance( "filters alpha provider models by default", @@ -324,66 +308,58 @@ experimentalModels.instance( { config: alphaProviderConfig }, ) -test("custom DeepSeek openai-compatible model defaults interleaved reasoning field", 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: { - "custom-provider": { - name: "Custom Provider", - npm: "@ai-sdk/openai-compatible", - api: "https://api.custom.com/v1", - models: { - "deepseek-r1": { - name: "DeepSeek R1", - }, - "deepseek-details": { - name: "DeepSeek Details", - interleaved: { field: "reasoning_details" }, - }, - "custom-model": { - name: "Custom Model", - }, - }, - options: { - apiKey: "custom-key", - }, +it.instance( + "custom DeepSeek openai-compatible model defaults interleaved reasoning field", + Effect.gen(function* () { + const providers = yield* Provider.Service.use((provider) => provider.list()) + const provider = providers[ProviderID.make("custom-provider")] + expect(provider.models["deepseek-r1"].capabilities.interleaved).toEqual({ field: "reasoning_content" }) + expect(provider.models["deepseek-details"].capabilities.interleaved).toEqual({ field: "reasoning_details" }) + expect(provider.models["custom-model"].capabilities.interleaved).toBe(false) + expect(providers[ProviderID.make("custom-anthropic-provider")].models["deepseek-r1"].capabilities.interleaved).toBe( + false, + ) + }), + { + config: { + provider: { + "custom-provider": { + name: "Custom Provider", + npm: "@ai-sdk/openai-compatible", + api: "https://api.custom.com/v1", + models: { + "deepseek-r1": { + name: "DeepSeek R1", }, - "custom-anthropic-provider": { - name: "Custom Anthropic Provider", - npm: "@ai-sdk/anthropic", - api: "https://api.custom.com/v1", - models: { - "deepseek-r1": { - name: "DeepSeek R1", - }, - }, - options: { - apiKey: "custom-key", - }, + "deepseek-details": { + name: "DeepSeek Details", + interleaved: { field: "reasoning_details" }, + }, + "custom-model": { + name: "Custom Model", }, }, - }), - ) + options: { + apiKey: "custom-key", + }, + }, + "custom-anthropic-provider": { + name: "Custom Anthropic Provider", + npm: "@ai-sdk/anthropic", + api: "https://api.custom.com/v1", + models: { + "deepseek-r1": { + name: "DeepSeek R1", + }, + }, + options: { + apiKey: "custom-key", + }, + }, + }, }, - }) - await withTestInstance({ - directory: tmp.path, - fn: async (ctx) => { - const providers = await list(ctx) - const provider = providers[ProviderID.make("custom-provider")] - expect(provider.models["deepseek-r1"].capabilities.interleaved).toEqual({ field: "reasoning_content" }) - expect(provider.models["deepseek-details"].capabilities.interleaved).toEqual({ field: "reasoning_details" }) - expect(provider.models["custom-model"].capabilities.interleaved).toBe(false) - expect( - providers[ProviderID.make("custom-anthropic-provider")].models["deepseek-r1"].capabilities.interleaved, - ).toBe(false) - }, - }) -}) + }, +) test("env variable takes precedence, config merges options", async () => { await using tmp = await tmpdir({ diff --git a/perf/test-suite.md b/perf/test-suite.md index 4be7d6ba6f..65f35bf57b 100644 --- a/perf/test-suite.md +++ b/perf/test-suite.md @@ -69,6 +69,7 @@ Repeated setup work, long sleeps/timeouts, serial integration tests, filesystem/ | HTTP listen PTY ticket tests restart the same listener topology twice | Folded directory-scoped ticket regression into the broader unsafe-ticket test | 7.051s | 6.170s | keep | Two targeted reruns passed after the change: 6.76s, 6.17s; still covers mint failure and successful same-directory upgrade. | | File watcher readiness can write before async native subscriptions are active | Retried short readiness writes and accepted symlink-realpath HEAD events | failed | 4.62s | keep | Three sequential focused watcher runs passed: 4.62s, 4.57s, 4.64s; full suite no longer failed in `watcher.test.ts`. | | First provider config/env/filtering block can use Effect-aware instance fixtures | Migrated six `tmpdir` + `withTestInstance` cases to `it.instance` | 6.06s | 6.07s | keep | Neutral timing, but removes manual config file writes and instance plumbing; use as the pattern for later provider slices. | +| Custom provider/model config cases can use Effect-aware instance fixtures | Migrated three more config-heavy provider cases to `it.instance` | 6.07s | 6.12s | keep | Neutral timing within noise, but continues removing manual config file writes on top of the first provider fixture PR. | ## Profiling Results