Skip to content
This repository was archived by the owner on Jul 4, 2025. It is now read-only.

Commit 9ee8b2b

Browse files
fix: add more parameters to server start command (#2032)
* fix: add more parameters to config command * chore: remove trt-llm log path config * fix: add more flags * fix: e2e tests * chore: update quality gate workflow * chore: e2e tests --------- Co-authored-by: sangjanai <sang@jan.ai>
1 parent 81211a4 commit 9ee8b2b

16 files changed

+307
-77
lines changed

.github/workflows/cortex-cpp-quality-gate.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ jobs:
149149
if: runner.os == 'Linux'
150150
run: |
151151
cd engine
152+
mkdir -p ~/.config/cortexcpp/
152153
echo "huggingFaceToken: ${{ secrets.HUGGINGFACE_TOKEN_READ }}" > ~/.config/cortexcpp/.cortexrc
153154
echo "gitHubToken: ${{ secrets.PAT_SERVICE_ACCOUNT }}" >> ~/.config/cortexcpp/.cortexrc
154155
# ./build/cortex
@@ -175,6 +176,7 @@ jobs:
175176
if: runner.os == 'Linux'
176177
run: |
177178
cd engine
179+
mkdir -p ~/.config/cortexcpp/
178180
echo "apiServerPort: 3928" > ~/.config/cortexcpp/.cortexrc
179181
echo "huggingFaceToken: ${{ secrets.HUGGINGFACE_TOKEN_READ }}" >> ~/.config/cortexcpp/.cortexrc
180182
echo "gitHubToken: ${{ secrets.PAT_SERVICE_ACCOUNT }}" >> ~/.config/cortexcpp/.cortexrc
@@ -453,6 +455,7 @@ jobs:
453455
if: runner.os == 'Linux'
454456
run: |
455457
cd engine
458+
mkdir -p ~/.config/cortexcpp/
456459
echo "gitHubToken: ${{ secrets.GITHUB_TOKEN }}" > ~/.config/cortexcpp/.cortexrc
457460
# ./build/cortex
458461
cat ~/.config/cortexcpp/.cortexrc
@@ -477,6 +480,7 @@ jobs:
477480
if: runner.os == 'Linux'
478481
run: |
479482
cd engine
483+
mkdir -p ~/.config/cortexcpp/
480484
echo "apiServerPort: 3928" > ~/.config/cortexcpp/.cortexrc
481485
echo "gitHubToken: ${{ secrets.GITHUB_TOKEN }}" > ~/.config/cortexcpp/.cortexrc
482486
# ./build/cortex

docs/docs/architecture/cortexrc.mdx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ Example of the `.cortexrc` file:
4444
```
4545
logFolderPath: /home/<user>/cortexcpp
4646
logLlamaCppPath: ./logs/cortex.log
47-
logTensorrtLLMPath: ./logs/cortex.log
4847
logOnnxPath: ./logs/cortex.log
4948
dataFolderPath: /home/<user>/cortexcpp
5049
maxLogLines: 100000

engine/cli/command_line_parser.cc

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,7 @@ void CommandLineParser::SetupConfigsCommands() {
437437

438438
auto is_empty = true;
439439
for (const auto& [key, value] : config_update_opts_) {
440-
if (!value.empty()) {
440+
if (!value.empty() || CONFIGURATIONS.at(key).allow_empty) {
441441
is_empty = false;
442442
break;
443443
}
@@ -656,36 +656,47 @@ void CommandLineParser::SetupHardwareCommands() {
656656
void CommandLineParser::SetupSystemCommands() {
657657
auto start_cmd = app_.add_subcommand("start", "Start the API server");
658658
start_cmd->group(kSystemGroup);
659-
cml_data_.port = std::stoi(cml_data_.config.apiServerPort);
660-
start_cmd->add_option("-p, --port", cml_data_.port, "Server port to listen");
661-
start_cmd->add_option("--loglevel", cml_data_.log_level,
662-
"Set up log level for server, accepted TRACE, DEBUG, "
663-
"INFO, WARN, ERROR");
664-
if (cml_data_.log_level != "INFO" && cml_data_.log_level != "TRACE" &&
665-
cml_data_.log_level != "DEBUG" && cml_data_.log_level != "WARN" &&
666-
cml_data_.log_level != "ERROR") {
667-
CLI_LOG("Invalid log level: " << cml_data_.log_level
668-
<< ", Set Loglevel to INFO");
669-
cml_data_.log_level = "INFO";
659+
660+
// Add options dynamically
661+
std::vector<std::pair<std::string, std::string>> option_names = {
662+
{"logspath", "The directory where logs are stored"},
663+
{"logsllama", "The directory where llama-cpp engine logs are stored"},
664+
{"logsonnx", "The directory where onnx engine logs are stored"},
665+
{"datapath", "The directory for storing data"},
666+
{"loglines", "Log size limit"},
667+
{"host", "The host IP for the API server"},
668+
{"port", "The port used by the API server"},
669+
{"hf-token", "HuggingFace authentication token"},
670+
{"gh-agent", "Github user agent"},
671+
{"gh-token", "Github authentication token"},
672+
{"cors", "Cross-Origin Resource Sharing"},
673+
{"origins", "Lists allowed origins for CORS requests"},
674+
{"proxy-url", "Proxy URL"},
675+
{"verify-proxy", "SSL verification for client proxy connections"},
676+
{"verify-proxy-host", "SSL verification for host proxy connections"},
677+
{"proxy-username", "Proxy username"},
678+
{"proxy-password", "Proxy password"},
679+
{"no-proxy", "Specifies exceptions for proxy usage"},
680+
{"verify-ssl-peer", "SSL/TLS verification for peer connections"},
681+
{"verify-ssl-host", "SSL/TLS verification for host connections"},
682+
{"ssl-cert-path", "Path to SSL certificates"},
683+
{"ssl-key-path", "Path to SSL and keys"},
684+
{"loglevel", "Log level"}};
685+
cml_data_.server_start_options["loglevel"] = "INFO";
686+
for (const auto& option_name : option_names) {
687+
start_cmd->add_option(
688+
"--" + std::get<0>(option_name),
689+
cml_data_.server_start_options[std::get<0>(option_name)],
690+
std::get<1>(option_name));
670691
}
692+
671693
start_cmd->callback([this] {
672694
if (std::exchange(executed_, true))
673695
return;
674-
if (cml_data_.port != stoi(cml_data_.config.apiServerPort)) {
675-
CTL_INF("apiServerPort changed from " << cml_data_.config.apiServerPort
676-
<< " to " << cml_data_.port);
677-
auto config_path = file_manager_utils::GetConfigurationPath();
678-
cml_data_.config.apiServerPort = std::to_string(cml_data_.port);
679-
auto result =
680-
config_yaml_utils::CortexConfigMgr::GetInstance().DumpYamlConfig(
681-
cml_data_.config, config_path.string());
682-
if (result.has_error()) {
683-
CLI_LOG("Error update " << config_path.string() << result.error());
684-
}
685-
}
696+
686697
commands::ServerStartCmd ssc;
687-
ssc.Exec(cml_data_.config.apiServerHost,
688-
std::stoi(cml_data_.config.apiServerPort), cml_data_.log_level);
698+
ssc.Exec(cml_data_.server_start_options["loglevel"],
699+
cml_data_.server_start_options, cml_data_.config);
689700
});
690701

691702
auto stop_cmd = app_.add_subcommand("stop", "Stop the API server");

engine/cli/command_line_parser.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,12 @@ class CommandLineParser {
6767
bool display_gpu_mode = false;
6868
bool display_available_model = false;
6969
std::string filter = "";
70-
std::string log_level = "INFO";
7170

7271
bool show_menu = false;
7372

74-
int port;
7573
config_yaml_utils::CortexConfig config;
7674
std::unordered_map<std::string, std::string> model_update_options;
75+
std::unordered_map<std::string, std::string> server_start_options;
7776
std::string model_src;
7877
};
7978
CmlData cml_data_;

engine/cli/commands/config_upd_cmd.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ void commands::ConfigUpdCmd::Exec(
5656

5757
auto non_null_opts = std::unordered_map<std::string, std::string>();
5858
for (const auto& [key, value] : options) {
59-
if (value.empty()) {
59+
if (value.empty() && !CONFIGURATIONS.at(key).allow_empty) {
6060
continue;
6161
}
6262
non_null_opts[key] = value;

engine/cli/commands/server_start_cmd.cc

Lines changed: 178 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ bool ServerStartCmd::Exec(const std::string& host, int port,
6666
si.cb = sizeof(si);
6767
ZeroMemory(&pi, sizeof(pi));
6868
std::wstring params = L"--start-server";
69-
params += L" --config_file_path \"" +
69+
params += L" --config_file_path \"" +
7070
file_manager_utils::GetConfigurationPath().wstring() + L"\"";
7171
params += L" --data_folder_path \"" +
7272
file_manager_utils::GetCortexDataPath().wstring() + L"\"";
@@ -80,17 +80,17 @@ bool ServerStartCmd::Exec(const std::string& host, int port,
8080
mutable_cmds.push_back(L'\0');
8181
// Create child process
8282
if (!CreateProcess(
83-
NULL, // No module name (use command line)
83+
NULL, // No module name (use command line)
8484
mutable_cmds
85-
.data(), // Command line (replace with your actual executable)
86-
NULL, // Process handle not inheritable
87-
NULL, // Thread handle not inheritable
88-
FALSE, // Set handle inheritance
89-
CREATE_NO_WINDOW, // No new console
90-
NULL, // Use parent's environment block
91-
NULL, // Use parent's starting directory
92-
&si, // Pointer to STARTUPINFO structure
93-
&pi)) // Pointer to PROCESS_INFORMATION structure
85+
.data(), // Command line (replace with your actual executable)
86+
NULL, // Process handle not inheritable
87+
NULL, // Thread handle not inheritable
88+
FALSE, // Set handle inheritance
89+
CREATE_NO_WINDOW, // No new console
90+
NULL, // Use parent's environment block
91+
NULL, // Use parent's starting directory
92+
&si, // Pointer to STARTUPINFO structure
93+
&pi)) // Pointer to PROCESS_INFORMATION structure
9494
{
9595
std::cout << "Could not start server: " << GetLastError() << std::endl;
9696
return false;
@@ -136,4 +136,171 @@ bool ServerStartCmd::Exec(const std::string& host, int port,
136136
#endif
137137
return true;
138138
}
139+
140+
bool ServerStartCmd::Exec(
141+
const std::optional<std::string>& log_level,
142+
const std::unordered_map<std::string, std::string>& options,
143+
CortexConfig& data) {
144+
for (const auto& [key, value] : options) {
145+
if (!value.empty()) {
146+
UpdateConfig(data, key, value);
147+
}
148+
}
149+
150+
auto config_path = file_manager_utils::GetConfigurationPath();
151+
auto result =
152+
config_yaml_utils::CortexConfigMgr::GetInstance().DumpYamlConfig(
153+
data, config_path.string());
154+
if (result.has_error()) {
155+
CTL_WRN("Error update " << config_path.string() << result.error());
156+
}
157+
return Exec(data.apiServerHost, std::stoi(data.apiServerPort), log_level);
158+
}
159+
160+
void ServerStartCmd::UpdateConfig(CortexConfig& data, const std::string& key,
161+
const std::string& value) {
162+
static const std::unordered_map<
163+
std::string, std::function<void(CortexConfig&, const std::string&,
164+
const std::string&)>>
165+
updaters = {
166+
{"logspath",
167+
[](CortexConfig& data, const std::string&, const std::string& v) {
168+
data.logFolderPath = v;
169+
}},
170+
{"logsllama",
171+
[](CortexConfig& data, const std::string&, const std::string& v) {
172+
data.logLlamaCppPath = v;
173+
}},
174+
{"logsonnx",
175+
[](CortexConfig& data, const std::string&, const std::string& v) {
176+
data.logOnnxPath = v;
177+
}},
178+
{"loglines",
179+
[this](CortexConfig& data, const std::string& k,
180+
const std::string& v) {
181+
UpdateNumericField(k, v, [&data](float f) {
182+
data.maxLogLines = static_cast<int>(f);
183+
});
184+
}},
185+
{"host",
186+
[](CortexConfig& data, const std::string&, const std::string& v) {
187+
data.apiServerHost = v;
188+
}},
189+
{"port",
190+
[](CortexConfig& data, const std::string& k, const std::string& v) {
191+
data.apiServerPort = v;
192+
}},
193+
{"hf-token",
194+
[](CortexConfig& data, const std::string&, const std::string& v) {
195+
data.huggingFaceToken = v;
196+
}},
197+
{"gh-agent",
198+
[](CortexConfig& data, const std::string&, const std::string& v) {
199+
data.gitHubUserAgent = v;
200+
}},
201+
{"gh-token",
202+
[](CortexConfig& data, const std::string&, const std::string& v) {
203+
data.gitHubToken = v;
204+
}},
205+
{"cors",
206+
[this](CortexConfig& data, const std::string& k,
207+
const std::string& v) {
208+
UpdateBooleanField(k, v, [&data](bool b) { data.enableCors = b; });
209+
}},
210+
{"origins",
211+
[this](CortexConfig& data, const std::string& k,
212+
const std::string& v) {
213+
UpdateVectorField(k, v,
214+
[&data](const std::vector<std::string>& orgs) {
215+
data.allowedOrigins = orgs;
216+
});
217+
}},
218+
{"proxy-url",
219+
[](CortexConfig& data, const std::string&, const std::string& v) {
220+
data.proxyUrl = v;
221+
}},
222+
{"verify-proxy",
223+
[this](CortexConfig& data, const std::string& k,
224+
const std::string& v) {
225+
UpdateBooleanField(k, v,
226+
[&data](bool b) { data.verifyProxySsl = b; });
227+
}},
228+
{"verify-proxy-host",
229+
[this](CortexConfig& data, const std::string& k,
230+
const std::string& v) {
231+
UpdateBooleanField(
232+
k, v, [&data](bool b) { data.verifyProxyHostSsl = b; });
233+
}},
234+
{"proxy-username",
235+
[](CortexConfig& data, const std::string&, const std::string& v) {
236+
data.proxyUsername = v;
237+
}},
238+
{"proxy-password",
239+
[](CortexConfig& data, const std::string&, const std::string& v) {
240+
data.proxyPassword = v;
241+
}},
242+
{"no-proxy",
243+
[](CortexConfig& data, const std::string&, const std::string& v) {
244+
data.noProxy = v;
245+
}},
246+
{"verify-ssl-peer",
247+
[this](CortexConfig& data, const std::string& k,
248+
const std::string& v) {
249+
UpdateBooleanField(k, v,
250+
[&data](bool b) { data.verifyPeerSsl = b; });
251+
}},
252+
{"verify-ssl-host",
253+
[this](CortexConfig& data, const std::string& k,
254+
const std::string& v) {
255+
UpdateBooleanField(k, v,
256+
[&data](bool b) { data.verifyHostSsl = b; });
257+
}},
258+
{"ssl-cert-path",
259+
[](CortexConfig& data, const std::string&, const std::string& v) {
260+
data.sslCertPath = v;
261+
}},
262+
{"ssl-key-path",
263+
[](CortexConfig& data, const std::string&, const std::string& v) {
264+
data.sslKeyPath = v;
265+
}},
266+
};
267+
268+
if (auto it = updaters.find(key); it != updaters.end()) {
269+
it->second(data, key, value);
270+
CTL_INF("Updated " << key << " to: " << value);
271+
} else {
272+
CTL_WRN("Warning: Unknown configuration key '" << key << "' ignored.");
273+
}
274+
}
275+
276+
void ServerStartCmd::UpdateVectorField(
277+
const std::string& key, const std::string& value,
278+
std::function<void(const std::vector<std::string>&)> setter) {
279+
std::vector<std::string> tokens;
280+
std::istringstream iss(value);
281+
std::string token;
282+
while (std::getline(iss, token, ',')) {
283+
tokens.push_back(token);
284+
}
285+
setter(tokens);
286+
}
287+
288+
void ServerStartCmd::UpdateNumericField(const std::string& key,
289+
const std::string& value,
290+
std::function<void(float)> setter) {
291+
try {
292+
float numeric_val = std::stof(value);
293+
setter(numeric_val);
294+
} catch (const std::exception& e) {
295+
CLI_LOG("Failed to parse numeric value for " << key << ": " << e.what());
296+
}
297+
}
298+
299+
void ServerStartCmd::UpdateBooleanField(const std::string& key,
300+
const std::string& value,
301+
std::function<void(bool)> setter) {
302+
bool bool_value = (value == "true" || value == "1");
303+
setter(bool_value);
304+
}
305+
139306
}; // namespace commands

engine/cli/commands/server_start_cmd.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22

33
#include <optional>
44
#include <string>
5+
#include "utils/config_yaml_utils.h"
56
#include "utils/curl_utils.h"
67
#include "utils/logging_utils.h"
78
#include "utils/url_parser.h"
89

910
namespace commands {
11+
using CortexConfig = config_yaml_utils::CortexConfig;
1012

1113
inline bool IsServerAlive(const std::string& host, int port) {
1214
auto url = url_parser::Url{
@@ -26,5 +28,23 @@ class ServerStartCmd {
2628
public:
2729
bool Exec(const std::string& host, int port,
2830
const std::optional<std::string>& log_level = std::nullopt);
31+
32+
bool Exec(const std::optional<std::string>& log_level,
33+
const std::unordered_map<std::string, std::string>& options,
34+
CortexConfig& data);
35+
36+
private:
37+
void UpdateConfig(CortexConfig& data, const std::string& key,
38+
const std::string& value);
39+
40+
void UpdateVectorField(
41+
const std::string& key, const std::string& value,
42+
std::function<void(const std::vector<std::string>&)> setter);
43+
44+
void UpdateNumericField(const std::string& key, const std::string& value,
45+
std::function<void(float)> setter);
46+
47+
void UpdateBooleanField(const std::string& key, const std::string& value,
48+
std::function<void(bool)> setter);
2949
};
3050
} // namespace commands

0 commit comments

Comments
 (0)