Commit graph

79 commits

Author SHA1 Message Date
Tejas Chopra
029ca7d7e8 Add demo GIF to README 2026-01-20 18:57:17 -08:00
Tejas Chopra
4e944db1d2 Bump version to 0.2.15 2026-01-20 18:00:30 -08:00
Tejas Chopra
5ef1d4a931 Fix streaming responses not tracking costs
The streaming code path in _stream_response was missing cost calculation
and recording. While non-streaming requests properly calculated costs via
CostTracker.estimate_cost() and passed them to metrics.record_request(),
streaming requests always passed the default value of 0.

This caused session summaries to show $0.00 for total cost and savings
even when using expensive models like Claude Opus.

Added cost calculation logic to the streaming finally block, matching
the non-streaming implementation.
2026-01-20 17:34:14 -08:00
chopratejas
cd5ea2ea1d Add architecture diagrams to README and docs 2026-01-20 00:44:55 -08:00
chopratejas
ec56092555 Add PyPI downloads badge to README 2026-01-19 23:51:31 -08:00
chopratejas
2ce26438a0 Integrate DynamicContentDetector into CacheAligner (Phase 1)
- Add DynamicContentDetector integration for comprehensive dynamic content
  detection (20+ patterns vs previous 4 date patterns)
- New detection: UUIDs, API keys, JWT tokens, Unix timestamps, request/trace
  IDs, hex hashes (MD5/SHA1/SHA256), version numbers, high-entropy strings
- Add CacheAlignerConfig options: use_dynamic_detector, detection_tiers,
  extra_dynamic_labels, entropy_threshold
- Maintain backward compatibility with legacy date-only mode
- Add 25 new comprehensive tests for Phase 1 functionality
- Fix code compressor fallback test to properly mock LLMLingua availability

Expected cache hit improvement: 30-50% by extracting more dynamic content
2026-01-19 22:56:20 -08:00
Tejas Chopra
6ec85f3cbd Fix cost tracking to use LiteLLM pricing database correctly
- Remove hardcoded fallback pricing dictionary
- Fix litellm API usage: use cost_per_token() instead of broken
completion_cost() call (API changed, old kwargs no longer work)
- Add proper logging when pricing lookup fails
- Handle cached tokens at 10% of input price

The previous code silently failed because litellm.completion_cost()
no longer accepts prompt_tokens/completion_tokens kwargs, causing
all cost calculations to return $0.00.
2026-01-19 22:47:52 -08:00
chopratejas
dc72670bce Add demo video link to README 2026-01-19 22:28:12 -08:00
chopratejas
bd2d447c26 Add quality retention eval and fix linting for Python 3.12
- Add quality_retention_eval.py for needle-in-haystack testing to verify
  intelligent compression retains critical information (100% retention achieved)
- Add intelligent_context_integration_test.py for comprehensive pipeline testing
- Add test_progressive_summarizer.py with 36 tests for ProgressiveSummarizer
- Add HeadroomConfig parameter to HeadroomClient for direct config injection
- Update pipeline.py with IntelligentContextManager wiring and logging
- Fix all ruff linting issues and format for Python 3.12 compatibility
- Add comprehensive_eval.py benchmark for multi-scenario evaluation
- Add real_data_demo.py for production-scale volume testing
- Add reasoning agent test examples (groq, debug)
2026-01-19 21:52:18 -08:00
chopratejas
d48f479882 Bump version to 0.2.14 2026-01-19 20:37:17 -08:00
Tejas Chopra
f5ffba61a7 Merge pull request #8 from nicolabeghin/proxy-custom-openai-api-url
Add OpenAI API URL override option
2026-01-19 17:58:11 -08:00
Tejas Chopra
9dceb8a895 Merge pull request #9 from nicolabeghin/docker-support
Add Docker configuration for containerized deployment
2026-01-19 17:53:17 -08:00
Tejas Chopra
18e01a0480 Merge pull request #6 from smartwatermelon/claude/docs-macos-deployment-20260119
Add macOS LaunchAgent deployment guide and templates
2026-01-19 17:52:25 -08:00
Nicola Beghin
1b023e3146 feat: add Docker configuration for containerized deployment
- Add .dockerignore to exclude unnecessary files from Docker builds
- Add Dockerfile to containerize Python application with health checks
- Add docker-compose.yml for easy local development and deployment of headroom proxy service
2026-01-20 00:17:05 +01:00
Nicola Beghin
f59690a7a7 docs update 2026-01-19 23:35:16 +01:00
Nicola Beghin
7ecf94c881 feat(config): add OpenAI API URL override option
Add support for a custom OpenAI API URL via new configuration field, CLI argument, and environment variable. This allows overriding the default OpenAI API endpoint in the proxy, for users needing to target specific API instances or custom endpoints. Includes null safety and conditional application in the proxy initialization.
2026-01-19 23:34:57 +01:00
Claude Code Bot
063b6e85f4 fix(deployment): correct port placeholder in LaunchAgent plist template
The plist template was using ${HEADROOM_PROXY_PORT} in ProgramArguments,
but LaunchAgent doesn't expand environment variables in that context.
Changed to use __PORT__ placeholder which install.sh replaces via sed.

