auto(0129): agents_dashboard — secret_store_cpp_infra + CMakeLists register #4
@@ -0,0 +1,134 @@
|
||||
---
|
||||
id: "0110"
|
||||
title: "Gap registry: helper HTTP cliente C++ (curl/popen) reutilizable"
|
||||
status: pendiente
|
||||
type: feature
|
||||
domain:
|
||||
- cpp-stack
|
||||
- registry-quality
|
||||
scope: registry
|
||||
priority: media
|
||||
depends: []
|
||||
blocks:
|
||||
- "0111"
|
||||
related:
|
||||
- "0106"
|
||||
created: 2026-05-18
|
||||
updated: 2026-05-18
|
||||
tags: [http, cpp, registry-gap, curl, helper]
|
||||
---
|
||||
|
||||
# 0110 — Helper HTTP cliente C++ en el registry
|
||||
|
||||
## Problema
|
||||
|
||||
Hoy no existe funcion HTTP cliente reutilizable en `cpp/functions/`. Cada app C++ que necesita
|
||||
golpear un endpoint reinventa la capa:
|
||||
|
||||
| App | Fichero | Tecnica | LOC aprox |
|
||||
|---|---|---|---|
|
||||
| `apps/services_monitor/` | `http_client.cpp` | cURL popen/WinHTTP segun plataforma | ~150 |
|
||||
| `apps/dag_engine_ui/` | inline en `main.cpp` | curl CLI via popen + parse | ~80 |
|
||||
| `apps/data_factory/` | inline | popen curl | ~60 |
|
||||
| `cpp/functions/core/llm_anthropic.cpp` | propio | cURL popen — solo Anthropic | — |
|
||||
| `apps/process_explorer/` (issue 0111) | `http_client.cpp` local | pendiente — clonara services_monitor | ~150 esperados |
|
||||
|
||||
El patron ya supera el umbral `>2x` que dispara la regla de promocion (CLAUDE.md
|
||||
"Si patron se repite >2x → propose nueva funcion via fn-constructor"). Cada app duplica:
|
||||
|
||||
- Detection de plataforma (Linux: `popen("curl -s ...")`, Win: `WinHTTPOpen`/popen)
|
||||
- Manejo de basicAuth / Bearer tokens
|
||||
- Timeouts
|
||||
- Captura de body + status code
|
||||
- Manejo de errores transitorios (DNS, conexion rechazada)
|
||||
|
||||
## Decision
|
||||
|
||||
Anadir al registry dos funciones C++ en dominio `core` (o `infra`):
|
||||
|
||||
### `http_request_cpp_core` (impure)
|
||||
|
||||
```cpp
|
||||
namespace fn_http {
|
||||
struct Request {
|
||||
std::string method; // "GET", "POST", "PUT", "DELETE"
|
||||
std::string url;
|
||||
std::vector<std::pair<std::string,std::string>> headers;
|
||||
std::string body; // raw bytes (JSON, etc.)
|
||||
int timeout_ms = 5000;
|
||||
std::string bearer_token; // shortcut: anade Authorization: Bearer <token>
|
||||
std::string basic_user; // shortcut: anade Authorization: Basic base64(user:pass)
|
||||
std::string basic_pass;
|
||||
};
|
||||
struct Response {
|
||||
int status = 0; // 0 = error de transporte
|
||||
std::string body;
|
||||
std::vector<std::pair<std::string,std::string>> headers;
|
||||
std::string error; // vacio si OK
|
||||
int64_t duration_ms = 0;
|
||||
};
|
||||
Response request(const Request& req);
|
||||
}
|
||||
```
|
||||
|
||||
Implementacion: cURL via popen (portable WSL+Win+Linux, igual que `llm_anthropic`).
|
||||
Si en el futuro queremos rendimiento real, swap a libcurl linkado estaticamente
|
||||
o WinHTTP via `#ifdef _WIN32` — interfaz Request/Response no cambia.
|
||||
|
||||
### `http_get_json_cpp_core` (impure, pure wrapper)
|
||||
|
||||
Helper que envuelve `http_request` + parse JSON (via `nlohmann::json` o similar
|
||||
ya disponible en el repo) para los casos comunes:
|
||||
|
||||
```cpp
|
||||
namespace fn_http {
|
||||
// Devuelve parsed JSON o lanza si status != 2xx
|
||||
nlohmann::json get_json(const std::string& url,
|
||||
const std::string& bearer_token = "",
|
||||
int timeout_ms = 5000);
|
||||
}
|
||||
```
|
||||
|
||||
## Plan de migracion
|
||||
|
||||
Tras crear las funciones, abrir issue separado por cada consumer para migrar:
|
||||
|
||||
1. `apps/services_monitor/http_client.cpp` -> usar `fn_http::request`
|
||||
2. `apps/dag_engine_ui/main.cpp` (inline)
|
||||
3. `apps/data_factory/` (inline)
|
||||
4. `cpp/functions/core/llm_anthropic.cpp` — refactor para usar `fn_http::request` por
|
||||
debajo (mantiene API publica)
|
||||
5. `apps/process_explorer/` (issue 0111) — nace ya usando el helper
|
||||
|
||||
## Criterios de aceptacion
|
||||
|
||||
- [ ] `cpp/functions/core/http_request.{cpp,h,md}` registrado en `registry.db`
|
||||
- [ ] `cpp/functions/core/http_get_json.{cpp,h,md}` idem
|
||||
- [ ] Tests visuales o de integracion contra `httpbin.org` (200/404/timeout/auth)
|
||||
- [ ] Frontmatter completo (`params`/`output`/`tags`/`example`)
|
||||
- [ ] `.md` cumple contrato self-doc (`## Ejemplo`, `## Cuando usarla`, `## Gotchas`)
|
||||
- [ ] Al menos 1 consumer migrado para validar API (recomendado `services_monitor`)
|
||||
- [ ] `fn doctor uses-functions` limpio
|
||||
|
||||
## Gotchas conocidos
|
||||
|
||||
- cURL popen en Windows necesita `curl.exe` en PATH — todos los WSL/Win lo tienen,
|
||||
pero documentar en `## Gotchas`.
|
||||
- Bodies binarios: popen complica el escape; primera version solo string bodies.
|
||||
- TLS verify: por defecto on; permitir `req.insecure = true` solo para testing.
|
||||
- Timeouts: cURL `--max-time` cubre handshake+transfer; documentar diferencia con
|
||||
read-timeout puro.
|
||||
|
||||
## Por que no usar libcurl linkado
|
||||
|
||||
- `popen("curl ...")` no requiere anadir libcurl al toolchain MinGW cross-compile
|
||||
(que ya costo configurar). `llm_anthropic` lleva meses funcionando asi.
|
||||
- Cuando aparezca un caso real de latencia (>10 req/s sostenido), abrimos issue
|
||||
separado para swap a libcurl.
|
||||
|
||||
## Out of scope (no en este issue)
|
||||
|
||||
- WebSocket / SSE — cliente WS C++ es otro gap; abrir issue propio cuando aplique.
|
||||
- Cliente gRPC.
|
||||
- Streaming responses (SSE chunk-by-chunk) — usar caso de `dag_engine_ui` para
|
||||
decidir cuando.
|
||||
Reference in New Issue
Block a user