Skip to content

chore: release v0.42.0 - #2221

Open
github-actions[bot] wants to merge 1 commit into
mainfrom
release-plz-2026-07-28T10-35-22Z
Open

chore: release v0.42.0#2221
github-actions[bot] wants to merge 1 commit into
mainfrom
release-plz-2026-07-28T10-35-22Z

Conversation

@github-actions

@github-actions github-actions Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

🤖 New release

  • rig-derive: 0.41.0 -> 0.42.0
  • rig-core: 0.41.0 -> 0.42.0 (⚠ API breaking changes)
  • rig-agent: 0.41.0 -> 0.42.0 (⚠ API breaking changes)
  • rig-bedrock: 0.41.0 -> 0.42.0 (✓ API compatible changes)
  • rig-candle: 0.41.0 -> 0.42.0 (✓ API compatible changes)
  • rig-fastembed: 0.41.0 -> 0.42.0
  • rig-gemini-grpc: 0.41.0 -> 0.42.0 (✓ API compatible changes)
  • rig-helixdb: 0.41.0 -> 0.42.0 (✓ API compatible changes)
  • rig-lancedb: 0.41.0 -> 0.42.0 (✓ API compatible changes)
  • rig-memory: 0.41.0 -> 0.42.0 (✓ API compatible changes)
  • rig-milvus: 0.41.0 -> 0.42.0 (✓ API compatible changes)
  • rig-mongodb: 0.41.0 -> 0.42.0 (✓ API compatible changes)
  • rig-neo4j: 0.41.0 -> 0.42.0 (✓ API compatible changes)
  • rig-postgres: 0.41.0 -> 0.42.0 (✓ API compatible changes)
  • rig-qdrant: 0.41.0 -> 0.42.0 (✓ API compatible changes)
  • rig-s3vectors: 0.41.0 -> 0.42.0 (✓ API compatible changes)
  • rig-scylladb: 0.41.0 -> 0.42.0 (✓ API compatible changes)
  • rig-sqlite: 0.41.0 -> 0.42.0 (✓ API compatible changes)
  • rig-surrealdb: 0.41.0 -> 0.42.0 (✓ API compatible changes)
  • rig-vectorize: 0.41.0 -> 0.42.0 (✓ API compatible changes)
  • rig-vertexai: 0.41.0 -> 0.42.0 (⚠ API breaking changes)
  • rig: 0.41.0 -> 0.42.0 (✓ API compatible changes)

rig-core breaking changes

--- failure constructible_struct_adds_field: externally-constructible struct adds field ---

Description:
A pub struct constructible with a struct literal has a new pub field. Existing struct literals must be updated to include the new field.
        ref: https://doc.rust-lang.org/reference/expressions/struct-expr.html
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/constructible_struct_adds_field.ron

Failed in:
  field StreamingCompletionResponse.response_id in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/gemini/streaming.rs:146
  field StreamingCompletionResponse.stop_reason in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/anthropic/streaming.rs:504
  field StreamingCompletionResponse.message_id in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/anthropic/streaming.rs:507
  field StreamingCompletionResponse.model in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/anthropic/streaming.rs:510
  field StreamingCompletionResponse.model in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/ollama.rs:625
  field ToolCall.provider in /tmp/.tmpzNVzck/rig/crates/rig-core/src/completion/message.rs:588
  field ToolCall.provider in /tmp/.tmpzNVzck/rig/crates/rig-core/src/completion/message.rs:588
  field CompletionResponse.incomplete_details in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/xai/completion.rs:149
  field CompletionResponse.incomplete_details in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/xai/completion.rs:149
  field StreamingCompletionResponse.finish_reason in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/cohere/streaming.rs:112
  field StreamingCompletionResponse.message_id in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/cohere/streaming.rs:115
  field StreamingCompletionResponse.status in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/openai/responses_api/streaming.rs:61
  field StreamingCompletionResponse.incomplete_details in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/openai/responses_api/streaming.rs:64
  field StreamingCompletionResponse.message_id in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/openai/responses_api/streaming.rs:71
  field StreamingCompletionResponse.response_id in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/openai/responses_api/streaming.rs:75
  field StreamingCompletionResponse.model in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/openai/responses_api/streaming.rs:78
  field ToolResult.call in /tmp/.tmpzNVzck/rig/crates/rig-core/src/completion/message.rs:286
  field ToolResult.provider in /tmp/.tmpzNVzck/rig/crates/rig-core/src/completion/message.rs:290
  field ToolResult.name in /tmp/.tmpzNVzck/rig/crates/rig-core/src/completion/message.rs:299
  field ToolResult.call in /tmp/.tmpzNVzck/rig/crates/rig-core/src/completion/message.rs:286
  field ToolResult.provider in /tmp/.tmpzNVzck/rig/crates/rig-core/src/completion/message.rs:290
  field ToolResult.name in /tmp/.tmpzNVzck/rig/crates/rig-core/src/completion/message.rs:299
  field StreamingCompletionResponse.finish_reason in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/openai/completion/streaming.rs:171
  field StreamingCompletionResponse.response_id in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/openai/completion/streaming.rs:174
  field StreamingCompletionResponse.model in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/openai/completion/streaming.rs:177
  field StreamingCompletionResponse.finish_reason in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/openai/completion/streaming.rs:171
  field StreamingCompletionResponse.response_id in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/openai/completion/streaming.rs:174
  field StreamingCompletionResponse.model in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/openai/completion/streaming.rs:177
  field StreamingCompletionResponse.finish_reason in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/openai/completion/streaming.rs:171
  field StreamingCompletionResponse.response_id in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/openai/completion/streaming.rs:174
  field StreamingCompletionResponse.model in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/openai/completion/streaming.rs:177
  field RawStreamingToolCall.tool_id in /tmp/.tmpzNVzck/rig/crates/rig-core/src/streaming/mod.rs:690
  field ToolCall.id in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/ollama.rs:1104

--- failure enum_discriminants_undefined_non_unit_variant: enum's variants no longer have defined discriminants due to non-unit variant ---

Description:
An enum's variants no longer have well-defined discriminant values due to a tuple or struct variant in the enum. This breaks downstream code that accesses discriminants via a numeric cast like `as isize`.
        ref: https://doc.rust-lang.org/reference/items/enumerations.html#assigning-discriminant-values
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/enum_discriminants_undefined_non_unit_variant.ron

Failed in:
  enum BlockReason in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/gemini/completion.rs:1490
  enum FinishReason in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/gemini/completion.rs:1510
  enum InteractionStatus in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/gemini/interactions_api/mod.rs:1289
  enum InteractionStatus in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/gemini/interactions_api/mod.rs:1289
  enum FinishReason in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/cohere/completion.rs:92

--- failure enum_struct_variant_field_added: pub enum struct variant field added ---

Description:
An enum's exhaustive struct variant has a new field, which has to be included when constructing or matching on this variant.
        ref: https://doc.rust-lang.org/reference/attributes/type_system.html#the-non_exhaustive-attribute
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/enum_struct_variant_field_added.ron

