cpp-workspace documentation

C++ API reference

struct Layout
#include <user-interface.hpp>

Public Members

int input_y
int input_x
int output_y
int output_height
int status_y
int spinner_y
int spinner_x
class OllamaClient
#include <ollama_client.hpp>

Public Functions

explicit OllamaClient(UserInterface *ui)

Constructs an OllamaClient connected to a UserInterface.

Initializes the Ollama API endpoint URLs, verifies the Ollama binary is installed, and creates a ProgressSpinner for network operations.

Constructs an OllamaClient and initializes Ollama API endpoints.

Sets up endpoint URLs for the local Ollama instance (localhost:11434), verifies that Ollama is installed, and creates a ProgressSpinner for use during network operations.

Prints a newline in CLI mode for clean output formatting.

Note

Calls check_ollama() during construction. Exits if Ollama is not found.

Parameters:

ui – Pointer to the UserInterface for displaying output. Must remain valid for the lifetime of this OllamaClient.

void query_model(OllamaPromptConfig config)

Sends a prompt to an Ollama model and displays the response.

Performs the following steps:

  1. Initializes CURL

  2. Starts the progress spinner

  3. Builds a JSON request with the model, prompt, and stream settings

  4. Sends a POST request to the generate endpoint

  5. Processes the response (streamed or complete)

  6. Cleans up CURL resources

Displays both the user’s prompt and the model’s response via the UI. Handles both CLI and interactive UI modes.

Sends a prompt to an Ollama model and displays the response.

Executes the following workflow:

  1. Initializes CURL and starts the progress spinner

  2. Formats and displays the user’s prompt via the UI

  3. Constructs a JSON request payload with model, prompt, and stream settings

  4. Sends a POST request to the Ollama generate endpoint

  5. Validates HTTP response status (expects 200 OK)

  6. Processes the response as either streamed or complete JSON

  7. Cleans up CURL resources (handle and headers list)

The prompt is displayed immediately with a “💬 user:” prefix. The model’s response is processed based on the stream setting:

  • If stream=true: Response chunks are printed incrementally as they arrive

  • If stream=false: Entire response is printed after completion

Note

On error, displays an error message and exits or ends the session.

Note

Error handling depends on UI mode:

  • CLI mode: Prints error to stderr and calls exit(1)

  • Interactive mode: Calls ui->print_error() and ui->end_session(EXIT_FAILURE)

Note

CURL errors include network failures, connection timeouts, and invalid URLs. HTTP errors are reported when Ollama returns non-200 status codes.

Warning

The method will not return if an error occurs; it terminates the program or session instead.

Parameters:
  • config – Configuration containing the model name, prompt, and stream setting.

  • config – OllamaPromptConfig containing:

    • model: Name of the model to query (e.g., “llama2”)

    • prompt: The text prompt to send

    • stream: Whether to stream the response

void query_model_list()

Retrieves and displays a list of available models from the Ollama server.

Sends a GET request to the /api/tags endpoint and parses the response to extract model metadata (name, size, modification date). Displays each model with its information formatted as a table.

Retrieves and displays all available models from the Ollama server.

Executes the following workflow:

  1. Initializes CURL and starts the progress spinner

  2. Sends a GET request to the Ollama /api/tags endpoint

  3. Validates HTTP response status (expects 200 OK)

  4. Parses the JSON response to extract the “models” array

  5. Displays each model with metadata in a formatted table

  6. Cleans up CURL resources (handle and headers list)

For each model, displays:

  • Last modified timestamp

  • Size in megabytes (or “size unknown” if unavailable)

  • Model name

Output format: “{modified_at}\t ({size_mb}) \t{name}”

See also

OllamaPromptConfig for model information structure

Note

On error, displays an error message and exits or ends the session.

Note

Error handling depends on UI mode:

  • CLI mode: Prints error to stderr and calls exit(1)

  • Interactive mode: Calls ui->print_error() and ui->end_session(EXIT_FAILURE)

