feat: add context summaries to homepage and tracking sheets
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 11:53:35 +08:00
parent 4adb545e0d
commit ce5a530427
3 changed files with 29 additions and 4 deletions

View File

@@ -4,6 +4,12 @@
## 2026-04-05
### 导入主页、导入当前对标、加入跟踪表单补齐上下文摘要
- `导入主页 / 导入当前对标 / 加入跟踪` 这三张仍需用户补信息的表单,现在和 `导入作品 / 导入文本 / 上传视频` 一样,都会在顶部展示 `当前项目 / 默认 Agent / 默认知识库` 的上下文摘要。
- 默认 Agent 也统一跟随当前已选 Agent避免用户每次打开表单都要重新对齐负责 Agent。
- 这让“仍然必须保留表单”的入口也和前面已经收好的输入型流程保持了同一套体验语言。
### 主 Agent 抖音相似搜索与对标关系 live 修复
- 修复 `search-similar-accounts` / `save-benchmark-link` 在抖音 live 数据上错误按 `project_id` 查询账号导致的 500。

View File

@@ -9072,17 +9072,19 @@ function openImportHomepageAction() {
const project = requireSelectedProject();
const kb = getProjectKnowledgeBases(project.id)[0];
const assistants = getAssistantOptions(project.id);
const defaultAssistantId = getSelectedAssistant()?.id || assistants[0]?.value || "";
openActionModal({
title: "导入主页并同步",
description: "适合抖音 / 小红书 / B站 / 快手 / 视频号主页。先建内容源,再触发同步与分析。",
submitLabel: "开始同步",
fields: [
{ name: "context", label: "当前上下文", type: "html", html: renderIntakeActionContextHtml(project.id, defaultAssistantId) },
{ name: "projectId", label: "归属项目", type: "select", value: project.id, options: getProjectOptions() },
{ name: "platform", label: "平台", type: "select", value: "douyin", options: getPlatformOptions() },
{ name: "title", label: "标题", placeholder: "例如:创业口播对标账号" },
{ name: "title", label: "标题", placeholder: "例如:创业口播主页对标" },
{ name: "handle", label: "账号名 / handle", placeholder: "可选" },
{ name: "sourceUrl", label: "主页链接", type: "url", placeholder: "https://..." },
{ name: "assistantId", label: "绑定 Agent", type: "select", value: assistants[0]?.value || "", options: [{ value: "", label: "暂不绑定" }, ...assistants] },
{ name: "assistantId", label: "绑定 Agent", type: "select", value: defaultAssistantId, options: [{ value: "", label: "暂不绑定" }, ...assistants] },
{ name: "maxItems", label: "最多同步作品数", type: "number", value: 5, min: 1, max: 20 }
],
onSubmit: async (values) => {
@@ -9114,6 +9116,7 @@ function openImportSelectedAccountAction() {
const platform = getAccountPlatform(account);
const project = requireSelectedProject();
const assistants = getAssistantOptions(project.id);
const defaultAssistantId = getSelectedAssistant()?.id || assistants[0]?.value || "";
const currentSources = getCurrentProjectSourcesForAccount(account, project.id);
const currentSource = currentSources[0];
const kb = getProjectKnowledgeBases(project.id)[0];
@@ -9124,12 +9127,13 @@ function openImportSelectedAccountAction() {
: "把当前选中的对标账号加入项目,并绑定 Agent 进入持续同步。",
submitLabel: currentSource ? "继续同步" : "导入并同步",
fields: [
{ name: "context", label: "当前上下文", type: "html", html: renderIntakeActionContextHtml(project.id, defaultAssistantId) },
{ name: "projectId", label: "归属项目", type: "select", value: project.id, options: getProjectOptions() },
{ name: "platform", label: "平台", type: "select", value: normalizePlatformValue(currentSource?.platform || platform), options: getPlatformOptions() },
{ name: "title", label: "内容源标题", value: currentSource?.title || `${getAccountName(account)} 对标主页` },
{ name: "handle", label: "账号标识", value: currentSource?.handle || getAccountHandle(account) || "" },
{ name: "sourceUrl", label: "主页链接", type: "url", value: currentSource?.source_url || getAccountProfileUrl(account) || "", placeholder: "https://..." },
{ name: "assistantId", label: "绑定 Agent", type: "select", value: getSelectedAssistant()?.id || assistants[0]?.value || "", options: [{ value: "", label: "暂不绑定" }, ...assistants] },
{ name: "assistantId", label: "绑定 Agent", type: "select", value: defaultAssistantId, options: [{ value: "", label: "暂不绑定" }, ...assistants] },
{ name: "maxItems", label: "最多同步作品数", type: "number", value: Number(currentSource?.metadata?.max_items || 6), min: 1, max: 20 },
{ name: "skipExisting", label: "跳过已存在作品", type: "checkbox", value: true },
{ name: "autoAnalyze", label: "同步后自动分析", type: "checkbox", value: true }
@@ -9163,6 +9167,7 @@ function openTrackSelectedAccountAction() {
const project = requireSelectedProject();
const assistants = getAssistantOptions(project.id);
const trackedItem = safeArray(appState.trackingAccounts).find((item) => item.tracked_account_id === account.id);
const defaultAssistantId = trackedItem?.assistant_id || getSelectedAssistant()?.id || assistants[0]?.value || "";
openActionModal({
title: trackedItem ? "更新跟踪账号" : "加入跟踪",
description: trackedItem
@@ -9170,8 +9175,9 @@ function openTrackSelectedAccountAction() {
: "把当前对标账号加入每日跟踪,系统会自动生成更新日报。",
submitLabel: trackedItem ? "保存跟踪" : "开始跟踪",
fields: [
{ name: "context", label: "当前上下文", type: "html", html: renderIntakeActionContextHtml(project.id, defaultAssistantId) },
{ name: "accountName", label: "账号", type: "html", html: `<div class="sheet-html"><strong>${escapeHtml(getAccountName(account) || "未命名账号")}</strong><p>${escapeHtml(getAccountProfileUrl(account) || account.signature || "")}</p></div>` },
{ name: "assistantId", label: "负责 Agent", type: "select", value: trackedItem?.assistant_id || getSelectedAssistant()?.id || assistants[0]?.value || "", options: [{ value: "", label: "先不绑定" }, ...assistants] },
{ name: "assistantId", label: "负责 Agent", type: "select", value: defaultAssistantId, options: [{ value: "", label: "先不绑定" }, ...assistants] },
{ name: "note", label: "跟踪备注", value: trackedItem?.note || "", placeholder: "例如:重点观察开头结构、成交句式和更新频率" }
],
onSubmit: async (values) => {

View File

@@ -1136,10 +1136,23 @@ test("import and tracking sheets submit through direct execute handlers", () =>
});
test("input-heavy intake sheets surface current context and smarter defaults", () => {
const importHomepage = extractBetween(APP, "function openImportHomepageAction()", "function openImportSelectedAccountAction()");
const importSelected = extractBetween(APP, "function openImportSelectedAccountAction()", "function openTrackSelectedAccountAction()");
const trackSelected = extractBetween(APP, "function openTrackSelectedAccountAction()", "function openImportVideoLinkAction()");
const importVideo = extractBetween(APP, "function openImportVideoLinkAction()", "function openImportTextAction()");
const importText = extractBetween(APP, "function openImportTextAction()", "function openUploadVideoAction()");
const uploadVideo = extractBetween(APP, "function openUploadVideoAction()", "function focusPlaybookOneLinerWorkspace(");
assert.match(APP, /function renderIntakeActionContextHtml\(/);
assert.match(importHomepage, /label: "当前上下文", type: "html"/);
assert.match(importHomepage, /const defaultAssistantId = getSelectedAssistant\(\)\?\.id \|\| assistants\[0\]\?\.value \|\| ""/);
assert.match(importHomepage, /renderIntakeActionContextHtml\(project\.id, defaultAssistantId\)/);
assert.match(importHomepage, /placeholder: "例如:创业口播主页对标"/);
assert.match(importSelected, /label: "当前上下文", type: "html"/);
assert.match(importSelected, /const defaultAssistantId = getSelectedAssistant\(\)\?\.id \|\| assistants\[0\]\?\.value \|\| ""/);
assert.match(importSelected, /renderIntakeActionContextHtml\(project\.id, defaultAssistantId\)/);
assert.match(trackSelected, /label: "当前上下文", type: "html"/);
assert.match(trackSelected, /const defaultAssistantId = trackedItem\?\.assistant_id \|\| getSelectedAssistant\(\)\?\.id \|\| assistants\[0\]\?\.value \|\| ""/);
assert.match(trackSelected, /renderIntakeActionContextHtml\(project\.id, defaultAssistantId\)/);
assert.match(importVideo, /label: "当前上下文", type: "html"/);
assert.match(importVideo, /const defaultAssistantId = getSelectedAssistant\(\)\?\.id \|\| assistants\[0\]\?\.value \|\| ""/);
assert.match(importVideo, /renderIntakeActionContextHtml\(project\.id, defaultAssistantId\)/);