What's Changed
⚠️ Compatibility Notes
- Handle draft-7 list-form
itemsinJsonSchemaTransformer,TestModeland Mistral streamed output, and makeTestModelaccept boolean subschemas and capprefixItemsatmaxItemsby @dsfaccini in #9560 - Fix
ImageGenerationunderFallbackModelanddataclasses.replace, and compareEmbedderby identity by @dsfaccini in #9477 - Refuse a second durable execution engine on an agent before either binds by @DouweM in #9391
- Make
wrap_*hooks enclose complete stage lifecycles by @adtyavrdhn in #7053 - Re-raise model errors from Temporal model activities with their original type in workflow code by @DouweM in #9580
- End the run when a
BackgroundToolstool raises an unexpected exception, as a sequential tool does by @DouweM in #9434 - Drop the
SubAgentsagent_foldersdefault-change warning: since v2.52.0 (#9023) theagentsfolder is not loaded by default, so passagent_folders='agents'to keep loading it by @DouweM in #9424
🚀 Features
- Tint
clai2file diffs from the selected/themepalette by @mpfaffenberger in #9648 - Make
clai2/updatealways install the newest build and restart into it, resuming the session by @mpfaffenberger in #9659 - Disable
RepoContextinventory by default by @DouweM in #9382 - Give the
CodeModemissing-return-schema warning its ownCodeModeReturnSchemaWarningcategory by @DouweM in #9423 - Add
cancel_and_resumeexample: cancel and resume a streaming run by @DouweM in #7012 - Reconnect dropped
OpenAILiveModelsessions by forking a stored session or replaying the history by @DouweM in #9401 - Default Pydantic AI-created HTTP clients to the OpenAI SDK's connection pool limits, and make
create_async_httpx2_client()public by @DouweM in #9600 - Use
gpt-live-transcribefor OpenAI realtime's defaultinput_transcription_model='auto'and listgpt-transcribeby @DouweM in #9402 - Support
WebSearchToolon OpenAI GPT-Live through its delegated backend by @DouweM in #9049 - Add
nativetoExaSearchandYouSearchto prefer the model's native web search, andweb_search_tool()forWebSearch(local=...)by @DouweM in #9386 - Add a double-
Escconversation rewind menu toclai2by @mpfaffenberger in #9688 - Allow deleting unused models from the
clai2/modelmenu by @mpfaffenberger in #9696
🐛 Bug Fixes
- Fail closed in the shell
realpathfallback whenreadlinkcannot read a symlink by @dsfaccini in #9613 - Stop importing the undeclared
sniffiopackage inpydantic-evalsandpydantic-ai-harnessby @pydanty in #9620 - Fall back from
ImageGenerationToolto the local tool on Gemini text models, and keep tool output when a native tool falls back locally on Gemini 2.5 by @dsfaccini in #9551 - Nest worktrees under their repository in the
clai2resume sidebar by @mpfaffenberger in #9667 - Remove the
clai2resume-directory confirmation by @mpfaffenberger in #9682 - Report
clai2startup plugin failures throughobservabilityby @mpfaffenberger in #9681 - Show file diffs in compact
clai2tool output by @mpfaffenberger in #9687 - Treat a
nullfinish_reasonon aSnowflakeModelresponse like an empty one by @DouweM in #9590 - Refuse a
LocalFileStoreroot another user owns, and logToolOutputLimitsspill and summarize fallbacks by @DouweM in #9020 - State when the
ConversationSearchdefault-scope warning will be removed by @DouweM in #9383 - Warn when
read_only=Trueremoves every hosted MCP tool by @DouweM in #9387 - Pin the request that started the current run, not the first prompt of the conversation, in the
TrajectoryJudgewindow by @DouweM in #9425 - Identify the
search_toolstool by itstool_kindinstead of its name by @DouweM in #9603 - Find the tool search tool in
CodeModeby itstool_kind, so a prefixed search tool still gets its notes by @DouweM in #9604 - Log
LLMRemindergeneration failures instead of silently falling back toGoalReanchortext by @DouweM in #9024 - Include function tools run after the final result in
run_stream()usage by @DouweM in #9694 - Build the same
ModelResponsefrom streamed and completeGoogleModelresponses, and add Gemini 3 web search sources by @DouweM in #9594 - Recover run state with
RunCancelled.from_cancellation()when a DBOS workflow is cancelled by @DouweM in #9394 - Make custom
setup_logfirecallbacks replay-safe and addreplay_safetoLogfirePluginby @DouweM in #9698 - Raise
ModelAPIErrorfor undecodable 200 response bodies from Anthropic, Bedrock, Groq, Hugging Face, Google, and OpenAI embeddings and images by @DouweM in #9350 - Keep the run state recoverable when Ctrl-C interrupts
run_sync()by @DouweM in #9605 - Clamp OpenAI realtime barge-in truncation at the profile's
audio_output_sample_rateby @DouweM in #9399 - Load a capability once when
load_capabilityis called twice for it in one response by @DouweM in #9397 - Keep a first-position
ToolAvailabilityDeltaPartannouncement out of the standing system prompt by @DouweM in #9413 - Commit an ACP turn up to its usage limit instead of rolling it back by @DouweM in #9426
- Preserve dependency extras in
clai2archive updates by @mpfaffenberger in #9690 - Preserve text and reasoning part boundaries in
OpenAIChatModelstreams by @pydanty in #8729 - Propagate a native cancel that lands during a command timeout's stop by @dsfaccini in #9675
- Return the live token from
PKCESignIn.token()when anotherclai2session saved one without a refresh token by @dsfaccini in #9670 - Keep
BubblewrapWorkspacecommands from running code on the SSH host through shell startup files or theSSHWorkspaceBackendstop script'sPATH(VERIA-212) by @mpfaffenberger in #9673
Full Changelog: v2.53.0...v2.54.0