feat(cpp): SSE streaming response support for C++ agent framework#518
Open
feat(cpp): SSE streaming response support for C++ agent framework#518
Conversation
Add token-by-token streaming through the full stack: - SseParser: stateful parser for OpenAI SSE responses (data: lines, [DONE] sentinel, chunked delivery, CRLF handling, malformed JSON safety) - LemonadeClient::chatCompletionsStreaming: streaming POST via httplib cli.send() with ContentReceiverWithProgress; falls back gracefully when server ignores stream:true; validates HTTP status on early Canceled exit to catch reverse-proxy errors - LemonadeClient::httpPostStreaming: low-level streaming HTTP helper - OutputHandler::printStreamToken / printStreamEnd: virtual no-op defaults; TerminalConsole and CleanConsole flush tokens immediately - Agent::callLlm: branches on config_.streaming; accumulates tokens via callback, falls back to non-streaming JSON parse if no tokens received - Agent::processQuery: skips progress spinners and duplicate printThought/printGoal/printFinalAnswer output when streaming - AgentConfig::streaming: defaults to GAIA_STREAMING env var (=1 to enable without recompiling) - 245 unit tests; 18 new SseParser tests covering all edge cases Closes #360
This was referenced Mar 16, 2026
6aa48cd to
73387f9
Compare
…ming-response-support
- Add /EHsc to CMake for MSVC builds (C++ tests crashed without exception unwinding) - Add USERPROFILE env var to MCP config tests (Path.home() uses USERPROFILE on Windows) - Skip signal name tests on Windows (SIGKILL/SIGSEGV not available)
d245f82 to
15c24df
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #360
Summary
sse_parser.h/cpp): stateful SSE line parser that handles chunked delivery, CRLF,[DONE]sentinel, malformed JSON, and role-only chunks without crashinglemonade_client.cpp):httpPostStreaminguses httplib'scli.send()API withContentReceiverWithProgress;chatCompletionsStreamingwires SSE parser to caller callback, falls back to non-streaming JSON parse if server ignoresstream:true, validates HTTP status even onError::Canceledearly exitconsole.h/cpp,clean_console.h/cpp):printStreamTokenflushes each token immediately;printStreamEndemits trailing newline;SilentConsoleinherits default no-opsagent.cpp):callLlmbranches onconfig_.streaming;processQuerysuppresses progress spinners and duplicate print calls (thought/goal/finalAnswer) that were already streamed liveGAIA_STREAMING=1env var: enables streaming without recompiling, following the same pattern asLEMONADE_BASE_URLSseParsertests covering all edge cases; streaming tests added to console and types suitesTest plan
cmake -B build -DGAIA_BUILD_TESTS=ON && cmake --build build && ctest --test-dir build— all tests pass (245 total; 1 pre-existing failure due toLEMONADE_BASE_URLenv var in CI)GAIA_STREAMING=1 ./build/my_agent— tokens stream to terminal word-by-wordconfig_.streaming = false(default) — behavior identical to pre-PR baselinestream:true— fallback returns correct response🤖 Generated with Claude Code