Failed in:
  field id of variant RawStreamingChoice::TextStart in /tmp/.tmpzNVzck/rig/crates/rig-core/src/streaming/mod.rs:456
  field provider_id of variant RawStreamingChoice::Reasoning in /tmp/.tmpzNVzck/rig/crates/rig-core/src/streaming/mod.rs:520
  field provider_id of variant RawStreamingChoice::ReasoningDelta in /tmp/.tmpzNVzck/rig/crates/rig-core/src/streaming/mod.rs:594
  field id of variant MockStreamEvent::TextStart in /tmp/.tmpzNVzck/rig/crates/rig-core/src/test_utils/streaming.rs:44
  field provider_id of variant StreamedAssistantContent::ReasoningDelta in /tmp/.tmpzNVzck/rig/crates/rig-core/src/streaming/mod.rs:2814

--- failure enum_struct_variant_field_missing: pub enum struct variant's field removed or renamed ---

Description:
A publicly-visible enum has a struct variant whose field is no longer available under its prior name. It may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/enum_struct_variant_field_missing.ron

Failed in:
  field internal_call_id of variant MockStreamEvent::ToolCallDelta, previously in file /tmp/.tmpNAKcBE/rig-core/src/test_utils/streaming.rs:65
  field id of variant StreamedAssistantContent::ToolCallDelta, previously in file /tmp/.tmpNAKcBE/rig-core/src/streaming.rs:972
  field internal_call_id of variant RawStreamingChoice::ToolCallDelta, previously in file /tmp/.tmpNAKcBE/rig-core/src/streaming.rs:100

--- failure enum_tuple_variant_changed_kind: An enum tuple variant changed kind ---

Description:
A public enum's exhaustive tuple variant has changed to a different kind of enum variant, breaking possible instantiations and patterns.
        ref: https://doc.rust-lang.org/reference/items/enumerations.html
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/enum_tuple_variant_changed_kind.ron

Failed in:
  variant StreamedAssistantContent::Reasoning in /tmp/.tmpzNVzck/rig/crates/rig-core/src/streaming/mod.rs:2794

--- failure enum_unit_variant_changed_kind: An enum unit variant changed kind ---

Description:
A public enum's exhaustive unit variant has changed to a different kind of enum variant, breaking possible instantiations and patterns.
        ref: https://doc.rust-lang.org/reference/items/enumerations.html
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/enum_unit_variant_changed_kind.ron

Failed in:
  variant ContentDelta::Unknown in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/anthropic/streaming.rs:175

--- failure enum_variant_added: enum variant added on exhaustive enum ---

Description:
A publicly-visible enum without #[non_exhaustive] has a new variant.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#enum-variant-new
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/enum_variant_added.ron

Failed in:
  variant StreamingEvent:Error in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/anthropic/streaming.rs:135
  variant BlockReason:Unknown in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/gemini/completion.rs:1505
  variant FinishReason:Unknown in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/gemini/completion.rs:1546
  variant FinishReason:Other in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/cohere/completion.rs:101
  variant ContentPartChunkPart:Unknown in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/openai/responses_api/streaming.rs:1386
  variant ContentDelta:ArgumentsDelta in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/gemini/interactions_api/mod.rs:2459
  variant ContentDelta:ArgumentsDelta in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/gemini/interactions_api/mod.rs:2459
  variant RawStreamingChoice:ToolInputEnd in /tmp/.tmpzNVzck/rig/crates/rig-core/src/streaming/mod.rs:501
  variant RawStreamingChoice:ReasoningStart in /tmp/.tmpzNVzck/rig/crates/rig-core/src/streaming/mod.rs:531
  variant RawStreamingChoice:ReasoningEnd in /tmp/.tmpzNVzck/rig/crates/rig-core/src/streaming/mod.rs:561
  variant RawStreamingChoice:TextEnd in /tmp/.tmpzNVzck/rig/crates/rig-core/src/streaming/mod.rs:580
  variant ResponsesWebSocketEvent:Unknown in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/openai/responses_api/websocket.rs:170
  variant InteractionStatus:Unknown in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/gemini/interactions_api/mod.rs:1301
  variant InteractionStatus:Unknown in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/gemini/interactions_api/mod.rs:1301
  variant ItemChunkKind:ReasoningTextDone in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/openai/responses_api/streaming.rs:1348

--- failure enum_variant_missing: pub enum variant removed or renamed ---

Description:
A publicly-visible enum has at least one variant that is no longer available under its prior name. It may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/enum_variant_missing.ron

Failed in:
  variant StreamingEvent::Unknown, previously in file /tmp/.tmpNAKcBE/rig-core/src/providers/anthropic/streaming.rs:103
  variant ItemChunkKind::Unknown, previously in file /tmp/.tmpNAKcBE/rig-core/src/providers/openai/responses_api/streaming.rs:772

--- failure function_missing: pub fn removed or renamed ---

Description:
A publicly-visible function cannot be imported by its prior path. A `pub use` may have been removed, or the function itself may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/function_missing.ron

Failed in:
  function rig_core::one_or_many::string_or_option_one_or_many, previously in file /tmp/.tmpNAKcBE/rig-core/src/one_or_many.rs:433
  function rig_core::one_or_many::string_or_one_or_many, previously in file /tmp/.tmpNAKcBE/rig-core/src/one_or_many.rs:381

--- failure function_parameter_count_changed: pub fn parameter count changed ---

Description:
A publicly-visible function now takes a different number of parameters.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#fn-change-arity
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/function_parameter_count_changed.ron

Failed in:
  rig_core::providers::openai::completion::streaming::send_compatible_streaming_request now takes 3 parameters instead of 2, in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/openai/completion/streaming.rs:461
  rig_core::providers::openai::streaming::send_compatible_streaming_request now takes 3 parameters instead of 2, in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/openai/completion/streaming.rs:461
  rig_core::providers::openai::send_compatible_streaming_request now takes 3 parameters instead of 2, in /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/openai/completion/streaming.rs:461

--- failure inherent_method_missing: pub method removed or renamed ---

Description:
A publicly-visible method or associated fn is no longer available under its prior name. It may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/inherent_method_missing.ron

Failed in:
  ToolCall::with_call_id, previously in file /tmp/.tmpNAKcBE/rig-core/src/completion/message.rs:307
  ToolCall::with_call_id, previously in file /tmp/.tmpNAKcBE/rig-core/src/completion/message.rs:307
  Message::tool_result_with_call_id, previously in file /tmp/.tmpNAKcBE/rig-core/src/completion/message.rs:690
  Message::tool_result_with_call_id, previously in file /tmp/.tmpNAKcBE/rig-core/src/completion/message.rs:690
  Message::tool_result_with_call_id, previously in file /tmp/.tmpNAKcBE/rig-core/src/completion/message.rs:690
  Message::tool_result_with_call_id, previously in file /tmp/.tmpNAKcBE/rig-core/src/completion/message.rs:690

--- failure method_parameter_count_changed: pub method parameter count changed ---

Description:
A publicly-visible method now takes a different number of parameters, not counting the receiver (self) parameter.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#fn-change-arity
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/method_parameter_count_changed.ron

