feat: direct-execute discovery selected-account actions
Some checks failed
StoryForge CI / Baseline checks (push) Has been cancelled
StoryForge CI / Backend tests (push) Has been cancelled
StoryForge CI / Web tests (push) Has been cancelled

This commit is contained in:
kris
2026-04-05 07:08:47 +08:00
parent 6a98559e78
commit 7a75f1cd85
3 changed files with 222 additions and 21 deletions

View File

@@ -446,3 +446,8 @@
- `OneLiner / 主 Agent` 现在新增了 `直接查相似账号``直接存对标关系` 两条真实执行动作,不再只停留在“建议后跳回找对标”。
- `直接查相似账号` 会调用当前平台的相似搜索接口,返回真实候选数量,并在有候选账号时直接落到该账号详情。
- `直接存对标关系` 会优先复用最近一次相似搜索的候选,把它直接写入当前平台的对标关系,并把结果回写到找对标工作区。
### 找对标顶部动作改成 direct-execute
- `导入当前对标 / 加入跟踪 / 账号分析 / 高分分析 / 查相似 / 存对标` 这批高频动作现在默认直接执行,不再先开表单。
- 执行后会按真实 `recommended_action` 继续落到任务详情、当前对象或关系区;只有当前没有可直接执行的候选时,才回退到原来的高级表单。

View File

