siluzan-tso-cli 1.0.0-beta.33 → 1.0.0-beta.35
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/README.md +1 -1
- package/dist/index.js +43 -39
- package/dist/skill/SKILL.md +16 -52
- package/dist/skill/_meta.json +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ siluzan-tso init -d /path/to/skills # 写入自定义目录
|
|
|
20
20
|
siluzan-tso init --force # 强制覆盖已存在文件
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
> **注意**:当前为测试版(1.0.0-beta.
|
|
23
|
+
> **注意**:当前为测试版(1.0.0-beta.35),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-tso-cli`。
|
|
24
24
|
|
|
25
25
|
| 助手 | 建议 `--ai` |
|
|
26
26
|
|------|-------------|
|
package/dist/index.js
CHANGED
|
@@ -873,6 +873,33 @@ function apiFetch2(url, config, options = {}, verbose = false) {
|
|
|
873
873
|
function apiFetchWithHeaders2(url, config, options = {}, verbose = false) {
|
|
874
874
|
return apiFetchWithHeaders(url, config, options, verbose);
|
|
875
875
|
}
|
|
876
|
+
async function apiDeleteRaw(url, config, options = {}) {
|
|
877
|
+
const bodyStr = options.body ?? "";
|
|
878
|
+
const headers = {
|
|
879
|
+
"Content-Type": "application/json; charset=utf-8",
|
|
880
|
+
Accept: "application/json, text/plain, */*",
|
|
881
|
+
"Accept-Language": "zh-CN",
|
|
882
|
+
...config.apiKey ? { "x-api-key": config.apiKey } : { Authorization: `Bearer ${config.authToken}` },
|
|
883
|
+
Datapermission: config.dataPermission ?? "",
|
|
884
|
+
"Content-Length": String(Buffer.byteLength(bodyStr, "utf8"))
|
|
885
|
+
};
|
|
886
|
+
const res = await rawRequest(url, {
|
|
887
|
+
method: "DELETE",
|
|
888
|
+
headers,
|
|
889
|
+
body: bodyStr.length > 0 ? bodyStr : void 0
|
|
890
|
+
});
|
|
891
|
+
const text = res.text;
|
|
892
|
+
if (res.status < 200 || res.status >= 300) {
|
|
893
|
+
const detail = options.verbose ? `\uFF1A${text.slice(0, 300)}` : "";
|
|
894
|
+
throw new Error(`HTTP ${res.status}${detail}`);
|
|
895
|
+
}
|
|
896
|
+
if (!text.trim()) return null;
|
|
897
|
+
try {
|
|
898
|
+
return JSON.parse(text);
|
|
899
|
+
} catch {
|
|
900
|
+
return text;
|
|
901
|
+
}
|
|
902
|
+
}
|
|
876
903
|
|
|
877
904
|
// src/commands/config.ts
|
|
878
905
|
function deriveWebUrl(apiBaseUrl) {
|
|
@@ -2505,10 +2532,10 @@ async function runReportCreate(opts) {
|
|
|
2505
2532
|
async function runReportDelete(opts) {
|
|
2506
2533
|
const config = loadConfig(opts.token);
|
|
2507
2534
|
let url;
|
|
2508
|
-
let
|
|
2535
|
+
let body;
|
|
2509
2536
|
if (opts.ids && opts.ids.length > 1) {
|
|
2510
2537
|
url = `${config.apiBaseUrl}/command/media-account-report/report/DeleteList`;
|
|
2511
|
-
|
|
2538
|
+
body = JSON.stringify(opts.ids);
|
|
2512
2539
|
} else {
|
|
2513
2540
|
const id = opts.id ?? opts.ids?.[0];
|
|
2514
2541
|
if (!id) {
|
|
@@ -2516,10 +2543,10 @@ async function runReportDelete(opts) {
|
|
|
2516
2543
|
process.exit(1);
|
|
2517
2544
|
}
|
|
2518
2545
|
url = `${config.apiBaseUrl}/command/media-account-report/report/${id}`;
|
|
2519
|
-
|
|
2546
|
+
body = void 0;
|
|
2520
2547
|
}
|
|
2521
2548
|
try {
|
|
2522
|
-
await
|
|
2549
|
+
await apiDeleteRaw(url, config, { body, verbose: opts.verbose });
|
|
2523
2550
|
} catch (err) {
|
|
2524
2551
|
console.error(`
|
|
2525
2552
|
\u274C \u5220\u9664\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
|
|
@@ -2617,7 +2644,7 @@ async function runReportPushDelete(opts) {
|
|
|
2617
2644
|
const config = loadConfig(opts.token);
|
|
2618
2645
|
const url = `${config.apiBaseUrl}/command/report-push/settings/${opts.media}/${opts.id}`;
|
|
2619
2646
|
try {
|
|
2620
|
-
await
|
|
2647
|
+
await apiDeleteRaw(url, config, { verbose: opts.verbose });
|
|
2621
2648
|
} catch (err) {
|
|
2622
2649
|
console.error(`
|
|
2623
2650
|
\u274C \u5220\u9664\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
|
|
@@ -4276,7 +4303,7 @@ async function runInvoiceInfoDelete(opts) {
|
|
|
4276
4303
|
const config = loadConfig(opts.token);
|
|
4277
4304
|
const url = `${config.apiBaseUrl}/InvoiceInfos/${opts.id}`;
|
|
4278
4305
|
try {
|
|
4279
|
-
await
|
|
4306
|
+
await apiDeleteRaw(url, config, { verbose: opts.verbose });
|
|
4280
4307
|
} catch (err) {
|
|
4281
4308
|
console.error(`
|
|
4282
4309
|
\u274C \u5220\u9664\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
|
|
@@ -5630,7 +5657,7 @@ async function runForewarningDelete(opts) {
|
|
|
5630
5657
|
const config = loadConfig(opts.token);
|
|
5631
5658
|
const url = `${config.apiBaseUrl}/command/smart-strategy/settings/${opts.media}/${opts.id}`;
|
|
5632
5659
|
try {
|
|
5633
|
-
await
|
|
5660
|
+
await apiDeleteRaw(url, config, { verbose: opts.verbose });
|
|
5634
5661
|
} catch (err) {
|
|
5635
5662
|
console.error(`
|
|
5636
5663
|
\u274C \u5220\u9664\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
|
|
@@ -6258,7 +6285,7 @@ async function runAdCampaignDelete(opts) {
|
|
|
6258
6285
|
process.exit(1);
|
|
6259
6286
|
}
|
|
6260
6287
|
try {
|
|
6261
|
-
await
|
|
6288
|
+
await apiDeleteRaw(detailUrl, config, { body: JSON.stringify(campaign), verbose: opts.verbose });
|
|
6262
6289
|
} catch (err) {
|
|
6263
6290
|
console.error(`
|
|
6264
6291
|
\u274C \u5220\u9664\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
|
|
@@ -6338,7 +6365,7 @@ async function runAdGroupDelete(opts) {
|
|
|
6338
6365
|
}
|
|
6339
6366
|
const deleteUrl = `${googleApiUrl}/adgroupnmanagement/adgroup/${opts.account}/${opts.id}`;
|
|
6340
6367
|
try {
|
|
6341
|
-
await
|
|
6368
|
+
await apiDeleteRaw(deleteUrl, config, { body: JSON.stringify(adgroup), verbose: opts.verbose });
|
|
6342
6369
|
} catch (err) {
|
|
6343
6370
|
console.error(`
|
|
6344
6371
|
\u274C \u5220\u9664\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
|
|
@@ -6439,7 +6466,7 @@ async function runAdDelete(opts) {
|
|
|
6439
6466
|
}
|
|
6440
6467
|
const deleteUrl = `${googleApiUrl}/admanagement/campaign/${opts.account}/${opts.id}`;
|
|
6441
6468
|
try {
|
|
6442
|
-
await
|
|
6469
|
+
await apiDeleteRaw(deleteUrl, config, { body: JSON.stringify(ad), verbose: opts.verbose });
|
|
6443
6470
|
} catch (err) {
|
|
6444
6471
|
console.error(`
|
|
6445
6472
|
\u274C \u5220\u9664\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
|
|
@@ -6737,7 +6764,7 @@ async function runAdKeywordDelete(opts) {
|
|
|
6737
6764
|
const body = [{ adGroupId: opts.adgroupId, id: opts.id }];
|
|
6738
6765
|
const url = `${googleApiUrl}/keywordmanagement/Keyword/${opts.account}/batch`;
|
|
6739
6766
|
try {
|
|
6740
|
-
await
|
|
6767
|
+
await apiDeleteRaw(url, config, { body: JSON.stringify(body), verbose: opts.verbose });
|
|
6741
6768
|
} catch (err) {
|
|
6742
6769
|
console.error(`
|
|
6743
6770
|
\u274C \u5220\u9664\u5173\u952E\u8BCD\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
|
|
@@ -6967,7 +6994,7 @@ async function runAdExtensionDelete(opts) {
|
|
|
6967
6994
|
}
|
|
6968
6995
|
const url = `${googleApiUrl}/extensionmanagement/extension/${opts.account}/${opts.id}`;
|
|
6969
6996
|
try {
|
|
6970
|
-
await
|
|
6997
|
+
await apiDeleteRaw(url, config, { body: JSON.stringify(ext), verbose: opts.verbose });
|
|
6971
6998
|
} catch (err) {
|
|
6972
6999
|
console.error(`
|
|
6973
7000
|
\u274C \u5220\u9664\u9644\u52A0\u4FE1\u606F\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
|
|
@@ -7146,7 +7173,7 @@ async function runAdGeoRemove(opts) {
|
|
|
7146
7173
|
const body = { campaignId: opts.campaignId, id: opts.locationId };
|
|
7147
7174
|
const url = `${googleApiUrl}/campaignmanagement/criterion/${opts.account}?campaignId=${opts.campaignId}`;
|
|
7148
7175
|
try {
|
|
7149
|
-
await
|
|
7176
|
+
await apiDeleteRaw(url, config, { body: JSON.stringify(body), verbose: opts.verbose });
|
|
7150
7177
|
} catch (err) {
|
|
7151
7178
|
console.error(`
|
|
7152
7179
|
\u274C \u5220\u9664\u5730\u7406\u4F4D\u7F6E\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
|
|
@@ -7175,7 +7202,7 @@ async function runAdNegativeKeywordDelete(opts) {
|
|
|
7175
7202
|
}
|
|
7176
7203
|
const url = `${googleApiUrl}/negativekeywordmanagement/negativekeyword/${opts.account}/${opts.id}`;
|
|
7177
7204
|
try {
|
|
7178
|
-
await
|
|
7205
|
+
await apiDeleteRaw(url, config, { body: JSON.stringify(keyword), verbose: opts.verbose });
|
|
7179
7206
|
} catch (err) {
|
|
7180
7207
|
console.error(`
|
|
7181
7208
|
\u274C \u5220\u9664\u5426\u5B9A\u5173\u952E\u8BCD\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
|
|
@@ -8035,7 +8062,7 @@ async function runAccountBcUnbind(opts) {
|
|
|
8035
8062
|
const body = [{ bcId: opts.bcId, mediacustomerIds: opts.customers }];
|
|
8036
8063
|
let result;
|
|
8037
8064
|
try {
|
|
8038
|
-
result = await
|
|
8065
|
+
result = await apiDeleteRaw(url, config, { body: JSON.stringify(body), verbose: opts.verbose });
|
|
8039
8066
|
} catch (err) {
|
|
8040
8067
|
console.error(`
|
|
8041
8068
|
\u274C BC \u89E3\u7ED1\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
|
|
@@ -8259,32 +8286,9 @@ async function runAccountEmailDeauth(opts) {
|
|
|
8259
8286
|
AgentType: opts.agentType,
|
|
8260
8287
|
resourceName
|
|
8261
8288
|
};
|
|
8262
|
-
const bodyStr = JSON.stringify(body);
|
|
8263
|
-
const headers = {
|
|
8264
|
-
"Content-Type": "application/json; charset=utf-8",
|
|
8265
|
-
Accept: "application/json, text/plain, */*",
|
|
8266
|
-
"Accept-Language": "zh-CN",
|
|
8267
|
-
...config.apiKey ? { "x-api-key": config.apiKey } : { Authorization: `Bearer ${config.authToken}` },
|
|
8268
|
-
Datapermission: config.dataPermission ?? "",
|
|
8269
|
-
"Content-Length": String(Buffer.byteLength(bodyStr, "utf8"))
|
|
8270
|
-
};
|
|
8271
8289
|
let result;
|
|
8272
8290
|
try {
|
|
8273
|
-
|
|
8274
|
-
const text = res.text;
|
|
8275
|
-
if (res.status < 200 || res.status >= 300) {
|
|
8276
|
-
const detail = opts.verbose ? `\uFF1A${text.slice(0, 300)}` : "";
|
|
8277
|
-
throw new Error(`HTTP ${res.status}${detail}`);
|
|
8278
|
-
}
|
|
8279
|
-
if (!text.trim()) {
|
|
8280
|
-
result = null;
|
|
8281
|
-
} else {
|
|
8282
|
-
try {
|
|
8283
|
-
result = JSON.parse(text);
|
|
8284
|
-
} catch {
|
|
8285
|
-
result = text;
|
|
8286
|
-
}
|
|
8287
|
-
}
|
|
8291
|
+
result = await apiDeleteRaw(url, config, { body: JSON.stringify(body), verbose: opts.verbose });
|
|
8288
8292
|
} catch (err) {
|
|
8289
8293
|
console.error(`
|
|
8290
8294
|
\u274C \u89E3\u9664\u90AE\u7BB1\u6388\u6743\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
|
package/dist/skill/SKILL.md
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: siluzan-tso
|
|
3
3
|
description: >-
|
|
4
|
-
Use when the user
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
4
|
+
Use when the user works with Siluzan TSO (advertising ops): OAuth login,
|
|
5
|
+
config, CLI/skill update and init; list accounts, balance, spend stats, and
|
|
6
|
+
open-account application history; open Google / TikTok / Yandex / BingV2 /
|
|
7
|
+
Kwai accounts (non-interactive CLI, interactive Google wizard, and
|
|
8
|
+
industry/timezone lookup helpers); account lifecycle (add OAuth, delink,
|
|
9
|
+
share/unshare, Google MCC bind/unbind, Meta BM bind, TikTok BC bind/unbind,
|
|
10
|
+
TikTok close, suspended-Google withdraw, Google email access invites);
|
|
11
|
+
optimization reports, report email push, Meta/TikTok/Bing account analytics,
|
|
12
|
+
and Google analysis via the configured gateway; inter-account transfers;
|
|
13
|
+
invoices plus invoice billing profiles (invoice-info); AI smart campaigns
|
|
14
|
+
(list/get/publish/update) and AIGC data prep or one-shot create; AI ad
|
|
15
|
+
optimization and intelligent forewarning; TikTok/Meta lead forms; full Google
|
|
16
|
+
Ads management including extensions, geo targeting, and search terms, plus
|
|
17
|
+
keyword suggestions (requires googleApiUrl); Google diagnostic link.
|
|
11
18
|
Do NOT use for content publishing (videos / images) — use siluzan-cso instead.
|
|
12
19
|
---
|
|
13
20
|
|
|
@@ -73,7 +80,6 @@ description: >-
|
|
|
73
80
|
| TSO 首页(网页) | `config show` 取 `webUrl` → `{webUrl}/v3/foreign_trade/tso/home` |
|
|
74
81
|
| 查广告主组(TikTok 等取 magKey) | `siluzan-tso open-account list-groups` |
|
|
75
82
|
| Google 开户(脚本) | `siluzan-tso open-account google --company "…" --promotion-link "…" --promotion-type b2c ...`(**无需 magKey**) |
|
|
76
|
-
|
|
77
83
|
| Google 开户时区列表 | `siluzan-tso open-account google-timezones`(可加 `--keyword`) |
|
|
78
84
|
| TikTok 开户时区列表 | `siluzan-tso open-account tiktok-timezones`(可加 `--keyword`) |
|
|
79
85
|
| TikTok 行业列表 | `siluzan-tso open-account tiktok-industries`(两级结构,传叶子节点 ID) |
|
|
@@ -142,8 +148,8 @@ CLI 命令执行后可能在输出末尾出现以下两种标记,Agent 必须
|
|
|
142
148
|
---
|
|
143
149
|
|
|
144
150
|
## AI 行为规范
|
|
145
|
-
|
|
146
|
-
- **先查账户再操作**:对具体账户做操作前,先通过 `list-accounts` 确认 ID
|
|
151
|
+
- **合理使用命令行的帮助功能**:使用命令前,调用-h查看命令有哪些参数
|
|
152
|
+
- **先查账户再操作**:对具体账户做操作前,先通过 `list-accounts -m [mediaType] -k {id}` 确认 ID。特别是不确定是Google/Bing/TikTok这些媒体平台中的哪一个的时候
|
|
147
153
|
- **使用 --json 处理数据**:需对返回数据做计算或筛选时,加 `--json`,再用 `node -e` 过滤提取(见 `references/tips.md`)。
|
|
148
154
|
- **不要猜测账户 ID**:`entityId` ≠ `mediaCustomerId`,两者均来自 `list-accounts`。
|
|
149
155
|
- **媒体类型区分大小写**:`Google`、`TikTok`、`MetaAd`、`BingV2`、`Kwai`。
|
|
@@ -155,45 +161,3 @@ CLI 命令执行后可能在输出末尾出现以下两种标记,Agent 必须
|
|
|
155
161
|
- **报告目录优先级**:生成报告时,先读 `report-templates/*.md` 定义内容,再读 `report-template*.html` 选择样式;**内容优先级永远高于样式**。
|
|
156
162
|
- **不确定时读文档**:遇到不熟悉的命令,先读对应 references 文件,不要猜参数。
|
|
157
163
|
|
|
158
|
-
---
|
|
159
|
-
|
|
160
|
-
## 用户习惯记录(User Adaptations)
|
|
161
|
-
|
|
162
|
-
### Skill 文件只读原则
|
|
163
|
-
|
|
164
|
-
**Agent 不得修改本目录中的任何 Skill 文件**(包括 `SKILL.md`、`references/*.md`、`report-templates/*.md`、`EVAL-HARNESS.md`)。
|
|
165
|
-
执行 `siluzan-tso update` 时,这些文件会被 Skill 包覆盖,手动修改会丢失。
|
|
166
|
-
|
|
167
|
-
### 用户习惯写入 user-adaptations.md
|
|
168
|
-
|
|
169
|
-
当 Agent 在会话中观察到用户习惯、偏好或项目级配置时,将其**追加**到本 Skill 目录下的 `user-adaptations.md`:
|
|
170
|
-
|
|
171
|
-
```
|
|
172
|
-
.cursor/skills/siluzan-tso/user-adaptations.md
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
此文件**不属于 Skill 包**,`siluzan-tso update` 时不会覆盖。
|
|
176
|
-
|
|
177
|
-
### 触发条件(何时写入)
|
|
178
|
-
|
|
179
|
-
满足以下任一条件时,主动写入 `user-adaptations.md`:
|
|
180
|
-
1. 用户明确告知一个偏好("我不需要看声明"、"默认用这个账户"等)
|
|
181
|
-
2. 同一会话中用户连续 2 次以上纠正相同行为
|
|
182
|
-
3. 用户说"记住这个"、"以后都这样"等明确保存意图的表达
|
|
183
|
-
|
|
184
|
-
### 何时读取
|
|
185
|
-
|
|
186
|
-
每次新会话开始时,检查 `user-adaptations.md` 是否存在:
|
|
187
|
-
- **存在**:读取并作为本项目的补充规则(优先级低于官方 Skill 文档,但高于默认行为)
|
|
188
|
-
- **不存在**:正常执行,无需创建空文件
|
|
189
|
-
|
|
190
|
-
### 条目格式
|
|
191
|
-
|
|
192
|
-
```markdown
|
|
193
|
-
### [YYYY-MM-DD] <一句话描述>
|
|
194
|
-
|
|
195
|
-
- **类别**:[报告习惯 / 命令偏好 / 账户配置 / 流程偏好 / 其他]
|
|
196
|
-
- **观察**:<具体的用户行为或明确表达>
|
|
197
|
-
- **适配规则**:<本项目中 Agent 应当如何调整>
|
|
198
|
-
- **来源**:[用户明确告知 / 会话观察]
|
|
199
|
-
```
|
package/dist/skill/_meta.json
CHANGED