From d34a0194ecc9e546ba14740aaf96cf3386d6a71d Mon Sep 17 00:00:00 2001 From: nv-kasikritc Date: Thu, 14 May 2026 15:21:58 -0700 Subject: [PATCH] feat(provider): add NVIDIA endpoints origin header (#27394) --- packages/core/src/plugin/provider/nvidia.ts | 1 + .../core/test/plugin/provider-nvidia.test.ts | 54 ++++++++++- packages/opencode/src/provider/provider.ts | 5 +- .../opencode/test/provider/provider.test.ts | 94 +++++++++++++++++++ 4 files changed, 151 insertions(+), 3 deletions(-) diff --git a/packages/core/src/plugin/provider/nvidia.ts b/packages/core/src/plugin/provider/nvidia.ts index b227e5cef3..49ef6af0f6 100644 --- a/packages/core/src/plugin/provider/nvidia.ts +++ b/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" }), } }), diff --git a/packages/core/test/plugin/provider-nvidia.test.ts b/packages/core/test/plugin/provider-nvidia.test.ts index 0e06356cd5..26e7db0bfb 100644 --- a/packages/core/test/plugin/provider-nvidia.test.ts +++ b/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", + }) + }), + ) }) diff --git a/packages/opencode/src/provider/provider.ts b/packages/opencode/src/provider/provider.ts index 8f8a6fe8f3..063e2800d1 100644 --- a/packages/opencode/src/provider/provider.ts +++ b/packages/opencode/src/provider/provider.ts @@ -427,13 +427,14 @@ function custom(dep: CustomDep): Record { }, }, }), - 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", }, }, }), diff --git a/packages/opencode/test/provider/provider.test.ts b/packages/opencode/test/provider/provider.test.ts index 18b0937efd..1c6a8b3377 100644 --- a/packages/opencode/test/provider/provider.test.ts +++ b/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) => {