Commit graph

2630 commits

Author SHA1 Message Date
chopratejas
8f438b0674 Introducing headroom wrap
- headroom wrap claude is the simplest way to start up claude
- It will also install rtk-ai locally
- rtk-ai is a cli wrapper that can save ~90% tokens for CLI calls made by Claude Code
2026-03-11 23:01:42 -07:00
chopratejas
95c8133b7c Kompress: use argmax for token selection, remove hardcoded 0.5 threshold
The model is a binary classifier — let it decide. When no target_ratio
is set (default proxy path), use argmax on token head logits directly
instead of score > 0.5 cutoff. Span head boosts borderline tokens
(0.3-0.5 probability) in important spans.

Result: compression adapts per content — 9% kept for verbose filler,
100% kept for dense commands/code. Previously uniform 29% everywhere.
2026-03-10 23:27:20 -07:00
chopratejas
df1705549f Add Kompress: ModernBERT token compressor replacing LLMLingua-2
Adds kompress_compressor.py — a self-contained ModernBERT-based token
compressor that auto-downloads from chopratejas/kompress-base on HuggingFace.
Trained on 330K structured tool outputs (JSON, diffs, logs, code, SQL,
agentic traces), achieving 82% entity preservation vs LLMLingua-2's 36%.

Changes:
- New: kompress_compressor.py — dual-head ModernBERT (token + span CNN)
with HuggingFace auto-download, no extra pip install needed
- ContentRouter: Kompress is primary ML compressor, LLMLingua-2 is fallback
- fallback_strategy changed from PASSTHROUGH to KOMPRESS — unknown/mixed
content now gets compressed instead of ignored
- No hardcoded compression ratios — model decides per-token importance,
optional target_ratio only when user explicitly sets it via API
- Version bump: 0.3.8 → 0.4.0
2026-03-10 18:45:02 -07:00
chopratejas
a727676a22 Updating the README to reflect the right positioning for Headroom
- Added Discord channel as well
- README is now simpler
2026-03-10 15:06:06 -07:00
Tejas Chopra
4a655fbc6e feat: provider-aware prefix cache tracking and combined savings dashboard
Add per-provider prefix cache metrics (Anthropic/OpenAI/Google/Bedrock)
with correct economics (read discounts, write premiums, bust detection).
Model-aware bust detection excludes cold starts when switching models.
Dashboard hero metric shows combined savings (compression + cache) with
per-provider breakdown table, efficiency bar, and hit rate tracking.

- Add _CACHE_ECONOMICS dict and _build_prefix_cache_stats() helper
- Track cache_by_provider with per-model cold start awareness
- Add _merge_cost_stats() to combine compression + cache savings
- Dashboard: "Prefix Cache Impact" section with provider breakdown
- Dashboard: hero "Total Savings" shows compress + cache breakdown
- Fix ruff (unused var, quoted annotations) and mypy type errors
- Refactor code_compressor to data-driven language config

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 14:14:15 -07:00
Tejas Chopra
08d81f2e2c fix: dashboard metrics, TTFB tracking, eager LLMLingua loading, and multi-provider consistency
Dashboard was showing wildly incorrect metrics (99.5% savings, 3ms overhead)
due to using Anthropic API's non-cached input_tokens instead of optimized_tokens,
and dividing overhead by total request count instead of optimized-only count.

Key fixes:
- Use optimized_tokens (what we sent) for dashboard aggregation, not API's
  input_tokens which excludes cached portion