Note

Errors may occur at multiple stages:

  • CURL errors: Network failures, connection issues

  • HTTP errors: Non-200 response codes from Ollama

  • JSON errors: Malformed response or missing “models” field

Warning

The method will not return if an error occurs; it terminates the program or session instead.

Private Functions

void check_ollama()

Verifies that the Ollama binary is available on the system.

Uses the which command to check for Ollama in the PATH. If not found, displays an error message and either exits (CLI mode) or ends the session (interactive mode).

Displays a checkmark on success.

Verifies that the Ollama binary is available on the system.

Uses the which ollama command to check if Ollama is in the PATH.

  • If found: displays a checkmark and continues.

  • If not found: displays an error message with installation instructions and exits or ends the session.

Output is routed through the UserInterface (if available) or stdout/stderr.

void init_curl()

Initializes the CURL library and allocates a CURL handle.

If initialization fails, displays an error message and exits or ends the session depending on the UI state.

Displays a checkmark on success.

Initializes the CURL library and allocates a CURL handle.

On failure, displays an error message and either exits (CLI mode) or ends the session (interactive mode). On success, displays a checkmark.

void setup_progress_callback()

Configures the CURL progress callback for download tracking.

Sets up CURLOPT_XFERINFOFUNCTION and CURLOPT_XFERINFODATA to enable progress tracking during HTTP transfers via the ProgressSpinner.

Configures CURL’s progress callback for download tracking.

Enables CURLOPT_NOPROGRESS and sets the progress callback function and data pointer. This allows the ProgressSpinner to update during network transfers.

Does nothing if curl is nullptr.

Note

Must be called before curl_easy_perform().

std::string trim_response(std::string response)

Removes leading and trailing whitespace from a string.

Uses std::find_if with lambda predicates to efficiently trim both ends without creating intermediate strings.

Removes leading and trailing whitespace from a string.

Uses std::find_if with lambda predicates to efficiently trim both ends without creating unnecessary intermediate strings.

Parameters:
  • response – The input string to trim.

  • response – The input string.

Returns:

The trimmed string.

Returns:

The trimmed string.

void process_response(std::string response)

Parses and displays a complete (non-streamed) JSON response from Ollama.

Extracts the “response” field from the JSON and displays it formatted with a llama emoji. If JSON parsing fails, displays an error and exits or ends the session.

Parses and displays a complete JSON response from Ollama.

Extracts the “response” field, trims whitespace, and displays it with a llama emoji header and separator. On JSON parse error, displays an error message and exits or ends the session.

Output is routed through the UserInterface or stdout/stderr.

Parameters:
  • response – The complete JSON response from the Ollama API.

  • response – The complete JSON response from the Ollama API.

void process_response_stream(std::string response)

Parses and displays a streamed JSON response from Ollama.

Processes the response as newline-delimited JSON chunks, extracting the “response” field from each chunk and printing it incrementally. Stops processing when a chunk has “done” set to true.

Parses and displays a streamed JSON response from Ollama.

Processes the response as newline-delimited JSON chunks. For each chunk:

  1. Extracts the “response” field (text fragment)

  2. Prints it incrementally to stdout

  3. Checks the “done” field to determine if streaming is complete

On JSON parse error, displays an error message and exits or ends the session.

Parameters:
  • response – The complete streamed response (newline-delimited JSON).

  • response – The complete streamed response (newline-delimited JSON).

Private Members

CURL *curl

CURL handle for HTTP requests. Initialized in init_curl().

OllamaServerURLs urls

API endpoint URLs for the Ollama server.

struct curl_slist *headers

CURL headers list for HTTP requests (Content-Type, etc.). Allocated in query methods and freed after each request.

UserInterface *ui

Pointer to the UserInterface for displaying messages and errors. Used for both CLI and interactive UI output.

std::unique_ptr<ProgressSpinner> spinner