Failed in:
  rig_core::streaming::StreamingCompletionResponse::stream takes 1 parameters in /tmp/.tmpNAKcBE/rig-core/src/streaming.rs:260, but now takes 2 parameters in /tmp/.tmpzNVzck/rig/crates/rig-core/src/streaming/mod.rs:925
  rig_core::completion::message::UserContent::tool_result takes 2 parameters in /tmp/.tmpNAKcBE/rig-core/src/completion/message.rs:837, but now takes 3 parameters in /tmp/.tmpzNVzck/rig/crates/rig-core/src/completion/message.rs:1536
  rig_core::completion::message::UserContent::tool_result_with_call_id takes 3 parameters in /tmp/.tmpNAKcBE/rig-core/src/completion/message.rs:846, but now takes 4 parameters in /tmp/.tmpzNVzck/rig/crates/rig-core/src/completion/message.rs:1590
  rig_core::message::UserContent::tool_result takes 2 parameters in /tmp/.tmpNAKcBE/rig-core/src/completion/message.rs:837, but now takes 3 parameters in /tmp/.tmpzNVzck/rig/crates/rig-core/src/completion/message.rs:1536
  rig_core::message::UserContent::tool_result_with_call_id takes 3 parameters in /tmp/.tmpNAKcBE/rig-core/src/completion/message.rs:846, but now takes 4 parameters in /tmp/.tmpzNVzck/rig/crates/rig-core/src/completion/message.rs:1590
  rig_core::test_utils::MockStreamEvent::text_start takes 1 parameters in /tmp/.tmpNAKcBE/rig-core/src/test_utils/streaming.rs:97, but now takes 2 parameters in /tmp/.tmpzNVzck/rig/crates/rig-core/src/test_utils/streaming.rs:113
  rig_core::test_utils::MockStreamEvent::tool_call_name_delta takes 3 parameters in /tmp/.tmpNAKcBE/rig-core/src/test_utils/streaming.rs:129, but now takes 2 parameters in /tmp/.tmpzNVzck/rig/crates/rig-core/src/test_utils/streaming.rs:148
  rig_core::test_utils::MockStreamEvent::tool_call_arguments_delta takes 3 parameters in /tmp/.tmpNAKcBE/rig-core/src/test_utils/streaming.rs:142, but now takes 2 parameters in /tmp/.tmpzNVzck/rig/crates/rig-core/src/test_utils/streaming.rs:156
  rig_core::test_utils::MockStreamEvent::reasoning_delta takes 2 parameters in /tmp/.tmpNAKcBE/rig-core/src/test_utils/streaming.rs:174, but now takes 1 parameters in /tmp/.tmpzNVzck/rig/crates/rig-core/src/test_utils/streaming.rs:187
  rig_core::completion::message::Message::tool_result takes 2 parameters in /tmp/.tmpNAKcBE/rig-core/src/completion/message.rs:680, but now takes 3 parameters in /tmp/.tmpzNVzck/rig/crates/rig-core/src/completion/message.rs:1378
  rig_core::message::Message::tool_result takes 2 parameters in /tmp/.tmpNAKcBE/rig-core/src/completion/message.rs:680, but now takes 3 parameters in /tmp/.tmpzNVzck/rig/crates/rig-core/src/completion/message.rs:1378
  rig_core::completion::Message::tool_result takes 2 parameters in /tmp/.tmpNAKcBE/rig-core/src/completion/message.rs:680, but now takes 3 parameters in /tmp/.tmpzNVzck/rig/crates/rig-core/src/completion/message.rs:1378
  rig_core::prelude::Message::tool_result takes 2 parameters in /tmp/.tmpNAKcBE/rig-core/src/completion/message.rs:680, but now takes 3 parameters in /tmp/.tmpzNVzck/rig/crates/rig-core/src/completion/message.rs:1378

--- failure module_missing: pub module removed or renamed ---

Description:
A publicly-visible module cannot be imported by its prior path. A `pub use` may have been removed, or the module may have been renamed, removed, or made non-public.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/module_missing.ron

Failed in:
  mod rig_core::one_or_many, previously in file /tmp/.tmpNAKcBE/rig-core/src/one_or_many.rs:1

--- failure struct_marked_non_exhaustive: struct marked #[non_exhaustive] ---

Description:
A public struct has been marked #[non_exhaustive], which will prevent it from being constructed using a struct literal outside of its crate. It previously had no private fields, so a struct literal could be used to construct it outside its crate.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#attr-adding-non-exhaustive
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/struct_marked_non_exhaustive.ron

Failed in:
  struct CompletionResponse in /tmp/.tmpzNVzck/rig/crates/rig-core/src/completion/request.rs:277
  struct CompletionResponse in /tmp/.tmpzNVzck/rig/crates/rig-core/src/completion/request.rs:277

--- failure struct_missing: pub struct removed or renamed ---

Description:
A publicly-visible struct cannot be imported by its prior path. A `pub use` may have been removed, or the struct itself may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/struct_missing.ron

Failed in:
  struct rig_core::test_utils::MockResponse, previously in file /tmp/.tmpNAKcBE/rig-core/src/test_utils/streaming.rs:12
  struct rig_core::one_or_many::IterMut, previously in file /tmp/.tmpNAKcBE/rig-core/src/one_or_many.rs:273
  struct rig_core::one_or_many::Iter, previously in file /tmp/.tmpNAKcBE/rig-core/src/one_or_many.rs:193
  struct rig_core::one_or_many::EmptyListError, previously in file /tmp/.tmpNAKcBE/rig-core/src/one_or_many.rs:25
  struct rig_core::EmptyListError, previously in file /tmp/.tmpNAKcBE/rig-core/src/one_or_many.rs:25
  struct rig_core::one_or_many::IntoIter, previously in file /tmp/.tmpNAKcBE/rig-core/src/one_or_many.rs:224
  struct rig_core::one_or_many::OneOrMany, previously in file /tmp/.tmpNAKcBE/rig-core/src/one_or_many.rs:15
  struct rig_core::prelude::OneOrMany, previously in file /tmp/.tmpNAKcBE/rig-core/src/one_or_many.rs:15
  struct rig_core::OneOrMany, previously in file /tmp/.tmpNAKcBE/rig-core/src/one_or_many.rs:15

--- failure struct_pub_field_missing: pub struct's pub field removed or renamed ---

Description:
A publicly-visible struct has at least one public field that is no longer available under its prior name. It may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/struct_pub_field_missing.ron

Failed in:
  field id of struct ToolResult, previously in file /tmp/.tmpNAKcBE/rig-core/src/completion/message.rs:213
  field call_id of struct ToolResult, previously in file /tmp/.tmpNAKcBE/rig-core/src/completion/message.rs:216
  field id of struct ToolResult, previously in file /tmp/.tmpNAKcBE/rig-core/src/completion/message.rs:213
  field call_id of struct ToolResult, previously in file /tmp/.tmpNAKcBE/rig-core/src/completion/message.rs:216
  field call_id of struct ToolCall, previously in file /tmp/.tmpNAKcBE/rig-core/src/completion/message.rs:279
  field call_id of struct ToolCall, previously in file /tmp/.tmpNAKcBE/rig-core/src/completion/message.rs:279
  field raw_response of struct CompletionResponse, previously in file /tmp/.tmpNAKcBE/rig-core/src/completion/request.rs:220
  field raw_response of struct CompletionResponse, previously in file /tmp/.tmpNAKcBE/rig-core/src/completion/request.rs:220

