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>
Major fix to code compression that was broken for most real-world files.
Root cause: body truncation used line-based slicing (keep first N lines),
which cut mid-expression (e.g., line 3 of a multi-line dict literal),
producing invalid syntax. 4 out of 5 files failed before this fix.
Changes:
- Statement-based truncation: walk body_node.children (AST statements)
instead of slicing lines. Each child is a complete, syntactically
valid statement. Never cuts mid-expression.
- Skip unnamed AST tokens: filter out { } ; punctuation nodes in
brace-language bodies (JS, Go, Rust, Java, C/C++)
- Fix FIRST_LINE docstring: use source lines directly instead of
reconstructing from byte offsets. Properly handles all quote styles.
- Remove Kompress fallback on syntax failure: return original code
(never serve broken code)
Results: 6/10 real Python files now compress successfully (was 1/5).
anthropic.py: 21,605 → 1,797 tokens (92% saved)
openai.py: 18,032 → 1,162 tokens (94% saved)
core.py: 7,319 → 3,238 tokens (56% saved)
local.py: 7,998 → 3,341 tokens (58% saved)
All 60 existing tests pass including JavaScript.
Memory system now tracks who saved what and prevents duplicates:
- Agent provenance: every memory_save records source_agent, source_provider,
created_via, and timestamp in metadata
- Enriched save response: when similar memory exists (>75% cosine),
tool result includes a note suggesting the LLM call memory_update
to consolidate — piggybacks on the user's own LLM for dedup decisions
- Async background dedup: obvious duplicates (>92% cosine) are
automatically removed in a fire-and-forget background task
- Edit history: memory_update tracks which agent updated and why
- Project-scoped DB: defaults to {cwd}/.headroom/memory.db
- Auto user_id: detects from $USER instead of hardcoded "default"
- Memory wired into OpenAI and Gemini handlers (context + tools)
- OpenAI embedder auto-detected when sentence-transformers unavailable
Verified E2E: Claude saves → Codex sees dedup hint → Codex calls
memory_update instead of saving duplicate → Claude reads back all.
Make memory work across ALL providers sharing the same vector store:
- Wire memory context injection into OpenAI handler (Codex, GPT, etc.)
- Wire memory context injection into Gemini handler
- Add memory tool call handling for OpenAI function calling format
- Project-scoped DB: default to {cwd}/.headroom/memory.db
- Auto-detect user_id from $USER instead of hardcoded "default"
- Auto-detect embedder: use OpenAI embeddings when sentence-transformers
unavailable (no torch/2GB dependency needed)
- Support embedder_backend/openai_api_key in LocalBackendConfig
Verified E2E: Claude saves memories → Codex reads them → Codex adds
new memories → Claude reads back everything including Codex's additions.
Cross-agent memory sharing works through the same proxy and DB.
Make the devcontainer bootstrap and CI smoke tests work from linked worktrees, including git metadata translation, cache ownership fixes, workspace path handling, and config-scoped smoke checks.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a default devcontainer and a compose-backed memory-stack profile, validate them in CI, and document the contributor workflow.
Also lock the memory-stack dependencies, pin related container tooling, and sync the latest healthcheck shutdown fix for stubbed memory handlers.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Guard proxy cleanup so tests and integrations that swap in lightweight memory-handler stubs do not fail during FastAPI lifespan shutdown.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Address the new mypy regression in the healthcheck helpers without changing endpoint behavior.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add /livez and /readyz, keep /health backward-compatible, and wire readiness into Docker artifacts and docs.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Address the new mypy regression in the healthcheck helpers without changing endpoint behavior.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add /livez and /readyz, keep /health backward-compatible, and wire readiness into Docker artifacts and docs.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When --model codex-cli is used but codex is not in PATH,
subprocess.run raises FileNotFoundError. Catch it and raise
a clear RuntimeError with guidance.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Allow `headroom learn` to use locally installed coding agent CLIs
(claude, gemini, codex) as LLM backends, so subscription users
without raw API keys can run failure analysis.
Priority: --model flag > API key > HEADROOM_LEARN_CLI env var > auto-detect
- Pass prompts via stdin to avoid ARG_MAX limits
- Handle TimeoutExpired, truncate stderr, enrich JSONDecodeError
- Add 31 new tests (48 total), all passing
- Update docs/learn.md with CLI backend documentation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Rebase the anonymous telemetry transparency warning work onto the latest main branch and format the new telemetry warning tests so the Python 3.12 lint lane passes cleanly.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add is_telemetry_warn_enabled() feature flag (HEADROOM_TELEMETRY_WARN=off
to suppress at build/pack time) and format_telemetry_notice() helper to beacon.py
- Export new helpers from headroom.telemetry.__init__
- Proxy CLI startup banner now shows Telemetry: ENABLED/DISABLED with opt-out
instructions when enabled
- Log telemetry status at proxy server startup() so it appears in log stream
- wrap CLI _launch_tool() and the bespoke claude wrap command both call
_print_telemetry_notice() so users see the notice before the tool launches
- /stats endpoint now includes anon_telemetry_shipping boolean flag
- Dashboard header shows amber Anon Telemetry indicator chip when
anon_telemetry_shipping is true (theme-matching, with tooltip showing opt-out)
- 30 new tests covering all paths; all 82 tests pass
Agent-Logs-Url: https://github.com/JerrettDavis/headroom/sessions/880a7bb3-3ad9-49f4-a0b6-3ffdde233e48
Co-authored-by: JerrettDavis <2610199+JerrettDavis@users.noreply.github.com>
Refactor headroom learn into a plugin architecture where each coding
agent (Claude Code, Codex, Gemini CLI) is a self-contained plugin
with scanner, writer, and detection logic. External plugins can
register via the headroom.learn_plugin entry point.
- Add LearnPlugin ABC (base.py) and plugin registry (registry.py)
- Move scanners from monolithic scanner.py into plugins/ directory
- Extract shared error classification and tool name map (_shared.py)
- Add GeminiScanner for Google Gemini CLI session parsing
- CLI uses dynamic agent detection via registry (no hardcoded choices)
- All existing imports preserved via backwards-compat re-exports
- Wire agent_type through wrap → proxy → TrafficLearner
- Flush learned patterns to correct .md file at proxy shutdown
- Fix shutdown queue drain bug (patterns were lost on exit)
- 97 tests pass (84 existing + 13 new registry/plugin tests)
Update the OpenAI Codex routing test double to match the response shape
expected by the handler so the success path is exercised instead of
falling into the generic failure branch.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Wire the proxy's operational metrics facade into the new observability
layer, expand built-in Prometheus export, surface OTEL and Langfuse status
in /stats, and document the split between anonymous telemetry, OTEL metrics,
and Langfuse traces.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a shared observability layer for OTEL metrics and Langfuse tracing.
Instrument the shared compression pipeline once so SDK and proxy paths can
reuse the same metrics and spans without scattering telemetry concerns.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
TemporaryDirectory cleanup fails with OSError when OpenClaw gateway
leaves behind lock/session files. ignore_cleanup_errors=True lets
the test pass while the OS cleans up /tmp on reboot.
Transcode technique now runs RapidOCR to extract text from images.
Falls back to full_low if OCR confidence < 70% or no text detected.
Token counting is now done AFTER compression by measuring the actual
output — no hardcoded estimates. OCR text counted by char length,
resized images re-estimated from new dimensions.
RapidOCR added to headroom-ai[image] extra (~15MB ONNX models, ~180ms CPU).
4 new OCR tests (extraction, blank image, confidence threshold, full pipeline).
29 total image compression tests passing.