From e0486708b718a711aec43ee776ab32184ec503f8 Mon Sep 17 00:00:00 2001 From: kris Date: Sun, 29 Mar 2026 19:55:22 +0800 Subject: [PATCH] feat: surface main agent results on landing pages --- web/storyforge-web-v4/assets/app.js | 18 ++++++++++++++++++ .../tests/workbench-pages.test.mjs | 3 +++ 2 files changed, 21 insertions(+) diff --git a/web/storyforge-web-v4/assets/app.js b/web/storyforge-web-v4/assets/app.js index 142c1c3..c310760 100644 --- a/web/storyforge-web-v4/assets/app.js +++ b/web/storyforge-web-v4/assets/app.js @@ -4444,12 +4444,30 @@ function captureMainAgentLandingContext(action, targetScreen) { function renderMainAgentLandingNotice(screenKey) { const landing = appState.mainAgentLanding; if (!landing || landing.screen !== screenKey) return ""; + const landingRun = safeArray(appState.onelinerRuns).find((item) => item.id === landing.runId); + const resultSections = landingRun?.result?.result_sections && typeof landingRun.result.result_sections === "object" + ? landingRun.result.result_sections + : {}; + const cards = safeArray(resultSections.cards).slice(0, 2); + const recommendedAction = landingRun?.result?.recommended_action || null; return `

你正在处理主 Agent 的结果

${escapeHtml(landing.summary || landing.title || "这是主 Agent 刚刚给出的下一步落点。")}

+ ${cards.length ? ` +
+ ${cards.map((card, index) => ` +
+

${escapeHtml(card?.title || (index === 0 ? "当前焦点" : "结果摘要"))}

+

${escapeHtml(card?.body || "主 Agent 已整理出一条可继续推进的建议。")}

+
+ `).join("")} +
+ ` : ""}
${landing.title ? `${escapeHtml(landing.title)}` : ""} + ${resultSections.workstream_label ? `${escapeHtml(resultSections.workstream_label)}` : ""} + ${recommendedAction?.label ? `${escapeHtml(recommendedAction.label)}` : ""} ${landing.runId ? `查看结果` : ""} 收起提示
diff --git a/web/storyforge-web-v4/tests/workbench-pages.test.mjs b/web/storyforge-web-v4/tests/workbench-pages.test.mjs index 65a4575..a268b18 100644 --- a/web/storyforge-web-v4/tests/workbench-pages.test.mjs +++ b/web/storyforge-web-v4/tests/workbench-pages.test.mjs @@ -261,11 +261,14 @@ test("main agent route actions keep landing context and destination screens rend const execution = extractBetween(APP, "function renderOneLinerExecutionPayloadHtml(payload)", "function parseOneLinerActionPayloadValue(value)"); const actions = extractBetween(APP, "document.addEventListener(\"click\", async (event) => {", "document.addEventListener(\"submit\", async (event) => {"); const strategy = extractBetween(APP, "function renderStrategyScreen()", "function renderCreditsScreen()"); + const landing = extractBetween(APP, "function renderMainAgentLandingNotice(screenKey)", "function renderEmptyState(title, description)"); const production = extractBetween(APP, "function renderProductionScreen()", "function renderReviewScreen()"); assert.match(execution, /data-main-agent-run-id/); assert.match(actions, /captureMainAgentLandingContext\(action,\s*"goto-production"/); assert.match(actions, /captureMainAgentLandingContext\(action,\s*"goto-strategy"/); assert.match(actions, /name === "dismiss-main-agent-landing"/); + assert.match(landing, /result_sections/); + assert.match(landing, /detail-grid/); assert.match(strategy, /renderMainAgentLandingNotice\("strategy"\)/); assert.match(production, /renderMainAgentLandingNotice\("production"\)/); });