provider-gateway.test.ts 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. import { AISDK } from "@opencode-ai/core/aisdk"
  2. import { describe, expect, mock } from "bun:test"
  3. import { Effect } from "effect"
  4. import { ModelV2 } from "@opencode-ai/core/model"
  5. import { PluginV2 } from "@opencode-ai/core/plugin"
  6. import { PluginHost } from "@opencode-ai/core/plugin/host"
  7. import { GatewayPlugin } from "@opencode-ai/core/plugin/provider/gateway"
  8. import { ProviderV2 } from "@opencode-ai/core/provider"
  9. import { testEffect } from "../lib/effect"
  10. import { PluginTestLayer } from "./fixture"
  11. const gatewayCalls: Record<string, unknown>[] = []
  12. const vercelGatewayModels = ["anthropic/claude-sonnet-4", "openai/gpt-5", "google/gemini-2.5-pro"]
  13. const it = testEffect(PluginTestLayer)
  14. const addPlugin = Effect.fn(function* () {
  15. const plugin = yield* PluginV2.Service
  16. const aisdk = yield* AISDK.Service
  17. const host = yield* PluginHost.make(plugin)
  18. yield* GatewayPlugin.effect(host)
  19. })
  20. mock.module("@ai-sdk/gateway", () => ({
  21. createGateway(options: Record<string, unknown>) {
  22. gatewayCalls.push({ ...options })
  23. return {
  24. languageModel(modelID: string) {
  25. return {
  26. modelId: modelID,
  27. provider: options.name,
  28. specificationVersion: "v3",
  29. }
  30. },
  31. }
  32. },
  33. }))
  34. describe("GatewayPlugin", () => {
  35. it.effect("creates a Gateway SDK for @ai-sdk/gateway", () =>
  36. Effect.gen(function* () {
  37. gatewayCalls.length = 0
  38. const plugin = yield* PluginV2.Service
  39. const aisdk = yield* AISDK.Service
  40. yield* addPlugin()
  41. const result = yield* aisdk.runSDK({
  42. model: ModelV2.Info.make({
  43. ...ModelV2.Info.empty(ProviderV2.ID.make("gateway"), ModelV2.ID.make("model")),
  44. api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" },
  45. }),
  46. package: "@ai-sdk/gateway",
  47. options: { name: "gateway" },
  48. })
  49. expect(result.sdk).toBeDefined()
  50. expect(gatewayCalls).toHaveLength(1)
  51. }),
  52. )
  53. it.effect("passes the model providerID as the Gateway SDK name", () =>
  54. Effect.gen(function* () {
  55. gatewayCalls.length = 0
  56. const plugin = yield* PluginV2.Service
  57. const aisdk = yield* AISDK.Service
  58. yield* addPlugin()
  59. const result = yield* aisdk.runSDK({
  60. model: ModelV2.Info.make({
  61. ...ModelV2.Info.empty(ProviderV2.ID.make("vercel"), ModelV2.ID.make("anthropic/claude-sonnet-4")),
  62. api: {
  63. id: ModelV2.ID.make("anthropic/claude-sonnet-4"),
  64. type: "aisdk",
  65. package: "test-provider",
  66. },
  67. }),
  68. package: "@ai-sdk/gateway",
  69. options: { name: "vercel", apiKey: "test-key" },
  70. })
  71. expect(gatewayCalls).toEqual([{ name: "vercel", apiKey: "test-key" }])
  72. expect(result.sdk.languageModel("anthropic/claude-sonnet-4").provider).toBe("vercel")
  73. }),
  74. )
  75. it.effect("matches Vercel AI Gateway models by their @ai-sdk/gateway package", () =>
  76. Effect.gen(function* () {
  77. gatewayCalls.length = 0
  78. const plugin = yield* PluginV2.Service
  79. const aisdk = yield* AISDK.Service
  80. yield* addPlugin()
  81. for (const modelID of vercelGatewayModels) {
  82. const ignored = yield* aisdk.runSDK({
  83. model: ModelV2.Info.make({
  84. ...ModelV2.Info.empty(ProviderV2.ID.make("vercel"), ModelV2.ID.make(modelID)),
  85. api: { id: ModelV2.ID.make(modelID), type: "aisdk", package: "test-provider" },
  86. }),
  87. package: "@ai-sdk/vercel",
  88. options: { name: "vercel" },
  89. })
  90. expect(ignored.sdk).toBeUndefined()
  91. const result = yield* aisdk.runSDK({
  92. model: ModelV2.Info.make({
  93. ...ModelV2.Info.empty(ProviderV2.ID.make("vercel"), ModelV2.ID.make(modelID)),
  94. api: { id: ModelV2.ID.make(modelID), type: "aisdk", package: "test-provider" },
  95. }),
  96. package: "@ai-sdk/gateway",
  97. options: { name: "vercel" },
  98. })
  99. expect(result.sdk).toBeDefined()
  100. }
  101. expect(gatewayCalls).toHaveLength(3)
  102. }),
  103. )
  104. })