mirror of
https://github.com/headroomlabs-ai/headroom.git
synced 2026-08-27 14:17:10 -04:00
Bumps the pip-minor-patch group with 1 update in the / directory: [ruff](https://github.com/astral-sh/ruff). Updates `ruff` from 0.15.22 to 0.16.2 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/astral-sh/ruff/releases">ruff's releases</a>.</em></p> <blockquote> <h2>0.16.2</h2> <h2>Release Notes</h2> <p>Released on 2026-08-06.</p> <h3>Bug fixes</h3> <ul> <li>[<code>flake8-pyi</code>] Avoid false positives on <code>singledispatch</code> functions (<code>PYI041</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/27335">#27335</a>)</li> </ul> <h3>Server</h3> <ul> <li>Register formatting capabilities dynamically to exclude TOML files (<a href="https://redirect.github.com/astral-sh/ruff/pull/27332">#27332</a>)</li> </ul> <h3>Contributors</h3> <ul> <li><a href="https://github.com/MeGaGiGaGon"><code>@MeGaGiGaGon</code></a></li> <li><a href="https://github.com/charliermarsh"><code>@charliermarsh</code></a></li> <li><a href="https://github.com/epage"><code>@epage</code></a></li> <li><a href="https://github.com/sharkdp"><code>@sharkdp</code></a></li> <li><a href="https://github.com/ntBre"><code>@ntBre</code></a></li> </ul> <h2>Install ruff 0.16.2</h2> <h3>Install prebuilt binaries via shell script</h3> <pre lang="sh"><code>curl --proto '=https' --tlsv1.2 -LsSf https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-installer.sh | sh </code></pre> <h3>Install prebuilt binaries via powershell script</h3> <pre lang="sh"><code>powershell -ExecutionPolicy Bypass -c "irm https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-installer.ps1 | iex" </code></pre> <h2>Download ruff 0.16.2</h2> <table> <thead> <tr> <th>File</th> <th>Platform</th> <th>Checksum</th> </tr> </thead> <tbody> <tr> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-aarch64-apple-darwin.tar.gz">ruff-aarch64-apple-darwin.tar.gz</a></td> <td>Apple Silicon macOS</td> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-aarch64-apple-darwin.tar.gz.sha256">checksum</a></td> </tr> <tr> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-x86_64-apple-darwin.tar.gz">ruff-x86_64-apple-darwin.tar.gz</a></td> <td>Intel macOS</td> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-x86_64-apple-darwin.tar.gz.sha256">checksum</a></td> </tr> <tr> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-aarch64-pc-windows-msvc.zip">ruff-aarch64-pc-windows-msvc.zip</a></td> <td>ARM64 Windows</td> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-aarch64-pc-windows-msvc.zip.sha256">checksum</a></td> </tr> <tr> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-i686-pc-windows-msvc.zip">ruff-i686-pc-windows-msvc.zip</a></td> <td>x86 Windows</td> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-i686-pc-windows-msvc.zip.sha256">checksum</a></td> </tr> <tr> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-x86_64-pc-windows-msvc.zip">ruff-x86_64-pc-windows-msvc.zip</a></td> <td>x64 Windows</td> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-x86_64-pc-windows-msvc.zip.sha256">checksum</a></td> </tr> <tr> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-aarch64-unknown-linux-gnu.tar.gz">ruff-aarch64-unknown-linux-gnu.tar.gz</a></td> <td>ARM64 Linux</td> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-aarch64-unknown-linux-gnu.tar.gz.sha256">checksum</a></td> </tr> <tr> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-i686-unknown-linux-gnu.tar.gz">ruff-i686-unknown-linux-gnu.tar.gz</a></td> <td>x86 Linux</td> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-i686-unknown-linux-gnu.tar.gz.sha256">checksum</a></td> </tr> <tr> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-powerpc64-unknown-linux-gnu.tar.gz">ruff-powerpc64-unknown-linux-gnu.tar.gz</a></td> <td>PPC64 Linux</td> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-powerpc64-unknown-linux-gnu.tar.gz.sha256">checksum</a></td> </tr> <tr> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-powerpc64le-unknown-linux-gnu.tar.gz">ruff-powerpc64le-unknown-linux-gnu.tar.gz</a></td> <td>PPC64LE Linux</td> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-powerpc64le-unknown-linux-gnu.tar.gz.sha256">checksum</a></td> </tr> <tr> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-riscv64gc-unknown-linux-gnu.tar.gz">ruff-riscv64gc-unknown-linux-gnu.tar.gz</a></td> <td>RISCV Linux</td> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-riscv64gc-unknown-linux-gnu.tar.gz.sha256">checksum</a></td> </tr> <tr> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-s390x-unknown-linux-gnu.tar.gz">ruff-s390x-unknown-linux-gnu.tar.gz</a></td> <td>S390x Linux</td> <td><a href="https://releases.astral.sh/github/ruff/releases/download/0.16.2/ruff-s390x-unknown-linux-gnu.tar.gz.sha256">checksum</a></td> </tr> </tbody> </table> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md">ruff's changelog</a>.</em></p> <blockquote> <h2>0.16.2</h2> <p>Released on 2026-08-06.</p> <h3>Bug fixes</h3> <ul> <li>[<code>flake8-pyi</code>] Avoid false positives on <code>singledispatch</code> functions (<code>PYI041</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/27335">#27335</a>)</li> </ul> <h3>Server</h3> <ul> <li>Register formatting capabilities dynamically to exclude TOML files (<a href="https://redirect.github.com/astral-sh/ruff/pull/27332">#27332</a>)</li> </ul> <h3>Contributors</h3> <ul> <li><a href="https://github.com/MeGaGiGaGon"><code>@MeGaGiGaGon</code></a></li> <li><a href="https://github.com/charliermarsh"><code>@charliermarsh</code></a></li> <li><a href="https://github.com/epage"><code>@epage</code></a></li> <li><a href="https://github.com/sharkdp"><code>@sharkdp</code></a></li> <li><a href="https://github.com/ntBre"><code>@ntBre</code></a></li> </ul> <h2>0.16.1</h2> <p>Released on 2026-07-30.</p> <h3>Preview features</h3> <ul> <li>Add an option to opt out of human-readable names (<a href="https://redirect.github.com/astral-sh/ruff/pull/27160">#27160</a>)</li> <li>[<code>flake8-pytest-style</code>] Make fixes safe by default and unsafe only when comments are present (<code>PT018</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/27201">#27201</a>)</li> <li>[<code>pyupgrade</code>] Skip fix when a defaulted <code>TypeVar</code> precedes a non-defaulted one (<code>UP040</code>, <code>UP046</code>, <code>UP047</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/27133">#27133</a>)</li> <li>[<code>ruff</code>] Fix false positive with unpacked arguments (<code>RUF065</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/26959">#26959</a>)</li> </ul> <h3>Bug fixes</h3> <ul> <li>Bump <code>gen-lsp-types</code> to gracefully handle unknown enumeration values in LSP messages (<a href="https://redirect.github.com/astral-sh/ruff/pull/27230">#27230</a>)</li> <li>[<code>flake8-bugbear</code>] Mark <code>range</code> as immutable (<code>B008</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/27247">#27247</a>)</li> <li>[<code>flake8-comprehensions</code>] NFKC-normalize keyword names in <code>C408</code> fix (<a href="https://redirect.github.com/astral-sh/ruff/pull/26813">#26813</a>)</li> <li>[<code>flake8-return</code>] Fix false positive when variable is read in <code>finally</code> clause (<code>RET504</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/25441">#25441</a>)</li> <li>[<code>pydocstyle</code>] Skip section detection inside RST directive bodies (<code>D214</code>, <code>D405</code>, <code>D413</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/23635">#23635</a>)</li> <li>[<code>refurb</code>] Parenthesize <code>yield</code> arguments in the <code>FURB192</code> fix (<a href="https://redirect.github.com/astral-sh/ruff/pull/27192">#27192</a>)</li> </ul> <h3>Rule changes</h3> <ul> <li>[<code>flake8-pytest-style</code>] Mark <code>PT022</code> fixes as unsafe (<a href="https://redirect.github.com/astral-sh/ruff/pull/26440">#26440</a>)</li> <li>[<code>refurb</code>] Mark fixes that remove unknown separators as unsafe (<code>FURB105</code>) (<a href="https://redirect.github.com/astral-sh/ruff/pull/27200">#27200</a>)</li> </ul> <h3>Server</h3> <ul> <li>Fix indexing of excluded nested Ruff workspaces (<a href="https://redirect.github.com/astral-sh/ruff/pull/27303">#27303</a>)</li> <li>Lint TOML files in the LSP (<a href="https://redirect.github.com/astral-sh/ruff/pull/26862">#26862</a>)</li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="5b48a04097"><code>5b48a04</code></a> Bump 0.16.2 (<a href="https://redirect.github.com/astral-sh/ruff/issues/27555">#27555</a>)</li> <li><a href="1b9e5fc483"><code>1b9e5fc</code></a> Update Swatinem/rust-cache action to v2.9.2 (<a href="https://redirect.github.com/astral-sh/ruff/issues/27568">#27568</a>)</li> <li><a href="c4e86fc039"><code>c4e86fc</code></a> [ty] Add helper extension methods for half-range and equality constraints (<a href="https://redirect.github.com/astral-sh/ruff/issues/2">#2</a>...</li> <li><a href="17a00de2e2"><code>17a00de</code></a> [ty] Reuse primer commands in memory reports (<a href="https://redirect.github.com/astral-sh/ruff/issues/27553">#27553</a>)</li> <li><a href="6ea296b969"><code>6ea296b</code></a> [ty] Normalize type labels in structured docstrings (<a href="https://redirect.github.com/astral-sh/ruff/issues/26923">#26923</a>)</li> <li><a href="2fc445f005"><code>2fc445f</code></a> [ty] Diagnose invalid <strong>getattr</strong> calls (<a href="https://redirect.github.com/astral-sh/ruff/issues/27502">#27502</a>)</li> <li><a href="22c7823c4e"><code>22c7823</code></a> [ty] Enable (but downrank) auto-import completion suggestions from stub-only ...</li> <li><a href="05160d507f"><code>05160d5</code></a> [ty] Diagnose invalid descriptor <code>__get__</code> calls (<a href="https://redirect.github.com/astral-sh/ruff/issues/27400">#27400</a>)</li> <li><a href="baea3d0dce"><code>baea3d0</code></a> [ty] Expose strict analysis options in the playground (<a href="https://redirect.github.com/astral-sh/ruff/issues/27543">#27543</a>)</li> <li><a href="c88946ebeb"><code>c88946e</code></a> [ty] Bump ecosystem-analyzer for strict project settings (<a href="https://redirect.github.com/astral-sh/ruff/issues/27542">#27542</a>)</li> <li>Additional commits viewable in <a href="https://github.com/astral-sh/ruff/compare/0.15.22...0.16.2">compare view</a></li> </ul> </details> <br /> --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: JerrettDavis <mxjerrett@gmail.com>
242 lines
5.3 KiB
Markdown
242 lines
5.3 KiB
Markdown
# Error Handling
|
|
|
|
Headroom provides explicit exceptions for debugging, with a safety guarantee that compression failures never break your LLM calls.
|
|
|
|
## Exception Hierarchy
|
|
|
|
```python
|
|
from headroom import (
|
|
HeadroomError, # Base class - catch all Headroom errors
|
|
ConfigurationError, # Invalid configuration
|
|
ProviderError, # Provider issues (unknown model, etc.)
|
|
StorageError, # Database/storage failures
|
|
CompressionError, # Compression failures (rare)
|
|
ValidationError, # Setup validation failures
|
|
)
|
|
```
|
|
|
|
## Usage
|
|
|
|
```python
|
|
from headroom import (
|
|
HeadroomClient,
|
|
HeadroomError,
|
|
ConfigurationError,
|
|
StorageError,
|
|
)
|
|
|
|
try:
|
|
client = HeadroomClient(...)
|
|
response = client.chat.completions.create(...)
|
|
|
|
except ConfigurationError as e:
|
|
print(f"Config issue: {e}")
|
|
print(f"Details: {e.details}") # Additional context
|
|
|
|
except StorageError as e:
|
|
print(f"Storage issue: {e}")
|
|
# Headroom continues to work, just without metrics persistence
|
|
|
|
except HeadroomError as e:
|
|
print(f"Headroom error: {e}")
|
|
```
|
|
|
|
## Exception Types
|
|
|
|
### ConfigurationError
|
|
|
|
Raised when configuration is invalid.
|
|
|
|
```python
|
|
# Examples:
|
|
# - Invalid mode value
|
|
# - Missing required provider
|
|
# - Invalid model context limit
|
|
|
|
try:
|
|
client = HeadroomClient(
|
|
original_client=OpenAI(),
|
|
provider=OpenAIProvider(),
|
|
default_mode="invalid_mode", # Will raise ConfigurationError
|
|
)
|
|
except ConfigurationError as e:
|
|
print(f"Config error: {e}")
|
|
print(f"Field: {e.details.get('field')}")
|
|
```
|
|
|
|
### ProviderError
|
|
|
|
Raised for provider-specific issues.
|
|
|
|
```python
|
|
# Examples:
|
|
# - Unknown model name
|
|
# - Provider API error
|
|
# - Token counting failure
|
|
|
|
try:
|
|
response = client.chat.completions.create(model="unknown-model-xyz", messages=[...])
|
|
except ProviderError as e:
|
|
print(f"Provider error: {e}")
|
|
print(f"Provider: {e.details.get('provider')}")
|
|
```
|
|
|
|
### StorageError
|
|
|
|
Raised when database operations fail.
|
|
|
|
```python
|
|
# Examples:
|
|
# - Database connection failure
|
|
# - Write permission denied
|
|
# - Disk full
|
|
|
|
try:
|
|
metrics = client.get_metrics()
|
|
except StorageError as e:
|
|
print(f"Storage error: {e}")
|
|
# Application can continue - just won't have metrics
|
|
```
|
|
|
|
### CompressionError
|
|
|
|
Raised when compression fails (rare).
|
|
|
|
```python
|
|
# Examples:
|
|
# - Malformed JSON in tool output
|
|
# - Unexpected data structure
|
|
|
|
# Note: In practice, compression errors are caught internally
|
|
# and the original content passes through unchanged.
|
|
# This exception is only raised if you explicitly enable strict mode.
|
|
```
|
|
|
|
### ValidationError
|
|
|
|
Raised when setup validation fails.
|
|
|
|
```python
|
|
result = client.validate_setup()
|
|
if not result["valid"]:
|
|
raise ValidationError("Setup validation failed", details={"issues": result["issues"]})
|
|
```
|
|
|
|
## Safety Guarantee
|
|
|
|
**If compression fails, the original content passes through unchanged.**
|
|
|
|
This is a core design principle. Your LLM calls never fail due to Headroom:
|
|
|
|
```python
|
|
# Even if SmartCrusher encounters unexpected data:
|
|
messages = [{"role": "tool", "content": "malformed json {{{"}]
|
|
|
|
# This will NOT raise an exception
|
|
# Instead, the malformed content passes through unchanged
|
|
response = client.chat.completions.create(model="gpt-4o", messages=messages)
|
|
```
|
|
|
|
## Logging Errors
|
|
|
|
Enable logging to see error details:
|
|
|
|
```python
|
|
import logging
|
|
|
|
logging.basicConfig(level=logging.WARNING)
|
|
|
|
# Now you'll see warnings when compression is skipped:
|
|
# WARNING:headroom.transforms.smart_crusher:Skipping compression: invalid JSON
|
|
```
|
|
|
|
## Error Details
|
|
|
|
All Headroom exceptions include a `details` dict with context:
|
|
|
|
```python
|
|
try:
|
|
client = HeadroomClient(...)
|
|
except HeadroomError as e:
|
|
print(f"Error: {e}")
|
|
print(f"Type: {type(e).__name__}")
|
|
print(f"Details: {e.details}")
|
|
|
|
# Details might include:
|
|
# - field: which config field caused the error
|
|
# - provider: which provider was involved
|
|
# - model: which model was requested
|
|
# - original_error: underlying exception
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
### 1. Catch Specific Exceptions
|
|
|
|
```python
|
|
# Good: catch specific exceptions
|
|
try:
|
|
response = client.chat.completions.create(...)
|
|
except ConfigurationError:
|
|
# Handle config issues
|
|
pass
|
|
except ProviderError:
|
|
# Handle provider issues
|
|
pass
|
|
|
|
# Avoid: catching all exceptions
|
|
try:
|
|
response = client.chat.completions.create(...)
|
|
except Exception:
|
|
# Too broad - might hide real bugs
|
|
pass
|
|
```
|
|
|
|
### 2. Let StorageError Pass
|
|
|
|
```python
|
|
# Storage errors don't affect core functionality
|
|
try:
|
|
metrics = client.get_metrics()
|
|
except StorageError:
|
|
metrics = [] # Continue without historical metrics
|
|
```
|
|
|
|
### 3. Validate on Startup
|
|
|
|
```python
|
|
client = HeadroomClient(...)
|
|
|
|
# Validate once at startup
|
|
result = client.validate_setup()
|
|
if not result["valid"]:
|
|
raise SystemExit(f"Headroom setup invalid: {result['issues']}")
|
|
|
|
# Then use client normally
|
|
response = client.chat.completions.create(...)
|
|
```
|
|
|
|
## Debugging
|
|
|
|
### Enable Debug Logging
|
|
|
|
```python
|
|
import logging
|
|
|
|
logging.basicConfig(level=logging.DEBUG)
|
|
|
|
# Shows detailed transform decisions
|
|
# DEBUG:headroom.transforms.smart_crusher:Analyzing 1000 items...
|
|
# DEBUG:headroom.transforms.smart_crusher:Kept 15 items (errors: 2, anomalies: 3)
|
|
```
|
|
|
|
### Check Stats After Error
|
|
|
|
```python
|
|
try:
|
|
response = client.chat.completions.create(...)
|
|
except HeadroomError:
|
|
# Check what happened
|
|
stats = client.get_stats()
|
|
print(f"Last request stats: {stats}")
|
|
```
|