@@ -60,17 +60,42 @@ static std::string detect_llama_server_binary() {
6060#endif
6161}
6262
63- const std::vector<std::string> & get_default_spawn () {
64- static const std::vector<std::string> spawn = [] {
65- std::vector<std::string> default_spawn = {
66- " llama-server" , " --ctx-size" , " 4096" , " --n-gpu-layers" , " 99" ,
63+ static SpawnConfig parse_spawn_config (const json & data) {
64+ SpawnConfig spawn;
65+ if (data.contains (" command" )) {
66+ spawn.command = data[" command" ].get <std::vector<std::string>>();
67+ }
68+ if (data.contains (" proxy_endpoints" )) {
69+ spawn.proxy_endpoints = data[" proxy_endpoints" ].get <std::vector<std::string>>();
70+ }
71+ if (data.contains (" health_endpoint" )) {
72+ spawn.health_endpoint = data[" health_endpoint" ].get <std::string>();
73+ }
74+
75+ return spawn;
76+ }
77+
78+ static json serialize_spawn_config (const SpawnConfig & spawn) {
79+ json obj;
80+ obj[" command" ] = spawn.command ;
81+ obj[" proxy_endpoints" ] = spawn.proxy_endpoints ;
82+ obj[" health_endpoint" ] = spawn.health_endpoint ;
83+ return obj;
84+ }
85+
86+ const SpawnConfig & get_default_spawn () {
87+ static const SpawnConfig spawn = [] {
88+ SpawnConfig default_spawn = {
89+ /* command =*/ {" llama-server" , " --ctx-size" , " 4096" , " --n-gpu-layers" , " 99" },
90+ /* proxy_endpoints =*/ {" /v1/" , " /health" , " /slots" , " /props" },
91+ /* health_endpoint =*/ " /health" ,
6792 };
6893
6994 std::error_code ec;
7095 const std::string detected_path = detect_llama_server_binary ();
7196 if (!detected_path.empty () && std::filesystem::exists (detected_path, ec) && !ec) {
7297 LOG_INF (" Detected llama-server at %s\n " , detected_path.c_str ());
73- default_spawn[0 ] = detected_path;
98+ default_spawn. command [0 ] = detected_path;
7499 } else {
75100 LOG_INF (" Falling back to llama-server resolved via PATH\n " );
76101 }
@@ -135,7 +160,7 @@ static void ensure_parent_directory(const std::string & path) {
135160void write_config_file (const RouterConfig & cfg, const std::string & path) {
136161 json out;
137162 out[" version" ] = cfg.version ;
138- out[" default_spawn" ] = cfg.default_spawn ;
163+ out[" default_spawn" ] = serialize_spawn_config ( cfg.default_spawn ) ;
139164 out[" router" ] = {{" host" , cfg.router .host },
140165 {" port" , cfg.router .port },
141166 {" base_port" , cfg.router .base_port },
@@ -155,8 +180,8 @@ void write_config_file(const RouterConfig & cfg, const std::string & path) {
155180 if (!m.group .empty ()) {
156181 obj[" group" ] = m.group ;
157182 }
158- if (!m.spawn . empty ( )) {
159- obj[" spawn" ] = m.spawn ;
183+ if (!is_spawn_empty ( m.spawn )) {
184+ obj[" spawn" ] = serialize_spawn_config ( m.spawn ) ;
160185 }
161186 out[" models" ].push_back (std::move (obj));
162187 }
@@ -204,7 +229,7 @@ RouterConfig load_config(const std::string & path) {
204229 cfg.version = data[" version" ].get <std::string>();
205230 }
206231 if (data.contains (" default_spawn" )) {
207- cfg.default_spawn = data[" default_spawn" ]. get <std::vector<std::string>>( );
232+ cfg.default_spawn = parse_spawn_config ( data[" default_spawn" ]);
208233 }
209234 if (data.contains (" router" )) {
210235 auto r = data[" router" ];
@@ -223,7 +248,7 @@ RouterConfig load_config(const std::string & path) {
223248 mc.state = m.value (" state" , " manual" );
224249 mc.group = m.value (" group" , " " );
225250 if (m.contains (" spawn" )) {
226- mc.spawn = m[" spawn" ]. get <std::vector<std::string>>( );
251+ mc.spawn = parse_spawn_config ( m[" spawn" ]);
227252 }
228253 cfg.models .push_back (std::move (mc));
229254 }
@@ -248,11 +273,14 @@ RouterConfig load_config(const std::string & path) {
248273 throw std::runtime_error (" model path does not exist: " + path_to_check);
249274 }
250275
251- if (!model.spawn .empty ()) {
252- const std::string & cmd = model.spawn .front ();
253- if (!cmd.empty () && cmd.find (' /' ) != std::string::npos && !std::filesystem::exists (cmd, ec)) {
254- throw std::runtime_error (" spawn command not executable: " + cmd);
255- }
276+ const SpawnConfig & spawn = is_spawn_empty (model.spawn ) ? cfg.default_spawn : model.spawn ;
277+ if (spawn.command .empty ()) {
278+ throw std::runtime_error (" spawn command missing for model: " + model.name );
279+ }
280+
281+ const std::string & cmd = spawn.command .front ();
282+ if (!cmd.empty () && cmd.find (' /' ) != std::string::npos && !std::filesystem::exists (cmd, ec)) {
283+ throw std::runtime_error (" spawn command not executable: " + cmd);
256284 }
257285 }
258286
0 commit comments