diff --git a/web/storyforge-web-v4/assets/app.js b/web/storyforge-web-v4/assets/app.js index 458b8bc..5651cf4 100644 --- a/web/storyforge-web-v4/assets/app.js +++ b/web/storyforge-web-v4/assets/app.js @@ -5850,7 +5850,7 @@ function renderPlaybookScreen() { `${button("配置 OneLiner", "open-oneliner-profile")} ${button("交给主 Agent", "handoff-to-main-agent", "secondary", { attrs: playbookHandoffAttrs })} ${button("设主模型", "open-preferred-model")} ${button("新建 Agent", "open-create-assistant")} ${button("去生产", "goto-production", "primary")}`, ` ${renderMainAgentLandingNotice("playbook")} -
+

Agent 概览

先定项目、平台和主模型,再导入内容让 Agent 学习。

@@ -5864,6 +5864,31 @@ function renderPlaybookScreen() {
先处理你当前真的会用到的 Agent 信息,系统治理内容已移到管理员配置台。
+
+
+ 当前 Agent 任务 + ${escapeHtml(tabs.find((tab) => tab.value === activeTab)?.label || "当前 Agent 工作台")} +
+

${escapeHtml( + activeTab === "platform_agents" + ? "先确认当前平台 Agent 是否已接上默认策略,再决定是否继续下放个性化策略。" + : activeTab === "models" + ? "先确定主模型和本机网关状态,再回到 Agent 工作区继续执行。" + : activeAdminOverrideNotice?.title + ? "先看当前管理员覆盖,再决定是调整我的策略还是继续交给主 Agent。" + : currentAssistant + ? `先围绕 ${currentAssistant.name} 调整配置,再决定是否继续交给主 Agent。` + : "先配置 OneLiner 或创建第一个 Agent,再把当前项目交给它。" + )}

+
+ ${activeTab === "platform_agents" + ? `${actionTag("看平台 Agent", "select-page-tab", `data-page-tab-key="playbookDetailTab" data-page-tab-value="platform_agents"`)} ${actionTag("交给主 Agent", "handoff-to-main-agent", playbookHandoffAttrs)}` + : activeTab === "models" + ? `${actionTag("设主模型", "open-preferred-model")} ${actionTag("回工作区", "select-page-tab", `data-page-tab-key="playbookDetailTab" data-page-tab-value="workspace"`)}` + : `${actionTag("配置 OneLiner", "open-oneliner-profile")} ${actionTag(currentAssistant ? "去生产" : "新建 Agent", currentAssistant ? "goto-production" : "open-create-assistant")} ${actionTag("交给主 Agent", "handoff-to-main-agent", playbookHandoffAttrs)}` + } +
+
主 Agent ${escapeHtml(appState.onelinerProfile?.display_name || "OneLiner")} ${escapeHtml(currentAssistant ? `当前 ${currentAssistant.name}` : "当前未选 Agent")} @@ -6354,7 +6379,7 @@ function renderStrategyScreen() { `${button("编辑全局策略", "open-user-global-policy")} ${button("编辑当前平台策略", "open-user-platform-policy", "primary")} ${button("交给主 Agent", "handoff-to-main-agent", "secondary", { attrs: strategyHandoffAttrs })}`, ` ${renderMainAgentLandingNotice("strategy")} -
+

当前策略工作区

${escapeHtml(project?.name || "当前项目")} · ${escapeHtml(platformLabel(platform))}。这里展示系统默认、你的个性化策略和管理员覆盖是如何叠加生效的。

${activeAdminOverrideNotice?.title ? ` @@ -6375,6 +6400,33 @@ function renderStrategyScreen() {
先看当前生效,再回看你自己的历史和管理员覆盖,不必再通过多个弹窗来回切。
+
+
+ 当前策略任务 + ${escapeHtml(tabs.find((tab) => tab.value === activeTab)?.label || "当前生效")} +
+

${escapeHtml( + activeTab === "global" + ? "先确认你的全局策略是否还贴合当前项目,再决定是否发布新版本。" + : activeTab === "platform" + ? `先看 ${platformLabel(platform)} 当前平台策略,再决定是否只改这个平台。` + : activeTab === "activity" + ? "先看最近变更和回滚,再决定是否继续交给主 Agent 调整。" + : activeAdminOverrideNotice?.title + ? "先确认管理员覆盖为什么生效,再决定要不要继续改自己的策略。" + : "先看当前生效层,再决定调整全局还是当前平台。" + )}

+
+ ${activeTab === "global" + ? `${actionTag("编辑全局策略", "open-user-global-policy")} ${actionTag("看全局历史", "open-user-global-policy-history")}` + : activeTab === "platform" + ? `${actionTag("编辑当前平台策略", "open-user-platform-policy", `data-platform="${escapeHtml(platform)}"`)} ${actionTag("看平台历史", "open-user-platform-policy-history", `data-platform="${escapeHtml(platform)}"`)}` + : activeTab === "activity" + ? `${actionTag("交给主 Agent", "handoff-to-main-agent", strategyHandoffAttrs)} ${actionTag("回当前生效", "select-page-tab", `data-page-tab-key="strategyDetailTab" data-page-tab-value="effective"`)}` + : `${actionTag("编辑全局策略", "open-user-global-policy")} ${actionTag("编辑当前平台策略", "open-user-platform-policy", `data-platform="${escapeHtml(platform)}"`)} ${actionTag("交给主 Agent", "handoff-to-main-agent", strategyHandoffAttrs)}` + } +
+
当前生效 ${escapeHtml(formatNumber(safeArray(appState.onelinerGovernanceEffective?.layers).length))} 层 ${escapeHtml(platformLabel(platform))} 平台策略 diff --git a/web/storyforge-web-v4/tests/workbench-pages.test.mjs b/web/storyforge-web-v4/tests/workbench-pages.test.mjs index 911df48..d97b979 100644 --- a/web/storyforge-web-v4/tests/workbench-pages.test.mjs +++ b/web/storyforge-web-v4/tests/workbench-pages.test.mjs @@ -141,6 +141,8 @@ test("strategy navigation and screen are real routes", () => { test("strategy screen exposes a compact mobile summary for current governance state", () => { const source = extractBetween(APP, "function renderStrategyScreen()", "function renderCreditsScreen()"); assert.match(source, /mobile-only compact-summary-row/); + assert.match(source, /mobile-only mobile-flow-focus-card/); + assert.match(source, /当前策略任务/); assert.match(source, /当前生效/); assert.match(source, /平台策略/); }); @@ -159,6 +161,8 @@ test("agent screen excludes quota and registry panels and uses page tabs", () => assert.doesNotMatch(source, /renderOneLinerActionRegistryPanel\(/); assert.match(source, /renderDetailTabs\("playbookDetailTab"/); assert.match(source, /mobile-only compact-summary-row/); + assert.match(source, /mobile-only mobile-flow-focus-card/); + assert.match(source, /当前 Agent 任务/); assert.match(source, /renderGovernanceSummaryCard\(/); assert.match(source, /open-user-global-policy/); assert.match(source, /open-user-platform-policy/); @@ -211,10 +215,14 @@ test("discovery and production screens expose mobile focus cards with next-step test("mobile heavy screens mark redundant desktop metric blocks for compact hiding", () => { const discovery = extractBetween(APP, "function renderDiscoveryScreen()", "function renderTrackingScreen()"); const production = extractBetween(APP, "function renderProductionScreen()", "function renderReviewScreen()"); + const playbook = extractBetween(APP, "function renderPlaybookScreen()", "function renderProductionScreen()"); + const strategy = extractBetween(APP, "function renderStrategyScreen()", "function renderCreditsScreen()"); const cssMobile = extractBetween(CSS, "@media (max-width: 760px) {", "@media (max-width: 560px) {"); assert.match(discovery, /discovery-selected-hero mobile-secondary-card/); assert.match(production, /production-queue-grid/); + assert.match(playbook, /hero-card mobile-secondary-card/); + assert.match(strategy, /hero-card mobile-secondary-card/); assert.match(cssMobile, /\.discovery-selected-hero \.mini-grid/); assert.match(cssMobile, /\.production-queue-grid/); assert.match(cssMobile, /\.mobile-priority-filters \.filter:nth-child\(n\+3\)/);