Skip to content

Commit 304828b

Browse files
committed
feat(nvidia): tag NIM request origin
1 parent 7c4f607 commit 304828b

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", "api.grok.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", {
@@ -198,6 +227,7 @@ describe("provider attribution", () => {
198227
]),
199228
).toEqual([
200229
["openrouter", true, "vendor-documented", "request-headers"],
230+
["nvidia", true, "vendor-documented", "request-headers"],
201231
["openai", true, "vendor-hidden-api-spec", "request-headers"],
202232
["openai-codex", true, "vendor-hidden-api-spec", "request-headers"],
203233
["anthropic", false, "vendor-sdk-hook-only", "default-headers"],
@@ -351,6 +381,10 @@ describe("provider attribution", () => {
351381
endpointClass: "cerebras-native",
352382
hostname: "api.cerebras.ai",
353383
});
384+
expectRecordFields(resolveProviderEndpoint("https://integrate.api.nvidia.com/v1"), {
385+
endpointClass: "nvidia-native",
386+
hostname: "integrate.api.nvidia.com",
387+
});
354388
expectRecordFields(resolveProviderEndpoint("https://opencode.ai/api"), {
355389
endpointClass: "opencode-native",
356390
hostname: "opencode.ai",
@@ -400,6 +434,46 @@ describe("provider attribution", () => {
400434
).toBeUndefined();
401435
});
402436

437+
it("gates documented NVIDIA attribution to official NVIDIA NIM endpoints", () => {
438+
expectRecordFields(
439+
resolveProviderRequestPolicy({
440+
provider: "nvidia",
441+
api: "openai-completions",
442+
baseUrl: "https://integrate.api.nvidia.com/v1",
443+
transport: "stream",
444+
capability: "llm",
445+
}),
446+
{
447+
endpointClass: "nvidia-native",
448+
knownProviderFamily: "nvidia",
449+
attributionProvider: "nvidia",
450+
allowsHiddenAttribution: false,
451+
},
452+
);
453+
454+
expect(
455+
resolveProviderRequestAttributionHeaders({
456+
provider: "custom-nim",
457+
api: "openai-completions",
458+
baseUrl: "https://integrate.api.nvidia.com/v1",
459+
transport: "stream",
460+
capability: "llm",
461+
}),
462+
).toEqual({
463+
"X-BILLING-INVOKE-ORIGIN": "OpenClaw",
464+
});
465+
466+
expect(
467+
resolveProviderRequestAttributionHeaders({
468+
provider: "nvidia",
469+
api: "openai-completions",
470+
baseUrl: "https://proxy.example.com/v1",
471+
transport: "stream",
472+
capability: "llm",
473+
}),
474+
).toBeUndefined();
475+
});
476+
403477
it("summarizes proxy-like, local, invalid, default, and native routing compactly", () => {
404478
expect(
405479
describeProviderRequestRoutingSummary({
@@ -469,6 +543,18 @@ describe("provider attribution", () => {
469543
capability: "llm",
470544
}),
471545
).toBe("provider=groq api=openai-completions endpoint=groq-native route=native policy=none");
546+
547+
expect(
548+
describeProviderRequestRoutingSummary({
549+
provider: "nvidia",
550+
api: "openai-completions",
551+
baseUrl: "https://integrate.api.nvidia.com/v1",
552+
transport: "stream",
553+
capability: "llm",
554+
}),
555+
).toBe(
556+
"provider=nvidia api=openai-completions endpoint=nvidia-native route=native policy=documented",
557+
);
472558
});
473559

474560
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"
@@ -143,6 +144,7 @@ const MANIFEST_PROVIDER_ENDPOINT_CLASSES = new Set<ProviderEndpointClass>([
143144
"mistral-public",
144145
"moonshot-native",
145146
"modelstudio-native",
147+
"nvidia-native",
146148
"openai-public",
147149
"openai-codex",
148150
"opencode-native",
@@ -480,6 +482,23 @@ function buildOpenRouterAttributionPolicy(
480482
};
481483
}
482484

485+
function buildNvidiaAttributionPolicy(
486+
env: RuntimeVersionEnv = process.env as RuntimeVersionEnv,
487+
): ProviderAttributionPolicy {
488+
return {
489+
provider: "nvidia",
490+
enabledByDefault: true,
491+
verification: "vendor-documented",
492+
hook: "request-headers",
493+
reviewNote:
494+
"NVIDIA NIM billing invoke-origin attribution header. Applied only on verified NVIDIA routes.",
495+
...resolveProviderAttributionIdentity(env),
496+
headers: {
497+
"X-BILLING-INVOKE-ORIGIN": OPENCLAW_ATTRIBUTION_PRODUCT,
498+
},
499+
};
500+
}
501+
483502
function buildOpenAIAttributionPolicy(
484503
env: RuntimeVersionEnv = process.env as RuntimeVersionEnv,
485504
): ProviderAttributionPolicy {
@@ -541,6 +560,7 @@ export function listProviderAttributionPolicies(
541560
): ProviderAttributionPolicy[] {
542561
return [
543562
buildOpenRouterAttributionPolicy(env),
563+
buildNvidiaAttributionPolicy(env),
544564
buildOpenAIAttributionPolicy(env),
545565
buildOpenAICodexAttributionPolicy(env),
546566
buildSdkHookOnlyPolicy(
@@ -626,21 +646,28 @@ export function resolveProviderRequestPolicy(
626646
attributionProvider = "openrouter";
627647
}
628648
}
649+
if (!attributionProvider && endpointClass === "nvidia-native") {
650+
attributionProvider = "nvidia";
651+
}
629652

630-
const attributionHeaders = attributionProvider
631-
? resolveProviderAttributionHeaders(attributionProvider, env)
653+
const attributionPolicy = attributionProvider
654+
? resolveProviderAttributionPolicy(attributionProvider, env)
655+
: undefined;
656+
const attributionHeaders = attributionPolicy?.enabledByDefault
657+
? attributionPolicy.headers
632658
: undefined;
633659

634660
return {
635661
provider: provider || undefined,
636-
policy,
662+
policy: attributionPolicy ?? policy,
637663
endpointClass,
638664
usesConfiguredBaseUrl,
639665
knownProviderFamily: resolveKnownProviderFamily(provider || undefined),
640666
attributionProvider,
641667
attributionHeaders,
642668
allowsHiddenAttribution:
643-
attributionProvider !== undefined && policy?.verification === "vendor-hidden-api-spec",
669+
attributionProvider !== undefined &&
670+
attributionPolicy?.verification === "vendor-hidden-api-spec",
644671
usesKnownNativeOpenAIEndpoint,
645672
usesKnownNativeOpenAIRoute:
646673
endpointClass === "default" ? provider === "openai" : usesKnownNativeOpenAIEndpoint,
@@ -674,6 +701,7 @@ export function resolveProviderRequestCapabilities(
674701
endpointClass === "mistral-public" ||
675702
endpointClass === "moonshot-native" ||
676703
endpointClass === "modelstudio-native" ||
704+
endpointClass === "nvidia-native" ||
677705
endpointClass === "openai-public" ||
678706
endpointClass === "openai-codex" ||
679707
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)