siluzan-tso-cli 1.1.13 → 1.1.14-beta.1

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
@@ -45,7 +45,7 @@ HTML 报告模板引用以下 CDN:`cdn.tailwindcss.com`、`cdnjs.cloudflare.co
45
45
  在**用户的目标项目根目录**执行(根据用户使用的助手选择 `--ai`):
46
46
 
47
47
  ```bash
48
- npm install -g siluzan-tso-cli
48
+ npm install -g siluzan-tso-cli@beta
49
49
  siluzan-tso init --ai cursor # 写入 Cursor(默认)
50
50
  siluzan-tso init --ai cursor,claude # 同时写入多个平台
51
51
  siluzan-tso init --ai all # 写入所有支持的平台
@@ -53,6 +53,7 @@ siluzan-tso init -d /path/to/skills # 写入自定义目录
53
53
  siluzan-tso init --force # 强制覆盖已存在文件
54
54
  ```
55
55
 
56
+ > **注意**:当前为测试版(1.1.14-beta.1),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-tso-cli`。
56
57
 
57
58
  | 助手 | 建议 `--ai` |
58
59
  | ----------------------- | ------------------------------------ |
package/dist/index.js CHANGED
@@ -1962,7 +1962,7 @@ import { fileURLToPath as fileURLToPath4 } from "url";
1962
1962
  import { Command } from "commander";
1963
1963
 
1964
1964
  // src/config/defaults.ts
1965
- var DEFAULT_API_BASE = "https://tso-api.siluzan.com";
1965
+ var DEFAULT_API_BASE = "https://tso-api-ci.siluzan.com";
1966
1966
 
1967
1967
  // ../common/dist/index.js
1968
1968
  import * as fs from "fs";
@@ -2441,19 +2441,19 @@ import * as fs3 from "fs/promises";
2441
2441
  import * as path3 from "path";
