Commit graph

2630 commits

Author SHA1 Message Date
Tejas Chopra
97d39580c5
Merge pull request #104 from pacifio/main
typescript coverage
2026-04-06 10:01:00 -07:00
Adib Mohsin
cdb721a713 typescript coverage 2026-04-06 21:24:36 +06:00
JerrettDavis
ca7384402b Fix review regressions in compare, wrap, and Docker 2026-04-05 17:12:48 -05:00
JerrettDavis
5ffa77f4a3 Harden anthropic cache-mode replay stability 2026-04-05 16:11:39 -05:00
JerrettDavis
d00c6739e1 Fix CI regressions for cache benchmark work 2026-04-04 22:33:44 -05:00
JerrettDavis
96fd3d9652 Add Anthropic cache-mode delta replay 2026-04-04 22:23:10 -05:00
JerrettDavis
f2a32f9721 Harden Anthropic cache mode stability 2026-04-04 22:06:52 -05:00
JerrettDavis
1206c0ede2 Improve Claude cache simulation accounting 2026-04-04 21:54:45 -05:00
JerrettDavis
09829be0f4 Add memory-conscious Claude session benchmark harness 2026-04-04 21:19:40 -05:00
JerrettDavis
5a2f1aeb42 Clarify token vs cache run modes in docs 2026-04-04 15:03:23 -05:00
JerrettDavis
0a8254d629 Remove obsolete Ruff UP038 ignore to stabilize CI lint output 2026-04-04 15:02:04 -05:00
JerrettDavis
83b730f2b9 Fix CI lint/format failures after proxy mode hardening 2026-04-04 14:42:32 -05:00
JerrettDavis
2625789a28 Harden cache-mode immutability for OpenAI and fix stats mode reporting 2026-04-04 14:36:29 -05:00
JerrettDavis
54419ad8b8 Rebrand proxy modes to token/cache and harden cache-mode stability 2026-04-04 14:32:07 -05:00
JerrettDavis
d78fdfe02d Merge remote-tracking branch 'upstream/main' into fix/anthropic-prefix-cache-stability
# Conflicts:
#	headroom/proxy/handlers/anthropic.py
2026-04-04 13:54:54 -05:00
JerrettDavis
7d02829f02 Harden Anthropic prefix cache stability across proxy and batch paths 2026-04-04 13:45:37 -05:00
Tejas Chopra
ef2d1dc1fb
Merge pull request #101 from pratikbin/main
fix: image verities
2026-04-04 11:15:33 -07:00
pratikbin
8f38d97ed7
Merge branch 'chopratejas:main' into main 2026-04-04 21:57:00 +05:30
pratikbin
63aebe8235 refactor(docker): migrate to bake with multi-variant distroless images 2026-04-04 21:51:37 +05:30
chopratejas
4bd778fb57 Fix headroom learn writing ~/CLAUDE.md instead of ~/.claude/CLAUDE.md
When sessions were started from ~ as working directory, the writer
produced ~/CLAUDE.md which Claude Code doesn't read. Now redirects
to ~/.claude/CLAUDE.md (the global location Claude Code reads for
all sessions).

Fixes #96
2026-04-03 23:28:56 -07:00
chopratejas
7f849658ce Fix remaining review issues: null safety, compressed count, batch tokens
- M8: Fix null prompt_tokens_details in streaming.py (2 more instances)
- Issue 2: requests_compressed now counts by tokens_saved > 0 only,
  not savings_percent > 0 (which could be negative from pipeline overhead)
- H3: Initialize original_tokens=0 before try block in Google batch handler
  so error handler has a valid value
- L4: Google batch handler now looks up model context limit via
  openai_provider.get_context_limit() instead of hardcoding 128000
2026-04-03 23:19:42 -07:00
chopratejas
da2fe3a0a1 Disable image compression until token counting is accurate
Image compression inflated savings metrics by 3-4x because the tokenizer
counted base64 data as text tokens (330K per 1MB image). The compressor
itself works, but reported metrics were wrong.

TODO: re-enable once tokenizer extracts image dimensions and uses
Anthropic's formula (width*height/750) for accurate counting.
2026-04-03 22:58:18 -07:00
chopratejas
af418a2556 Fix code review issues: batch NameError, null safety, token types
From deep code review of the refactoring:
- H3: Fix potential NameError in Google batch error handler (original_tokens
  unbound if pipeline fails before producing result)
