feat: route main agent results back into workbench
This commit is contained in:
@@ -2682,6 +2682,58 @@ def register_oneliner_routes(app: Any, legacy: Any) -> None:
|
||||
)
|
||||
return bool(row)
|
||||
|
||||
def _build_agent_run_recommended_action(row: dict[str, Any], plan: dict[str, Any]) -> dict[str, Any]:
|
||||
source_screen = str(plan.get("source_screen") or row.get("source_screen") or "").strip().lower()
|
||||
source_action_key = str(plan.get("source_action_key") or row.get("source_action_key") or "").strip().lower()
|
||||
intent_key = str(plan.get("intent_key") or row.get("intent_key") or "custom").strip().lower() or "custom"
|
||||
|
||||
def route(action: str, screen: str, label: str, summary: str) -> dict[str, Any]:
|
||||
return {
|
||||
"action": action,
|
||||
"screen": screen,
|
||||
"label": label,
|
||||
"summary": summary,
|
||||
}
|
||||
|
||||
source_routes = {
|
||||
"strategy": route("goto-strategy", "strategy", "回到我的策略", "继续查看当前用户策略与覆盖状态。"),
|
||||
"automation": route("goto-automation", "automation", "回到自动流程", "继续检查自动流程和依赖状态。"),
|
||||
"playbook": route("goto-playbook", "playbook", "回到 Agent", "继续调整 Agent 与平台能力。"),
|
||||
"agent": route("goto-playbook", "playbook", "回到 Agent", "继续调整 Agent 与平台能力。"),
|
||||
"production": route("goto-production", "production", "回到生产中心", "继续推进生产任务与恢复动作。"),
|
||||
"tracking": route("goto-tracking", "tracking", "回到跟踪账号", "继续查看跟踪摘要和更新提醒。"),
|
||||
"review": route("goto-review", "review", "回到发布与复盘", "继续沉淀复盘结论和发布结果。"),
|
||||
"discovery": route("goto-discovery", "discovery", "回到找对标", "继续查看账号拆解和高分样本。"),
|
||||
"intake": route("goto-intake", "projects", "回到我的项目", "继续切换项目或补齐项目基础信息。"),
|
||||
"projects": route("goto-intake", "projects", "回到我的项目", "继续切换项目或补齐项目基础信息。"),
|
||||
}
|
||||
if source_screen == "dashboard" and source_action_key == "homepage-primary-action":
|
||||
return route("goto-discovery", "discovery", "回到找对标", "继续查看首页当前最优先的对标与高分样本动作。")
|
||||
if source_screen == "dashboard" and source_action_key.startswith("homepage-secondary-action-"):
|
||||
if intent_key == "track_account":
|
||||
return route("goto-tracking", "tracking", "回到跟踪账号", "继续跟进首页建议的重点账号跟踪。")
|
||||
return route("goto-production", "production", "回到生产中心", "继续处理首页建议的生产推进动作。")
|
||||
if source_screen in source_routes:
|
||||
return source_routes[source_screen]
|
||||
|
||||
intent_routes = {
|
||||
"analyze_account": route("goto-discovery", "discovery", "回到找对标", "继续拆解当前账号和对标对象。"),
|
||||
"analyze_top_videos": route("goto-discovery", "discovery", "回到找对标", "继续查看高分作品分析结论。"),
|
||||
"track_account": route("goto-tracking", "tracking", "回到跟踪账号", "继续更新账号跟踪与日报。"),
|
||||
"ai_video": route("goto-production", "production", "回到生产中心", "继续推进 AI 视频生产任务。"),
|
||||
"real_cut": route("goto-production", "production", "回到生产中心", "继续推进实拍剪辑任务。"),
|
||||
"live_recorder": route("goto-production", "production", "回到生产中心", "继续查看录制维护与产物。"),
|
||||
"review": route("goto-review", "review", "回到发布与复盘", "继续补齐复盘与发布总结。"),
|
||||
"create_assistant": route("goto-playbook", "playbook", "回到 Agent", "继续创建或调整项目 Agent。"),
|
||||
"create_project": route("goto-intake", "projects", "回到我的项目", "继续创建或切换当前项目。"),
|
||||
"import_homepage": route("goto-discovery", "discovery", "回到找对标", "继续处理主页导入后的账号分析。"),
|
||||
"ops_admin": route("goto-automation", "automation", "回到自动流程", "继续查看系统依赖和治理状态。"),
|
||||
"storage_status": route("goto-automation", "automation", "回到自动流程", "继续查看存储与依赖健康状态。"),
|
||||
}
|
||||
if intent_key in intent_routes:
|
||||
return intent_routes[intent_key]
|
||||
return route("goto-production", "production", "回到生产中心", "继续推进当前主 Agent 任务的执行结果。")
|
||||
|
||||
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 "")
|
||||
@@ -2724,6 +2776,7 @@ def register_oneliner_routes(app: Any, legacy: Any) -> None:
|
||||
steps = ["读取当前项目上下文", "结合治理层生成执行计划", "收口为可执行建议"]
|
||||
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_payload = {
|
||||
"result_kind": "main_agent_plan",
|
||||
"goal": str(plan.get("goal") or row.get("title") or "主 Agent 任务").strip() or "主 Agent 任务",
|
||||
@@ -2733,6 +2786,7 @@ def register_oneliner_routes(app: Any, legacy: Any) -> None:
|
||||
"intent_key": str(plan.get("intent_key") or row.get("intent_key") or "custom").strip() or "custom",
|
||||
"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,
|
||||
"active_admin_override_notice": _parse_json(row.get("active_admin_override_notice_json"), {}),
|
||||
}
|
||||
_log_agent_run_event(
|
||||
|
||||
@@ -286,6 +286,8 @@ class MainAgentGovernanceTests(unittest.TestCase):
|
||||
self.assertEqual(payload["run_status"], "done")
|
||||
self.assertTrue(payload["finished_at"])
|
||||
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")
|
||||
event_types = [item["event_type"] for item in payload["events"]]
|
||||
self.assertIn("run.progress", event_types)
|
||||
self.assertIn("run.done", event_types)
|
||||
|
||||
@@ -977,6 +977,7 @@ function renderOneLinerRunsHtml() {
|
||||
const runEvents = safeArray(currentRun.events).slice(-3);
|
||||
const planSteps = safeArray(currentRun.plan?.steps).slice(0, 4);
|
||||
const resultPayload = currentRun.result && typeof currentRun.result === "object" ? currentRun.result : null;
|
||||
const recommendedAction = resultPayload?.recommended_action || null;
|
||||
const hasResultPayload = Boolean(resultPayload && Object.keys(resultPayload).length);
|
||||
const runStatusLabel = {
|
||||
needs_confirmation: "待确认",
|
||||
@@ -1043,7 +1044,9 @@ function renderOneLinerRunsHtml() {
|
||||
<span class="tag ${statusTone}">${escapeHtml(currentRun.status_summary || "主 Agent 正在推进中")}</span>
|
||||
`}
|
||||
${hasResultPayload ? `<span class="tag clickable-tag" data-action="open-oneliner-run-result" data-run-id="${escapeHtml(currentRun.id)}">查看结果</span>` : ""}
|
||||
${recommendedAction?.action ? `<span class="tag clickable-tag" data-action="${escapeHtml(recommendedAction.action)}">${escapeHtml(recommendedAction.label || "回到对应页面")}</span>` : ""}
|
||||
</div>
|
||||
${recommendedAction?.summary ? `<div class="panel-subtitle" style="margin-top:8px;">${escapeHtml(recommendedAction.summary)}</div>` : ""}
|
||||
${hasResultPayload ? `
|
||||
<div class="task-item compact" style="margin-top:10px;">
|
||||
<h4>执行结果</h4>
|
||||
@@ -1737,8 +1740,15 @@ function renderOneLinerExecutionPayloadHtml(payload) {
|
||||
${payload.platform ? `<span class="tag blue">${escapeHtml(platformLabel(payload.platform))}</span>` : ""}
|
||||
<span class="tag">${escapeHtml(payload.platform_scope === "all_platforms" ? "全平台" : "单平台")}</span>
|
||||
<span class="tag green">已收口</span>
|
||||
${payload.recommended_action?.action ? `<span class="tag clickable-tag" data-action="${escapeHtml(payload.recommended_action.action)}">${escapeHtml(payload.recommended_action.label || "回到对应页面")}</span>` : ""}
|
||||
</div>
|
||||
</div>
|
||||
${payload.recommended_action?.summary ? `
|
||||
<div class="task-item compact" style="margin-top:12px;">
|
||||
<h4>建议回跳</h4>
|
||||
<p>${escapeHtml(payload.recommended_action.summary)}</p>
|
||||
</div>
|
||||
` : ""}
|
||||
${safeArray(payload.next_steps).length ? `
|
||||
<div class="list" style="margin-top:12px;">
|
||||
${safeArray(payload.next_steps).slice(0, 4).map((step, index) => `
|
||||
@@ -6174,6 +6184,9 @@ function extractGeneratedCopy(payload) {
|
||||
|
||||
function renderLastActionCard() {
|
||||
if (!appState.lastAction) return "";
|
||||
const payload = appState.lastAction.payload || {};
|
||||
const recommendedAction = payload?.result?.recommended_action || payload?.recommended_action || null;
|
||||
const runId = payload?.id || payload?.run_id || "";
|
||||
return `
|
||||
<div class="panel pad">
|
||||
<div class="panel-head">
|
||||
@@ -6186,6 +6199,12 @@ function renderLastActionCard() {
|
||||
<div class="task-item">
|
||||
<h4>${escapeHtml(appState.lastAction.title)}</h4>
|
||||
<p>${escapeHtml(appState.lastAction.summary)}</p>
|
||||
${(runId || recommendedAction?.action) ? `
|
||||
<div class="task-meta" style="margin-top:10px;">
|
||||
${runId ? `<span class="tag clickable-tag" data-action="open-oneliner-run-result" data-run-id="${escapeHtml(runId)}">查看结果</span>` : ""}
|
||||
${recommendedAction?.action ? `<span class="tag clickable-tag" data-action="${escapeHtml(recommendedAction.action)}">${escapeHtml(recommendedAction.label || "回到对应页面")}</span>` : ""}
|
||||
</div>
|
||||
` : ""}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -136,6 +136,7 @@ test("oneliner panel includes a dedicated runtime header for agent runs", () =>
|
||||
assert.match(runtime, /当前计划/);
|
||||
assert.match(runtime, /renderOneLinerExecutionPayloadHtml\(currentRun\.result\)/);
|
||||
assert.match(runtime, /open-oneliner-run-result/);
|
||||
assert.match(runtime, /recommended_action/);
|
||||
});
|
||||
|
||||
test("oneliner meta and action handlers expose governance entry points", () => {
|
||||
@@ -229,3 +230,12 @@ test("user governance UI exposes personal history and rollback entrypoints", ()
|
||||
assert.match(actions, /name === "open-user-global-policy-history"/);
|
||||
assert.match(actions, /name === "open-user-platform-policy-history"/);
|
||||
});
|
||||
|
||||
test("main agent result rendering offers a direct route back into the recommended screen", () => {
|
||||
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, /data-action="\$\{escapeHtml\(payload\.recommended_action\.action\)\}"/);
|
||||
assert.match(lastAction, /open-oneliner-run-result/);
|
||||
assert.match(lastAction, /recommended_action/);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user