Add host-managed OpenClaw wrap and unwrap flows to the Docker-native wrappers so the installed headroom script can configure the OpenClaw plugin on the host while keeping Headroom itself in Docker. Reuse hidden prepare-only hooks for OpenClaw config payloads, preserve existing plugin metadata on unwrap, and update the Docker-native and integration docs to reflect the supported flow.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep the default Headroom proxy startup path lightweight so OpenClaw can launch it reliably on Windows. This defers heavyweight provider, cache, transform, pricing, and detector imports until they are actually needed, adds a lightweight version module, and keeps the OpenClaw launcher on the configured Python path.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Extract shared defaultLogger constant, use in both ProxyManager and
HeadroomContextEngine (was duplicated inline in both constructors)
- Extract parseProxyUrl() helper, reused by normalizeAndValidateProxyUrl
and withDefaultPort (eliminates redundant URL parsing)
- Add test helpers: stubProbeSuccess/NonHeadroom/Unreachable to replace
6 identical inline fetch mock constructions
- Remove duplicate probe tests from engine.test.ts (already covered in
proxy-manager.test.ts)
- Clean up unused probeHeadroomProxy import from engine.test.ts
Net: -26 lines, same coverage (28 tests)
- 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
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)
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.
OpenClaw plugin:
- Fix assistant content always returned as array (fixes flatMap crash)
- Clean up debug logging, restore clean plugin entry point
- Add test for text-only assistant round-trip
- Set headroom-ai dependency to npm (not local path)
Telemetry:
- Switch from sb_publishable_ to JWT anon key (PostgREST needs JWT for RLS)
- Switch from upsert to plain INSERT (anon role upsert was failing with 42501)
- Verified: full payload with all JSONB columns writes successfully (201)
Cost tracker:
- Use output_buffer instead of hardcoded 500 for cost estimation in client.py
- CostTracker counterfactual: value removed tokens at avg effective $/token
(actual_spend / billed_tokens) instead of uncached list price — aligns
savings with real billing mix (cache reads, writes, uncached)
- Add debug log for /stats summary payload
- Add 3 tests for new cost savings calculation
TypeScript SDK:
- Add tokenBudget param to compress(), HeadroomClient, CompressOptions
- Proxy /v1/compress accepts optional token_budget to override model limit