--- failure trait_method_default_impl_removed: pub trait default method impl removed ---

Description:
A method's default impl in an unsealed trait has been removed, breaking trait implementations that relied on that default
        ref: https://doc.rust-lang.org/book/ch10-02-traits.html#default-implementations
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/trait_method_default_impl_removed.ron

Failed in:
  trait method rig_core::client::completion::CompletionClient::completion_model in file /tmp/.tmpzNVzck/rig/crates/rig-core/src/client/completion.rs:30
  trait method rig_core::client::CompletionClient::completion_model in file /tmp/.tmpzNVzck/rig/crates/rig-core/src/client/completion.rs:30
  trait method rig_core::prelude::CompletionClient::completion_model in file /tmp/.tmpzNVzck/rig/crates/rig-core/src/client/completion.rs:30

--- failure trait_method_missing: pub trait method removed or renamed ---

Description:
A trait method is no longer callable, and may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#trait-item-signature
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/trait_method_missing.ron

Failed in:
  method make of trait CompletionModel, previously in file /tmp/.tmpNAKcBE/rig-core/src/completion/request.rs:354
  method composes_native_output_with_tools of trait CompletionModel, previously in file /tmp/.tmpNAKcBE/rig-core/src/completion/request.rs:385
  method make of trait CompletionModel, previously in file /tmp/.tmpNAKcBE/rig-core/src/completion/request.rs:354
  method composes_native_output_with_tools of trait CompletionModel, previously in file /tmp/.tmpNAKcBE/rig-core/src/completion/request.rs:385
  method make of trait CompletionModel, previously in file /tmp/.tmpNAKcBE/rig-core/src/completion/request.rs:354
  method composes_native_output_with_tools of trait CompletionModel, previously in file /tmp/.tmpNAKcBE/rig-core/src/completion/request.rs:385

--- failure trait_method_parameter_count_changed: pub trait method parameter count changed ---

Description:
A trait method now takes a different number of parameters.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#trait-item-signature
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/trait_method_parameter_count_changed.ron

Failed in:
  OpenAICompatibleProvider::decorate_streaming_tool_call now takes 1 instead of 2 parameters, in file /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/openai/completion/mod.rs:1571
  OpenAICompatibleProvider::decorate_streaming_tool_call now takes 1 instead of 2 parameters, in file /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/openai/completion/mod.rs:1571

--- failure trait_method_requires_different_generic_type_params: trait method now requires a different number of generic type parameters ---

Description:
A trait method now requires a different number of generic type parameters than it used to. Calls or implementations of this trait method using the previous number of generic types will be broken.
        ref: https://doc.rust-lang.org/reference/items/generics.html
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/trait_method_requires_different_generic_type_params.ron

Failed in:
  SpanCombinator::record_token_usage (1 -> 0 generic types) in /tmp/.tmpzNVzck/rig/crates/rig-core/src/telemetry/mod.rs:770

--- failure trait_method_return_value_added: pub trait method return value added ---

Description:
A trait method that previously returned `()` now returns a value. Since the trait is not sealed, downstream implementations of the trait will get compile errors.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#trait-item-signature
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/trait_method_return_value_added.ron

Failed in:
  rig_core::providers::openai::completion::OpenAICompatibleProvider::decorate_streaming_tool_call in file /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/openai/completion/mod.rs:1571
  rig_core::providers::openai::OpenAICompatibleProvider::decorate_streaming_tool_call in file /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/openai/completion/mod.rs:1571

--- failure trait_missing: pub trait removed or renamed ---

Description:
A publicly-visible trait cannot be imported by its prior path. A `pub use` may have been removed, or the trait itself may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/trait_missing.ron

Failed in:
  trait rig_core::completion::request::GetTokenUsage, previously in file /tmp/.tmpNAKcBE/rig-core/src/completion/request.rs:229
  trait rig_core::completion::GetTokenUsage, previously in file /tmp/.tmpNAKcBE/rig-core/src/completion/request.rs:229

--- failure trait_no_longer_dyn_compatible: trait no longer dyn compatible ---

Description:
Trait is no longer dyn compatible, which breaks `dyn Trait` usage.
        ref: https://doc.rust-lang.org/stable/reference/items/traits.html#object-safety
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/trait_no_longer_dyn_compatible.ron

Failed in:
  trait ResponsesProviderExt in file /tmp/.tmpzNVzck/rig/crates/rig-core/src/providers/openai/responses_api/mod.rs:1191

--- failure trait_removed_associated_type: trait's associated type was removed ---

Description:
A public trait's associated type was removed or renamed.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/trait_removed_associated_type.ron

Failed in:
  associated type CompletionModel::Response, previously at /tmp/.tmpNAKcBE/rig-core/src/completion/request.rs:340
  associated type CompletionModel::StreamingResponse, previously at /tmp/.tmpNAKcBE/rig-core/src/completion/request.rs:342
  associated type CompletionModel::Client, previously at /tmp/.tmpNAKcBE/rig-core/src/completion/request.rs:351
  associated type CompletionModel::Response, previously at /tmp/.tmpNAKcBE/rig-core/src/completion/request.rs:340
  associated type CompletionModel::StreamingResponse, previously at /tmp/.tmpNAKcBE/rig-core/src/completion/request.rs:342
  associated type CompletionModel::Client, previously at /tmp/.tmpNAKcBE/rig-core/src/completion/request.rs:351
  associated type CompletionModel::Response, previously at /tmp/.tmpNAKcBE/rig-core/src/completion/request.rs:340
  associated type CompletionModel::StreamingResponse, previously at /tmp/.tmpNAKcBE/rig-core/src/completion/request.rs:342
  associated type CompletionModel::Client, previously at /tmp/.tmpNAKcBE/rig-core/src/completion/request.rs:351

--- failure type_allows_fewer_generic_type_params: type now allows fewer generic type parameters ---

Description:
A type now allows fewer generic type parameters than it used to. Uses of this type that supplied all previously-supported generic types will be broken.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#trait-new-parameter-no-default
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/type_allows_fewer_generic_type_params.ron

Failed in:
  Struct StreamingCompletionResponse allows 1 -> 0 generic types in /tmp/.tmpzNVzck/rig/crates/rig-core/src/streaming/mod.rs:876
  Struct CompletionResponse allows 1 -> 0 generic types in /tmp/.tmpzNVzck/rig/crates/rig-core/src/completion/request.rs:277
  Struct CompletionResponse allows 1 -> 0 generic types in /tmp/.tmpzNVzck/rig/crates/rig-core/src/completion/request.rs:277
  Enum StreamedAssistantContent allows 1 -> 0 generic types in /tmp/.tmpzNVzck/rig/crates/rig-core/src/streaming/mod.rs:2766

rig-agent breaking changes

--- failure enum_struct_variant_field_missing: pub enum struct variant's field removed or renamed ---

