Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
bbfa631
Restructure C++ framework docs, add production readiness content and …
Karim13014 Feb 27, 2026
836c830
Fix doc accuracy issues found in pre-release audit
Karim13014 Mar 2, 2026
e5d8f2c
Clarify Lemonade as recommended backend, move FetchContent to integra…
Karim13014 Mar 2, 2026
fdd14d2
Fix MSVC getenv warnings, split doc command blocks for copy-paste
Karim13014 Mar 2, 2026
46da99a
Add integration test suite with MCP, WiFi, and Health agent coverage
Karim13014 Mar 3, 2026
ef51b0b
Update CI to run full integration tests (LLM + MCP + WiFi + Health) o…
Karim13014 Mar 3, 2026
84e5f27
Add CleanConsole, health_agent, and missing test sources
Karim13014 Mar 3, 2026
868a46f
Fix false-positive loop detection for MCP tool calls
Karim13014 Mar 3, 2026
3684159
Fix MinGW build and health agent Notepad report formatting
Karim13014 Mar 3, 2026
e8d5ee1
Fix MinGW _dupenv_s link errors, increase health agent context to 32K
Karim13014 Mar 3, 2026
c12f605
Increase STX context size to 32K and test timeout to 30 minutes
Karim13014 Mar 3, 2026
e76cd6d
Revert CI to 16K context and 20min timeout
Karim13014 Mar 3, 2026
8f5c788
Simplify health agent menu: option 1 is quick console check, option 1…
Karim13014 Mar 3, 2026
935fb22
Update C++ docs: rename simple_agent to health_agent, fix architectur…
Karim13014 Mar 3, 2026
594d77a
Merge branch 'main' into feature/cpp-framework-updates
kovtcharov Mar 3, 2026
030d9f7
Reduce integration test maxSteps to 3 to prevent CI timeout
Karim13014 Mar 3, 2026
7d4f88a
Speed up STX integration tests: pre-warm uvx, reduce maxSteps
Karim13014 Mar 3, 2026
229514d
Use uv tool install for windows-mcp instead of uvx pre-warm
Karim13014 Mar 3, 2026
963feee
Fix PowerShell stderr handling for uv tool install in CI
Karim13014 Mar 3, 2026
6ae2f2f
Fix PowerShell 5.1 NativeCommandError for uv tool install
Karim13014 Mar 3, 2026
c74faf4
Revert uv tool install, fix broken MCP venv on STX runner
Karim13014 Mar 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 38 additions & 16 deletions .github/workflows/build_cpp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
# SPDX-License-Identifier: MIT

# This workflow builds and tests the C++ library in cpp/
# Tests include: CMake build, GoogleTest unit tests
# Platform: Cross-platform (Linux and Windows)
# Tests include: CMake build, GoogleTest mock tests (cloud), integration tests (STX)
# Integration tests: LLM chat/tool-calling, MCP connection, WiFi diagnostics, Health monitoring
# Platform: Cross-platform (Linux and Windows cloud), Windows STX (self-hosted AMD hardware)

name: C++ Build & Test

Expand Down Expand Up @@ -60,7 +61,7 @@ jobs:
key: fetchcontent-${{ matrix.os }}-${{ hashFiles('cpp/CMakeLists.txt') }}

- name: Configure CMake
run: cmake -B cpp/build -S cpp -DCMAKE_BUILD_TYPE=Release
run: cmake -B cpp/build -S cpp -DCMAKE_BUILD_TYPE=Release -DGAIA_BUILD_INTEGRATION_TESTS=OFF

- name: Build
run: cmake --build cpp/build --config Release --parallel
Expand Down Expand Up @@ -102,6 +103,7 @@ jobs:
run: |
cmake -B cpp/build -S cpp -DCMAKE_BUILD_TYPE=Release \
-DGAIA_BUILD_TESTS=OFF -DGAIA_BUILD_EXAMPLES=OFF \
-DGAIA_BUILD_INTEGRATION_TESTS=OFF \
-DCMAKE_INSTALL_PREFIX="${{ runner.temp }}/gaia_install"
cmake --build cpp/build --config Release --parallel
cmake --install cpp/build --config Release
Expand Down Expand Up @@ -148,12 +150,13 @@ jobs:
run: |
cmake -B cpp/build-shared -S cpp -DCMAKE_BUILD_TYPE=Release \
-DBUILD_SHARED_LIBS=ON \
-DGAIA_BUILD_TESTS=OFF -DGAIA_BUILD_EXAMPLES=OFF
-DGAIA_BUILD_TESTS=OFF -DGAIA_BUILD_EXAMPLES=OFF \
-DGAIA_BUILD_INTEGRATION_TESTS=OFF
cmake --build cpp/build-shared --config Release --parallel

