provider-gateway.test.ts 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import { describe, expect, mock } from "bun:test"
  2. import { Effect } from "effect"
  3. import { PluginV2 } from "@opencode-ai/core/plugin"
  4. import { GatewayPlugin } from "@opencode-ai/core/plugin/provider/gateway"
  5. import { it, model } from "./provider-helper"
  6. const gatewayCalls: Record<string, unknown>[] = []
  7. const vercelGatewayModels = ["anthropic/claude-sonnet-4", "openai/gpt-5", "google/gemini-2.5-pro"]
  8. mock.module("@ai-sdk/gateway", () => ({
  9. createGateway(options: Record<string, unknown>) {
  10. gatewayCalls.push({ ...options })
  11. return {
  12. languageModel(modelID: string) {
  13. return {
  14. modelId: modelID,
  15. provider: options.name,
  16. specificationVersion: "v3",
  17. }
  18. },
  19. }
  20. },
  21. }))
  22. describe("GatewayPlugin", () => {
  23. it.effect("creates a Gateway SDK for @ai-sdk/gateway", () =>
  24. Effect.gen(function* () {
  25. gatewayCalls.length = 0
  26. const plugin = yield* PluginV2.Service
  27. yield* plugin.add(GatewayPlugin)
  28. const result = yield* plugin.trigger(
  29. "aisdk.sdk",
  30. { model: model("gateway", "model"), package: "@ai-sdk/gateway", options: { name: "gateway" } },
  31. {},
  32. )
  33. expect(result.sdk).toBeDefined()
  34. expect(gatewayCalls).toHaveLength(1)
  35. }),
  36. )
  37. it.effect("passes the model providerID as the Gateway SDK name", () =>
  38. Effect.gen(function* () {
  39. gatewayCalls.length = 0
  40. const plugin = yield* PluginV2.Service
  41. yield* plugin.add(GatewayPlugin)
  42. const result = yield* plugin.trigger(
  43. "aisdk.sdk",
  44. {
  45. model: model("vercel", "anthropic/claude-sonnet-4"),
  46. package: "@ai-sdk/gateway",
  47. options: { name: "vercel", apiKey: "test-key" },
  48. },
  49. {},
  50. )
  51. expect(gatewayCalls).toEqual([{ name: "vercel", apiKey: "test-key" }])
  52. expect(result.sdk.languageModel("anthropic/claude-sonnet-4").provider).toBe("vercel")
  53. }),
  54. )
  55. it.effect("matches Vercel AI Gateway models by their @ai-sdk/gateway package", () =>
  56. Effect.gen(function* () {
  57. gatewayCalls.length = 0
  58. const plugin = yield* PluginV2.Service
  59. yield* plugin.add(GatewayPlugin)
  60. for (const modelID of vercelGatewayModels) {
  61. const ignored = yield* plugin.trigger(
  62. "aisdk.sdk",
  63. { model: model("vercel", modelID), package: "@ai-sdk/vercel", options: { name: "vercel" } },
  64. {},
  65. )
  66. expect(ignored.sdk).toBeUndefined()
  67. const result = yield* plugin.trigger(
  68. "aisdk.sdk",
  69. { model: model("vercel", modelID), package: "@ai-sdk/gateway", options: { name: "vercel" } },
  70. {},
  71. )
  72. expect(result.sdk).toBeDefined()
  73. }
  74. expect(gatewayCalls).toHaveLength(3)
  75. }),
  76. )
  77. })