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