feat: 打通通知回执与消息状态留痕
This commit is contained in:
@@ -193,6 +193,11 @@ def _build_notification_payload(structured_output: dict, options: dict, status:
|
|||||||
"product_name": str(options.get("product_name", "")),
|
"product_name": str(options.get("product_name", "")),
|
||||||
"notify_reason": notify_reason,
|
"notify_reason": notify_reason,
|
||||||
"owners": owners,
|
"owners": owners,
|
||||||
|
"mentioned_users": structured_output.get("mentioned_users") or [],
|
||||||
|
"message_status": structured_output.get("message_status")
|
||||||
|
or ("sent" if status == "success" else "failed"),
|
||||||
|
"web_detail_url": structured_output.get("web_detail_url", ""),
|
||||||
|
"receipt": structured_output.get("receipt") or {},
|
||||||
"status": status,
|
"status": status,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -135,6 +135,11 @@ def _persist_notification_records(result: AgentResult, *, web_detail_url: str =
|
|||||||
owners = payload.get("owners") or []
|
owners = payload.get("owners") or []
|
||||||
if not owners:
|
if not owners:
|
||||||
return
|
return
|
||||||
|
resolved_detail_url = payload.get("web_detail_url") or web_detail_url
|
||||||
|
resolved_message_status = payload.get("message_status") or (
|
||||||
|
"sent" if result.status == "success" else "failed"
|
||||||
|
)
|
||||||
|
resolved_receipt = payload.get("receipt") or {"status": result.status}
|
||||||
for owner in owners:
|
for owner in owners:
|
||||||
create_notification_record(
|
create_notification_record(
|
||||||
batch_id=payload.get("batch_id", ""),
|
batch_id=payload.get("batch_id", ""),
|
||||||
@@ -144,9 +149,9 @@ def _persist_notification_records(result: AgentResult, *, web_detail_url: str =
|
|||||||
notify_reason=payload.get("notify_reason", "task_completed"),
|
notify_reason=payload.get("notify_reason", "task_completed"),
|
||||||
owner_role=owner.get("owner_role", ""),
|
owner_role=owner.get("owner_role", ""),
|
||||||
feishu_user_id=owner.get("feishu_user_id", ""),
|
feishu_user_id=owner.get("feishu_user_id", ""),
|
||||||
message_status="sent" if result.status == "success" else "failed",
|
message_status=resolved_message_status,
|
||||||
web_detail_url=web_detail_url,
|
web_detail_url=resolved_detail_url,
|
||||||
receipt={"status": result.status},
|
receipt=resolved_receipt,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -460,3 +460,54 @@ owner_mappings:
|
|||||||
assert result.notification_payload["notify_reason"] == "task_failed"
|
assert result.notification_payload["notify_reason"] == "task_failed"
|
||||||
assert owner["owner_name"] == "孙七"
|
assert owner["owner_name"] == "孙七"
|
||||||
assert owner["feishu_open_id"] == "on_failed_1"
|
assert owner["feishu_open_id"] == "on_failed_1"
|
||||||
|
|
||||||
|
|
||||||
|
def test_feishu_notification_report_builds_notification_payload_with_receipt_and_node_status():
|
||||||
|
scenario = {
|
||||||
|
"id": "document_review",
|
||||||
|
"name": "注册审核智能体",
|
||||||
|
"agent": {
|
||||||
|
"role": "注册审核助手",
|
||||||
|
"goal": "输出通知结果",
|
||||||
|
"instructions": ["输出结构化通知结果"],
|
||||||
|
},
|
||||||
|
"rag": {"enabled": False},
|
||||||
|
"tools": [],
|
||||||
|
"output": {"type": "feishu_notification_report"},
|
||||||
|
}
|
||||||
|
provider_response = """
|
||||||
|
{
|
||||||
|
"batch_id": "SUB-20260604-003",
|
||||||
|
"conversation_id": "conv-003",
|
||||||
|
"notify_reason": "task_completed",
|
||||||
|
"mentioned_users": ["ou_demo_1"],
|
||||||
|
"message_status": "sent",
|
||||||
|
"web_detail_url": "https://example.com/audit/3",
|
||||||
|
"receipt": {
|
||||||
|
"message_id": "msg-3",
|
||||||
|
"status": "sent"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
class FakeProvider:
|
||||||
|
def generate(self, messages, response_format=None):
|
||||||
|
from agent_core.llm_provider import LLMResponse
|
||||||
|
|
||||||
|
return LLMResponse(content=provider_response, model_name="demo-model", success=True)
|
||||||
|
|
||||||
|
result = run_agent(
|
||||||
|
scenario,
|
||||||
|
"请生成通知结果",
|
||||||
|
options={
|
||||||
|
"llm_provider": FakeProvider(),
|
||||||
|
"batch_id": "SUB-20260604-003",
|
||||||
|
"conversation_id": "conv-003",
|
||||||
|
"product_name": "产品C",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result.node_results[7]["status"] == "已完成"
|
||||||
|
assert result.notification_payload["message_status"] == "sent"
|
||||||
|
assert result.notification_payload["web_detail_url"] == "https://example.com/audit/3"
|
||||||
|
assert result.notification_payload["receipt"]["message_id"] == "msg-3"
|
||||||
|
|||||||
@@ -174,6 +174,51 @@ def test_chat_execution_creates_notification_record_from_agent_result(client, db
|
|||||||
assert record.web_detail_url.endswith(f"/audit/{AgentAuditLog.objects.get().id}/")
|
assert record.web_detail_url.endswith(f"/audit/{AgentAuditLog.objects.get().id}/")
|
||||||
|
|
||||||
|
|
||||||
|
def test_chat_execution_uses_notification_payload_message_status_and_receipt(client, db, monkeypatch):
|
||||||
|
batch, conversation = _create_conversation_with_batch()
|
||||||
|
UploadedDocument.objects.create(
|
||||||
|
batch=batch,
|
||||||
|
scenario_id="document_review",
|
||||||
|
original_name="说明书.md",
|
||||||
|
file_type="md",
|
||||||
|
size=1,
|
||||||
|
status=UploadedDocument.STATUS_INDEXED,
|
||||||
|
)
|
||||||
|
|
||||||
|
monkeypatch.setattr(
|
||||||
|
"apps.chat.views.run_agent",
|
||||||
|
lambda *args, **kwargs: AgentResult(
|
||||||
|
answer="通知已发送",
|
||||||
|
status="success",
|
||||||
|
notification_payload={
|
||||||
|
"batch_id": batch.batch_id,
|
||||||
|
"conversation_id": conversation.conversation_id,
|
||||||
|
"product_name": batch.product_name,
|
||||||
|
"notify_reason": "task_completed",
|
||||||
|
"message_status": "sent",
|
||||||
|
"web_detail_url": "https://example.com/audit/custom",
|
||||||
|
"receipt": {"message_id": "msg-custom", "status": "sent"},
|
||||||
|
"owners": [
|
||||||
|
{
|
||||||
|
"owner_role": "注册资料负责人",
|
||||||
|
"feishu_user_id": "ou_demo_1",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
response = client.post(
|
||||||
|
reverse("chat:detail", args=[conversation.conversation_id]),
|
||||||
|
{"message": "执行通知任务"},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
record = NotificationRecord.objects.get()
|
||||||
|
assert record.message_status == "sent"
|
||||||
|
assert record.receipt["message_id"] == "msg-custom"
|
||||||
|
|
||||||
|
|
||||||
def test_chat_execution_creates_failed_notification_record_and_updates_conversation(client, db, monkeypatch):
|
def test_chat_execution_creates_failed_notification_record_and_updates_conversation(client, db, monkeypatch):
|
||||||
batch, conversation = _create_conversation_with_batch()
|
batch, conversation = _create_conversation_with_batch()
|
||||||
UploadedDocument.objects.create(
|
UploadedDocument.objects.create(
|
||||||
|
|||||||
Reference in New Issue
Block a user