Add daemon-backed chat backend (ffp_chat) + chat actions (#20) #49
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
| name: ci | |
| on: | |
| push: | |
| branches: [main, develop] | |
| pull_request: | |
| branches: [main, develop] | |
| permissions: | |
| contents: read | |
| jobs: | |
| python: | |
| name: Python ${{ matrix.python }} | |
| runs-on: windows-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| python: ["3.11", "3.12", "3.13"] | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ matrix.python }} | |
| - name: Install package and dev tools | |
| shell: pwsh | |
| run: python -m pip install -e ".[dev]" | |
| - name: AST validate Python scripts | |
| shell: pwsh | |
| run: | | |
| $files = Get-ChildItem -Path scripts -Filter *.py -File | |
| foreach ($f in $files) { | |
| python -c "import ast; ast.parse(open(r'$($f.FullName)', encoding='utf-8').read()); print('OK $($f.Name)')" | |
| } | |
| - name: Validate JSON configs | |
| shell: pwsh | |
| run: | | |
| $files = Get-ChildItem -Path config -Filter *.json -File | |
| foreach ($f in $files) { | |
| python -c "import json; json.load(open(r'$($f.FullName)', encoding='utf-8')); print('OK $($f.Name)')" | |
| } | |
| - name: Ruff | |
| shell: pwsh | |
| run: ruff check scripts tests | |
| - name: Pytest | |
| shell: pwsh | |
| run: python -m pytest tests -q | |
| ahk: | |
| name: AutoHotkey syntax check | |
| runs-on: windows-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Install AutoHotkey v2 | |
| shell: pwsh | |
| run: | | |
| $ErrorActionPreference = 'Stop' | |
| # Don't let choco's non-zero exit throw (pwsh 7.4+ default) — we want to | |
| # inspect $LASTEXITCODE ourselves and retry / fall back, not abort here. | |
| $PSNativeCommandUseErrorActionPreference = $false | |
| $installed = $false | |
| # Primary: Chocolatey, retried — the community feed has transient 503s | |
| # that would otherwise red-flag PRs that touch no AHK code at all. | |
| for ($i = 1; $i -le 3; $i++) { | |
| choco install autohotkey --version=2.0.26 -y --no-progress | |
| if ($LASTEXITCODE -eq 0) { $installed = $true; break } | |
| Write-Host "choco attempt $i failed (exit $LASTEXITCODE); retrying in 15s..." | |
| Start-Sleep -Seconds 15 | |
| } | |
| if (-not $installed) { | |
| # Fallback: the official AutoHotkey v2 release zip (AutoHotkey64.exe at | |
| # its root), so a full Chocolatey outage can't block the syntax check. | |
| Write-Host "Chocolatey unavailable; falling back to the GitHub release zip." | |
| $zip = Join-Path $env:RUNNER_TEMP "ahk2.zip" | |
| $dest = "C:\Program Files\AutoHotkey" | |
| Invoke-WebRequest -UseBasicParsing -OutFile $zip ` | |
| -Uri "https://github.com/AutoHotkey/AutoHotkey/releases/download/v2.0.26/AutoHotkey_2.0.26.zip" | |
| New-Item -ItemType Directory -Force -Path $dest | Out-Null | |
| Expand-Archive -Path $zip -DestinationPath $dest -Force | |
| } | |
| # Fail fast if neither path produced the interpreter — the parse-check | |
| # steps below skip silently when it is missing, which must not pass green. | |
| $ahk = Get-ChildItem -Path "C:\Program Files\AutoHotkey" -Recurse -Filter AutoHotkey64.exe -File -ErrorAction SilentlyContinue | Select-Object -First 1 | |
| if (-not $ahk) { Write-Error "AutoHotkey64.exe not found after install"; exit 1 } | |
| Write-Host "AutoHotkey64.exe at $($ahk.FullName)" | |
| # A failed-then-recovered choco attempt leaves $LASTEXITCODE non-zero; | |
| # exit explicitly so GitHub's wrapper doesn't fail this successful step. | |
| exit 0 | |
| - name: Validate AutoHotkey scripts (brace balance, all .ahk) | |
| shell: pwsh | |
| run: | | |
| $files = Get-ChildItem -Path scripts -Recurse -Filter *.ahk -File | |
| $failed = $false | |
| foreach ($f in $files) { | |
| $script = Get-Content -Raw $f.FullName | |
| $noComments = ($script -split "`n" | ForEach-Object { $_ -replace ';.*$','' }) -join "`n" | |
| $noStrings = $noComments -replace '"[^"\n]*"','' -replace "'[^'\n]*'", '' | |
| $opens = ($noStrings.ToCharArray() | Where-Object { $_ -eq '{' }).Count | |
| $closes = ($noStrings.ToCharArray() | Where-Object { $_ -eq '}' }).Count | |
| if ($opens -ne $closes) { Write-Host "FAIL $($f.Name): braces $opens / $closes"; $failed = $true } | |
| else { Write-Host "OK $($f.Name): braces $opens / $closes" } | |
| } | |
| if ($failed) { Write-Error "Brace mismatch in one or more .ahk files"; exit 1 } | |
| - name: Parse-check whole include tree | |
| shell: pwsh | |
| run: | | |
| $ahk = Get-ChildItem -Path "C:\Program Files\AutoHotkey" -Recurse -Filter AutoHotkey64.exe -File -ErrorAction SilentlyContinue | Select-Object -First 1 | |
| if (-not $ahk) { Write-Host "AutoHotkey64.exe not found; skipping parse-check"; exit 0 } | |
| $stub = Join-Path $env:RUNNER_TEMP "_ci_syntaxcheck.ahk" | |
| # ExitApp(0) runs before any hotkey binds; #Include pulls the whole tree. | |
| $main = (Resolve-Path -LiteralPath "scripts\grammarFix.ahk").Path | |
| Set-Content -LiteralPath $stub -Encoding UTF8 -Value "ExitApp(0)`n#Include `"$main`"`n" | |
| $errFile = Join-Path $env:RUNNER_TEMP "_ci_syntaxcheck.err" | |
| $p = Start-Process -FilePath $ahk.FullName -ArgumentList @('/ErrorStdOut', "`"$stub`"") -WorkingDirectory "scripts" -RedirectStandardError $errFile -PassThru -Wait | |
| $e = Get-Content -Raw -LiteralPath $errFile -ErrorAction SilentlyContinue | |
| if ($e -and $e.Trim()) { Write-Error "AHK parse errors:`n$e"; exit 1 } | |
| Write-Host "AHK parse-check clean (exit $($p.ExitCode))" | |
| - name: AHK unit tests | |
| shell: pwsh | |
| run: | | |
| $ahk = Get-ChildItem -Path "C:\Program Files\AutoHotkey" -Recurse -Filter AutoHotkey64.exe -File -ErrorAction SilentlyContinue | Select-Object -First 1 | |
| if (-not $ahk) { Write-Host "AutoHotkey64.exe not found; skipping AHK unit tests"; exit 0 } | |
| foreach ($test in @("tests/test_classify_clipboard.ahk", "tests/test_parse_mode.ahk")) { | |
| $errFile = Join-Path $env:RUNNER_TEMP "_ahk_test.err" | |
| $p = Start-Process -FilePath $ahk.FullName -ArgumentList @('/ErrorStdOut', $test) -RedirectStandardError $errFile -PassThru -Wait | |
| $e = Get-Content -Raw -LiteralPath $errFile -ErrorAction SilentlyContinue | |
| if ($p.ExitCode -ne 0) { Write-Error "AHK unit test failed ($test, exit $($p.ExitCode)):`n$e"; exit 1 } | |
| Write-Host "AHK unit test passed: $test" | |
| } | |
| web: | |
| name: Web dashboard JS syntax | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| # ubuntu-latest ships Node, so no setup-node step (and no extra Node-20 | |
| # action). --check validates syntax without executing browser globals. | |
| - name: node --check app.js | |
| run: node --check scripts/ui/web/app.js |