# LLM integration tests on STX hardware with Lemonade Server
# Integration tests on STX hardware: LLM + MCP + WiFi + Health
integration-test:
name: C++ LLM Integration Test (STX)
name: C++ Integration Tests (STX)
runs-on: ${{ (contains(github.event.pull_request.labels.*.name, 'stx-test') && 'stx-test') || 'stx' }}
if: github.event_name != 'pull_request' || github.event.pull_request.draft == false || contains(github.event.pull_request.labels.*.name, 'ready_for_ci')

Expand Down Expand Up @@ -261,29 +264,48 @@ jobs:
cmake --build cpp/build-integration --config Release --parallel
if ($LASTEXITCODE -ne 0) { throw "CMake build failed" }

- name: Verify uvx is available
shell: powershell
run: |
# uvx is provided by uv (installed by setup-venv)
$uvx = Get-Command uvx -ErrorAction SilentlyContinue
if ($uvx) {
Write-Host "[OK] uvx found at: $($uvx.Source)"
} else {
Write-Host "[WARN] uvx not found -- MCP and Health integration tests will fail"
Write-Host " uvx should be available via uv (installed by setup-venv)"
exit 0
}

# Remove any broken persistent installation that may interfere with uvx
$ErrorActionPreference = "SilentlyContinue"
uv tool uninstall windows-mcp 2>$null
$ErrorActionPreference = "Stop"
Write-Host "[OK] uvx ready (windows-mcp will run via temporary uvx environments)"

- name: Start Lemonade Server and run integration tests
shell: powershell
timeout-minutes: 15
timeout-minutes: 20
env:
GAIA_CPP_TEST_MODEL: Qwen3-4B-GGUF
GAIA_CPP_TEST_MODEL: Qwen3-4B-Instruct-2507-GGUF
GAIA_CPP_BASE_URL: http://localhost:8000/api/v1
run: |
try {
# Start Lemonade with Qwen3-4B-GGUF
.\scripts\start-lemonade.ps1 -ModelName "Qwen3-4B-GGUF" -Port 8000 -CtxSize 8192 -InitWaitTime 15
.\scripts\start-lemonade.ps1 -ModelName "Qwen3-4B-Instruct-2507-GGUF" -Port 8000 -CtxSize 16384 -InitWaitTime 15

# Verify health
$health = Invoke-RestMethod -Uri "http://localhost:8000/api/v1/health" -Method GET -TimeoutSec 10
if ($health.status -ne "ok") { throw "Lemonade health check failed" }
Write-Host "[OK] Lemonade Server ready with Qwen3-4B-GGUF"
Write-Host "[OK] Lemonade Server ready with Qwen3-4B-Instruct-2507-GGUF"

# Run C++ integration tests
Write-Host "=== Running C++ LLM Integration Tests ==="
$env:GAIA_CPP_TEST_MODEL = "Qwen3-4B-GGUF"
# Run all C++ integration tests (LLM + MCP + WiFi + Health)
Write-Host "=== Running C++ Integration Tests (LLM + MCP + WiFi + Health) ==="
$env:GAIA_CPP_TEST_MODEL = "Qwen3-4B-Instruct-2507-GGUF"
$env:GAIA_CPP_BASE_URL = "http://localhost:8000/api/v1"
ctest --test-dir cpp/build-integration -C Release --output-on-failure
if ($LASTEXITCODE -ne 0) { throw "C++ integration tests failed" }
Write-Host "[SUCCESS] All C++ LLM integration tests passed!"
Write-Host "[SUCCESS] All C++ integration tests passed!"

} catch {
Write-Host "[ERROR] $($_.Exception.Message)"
Expand Down Expand Up @@ -320,7 +342,7 @@ jobs:
echo "Build & Test: ${{ needs.build-and-test.result }}"
echo "Install Test: ${{ needs.install-test.result }}"
echo "Shared Lib Test: ${{ needs.shared-lib-test.result }}"
echo "LLM Integration: ${{ needs.integration-test.result }}"
echo "Integration Tests: ${{ needs.integration-test.result }}"
echo ""

if [[ "${{ needs.build-and-test.result }}" == "skipped" ]]; then
Expand All @@ -336,7 +358,7 @@ jobs:
# 'skipped' and 'failure' as non-blocking (warn only) since the
# runner may lack tools like cmake in PATH.
if [[ "${{ needs.integration-test.result }}" == "failure" ]]; then
echo "::warning::LLM integration test failed (STX runner infrastructure issue)"
echo "::warning::Integration tests failed (STX runner infrastructure issue)"
fi

if [[ "$FAILED" == "0" ]]; then
Expand Down
29 changes: 18 additions & 11 deletions cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ endif()

# Integration tests require a running Lemonade server -- always OFF by default.
option(GAIA_BUILD_INTEGRATION_TESTS
"Build LLM integration tests (requires lemonade-server with Qwen3-4B-GGUF loaded)" OFF)
"Build LLM integration tests (requires lemonade-server with Qwen3-4B-GGUF loaded)" ON)

