refactor: 重构 Tool Result 契约,移除 ui_hints 统一使用 result 字段

- ToolAgentOutput 移除 result_summary 和 ui_hints,统一使用 result 字段
- 日历/用户查找工具移除 ui_hints 输出,改为机器可读的结构化结果
- Agent History 移除 tool 消息的 ui_hints 处理逻辑
- App 版本检查改为 manifest.json 方式,支持多渠道发布
- 更新 settings 配置和测试用例适配新结构
This commit is contained in:
qzl
2026-03-17 12:18:09 +08:00
parent c26cdbbc27
commit aa30fe0ce6
44 changed files with 984 additions and 655 deletions
@@ -38,8 +38,7 @@ def test_tool_result_wire_event_with_bare_fields() -> None:
"tool_call_id": "call-1",
"tool_call_args": {"start_date": "2024-01-01"},
"status": "success",
"result_summary": "summary",
"ui_schema": {"version": "2.0"},
"result": "summary",
},
}
@@ -50,8 +49,7 @@ def test_tool_result_wire_event_with_bare_fields() -> None:
assert result["tool_name"] == "calendar_write"
assert result["tool_call_id"] == "call-1"
assert result["status"] == "success"
assert result["result_summary"] == "summary"
assert result["ui_schema"] == {"version": "2.0"}
assert result["result"] == "summary"
def test_text_end_event_with_bare_fields() -> None:
@@ -124,7 +122,7 @@ def test_text_message_end_agui_event_strips_internal_usage_fields() -> None:
assert "model" not in result
def test_tool_call_result_agui_event_compiles_ui_hints_to_ui_schema() -> None:
def test_tool_call_result_agui_event_strips_tool_ui_fields() -> None:
event = {
"type": "TOOL_CALL_RESULT",
"threadId": "thread-1",
@@ -136,19 +134,20 @@ def test_tool_call_result_agui_event_compiles_ui_hints_to_ui_schema() -> None:
"tool_call_id": "call-1",
"tool_call_args": {"page": 1},
"status": "success",
"result_summary": "ok",
"result": "ok",
"ui_hints": {
"intent": "status",
"status": "success",
"title": "Done",
},
"ui_schema": {"version": "2.0"},
}
result = to_agui_wire_event(event)
assert result["type"] == "TOOL_CALL_RESULT"
assert "ui_hints" not in result
assert isinstance(result.get("ui_schema"), dict)
assert "ui_schema" not in result
def test_text_message_end_agui_event_compiles_ui_hints_to_ui_schema() -> None:
@@ -125,19 +125,19 @@ async def test_store_persists_tool_output_with_summary_as_content(
"tool_call_id": "call-1",
"tool_call_args": {"title": "A"},
"status": "success",
"result_summary": "已创建日程 A",
"ui_hints": {
"intent": "status",
"status": "success",
"sections": [],
},
"result": "status=success batch=1 success=1 failed=0 ids=[event-1]",
}
)
append_kwargs = cast(dict[str, Any], captured["append_kwargs"])
assert getattr(append_kwargs["role"], "value", None) == "tool"
assert append_kwargs["content"] == "已创建日程 A"
assert (
append_kwargs["content"]
== "status=success batch=1 success=1 failed=0 ids=[event-1]"
)
metadata = cast(dict[str, Any], append_kwargs["metadata"])
assert sorted(metadata.keys()) == ["run_id", "tool_agent_output"]
assert metadata["tool_agent_output"]["result_summary"] == "已创建日程 A"
assert metadata["tool_agent_output"]["ui_hints"]["intent"] == "status"
assert (
metadata["tool_agent_output"]["result"]
== "status=success batch=1 success=1 failed=0 ids=[event-1]"
)
@@ -1,73 +0,0 @@
from __future__ import annotations
from core.agentscope.events.tool_result_summary import build_tool_content_summary
def test_summary_prioritizes_error() -> None:
text = build_tool_content_summary(
tool_name="calendar_write",
args={"title": "A"},
result={"message": "ignored"},
error={"message": "denied"},
)
assert text == "calendar_write 执行失败:denied"
def test_summary_for_calendar_write() -> None:
text = build_tool_content_summary(
tool_name="calendar_write",
args={"title": "项目评审"},
result={"startAt": "明天 10:00"},
error=None,
)
assert text == "已创建日程:项目评审(明天 10:00)"
def test_summary_for_calendar_read() -> None:
text = build_tool_content_summary(
tool_name="calendar_read",
args={"query": "今天"},
result={"data": {"total": 3}},
error=None,
)
assert text == "查询到 3 条日程(今天)"
def test_summary_falls_back_to_result_content() -> None:
text = build_tool_content_summary(
tool_name="unknown_tool",
args=None,
result={"content": "这是非常长的说明" * 20},
error=None,
)
assert text.startswith("这是非常长的说明")
assert len(text) <= 80
def test_summary_default_done() -> None:
text = build_tool_content_summary(
tool_name="unknown_tool",
args=None,
result=None,
error=None,
)
assert text == "unknown_tool 执行完成"
def test_summary_marks_business_failure_when_ok_false() -> None:
text = build_tool_content_summary(
tool_name="calendar_write",
args={"title": "上学"},
result={
"type": "calendar_operation.v1",
"data": {
"ok": False,
"code": "UNAUTHORIZED",
"message": "calendar.write requires validated user token",
},
},
error=None,
)
assert (
text == "calendar_write 执行失败:calendar.write requires validated user token"
)