This fixes the "invalid int value" error when starting the proxy service.

AI review: Clean (via pre-commit hook)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-19 13:44:30 -08:00
Claude Code Bot
3ac26207b8 docs(deployment): add macOS LaunchAgent deployment guide and templates
Add comprehensive macOS deployment support for running headroom proxy as a
persistent background service using LaunchAgent. This enables automatic startup,
crash recovery, and proper lifecycle management for local development environments.

Files added:
- examples/deployment/macos-launchagent/com.headroom.proxy.plist.template
- examples/deployment/macos-launchagent/install.sh (shellcheck-clean)
- examples/deployment/macos-launchagent/uninstall.sh (shellcheck-clean)
- examples/deployment/macos-launchagent/shell-integration.sh (bash + zsh)
- examples/deployment/macos-launchagent/README.md
- docs/macos-deployment.md

Key features:
- Configurable port via HEADROOM_PROXY_PORT environment variable (default: 8787)
- Automated installation and uninstallation scripts
- Shell integration supporting both bash and zsh
- Comprehensive documentation with troubleshooting guide
- All shell scripts are shellcheck-clean (zero errors, warnings, or info messages)

Files modified:
- .gitignore: Added CLAUDE.md to prevent committing local config
- docs/README.md: Added Deployment & Operations section with navigation entry

AI review: Pending (will be run by pre-commit hook)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-19 13:34:52 -08:00
chopratejas
4102402c5e Add Phase 2 Progressive Summarization and fix Agno integration tests
Phase 2 - Progressive Summarization:
- Add ProgressiveSummarizer with callback pattern for external summarization
- Add AnchoredSummary for tracking which message positions were summarized
- Add SummarizationResult for tracking summarization operations
- Add extractive_summarizer fallback when no LLM callback provided
- Integrate CCR for storing originals and enabling retrieval
- Add SUMMARIZE strategy to IntelligentContextManager
- Add comprehensive tests (59 total for intelligent context)

Agno Integration Fix:
- Add _ensure_message_objects() to convert dicts to Agno Message objects
- Fix response(), response_stream(), aresponse(), aresponse_stream() to
  ensure messages are Message objects before calling super()
- Update test mocks to use proper ModelResponse and Metrics objects
- All 66 Agno tests now pass
2026-01-19 09:49:04 -08:00
chopratejas
39a55b4810 Fix HeadroomAgnoModel to optimize tool outputs at invoke level
Previously, HeadroomAgnoModel called wrapped_model.response() which ran the
tool execution loop internally. This meant tool outputs (often 60k+ chars)
were never optimized - only the initial messages were compressed.

The fix delegates response() to the inherited Model.response(), which calls
self.invoke() for each API call. Our invoke() override optimizes messages
before delegating to wrapped_model.invoke(), ensuring tool outputs are
compressed on every API request.

Results from multi_tool_agent_test.py with Claude Sonnet:
- Tokens before optimization: 25,713
- Tokens after optimization: 6,100
- Tokens saved: 19,613 (76.3%)
- Both baseline and optimized found all critical information

Also adds:
- multi_tool_agent_test.py: Real function calling test with 4 tools
- multi_tool_compression_test.py: Direct compression test
- README update with multi-tool agent test results
2026-01-19 09:16:01 -08:00
chopratejas
8766d83f68 Rewrite README with verified before/after examples
- Replace marketing claims with actual API test results
- Add needle-in-haystack test: critical error at position 67/100
- Show real JSON compression: 100 entries → 6 entries (93.9% reduction)
- Verified with Claude Sonnet: 87.6% fewer tokens, 4/4 correct answers
- Add example scripts for reproducing the tests
2026-01-19 08:19:37 -08:00
chopratejas
57b2de525c Implement COMPRESS_FIRST strategy for IntelligentContextManager
When context is <10% over budget, try deeper compression of tool messages
before dropping. Uses ContentRouter integration for intelligent routing to
SmartCrusher, CodeAwareCompressor, SearchCompressor, or LogCompressor.