- Track overhead_count separately from latency_count for correct averages
- Add TTFB (time to first byte) measurement, replace full stream latency in UI
- Eager-load LLMLingua model at proxy startup (eliminates 5.9s first-request delay)
- Simplify CostTracker to token-based accounting with counterfactual cost display
- Add two-tier compression cache to ContentRouter (skip set + result cache)
- Fix compression pinning to detect both CCR and ReadLifecycle markers
- Clamp tokens_saved to max(0, ...) across all provider paths
- Add per-transform timing instrumentation to pipeline
- Guard against over-aggressive code compression (<5% ratio)
- Fix ReadLifecycle partial read supersede logic (_read_covers range check)
- Disable CacheAligner and compress_superseded by default
- Fix all pre-existing mypy errors (CompressionCache return types)
- Fix test mocks to accept **kwargs for cache token parameters
2026-03-07 23:33:45 -08:00
Tejas Chopra
68a75aa28c docs: add headroom learn demo GIF to README
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 17:56:17 -08:00
Tejas Chopra
76e2cb1928 Fixing the build AND the perf logs 2026-03-07 15:28:02 -08:00
Tejas Chopra
7fd1f6f5f1 style: ruff format parser.py, content_router.py, smart_crusher.py
Pre-existing formatting issues caught by CI.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 15:24:14 -08:00
Tejas Chopra
da481a359b fix(learn): pass explicit model in tests to avoid API key requirement
SessionAnalyzer() without a model calls _detect_default_model() which
raises when no API keys are set (e.g., in CI). Pass model="test-model"
in the three tests that mock _call_llm.
2026-03-07 15:10:25 -08:00
Tejas Chopra
4d14012c2f feat: add headroom perf CLI and rewrite headroom learn to use LLM analysis
Proxy performance logging (`headroom perf`):
- Add always-on RotatingFileHandler to ~/.headroom/logs/proxy.log (10MB x 5 backups)
- Replace scattered log lines with structured PERF lines containing model, msgs,
  tok_before/after/saved, cache_read/write/hit_pct, opt_ms, and transforms
- Emit PERF lines from all three response paths (streaming Anthropic, non-streaming
  Anthropic, Bedrock streaming)
- Add `headroom perf` CLI that parses proxy logs and reports token savings, cache
  hit rates, prefix stability, transform effectiveness, routing breakdown, TOIN
  status, and actionable recommendations
- Support --hours and --raw flags for time filtering and raw record output

Learn module rewrite (LLM-based analysis):
- Replace all regex/heuristic analyzers with a single LLM call via LiteLLM
- New SessionAnalyzer builds compact digests and sends to any of 100+ models
- Auto-detect best model from API keys (Anthropic → OpenAI → Gemini)
- Add --model flag for explicit model selection
- Enrich scanner with SessionEvent (user messages, interruptions, subagent summaries),
  token usage tracking, and timestamps
- Simplify models: remove EnvironmentFact, StructureNote, Correction, CommandPattern,
  RetryPattern, AnalysisReport; add SessionEvent, AnalysisResult
- Simplify writer: remove Recommender class (LLM now produces recommendations directly)
- Update tests for new analyzer and models
2026-03-07 14:15:49 -08:00
Tejas Chopra
3945c02aa5 fix: harden edge cases, expand tool exclusions, and fix mypy errors
- Fix division-by-zero in OpenAI cache, BM25 scorer, BLEU metrics, and smart_crusher
- Add null safety for SQLite memory store JSON fields
- Add thread safety lock for CCR retrieval counter
- Add timeout/error handling for CCR stream collection
- Safer error logging and JSON serialization fallback in proxy server
- Return explicit zero stats on compression failure instead of None defaults
- Guard against missing "messages" key in ASGI and LiteLLM integrations
- Add aclose() for proper httpx client cleanup in ASGI middleware
- Expand DEFAULT_EXCLUDE_TOOLS to include Grep, Write, Edit
- Revert protect_recent_reads_fraction to 0.0 (protect all excluded-tool outputs)
- Fix whitespace waste detection to use tokenizer for both original and normalized
- Fix top-waste-requests sorting by tokens_saved instead of tokens_before
- Fix TOCTOU race in semantic cache _touch() method
- Fix mypy errors: type annotations for ASGI receive/send and proxy error logging
2026-03-06 22:30:30 -08:00
Tejas Chopra
448acb7b44
Merge pull request #40 from smartwatermelon/claude/fix-mcp-startup-and-install-20260306
fix(mcp): use claude mcp add for install/uninstall, fix startup import
2026-03-06 13:45:35 -08:00
Claude Code Bot
fcafa373e7 fix(mcp): fix uninstall symmetry, move subprocess import, add cli-path tests
Address code review feedback on the initial MCP fix:

- mcp_uninstall: now also calls `claude mcp remove -s user` when the claude
  CLI is available, mirroring mcp_install. Removes from mcp.json fallback
  config as well if present. This fixes the broken uninstall->reinstall
  roundtrip on machines using Claude Code CLI >=2.x.

- cli/mcp.py: move `import subprocess` to module level (was deferred inside
  mcp_install function body, inconsistent with other stdlib imports and
  harder to mock).

- tests: add TestMCPInstallWithClaudeCLI and TestMCPUninstallWithClaudeCLI
  covering the previously-untested `claude mcp add` code path, including
  force-overwrite ordering, -e flag for env vars, and fallback on failure.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 13:02:35 -08:00