# HTTPS support for LLM endpoints -- ON by default (required for remote/cloud Lemonade).
option(GAIA_ENABLE_SSL
Expand Down Expand Up @@ -85,6 +85,7 @@ endif()
add_library(gaia_core
src/tool_registry.cpp
src/console.cpp
src/clean_console.cpp
src/json_utils.cpp
src/agent.cpp
src/mcp_client.cpp
Expand Down Expand Up @@ -167,8 +168,8 @@ endif()
# Examples
# ---------------------------------------------------------------------------
if(GAIA_BUILD_EXAMPLES AND WIN32)
add_executable(simple_agent examples/simple_agent.cpp)
target_link_libraries(simple_agent PRIVATE gaia::gaia_core)
add_executable(health_agent examples/health_agent.cpp)
target_link_libraries(health_agent PRIVATE gaia::gaia_core)

add_executable(wifi_agent examples/wifi_agent.cpp)
target_link_libraries(wifi_agent PRIVATE gaia::gaia_core)
Expand All @@ -180,22 +181,24 @@ endif()
if(GAIA_BUILD_TESTS)
enable_testing()

add_executable(gaia_tests
add_executable(tests_mock
tests/test_types.cpp
tests/test_tool_registry.cpp
tests/test_json_utils.cpp
tests/test_agent.cpp
tests/test_mcp_client.cpp
tests/test_console.cpp
tests/test_clean_console.cpp
tests/test_tool_integration.cpp
)

target_link_libraries(gaia_tests PRIVATE
target_link_libraries(tests_mock PRIVATE
gaia::gaia_core
GTest::gtest_main
)

include(GoogleTest)
gtest_discover_tests(gaia_tests)
gtest_discover_tests(tests_mock)
endif()

# ---------------------------------------------------------------------------
Expand All @@ -205,18 +208,22 @@ endif()
if(GAIA_BUILD_INTEGRATION_TESTS)
enable_testing()

add_executable(gaia_integration_tests
add_executable(tests_integration
tests/integration/test_main.cpp
tests/integration/test_integration_llm.cpp
tests/integration/test_integration_mcp.cpp
tests/integration/test_integration_wifi.cpp
tests/integration/test_integration_health.cpp
)

target_link_libraries(gaia_integration_tests PRIVATE
target_link_libraries(tests_integration PRIVATE
gaia::gaia_core
GTest::gtest_main
GTest::gtest
)

include(GoogleTest)
gtest_discover_tests(gaia_integration_tests
PROPERTIES TIMEOUT 120
gtest_discover_tests(tests_integration
PROPERTIES TIMEOUT 300
)
endif()

Expand Down
24 changes: 15 additions & 9 deletions cpp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ A C++ port of the [GAIA](https://github.com/amd/gaia) Python base agent framewor

Included demos:

- **`simple_agent`** — Windows System Health Agent that connects to the [Windows MCP server](https://github.com/microsoft/windows-mcp), gathers memory/disk/CPU metrics via PowerShell, and pastes a formatted report into Notepad — demonstrating the full computer-use (CUA) flow over the MCP client-server interface.
- **`health_agent`** — Windows System Health Agent that connects to the [Windows MCP server](https://github.com/microsoft/windows-mcp), gathers memory/disk/CPU metrics via PowerShell, and pastes a formatted report into Notepad — demonstrating the full computer-use (CUA) flow over the MCP client-server interface.
- **`wifi_agent`** — Wi-Fi Troubleshooter that diagnoses and fixes network connectivity issues using registered PowerShell tools. Demonstrates adaptive reasoning: the agent decides which tools to run based on the query, interprets results, skips irrelevant steps, applies fixes, and verifies fixes worked — all driven by real LLM reasoning with no hard-coded sequences.

---
Expand Down Expand Up @@ -41,7 +41,7 @@ Default model: `Qwen3-4B-GGUF` (configurable via `AgentConfig::modelId`)

### 3. Windows MCP Server (for the demo)

The `simple_agent` demo launches the Windows MCP server via `uvx`. Install `uv` first:
The `health_agent` demo launches the Windows MCP server via `uvx`. Install `uv` first:

```bash
pip install uv
Expand All @@ -64,7 +64,7 @@ cmake --build build --config Release
```

Binaries are placed in `build\Release\`:
- `simple_agent.exe` — System Health Agent (MCP demo)
- `health_agent.exe` — System Health Agent (MCP demo)
- `wifi_agent.exe` — Wi-Fi Troubleshooter (registered-tool demo)
- `gaia_tests.exe` — unit test suite

Expand All @@ -83,7 +83,7 @@ cmake --build build
```

Binaries are placed in `build/`:
- `simple_agent`
- `health_agent`
- `wifi_agent`
- `gaia_tests`

Expand All @@ -94,7 +94,7 @@ Binaries are placed in `build/`:
Make sure the Lemonade server is running, then launch the agent:

```bat
build\Release\simple_agent.exe
build\Release\health_agent.exe
```

The agent will attempt to connect to the Windows MCP server on startup. Once connected, try one of these prompts:
Expand Down Expand Up @@ -186,22 +186,26 @@ gaia/ # repo root
│ ├── tool_registry.h # Tool registration and execution
│ ├── mcp_client.h # MCP JSON-RPC client (stdio transport)
│ ├── json_utils.h # JSON extraction with multi-strategy fallback
│ └── console.h # TerminalConsole / SilentConsole output handlers
│ ├── console.h # TerminalConsole / SilentConsole output handlers
│ └── clean_console.h # CleanConsole — polished TUI with colors and word-wrap
├── src/
│ ├── agent.cpp # Agent loop state machine
│ ├── tool_registry.cpp
│ ├── mcp_client.cpp # Cross-platform subprocess + pipes (Win32 / POSIX)
│ ├── json_utils.cpp
│ └── console.cpp
│ ├── console.cpp
│ └── clean_console.cpp
├── examples/
│ ├── simple_agent.cpp # Windows System Health Agent (MCP/CUA demo)
│ ├── health_agent.cpp # Windows System Health Agent (MCP/CUA demo)
│ └── wifi_agent.cpp # Wi-Fi Troubleshooter (registered-tool demo)
└── tests/
├── test_agent.cpp
├── test_tool_registry.cpp
├── test_json_utils.cpp
├── test_mcp_client.cpp
├── test_console.cpp
├── test_clean_console.cpp
├── test_tool_integration.cpp
└── test_types.cpp
```

Expand Down Expand Up @@ -267,7 +271,9 @@ The agent is pure C++ — PowerShell is just the subprocess that runs system com

### Custom TUI (`CleanConsole`)

The `wifi_agent` overrides the default `OutputHandler` with a custom `CleanConsole` that parses the LLM's structured reasoning output:
Both example agents use `gaia::CleanConsole` (from `<gaia/clean_console.h>`) for polished terminal output: ANSI colors, word-wrapping, bordered tool output previews, and a bordered final answer section.

The base `CleanConsole` parses structured reasoning prefixes from the LLM output:

- **`FINDING:`** prefix → green label — what the data shows
- **`DECISION:`** prefix → yellow label — what the agent will do next and why
Expand Down
Loading
Loading