- Add _get_content_router() with lazy loading and aggressive config
- Add _apply_compress_first() to compress tool messages via ContentRouter
- Add _get_tool_source_hint() to extract hints from tool calls
- Add _compress_content_blocks() for Anthropic-style content blocks
- Falls back to DROP_BY_SCORE if compression isn't enough

Adds 14 comprehensive integration tests (no mocks):
- TestCompressFirstStrategy: core functionality (8 tests)
- TestCompressFirstWithContentBlocks: Anthropic format
- TestCompressFirstIntegrationWithTOIN: TOIN integration
- TestCompressFirstEdgeCases: edge cases (4 tests)
2026-01-18 22:55:32 -08:00
chopratejas
14ecab6bfa Add IntelligentContextManager for semantic-aware context management
- Add multi-factor importance scoring (recency, semantic similarity,
  TOIN importance, error indicators, forward references, token density)
- No hardcoded patterns - all signals learned from TOIN or computed
- Add ScoringWeights and IntelligentContextConfig dataclasses
- Add MessageScorer for scoring individual messages
- Add strategy selection: NONE, COMPRESS_FIRST, DROP_BY_SCORE
- Preserve tool call/response atomicity when dropping
- Add comprehensive tests (62 tests total)
- Update documentation (transforms, configuration, api, architecture)
2026-01-18 22:22:48 -08:00
chopratejas
0acc7fb477 Bump version to 0.2.13 2026-01-18 21:46:10 -08:00
chopratejas
f858451ba6 Fix agno model.py mypy errors by declaring name and provider fields 2026-01-18 21:40:48 -08:00
chopratejas
8c0da95f58 Fix test_on_llm_error to pass required run_id argument 2026-01-18 21:35:43 -08:00
chopratejas
31c4f196f3 Fix mypy type errors for Python 3.12 compatibility
- Fix LangChain chat_model.py type errors:
  - Add type annotations for list[BaseMessage] conversions
  - Fix _stream/_astream return types to use ChatGenerationChunk
  - Fix on_llm_error signature to match supertype
  - Add type: ignore comments for fallback assignments

- Fix LangChain memory.py override errors:
  - Fix messages property override
  - Fix add_user_message/add_ai_message signatures

- Fix tree-sitter get_parser type errors in code_handler.py
  and code_compressor.py
2026-01-18 21:24:45 -08:00
chopratejas
67c927f857 Fix HeadroomAgnoModel to extend agno.models.base.Model and add real integration tests
- Fix HeadroomAgnoModel to properly extend agno.models.base.Model as a dataclass
- Implement required abstract methods (invoke, ainvoke, invoke_stream, ainvoke_stream)
- Add type: ignore comments for method signature overrides
- Fix mypy errors in telemetry/models.py and telemetry/toin.py
- Add real Ollama integration tests for both Agno and LangChain (no API keys needed)
- Add ollama and langchain-ollama to dev dependencies for local testing
- Update existing tests to use new HeadroomAgnoModel API
2026-01-18 21:13:20 -08:00
chopratejas
77248cd1a3 Enhance /stats endpoint and add comprehensive benchmarks
- Add detailed breakdowns by provider and model to /stats
- Include compression, telemetry, and feedback loop statistics
- Add latency.average_ms metric
- Add real-world agent benchmark with MCP tool patterns
- Add worst-case and adversarial benchmarks for edge cases
- Bump version to 0.2.12
2026-01-17 22:49:04 -08:00
chopratejas
313fe0158a Fix ruff formatting 2026-01-17 17:14:12 -08:00
chopratejas
dd832fee0c Add TOIN field-level learning and comprehensive integration tests
Features:
- Add field-level learning to TOIN from retrieved items
- CompressionStore now passes retrieved_items to TOIN for learning
- Add FieldSemantics class for tracking field usage patterns

Test improvements:
- Add TestCacheOptimizerInvocation to verify optimizer is actually invoked
- Add TestSemanticCacheIntegration to verify cache hit returns without API call
- Add TestSessionStatsTracking to verify session stats are tracked
- Add TestEndToEndTOINIntegration for full CCR cycle with TOIN
- Add critical field_semantics assertions to catch feedback loop bugs

Fixes:
- Remove unused imports and variables (ruff linting)

