File size: 6,181 Bytes
3e05655
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
import { AISDK } from "@opencode-ai/core/aisdk"
import { describe, expect, mock } from "bun:test"
import { Effect } from "effect"
import { ModelV2 } from "@opencode-ai/core/model"
import { PluginV2 } from "@opencode-ai/core/plugin"
import { PluginHost } from "@opencode-ai/core/plugin/host"
import { DeepInfraPlugin } from "@opencode-ai/core/plugin/provider/deepinfra"
import { ProviderV2 } from "@opencode-ai/core/provider"
import { testEffect } from "../lib/effect"
import { PluginTestLayer } from "./fixture"

const it = testEffect(PluginTestLayer)
const deepinfraOptions: Record<string, unknown>[] = []
const deepinfraLanguageModels: string[] = []

const addPlugin = Effect.fn(function* () {
  const plugin = yield* PluginV2.Service
  const aisdk = yield* AISDK.Service
  const host = yield* PluginHost.make(plugin)
  yield* DeepInfraPlugin.effect(host)
})

void mock.module("@ai-sdk/deepinfra", () => ({
  createDeepInfra: (options: Record<string, unknown>) => {
    const captured = { ...options }
    deepinfraOptions.push(captured)
    return {
      languageModel: (modelID: string) => {
        deepinfraLanguageModels.push(modelID)
        return { modelID, provider: `${captured.name ?? "deepinfra"}.chat`, specificationVersion: "v3" }
      },
    }
  },
}))

function resetDeepInfraMock() {
  deepinfraOptions.length = 0
  deepinfraLanguageModels.length = 0
}

describe("DeepInfraPlugin", () => {
  it.effect("creates a DeepInfra SDK for @ai-sdk/deepinfra", () =>
    Effect.gen(function* () {
      resetDeepInfraMock()
      const plugin = yield* PluginV2.Service
      const aisdk = yield* AISDK.Service
      yield* addPlugin()
      const result = yield* aisdk.runSDK({
        model: ModelV2.Info.make({
          ...ModelV2.Info.empty(ProviderV2.ID.make("deepinfra"), ModelV2.ID.make("model")),
          api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "@ai-sdk/deepinfra" },
        }),
        package: "@ai-sdk/deepinfra",
        options: { name: "deepinfra" },
      })
      expect(result.sdk).toBeDefined()
    }),
  )

  it.effect("passes the model provider ID as the bundled DeepInfra SDK name", () =>
    Effect.gen(function* () {
      resetDeepInfraMock()
      const plugin = yield* PluginV2.Service
      const aisdk = yield* AISDK.Service
      yield* addPlugin()
      const result = yield* aisdk.runSDK({
        model: ModelV2.Info.make({
          ...ModelV2.Info.empty(ProviderV2.ID.make("custom-deepinfra"), ModelV2.ID.make("model")),
          api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "@ai-sdk/deepinfra" },
        }),
        package: "@ai-sdk/deepinfra",
        options: { name: "custom-deepinfra", apiKey: "test" },
      })
      expect(result.sdk.languageModel("model").provider).toBe("custom-deepinfra.chat")
      expect(deepinfraOptions).toEqual([{ name: "custom-deepinfra", apiKey: "test" }])
    }),
  )

  it.effect("uses the canonical provider ID as the bundled DeepInfra SDK name", () =>
    Effect.gen(function* () {
      resetDeepInfraMock()
      const plugin = yield* PluginV2.Service
      const aisdk = yield* AISDK.Service
      yield* addPlugin()
      const result = yield* aisdk.runSDK({
        model: ModelV2.Info.make({
          ...ModelV2.Info.empty(ProviderV2.ID.make("deepinfra"), ModelV2.ID.make("model")),
          api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "@ai-sdk/deepinfra" },
        }),
        package: "@ai-sdk/deepinfra",
        options: { name: "deepinfra", apiKey: "test" },
      })
      expect(result.sdk.languageModel("model").provider).toBe("deepinfra.chat")
      expect(deepinfraOptions).toEqual([{ name: "deepinfra", apiKey: "test" }])
    }),
  )

  it.effect("matches only the exact bundled DeepInfra package", () =>
    Effect.gen(function* () {
      resetDeepInfraMock()
      const plugin = yield* PluginV2.Service
      const aisdk = yield* AISDK.Service
      yield* addPlugin()
      const packages = [
        "unmatched-package",
        "@ai-sdk/deepinfra-compatible",
        "file:///tmp/@ai-sdk/deepinfra-provider.js",
      ]
      yield* Effect.forEach(packages, (item) =>
        Effect.gen(function* () {
          const ignored = yield* aisdk.runSDK({
            model: ModelV2.Info.make({
              ...ModelV2.Info.empty(ProviderV2.ID.make("deepinfra"), ModelV2.ID.make("model")),
              api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "@ai-sdk/deepinfra" },
            }),
            package: item,
            options: { name: "deepinfra" },
          })
          expect(ignored.sdk).toBeUndefined()
        }),
      )
      const result = yield* aisdk.runSDK({
        model: ModelV2.Info.make({
          ...ModelV2.Info.empty(ProviderV2.ID.make("deepinfra"), ModelV2.ID.make("model")),
          api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "@ai-sdk/deepinfra" },
        }),
        package: "@ai-sdk/deepinfra",
        options: { name: "deepinfra" },
      })
      expect(result.sdk).toBeDefined()
      expect(deepinfraOptions).toEqual([{ name: "deepinfra" }])
    }),
  )

  it.effect("uses the default languageModel selection for DeepInfra models", () =>
    Effect.gen(function* () {
      resetDeepInfraMock()
      const plugin = yield* PluginV2.Service
      const aisdk = yield* AISDK.Service
      yield* addPlugin()
      const sdkEvent = yield* aisdk.runSDK({
        model: ModelV2.Info.make({
          ...ModelV2.Info.empty(ProviderV2.ID.make("deepinfra"), ModelV2.ID.make("meta-llama/Llama-3.3-70B-Instruct")),
          api: {
            id: ModelV2.ID.make("meta-llama/Llama-3.3-70B-Instruct"),
            type: "aisdk",
            package: "@ai-sdk/deepinfra",
          },
        }),
        package: "@ai-sdk/deepinfra",
        options: { name: "deepinfra" },
      })
      const result = yield* aisdk.runLanguage({ model: sdkEvent.model, sdk: sdkEvent.sdk, options: sdkEvent.options })
      const language = result.language ?? result.sdk.languageModel(result.model.api.id)
      expect(language.provider).toBe("deepinfra.chat")
      expect(deepinfraLanguageModels).toEqual(["meta-llama/Llama-3.3-70B-Instruct"])
    }),
  )
})