feat: land direct copy results and expand live action smoke
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 08:14:33 +08:00
parent 78d90542cc
commit 0b96562e86
6 changed files with 12 additions and 4 deletions

View File

@@ -477,3 +477,4 @@
- 后端新增了 `import-video-link / import-text` 两条真实执行动作,并且 `generate-copy / import-homepage / track-account / create-ai-video` 现在都会优先尊重显式 `assistant_id`,避免切到执行器后丢失用户在表单里选定的 Agent。
- `runDirectWorkbenchAction / runDirectDiscoveryAction` 也已支持显式 `projectId / platform`,所以这批旧表单里的“归属项目 / 平台”选择不会在切换到执行器后失效。
- SQLite 连接现在保持 `WAL` 优先,但在临时盘或受限文件系统无法启用 `WAL` 时会自动回退到 `DELETE`,避免测试环境和受限部署因为 `disk I/O error` 直接起不来。
- `generate-copy` 这条执行链现在会直接推荐回到“最近生成”结果区而不是再打开旧文案表单LAN smoke 也同步把 `track-account / import-video-link / import-text / generate-copy / create-assistant` 纳入 action-registry 护栏。

View File

@@ -5756,9 +5756,9 @@ def register_oneliner_routes(app: Any, legacy: Any) -> None:
"summary": f"已用 {assistant.get('name') or '默认 Agent'} 生成一版可发布文案。",
"payload": payload,
"recommended_action": _recommended_action(
"open-generate-copy",
label="继续调文案",
summary="继续修改提示、受众和补充要求,快速迭代这版文案。",
"open-generated-copy-results",
label="查看最近生成",
summary="直接回到最近生成结果区,继续查看、复制和迭代这版文案。",
screen="playbook",
platform=normalized_platform or "douyin",
),

View File

@@ -114,6 +114,7 @@ payload = json.loads(pathlib.Path(sys.argv[1]).read_text())
items = payload.get("items") or []
keys = {str(item.get("action_key") or "") for item in items}
required = {"import-homepage", "search-similar-accounts", "save-benchmark-link", "refresh-tracking", "mark-tracking-read"}
required = required | {"track-account", "import-video-link", "import-text", "generate-copy", "create-assistant"}
missing = sorted(required - keys)
if missing:
raise SystemExit(f"action registry missing: {missing}")

View File

@@ -1016,7 +1016,7 @@ class MainAgentGovernanceTests(unittest.TestCase):
)
self.assertEqual(copy_response.status_code, 200, copy_response.text)
copy_payload = copy_response.json()
self.assertEqual(copy_payload["recommended_action"]["action"], "open-generate-copy")
self.assertEqual(copy_payload["recommended_action"]["action"], "open-generated-copy-results")
self.assertEqual(copy_payload["recommended_action"]["screen"], "playbook")
self.assertEqual(copy_payload["recommended_action"]["platform"], "douyin")

View File

@@ -12325,6 +12325,11 @@ document.addEventListener("click", async (event) => {
openGenerateCopyAction();
return;
}
if (name === "open-generated-copy-results") {
closeActionModal();
focusRecentGeneratedCopy();
return;
}
if (name === "direct-generate-copy") {
const jobId = action.dataset.jobId || "";
const detail = appState.lastJobDetail?.job?.id === jobId ? appState.lastJobDetail.job : null;

View File

@@ -387,6 +387,7 @@ test("job detail and follow-up flows use direct generate-copy execution and pers
assert.match(APP, /function cacheGeneratedCopyResult\(payload, options = \{\}\)/);
assert.match(jobDetail, /actionTag\("用摘要写文案", "direct-generate-copy"/);
assert.match(clickActions, /name === "open-generated-copy-results"[\s\S]*focusRecentGeneratedCopy\(\)/);
assert.match(clickActions, /name === "direct-generate-copy"[\s\S]*runDirectWorkbenchAction\("generate-copy"/);
assert.match(clickActions, /name === "direct-generate-copy"[\s\S]*followRecommendedAction:\s*false/);
assert.match(clickActions, /name === "direct-generate-copy"[\s\S]*cacheGeneratedCopyResult\(result,\s*\{\s*brief\s*\}\)/);