Skip to content

v0.93.0

Choose a tag to compare

@sboily sboily released this 30 Sep 16:31
· 1990 commits to main since this release

What's Changed

  • docs(changelog): 0.93.0 — BREAKING leads on the contract breaks, entries realigned with HEAD, and the new catalogue models
  • feat(providers): Claude Sonnet 5.5 and GPT-6.1 Sol in the model catalogues
  • docs(changelog): the conference and configure() refusals, the exported ToolNameCollisionError, a re-install replacing its own, and call_tool, per review (RMK-307)
  • fix(tools): the registry counts orchestration's entries instead of scanning every room at each dispatch, a delegation to an agent owning the result tool's name fails naming it, and stale comments go, per review (RMK-307)
  • refactor(orchestration): extract the call_tool unwrap, the host tools' composition, a delegation's report and completion tracking, and a team's background start from the functions that grew around them, per review (RMK-307)
  • fix(realtime): a reconfiguration decides Tool Search on its catalogue without keeping it until the provider took it, and the skills support is built by its own function, per review (RMK-307)
  • fix(tools): ToolNameCollisionError is exported from roomkit, and a realtime configure() refuses what the constructor refuses, per review (RMK-307)
  • fix(conference): a realtime configuration with two tools under one name is refused, as on the other channels, per review (RMK-307)
  • fix(orchestration): installing Pipeline or Swarm again in a room replaces its own handoffs, and an install with several tools sets them all up or none, per review (RMK-307)
  • fix(realtime): a reconfiguration decides Tool Search on the catalogue it brings, and a session keeps the channel's voice and prompt its room's agent leaves unset, per review (RMK-307)
  • fix(examples): the supervisor and swarm examples read a room's tools from where the strategy sets them up (RMK-307)
  • docs(changelog): name the realtime per-room setups, the session-only reconfiguration and Tool Search per session (RMK-307)
  • test(orchestration): two rooms run at once and leave the channels they share as they were (RMK-307)
  • fix(realtime): Tool Search hides a session's catalogue on what that session declares, instead of on the tools the channel was built with (RMK-307)
  • fix(realtime): a strategy's voice tools are set up for its room and declared in that room's sessions, a session starts with its room's active agent, and reconfiguring a session changes that session only (RMK-307)
  • docs(changelog): name the per-room setups, the refused collisions and the host's tool_handler (RMK-307)
  • fix(orchestration): a sync loop or auto-delegating supervisor takes the turns of the rooms it is installed in, instead of wrapping the agent's on_event for every room (RMK-307)
  • fix(orchestration): a strategy sets its tools up for the room it is installed in, with that install's configuration, served through the channel's dispatch instead of a wrapped handler (RMK-307)
  • fix(tools): a channel keeps the tools it serves in a registry with their traits, the exempt, pure and digest name lists become traits, and a host tool given twice is refused (RMK-307)
  • refactor(orchestration): extract each orchestration tool's serving into a named server, and a pipeline's speech-to-speech wiring into its own module (RMK-307)
  • refactor(channels): extract the tool surface setup, the turn's base tools and a new session's config from the functions that grew around them (RMK-307)
  • fix(ai): the catalogue tags only what was checked on the wire, the turn outranks a same-named setting, and OpenRouter sends only the switch-off on tool turns, per review (RMK-319)
  • perf(ai): a turn with tools gets the turn's reasoning settings, with what OpenAI accepts there read from its catalogue (RMK-319)
  • fix(ai): a held tool called unreferenced references itself, and a fallback or a compaction declares what references opened, per review (RMK-330)
  • perf(ai): on Anthropic, a tool that has to appear mid-turn is held unseen and referenced, so the prompt cache survives it (RMK-330)
  • fix(ai): the turn's notes ask nothing of any input above them, and name speakers too, per review (RMK-318)
  • refactor(ai): extract the turn's messages, its history and its input, from _build_context (RMK-318)
  • refactor(tools): extract what the model reads of a call from _run_one (RMK-330)
  • docs(plan): ON_PLAN_UPDATED fires as an async hook, it is not a reserved value (RMK-318)
  • feat(benchmarks): the cost suite prices a steady turn and a long history too (RMK-318)
  • perf(ai): the system prompt holds from turn to turn, and the room's notes ride the turn's input (RMK-318)
  • fix(ai): the generation hook sees the re-read tool only once a result is stored, and the rounds declare it last, per review (RMK-317)
  • perf(ai): a turn's tool declaration holds from round to round, so a provider's prompt cache does (RMK-317)
  • refactor(benchmarks): one registry names the suites, the cost report splits its tables, per review (RMK-329)
  • fix(hooks): every kit hook callback builds the room's context only for a registered hook, per review (RMK-316)
  • refactor(ai): extract what the channel's own features add to a turn from _build_context (RMK-317)
  • feat(benchmarks): a cost suite plays scripted tool rounds billed by the real provider (RMK-329)
  • fix(hooks): BEFORE_TOOL_USE builds the room's context only when a hook will read it (RMK-316)
  • refactor(benchmarks): extract the suite's scenario catalogue from main (RMK-329)
  • fix(realtime): the skills preamble says scripts cannot run when the tool policy denies them (RMK-290)
  • docs(changelog): precise the call-reading, turn-end and eviction entries, and the docstrings that stated them, per review (RMK-303)
  • docs(changelog): the unreleased entries agree with the code at HEAD (RMK-303)
  • fix(streaming): a stream reads the room's status at its first row and again after its hooks, per review (RMK-302)
  • fix(tools): a malformed call is told after text too and on schema turns, a spoken call's anchors hold, and the fence takes every closing spelling, per review (RMK-314)
  • perf(streaming): a stream reads the room's status once, not once per row (RMK-302)
  • fix(hooks): a BEFORE_TOOL_USE refusal tells a hook's failure from a deliberate block, and external handlers refuse in the same words, per review (RMK-313)
  • fix(tools): data cannot close its own block, a spoken call runs only when said as one, and a malformed call is told to the model (RMK-314)
  • fix(providers): xAI and Gemini Live count the thinking they bill as output, per review (RMK-312)
  • fix(hooks): BEFORE_TOOL_USE fails closed, and the refusal reads the same on every channel without the hook's error (RMK-313)
  • fix(providers): a streamed turn reports its usage by default, and Gemini counts the thinking it bills (RMK-312)
  • fix(delivery): a background result is handed back as an instruction through deliver(), so the strategy and delivery hooks gate it, per review (RMK-310)
  • fix(realtime): a live reconfigure keeps only the provider config it applied, per review (RMK-311)
  • fix(tools): a raised call is a failed call wherever the model reads it, its detail reaches the observers on every path, and orchestration reads a failed task without its error, per review (RMK-295)
  • fix(orchestration): a delegation's result reaches the notified agent as an instruction, never through its prompt, and the supervisor's pass-1 instruction stays in its turn (RMK-310)
  • fix(realtime): xAI reconfigures a live session in band like OpenAI, and PersonaPlex and Anam declare they cannot (RMK-311)
  • fix(tools): a tool that raised reads as its failure and exception class on every channel, its message going to logs and observers only (RMK-295)
  • fix(tools): one declaration rule on every entry, the delegation gate, the realtime gate's schema, the generation hook and the conference, through one shared module, per review (RMK-294)
  • fix(ai): find_tools never names a tool the generation hook added, both loops prepare their first round alike, and the declared-tool check is its own step, per review (RMK-293)
  • fix(tools): a name a channel serves is declared once with its own definition, a static host tool under it is refused, and no name is declared twice (RMK-294)
  • fix(tools): the policy exemption covers the tool the channel serves itself, not a name, on every path (RMK-294)
  • fix(ai): under Tool Search a generation hook sees the whole catalogue, a tool it withdraws is gone and one it adds stays declared, and nothing undeclared is callable (RMK-293)
  • fix(tools): a firing on a call the model already read is a report, for a provider-run call and a realtime Tool Search call alike, per review (RMK-292)
  • fix(core): a delegated turn reads every response its broadcast started, not only the first to answer (RMK-291)
  • fix(core): a delegated streamed turn records its end when it fails and closes its response when cancelled, through one drain shared with a headless turn, per review (RMK-291)
  • fix(tools): an ON_TOOL_CALL hook that clears a result replaces it on every channel, and observers see what the model reads (RMK-292)
  • fix(core): a delegated turn's streamed trace closes its open calls and keeps its structured copy, through the room's writer (RMK-291)
  • refactor(core): a streamed turn's rows commit through a sink, and the writer owns the read loop and what a cut-short turn leaves (RMK-291)
  • refactor(core): one builder for an unanswered record, one test for a tool-call row, and the transcription mixin owns its session state, per review (RMK-287)
  • fix(core): the caller is handed every answer of its chain, a regenerated answer keeps its scope, and a child room keeps what its broadcast blocked, per review (RMK-287)
  • refactor(core): extract the turn's tool context, the caller's message fields and the supervisor's results event, and read a background task's depth from the call that started it (RMK-287)
  • docs(changelog): streamed agent chains, the depth limit that asks no agent, and bounded delegation cycles (RMK-287)
  • fix(core): a regeneration stores and announces what its broadcast blocked, with its side effects, as the inbound path does (RMK-287)
  • fix(tasks): a result delivered for a turn that delegated continues its chain, so a delegation cycle ends at max_chain_depth (RMK-287)
  • fix(realtime): a realtime answer, a loop result and a supervisor's answer carry their trigger's depth plus one instead of restarting the chain (RMK-287)
  • refactor(realtime): extract storing a final transcription from the transcription step (RMK-287)
  • fix(events): a response any pass starts is read, so a streamed segment, a greeting and a regenerated answer wake the other agents under one chain (RMK-287)
  • refactor(core): extract what a regeneration does off the room lock from regenerate_response (RMK-287)
  • fix(events): past max_chain_depth no agent is asked, streamed or buffered, and one BLOCKED record stands in for its answer (RMK-287)
  • refactor(events): extract what an unasked intelligence target leaves from the router's per-target step (RMK-287)
  • refactor(ai): an interrupted turn has no answer to hand on, and every streamed turn records its end, per review (RMK-289)
  • fix(realtime): an OpenAI caller's turn is answered after the response in its way, and a rejected request frees the session (RMK-288)
  • fix(realtime): a Gemini reconfiguration runs to its end and its instruction takes effect (RMK-288)
  • fix(voice): a playback caller keeps its cancellation when the stream feeder swallows it (RMK-288)
  • fix(ai): both tool loops record and report the end of a turn alike (RMK-289)
  • fix(realtime): every session of a Gemini 3.8 room takes the new agent after a handoff (RMK-288)
  • fix(realtime): wait_idle opens once a tool call that owes nothing ends (RMK-288)
  • fix(realtime): an OpenAI continuation waits for the caller and never doubles a request (RMK-288)
  • fix(core): a cancelled caller is no longer resumed by the task it tears down (RMK-288)
  • test: the streamed-metadata divergence names its card (RMK-289)
  • fix(events): a closed room refuses a streamed row, as it refuses every write (RMK-283)
  • fix(ai): the external tool path refuses a partial call instead of handing it on (RMK-284)
  • fix(ai): an aborted tool round publishes the END of every call it started (RMK-282)
  • fix(realtime): realtime providers read a call's arguments the shared way (RMK-284)
  • fix(gemini): a Live receive loop runs in a context of its own, not its starter's (RMK-280)
  • fix(tools): a released eviction id is never given again, and the store's bound spares a quiet room (RMK-285)
  • fix(tools): a stored large result stays readable while its room works, under its own id (RMK-285)
  • fix(providers): a reasoning backend does not run a partial call, and id-less calls on one index stay apart (RMK-284)
  • fix(providers): every provider hands the tool loop the same call (RMK-284)
  • fix(events): a blocked stream records its observation where it is read, one per row (RMK-283)
  • fix(events): the chain-depth limit blocks a streamed response too (RMK-283)
  • fix(ai): an unfinished turn's span keeps its usage, and a closed call's end reaches the streaming channel (RMK-282)
  • fix(ai): a turn that did not complete reports nothing, and a stop keeps a round's tools from running (RMK-282)
  • fix(gemini): a refused declaration is not an overflow, and an enum keeps its null and shared type (RMK-281)
  • fix(gemini): a tool with a non-string enum is declarable, and a refused declaration names its tool (RMK-281)
  • fix(realtime): a spared call's record ends with the call (RMK-280)
  • fix(realtime): a reconnect a tool call's own handler caused does not abandon that call (RMK-280)
  • fix(realtime): a requested continuation counts as the response in progress (RMK-279)
  • fix(realtime): OpenAI Realtime and xAI ask the model to go on once per response (RMK-279)
  • fix(ai): a turn the provider interrupts after a round is an error that keeps its rounds (RMK-156)
  • fix(ai): a turn cut short no longer replays the room's history (RMK-156)
  • fix(tools): a chain of not-mine answers served nothing, content parts may come as mappings, and a call has one outcome (RMK-278)
  • fix(tools): a handler's answer reaches the model as JSON, and the channel's own outcomes are refusals (RMK-278)
  • fix(tools): find_tools does not name an orchestration tool, and declared_tools reports it always (RMK-277)
  • fix(tools): Tool Search keeps the tools orchestration injects declared (RMK-277)
  • fix(orchestration): a strategy's tools stay in the rooms it was installed in, and an agent tool without a handler falls to the channel's (RMK-276)
  • fix(orchestration): a strategy installed in several rooms keeps what it adds per room (RMK-276)
  • fix(realtime): a recovered spoken tool call runs its handler in the tool call context (RMK-275)
  • fix(supervisor): a supervisor serving several rooms keeps their delegations apart (RMK-275)
  • fix(orchestration): the orchestration examples run again, and the call's room is resolved in one place (RMK-275)
  • fix(orchestration): a handoff or a delegation acts on the room of its call (RMK-275)
  • refactor(realtime): the realtime tool gate runs as named steps, and a backend is offered only the tools it may call (RMK-286)
  • fix(realtime): a tool policy keeps Tool Search's call_tool, audits a backend's refusals and reads the role at each call (RMK-286)
  • fix(conference): a refused tool call is reported once sent, a cancellation adds no second outcome (RMK-274)
  • feat(realtime): RealtimeVoiceChannel and a conference's provider take a tool_policy (RMK-286)
  • fix(conference): the realtime provider's tool calls pass the tool gate (RMK-274)
  • fix(hooks): an unusable MODIFY keeps ON_TOOL_CALL's chain, external reports stay the provider's, and a cold digest keeps the model's arguments, per review (RMK-273)
  • fix(tools): a withdrawn channel tool is refused, and a realtime activation rechecks its required tools, per review (RMK-272)
  • fix(hooks): ON_TOOL_CALL's sync hooks chain on one result, observers see the final one, and the digest keeps the model's arguments (RMK-273)
  • fix(realtime): skill tools run ON_TOOL_CALL before their result is sent (RMK-272)
  • fix(ai): a tool a BEFORE_AI_GENERATION hook removes stays removed, and a blocked activate_skill opens no gate (RMK-272)
  • fix(tools): Tool Search, the prompt and sandbox routing name no tool the policy closes, per review (RMK-271)
  • refactor(tools): tidy the dual-mode tool-loop tests per review (RMK-270)
  • fix(tools): ToolPolicy governs sandbox and skill-script tools, and Tool Search names no denied tool (RMK-271)
  • test(tools): the tool-loop tests run in both generation modes (RMK-270)
  • fix(ai): the non-streaming tool loop stores the arguments a call ran with (RMK-270)
  • refactor(gemini): tidy the schema cleaner's shape rules per review (RMK-266)
  • fix(gemini): a tool schema's implied type and missing items reach Gemini spelled out (RMK-266)
  • refactor(gemini): tidy the refining-union rule per review (RMK-266)
  • feat(tts): ElevenLabs streams its text input over WebSocket, opt-in (RMK-265)
  • fix(tts): ElevenLabs optimize_streaming_latency reaches the API again (RMK-264)
  • fix(gemini): a union that narrows an object no longer replaces it in a tool schema (RMK-266)
  • feat(tts): ElevenLabs expressive mode runs on Eleven v4 Turbo (RMK-263)
  • fix(hooks): a fail-closed ON_TOOL_CALL hook withholds the result when the room's context cannot be built (RMK-262)
  • refactor(ai): tidy the ON_TOOL_CALL verdict per review (RMK-262)
  • fix(ai): a blocked ON_TOOL_CALL drops the call's structured copy, and the hook can rewrite it (RMK-262)
  • refactor(ai): tidy the TOOL_CALL_END image bound per review (RMK-261)
  • fix(ai): the TOOL_CALL_END image bound holds in any result shape (RMK-261)
  • refactor(ai): tidy the ON_TOOL_CALL ordering per review (RMK-260)
  • fix(ai): a TOOL_CALL_END event keeps a bounded share of a result's images (RMK-260)
  • fix(ai): ON_TOOL_CALL sees a tool's whole result and eviction stores its rewrite (RMK-260)
  • docs(ai): a text-only model gets the text of a content-part tool result (RMK-259)
  • refactor(ai): tidy tool-result eviction per review (RMK-259)
  • fix(ai): the tool-usage digest keeps the text of a part list rebuilt from history (RMK-259)
  • fix(ai): a text-only model gets the text of a content-part tool result (RMK-259)
  • fix(tools): an MCP image reaches the model only when a vendor can take it (RMK-259)
  • fix(ai): the identical-result note recognises an evicted answer (RMK-259)
  • docs(ai): every tool outcome the model reads goes through eviction (RMK-259)
  • fix(tools): the MCP tool handler hands an image to the model as an image (RMK-259)
  • fix(memory): the token estimate counts the images of a tool result (RMK-259)
  • fix(ai): a refusal, an error and a hook override are evicted like a result (RMK-259)
  • fix(ai): the text of a content-part tool result is evicted, its images kept (RMK-259)
  • refactor(ai): the eviction preview shows the last line of a short result too, per review (RMK-258)
  • fix(ai): read_stored_result advertises the default line limit it applies (RMK-258)
  • fix(ai): the eviction preview is bounded in characters, not only in lines (RMK-258)
  • docs(ai): name the re-read tool read_stored_result, the name it is registered under (RMK-258)
  • fix(providers): a Meta API key no HTTP header can carry is refused when the config is built (RMK-257)
  • fix(voice): the diarization stage fires no speaker change for a voice it matched to nobody (RMK-256)
  • Begin 0.93.0.dev0 development

Full Changelog: v0.92.0...v0.93.0