feat: structure main agent result cards

This commit is contained in:
kris
2026-03-29 19:51:06 +08:00
parent e48074e24b
commit f13c83a583
4 changed files with 144 additions and 0 deletions

View File

@@ -2740,6 +2740,115 @@ def register_oneliner_routes(app: Any, legacy: Any) -> None:
return intent_routes[intent_key]
return route("goto-production", "production", "回到生产中心", "继续推进当前主 Agent 任务的执行结果。")
def _build_agent_run_result_sections(
row: dict[str, Any],
plan: dict[str, Any],
recommended_action: dict[str, Any],
) -> dict[str, Any]:
source_screen = str(plan.get("source_screen") or row.get("source_screen") or "").strip().lower()
recommended_screen = str(recommended_action.get("screen") or "").strip().lower()
screen_key = recommended_screen or source_screen
intent_key = str(plan.get("intent_key") or row.get("intent_key") or "custom").strip().lower() or "custom"
platform = str(plan.get("platform") or row.get("platform") or "").strip()
platform_label = legacy.platform_label(platform) if platform else ""
plan_summary = str(plan.get("summary") or row.get("summary") or "").strip() or "主 Agent 已按当前上下文完成首轮收口。"
goal = str(plan.get("goal") or row.get("title") or "主 Agent 任务").strip() or "主 Agent 任务"
override_notice = _parse_json(row.get("active_admin_override_notice_json"), {})
workstream_map = {
"dashboard": ("dashboard", "首页动作"),
"discovery": ("discovery", "对标推进"),
"tracking": ("tracking", "跟踪推进"),
"production": ("production", "生产推进"),
"review": ("review", "复盘推进"),
"strategy": ("strategy", "策略治理"),
"playbook": ("playbook", "Agent 治理"),
"agent": ("playbook", "Agent 治理"),
"automation": ("automation", "自动流程"),
"intake": ("intake", "项目推进"),
"projects": ("intake", "项目推进"),
}
workstream_key, workstream_label = workstream_map.get(screen_key, ("production", "主 Agent 执行结果"))
if intent_key in {"analyze_account", "analyze_top_videos", "import_homepage"}:
workstream_key, workstream_label = "discovery", "对标推进"
elif intent_key == "track_account":
workstream_key, workstream_label = "tracking", "跟踪推进"
elif intent_key in {"ai_video", "real_cut", "live_recorder"}:
workstream_key, workstream_label = "production", "生产推进"
elif intent_key == "review":
workstream_key, workstream_label = "review", "复盘推进"
elif intent_key in {"create_assistant"}:
workstream_key, workstream_label = "playbook", "Agent 治理"
elif intent_key in {"create_project"}:
workstream_key, workstream_label = "intake", "项目推进"
elif intent_key in {"storage_status", "ops_admin"}:
workstream_key, workstream_label = "automation", "自动流程"
def card(title: str, body: str, *, tone: str = "blue", tags: list[str] | None = None) -> dict[str, Any]:
return {
"title": title,
"body": body,
"tone": tone,
"tags": [item for item in list(tags or []) if str(item).strip()],
}
cards = [
card(
"当前焦点",
f"围绕「{goal}」先完成一版可执行收口,避免你先在多个页面之间来回切换。",
tone="blue",
tags=[platform_label or "当前平台", workstream_label],
)
]
focus_body_map = {
"discovery": "优先回到找对标,继续看账号、相似关系和高分样本,再决定是否导入或加入跟踪。",
"tracking": "优先回到跟踪账号,看最近日报窗口和值得继续跟进的对象,再决定同步或加深跟踪。",
"production": "优先回到生产中心,看队列、失败恢复和产物,再决定下一步是推进还是补救。",
"review": "优先回到发布与复盘,把最近完成任务沉淀成结构化复盘,再决定是否继续发布。",
"strategy": "优先回到我的策略,先看当前生效层和管理员覆盖,再决定是否继续调整用户策略。",
"playbook": "优先回到 Agent 工作区,结合当前平台 Agent、模型和技能继续完善执行能力。",
"automation": "优先回到自动流程,先看依赖健康和动作防呆,再决定是否恢复或放行动作。",
"intake": "优先回到我的项目,先补项目、账号和导入基础,再决定往哪个工作页继续推进。",
"dashboard": "优先回到首页当前推荐动作,把这一轮的重点从概览转成真实执行。",
}
cards.append(
card(
workstream_label,
focus_body_map.get(workstream_key, plan_summary),
tone="green",
tags=[recommended_action.get("label") or "回到业务页"],
)
)
cards.append(
card(
"建议落点",
str(recommended_action.get("summary") or plan_summary).strip() or "回到对应业务页面继续推进。",
tone="orange" if override_notice.get("title") else "blue",
tags=[
recommended_action.get("screen") or "",
"管理员覆盖生效中" if override_notice.get("title") else "",
"全平台" if str(plan.get("platform_scope") or row.get("platform_scope") or "") == "all_platforms" else "单平台",
],
)
)
if override_notice.get("title"):
cards.append(
card(
"管理员覆盖提醒",
str(override_notice.get("summary") or "当前执行会优先遵循管理员覆盖层。").strip(),
tone="orange",
tags=[str(override_notice.get("title") or "管理员覆盖").strip()],
)
)
return {
"workstream_key": workstream_key,
"workstream_label": workstream_label,
"cards": cards,
}
def _complete_agent_run_for_read(row: dict[str, Any]) -> dict[str, Any]:
current_status = str(row.get("run_status") or "")
run_id = str(row.get("id") or "")
@@ -2783,6 +2892,7 @@ def register_oneliner_routes(app: Any, legacy: Any) -> None:
summary_text = str(plan.get("summary") or row.get("summary") or "").strip() or "主 Agent 已根据当前计划完成第一版执行收口。"
execution_summary = f"已完成「{str(plan.get('goal') or row.get('title') or '主 Agent 任务').strip() or '主 Agent 任务'}」的首轮执行建议。"
recommended_action = _build_agent_run_recommended_action(row, plan)
result_sections = _build_agent_run_result_sections(row, plan, recommended_action)
result_payload = {
"result_kind": "main_agent_plan",
"run_id": run_id,
@@ -2794,6 +2904,7 @@ def register_oneliner_routes(app: Any, legacy: Any) -> None:
"platform": str(plan.get("platform") or row.get("platform") or "").strip(),
"platform_scope": str(plan.get("platform_scope") or row.get("platform_scope") or "single_platform").strip() or "single_platform",
"recommended_action": recommended_action,
"result_sections": result_sections,
"active_admin_override_notice": _parse_json(row.get("active_admin_override_notice_json"), {}),
}
_log_agent_run_event(

View File

@@ -292,6 +292,9 @@ class MainAgentGovernanceTests(unittest.TestCase):
self.assertEqual(payload["result"]["result_kind"], "main_agent_plan")
self.assertEqual(payload["result"]["recommended_action"]["action"], "goto-discovery")
self.assertEqual(payload["result"]["recommended_action"]["screen"], "discovery")
self.assertEqual(payload["result"]["result_sections"]["workstream_key"], "discovery")
self.assertGreaterEqual(len(payload["result"]["result_sections"]["cards"]), 2)
self.assertEqual(payload["result"]["result_sections"]["cards"][0]["title"], "当前焦点")
event_types = [item["event_type"] for item in payload["events"]]
self.assertIn("run.progress", event_types)
self.assertIn("run.done", event_types)

View File

@@ -1808,6 +1808,10 @@ function renderOneLinerExecutionPayloadHtml(payload) {
const landingSummary = String(
payload.recommended_action?.summary || payload.execution_summary || payload.summary_text || ""
).trim();
const resultSections = payload.result_sections && typeof payload.result_sections === "object"
? payload.result_sections
: {};
const resultCards = safeArray(resultSections.cards).slice(0, 4);
const landingAttrs = buildMainAgentLandingAttrs({
runId: landingRunId,
screen: landingScreen,
@@ -1825,6 +1829,29 @@ function renderOneLinerExecutionPayloadHtml(payload) {
${payload.recommended_action?.action ? `<span class="tag clickable-tag" data-action="${escapeHtml(payload.recommended_action.action)}" data-main-agent-run-id="${escapeHtml(landingRunId)}" data-main-agent-screen="${escapeHtml(landingScreen)}" data-main-agent-title="${escapeHtml(landingTitle)}" data-main-agent-summary="${escapeHtml(landingSummary)}" ${landingAttrs}>${escapeHtml(payload.recommended_action.label || "回到对应页面")}</span>` : ""}
</div>
</div>
${resultCards.length ? `
<div class="task-item compact" style="margin-top:12px;">
<h4>${escapeHtml(resultSections.workstream_label || "执行结果分组")}</h4>
<p>${escapeHtml(payload.summary_text || "主 Agent 已将当前执行结果整理为可继续推进的结构化建议。")}</p>
<div class="detail-grid" style="margin-top:12px;">
${resultCards.map((card, index) => {
const tags = safeArray(card?.tags).slice(0, 3);
const tone = String(card?.tone || "").trim();
const toneClass = tone === "orange" ? "orange" : tone === "green" ? "green" : "blue";
return `
<div class="task-item compact">
<h4>${escapeHtml(card?.title || (index === 0 ? "当前焦点" : "执行结果"))}</h4>
<p>${escapeHtml(card?.body || "主 Agent 已生成一条可继续执行的结果说明。")}</p>
<div class="task-meta">
<span class="tag ${toneClass}">${escapeHtml(card?.title || (index === 0 ? "当前焦点" : "结果卡片"))}</span>
${tags.map((tag) => `<span class="tag">${escapeHtml(tag)}</span>`).join("")}
</div>
</div>
`;
}).join("")}
</div>
</div>
` : ""}
${payload.recommended_action?.summary ? `
<div class="task-item compact" style="margin-top:12px;">
<h4>建议回跳</h4>

View File

@@ -249,6 +249,9 @@ test("main agent result rendering offers a direct route back into the recommende
const execution = extractBetween(APP, "function renderOneLinerExecutionPayloadHtml(payload)", "function parseOneLinerActionPayloadValue(value)");
const lastAction = extractBetween(APP, "function renderLastActionCard()", "function getJobRecoveryCategory(job)");
assert.match(execution, /recommended_action/);
assert.match(execution, /result_sections/);
assert.match(execution, /当前焦点/);
assert.match(execution, /detail-grid/);
assert.match(execution, /data-action="\$\{escapeHtml\(payload\.recommended_action\.action\)\}"/);
assert.match(lastAction, /open-oneliner-run-result/);
assert.match(lastAction, /recommended_action/);