feat: 持久化会话节点结果与失败通知留痕
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
from django.utils import timezone
|
||||||
from django.shortcuts import get_object_or_404, redirect, render
|
from django.shortcuts import get_object_or_404, redirect, render
|
||||||
|
|
||||||
from agent_core.orchestrator import run_agent
|
from agent_core.orchestrator import run_agent
|
||||||
@@ -70,8 +71,10 @@ def detail(request, conversation_id: str):
|
|||||||
conversation_id=conversation.conversation_id,
|
conversation_id=conversation.conversation_id,
|
||||||
product_name=conversation.product_name,
|
product_name=conversation.product_name,
|
||||||
)
|
)
|
||||||
|
_apply_agent_result_to_conversation(conversation, result)
|
||||||
_persist_notification_records(result)
|
_persist_notification_records(result)
|
||||||
active_node = "risk"
|
active_node = "risk"
|
||||||
|
conversation.refresh_from_db()
|
||||||
workspace_summary = _build_workspace_summary(conversation, batch)
|
workspace_summary = _build_workspace_summary(conversation, batch)
|
||||||
|
|
||||||
return render(
|
return render(
|
||||||
@@ -129,3 +132,25 @@ def _build_workspace_summary(conversation: Conversation, batch: SubmissionBatch
|
|||||||
"file_count": batch.file_count if batch else 0,
|
"file_count": batch.file_count if batch else 0,
|
||||||
"page_count": batch.page_count if batch else 0,
|
"page_count": batch.page_count if batch else 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _apply_agent_result_to_conversation(conversation: Conversation, result: AgentResult) -> None:
|
||||||
|
conversation.task_status = result.status
|
||||||
|
if result.node_results:
|
||||||
|
conversation.node_results = result.node_results
|
||||||
|
conversation.latest_summary = {
|
||||||
|
"answer": result.answer,
|
||||||
|
"status": result.status,
|
||||||
|
"error": result.error,
|
||||||
|
"notification_payload": result.notification_payload,
|
||||||
|
}
|
||||||
|
conversation.last_run_at = timezone.now()
|
||||||
|
conversation.save(
|
||||||
|
update_fields=[
|
||||||
|
"task_status",
|
||||||
|
"node_results",
|
||||||
|
"latest_summary",
|
||||||
|
"last_run_at",
|
||||||
|
"updated_at",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|||||||
@@ -172,6 +172,106 @@ def test_chat_execution_creates_notification_record_from_agent_result(client, db
|
|||||||
assert record.batch_id == batch.batch_id
|
assert record.batch_id == batch.batch_id
|
||||||
|
|
||||||
|
|
||||||
|
def test_chat_execution_creates_failed_notification_record_and_updates_conversation(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="failed",
|
||||||
|
error="规则执行失败",
|
||||||
|
node_results=[
|
||||||
|
{"code": "package_import", "label": "资料包导入", "status": "已完成"},
|
||||||
|
{"code": "overview", "label": "目录汇总", "status": "已完成"},
|
||||||
|
{"code": "risk", "label": "风险预警", "status": "已阻断"},
|
||||||
|
{"code": "feishu_notify", "label": "飞书通知", "status": "失败"},
|
||||||
|
],
|
||||||
|
notification_payload={
|
||||||
|
"batch_id": batch.batch_id,
|
||||||
|
"conversation_id": conversation.conversation_id,
|
||||||
|
"product_name": batch.product_name,
|
||||||
|
"notify_reason": "task_failed",
|
||||||
|
"owners": [
|
||||||
|
{
|
||||||
|
"owner_role": "注册申报负责人",
|
||||||
|
"feishu_user_id": "ou_demo_2",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
response = client.post(
|
||||||
|
reverse("chat:detail", args=[conversation.conversation_id]),
|
||||||
|
{"message": "执行失败任务"},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
record = NotificationRecord.objects.get()
|
||||||
|
conversation.refresh_from_db()
|
||||||
|
assert record.notify_reason == "task_failed"
|
||||||
|
assert record.message_status == "failed"
|
||||||
|
assert conversation.task_status == "failed"
|
||||||
|
assert conversation.node_results[-1]["label"] == "飞书通知"
|
||||||
|
|
||||||
|
|
||||||
|
def test_chat_execution_persists_agent_node_results_to_conversation(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",
|
||||||
|
node_results=[
|
||||||
|
{"code": "package_import", "label": "资料包导入", "status": "已完成"},
|
||||||
|
{"code": "overview", "label": "目录汇总", "status": "已完成"},
|
||||||
|
{"code": "completeness", "label": "法规完整性检查", "status": "已完成"},
|
||||||
|
{"code": "field_extraction", "label": "字段抽取", "status": "已完成"},
|
||||||
|
{"code": "consistency", "label": "一致性核查", "status": "待复核"},
|
||||||
|
{"code": "risk", "label": "风险预警", "status": "已阻断", "summary": "存在高风险"},
|
||||||
|
{"code": "word_export", "label": "Word 回填导出", "status": "待处理"},
|
||||||
|
{"code": "feishu_notify", "label": "飞书通知", "status": "待处理"},
|
||||||
|
],
|
||||||
|
notification_payload={
|
||||||
|
"batch_id": batch.batch_id,
|
||||||
|
"conversation_id": conversation.conversation_id,
|
||||||
|
"product_name": batch.product_name,
|
||||||
|
"notify_reason": "task_completed",
|
||||||
|
"owners": [],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
response = client.post(
|
||||||
|
reverse("chat:detail", args=[conversation.conversation_id]),
|
||||||
|
{"message": "执行节点任务"},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
conversation.refresh_from_db()
|
||||||
|
assert len(conversation.node_results) == 8
|
||||||
|
assert conversation.task_status == "success"
|
||||||
|
assert conversation.latest_summary["answer"] == "已生成风险结论"
|
||||||
|
|
||||||
|
|
||||||
def test_create_conversation_for_batch_initializes_eight_workflow_nodes(db):
|
def test_create_conversation_for_batch_initializes_eight_workflow_nodes(db):
|
||||||
conversation = create_conversation_for_batch(
|
conversation = create_conversation_for_batch(
|
||||||
"SUB-20260604-001",
|
"SUB-20260604-001",
|
||||||
|
|||||||
Reference in New Issue
Block a user