- M8: Fix null prompt_tokens_details from OpenAI (use `or {}` not default)
- L3: Add input_audio/audio/input_image to tokenizer (prevent json.dumps fallback)
- L6: _read_request_json now validates result is a dict (not list/string)
- H1/L2: Remove stale _HEADROOM_LOG_DIR and unused MAX_RATE_LIMITER_BUCKETS
2026-04-03 22:49:40 -07:00
Tejas Chopra
f984021db1
Merge pull request #98 from JerrettDavis/hotfix/openclaw-toolcall-stream-linkage
fix(openclaw): preserve toolCall linkage for streaming tool outputs
2026-04-03 22:39:09 -07:00
Tejas Chopra
43f73981cf
Merge pull request #100 from JerrettDavis/feat/wrap-openclaw-bootstrap
feat(cli): add one-command OpenClaw wrap bootstrap
2026-04-03 22:38:47 -07:00
JerrettDavis
cd2741cfff test(cli): add branch coverage for wrap openclaw flows 2026-04-03 23:55:14 -05:00
JerrettDavis
61dacc94a1 fix(cli): default wrap openclaw spec to headroom-ai/openclaw 2026-04-03 23:36:23 -05:00
JerrettDavis
490cf15a57 style: apply ruff formatting for wrap openclaw changes 2026-04-03 23:20:15 -05:00
JerrettDavis
3a25ed4571 fix(cli): make wrap openclaw npm-first and idempotent 2026-04-03 23:15:24 -05:00
JerrettDavis
c5e3686c89 feat(cli): add one-command OpenClaw wrap bootstrap 2026-04-03 23:08:13 -05:00
JerrettDavis
5f075dee81 fix(openclaw): preserve tool call linkage in converted history 2026-04-03 22:49:30 -05:00
chopratejas
e8ab444f09 Refactor: split server.py into handler mixins (Steps 5-9)
server.py: 8778 → 2343 lines (73% reduction)

HeadroomProxy now inherits from 5 handler mixins:
- StreamingMixin (901 lines): SSE parsing, streaming, response relay
- AnthropicHandlerMixin (1435 lines): /v1/messages, batch API
- OpenAIHandlerMixin (1320 lines): /v1/chat/completions, /v1/responses, WebSocket
- GeminiHandlerMixin (649 lines): Gemini native API
- BatchHandlerMixin (995 lines): Google/OpenAI batch processing

All backward-compatible imports preserved via re-exports.
181 tests pass, 0 regressions. Real-world tested with Anthropic,
OpenAI, and GPT-5.4 API calls.
2026-04-03 17:08:39 -07:00
chopratejas
6a8ae297d6 Refactor: extract 7 modules from server.py (Steps 2-4)
server.py: 8778 → 7412 lines (-1366, -15.5%)

Extracted modules:
- cost.py (629 lines): CostTracker, build_prefix_cache_stats, merge_cost_stats
- prometheus_metrics.py (312 lines): PrometheusMetrics
- semantic_cache.py (142 lines): SemanticCache
- rate_limiter.py (101 lines): TokenBucketRateLimiter
- request_logger.py (108 lines): RequestLogger
- helpers.py (195 lines): _read_request_json, constants, lazy loaders
- models.py (199 lines): ProxyConfig, RequestLog, CacheEntry (from Step 1)

All existing imports via headroom.proxy.server continue to work
through re-exports. Updated test patches to target new module paths.

181 tests pass, 0 regressions.
2026-04-03 16:18:08 -07:00
Tejas Chopra
814701e5ac
Merge pull request #94 from JerrettDavis/fix/openclaw-safe-proxy-config
docs: add OpenClaw plugin section to main README
2026-04-03 08:58:59 -07:00
JerrettDavis
3e368f13c8 refactor(openclaw): DRY up duplicate code across plugin
- 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)
2026-04-03 10:30:10 -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
chopratejas
4f2213b7a4 Update benchmarks with real production telemetry and compression data
- Added compression performance table (6 content types, 1-2ms latency)
- Added production telemetry: 52ms median overhead, 50K+ sessions
- Added pipeline step timing from real-world data
- Added fleet summary (249 instances, 1.4B tokens saved)
- Added honest Limitations section (what we don't compress)
- Removed stale multi-tool agent test (script missing)
2026-04-02 22:36:51 -07:00
Tejas Chopra
48c461665d
Merge pull request #91 from pratikbin/main
[WIP] feat: Dockerfile & ci
2026-04-02 22:31:28 -07:00
Tejas Chopra
e2c2ba8195
Merge pull request #88 from gglucass/codex/display-session-metrics
Add canonical display-session metrics for downstream dashboards
2026-04-02 22:22:17 -07:00
Tejas Chopra
865926a7a1
Merge pull request #93 from JerrettDavis/fix/openclaw-safe-proxy-config
fix: harden openclaw proxy auto-detect and startup
2026-04-02 22:21:35 -07:00
JerrettDavis
3e11dc6316 Remove skipped integration test registration 2026-04-02 22:51:13 -05:00
JerrettDavis
3569eabdbd Add comprehensive tests for proxy detection and launcher logic 2026-04-02 22:28:48 -05:00
JerrettDavis
593f1b7829 Restore pythonPath and proxyPort config support 2026-04-02 22:21:05 -05:00
JerrettDavis
536ef8b5e2 Clarify local npm install path for launcher detection 2026-04-02 22:12:53 -05:00
JerrettDavis
e4c7c47e34 Auto-detect proxyUrl by default and keep explicit override 2026-04-02 22:10:12 -05:00
JerrettDavis
74ca68888f Add ordered launcher fallback for headroom proxy startup 2026-04-02 21:52:26 -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