@@ -43,6 +43,9 @@ enum Commands {
4343
4444#[ derive( Parser ) ]
4545struct ServeArgs {
46+ /// Model name to serve (e.g., inftyai/tiny-random-gpt2)
47+ model : String ,
48+
4649 /// Host address to bind to
4750 #[ arg( long, default_value = "0.0.0.0" ) ]
4851 host : String ,
@@ -221,7 +224,24 @@ pub async fn run(cli: Cli) {
221224 }
222225
223226 Commands :: SERVE ( args) => {
224- if let Err ( e) = crate :: cli:: serve:: execute ( & args. host , args. port ) . await {
227+ // Verify model exists
228+ let registry = ModelRegistry :: new ( None ) ;
229+ match registry. get_model ( & args. model ) {
230+ Ok ( Some ( _) ) => {
231+ // Model exists, proceed
232+ }
233+ Ok ( None ) => {
234+ eprintln ! ( "❌ Error: Model '{}' not found in registry" , args. model) ;
235+ eprintln ! ( "Run 'puma pull {}' to download it first" , args. model) ;
236+ std:: process:: exit ( 1 ) ;
237+ }
238+ Err ( e) => {
239+ eprintln ! ( "❌ Error checking model: {}" , e) ;
240+ std:: process:: exit ( 1 ) ;
241+ }
242+ }
243+
244+ if let Err ( e) = crate :: cli:: serve:: execute ( & args. host , args. port , & args. model ) . await {
225245 eprintln ! ( "Error starting server: {}" , e) ;
226246 std:: process:: exit ( 1 ) ;
227247 }
@@ -392,4 +412,58 @@ mod tests {
392412 assert_eq ! ( result. metadata. cache. revision, "v2" ) ;
393413 assert_eq ! ( result. metadata. cache. size, 2000 ) ;
394414 }
415+
416+ #[ test]
417+ fn test_serve_with_existing_model ( ) {
418+ let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
419+ let registry = ModelRegistry :: new ( Some ( temp_dir. path ( ) . to_path_buf ( ) ) ) ;
420+
421+ let model = create_test_model ( "test/serve-model" , "abc123" ) ;
422+ registry. register_model ( model) . unwrap ( ) ;
423+
424+ // Verify model exists (this is what serve command checks)
425+ let result = registry. get_model ( "test/serve-model" ) ;
426+ assert ! ( result. is_ok( ) ) ;
427+ assert ! ( result. unwrap( ) . is_some( ) ) ;
428+ }
429+
430+ #[ test]
431+ fn test_serve_with_nonexistent_model ( ) {
432+ let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
433+ let registry = ModelRegistry :: new ( Some ( temp_dir. path ( ) . to_path_buf ( ) ) ) ;
434+
435+ // Verify model doesn't exist
436+ let result = registry. get_model ( "nonexistent/model" ) ;
437+ assert ! ( result. is_ok( ) ) ;
438+ assert ! ( result. unwrap( ) . is_none( ) ) ;
439+ }
440+
441+ #[ test]
442+ fn test_serve_args_parsing ( ) {
443+ // Test that ServeArgs requires model argument
444+ use clap:: CommandFactory ;
445+ let app = Cli :: command ( ) ;
446+
447+ // This should fail without model argument
448+ let result = app. clone ( ) . try_get_matches_from ( vec ! [ "puma" , "serve" ] ) ;
449+ assert ! ( result. is_err( ) ) ;
450+
451+ // This should succeed with model argument
452+ let result = app
453+ . clone ( )
454+ . try_get_matches_from ( vec ! [ "puma" , "serve" , "test/model" ] ) ;
455+ assert ! ( result. is_ok( ) ) ;
456+
457+ // This should succeed with model and optional args
458+ let result = app. try_get_matches_from ( vec ! [
459+ "puma" ,
460+ "serve" ,
461+ "test/model" ,
462+ "--host" ,
463+ "127.0.0.1" ,
464+ "--port" ,
465+ "9000" ,
466+ ] ) ;
467+ assert ! ( result. is_ok( ) ) ;
468+ }
395469}
0 commit comments