siluzan-tso-cli 1.1.29-beta.14 → 1.1.29-beta.15

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
@@ -51,7 +51,7 @@ siluzan-tso init -d /path/to/skills # 写入自定义目录
51
51
  siluzan-tso init --force # 强制覆盖已存在文件
52
52
  ```
53
53
 
54
- > **注意**:当前为测试版(1.1.29-beta.14),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-tso-cli`。
54
+ > **注意**:当前为测试版(1.1.29-beta.15),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-tso-cli`。
55
55
 
56
56
  | 助手 | 建议 `--ai` |
57
57
  | ----------------------- | ------------------------------------ |
package/dist/index.js CHANGED
@@ -105394,6 +105394,18 @@ async function fetchAllAccountPages(media, pageSize, maxPages, config, verbose)
105394
105394
  }
105395
105395
 
105396
105396
  // src/commands/balance-scan/run.ts
105397
+ function balanceScanChunkSize(media) {
105398
+ switch (media) {
105399
+ case "BingV2":
105400
+ case "TikTok":
105401
+ case "Yandex":
105402
+ return 10;
105403
+ case "Kwai":
105404
+ return 20;
105405
+ default:
105406
+ return 100;
105407
+ }
105408
+ }
105397
105409
  async function runBalanceScan(opts) {
105398
105410
  let config = loadConfig(opts.token);
105399
105411
  if (opts.refreshDp) {
@@ -105452,59 +105464,54 @@ async function runBalanceScan(opts) {
105452
105464
  let balanceMap = /* @__PURE__ */ new Map();
105453
105465
  let overviewMap = /* @__PURE__ */ new Map();
105454
105466
  if (validIds.length > 0) {
105455
- const CHUNK = 100;
105467
+ const chunkSize = balanceScanChunkSize(media);
105456
105468
  const chunks = [];
105457
- for (let i = 0; i < validIds.length; i += CHUNK) chunks.push(validIds.slice(i, i + CHUNK));
105469
+ for (let i = 0; i < validIds.length; i += chunkSize) {
105470
+ chunks.push(validIds.slice(i, i + chunkSize));
105471
+ }
105458
105472
  process.stderr.write(
105459
- `\u23F3 [balance-scan] \u6709\u6548\u8D26\u6237 ${validIds.length} \u4E2A\uFF0C\u5206 ${chunks.length} \u6279\uFF1B\u4F59\u989D\u4E0E\u8FD1 7 \u65E5\u6D88\u8017\u5E76\u884C\u8BF7\u6C42\uFF08\u5355\u8BF7\u6C42\u6700\u957F\u7EA6 10 \u5206\u949F\uFF09\u3002
105473
+ `\u23F3 [balance-scan] \u6709\u6548\u8D26\u6237 ${validIds.length} \u4E2A\uFF0C\u5206 ${chunks.length} \u6279\uFF08\u6BCF\u6279 \u2264${chunkSize} \u6237\uFF09\uFF1B\u6309 Web \u8D26\u6237\u5217\u8868\u53E3\u5F84\u4E32\u884C\u62C9\u53D6\u6D88\u8017 \u2192 \u4F59\u989D\uFF08\u5355\u8BF7\u6C42\u6700\u957F\u7EA6 10 \u5206\u949F\uFF09\u3002
105460
105474
  `
105461
105475
  );
