Skip to content
This repository was archived by the owner on Jul 4, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions engine/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ if(DEBUG)
add_compile_definitions(ALLOW_ALL_CORS)
endif()

if(NOT DEFINED CORTEX_CPP_VERSION)
set(CORTEX_CPP_VERSION "default_version")
if(CORTEX_CPP_VERSION)
add_compile_definitions(CORTEX_CPP_VERSION="${CORTEX_CPP_VERSION}")
endif()

if(APPLE)
Expand Down
167 changes: 167 additions & 0 deletions engine/commands/cortex_upd_cmd.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
// clang-format off
#include "utils/cortex_utils.h"
// clang-format on
#include "cortex_upd_cmd.h"
#include "httplib.h"
#include "nlohmann/json.hpp"
#include "services/download_service.h"
#include "utils/archive_utils.h"
#include "utils/logging_utils.h"
#include "utils/system_info_utils.h"
#if defined(_WIN32) || defined(__linux__)
#include "utils/file_manager_utils.h"
#endif

namespace commands {

namespace {
const std::string kCortexBinary = "cortex-cpp";
}

CortexUpdCmd::CortexUpdCmd() {}

void CortexUpdCmd::Exec(std::string v) {
// Check if the architecture and OS are supported
auto system_info = system_info_utils::GetSystemInfo();
if (system_info.arch == system_info_utils::kUnsupported ||
system_info.os == system_info_utils::kUnsupported) {
CTL_ERR("Unsupported OS or architecture: " << system_info.os << ", "
<< system_info.arch);
return;
}
CTL_INF("OS: " << system_info.os << ", Arch: " << system_info.arch);

// Download file
constexpr auto github_host = "https://api.github.com";
// std::string version = v.empty() ? "latest" : std::move(v);
// TODO(sang): support download with version
std::string version = "latest";
std::ostringstream release_path;
release_path << "/repos/janhq/cortex.cpp/releases/" << version;
CTL_INF("Engine release path: " << github_host << release_path.str());

httplib::Client cli(github_host);
if (auto res = cli.Get(release_path.str())) {
if (res->status == httplib::StatusCode::OK_200) {
try {
auto jsonResponse = nlohmann::json::parse(res->body);
auto assets = jsonResponse["assets"];
auto os_arch{system_info.os + "-" + system_info.arch};

std::string matched_variant = "";
for (auto& asset : assets) {
auto asset_name = asset["name"].get<std::string>();
if (asset_name.find("cortex-cpp") != std::string::npos &&
asset_name.find(os_arch) != std::string::npos) {
matched_variant = asset_name;
break;
}
CTL_INF(asset_name);
}
if (matched_variant.empty()) {
CTL_ERR("No variant found for " << os_arch);
return;
}
CTL_INF("Matched variant: " << matched_variant);

for (auto& asset : assets) {
auto asset_name = asset["name"].get<std::string>();
if (asset_name == matched_variant) {
std::string host{"https://github.com"};

auto full_url = asset["browser_download_url"].get<std::string>();
std::string path = full_url.substr(host.length());

auto fileName = asset["name"].get<std::string>();
CTL_INF("URL: " << full_url);

auto download_task = DownloadTask{.id = "cortex",
.type = DownloadType::Cortex,
.error = std::nullopt,
.items = {DownloadItem{
.id = "cortex",
.host = host,
.fileName = fileName,
.type = DownloadType::Cortex,
.path = path,
}}};

DownloadService download_service;
download_service.AddDownloadTask(
download_task,
[this](const std::string& absolute_path, bool unused) {
// try to unzip the downloaded file
std::filesystem::path download_path{absolute_path};
CTL_INF("Downloaded engine path: " << download_path.string());

std::filesystem::path extract_path =
download_path.parent_path().parent_path();

archive_utils::ExtractArchive(download_path.string(),
extract_path.string());

// remove the downloaded file
// TODO(any) Could not delete file on Windows because it is currently hold by httplib(?)
// Not sure about other platforms
try {
std::filesystem::remove(absolute_path);
} catch (const std::exception& e) {
CTL_WRN("Could not delete file: " << e.what());
}
CTL_INF("Finished!");
});
break;
}
}
} catch (const nlohmann::json::parse_error& e) {
std::cerr << "JSON parse error: " << e.what() << std::endl;
return;
}
} else {
CTL_ERR("HTTP error: " << res->status);
return;
}
} else {
auto err = res.error();
CTL_ERR("HTTP error: " << httplib::to_string(err));
return;
}
#if defined(_WIN32)
std::string temp = ".\\cortex_tmp.exe";
remove(temp.c_str()); // ignore return code

std::string src =
".\\cortex\\" + kCortexBinary + "\\" + kCortexBinary + ".exe";
std::string dst = ".\\" + kCortexBinary + ".exe";
// Rename
rename(dst.c_str(), temp.c_str());
// Update
CopyFile(const_cast<char*>(src.c_str()), const_cast<char*>(dst.c_str()),
false);
remove(".\\cortex");
remove(temp.c_str());
#else
std::string temp = "./cortex_tmp";
std::string src = "./cortex/" + kCortexBinary + "/" + kCortexBinary;
std::string dst = "./" + kCortexBinary;
if (std::rename(dst.c_str(), temp.c_str())) {
CTL_ERR("Failed to rename from " << dst << " to " << temp);
return;
}
try {
std::filesystem::copy_file(
src, dst, std::filesystem::copy_options::overwrite_existing);
std::filesystem::permissions(dst, std::filesystem::perms::owner_all |
std::filesystem::perms::group_all |
std::filesystem::perms::others_read |
std::filesystem::perms::others_exec);
std::filesystem::remove(temp);
std::filesystem::remove_all("./cortex/");
} catch (const std::exception& e) {
CTL_WRN("Something wrong happened: " << e.what());
return;
}
#endif
CLI_LOG("Update cortex sucessfully");
}
} // namespace commands
15 changes: 15 additions & 0 deletions engine/commands/cortex_upd_cmd.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#pragma once
#include <string>
#include <optional>

