Просмотр исходного кода

feat(provider): add NVIDIA endpoints origin header (#27394)

nv-kasikritc 3 месяцев назад
Родитель
Сommit
d34a0194ec

+ 1 - 0
packages/core/src/plugin/provider/nvidia.ts

@@ -10,6 +10,7 @@ export const NvidiaPlugin = PluginV2.define({
         if (evt.provider.id !== ProviderV2.ID.make("nvidia")) return
         evt.provider.options.headers["HTTP-Referer"] = "https://opencode.ai/"
         evt.provider.options.headers["X-Title"] = "opencode"
+        evt.provider.options.headers["X-BILLING-INVOKE-ORIGIN"] ??= "OpenCode"
       }),
     }
   }),

+ 53 - 1
packages/core/test/plugin/provider-nvidia.test.ts

@@ -15,7 +15,7 @@ describe("NvidiaPlugin", () => {
     ),
   )
 
-  it.effect("applies legacy referer headers only to nvidia", () =>
+  it.effect("applies NVIDIA tracking headers only to nvidia", () =>
     Effect.gen(function* () {
       const plugin = yield* PluginV2.Service
       yield* plugin.add(NvidiaPlugin)
@@ -34,8 +34,60 @@ describe("NvidiaPlugin", () => {
         Existing: "value",
         "HTTP-Referer": "https://opencode.ai/",
         "X-Title": "opencode",
+        "X-BILLING-INVOKE-ORIGIN": "OpenCode",
       })
       expect(ignored.provider.options.headers).toEqual({})
     }),
   )
+
+  it.effect("adds billing origin for custom NVIDIA endpoints", () =>
+    Effect.gen(function* () {
+      const plugin = yield* PluginV2.Service
+      yield* plugin.add(NvidiaPlugin)
+      const result = yield* plugin.trigger(
+        "provider.update",
+        {},
+        {
+          provider: provider("nvidia", {
+            endpoint: { type: "aisdk", package: "test-provider", url: "http://localhost:8000/v1" },
+            options: { headers: {}, body: {}, aisdk: { provider: {}, request: {} } },
+          }),
+          cancel: false,
+        },
+      )
+
+      expect(result.provider.options.headers).toEqual({
+        "HTTP-Referer": "https://opencode.ai/",
+        "X-Title": "opencode",
+        "X-BILLING-INVOKE-ORIGIN": "OpenCode",
+      })
+    }),
+  )
+
+  it.effect("preserves an explicit NVIDIA billing origin header", () =>
+    Effect.gen(function* () {
+      const plugin = yield* PluginV2.Service
+      yield* plugin.add(NvidiaPlugin)
+      const result = yield* plugin.trigger(
+        "provider.update",
+        {},
+        {
+          provider: provider("nvidia", {
+            options: {
+              headers: { "X-BILLING-INVOKE-ORIGIN": "CustomOrigin" },
+              body: {},
+              aisdk: { provider: { baseURL: "https://integrate.api.nvidia.com/v1" }, request: {} },
+            },
+          }),
+          cancel: false,
+        },
+      )
+
+      expect(result.provider.options.headers).toEqual({
+        "HTTP-Referer": "https://opencode.ai/",
+        "X-Title": "opencode",
+        "X-BILLING-INVOKE-ORIGIN": "CustomOrigin",
+      })
+    }),
+  )
 })

+ 3 - 2
packages/opencode/src/provider/provider.ts

@@ -427,13 +427,14 @@ function custom(dep: CustomDep): Record<string, CustomLoader> {
           },
         },
       }),
-    nvidia: () =>
+    nvidia: (provider) =>
       Effect.succeed({
-        autoload: false,
+        autoload: provider.source === "config",
         options: {
           headers: {
             "HTTP-Referer": "https://opencode.ai/",
             "X-Title": "opencode",
+            "X-BILLING-INVOKE-ORIGIN": "OpenCode",
           },
         },
       }),

+ 94 - 0
packages/opencode/test/provider/provider.test.ts

@@ -1868,6 +1868,100 @@ test("provider options are deeply merged", async () => {
   })
 })
 
+test("hosted nvidia provider adds billing origin header", async () => {
+  await using tmp = await tmpdir({
+    init: async (dir) => {
+      await Bun.write(
+        path.join(dir, "opencode.json"),
+        JSON.stringify({
+          $schema: "https://opencode.ai/config.json",
+          provider: {
+            nvidia: {
+              options: {
+                apiKey: "test-api-key",
+              },
+            },
+          },
+        }),
+      )
+    },
+  })
+  await WithInstance.provide({
+    directory: tmp.path,
+    fn: async () => {
+      const providers = await list()
+      expect(providers[ProviderID.make("nvidia")].options.headers).toEqual({
+        "HTTP-Referer": "https://opencode.ai/",
+        "X-Title": "opencode",
+        "X-BILLING-INVOKE-ORIGIN": "OpenCode",
+      })
+    },
+  })
+})
+
+test("custom nvidia baseURL adds billing origin header", async () => {
+  await using tmp = await tmpdir({
+    init: async (dir) => {
+      await Bun.write(
+        path.join(dir, "opencode.json"),
+        JSON.stringify({
+          $schema: "https://opencode.ai/config.json",
+          provider: {
+            nvidia: {
+              options: {
+                apiKey: "test-api-key",
+                baseURL: "http://localhost:8000/v1",
+              },
+            },
+          },
+        }),
+      )
+    },
+  })
+  await WithInstance.provide({
+    directory: tmp.path,
+    fn: async () => {
+      const providers = await list()
+      expect(providers[ProviderID.make("nvidia")].options.headers).toEqual({
+        "HTTP-Referer": "https://opencode.ai/",
+        "X-Title": "opencode",
+        "X-BILLING-INVOKE-ORIGIN": "OpenCode",
+      })
+    },
+  })
+})
+
+test("explicit nvidia billing origin header is preserved", async () => {
+  await using tmp = await tmpdir({
+    init: async (dir) => {
+      await Bun.write(
+        path.join(dir, "opencode.json"),
+        JSON.stringify({
+          $schema: "https://opencode.ai/config.json",
+          provider: {
+            nvidia: {
+              options: {
+                apiKey: "test-api-key",
+                baseURL: "http://localhost:8000/v1",
+                headers: {
+                  "X-BILLING-INVOKE-ORIGIN": "CustomOrigin",
+                },
+              },
+            },
+          },
+        }),
+      )
+    },
+  })
+  await WithInstance.provide({
+    directory: tmp.path,
+    fn: async () => {
+      const providers = await list()
+      expect(providers[ProviderID.make("nvidia")].options.headers["X-BILLING-INVOKE-ORIGIN"]).toBe("CustomOrigin")
+    },
+  })
+})
+
 test("custom model inherits npm package from models.dev provider config", async () => {
   await using tmp = await tmpdir({
     init: async (dir) => {