Skip to content

Commit 0efad13

Browse files
Alex Holmbergclaude
authored andcommitted
refactor(bedrock): inline rig-bedrock module for crates.io compatibility
Move vendored rig-bedrock code from vendor/ into src/bedrock/ so it gets published with the crate. This ensures users installing from crates.io get the extended thinking fixes, since crates.io ignores path dependencies and [patch.crates-io] sections. Changes: - Move vendor/rig-bedrock/src/* to src/bedrock/ - Update Cargo.toml: remove rig-bedrock dep, add AWS SDK deps directly - Update imports from rig_bedrock:: to crate::bedrock:: - Remove vendor/rig-bedrock directory - Add debug logging for extended thinking troubleshooting The inlined module contains fixes for: - Extended thinking with multi-turn tool use - Reasoning block preservation in conversation history - Content block sorting (Reasoning before ToolUse) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 44b551d commit 0efad13

36 files changed

Lines changed: 146 additions & 802 deletions

Cargo.lock

Lines changed: 7 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,16 @@ rand = "0.8"
7373
futures-util = "0.3"
7474

7575
# Agent dependencies (using Rig - LLM application framework)
76-
rig-core = { version = "0.27", features = ["derive"] }
77-
rig-bedrock = { version = "0.3", path = "vendor/rig-bedrock" } # Vendored with fix for extended thinking + tool calls
76+
rig-core = { version = "0.27", features = ["derive", "image"] }
77+
78+
# AWS Bedrock dependencies (inlined bedrock module with extended thinking fixes)
79+
async-stream = "0.3"
80+
aws-config = { version = "1", features = ["behavior-version-latest"] }
81+
aws-sdk-bedrockruntime = "1"
82+
aws-smithy-types = "1"
83+
base64 = "0.22"
84+
schemars = "0.8"
85+
tracing = "0.1"
7886

7987
# Diff rendering for file confirmation UI
8088
similar = "2.6"
@@ -107,8 +115,3 @@ path = "examples/check_vulnerabilities.rs"
107115
name = "security_analysis"
108116
path = "examples/security_analysis.rs"
109117

110-
# Patch rig-bedrock to fix extended thinking support with tool use
111-
# The upstream version drops Reasoning blocks when a tool call is present.
112-
# See: vendor/rig-bedrock/src/types/assistant_content.rs for the fix.
113-
[patch.crates-io]
114-
rig-bedrock = { version = "0.3", path = "vendor/rig-bedrock" }

src/agent/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,7 @@ pub async fn run_interactive(
495495
}
496496
ProviderType::Bedrock => {
497497
// Bedrock provider via rig-bedrock - same pattern as OpenAI/Anthropic
498-
let client = rig_bedrock::client::Client::from_env();
498+
let client = crate::bedrock::client::Client::from_env();
499499

500500
// Extended thinking for Claude models via Bedrock
501501
// This enables Claude to show its reasoning process before responding.
@@ -1477,7 +1477,7 @@ pub async fn run_query(
14771477
}
14781478
ProviderType::Bedrock => {
14791479
// Bedrock provider via rig-bedrock - same pattern as Anthropic
1480-
let client = rig_bedrock::client::Client::from_env();
1480+
let client = crate::bedrock::client::Client::from_env();
14811481
let model_name = model
14821482
.as_deref()
14831483
.unwrap_or("global.anthropic.claude-sonnet-4-5-20250929-v1:0");
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
use crate::image::ImageGenerationModel;
2-
use crate::{completion::CompletionModel, embedding::EmbeddingModel};
1+
use super::image::ImageGenerationModel;
2+
use super::{completion::CompletionModel, embedding::EmbeddingModel};
33
use aws_config::{BehaviorVersion, Region};
44
use rig::client::Nothing;
55
use rig::prelude::*;
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! All supported models <https://docs.aws.amazon.com/bedrock/latest/userguide/models-supported.html>
22
3-
use crate::{
3+
use super::{
44
client::Client,
55
types::{
66
assistant_content::AwsConverseOutput, completion_request::AwsCompletionRequest,
@@ -173,7 +173,7 @@ impl CompletionModel {
173173

174174
impl completion::CompletionModel for CompletionModel {
175175
type Response = AwsConverseOutput;
176-
type StreamingResponse = crate::streaming::BedrockStreamingResponse;
176+
type StreamingResponse = super::streaming::BedrockStreamingResponse;
177177

178178
type Client = Client;
179179

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use aws_smithy_types::Blob;
22
use rig::embeddings::{self, Embedding, EmbeddingError};
33
use serde::{Deserialize, Serialize};
44

5-
use crate::{client::Client, types::errors::AwsSdkInvokeModelError};
5+
use super::{client::Client, types::errors::AwsSdkInvokeModelError};
66

77
#[derive(Serialize)]
88
#[serde(rename_all = "camelCase")]
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
use crate::client::Client;
2-
use crate::types::errors::AwsSdkInvokeModelError;
3-
use crate::types::text_to_image::{TextToImageGeneration, TextToImageResponse};
1+
use super::client::Client;
2+
use super::types::errors::AwsSdkInvokeModelError;
3+
use super::types::text_to_image::{TextToImageGeneration, TextToImageResponse};
44
use aws_smithy_types::Blob;
55
use rig::image_generation::{
66
self, ImageGenerationError, ImageGenerationRequest, ImageGenerationResponse,
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
use crate::types::completion_request::AwsCompletionRequest;
2-
use crate::{completion::CompletionModel, types::errors::AwsSdkConverseStreamError};
1+
use super::types::completion_request::AwsCompletionRequest;
2+
use super::{completion::CompletionModel, types::errors::AwsSdkConverseStreamError};
33
use async_stream::stream;
44
use aws_sdk_bedrockruntime::types as aws_bedrock;
55
use rig::completion::GetTokenUsage;

vendor/rig-bedrock/src/types/assistant_content.rs renamed to src/bedrock/types/assistant_content.rs

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use rig::{
66
};
77
use serde::{Deserialize, Serialize};
88

9-
use crate::types::message::RigMessage;
9+
use super::message::RigMessage;
1010

1111
use super::{converse_output::InternalConverseOutput, json::AwsDocument};
1212
use rig::completion;
@@ -78,6 +78,29 @@ impl TryFrom<aws_bedrock::ContentBlock> for RigAssistantContent {
7878
type Error = CompletionError;
7979

8080
fn try_from(value: aws_bedrock::ContentBlock) -> Result<Self, Self::Error> {
81+
// Debug: Log incoming AWS content block
82+
let block_type = match &value {
83+
aws_bedrock::ContentBlock::Text(t) => format!("Text(len={})", t.len()),
84+
aws_bedrock::ContentBlock::ToolUse(t) => {
85+
format!("ToolUse(id={}, name={})", t.tool_use_id, t.name)
86+
}
87+
aws_bedrock::ContentBlock::ReasoningContent(r) => match r {
88+
aws_bedrock::ReasoningContentBlock::ReasoningText(rt) => format!(
89+
"ReasoningContent::ReasoningText(len={}, has_sig={})",
90+
rt.text.len(),
91+
rt.signature.is_some()
92+
),
93+
aws_bedrock::ReasoningContentBlock::RedactedContent(blob) => format!(
94+
"ReasoningContent::RedactedContent(blob_len={})",
95+
blob.as_ref().len()
96+
),
97+
_ => "ReasoningContent::Unknown".to_string(),
98+
},
99+
aws_bedrock::ContentBlock::ToolResult(_) => "ToolResult".to_string(),
100+
_ => "Other".to_string(),
101+
};
102+
tracing::debug!("Converting AWS ContentBlock to Rig: {}", block_type);
103+
81104
match value {
82105
aws_bedrock::ContentBlock::Text(text) => {
83106
Ok(RigAssistantContent(AssistantContent::Text(Text { text })))
@@ -91,18 +114,42 @@ impl TryFrom<aws_bedrock::ContentBlock> for RigAssistantContent {
91114
)),
92115
aws_bedrock::ContentBlock::ReasoningContent(reasoning_block) => match reasoning_block {
93116
aws_bedrock::ReasoningContentBlock::ReasoningText(reasoning_text) => {
117+
tracing::debug!(
118+
"Converting ReasoningText: text_len={}, signature={:?}",
119+
reasoning_text.text.len(),
120+
reasoning_text
121+
.signature
122+
.as_ref()
123+
.map(|s| format!("{}...", &s[..s.len().min(20)]))
124+
);
94125
Ok(RigAssistantContent(AssistantContent::Reasoning(
95126
rig::message::Reasoning::new(&reasoning_text.text)
96127
.with_signature(reasoning_text.signature),
97128
)))
98129
}
99-
_ => Err(CompletionError::ProviderError(
100-
"AWS Bedrock returned unsupported ReasoningContentBlock variant".into(),
101-
)),
130+
aws_bedrock::ReasoningContentBlock::RedactedContent(blob) => {
131+
tracing::warn!(
132+
"AWS Bedrock returned RedactedContent (blob_len={}). This variant is not yet supported!",
133+
blob.as_ref().len()
134+
);
135+
Err(CompletionError::ProviderError(format!(
136+
"AWS Bedrock returned RedactedContent (blob_len={}). This variant needs to be handled for multi-turn conversations with extended thinking.",
137+
blob.as_ref().len()
138+
)))
139+
}
140+
_ => {
141+
tracing::error!("AWS Bedrock returned unknown ReasoningContentBlock variant");
142+
Err(CompletionError::ProviderError(
143+
"AWS Bedrock returned unsupported ReasoningContentBlock variant".into(),
144+
))
145+
}
102146
},
103-
_ => Err(CompletionError::ProviderError(
104-
"AWS Bedrock returned unsupported ContentBlock".into(),
105-
)),
147+
_ => {
148+
tracing::warn!("AWS Bedrock returned unsupported ContentBlock type");
149+
Err(CompletionError::ProviderError(
150+
"AWS Bedrock returned unsupported ContentBlock".into(),
151+
))
152+
}
106153
}
107154
}
108155
}
@@ -190,12 +237,9 @@ impl TryFrom<RigAssistantContent> for aws_bedrock::ContentBlock {
190237

191238
#[cfg(test)]
192239
mod tests {
193-
use crate::types::{
194-
assistant_content::RigAssistantContent, converse_output::InternalConverseOutput,
195-
errors::TypeConversionError,
196-
};
197-
240+
use super::super::{converse_output::InternalConverseOutput, errors::TypeConversionError};
198241
use super::AwsConverseOutput;
242+
use super::RigAssistantContent;
199243
use aws_sdk_bedrockruntime::types as aws_bedrock;
200244
use rig::{OneOrMany, completion, message::AssistantContent};
201245

0 commit comments

Comments
 (0)