Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
67 changes: 67 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ on:
branches: [main]
pull_request:
workflow_dispatch:
inputs:
live_windows:
description: 'Run only live Windows generation using preinstalled Chrome and a free model'
type: boolean
default: false

permissions:
contents: read
Expand All @@ -17,6 +22,7 @@ concurrency:
# Pin action revisions so upstream tag changes cannot alter CI code.
jobs:
lint:
if: github.event_name != 'workflow_dispatch' || !inputs.live_windows
name: ruff
runs-on: ubuntu-latest
steps:
Expand All @@ -33,6 +39,7 @@ jobs:
# in the logs, but it never blocks a merge. Remove `continue-on-error` once
# `uv run mypy src` is clean.
typecheck:
if: github.event_name != 'workflow_dispatch' || !inputs.live_windows
name: mypy (informational)
runs-on: ubuntu-latest
continue-on-error: true
Expand All @@ -45,11 +52,15 @@ jobs:
- run: uv run mypy src

test:
if: github.event_name != 'workflow_dispatch' || !inputs.live_windows
name: pytest (py${{ matrix.python-version }}, ${{ matrix.os }})
timeout-minutes: 15
runs-on: ${{ matrix.os }}
env:
# Make the matrix interpreter explicit for every uv invocation.
UV_PYTHON: ${{ matrix.python-version }}
# Exercise real PowerShell execution on every platform; do not silently skip.
RAE_REQUIRE_PWSH: "1"
strategy:
fail-fast: false
matrix:
Expand All @@ -63,4 +74,60 @@ jobs:
python-version: ${{ matrix.python-version }}
# --locked: fail loudly if uv.lock is stale instead of silently re-resolving.
- run: uv sync --all-extras --locked
- name: Verify PowerShell 7+
shell: pwsh
run: |
if ($PSVersionTable.PSVersion.Major -lt 7) { throw 'PowerShell 7+ required' }
- run: uv run reverse-api-engineer --version

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The new --version and --help smoke steps duplicate coverage that tests/test_cli_no_httpx.py already provides in a stronger form: that test parametrizes both flags and runs them in a subprocess with a fresh interpreter (python -I) plus legacy-HTTP-import blocking on every matrix entry. The only coverage the smoke steps add is the uv-generated console-script wrapper, which is low-risk. Consider dropping these two steps, or keeping a single one (--version) if you want an entry-point smoke test, to avoid paying ~9 extra uv run invocations per PR for near-zero added coverage.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/ci.yml, line 73:

<comment>The new `--version` and `--help` smoke steps duplicate coverage that `tests/test_cli_no_httpx.py` already provides in a stronger form: that test parametrizes both flags and runs them in a subprocess with a fresh interpreter (`python -I`) plus legacy-HTTP-import blocking on every matrix entry. The only coverage the smoke steps add is the `uv`-generated console-script wrapper, which is low-risk. Consider dropping these two steps, or keeping a single one (`--version`) if you want an entry-point smoke test, to avoid paying ~9 extra `uv run` invocations per PR for near-zero added coverage.</comment>

<file context>
@@ -63,4 +66,10 @@ jobs:
+        shell: pwsh
+        run: |
+          if ($PSVersionTable.PSVersion.Major -lt 7) { throw 'PowerShell 7+ required' }
+      - run: uv run reverse-api-engineer --version
+      - run: uv run reverse-api-engineer --help
       - run: uv run pytest -q
</file context>

- run: uv run reverse-api-engineer --help
- run: uv run pytest -q

live-windows:
name: Live Windows generation (Chrome already installed)
if: github.event_name == 'workflow_dispatch' && inputs.live_windows

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: When a live Windows dispatch runs on main while ordinary CI is active, the shared concurrency group cancels the ordinary run, but this dispatch does not run its required checks. Use a separate concurrency group for live validation so it cannot cancel normal CI.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/ci.yml, line 87:

<comment>When a live Windows dispatch runs on `main` while ordinary CI is active, the shared concurrency group cancels the ordinary run, but this dispatch does not run its required checks. Use a separate concurrency group for live validation so it cannot cancel normal CI.</comment>