namespace commands {

class CortexUpdCmd{
public:
CortexUpdCmd();
void Exec(std::string version);

private:
};

} // namespace commands
63 changes: 62 additions & 1 deletion engine/controllers/command_line_parser.cc
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
#include "command_line_parser.h"
#include "commands/chat_cmd.h"
#include "commands/cmd_info.h"
#include "commands/cortex_upd_cmd.h"
#include "commands/engine_init_cmd.h"
#include "commands/engine_list_cmd.h"
#include "commands/model_get_cmd.h"
#include "commands/model_list_cmd.h"
#include "commands/model_pull_cmd.h"
#include "commands/model_start_cmd.h"
#include "commands/run_cmd.h"
#include "commands/model_stop_cmd.h"
#include "commands/run_cmd.h"
#include "commands/server_stop_cmd.h"
#include "config/yaml_config.h"
#include "httplib.h"
#include "utils/cortex_utils.h"
#include "utils/logging_utils.h"

CommandLineParser::CommandLineParser() : app_("Cortex.cpp CLI") {}

bool CommandLineParser::SetupCommand(int argc, char** argv) {

std::string model_id;

// Models group commands
Expand Down Expand Up @@ -153,7 +156,65 @@ bool CommandLineParser::SetupCommand(int argc, char** argv) {

app_.add_flag("--verbose", log_verbose, "Verbose logging");

// cortex version
auto cb = [&](int c) {
#ifdef CORTEX_CPP_VERSION
CLI_LOG(CORTEX_CPP_VERSION);
#else
CLI_LOG("default");
#endif
};
app_.add_flag_function("-v", cb, "Cortex version");

std::string cortex_version;
bool check_update = true;
{
auto update_cmd = app_.add_subcommand("update", "Update cortex version");

update_cmd->add_option("-v", cortex_version, "");
update_cmd->callback([&cortex_version, &check_update] {
commands::CortexUpdCmd cuc;
cuc.Exec(cortex_version);
check_update = false;
});
}

CLI11_PARSE(app_, argc, argv);

// Check new update, only check for stable release for now
#ifdef CORTEX_CPP_VERSION
if (check_update) {
constexpr auto github_host = "https://api.github.com";
std::ostringstream release_path;
release_path << "/repos/janhq/cortex.cpp/releases/latest";
CTL_INF("Engine release path: " << github_host << release_path.str());

httplib::Client cli(github_host);
if (auto res = cli.Get(release_path.str())) {
if (res->status == httplib::StatusCode::OK_200) {
try {
auto json_res = nlohmann::json::parse(res->body);
std::string latest_version = json_res["tag_name"].get<std::string>();
std::string current_version = CORTEX_CPP_VERSION;
if (current_version != latest_version) {
CLI_LOG("\nA new release of cortex is available: "
<< current_version << " -> " << latest_version);
CLI_LOG("To upgrade, run: cortex update");
CLI_LOG(json_res["html_url"].get<std::string>());
}
} catch (const nlohmann::json::parse_error& e) {
CTL_INF("JSON parse error: " << e.what());
}
} else {
CTL_INF("HTTP error: " << res->status);
}
} else {
auto err = res.error();
CTL_INF("HTTP error: " << httplib::to_string(err));
}
}
#endif

return true;
}

Expand Down
2 changes: 1 addition & 1 deletion engine/services/download_service.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include <optional>
#include <vector>

enum class DownloadType { Model, Engine, Miscellaneous, CudaToolkit };
enum class DownloadType { Model, Engine, Miscellaneous, CudaToolkit, Cortex };

enum class DownloadStatus {
Pending,
Expand Down
6 changes: 5 additions & 1 deletion engine/utils/file_manager_utils.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#pragma once
#include "logging_utils.h"
#include <filesystem>
#include <string>
#include <string_view>
#include "logging_utils.h"

#if defined(__APPLE__) && defined(__MACH__)
#include <mach-o/dyld.h>
Expand Down Expand Up @@ -61,6 +61,8 @@ inline std::filesystem::path GetContainerFolderPath(
container_folder_path = current_path / "engines";
} else if (type == "CudaToolkit") {
container_folder_path = current_path;
} else if (type == "Cortex") {
container_folder_path = current_path / "cortex";
} else {
container_folder_path = current_path / "misc";
}
Expand All @@ -83,6 +85,8 @@ inline std::string downloadTypeToString(DownloadType type) {
return "Misc";
case DownloadType::CudaToolkit:
return "CudaToolkit";
case DownloadType::Cortex:
return "Cortex";
default:
return "UNKNOWN";
}
Expand Down
3 changes: 2 additions & 1 deletion engine/utils/logging_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ inline bool log_verbose = false;
LOG_INFO << msg; \
} else { \
std::cout << msg << std::endl; \
}
}