diff --git a/packages/opencode/src/project/instance.ts b/packages/opencode/src/project/instance.ts index 549df4b751..6b037c711a 100644 --- a/packages/opencode/src/project/instance.ts +++ b/packages/opencode/src/project/instance.ts @@ -9,15 +9,13 @@ export type { LoadInput } from "./instance-store" type LegacyLoadInput = { directory: string - init?: () => Promise + init?: Effect.Effect project?: Project.Info worktree?: string } -// Promise-style legacy inits often read Instance.directory etc. from the ALS context. -// The new Effect-typed init path doesn't bind ALS — it provides InstanceRef. To keep -// legacy inits working without forcing every test to convert, bind ALS around the -// Promise call here using the instance ctx that the store provides via InstanceRef. +// Bind ALS around init so legacy code reachable through it (Instance.directory reads, etc.) +// stays bound. The Effect-typed init also gets InstanceRef provided by the store. const liftLegacyInput = (input: LegacyLoadInput): InstanceStore.LoadInput => { const { init, ...rest } = input if (!init) return rest @@ -25,7 +23,15 @@ const liftLegacyInput = (input: LegacyLoadInput): InstanceStore.LoadInput => { ...rest, init: Effect.gen(function* () { const ctx = yield* InstanceRef - yield* Effect.promise(() => (ctx ? context.provide(ctx, init) : init())) + if (!ctx) return yield* init + yield* Effect.callback((resume) => { + context.provide(ctx, () => { + Effect.runPromise(init).then( + () => resume(Effect.void), + (err) => resume(Effect.die(err)), + ) + }) + }) }), } } @@ -34,7 +40,7 @@ export const Instance = { load(input: LegacyLoadInput): Promise { return InstanceStore.runtime.runPromise((store) => store.load(liftLegacyInput(input))) }, - async provide(input: { directory: string; init?: () => Promise; fn: () => R }): Promise { + async provide(input: { directory: string; init?: Effect.Effect; fn: () => R }): Promise { return context.provide( await Instance.load({ directory: input.directory, init: input.init }), async () => input.fn(), diff --git a/packages/opencode/test/provider/amazon-bedrock.test.ts b/packages/opencode/test/provider/amazon-bedrock.test.ts index 88c67aa6dc..43b23dafad 100644 --- a/packages/opencode/test/provider/amazon-bedrock.test.ts +++ b/packages/opencode/test/provider/amazon-bedrock.test.ts @@ -45,10 +45,10 @@ test("Bedrock: config region takes precedence over AWS_REGION env var", async () }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("AWS_REGION", "us-east-1") set("AWS_PROFILE", "default") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() expect(providers[ProviderID.amazonBedrock]).toBeDefined() @@ -70,10 +70,10 @@ test("Bedrock: falls back to AWS_REGION env var when no config region", async () }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("AWS_REGION", "eu-west-1") set("AWS_PROFILE", "default") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() expect(providers[ProviderID.amazonBedrock]).toBeDefined() @@ -125,11 +125,11 @@ test("Bedrock: loads when bearer token from auth.json is present", async () => { await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("AWS_PROFILE", "") set("AWS_ACCESS_KEY_ID", "") set("AWS_BEARER_TOKEN_BEDROCK", "") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() expect(providers[ProviderID.amazonBedrock]).toBeDefined() @@ -171,10 +171,10 @@ test("Bedrock: config profile takes precedence over AWS_PROFILE env var", async }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("AWS_PROFILE", "default") set("AWS_ACCESS_KEY_ID", "test-key-id") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() expect(providers[ProviderID.amazonBedrock]).toBeDefined() @@ -203,9 +203,9 @@ test("Bedrock: includes custom endpoint in options when specified", async () => }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("AWS_PROFILE", "default") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() expect(providers[ProviderID.amazonBedrock]).toBeDefined() @@ -236,12 +236,12 @@ test("Bedrock: autoloads when AWS_WEB_IDENTITY_TOKEN_FILE is present", async () }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("AWS_WEB_IDENTITY_TOKEN_FILE", "/var/run/secrets/eks.amazonaws.com/serviceaccount/token") set("AWS_ROLE_ARN", "arn:aws:iam::123456789012:role/my-eks-role") set("AWS_PROFILE", "") set("AWS_ACCESS_KEY_ID", "") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() expect(providers[ProviderID.amazonBedrock]).toBeDefined() @@ -279,9 +279,9 @@ test("Bedrock: model with us. prefix should not be double-prefixed", async () => }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("AWS_PROFILE", "default") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() expect(providers[ProviderID.amazonBedrock]).toBeDefined() @@ -316,9 +316,9 @@ test("Bedrock: model with global. prefix should not be prefixed", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("AWS_PROFILE", "default") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() expect(providers[ProviderID.amazonBedrock]).toBeDefined() @@ -352,9 +352,9 @@ test("Bedrock: model with eu. prefix should not be double-prefixed", async () => }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("AWS_PROFILE", "default") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() expect(providers[ProviderID.amazonBedrock]).toBeDefined() @@ -388,9 +388,9 @@ test("Bedrock: model without prefix in US region should get us. prefix added", a }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("AWS_PROFILE", "default") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() expect(providers[ProviderID.amazonBedrock]).toBeDefined() diff --git a/packages/opencode/test/provider/provider.test.ts b/packages/opencode/test/provider/provider.test.ts index d0aa299e70..edbf4d6648 100644 --- a/packages/opencode/test/provider/provider.test.ts +++ b/packages/opencode/test/provider/provider.test.ts @@ -82,9 +82,9 @@ test("provider loaded from env variable", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() expect(providers[ProviderID.anthropic]).toBeDefined() @@ -137,9 +137,9 @@ test("disabled_providers excludes provider", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() expect(providers[ProviderID.anthropic]).toBeUndefined() @@ -161,10 +161,10 @@ test("enabled_providers restricts to only listed providers", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") set("OPENAI_API_KEY", "test-openai-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() expect(providers[ProviderID.anthropic]).toBeDefined() @@ -191,9 +191,9 @@ test("model whitelist filters models for provider", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() expect(providers[ProviderID.anthropic]).toBeDefined() @@ -222,9 +222,9 @@ test("model blacklist excludes specific models", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() expect(providers[ProviderID.anthropic]).toBeDefined() @@ -257,9 +257,9 @@ test("custom model alias via config", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() expect(providers[ProviderID.anthropic]).toBeDefined() @@ -394,9 +394,9 @@ test("env variable takes precedence, config merges options", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "env-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() expect(providers[ProviderID.anthropic]).toBeDefined() @@ -420,9 +420,9 @@ test("getModel returns model for valid provider/model", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const model = await getModel(ProviderID.anthropic, ModelID.make("claude-sonnet-4-20250514")) expect(model).toBeDefined() @@ -447,9 +447,9 @@ test("getModel throws ModelNotFoundError for invalid model", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { expect(getModel(ProviderID.anthropic, ModelID.make("nonexistent-model"))).rejects.toThrow() }, @@ -500,9 +500,9 @@ test("defaultModel returns first available model when no config set", async () = }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const model = await defaultModel() expect(model.providerID).toBeDefined() @@ -525,9 +525,9 @@ test("defaultModel respects config model setting", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const model = await defaultModel() expect(String(model.providerID)).toBe("anthropic") @@ -640,9 +640,9 @@ test("model options are merged from existing model", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() const model = providers[ProviderID.anthropic].models["claude-sonnet-4-20250514"] @@ -669,9 +669,9 @@ test("provider removed when all models filtered out", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() expect(providers[ProviderID.anthropic]).toBeUndefined() @@ -692,9 +692,9 @@ test("closest finds model by partial match", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const result = await closest(ProviderID.anthropic, ["sonnet-4"]) expect(result).toBeDefined() @@ -747,9 +747,9 @@ test("getModel uses realIdByKey for aliased models", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() expect(providers[ProviderID.anthropic].models["my-sonnet"]).toBeDefined() @@ -862,9 +862,9 @@ test("model inherits properties from existing database model", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() const model = providers[ProviderID.anthropic].models["claude-sonnet-4-20250514"] @@ -890,9 +890,9 @@ test("disabled_providers prevents loading even with env var", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("OPENAI_API_KEY", "test-openai-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() expect(providers[ProviderID.openai]).toBeUndefined() @@ -914,10 +914,10 @@ test("enabled_providers with empty array allows no providers", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") set("OPENAI_API_KEY", "test-openai-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() expect(Object.keys(providers).length).toBe(0) @@ -944,9 +944,9 @@ test("whitelist and blacklist can be combined", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() expect(providers[ProviderID.anthropic]).toBeDefined() @@ -1053,9 +1053,9 @@ test("getSmallModel returns appropriate small model", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const model = await getSmallModel(ProviderID.anthropic) expect(model).toBeDefined() @@ -1078,9 +1078,9 @@ test("getSmallModel respects config small_model override", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const model = await getSmallModel(ProviderID.anthropic) expect(model).toBeDefined() @@ -1126,10 +1126,10 @@ test("multiple providers can be configured simultaneously", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-anthropic-key") set("OPENAI_API_KEY", "test-openai-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() expect(providers[ProviderID.anthropic]).toBeDefined() @@ -1205,9 +1205,9 @@ test("model alias name defaults to alias key when id differs", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() expect(providers[ProviderID.anthropic].models["sonnet"].name).toBe("sonnet") @@ -1245,9 +1245,9 @@ test("provider with multiple env var options only includes apiKey when single en }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("MULTI_ENV_KEY_1", "test-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() expect(providers[ProviderID.make("multi-env")]).toBeDefined() @@ -1287,9 +1287,9 @@ test("provider with single env var includes apiKey automatically", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("SINGLE_ENV_KEY", "my-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() expect(providers[ProviderID.make("single-env")]).toBeDefined() @@ -1324,9 +1324,9 @@ test("model cost overrides existing cost values", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() const model = providers[ProviderID.anthropic].models["claude-sonnet-4-20250514"] @@ -1403,11 +1403,11 @@ test("disabled_providers and enabled_providers interaction", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-anthropic") set("OPENAI_API_KEY", "test-openai") set("GOOGLE_GENERATIVE_AI_API_KEY", "test-google") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() // anthropic: in enabled, not in disabled = allowed @@ -1561,10 +1561,10 @@ test("provider env fallback - second env var used if first missing", async () => }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { // Only set fallback, not primary set("FALLBACK_KEY", "fallback-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() // Provider should load because fallback env var is set @@ -1586,9 +1586,9 @@ test("getModel returns consistent results", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const model1 = await getModel(ProviderID.anthropic, ModelID.make("claude-sonnet-4-20250514")) const model2 = await getModel(ProviderID.anthropic, ModelID.make("claude-sonnet-4-20250514")) @@ -1647,9 +1647,9 @@ test("ModelNotFoundError includes suggestions for typos", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { try { await getModel(ProviderID.anthropic, ModelID.make("claude-sonet-4")) // typo: sonet instead of sonnet @@ -1675,9 +1675,9 @@ test("ModelNotFoundError for provider includes suggestions", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { try { await getModel(ProviderID.make("antropic"), ModelID.make("claude-sonnet-4")) // typo: antropic @@ -1723,9 +1723,9 @@ test("getProvider returns provider info", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const provider = await getProvider(ProviderID.anthropic) expect(provider).toBeDefined() @@ -1747,9 +1747,9 @@ test("closest returns undefined when no partial match found", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const result = await closest(ProviderID.anthropic, ["nonexistent-xyz-model"]) expect(result).toBeUndefined() @@ -1770,9 +1770,9 @@ test("closest checks multiple query terms in order", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { // First term won't match, second will const result = await closest(ProviderID.anthropic, ["nonexistent", "haiku"]) @@ -1842,9 +1842,9 @@ test("provider options are deeply merged", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() // Custom options should be merged @@ -1880,9 +1880,9 @@ test("custom model inherits npm package from models.dev provider config", async }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("OPENAI_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() const model = providers[ProviderID.openai].models["my-custom-model"] @@ -1915,9 +1915,9 @@ test("custom model inherits api.url from models.dev provider", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("OPENROUTER_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() expect(providers[ProviderID.openrouter]).toBeDefined() @@ -2048,9 +2048,9 @@ test("model variants are generated for reasoning models", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() // Claude sonnet 4 has reasoning capability @@ -2086,9 +2086,9 @@ test("model variants can be disabled via config", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() const model = providers[ProviderID.anthropic].models["claude-sonnet-4-20250514"] @@ -2129,9 +2129,9 @@ test("model variants can be customized via config", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() const model = providers[ProviderID.anthropic].models["claude-sonnet-4-20250514"] @@ -2168,9 +2168,9 @@ test("disabled key is stripped from variant config", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() const model = providers[ProviderID.anthropic].models["claude-sonnet-4-20250514"] @@ -2206,9 +2206,9 @@ test("all variants can be disabled via config", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() const model = providers[ProviderID.anthropic].models["claude-sonnet-4-20250514"] @@ -2244,9 +2244,9 @@ test("variant config merges with generated variants", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() const model = providers[ProviderID.anthropic].models["claude-sonnet-4-20250514"] @@ -2282,9 +2282,9 @@ test("variants filtered in second pass for database models", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("OPENAI_API_KEY", "test-api-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() const model = providers[ProviderID.openai].models["gpt-5"] @@ -2386,9 +2386,9 @@ test("Google Vertex: retains baseURL for custom proxy", async () => { await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("GOOGLE_APPLICATION_CREDENTIALS", "test-creds") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() expect(providers[ProviderID.make("vertex-proxy")]).toBeDefined() @@ -2431,9 +2431,9 @@ test("Google Vertex: supports OpenAI compatible models", async () => { await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("GOOGLE_APPLICATION_CREDENTIALS", "test-creds") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() const model = providers[ProviderID.make("vertex-openai")].models["gpt-4"] @@ -2457,11 +2457,11 @@ test("cloudflare-ai-gateway loads with env variables", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("CLOUDFLARE_ACCOUNT_ID", "test-account") set("CLOUDFLARE_GATEWAY_ID", "test-gateway") set("CLOUDFLARE_API_TOKEN", "test-token") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() expect(providers[ProviderID.make("cloudflare-ai-gateway")]).toBeDefined() @@ -2489,11 +2489,11 @@ test("cloudflare-ai-gateway forwards config metadata options", async () => { }) await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("CLOUDFLARE_ACCOUNT_ID", "test-account") set("CLOUDFLARE_GATEWAY_ID", "test-gateway") set("CLOUDFLARE_API_TOKEN", "test-token") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() expect(providers[ProviderID.make("cloudflare-ai-gateway")]).toBeDefined() @@ -2592,10 +2592,10 @@ test("plugin config enabled and disabled providers are honored", async () => { await Instance.provide({ directory: tmp.path, - init: async () => { + init: Effect.promise(async () => { set("ANTHROPIC_API_KEY", "test-anthropic-key") set("OPENAI_API_KEY", "test-openai-key") - }, + }).pipe(Effect.asVoid), fn: async () => { const providers = await list() expect(providers[ProviderID.anthropic]).toBeDefined()