diff --git a/README.md b/README.md
index 2c944815a..8ab39aba8 100644
--- a/README.md
+++ b/README.md
@@ -56,14 +56,18 @@ Cortex also has a [Network Installer](#network-installer) which downloads the ne
- For Linux: Download the installer and run the following command in terminal:
```bash
- sudo apt install ./cortex-local-installer.deb
+ # Linux debian based distros
+ curl -s https://raw.githubusercontent.com/janhq/cortex/main/engine/templates/linux/install.sh | sudo bash -s -- --deb_local
+
+ # Other Linux distros
+ curl -s https://raw.githubusercontent.com/janhq/cortex/main/engine/templates/linux/install.sh | sudo bash -s
```
- The binary will be installed in the `/usr/bin/` directory.
@@ -149,6 +153,28 @@ Select a model (1-9):
```
## Advanced Installation
+
+### Network Installer (Stable)
+
+Cortex.cpp is available with a Network Installer, which is a smaller installer but requires internet connection during installation to download the necessary dependencies.
+
+
+
+
+
+
### Beta & Nightly Versions (Local Installer)
@@ -163,7 +189,7 @@ Cortex releases Beta and Nightly versions for advanced users to try new features
Version |
Windows |
MacOS |
- Linux |
+ Linux debian based distros |
Beta (Preview) |
@@ -218,7 +244,7 @@ Cortex.cpp is available with a Network Installer, which is a smaller installer b
Version Type |
Windows |
MacOS |
- Linux |
+ Linux debian based distros |
Stable (Recommended) |
diff --git a/docs/docs/configurations/index.mdx b/docs/docs/configurations/index.mdx
index 38e7d8e92..fe3ab2f0e 100644
--- a/docs/docs/configurations/index.mdx
+++ b/docs/docs/configurations/index.mdx
@@ -8,5 +8,6 @@ title: Cortex configurations
Welcome to the Cortex configurations documentation. Here you will find detailed guides and references for configuring various aspects of Cortex, including:
- **CORS**: Learn how to set up Cross-Origin Resource Sharing.
+- **Proxy**: Configure the proxy for Cortex.
Use the sidebar to navigate through the different configuration topics.
diff --git a/docs/docs/configurations/proxy.mdx b/docs/docs/configurations/proxy.mdx
new file mode 100644
index 000000000..ccd3aa9dc
--- /dev/null
+++ b/docs/docs/configurations/proxy.mdx
@@ -0,0 +1,207 @@
+---
+title: Proxy
+description: Setting up Proxy
+slug: "proxy"
+---
+
+import Tabs from "@theme/Tabs";
+import TabItem from "@theme/TabItem";
+
+:::warning
+🚧 Cortex.cpp is currently under development. Our documentation outlines the intended behavior of Cortex, which may not yet be fully implemented in the codebase.
+:::
+
+# Proxy Configuration Guide
+
+This document describes how to configure proxy settings for Cortex to be able to work behind your proxy.
+
+## Command Line Interface (CLI)
+
+### Basic Usage
+
+```bash
+cortex config [OPTIONS] [COMMAND]
+```
+
+### Commands
+
+- `status`: Display all current configurations
+
+```bash
+cortex config status
+```
+
+Example Output:
+
+```bash
++-----------------------+------------------------+
+| Config name | Value |
++-----------------------+------------------------+
+| no_proxy | localhost,127.0.0.1 |
++-----------------------+------------------------+
+| proxy_password | |
++-----------------------+------------------------+
+| proxy_url | http://localhost:8080 |
++-----------------------+------------------------+
+| proxy_username | |
++-----------------------+------------------------+
+| verify_host_ssl | true |
++-----------------------+------------------------+
+| verify_peer_ssl | false |
++-----------------------+------------------------+
+| verify_proxy_host_ssl | true |
++-----------------------+------------------------+
+| verify_proxy_ssl | true |
++-----------------------+------------------------+
+```
+
+### Options
+
+| Option | Description | Example |
+| ----------------------------------- | --------------------------- | ------------------------------------------------- |
+| `-h, --help` | Print help message and exit |
+| `--proxy_url ` | Set the proxy URL | `cortex config --proxy_url http://localhost:8080` |
+| `--proxy_username ` | Set the username for proxy | `cortex config --proxy_username my_username` |
+| `--proxy_password ` | Set the password for proxy | `cortex config --proxy_password my_password` |
+| `--no_proxy ` | Set the no_proxy list | `cortex config --no_proxy localhost,127.0.0.1` |
+| `--verify_proxy_ssl [on/off]` | Verify proxy SSL | `cortex config --verify_proxy_ssl on` |
+| `--verify_proxy_host_ssl [on/off]` | Verify proxy host SSL | `cortex config --verify_proxy_host_ssl on` |
+| `--verify_peer_ssl [on/off]` | Verify peer SSL | `cortex config --verify_peer_ssl off` |
+| `--verify_host_ssl [on/off]` | Verify host SSL | `cortex config --verify_host_ssl on` |
+
+## Proxy API Configuration
+
+### Endpoints
+
+#### Get Current Configuration
+
+```http
+GET /v1/configs
+```
+
+Retrieves the current configuration settings.
+
+##### Response
+
+```json
+{
+ "allowed_origins": [
+ "http://localhost:39281",
+ "http://127.0.0.1:39281",
+ "http://0.0.0.0:39281"
+ ],
+ "cors": true,
+ "no_proxy": "localhost,127.0.0.1",
+ "proxy_password": "",
+ "proxy_url": "http://localhost:8080",
+ "proxy_username": "",
+ "verify_host_ssl": true,
+ "verify_peer_ssl": false,
+ "verify_proxy_host_ssl": true,
+ "verify_proxy_ssl": true
+}
+```
+
+#### Update Configuration
+
+```http
+PATCH /v1/configs
+```
+
+Updates proxy configuration settings.
+
+##### Request Headers
+
+```
+Content-Type: application/json
+```
+
+##### Request Body
+
+```json
+{
+ "no_proxy": "localhost",
+ "proxy_url": "http://localhost:8080",
+ "proxy_username": "my_username",
+ "proxy_password": "my_password",
+ "verify_host_ssl": false,
+ "verify_peer_ssl": false,
+ "verify_proxy_host_ssl": false,
+ "verify_proxy_ssl": false
+}
+```
+
+##### Parameters
+
+| Field | Type | Description |
+| ----------------------- | ------- | -------------------------------------------------------------------------------------- |
+| `no_proxy` | string | List of origins which request do not need to go through a proxy. Comma separated value |
+| `proxy_url` | string | Proxy URL |
+| `proxy_username` | string | Username for proxy authentication |
+| `proxy_password` | string | Password for proxy authentication |
+| `verify_host_ssl` | boolean | Verify host SSL |
+| `verify_peer_ssl` | boolean | Verify peer SSL |
+| `verify_proxy_host_ssl` | boolean | Verify proxy host SSL |
+| `verify_proxy_ssl` | boolean | Verify proxy SSL |
+
+##### Response
+
+```json
+{
+ "config": {
+ "allowed_origins": [
+ "http://localhost:39281",
+ "http://127.0.0.1:39281",
+ "http://0.0.0.0:39281"
+ ],
+ "cors": true,
+ "no_proxy": "localhost",
+ "proxy_password": "my_password",
+ "proxy_url": "http://localhost:8080",
+ "proxy_username": "my_username",
+ "verify_host_ssl": false,
+ "verify_peer_ssl": false,
+ "verify_proxy_host_ssl": false,
+ "verify_proxy_ssl": false
+ },
+ "message": "Configuration updated successfully"
+}
+```
+
+## Testing proxy configuration
+
+You can test your proxy configuration using [mitmproxy](https://docs.mitmproxy.org/stable). This guide is written on macOS, but you can use it on any other platform.
+
+### Install mitmproxy
+
+```bash
+brew install mitmproxy
+```
+
+### Start mitmproxy
+
+```bash
+mitmproxy --set stream_large_bodies=1m
+```
+
+mitmproxy will start on port `8080`. After mitmproxy started, you can adding options by pressing `O`. mitmproxy will display an option screen. You can check their document to learn more about mitmproxy. But let's take a simple option for now by setting the `proxyauth` for our local proxy. Inside the option screen, search for `proxyauth` and hit enter. Then, type `username:password` and hit enter again. You will see your newly added option is red-colored.
+
+### Configuring Cortex to use that proxy
+
+Let's using CLI to configure Cortex to use that proxy.
+
+```bash
+cortex config --proxy_url http://localhost:8080 --proxy_username username --proxy_password password
+```
+
+### Testing the proxy
+
+Now, let's test the proxy. If you are setting the username and password correctly (same with `proxyauth` in mitmproxy), you will see the request in mitmproxy. For example, command `cortex pull tinyllama` should be successfully and returns a list of selectable models. Also, you will see your request in mitmproxy CLI screen.
+
+Let's try to use a wrong authentication for your proxy.
+
+```bash
+cortex config --proxy_password wrong_pw
+```
+
+Now, let's test the proxy again. You will see the request is failed and returns an error.
diff --git a/docs/docs/configurations/token.mdx b/docs/docs/configurations/token.mdx
new file mode 100644
index 000000000..687879cb4
--- /dev/null
+++ b/docs/docs/configurations/token.mdx
@@ -0,0 +1,120 @@
+---
+title: Token
+description: Setting up token
+slug: "token"
+---
+
+import Tabs from "@theme/Tabs";
+import TabItem from "@theme/TabItem";
+
+:::warning
+🚧 Cortex.cpp is currently under development. Our documentation outlines the intended behavior of Cortex, which may not yet be fully implemented in the codebase.
+:::
+
+# Token Configuration Guide
+
+This document describes how to configure HuggingFace token settings for Cortex.
+
+## Command Line Interface (CLI)
+
+### Basic Usage
+
+```bash
+cortex config [OPTIONS] [COMMAND]
+```
+
+### Commands
+
+- `status`: Display all current configurations
+
+```bash
+cortex config status
+```
+
+Example Output:
+
+```bash
++-----------------------+------------------------+
+| Config name | Value |
++-----------------------+------------------------+
+| huggingface_token | |
++-----------------------+------------------------+
+```
+
+### Options
+
+| Option | Description | Example |
+| ----------------------------------- | --------------------------- | ------------------------------------------------- |
+| `-h, --help` | Print help message and exit |
+| `--huggingface_token ` | Set HuggingFace token | `cortex config --huggingface_token token` |
+
+## Token API Configuration
+
+### Endpoints
+
+#### Get Current Configuration
+
+```http
+GET /v1/configs
+```
+
+Retrieves the current configuration settings.
+
+##### Response
+
+```json
+{
+ "allowed_origins": [
+ "http://localhost:39281",
+ "http://127.0.0.1:39281",
+ "http://0.0.0.0:39281"
+ ],
+ "cors": true,
+ "huggingface_token": ""
+}
+```
+
+#### Update Configuration
+
+```http
+PATCH /v1/configs
+```
+
+Updates HuggingFace token configuration settings.
+
+##### Request Headers
+
+```
+Content-Type: application/json
+```
+
+##### Request Body
+
+```json
+{
+ "huggingface_token": "token"
+}
+```
+
+##### Parameters
+
+| Field | Type | Description |
+| ----------------------- | ------- | ------------------------------------------|
+| `huggingface_token` | string | HuggingFace token to pull models |
+
+##### Response
+
+```json
+{
+ "config": {
+ "allowed_origins": [
+ "http://localhost:39281",
+ "http://127.0.0.1:39281",
+ "http://0.0.0.0:39281"
+ ],
+ "cors": true,
+ "huggingface_token": "token"
+ },
+ "message": "Configuration updated successfully"
+}
+```
\ No newline at end of file
diff --git a/docs/docs/installation/linux.mdx b/docs/docs/installation/linux.mdx
index 23e538a52..a14450f47 100644
--- a/docs/docs/installation/linux.mdx
+++ b/docs/docs/installation/linux.mdx
@@ -20,43 +20,35 @@ This instruction is for stable releases. For beta and nightly releases, please r
### Prerequisites
- OpenMPI
+- curl
+- jq
+- tar
### Install Cortex.cpp
-1. Download the Linux installer:
- - From release: https://github.com/janhq/cortex.cpp/releases
- - From quick download links:
- - Local installer `.deb`:
- - Stable: https://app.cortexcpp.com/download/latest/linux-amd64-local
- - Beta: https://app.cortexcpp.com/download/beta/linux-amd64-local
- - Nightly: https://app.cortexcpp.com/download/nightly/linux-amd64-local
- - Network installer `.deb`:
- - Stable: https://app.cortexcpp.com/download/latest/linux-amd64-network
- - Beta: https://app.cortexcpp.com/download/beta/linux-amd64-network
- - Nightly: https://app.cortexcpp.com/download/nightly/linux-amd64-network
- - Binary:
- - Stable: https://app.cortexcpp.com/download/latest/linux-amd64-binary
- - Beta: https://app.cortexcpp.com/download/beta/linux-amd64-binary
- - Nightly: https://app.cortexcpp.com/download/nightly/linux-amd64-binary
-
-2. Install Cortex.cpp using the following command:
- ```bash
- # Installer
- sudo apt install ./cortex--linux-amd64-network-installer.deb
+1. Install cortex with one command
+- Linux debian base distros
+ ```bash
+ # Network installer
+ curl -s https://raw.githubusercontent.com/janhq/cortex/main/engine/templates/linux/install.sh | sudo bash -s
- # Binary
- tar -xvf cortex--linux-amd64.tar.gz
- cd cortex
- sudo mv cortex /usr/bin/cortex
- sudo chmod +x /usr/bin/Cortexs
- sudo mv cortex-server /usr/bin/cortex-server
+ # Local installer
+ curl -s https://raw.githubusercontent.com/janhq/cortex/main/engine/templates/linux/install.sh | sudo bash -s -- --deb_local
+ ```
- ## For binary, you need to install engine manually after extracting the binary
- cortex engines install llama-cpp
- ```
+- Other linux distros
+ ```bash
+ curl -s https://raw.githubusercontent.com/janhq/cortex/main/engine/templates/linux/install.sh | sudo bash -s
+ ```
+
+- Parameters
+ - `--channel ` cortex channel will be installed `stable`, `beta` or `nightly`. Default vaule is `stable`
+ - `--version ` version cortex want to install Ex `--version 1.0.2`. Default the script will get latest version of corresponding channel
+ - `--is_update` the current command run is for update
+ - `--deb_local` Using local installer for linux debian base distros
-3. Ensure that Cortex.cpp is sucessfulyy installed:
+2. Ensure that Cortex.cpp is sucessfulyy installed:
```bash
# Stable
cortex -v
@@ -79,7 +71,7 @@ By default, Cortex.cpp is installed in the following directory:
## Uninstall Cortex.cpp
```bash
# Stable version
-sudo apt remove cortexcpp
+sudo /usr/bin/cortex-uninstall.sh
```
## Build from Source
@@ -115,9 +107,10 @@ sudo apt remove cortexcpp
```
## Update cortex to latest version
-:::info
-The script requires sudo permission. Supported for debians based systems only (Ubuntu, Debian, etc).
+:::warning
+🚧 The script requires sudo permissions and works only if the user follows the installation instructions above or if the cortex binary file and the cortex-server binary file are installed in /usr/bin for all Linux distributions. If your binary files are located in a different folder, please manually update the binary files.
:::
+
```bash
sudo cortex update
```
\ No newline at end of file
diff --git a/docs/sidebars.ts b/docs/sidebars.ts
index 126673f1a..8c0800345 100644
--- a/docs/sidebars.ts
+++ b/docs/sidebars.ts
@@ -95,6 +95,16 @@ const sidebars: SidebarsConfig = {
id: "configurations/cors",
label: "CORS",
},
+ {
+ type: "doc",
+ id: "configurations/proxy",
+ label: "Proxy",
+ },
+ {
+ type: "doc",
+ id: "configurations/token",
+ label: "Token",
+ }
],
},
{
diff --git a/docs/static/openapi/cortex.json b/docs/static/openapi/cortex.json
index 9747a1830..1ac69d78e 100644
--- a/docs/static/openapi/cortex.json
+++ b/docs/static/openapi/cortex.json
@@ -1810,6 +1810,10 @@
"no_proxy": {
"type": "string",
"example": "localhost"
+ },
+ "huggingface_token": {
+ "type": "string",
+ "example": "your_token"
}
}
},
@@ -1826,7 +1830,8 @@
"verify_proxy_host_ssl": false,
"verify_peer_ssl": false,
"verify_host_ssl": false,
- "no_proxy": "localhost"
+ "no_proxy": "localhost",
+ "huggingface_token": "your_token"
}
}
}
@@ -1896,6 +1901,11 @@
"type": "string",
"description": "List of hosts that should not be proxied.",
"example": "localhost"
+ },
+ "huggingface_token": {
+ "type": "string",
+ "description": "HuggingFace token to pull models.",
+ "example": "your_token"
}
}
}
@@ -1958,6 +1968,10 @@
"no_proxy": {
"type": "string",
"example": "localhost"
+ },
+ "huggingface_token": {
+ "type": "string",
+ "example": "your_token"
}
}
},
diff --git a/engine/cli/commands/cortex_upd_cmd.cc b/engine/cli/commands/cortex_upd_cmd.cc
index 30d1ed3e2..231594346 100644
--- a/engine/cli/commands/cortex_upd_cmd.cc
+++ b/engine/cli/commands/cortex_upd_cmd.cc
@@ -36,9 +36,6 @@ std::unique_ptr GetSystemInfoWithUniversal() {
return system_info;
}
-// https://delta.jan.ai/cortex/v1.0.0-176/windows-amd64/cortex-1.0.0-176-windows-amd64-network-installer.exe
-// https://delta.jan.ai/cortex/v1.0.0-176/mac-universal/cortex-1.0.0-176-mac-universal-network-installer.pkg
-// https://delta.jan.ai/cortex/v1.0.0-176/linux-amd64/cortex-1.0.0-176-linux-amd64-network-installer.deb
std::string GetNightlyInstallerName(const std::string& v,
const std::string& os_arch) {
const std::string kCortex = "cortex";
@@ -53,13 +50,14 @@ std::string GetNightlyInstallerName(const std::string& v,
#endif
}
-// C:\Users\vansa\AppData\Local\Temp\cortex\cortex-windows-amd64-network-installer.exe
std::string GetInstallCmd(const std::string& exe_path) {
#if defined(__APPLE__) && defined(__MACH__)
- return "sudo touch /var/tmp/cortex_installer_skip_postinstall_check && sudo installer "
+ return "sudo touch /var/tmp/cortex_installer_skip_postinstall_check && sudo "
+ "installer "
"-pkg " +
exe_path +
- " -target / && sudo rm /var/tmp/cortex_installer_skip_postinstall_check";
+ " -target / && sudo rm "
+ "/var/tmp/cortex_installer_skip_postinstall_check";
#elif defined(__linux__)
return "echo -e \"n\\n\" | sudo SKIP_POSTINSTALL=true apt install -y "
"--allow-downgrades " +
@@ -70,8 +68,22 @@ std::string GetInstallCmd(const std::string& exe_path) {
#endif
}
+std::string GetInstallCmdLinux(const std::string& script_path,
+ const std::string& channel,
+ const std::string& version) {
+ std::string cmd = "sudo " + script_path;
+ if (!channel.empty()) {
+ cmd += " --channel " + channel;
+ }
+ if (!version.empty()) {
+ cmd += " --version " + version.substr(1);
+ }
+ return cmd + " --is_update";
+}
+
bool InstallNewVersion(const std::filesystem::path& dst,
- const std::string& exe_path) {
+ const std::string& exe_script_path,
+ const std::string& channel, const std::string& version) {
std::filesystem::path temp = dst.parent_path() / "cortex_temp";
auto restore_binary = [&temp, &dst]() {
if (std::filesystem::exists(temp)) {
@@ -86,7 +98,14 @@ bool InstallNewVersion(const std::filesystem::path& dst,
// rename binary
std::rename(dst.string().c_str(), temp.string().c_str());
// install here
- CommandExecutor c(GetInstallCmd(exe_path));
+ std::string install_cmd;
+#if defined(__linux__)
+ install_cmd = GetInstallCmdLinux(exe_script_path, channel, version);
+#else
+ install_cmd = GetInstallCmd(exe_script_path);
+#endif
+ CTL_INF("Cmd: " << install_cmd);
+ CommandExecutor c(install_cmd);
auto output = c.execute();
if (!std::filesystem::exists(dst)) {
CLI_LOG_ERROR("Something went wrong: could not execute command");
@@ -110,7 +129,6 @@ bool InstallNewVersion(const std::filesystem::path& dst,
}
return true;
}
-
} // namespace
std::optional CheckNewUpdate(
@@ -200,76 +218,6 @@ std::optional CheckNewUpdate(
return std::nullopt;
}
-bool ReplaceBinaryInflight(const std::filesystem::path& src,
- const std::filesystem::path& dst) {
- if (src == dst) {
- // Already has the newest
- return true;
- }
-
- std::filesystem::path temp = dst.parent_path() / "cortex_temp";
- auto restore_binary = [&temp, &dst]() {
- if (std::filesystem::exists(temp)) {
- std::rename(temp.string().c_str(), dst.string().c_str());
- CLI_LOG("Restored binary file");
- }
- };
-
- try {
- if (std::filesystem::exists(temp)) {
- std::filesystem::remove(temp);
- }
-#if !defined(_WIN32)
- // Get permissions of the executable file
- struct stat dst_file_stat;
- if (stat(dst.string().c_str(), &dst_file_stat) != 0) {
- CLI_LOG_ERROR(
- "Error getting permissions of executable file: " << dst.string());
- return false;
- }
-
- // Get owner and group of the executable file
- uid_t dst_file_owner = dst_file_stat.st_uid;
- gid_t dst_file_group = dst_file_stat.st_gid;
-#endif
-
- std::rename(dst.string().c_str(), temp.string().c_str());
- std::filesystem::copy_file(
- src, dst, std::filesystem::copy_options::overwrite_existing);
-
-#if !defined(_WIN32)
- // Set permissions of the executable file
- if (chmod(dst.string().c_str(), dst_file_stat.st_mode) != 0) {
- CLI_LOG_ERROR(
- "Error setting permissions of executable file: " << dst.string());
- restore_binary();
- return false;
- }
-
- // Set owner and group of the executable file
- if (chown(dst.string().c_str(), dst_file_owner, dst_file_group) != 0) {
- CLI_LOG_ERROR(
- "Error setting owner and group of executable file: " << dst.string());
- restore_binary();
- return false;
- }
-
- // Remove cortex_temp
- if (unlink(temp.string().c_str()) != 0) {
- CLI_LOG_ERROR("Error deleting self: " << strerror(errno));
- restore_binary();
- return false;
- }
-#endif
- } catch (const std::exception& e) {
- CLI_LOG_ERROR("Something went wrong: " << e.what());
- restore_binary();
- return false;
- }
-
- return true;
-}
-
void CortexUpdCmd::Exec(const std::string& v, bool force) {
// Check for update, if current version is the latest, notify to user
if (auto latest_version = commands::CheckNewUpdate(std::nullopt);
@@ -314,6 +262,9 @@ void CortexUpdCmd::Exec(const std::string& v, bool force) {
}
bool CortexUpdCmd::GetStable(const std::string& v) {
+#if defined(__linux__)
+ return GetLinuxInstallScript(v, "stable");
+#else
std::optional downloaded_exe_path;
auto system_info = GetSystemInfoWithUniversal();
CTL_INF("OS: " << system_info->os << ", Arch: " << system_info->arch);
@@ -366,10 +317,14 @@ bool CortexUpdCmd::GetStable(const std::string& v) {
});
assert(!!downloaded_exe_path);
- return InstallNewVersion(dst, downloaded_exe_path.value());
+ return InstallNewVersion(dst, downloaded_exe_path.value(), "", "");
+#endif
}
bool CortexUpdCmd::GetBeta(const std::string& v) {
+#if defined(__linux__)
+ return GetLinuxInstallScript(v, "beta");
+#else
std::optional downloaded_exe_path;
auto system_info = GetSystemInfoWithUniversal();
CTL_INF("OS: " << system_info->os << ", Arch: " << system_info->arch);
@@ -434,7 +389,8 @@ bool CortexUpdCmd::GetBeta(const std::string& v) {
});
assert(!!downloaded_exe_path);
- return InstallNewVersion(dst, downloaded_exe_path.value());
+ return InstallNewVersion(dst, downloaded_exe_path.value(), "", "");
+#endif
}
std::optional CortexUpdCmd::HandleGithubRelease(
@@ -500,6 +456,9 @@ std::optional CortexUpdCmd::HandleGithubRelease(
}
bool CortexUpdCmd::GetNightly(const std::string& v) {
+#if defined(__linux__)
+ return GetLinuxInstallScript(v, "nightly");
+#else
auto system_info = GetSystemInfoWithUniversal();
CTL_INF("OS: " << system_info->os << ", Arch: " << system_info->arch);
@@ -566,6 +525,82 @@ bool CortexUpdCmd::GetNightly(const std::string& v) {
}
});
- return InstallNewVersion(dst, localPath.string());
+ return InstallNewVersion(dst, localPath.string(), "", "");
+#endif
+}
+
+bool CortexUpdCmd::GetLinuxInstallScript(const std::string& v,
+ const std::string& channel) {
+ std::vector path_list;
+ if (channel == "nightly") {
+ path_list = {"janhq", "cortex.cpp", "dev", "engine",
+ "templates", "linux", "install.sh"};
+ } else {
+ path_list = {"janhq", "cortex.cpp", "main", "engine",
+ "templates", "linux", "install.sh"};
+ }
+ auto url_obj = url_parser::Url{
+ .protocol = "https",
+ .host = "raw.githubusercontent.com",
+ .pathParams = path_list,
+ };
+
+ CTL_INF("Linux installer script path: " << url_parser::FromUrl(url_obj));
+
+ std::filesystem::path localPath =
+ std::filesystem::temp_directory_path() / "cortex" / path_list.back();
+ try {
+ if (!std::filesystem::exists(localPath.parent_path())) {
+ std::filesystem::create_directories(localPath.parent_path());
+ }
+ } catch (const std::filesystem::filesystem_error& e) {
+ CLI_LOG_ERROR("Failed to create directories: " << e.what());
+ return false;
+ }
+ auto download_task =
+ DownloadTask{.id = "cortex",
+ .type = DownloadType::Cortex,
+ .items = {DownloadItem{
+ .id = "cortex",
+ .downloadUrl = url_parser::FromUrl(url_obj),
+ .localPath = localPath,
+ }}};
+
+ auto result = download_service_->AddDownloadTask(
+ download_task, [](const DownloadTask& finishedTask) {
+ // try to unzip the downloaded file
+ CTL_INF("Downloaded cortex path: "
+ << finishedTask.items[0].localPath.string());
+
+ CTL_INF("Finished!");
+ });
+ if (result.has_error()) {
+ CLI_LOG_ERROR("Failed to download: " << result.error());
+ return false;
+ }
+
+ auto executable_path = file_manager_utils::GetExecutableFolderContainerPath();
+ auto dst = executable_path / GetCortexBinary();
+ cortex::utils::ScopeExit se([]() {
+ auto cortex_tmp = std::filesystem::temp_directory_path() / "cortex";
+ try {
+ auto n = std::filesystem::remove_all(cortex_tmp);
+ CTL_INF("Deleted " << n << " files or directories");
+ } catch (const std::exception& e) {
+ CTL_WRN(e.what());
+ }
+ });
+ try {
+ std::filesystem::permissions(localPath,
+ std::filesystem::perms::owner_exec |
+ std::filesystem::perms::group_exec |
+ std::filesystem::perms::others_exec,
+ std::filesystem::perm_options::add);
+ } catch (const std::filesystem::filesystem_error& e) {
+ CTL_WRN("Error: " << e.what());
+ return false;
+ }
+
+ return InstallNewVersion(dst, localPath.string(), channel, v);
}
} // namespace commands
diff --git a/engine/cli/commands/cortex_upd_cmd.h b/engine/cli/commands/cortex_upd_cmd.h
index bd3fc51df..9c500a999 100644
--- a/engine/cli/commands/cortex_upd_cmd.h
+++ b/engine/cli/commands/cortex_upd_cmd.h
@@ -86,9 +86,6 @@ inline std::string GetReleasePath() {
std::optional CheckNewUpdate(
std::optional timeout);
-bool ReplaceBinaryInflight(const std::filesystem::path& src,
- const std::filesystem::path& dst);
-
// This class manages the 'cortex update' command functionality
// There are three release types available:
// - Stable: Only retrieves the latest version
@@ -109,5 +106,11 @@ class CortexUpdCmd {
std::optional HandleGithubRelease(const Json::Value& assets,
const std::string& os_arch);
bool GetNightly(const std::string& v);
+
+ // For Linux, we use different approach to update
+ // The installation bash script will perform the following tasks (all logic for update will be put into the bash script):
+ // - Detect whether the user is performing a new installation or an update.
+ // - Detect whether a .deb package needs to be installed or if the binary file should be installed directly.
+ bool GetLinuxInstallScript(const std::string& v, const std::string& channel);
};
} // namespace commands
diff --git a/engine/common/api_server_configuration.h b/engine/common/api_server_configuration.h
index 5bfcbbdc5..03b3022a4 100644
--- a/engine/common/api_server_configuration.h
+++ b/engine/common/api_server_configuration.h
@@ -90,6 +90,13 @@ static const std::unordered_map
.group = "Proxy",
.accept_value = "[on|off]",
.default_value = "on"}},
+ {"huggingface_token",
+ ApiConfigurationMetadata{.name = "huggingface_token",
+ .desc = "HuggingFace token to pull models",
+ .group = "Token",
+ .accept_value = "string",
+ .default_value = "",
+ .allow_empty = true}},
};
class ApiServerConfiguration {
@@ -99,7 +106,8 @@ class ApiServerConfiguration {
bool verify_proxy_ssl = true, bool verify_proxy_host_ssl = true,
const std::string& proxy_url = "", const std::string& proxy_username = "",
const std::string& proxy_password = "", const std::string& no_proxy = "",
- bool verify_peer_ssl = true, bool verify_host_ssl = true)
+ bool verify_peer_ssl = true, bool verify_host_ssl = true,
+ const std::string& hf_token = "")
: cors{cors},
allowed_origins{allowed_origins},
verify_proxy_ssl{verify_proxy_ssl},
@@ -109,7 +117,8 @@ class ApiServerConfiguration {
proxy_password{proxy_password},
no_proxy{no_proxy},
verify_peer_ssl{verify_peer_ssl},
- verify_host_ssl{verify_host_ssl} {}
+ verify_host_ssl{verify_host_ssl},
+ hf_token{hf_token} {}
// cors
bool cors{true};
@@ -127,6 +136,9 @@ class ApiServerConfiguration {
bool verify_peer_ssl{true};
bool verify_host_ssl{true};
+ // token
+ std::string hf_token{""};
+
Json::Value ToJson() const {
Json::Value root;
root["cors"] = cors;
@@ -142,6 +154,7 @@ class ApiServerConfiguration {
root["no_proxy"] = no_proxy;
root["verify_peer_ssl"] = verify_peer_ssl;
root["verify_host_ssl"] = verify_host_ssl;
+ root["huggingface_token"] = hf_token;
return root;
}
@@ -225,6 +238,15 @@ class ApiServerConfiguration {
return true;
}},
+ {"huggingface_token",
+ [this](const Json::Value& value) -> bool {
+ if (!value.isString()) {
+ return false;
+ }
+ hf_token = value.asString();
+ return true;
+ }},
+
{"cors",
[this](const Json::Value& value) -> bool {
if (!value.isBool()) {
diff --git a/engine/services/config_service.cc b/engine/services/config_service.cc
index 9c794bb38..ce5526090 100644
--- a/engine/services/config_service.cc
+++ b/engine/services/config_service.cc
@@ -6,10 +6,10 @@ cpp::result
ConfigService::UpdateApiServerConfiguration(const Json::Value& json) {
auto config = file_manager_utils::GetCortexConfig();
ApiServerConfiguration api_server_config{
- config.enableCors, config.allowedOrigins, config.verifyProxySsl,
- config.verifyProxyHostSsl, config.proxyUrl, config.proxyUsername,
- config.proxyPassword, config.noProxy, config.verifyPeerSsl,
- config.verifyHostSsl};
+ config.enableCors, config.allowedOrigins, config.verifyProxySsl,
+ config.verifyProxyHostSsl, config.proxyUrl, config.proxyUsername,
+ config.proxyPassword, config.noProxy, config.verifyPeerSsl,
+ config.verifyHostSsl, config.huggingFaceToken};
std::vector updated_fields;
std::vector invalid_fields;
@@ -35,6 +35,8 @@ ConfigService::UpdateApiServerConfiguration(const Json::Value& json) {
config.verifyPeerSsl = api_server_config.verify_peer_ssl;
config.verifyHostSsl = api_server_config.verify_host_ssl;
+ config.huggingFaceToken = api_server_config.hf_token;
+
auto result = file_manager_utils::UpdateCortexConfig(config);
return api_server_config;
}
@@ -43,8 +45,8 @@ cpp::result
ConfigService::GetApiServerConfiguration() {
auto config = file_manager_utils::GetCortexConfig();
return ApiServerConfiguration{
- config.enableCors, config.allowedOrigins, config.verifyProxySsl,
- config.verifyProxyHostSsl, config.proxyUrl, config.proxyUsername,
- config.proxyPassword, config.noProxy, config.verifyPeerSsl,
- config.verifyHostSsl};
+ config.enableCors, config.allowedOrigins, config.verifyProxySsl,
+ config.verifyProxyHostSsl, config.proxyUrl, config.proxyUsername,
+ config.proxyPassword, config.noProxy, config.verifyPeerSsl,
+ config.verifyHostSsl, config.huggingFaceToken};
}
diff --git a/engine/services/download_service.cc b/engine/services/download_service.cc
index c58935fe3..09c4d1a75 100644
--- a/engine/services/download_service.cc
+++ b/engine/services/download_service.cc
@@ -10,6 +10,7 @@
#include "utils/format_utils.h"
#include "utils/logging_utils.h"
#include "utils/result.hpp"
+#include "utils/string_utils.h"
namespace {
size_t WriteCallback(char* ptr, size_t size, size_t nmemb, void* userdata) {
@@ -75,6 +76,10 @@ void SetUpProxy(CURL* handle, std::shared_ptr config_service) {
CTL_INF("Verify host ssl: " << verify_host_ssl);
curl_easy_setopt(handle, CURLOPT_PROXY, proxy_url.c_str());
+ if (string_utils::StartsWith(proxy_url, "https")) {
+ curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTPS);
+ }
+
curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, verify_ssl ? 1L : 0L);
curl_easy_setopt(handle, CURLOPT_SSL_VERIFYHOST,
verify_host_ssl ? 2L : 0L);
diff --git a/engine/templates/linux/install.sh b/engine/templates/linux/install.sh
index e907150a8..e11b879c6 100644
--- a/engine/templates/linux/install.sh
+++ b/engine/templates/linux/install.sh
@@ -278,4 +278,4 @@ fi
install_cortex $CHANNEL $VERSION $IS_DEB
create_uninstall_script $IS_DEB
-echo "Installation complete. Run cortex-uninstall.sh to uninstall."
\ No newline at end of file
+echo "Installation complete. Run cortex-uninstall.sh to uninstall."
diff --git a/engine/test/components/test_cortex_upd_cmd.cc b/engine/test/components/test_cortex_upd_cmd.cc
index a8815f4f4..772889fbd 100644
--- a/engine/test/components/test_cortex_upd_cmd.cc
+++ b/engine/test/components/test_cortex_upd_cmd.cc
@@ -34,37 +34,3 @@ class CortexUpdCmdTest : public ::testing::Test {
}
}
};
-
-TEST_F(CortexUpdCmdTest, return_true_if_self_replace) {
- EXPECT_TRUE(commands::ReplaceBinaryInflight("test", "test"));
-}
-
-TEST_F(CortexUpdCmdTest, replace_binary_successfully) {
- std::filesystem::path new_binary(kNewReleaseFile);
- std::filesystem::path cur_binary(kCurReleaseFile);
-#if !defined(_WIN32)
- struct stat cur_file_stat;
- EXPECT_TRUE(stat(cur_binary.string().c_str(), &cur_file_stat) == 0);
-#endif
-
- EXPECT_TRUE(commands::ReplaceBinaryInflight(new_binary, cur_binary));
-
-#if !defined(_WIN32)
- EXPECT_FALSE(std::filesystem::exists(kCortexTemp));
-
- struct stat new_file_stat;
- EXPECT_TRUE(stat(cur_binary.string().c_str(), &new_file_stat) == 0);
- EXPECT_EQ(cur_file_stat.st_uid, new_file_stat.st_uid);
- EXPECT_EQ(cur_file_stat.st_gid, new_file_stat.st_gid);
- EXPECT_EQ(cur_file_stat.st_mode, new_file_stat.st_mode);
-#else
- EXPECT_TRUE(std::filesystem::exists(kCortexTemp));
-#endif
-}
-
-TEST_F(CortexUpdCmdTest, should_restore_old_binary_if_has_error) {
- std::filesystem::path new_binary("Non-exist");
- std::filesystem::path cur_binary(kCurReleaseFile);
- EXPECT_FALSE(commands::ReplaceBinaryInflight(new_binary, cur_binary));
- EXPECT_FALSE(std::filesystem::exists(kCortexTemp));
-}
\ No newline at end of file
diff --git a/engine/utils/config_yaml_utils.h b/engine/utils/config_yaml_utils.h
index 3dc6bc61f..6b1660467 100644
--- a/engine/utils/config_yaml_utils.h
+++ b/engine/utils/config_yaml_utils.h
@@ -57,7 +57,7 @@ constexpr const auto kDefaultLatestLlamacppRelease = "";
constexpr const auto kDefaultCorsEnabled = true;
const std::vector kDefaultEnabledOrigins{
"http://localhost:39281", "http://127.0.0.1:39281", "http://0.0.0.0:39281"};
-constexpr const auto kDefaultNoProxy = "localhost,127.0.0.1";
+constexpr const auto kDefaultNoProxy = "example.com,::1,localhost,127.0.0.1";
inline cpp::result DumpYamlConfig(const CortexConfig& config,
const std::string& path) {
diff --git a/engine/utils/curl_utils.h b/engine/utils/curl_utils.h
index 34fa634b5..7bfbec44c 100644
--- a/engine/utils/curl_utils.h
+++ b/engine/utils/curl_utils.h
@@ -10,6 +10,7 @@
#include "utils/file_manager_utils.h"
#include "utils/logging_utils.h"
#include "utils/result.hpp"
+#include "utils/string_utils.h"
#include "utils/url_parser.h"
enum class RequestType { GET, PATCH, POST, DEL };
@@ -24,7 +25,7 @@ size_t WriteCallback(void* contents, size_t size, size_t nmemb,
return totalSize;
}
-void SetUpProxy(CURL* handle) {
+void SetUpProxy(CURL* handle, const std::string& url) {
auto config = file_manager_utils::GetCortexConfig();
if (!config.proxyUrl.empty()) {
auto proxy_url = config.proxyUrl;
@@ -39,13 +40,18 @@ void SetUpProxy(CURL* handle) {
auto no_proxy = config.noProxy;
CTL_INF("=== Proxy configuration ===");
+ CTL_INF("Request url: " << url);
CTL_INF("Proxy url: " << proxy_url);
CTL_INF("Verify proxy ssl: " << verify_proxy_ssl);
CTL_INF("Verify proxy host ssl: " << verify_proxy_host_ssl);
CTL_INF("Verify ssl: " << verify_ssl);
CTL_INF("Verify host ssl: " << verify_host_ssl);
+ CTL_INF("No proxy: " << no_proxy);
curl_easy_setopt(handle, CURLOPT_PROXY, proxy_url.c_str());
+ if (string_utils::StartsWith(proxy_url, "https")) {
+ curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTPS);
+ }
curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, verify_ssl ? 1L : 0L);
curl_easy_setopt(handle, CURLOPT_SSL_VERIFYHOST, verify_host_ssl ? 2L : 0L);
@@ -88,7 +94,7 @@ inline cpp::result SimpleGet(const std::string& url,
std::string readBuffer;
- SetUpProxy(curl);
+ SetUpProxy(curl, url);
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
@@ -139,7 +145,7 @@ inline cpp::result SimpleRequest(
}
std::string readBuffer;
- SetUpProxy(curl);
+ SetUpProxy(curl, url);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers);
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
if (request_type == RequestType::PATCH) {