🛡️ Security
This release fixes one security issue in ConcurrencyLimitedModel. See the advisory for full details and affected versions.
- GHSA-6fqq-452j-qhrp (high): a streamed request through
ConcurrencyLimitedModelorlimit_model_concurrencycould keep its concurrency slot when the slot was released on a different task than the one that acquired it: after an early exit (the consumer stopped iterating, raised, or was cancelled), and also after fully consumingstream_text()with its default debouncing. Repeated streams could then block every request sharing the limiter. Agent-levelmax_concurrencyand non-streaming requests are not affected. Reported by @lche511. (#9478)
The fix also changes how limiters are shared: a model wrapper now raises UserError when it shares a limiter with the agent making the request or with an enclosing model wrapper, ConcurrencyLimiter.acquire() takes a slot on every call, even on the same task, and a custom AbstractConcurrencyLimiter must allow release() from another task.
Patched in 2.53.0. v1 is not affected.
What's Changed
⚠️ Compatibility Notes
- Add
oneOfschema support toTestModel's generated data by @pydanty in #8783 - Make
clai2plugins declarativePluginsubclasses, modeled onAbstractCapabilityby @mpfaffenberger in #9493
🚀 Features
- Add a built-in
posthogplugin topydantic-clai2with/keysor browser sign-in by @mpfaffenberger in #8901 - Add a built-in
grainplugin toclai2with a keyring-backed Grain sign-in by @mpfaffenberger in #8905 - Add a built-in
linearplugin toclai2with a settings menu and/keyscredentials by @mpfaffenberger in #8949 - Count Google grounding web search queries in
usageby @pydanty in #8891 - Add
AbsurdDurabilityto the harness as a replacement forpydantic-ai-absurdby @adtyavrdhn in #8946 - Let CLAI2 plugins run models under their own prefix with
host.model_providerby @mpfaffenberger in #9468 - Apply theme-aware accents to the
clai2status row by @mpfaffenberger in #9473 - Add opt-in Logfire UI telemetry and a Logfire setup menu (region, sign-in, project) to
pydantic-clai2by @mpfaffenberger in #9467 - Add an opt-in herdr plugin for
clai2by @mpfaffenberger in #9480 - Let
AskUserdefer questions to the host and time out a slow answerer by @mpfaffenberger in #9509 - Add a Codex-only
/fastcommand to CLAI2 by @mpfaffenberger in #9518 - Let /login take a provider name, and let plugins add their own sign-ins by @mpfaffenberger in #9485
- Add
SystemOneModelto run decision models such as CLM and Laya over the/v1/systemoneAPI by @mpfaffenberger in #8942 - CLAI2: plugin logins add their models; plugin models can use a provider's /model_settings controls by @mpfaffenberger in #9558
- Rename the CLAI
logfireplugin toobservabilityby @mpfaffenberger in #9566 - Add
ToolCallJudgeto assess tool calls before execution by @DouweM in #9041 - Add managed subagents to CLAI2, with Claude and Codex agent definitions in Harness by @mpfaffenberger in #9573
- Add a settings menu to CLAI2's built-in
observability(Logfire) plugin by @mpfaffenberger in #9306 - CLAI2:
/updatewith stable (PyPI) and bleeding (main) channels by @mpfaffenberger in #9576 - Make the CLAI2
/pluginsmenu themed and readable, with plugin descriptions by @mpfaffenberger in #9570 - Send images and documents from GPT-Live tool results to the delegated backend by @DouweM in #9048
- Tag
clai2plugin settings with the features they need, and skip a plugin capability that rejects its settings at run setup by @mpfaffenberger in #9569 - Show compact used/max context in the CLAI2 status line by @mpfaffenberger in #9583
- Expose the message-history repair pipeline as
repair_messagesby @DouweM in #8370
🐛 Bug Fixes
- Kill the process group when a
LocalWorkspaceBackend.runtimeout fires during process startup by @dsfaccini in #9358 - Ask for CLAI2 keychain access once per session by encrypting credentials with one keyring-held key by @mpfaffenberger in #9465
- Name CLAI2 worktree branches
clai-NAMEand reopen existing worktrees with--worktree NAMEby @mpfaffenberger in #9462 - Avoid invalid-escape warning floods during
CodeModeanalysis by @mpfaffenberger in #9475 - Group
clai2resume sessions by repository identity by @mpfaffenberger in #9482 - Create the CLAI2 plugins folder at startup by @mpfaffenberger in #9484
- Keep the registered
Memorytoolset across runs so durable execution accepts it by @mpfaffenberger in #9489 - Keep the registered
Planningtoolset across runs so durable execution accepts it by @mpfaffenberger in #9507 - Keep planted files from escaping
BubblewrapSandboxon the next launch by @dsfaccini in #9457 - Render non-finite eval metrics as
inf/-inf/nanby @pydanty in #8852 - Snap
gemini-3.1-flash-imagethinking efforts tominimalandhighon the Gemini API by @dsfaccini in #9515 - Raise
UnexpectedModelBehaviorinstead of running the wrong tool when function tool calls share atool_call_idby @pydanty in #8782 - Explain that CLAI2 needs a restart when
/reloadhits a stale Harness import by @mpfaffenberger in #9571 - Build one streamed
XaiModelthinking part per output, matching the non-streamed response by @DouweM in #9416 - Leave image generation calls out of the
OpenAIResponsesModelreplay whenopenai_store=Falseby @DouweM in #9388 - Build the same
ModelResponsefrom streamed and completeOpenAIChatModelandOpenRouterModelresponses by @DouweM in #9418 - Make
OpenAIResponsesModelbuild the sameModelResponsefrom a stream as from a complete response by @DouweM in #9417 - Make xAI push-to-talk reply only when asked:
commit_audio()alone no longer triggers a reply, andcreate_response()is always answered by @DouweM in #9070 - Tolerate OpenAI realtime
status,status_detailsand session values the SDK does not know yet by @DouweM in #9392 - Stop
SubAgentsfrom forcingthinkingon disk agents by @DouweM in #9384 - Restore
DynamicWorkflowreveal announcements after compaction or history loss by @DouweM in #9371 - Preserve free-text focus in CLAI2
/compactby @mpfaffenberger in #9587 - Make Logfire Temporal spans replay-safe by @DouweM in #7006
- Keep the launch-directory workspace in
clai2when capability functions supply none, and exposeunrestricted_filesystemin/plugins configure coderby @mpfaffenberger in #9593 - Allow unschemable types in the derived Temporal
ActivityConfigschema by @pydanty in #9577 - Let
GoogleRealtimeModeldeclare tools whosedictvalues are recursive models by @dsfaccini in #9607
📦 Dependencies
- Bump CLAI2 to
termflow-md0.11.0 by @mpfaffenberger in #9483
New Contributors
- @Poojita060926 made their first contribution in #8900
Full Changelog: v2.52.0...v2.53.0