@@ -28,6 +28,10 @@ import {
2828 printShortUsage ,
2929 printUsage ,
3030} from "./cli_args.ts" ;
31+ import {
32+ createModelAliasResolver ,
33+ loadProjectConfig ,
34+ } from "./project_config.ts" ;
3135
3236const logger = console ;
3337const DEFAULT_OLLAMA_BASE_URL = "http://localhost:11434/v1" ;
@@ -232,6 +236,42 @@ async function main() {
232236 Deno . exit ( 1 ) ;
233237 }
234238
239+ const configHint = deckPath || args . graderPath || args . testDeckPath ||
240+ args . exportDeckPath || Deno . cwd ( ) ;
241+ let projectConfig : Awaited < ReturnType < typeof loadProjectConfig > > = null ;
242+ try {
243+ projectConfig = await loadProjectConfig ( configHint ) ;
244+ } catch ( err ) {
245+ logger . error (
246+ `Failed to load gambit.toml: ${ ( err as Error ) . message } ` ,
247+ ) ;
248+ Deno . exit ( 1 ) ;
249+ }
250+ const modelAliasResolver = createModelAliasResolver (
251+ projectConfig ?. config ,
252+ ) ;
253+ const warnedMissingAliases = new Set < string > ( ) ;
254+ const applyModelAlias = (
255+ model ?: string ,
256+ params ?: Record < string , unknown > ,
257+ ) : { model ?: string ; params ?: Record < string , unknown > } => {
258+ const resolution = modelAliasResolver ( model ) ;
259+ if (
260+ resolution . missingAlias &&
261+ model &&
262+ ! warnedMissingAliases . has ( model )
263+ ) {
264+ logger . warn (
265+ `[gambit] Model alias "${ model } " is not defined in gambit.toml; using literal value.` ,
266+ ) ;
267+ warnedMissingAliases . add ( model ) ;
268+ }
269+ const mergedParams = resolution . params
270+ ? { ...resolution . params , ...( params ?? { } ) }
271+ : params ;
272+ return { model : resolution . model ?? model , params : mergedParams } ;
273+ } ;
274+
235275 if ( args . cmd === "grade" ) {
236276 const graderPath = args . graderPath ?? deckPath ;
237277 if ( ! graderPath ) {
@@ -282,6 +322,7 @@ async function main() {
282322 openRouterBaseURL : Deno . env . get ( "OPENROUTER_BASE_URL" ) ?? undefined ,
283323 ollamaApiKey : Deno . env . get ( "OLLAMA_API_KEY" ) ?? undefined ,
284324 ollamaBaseURL : Deno . env . get ( "OLLAMA_BASE_URL" ) ?? undefined ,
325+ modelResolver : modelAliasResolver ,
285326 } ) ;
286327 return ;
287328 }
@@ -304,10 +345,12 @@ async function main() {
304345 baseURL : ollamaBaseURL ,
305346 } ) ;
306347 const ollamaPrefix = "ollama/" ;
307- const ollamaModels = [
348+ const flagModels = [
308349 args . model ?? undefined ,
309350 args . modelForce ?? undefined ,
310- ]
351+ ] . filter ( ( model ) : model is string => Boolean ( model ) ) ;
352+ const ollamaModels = flagModels
353+ . map ( ( model ) => applyModelAlias ( model ) . model )
311354 . filter ( ( model ) : model is string => Boolean ( model ) )
312355 . filter ( ( model ) => model . startsWith ( ollamaPrefix ) )
313356 . map ( ( model ) => model . slice ( ollamaPrefix . length ) ) ;
@@ -322,16 +365,28 @@ async function main() {
322365 event : import ( "@bolt-foundry/gambit-core" ) . ResponseEvent ,
323366 ) => void ;
324367 } ) => {
325- if ( input . request . model . startsWith ( ollamaPrefix ) ) {
326- const trimmedModel = input . request . model . slice ( ollamaPrefix . length ) ;
368+ const applied = applyModelAlias (
369+ input . request . model ,
370+ input . request . params ,
371+ ) ;
372+ const request = {
373+ ...input . request ,
374+ model : applied . model ?? input . request . model ,
375+ params : applied . params ,
376+ } ;
377+ if ( ! request . model ) {
378+ throw new Error ( "Model is required." ) ;
379+ }
380+ if ( request . model . startsWith ( ollamaPrefix ) ) {
381+ const trimmedModel = request . model . slice ( ollamaPrefix . length ) ;
327382 const ollamaResponses = ollamaProvider . responses ;
328383 if ( ! ollamaResponses ) {
329384 throw new Error ( "Ollama responses are not configured." ) ;
330385 }
331386 return await ollamaResponses ( {
332387 ...input ,
333388 request : {
334- ...input . request ,
389+ ...request ,
335390 model : trimmedModel ,
336391 } ,
337392 } ) ;
@@ -341,7 +396,10 @@ async function main() {
341396 "OPENROUTER_API_KEY is required for non-ollama models." ,
342397 ) ;
343398 }
344- return await openRouterProvider . responses ( input ) ;
399+ return await openRouterProvider . responses ( {
400+ ...input ,
401+ request,
402+ } ) ;
345403 } ,
346404 chat : async ( input : {
347405 model : string ;
@@ -352,16 +410,25 @@ async function main() {
352410 onStreamText ?: ( chunk : string ) => void ;
353411 params ?: Record < string , unknown > ;
354412 } ) => {
355- if ( input . model . startsWith ( ollamaPrefix ) ) {
356- const model = input . model . slice ( ollamaPrefix . length ) ;
357- return await ollamaProvider . chat ( { ...input , model } ) ;
413+ const applied = applyModelAlias ( input . model , input . params ) ;
414+ const request = {
415+ ...input ,
416+ model : applied . model ?? input . model ,
417+ params : applied . params ,
418+ } ;
419+ if ( ! request . model ) {
420+ throw new Error ( "Model is required." ) ;
421+ }
422+ if ( request . model . startsWith ( ollamaPrefix ) ) {
423+ const model = request . model . slice ( ollamaPrefix . length ) ;
424+ return await ollamaProvider . chat ( { ...request , model } ) ;
358425 }
359426 if ( ! openRouterProvider ) {
360427 throw new Error (
361428 "OPENROUTER_API_KEY is required for non-ollama models." ,
362429 ) ;
363430 }
364- return await openRouterProvider . chat ( input ) ;
431+ return await openRouterProvider . chat ( request ) ;
365432 } ,
366433 } ;
367434
0 commit comments