mirror of
https://github.com/headroomlabs-ai/headroom.git
synced 2026-08-27 14:17:10 -04:00
183 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
34a5517562
|
chore: release 0.36.5 (#3214)
🤖 I have created a release *beep* *boop* --- ## [0.36.5](https://github.com/headroomlabs-ai/headroom/compare/v0.36.4...v0.36.5) (2026-08-22) ### Bug Fixes * **codex:** detect ChatGPT auth from id_token claims so wrap/init emit requires_openai_auth ([#3212](https://github.com/headroomlabs-ai/headroom/issues/3212)) ([ |
||
|
|
91186b40d8
|
chore: release 0.36.4 (#3189)
🤖 I have created a release *beep* *boop* --- ## [0.36.4](https://github.com/headroomlabs-ai/headroom/compare/v0.36.3...v0.36.4) (2026-08-22) ### Bug Fixes * **dashboard:** pin MIME types for the vendored static assets ([#3193](https://github.com/headroomlabs-ai/headroom/issues/3193)) ([ |
||
|
|
87e71dd100
|
chore: release 0.36.3 (#3188)
🤖 I have created a release *beep* *boop* --- ## [0.36.3](https://github.com/headroomlabs-ai/headroom/compare/v0.36.2...v0.36.3) (2026-08-21) ### Bug Fixes * **proxy/responses:** lift Codex >= 0.149.0 additional_tools into top-level tools ([#3186](https://github.com/headroomlabs-ai/headroom/issues/3186)) ([ |
||
|
|
5e0ce242e9
|
chore: release 0.36.2 (#3157)
🤖 I have created a release *beep* *boop* --- ## [0.36.2](https://github.com/headroomlabs-ai/headroom/compare/v0.36.1...v0.36.2) (2026-08-21) ### Bug Fixes * **copilot:** bind the minted token to the integration ID we forward ([#3164](https://github.com/headroomlabs-ai/headroom/issues/3164)) ([ |
||
|
|
c8db13d5ad
|
deps: bump ruff from 0.16.2 to 0.16.3 in the pip-minor-patch group (#3143)
Bumps the pip-minor-patch group with 1 update: [ruff](https://github.com/astral-sh/ruff). Updates `ruff` from 0.16.2 to 0.16.3 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/astral-sh/ruff/releases">ruff's releases</a>.</em></p> <blockquote> <h2>0.16.3</h2> <h2>Release Notes</h2> <p>Released on 2026-08-13.</p> <h3>Preview features</h3> <ul> <li>[<code>pylint</code>] Fix false negatives on negative numbers (<code>PLR6104</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/27251">#27251</a>)</li> <li>[<code>pyupgrade</code>] Add rule to replace <code>while 1</code> with <code>while True</code> (<code>UP048</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/27190">#27190</a>)</li> </ul> <h3>Bug fixes</h3> <ul> <li>[<code>flake8-bandit</code>] Also check keyword arguments (<code>S602</code>, <code>S603</code>, <code>S607</code>, <code>S609</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/27687">#27687</a>)</li> <li>[<code>pylint</code>] Allow <code>continue</code> in <code>finally</code> on Python 3.8 (<a href="https://redirect.github.com/astral-sh/ruff/pull/27626">#27626</a>)</li> <li>[<code>pylint</code>] Fix <code>PLE1307</code> false positive with bools (<a href="https://redirect.github.com/astral-sh/ruff/pull/27651">#27651</a>)</li> <li>[<code>pylint</code>] Fix false positives and negatives with <code>%b</code> format character (<code>PLE1300</code>, <code>PLE1307</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/27560">#27560</a>)</li> <li>[<code>pylint</code>] Improve handling of concatenated strings (<code>PLE1300</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/27659">#27659</a>)</li> </ul> <h3>Rule changes</h3> <ul> <li>[<code>numpy</code>] Make <code>np.chararray</code> autofix backwards-compatible (<code>NPY201</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/27527">#27527</a>)</li> </ul> <h3>Performance</h3> <ul> <li>Enable PGO for Linux x86-64 Ruff releases (<a href="https://redirect.github.com/astral-sh/ruff/pull/27570">#27570</a>)</li> <li>Enable PGO for Linux ARM64 Ruff releases (<a href="https://redirect.github.com/astral-sh/ruff/pull/27574">#27574</a>)</li> <li>Enable PGO for Windows x86-64 Ruff releases (<a href="https://redirect.github.com/astral-sh/ruff/pull/27573">#27573</a>)</li> <li>Enable PGO for macOS ARM64 Ruff releases (<a href="https://redirect.github.com/astral-sh/ruff/pull/27572">#27572</a>)</li> <li>Reduce <code>Expr</code> size to 64 bytes (<a href="https://redirect.github.com/astral-sh/ruff/pull/27591">#27591</a>)</li> </ul> <h3>CLI</h3> <ul> <li>Hyperlink rule codes in <code>ruff check --statistics</code> output (<a href="https://redirect.github.com/astral-sh/ruff/pull/27646">#27646</a>)</li> </ul> <h3>Documentation</h3> <ul> <li>[<code>ruff</code>] Also suggest <code>asyncio.TaskGroup</code> (<code>RUF006</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/27461">#27461</a>)</li> </ul> <h3>Other changes</h3> <ul> <li>Use mimalloc v3 (<a href="https://redirect.github.com/astral-sh/ruff/pull/27586">#27586</a>)</li> </ul> <h3>Contributors</h3> <ul> <li><a href="https://github.com/Andrej730"><code>@Andrej730</code></a></li> <li><a href="https://github.com/alonfaraj"><code>@alonfaraj</code></a></li> <li><a href="https://github.com/romero-deshaw"><code>@romero-deshaw</code></a></li> <li><a href="https://github.com/Avasam"><code>@Avasam</code></a></li> <li><a href="https://github.com/tjkuson"><code>@tjkuson</code></a></li> <li><a href="https://github.com/charliermarsh"><code>@charliermarsh</code></a></li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md">ruff's changelog</a>.</em></p> <blockquote> <h2>0.16.3</h2> <p>Released on 2026-08-13.</p> <h3>Preview features</h3> <ul> <li>[<code>pylint</code>] Fix false negatives on negative numbers (<code>PLR6104</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/27251">#27251</a>)</li> <li>[<code>pyupgrade</code>] Add rule to replace <code>while 1</code> with <code>while True</code> (<code>UP048</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/27190">#27190</a>)</li> </ul> <h3>Bug fixes</h3> <ul> <li>[<code>flake8-bandit</code>] Also check keyword arguments (<code>S602</code>, <code>S603</code>, <code>S607</code>, <code>S609</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/27687">#27687</a>)</li> <li>[<code>pylint</code>] Allow <code>continue</code> in <code>finally</code> on Python 3.8 (<a href="https://redirect.github.com/astral-sh/ruff/pull/27626">#27626</a>)</li> <li>[<code>pylint</code>] Fix <code>PLE1307</code> false positive with bools (<a href="https://redirect.github.com/astral-sh/ruff/pull/27651">#27651</a>)</li> <li>[<code>pylint</code>] Fix false positives and negatives with <code>%b</code> format character (<code>PLE1300</code>, <code>PLE1307</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/27560">#27560</a>)</li> <li>[<code>pylint</code>] Improve handling of concatenated strings (<code>PLE1300</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/27659">#27659</a>)</li> </ul> <h3>Rule changes</h3> <ul> <li>[<code>numpy</code>] Make <code>np.chararray</code> autofix backwards-compatible (<code>NPY201</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/27527">#27527</a>)</li> </ul> <h3>Performance</h3> <ul> <li>Enable PGO for Linux x86-64 Ruff releases (<a href="https://redirect.github.com/astral-sh/ruff/pull/27570">#27570</a>)</li> <li>Enable PGO for Linux ARM64 Ruff releases (<a href="https://redirect.github.com/astral-sh/ruff/pull/27574">#27574</a>)</li> <li>Enable PGO for Windows x86-64 Ruff releases (<a href="https://redirect.github.com/astral-sh/ruff/pull/27573">#27573</a>)</li> <li>Enable PGO for macOS ARM64 Ruff releases (<a href="https://redirect.github.com/astral-sh/ruff/pull/27572">#27572</a>)</li> <li>Reduce <code>Expr</code> size to 64 bytes (<a href="https://redirect.github.com/astral-sh/ruff/pull/27591">#27591</a>)</li> </ul> <h3>CLI</h3> <ul> <li>Hyperlink rule codes in <code>ruff check --statistics</code> output (<a href="https://redirect.github.com/astral-sh/ruff/pull/27646">#27646</a>)</li> </ul> <h3>Documentation</h3> <ul> <li>[<code>ruff</code>] Also suggest <code>asyncio.TaskGroup</code> (<code>RUF006</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/27461">#27461</a>)</li> </ul> <h3>Other changes</h3> <ul> <li>Use mimalloc v3 (<a href="https://redirect.github.com/astral-sh/ruff/pull/27586">#27586</a>)</li> </ul> <h3>Contributors</h3> <ul> <li><a href="https://github.com/Andrej730"><code>@Andrej730</code></a></li> <li><a href="https://github.com/alonfaraj"><code>@alonfaraj</code></a></li> <li><a href="https://github.com/romero-deshaw"><code>@romero-deshaw</code></a></li> <li><a href="https://github.com/Avasam"><code>@Avasam</code></a></li> <li><a href="https://github.com/tjkuson"><code>@tjkuson</code></a></li> <li><a href="https://github.com/charliermarsh"><code>@charliermarsh</code></a></li> <li><a href="https://github.com/chirizxc"><code>@chirizxc</code></a></li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href=" |
||
|
|
37faf2f247
|
chore: release 0.36.1 (#3152)
## Description Release 0.36.1, generated by Release Please, containing the security fixes from #2207 (WEB-01–07). This updates the changelog and keeps Python, TypeScript SDK, plugin package, marketplace, server, and release metadata versions aligned at 0.36.1. ## Type of Change - [x] Release / version metadata ## Changes Made - Updated the release manifest and generated changelog for 0.36.1. - Synchronized `pyproject.toml`, TypeScript SDK, OpenClaw, OpenCode, agent-hook plugin, marketplace, server, and release metadata versions. - Included the 0.36.1 changelog entry for the security assessment fixes merged in #2207. ## Testing - [x] CI and release validation pass ### Test Output All current required checks are complete and passing, including version sync, package builds, wheel smoke imports, security scans, Python test shards, native wrapper checks, and devcontainer validation. ## Real Behavior Proof - Environment: GitHub Actions release and CI workflows for commit `52c0a0c61dce0af81af3ff73a34efe8b451501cb`. - Observed result: all generated version-bearing files report 0.36.1; build and smoke-import jobs produced and validated the release artifacts. - Not exercised: publishing jobs are intentionally skipped for a pull request and run only after the release receives final human approval and is merged. ## Runtime Rollout Safety - Rollout-managed features: none; this PR packages already-merged behavior. - Stable/default behavior changed: no additional runtime behavior beyond the included, already-reviewed security fixes. - Kill switch / disable path: not applicable to generated release metadata. - Qualification impact: release artifact construction and smoke-import validation are green. - Rollback path: do not merge the release PR, or revert the release commit before publishing. ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Release Notes ### Bug Fixes - **security:** address u9up assessment findings (WEB-01–07) (#2207) This PR was generated with Release Please and then its description was expanded to document review and qualification evidence. It still requires final human review; no publishing or merge has been performed. --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
b88b9078d8
|
chore: release 0.36.0 (#3067)
🤖 I have created a release *beep* *boop* --- ## [0.36.0](https://github.com/headroomlabs-ai/headroom/compare/v0.35.0...v0.36.0) (2026-08-20) ### Features * add deterministic runtime rollout controls ([#1490](https://github.com/headroomlabs-ai/headroom/issues/1490)) ([ |
||
|
|
df6ff6bd5b
|
fix(deps): bump datasets past PYSEC-2026-3716 (#3136)
## Why this is urgent
`datasets` 4.5.0 picked up **PYSEC-2026-3716** — path traversal in
folder-based dataset builders, where an unvalidated `file_name` metadata
field is joined to the dataset directory, so crafted traversal sequences
can read arbitrary local files into output on
`save_to_disk`/`push_to_hub`.
**The advisory was published today between 07:17 and 15:35 UTC.**
`main`'s audit passed at 07:17 on `
|
||
|
|
8156d4dc3a
|
fix(deps): raise the GitPython floor to 3.1.58 to clear 9 open advisories (#3120)
## Description
The reported advisory — **GHSA-956x-8gvw-wg5v** (High; command injection
via unguarded Git options in `Repo.archive()` / `git.ls_remote()`,
arbitrary file overwrite via `Repo.iter_commits()` / `Repo.blame()`) —
is fixed in GitPython **3.1.51**, and the lock already resolved to
**3.1.54**. So that specific advisory was not live exposure.
Checking the alert list rather than that one advisory turned up the real
problem: **nine other GitPython advisories are open against `uv.lock`**,
and 3.1.54 is inside all of their ranges.
| advisory | severity | affected | fixed in |
|---|---|---|---|
| GHSA-hmq2-w58f-27jc | High | ≤ 3.1.57 | 3.1.58 |
| GHSA-jm78-9fvv-mhgr | High | ≤ 3.1.57 | 3.1.58 |
| GHSA-wvpp-8hx9-p66j | High | ≤ 3.1.57 | 3.1.58 |
| GHSA-9rj7-rf2p-w77r | High | ≤ 3.1.57 | 3.1.58 |
| GHSA-4gmw-gg2m-w46p | High | ≤ 3.1.57 | 3.1.58 |
| GHSA-hh9p-6wh2-4mfc | Medium | ≤ 3.1.57 | 3.1.58 |
| GHSA-3f7w-8rr8-f37f | High | ≤ 3.1.56 | 3.1.57 |
| GHSA-539m-9xh6-q6rr | Medium | ≤ 3.1.56 | 3.1.57 |
| GHSA-p538-c434-8v24 | Medium | ≤ 3.1.55 | 3.1.56 |
The existing `[tool.uv] constraint-dependencies` floor was
`gitpython>=3.1.50`, set for an earlier batch, and had gone stale.
**Reachability:** GitPython is a transitive dependency (via `agno`) and
is imported nowhere in `headroom/`. This is a supply-chain floor bump,
not a fix to code we call.
## Type of Change
- [x] Bug fix (non-breaking change that fixes an issue)
## Changes Made
- `pyproject.toml`: raised the `constraint-dependencies` floor from
`gitpython>=3.1.50` to `>=3.1.58`, following the file's existing pattern
for transitive security floors, and replaced the stale comment with the
advisories it now covers. 3.1.58 is the highest fixed version across
**every** GitPython advisory published to date, so the floor clears all
of them rather than only the newest.
- `uv.lock`: regenerated with `uv lock --upgrade-package gitpython`;
resolves 3.1.54 → 3.1.59.
## Testing
- [x] Unit tests pass (`pytest`)
- [x] Manual testing performed
### Test Output
```text
tests/test_optional_dependencies.py tests/test_litellm_optional.py
tests/test_mcp_dependency_contract.py tests/test_onnx_dependency_contract.py
tests/test_toin_publish.py tests/test_release_workflows.py
1 failed, 61 passed, 1 skipped
Lock delta (263 packages before and after):
ADDED : none
REMOVED : none
CHANGED : {'gitpython': ('3.1.54', '3.1.59')}
```
The single failure is `test_no_native_tls_in_wheel_build_tree`,
pre-existing and environmental (no `cargo` on this machine); it fails
identically on a plain-`main` checkout.
## Real Behavior Proof
- Environment: macOS (darwin 25.4.0), Python 3.12.13, `uv` resolver,
worktree off `main` @ `
|
||
|
|
ff17961cd7
|
deps: bump ruff from 0.15.22 to 0.16.2 in the pip-minor-patch group across 1 directory (#2962)
Bumps the pip-minor-patch group with 1 update in the / directory: [ruff](https://github.com/astral-sh/ruff). Updates `ruff` from 0.15.22 to 0.16.2 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/astral-sh/ruff/releases">ruff's releases</a>.</em></p> <blockquote> <h2>0.16.2</h2> <h2>Release Notes</h2> <p>Released on 2026-08-06.</p> <h3>Bug fixes</h3> <ul> <li>[<code>flake8-pyi</code>] Avoid false positives on <code>singledispatch</code> functions (<code>PYI041</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/27335">#27335</a>)</li> </ul> <h3>Server</h3> <ul> <li>Register formatting capabilities dynamically to exclude TOML files (<a href="https://redirect.github.com/astral-sh/ruff/pull/27332">#27332</a>)</li> </ul> <h3>Contributors</h3> <ul> <li><a href="https://github.com/MeGaGiGaGon"><code>@MeGaGiGaGon</code></a></li> <li><a href="https://github.com/charliermarsh"><code>@charliermarsh</code></a></li> <li><a href="https://github.com/epage"><code>@epage</code></a></li> <li><a href="https://github.com/sharkdp"><code>@sharkdp</code></a></li> <li><a href="https://github.com/ntBre"><code>@ntBre</code></a></li> </ul> <h2>Install ruff 0.16.2</h2> <h3>Install prebuilt binaries via shell script</h3> <pre lang="sh"><code>curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-installer.sh | sh </code></pre> <h3>Install prebuilt binaries via powershell script</h3> <pre lang="sh"><code>powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-installer.ps1 | iex" </code></pre> <h2>Download ruff 0.16.2</h2> <table> <thead> <tr> <th>File</th> <th>Platform</th> <th>Checksum</th> </tr> </thead> <tbody> <tr> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-aarch64-apple-darwin.tar.gz">ruff-aarch64-apple-darwin.tar.gz</a></td> <td>Apple Silicon macOS</td> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-aarch64-apple-darwin.tar.gz.sha256">checksum</a></td> </tr> <tr> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-x86_64-apple-darwin.tar.gz">ruff-x86_64-apple-darwin.tar.gz</a></td> <td>Intel macOS</td> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-x86_64-apple-darwin.tar.gz.sha256">checksum</a></td> </tr> <tr> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-aarch64-pc-windows-msvc.zip">ruff-aarch64-pc-windows-msvc.zip</a></td> <td>ARM64 Windows</td> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-aarch64-pc-windows-msvc.zip.sha256">checksum</a></td> </tr> <tr> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-i686-pc-windows-msvc.zip">ruff-i686-pc-windows-msvc.zip</a></td> <td>x86 Windows</td> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-i686-pc-windows-msvc.zip.sha256">checksum</a></td> </tr> <tr> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-x86_64-pc-windows-msvc.zip">ruff-x86_64-pc-windows-msvc.zip</a></td> <td>x64 Windows</td> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-x86_64-pc-windows-msvc.zip.sha256">checksum</a></td> </tr> <tr> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-aarch64-unknown-linux-gnu.tar.gz">ruff-aarch64-unknown-linux-gnu.tar.gz</a></td> <td>ARM64 Linux</td> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256">checksum</a></td> </tr> <tr> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-i686-unknown-linux-gnu.tar.gz">ruff-i686-unknown-linux-gnu.tar.gz</a></td> <td>x86 Linux</td> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-i686-unknown-linux-gnu.tar.gz.sha256">checksum</a></td> </tr> <tr> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-powerpc64-unknown-linux-gnu.tar.gz">ruff-powerpc64-unknown-linux-gnu.tar.gz</a></td> <td>PPC64 Linux</td> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256">checksum</a></td> </tr> <tr> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-powerpc64le-unknown-linux-gnu.tar.gz">ruff-powerpc64le-unknown-linux-gnu.tar.gz</a></td> <td>PPC64LE Linux</td> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256">checksum</a></td> </tr> <tr> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-riscv64gc-unknown-linux-gnu.tar.gz">ruff-riscv64gc-unknown-linux-gnu.tar.gz</a></td> <td>RISCV Linux</td> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256">checksum</a></td> </tr> <tr> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-s390x-unknown-linux-gnu.tar.gz">ruff-s390x-unknown-linux-gnu.tar.gz</a></td> <td>S390x Linux</td> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-s390x-unknown-linux-gnu.tar.gz.sha256">checksum</a></td> </tr> </tbody> </table> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md">ruff's changelog</a>.</em></p> <blockquote> <h2>0.16.2</h2> <p>Released on 2026-08-06.</p> <h3>Bug fixes</h3> <ul> <li>[<code>flake8-pyi</code>] Avoid false positives on <code>singledispatch</code> functions (<code>PYI041</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/27335">#27335</a>)</li> </ul> <h3>Server</h3> <ul> <li>Register formatting capabilities dynamically to exclude TOML files (<a href="https://redirect.github.com/astral-sh/ruff/pull/27332">#27332</a>)</li> </ul> <h3>Contributors</h3> <ul> <li><a href="https://github.com/MeGaGiGaGon"><code>@MeGaGiGaGon</code></a></li> <li><a href="https://github.com/charliermarsh"><code>@charliermarsh</code></a></li> <li><a href="https://github.com/epage"><code>@epage</code></a></li> <li><a href="https://github.com/sharkdp"><code>@sharkdp</code></a></li> <li><a href="https://github.com/ntBre"><code>@ntBre</code></a></li> </ul> <h2>0.16.1</h2> <p>Released on 2026-07-30.</p> <h3>Preview features</h3> <ul> <li>Add an option to opt out of human-readable names (<a href="https://redirect.github.com/astral-sh/ruff/pull/27160">#27160</a>)</li> <li>[<code>flake8-pytest-style</code>] Make fixes safe by default and unsafe only when comments are present (<code>PT018</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/27201">#27201</a>)</li> <li>[<code>pyupgrade</code>] Skip fix when a defaulted <code>TypeVar</code> precedes a non-defaulted one (<code>UP040</code>, <code>UP046</code>, <code>UP047</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/27133">#27133</a>)</li> <li>[<code>ruff</code>] Fix false positive with unpacked arguments (<code>RUF065</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/26959">#26959</a>)</li> </ul> <h3>Bug fixes</h3> <ul> <li>Bump <code>gen-lsp-types</code> to gracefully handle unknown enumeration values in LSP messages (<a href="https://redirect.github.com/astral-sh/ruff/pull/27230">#27230</a>)</li> <li>[<code>flake8-bugbear</code>] Mark <code>range</code> as immutable (<code>B008</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/27247">#27247</a>)</li> <li>[<code>flake8-comprehensions</code>] NFKC-normalize keyword names in <code>C408</code> fix (<a href="https://redirect.github.com/astral-sh/ruff/pull/26813">#26813</a>)</li> <li>[<code>flake8-return</code>] Fix false positive when variable is read in <code>finally</code> clause (<code>RET504</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/25441">#25441</a>)</li> <li>[<code>pydocstyle</code>] Skip section detection inside RST directive bodies (<code>D214</code>, <code>D405</code>, <code>D413</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/23635">#23635</a>)</li> <li>[<code>refurb</code>] Parenthesize <code>yield</code> arguments in the <code>FURB192</code> fix (<a href="https://redirect.github.com/astral-sh/ruff/pull/27192">#27192</a>)</li> </ul> <h3>Rule changes</h3> <ul> <li>[<code>flake8-pytest-style</code>] Mark <code>PT022</code> fixes as unsafe (<a href="https://redirect.github.com/astral-sh/ruff/pull/26440">#26440</a>)</li> <li>[<code>refurb</code>] Mark fixes that remove unknown separators as unsafe (<code>FURB105</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/27200">#27200</a>)</li> </ul> <h3>Server</h3> <ul> <li>Fix indexing of excluded nested Ruff workspaces (<a href="https://redirect.github.com/astral-sh/ruff/pull/27303">#27303</a>)</li> <li>Lint TOML files in the LSP (<a href="https://redirect.github.com/astral-sh/ruff/pull/26862">#26862</a>)</li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href=" |
||
|
|
a3fe5cb65b
|
fix(onnx): enforce Rust API-24 runtime compatibility (#2979)
## Description Rust fastembed enables ORT C API 24, but the Python dependency allowed ONNX Runtime 1.23.2. Entering ort's initializer with that library deadlocks permanently instead of returning an error. Align dependency resolution where compatible wheels exist and preflight native detection where they do not. Closes #2960 ## Type of Change - [x] Bug fix (non-breaking change that fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - Require ONNX Runtime 1.24+ for Python 3.11+ in the proxy and voice extras. - Keep the available pre-1.24 runtime on Python 3.10 for Python ONNX consumers. - Refuse to auto-pin an incompatible runtime into the Rust extension. - Bypass native detection immediately when API 24 is unavailable, preserving Python fallback without a five-second watchdog delay or stuck native thread. - Add dependency, pinning, override, and router regression coverage. ## Testing - [x] Unit tests pass (`pytest`) - [x] Linting passes (`ruff check .`) - [ ] Type checking passes (`mypy headroom`) - [x] New tests added for new functionality - [x] Manual testing performed ### Test Output ```text $ uv run pytest -q tests/test_transforms/test_ort_dylib.py tests/test_onnx_dependency_contract.py tests/test_onnx_runtime.py tests/test_transforms/test_content_router.py 88 passed in 9.31s $ uv run ruff check headroom/_ort.py headroom/transforms/content_router.py tests/test_transforms/test_ort_dylib.py tests/test_onnx_dependency_contract.py All checks passed! ``` ## Real Behavior Proof - Environment: macOS arm64; Python 3.13.14 and uv-managed Python 3.10.20. - Exact command / steps: run the issue's direct `headroom._core.detect_content_type` call in a subprocess with a 12-second timeout on Python 3.13; run `_detect_content` on Python 3.10 after resolving the proxy extra. - Observed result: Python 3.13 resolves ORT 1.26.0 and native detection returns `json_array`; Python 3.10 resolves ORT 1.23.2, leaves `ORT_DYLIB_PATH` unset, reports compatibility false, and immediately returns the Python `json_array` fallback. - Not tested: Linux-specific shared-object execution locally; CI's existing Linux Rust job already preflights ORT 1.24+ and exercises native tests. ## Runtime Rollout Safety - Rollout-managed feature(s): Native Rust content detection. - Minimum rollout channel: Stable/default; this is a deadlock prevention guard. - Stable/default behavior changed: Python 3.11+ installs a compatible ORT; Python 3.10 skips incompatible native detection. - Kill switch / disable path: `HEADROOM_DETECT_BACKEND=python` remains available; an explicit `ORT_DYLIB_PATH` remains an operator override. - Unsafe override required: No. - Qualification impact: Native detection stays enabled only with API-24-compatible ORT. - Rollback path: Revert this PR, which restores the old watchdog-only degradation. ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Checklist - [x] My code follows the project's style guidelines - [x] I have performed a self-review of my code - [x] I have commented my code, particularly in hard-to-understand areas - [x] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [x] I did **not** edit `CHANGELOG.md` — it is generated by release-please from my Conventional Commit PR title (a CI guard enforces this) ## Screenshots (if applicable) Not applicable. ## Additional Notes The large lockfile diff is dependency resolution: Python 3.10 keeps ORT 1.23.2 while 3.11+ resolves 1.26.0. The functional Python change is intentionally small and keeps explicit `ORT_DYLIB_PATH` overrides working. |
||
|
|
6077e5a149
|
fix(mcp): restore SDK v1 compatibility cap (#2978)
## Description PR #2963 widened the MCP dependency to 2.x while Headroom's live MCP server still uses the v1 low-level `Server.list_tools()` and `Server.call_tool()` decorators. Fresh installs therefore crash before serving tools. Restore the v1 cap until the explicit SDK 2.x port in #2658 lands, and pin that compatibility contract with a regression test. Closes #2977 ## Type of Change - [x] Bug fix (non-breaking change that fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - Restore `mcp>=1.28.1,<2.0.0` in the `proxy` and `mcp` extras. - Regenerate `uv.lock`, resolving MCP 1.28.1 and removing the incompatible 2.x transitive set. - Add a dependency-contract test covering both shipping extras. ## Testing - [x] Unit tests pass (`pytest`) - [x] Linting passes (`ruff check .`) - [ ] Type checking passes (`mypy headroom`) - [x] New tests added for new functionality - [x] Manual testing performed ### Test Output ```text $ uv run pytest -q tests/test_mcp_dependency_contract.py tests/test_ccr_mcp_server.py tests/test_cli/test_mcp.py 41 passed in 0.56s $ uv run ruff check tests/test_mcp_dependency_contract.py All checks passed! $ uv run ruff format --check tests/test_mcp_dependency_contract.py 1 file already formatted ``` ## Real Behavior Proof - Environment: macOS arm64, Python 3.13.14, uv-managed project environment. - Exact command / steps: resolve the `mcp` extra, inspect the installed SDK version and v1 decorators, then instantiate `HeadroomMCPServer(check_proxy=False)`. - Observed result: `1.28.1 True True`; server construction returns a v1 `Server` successfully. - Not tested: full stdio exchange against every external MCP client; existing MCP unit and CLI suites cover server setup and handlers. ## Runtime Rollout Safety - Rollout-managed feature(s): None; dependency resolution guard. - Minimum rollout channel: Stable/default. - Stable/default behavior changed: Fresh installs stop resolving the incompatible MCP SDK 2.x release. - Kill switch / disable path: Revert the dependency cap after #2658 lands. - Unsafe override required: No. - Qualification impact: MCP extras and proxy installs remain on the maintained MCP 1.x line. - Rollback path: Revert this PR; not recommended until the v2 server port is merged and tested. ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Checklist - [x] My code follows the project's style guidelines - [x] I have performed a self-review of my code - [x] I have commented my code, particularly in hard-to-understand areas - [x] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [x] I did **not** edit `CHANGELOG.md` — it is generated by release-please from my Conventional Commit PR title (a CI guard enforces this) ## Screenshots (if applicable) Not applicable. ## Additional Notes The documentation change is the inline dependency rationale next to the cap. The long-term migration remains #2658; this PR deliberately does not mix that breaking SDK port into the release-blocker rollback. |
||
|
|
b7f342c153
|
fix(wrap): verify proxy deps before mutating Codex config (#1628)
## Description \`headroom wrap codex\` now verifies that optional proxy dependencies (\`headroom-ai[proxy]\`) are installed before mutating Codex \`config.toml\`. If the check fails, the command exits with the same error message as \`headroom proxy\` and leaves Codex config untouched. Fixes #1614 (Bug 1: config mutated before proxy dependency check). ## Type of Change - [x] Bug fix (non-breaking change that fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - Extract \`ensure_proxy_dependencies()\` in \`headroom/cli/proxy.py\` (shared with \`headroom proxy\`) - Call it at the start of \`wrap codex\` when \`not no_proxy\`, before config snapshot/injection - Add regression tests for prepare-only abort, \`--no-proxy\` skip, and import failure messaging ## Testing - [x] Unit tests pass (\`pytest\`) - [x] Linting passes (\`ruff check .\`) - [ ] Type checking passes (\`mypy headroom\`) - [x] New tests added for new functionality - [x] Manual testing performed ### Test Output \`\`\`bash pytest tests/test_cli/test_wrap_codex.py::test_wrap_codex_aborts_before_mutating_config_when_proxy_deps_missing \ tests/test_cli/test_wrap_codex.py::test_wrap_codex_skips_proxy_dependency_check_with_no_proxy \ tests/test_cli/test_wrap_codex.py::test_ensure_proxy_dependencies_exits_when_server_import_fails -q # 3 passed ruff check headroom/cli/wrap.py headroom/cli/proxy.py tests/test_cli/test_wrap_codex.py ruff format --check headroom/cli/wrap.py headroom/cli/proxy.py tests/test_cli/test_wrap_codex.py \`\`\` ## Real Behavior Proof Environment: Linux (Ubuntu), Python 3.12, local checkout with \`PYTHONPATH\` pointed at patched sources. Exact command / steps: 1. Created a temp \`~/.codex/config.toml\` with \`model_provider = "openai"\`. 2. Patched \`headroom.cli.wrap.ensure_proxy_dependencies\` to raise \`SystemExit(1)\` (simulating missing \`[proxy]\` extra). 3. Ran \`headroom wrap codex --prepare-only --no-serena --port 8787\`. Observed result: exit code 1; \`config.toml\` unchanged; no \`config.toml.headroom-backup\` created; no \`[mcp_servers.headroom]\` block written. Also verified: \`headroom wrap codex --prepare-only --no-proxy ...\` does not invoke the dependency check. Not tested: Windows-specific proxy selector behavior (covered separately in #1655). ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Checklist - [x] My code follows the project's style guidelines - [x] I have performed a self-review of my code - [x] I have commented my code, particularly in hard-to-understand areas - [x] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [x] I did not edit CHANGELOG.md; release notes are generated automatically --------- Co-authored-by: syf2211 <syf2211@users.noreply.github.com> Co-authored-by: JerrettDavis <mxjerrett@gmail.com> Co-authored-by: JD Davis <jd@jds-macbook-air.tail2a279.ts.net> |
||
|
|
d6fb5365f6
|
deps: update mcp requirement from <2.0.0,>=1.28.1 to >=1.28.1,<3.0.0 (#2963)
Updates the requirements on [mcp](https://github.com/modelcontextprotocol/python-sdk) to permit the latest version. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/modelcontextprotocol/python-sdk/releases">mcp's releases</a>.</em></p> <blockquote> <h2>v2.0.0</h2> <h1>MCP Python SDK v2 Stable Release</h1> <p>This is v2.0.0, the stable v2 release of the MCP Python SDK. It supports the 2026-07-28 revision of the Model Context Protocol and serves every earlier revision from the same server. <code>pip install mcp</code> now installs 2.x.</p> <pre lang="bash"><code>pip install "mcp[cli]" # or uv add "mcp[cli]" </code></pre> <h3>Documentation Rewrite</h3> <p>The <a href="https://py.sdk.modelcontextprotocol.io/">documentation</a> has the full tutorial and API reference. Coming from v1? <a href="https://py.sdk.modelcontextprotocol.io/whats-new/">What's new in v2</a> is the tour of what changed and why, and the <a href="https://py.sdk.modelcontextprotocol.io/migration/">migration guide</a> lists every breaking change with before-and-after code.</p> <h3>V1 Maintenance mode</h3> <p><strong>v1.x is in maintenance mode and will only receive security fixes from now on</strong> The 1.x line lives on the <a href="https://github.com/modelcontextprotocol/python-sdk/tree/v1.x"><code>v1.x</code> branch</a>, continues to receive critical bug fixes and security patches, and is documented at <a href="https://py.sdk.modelcontextprotocol.io/v1/">https://py.sdk.modelcontextprotocol.io/v1/</a>. If your project is not ready to migrate, keep a <code><2</code> upper bound on your requirement (for example <code>mcp>=1.28,<2</code>).</p> <h2>Highlights</h2> <h3>One SDK, both protocol eras</h3> <p>v2 speaks the 2026-07-28 revision (stateless requests with no handshake, <code>server/discover</code>, <code>subscriptions/listen</code>, multi-round-trip requests) and still serves every 2025-era client from the same <code>MCPServer</code>, over Streamable HTTP and stdio, with nothing to configure. <code>Client(target)</code> negotiates the version automatically.</p> <h3><code>FastMCP</code> is now <code>MCPServer</code>, and there is a first-class <code>Client</code></h3> <p>The decorator API is unchanged; the low-level <code>Server</code> is rebuilt around a shared dispatcher engine, and one <code>Client</code> object replaces v1's transport-plus-<code>ClientSession</code>-plus-<code>initialize()</code> layering. It connects to a URL, a stdio subprocess, a custom transport, or straight to a server object in memory for tests.</p> <h3>Multi-round-trip requests and resolver dependency injection</h3> <p>At 2026-07-28 the server can no longer call the client, so tools return the question instead. A <code>Resolve(fn)</code> parameter is filled by your function invisibly to the model and can put a question to the user; one tool body serves both eras.</p> <h3>Extension APIs, OpenTelemetry, and a standalone types package</h3> <p>Servers and clients compose protocol extensions through pluggable extension APIs (MCP Apps built in); OpenTelemetry tracing ships on by default; every protocol type is its own package, <code>mcp-types</code> (imported as <code>mcp_types</code>), published in lock-step with <code>mcp</code>.</p> <h3>Hardened stdio and auth</h3> <p>stdio servers keep handler subprocesses and stray prints off the wire, and stdout is diverted to stderr while serving. OAuth adds RFC 9207 issuer validation, the SEP-990 identity-assertion flow, and the client-credentials extension.</p> <h2>Coming from a v2 pre-release</h2> <p>Since the last release candidate: the per-version wire packages are private (<code>mcp_types._v*</code>), <code>mcp.types</code> is a permanent alias for <code>mcp_types</code>, the auth registration request model is split from the registered-client record, cancelled requests are no longer answered, and log notifications are gated on the per-request log-level opt-in at 2026-07-28. Since the betas: <code>Client(cache=False)</code> is now <code>cache=None</code> with <code>CacheConfig()</code> the default; <code>Context.client_id</code>, <code>RFC7523OAuthClientProvider</code>, and <code>OAuthClientProvider(timeout=)</code> are removed; the client-credentials providers take <code>scope=</code>; <code>message_handler</code> receives notifications and exceptions only; <code>FileResource(is_binary=)</code> becomes <code>encoding</code>; <code>MCP_*</code> env vars are gone with <code>pydantic-settings</code>; Streamable HTTP servers reject bodies over 4 MiB with HTTP 413. The migration guide covers all of it.</p> <h2>Known gaps</h2> <p>The tasks extension (SEP-2663) is not part of this release. On the client, the DPoP proof binding (SEP-1932) and the workload-identity <code>jwt-bearer</code> grant are not implemented; both are additive and can land in 2.x.</p> <h2>Feedback</h2> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href=" |
||
|
|
93f2d7a2da
|
chore: release main (#2792)
🤖 I have created a release *beep* *boop* --- <details><summary>0.35.0</summary> ## [0.35.0](https://github.com/headroomlabs-ai/headroom/compare/v0.34.0...v0.35.0) (2026-08-12) ### Features * **beacon:** allowlist the routing summary key ([#2818](https://github.com/headroomlabs-ai/headroom/issues/2818)) ([ |
||
|
|
ecf130d3ac
|
deps: bump ruff from 0.15.17 to 0.15.22 in the pip-minor-patch group (#2501)
Bumps the pip-minor-patch group with 1 update: [ruff](https://github.com/astral-sh/ruff). Updates `ruff` from 0.15.17 to 0.15.22 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/astral-sh/ruff/releases">ruff's releases</a>.</em></p> <blockquote> <h2>0.15.22</h2> <h2>Release Notes</h2> <p>Released on 2026-07-16.</p> <h3>Preview features</h3> <ul> <li>[<code>pycodestyle</code>] Add an autofix for <code>E402</code> (<a href="https://redirect.github.com/astral-sh/ruff/pull/22212">#22212</a>)</li> <li>[<code>refurb</code>] Allow subclassing builtins in stub files (<code>FURB189</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/26812">#26812</a>)</li> <li>[<code>ruff</code>] Add rule to replace <code>noqa</code> comments with <code>ruff:ignore</code> (<code>RUF105</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/26423">#26423</a>)</li> <li>[<code>ruff</code>] Add rule to use human-readable names in <code>ruff:ignore</code> comments (<code>RUF106</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/26682">#26682</a>)</li> <li>[<code>ruff</code>] Add rule to use human-readable names in configuration selectors (<code>RUF201</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/26772">#26772</a>)</li> </ul> <h3>Bug fixes</h3> <ul> <li>[<code>flake8-pyi</code>] Fix false positive in <code>__all__</code> (<code>PYI053</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/26872">#26872</a>)</li> </ul> <h3>Rule changes</h3> <ul> <li>[<code>pylint</code>] Ignore mutable type updates in <code>redefined-loop-name</code> (<code>PLW2901</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/25733">#25733</a>)</li> </ul> <h3>Performance</h3> <ul> <li>Avoid redundant lexer token bookkeeping (<a href="https://redirect.github.com/astral-sh/ruff/pull/26765">#26765</a>)</li> <li>Avoid redundant pending-indentation writes (<a href="https://redirect.github.com/astral-sh/ruff/pull/26774">#26774</a>)</li> <li>Avoid unnecessary identifier lookahead (<a href="https://redirect.github.com/astral-sh/ruff/pull/26525">#26525</a>)</li> <li>Reuse parser scratch buffers (<a href="https://redirect.github.com/astral-sh/ruff/pull/26798">#26798</a>)</li> </ul> <h3>Documentation</h3> <ul> <li>Document argfile support (<a href="https://redirect.github.com/astral-sh/ruff/pull/26803">#26803</a>)</li> <li>[<code>flake8-datetimez</code>] Clarify naming guidance for <code>datetime.today</code> (<code>DTZ002</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/26658">#26658</a>)</li> <li>[<code>pycodestyle</code>] Document <code>E731</code> fix safety (<a href="https://redirect.github.com/astral-sh/ruff/pull/26847">#26847</a>)</li> <li>[<code>ruff</code>] Clarify intentional async contexts for <code>unused-async</code> (<code>RUF029</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/26641">#26641</a>)</li> </ul> <h3>Contributors</h3> <ul> <li><a href="https://github.com/dwego"><code>@dwego</code></a></li> <li><a href="https://github.com/MichaReiser"><code>@MichaReiser</code></a></li> <li><a href="https://github.com/Joosboy"><code>@Joosboy</code></a></li> <li><a href="https://github.com/KaufmanDmitriy"><code>@KaufmanDmitriy</code></a></li> <li><a href="https://github.com/PeterJCLaw"><code>@PeterJCLaw</code></a></li> <li><a href="https://github.com/ntBre"><code>@ntBre</code></a></li> <li><a href="https://github.com/charliermarsh"><code>@charliermarsh</code></a></li> </ul> <h2>Install ruff 0.15.22</h2> <h3>Install prebuilt binaries via shell script</h3> <pre lang="sh"><code></tr></table> </code></pre> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md">ruff's changelog</a>.</em></p> <blockquote> <h2>0.15.22</h2> <p>Released on 2026-07-16.</p> <h3>Preview features</h3> <ul> <li>[<code>pycodestyle</code>] Add an autofix for <code>E402</code> (<a href="https://redirect.github.com/astral-sh/ruff/pull/22212">#22212</a>)</li> <li>[<code>refurb</code>] Allow subclassing builtins in stub files (<code>FURB189</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/26812">#26812</a>)</li> <li>[<code>ruff</code>] Add rule to replace <code>noqa</code> comments with <code>ruff:ignore</code> (<code>RUF105</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/26423">#26423</a>)</li> <li>[<code>ruff</code>] Add rule to use human-readable names in <code>ruff:ignore</code> comments (<code>RUF106</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/26682">#26682</a>)</li> <li>[<code>ruff</code>] Add rule to use human-readable names in configuration selectors (<code>RUF201</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/26772">#26772</a>)</li> </ul> <h3>Bug fixes</h3> <ul> <li>[<code>flake8-pyi</code>] Fix false positive in <code>__all__</code> (<code>PYI053</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/26872">#26872</a>)</li> </ul> <h3>Rule changes</h3> <ul> <li>[<code>pylint</code>] Ignore mutable type updates in <code>redefined-loop-name</code> (<code>PLW2901</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/25733">#25733</a>)</li> </ul> <h3>Performance</h3> <ul> <li>Avoid redundant lexer token bookkeeping (<a href="https://redirect.github.com/astral-sh/ruff/pull/26765">#26765</a>)</li> <li>Avoid redundant pending-indentation writes (<a href="https://redirect.github.com/astral-sh/ruff/pull/26774">#26774</a>)</li> <li>Avoid unnecessary identifier lookahead (<a href="https://redirect.github.com/astral-sh/ruff/pull/26525">#26525</a>)</li> <li>Reuse parser scratch buffers (<a href="https://redirect.github.com/astral-sh/ruff/pull/26798">#26798</a>)</li> </ul> <h3>Documentation</h3> <ul> <li>Document argfile support (<a href="https://redirect.github.com/astral-sh/ruff/pull/26803">#26803</a>)</li> <li>[<code>flake8-datetimez</code>] Clarify naming guidance for <code>datetime.today</code> (<code>DTZ002</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/26658">#26658</a>)</li> <li>[<code>pycodestyle</code>] Document <code>E731</code> fix safety (<a href="https://redirect.github.com/astral-sh/ruff/pull/26847">#26847</a>)</li> <li>[<code>ruff</code>] Clarify intentional async contexts for <code>unused-async</code> (<code>RUF029</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/26641">#26641</a>)</li> </ul> <h3>Contributors</h3> <ul> <li><a href="https://github.com/dwego"><code>@dwego</code></a></li> <li><a href="https://github.com/MichaReiser"><code>@MichaReiser</code></a></li> <li><a href="https://github.com/Joosboy"><code>@Joosboy</code></a></li> <li><a href="https://github.com/KaufmanDmitriy"><code>@KaufmanDmitriy</code></a></li> <li><a href="https://github.com/PeterJCLaw"><code>@PeterJCLaw</code></a></li> <li><a href="https://github.com/ntBre"><code>@ntBre</code></a></li> <li><a href="https://github.com/charliermarsh"><code>@charliermarsh</code></a></li> </ul> <h2>0.15.21</h2> <p>Released on 2026-07-09.</p> <h3>Preview features</h3> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href=" |
||
|
|
64e203931b
|
fix(deps): enforce audited transitive dependency floors (#2791)
## Description Enforces patched minimum versions for the vulnerable transitive `aiohttp` and `cryptography` dependencies so future lockfile refreshes cannot reintroduce the pip-audit failures affecting open pull requests. Related to the shared Security / pip-audit failures across open PRs. ## Type of Change - [x] Bug fix (non-breaking change that fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - Enforces `aiohttp>=3.14.3` for PYSEC-2026-3545/3546/3547. - Enforces `cryptography>=50.0.0` for PYSEC-2026-3552/3553/3554. - Synchronizes the project version recorded in `uv.lock` with `pyproject.toml`. ## Testing - [x] Dependency audit passes (`pip-audit`) - [x] Lockfile validation passes (`uv lock --check`) - [ ] Unit tests pass (`pytest`) - [ ] Type checking passes (`mypy headroom`) - [x] Manual verification performed ### Test Output ```text $ uv lock --check Resolved 269 packages $ uv export --frozen --no-dev --no-emit-project --no-hashes --extra all --format requirements-txt | uvx --python 3.12 pip-audit -r /dev/stdin No known vulnerabilities found ``` ## Real Behavior Proof - Environment: Local macOS worktree using CPython 3.12.13 and the frozen production dependency export. - Exact command / steps: Validated the lockfile, exported every production dependency with the `all` extra, and audited that exact export with pip-audit. - Observed result: The lockfile resolved successfully and pip-audit reported no known vulnerabilities. - Not tested: Publishing or deployment; the refreshed GitHub CI suite covers builds, wheels, containers, security scans, and platform tests. ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Checklist - [x] My code follows the project style guidelines - [x] I have performed a self-review of my changes - [x] No explanatory code comments are required beyond the PYSEC constraint annotations - [x] Documentation changes are not required for transitive security floors - [x] My changes generate no new local warnings - [x] The dependency audit proves the security fix is effective - [ ] Full repository tests are delegated to GitHub CI - [x] I did not edit `CHANGELOG.md`; release-please owns it ## Screenshots (if applicable) N/A — dependency metadata only. ## Additional Notes The earlier Docker-native failure was a transient Docker Hub HTTP 502 while resolving `python:3.13-slim`; the build did not reach project code. A fresh CI suite is running on the current head. Co-authored-by: JD Davis <jd@jds-macbook-air.tail2a279.ts.net> |
||
|
|
9fd5ae3d53
|
chore: release main (#2679)
🤖 I have created a release *beep* *boop* --- <details><summary>0.34.0</summary> ## [0.34.0](https://github.com/headroomlabs-ai/headroom/compare/v0.33.0...v0.34.0) (2026-08-05) ### Features * **claude:** support Claude Code in VS Code ([#2752](https://github.com/headroomlabs-ai/headroom/issues/2752)) ([ |
||
|
|
28aa53dc7c
|
chore: release main (#2339)
🤖 I have created a release *beep* *boop* --- <details><summary>0.33.0</summary> ## [0.33.0](https://github.com/headroomlabs-ai/headroom/compare/v0.32.0...v0.33.0) (2026-07-29) ### Features * **lossless:** factor shared directory prefix in the grep search fold ([#2547](https://github.com/headroomlabs-ai/headroom/issues/2547)) ([ |
||
|
|
b3f016b866
|
fix(mcp): pin mcp dependency to <2.0.0 to prevent server startup crash (#2642)
## Description
The MCP Python SDK recently released version `2.0.0`, which introduced
breaking changes to the high-level server interface (removing
`.list_tools()` and `.call_tool()` decorators on `mcp.server.Server`).
Because `headroom-ai` specified `mcp>=1.28.1` without an upper bound,
installing or upgrading `headroom-ai` pulled in `mcp 2.0.0`. When
`headroom mcp serve` was started by an MCP client (such as OpenCode or
Claude Code), the server crashed immediately on startup with
`AttributeError: 'Server' object has no attribute 'list_tools'`,
resulting in the connection closing error (`headroom MCP error -32000:
Connection closed`).
This PR pins the `mcp` dependency to `<2.0.0` (`mcp>=1.28.1,<2.0.0`) in
`pyproject.toml` so compatible 1.x SDK releases (e.g. `1.29.0`) are
used.
## Type of Change
- [x] Bug fix (non-breaking change that fixes an issue)
- [ ] New feature (non-breaking change that adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] Documentation update
- [ ] Performance improvement
- [ ] Code refactoring (no functional changes)
## Changes Made
- Pinned `mcp` dependency to `"mcp>=1.28.1,<2.0.0"` under both `proxy`
dependencies and the `mcp` extra in `pyproject.toml`.
## Testing
- [x] Unit tests pass (`pytest`)
- [x] Linting passes (`ruff check .`)
- [x] Type checking passes (`mypy headroom`)
- [ ] New tests added for new functionality
- [x] Manual testing performed
### Test Output
```text
$ ruff check pyproject.toml headroom/ccr/mcp_server.py
All checks passed!
$ pytest tests/test_ccr_mcp_server.py tests/test_cli/test_mcp.py tests/test_cli/test_mcp_status.py
============================== 45 passed in 1.03s ==============================
```
## Real Behavior Proof
- Environment: macOS (Darwin arm64), Python 3.14.5, uv
- Exact command / steps: Executed uv sync --all-extras and sent stdio
JSON-RPC initialize and tools/list requests to .venv/bin/headroom mcp
serve.
- Observed result: Server initializes cleanly and returns JSON-RPC
response
{"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2024-11-05","capabilities":{"experimental":{},"tools":{"listChanged":false}},"serverInfo":{"name":"headroom","version":"1.29.0"}}}
with no startup AttributeError or closed pipe errors.
- Not tested: N/A
## Review Readiness
- [x] I have performed a self-review
- [x] This PR is ready for human review
## Checklist
- [x] My code follows the project's style guidelines
- [x] I have performed a self-review of my code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [x] I did not edit CHANGELOG.md — it is generated by release-please
from my Conventional Commit PR title (a CI guard enforces this)
## Screenshots (if applicable)
N/A
## Additional Notes
Capping mcp<2.0.0 ensures stability with current headroom releases while
a future update can adopt MCP SDK 2.x interface changes if desired.
|
||
|
|
2bb14d1ab2
|
fix(ci): align Ruff tooling versions (#2406)
## Description Ruff currently has three independent versions: `uv.lock` resolves `0.14.14`, pre-commit runs `0.9.4`, and CI installs `0.15.17`. Contributors can therefore pass one formatter path and fail another. Make the exact Ruff pin in `pyproject.toml` the source of truth, align the lockfile and pre-commit hook to it, and make CI read that pin through a deterministic consistency verifier instead of carrying another hardcoded version. Closes #2398 ## Type of Change - [x] Bug fix (non-breaking change that fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that causes existing functionality to change) - [ ] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - Pin the existing `[dev]` Ruff dependency to `0.15.17`, the formatter baseline already used by CI. - Refresh only Ruff in `uv.lock` with `uv 0.11.29`. - Align `ruff-pre-commit` to `v0.15.17`. - Add `scripts/verify-ruff-version.py` and run it from pre-commit and CI. - Make CI install the verified version read from `pyproject.toml` rather than a separate literal. ## Testing - [ ] Unit tests pass (`pytest`) — not run; no runtime source or test behavior changed. - [x] Linting passes (`ruff check .`) - [x] Type checking passes (`mypy headroom`) - [x] New deterministic guard proves the configuration fix - [x] Manual testing performed ### Test Output ```text # Before: run the verifier with the patched pyproject pin but base-branch # uv.lock, pre-commit config, and workflow. Ruff version mismatch detected: uv.lock uses Ruff 0.14.14, expected 0.15.17 .pre-commit-config.yaml uses Ruff 0.9.4, expected 0.15.17 ci.yml does not run 'python scripts/verify-ruff-version.py --print-version' ci.yml does not install Ruff from 'steps.ruff-version.outputs.version' $ python3 scripts/verify-ruff-version.py Ruff versions aligned at 0.15.17 $ uvx uv@0.11.29 lock --check Resolved 269 packages $ uvx uv@0.11.29 tree --locked --package ruff ruff v0.15.17 $ uvx ruff@0.15.17 check . All checks passed! $ uvx ruff@0.15.17 format --check . 1322 files already formatted $ uvx mypy@1.20.2 headroom --ignore-missing-imports Success: no issues found in 505 source files $ uvx --with tomli mypy@1.20.2 scripts/verify-ruff-version.py --ignore-missing-imports Success: no issues found in 1 source file $ uvx pre-commit run ruff --all-files Passed $ uvx pre-commit run ruff-format --all-files Passed $ uvx pre-commit run verify-ruff-version --all-files Passed ``` ## Real Behavior Proof - Environment: macOS 26.5, Python 3.14.6 locally; Python 3.10 fallback also exercised; `uv 0.11.29`, Ruff `0.15.17`, mypy `1.20.2`. - Exact command / steps: reproduced the mismatch using the base branch's real `uv.lock`, `.pre-commit-config.yaml`, and `.github/workflows/ci.yml`; then ran the verifier, locked Ruff tree, full Ruff check/format, mypy, and actual pre-commit hooks after the patch. - Observed result: the base state fails with all four drift points listed; the patched state reports one aligned Ruff version (`0.15.17`) and every formatter path passes. - Not tested: runtime proxy behavior and the pytest suite, because the change is limited to development-tool configuration, lock metadata, pre-commit, and CI wiring. ## Dependency / Supply-Chain Justification - Ruff is an existing development-only formatter maintained by Astral; this PR adds no new package. - `0.15.17` is required to fix local/CI reproducibility and has already been the repository's CI formatter baseline since #1295. - Install surface is limited to the `[dev]` extra, lint CI job, and pre-commit environment. Production/runtime dependencies are unchanged. - The `uv.lock` refresh updates only Ruff; no unrelated dependency upgrades are included. ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Checklist - [x] My code follows the project's style guidelines - [x] I have performed a self-review of my code - [x] I have commented the non-obvious consistency checks - [x] Documentation changes are N/A; contributor commands are unchanged - [x] My changes generate no new warnings - [x] The guard fails on the real base-state mismatch and passes after the fix - [ ] New and existing unit tests pass locally — not run; no runtime code changed - [x] I did not edit `CHANGELOG.md`; release-please will use the conventional PR title ## Additional Notes No formatter-driven source changes are included. AI assistance was used to inspect configuration, implement the verifier, and run validation. |
||
|
|
494fb5a60e
|
fix(security): exclude compromised ast-grep-cli 0.44.1 (supply-chain trojan) (#2342)
## Description Fixes #2332. The `ast_grep_cli` **0.44.1** PyPI release was a compromised supply-chain build: it shipped an info-stealer `sg.exe` (212 KB, detected as `Trojan:Win64/Lazy!MTB`) alongside the legitimate `ast-grep` binary as camouflage. `headroom-ai` declares `ast-grep-cli>=0.30.0`, so a fresh PyPI install — `pip install "headroom-ai[all]"` or `uv tool install "headroom-ai[all]"` — can resolve the malicious 0.44.1 (the repo `uv.lock` protects only `uv sync`-from-source, not end users installing the published package). ## Fix Exclude exactly the compromised version in the shipped dependency metadata: ```toml "ast-grep-cli>=0.30.0,!=0.44.1", ``` `!=0.44.1` removes only the known-bad build, so every other release stays installable — older safe versions and any future patched release alike. The committed `uv.lock` already resolves to the safe **0.42.1**, which still satisfies the new constraint, so no re-resolution is needed; I updated the lock's `requires-dist` entry to match the new specifier to keep `uv lock --locked` consistent. ## Type of Change - [x] Bug fix (non-breaking change that fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - `pyproject.toml`: `ast-grep-cli` constraint is now `>=0.30.0,!=0.44.1`, with a comment recording why. - `uv.lock`: update the `ast-grep-cli` `requires-dist` specifier to match (resolved version unchanged at 0.42.1). ## Testing - [ ] Unit tests pass (`pytest`) - [x] Linting passes (`ruff check .`) - [x] Type checking passes (`mypy headroom`) - [ ] New tests added for new functionality - [ ] Manual testing performed ### Test Output ```text # Verified the specifier semantics with packaging: $ python -c "from packaging.specifiers import SpecifierSet; from packaging.version import Version; s=SpecifierSet('>=0.30.0,!=0.44.1'); print(Version('0.44.1') in s, [str(v) for v in ['0.42.1','0.44.0','0.44.2','0.45.0'] if Version(v) in s])" False ['0.42.1', '0.44.0', '0.44.2', '0.45.0'] # pyproject still parses and carries the new constraint: $ python -c "import tomllib; print([d for d in tomllib.load(open('pyproject.toml','rb'))['project']['dependencies'] if 'ast-grep' in d])" ['ast-grep-cli>=0.30.0,!=0.44.1'] ``` ## Real Behavior Proof - Environment: Windows 11, Python 3.12. - Exact command / steps: evaluated the new `SpecifierSet('>=0.30.0,!=0.44.1')` against the compromised version and a range of safe versions, and re-parsed `pyproject.toml`. - Observed result: `0.44.1` is excluded (`in` -> False); `0.42.1` (the current lock pin), `0.44.0`, `0.44.2`, `0.45.0`, and `1.0.0` all remain allowed; the pre-0.30 floor is still enforced. So a resolver can no longer select the trojaned build, and no legitimate release is blocked. - Not tested: a full `pip install`/`uv tool install` from a built wheel on a clean machine; the change is a metadata-only constraint tightening and the resolver semantics are verified above. ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Checklist - [x] My code follows the project's style guidelines - [x] I have performed a self-review of my code - [x] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] I have updated the CHANGELOG.md if applicable ## Additional Notes This is the minimal, high-priority piece of the issue's recommended actions (pin away from the compromised version). The issue also suggests an install-docs warning and a `pip-audit` / `uv audit` CI step; those are worth doing but are separate follow-ups (a CI workflow change I can't meaningfully validate here), so I left them out to keep this fix small and obviously correct. No CHANGELOG entry is added since this is a dependency-metadata security pin, but I'm happy to add one if the project prefers it here. Co-authored-by: JerrettDavis <mxjerrett@gmail.com> |
||
|
|
a90be94e32
|
fix(deps): bump mcp to 1.28.1 to clear 3 high-severity CVEs (#2348)
## Description Clears **all 3 open Dependabot alerts** (and the `pip-audit` CI failure) — every one is `mcp 1.26.0` in `uv.lock`: | Alert | CVE | Issue | Fix | |-------|-----|-------|-----| | #155 | CVE-2026-52870 | experimental task handlers leak cross-session tasks | 1.27.2 | | #156 | CVE-2026-52869 | HTTP transports serve session requests without auth check | 1.27.2 | | #157 | CVE-2026-59950 | deprecated WebSocket transport lacks Host/Origin validation | 1.28.1 | `mcp 1.28.1` satisfies all three. Closes # ## Type of Change - [x] Bug fix (security / dependency) ## Changes Made - `pyproject.toml`: raise the floor `mcp>=1.0.0` → `mcp>=1.28.1` (core dep **and** the `[mcp]` extra). - `uv.lock`: bump the `mcp` entry `1.26.0` → `1.28.1` (version + sdist/wheel URL, sha256, size from PyPI). **Surgical on purpose.** mcp 1.28.1's resolved dependency set is unchanged for this project's Python range (1.26 vs 1.28.1 differ only in `python_version>=3.14` conditionals and an httpx upper bound already satisfied), so no other locked package changes. Verified: `uv.lock` parses, `mcp = 1.28.1`, no `mcp-1.26.0` refs remain. ## Testing ```text python -c "import tomllib; ...; print(pkgs['mcp'])" -> 1.28.1 (uv.lock valid TOML) git diff --stat -> pyproject.toml | 4 ; uv.lock | 6 grep -c mcp-1.26.0 uv.lock -> 0 ``` mcp 1.28.1 ≥ every advisory's fixed-version, so all 3 alerts + pip-audit clear. ## Real Behavior Proof - Env: local; hashes fetched from `https://pypi.org/pypi/mcp/1.28.1/json`. - Steps: bumped the pyproject floor + the single mcp lock entry; validated TOML + version + absence of old refs. - Not tested: full `uv sync` (the lock is separately stale — see note). ## Note (deliberate scoping) A full `uv lock` refresh churns ~900 lines: the lock is **separately stale** (missing some declared deps) and local `uv` resolution diverges (major downgrades of protobuf/posthog/portalocker — likely an env artifact). That's a pre-existing lock-hygiene problem for its own PR — **not** bundled into this security fix. No `CHANGELOG.md` edit (release-please owns it). |
||
|
|
4381388d56
|
chore: release main (#1923)
## Description Release Please generated the 0.33.0 release PR for main. This updates release metadata, package versions, and the generated changelog for the 0.33.0 release. I also aligned the agent-hook plugin manifests, marketplace metadata, editable lockfile package version, and canonical MCP `server.json` descriptor to 0.33.0 so all package/plugin/registry version declarations match the Release Please version bump. ## Type of Change - [x] Documentation update - [x] Release / packaging metadata ## Changes Made - Updated `.release-please-manifest.json`, `pyproject.toml`, `plugins/openclaw/package.json`, and `sdk/typescript/package.json` to 0.33.0. - Updated the generated `CHANGELOG.md` release notes for 0.33.0. - Synced `plugins/headroom-agent-hooks` plugin manifests and marketplace metadata to 0.33.0. - Synced `uv.lock` editable `headroom-ai` package version to 0.33.0. - Regenerated the canonical MCP `server.json` descriptor to 0.33.0. ## Testing - [x] Version verification passes - [x] Version-sync tests pass - [x] MCP server descriptor test passes - [x] Whitespace check passes ### Test Output ```text uv run python scripts/verify-versions.py All versions aligned at 0.33.0 uv run pytest scripts/tests/test_version_sync.py scripts/tests/test_sync_plugin_versions.py -q 14 passed in 0.80s uv run pytest tests/test_mcp_registry/test_server_json.py -q 4 passed in 0.42s git diff --check # no output ``` ## Real Behavior Proof - Environment: Windows 11, local checkout of the Release Please branch. - Exact command / steps: Ran version verification and MCP descriptor tests after syncing release metadata, plugin marketplace versions, lockfile version, and `server.json`. - Observed result: All package, plugin manifest, marketplace, lockfile, and MCP descriptor release versions are aligned at 0.33.0. |
||
|
|
63945abe3a
|
chore: sync version state to released 0.31.0 to unblock release-please (v0.32.0) (#2338)
## Description **Fixes the Release Please pipeline so it emits `v0.32.0`.** pip / Docker / npm are out of sync because 0.32.0 was never actually released. ### Root cause Same failure mode as #1916. #2175 (a `fix(deps)` PR) bumped `pyproject.toml` + `.release-please-manifest.json` to **0.32.0 out-of-band**, so release-please reads 0.32.0 as the *current* version and computes the next release as **0.33.0** (#1923) — **skipping 0.32.0, which was never tagged, GitHub-released, or published to PyPI/Docker.** The last real release is `v0.31.0` (2026-07-09). The plugin/marketplace manifests were also left at 0.31.0, so version state was split-brained: ``` pyproject.toml / openclaw / sdk-typescript : 0.32.0 <- #2175 plugin.json (x2) / marketplace.json (x2) : 0.31.0 manifest : 0.32.0 ``` ### Fix Realign every version-tracked file **and** the RP manifest to the last real release, **0.31.0**, via the repo's own `scripts/version-sync.py --version 0.31.0`. Versions only — no code change. ## What happens after merge 1. Release Please runs on `main`, sees `manifest = 0.31.0` + releasable commits since `v0.31.0`, and **rewrites its release PR (#1923) to `chore: release 0.32.0`** (bumping every version file). 2. Merging that PR tags `v0.32.0` and fires `release: published`, which publishes **PyPI + npm (SDK + openclaw) + Docker** at 0.32.0 in one shot — bringing all registries back in sync. ## Changes Made - `.release-please-manifest.json` → `0.31.0` - `pyproject.toml`, `sdk/typescript/package.json`, `plugins/openclaw/package.json`, `.releasemetadata` → `0.31.0` (via `version-sync.py`) - Plugin/marketplace manifests were already `0.31.0` (unchanged). ## Testing ```text $ python scripts/verify-versions.py All versions aligned at 0.31.0 ``` ## Real Behavior Proof - Environment: local `.venv`. - Steps: `version-sync.py --version 0.31.0`, reset manifest, `verify-versions.py`. - Observed: all 9 version entries aligned at 0.31.0; no CHANGELOG touched (Changelog Guard passes). - Not tested: the live release-please recompute (will run on merge — expected to rewrite #1923 to `chore: release 0.32.0`). ## Note on downstream publish The release-please workflow only triggers `release.yml`/`docker.yml` if `RELEASE_PLEASE_TOKEN` (a PAT) is set — with the `GITHUB_TOKEN` fallback the release is created but downstream publishes don't fire. #1916 shipped 0.31.0 fully via this path, so the PAT was set then; if the 0.32.0 publish doesn't fire on merge, verify that secret still exists. |
||
|
|
412db40a0b
|
fix(code): pin tree-sitter-language-pack <1.0.0 in [code] extra (#1219)
## Description <!-- Briefly explain the change and why it is needed. --> Closes # ## Type of Change - [ ] Bug fix (non-breaking change that fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - ## Testing <!-- Check what you actually ran, then paste the real command output below. --> - [ ] Unit tests pass (`pytest`) - [ ] Linting passes (`ruff check .`) - [ ] Type checking passes (`mypy headroom`) - [ ] New tests added for new functionality - [ ] Manual testing performed ### Test Output ```text # Paste relevant command output or artifact links here ``` ## Real Behavior Proof - Environment: - Exact command / steps: - Observed result: - Not tested: ## Review Readiness - [ ] I have performed a self-review - [ ] This PR is ready for human review ## Checklist - [ ] My code follows the project's style guidelines - [ ] I have performed a self-review of my code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] I have updated the CHANGELOG.md if applicable ## Screenshots (if applicable) Add screenshots to help explain your changes. ## Additional Notes <!-- Mention any N/A checklist items, tradeoffs, follow-ups, or maintainer context. --> --------- Co-authored-by: JerrettDavis <mxjerrett@gmail.com> |
||
|
|
420dc9077b
|
feat(grok-build): add Grok Build wrap command and MCP integration (#1629)
## Description
Adds first-class Grok Build support to Headroom so Grok CLI sessions can
route through the local proxy for context compression and savings
tracking.
This PR introduces `headroom wrap grok-build` / `headroom unwrap
grok-build`, a `grok_build` provider slice, Grok MCP registrar support,
and install/telemetry wiring so Grok traffic is attributed correctly in
the proxy and dashboard.
Review follow-up (`9368c413`): when users already own
`[model.grok-build]` in `~/.grok/config.toml`, wrap rewrites `base_url`
in that table in place instead of appending a duplicate header (invalid
TOML).
## Type of Change
- [x] New feature (non-breaking change that adds functionality)
## Changes Made
- Added `headroom/providers/grok_build/` with runtime helpers,
reversible `~/.grok/config.toml` injection, and install env builders.
- Added `headroom wrap grok-build` and `headroom unwrap grok-build` CLI
commands.
- Added `GrokRegistrar` for Headroom MCP registration in Grok config.
- Wired `grok_build` into install planner/registry, agent savings,
telemetry, and proxy client detection (`grok/` user agent).
- **Review fix:** rewrite `base_url` inside an existing user-owned
`[model.grok-build]` table in place (`# was: …` metadata).
- Added regression tests + docs (`grok-build.mdx`, `proxy.mdx`) and
CHANGELOG entry.
## Testing
- [x] Unit tests pass (`pytest`)
- [x] New tests added for new functionality
- [x] Manual testing performed
### Test Output
```text
$ pytest -q tests/test_provider_grok_build.py tests/test_mcp_registry/test_grok_registrar.py
============================== 12 passed in 1.13s ==============================
```
See **Screenshots** below for terminal captures (pytest, review-fix
in-place rewrite, proxy `/readyz`, unwrap).
## Real Behavior Proof
- Environment: macOS, Python 3.11.12 venv, feat/grok-build @ `
|
||
|
|
e8bff1cfe3
|
feat: add CrewAI and AutoGen tool compression integrations (#1384)
## Description Add CrewAI and AutoGen tool compression integrations, following the same patterns as the existing LangChain agent integration (`HeadroomToolWrapper` / `wrap_tools_with_headroom`). Both delegate compression to `compress_tool_result()` from the MCP integration, with per-tool metrics tracking via `ToolCompressionMetrics` / `ToolMetricsCollector`. Closes #1379 ## Type of Change - [x] New feature (non-breaking change that adds functionality) ## Changes Made - Add `headroom/integrations/crewai/` — `HeadroomToolWrapper` subclasses CrewAI `BaseTool`, wraps `_run()` with compression - Add `headroom/integrations/autogen/` — `HeadroomToolWrapper` wraps AutoGen `FunctionTool` (sync and async) with compression - Wire both into `headroom/integrations/__init__.py` with aliased re-exports (avoids name collision with LangChain's `HeadroomToolWrapper`) - Add `[crewai]` and `[autogen]` optional dependency extras to `pyproject.toml` - Add 24 unit tests (12 per framework) under `tests/test_integrations/` - Add `.mdx` doc pages for both frameworks under `docs/content/docs/` - Update `CHANGELOG.md` with entries under `### Added` ## Testing - [x] Unit tests pass (`pytest`) - [x] Linting passes (`ruff check .`) - [ ] Type checking passes (`mypy headroom`) - [x] New tests added for new functionality - [x] Manual testing performed ### Test Output ```text $ ruff check headroom/integrations/crewai headroom/integrations/autogen tests/test_integrations/crewai tests/test_integrations/autogen All checks passed! $ pytest tests/test_integrations/autogen -v 12 passed $ pytest tests/test_integrations/crewai -v 12 passed ``` ## Real Behavior Proof - Environment: Windows 11, Python 3.11, crewai 1.14.7, autogen-agentchat 0.7.5 - Exact command / steps: Ran standalone adapter demos and benchmark runner across 4 task types - Observed result: | Task | Tokens (raw) | Tokens (compressed) | Savings | |------|-------------|-------------------|---------| | Inventory JSON (80 items) | 5,044 | 1,532 | 69.6% | | Server logs (150 lines) | 8,712 | 314 | 96.4% | | Analytics query (100 rows) | 10,762 | 10,762 | 0% | | API docs (20 endpoints) | 8,043 | 8,043 | 0% | Compression results are identical across CrewAI and AutoGen — expected since both route through the same `compress_tool_result()` pipeline. - Not tested: Full end-to-end with a live LLM agent loop (demos test the compression pipeline standalone). LangGraph not included — headroom already has `headroom/integrations/langchain/langgraph.py`. ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Checklist - [x] My code follows the project's style guidelines - [x] I have performed a self-review of my code - [x] I have commented my code, particularly in hard-to-understand areas - [x] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [x] I have updated the CHANGELOG.md if applicable ## Additional Notes - LangGraph integration is intentionally excluded — headroom already has one at `headroom/integrations/langchain/langgraph.py` - Re-exports in `__init__.py` are aliased (`CrewAIToolWrapper`, `AutoGenToolWrapper`) to avoid collision with the existing LangChain `HeadroomToolWrapper` - Both integrations follow the exact same conventions as the existing LangChain agents module: optional dep guard, `compress_tool_result()` delegation, metrics with 1000-entry cap, Google-style docstrings - `mypy` not checked due to Rust build dependency (`maturin`) that requires Application Control policy changes on this machine --------- Co-authored-by: Sneha27feb <sroy27.ai@gmail.com> |
||
|
|
dec60de976
|
fix(codex): preserve wrapped sessions and recover state (#2160)
## Description Closes #2159. Codex wrappers currently launch against a disposable `CODEX_HOME`, so session state created during a wrapped run can disappear when that temporary directory is removed. This change launches Codex against its durable home, keeps proxy routing process-local, and adds recovery for retained temporary homes and pinned recovery sources. ## Type of Change - [x] Bug fix (non-breaking change that fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [x] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - Launch Codex against its durable `CODEX_HOME` and apply routing through process-local config overrides after the actual proxy port is resolved. - Preserve custom provider identity and reject providers that cannot be redirected safely. - Detect dangling temporary Codex homes before interactive wraps and offer recovery. - Add `headroom recover codex` with automatic discovery, repeatable `--source`, preview, confirmation, retained backups, and rollback on failure. - Search Python's temp root, `$TMPDIR`, `/tmp`, `/private/tmp`, and macOS `/private/var/folders/*/*/T` for retained `headroom-codex-home-*` directories. - Reuse `source-pinned/` copies left by interrupted or failed recovery attempts after the original temporary home has disappeared. - Report deleted temporary homes still referenced by SQLite rollout paths without treating paths pasted into prompts or errors as filesystem evidence. - Audit the durable thread index, rollout files, and history when no source remains, including indexed chat counts and history-only orphan records. - Normalize legacy localhost `headroom` providers in both SQLite thread rows and rollout `session_meta`, including retries after an earlier broken recovery, while preserving user-defined remote providers named `headroom`. - Merge compatible config, JSONL, rollout, SQLite, credential, and regular-file state without propagating deletions or runtime artifacts. - Rewrite recovered thread rollout paths to the durable home and restore legacy Headroom thread providers to the active provider. - Validate SQLite schemas, SQLx migration checksums, integrity, and foreign keys, and quarantine malformed JSONL. - Preserve failed targets with an atomic rename before rollback, avoiding recursive-deletion races with live SQLite runtime files. - Document discovery, migration, retained backups, rollback behavior, and the limits of deleted-source recovery. ## Testing - [x] Unit tests pass (`pytest`) - [x] Linting passes (`ruff check`) - [x] Type checking passes (`mypy`) - [x] New tests added for new functionality - [x] Manual testing performed in isolated Docker containers ### Test Output ```text $ uv run pytest tests/test_cli/test_wrap_codex.py tests/test_cli/test_recover_codex.py -q 122 passed $ uv run ruff check headroom/cli/recover.py headroom/providers/codex/recovery.py tests/test_cli/test_recover_codex.py All checks passed! $ uv run ruff format --check headroom/cli/recover.py headroom/providers/codex/recovery.py tests/test_cli/test_recover_codex.py 3 files already formatted $ uv run mypy headroom/cli/recover.py headroom/providers/codex/recovery.py Success: no issues found in 2 source files ``` All validation ran in `ghcr.io/astral-sh/uv:python3.12-bookworm` against a writable disposable copy of a read-only source mount. Codex was not installed or launched, and no real user Codex state was read or modified. The tests cover multi-root discovery, deleted-reference reporting, retained pinned-source recovery, durable SQLite path relocation, SQLite and rollout provider normalization, idempotent repair after an earlier broken recovery, remote provider preservation, unrelated dangling target rows, backup retention, atomic rollback, malformed-state quarantine, SQLite validation, and Windows-safe handle closure. The repository shim E2E was not launched locally because this recovery work intentionally avoids launching Codex. Upstream CI exercises wrapper E2E in isolated environments. ## Real Behavior Proof - Environment: `ghcr.io/astral-sh/uv:python3.12-bookworm`, Python 3.12, a writable disposable checkout copied from a read-only source mount, at head ` |
||
|
|
fcf455a7eb
|
feat(wrap): add omp target (Oh My Pi) with models.yml override and unwrap (#1811)
## Description Adds `headroom wrap omp` / `headroom unwrap omp` — a one-command wrap for [Oh My Pi](https://www.npmjs.com/package/@oh-my-pi/pi-coding-agent) (`omp`), the pi-mono-lineage coding agent, as proposed in #1149. One honest correction to the issue: #1149 proposed reusing the `ANTHROPIC_BASE_URL` redirect from `wrap claude`. During implementation I probed that empirically and it turned out to be wrong — omp only reads `ANTHROPIC_BASE_URL` in its web-search helper; its **chat** endpoint comes from the model registry (`providers.anthropic.baseUrl` in `~/.omp/agent/models.yml`). With the env var pointed at a local probe server, omp's chat traffic still went straight to the real endpoint (0 probe hits); with a `models.yml` same-ID override, every request arrived at the probe (9/9 hits on `/v1/messages`). A same-ID override keeps omp's bundled Anthropic model catalog and stored credentials (both keyed by provider id `anthropic`), so only the endpoint moves. The wrap therefore injects a marker-fenced `providers.anthropic.baseUrl` override into `models.yml`, snapshotting the pre-wrap file **byte-for-byte** first, and `headroom unwrap omp` restores it exactly (or removes the file when the wrap created it) — the same durable-wrap + backup + unwrap contract `wrap codex` uses for `config.toml`. Closes #1149 ## Type of Change - [ ] Bug fix (non-breaking change that fixes an issue) - [x] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - `headroom/providers/omp/` (new provider slice): `models_yml_path()` (honors `PI_CODING_AGENT_DIR`), `inject_models_override()` (yaml-merge preserving user providers; pristine byte-for-byte backup, never re-snapshotted while managed), `restore_models_override()` (`restored` / `removed` / `noop`; never touches an unmanaged file), `build_launch_env()` - `headroom/cli/wrap.py`: `wrap omp` (mirrors the aider/vibe `_launch_tool` shape; rtk instructions into the project's `AGENTS.md`, which omp reads natively) and `unwrap omp` (restore models.yml + scrub rtk block + stop proxy) - `headroom/telemetry/context.py`: `omp` added to `_KNOWN_WRAP_AGENTS` so the stack slug reports `wrap_omp` instead of `unknown` - `README.md` (agent matrix row + unwrap list), `llms.txt`, `CHANGELOG.md` - `tests/test_cli/test_wrap_omp.py`: 16 tests (injection fresh/merge/re-inject, restore statuses incl. unmanaged-file safety, env passthrough, CLI wiring, unwrap flows) ## Testing - [ ] Unit tests pass (`pytest`) — all new + `test_cli` tests pass; the full suite carries **3 pre-existing failures** that reproduce identically on unmodified `origin/main` (same set, same asserts — see Test Output and the rebase-validation comment) - [x] Linting passes (`ruff check .`) - [x] Type checking passes (`mypy headroom`) - [x] New tests added for new functionality - [x] Manual testing performed ### Test Output ```text $ uv run pytest -q # post-rebase, base |
||
|
|
e5b3a634df
|
fix(proxy): dedupe Codex WS request logging for accurate mixed-provider dashboards (#2189)
## Description Running Claude Code (Anthropic) and Codex (OpenAI) against the **same** Headroom proxy instance on one port produced incorrect, unstable dashboard data. The proxy core is provider-isolated and multi-provider-safe by design; the defect was in the observability layer. The Codex `/v1/responses` **WebSocket** handler was the only path in the proxy that wrote to the request logger by hand instead of through the unified `emit_request_outcome` funnel, and it did so twice per session close: the per-turn funnel record plus an unconditional cumulative session-summary `RequestLog`. This PR removes the duplicate summary log so Codex WS emits exactly one request log per turn, matching the HTTP provider paths. ## Type of Change - [x] Bug fix (non-breaking change that fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - Dropped the duplicate cumulative session-summary `RequestLog` in the Codex WS handler while preserving the per-turn `emit_request_outcome` path. - Preserved gated `request_messages` and `turn_id` on residual outcomes so dashboard telemetry keeps the useful attribution without double-counting tokens. - Ensured explicit `--anyllm-provider` wins over a leaked `HEADROOM_ANYLLM_PROVIDER` environment variable. - Registered retry delay settings that had drifted out of the settings registry. - Hardened tests against developer-shell `HEADROOM_*` / `ANTHROPIC_CUSTOM_HEADERS` leakage and stabilized several focused proxy/wrap test fixtures. ## Testing - [x] Unit tests pass (`pytest`) - [x] Linting passes (`ruff check .`) - [ ] Type checking passes (`mypy headroom`) - [x] New tests added for new functionality - [x] Manual testing performed ### Test Output ```text $ .venv/bin/pytest tests/ -q -p no:cacheprovider 8529 passed, 537 skipped, 5831 warnings in 276.25s (0:04:36) $ .venv/bin/ruff check <touched files> All checks passed! ``` ## Real Behavior Proof - Environment: macOS (Darwin 25.4.0), Python 3.13.14, pytest 9.0.3, ruff via project venv, branch `fix/multi-provider-runtime`. - Exact command / steps: Ran the full test suite without pytest cache provider and Ruff on all touched files; used `git stash` to confirm the stale fake-config failures pre-existed this change. - Observed result: Full suite passed with no failures; Ruff passed; Codex WS now routes end-of-session logging through `emit_request_outcome`, emitting one request log per turn with the same accounting model as Anthropic HTTP turns. - Not tested: Live simultaneous Claude + Codex dashboard run. `mypy headroom` was not run to completion; a scoped run reported one pre-existing `settings_store.py:470` coercion error outside this diff. ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Checklist - [x] My code follows the project's style guidelines - [x] I have performed a self-review of my code - [x] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] I have updated the CHANGELOG.md if applicable ## Screenshots (if applicable) N/A - server-side observability fix; no UI markup changed. ## Additional Notes - The proxy's multi-provider routing, header/auth isolation, and per-model cache keying are already correct and unchanged here; only the WS observability write path was double-counting. - Architectural assessment: `plans/reports/research-260714-0004-multi-provider-upstream-compression-report.md`; root-cause + resolution trail: `plans/reports/debug-assessment-260714-0011-dashboard-instability-mixed-claude-codex-report.md`. - No live simultaneous Claude + Codex dashboard run was performed; validation is from test coverage and code review of the WS logging path. --------- Co-authored-by: JerrettDavis <mxjerrett@gmail.com> |
||
|
|
cbfa267c5f
|
fix(deps): enforce transformers security floor (#2201)
## Description Raise the production `transformers` dependency floor so the security workflow cannot resolve the CVE-2026-5241 vulnerable range reported by `pip-audit`, and refresh the small current-main test fixtures needed for the PR matrix to run green. ## Type of Change - [x] Bug fix (non-breaking change that fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - Raised direct optional `transformers` declarations for `proxy`, `ml`, and `voice` extras to `>=5.5.0,<6.0`. - Refreshed `uv.lock` metadata so `uv export --extra all` resolves a patched `transformers` version for the production audit set. - Kept the current-main test fixture fixes for the ZCode setup printer and deferred compression fallback metrics. ## Testing - [x] Unit tests pass (`pytest`) - [x] Linting passes (`ruff check .`) - [ ] Type checking passes (`mypy headroom`) - [ ] New tests added for new functionality - [x] Manual testing performed ### Test Output ```text $ uv lock --check Resolved 238 packages in 1ms $ uv export --frozen --no-dev --no-emit-project --no-hashes --extra all --format requirements-txt | rg "^transformers==|^huggingface-hub==" huggingface-hub==1.16.1 transformers==5.13.1 $ uv export --frozen --no-dev --no-emit-project --no-hashes --extra all --format requirements-txt > requirements-prod.txt $ uvx pip-audit -r requirements-prod.txt No known vulnerabilities found $ uv run --with pytest --with pytest-asyncio --with fastapi --with httpx --with numpy pytest tests/test_cli/test_wrap_zcode.py::test_wrap_prints_proxy_urls tests/test_cold_start_fast_pass.py::test_fast_pass_failure_falls_back_to_full_deferral -q 2 passed $ uvx ruff==0.15.17 check headroom/cli/wrap.py headroom/proxy/handlers/anthropic.py --output-format concise All checks passed! $ git diff --check passed ``` ## Real Behavior Proof - Environment: Windows checkout plus the same frozen production dependency export shape used by the GitHub Actions security workflow. - Exact command / steps: raised the `transformers` floor, refreshed `uv.lock`, exported `--extra all` production requirements, ran `pip-audit`, then reproduced the focused ZCode and deferred-compression tests. - Observed result: the export resolves `transformers==5.13.1`; `pip-audit` reported no known vulnerabilities; the focused tests pass locally; CI is rerunning on the updated head. - Not tested: full GitHub Actions matrix locally; CI is running the complete suite on this PR. ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Checklist - [x] My code follows the project's style guidelines - [x] I have performed a self-review of my code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] I have updated the CHANGELOG.md if applicable ## Screenshots (if applicable) N/A - dependency metadata and CI fixture fix. ## Additional Notes This PR is intentionally scoped to clearing the current red mainline security gate while keeping the small fixture updates needed by the branch test matrix. |
||
|
|
ea3d5a86b7
|
fix(deps): clear Dependabot lockfile alerts (#2175)
## Description Clears the current dependency/security-audit blockers that are making unrelated PRs red: - `transformers 5.3.0` / `CVE-2026-5241`, fixed by requiring `transformers>=5.5.0` in the locked optional dependency set. - `sqlitedict <=2.1.0` via the optional `benchmark` extra's `lm-eval[api]` dependency. There is no patched `sqlitedict` release, so this PR removes the published/locked `benchmark` extra instead of shipping a known-vulnerable transitive dependency. - `esbuild >=0.27.3,<0.28.1` in the OpenCode plugin lockfile, fixed by forcing `esbuild@0.28.1` through the OpenCode npm override and regenerated lockfile. The benchmark code still invokes `python -m lm_eval`; researchers who need that harness should install `lm-eval[api]` in their benchmark environment until its transitive vulnerability has a patched release. ## Type of Change - [x] Bug fix (non-breaking change that fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - `pyproject.toml`: remove the `benchmark` optional extra, document external `lm-eval[api]` installation guidance, and require `transformers>=5.5.0`. - `uv.lock`: regenerate without the `benchmark` extra, removing `lm-eval` and `sqlitedict` lock entries and locking the patched transformers floor. - `plugins/opencode/package.json`: add an `overrides` entry for `esbuild@0.28.1`. - `plugins/opencode/package-lock.json`: regenerate the OpenCode lockfile with `esbuild@0.28.1`. ## Testing - [x] Unit tests pass (`pytest`) - [x] Linting passes (`ruff check .`) - [ ] Type checking passes (`mypy headroom`) - [ ] New tests added for new functionality - [x] Manual testing performed ### Test Output ```text uv lock --check rg -n -F 'sqlitedict' uv.lock # no matches rg -n -F 'name = "lm-eval"' uv.lock # no matches rg -n -F "extra == 'benchmark'" uv.lock # no matches rg -n -F '0.27.7' plugins/opencode/package-lock.json plugins/opencode/package.json # no matches npm ls esbuild --package-lock-only npm audit --package-lock-only # found 0 vulnerabilities git diff --check ``` Previous GitHub checks were green. After merging current `main`, fresh GitHub checks are running again; local targeted validation still passes. ## Real Behavior Proof - Environment: Windows 11, Python 3.13.3, uv, npm in `plugins/opencode`, Dependabot/pip-audit alert metadata from the failing PR jobs. - Exact command / steps: inspected the regenerated Python and npm lockfiles with `rg`, checked the uv lock with `uv lock --check`, checked OpenCode's dependency tree with `npm ls esbuild --package-lock-only`, and ran `npm audit --package-lock-only`. - Observed result: `uv.lock` no longer contains `sqlitedict`, `lm-eval`, or a `benchmark` extra marker; `transformers` resolves at the patched `>=5.5.0` floor; OpenCode's lock resolves `esbuild@0.28.1`; `npm audit --package-lock-only` reports 0 vulnerabilities; GitHub `Dependency audit (pip-audit)` passes. - Not tested: running the external `lm-eval` harness after installing it separately. ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Checklist - [x] My code follows the project's style guidelines - [x] I have performed a self-review of my code - [ ] I have commented my code, particularly in hard-to-understand areas - [x] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [x] I have updated the CHANGELOG.md if applicable ## Screenshots (if applicable) N/A - dependency and lockfile security fix. ## Additional Notes The `benchmark` extra can be restored once the upstream `lm-eval[api]` dependency chain stops pulling a vulnerable `sqlitedict` release. --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
4ea96a417c
|
feat(mcp): add streamable HTTP MCP transport (#1773)
## Description `headroom mcp serve` only exposed stdio, which blocked MCP clients that require a Streamable HTTP endpoint. This PR adds an explicit HTTP transport mode around the existing Headroom MCP server while keeping stdio as the default and keeping tool registration single-sourced. Closes #1346. ## Type of Change - [ ] Bug fix (non-breaking change that fixes an issue) - [x] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [x] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - Add `headroom mcp serve --transport http` with host, port, and path options. - Serve `headroom_compress`, `headroom_retrieve`, and `headroom_stats` through the same MCP server instance used by stdio. - Keep `headroom mcp serve` defaulting to stdio for current Claude Code and local MCP host configs. - Update MCP docs for stdio and HTTP setup without implying the proxy automatically owns `/mcp`. - Keep the scope clean, rebased, and covered by focused tests. ## Testing - [x] Unit tests pass (`uv run pytest tests/test_ccr_mcp_http.py tests/test_cli/test_mcp.py -q`) - [x] Linting passes (`uv run ruff check headroom/cli/mcp.py headroom/ccr/mcp_server.py headroom/ccr/mcp_http.py tests/test_ccr_mcp_http.py tests/test_cli/test_mcp.py`) - [x] Type checking passes (`uv run mypy headroom --ignore-missing-imports`) - [x] New tests added for new functionality when applicable - [x] Manual testing performed ### Test Output ```text uv run pytest tests/test_ccr_mcp_http.py tests/test_cli/test_mcp.py -q 20 passed in 0.53s uv run ruff check headroom/cli/mcp.py headroom/ccr/mcp_server.py headroom/ccr/mcp_http.py tests/test_ccr_mcp_http.py tests/test_cli/test_mcp.py All checks passed! uv run ruff format headroom/cli/mcp.py headroom/ccr/mcp_server.py headroom/ccr/mcp_http.py tests/test_ccr_mcp_http.py tests/test_cli/test_mcp.py --check 5 files already formatted uv run mypy headroom --ignore-missing-imports Success: no issues found in 407 source files ``` ## Real Behavior Proof - Environment: Local Python environment with Headroom dev dependencies and MCP extra installed. - Exact command / steps: Start `headroom mcp serve --transport http --host 127.0.0.1 --port <test-port> --path /mcp`, then perform an MCP SDK Streamable HTTP initialize/list-tools exchange. - Observed result: The HTTP transport initializes and lists the existing Headroom MCP tools; `headroom mcp serve` without `--transport` still selects stdio, and mixed-case `--transport HTTP` routes to the HTTP transport. - Not tested: live validation against external MCP hosts ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Additional Notes `CHANGELOG.md` is not edited because this repository generates changelog entries from conventional commits. Full-suite validation is left to CI. |
||
|
|
fce93bf39a
|
fix(ci/deps): clear audit and release smoke failures (#2190)
## Summary - add a uv constraint floor for `setuptools>=83.0.0` to address `PYSEC-2026-3447` - refresh `uv.lock` so the production audit export resolves with `setuptools 83.0.0` - harden the Release wheel smoke-import gate by retrying Ubuntu-container `apt-get` operations and using `--fix-missing` - keep the generated `requirements-prod.txt` uncommitted; it is produced by the security workflow ## Why This clears the new dependency audit alert that made PRs red: - `setuptools 80.10.2` - `PYSEC-2026-3447` - fixed in `83.0.0` While validating the queue, the same PR class also hit a Release smoke-import failure in the Ubuntu 22.04 ARM container due apt mirror skew: `E: Failed to fetch ... python3-httplib2_0.20.2-2ubuntu0.1_all.deb 404 Not Found` The smoke gate should still fail for broken wheels, but transient apt mirror skew should not make unrelated PRs red. ## Lockfile impact - `setuptools 80.10.2 -> 83.0.0` - `torch 2.12.1 -> 2.13.0`, required for pip resolver compatibility with `setuptools 83.0.0` in the exported audit set - `cuda-toolkit 13.0.2 -> 13.0.3.0`, pulled by the torch lock refresh - uv also refreshed the existing project metadata for the sandbox extra so `uv lock --check` passes ## Validation - `uv lock --check` - `uv export --frozen --no-dev --no-emit-project --no-hashes --extra all --format requirements-txt > requirements-prod.txt` - confirmed generated `requirements-prod.txt` contains `setuptools==83.0.0`, `torch==2.13.0`, `cuda-toolkit==13.0.3.0` - `uvx pip-audit -r requirements-prod.txt` -> No known vulnerabilities found - `python -m pytest tests/test_release_workflows.py -q` -> 32 passed - `uvx ruff@0.15.17 check tests/test_release_workflows.py` -> All checks passed - `git diff --check` |
||
|
|
b6eb7a7613
|
feat(kompress): optional remote compression endpoint (HEADROOM_KOMPRESS_ENDPOINT) (#2171)
## Description Adds an **opt-in remote Kompress backend** so the proxy can offload Kompress ML inference to a hosted `/compress` endpoint instead of loading the ONNX model in-process. This lets Headroom run as a lean proxy in a sandbox installed with only `[proxy]` deps while the model runs elsewhere. The feature is purely additive: with `HEADROOM_KOMPRESS_ENDPOINT` unset, behavior remains the existing in-process Kompress path. ## Type of Change - [x] New feature (non-breaking change that adds functionality) ## Changes Made - `headroom/transforms/kompress_remote.py`: adds `RemoteKompressCompressor`, a `KompressCompressor`-compatible HTTP client that posts to `/compress`, sends optional bearer auth, skips network for tiny inputs, and fails open on HTTP/network/malformed-response errors. - `headroom/transforms/kompress_compressor.py`: extracts `store_kompress_in_ccr()` so the remote client reuses the same proxy-local CCR marker/storage policy without importing the ML model. - `headroom/transforms/content_router.py`: selects the remote compressor when `HEADROOM_KOMPRESS_ENDPOINT` is set, while `"disabled"` still wins and the unset path remains local Kompress. - `tests/test_transforms/test_kompress_remote.py`: covers mocked remote success, auth/header/request behavior, tiny-input no-call behavior, HTTP fail-open, malformed-success fail-open, and router env selection. ## Testing - [x] Unit tests pass (`uv run --extra dev pytest tests/test_transforms/test_kompress_remote.py -q`) - [x] Linting passes (`uvx ruff@0.15.17 check headroom/transforms/kompress_remote.py headroom/transforms/kompress_compressor.py headroom/transforms/content_router.py tests/test_transforms/test_kompress_remote.py`) - [x] Formatting passes (`uvx ruff@0.15.17 format --check headroom/transforms/kompress_remote.py headroom/transforms/kompress_compressor.py headroom/transforms/content_router.py tests/test_transforms/test_kompress_remote.py`) - [x] Type checking passes (`uv run --extra dev mypy headroom/transforms/kompress_remote.py headroom/transforms/kompress_compressor.py headroom/transforms/content_router.py`) - [x] New tests added for new functionality - [x] Manual testing performed by the author against a live endpoint ## Real Behavior Proof - Environment: Windows 11 review worktree, Python 3.13.3 for mocked tests; author also manually tested against a Modal deployment of `chopratejas/kompress-v2-base`. - Exact command / steps: ran the focused mocked endpoint test file plus lint/format/mypy on the changed modules. - Observed result: remote success maps endpoint response into `KompressResult`; short inputs do not call the network; 503 responses and malformed 200 responses return the original content; router selects the remote compressor only when the env var is set. - Not tested: full `pytest` suite; production concurrency/latency under load; endpoints other than the author's Modal reference deployment. ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Checklist - [x] My code follows the project's style guidelines - [x] I have performed a self-review of my code - [x] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation — follow-up README flag section - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] I have updated the CHANGELOG.md if applicable ## Additional Notes - The endpoint/deploy artifact (`modal_serve.py`) lives in the separate `kompress` repo; this PR is only the client-side flag. - The endpoint is intentionally stateless for CCR. Original-content storage and retrieval markers remain proxy-local. - Design note: this capability is intentionally in OSS as an opt-in flag. The same flag serves self-hosted endpoints and, later, a hosted endpoint. --------- Co-authored-by: JerrettDavis <mxjerrett@gmail.com> |
||
|
|
e9000863fc
|
fix(kompress): fail-open wall-clock guard on single-cache-miss compression (#2114)
## Description The single-cache-miss branch in `ContentRouter` ran compression inline on the request path without its own wall-clock guard, so a cooperative stall waited for the full call even when `HEADROOM_COMPRESSION_DEADLINE_MS` was meant to fail open. This change adds a branch-level watchdog that returns `PASSTHROUGH` after the deadline, scoped only to the one-pending-task path and not the native GIL-hold root cause. Closes #2046 ## Type of Change - [x] Bug fix (non-breaking change that fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - Added `_compression_deadline_seconds()` and a watchdog around the single-cache-miss inline compression branch in `ContentRouter`. - Returned the original content with `PASSTHROUGH` and logged a fail-open warning after the configured deadline, while preserving under-deadline and deadline-disabled behavior. - Added focused regressions for timeout, under-deadline output, and disabled-deadline behavior, then kept the wider deadline suite green. - Raised the locked production floors for `click` and `pillow` to clear the current `pip-audit` findings that now fail external PR merge snapshots. ## Testing - [x] Unit tests pass (`uv run pytest tests/test_content_router_single_item_deadline.py tests/test_transforms/test_kompress_deadline.py -q`) - [x] Linting passes (`uv run ruff check headroom/transforms/content_router.py tests/test_content_router_single_item_deadline.py tests/test_transforms/test_kompress_deadline.py`) - [ ] Type checking passes (`uv run mypy headroom`) - [x] New tests added for new functionality - [x] Manual testing performed ### Test Output ```text uv run pytest tests/test_content_router_single_item_deadline.py tests/test_transforms/test_kompress_deadline.py -q ============================= test session starts ============================= platform win32 -- Python 3.12.13, pytest-9.0.3, pluggy-1.6.0 rootdir: D:\Repos\headroom-pr-2046-compression-freeze configfile: pyproject.toml plugins: anyio-4.12.1, langsmith-0.9.3, asyncio-1.3.0, cov-7.0.0 asyncio: mode=Mode.AUTO, debug=False, asyncio_default_fixture_loop_scope=None, asyncio_default_test_loop_scope=function collected 5 items tests\test_content_router_single_item_deadline.py ... [ 60%] tests\test_transforms\test_kompress_deadline.py .. [100%] ============================== 5 passed in 0.42s ============================== uv run ruff check headroom/transforms/content_router.py tests/test_content_router_single_item_deadline.py tests/test_transforms/test_kompress_deadline.py All checks passed! uv run ruff format headroom/transforms/content_router.py tests/test_content_router_single_item_deadline.py tests/test_transforms/test_kompress_deadline.py --check 3 files already formatted ``` ## Real Behavior Proof - Environment: Windows, Python 3.12.13, router-level harness with a cooperative slow-compression stub - Exact command / steps: `uv run pytest tests/test_content_router_single_item_deadline.py tests/test_transforms/test_kompress_deadline.py -q`, which forces one frozen prefix and one cache miss, then sleeps past a 10 ms deadline - Observed result: the guarded branch returns the original content through `PASSTHROUGH` at the deadline, while under-deadline and deadline-disabled behavior stay unchanged - Not tested: native GIL-holding freeze ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Checklist - [x] My code follows the project's style guidelines - [x] I have performed a self-review of my code - [x] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] I have updated the CHANGELOG.md if applicable ## Screenshots (if applicable) Not applicable. ## Additional Notes - Security CI currently flags `click 8.3.1` and `pillow 12.2.0`, so this PR carries the narrow floor bump to `click>=8.3.3` and `pillow>=12.3.0` as a supply-chain unblock for the same final merge snapshot. - `CHANGELOG.md` remains untouched because Headroom generates release notes from conventional commits. - This PR is a Python-side mitigation for the single-cache-miss branch only; the native GIL-hold root cause remains a separate owner. --------- Co-authored-by: JerrettDavis <mxjerrett@gmail.com> |
||
|
|
09be107d06
|
fix(deps): raise transformers security floor
Raise the production transformers floor to a version fixed for CVE-2026-5241 and refresh uv.lock so pip-audit passes. |
||
|
|
09d1ef45be
|
fix(proxy): compress Hermes scoped coding-agent passthrough (#1815)
## Description Compress Hermes Studio scoped coding-agent passthrough requests in the generic OpenAI passthrough handler. Hermes can route scoped Claude Code and Codex traffic through Headroom while preserving its own proxy paths; this PR keeps Hermes responsible for scoped proxy authentication/provider adaptation while still applying Headroom compression to supported chat payloads before forwarding. The compression remains narrow-scoped: - Only chat messages with `user` or `assistant` roles are compressed. - Tool, function, reasoning, and system items are preserved byte-stable. - Non-dict items in the Responses `input` array are preserved and spliced back. ## Type of Change - [ ] Bug fix (non-breaking change that fixes an issue) - [x] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - Detect `/api/codex-proxy/.../v1/responses` paths and compress supported Responses `input` chat items before forwarding. - Detect `/api/claude-code-proxy/.../v1/messages` paths and compress supported Anthropic `messages` payloads before forwarding. - Preserve bypass, malformed payload, missing-model, tool/function, reasoning/system, and non-dict passthrough behavior. - Add regression coverage in `tests/test_hermes_passthrough_compression.py`. ## Testing - [x] Unit tests pass (`pytest`) - [ ] Linting passes (`ruff check .`) - [ ] Type checking passes (`mypy headroom`) - [x] New tests added for new functionality - [ ] Manual testing performed ### Test Output ```text $ python -m pytest tests/test_hermes_passthrough_compression.py -v test_codex_proxy_preserves_tool_and_function_items PASSED test_codex_proxy_preserves_nondict_items PASSED test_codex_proxy_bypass_header_skips_compression PASSED test_codex_proxy_malformed_input_preserved PASSED test_codex_proxy_compression_applies_to_chat_messages PASSED test_claude_proxy_preserves_tool_use_items PASSED test_claude_proxy_bypass_header_skips_compression PASSED test_claude_proxy_no_model_forwarded_unchanged PASSED test_claude_proxy_compression_applies_to_chat_messages PASSED test_non_hermes_routes_not_affected PASSED ``` ## Real Behavior Proof - Environment: Author-reported local test environment for `headroom/proxy/handlers/openai.py` and `tests/test_hermes_passthrough_compression.py`. - Exact command / steps: `python -m pytest tests/test_hermes_passthrough_compression.py -v`. - Observed result: The 10 Hermes passthrough regression tests passed, covering Codex and Claude scoped proxy routes plus preservation/bypass cases. - Not tested: End-to-end Hermes Studio traffic against a live upstream service is not covered by this PR body evidence. ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Checklist - [x] My code follows the project's style guidelines - [x] I have performed a self-review of my code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] I have updated the CHANGELOG.md if applicable ## Screenshots (if applicable) N/A. ## Additional Notes Generated with Claude Code. The unchecked checklist items are not required for this narrow proxy-handler test change. --------- Co-authored-by: x1051445024 <你的GitHub注册邮箱> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: JerrettDavis <mxjerrett@gmail.com> |
||
|
|
4f3d5ab341
|
fix(install): add orjson to [proxy] extra for LiteLLM provider backends (#2074)
## Description Add `orjson` to the `[proxy]` extra so `uv tool install "headroom-ai[all]"` installs a runtime dependency required by LiteLLM provider backends (e.g. OpenRouter). ## Type of Change - [x] Bug fix (non-breaking change which fixes an issue) - [ ] New feature - [ ] Breaking change - [ ] Documentation update ## Changes Made - Add `orjson>=3.9.14; platform_python_implementation != 'PyPy'` to `[proxy]`. - Regression test in `tests/test_optional_dependencies.py`. - Minimal `uv.lock` update (proxy/all optional-deps + metadata only). ## Motivation Fixes #2056. `headroom-ai[all]` installs `litellm` (core dep) but not `orjson`. LiteLLM provider backends import `orjson` at runtime; LiteLLM only declares it under `litellm[proxy]`, not base deps. Headroom does not depend on `litellm[proxy]` (would pull the full LiteLLM proxy server stack). ## Testing - `uv run --extra dev python -m pytest tests/test_optional_dependencies.py -q` — 2 passed - `uvx --from ruff==0.15.17 ruff check tests/test_optional_dependencies.py` - `uvx --from ruff==0.15.17 ruff format --check tests/test_optional_dependencies.py` ## Real Behavior Proof - **Setup:** Ubuntu, Python 3.12.3 - **Verified:** dependency graph test confirms `orjson` is selected for `[proxy]` and `[all]` extras after this patch. - **Not tested locally:** full `uv tool install` end-to-end (local sdist build requires Rust/C++ toolchain unavailable in this environment). Reporter workaround `uv tool install ... --with orjson` confirms the missing transitive dep diagnosis. ## Review Readiness - [x] I have performed a self-review of my code - [x] This PR is ready for human review ## Notes - Reporter used Python 3.14.4; `litellm` is intentionally skipped on 3.14 (GH #956). This PR fixes the missing `orjson` install path for supported Python versions using `[all]`. Co-authored-by: syf2211 <syf2211@users.noreply.github.com> Co-authored-by: JerrettDavis <mxjerrett@gmail.com> Co-authored-by: Tejas Chopra <chopratejas@gmail.com> |
||
|
|
ce3c959eae
|
deps: update tree-sitter requirement from <0.26,>=0.25.2 to >=0.25.2,<0.27 (#1681)
Updates the requirements on [tree-sitter](https://github.com/tree-sitter/py-tree-sitter) to permit the latest version. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/tree-sitter/py-tree-sitter/releases">tree-sitter's releases</a>.</em></p> <blockquote> <h2>v0.26.0</h2> <h2>What's Changed</h2> <ul> <li>ci: use windows-2025 & macos-15-intel runners by <a href="https://github.com/ObserverOfTime"><code>@ObserverOfTime</code></a> in <a href="https://redirect.github.com/tree-sitter/py-tree-sitter/pull/422">tree-sitter/py-tree-sitter#422</a></li> <li>ci: bump pypa/cibuildwheel from 3.1 to 3.2 in the actions group by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/tree-sitter/py-tree-sitter/pull/418">tree-sitter/py-tree-sitter#418</a></li> <li>ci: bump the actions group with 2 updates by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/tree-sitter/py-tree-sitter/pull/424">tree-sitter/py-tree-sitter#424</a></li> <li>ci: bump pypa/cibuildwheel from 3.2 to 3.3 in the actions group by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/tree-sitter/py-tree-sitter/pull/426">tree-sitter/py-tree-sitter#426</a></li> <li>ci: bump the actions group across 1 directory with 3 updates by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/tree-sitter/py-tree-sitter/pull/430">tree-sitter/py-tree-sitter#430</a></li> <li>feat!: update API for tree-sitter 0.26 by <a href="https://github.com/ObserverOfTime"><code>@ObserverOfTime</code></a> in <a href="https://redirect.github.com/tree-sitter/py-tree-sitter/pull/431">tree-sitter/py-tree-sitter#431</a></li> <li>Add Python 3.14 to CI workflow matrix by <a href="https://github.com/cclauss"><code>@cclauss</code></a> in <a href="https://redirect.github.com/tree-sitter/py-tree-sitter/pull/434">tree-sitter/py-tree-sitter#434</a></li> <li>ci: add riscv64 wheels to PyPI release workflow by <a href="https://github.com/gounthar"><code>@gounthar</code></a> in <a href="https://redirect.github.com/tree-sitter/py-tree-sitter/pull/443">tree-sitter/py-tree-sitter#443</a></li> <li>ci: bump the actions group across 1 directory with 5 updates by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/tree-sitter/py-tree-sitter/pull/446">tree-sitter/py-tree-sitter#446</a></li> <li>fix type hints for Query properties by <a href="https://github.com/unawarez"><code>@unawarez</code></a> in <a href="https://redirect.github.com/tree-sitter/py-tree-sitter/pull/439">tree-sitter/py-tree-sitter#439</a></li> <li>build: bump tree_sitter/core from <code>cd4b6e2</code> to <code>6f2e8a6</code> by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/tree-sitter/py-tree-sitter/pull/447">tree-sitter/py-tree-sitter#447</a></li> <li>build: bump tree_sitter/core from <code>6f2e8a6</code> to <code>cd5b087</code> by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/tree-sitter/py-tree-sitter/pull/449">tree-sitter/py-tree-sitter#449</a></li> <li>build: bump tree-sitter-rust from 0.24.0 to 0.24.1 by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/tree-sitter/py-tree-sitter/pull/444">tree-sitter/py-tree-sitter#444</a></li> <li>ci: bump actions/upload-pages-artifact from 4 to 5 in the actions group by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/tree-sitter/py-tree-sitter/pull/452">tree-sitter/py-tree-sitter#452</a></li> <li>build: bump tree_sitter/core from <code>cd5b087</code> to <code>7f53486</code> by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/tree-sitter/py-tree-sitter/pull/459">tree-sitter/py-tree-sitter#459</a></li> <li>ci: bump the actions group across 1 directory with 2 updates by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/tree-sitter/py-tree-sitter/pull/463">tree-sitter/py-tree-sitter#463</a></li> <li>build: bump tree-sitter-rust from 0.24.1 to 0.24.2 by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/tree-sitter/py-tree-sitter/pull/453">tree-sitter/py-tree-sitter#453</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/cclauss"><code>@cclauss</code></a> made their first contribution in <a href="https://redirect.github.com/tree-sitter/py-tree-sitter/pull/434">tree-sitter/py-tree-sitter#434</a></li> <li><a href="https://github.com/gounthar"><code>@gounthar</code></a> made their first contribution in <a href="https://redirect.github.com/tree-sitter/py-tree-sitter/pull/443">tree-sitter/py-tree-sitter#443</a></li> <li><a href="https://github.com/unawarez"><code>@unawarez</code></a> made their first contribution in <a href="https://redirect.github.com/tree-sitter/py-tree-sitter/pull/439">tree-sitter/py-tree-sitter#439</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/tree-sitter/py-tree-sitter/compare/v0.25.2...v0.26.0">https://github.com/tree-sitter/py-tree-sitter/compare/v0.25.2...v0.26.0</a></p> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href=" |
||
|
|
fd0d29c92d
|
fix(packaging): guard torch extras on intel macos (#2011)
## Description Closes #1931 Guard the `ml` and `voice` `torch` optional dependencies on macOS x86_64 so `headroom-ai[all]` remains resolvable on Intel Macs where PyTorch does not publish compatible wheels for this version floor. The lockfile metadata is updated with the same markers. ## Type of Change - [x] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) - [ ] Documentation update - [ ] Refactoring - [ ] Performance improvement - [ ] Test update - [ ] Other ## Changes Made - Added macOS x86_64 environment markers to `torch` in the `ml` and `voice` extras. - Updated `uv.lock` optional dependency metadata to match the guarded extras. - Added a packaging regression test that checks `[all]` keeps `ml` and `voice` while guarding `torch` on macOS x86_64. ## Testing - [x] Unit tests pass (`pytest`) - [x] Linting passes (`ruff check`) - [x] Formatting verified (`ruff format --check`) - [ ] Manual testing performed ### Test Output ```text $ python3 -m pytest tests/test_optional_dependencies.py -q collected 1 item tests/test_optional_dependencies.py . [100%] ============================== 1 passed in 0.26s =============================== $ .venv/bin/ruff check tests/test_optional_dependencies.py All checks passed! $ .venv/bin/ruff format --check tests/test_optional_dependencies.py pyproject.toml 1 file already formatted ``` ## Test verification (RED -> GREEN) RED, with the `torch` markers temporarily removed from `pyproject.toml`: ```text tests/test_optional_dependencies.py F [100%] FAILED tests/test_optional_dependencies.py::test_all_extra_does_not_require_torch_on_macos_x86_64 E assert False ``` GREEN, with this patch applied: ```text tests/test_optional_dependencies.py . [100%] ============================== 1 passed in 0.26s =============================== ``` ## Real Behavior Proof - Environment: Linux, Python 3.12.3, pytest 9.1.1, ruff 0.14.14. - Exact command / steps: Removed the environment markers from `torch`, ran the new packaging test, restored the markers, and reran the test plus targeted ruff checks. - Observed result: The test fails without the macOS x86_64 guard and passes once the `ml` and `voice` `torch` requirements are guarded. - Not tested: Full `uv run pytest`, full-project `uv run ruff check .`, full-project `uv run ruff format --check .`, and `uv run mypy headroom` were not run locally for this targeted packaging change. ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Checklist - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my code - [x] I have added tests that prove my fix is effective - [x] New and existing targeted tests pass locally with my changes - [x] Any dependent changes have been merged and published in downstream modules ## Screenshots (if applicable) N/A ## Additional Notes No new dependency is added; this only narrows when the existing `torch` optional dependency is selected. |
||
|
|
28ca61fc9d
|
fix: patch nltk vulnerability (CVE-2026-54293) (#1929)
## Description
Updates the locked `nltk` package from 3.9.4 to 3.10.0 to address
CVE-2026-54293, reported by OrbisAI Security as an information
disclosure/path traversal issue in `nltk.data.load()`.
Closes #
## Type of Change
- [x] Bug fix (non-breaking change that fixes an issue)
- [ ] New feature (non-breaking change that adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] Documentation update
- [ ] Performance improvement
- [ ] Code refactoring (no functional changes)
## Changes Made
- Updated the `nltk` lockfile entry from 3.9.4 to 3.10.0.
- Added the new locked `defusedxml` dependency required by `nltk`
3.10.0.
- Added an explicit `nltk>=3.10.0` uv constraint so future lock
refreshes cannot regress below the fixed version.
- Updated the benchmark-extra comment now that the nltk CVE has an
upstream fixed release.
## Testing
<!-- Check what you actually ran, then paste the real command output
below. -->
- [ ] Unit tests pass (`pytest`)
- [ ] Linting passes (`ruff check .`)
- [ ] Type checking passes (`mypy headroom`)
- [ ] New tests added for new functionality
- [x] Manual testing performed
### Test Output
```text
uv lock --locked
Resolved 257 packages in 1ms
uv run --extra benchmark python -c "import importlib.metadata as md; print('lm-eval', md.version('lm-eval')); print('rouge-score', md.version('rouge-score')); print('nltk', md.version('nltk'))"
lm-eval 0.4.10
rouge-score 0.1.2
nltk 3.10.0
```
## Real Behavior Proof
- Environment: GitHub pull request diff for
headroomlabs-ai/headroom#1929.
- Exact command / steps: Reviewed the PR diff and ran the focused uv
lock/import checks listed above.
- Observed result: The lockfile now points at nltk 3.10.0 artifacts,
includes the new defusedxml dependency, and records the nltk>=3.10.0
resolver constraint.
- Not tested: Full local test suite was not run for this lockfile-only
security update.
## Review Readiness
- [x] I have performed a self-review
- [x] This PR is ready for human review
## Checklist
- [x] My code follows the project's style guidelines
- [x] I have performed a self-review of my code
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] I have updated the CHANGELOG.md if applicable
## Screenshots (if applicable)
N/A.
## Additional Notes
Original automated security context from OrbisAI Security:
- CVE: CVE-2026-54293
- Severity: HIGH
- Scanner: trivy
- Rule: `CVE-2026-54293`
- File: `uv.lock`
- Assessment: Likely exploitable
- Description: nltk information disclosure via path traversal in
`nltk.data.load()`.
---------
Co-authored-by: JerrettDavis <mxjerrett@gmail.com>
|
||
|
|
a9515155c7
|
chore: release main (#1918)
🤖 I have created a release *beep* *boop* --- <details><summary>0.31.0</summary> ## [0.31.0](https://github.com/headroomlabs-ai/headroom/compare/v0.30.0...v0.31.0) (2026-07-09) ### Features * **cache:** provider-agnostic cache-mode delta + cc-agnostic prefix comparison ([#1868](https://github.com/headroomlabs-ai/headroom/issues/1868)) ([ |
||
|
|
2990b7457d
|
chore: sync version state to released 0.30.0 to unblock release-please (#1916)
## Description **Fixes the Release Please pipeline**, which stopped opening the release PR, leaving pip / Docker / npm out of sync. ### Root cause Recent releases (0.28 → 0.30) were cut **out-of-band** (manual tag + release), so Release Please's state drifted from reality: - `.release-please-manifest.json` was frozen at **0.29.0**, and the in-repo version files at **0.29.0** — even the `v0.30.0` tag commit has `pyproject.toml = 0.29.0`. The plugin/marketplace manifests were frozen even further back, at **0.22.3**. - `v0.30.0` was tagged and published to PyPI (CI stamps the version from the tag at build time via `version-sync.py`, which is why PyPI got 0.30.0 despite the committed 0.29.0). - With the manifest at 0.29.0, RP kept computing the next version as **0.30.0**, saw that tag already exists, and produced **no PR** — so nothing new could ship, and Docker/npm fell behind. ### Fix Realign the repo with the last real release (0.30.0) so RP can drive the next one: - `.release-please-manifest.json` → `0.30.0` - `pyproject.toml`, `sdk/typescript/package.json`, `plugins/openclaw/package.json`, both `plugin.json`, both `marketplace.json` → `0.30.0` (via `scripts/version-sync.py --version 0.30.0`, which also fixes the 0.22.3 drift). ### What happens after merge 1. Release Please runs on `main`, sees manifest = 0.30.0 + 69 releasable commits since `v0.30.0`, and opens a clean **`chore: release 0.31.0`** PR (bumping every version file). 2. Merging that PR tags `v0.31.0` and fires `release: published`, which publishes **PyPI + npm (SDK + openclaw) + Docker** at 0.31.0 in one shot — bringing all three registries back in sync. No behavior/code change — versions only. ## Type of Change - [x] Bug fix (non-breaking change that fixes an issue) - [ ] New feature - [ ] Breaking change - [ ] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - Advance the Release Please manifest to the last released version (0.30.0). - Sync all 7 version-tracked files to 0.30.0 with the repo's own `version-sync.py`. ## Testing - [x] Linting passes (`ruff check .`) - [x] Manual testing performed (`scripts/verify-versions.py`) ### Test Output ```text $ python scripts/version-sync.py --version 0.30.0 Version synchronized to 0.30.0 $ python scripts/verify-versions.py All versions aligned at 0.30.0 Packages: pyproject.toml, plugins/openclaw/package.json, sdk/typescript/package.json, plugins/headroom-agent-hooks/.claude-plugin/plugin.json, plugins/headroom-agent-hooks/.github/plugin/plugin.json, .claude-plugin/marketplace.json, .github/plugin/marketplace.json ``` ## Real Behavior Proof - Environment: local macOS, project `.venv` (Python 3.12.6). - Exact command / steps: ran `scripts/version-sync.py --version 0.30.0`, set the RP manifest to 0.30.0, then `scripts/verify-versions.py`. - Observed result: `verify-versions.py` reports all seven version locations aligned at 0.30.0; `git diff` shows version-field changes only (no code). Confirmed PyPI latest is 0.30.0 and a `v0.30.0` tag/release exists, while the manifest was 0.29.0 — the drift this PR corrects. - Not tested: the downstream release itself (that runs when the follow-up `chore: release 0.31.0` PR is merged); npm registry state could not be read from this environment (network), but the `publish-npm` job in `release.yml` publishes both npm packages on release. ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Checklist - [x] My code follows the project's style guidelines - [x] I have performed a self-review of my code - [x] My changes generate no new warnings - [x] New and existing unit tests pass locally with my changes |
||
|
|
0ba5065d40
|
Tejas/tool search deferral (#1885)
## Description <!-- Briefly explain the change and why it is needed. --> Closes # ## Type of Change - [ ] Bug fix (non-breaking change that fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - ## Testing <!-- Check what you actually ran, then paste the real command output below. --> - [ ] Unit tests pass (`pytest`) - [ ] Linting passes (`ruff check .`) - [ ] Type checking passes (`mypy headroom`) - [ ] New tests added for new functionality - [ ] Manual testing performed ### Test Output ```text # Paste relevant command output or artifact links here ``` ## Real Behavior Proof - Environment: - Exact command / steps: - Observed result: - Not tested: ## Review Readiness - [ ] I have performed a self-review - [ ] This PR is ready for human review ## Checklist - [ ] My code follows the project's style guidelines - [ ] I have performed a self-review of my code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] I have updated the CHANGELOG.md if applicable ## Screenshots (if applicable) Add screenshots to help explain your changes. ## Additional Notes <!-- Mention any N/A checklist items, tradeoffs, follow-ups, or maintainer context. --> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
660fa8cfb6
|
chore: release main (#1574)
🤖 I have created a release *beep* *boop* --- <details><summary>0.29.0</summary> ## [0.29.0](https://github.com/headroomlabs-ai/headroom/compare/v0.28.0...v0.29.0) (2026-07-03) ### Features * **proxy:** add --lossless no-CCR mode with format-native compaction ([#1721](https://github.com/headroomlabs-ai/headroom/issues/1721)) ([ |
||
|
|
aea3c35177
|
chore: release main (#1441)
🤖 I have created a release *beep* *boop* --- <details><summary>0.28.0</summary> ## [0.28.0](https://github.com/headroomlabs-ai/headroom/compare/v0.27.0...v0.28.0) (2026-06-29) ### Features * add --disable-kompress-fallback to restore legacy PASSTHROUGH fallback ([#1185](https://github.com/headroomlabs-ai/headroom/issues/1185)) ([ |
||
|
|
4db3bc91d9
|
fix(bedrock): add boto3 1.41 + CRT for aws login credentials (#1486)
## Description `pip install headroom-ai[bedrock]` cannot serve users who authenticate with `aws login` (IAM Identity Provider / console-login, DPoP). Resolving those credentials requires the AWS Common Runtime (CRT); without `awscrt`, botocore raises `MissingDependencyException`. The AWS docs state the requirement as: **"Boto3 version 1.41.0 or later with AWS Common Runtime (CRT)"** — i.e. both a modern boto3 floor and CRT (installed via the `[crt]` extra). ## Type of Change - [x] Bug fix (non-breaking) ## Changes Made - `pyproject.toml` `bedrock` extra: bump `boto3>=1.28.0` → `boto3>=1.41.0`, add `botocore[crt]>=1.41.0` (installs `awscrt`). - `uv.lock`: regenerated — adds `awscrt`, resolves `boto3` to 1.42.x. No code changes — the bedrock backend already passes `aws_profile_name` through to the LiteLLM calls (via #1456); this just makes the installed dependencies actually able to resolve `aws login` credentials. ## Impact - **`aws login` (IAM Identity Provider / DPoP):** now works — awscrt present. - **`aws sso login` (classic Identity Center):** unaffected (already worked). - **static keys (`~/.aws/credentials`):** unaffected. - Bumping the boto3 floor only affects the optional `[bedrock]` extra; bedrock users benefit from a current boto3 regardless. ## Testing Dependency-only change. `uv lock` resolves cleanly (257 packages, awscrt 0.29.2, boto3 1.42.38). No runtime code path altered, so existing bedrock tests are unaffected. ## Checklist - [x] Self-review performed - [x] No new warnings - [x] Linting passes ## Additional Notes Focused on the dependency gap only. ARN routing / named-profile wiring / docs are handled in #1456; pricing in #1485. |
||
|
|
80fa086660
|
fix(packaging): move hnswlib to optional [vector] extra so [all] needs no C++ toolchain (#1499)
## Description `pip install "headroom-ai[all]"` aborts on any machine without a C++ toolchain. `[all]` pulls `[memory]`, which was the only extra carrying `hnswlib>=0.8.0`. hnswlib compiles from source where no wheel matches the target, and that build failure rolls back the **entire** `[all]` install. hnswlib is already fully optional at runtime: `MemoryConfig` defaults to `VectorBackend.AUTO` → **sqlite-vec** (pure Python, no compiler), and only falls back to HNSW. So `[memory]` does not need hnswlib to function. This moves hnswlib into a dedicated optional `[vector]` extra, exactly like `[pytorch-mps]` is already kept out of `[all]`. Closes #1368 ## Type of Change - [x] Bug fix (non-breaking change that fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - `pyproject.toml`: - Removed `hnswlib>=0.8.0` from `[memory]` (keeps `sqlite-vec` + `sentence-transformers`; the default sqlite-vec backend still works). - Added `vector = ["hnswlib>=0.8.0"]` for users who opt into the HNSW backend. - `[all]` still references `[memory]` (now hnswlib-free) and does **not** add `[vector]`, so it resolves with no compiler. - `[dev]` keeps `hnswlib`, so CI still installs and exercises the HNSW backend tests. - Docs: documented the new `[vector]` extra in `installation.mdx` and the README, and noted it is excluded from `[all]`; fixed the `[memory]` row that claimed to bundle hnswlib. No application code changed. ## Testing - [x] Linting passes (`ruff check .`) - [x] Manual testing performed (TOML resolution check — see proof) - [ ] Unit tests pass (`pytest`) — no app code changed; existing memory/HNSW tests are unaffected (the HNSW backend dependency moved extras but `[dev]`/CI still install it). ### Test Output ```text $ python - <<'PY' # resolve [all] transitively and check hnswlib placement memory has hnswlib: False vector has hnswlib: True dev has hnswlib: True [all] resolved has hnswlib: False [all] has sqlite-vec: True [all] has sentence-transformers: True PY $ ruff check headroom/ tests/ All checks passed! ``` ## Real Behavior Proof - Environment: Windows 11, Python 3.13.11; `tomllib` + a small transitive-extra resolver over the edited `pyproject.toml`. - Exact command / steps: parse `pyproject.toml`, expand `headroom-ai[...]` self-references in `[all]` recursively, then check which extras carry `hnswlib`. - Observed result: the resolved `[all]` set contains no hnswlib while `[vector]` and `[dev]` do. Full output: ```text memory has hnswlib: False vector has hnswlib: True dev has hnswlib: True [all] resolved has hnswlib: False [all] has sqlite-vec: True [all] has sentence-transformers: True ``` `[all]` now resolves with **no** hnswlib (so no compiler needed), while the HNSW backend stays installable via `[vector]` and still tested via `[dev]`. - Not tested: a real `pip install` on a compiler-less host (the failure is a build-time rollback that the resolver check captures deterministically); the native-wrapper e2e jobs that this `pyproject.toml` change triggers run `wrap` e2e, not the memory HNSW path, so dropping hnswlib from `[all]` does not affect them. ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Additional Notes - Editing `pyproject.toml` trips the `e2e` path filter, so the Windows/macOS/Docker native-wrapper jobs also run on this PR. They install + run the `wrap` e2e flow (not the memory HNSW backend), so the extras change is safe for them. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |