@optima-chat/optima-agent 0.8.94 → 0.8.95
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.
- package/.claude/skills/ads/SKILL.md +220 -261
- package/.claude/skills/ads/template/campaign/CREATIVES.md +18 -0
- package/.claude/skills/ads/template/campaign/NOTES.md +10 -0
- package/.claude/skills/ads/template/campaign/STRATEGY.md +29 -0
- package/.claude/skills/ads/template/user/ADS.md +29 -0
- package/.claude/skills/ads/template/user/LEARNINGS.md +15 -0
- package/.claude/skills/ads/template/user/PROGRESS.md +20 -0
- package/.claude/skills/ads/template/user/README.md +25 -0
- package/.claude/skills/ads/template/user/REPORTS/.gitkeep +0 -0
- package/.claude/skills/ads/template/user/assets/.gitignore +2 -0
- package/.claude/skills/ads/template/user/campaigns/.gitkeep +0 -0
- package/.claude/skills/browser/SKILL.md +72 -307
- package/.claude/skills/i18n/SKILL.md +31 -1
- package/.claude/skills/shop-content/SKILL.md +101 -0
- package/package.json +1 -1
|
@@ -1,285 +1,244 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ads
|
|
3
|
-
description:
|
|
3
|
+
description: |
|
|
4
|
+
Managed multi-channel ads. Only load when user explicitly asks to run paid ads
|
|
5
|
+
(e.g. "帮我投广告", "launch a campaign", "推广这款商品", "加广告预算", "查看广告效果",
|
|
6
|
+
"ads launch", "优化广告", "生成广告报告"). Do NOT load for general marketing
|
|
7
|
+
questions or organic growth — those go to the `growth` skill.
|
|
4
8
|
---
|
|
5
9
|
|
|
6
|
-
#
|
|
10
|
+
# Ads 托管广告投放
|
|
7
11
|
|
|
8
|
-
|
|
12
|
+
AI 广告官:通过 `~/ads/` 工作目录持续运营用户的付费广告投放。
|
|
9
13
|
|
|
10
|
-
##
|
|
14
|
+
## 核心:`~/ads/` 工作目录
|
|
11
15
|
|
|
12
|
-
|
|
13
|
-
# 检查用户是否已授权 Google Ads 账号
|
|
14
|
-
google-ads account check
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
**返回状态及处理**:
|
|
18
|
-
| 状态 | 含义 | 处理方式 |
|
|
19
|
-
|------|------|----------|
|
|
20
|
-
| `active` | 已连接,可访问 | 继续操作 |
|
|
21
|
-
| `pending` | 邀请已发送,等待接受 | 告知用户去 Google Ads 后台接受邀请 |
|
|
22
|
-
| `refused` | 用户拒绝了邀请 | 输出:`[重新关联 Google Ads 账号](action://link-google-ads-account)` |
|
|
23
|
-
| `canceled` | 邀请已取消 | 输出:`[关联 Google Ads 账号](action://link-google-ads-account)` |
|
|
24
|
-
| `not_linked` | 未关联 | 输出:`[关联 Google Ads 账号](action://link-google-ads-account)` |
|
|
25
|
-
|
|
26
|
-
## 典型场景
|
|
27
|
-
|
|
28
|
-
### 场景1:从零开始投放广告
|
|
29
|
-
|
|
30
|
-
**用户说**:"我想投放 Google 广告推广我的产品"
|
|
31
|
-
|
|
32
|
-
**流程**: 创建广告系列 → 创建广告组 → 添加关键词 → 创建广告 → 启用
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
# 1. 创建广告系列(每日预算 $50,默认 PAUSED)
|
|
36
|
-
google-ads campaign create -n "产品推广" -b 50
|
|
37
|
-
|
|
38
|
-
# 2. 创建广告组(CPC 出价 $2)
|
|
39
|
-
google-ads ad-group create --campaign-id <campaign-id> -n "核心关键词组" --cpc-bid 2
|
|
40
|
-
|
|
41
|
-
# 3. 添加关键词
|
|
42
|
-
google-ads keyword add --ad-group-id <ad-group-id> -k "产品名称,品牌词,行业词"
|
|
43
|
-
|
|
44
|
-
# 4. 创建广告
|
|
45
|
-
google-ads ad create \
|
|
46
|
-
--ad-group-id <ad-group-id> \
|
|
47
|
-
--headlines "优质产品,限时优惠,免费配送" \
|
|
48
|
-
--descriptions "高品质产品限时优惠中,立即下单享受专属折扣" \
|
|
49
|
-
--final-url "https://shop.example.com"
|
|
50
|
-
|
|
51
|
-
# 5. 确认无误后启用
|
|
52
|
-
google-ads campaign update --campaign-id <campaign-id> --status ENABLED
|
|
53
|
-
```
|
|
16
|
+
所有操作基于用户 workspace 的 `~/ads/`,两层结构:
|
|
54
17
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
**用户说**:"看看我的广告效果怎么样"
|
|
58
|
-
|
|
59
|
-
```bash
|
|
60
|
-
# 快速查看所有广告系列状态
|
|
61
|
-
google-ads campaign list
|
|
62
|
-
|
|
63
|
-
# 查看详细效果数据(GAQL 查询)
|
|
64
|
-
google-ads query -q "
|
|
65
|
-
SELECT
|
|
66
|
-
campaign.name,
|
|
67
|
-
metrics.impressions,
|
|
68
|
-
metrics.clicks,
|
|
69
|
-
metrics.ctr,
|
|
70
|
-
metrics.average_cpc,
|
|
71
|
-
metrics.cost_micros,
|
|
72
|
-
metrics.conversions
|
|
73
|
-
FROM campaign
|
|
74
|
-
WHERE segments.date DURING LAST_7_DAYS
|
|
75
|
-
ORDER BY metrics.cost_micros DESC
|
|
76
|
-
"
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
### 场景3:暂停/启用广告
|
|
80
|
-
|
|
81
|
-
**用户说**:"暂停那个效果不好的广告系列"
|
|
18
|
+
- **用户级根目录**: 跨 campaign 的整体策略和经验
|
|
19
|
+
- **`campaigns/<slug>/` 子目录**: 每个 campaign 的专属文件
|
|
82
20
|
|
|
83
|
-
```bash
|
|
84
|
-
# 先查看列表确认 ID
|
|
85
|
-
google-ads campaign list
|
|
86
|
-
|
|
87
|
-
# 暂停广告系列
|
|
88
|
-
google-ads campaign update --campaign-id <id> --status PAUSED
|
|
89
|
-
|
|
90
|
-
# 重新启用
|
|
91
|
-
google-ads campaign update --campaign-id <id> --status ENABLED
|
|
92
21
|
```
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
22
|
+
~/ads/
|
|
23
|
+
├── ADS.md 用户级整体策略
|
|
24
|
+
├── LEARNINGS.md 跨 campaign 经验沉淀
|
|
25
|
+
├── PROGRESS.md 全局工作日志 (每段标 campaign tag)
|
|
26
|
+
├── REPORTS/ 用户级周报/月报
|
|
27
|
+
├── assets/ 跨 campaign 共享素材 (.gitignore)
|
|
28
|
+
├── campaigns/
|
|
29
|
+
│ └── <slug>/
|
|
30
|
+
│ ├── STRATEGY.md campaign 专属策略
|
|
31
|
+
│ ├── CREATIVES.md campaign 变体表
|
|
32
|
+
│ └── NOTES.md campaign 运行观察
|
|
33
|
+
└── .git/
|
|
104
34
|
```
|
|
105
35
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
36
|
+
## 启动 SOP(每次会话)
|
|
37
|
+
|
|
38
|
+
1. `ls ~/ads/ADS.md` — 不存在 → 进入"初始化流程"(见下方)
|
|
39
|
+
2. `cat ~/ads/PROGRESS.md | head -30` — 上次做了什么、异常、下次待办
|
|
40
|
+
3. `git -C ~/ads log --oneline -5` — 最近变更
|
|
41
|
+
4. `ls ~/ads/campaigns/` — 列出本地登记的 campaign
|
|
42
|
+
5. `ads status --json` — 从后端拉事实: 在跑的 campaign 列表 + 7 天花费 + 钱包 + 月度 cap
|
|
43
|
+
- 如果钱包余额 < 阈值,第一时间告诉用户
|
|
44
|
+
- 如果月度 cap 使用率 > 80%,同样提示
|
|
45
|
+
- 如果后端 campaign 和本地目录对不齐,视为需要修复
|
|
46
|
+
6. → 决定本次要做的**一个**动作
|
|
47
|
+
- 聚焦单 campaign 的 session 优先 `cat ~/ads/campaigns/<name>/*.md` 载入专属上下文
|
|
48
|
+
|
|
49
|
+
## 初始化流程(第一次会话)
|
|
50
|
+
|
|
51
|
+
1. Copy the template from this skill's directory: `cp -r $(dirname "$SKILL_PATH")/template/user/ ~/ads/`
|
|
52
|
+
(The template directory is at the same path as this SKILL.md file, under `template/user/`.)
|
|
53
|
+
2. `cd ~/ads && git init && git add -A && git commit -m "init workspace"`
|
|
54
|
+
3. **对话式引导填 ADS.md**(一次问一个,不要塞 10 个表单):
|
|
55
|
+
- "我们要推广什么?" → `commerce-cli product list` 列候选商品
|
|
56
|
+
- "默认目标受众是谁?(地域 / 年龄 / 设备 / 时段)"
|
|
57
|
+
- "月度总预算上限多少美元?"
|
|
58
|
+
- "有什么品牌禁忌或必须避开的词吗?"
|
|
59
|
+
每问完一段就写进 ADS.md,`git commit -m "fill ADS.md: <段落>"`
|
|
60
|
+
4. `ads init --total-monthly-budget <X>` — 后端创建 user_ads 记录 + 确保 Google Ads label 存在 + 查 USD wallet
|
|
61
|
+
5. 把后端返回的 ID 自动填进 ADS.md 的"后端登记"段,`git commit -m "register backend"`
|
|
62
|
+
6. 提示用户:
|
|
63
|
+
- 钱包余额为 0 → "需要先充值. 说 'topup 100' 可充 $100"
|
|
64
|
+
- 有余额 → "可以现在 launch 第一个 campaign,或者下次会话再开始"
|
|
116
65
|
|
|
117
|
-
|
|
118
|
-
|
|
66
|
+
**不会自动 launch 任何 campaign.** 第一次 launch 必须由用户明确要求。
|
|
67
|
+
|
|
68
|
+
## 单会话单任务
|
|
69
|
+
|
|
70
|
+
每次会话只执行一种动作(launch / optimize / collect / report / budget / pause / diagnose / creative 的其中一个),完成后 commit 并更新 `PROGRESS.md`。出错时可以精准 `git revert`。
|
|
71
|
+
|
|
72
|
+
**例外**: `collect` 在每个其它动作开头隐式跑(让 LLM 基于新鲜数据推理),不算独立 session 动作。
|
|
73
|
+
|
|
74
|
+
## 8 个动作
|
|
75
|
+
|
|
76
|
+
### 1. launch — 启动新 campaign
|
|
119
77
|
|
|
120
|
-
|
|
121
|
-
|
|
78
|
+
**触发**: 用户说"推广 XX"、或 PROGRESS 里标记了下次 launch。
|
|
79
|
+
|
|
80
|
+
**流程**:
|
|
81
|
+
1. 读 ADS.md 拿整体策略,确认推什么产品、受众、预算
|
|
82
|
+
2. 调 `gen image` 生成多个素材变体到 `~/ads/assets/`
|
|
83
|
+
3. 构造 CampaignSpec JSON(参考下方"CampaignSpec 结构"),写到 `/tmp/spec.json`
|
|
84
|
+
4. `ads launch --spec /tmp/spec.json --reason "..."` — 默认 PAUSED
|
|
85
|
+
5. **必做**: 创建 `~/ads/campaigns/<slug>/` 子目录:
|
|
86
|
+
```bash
|
|
87
|
+
slug=<campaign-slug>
|
|
88
|
+
mkdir -p ~/ads/campaigns/$slug
|
|
89
|
+
cp -r $(dirname "$SKILL_PATH")/template/campaign/. ~/ads/campaigns/$slug/
|
|
90
|
+
```
|
|
91
|
+
6. 填 `campaigns/<slug>/STRATEGY.md`(从 spec.json 拷贝产品、受众、关键词、日预算、差异化角度,加后端关联 ID)
|
|
92
|
+
7. 填 `campaigns/<slug>/CREATIVES.md`(5 个变体的表格,CTR/CVR 留空)
|
|
93
|
+
8. 检查 compliance_check 通过后 → `ads launch enable <id> --reason "compliance passed"`
|
|
94
|
+
9. 追加到 `PROGRESS.md`(tag: `launch, campaign=<slug>`)
|
|
95
|
+
10. `git -C ~/ads add -A && git -C ~/ads commit -m "launch: <slug>"`
|
|
96
|
+
|
|
97
|
+
### 2. optimize — 优化一个 campaign
|
|
98
|
+
|
|
99
|
+
**触发**: sentinel 定时或用户说"优化一下"。
|
|
100
|
+
|
|
101
|
+
**流程**:
|
|
102
|
+
1. `ads collect` 先拉最新数据(SOP 前置)
|
|
103
|
+
2. 读 `~/ads/campaigns/<slug>/CREATIVES.md` 看变体表现
|
|
104
|
+
3. 读 `~/ads/LEARNINGS.md` 看历史经验
|
|
105
|
+
4. 决定要改什么(一个或多个):
|
|
106
|
+
- 淘汰低 CTR 素材: `ads optimize pause-creative <id> --reason "..."`
|
|
107
|
+
- 加新关键词: `ads optimize add-keywords <ad_group_id> --keywords "..." --reason "..."`
|
|
108
|
+
- 加否定词: `ads optimize add-negatives <ad_group_id> --keywords "..." --reason "..."`
|
|
109
|
+
- 调出价修正: `ads optimize change-bid-mod <criterion_id> --modifier 1.2 --reason "..."`
|
|
110
|
+
- 调预算: `ads budget set --campaign <id> --daily <usd> --reason "..."`
|
|
111
|
+
5. 更新 `campaigns/<slug>/CREATIVES.md`(把被淘汰的变体移到"已淘汰"段)
|
|
112
|
+
6. 追加一段到 `campaigns/<slug>/NOTES.md`(观察 + 推理 + 下次验证点)
|
|
113
|
+
7. 如果这个洞察是可泛化的,也追加到 `~/ads/LEARNINGS.md`
|
|
114
|
+
8. 追加到 `PROGRESS.md`
|
|
115
|
+
9. commit
|
|
116
|
+
|
|
117
|
+
### 3. collect — 拉最新数据
|
|
118
|
+
|
|
119
|
+
**触发**: 定时(每天)或作为其它动作的前置。
|
|
120
|
+
|
|
121
|
+
**流程**:
|
|
122
|
+
1. `ads collect --days 7` → 后端从 Google Ads 拉 per-campaign 和 per-creative 的最新数据,返回 JSON
|
|
123
|
+
2. 对返回的每个 `creative_perf` 项,找到对应 `campaigns/<slug>/CREATIVES.md`(通过 `campaign_id` 匹配——每个 `campaigns/<slug>/STRATEGY.md` 的"后端关联"段记录了 `campaign_id`),用新 CTR/CVR/花费重写"在投变体"表
|
|
124
|
+
3. 如果是纯 collect session(不是被其它动作调用),追加一段到 PROGRESS.md 和 commit。
|
|
125
|
+
如果是嵌入在其它动作里,则跟那个动作的 commit 合并。
|
|
126
|
+
|
|
127
|
+
### 4. report — 生成周/月报告
|
|
128
|
+
|
|
129
|
+
**触发**: sentinel 定时或用户问"最近怎么样"。
|
|
130
|
+
|
|
131
|
+
**流程**:
|
|
132
|
+
1. `ads report --period week`(或 `--period month`)→ 后端返回结构化数据
|
|
133
|
+
2. LLM 结合 `LEARNINGS.md` 和 `ADS.md` 的业务目标,组合出人话 markdown 报告
|
|
134
|
+
3. 写到 `~/ads/REPORTS/2026-W14.md`(周报)或 `~/ads/REPORTS/2026-04.md`(月报)
|
|
135
|
+
4. PROGRESS.md tag 一段 "generated report"
|
|
136
|
+
5. commit
|
|
137
|
+
|
|
138
|
+
### 5. budget — 调预算 / 钱包
|
|
139
|
+
|
|
140
|
+
**触发**: 用户说"加预算"、"充钱"。
|
|
141
|
+
|
|
142
|
+
**场景**:
|
|
143
|
+
- "加到 $20/天" → `ads budget set --campaign <id> --daily 20 --reason "..."`
|
|
144
|
+
- "月度上限改 $500" → `ads budget set --total-monthly 500 --reason "..."`
|
|
145
|
+
- "充 $100" → `ads budget topup 100` → 把返回的 `checkout_url` 作为 markdown 链接输出给用户
|
|
146
|
+
- "看下预算" → `ads budget show`
|
|
147
|
+
|
|
148
|
+
改完之后相应更新 `ADS.md`(月度 cap 变化)或 `campaigns/<slug>/STRATEGY.md`(campaign 日预算变化),commit。
|
|
149
|
+
|
|
150
|
+
### 6. pause — 紧急停投
|
|
151
|
+
|
|
152
|
+
**触发**: 用户说"停掉"、"全停"。
|
|
153
|
+
|
|
154
|
+
**流程**:
|
|
155
|
+
- "停掉 XX campaign" → `ads pause campaign <id> --reason "..."`
|
|
156
|
+
- "全停" → `ads pause all --reason "..."`
|
|
157
|
+
- "停某个素材" → `ads pause creative <variant_id> --reason "..."`
|
|
158
|
+
- "恢复" → `ads resume ...`(但钱包低余额或月度 cap 超出时会被后端拒)
|
|
159
|
+
|
|
160
|
+
停掉之后在对应 `campaigns/<slug>/NOTES.md` 记一笔,commit。
|
|
161
|
+
|
|
162
|
+
### 7. diagnose — 问题排查
|
|
163
|
+
|
|
164
|
+
**触发**: 用户说"为啥没展示"、"怎么烧钱没单"。
|
|
165
|
+
|
|
166
|
+
**流程**:
|
|
167
|
+
1. `ads diagnose --scope all`(或 `--campaign <id>` 聚焦某个)
|
|
168
|
+
2. 后端返回 issues 列表,每个带 `cli_hint`
|
|
169
|
+
3. LLM 把问题翻译成人话解释给用户,并建议下一步
|
|
170
|
+
4. 如果用户同意某个建议,执行对应的 `cli_hint`(这变成一个新的 optimize / pause / budget session,原则上 diagnose session 本身不改任何东西)
|
|
171
|
+
5. 更新 `campaigns/<slug>/NOTES.md` 或 `PROGRESS.md`(记录诊断发现和建议,不改其它状态文件)
|
|
172
|
+
6. commit(仅包含文档更新)
|
|
173
|
+
|
|
174
|
+
### 8. creative — 素材迭代
|
|
175
|
+
|
|
176
|
+
**触发**: 独立会话,聚焦素材质量。
|
|
177
|
+
|
|
178
|
+
**流程**:
|
|
179
|
+
1. `ads status --include-creatives` 看现状
|
|
180
|
+
2. 读 `~/ads/campaigns/<slug>/CREATIVES.md` 和 `~/ads/LEARNINGS.md`
|
|
181
|
+
3. 决定要生成什么新变体(几个 prompt、什么风格)
|
|
182
|
+
4. `gen image "<prompt>" -o ~/ads/assets` 多次调用
|
|
183
|
+
5. 写进对应 `campaigns/<slug>/CREATIVES.md`
|
|
184
|
+
6. 如果要把新变体上线到现有 campaign: `ads optimize replace-creative <campaign_id> --new-spec /tmp/v.json --reason "..."`
|
|
185
|
+
7. 如果只是建素材库待用,不上线,也 OK
|
|
186
|
+
8. commit
|
|
187
|
+
|
|
188
|
+
## CampaignSpec 结构(构造 spec.json 用)
|
|
189
|
+
|
|
190
|
+
```json
|
|
191
|
+
{
|
|
192
|
+
"userId": "<CLI 自动从 ~/.optima/token.json 的 JWT 提取, 不需要手动填>",
|
|
193
|
+
"name": "<slug-name-without-u-prefix>",
|
|
194
|
+
"objective": "conversions",
|
|
195
|
+
"productIds": ["12345"],
|
|
196
|
+
"audience": {
|
|
197
|
+
"geos": ["US", "CA"],
|
|
198
|
+
"ageRanges": ["AGE_RANGE_25_34", "AGE_RANGE_35_44"],
|
|
199
|
+
"genders": ["FEMALE"],
|
|
200
|
+
"devices": ["MOBILE", "DESKTOP"],
|
|
201
|
+
"intentSignals": ["夏季连衣裙", "summer dress"],
|
|
202
|
+
"excludeSignals": ["免费", "free"]
|
|
203
|
+
},
|
|
204
|
+
"budget": { "dailyLimitUsd": 10 },
|
|
205
|
+
"creatives": [
|
|
206
|
+
{
|
|
207
|
+
"variantId": "v_abc123",
|
|
208
|
+
"headlines": ["标题1 最多 30 字", "标题2", "标题3", "标题4", "标题5"],
|
|
209
|
+
"descriptions": ["描述1 最多 90 字", "描述2"],
|
|
210
|
+
"imageAssets": ["/home/user/ads/assets/image_abc.png"],
|
|
211
|
+
"finalUrl": "https://shop.example.com/p/12345"
|
|
212
|
+
}
|
|
213
|
+
]
|
|
214
|
+
}
|
|
122
215
|
```
|
|
123
216
|
|
|
124
|
-
|
|
217
|
+
**Google Ads RSA 要求**: 至少 3 个 headlines(各 ≤30 字符),至少 2 个 descriptions(各 ≤90 字符)。后端会强制校验,违规会 fail compliance 预审。
|
|
125
218
|
|
|
126
|
-
|
|
219
|
+
## 提交约定
|
|
127
220
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
221
|
+
- 每次会话结束必有**一个** commit
|
|
222
|
+
- message: `<action>: <一句话>` 例: `launch: summer-promo`、`optimize: drop low-CTR creative`、`budget: topup $100`
|
|
223
|
+
- PROGRESS.md 更新和动作产物**合并在同一个 commit**
|
|
224
|
+
- 失败时,只更新 PROGRESS.md 记失败原因(其它状态文件不动)
|
|
225
|
+
- `~/ads/.git/` 是本地 only,不推远程
|
|
131
226
|
|
|
132
|
-
|
|
133
|
-
google-ads campaign targeting add --campaign-id <id> --type location --geo-target 2840
|
|
227
|
+
## 归档
|
|
134
228
|
|
|
135
|
-
|
|
136
|
-
google-ads campaign targeting add --campaign-id <id> --type device --device MOBILE --bid-modifier 1.2
|
|
229
|
+
某 campaign 被删除或生命周期结束时:`mv ~/ads/campaigns/<slug> ~/ads/archive/<slug>`,不要直接删(保留历史给 LEARNINGS 参考)。`ls ~/ads/campaigns/` 永远只反映当前活跃/暂停的 campaign。
|
|
137
230
|
|
|
138
|
-
|
|
139
|
-
google-ads campaign targeting add --campaign-id <id> --type schedule --day MONDAY --start-hour 9 --end-hour 18
|
|
231
|
+
## Skill 之间的协作
|
|
140
232
|
|
|
141
|
-
|
|
142
|
-
|
|
233
|
+
按需加载其它 skill:
|
|
234
|
+
- **`gen`** — image/video/tts 生成
|
|
235
|
+
- **`scout`** / **`shein`** / **`tiktok`** 等 — 竞品研究、关键词发现(在 launch 或 optimize 的策略阶段)
|
|
236
|
+
- **`sentinel`** — 定时调度 collect / optimize / report
|
|
237
|
+
- **`browser`** — API 不支持时的兜底
|
|
143
238
|
|
|
144
|
-
|
|
145
|
-
google-ads campaign targeting remove --campaign-id <id> --criterion-id <criterion-id>
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
**注意**:人口统计定向(年龄、性别)在 Campaign 级别只能排除,正向定向需在 Ad-Group 级别设置。
|
|
149
|
-
|
|
150
|
-
## 场景决策表
|
|
151
|
-
|
|
152
|
-
| 用户需求 | 推荐命令 | 关键注意点 |
|
|
153
|
-
|---------|---------|-----------|
|
|
154
|
-
| 新建广告投放 | 完整流程(场景1) | 按顺序:系列→组→关键词→广告 |
|
|
155
|
-
| 查看效果 | `campaign list` 或 GAQL | GAQL 获取详细指标 |
|
|
156
|
-
| 暂停/启用 | `campaign update --status` | PAUSED 或 ENABLED |
|
|
157
|
-
| 调整预算 | `campaign update --budget` | 单位美元 |
|
|
158
|
-
| 调整出价 | `ad-group update --cpc-bid` | 单位美元 |
|
|
159
|
-
| 添加关键词 | `keyword add` | 注意匹配类型 |
|
|
160
|
-
| 地理定向 | `campaign targeting add --type location` | geo-target ID |
|
|
161
|
-
| 人群定向 | `ad-group targeting add` | Campaign 级别只能排除 |
|
|
162
|
-
| 删除广告 | `campaign delete` / `ad delete` | 不可恢复,建议先暂停 |
|
|
163
|
-
|
|
164
|
-
## 自然语言映射
|
|
165
|
-
|
|
166
|
-
当用户说:
|
|
167
|
-
- "投放广告" / "创建广告" → 引导完整流程(场景1)
|
|
168
|
-
- "广告效果" / "看看数据" → `campaign list` + GAQL
|
|
169
|
-
- "暂停广告" → `campaign update --status PAUSED`
|
|
170
|
-
- "启用广告" → `campaign update --status ENABLED`
|
|
171
|
-
- "调整预算到 XX" → `campaign update --budget XX`
|
|
172
|
-
- "添加关键词 XX" → `keyword add -k "XX"`
|
|
173
|
-
- "只投放美国/中国" → `campaign targeting add --type location`
|
|
174
|
-
- "针对年轻人/男性" → `ad-group targeting add --type age_range/gender`
|
|
175
|
-
- "移动端出价加 20%" → `campaign targeting add --type device --bid-modifier 1.2`
|
|
176
|
-
- "删除广告" → 先确认,再执行删除
|
|
177
|
-
|
|
178
|
-
## 关键概念
|
|
179
|
-
|
|
180
|
-
### 广告层级结构
|
|
181
|
-
|
|
182
|
-
```
|
|
183
|
-
Account(账号)
|
|
184
|
-
└── Campaign(广告系列)- 设置预算
|
|
185
|
-
└── Ad Group(广告组)- 设置出价
|
|
186
|
-
├── Keywords(关键词)- 触发条件
|
|
187
|
-
└── Ads(广告)- 展示内容
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
### 状态说明
|
|
191
|
-
|
|
192
|
-
| 状态 | 含义 |
|
|
193
|
-
|------|------|
|
|
194
|
-
| `ENABLED` | 正常投放中 |
|
|
195
|
-
| `PAUSED` | 已暂停 |
|
|
196
|
-
| `REMOVED` | 已删除 |
|
|
197
|
-
|
|
198
|
-
### 关键词匹配类型
|
|
199
|
-
|
|
200
|
-
| 类型 | 说明 |
|
|
201
|
-
|------|------|
|
|
202
|
-
| `BROAD` | 广泛匹配(默认) |
|
|
203
|
-
| `PHRASE` | 词组匹配 |
|
|
204
|
-
| `EXACT` | 精确匹配 |
|
|
205
|
-
|
|
206
|
-
### RSA 广告要求
|
|
207
|
-
|
|
208
|
-
- **标题**: 至少 3 个,最多 15 个(每个 ≤30 字符)
|
|
209
|
-
- **描述**: 至少 2 个,最多 4 个(每个 ≤90 字符)
|
|
210
|
-
|
|
211
|
-
## 常见问题
|
|
212
|
-
|
|
213
|
-
### 广告创建后没有展示
|
|
214
|
-
|
|
215
|
-
1. 检查状态是否 PAUSED → 启用它
|
|
216
|
-
2. 账号是否设置账单信息 → 去 Google Ads 后台设置
|
|
217
|
-
3. 关键词是否有搜索量 → 添加更多关键词
|
|
218
|
-
|
|
219
|
-
### 不知道广告效果好不好
|
|
220
|
-
|
|
221
|
-
用 GAQL 查询关键指标:
|
|
222
|
-
```bash
|
|
223
|
-
google-ads query -q "
|
|
224
|
-
SELECT campaign.name, metrics.impressions, metrics.clicks, metrics.ctr, metrics.conversions, metrics.cost_micros
|
|
225
|
-
FROM campaign WHERE segments.date DURING LAST_7_DAYS
|
|
226
|
-
"
|
|
227
|
-
```
|
|
239
|
+
## 依赖的 CLI
|
|
228
240
|
|
|
229
|
-
|
|
230
|
-
-
|
|
231
|
-
-
|
|
232
|
-
|
|
233
|
-
### 关键词出价设多少
|
|
234
|
-
|
|
235
|
-
- 新广告先设 $1-2,观察效果
|
|
236
|
-
- 效果好提高出价,效果差降低或暂停
|
|
237
|
-
|
|
238
|
-
## 命令参考
|
|
239
|
-
|
|
240
|
-
### 账号
|
|
241
|
-
- `google-ads account check` - 检查 Google Ads 账号授权状态
|
|
242
|
-
|
|
243
|
-
### 广告系列
|
|
244
|
-
- `google-ads campaign list [--status ENABLED|PAUSED]` - 列出
|
|
245
|
-
- `google-ads campaign info <id>` - 详情
|
|
246
|
-
- `google-ads campaign create -n "名称" -b 预算` - 创建
|
|
247
|
-
- `google-ads campaign update --campaign-id <id> [--status|--budget|--name]` - 更新
|
|
248
|
-
- `google-ads campaign delete --campaign-id <id>` - 删除
|
|
249
|
-
- `google-ads campaign targeting list --campaign-id <id>` - 列出定向条件
|
|
250
|
-
- `google-ads campaign targeting add --campaign-id <id> --type <type> [options]` - 添加定向
|
|
251
|
-
- `google-ads campaign targeting remove --campaign-id <id> --criterion-id <id>` - 删除定向
|
|
252
|
-
|
|
253
|
-
### 广告组
|
|
254
|
-
- `google-ads ad-group list [--campaign-id <id>]` - 列出
|
|
255
|
-
- `google-ads ad-group info <id>` - 详情
|
|
256
|
-
- `google-ads ad-group create --campaign-id <id> -n "名称" [--cpc-bid 出价]` - 创建
|
|
257
|
-
- `google-ads ad-group update --ad-group-id <id> [--status|--cpc-bid|--name]` - 更新
|
|
258
|
-
- `google-ads ad-group delete --ad-group-id <id>` - 删除
|
|
259
|
-
- `google-ads ad-group targeting list --ad-group-id <id>` - 列出定向条件
|
|
260
|
-
- `google-ads ad-group targeting add --ad-group-id <id> --type <type> [options]` - 添加定向
|
|
261
|
-
- `google-ads ad-group targeting remove --ad-group-id <id> --criterion-id <id>` - 删除定向
|
|
262
|
-
|
|
263
|
-
### 关键词
|
|
264
|
-
- `google-ads keyword list [--campaign-id <id>]` - 列出
|
|
265
|
-
- `google-ads keyword add --ad-group-id <id> -k "词1,词2" [--match-type BROAD|PHRASE|EXACT]` - 添加
|
|
266
|
-
- `google-ads keyword update --ad-group-id <id> --criterion-id <id> --status` - 更新
|
|
267
|
-
- `google-ads keyword delete --ad-group-id <id> --criterion-id <id>` - 删除
|
|
268
|
-
|
|
269
|
-
### 广告
|
|
270
|
-
- `google-ads ad list [--ad-group-id <id>]` - 列出
|
|
271
|
-
- `google-ads ad info <id>` - 详情
|
|
272
|
-
- `google-ads ad create --ad-group-id <id> --headlines "..." --descriptions "..." --final-url "..."` - 创建
|
|
273
|
-
- `google-ads ad update --ad-group-id <id> --ad-id <id> --status` - 更新
|
|
274
|
-
- `google-ads ad delete --ad-group-id <id> --ad-id <id>` - 删除
|
|
275
|
-
|
|
276
|
-
### GAQL 查询
|
|
277
|
-
- `google-ads query -q "SELECT ... FROM ..."` - 执行查询
|
|
278
|
-
- `google-ads query -f query.gaql` - 从文件读取
|
|
279
|
-
|
|
280
|
-
## 重要提示
|
|
281
|
-
|
|
282
|
-
- **所有命令默认 JSON 输出**
|
|
283
|
-
- **预算和出价单位**:美元
|
|
284
|
-
- **新广告默认 PAUSED**:创建后需手动启用
|
|
285
|
-
- **删除不可恢复**:建议先暂停
|
|
241
|
+
- `ads`(`@optima-chat/ads-cli`)— 本 skill 的核心后端入口
|
|
242
|
+
- `gen`(`@optima-chat/gen-cli`)— 素材生成
|
|
243
|
+
- `commerce-cli`(`@optima-chat/commerce-cli`)— 查商家商品
|
|
244
|
+
- `git`(系统)— workspace 版本管理
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Creatives: <name>
|
|
2
|
+
|
|
3
|
+
## 在投变体
|
|
4
|
+
| 变体ID | 类型 | 标题/描述 | CTR | CVR | 花费 | 状态 |
|
|
5
|
+
|---|---|---|---|---|---|---|
|
|
6
|
+
<!-- ads collect 后由 LLM 回填 CTR/CVR/花费 -->
|
|
7
|
+
|
|
8
|
+
## 已淘汰变体
|
|
9
|
+
<!-- optimize 淘汰的变体迁到这里, 保留作为反例 -->
|
|
10
|
+
|
|
11
|
+
## Prompt 记录
|
|
12
|
+
<!-- gen image 用过的 prompt, 方便复现和迭代
|
|
13
|
+
|
|
14
|
+
示例:
|
|
15
|
+
- v_abc (2026-04-11): "minimalist summer fashion banner, product 12345, 7折促销"
|
|
16
|
+
→ ~/ads/assets/image_abc.png
|
|
17
|
+
|
|
18
|
+
-->
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Notes: <name>
|
|
2
|
+
> 这个 campaign 的运行观察、临时发现、踩过的坑.
|
|
3
|
+
> 泛化到跨 campaign 的经验, 整理到 ~/ads/LEARNINGS.md.
|
|
4
|
+
|
|
5
|
+
<!-- 示例:
|
|
6
|
+
## 2026-04-15 14:30 (optimize session)
|
|
7
|
+
- 观察: 周末 CTR 比工作日高 40%, 但 CVR 低 20%, 推测周末逛店多但下单少
|
|
8
|
+
- 临时调整: 周六日 bid modifier -15%, 省钱给工作日
|
|
9
|
+
- 下次验证: 7 天后看 CPA 是否改善
|
|
10
|
+
-->
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Campaign: <name>
|
|
2
|
+
> 这个 campaign 的专属策略. 用户级整体策略见 ~/ads/ADS.md.
|
|
3
|
+
> 由 `ads launch` 之后 LLM 根据 ADS.md + 用户请求生成草稿, 后续可编辑.
|
|
4
|
+
|
|
5
|
+
## 目标
|
|
6
|
+
<!-- 这个 campaign 要达成什么? 例: "推新上的夏季系列裙装, 主打 25-35 女性" -->
|
|
7
|
+
|
|
8
|
+
## 推广产品
|
|
9
|
+
<!-- 具体 product_id 列表 -->
|
|
10
|
+
|
|
11
|
+
## 目标受众 (campaign-specific)
|
|
12
|
+
<!-- 相对 ADS.md 默认受众的调整. 没有调整就写 "same as ADS.md" -->
|
|
13
|
+
|
|
14
|
+
## 关键词意图 (Google Ads)
|
|
15
|
+
- 核心词:
|
|
16
|
+
- 长尾词:
|
|
17
|
+
- 否定词:
|
|
18
|
+
|
|
19
|
+
## 日预算
|
|
20
|
+
- 日预算: $___
|
|
21
|
+
- 持续时长: ___天 / 无限期
|
|
22
|
+
|
|
23
|
+
## 差异化角度
|
|
24
|
+
<!-- 这个 campaign 跟其它 campaign 的区别, 为什么单独开? -->
|
|
25
|
+
|
|
26
|
+
## 后端关联 (由 `ads launch` 自动填)
|
|
27
|
+
- campaign_id:
|
|
28
|
+
- platform_campaign_id:
|
|
29
|
+
- platform_budget_id:
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Ads 整体策略 (用户级)
|
|
2
|
+
> 修改后 git commit. 单个 campaign 的专属策略在 campaigns/<name>/STRATEGY.md.
|
|
3
|
+
|
|
4
|
+
## 业务目标
|
|
5
|
+
<!-- 例: 提升店铺月销量 / 打响品牌认知 / 某类目拓新 -->
|
|
6
|
+
|
|
7
|
+
## 候选产品
|
|
8
|
+
<!-- 从 commerce-backend 拉的候选, 或手填. 具体哪个 campaign 推哪个产品由每个 STRATEGY.md 定 -->
|
|
9
|
+
|
|
10
|
+
## 默认目标受众
|
|
11
|
+
<!-- 可被 campaign 级 STRATEGY.md 覆盖 -->
|
|
12
|
+
- 地域:
|
|
13
|
+
- 年龄段:
|
|
14
|
+
- 设备:
|
|
15
|
+
- 时段偏好:
|
|
16
|
+
|
|
17
|
+
## 月度总预算 (软性, 超出后所有 campaign 自动暂停到下月 1 日)
|
|
18
|
+
- 月度上限: $___
|
|
19
|
+
- 钱包余额低于 $___ 时自动暂停
|
|
20
|
+
|
|
21
|
+
## 渠道偏好
|
|
22
|
+
- [x] google_ads
|
|
23
|
+
|
|
24
|
+
## 品牌禁忌
|
|
25
|
+
<!-- 不能出现的词、不能投放的关键词、必须的免责声明 -->
|
|
26
|
+
|
|
27
|
+
## 后端登记 (由 `ads init` 自动填, 不要手动改)
|
|
28
|
+
- user_ad_account_id:
|
|
29
|
+
- google_label_id:
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# 优化经验沉淀
|
|
2
|
+
> 跨 campaign 的经验和洞察. 每次 optimize 之后, AI 把可泛化的发现追加到这里.
|
|
3
|
+
> 单 campaign 特有的观察不放这里, 放对应 campaigns/<name>/NOTES.md.
|
|
4
|
+
|
|
5
|
+
## 什么有效
|
|
6
|
+
<!-- 每条都用一两句话说清楚: "发现了什么" + "在哪次 optimize 时得到的" -->
|
|
7
|
+
|
|
8
|
+
## 什么无效
|
|
9
|
+
<!-- 同上 -->
|
|
10
|
+
|
|
11
|
+
## 受众洞察
|
|
12
|
+
<!-- 哪些人群、哪些地域转化高 -->
|
|
13
|
+
|
|
14
|
+
## 时段/季节规律
|
|
15
|
+
<!-- 一周/一天的高转化时段, 季节性趋势 -->
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# 工作日志
|
|
2
|
+
> 每次会话结束前, 在最上方追加一段. 最新的在顶部.
|
|
3
|
+
> 每段必须标注: 时间 + 动作 + 作用的 campaign (或 "all campaigns").
|
|
4
|
+
|
|
5
|
+
<!-- 示例:
|
|
6
|
+
|
|
7
|
+
## 2026-04-11 14:30 - launch (campaign: summer-promo)
|
|
8
|
+
- 基于 ADS.md 推了产品 12345 (夏季连衣裙)
|
|
9
|
+
- 生成 5 个素材变体 (minimalist / playful / elegant / beach / street)
|
|
10
|
+
- 合规预审通过, 上线
|
|
11
|
+
- 日预算 $10
|
|
12
|
+
- 异常: 无
|
|
13
|
+
- 下次待办: 7 天后 collect + optimize
|
|
14
|
+
|
|
15
|
+
## 2026-04-10 10:00 - (init)
|
|
16
|
+
- 初始化 workspace, 填 ADS.md
|
|
17
|
+
- 月度预算 $300, 品牌禁忌: 不能用 "最便宜" "全网最低" 这类绝对化词语
|
|
18
|
+
- 用户说下次会话再 launch
|
|
19
|
+
|
|
20
|
+
-->
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# ~/ads/ 工作目录
|
|
2
|
+
|
|
3
|
+
这是你的广告投放工作目录, 由 optima-agent 的 `ads` skill 维护.
|
|
4
|
+
|
|
5
|
+
## 结构
|
|
6
|
+
|
|
7
|
+
- `ADS.md` — 你的整体广告策略
|
|
8
|
+
- `LEARNINGS.md` — AI 沉淀的跨 campaign 经验
|
|
9
|
+
- `PROGRESS.md` — 每次 AI 会话的工作日志
|
|
10
|
+
- `REPORTS/` — 周报和月报
|
|
11
|
+
- `assets/` — AI 生成的广告素材 (不进 git)
|
|
12
|
+
- `campaigns/<name>/` — 每个 campaign 的专属文件
|
|
13
|
+
- `.git/` — 本地版本管理, 出错可回滚
|
|
14
|
+
|
|
15
|
+
## 使用方法
|
|
16
|
+
|
|
17
|
+
不要直接在这里修改文件. 在 optima.chat 聊天里告诉 AI 你想做什么, 它会替你管理这个目录.
|
|
18
|
+
|
|
19
|
+
如果你想亲自改 `ADS.md` 的策略(例如加新产品、改预算上限), 也可以. 改完后 AI 下次会话会读到新版本.
|
|
20
|
+
|
|
21
|
+
## 工作原则
|
|
22
|
+
|
|
23
|
+
- **单会话单任务**: 每次 AI 会话只做一件事 (launch / optimize / pause / report / ...), 完成后 commit
|
|
24
|
+
- **Git 是保险**: 所有变动都有 commit, 出错可以 `git revert`
|
|
25
|
+
- **事实在后端**: 这里只有策略和 AI 的思考轨迹. 真实的 campaign 状态、花费、余额在后端, 用 `ads status` 查
|
|
File without changes
|
|
File without changes
|
|
@@ -23,60 +23,75 @@ description: "Browser automation for web interactions. Use when user needs to op
|
|
|
23
23
|
|
|
24
24
|
1. `browser-cli scripts` — 查看已有脚本(显示名称、描述、步骤)
|
|
25
25
|
2. 如果有匹配的脚本 → 直接用 `browser-cli runscript <name> --param ...`
|
|
26
|
-
3. 如果没有 →
|
|
26
|
+
3. 如果没有 → 手动用 browser-cli 命令完成任务
|
|
27
27
|
|
|
28
28
|
脚本执行零 token 消耗,比手动操作快 10 倍以上。
|
|
29
29
|
|
|
30
30
|
## 命令
|
|
31
31
|
|
|
32
|
-
###
|
|
32
|
+
### 会话管理
|
|
33
33
|
|
|
34
34
|
```bash
|
|
35
|
-
# 会话管理
|
|
36
35
|
browser-cli launch [--url <url>] [--force] # 启动浏览器(--force 先关闭已有会话)
|
|
37
36
|
browser-cli close # 关闭浏览器并释放资源
|
|
38
37
|
browser-cli status # 查看当前会话状态
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### 导航
|
|
39
41
|
|
|
40
|
-
|
|
42
|
+
```bash
|
|
41
43
|
browser-cli navigate <url> # 跳转到 URL
|
|
42
44
|
browser-cli back # 后退
|
|
43
45
|
browser-cli refresh # 刷新页面
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### 交互
|
|
44
49
|
|
|
45
|
-
|
|
50
|
+
```bash
|
|
46
51
|
browser-cli click <index> # 按索引点击元素
|
|
47
52
|
browser-cli input <index> <text> [--no-clear] # 输入文本(--no-clear 追加而非替换)
|
|
48
53
|
browser-cli select <index> <option> # 选择下拉选项
|
|
49
54
|
browser-cli scroll <up|down> [--pages <n>] # 滚动页面(默认 1 页)
|
|
50
55
|
browser-cli keys <key> # 键盘操作(Enter、Tab 等)
|
|
51
|
-
browser-cli upload <index> <file...>
|
|
56
|
+
browser-cli upload <index> <file...> # 上传文件到 file input(路径自动转换)
|
|
57
|
+
```
|
|
52
58
|
|
|
53
|
-
|
|
59
|
+
### 页面检查
|
|
60
|
+
|
|
61
|
+
```bash
|
|
54
62
|
browser-cli dom # 获取当前 DOM 状态
|
|
55
63
|
browser-cli screenshot [file] # 截图(默认:/tmp/screenshot.png)
|
|
56
64
|
browser-cli search <pattern> # 搜索页面文本
|
|
57
65
|
browser-cli find <css_selector> # 通过 CSS 选择器查询
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### 标签页管理
|
|
58
69
|
|
|
59
|
-
|
|
70
|
+
```bash
|
|
60
71
|
browser-cli tabs # 列出所有标签页
|
|
61
72
|
browser-cli switch <tab_id> # 切换标签页
|
|
62
73
|
browser-cli close-tab <tab_id> # 关闭标签页
|
|
63
74
|
```
|
|
64
75
|
|
|
65
|
-
###
|
|
76
|
+
### 脚本
|
|
66
77
|
|
|
67
78
|
```bash
|
|
68
|
-
# 查看与管理
|
|
69
79
|
browser-cli scripts # 列出所有脚本(含描述和步骤)
|
|
70
80
|
browser-cli script-code <name> # 查看脚本源码
|
|
71
|
-
browser-cli delete-script <name> # 删除脚本
|
|
72
|
-
|
|
73
|
-
# 提交
|
|
74
|
-
browser-cli submit-script --name <name> --code-file <path> # 提交脚本(新建或覆盖)
|
|
75
|
-
|
|
76
|
-
# 执行
|
|
77
81
|
browser-cli runscript <name> --param key=value [...] # 执行脚本(自动轮询到完成)
|
|
78
82
|
browser-cli runscript <name> --param key=value --no-poll # 执行但不等待
|
|
79
83
|
browser-cli script-task <task-id> # 查询执行状态
|
|
84
|
+
browser-cli submit-script --name <name> --code-file <path> # 提交新脚本(新建或覆盖)
|
|
85
|
+
browser-cli delete-script <name> # 删除脚本
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Profile 管理
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
browser-cli profiles # 列出浏览器 profile
|
|
92
|
+
browser-cli delete-profile <id> # 删除 profile
|
|
93
|
+
browser-cli launch --profile <id> # 用指定 profile 启动
|
|
94
|
+
browser-cli runscript <name> --profile <id> --param ... # 用指定 profile 执行脚本
|
|
80
95
|
```
|
|
81
96
|
|
|
82
97
|
## DOM 索引格式
|
|
@@ -92,38 +107,6 @@ browser-cli script-task <task-id> # 查询执行状态
|
|
|
92
107
|
- 每次操作后索引会**重新分配** — 务必使用最新的索引
|
|
93
108
|
- 使用这些索引来执行 `click`、`input` 和 `select` 命令
|
|
94
109
|
|
|
95
|
-
## 登录与 Profile
|
|
96
|
-
|
|
97
|
-
浏览器支持命名 Profile,用于隔离不同账号的登录态(cookies、session)。
|
|
98
|
-
|
|
99
|
-
**当有明确的账号身份时(如多账号运营),必须使用 `--profile`。** 省略 `--profile` 会使用默认 Profile,导致不同账号登录态互相覆盖。
|
|
100
|
-
|
|
101
|
-
- **命名 Profile**:`--profile <id>` 隔离不同账号的登录态,`launch` 和 `runscript` 都支持
|
|
102
|
-
- **登录态自动持久化**:Profile 数据在浏览器运行时实时保存到磁盘,不依赖 close
|
|
103
|
-
- **首次登录**:需要用户提供账号和验证码
|
|
104
|
-
- **后续使用**:自动恢复登录态,无需重新登录
|
|
105
|
-
- **login_required 处理**:如果 `runscript` 报此错误,用 `browser-cli launch --profile <id> --url <平台URL>` 引导用户重新登录
|
|
106
|
-
|
|
107
|
-
```bash
|
|
108
|
-
# 登录到指定 Profile
|
|
109
|
-
browser-cli launch --profile xhs-tech --url https://creator.xiaohongshu.com
|
|
110
|
-
|
|
111
|
-
# 用指定 Profile 执行脚本
|
|
112
|
-
browser-cli runscript xiaohongshu-image-note --profile xhs-tech --param title="..."
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
## 文件路径
|
|
116
|
-
|
|
117
|
-
浏览器后端可以直接读取用户工作空间的文件(通过共享 EFS)。传文件路径时直接使用你看到的路径即可,后端会自动转换:
|
|
118
|
-
|
|
119
|
-
```
|
|
120
|
-
~/images/photo.jpg → 自动转换 ✓
|
|
121
|
-
/home/aiuser/images/photo.jpg → 自动转换 ✓
|
|
122
|
-
/mnt/efs/{userId}/images/... → 自动转换 ✓
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
不需要上传文件,不需要手动转换路径。
|
|
126
|
-
|
|
127
110
|
## 操作流程
|
|
128
111
|
|
|
129
112
|
### 流程一:有脚本(常见)
|
|
@@ -131,12 +114,6 @@ browser-cli runscript xiaohongshu-image-note --profile xhs-tech --param title=".
|
|
|
131
114
|
```bash
|
|
132
115
|
# 1. 检查脚本
|
|
133
116
|
browser-cli scripts
|
|
134
|
-
# 输出:
|
|
135
|
-
# xiaohongshu-image-note — 在小红书创作者平台发布图文笔记
|
|
136
|
-
# [1] navigate — 打开小红书发布页
|
|
137
|
-
# [2] switch_tab — 切换到上传图文模式
|
|
138
|
-
# [3] upload — 上传图片 {images}
|
|
139
|
-
# ...
|
|
140
117
|
|
|
141
118
|
# 2. 直接执行
|
|
142
119
|
browser-cli runscript xiaohongshu-image-note \
|
|
@@ -145,52 +122,35 @@ browser-cli runscript xiaohongshu-image-note \
|
|
|
145
122
|
--param 'images=["~/images/photo1.jpg", "~/images/photo2.jpg"]'
|
|
146
123
|
# 输出: ✓ Script completed
|
|
147
124
|
|
|
148
|
-
#
|
|
125
|
+
# 小红书评论
|
|
149
126
|
browser-cli runscript xiaohongshu-comment \
|
|
150
127
|
--param search_keyword="辞职做跨境电商" \
|
|
151
128
|
--param comment="写得好!"
|
|
152
|
-
|
|
153
|
-
#
|
|
129
|
+
|
|
130
|
+
# 小红书数据采集
|
|
131
|
+
browser-cli runscript xiaohongshu-data-collect
|
|
132
|
+
|
|
133
|
+
# Instagram 发帖
|
|
134
|
+
browser-cli runscript instagram-image-post \
|
|
135
|
+
--param 'images=["~/images/photo.jpg"]' \
|
|
136
|
+
--param body="Morning vibes ☕"
|
|
154
137
|
```
|
|
155
138
|
|
|
156
|
-
###
|
|
139
|
+
### 流程二:无脚本(手动操作)
|
|
157
140
|
|
|
158
141
|
```bash
|
|
159
|
-
# 1.
|
|
160
|
-
browser-cli
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
#
|
|
166
|
-
browser-cli
|
|
167
|
-
browser-cli
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
# → 登录成功,继续操作...
|
|
172
|
-
browser-cli dom # 分析页面
|
|
173
|
-
browser-cli click 1880 # 点击"上传图文"
|
|
174
|
-
browser-cli dom # 找到 file input
|
|
175
|
-
browser-cli upload 1092 ~/images/photo.jpg # 上传图片
|
|
176
|
-
browser-cli input 2905 "标题" # 填写标题
|
|
177
|
-
browser-cli input 3432 "正文内容" # 填写正文
|
|
178
|
-
browser-cli click 2814 # 点击发布
|
|
179
|
-
# → 任务完成
|
|
180
|
-
|
|
181
|
-
# 3. 生成 Python 脚本
|
|
182
|
-
# 根据上面的探索轨迹,生成脚本文件,必须包含:
|
|
183
|
-
# - DESCRIPTION: 脚本描述
|
|
184
|
-
# - STEPS: 语义步骤列表(StepDef)
|
|
185
|
-
# - run(ctx): 异步执行函数
|
|
186
|
-
# 写到本地文件
|
|
187
|
-
|
|
188
|
-
# 4. 提交脚本
|
|
189
|
-
browser-cli submit-script \
|
|
190
|
-
--name xiaohongshu-image-note \
|
|
191
|
-
--code-file /tmp/xiaohongshu_image_note.py
|
|
192
|
-
|
|
193
|
-
# 5. 关闭浏览器
|
|
142
|
+
# 1. 启动浏览器
|
|
143
|
+
browser-cli launch --url https://example.com
|
|
144
|
+
|
|
145
|
+
# 2. 查看 DOM,找到要操作的元素
|
|
146
|
+
browser-cli dom
|
|
147
|
+
|
|
148
|
+
# 3. 操作元素(用 DOM 返回的索引)
|
|
149
|
+
browser-cli click 15
|
|
150
|
+
browser-cli input 22 "内容"
|
|
151
|
+
browser-cli keys Enter
|
|
152
|
+
|
|
153
|
+
# 4. 完成后关闭
|
|
194
154
|
browser-cli close
|
|
195
155
|
```
|
|
196
156
|
|
|
@@ -199,228 +159,35 @@ browser-cli close
|
|
|
199
159
|
```bash
|
|
200
160
|
# 1. 执行脚本
|
|
201
161
|
browser-cli runscript xiaohongshu-image-note --param ...
|
|
202
|
-
# 输出:
|
|
203
|
-
#
|
|
204
|
-
#
|
|
205
|
-
# ✓ Completed:
|
|
206
|
-
# [1] navigate — 打开小红书发布页
|
|
207
|
-
# [2] switch_tab — 切换到上传图文模式
|
|
208
|
-
#
|
|
209
|
-
# ✗ Failed at step [3] upload: file input not found
|
|
210
|
-
#
|
|
211
|
-
# → Remaining steps:
|
|
212
|
-
# [3] upload — 上传图片 ["~/photo.jpg"]
|
|
213
|
-
# [4] fill_title — 填写标题'测试'
|
|
214
|
-
# [5] fill_body — 填写正文'内容'
|
|
215
|
-
# [6] publish — 点击发布按钮
|
|
216
|
-
# [7] verify — 确认发布成功
|
|
217
|
-
#
|
|
218
|
-
# Session is still open — use browser-cli dom/click/input to continue
|
|
219
|
-
|
|
220
|
-
# 2. 接管完成剩余步骤(Session 仍然打开,不需要重新 launch)
|
|
221
|
-
browser-cli dom # 查看当前页面
|
|
222
|
-
browser-cli click 15 # 继续操作
|
|
223
|
-
browser-cli input 22 "测试"
|
|
224
|
-
browser-cli click 30
|
|
225
|
-
# → 任务完成
|
|
226
|
-
|
|
227
|
-
# 3. (可选) 更新脚本以修复问题
|
|
228
|
-
# 重新生成脚本,覆盖旧版本
|
|
229
|
-
browser-cli submit-script \
|
|
230
|
-
--name xiaohongshu-image-note \
|
|
231
|
-
--code-file /tmp/xiaohongshu_image_note_v2.py
|
|
232
|
-
|
|
233
|
-
# 4. 关闭浏览器
|
|
234
|
-
browser-cli close
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
## 脚本代码规范
|
|
238
|
-
|
|
239
|
-
### 基本结构
|
|
240
|
-
|
|
241
|
-
每个脚本必须包含 `DESCRIPTION`、`STEPS` 和 `async def run(ctx)`:
|
|
242
|
-
|
|
243
|
-
```python
|
|
244
|
-
"""脚本描述。"""
|
|
245
|
-
from __future__ import annotations
|
|
246
|
-
import asyncio
|
|
247
|
-
import json
|
|
248
|
-
from app.scripts.base import ScriptContext, ScriptResult, StepDef, render_steps
|
|
249
|
-
|
|
250
|
-
DESCRIPTION = "一句话描述脚本功能"
|
|
251
|
-
|
|
252
|
-
STEPS = [
|
|
253
|
-
StepDef(id="step_id", description="步骤描述,支持 {param} 占位符"),
|
|
254
|
-
]
|
|
255
|
-
|
|
256
|
-
PAGE_SETTLE = 2 # 页面操作后等待秒数
|
|
257
|
-
|
|
258
|
-
async def run(ctx: ScriptContext) -> ScriptResult:
|
|
259
|
-
bs = ctx.browser_session
|
|
260
|
-
steps = render_steps(STEPS, ctx.params)
|
|
261
|
-
completed: list[StepDef] = []
|
|
262
|
-
|
|
263
|
-
try:
|
|
264
|
-
# 逐步执行,每完成一步 append
|
|
265
|
-
# ...
|
|
266
|
-
return ScriptResult(status="completed", output={...}, completed_steps=completed)
|
|
267
|
-
except Exception as e:
|
|
268
|
-
remaining = [s for s in steps if s not in completed]
|
|
269
|
-
snapshot = await _capture_snapshot(bs)
|
|
270
|
-
return ScriptResult(
|
|
271
|
-
status="needs_fallback",
|
|
272
|
-
completed_steps=completed,
|
|
273
|
-
remaining_steps=remaining,
|
|
274
|
-
error=str(e),
|
|
275
|
-
snapshot=snapshot,
|
|
276
|
-
)
|
|
277
|
-
|
|
278
|
-
async def _capture_snapshot(bs) -> dict:
|
|
279
|
-
try:
|
|
280
|
-
state = await bs.get_browser_state_summary(include_screenshot=False)
|
|
281
|
-
dom = state.dom_state.llm_representation() if state and state.dom_state else ""
|
|
282
|
-
except Exception:
|
|
283
|
-
dom = ""
|
|
284
|
-
return {"dom": dom}
|
|
285
|
-
```
|
|
286
|
-
|
|
287
|
-
### 浏览器操作 API
|
|
288
|
-
|
|
289
|
-
```python
|
|
290
|
-
# 导航
|
|
291
|
-
action = ctx.action_model(navigate={"url": "https://example.com"})
|
|
292
|
-
await ctx.controller.act(action, bs)
|
|
293
|
-
await asyncio.sleep(PAGE_SETTLE)
|
|
162
|
+
# 输出: ⚠ Script needs fallback
|
|
163
|
+
# → 显示已完成和剩余步骤
|
|
294
164
|
|
|
295
|
-
#
|
|
296
|
-
|
|
297
|
-
|
|
165
|
+
# 2. Session 仍然打开 — 用手动命令继续完成剩余步骤
|
|
166
|
+
browser-cli dom
|
|
167
|
+
browser-cli click 15
|
|
168
|
+
browser-cli input 22 "内容"
|
|
298
169
|
|
|
299
|
-
#
|
|
300
|
-
|
|
301
|
-
await ctx.controller.act(action, bs)
|
|
302
|
-
|
|
303
|
-
# 获取当前 DOM(每步操作前刷新)
|
|
304
|
-
state = await bs.get_browser_state_summary(include_screenshot=False, cached=False)
|
|
305
|
-
sm = state.dom_state.selector_map or {}
|
|
306
|
-
|
|
307
|
-
# 获取当前 URL
|
|
308
|
-
page = await bs.get_current_page()
|
|
309
|
-
url = await page.get_url()
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
### 元素查找(语义匹配,不要硬编码 index)
|
|
313
|
-
|
|
314
|
-
DOM index 每次页面变化后会重新分配,脚本中**不能硬编码 index**。
|
|
315
|
-
必须通过语义属性动态查找:
|
|
316
|
-
|
|
317
|
-
```python
|
|
318
|
-
# 按文字内容查找(如按钮、标签页)
|
|
319
|
-
def _find_by_text(sm, text, tag=None):
|
|
320
|
-
for idx, node in sm.items():
|
|
321
|
-
node_tag = (getattr(node, "tag_name", "") or "").lower()
|
|
322
|
-
if tag and node_tag != tag:
|
|
323
|
-
continue
|
|
324
|
-
try:
|
|
325
|
-
node_text = node.get_all_children_text().strip() if hasattr(node, "get_all_children_text") else ""
|
|
326
|
-
except Exception:
|
|
327
|
-
node_text = ""
|
|
328
|
-
if text in node_text:
|
|
329
|
-
return idx
|
|
330
|
-
return None
|
|
331
|
-
|
|
332
|
-
# 按 placeholder 查找(如输入框,支持 shadow DOM)
|
|
333
|
-
def _find_by_placeholder(sm, placeholder_contains):
|
|
334
|
-
for idx, node in sm.items():
|
|
335
|
-
attrs = getattr(node, "attributes", {}) or {}
|
|
336
|
-
if placeholder_contains in attrs.get("placeholder", ""):
|
|
337
|
-
return idx
|
|
338
|
-
# Shadow DOM fallback
|
|
339
|
-
if not attrs:
|
|
340
|
-
try:
|
|
341
|
-
llm = node.llm_representation() if hasattr(node, "llm_representation") else ""
|
|
342
|
-
if placeholder_contains in llm:
|
|
343
|
-
return idx
|
|
344
|
-
except Exception:
|
|
345
|
-
pass
|
|
346
|
-
return None
|
|
347
|
-
|
|
348
|
-
# 按 role 查找(如 contenteditable 编辑器)
|
|
349
|
-
def _find_by_role(sm, role, tag=None):
|
|
350
|
-
for idx, node in sm.items():
|
|
351
|
-
node_tag = (getattr(node, "tag_name", "") or "").lower()
|
|
352
|
-
if tag and node_tag != tag:
|
|
353
|
-
continue
|
|
354
|
-
attrs = getattr(node, "attributes", {}) or {}
|
|
355
|
-
if attrs.get("role") == role:
|
|
356
|
-
return idx
|
|
357
|
-
if attrs.get("contenteditable") and role == "textbox":
|
|
358
|
-
return idx
|
|
359
|
-
return None
|
|
360
|
-
|
|
361
|
-
# 按文件类型查找 file input(如图片上传)
|
|
362
|
-
def _find_image_file_input(bs, sm):
|
|
363
|
-
for idx, node in sm.items():
|
|
364
|
-
if not bs.is_file_input(node):
|
|
365
|
-
continue
|
|
366
|
-
attrs = getattr(node, "attributes", {}) or {}
|
|
367
|
-
accept = attrs.get("accept", "")
|
|
368
|
-
if any(ext in accept for ext in [".jpg", ".jpeg", ".png", ".webp"]):
|
|
369
|
-
return idx
|
|
370
|
-
for idx, node in sm.items():
|
|
371
|
-
if bs.is_file_input(node):
|
|
372
|
-
return idx
|
|
373
|
-
return None
|
|
170
|
+
# 3. 完成后关闭
|
|
171
|
+
browser-cli close
|
|
374
172
|
```
|
|
375
173
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
上传文件需要 `FileSystem` 和 `available_file_paths`:
|
|
379
|
-
|
|
380
|
-
```python
|
|
381
|
-
from browser_use.filesystem.file_system import FileSystem
|
|
382
|
-
from app.services.file_upload import UPLOAD_TEMP_BASE
|
|
383
|
-
import secrets as _secrets
|
|
174
|
+
## 文件路径
|
|
384
175
|
|
|
385
|
-
|
|
386
|
-
fs_dir = UPLOAD_TEMP_BASE / f"script_{_secrets.token_hex(4)}"
|
|
387
|
-
fs_dir.mkdir(parents=True, exist_ok=True)
|
|
388
|
-
file_system = FileSystem(base_dir=str(fs_dir), create_default_files=False)
|
|
176
|
+
浏览器后端可以直接读取用户工作空间的文件。传文件路径时直接使用你看到的路径即可,后端会自动转换:
|
|
389
177
|
|
|
390
|
-
|
|
391
|
-
images
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
action = ctx.action_model(upload_file={"index": file_idx, "path": img_path})
|
|
395
|
-
await ctx.controller.act(action, bs, available_file_paths=images, file_system=file_system)
|
|
178
|
+
```
|
|
179
|
+
~/images/photo.jpg → 自动转换 ✓
|
|
180
|
+
/home/aiuser/images/photo.jpg → 自动转换 ✓
|
|
181
|
+
/mnt/efs/{userId}/images/... → 自动转换 ✓
|
|
396
182
|
```
|
|
397
183
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
### 等待页面变化
|
|
401
|
-
|
|
402
|
-
页面操作后(导航、上传、点击)需要等待,用轮询模式:
|
|
403
|
-
|
|
404
|
-
```python
|
|
405
|
-
# 简单等待
|
|
406
|
-
await asyncio.sleep(PAGE_SETTLE)
|
|
184
|
+
## 需要用户登录态的任务
|
|
407
185
|
|
|
408
|
-
|
|
409
|
-
target_idx = None
|
|
410
|
-
for attempt in range(10):
|
|
411
|
-
await asyncio.sleep(PAGE_SETTLE)
|
|
412
|
-
state = await bs.get_browser_state_summary(include_screenshot=False, cached=False)
|
|
413
|
-
sm = state.dom_state.selector_map or {}
|
|
414
|
-
target_idx = _find_by_placeholder(sm, "填写标题")
|
|
415
|
-
if target_idx is not None:
|
|
416
|
-
break
|
|
417
|
-
if target_idx is None:
|
|
418
|
-
raise RuntimeError("等待超时:目标元素未出现")
|
|
419
|
-
```
|
|
186
|
+
当用户要求操作需要登录的平台(小红书、Instagram、微博、淘宝等社交/电商平台),在开始执行前先引导用户安装扩展:
|
|
420
187
|
|
|
421
|
-
|
|
188
|
+
"这个任务需要用到你在 [平台名] 的登录态。请安装 Optima Browser Operator Chrome 扩展,这样我可以直接用你已登录的浏览器来操作,不需要你提供密码。"
|
|
422
189
|
|
|
423
|
-
|
|
190
|
+
安装后用户回到聊天页面,扩展自动连接,直接执行任务。如果用户在该平台未登录,提示用户先在自己的 Chrome 里登录。
|
|
424
191
|
|
|
425
192
|
## 注意事项
|
|
426
193
|
|
|
@@ -428,9 +195,7 @@ if target_idx is None:
|
|
|
428
195
|
- **DOM 自动返回**:每个操作会自动返回 DOM 状态 — 无需单独调用 `browser-cli dom`
|
|
429
196
|
- **避免不必要的截图**:截图消耗 token,日常导航用 DOM 输出即可
|
|
430
197
|
- **5 分钟超时**:无操作 5 分钟后会话自动关闭
|
|
431
|
-
- **登录自动保持**:登录一次后自动持久化,无需重复登录
|
|
432
|
-
- **文件路径自动转换**:直接传你看到的路径(~/xxx),后端自动处理
|
|
433
198
|
- **务必关闭**:操作完成后运行 `browser-cli close` 释放资源
|
|
434
|
-
- **login_required 处理**:如果 runscript 返回 `login_required`
|
|
199
|
+
- **login_required 处理**:如果 runscript 返回 `login_required` 错误,说明该平台未登录。如果用户已安装 Extension 且 Extension 已连接,用户的 Chrome 通常已经登录了——让用户在自己的 Chrome 里手动登录该平台,然后重新 `runscript`。如果没有 Extension(走 Chromium),用 `browser-cli launch --url <平台URL>` 引导用户登录
|
|
435
200
|
- **Fallback 后更新脚本**:如果脚本频繁失败,重新生成并 submit-script 覆盖
|
|
436
201
|
- **Extension 模式**:标记了 `REQUIRES_USER_SESSION=True` 的脚本会自动使用用户的真实 Chrome(通过 Optima Browser Operator 扩展),未标记的脚本走 Chromium。这由后端自动判断,无需手动指定
|
|
@@ -177,6 +177,26 @@ commerce i18n homepage set \
|
|
|
177
177
|
commerce i18n homepage list --section-id section_123
|
|
178
178
|
```
|
|
179
179
|
|
|
180
|
+
### 场景7: 店铺政策翻译
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
# 翻译退货政策
|
|
184
|
+
commerce i18n shop-policy set --policy-type returns --lang zh-CN --title "退货政策" --content "# 退货政策\n\n..."
|
|
185
|
+
|
|
186
|
+
# 翻译隐私政策
|
|
187
|
+
commerce i18n shop-policy set --policy-type privacy --lang ja-JP --title "プライバシーポリシー" --content "# ..."
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### 场景8: 店铺关于页面翻译
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
# 翻译关于页面
|
|
194
|
+
commerce i18n shop-about set --lang zh-CN --about-content "# 我们的故事\n\n..."
|
|
195
|
+
|
|
196
|
+
# 翻译联系页面补充内容
|
|
197
|
+
commerce i18n shop-about set --lang ja-JP --contact-content "# お問い合わせ\n\n..."
|
|
198
|
+
```
|
|
199
|
+
|
|
180
200
|
## 卓越标准 (Excellence Standards)
|
|
181
201
|
|
|
182
202
|
### 翻译质量维度
|
|
@@ -354,6 +374,8 @@ commerce i18n variant create --variant-id var_2 --lang ja-JP \
|
|
|
354
374
|
- "翻译集合信息" → `commerce i18n collection create --collection-id XX --lang YY`
|
|
355
375
|
- "设置商户多语言信息" → `commerce i18n merchant create --lang XX`
|
|
356
376
|
- "翻译首页区块" → `commerce i18n homepage set --section-id XX --lang YY`
|
|
377
|
+
- "翻译店铺政策" → `commerce i18n shop-policy set --policy-type XX --lang YY`
|
|
378
|
+
- "翻译关于页面" → `commerce i18n shop-about set --lang XX`
|
|
357
379
|
|
|
358
380
|
### 商品翻译
|
|
359
381
|
|
|
@@ -390,6 +412,14 @@ commerce i18n variant create --variant-id var_2 --lang ja-JP \
|
|
|
390
412
|
- `commerce i18n homepage list` - 查看首页翻译
|
|
391
413
|
- `commerce i18n homepage delete` - 删除首页翻译
|
|
392
414
|
|
|
415
|
+
### 店铺政策翻译
|
|
416
|
+
|
|
417
|
+
- `commerce i18n shop-policy set` - 设置店铺政策翻译
|
|
418
|
+
|
|
419
|
+
### 店铺关于页面翻译
|
|
420
|
+
|
|
421
|
+
- `commerce i18n shop-about set` - 设置店铺关于页面翻译
|
|
422
|
+
|
|
393
423
|
## 详细示例 (Detailed Examples)
|
|
394
424
|
|
|
395
425
|
### 商品翻译示例
|
|
@@ -477,7 +507,7 @@ commerce i18n product create --product-id prod_2 --lang ja-JP --name "..."
|
|
|
477
507
|
|
|
478
508
|
## 重要提示 (Important Notes)
|
|
479
509
|
|
|
480
|
-
- **支持的语言**:en-US, es-ES, ja-JP, vi-VN, zh-CN
|
|
510
|
+
- **支持的语言**:en-US, es-ES, ja-JP, vi-VN, zh-CN, zh-HK, zh-TW
|
|
481
511
|
- **语言代码格式**:必须使用BCP 47格式(如 en-US),不能使用短代码(如 en)
|
|
482
512
|
- **变体翻译参数**:使用 `--variant-id`(不是 `--product-id`)
|
|
483
513
|
- **变体规格翻译**:`variant-attributes-translations` 格式需要同时翻译规格键和值
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: shop-content
|
|
3
|
+
description: "店铺内容管理。使用场景:更新关于我们、设置联系信息、管理退货/隐私/条款/配送政策、设置社交链接。注意:翻译用 i18n skill。"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 店铺内容管理
|
|
7
|
+
|
|
8
|
+
## 典型场景
|
|
9
|
+
|
|
10
|
+
| 用户说 | 命令 |
|
|
11
|
+
|--------|------|
|
|
12
|
+
| "更新关于我们" / "写关于页面" | `commerce shop-about update --about-content "# Our Story..."` |
|
|
13
|
+
| "设置联系方式" | `commerce shop-about update --contact-email "..." --contact-phone "..."` |
|
|
14
|
+
| "添加联系页面内容" | `commerce shop-about update --contact-content "# Contact..."` |
|
|
15
|
+
| "查看关于信息" | `commerce shop-about get` |
|
|
16
|
+
| "设置 Instagram" / "添加社交链接" | `commerce shop-about update --social-instagram "https://..."` |
|
|
17
|
+
| "设置退货政策" / "更新退货政策" | `commerce shop-policy set --type returns --title "退货政策" --content "# ..."` |
|
|
18
|
+
| "设置隐私政策" | `commerce shop-policy set --type privacy --title "隐私政策" --content "# ..."` |
|
|
19
|
+
| "设置服务条款" | `commerce shop-policy set --type terms --title "服务条款" --content "# ..."` |
|
|
20
|
+
| "设置配送政策" | `commerce shop-policy set --type shipping --title "配送政策" --content "# ..."` |
|
|
21
|
+
| "查看所有政策" | `commerce shop-policy list` |
|
|
22
|
+
| "查看退货政策" | `commerce shop-policy get --type returns` |
|
|
23
|
+
|
|
24
|
+
## 不在此模块(重要)
|
|
25
|
+
|
|
26
|
+
| 用户说 | 正确位置 |
|
|
27
|
+
|--------|----------|
|
|
28
|
+
| "翻译退货政策" / "政策日语版" | **i18n skill**:`commerce i18n shop-policy set` |
|
|
29
|
+
| "翻译关于我们" | **i18n skill**:`commerce i18n shop-about set` |
|
|
30
|
+
| "首页设置" / "首页区块" | **homepage skill** |
|
|
31
|
+
| "修改品牌色" / "主题色" | **merchant skill**:`commerce merchant update --primary-color` |
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## 关于页面内容
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# 查看当前内容
|
|
39
|
+
commerce shop-about get
|
|
40
|
+
|
|
41
|
+
# 更新关于页面(Markdown 格式)
|
|
42
|
+
commerce shop-about update --about-content "# Our Story\n\nWe started in 2020..."
|
|
43
|
+
|
|
44
|
+
# 更新联系页面补充内容
|
|
45
|
+
commerce shop-about update --contact-content "## 批发合作\n\n请联系..."
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## 联系信息
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
commerce shop-about update \
|
|
52
|
+
--contact-email "hello@store.com" \
|
|
53
|
+
--contact-phone "+86 138xxxx" \
|
|
54
|
+
--business-address "深圳市南山区..." \
|
|
55
|
+
--business-hours "Mon-Fri 9:00-18:00"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## 社交链接
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
# 设置单个
|
|
62
|
+
commerce shop-about update --social-instagram "https://instagram.com/mystore"
|
|
63
|
+
|
|
64
|
+
# 设置多个
|
|
65
|
+
commerce shop-about update \
|
|
66
|
+
--social-instagram "https://instagram.com/mystore" \
|
|
67
|
+
--social-tiktok "https://tiktok.com/@mystore" \
|
|
68
|
+
--social-youtube "https://youtube.com/@mystore"
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
支持:`--social-instagram`, `--social-facebook`, `--social-twitter`, `--social-tiktok`, `--social-youtube`
|
|
72
|
+
|
|
73
|
+
## 店铺政策
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# 查看所有政策
|
|
77
|
+
commerce shop-policy list
|
|
78
|
+
|
|
79
|
+
# 查看特定政策
|
|
80
|
+
commerce shop-policy get --type returns
|
|
81
|
+
|
|
82
|
+
# 设置/更新政策(Markdown 格式)
|
|
83
|
+
commerce shop-policy set --type returns --title "退货政策" --content "# 退货政策\n\n..."
|
|
84
|
+
commerce shop-policy set --type privacy --title "隐私政策" --content "# 隐私政策\n\n..."
|
|
85
|
+
commerce shop-policy set --type terms --title "服务条款" --content "# 服务条款\n\n..."
|
|
86
|
+
commerce shop-policy set --type shipping --title "配送政策" --content "# 配送政策\n\n..."
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**注意**:政策类型只能是 `terms`、`privacy`、`returns`、`shipping`。
|
|
90
|
+
|
|
91
|
+
## 内容格式
|
|
92
|
+
|
|
93
|
+
所有内容字段(about_content、contact_content、policy content)使用 **Markdown 格式**,支持标题、列表、粗体、链接等。
|
|
94
|
+
|
|
95
|
+
## 命令参考
|
|
96
|
+
|
|
97
|
+
- `commerce shop-about get` - 查看关于/联系信息
|
|
98
|
+
- `commerce shop-about update` - 更新关于/联系/社交链接
|
|
99
|
+
- `commerce shop-policy list` - 查看所有政策
|
|
100
|
+
- `commerce shop-policy get --type <type>` - 查看特定政策
|
|
101
|
+
- `commerce shop-policy set --type <type> --title <title> --content <content>` - 设置政策
|