66import os
77import platform
88import shutil
9+ import subprocess
910import sys
1011import tempfile
1112from collections .abc import Mapping
@@ -312,7 +313,6 @@ def service_ready_check(self, conn: HTTPConnection, args: Any, model_name: Optio
312313 except ValueError :
313314 logger .debug (f"{ self .name } { container_name } /models does not include a model list in the response" )
314315 return False
315-
316316 if not model_name :
317317 if hasattr (args , 'MODEL' ) and isinstance (args .MODEL , str ):
318318 model_name = New (args .MODEL , args ).model_alias
@@ -539,13 +539,12 @@ def _serve_handler(self, args: argparse.Namespace) -> None:
539539
540540 super ()._serve_handler (args )
541541
542- def _serve_router (self , args : argparse .Namespace ) -> None :
543- """Serve multiple models using llama.cpp router mode (container-only) ."""
542+ def _build_router_engine (self , args : argparse .Namespace ) -> Engine :
543+ """Resolve models and build an Engine with bind mounts for router mode."""
544544 if not args .container :
545545 sys .exit ("Error: multi-model router mode requires a container runtime." )
546546
547547 set_accel_env_vars ()
548- args .port = compute_serving_port (args )
549548 args .router_mode = True
550549
551550 if args .MODEL :
@@ -563,28 +562,46 @@ def _serve_router(self, args: argparse.Namespace) -> None:
563562 if not models :
564563 sys .exit ("Error: no GGUF models found in the model store. Pull a model first with: ramalama pull <model>" )
565564
566- if args .container and not args . dryrun :
565+ if not args .dryrun and not getattr ( args , "image" , None ) :
567566 config = ActiveConfig ()
568567 should_pull = config .pull in ["always" , "missing" , "newer" ]
569568 args .image = ensure_image (config .engine , accel_image (config ), should_pull = should_pull )
570569
571- cmd = assemble_command ( args )
570+ cmd = self . handle_subcommand ( "serve" , args )
572571 engine = Engine (args )
573572 name = getattr (args , "name" , None ) or genname ()
573+ args .name = name
574574 engine .add (["--label" , "ai.ramalama" , "--name" , name , "--env=HOME=/tmp" , "--init" ])
575575
576576 for host_path , container_name in models :
577577 mount_path = f"/mnt/models/{ container_name } "
578578 container_host_path = get_container_mount_path (host_path )
579- engine .add ([f"--mount=type=bind,src={ container_host_path } ,destination={ mount_path } ,ro" ])
579+ engine .add ([f"--mount=type=bind,src={ container_host_path } ,destination={ mount_path } ,ro{ engine . relabel () } " ])
580580
581581 engine .add ([args .image ] + cmd )
582+ return engine
583+
584+ def _serve_router (self , args : argparse .Namespace ) -> None :
585+ """Serve multiple models using llama.cpp router mode (container-only)."""
586+ args .port = compute_serving_port (args )
587+ engine = self ._build_router_engine (args )
582588
583589 if args .dryrun :
584590 engine .dryrun ()
585591 return
586592 engine .exec ()
587593
594+ def serve_router_nonblocking (self , args : argparse .Namespace ) -> None :
595+ """Start the router-mode server non-blocking (for sandbox use)."""
596+ args .detach = True
597+ engine = self ._build_router_engine (args )
598+
599+ if args .dryrun :
600+ engine .dryrun ()
601+ return
602+
603+ subprocess .Popen (engine .exec_args )
604+
588605 @staticmethod
589606 def _migrate_store_ref_files (store : Any ) -> None :
590607 """Migrate any old-format ref files to JSON before enumeration."""
0 commit comments