105462
- const logBalanceChunk = (idx, ids, m) => {
105476
+ for (let chunkIdx = 0; chunkIdx < chunks.length; chunkIdx++) {
105477
+ const ids = chunks[chunkIdx];
105463
105478
  process.stderr.write(
105464
- ` \u2713 [\u4F59\u989D] \u7B2C ${idx + 1}/${chunks.length} \u6279\u5B8C\u6210\uFF08${ids.length} \u6237 \u2192 ${m.size} \u6761\uFF09
105479
+ ` \u2192 [\u8FD17\u65E5\u6D88\u8017] \u7B2C ${chunkIdx + 1}/${chunks.length} \u6279\u8BF7\u6C42\u4E2D\uFF08${ids.length} \u6237\uFF09\u2026
105465
105480
  `
105466
105481
  );
105467
- };
105468
- const logOverviewChunk = (idx, ids, m) => {
105482
+ const overviewChunk = await fetchOverviewMap(
105483
+ media,
105484
+ ids,
105485
+ config,
105486
+ void 0,
105487
+ void 0,
105488
+ opts.verbose
105489
+ );
105469
105490
  process.stderr.write(
105470
- ` \u2713 [\u8FD17\u65E5\u6D88\u8017] \u7B2C ${idx + 1}/${chunks.length} \u6279\u5B8C\u6210\uFF08${ids.length} \u6237 \u2192 ${m.size} \u6761\uFF09
105491
+ ` \u2713 [\u8FD17\u65E5\u6D88\u8017] \u7B2C ${chunkIdx + 1}/${chunks.length} \u6279\u5B8C\u6210\uFF08${ids.length} \u6237 \u2192 ${overviewChunk.size} \u6761\uFF09
105471
105492
  `
105472
105493
  );
105473
- };
105474
- const [bMaps, oMaps] = await Promise.all([
105475
- Promise.all(
105476
- chunks.map((ids, chunkIdx) => {
105477
- process.stderr.write(
105478
- ` \u2192 [\u4F59\u989D] \u7B2C ${chunkIdx + 1}/${chunks.length} \u6279\u8BF7\u6C42\u4E2D\uFF08${ids.length} \u6237\uFF09\u2026
105494
+ for (const [k, v] of overviewChunk) overviewMap.set(k, v);
105495
+ process.stderr.write(
105496
+ ` \u2192 [\u4F59\u989D] \u7B2C ${chunkIdx + 1}/${chunks.length} \u6279\u8BF7\u6C42\u4E2D\uFF08${ids.length} \u6237\uFF09\u2026
105479
105497
  `
105480
- );
105481
- return fetchBalanceMap(media, ids, config, void 0, void 0, opts.verbose).then(
105482
- (m) => {
105483
- logBalanceChunk(chunkIdx, ids, m);
105484
- return m;
105485
- }
105486
- );
105487
- })
105488
- ),
105489
- Promise.all(
105490
- chunks.map((ids, chunkIdx) => {
105491
- process.stderr.write(
105492
- ` \u2192 [\u8FD17\u65E5\u6D88\u8017] \u7B2C ${chunkIdx + 1}/${chunks.length} \u6279\u8BF7\u6C42\u4E2D\uFF08${ids.length} \u6237\uFF09\u2026
105498
+ );
105499
+ const balanceChunk = await fetchBalanceMap(
105500
+ media,
105501
+ ids,
105502
+ config,
105503
+ void 0,
105504
+ void 0,
105505
+ opts.verbose
105506
+ );
105507
+ process.stderr.write(
105508
+ ` \u2713 [\u4F59\u989D] \u7B2C ${chunkIdx + 1}/${chunks.length} \u6279\u5B8C\u6210\uFF08${ids.length} \u6237 \u2192 ${balanceChunk.size} \u6761\uFF09
105493
105509
  `
105494
- );
105495
- return fetchOverviewMap(media, ids, config, void 0, void 0, opts.verbose).then(
105496
- (m) => {
105497
- logOverviewChunk(chunkIdx, ids, m);
105498
- return m;
105499
- }
105500
- );
105501
- })
105502
- )
105503
- ]);
105510
+ );
105511
+ for (const [k, v] of balanceChunk) balanceMap.set(k, v);
105512
+ }
105504
105513
  process.stderr.write(`\u23F3 [balance-scan] \u4F59\u989D\u4E0E\u6D88\u8017\u5DF2\u9F50\uFF0C\u6B63\u5728\u6309\u9608\u503C\u7B5B\u9009\u2026
105505
105514
  `);
105506
- for (const m of bMaps) for (const [k, v] of m) balanceMap.set(k, v);
105507
- for (const m of oMaps) for (const [k, v] of m) overviewMap.set(k, v);
105508
105515
  }
105509
105516
  const evaluated = [];
105510
105517
  for (const item of allItems) {
@@ -105561,6 +105568,7 @@ async function runBalanceScan(opts) {
105561
105568
  },
105562
105569
  pageSize,
105563
105570
  maxPages,
105571
+ batchChunkSize: validIds.length > 0 ? balanceScanChunkSize(media) : null,
105564
105572
  totalReported: total ?? null,
105565
105573
  generatedAt: (/* @__PURE__ */ new Date()).toISOString()
105566
105574
  };