<file context>
@@ -73,3 +81,53 @@ jobs:
+
+  live-windows:
+    name: Live Windows generation (Chrome already installed)
+    if: github.event_name == 'workflow_dispatch' && inputs.live_windows
+    runs-on: windows-latest
+    timeout-minutes: 12
</file context>

runs-on: windows-latest
timeout-minutes: 12
env:
UV_PYTHON: '3.13'
PYTHONIOENCODING: utf-8
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1'
PLAYWRIGHT_MCP_BROWSER: chrome
RAE_OPENCODE_PACKAGE: opencode-ai@1.18.31
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
- uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
with:
python-version: '3.13'
enable-cache: true
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: '22'
- name: Locate npm cache
id: npm-cache
shell: pwsh
run: '"path=$(npm config get cache)" >> $env:GITHUB_OUTPUT'
- uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: ${{ steps.npm-cache.outputs.path }}
key: windows-node22-opencode1.18.31-rae-mcp0.0.8-v1
- name: Verify preinstalled Chrome and PowerShell
shell: pwsh
run: |
$chrome = Join-Path $env:ProgramFiles 'Google/Chrome/Application/chrome.exe'
if (!(Test-Path $chrome)) { throw 'Preinstalled Chrome missing; refusing browser download' }
if ($PSVersionTable.PSVersion.Major -lt 7) { throw 'PowerShell 7+ required' }
"PLAYWRIGHT_MCP_EXECUTABLE_PATH=$chrome" >> $env:GITHUB_ENV
(Get-Item $chrome).VersionInfo.ProductVersion
- run: uv sync --locked --no-dev
- name: Warm OpenCode package cache
run: npx --yes opencode-ai@1.18.31 --version
- name: Generate and execute PowerShell and Python clients
shell: pwsh
run: |
foreach ($language in @('powershell', 'python')) {
uv run --no-sync python scripts/validation/generation_e2e.py --language $language --artifacts-dir "$env:RUNNER_TEMP/rae-$language"
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
Get-Content "$env:RUNNER_TEMP/rae-$language/result.json" >> $env:GITHUB_STEP_SUMMARY
}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ cython_debug/
har/
scripts/*
!scripts/clean_build.sh
!scripts/validation/
scripts_built/
src/reverse_api/scripts/
.reverse-api/
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added
- **PowerShell 7+ output**: generate an `api_client.psm1` module and `Example.ps1`, with CLI execution through `pwsh` on Windows, macOS, and Linux.
- **Live client validation**: an opt-in local test captures a fixture API, generates a Python or PowerShell client with a verified free OpenCode model, and checks fresh API data on replay. The manual `live_windows` CI option validates both languages using preinstalled Chrome and cached Python/npm dependencies, without downloading Chromium. Regular CI requires real PowerShell execution and CLI startup checks across all three operating systems.

### Fixed
- **PowerShell execution validation**: reject unsupported module names, missing `Example.ps1`, and script arguments that the example cannot forward, rather than silently running a different command. Generation instructions require portable module imports and terminating errors so failed API calls produce a nonzero exit status.
- Refresh the locked Claude Agent SDK and MCP dependencies so the development environment also uses MCP 2.x and `httpx2`, without the legacy `httpx`, `httpx-sse`, and `httpcore` packages. Add subprocess smoke tests for CLI startup with legacy HTTP client imports blocked.

## [0.13.1] - 2026-08-30
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
1. You give it a website and a goal ("fetch all Apple jobs").
2. A browser visits the site, either driven by you or by an AI agent.
3. Network traffic is captured to a HAR file.
4. Your configured model reads the traffic and writes a working API client in Python, JavaScript, TypeScript, Go, Java, C#, PHP, Ruby, or C.
4. Your configured model reads the traffic and writes a working API client in Python, JavaScript, TypeScript, Go, Java, C#, PHP, Ruby, C, or PowerShell.

No more manually opening DevTools, copying cURL commands, and gluing together a client.

Expand Down Expand Up @@ -117,7 +117,7 @@ Settings live in `~/.reverse-api/config.json` and can be edited via `/settings`
- **SDK**: `claude` (default), `opencode`, `cursor`, or `copilot` (GitHub Copilot).
- **OpenCode setup**: with `sdk: "opencode"`, RAE reuses an existing server or downloads/starts `opencode-ai@latest` through `npx`; a global OpenCode installation is not required. Fresh configurations default to the free `opencode/big-pickle` model. `/settings` shows a loading spinner, then offers a searchable **OpenCode Provider / Model** picker populated from the server's connected, tool-capable catalog and marks free OpenCode options. Before creating a session, RAE validates the saved pair again and suggests currently available free models when configuration is invalid. Compatible older servers are reused with a version warning. Node.js 20+ is required for automatic startup. Password-protected servers use `OPENCODE_SERVER_PASSWORD` and optional `OPENCODE_SERVER_USERNAME`. Override startup with `OPENCODE_BASE_URL`, `RAE_OPENCODE_PACKAGE`, or `RAE_OPENCODE_AUTO_START=0`.
- **Ollama through OpenCode**: choose provider `ollama` in `/settings`; RAE starts an installed Ollama daemon if needed, lists only installed models with tool calling and 64k+ context, and supplies OpenCode's provider config inline. Models are never downloaded silently. Override with `RAE_OLLAMA_BASE_URL` or `RAE_OLLAMA_AUTO_START=0`.
- **Output language**: `python`, `javascript`, `typescript`, `go`, `java`, `csharp`, `php`, `ruby`, or `c`. C needs a POSIX toolchain (`cc`, libcurl headers) — macOS/Linux, or WSL/MSYS2 on Windows.
- **Output language**: `python`, `javascript`, `typescript`, `go`, `java`, `csharp`, `php`, `ruby`, `c`, or `powershell`. C needs a POSIX toolchain (`cc`, libcurl headers) — macOS/Linux, or WSL/MSYS2 on Windows. PowerShell needs `pwsh` 7+ (PowerShell Core, not Windows PowerShell 5.1). Its runner executes the generated `Example.ps1` beside `api_client.psm1`; argument overrides are not supported. Edit the example or import the module to call its exported functions with your own arguments.

## CLI

Expand Down
40 changes: 40 additions & 0 deletions scripts/validation/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Local live generation check

Run this manually with the Python environment containing the RAE package you
want to validate. Node.js/npm and a supported Playwright browser are required;
PowerShell 7+ is required for the PowerShell case.

```sh
python scripts/validation/generation_e2e.py --language python
python scripts/validation/generation_e2e.py --language powershell
```

The script starts a local website, asks OpenCode to capture its API and generate
a client, then runs that client through `reverse-api-engineer run`. It changes
the server response after generation and checks both the returned data and a new
HTTP request, so cached or hardcoded answers cannot pass.

Only `opencode/big-pickle` is allowed. Its advertised input/output prices must
both be zero; otherwise the check fails without selecting another model. Free
model availability and network access can still affect this optional test.

RAE configuration is redirected inside the test process and CLI subprocesses;
OpenCode uses separate XDG directories and the browser uses an isolated profile.
No existing user configuration is overwritten. The interpreter must be the one
from the installation under test (for example `/path/to/venv/bin/python`).

Logs, HAR capture, generated clients and OpenCode state are retained in the
printed temporary directory. Pass `--artifacts-dir /path/to/new-directory` to
choose a location; an existing directory is rejected. The local fixture server
stops when the test ends, so retained clients need a new matching server before
they can be replayed again.

To run on Windows in GitHub Actions, open **CI → Run workflow** and enable
**live_windows**. This starts one Windows job, running PowerShell then Python,
with preinstalled Chrome. It does not download browsers or install Windows media
components. Python and npm dependencies are cached; the first run can be slower.
The result for each language is included in the run summary. This uses the same
free-model checks and fresh-response validation as the local command.

Ordinary pushes and PRs only run the deterministic unit, CLI startup and real
PowerShell execution checks across all three OSes. The live test is manual only.
Loading
Loading