@optima-chat/optima-agent 0.7.2 → 0.7.4
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/settings.local.json +110 -0
- package/.claude/skills/ads/SKILL.md +201 -52
- package/dist/bin/bi-cli.js +0 -0
- package/dist/bin/comfy.js +0 -0
- package/dist/bin/commerce.js +0 -0
- package/dist/bin/google-ads.js +0 -0
- package/dist/bin/optima.js +0 -0
- package/dist/bin/scout.js +0 -0
- package/dist/src/hooks-loader.d.ts +6 -0
- package/dist/src/hooks-loader.d.ts.map +1 -0
- package/dist/src/hooks-loader.js +215 -0
- package/dist/src/hooks-loader.js.map +1 -0
- package/dist/src/ui/App.d.ts +6 -0
- package/dist/src/ui/App.d.ts.map +1 -0
- package/dist/src/ui/App.js +164 -0
- package/dist/src/ui/App.js.map +1 -0
- package/dist/src/ui/components/Composer.d.ts +10 -0
- package/dist/src/ui/components/Composer.d.ts.map +1 -0
- package/dist/src/ui/components/Composer.js +13 -0
- package/dist/src/ui/components/Composer.js.map +1 -0
- package/dist/src/ui/components/Header.d.ts +7 -0
- package/dist/src/ui/components/Header.d.ts.map +1 -0
- package/dist/src/ui/components/Header.js +7 -0
- package/dist/src/ui/components/Header.js.map +1 -0
- package/dist/src/ui/components/Message.d.ts +12 -0
- package/dist/src/ui/components/Message.d.ts.map +1 -0
- package/dist/src/ui/components/Message.js +21 -0
- package/dist/src/ui/components/Message.js.map +1 -0
- package/dist/src/ui/components/MessageList.d.ts +9 -0
- package/dist/src/ui/components/MessageList.d.ts.map +1 -0
- package/dist/src/ui/components/MessageList.js +18 -0
- package/dist/src/ui/components/MessageList.js.map +1 -0
- package/dist/src/ui/components/Spinner.d.ts +6 -0
- package/dist/src/ui/components/Spinner.d.ts.map +1 -0
- package/dist/src/ui/components/Spinner.js +7 -0
- package/dist/src/ui/components/Spinner.js.map +1 -0
- package/dist/src/ui/components/StatusBar.d.ts +11 -0
- package/dist/src/ui/components/StatusBar.d.ts.map +1 -0
- package/dist/src/ui/components/StatusBar.js +7 -0
- package/dist/src/ui/components/StatusBar.js.map +1 -0
- package/dist/src/ui/components/index.d.ts +7 -0
- package/dist/src/ui/components/index.d.ts.map +1 -0
- package/dist/src/ui/components/index.js +7 -0
- package/dist/src/ui/components/index.js.map +1 -0
- package/dist/src/validation/error-formatter.d.ts +21 -0
- package/dist/src/validation/error-formatter.d.ts.map +1 -0
- package/dist/src/validation/error-formatter.js +98 -0
- package/dist/src/validation/error-formatter.js.map +1 -0
- package/dist/src/validation/index.d.ts +10 -0
- package/dist/src/validation/index.d.ts.map +1 -0
- package/dist/src/validation/index.js +10 -0
- package/dist/src/validation/index.js.map +1 -0
- package/dist/src/validation/json-validator.d.ts +25 -0
- package/dist/src/validation/json-validator.d.ts.map +1 -0
- package/dist/src/validation/json-validator.js +173 -0
- package/dist/src/validation/json-validator.js.map +1 -0
- package/dist/src/validation/schema.d.ts +353 -0
- package/dist/src/validation/schema.d.ts.map +1 -0
- package/dist/src/validation/schema.js +57 -0
- package/dist/src/validation/schema.js.map +1 -0
- package/dist/src/validation/suggestions.d.ts +25 -0
- package/dist/src/validation/suggestions.d.ts.map +1 -0
- package/dist/src/validation/suggestions.js +144 -0
- package/dist/src/validation/suggestions.js.map +1 -0
- package/dist/src/validation/types.d.ts +40 -0
- package/dist/src/validation/types.d.ts.map +1 -0
- package/dist/src/validation/types.js +5 -0
- package/dist/src/validation/types.js.map +1 -0
- package/dist/src/validation/yaml-validator.d.ts +25 -0
- package/dist/src/validation/yaml-validator.d.ts.map +1 -0
- package/dist/src/validation/yaml-validator.js +177 -0
- package/dist/src/validation/yaml-validator.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(gh api:*)",
|
|
5
|
+
"WebFetch(domain:platform.claude.com)",
|
|
6
|
+
"Bash(git init:*)",
|
|
7
|
+
"Bash(mkdir:*)",
|
|
8
|
+
"Bash(npm run typecheck:*)",
|
|
9
|
+
"Bash(npm view:*)",
|
|
10
|
+
"WebSearch",
|
|
11
|
+
"Bash(commerce --help)",
|
|
12
|
+
"Bash(done)",
|
|
13
|
+
"Bash(commerce product:*)",
|
|
14
|
+
"Bash(commerce order:*)",
|
|
15
|
+
"Bash(commerce i18n:*)",
|
|
16
|
+
"Bash(google-ads:*)",
|
|
17
|
+
"Bash(scout --help:*)",
|
|
18
|
+
"Bash(tree:*)",
|
|
19
|
+
"Bash(cloc:*)",
|
|
20
|
+
"Bash(npm run build:*)",
|
|
21
|
+
"Bash(git restore:*)",
|
|
22
|
+
"Bash(gh repo view:*)",
|
|
23
|
+
"Bash(mv:*)",
|
|
24
|
+
"Bash(rmdir:*)",
|
|
25
|
+
"Bash(git add:*)",
|
|
26
|
+
"Bash(git commit:*)",
|
|
27
|
+
"Bash(git push)",
|
|
28
|
+
"Bash(timeout 5 npm run optima:*)",
|
|
29
|
+
"Bash(npm install:*)",
|
|
30
|
+
"Bash(cat:*)",
|
|
31
|
+
"Bash(gh issue create:*)",
|
|
32
|
+
"Bash(npx tsx:*)",
|
|
33
|
+
"Bash(timeout 30 npx tsx:*)",
|
|
34
|
+
"Bash(git push origin feature/ask-user-question)",
|
|
35
|
+
"Bash(node:*)",
|
|
36
|
+
"Bash(npm version:*)",
|
|
37
|
+
"Bash(git push:*)",
|
|
38
|
+
"Bash(npm publish:*)",
|
|
39
|
+
"Bash(pkill:*)",
|
|
40
|
+
"Bash(git -C /Users/verypro/optima-agent log --oneline --all -- \".claude/\")",
|
|
41
|
+
"Bash(wc:*)",
|
|
42
|
+
"Bash(grep:*)",
|
|
43
|
+
"Bash(find:*)",
|
|
44
|
+
"Bash(commerce collection --help:*)",
|
|
45
|
+
"Bash(commerce collection update --help:*)",
|
|
46
|
+
"Bash(commerce collection set-cover:*)",
|
|
47
|
+
"Bash(commerce collection get --help:*)",
|
|
48
|
+
"Bash(commerce collection list --help:*)",
|
|
49
|
+
"Bash(commerce collection create --help:*)",
|
|
50
|
+
"Bash(commerce collection remove-products:*)",
|
|
51
|
+
"Bash(commerce collection list-products:*)",
|
|
52
|
+
"Bash(commerce --version:*)",
|
|
53
|
+
"Bash(bi-cli --version:*)",
|
|
54
|
+
"Bash(commerce homepage create --help:*)",
|
|
55
|
+
"Bash(commerce homepage reorder --help:*)",
|
|
56
|
+
"Bash(commerce homepage delete --help:*)",
|
|
57
|
+
"Bash(commerce homepage update-images:*)",
|
|
58
|
+
"Bash(commerce homepage update-collections:*)",
|
|
59
|
+
"Bash(commerce homepage update-target:*)",
|
|
60
|
+
"Bash(commerce homepage switch-template:*)",
|
|
61
|
+
"Bash(commerce inventory:*)",
|
|
62
|
+
"Bash(commerce merchant:*)",
|
|
63
|
+
"Bash(commerce review:*)",
|
|
64
|
+
"Bash(commerce product-page:*)",
|
|
65
|
+
"Bash(bi-cli:*)",
|
|
66
|
+
"Bash(comfy:*)",
|
|
67
|
+
"Bash(scout search:*)",
|
|
68
|
+
"Bash(scout product:*)",
|
|
69
|
+
"Bash(commerce homepage create-collections:*)",
|
|
70
|
+
"Bash(commerce homepage create-featured:*)",
|
|
71
|
+
"Bash(commerce homepage create-collection-products:*)",
|
|
72
|
+
"Bash(commerce homepage create-banner:*)",
|
|
73
|
+
"Bash(xargs -I {} sh -c 'echo \"\"\"\"=== {} ===\"\"\"\"; head -3 /Users/verypro/optima-agent/.claude/skills/{}/SKILL.md | grep \"\"\"\"name:\"\"\"\"')",
|
|
74
|
+
"Bash(ls:*)",
|
|
75
|
+
"Bash(gh issue view:*)",
|
|
76
|
+
"Bash(npx markdownlint-cli:*)",
|
|
77
|
+
"Bash(chmod:*)",
|
|
78
|
+
"Bash(npm whoami:*)",
|
|
79
|
+
"Bash(tsx test-scripts/test-headless-progress.ts:*)",
|
|
80
|
+
"Bash(DEBUG_STREAM=1 node dist/bin/optima.js:*)",
|
|
81
|
+
"Bash(git describe:*)",
|
|
82
|
+
"WebFetch(domain:github.com)",
|
|
83
|
+
"Bash(./scripts/test-headless.sh:*)",
|
|
84
|
+
"Bash(./scripts/test-headless-simple.sh:*)",
|
|
85
|
+
"Bash(env)",
|
|
86
|
+
"Bash(gh pr list:*)",
|
|
87
|
+
"Bash(gh pr view:*)",
|
|
88
|
+
"Bash(gh pr diff:*)",
|
|
89
|
+
"Bash(optima --version:*)",
|
|
90
|
+
"Bash(optima agent headless:*)",
|
|
91
|
+
"Bash(optima headless:*)",
|
|
92
|
+
"Bash(/Users/verypro/optima-agent/scripts/test-headless.sh:*)",
|
|
93
|
+
"Bash(/Users/verypro/optima-agent/scripts/test-headless-simple.sh:*)",
|
|
94
|
+
"Bash(tee:*)",
|
|
95
|
+
"Bash(CONV_ID=\"conv-1\":*)",
|
|
96
|
+
"Bash(echo:*)",
|
|
97
|
+
"Bash(scout tiktok trending --help:*)",
|
|
98
|
+
"Bash(scout tiktok trending:*)",
|
|
99
|
+
"Bash(git checkout:*)",
|
|
100
|
+
"Bash(npm test:*)",
|
|
101
|
+
"Bash(git tag:*)",
|
|
102
|
+
"Bash(/private/tmp/claude/-Users-verypro-optima-agent/68a9ac2c-def2-44e1-b42b-e53bd9022ab6/scratchpad/test-canUseTool.sh)",
|
|
103
|
+
"Bash(optima --help:*)",
|
|
104
|
+
"Bash(npx @optima-chat/ads-cli:*)",
|
|
105
|
+
"Bash(head:*)"
|
|
106
|
+
],
|
|
107
|
+
"deny": [],
|
|
108
|
+
"ask": []
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -1,94 +1,243 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ads
|
|
3
|
-
description: Google Ads
|
|
3
|
+
description: Google Ads campaign management. Create campaigns, ad groups, keywords, and ads. View performance metrics. Use when user needs to run ads (投放广告/打广告), manage Google Ads (广告系列/广告组), or analyze ad performance (广告效果/点击率/转化).
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Google Ads CLI
|
|
6
|
+
# Google Ads CLI - 广告投放管理
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
CLI 命令: `google-ads`(或 `ads`)
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
## 首次使用
|
|
11
11
|
|
|
12
12
|
```bash
|
|
13
|
-
#
|
|
14
|
-
google-ads account create --email your@gmail.com --name "公司名称"
|
|
15
|
-
|
|
16
|
-
# 验证账号
|
|
13
|
+
# 检查用户是否已授权 Google Ads 账号
|
|
17
14
|
google-ads account check
|
|
18
|
-
|
|
19
|
-
# 查看配置
|
|
20
|
-
google-ads config show
|
|
21
15
|
```
|
|
22
16
|
|
|
23
|
-
|
|
17
|
+
**返回状态**:
|
|
18
|
+
- `status: "active"` → 已授权,可以开始使用
|
|
19
|
+
- `status: "not_linked"` → 用户尚未授权 Google Ads,需引导用户在 Optima 平台完成 Google Ads 账号授权
|
|
20
|
+
|
|
21
|
+
## 典型场景
|
|
22
|
+
|
|
23
|
+
### 场景1:从零开始投放广告
|
|
24
|
+
|
|
25
|
+
**用户说**:"我想投放 Google 广告推广我的产品"
|
|
26
|
+
|
|
27
|
+
**流程**: 创建广告系列 → 创建广告组 → 添加关键词 → 创建广告 → 启用
|
|
24
28
|
|
|
25
29
|
```bash
|
|
26
|
-
#
|
|
27
|
-
google-ads campaign
|
|
30
|
+
# 1. 创建广告系列(每日预算 $50,默认 PAUSED)
|
|
31
|
+
google-ads campaign create -n "产品推广" -b 50
|
|
32
|
+
|
|
33
|
+
# 2. 创建广告组(CPC 出价 $2)
|
|
34
|
+
google-ads ad-group create --campaign-id <campaign-id> -n "核心关键词组" --cpc-bid 2
|
|
28
35
|
|
|
29
|
-
#
|
|
30
|
-
google-ads
|
|
36
|
+
# 3. 添加关键词
|
|
37
|
+
google-ads keyword add --ad-group-id <ad-group-id> -k "产品名称,品牌词,行业词"
|
|
31
38
|
|
|
32
|
-
#
|
|
33
|
-
google-ads
|
|
39
|
+
# 4. 创建广告
|
|
40
|
+
google-ads ad create \
|
|
41
|
+
--ad-group-id <ad-group-id> \
|
|
42
|
+
--headlines "优质产品,限时优惠,免费配送" \
|
|
43
|
+
--descriptions "高品质产品限时优惠中,立即下单享受专属折扣" \
|
|
44
|
+
--final-url "https://shop.example.com"
|
|
34
45
|
|
|
35
|
-
#
|
|
36
|
-
google-ads campaign
|
|
37
|
-
google-ads campaign enable <campaign-id>
|
|
46
|
+
# 5. 确认无误后启用
|
|
47
|
+
google-ads campaign update --campaign-id <campaign-id> --status ENABLED
|
|
38
48
|
```
|
|
39
49
|
|
|
40
|
-
###
|
|
50
|
+
### 场景2:查看广告效果
|
|
51
|
+
|
|
52
|
+
**用户说**:"看看我的广告效果怎么样"
|
|
41
53
|
|
|
42
54
|
```bash
|
|
43
|
-
#
|
|
44
|
-
google-ads
|
|
55
|
+
# 快速查看所有广告系列状态
|
|
56
|
+
google-ads campaign list
|
|
45
57
|
|
|
46
|
-
#
|
|
47
|
-
google-ads
|
|
58
|
+
# 查看详细效果数据(GAQL 查询)
|
|
59
|
+
google-ads query -q "
|
|
60
|
+
SELECT
|
|
61
|
+
campaign.name,
|
|
62
|
+
metrics.impressions,
|
|
63
|
+
metrics.clicks,
|
|
64
|
+
metrics.ctr,
|
|
65
|
+
metrics.average_cpc,
|
|
66
|
+
metrics.cost_micros,
|
|
67
|
+
metrics.conversions
|
|
68
|
+
FROM campaign
|
|
69
|
+
WHERE segments.date DURING LAST_7_DAYS
|
|
70
|
+
ORDER BY metrics.cost_micros DESC
|
|
71
|
+
"
|
|
48
72
|
```
|
|
49
73
|
|
|
50
|
-
###
|
|
74
|
+
### 场景3:暂停/启用广告
|
|
75
|
+
|
|
76
|
+
**用户说**:"暂停那个效果不好的广告系列"
|
|
51
77
|
|
|
52
78
|
```bash
|
|
53
|
-
#
|
|
54
|
-
google-ads
|
|
79
|
+
# 先查看列表确认 ID
|
|
80
|
+
google-ads campaign list
|
|
81
|
+
|
|
82
|
+
# 暂停广告系列
|
|
83
|
+
google-ads campaign update --campaign-id <id> --status PAUSED
|
|
55
84
|
|
|
56
|
-
#
|
|
57
|
-
google-ads
|
|
85
|
+
# 重新启用
|
|
86
|
+
google-ads campaign update --campaign-id <id> --status ENABLED
|
|
58
87
|
```
|
|
59
88
|
|
|
60
|
-
###
|
|
89
|
+
### 场景4:调整预算和出价
|
|
90
|
+
|
|
91
|
+
**用户说**:"把预算提高到 100 美元"
|
|
61
92
|
|
|
62
93
|
```bash
|
|
63
|
-
#
|
|
64
|
-
google-ads
|
|
94
|
+
# 更新广告系列预算
|
|
95
|
+
google-ads campaign update --campaign-id <id> --budget 100
|
|
65
96
|
|
|
66
|
-
#
|
|
67
|
-
google-ads
|
|
97
|
+
# 更新广告组 CPC 出价
|
|
98
|
+
google-ads ad-group update --ad-group-id <id> --cpc-bid 3
|
|
68
99
|
```
|
|
69
100
|
|
|
70
|
-
|
|
101
|
+
### 场景5:添加新关键词
|
|
71
102
|
|
|
72
|
-
|
|
103
|
+
**用户说**:"给广告添加一些新关键词"
|
|
73
104
|
|
|
74
105
|
```bash
|
|
75
|
-
#
|
|
76
|
-
google-ads
|
|
77
|
-
# 获得 campaign_id
|
|
106
|
+
# 先确认广告组 ID
|
|
107
|
+
google-ads ad-group list
|
|
78
108
|
|
|
79
|
-
#
|
|
80
|
-
google-ads
|
|
81
|
-
# 获得 adgroup_id
|
|
109
|
+
# 添加关键词(默认广泛匹配)
|
|
110
|
+
google-ads keyword add --ad-group-id <id> -k "新关键词1,新关键词2"
|
|
82
111
|
|
|
83
|
-
#
|
|
84
|
-
google-ads keyword add --
|
|
112
|
+
# 添加精确匹配关键词
|
|
113
|
+
google-ads keyword add --ad-group-id <id> -k "精确词" --match-type EXACT
|
|
85
114
|
|
|
86
|
-
#
|
|
87
|
-
google-ads
|
|
115
|
+
# 添加词组匹配关键词
|
|
116
|
+
google-ads keyword add --ad-group-id <id> -k "词组匹配" --match-type PHRASE
|
|
88
117
|
```
|
|
89
118
|
|
|
90
|
-
##
|
|
119
|
+
## 场景决策表
|
|
91
120
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
121
|
+
| 用户需求 | 推荐命令 | 关键注意点 |
|
|
122
|
+
|---------|---------|-----------|
|
|
123
|
+
| 新建广告投放 | 完整流程(场景1) | 按顺序:系列→组→关键词→广告 |
|
|
124
|
+
| 查看效果 | `campaign list` 或 GAQL | GAQL 获取详细指标 |
|
|
125
|
+
| 暂停/启用 | `campaign update --status` | PAUSED 或 ENABLED |
|
|
126
|
+
| 调整预算 | `campaign update --budget` | 单位美元 |
|
|
127
|
+
| 调整出价 | `ad-group update --cpc-bid` | 单位美元 |
|
|
128
|
+
| 添加关键词 | `keyword add` | 注意匹配类型 |
|
|
129
|
+
| 删除广告 | `campaign delete` / `ad delete` | 不可恢复,建议先暂停 |
|
|
130
|
+
|
|
131
|
+
## 自然语言映射
|
|
132
|
+
|
|
133
|
+
当用户说:
|
|
134
|
+
- "投放广告" / "创建广告" → 引导完整流程(场景1)
|
|
135
|
+
- "广告效果" / "看看数据" → `campaign list` + GAQL
|
|
136
|
+
- "暂停广告" → `campaign update --status PAUSED`
|
|
137
|
+
- "启用广告" → `campaign update --status ENABLED`
|
|
138
|
+
- "调整预算到 XX" → `campaign update --budget XX`
|
|
139
|
+
- "添加关键词 XX" → `keyword add -k "XX"`
|
|
140
|
+
- "删除广告" → 先确认,再执行删除
|
|
141
|
+
|
|
142
|
+
## 关键概念
|
|
143
|
+
|
|
144
|
+
### 广告层级结构
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
Account(账号)
|
|
148
|
+
└── Campaign(广告系列)- 设置预算
|
|
149
|
+
└── Ad Group(广告组)- 设置出价
|
|
150
|
+
├── Keywords(关键词)- 触发条件
|
|
151
|
+
└── Ads(广告)- 展示内容
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### 状态说明
|
|
155
|
+
|
|
156
|
+
| 状态 | 含义 |
|
|
157
|
+
|------|------|
|
|
158
|
+
| `ENABLED` | 正常投放中 |
|
|
159
|
+
| `PAUSED` | 已暂停 |
|
|
160
|
+
| `REMOVED` | 已删除 |
|
|
161
|
+
|
|
162
|
+
### 关键词匹配类型
|
|
163
|
+
|
|
164
|
+
| 类型 | 说明 |
|
|
165
|
+
|------|------|
|
|
166
|
+
| `BROAD` | 广泛匹配(默认) |
|
|
167
|
+
| `PHRASE` | 词组匹配 |
|
|
168
|
+
| `EXACT` | 精确匹配 |
|
|
169
|
+
|
|
170
|
+
### RSA 广告要求
|
|
171
|
+
|
|
172
|
+
- **标题**: 至少 3 个,最多 15 个(每个 ≤30 字符)
|
|
173
|
+
- **描述**: 至少 2 个,最多 4 个(每个 ≤90 字符)
|
|
174
|
+
|
|
175
|
+
## 常见问题
|
|
176
|
+
|
|
177
|
+
### 广告创建后没有展示
|
|
178
|
+
|
|
179
|
+
1. 检查状态是否 PAUSED → 启用它
|
|
180
|
+
2. 账号是否设置账单信息 → 去 Google Ads 后台设置
|
|
181
|
+
3. 关键词是否有搜索量 → 添加更多关键词
|
|
182
|
+
|
|
183
|
+
### 不知道广告效果好不好
|
|
184
|
+
|
|
185
|
+
用 GAQL 查询关键指标:
|
|
186
|
+
```bash
|
|
187
|
+
google-ads query -q "
|
|
188
|
+
SELECT campaign.name, metrics.impressions, metrics.clicks, metrics.ctr, metrics.conversions, metrics.cost_micros
|
|
189
|
+
FROM campaign WHERE segments.date DURING LAST_7_DAYS
|
|
190
|
+
"
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
**指标参考**:
|
|
194
|
+
- CTR > 2% = 良好
|
|
195
|
+
- CPC 看行业,一般 $0.5-2
|
|
196
|
+
|
|
197
|
+
### 关键词出价设多少
|
|
198
|
+
|
|
199
|
+
- 新广告先设 $1-2,观察效果
|
|
200
|
+
- 效果好提高出价,效果差降低或暂停
|
|
201
|
+
|
|
202
|
+
## 命令参考
|
|
203
|
+
|
|
204
|
+
### 账号
|
|
205
|
+
- `google-ads account check` - 检查 Google Ads 账号授权状态
|
|
206
|
+
|
|
207
|
+
### 广告系列
|
|
208
|
+
- `google-ads campaign list [--status ENABLED|PAUSED]` - 列出
|
|
209
|
+
- `google-ads campaign info <id>` - 详情
|
|
210
|
+
- `google-ads campaign create -n "名称" -b 预算` - 创建
|
|
211
|
+
- `google-ads campaign update --campaign-id <id> [--status|--budget|--name]` - 更新
|
|
212
|
+
- `google-ads campaign delete --campaign-id <id>` - 删除
|
|
213
|
+
|
|
214
|
+
### 广告组
|
|
215
|
+
- `google-ads ad-group list [--campaign-id <id>]` - 列出
|
|
216
|
+
- `google-ads ad-group info <id>` - 详情
|
|
217
|
+
- `google-ads ad-group create --campaign-id <id> -n "名称" [--cpc-bid 出价]` - 创建
|
|
218
|
+
- `google-ads ad-group update --ad-group-id <id> [--status|--cpc-bid|--name]` - 更新
|
|
219
|
+
- `google-ads ad-group delete --ad-group-id <id>` - 删除
|
|
220
|
+
|
|
221
|
+
### 关键词
|
|
222
|
+
- `google-ads keyword list [--campaign-id <id>]` - 列出
|
|
223
|
+
- `google-ads keyword add --ad-group-id <id> -k "词1,词2" [--match-type BROAD|PHRASE|EXACT]` - 添加
|
|
224
|
+
- `google-ads keyword update --keyword-id <id> --status` - 更新
|
|
225
|
+
- `google-ads keyword delete --keyword-id <id>` - 删除
|
|
226
|
+
|
|
227
|
+
### 广告
|
|
228
|
+
- `google-ads ad list [--ad-group-id <id>]` - 列出
|
|
229
|
+
- `google-ads ad info <id>` - 详情
|
|
230
|
+
- `google-ads ad create --ad-group-id <id> --headlines "..." --descriptions "..." --final-url "..."` - 创建
|
|
231
|
+
- `google-ads ad update --ad-id <id> --status` - 更新
|
|
232
|
+
- `google-ads ad delete --ad-id <id>` - 删除
|
|
233
|
+
|
|
234
|
+
### GAQL 查询
|
|
235
|
+
- `google-ads query -q "SELECT ... FROM ..."` - 执行查询
|
|
236
|
+
- `google-ads query -f query.gaql` - 从文件读取
|
|
237
|
+
|
|
238
|
+
## 重要提示
|
|
239
|
+
|
|
240
|
+
- **所有命令默认 JSON 输出**
|
|
241
|
+
- **预算和出价单位**:美元
|
|
242
|
+
- **新广告默认 PAUSED**:创建后需手动启用
|
|
243
|
+
- **删除不可恢复**:建议先暂停
|
package/dist/bin/bi-cli.js
CHANGED
|
File without changes
|
package/dist/bin/comfy.js
CHANGED
|
File without changes
|
package/dist/bin/commerce.js
CHANGED
|
File without changes
|
package/dist/bin/google-ads.js
CHANGED
|
File without changes
|
package/dist/bin/optima.js
CHANGED
|
File without changes
|
package/dist/bin/scout.js
CHANGED
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks-loader.d.ts","sourceRoot":"","sources":["../../src/hooks-loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAgB,MAAM,YAAY,CAAC;AAwL5D;;GAEG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,MAAM,MAAM,GAAG,SAAS,GACrC,WAAW,CAiFb"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { readFileSync, readdirSync, existsSync, writeFileSync, mkdirSync } from "fs";
|
|
2
|
+
import { join, dirname } from "path";
|
|
3
|
+
import yaml from "js-yaml";
|
|
4
|
+
import { execSync } from "child_process";
|
|
5
|
+
import { YamlValidator, formatValidationErrors, formatValidationWarning } from "./validation/index.js";
|
|
6
|
+
/**
|
|
7
|
+
* 从 SKILL.md 提取 YAML frontmatter
|
|
8
|
+
*/
|
|
9
|
+
function extractYamlFrontmatter(content) {
|
|
10
|
+
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
11
|
+
if (!match)
|
|
12
|
+
return null;
|
|
13
|
+
try {
|
|
14
|
+
return yaml.load(match[1]);
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
console.error("Failed to parse YAML frontmatter:", error);
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* 执行 shell 命令并返回结果
|
|
23
|
+
*/
|
|
24
|
+
function executeCommand(command, cwd, skillDir, sessionId) {
|
|
25
|
+
try {
|
|
26
|
+
// 替换环境变量
|
|
27
|
+
const expandedCommand = command
|
|
28
|
+
.replace(/\$\{CLAUDE_PLUGIN_ROOT\}/g, skillDir)
|
|
29
|
+
.replace(/\$\{SESSION_ID\}/g, sessionId || 'default');
|
|
30
|
+
const result = execSync(expandedCommand, {
|
|
31
|
+
cwd,
|
|
32
|
+
encoding: "utf-8",
|
|
33
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
34
|
+
});
|
|
35
|
+
return result.trim();
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
// 命令失败不阻塞,返回错误信息
|
|
39
|
+
return error.stdout || error.message || "";
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* 转换 skill hooks 为 SDK hooks 格式
|
|
44
|
+
*/
|
|
45
|
+
function convertSkillHooksToSdkHooks(skillHooks, skillDir, cwd, getSessionId, hookType) {
|
|
46
|
+
return skillHooks.map((hookConfig) => ({
|
|
47
|
+
matcher: hookConfig.matcher,
|
|
48
|
+
hooks: hookConfig.hooks.map((hook) => {
|
|
49
|
+
// SDK HookCallback 签名: (input, toolUseID, options) => Promise<HookJSONOutput>
|
|
50
|
+
return async (input, toolUseID, options) => {
|
|
51
|
+
// PreToolUse: 拦截并重定向 planning 文件操作
|
|
52
|
+
if (hookType === "PreToolUse" && input.tool_name && input.tool_input) {
|
|
53
|
+
const toolName = input.tool_name;
|
|
54
|
+
const toolInput = input.tool_input;
|
|
55
|
+
// 处理文件操作工具的路径重定向
|
|
56
|
+
if ((toolName === "Write" || toolName === "Read" || toolName === "Edit") && toolInput.file_path) {
|
|
57
|
+
const filePath = toolInput.file_path;
|
|
58
|
+
if (filePath.includes(".planning/default/")) {
|
|
59
|
+
const sessionId = getSessionId() || "default";
|
|
60
|
+
const updatedPath = filePath.replace(".planning/default/", `.planning/${sessionId}/`);
|
|
61
|
+
console.log(`[hooks-loader] Intercepting and redirecting: ${filePath} -> ${updatedPath}`);
|
|
62
|
+
// 手动执行文件操作并 return,不要继续到 command 部分
|
|
63
|
+
try {
|
|
64
|
+
console.log(`[hooks-loader] Inside try block, toolName=${toolName}`);
|
|
65
|
+
if (toolName === "Write") {
|
|
66
|
+
console.log(`[hooks-loader] Handling Write operation`);
|
|
67
|
+
// 创建目录
|
|
68
|
+
const dir = dirname(updatedPath);
|
|
69
|
+
if (!existsSync(dir)) {
|
|
70
|
+
mkdirSync(dir, { recursive: true });
|
|
71
|
+
}
|
|
72
|
+
// 写入文件
|
|
73
|
+
writeFileSync(updatedPath, toolInput.content || "", "utf-8");
|
|
74
|
+
console.log(`[hooks-loader] File written to ${updatedPath}`);
|
|
75
|
+
// Block 原始工具执行
|
|
76
|
+
return {
|
|
77
|
+
decision: "block",
|
|
78
|
+
systemMessage: `File written to session-specific directory`,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
else if (toolName === "Read") {
|
|
82
|
+
// 读取文件
|
|
83
|
+
if (existsSync(updatedPath)) {
|
|
84
|
+
const content = readFileSync(updatedPath, "utf-8");
|
|
85
|
+
console.log(`[hooks-loader] File read from ${updatedPath}`);
|
|
86
|
+
// Block 原始工具,返回文件内容
|
|
87
|
+
return {
|
|
88
|
+
decision: "block",
|
|
89
|
+
systemMessage: `File content:\n\n${content}`,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
return {
|
|
94
|
+
decision: "block",
|
|
95
|
+
systemMessage: `File not found: ${updatedPath}`,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
else if (toolName === "Edit") {
|
|
100
|
+
// Edit 需要读取、修改、写入
|
|
101
|
+
if (existsSync(updatedPath)) {
|
|
102
|
+
let content = readFileSync(updatedPath, "utf-8");
|
|
103
|
+
// 执行替换
|
|
104
|
+
if (toolInput.old_string && toolInput.new_string) {
|
|
105
|
+
if (toolInput.replace_all) {
|
|
106
|
+
content = content.split(toolInput.old_string).join(toolInput.new_string);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
content = content.replace(toolInput.old_string, toolInput.new_string);
|
|
110
|
+
}
|
|
111
|
+
writeFileSync(updatedPath, content, "utf-8");
|
|
112
|
+
console.log(`[hooks-loader] File edited at ${updatedPath}`);
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
decision: "block",
|
|
116
|
+
systemMessage: `File edited successfully`,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
return {
|
|
121
|
+
decision: "block",
|
|
122
|
+
systemMessage: `File not found: ${updatedPath}`,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
console.error(`[hooks-loader] Error:`, error);
|
|
129
|
+
return {
|
|
130
|
+
decision: "block",
|
|
131
|
+
systemMessage: `Error: ${error.message}`,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (hook.type === "command") {
|
|
138
|
+
const sessionId = getSessionId();
|
|
139
|
+
const result = executeCommand(hook.command, cwd, skillDir, sessionId);
|
|
140
|
+
// 如果有输出,作为系统消息返回
|
|
141
|
+
if (result) {
|
|
142
|
+
return {
|
|
143
|
+
continue: true,
|
|
144
|
+
systemMessage: result,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return { continue: true };
|
|
149
|
+
};
|
|
150
|
+
}),
|
|
151
|
+
}));
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* 从 skills 目录加载所有 skill 的 hooks
|
|
155
|
+
*/
|
|
156
|
+
export function loadSkillHooks(skillsDir, cwd, getSessionId) {
|
|
157
|
+
const hooks = {};
|
|
158
|
+
if (!existsSync(skillsDir)) {
|
|
159
|
+
return hooks;
|
|
160
|
+
}
|
|
161
|
+
const skillDirs = readdirSync(skillsDir, { withFileTypes: true })
|
|
162
|
+
.filter((dirent) => dirent.isDirectory())
|
|
163
|
+
.map((dirent) => dirent.name);
|
|
164
|
+
for (const skillName of skillDirs) {
|
|
165
|
+
const skillDir = join(skillsDir, skillName);
|
|
166
|
+
const skillMdPath = join(skillDir, "SKILL.md");
|
|
167
|
+
if (!existsSync(skillMdPath)) {
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
try {
|
|
171
|
+
const content = readFileSync(skillMdPath, "utf-8");
|
|
172
|
+
// 验证配置文件
|
|
173
|
+
const validator = new YamlValidator();
|
|
174
|
+
const validationResult = validator.validate(content, skillMdPath);
|
|
175
|
+
// 显示错误
|
|
176
|
+
if (!validationResult.valid) {
|
|
177
|
+
console.error(formatValidationErrors(validationResult.errors));
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
// 显示警告
|
|
181
|
+
if (validationResult.warnings && validationResult.warnings.length > 0) {
|
|
182
|
+
for (const warning of validationResult.warnings) {
|
|
183
|
+
console.warn(formatValidationWarning(warning));
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
const frontmatter = extractYamlFrontmatter(content);
|
|
187
|
+
if (!frontmatter?.hooks) {
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
// 转换各个 hook 事件
|
|
191
|
+
if (frontmatter.hooks.SessionStart) {
|
|
192
|
+
hooks.SessionStart = hooks.SessionStart || [];
|
|
193
|
+
hooks.SessionStart.push(...convertSkillHooksToSdkHooks(frontmatter.hooks.SessionStart, skillDir, cwd, getSessionId, "SessionStart"));
|
|
194
|
+
}
|
|
195
|
+
if (frontmatter.hooks.PreToolUse) {
|
|
196
|
+
hooks.PreToolUse = hooks.PreToolUse || [];
|
|
197
|
+
hooks.PreToolUse.push(...convertSkillHooksToSdkHooks(frontmatter.hooks.PreToolUse, skillDir, cwd, getSessionId, "PreToolUse"));
|
|
198
|
+
}
|
|
199
|
+
if (frontmatter.hooks.PostToolUse) {
|
|
200
|
+
hooks.PostToolUse = hooks.PostToolUse || [];
|
|
201
|
+
hooks.PostToolUse.push(...convertSkillHooksToSdkHooks(frontmatter.hooks.PostToolUse, skillDir, cwd, getSessionId, "PostToolUse"));
|
|
202
|
+
}
|
|
203
|
+
if (frontmatter.hooks.Stop) {
|
|
204
|
+
hooks.Stop = hooks.Stop || [];
|
|
205
|
+
hooks.Stop.push(...convertSkillHooksToSdkHooks(frontmatter.hooks.Stop, skillDir, cwd, getSessionId, "Stop"));
|
|
206
|
+
}
|
|
207
|
+
console.log(`[hooks-loader] Loaded hooks from skill: ${skillName}`);
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
console.error(`[hooks-loader] Failed to load hooks from ${skillName}:`, error);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return hooks;
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=hooks-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks-loader.js","sourceRoot":"","sources":["../../src/hooks-loader.ts"],"names":[],"mappings":"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"}
|