chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
|
||||
from yuxi.utils.hash_utils import hash_id, hashstr, subagent_child_thread_id
|
||||
|
||||
|
||||
def test_hashstr_matches_sha256_hex() -> None:
|
||||
assert hashstr("abc") == hashlib.sha256(b"abc").hexdigest()
|
||||
|
||||
|
||||
def test_hashstr_supports_length_and_salt() -> None:
|
||||
expected = hashlib.sha256(b"abc-fixed").hexdigest()[:12]
|
||||
|
||||
assert hashstr("abc", length=12, with_salt=True, salt="-fixed") == expected
|
||||
|
||||
|
||||
def test_hash_id_generates_stable_prefixed_id() -> None:
|
||||
hashed = hash_id("subagent:", "parent-run:child-thread:tool-1:worker")
|
||||
|
||||
assert hashed.startswith("subagent:")
|
||||
assert len(hashed) == 48
|
||||
assert hashed == hash_id("subagent:", "parent-run:child-thread:tool-1:worker")
|
||||
|
||||
|
||||
def test_hash_id_length_includes_prefix() -> None:
|
||||
hashed = hash_id("subagent_", "parent-thread:worker:tool-1", length=64)
|
||||
|
||||
assert hashed.startswith("subagent_")
|
||||
assert len(hashed) == 64
|
||||
|
||||
|
||||
def test_subagent_child_thread_id_matches_inline_formula() -> None:
|
||||
expected = hash_id("subagent_", "parent-thread:worker:tool-1", length=64)
|
||||
|
||||
assert subagent_child_thread_id("parent-thread", "worker", "tool-1") == expected
|
||||
assert len(subagent_child_thread_id("parent-thread", "worker", "tool-1")) == 64
|
||||
@@ -0,0 +1,31 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
import io
|
||||
|
||||
from PIL import Image
|
||||
|
||||
from yuxi.utils.image_processor import process_uploaded_image
|
||||
|
||||
|
||||
def test_process_uploaded_image_composites_transparent_png_pixels_on_white():
|
||||
image = Image.new("RGBA", (2, 2), (255, 255, 255, 0))
|
||||
image.putpixel((0, 0), (50, 87, 244, 0))
|
||||
image.putpixel((1, 0), (50, 87, 244, 255))
|
||||
|
||||
with io.BytesIO() as buffer:
|
||||
image.save(buffer, format="PNG")
|
||||
image_data = buffer.getvalue()
|
||||
|
||||
result = process_uploaded_image(image_data, "transparent.png")
|
||||
|
||||
assert result["success"] is True
|
||||
assert result["format"] == "PNG"
|
||||
assert result["mime_type"] == "image/png"
|
||||
|
||||
processed_data = base64.b64decode(result["image_content"])
|
||||
with Image.open(io.BytesIO(processed_data)) as processed_image:
|
||||
rgb_image = processed_image.convert("RGB")
|
||||
|
||||
assert rgb_image.getpixel((0, 0)) == (255, 255, 255)
|
||||
assert rgb_image.getpixel((1, 0)) == (50, 87, 244)
|
||||
@@ -0,0 +1,52 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from yuxi.utils.share_config import normalize_share_config
|
||||
|
||||
|
||||
def test_normalize_share_config_defaults_to_global() -> None:
|
||||
result = normalize_share_config(
|
||||
None,
|
||||
default_config={"access_level": "global", "department_ids": [], "user_uids": []},
|
||||
default_access_level="global",
|
||||
invalid_access_level_message="无效的权限等级",
|
||||
)
|
||||
|
||||
assert result == {"access_level": "global", "department_ids": [], "user_uids": []}
|
||||
|
||||
|
||||
def test_normalize_share_config_department_adds_actor_department_and_deduplicates() -> None:
|
||||
result = normalize_share_config(
|
||||
{"access_level": "department", "department_ids": ["2", 1], "user_uids": ["ignored"]},
|
||||
default_config={"access_level": "global", "department_ids": [], "user_uids": []},
|
||||
default_access_level="global",
|
||||
invalid_access_level_message="无效的权限等级",
|
||||
department_id="2",
|
||||
)
|
||||
|
||||
assert result == {"access_level": "department", "department_ids": [1, 2], "user_uids": []}
|
||||
|
||||
|
||||
def test_normalize_share_config_user_adds_actor_and_deduplicates() -> None:
|
||||
result = normalize_share_config(
|
||||
{"access_level": "user", "department_ids": [1], "user_uids": [" other ", "owner", ""]},
|
||||
default_config={"access_level": "user", "department_ids": [], "user_uids": []},
|
||||
default_access_level="user",
|
||||
invalid_access_level_message="无效的权限等级",
|
||||
user_uid="owner",
|
||||
)
|
||||
|
||||
assert result == {"access_level": "user", "department_ids": [], "user_uids": ["other", "owner"]}
|
||||
|
||||
|
||||
def test_normalize_share_config_rejects_disallowed_access_level() -> None:
|
||||
with pytest.raises(ValueError, match="无权使用该共享范围"):
|
||||
normalize_share_config(
|
||||
{"access_level": "global", "department_ids": [], "user_uids": []},
|
||||
default_config={"access_level": "user", "department_ids": [], "user_uids": []},
|
||||
default_access_level="user",
|
||||
invalid_access_level_message="无效的权限等级",
|
||||
allowed_access_levels={"user"},
|
||||
unauthorized_access_level_message="无权使用该共享范围",
|
||||
)
|
||||
@@ -0,0 +1,22 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from yuxi.utils.thread_utils import extract_thread_id
|
||||
|
||||
|
||||
def test_extract_thread_id_reads_stable_event_paths():
|
||||
assert extract_thread_id({"thread_id": " parent-thread "}) == "parent-thread"
|
||||
assert extract_thread_id({"configurable": {"thread_id": "child-thread"}}) == "child-thread"
|
||||
assert extract_thread_id({"metadata": {"thread_id": "meta-thread"}}) == "meta-thread"
|
||||
assert extract_thread_id({"stream_event": {"thread_id": "event-thread"}}) == "event-thread"
|
||||
assert extract_thread_id({"meta": {"thread_id": "run-thread"}}) == "run-thread"
|
||||
|
||||
|
||||
def test_extract_thread_id_uses_fallback_for_missing_or_unstable_paths():
|
||||
assert extract_thread_id(None, "fallback-thread") == "fallback-thread"
|
||||
assert extract_thread_id({"thread_id": " "}, "fallback-thread") == "fallback-thread"
|
||||
assert extract_thread_id({"data": {"metadata": {"thread_id": "nested-thread"}}}, "fallback-thread") == (
|
||||
"fallback-thread"
|
||||
)
|
||||
assert extract_thread_id({"metadata": {"configurable": {"thread_id": "nested-thread"}}}, "fallback-thread") == (
|
||||
"fallback-thread"
|
||||
)
|
||||
Reference in New Issue
Block a user