siluzan-tso-cli 1.1.20-beta.23 → 1.1.20-beta.25

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.20-beta.23),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-tso-cli`。
54
+ > **注意**:当前为测试版(1.1.20-beta.25),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-tso-cli`。
55
55
 
56
56
  | 助手 | 建议 `--ai` |
57
57
  | ----------------------- | ------------------------------------ |
package/dist/index.js CHANGED
@@ -109507,6 +109507,7 @@ function formatLengthViolationsReport(violations) {
109507
109507
 
109508
109508
  // src/commands/ad/campaign-extensions.ts
109509
109509
  var SITELINK_DESCRIPTION_MAX_LEN = 25;
109510
+ var CALLOUT_TEXT_MAX_LEN = 25;
109510
109511
  function pushErr(errors, msg) {
109511
109512
  errors.push(msg);
109512
109513
  }
@@ -109546,8 +109547,14 @@ function normalizeExtensionsForBatchJob(extensions) {
109546
109547
  return extensions.map((ext) => {
109547
109548
  const raw = ext.Properties ?? {};
109548
109549
  let props = coercePropertiesFromRaw(raw);
109549
- if (extensionType(ext) === "SITELINK") {
109550
+ const type = extensionType(ext);
109551
+ if (type === "SITELINK") {
109550
109552
  props = normalizeSitelinkProperties(props);
109553
+ } else if (type === "CALLOUT") {
109554
+ if (props.CalloutText && !props.Text) {
109555
+ props.Text = props.CalloutText;
109556
+ delete props.CalloutText;
109557
+ }
109551
109558
  }
109552
109559
  const out = { ...ext, Properties: props };
109553
109560
  if (typeof ext.level === "string" && !out.Level) out.Level = ext.level;
@@ -109623,6 +109630,87 @@ function validateSitelinkProperties(prefix, raw, errors, warnings, lengthViolati
109623
109630
  );
109624
109631
  }
109625
109632
  }
109633
+ function validateCalloutProperties(prefix, rec, errors, _warnings, lengthViolations) {
109634
+ const props = rec["Properties"];
109635
+ if (!props || typeof props !== "object" || Array.isArray(props)) {
109636
+ pushErr(errors, `${prefix}\uFF08CALLOUT\uFF09\u7F3A\u5C11 Properties`);
109637
+ return;
109638
+ }
109639
+ const raw = props;
109640
+ if (raw["CalloutText"] !== void 0 && raw["Text"] === void 0) {
109641
+ pushErr(
109642
+ errors,
109643
+ `${prefix}.Properties \u4F7F\u7528\u4E86\u9519\u8BEF\u5B57\u6BB5\u540D "CalloutText"\uFF08\u540E\u7AEF ExtensionConstants.CalloutText = "Text"\uFF0CProperties key \u5FC5\u987B\u662F "Text"\uFF09\u3002\u8BF7\u5C06 "CalloutText" \u6539\u4E3A "Text"\uFF0C\u5426\u5219\u540E\u7AEF CreateCalloutFeedItem \u8BFB\u5230 null \u2192 ArgumentNullException`
109644
+ );
109645
+ return;
109646
+ }
109647
+ const text = raw["Text"];
109648
+ if (typeof text !== "string" || !text.trim()) {
109649
+ pushErr(
109650
+ errors,
109651
+ `${prefix}.Properties.Text \u4E0D\u80FD\u4E3A\u7A7A\uFF08CALLOUT \u5FC5\u586B\uFF0C\u540E\u7AEF CreateCalloutFeedItem \u8BFB\u53D6 Properties["Text"]\uFF09`
109652
+ );
109653
+ return;
109654
+ }
109655
+ if (text.length > CALLOUT_TEXT_MAX_LEN) {
109656
+ pushLengthViolation(lengthViolations, {
109657
+ path: `${prefix}.Properties.Text`,
109658
+ field: "Text",
109659
+ kind: "callout_text",
109660
+ limit: CALLOUT_TEXT_MAX_LEN,
109661
+ actual: text.length,
109662
+ countMode: "ascii",
109663
+ text
109664
+ });
109665
+ pushErr(
109666
+ errors,
109667
+ `${prefix}.Properties.Text \u8D85\u8FC7 ${CALLOUT_TEXT_MAX_LEN} \u5B57\u7B26\uFF08\u5F53\u524D ${text.length}\uFF0CGoogle \u786C\u7EA6\u675F\uFF09\uFF1A"${text}"`
109668
+ );
109669
+ }
109670
+ }
109671
+ function validateCallProperties(prefix, rec, errors) {
109672
+ const props = rec["Properties"];
109673
+ if (!props || typeof props !== "object" || Array.isArray(props)) {
109674
+ pushErr(errors, `${prefix}\uFF08CALL\uFF09\u7F3A\u5C11 Properties`);
109675
+ return;
109676
+ }
109677
+ const raw = props;
109678
+ if (raw["CountryCode"] !== void 0 && raw["ContryCode"] === void 0) {
109679
+ pushErr(
109680
+ errors,
109681
+ `${prefix}.Properties \u4F7F\u7528\u4E86 "CountryCode"\uFF0C\u4F46\u540E\u7AEF ExtensionConstants.CallCountryCode = "ContryCode"\uFF08\u540E\u7AEF typo\uFF0C\u7F3A\u4E00\u4E2A u\uFF09\u3002\u8BF7\u5C06\u5B57\u6BB5\u540D\u6539\u4E3A "ContryCode"\uFF0C\u5426\u5219\u540E\u7AEF\u8BFB\u5230 null \u2192 ArgumentNullException`
109682
+ );
109683
+ } else if (!raw["ContryCode"] || typeof raw["ContryCode"] !== "string" || !raw["ContryCode"].trim()) {
109684
+ pushErr(
109685
+ errors,
109686
+ `${prefix}.Properties.ContryCode \u4E0D\u80FD\u4E3A\u7A7A\uFF08CALL \u5FC5\u586B\uFF0C\u6CE8\u610F\u540E\u7AEF typo\uFF1AContryCode \u975E CountryCode\uFF09`
109687
+ );
109688
+ }
109689
+ if (!raw["PhoneNumber"] || typeof raw["PhoneNumber"] !== "string" || !raw["PhoneNumber"].trim()) {
109690
+ pushErr(errors, `${prefix}.Properties.PhoneNumber \u4E0D\u80FD\u4E3A\u7A7A\uFF08CALL \u5FC5\u586B\uFF09`);
109691
+ }
109692
+ }
109693
+ function validateStructuredSnippetExtension(prefix, rec, errors) {
109694
+ const ssv = rec["StructuredSnippetHeaderValue"];
109695
+ if (ssv === void 0 || ssv === null) {
109696
+ pushErr(
109697
+ errors,
109698
+ `${prefix}\uFF08STRUCTURED_SNIPPET\uFF09\u7F3A\u5C11\u9876\u5C42\u5B57\u6BB5 StructuredSnippetHeaderValue\uFF08\u683C\u5F0F\uFF1A{ "Key": "Services", "Value": ["item1", "item2"] }\uFF09\u3002\u540E\u7AEF CreateStructuredSnippetFeedItem \u4E0D\u8D70 Properties\uFF0CStructuredSnippetHeaderValue \u4E3A null \u65F6\u8FD4\u56DE null Asset`
109699
+ );
109700
+ return;
109701
+ }
109702
+ if (typeof ssv !== "object" || Array.isArray(ssv)) {
109703
+ pushErr(errors, `${prefix}.StructuredSnippetHeaderValue \u5FC5\u987B\u662F\u5BF9\u8C61 { Key: string; Value: string[] }`);
109704
+ return;
109705
+ }
109706
+ const sv = ssv;
109707
+ if (typeof sv["Key"] !== "string" || !sv["Key"].trim()) {
109708
+ pushErr(errors, `${prefix}.StructuredSnippetHeaderValue.Key \u4E0D\u80FD\u4E3A\u7A7A\uFF08\u7247\u6BB5\u6807\u9898\uFF0C\u5982 "Services"\uFF09`);
109709
+ }
109710
+ if (!Array.isArray(sv["Value"]) || sv["Value"].length === 0) {
109711
+ pushErr(errors, `${prefix}.StructuredSnippetHeaderValue.Value \u4E0D\u80FD\u4E3A\u7A7A\u6570\u7EC4\uFF08\u81F3\u5C11\u586B\u4E00\u4E2A\u7247\u6BB5\u503C\uFF09`);
109712
+ }
109713
+ }
109626
109714
  function validateCampaignExtensionsForBatchJob(campaign, errors, warnings, lengthViolations = []) {
109627
109715
  const extensions = campaign["ExtensionsForBatchJob"];
109628
109716
  if (extensions === void 0) return;
@@ -109639,21 +109727,23 @@ function validateCampaignExtensionsForBatchJob(campaign, errors, warnings, lengt
109639
109727
  }
109640
109728
  const rec = ext;
109641
109729
  const type = extensionType(rec);
109642
- const props = rec["Properties"];
109643
- if (props !== void 0 && (typeof props !== "object" || props === null || Array.isArray(props))) {
109644
- pushErr(errors, `${prefix}.Properties \u5FC5\u987B\u662F\u5BF9\u8C61`);
109645
- continue;
109646
- }
109647
- if (type === "SITELINK" && props && typeof props === "object") {
109648
- validateSitelinkProperties(
109649
- prefix,
109650
- props,
109651
- errors,
109652
- warnings,
109653
- lengthViolations
109654
- );
109655
- } else if (type === "SITELINK") {
109656
- pushErr(errors, `${prefix}\uFF08SITELINK\uFF09\u7F3A\u5C11 Properties`);
109730
+ if (type === "SITELINK") {
109731
+ const props = rec["Properties"];
109732
+ if (props !== void 0 && (typeof props !== "object" || props === null || Array.isArray(props))) {
109733
+ pushErr(errors, `${prefix}.Properties \u5FC5\u987B\u662F\u5BF9\u8C61`);
109734
+ continue;
109735
+ }
109736
+ if (props && typeof props === "object") {
109737
+ validateSitelinkProperties(prefix, props, errors, warnings, lengthViolations);
109738
+ } else {
109739
+ pushErr(errors, `${prefix}\uFF08SITELINK\uFF09\u7F3A\u5C11 Properties`);
109740
+ }
109741
+ } else if (type === "CALLOUT") {
109742
+ validateCalloutProperties(prefix, rec, errors, warnings, lengthViolations);
109743
+ } else if (type === "CALL") {
109744
+ validateCallProperties(prefix, rec, errors);
109745
+ } else if (type === "STRUCTURED_SNIPPET") {
109746
+ validateStructuredSnippetExtension(prefix, rec, errors);
109657
109747
  }
109658
109748
  }
109659
109749
  }
@@ -110476,7 +110566,12 @@ function validateRsaAd(prefix, ad, errors, warnings, lengthViolations) {
110476
110566
  }
110477
110567
  validateRsaDisplayPath(prefix, ad, errors, lengthViolations);
110478
110568
  const finalUrl = ad["Finalurl"] ?? ad["DestinationUrl"];
110479
- if (typeof finalUrl === "string" && finalUrl.length > 0 && !URL_REGEX.test(finalUrl)) {
110569
+ if (!finalUrl || typeof finalUrl !== "string" || !finalUrl.trim()) {
110570
+ pushErr2(
110571
+ errors,
110572
+ `${prefix} Finalurl\uFF08\u843D\u5730\u9875 URL\uFF09\u4E0D\u80FD\u4E3A\u7A7A\uFF08\u540E\u7AEF BuildResponsiveSearchAd \u5199\u5165 FinalUrls\uFF0C\u4E3A\u7A7A Google \u62D2\u7EDD\uFF09`
110573
+ );
110574
+ } else if (!URL_REGEX.test(finalUrl)) {
110480
110575
  pushErr2(errors, `${prefix} Finalurl \u683C\u5F0F\u4E0D\u6B63\u786E\uFF08\u5E94\u4EE5 http(s):// \u5F00\u5934\uFF09\uFF1A${finalUrl}`);
110481
110576
  }
110482
110577
  validateRsaHeadlinesWithinAd(prefix, ad, errors);
@@ -110622,6 +110717,16 @@ function validateCampaignCreateConfigCore(cfg) {
110622
110717
  const targetedLanguages = campaign["targetedLanguages"];
110623
110718
  if (!Array.isArray(targetedLanguages) || targetedLanguages.length === 0) {
110624
110719
  pushErr2(errors, "campaign.targetedLanguages \u4E0D\u80FD\u4E3A\u7A7A\uFF08\u82F1\u8BED id=1000\uFF0C\u4E2D\u6587 id=1017\uFF09");
110720
+ } else {
110721
+ for (let i = 0; i < targetedLanguages.length; i++) {
110722
+ const lang = targetedLanguages[i];
110723
+ if (!lang || lang["id"] === void 0 && lang["Id"] === void 0) {
110724
+ pushErr2(
110725
+ errors,
110726
+ `campaign.targetedLanguages[${i}] \u7F3A\u5C11 id \u5B57\u6BB5\uFF08\u540E\u7AEF BuildCampaignCriterion \u8BFB domainCriterion.Id \u6784\u5EFA ResourceNames.LanguageConstant\uFF09`
110727
+ );
110728
+ }
110729
+ }
110625
110730
  }
110626
110731
  const start = campaign["StartTime"];
110627
110732
  const end = campaign["EndTime"];
@@ -110636,6 +110741,48 @@ function validateCampaignCreateConfigCore(cfg) {
110636
110741
  pushErr2(errors, `campaign.EndTime\uFF08${end}\uFF09\u5FC5\u987B\u665A\u4E8E StartTime\uFF08${start}\uFF09`);
110637
110742
  }
110638
110743
  }
110744
+ const VALID_DAY_OF_WEEK_V2 = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
110745
+ const VALID_MINUTE_OF_HOUR_V2 = ["Zero", "Fifteen", "Thirty", "FortyFive"];
110746
+ const adSchedules = campaign["AdSchedules"];
110747
+ if (Array.isArray(adSchedules) && adSchedules.length > 0) {
110748
+ for (let i = 0; i < adSchedules.length; i++) {
110749
+ const s = adSchedules[i];
110750
+ const sPrefix = `campaign.AdSchedules[${i}]`;
110751
+ if (!s || typeof s !== "object") {
110752
+ pushErr2(errors, `${sPrefix} \u5FC5\u987B\u662F\u5BF9\u8C61`);
110753
+ continue;
110754
+ }
110755
+ const dow = s["DayOfWeekV2"];
110756
+ if (dow === void 0 || dow === null || typeof dow === "string" && !VALID_DAY_OF_WEEK_V2.includes(dow)) {
110757
+ pushErr2(
110758
+ errors,
110759
+ `${sPrefix}.DayOfWeekV2 \u65E0\u6548\uFF08${String(dow)}\uFF09\uFF0C\u5408\u6CD5\u503C\uFF1A${VALID_DAY_OF_WEEK_V2.join(" | ")}`
110760
+ );
110761
+ }
110762
+ const startHour = s["StartHour"];
110763
+ const endHour = s["EndHour"];
110764
+ if (typeof startHour !== "number" || startHour < 0 || startHour > 23) {
110765
+ pushErr2(errors, `${sPrefix}.StartHour \u5FC5\u987B\u662F 0\u201323 \u7684\u6574\u6570`);
110766
+ }
110767
+ if (typeof endHour !== "number" || endHour < 1 || endHour > 24) {
110768
+ pushErr2(errors, `${sPrefix}.EndHour \u5FC5\u987B\u662F 1\u201324 \u7684\u6574\u6570\uFF0824 \u8868\u793A\u5168\u5929\u7ED3\u675F\uFF09`);
110769
+ }
110770
+ const startMin = s["StartMinuteV2"];
110771
+ const endMin = s["EndMinuteV2"];
110772
+ if (startMin !== void 0 && typeof startMin === "string" && !VALID_MINUTE_OF_HOUR_V2.includes(startMin)) {
110773
+ pushErr2(
110774
+ errors,
110775
+ `${sPrefix}.StartMinuteV2 \u65E0\u6548\uFF08${startMin}\uFF09\uFF0C\u5408\u6CD5\u503C\uFF1A${VALID_MINUTE_OF_HOUR_V2.join(" | ")}`
110776
+ );
110777
+ }
110778
+ if (endMin !== void 0 && typeof endMin === "string" && !VALID_MINUTE_OF_HOUR_V2.includes(endMin)) {
110779
+ pushErr2(
110780
+ errors,
110781
+ `${sPrefix}.EndMinuteV2 \u65E0\u6548\uFF08${endMin}\uFF09\uFF0C\u5408\u6CD5\u503C\uFF1A${VALID_MINUTE_OF_HOUR_V2.join(" | ")}`
110782
+ );
110783
+ }
110784
+ }
110785
+ }
110639
110786
  if (cfg.url !== void 0 && cfg.url !== "" && !URL_REGEX.test(cfg.url)) {
110640
110787
  pushErr2(errors, `url\uFF08${cfg.url}\uFF09\u683C\u5F0F\u4E0D\u6B63\u786E\uFF0C\u5E94\u4EE5 http(s):// \u5F00\u5934`);
110641
110788
  }
@@ -110654,6 +110801,15 @@ function validateCampaignCreateConfigCore(cfg) {
110654
110801
  if (typeof gName !== "string" || !gName.trim()) {
110655
110802
  pushErr2(errors, `${gPrefix}.Name \u4E0D\u80FD\u4E3A\u7A7A`);
110656
110803
  }
110804
+ const gTypeV2 = g["TypeV2"];
110805
+ if (gTypeV2 === void 0 || gTypeV2 === null) {
110806
+ pushErr2(
110807
+ errors,
110808
+ `${gPrefix}.TypeV2 \u4E0D\u80FD\u4E3A\u7A7A\uFF08\u641C\u7D22\u5E7F\u544A\u586B "SEARCH_STANDARD"\uFF0C\u540E\u7AEF BuildAdGroupOperations \u5F3A\u8F6C AdGroupTypeV2 enum\uFF09`
110809
+ );
110810
+ } else if (typeof gTypeV2 === "string" && (gTypeV2.toUpperCase() === "UNSPECIFIED" || gTypeV2.toUpperCase() === "UNKNOWN")) {
110811
+ pushErr2(errors, `${gPrefix}.TypeV2 \u4E0D\u80FD\u4E3A "${gTypeV2}"\uFF08\u4F1A\u5BFC\u81F4 Google \u62D2\u7EDD\u5E7F\u544A\u7EC4\uFF09`);
110812
+ }
110657
110813
  const mc = g["MaxCPCAmount"];
110658
110814
  if (mc !== void 0 && (typeof mc !== "number" || !Number.isFinite(mc) || mc < 0)) {
110659
110815
  pushErr2(errors, `${gPrefix}.MaxCPCAmount \u5FC5\u987B\u4E3A\u975E\u8D1F\u6570\u5B57\uFF08\u5355\u4F4D\u300C\u5143\u300D\uFF09`);
@@ -110677,8 +110833,21 @@ function validateCampaignCreateConfigCore(cfg) {
110677
110833
  for (let j = 0; j < kws.length; j++) {
110678
110834
  const block = kws[j];
110679
110835
  const texts = block?.["KeywordText"];
110680
- if (!Array.isArray(texts) || texts.length === 0) {
110681
- pushErr2(errors, `${gPrefix}.KeywordsForBatchJob[${j}].KeywordText \u4E0D\u80FD\u4E3A\u7A7A\u6570\u7EC4`);
110836
+ const items = block?.["Items"];
110837
+ const hasTexts = Array.isArray(texts) && texts.length > 0;
110838
+ const hasItems = Array.isArray(items) && items.length > 0;
110839
+ if (!hasTexts && !hasItems) {
110840
+ pushErr2(
110841
+ errors,
110842
+ `${gPrefix}.KeywordsForBatchJob[${j}] KeywordText \u6570\u7EC4\u548C Items \u6570\u7EC4\u4E0D\u80FD\u540C\u65F6\u4E3A\u7A7A\uFF08\u540E\u7AEF GetAdGroupCriterionOperations \u8981\u6C42\u81F3\u5C11\u4E00\u4E2A\u975E\u7A7A\uFF09`
110843
+ );
110844
+ } else if (hasTexts) {
110845
+ for (let k = 0; k < texts.length; k++) {
110846
+ const kw = texts[k];
110847
+ if (typeof kw !== "string" || !kw.trim()) {
110848
+ pushErr2(errors, `${gPrefix}.KeywordsForBatchJob[${j}].KeywordText[${k}] \u4E0D\u80FD\u4E3A\u7A7A\u5B57\u7B26\u4E32`);
110849
+ }
110850
+ }
110682
110851
  }
110683
110852
  }
110684
110853
  }
@@ -151,6 +151,7 @@ Windows 注意:部分 Agent 客户端通过 PowerShell / cmd 代执行命令
151
151
  - **常用字段**:
152
152
  - `ad campaigns --json/--json-out` → `budget`(元,与 `campaign-edit --budget` 同口径)
153
153
  - `ad groups --json` → `maxCPCAmountYuan` / `targetCpaAmountYuan`(元)
154
+ - `google-analysis overview-*.json` → **余额取 `remainingAccountBudget`,禁止取 `balance`**(`balance` 是 Google 原始字段,多数账户恒为 0)
154
155
  - `google-analysis campaigns-*.json` → `budgetAmountYuan` / `campaignTargetCpaYuan` / `maximizeConversionsTargetCpaYuan` / `spend` / `averageCpc` / `costPerConversion`(均元)
155
156
  - `keyword --json` → `averageCpc` / `lowTopOfPageBid` / `highTopOfPageBid` + 根级与每条 `bidAmountCurrency`(无 `-a` 为 USD;有 `-a` 为账户 `currencyCode`);`-a <mediaCustomerId>` 走账户级推荐接口;限定市场用 `keyword geo-list` + `--geo <id>`(**多 id = 汇总指标**;分市场须多次调用、每次一个 `--geo`,见 `references/keyword-planner-workflows.md`)
156
157
  - **品牌名优先级**:(1) 用户明确提供 → (2) `list-accounts.mag.advertiserName` → (3) 用户提供网址 → 域名占位并标注 `[待确认品牌名]`。**严禁**把英文域名翻译为虚构中文品牌。
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "slug": "siluzan-tso",
3
- "version": "1.1.20-beta.23",
4
- "publishedAt": 1779357196416
3
+ "version": "1.1.20-beta.25",
4
+ "publishedAt": 1779364196042
5
5
  }
@@ -84,7 +84,7 @@ CLI 出口的所有 JSON / 表格金额已统一为**元**,关键字段:
84
84
  | `ad groups --json` | `maxCPCAmountYuan`、`targetCpaAmountYuan` |
85
85
  | `google-analysis campaigns` 落盘 `campaigns-*.json` | `budgetAmountYuan`、`campaignTargetCpaYuan`、`maximizeConversionsTargetCpaYuan`;同行 `spend` / `averageCpc` / `costPerConversion` 也是元 |
86
86
  | `keyword suggest --json` | `averageCpc`、`lowTopOfPageBid`、`highTopOfPageBid`;根级与每条 `bidAmountCurrency`(有 `-a` 为账户币;无 `-a` 为 USD) |
87
- | `balance` 等账户余额接口 | `remainingAccountBudget`(元) |
87
+ | `balance` 等账户余额接口 | `remainingAccountBudget`(元);**注意:`google-analysis overview` 同时返回 `balance`(Google 原始字段,多数账户恒为 0)和 `remainingAccountBudget`(真实余额),余额取值必须用后者** |
88
88
 
89
89
  旧字段 `budgetAmount`(分)、`maxCPCAmountDisplay`、`*Micros`(微元)**已不再落盘**,下游脚本无需做单位换算。金额保留 2 位小数,带货币代码(如 `¥50.00 CNY`、`$50.00 USD`),`currencyCode` 从响应读取,跨币种账户分表;细则见 `references/currency.md`。
90
90
 
@@ -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.20-beta.23'
12
+ $PKG_VERSION = '1.1.20-beta.25'
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.20-beta.23"
12
+ readonly PKG_VERSION="1.1.20-beta.25"
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.20-beta.23",
3
+ "version": "1.1.20-beta.25",
4
4
  "description": "Siluzan 广告账户管理 CLI — 查询账户、余额、消耗数据,管理绑定关系与充值。",
5
5
  "keywords": [
6
6
  "ad-account",