2442
2442
  async function getSkillFiles(skillDir) {
2443
2443
  const out = {};
2444
- async function walk(dir, prefix) {
2444
+ async function walk2(dir, prefix) {
2445
2445
  const entries = await fs3.readdir(dir, { withFileTypes: true });
2446
2446
  for (const ent of entries) {
2447
2447
  const rel = prefix ? `${prefix}/${ent.name}` : ent.name;
2448
2448
  const full = path3.join(dir, ent.name);
2449
2449
  if (ent.isDirectory()) {
2450
- await walk(full, rel);
2450
+ await walk2(full, rel);
2451
2451
  } else {
2452
2452
  out[rel] = await fs3.readFile(full, "utf8");
2453
2453
  }
2454
2454
  }
2455
2455
  }
2456
- await walk(skillDir, "");
2456
+ await walk2(skillDir, "");
2457
2457
  return out;
2458
2458
  }
2459
2459
 
@@ -5070,6 +5070,37 @@ async function runReportPushReceiveEmails(opts) {
5070
5070
  console.log();
5071
5071
  }
5072
5072
 
5073
+ // src/utils/strip-legacy-google-fields.ts
5074
+ var LEGACY_WHEN_V2_PRESENT = [
5075
+ ["status", "statusV2"],
5076
+ ["channelType", "channelTypeV2"],
5077
+ ["subChannelType", "subChannelTypeV2"],
5078
+ ["biddingStrategyType", "biddingStrategyTypeV2"],
5079
+ ["campaignStatus", "campaignStatusV2"],
5080
+ ["adGroupStatus", "adGroupStatusV2"],
5081
+ ["matchType", "matchTypeV2"],
5082
+ ["type", "typeV2"]
5083
+ ];
5084
+ function stripLegacyGoogleFieldsIfV2Present(value) {
5085
+ return walk(value);
5086
+ }
5087
+ function walk(obj) {
5088
+ if (Array.isArray(obj)) return obj.map(walk);
5089
+ if (obj !== null && typeof obj === "object") {
5090
+ const o = { ...obj };
5091
+ for (const [legacy, modern] of LEGACY_WHEN_V2_PRESENT) {
5092
+ if (modern in o && legacy in o) {
5093
+ delete o[legacy];
5094
+ }
5095
+ }
5096
+ for (const k of Object.keys(o)) {
5097
+ o[k] = walk(o[k]);
5098
+ }
5099
+ return o;
5100
+ }
5101
+ return obj;
5102
+ }
5103
+
5073
5104
  // src/commands/google-analysis.ts
5074
5105
  var SECTIONS = [
5075
5106
  {
@@ -5292,7 +5323,7 @@ async function runOneSection(def, opts) {
5292
5323
  ]);
5293
5324
  const merged = { images, videos };
5294
5325
  if (opts.json) {
5295
- console.log(JSON.stringify(merged, null, 2));
5326
+ console.log(JSON.stringify(stripLegacyGoogleFieldsIfV2Present(merged), null, 2));
5296
5327
  return;
5297
5328
  }
5298
5329
  const iLen = Array.isArray(images) ? images.length : 0;
@@ -5307,7 +5338,7 @@ async function runOneSection(def, opts) {
5307
5338
  }
5308
5339
  const data = await fetchJson(config, fullPath, !!opts.verbose);
5309
5340
  if (opts.json) {
5310
- console.log(JSON.stringify(data, null, 2));
5341
+ console.log(JSON.stringify(stripLegacyGoogleFieldsIfV2Present(data), null, 2));
5311
5342
  return;
5312
5343
  }
5313
5344
  console.log(
@@ -6806,6 +6837,39 @@ function requireGoogleApi(config) {
6806
6837
  }
6807
6838
  return config.googleApiUrl;
6808
6839
  }
6840
+ function formatGoogleCampaignListStatus(row) {
6841
+ let result = "-";
6842
+ const raw = row.statusV2;
6843
+ if (raw == null || String(raw).trim() === "") return result;
6844
+ const statusV2 = String(raw).toUpperCase();
6845
+ const start = parseCampaignTimeMs(row.startTime);
6846
+ const end = parseCampaignTimeMs(row.endTime);
6847
+ if (start == null || end == null) return result;
6848
+ const now = Date.now();
6849
+ if (statusV2 === "PAUSED") {
6850
+ if (now > start && now < end) {
6851
+ result = "\u5DF2\u6682\u505C";
6852
+ } else if (now > end) {
6853
+ result = "\u5DF2\u7ED3\u675F\u4F7F\u7528";
6854
+ } else if (now < start) {
6855
+ result = "\u672A\u6295\u653E";
6856
+ }
6857
+ } else if (statusV2 === "ENABLED") {
6858
+ if (now > start && now < end) {
6859
+ result = "\u6709\u6548";
6860
+ } else if (now > end) {
6861
+ result = "\u5DF2\u7ED3\u675F\u4F7F\u7528";
6862
+ } else if (now < start) {
6863
+ result = "\u672A\u6295\u653E";
6864
+ }
6865
+ }
6866
+ return result;
6867
+ }
6868
+ function parseCampaignTimeMs(v) {
6869
+ if (v == null || v === "") return null;
6870
+ const t = new Date(v).getTime();
6871
+ return Number.isFinite(t) ? t : null;
6872
+ }
6809
6873
  async function runAdCampaigns(opts) {
6810
6874
  const config = loadConfig(opts.token);
6811
6875
  const googleApiUrl = requireGoogleApi(config);
@@ -6828,18 +6892,19 @@ async function runAdCampaigns(opts) {
6828
6892
  return {
6829
6893
  ...item,
6830
6894
  budgetDisplay,
6831
- budgetUnit: "display"
6895
+ budgetUnit: "display",
6896
+ statusDisplay: formatGoogleCampaignListStatus(item)
6832
6897
  };
6833
6898
  });
6834
6899
  const n = items.length;
6835
6900
  if (opts.json) {
6836
6901
  console.log(
6837
6902
  JSON.stringify(
6838
- {
6903
+ stripLegacyGoogleFieldsIfV2Present({
6839
6904
  ...wrapListJson({ page: 1, pageSize: Math.max(n, 1), total: n, items }),
6840
6905
  code: data.code ?? null,
6841
6906
  message: data.message ?? null
6842
- },
6907
+ }),
6843
6908
  null,
6844
6909
  2
6845
6910
  )
@@ -6874,7 +6939,7 @@ async function runAdCampaigns(opts) {
6874
6939
  const budget = item.budgetDisplay != null ? item.budgetDisplay.toFixed(2) : "\u2014";
6875
6940
  return {
6876
6941
  name: (item.name ?? "").slice(0, nameW),
6877
- status: item.statusV2 ?? "",
6942
+ status: item.statusDisplay ?? formatGoogleCampaignListStatus(item),
6878
6943
  channelType: item.channelTypeV2 ?? "",
6879
6944
  bidding: String(item.biddingStrategyTypeV2 ?? ""),
6880
6945
  budget,
@@ -6917,10 +6982,10 @@ async function runAdGroups(opts) {
6917
6982
  if (opts.json) {
6918
6983
  console.log(
6919
6984
  JSON.stringify(
6920
- {
6985
+ stripLegacyGoogleFieldsIfV2Present({
6921
6986
  ...wrapListJson({ page: 1, pageSize: Math.max(n, 1), total: n, items }),
6922
6987
  code: data.code ?? null
6923
- },
6988
+ }),
6924
6989
  null,
6925
6990
  2
6926
6991
  )
@@ -6990,7 +7055,13 @@ async function runAdList(opts) {
6990
7055
  const n = items.length;
6991
7056
  if (opts.json) {
6992
7057
  console.log(
6993
- JSON.stringify(wrapListJson({ page: 1, pageSize: Math.max(n, 1), total: n, items }), null, 2)
7058
+ JSON.stringify(
7059
+ stripLegacyGoogleFieldsIfV2Present(
7060
+ wrapListJson({ page: 1, pageSize: Math.max(n, 1), total: n, items })
7061
+ ),
7062
+ null,
7063
+ 2
7064
+ )
6994
7065
  );
6995
7066
  return;
6996
7067
  }
@@ -7027,7 +7098,7 @@ async function runAdList(opts) {
7027
7098
  campaign: String(item["campaign"] ?? "").slice(0, campW),
7028
7099
  adGroup: String(item["adGroup"] ?? "").slice(0, grpW),
7029
7100
  status: String(item["statusV2"]),
7030
- type: String(item["typeV2"] ?? item["type"] ?? ""),
7101
+ type: String(item["typeV2"] ?? ""),
7031
7102
  impressions: String(item["impressions"] ?? 0),
7032
7103
  clicks: String(item["clicks"] ?? 0),
7033
7104
  ctr,
@@ -7066,7 +7137,13 @@ async function runAdKeywords(opts) {
7066
7137
  const n = items.length;
7067
7138
  if (opts.json) {
7068
7139
  console.log(
7069
- JSON.stringify(wrapListJson({ page: 1, pageSize: Math.max(n, 1), total: n, items }), null, 2)
7140
+ JSON.stringify(
7141
+ stripLegacyGoogleFieldsIfV2Present(
7142
+ wrapListJson({ page: 1, pageSize: Math.max(n, 1), total: n, items })
7143
+ ),
7144
+ null,
7145
+ 2
7146
+ )
7070
7147
  );
7071
7148
  return;
7072
7149
  }
@@ -7082,7 +7159,7 @@ ${label}\uFF08\u8D26\u6237\uFF1A${opts.account}\uFF0C\u7B2C 1 \u9875\uFF0C\u672C
7082
7159
  if (opts.negative) {
7083
7160
  items.forEach((item) => {
7084
7161
  const kwText = Array.isArray(item["keywordText"]) ? item["keywordText"].join(", ") : String(item["text"] ?? item["keywordText"] ?? item["id"] ?? "\u2014");
7085
- const matchType = item["matchTypeV2"] ?? item["matchType"] ?? "\u2014";
7162
+ const matchType = item["matchTypeV2"] ?? "\u2014";
7086
7163
  console.log(` [${matchType}] ${kwText} id: ${String(item["id"] ?? "")}`);
7087
7164
  });
7088
7165
  } else {
@@ -7113,8 +7190,8 @@ ${label}\uFF08\u8D26\u6237\uFF1A${opts.account}\uFF0C\u7B2C 1 \u9875\uFF0C\u672C
7113
7190
  const kwText = String(item["text"] ?? item["keywordText"] ?? "\u2014");
7114
7191
  const campaign = String(item["campaignName"] ?? item["campaign"] ?? "");
7115
7192
  const adGroup = String(item["adGroupName"] ?? item["adGroup"] ?? "");
7116
- const status = String(item["status"] ?? item["userStatus"] ?? "");
7117
- const matchType = String(item["matchTypeV2"] ?? item["matchType"] ?? "");
7193
+ const status = String(item["userStatus"] ?? "");
7194
+ const matchType = String(item["matchTypeV2"] ?? "");
7118
7195
  const ctr = item["ctr"] != null ? (Number(item["ctr"]) * 100).toFixed(2) + "%" : "\u2014";
7119
7196
  const spend = item["spend"] != null ? Number(item["spend"]).toFixed(2) : "\u2014";
7120
7197
  return {
@@ -8145,7 +8222,13 @@ async function runAdExtensionList(opts) {
8145
8222
  const n = items.length;
8146
8223
  if (opts.json) {
8147
8224
  console.log(
8148
- JSON.stringify(wrapListJson({ page: 1, pageSize: Math.max(n, 1), total: n, items }), null, 2)
8225
+ JSON.stringify(
8226
+ stripLegacyGoogleFieldsIfV2Present(
8227
+ wrapListJson({ page: 1, pageSize: Math.max(n, 1), total: n, items })
8228
+ ),
8229
+ null,
8230
+ 2
8231
+ )
8149
8232
  );
8150
8233
  return;
8151
8234
  }
@@ -8278,7 +8361,13 @@ async function runAdSearchTerms(opts) {
8278
8361
  const n = items.length;
8279
8362
  if (opts.json) {
8280
8363
  console.log(
8281
- JSON.stringify(wrapListJson({ page: 1, pageSize: Math.max(n, 1), total: n, items }), null, 2)
8364
+ JSON.stringify(
8365
+ stripLegacyGoogleFieldsIfV2Present(
8366
+ wrapListJson({ page: 1, pageSize: Math.max(n, 1), total: n, items })
8367
+ ),
8368
+ null,
8369
+ 2
8370
+ )
8282
8371
  );
8283
8372
  return;
8284
8373
  }
@@ -8321,7 +8410,7 @@ async function runAdSearchTerms(opts) {
8321
8410
  term: term.slice(0, termW),
8322
8411
  campaign: String(item["campaignName"] ?? "").slice(0, campW),
8323
8412
  adGroup: String(item["adGroupName"] ?? "").slice(0, grpW),
8324
- matchType: String(item["matchType"] ?? ""),
8413
+ matchType: String(item["matchTypeV2"] ?? ""),
8325
8414
  impressions: String(item["impressions"] ?? 0),
8326
8415
  clicks: String(item["clicks"] ?? 0),
8327
8416
  ctr,
@@ -8355,7 +8444,7 @@ async function runAdGeoSearch(opts) {
8355
8444
  for (const item of items) {
8356
8445
  const id = String(item["id"] ?? "");
8357
8446
  const name = String(item["locationName"] ?? item["canonicalName"] ?? item["name"] ?? "");
8358
- const type = String(item["targetType"] ?? item["typeV2"] ?? item["type"] ?? "");
8447
+ const type = String(item["targetType"] ?? item["typeV2"] ?? "");
8359
8448
  console.log(` id:${id} ${name} [${type}]`);
8360
8449
  }
8361
8450
  console.log();
@@ -8391,7 +8480,13 @@ async function runAdGeoList(opts) {
8391
8480
  const n = items.length;
8392
8481
  if (opts.json) {
8393
8482
  console.log(
8394
- JSON.stringify(wrapListJson({ page: 1, pageSize: Math.max(n, 1), total: n, items }), null, 2)
8483
+ JSON.stringify(
8484
+ stripLegacyGoogleFieldsIfV2Present(
8485
+ wrapListJson({ page: 1, pageSize: Math.max(n, 1), total: n, items })
8486
+ ),
8487
+ null,
8488
+ 2
8489
+ )
8395
8490
  );
8396
8491
  return;
8397
8492
  }
@@ -75,6 +75,8 @@ allowed-tools: Bash(siluzan-tso:*) Read
75
75
  - 这种报告你无法用它来做数据分析除非用户明确要求(Siluzan平台的优化报告)
76
76
  - (推荐,默认生成这种报告)由你主动拉取数据,并按照skill给出的格式,输出给用户:详情请查看(`references/account-analytics.md`)
77
77
 
78
+ **写报告前必读(账户 vs 系列)**:`stats` / `balance` / `list-accounts` 里的账户 `status` 只表示**广告账户**是否可用,**不能**当作**广告系列**是否启用;系列是否投放须用 `ad campaigns`(及 CLI 派生的 `statusDisplay` 等)。详见 `references/account-analytics.md`「账户状态 ≠ 广告系列状态」。
79
+
78
80
  ### 广告账户相关
79
81
 
80
82
  - 广告账户开户请阅读: `references/open-account-by-media.md`
@@ -121,6 +123,7 @@ allowed-tools: Bash(siluzan-tso:*) Read
121
123
 
122
124
  ### 硬规范
123
125
 
126
+ - **出报告时账户状态 ≠ 广告系列状态**:`stats` / `balance` / `list-accounts` 中的 `status`(如 Enabled)只表示**广告账户**关联/可用,**绝不能**据此填写或推断**各广告系列**是否「启用/在投」。已暂停或移除的系列若被写成启用,属于严重错误。系列是否启用**必须**来自 `ad campaigns`(或系列维报表中的系列状态)。详见 `references/account-analytics.md`「账户状态 ≠ 广告系列状态」。
124
127
  - **不确定时读文档**:遇到不熟悉的命令,先读对应 references 文件或使用-h查看命令帮助,不要猜参数。
125
128
  - **先查账户再操作**:对具体账户做操作前,先通过 `list-accounts -m [mediaType] -k [mediaCustomerId]` 确认。特别是不确定是Google/Bing/TikTok这些媒体平台中的哪一个的时候
126
129
  - **使用 --json 处理数据**:需对返回数据做计算或筛选时,加 `--json`,再用 `node -e` 过滤提取(见 `references/tips.md`)。
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "slug": "siluzan-tso",
3
- "version": "1.1.13",
4
- "publishedAt": 1776762370285
3
+ "version": "1.1.14-beta.1",
4
+ "publishedAt": 1776765041399
5
5
  }
@@ -22,6 +22,23 @@
22
22
 
23
23
  ## 报告中的硬约束(必须遵守)
24
24
 
25
+ ### 账户状态 ≠ 广告系列状态(出报告最高优先级)
26
+
27
+ **常见错误**:Agent 看到 `stats`、`balance` 或账户列表里 `status: Enabled`(或「账户正常」),就在报告中把**广告系列**写成「启用」「在投」。这会导致**已暂停、已结束排期或已从投放层面移除**的系列被误标为启用。
28
+
29
+ | 含义 | 数据来源(示例) | `status` / 状态字段表示什么 |
30
+ |------|------------------|-----------------------------|
31
+ | **广告账户**是否在媒体侧关联可用、能否拉数 | `stats`、`balance`、`list-accounts` | 账户级启用/可用,**不描述单个系列是否在投** |
32
+ | **广告系列**是否暂停、是否在排期内可投放 | **`ad campaigns`**(含 `statusDisplay` 等)、系列维报表 | 系列级启停;**唯一**用于写「某系列启用/暂停」 |
33
+
34
+ **写报告时的硬性规则**:
35
+
36
+ 1. **禁止**用 `stats` / `balance` / `list-accounts` 返回的账户 `status` 推断或概括**广告系列**是否启用;不得在报告正文写「根据账户状态,各系列均为启用」这类表述(除非已逐条用 `ad campaigns` 核对)。
37
+ 2. **凡是**描述「某广告系列是否投放 / 启用 / 暂停 / 移除」,**必须**基于 `siluzan-tso ad campaigns -a <mediaCustomerId> --json`(或 `google-analysis` 中带系列粒度、含系列状态的数据)。账户总览里的消耗/点击可以与系列表并列,但**系列状态列不得来自账户接口**。
38
+ 3. 若报告中有「账户概况」与「广告系列明细」两块:前者可用账户级接口;后者**系列状态列只能**来自系列级接口(如 `statusDisplay`),与账户 `status` **不得混为一谈**。
39
+
40
+ **一句话**:账户「能用 / Enabled」≠ 系列「在投」;系列是否启用只看系列级数据(首推 `ad campaigns`)。
41
+
25
42
  ### 品牌名 / 公司名来源
26
43
 
27
44
  生成带品牌名、方案、邮件、广告文案的报告时,**严禁自行生成品牌名(包括中文译名、拼音、意译)**。品牌名必须来自以下来源之一,按优先级:
@@ -7,7 +7,7 @@
7
7
 
8
8
  ## invoice-info — 发票抬头管理
9
9
 
10
- 对应页面:`https://www.siluzan.com/v3/foreign_trade/settings/invoiceInformation`
10
+ 对应页面:`https://www-ci.siluzan.com/v3/foreign_trade/settings/invoiceInformation`
11
11
 
12
12
  发票抬头是开票申请时使用的公司/企业信息模板,支持三种类型:
13
13
 
@@ -131,10 +131,10 @@ siluzan-tso config show
131
131
  **示例:**
132
132
 
133
133
  ```
134
- - 现金充值(单笔):https://www.siluzan.com/recharge/pay
135
- - 现金充值(批量):https://www.siluzan.com/recharge/pay_batch
136
- - 月结充值: https://www.siluzan.com/recharge/accountBillingQuota
137
- - 丝路赞钱包: https://www.siluzan.com/recharge/siluzanWallet
134
+ - 现金充值(单笔):https://www-ci.siluzan.com/recharge/pay
135
+ - 现金充值(批量):https://www-ci.siluzan.com/recharge/pay_batch
136
+ - 月结充值: https://www-ci.siluzan.com/recharge/accountBillingQuota
137
+ - 丝路赞钱包: https://www-ci.siluzan.com/recharge/siluzanWallet
138
138
  ```
139
139
 
140
140
  ---
@@ -124,7 +124,7 @@ siluzan-tso ad campaigns -a 6326027735 --start 2026-03-01 --end 2026-03-31
124
124
  siluzan-tso ad campaigns -a 6326027735 --json
125
125
  ```
126
126
 
127
- 输出字段:名称、状态(`statusV2`)、类型(`channelTypeV2`)、预算、点击数、展示数。
127
+ 输出字段:名称、状态、类型、预算、点击数、展示数(具体字段名以 `--json` 为准;另有 CLI 派生的 `statusDisplay`、`budgetDisplay` 等便于阅读)。
128
128
 
129
129
  ---
130
130
 
@@ -212,8 +212,8 @@ siluzan-tso report list -m Google --json
212
212
 
213
213
  # 第二步:查看 webUrl
214
214
  siluzan-tso config show
215
- # webUrl: https://www.siluzan.com
215
+ # webUrl: https://www-ci.siluzan.com
216
216
 
217
217
  # 第三步:拼接链接(Google 日报)
218
- # https://www.siluzan.com/media-report/publish/rpt_abc123?culture=zh-CN
218
+ # https://www-ci.siluzan.com/media-report/publish/rpt_abc123?culture=zh-CN
219
219
  ```
@@ -10,7 +10,7 @@
10
10
  ## 安装 CLI
11
11
 
12
12
  ```bash
13
- npm install -g siluzan-tso-cli
13
+ npm install -g siluzan-tso-cli@beta
14
14
  ```
15
15
 
16
16
  ---
@@ -47,7 +47,7 @@ siluzan-tso config set --api-key <Key> # 或通过 config set 直接写入
47
47
  siluzan-tso config set --token <Token> # 备用:设置 JWT Token
48
48
  ```
49
49
 
50
- API Key 获取入口:`https://www.siluzan.com/v3/foreign_trade/settings/apiKeyManagement`
50
+ API Key 获取入口:`https://www-ci.siluzan.com/v3/foreign_trade/settings/apiKeyManagement`
51
51
 
52
52
  ### 通过环境变量传入凭据(CI/CD 推荐)
53
53
 
@@ -82,9 +82,9 @@ siluzan-tso config show
82
82
 
83
83
  ```
84
84
  构建环境 : production
85
- apiBaseUrl : https://tso-api.siluzan.com
86
- googleApiUrl : https://googleapi.mysiluzan.com
87
- webUrl : https://www.siluzan.com
85
+ apiBaseUrl : https://tso-api-ci.siluzan.com
86
+ googleApiUrl : https://googleapi-ci.mysiluzan.com
87
+ webUrl : https://www-ci.siluzan.com
88
88
  apiKey : abcd****1234
89
89
  ```
90
90
 
@@ -6,7 +6,7 @@
6
6
 
7
7
  用 `siluzan-tso config show` 读取 **`webUrl`**,再拼接路径:
8
8
 
9
- 首页地址:`https://www.siluzan.com/v3/foreign_trade/tso/home`
9
+ 首页地址:`https://www-ci.siluzan.com/v3/foreign_trade/tso/home`
10
10
 
11
11
  > 若用户已登录 TSO,也可从左侧菜单进入「首页」。
12
12
 
@@ -10,8 +10,8 @@ $ErrorActionPreference = 'Stop'
10
10
  $PKG_NAME = 'siluzan-tso-cli'
11
11
  $CLI_BIN = 'siluzan-tso'
12
12
  $SKILL_LABEL = 'Siluzan TSO'
13
- $INSTALL_CMD = 'npm install -g siluzan-tso-cli'
14
- $WEB_BASE = 'https://www.siluzan.com'
13
+ $INSTALL_CMD = 'npm install -g siluzan-tso-cli@beta'
14
+ $WEB_BASE = 'https://www-ci.siluzan.com'
15
15
 
16
16
  # -- Constants ----------------------------------------------------------------
17
17
  $NODE_MAJOR_MIN = 18
@@ -10,8 +10,8 @@ set -euo pipefail
10
10
  readonly PKG_NAME="siluzan-tso-cli"
11
11
  readonly CLI_BIN="siluzan-tso"
12
12
  readonly SKILL_LABEL="Siluzan TSO"
13
- readonly INSTALL_CMD="npm install -g siluzan-tso-cli"
14
- readonly WEB_BASE="https://www.siluzan.com"
13
+ readonly INSTALL_CMD="npm install -g siluzan-tso-cli@beta"
14
+ readonly WEB_BASE="https://www-ci.siluzan.com"
15
15
 
16
16
  # -- Constants ----------------------------------------------------------------
17
17
  readonly NODE_MAJOR_MIN=18
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "siluzan-tso-cli",
3
- "version": "1.1.13",
3
+ "version": "1.1.14-beta.1",
4
4
  "description": "Siluzan 广告账户管理 CLI — 查询账户、余额、消耗数据,管理绑定关系与充值。",
5
5
  "keywords": [
6
6
  "ad-account",