86 lines
2.8 KiB
Python
86 lines
2.8 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
覆盖 `HyMemoryClient._normalize_message` 对 `tool_calls` 字段的兼容处理。
|
|
|
|
背景:部分客户端(如 codebuddy)会把 `tool_calls` 编码成 JSON 字符串而非
|
|
list[dict],直接对字符串做 for 循环会按字符迭代,随后 `tc.get(...)` 抛出
|
|
`AttributeError: 'str' object has no attribute 'get'`。
|
|
|
|
运行方式:
|
|
pytest tests/test_normalize_message_tool_calls.py -v
|
|
"""
|
|
|
|
from hy_memory.client import HyMemoryClient
|
|
|
|
|
|
def test_tool_calls_normal_list():
|
|
msg = {
|
|
"role": "assistant",
|
|
"content": "",
|
|
"tool_calls": [
|
|
{"id": "1", "function": {"name": "f", "arguments": "{}"}},
|
|
],
|
|
}
|
|
result = HyMemoryClient._normalize_message(msg)
|
|
assert len(result) == 1
|
|
assert len(result[0].tool_calls) == 1
|
|
assert result[0].tool_calls[0].name == "f"
|
|
assert result[0].tool_calls[0].id == "1"
|
|
|
|
|
|
def test_tool_calls_json_string():
|
|
msg = {
|
|
"role": "assistant",
|
|
"content": "",
|
|
"tool_calls": '[{"id":"1","function":{"name":"f","arguments":"{}"}}]',
|
|
}
|
|
result = HyMemoryClient._normalize_message(msg)
|
|
assert len(result) == 1
|
|
assert len(result[0].tool_calls) == 1
|
|
assert result[0].tool_calls[0].name == "f"
|
|
assert result[0].tool_calls[0].id == "1"
|
|
|
|
|
|
def test_tool_calls_empty_string():
|
|
msg = {"role": "assistant", "content": "", "tool_calls": ""}
|
|
result = HyMemoryClient._normalize_message(msg)
|
|
assert result[0].tool_calls == []
|
|
|
|
|
|
def test_tool_calls_invalid_json_string():
|
|
msg = {"role": "assistant", "content": "", "tool_calls": "not-json"}
|
|
result = HyMemoryClient._normalize_message(msg)
|
|
assert result[0].tool_calls == []
|
|
|
|
|
|
def test_tool_calls_list_with_non_dict_items():
|
|
msg = {
|
|
"role": "assistant",
|
|
"content": "",
|
|
"tool_calls": ["x", {"id": "1", "function": {"name": "f", "arguments": "{}"}}],
|
|
}
|
|
result = HyMemoryClient._normalize_message(msg)
|
|
assert len(result[0].tool_calls) == 1
|
|
assert result[0].tool_calls[0].name == "f"
|
|
|
|
|
|
def test_real_world_codebuddy_case():
|
|
"""回归验收现场:assistant 消息 tool_calls 为字符串,read_file 调用需被正确抽出。"""
|
|
msg = {
|
|
"role": "assistant",
|
|
"content": "",
|
|
"tool_calls": (
|
|
'[{"id":"toolu_bdrk_013NXmCFJ53CN1uTUuUtz8mH","type":"function",'
|
|
'"function":{"name":"read_file",'
|
|
'"arguments":"{\\"filePath\\":\\"/a/b.java\\"}"}}]'
|
|
),
|
|
"tool_call_id": "",
|
|
}
|
|
result = HyMemoryClient._normalize_message(msg)
|
|
assert len(result) == 1
|
|
tool_calls = result[0].tool_calls
|
|
assert len(tool_calls) == 1
|
|
assert tool_calls[0].id == "toolu_bdrk_013NXmCFJ53CN1uTUuUtz8mH"
|
|
assert tool_calls[0].name == "read_file"
|
|
assert tool_calls[0].arguments == {"filePath": "/a/b.java"}
|