Claude Code Bot
c078faa353 fix(mcp): use claude mcp add for install and fix startup import
Two fixes to get the headroom MCP server working with Claude Code CLI:

1. mcp_server.py: define CCR_TOOL_NAME inline instead of importing from
   tool_injection, which triggered headroom/__init__.py -> LiteLLM -> HTTP
   requests to GitHub, adding 4-5 seconds to startup time.

2. cli/mcp.py: prefer `claude mcp add -s user` when the claude CLI is
   available (Claude Code CLI ≥2.x stores servers in ~/.claude/.claude.json,
   not ~/.claude/mcp.json). Falls back to writing mcp.json for older versions
   and the claude.ai desktop app.

3. tests/test_cli/test_mcp.py: update mock_claude_config_path fixture to
   also stub out the claude CLI so install tests exercise the mcp.json
   fallback path, matching the fixture's intent.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 12:46:36 -08:00
Tejas Chopra
13c6c88b13 Revert "docs: update README demo GIF to headroom_recording.gif"
This reverts commit 1b350b4191.
2026-03-06 00:34:19 -08:00
Tejas Chopra
1b350b4191 docs: update README demo GIF to headroom_recording.gif 2026-03-06 00:32:16 -08:00
Tejas Chopra
655df095fd feat(router): adaptive compression with Read lifecycle and context-pressure scaling
Enable ReadLifecycle by default so stale/superseded Read outputs are
automatically replaced with compact CCR markers — these are provably safe
to compress (file was edited or re-read).

Replace static compression thresholds with adaptive parameters that scale
with conversation length and context pressure:

- protect_recent_reads_fraction: protects the most-recent 50% of messages
  from Read exclusion. Old Reads beyond this window become compressible,
  preventing the "28 excluded Read/Glob, 0 tokens saved" problem.

- min_ratio_relaxed / min_ratio_aggressive: compression acceptance
  threshold interpolates linearly with context pressure (tokens / model
  limit). Low pressure → 0.85 (picky), high pressure → 0.65 (accept
  anything helpful). Eliminates the fixed 0.9 gate that was rejecting
  20+ messages per request.

Also adds --no-read-lifecycle CLI flag, and fixes a missing
pytest.importorskip guard for sentence-transformers in memory tests.
2026-03-06 00:29:53 -08:00
chopratejas
9c31b22bff feat(code): add semantic symbol importance to CodeAwareCompressor
CodeAwareCompressor now analyzes intra-file symbol relationships before
compression, using tree-sitter AST walks to count references, map call
graphs, and detect public/private visibility. This replaces uniform
"keep first N body lines" compression with budget-based allocation driven
by the existing target_compression_rate config.

Key design decisions:
- Distribution-based scoring (min-max normalized within each file) so it
  adapts to any file structure: utility libs, test files, orchestrators
- Budget allocation: target_compression_rate determines total body line
  budget, distributed proportionally to importance × body size
- max_body_lines respected as a hard cap over budget allocation
- Context-aware: the existing `context` parameter now boosts symbols
  matching the user's task (word-boundary matching, not substring)
- Qualified names (ClassName.method) internally to avoid collisions
  between identically-named methods in different classes
- Omitted comments include call graph info from AST analysis
- Zero new dependencies — uses tree-sitter already in headroom[code]
- semantic_analysis=True by default, fully backward-compatible when False
2026-03-03 14:18:41 -08:00
Tejas Chopra
d90c47bcfb
Merge pull request #39 from longtngo/fix/dev-deps-sqlite-vec
fix(ci): add sqlite-vec to dev deps to fix memory tests on CI
2026-03-02 13:31:28 -08:00
Long Ngo
1df0b14ea0 fix(ci): add sqlite-vec to dev deps to fix memory tests on CI
The AUTO vector backend prefers sqlite-vec over hnswlib. On GitHub
Actions runners, hnswlib's subprocess AVX probe fails (runner CPUs
lack AVX support), leaving no available vector backend and causing
test_memory_bridge.py to error with:

  ValueError: hnswlib is not available. Install with: pip install hnswlib

sqlite-vec is a pure SQLite extension with pre-built wheels that works
on all CI runners without requiring AVX. Adding it to [dev] lets the
AUTO backend select it instead of falling through to the failing HNSW path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 15:25:50 -06:00
Tejas Chopra
62daa897d1
Merge pull request #38 from longtngo/fix/docker-example-build-deps
fix(docs): fix Docker example and document hnswlib C++ build requirement
2026-03-02 12:47:32 -08:00
Long Ngo
693deb4d58 fix(docs): fix Docker example and document hnswlib C++ build requirement
The Docker example in proxy.md used the wrong package name and lacked
build-essential, causing install failures on slim images. hnswlib (a
core dependency) requires a C++ compiler to build from source.

