-
Notifications
You must be signed in to change notification settings - Fork 207
I've integrated the Rust backend for process management and API proxy- #213
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 2 commits
b382be7
4da3fe0
0cdd5a6
78a0911
84ce290
d4e59b6
0ac7c01
8938ea8
8297e10
1f7cb2f
9399c2a
bf3598e
009e03e
8f22f3f
1d156d3
09621db
8881db0
e9939b6
a7afd93
ea0364a
a9f9b55
c33b59d
9c92a01
cf98e74
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| # Deployment Guide: Running Amica Locally | ||
|
|
||
| This guide provides step-by-step instructions for setting up and running the Rust-powered version of Amica on your local machine. | ||
|
|
||
| ## 1. Prerequisites | ||
|
|
||
| Before you begin, you need to have the following software installed on your system: | ||
|
|
||
| * **Node.js:** Amica's user interface is built with Node.js. You will need version `18.18.0` or newer. You can download it from the [official Node.js website](https://nodejs.org/). | ||
| * **Rust:** The new backend is written in Rust. The easiest way to install Rust is by using `rustup`. You can find instructions at the [official Rust website](https://www.rust-lang.org/tools/install). | ||
| * **`text-generation-webui`:** You must have a working, pre-compiled version of `text-generation-webui`. You can find releases and setup instructions on its [GitHub repository](https://github.com/oobabooga/text-generation-webui). Make sure you can run it successfully on its own before integrating it with Amica. | ||
| * **(Linux Only) Build Dependencies:** On Linux, you will need to install a few extra packages for Tauri to build correctly. You can install them with the following command: | ||
| ```bash | ||
| sudo apt-get update | ||
| sudo apt-get install -y libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev | ||
| ``` | ||
AlphaEcho11 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| ## 2. Installation and Configuration | ||
|
|
||
| Follow these steps to get the Amica project set up. | ||
|
|
||
| #### Step 1: Clone the Amica Repository | ||
|
|
||
| Open your terminal, navigate to where you want to store the project, and run the following command: | ||
|
|
||
| ```bash | ||
| git clone https://github.com/semperai/amica | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Need to look at the temp/final git location - for now, should be the current project at: https://github.com/AlphaEcho11/amica |
||
| cd amica | ||
| ``` | ||
|
|
||
| #### Step 2: Install JavaScript Dependencies | ||
|
|
||
| Once you are in the `amica` directory, run this command to install all the necessary frontend packages: | ||
|
|
||
| ```bash | ||
| npm install | ||
| ``` | ||
|
|
||
| #### Step 3: Configure the `text-generation-webui` Path | ||
AlphaEcho11 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| The application needs to know where to find your `text-generation-webui` executable. This is configured using a `settings.json` file. | ||
|
|
||
| 1. In the root of the `amica` project directory, you will find a `settings.json` file. For the final packaged application, you must place this `settings.json` file in the same directory as the Amica executable. | ||
| 2. Open the file. It will look like this: | ||
| ```json | ||
| { | ||
| "text_generation_webui_path": "" | ||
| } | ||
| ``` | ||
|
Comment on lines
+66
to
+69
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Document the configurable proxy port setting The backend now supports a configurable proxy port, but the documentation only shows the path configuration. ```json
{
- "text_generation_webui_path": ""
+ "text_generation_webui_path": "",
+ "proxy_port": 5000
}
```Add a note explaining the proxy_port field: 4. Add the **full path** to your `text-generation-webui` executable inside the quotes.
+ The `proxy_port` field (default: 5000) specifies which port the text-generation-webui API server is listening on.🤖 Prompt for AI Agents |
||
| 3. Add the **full path** to your executable inside the quotes. | ||
|
|
||
| * **Windows Example:** | ||
| ```json | ||
| { | ||
| "text_generation_webui_path": "C:\\Users\\YourUser\\Desktop\\text-generation-webui\\start.bat" | ||
| } | ||
| ``` | ||
|
Comment on lines
+75
to
+78
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Update examples to include proxy_port The examples should reflect the complete settings structure. ```json
{
- "text_generation_webui_path": "C:\\Users\\YourUser\\Desktop\\text-generation-webui\\start.bat"
+ "text_generation_webui_path": "C:\\Users\\YourUser\\Desktop\\text-generation-webui\\start.bat",
+ "proxy_port": 5000
}
``` ```json
{
- "text_generation_webui_path": "/home/youruser/text-generation-webui/start.sh"
+ "text_generation_webui_path": "/home/youruser/text-generation-webui/start.sh",
+ "proxy_port": 5000
}
```Also applies to: 83-85 🤖 Prompt for AI Agents |
||
| *(Note the double backslashes `\\`)* | ||
|
|
||
| * **Linux/macOS Example:** | ||
| ```json | ||
| { | ||
| "text_generation_webui_path": "/home/youruser/text-generation-webui/start.sh" | ||
| } | ||
| ``` | ||
|
|
||
| > **Important Note:** Amica always reads `settings.json` from the **current working directory (CWD)** from which it is launched. It does not use OS-specific configuration paths (e.g., `%APPDATA%` or `~/.config`). This applies to both development runs (`npm run tauri dev`) and when running the final packaged application. For the packaged application, this usually means placing `settings.json` next to the executable file. | ||
|
|
||
| ## 3. Building the Application | ||
|
|
||
| Now that everything is configured, you can build the final, standalone executable. | ||
|
|
||
| Run the following command in your terminal. This process will compile the Rust backend and package it with the frontend into a single application. It may take several minutes. | ||
|
|
||
| ```bash | ||
| npm run tauri build | ||
| ``` | ||
|
|
||
| Once the build is complete, you will find the final application inside the `src-tauri/target/release/` directory. It will be a `.exe` file on Windows, a `.AppImage` on Linux, or a `.app` file inside a `.dmg` on macOS. | ||
coderabbitai[bot] marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ## 4. Running Amica | ||
|
|
||
| You can now run this executable file directly! There is no need for any further commands. | ||
|
|
||
| On the first run, be sure to open the in-app settings and configure the following: | ||
| * **Chatbot Backend:** Select **KoboldAI**. | ||
| * **Streaming/Extra Option:** If you see an option for streaming, make sure it is **disabled**. | ||
|
|
||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| That's it! Your self-contained, Rust-powered Amica application is now ready to use. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "text_generation_webui_path": "" | ||
| } | ||
AlphaEcho11 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,52 +2,176 @@ | |||||||||||||||
| #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] | ||||||||||||||||
|
|
||||||||||||||||
| use tauri::{ | ||||||||||||||||
| CustomMenuItem, | ||||||||||||||||
| SystemTray, | ||||||||||||||||
| SystemTrayEvent, | ||||||||||||||||
| SystemTrayMenu, | ||||||||||||||||
| SystemTrayMenuItem, | ||||||||||||||||
| api::process::{Command, CommandEvent}, | ||||||||||||||||
| CustomMenuItem, Manager, SystemTray, SystemTrayEvent, SystemTrayMenu, SystemTrayMenuItem, | ||||||||||||||||
| }; | ||||||||||||||||
| use tauri::Manager; | ||||||||||||||||
| use std::sync::Mutex; | ||||||||||||||||
| use std::fs; | ||||||||||||||||
|
|
||||||||||||||||
| #[derive(serde::Deserialize, Clone)] | ||||||||||||||||
| struct Settings { | ||||||||||||||||
| text_generation_webui_path: String, | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| // the payload type must implement `Serialize` and `Clone`. | ||||||||||||||||
| #[derive(Clone, serde::Serialize)] | ||||||||||||||||
| struct Payload { | ||||||||||||||||
| message: String, | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| struct AppState { | ||||||||||||||||
| child_process: Mutex<Option<tauri::api::process::Child>>, | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| #[tauri::command] | ||||||||||||||||
| async fn close_splashscreen(window: tauri::Window) { | ||||||||||||||||
| // Close splashscreen | ||||||||||||||||
| window.get_window("splashscreen").expect("no window labeled 'splashscreen' found").close().unwrap(); | ||||||||||||||||
| if let Some(splashscreen) = window.get_window("splashscreen") { | ||||||||||||||||
| splashscreen.close().unwrap(); | ||||||||||||||||
| } | ||||||||||||||||
| // Show main window | ||||||||||||||||
| window.get_window("main").expect("no window labeled 'main' found").show().unwrap(); | ||||||||||||||||
| window.get_window("main").unwrap().show().unwrap(); | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| #[derive(serde::Deserialize)] | ||||||||||||||||
| struct ProxyRequestPayload { | ||||||||||||||||
| path: String, | ||||||||||||||||
| body: serde_json::Value, | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| #[tauri::command] | ||||||||||||||||
| async fn proxy_request(payload: ProxyRequestPayload) -> Result<serde_json::Value, String> { | ||||||||||||||||
| let client = reqwest::Client::new(); | ||||||||||||||||
| // This port should be configurable in the future. | ||||||||||||||||
| let url = format!("http://127.0.0.1:5000/{}", payload.path); | ||||||||||||||||
AlphaEcho11 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||
|
|
||||||||||||||||
| let res = client | ||||||||||||||||
| .post(&url) | ||||||||||||||||
| .json(&payload.body) | ||||||||||||||||
| .send() | ||||||||||||||||
| .await | ||||||||||||||||
| .map_err(|e| e.to_string())?; | ||||||||||||||||
|
|
||||||||||||||||
| if res.status().is_success() { | ||||||||||||||||
| res.json::<serde_json::Value>() | ||||||||||||||||
| .await | ||||||||||||||||
| .map_err(|e| e.to_string()) | ||||||||||||||||
| } else { | ||||||||||||||||
| let status = res.status(); | ||||||||||||||||
| let text = res.text().await.map_err(|e| e.to_string())?; | ||||||||||||||||
| Err(format!( | ||||||||||||||||
| "API request to {} failed with status {}: {}", | ||||||||||||||||
| url, status, text | ||||||||||||||||
| )) | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||
|
|
||||||||||||||||
| fn main() { | ||||||||||||||||
| tauri::Builder::default() | ||||||||||||||||
| .system_tray(SystemTray::new() | ||||||||||||||||
| .with_menu(SystemTrayMenu::new() | ||||||||||||||||
| .add_item(CustomMenuItem::new("checkforupdates".to_string(), "Check for updates")) | ||||||||||||||||
| .add_native_item(SystemTrayMenuItem::Separator) | ||||||||||||||||
| .add_item(CustomMenuItem::new("help".to_string(), "Help")) | ||||||||||||||||
| .add_native_item(SystemTrayMenuItem::Separator) | ||||||||||||||||
| .add_item(CustomMenuItem::new("quit".to_string(), "Quit")) | ||||||||||||||||
| ) | ||||||||||||||||
| ) | ||||||||||||||||
| .on_system_tray_event(|app, event| match event { | ||||||||||||||||
| SystemTrayEvent::MenuItemClick { id, .. } => { | ||||||||||||||||
| match id.as_str() { | ||||||||||||||||
| "quit" => { | ||||||||||||||||
| std::process::exit(0); | ||||||||||||||||
| } | ||||||||||||||||
| "checkforupdates" => { | ||||||||||||||||
| tauri::api::shell::open(&app.shell_scope(), "https://github.com/semperai/amica/releases/latest", None).expect("failed to open url"); | ||||||||||||||||
| } | ||||||||||||||||
| "help" => { | ||||||||||||||||
| tauri::api::shell::open(&app.shell_scope(), "https://docs.heyamica.com", None).expect("failed to open url"); | ||||||||||||||||
| } | ||||||||||||||||
| _ => {} | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
| _ => {} | ||||||||||||||||
| }) | ||||||||||||||||
| .invoke_handler(tauri::generate_handler![close_splashscreen]) | ||||||||||||||||
| .run(tauri::generate_context!()) | ||||||||||||||||
| .expect("error while running tauri application"); | ||||||||||||||||
| let app_state = AppState { | ||||||||||||||||
| child_process: Mutex::new(None), | ||||||||||||||||
| }; | ||||||||||||||||
|
|
||||||||||||||||
| tauri::Builder::default() | ||||||||||||||||
| .manage(app_state) | ||||||||||||||||
| .setup(|app| { | ||||||||||||||||
| let handle = app.handle(); | ||||||||||||||||
| let app_state = handle.state::<AppState>(); | ||||||||||||||||
|
|
||||||||||||||||
| // Read settings | ||||||||||||||||
| let settings_path = "settings.json"; | ||||||||||||||||
| let settings_str = fs::read_to_string(settings_path) | ||||||||||||||||
|
||||||||||||||||
| let settings_path = "settings.json"; | |
| let settings_str = fs::read_to_string(settings_path) | |
| // Read settings | |
| let settings_path = app.path_resolver() | |
| .resolve_resource("settings.json") | |
| .ok_or("Failed to resolve settings.json path")?; | |
| let settings_str = fs::read_to_string(settings_path) |
🤖 Prompt for AI Agents
In src-tauri/src/main.rs around lines 81 to 82, the code uses a hardcoded
relative path "settings.json" which breaks if the app is launched from a
different CWD; replace this with the application's resource directory path
(e.g., obtain the app resource dir via tauri::api::path::resource_dir() or the
app handle/path resolver, join "settings.json" to that PathBuf, and read that
full path with fs::read_to_string); also handle the Option/Result (return an
error or fallback) so the app fails gracefully if the resource dir or file is
missing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've taken a close look at the current implementation in main.rs to ensure it follows this best practice. The code currently uses handle.path_resolver().resolve_resource("resources/settings.json").
Good news - this is Tauri's recommended API for exactly this purpose! It correctly resolves the path to the bundled resource file regardless of where the application is launched from. So, it seems the code is already robust against the CWD issue you've described.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@AlphaEcho11 You're absolutely right! I apologize for the confusion. Looking at the current implementation in the file, I can see that the code already properly handles the settings file path resolution:
- It first attempts to load from the user's config directory:
config_dir.join("settings.json") - If that doesn't exist, it falls back to the bundled resource:
handle.path_resolver().resolve_resource("resources/settings.json")
This is indeed the correct and robust approach using Tauri's recommended APIs. The diff I commented on appears to have shown an intermediate state during development. The current implementation properly handles both user configuration overrides and bundled defaults, with appropriate error handling for missing files or directories.
Thank you for taking the time to clarify this - the current code is well-implemented and follows Tauri best practices perfectly!
Uh oh!
There was an error while loading. Please reload this page.