Description:
A publicly-visible enum has a struct variant whose field is no longer available under its prior name. It may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/enum_struct_variant_field_missing.ron

Failed in:
  field id of variant StreamedTurnEvent::EmitToolCallDelta, previously in file /tmp/.tmpNAKcBE/rig-agent/src/agent/run/streamed.rs:266
  field id of variant StreamedTurnEvent::EmitToolCallDelta, previously in file /tmp/.tmpNAKcBE/rig-agent/src/agent/run/streamed.rs:266

--- failure function_requires_different_generic_type_params: function now requires a different number of generic type parameters ---

Description:
A function now requires a different number of generic type parameters than it used to. Uses of this function that supplied the previous number of generic types (e.g. via turbofish syntax) will be broken.
        ref: https://doc.rust-lang.org/reference/items/generics.html
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/function_requires_different_generic_type_params.ron

Failed in:
  function stream_to_stdout (1 -> 0 generic types) in /tmp/.tmpzNVzck/rig/crates/rig-agent/src/agent/prompt_request/streaming.rs:1608

--- failure method_requires_different_generic_type_params: method now requires a different number of generic type parameters ---

Description:
A method now requires a different number of generic type parameters than it used to. Uses of this method that supplied the previous number of generic types will be broken.
        ref: https://doc.rust-lang.org/reference/items/generics.html
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/method_requires_different_generic_type_params.ron

Failed in:
  rig_agent::integrations::cli_chatbot::ChatBotBuilder::agent takes 0 generic types instead of 1, in /tmp/.tmpzNVzck/rig/crates/rig-agent/src/integrations/cli_chatbot.rs:137
  rig_agent::extractor::ExtractorBuilder::new takes 1 generic types instead of 0, in /tmp/.tmpzNVzck/rig/crates/rig-agent/src/extractor.rs:367
  rig_agent::agent::run::streamed::StreamedTurnAssembler::ingest takes 0 generic types instead of 1, in /tmp/.tmpzNVzck/rig/crates/rig-agent/src/agent/run/streamed.rs:578
  rig_agent::agent::run::StreamedTurnAssembler::ingest takes 0 generic types instead of 1, in /tmp/.tmpzNVzck/rig/crates/rig-agent/src/agent/run/streamed.rs:578
  rig_agent::agent::AgentBuilder::new takes 1 generic types instead of 0, in /tmp/.tmpzNVzck/rig/crates/rig-agent/src/agent/builder.rs:358
  rig_agent::AgentBuilder::new takes 1 generic types instead of 0, in /tmp/.tmpzNVzck/rig/crates/rig-agent/src/agent/builder.rs:358

--- failure struct_pub_field_missing: pub struct's pub field removed or renamed ---

Description:
A publicly-visible struct has at least one public field that is no longer available under its prior name. It may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/struct_pub_field_missing.ron

Failed in:
  field tool_call_id of struct ToolCallDelta, previously in file /tmp/.tmpNAKcBE/rig-agent/src/agent/hook.rs:527
  field tool_call_id of struct ToolCallDelta, previously in file /tmp/.tmpNAKcBE/rig-agent/src/agent/hook.rs:527

--- failure trait_allows_fewer_generic_type_params: trait now allows fewer generic type parameters ---

Description:
A trait now allows fewer generic type parameters than it used to. Uses of this trait that supplied all previously-supported generic types will be broken.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#trait-new-parameter-no-default
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/trait_allows_fewer_generic_type_params.ron

Failed in:
  trait StreamingChat allows 2 -> 0 generic types in /tmp/.tmpzNVzck/rig/crates/rig-agent/src/streaming.rs:15
  trait StreamingChat allows 2 -> 0 generic types in /tmp/.tmpzNVzck/rig/crates/rig-agent/src/streaming.rs:15
  trait StreamingPrompt allows 2 -> 0 generic types in /tmp/.tmpzNVzck/rig/crates/rig-agent/src/streaming.rs:9
  trait StreamingPrompt allows 2 -> 0 generic types in /tmp/.tmpzNVzck/rig/crates/rig-agent/src/streaming.rs:9

--- failure type_allows_fewer_generic_type_params: type now allows fewer generic type parameters ---

Description:
A type now allows fewer generic type parameters than it used to. Uses of this type that supplied all previously-supported generic types will be broken.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#trait-new-parameter-no-default
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/type_allows_fewer_generic_type_params.ron

Failed in:
  Struct TypedPromptRequest allows 3 -> 2 generic types in /tmp/.tmpzNVzck/rig/crates/rig-agent/src/agent/prompt_request/mod.rs:690
  Struct Extractor allows 2 -> 1 generic types in /tmp/.tmpzNVzck/rig/crates/rig-agent/src/extractor.rs:76
  Struct StreamingPromptRequest allows 1 -> 0 generic types in /tmp/.tmpzNVzck/rig/crates/rig-agent/src/agent/prompt_request/streaming.rs:284
  Struct ExtractorBuilder allows 2 -> 1 generic types in /tmp/.tmpzNVzck/rig/crates/rig-agent/src/extractor.rs:354
  Struct AgentRunner allows 1 -> 0 generic types in /tmp/.tmpzNVzck/rig/crates/rig-agent/src/agent/runner.rs:198
  Struct AgentRunner allows 1 -> 0 generic types in /tmp/.tmpzNVzck/rig/crates/rig-agent/src/agent/runner.rs:198
  Struct AgentRunner allows 1 -> 0 generic types in /tmp/.tmpzNVzck/rig/crates/rig-agent/src/agent/runner.rs:198
  Struct AgentImpl allows 1 -> 0 generic types in /tmp/.tmpzNVzck/rig/crates/rig-agent/src/integrations/cli_chatbot.rs:18
  Struct Agent allows 1 -> 0 generic types in /tmp/.tmpzNVzck/rig/crates/rig-agent/src/agent/completion.rs:555
  Struct Agent allows 1 -> 0 generic types in /tmp/.tmpzNVzck/rig/crates/rig-agent/src/agent/completion.rs:555
  Struct Agent allows 1 -> 0 generic types in /tmp/.tmpzNVzck/rig/crates/rig-agent/src/agent/completion.rs:555
  Struct PromptRequest allows 2 -> 1 generic types in /tmp/.tmpzNVzck/rig/crates/rig-agent/src/agent/prompt_request/mod.rs:228
  Struct AgentBuilder allows 2 -> 1 generic types in /tmp/.tmpzNVzck/rig/crates/rig-agent/src/agent/builder.rs:148
  Struct AgentBuilder allows 2 -> 1 generic types in /tmp/.tmpzNVzck/rig/crates/rig-agent/src/agent/builder.rs:148
  Enum MultiTurnStreamItem allows 1 -> 0 generic types in /tmp/.tmpzNVzck/rig/crates/rig-agent/src/agent/prompt_request/streaming.rs:52
  Enum MultiTurnStreamItem allows 1 -> 0 generic types in /tmp/.tmpzNVzck/rig/crates/rig-agent/src/agent/prompt_request/streaming.rs:52

rig-vertexai breaking changes

--- failure struct_missing: pub struct removed or renamed ---

Description:
A publicly-visible struct cannot be imported by its prior path. A `pub use` may have been removed, or the struct itself may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.48.0/src/lints/struct_missing.ron

