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