provider-deepinfra.test.ts 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  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 { DeepInfraPlugin } from "@opencode-ai/core/plugin/provider/deepinfra"
  8. import { ProviderV2 } from "@opencode-ai/core/provider"
  9. import { testEffect } from "../lib/effect"
  10. import { PluginTestLayer } from "./fixture"
  11. const it = testEffect(PluginTestLayer)
  12. const deepinfraOptions: Record<string, unknown>[] = []
  13. const deepinfraLanguageModels: string[] = []
  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* DeepInfraPlugin.effect(host)
  19. })
  20. void mock.module("@ai-sdk/deepinfra", () => ({
  21. createDeepInfra: (options: Record<string, unknown>) => {
  22. const captured = { ...options }
  23. deepinfraOptions.push(captured)
  24. return {
  25. languageModel: (modelID: string) => {
  26. deepinfraLanguageModels.push(modelID)
  27. return { modelID, provider: `${captured.name ?? "deepinfra"}.chat`, specificationVersion: "v3" }
  28. },
  29. }
  30. },
  31. }))
  32. function resetDeepInfraMock() {
  33. deepinfraOptions.length = 0
  34. deepinfraLanguageModels.length = 0
  35. }
  36. describe("DeepInfraPlugin", () => {
  37. it.effect("creates a DeepInfra SDK for @ai-sdk/deepinfra", () =>
  38. Effect.gen(function* () {
  39. resetDeepInfraMock()
  40. const plugin = yield* PluginV2.Service
  41. const aisdk = yield* AISDK.Service
  42. yield* addPlugin()
  43. const result = yield* aisdk.runSDK({
  44. model: ModelV2.Info.make({
  45. ...ModelV2.Info.empty(ProviderV2.ID.make("deepinfra"), ModelV2.ID.make("model")),
  46. api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "@ai-sdk/deepinfra" },
  47. }),
  48. package: "@ai-sdk/deepinfra",
  49. options: { name: "deepinfra" },
  50. })
  51. expect(result.sdk).toBeDefined()
  52. }),
  53. )
  54. it.effect("passes the model provider ID as the bundled DeepInfra SDK name", () =>
  55. Effect.gen(function* () {
  56. resetDeepInfraMock()
  57. const plugin = yield* PluginV2.Service
  58. const aisdk = yield* AISDK.Service
  59. yield* addPlugin()
  60. const result = yield* aisdk.runSDK({
  61. model: ModelV2.Info.make({
  62. ...ModelV2.Info.empty(ProviderV2.ID.make("custom-deepinfra"), ModelV2.ID.make("model")),
  63. api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "@ai-sdk/deepinfra" },
  64. }),
  65. package: "@ai-sdk/deepinfra",
  66. options: { name: "custom-deepinfra", apiKey: "test" },
  67. })
  68. expect(result.sdk.languageModel("model").provider).toBe("custom-deepinfra.chat")
  69. expect(deepinfraOptions).toEqual([{ name: "custom-deepinfra", apiKey: "test" }])
  70. }),
  71. )
  72. it.effect("uses the canonical provider ID as the bundled DeepInfra SDK name", () =>
  73. Effect.gen(function* () {
  74. resetDeepInfraMock()
  75. const plugin = yield* PluginV2.Service
  76. const aisdk = yield* AISDK.Service
  77. yield* addPlugin()
  78. const result = yield* aisdk.runSDK({
  79. model: ModelV2.Info.make({
  80. ...ModelV2.Info.empty(ProviderV2.ID.make("deepinfra"), ModelV2.ID.make("model")),
  81. api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "@ai-sdk/deepinfra" },
  82. }),
  83. package: "@ai-sdk/deepinfra",
  84. options: { name: "deepinfra", apiKey: "test" },
  85. })
  86. expect(result.sdk.languageModel("model").provider).toBe("deepinfra.chat")
  87. expect(deepinfraOptions).toEqual([{ name: "deepinfra", apiKey: "test" }])
  88. }),
  89. )
  90. it.effect("matches only the exact bundled DeepInfra package", () =>
  91. Effect.gen(function* () {
  92. resetDeepInfraMock()
  93. const plugin = yield* PluginV2.Service
  94. const aisdk = yield* AISDK.Service
  95. yield* addPlugin()
  96. const packages = [
  97. "unmatched-package",
  98. "@ai-sdk/deepinfra-compatible",
  99. "file:///tmp/@ai-sdk/deepinfra-provider.js",
  100. ]
  101. yield* Effect.forEach(packages, (item) =>
  102. Effect.gen(function* () {
  103. const ignored = yield* aisdk.runSDK({
  104. model: ModelV2.Info.make({
  105. ...ModelV2.Info.empty(ProviderV2.ID.make("deepinfra"), ModelV2.ID.make("model")),
  106. api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "@ai-sdk/deepinfra" },
  107. }),
  108. package: item,
  109. options: { name: "deepinfra" },
  110. })
  111. expect(ignored.sdk).toBeUndefined()
  112. }),
  113. )
  114. const result = yield* aisdk.runSDK({
  115. model: ModelV2.Info.make({
  116. ...ModelV2.Info.empty(ProviderV2.ID.make("deepinfra"), ModelV2.ID.make("model")),
  117. api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "@ai-sdk/deepinfra" },
  118. }),
  119. package: "@ai-sdk/deepinfra",
  120. options: { name: "deepinfra" },
  121. })
  122. expect(result.sdk).toBeDefined()
  123. expect(deepinfraOptions).toEqual([{ name: "deepinfra" }])
  124. }),
  125. )
  126. it.effect("uses the default languageModel selection for DeepInfra models", () =>
  127. Effect.gen(function* () {
  128. resetDeepInfraMock()
  129. const plugin = yield* PluginV2.Service
  130. const aisdk = yield* AISDK.Service
  131. yield* addPlugin()
  132. const sdkEvent = yield* aisdk.runSDK({
  133. model: ModelV2.Info.make({
  134. ...ModelV2.Info.empty(ProviderV2.ID.make("deepinfra"), ModelV2.ID.make("meta-llama/Llama-3.3-70B-Instruct")),
  135. api: {
  136. id: ModelV2.ID.make("meta-llama/Llama-3.3-70B-Instruct"),
  137. type: "aisdk",
  138. package: "@ai-sdk/deepinfra",
  139. },
  140. }),
  141. package: "@ai-sdk/deepinfra",
  142. options: { name: "deepinfra" },
  143. })
  144. const result = yield* aisdk.runLanguage({ model: sdkEvent.model, sdk: sdkEvent.sdk, options: sdkEvent.options })
  145. const language = result.language ?? result.sdk.languageModel(result.model.api.id)
  146. expect(language.provider).toBe("deepinfra.chat")
  147. expect(deepinfraLanguageModels).toEqual(["meta-llama/Llama-3.3-70B-Instruct"])
  148. }),
  149. )
  150. })