fix(bedrock): hash-suffix tool ids whose chars were rewritten so they cannot collide

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
shivam 2026-09-12 18:17:52 +00:00
parent d5c7e279d7
commit 646fd53740
2 changed files with 13 additions and 3 deletions

View file

@ -1522,11 +1522,11 @@ _BEDROCK_TOOL_USE_ID_HASH_LEN: Final = 8
def _sanitize_bedrock_tool_use_id(tool_use_id: str) -> str:
"""
Bedrock Converse requires toolUseId to match [a-zA-Z0-9_.:-]+ and be at most 64 chars.
Over-long ids are truncated and suffixed with a short hash of the original so two ids
that only differ past the cut still map to distinct values.
Ids that need rewriting get a short hash of the original appended so two ids that only
differ in a replaced char or past the cut still map to distinct values.
"""
sanitized: Final = re.sub(r"[^a-zA-Z0-9_.:-]", "_", tool_use_id) or "tool_use_id"
if len(sanitized) <= _BEDROCK_TOOL_USE_ID_MAX_LEN:
if sanitized == tool_use_id and len(sanitized) <= _BEDROCK_TOOL_USE_ID_MAX_LEN:
return sanitized
digest: Final = hashlib.sha256(tool_use_id.encode()).hexdigest()[:_BEDROCK_TOOL_USE_ID_HASH_LEN]
return f"{sanitized[: _BEDROCK_TOOL_USE_ID_MAX_LEN - _BEDROCK_TOOL_USE_ID_HASH_LEN - 1]}_{digest}"

View file

@ -2264,6 +2264,16 @@ def test_bedrock_tool_use_id_truncation_keeps_distinct_ids_distinct():
assert all(len(i) == 64 for i in ids)
def test_bedrock_tool_use_id_replaced_chars_do_not_collide_with_existing_ids():
ids = {
_convert_to_bedrock_tool_call_result({"tool_call_id": i, "role": "tool", "name": "f", "content": "ok"})[
"toolResult"
]["toolUseId"]
for i in ("call|x", "call_x")
}
assert len(ids) == 2
def test_bedrock_tool_call_invoke_concatenated_json_long_id_stays_within_limit():
long_id = "call_" + "q" * 62
result = _convert_to_bedrock_tool_call_invoke(