Commit graph

17 commits

Author SHA1 Message Date
Sergei Baikin
6576ef639c
fix(openclaw-plugin): circuit breaker + per-request timeout for proxy resilience (#639)
## Description

This change adds bounded timeout and circuit-breaker behavior so
OpenClaw can degrade safely when Headroom or the upstream stream stalls,
while returning structured proxy errors instead of hanging.

Closes #638 by improving OpenClaw/proxy resilience when the Headroom
proxy stalls or Anthropic resets a stream. The PR adds proxy-side
handling for `httpx.RemoteProtocolError`, returns structured 502
responses for otherwise unhandled proxy middleware errors, and adds
OpenClaw plugin timeout/circuit-breaker fallback behavior.

## Type of Change

- [x] Bug fix
- [ ] New feature
- [x] Documentation
- [ ] Refactor
- [x] Tests only

## Changes Made

- Added OpenClaw plugin per-request compression timeout and circuit
breaker fallback.
- Cleared timeout timers after successful or failed compression so
successful calls do not leave pending timers.
- Added a focused Vitest regression for timeout cleanup.
- Added `contracts.tools` for `headroom_retrieve` without whole-file
manifest reformatting.
- Added proxy handling for mid-stream `httpx.RemoteProtocolError` and
structured 502 fallback behavior.
- Documented the new OpenClaw resilience configuration fields.

## Testing

- [x] Unit tests
- [x] Integration-style proxy tests
- [x] Typecheck/build
- [ ] Manual testing

### Test Output

```text
cd plugins/openclaw && npm test
Test Files 6 passed (6), Tests 55 passed (55)

cd plugins/openclaw && npm run typecheck
passed

cd plugins/openclaw && npm run build
Build success

UV_SKIP_WHEEL_FILENAME_CHECK=1 uv run --with pytest --with pytest-asyncio --with fastapi --with httpx --with uvicorn --with h2 python -m pytest tests/test_proxy_streaming_resilience.py -q
24 passed in 2.16s
```

## Real Behavior Proof

- Environment: Windows 11, Node/npm from local plugin worktree, Python
3.13.3, focused local worktree for PR #639.
- Exact command / steps: Installed plugin dependencies, ran OpenClaw
plugin tests/typecheck/build, and ran the proxy streaming resilience
suite with required async/FastAPI/httpx extras.
- Observed result: Plugin tests, typecheck, build, and proxy resilience
tests all passed.
- Not tested: Live OpenClaw gateway session in this pass; original
reporter previously verified patched files in a container and OpenClaw
degraded/recovered cleanly.

## Review Readiness

- [x] I have performed a self-review
- [x] This PR is ready for human review

---------

Co-authored-by: Sergei Baikin <sergei.baikin@fotograf.de>
Co-authored-by: JerrettDavis <mxjerrett@gmail.com>
Co-authored-by: JD Davis <jd@jds-macbook-air.tail2a279.ts.net>
2026-08-13 11:52:01 -05:00
felixboenkost-droid
6d116b15f1
Harden OpenClaw plugin proxy routing (#1074)
## Description

Hardens the bundled OpenClaw plugin so configured proxy routing is
fail-closed and `autoStart` is opt-in.

Closes: N/A

This follow-up is intentionally separate from the ContentRouter cache
fix because it changes plugin/gateway behavior rather than core
compression routing.

The plugin should not mutate upstream provider routing unless a
configured proxy URL is reachable and looks like Headroom. It should
also avoid unhandled startup promise rejections when proxy startup is
fire-and-forget.

Why this shape:

- `autoStart: false` by default matches deployments where Headroom is
supervised externally, for example by systemd. The plugin should not
silently start or assume ownership of a proxy unless the operator opted
in.
- Provider routing is fail-closed: a configured URL must first respond
like Headroom, not merely expose a generic liveness endpoint. This
prevents accidentally routing model traffic through the wrong local
service.
- `/readyz` is treated as liveness, not identity. Identity comes from
Headroom-shaped stats endpoints (`/v1/retrieve/stats` or `/stats`)
because those are harder for unrelated services to satisfy by accident.
- Startup remains asynchronous, but errors are captured and exposed
instead of becoming unhandled promise rejections.
- This is a separate PR because the core cache fix is about compression
correctness, while this patch is about integration safety around
OpenClaw gateway routing.

## Type of Change

- [x] Bug fix (non-breaking change fixes issue)
- [ ] New feature (non-breaking change adds functionality)
- [ ] Breaking change (fix or feature would cause existing functionality
change)
- [ ] Documentation update
- [ ] Performance improvement
- [ ] Code refactoring (no functional changes)

## Changes Made

- Make proxy `autoStart` opt-in (`default: false`).
- Probe configured `proxyUrl` before applying provider routing.
- Treat `/readyz` as liveness only; require Headroom-shaped
`/v1/retrieve/stats` or `/stats` for identity.
- Observe fire-and-forget startup promise rejection and expose startup
error for callers.
- Isolate proxy-ready listener failures.
- Keep provider routing deferred when no active/probed Headroom proxy
exists.
- Register retrieve tool with explicit `headroom_retrieve` name.
- Extend plugin/unit tests for configured proxy failures, generic
non-Headroom endpoints, path collisions, and routing behavior.

Changed files:

- `plugins/openclaw/README.md`
- `plugins/openclaw/openclaw.plugin.json`
- `plugins/openclaw/src/engine.ts`
- `plugins/openclaw/src/plugin/index.ts`
- `plugins/openclaw/src/proxy-manager.ts`
- `plugins/openclaw/test/engine.test.ts`
- `plugins/openclaw/test/gateway-config.test.ts`
- `plugins/openclaw/test/plugin-runtime-routing.test.ts`
- `plugins/openclaw/test/proxy-manager.test.ts`

## Testing

- [x] Unit tests pass (`pytest`)
- [x] Linting passes (`ruff check .`)
- [x] Type checking passes (`mypy headroom`)
- [x] New tests added new functionality
- [x] Manual testing performed

### Test Output

```text
$ npm test

Test Files  6 passed (6)
Tests  74 passed (74)

$ npm run typecheck
tsc --noEmit

$ npm run build
tsup && node prepare-dist.mjs
Build success
```

## Real Behavior Proof

- Environment: local OpenClaw plugin package in the Headroom repo.
- Exact command / steps:
  - Run plugin test suite.
  - Run TypeScript typecheck.
  - Run plugin build.
- Observed result:
  - Tests passed: `74/74`.
  - Typecheck passed.
  - Build passed.
- Not tested:
- Full OpenClaw Gateway integration as part of this standalone PR prep.

## Review Readiness

- [x] I performed self-review
- [x] This PR ready for human review

## Checklist

- [x] My code follows project's style guidelines
- [x] I performed self-review my code
- [ ] I commented my code, particularly in hard-to-understand areas
- [x] I made corresponding changes documentation
- [x] My changes generate no new warnings
- [x] I added tests prove fix is effective or feature works
- [x] New and existing unit tests pass locally my changes
- [ ] I updated CHANGELOG.md if applicable

## Screenshots (if applicable)

N/A.

## Additional Notes

Checklist items left unchecked intentionally:

- No CHANGELOG update included.
- No extra comments were needed beyond existing code structure.

Co-authored-by: Björn-Christian Bönkost <bjoern@v2202603344248440850.hotsrv.de>
2026-06-22 22:52:59 -05:00
Tim Poppe
7c8c909c85
fix(openclaw): declare headroom_retrieve tool contract (#947)
## Summary
- add `contracts.tools` to the OpenClaw plugin manifest
- declare `headroom_retrieve` so the manifest matches the tool
registered at runtime
- remove the OpenClaw `contracts.tools` warning during startup

## Testing
- npm test
- npm run typecheck


<!-- headroom-maintainer-template-completion:start -->

## Description

This PR prepares `fix(openclaw): declare headroom_retrieve tool
contract` for review by documenting the intended change, validation
evidence, and remaining merge-readiness context.

Linked issues: None declared.

## Type of Change

- [x] Bug fix
- [ ] New feature
- [ ] Documentation
- [ ] Refactor
- [ ] Tests only

## Changes Made

- Commit: fix(openclaw): declare headroom_retrieve tool contract
- Touches `plugins/openclaw/openclaw.plugin.json`

## Testing

- [x] GitHub checks reviewed
- [x] Metadata/template validation
- [ ] Local functional testing

### Test Output

```text
gh pr view 947 --repo chopratejas/headroom --json statusCheckRollup
- PR Governance / template: FAILURE
- PR Governance / label: SUCCESS
- external / GitGuardian Security Checks: SUCCESS
```

## Real Behavior Proof

- Environment: GitHub PR metadata and checks for `chopratejas/headroom`
PR #947.
- Exact command / steps: Reviewed PR title, commits, changed files,
linked issues, labels, and check rollup; appended this maintainer
template completion block without replacing the author's original
description.
- Observed result: PR body now contains all required governance
sections, checked readiness fields, and a non-placeholder validation
evidence block.
- Not tested: This pass updated PR metadata only; code validation
remains represented by the linked GitHub checks and any author-provided
evidence above.

## Review Readiness

- [x] I have performed a self-review
- [x] This PR is ready for human review

<!-- headroom-maintainer-template-completion:end -->
2026-06-15 11:12:26 -05:00
JerrettDavis
2f05705043 fix(openclaw): normalize provider proxy routing
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-08 22:28:17 -05:00
JerrettDavis
d4f6e3938f fix(proxy): add fast-fail launch settings
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-08 22:03:21 -05:00
JerrettDavis
e0383675aa fix(openclaw): keep gateway routing runtime-only 2026-04-08 21:10:49 -05:00
JerrettDavis
6f500dfa9c feat(openclaw): support configurable gateway providers 2026-04-08 21:10:49 -05:00
JerrettDavis
92b7b09f70 fix(openclaw): route codex through headroom proxy 2026-04-08 21:10:49 -05:00
JerrettDavis
746a1737c1 Select Headroom context engine on install 2026-04-06 21:35:58 -05:00
JerrettDavis
89f3e5f01f fix(openclaw): proxyPort only applies to local URLs, consistency pass
- proxyPort default (8787) now only applied to local URLs; remote URLs
  use their protocol default (80/443) as expected
- Remove redundant localhost-only entries from network capabilities
  (covered by http://*:* and https://*:* wildcards)
- Sync package.json capabilities with openclaw.plugin.json
- Export isLocalProxyUrl from barrel index
- Fix JSDoc indentation in start() method
- Rename "Required Proxy Setup" to "Manual Proxy Setup" with accurate
  description for remote proxy users
- Clarify autoStart description: local-only, ignored for remote
- Add test: remote URL does not get proxyPort applied

Build: tsc clean, 30 tests passed
2026-04-03 10:30:10 -05:00
JerrettDavis
4c3d9c4e28 feat(openclaw): support remote Headroom proxy (connect-only)
Remove localhost-only restriction from proxyUrl validation. Remote URLs
are connect-only: the plugin probes and uses them but never attempts to
spawn a subprocess. Auto-start remains available for local addresses
(127.0.0.1/localhost) only.

- Accept http:// and https:// URLs for any hostname
- Add isLocalProxyUrl() helper to gate auto-start on local addresses
- Remote URLs that fail probe get a clear "Remote proxy not reachable"
  error instead of falling through to auto-start
- Update plugin.json schema, network capabilities, and UI hints
- Update plugin README with local vs remote proxy sections
- Add tests: remote connect, remote fail-fast, isLocalProxyUrl

Build: tsc --noEmit clean
Tests: 29 passed (0 skipped)
2026-04-03 10:30:09 -05:00
JerrettDavis
fa99ba785e docs: add OpenClaw plugin section to main README
Add dedicated OpenClaw plugin section with install instructions,
explanation of --dangerously-force-unsafe-install requirement (proxy
subprocess spawning), and quick config example. Links to plugin README
for full details. Update integration tables to reference new section.

Also fix proxy port handling: apply default proxyPort when explicit
proxyUrl omits port, and allow trailing slash in proxyUrl validation
pattern. Add test coverage for port defaulting behavior.
2026-04-03 10:30:09 -05:00
JerrettDavis
593f1b7829 Restore pythonPath and proxyPort config support 2026-04-02 22:21:05 -05:00
JerrettDavis
e4c7c47e34 Auto-detect proxyUrl by default and keep explicit override 2026-04-02 22:10:12 -05:00
JerrettDavis
777ffeb716 Add controlled proxy autostart and unsafe-install guidance 2026-04-02 21:47:27 -05:00
JerrettDavis
205ec54df2 Harden openclaw plugin proxy handling and metadata 2026-04-02 21:27:12 -05:00
chopratejas
053c4a06af feat: add OpenClaw ContextEngine plugin (@headroom-ai/openclaw)
- HeadroomContextEngine: implements ContextEngine interface (bootstrap, ingest,
  assemble, compact, afterTurn, prepareSubagentSpawn, dispose)
- ProxyManager: auto-detects running proxy or spawns one as child process,
  health checks, restart on crash, graceful shutdown
- AgentMessage ↔ OpenAI format conversion (user, assistant/tool_use, toolResult)
- headroom_retrieve CCR tool: agent can retrieve original uncompressed content
- Plugin manifest (openclaw.plugin.json) with config schema
- 11 tests (6 unit + 5 integration), all passing
- Integration tested: 100 servers compressed, 3,735 tokens saved (82%)
2026-03-28 13:43:40 -07:00