mirror of
https://github.com/anomalyco/opencode.git
synced 2026-08-29 23:01:53 +00:00
test(core): simplify provider test fixtures (#45743)
This commit is contained in:
parent
f61858e683
commit
2751813454
8 changed files with 60 additions and 133 deletions
|
|
@ -27,7 +27,7 @@ import { Pty } from "@opencode-ai/schema/pty"
|
|||
import type { SessionHooks } from "@opencode-ai/plugin/effect/session"
|
||||
import { testEffect } from "../lib/effect"
|
||||
import { PluginTestLayer } from "./fixture"
|
||||
import { host as testHost } from "./host"
|
||||
import { host } from "./host"
|
||||
|
||||
const it = testEffect(PluginTestLayer)
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ describe("fromPromise", () => {
|
|||
foregroundProcess: "bun",
|
||||
screen: { text: "one\ntwo\nthree", cols: 80, rows: 2, cursor: { x: 3, y: 1 } },
|
||||
})
|
||||
const host = testHost({
|
||||
const context = host({
|
||||
experimental: {
|
||||
terminal: {
|
||||
read: (input) => {
|
||||
|
|
@ -72,7 +72,7 @@ describe("fromPromise", () => {
|
|||
await ctx.experimental.terminal.read({ sessionID: "ses_terminal", lines: 65535 })
|
||||
},
|
||||
}),
|
||||
).effect(host)
|
||||
).effect(context)
|
||||
|
||||
expect(seen).toEqual([
|
||||
{ sessionID: Session.ID.make("ses_terminal") },
|
||||
|
|
@ -85,7 +85,7 @@ describe("fromPromise", () => {
|
|||
|
||||
it.effect("preserves null terminal reads and rejects daemon failures", () =>
|
||||
Effect.gen(function* () {
|
||||
const host = testHost({
|
||||
const context = host({
|
||||
experimental: {
|
||||
terminal: {
|
||||
read: (input) =>
|
||||
|
|
@ -106,7 +106,7 @@ describe("fromPromise", () => {
|
|||
)
|
||||
},
|
||||
}),
|
||||
).effect(host)
|
||||
).effect(context)
|
||||
}),
|
||||
)
|
||||
|
||||
|
|
@ -174,7 +174,7 @@ describe("fromPromise", () => {
|
|||
it.effect("adapts session creation through the protocol schema", () =>
|
||||
Effect.gen(function* () {
|
||||
let seen: unknown
|
||||
const host = testHost({
|
||||
const context = host({
|
||||
session: {
|
||||
create: (input) => {
|
||||
seen = input
|
||||
|
|
@ -212,7 +212,7 @@ describe("fromPromise", () => {
|
|||
})
|
||||
},
|
||||
}),
|
||||
).effect(host)
|
||||
).effect(context)
|
||||
|
||||
expect(seen).toEqual({ title: "Promise title" })
|
||||
}),
|
||||
|
|
@ -220,7 +220,7 @@ describe("fromPromise", () => {
|
|||
|
||||
it.effect("forwards transient session generation", () =>
|
||||
Effect.gen(function* () {
|
||||
const host = testHost({
|
||||
const context = host({
|
||||
session: {
|
||||
generate: (input) => Effect.succeed({ text: `${input.sessionID}: ${input.prompt}` }),
|
||||
},
|
||||
|
|
@ -235,14 +235,14 @@ describe("fromPromise", () => {
|
|||
})
|
||||
},
|
||||
}),
|
||||
).effect(host)
|
||||
).effect(context)
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("preserves interrupt results and rejected Promise behavior", () =>
|
||||
Effect.gen(function* () {
|
||||
const seen: unknown[] = []
|
||||
const host = testHost({
|
||||
const context = host({
|
||||
session: {
|
||||
interrupt: (input) => {
|
||||
if (input.sessionID === Session.ID.make("ses_failure")) {
|
||||
|
|
@ -281,7 +281,7 @@ describe("fromPromise", () => {
|
|||
expect(await ctx.session.wait({ sessionID: "ses_success" })).toBeUndefined()
|
||||
},
|
||||
}),
|
||||
).effect(host)
|
||||
).effect(context)
|
||||
|
||||
expect(seen).toEqual([
|
||||
{ sessionID: Session.ID.make("ses_success"), agent: Agent.ID.make("build") },
|
||||
|
|
@ -312,7 +312,7 @@ describe("fromPromise", () => {
|
|||
resume: null,
|
||||
}
|
||||
let seen: unknown
|
||||
const host = testHost({
|
||||
const context = host({
|
||||
session: {
|
||||
synthetic: (value) => {
|
||||
seen = value
|
||||
|
|
@ -340,7 +340,7 @@ describe("fromPromise", () => {
|
|||
await ctx.session.synthetic(input)
|
||||
},
|
||||
}),
|
||||
).effect(host)
|
||||
).effect(context)
|
||||
|
||||
expect(seen).toEqual({
|
||||
...input,
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ const it = testEffect(PluginTestLayer)
|
|||
|
||||
const addPlugin = Effect.fn(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
const host = yield* PluginHost.make(plugin)
|
||||
yield* AmazonBedrockPlugin.effect(host)
|
||||
})
|
||||
|
|
@ -83,13 +82,8 @@ describe("AmazonBedrockPlugin", () => {
|
|||
Effect.gen(function* () {
|
||||
const catalog = yield* Catalog.Service
|
||||
yield* catalog.transform((catalog) => {
|
||||
const bedrock = Provider.Info.make({
|
||||
...Provider.Info.empty(Provider.ID.amazonBedrock),
|
||||
package: Provider.aisdk("@ai-sdk/amazon-bedrock"),
|
||||
settings: { endpoint: "https://bedrock.example" },
|
||||
})
|
||||
catalog.provider.update(bedrock.id, (item) => {
|
||||
item.package = bedrock.package
|
||||
catalog.provider.update(Provider.ID.amazonBedrock, (item) => {
|
||||
item.package = Provider.aisdk("@ai-sdk/amazon-bedrock")
|
||||
item.settings = { endpoint: "https://bedrock.example" }
|
||||
})
|
||||
})
|
||||
|
|
@ -103,7 +97,6 @@ describe("AmazonBedrockPlugin", () => {
|
|||
it.effect("prefers endpoint over baseURL for SDK base URL", () =>
|
||||
withEnv({ AWS_BEARER_TOKEN_BEDROCK: undefined, AWS_PROFILE: undefined, AWS_ACCESS_KEY_ID: undefined }, () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
yield* addPlugin()
|
||||
const result = yield* aisdk.runSDK({
|
||||
|
|
@ -129,7 +122,6 @@ describe("AmazonBedrockPlugin", () => {
|
|||
it.effect("uses baseURL as SDK base URL", () =>
|
||||
withEnv({ AWS_BEARER_TOKEN_BEDROCK: undefined, AWS_PROFILE: undefined, AWS_ACCESS_KEY_ID: undefined }, () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
yield* addPlugin()
|
||||
const result = yield* aisdk.runSDK({
|
||||
|
|
@ -164,7 +156,6 @@ describe("AmazonBedrockPlugin", () => {
|
|||
},
|
||||
() =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
yield* addPlugin()
|
||||
const result = yield* aisdk.runSDK({
|
||||
|
|
@ -185,7 +176,6 @@ describe("AmazonBedrockPlugin", () => {
|
|||
it.effect("uses config region over AWS_REGION for SDK base URL", () =>
|
||||
withEnv({ AWS_BEARER_TOKEN_BEDROCK: "token", AWS_REGION: "us-east-1" }, () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
yield* addPlugin()
|
||||
const result = yield* aisdk.runSDK({
|
||||
|
|
@ -205,7 +195,6 @@ describe("AmazonBedrockPlugin", () => {
|
|||
it.effect("uses AWS_REGION for SDK base URL when config region is absent", () =>
|
||||
withEnv({ AWS_BEARER_TOKEN_BEDROCK: "token", AWS_REGION: "eu-west-1" }, () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
yield* addPlugin()
|
||||
const result = yield* aisdk.runSDK({
|
||||
|
|
@ -225,7 +214,6 @@ describe("AmazonBedrockPlugin", () => {
|
|||
it.effect("defaults SDK region to us-east-1", () =>
|
||||
withEnv({ AWS_BEARER_TOKEN_BEDROCK: "token", AWS_REGION: undefined }, () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
yield* addPlugin()
|
||||
const result = yield* aisdk.runSDK({
|
||||
|
|
@ -245,7 +233,6 @@ describe("AmazonBedrockPlugin", () => {
|
|||
it.effect("loads bearer token option into env and uses bearer auth", () =>
|
||||
withEnv({ AWS_ACCESS_KEY_ID: undefined, AWS_BEARER_TOKEN_BEDROCK: undefined, AWS_PROFILE: undefined }, () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
const headers: Array<string | null> = []
|
||||
yield* addPlugin()
|
||||
|
|
@ -275,7 +262,6 @@ describe("AmazonBedrockPlugin", () => {
|
|||
it.effect("prefers bearer token env over bearer token option", () =>
|
||||
withEnv({ AWS_BEARER_TOKEN_BEDROCK: "env-token" }, () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
const headers: Array<string | null> = []
|
||||
yield* addPlugin()
|
||||
|
|
@ -305,7 +291,6 @@ describe("AmazonBedrockPlugin", () => {
|
|||
it.effect("creates Mantle SDK with GPT-5 OpenAI base path", () =>
|
||||
withEnv({ AWS_BEARER_TOKEN_BEDROCK: undefined, AWS_PROFILE: undefined, AWS_ACCESS_KEY_ID: undefined }, () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
yield* addPlugin()
|
||||
const result = yield* aisdk.runSDK({
|
||||
|
|
@ -332,7 +317,6 @@ describe("AmazonBedrockPlugin", () => {
|
|||
|
||||
it.effect("selects Mantle APIs without Bedrock cross-region prefixes", () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
const calls: string[] = []
|
||||
yield* addPlugin()
|
||||
|
|
@ -360,7 +344,6 @@ describe("AmazonBedrockPlugin", () => {
|
|||
|
||||
it.effect("ignores other Bedrock provider subpaths", () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
yield* addPlugin()
|
||||
const result = yield* aisdk.runSDK({
|
||||
|
|
@ -387,7 +370,6 @@ describe("AmazonBedrockPlugin", () => {
|
|||
},
|
||||
() =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
const headers: Array<string | null> = []
|
||||
yield* addPlugin()
|
||||
|
|
@ -419,7 +401,6 @@ describe("AmazonBedrockPlugin", () => {
|
|||
|
||||
it.effect("applies legacy cross-region inference prefixes", () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
const calls: string[] = []
|
||||
yield* addPlugin()
|
||||
|
|
@ -481,7 +462,6 @@ describe("AmazonBedrockPlugin", () => {
|
|||
it.effect("uses AWS_REGION for language prefixes when region option is absent", () =>
|
||||
withEnv({ AWS_REGION: "eu-west-1" }, () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
const calls: string[] = []
|
||||
yield* addPlugin()
|
||||
|
|
@ -501,7 +481,6 @@ describe("AmazonBedrockPlugin", () => {
|
|||
|
||||
it.effect("applies the full legacy cross-region prefix matrix", () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
const calls: string[] = []
|
||||
const cases = [
|
||||
|
|
@ -588,7 +567,6 @@ describe("AmazonBedrockPlugin", () => {
|
|||
|
||||
it.effect("ignores non-Bedrock providers for language selection", () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
const calls: string[] = []
|
||||
yield* addPlugin()
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ const it = testEffect(PluginTestLayer)
|
|||
|
||||
const addPlugin = Effect.fn(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
const host = yield* PluginHost.make(plugin)
|
||||
yield* AnthropicPlugin.effect(host)
|
||||
})
|
||||
|
|
@ -29,13 +28,8 @@ describe("AnthropicPlugin", () => {
|
|||
Effect.gen(function* () {
|
||||
const catalog = yield* Catalog.Service
|
||||
yield* catalog.transform((catalog) => {
|
||||
const item = Provider.Info.make({
|
||||
...Provider.Info.empty(Provider.ID.anthropic),
|
||||
package: Provider.aisdk("@ai-sdk/anthropic"),
|
||||
headers: { Existing: "1" },
|
||||
})
|
||||
catalog.provider.update(item.id, (draft) => {
|
||||
draft.package = item.package
|
||||
catalog.provider.update(Provider.ID.anthropic, (draft) => {
|
||||
draft.package = Provider.aisdk("@ai-sdk/anthropic")
|
||||
draft.headers = { Existing: "1" }
|
||||
})
|
||||
})
|
||||
|
|
@ -58,7 +52,6 @@ describe("AnthropicPlugin", () => {
|
|||
|
||||
it.effect("creates Anthropic SDKs with the model provider ID as the SDK name", () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
yield* addPlugin()
|
||||
const result = yield* aisdk.runSDK({
|
||||
|
|
@ -76,7 +69,6 @@ describe("AnthropicPlugin", () => {
|
|||
|
||||
it.effect("uses the Anthropic provider ID as the SDK name for the bundled Anthropic provider", () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
yield* addPlugin()
|
||||
const result = yield* aisdk.runSDK({
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ const it = testEffect(PluginTestLayer)
|
|||
|
||||
const addPlugin = Effect.fn(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
const host = yield* PluginHost.make(plugin)
|
||||
yield* AzurePlugin.effect(host)
|
||||
})
|
||||
|
|
@ -137,7 +136,8 @@ describe("AzurePlugin", () => {
|
|||
withEnv({ AZURE_RESOURCE_NAME: undefined, AZURE_COGNITIVE_SERVICES_RESOURCE_NAME: undefined }, () =>
|
||||
Effect.gen(function* () {
|
||||
yield* addPlugin()
|
||||
expect((yield* (yield* Integration.Service).get(Integration.ID.make("azure")))?.methods).toContainEqual({
|
||||
const integrations = yield* Integration.Service
|
||||
expect((yield* integrations.get(Integration.ID.make("azure")))?.methods).toContainEqual({
|
||||
type: "key",
|
||||
label: "API key",
|
||||
form: [
|
||||
|
|
@ -562,13 +562,8 @@ describe("AzurePlugin", () => {
|
|||
Effect.gen(function* () {
|
||||
const catalog = yield* Catalog.Service
|
||||
yield* catalog.transform((catalog) => {
|
||||
const azure = Provider.Info.make({
|
||||
...Provider.Info.empty(Provider.ID.azure),
|
||||
package: Provider.aisdk("@ai-sdk/azure"),
|
||||
settings: { resourceName: "from-config" },
|
||||
})
|
||||
catalog.provider.update(azure.id, (item) => {
|
||||
item.package = azure.package
|
||||
catalog.provider.update(Provider.ID.azure, (item) => {
|
||||
item.package = Provider.aisdk("@ai-sdk/azure")
|
||||
item.settings = { resourceName: "from-config" }
|
||||
})
|
||||
catalog.provider.update(Provider.ID.openai, () => {})
|
||||
|
|
@ -585,13 +580,8 @@ describe("AzurePlugin", () => {
|
|||
Effect.gen(function* () {
|
||||
const catalog = yield* Catalog.Service
|
||||
yield* catalog.transform((catalog) => {
|
||||
const azure = Provider.Info.make({
|
||||
...Provider.Info.empty(Provider.ID.azure),
|
||||
package: Provider.aisdk("@ai-sdk/azure"),
|
||||
settings: { resourceName: "" },
|
||||
})
|
||||
catalog.provider.update(azure.id, (item) => {
|
||||
item.package = azure.package
|
||||
catalog.provider.update(Provider.ID.azure, (item) => {
|
||||
item.package = Provider.aisdk("@ai-sdk/azure")
|
||||
item.settings = { resourceName: "" }
|
||||
})
|
||||
})
|
||||
|
|
@ -606,13 +596,8 @@ describe("AzurePlugin", () => {
|
|||
Effect.gen(function* () {
|
||||
const catalog = yield* Catalog.Service
|
||||
yield* catalog.transform((catalog) => {
|
||||
const azure = Provider.Info.make({
|
||||
...Provider.Info.empty(Provider.ID.azure),
|
||||
package: Provider.aisdk("@ai-sdk/azure"),
|
||||
settings: { resourceName: " " },
|
||||
})
|
||||
catalog.provider.update(azure.id, (item) => {
|
||||
item.package = azure.package
|
||||
catalog.provider.update(Provider.ID.azure, (item) => {
|
||||
item.package = Provider.aisdk("@ai-sdk/azure")
|
||||
item.settings = { resourceName: " " }
|
||||
})
|
||||
})
|
||||
|
|
@ -625,7 +610,6 @@ describe("AzurePlugin", () => {
|
|||
it.effect("allows configured baseURL without resourceName", () =>
|
||||
withEnv({ AZURE_RESOURCE_NAME: undefined }, () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
const catalog = yield* Catalog.Service
|
||||
yield* catalog.transform((catalog) =>
|
||||
|
|
@ -634,7 +618,8 @@ describe("AzurePlugin", () => {
|
|||
}),
|
||||
)
|
||||
yield* addPlugin()
|
||||
expect((yield* (yield* Integration.Service).get(Integration.ID.make("azure")))?.methods).toContainEqual({
|
||||
const integrations = yield* Integration.Service
|
||||
expect((yield* integrations.get(Integration.ID.make("azure")))?.methods).toContainEqual({
|
||||
type: "key",
|
||||
label: "API key",
|
||||
})
|
||||
|
|
@ -722,7 +707,6 @@ describe("AzurePlugin", () => {
|
|||
|
||||
it.effect("selects chat only for completion URLs", () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
const calls: string[] = []
|
||||
yield* addPlugin()
|
||||
|
|
@ -741,7 +725,6 @@ describe("AzurePlugin", () => {
|
|||
|
||||
it.effect("selects chat from per-call useCompletionUrls", () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
const calls: string[] = []
|
||||
yield* addPlugin()
|
||||
|
|
@ -760,7 +743,6 @@ describe("AzurePlugin", () => {
|
|||
|
||||
it.effect("ignores model useCompletionUrls when per-call option is unset", () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
const calls: string[] = []
|
||||
yield* addPlugin()
|
||||
|
|
@ -780,7 +762,6 @@ describe("AzurePlugin", () => {
|
|||
|
||||
it.effect("uses the legacy Azure selector order and provider guard", () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
const calls: string[] = []
|
||||
yield* addPlugin()
|
||||
|
|
@ -809,7 +790,6 @@ describe("AzurePlugin", () => {
|
|||
|
||||
it.effect("falls back through the legacy Azure selector order", () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
const calls: string[] = []
|
||||
const make = (method: string) => (id: string) => {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ const it = testEffect(PluginTestLayer)
|
|||
|
||||
const addPlugin = Effect.fn(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
const host = yield* PluginHost.make(plugin)
|
||||
yield* CloudflareWorkersAIPlugin.effect(host)
|
||||
})
|
||||
|
|
@ -84,9 +83,8 @@ describe("CloudflareWorkersAIPlugin", () => {
|
|||
withEnv({ CLOUDFLARE_ACCOUNT_ID: undefined }, () =>
|
||||
Effect.gen(function* () {
|
||||
yield* addPlugin()
|
||||
expect(
|
||||
(yield* (yield* Integration.Service).get(Integration.ID.make("cloudflare-workers-ai")))?.methods,
|
||||
).toContainEqual({
|
||||
const integrations = yield* Integration.Service
|
||||
expect((yield* integrations.get(Integration.ID.make("cloudflare-workers-ai")))?.methods).toContainEqual({
|
||||
type: "key",
|
||||
label: "API key",
|
||||
form: [
|
||||
|
|
@ -106,7 +104,6 @@ describe("CloudflareWorkersAIPlugin", () => {
|
|||
it.effect("maps account ID to endpoint URL and creates an OpenAI-compatible SDK", () =>
|
||||
withEnv({ CLOUDFLARE_ACCOUNT_ID: "acct", CLOUDFLARE_API_KEY: "key" }, () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
const catalog = yield* Catalog.Service
|
||||
yield* catalog.transform((catalog) =>
|
||||
|
|
@ -115,9 +112,11 @@ describe("CloudflareWorkersAIPlugin", () => {
|
|||
}),
|
||||
)
|
||||
yield* addPlugin()
|
||||
expect(
|
||||
(yield* (yield* Integration.Service).get(Integration.ID.make("cloudflare-workers-ai")))?.methods,
|
||||
).toContainEqual({ type: "key", label: "API key" })
|
||||
const integrations = yield* Integration.Service
|
||||
expect((yield* integrations.get(Integration.ID.make("cloudflare-workers-ai")))?.methods).toContainEqual({
|
||||
type: "key",
|
||||
label: "API key",
|
||||
})
|
||||
const provider = required(yield* catalog.provider.get(Provider.ID.make("cloudflare-workers-ai")))
|
||||
const sdk = yield* aisdk.runSDK({
|
||||
model: Model.Info.make({
|
||||
|
|
@ -160,7 +159,6 @@ describe("CloudflareWorkersAIPlugin", () => {
|
|||
it.effect("allows a configured baseURL without account ID", () =>
|
||||
withEnv({ CLOUDFLARE_ACCOUNT_ID: undefined, CLOUDFLARE_API_KEY: "key" }, () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
const catalog = yield* Catalog.Service
|
||||
yield* catalog.transform((catalog) =>
|
||||
|
|
@ -169,9 +167,11 @@ describe("CloudflareWorkersAIPlugin", () => {
|
|||
}),
|
||||
)
|
||||
yield* addPlugin()
|
||||
expect(
|
||||
(yield* (yield* Integration.Service).get(Integration.ID.make("cloudflare-workers-ai")))?.methods,
|
||||
).toContainEqual({ type: "key", label: "API key" })
|
||||
const integrations = yield* Integration.Service
|
||||
expect((yield* integrations.get(Integration.ID.make("cloudflare-workers-ai")))?.methods).toContainEqual({
|
||||
type: "key",
|
||||
label: "API key",
|
||||
})
|
||||
const result = yield* aisdk.runSDK({
|
||||
model: Model.Info.make({
|
||||
...Model.Info.default(Provider.ID.make("cloudflare-workers-ai"), Model.ID.make("@cf/model")),
|
||||
|
|
@ -209,7 +209,6 @@ describe("CloudflareWorkersAIPlugin", () => {
|
|||
it.effect("uses env API key over auth or configured API key and keeps the Cloudflare User-Agent", () =>
|
||||
withEnv({ CLOUDFLARE_ACCOUNT_ID: "acct", CLOUDFLARE_API_KEY: "env-key" }, () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
yield* addPlugin()
|
||||
const result = yield* aisdk.runSDK({
|
||||
|
|
@ -238,7 +237,6 @@ describe("CloudflareWorkersAIPlugin", () => {
|
|||
it.effect("expands account ID vars in endpoint URLs", () =>
|
||||
withEnv({ CLOUDFLARE_ACCOUNT_ID: "acct", CLOUDFLARE_API_KEY: "key" }, () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
yield* addPlugin()
|
||||
const result = yield* aisdk.runSDK({
|
||||
|
|
@ -263,7 +261,6 @@ describe("CloudflareWorkersAIPlugin", () => {
|
|||
|
||||
it.effect("selects languageModel with the API model ID", () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
const calls: string[] = []
|
||||
yield* addPlugin()
|
||||
|
|
@ -284,7 +281,6 @@ describe("CloudflareWorkersAIPlugin", () => {
|
|||
it.effect("does not create an SDK for non OpenAI-compatible packages", () =>
|
||||
withEnv({ CLOUDFLARE_ACCOUNT_ID: "acct", CLOUDFLARE_API_KEY: "key" }, () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
yield* addPlugin()
|
||||
const result = yield* aisdk.runSDK({
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ const it = testEffect(PluginTestLayer)
|
|||
|
||||
const addPlugin = Effect.fn(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
const host = yield* PluginHost.make(plugin)
|
||||
yield* OpenAICompatiblePlugin.effect(host)
|
||||
})
|
||||
|
|
@ -21,7 +20,6 @@ const addPlugin = Effect.fn(function* () {
|
|||
describe("OpenAICompatiblePlugin", () => {
|
||||
it.effect("preserves explicit includeUsage false and defaults it to true", () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
yield* addPlugin()
|
||||
const defaulted = yield* aisdk.runSDK({
|
||||
|
|
@ -49,7 +47,6 @@ describe("OpenAICompatiblePlugin", () => {
|
|||
|
||||
it.effect("defaults includeUsage for OpenAI-compatible package matches", () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
yield* addPlugin()
|
||||
const result = yield* aisdk.runSDK({
|
||||
|
|
@ -67,7 +64,6 @@ describe("OpenAICompatiblePlugin", () => {
|
|||
|
||||
it.effect("uses the provider ID as the OpenAI-compatible provider name", () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
const observed: string[] = []
|
||||
yield* addPlugin()
|
||||
|
|
|
|||
|
|
@ -85,14 +85,10 @@ describe("OpenAIPlugin", () => {
|
|||
const catalog = yield* Catalog.Service
|
||||
const credentials = yield* Credential.Service
|
||||
yield* catalog.transform((catalog) => {
|
||||
const item = Provider.Info.make({
|
||||
...Provider.Info.empty(Provider.ID.openai),
|
||||
package: Provider.aisdk("@ai-sdk/openai"),
|
||||
catalog.provider.update(Provider.ID.openai, (draft) => {
|
||||
draft.package = Provider.aisdk("@ai-sdk/openai")
|
||||
})
|
||||
catalog.provider.update(item.id, (draft) => {
|
||||
draft.package = item.package
|
||||
})
|
||||
catalog.model.update(item.id, Model.ID.make("gpt-5.5"), (model) => {
|
||||
catalog.model.update(Provider.ID.openai, Model.ID.make("gpt-5.5"), (model) => {
|
||||
model.limit = { context: 1_050_000, input: 922_000, output: 128_000 }
|
||||
model.cost = [
|
||||
{
|
||||
|
|
@ -105,19 +101,19 @@ describe("OpenAIPlugin", () => {
|
|||
},
|
||||
]
|
||||
})
|
||||
catalog.model.update(item.id, Model.ID.make("gpt-5.5-pro"), () => {})
|
||||
catalog.model.update(item.id, Model.ID.make("gpt-5.4"), (model) => {
|
||||
catalog.model.update(Provider.ID.openai, Model.ID.make("gpt-5.5-pro"), () => {})
|
||||
catalog.model.update(Provider.ID.openai, Model.ID.make("gpt-5.4"), (model) => {
|
||||
model.limit = { context: 1_050_000, input: 922_000, output: 64_000 }
|
||||
})
|
||||
catalog.model.update(item.id, Model.ID.make("gpt-5.4-pro"), (model) => {
|
||||
catalog.model.update(Provider.ID.openai, Model.ID.make("gpt-5.4-pro"), (model) => {
|
||||
model.modelID = Model.ID.make("gpt-5.4")
|
||||
model.body = { reasoning: { mode: "pro" } }
|
||||
})
|
||||
catalog.model.update(item.id, Model.ID.make("gpt-5.6"), () => {})
|
||||
catalog.model.update(item.id, Model.ID.make("gpt-5.6-sol"), (model) => {
|
||||
catalog.model.update(Provider.ID.openai, Model.ID.make("gpt-5.6"), () => {})
|
||||
catalog.model.update(Provider.ID.openai, Model.ID.make("gpt-5.6-sol"), (model) => {
|
||||
model.limit = { context: 1_050_000, input: 922_000, output: 128_000 }
|
||||
})
|
||||
catalog.model.update(item.id, Model.ID.make("gpt-4.1"), () => {})
|
||||
catalog.model.update(Provider.ID.openai, Model.ID.make("gpt-4.1"), () => {})
|
||||
})
|
||||
yield* credentials.create({
|
||||
integrationID: Integration.ID.make("openai"),
|
||||
|
|
@ -172,17 +168,13 @@ describe("OpenAIPlugin", () => {
|
|||
const catalog = yield* Catalog.Service
|
||||
const credentials = yield* Credential.Service
|
||||
yield* catalog.transform((catalog) => {
|
||||
const item = Provider.Info.make({
|
||||
...Provider.Info.empty(Provider.ID.openai),
|
||||
package: Provider.aisdk("@ai-sdk/openai"),
|
||||
catalog.provider.update(Provider.ID.openai, (draft) => {
|
||||
draft.package = Provider.aisdk("@ai-sdk/openai")
|
||||
})
|
||||
catalog.provider.update(item.id, (draft) => {
|
||||
draft.package = item.package
|
||||
})
|
||||
catalog.model.update(item.id, Model.ID.make("gpt-5.5"), (model) => {
|
||||
catalog.model.update(Provider.ID.openai, Model.ID.make("gpt-5.5"), (model) => {
|
||||
model.limit = { context: 1_050_000, input: 922_000, output: 128_000 }
|
||||
})
|
||||
catalog.model.update(item.id, Model.ID.make("gpt-4.1"), () => {})
|
||||
catalog.model.update(Provider.ID.openai, Model.ID.make("gpt-4.1"), () => {})
|
||||
})
|
||||
yield* credentials.create({
|
||||
integrationID: Integration.ID.make("openai"),
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { AISDK } from "@opencode-ai/core/aisdk"
|
||||
import { describe, expect, it as bun_it } from "bun:test"
|
||||
import { describe, expect, test } from "bun:test"
|
||||
import { Effect } from "effect"
|
||||
import { Model } from "@opencode-ai/core/model"
|
||||
import { Plugin } from "@opencode-ai/core/plugin"
|
||||
|
|
@ -14,7 +14,6 @@ const it = testEffect(PluginTestLayer)
|
|||
|
||||
const addPlugin = Effect.fn(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
const host = yield* PluginHost.make(plugin)
|
||||
yield* SnowflakeCortexPlugin.effect(host)
|
||||
})
|
||||
|
|
@ -53,7 +52,6 @@ describe("SnowflakeCortexPlugin", () => {
|
|||
|
||||
it.effect("ignores non-snowflake-cortex providers", () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
yield* addPlugin()
|
||||
const result = yield* aisdk.runSDK({
|
||||
|
|
@ -72,7 +70,6 @@ describe("SnowflakeCortexPlugin", () => {
|
|||
it.effect("creates SDK for snowflake-cortex using SNOWFLAKE_CORTEX_PAT env var", () =>
|
||||
withEnv({ SNOWFLAKE_CORTEX_PAT: "test-pat" }, () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
yield* addPlugin()
|
||||
const result = yield* aisdk.runSDK({
|
||||
|
|
@ -92,7 +89,6 @@ describe("SnowflakeCortexPlugin", () => {
|
|||
it.effect("falls back to options.apiKey when SNOWFLAKE_CORTEX_PAT env var is absent", () =>
|
||||
withEnv({ SNOWFLAKE_CORTEX_PAT: undefined }, () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
yield* addPlugin()
|
||||
const result = yield* aisdk.runSDK({
|
||||
|
|
@ -116,7 +112,6 @@ describe("SnowflakeCortexPlugin", () => {
|
|||
it.effect("uses SNOWFLAKE_CORTEX_TOKEN env var", () =>
|
||||
withEnv({ SNOWFLAKE_CORTEX_TOKEN: "oauth-token", SNOWFLAKE_CORTEX_PAT: undefined }, () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
yield* addPlugin()
|
||||
const result = yield* aisdk.runSDK({
|
||||
|
|
@ -136,7 +131,6 @@ describe("SnowflakeCortexPlugin", () => {
|
|||
it.effect("falls back to options.token when no Snowflake env token is set", () =>
|
||||
withEnv({ SNOWFLAKE_CORTEX_TOKEN: undefined, SNOWFLAKE_CORTEX_PAT: undefined }, () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
yield* addPlugin()
|
||||
const result = yield* aisdk.runSDK({
|
||||
|
|
@ -160,7 +154,6 @@ describe("SnowflakeCortexPlugin", () => {
|
|||
it.effect("sets includeUsage on the SDK options", () =>
|
||||
withEnv({ SNOWFLAKE_CORTEX_PAT: "test-pat" }, () =>
|
||||
Effect.gen(function* () {
|
||||
const plugin = yield* Plugin.Service
|
||||
const aisdk = yield* AISDK.Service
|
||||
yield* addPlugin()
|
||||
const result = yield* aisdk.runSDK({
|
||||
|
|
@ -181,7 +174,7 @@ describe("SnowflakeCortexPlugin", () => {
|
|||
type FetchLike = (url: string | URL | Request, init?: RequestInit) => Promise<Response>
|
||||
|
||||
describe("cortexFetch", () => {
|
||||
bun_it("rewrites max_tokens to max_completion_tokens", async () => {
|
||||
test("rewrites max_tokens to max_completion_tokens", async () => {
|
||||
const captured: RequestInit[] = []
|
||||
const upstream: FetchLike = async (_url, init) => {
|
||||
captured.push(init ?? {})
|
||||
|
|
@ -196,7 +189,7 @@ describe("cortexFetch", () => {
|
|||
expect(body.max_tokens).toBeUndefined()
|
||||
})
|
||||
|
||||
bun_it("preserves body when max_tokens is absent", async () => {
|
||||
test("preserves body when max_tokens is absent", async () => {
|
||||
const captured: RequestInit[] = []
|
||||
const upstream: FetchLike = async (_url, init) => {
|
||||
captured.push(init ?? {})
|
||||
|
|
@ -207,7 +200,7 @@ describe("cortexFetch", () => {
|
|||
expect(captured[0].body).toBe(original)
|
||||
})
|
||||
|
||||
bun_it("treats 400 'conversation complete' as a stop response", async () => {
|
||||
test("treats 400 'conversation complete' as a stop response", async () => {
|
||||
const upstream: FetchLike = async () =>
|
||||
new Response(JSON.stringify({ message: "Conversation complete" }), {
|
||||
status: 400,
|
||||
|
|
@ -219,7 +212,7 @@ describe("cortexFetch", () => {
|
|||
expect(data.choices[0].finish_reason).toBe("stop")
|
||||
})
|
||||
|
||||
bun_it("passes through other 400 errors unchanged", async () => {
|
||||
test("passes through other 400 errors unchanged", async () => {
|
||||
const upstream: FetchLike = async () =>
|
||||
new Response(JSON.stringify({ message: "Invalid model" }), {
|
||||
status: 400,
|
||||
|
|
@ -229,13 +222,13 @@ describe("cortexFetch", () => {
|
|||
expect(response.status).toBe(400)
|
||||
})
|
||||
|
||||
bun_it("passes through non-400 errors unchanged", async () => {
|
||||
test("passes through non-400 errors unchanged", async () => {
|
||||
const upstream: FetchLike = async () => new Response("Unauthorized", { status: 401 })
|
||||
const response = await cortexFetch(upstream)("https://test", {})
|
||||
expect(response.status).toBe(401)
|
||||
})
|
||||
|
||||
bun_it("handles invalid JSON body gracefully without throwing", async () => {
|
||||
test("handles invalid JSON body gracefully without throwing", async () => {
|
||||
const captured: RequestInit[] = []
|
||||
const upstream: FetchLike = async (_url, init) => {
|
||||
captured.push(init ?? {})
|
||||
|
|
@ -246,7 +239,7 @@ describe("cortexFetch", () => {
|
|||
expect(captured[0].body).toBe(invalidBody)
|
||||
})
|
||||
|
||||
bun_it("rewrites role:'' to role:'assistant' in streaming SSE chunks", async () => {
|
||||
test("rewrites role:'' to role:'assistant' in streaming SSE chunks", async () => {
|
||||
const chunk = `data: {"choices":[{"delta":{"role":"","content":"Hi"},"index":0}]}\n\n`
|
||||
const upstream: FetchLike = async () =>
|
||||
new Response(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue