mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-18 08:31:49 -06:00
9a0b43c47e
* feat(nvidia): add NVIDIA provider with onboarding flow Add the NVIDIA build.nvidia.com API as a bundled provider. Default model is nvidia/nvidia/nemotron-3-super-120b-a12b: first segment is the provider id, remaining "nvidia/nemotron-3-super-120b-a12b" is the literal upstream model id (which happens to start with "nvidia/" because NVIDIA is also the model maker). Supporting core change: introduce a provider capability flag nativeIdsIncludeProviderPrefix so providers whose native catalog ids intentionally include their provider prefix (OpenRouter) opt into self-prefix dedupe in modelKey, without hardcoding provider names in core. Providers whose ids merely happen to start with their own name (NVIDIA) leave the flag unset and get the full <provider>/<model-id> concatenation. - extensions/nvidia/*: new plugin, catalog, onboarding, tests, docs - extensions/openrouter/index.ts: declare nativeIdsIncludeProviderPrefix - src/plugins/types.ts: add field to ProviderPlugin - src/plugins/registry.ts: populate self-prefix set on registration - src/agents/provider-self-prefix.ts: sync accessor used by modelKey - src/agents/model-ref-shared.ts: modelKey consults the flag - test updates for affected surfaces Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(model-picker): simplify literal-prefix display to label-only * fix(model-picker): pass workspaceDir/env to allowlist literal-prefix resolution * chore: untrack generated baseline JSON artifacts (gitignored) * fix(nvidia): show literal model ref in picker and onboarding notes * fix(nvidia): show hint whenever display label differs from stored config * fix(nvidia): drop redundant hint from Keep current label * fix(nvidia): restore literal double-prefix display labels * fix(picker): handle literal-prefix fast path * fix(picker): show literal keep label * fix(docs): update nvidia provider docs * fix(nvidia): update test helper imports * fix(changelog): add nvidia provider entry --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
87 lines
2.4 KiB
TypeScript
87 lines
2.4 KiB
TypeScript
import { normalizeProviderModelIdWithManifest } from "../plugins/manifest-model-id-normalization.js";
|
|
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
|
import { normalizeProviderId } from "./provider-id.js";
|
|
|
|
export type StaticModelRef = {
|
|
provider: string;
|
|
model: string;
|
|
};
|
|
|
|
export function modelKey(provider: string, model: string): string {
|
|
const providerId = provider.trim();
|
|
const modelId = model.trim();
|
|
if (!providerId) {
|
|
return modelId;
|
|
}
|
|
if (!modelId) {
|
|
return providerId;
|
|
}
|
|
return normalizeLowercaseStringOrEmpty(modelId).startsWith(
|
|
`${normalizeLowercaseStringOrEmpty(providerId)}/`,
|
|
)
|
|
? modelId
|
|
: `${providerId}/${modelId}`;
|
|
}
|
|
|
|
export function normalizeStaticProviderModelId(
|
|
provider: string,
|
|
model: string,
|
|
options: { allowManifestNormalization?: boolean } = {},
|
|
): string {
|
|
if (options.allowManifestNormalization === false) {
|
|
return model;
|
|
}
|
|
return (
|
|
normalizeProviderModelIdWithManifest({
|
|
provider,
|
|
context: {
|
|
provider,
|
|
modelId: model,
|
|
},
|
|
}) ?? model
|
|
);
|
|
}
|
|
|
|
export function parseStaticModelRef(raw: string, defaultProvider: string): StaticModelRef | null {
|
|
const trimmed = raw.trim();
|
|
if (!trimmed) {
|
|
return null;
|
|
}
|
|
const slash = trimmed.indexOf("/");
|
|
const providerRaw = slash === -1 ? defaultProvider : trimmed.slice(0, slash).trim();
|
|
const modelRaw = slash === -1 ? trimmed : trimmed.slice(slash + 1).trim();
|
|
if (!providerRaw || !modelRaw) {
|
|
return null;
|
|
}
|
|
const provider = normalizeProviderId(providerRaw);
|
|
return {
|
|
provider,
|
|
model: normalizeStaticProviderModelId(provider, modelRaw),
|
|
};
|
|
}
|
|
|
|
export function resolveStaticAllowlistModelKey(
|
|
raw: string,
|
|
defaultProvider: string,
|
|
): string | null {
|
|
const parsed = parseStaticModelRef(raw, defaultProvider);
|
|
if (!parsed) {
|
|
return null;
|
|
}
|
|
return modelKey(parsed.provider, parsed.model);
|
|
}
|
|
|
|
export function formatLiteralProviderPrefixedModelRef(provider: string, modelRef: string): string {
|
|
const providerId = normalizeProviderId(provider);
|
|
const trimmedRef = modelRef.trim();
|
|
if (!providerId || !trimmedRef) {
|
|
return trimmedRef;
|
|
}
|
|
const normalizedRef = normalizeLowercaseStringOrEmpty(trimmedRef);
|
|
const literalPrefix = `${providerId}/${providerId}/`;
|
|
if (normalizedRef.startsWith(literalPrefix)) {
|
|
return trimmedRef;
|
|
}
|
|
return normalizedRef.startsWith(`${providerId}/`) ? `${providerId}/${trimmedRef}` : trimmedRef;
|
|
}
|