diff --git a/web/storyforge-web-v4/assets/app.js b/web/storyforge-web-v4/assets/app.js
index c310760..c6f475f 100644
--- a/web/storyforge-web-v4/assets/app.js
+++ b/web/storyforge-web-v4/assets/app.js
@@ -984,6 +984,9 @@ function renderOneLinerRunsHtml() {
const pendingRunCount = safeArray(runs).filter((item) => item.run_status === "needs_confirmation").length;
const activeRunCount = safeArray(runs).filter((item) => ["queued", "running", "blocked"].includes(item.run_status)).length;
const completedRunCount = safeArray(runs).filter((item) => item.run_status === "done").length;
+ const recentCompletedRuns = safeArray(runs)
+ .filter((item) => item.run_status === "done" && item.id !== currentRun.id)
+ .slice(0, 3);
const previewLandingAttrs = buildMainAgentLandingAttrs({
runId: currentRun.id || "",
screen: previewAction?.screen || "",
@@ -1109,6 +1112,33 @@ function renderOneLinerRunsHtml() {
`).join("")}
` : ""}
+ ${recentCompletedRuns.length ? `
+
+
最近完成
+
+ ${recentCompletedRuns.map((item) => {
+ const doneAction = item.result?.recommended_action || null;
+ const doneLandingAttrs = buildMainAgentLandingAttrs({
+ runId: item.id || "",
+ screen: doneAction?.screen || "",
+ title: item.title || item.plan?.goal || "主 Agent 任务",
+ summary: doneAction?.summary || item.status_summary || ""
+ });
+ return `
+
+
${escapeHtml(item.title || item.plan?.goal || "主 Agent 任务")}
+
${escapeHtml(item.status_summary || item.summary || "已完成,可继续回看结果。")}
+
+ 已完成
+ 查看结果
+ ${doneAction?.action ? `${escapeHtml(doneAction.label || "回到对应页面")}` : ""}
+
+
+ `;
+ }).join("")}
+
+
+ ` : ""}
`;
}
diff --git a/web/storyforge-web-v4/tests/workbench-pages.test.mjs b/web/storyforge-web-v4/tests/workbench-pages.test.mjs
index a268b18..7eb2aa3 100644
--- a/web/storyforge-web-v4/tests/workbench-pages.test.mjs
+++ b/web/storyforge-web-v4/tests/workbench-pages.test.mjs
@@ -307,6 +307,8 @@ test("oneliner runtime shows grouped run health summary above the current run ca
assert.match(runtime, /待确认/);
assert.match(runtime, /执行中/);
assert.match(runtime, /已完成/);
+ assert.match(runtime, /最近完成/);
+ assert.match(runtime, /recentCompletedRuns/);
assert.match(runtime, /safeArray\(runs\)\.filter\(\(item\) => item\.run_status === "needs_confirmation"\)\.length/);
});