@@ -2361,23 +2361,108 @@ async function executeOneLinerAction(executorKey, options = {}) {
if (appState.selectedOnelinerSessionId) {
await loadOneLinerMessages(appState.selectedOnelinerSessionId);
}
openActionModal({
title: payload.title || "OneLiner 执行结果",
description: payload.summary || "已完成一次对话内执行。",
hideSubmit: true,
fields: [
{
type: "html",
label: "执行结果",
html: `<div class="sheet-html">${renderOneLinerExecutionPayloadHtml(payload.payload || {})}</div>`
}
]
});
if (options.showResultModal !== false) {
openActionModal({
title: payload.title || "OneLiner 执行结果",
description: payload.summary || "已完成一次对话内执行。",
hideSubmit: true,
fields: [
{
type: "html",
label: "执行结果",
html: `<div class="sheet-html">${renderOneLinerExecutionPayloadHtml(payload.payload || {})}</div>`
}
]
});
}
rememberAction("OneLiner 已执行", payload.summary || "当前动作已在对话内执行。", "green", payload);
renderAll();
return payload;
}
async function followRecommendedActionResult(payload, options = {}) {
const recommendedAction = payload?.recommended_action && typeof payload.recommended_action === "object"
? payload.recommended_action
: null;
if (!recommendedAction?.action) return false;
const actionName = String(recommendedAction.action || "").trim();
const platform = normalizePlatformValue(
recommendedAction.platform || payload?.payload?.platform || options.platform || getPreferredPlatform(),
getPreferredPlatform()
);
if (options.refreshWorkbench) {
await bootstrap();
}
if (actionName === "open-job-detail" && recommendedAction.job_id) {
closeActionModal();
openJobDetailAction(recommendedAction.job_id);
return true;
}
if (actionName === "select-account" && recommendedAction.account_id) {
closeActionModal();
await loadPlatformAccount(platform, recommendedAction.account_id);
if (options.discoveryFocus === "relations") {
focusDiscoveryRelations();
} else if (options.discoveryFocus === "snapshots") {
focusDiscoveryInsights();
} else if (options.discoveryFocus === "top-videos") {
focusDiscoveryTopVideoInsights();
} else {
focusDiscoveryDetailTab("overview");
}
return true;
}
if (actionName === "goto-tracking") {
closeActionModal();
focusTrackingWorkspace();
return true;
}
if (actionName === "open-edit-assistant" && recommendedAction.assistant_id) {
closeActionModal();
focusPlaybookWorkspace(recommendedAction.assistant_id);
return true;
}
if (actionName === "open-review-edit" && recommendedAction.review_id) {
closeActionModal();
focusReviewWorkspace(recommendedAction.review_id);
return true;
}
if (actionName === "goto-discovery") {
closeActionModal();
if (options.discoveryFocus === "relations") {
focusDiscoveryRelations();
} else {
focusDiscoveryDetailTab("overview");
}
return true;
}
return false;
}
async function runDirectDiscoveryAction(executorKey, payload, options = {}) {
const account = requireSelectedAccountRow();
const platform = getAccountPlatform(account);
setBusy(true, options.busyLabel || "正在执行当前动作...");
try {
const result = await executeOneLinerAction(executorKey, {
platform,
payload,
showResultModal: false
});
await followRecommendedActionResult(result, {
platform,
refreshWorkbench: true,
discoveryFocus: options.discoveryFocus || ""
});
return result;
} catch (error) {
presentActionFailure(error, options.errorTitle || "执行失败");
throw error;
} finally {
setBusy(false, "");
}
}
function openCurrentOneLinerRunResultAction(runId = "") {
openOneLinerRunContextAction(runId)
.then((currentRun) => {
@@ -6017,6 +6102,8 @@ function renderDiscoveryScreen() {
const topVideos = getHighScoreVideos(3);
const latestVideos = getLatestVideos(2);
const similarCandidates = safeArray(appState.lastSimilaritySearch?.candidates).slice(0, 5);
const saveBenchmarkActionName = similarCandidates.length ? "direct-save-benchmark-link" : "open-benchmark-link";
const saveBenchmarkActionLabel = similarCandidates.length ? "直接存对标" : "存对标";
const selectedProject = getSelectedProject();
const importedSources = getCurrentProjectSourcesForAccount(selected, selectedProject?.id || "");
const tracked = selected?.id ? isTrackedAccount(selected.id) : false;
@@ -6083,8 +6170,8 @@ function renderDiscoveryScreen() {
detailBodyHtml = renderDiscoveryRelationsSection(linkedAccounts, similarCandidates);
}
const discoveryActionsHtml = isMobileUi
? `${button("导入主页", "open-import-homepage")} ${button("交给主 Agent", "handoff-to-main-agent", "secondary", { attrs: discoveryHandoffAttrs })} ${button("存对标", "open-benchmark-link", "primary")}`
: `${button("导入主页", "open-import-homepage")} ${button("导入当前对标", "open-import-selected-account", "secondary")} ${button(tracked ? "已在跟踪" : "加入跟踪", "open-track-selected-account", "secondary")} ${button("账号分析", "analyze-selected-account", "secondary")} ${button("高分分析", "analyze-top-videos", "secondary")} ${button("查相似", "open-similar-search", "secondary")} ${button("交给主 Agent", "handoff-to-main-agent", "secondary", { attrs: discoveryHandoffAttrs })} ${button("存对标", "open-benchmark-link", "primary")}`;
? `${button("导入主页", "open-import-homepage")} ${button("交给主 Agent", "handoff-to-main-agent", "secondary", { attrs: discoveryHandoffAttrs })} ${button(saveBenchmarkActionLabel, saveBenchmarkActionName, "primary")}`
: `${button("导入主页", "open-import-homepage")} ${button("导入当前对标", "direct-import-selected-account", "secondary")} ${button(tracked ? "更新跟踪" : "加入跟踪", "direct-track-selected-account", "secondary")} ${button("账号分析", "direct-analyze-selected-account", "secondary")} ${button("高分分析", "direct-analyze-top-videos", "secondary")} ${button("查相似", "direct-search-similar", "secondary")} ${button("交给主 Agent", "handoff-to-main-agent", "secondary", { attrs: discoveryHandoffAttrs })} ${button(saveBenchmarkActionLabel, saveBenchmarkActionName, "primary")}`;
return screenShell(
"找对标",
`这里已经接入真实${currentPlatformLabel}账号列表和单账号详情`,
@@ -6119,9 +6206,9 @@ function renderDiscoveryScreen() {
</div>
<p>${escapeHtml(selected ? `先围绕 ${getAccountName(selected)} 做导入、分析和相似扩展。` : "先从账号池里选一个对象,再继续导入和分析。")}</p>
<div class="task-meta">
${actionTag("导入当前对标", "open-import-selected-account")}
${actionTag("账号分析", "analyze-selected-account")}
${actionTag("查相似", "open-similar-search")}
${actionTag("导入当前对标", "direct-import-selected-account")}
${actionTag("账号分析", "direct-analyze-selected-account")}
${actionTag("查相似", "direct-search-similar")}
</div>
</div>
<div class="compact-summary-row mobile-discovery-selected-summary" style="margin-bottom:14px;">
@@ -6206,9 +6293,9 @@ function renderDiscoveryScreen() {
</div>
<p>${escapeHtml(selected ? `先围绕 ${getAccountName(selected)} 做导入、分析和相似扩展。` : "先从账号池里选一个对象,再继续导入和分析。")}</p>
<div class="task-meta">
${actionTag("导入当前对标", "open-import-selected-account")}
${actionTag("账号分析", "analyze-selected-account")}
${actionTag("查相似", "open-similar-search")}
${actionTag("导入当前对标", "direct-import-selected-account")}
${actionTag("账号分析", "direct-analyze-selected-account")}
${actionTag("查相似", "direct-search-similar")}
</div>
</div>
<div class="mobile-only compact-summary-row mobile-secondary-card" style="margin-bottom:14px;">
@@ -11927,6 +12014,35 @@ document.addEventListener("click", async (event) => {
openTrackSelectedAccountAction();
return;
}
if (name === "direct-import-selected-account") {
const account = requireSelectedAccountRow();
const sourceUrl = String(getAccountProfileUrl(account) || "").trim();
if (!sourceUrl) {
openImportSelectedAccountAction();
return;
}
await runDirectDiscoveryAction("import-homepage", {
source_url: sourceUrl,
title: `${getAccountName(account) || "当前对标"} 对标主页`,
handle: getAccountHandle(account) || ""
}, {
busyLabel: "正在把当前对标接入项目...",
errorTitle: "导入当前对标失败"
});
return;
}
if (name === "direct-track-selected-account") {
const account = requireSelectedAccountRow();
await runDirectDiscoveryAction("track-account", {
target_account_id: account.id,
note: "由对标工作台直接加入跟踪。",
refresh_now: true
}, {
busyLabel: "正在更新跟踪状态...",
errorTitle: "加入跟踪失败"
});
return;
}
if (name === "refresh-tracked-account") {
try {
await refreshTrackedAccountAction(action.dataset.trackedAccountId || "");
@@ -12167,10 +12283,40 @@ document.addEventListener("click", async (event) => {
openAnalyzeSelectedAccountAction();
return;
}
if (name === "direct-analyze-selected-account") {
const account = requireSelectedAccountRow();
await runDirectDiscoveryAction("analyze-account", {
target_account_id: account.id,
max_videos: 6,
extra_focus: "",
temperature: 0.35,
auto_analyze_top_videos: true,
top_video_analysis_count: 4
}, {
busyLabel: "正在分析当前对标账号...",
errorTitle: "账号分析失败",
discoveryFocus: "snapshots"
});
return;
}
if (name === "analyze-top-videos") {
openAnalyzeTopVideosAction();
return;
}
if (name === "direct-analyze-top-videos") {
const account = requireSelectedAccountRow();
await runDirectDiscoveryAction("analyze-top-videos", {
target_account_id: account.id,
top_video_count: 5,
min_score: 45,
temperature: 0.25
}, {
busyLabel: "正在分析高分作品...",
errorTitle: "高分作品分析失败",
discoveryFocus: "top-videos"
});
return;
}
if (name === "open-generate-copy") {
openGenerateCopyAction();
return;
@@ -12216,10 +12362,43 @@ document.addEventListener("click", async (event) => {
openSimilaritySearchAction();
return;
}
if (name === "direct-search-similar") {
const account = requireSelectedAccountRow();
await runDirectDiscoveryAction("search-similar-accounts", {
target_account_id: account.id,
max_candidates: 8,
extra_requirements: ""
}, {
busyLabel: "正在查找相似账号...",
errorTitle: "查相似失败",
discoveryFocus: "relations"
});
return;
}
if (name === "open-benchmark-link") {
openBenchmarkLinkAction();
return;
}
if (name === "direct-save-benchmark-link") {
const account = requireSelectedAccountRow();
const candidate = safeArray(appState.lastSimilaritySearch?.candidates)[0] || null;
if (!candidate) {
openBenchmarkLinkAction();
return;
}
await runDirectDiscoveryAction("save-benchmark-link", {
source_account_id: account.id,
target_account_id: candidate.candidate_account_id || "",
target_profile_url: candidate.candidate_account_id ? "" : (candidate.candidate_profile_url || ""),
search_id: appState.lastSimilaritySearch?.id || "",
note: brief(candidate.rationale_text || "由对标工作台直接加入对标库。", 120)
}, {
busyLabel: "正在保存对标关系...",
errorTitle: "保存对标失败",
discoveryFocus: "relations"
});
return;
}
if (name === "save-candidate-benchmark") {
setBusy(true, "正在保存对标关系...");
try {

View File

@@ -433,13 +433,30 @@ test("mobile discovery and production simplify duplicated top-level actions", ()
assert.match(discovery, /const isMobileUi = isMobileViewport\(\);/);
assert.match(discovery, /const discoveryActionsHtml = isMobileUi/);
assert.match(discovery, /button\("导入主页", "open-import-homepage"\)/);
assert.match(discovery, /button\("对标", "open-benchmark-link"/);
assert.match(discovery, /button\("导入当前对标", "direct-import-selected-account"/);
assert.match(discovery, /button\("查相似", "direct-search-similar"/);
assert.match(discovery, /saveBenchmarkActionName = similarCandidates\.length \? "direct-save-benchmark-link" : "open-benchmark-link"/);
assert.match(production, /const isMobileUi = isMobileViewport\(\);/);
assert.match(production, /const productionActionsHtml = isMobileUi/);
assert.match(production, /button\("交给主 Agent", "handoff-to-main-agent"/);
assert.match(production, /button\("去复盘", "goto-review", "primary"\)/);
});
test("discovery page promotes selected-account actions into direct execute flows", () => {
const discovery = extractBetween(APP, "function renderDiscoveryScreen()", "function renderTrackingScreen()");
assert.match(APP, /async function runDirectDiscoveryAction\(executorKey, payload, options = \{\}\)/);
assert.match(APP, /async function followRecommendedActionResult\(payload, options = \{\}\)/);
assert.match(discovery, /actionTag\("导入当前对标", "direct-import-selected-account"\)/);
assert.match(discovery, /actionTag\("账号分析", "direct-analyze-selected-account"\)/);
assert.match(discovery, /actionTag\("查相似", "direct-search-similar"\)/);
assert.match(APP, /if \(name === "direct-import-selected-account"\)/);
assert.match(APP, /if \(name === "direct-track-selected-account"\)/);
assert.match(APP, /if \(name === "direct-analyze-selected-account"\)/);
assert.match(APP, /if \(name === "direct-analyze-top-videos"\)/);
assert.match(APP, /if \(name === "direct-search-similar"\)/);
assert.match(APP, /if \(name === "direct-save-benchmark-link"\)/);
});
test("mobile discovery prioritizes the selected-account task flow before the scrollable account list", () => {
const discovery = extractBetween(APP, "function renderDiscoveryScreen()", "function renderTrackingScreen()");
assert.match(discovery, /mobile-discovery-priority/);