Skip to content

fix(ui): refuse a tool decision that arrives before its prompt #7069

fix(ui): refuse a tool decision that arrives before its prompt

fix(ui): refuse a tool decision that arrives before its prompt #7069

# Copyright(C) 2025-2026 Advanced Micro Devices, Inc. All rights reserved.
# SPDX-License-Identifier: MIT
# This workflow tests the GAIA CLI on Windows with full Lemonade server integration
# Tests include: CLI functionality, Lemonade integration, audio features, and core commands
# Platform: Windows (with Lemonade server and NPU support)
name: GAIA CLI Tests (Windows)
on:
push:
branches: ["main"]
paths:
- 'src/gaia/version.py'
- '.github/actions/install-lemonade/**'
- "src/**"
- "tests/**"
- "setup.py"
- "pyproject.toml"
- "installer/scripts/**"
- ".github/workflows/test_gaia_cli_windows.yml"
pull_request:
# No `branches:` filter: it matches the PR base, so `[ main ]` skipped stacked PRs (#2767).
types: [opened, synchronize, reopened, ready_for_review]
paths:
- 'src/gaia/version.py'
- '.github/actions/install-lemonade/**'
- "src/**"
- "tests/**"
- "setup.py"
- "pyproject.toml"
- "installer/scripts/**"
- ".github/workflows/test_gaia_cli_windows.yml"
merge_group:
workflow_dispatch:
# Cancel in-progress runs when a new run is triggered
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
test-gaia-cli-windows:
name: Test GAIA CLI on Windows (Full Integration)
# Runs on the AMD Ryzen DevLab Dispatch ephemeral pool via the devlab-dispatch label.
runs-on: [self-hosted, Windows, devlab-dispatch, strix-halo]
if: github.event_name != 'pull_request' || github.event.pull_request.draft == false || contains(github.event.pull_request.labels.*.name, 'ready_for_ci')
steps:
- uses: actions/checkout@v7
- name: Setup Python Environment
uses: ./.github/actions/setup-venv
with:
python-version: '3.12'
# Note: 'blender' excluded as bpy requires Blender runtime
install-package: '.[dev,talk,rag,mcp,api]'
- name: Install Lemonade Server
uses: ./.github/actions/install-lemonade
- name: Verify GAIA Installation
run: |
Write-Host "Verifying GAIA installation..."
$gaiaPath = Get-Command gaia -ErrorAction SilentlyContinue
if (-not $gaiaPath) {
Write-Host "Error: gaia not installed correctly"
Write-Host "Current PATH: $env:Path"
exit 1
}
Write-Host "Found gaia at: $($gaiaPath.Source)"
python --version
python -m pip check
# #2250: the launch-secret DACL cannot be proven off-Windows. The mocked
# layer of test_daemon_secret_acl.py already runs on ubuntu (test_unit.yml),
# but only a real NTFS volume shows whether the ACL is actually applied
# and whether inherited ACEs die. Runs before Lemonade: no server needed.
- name: Run Windows Launch-Secret DACL Tests (CMD)
shell: cmd
env:
PYTHONUTF8: 1
run: |
REM Activate virtual environment
call "%GITHUB_WORKSPACE%\.venv\Scripts\activate.bat"
echo ================================================================
echo WINDOWS LAUNCH-SECRET DACL TESTS (issue #2250)
echo ================================================================
echo Virtual Environment: %VIRTUAL_ENV%
python --version
echo.
REM -rs prints skip reasons: if the win32-gated tests SKIP here, the
REM platform guard is misfiring and the real coverage is silently
REM absent -- that must be visible in the log, not swallowed.
python -m pytest tests\unit\test_daemon_secret_acl.py -v -rs --tb=short
set dacl_exit=%ERRORLEVEL%
echo.
echo ----------------------------------------------------------------
echo test_daemon_secret_acl.py exit code: %dacl_exit%
if %dacl_exit% equ 0 (
echo [SUCCESS] Launch-secret DACL tests passed
) else (
echo [FAILURE] Launch-secret DACL tests failed
echo The sidecar launch secret may be readable by other local
echo accounts on NTFS - see issue #2250.
)
echo ----------------------------------------------------------------
exit /b %dacl_exit%
- name: Run Windows Schedule-Lock Tests (CMD)
shell: cmd
env:
PYTHONUTF8: 1
run: |
REM Activate virtual environment
call "%GITHUB_WORKSPACE%\.venv\Scripts\activate.bat"
echo ================================================================
echo WINDOWS SCHEDULE-LOCK TESTS (issue #4208)
echo ================================================================
REM The single-daemon guard takes msvcrt.locking here and fcntl.flock
REM everywhere else, and tests/unit/ runs on ubuntu-latest only -- so
REM without this step the branch most GAIA users hit is never run.
REM -rs prints skip reasons: if the win32-gated tests SKIP here, the
REM platform guard is misfiring and the real coverage is silently
REM absent -- that must be visible in the log, not swallowed.
python -m pytest tests\unit\test_schedule_lock.py -v -rs --tb=short
set lock_exit=%ERRORLEVEL%
echo.
echo ----------------------------------------------------------------
echo test_schedule_lock.py exit code: %lock_exit%
if %lock_exit% equ 0 (
echo [SUCCESS] Schedule-lock tests passed
) else (
echo [FAILURE] Schedule-lock tests failed
echo Two `gaia schedule daemon` processes may both start on
echo Windows and fire every schedule twice - see issue #4208.
)
echo ----------------------------------------------------------------
exit /b %lock_exit%
# Pin the version: the default `release` resolves through gyan.dev, so that
# host 503ing fails the job outright (2026-08-05, "Cannot get latest release").
# An explicit version resolves from the GyanD/codexffmpeg GitHub releases API.
- uses: FedericoCarboni/setup-ffmpeg@v3
id: setup-ffmpeg
with:
ffmpeg-version: '8.1.2'
- name: Start Lemonade Server and Run Tests
timeout-minutes: 20
env:
HUGGINGFACE_ACCESS_TOKEN: ${{ secrets.HUGGINGFACE_ACCESS_TOKEN }}
HF_TOKEN: ${{ secrets.HUGGINGFACE_ACCESS_TOKEN }}
PYTHONUTF8: 1
run: |
Write-Host "Verify Python environment"
python -c "import sys; print(sys.executable)"
Write-Host "Find gaia executable location"
$gaiaPath = Get-Command gaia -ErrorAction SilentlyContinue
if (-not $gaiaPath) {
Write-Host "Error: Cannot find gaia executable in PATH"
Write-Host "Current PATH: $env:Path"
exit 1
}
Write-Host "Found gaia at: $($gaiaPath.Source)"
# Ensure a healthy, Gemma-warmed Lemonade server is up on 13305. The
# helper launches the version-matched server as a persistent Scheduled
# Task (survives across CI jobs since GitHub Actions kills job-spawned
# processes), reuses it if already healthy, and warms Gemma-4.
powershell -ExecutionPolicy Bypass -File installer\scripts\ensure-lemonade-running.ps1 -WarmModel "Gemma-4-E4B-it-GGUF"
if ($LASTEXITCODE -ne 0) { throw "Lemonade server not ready" }
- name: Run Unit Tests (Direct CMD - Full Error Visibility)
shell: cmd
env:
PYTHONUTF8: 1
run: |
REM Activate virtual environment
call "%GITHUB_WORKSPACE%\.venv\Scripts\activate.bat"
echo ================================================================
echo GAIA UNIT TESTS - FULL ERROR LOGGING
echo ================================================================
echo Virtual Environment: %VIRTUAL_ENV%
echo Python Version:
python --version
echo Working Directory: %CD%
echo.
REM Initialize test tracking
set test_llm_exit=0
set test_asr_exit=0
set test_tts_exit=0
REM ================================================================
REM TEST_LLM.PY
REM ================================================================
echo ****************************************************************
echo TEST_LLM.PY
echo ****************************************************************
echo Starting test_llm.py at %TIME%...
echo.
python tests\unit\test_llm.py
set test_llm_exit=%ERRORLEVEL%
echo.
echo ----------------------------------------------------------------
echo test_llm.py completed at %TIME% with exit code: %test_llm_exit%
if %test_llm_exit% equ 0 (
echo [SUCCESS] test_llm.py passed
) else (
echo [FAILURE] test_llm.py failed with exit code %test_llm_exit%
echo Full error output displayed above - no truncation
)
echo ----------------------------------------------------------------
echo.
REM ================================================================
REM TEST_ASR.PY
REM ================================================================
echo ****************************************************************
echo TEST_ASR.PY
echo ****************************************************************
echo Starting test_asr.py at %TIME%...
echo.
python tests\unit\test_asr.py
set test_asr_exit=%ERRORLEVEL%
echo.
echo ----------------------------------------------------------------
echo test_asr.py completed at %TIME% with exit code: %test_asr_exit%
if %test_asr_exit% equ 0 (
echo [SUCCESS] test_asr.py passed
) else (
echo [FAILURE] test_asr.py failed with exit code %test_asr_exit%
echo Full error output displayed above - no truncation
)
echo ----------------------------------------------------------------
echo.
REM ================================================================
REM TEST_LEMONADE_SPEECH.PY
REM ================================================================
echo ****************************************************************
echo TEST_LEMONADE_SPEECH.PY
echo ****************************************************************
echo Starting test_lemonade_speech.py at %TIME%...
echo.
python -m pytest tests\unit\test_lemonade_speech.py -v
set test_tts_exit=%ERRORLEVEL%
echo.
echo ----------------------------------------------------------------
echo test_lemonade_speech.py completed at %TIME% with exit code: %test_tts_exit%
if %test_tts_exit% equ 0 (
echo [SUCCESS] test_lemonade_speech.py passed
) else (
echo [FAILURE] test_lemonade_speech.py failed with exit code %test_tts_exit%
echo Full error output displayed above - no truncation
)
echo ----------------------------------------------------------------
echo.
REM ================================================================
REM FINAL SUMMARY
REM ================================================================
echo ================================================================
echo FINAL TEST SUMMARY
echo ================================================================
echo test_llm.py: exit code %test_llm_exit%
echo test_asr.py: exit code %test_asr_exit%
echo test_lemonade_speech.py: exit code %test_tts_exit%
echo ================================================================
REM Calculate total failures
set /a total_failures=%test_llm_exit%+%test_asr_exit%+%test_tts_exit%
if %total_failures% equ 0 (
echo [OVERALL SUCCESS] All tests passed successfully
echo ================================================================
exit /b 0
) else (
echo [OVERALL FAILURE] One or more tests failed
echo ================================================================
echo FAILED TESTS:
if %test_llm_exit% neq 0 echo - test_llm.py ^(exit code %test_llm_exit%^)
if %test_asr_exit% neq 0 echo - test_asr.py ^(exit code %test_asr_exit%^)
if %test_tts_exit% neq 0 echo - test_lemonade_speech.py ^(exit code %test_tts_exit%^)
echo ================================================================
echo IMPORTANT: All error messages are displayed in full above
echo No PowerShell wrapping or truncation - raw Python output preserved
echo ================================================================
exit /b 1
)
- name: Run Lemonade Client Integration Tests (CMD)
shell: cmd
env:
PYTHONUTF8: 1
GAIA_TEST_MODEL: Gemma-4-E4B-it-GGUF
run: |
REM Activate virtual environment
call "%GITHUB_WORKSPACE%\.venv\Scripts\activate.bat"
echo ================================================================
echo LEMONADE CLIENT INTEGRATION TESTS
echo ================================================================
echo Virtual Environment: %VIRTUAL_ENV%
echo Python Version:
python --version
echo Test Model: %GAIA_TEST_MODEL%
echo Working Directory: %CD%
echo.
REM Initialize test tracking
set lemonade_exit=0
REM ================================================================
REM TEST_LEMONADE_CLIENT.PY - INTEGRATION TESTS ONLY
REM ================================================================
echo ****************************************************************
echo LEMONADE CLIENT INTEGRATION TESTS
echo ****************************************************************
echo Starting test_lemonade_client.py integration tests at %TIME%...
echo.
REM Run only integration tests (skip mock tests which don't need server)
python -m pytest tests\test_lemonade_client.py -vs --tb=short -k "Integration"
set lemonade_exit=%ERRORLEVEL%
echo.
echo ----------------------------------------------------------------
echo test_lemonade_client.py completed at %TIME% with exit code: %lemonade_exit%
if %lemonade_exit% equ 0 (
echo [SUCCESS] Lemonade client integration tests passed
) else (
echo [FAILURE] Lemonade client integration tests failed with exit code %lemonade_exit%
echo Full error output displayed above - no truncation
)
echo ----------------------------------------------------------------
echo.
REM ================================================================
REM LEMONADE CLIENT TEST SUMMARY
REM ================================================================
echo ================================================================
echo LEMONADE CLIENT TEST SUMMARY
echo ================================================================
echo test_lemonade_client.py: exit code %lemonade_exit%
echo ================================================================
if %lemonade_exit% neq 0 (
echo [FAILURE] Lemonade client integration tests failed
echo ================================================================
echo FAILED TEST:
echo - test_lemonade_client.py ^(exit code %lemonade_exit%^)
echo ================================================================
echo IMPORTANT: All error messages are displayed in full above
echo No PowerShell wrapping or truncation - raw Python output preserved
echo ================================================================
exit /b 1
) else (
echo [SUCCESS] Lemonade client integration tests passed successfully
echo ================================================================
)
- name: Debug GAIA Logs on Failure
if: failure()
shell: cmd
run: |
echo === Debugging GAIA failure ===
echo === Check for GAIA log files ===
if exist "gaia.cli.log" (
echo Found gaia.cli.log:
type gaia.cli.log
) else (
echo No gaia.cli.log found
)
echo === Check running processes ===
tasklist | findstr /i "python gaia lemonade-server"
echo === Check ports in use ===
netstat -an | findstr ":8000 :8001"