Files
fn_registry/cpp/functions/viz/agent_runs_timeline.md
egutierrez 4ab3678b45 docs(viz): agent_runs_timeline.md — frontmatter + self-doc
Issue 0118. Frontmatter completo (kind, lang, domain, version, purity,
signature, params, tags=agents/timeline/sse/imgui/viz/panel,
uses_functions=http_request_cpp_core, error_type, tested).

Secciones obligatorias por contrato self-doc:
- ## Ejemplo — wiring concreto con TimelineState g_state + lock + render
- ## Cuando usarla — dashboard cross-app de agentes
- ## Gotchas — SSE stub, ts en segundos, mutex obligatorio, no autoscroll,
  ImGuiSelectableFlags_AllowOverlap (rename desde AllowItemOverlap),
  app chip hex hardcoded, since_ts no determinista en tests

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 18:31:45 +02:00

4.6 KiB

name, kind, lang, domain, version, description, tags, purity, signature, params, output, uses_functions, uses_types, returns, returns_optional, error_type, imports, example, tested, tests, test_file_path, file_path, framework
name kind lang domain version description tags purity signature params output uses_functions uses_types returns returns_optional error_type imports example tested tests test_file_path file_path framework
agent_runs_timeline function cpp viz 0.1.0 Panel ImGui timeline de agent runs cross-app, filtros + sort + click row + connection badge
agents
timeline
sse
imgui
viz
panel
impure fn_viz::render_agent_runs_timeline(state) — ImGui draw call
name desc
state TimelineState con runs, filter, callbacks. Mutex protege runs ante el thread del SSE/poll
void — pinta el panel inline en el current ImGui window
http_request_cpp_core
false error_go_core
imgui
ver ## Ejemplo abajo; demo visual TODO en cpp/apps/primitives_gallery/demos_viz.cpp true
test_agent_runs_timeline
cpp/tests/test_agent_runs_timeline.cpp cpp/functions/viz/agent_runs_timeline.cpp imgui

agent_runs_timeline

Panel ImGui que pinta una tabla cross-app de "agent runs" (ejecuciones de fn-orquestador / /autonomous-task / hooks que disparan agentes) con:

  • Filtros: multi-select de apps, multi-select de statuses, slider Since (days) para acotar started_at.
  • Connection badge (● verde / ○ rojo / ◐ amarillo) segun state.connection_status.
  • Tabla ordenada por started_at DESC con columnas: status icon | app (chip coloreado) | issue/card | branch | dod (badge done/validated/total) | duration | started (humano).
  • Row click → setea state.selected_run_id e invoca state.on_select(id) si existe.
  • Footer: contadores por status sobre el set FULL (no el filtrado).

La logica pura (filter / sort / formato duration / mapping status→color/icon / app→chip hex) vive en agent_runs_timeline_helpers.{h,cpp} y es testable sin contexto ImGui (ver cpp/tests/test_agent_runs_timeline.cpp).

Ejemplo

#include "viz/agent_runs_timeline.h"

static fn_viz::TimelineState g_runs_state;

// En setup (una vez):
g_runs_state.sse_url   = "http://127.0.0.1:8497/api/runs/stream";
g_runs_state.on_select = [](const std::string& run_id) {
    open_run_detail_window(run_id);
};

// Por algun mecanismo (test fixture, http poll, future SSE) — poblar runs:
{
    std::lock_guard<std::mutex> lk(g_runs_state.runs_mutex);
    g_runs_state.runs = {
        {"r1", "kanban_cpp", "0118", "c1", "issue/0118", "running",
         /*started*/ 1731920000, /*finished*/ 0, /*dod*/ 5, 2, 0},
    };
    g_runs_state.connection_status = "connected";
}

// En render (cada frame):
ImGui::Begin("Agent runs");
fn_viz::render_agent_runs_timeline(g_runs_state);
ImGui::End();

Cuando usarla

Cuando construyas un dashboard cross-app que exponga el estado de los agentes (orquestador, autonomous-task, hooks reactivos): registry_dashboard, kanban, agent_runner_ui. La quieres siempre que el usuario necesite una vista unica "que esta corriendo / que merge / que fallo" sin abrir N apps. Tambien util como panel Recent runs dentro de una app que dispara agentes propios.

Gotchas

  • SSE client NO esta implementado. poll_sse_runs() es un stub documentado. Hoy el consumer tiene que poblar state.runs por su cuenta (fixture, orquestador in-proc, o polling manual con http_request_cpp_core contra GET /api/runs). Cuando exista un endpoint estable /api/runs/stream, conectar via libcurl multi en thread aparte y empujar updates bajo state.runs_mutex.
  • Timestamps en segundos epoch (no ms). format_duration asume int64_t unix-epoch seconds; si tu fuente emite ms, divide entre 1000 antes de rellenar started_at/finished_at.
  • runs_mutex es obligatorio cuando algun thread distinto del UI escribe state.runs o state.connection_status. El render hace un snapshot bajo lock al principio del frame para no bloquear el resto del dibujo.
  • No autoescroll. Si la tabla crece y queres mantener "lo mas reciente visible", anade tu scroll-to-top tras detectar runs.size() cambia. Decision deliberada: muchas vistas prefieren no saltar mientras lees.
  • Selectable + SpanAllColumns: usa ImGuiSelectableFlags_AllowOverlap (Dear ImGui >= 1.91). En forks viejos pasaba a llamarse AllowItemOverlap — si tu vendor de imgui es viejo, sustituye en agent_runs_timeline.cpp.
  • App chip colors estan hardcodeados en app_chip_hex. Anadir entrada cuando salga una app nueva; sin entrada cae a gris neutral. Mantener el hex aligned con icon.accent del app.md de cada app C++.
  • Filter "Since (days)" convierte a/desde epoch usando std::time(nullptr): no determinista en tests. Por eso los tests del helper pasan since_ts directamente en segundos epoch ficticios (ej. f.since_ts = 1000).