siluzan-tso-cli 1.1.43 → 1.1.44-beta.2

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
@@ -43,7 +43,7 @@ HTML 报告模板外部资源:**ECharts** 统一使用 `https://staticpn.siluz
43
43
  在**用户的目标项目根目录**执行(根据用户使用的助手选择 `--ai`):
44
44
 
45
45
  ```bash
46
- npm install -g siluzan-tso-cli
46
+ npm install -g siluzan-tso-cli@beta
47
47
  siluzan-tso init --ai cursor # 写入 Cursor(默认)
48
48
  siluzan-tso init --ai cursor,claude # 同时写入多个平台
49
49
  siluzan-tso init --ai all # 写入所有支持的平台
@@ -51,6 +51,7 @@ siluzan-tso init -d /path/to/skills # 写入自定义目录
51
51
  siluzan-tso init --force # 强制覆盖已存在文件
52
52
  ```
53
53
 
54
+ > **注意**:当前为测试版(1.1.44-beta.2),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-tso-cli`。
54
55
 
55
56
  | 助手 | 建议 `--ai` |
56
57
  | ----------------------- | ------------------------------------ |
package/dist/index.js CHANGED
@@ -4026,7 +4026,7 @@ var DEFAULT_API_BASE;
4026
4026
  var init_defaults = __esm({
4027
4027
  "src/config/defaults.ts"() {
4028
4028
  "use strict";
4029
- DEFAULT_API_BASE = "https://tso-api.siluzan.com";
4029
+ DEFAULT_API_BASE = "https://tso-api-ci.siluzan.com";
4030
4030
  }
4031
4031
  });
4032
4032
 