- Fix proxy.md Docker example: headroom[proxy] -> headroom-ai[proxy],
  add build-essential install/cleanup pattern
- Add troubleshooting entry for C++ compilation errors with solutions
  for Linux and macOS environments

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 14:46:14 -06:00
Tejas Chopra
ae661c8a2e
Merge pull request #37 from longtngo/fix/docker-install-hnswlib-core-dep
fix(docs): correct PyPI package name from headroom to headroom-ai
2026-03-02 12:39:07 -08:00
Long Ngo
460250c80e revert: restore hnswlib to core dependencies
hnswlib may be used by core features at runtime even without the
[memory] extra explicitly installed. Safer to leave it in core deps
and document the C++ build requirement instead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 10:13:15 -06:00
Long Ngo
180b4ef05a fix: remove hnswlib from core deps and fix package name in docs
hnswlib requires C++ compilation and is only used by the memory
subsystem - it belongs in the [memory] extra, not core dependencies.
Installing headroom-ai on slim Docker images or any environment
without build tools would fail at the hnswlib build step.

Also fixes docs/quickstart.md and docs/troubleshooting.md which
referenced the wrong PyPI package name `headroom` (an unrelated
package) instead of `headroom-ai`.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 10:11:16 -06:00
chopratejas
7cf086c2e8 Add multi-agent support, quality gates, and integration tests for headroom learn
- Codex adapter: CodexScanner reads ~/.codex/sessions/*.json, CodexWriter
  writes to AGENTS.md + instructions.md. Tested on 328 real sessions.
- Gemini writer: GeminiWriter writes to GEMINI.md (scanner deferred,
  sessions stored in protobuf).
- CLI --agent flag: auto-detect available agents or specify claude/codex/gemini.
- Quality gates: min_evidence, min_confidence, min_total_evidence thresholds
  prevent weak signals from writing noise to project files.
- Integration tests against real Claude Code and Codex session data on disk.
  Tests skip gracefully if data directories don't exist.
- Bash path extraction for Codex (reads files via sed/cat, not Read tool).
- Idempotency, false positive filtering, and skip-write-on-empty tests.
2026-02-28 23:29:02 -08:00
chopratejas
17442c2dcc Add headroom learn: offline failure learning for coding agents
Analyzes past conversation history to find tool call failure patterns,
correlates each failure with what eventually succeeded, and writes
specific project-level learnings to CLAUDE.md and MEMORY.md.

Key design:
- Success correlation: extracts the diff between failed and successful
  inputs as the learning (not generic advice)
- Generic architecture: tool-agnostic ToolCall model with pluggable
  Scanner/Writer adapters (Claude Code first, extensible to Cursor/Codex)
- 5 analyzers: Environment, Structure, Commands, Retries, Cross-Session
- Dry-run by default, --apply to write, --all for all projects

Also fixes mypy errors in litellm_callback, asgi, langchain chat_model,
and anthropic provider (AsyncClient typing, ToolCall arg-type, int cast).
2026-02-27 21:19:03 -08:00
chopratejas
40369762dd Add Cloud mode to ASGI middleware and LiteLLM callback
Both CompressionMiddleware and HeadroomCallback now support a cloud mode
(api_key="hdr_xxx") that calls Headroom Cloud API for managed compression
with org-scoped CCR, TOIN learning, and analytics. Falls back to
HEADROOM_API_KEY env var. Local mode (default) is unchanged.

Also adds x-headroom-tokens-before/after response headers and updates
uv.lock with mcp extra and version bump to 0.3.3.
2026-02-27 20:10:07 -08:00
chopratejas
876949e638 Fix LangChain tool_call argument handling for varied message formats
LangChain provides tool_call args in different shapes (dict args, str
arguments, nested function.arguments) depending on the source. Add
_tool_call_args_to_json() helper to normalize all formats to JSON strings.
Use .get() instead of [] to handle missing keys gracefully.
2026-02-27 20:09:18 -08:00
chopratejas
bc2d4bd6b6 Add Read Lifecycle: event-driven stale/superseded Read detection
Detects Read tool outputs that became stale (file was later edited) or
superseded (file was later re-Read) and replaces them with compact markers
+ CCR hashes. Fresh Reads are never touched.

Adds ReadLifecycleConfig to config.py and integrates ReadLifecycleManager
as a pre-processing pass in ContentRouter. Opt-in via config flag to
preserve backward-compatible behavior.
2026-02-27 20:09:09 -08:00
chopratejas
df1f53efe7 Add Memory Bridge: bidirectional sync between markdown files and Headroom memory
Foundational models (Claude Code, ChatGPT) store memory in flat .md files while
Headroom uses a semantic vector store. This bridge connects the two worlds —
importing .md files into Headroom for semantic search, exporting Headroom memories
back to .md, and keeping them in sync with hash-based change detection.
2026-02-23 22:45:38 -08:00
chopratejas
30a5aba9d6 Fixing the ruff linting 2026-02-23 19:24:19 -08:00
chopratejas
a2b2ec5463 Add OSS evaluation suite, universal JSON crush, latency benchmarks
Evaluation Suite:
- Tiered eval framework (Tier 1 ~$3/15min, Tier 2/3 for extended coverage)
- 16 benchmarks across 3 tiers: GSM8K, TruthfulQA, MMLU, ARC, HumanEval,
  SQuAD v2, BFCL, Tool Outputs, CCR needle retention, HotpotQA, and more
- Before/After runner with full proxy support (compression + CCR retrieval)
- LLM-as-judge for ground-truth comparison (BFCL function calling)
- Zero-cost compression-only runner (CCR needle retention, info retention)
- Cost tracker with per-model pricing and budget enforcement
- Report card generator (Markdown, JSON, HTML)
- Suite CLI: python -m headroom.evals suite --tier 1
- Fix BFCL dataset loader for current HuggingFace schema
- CI workflow: PR smoke test + weekly full Tier 1

Results: SQuAD 97%, BFCL 97%, Tool Outputs 100%, CCR 100%

SmartCrusher:
- Universal JSON crush for heterogeneous arrays
- Fix mypy redefinition warning in _crush_string_array

Other:
- Latency benchmark suite with docs
- Known limitations doc
- Prompt comparison evaluator
- Config updates for new features
2026-02-23 19:08:54 -08:00
Tejas Chopra
30fffc9216
Merge pull request #33 from angpt/angpt/any-llm-integration
angpt/any llm integration
2026-02-23 10:59:33 -08:00
angpt
b66b13ec86 Update CHANGELOG.md 2026-02-23 09:35:41 -06:00
chopratejas
42e48bbc2a Bump version to 0.3.7 2026-02-19 11:10:06 -08:00
chopratejas
0adc39ab7a Fix CI: guard starlette imports, asyncio.run(), deprecate datetime.utcnow()
- Guard starlette imports in test_compress_api.py (skip ASGI tests without proxy deps)
- Replace asyncio.get_event_loop().run_until_complete() with asyncio.run() (Python 3.13)
- Replace datetime.utcnow() with datetime.now(timezone.utc).replace(tzinfo=None) everywhere
2026-02-19 11:03:24 -08:00
chopratejas
0a434531d8 Fix: guard starlette imports in test_compress_api.py for CI without proxy deps 2026-02-19 10:48:39 -08:00
chopratejas
a80ed157a2 README: replace plain text architecture with Mermaid diagrams 2026-02-19 10:26:09 -08:00
chopratejas
99caff5702 README: add back proof points — needle-in-haystack demo, benchmarks, architecture detail 2026-02-19 10:23:33 -08:00
chopratejas
f699375f8f README: proxy as the hero quickstart, compress() for Python, integration table for existing proxies 2026-02-19 10:21:18 -08:00
chopratejas
3ebcd89d46 Rewrite README + add Integration Guide
README: 694 → 203 lines. Crisp, scannable, links to docs.
- compress() as the hero quickstart (not proxy)
- Integration table: compress(), LiteLLM, ASGI, proxy, Agno, LangChain
- LangChain marked as experimental
- "Already have a proxy?" callout linking to Integration Guide
- Architecture: ContentRouter (not SmartCrusher) as the primary compressor

New: docs/integration-guide.md
- Detailed setup for every integration path
- compress() with Anthropic, OpenAI, LiteLLM, raw HTTP
- LiteLLM callback + LiteLLM proxy ASGI middleware
- ASGI middleware for any FastAPI/Starlette app
- Compression hooks for advanced customization
- FAQ section

Fix: compress() uses default pipeline (CacheAligner + ContentRouter +
IntelligentContext) instead of manually specifying SmartCrusher.
2026-02-19 10:17:33 -08:00
chopratejas
dde2f9f848 Add one-function compress() API, ASGI middleware, LiteLLM callback
Three new integration paths — no proxy needed:

1. headroom.compress(messages, model) → CompressResult
   One function, auto-detects tokenizer per model, works with any client.

2. headroom.integrations.asgi.CompressionMiddleware
   Drop-in ASGI middleware for LiteLLM proxy, FastAPI, or any ASGI app.

3. headroom.integrations.litellm_callback.HeadroomCallback
   LiteLLM callback: litellm.callbacks = [HeadroomCallback()]

Fix: TransformPipeline._get_tokenizer() no longer requires a Provider.
Falls back to tokenizer registry which auto-detects per model:
- OpenAI → tiktoken (exact)
- Anthropic → calibrated estimation (3.5 chars/token)
- Open models → HuggingFace (if installed)

15 tests covering compress(), ASGI middleware, LiteLLM callback.
2026-02-19 10:00:31 -08:00
chopratejas
7c2c55abc0 Add Compression Hooks — extension points for SaaS and advanced customization
Three hooks at well-defined pipeline stages:

1. pre_compress(messages, ctx) → messages
   Modify messages before compression: cross-turn dedup, memory injection.

2. compute_biases(messages, ctx) → dict[int, float]
   Per-message compression bias: position-aware, phase-aware, learned.

3. post_compress(event) → None
   Observe results: failure-driven learning, analytics, A/B testing.

- headroom/hooks.py: CompressionHooks, CompressContext, CompressEvent
- ProxyConfig.hooks: optional, default None (zero overhead)
- Wired into Anthropic and OpenAI handlers
- ContentRouter reads hook biases, multiplies with tool bias
- 11 tests
2026-02-19 08:17:30 -08:00
angpt
8fb1456211 Update anyllm.py
Removing double for loop
2026-02-19 09:17:05 -06:00
chopratejas
78d2847398 Bump version to 0.3.6 2026-02-18 23:41:56 -08:00
chopratejas
d4d8dd0c26 Add Query Echo: re-inject user question after compressed tool outputs
Query Echo addresses attention decay in compressed contexts. After
SmartCrusher compresses tool outputs, the user's question may be
thousands of tokens away. Echo appends a brief reminder after the
last compressed block.

- New: headroom/transforms/query_echo.py
- Compression-ratio-proportional: only triggers when >30% compressed
- Cache-safe: appended at end (after KV cache boundary)
- Provider-agnostic: Anthropic, OpenAI, Gemini
- 18 tests (15 unit + 3 integration with real API)
- Fix _crush_array 4-tuple unpack in test_critical_fixes.py
2026-02-18 23:39:26 -08:00
chopratejas
729cc035a4 Add compression summaries, multi-provider headers, Dockerfile fix
Compression Summaries:
- New: headroom/transforms/compression_summary.py
  - summarize_dropped_items(): categorizes compressed JSON items by
    field values (status, type, level, etc.), highlights errors/failures
  - summarize_compressed_code(): extracts function names from AST
    signatures (language-agnostic: Python, JS, Go, Rust, Java)
  - Newline-safe: strips \n from field values to keep markers single-line
- SmartCrusher: CCR markers include categorical summary of dropped items
  e.g. "[500 items compressed to 20. Omitted: 87 passed, 2 failed.
  Retrieve more: hash=abc123. Expires in 5m.]"
- CodeCompressor: CCR markers list compressed function names from AST
  e.g. "[180 tokens compressed. 5 bodies compressed: authenticate().
  Retrieve more: hash=abc123. Expires in 5m.]"
- Markers include TTL so LLM knows retrieval window
- Summary escapes { } to prevent .format() crashes
- Uses index-based dropped detection (not id()) for .copy() correctness

Proxy Response Headers:
- Anthropic, OpenAI, and Gemini handlers inject x-headroom-tokens-*
  headers for SaaS metering

Multi-Provider Passthrough Routing:
- Detect x-goog-api-key (Gemini) and api-key (Azure OpenAI)
- X-Headroom-Base-URL for explicit upstream URL override

Dockerfile: add build-essential + g++ for hnswlib compilation
Bump version to 0.3.5

Tests: 27 new tests (unit, eval, integration with real API, tool invocation)
2026-02-18 16:54:20 -08:00
chopratejas
55d8fb6361 Fixing the DockerFile to have hnswlib working 2026-02-17 07:06:53 -08:00