Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.20)

project(cpp-workspace VERSION 0.4.1 LANGUAGES CXX)
project(cpp-workspace VERSION 0.4.2 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
Expand All @@ -17,6 +17,7 @@ add_executable(cpp-workspace-app
src/interface/user_interface.cpp
src/ollama/ollama_client.cpp
src/storage/qdrant_client.cpp
src/utils/args_utils.cpp
src/utils/curl_utils.cpp
src/utils/text_utils.cpp
src/utils/system_utils.cpp
Expand Down
64 changes: 45 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,25 +53,27 @@ In order to run your own copy of the project it is recommended to satisfly the f
```bash
git config --global core.autocrlf false
git config --global core.eol lf
```

### Integrated development environment

🏆 **Visual Studio Code** - recommended for all operating systems

Suggested extensions:

- [C/C++ Extension Pack](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools-extension-pack)
- [CMake Tools](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cmake-tools)

See [`.vscode/extensions`](.vscode/extensions.json) for the complete list.

### Core dependencies

- [Git]((https://git-scm.com/))
- [Git](<(https://git-scm.com/)>)
- [Python](https://www.python.org/) or [NodeJS](https://nodejs.org/) _for conventional commits_
- [Bash 5](https://www.gnu.org/software/bash/) _for scripting_
- [CMake](https://cmake.org/)
- A **Build system** (one of):
- [Make](https://en.wikipedia.org/wiki/Make_(software))
- [Make](<https://en.wikipedia.org/wiki/Make_(software)>)
- [Ninja](https://ninja-build.org/)
- A **C++ compiler** (one of):
- [GCC](https://gcc.gnu.org/)
Expand All @@ -95,10 +97,12 @@ export QDRANT_API_KEY_READ_ONLY="your-secure-read-only-key"
This project requires [Commitizen](https://commitizen.org/) for standardized commit messages.

**Setup:**

- **Linux/macOS:** `brew install commitizen` or `pip install commitizen`
- **Windows:** Use WSL2 and follow Linux instructions, or install via [MSYS2](https://www.msys2.org/)

**Committing:**

```bash
cz commit # Interactive commit prompt
```
Expand All @@ -109,21 +113,21 @@ cz commit # Interactive commit prompt

1. Install

```bash
bash ./tools/shell/install.sh --help
```
```bash
bash ./tools/shell/install.sh --help
```

2. Build

```bash
bash ./tools/shell/build.sh --help
```
```bash
bash ./tools/shell/build.sh --help
```

3. Format

```bash
bash ./tools/shell/format.sh
```
```bash
bash ./tools/shell/format.sh
```

### Manual build

Expand All @@ -143,9 +147,31 @@ rm -rf ./build/* ./CMakeUserPresets.json ;\
cmake --build --preset conan-release
```

### Runtime arguments

This app accepts the following command-line arguments to customize behavior:

| Argument | Type | Default | Description |
| -------------------------------- | ------- | ----------------------- | ----------------------------------------------------- |
| `--model=<name>` | String | `gemma3n:latest` | The LLM model to use for inference. |
| `--embedding_model=<name>` | String | `embeddinggemma:latest` | The model to use for generating embeddings. |
| `--prompt=<text>` | String | `Hey! What's up!` | Initial prompt or query to send to the model. |
| `--stream=<true\|false>` | Boolean | `false` | Enable streaming responses. |
| `--rag=<true\|false>` | Boolean | `false` | Enable Retrieval-Augmented Generation (RAG) mode. |
| `--interactive=<true\|false>` | Boolean | `false` | Enable interactive mode for multi-turn conversations. |
| `--dark_theme=<true\|false>` | Boolean | `false` | Use dark theme for the ncurses interface. |
| `--skip_embedding=<true\|false>` | Boolean | `false` | Skip embedding creation. |
| `--help=<true\|false>` | Boolean | `false` | Print help. |

### Notes

- Boolean arguments accept **`true`** or **`false`** (case-sensitive lowercase)
- String arguments (`--model`, `--embedding_model`, `--prompt`) accept any alphanumeric string; no spaces or special characters are recommended
- Arguments can be provided in any order

### Run the app

Source .env first, then run the app
Source `.env` first (see the [Environment variables](#environment-variables) section), then run the app

```bash
source .env; \
Expand All @@ -154,12 +180,12 @@ source .env; \

### Quick Start

1. Install Ollama and pull two models, e.g. [__embeddinggemma:latest__](https://ollama.com/library/embeddinggemma) and [__gemma3n:latest__](https://ollama.com/library/gemma3n:latest).
1. Install Ollama and pull two models, e.g. [**embeddinggemma:latest**](https://ollama.com/library/embeddinggemma) and [**gemma3n:latest**](https://ollama.com/library/gemma3n:latest).
2. Build the project or [download the latest release](https://github.com/rfprod/cpp-workspace/releases):
```bash
bash tools/shell/build.sh --clean --release --exe-args '--skip_embedding=true'
```
```bash
bash tools/shell/build.sh --clean --release --exe-args '--skip_embedding=true'
```
3. Run in interactive RAG mode:
```bash
./build/Release/bin/cpp-workspace-app --interactive=true --rag=true
```
```bash
./build/Release/bin/cpp-workspace-app --interactive=true --rag=true
```
9 changes: 6 additions & 3 deletions src/interface/progress_spinner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ void ProgressSpinner::start() {
const char spinner_chars[] = {'|', '/', '-', '\\'};
int i = 0;
while (this->active) {
std::cout << "\r" << spinner_chars[i++ % 4] << " Loading..." << std::flush;
fprintf(stdout, "\r%c Loading...", spinner_chars[i++ % 4]);
fflush(stdout);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
UserInterface::print_message_noninteractive("\n");
Expand Down Expand Up @@ -117,10 +118,12 @@ int ProgressSpinner::progress_callback_impl(curl_off_t dltotal, curl_off_t dlnow

if (dltotal > 0) {
int progress = (dlnow * 100) / dltotal;
std::cout << "\r▰▰▰▱ Progress: " << progress << "% " << std::flush;
fprintf(stdout, "\r▰▰▰▱ Progress %d%% ", progress);
fflush(stdout);
} else {
static int i = 0;
std::cout << "\r" << spinner_chars[i++ % 4] << " Loading..." << std::flush;
fprintf(stdout, "\r%c Loading...", spinner_chars[i++ % 4]);
fflush(stdout);
}
return 0;
}
Expand Down
20 changes: 10 additions & 10 deletions src/interface/user_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ void UserInterface::init_ncurses(void) {
const WINDOW* w = initscr();
if (!w) {
const char* term = getenv("TERM");
std::cerr << "Failed to initialize ncurses with TERM=" << (term ? term : "unset") << "\n";
fprintf(stderr, "Failed to initialize ncurses with TERM=%s\n", term ? term : "unset");
std::exit(EXIT_FAILURE);
}

Expand All @@ -141,21 +141,21 @@ void UserInterface::init_ncurses(void) {
// Setup terminal.
if (cbreak() == ERR || noecho() == ERR) {
endwin();
std::cerr << "Terminal setup failed\n";
fprintf(stderr, "Terminal setup failed\n");
std::exit(EXIT_FAILURE);
}

// Enable function keys and arrow keys.
if (keypad(stdscr, TRUE) == ERR) {
std::cerr << "Warning: keypad() not supported\n";
fprintf(stderr, "Warning: keypad() not supported\n");
}

// Block on input (getch waits for input).
nodelay(stdscr, FALSE);

// Cursor hiding (may not be supported).
if (curs_set(0) == ERR) {
std::cerr << "Warning: cursor control not supported on this terminal\n";
fprintf(stderr, "Warning: cursor control not supported on this terminal\n");
}

if (has_colors()) {
Expand Down Expand Up @@ -1106,8 +1106,8 @@ void UserInterface::print_message(const std::string& text, bool stream) {
* @see print_error()
*/
void UserInterface::print_error_noninteractive(const std::string& text) {
std::cerr << "❌ " << text;
std::cerr.flush();
fprintf(stderr, "❌ %s", text.c_str());
fflush(stderr);
}

/**
Expand All @@ -1123,8 +1123,8 @@ void UserInterface::print_error_noninteractive(const std::string& text) {
* @see print_error()
*/
void UserInterface::print_success_noninteractive(const std::string& text) {
std::cout << "✅ " << text;
std::cout.flush();
fprintf(stdout, "✅ %s", text.c_str());
fflush(stdout);
}

/**
Expand All @@ -1139,8 +1139,8 @@ void UserInterface::print_success_noninteractive(const std::string& text) {
* @see print_message()
*/
void UserInterface::print_message_noninteractive(const std::string& text) {
std::cout << text;
std::cout.flush();
fprintf(stdout, "%s", text.c_str());
fflush(stdout);
}

/**
Expand Down
Loading
Loading