-
Notifications
You must be signed in to change notification settings - Fork 67
Description
Context
Part of the C++ WebUI Integration milestone. See docs/plans/cpp-webui-integration.md for full architecture.
Description
Create a new OutputHandler subclass in the C++ framework that emits JSON-line events to stdout. Each line is a JSON object matching the SSE event format the WebUI frontend already consumes.
Files:
cpp/include/gaia/json_event_handler.hcpp/src/json_event_handler.cpp
Event Mapping
Every OutputHandler virtual method maps to one JSON event:
| Method | Event JSON |
|---|---|
printStepHeader(n, total) |
{"type": "step", "step": n, "total": total, "status": "started"} |
printStreamToken(token) |
{"type": "chunk", "content": "token"} |
printStreamEnd() |
(internal state, no output) |
printThought(text) |
{"type": "thinking", "content": "text"} |
printGoal(text) |
{"type": "status", "status": "working", "message": "text"} |
printPlan(plan, current) |
{"type": "plan", "steps": [...], "current_step": n} |
printToolUsage(name) |
{"type": "tool_start", "tool": "name"} |
prettyPrintJson(args, "Tool Args") |
{"type": "tool_args", "tool": "name", "args": {...}, "detail": "..."} |
printToolComplete() |
{"type": "tool_end", "success": true} |
prettyPrintJson(result, "Tool Result") |
{"type": "tool_result", "title": "...", "summary": "...", "success": true} |
printFinalAnswer(text) |
{"type": "answer", "content": "text", "steps": n, "tools_used": n} |
printError(msg) |
{"type": "agent_error", "content": "msg"} |
printWarning(msg) |
{"type": "status", "status": "warning", "message": "msg"} |
printInfo(msg) |
{"type": "status", "status": "info", "message": "msg"} |
printCompletion(steps, limit) |
{"type": "status", "status": "complete", "steps": n} |
IMPORTANT: Do NOT Emit done Event
The done SSE event ({"type": "done", "message_id": N}) is emitted by the Python wrapper after the C++ subprocess exits and the message is saved to the database. The C++ JsonEventOutputHandler must NOT emit done — it doesn't have access to the database message ID.
Tool Result command_output Extraction
For tool results containing shell command output, parse the result JSON to extract structured command_output:
{
"type": "tool_result",
"title": "Tool Result",
"summary": "...",
"success": true,
"command_output": {
"command": "netsh wlan show interfaces",
"stdout": "...",
"return_code": 0
}
}C++ agent tools typically return JSON with "tool", "command", "output", and "exitCode" fields. The handler should map these to the command_output structure the frontend expects.
Distinguishing Tool Args vs Results
The prettyPrintJson(data, title) method is called with:
title = "Tool Args"→ emit astool_argseventtitle = "Tool Result"→ emit astool_resultevent- Other titles → emit as generic
tool_result
This is already how the C++ agent uses it (verified in agent.cpp lines 501, 508).
Internal State Tracking
The handler must track:
currentTool_— name of the tool currently executing (set byprintToolUsage)stepsTaken_— step counter (incremented byprintStepHeader)toolsUsed_— tool counter (incremented byprintToolComplete)- These are needed for the
answerevent'sstepsandtools_usedfields
Acceptance Criteria
-
JsonEventOutputHandlerimplements all 19OutputHandlervirtual methods - Each method emits exactly one JSON line to stdout (flushed immediately)
- JSON format matches the SSE event types the WebUI expects
- Tool args and results correctly distinguished via
titleparameter -
command_outputstructured format for shell tool results - Internal step/tool counters maintained for
answerevent stats - Does NOT emit
doneevent (Python wrapper responsibility) - Unit tests validate JSON output for each method
- Registered in CMakeLists.txt build
Dependencies
- PR feat(cpp): SSE streaming response support for C++ agent framework #518 must be merged first (provides
printStreamToken()/printStreamEnd())