@@ -607,6 +607,12 @@ function resolveProviderDefaults(cfg) {
607607 } else if ( p === "deepseek" ) {
608608 baseUrl = baseUrl || "https://api.deepseek.com/v1" ;
609609 model = model || "deepseek-chat" ;
610+ } else if ( p === "nvidia" ) {
611+ baseUrl = baseUrl || "https://integrate.api.nvidia.com/v1" ;
612+ model = model || "meta/llama-3.1-405b-instruct" ;
613+ } else if ( p === "huggingface" ) {
614+ baseUrl = baseUrl || "https://router.huggingface.co/v1" ;
615+ model = model || "meta-llama/Llama-3.1-70B-Instruct" ;
610616 }
611617 // custom / other: user must supply both
612618
@@ -7477,6 +7483,8 @@ async function handleBYOKValidate(request, env, ctx) {
74777483 anthropic : [ "claude-sonnet-4-20250514" , "claude-3-5-sonnet-20241022" , "claude-3-haiku-20240307" ] ,
74787484 deepseek : [ "deepseek-chat" , "deepseek-reasoner" ] ,
74797485 kimi : [ "kimi-k2-0520" , "moonshot-v1-128k" , "moonshot-v1-32k" ] ,
7486+ nvidia : [ "meta/llama-3.1-405b-instruct" , "meta/llama-3.3-70b-instruct" , "mistralai/mixtral-8x22b-instruct-v0.1" ] ,
7487+ huggingface : [ "meta-llama/Llama-3.1-70B-Instruct" , "Qwen/Qwen2.5-72B-Instruct" , "mistralai/Mistral-7B-Instruct-v0.3" ] ,
74807488 } ;
74817489
74827490 try {
@@ -7601,6 +7609,44 @@ async function handleBYOKValidate(request, env, ctx) {
76017609 id : m . id , name : m . id , recommended : ( RECOMMENDED . kimi || [ ] ) . includes ( m . id ) ,
76027610 } ) ) ;
76037611
7612+ } else if ( provider === "nvidia" ) {
7613+ // NVIDIA NIM — OpenAI-compatible, free tier 40 RPM
7614+ const nimUrl = ( base_url || "https://integrate.api.nvidia.com/v1" ) + "/models" ;
7615+ const res = await fetch ( nimUrl , { headers : { Authorization : `Bearer ${ api_key } ` } } ) ;
7616+ if ( ! res . ok ) {
7617+ const errText = await res . text ( ) . catch ( ( ) => "" ) ;
7618+ return apiResponse ( {
7619+ connected : false , provider : "nvidia" ,
7620+ error : res . status === 401 || res . status === 403 ? "Invalid API key — get one at build.nvidia.com" : `API error ${ res . status } : ${ errText . substring ( 0 , 100 ) } ` ,
7621+ } ) ;
7622+ }
7623+ const data = await res . json ( ) ;
7624+ models = ( data . data || [ ] )
7625+ . filter ( m => m . id && ( m . id . includes ( "llama" ) || m . id . includes ( "mistral" ) || m . id . includes ( "mixtral" ) || m . id . includes ( "qwen" ) || m . id . includes ( "gemma" ) || m . id . includes ( "deepseek" ) ) )
7626+ . map ( m => ( { id : m . id , name : m . id , recommended : ( RECOMMENDED . nvidia || [ ] ) . includes ( m . id ) } ) )
7627+ . sort ( ( a , b ) => ( b . recommended ? 1 : 0 ) - ( a . recommended ? 1 : 0 ) ) ;
7628+
7629+ } else if ( provider === "huggingface" ) {
7630+ // Hugging Face — OpenAI-compatible router, free tier ~few hundred req/hr
7631+ const hfUrl = ( base_url || "https://router.huggingface.co/v1" ) + "/models" ;
7632+ const res = await fetch ( hfUrl , { headers : { Authorization : `Bearer ${ api_key } ` } } ) ;
7633+ if ( ! res . ok ) {
7634+ const errText = await res . text ( ) . catch ( ( ) => "" ) ;
7635+ return apiResponse ( {
7636+ connected : false , provider : "huggingface" ,
7637+ error : res . status === 401 ? "Invalid token — get one at huggingface.co/settings/tokens" : `API error ${ res . status } : ${ errText . substring ( 0 , 100 ) } ` ,
7638+ } ) ;
7639+ }
7640+ const data = await res . json ( ) ;
7641+ models = ( data . data || [ ] )
7642+ . filter ( m => m . id )
7643+ . map ( m => ( { id : m . id , name : m . id , recommended : ( RECOMMENDED . huggingface || [ ] ) . includes ( m . id ) } ) )
7644+ . sort ( ( a , b ) => ( b . recommended ? 1 : 0 ) - ( a . recommended ? 1 : 0 ) ) ;
7645+ // If model listing fails (HF may not support /models), provide curated list
7646+ if ( models . length === 0 ) {
7647+ models = ( RECOMMENDED . huggingface || [ ] ) . map ( id => ( { id, name : id , recommended : true } ) ) ;
7648+ }
7649+
76047650 } else {
76057651 const customUrl = ( base_url || "" ) . replace ( / \/ $ / , "" ) + "/models" ;
76067652 try {
0 commit comments