feat(plugin): add v2 effect host (#33111)

This commit is contained in:
Dax
2026-06-21 08:05:49 -04:00
committed by GitHub
parent 7a9337da8a
commit c780d7cee7
139 changed files with 3749 additions and 1952 deletions
@@ -1,35 +1,10 @@
import { describe, expect } from "bun:test"
import { Effect, Layer } from "effect"
import { Credential } from "@opencode-ai/core/credential"
import { Integration } from "@opencode-ai/core/integration"
import { Database } from "@opencode-ai/core/database/database"
import { Effect } from "effect"
import { Catalog } from "@opencode-ai/core/catalog"
import { EventV2 } from "@opencode-ai/core/event"
import { Location } from "@opencode-ai/core/location"
import { PluginV2 } from "@opencode-ai/core/plugin"
import { AzurePlugin } from "@opencode-ai/core/plugin/provider/azure"
import { ProviderV2 } from "@opencode-ai/core/provider"
import { AbsolutePath } from "@opencode-ai/core/schema"
import { location } from "../fixture/location"
import { testEffect } from "../lib/effect"
import { fakeSelectorSdk, it, model, npmLayer, provider, withEnv } from "./provider-helper"
const database = Database.layerFromPath(":memory:").pipe(Layer.fresh)
const preferences = Credential.layer.pipe(Layer.provide(database))
const accounts = Layer.merge(
Credential.layer.pipe(Layer.provide(database), Layer.provide(preferences), Layer.provide(EventV2.defaultLayer)),
preferences,
)
const itWithAccount = testEffect(
Catalog.locationLayer.pipe(
Layer.provideMerge(accounts),
Layer.provideMerge(EventV2.defaultLayer),
Layer.provideMerge(
Layer.succeed(Location.Service, Location.Service.of(location({ directory: AbsolutePath.make("test") }))),
),
Layer.provideMerge(npmLayer),
),
)
import { addPlugin, fakeSelectorSdk, it, model, provider, required, withEnv } from "./provider-helper"
describe("AzurePlugin", () => {
it.effect("resolves resourceName from env", () =>
@@ -37,14 +12,13 @@ describe("AzurePlugin", () => {
Effect.gen(function* () {
const plugin = yield* PluginV2.Service
const catalog = yield* Catalog.Service
yield* plugin.add(AzurePlugin)
const transform = yield* catalog.transform()
yield* transform((catalog) => {
yield* catalog.transform((catalog) => {
catalog.provider.update(ProviderV2.ID.azure, (item) => {
item.api = { type: "aisdk", package: "@ai-sdk/azure" }
})
})
expect((yield* catalog.provider.get(ProviderV2.ID.azure)).request.body.resourceName).toBe("from-env")
yield* addPlugin(plugin, AzurePlugin)
expect(required(yield* catalog.provider.get(ProviderV2.ID.azure)).request.body.resourceName).toBe("from-env")
}),
),
)
@@ -54,9 +28,7 @@ describe("AzurePlugin", () => {
Effect.gen(function* () {
const plugin = yield* PluginV2.Service
const catalog = yield* Catalog.Service
yield* plugin.add(AzurePlugin)
const transform = yield* catalog.transform()
yield* transform((catalog) => {
yield* catalog.transform((catalog) => {
const azure = provider("azure", {
api: { type: "aisdk", package: "@ai-sdk/azure" },
request: { headers: {}, body: { resourceName: "from-config" } },
@@ -67,50 +39,19 @@ describe("AzurePlugin", () => {
})
catalog.provider.update(ProviderV2.ID.openai, () => {})
})
expect((yield* catalog.provider.get(ProviderV2.ID.azure)).request.body.resourceName).toBe("from-config")
expect((yield* catalog.provider.get(ProviderV2.ID.openai)).request.body.resourceName).toBeUndefined()
yield* addPlugin(plugin, AzurePlugin)
expect(required(yield* catalog.provider.get(ProviderV2.ID.azure)).request.body.resourceName).toBe("from-config")
expect(required(yield* catalog.provider.get(ProviderV2.ID.openai)).request.body.resourceName).toBeUndefined()
}),
),
)
itWithAccount.effect("prefers account resourceName over env", () =>
withEnv(
{
AZURE_RESOURCE_NAME: "from-env",
},
() =>
Effect.gen(function* () {
const plugin = yield* PluginV2.Service
const credentials = yield* Credential.Service
const catalog = yield* Catalog.Service
yield* credentials.create({
integrationID: Integration.ID.make("azure"),
value: new Credential.Key({
type: "key",
key: "key",
metadata: { resourceName: "from-account" },
}),
})
yield* plugin.add(AzurePlugin)
const transform = yield* catalog.transform()
yield* transform((catalog) => {
catalog.provider.update(ProviderV2.ID.azure, (item) => {
item.api = { type: "aisdk", package: "@ai-sdk/azure" }
})
})
expect((yield* catalog.provider.get(ProviderV2.ID.azure)).request.body.resourceName).toBe("from-account")
}),
),
)
it.effect("falls back to env when configured resourceName is blank", () =>
withEnv({ AZURE_RESOURCE_NAME: "from-env" }, () =>
Effect.gen(function* () {
const plugin = yield* PluginV2.Service
const catalog = yield* Catalog.Service
yield* plugin.add(AzurePlugin)
const transform = yield* catalog.transform()
yield* transform((catalog) => {
yield* catalog.transform((catalog) => {
const azure = provider("azure", {
api: { type: "aisdk", package: "@ai-sdk/azure" },
request: { headers: {}, body: { resourceName: "" } },
@@ -120,7 +61,8 @@ describe("AzurePlugin", () => {
item.request = azure.request
})
})
expect((yield* catalog.provider.get(ProviderV2.ID.azure)).request.body.resourceName).toBe("from-env")
yield* addPlugin(plugin, AzurePlugin)
expect(required(yield* catalog.provider.get(ProviderV2.ID.azure)).request.body.resourceName).toBe("from-env")
}),
),
)
@@ -130,9 +72,7 @@ describe("AzurePlugin", () => {
Effect.gen(function* () {
const plugin = yield* PluginV2.Service
const catalog = yield* Catalog.Service
yield* plugin.add(AzurePlugin)
const transform = yield* catalog.transform()
yield* transform((catalog) => {
yield* catalog.transform((catalog) => {
const azure = provider("azure", {
api: { type: "aisdk", package: "@ai-sdk/azure" },
request: { headers: {}, body: { resourceName: " " } },
@@ -142,7 +82,8 @@ describe("AzurePlugin", () => {
item.request = azure.request
})
})
expect((yield* catalog.provider.get(ProviderV2.ID.azure)).request.body.resourceName).toBe("from-env")
yield* addPlugin(plugin, AzurePlugin)
expect(required(yield* catalog.provider.get(ProviderV2.ID.azure)).request.body.resourceName).toBe("from-env")
}),
),
)
@@ -151,7 +92,7 @@ describe("AzurePlugin", () => {
withEnv({ AZURE_RESOURCE_NAME: undefined }, () =>
Effect.gen(function* () {
const plugin = yield* PluginV2.Service
yield* plugin.add(AzurePlugin)
yield* addPlugin(plugin, AzurePlugin)
const result = yield* plugin.trigger(
"aisdk.sdk",
{
@@ -170,7 +111,7 @@ describe("AzurePlugin", () => {
withEnv({ AZURE_RESOURCE_NAME: undefined }, () =>
Effect.gen(function* () {
const plugin = yield* PluginV2.Service
yield* plugin.add(AzurePlugin)
yield* addPlugin(plugin, AzurePlugin)
const exit = yield* plugin
.trigger(
"aisdk.sdk",
@@ -187,7 +128,7 @@ describe("AzurePlugin", () => {
Effect.gen(function* () {
const plugin = yield* PluginV2.Service
const calls: string[] = []
yield* plugin.add(AzurePlugin)
yield* addPlugin(plugin, AzurePlugin)
yield* plugin.trigger(
"aisdk.language",
{ model: model("azure", "deployment"), sdk: fakeSelectorSdk(calls), options: { useCompletionUrls: true } },
@@ -201,7 +142,7 @@ describe("AzurePlugin", () => {
Effect.gen(function* () {
const plugin = yield* PluginV2.Service
const calls: string[] = []
yield* plugin.add(AzurePlugin)
yield* addPlugin(plugin, AzurePlugin)
yield* plugin.trigger(
"aisdk.language",
{ model: model("azure", "deployment"), sdk: fakeSelectorSdk(calls), options: { useCompletionUrls: true } },
@@ -215,7 +156,7 @@ describe("AzurePlugin", () => {
Effect.gen(function* () {
const plugin = yield* PluginV2.Service
const calls: string[] = []
yield* plugin.add(AzurePlugin)
yield* addPlugin(plugin, AzurePlugin)
yield* plugin.trigger(
"aisdk.language",
{
@@ -235,7 +176,7 @@ describe("AzurePlugin", () => {
Effect.gen(function* () {
const plugin = yield* PluginV2.Service
const calls: string[] = []
yield* plugin.add(AzurePlugin)
yield* addPlugin(plugin, AzurePlugin)
yield* plugin.trigger(
"aisdk.language",
{ model: model("azure", "deployment"), sdk: fakeSelectorSdk(calls), options: {} },
@@ -259,7 +200,7 @@ describe("AzurePlugin", () => {
calls.push(`${method}:${id}`)
return { modelId: id, provider: method, specificationVersion: "v3" }
}
yield* plugin.add(AzurePlugin)
yield* addPlugin(plugin, AzurePlugin)
yield* plugin.trigger(
"aisdk.language",
{