chore: auto-commit (8 archivos)

- backend/handlers.go
- data.cpp
- data.h
- main.cpp
- panel_board.cpp
- panel_filters.cpp
- appicon.ico
- backend/kanban_cpp_backend.exe

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-26 19:38:15 +02:00
parent 255e8dcf71
commit 98bf278472
8 changed files with 374 additions and 51 deletions
+55
View File
@@ -86,6 +86,16 @@ static fn_http::Response http_patch_json(const std::string& path, const std::str
return fn_http::request(req);
}
static fn_http::Response http_post_json(const std::string& path, const std::string& body) {
fn_http::Request req;
req.method = "POST";
req.url = state().backend_url + path;
req.timeout_ms = 10000;
req.headers.push_back({"Content-Type", "application/json"});
req.body = body;
return fn_http::request(req);
}
bool refresh_issues() {
auto resp = http_get("/api/issues");
if (resp.status != 200) {
@@ -179,6 +189,51 @@ bool patch_issue_status(const std::string& id, const std::string& new_status) {
return true;
}
bool refresh_agent_status() {
auto resp = http_get("/api/agent_status");
if (resp.status != 200) {
std::lock_guard<std::mutex> g(state().mu);
state().agent_runner_up = false;
state().agent_active.clear();
return false;
}
auto j = json::parse(resp.body, nullptr, false);
if (j.is_discarded()) return false;
std::map<std::string, std::string> active;
if (j.contains("active") && j["active"].is_object()) {
for (auto it = j["active"].begin(); it != j["active"].end(); ++it) {
if (it.value().is_string()) active[it.key()] = it.value().get<std::string>();
}
}
bool up = j.value("available", false);
std::lock_guard<std::mutex> g(state().mu);
state().agent_runner_up = up;
state().agent_active = std::move(active);
return true;
}
bool launch_agent(const std::string& issue_id) {
std::string body = "{\"issue_id\":" + json_escape(issue_id) + ",\"mode\":\"fix-issue\"}";
auto resp = http_post_json("/api/agent_launch", body);
if (resp.status < 200 || resp.status >= 300) {
std::lock_guard<std::mutex> g(state().mu);
state().last_launch_msg = "launch failed (" + std::to_string(resp.status) + "): " + resp.body;
return false;
}
{
std::lock_guard<std::mutex> g(state().mu);
state().last_launch_msg = "launched agent on " + issue_id;
// Optimistically mark as active so the dot shows up immediately.
state().agent_active[issue_id] = "pending";
}
return true;
}
bool is_agent_active(const std::string& issue_id) {
std::lock_guard<std::mutex> g(state().mu);
return state().agent_active.find(issue_id) != state().agent_active.end();
}
bool patch_issue_fields(const std::string& id, const std::string& json_partial) {
auto resp = http_patch_json("/api/issues/" + id, json_partial);
if (resp.status != 200) {