Bump version to 0.2.11
2026-01-17 15:40:08 -08:00
chopratejas
ceb43cb932 Bump version to 0.2.10
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 16:42:22 -08:00
chopratejas
7a34030b0d Fix mypy type errors in LiteLLM and OpenAI providers
- Add type: ignore[assignment] comments for optional litellm imports
- Add None checks before accessing optional module functions
- Handle nullable max_input_tokens and max_output_tokens values

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 16:42:11 -08:00
chopratejas
37c30d4790 Bump version to 0.2.9
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 16:33:56 -08:00
chopratejas
0b945cf862 Add feature coverage and known limitations to Agno docs
Documents what the integration optimizes (messages, tool calls, streaming)
and what operates outside the optimization boundary (agent memory, knowledge
bases, agent teams). Includes best practices and future improvement plans.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 16:25:31 -08:00
chopratejas
aaaca9fa6a Add Agno integration documentation
- Update README.md with Agno quickstart and framework integration
- Create comprehensive docs/agno.md guide covering:
  - Model wrapping with HeadroomAgnoModel
  - Observability hooks (HeadroomPreHook, HeadroomPostHook)
  - Multi-provider auto-detection
  - Real-world examples and configuration reference
- Update docs/README.md index with Agno link
2026-01-16 16:17:14 -08:00
chopratejas
1f806cef4c Add Agno integration tests to CI workflow 2026-01-16 16:11:02 -08:00
chopratejas
f1e7b628c4 Add Agno agent framework integration
- HeadroomAgnoModel: Drop-in wrapper for any Agno model with automatic
  context optimization
- HeadroomPreHook/HeadroomPostHook: Agent-level hooks for tracking
  optimization metrics across tool calls
- Provider detection for Agno models (OpenAI, Anthropic, Google, etc.)
- Full test coverage for model wrapper and hooks
2026-01-16 16:02:55 -08:00
chopratejas
09973b614d Use LiteLLM for model pricing instead of hardcoded values
- Add litellm as a core dependency for accessing its community-maintained
  model pricing database (2,425+ models across all major providers)
- Create headroom/pricing/litellm_pricing.py with simple wrapper functions
- Update ModelRegistry.estimate_cost() to fetch pricing from LiteLLM
- Remove hardcoded pricing fields from ModelInfo dataclass
- Update tests to reflect new pricing source
2026-01-16 00:35:04 -08:00
Tejas Chopra
319fb56530 Fix proxy passthrough routing to use SDK headers instead of User-Agent
The passthrough route was incorrectly routing requests based on
User-Agent string, which caused requests from Anthropic SDK to be
forwarded to OpenAI's API instead of Anthropic's API.

Now checks for anthropic-version header or x-api-key header to
reliably detect Anthropic SDK requests and route them correctly.
2026-01-15 23:49:45 -08:00
chopratejas
1a25d56cd0 Bump version to 0.2.8 2026-01-15 23:22:21 -08:00
chopratejas
dcbc220929 Fix mypy type annotation error in content_router.py 2026-01-15 23:22:09 -08:00
chopratejas
01472fefec Bump version to 0.2.7 2026-01-15 23:10:34 -08:00
chopratejas
ac3b21bfde Add CCR marker support to all compressors and fix retrieval
- Fix CCRToolInjector detection for LLMLingua (use standard marker format)
- Add CCR marker output to CodeAwareCompressor
- Add SmartCrusher.crush() method for ContentRouter integration
- Fix ContentRouter to pass CCRConfig to SmartCrusher
- Fix CCR response handler decompression error (remove encoding headers)
- Add content block processing for Anthropic tool_result format
2026-01-15 23:08:47 -08:00
chopratejas
02fd2284e0 Fix LLMLingua API: use context=[content] not original_prompt
The LLMLingua PromptCompressor.compress_prompt() expects context as a list,
not original_prompt as a string. Also use empty list [] for force_tokens
instead of None.
2026-01-15 21:33:39 -08:00
chopratejas
07dfa9d25c Fix 'list' object has no attribute 'strip' error
Handle multimodal messages (images) where content is a list instead of string.
Skip non-string content in LLMLingua and code-aware compression transforms.
2026-01-15 21:25:48 -08:00
chopratejas
e6370026bc Bump version to 0.2.6 2026-01-15 21:18:26 -08:00
chopratejas
d5ea931635 Enable LLMLingua and code-aware compression by default in proxy
- Add --no-llmlingua flag (compression ON by default, opt-out)
- Add --llmlingua-device and --llmlingua-rate flags
- Add --no-code-aware flag (AST compression ON by default, opt-out)
- Add code_aware_enabled config and _setup_code_aware() method
- Update banner to show Code-Aware compression status
- Better UX: zero-config proxy starts with all optimizations enabled
2026-01-15 21:17:10 -08:00
chopratejas
bcd96b3a94 Bump version to 0.2.5 2026-01-15 21:08:15 -08:00
chopratejas
2c225854bb Fix mypy type errors in compression module
- Fix compress_with_llmlingua call: use compression_rate parameter
- Fix CompressionStore.store() call: use positional args for original/compressed
- Fix extract_json_schema return type to support arrays
- Add proper type casts for Any returns
2026-01-15 16:41:43 -08:00