fix: stop false missing-capability warnings
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-03-30 20:12:49 +08:00
parent f492cb3f83
commit f2c75755b6
2 changed files with 65 additions and 15 deletions

View File

@@ -589,6 +589,13 @@ function formatActionErrorMessage(error, fallbackTitle = "执行失败") {
return [detail.title, detail.summary, detail.hint].filter(Boolean).join(" · ");
}
function isMissingBackendCapability(error) {
const status = Number(error?.status || error?.payload?.status_code || 0);
if (status === 404) return true;
const raw = String(error?.message || error?.payload?.detail || error?.statusText || "").trim().toLowerCase();
return raw.includes("not found") || raw.includes("404");
}
function presentActionFailure(error, fallbackTitle = "执行失败") {
const detail = describeActionError(error, fallbackTitle);
rememberAction(detail.title, [detail.summary, detail.hint].filter(Boolean).join(" · "), detail.tone);
@@ -2642,16 +2649,25 @@ async function bootstrap() {
async function markTrackingDigestRead() {
const platform = getCurrentPlatformValue();
const trackingCursorPath = getWorkbenchRoute(platform, "trackingCursor");
if (!trackingCursorPath || !backendSupports(trackingCursorPath)) {
rememberAction("当前后端暂不支持", "这套 live collector 还没有接入跟踪已读游标。", "orange");
if (!trackingCursorPath) {
rememberAction("当前平台待接入", getPendingWorkbenchReason(platform), "orange");
renderAll();
return;
}
const nextSeenAt = new Date().toISOString();
await storyforgeFetch(trackingCursorPath, {
method: "POST",
body: { last_seen_at: nextSeenAt }
});
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;
}
appState.trackingCursorMap = {
...(appState.trackingCursorMap || {}),
[platform]: nextSeenAt
@@ -2671,8 +2687,8 @@ async function markTrackingDigestRead() {
async function refreshTrackingAccountsAction() {
const platform = getCurrentPlatformValue();
const trackingRefreshPath = getWorkbenchRoute(platform, "trackingRefresh");
if (!trackingRefreshPath || !backendSupports(trackingRefreshPath)) {
rememberAction("当前后端暂不支持", "这套 live collector 还没有接入批量跟踪同步。", "orange");
if (!trackingRefreshPath) {
rememberAction("当前平台待接入", getPendingWorkbenchReason(platform), "orange");
renderAll();
return;
}
@@ -2680,7 +2696,15 @@ async function refreshTrackingAccountsAction() {
try {
const payload = await storyforgeFetch(trackingRefreshPath, {
method: "POST"
}).catch((error) => {
if (isMissingBackendCapability(error)) {
rememberAction("当前实例未提供", `这套 ${platformLabel(platform)} collector 当前没有开放批量跟踪同步。`, "orange");
renderAll();
return null;
}
throw error;
});
if (!payload) return;
const refreshNotice = summarizeTrackingRefreshPayload(payload, platform, "batch");
rememberTrackingRefreshNotice(refreshNotice);
rememberAction(
@@ -2702,8 +2726,8 @@ async function refreshTrackedAccountAction(trackedAccountId) {
const trackedItem = getTrackingAccounts().find((item) => item.tracked_account_id === trackedAccountId);
const platform = trackedItem?.platform || getCurrentPlatformValue();
const trackingRefreshPath = getWorkbenchRoute(platform, "trackingAccountRefresh", trackedAccountId);
if (!trackingRefreshPath || !backendSupports(`/v2/${platform}/tracking/accounts/{tracked_account_id}/refresh`)) {
rememberAction("当前后端暂不支持", "这套 live collector 还没有接入单账号跟踪同步。", "orange");
if (!trackingRefreshPath) {
rememberAction("当前平台待接入", getPendingWorkbenchReason(platform), "orange");
renderAll();
return;
}
@@ -2711,7 +2735,15 @@ async function refreshTrackedAccountAction(trackedAccountId) {
try {
const payload = await storyforgeFetch(trackingRefreshPath, {
method: "POST"
}).catch((error) => {
if (isMissingBackendCapability(error)) {
rememberAction("当前实例未提供", `这套 ${platformLabel(platform)} collector 当前没有开放单账号跟踪同步。`, "orange");
renderAll();
return null;
}
throw error;
});
if (!payload) return;
const refreshNotice = summarizeTrackingRefreshPayload(payload, platform, "single");
rememberTrackingRefreshNotice(refreshNotice);
const success = payload.success !== false;
@@ -9391,9 +9423,6 @@ function openPlatformSkillReviewAction(platform, skillId, accepted) {
{ name: "score", label: "得分", type: "number", value: accepted ? 0.9 : 0.45, min: 0, max: 1, step: 0.05 }
],
onSubmit: async (values) => {
if (!backendSupports("/v2/platform-agents/{platform}/skills/{skill_id}/review")) {
throw new Error("当前后端还没有接入平台技能验收接口。");
}
const saved = await storyforgeFetch(`/v2/platform-agents/${encodeURIComponent(normalizedPlatform)}/skills/${encodeURIComponent(skillId)}/review`, {
method: "POST",
body: {
@@ -9403,6 +9432,11 @@ function openPlatformSkillReviewAction(platform, skillId, accepted) {
summary: values.summary || "",
review_notes: values.reviewNotes || ""
}
}).catch((error) => {
if (isMissingBackendCapability(error)) {
throw new Error("当前实例还没有开放平台技能验收接口。");
}
throw error;
});
rememberAction(
accepted ? "平台技能已通过" : "平台技能待优化",
@@ -9665,8 +9699,8 @@ function openAnalyzeTopVideosAction() {
}
const platform = gate.platform;
const analyzePath = getWorkbenchRoute(platform, "analyzeTopVideos", account.id);
if (!analyzePath || !backendSupports(`/v2/${platform}/accounts/{account_id}/videos/analyze-top`)) {
rememberAction("当前后端暂不支持", "这套 live collector 还没有接入高分作品批量分析。", "orange");
if (!analyzePath) {
rememberAction("当前平台待接入", getPendingWorkbenchReason(platform), "orange");
renderAll();
return;
}
@@ -9687,7 +9721,15 @@ 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]: {

View File

@@ -288,15 +288,23 @@ test("quota and review screens foreground live next-step guidance", () => {
test("tracking refresh and top-video analysis flows expose async feedback inside the workbench", () => {
const tracking = extractBetween(APP, "function renderTrackingScreen()", "function renderAutomationScreen()");
const discovery = extractBetween(APP, "function renderDiscoveryOverviewSection(", "function renderDiscoveryRelationsSection(");
const trackingActions = extractBetween(APP, "async function markTrackingDigestRead()", "function createEmptyTrackingDigest(");
const skillReview = extractBetween(APP, "function openPlatformSkillReviewAction(", "function openPlatformSkillRollbackAction(");
const topVideoAction = extractBetween(APP, "function openAnalyzeTopVideosAction()", "function openSimilaritySearchAction()");
assert.match(APP, /function summarizeTrackingRefreshPayload\(/);
assert.match(APP, /function rememberTrackingRefreshNotice\(/);
assert.match(APP, /function isMissingBackendCapability\(/);
assert.match(tracking, /批量同步已排队|单账号同步已排队|后台同步状态/);
assert.match(tracking, /去生产中心/);
assert.match(APP, /function getSelectedTopVideoAnalysisResult\(/);
assert.match(discovery, /最近高分拆解/);
assert.match(discovery, /这批结果已经回流到当前账号页/);
assert.doesNotMatch(trackingActions, /.*|.*|.*/s);
assert.doesNotMatch(skillReview, /当前后端还没有接入平台技能验收接口/);
assert.doesNotMatch(topVideoAction, /.*/s);
assert.match(topVideoAction, /当前实例未提供/);
});
test("discovery and production screens expose compact mobile flow summaries", () => {