@iducky/media-agent 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/README.md +90 -0
  2. package/SHA256SUMS +94 -0
  3. package/bin/media-agent.mjs +89 -0
  4. package/docs/guides/capabilities.md +103 -0
  5. package/docs/guides/image-text-publishing.md +81 -0
  6. package/docs/guides/installation.md +103 -0
  7. package/docs/guides/runtime.md +13 -0
  8. package/manifest.json +382 -0
  9. package/package.json +42 -0
  10. package/pyproject.toml +20 -0
  11. package/resources/capabilities.json +34 -0
  12. package/resources/configs/accounts.yaml +21 -0
  13. package/resources/configs/profile.template.json +20 -0
  14. package/resources/configs/ranking-profiles.yaml +21 -0
  15. package/resources/configs/toutiao-profile.template.json +22 -0
  16. package/resources/configs/xiaohongshu-profile.template.json +27 -0
  17. package/resources/data/industry-taxonomy.yaml +326 -0
  18. package/skills/douyin-competitor-collect/SKILL.md +177 -0
  19. package/skills/douyin-competitor-collect/agents/openai.yaml +4 -0
  20. package/skills/douyin-competitor-collect/references/output-schema.md +178 -0
  21. package/skills/douyin-creator-image-text-publish/SKILL.md +44 -0
  22. package/skills/douyin-creator-image-text-publish/agents/openai.yaml +4 -0
  23. package/skills/douyin-creator-image-text-publish/references/LICENSE.social-auto-upload +21 -0
  24. package/skills/douyin-creator-image-text-publish/references/execution-contract.md +46 -0
  25. package/skills/douyin-creator-image-text-publish/references/upstream.md +30 -0
  26. package/skills/douyin-creator-index/SKILL.md +32 -0
  27. package/skills/douyin-creator-index/agents/openai.yaml +4 -0
  28. package/skills/douyin-creator-login/SKILL.md +58 -0
  29. package/skills/douyin-creator-login/agents/openai.yaml +4 -0
  30. package/skills/douyin-creator-publish/SKILL.md +56 -0
  31. package/skills/douyin-creator-publish/agents/openai.yaml +4 -0
  32. package/skills/douyin-enterprise-leads/SKILL.md +26 -0
  33. package/skills/douyin-enterprise-leads/agents/openai.yaml +4 -0
  34. package/skills/douyin-enterprise-leads-login/SKILL.md +36 -0
  35. package/skills/douyin-enterprise-leads-login/agents/openai.yaml +4 -0
  36. package/skills/douyin-enterprise-short-video-export/SKILL.md +29 -0
  37. package/skills/douyin-enterprise-short-video-export/agents/openai.yaml +4 -0
  38. package/skills/douyin-enterprise-video-rankings/SKILL.md +51 -0
  39. package/skills/douyin-enterprise-video-rankings/agents/openai.yaml +4 -0
  40. package/skills/douyin-enterprise-video-rankings/references/industry-taxonomy.md +29 -0
  41. package/skills/douyin-web-login/SKILL.md +102 -0
  42. package/skills/douyin-web-login/agents/openai.yaml +4 -0
  43. package/skills/toutiao-creator-article-draft/SKILL.md +154 -0
  44. package/skills/toutiao-creator-article-draft/agents/openai.yaml +4 -0
  45. package/skills/toutiao-web-login/SKILL.md +96 -0
  46. package/skills/toutiao-web-login/agents/openai.yaml +4 -0
  47. package/skills/xiaohongshu-creator-image-text-publish/SKILL.md +46 -0
  48. package/skills/xiaohongshu-creator-image-text-publish/agents/openai.yaml +4 -0
  49. package/skills/xiaohongshu-creator-image-text-publish/references/LICENSE.social-auto-upload +21 -0
  50. package/skills/xiaohongshu-creator-image-text-publish/references/execution-contract.md +46 -0
  51. package/skills/xiaohongshu-creator-image-text-publish/references/upstream.md +31 -0
  52. package/skills/xiaohongshu-creator-login/SKILL.md +106 -0
  53. package/skills/xiaohongshu-creator-login/agents/openai.yaml +4 -0
  54. package/skills/xiaohongshu-creator-publish/SKILL.md +153 -0
  55. package/skills/xiaohongshu-creator-publish/agents/openai.yaml +4 -0
  56. package/src/media_agent/__init__.py +1 -0
  57. package/src/media_agent/cli.py +28 -0
  58. package/src/media_agent/commands.sh +436 -0
  59. package/src/media_agent/platforms/__init__.py +1 -0
  60. package/src/media_agent/platforms/douyin/__init__.py +1 -0
  61. package/src/media_agent/platforms/douyin/check_login.py +196 -0
  62. package/src/media_agent/platforms/douyin/collect_industry_taxonomy.py +184 -0
  63. package/src/media_agent/platforms/douyin/collect_video_rankings.py +352 -0
  64. package/src/media_agent/platforms/douyin/douyin_full_login.py +391 -0
  65. package/src/media_agent/platforms/douyin/douyin_hotspot_v2.py +454 -0
  66. package/src/media_agent/platforms/douyin/douyin_publish.py +1135 -0
  67. package/src/media_agent/platforms/douyin/enterprise_login.py +128 -0
  68. package/src/media_agent/platforms/douyin/export_short_video.py +70 -0
  69. package/src/media_agent/platforms/douyin/login_controller.py +508 -0
  70. package/src/media_agent/platforms/douyin/validate_industry_taxonomy.py +152 -0
  71. package/src/media_agent/platforms/douyin/validate_rankings.py +254 -0
  72. package/src/media_agent/platforms/toutiao/__init__.py +1 -0
  73. package/src/media_agent/platforms/toutiao/toutiao_check_login.py +54 -0
  74. package/src/media_agent/platforms/toutiao/toutiao_login_controller.py +250 -0
  75. package/src/media_agent/platforms/toutiao/toutiao_login_evidence.py +50 -0
  76. package/src/media_agent/platforms/toutiao/toutiao_login_ipc.py +70 -0
  77. package/src/media_agent/platforms/xiaohongshu/__init__.py +1 -0
  78. package/src/media_agent/platforms/xiaohongshu/xiaohongshu_check_login.py +189 -0
  79. package/src/media_agent/platforms/xiaohongshu/xiaohongshu_login_controller.py +449 -0
  80. package/src/media_agent/platforms/xiaohongshu/xiaohongshu_login_evidence.py +64 -0
  81. package/src/media_agent/platforms/xiaohongshu/xiaohongshu_login_ipc.py +120 -0
  82. package/src/media_agent/platforms/xiaohongshu/xiaohongshu_publish.py +925 -0
  83. package/src/media_agent/runtime/__init__.py +1 -0
  84. package/src/media_agent/runtime/account_manager.py +672 -0
  85. package/src/media_agent/runtime/browser.py +5 -0
  86. package/src/media_agent/runtime/paths.py +7 -0
  87. package/src/media_agent/script_map.json +23 -0
  88. package/src/node/config.mjs +48 -0
  89. package/src/node/integrity.mjs +34 -0
  90. package/src/node/skills.mjs +85 -0
  91. package/tools/archive_releases.py +83 -0
  92. package/tools/artifacts.py +56 -0
  93. package/tools/build_release.py +82 -0
  94. package/tools/check_catalog.py +23 -0
  95. package/tools/install_runtime.py +144 -0
  96. package/tools/run_tests.py +21 -0
