siluzan-tso-cli 1.1.43-beta.2 → 1.1.43-beta.3
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 +89 -24
- package/dist/skill/SKILL.md +3 -1
- package/dist/skill/_meta.json +2 -2
- package/dist/skill/references/accounts/accounts-permissions.md +3 -1
- package/dist/skill/references/accounts/accounts.md +3 -1
- package/dist/skill/references/core/agent-conventions.md +3 -2
- package/dist/skill/references/google-ads/google-ads-read.md +3 -1
- package/dist/skill/references/google-ads/google-ads-write.md +1 -1
- package/dist/skill/references/google-ads/google-ads.md +4 -0
- package/dist/skill/scripts/install.ps1 +1 -1
- package/dist/skill/scripts/install.sh +1 -1
- package/package.json +1 -1
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.43-beta.
|
|
54
|
+
> **注意**:当前为测试版(1.1.43-beta.3),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-tso-cli`。
|
|
55
55
|
|
|
56
56
|
| 助手 | 建议 `--ai` |
|
|
57
57
|
| ----------------------- | ------------------------------------ |
|
package/dist/index.js
CHANGED
|
@@ -4816,6 +4816,19 @@ function normalizeNumericMediaCustomerId(raw) {
|
|
|
4816
4816
|
if (!looksLikeNumericMediaCustomerId(raw)) return null;
|
|
4817
4817
|
return stripMediaCustomerIdDecorators(raw);
|
|
4818
4818
|
}
|
|
4819
|
+
function requireNumericMediaCustomerId(raw, label = "-a, --account") {
|
|
4820
|
+
const trimmed = raw?.toString().trim() ?? "";
|
|
4821
|
+
if (!trimmed) {
|
|
4822
|
+
throw new Error(`\u8BF7\u6307\u5B9A\u5A92\u4F53\u8D26\u6237 ID\uFF08${label}\uFF09`);
|
|
4823
|
+
}
|
|
4824
|
+
const id = normalizeNumericMediaCustomerId(trimmed);
|
|
4825
|
+
if (!id) {
|
|
4826
|
+
throw new Error(
|
|
4827
|
+
`\u5A92\u4F53\u8D26\u6237 ID \u5FC5\u987B\u4E3A\u7EAF\u6570\u5B57\uFF08Google CID \u53EF\u542B\u8FDE\u5B57\u7B26\uFF0C\u5982 123-456-7890\uFF1B\u52FF\u4F20 entityId/UUID\uFF09\uFF1A${trimmed}`
|
|
4828
|
+
);
|
|
4829
|
+
}
|
|
4830
|
+
return id;
|
|
4831
|
+
}
|
|
4819
4832
|
function looksLikeEntityIdUuid(raw) {
|
|
4820
4833
|
return ENTITY_ID_UUID_RE.test(raw.trim());
|
|
4821
4834
|
}
|
|
@@ -107265,6 +107278,20 @@ init_list_fetch();
|
|
|
107265
107278
|
|
|
107266
107279
|
// src/commands/ad/_shared.ts
|
|
107267
107280
|
init_auth();
|
|
107281
|
+
init_media_customer_id();
|
|
107282
|
+
function resolveAdAccountId(account, label = "-a, --account") {
|
|
107283
|
+
try {
|
|
107284
|
+
return requireNumericMediaCustomerId(account, label);
|
|
107285
|
+
} catch (e) {
|
|
107286
|
+
console.error(`
|
|
107287
|
+
\u274C ${e instanceof Error ? e.message : String(e)}
|
|
107288
|
+
`);
|
|
107289
|
+
process.exit(1);
|
|
107290
|
+
}
|
|
107291
|
+
}
|
|
107292
|
+
function withResolvedAdAccount(opts) {
|
|
107293
|
+
return { ...opts, account: resolveAdAccountId(opts.account) };
|
|
107294
|
+
}
|
|
107268
107295
|
async function findItemInList(listUrl, config, id, verbose) {
|
|
107269
107296
|
const res = await apiFetch2(listUrl, config, {}, verbose);
|
|
107270
107297
|
const item = (res.data ?? []).find((x) => x["id"] === id);
|
|
@@ -111394,6 +111421,9 @@ init_cli_json_snapshot();
|
|
|
111394
111421
|
init_strip_legacy_google_fields();
|
|
111395
111422
|
init_cli_table();
|
|
111396
111423
|
|
|
111424
|
+
// src/commands/ad/campaign-create-validate.ts
|
|
111425
|
+
init_media_customer_id();
|
|
111426
|
+
|
|
111397
111427
|
// src/commands/ad/campaign-length-violations.ts
|
|
111398
111428
|
function pushLengthViolation(violations, item) {
|
|
111399
111429
|
violations.push({ ...item, excess: item.actual - item.limit });
|
|
@@ -111791,6 +111821,7 @@ function keywordRowToYuan(item) {
|
|
|
111791
111821
|
return { ...rest, maxCPCYuan: toDisplayMoney(rawMaxCpc) };
|
|
111792
111822
|
}
|
|
111793
111823
|
async function runAdKeywords(opts) {
|
|
111824
|
+
opts = withResolvedAdAccount(opts);
|
|
111794
111825
|
const config = loadConfig(opts.token);
|
|
111795
111826
|
const googleApiUrl = requireGoogleApi(config);
|
|
111796
111827
|
const params = new URLSearchParams();
|
|
@@ -111894,6 +111925,7 @@ ${label}\uFF08\u8D26\u6237\uFF1A${opts.account}\uFF0C\u7B2C 1 \u9875\uFF0C\u672C
|
|
|
111894
111925
|
console.log();
|
|
111895
111926
|
}
|
|
111896
111927
|
async function runAdKeywordCreate(opts) {
|
|
111928
|
+
opts = withResolvedAdAccount(opts);
|
|
111897
111929
|
const config = loadConfig(opts.token);
|
|
111898
111930
|
const googleApiUrl = requireGoogleApi(config);
|
|
111899
111931
|
let keywords;
|
|
@@ -111946,6 +111978,7 @@ async function runAdKeywordCreate(opts) {
|
|
|
111946
111978
|
`);
|
|
111947
111979
|
}
|
|
111948
111980
|
async function runAdNegativeKeywordCreate(opts) {
|
|
111981
|
+
opts = withResolvedAdAccount(opts);
|
|
111949
111982
|
const config = loadConfig(opts.token);
|
|
111950
111983
|
const googleApiUrl = requireGoogleApi(config);
|
|
111951
111984
|
let keywords;
|
|
@@ -111985,6 +112018,7 @@ async function runAdNegativeKeywordCreate(opts) {
|
|
|
111985
112018
|
`);
|
|
111986
112019
|
}
|
|
111987
112020
|
async function runAdKeywordDelete(opts) {
|
|
112021
|
+
opts = withResolvedAdAccount(opts);
|
|
111988
112022
|
const config = await ensureDataPermission(loadConfig(opts.token));
|
|
111989
112023
|
const googleApiUrl = requireGoogleApi(config);
|
|
111990
112024
|
const body = [{ adGroupId: opts.adgroupId, id: opts.id }];
|
|
@@ -112002,6 +112036,7 @@ async function runAdKeywordDelete(opts) {
|
|
|
112002
112036
|
`);
|
|
112003
112037
|
}
|
|
112004
112038
|
async function runAdKeywordEdit(opts) {
|
|
112039
|
+
opts = withResolvedAdAccount(opts);
|
|
112005
112040
|
const config = await ensureDataPermission(loadConfig(opts.token));
|
|
112006
112041
|
const googleApiUrl = requireGoogleApi(config);
|
|
112007
112042
|
const hasChange = opts.text !== void 0 || opts.matchType !== void 0 || opts.maxCpc !== void 0 || opts.finalUrl !== void 0 || opts.status !== void 0;
|
|
@@ -112067,6 +112102,7 @@ async function runAdKeywordEdit(opts) {
|
|
|
112067
112102
|
`);
|
|
112068
112103
|
}
|
|
112069
112104
|
async function runAdKeywordStatus(opts) {
|
|
112105
|
+
opts = withResolvedAdAccount(opts);
|
|
112070
112106
|
const config = await ensureDataPermission(loadConfig(opts.token));
|
|
112071
112107
|
const googleApiUrl = requireGoogleApi(config);
|
|
112072
112108
|
const params = new URLSearchParams();
|
|
@@ -112102,6 +112138,7 @@ async function runAdKeywordStatus(opts) {
|
|
|
112102
112138
|
`);
|
|
112103
112139
|
}
|
|
112104
112140
|
async function runAdNegativeKeywordEdit(opts) {
|
|
112141
|
+
opts = withResolvedAdAccount(opts);
|
|
112105
112142
|
const config = loadConfig(opts.token);
|
|
112106
112143
|
const googleApiUrl = requireGoogleApi(config);
|
|
112107
112144
|
const dateParams = new URLSearchParams();
|
|
@@ -112143,6 +112180,7 @@ async function runAdNegativeKeywordEdit(opts) {
|
|
|
112143
112180
|
`);
|
|
112144
112181
|
}
|
|
112145
112182
|
async function runAdNegativeKeywordDelete(opts) {
|
|
112183
|
+
opts = withResolvedAdAccount(opts);
|
|
112146
112184
|
const config = loadConfig(opts.token);
|
|
112147
112185
|
const googleApiUrl = requireGoogleApi(config);
|
|
112148
112186
|
const dateParams = new URLSearchParams();
|
|
@@ -112985,9 +113023,13 @@ function validateCampaignCreateConfigCore(cfg) {
|
|
|
112985
113023
|
"customerName \u4E3A\u7A7A\uFF1A\u63D0\u4EA4 campaign-create \u65F6\u5C06\u6309 account \u4ECE list-accounts \u81EA\u52A8\u586B\u5145 mediaCustomerName"
|
|
112986
113024
|
);
|
|
112987
113025
|
}
|
|
112988
|
-
const
|
|
112989
|
-
|
|
112990
|
-
|
|
113026
|
+
const normalizedAccount = normalizeNumericMediaCustomerId(String(cfg.account ?? "").trim());
|
|
113027
|
+
const accountNum = normalizedAccount ? Number(normalizedAccount) : NaN;
|
|
113028
|
+
if (!normalizedAccount || !Number.isFinite(accountNum) || accountNum <= 0) {
|
|
113029
|
+
pushErr2(
|
|
113030
|
+
errors,
|
|
113031
|
+
"account \u5FC5\u987B\u662F\u53EF\u89E3\u6790\u4E3A\u6B63\u6570\u7684\u5A92\u4F53\u8D26\u6237 ID\uFF08\u53EF\u542B\u8FDE\u5B57\u7B26\uFF1B\u63D0\u4EA4\u65F6 customerId \u4E3A number\uFF09"
|
|
113032
|
+
);
|
|
112991
113033
|
}
|
|
112992
113034
|
if (!cfg.campaign || typeof cfg.campaign !== "object" || Array.isArray(cfg.campaign)) {
|
|
112993
113035
|
pushErr2(errors, "campaign \u5BF9\u8C61\u4E0D\u80FD\u4E3A\u7A7A\uFF08\u540E\u7AEF\uFF1Acampaign is null\uFF09");
|
|
@@ -113353,6 +113395,7 @@ function parseCampaignTimeMs(v) {
|
|
|
113353
113395
|
return Number.isFinite(t) ? t : null;
|
|
113354
113396
|
}
|
|
113355
113397
|
async function runAdCampaigns(opts) {
|
|
113398
|
+
opts = withResolvedAdAccount(opts);
|
|
113356
113399
|
const config = loadConfig(opts.token);
|
|
113357
113400
|
const googleApiUrl = requireGoogleApi(config);
|
|
113358
113401
|
const params = new URLSearchParams();
|
|
@@ -113435,6 +113478,7 @@ async function runAdCampaigns(opts) {
|
|
|
113435
113478
|
console.log();
|
|
113436
113479
|
}
|
|
113437
113480
|
async function runAdCampaignStatus(opts) {
|
|
113481
|
+
opts = withResolvedAdAccount(opts);
|
|
113438
113482
|
const config = loadConfig(opts.token);
|
|
113439
113483
|
const googleApiUrl = requireGoogleApi(config);
|
|
113440
113484
|
const detailUrl = `${googleApiUrl}/campaignmanagement/campaign/${opts.account}/${opts.id}`;
|
|
@@ -113469,6 +113513,7 @@ async function runAdCampaignStatus(opts) {
|
|
|
113469
113513
|
`);
|
|
113470
113514
|
}
|
|
113471
113515
|
async function runAdCampaignDelete(opts) {
|
|
113516
|
+
opts = withResolvedAdAccount(opts);
|
|
113472
113517
|
const config = loadConfig(opts.token);
|
|
113473
113518
|
const googleApiUrl = requireGoogleApi(config);
|
|
113474
113519
|
const detailUrl = `${googleApiUrl}/campaignmanagement/campaign/${opts.account}/${opts.id}`;
|
|
@@ -113506,6 +113551,7 @@ async function runAdCampaignDelete(opts) {
|
|
|
113506
113551
|
}
|
|
113507
113552
|
async function runAdCampaignCreate(opts) {
|
|
113508
113553
|
const cfg = loadCampaignCreateConfig(opts.configFile);
|
|
113554
|
+
cfg.account = resolveAdAccountId(cfg.account, "account");
|
|
113509
113555
|
const { errors, warnings } = runCampaignCreateValidation(cfg);
|
|
113510
113556
|
if (warnings.length > 0) {
|
|
113511
113557
|
console.warn("\n\u26A0\uFE0F \u6295\u653E\u914D\u7F6E\u8B66\u544A\uFF08\u4E0D\u963B\u65AD\u63D0\u4EA4\uFF0C\u4F46\u5EFA\u8BAE\u4FEE\u6B63\uFF09\uFF1A");
|
|
@@ -113712,6 +113758,7 @@ function validateCampaignEditBidding(opts) {
|
|
|
113712
113758
|
}
|
|
113713
113759
|
}
|
|
113714
113760
|
async function runAdCampaignEdit(opts) {
|
|
113761
|
+
opts = withResolvedAdAccount(opts);
|
|
113715
113762
|
validateCampaignEditBidding(opts);
|
|
113716
113763
|
const config = loadConfig(opts.token);
|
|
113717
113764
|
const googleApiUrl = requireGoogleApi(config);
|
|
@@ -113781,6 +113828,7 @@ init_cli_json_snapshot();
|
|
|
113781
113828
|
init_strip_legacy_google_fields();
|
|
113782
113829
|
init_cli_table();
|
|
113783
113830
|
async function runAdGroups(opts) {
|
|
113831
|
+
opts = withResolvedAdAccount(opts);
|
|
113784
113832
|
const config = loadConfig(opts.token);
|
|
113785
113833
|
const googleApiUrl = requireGoogleApi(config);
|
|
113786
113834
|
const params = new URLSearchParams();
|
|
@@ -113872,6 +113920,7 @@ function adGroupRowToYuan(item) {
|
|
|
113872
113920
|
};
|
|
113873
113921
|
}
|
|
113874
113922
|
async function runAdGroupCreate(opts) {
|
|
113923
|
+
opts = withResolvedAdAccount(opts);
|
|
113875
113924
|
const config = loadConfig(opts.token);
|
|
113876
113925
|
const googleApiUrl = requireGoogleApi(config);
|
|
113877
113926
|
const body = {
|
|
@@ -113923,6 +113972,7 @@ async function runAdGroupCreate(opts) {
|
|
|
113923
113972
|
}
|
|
113924
113973
|
}
|
|
113925
113974
|
async function runAdGroupStatus(opts) {
|
|
113975
|
+
opts = withResolvedAdAccount(opts);
|
|
113926
113976
|
const config = loadConfig(opts.token);
|
|
113927
113977
|
const googleApiUrl = requireGoogleApi(config);
|
|
113928
113978
|
const listUrl = adgroupListUrl(googleApiUrl, opts.account, opts.startDate, opts.endDate);
|
|
@@ -113950,6 +114000,7 @@ async function runAdGroupStatus(opts) {
|
|
|
113950
114000
|
`);
|
|
113951
114001
|
}
|
|
113952
114002
|
async function runAdGroupDelete(opts) {
|
|
114003
|
+
opts = withResolvedAdAccount(opts);
|
|
113953
114004
|
const config = loadConfig(opts.token);
|
|
113954
114005
|
const googleApiUrl = requireGoogleApi(config);
|
|
113955
114006
|
const listUrl = adgroupListUrl(googleApiUrl, opts.account, opts.startDate, opts.endDate);
|
|
@@ -113976,6 +114027,7 @@ async function runAdGroupDelete(opts) {
|
|
|
113976
114027
|
`);
|
|
113977
114028
|
}
|
|
113978
114029
|
async function runAdGroupRename(opts) {
|
|
114030
|
+
opts = withResolvedAdAccount(opts);
|
|
113979
114031
|
const config = loadConfig(opts.token);
|
|
113980
114032
|
const googleApiUrl = requireGoogleApi(config);
|
|
113981
114033
|
const listUrl = adgroupListUrl(googleApiUrl, opts.account, opts.startDate, opts.endDate);
|
|
@@ -114003,6 +114055,7 @@ async function runAdGroupRename(opts) {
|
|
|
114003
114055
|
`);
|
|
114004
114056
|
}
|
|
114005
114057
|
async function runAdGroupEdit(opts) {
|
|
114058
|
+
opts = withResolvedAdAccount(opts);
|
|
114006
114059
|
const hasName = opts.name !== void 0 && opts.name.trim() !== "";
|
|
114007
114060
|
const hasMax = opts.maxCPCAmount !== void 0;
|
|
114008
114061
|
const hasTcpa = opts.targetCpaAmount !== void 0;
|
|
@@ -114125,6 +114178,7 @@ function formatRsaCliValidationError(errors) {
|
|
|
114125
114178
|
|
|
114126
114179
|
// src/commands/ad/ad-creative.ts
|
|
114127
114180
|
async function runAdList(opts) {
|
|
114181
|
+
opts = withResolvedAdAccount(opts);
|
|
114128
114182
|
const config = loadConfig(opts.token);
|
|
114129
114183
|
const googleApiUrl = requireGoogleApi(config);
|
|
114130
114184
|
const params = new URLSearchParams();
|
|
@@ -114201,6 +114255,7 @@ async function runAdList(opts) {
|
|
|
114201
114255
|
console.log();
|
|
114202
114256
|
}
|
|
114203
114257
|
async function runAdCreate(opts) {
|
|
114258
|
+
opts = withResolvedAdAccount(opts);
|
|
114204
114259
|
const config = loadConfig(opts.token);
|
|
114205
114260
|
const googleApiUrl = requireGoogleApi(config);
|
|
114206
114261
|
const rsaErrors = validateRsaCliCopy({
|
|
@@ -114267,6 +114322,7 @@ async function runAdCreate(opts) {
|
|
|
114267
114322
|
}
|
|
114268
114323
|
}
|
|
114269
114324
|
async function runAdStatus(opts) {
|
|
114325
|
+
opts = withResolvedAdAccount(opts);
|
|
114270
114326
|
const config = loadConfig(opts.token);
|
|
114271
114327
|
const googleApiUrl = requireGoogleApi(config);
|
|
114272
114328
|
const params = new URLSearchParams();
|
|
@@ -114297,6 +114353,7 @@ async function runAdStatus(opts) {
|
|
|
114297
114353
|
`);
|
|
114298
114354
|
}
|
|
114299
114355
|
async function runAdDelete(opts) {
|
|
114356
|
+
opts = withResolvedAdAccount(opts);
|
|
114300
114357
|
const config = loadConfig(opts.token);
|
|
114301
114358
|
const googleApiUrl = requireGoogleApi(config);
|
|
114302
114359
|
const params = new URLSearchParams();
|
|
@@ -114326,6 +114383,7 @@ async function runAdDelete(opts) {
|
|
|
114326
114383
|
`);
|
|
114327
114384
|
}
|
|
114328
114385
|
async function runAdEdit(opts) {
|
|
114386
|
+
opts = withResolvedAdAccount(opts);
|
|
114329
114387
|
const config = await ensureDataPermission(loadConfig(opts.token));
|
|
114330
114388
|
const googleApiUrl = requireGoogleApi(config);
|
|
114331
114389
|
const hasTextOrUrl = opts.headlines || opts.descriptions || opts.finalUrl !== void 0 || opts.path1 !== void 0 || opts.path2 !== void 0;
|
|
@@ -114629,6 +114687,7 @@ function buildBusinessMessageBodyForCampaign(accountId, campaignId, bm) {
|
|
|
114629
114687
|
|
|
114630
114688
|
// src/commands/ad/extension.ts
|
|
114631
114689
|
async function runAdExtensionList(opts) {
|
|
114690
|
+
opts = withResolvedAdAccount(opts);
|
|
114632
114691
|
const config = loadConfig(opts.token);
|
|
114633
114692
|
const googleApiUrl = requireGoogleApi(config);
|
|
114634
114693
|
const url = `${googleApiUrl}/extensionmanagement/v2/list/${opts.account}`;
|
|
@@ -114705,6 +114764,7 @@ async function runAdExtensionList(opts) {
|
|
|
114705
114764
|
console.log();
|
|
114706
114765
|
}
|
|
114707
114766
|
async function runAdExtensionCreate(opts) {
|
|
114767
|
+
opts = withResolvedAdAccount(opts);
|
|
114708
114768
|
const config = loadConfig(opts.token);
|
|
114709
114769
|
const googleApiUrl = requireGoogleApi(config);
|
|
114710
114770
|
const body = {
|
|
@@ -114782,6 +114842,7 @@ async function runAdExtensionCreate(opts) {
|
|
|
114782
114842
|
}
|
|
114783
114843
|
}
|
|
114784
114844
|
async function runAdExtensionDelete(opts) {
|
|
114845
|
+
opts = withResolvedAdAccount(opts);
|
|
114785
114846
|
const config = loadConfig(opts.token);
|
|
114786
114847
|
const googleApiUrl = requireGoogleApi(config);
|
|
114787
114848
|
const listUrl = `${googleApiUrl}/extensionmanagement/v2/list/${opts.account}`;
|
|
@@ -114883,6 +114944,7 @@ async function runAdExtensionSnippetHeaders(opts) {
|
|
|
114883
114944
|
console.log();
|
|
114884
114945
|
}
|
|
114885
114946
|
async function runAdExtensionLeadFormCreate(opts) {
|
|
114947
|
+
opts = withResolvedAdAccount(opts);
|
|
114886
114948
|
const config = loadConfig(opts.token);
|
|
114887
114949
|
const googleApiUrl = requireGoogleApi(config);
|
|
114888
114950
|
let cfg;
|
|
@@ -114941,6 +115003,7 @@ async function runAdExtensionLeadFormCreate(opts) {
|
|
|
114941
115003
|
);
|
|
114942
115004
|
}
|
|
114943
115005
|
async function runAdExtensionWhatsappCreate(opts) {
|
|
115006
|
+
opts = withResolvedAdAccount(opts);
|
|
114944
115007
|
const config = loadConfig(opts.token);
|
|
114945
115008
|
const googleApiUrl = requireGoogleApi(config);
|
|
114946
115009
|
if (!opts.configFile) {
|
|
@@ -115003,6 +115066,7 @@ function detectExtensionUpdateKind(raw) {
|
|
|
115003
115066
|
process.exit(1);
|
|
115004
115067
|
}
|
|
115005
115068
|
async function runAdExtensionUpdate(opts) {
|
|
115069
|
+
opts = withResolvedAdAccount(opts);
|
|
115006
115070
|
const config = loadConfig(opts.token);
|
|
115007
115071
|
const googleApiUrl = requireGoogleApi(config);
|
|
115008
115072
|
let raw;
|
|
@@ -115077,6 +115141,7 @@ init_cli_json_snapshot();
|
|
|
115077
115141
|
init_strip_legacy_google_fields();
|
|
115078
115142
|
init_cli_table();
|
|
115079
115143
|
async function runAdSearchTerms(opts) {
|
|
115144
|
+
opts = withResolvedAdAccount(opts);
|
|
115080
115145
|
const config = loadConfig(opts.token);
|
|
115081
115146
|
const googleApiUrl = requireGoogleApi(config);
|
|
115082
115147
|
const params = new URLSearchParams();
|
|
@@ -115205,6 +115270,7 @@ function resolveCriterionId(rows, opts) {
|
|
|
115205
115270
|
return String(match.id);
|
|
115206
115271
|
}
|
|
115207
115272
|
async function runAdDeviceBidList(opts) {
|
|
115273
|
+
opts = withResolvedAdAccount(opts);
|
|
115208
115274
|
const config = loadConfig(opts.token);
|
|
115209
115275
|
const googleApiUrl = requireGoogleApi(config);
|
|
115210
115276
|
const level = opts.level ?? "campaign";
|
|
@@ -115301,6 +115367,7 @@ async function runAdDeviceBidList(opts) {
|
|
|
115301
115367
|
console.log();
|
|
115302
115368
|
}
|
|
115303
115369
|
async function runAdDeviceBidSet(opts) {
|
|
115370
|
+
opts = withResolvedAdAccount(opts);
|
|
115304
115371
|
const config = loadConfig(opts.token);
|
|
115305
115372
|
const googleApiUrl = requireGoogleApi(config);
|
|
115306
115373
|
const level = opts.level ?? "campaign";
|
|
@@ -115431,6 +115498,7 @@ function pickGeoResolveCandidate(query, items2) {
|
|
|
115431
115498
|
return items2[0] ?? null;
|
|
115432
115499
|
}
|
|
115433
115500
|
async function runAdGeoSearch(opts) {
|
|
115501
|
+
opts = withResolvedAdAccount(opts);
|
|
115434
115502
|
const config = loadConfig(opts.token);
|
|
115435
115503
|
const googleApiUrl = requireGoogleApi(config);
|
|
115436
115504
|
let items2;
|
|
@@ -115503,6 +115571,7 @@ function parseGeoResolveQueries(opts) {
|
|
|
115503
115571
|
return unique;
|
|
115504
115572
|
}
|
|
115505
115573
|
async function runAdGeoResolve(opts) {
|
|
115574
|
+
opts = withResolvedAdAccount(opts);
|
|
115506
115575
|
let queries;
|
|
115507
115576
|
try {
|
|
115508
115577
|
queries = parseGeoResolveQueries(opts);
|
|
@@ -115614,6 +115683,7 @@ async function runAdGeoResolve(opts) {
|
|
|
115614
115683
|
}
|
|
115615
115684
|
}
|
|
115616
115685
|
async function runAdGeoList(opts) {
|
|
115686
|
+
opts = withResolvedAdAccount(opts);
|
|
115617
115687
|
const config = loadConfig(opts.token);
|
|
115618
115688
|
const googleApiUrl = requireGoogleApi(config);
|
|
115619
115689
|
let url;
|
|
@@ -115677,6 +115747,7 @@ async function runAdGeoList(opts) {
|
|
|
115677
115747
|
console.log();
|
|
115678
115748
|
}
|
|
115679
115749
|
async function runAdGeoAdd(opts) {
|
|
115750
|
+
opts = withResolvedAdAccount(opts);
|
|
115680
115751
|
const config = loadConfig(opts.token);
|
|
115681
115752
|
const googleApiUrl = requireGoogleApi(config);
|
|
115682
115753
|
const body = {
|
|
@@ -115703,6 +115774,7 @@ async function runAdGeoAdd(opts) {
|
|
|
115703
115774
|
`);
|
|
115704
115775
|
}
|
|
115705
115776
|
async function runAdGeoRemove(opts) {
|
|
115777
|
+
opts = withResolvedAdAccount(opts);
|
|
115706
115778
|
const config = loadConfig(opts.token);
|
|
115707
115779
|
const googleApiUrl = requireGoogleApi(config);
|
|
115708
115780
|
const body = { campaignId: opts.campaignId, id: opts.locationId };
|
|
@@ -115743,6 +115815,7 @@ function resolveGeoCriterionId(rows, opts) {
|
|
|
115743
115815
|
return String(match["id"]);
|
|
115744
115816
|
}
|
|
115745
115817
|
async function runAdGeoSetBid(opts) {
|
|
115818
|
+
opts = withResolvedAdAccount(opts);
|
|
115746
115819
|
const config = loadConfig(opts.token);
|
|
115747
115820
|
const googleApiUrl = requireGoogleApi(config);
|
|
115748
115821
|
if (opts.bidModifier < 0) {
|
|
@@ -116599,11 +116672,12 @@ async function runCampaignBatchDiff(opts) {
|
|
|
116599
116672
|
`);
|
|
116600
116673
|
process.exit(1);
|
|
116601
116674
|
}
|
|
116602
|
-
const
|
|
116603
|
-
if (!
|
|
116675
|
+
const rawAccountId = pickString2(opts.account, cfg.account);
|
|
116676
|
+
if (!rawAccountId) {
|
|
116604
116677
|
console.error("\n\u274C \u7F3A\u5C11\u8D26\u6237 ID\uFF1A\u8BF7\u5728 JSON \u4E2D\u586B\u5199 account \u6216\u4F7F\u7528 -a\n");
|
|
116605
116678
|
process.exit(1);
|
|
116606
116679
|
}
|
|
116680
|
+
const accountId = resolveAdAccountId(rawAccountId, "account / -a");
|
|
116607
116681
|
cfg.account = accountId;
|
|
116608
116682
|
const config = loadConfig(opts.token);
|
|
116609
116683
|
let campaignId = pickString2(opts.campaignId);
|
|
@@ -118624,14 +118698,7 @@ async function emitPmaxResult(opts, section, commandLabel, payload, idSuffix) {
|
|
|
118624
118698
|
});
|
|
118625
118699
|
}
|
|
118626
118700
|
function requireAccountId(account, label = "-a, --account") {
|
|
118627
|
-
|
|
118628
|
-
if (!id) {
|
|
118629
|
-
console.error(`
|
|
118630
|
-
\u274C \u8BF7\u6307\u5B9A\u5A92\u4F53\u8D26\u6237 ID\uFF08${label}\uFF09
|
|
118631
|
-
`);
|
|
118632
|
-
process.exit(1);
|
|
118633
|
-
}
|
|
118634
|
-
return id;
|
|
118701
|
+
return resolveAdAccountId(account, label);
|
|
118635
118702
|
}
|
|
118636
118703
|
|
|
118637
118704
|
// src/commands/ad/pmax-video-upload.ts
|
|
@@ -118994,7 +119061,8 @@ async function runAdPmaxCreate(opts) {
|
|
|
118994
119061
|
}
|
|
118995
119062
|
const config = await ensureDataPermission(loadConfig(opts.token));
|
|
118996
119063
|
const googleApiUrl = requireGoogleApi(config);
|
|
118997
|
-
const accountId = cfg.account.toString()
|
|
119064
|
+
const accountId = resolveAdAccountId(cfg.account.toString(), "account");
|
|
119065
|
+
cfg.account = accountId;
|
|
118998
119066
|
let imageSlots;
|
|
118999
119067
|
try {
|
|
119000
119068
|
imageSlots = await resolvePmaxImageSlots(
|
|
@@ -122803,6 +122871,7 @@ async function runAccountMe(opts) {
|
|
|
122803
122871
|
init_dist();
|
|
122804
122872
|
init_auth();
|
|
122805
122873
|
init_cli_json_snapshot();
|
|
122874
|
+
init_media_customer_id();
|
|
122806
122875
|
|
|
122807
122876
|
// src/commands/account-manage/google-mcc.ts
|
|
122808
122877
|
init_auth();
|
|
@@ -122978,18 +123047,14 @@ function hintGoogleOAuth(kind) {
|
|
|
122978
123047
|
return "\u6267\u884C siluzan-tso account auth -m Google \u5B8C\u6210 OAuth \u7ED1\u5B9A\u3002";
|
|
122979
123048
|
}
|
|
122980
123049
|
function assertGoogleMediaCustomerId(raw) {
|
|
122981
|
-
|
|
122982
|
-
|
|
122983
|
-
|
|
122984
|
-
|
|
122985
|
-
|
|
122986
|
-
|
|
122987
|
-
console.error(
|
|
122988
|
-
"\n\u274C --account \u987B\u4E3A Google mediaCustomerId\uFF08\u7EAF\u6570\u5B57\uFF0C\u4E0E list-accounts -m Google \u4E00\u81F4\uFF09\u3002\n"
|
|
122989
|
-
);
|
|
123050
|
+
try {
|
|
123051
|
+
return requireNumericMediaCustomerId(raw, "--account");
|
|
123052
|
+
} catch (e) {
|
|
123053
|
+
console.error(`
|
|
123054
|
+
\u274C ${e instanceof Error ? e.message : String(e)}
|
|
123055
|
+
`);
|
|
122990
123056
|
process.exit(1);
|
|
122991
123057
|
}
|
|
122992
|
-
return id;
|
|
122993
123058
|
}
|
|
122994
123059
|
function parseCustomerAccessPermissionBody(text) {
|
|
122995
123060
|
const trimmed = text.trim();
|
package/dist/skill/SKILL.md
CHANGED
|
@@ -38,7 +38,9 @@ siluzan-tso -h
|
|
|
38
38
|
|
|
39
39
|
## 即时规范
|
|
40
40
|
|
|
41
|
-
- `entityId`(UUID)≠ `mediaCustomerId`(`list-accounts` 的 `ma.mediaCustomerId`:Google/TikTok/Bing 多为数字;**Yandex=`porg-…`**;Meta 常带 `act_`)。`stats`/`balance`/`accounts-digest
|
|
41
|
+
- `entityId`(UUID)≠ `mediaCustomerId`(`list-accounts` 的 `ma.mediaCustomerId`:Google/TikTok/Bing 多为数字;**Yandex=`porg-…`**;Meta 常带 `act_`)。`stats`/`balance`/`accounts-digest`/`ad *` 的 `-a` **只传 mediaCustomerId**;空结果或 verbose 打出 403 时**先核验 ID**,禁止把 UUID/`entityId` 传给 `-a`,也**禁止**据此直接 `reauth`。
|
|
42
|
+
- **Google CID 特殊性**:UI 常写 `123-456-7890`(带连字符),平台 `mediaCustomerId` 为纯数字 `1234567890`。CLI 会自动去连字符;**勿**把带横杠 403 误判为 OAuth 失效。优先用 `list-accounts` 的纯数字 ID。
|
|
43
|
+
- **禁止臆测授权过期**:见 403/`HTTP 403`/拉数失败/「可能 OAuth 失效」时,**禁止**口头推断授权过期或直接 `reauth`。须先核验 ID(及 Google 连字符),再跑 `account check-access -a <mediaCustomerId>`(套餐已激活前提下),以返回的 `accessible` / `reauth_required` / `no_permission` 为准;细则见 `accounts-permissions.md`。
|
|
42
44
|
- `list-accounts` 无余额/消耗;列全部用 `--page-size 999`。
|
|
43
45
|
- 多户余额用 `balance-scan`(P2),多户消耗用 `accounts-digest`(P3);禁止外层 for-loop 逐户拉数。
|
|
44
46
|
- `stats` 的 `spend` = **区间合计**,不是日消耗。
|
package/dist/skill/_meta.json
CHANGED
|
@@ -35,7 +35,9 @@ siluzan-tso account me --check-phone 15130150466 --json-out ./snap-me
|
|
|
35
35
|
|
|
36
36
|
校验当前丝路赞凭据是否对指定 **Google** 广告账户有访问权限。应在拉数/诊断前调用,避免误用他户 ID。
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
> **硬约束**:**禁止**凭 403、空结果或经验臆测「授权/OAuth 过期」。要对用户下「授权不可用 / 需重授权」结论前,**必须**先跑本命令(并满足下方套餐已激活前提),以 CLI 返回的 `status` 为准;**禁止**跳过本命令直接 `reauth` 或口头推断。
|
|
39
|
+
|
|
40
|
+
**前提(查授权是否过期时)**:须先确认该户 **套餐已激活**(`list-accounts` 的 `ma.scopeActivatedSources` 有未过期条目,或 Google 表格「套餐激活」= ✅ 已激活)。在已激活前提下,**必须**用本命令检查授权是否可用:
|
|
39
41
|
|
|
40
42
|
| 结果 | 含义(套餐已激活时) |
|
|
41
43
|
| ---- | -------------------- |
|
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
- `list-accounts` **不含**余额/消耗;列全部账户用 `--page-size 999`,禁止默认 20 再翻页。
|
|
20
20
|
- `entityId`(UUID,分享/delink/账单/`reauth`)≠ `mediaCustomerId`(`balance`/`stats`/`accounts-digest`/`ad` 的 `-a`)。**Yandex 的 mediaCustomerId 形如 `porg-…`,不是 UUID。**
|
|
21
21
|
- MetaAd OAuth 户的 `mediaCustomerId` **须带 `act_` 前缀**。
|
|
22
|
-
- `stats`/`balance
|
|
22
|
+
- **Google CID**:广告后台展示常为 `XXX-XXX-XXXX`(连字符),`list-accounts` / 网关要的是**纯数字**(无横杠)。`stats`/`balance`/`ad *`/`google-analysis` 的 `-a` 可带连字符(CLI 会去掉);若仍见 `HTTP 403:123-456-7890` 这类**回显带横杠 ID**,优先改成纯数字重试,**不要**直接当 OAuth 失效去 `reauth`。
|
|
23
|
+
- **禁止臆测授权过期**:403 / 拉数失败时**禁止**口头说「可能授权过期」。须 ID 核验后,对 Google 在套餐已激活前提下执行 `account check-access -a <mediaCustomerId>`,以返回 `status` 为准(见 [`accounts-permissions.md`](accounts-permissions.md));非 Google 看 `list-accounts` 的 `invalidOAuthToken`。
|
|
24
|
+
- `stats`/`balance` 空结果 + verbose `HTTP 403`:先确认 `-a` 是否为 `ma.mediaCustomerId`(且 Google 已去连字符);**禁止**把 `entityId` / tokenId 当 `-a`;未跑 `account check-access`(或未见 `invalidOAuthToken=true`)**禁止** `reauth`。
|
|
23
25
|
- 多账户余额预警用 `balance-scan`(P2),多账户消耗汇总用 `accounts-digest`(P3);**禁止**外层 for-loop 逐户 `balance`/`stats`。
|
|
24
26
|
- `stats` 默认 `spend` = **区间合计**,不是日消耗;日均看 `balance-scan.dailySpend` 或合计÷天数。
|
|
@@ -126,7 +126,8 @@
|
|
|
126
126
|
|
|
127
127
|
- **账户状态 ≠ 系列状态**:`stats` / `balance` / `list-accounts` 的 `status` 只表示账户是否可用;系列状态必须来自 `ad campaigns`。
|
|
128
128
|
- **数据时效性**:涉及「今天/当天/今日消耗」「实时消耗排行」前,必读 `references/analytics/account-analytics.md` 顶部「数据时效性」表。TikTok / Yandex / BingV2 / Kwai 是 `accountsoverview` 同步昨天数据,**不能查今天**。
|
|
129
|
-
- **先查账户再操作**(拉数 / 改账户 / 报告 / **创建广告**):`list-accounts -m [mediaType] -k [mediaCustomerId]`;用户给出的 `mediaCustomerId` 必须 `-k` 核验,无结果则告知用户并停止,**禁止**翻页 grep 自行换 ID(会导致报告错户);拉数、脚本、报告文件名全链路用同一 ID(以 stdout `accountId`
|
|
129
|
+
- **先查账户再操作**(拉数 / 改账户 / 报告 / **创建广告**):`list-accounts -m [mediaType] -k [mediaCustomerId]`;用户给出的 `mediaCustomerId` 必须 `-k` 核验,无结果则告知用户并停止,**禁止**翻页 grep 自行换 ID(会导致报告错户);拉数、脚本、报告文件名全链路用同一 ID(以 stdout `accountId` 为准)。
|
|
130
|
+
- **禁止臆测授权过期(硬约束)**:任何 403、空结果、「可能授权/OAuth 过期」话术,**禁止**凭感觉下结论或直接 `reauth`。Google:在 `list-accounts` 确认套餐**已激活**后,**必须**执行 `account check-access -a <mediaCustomerId>`,仅当结果为 `reauth_required`(或列表 `invalidOAuthToken=true` 与之交叉确认)才谈重授权;`no_permission` 也可能是账户不在当前丝路赞账号下。**未激活套餐时勿用 check-access 判断授权过期**。非 Google 媒体以 `list-accounts` 的 `invalidOAuthToken` 为准,同样禁止臆测。详见 `accounts-permissions.md`。
|
|
130
131
|
- **一律走 CLI,禁止自拼网关请求**:查余额 / 拉数 / 写操作只用 `siluzan-tso …`。**禁止**用 curl、自写脚本或改请求头直连 TSO/Google 网关「另辟蹊径」取数;`balance` 等无数据时按 CLI/`list-accounts` 字段向用户说明(如套餐未激活、授权失效),**禁止**尝试任何绕过平台门禁的取数方式。
|
|
131
132
|
- **W3 仅出方案例外(覆盖上条)**:用户只要「投放方案 / 规划 / 表格 / 先别创建·开户·投钱」,或未给账户且未要求创建/发布时——**禁止**把「请先提供 Google 广告账户」当作第一步;按 `google-ads-campaign-plan.md` §「仅出方案 vs 创建」落盘 JSON 后 **写代码**投影完整审查稿(默认 MD;用户指定则 Excel 等;`account`=`[PENDING_ACCOUNT]`),跳过 `list-accounts` / `geo resolve` / validate / create。**禁止**只交概览表。用户确认要创建后再要账户并续跑创建流水线。
|
|
132
133
|
- **W3 审查稿(搜索与 PMax)**:JSON 落盘后、创建前,必须 **写代码**读取 JSON,按 `google-ads-launch-plan-template.md`(搜索)或 `google-ads-pmax-launch-plan-template.md`(PMax)生成完整审查文件交给用户;须含全部关键词/RSA 或全部 PMax 文案与附加资产。**禁止**用「方案总结」条数勾选代替。用户要求其他格式时改脚本输出,数据仍只从 JSON 来。
|
|
@@ -276,7 +277,7 @@
|
|
|
276
277
|
|
|
277
278
|
- **400**:参数错误,查看对应 reference 或 `-h`
|
|
278
279
|
- **401 / OAuth 失效**:仅当 `list-accounts` 的 `invalidOAuthToken=true`(或表格「授权状态」为失效)且用户确认后——Siluzan Agent **优先**用平台重新授权工具(如 `present_reauth`);备选 `account reauth -m <媒体> --id <entityId> --i-confirm --commit "…"`(内置 delink→OAuth,见 W9 / `accounts-permissions.md`)。走 CLI 时**必须把 stdout 中的完整授权 URL 原样贴给用户**,禁止只说「链接已生成」,也**禁止**自行改写/补全该 URL。解绑后若列表已无该户,恢复用平台授权工具或 `account auth -m <媒体>`。**丝路赞登录凭据失效** → `send-login-code` + `login --phone --code`,见 `references/core/setup.md`
|
|
279
|
-
- **403
|
|
280
|
+
- **403(拉数空结果 / ad 网关)**:① **优先核验 `-a` 是否为 `ma.mediaCustomerId`**(勿传 `entityId`/UUID;Google 注意连字符 CID;Yandex 形如 `porg-…`);② Google 看套餐是否激活(`scopeActivatedSources`),未激活则说明需先激活,**禁止**非 CLI 绕过取数;③ **禁止臆测授权过期**:套餐已激活时**必须**跑 `account check-access -a <mediaCustomerId>`,以 `status` 为准后再决定是否 `reauth`;**禁止**仅凭 403 文案对用户说「授权过期」。
|
|
280
281
|
- **500**:服务可能正在部署/升级,建议反馈 Siluzan 相关人员
|
|
281
282
|
|
|
282
283
|
---
|
|
@@ -26,12 +26,14 @@
|
|
|
26
26
|
|
|
27
27
|
| 需要的 ID | 获取命令 |
|
|
28
28
|
| ------------------- | ----------------------------------------------------------------------- |
|
|
29
|
-
| `accountId`(`-a`) | `siluzan-tso list-accounts --json-out ./snap` → `mediaCustomerId`
|
|
29
|
+
| `accountId`(`-a`) | `siluzan-tso list-accounts -m Google --json-out ./snap` → `mediaCustomerId`(**纯数字**;UI 的 `123-456-7890` 可原样传入,CLI 去连字符) |
|
|
30
30
|
| 广告系列 `id` | `siluzan-tso ad campaigns -a <accountId> --json-out ./snap` → `id` |
|
|
31
31
|
| 广告组 `id`、`name` | `siluzan-tso ad groups -a <accountId> --json-out ./snap` → `id`、`name` |
|
|
32
32
|
| 广告 `id` | `siluzan-tso ad list -a <accountId> --json-out ./snap` → `id` |
|
|
33
33
|
| 关键词 `id` | `siluzan-tso ad keywords -a <accountId> --json-out ./snap` → `id` |
|
|
34
34
|
|
|
35
|
+
> **Google CID**:带连字符进网关曾导致 `HTTP 403:123-456-7890`;现 CLI 已归一化。仍失败时用纯数字重试;**禁止臆测授权过期**,须 `account check-access -a <mediaCustomerId>`(详见 [google-ads.md](google-ads.md) Gotchas / `accounts-permissions.md`)。
|
|
36
|
+
|
|
35
37
|
---
|
|
36
38
|
|
|
37
39
|
## ad campaigns — 广告系列管理
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
|
|
33
33
|
| 需要的 ID | 获取命令 |
|
|
34
34
|
| ------------------- | ----------------------------------------------------------------------- |
|
|
35
|
-
| `accountId`(`-a`) | `
|
|
35
|
+
| `accountId`(`-a`) / JSON `account` | `list-accounts -m Google` → `mediaCustomerId`(纯数字;UI 带连字符 CID 可传入,CLI 去横杠,见 [google-ads.md](google-ads.md) Gotchas) |
|
|
36
36
|
| 广告系列 `id` | `siluzan-tso ad campaigns -a <accountId> --json-out ./snap` → `id` |
|
|
37
37
|
| 广告组 `id`、`name` | `siluzan-tso ad groups -a <accountId> --json-out ./snap` → `id`、`name` |
|
|
38
38
|
| 广告 `id` | `siluzan-tso ad list -a <accountId> --json-out ./snap` → `id` |
|
|
@@ -15,6 +15,10 @@
|
|
|
15
15
|
|
|
16
16
|
## Gotchas
|
|
17
17
|
|
|
18
|
+
- **Google 客户 ID(CID)带连字符**:UI / 用户口述常为 `123-456-7890`,平台 `mediaCustomerId` 与 Google 网关路径需要 `1234567890`。`ad campaigns` / `ad groups` / `ad list` 等 `-a` 与 JSON 顶层 `account` **可带连字符**(CLI 自动去掉)。若错误为 `HTTP 403:123-456-7890`(回显带横杠),先换纯数字重试,**禁止**据此直接判断 OAuth 过期或 `reauth`。
|
|
19
|
+
- **禁止臆测授权过期**:`ad *` / 拉数出现 403 或失败时,**禁止**对用户说「授权可能过期」。须核验 ID 后,在套餐已激活前提下执行 `account check-access -a <mediaCustomerId>`,仅当 `reauth_required`(或与 `invalidOAuthToken=true` 交叉确认)才走重授权。见 [`accounts-permissions.md`](../accounts/accounts-permissions.md)。
|
|
20
|
+
- `-a` 必须是 `list-accounts -m Google` 的 `ma.mediaCustomerId`,**禁止**传 `entityId`(UUID)。
|
|
21
|
+
|
|
18
22
|
## 金额单位(全局重要)
|
|
19
23
|
|
|
20
24
|
> **所有 CLI 金额参数均按「主币种金额」传入**(如 `1.5` = ¥1.50 / $1.50);CLI 写入网关前对「分」字段 ×100(含 `ad keyword-edit --max-cpc` → `maxCPC`)。
|
|
@@ -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.43-beta.
|
|
12
|
+
$PKG_VERSION = '1.1.43-beta.3'
|
|
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.43-beta.
|
|
12
|
+
readonly PKG_VERSION="1.1.43-beta.3"
|
|
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"
|