provider-openrouter.test.ts 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. import { describe, expect } from "bun:test"
  2. import { Effect } from "effect"
  3. import { Catalog } from "@opencode-ai/core/catalog"
  4. import { ModelV2 } from "@opencode-ai/core/model"
  5. import { PluginV2 } from "@opencode-ai/core/plugin"
  6. import { ProviderPlugins } from "@opencode-ai/core/plugin/provider"
  7. import { OpenRouterPlugin } from "@opencode-ai/core/plugin/provider/openrouter"
  8. import { ProviderV2 } from "@opencode-ai/core/provider"
  9. import { expectPluginRegistered, it, model, provider } from "./provider-helper"
  10. describe("OpenRouterPlugin", () => {
  11. it.effect("is registered so legacy OpenRouter behavior can be applied", () =>
  12. Effect.sync(() =>
  13. expectPluginRegistered(
  14. ProviderPlugins.map((item) => item.id),
  15. "openrouter",
  16. ),
  17. ),
  18. )
  19. it.effect("applies legacy referer headers only to openrouter", () =>
  20. Effect.gen(function* () {
  21. const plugin = yield* PluginV2.Service
  22. const catalog = yield* Catalog.Service
  23. yield* plugin.add(OpenRouterPlugin)
  24. const transform = yield* catalog.transform()
  25. yield* transform((catalog) => {
  26. const openrouter = provider("openrouter", {
  27. api: { type: "aisdk", package: "@openrouter/ai-sdk-provider" },
  28. request: { headers: { Existing: "value" }, body: {} },
  29. })
  30. catalog.provider.update(openrouter.id, (item) => {
  31. item.api = openrouter.api
  32. item.request = openrouter.request
  33. })
  34. catalog.provider.update(ProviderV2.ID.make("nvidia"), () => {})
  35. })
  36. expect((yield* catalog.provider.get(ProviderV2.ID.make("openrouter"))).request.headers).toEqual({
  37. Existing: "value",
  38. "HTTP-Referer": "https://opencode.ai/",
  39. "X-Title": "opencode",
  40. })
  41. expect((yield* catalog.provider.get(ProviderV2.ID.make("nvidia"))).request.headers).toEqual({})
  42. }),
  43. )
  44. it.effect("creates an SDK only for the OpenRouter package", () =>
  45. Effect.gen(function* () {
  46. const plugin = yield* PluginV2.Service
  47. yield* plugin.add(OpenRouterPlugin)
  48. const ignored = yield* plugin.trigger(
  49. "aisdk.sdk",
  50. {
  51. model: model("openrouter", "openai/gpt-5"),
  52. package: "@ai-sdk/openai-compatible",
  53. options: { name: "openrouter" },
  54. },
  55. {},
  56. )
  57. expect(ignored.sdk).toBeUndefined()
  58. const result = yield* plugin.trigger(
  59. "aisdk.sdk",
  60. { model: model("custom", "openai/gpt-5"), package: "@openrouter/ai-sdk-provider", options: { name: "custom" } },
  61. {},
  62. )
  63. expect(result.sdk).toBeDefined()
  64. }),
  65. )
  66. it.effect("filters OpenRouter's gpt-5 chat alias", () =>
  67. Effect.gen(function* () {
  68. const plugin = yield* PluginV2.Service
  69. const catalog = yield* Catalog.Service
  70. yield* plugin.add(OpenRouterPlugin)
  71. const transform = yield* catalog.transform()
  72. yield* transform((catalog) => {
  73. const openrouter = provider("openrouter", {
  74. api: { type: "aisdk", package: "@openrouter/ai-sdk-provider" },
  75. })
  76. catalog.provider.update(openrouter.id, (item) => {
  77. item.api = openrouter.api
  78. })
  79. catalog.provider.update(ProviderV2.ID.openai, () => {})
  80. for (const item of [
  81. model("openrouter", "openai/gpt-5-chat"),
  82. model("openrouter", "openai/gpt-5"),
  83. model("openai", "openai/gpt-5-chat"),
  84. ]) {
  85. catalog.model.update(item.providerID, item.id, () => {})
  86. }
  87. })
  88. expect(
  89. (yield* catalog.model.get(ProviderV2.ID.make("openrouter"), ModelV2.ID.make("openai/gpt-5-chat"))).enabled,
  90. ).toBe(false)
  91. expect(
  92. (yield* catalog.model.get(ProviderV2.ID.make("openrouter"), ModelV2.ID.make("openai/gpt-5"))).enabled,
  93. ).toBe(true)
  94. expect((yield* catalog.model.get(ProviderV2.ID.openai, ModelV2.ID.make("openai/gpt-5-chat"))).enabled).toBe(true)
  95. }),
  96. )
  97. it.effect("does not disable gpt-5-chat-latest for non-OpenRouter providers", () =>
  98. Effect.gen(function* () {
  99. const plugin = yield* PluginV2.Service
  100. const catalog = yield* Catalog.Service
  101. yield* plugin.add(OpenRouterPlugin)
  102. const transform = yield* catalog.transform()
  103. yield* transform((catalog) => {
  104. catalog.provider.update(ProviderV2.ID.make("custom-openrouter"), () => {})
  105. catalog.model.update(ProviderV2.ID.make("custom-openrouter"), ModelV2.ID.make("gpt-5-chat-latest"), () => {})
  106. })
  107. expect(
  108. (yield* catalog.model.get(ProviderV2.ID.make("custom-openrouter"), ModelV2.ID.make("gpt-5-chat-latest")))
  109. .enabled,
  110. ).toBe(true)
  111. }),
  112. )
  113. })