Progress spinner for visual feedback during network operations. Managed via std::unique_ptr for automatic cleanup.

struct OllamaPromptConfig
#include <ollama_client.hpp>

Configuration for sending a prompt to an Ollama model.

Param model:

The name of the model to query (e.g., “llama2”, “neural-chat”).

Param prompt:

The text prompt to send to the model.

Param stream:

Whether to stream the response (true) or receive it all at once (false).

Public Members

std::string model
std::string prompt
bool stream
struct OllamaServerURLs
#include <ollama_client.hpp>

URLs for Ollama API endpoints.

Param generate_url:

The endpoint for querying a model.

Param tags_url:

The endpoint for listing available models.

Public Members

std::string generate_url
std::string tags_url
class ProgressSpinner

Public Functions

ProgressSpinner()

Constructs a ProgressSpinner in manual mode.

Creates a spinner that displays to stdout without UI integration. Must be manually started with start().

explicit ProgressSpinner(UserInterface *user_interface, bool activate = false)

Constructs a ProgressSpinner with optional UI integration.

Note

The UserInterface pointer must remain valid for the lifetime of the ProgressSpinner object.

Parameters:
  • user_interface – Pointer to a UserInterface instance for rendering, or nullptr for manual mode (CLI spinner).

  • activate – If true and user_interface is not nullptr, automatically starts the spinner. Default: false.

~ProgressSpinner()

Destructs the ProgressSpinner, ensuring the spinner thread is stopped.

Calls stop() to cleanly shut down the spinner thread.

void start()

Starts the spinner animation on a background thread.

  • If no UserInterface is set, displays an animated spinner (| / - ) to stdout.

  • If a UserInterface is set, delegates animation to the UI via start_spinner() and advance_spinner_frame().

Sets progress to 0% and resets the completion_shown flag.

Implementation details:

  • In manual mode, renders spinner characters and progress directly to stdout.

  • In interactive mode, delegates animation and progress updates to the UserInterface.

  • Resets completion_shown flag and initializes progress to 0%.

Note

Safe to call multiple times; subsequent calls are no-ops if already running.

void stop()

Stops the spinner animation and cleans up the background thread.

Waits for the spinner thread to finish (via join()) and notifies the UserInterface to stop its spinner, if set.

Sets active flag to false, waits for the spinner thread to finish, and notifies the UserInterface to stop its spinner if present.

Note

Safe to call multiple times or if start() was never called.

int progress_callback_impl(curl_off_t dltotal, curl_off_t dlnow)

Internal progress callback for CURL integration.

Processes download progress information and updates the spinner or UI accordingly. Displays a progress bar (▰▰▰▱) with percentage if total size is known.

Implementation notes:

  • In manual mode, displays progress percentage if total is known, otherwise shows spinner.

  • In interactive mode, updates both spinner frame and progress bar in the UI.

  • Returns 0 to allow CURL to continue operation.

Note

This method is called frequently by CURL; keep it lightweight.

Parameters:
  • dltotal – Total bytes to download (0 if unknown).

  • dlnow – Bytes downloaded so far.

Returns:

0 to continue the CURL operation, non-zero to abort.

Public Static Functions

static int progress_callback(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)

Static CURL callback adapter for progress tracking.

This static method serves as the callback function for CURL’s CURLOPT_XFERINFOFUNCTION option. It casts the clientp parameter to a ProgressSpinner instance and delegates to progress_callback_impl().

Static callback adapter that casts the clientp void pointer to a ProgressSpinner instance and delegates to the progress_callback_impl() method.

Note

CURL calls this frequently; ensure your clientp points to a valid ProgressSpinner instance.

Parameters:
  • clientp – Opaque pointer to the ProgressSpinner instance (passed via CURLOPT_XFERINFODATA).

  • dltotal – Total bytes to download (0 if unknown).

  • dlnow – Bytes downloaded so far.

  • ultotal – Total bytes to upload (unused).

  • ulnow – Bytes uploaded so far (unused).

