Skip to content

Commit 38f11a0

Browse files
authored
feat(nvidia): tag NIM request origin (#81524)
1 parent cf19441 commit 38f11a0

4 files changed

Lines changed: 163 additions & 4 deletions

File tree

extensions/nvidia/openclaw.plugin.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@
55
},
66
"enabledByDefault": true,
77
"providers": ["nvidia"],
8+
"providerEndpoints": [
9+
{
10+
"endpointClass": "nvidia-native",
11+
"hosts": ["integrate.api.nvidia.com"],
12+
"baseUrls": ["https://integrate.api.nvidia.com/v1"]
13+
}
14+
],
815
"modelIdNormalization": {
916
"providers": {
1017
"nvidia": {

src/agents/provider-attribution.test.ts

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ const providerEndpointPlugins = vi.hoisted(() => [
5555
endpointClass: "xai-native",
5656
hosts: ["api.x.ai"],
5757
},
58+
{
59+
endpointClass: "nvidia-native",
60+
hosts: ["integrate.api.nvidia.com"],
61+
baseUrls: ["https://integrate.api.nvidia.com/v1"],
62+
},
5863
],
5964
providerRequest: {
6065
providers: {
@@ -68,6 +73,7 @@ const providerEndpointPlugins = vi.hoisted(() => [
6873
kimi: { family: "moonshot", compatibilityFamily: "moonshot" },
6974
mistral: { family: "mistral" },
7075
moonshot: { family: "moonshot", compatibilityFamily: "moonshot" },
76+
nvidia: { family: "nvidia" },
7177
openrouter: { family: "openrouter" },
7278
qwen: { family: "modelstudio" },
7379
together: { family: "together" },
@@ -132,6 +138,29 @@ describe("provider attribution", () => {
132138
});
133139
});
134140

141+
it("returns a documented NVIDIA attribution policy", () => {
142+
const policy = resolveProviderAttributionPolicy("nvidia", {
143+
OPENCLAW_VERSION: "2026.3.22",
144+
});
145+
146+
expect(policy).toEqual({
147+
provider: "nvidia",
148+
enabledByDefault: true,
149+
verification: "vendor-documented",
150+
hook: "request-headers",
151+
reviewNote:
152+
"NVIDIA NIM billing invoke-origin attribution header. Applied only on verified NVIDIA routes.",
153+
product: "OpenClaw",
154+
version: "2026.3.22",
155+
headers: {
156+
"X-BILLING-INVOKE-ORIGIN": "OpenClaw",
157+
},
158+
});
159+
expect(resolveProviderAttributionHeaders("NVIDIA", { OPENCLAW_VERSION: "2026.3.22" })).toEqual({
160+
"X-BILLING-INVOKE-ORIGIN": "OpenClaw",
161+
});
162+
});
163+
135164
it("normalizes aliases when resolving provider headers", () => {
136165
expect(
137166
resolveProviderAttributionHeaders("OpenRouter", {
@@ -221,6 +250,7 @@ describe("provider attribution", () => {
221250
]),
222251
).toEqual([
223252
["openrouter", true, "vendor-documented", "request-headers"],
253+
["nvidia", true, "vendor-documented", "request-headers"],
224254
["openai", true, "vendor-hidden-api-spec", "request-headers"],
225255
["openai-codex", true, "vendor-hidden-api-spec", "request-headers"],
226256
["xai", true, "vendor-hidden-api-spec", "request-headers"],
@@ -446,6 +476,10 @@ describe("provider attribution", () => {
446476
endpointClass: "cerebras-native",
447477
hostname: "api.cerebras.ai",
448478
});
479+
expectRecordFields(resolveProviderEndpoint("https://integrate.api.nvidia.com/v1"), {
480+
endpointClass: "nvidia-native",
481+
hostname: "integrate.api.nvidia.com",
482+
});
449483
expectRecordFields(resolveProviderEndpoint("https://opencode.ai/api"), {
450484
endpointClass: "opencode-native",
451485
hostname: "opencode.ai",
@@ -511,6 +545,46 @@ describe("provider attribution", () => {
511545
).toBeUndefined();
512546
});
513547

548+
it("gates documented NVIDIA attribution to official NVIDIA NIM endpoints", () => {
549+
expectRecordFields(
550+
resolveProviderRequestPolicy({
551+
provider: "nvidia",
552+
api: "openai-completions",
553+
baseUrl: "https://integrate.api.nvidia.com/v1",
554+
transport: "stream",
555+
capability: "llm",
556+
}),
557+
{
558+
endpointClass: "nvidia-native",
559+
knownProviderFamily: "nvidia",
560+
attributionProvider: "nvidia",
561+
allowsHiddenAttribution: false,
562+
},
563+
);
564+
565+
expect(
566+
resolveProviderRequestAttributionHeaders({
567+
provider: "custom-nim",
568+
api: "openai-completions",
569+
baseUrl: "https://integrate.api.nvidia.com/v1",
570+
transport: "stream",
571+
capability: "llm",
572+
}),
573+
).toEqual({
574+
"X-BILLING-INVOKE-ORIGIN": "OpenClaw",
575+
});
576+
577+
expect(
578+
resolveProviderRequestAttributionHeaders({
579+
provider: "nvidia",
580+
api: "openai-completions",
581+
baseUrl: "https://proxy.example.com/v1",
582+
transport: "stream",
583+
capability: "llm",
584+
}),
585+
).toBeUndefined();
586+
});
587+
514588
it("summarizes proxy-like, local, invalid, default, and native routing compactly", () => {
515589
expect(
516590
describeProviderRequestRoutingSummary({
@@ -580,6 +654,18 @@ describe("provider attribution", () => {
580654
capability: "llm",
581655
}),
582656
).toBe("provider=groq api=openai-completions endpoint=groq-native route=native policy=none");
657+
658+
expect(
659+
describeProviderRequestRoutingSummary({
660+
provider: "nvidia",
661+
api: "openai-completions",
662+
baseUrl: "https://integrate.api.nvidia.com/v1",
663+
transport: "stream",
664+
capability: "llm",
665+
}),
666+
).toBe(
667+
"provider=nvidia api=openai-completions endpoint=nvidia-native route=native policy=documented",
668+
);
583669
});
584670

585671
it("models other provider families without enabling hidden attribution", () => {

src/agents/provider-attribution.ts

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ export type ProviderEndpointClass =
4848
| "mistral-public"
4949
| "moonshot-native"
5050
| "modelstudio-native"
51+
| "nvidia-native"
5152
| "openai-public"
5253
| "openai-codex"
5354
| "opencode-native"
@@ -144,6 +145,7 @@ const MANIFEST_PROVIDER_ENDPOINT_CLASSES = new Set<ProviderEndpointClass>([
144145
"mistral-public",
145146
"moonshot-native",
146147
"modelstudio-native",
148+
"nvidia-native",
147149
"openai-public",
148150
"openai-codex",
149151
"opencode-native",
@@ -482,6 +484,23 @@ function buildOpenRouterAttributionPolicy(
482484
};
483485
}
484486

487+
function buildNvidiaAttributionPolicy(
488+
env: RuntimeVersionEnv = process.env as RuntimeVersionEnv,
489+
): ProviderAttributionPolicy {
490+
return {
491+
provider: "nvidia",
492+
enabledByDefault: true,
493+
verification: "vendor-documented",
494+
hook: "request-headers",
495+
reviewNote:
496+
"NVIDIA NIM billing invoke-origin attribution header. Applied only on verified NVIDIA routes.",
497+
...resolveProviderAttributionIdentity(env),
498+
headers: {
499+
"X-BILLING-INVOKE-ORIGIN": OPENCLAW_ATTRIBUTION_PRODUCT,
500+
},
501+
};
502+
}
503+
485504
function buildOpenAIAttributionPolicy(
486505
env: RuntimeVersionEnv = process.env as RuntimeVersionEnv,
487506
): ProviderAttributionPolicy {
@@ -563,6 +582,7 @@ export function listProviderAttributionPolicies(
563582
): ProviderAttributionPolicy[] {
564583
return [
565584
buildOpenRouterAttributionPolicy(env),
585+
buildNvidiaAttributionPolicy(env),
566586
buildOpenAIAttributionPolicy(env),
567587
buildOpenAICodexAttributionPolicy(env),
568588
buildXaiAttributionPolicy(env),
@@ -655,21 +675,28 @@ export function resolveProviderRequestPolicy(
655675
attributionProvider = "xai";
656676
}
657677
}
678+
if (!attributionProvider && endpointClass === "nvidia-native") {
679+
attributionProvider = "nvidia";
680+
}
658681

659-
const attributionHeaders = attributionProvider
660-
? resolveProviderAttributionHeaders(attributionProvider, env)
682+
const attributionPolicy = attributionProvider
683+
? resolveProviderAttributionPolicy(attributionProvider, env)
684+
: undefined;
685+
const attributionHeaders = attributionPolicy?.enabledByDefault
686+
? attributionPolicy.headers
661687
: undefined;
662688

663689
return {
664690
provider: provider || undefined,
665-
policy,
691+
policy: attributionPolicy ?? policy,
666692
endpointClass,
667693
usesConfiguredBaseUrl,
668694
knownProviderFamily: resolveKnownProviderFamily(provider || undefined),
669695
attributionProvider,
670696
attributionHeaders,
671697
allowsHiddenAttribution:
672-
attributionProvider !== undefined && policy?.verification === "vendor-hidden-api-spec",
698+
attributionProvider !== undefined &&
699+
attributionPolicy?.verification === "vendor-hidden-api-spec",
673700
usesKnownNativeOpenAIEndpoint,
674701
usesKnownNativeOpenAIRoute:
675702
endpointClass === "default" ? provider === "openai" : usesKnownNativeOpenAIEndpoint,
@@ -703,6 +730,7 @@ export function resolveProviderRequestCapabilities(
703730
endpointClass === "mistral-public" ||
704731
endpointClass === "moonshot-native" ||
705732
endpointClass === "modelstudio-native" ||
733+
endpointClass === "nvidia-native" ||
706734
endpointClass === "openai-public" ||
707735
endpointClass === "openai-codex" ||
708736
endpointClass === "opencode-native" ||

src/agents/provider-request-config.test.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,44 @@ describe("provider request config", () => {
461461
});
462462
});
463463

464+
it("protects NVIDIA billing invoke origin on official NIM routes", () => {
465+
const resolved = resolveProviderRequestHeaders({
466+
provider: "custom-nim",
467+
api: "openai-completions",
468+
baseUrl: "https://integrate.api.nvidia.com/v1",
469+
capability: "llm",
470+
transport: "stream",
471+
callerHeaders: {
472+
"X-BILLING-INVOKE-ORIGIN": "spoofed",
473+
"X-Custom": "1",
474+
},
475+
precedence: "caller-wins",
476+
});
477+
478+
expect(resolved).toEqual({
479+
"X-BILLING-INVOKE-ORIGIN": "OpenClaw",
480+
"X-Custom": "1",
481+
});
482+
});
483+
484+
it("does not attach NVIDIA billing invoke origin to custom proxy routes", () => {
485+
const resolved = resolveProviderRequestHeaders({
486+
provider: "nvidia",
487+
api: "openai-completions",
488+
baseUrl: "https://proxy.example.com/v1",
489+
capability: "llm",
490+
transport: "stream",
491+
callerHeaders: {
492+
"X-BILLING-INVOKE-ORIGIN": "operator-value",
493+
},
494+
precedence: "caller-wins",
495+
});
496+
497+
expect(resolved).toEqual({
498+
"X-BILLING-INVOKE-ORIGIN": "operator-value",
499+
});
500+
});
501+
464502
it("merges header names case-insensitively", () => {
465503
const resolved = resolveProviderRequestHeaders({
466504
provider: "openai",

0 commit comments

Comments
 (0)