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 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.33),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-tso-cli`。
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 fetchOpts;
2535
+ let body;
2509
2536
  if (opts.ids && opts.ids.length > 1) {
2510
2537
  url = `${config.apiBaseUrl}/command/media-account-report/report/DeleteList`;
2511
- fetchOpts = { method: "DELETE", body: JSON.stringify(opts.ids) };
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
- fetchOpts = { method: "DELETE" };
2546
+ body = void 0;
2520
2547
  }
2521
2548
  try {
2522
- await apiFetch2(url, config, fetchOpts, opts.verbose);
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 apiFetch2(url, config, { method: "DELETE" }, opts.verbose);
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 apiFetch2(url, config, { method: "DELETE" }, opts.verbose);
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 apiFetch2(url, config, { method: "DELETE" }, opts.verbose);
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 apiFetch2(detailUrl, config, { method: "DELETE", body: JSON.stringify(campaign) }, opts.verbose);
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 apiFetch2(deleteUrl, config, { method: "DELETE", body: JSON.stringify(adgroup) }, opts.verbose);
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 apiFetch2(deleteUrl, config, { method: "DELETE", body: JSON.stringify(ad) }, opts.verbose);
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 apiFetch2(url, config, { method: "DELETE", body: JSON.stringify(body) }, opts.verbose);
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 apiFetch2(url, config, { method: "DELETE", body: JSON.stringify(ext) }, opts.verbose);
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 apiFetch2(url, config, { method: "DELETE", body: JSON.stringify(body) }, opts.verbose);
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 apiFetch2(url, config, { method: "DELETE", body: JSON.stringify(keyword) }, opts.verbose);
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 apiFetch2(url, config, { method: "DELETE", body: JSON.stringify(body) }, opts.verbose);
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
- const res = await rawRequest(url, { method: "DELETE", headers, body: bodyStr });
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)}
@@ -1,13 +1,20 @@
1
1
  ---
2
2
  name: siluzan-tso
3
3
  description: >-
4
- Use when the user needs to manage advertising on the Siluzan TSO platform:
5
- querying ad accounts / balance / spend data, opening new ad accounts
6
- (Google / TikTok / Yandex / Bing / Kwai), managing Google ad campaigns /
7
- groups / creatives / keywords (full CRUD), generating optimization reports,
8
- managing media transfers or invoices, viewing AI creation records and
9
- intelligent alerts, querying lead forms (TikTok / Meta), or running any
10
- AIGC ad-plan preparation workflow.
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
- ```
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "slug": "siluzan-tso",
3
- "version": "1.0.0-beta.33",
4
- "publishedAt": 1774518784168
3
+ "version": "1.0.0-beta.35",
4
+ "publishedAt": 1774524361117
5
5
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "siluzan-tso-cli",
3
- "version": "1.0.0-beta.33",
3
+ "version": "1.0.0-beta.35",
4
4
  "description": "Siluzan 广告账户管理 CLI — 查询账户、余额、消耗数据,管理绑定关系与充值。",
5
5
  "type": "module",
6
6
  "bin": {