Returns:

0 to continue the CURL operation, 1 to abort if clientp is nullptr.

Returns:

0 to continue the operation, 1 if clientp is nullptr.

Private Members

UserInterface *ui

Pointer to the associated UserInterface, or nullptr for manual mode.

std::atomic<bool> active = {false}

Flag indicating whether the spinner is currently active.

std::thread spinner_thread

Thread running the spinner animation loop.

std::atomic<bool> completion_shown = {false}

Flag tracking whether a completion message has been displayed.

class TextUtils
#include <text-utils.hpp>

Utility class for text manipulation operations.

Provides static methods for common text processing tasks, including line wrapping based on a specified maximum width.

Public Functions

TextUtils()

Constructs a TextUtils object.

Default constructor. Since all methods are static, instantiation is optional but permitted.

~TextUtils()

Destructs the TextUtils object.

Default destructor. Performs no special cleanup.

Public Static Functions

static std::vector<std::string> wrap_text(const std::string &text, int max_width)

Wraps text to fit within a specified width.

Implementation of wrap_text method.

Splits the input text into multiple lines, breaking at word boundaries where possible to avoid exceeding the maximum width. Respects natural spaces and removes leading spaces from wrapped lines.

Algorithm:

  1. Iteratively extract lines of up to max_width characters

  2. Prefer breaking at word boundaries (spaces)

  3. If no space exists within max_width, break at max_width

  4. Remove leading whitespace from each new line

  5. Continue until remaining text fits within max_width

Note

If a single word exceeds max_width, it will be placed on its own line without being broken.

Parameters:
  • text – The input text to wrap.

  • max_width – The maximum width (in characters) for each line.

Returns:

A vector of strings, each representing a wrapped line. The last line may be shorter than max_width.

class UserInterface
#include <user-interface.hpp>

Public Functions

UserInterface()
~UserInterface()
bool is_running()
void run(void)
void end_session(int exit_code)
void print_args(const std::string &model, const std::string &prompt, bool stream, bool interactive)
bool next_prompt(std::string *prompt)
void print(const std::string &text, int type = UserInterface::MESSAGE_TYPE_NORMAL)
void print_error(const std::string &text)
void print_success(const std::string &text)
void print_message(const std::string &text)
void request_redraw(void)
void start_spinner(void)
void stop_spinner(void)
void advance_spinner_frame(void)
bool is_spinner_active(void) const
void set_progress(int percent)

Public Static Functions

static void handle_resize(int sig)
static void handle_interrupt(int sig)
static void print_args_noninteractive(const std::string &model, const std::string &prompt, bool stream, bool interactive)
static bool next_prompt_noninteractive(std::string *prompt)

Private Functions

void init_ncurses(void)
void cleanup_ncurses(void)
void start_render_thread(void)
void stop_render_thread(void)
void render_loop(void)
void draw_ui(void)
void draw_spinner(void)
void update_layout()
void draw_input_area()
void clear_input_area()
void draw_output_area()

Private Members

volatile sig_atomic_t resize_flag
volatile sig_atomic_t running
struct Layout layout
std::string input_buffer
int input_cursor_x
std::vector<std::pair<std::string, int>> output_buffer
std::thread render_thread
std::mutex ui_mutex
std::condition_variable cv_redraw
std::atomic<bool> should_redraw = {true}
std::atomic<bool> thread_running = {false}
std::atomic<bool> spinner_active = {false}
std::atomic<int> spinner_frame = {0}
std::atomic<int> progress_percent = {0}

Private Static Attributes

static constexpr int MESSAGE_TYPE_NORMAL = 0
static constexpr int MESSAGE_TYPE_ERROR = 1
static constexpr int MESSAGE_TYPE_SUCCESS = 2
static UserInterface *instance = nullptr

Friends

