From 3f3c8de949dece549dcb96891b6deaa5745a2e44 Mon Sep 17 00:00:00 2001 From: kris Date: Mon, 30 Mar 2026 22:06:05 +0800 Subject: [PATCH] fix: remove stale missing-capability fallbacks --- CHANGELOG.md | 3 +- web/storyforge-web-v4/assets/app.js | 99 +++++-------------- .../tests/workbench-pages.test.mjs | 10 +- 3 files changed, 38 insertions(+), 74 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c7cb806..d3b72ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ - 任务恢复链会优先真实调用 `/v2/explore/jobs/{job_id}/retry`,只有接口真的不存在时才回退到手动恢复模板。 - `找对标 / 跟踪账号` 里一批已经失效的 “当前平台待接入” 按钮禁用与入口分支已删除,当前 active 平台都直接走真实路由,失败时再给真实反馈。 - 工作台前端已经清掉浏览器 `alert` 弹窗,缺对象、权限不足、刷新失败和加载失败都会回到站内反馈,不再把用户从当前流程里打断出去。 +- `OneLiner 会话 / 主 Agent 运行 / 动作执行器 / 跟踪同步 / 高分分析 / 平台技能验收` 这批真接口也已经去掉“当前实例未提供”的旧降级口径,统一按 live 结果说话。 ### NAS 联调与回归 @@ -39,7 +40,7 @@ - Web: `http://192.168.31.188:19192/` - Collector: `http://192.168.31.188:19193/healthz` - 当前基线通过: - - 前端测试 `61/61` + - 前端测试 `62/62` - `bash scripts/check_repo_baseline.sh` - `bash scripts/smoke_fnos_storyforge_lan.sh` diff --git a/web/storyforge-web-v4/assets/app.js b/web/storyforge-web-v4/assets/app.js index a18b543..9f1be6d 100644 --- a/web/storyforge-web-v4/assets/app.js +++ b/web/storyforge-web-v4/assets/app.js @@ -1845,11 +1845,6 @@ async function ensureOneLinerSession() { project_id: projectId, preferred_platform: getPreferredPlatform() } - }).catch((error) => { - if (isMissingBackendCapability(error)) { - throw new Error("当前实例还没有开放 OneLiner 会话接口。"); - } - throw error; }); appState.onelinerSessions = [session, ...safeArray(appState.onelinerSessions)]; appState.selectedOnelinerSessionId = session.id; @@ -1897,11 +1892,6 @@ async function createOneLinerRun(runRequest) { scheduling_mode: "queued", ...runRequest } - }).catch((error) => { - if (isMissingBackendCapability(error)) { - throw new Error("当前实例还没有开放主 Agent 运行层。"); - } - throw error; }); await loadAgentControlSurfaces(projectId); appState.selectedOnelinerRunId = payload?.id || choosePreferredOneLinerRunId(appState.onelinerRuns, ""); @@ -2197,11 +2187,6 @@ async function executeOneLinerAction(executorKey, options = {}) { session_id: options.sessionId || session?.id || "", payload: options.payload || {} } - }).catch((error) => { - if (isMissingBackendCapability(error)) { - throw new Error("当前实例还没有开放 OneLiner 动作执行器。"); - } - throw error; }); await loadAgentControlSurfaces(projectId); if (appState.selectedOnelinerSessionId) { @@ -2590,19 +2575,10 @@ async function markTrackingDigestRead() { const platform = getCurrentPlatformValue(); const trackingCursorPath = getWorkbenchRoute(platform, "trackingCursor"); const nextSeenAt = new Date().toISOString(); - try { - await storyforgeFetch(trackingCursorPath, { - method: "POST", - body: { last_seen_at: nextSeenAt } - }); - } catch (error) { - if (isMissingBackendCapability(error)) { - rememberAction("当前实例未提供", `这套 ${platformLabel(platform)} collector 当前没有开放跟踪已读游标接口。`, "orange"); - renderAll(); - return; - } - throw error; - } + await storyforgeFetch(trackingCursorPath, { + method: "POST", + body: { last_seen_at: nextSeenAt } + }); appState.trackingCursorMap = { ...(appState.trackingCursorMap || {}), [platform]: nextSeenAt @@ -2624,19 +2600,9 @@ async function refreshTrackingAccountsAction() { const trackingRefreshPath = getWorkbenchRoute(platform, "trackingRefresh"); setBusy(true, "正在同步跟踪账号..."); try { - let payload; - try { - payload = await storyforgeFetch(trackingRefreshPath, { - method: "POST" - }); - } catch (error) { - if (isMissingBackendCapability(error)) { - rememberAction("当前实例未提供", `这套 ${platformLabel(platform)} collector 当前没有开放批量跟踪同步。`, "orange"); - renderAll(); - return; - } - throw error; - } + const payload = await storyforgeFetch(trackingRefreshPath, { + method: "POST" + }); const refreshNotice = summarizeTrackingRefreshPayload(payload, platform, "batch"); rememberTrackingRefreshNotice(refreshNotice); rememberAction( @@ -2660,19 +2626,9 @@ async function refreshTrackedAccountAction(trackedAccountId) { const trackingRefreshPath = getWorkbenchRoute(platform, "trackingAccountRefresh", trackedAccountId); setBusy(true, "正在同步该跟踪账号..."); try { - let payload; - try { - payload = await storyforgeFetch(trackingRefreshPath, { - method: "POST" - }); - } catch (error) { - if (isMissingBackendCapability(error)) { - rememberAction("当前实例未提供", `这套 ${platformLabel(platform)} collector 当前没有开放单账号跟踪同步。`, "orange"); - renderAll(); - return; - } - throw error; - } + const payload = await storyforgeFetch(trackingRefreshPath, { + method: "POST" + }); const refreshNotice = summarizeTrackingRefreshPayload(payload, platform, "single"); rememberTrackingRefreshNotice(refreshNotice); const success = payload.success !== false; @@ -9321,11 +9277,6 @@ function openPlatformSkillReviewAction(platform, skillId, accepted) { summary: values.summary || "", review_notes: values.reviewNotes || "" } - }).catch((error) => { - if (isMissingBackendCapability(error)) { - throw new Error("当前实例还没有开放平台技能验收接口。"); - } - throw error; }); rememberAction( accepted ? "平台技能已通过" : "平台技能待优化", @@ -9590,15 +9541,7 @@ function openAnalyzeTopVideosAction() { min_score: Number(values.minScore || 45), temperature: 0.25 } - }).catch((error) => { - if (isMissingBackendCapability(error)) { - rememberAction("当前实例未提供", `这套 ${platformLabel(platform)} collector 当前没有开放高分作品批量分析。`, "orange"); - renderAll(); - return null; - } - throw error; }); - if (!result) return; appState.topVideoAnalysisResults = { ...(appState.topVideoAnalysisResults || {}), [account.id]: { @@ -10700,7 +10643,11 @@ document.addEventListener("click", async (event) => { return; } if (name === "refresh-tracking") { - await refreshTrackingAccountsAction(); + try { + await refreshTrackingAccountsAction(); + } catch (error) { + presentActionFailure(error, "刷新跟踪账号失败"); + } return; } if (name === "open-live-recorder") { @@ -10736,9 +10683,13 @@ document.addEventListener("click", async (event) => { return; } if (name === "mark-tracking-read") { - await markTrackingDigestRead(); - rememberAction("日报已标记", "当前跟踪摘要已更新为已读,下次会从新的时间点继续汇总。", "green"); - await bootstrap(); + try { + await markTrackingDigestRead(); + rememberAction("日报已标记", "当前跟踪摘要已更新为已读,下次会从新的时间点继续汇总。", "green"); + await bootstrap(); + } catch (error) { + presentActionFailure(error, "标记日报已读失败"); + } return; } if (name === "logout-session") { @@ -10824,7 +10775,11 @@ document.addEventListener("click", async (event) => { return; } if (name === "refresh-tracked-account") { - await refreshTrackedAccountAction(action.dataset.trackedAccountId || ""); + try { + await refreshTrackedAccountAction(action.dataset.trackedAccountId || ""); + } catch (error) { + presentActionFailure(error, "同步跟踪账号失败"); + } return; } if (name === "open-import-video-link") { diff --git a/web/storyforge-web-v4/tests/workbench-pages.test.mjs b/web/storyforge-web-v4/tests/workbench-pages.test.mjs index e94b118..fc88c55 100644 --- a/web/storyforge-web-v4/tests/workbench-pages.test.mjs +++ b/web/storyforge-web-v4/tests/workbench-pages.test.mjs @@ -332,7 +332,7 @@ test("tracking refresh and top-video analysis flows expose async feedback inside assert.doesNotMatch(skillReview, /当前后端还没有接入平台技能验收接口/); assert.ok(!agentDetail.includes('backendSupports("/v2/platform-agents/{platform}/skills/{skill_id}/versions")')); assert.doesNotMatch(topVideoAction, /当前后端暂不支持.*高分作品批量分析/s); - assert.match(topVideoAction, /当前实例未提供/); + assert.doesNotMatch(topVideoAction, /当前实例未提供/); assert.ok(!jobRecoverability.includes('backendSupports("/v2/explore/jobs/{job_id}/retry") && uploadedPath')); assert.ok(!recoveryAction.includes('if (backendSupports("/v2/explore/jobs/{job_id}/retry"))')); assert.ok(!clickActions.includes('else if (backendSupports("/v2/oneliner/sessions"))')); @@ -789,3 +789,11 @@ test("workbench interaction flow avoids browser alerts and keeps failures inside assert.match(clicks, /name === "show-disabled-reason"[\s\S]*rememberAction\("动作已拦截"/); assert.match(clicks, /name === "auth-refresh" \|\| name === "refresh-data"[\s\S]*presentActionFailure\(error, "刷新数据失败"\)/); }); + +test("live-first workbench flows no longer advertise stale missing-capability placeholders for active routes", () => { + assert.doesNotMatch(APP, /当前实例还没有开放 OneLiner 会话接口/); + assert.doesNotMatch(APP, /当前实例还没有开放主 Agent 运行层/); + assert.doesNotMatch(APP, /当前实例还没有开放 OneLiner 动作执行器/); + assert.doesNotMatch(APP, /当前实例还没有开放平台技能验收接口/); + assert.doesNotMatch(APP, /当前实例未提供/); +});