@@ -4503,13 +4503,17 @@ var init_currency_display = __esm({
4503
4503
  function fmt(d) {
4504
4504
  return d.toISOString().slice(0, 10);
4505
4505
  }
4506
- function defaultDateRange() {
4506
+ function dateRangeLastNDays(n) {
4507
+ const days = Math.max(1, Math.floor(Number(n) || 1));
4507
4508
  const end = /* @__PURE__ */ new Date();
4508
4509
  end.setDate(end.getDate() - 1);
4509
4510
  const start = new Date(end);
4510
- start.setDate(start.getDate() - 6);
4511
+ start.setDate(start.getDate() - (days - 1));
4511
4512
  return { startDate: fmt(start), endDate: fmt(end) };
4512
4513
  }
4514
+ function defaultDateRange() {
4515
+ return dateRangeLastNDays(7);
4516
+ }
4513
4517
  function resolveAccountOverviewMediaRoute(cliMedia, accountMediaAccountType) {
4514
4518
  if (cliMedia === "MetaAd" && accountMediaAccountType === "FacebookAds") {
4515
4519
  return "FacebookAds";
@@ -105831,7 +105835,11 @@ function register5(program2) {
105831
105835
  }
105832
105836
 
105833
105837
  // src/commands/list-accounts/_shared.ts
105838
+ init_dist();
105834
105839
  init_auth();
105840
+ function shouldExposeScopeActivatedSources() {
105841
+ return resolveCompanySourceType() === "Ctaiad";
105842
+ }
105835
105843
  var VALID_MEDIA_TYPES = [
105836
105844
  "Google",
105837
105845
  "TikTok",
@@ -105970,6 +105978,10 @@ function stripListAccountsEnrichmentFields(item) {
105970
105978
  ]) {
105971
105979
  delete maExt[key];
105972
105980
  }
105981
+ if (!shouldExposeScopeActivatedSources()) {
105982
+ delete item.ma.scopeActivatedSources;
105983
+ delete maExt["scopeActivatedSources"];
105984
+ }
105973
105985
  }
105974
105986
  async function fetchGoogleAccountByMediaCustomerId(config, mediaCustomerId, verbose) {
105975
105987
  const cfg = PLATFORM_CONFIG.Google;
@@ -106054,7 +106066,7 @@ var COL_TIKTOK = [
106054
106066
  { key: "createdAt", header: "\u6388\u6743/\u5F00\u6237\u65F6\u95F4" },
106055
106067
  { key: "shared", header: "\u5206\u4EAB\u8D26\u6237" }
106056
106068
  ];
106057
- var COL_GOOGLE = [
106069
+ var COL_GOOGLE_BASE = [
106058
106070
  { key: "company", header: "\u516C\u53F8\u540D\u79F0" },
106059
106071
  { key: "id", header: "\u8D26\u6237ID" },
106060
106072
  { key: "name", header: "\u8D26\u6237\u540D\u79F0" },
@@ -106067,11 +106079,17 @@ var COL_GOOGLE = [
106067
106079
  { key: "arit", header: "Arit" },
106068
106080
  { key: "platformStatus", header: "\u8D26\u6237\u72B6\u6001" },
106069
106081
  { key: "authStatus", header: "\u6388\u6743\u72B6\u6001" },
106070
- /** 对应 JSON `ma.scopeActivatedSources`(有未过期记录=已激活) */
106071
- { key: "packageStatus", header: "\u5957\u9910\u6FC0\u6D3B" },
106072
106082
  { key: "createdAt", header: "\u6388\u6743/\u5F00\u6237\u65F6\u95F4" },
106073
106083
  { key: "shared", header: "\u5206\u4EAB" }
106074
106084
  ];
106085
+ var COL_GOOGLE_PACKAGE = { key: "packageStatus", header: "\u5957\u9910\u6FC0\u6D3B" };
106086
+ function googleTableColumns() {
106087
+ if (!shouldExposeScopeActivatedSources()) return COL_GOOGLE_BASE;
106088
+ const authIdx = COL_GOOGLE_BASE.findIndex((c) => c.key === "authStatus");
106089
+ const cols = [...COL_GOOGLE_BASE];
106090
+ cols.splice(authIdx + 1, 0, COL_GOOGLE_PACKAGE);
106091
+ return cols;
106092
+ }
106075
106093
  function formatTikTokAuditStatus(ma) {
106076
106094
  const state = ma.mediaAccountState ?? "";
106077
106095
  const tt = ma.TTADInfo?.status ?? "";
@@ -106241,11 +106259,12 @@ function printTikTokTable(items2, tableOpts) {
106241
106259
  printCliTable(rows, COL_TIKTOK, tableOpts);
106242
106260
  }
106243
106261
  function printGoogleTable(items2, tableOpts) {
106262
+ const exposePackage = shouldExposeScopeActivatedSources();
106244
106263
  const rows = items2.map((item) => {
106245
106264
  const ma = item.ma;
106246
106265
  const platformStatus = ma.platformStatus ?? "-";
106247
106266
  const sharedCount = Array.isArray(ma.accountIds) ? String(Math.max(0, ma.accountIds.length - 1)) : "-";
106248
- return {
106267
+ const row = {
106249
106268
  company: item.mag?.advertiserName ?? "-",
106250
106269
  id: String(ma.mediaCustomerId ?? "(\u672A\u5F00\u901A)"),
106251
106270
  name: ma.mediaCustomerName ?? "-",
@@ -106258,12 +106277,15 @@ function printGoogleTable(items2, tableOpts) {
106258
106277
  arit: String(ma.aritScore ?? "-"),
106259
106278
  platformStatus,
106260
106279
  authStatus: formatOAuthAuthStatus(ma),
106261
- packageStatus: formatScopeActivatedStatus(ma),
106262
106280
  createdAt: fmtDate(ma.createdDateTime),
106263
106281
  shared: sharedCount
106264
106282
  };
106283
+ if (exposePackage) {
106284
+ row.packageStatus = formatScopeActivatedStatus(ma);
106285
+ }
106286
+ return row;
106265
106287
  });
106266
- printCliTable(rows, COL_GOOGLE, tableOpts);
106288
+ printCliTable(rows, googleTableColumns(), tableOpts);
106267
106289
  }
106268
106290
  var COL_DEFAULT_WITH_MEDIA = [
106269
106291
  { key: "mediaType", header: "\u5A92\u4F53\u7C7B\u578B" },
@@ -106986,6 +107008,8 @@ async function runBalanceScan(opts) {
106986
107008
  }
106987
107009
  const media = opts.media;
106988
107010
  const thresholdDays = opts.thresholdDays ?? 7;
107011
+ const spendDays = Math.max(1, Math.floor(opts.spendDays ?? 7));
107012
+ const spendWindow = dateRangeLastNDays(spendDays);
106989
107013
  const minBalance = opts.minBalance ?? null;
106990
107014
  const minDailySpend = opts.minDailySpend ?? 0.01;
106991
107015
  const targetDays = opts.targetDays ?? 30;
@@ -107042,17 +107066,19 @@ async function runBalanceScan(opts) {
107042
107066
  media,
107043
107067
  accountIds: validIds,
107044
107068
  config,
107069
+ startDate: spendWindow.startDate,
107070
+ endDate: spendWindow.endDate,
107045
107071
  verbose: opts.verbose,
107046
107072
  accountMediaTypes: buildAccountMediaTypesMap(allItems),
107047
107073
  onChunkStart: (chunkIdx, totalChunks, ids) => {
107048
107074
  process.stderr.write(
107049
- ` \u2192 [\u8FD17\u65E5\u6D88\u8017] \u7B2C ${chunkIdx}/${totalChunks} \u6279\u8BF7\u6C42\u4E2D\uFF08${ids.length} \u6237\uFF09\u2026
107075
+ ` \u2192 [\u8FD1${spendDays}\u65E5\u6D88\u8017] \u7B2C ${chunkIdx}/${totalChunks} \u6279\u8BF7\u6C42\u4E2D\uFF08${ids.length} \u6237\uFF09\u2026
107050
107076
  `
107051
107077
  );
107052
107078
  },
107053
107079
  onOverviewDone: (chunkIdx, totalChunks, ids, size) => {
107054
107080
  process.stderr.write(
107055
- ` \u2713 [\u8FD17\u65E5\u6D88\u8017] \u7B2C ${chunkIdx}/${totalChunks} \u6279\u5B8C\u6210\uFF08${ids.length} \u6237 \u2192 ${size} \u6761\uFF09
107081
+ ` \u2713 [\u8FD1${spendDays}\u65E5\u6D88\u8017] \u7B2C ${chunkIdx}/${totalChunks} \u6279\u5B8C\u6210\uFF08${ids.length} \u6237 \u2192 ${size} \u6761\uFF09
107056
107082
  `
107057
107083
  );
107058
107084
  process.stderr.write(
@@ -107081,8 +107107,8 @@ async function runBalanceScan(opts) {
107081
107107
  const bal = balanceMap.get(id);
107082
107108
  const ov = overviewMap.get(id);
107083
107109
  const balance = bal?.remainingAccountBudget ?? null;
107084
- const sevenDaySpend = Number(ov?.spend ?? 0);
107085
- const dailySpend = sevenDaySpend > 0 ? sevenDaySpend / 7 : 0;
107110
+ const windowSpend = Number(ov?.spend ?? 0);
107111
+ const dailySpend = windowSpend > 0 ? windowSpend / spendDays : 0;
107086
107112
  let remainingDays = null;
107087
107113
  let recommendedTopup = null;
107088
107114
  if (dailySpend >= minDailySpend && balance !== null) {
@@ -107135,6 +107161,8 @@ async function runBalanceScan(opts) {
107135
107161
  minDailySpend,
107136
107162
  targetDaysForTopup: targetDays
107137
107163
  },
107164
+ spendDays,
107165
+ spendWindow,
107138
107166
  pageSize,
107139
107167
  maxPages,
107140
107168
  batchChunkSize: validIds.length > 0 ? batchChunkSize : null,
@@ -107184,7 +107212,7 @@ ${media} \u8D26\u6237\u4F59\u989D\u626B\u63CF\u5B8C\u6210\uFF1A\u5171\u626B\u63C
107184
107212
  { key: "company", header: "\u516C\u53F8" },
107185
107213
  { key: "name", header: "\u8D26\u6237\u540D" },
107186
107214
  { key: "balance", header: "\u4F59\u989D" },
107187
- { key: "daily", header: "\u65E5\u5747\u6D88\u8017(\u8FD17\u65E5)" },
107215
+ { key: "daily", header: `\u65E5\u5747\u6D88\u8017(\u8FD1${spendDays}\u65E5)` },
107188
107216
  { key: "days", header: "\u5269\u4F59\u5929\u6570" },
107189
107217
  { key: "topup", header: `\u5EFA\u8BAE\u5145\u503C(\u76EE\u6807${targetDays}\u5929)` },
107190
107218
  { key: "reason", header: "\u547D\u4E2D\u539F\u56E0" }
@@ -107210,6 +107238,7 @@ ${media} \u8D26\u6237\u4F59\u989D\u626B\u63CF\u5B8C\u6210\uFF1A\u5171\u626B\u63C
107210
107238
  `
107211
107239
  \u63D0\u793A\uFF1A\u4E0A\u8868\u5DF2\u6309\u5269\u4F59\u5929\u6570\u5347\u5E8F\u6392\u5E8F\u3002
107212
107240
  - \u5982\u9700\u8C03\u6574\u9608\u503C\uFF1A--threshold-days 14 / --min-balance 500
107241
+ - \u5982\u9700\u8C03\u6574\u65E5\u5747\u56DE\u770B\u5929\u6570\uFF1A--spend-days 3
107213
107242
  - \u5982\u9700\u8C03\u6574\u5EFA\u8BAE\u5145\u503C\u76EE\u6807\u7EED\u822A\uFF1A--target-days 60
107214
107243
  - \u5982\u9700\u5BFC\u51FA\u7ED3\u6784\u5316\u6570\u636E\uFF1A\u52A0 --json-out <\u76EE\u5F55>\uFF08\u542B meta \u6C47\u603B\uFF0C\u89C1 cli-manifest-<media>.json\uFF09
107215
107244
  `
@@ -107226,17 +107255,17 @@ function register9(program2) {
107226
107255
  ).option(
107227
107256
  "-a, --accounts <ids>",
107228
107257
  "\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"
107229
- ).option(
107230
- "--threshold-days <n>",
107231
- "\u5269\u4F59\u7EED\u822A\u5929\u6570\u9608\u503C\uFF08\u9ED8\u8BA4 7\uFF0C\u6309\u8FD1 7 \u65E5\u65E5\u5747\u6D88\u8017\u4F30\u7B97\uFF09",
107232
- (v) => parseFloat(v)
107258
+ ).option("--threshold-days <n>", "\u5269\u4F59\u7EED\u822A\u5929\u6570\u9608\u503C\uFF08\u9ED8\u8BA4 7\uFF09", (v) => parseFloat(v)).option(
107259
+ "--spend-days <n>",
107260
+ "\u65E5\u5747\u6D88\u8017\u56DE\u770B\u81EA\u7136\u65E5\u6570\uFF08\u622A\u81F3\u6628\u5929\u4E0D\u542B\u4ECA\u5929\uFF1B\u9ED8\u8BA4 7\uFF1B\u65E5\u5747=\u7A97\u53E3\u5408\u8BA1/\u5929\u6570\uFF09",
107261
+ (v) => parseInt(v, 10)
107233
107262
  ).option(
107234
107263
  "--min-balance <n>",
107235
107264
  "\u989D\u5916\u6309\u7EDD\u5BF9\u4F59\u989D\u9608\u503C\u547D\u4E2D\uFF08\u4E3B\u5E01\u79CD\u91D1\u989D\uFF0C\u4E0E --threshold-days \u53D6\u5E76\u96C6\uFF09",
107236
107265
  (v) => parseFloat(v)
107237
107266
  ).option(
107238
107267
  "--min-daily-spend <n>",
107239
- "\u8FD1 7 \u65E5\u65E5\u5747\u6D88\u8017 < \u6B64\u503C\u7684\u8D26\u6237\u89C6\u4E3A\u50F5\u5C38\u8D26\u6237\u4E0D\u505A\u7EED\u822A\u4F30\u7B97\uFF08\u9ED8\u8BA4 0.01\uFF09",
107268
+ "\u8FD1 N \u65E5\u65E5\u5747\u6D88\u8017 < \u6B64\u503C\u7684\u8D26\u6237\u89C6\u4E3A\u50F5\u5C38\u8D26\u6237\u4E0D\u505A\u7EED\u822A\u4F30\u7B97\uFF08\u9ED8\u8BA4 0.01\uFF1BN \u89C1 --spend-days\uFF09",
107240
107269
  (v) => parseFloat(v)
107241
107270
  ).option("--target-days <n>", "\u5EFA\u8BAE\u5145\u503C\u6309\u6B64\u76EE\u6807\u7EED\u822A\u5929\u6570\u8BA1\u7B97\uFF08\u9ED8\u8BA4 30\uFF09", (v) => parseFloat(v)).option("--page-size <n>", "\u5206\u9875\u5927\u5C0F\uFF08\u9ED8\u8BA4 200\uFF0C\u4E0A\u9650 500\uFF09", (v) => parseInt(v, 10)).option(
107242
107271
  "--max-pages <n>",
@@ -107253,6 +107282,7 @@ function register9(program2) {
107253
107282
  media: opts.media,
107254
107283
  accounts: opts.accounts,
107255
107284
  thresholdDays: opts.thresholdDays,
107285
+ spendDays: opts.spendDays,
107256
107286
  minBalance: opts.minBalance,
107257
107287
  minDailySpend: opts.minDailySpend,
107258
107288
  targetDays: opts.targetDays,
@@ -116655,9 +116685,9 @@ function compareCampaignCreateToLive(cfg, campaignId, live, meta) {
116655
116685
  const remediateCount = missing.filter((m) => m.remediateCommand).length;
116656
116686
  let agentHint;
116657
116687
  if (!ok) {
116658
- agentHint = `\u53D1\u73B0 ${missing.length} \u9879\u4E0E\u8BA1\u5212\u4E0D\u4E00\u81F4\uFF08\u8BE6\u89C1 items[] / reportMarkdown\uFF1A\u2705${statusCounts.ok} / \u274C${missing.length} / \u23ED${statusCounts.skipped}\uFF09` + (remediateCount > 0 ? `\uFF1B\u5176\u4E2D ${remediateCount} \u6761\u542B remediateCommand\uFF0CAgent \u5E94\u76F4\u63A5\u6267\u884C\u8865\u5EFA\uFF08\u52FF\u4EC5\u8BE2\u95EE\u7528\u6237\uFF09` : "\uFF1B\u6309 layer \u7528 ad adgroup-create / keyword-create / ad-create / keyword-negative-create / ad geo add / ad extension * \u8865\u5EFA") + "\uFF1B\u8865\u5EFA\u540E\u518D\u6B21 ad batch diff\u3002**\u5FC5\u987B**\u628A reportMarkdown \u5168\u6587\u4EE5 Markdown \u53D1\u7ED9\u7528\u6237\u3002";
116688
+ agentHint = `\u53D1\u73B0 ${missing.length} \u9879\u4E0E\u8BA1\u5212\u4E0D\u4E00\u81F4\uFF08\u8BE6\u89C1 items[] / reportMarkdown\uFF1A\u2705${statusCounts.ok} / \u274C${missing.length} / \u23ED${statusCounts.skipped}\uFF09\u3002**\u7ACB\u523B**\u628A\u672C\u547D\u4EE4 stdout \u4E2D BEGIN_USER_DELIVERY_MARKDOWN\u2026END \u5168\u6587\u539F\u6837\u53D1\u7ED9\u7528\u6237\uFF08\u7981\u6B62\u6458\u8981/\u7981\u6B62\u53EA\u8BF4\u300C\u521B\u5EFA\u6210\u529F\u300D\uFF09\uFF0C` + (remediateCount > 0 ? `\u4EA4\u4ED8\u540E\u518D\u6267\u884C ${remediateCount} \u6761 remediateCommand \u8865\u5EFA\uFF08\u52FF\u56E0\u8865\u5EFA\u63A8\u8FDF\u4EA4\u4ED8\uFF09` : "\u4EA4\u4ED8\u540E\u518D\u6309 layer \u8865\u5EFA") + "\uFF1B\u8865\u5EFA\u540E\u518D\u6B21 ad batch diff \u5E76\u518D\u6B21\u4EA4\u4ED8\u66F4\u65B0\u540E\u7684 Markdown\u3002";
116659
116689
  } else {
116660
- agentHint = `\u4E0E JSON \u8BA1\u5212\u4E00\u81F4\uFF08\u542B\u6295\u653E\u5730\u57DF\uFF1Bitems[] \u5171 ${statusCounts.ok} \u6761\u5747\u4E3A ok\uFF09\u3002**\u5FC5\u987B**\u628A reportMarkdown \u5168\u6587\u4EE5 Markdown \u53D1\u7ED9\u7528\u6237\uFF0C\u7981\u6B62\u53EA\u8BF4\u300C\u672A\u53D1\u73B0\u7F3A\u5931\u300D\u3002`;
116690
+ agentHint = `\u4E0E JSON \u8BA1\u5212\u4E00\u81F4\uFF08\u542B\u6295\u653E\u5730\u57DF\uFF1Bitems[] \u5171 ${statusCounts.ok} \u6761\u5747\u4E3A ok\uFF09\u3002**\u7ACB\u523B**\u628A\u672C\u547D\u4EE4 stdout \u4E2D BEGIN_USER_DELIVERY_MARKDOWN\u2026END \u5168\u6587\u539F\u6837\u53D1\u7ED9\u7528\u6237\uFF1B\u7981\u6B62\u53EA\u8BF4\u300C\u672A\u53D1\u73B0\u7F3A\u5931\u300D\u6216\u53EA\u8D34 counts \u6458\u8981\u3002`;
116661
116691
  }
116662
116692
  return {
116663
116693
  accountId,
@@ -116833,7 +116863,7 @@ function buildBatchGetAgentWorkflow(opts) {
116833
116863
  configFile: opts.configFile,
116834
116864
  campaignId: campaignId ?? void 0
116835
116865
  });
116836
- agentHint = `\u5FC5\u505A\u4E0B\u4E00\u6B65\uFF1A\u6267\u884C nextCommand\uFF08ad batch diff\uFF09\u3002\u5B8C\u6210\u540E\u628A\u843D\u76D8 JSON \u7684 reportMarkdown\uFF08\u6216 Read reportMarkdownFile\uFF09**\u5168\u6587\u4EE5 Markdown \u6D88\u606F\u53D1\u7ED9\u7528\u6237**\uFF0C\u52FF\u6458\u8981\uFF1B\u6709 remediateCommand \u5219\u5148\u8865\u5EFA\u518D\u5237\u65B0\u62A5\u544A\u3002`;
116866
+ agentHint = `\u5FC5\u505A\u4E0B\u4E00\u6B65\uFF1A\u6267\u884C nextCommand\uFF08ad batch diff\uFF09\u3002diff \u7684 stdout \u542B BEGIN_USER_DELIVERY_MARKDOWN\u2026END\u2014\u2014**\u7ACB\u523B\u539F\u6837\u53D1\u7ED9\u7528\u6237**\uFF08\u52FF\u6458\u8981\u3001\u52FF\u7B49\u8865\u5EFA\u7ED3\u675F\uFF09\uFF1B\u6709 remediateCommand \u5219\u4EA4\u4ED8\u540E\u518D\u8865\u5EFA\u5E76\u518D\u8DD1 diff\u3002`;
116837
116867
  }
116838
116868
  } else {
116839
116869
  agentHint = `\u5F53\u524D status=${status || "\u2014"}\uFF0C\u6309 google-ads.md \xA7 batch \u5904\u7406\u3002`;
@@ -116910,7 +116940,7 @@ function printBatchDiffFollowUpHint(opts) {
116910
116940
  console.log(` ${cmd}
116911
116941
  `);
116912
116942
  console.log(
116913
- " Agent\uFF1A\u5E26 --json-out \u4E0E --md-out\uFF1B\u8BFB reportMarkdown\uFF08\u6216 Read reportMarkdownFile\uFF09**\u5168\u6587\u4EE5 Markdown \u53D1\u7ED9\u7528\u6237**\uFF1B\u5E76\u5904\u7406 missing[].remediateCommand\u3002\n"
116943
+ " Agent\uFF1A\u5E26 --json-out \u4E0E --md-out\uFF1Bdiff \u540E**\u7ACB\u523B**\u628A stdout \u4E2D BEGIN_USER_DELIVERY_MARKDOWN\u2026END \u5168\u6587\u53D1\u7ED9\u7528\u6237\uFF0C\u518D\u5904\u7406 missing[].remediateCommand\u3002\n"
116914
116944
  );
116915
116945
  }
116916
116946
  var LAYER_ORDER = [
@@ -117080,6 +117110,19 @@ function writeCampaignCreateStatusMarkdown(result, mdPath) {
117080
117110
  fs9.writeFileSync(mdPath, reportMarkdown, "utf8");
117081
117111
  return { reportMarkdown, reportMarkdownFile: mdPath };
117082
117112
  }
117113
+ var USER_DELIVERY_MARKDOWN_BEGIN = "\u2500\u2500 BEGIN_USER_DELIVERY_MARKDOWN \uFF08\u5FC5\u987B\u539F\u6837\u7C98\u8D34\u5230\u5BF9\u7528\u6237\u7684\u4E0B\u4E00\u6761\u6D88\u606F\uFF1B\u7981\u6B62\u6458\u8981\u4EE3\u66FF\uFF1B\u4EA4\u4ED8\u4F18\u5148\u4E8E\u8865\u5EFA\uFF09\u2500\u2500";
117114
+ var USER_DELIVERY_MARKDOWN_END = "\u2500\u2500 END_USER_DELIVERY_MARKDOWN \u2500\u2500";
117115
+ function printBatchDiffUserDeliveryMarkdown(report) {
117116
+ console.log(`
117117
+ \u{1F4C4} \u521B\u5EFA\u8BE6\u60C5 Markdown \u5DF2\u5199\u5165\uFF1A${report.reportMarkdownFile}`);
117118
+ console.log(
117119
+ " Agent\uFF1A\u4E0B\u4E00\u6761\u5BF9\u7528\u6237\u6D88\u606F\u5FC5\u987B\u662F\u4E0B\u65B9 BEGIN\u2026END \u4E4B\u95F4\u7684 Markdown \u5168\u6587\uFF1B\u7981\u6B62\u53EA\u8BF4\u300C\u521B\u5EFA\u6210\u529F/\u8BE6\u60C5\u5DF2\u4EA4\u4ED8\u300D\u3002\n"
117120
+ );
117121
+ console.log(USER_DELIVERY_MARKDOWN_BEGIN);
117122
+ console.log(report.reportMarkdown.replace(/\s+$/, ""));
117123
+ console.log(USER_DELIVERY_MARKDOWN_END);
117124
+ console.log();
117125
+ }
117083
117126
  function formatBatchDiffGrouped(result) {
117084
117127
  console.log(
117085
117128
  `
@@ -117235,10 +117278,7 @@ async function runCampaignBatchDiff(opts) {
117235
117278
  ...result,
117236
117279
  ...report
117237
117280
  };
117238
- console.log(`
117239
- \u{1F4C4} \u521B\u5EFA\u8BE6\u60C5 Markdown \u5DF2\u5199\u5165\uFF1A${report.reportMarkdownFile}`);
117240
- console.log(` Agent\uFF1A\u5FC5\u987B\u5C06 reportMarkdown \u5168\u6587\u4EE5 Markdown \u6D88\u606F\u53D1\u7ED9\u7528\u6237\uFF08\u52FF\u6458\u8981\uFF09\u3002
117241
- `);
117281
+ printBatchDiffUserDeliveryMarkdown(report);
117242
117282
  if (await emitCliJsonOrSnapshot(
117243
117283
  { jsonOut: opts.jsonOut },
117244
117284
  {
@@ -121080,7 +121120,7 @@ function register21(program2) {
121080
121120
  }
121081
121121
  );
121082
121122
  adBatchCmd.command("diff").description(
121083
- "\u6210\u529F\u6216\u90E8\u5206\u6210\u529F\uFF1A\u6309 campaign-create JSON \u4E0E\u8D26\u6237\u5B9E\u51B5\u9010\u5C42\u6BD4\u5BF9\uFF08\u542B\u6295\u653E\u56FD\u5BB6/\u5730\u57DF\uFF09\n \u8F93\u51FA\u8BA1\u5212\u5168\u91CF items[] + Markdown \u521B\u5EFA\u8BE6\u60C5\uFF08reportMarkdown / --md-out\uFF09\n Agent \u5FC5\u987B\u628A reportMarkdown \u5168\u6587\u4EE5 Markdown \u53D1\u7ED9\u7528\u6237\uFF1B\u6709\u7F3A\u5931\u65F6 exit 2\n Failed \u4E0D\u9002\u7528\uFF08\u7CFB\u5217\u672A\u521B\u5EFA\uFF09\uFF0C\u8BF7\u7528 ad batch get \u67E5\u770B reason/errors \u540E\u6539 JSON \u91CD\u63D0\n\n \u793A\u4F8B\uFF1A\n siluzan-tso ad batch diff --batch-id <taskId> --config-file ./campaign.json --json-out ./snap-campaign --md-out ./snap-campaign/campaign-create-status.md\n siluzan-tso ad batch diff --campaign-id <id> --config-file ./campaign.json"
121123
+ "\u6210\u529F\u6216\u90E8\u5206\u6210\u529F\uFF1A\u6309 campaign-create JSON \u4E0E\u8D26\u6237\u5B9E\u51B5\u9010\u5C42\u6BD4\u5BF9\uFF08\u542B\u6295\u653E\u56FD\u5BB6/\u5730\u57DF\uFF09\n \u8F93\u51FA\u8BA1\u5212\u5168\u91CF items[] + Markdown \u521B\u5EFA\u8BE6\u60C5\uFF08stdout \u4EA4\u4ED8\u5757 + reportMarkdown / --md-out\uFF09\n Agent \u5FC5\u987B\u628A BEGIN_USER_DELIVERY_MARKDOWN\u2026END \u5168\u6587\u53D1\u7ED9\u7528\u6237\uFF08\u5148\u4E8E\u8865\u5EFA\uFF09\uFF1B\u6709\u7F3A\u5931\u65F6 exit 2\n Failed \u4E0D\u9002\u7528\uFF08\u7CFB\u5217\u672A\u521B\u5EFA\uFF09\uFF0C\u8BF7\u7528 ad batch get \u67E5\u770B reason/errors \u540E\u6539 JSON \u91CD\u63D0\n\n \u793A\u4F8B\uFF1A\n siluzan-tso ad batch diff --batch-id <taskId> --config-file ./campaign.json --json-out ./snap-campaign --md-out ./snap-campaign/campaign-create-status.md\n siluzan-tso ad batch diff --campaign-id <id> --config-file ./campaign.json"
121084
121124
  ).requiredOption("--config-file <path>", "\u63D0\u4EA4\u65F6\u4F7F\u7528\u7684 campaign-create JSON").option(
121085
121125
  "--campaign-id <id>",
121086
121126
  "Google \u5E7F\u544A\u7CFB\u5217 ID\uFF08\u53EF\u4ECE ad campaigns --json-out \u83B7\u53D6\uFF1B\u7701\u7565\u65F6\u6309\u7CFB\u5217\u540D\u5339\u914D\uFF09"
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: siluzan-tso
3
- description: 丝路赞 TSO 广告平台(Google/Bing/Yandex/TikTok/Kwai/MetaAd),凡涉及丝路赞/TSO、投广告、出价预算、广告账户管理,或需要做行业分析/市场分析/行业分析报告(含「写一份 XX 行业报告」「电商/制造/医疗等行业报告」「市场调查/战略市场/KA 市场报告」「竞品/GTM/市场格局/行业趋势」等,无论是否提及丝路赞/广告/客户)须加载本 skill。【§零·最高优先】网址/域名/官网+诊断/检测/监测/评估/体检/报告/符合投放要求/能不能投(含「网络诊断」混说)→P8 website-diagnosis collect(禁纯WebFetch/肉眼看页),禁止P9/P1/W3、禁止A/B/C/D追问;细则见 intent-routing.md §零。【§零·B·次高优先】未命中§零时,行业/市场分析报告类话术→必走P9 market-analysis collect+render出HTML,禁止纯WebSearch/WebFetch在对话里写Markdown/HTML当终稿、禁止改走P8/P1/P4/W5/google-analysis;细则见 references/core/intent-routing.md §零·B。【§零·C·关键词规划】Google Ads/谷歌广告拓词、关键词规划/推荐、Keyword Planner、长尾关键词、月搜索量/搜索量、竞争度、核心词/种子词扩词(含「阅读网址/文章/页面后针对核心词出带搜索量词表」,无论是否提及丝路赞/TSO/账户)→必走W5 keyword -k … --google-only --json-out,禁止WebSearch/WebFetch编造搜索量当终稿;细则见 references/core/intent-routing.md §零·C。【报告/诊断消歧】其余报告类话术禁止默认某一CLI——行业/市场/战略/行业分析报告→P9 market-analysis(必走collect+render,禁止纯WebSearch代替);Google账户ID+健康诊断→P1 google-ads-diagnosis;账户ID+周期/月度→P4;Meta/TikTok/Bing周期→P4/P4-FB;多账户对比→P3/P5;OKKI周报→P6;Google询盘→P7;官网+明确要搜索广告方案/campaign JSON→W3;仅要词表+搜索量/竞争度→W5;平台优化报告列表/推送→W7;对象仍不清→Read intent-routing.md。【账户】列表/余额/消耗/激活账单(W1)、多账户余额预警 balance-scan(P2)、多户消耗汇总 accounts-digest(P3)、六大媒体开户与进度(W2)、分享/解绑/MCC/BC/BM/权限(W9)。【投放】Google搜索系列方案与 campaign-validate/create(W3)、系列/组/广告/关键词 CRUD/拒审、PMax 创建与素材、AI智投草稿 batch(W4)、拓词 keyword -k(W5)、AI广告优化 optimize(W6)、优化合规 SOP。【财务】充值/钱包、转账记录、发票/开票/抬头(W8);写操作审计与 restore。【运营】智能预警 forewarning 创建/启停/记录(W10)、TikTok/Meta 线索 clue(W11)、日周巡检(W12)、宿主编排/投放自控/异常监控(hosted-automation)。【其他】RAG 知识库检索、Meta/Facebook 周期与诊断 HTML、Google/Meta 周期 Excel、多账户 google-analysis-batch。
3
+ description: 丝路赞 TSO 广告平台(Google/Bing/Yandex/TikTok/Kwai/MetaAd),凡涉及丝路赞/TSO、投广告、出价预算、广告账户管理,或需要做行业分析/市场分析/行业分析报告(含「写一份 XX 行业报告」「电商/制造/医疗等行业报告」「市场调查/战略市场/KA 市场报告」「竞品/GTM/市场格局/行业趋势」等,无论是否提及丝路赞/广告/客户)须加载本 skill。【§零·最高优先】网址/域名/官网+诊断/检测/监测/评估/体检/报告/符合投放要求/能不能投(含「网络诊断」混说)→P8 website-diagnosis collect(禁纯WebFetch/肉眼看页),禁止P9/P1/W3、禁止A/B/C/D追问;细则见 intent-routing.md §零。【§零·B·次高优先】未命中§零时,行业/市场分析报告类话术→必走P9 market-analysis collect+render出HTML,禁止纯WebSearch/WebFetch在对话里写Markdown/HTML当终稿、禁止改走P8/P1/P4/W5/google-analysis;细则见 references/core/intent-routing.md §零·B。【§零·C·关键词规划】Google Ads/谷歌广告拓词、关键词规划/推荐、Keyword Planner、长尾关键词、月搜索量/搜索量、竞争度、核心词/种子词扩词(含「阅读网址/文章/页面后针对核心词出带搜索量词表」,无论是否提及丝路赞/TSO/账户)→必走W5 keyword -k … --google-only --json-out,禁止WebSearch/WebFetch编造搜索量当终稿;细则见 references/core/intent-routing.md §零·C。【报告/诊断消歧】其余报告类话术禁止默认某一CLI——行业/市场/战略/行业分析报告→P9 market-analysis(必走collect+render,禁止纯WebSearch代替);Google账户ID+健康诊断→P1 google-ads-diagnosis;账户ID+周期/月度→P4;Meta/TikTok/Bing周期→P4/P4-FB;多账户对比→P3/P5;OKKI周报→P6;Google询盘→P7;官网+明确要搜索广告方案/campaign JSON→W3;仅要词表+搜索量/竞争度→W5;平台优化报告列表/推送→W7;对象仍不清→Read intent-routing.md。【账户】列表/余额/消耗/激活账单(W1)、多账户余额预警 balance-scan(P2)、多户消耗汇总 accounts-digest(P3)、六大媒体开户与进度(W2)、分享/解绑/MCC/BC/BM/权限(W9)。【投放】Google **仅支持搜索广告(Search)与 PMax**(不支持展示广告 Display);搜索系列方案与 campaign-validate/create(W3)、系列/组/广告/关键词 CRUD/拒审、PMax 创建与素材、AI智投草稿 batch(W4)、拓词 keyword -k(W5)、AI广告优化 optimize(W6)、优化合规 SOP。【财务】充值/钱包、转账记录、发票/开票/抬头(W8);写操作审计与 restore。【运营】智能预警 forewarning 创建/启停/记录(W10)、TikTok/Meta 线索 clue(W11)、日周巡检(W12)、宿主编排/投放自控/异常监控(hosted-automation)。【其他】RAG 知识库检索、Meta/Facebook 周期与诊断 HTML、Google/Meta 周期 Excel、多账户 google-analysis-batch。
4
4
  license: MIT
5
5
  compatibility: 需要 Node.js 18+、已安装 siluzan-tso-cli,通过 send-login-code + login 或 config set 完成鉴权
6
6
  metadata:
@@ -40,9 +40,10 @@ siluzan-tso -h
40
40
 
41
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
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`。
43
+ - **禁止臆测授权过期**:见 403/`HTTP 403`/拉数失败/「可能 OAuth 失效」时,**禁止**口头推断授权过期或直接 `reauth`。须先核验 ID(及 Google 连字符),再跑 `account check-access -a <mediaCustomerId>`,以返回的 `accessible` / `reauth_required` / `no_permission` 为准;仅当 `list-accounts` 输出含激活字段且可判定未激活时才跳过用其判断授权过期;细则见 `accounts-permissions.md`。
44
44
  - **Google 广告命令名**:列表是 `ad campaigns`(不是 `ad-campaigns` / `campaign list`);`balance`/`stats` 须带 `-m Google`;单国地域用 `ad geo search … --json-out`(或 `geo resolve`)。
45
- - **创建完成后交付(硬性)**:跑完 `ad batch diff`(须带 `--json-out`/`--md-out`)后,把落盘 JSON **`reportMarkdown` 全文**(或 Read `reportMarkdownFile`)以 **Markdown 消息原样发给用户**;禁止只摘要、禁止只说「创建成功/未发现缺失」。
45
+ - **Google 广告类型边界**:CLI/Skill **仅支持** Google **搜索广告(Search)** **Performance Max(PMax)** 的方案、创建与精细管理;**不支持展示广告(Display)**(含自适应展示广告 RDA、独立 Display 系列)。用户要做展示广告时须明确告知不支持,可改推 Search / PMax;**禁止**用 `campaign-create` / `ad-create` 伪装创建 Display。
46
+ - **创建完成后交付(硬性)**:`ad batch diff` 的 stdout 含 `BEGIN_USER_DELIVERY_MARKDOWN`…`END_USER_DELIVERY_MARKDOWN`——**立刻**把中间全文原样发给用户(可先于补建);禁止只摘要、禁止只说「创建成功/详情已交付/未发现缺失」、禁止等全部补建结束再交付。
46
47
  - `list-accounts` 无余额/消耗;列全部用 `--page-size 999`。
47
48
  - 多户余额用 `balance-scan`(P2),多户消耗用 `accounts-digest`(P3);禁止外层 for-loop 逐户拉数。
48
49
  - `stats` 的 `spend` = **区间合计**,不是日消耗。
@@ -72,9 +73,12 @@ siluzan-tso -h
72
73
 
73
74
  ### Google 广告投放
74
75
 
76
+ > **类型边界**:仅 **Search** + **PMax**;**不支持 Display(展示广告)**。详见 `references/google-ads/google-ads.md` Gotchas。
77
+
75
78
  | 用户意图(关键词) | 工作流 | 必读文档 |
76
79
  | ------------------ | ------ | -------- |
77
80
  | 新建搜索系列 / 出投放方案 / Excel·表格方案 / 官网生成搜索广告 | **W3** | `references/google-ads/google-ads-campaign-plan.md`(§**仅出方案 vs 创建**)+ **`assets/campaign-create-template.json`**(先 Read)+ `assets/campaign-create-template.md` + `rules/google-ads-launch-plan-template.md`(JSON 后**写代码**投影完整审查稿);有方案文件时加 `rules/google-ads-plan-source-fidelity.md`。**≠ P8 / ≠ P9 / ≠ W5**;**禁止**因缺账户阻塞出方案、**禁止**只交概览表 |
81
+ | 展示广告 / Display / 自适应展示广告(RDA) | — | **不支持**。向用户说明后改推 Search(W3)或 PMax(W3);勿创建、勿假装已支持 |
78
82
  | 广告系列/组/广告/关键词 **查询** / 拒审字段 | W3 | `references/google-ads/google-ads-read.md` |
79
83
  | 广告系列/组/广告/关键词 **创建·编辑·启停** | W3 | `references/google-ads/google-ads-write.md` |
80
84
  | PMax 系列 | W3 | **`assets/pmax-create-template.json`**(先 Read)+ `assets/pmax-create-template.md` + `rules/google-ads-pmax-launch-plan-template.md`(**写代码**投影完整审查稿)+ `references/google-ads/pmax-api.md` + `google-ads-write.md`(PMax 节) |
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "slug": "siluzan-tso",
3
- "version": "1.1.43",
4
- "publishedAt": 1786008983339
3
+ "version": "1.1.44-beta.2",
4
+ "publishedAt": 1786442545653
5
5
  }
@@ -23,7 +23,8 @@ siluzan-tso balance-scan -m <媒体类型> [选项]
23
23
  | ---- | ---- | ---- |
24
24
  | `-m, --media <type>` | 必填:`Google \| TikTok \| Yandex \| MetaAd \| BingV2 \| Kwai` | — |
25
25
  | `-a, --accounts <ids>` | 指定 `mediaCustomerId`(逗号分隔);**跳过清单翻页**,拉取后全部输出(不按阈值过滤) | — |
26
- | `--threshold-days <n>` | 剩余续航天数阈值(按近 7 日日均消耗估算) | `7` |
26
+ | `--threshold-days <n>` | 剩余续航天数阈值 | `7` |
27
+ | `--spend-days <n>` | 日均消耗回看自然日数(截至昨天不含今天;日均 = 窗口合计 / N) | `7` |
27
28
  | `--min-balance <n>` | 绝对余额阈值(与 threshold 取并集) | — |
28
29
  | `--min-daily-spend <n>` | 日均消耗低于此值视为僵尸账户,不做续航估算 | `0.01` |
29
30
  | `--target-days <n>` | 建议充值目标续航天数 | `30` |
@@ -36,6 +37,9 @@ siluzan-tso balance-scan -m <媒体类型> [选项]
36
37
  # 全量巡检(Playbook P2)
37
38
  siluzan-tso balance-scan -m Google --threshold-days 7 --json-out ./snap-p2
38
39
 
40
+ # 近 3 日日均 + 续航阈值 7 天
41
+ siluzan-tso balance-scan -m Google --threshold-days 7 --spend-days 3 --json-out ./snap-p2
42
+
39
43
  # 已知子集
40
44
  siluzan-tso balance-scan -m BingV2 -a id1,id2,id3 --json-out ./snap-p2-subset
41
45
 
@@ -43,7 +47,7 @@ siluzan-tso balance-scan -m BingV2 -a id1,id2,id3 --json-out ./snap-p2-subset
43
47
  siluzan-tso balance-scan -m MetaAd --json-out ./snap-p2-meta
44
48
  ```
45
49
 
46
- **读盘要点**:先看 `meta.dataIssue`(非空则失败);再按 `remainingDays` 升序交付;`hitReason="none"` 表示未触阈值;用 **`dailySpend`** 做日均,勿把 `stats` 区间合计 `spend` 当「每天消耗」。与 `balance` / `accounts-digest` 分工见 `references/core/agent-conventions.md` §八。
50
+ **读盘要点**:先看 `meta.dataIssue`(非空则失败);再按 `remainingDays` 升序交付;`hitReason="none"` 表示未触阈值;用 **`dailySpend`** 做日均(口径见 `meta.spendDays` / `meta.spendWindow`),勿把 `stats` 区间合计 `spend` 当「每天消耗」。与 `balance` / `accounts-digest` 分工见 `references/core/agent-conventions.md` §八。
47
51
 
48
52
  ---
49
53
 
@@ -177,9 +181,9 @@ siluzan-tso stats -m <媒体类型> [选项]
177
181
 
178
182
  1. 用户若已给出账户号(如 Yandex `porg-kqquuxx6`),`-a` **必须原样用该 mediaCustomerId**;先 `list-accounts -m <媒体> -k <mediaCustomerId>` 核验存在即可。
179
183
  2. **禁止**把 `ma.entityId`、`externalMediaAccountTokenId` 或会话里其它 UUID 传给 `-a`(会空结果,verbose 常打出被吞的 `HTTP 403`,**不等于** OAuth 过期)。
180
- 3. Google:若 `list-accounts` 显示套餐**未激活**(`scopeActivatedSources` 为空),`balance` 等可能无数据——向用户说明需先激活套餐;**禁止**用非 CLI / 自拼请求等方式绕过。
184
+ 3. Google:仅当 `list-accounts` **输出中出现** `scopeActivatedSources` 且可判定未激活时,才可向用户说明需先激活套餐;**若无该字段,禁止谈套餐激活**。空结果时按 CLI 报错/字段说明,**禁止**用非 CLI / 自拼请求等方式绕过。
181
185
  4. 仅当 `list-accounts` 显示 `invalidOAuthToken=true`(或授权状态列为失效),且用户确认后,才走 `account reauth --id <entityId> --i-confirm --commit "…"`(见 `accounts-permissions.md`)。
182
- 5. `list-accounts` 显示 `Linked` + `hasToken:1` + `invalidOAuthToken=false` 且套餐已激活时,**禁止**因 stats/balance 空结果自行 `reauth`/解绑。
186
+ 5. `list-accounts` 显示 `Linked` + `hasToken:1` + `invalidOAuthToken=false`(若有激活字段则须已激活)时,**禁止**因 stats/balance 空结果自行 `reauth`/解绑。
183
187
 
184
188
  **示例:**
185
189
 
@@ -81,12 +81,12 @@ siluzan-tso list-accounts -m Google --page 2 --page-size 999 --json-out ./snap-p
81
81
  | `ma.mediaCustomerName` | 账户名称(表格「账户名称」) |
82
82
  | `ma.mediaAccountState` 等 | 平台开户/审核态(如 Approved / Linked);**不是** OAuth 是否可用 |
83
83
  | **`ma.invalidOAuthToken`** | **OAuth 是否失效**:`true`=失效,`false`=正常。**表格必有「授权状态」列**(✅ 正常 / ⚠️ 失效),与此字段一一对应;判失效、筛 `-s invalid`、走 `reauth` 均看它 |
84
- | **`ma.scopeActivatedSources`** | **套餐是否已购买/激活**:非空且存在未过期条目(看 `expireAt`)= 已激活;空数组或全部过期 = 未激活。**Google 表格有「套餐激活」列**(✅ 已激活 / 未激活)。未激活时部分读接口(如 `balance`)可能无数据,引导用户先激活套餐;**勿**尝试非 CLI 途径取数 |
84
+ | **`ma.scopeActivatedSources`**(可选) | **仅当本次 `list-accounts` 输出中出现该字段时才可读**:非空且存在未过期条目(看 `expireAt`)= 已激活;空数组或全部过期 = 未激活。出现时 Google 表格才有「套餐激活」列。**若 JSON/表格中无此字段/列:禁止向用户谈套餐是否激活,禁止臆造未激活/已激活** |
85
85
  | `ma.TTADInfo.status` 等 | 媒体侧投放/审核细态(TikTok 表格「审核状态」等);**勿**当成 OAuth 授权状态 |
86
86
 
87
87
  > **Agent**:用户问「哪些授权失效 / OAuth 状态」时,读盘看 `items[].ma.invalidOAuthToken`,表格看「授权状态」列;**不要**用 `mediaAccountState` 或审核状态列代替。
88
- > 用户问「哪些买了套餐 / 是否激活套餐」时,读盘看 `items[].ma.scopeActivatedSources`,Google 表格看「套餐激活」列;**不要**用 `mediaAccountState` 或授权状态代替。
89
- > **Google 单户**:若套餐**已激活**,可用 `account check-access -a <mediaCustomerId>` 再确认网关侧授权是否可用(`reauth_required` / `no_permission` 等);**未激活时不要用 check-access 判断授权过期**(仍可能 `accessible`)。见 `accounts-permissions.md` § check-access。
88
+ > 用户问「哪些买了套餐 / 是否激活套餐」时:**仅当**输出含 `ma.scopeActivatedSources`(或 Google 表格有「套餐激活」列)才可据此回答;**缺失时直接说明当前环境无法查询套餐激活状态**,不要用 `mediaAccountState` / 授权状态代替,也不要去猜。
89
+ > **Google 单户**:若输出中能确认套餐**已激活**,可用 `account check-access -a <mediaCustomerId>` 再确认网关侧授权是否可用;若输出无激活字段,仍可直接跑 `check-access`(以返回 `status` 为准),**不要**先编造「未激活」。见 `accounts-permissions.md` § check-access。
90
90
 
91
91
  ---
92
92
 
@@ -167,7 +167,7 @@ siluzan-tso account-history --start 2026-03-01 --end 2026-03-31 --json-out ./sna
167
167
  | 状态 | 含义 | 下一步操作 |
168
168
  | ---------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
169
169
  | `Pending` | 审核中 | 等待,可反复运行此命令轮询;审核周期因媒体而异 |
170
- | `Approved` | 审核通过 | 运行 `list-accounts -m <媒体>` 确认账户已出现;引导用户充值激活(`config show` 取 `webUrl`,按 `finance.md` 打开对应媒体充值页;例如 Google 为 `https://www.siluzan.com/v3/foreign_trade/tso/recharge/pay?mediaType=Google`;Kwai、Yandex 当前没有对应充值界面) |
170
+ | `Approved` | 审核通过 | 运行 `list-accounts -m <媒体>` 确认账户已出现;引导用户充值激活(`config show` 取 `webUrl`,按 `finance.md` 打开对应媒体充值页;例如 Google 为 `https://www-ci.siluzan.com/v3/foreign_trade/tso/recharge/pay?mediaType=Google`;Kwai、Yandex 当前没有对应充值界面) |
171
171
  | `Rejected` | 被拒 | 查看 `--json-out` 落盘中的 `reason` 字段了解拒绝原因;修改资料后重新提交;若原因不明,引导用户联系丝路赞客服 |
172
172
 
173
173
  ---
@@ -35,23 +35,23 @@ siluzan-tso account me --check-phone 15130150466 --json-out ./snap-me
35
35
 
36
36
  校验当前丝路赞凭据是否对指定 **Google** 广告账户有访问权限。应在拉数/诊断前调用,避免误用他户 ID。
37
37
 
38
- > **硬约束**:**禁止**凭 403、空结果或经验臆测「授权/OAuth 过期」。要对用户下「授权不可用 / 需重授权」结论前,**必须**先跑本命令(并满足下方套餐已激活前提),以 CLI 返回的 `status` 为准;**禁止**跳过本命令直接 `reauth` 或口头推断。
38
+ > **硬约束**:**禁止**凭 403、空结果或经验臆测「授权/OAuth 过期」。要对用户下「授权不可用 / 需重授权」结论前,**必须**先跑本命令,以 CLI 返回的 `status` 为准;**禁止**跳过本命令直接 `reauth` 或口头推断。
39
39
 
40
- **前提(查授权是否过期时)**:须先确认该户 **套餐已激活**(`list-accounts` `ma.scopeActivatedSources` 有未过期条目,或 Google 表格「套餐激活」= ✅ 已激活)。在已激活前提下,**必须**用本命令检查授权是否可用:
40
+ **套餐激活字段(可选前提)**:若 `list-accounts` 输出中**出现** `ma.scopeActivatedSources`(或 Google「套餐激活」列),须先确认有未过期条目再据此谈「授权过期」;**输出中无该字段/列时:跳过套餐判断,直接跑本命令**,且**禁止**向用户解释套餐是否激活。
41
41
 
42
- | 结果 | 含义(套餐已激活时) |
43
- | ---- | -------------------- |
42
+ | 结果 | 含义 |
43
+ | ---- | ---- |
44
44
  | `accessible`(200 / `true`) | 授权可用,可继续拉数/操作 |
45
45
  | `reauth_required`(200 / `false`) | 已绑定但 Google OAuth 不可用 → 走重授权 |
46
46
  | `no_permission`(403 / 账户 ID) | 网关不可访问;可与 `list-accounts` 的 `invalidOAuthToken` 交叉确认是否授权失效或不在本账号下 |
47
47
 
48
- **未激活套餐时不要用本命令判断授权过期**:未激活户仍可能返回 `accessible`,无法据此下结论。套餐状态见 `accounts-list.md` 的 `scopeActivatedSources`。
48
+ **注意**:当输出能确认套餐**未激活**时,不要用本命令判断授权过期(未激活户仍可能返回 `accessible`)。无激活字段时不适用本条。
49
49
 
50
50
  ```bash
51
- # 1) 先确认套餐已激活
51
+ # 1) 可选:list-accounts 核验账户;仅当输出含 scopeActivatedSources 时才看套餐
52
52
  siluzan-tso list-accounts -m Google -k <mediaCustomerId> --json-out ./snap
53
53
 
54
- # 2) 已激活后再查网关访问 / 授权是否可用
54
+ # 2) 查网关访问 / 授权是否可用
55
55
  siluzan-tso account check-access -a <mediaCustomerId>
56
56
  siluzan-tso account check-access -a 4256317784 --json-out ./snap-access
57
57
  ```
@@ -64,7 +64,7 @@ siluzan-tso account check-access -a 4256317784 --json-out ./snap-access
64
64
  | 403 | `token不能为空` | 未绑定 Google 媒体 | `google_not_bound` → Agent 优先平台授权;备选 `account auth -m Google` |
65
65
  | 401 | 空 | 丝路赞 Token 失效 | `siluzan_token_invalid` → 重新 login |
66
66
 
67
- > 与 `list-accounts -k` 互补:`list-accounts` 查「是否在列表 / 套餐是否激活 / `invalidOAuthToken`」;本接口查「Google 网关是否允许当前凭据访问该 mediaCustomerId」。列表批量筛失效仍优先看 `invalidOAuthToken`;单户深查在**已激活**后用本命令。
67
+ > 与 `list-accounts -k` 互补:`list-accounts` 查「是否在列表 / `invalidOAuthToken`」(以及**若存在**则含套餐激活);本接口查「Google 网关是否允许当前凭据访问该 mediaCustomerId」。列表批量筛失效仍优先看 `invalidOAuthToken`;单户深查用本命令。
68
68
 
69
69
  ---
70
70
 
@@ -488,7 +488,7 @@ siluzan-tso account email-deauth -c <mediaCustomerId> --invitation-id <id> --res
488
488
 
489
489
  | 功能 | 媒体 | 网页路径 |
490
490
  | --------------------------------------- | ------ | ------------------------------------------------- |
491
- | **账户激活**(邀请他人激活 / 充值激活) | Google | `https://www.siluzan.com/v3/foreign_trade/tso/manageAccounts` |
491
+ | **账户激活**(邀请他人激活 / 充值激活) | Google | `https://www-ci.siluzan.com/v3/foreign_trade/tso/manageAccounts` |
492
492
 
493
493
  **Agent 建议话术**:
494
494
 
@@ -497,5 +497,5 @@ siluzan-tso account email-deauth -c <mediaCustomerId> --invitation-id <id> --res
497
497
  siluzan-tso config show # 查看 webUrl 字段
498
498
 
499
499
  # 账户激活(Google)→ 引导至账户管理页
500
- # https://www.siluzan.com/v3/foreign_trade/tso/manageAccounts
500
+ # https://www-ci.siluzan.com/v3/foreign_trade/tso/manageAccounts
501
501
  ```
@@ -20,7 +20,7 @@
20
20
  - `entityId`(UUID,分享/delink/账单/`reauth`)≠ `mediaCustomerId`(`balance`/`stats`/`accounts-digest`/`ad` 的 `-a`)。**Yandex 的 mediaCustomerId 形如 `porg-…`,不是 UUID。**
21
21
  - MetaAd OAuth 户的 `mediaCustomerId` **须带 `act_` 前缀**。
22
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`。
23
+ - **禁止臆测授权过期**:403 / 拉数失败时**禁止**口头说「可能授权过期」。须 ID 核验后,对 Google 执行 `account check-access -a <mediaCustomerId>`,以返回 `status` 为准(见 [`accounts-permissions.md`](accounts-permissions.md));仅当 `list-accounts` 输出含激活字段且可判定未激活时,勿用其判断授权过期;非 Google 看 `invalidOAuthToken`。
24
24
  - `stats`/`balance` 空结果 + verbose `HTTP 403`:先确认 `-a` 是否为 `ma.mediaCustomerId`(且 Google 已去连字符);**禁止**把 `entityId` / tokenId 当 `-a`;未跑 `account check-access`(或未见 `invalidOAuthToken=true`)**禁止** `reauth`。
25
25
  - 多账户余额预警用 `balance-scan`(P2),多账户消耗汇总用 `accounts-digest`(P3);**禁止**外层 for-loop 逐户 `balance`/`stats`。
26
26
  - `stats` 默认 `spend` = **区间合计**,不是日消耗;日均看 `balance-scan.dailySpend` 或合计÷天数。
@@ -127,7 +127,7 @@ siluzan-tso config show
127
127
 
128
128
  ### 充值页链接(按媒体 × 类型)
129
129
 
130
- 链接模式:`https://www.siluzan.com/v3/foreign_trade/tso/recharge/<page>?mediaType=<mediaType>`;丝路赞钱包:`https://www.siluzan.com/v3/foreign_trade/tso/recharge/siluzanWallet`(无媒体参数)。
130
+ 链接模式:`https://www-ci.siluzan.com/v3/foreign_trade/tso/recharge/<page>?mediaType=<mediaType>`;丝路赞钱包:`https://www-ci.siluzan.com/v3/foreign_trade/tso/recharge/siluzanWallet`(无媒体参数)。
131
131
 
132
132
  | 充值类型 | `<page>` | 支持媒体(`mediaType` 参数) |
133
133
  | ------------------------- | --------------------- | ------------------------------------------- |
@@ -1,6 +1,6 @@
1
1
  # 各媒体开户
2
2
 
3
- > 网页链接:`https://www.siluzan.com/v3/foreign_trade/tso/accountOpeningHistory?tso=%2Fv3umijs%2Ftso%2FaccountOpeningHistory`
3
+ > 网页链接:`https://www-ci.siluzan.com/v3/foreign_trade/tso/accountOpeningHistory?tso=%2Fv3umijs%2Ftso%2FaccountOpeningHistory`
4
4
  > 多命令串联见 `references/core/workflows.md` § 流程一。
5
5
 
6
6
 
@@ -65,7 +65,7 @@ siluzan-tso open-account google-wizard
65
65
 
66
66
  ```bash
67
67
  siluzan-tso account-history -m Google
68
- # 审核通过后:config show → https://www.siluzan.com/v3/foreign_trade/tso/recharge/pay?mediaType=Google
68
+ # 审核通过后:config show → https://www-ci.siluzan.com/v3/foreign_trade/tso/recharge/pay?mediaType=Google
69
69
  ```
70
70
 
71
71
  ---
@@ -1,6 +1,6 @@
1
1
  # rag:知识库检索(TSO 广告投放辅助)
2
2
 
3
- 知识库管理页面在 https://www.siluzan.com/knowledge-base/
3
+ 知识库管理页面在 https://www-ci.siluzan.com/knowledge-base/
4
4
 
5
5
  为 **广告投放、账户分析、拓词、诊断报告** 等 TSO 业务提供**企业已入库**的产品、行业、客户背景事实依据。
6
6
 
@@ -190,9 +190,9 @@ siluzan-tso report push receive-emails -m Google [--json-out ./snap]
190
190
 
191
191
  | 媒体 | 报告类型 | URL 模板 |
192
192
  | ------ | ---------------- | ----------------------------------------------------------- |
193
- | Google | 日报(Daily) | `https://www.siluzan.com/media-report/publish/{entityId}?culture=zh-CN` |
194
- | Google | 小时报(Hourly) | `https://www.siluzan.com/media-report/hour/{entityId}?culture=zh-CN` |
195
- | TikTok | 日报 | `https://www.siluzan.com/media-report/publish/{entityId}?culture=zh-CN` |
193
+ | Google | 日报(Daily) | `https://www-ci.siluzan.com/media-report/publish/{entityId}?culture=zh-CN` |
194
+ | Google | 小时报(Hourly) | `https://www-ci.siluzan.com/media-report/hour/{entityId}?culture=zh-CN` |
195
+ | TikTok | 日报 | `https://www-ci.siluzan.com/media-report/publish/{entityId}?culture=zh-CN` |
196
196
 
197
197
  `entityId` 来自 `siluzan-tso report list --json-out ./snap` 中每条记录的 `entityId` 字段。
198
198
 
@@ -205,8 +205,8 @@ siluzan-tso report list -m Google --json-out ./snap
205
205
 
206
206
  # 第二步:查看 webUrl
207
207
  siluzan-tso config show
208
- # webUrl: https://www.siluzan.com
208
+ # webUrl: https://www-ci.siluzan.com
209
209
 
210
210
  # 第三步:拼接链接(Google 日报)
211
- # https://www.siluzan.com/media-report/publish/rpt_abc123?culture=zh-CN
211
+ # https://www-ci.siluzan.com/media-report/publish/rpt_abc123?culture=zh-CN
212
212
  ```
@@ -127,8 +127,8 @@
127
127
  - **账户状态 ≠ 系列状态**:`stats` / `balance` / `list-accounts` 的 `status` 只表示账户是否可用;系列状态必须来自 `ad campaigns`。
128
128
  - **数据时效性**:涉及「今天/当天/今日消耗」「实时消耗排行」前,必读 `references/analytics/account-analytics.md` 顶部「数据时效性」表。TikTok / Yandex / BingV2 / Kwai 是 `accountsoverview` 同步昨天数据,**不能查今天**。
129
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`。
131
- - **一律走 CLI,禁止自拼网关请求**:查余额 / 拉数 / 写操作只用 `siluzan-tso …`。**禁止**用 curl、自写脚本或改请求头直连 TSO/Google 网关「另辟蹊径」取数;`balance` 等无数据时按 CLI/`list-accounts` 字段向用户说明(如套餐未激活、授权失效),**禁止**尝试任何绕过平台门禁的取数方式。
130
+ - **禁止臆测授权过期(硬约束)**:任何 403、空结果、「可能授权/OAuth 过期」话术,**禁止**凭感觉下结论或直接 `reauth`。Google:**必须**执行 `account check-access -a <mediaCustomerId>`,仅当结果为 `reauth_required`(或列表 `invalidOAuthToken=true` 与之交叉确认)才谈重授权;`no_permission` 也可能是账户不在当前丝路赞账号下。若 `list-accounts` **输出含** `scopeActivatedSources` 且可判定未激活,则勿用 check-access 判断授权过期;**无该字段时禁止谈套餐激活**。非 Google 媒体以 `list-accounts` 的 `invalidOAuthToken` 为准,同样禁止臆测。详见 `accounts-permissions.md`。
131
+ - **一律走 CLI,禁止自拼网关请求**:查余额 / 拉数 / 写操作只用 `siluzan-tso …`。**禁止**用 curl、自写脚本或改请求头直连 TSO/Google 网关「另辟蹊径」取数;`balance` 等无数据时按 CLI/`list-accounts` **实际出现的字段**向用户说明(如授权失效;仅当输出含激活字段时才可谈套餐),**禁止**尝试任何绕过平台门禁的取数方式。
132
132
  - **W3 仅出方案例外(覆盖上条)**:用户只要「投放方案 / 规划 / 表格 / 先别创建·开户·投钱」,或未给账户且未要求创建/发布时——**禁止**把「请先提供 Google 广告账户」当作第一步;按 `google-ads-campaign-plan.md` §「仅出方案 vs 创建」落盘 JSON 后 **写代码**投影完整审查稿(默认 MD;用户指定则 Excel 等;`account`=`[PENDING_ACCOUNT]`),跳过 `list-accounts` / `geo resolve` / validate / create。**禁止**只交概览表。用户确认要创建后再要账户并续跑创建流水线。
133
133
  - **W3 审查稿(搜索与 PMax)**:JSON 落盘后、创建前,必须 **写代码**读取 JSON,按 `google-ads-launch-plan-template.md`(搜索)或 `google-ads-pmax-launch-plan-template.md`(PMax)生成完整审查文件交给用户;须含全部关键词/RSA 或全部 PMax 文案与附加资产。**禁止**用「方案总结」条数勾选代替。用户要求其他格式时改脚本输出,数据仍只从 JSON 来。
134
134
  - **不猜测账户 ID**:`entityId`(UUID,仅 delink/share/reauth/账单)≠ `mediaCustomerId`(`stats`/`balance`/`accounts-digest`/`ad` 的 `-a`)。两者均来自 `list-accounts` 的 `ma.*`。用户已给出媒体账户号时(Google 数字 CID、**Yandex `porg-…`**、Meta `act_…` 等)→ `-a` **原样使用**,再用 `-k` 核验;**禁止**改成 `entityId` / tokenId / 会话里其它 UUID。**禁止**把 `entityId` 传给 `stats -a` / `balance -a` / `accounts-digest -a`。
@@ -150,10 +150,11 @@
150
150
  - **禁止**只贴一行 CLI `✅`/`❌` 或整段 stdout 当交付;**禁止**写命令成功后静默结束。
151
151
  - **广告创建(W3)另有加强**:见下条与 `workflows.md` W3——创建完成后必须输出**每个系列**的详情,不能只报「任务已提交 / 创建完成」。
152
152
  - **Google 广告创建完成后必出系列详情报告**(用户确认计划并执行 `campaign-create` / `pmax-create` 之后):
153
- - 流水线跑完:`batch get` 至终态 →(搜索)`batch diff` + 必要自动补建再读 `ad campaigns`(及组/词/扩展等按需)核对。
154
- - **交付物必须是 Markdown 文档正文**:执行 `ad batch diff --json-out --md-out …` 后,将落盘 JSON 的 **`reportMarkdown` 全文**(或 Read `reportMarkdownFile` 的完整内容)作为 **Markdown 消息发给用户**(可附文件路径)。报告已含概览、数量汇总、按广告组展开的关键词/RSA 标题与描述状态表、仍未创建项。
153
+ - 流水线:`batch get` 至终态 →(搜索)**每次** `batch diff` 后**立刻交付** 再自动补建 补建后可再 diff 并再交付更新版。
154
+ - **交付物必须是 Markdown 文档正文**:`ad batch diff` stdout `BEGIN_USER_DELIVERY_MARKDOWN` `END_USER_DELIVERY_MARKDOWN` 之间的全文(即 `reportMarkdown`)**原样**作为对用户消息发出;亦可 Read `reportMarkdownFile`。报告含概览、数量汇总、按广告组展开的关键词/RSA 状态表、仍未创建项。
155
+ - **交付优先于补建**:不得以「先补扩展/稍后再统一读 reportMarkdown」推迟对用户发详情;假称「详情已交付」却只贴汇总表 = 违规。
155
156
  - 多系列:每个系列各跑一次 diff,**各发一份** Markdown(或同一回复里多份 `#` 一级标题分节)。
156
- - **禁止**只说「已创建成功 / 未发现缺失」、**禁止**只贴 `counts` 摘要而不发 `reportMarkdown`;代改过用户方案时另加修改表(见 `google-ads-plan-source-fidelity.md`)。
157
+ - **禁止**只说「已创建成功 / 详情已交付 / 未发现缺失」、**禁止**只贴 `counts`/系列 ID 摘要表;代改过用户方案时另加修改表(见 `google-ads-plan-source-fidelity.md`)。
157
158
  - **不确定时读文档**:先读对应 references 或用 `-h`,不要猜参数。
158
159
  - **跨账号 / 企业管家手机号**:用户消息中出现**中国大陆 11 位手机号**(常见语境:「企业管家」「管家账户」「账号 xxx」)且意图是查**该手机号名下**的账户数据时,**必须先**执行 `siluzan-tso account me --check-phone <手机号> --json-out ./snap-me`。**禁止**在未校验通过前用当前凭据拉他户数据。
159
160
  - `matched: true`(或 CLI exit 0)→ 按原工作流继续(如 P3 `accounts-digest` 查 TOP 消耗)。
@@ -277,7 +278,7 @@
277
278
 
278
279
  - **400**:参数错误,查看对应 reference 或 `-h`
279
280
  - **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`
280
- - **403(拉数空结果 / ad 网关)**:① **优先核验 `-a` 是否为 `ma.mediaCustomerId`**(勿传 `entityId`/UUID;Google 注意连字符 CID;Yandex 形如 `porg-…`);② Google 看套餐是否激活(`scopeActivatedSources`),未激活则说明需先激活,**禁止**非 CLI 绕过取数;③ **禁止臆测授权过期**:套餐已激活时**必须**跑 `account check-access -a <mediaCustomerId>`,以 `status` 为准后再决定是否 `reauth`;**禁止**仅凭 403 文案对用户说「授权过期」。
281
+ - **403(拉数空结果 / ad 网关)**:① **优先核验 `-a` 是否为 `ma.mediaCustomerId`**(勿传 `entityId`/UUID;Google 注意连字符 CID;Yandex 形如 `porg-…`);② 仅当 `list-accounts` **输出含** `scopeActivatedSources` 且可判定未激活时,才可说明需先激活;**无该字段则禁止谈套餐**;**禁止**非 CLI 绕过取数;③ **禁止臆测授权过期**:**必须**跑 `account check-access -a <mediaCustomerId>`,以 `status` 为准后再决定是否 `reauth`;**禁止**仅凭 403 文案对用户说「授权过期」。
281
282
  - **500**:服务可能正在部署/升级,建议反馈 Siluzan 相关人员
282
283
 
283
284
  ---
@@ -240,6 +240,7 @@
240
240
  | 「这个**网站**好不好 / 能不能投 / **是否符合投放要求**」(无广告方案诉求) | **P8** | 误走 W3(因带「Google 广告」);或 WebFetch 当终稿 |
241
241
  | 「**电商/制造**行业怎么样 / 市场格局」(**无 URL**) | **P9** | 误走 P8 |
242
242
  | 「根据**官网**做 **Google 搜索广告** / 关键词表」 | **W3**(可无账户先出方案) | 误走 P8;或卡在要账户才出方案 |
243
+ | 「做 **展示广告** / Display / 自适应展示广告(RDA)」 | **不支持**(告知用户;可改推 Search / PMax → W3) | 误用 `campaign-create` / `ad-create` 伪装 Display |
243
244
  | 「读**网址/文章** + **核心词** + 要 **月搜索量/竞争度** 长尾词表」 | **W5(§零·C)** | 纯 WebSearch 编数;误走 P8/P9/W3 |
244
245
  | 只要 **Keyword Planner / 拓词** 指标,不要 campaign JSON | **W5** | 误走 W3 走 validate/create |
245
246
 
@@ -264,6 +265,7 @@
264
265
  | `转化成本监控` / `CPA 监控` / `谷歌ADS转化成本` / `低余额账户转化成本` | **P3(§零·D)** | `accounts-digest`;可加 `--max-cpa` |
265
266
  | `昨日零询盘` / `零询盘账户` / `0 转化` / `有消耗无转化`(**无 CRM 附件**) | **P3(§零·D)** | `--zero-conversions`;**不是 P7** |
266
267
  | `根据 … 生成 Google **搜索**广告` / `搜索广告方案` / `关键词表` + 官网 URL | **W3** | ≠ P8 ≠ P9;若同时要 **搜索量/竞争度** → **W5** |
268
+ | `展示广告` / `Display 广告` / `自适应展示广告` / `RDA`(要创建/出方案) | **不支持** | 仅 Search + PMax;告知后可改推 W3 |
267
269
  | **月搜索量** / **竞争度** / **Keyword Planner** / **长尾关键词** / **针对核心词推荐** | **W5(§零·C)** | 必 `keyword --google-only` |
268
270
  | `丝路赞` / `Siluzan` + `优化报告列表` / `报告推送` | **W7** | ≠ 自拉数 P1/P4 |
269
271
 
@@ -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
  ---
@@ -63,7 +63,7 @@ siluzan-tso config set --api-key <Key> # 或 config 直接写入
63
63
  siluzan-tso config set --token <Token> # 备用:设置 JWT Token
64
64
  ```
65
65
 
66
- API Key 获取入口:`https://www.siluzan.com/v3/foreign_trade/settings/apiKeyManagement`
66
+ API Key 获取入口:`https://www-ci.siluzan.com/v3/foreign_trade/settings/apiKeyManagement`
67
67
 
68
68
  ```bash
69
69
  # 第 1 步:让用户报出手机号后,立刻发码(命令立即返回,不会等待输入)
@@ -126,9 +126,9 @@ siluzan-tso config show
126
126
 
127
127
  ```
128
128
  构建环境 : production
129
- apiBaseUrl : https://tso-api.siluzan.com
130
- googleApiUrl : https://googleapi.mysiluzan.com
131
- webUrl : https://www.siluzan.com
129
+ apiBaseUrl : https://tso-api-ci.siluzan.com
130
+ googleApiUrl : https://googleapi-ci.mysiluzan.com
131
+ webUrl : https://www-ci.siluzan.com
132
132
  apiKey : abcd****1234
133
133
  ```
134
134
 
@@ -55,6 +55,7 @@
55
55
  ## W3 · Google 广告创建与精细管理
56
56
 
57
57
  - **触发**:新建搜索系列、出投放方案、**按 Excel/表格投放方案创建**、**根据官网/网站/URL 生成 Google 搜索广告(含「表格格式」)**、搜索广告文案/关键词/计划表、系列/组/广告/关键词 CRUD、PMax、拒审处理、日常调价/启停。
58
+ - **类型边界**:本工作流 **仅支持** Google **搜索广告(Search)** 与 **PMax**;**不支持展示广告(Display)**(含 RDA / 独立 Display 系列)。用户要做展示广告 → 明确告知不支持,可改推 Search / PMax;**禁止**用本卡片流程伪装创建 Display。
58
59
  - **勿误判**:仅给官网 URL 且目标是「写/生成搜索广告」→ **本卡片(W3)**,不是 P8 网站诊断、不是 P9 市场分析;若用户只要拓词无系列结构 → **W5**。
59
60
  - **仅出方案(默认优先)**:用户说「出方案 / 规划 / 表格 / 先别创建·开户·投钱」,或**未给账户且未要求创建** → 按 `google-ads-campaign-plan.md` §「仅出方案 vs 创建」:落盘 JSON + **写代码投影完整审查稿**(默认 MD;用户指定则 Excel 等),`account`=`[PENDING_ACCOUNT]`;**禁止**先要广告账户再开工;跳过 `list-accounts` / `geo resolve` / validate / create,直到用户确认创建。
60
61
  - **必读**:方案与门禁 `references/google-ads/google-ads-campaign-plan.md` + **`assets/campaign-create-template.json`**(先 Read)+ `assets/campaign-create-template.md` + `rules/google-ads-launch-plan-template.md`;**有 Excel/表格方案时另读** `references/google-ads/rules/google-ads-plan-source-fidelity.md`;写命令参数 `references/google-ads/google-ads-write.md`;查询/拒审 `google-ads-read.md`;batch 补建 `google-ads-batch.md`;PMax 加 **`assets/pmax-create-template.json`** + `assets/pmax-create-template.md` + `rules/google-ads-pmax-launch-plan-template.md` + `references/google-ads/pmax-api.md`。
@@ -82,7 +83,7 @@
82
83
  2. `ad geo resolve -a <id> --from-file ./locations.json --json-out ./snap-geo`,把 id 写回 JSON。
83
84
  3. `ad campaign-validate`;**有不合规 → 询问「您自己改还是我帮您改?」**(见 `google-ads-plan-source-fidelity.md`)→ **写代码投影完整审查稿** → 用户确认 → `campaign-create` → `batch get` / `batch diff` / 自动补扩展 → **必出系列创建详情报告**;若 Agent 代改过 → 详情中**另附**修改表(创建清单 + 从 xxx→xxx + 原因)。
84
85
  - **步骤(Search 一体化创建,无现成方案文件)**:
85
- 0. **最小清单**(详见 `google-ads-campaign-plan.md` §创建前最小命令清单):`list-accounts -m Google -k …` →(已激活)`account check-access` → geo → validate → 审查稿 → create → `batch get`(看 `agentWorkflow`)→ **仅有 campaignId 时** `batch diff`。命令是 `ad campaigns`(禁 `ad-campaigns`/`campaign list`);geo/ad 失败禁臆测授权过期。
86
+ 0. **最小清单**(详见 `google-ads-campaign-plan.md` §创建前最小命令清单):`list-accounts -m Google -k …` → `account check-access` → geo → validate → 审查稿 → create → `batch get`(看 `agentWorkflow`)→ **仅有 campaignId 时** `batch diff`。命令是 `ad campaigns`(禁 `ad-campaigns`/`campaign list`);geo/ad 失败禁臆测授权过期;仅当列表输出含激活字段且未激活时才先处理激活。
86
87
  1. 地域:多国 `ad geo resolve --json-out`;单国 `ad geo search -a <id> -q "United States" --json-out`(读 `picked`/`targetedLocations`;仍禁止编造)。
87
88
  2. 门禁:`ad campaign-validate --config-file ./campaign.json --json-out …`(必跑;STRUCTURED_SNIPPET Key 须合法英文标头;ACCELERATED 预算看 warnings)。
88
89
  3. **写代码**按 `google-ads-launch-plan-template.md` 从 JSON 投影完整审查稿 → 用户确认。
@@ -1,6 +1,8 @@
1
1
  # Google 搜索广告:方案生成与系列创建
2
2
 
3
3
  > **新建/规划搜索系列时 Read 本文件**。写命令见 `google-ads-write.md`;batch 见 `google-ads-batch.md`;查询见 `google-ads-read.md`。
4
+ >
5
+ > **类型边界**:本文件仅覆盖 **搜索广告(Search)**。PMax 走 `pmax-api.md` / `pmax-create-template`。**不支持展示广告(Display)**——用户要 Display 时须说明不支持,勿用本文件 JSON 伪装。
4
6
 
5
7
  ---
6
8
 
@@ -66,8 +68,9 @@
66
68
  | 8 | 用户确认后 **`ad campaign-create`** | `references/google-ads/google-ads-write.md` |
67
69
  | 9 | 每隔5s 获取创建结果 | `ad batch get --id <taskId> --config-file ./campaign.json` |
68
70
  | 10 | 成功或部分成功后 **`ad batch diff`** 对照 JSON 与账户实况 | |
69
- | 11 | **自动补建缺失项**(见下文「batch diff 后自动补建」):附加信息(Sitelink/Callout 等)**直接**执行 `ad extension *`;组/词/RSA 用对应 create 命令。**勿**仅汇报失败并反问用户是否补建 | `references/google-ads/google-ads-batch.md` § batch diff 后自动补建 |
70
- | 12 | **向用户交付系列创建详情**(每个系列:计划 vs 实况、补建、失败项);代改过方案时**另附**修改表(从 xxx → xxx + 原因) | `agent-conventions.md` §四;**`rules/google-ads-plan-source-fidelity.md`** § 创建完成报告 |
71
+ | 11 | **立刻交付创建详情**:把 diff stdout `BEGIN_USER_DELIVERY_MARKDOWN`…`END` 全文原样发给用户(先于补建;禁止只贴汇总表) | `agent-conventions.md` §四 |
72
+ | 12 | **自动补建缺失项**(见下文):扩展/地域等执行 `remediateCommand`;补建后再 diff 时可再发更新版详情。**勿**仅反问用户是否补建 | `references/google-ads/google-ads-batch.md` § batch diff 后自动补建 |
73
+ | 13 | 代改过方案时**另附**修改表(从 xxx → xxx + 原因) | **`rules/google-ads-plan-source-fidelity.md`** § 创建完成报告 |
71
74
 
72
75
  多系列:每系列一个 JSON;可选 `campaign-manifest.json`(`role: brand|competitor|generic`)仅作文件组织参考。
73
76
 
@@ -157,12 +160,12 @@ validate 与 create **共用** `runCampaignCreateValidation`:词面规范化 +
157
160
  | ---- | ---- |
158
161
  | 1 | `ad batch get --id <taskId> --config-file ./campaign.json --json-out ./snap-campaign` 直至终端态(Creating 时每 5s 轮询;**读落盘 `agentWorkflow.nextCommand`**,勿只看人读提示) |
159
162
  | 2 | `Successfully` / `HasFailed`:执行 `agentWorkflow.nextCommand`(即 `ad batch diff … --json-out`);**Failed** 勿 diff |
160
- | 3 | 读落盘 `ok` / `missing[]`;`layer=location` 执行 `ad geo add`;`layer=extension` → 执行 `remediateCommand` |
161
- | 4 | `remediateCommand` 时,按 JSON 路径映射 `ad extension *` / `adgroup-create` / `keyword-create` / `ad-create` / `keyword-negative-create` |
162
- | 5 | 有缺失时 CLI **exit 2**;补建后再 `ad batch diff`,直到 `ok===true`(含 `counts.liveLocations === plannedLocations`) |
163
- | 6 | 汇总告诉用户「已自动补上 N 个投放国家 / M Sitelink」 |
164
- | 7 | 仅当补建命令也失败时,才向用户说明原因并给改写方案 |
165
- | 8 | **向用户发送 Markdown 创建详情**(必做,即使 `ok===true`):把 `batch diff` 的 **`reportMarkdown` 全文**(或 Read `reportMarkdownFile`)作为 Markdown 消息发出;含关键词/RSA 文案逐条状态。**禁止**只说「创建完成 / 未发现缺失」。多系列各发一份。细则见 `agent-conventions.md` §四;代改方案另附修改表见 `google-ads-plan-source-fidelity.md` |
163
+ | 3 | **立刻交付**:把本次 diff stdout `BEGIN_USER_DELIVERY_MARKDOWN`…`END_USER_DELIVERY_MARKDOWN` 全文原样发给用户(即 `reportMarkdown`)。**禁止**只贴系列 ID/counts 摘要,**禁止**等补建结束再交付 |
164
+ | 4 | 读落盘 `ok` / `missing[]`;`layer=location` `ad geo add`;`layer=extension` 执行 `remediateCommand` |
165
+ | 5 | `remediateCommand` 时,按 JSON 路径映射 `ad extension *` / `adgroup-create` / `keyword-create` / `ad-create` / `keyword-negative-create` |
166
+ | 6 | 有缺失时 CLI **exit 2**;补建后再 `ad batch diff`,直到 `ok===true`;每次 diff 后若状态有变可再发更新版详情 |
167
+ | 7 | 可简短补充「已自动补上 N 个投放国家 / M 条 Sitelink」(**不能代替**步骤 3 的 Markdown 全文) |
168
+ | 8 | 仅当补建命令也失败时,才向用户说明原因并给改写方案;代改方案另附修改表见 `google-ads-plan-source-fidelity.md` |
166
169
 
167
170
  **Agent 易漏点**:`--json-out` 时人读「下一步」不会打印——**必须以落盘 `agentWorkflow` 为准**;`campaign-create` 落盘同样带 `agentWorkflow.nextCommand`(首轮 `batch get`)。
168
171
 
@@ -12,12 +12,21 @@
12
12
 
13
13
  ---
14
14
 
15
+ ## 支持范围
16
+
17
+ - ✅ **搜索广告(Search)**:`campaign-validate` / `campaign-create`、组/关键词、`ad-create`(RSA)等
18
+ - ✅ **Performance Max(PMax)**:`pmax-validate` / `pmax-create` 及存量 PMax 写命令(见 `pmax-api.md`)
19
+ - ❌ **展示广告(Display)**:**不支持**创建与精细管理(含 RDA);用户要 Display 时须说明不支持并改推 Search / PMax,**禁止**伪装创建
20
+
21
+ ---
22
+
15
23
  ## 写操作硬纪律(Agent 易踩)
16
24
 
17
25
  - **必须** `--commit "…"`;漏了会直接失败。
18
26
  - 列表命令:`ad campaigns` / `ad groups` / `ad list` / `ad keywords`(**没有** `google-ads`、没有必用 `campaign-list`;`campaign-list` 仅为 `campaigns` 别名)。
19
27
  - `--json-out <path>`:**路径必填**,JSON 落盘;禁止 `--json-out` 裸用或管道 stdout。
20
28
  - 系列 `statusDisplay` 含「投放期已结束」≠ 已删除;以 JSON **`statusV2`** 为准(见 `google-ads-read.md`)。
29
+ - **勿创建 Display**:`campaign-create` / `ad-create` 仅面向 Search(RSA);PMax 走 `pmax-*`。
21
30
 
22
31
  ---
23
32
 
@@ -173,11 +182,11 @@ siluzan-tso ad batch diff --batch-id <taskId> --config-file ./campaign.json --js
173
182
  BatchJob 常漏 **附加信息**(Sitelink)与 **投放地域**;系列/组/词/RSA 往往已成功。用户确认创建时已认可 JSON → Agent **须直接补建**,**禁止**仅汇报「未创建,需要我现在补上吗?」。
174
183
 
175
184
  1. `ad campaign-create` / `ad batch get` 的 `--json-out` 落盘含 **`agentWorkflow`**:读 `nextCommand` / `shouldRunBatchDiff` / `agentHint`(人读提示在 `--json-out` 早退时不可见)。
176
- 2. 跑 `ad batch diff`;对 `missing[]` 中带 `remediateCommand` 的项**直接执行**(`location` → `ad geo add`;`extension` → `ad extension *`)。
177
- 3. 扩展字段映射:`Properties.Text` + `DestinationUrl` → `ad extension sitelink`;`CALLOUT` → `callout`;`CALL` `call`;`STRUCTURED_SNIPPET` → `snippet`。
178
- 4. 有缺失时 CLI **exit 2**;补建后再跑一次 `ad batch diff`,直到 `ok===true`。
179
- 5. 向用户汇报已补挂条数(地域 + Sitelink 等)。
180
- 6. **无论全成功或部分失败**,收尾必须把 **`reportMarkdown` 全文以 Markdown 发给用户**(见 `--md-out` / `reportMarkdownFile`)。**禁止**只说「已创建成功」或只复述「未发现缺失」。见 `agent-conventions.md` §四。
185
+ 2. 跑 `ad batch diff`;stdout `BEGIN_USER_DELIVERY_MARKDOWN`…`END`——**立刻原样发给用户**(先于补建)。
186
+ 3. `missing[]` 中带 `remediateCommand` 的项**直接执行**(`location` → `ad geo add`;`extension` → `ad extension *`)。
187
+ 4. 扩展字段映射:`Properties.Text` + `DestinationUrl` `ad extension sitelink`;`CALLOUT` `callout`;`CALL` → `call`;`STRUCTURED_SNIPPET` → `snippet`。
188
+ 5. 有缺失时 CLI **exit 2**;补建后再跑一次 `ad batch diff`,直到 `ok===true`;可再发更新版详情。
189
+ 6. 可简短补充已补挂条数(**不能代替**步骤 2 Markdown 全文)。**禁止**只说「已创建成功 / 详情已交付」或只复述「未发现缺失」。见 `agent-conventions.md` §四。
181
190
 
182
191
  完整流水线见 `references/google-ads/google-ads-campaign-plan.md` § batch diff 后自动补建。
183
192
 
@@ -2,6 +2,18 @@
2
2
 
3
3
  > `SKILL.md` / 工作流已指向子文件时,**直接 Read 子文件**。本文件含共享 Gotchas。
4
4
 
5
+ ## 支持的广告类型(硬边界)
6
+
7
+ | 类型 | CLI / Skill | 说明 |
8
+ | ---- | ----------- | ---- |
9
+ | **搜索广告(Search)** | ✅ 支持 | 方案、`campaign-validate` / `campaign-create`、组/RSA/关键词 CRUD、扩展等 |
10
+ | **Performance Max(PMax)** | ✅ 支持 | `pmax-validate` / `pmax-create` 及存量 PMax 管理(见 `pmax-api.md`) |
11
+ | **展示广告(Display)** | ❌ **不支持** | 含独立 Display 系列、自适应展示广告(RDA)等;**禁止**创建或伪装创建 |
12
+
13
+ 用户明确要求展示广告时:如实告知不支持,可改推 Search 或 PMax;**禁止**用搜索系列 JSON / `ad-create`(RSA)冒充 Display。
14
+
15
+ > 账户内若已有 Display 系列,`ad campaigns` 等**只读列表**仍可能见到(`channelTypeV2` 含 `DISPLAY`);本 Skill **不对**其做方案/创建/精细写管理。
16
+
5
17
  ## 何时 Read
6
18
 
7
19
  | 任务 | Read |
@@ -15,13 +27,14 @@
15
27
 
16
28
  ## Gotchas
17
29
 
30
+ - **广告类型**:仅 Search + PMax;**不支持 Display**(见上文「支持的广告类型」)。
18
31
  - **命令名**:系列列表是 `ad campaigns`(别名 `campaign-list`),**禁止** `ad-campaigns` / `campaign list`。`balance`/`stats` 须 `-m Google`。
19
32
  - **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`。
20
- - **禁止臆测授权过期**:`ad *` / geo / 拉数出现 403/500 时,**禁止**对用户说「授权可能过期」。须核验 ID 后,在套餐已激活前提下执行 `account check-access -a <mediaCustomerId>`,仅当 `reauth_required`(或与 `invalidOAuthToken=true` 交叉确认)才走重授权。见 [`accounts-permissions.md`](../accounts/accounts-permissions.md)。
33
+ - **禁止臆测授权过期**:`ad *` / geo / 拉数出现 403/500 时,**禁止**对用户说「授权可能过期」。须核验 ID 后执行 `account check-access -a <mediaCustomerId>`,仅当 `reauth_required`(或与 `invalidOAuthToken=true` 交叉确认)才走重授权;无激活字段时禁止谈套餐。见 [`accounts-permissions.md`](../accounts/accounts-permissions.md)。
21
34
  - **预算投放**:`BudgetBudgetDeliveryMethodV2` 默认用 `STANDARD`;`ACCELERATED` 多数账户会被 Google 拒(validate 警告)。
22
35
  - **STRUCTURED_SNIPPET**:`StructuredSnippetHeaderValue.Key` 须为合法英文标头(`ad extension snippet-headers`);`Features` 等非法值 validate 会拦(建议 `Amenities`)。
23
36
  - **batch get**:读 `agentWorkflow`——无 `campaignId` 的 Failed/HasFailed **禁止**跑 `batch diff`,按 `agentHint` 改 JSON 重提。
24
- - **batch diff 交付**:把 `reportMarkdown`(或 `reportMarkdownFile`)**全文以 Markdown 发给用户**;**禁止**只说「未发现缺失」。
37
+ - **batch diff 交付**:把 stdout 中 `BEGIN_USER_DELIVERY_MARKDOWN`…`END`(或 `reportMarkdownFile`)**全文以 Markdown 发给用户**(先于补建);**禁止**只说「未发现缺失 / 详情已交付」。
25
38
  - `-a` 必须是 `list-accounts -m Google` 的 `ma.mediaCustomerId`,**禁止**传 `entityId`(UUID)。
26
39
 
27
40
  ## 金额单位(全局重要)
@@ -6,7 +6,7 @@
6
6
  siluzan-tso config show # 取 webUrl
7
7
  ```
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
  ---
12
12
 
@@ -25,7 +25,7 @@ siluzan-tso config show # 取 webUrl
25
25
 
26
26
  ## 推荐话术
27
27
 
28
- 1. **「和首页一样的总览」** → 打开 `https://www.siluzan.com/v3/foreign_trade/tso/home`。
28
+ 1. **「和首页一样的总览」** → 打开 `https://www-ci.siluzan.com/v3/foreign_trade/tso/home`。
29
29
  2. **「某个 Google 账户昨天花了多少」** → `list-accounts -m Google` + `stats -m Google -a <id>`。
30
30
  3. **「有待充值账户」** → 说明聚合数据在首页;CLI 可 `list-accounts` + `balance` 逐户排查,或引导充值页。
31
31
 
@@ -9,11 +9,11 @@ $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'
12
+ $PKG_VERSION = '1.1.44-beta.2'
13
13
  $CLI_BIN = 'siluzan-tso'
14
14
  $SKILL_LABEL = 'Siluzan TSO'
15
- $INSTALL_CMD = 'npm install -g siluzan-tso-cli'
16
- $WEB_BASE = 'https://www.siluzan.com'
15
+ $INSTALL_CMD = 'npm install -g siluzan-tso-cli@beta'
16
+ $WEB_BASE = 'https://www-ci.siluzan.com'
17
17
 
18
18
  # -- Constants ----------------------------------------------------------------
19
19
  $NODE_MAJOR_MIN = 18
@@ -9,11 +9,11 @@ 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"
12
+ readonly PKG_VERSION="1.1.44-beta.2"
13
13
  readonly CLI_BIN="siluzan-tso"
14
14
  readonly SKILL_LABEL="Siluzan TSO"
15
- readonly INSTALL_CMD="npm install -g siluzan-tso-cli"
16
- readonly WEB_BASE="https://www.siluzan.com"
15
+ readonly INSTALL_CMD="npm install -g siluzan-tso-cli@beta"
16
+ readonly WEB_BASE="https://www-ci.siluzan.com"
17
17
 
18
18
  # -- Constants ----------------------------------------------------------------
19
19
  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.43",
3
+ "version": "1.1.44-beta.2",
4
4
  "description": "Siluzan 广告账户管理 CLI — 查询账户、余额、消耗数据,管理绑定关系与充值。",
5
5
  "keywords": [
6
6
  "ad-account",