Releases: arieradle/shekel
v1.0.2
Full Changelog: v1.0.1...v1.0.2
v1.0.1
Full Changelog: v1.0.0...v1.0.1
v0.2.9
What's Changed
- feat: shekel run — non-invasive CLI budget enforcement (v0.2.9) by @arieradle in #23
Full Changelog: v0.2.8...v0.2.9
v0.2.8
What's Changed
- feat: temporal budgets with rolling-window spend enforcement (v0.2.8) by @arieradle in #21
- feat: Tool Budget API (v0.2.8) — max_tool_calls, tool_prices, auto-interception by @arieradle in #22
Full Changelog: v0.2.7...v0.2.8
v0.2.7
What's Changed
- feat: full async support for Gemini, HuggingFace, and nested budgets by @arieradle in #19
- feat: OpenTelemetry metrics integration (ShekelMeter) by @arieradle in #20
Full Changelog: v0.2.6...v0.2.7
v0.2.6
What's Changed
- feat: v0.2.6 — call limits, dict fallback API, breaking-change cleanup by @arieradle in #12
- feat: add LiteLLM provider adapter (v0.2.6) by @arieradle in #14
- feat: add LangGraph integration helper (v0.2.6) by @arieradle in #13
- feat: LangGraph integration docs + mypy CI fix by @arieradle in #15
- test: LangGraph integration tests (Groq, Gemini, mock) by @arieradle in #16
- feat: add Google Gemini and HuggingFace provider adapters by @arieradle in #17
- feat: release hardening for v0.2.6 by @arieradle in #18
Full Changelog: v0.2.5...v0.2.6
v0.2.5
What's Changed
- feat: implement ProviderAdapter pattern for pluggable LLM provider integration (v0.2.5) by @arieradle in #8
- test & ci: add comprehensive performance testing suite with CI/CD integration by @arieradle in #9
- feat: comprehensive Ollama/Groq/Gemini integration tests by @arieradle in #10
Full Changelog: v0.2.4...v0.2.5
v0.2.4 — Langfuse Integration
What's New
🔭 Langfuse Integration — Full LLM Observability
Track costs, visualize budget hierarchies, and debug overruns in Langfuse — automatically.
from langfuse import Langfuse
from shekel import budget
from shekel.integrations import AdapterRegistry
from shekel.integrations.langfuse import LangfuseAdapter
lf = Langfuse(public_key="pk-lf-...", secret_key="sk-lf-...")
AdapterRegistry.register(LangfuseAdapter(client=lf, trace_name="my-app"))
with budget(max_usd=10.00, fallback="gpt-4o-mini", name="agent") as b:
run_agent() # costs flow to Langfuse automatically
Four features out of the box:
- 💰 Real-time cost streaming —
shekel_spent,shekel_limit,shekel_utilizationon every LLM call - 🌳 Nested budget hierarchy — child budgets become child spans (perfect waterfall view)
⚠️ Circuit break events — WARNING events when budgets are exceeded, with overage metadata- 🔄 Fallback annotations — INFO events when fallback models activate, with savings data
Install
pip install shekel[langfuse] # Langfuse only
pip install shekel[all] # OpenAI + Anthropic + Langfuse
Also in this release
AdapterRegistry.unregister()— remove individual adaptersnameparameter on@with_budgetdecorator — enables named parent budgets for nestingeffective_limitenforcement fix — auto-capped nested budgets now raise at their capped limit (notmax_usd)- 267 tests, 95%+ coverage
Links
v0.2.3: Nested Budgets
🌳 Nested Budgets - Hierarchical Cost Tracking
Version 0.2.3 introduces nested budgets, the flagship feature that enables hierarchical budget tracking for multi-stage AI workflows.
Major Features
Nested Budget Contexts
- Automatic parent-child relationships - Child budgets inherit context from parent
- Automatic spend propagation - Child spend flows to parent on exit
- Auto-capping - Child budgets automatically capped to parent's remaining budget
- Parent locking - Parent cannot spend while child is active (sequential execution)
- Named budgets - Required when nesting for clear cost attribution
- Track-only children - Use
max_usd=Nonefor unlimited child tracking - Maximum nesting depth - 5 levels enforced for safety
Rich Introspection API
budget.full_name- Hierarchical path (e.g.,"workflow.research.validation")budget.spent_direct- Direct spend by this budget (excluding children)budget.spent_by_children- Sum of all child spendbudget.parent- Reference to parent budget (Nonefor root)budget.children- List of child budgetsbudget.active_child- Currently active child budgetbudget.tree()- Visual hierarchy of budget tree with spend breakdown
Safety Rails
- Zero/negative budget validation at
__init__ - Async nesting detection (raises clear error - deferred to future version)
- Spend propagation on all exceptions (money spent is money spent)
- Sibling budgets must have unique names under the same parent
Breaking Changes
with blocks
- Previously:
budget(max_usd=10)reset on each entry (unlesspersistent=True) - Now: Same budget variable = same accumulated state
- Migration: Create new
Budget()instances instead of relying on reset behavior
- Both parent and child must have
nameparameter when creating nested contexts - Validation happens at child
__enter__with clear error messages
Deprecations
persistentparameter deprecated (showsDeprecationWarningwhen used)- Parameter kept for backwards compatibility but no longer has effect
- Will be removed in v0.3.0
Bug Fixes
- ContextVar token management now uses proper
.reset()instead of manual.set(None) - Patch reference counting no longer leaks when validation errors occur before patching
Documentation
- Comprehensive nested budgets guide (800+ lines)
- Real-world examples:
nested_content_pipeline.py,nested_research_agent.py - Updated all existing docs to reflect v0.2.3 changes
- Migration guide from v0.2.2
Installation
pip install shekel==0.2.3See CHANGELOG.md for complete details.
v0.2.2 — Prefix model resolution + CLI
What's new
Prefix model name resolution
Versioned model names now resolve automatically without any configuration:
gpt-4o-2024-08-06→gpt-4opricinggpt-4o-mini-2024-07-18→gpt-4o-minipricingclaude-3-5-sonnet-20241022-preview→claude-3-5-sonnet-20241022pricing
Uses longest-prefix match so gpt-4o-mini-* correctly maps to gpt-4o-mini, not gpt-4o.
CLI tools
pip install shekel[cli]
# Estimate cost before writing any code
shekel estimate --model gpt-4o --input-tokens 1000 --output-tokens 500
# List all bundled models with pricing
shekel models
shekel models --provider openai
shekel models --provider anthropicInternal improvements
- Replaced fragile inline
# type: ignorewith proper[[tool.mypy.overrides]]inpyproject.toml - Test coverage at 94%
Full changelog
See CHANGELOG.md