fix: resolve file-artifact handles with uppercased uuid hex

The handle regex matches hex case-insensitively, but store keys are
lowercase uuid4 strings. Normalize the captured uuid to lowercase before
lookup so a handle echoed by the model with uppercase hex still resolves
to its bytes instead of leaking the raw token to the downstream tool.
This commit is contained in:
Matt Aitchison
2026-06-04 19:14:56 -05:00
parent f7667c1f12
commit 06b239d8fe
2 changed files with 14 additions and 1 deletions

View File

@@ -187,7 +187,10 @@ def resolve_artifact_handles(value: Any) -> Any:
return value
def _sub(match: re.Match[str]) -> str:
artifact = _store.resolve(match.group(1))
# Store keys are lowercase uuid4 strings; the regex matches hex
# case-insensitively, so normalize before lookup in case the model
# echoed the handle with uppercase hex.
artifact = _store.resolve(match.group(1).lower())
return artifact.as_base64() if artifact is not None else match.group(0)
return _HANDLE_RE.sub(_sub, value)

View File

@@ -100,6 +100,16 @@ class TestResolveArtifactHandles:
resolved = resolve_artifact_handles(handle)
assert base64.b64decode(resolved) == data
def test_resolves_handle_with_uppercased_hex(self) -> None:
# A model may echo the handle with uppercase uuid hex; lookup must still
# hit the lowercase-keyed store.
data = b"upper-case-payload" * 100
handle = _handle_in(store_artifact(FileArtifact(data=data)))
scheme, _, hex_part = handle.rpartition("/")
upper = f"{scheme}/{hex_part.upper()}"
assert upper != handle
assert base64.b64decode(resolve_artifact_handles(upper)) == data
def test_resolves_handle_inside_dict(self) -> None:
data = b"binary-payload" * 1000
handle = _handle_in(store_artifact(FileArtifact(data=data)))