@@ -105636,6 +105644,9 @@ function register9(program2) {
105636
105644
  ).requiredOption(
105637
105645
  "-m, --media <type>",
105638
105646
  "\u5A92\u4F53\u7C7B\u578B\uFF1AGoogle | TikTok | Yandex | BingV2 | Kwai\uFF08MetaAd \u63A5\u53E3\u672A\u5F00\u653E\u4F59\u989D\u67E5\u8BE2\uFF09"
105647
+ ).option(
105648
+ "-a, --accounts <ids>",
105649
+ "\u6307\u5B9A mediaCustomerId\uFF08\u9017\u53F7\u5206\u9694\uFF09\uFF1B\u8DF3\u8FC7\u6E05\u5355\u7FFB\u9875\uFF0C\u62C9\u53D6\u540E\u5168\u90E8\u8F93\u51FA\uFF08\u4E0D\u6309\u9608\u503C\u8FC7\u6EE4\uFF09"
105639
105650
  ).option(
105640
105651
  "--threshold-days <n>",
105641
105652
  "\u5269\u4F59\u7EED\u822A\u5929\u6570\u9608\u503C\uFF08\u9ED8\u8BA4 7\uFF0C\u6309\u8FD1 7 \u65E5\u65E5\u5747\u6D88\u8017\u4F30\u7B97\uFF09",
@@ -105661,6 +105672,7 @@ function register9(program2) {
105661
105672
  await runBalanceScan({
105662
105673
  token: opts.token,
105663
105674
  media: opts.media,
105675
+ accounts: opts.accounts,
105664
105676
  thresholdDays: opts.thresholdDays,
105665
105677
  minBalance: opts.minBalance,
105666
105678
  minDailySpend: opts.minDailySpend,
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "slug": "siluzan-tso",
3
- "version": "1.1.29-beta.14",
4
- "publishedAt": 1781667337678
3
+ "version": "1.1.29-beta.15",
4
+ "publishedAt": 1781680166141
5
5
  }
@@ -247,11 +247,7 @@ siluzan-tso ad batch diff --batch-id <taskId> --config-file ./campaign.json --js
247
247
  | 基础 | `customerName` / `campaign` 非空;`Budget > 0`;地理/语言至少 1 项 |
248
248
  | 网络 | `TargetPartnerSearchNetwork` 须 false;不可同时关闭 Google 搜索与搜索网络 |
249
249
  | RSA / 关键词 / 附加信息 | 标题 **15** 条、描述 **4** 条(须写满);字符上限、词面非空;RSA `Path1`/`Path2` 必填;SITELINK 行长度限制 |
250
- <<<<<<< HEAD
251
250
  | 否词误填 | `KeywordsForBatchJob` 含常见否词词根或与 `NegativeKeywordsForBatchJob` 重复 → **warnings**(不阻断,须 Agent 修正后再 create) |
252
251
  | 实务 | 日期格式与先后、出价策略与配套字段一致 |
253
- =======
254
- | 实务 | 日期格式与先后、出价策略与配套字段一致 |
255
- >>>>>>> b58a64bcff40d4987fd54f6ad3e0b79061bf833c
256
252
 
257
253
  `ad campaign-validate` 通过不保证 BatchJob 成功(例如仅写 `DestinationUrl` 未写 `Finalurl` 时 validate 仍可能 ✅)。异步结果用 `ad batch get` 轮询;`HasFailed` / 部分失败时用 `ad batch diff` 对照 JSON 补缺,系列级失败时改 JSON 重提,勿在半成品上反复整包创建。写操作须 `--commit`,见 `references/google-ads/google-ads.md` § ad campaign-create。
@@ -23,7 +23,6 @@
23
23
 
24
24
  ### Skill 内 Read 路径约定
25
25
 
26
- <<<<<<< HEAD
27
26
  | 类型 | 正确路径(相对 Skill 根目录) | 说明 |
28
27
  | ---- | ----------------------------- | ---- |
29
28
  | 命令 reference | `references/<域>/<文件>.md` | 如 `references/analytics/account-analytics.md` |
@@ -31,14 +30,6 @@
31
30
  | JSON 契约模板(结构) | `assets/*-template.json`、`assets/*.schema.json` 等 | **先 Read**;如 `assets/campaign-create-template.json` |
32
31
  | 契约说明 / 规则 | `assets/<文件>.md` | 与上表 JSON **成对** Read;如 `assets/campaign-create-template.md` |
33
32
  | HTML 终稿模板 | `report-templates/*.html` | 由 CLI `render` 使用,Agent 通常只 Read 对应 `.md` 纲要 |
34
- =======
35
- | 类型 | 正确路径(相对 Skill 根目录) | 说明 |
36
- | ---------------- | --------------------------------------- | -------------------------------------------------------- |
37
- | 命令 reference | `references/<域>/<文件>.md` | 如 `references/analytics/account-analytics.md` |
38
- | 报告纲要 | `references/report-templates/<文件>.md` | 如 `references/report-templates/google-period-report.md` |
39
- | JSON 契约 / 规则 | `assets/<文件>.md` | 如 `assets/website-diagnosis-rules.md` |
40
- | HTML 终稿模板 | `report-templates/*.html` | 由 CLI `render` 使用,Agent 通常只 Read 对应 `.md` 纲要 |
41
- >>>>>>> b58a64bcff40d4987fd54f6ad3e0b79061bf833c
42
33
 
43
34
  路由表若写 `analytics/…` 或 `report-templates/…` 而无 `references/` 前缀,**Read 时仍须加上 `references/`**(`assets/`、`report-templates/*.html` 除外)。
44
35
 
@@ -21,7 +21,6 @@
21
21
 
22
22
  ## 标准流水线
23
23
 
24
- <<<<<<< HEAD
25
24
  | 步 | 动作 | 文档/命令 |
26
25
  |----|------|-----------|
27
26
  | 1 | `list-accounts` 锁定 `account` / `customerName` / 币种 | `references/accounts/currency.md` |
@@ -36,20 +35,6 @@
36
35
  | 10 | 输出所有失败的内容与原因,并询问用户是否需要修改后单独添加到系列中如果用户要求是则读取 `references\google-ads/google-ads.md` 来获取对应缺失部分的创建命令 |
37
36
 
38
37
 
39
- =======
40
- | 步 | 动作 | 文档/命令 |
41
- | --- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------- |
42
- | 1 | `list-accounts` 锁定 `account` / `customerName` / 币种 | `references/accounts/currency.md` |
43
- | 2 | 可选 `rag query`;`keyword` / `keyword geo-list` 拓词 | `references/analytics/keyword-planner-workflows.md` |
44
- | 3 | 按分层规则写入 `KeywordsForBatchJob`(Exact/Phrase/Broad) | `google-ads/rules/google-ads-keyword-taxonomy.md`(参考,非 CLI 强制) |
45
- | 4 | 填 `campaign`(预算/出价/地域/否词≥20/RSA/附加信息) | `assets/campaign-create-template.md` |
46
- | 5 | **`ad campaign-validate --config-file <json>`**(失败只改 JSON;超长见下文「超长人工确认」) | 下文「校验」 |
47
- | 6 | 输出:**JSON 代码块** → **Markdown**(`google-ads-launch-plan-template.md` 正文)→ 待确认 | — |
48
- | 7 | 用户确认后 **`ad campaign-create`** | `google-ads/google-ads.md` |
49
- | 8 | 每隔5s 获取创建结果 | `ad batch get --id <taskId> --config-file ./campaign.json` |
50
- | 9 | 创建失败根据失败原因修改json重新走创建流程,部分成功/成功/部分失败:都调用来做最后一步调整 `ad batch diff --batch-id <taskId> --config-file ./campaign.json` | |
51
- | 10 | 输出所有失败的内容与原因,并询问用户是否需要修改后单独添加到系列中如果用户要求是则读取 `references\google-ads/google-ads.md` 来获取对应缺失部分的创建命令 |
52
- >>>>>>> b58a64bcff40d4987fd54f6ad3e0b79061bf833c
53
38
 
54
39
  多系列:每系列一个 JSON;可选 `campaign-manifest.json`(`role: brand|competitor|generic`)仅作文件组织参考。
55
40
 
@@ -66,11 +51,7 @@
66
51
  | `google-ads/rules/sensitive-industries.md` | 敏感行业(若相关) |
67
52
  | `google-ads/rules/google-ads-launch-plan-template.md` | 用户可见 Markdown 结构与 RSA/否词表 |
68
53
  | `google-ads/rules/google-ads-creative-optimization.md` | RSA 创意主题;`campaign-validate` 强制 **15** 标题 + **4** 描述 |
69
- <<<<<<< HEAD
70
54
  | **`assets/campaign-create-template.json`** + `assets/campaign-create-template.md` | JSON 结构(先 Read `.json`)+ 字段说明 |
71
- =======
72
- | `assets/campaign-create-template.md` | JSON 字段契约 |
73
- >>>>>>> b58a64bcff40d4987fd54f6ad3e0b79061bf833c
74
55
 
75
56
  ### 按需(触及时再读)
76
57
 
@@ -7,7 +7,6 @@
7
7
 
8
8
  ## 结构数量(每广告系列 / 每广告组)
9
9
 
10
- <<<<<<< HEAD
11
10
  | 模块 | 规则 | 建议数量 | 示例 |
12
11
  |------|------|----------|------|
13
12
  | Campaign | 按产品线拆分 | 3–10 个系列(多文件 + `campaign-manifest.json`) | Payment Gateway / CRM |
@@ -31,21 +30,6 @@
31
30
  | 品牌系列 | 独立 Campaign | manifest `role: brand` | company crm |
32
31
  | 竞品系列 | 独立 Campaign | manifest `role: competitor` | stripe alternative |
33
32
  | Search Terms | 运营节奏 | 每周检查 | `ad search-terms` |
34
- =======
35
- | 模块 | 规则 | 建议数量 | 示例 |
36
- | ------------ | ------------------ | ------------------------------------------------ | ----------------------- |
37
- | Campaign | 按产品线拆分 | 3–10 个系列(多文件 + `campaign-manifest.json`) | Payment Gateway / CRM |
38
- | Ad Group | 一个搜索意图一组 | 每组 5–20 个词 | Payment API Integration |
39
- | 核心词 | 高商业意图 | 每组 **5–15** | payment api pricing |
40
- | 长尾词 | 场景明确的长 query | 每组 **10–25** | crm for manufacturing |
41
- | Exact Match | 核心高转化 | 每组 **2–8** 条 | [stripe alternative] |
42
- | Phrase Match | 主流量 | 每组 **3–10** 条 | "payment solution" |
43
- | Broad Match | 少量测试 | 每组 **1–3** 条 | payment platform |
44
- | 否定关键词 | 基础否词库 | 系列级建议 **≥20** | free / jobs / tutorial |
45
- | 品牌系列 | 独立 Campaign | manifest `role: brand` | company crm |
46
- | 竞品系列 | 独立 Campaign | manifest `role: competitor` | stripe alternative |
47
- | Search Terms | 运营节奏 | 每周检查 | `ad search-terms` |
48
- >>>>>>> b58a64bcff40d4987fd54f6ad3e0b79061bf833c
49
33
 
50
34
  ### 初始匹配类型占比(按组内词条数)
51
35
 
@@ -9,7 +9,7 @@ $ErrorActionPreference = 'Stop'
9
9
  # -- Package info (injected at build time) ------------------------------------
10
10
  $PKG_NAME = 'siluzan-tso-cli'
11
11
  # PKG_VERSION 锁定到与本脚本同批构建产物一致的版本,避免与 dist/skill 错位
12
- $PKG_VERSION = '1.1.29-beta.14'
12
+ $PKG_VERSION = '1.1.29-beta.15'
13
13
  $CLI_BIN = 'siluzan-tso'
14
14
  $SKILL_LABEL = 'Siluzan TSO'
15
15
  $INSTALL_CMD = 'npm install -g siluzan-tso-cli@beta'
@@ -9,7 +9,7 @@ set -euo pipefail
9
9
  # -- Package info (injected at build time) ------------------------------------
10
10
  readonly PKG_NAME="siluzan-tso-cli"
11
11
  # PKG_VERSION 锁定到与本脚本同批构建产物一致的版本,避免与 dist/skill 错位
12
- readonly PKG_VERSION="1.1.29-beta.14"
12
+ readonly PKG_VERSION="1.1.29-beta.15"
13
13
  readonly CLI_BIN="siluzan-tso"
14
14
  readonly SKILL_LABEL="Siluzan TSO"
15
15
  readonly INSTALL_CMD="npm install -g siluzan-tso-cli@beta"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "siluzan-tso-cli",
3
- "version": "1.1.29-beta.14",
3
+ "version": "1.1.29-beta.15",
4
4
  "description": "Siluzan 广告账户管理 CLI — 查询账户、余额、消耗数据,管理绑定关系与充值。",
5
5
  "keywords": [
6
6
  "ad-account",