friend class ProgressSpinner
file main.cpp
#include “ollama_client.hpp”
#include “user-interface.hpp”
#include <iostream>
#include <unistd.h>

Functions

int main(int argc, const char *argv[])
file ollama_client.cpp
#include “ollama_client.hpp”
#include <algorithm>
#include <curl/curl.h>
#include <format>
#include <iostream>
#include <nlohmann/json.hpp>
#include <sstream>
#include <string>

Functions

static size_t WriteCallback(char *contents, size_t size, size_t nmemb, std::string *userp)

CURL write callback for accumulating response data.

Called by CURL whenever data is received. Appends the chunk to the userp string buffer.

Parameters:
  • contents – Pointer to the received data chunk.

  • size – Size of each element (always 1 for this use case).

  • nmemb – Number of elements received.

  • userp – Pointer to the std::string buffer to append data to.

Returns:

Total bytes processed (size * nmemb).

file ollama_client.hpp
#include “progress_spinner.hpp”
#include “user-interface.hpp”
#include <curl/curl.h>
#include <iostream>
file progress_spinner.cpp
#include “progress_spinner.hpp”
#include <atomic>
#include <chrono>
#include <curl/curl.h>
#include <iostream>
#include <thread>
file progress_spinner.hpp
#include “user-interface.hpp”
#include <atomic>
#include <curl/curl.h>
#include <iostream>
#include <thread>
file text-utils.cpp
#include “text-utils.hpp”
file text-utils.hpp
#include <string>
#include <vector>
file user-interface.cpp
#include “user-interface.hpp”
#include <chrono>
#include <csignal>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <locale>
#include <ncurses.h>
#include <sstream>

Variables

constexpr int COLOR_PAIR_DEFAULT = 1
constexpr int COLOR_PAIR_INVERT = 2
file user-interface.hpp
#include “text-utils.hpp”
#include <atomic>
#include <condition_variable>
#include <functional>
#include <mutex>
#include <ncurses.h>
#include <signal.h>
#include <string>
#include <thread>
#include <vector>
dir src
example Query

Client for communicating with a local Ollama instance.

OllamaClient manages HTTP requests to Ollama’s REST API, handling both model queries and model listing. It integrates with a UserInterface for displaying messages and errors, and uses ProgressSpinner to provide visual feedback during network operations.

The client verifies that the Ollama binary is installed on the system and initializes CURL for HTTP communication. All responses are parsed as JSON and formatted for display.

a model:

UserInterface ui;
OllamaClient client(&ui);

OllamaPromptConfig config{
    .model = "llama2",
    .prompt = "What is machine learning?",
    .stream = false
};
client.query_model(config);

Note

Designed for local Ollama instances running on localhost:11434.

example List

available models:

UserInterface ui;
OllamaClient client(&ui);
client.query_model_list();

example Manual

Displays a progress indicator for asynchronous operations, with optional UI integration.

ProgressSpinner supports two modes:

  • Manual mode: Displays an animated spinner to stdout for CLI applications.

  • Interactive mode: Integrates with a UserInterface instance for display within a graphical or TUI framework.

The spinner runs on a separate thread and updates independently of the main operation. Designed to work seamlessly with CURL operations via the static progress_callback method.

mode (CLI spinner):

ProgressSpinner spinner;
spinner.start();
curl_easy_perform(curl_handle);
spinner.stop();

Note

Thread-safe: Uses std::atomic for synchronization without locks.

example Interactive

mode (with UserInterface):

UserInterface ui;
ProgressSpinner spinner(&ui, true);  // auto-starts
// UI displays progress and spinner animation
curl_easy_perform(curl_handle);
spinner.stop();

example CURL

integration with progress tracking:

ProgressSpinner spinner(&ui);
spinner.start();

CURL* curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, ProgressSpinner::progress_callback);
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, &spinner);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
curl_easy_perform(curl);

spinner.stop();
curl_easy_cleanup(curl);