@@ -12,6 +12,7 @@ import {
1212 deriveProviderPresets ,
1313 providerConfigSeed ,
1414} from "../src/providers/derive" ;
15+ import { FREE_PROVIDER_DIRECTORY } from "../src/providers/free-directory" ;
1516import { PROVIDER_REGISTRY , type ProviderRegistryEntry } from "../src/providers/registry" ;
1617import { routedSlug } from "../src/providers/slug-codec" ;
1718import { routeModel } from "../src/router" ;
@@ -51,6 +52,7 @@ afterEach(() => {
5152 globalThis . fetch = originalFetch ;
5253 clearModelCache ( "sambanova" ) ;
5354 clearModelCache ( "nebius" ) ;
55+ clearModelCache ( "nebius-team" ) ;
5456} ) ;
5557
5658function registryEntry ( id : ProviderId ) : ProviderRegistryEntry {
@@ -90,7 +92,9 @@ describe("SambaNova and Nebius providers", () => {
9092 dashboardUrl : PROVIDERS . sambanova . dashboardUrl ,
9193 liveModels : true ,
9294 preserveCustomDestination : true ,
95+ apiKeyValidation : "unknown" ,
9396 parallelToolCalls : false ,
97+ reasoningEfforts : [ ] ,
9498 modelDiscovery : {
9599 path : "models" ,
96100 maxResponseBytes : 131_072 ,
@@ -109,6 +113,7 @@ describe("SambaNova and Nebius providers", () => {
109113 liveModels : true ,
110114 preserveCustomDestination : true ,
111115 parallelToolCalls : false ,
116+ reasoningEfforts : [ ] ,
112117 modelDiscovery : {
113118 path : "models" ,
114119 query : { verbose : "true" } ,
@@ -120,6 +125,9 @@ describe("SambaNova and Nebius providers", () => {
120125 } ,
121126 } ) ;
122127 expect ( registryEntry ( "nebius" ) . note ) . toContain ( "embedding and image-generation rows" ) ;
128+ expect ( FREE_PROVIDER_DIRECTORY . find ( row => row . id === "nebius" ) ) . toMatchObject ( {
129+ modelsUrl : PROVIDERS . nebius . modelsUrl ,
130+ } ) ;
123131 } ) ;
124132
125133 test ( "derives CLI and dashboard presets without persisting registry trust policy" , ( ) => {
@@ -133,6 +141,7 @@ describe("SambaNova and Nebius providers", () => {
133141 baseUrl : provider . baseUrl ,
134142 dashboardUrl : provider . dashboardUrl ,
135143 liveModels : true ,
144+ ...( id === "sambanova" ? { apiKeyValidation : "unknown" } : { } ) ,
136145 } ) ;
137146 expect ( buildInitProviders ( ) . find ( row => row . id === id ) ) . toMatchObject ( {
138147 kind : "key" ,
@@ -151,34 +160,52 @@ describe("SambaNova and Nebius providers", () => {
151160 authMode : "key" ,
152161 liveModels : true ,
153162 parallelToolCalls : false ,
163+ reasoningEfforts : [ ] ,
154164 } ) ;
165+ expect ( seed ) . not . toHaveProperty ( "apiKeyValidation" ) ;
155166 expect ( seed ) . not . toHaveProperty ( "modelDiscovery" ) ;
156167 expect ( seed ) . not . toHaveProperty ( "preserveCustomDestination" ) ;
157168 expect ( KEY_LOGIN_PROVIDERS [ id ] ) . not . toHaveProperty ( "modelDiscovery" ) ;
158169 expect ( KEY_LOGIN_PROVIDERS [ id ] ) . not . toHaveProperty ( "preserveCustomDestination" ) ;
159170 }
160171 } ) ;
161172
162- test ( "lists and validates models through each registry-owned endpoint " , async ( ) => {
173+ test ( "builds each registry-owned models request and validates the authenticated Nebius catalog " , async ( ) => {
163174 for ( const id of [ "sambanova" , "nebius" ] as const ) {
164175 const provider = PROVIDERS [ id ] ;
165176 expect ( buildModelsRequest ( providerConfig ( id ) . providers [ id ] ! , provider . key , id ) ) . toEqual ( {
166177 url : provider . modelsUrl ,
167178 headers : { Authorization : `Bearer ${ provider . key } ` } ,
168179 } ) ;
180+ }
169181
170- globalThis . fetch = ( async ( input , init ) => {
171- expect ( String ( input ) ) . toBe ( provider . modelsUrl ) ;
172- expect ( new Headers ( init ?. headers ) . get ( "authorization" ) ) . toBe ( `Bearer ${ provider . key } ` ) ;
173- expect ( init ?. redirect ) . toBe ( "error" ) ;
174- return new Response ( provider . fixture , {
175- status : 200 ,
176- headers : { "content-type" : "application/json" } ,
177- } ) ;
178- } ) as typeof fetch ;
182+ const provider = PROVIDERS . nebius ;
183+ globalThis . fetch = ( async ( input , init ) => {
184+ expect ( String ( input ) ) . toBe ( provider . modelsUrl ) ;
185+ expect ( new Headers ( init ?. headers ) . get ( "authorization" ) ) . toBe ( `Bearer ${ provider . key } ` ) ;
186+ expect ( init ?. redirect ) . toBe ( "error" ) ;
187+ return new Response ( provider . fixture , {
188+ status : 200 ,
189+ headers : { "content-type" : "application/json" } ,
190+ } ) ;
191+ } ) as typeof fetch ;
179192
180- expect ( await validateApiKey ( id , KEY_LOGIN_PROVIDERS [ id ] ! , provider . key ) ) . toBe ( true ) ;
181- }
193+ expect ( await validateApiKey ( "nebius" , KEY_LOGIN_PROVIDERS . nebius ! , provider . key ) ) . toBe ( true ) ;
194+ } ) ;
195+
196+ test ( "does not treat SambaNova's public model catalog as proof that a key is valid" , async ( ) => {
197+ let fetchCalled = false ;
198+ globalThis . fetch = ( async ( ) => {
199+ fetchCalled = true ;
200+ return new Response ( SAMBANOVA_FIXTURE , { status : 200 } ) ;
201+ } ) as typeof fetch ;
202+
203+ expect ( await validateApiKey (
204+ "sambanova" ,
205+ KEY_LOGIN_PROVIDERS . sambanova ! ,
206+ PROVIDERS . sambanova . key ,
207+ ) ) . toBe ( "unknown" ) ;
208+ expect ( fetchCalled ) . toBe ( false ) ;
182209 } ) ;
183210
184211 test ( "filters Nebius mixed rows and preserves model metadata and native ids" , async ( ) => {
@@ -220,6 +247,7 @@ describe("SambaNova and Nebius providers", () => {
220247 expect ( sambanovaModels [ 1 ] ) . toMatchObject ( {
221248 owned_by : "sambanova" ,
222249 contextWindow : 131_072 ,
250+ reasoningEfforts : [ ] ,
223251 } ) ;
224252 expect ( nebiusModels . map ( row => row . id ) ) . toEqual ( [
225253 "meta-llama/Meta-Llama-3.1-8B-Instruct-fast" ,
@@ -230,6 +258,7 @@ describe("SambaNova and Nebius providers", () => {
230258 contextWindow : 131_072 ,
231259 inputModalities : [ "text" ] ,
232260 capabilities : [ "function-calling" , "json-mode" ] ,
261+ reasoningEfforts : [ ] ,
233262 } ) ;
234263 expect ( nebiusModels [ 1 ] ) . toMatchObject ( {
235264 contextWindow : 262_144 ,
@@ -246,6 +275,33 @@ describe("SambaNova and Nebius providers", () => {
246275 }
247276 } ) ;
248277
278+ test ( "keeps Nebius query and text-output filtering when the preset is renamed" , async ( ) => {
279+ const provider = PROVIDERS . nebius ;
280+ globalThis . fetch = ( async ( input , init ) => {
281+ expect ( String ( input ) ) . toBe ( provider . modelsUrl ) ;
282+ expect ( new Headers ( init ?. headers ) . get ( "authorization" ) ) . toBe ( `Bearer ${ provider . key } ` ) ;
283+ expect ( init ?. redirect ) . toBe ( "manual" ) ;
284+ return new Response ( provider . fixture , {
285+ status : 200 ,
286+ headers : { "content-type" : "application/json" } ,
287+ } ) ;
288+ } ) as typeof fetch ;
289+
290+ const renamed = "nebius-team" ;
291+ const config = withStubbedProviderFetch ( {
292+ port : 10100 ,
293+ defaultProvider : renamed ,
294+ providers : {
295+ [ renamed ] : providerConfig ( "nebius" ) . providers . nebius ! ,
296+ } ,
297+ } satisfies OcxConfig ) ;
298+ const models = await gatherRoutedModels ( config ) ;
299+ expect ( models . filter ( row => row . provider === renamed ) . map ( row => row . id ) ) . toEqual ( [
300+ "meta-llama/Meta-Llama-3.1-8B-Instruct-fast" ,
301+ "Qwen/Qwen3-VL-235B-A22B-Instruct" ,
302+ ] ) ;
303+ } ) ;
304+
249305 test ( "routes tool requests to the fixed hosts without claiming parallel tool calls" , ( ) => {
250306 const cases = [
251307 [ "sambanova" , "Meta-Llama-3.3-70B-Instruct" ] ,
@@ -265,14 +321,15 @@ describe("SambaNova and Nebius providers", () => {
265321 } ] ,
266322 } ,
267323 stream : true ,
268- options : { } ,
324+ options : { reasoning : "high" } ,
269325 } ) ;
270326 const body = JSON . parse ( String ( request . body ) ) as Record < string , unknown > ;
271327
272328 expect ( request . url ) . toBe ( `${ PROVIDERS [ providerId ] . baseUrl } /chat/completions` ) ;
273329 expect ( request . headers . Authorization ) . toBe ( `Bearer ${ PROVIDERS [ providerId ] . key } ` ) ;
274330 expect ( body . model ) . toBe ( modelId ) ;
275331 expect ( body . parallel_tool_calls ) . toBe ( false ) ;
332+ expect ( body ) . not . toHaveProperty ( "reasoning_effort" ) ;
276333 }
277334 } ) ;
278335
0 commit comments