mirror of
https://github.com/headroomlabs-ai/headroom.git
synced 2026-08-27 14:17:10 -04:00
2 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
fa05ebc849
|
docs: clarify OpenCode integration (#1317)
## Description Clarifies the OpenCode documentation follow-up for PR #1105 so users can install `headroom-opencode`, configure provider routing, use the native plugin, and copy working retrieve/compression helper examples. ## Type of Change - [x] Documentation update - [ ] Bug fix - [ ] New feature - [ ] Breaking change ## Changes Made - Documented how `headroom wrap opencode` wires provider config, MCP tools, and runtime environment. - Documented the native `HeadroomPlugin` path, `HEADROOM_PROXY_URL`, retrieve tooling, and programmatic config helpers. - Fixed `plugins/opencode/README.md` examples so `compressWithHeadroom` uses the exported options-object API and `headroom_retrieve` uses `hash`. ## Testing - [x] Type checks pass. - [x] Unit tests pass. - [x] Whitespace check passes. ### Test Output ```text plugins/opencode: npm run typecheck > tsc --noEmit plugins/opencode: npm test Test Files 2 passed (2) Tests 9 passed (9) docs: npm run types:check ✓ Types generated successfully repo: git diff --check (no output) ``` ## Real Behavior Proof - Environment: Local macOS worktree at `docs/pr-1105-documentation-followup`, Node/npm project commands run from `plugins/opencode` and `docs`. - Exact command / steps: Updated the README snippets, ran `npm run typecheck`, reran `npm test` with elevated permissions after the sandbox blocked a local `127.0.0.1` listener, ran `npm run types:check` in `docs`, and ran `git diff --check`. - Observed result: Typecheck completed with `tsc --noEmit`; the OpenCode package test suite reported 2 files and 9 tests passed; docs type generation completed successfully; `git diff --check` produced no output. - Not tested: Browser-rendered documentation preview. `docs: npm run build` was started locally but produced no output for roughly 90 seconds and was stopped, so this follow-up does not claim a fresh local docs build result. ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Additional Notes - The linked review comment asked for README examples to match `compressWithHeadroom(messages, options)` and `createHeadroomRetrieveTool` requiring `hash`; both snippets now match the exported API. |
||
|
|
b4571cc346
|
feat: headroom wrap opencode / unwrap opencode CLI (#1105)
## Summary This PR implements transparent `headroom wrap opencode` support without asking users to edit OpenCode provider URLs, choose an extra CLI flag, or maintain a static provider list. The wrapper now lives at the runtime transport boundary: OpenCode keeps its user/provider config, while Headroom intercepts outbound provider traffic in-process and routes it through the local Headroom proxy. ## What changed ### Transparent OpenCode wrapping - `headroom wrap opencode` injects the `headroom-opencode` plugin through `OPENCODE_CONFIG_CONTENT`. - Existing OpenCode provider URLs are preserved. We do not rewrite user config URLs to point at Headroom. - Existing `OPENAI_BASE_URL` and `ANTHROPIC_BASE_URL` env vars are preserved. - Local OpenCode traffic, localhost traffic, and Headroom proxy traffic bypass the shim to avoid loops. ### Runtime transport interception - Added an OpenCode plugin transport shim that wraps: - `globalThis.fetch` - `http.request` / `http.get` - `https.request` / `https.get` - External provider calls are routed to the local Headroom proxy. - The original upstream origin is passed through `x-headroom-base-url`, so the proxy can forward to the real provider without changing OpenCode config. - External `http2.connect` is blocked loudly instead of allowing direct provider traffic to leak outside Headroom. ### Live provider additions Provider coverage is no longer based on a static config scan. Because routing happens at outbound request time, providers added mid-session are routed through Headroom automatically as long as they use the covered Node transport paths. ### Subagent and child-process coverage - The parent OpenCode plugin sets a packaged Node preload shim through `NODE_OPTIONS=--import=.../hook-shim/handler.js`. - The transport shim patches `child_process.spawn`, `exec`, `execFile`, and `fork` so child Node processes receive the Headroom preload even when OpenCode passes a custom `env`. - The child-process shim fails closed if it loads without `HEADROOM_OPENCODE_TRANSPORT_PROXY_URL`. - This closes the subagent leak path where a child Node process could otherwise start without Headroom transport interception. ## Why this goes beyond PR #1089 PR #1089 improves OpenCode provider registration, but it still focuses on provider config shape. This PR moves the enforcement boundary to runtime transport interception. This PR goes further because: - No provider URL rewriting is required. - New providers added mid-session are covered automatically. - Subagents and child Node processes inherit the Headroom transport shim. - Direct external HTTP/2 paths fail loudly instead of leaking. - The wrap remains transparent to the user's OpenCode provider config. - The wrapper is fail-closed for unsupported child-process preload state. ## Additional robustness fixes While validating the change in Docker, the full Python suite exposed unrelated Linux/container robustness issues. These are fixed in this PR so the suite is green: - Binary cache handling now treats cache paths under a non-writable existing parent as unavailable, including when tests run as root in Docker. - `release_version.py` honors `MANUAL_VER` before git calls so direct script execution works outside a `.git` checkout. - Test logger isolation now resets relevant Headroom child loggers so proxy logging setup cannot poison later `caplog` tests. - The scanner missing-path test now uses a guaranteed missing `tmp_path` child instead of relying on `/nonexistent/path`. ## Validation All implementation validation was run inside Docker. - Full Python suite from a fresh Docker copy: `6605 passed, 523 skipped`. - Ruff on changed Python/OpenCode paths: passed. - OpenCode plugin typecheck: passed. - OpenCode plugin tests: `9 passed`. - OpenCode plugin build: passed. - Hook shim preload smoke test: passed. ## Notes This PR intentionally does not add a CLI option. `headroom wrap opencode` means full wrap. Either Headroom wraps OpenCode transparently, or the path fails loudly instead of silently leaking provider traffic. --------- Co-authored-by: Rudimar Ronsoni <6081613+rudironsoni@users.noreply.github.com> |