feat: add direct tracking digest actions
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 06:30:53 +08:00
parent 22f6e6e686
commit f320ec1b44
3 changed files with 74 additions and 0 deletions

View File

@@ -23,6 +23,12 @@
- 如果本轮只生成了一条同步任务,结果会直接落到任务详情;如果是多条批量同步,则回到跟踪工作区继续看结果。
- 治理回归补上了这条动作的断言,锁住动作注册表、批量同步执行和推荐落点都必须保持 live。
### 主 Agent 可直接标记跟踪日报已读
- `OneLiner / 主 Agent` 现在新增了 `直接标记日报已读` 动作,会直接调用 `/v2/{platform}/tracking/cursor` 更新当前平台的已读游标。
- 这让跟踪流不再只停在“同步一批账号”,而是可以顺手把这轮日报窗口标成已处理。
- 动作完成后会统一回到 `跟踪工作区`,继续看当前平台的日报和下一步跟进动作。
### 额度编辑弹层补成真正的套餐配置器
- `编辑租户额度` 不再只是裸数字表单,而是会即时预览当前套餐的预算、动作池和预警阈值。

View File

@@ -346,6 +346,16 @@ ACTION_REGISTRY_DEFAULTS: dict[str, dict[str, Any]] = {
"requires_platform": True,
"config": {},
},
"mark-tracking-read": {
"label": "直接标记日报已读",
"description": "把当前平台跟踪日报更新为已读,下次从新的时间点继续汇总。",
"category": "tracking",
"handler_key": "mark-tracking-read",
"status": "enabled",
"admin_only": False,
"requires_platform": True,
"config": {},
},
"create-assistant": {
"label": "直接创建 Agent",
"description": "根据当前项目和平台上下文,直接创建可继续编辑的 Agent。",
@@ -4563,6 +4573,15 @@ def register_oneliner_routes(app: Any, legacy: Any) -> None:
"platform": plan.get("platform", ""),
}
)
secondary_actions.append(
{
"key": "run-oneliner-action",
"label": "直接标记日报已读",
"kind": "api_action",
"executor_key": "mark-tracking-read",
"platform": plan.get("platform", ""),
}
)
if context_assistant:
secondary_actions.append(
{
@@ -5869,6 +5888,36 @@ def register_oneliner_routes(app: Any, legacy: Any) -> None:
"recommended_action": recommended_action,
}
async def _run_mark_tracking_read() -> dict[str, Any]:
if not normalized_platform:
raise HTTPException(status_code=400, detail="Platform is required for tracking cursor update")
last_seen_at = str(
requested_payload.get("last_seen_at")
or requested_payload.get("lastSeenAt")
or legacy.utc_now()
).strip() or legacy.utc_now()
payload = await _call_local_api(
account,
method="POST",
path=f"/v2/{normalized_platform}/tracking/cursor",
json_body={"last_seen_at": last_seen_at},
)
return {
"title": "OneLiner 已标记日报已读",
"summary": f"已把 {legacy.platform_label(normalized_platform)} 跟踪日报更新为已读,后续将从新的时间点继续汇总。",
"payload": {
"platform": normalized_platform,
"cursor": payload,
},
"recommended_action": _recommended_action(
"goto-tracking",
label="回到跟踪工作区",
summary="继续查看当前平台跟踪日报和下一步跟进动作。",
screen="tracking",
platform=normalized_platform,
),
}
async def _run_analyze_top_videos() -> dict[str, Any]:
if not normalized_platform:
raise HTTPException(status_code=400, detail="Platform is required for top video analysis")
@@ -6174,6 +6223,7 @@ def register_oneliner_routes(app: Any, legacy: Any) -> None:
"analyze-account": _run_analyze_account,
"track-account": _run_track_account,
"refresh-tracking": _run_refresh_tracking,
"mark-tracking-read": _run_mark_tracking_read,
"analyze-top-videos": _run_analyze_top_videos,
"create-assistant": _run_create_assistant,
"create-ai-video": _run_create_ai_video,

View File

@@ -800,6 +800,7 @@ class MainAgentGovernanceTests(unittest.TestCase):
self.assertIn("analyze-account", action_keys)
self.assertIn("track-account", action_keys)
self.assertIn("refresh-tracking", action_keys)
self.assertIn("mark-tracking-read", action_keys)
self.assertIn("create-assistant", action_keys)
save_registry = self.client.put(
@@ -1122,6 +1123,23 @@ class MainAgentGovernanceTests(unittest.TestCase):
self.assertEqual(refresh_tracking_payload["payload"]["platform"], "kuaishou")
self.assertGreaterEqual(int(refresh_tracking_payload["payload"]["refresh"]["refreshed"] or 0), 1)
mark_read_response = self.client.post(
"/v2/oneliner/actions/execute",
headers=self.ctx["member_headers"],
json={
"action_key": "mark-tracking-read",
"project_id": self.ctx["project_id"],
"platform": "kuaishou",
"payload": {"last_seen_at": "2026-04-05T00:00:00+00:00"},
},
)
self.assertEqual(mark_read_response.status_code, 200, mark_read_response.text)
mark_read_payload = mark_read_response.json()
self.assertEqual(mark_read_payload["recommended_action"]["action"], "goto-tracking")
self.assertEqual(mark_read_payload["recommended_action"]["screen"], "tracking")
self.assertEqual(mark_read_payload["payload"]["platform"], "kuaishou")
self.assertEqual(mark_read_payload["payload"]["cursor"]["last_seen_at"], "2026-04-05T00:00:00+00:00")
create_response = self.client.post(
"/v2/oneliner/actions/execute",
headers=self.ctx["member_headers"],