Skip to content

Conversation

@jeffzwang
Copy link
Contributor

⚠️ Experimental PR - Generated by Claude Code

Author: @jwang (via Claude Code / Claude Opus 4.5)

This PR was generated entirely by Claude Code as an experiment to improve the exa-py SDK quality. Please review carefully before merging!


Summary

This PR addresses critical issues identified in a comprehensive SDK quality analysis:

  • Custom exception hierarchy for proper error handling (was using generic ValueError for everything)
  • Automatic retry with exponential backoff for transient failures (was: no retry at all)
  • Configurable timeout (sync client had NO timeout - could hang forever!)
  • Documentation (Quick Start Guide + Changelog)

Changes

🆕 New: Custom Exception Hierarchy (exa_py/exceptions.py)

from exa_py import ExaRateLimitError, ExaAuthenticationError

try:
    results = exa.search("query")
except ExaRateLimitError as e:
    print(f"Rate limited. Retry after {e.retry_after}s")
except ExaAuthenticationError:
    print("Invalid API key")

Exception classes:

  • ExaError - Base exception
  • ExaAPIError - API errors (4xx/5xx)
  • ExaAuthenticationError - 401/403
  • ExaRateLimitError - 429 with retry_after
  • ExaNotFoundError - 404
  • ExaServerError - 5xx
  • ExaValidationError - Invalid parameters
  • ExaTimeoutError - Timeout with timeout attribute
  • ExaNetworkError - Connection issues

🆕 New: Retry with Exponential Backoff

exa = Exa(
    max_retries=5,              # Default: 3
    backoff_factor=1.0,         # Default: 0.5
    retry_on_status=(429, 500), # Default: (429, 500, 502, 503, 504)
)

🆕 New: Configurable Timeout

exa = Exa(timeout=30)  # Default: 60s (was infinite!)

🆕 New: Async Context Manager

async with AsyncExa() as exa:
    results = await exa.search("query")
# Client automatically closed

🔧 Fixed: Parameter Naming Consistency

# Before (inconsistent)
AsyncExa(api_base="...")

# After (consistent with Exa)
AsyncExa(base_url="...")

🔧 Fixed: Missing Dependencies

Added to setup.py: httpx, pydantic, httpcore, python-dotenv

📚 New: Documentation

  • QUICKSTART.md - 5-minute getting started guide
  • CHANGELOG.md - Release notes and migration guide

Breaking Changes

  • AsyncExa parameter api_base renamed to base_url

Test Plan

  • All 128 existing unit tests pass
  • Manual testing of new exception types
  • Manual testing of retry logic
  • Manual testing of timeout behavior
  • Review by human developers 👀

🤖 Generated with Claude Code

This PR adds several critical improvements to the exa-py SDK:

## New Features

### Custom Exception Hierarchy
- `ExaError` - Base exception for all SDK errors
- `ExaAPIError` - API returned an error response
- `ExaAuthenticationError` - Invalid or missing API key (401/403)
- `ExaRateLimitError` - Rate limit exceeded (429) with `retry_after`
- `ExaNotFoundError` - Resource not found (404)
- `ExaServerError` - Server errors (5xx)
- `ExaValidationError` - Invalid parameters
- `ExaTimeoutError` - Request timeout
- `ExaNetworkError` - Connection issues

### Automatic Retry with Exponential Backoff
- Configurable `max_retries` (default: 3)
- Configurable `retry_on_status` (default: 429, 500, 502, 503, 504)
- Configurable `backoff_factor` (default: 0.5)

### Configurable Timeout
- Default timeout of 60 seconds (was infinite for sync!)
- Configurable via `timeout` parameter

### Async Context Manager
- `async with AsyncExa() as exa:` for proper cleanup

## Breaking Changes
- `AsyncExa` parameter renamed from `api_base` to `base_url` for consistency

## Documentation
- Added QUICKSTART.md - 5-minute getting started guide
- Added CHANGELOG.md - Release notes and migration guide

## Bug Fixes
- Added missing dependencies to setup.py (httpx, pydantic, etc.)
- Sync requests no longer hang indefinitely

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants