Adding the ability to cancel an agent midstream

This commit is contained in:
2026-08-05 18:11:32 -05:00
parent 975069c9d0
commit 618976e316
5 changed files with 54 additions and 0 deletions
+6
View File
@@ -5,6 +5,7 @@
#include <vector>
#include <iostream>
#include <optional>
#include <curl/curl.h>
using http_req_cb_t = std::function<std::string(std::string const& old, std::string const& new_str)>;
@@ -30,6 +31,11 @@ private:
nlohmann::json build_body(const std::vector<Message>& messages,
const std::vector<Tool>& tools) const;
static size_t write_cb(char* ptr, size_t size, size_t nmemb, void* userdata);
static int xferinfo_cb(void* cookie,
curl_off_t dltotal,
curl_off_t dlnow,
curl_off_t ultotal,
curl_off_t ulnow);
std::expected<std::string, std::string> http_request(const std::string& full_url,
const std::string& method,
const std::string& body = "",
+3
View File
@@ -2,6 +2,9 @@
#include <string>
#include <expected>
#include <functional>
#include <atomic>
extern std::atomic<bool> ctrlc_request;
// Trim whitespace from both ends of a string
std::string trim(const std::string& s);
+10
View File
@@ -2,6 +2,7 @@
#include "json_types.hpp"
#include "base64_util.hpp"
#include <iostream>
#include "utility.hpp"
Harness::Harness(std::unique_ptr<Client> client, const ToolRegistry& registry,
HarnessConfig config)
@@ -80,11 +81,20 @@ std::expected<std::string, std::string> Harness::chat(const Message& user_messag
push_message(user_message);
for (size_t i = 0; i < config_.max_tool_iterations; ++i) {
if (ctrlc_request)
{
return "";
}
Message response;
bool done = false;
size_t retries = 20;
while (!done)
{
if (ctrlc_request)
return "";
retries--;
if (retries == 0)
{
+11
View File
@@ -29,6 +29,15 @@
#include <filesystem>
#include <random>
#include <iomanip>
#include <signal.h>
std::atomic<bool> ctrlc_request;
void signalHandler(int signal) {
if (signal == SIGINT) {
ctrlc_request = true;
}
}
static const std::vector<AgentProfile> profiles = {
#if !defined(_WIN32)
@@ -97,6 +106,8 @@ static HarnessState read_harness_state_or_exit(const char* file_path) {
}
int main(int argc, char** argv) {
signal(SIGINT, signalHandler);
OllamaConfig cfg;
if (const char* m = std::getenv("OLLAMA_MODEL")) cfg.model = m;
if (const char* u = std::getenv("OLLAMA_URL")) cfg.base_url = u;
+24
View File
@@ -4,6 +4,7 @@
#include <string>
#include <iostream>
#include <expected>
#include "utility.hpp"
static int ollama_clients = 0;
@@ -37,6 +38,27 @@ size_t OllamaClient::write_cb(char* ptr, size_t size, size_t nmemb, void* userda
return size * nmemb;
}
int OllamaClient::xferinfo_cb(void* cookie,
curl_off_t dltotal,
curl_off_t dlnow,
curl_off_t ultotal,
curl_off_t ulnow)
{
(void)cookie;
(void)dltotal;
(void)dlnow;
(void)ultotal;
(void)ulnow;
if (ctrlc_request)
{
return 1; // Cancel
}
return 0; // Continue transfer
}
std::expected<std::string, std::string> OllamaClient::http_request(const std::string& full_url,
const std::string& method,
const std::string& body,
@@ -70,6 +92,8 @@ std::expected<std::string, std::string> OllamaClient::http_request(const std::st
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, xferinfo_cb);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_buf);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);