This commit is contained in:
@@ -1278,7 +1278,22 @@ def _write_builder_state(
|
||||
|
||||
|
||||
def _source_bundle_hash(bundle: bytes) -> str:
|
||||
return hashlib.sha256(bundle).hexdigest()
|
||||
digest = hashlib.sha256()
|
||||
with tarfile.open(fileobj=io.BytesIO(bundle), mode="r:gz") as tf:
|
||||
members = sorted(
|
||||
(member for member in tf.getmembers() if member.isfile()),
|
||||
key=lambda member: member.name,
|
||||
)
|
||||
for member in members:
|
||||
extracted = tf.extractfile(member)
|
||||
body = extracted.read() if extracted is not None else b""
|
||||
digest.update(member.name.encode("utf-8"))
|
||||
digest.update(b"\0")
|
||||
digest.update(str(len(body)).encode("ascii"))
|
||||
digest.update(b"\0")
|
||||
digest.update(body)
|
||||
digest.update(b"\0")
|
||||
return digest.hexdigest()
|
||||
|
||||
|
||||
def _record_sandbox_result(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import hashlib
|
||||
import gzip
|
||||
import io
|
||||
import json
|
||||
import tarfile
|
||||
@@ -22,6 +22,7 @@ from agent_builder.tools import (
|
||||
_replace_workspace_files,
|
||||
_render_a2a_init_template,
|
||||
_render_skill_md,
|
||||
_source_bundle_hash,
|
||||
_tarball_workspace_dir,
|
||||
ToolContext,
|
||||
build_tools,
|
||||
@@ -382,9 +383,9 @@ class TemplateInitTests(unittest.TestCase):
|
||||
}
|
||||
for rel, content in files.items():
|
||||
workspace.write_bytes(prefix + rel, content.encode("utf-8"))
|
||||
source_hash = hashlib.sha256(
|
||||
source_hash = _source_bundle_hash(
|
||||
_tarball_workspace_dir(_WorkspaceObjectStore(workspace), prefix)
|
||||
).hexdigest()
|
||||
)
|
||||
workspace.write_bytes(
|
||||
prefix + _BUILDER_STATE_FILE,
|
||||
json.dumps({
|
||||
@@ -478,6 +479,27 @@ class TemplateInitTests(unittest.TestCase):
|
||||
self.assertEqual(result["error"], "sandbox_not_passed")
|
||||
self.assertEqual(_FakeAsyncClient.posts, [])
|
||||
|
||||
def test_source_bundle_hash_ignores_archive_metadata(self) -> None:
|
||||
def bundle_with_mtime(mtime: int) -> bytes:
|
||||
raw = io.BytesIO()
|
||||
with tarfile.open(fileobj=raw, mode="w") as tf:
|
||||
body = b"print('ok')\n"
|
||||
info = tarfile.TarInfo(name="agent.py")
|
||||
info.size = len(body)
|
||||
info.mode = 0o644
|
||||
info.mtime = mtime
|
||||
tf.addfile(info, io.BytesIO(body))
|
||||
compressed = io.BytesIO()
|
||||
with gzip.GzipFile(fileobj=compressed, mode="wb", mtime=mtime) as gz:
|
||||
gz.write(raw.getvalue())
|
||||
return compressed.getvalue()
|
||||
|
||||
first = bundle_with_mtime(1)
|
||||
second = bundle_with_mtime(2)
|
||||
|
||||
self.assertNotEqual(first, second)
|
||||
self.assertEqual(_source_bundle_hash(first), _source_bundle_hash(second))
|
||||
|
||||
def test_cp_compose_meta_agent_posts_manifest_and_records_state(self) -> None:
|
||||
workspace = _FakeWorkspace()
|
||||
tools = build_tools(
|
||||
|
||||
Reference in New Issue
Block a user