Failed in:
  struct rig_vertexai::completion::PlaceholderStreamingResponse, previously in file /tmp/.tmpNAKcBE/rig-vertexai/src/completion.rs:38
Changelog

rig-derive

0.41.0 - 2026-07-28

Added

Other

Contributors

Changed

  • (rig-derive) [breaking] #[rig_tool] required-ness is derived from the
    parameter types so the advertised schema and the deserializer always agree:
    without required(...), Option<T> parameters are optional (previously
    advertised as required); with required(...), omitted parameters get
    #[serde(default)] (their types must be Option<T> or Default). Names in
    params(...)/required(...) must match actual parameters, and malformed or
    duplicate attribute entries are compile errors instead of silently ignored.
    Listing an Option<T> parameter in required(...) is a compile error
    (schemars and serde would both silently ignore the directive), and a
    wildcard context binding (#[rig(context)] _: &mut ToolContext) is now
    rejected — name it _context instead.

  • (rig-derive) Crate-name resolution and context classification share one
    authority: fully qualified &mut ToolContext paths are recognized under
    renamed rig/rig-agent dependencies without #[rig(context)], and a
    contextual tool without a reachable runtime crate gets a targeted
    diagnostic. Generated code resolves serde/serde_json/schemars through
    rig-core's re-exports (no direct downstream dependency needed), the
    Embed derive emits fully qualified impls (no Embed import needed at the
    call site), and parameters() builds its schema once via LazyLock with no
    generated expect. A field carrying both #[embed] and
    #[embed(embed_with = "...")] is now a compile error instead of being
    embedded twice, and a field carrying more than one
    #[embed(embed_with = "...")] attribute is a compile error instead of the
    first silently winning.

  • (rig-derive) [breaking] generated #[rig_tool] implementations preserve the function's Result<T, E> error as Tool::Error until erased dispatch normalizes it. Context-free functions implement the portable Tool::call API; functions with one &mut ToolContext parameter implement the contextual classic API. The context parameter may appear in any position; fully qualified rig::agent::tool::ToolContext / rig_agent::tool::ToolContext paths are recognized directly, while imported names and aliases use #[rig(context)]. The macro forwards runtime context and excludes that parameter from the generated arguments and JSON Schema without confusing unrelated application types also named ToolContext.

rig-core

0.42.0 - 2026-08-11

Fixed

Other

Contributors

Changed

  • (completion) [breaking] AssistantContent serializes with a "type" tag, exactly like UserContent — the tag is required on deserialize and there is no untagged fallback — 0.41-persisted assistant content (serialized untagged) does not load; insert the tag per MIGRATING's recipe. additional_params on every content block (Text/Image/Audio/Video/Document) is a named serde field instead of a flatten, typed Option<message::AdditionalParams> — a newtype that is a non-empty JSON object by construction (the non_empty_params/params_carry_data helper family is gone; plain is_none()/is_some() are always correct). A stray key can no longer be silently captured and replayed to providers, an absent field round-trips as None instead of the flatten's Some({}) artifact, and a non-object additional_params value is a loud decode error while being unrepresentable in memory. The unknown-key policy is uniform and tolerant across every content block: unknown keys are ignored on load (0.41 flattened extras that were never re-nested load silently minus those keys — verify with message::keys_lost_in_round_trip, per MIGRATING's recipe), and an unknown content-block tag stays a loud error. A 0.41-serialized stream item with flattened text extras decodes as stream text (stray keys dropped, text assembled); a replayed tagged assistant block decodes as StreamedAssistantContent::Unknown and is excluded from assembly — the agent assembler counts those exclusions and logs one warning per turn. A streamed TextStart whose metadata is the empty object no longer opens (or position-fixes) a text block: null and {} are canonicalized to "no metadata" before accumulation, so a {}-only start yields no empty text part and no longer pins part order. The OpenAI Responses wire type responses_api::AssistantContent::OutputText carries its own OutputText wire struct (preserving annotations/siblings verbatim), and on the blocking response path its extras now also survive conversion into generic history under additional_params["openai_responses"], replayed by the Responses serializer alone (the streaming adapter does not yet capture annotation events into params)

  • (completion) [breaking] pre-provider-split ToolCall JSON is no longer migrated on load: the ToolCallWire legacy lift is deleted, ToolCall deserializes against the current schema only, and a legacy call_id key is ignored as an unknown field — migrate persisted JSON by hand (call_idprovider.call_id, and for dual-identifier payloads also id → the call_… correlator, with the fc_… handle as provider.item_id) if you need those identifiers; see MIGRATING

  • (tool) [breaking] ToolOutput::as_content returns &[ToolResultContent] instead of &Vec<ToolResultContent>; message::EMPTY_RESPONSE_ERROR (via message::require_non_empty_response) is the one home for the shared empty-response wording every provider decode rejects with. [behavior] Four wires' empty-response error text changes to the shared wording: ollama (was "No content provided"), xai (was "Response contained no output"), vertexai (was ProviderError("No text or tool call content found in response") — the variant changes to ResponseError too), and bedrock's assistant-message conversion (was "Bedrock returned an assistant message with no content")

  • (completion) [breaking] OneOrMany<T> and EmptyListError are removed; message content, CompletionResponse::choice, CompletionRequest::chat_history, ToolResult::content and EmbeddingsBuilder output are Vec<T>. The serialized form is unchanged (the container already wrote a plain sequence), so persisted histories and stored embeddings need no migration and no recorded fixture changes. Decoding widens in two places that used to be parse errors: [], which the container rejected outright, and null on the fields that moved onto json_utils::string_or_vec (its visit_none/visit_unit arms are load-bearing for OpenAI's tool-calls-only "content": null). A tool with type Output = Vec<ToolResultContent> also compiles unchanged and now takes IntoToolOutput's rich-content path — N ordered blocks instead of one JSON array — because the guard that used to name OneOrMany<ToolResultContent> now names Vec; see MIGRATING. one_or_many::string_or_one_or_many folds into json_utils::string_or_vec; the orphan rule turns three list conversions into the pub free functions openai::completion::{user_content_to_messages, assistant_content_to_messages} and openai::responses_api::reasoning_summaries — see MIGRATING

  • (completion) [behavior] an assistant turn that carried no text and no tool calls is now empty instead of a fabricated AssistantContent::text(""). Six production sites pushed that part solely to satisfy the non-empty container — including anthropic's documented empty end_turn follow-up — and it reached history and the wire indistinguishable from a real empty text block; is_empty_assistant_turn recognises both spellings of an empty turn — zero parts, or one empty unannotated text block (a shape a blocking wire can still deliver, and the shape old histories encode) — and the agent loop keeps such turns out of history; caller-supplied history is never filtered. Three guards that were unreachable only because of the padding are removed rather than made live: reachable, each would have failed a run that previously succeeded

  • (completion) the container's two enforcement directions separate: CompletionRequest::validate_message_content rejects an empty chat_history, a content-less user/assistant message, or a tool result whose own block list is empty (named by tool, since ToolResult::content carried the same by-construction guarantee; a single empty-string block still passes — the rule is on block count, not block content) once at the request boundary (called by CompletionRequestBuilder::send/stream, which is also how both agent surfaces issue their requests; System content exempt — it is a String and was never constrained), while inbound per-wire guards route through the new message::require_non_empty(items, || error) — most via require_non_empty_response, which pairs the guard with the shared EMPTY_RESPONSE_ERROR wording (see the dedicated entry); guards rejecting a different state keep their own text; its Option sibling message::non_empty(items) is the one home for the "empty list means absent" rule (the replacement for OneOrMany::from_iter_optional). The OpenAI Responses websocket session validates in send_with_options — it takes a raw CompletionRequest, so it is a direct-to-model surface under the validator's own contract

  • (tool) [breaking] an empty tool output is rejected at construction: ToolOutput::content is fallible (Vec<ToolResultContent> -> Result<ToolOutput, ToolExecutionError>) and From<Vec<ToolResultContent>> becomes TryFrom — on 0.41 the OneOrMany argument made the empty case unrepresentable, and the Vec argument moves that guarantee into the return type. Every construction route is covered (rich-content tool returns, tools returning ToolOutput directly, hook rewrites), so the failure surfaces as an ordinary tool error fed back to the model instead of a zero-block result entering history and aborting the run at the next request's boundary check. Deliberately not normalized to an empty text block (that would fabricate content the tool never produced); an empty MCP result still normalizes to one empty text block, because that outcome is protocol-legal and outside the tool author's control. text/json/one stay infallible

  • (ollama) [behavior] converting an assistant history message with empty content no longer mints the legacy vec![AssistantContent::text("")] sentinel — the text block is pushed only when non-empty, matching the response decode path. Consequence: such a converted message cannot be replayed through the request boundary (validate_message_content rejects a content-less assistant message); callers ingesting raw Ollama history filter empty assistant messages rather than rig inventing content for them. The agent loop never produces this shape — it drops empty turns before history

  • (completion) [breaking] UserContent::tool_result/Message::tool_result record their string as the correlation handle only (echo ToolCall::id), never as a provider-issued id — a bare string cannot prove provider provenance, and stamping an echoed minted handle sent it upstream on optional-id wires as an asymmetric functionCall/functionResponse pair. Wire output on required-id wires is unchanged (the handle is the fallback). Callers holding a wire-issued id use the new tool_result_from_wire (the ToolCall::from_wire mirror), tool_result_with_call_id, or tool_result_for

  • (streaming) [breaking] RawStreamingChoice::ReasoningEnd gains wire_sent; the driver yields the completed Reasoning block for a payload-carrying end OR a bare end frame the wire itself sent (anthropic content_block_stop on an unsigned thinking block, restoring its pre-lifecycle completed event) — only adapter-synthesized bare ends stay silent. The chat-compat adapter now synthesizes the reasoning end before tool calls as well as text, matching the ollama adapter

  • (ollama) ToolCall gains id: Option<String>: modern daemons issue "id":"call_..." and rig now preserves it as the durable tool-call id (streaming key + blocking history) instead of discarding it; absent ids still mint. Never serialized back — request shapes are unchanged

  • (openrouter) id-less encrypted reasoning details key by a dedicated MintKind::EncryptedReasoning, so a whole encrypted block can no longer replace reasoning text accumulating under the shared compat Reasoning mint key

  • (gemini) [behavior] streamed function calls carry a single-wire identity: the wire's one id travels as the part id only, so provider is {call_id, item_id: None} — filling both slots fabricated a dual identity whose fake item id could pass the foreign-id guard on cross-provider replay, and made stream() and completion() disagree on byte-identical wire content

  • (cohere) [behavior] an id-less tool call mints its correlation handle and records no provider id, instead of adopting the tool name as a provider-issued id — a name-as-id is fake provenance and collided two parallel same-tool calls in one turn

  • (xai) [behavior] the request conversion guards its converted input with require_non_empty (id-less reasoning has no xAI representation and drops — now with a warning — so rig-level non-empty content can convert to zero wire items), failing locally with a named error instead of shipping input: [] for a remote 400

  • (openai) [behavior] a Responses unary response with status: incomplete and an empty choice normalizes with its finish reason (e.g. Length after the documented truncated-function-call drop) instead of being rejected as "contained no message or tool call" — matching the streaming path, which already surfaced truncation this way

  • (completion) [breaking] tool-call identity is typed: message::ToolCall is { id: ToolCallId, provider: Option<ProviderCallId>, .. } and message::ToolResult is { call: ToolCallId, provider: Option<ProviderCallId>, name: String, .. }. ToolCallId is non-empty by construction and minted at the provider boundary when the wire issued no id (ToolCall::from_wire / from_dual_wire); ProviderCallId carries the wire's call_id plus the dual-wire item id (OpenAI Responses fc_*). Serializers send provider.call_id when the provider issued one, else the minted handle on wires that require an id; optional-id wires (Gemini REST/gRPC) omit minted handles entirely, and the Interactions/Responses/xAI "requires call_id" request errors are gone. ToolResult::name is required and read directly by every name-keyed serializer; the resolve_tool_result_names back-compat pairing shim (and its name-in-id legacy encodings) is deleted. Persisted-history serde is breaking — see MIGRATING

  • (streaming) [breaking] the raw grammar is a part lifecycle: ReasoningStart/ReasoningEnd/TextEnd join the vocabulary, ReasoningSignature is deleted (a trailing signature is an End arriving late), and the accumulator becomes open-maps into an arrival-ordered part list with entity-owned idempotence — a repeated ToolInputEnd finalizes nothing even with an authoritative payload (review 84a43e9 environment variables? #1), and one end primitive replaces the per-adapter signature/boundary branches (feat(datastore): add Qdrant data store #2). Boundary-less wires synthesize their ends in the adapter; the ordinal machinery, closed_by_full_call, and every adapter-side thought/restatement buffer are deleted

  • (streaming) [breaking] the raw-event identity is the opaque StreamPartId (no Serialize, no rendering, no durable accessor), with the durable provider handle carried separately as WireId (provider_id on reasoning events, tool_id on RawStreamingToolCall/ToolInputEnd); WireId::new rejects the empty string so absence is None — the fabricated Wire("") class and its per-serializer empty-string filters are gone (review 84a43e9 feat: Add support for Anthropic models #3/feat: Add support for Perplexity models #4). Public delta ids are rig-generated correlators (ReasoningDelta gains provider_id; ToolCallDelta drops id)

  • (completion) [breaking] message::ToolResult carries the executed tool's name as required data (name: String) — name-requiring wires (Gemini functionResponse.name, Ollama tool messages, Vertex, gemini-grpc) read it directly, and an identifier is never replayed as a name (review 84a43e9 feat: Add support for PostgreSQL vector store #5, pinned by live cross-provider replay cassettes)

  • (gemini) [behavior] Interactions function-call steps assemble their arguments_delta fragments through the shared accumulator — previously the wire's fragmented tool-call arguments were dropped entirely (the call aggregated with {} args) and an unmodeled arguments_delta frame errored the stream; recorded live in interactions_same_tool_twice

  • (streaming) [breaking] RawStreamingChoice's part ids (TextStart/ToolCallDelta/Reasoning/ReasoningDelta, ToolInputEnd::id, RawStreamingToolCall::id) are the opaque streaming::StreamPartId; SyntheticIds lives in rig_core::streaming and mints it. ToolCallDelta lost internal_call_id (the shared accumulator mints it at assembly open; read it from StreamedAssistantContent::ToolCallDelta); exhaustive matches over RawStreamingChoice need arms for the lifecycle variants (ToolInputEnd, ReasoningStart/ReasoningEnd, TextEnd) — RawStreamingChoice is not #[non_exhaustive]. MINTED_ID_NAMESPACES/is_boundary_minted_id and the request-side provenance gate are deleted (unrepresentable by construction)

  • (providers) [breaking] OpenAICompatibleProvider::decorate_streaming_tool_call returns Option<ToolCallDecoration> instead of mutating a &mut HashMap<usize, RawStreamingToolCall>; OutputFunctionCall::arguments is a FunctionCallArguments newtype over the raw string (.parse()/.as_str())

  • (providers) [breaking] the Anthropic and OpenAI Responses streaming event enums no longer carry #[serde(other)]: unrecognized events triage as Unknown in the classify layer, and a known tag with a defective payload is a decode error instead of a silent absorb

  • (providers) [behavior] gemini (REST/interactions/gRPC), vertex and ollama no longer fabricate durable tool-call ids — not from an index and not from the tool name, so two calls to the same tool in one turn stay distinct; an id-less call carries a minted ToolCallId with provider: None, replays with the wire id absent on optional-id wires, and the function name a replayed tool result needs travels as the required ToolResult::name

Added

  • (streaming) wire::classify_typed_event extends the decode-then-validate policy to typed-transport wires (bedrock, candle, gemini-grpc): modeled variants are Known, the SDK's non-exhaustive/unrecognized variants are Unknown, SDK decode errors are Corrupt — a typed transport earns no policy exemption
  • (streaming) WireAdapter gains an associated Frame type so typed-event wires implement the same contract over their SDK events; classify now takes the frame by value
  • (streaming) the conformance corpus accepts typed-event input (WireInput::{Bytes, Event}), so typed wires run the shared scenarios events-first with no mock transport; frame-level scenarios a typed wire cannot spell report visible skips
  • (streaming) wire-sequence conformance corpus (test_utils::streaming_conformance + tests/core) driving raw bytes through each provider's full pipeline; recorded streaming_grammar cassette suites for openai (reasoning summaries, encrypted multi-part reasoning, parallel tool calls, incomplete) and gemini (max-tokens truncation, tool calls, thinking, interactions requires_action)
  • (streaming) OpenAICompatibleProvider::streaming_detail_reasoning — a defaulted hook letting an OpenAI-compatible provider map a per-chunk streaming detail onto a complete reasoning block instead of a tool-call decoration
  • (completion) ToolCall::wire_call_id()/ToolResult::wire_call_id() — the one derivation for a required-id wire's call-id slot (provider-issued when it exists, else the minted handle), replacing the expression every serializer hand-rolled — and ToolCallId::for_provider, the shared correlation-handle derivation
  • (completion) add typed raw_completion/raw_stream escape hatches on every provider model
  • (completion) add public ProviderCapabilities, replacing CompletionModel::composes_native_output_with_tools

Fixed

  • (anthropic) a streamed turn's Usage::input_tokens prefers the terminal message_delta and falls back to message_start, instead of always reading message_start. Anthropic proper reports the count on both frames and they agree, so nothing changes there; Anthropic-compatible gateways need not, and OpenRouter's Messages endpoint can send input_tokens: 0 on message_start with the real count on message_delta (observed when it routes to an Amazon Bedrock upstream) — which silently surfaced as Usage { input_tokens: 0 }, worse than a missing value for a consumer sizing a context window from it. A zero on the delta is read as "not reported" so a gateway with the inverse split cannot erase a count message_start got right

  • (providers) name-keyed wires (Gemini REST/Interactions, Ollama, Vertex AI, gemini-grpc) fill a cross-provider ingested result's empty name from its paired call at request assembly (providers::internal::resolve_empty_tool_result_names, matched by identifier only) — rig's own inbound converters stamp "" because the Anthropic/OpenAI-chat/Cohere/Bedrock wires carry no name, and replaying it raw was INVALID_ARGUMENT

  • (openai) a Responses tool call whose output_item.done frame was lost survives a healthy response.completed: the terminal closes every open slot (with the announced dual-wire identity) and the call finalizes from its streamed fragments instead of being discarded as truncation — the same terminal-proof drain Interactions and chat-compat ship

  • (gemini) an Interactions streamed call carries a single-wire identity: its fc_* id lands in provider.call_id with item_id empty, instead of a fabricated Responses-shaped dual id whose fake item id passed the foreign-id guard on cross-provider replay

  • (streaming) whole-call adoption accepts the two gateway shapes it rejected: a nameless args-only assembly (empty name is no evidence against the restatement) and a buffer still holding the literal null placeholder (covered vacuously) — both used to publish the call under a fresh minted id and finalize the assembly as a duplicate

  • (openai) a multi-block Responses reasoning done item (summaries + encrypted_content) aggregates as ONE part: the adapter emits one wire-sent end restatement carrying every block in wire order, so history replays exactly one rs_* input item instead of same-id siblings that duplicated the reasoning input on the next request (xai shares the fix)

  • (openai) Responses reasoning keys are slot-scoped like the tool path: a slot mixing id-bearing and id-less frames (gateways, ChatGPT envelope-less replays) keeps one assembly key fixed at the slot's first event, and the done item resolves through the slot map — no more orphaned partial part beside the superseded one

  • (openai) an unparseable restated done-item argument string is re-emitted into the assembly buffer only when no function_call_arguments.delta fragment preceded it — fragments already streamed those bytes, and the re-emit doubled them against consumers and the accumulation bound

  • (streaming) a second signature under a per-stream constant reasoning key (gemini, cohere, ollama) records a distinct signed part instead of overwriting the first — signatures cannot merge, and the overwrite left only the last one to replay (`MISSI

@github-actions
github-actions Bot force-pushed the release-plz-2026-07-28T10-35-22Z branch 2 times, most recently from c7ca529 to f8582c9 Compare July 28, 2026 18:34
@github-actions github-actions Bot changed the title chore: release v0.41.0 chore: release v0.41.1 Jul 28, 2026
@github-actions
github-actions Bot force-pushed the release-plz-2026-07-28T10-35-22Z branch 3 times, most recently from 41a1267 to 2d4419c Compare July 29, 2026 01:13
@github-actions github-actions Bot changed the title chore: release v0.41.1 chore: release v0.42.0 Aug 5, 2026
@github-actions
github-actions Bot force-pushed the release-plz-2026-07-28T10-35-22Z branch 11 times, most recently from 512d318 to 95969f6 Compare August 11, 2026 02:05
@github-actions
github-actions Bot force-pushed the release-plz-2026-07-28T10-35-22Z branch from 95969f6 to cbfb176 Compare August 11, 2026 07:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants