feat: add main agent run filters

This commit is contained in:
kris
2026-03-29 22:47:10 +08:00
parent 6c9b45ab37
commit 2f3ac47439
2 changed files with 32 additions and 1 deletions

View File

@@ -53,6 +53,7 @@ const appState = {
onelinerSessions: [], onelinerSessions: [],
selectedOnelinerSessionId: "", selectedOnelinerSessionId: "",
onelinerRuns: [], onelinerRuns: [],
onelinerRunFilter: "focus",
selectedOnelinerRunId: "", selectedOnelinerRunId: "",
lastCompletedOnelinerRunId: "", lastCompletedOnelinerRunId: "",
onelinerMessages: [], onelinerMessages: [],
@@ -984,6 +985,14 @@ function renderOneLinerRunsHtml() {
const pendingRunCount = safeArray(runs).filter((item) => item.run_status === "needs_confirmation").length; 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 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 completedRunCount = safeArray(runs).filter((item) => item.run_status === "done").length;
const filterKey = String(appState.onelinerRunFilter || "").trim() || (activeRunCount || pendingRunCount ? "focus" : "done");
const runFilterPredicates = {
focus: (item) => ["needs_confirmation", "queued", "running", "blocked"].includes(item.run_status),
done: (item) => item.run_status === "done",
all: () => true
};
const filteredRuns = safeArray(runs).filter(runFilterPredicates[filterKey] || runFilterPredicates.focus);
const visibleRuns = (filteredRuns.length ? filteredRuns : runs).slice(0, 8);
const recentCompletedRuns = safeArray(runs) const recentCompletedRuns = safeArray(runs)
.filter((item) => item.run_status === "done" && item.id !== currentRun.id) .filter((item) => item.run_status === "done" && item.id !== currentRun.id)
.slice(0, 3); .slice(0, 3);
@@ -1027,9 +1036,14 @@ function renderOneLinerRunsHtml() {
<span class="tag green">执行中 ${escapeHtml(formatNumber(activeRunCount))}</span> <span class="tag green">执行中 ${escapeHtml(formatNumber(activeRunCount))}</span>
<span class="tag">已完成 ${escapeHtml(formatNumber(completedRunCount))}</span> <span class="tag">已完成 ${escapeHtml(formatNumber(completedRunCount))}</span>
</div> </div>
<div class="task-meta" style="margin-top:10px;">
<span class="tag clickable-tag ${filterKey === "focus" ? "blue" : ""}" data-action="select-oneliner-run-filter" data-run-filter="focus">重点运行</span>
<span class="tag clickable-tag ${filterKey === "done" ? "green" : ""}" data-action="select-oneliner-run-filter" data-run-filter="done">已完成</span>
<span class="tag clickable-tag ${filterKey === "all" ? "orange" : ""}" data-action="select-oneliner-run-filter" data-run-filter="all">全部</span>
</div>
${runs.length > 1 ? ` ${runs.length > 1 ? `
<div class="chip-row" style="margin-top:10px;"> <div class="chip-row" style="margin-top:10px;">
${runs.slice(0, 6).map((item) => ` ${visibleRuns.map((item) => `
<span class="chip clickable-tag ${item.id === currentRun.id ? "active" : ""}" data-action="select-oneliner-run" data-run-id="${escapeHtml(item.id)}"> <span class="chip clickable-tag ${item.id === currentRun.id ? "active" : ""}" data-action="select-oneliner-run" data-run-id="${escapeHtml(item.id)}">
${escapeHtml(brief(item.title || item.plan?.goal || "主 Agent 任务", 14))} · ${escapeHtml({ ${escapeHtml(brief(item.title || item.plan?.goal || "主 Agent 任务", 14))} · ${escapeHtml({
needs_confirmation: "待确认", needs_confirmation: "待确认",
@@ -2118,6 +2132,8 @@ function openCurrentOneLinerRunResultAction(runId = "") {
renderAll(); renderAll();
return; return;
} }
appState.selectedOnelinerRunId = currentRun.id;
appState.onelinerRunFilter = currentRun.run_status === "done" ? "done" : appState.onelinerRunFilter;
openActionModal({ openActionModal({
title: currentRun.title || currentRun.plan?.goal || "主 Agent 执行结果", title: currentRun.title || currentRun.plan?.goal || "主 Agent 执行结果",
description: currentRun.result?.execution_summary || currentRun.status_summary || "这是当前主 Agent 任务的执行结果。", description: currentRun.result?.execution_summary || currentRun.status_summary || "这是当前主 Agent 任务的执行结果。",
@@ -10002,6 +10018,11 @@ document.addEventListener("click", async (event) => {
renderAll(); renderAll();
return; return;
} }
if (name === "select-oneliner-run-filter") {
appState.onelinerRunFilter = action.dataset.runFilter || "focus";
renderAll();
return;
}
if (name === "select-oneliner-session") { if (name === "select-oneliner-session") {
appState.selectedOnelinerSessionId = action.dataset.sessionId || ""; appState.selectedOnelinerSessionId = action.dataset.sessionId || "";
await loadOneLinerMessages(appState.selectedOnelinerSessionId); await loadOneLinerMessages(appState.selectedOnelinerSessionId);

View File

@@ -313,9 +313,19 @@ 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, /recentCompletedRuns/);
assert.match(runtime, /select-oneliner-run-filter/);
assert.match(runtime, /重点运行/);
assert.match(runtime, /已完成/);
assert.match(runtime, /全部/);
assert.match(runtime, /safeArray\(runs\)\.filter\(\(item\) => item\.run_status === "needs_confirmation"\)\.length/); assert.match(runtime, /safeArray\(runs\)\.filter\(\(item\) => item\.run_status === "needs_confirmation"\)\.length/);
}); });
test("opening a main agent run result keeps that run selected in the floating runtime", () => {
const resultAction = extractBetween(APP, "function openCurrentOneLinerRunResultAction(runId = \"\")", "function openConfirmOneLinerRunAction(runId = \"\")");
assert.match(resultAction, /appState\.selectedOnelinerRunId = currentRun\.id/);
assert.match(resultAction, /appState\.onelinerRunFilter = currentRun\.run_status === "done" \? "done" : appState\.onelinerRunFilter/);
});
test("oneliner panel auto-polls active runs while the floating panel stays open", () => { test("oneliner panel auto-polls active runs while the floating panel stays open", () => {
const render = extractBetween(APP, "function renderOneLinerUi()", "function openOneLinerPanel()"); const render = extractBetween(APP, "function renderOneLinerUi()", "function openOneLinerPanel()");
const open = extractBetween(APP, "function openOneLinerPanel()", "function closeOneLinerPanel()"); const open = extractBetween(APP, "function openOneLinerPanel()", "function closeOneLinerPanel()");