@@ -10,10 +10,83 @@ both packages adhere to [Semantic Versioning](https://semver.org/).
1010
1111## Unreleased
1212
13- ## js 0.2.0 — 2026-07-08
13+ ## py 0.2.0 / js 0.2.1 — 2026-07-10
14+
15+ Everything the repo grew between the 0.1.0 uploads and this release ships here —
16+ the earlier revision of this changelog misattributed several of these features
17+ to the py 0.1.0 entry; that entry now reflects what the released artifact
18+ actually contained.
19+
20+ ### Added (py)
21+
22+ - ** Concurrency-safe enforcement** : atomic ` reserve() ` / ` settle() ` /
23+ ` release() ` with a lock-guarded running total, closing the
24+ check-then-record race that let parallel callers blow the ceiling
25+ (issue #18 ). ` check() ` / ` record() ` are unchanged for sequential use.
26+ - ** Context-aware budgeting** : ` BudgetGuard.advisory() ` returning a
27+ ` BudgetAdvisory ` (` near_limit ` , ` used_bps ` , ` remaining_usd ` , totals), with a
28+ ` near_limit_bps ` constructor threshold (default 8000 = 80%).
29+ - ** Adapters** : LangChain (` budget_guard_callback_handler ` ), OpenAI
30+ (` guarded_completion ` / ` guarded_acompletion ` ), and Anthropic (same pair,
31+ with cache-token metering) — each behind an optional extra
32+ (` [langchain] ` , ` [openai] ` , ` [anthropic] ` ).
33+ - ** Hosted budget read** : ` hosted_remaining_usd() ` (GET
34+ ` /v1/agents/credit-remaining ` , opt-in via ` FLOE_API_KEY ` , host override via
35+ ` FLOE_API_BASE_URL ` ), ` HostedEnforcementError ` , and package-root export of
36+ ` hosted_enforcement_available() ` . This is the package's only network call
37+ and never runs unless you set the key.
38+
39+ ### Added (py + js)
40+
41+ - ** Groq pricing** : curated Groq models vendored in the cost map —
42+ ` llama-3.1-8b-instant ` , ` llama-3.3-70b-versatile ` ,
43+ ` meta-llama/llama-4-scout-17b-16e-instruct ` , ` qwen/qwen3-32b ` (new for py;
44+ these four already shipped in js 0.2.0), plus the current production lineup
45+ ` openai/gpt-oss-120b ` , ` openai/gpt-oss-20b ` , ` openai/gpt-oss-safeguard-20b `
46+ (new for both packages). Kept as an explicit allowlist
47+ (` scripts/update-cost-map.mjs ` ) so generic multi-provider names stay
48+ fail-closed instead of under-metering.
49+ - ** Smarter model-id resolution** (both packages, identical logic): lookup
50+ candidates are tried most-specific-first — the raw id, the id with a known
51+ ` openai/ ` / ` anthropic/ ` / ` groq/ ` first segment stripped (so
52+ ` groq/qwen/qwen3-32b ` and ChatGroq's ` qwen/qwen3-32b ` hit the same entry),
53+ then the bare last segment; each also with a trailing dated-snapshot suffix
54+ removed, so an unlisted snapshot like ` claude-opus-4-8-<date> ` prices at its
55+ alias entry instead of failing closed. Unknown provider prefixes are
56+ deliberately not bridged.
57+ - Cost-map refresh adds ` claude-sonnet-5 ` (both packages; the py package also
58+ gains ` claude-fable-5 ` , which already shipped in js 0.2.0 —
59+ ` claude-opus-4-8 ` and ` claude-sonnet-4-6 ` shipped in the 0.1.0 maps) and
60+ warns when a curated Groq model disappears upstream instead of silently
61+ dropping it.
62+
63+ ### Fixed (py)
64+
65+ - ** CrewAI / LiteLLM-callback silent footgun** : LiteLLM runs custom-logger
66+ hooks inside ` except Exception ` , so the callback's enforcement raise
67+ (pre-call ` BudgetExceeded ` , fail-closed ` UnpriceableModelError ` ) could be
68+ swallowed and a crew kept running unmetered with no visible signal. The
69+ callback now records the violation on its ` tripped ` attribute and logs it at
70+ ERROR level on the ` floe_guard ` logger, and
71+ ` budget_guarded_llm ` returns a ` crewai.LLM ` subclass that re-raises
72+ ` tripped ` and runs ` check() ` in the call path — outside LiteLLM — so the
73+ crew hard-stops at the next call. ` guard_crew ` now returns the registered
74+ callback (previously ` None ` ) and reuses an existing registration for the
75+ same guard.
76+
77+ ### Changed (py + js)
78+
79+ - Price lookup order is now most-specific-first (raw id before stripped
80+ forms) for both ` price_overrides ` and the cost map. Previously the bare name
81+ was tried before the raw id.
82+
83+ ## js 0.2.0 — published 2026-07-10
1484
1585### Added
1686
87+ - Curated Groq cost-map entries: ` llama-3.1-8b-instant ` ,
88+ ` llama-3.3-70b-versatile ` , ` meta-llama/llama-4-scout-17b-16e-instruct ` ,
89+ ` qwen/qwen3-32b ` , plus ` claude-fable-5 ` .
1790- ** Vercel AI SDK v5 support.** The middleware now works with both ` ai@4 `
1891 (` LanguageModelV1Middleware ` , ` promptTokens ` /` completionTokens ` ) and ` ai@5 `
1992 (` LanguageModelV2Middleware ` , ` inputTokens ` /` outputTokens ` ) from a single
@@ -30,18 +103,18 @@ both packages adhere to [Semantic Versioning](https://semver.org/).
30103
31104## py 0.1.0 / js 0.1.0 — 2026-06
32105
33- Initial public release .
106+ Initial public releases (PyPI 2026-06-15, npm 2026-06-16) .
34107
35- - ` BudgetGuard ` with ` check() ` / ` record() ` , concurrency-safe
36- ` reserve() ` / ` settle() ` / ` release() ` , and ` advisory() ` for context-aware
37- budgeting (taper before the hard-stop).
38- - Offline pricing from a vendored LiteLLM cost map; unpriceable models fail
39- closed (` UnpriceableModelError ` ) with manual ` price_overrides ` as the
40- escape hatch.
41- - Python adapters: CrewAI, LiteLLM, LangChain, OpenAI, Anthropic — each behind
42- an optional extra; the core stays dependency-free.
108+ - ` BudgetGuard ` with ` check() ` / ` record() ` (sequential; the atomic
109+ reservation API landed in py 0.2.0).
110+ - Offline pricing from a vendored LiteLLM cost map covering OpenAI and
111+ Anthropic; unpriceable models fail closed (` UnpriceableModelError ` ) with
112+ manual ` price_overrides ` as the escape hatch.
113+ - Python adapters: CrewAI and LiteLLM, behind optional extras; the core stays
114+ dependency-free. (The LangChain, OpenAI, and Anthropic adapters landed in
115+ py 0.2.0.)
116+ - Hosted-Floe hook as a stub (` hosted_enforcement_available() ` under
117+ ` floe_guard.hosted ` ); this release performs no network calls of any kind.
43118- TypeScript package (` js/ ` ) with Vercel AI SDK middleware
44119 (` budgetGuardMiddleware ` ), verified against ` ai@4 ` .
45- - Optional hosted-Floe budget read (` hosted_remaining_usd() ` ) via
46- ` FLOE_API_KEY ` — the only network call in the package, opt-in.
47120- No runtime telemetry of any kind.
0 commit comments