bedrock function toolname truncation - #3890
Conversation
|
Warning Review limit reached
More reviews will be available in 9 minutes and 50 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (8)
📝 WalkthroughWalkthroughThis PR addresses the AWS Bedrock tool name length limit by implementing deterministic aliasing. Long MCP tool names (exceeding 64 characters) are converted to Bedrock-safe aliases during request conversion and restored to original names during response conversion. The solution propagates context through streaming and batch conversion paths for both ChatCompletion and Responses APIs, with comprehensive test coverage. ChangesTool Name Aliasing for Bedrock Requests
CodeEditor Folding UI Adjustment
🎯 4 (Complex) | ⏱️ ~60 minutes Suggested reviewers
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
This stack of pull requests is managed by Graphite. Learn more about stacking. |
Confidence Score: 4/5The core aliasing logic is correct and the change is safe to merge, but an unresolved concurrent map write (flagged in a prior review pass) means a retry or parallel-tool path on the same BifrostContext could trigger a data race on the alias map. The alias map is populated under a read lock on the context's value slot but is then mutated directly — a concurrent call to bedrockAliasToolName or bedrockRestoreToolName on the same context could race. Until the map access is protected, the Go race detector could fire on production workloads that retry or fan out tool calls. core/providers/bedrock/utils.go — the alias map mutation and hash truncation both live here Important Files Changed
Reviews (7): Last reviewed commit: "bedrock function toolname truncation" | Re-trigger Greptile |
|
|
8f486e1 to
6ff893e
Compare
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
b2c5f2a to
1e84203
Compare
6ff893e to
0b7a46a
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
core/providers/bedrock/responses.go (1)
160-230:⚠️ Potential issue | 🟠 Major | ⚡ Quick winPool reset discipline violation:
flush()does not resetCtxfield.The
flush()method resets all other fields ofBedrockResponsesStreamStatebut omits resetting theCtxfield added at line 42. SincereleaseBedrockResponsesStreamState()callsflush()before returning the object to the pool, this creates a data leakage risk where a request context could persist across pooled object reuses.While
acquireBedrockResponsesStreamState()does resetstate.Ctx = nil(line 143), both reset paths should be consistent per repository patterns.🔧 Proposed fix
func (state *BedrockResponsesStreamState) flush() { // Clear maps (reuse if already initialized, otherwise initialize) // ... existing map clearing code ... state.CreatedAt = int(time.Now().Unix()) state.HasEmittedCreated = false state.HasEmittedInProgress = false state.UsedStructuredOutputTool = false + state.Ctx = nil }Add after line 229:
state.Ctx = nilAs per coding guidelines: "Reset all fields of pooled objects before calling pool.Put() to prevent data leakage between requests" and "Pooled objects must have every field reset before returning to a pool."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@core/providers/bedrock/responses.go` around lines 160 - 230, The flush() method of BedrockResponsesStreamState fails to clear the Ctx field, risking context leakage when objects are returned to the pool; update flush() to set state.Ctx = nil (mirroring acquireBedrockResponsesStreamState() and ensuring releaseBedrockResponsesStreamState() returns fully-reset objects) so all fields are reset before pool.Put().
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@core/providers/bedrock/bedrock_test.go`:
- Around line 5343-5382: The test
TestToBedrockChatCompletionRequest_AliasesLongMCPToolNames only checks
length/prefix/suffix; update it (and the similar block around lines 5430-5476)
to assert the full Bedrock tool-name regex /^[A-Za-z0-9_-]{1,64}$/ for alias and
add an extra subcase where the original tool name contains invalid characters
(e.g., spaces, ":", "/", ".") to confirm ToBedrockChatCompletionRequest
sanitizes them into a Bedrock-valid name; specifically, after computing alias :=
result.ToolConfig.Tools[0].ToolSpec.Name assert it matches the regex and that
the alias contains no disallowed characters, and add a new test input toolName
with invalid chars and repeat the same assertions (including equality with
result.ToolConfig.ToolChoice.Tool.Name).
In `@core/providers/bedrock/utils.go`:
- Around line 138-142: The function bedrockAliasToolName currently only checks
length and returns names with disallowed characters unchanged; update
bedrockAliasToolName to validate the name against Bedrock's pattern
`[A-Za-z0-9_-]{1,64}` (use a regexp or equivalent) and only return the original
name when it matches that pattern, otherwise generate a safe alias (e.g.,
truncated + deterministic hash) and record the reverse mapping as the existing
mapping logic expects; ensure you reference and update the same alias storage
used by bedrockAliasToolName so lookups still work.
---
Outside diff comments:
In `@core/providers/bedrock/responses.go`:
- Around line 160-230: The flush() method of BedrockResponsesStreamState fails
to clear the Ctx field, risking context leakage when objects are returned to the
pool; update flush() to set state.Ctx = nil (mirroring
acquireBedrockResponsesStreamState() and ensuring
releaseBedrockResponsesStreamState() returns fully-reset objects) so all fields
are reset before pool.Put().
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 0cd64091-002b-4f86-a8cd-2b358c1b60cd
⛔ Files ignored due to path filters (1)
core/go.sumis excluded by!**/*.sum
📒 Files selected for processing (8)
core/go.modcore/providers/bedrock/bedrock.gocore/providers/bedrock/bedrock_test.gocore/providers/bedrock/chat.gocore/providers/bedrock/responses.gocore/providers/bedrock/utils.goui/app/workspace/logs/sheets/logDetailView.tsxui/components/ui/codeEditor.tsx
0b7a46a to
7880ecb
Compare
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
7880ecb to
7cbfd9b
Compare
1e84203 to
13d1650
Compare
7cbfd9b to
9588db5
Compare
13d1650 to
367b062
Compare
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
Merge activity
|
9588db5 to
94956a5
Compare
## Summary
Bedrock enforces a strict tool name format: names must match `[A-Za-z0-9_-]{1,64}`. MCP tool names (e.g. `mcp__plugin_chrome-devtools-mcp_chrome-devtools__list_network_requests`) violate this constraint, causing API errors. This PR introduces transparent aliasing so that long or unsafe tool names are automatically shortened to a safe alias before being sent to Bedrock, and then restored to their original names in the response.
## Issue
closes maximhq#3788
## Changes
- Added `bedrockAliasToolName` which, for any tool name that doesn't satisfy Bedrock's naming rules, generates a deterministic alias of the form `<8-char sha1 hash>_<semantic suffix>` (≤64 chars total). The alias-to-original mapping is stored in the `BifrostContext` using a typed context key.
- Added `bedrockRestoreToolName` which looks up the alias map in the context and returns the original name, used when converting Bedrock responses back to Bifrost format.
- Aliasing is applied consistently across all code paths: tool definitions, `toolChoice.tool.name`, tool calls in assistant messages, and tools extracted from conversation history.
- Name restoration is applied in both non-streaming (`ToBifrostChatResponse`) and streaming (`ToBifrostChatCompletionStream`) response conversion paths.
- `BedrockStreamState` now carries a `context.Context`, populated via `NewBedrockStreamStateWithContext`, so the streaming path has access to the alias map.
- Added two tests: one verifying that long MCP tool names are aliased correctly on the request side, and one verifying that aliased names are restored to their originals in the response.
## Type of change
- [x] Bug fix
## Affected areas
- [x] Core (Go)
- [x] Providers/Integrations
## How to test
```sh
go test ./core/providers/bedrock/... -run "TestToBedrockChatCompletionRequest_AliasesLongMCPToolNames"
go test ./core/providers/bedrock/... -run "TestBedrockToBifrostChatResponse_RestoresAliasedToolName"
go test ./core/providers/bedrock/...
```
Pass a tool with a name longer than 64 characters or containing characters outside `[A-Za-z0-9_-]` (such as an MCP-style name with `__` and `.` segments) to a Bedrock-backed model. Verify that the request succeeds and that the tool name in the response matches the original name provided.
## Breaking changes
- [x] No
## Security considerations
The alias map is scoped to a single `BifrostContext` per request and is never persisted or shared across requests. Tool names are hashed with SHA-1 solely for collision-resistant shortening; no sensitive data is derived from the hash.
## Checklist
- [x] I added/updated tests where appropriate
- [x] I verified builds succeed (Go and UI)
<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit
* **New Features**
* Enhanced Bedrock provider with improved tool name handling across chat and responses APIs
* Updated code editor UI with better code folding controls
* **Tests**
* Added comprehensive test coverage for Bedrock tool handling in chat completion and responses APIs
* **Chores**
* Updated dependencies for internal tooling
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/maximhq/bifrost/pull/3890?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Summary
Bedrock enforces a strict tool name format: names must match `[A-Za-z0-9_-]{1,64}`. MCP tool names (e.g. `mcp__plugin_chrome-devtools-mcp_chrome-devtools__list_network_requests`) violate this constraint, causing API errors. This PR introduces transparent aliasing so that long or unsafe tool names are automatically shortened to a safe alias before being sent to Bedrock, and then restored to their original names in the response.
## Issue
closes maximhq#3788
## Changes
- Added `bedrockAliasToolName` which, for any tool name that doesn't satisfy Bedrock's naming rules, generates a deterministic alias of the form `<8-char sha1 hash>_<semantic suffix>` (≤64 chars total). The alias-to-original mapping is stored in the `BifrostContext` using a typed context key.
- Added `bedrockRestoreToolName` which looks up the alias map in the context and returns the original name, used when converting Bedrock responses back to Bifrost format.
- Aliasing is applied consistently across all code paths: tool definitions, `toolChoice.tool.name`, tool calls in assistant messages, and tools extracted from conversation history.
- Name restoration is applied in both non-streaming (`ToBifrostChatResponse`) and streaming (`ToBifrostChatCompletionStream`) response conversion paths.
- `BedrockStreamState` now carries a `context.Context`, populated via `NewBedrockStreamStateWithContext`, so the streaming path has access to the alias map.
- Added two tests: one verifying that long MCP tool names are aliased correctly on the request side, and one verifying that aliased names are restored to their originals in the response.
## Type of change
- [x] Bug fix
## Affected areas
- [x] Core (Go)
- [x] Providers/Integrations
## How to test
```sh
go test ./core/providers/bedrock/... -run "TestToBedrockChatCompletionRequest_AliasesLongMCPToolNames"
go test ./core/providers/bedrock/... -run "TestBedrockToBifrostChatResponse_RestoresAliasedToolName"
go test ./core/providers/bedrock/...
```
Pass a tool with a name longer than 64 characters or containing characters outside `[A-Za-z0-9_-]` (such as an MCP-style name with `__` and `.` segments) to a Bedrock-backed model. Verify that the request succeeds and that the tool name in the response matches the original name provided.
## Breaking changes
- [x] No
## Security considerations
The alias map is scoped to a single `BifrostContext` per request and is never persisted or shared across requests. Tool names are hashed with SHA-1 solely for collision-resistant shortening; no sensitive data is derived from the hash.
## Checklist
- [x] I added/updated tests where appropriate
- [x] I verified builds succeed (Go and UI)
<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit
* **New Features**
* Enhanced Bedrock provider with improved tool name handling across chat and responses APIs
* Updated code editor UI with better code folding controls
* **Tests**
* Added comprehensive test coverage for Bedrock tool handling in chat completion and responses APIs
* **Chores**
* Updated dependencies for internal tooling
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/maximhq/bifrost/pull/3890?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Summary
Bedrock enforces a strict tool name format: names must match
[A-Za-z0-9_-]{1,64}. MCP tool names (e.g.mcp__plugin_chrome-devtools-mcp_chrome-devtools__list_network_requests) violate this constraint, causing API errors. This PR introduces transparent aliasing so that long or unsafe tool names are automatically shortened to a safe alias before being sent to Bedrock, and then restored to their original names in the response.Issue
closes #3788
Changes
bedrockAliasToolNamewhich, for any tool name that doesn't satisfy Bedrock's naming rules, generates a deterministic alias of the form<8-char sha1 hash>_<semantic suffix>(≤64 chars total). The alias-to-original mapping is stored in theBifrostContextusing a typed context key.bedrockRestoreToolNamewhich looks up the alias map in the context and returns the original name, used when converting Bedrock responses back to Bifrost format.toolChoice.tool.name, tool calls in assistant messages, and tools extracted from conversation history.ToBifrostChatResponse) and streaming (ToBifrostChatCompletionStream) response conversion paths.BedrockStreamStatenow carries acontext.Context, populated viaNewBedrockStreamStateWithContext, so the streaming path has access to the alias map.Type of change
Affected areas
How to test
Pass a tool with a name longer than 64 characters or containing characters outside
[A-Za-z0-9_-](such as an MCP-style name with__and.segments) to a Bedrock-backed model. Verify that the request succeeds and that the tool name in the response matches the original name provided.Breaking changes
Security considerations
The alias map is scoped to a single
BifrostContextper request and is never persisted or shared across requests. Tool names are hashed with SHA-1 solely for collision-resistant shortening; no sensitive data is derived from the hash.Checklist
Summary by CodeRabbit
New Features
Tests
Chores