@@ -0,0 +1,178 @@
1
+ # 输出 Schema
2
+
3
+ 所有时间使用带时区的 ISO 8601。计数同时保留页面原文和解析值;字段不可见时解析值为 `null`,并填写 `missing_reason`。
4
+
5
+ ## 账号 JSON
6
+
7
+ ```json
8
+ {
9
+ "platform": "douyin",
10
+ "query": "一叶智能",
11
+ "profile_url": "https://www.douyin.com/user/...",
12
+ "douyin_id": "98898695066",
13
+ "nickname": "一叶智能",
14
+ "avatar_url": "https://example.invalid/avatar.jpg",
15
+ "avatar_screenshot": "evidence/account-avatar.png",
16
+ "verification_text": "深圳一数一叶智能科技有限公司",
17
+ "verification_type": "enterprise",
18
+ "works_display": "9",
19
+ "works_count": 9,
20
+ "following_display": "54",
21
+ "following_count": 54,
22
+ "followers_display": "551",
23
+ "followers_count": 551,
24
+ "likes_received_display": "989",
25
+ "likes_received_count": 989,
26
+ "confirmed_by_user": true,
27
+ "confirmed_at": "2026-08-06T15:00:00+08:00",
28
+ "collected_at": "2026-08-06T15:01:00+08:00",
29
+ "source_screenshot": "evidence/account-profile.png",
30
+ "required_fields_complete": true,
31
+ "missing_reasons": {}
32
+ }
33
+ ```
34
+
35
+ 示例值只说明字段形状,不是实际采集事实。
36
+
37
+ 账号层固定必检字段为:`avatar_screenshot`、`nickname`、`douyin_id`、`verification_text`、`following_display/count`、`followers_display/count`、`likes_received_display/count`、`works_display/count`。无认证时 `verification_text` 和 `verification_type` 可为 `null`,但 `missing_reasons.verification_text` 必须明确为 `not_verified`。除无认证外,任何必检字段为 `null` 都必须提供页面不可见等具体原因,并使 `required_fields_complete=false`。
38
+
39
+ `source_screenshot` 必须引用账号个人主页顶部信息区截图。该截图需进入证据 ZIP;证据 manifest 对应记录至少包含:
40
+
41
+ ```json
42
+ {
43
+ "evidence_type": "account_profile",
44
+ "source_url": "https://www.douyin.com/user/...",
45
+ "screenshot": "evidence/account-profile.png",
46
+ "screenshot_sha256": "64位小写SHA-256"
47
+ }
48
+ ```
49
+
50
+ 作品网格截图使用 `evidence_type="works_grid"`,每个作品详情截图使用 `evidence_type="work_detail"`。禁止将主页和网格都笼统标成 `profile`。作品详情证据还必须保存 `work_id`、`profile_grid_position`、`final_filename`、`source_url` 和最终 ZIP 内文件的 `screenshot_sha256`。
51
+
52
+ ## 作品 JSONL/CSV
53
+
54
+ 进入详情页前先保存 `candidates.json`。数组严格按主页作品网格从左到右、从上到下排序;默认最多 20 条,账号不足 20 条时按实际数量:
55
+
56
+ ```json
57
+ [
58
+ {
59
+ "profile_grid_position": 1,
60
+ "work_id": "作品ID",
61
+ "work_type": "video",
62
+ "raw_detail_url": "https://www.douyin.com/video/...?source=profile",
63
+ "detail_url": "https://www.douyin.com/video/...",
64
+ "dedupe_method": "work_id",
65
+ "is_pinned": true,
66
+ "card_visible_title": "卡片可见文本",
67
+ "bounding_box_left": 190,
68
+ "bounding_box_top": 330,
69
+ "card_screenshot": "evidence/card-001.png",
70
+ "grid_screenshot": "evidence/account-works-grid.png"
71
+ }
72
+ ]
73
+ ```
74
+
75
+ 候选对象来自同一个作品卡片节点。不得将独立获得的链接数组、标题数组、封面数组或坐标数组按下标拼接。`work_type` 至少允许 `video`、`note` 和 `unknown`,对应详情路径至少支持 `/video/<id>` 与 `/note/<id>`。`work_type` 表示平台详情路由类型;如需描述内容形态,另存 `content_format=video|image_text`。未知类型或无法解析链接的卡片仍保留真实 `profile_grid_position`,相应字段为 `null` 并填写 `missing_reasons`,后续卡片不得向前补位。
76
+
77
+ 候选顺序使用卡片 bounding box 动态还原:先按 `top` 分行,同一行按 `left` 排序。当前页面列数由实际布局决定,不能固化为特定列数。主页展示作品总数与已加载直属卡片数不一致时,必须继续加载或记录差异原因。
78
+
79
+ 每条作品一行,CSV 与 JSONL 的共享业务字段保持一致;JSONL 可额外保存平台、账号和证据路径等溯源字段。`hashtags` 和 `missing_reasons` 在 CSV 中编码为 JSON 字符串。作品文本采用兼容口径 `legacy_title_as_full_caption_v1`:`title` 保存详情页完整作品文案,不生成 `description`、`display_text` 或 `title_status` 等重复文本列。
80
+
81
+ ```json
82
+ {
83
+ "platform": "douyin",
84
+ "competitor_profile_url": "https://www.douyin.com/user/...",
85
+ "competitor_douyin_id": null,
86
+ "competitor_nickname": "一叶智能",
87
+ "work_id": "作品ID",
88
+ "work_type": "video",
89
+ "content_format": "video",
90
+ "dedupe_method": "work_id",
91
+ "raw_detail_url": "https://www.douyin.com/video/...?source=profile",
92
+ "detail_url": "https://www.douyin.com/video/...",
93
+ "sequence": 1,
94
+ "profile_grid_position": 1,
95
+ "is_pinned": false,
96
+ "grid_screenshot": "evidence/account-works-grid.png",
97
+ "cover_url": "https://example.invalid/cover.jpg",
98
+ "cover_screenshot": "evidence/work-001-cover.png",
99
+ "detail_screenshot": "evidence/work-001-detail.png",
100
+ "title": "标题或完整描述",
101
+ "title_extraction_method": "visible_dom",
102
+ "hashtags": ["标签1", "标签2"],
103
+ "duration_display": "00:49",
104
+ "duration_seconds": 49,
105
+ "published_at_display": "2022年11月30日",
106
+ "published_at": "2022-11-30",
107
+ "likes_display": "299",
108
+ "likes_count": 299,
109
+ "comments_display": "6",
110
+ "comments_count": 6,
111
+ "favorites_display": "28",
112
+ "favorites_count": 28,
113
+ "shares_display": "15",
114
+ "shares_count": 15,
115
+ "collected_at": "2026-08-06T15:03:00+08:00",
116
+ "missing_reasons": {}
117
+ }
118
+ ```
119
+
120
+ `title_extraction_method` 允许 `visible_dom` 或 `evidence_screenshot_transcription`,每条非空 `title` 都必须填写。页面存在一段当前作品文案时,`title` 保存该完整原文;DOM 读取失败但本作品截图中文字清晰可辨时允许转录。截图中文字可见而 `title` 为空属于提取失败,不能填写页面不可见类缺失原因。只有页面和本作品证据截图都没有作品文案时,才允许 `title=null`,并保存 `missing_reasons.title="no_caption_visible"`。
121
+
122
+ `card_visible_title` 只用于候选核验,不能直接复制为最终 `title`。卡片文本中的互动数字前缀、无障碍副本或完全重复文本必须在详情页重新读取后规范化;不得误删正文中的真实数字、表情、话题或原始顺序。最终标题仍含确认过的卡片指标前缀或完整重复副本时,记录标题提取失败并返回 `PARTIAL_COMPLETE`。
123
+
124
+ 播放器控件、快捷键提示、悬浮提示、自动播放提示和无障碍操作文案必须排除。例如“1s 后循环播放当前视频”属于播放器 UI,不是作品文案;不得写入 `title`。找不到真实文案时使用 `title=null` 和对应缺失原因。
125
+
126
+ 详情字段按路由类型读取:`video` 使用播放器下方标题区和底部横向互动栏;`note` 使用右侧作者信息区的标题/发布时间以及媒体右缘的竖向互动栏。Note右侧“相关推荐”列表不得作为当前作品字段来源。
127
+
128
+ 任何其他字段为 `null` 或空字符串时,也必须在 `missing_reasons` 中提供对应字段的具体原因;不得出现空字段与空的 `missing_reasons` 并存。
129
+
130
+ `is_pinned` 的唯一依据是账号主页作品卡片左上角可见的黄色“置顶”角标。存在角标时为 `true`,不存在时为 `false`;`grid_screenshot` 必须能证明这一判断。置顶作品仍需保存真实发布时间,不能把网格第一位等同于最新发布。
131
+
132
+ 互动指标存在四种明确的零值文案:
133
+
134
+ - 当前作品心形点赞图标旁显示“赞”时:`likes_display` 保存 `"赞"`,`likes_count` 保存 `0`。
135
+ - 当前作品评论图标旁显示“抢首评”时:`comments_display` 保存 `"抢首评"`,`comments_count` 保存 `0`。
136
+ - 当前作品收藏图标旁显示“收藏”时:`favorites_display` 保存 `"收藏"`,`favorites_count` 保存 `0`。
137
+ - 当前作品分享图标旁显示“分享”时:`shares_display` 保存 `"分享"`,`shares_count` 保存 `0`。
138
+
139
+ 这些值不是缺失值,对应字段不得写入 `missing_reasons`。必须从当前作品详情页互动栏的对应图标旁读取,右侧推荐视频、评论正文和播放器控制栏不属于互动数据来源。
140
+
141
+ `missing_reasons` 与完成状态必须一致。若某行包含 `interaction_bar_not_found` 或任一必需互动字段缺失原因,该行不能计入 `complete_works`,批次 `interaction_extraction_failures` 必须反映实际失败数。不得同时报告 `complete_works=collected_works`、`interaction_extraction_failures=0`。
142
+
143
+ 所有截图字段使用证据 ZIP 内可解析的相对路径,例如 `profile.png`、`grid_full.png`、`work_01.png`;不得保存发送方环境的绝对路径。交付前要求 `manifest_hash_mismatches=0` 且 `absolute_screenshot_paths=0`。
144
+
145
+ ## 批次元数据
146
+
147
+ 结果目录另存 `meta.json`:
148
+
149
+ ```json
150
+ {
151
+ "task_id": "collect_douyin_competitor_...",
152
+ "text_schema": "legacy_title_as_full_caption_v1",
153
+ "social_profile": "douyin_woshiyanyuan",
154
+ "query": "一叶智能",
155
+ "competitor_confirmed": true,
156
+ "requested_works": 20,
157
+ "candidate_works": 20,
158
+ "unique_candidate_works": 20,
159
+ "video_works": 19,
160
+ "note_works": 1,
161
+ "unresolved_candidates": 0,
162
+ "collected_works": 20,
163
+ "complete_works": 20,
164
+ "partial_works": 0,
165
+ "failed_works": 0,
166
+ "duplicate_candidates": 0,
167
+ "insufficient_public_works": false,
168
+ "identity_mismatches": 0,
169
+ "evidence_binding_mismatches": 0,
170
+ "manifest_hash_mismatches": 0,
171
+ "absolute_screenshot_paths": 0,
172
+ "account_fields_complete": true,
173
+ "account_profile_screenshot_included": true,
174
+ "evidence_screenshots": 41,
175
+ "started_at": "2026-08-06T15:00:00+08:00",
176
+ "finished_at": "2026-08-06T15:20:00+08:00"
177
+ }
178
+ ```
@@ -0,0 +1,44 @@
1
+ ---
2
+ name: douyin-creator-image-text-publish
3
+ description: 用于用户提供有序本地图片、标题和正文后,在抖音创作者中心准备或发布多图图文作品,以及核验或恢复该图文任务。不要用于视频、文章、登录或生成文案和图片。
4
+ ---
5
+
6
+ # 抖音图文发布(可见浏览器)
7
+
8
+ 从 social-auto-upload 的图文 Skill 和 `DouYinNote` 提取页面流程,由 Agent 操作本项目可见持久化浏览器。状态为 **ADAPTED_UNVERIFIED**:已提取适配,尚未完成真实账号图文验收。
9
+
10
+ 执行前必须读取 [任务与会话契约](references/execution-contract.md)。页面定位线索和上游固定版本见 [提取来源](references/upstream.md)。
11
+
12
+ ## 输入与路由
13
+
14
+ - 必需:`profile_id`、稳定 `task_id`、有序 `images`(本地绝对路径)、用户提供的 `title` 和 `body`;可选 `tags`。正文允许用户明确指定空字符串,缺失不等于留空。
15
+ - “上传看看/准备/预览”走 `prepare`,停在 `PREPARED`;明确“发布这些图文”走 `publish`,授权绑定当前账号及完整内容;“查结果”走只读 `verify`。意图不明时先澄清。
16
+ - 图片顺序以传入列表为准,不按文件名排序。只接收图片;视频使用 `douyin-creator-publish`,文章不走本流程。
17
+ - 成稿原样填写;超出页面限制返回 `CONTENT_INVALID`,不截断、改写或自动生成标题、正文、封面、配图、音乐。用户要求定时或其他扩展设置时返回 `UNSUPPORTED_OPTION`,本版仅立即发布。
18
+
19
+ ## 进入图文编辑页
20
+
21
+ 1. 按契约核对 Profile、`creator_publish`、锁所有权及真实页面账号。保持同一个 browser/context/page,`headless=False`;不运行 `sau`,不安装或调用第三方 MCP,不复制 Cookie。
22
+ 2. 在当前页面进入 `https://creator.douyin.com/creator-micro/content/upload`,按可见文本点击“发布图文”。必须确认图文上传控件及页面类型;不能误用“发布文章”或视频入口。
23
+ 3. 如果自动弹出原生文件选择器,先取消并确认窗口消失,再用当前控制器的文件上传能力。定位图文面板内接收图片的 file input;候选选择器见来源文档,不可对多个候选直接取第一个。
24
+ 4. 当前编辑器若已有其他素材或文案,返回 `EDITOR_NOT_EMPTY`,不得清空或覆盖旧稿。只有本任务明确恢复且身份重新核验通过的页面可继续。
25
+
26
+ ## 上传并填写
27
+
28
+ 1. 校验本地图片稳定可读、实际格式与页面允许格式一致,保存每张 SHA-256 和顺序;先检查任务记录中的重复与未决提交。
29
+ 2. 一次把有序图片清单交给目标 file input,进入 `UPLOADING`。上游路由线索为 `/creator-micro/content/post/image`,但 URL 变化不代表全部图片已上传。
30
+ 3. 最多等待 5 分钟,持续读取进度、错误及逐张预览;全部上传完成且预览数量、内容和顺序与清单一致,才可继续。少图、顺序不明、失败或超时按契约停止,不整批重传。
31
+ 4. 定位“填写作品标题”输入框及图文正文 `contenteditable` 编辑器,原样填写标题和正文。键盘操作先聚焦目标编辑器,按宿主系统使用全选快捷键,不对整个页面盲目全选。
32
+ 5. 只添加用户明确提供的话题,核对准确候选;没有匹配项时返回 `TAG_UNRESOLVED`,不选相近热词。收起候选浮层,读回标题、正文、已选话题,确认无截断、漏字、重复或残留。
33
+ 6. 保持用户提供的图片顺序和平台默认首图展示,不另做封面、裁剪、音乐、位置、活动、商品或声明。确认页面为立即发布;记录可见范围和任何平台自动附加项。如平台强制要求未提供的设置,返回 `SETTING_REQUIRED`。
34
+ 7. 按契约保存准备快照,返回 `PREPARED`,包含实际图片数量、顺序、文案和默认设置。仅准备任务在此停止并保持会话。
35
+
36
+ ## 单次提交与核验
37
+
38
+ 1. 按契约核对当前任务授权、快照和素材,保存 `SUBMITTING` 后,对唯一可见、启用、无遮挡的“发布”按钮执行一次真实 locator/pointer click。不得用 JS `element.click()` 或重试循环提交。
39
+ 2. 等待平台自动进入作品管理或显示明确结果,最多 180 秒;期间不刷新、不导航、不再次点击。
40
+ 3. 有明确平台接收证据后等待约 10 秒,在同一页面的作品管理列表读取结果;已在管理页时可刷新一次。按账号、图文类型、完整标题、本次时间及图片预览综合匹配,不借用视频时长或同名旧作品。
41
+ 4. 每 15–20 秒只读核验,最多 5 分钟。目标唯一出现但审核未知为 `SUBMITTED`;明确审核中为 `REVIEWING`;明确已发布为 `PUBLISHED`;明确拒绝为 `REJECTED`。列表未找到或匹配有歧义为 `PUBLISH_INDETERMINATE`,不重发。
42
+ 5. 没有接收证据时依契约进入不确定状态,只读查找;不要把成功 URL、按钮消失或本地点击返回当作已发布。
43
+
44
+ 结果字段、跨消息恢复和收尾均按 [任务与会话契约](references/execution-contract.md) 执行。图文没有新增 CLI;现有 `publish-*` 仍是视频命令。
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "抖音图文发布"
3
+ short_description: "在现有可见浏览器中上传给定图片和成稿,单次发布并核验结果"
4
+ default_prompt: "Use $douyin-creator-image-text-publish to prepare or publish the supplied images and text in the existing visible account browser."
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 dreammis
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,46 @@
1
+ # Agent 图文任务与会话契约
2
+
3
+ 本文件定义 Agent 应遵守的步骤,不是已经实现这些门禁的发布 CLI。需要宿主提供可见浏览器控制、文件上传和任务记录读写能力;缺少能力时报告具体阻塞,不编造命令或执行结果。
4
+
5
+ ## 会话前提
6
+
7
+ - 只使用目标账号已配置的持久化 Profile、`browser_data`、固定指纹和唯一 lock,确认 `creator_publish` capability。实际运行目录以部署配置为准,不硬编码开发机器路径。
8
+ - 当前 browser/context/page 和 lock 已归本任务时复用原控制器。其他任务持锁或无法证实所有权时返回 `PROFILE_LOCKED`,不抢锁、不强删锁、不启动第二个浏览器。
9
+ - 尚无会话时,由本项目既有可见浏览器运行时按原 Profile 配置及 `headless=False` 建立会话、取得锁;无法取得受控页面时返回 `BROWSER_SESSION_REQUIRED`。本 Skill 不提供另一套浏览器启动器。
10
+ - 在当前页面核验真实账号及后台菜单;不能仅凭 Cookie 文件、URL 或缓存认定登录。无法确认账号返回 `ACCOUNT_UNVERIFIED`,账号不符返回 `ACCOUNT_MISMATCH`,登录失效返回 `LOGIN_REQUIRED` 并交给平台专用登录 Skill。已有锁期间不要另跑会启动浏览器的登录检查命令。
11
+ - 保持现有窗口、控制器和锁直到任务结束。禁止无头浏览器、临时 context、复制登录态、Cookie 导入导出、第三方 MCP 或 `sau ... upload-note`。上游 `--headed` 不是现有会话的接管接口。
12
+
13
+ ## 内容与准备快照
14
+
15
+ 1. 输入缺失返回 `INPUT_REQUIRED`,等待用户提供;正文明确留空可接受。完整文案原样使用,不自动生成、截断或润色;图像不自动生成、编辑或替换。
16
+ 2. 图片必须是稳定普通文件,记录绝对路径、大小、真实格式和 SHA-256,检查前后大小/修改时间一致;只按后缀判断格式不够。不支持或仍在写入时停止。
17
+ 3. `media_digest` 是有序图片 SHA-256 字符串数组的 UTF-8 JSON 的 SHA-256。用以下 JSON 对象的 SHA-256 构造 `payload_digest`:`platform`、`profile_id`、`title`、`body`、有序 `tags`、有序 `images_sha256`、`publish_mode=immediate`。二者均采用 JSON 对象键排序、`ensure_ascii=False`、无多余空白;数组顺序不变。记录页面实际设置的快照,不能仅记录输入期望值。
18
+ 4. 任务记录放在运行时的 `tasks/<platform>_image_text_publish/<profile_id>/<task_id>/`。标识只能用字母、数字、下划线、短横线,禁止路径穿越;该目录和任何截图、账本均不得进入 Git 或迁移包。
19
+ 5. 持有账号锁时,扫描同平台同账号所有图文任务记录;相同 `media_digest` 已处于 `SUBMITTING`、`SUBMITTED`、`REVIEWING`、`PUBLISHED` 或 `PUBLISH_INDETERMINATE`,先核验旧任务,不新建发布。改标题或换 `task_id` 不解除阻止;其他账号的平台记录不能误挡当前任务。
20
+ 6. 每个任务维护追加式 `events.jsonl`,记录任务、两个摘要、会话身份、状态、可见证据及时间;不能写入凭据。旧记录不可覆写。首次任务可新建记录;已知旧任务记录缺失、损坏、无法持久化或历史提交无法查清时返回 `LEDGER_UNAVAILABLE`,禁止提交。
21
+ 7. 用编辑器内逐张预览核对数量、内容和顺序;头像、推荐图片、上传占位符不计入。数量一致但顺序或对应内容无法核实,也不能给出 `images_verified=true`。返回 `UPLOAD_INCOMPLETE` 或 `IMAGE_ORDER_UNVERIFIED`,保持现场,不整批重传。
22
+ 8. 标题、正文、话题和页面设置均须读回。正文仅可为比较而统一 CRLF/LF;不能通过删空格、删段落等方式掩盖实际差异。平台话题 token 应与正文分别核验。身份或内容不一致返回 `CONTENT_MISMATCH`。
23
+ 9. 门禁均通过后持久化 `PREPARED` 事件,保存快照及截图证据路径。仅准备时保持浏览器和 lock,返回 `submit_attempted=false`;不声称已保存平台草稿,除非另有真实草稿保存与列表证据。
24
+
25
+ ## 发布授权与一次提交
26
+
27
+ - 授权包含当前 `task_id`、账号、`payload_digest` 和页面设置。用户明确要求发布给定成稿时,该指令就是本任务授权,不重复索取同一授权;“准备看看”没有发布授权。后续“发布”只能绑定唯一、完整读回的准备任务。
28
+ - 正文、图片字节、顺序、账号或设置有变化时,准备快照及旧内容授权失效。先说明差异、重新核验并确认变更后的内容,不偷偷替换。
29
+ - 提交前再次核验账号、页面、图片哈希与顺序、完整文案、设置和按钮唯一/可见/启用/无遮挡。先追加并持久化 `SUBMITTING`、`submit_attempted=true`、授权摘要和时间,再发出一次真实点击。记录写入失败则不点击。
30
+ - 点击调用超时或抛异常,也属于已经尝试提交;禁止重新调用点击,不能等工具返回成功才记下提交意图。日志无法确定是否点过时同样按不确定处理。
31
+ - 提交后有明确接收证据才能记 `SUBMITTED`;只有平台目标作品状态才能给出 `REVIEWING`、`PUBLISHED`、`REJECTED`。按钮消失、URL 改变、固定等待结束和本地日志不能单独证明发布。
32
+ - 无响应、网络超时、作品缺失或同名歧义都进入 `PUBLISH_INDETERMINATE`。先等待规定窗口再只读核验;平台无明确接收结果时保持当前页,可在同一 context 的只读标签页查看作品管理,不新开浏览器。禁止自动再次提交、上传或改标题重发。
33
+
34
+ ## 中断、恢复与收尾
35
+
36
+ - 会话关闭后,旧 page、DOM、准备快照的页面证据全部失效。持久化 Profile 只证明可能保留登录,不证明编辑器保留。
37
+ - 恢复前读取旧任务记录。有提交意图或意图不明时,只读核验作品,不能重新准备发布。
38
+ - 明确从未尝试提交时,允许由现有运行时重开同一 Profile;重新核验账号,按平台真实草稿证据唯一恢复本任务。没有可核验草稿时返回 `PREPARE_SESSION_LOST`,不得自动新建、重传或点击;用户明确要求重新准备后才可继续。
39
+ - 临时控制失败保持现场;只能重试已确定无提交副作用的读取/可逆动作,不能把失败处理包装成再次点击发布。
40
+ - 仅准备或结果不确定时默认保留会话与锁。用户要求关闭时先持久化状态,再正常关闭本任务拥有的 page/context/browser,确认退出后释放本任务锁;不确定状态仍禁止重发。用户未要求关闭时,已发布/明确拒绝/只读查询完成可正常收尾。禁止 `kill`、清空 Profile 或删除作品。
41
+
42
+ ## 最小返回
43
+
44
+ 返回 `state`、`platform`、`task_id`、`profile_id`、`account_verified`、`media_digest`、`payload_digest`、`expected_image_count`、`actual_image_count`、`images_verified`、`image_order_verified`、`title`、`body_verified`、`tags_verified`、`settings_readback`、`submit_attempted`、`work_found`、`work_id`(拿不到为 null)、`status_evidence`、`browser_retained`、`lock_retained`。
45
+
46
+ 缺失证据用 false/unknown/null 表达,不能补造。准备完成、平台接收、审核中和审核通过必须分别报告。
@@ -0,0 +1,30 @@
1
+ # 提取来源与适配差异
2
+
3
+ - 上游:[dreammis/social-auto-upload](https://github.com/dreammis/social-auto-upload)
4
+ - 固定提交:`0012d2c355f88f683cc38dde2a2db209e14091bc`,提取日期:2026-09-23。
5
+ - [上游 Skill](https://github.com/dreammis/social-auto-upload/blob/0012d2c355f88f683cc38dde2a2db209e14091bc/skills/douyin-upload/SKILL.md)
6
+ - [上游 CLI 契约](https://github.com/dreammis/social-auto-upload/blob/0012d2c355f88f683cc38dde2a2db209e14091bc/skills/douyin-upload/references/cli-contract.md)
7
+ - [上游代码](https://github.com/dreammis/social-auto-upload/blob/0012d2c355f88f683cc38dde2a2db209e14091bc/uploader/douyin_uploader/main.py):`DouYinNote.validate_upload_args`、`upload_note_content`、`DouYinBaseUploader.fill_title_and_description`。
8
+ - 来源材料采用 MIT;版权与许可全文随 Skill 保存在 [LICENSE.social-auto-upload](LICENSE.social-auto-upload)。本地内容是图文流程的适配文档,不是原版 Skill 或完整上游运行时。
9
+
10
+ ## 提取的页面线索
11
+
12
+ | 步骤 | 固定版本中的线索 | 本项目采用条件 |
13
+ | --- | --- | --- |
14
+ | 入口 | `/creator-micro/content/upload` → “发布图文” | 实际页面可见并确认图文类型 |
15
+ | 上传 | `div[class^='container'] input[accept*='image']` | 在图文面板内唯一匹配,不依赖易变类名作唯一证据 |
16
+ | 编辑页 | `/creator-micro/content/post/image` | 同时检查逐张图片预览,不能只等 URL |
17
+ | 标题 | `input[placeholder*="填写作品标题"]` | 唯一、可见且页面语义相符 |
18
+ | 正文 | `div.zone-container[contenteditable="true"]` | 确认属于当前图文正文编辑器 |
19
+ | 发布 | role=button、name=发布、exact=true | 必须经过任务授权门禁且仅点击一次 |
20
+ | 结果 | `/creator-micro/content/manage?enter_from=publish` | 继续核验目标作品卡片及审核状态 |
21
+
22
+ 上游图文校验为最多 35 张图片、标题不超过 20 字符、正文不超过 1000 字符;CLI 契约说明不支持 GIF。这些是固定版本实现值,不是平台永远有效的规则;以当前页面限制和实际格式校验为准,遇到冲突停止并报告,不自行删图或缩短文案。
23
+
24
+ ## 适配范围
25
+
26
+ 保留用户输入 `images + title + note + tags` 的图文流程,将 `note` 映射为本项目 `body`。标题/正文/图片顺序原样保留。
27
+
28
+ 上游 CLI 同时支持 `--headless` / `--headed`;这里不直接调用 CLI。上游 `upload()` 会 launch 浏览器、new_context 并载入 `storage_state`;本 Skill 改为操作本项目现有可见持久化会话。
29
+
30
+ 不提取上游 Cookie 登录/导出、位置权限、可选音乐、定时、文案截断和发布循环。上游图文提交在 `while True` 中点击发布并等待 URL,超时可能再次点击;本项目以先记录提交意图、单次点击和列表核验替换。选择器只用于辅助 Agent 识别当前页面,不是线上已验收的保证。
@@ -0,0 +1,32 @@
1
+ ---
2
+ name: douyin-creator-index
3
+ description: 采集抖音创作者中心的实时热点和飙升热点。用于抖音指数分页采集、真实排名与热度解析、趋势证据识别、热点链接覆盖与抽检、JSON/CSV/meta/报告输出及交付验证。
4
+ ---
5
+
6
+ # 抖音创作者指数采集
7
+
8
+ 目标页:`https://creator.douyin.com/creator-micro/creator-count/arithmetic-index`。
9
+
10
+ ```bash
11
+ media-agent collect-douyin-index <profile_id> [--lists realtime,rising] [--pages 3]
12
+ ```
13
+
14
+ ## 流程
15
+
16
+ 1. 确认 Profile 有 `creator_index_collect` capability,获取 lock 并真实检查 Creator 登录。
17
+ 2. 未登录返回 `LOGIN_REQUIRED`;采集任务不处理扫码或验证码。
18
+ 3. 通过“抖音实时热点”和“抖音飙升热点”标题定位各自最近公共容器,将行与分页器限定在对应容器内。
19
+ 4. 默认各采集 3 页、每页 10 条。翻页后验证首行、rank 或 active 页变化,并检查跨页重复。
20
+ 5. 保存 `list_type`、rank、热点名称、热度 display/numeric、趋势、采集时间、来源 URL、热点 ID、详情 URL 和 URL 类型。
21
+ 6. 文本被省略时读取 `textContent`、`title`、`aria-label` 或 tooltip;不能保存省略号文本。
22
+ 7. 趋势仅依据文字、SVG、class、颜色、旋转或 `data-*` 证据映射为 `up/down/flat/unknown`,不得猜测。
23
+ 8. 详情 URL 只从真实链接、路由或点击后的最终 URL 获取。构造链接必须标记并验证;无证据时留空。
24
+ 9. 至少抽查两类榜单各 3 个详情链接,验证非登录页、非空白/404 且主题一致。
25
+
26
+ ## 输出与边界
27
+
28
+ 输出 JSON、CSV、meta JSON、截图和 Markdown 报告;JSON/CSV 为事实来源。meta 披露实际范围、排名连续性、重复、链接覆盖、未知趋势、缺失字段、抽检、浏览器关闭、lock 释放和附件投递状态。
29
+
30
+ v1.0.3 的 `douyin_hotspot_v2.py` 硬编码测试 Profile,`media-agent` 未把 `<profile_id>` 传入采集脚本。对其他 Profile 执行前必须确认安装版本已参数化,否则返回 `IMPLEMENTATION_REQUIRED`,不得声称使用了请求的账号。
31
+
32
+ 检查上述参数化限制时,必须读取实现 `src/media_agent/platforms/douyin/douyin_hotspot_v2.py` 和命令路由 `src/media_agent/commands.sh`;已安装环境对应 `<MEDIA_AGENT_HOME>/.app/current/` 下的这些路径。命令存在不代表参数化限制已消除。
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "抖音创作者指数采集"
3
+ short_description: "采集抖音创作者中心实时热点和飙升热点并验证分页、趋势与链接"
4
+ default_prompt: "Use $douyin-creator-index to collect and validate Douyin Creator hotspot rankings."
@@ -0,0 +1,58 @@
1
+ ---
2
+ name: douyin-creator-login
3
+ description: 登录抖音创作者中心并固化浏览器会话。用于 creator.douyin.com 的二维码登录、扫码后的短信二次验证、二维码或验证码重试、跨消息恢复、真实登录状态检查,以及正常关闭后使用同一 Profile 验证免扫码登录。
4
+ ---
5
+
6
+ # 抖音创作者中心持久化登录
7
+
8
+ 仅处理 Creator 登录和持久化验证,不执行发布或采集。
9
+
10
+ ## 运行边界
11
+
12
+ - 从 `~/.media-agent/social-accounts` 执行命令,以安装机器的 `media-agent --help` 为准。
13
+ - 一个账号使用一个独立 `profile_id`、`browser_data`、固定指纹和 lock;禁止复制或共用登录状态。
14
+ - 保持一个 controller、browser、context 和 page。后续消息只通过原 Unix Socket 推进状态。
15
+ - 先执行 `media-agent check-login <profile_id> --site creator`;返回 0 时复核账号后结束。
16
+
17
+ ## 命令
18
+
19
+ ```bash
20
+ media-agent login-start <profile_id>
21
+ media-agent login-status <profile_id>
22
+ media-agent login-scan-done <profile_id>
23
+ media-agent login-refresh-qr <profile_id>
24
+ media-agent login-submit-code <profile_id>
25
+ media-agent login-resend-code <profile_id>
26
+ media-agent login-close <profile_id>
27
+ ```
28
+
29
+ 验证码必须通过 stdin/受限 IPC 传递,禁止放入命令参数、文件、环境变量、日志或回复。
30
+
31
+ ## 流程
32
+
33
+ 1. 执行 `login-start`,获取 `task_id`、controller PID、状态和真实二维码附件。
34
+ 2. 返回 `WAIT_QR_SCAN`,让用户只扫描最新二维码。不要结束 controller 或重新 `login-start`。
35
+ 3. 用户确认扫码后只执行 `login-scan-done`。
36
+ 4. 在原 page 中定位唯一可见的 `second_verify_panel`;仅在该 modal 内点击“接收短信验证码”。
37
+ 5. 确认 modal 内 input 唯一、可见、可用且完全位于 modal bounds 内,再请求验证码。
38
+ 6. 填写后验证 `modal_code_length=6`、`underlying_input_length=0`;在同一 modal 内点击一次“验证”。
39
+ 7. 验证码错误或过期时保持 page 和 lock,原地 `login-resend-code`,不要重新扫码。
40
+ 8. 二维码过期时只执行 `login-refresh-qr`;controller、browser 和 page 标识必须保持不变。
41
+
42
+ ## 登录判断与固化
43
+
44
+ 综合检查 `/creator-micro/` 路由、登录弹层和二维码消失、后台菜单、头像或账号名。证据冲突时返回 `indeterminate` 并短轮询,不能只凭 URL、Cookie 或 `state.json`。
45
+
46
+ 确认 `logged_in` 后:
47
+
48
+ 1. 执行 `login-close` 正常关闭写盘。
49
+ 2. 确认浏览器退出并释放 lock,等待至少 10 秒。
50
+ 3. 用同一 Profile 和启动参数重开,最多等待 60 秒。
51
+ 4. 无需扫码进入 Creator 后台后,报告 `persistence_verified=true`。
52
+ 5. 再次正常关闭;禁止 `kill`、`pkill`、清理 `browser_data` 或强删未知 lock。
53
+
54
+ 如果任务要求验证 Creator 与抖音主站共享登录态,必须继续调用 `douyin-web-login`,复用完全相同的账号 Profile 做双站点只读检查。不得新建临时 Profile,也不能仅凭 Cookie 文件存在宣称双站点一致。
55
+
56
+ ## 返回
57
+
58
+ 返回 `profile_id`、`task_id`、`login_status`、非敏感后台证据、`persistence_verified`、`relogin_qr_required`、浏览器退出和 lock 释放状态。不要返回 Cookie、手机号、二维码内容或验证码。
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "抖音创作者中心持久化登录"
3
+ short_description: "通过扫码和短信验证登录抖音创作者中心,并验证持久化浏览器会话"
4
+ default_prompt: "Use $douyin-creator-login to sign in to Douyin Creator and verify persistent login state."
@@ -0,0 +1,56 @@
1
+ ---
2
+ name: douyin-creator-publish
3
+ description: 在抖音创作者中心准备、确认、提交和核验视频作品。用于立即或定时发布、无副作用 dry-run、素材 SHA-256 去重、页面字段读回、最终发布单次授权、作品列表落地验证、状态查询及不确定提交恢复。
4
+ ---
5
+
6
+ # 抖音创作者中心作品发布
7
+
8
+ ## 命令
9
+
10
+ ```bash
11
+ media-agent publish-dry-run <profile_id> --media-path <path> [--scheduled-at <ISO>]
12
+ media-agent publish-prepare <profile_id> --media-path <path> [--scheduled-at <ISO>]
13
+ media-agent publish-confirm <profile_id>
14
+ media-agent publish-status <profile_id> --task-id <task_id>
15
+ media-agent publish-close <profile_id>
16
+ ```
17
+
18
+ 先确认目标 Profile 显式包含 `creator_publish` capability。
19
+
20
+ ## 准备
21
+
22
+ 1. 保持稳定 `task_id`,获取唯一 Profile lock。
23
+ 2. 执行真实 Creator `check-login` 并核对账号;未登录返回 `LOGIN_REQUIRED`,不要在发布任务中扫码。
24
+ 3. 校验素材为稳定普通文件,支持 MOV、MP4、WEBM;读取大小、时长、编解码和 SHA-256。
25
+ 4. 检查账本。相同 SHA-256 的 `submitted`、`reviewing` 或 `published` 永久阻止重复发布。
26
+ 5. `publish-dry-run` 不得打开浏览器、获取 lock、上传或写账本。
27
+ 6. `publish-prepare` 上传并等待平台处理完成,填写标题和简介,再从页面读回。
28
+ 7. 默认封面可接受;默认公开、允许保存。未明确授权时不设置位置、活动、合集、热点或声明。
29
+
30
+ ## 发布时间
31
+
32
+ - 立即发布:必须从页面确认“立即发布”真实选中。
33
+ - 定时发布:仅使用任务明确时间;平台实测要求当前时间至少 2 小时后且 14 天内。
34
+ - 对组合文本框输入 `YYYY-MM-DD HH:mm`,按 `Tab` 触发 React change/blur,并从页面读回完整时间。
35
+
36
+ ## 最终点击门禁
37
+
38
+ 1. 返回素材 SHA-256、标题、简介、封面、可见范围、时间和声明,进入 `WAIT_PUBLISH_CONFIRM`。
39
+ 2. 仅接受匹配 `task_id` 的 `authorization=CLICK_PUBLISH_ONCE`。
40
+ 3. 确认底部红色“发布”按钮唯一、可见、启用且无遮挡;必要时先关闭“视频预览功能”提示。
41
+ 4. 使用真实 locator/pointer click,最多一次;不要以 JavaScript `element.click()` 充当真实提交。
42
+ 5. 点击后禁止主动导航作品管理,等待平台自动跳转,最长 180 秒;禁止因超时第二次点击。
43
+
44
+ ## 落地核验
45
+
46
+ 平台进入作品管理后等待约 10 秒,强制刷新一次,再按完整标题、时长、封面和发布时间综合匹配。未找到时每 15–20 秒轮询,最长 5 分钟。
47
+
48
+ - 列表出现目标:写 `submitted`;页面显示审核中或已发布时写对应状态。
49
+ - 明确拒绝或未提交:写 `failed`。
50
+ - 页面、网络或 DOM 证据冲突:写 `indeterminate`,保持浏览器和 lock,禁止自动重发。
51
+
52
+ URL 跳转、点击计数、按钮消失或本地账本均不是成功证据。Creator 成功但 Leads 未同步时仍永久阻止重复发布。
53
+
54
+ ## 收尾
55
+
56
+ 成功或明确失败后正常关闭并释放 lock。`indeterminate` 默认保持现场。禁止 `kill`、`pkill`、覆盖账本原记录或自动重试。
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "抖音创作者中心作品发布"
3
+ short_description: "准备、确认、提交并核验抖音创作者中心视频作品发布结果"
4
+ default_prompt: "Use $douyin-creator-publish to safely prepare and publish a Douyin Creator video."
@@ -0,0 +1,26 @@
1
+ ---
2
+ name: douyin-enterprise-leads
3
+ description: 路由抖音企业号线索版后台任务。用于用户同时或概括请求 leads.cluerich.com 登录、短视频明细导出、视频榜单采集、行业分类树采集,或需要判断应调用哪个企业号线索版子 Skill 时。
4
+ ---
5
+
6
+ # 抖音企业号线索版工作流
7
+
8
+ 根据任务选择一个或多个专用 Skill:
9
+
10
+ - 登录或状态固化:`$douyin-enterprise-leads-login`
11
+ - 自有短视频原始 XLSX 导出:`$douyin-enterprise-short-video-export`
12
+ - 行业目录查询、一级/二级分类候选更新,以及线索榜、引流榜、热门榜采集:`$douyin-enterprise-video-rankings`(按意图选择子流程,不自动串联全量分类和榜单采集)
13
+
14
+ ## 共同约束
15
+
16
+ - 一个企业账号使用独立 Profile、`browser_data`、固定指纹和 lock。
17
+ - 同一 Profile 可访问 Creator 与 Leads,但两个主域的 Cookie/Storage 独立;必须分别真实检查登录状态。
18
+ - `state.json` 只作缓存,不能替代可见 DOM 证据。
19
+ - 在线任务按子流程检查 capability:导出用 `leads_export`,榜单用 `leads_rankings`,分类更新用 `leads_taxonomy`;仅查询本地行业基线不需要在线 capability、登录或浏览器锁。
20
+ - 数据任务未登录时返回 `LOGIN_REQUIRED` 并结束,不在采集任务内启动扫码。
21
+ - 正常关闭浏览器写盘并释放 lock;禁止强杀浏览器或清理 Profile。
22
+ - 登录、导出、榜单、行业分类分别保留独立 `task_id` 和输出目录,不把一个任务的状态推断给另一个。
23
+
24
+ ## v1.0.3 边界
25
+
26
+ 正式归档内的 `douyin-enterprise-leads` 是合并式 Skill。本仓库增加专用子 Skill 以改善触发和验收,但不修改不可变归档。执行前始终检查安装机器的 `media-agent --help` 和脚本参数,不根据旧文档编造命令。
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "抖音企业号线索版工作流"
3
+ short_description: "路由企业号线索版登录、短视频导出、视频榜单和行业分类任务"
4
+ default_prompt: "Use $douyin-enterprise-leads to route a Douyin enterprise Leads task to the correct workflow."
@@ -0,0 +1,36 @@
1
+ ---
2
+ name: douyin-enterprise-leads-login
3
+ description: 登录抖音企业号线索版后台并固化会话。用于 leads.cluerich.com 的“其他方式”抖音 OAuth 扫码授权、登录状态检查、提示框处理、正常关闭写盘,以及同一企业 Profile 重开后的免扫码验证。
4
+ ---
5
+
6
+ # 抖音企业号线索版登录
7
+
8
+ ## 站点与命令
9
+
10
+ 目标登录页:`https://leads.cluerich.com/pc/auth/login`。
11
+
12
+ ```bash
13
+ media-agent check-login <profile_id> --site leads
14
+ media-agent enterprise-login <profile_id> --site leads
15
+ ```
16
+
17
+ `media-agent-capabilities-v1.0.3` 的 `login-start` 控制器硬编码打开 Creator,不能把它当作 Leads OAuth 登录命令。使用 `enterprise_login.py` 前先确认安装目录和实际脚本参数。
18
+
19
+ ## 登录
20
+
21
+ 1. 获取企业 Profile lock,以固定 `browser_data` 和指纹启动可见持久化浏览器。
22
+ 2. 打开登录页,选择“其他方式”,点击抖音图标进入 OAuth 扫码页。
23
+ 3. 向用户发送清晰的最新二维码,保持原 browser/context/page 和 lock,等待用户用抖音 App 扫码并授权。
24
+ 4. 等待 OAuth 自动回调到 Leads 后台。可关闭新手教程、服务说明或体验调查,但不要修改业务配置。
25
+ 5. 结合当前域名、可见“运营工作台”“数据分析”“线索管理”“昨日数据概览”、账号名,以及登录表单和二维码消失判断结果。
26
+
27
+ URL 仍为 `/pc/auth/login` 但后台 DOM 已完整出现时,不得仅凭 URL 判定失效。后台与登录证据冲突时返回 `indeterminate`。
28
+
29
+ ## 固化
30
+
31
+ 1. 确认 `logged_in` 后正常关闭,使状态写入 `browser_data`,再释放 lock。
32
+ 2. 用完全相同的 Profile、指纹和启动参数重开 Leads。
33
+ 3. 确认无需扫码进入后台,再次正常关闭并释放 lock。
34
+ 4. 返回 `persistence_verified=true`、非敏感后台证据、浏览器退出和 lock 状态。
35
+
36
+ 不得输出 Cookie、token、二维码内容或账号凭据;不得用 `kill`、`pkill` 或删除 `browser_data` 排障。
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "抖音企业号线索版登录"
3
+ short_description: "通过抖音 OAuth 扫码登录企业号线索版后台并验证持久化状态"
4
+ default_prompt: "Use $douyin-enterprise-leads-login to sign in to the Douyin enterprise Leads dashboard."
@@ -0,0 +1,29 @@
1
+ ---
2
+ name: douyin-enterprise-short-video-export
3
+ description: 从抖音企业号线索版后台导出自有短视频明细。用于指定日期或默认前一天的数据分析视频列表导出、真实下载等待、XLSX 文件完整性检查、零数据交付和附件发送确认。
4
+ ---
5
+
6
+ # 企业号短视频明细导出
7
+
8
+ 目标页:`https://leads.cluerich.com/pc/analysis/short-video/list`。
9
+
10
+ ```bash
11
+ media-agent export-short-video <profile_id> [--date YYYY-MM-DD]
12
+ ```
13
+
14
+ ## 流程
15
+
16
+ 1. 确认 Profile 有 `leads_export` capability,并回显目标账号和具体日期;未指定时使用前一天。
17
+ 2. 获取 lock,执行真实 `check-login --site leads`;未登录返回 `LOGIN_REQUIRED`,不要在导出任务内扫码。
18
+ 3. 打开“数据分析 → 短视频 → 视频列表”,关闭遮挡说明弹窗。
19
+ 4. 选择统计日期和“当前账户”,除非用户明确要求子账号。
20
+ 5. 滚动到“短视频明细”,点击一次“导出数据”。
21
+ 6. 使用浏览器 download 事件等待真实下载完成,不能只凭点击或 toast 报告成功。
22
+ 7. 校验文件存在、大小大于 0、扩展名和实际格式为 XLSX、工作表可读,并统计数据行数。
23
+ 8. 保留平台原始文件,不改写业务内容。即使 0 行也交付原始表头文件并明确说明。
24
+ 9. 将真实附件发送给用户并确认投递成功;本地路径不等于交付。
25
+ 10. 正常关闭浏览器并释放 lock。
26
+
27
+ ## 返回
28
+
29
+ 返回 `profile_id`、日期范围、`file_name`、`file_size`、`sheet_names`、`data_rows`、下载状态、附件投递状态、浏览器关闭和 lock 释放状态。不得把榜单抓取结果冒充平台原始导出。
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "企业号短视频明细导出"
3
+ short_description: "从抖音企业号线索版导出指定日期的自有短视频原始明细文件"
4
+ default_prompt: "Use $douyin-enterprise-short-video-export to export a dated short-video detail workbook."