siluzan-tso-cli 1.1.48-beta.8 → 1.1.48

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.
Files changed (28) hide show
  1. package/README.md +1 -2
  2. package/dist/index.js +909 -647
  3. package/dist/skill/SKILL.md +4 -4
  4. package/dist/skill/_meta.json +2 -2
  5. package/dist/skill/references/accounts/accounts-balance-stats.md +5 -5
  6. package/dist/skill/references/accounts/accounts-list.md +3 -3
  7. package/dist/skill/references/accounts/accounts-permissions.md +4 -4
  8. package/dist/skill/references/accounts/accounts.md +1 -1
  9. package/dist/skill/references/accounts/finance.md +3 -3
  10. package/dist/skill/references/accounts/open-account-by-media.md +3 -54
  11. package/dist/skill/references/accounts/open-account-google-ui.md +1 -1
  12. package/dist/skill/references/analytics/account-analytics.md +27 -3
  13. package/dist/skill/references/analytics/rag.md +1 -1
  14. package/dist/skill/references/analytics/reporting.md +5 -5
  15. package/dist/skill/references/core/agent-conventions.md +5 -7
  16. package/dist/skill/references/core/cli-enums.md +1 -9
  17. package/dist/skill/references/core/setup.md +5 -5
  18. package/dist/skill/references/core/workflows.md +5 -5
  19. package/dist/skill/references/misc/tso-home.md +2 -2
  20. package/dist/skill/references/operations/hosted-automation-scenarios.md +1 -1
  21. package/dist/skill/references/operations/hosted-automation-user-catalog.md +9 -7
  22. package/dist/skill/references/operations/hosted-automation-yandex.md +104 -34
  23. package/dist/skill/references/report-templates/excel-style-guide.md +1 -3
  24. package/dist/skill/report-templates/excel-style-guide.md +1 -3
  25. package/dist/skill/report-templates/excel-style-kit.mjs +1 -2
  26. package/dist/skill/scripts/install.ps1 +3 -3
  27. package/dist/skill/scripts/install.sh +3 -3
  28. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2636,18 +2636,6 @@ function decodeJwtClaims(token) {
2636
2636
  function decodeJwtSub(token) {
2637
2637
  return decodeJwtClaims(token)?.sub ?? null;
2638
2638
  }
2639
- function sleep(ms) {
2640
- return new Promise((resolve52) => setTimeout(resolve52, ms));
2641
- }
2642
- async function pollUntil(fn, intervalMs, timeoutMs) {
2643
- const deadline = Date.now() + timeoutMs;
2644
- while (Date.now() < deadline) {
2645
- const result = await fn();
2646
- if (result !== null) return result;
2647
- await sleep(intervalMs);
2648
- }
2649
- return null;
2650
- }
2651
2639
  function getCurrentVersion(importMetaUrl) {
2652
2640
  try {
2653
2641
  const __dirname3 = path2.dirname(fileURLToPath(importMetaUrl));
@@ -4030,7 +4018,7 @@ var DEFAULT_API_BASE;
4030
4018
  var init_defaults = __esm({
4031
4019
  "src/config/defaults.ts"() {
4032
4020
  "use strict";
4033
- DEFAULT_API_BASE = "https://tso-api-ci.siluzan.com";
4021
+ DEFAULT_API_BASE = "https://tso-api.siluzan.com";
4034
4022
  }
4035
4023
  });
4036
4024
 
@@ -4835,27 +4823,6 @@ async function fetchBalanceMap(media, accountIds, config, startDate, endDate, ve
4835
4823
  indexByMediaCustomerId(result, String(item.mediaCustomerId), item);
4836
4824
  }
4837
4825
  }
4838
- } else if (media === "Kwai") {
4839
- const range = defaultDateRange();
4840
- const params = new URLSearchParams({
4841
- period: "true",
4842
- startDate: startDate ?? range.startDate,
4843
- endDate: endDate ?? range.endDate,
4844
- mediaCustomerIds: accountIds.join(",")
4845
- });
4846
- const url = `${config.apiBaseUrl}/report/media-account/Kwai/accountsoverview?${params}`;
4847
- const raw = await apiFetch2(url, config, {}, verbose);
4848
- const items2 = Array.isArray(raw) ? raw : [];
4849
- for (const item of items2) {
4850
- if (item.mediaAccountId != null) {
4851
- result.set(String(item.mediaAccountId), {
4852
- mediaCustomerId: item.mediaAccountId,
4853
- remainingAccountBudget: item.remainingAccountBudget,
4854
- status: item.status,
4855
- currencyCode: item.currencyCode
4856
- });
4857
- }
4858
- }
4859
4826
  }
4860
4827
  } catch {
4861
4828
  }
@@ -5040,7 +5007,6 @@ var init_balance = __esm({
5040
5007
  "Yandex",
5041
5008
  "TikTok",
5042
5009
  "BingV2",
5043
- "Kwai",
5044
5010
  "MetaAd"
5045
5011
  ];
5046
5012
  CHINA_OFFSET_MS2 = 8 * 36e5;
@@ -5117,8 +5083,6 @@ function mediaAccountDataBatchSize(media) {
5117
5083
  case "TikTok":
5118
5084
  case "Yandex":
5119
5085
  return 10;
5120
- case "Kwai":
5121
- return 20;
5122
5086
  default:
5123
5087
  return 100;
5124
5088
  }
@@ -5245,18 +5209,6 @@ var init_list_fetch = __esm({
5245
5209
  },
5246
5210
  responseType: "mas"
5247
5211
  },
5248
- Kwai: {
5249
- path: "/query/media-account/SearchMediaAcountByCriteria",
5250
- pageParam: "pageNum",
5251
- fixedParams: {
5252
- MediaTypes: "Kwai",
5253
- MediaType: "Kwai",
5254
- advStatus: "",
5255
- mediaAccountState: "Approved,Linked",
5256
- isForce: false
5257
- },
5258
- responseType: "mas"
5259
- },
5260
5212
  MetaAd: {
5261
5213
  path: "/query/media-account/SearchMediaAcountByCriteria",
5262
5214
  pageParam: "pageNum",
@@ -5561,7 +5513,7 @@ function register10(program2) {
5561
5513
  "\u591A\u8D26\u6237\u6295\u653E\u753B\u50CF\uFF1A\u4E00\u6761\u547D\u4EE4\u62FF\u9F50\u6D88\u8017/\u70B9\u51FB/\u8F6C\u5316/\u4F59\u989D/\u6D3E\u751F\u6307\u6807\uFF08CTR/CPC/CPA\uFF09\uFF0C\u66FF\u4EE3 AI \u9010\u8D26\u6237 `list-accounts` + `stats` \u7684\u7F16\u6392\u3002\u5178\u578B\u573A\u666F\uFF1A\u300C\u8FD9 10 \u4E2A\u8D26\u6237\uFF08\u6216\u67D0\u5A92\u4F53\u5168\u90E8\u8D26\u6237\uFF09\u5E2E\u6211\u6574\u7406\u4E00\u4E0B\u300D\u3001\u8F6C\u5316\u6210\u672C/CPA/\u96F6\u8F6C\u5316\u5DE1\u68C0\u3002\u65E0 --period\uFF1B\u533A\u95F4\u7528 --start/--end\uFF08\u6216 --start-date/--end-date\uFF09\u3002"
5562
5514
  ).requiredOption(
5563
5515
  "-m, --media <type>",
5564
- "\u5A92\u4F53\u7C7B\u578B\uFF1AGoogle | TikTok | Yandex | MetaAd | BingV2 | Kwai"
5516
+ "\u5A92\u4F53\u7C7B\u578B\uFF1AGoogle | TikTok | Yandex | MetaAd | BingV2"
5565
5517
  ).option(
5566
5518
  "-a, --accounts <ids>",
5567
5519
  "\u6307\u5B9A\u8D26\u6237 mediaCustomerId\uFF0C\u9017\u53F7\u5206\u9694\uFF1B\u7559\u7A7A\u5219\u626B\u63CF\u8BE5\u5A92\u4F53\u4E0B\u5168\u90E8\u8D26\u6237"
@@ -102375,8 +102327,8 @@ var init_fetch = __esm({
102375
102327
  });
102376
102328
 
102377
102329
  // src/commands/google-analysis/merge-snapshot.ts
102378
- import * as fs23 from "fs/promises";
102379
- import * as path28 from "path";
102330
+ import * as fs22 from "fs/promises";
102331
+ import * as path27 from "path";
102380
102332
  function asRecord11(value) {
102381
102333
  if (value && typeof value === "object" && !Array.isArray(value)) {
102382
102334
  return value;
@@ -102394,7 +102346,7 @@ async function readManifest(snapshotDir, accountId) {
102394
102346
  const candidates = [];
102395
102347
  if (accountId) candidates.push(googleAnalysisManifestFile(accountId));
102396
102348
  try {
102397
- const entries = await fs23.readdir(snapshotDir);
102349
+ const entries = await fs22.readdir(snapshotDir);
102398
102350
  const manifestNames = entries.filter((n) => n.startsWith("manifest") && n.endsWith(".json"));
102399
102351
  for (const name2 of manifestNames) {
102400
102352
  if (!candidates.includes(name2)) candidates.push(name2);
@@ -102403,7 +102355,7 @@ async function readManifest(snapshotDir, accountId) {
102403
102355
  }
102404
102356
  for (const name2 of candidates) {
102405
102357
  try {
102406
- const raw = await fs23.readFile(path28.join(snapshotDir, name2), "utf8");
102358
+ const raw = await fs22.readFile(path27.join(snapshotDir, name2), "utf8");
102407
102359
  const parsed = JSON.parse(raw);
102408
102360
  if (Array.isArray(parsed.artifacts) && parsed.artifacts.length > 0) return parsed;
102409
102361
  } catch {
@@ -102413,7 +102365,7 @@ async function readManifest(snapshotDir, accountId) {
102413
102365
  }
102414
102366
  async function loadSectionFile(snapshotDir, file) {
102415
102367
  try {
102416
- const raw = await fs23.readFile(path28.join(snapshotDir, file), "utf8");
102368
+ const raw = await fs22.readFile(path27.join(snapshotDir, file), "utf8");
102417
102369
  const parsed = JSON.parse(raw);
102418
102370
  if (parsed && typeof parsed === "object") return parsed;
102419
102371
  return null;
@@ -102447,7 +102399,7 @@ async function recoverMissingReportSections(sectionMap, absDir, accountId, prefe
102447
102399
  if (!accountId) return;
102448
102400
  let entries;
102449
102401
  try {
102450
- entries = await fs23.readdir(absDir);
102402
+ entries = await fs22.readdir(absDir);
102451
102403
  } catch {
102452
102404
  return;
102453
102405
  }
@@ -102519,7 +102471,7 @@ function sumCampaignRowsToPeriodKpis(rows) {
102519
102471
  };
102520
102472
  }
102521
102473
  async function mergeGoogleAnalysisSnapshotIntoReport(payload, snapshotDir) {
102522
- const absDir = path28.resolve(snapshotDir);
102474
+ const absDir = path27.resolve(snapshotDir);
102523
102475
  const metaAccountId = typeof asRecord11(payload.meta)?.accountId === "string" ? asRecord11(payload.meta)?.accountId : void 0;
102524
102476
  const manifest = await readManifest(snapshotDir, metaAccountId);
102525
102477
  if (!manifest) {
@@ -102798,19 +102750,19 @@ var init_report_content = __esm({
102798
102750
  });
102799
102751
 
102800
102752
  // src/commands/google-analysis/render-report.ts
102801
- import fs24 from "fs";
102753
+ import fs23 from "fs";
102802
102754
  import fsPromises2 from "fs/promises";
102803
- import path29 from "path";
102755
+ import path28 from "path";
102804
102756
  import { fileURLToPath as fileURLToPath6 } from "url";
102805
102757
  function resolveSkillTemplatePath3(basename13) {
102806
- const dir = path29.dirname(fileURLToPath6(import.meta.url));
102758
+ const dir = path28.dirname(fileURLToPath6(import.meta.url));
102807
102759
  const candidates = [
102808
- path29.join(dir, "skill", "report-templates", basename13),
102809
- path29.join(dir, "skill", "siluzan-ads", "report-templates", basename13),
102810
- path29.join(dir, "..", "..", "assets", "siluzan-ads", "report-templates", basename13)
102760
+ path28.join(dir, "skill", "report-templates", basename13),
102761
+ path28.join(dir, "skill", "siluzan-ads", "report-templates", basename13),
102762
+ path28.join(dir, "..", "..", "assets", "siluzan-ads", "report-templates", basename13)
102811
102763
  ];
102812
102764
  for (const p of candidates) {
102813
- if (fs24.existsSync(p)) return p;
102765
+ if (fs23.existsSync(p)) return p;
102814
102766
  }
102815
102767
  return candidates[0];
102816
102768
  }
@@ -102839,10 +102791,10 @@ function injectReportData2(html, payload) {
102839
102791
  return html.replace(INJECT_MARKER, `window.__GOOGLE_PERIOD_REPORT__ = ${json};`);
102840
102792
  }
102841
102793
  async function runGoogleAnalysisRender(opts) {
102842
- const dataPath = path29.resolve(opts.dataFile);
102794
+ const dataPath = path28.resolve(opts.dataFile);
102843
102795
  let data = asRecord13(await readJsonFile2(dataPath));
102844
102796
  if (opts.snapshotDir?.trim()) {
102845
- data = await mergeGoogleAnalysisSnapshotIntoReport(data, path29.resolve(opts.snapshotDir));
102797
+ data = await mergeGoogleAnalysisSnapshotIntoReport(data, path28.resolve(opts.snapshotDir));
102846
102798
  }
102847
102799
  const contentCheck = validateGooglePeriodReportContent(data);
102848
102800
  if (!contentCheck.ok) {
@@ -102868,10 +102820,10 @@ async function runGoogleAnalysisRender(opts) {
102868
102820
  `);
102869
102821
  process.exit(1);
102870
102822
  }
102871
- const outPath = path29.resolve(
102872
- opts.out ?? path29.join(path29.dirname(dataPath), "google-period-report.html")
102823
+ const outPath = path28.resolve(
102824
+ opts.out ?? path28.join(path28.dirname(dataPath), "google-period-report.html")
102873
102825
  );
102874
- const outDir = path29.dirname(outPath);
102826
+ const outDir = path28.dirname(outPath);
102875
102827
  await fsPromises2.mkdir(outDir, { recursive: true });
102876
102828
  await fsPromises2.writeFile(outPath, injectReportData2(html, data), "utf8");
102877
102829
  const { stats } = contentCheck;
@@ -102898,8 +102850,8 @@ var init_render_report = __esm({
102898
102850
  });
102899
102851
 
102900
102852
  // src/utils/batch-manifest.ts
102901
- import * as fs25 from "fs/promises";
102902
- import * as path30 from "path";
102853
+ import * as fs24 from "fs/promises";
102854
+ import * as path29 from "path";
102903
102855
  import { randomUUID as randomUUID2 } from "crypto";
102904
102856
  function generateRunId(now = /* @__PURE__ */ new Date()) {
102905
102857
  const pad = (n) => String(n).padStart(2, "0");
@@ -102913,26 +102865,26 @@ function isValidRunId(id) {
102913
102865
  }
102914
102866
  function resolveBatchPaths(baseDir, runId) {
102915
102867
  if (!isValidRunId(runId)) throw new Error(`\u975E\u6CD5 runId\uFF1A${runId}`);
102916
- const runDir = path30.resolve(baseDir, runId);
102917
- const stateDir = path30.join(runDir, "state");
102868
+ const runDir = path29.resolve(baseDir, runId);
102869
+ const stateDir = path29.join(runDir, "state");
102918
102870
  return {
102919
102871
  runDir,
102920
- runManifestFile: path30.join(runDir, "run-manifest.json"),
102921
- progressFile: path30.join(runDir, "progress.json"),
102922
- accountsFile: path30.join(runDir, "accounts.json"),
102923
- resultsDir: path30.join(runDir, "results"),
102924
- errorsDir: path30.join(runDir, "errors"),
102872
+ runManifestFile: path29.join(runDir, "run-manifest.json"),
102873
+ progressFile: path29.join(runDir, "progress.json"),
102874
+ accountsFile: path29.join(runDir, "accounts.json"),
102875
+ resultsDir: path29.join(runDir, "results"),
102876
+ errorsDir: path29.join(runDir, "errors"),
102925
102877
  stateDir,
102926
- tasksLogFile: path30.join(stateDir, "tasks.jsonl"),
102927
- lockFile: path30.join(stateDir, "tasks.lock")
102878
+ tasksLogFile: path29.join(stateDir, "tasks.jsonl"),
102879
+ lockFile: path29.join(stateDir, "tasks.lock")
102928
102880
  };
102929
102881
  }
102930
102882
  async function ensureAccountDirs(paths, accountId) {
102931
102883
  const safe = sanitizeAccountSegment(accountId);
102932
- const results = path30.join(paths.resultsDir, safe);
102933
- const errors = path30.join(paths.errorsDir, safe);
102934
- await fs25.mkdir(results, { recursive: true });
102935
- await fs25.mkdir(errors, { recursive: true });
102884
+ const results = path29.join(paths.resultsDir, safe);
102885
+ const errors = path29.join(paths.errorsDir, safe);
102886
+ await fs24.mkdir(results, { recursive: true });
102887
+ await fs24.mkdir(errors, { recursive: true });
102936
102888
  return { results, errors };
102937
102889
  }
102938
102890
  function sanitizeAccountSegment(accountId) {
@@ -102947,20 +102899,20 @@ function sanitizeAccountSegment(accountId) {
102947
102899
  return slug;
102948
102900
  }
102949
102901
  async function atomicWriteFile(target, content) {
102950
- const dir = path30.dirname(target);
102951
- await fs25.mkdir(dir, { recursive: true });
102952
- const tmp = path30.join(dir, `.tmp-${randomUUID2()}-${path30.basename(target)}`);
102902
+ const dir = path29.dirname(target);
102903
+ await fs24.mkdir(dir, { recursive: true });
102904
+ const tmp = path29.join(dir, `.tmp-${randomUUID2()}-${path29.basename(target)}`);
102953
102905
  try {
102954
- await fs25.writeFile(tmp, content, "utf8");
102955
- await fs25.rename(tmp, target);
102906
+ await fs24.writeFile(tmp, content, "utf8");
102907
+ await fs24.rename(tmp, target);
102956
102908
  } catch (e) {
102957
- await fs25.rm(tmp, { force: true }).catch(() => void 0);
102909
+ await fs24.rm(tmp, { force: true }).catch(() => void 0);
102958
102910
  throw e;
102959
102911
  }
102960
102912
  }
102961
102913
  async function readJsonIfExists(file) {
102962
102914
  try {
102963
- const raw = await fs25.readFile(file, "utf8");
102915
+ const raw = await fs24.readFile(file, "utf8");
102964
102916
  return JSON.parse(raw);
102965
102917
  } catch (e) {
102966
102918
  if (e.code === "ENOENT") return null;
@@ -102990,12 +102942,12 @@ function readProgress(paths) {
102990
102942
  return readJsonIfExists(paths.progressFile);
102991
102943
  }
102992
102944
  async function appendTaskLog(paths, entry) {
102993
- await fs25.mkdir(paths.stateDir, { recursive: true });
102994
- await fs25.appendFile(paths.tasksLogFile, JSON.stringify(entry) + "\n", "utf8");
102945
+ await fs24.mkdir(paths.stateDir, { recursive: true });
102946
+ await fs24.appendFile(paths.tasksLogFile, JSON.stringify(entry) + "\n", "utf8");
102995
102947
  }
102996
102948
  async function readTaskLog(paths) {
102997
102949
  try {
102998
- const raw = await fs25.readFile(paths.tasksLogFile, "utf8");
102950
+ const raw = await fs24.readFile(paths.tasksLogFile, "utf8");
102999
102951
  return raw.split("\n").filter((s) => s.trim() !== "").map((line) => JSON.parse(line));
103000
102952
  } catch (e) {
103001
102953
  if (e.code === "ENOENT") return [];
@@ -103050,9 +103002,9 @@ function emptyProgress(runId, totalTasks, accountConcurrency, sectionConcurrency
103050
103002
  };
103051
103003
  }
103052
103004
  async function tryAcquireLock(paths) {
103053
- await fs25.mkdir(paths.stateDir, { recursive: true });
103005
+ await fs24.mkdir(paths.stateDir, { recursive: true });
103054
103006
  try {
103055
- const handle = await fs25.open(paths.lockFile, "wx");
103007
+ const handle = await fs24.open(paths.lockFile, "wx");
103056
103008
  await handle.writeFile(`${process.pid}@${(/* @__PURE__ */ new Date()).toISOString()}`);
103057
103009
  await handle.close();
103058
103010
  return true;
@@ -103062,7 +103014,7 @@ async function tryAcquireLock(paths) {
103062
103014
  }
103063
103015
  }
103064
103016
  async function releaseLock(paths) {
103065
- await fs25.rm(paths.lockFile, { force: true }).catch(() => void 0);
103017
+ await fs24.rm(paths.lockFile, { force: true }).catch(() => void 0);
103066
103018
  }
103067
103019
  var BATCH_SCHEMA_VERSION;
103068
103020
  var init_batch_manifest = __esm({
@@ -103074,8 +103026,8 @@ var init_batch_manifest = __esm({
103074
103026
 
103075
103027
  // src/utils/batch-runner.ts
103076
103028
  import { performance as performance2 } from "perf_hooks";
103077
- import * as path31 from "path";
103078
- import * as fs26 from "fs/promises";
103029
+ import * as path30 from "path";
103030
+ import * as fs25 from "fs/promises";
103079
103031
  async function runPool(items2, concurrencyRef, worker, signal) {
103080
103032
  let cursor = 0;
103081
103033
  const launch = () => {
@@ -103214,7 +103166,7 @@ async function runBatch(opts) {
103214
103166
  }
103215
103167
  const inner = {
103216
103168
  ...emptyProgress(
103217
- opts.paths.runDir.split(path31.sep).pop() ?? "run",
103169
+ opts.paths.runDir.split(path30.sep).pop() ?? "run",
103218
103170
  allTasks.length,
103219
103171
  opts.accountConcurrency,
103220
103172
  opts.sectionConcurrency
@@ -103339,7 +103291,7 @@ async function runBatch(opts) {
103339
103291
  signal: aborterToken.signal
103340
103292
  });
103341
103293
  await writer({
103342
- snapshotDir: path31.join(opts.paths.resultsDir, sanitizeAccountSegment(task.accountId)),
103294
+ snapshotDir: path30.join(opts.paths.resultsDir, sanitizeAccountSegment(task.accountId)),
103343
103295
  section: task.section,
103344
103296
  accountId: task.accountId,
103345
103297
  dateRange: result.dateRange,
@@ -103428,7 +103380,7 @@ async function runBatch(opts) {
103428
103380
  };
103429
103381
  }
103430
103382
  async function writeTaskError(paths, errorsDir, task, err, cls) {
103431
- const file = path31.join(errorsDir, `${sanitizeSection(task.section)}.error.json`);
103383
+ const file = path30.join(errorsDir, `${sanitizeSection(task.section)}.error.json`);
103432
103384
  const payload = {
103433
103385
  schemaVersion: 1,
103434
103386
  taskId: task.id,
@@ -103474,10 +103426,10 @@ async function persistRunMetadata(input) {
103474
103426
  accountsTotal: input.accounts.length,
103475
103427
  invocation: input.invocation
103476
103428
  };
103477
- await fs26.mkdir(paths.runDir, { recursive: true });
103478
- await fs26.mkdir(paths.stateDir, { recursive: true });
103479
- await fs26.mkdir(paths.resultsDir, { recursive: true });
103480
- await fs26.mkdir(paths.errorsDir, { recursive: true });
103429
+ await fs25.mkdir(paths.runDir, { recursive: true });
103430
+ await fs25.mkdir(paths.stateDir, { recursive: true });
103431
+ await fs25.mkdir(paths.resultsDir, { recursive: true });
103432
+ await fs25.mkdir(paths.errorsDir, { recursive: true });
103481
103433
  await writeRunManifest(paths, manifest);
103482
103434
  await writeAccounts(paths, input.accounts);
103483
103435
  return paths;
@@ -103520,8 +103472,8 @@ var init_batch_runner = __esm({
103520
103472
  shouldDowngrade(now = Date.now()) {
103521
103473
  if (this.window.length < this.opts.windowSize) return false;
103522
103474
  if (now - this.lastDowngradeAt < this.opts.cooldownMs) return false;
103523
- const fail3 = this.window.filter((s) => !s).length;
103524
- const rate = fail3 / this.window.length;
103475
+ const fail4 = this.window.filter((s) => !s).length;
103476
+ const rate = fail4 / this.window.length;
103525
103477
  if (rate >= this.opts.errorRateThreshold) {
103526
103478
  this.lastDowngradeAt = now;
103527
103479
  this.window.length = 0;
@@ -103540,7 +103492,7 @@ __export(google_analysis_batch_exports, {
103540
103492
  parseAccountIds: () => parseAccountIds,
103541
103493
  registerGoogleAnalysisBatchCommands: () => registerGoogleAnalysisBatchCommands
103542
103494
  });
103543
- import * as path32 from "path";
103495
+ import * as path31 from "path";
103544
103496
  import { performance as performance3 } from "perf_hooks";
103545
103497
  function parseSections(input) {
103546
103498
  if (!input || !input.trim()) return DEFAULT_SECTIONS;
@@ -104075,7 +104027,7 @@ var init_google_analysis_batch = __esm({
104075
104027
  });
104076
104028
 
104077
104029
  // src/commands/google-analysis/register-cli.ts
104078
- import * as path33 from "path";
104030
+ import * as path32 from "path";
104079
104031
  import { performance as performance4 } from "perf_hooks";
104080
104032
  import { Command } from "commander";
104081
104033
  function normalizeAnalysisDateOpts(opts) {
@@ -104201,7 +104153,7 @@ async function runAllSections(opts) {
104201
104153
  }
104202
104154
  const succeeded = results.filter((r) => r.ok).length;
104203
104155
  const failed = results.length - succeeded;
104204
- const absoluteSnapshotDir = path33.resolve(opts.jsonOut);
104156
+ const absoluteSnapshotDir = path32.resolve(opts.jsonOut);
104205
104157
  const summary = {
104206
104158
  kind: "siluzan-tso-google-analysis-snapshot-batch",
104207
104159
  absoluteSnapshotDir,
@@ -104449,8 +104401,8 @@ var init_google_analysis3 = __esm({
104449
104401
  // src/index.ts
104450
104402
  init_dist();
104451
104403
  init_dist();
104452
- import * as fs37 from "fs";
104453
- import * as path48 from "path";
104404
+ import * as fs36 from "fs";
104405
+ import * as path47 from "path";
104454
104406
  import { fileURLToPath as fileURLToPath12 } from "url";
104455
104407
  import { Command as Command6 } from "commander";
104456
104408
 
@@ -104937,8 +104889,8 @@ function deriveWebUrl(apiBaseUrl) {
104937
104889
  }
104938
104890
  var TSO_UMI_ROUTE_PREFIX = "/v3umijs/tso";
104939
104891
  function buildTsoPageWebUrl(webUrl, tsoSubRoute, extraQuery) {
104940
- const path49 = tsoSubRoute.replace(/^\/+/, "");
104941
- const umiPath = `${TSO_UMI_ROUTE_PREFIX}/${path49}`;
104892
+ const path48 = tsoSubRoute.replace(/^\/+/, "");
104893
+ const umiPath = `${TSO_UMI_ROUTE_PREFIX}/${path48}`;
104942
104894
  const q = new URLSearchParams({ tso: umiPath });
104943
104895
  if (extraQuery) {
104944
104896
  for (const [key, value] of Object.entries(extraQuery)) {
@@ -104946,7 +104898,7 @@ function buildTsoPageWebUrl(webUrl, tsoSubRoute, extraQuery) {
104946
104898
  if (v) q.set(key, v);
104947
104899
  }
104948
104900
  }
104949
- return `${webUrl.replace(/\/+$/, "")}/v3/foreign_trade/tso/${path49}?${q.toString()}`;
104901
+ return `${webUrl.replace(/\/+$/, "")}/v3/foreign_trade/tso/${path48}?${q.toString()}`;
104950
104902
  }
104951
104903
  function cmdConfigShow() {
104952
104904
  const shared = readSharedConfig();
@@ -105934,8 +105886,7 @@ var VALID_MEDIA_TYPES = [
105934
105886
  "TikTok",
105935
105887
  "Yandex",
105936
105888
  "MetaAd",
105937
- "BingV2",
105938
- "Kwai"
105889
+ "BingV2"
105939
105890
  ];
105940
105891
  function applyListAccountsSearchKeyword(params, keyword) {
105941
105892
  const kw = (keyword ?? "").trim();
@@ -105994,20 +105945,6 @@ var PLATFORM_CONFIG = {
105994
105945
  },
105995
105946
  responseType: "mas",
105996
105947
  idSearchParam: "mediaCustomerIds"
105997
- },
105998
- Kwai: {
105999
- path: "/query/media-account/SearchMediaAcountByCriteria",
106000
- pageParam: "pageNum",
106001
- fixedParams: {
106002
- // 与 Meta 同源接口,后端要求 MediaTypes(否则会 400:mediaTypes is required)
106003
- MediaTypes: "Kwai",
106004
- MediaType: "Kwai",
106005
- advStatus: "",
106006
- mediaAccountState: "Approved,Linked",
106007
- isForce: false
106008
- },
106009
- responseType: "mas",
106010
- idSearchParam: "mediaCustomerIds"
106011
105948
  }
106012
105949
  };
106013
105950
  function mergeTikTokAdList(items2, adList) {
@@ -106554,7 +106491,6 @@ async function runListAccounts(opts) {
106554
106491
  const isTikTok = opts.media === "TikTok";
106555
106492
  const isMetaAd = opts.media === "MetaAd";
106556
106493
  const isBingV2 = opts.media === "BingV2";
106557
- const isKwai = opts.media === "Kwai";
106558
106494
  const tableBorderOpts = opts.unicode ? { plain: false } : void 0;
106559
106495
  if (isGoogle) {
106560
106496
  printGoogleTable(items2, tableBorderOpts, exposeScopeActivated);
@@ -106564,7 +106500,7 @@ async function runListAccounts(opts) {
106564
106500
  printTikTokTable(items2, tableBorderOpts);
106565
106501
  } else if (isMetaAd) {
106566
106502
  printMetaTable(items2, tableBorderOpts);
106567
- } else if (isBingV2 || isKwai) {
106503
+ } else if (isBingV2) {
106568
106504
  printSpendMetricsAccountTable(items2, tableBorderOpts);
106569
106505
  } else {
106570
106506
  printDefaultTable(items2, opts.media, tableBorderOpts);
@@ -106591,10 +106527,10 @@ async function runListAccounts(opts) {
106591
106527
  // src/commands/list-accounts/register.ts
106592
106528
  function register6(program2) {
106593
106529
  program2.command("list-accounts").description(
106594
- "\u67E5\u8BE2\u5E7F\u544A\u8D26\u6237\u5217\u8868\u3002\u5F53\u524D\u8D26\u6237\u5728 TSO \u5E73\u53F0\u5173\u8054\u7684\u5168\u90E8\u5E7F\u544A\u8D26\u6237\uFF08Google/TikTok/Yandex/MetaAd/BingV2/Kwai \u7B49\u5A92\u4F53\uFF09"
106530
+ "\u67E5\u8BE2\u5E7F\u544A\u8D26\u6237\u5217\u8868\u3002\u5F53\u524D\u8D26\u6237\u5728 TSO \u5E73\u53F0\u5173\u8054\u7684\u5168\u90E8\u5E7F\u544A\u8D26\u6237\uFF08Google/TikTok/Yandex/MetaAd/BingV2 \u7B49\u5A92\u4F53\uFF09"
106595
106531
  ).option(
106596
106532
  "-m, --media <type>",
106597
- "\u5A92\u4F53\u7C7B\u578B\uFF1AGoogle | TikTok | Yandex | MetaAd | BingV2 | Kwai\uFF08\u7559\u7A7A\u5219\u67E5\u8BE2\u5168\u90E8\u5A92\u4F53\uFF09"
106533
+ "\u5A92\u4F53\u7C7B\u578B\uFF1AGoogle | TikTok | Yandex | MetaAd | BingV2\uFF08\u7559\u7A7A\u5219\u67E5\u8BE2\u5168\u90E8\u5A92\u4F53\uFF09"
106598
106534
  ).option("-k, --keyword <text>", "\u5173\u952E\u5B57\uFF08\u516C\u53F8/\u8D26\u6237\u540D/\u8D26\u6237ID \u6A21\u7CCA\u5339\u914D\uFF09").option(
106599
106535
  "-s, --status <status>",
106600
106536
  "\u8D26\u6237\u72B6\u6001\uFF1Anormal\uFF08\u6B63\u5E38\uFF09| invalid\uFF08\u5931\u6548\uFF09| all\uFF08\u5168\u90E8\uFF0C\u9ED8\u8BA4\uFF09",
@@ -106629,7 +106565,7 @@ function register6(program2) {
106629
106565
  init_auth();
106630
106566
  init_cli_json_snapshot();
106631
106567
  init_cli_table();
106632
- var VALID_MEDIA = ["Google", "TikTok", "Yandex", "MetaAd", "BingV2", "Kwai"];
106568
+ var VALID_MEDIA = ["Google", "TikTok", "Yandex", "MetaAd", "BingV2"];
106633
106569
  async function runAccountActiveBills(opts) {
106634
106570
  if (!VALID_MEDIA.includes(opts.media)) {
106635
106571
  console.error(
@@ -106717,7 +106653,7 @@ function register7(program2) {
106717
106653
  "\u67E5\u8BE2\u8D26\u6237\u6FC0\u6D3B/\u5145\u503C\u8D26\u5355\u660E\u7EC6\uFF08GET TSO /AccountActiveBills/{\u5A92\u4F53}/{entityId}\uFF1BentityId \u6765\u81EA list-accounts --json-out ./snap\uFF09"
106718
106654
  ).requiredOption(
106719
106655
  "-m, --media <type>",
106720
- "\u5A92\u4F53\u7C7B\u578B\uFF1AGoogle | TikTok | Yandex | MetaAd | BingV2 | Kwai"
106656
+ "\u5A92\u4F53\u7C7B\u578B\uFF1AGoogle | TikTok | Yandex | MetaAd | BingV2"
106721
106657
  ).requiredOption(
106722
106658
  "--id <entityId>",
106723
106659
  "\u8D26\u6237 entityId\uFF08list-accounts --json-out ./snap-out \u4E2D\u6BCF\u6761 ma.entityId\uFF0C\u975E mediaCustomerId\uFF09"
@@ -106745,7 +106681,7 @@ init_cli_table();
106745
106681
  init_balance();
106746
106682
  init_media_account_lookup();
106747
106683
  init_media_customer_id();
106748
- var VALID_MEDIA_TYPES2 = ["Google", "TikTok", "Yandex", "MetaAd", "BingV2", "Kwai"];
106684
+ var VALID_MEDIA_TYPES2 = ["Google", "TikTok", "Yandex", "MetaAd", "BingV2"];
106749
106685
  async function runBalance(opts) {
106750
106686
  const config = loadConfig(opts.token);
106751
106687
  if (!VALID_MEDIA_TYPES2.includes(opts.media)) {
@@ -106869,7 +106805,7 @@ ${media} \u8D26\u6237\u4F59\u989D\uFF08\u7B2C 1 \u9875\uFF0C\u672C\u9875 ${out.l
106869
106805
  function register8(program2) {
106870
106806
  program2.command("balance").description("\u67E5\u8BE2\u5E7F\u544A\u8D26\u6237\u5B9E\u65F6\u4F59\u989D").requiredOption(
106871
106807
  "-m, --media <type>",
106872
- "\u5A92\u4F53\u7C7B\u578B\uFF1AGoogle | TikTok | Yandex | MetaAd | BingV2 | Kwai"
106808
+ "\u5A92\u4F53\u7C7B\u578B\uFF1AGoogle | TikTok | Yandex | MetaAd | BingV2"
106873
106809
  ).requiredOption(
106874
106810
  "-a, --accounts <ids>",
106875
106811
  "\u8D26\u6237 mediaCustomerId\uFF08list-accounts \u7684 ma.mediaCustomerId\uFF1BYandex \u5F62\u5982 porg-\u2026\uFF1B\u7981\u6B62 entityId/UUID\uFF09\uFF0C\u591A\u4E2A\u7528\u9017\u53F7\u5206\u9694"
@@ -106938,18 +106874,6 @@ var SCAN_PLATFORM_CONFIG = {
106938
106874
  },
106939
106875
  responseType: "mas"
106940
106876
  },
106941
- Kwai: {
106942
- path: "/query/media-account/SearchMediaAcountByCriteria",
106943
- pageParam: "pageNum",
106944
- fixedParams: {
106945
- MediaTypes: "Kwai",
106946
- MediaType: "Kwai",
106947
- advStatus: "",
106948
- mediaAccountState: "Approved,Linked",
106949
- isForce: false
106950
- },
106951
- responseType: "mas"
106952
- },
106953
106877
  MetaAd: {
106954
106878
  path: "/query/media-account/SearchMediaAcountByCriteria",
106955
106879
  pageParam: "pageNum",
@@ -107378,7 +107302,7 @@ function register9(program2) {
107378
107302
  "\u4E00\u952E\u626B\u63CF\u67D0\u5A92\u4F53\u4E0B\u6709\u6548\u8D26\u6237\u7684\u4F59\u989D\u4E0E\u65E5\u5747\u6D88\u8017\uFF0C\u8FD4\u56DE\u5168\u90E8\u5DF2\u68C0\u67E5\u8D26\u6237\uFF1B\u7528 hitReason \u6807\u8BB0\u7EED\u822A/\u4F59\u989D\u4E0D\u8DB3\u7684\u9884\u8B66\u884C\u3002\u66FF\u4EE3\u5FAA\u73AF\u8C03\u7528 balance \u7684\u4F20\u7EDF\u505A\u6CD5\u3002"
107379
107303
  ).requiredOption(
107380
107304
  "-m, --media <type>",
107381
- "\u5A92\u4F53\u7C7B\u578B\uFF1AGoogle | TikTok | Yandex | MetaAd | BingV2 | Kwai"
107305
+ "\u5A92\u4F53\u7C7B\u578B\uFF1AGoogle | TikTok | Yandex | MetaAd | BingV2"
107382
107306
  ).option(
107383
107307
  "-a, --accounts <ids>",
107384
107308
  "\u6307\u5B9A mediaCustomerId\uFF08\u9017\u53F7\u5206\u9694\uFF09\uFF1B\u8DF3\u8FC7\u6E05\u5355\u7FFB\u9875\uFF0C\u5BF9\u8FD9\u4E9B ID \u62C9\u4F59\u989D+\u6D88\u8017\u540E\u5168\u90E8\u8F93\u51FA"
@@ -108080,7 +108004,7 @@ init_balance();
108080
108004
  init_daily_metrics_range();
108081
108005
  init_media_account_lookup();
108082
108006
  init_media_customer_id();
108083
- var VALID_MEDIA_TYPES3 = ["Google", "TikTok", "Yandex", "MetaAd", "BingV2", "Kwai"];
108007
+ var VALID_MEDIA_TYPES3 = ["Google", "TikTok", "Yandex", "MetaAd", "BingV2"];
108084
108008
  var MAX_BY_DAY_SPAN = 366;
108085
108009
  var DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
108086
108010
  function defaultDateRange2(now = /* @__PURE__ */ new Date()) {
@@ -108317,7 +108241,7 @@ function register12(program2) {
108317
108241
  "\u67E5\u8BE2\u5E7F\u544A\u6D88\u8017\u3001\u70B9\u51FB\u3001\u8F6C\u5316\u7B49\u6295\u653E\u6570\u636E\uFF08\u9ED8\u8BA4\u8FD1 7 \u5929\u533A\u95F4\u5408\u8BA1\uFF0C\u4E0D\u542B\u4ECA\u5929\uFF0C\u65E5\u5386\u6309 UTC+8\uFF1B\u8981\u6309\u65E5\u660E\u7EC6\u52A0 --by-day\uFF09"
108318
108242
  ).requiredOption(
108319
108243
  "-m, --media <type>",
108320
- "\u5A92\u4F53\u7C7B\u578B\uFF1AGoogle | TikTok | Yandex | MetaAd | BingV2 | Kwai"
108244
+ "\u5A92\u4F53\u7C7B\u578B\uFF1AGoogle | TikTok | Yandex | MetaAd | BingV2"
108321
108245
  ).option(
108322
108246
  "-a, --accounts <ids>",
108323
108247
  "\u8D26\u6237 mediaCustomerId\uFF08list-accounts \u7684 ma.mediaCustomerId\uFF1BYandex \u5F62\u5982 porg-\u2026\uFF1B\u7981\u6B62 entityId/UUID\uFF09\uFF0C\u591A\u4E2A\u7528\u9017\u53F7\u5206\u9694\uFF08\u5FC5\u586B\uFF09"
@@ -108349,7 +108273,7 @@ function register12(program2) {
108349
108273
  init_auth();
108350
108274
  init_cli_json_snapshot();
108351
108275
  init_cli_table();
108352
- var VALID_MEDIA_TYPES4 = ["Google", "TikTok", "Yandex", "MetaAd", "BingV2", "Kwai"];
108276
+ var VALID_MEDIA_TYPES4 = ["Google", "TikTok", "Yandex", "MetaAd", "BingV2"];
108353
108277
  async function runAccountHistory(opts) {
108354
108278
  const config = loadConfig(opts.token);
108355
108279
  if (opts.media && !VALID_MEDIA_TYPES4.includes(opts.media)) {
@@ -108432,7 +108356,7 @@ async function runAccountHistory(opts) {
108432
108356
  console.log();
108433
108357
  }
108434
108358
  function register13(program2) {
108435
- program2.command("account-history").description("\u67E5\u8BE2\u5F00\u6237\u7533\u8BF7\u5386\u53F2\u8BB0\u5F55").option("-m, --media <type>", "\u5A92\u4F53\u7C7B\u578B\uFF1AGoogle | TikTok | MetaAd | BingV2 | Kwai").option("-s, --status <status>", "\u7533\u8BF7\u72B6\u6001\u5173\u952E\u5B57").option("-k, --keyword <text>", "\u641C\u7D22\u5173\u952E\u5B57\uFF08\u8D26\u6237\u540D/ID\uFF09").option("--start <date>", "\u5F00\u59CB\u65E5\u671F YYYY-MM-DD").option("--end <date>", "\u7ED3\u675F\u65E5\u671F YYYY-MM-DD").option("-p, --page <n>", "\u9875\u7801", parseInt).option("--page-size <n>", "\u6BCF\u9875\u6570\u91CF\uFF08\u9ED8\u8BA4 20\uFF09", parseInt).option("-t, --token <token>", "Auth Token").option(
108359
+ program2.command("account-history").description("\u67E5\u8BE2\u5F00\u6237\u7533\u8BF7\u5386\u53F2\u8BB0\u5F55").option("-m, --media <type>", "\u5A92\u4F53\u7C7B\u578B\uFF1AGoogle | TikTok | Yandex | MetaAd | BingV2").option("-s, --status <status>", "\u7533\u8BF7\u72B6\u6001\u5173\u952E\u5B57").option("-k, --keyword <text>", "\u641C\u7D22\u5173\u952E\u5B57\uFF08\u8D26\u6237\u540D/ID\uFF09").option("--start <date>", "\u5F00\u59CB\u65E5\u671F YYYY-MM-DD").option("--end <date>", "\u7ED3\u675F\u65E5\u671F YYYY-MM-DD").option("-p, --page <n>", "\u9875\u7801", parseInt).option("--page-size <n>", "\u6BCF\u9875\u6570\u91CF\uFF08\u9ED8\u8BA4 20\uFF09", parseInt).option("-t, --token <token>", "Auth Token").option(
108436
108360
  "--json-out <path>",
108437
108361
  "\u843D\u76D8\uFF08\u76EE\u5F55\u6216 *.json \u6587\u4EF6\u8DEF\u5F84\uFF09\u5E76\u66F4\u65B0 cli-manifest[-<\u67E5\u8BE2id>].json\uFF1B\u76EE\u5F55\u6A21\u5F0F\u6587\u4EF6\u540D\u4E3A `<section>[-<\u67E5\u8BE2id>].json`\uFF1Bstdout \u4E00\u884C\u6458\u8981 JSON\uFF0C\u542B outlineFile\uFF08TS \u5F0F\u7C7B\u578B\u5728 `*.outline.txt`\uFF09",
108438
108362
  void 0
@@ -108460,8 +108384,7 @@ var VALID_MEDIA_TYPES5 = [
108460
108384
  "TikTok",
108461
108385
  "Yandex",
108462
108386
  "MetaAd",
108463
- "BingV2",
108464
- "Kwai"
108387
+ "BingV2"
108465
108388
  ];
108466
108389
  var REPORT_PUSH_MEDIA = /* @__PURE__ */ new Set(["Google", "TikTok"]);
108467
108390
  function assertReportPushMedia(media) {
@@ -112449,7 +112372,7 @@ function cloneKeywordBlockShell(block) {
112449
112372
  delete shell["matchTypeV2"];
112450
112373
  return shell;
112451
112374
  }
112452
- function splitKeywordsForBatchJobBlockIfMixed(block, path49, warnings) {
112375
+ function splitKeywordsForBatchJobBlockIfMixed(block, path48, warnings) {
112453
112376
  const declaredUi = matchTypeV2ToUi(readBlockMatchTypeRaw(block));
112454
112377
  const entries = collectKeywordEntriesFromBlock(block);
112455
112378
  if (entries.length === 0) return [block];
@@ -112468,7 +112391,7 @@ function splitKeywordsForBatchJobBlockIfMixed(block, path49, warnings) {
112468
112391
  (ui) => matchTypeUiToV2(ui)
112469
112392
  );
112470
112393
  warnings.push(
112471
- `${path49} \u542B\u591A\u79CD\u5339\u914D\u7C7B\u578B\uFF0C\u5DF2\u81EA\u52A8\u62C6\u5206\u4E3A ${groups.size} \u4E2A KeywordsForBatchJob \u5757\uFF08${labels.join("\u3001")}\uFF09`
112394
+ `${path48} \u542B\u591A\u79CD\u5339\u914D\u7C7B\u578B\uFF0C\u5DF2\u81EA\u52A8\u62C6\u5206\u4E3A ${groups.size} \u4E2A KeywordsForBatchJob \u5757\uFF08${labels.join("\u3001")}\uFF09`
112472
112395
  );
112473
112396
  const shell = cloneKeywordBlockShell(block);
112474
112397
  const splitBlocks = [];
@@ -112488,16 +112411,16 @@ function splitKeywordsForBatchJobBlockIfMixed(block, path49, warnings) {
112488
112411
  }
112489
112412
  return splitBlocks;
112490
112413
  }
112491
- function validateKeywordCore(core, path49, errors, lengthViolations) {
112414
+ function validateKeywordCore(core, path48, errors, lengthViolations) {
112492
112415
  const trimmed = core.trim();
112493
112416
  if (!trimmed) {
112494
- errors.push(`${path49} \u5173\u952E\u8BCD\u8BCD\u5E72\u4E0D\u80FD\u4E3A\u7A7A`);
112417
+ errors.push(`${path48} \u5173\u952E\u8BCD\u8BCD\u5E72\u4E0D\u80FD\u4E3A\u7A7A`);
112495
112418
  return false;
112496
112419
  }
112497
112420
  if (trimmed.length > GOOGLE_KEYWORD_MAX_CORE_LENGTH) {
112498
112421
  if (lengthViolations) {
112499
112422
  pushLengthViolation(lengthViolations, {
112500
- path: path49,
112423
+ path: path48,
112501
112424
  field: "KeywordText",
112502
112425
  kind: "keyword_core",
112503
112426
  limit: GOOGLE_KEYWORD_MAX_CORE_LENGTH,
@@ -112507,13 +112430,13 @@ function validateKeywordCore(core, path49, errors, lengthViolations) {
112507
112430
  });
112508
112431
  }
112509
112432
  errors.push(
112510
- `${path49} \u5173\u952E\u8BCD\u8BCD\u5E72\u8D85\u8FC7 ${GOOGLE_KEYWORD_MAX_CORE_LENGTH} \u5B57\u7B26\uFF08\u5F53\u524D ${trimmed.length}\uFF09\uFF1A"${trimmed}"`
112433
+ `${path48} \u5173\u952E\u8BCD\u8BCD\u5E72\u8D85\u8FC7 ${GOOGLE_KEYWORD_MAX_CORE_LENGTH} \u5B57\u7B26\uFF08\u5F53\u524D ${trimmed.length}\uFF09\uFF1A"${trimmed}"`
112511
112434
  );
112512
112435
  return false;
112513
112436
  }
112514
112437
  if (!VALID_CORE_REGEX.test(trimmed)) {
112515
112438
  errors.push(
112516
- `${path49} \u542B Google \u4E0D\u5141\u8BB8\u7684\u5B57\u7B26\uFF08\u8BCD\u5E72\u4EC5\u5141\u8BB8\u5B57\u6BCD/\u6570\u5B57/\u7A7A\u683C/\u8FDE\u5B57\u7B26/\u53E5\u70B9\uFF09\uFF1A"${trimmed.slice(0, 40)}${trimmed.length > 40 ? "\u2026" : ""}"`
112439
+ `${path48} \u542B Google \u4E0D\u5141\u8BB8\u7684\u5B57\u7B26\uFF08\u8BCD\u5E72\u4EC5\u5141\u8BB8\u5B57\u6BCD/\u6570\u5B57/\u7A7A\u683C/\u8FDE\u5B57\u7B26/\u53E5\u70B9\uFF09\uFF1A"${trimmed.slice(0, 40)}${trimmed.length > 40 ? "\u2026" : ""}"`
112517
112440
  );
112518
112441
  return false;
112519
112442
  }
@@ -112570,24 +112493,24 @@ function canonicalizeKeywordBatchBlock(block, resolvedMatchV2, normalizedTexts,
112570
112493
  }
112571
112494
  }
112572
112495
  }
112573
- function pushKeywordAutoFixWarning(warnings, path49, fieldLabel, trimmedRaw, formatted, declaredUi, beforeUi, matchType, inferredMatchType) {
112496
+ function pushKeywordAutoFixWarning(warnings, path48, fieldLabel, trimmedRaw, formatted, declaredUi, beforeUi, matchType, inferredMatchType) {
112574
112497
  if (inferredMatchType) {
112575
112498
  warnings.push(
112576
- `${path49}.${fieldLabel} \u672A\u6307\u5B9A MatchTypeV2\uFF0C\u5DF2\u6309\u8BCD\u9762\u63A8\u65AD\u4E3A ${matchTypeUiToV2(matchType)}`
112499
+ `${path48}.${fieldLabel} \u672A\u6307\u5B9A MatchTypeV2\uFF0C\u5DF2\u6309\u8BCD\u9762\u63A8\u65AD\u4E3A ${matchTypeUiToV2(matchType)}`
112577
112500
  );
112578
112501
  return;
112579
112502
  }
112580
112503
  if (declaredUi && beforeUi !== declaredUi) {
112581
112504
  warnings.push(
112582
- `${path49}.${fieldLabel} MatchTypeV2=${matchTypeUiToV2(declaredUi)} \u4E0E\u8BCD\u9762\u4E0D\u4E00\u81F4\uFF0C\u5DF2\u81EA\u52A8\u4FEE\u590D\u4E3A\uFF1A${formatted}`
112505
+ `${path48}.${fieldLabel} MatchTypeV2=${matchTypeUiToV2(declaredUi)} \u4E0E\u8BCD\u9762\u4E0D\u4E00\u81F4\uFF0C\u5DF2\u81EA\u52A8\u4FEE\u590D\u4E3A\uFF1A${formatted}`
112583
112506
  );
112584
112507
  return;
112585
112508
  }
112586
112509
  if (formatted !== trimmedRaw) {
112587
- warnings.push(`${path49}.${fieldLabel} \u5DF2\u81EA\u52A8\u4FEE\u590D\u8BCD\u9762\uFF1A${trimmedRaw} \u2192 ${formatted}`);
112510
+ warnings.push(`${path48}.${fieldLabel} \u5DF2\u81EA\u52A8\u4FEE\u590D\u8BCD\u9762\uFF1A${trimmedRaw} \u2192 ${formatted}`);
112588
112511
  }
112589
112512
  }
112590
- function normalizeKeywordTextList(texts, matchTypeRaw, path49, fieldLabel, errors, warnings, lengthViolations) {
112513
+ function normalizeKeywordTextList(texts, matchTypeRaw, path48, fieldLabel, errors, warnings, lengthViolations) {
112591
112514
  const declaredUi = matchTypeV2ToUi(matchTypeRaw);
112592
112515
  const normalized = [];
112593
112516
  const seen = /* @__PURE__ */ new Set();
@@ -112595,7 +112518,7 @@ function normalizeKeywordTextList(texts, matchTypeRaw, path49, fieldLabel, error
112595
112518
  for (let k = 0; k < texts.length; k++) {
112596
112519
  const raw = texts[k];
112597
112520
  if (typeof raw !== "string" || !raw.trim()) {
112598
- errors.push(`${path49}.${fieldLabel}[${k}] \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32`);
112521
+ errors.push(`${path48}.${fieldLabel}[${k}] \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32`);
112599
112522
  continue;
112600
112523
  }
112601
112524
  const trimmedRaw = collapseDuplicateSpacesInKeywordText(raw.trim());
@@ -112606,7 +112529,7 @@ function normalizeKeywordTextList(texts, matchTypeRaw, path49, fieldLabel, error
112606
112529
  );
112607
112530
  pushKeywordAutoFixWarning(
112608
112531
  warnings,
112609
- path49,
112532
+ path48,
112610
112533
  fieldLabel,
112611
112534
  trimmedRaw,
112612
112535
  formatted,
@@ -112616,11 +112539,11 @@ function normalizeKeywordTextList(texts, matchTypeRaw, path49, fieldLabel, error
112616
112539
  inferredMatchType
112617
112540
  );
112618
112541
  const core = unwrapKeywordDisplayTextForEdit(formatted);
112619
- if (!validateKeywordCore(core, `${path49}.${fieldLabel}[${k}]`, errors, lengthViolations))
112542
+ if (!validateKeywordCore(core, `${path48}.${fieldLabel}[${k}]`, errors, lengthViolations))
112620
112543
  continue;
112621
112544
  const dedupeKey = `${matchTypeUiToV2(matchType)}:${core.toLowerCase()}`;
112622
112545
  if (seen.has(dedupeKey)) {
112623
- warnings.push(`${path49}.${fieldLabel}[${k}] \u4E0E\u540C\u7EC4\u91CD\u590D\uFF0C\u5DF2\u8DF3\u8FC7\uFF1A${formatted}`);
112546
+ warnings.push(`${path48}.${fieldLabel}[${k}] \u4E0E\u540C\u7EC4\u91CD\u590D\uFF0C\u5DF2\u8DF3\u8FC7\uFF1A${formatted}`);
112624
112547
  continue;
112625
112548
  }
112626
112549
  seen.add(dedupeKey);
@@ -112629,12 +112552,12 @@ function normalizeKeywordTextList(texts, matchTypeRaw, path49, fieldLabel, error
112629
112552
  }
112630
112553
  return { normalized, resolvedUi };
112631
112554
  }
112632
- function normalizeKeywordsForBatchJobBlock(block, path49, errors, warnings, lengthViolations) {
112555
+ function normalizeKeywordsForBatchJobBlock(block, path48, errors, warnings, lengthViolations) {
112633
112556
  const matchTypeRaw = readBlockMatchTypeRaw(block);
112634
112557
  const declaredUi = matchTypeV2ToUi(matchTypeRaw);
112635
112558
  if (matchTypeRaw !== void 0 && declaredUi === null) {
112636
112559
  errors.push(
112637
- `${path49}.MatchTypeV2 \u65E0\u6548\uFF08${String(matchTypeRaw)}\uFF09\uFF0C\u5408\u6CD5\u503C\uFF1ABROAD | PHRASE | EXACT`
112560
+ `${path48}.MatchTypeV2 \u65E0\u6548\uFF08${String(matchTypeRaw)}\uFF09\uFF0C\u5408\u6CD5\u503C\uFF1ABROAD | PHRASE | EXACT`
112638
112561
  );
112639
112562
  return;
112640
112563
  }
@@ -112649,7 +112572,7 @@ function normalizeKeywordsForBatchJobBlock(block, path49, errors, warnings, leng
112649
112572
  const result = normalizeKeywordTextList(
112650
112573
  texts,
112651
112574
  matchTypeRaw,
112652
- path49,
112575
+ path48,
112653
112576
  "KeywordText",
112654
112577
  errors,
112655
112578
  warnings,
@@ -112658,7 +112581,7 @@ function normalizeKeywordsForBatchJobBlock(block, path49, errors, warnings, leng
112658
112581
  normalizedTexts = result.normalized;
112659
112582
  if (result.resolvedUi) resolvedUi = result.resolvedUi;
112660
112583
  if (normalizedTexts.length === 0 && texts.length > 0) {
112661
- errors.push(`${path49}.KeywordText \u7ECF\u6821\u9A8C\u540E\u65E0\u6709\u6548\u5173\u952E\u8BCD\uFF0C\u8BF7\u4FEE\u6B63\u8BCD\u9762\u6216 MatchTypeV2`);
112584
+ errors.push(`${path48}.KeywordText \u7ECF\u6821\u9A8C\u540E\u65E0\u6709\u6548\u5173\u952E\u8BCD\uFF0C\u8BF7\u4FEE\u6B63\u8BCD\u9762\u6216 MatchTypeV2`);
112662
112585
  }
112663
112586
  }
112664
112587
  if (hasItems && items2) {
@@ -112666,12 +112589,12 @@ function normalizeKeywordsForBatchJobBlock(block, path49, errors, warnings, leng
112666
112589
  for (let k = 0; k < items2.length; k++) {
112667
112590
  const item = items2[k];
112668
112591
  if (!item || typeof item !== "object") {
112669
- errors.push(`${path49}.Items[${k}] \u5FC5\u987B\u662F\u5BF9\u8C61`);
112592
+ errors.push(`${path48}.Items[${k}] \u5FC5\u987B\u662F\u5BF9\u8C61`);
112670
112593
  continue;
112671
112594
  }
112672
112595
  const raw = readItemText(item);
112673
112596
  if (raw === null || !raw.trim()) {
112674
- errors.push(`${path49}.Items[${k}].Text \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32`);
112597
+ errors.push(`${path48}.Items[${k}].Text \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32`);
112675
112598
  continue;
112676
112599
  }
112677
112600
  const trimmedRaw = collapseDuplicateSpacesInKeywordText(raw.trim());
@@ -112682,7 +112605,7 @@ function normalizeKeywordsForBatchJobBlock(block, path49, errors, warnings, leng
112682
112605
  );
112683
112606
  pushKeywordAutoFixWarning(
112684
112607
  warnings,
112685
- path49,
112608
+ path48,
112686
112609
  `Items[${k}].Text`,
112687
112610
  trimmedRaw,
112688
112611
  formatted,
@@ -112692,11 +112615,11 @@ function normalizeKeywordsForBatchJobBlock(block, path49, errors, warnings, leng
112692
112615
  inferredMatchType
112693
112616
  );
112694
112617
  const core = unwrapKeywordDisplayTextForEdit(formatted);
112695
- if (!validateKeywordCore(core, `${path49}.Items[${k}].Text`, errors, lengthViolations))
112618
+ if (!validateKeywordCore(core, `${path48}.Items[${k}].Text`, errors, lengthViolations))
112696
112619
  continue;
112697
112620
  const dedupeKey = `${matchTypeUiToV2(matchType)}:${core.toLowerCase()}`;
112698
112621
  if (seen.has(dedupeKey)) {
112699
- warnings.push(`${path49}.Items[${k}].Text \u4E0E\u540C\u7EC4\u91CD\u590D\uFF0C\u5DF2\u8DF3\u8FC7\uFF1A${formatted}`);
112622
+ warnings.push(`${path48}.Items[${k}].Text \u4E0E\u540C\u7EC4\u91CD\u590D\uFF0C\u5DF2\u8DF3\u8FC7\uFF1A${formatted}`);
112700
112623
  continue;
112701
112624
  }
112702
112625
  seen.add(dedupeKey);
@@ -112841,16 +112764,16 @@ function warnIfNegativeKeywordsInPositiveKeywords(campaign, warnings) {
112841
112764
  const raw = texts[ki];
112842
112765
  if (typeof raw !== "string" || !raw.trim()) continue;
112843
112766
  const core = normalizeKeywordCoreForNegativeCheck(raw);
112844
- const path49 = `campaign.AdGroupsForBatchJob[${gi}].KeywordsForBatchJob[${bi}].KeywordText[${ki}]`;
112767
+ const path48 = `campaign.AdGroupsForBatchJob[${gi}].KeywordsForBatchJob[${bi}].KeywordText[${ki}]`;
112845
112768
  if (plannedNegCores.has(core)) {
112846
112769
  warnings.push(
112847
- `${path49} \u8BCD\u9762\u300C${raw}\u300D\u5DF2\u51FA\u73B0\u5728 campaign.NegativeKeywordsForBatchJob\uFF0C\u4E0D\u5E94\u91CD\u590D\u5199\u5165\u6B63\u5411 KeywordsForBatchJob\uFF1B\u5426\u8BCD\u53EA\u653E NegativeKeywordsForBatchJob`
112770
+ `${path48} \u8BCD\u9762\u300C${raw}\u300D\u5DF2\u51FA\u73B0\u5728 campaign.NegativeKeywordsForBatchJob\uFF0C\u4E0D\u5E94\u91CD\u590D\u5199\u5165\u6B63\u5411 KeywordsForBatchJob\uFF1B\u5426\u8BCD\u53EA\u653E NegativeKeywordsForBatchJob`
112848
112771
  );
112849
112772
  continue;
112850
112773
  }
112851
112774
  if (looksLikeStandaloneNegativeKeyword(core)) {
112852
112775
  warnings.push(
112853
- `${path49} \u8BCD\u9762\u300C${raw}\u300D\u7591\u4F3C\u5426\u5B9A\u5173\u952E\u8BCD\uFF08\u5E38\u89C1\u5426\u8BCD\u8BCD\u6839\uFF09\uFF0C\u5E94\u5199\u5165 campaign.NegativeKeywordsForBatchJob\uFF08MatchTypeV2: BROAD\uFF09\uFF0C\u52FF\u653E\u5165 KeywordsForBatchJob`
112776
+ `${path48} \u8BCD\u9762\u300C${raw}\u300D\u7591\u4F3C\u5426\u5B9A\u5173\u952E\u8BCD\uFF08\u5E38\u89C1\u5426\u8BCD\u8BCD\u6839\uFF09\uFF0C\u5E94\u5199\u5165 campaign.NegativeKeywordsForBatchJob\uFF08MatchTypeV2: BROAD\uFF09\uFF0C\u52FF\u653E\u5165 KeywordsForBatchJob`
112854
112777
  );
112855
112778
  }
112856
112779
  }
@@ -116478,13 +116401,13 @@ function compareCampaignCreateToLive(cfg, campaignId, live, meta) {
116478
116401
  for (let ki = 0; ki < texts.length; ki++) {
116479
116402
  const t = texts[ki];
116480
116403
  if (typeof t !== "string" || !t.trim()) continue;
116481
- const path49 = `${groupPath}.KeywordsForBatchJob[${bi}].KeywordText[${ki}]`;
116404
+ const path48 = `${groupPath}.KeywordsForBatchJob[${bi}].KeywordText[${ki}]`;
116482
116405
  const key = keywordKey(t, matchTypeV2);
116483
116406
  const plannedContent = `\u8BCD\u9762: ${t} | \u5339\u914D: ${matchTypeV2}`;
116484
116407
  if (groupAbsent) {
116485
116408
  pushItem(items2, {
116486
116409
  layer: "keyword",
116487
- path: path49,
116410
+ path: path48,
116488
116411
  adGroupName: groupName,
116489
116412
  plannedContent,
116490
116413
  status: "skipped",
@@ -116496,7 +116419,7 @@ function compareCampaignCreateToLive(cfg, campaignId, live, meta) {
116496
116419
  if (!liveKwKeys.has(key)) {
116497
116420
  pushItem(items2, {
116498
116421
  layer: "keyword",
116499
- path: path49,
116422
+ path: path48,
116500
116423
  adGroupName: groupName,
116501
116424
  plannedContent,
116502
116425
  status: "missing",
@@ -116506,7 +116429,7 @@ function compareCampaignCreateToLive(cfg, campaignId, live, meta) {
116506
116429
  } else {
116507
116430
  pushItem(items2, {
116508
116431
  layer: "keyword",
116509
- path: path49,
116432
+ path: path48,
116510
116433
  adGroupName: groupName,
116511
116434
  plannedContent,
116512
116435
  status: "ok",
@@ -116531,14 +116454,14 @@ function compareCampaignCreateToLive(cfg, campaignId, live, meta) {
116531
116454
  for (let ai = 0; ai < ads.length; ai++) {
116532
116455
  const ad = asRecord3(ads[ai]);
116533
116456
  if (!ad) continue;
116534
- const path49 = `${groupPath}.AdsForBatchJob[${ai}]`;
116457
+ const path48 = `${groupPath}.AdsForBatchJob[${ai}]`;
116535
116458
  const primary = pickString2(ad["headlinePart1"], ad["AdTitle"]);
116536
116459
  const finalUrl = pickString2(ad["Finalurl"], ad["DestinationUrl"], ad["finalUrl"]);
116537
116460
  const rsaAssets = listPlannedRsaAssets(ad, groupPath, ai, groupName);
116538
116461
  if (groupAbsent) {
116539
116462
  pushItem(items2, {
116540
116463
  layer: "ad",
116541
- path: path49,
116464
+ path: path48,
116542
116465
  adGroupName: groupName,
116543
116466
  plannedContent: primary ? `RSA \u9996\u6807\u9898: ${primary}${finalUrl ? ` | \u843D\u5730\u9875: ${finalUrl}` : ""}` : `AdsForBatchJob[${ai}]\uFF08\u7F3A\u5C11 headlinePart1\uFF09`,
116544
116467
  status: "skipped",
@@ -116562,7 +116485,7 @@ function compareCampaignCreateToLive(cfg, campaignId, live, meta) {
116562
116485
  if (!primary) {
116563
116486
  pushItem(items2, {
116564
116487
  layer: "ad",
116565
- path: path49,
116488
+ path: path48,
116566
116489
  adGroupName: groupName,
116567
116490
  plannedContent: `AdsForBatchJob[${ai}]\uFF08\u7F3A\u5C11 headlinePart1\uFF0C\u65E0\u6CD5\u6BD4\u5BF9\u6574\u6761 RSA\uFF09`,
116568
116491
  status: "missing",
@@ -116588,7 +116511,7 @@ function compareCampaignCreateToLive(cfg, campaignId, live, meta) {
116588
116511
  const rsaFound = liveAdsInGroup.some((la) => liveAdHasHeadline(la, primary));
116589
116512
  pushItem(items2, {
116590
116513
  layer: "ad",
116591
- path: path49,
116514
+ path: path48,
116592
116515
  adGroupName: groupName,
116593
116516
  plannedContent: `RSA \u9996\u6807\u9898: ${primary}${finalUrl ? ` | \u843D\u5730\u9875: ${finalUrl}` : ""}`,
116594
116517
  status: rsaFound ? "ok" : "missing",
@@ -116654,11 +116577,11 @@ function compareCampaignCreateToLive(cfg, campaignId, live, meta) {
116654
116577
  for (let ei = 0; ei < extBlocks.length; ei++) {
116655
116578
  const ext = asRecord3(extBlocks[ei]);
116656
116579
  const plannedContent = formatExtensionPlanned(ext);
116657
- const path49 = `campaign.ExtensionsForBatchJob[${ei}]`;
116580
+ const path48 = `campaign.ExtensionsForBatchJob[${ei}]`;
116658
116581
  if (campaignMissing) {
116659
116582
  pushItem(items2, {
116660
116583
  layer: "extension",
116661
- path: path49,
116584
+ path: path48,
116662
116585
  plannedContent,
116663
116586
  status: "skipped",
116664
116587
  liveNote: "\u7CFB\u5217\u672A\u627E\u5230\uFF0C\u8DF3\u8FC7\u9644\u52A0\u4FE1\u606F\u6BD4\u5BF9",
@@ -116670,7 +116593,7 @@ function compareCampaignCreateToLive(cfg, campaignId, live, meta) {
116670
116593
  const remediateCommand = !found && ext && accountId && campaignId ? buildExtensionRemediateCommandLine({ accountId, campaignId, ext }) ?? void 0 : void 0;
116671
116594
  pushItem(items2, {
116672
116595
  layer: "extension",
116673
- path: path49,
116596
+ path: path48,
116674
116597
  plannedContent,
116675
116598
  status: found ? "ok" : "missing",
116676
116599
  liveNote: `\u7CFB\u5217\u7EA7\u9644\u52A0\u4FE1\u606F\u8D26\u6237\u5185 ${liveExt}/${plannedExt} \u6761`,
@@ -116697,11 +116620,11 @@ function compareCampaignCreateToLive(cfg, campaignId, live, meta) {
116697
116620
  if (!id) continue;
116698
116621
  const displayName = locationNames[li] || pickString2(loc["locationName"], loc["name"], loc["countryOrRegion"]) || "";
116699
116622
  const plannedContent = `locationId: ${id}${displayName ? ` | \u540D\u79F0: ${displayName}` : ""}`;
116700
- const path49 = `campaign.targetedLocations[${li}]`;
116623
+ const path48 = `campaign.targetedLocations[${li}]`;
116701
116624
  if (campaignMissing) {
116702
116625
  pushItem(items2, {
116703
116626
  layer: "location",
116704
- path: path49,
116627
+ path: path48,
116705
116628
  plannedContent,
116706
116629
  status: "skipped",
116707
116630
  liveNote: "\u7CFB\u5217\u672A\u627E\u5230\uFF0C\u8DF3\u8FC7\u5730\u57DF\u6BD4\u5BF9",
@@ -116713,7 +116636,7 @@ function compareCampaignCreateToLive(cfg, campaignId, live, meta) {
116713
116636
  const remediateCommand = !found && accountId && campaignId ? buildGeoRemediateCommandLine({ accountId, campaignId, locationId: id }) : void 0;
116714
116637
  pushItem(items2, {
116715
116638
  layer: "location",
116716
- path: path49,
116639
+ path: path48,
116717
116640
  plannedContent,
116718
116641
  status: found ? "ok" : "missing",
116719
116642
  liveNote: `\u7CFB\u5217\u5DF2\u5B9A\u5411 ${liveLocIds.size}/${plannedLocCount} \u4E2A\u5730\u57DF`,
@@ -118225,8 +118148,8 @@ function pmaxChannelTypesUrl(googleApiUrl) {
118225
118148
  }
118226
118149
  function pmaxCampaignUrl(googleApiUrl, accountId, campaignId) {
118227
118150
  const base = googleApiUrl.replace(/\/$/, "");
118228
- const path49 = `${base}/accounts/${accountId}/campaign/pmax`;
118229
- return campaignId ? `${path49}/${campaignId}` : path49;
118151
+ const path48 = `${base}/accounts/${accountId}/campaign/pmax`;
118152
+ return campaignId ? `${path48}/${campaignId}` : path48;
118230
118153
  }
118231
118154
  function pmaxBrandAssetsUrl(googleApiUrl, accountId, campaignId) {
118232
118155
  return `${pmaxCampaignUrl(googleApiUrl, accountId, campaignId)}/brand-assets`;
@@ -118236,8 +118159,8 @@ function pmaxBrandGuidelinesEnableUrl(googleApiUrl, accountId, campaignId) {
118236
118159
  }
118237
118160
  function pmaxAssetGroupUrl(googleApiUrl, accountId, assetGroupId, suffix) {
118238
118161
  const base = googleApiUrl.replace(/\/$/, "");
118239
- const path49 = `${base}/accounts/${accountId}/campaign/pmax/asset-group/${assetGroupId}`;
118240
- return suffix ? `${path49}/${suffix.replace(/^\//, "")}` : path49;
118162
+ const path48 = `${base}/accounts/${accountId}/campaign/pmax/asset-group/${assetGroupId}`;
118163
+ return suffix ? `${path48}/${suffix.replace(/^\//, "")}` : path48;
118241
118164
  }
118242
118165
  function pmaxCampaignAssetGroupUrl(googleApiUrl, accountId, campaignId) {
118243
118166
  const base = googleApiUrl.replace(/\/$/, "");
@@ -120978,8 +120901,8 @@ async function runAdPmaxImageConvert(opts) {
120978
120901
  }
120979
120902
 
120980
120903
  // src/commands/ad/pmax-brand-mgmt.ts
120981
- function loadBrandConfig(path49, accountId, campaignId) {
120982
- const cfg = loadPmaxJsonFile(path49);
120904
+ function loadBrandConfig(path48, accountId, campaignId) {
120905
+ const cfg = loadPmaxJsonFile(path48);
120983
120906
  return {
120984
120907
  ...cfg,
120985
120908
  account: String(cfg["account"] ?? accountId).trim(),
@@ -122611,9 +122534,9 @@ function metaAdContext(token) {
122611
122534
  const config = loadConfig(token);
122612
122535
  return { config, facebookApiUrl: requireFacebookApi(config) };
122613
122536
  }
122614
- function adsUrl(facebookApiUrl, account, path49) {
122537
+ function adsUrl(facebookApiUrl, account, path48) {
122615
122538
  const base = metaAdsBaseUrl(facebookApiUrl, account);
122616
- const p = path49.startsWith("/") ? path49 : `/${path49}`;
122539
+ const p = path48.startsWith("/") ? path48 : `/${path48}`;
122617
122540
  return `${base}${p}`;
122618
122541
  }
122619
122542
  async function metaAdGet(url, config, verbose, action) {
@@ -123545,9 +123468,9 @@ async function runMetaAdForms(opts) {
123545
123468
  if (opts.after) params.set("after", opts.after);
123546
123469
  if (opts.before) params.set("before", opts.before);
123547
123470
  const qs = params.toString();
123548
- const path49 = `/pages/${encodeURIComponent(opts.pageId)}/forms${qs ? `?${qs}` : ""}`;
123471
+ const path48 = `/pages/${encodeURIComponent(opts.pageId)}/forms${qs ? `?${qs}` : ""}`;
123549
123472
  const raw = await metaAdGet(
123550
- adsUrl(facebookApiUrl, digits, path49),
123473
+ adsUrl(facebookApiUrl, digits, path48),
123551
123474
  config,
123552
123475
  opts.verbose,
123553
123476
  "\u5217\u8868\u5355\u5931\u8D25"
@@ -123655,8 +123578,7 @@ var PLATFORM_ACCENTS = {
123655
123578
  tiktok: "FE2C55",
123656
123579
  yandex: "FC3F1D",
123657
123580
  bingv2: "0078D4",
123658
- bing: "0078D4",
123659
- kwai: "FF8300"
123581
+ bing: "0078D4"
123660
123582
  };
123661
123583
  var NEUTRAL = {
123662
123584
  titleFill: "1F2937",
@@ -123849,9 +123771,9 @@ function xfXml(x) {
123849
123771
  function stylesXml(reg) {
123850
123772
  return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><fonts count="${reg.fonts.length}">${reg.fonts.map(fontXml).join("")}</fonts><fills count="${reg.fills.length}">${reg.fills.map(fillXml).join("")}</fills><borders count="${reg.borders.length}">${reg.borders.map(borderXml).join("")}</borders><cellStyleXfs count="1"><xf numFmtId="0" fontId="0" fillId="0" borderId="0"/></cellStyleXfs><cellXfs count="${reg.xfs.length}">${reg.xfs.map(xfXml).join("")}</cellXfs><cellStyles count="1"><cellStyle name="\u5E38\u89C4" xfId="0" builtinId="0"/></cellStyles></styleSheet>`;
123851
123773
  }
123852
- function cellXml(ref, cell2) {
123853
- if (cell2 == null) return "";
123854
- const { value, styleId } = cell2;
123774
+ function cellXml(ref, cell3) {
123775
+ if (cell3 == null) return "";
123776
+ const { value, styleId } = cell3;
123855
123777
  const sAttr = styleId ? ` s="${styleId}"` : "";
123856
123778
  if (value == null || value === "") {
123857
123779
  return styleId ? `<c r="${ref}"${sAttr}/>` : "";
@@ -123866,7 +123788,7 @@ function sheetXml(sheet) {
123866
123788
  const rowsXml = sheet.rows.map((row, i) => {
123867
123789
  const r = i + 1;
123868
123790
  const htAttr = row.height ? ` ht="${row.height}" customHeight="1"` : "";
123869
- const cells = row.cells.map((cell2, cIdx) => cellXml(`${colLetter(cIdx)}${r}`, cell2)).join("");
123791
+ const cells = row.cells.map((cell3, cIdx) => cellXml(`${colLetter(cIdx)}${r}`, cell3)).join("");
123870
123792
  return `<row r="${r}"${htAttr}>${cells}</row>`;
123871
123793
  }).join("");
123872
123794
  const mergesXml = sheet.merges.length ? `<mergeCells count="${sheet.merges.length}">${sheet.merges.map((m) => `<mergeCell ref="${m}"/>`).join("")}</mergeCells>` : "";
@@ -127731,7 +127653,7 @@ function register25(program2) {
127731
127653
  const accountCmd = program2.command("account").description("\u5E7F\u544A\u8D26\u6237\u7BA1\u7406\uFF1AOAuth \u6DFB\u52A0\u6388\u6743\u3001\u89E3\u9664\u5173\u8054\uFF08\u89E3\u7ED1\uFF09\u3001Google MCC \u7ED1\u5B9A/\u89E3\u7ED1\u3001\u8D26\u53F7\u5206\u4EAB");
127732
127654
  accountCmd.command("list", { hidden: true }).description("\uFF08\u517C\u5BB9\u522B\u540D\uFF09\u540C list-accounts").option(
127733
127655
  "-m, --media <type>",
127734
- "\u5A92\u4F53\u7C7B\u578B\uFF1AGoogle | TikTok | Yandex | MetaAd | BingV2 | Kwai\uFF08\u7559\u7A7A\u5219\u67E5\u8BE2\u5168\u90E8\u5A92\u4F53\uFF09"
127656
+ "\u5A92\u4F53\u7C7B\u578B\uFF1AGoogle | TikTok | Yandex | MetaAd | BingV2\uFF08\u7559\u7A7A\u5219\u67E5\u8BE2\u5168\u90E8\u5A92\u4F53\uFF09"
127735
127657
  ).option("-k, --keyword <text>", "\u5173\u952E\u5B57\uFF08\u516C\u53F8/\u8D26\u6237\u540D/\u8D26\u6237ID \u6A21\u7CCA\u5339\u914D\uFF09").option(
127736
127658
  "-s, --status <status>",
127737
127659
  "\u8D26\u6237\u72B6\u6001\uFF1Anormal\uFF08\u6B63\u5E38\uFF09| invalid\uFF08\u5931\u6548\uFF09| all\uFF08\u5168\u90E8\uFF0C\u9ED8\u8BA4\uFF09",
@@ -127846,7 +127768,7 @@ function register25(program2) {
127846
127768
  "\u6DFB\u52A0\u6388\u6743\uFF1A\u9996\u6B21\u7ED1\u5B9A\u5A92\u4F53\u8D26\u6237 OAuth\uFF08\u7F51\u9875 manageAccounts\u300C\u6DFB\u52A0\u6388\u6743\u300D\uFF09\uFF1BOAuth \u5931\u6548\u8BF7\u7528 reauth"
127847
127769
  ).requiredOption(
127848
127770
  "-m, --media <type>",
127849
- "\u5A92\u4F53\u7C7B\u578B\uFF1AGoogle | TikTok | Meta | Yandex | BingV2 | Kwai"
127771
+ "\u5A92\u4F53\u7C7B\u578B\uFF1AGoogle | TikTok | Meta | Yandex | BingV2"
127850
127772
  ).option("-t, --token <token>", "Auth Token").option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(async (opts) => {
127851
127773
  await runAccountAuth({ token: opts.token, media: opts.media, verbose: opts.verbose });
127852
127774
  });
@@ -127854,7 +127776,7 @@ function register25(program2) {
127854
127776
  "\u91CD\u65B0\u6388\u6743\uFF1A\u5148\u89E3\u7ED1\u518D OAuth\uFF08\u7834\u574F\u6027\uFF1B\u987B\u7528\u6237\u786E\u8BA4\u540E\u52A0 --i-confirm + --commit\uFF1BAgent \u73AF\u5883\u7981\u6B62\uFF09"
127855
127777
  ).requiredOption(
127856
127778
  "-m, --media <type>",
127857
- "\u5A92\u4F53\u7C7B\u578B\uFF1AGoogle | TikTok | Meta | Yandex | BingV2 | Kwai"
127779
+ "\u5A92\u4F53\u7C7B\u578B\uFF1AGoogle | TikTok | Meta | Yandex | BingV2"
127858
127780
  ).option("--id <entityId>", "\u5355\u4E2A\u8D26\u6237 entityId\uFF08\u6765\u81EA list-accounts \u7684 ma.entityId\uFF09").option("--ids <entityIds>", "\u6279\u91CF entityId\uFF0C\u9017\u53F7\u5206\u9694\uFF08\u4E0E --id \u4E8C\u9009\u4E00\uFF0C\u53EF\u540C\u65F6\u4F20\uFF09").option("--i-confirm", "\u786E\u8BA4\u5DF2\u5411\u7528\u6237\u8BF4\u660E\u4F1A\u5148\u89E3\u7ED1\u518D OAuth \u5E76\u83B7\u5F97\u660E\u786E\u540C\u610F", false).option("-t, --token <token>", "Auth Token").option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(
127859
127781
  async (opts) => {
127860
127782
  await runAccountReauth({
@@ -128709,212 +128631,6 @@ BingV2 \u884C\u4E1A\u5217\u8868\uFF08\u7B2C 1 \u9875\uFF0C\u672C\u9875 ${list.le
128709
128631
  console.log();
128710
128632
  }
128711
128633
 
128712
- // src/commands/open-account/kwai.ts
128713
- init_auth();
128714
- import * as fs13 from "fs";
128715
- import * as path18 from "path";
128716
-
128717
- // src/commands/open-account/kwai-licence-id-type.ts
128718
- var KWAI_LICENCE_ID_TYPE_LABELS = {
128719
- "1": "\u7EDF\u4E00\u793E\u4F1A\u4FE1\u7528\u4EE3\u7801 / Business license Uniform social credit code",
128720
- "2": "DUNS / Data Universal Numbering System",
128721
- "3": "CNPJ"
128722
- };
128723
- var VALID = new Set(Object.keys(KWAI_LICENCE_ID_TYPE_LABELS));
128724
- var LEGACY_ALIASES = {
128725
- ENTERPRISE: "1",
128726
- INDIVIDUAL: "1"
128727
- };
128728
- function normalizeKwaiLicenceIdType(raw) {
128729
- const trimmed = raw.trim();
128730
- const upper = trimmed.toUpperCase();
128731
- const legacy = LEGACY_ALIASES[upper];
128732
- if (legacy) {
128733
- return { value: legacy, legacyAlias: trimmed };
128734
- }
128735
- if (VALID.has(trimmed)) {
128736
- return { value: trimmed };
128737
- }
128738
- const options = Object.entries(KWAI_LICENCE_ID_TYPE_LABELS).map(([k, v]) => `${k}=${v.split(" / ")[0]}`).join("\uFF1B");
128739
- throw new Error(
128740
- `\u65E0\u6548\u7684 --licence-id-type\uFF1A${JSON.stringify(raw)}\u3002Kwai \u987B\u4F7F\u7528\u6570\u5B57\u4EE3\u7801\uFF08\u4E0E\u7F51\u9875\u4E00\u81F4\uFF09\uFF1A${options}\u3002\u52FF\u4F7F\u7528 ENTERPRISE / INDIVIDUAL\u3002`
128741
- );
128742
- }
128743
-
128744
- // src/commands/open-account/kwai.ts
128745
- async function uploadToKwai(filePath, apiBaseUrl, config, verbose) {
128746
- const ext = path18.extname(filePath).toLowerCase().replace(".", "").replace("jpg", "jpeg");
128747
- const imageType = ext || "jpeg";
128748
- const fileBuffer = fs13.readFileSync(filePath);
128749
- const base64Image = fileBuffer.toString("base64");
128750
- const res = await apiFetch2(
128751
- `${apiBaseUrl}/KwaiAccount/Management/Upload`,
128752
- config,
128753
- {
128754
- method: "POST",
128755
- body: JSON.stringify({ ImageType: imageType, base64Image })
128756
- },
128757
- verbose
128758
- );
128759
- const blobstoreKey = res?.data?.fileBlobKey;
128760
- if (!blobstoreKey) {
128761
- throw new Error("Kwai \u56FE\u7247\u4E0A\u4F20\u5931\u8D25\uFF1A\u54CD\u5E94\u4E2D\u672A\u5305\u542B fileBlobKey");
128762
- }
128763
- return blobstoreKey;
128764
- }
128765
- async function waitForKwaiAccountInHistory(config, accountName, verbose) {
128766
- return pollUntil(
128767
- async () => {
128768
- const params = new URLSearchParams({
128769
- MediaType: "Kwai",
128770
- mediaAccountState: "Created,Approved,Denied",
128771
- pageNo: "1",
128772
- pageSize: "5",
128773
- mediaCustomerName: accountName
128774
- });
128775
- const res = await apiFetchWithHeaders2(
128776
- `${config.apiBaseUrl}/query/media-account/?${params}`,
128777
- config,
128778
- {},
128779
- verbose
128780
- );
128781
- const hits = parseInt(res.headers["s-total-hits"] ?? "0", 10);
128782
- if (hits > 0 && res.data?.length) {
128783
- return res.data[0] ?? null;
128784
- }
128785
- return null;
128786
- },
128787
- 2e3,
128788
- 3e4
128789
- );
128790
- }
128791
- async function runOpenAccountKwai(opts) {
128792
- const config = loadConfig(opts.token);
128793
- let licenceIdType;
128794
- try {
128795
- const normalized = normalizeKwaiLicenceIdType(opts.licenceIdType);
128796
- licenceIdType = normalized.value;
128797
- if (normalized.legacyAlias) {
128798
- console.error(
128799
- `
128800
- \u26A0\uFE0F --licence-id-type ${normalized.legacyAlias} \u5DF2\u5E9F\u5F03\uFF0C\u5DF2\u81EA\u52A8\u6620\u5C04\u4E3A ${licenceIdType}\uFF08\u7EDF\u4E00\u793E\u4F1A\u4FE1\u7528\u4EE3\u7801\uFF09\u3002\u8BF7\u6539\u7528\u6570\u5B57\u4EE3\u7801\uFF0C\u89C1 open-account-by-media.md \xA7 Kwai\u3002
128801
- `
128802
- );
128803
- }
128804
- } catch (err) {
128805
- console.error(`
128806
- \u274C ${err instanceof Error ? err.message : String(err)}
128807
- `);
128808
- process.exit(1);
128809
- }
128810
- if (!fs13.existsSync(opts.licenseFile)) {
128811
- console.error(`
128812
- \u274C \u8425\u4E1A\u6267\u7167\u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${opts.licenseFile}
128813
- `);
128814
- process.exit(1);
128815
- }
128816
- console.log(" [1/3] \u6B63\u5728\u4E0A\u4F20\u8425\u4E1A\u6267\u7167\u5230 Siluzan \u5B58\u6863...");
128817
- let imageId;
128818
- let storageProvider;
128819
- try {
128820
- const uploaded = await uploadAttachment(
128821
- opts.licenseFile,
128822
- config.apiBaseUrl,
128823
- config,
128824
- opts.verbose
128825
- );
128826
- imageId = uploaded.id;
128827
- storageProvider = uploaded.storageProvider;
128828
- console.log(` Siluzan imageId: ${imageId}`);
128829
- } catch (err) {
128830
- console.error(
128831
- `
128832
- \u274C Siluzan \u5B58\u6863\u4E0A\u4F20\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
128833
- `
128834
- );
128835
- process.exit(1);
128836
- }
128837
- console.log(" [2/3] \u6B63\u5728\u4E0A\u4F20\u8425\u4E1A\u6267\u7167\u5230 Kwai...");
128838
- let blobstoreKey;
128839
- try {
128840
- blobstoreKey = await uploadToKwai(opts.licenseFile, config.apiBaseUrl, config, opts.verbose);
128841
- } catch (err) {
128842
- console.error(
128843
- `
128844
- \u274C Kwai \u8425\u4E1A\u6267\u7167\u4E0A\u4F20\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
128845
- `
128846
- );
128847
- process.exit(1);
128848
- }
128849
- console.log(` Kwai blobstoreKey: ${blobstoreKey}`);
128850
- console.log(" [3/3] \u6B63\u5728\u5173\u8054\u5E7F\u544A\u4E3B\u7EC4...");
128851
- const magKey = await resolveGenericMagKey(
128852
- config,
128853
- opts.companyName,
128854
- { ImageId: imageId, StorageProvider: storageProvider },
128855
- opts.verbose,
128856
- opts.advertiserId
128857
- );
128858
- const body = {
128859
- MediaAccountGroupId: magKey,
128860
- KwaiAccountInfo: {
128861
- licenceId: opts.licenceId,
128862
- licenceRegisterCountryCode: opts.licenceCountry,
128863
- licenceRegisterLocation: opts.licenceLocation,
128864
- businessScope: opts.businessScope,
128865
- product: opts.product,
128866
- advertisementType: opts.adType,
128867
- productUrl: opts.productUrl,
128868
- currencyCode: "USD",
128869
- licenceIdType,
128870
- accountName: opts.accountName,
128871
- legalEntityName: opts.companyName,
128872
- newIndustryId1: opts.industryId1,
128873
- newIndustryId2: opts.industryId2,
128874
- mainCertPhotos: [
128875
- {
128876
- blobstoreKey,
128877
- expireType: opts.expireType,
128878
- expireAt: opts.expireType === 2 ? 0 : opts.expireAt ?? 0
128879
- }
128880
- ],
128881
- targetCountryInfos: [{ targetCountryCode: opts.targetCountry }]
128882
- }
128883
- };
128884
- try {
128885
- await apiFetch2(
128886
- `${config.apiBaseUrl}/command/media-account/AddKwaiAccount`,
128887
- config,
128888
- { method: "POST", body: JSON.stringify(body) },
128889
- opts.verbose
128890
- );
128891
- } catch (err) {
128892
- console.error(`
128893
- \u274C \u63D0\u4EA4\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
128894
- `);
128895
- process.exit(1);
128896
- }
128897
- console.log("\n \u5DF2\u6536\u5230\u670D\u52A1\u7AEF\u53D7\u7406\uFF08HTTP 202\uFF09\uFF0C\u6B63\u5728\u786E\u8BA4\u5F00\u6237\u8BB0\u5F55\u662F\u5426\u843D\u5E93\u2026");
128898
- const record2 = await waitForKwaiAccountInHistory(config, opts.accountName, opts.verbose);
128899
- if (!record2) {
128900
- console.error(
128901
- `
128902
- \u274C \u5F00\u6237\u8BF7\u6C42\u5DF2\u53D7\u7406\uFF0C\u4F46\u5728 30 \u79D2\u5185\u672A\u5728\u300C\u5F00\u6237\u8BB0\u5F55\u300D\u4E2D\u67E5\u5230\u8D26\u6237\u300C${opts.accountName}\u300D\u3002
128903
- \u5E38\u89C1\u539F\u56E0\uFF1A--licence-id-type \u975E\u6CD5\uFF08\u987B\u4E3A 1/2/3\uFF0C\u4E0E\u7F51\u9875 KwaiOpenAnAccount \u4E00\u81F4\uFF09\u3001\u884C\u4E1A ID \u65E0\u6548\u6216\u8D44\u8D28\u5B57\u6BB5\u88AB Kwai \u5F02\u6B65\u62D2\u7EDD\u3002
128904
- \u8BF7\u6838\u5BF9\u53C2\u6570\u540E\u91CD\u8BD5\uFF0C\u6216\u6267\u884C\uFF1Asiluzan-tso account-history -m Kwai -k ${opts.accountName}
128905
- `
128906
- );
128907
- process.exit(1);
128908
- }
128909
- const state = record2.ma.mediaAccountState ?? "Unknown";
128910
- console.log(
128911
- `
128912
- \u2705 Kwai \u5F00\u6237\u7533\u8BF7\u5DF2\u843D\u5E93\uFF08\u72B6\u6001\uFF1A${state}\uFF0C\u8D26\u6237\u540D\uFF1A${opts.accountName}\uFF09\u3002\u8BF7\u5728\u300C\u5F00\u6237\u8BB0\u5F55\u300D\u67E5\u770B\u5BA1\u6838\u8FDB\u5EA6\u3002
128913
- `
128914
- );
128915
- logAccountOpeningHistoryWebUrl(config.apiBaseUrl, "Kwai");
128916
- }
128917
-
128918
128634
  // src/commands/open-account/google.ts
128919
128635
  init_auth();
128920
128636
  import * as readline2 from "readline/promises";
@@ -129282,13 +128998,13 @@ Google \u5F00\u6237\u884C\u4E1A\uFF08\u7B2C 1 \u9875\uFF0C\u672C\u9875 ${rows.le
129282
128998
 
129283
128999
  // src/commands/open-account/tiktok.ts
129284
129000
  init_auth();
129285
- import * as fs14 from "fs";
129286
- import * as path19 from "path";
129001
+ import * as fs13 from "fs";
129002
+ import * as path18 from "path";
129287
129003
  init_cli_json_snapshot();
129288
129004
  init_cli_table();
129289
129005
  async function uploadLicenseToTikTok(filePath, businessCentreType, config, verbose) {
129290
- const fileName = path19.basename(filePath);
129291
- const fileBuffer = fs14.readFileSync(filePath);
129006
+ const fileName = path18.basename(filePath);
129007
+ const fileBuffer = fs13.readFileSync(filePath);
129292
129008
  const base64Image = fileBuffer.toString("base64");
129293
129009
  const res = await apiFetch2(
129294
129010
  `${config.apiBaseUrl}/command/media-account/tiktok/Upload`,
@@ -129313,7 +129029,7 @@ async function uploadLicenseToTikTok(filePath, businessCentreType, config, verbo
129313
129029
  async function runOpenAccountTikTok(opts) {
129314
129030
  const config = loadConfig(opts.token);
129315
129031
  const bcType = opts.businessCentreType ?? "Shop";
129316
- if (!fs14.existsSync(opts.licenseFile)) {
129032
+ if (!fs13.existsSync(opts.licenseFile)) {
129317
129033
  console.error(`
129318
129034
  \u274C \u8425\u4E1A\u6267\u7167\u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${opts.licenseFile}
129319
129035
  `);
@@ -129685,7 +129401,7 @@ async function runOpenAccountMeta(opts) {
129685
129401
 
129686
129402
  // src/commands/open-account-register.ts
129687
129403
  function register26(program2) {
129688
- const openAccountCmd = program2.command("open-account").description("\u5F00\u6237\u7533\u8BF7\uFF08Google / TikTok / Yandex / Bing / Kwai / Meta \u5F00\u6237\u94FE\u63A5\uFF09");
129404
+ const openAccountCmd = program2.command("open-account").description("\u5F00\u6237\u7533\u8BF7\uFF08Google / TikTok / Yandex / Bing / Meta \u5F00\u6237\u94FE\u63A5\uFF09");
129689
129405
  openAccountCmd.command("meta").description(
129690
129406
  "\u83B7\u53D6 Meta/Facebook \u5B98\u65B9\u5F00\u6237\u94FE\u63A5\uFF08GET MetaAccount/Management/GetOpenAccountLink\uFF0C\u4E0E\u7F51\u9875\u300C\u7533\u8BF7\u5F00\u6237\u300D\u4E00\u81F4\uFF09"
129691
129407
  ).option("-t, --token <token>", "Auth Token").option("--open-browser", "\u5C1D\u8BD5\u7528\u7CFB\u7EDF\u9ED8\u8BA4\u6D4F\u89C8\u5668\u6253\u5F00\u94FE\u63A5").option("--json-out <path>", "\u843D\u76D8 JSON\uFF08\u542B openAccountUrl\uFF09\uFF1Bstdout \u4E00\u884C\u6458\u8981", void 0).option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(
@@ -129901,34 +129617,6 @@ function register26(program2) {
129901
129617
  });
129902
129618
  }
129903
129619
  );
129904
- openAccountCmd.command("kwai").description("\u63D0\u4EA4 Kwai \u5F00\u6237\u7533\u8BF7\uFF08\u9700\u4E0A\u4F20\u8425\u4E1A\u6267\u7167\u56FE\u7247\uFF0C\u6309\u516C\u53F8\u540D\u81EA\u52A8\u521B\u5EFA/\u5173\u8054\u5E7F\u544A\u4E3B\u7EC4\uFF09").requiredOption("--licence-id <id>", "\u8425\u4E1A\u6267\u7167\u53F7\uFF08\u4E3B\u4F53\u4EE3\u7801\uFF09").requiredOption("--licence-country <code>", "\u4E3B\u4F53\u6CE8\u518C\u56FD\u5BB6\u4EE3\u7801\uFF0C\u5982 CN").requiredOption("--licence-location <address>", "\u4E3B\u4F53\u6CE8\u518C\u5730\uFF08\u7701\u5E02\u533A\u8BE6\u7EC6\u5730\u5740\uFF09").requiredOption("--business-scope <scope>", "\u8425\u4E1A\u8303\u56F4").requiredOption("--product <name>", "\u4EA7\u54C1\u6216\u54C1\u724C\u540D\u79F0").requiredOption("--ad-type <n>", "\u8D26\u6237\u7C7B\u578B\uFF1A1=\u6548\u679C\u5E7F\u544A 2=\u54C1\u724C\u5E7F\u544A", parseInt).requiredOption("--product-url <url>", "\u4EA7\u54C1\u6216\u54C1\u724C\u7F51\u5740").requiredOption(
129905
- "--licence-id-type <code>",
129906
- "\u6267\u7167/\u8BC1\u4EF6\u7C7B\u578B\uFF1A1=\u7EDF\u4E00\u793E\u4F1A\u4FE1\u7528\u4EE3\u7801 2=DUNS 3=CNPJ\uFF08\u4E0E\u7F51\u9875 KwaiOpenAnAccount \u4E0B\u62C9 value \u4E00\u81F4\uFF09"
129907
- ).requiredOption("--account-name <name>", "\u8D26\u6237\u540D\u79F0").requiredOption("--company-name <name>", "\u516C\u53F8\u4E3B\u4F53\u540D\u79F0").requiredOption("--industry-id1 <id>", "\u4E00\u7EA7\u884C\u4E1A ID").requiredOption("--industry-id2 <id>", "\u4E8C\u7EA7\u884C\u4E1A ID").requiredOption("--expire-type <n>", "\u6709\u6548\u671F\u7C7B\u578B\uFF1A1=\u6709\u9650\u671F 2=\u957F\u671F\u6709\u6548", parseInt).requiredOption("--target-country <code>", "\u6295\u653E\u5730\u533A\u56FD\u5BB6\u4EE3\u7801\uFF0C\u5982 US").requiredOption("--license-file <path>", "\u8425\u4E1A\u6267\u7167\u56FE\u7247\u672C\u5730\u8DEF\u5F84\uFF08JPG/PNG\uFF09").option("--expire-at <ms>", "\u5230\u671F\u65F6\u95F4\u6233\uFF08\u6BEB\u79D2\uFF09\uFF0Cexpire-type=1 \u65F6\u586B\u5199", parseInt).option("--advertiser-id <magKey>", "\u53EF\u9009\uFF1A\u624B\u52A8\u6307\u5B9A\u5E7F\u544A\u4E3B\u7EC4 magKey\uFF08\u4E00\u822C\u65E0\u9700\u586B\u5199\uFF09").option("-t, --token <token>", "Auth Token").option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(
129908
- async (opts) => {
129909
- await runOpenAccountKwai({
129910
- token: opts.token,
129911
- advertiserId: opts.advertiserId,
129912
- licenceId: opts.licenceId,
129913
- licenceCountry: opts.licenceCountry,
129914
- licenceLocation: opts.licenceLocation,
129915
- businessScope: opts.businessScope,
129916
- product: opts.product,
129917
- adType: opts.adType,
129918
- productUrl: opts.productUrl,
129919
- licenceIdType: opts.licenceIdType,
129920
- accountName: opts.accountName,
129921
- companyName: opts.companyName,
129922
- industryId1: opts.industryId1,
129923
- industryId2: opts.industryId2,
129924
- expireType: opts.expireType,
129925
- targetCountry: opts.targetCountry,
129926
- licenseFile: opts.licenseFile,
129927
- expireAt: opts.expireAt,
129928
- verbose: opts.verbose
129929
- });
129930
- }
129931
- );
129932
129620
  }
129933
129621
 
129934
129622
  // src/commands/diagnostic.ts
@@ -130577,10 +130265,10 @@ async function runWebsiteDiagnosisCollect(opts) {
130577
130265
 
130578
130266
  // src/commands/website-diagnosis/prepare.ts
130579
130267
  init_cli_json_snapshot();
130580
- import fs15 from "fs";
130581
- import path20 from "path";
130268
+ import fs14 from "fs";
130269
+ import path19 from "path";
130582
130270
  function readJson(filePath) {
130583
- const text2 = fs15.readFileSync(filePath, "utf8");
130271
+ const text2 = fs14.readFileSync(filePath, "utf8");
130584
130272
  try {
130585
130273
  const v = JSON.parse(text2);
130586
130274
  if (!v || typeof v !== "object" || Array.isArray(v)) {
@@ -130610,8 +130298,8 @@ function signalsFromCollectPayload(collect) {
130610
130298
  });
130611
130299
  }
130612
130300
  async function runWebsiteDiagnosisPrepare(opts) {
130613
- const collectPath = path20.resolve(opts.collectFile);
130614
- if (!fs15.existsSync(collectPath)) {
130301
+ const collectPath = path19.resolve(opts.collectFile);
130302
+ if (!fs14.existsSync(collectPath)) {
130615
130303
  console.error(`
130616
130304
  \u274C \u627E\u4E0D\u5230 collect \u6587\u4EF6\uFF1A${collectPath}
130617
130305
  `);
@@ -130620,11 +130308,11 @@ async function runWebsiteDiagnosisPrepare(opts) {
130620
130308
  const collect = readJson(collectPath);
130621
130309
  const signals = signalsFromCollectPayload(collect);
130622
130310
  const scaffold = buildDiagnosisScaffold(signals);
130623
- const outPath = path20.resolve(
130624
- opts.out ?? path20.join(path20.dirname(collectPath), "diagnosis.scaffold.json")
130311
+ const outPath = path19.resolve(
130312
+ opts.out ?? path19.join(path19.dirname(collectPath), "diagnosis.scaffold.json")
130625
130313
  );
130626
- fs15.mkdirSync(path20.dirname(outPath), { recursive: true });
130627
- fs15.writeFileSync(outPath, JSON.stringify(scaffold, null, 2), "utf8");
130314
+ fs14.mkdirSync(path19.dirname(outPath), { recursive: true });
130315
+ fs14.writeFileSync(outPath, JSON.stringify(scaffold, null, 2), "utf8");
130628
130316
  const summary = {
130629
130317
  url: signals.url,
130630
130318
  out: outPath,
@@ -130661,23 +130349,23 @@ async function runWebsiteDiagnosisPrepare(opts) {
130661
130349
  }
130662
130350
 
130663
130351
  // src/commands/website-diagnosis/render-report.ts
130664
- import fs16 from "fs";
130352
+ import fs15 from "fs";
130665
130353
  import fsPromises from "fs/promises";
130666
- import path21 from "path";
130354
+ import path20 from "path";
130667
130355
  import { fileURLToPath as fileURLToPath4 } from "url";
130668
130356
  var TEMPLATE_BASENAMES = {
130669
130357
  html: "website-diagnosis-report.html",
130670
130358
  runtime: "website-diagnosis-report.runtime.js"
130671
130359
  };
130672
130360
  function resolveSkillTemplatePath(basename13) {
130673
- const dir = path21.dirname(fileURLToPath4(import.meta.url));
130361
+ const dir = path20.dirname(fileURLToPath4(import.meta.url));
130674
130362
  const candidates = [
130675
- path21.join(dir, "skill", "report-templates", basename13),
130676
- path21.join(dir, "skill", "siluzan-ads", "report-templates", basename13),
130677
- path21.join(dir, "..", "..", "assets", "siluzan-ads", "report-templates", basename13)
130363
+ path20.join(dir, "skill", "report-templates", basename13),
130364
+ path20.join(dir, "skill", "siluzan-ads", "report-templates", basename13),
130365
+ path20.join(dir, "..", "..", "assets", "siluzan-ads", "report-templates", basename13)
130678
130366
  ];
130679
130367
  for (const p of candidates) {
130680
- if (fs16.existsSync(p)) return p;
130368
+ if (fs15.existsSync(p)) return p;
130681
130369
  }
130682
130370
  return candidates[0];
130683
130371
  }
@@ -130721,11 +130409,11 @@ function injectReportData(html, payload) {
130721
130409
  return html.replace(marker, `window.__WEBSITE_DIAGNOSIS__ = ${json};`);
130722
130410
  }
130723
130411
  async function runWebsiteDiagnosisRender(opts) {
130724
- const dataPath = path21.resolve(opts.dataFile);
130412
+ const dataPath = path20.resolve(opts.dataFile);
130725
130413
  const dataRaw = await readJsonFile(dataPath);
130726
130414
  let data = asRecord4(dataRaw);
130727
130415
  if (opts.collectFile) {
130728
- const collectRaw = await readJsonFile(path21.resolve(opts.collectFile));
130416
+ const collectRaw = await readJsonFile(path20.resolve(opts.collectFile));
130729
130417
  data = mergeCollectLighthouse(data, asRecord4(collectRaw));
130730
130418
  }
130731
130419
  const templatePath = websiteDiagnosisReportTemplatePath();
@@ -130739,14 +130427,14 @@ async function runWebsiteDiagnosisRender(opts) {
130739
130427
  `);
130740
130428
  process.exit(1);
130741
130429
  }
130742
- const outPath = path21.resolve(
130743
- opts.out ?? path21.join(path21.dirname(dataPath), "website-diagnosis-report.html")
130430
+ const outPath = path20.resolve(
130431
+ opts.out ?? path20.join(path20.dirname(dataPath), "website-diagnosis-report.html")
130744
130432
  );
130745
- const outDir = path21.dirname(outPath);
130433
+ const outDir = path20.dirname(outPath);
130746
130434
  await fsPromises.mkdir(outDir, { recursive: true });
130747
130435
  await fsPromises.writeFile(outPath, injectReportData(html, data), "utf8");
130748
130436
  const runtimeSrc = websiteDiagnosisRuntimePath();
130749
- const runtimeOut = path21.join(outDir, TEMPLATE_BASENAMES.runtime);
130437
+ const runtimeOut = path20.join(outDir, TEMPLATE_BASENAMES.runtime);
130750
130438
  let runtimeCopied = false;
130751
130439
  try {
130752
130440
  await fsPromises.copyFile(runtimeSrc, runtimeOut);
@@ -130950,8 +130638,8 @@ async function runMarketAnalysisCollect(opts) {
130950
130638
  }
130951
130639
 
130952
130640
  // src/commands/market-analysis/render-report.ts
130953
- import fs17 from "fs/promises";
130954
- import path22 from "path";
130641
+ import fs16 from "fs/promises";
130642
+ import path21 from "path";
130955
130643
 
130956
130644
  // src/commands/market-analysis/report-content.ts
130957
130645
  var SILUZAN_ECHARTS_CDN_URL = "https://staticpn.siluzan.com/assets/slz/homeCDN/echarts.min.js";
@@ -131402,10 +131090,10 @@ function resolveMarketAnalysisHtml(data) {
131402
131090
  throw new Error("JSON \u4E2D\u7F3A\u5C11 htmlContent \u6216 rawResponse \u5B57\u6BB5");
131403
131091
  }
131404
131092
  async function runMarketAnalysisRender(opts) {
131405
- const dataPath = path22.resolve(opts.dataFile);
131093
+ const dataPath = path21.resolve(opts.dataFile);
131406
131094
  let dataRaw;
131407
131095
  try {
131408
- dataRaw = JSON.parse(await fs17.readFile(dataPath, "utf8"));
131096
+ dataRaw = JSON.parse(await fs16.readFile(dataPath, "utf8"));
131409
131097
  } catch {
131410
131098
  console.error(`
131411
131099
  \u274C \u65E0\u6CD5\u89E3\u6790 JSON\uFF1A${dataPath}
@@ -131438,11 +131126,11 @@ async function runMarketAnalysisRender(opts) {
131438
131126
  );
131439
131127
  process.exit(1);
131440
131128
  }
131441
- const outPath = path22.resolve(
131442
- opts.out ?? path22.join(path22.dirname(dataPath), "market-analysis-report.html")
131129
+ const outPath = path21.resolve(
131130
+ opts.out ?? path21.join(path21.dirname(dataPath), "market-analysis-report.html")
131443
131131
  );
131444
- await fs17.mkdir(path22.dirname(outPath), { recursive: true });
131445
- await fs17.writeFile(outPath, html, "utf8");
131132
+ await fs16.mkdir(path21.dirname(outPath), { recursive: true });
131133
+ await fs16.writeFile(outPath, html, "utf8");
131446
131134
  const { stats } = contentCheck;
131447
131135
  console.log(`
131448
131136
  \u2705 \u5E02\u573A\u5206\u6790 HTML \u62A5\u544A\u5DF2\u751F\u6210\uFF1A${outPath}
@@ -131488,12 +131176,12 @@ function registerMarketAnalysisCommands(program2) {
131488
131176
 
131489
131177
  // src/commands/google-ads-diagnosis/run-collect.ts
131490
131178
  init_auth();
131491
- import fs21 from "fs/promises";
131492
- import path26 from "path";
131179
+ import fs20 from "fs/promises";
131180
+ import path25 from "path";
131493
131181
 
131494
131182
  // src/commands/google-ads-diagnosis/shared.ts
131495
- import fs18 from "fs";
131496
- import path23 from "path";
131183
+ import fs17 from "fs";
131184
+ import path22 from "path";
131497
131185
  import { fileURLToPath as fileURLToPath5 } from "url";
131498
131186
  var GOOGLE_ADS_DIAGNOSIS_TEMPLATE_BASENAME = "GoogleAdsDiagnosisReport.html";
131499
131187
  var GOOGLE_ADS_DIAGNOSIS_DATA_MARKER = "__REPORT_DATA__";
@@ -131549,14 +131237,14 @@ function buildGoogleAdsDiagnosisNarrativeChecks() {
131549
131237
  }
131550
131238
  var GOOGLE_ADS_DIAGNOSIS_NARRATIVE_CHECKS = buildGoogleAdsDiagnosisNarrativeChecks();
131551
131239
  function resolveSkillTemplatePath2(basename13) {
131552
- const dir = path23.dirname(fileURLToPath5(import.meta.url));
131240
+ const dir = path22.dirname(fileURLToPath5(import.meta.url));
131553
131241
  const candidates = [
131554
- path23.join(dir, "skill", "report-templates", basename13),
131555
- path23.join(dir, "skill", "siluzan-ads", "report-templates", basename13),
131556
- path23.join(dir, "..", "..", "assets", "siluzan-ads", "report-templates", basename13)
131242
+ path22.join(dir, "skill", "report-templates", basename13),
131243
+ path22.join(dir, "skill", "siluzan-ads", "report-templates", basename13),
131244
+ path22.join(dir, "..", "..", "assets", "siluzan-ads", "report-templates", basename13)
131557
131245
  ];
131558
131246
  for (const p of candidates) {
131559
- if (fs18.existsSync(p)) return p;
131247
+ if (fs17.existsSync(p)) return p;
131560
131248
  }
131561
131249
  return candidates[0];
131562
131250
  }
@@ -131583,8 +131271,8 @@ function buildGoogleAdsDiagnosisCollectAgentHint(snapDir) {
131583
131271
  }
131584
131272
 
131585
131273
  // src/commands/google-ads-diagnosis/build-report-data.ts
131586
- import fs20 from "fs";
131587
- import path25 from "path";
131274
+ import fs19 from "fs";
131275
+ import path24 from "path";
131588
131276
 
131589
131277
  // src/commands/google-ads-diagnosis/agent-brief.ts
131590
131278
  function buildGoogleAdsDiagnosisAgentBrief(input) {
@@ -131798,8 +131486,8 @@ function emptySummary() {
131798
131486
 
131799
131487
  // src/commands/google-ads-diagnosis/snapshot-io.ts
131800
131488
  init_google_analysis_snapshot();
131801
- import fs19 from "fs";
131802
- import path24 from "path";
131489
+ import fs18 from "fs";
131490
+ import path23 from "path";
131803
131491
  function dateRangeManifest(start, end) {
131804
131492
  if (start && end) return { mode: "range", start, end };
131805
131493
  return null;
@@ -131810,17 +131498,17 @@ function findSectionSnapshotFile(snapDir, section, accountId, start, end) {
131810
131498
  accountId,
131811
131499
  dateRangeManifest(start, end)
131812
131500
  );
131813
- const exactPath = path24.join(snapDir, exactName);
131814
- if (fs19.existsSync(exactPath)) return exactPath;
131501
+ const exactPath = path23.join(snapDir, exactName);
131502
+ if (fs18.existsSync(exactPath)) return exactPath;
131815
131503
  if (start && end) return void 0;
131816
- const files = fs19.readdirSync(snapDir);
131817
- return files.filter((f) => f.startsWith(`${section}-${accountId}`) && f.endsWith(".json")).sort().map((f) => path24.join(snapDir, f)).at(-1);
131504
+ const files = fs18.readdirSync(snapDir);
131505
+ return files.filter((f) => f.startsWith(`${section}-${accountId}`) && f.endsWith(".json")).sort().map((f) => path23.join(snapDir, f)).at(-1);
131818
131506
  }
131819
131507
  function loadSectionSnapshot(snapDir, section, accountId, start, end) {
131820
131508
  const file = findSectionSnapshotFile(snapDir, section, accountId, start, end);
131821
- if (!file || !fs19.existsSync(file)) return null;
131509
+ if (!file || !fs18.existsSync(file)) return null;
131822
131510
  try {
131823
- return JSON.parse(fs19.readFileSync(file, "utf8"));
131511
+ return JSON.parse(fs18.readFileSync(file, "utf8"));
131824
131512
  } catch {
131825
131513
  return null;
131826
131514
  }
@@ -131947,10 +131635,10 @@ function toDailyConversionItem(row) {
131947
131635
  };
131948
131636
  }
131949
131637
  function loadCompanyNameFromSnap(snapDir) {
131950
- const file = path25.join(snapDir, "list-accounts-google.json");
131951
- if (!fs20.existsSync(file)) return void 0;
131638
+ const file = path24.join(snapDir, "list-accounts-google.json");
131639
+ if (!fs19.existsSync(file)) return void 0;
131952
131640
  try {
131953
- const parsed = JSON.parse(fs20.readFileSync(file, "utf8"));
131641
+ const parsed = JSON.parse(fs19.readFileSync(file, "utf8"));
131954
131642
  const item = parsed.items?.[0];
131955
131643
  return item?.ma?.mediaCustomerName?.trim() || item?.mag?.advertiserName?.trim() || void 0;
131956
131644
  } catch {
@@ -132528,8 +132216,8 @@ async function runGoogleAdsDiagnosisCollect(opts) {
132528
132216
  console.error("\n\u274C collect \u987B\u540C\u65F6\u6307\u5B9A --start \u4E0E --end\u3002\n");
132529
132217
  process.exit(1);
132530
132218
  }
132531
- const snapDir = path26.resolve(opts.jsonOut);
132532
- await fs21.mkdir(snapDir, { recursive: true });
132219
+ const snapDir = path25.resolve(opts.jsonOut);
132220
+ await fs20.mkdir(snapDir, { recursive: true });
132533
132221
  let degraded = false;
132534
132222
  console.error(`
132535
132223
  \u{1F4E5} google-analysis \u62C9\u6570\uFF1A\u8D26\u6237 ${accountId}\uFF0C${opts.start} ~ ${opts.end}
@@ -132622,8 +132310,8 @@ async function runGoogleAdsDiagnosisCollect(opts) {
132622
132310
  agentBrief,
132623
132311
  agentHint: buildGoogleAdsDiagnosisCollectAgentHint(snapDir)
132624
132312
  };
132625
- const collectPath = path26.join(snapDir, GOOGLE_ADS_DIAGNOSIS_COLLECT_BASENAME);
132626
- await fs21.writeFile(collectPath, `${JSON.stringify(collectPayload, null, 2)}
132313
+ const collectPath = path25.join(snapDir, GOOGLE_ADS_DIAGNOSIS_COLLECT_BASENAME);
132314
+ await fs20.writeFile(collectPath, `${JSON.stringify(collectPayload, null, 2)}
132627
132315
  `, "utf8");
132628
132316
  console.log(
132629
132317
  JSON.stringify({
@@ -132641,15 +132329,15 @@ async function runGoogleAdsDiagnosisCollect(opts) {
132641
132329
  ` Agent\uFF1A\u8BFB agentBrief + reportData\uFF0C\u6309 google-ads-diagnosis.md \u64B0\u5199 narrative\uFF0C\u4FDD\u5B58 ${GOOGLE_ADS_DIAGNOSIS_REPORT_BASENAME}`
132642
132330
  );
132643
132331
  console.error(
132644
- ` \u7EC8\u7A3F\uFF1Asiluzan-tso google-ads-diagnosis render --data ${path26.join(snapDir, GOOGLE_ADS_DIAGNOSIS_REPORT_BASENAME)}
132332
+ ` \u7EC8\u7A3F\uFF1Asiluzan-tso google-ads-diagnosis render --data ${path25.join(snapDir, GOOGLE_ADS_DIAGNOSIS_REPORT_BASENAME)}
132645
132333
  `
132646
132334
  );
132647
132335
  if (degraded) process.exit(2);
132648
132336
  }
132649
132337
 
132650
132338
  // src/commands/google-ads-diagnosis/render-report.ts
132651
- import fs22 from "fs/promises";
132652
- import path27 from "path";
132339
+ import fs21 from "fs/promises";
132340
+ import path26 from "path";
132653
132341
 
132654
132342
  // src/commands/google-ads-diagnosis/report-content.ts
132655
132343
  function asRecord7(value) {
@@ -132658,9 +132346,9 @@ function asRecord7(value) {
132658
132346
  }
132659
132347
  return null;
132660
132348
  }
132661
- function getNestedValue(root, path49) {
132349
+ function getNestedValue(root, path48) {
132662
132350
  let cur = root;
132663
- for (const key of path49) {
132351
+ for (const key of path48) {
132664
132352
  const rec = asRecord7(cur);
132665
132353
  if (!rec) return void 0;
132666
132354
  cur = rec[key];
@@ -133053,7 +132741,7 @@ function asRecord10(value) {
133053
132741
  }
133054
132742
  async function tryLoadCollectReportData(collectPath) {
133055
132743
  try {
133056
- const raw = JSON.parse(await fs22.readFile(collectPath, "utf8"));
132744
+ const raw = JSON.parse(await fs21.readFile(collectPath, "utf8"));
133057
132745
  const root = asRecord10(raw);
133058
132746
  const reportData = asRecord10(root?.reportData);
133059
132747
  return reportData ?? root;
@@ -133062,10 +132750,10 @@ async function tryLoadCollectReportData(collectPath) {
133062
132750
  }
133063
132751
  }
133064
132752
  async function runGoogleAdsDiagnosisRender(opts) {
133065
- const dataPath = path27.resolve(opts.dataFile);
132753
+ const dataPath = path26.resolve(opts.dataFile);
133066
132754
  let dataRaw;
133067
132755
  try {
133068
- dataRaw = JSON.parse(await fs22.readFile(dataPath, "utf8"));
132756
+ dataRaw = JSON.parse(await fs21.readFile(dataPath, "utf8"));
133069
132757
  } catch {
133070
132758
  console.error(`
133071
132759
  \u274C \u65E0\u6CD5\u89E3\u6790 JSON\uFF1A${dataPath}
@@ -133074,8 +132762,8 @@ async function runGoogleAdsDiagnosisRender(opts) {
133074
132762
  }
133075
132763
  let data = asRecord10(dataRaw);
133076
132764
  if (!opts.noMergeCollect) {
133077
- const collectPath = path27.resolve(
133078
- opts.collectFile ?? path27.join(path27.dirname(dataPath), GOOGLE_ADS_DIAGNOSIS_COLLECT_BASENAME)
132765
+ const collectPath = path26.resolve(
132766
+ opts.collectFile ?? path26.join(path26.dirname(dataPath), GOOGLE_ADS_DIAGNOSIS_COLLECT_BASENAME)
133079
132767
  );
133080
132768
  const collectReportData = await tryLoadCollectReportData(collectPath);
133081
132769
  if (collectReportData) {
@@ -133148,7 +132836,7 @@ async function runGoogleAdsDiagnosisRender(opts) {
133148
132836
  const templatePath = googleAdsDiagnosisReportTemplatePath();
133149
132837
  let html;
133150
132838
  try {
133151
- html = await fs22.readFile(templatePath, "utf8");
132839
+ html = await fs21.readFile(templatePath, "utf8");
133152
132840
  } catch {
133153
132841
  console.error(`
133154
132842
  \u274C \u672A\u627E\u5230\u62A5\u544A\u6A21\u677F\uFF1A${templatePath}
@@ -133166,11 +132854,11 @@ async function runGoogleAdsDiagnosisRender(opts) {
133166
132854
  `);
133167
132855
  process.exit(1);
133168
132856
  }
133169
- const outPath = path27.resolve(
133170
- opts.out ?? path27.join(path27.dirname(dataPath), "google-ads-diagnosis-report.html")
132857
+ const outPath = path26.resolve(
132858
+ opts.out ?? path26.join(path26.dirname(dataPath), "google-ads-diagnosis-report.html")
133171
132859
  );
133172
- await fs22.mkdir(path27.dirname(outPath), { recursive: true });
133173
- await fs22.writeFile(outPath, rendered, "utf8");
132860
+ await fs21.mkdir(path26.dirname(outPath), { recursive: true });
132861
+ await fs21.writeFile(outPath, rendered, "utf8");
133174
132862
  console.log(`
133175
132863
  \u2705 Google \u5E7F\u544A\u8BCA\u65AD HTML \u62A5\u544A\u5DF2\u751F\u6210\uFF1A${outPath}
133176
132864
  `);
@@ -133314,14 +133002,14 @@ var FACEBOOK_SECTION_ALIASES = {
133314
133002
  import { Command as Command2 } from "commander";
133315
133003
 
133316
133004
  // src/commands/facebook-analysis/render-report.ts
133317
- import fs28 from "fs";
133005
+ import fs27 from "fs";
133318
133006
  import fsPromises3 from "fs/promises";
133319
- import path35 from "path";
133007
+ import path34 from "path";
133320
133008
  import { fileURLToPath as fileURLToPath7 } from "url";
133321
133009
 
133322
133010
  // src/commands/facebook-analysis/merge-snapshot.ts
133323
- import * as fs27 from "fs/promises";
133324
- import * as path34 from "path";
133011
+ import * as fs26 from "fs/promises";
133012
+ import * as path33 from "path";
133325
133013
 
133326
133014
  // src/commands/facebook-analysis/report-metrics.ts
133327
133015
  function asRecord14(value) {
@@ -133378,24 +133066,94 @@ function genderLabel(gender) {
133378
133066
  if (g === "female") return "female";
133379
133067
  return str(gender) || "unknown";
133380
133068
  }
133069
+ function enumKey(raw) {
133070
+ return raw.toLowerCase().replace(/[\s_\-./]+/g, "");
133071
+ }
133072
+ var RESULT_TYPE_ZH = {
133073
+ linkclick: "\u94FE\u63A5\u70B9\u51FB",
133074
+ landingpageview: "\u843D\u5730\u9875\u6D4F\u89C8",
133075
+ pageengagement: "\u516C\u5171\u4E3B\u9875\u4E92\u52A8",
133076
+ postengagement: "\u5E16\u5B50\u4E92\u52A8",
133077
+ videoview: "\u89C6\u9891\u64AD\u653E",
133078
+ purchase: "\u8D2D\u7269",
133079
+ addtocart: "\u52A0\u5165\u8D2D\u7269\u8F66",
133080
+ initiatecheckout: "\u53D1\u8D77\u7ED3\u8D26",
133081
+ completeregistration: "\u5B8C\u6210\u6CE8\u518C",
133082
+ viewcontent: "\u67E5\u770B\u5185\u5BB9",
133083
+ appinstall: "\u5E94\u7528\u5B89\u88C5",
133084
+ mobileappinstall: "\u5E94\u7528\u5B89\u88C5"
133085
+ };
133086
+ var OBJECTIVE_ZH = {
133087
+ outcomeawareness: "\u77E5\u540D\u5EA6",
133088
+ outcomeengagement: "\u4E92\u52A8",
133089
+ outcomeleads: "\u6F5C\u5728\u5BA2\u6237",
133090
+ outcomesales: "\u9500\u91CF",
133091
+ outcometraffic: "\u6D41\u91CF",
133092
+ outcomeapppromotion: "\u5E94\u7528\u63A8\u5E7F",
133093
+ brandawareness: "\u54C1\u724C\u77E5\u540D\u5EA6",
133094
+ reach: "\u8986\u76D6\u4EBA\u6570",
133095
+ traffic: "\u6D41\u91CF",
133096
+ linkclicks: "\u94FE\u63A5\u70B9\u51FB",
133097
+ engagement: "\u4E92\u52A8",
133098
+ postengagement: "\u5E16\u5B50\u4E92\u52A8",
133099
+ leadgeneration: "\u6F5C\u5728\u5BA2\u6237",
133100
+ conversions: "\u8F6C\u5316",
133101
+ appinstalls: "\u5E94\u7528\u5B89\u88C5",
133102
+ videoviews: "\u89C6\u9891\u64AD\u653E",
133103
+ messages: "\u6D88\u606F",
133104
+ catalogsales: "\u76EE\u5F55\u9500\u552E"
133105
+ };
133381
133106
  function displayResultType(raw) {
133382
133107
  const v = str(raw);
133383
133108
  if (!v) return "";
133384
- const key = v.toLowerCase().replace(/[\s_]+/g, "");
133109
+ const key = enumKey(v);
133385
133110
  if (key === "lead" || key === "leads" || key.includes("leadgrouped") || key.includes("instantform") || key === "onsiteconversionleadgrouped") {
133386
133111
  return "\u6F5C\u5728\u5BA2\u6237\u4FE1\u606F\uFF08\u8868\u5355\uFF09\u91CF";
133387
133112
  }
133388
- return v;
133113
+ return RESULT_TYPE_ZH[key] ?? v;
133114
+ }
133115
+ function displayObjective(raw) {
133116
+ const v = str(raw);
133117
+ if (!v) return "";
133118
+ return OBJECTIVE_ZH[enumKey(v)] ?? v;
133389
133119
  }
133390
133120
  function displayAttribution(raw) {
133391
133121
  const v = str(raw);
133392
133122
  if (!v) return "";
133393
- const key = v.toLowerCase().replace(/[\s_\-/]/g, "");
133123
+ const key = enumKey(v);
133394
133124
  if (key === "multiple" || key === "7dclick" || key === "7dclick1dview" || key.includes("7dclick") || key.includes("7dayclick")) {
133395
133125
  return "\u70B9\u51FB\u540E 7 \u5929\u5185\u6216\u6D4F\u89C8\u540E 1 \u5929\u5185";
133396
133126
  }
133127
+ if (key === "1dclick1dview" || key === "1dclickor1dview") {
133128
+ return "\u70B9\u51FB\u540E 1 \u5929\u5185\u6216\u6D4F\u89C8\u540E 1 \u5929\u5185";
133129
+ }
133130
+ if (key === "1dclick") return "\u70B9\u51FB\u540E 1 \u5929\u5185";
133131
+ if (key === "1dview") return "\u6D4F\u89C8\u540E 1 \u5929\u5185";
133132
+ if (key === "7dview") return "\u6D4F\u89C8\u540E 7 \u5929\u5185";
133133
+ if (key === "28dclick") return "\u70B9\u51FB\u540E 28 \u5929\u5185";
133397
133134
  return v;
133398
133135
  }
133136
+ function localizeMetricLabels(row) {
133137
+ if (!row) return;
133138
+ if (row.resultType != null) row.resultType = displayResultType(row.resultType);
133139
+ if (row.attributionSetting != null) {
133140
+ row.attributionSetting = displayAttribution(row.attributionSetting);
133141
+ }
133142
+ if (row.objective != null) row.objective = displayObjective(row.objective);
133143
+ }
133144
+ function localizeFacebookReportLabels(payload) {
133145
+ localizeMetricLabels(payload.meta);
133146
+ localizeMetricLabels(payload.kpis);
133147
+ const tables = payload.tables;
133148
+ if (!tables) return payload;
133149
+ for (const rows of Object.values(tables)) {
133150
+ if (!Array.isArray(rows)) continue;
133151
+ for (const row of rows) {
133152
+ localizeMetricLabels(asRecord14(row));
133153
+ }
133154
+ }
133155
+ return payload;
133156
+ }
133399
133157
  function hasResults(row) {
133400
133158
  const n = num3(row.results);
133401
133159
  return n != null && n > 0;
@@ -133403,7 +133161,7 @@ function hasResults(row) {
133403
133161
 
133404
133162
  // src/commands/facebook-analysis/merge-snapshot.ts
133405
133163
  async function readManifest2(snapshotDir) {
133406
- const entries = await fs27.readdir(snapshotDir);
133164
+ const entries = await fs26.readdir(snapshotDir);
133407
133165
  const manifestNames = entries.filter(
133408
133166
  (n) => n.startsWith("report-manifest") && n.endsWith(".json")
133409
133167
  );
@@ -133413,7 +133171,7 @@ async function readManifest2(snapshotDir) {
133413
133171
  ];
133414
133172
  for (const name2 of ordered) {
133415
133173
  try {
133416
- const raw = await fs27.readFile(path34.join(snapshotDir, name2), "utf8");
133174
+ const raw = await fs26.readFile(path33.join(snapshotDir, name2), "utf8");
133417
133175
  const parsed = JSON.parse(raw);
133418
133176
  if (parsed?.artifacts?.length) return parsed;
133419
133177
  } catch {
@@ -133423,7 +133181,7 @@ async function readManifest2(snapshotDir) {
133423
133181
  }
133424
133182
  async function loadSectionFile2(snapshotDir, file) {
133425
133183
  try {
133426
- const raw = await fs27.readFile(path34.join(snapshotDir, file), "utf8");
133184
+ const raw = await fs26.readFile(path33.join(snapshotDir, file), "utf8");
133427
133185
  return asRecord14(JSON.parse(raw));
133428
133186
  } catch {
133429
133187
  return null;
@@ -133467,7 +133225,7 @@ function mapAdSetRows(groups) {
133467
133225
  })).sort((a, b) => (b.spend ?? 0) - (a.spend ?? 0));
133468
133226
  }
133469
133227
  async function mergeFacebookSnapshotIntoReport(payload, snapshotDir) {
133470
- const absDir = path34.resolve(snapshotDir);
133228
+ const absDir = path33.resolve(snapshotDir);
133471
133229
  const manifest = await readManifest2(snapshotDir);
133472
133230
  if (!manifest) {
133473
133231
  throw new Error(
@@ -133577,10 +133335,10 @@ function estimateColWidths(rows) {
133577
133335
  const colCount = rows.reduce((max, row) => Math.max(max, row.length), 0);
133578
133336
  const widths = new Array(colCount).fill(MIN_COL_WIDTH);
133579
133337
  for (const row of rows) {
133580
- row.forEach((cell2, idx) => {
133581
- if (cell2 == null) return;
133338
+ row.forEach((cell3, idx) => {
133339
+ if (cell3 == null) return;
133582
133340
  const longestLine = Math.max(
133583
- ...String(cell2).split("\n").map((l) => l.length)
133341
+ ...String(cell3).split("\n").map((l) => l.length)
133584
133342
  );
133585
133343
  const width = Math.min(MAX_COL_WIDTH, Math.max(MIN_COL_WIDTH, Math.ceil(longestLine * 1.3)));
133586
133344
  if (width > widths[idx]) widths[idx] = width;
@@ -134072,14 +133830,14 @@ var TEMPLATE_BASENAMES2 = {
134072
133830
  };
134073
133831
  var INJECT_MARKER2 = "window.__META_PERIOD_REPORT__ = window.__META_PERIOD_REPORT__ || null;";
134074
133832
  function resolveSkillTemplatePath4(basename13) {
134075
- const dir = path35.dirname(fileURLToPath7(import.meta.url));
133833
+ const dir = path34.dirname(fileURLToPath7(import.meta.url));
134076
133834
  const candidates = [
134077
- path35.join(dir, "skill", "report-templates", basename13),
134078
- path35.join(dir, "skill", "siluzan-ads", "report-templates", basename13),
134079
- path35.join(dir, "..", "..", "assets", "siluzan-ads", "report-templates", basename13)
133835
+ path34.join(dir, "skill", "report-templates", basename13),
133836
+ path34.join(dir, "skill", "siluzan-ads", "report-templates", basename13),
133837
+ path34.join(dir, "..", "..", "assets", "siluzan-ads", "report-templates", basename13)
134080
133838
  ];
134081
133839
  for (const p of candidates) {
134082
- if (fs28.existsSync(p)) return p;
133840
+ if (fs27.existsSync(p)) return p;
134083
133841
  }
134084
133842
  return candidates[0];
134085
133843
  }
@@ -134124,7 +133882,7 @@ function injectReportData3(html, payload) {
134124
133882
  }
134125
133883
  function defaultOutPath(dataPath, format, out) {
134126
133884
  if (out?.trim()) {
134127
- const resolved = path35.resolve(out);
133885
+ const resolved = path34.resolve(out);
134128
133886
  if (format === "xlsx" && !/\.xlsx$/i.test(resolved)) {
134129
133887
  return resolved.replace(/\.(html?)$/i, ".xlsx");
134130
133888
  }
@@ -134133,15 +133891,16 @@ function defaultOutPath(dataPath, format, out) {
134133
133891
  }
134134
133892
  return resolved;
134135
133893
  }
134136
- const dir = path35.dirname(dataPath);
134137
- return path35.join(dir, format === "xlsx" ? "meta-period-report.xlsx" : "meta-period-report.html");
133894
+ const dir = path34.dirname(dataPath);
133895
+ return path34.join(dir, format === "xlsx" ? "meta-period-report.xlsx" : "meta-period-report.html");
134138
133896
  }
134139
133897
  async function runFacebookAnalysisRender(opts) {
134140
- const dataPath = path35.resolve(opts.dataFile);
133898
+ const dataPath = path34.resolve(opts.dataFile);
134141
133899
  let data = asRecord17(await readJsonFile3(dataPath));
134142
133900
  if (opts.snapshotDir?.trim()) {
134143
- data = await mergeFacebookSnapshotIntoReport(data, path35.resolve(opts.snapshotDir));
133901
+ data = await mergeFacebookSnapshotIntoReport(data, path34.resolve(opts.snapshotDir));
134144
133902
  }
133903
+ localizeFacebookReportLabels(data);
134145
133904
  const contentCheck = validateMetaPeriodReportContent(data);
134146
133905
  if (!contentCheck.ok) {
134147
133906
  console.error(`
@@ -134158,7 +133917,7 @@ async function runFacebookAnalysisRender(opts) {
134158
133917
  const written = [];
134159
133918
  for (const format of formats) {
134160
133919
  const outPath = defaultOutPath(dataPath, format, opts.out);
134161
- await fsPromises3.mkdir(path35.dirname(outPath), { recursive: true });
133920
+ await fsPromises3.mkdir(path34.dirname(outPath), { recursive: true });
134162
133921
  if (format === "xlsx") {
134163
133922
  writeMetaPeriodExcel(outPath, data);
134164
133923
  } else {
@@ -134193,14 +133952,14 @@ async function runFacebookAnalysisRender(opts) {
134193
133952
  }
134194
133953
 
134195
133954
  // src/commands/facebook-analysis/diagnosis-render-report.ts
134196
- import fs30 from "fs";
133955
+ import fs29 from "fs";
134197
133956
  import fsPromises4 from "fs/promises";
134198
- import path37 from "path";
133957
+ import path36 from "path";
134199
133958
  import { fileURLToPath as fileURLToPath8 } from "url";
134200
133959
 
134201
133960
  // src/commands/facebook-analysis/diagnosis-merge-snapshot.ts
134202
- import * as fs29 from "fs/promises";
134203
- import * as path36 from "path";
133961
+ import * as fs28 from "fs/promises";
133962
+ import * as path35 from "path";
134204
133963
  function asRecord18(value) {
134205
133964
  if (value && typeof value === "object" && !Array.isArray(value)) {
134206
133965
  return value;
@@ -134236,7 +133995,7 @@ async function readManifest3(snapshotDir, accountId) {
134236
133995
  const candidates = [];
134237
133996
  if (accountId) candidates.push(reportManifestFile(accountId));
134238
133997
  try {
134239
- const entries = await fs29.readdir(snapshotDir);
133998
+ const entries = await fs28.readdir(snapshotDir);
134240
133999
  const manifestNames = entries.filter(
134241
134000
  (n) => n.startsWith("report-manifest") && n.endsWith(".json")
134242
134001
  );
@@ -134250,7 +134009,7 @@ async function readManifest3(snapshotDir, accountId) {
134250
134009
  }
134251
134010
  for (const name2 of candidates) {
134252
134011
  try {
134253
- const raw = await fs29.readFile(path36.join(snapshotDir, name2), "utf8");
134012
+ const raw = await fs28.readFile(path35.join(snapshotDir, name2), "utf8");
134254
134013
  const parsed = JSON.parse(raw);
134255
134014
  if (Array.isArray(parsed.artifacts) && parsed.artifacts.length > 0) return parsed;
134256
134015
  } catch {
@@ -134260,14 +134019,14 @@ async function readManifest3(snapshotDir, accountId) {
134260
134019
  }
134261
134020
  async function loadSectionFile3(snapshotDir, file) {
134262
134021
  try {
134263
- const raw = await fs29.readFile(path36.join(snapshotDir, file), "utf8");
134022
+ const raw = await fs28.readFile(path35.join(snapshotDir, file), "utf8");
134264
134023
  return asRecord18(JSON.parse(raw));
134265
134024
  } catch {
134266
134025
  return null;
134267
134026
  }
134268
134027
  }
134269
134028
  async function mergeMetaDiagnosisSnapshotIntoReport(payload, snapshotDir) {
134270
- const absDir = path36.resolve(snapshotDir);
134029
+ const absDir = path35.resolve(snapshotDir);
134271
134030
  const metaAccountId = typeof asRecord18(payload.meta)?.accountId === "string" ? asRecord18(payload.meta)?.accountId : void 0;
134272
134031
  const manifest = await readManifest3(snapshotDir, metaAccountId);
134273
134032
  if (!manifest) {
@@ -134546,14 +134305,14 @@ function formatMetaDiagnosisReportErrors(result) {
134546
134305
  var TEMPLATE_BASENAME2 = "meta-account-diagnosis-report.html";
134547
134306
  var INJECT_MARKER3 = "window.__META_DIAGNOSIS_REPORT__ = window.__META_DIAGNOSIS_REPORT__ || null;";
134548
134307
  function resolveSkillTemplatePath5(basename13) {
134549
- const dir = path37.dirname(fileURLToPath8(import.meta.url));
134308
+ const dir = path36.dirname(fileURLToPath8(import.meta.url));
134550
134309
  const candidates = [
134551
- path37.join(dir, "skill", "report-templates", basename13),
134552
- path37.join(dir, "skill", "siluzan-ads", "report-templates", basename13),
134553
- path37.join(dir, "..", "..", "assets", "siluzan-ads", "report-templates", basename13)
134310
+ path36.join(dir, "skill", "report-templates", basename13),
134311
+ path36.join(dir, "skill", "siluzan-ads", "report-templates", basename13),
134312
+ path36.join(dir, "..", "..", "assets", "siluzan-ads", "report-templates", basename13)
134554
134313
  ];
134555
134314
  for (const p of candidates) {
134556
- if (fs30.existsSync(p)) return p;
134315
+ if (fs29.existsSync(p)) return p;
134557
134316
  }
134558
134317
  return candidates[0];
134559
134318
  }
@@ -134582,10 +134341,10 @@ function injectReportData4(html, payload) {
134582
134341
  return html.replace(INJECT_MARKER3, `window.__META_DIAGNOSIS_REPORT__ = ${json};`);
134583
134342
  }
134584
134343
  async function runFacebookAnalysisDiagnosisRender(opts) {
134585
- const dataPath = path37.resolve(opts.dataFile);
134344
+ const dataPath = path36.resolve(opts.dataFile);
134586
134345
  let data = asRecord20(await readJsonFile4(dataPath));
134587
134346
  if (opts.snapshotDir?.trim()) {
134588
- data = await mergeMetaDiagnosisSnapshotIntoReport(data, path37.resolve(opts.snapshotDir));
134347
+ data = await mergeMetaDiagnosisSnapshotIntoReport(data, path36.resolve(opts.snapshotDir));
134589
134348
  }
134590
134349
  const contentCheck = validateMetaDiagnosisReportContent(data);
134591
134350
  if (!contentCheck.ok) {
@@ -134611,10 +134370,10 @@ async function runFacebookAnalysisDiagnosisRender(opts) {
134611
134370
  `);
134612
134371
  process.exit(1);
134613
134372
  }
134614
- const outPath = path37.resolve(
134615
- opts.out ?? path37.join(path37.dirname(dataPath), "meta-account-diagnosis-report.html")
134373
+ const outPath = path36.resolve(
134374
+ opts.out ?? path36.join(path36.dirname(dataPath), "meta-account-diagnosis-report.html")
134616
134375
  );
134617
- const outDir = path37.dirname(outPath);
134376
+ const outDir = path36.dirname(outPath);
134618
134377
  await fsPromises4.mkdir(outDir, { recursive: true });
134619
134378
  await fsPromises4.writeFile(outPath, injectReportData4(html, data), "utf8");
134620
134379
  const { stats } = contentCheck;
@@ -134632,7 +134391,7 @@ async function runFacebookAnalysisDiagnosisRender(opts) {
134632
134391
 
134633
134392
  // src/commands/facebook-analysis/run-batch.ts
134634
134393
  init_auth();
134635
- import * as path38 from "path";
134394
+ import * as path37 from "path";
134636
134395
  import { performance as performance5 } from "perf_hooks";
134637
134396
  init_version();
134638
134397
 
@@ -134734,7 +134493,7 @@ async function runAllFacebookSections(opts) {
134734
134493
  const results = await runWithConcurrency3(tasks, concurrency);
134735
134494
  const succeeded = results.filter((r) => r.ok).length;
134736
134495
  const failed = results.length - succeeded;
134737
- const absoluteSnapshotDir = path38.resolve(opts.jsonOut);
134496
+ const absoluteSnapshotDir = path37.resolve(opts.jsonOut);
134738
134497
  const summary = {
134739
134498
  kind: "siluzan-tso-facebook-analysis-snapshot-batch",
134740
134499
  absoluteSnapshotDir,
@@ -134858,9 +134617,9 @@ function parseEffectiveStatusFilter(raw) {
134858
134617
  }
134859
134618
  return canonical.length ? canonical.join(",") : void 0;
134860
134619
  }
134861
- function facebookAdsUrl(facebookApiUrl, digits, path49) {
134620
+ function facebookAdsUrl(facebookApiUrl, digits, path48) {
134862
134621
  const base = facebookApiUrl.replace(/\/$/, "");
134863
- const p = path49.startsWith("/") ? path49 : `/${path49}`;
134622
+ const p = path48.startsWith("/") ? path48 : `/${path48}`;
134864
134623
  return `${base}/api/fb/ads/${digits}${p}`;
134865
134624
  }
134866
134625
  function facebookInsightsUrl(facebookApiUrl, digits, level) {
@@ -134897,7 +134656,7 @@ async function fetchFacebookAccount(config, digits, verbose) {
134897
134656
  verbose
134898
134657
  );
134899
134658
  }
134900
- async function fetchFacebookPagedList(config, digits, path49, opts) {
134659
+ async function fetchFacebookPagedList(config, digits, path48, opts) {
134901
134660
  const base = requireFacebookApi(config);
134902
134661
  const items2 = [];
134903
134662
  let after;
@@ -134912,7 +134671,7 @@ async function fetchFacebookPagedList(config, digits, path49, opts) {
134912
134671
  adsetId: opts.adsetId
134913
134672
  });
134914
134673
  const raw = await apiFetch2(
134915
- `${facebookAdsUrl(base, digits, path49)}?${query}`,
134674
+ `${facebookAdsUrl(base, digits, path48)}?${query}`,
134916
134675
  config,
134917
134676
  {},
134918
134677
  opts.verbose
@@ -135047,7 +134806,7 @@ async function runFacebookEntityList(opts, kind) {
135047
134806
  }
135048
134807
  const pageSize = resolveFacebookPageSize(opts.pageSize);
135049
134808
  const config = loadConfig(opts.token);
135050
- const path49 = `/${kind}`;
134809
+ const path48 = `/${kind}`;
135051
134810
  const labels = {
135052
134811
  campaigns: {
135053
134812
  section: "facebook-campaign-entities",
@@ -135060,7 +134819,7 @@ async function runFacebookEntityList(opts, kind) {
135060
134819
  const meta = labels[kind];
135061
134820
  let result;
135062
134821
  try {
135063
- result = await fetchFacebookPagedList(config, manifestId, path49, {
134822
+ result = await fetchFacebookPagedList(config, manifestId, path48, {
135064
134823
  pageSize,
135065
134824
  verbose: !!opts.verbose,
135066
134825
  effectiveStatus,
@@ -135793,7 +135552,7 @@ function endpointHintForBingSection(def) {
135793
135552
 
135794
135553
  // src/commands/bing-analysis/run-batch.ts
135795
135554
  init_auth();
135796
- import * as path39 from "path";
135555
+ import * as path38 from "path";
135797
135556
  import { performance as performance6 } from "perf_hooks";
135798
135557
  init_version();
135799
135558
  async function runWithConcurrency4(tasks, concurrency) {
@@ -135868,7 +135627,7 @@ async function runAllBingSections(opts) {
135868
135627
  const results = await runWithConcurrency4(tasks, concurrency);
135869
135628
  const succeeded = results.filter((r) => r.ok).length;
135870
135629
  const failed = results.length - succeeded;
135871
- const absoluteSnapshotDir = path39.resolve(opts.jsonOut);
135630
+ const absoluteSnapshotDir = path38.resolve(opts.jsonOut);
135872
135631
  const summary = {
135873
135632
  kind: "siluzan-tso-bing-analysis-snapshot-batch",
135874
135633
  absoluteSnapshotDir,
@@ -136212,14 +135971,14 @@ Bing \u5B98\u65B9\u6708\u6D88\u8017\uFF08${id}\uFF09
136212
135971
  import { Command as Command3 } from "commander";
136213
135972
 
136214
135973
  // src/commands/bing-analysis/render-report.ts
136215
- import fs32 from "fs";
135974
+ import fs31 from "fs";
136216
135975
  import fsPromises5 from "fs/promises";
136217
- import path41 from "path";
135976
+ import path40 from "path";
136218
135977
  import { fileURLToPath as fileURLToPath9 } from "url";
136219
135978
 
136220
135979
  // src/commands/bing-analysis/merge-snapshot.ts
136221
- import * as fs31 from "fs/promises";
136222
- import * as path40 from "path";
135980
+ import * as fs30 from "fs/promises";
135981
+ import * as path39 from "path";
136223
135982
  function asRecord22(value) {
136224
135983
  if (value && typeof value === "object" && !Array.isArray(value)) {
136225
135984
  return value;
@@ -136241,7 +136000,7 @@ function asRows2(value) {
136241
136000
  }
136242
136001
  async function loadSectionPayload(snapshotDir, file) {
136243
136002
  try {
136244
- const raw = await fs31.readFile(path40.join(snapshotDir, file), "utf8");
136003
+ const raw = await fs30.readFile(path39.join(snapshotDir, file), "utf8");
136245
136004
  return JSON.parse(raw);
136246
136005
  } catch {
136247
136006
  return null;
@@ -136251,7 +136010,7 @@ async function readManifest4(snapshotDir, accountId) {
136251
136010
  const candidates = [];
136252
136011
  if (accountId) candidates.push(reportManifestFile(accountId));
136253
136012
  try {
136254
- const entries = await fs31.readdir(snapshotDir);
136013
+ const entries = await fs30.readdir(snapshotDir);
136255
136014
  const manifestNames = entries.filter(
136256
136015
  (n) => n.startsWith("report-manifest") && n.endsWith(".json")
136257
136016
  );
@@ -136262,7 +136021,7 @@ async function readManifest4(snapshotDir, accountId) {
136262
136021
  }
136263
136022
  for (const name2 of candidates) {
136264
136023
  try {
136265
- const raw = await fs31.readFile(path40.join(snapshotDir, name2), "utf8");
136024
+ const raw = await fs30.readFile(path39.join(snapshotDir, name2), "utf8");
136266
136025
  const parsed = JSON.parse(raw);
136267
136026
  if (Array.isArray(parsed.artifacts) && parsed.artifacts.length > 0) return parsed;
136268
136027
  } catch {
@@ -136411,7 +136170,7 @@ function mapSearchTermRows(payload) {
136411
136170
  );
136412
136171
  }
136413
136172
  async function mergeBingAnalysisSnapshotIntoReport(payload, snapshotDir) {
136414
- const absDir = path40.resolve(snapshotDir);
136173
+ const absDir = path39.resolve(snapshotDir);
136415
136174
  const metaAccountId = typeof asRecord22(payload.meta)?.accountId === "string" ? asRecord22(payload.meta)?.accountId : void 0;
136416
136175
  const manifest = await readManifest4(snapshotDir, metaAccountId);
136417
136176
  if (!manifest) {
@@ -136646,14 +136405,14 @@ function formatBingPeriodReportErrors(result) {
136646
136405
  var TEMPLATE_BASENAME3 = "bing-period-report.html";
136647
136406
  var INJECT_MARKER4 = "window.__BING_PERIOD_REPORT__ = window.__BING_PERIOD_REPORT__ || null;";
136648
136407
  function resolveSkillTemplatePath6(basename13) {
136649
- const dir = path41.dirname(fileURLToPath9(import.meta.url));
136408
+ const dir = path40.dirname(fileURLToPath9(import.meta.url));
136650
136409
  const candidates = [
136651
- path41.join(dir, "skill", "report-templates", basename13),
136652
- path41.join(dir, "skill", "siluzan-ads", "report-templates", basename13),
136653
- path41.join(dir, "..", "..", "assets", "siluzan-ads", "report-templates", basename13)
136410
+ path40.join(dir, "skill", "report-templates", basename13),
136411
+ path40.join(dir, "skill", "siluzan-ads", "report-templates", basename13),
136412
+ path40.join(dir, "..", "..", "assets", "siluzan-ads", "report-templates", basename13)
136654
136413
  ];
136655
136414
  for (const p of candidates) {
136656
- if (fs32.existsSync(p)) return p;
136415
+ if (fs31.existsSync(p)) return p;
136657
136416
  }
136658
136417
  return candidates[0];
136659
136418
  }
@@ -136682,10 +136441,10 @@ function injectReportData5(html, payload) {
136682
136441
  return html.replace(INJECT_MARKER4, `window.__BING_PERIOD_REPORT__ = ${json};`);
136683
136442
  }
136684
136443
  async function runBingAnalysisRender(opts) {
136685
- const dataPath = path41.resolve(opts.dataFile);
136444
+ const dataPath = path40.resolve(opts.dataFile);
136686
136445
  let data = asRecord24(await readJsonFile5(dataPath));
136687
136446
  if (opts.snapshotDir?.trim()) {
136688
- data = await mergeBingAnalysisSnapshotIntoReport(data, path41.resolve(opts.snapshotDir));
136447
+ data = await mergeBingAnalysisSnapshotIntoReport(data, path40.resolve(opts.snapshotDir));
136689
136448
  }
136690
136449
  const contentCheck = validateBingPeriodReportContent(data);
136691
136450
  if (!contentCheck.ok) {
@@ -136711,10 +136470,10 @@ async function runBingAnalysisRender(opts) {
136711
136470
  `);
136712
136471
  process.exit(1);
136713
136472
  }
136714
- const outPath = path41.resolve(
136715
- opts.out ?? path41.join(path41.dirname(dataPath), "bing-period-report.html")
136473
+ const outPath = path40.resolve(
136474
+ opts.out ?? path40.join(path40.dirname(dataPath), "bing-period-report.html")
136716
136475
  );
136717
- const outDir = path41.dirname(outPath);
136476
+ const outDir = path40.dirname(outPath);
136718
136477
  await fsPromises5.mkdir(outDir, { recursive: true });
136719
136478
  await fsPromises5.writeFile(outPath, injectReportData5(html, data), "utf8");
136720
136479
  const { stats } = contentCheck;
@@ -137050,7 +136809,7 @@ async function fetchTikTokInterestList(config, account, verbose) {
137050
136809
 
137051
136810
  // src/commands/tiktok-analysis/run-batch.ts
137052
136811
  init_auth();
137053
- import * as path42 from "path";
136812
+ import * as path41 from "path";
137054
136813
  import { performance as performance7 } from "perf_hooks";
137055
136814
  init_version();
137056
136815
  async function runWithConcurrency5(tasks, concurrency) {
@@ -137125,7 +136884,7 @@ async function runAllTikTokSections(opts) {
137125
136884
  const results = await runWithConcurrency5(tasks, concurrency);
137126
136885
  const succeeded = results.filter((r) => r.ok).length;
137127
136886
  const failed = results.length - succeeded;
137128
- const absoluteSnapshotDir = path42.resolve(opts.jsonOut);
136887
+ const absoluteSnapshotDir = path41.resolve(opts.jsonOut);
137129
136888
  const summary = {
137130
136889
  kind: "siluzan-tso-tiktok-analysis-snapshot-batch",
137131
136890
  absoluteSnapshotDir,
@@ -137148,14 +136907,14 @@ init_auth();
137148
136907
  import { Command as Command4 } from "commander";
137149
136908
 
137150
136909
  // src/commands/tiktok-analysis/render-report.ts
137151
- import fs34 from "fs";
136910
+ import fs33 from "fs";
137152
136911
  import fsPromises6 from "fs/promises";
137153
- import path44 from "path";
136912
+ import path43 from "path";
137154
136913
  import { fileURLToPath as fileURLToPath10 } from "url";
137155
136914
 
137156
136915
  // src/commands/tiktok-analysis/merge-snapshot.ts
137157
- import * as fs33 from "fs/promises";
137158
- import * as path43 from "path";
136916
+ import * as fs32 from "fs/promises";
136917
+ import * as path42 from "path";
137159
136918
  function asRecord25(value) {
137160
136919
  if (value && typeof value === "object" && !Array.isArray(value)) {
137161
136920
  return value;
@@ -137171,7 +136930,7 @@ function round24(value) {
137171
136930
  }
137172
136931
  async function loadSectionPayload2(snapshotDir, file) {
137173
136932
  try {
137174
- const raw = await fs33.readFile(path43.join(snapshotDir, file), "utf8");
136933
+ const raw = await fs32.readFile(path42.join(snapshotDir, file), "utf8");
137175
136934
  return JSON.parse(raw);
137176
136935
  } catch {
137177
136936
  return null;
@@ -137181,7 +136940,7 @@ async function readManifest5(snapshotDir, accountId) {
137181
136940
  const candidates = [];
137182
136941
  if (accountId) candidates.push(reportManifestFile(accountId));
137183
136942
  try {
137184
- const entries = await fs33.readdir(snapshotDir);
136943
+ const entries = await fs32.readdir(snapshotDir);
137185
136944
  const manifestNames = entries.filter(
137186
136945
  (n) => n.startsWith("report-manifest") && n.endsWith(".json")
137187
136946
  );
@@ -137192,7 +136951,7 @@ async function readManifest5(snapshotDir, accountId) {
137192
136951
  }
137193
136952
  for (const name2 of candidates) {
137194
136953
  try {
137195
- const raw = await fs33.readFile(path43.join(snapshotDir, name2), "utf8");
136954
+ const raw = await fs32.readFile(path42.join(snapshotDir, name2), "utf8");
137196
136955
  const parsed = JSON.parse(raw);
137197
136956
  if (Array.isArray(parsed.artifacts) && parsed.artifacts.length > 0) return parsed;
137198
136957
  } catch {
@@ -137333,7 +137092,7 @@ function mapAudienceMerged(payload) {
137333
137092
  };
137334
137093
  }
137335
137094
  async function mergeTikTokAnalysisSnapshotIntoReport(payload, snapshotDir) {
137336
- const absDir = path43.resolve(snapshotDir);
137095
+ const absDir = path42.resolve(snapshotDir);
137337
137096
  const metaAccountId = typeof asRecord25(payload.meta)?.accountId === "string" ? asRecord25(payload.meta)?.accountId : void 0;
137338
137097
  const manifest = await readManifest5(snapshotDir, metaAccountId);
137339
137098
  if (!manifest) {
@@ -137543,14 +137302,14 @@ function formatTikTokPeriodReportErrors(result) {
137543
137302
  var TEMPLATE_BASENAME4 = "tiktok-period-report.html";
137544
137303
  var INJECT_MARKER5 = "window.__TIKTOK_PERIOD_REPORT__ = window.__TIKTOK_PERIOD_REPORT__ || null;";
137545
137304
  function resolveSkillTemplatePath7(basename13) {
137546
- const dir = path44.dirname(fileURLToPath10(import.meta.url));
137305
+ const dir = path43.dirname(fileURLToPath10(import.meta.url));
137547
137306
  const candidates = [
137548
- path44.join(dir, "skill", "report-templates", basename13),
137549
- path44.join(dir, "skill", "siluzan-ads", "report-templates", basename13),
137550
- path44.join(dir, "..", "..", "assets", "siluzan-ads", "report-templates", basename13)
137307
+ path43.join(dir, "skill", "report-templates", basename13),
137308
+ path43.join(dir, "skill", "siluzan-ads", "report-templates", basename13),
137309
+ path43.join(dir, "..", "..", "assets", "siluzan-ads", "report-templates", basename13)
137551
137310
  ];
137552
137311
  for (const p of candidates) {
137553
- if (fs34.existsSync(p)) return p;
137312
+ if (fs33.existsSync(p)) return p;
137554
137313
  }
137555
137314
  return candidates[0];
137556
137315
  }
@@ -137579,10 +137338,10 @@ function injectReportData6(html, payload) {
137579
137338
  return html.replace(INJECT_MARKER5, `window.__TIKTOK_PERIOD_REPORT__ = ${json};`);
137580
137339
  }
137581
137340
  async function runTikTokAnalysisRender(opts) {
137582
- const dataPath = path44.resolve(opts.dataFile);
137341
+ const dataPath = path43.resolve(opts.dataFile);
137583
137342
  let data = asRecord27(await readJsonFile6(dataPath));
137584
137343
  if (opts.snapshotDir?.trim()) {
137585
- data = await mergeTikTokAnalysisSnapshotIntoReport(data, path44.resolve(opts.snapshotDir));
137344
+ data = await mergeTikTokAnalysisSnapshotIntoReport(data, path43.resolve(opts.snapshotDir));
137586
137345
  }
137587
137346
  const contentCheck = validateTikTokPeriodReportContent(data);
137588
137347
  if (!contentCheck.ok) {
@@ -137608,10 +137367,10 @@ async function runTikTokAnalysisRender(opts) {
137608
137367
  `);
137609
137368
  process.exit(1);
137610
137369
  }
137611
- const outPath = path44.resolve(
137612
- opts.out ?? path44.join(path44.dirname(dataPath), "tiktok-period-report.html")
137370
+ const outPath = path43.resolve(
137371
+ opts.out ?? path43.join(path43.dirname(dataPath), "tiktok-period-report.html")
137613
137372
  );
137614
- const outDir = path44.dirname(outPath);
137373
+ const outDir = path43.dirname(outPath);
137615
137374
  await fsPromises6.mkdir(outDir, { recursive: true });
137616
137375
  await fsPromises6.writeFile(outPath, injectReportData6(html, data), "utf8");
137617
137376
  const { stats } = contentCheck;
@@ -138537,7 +138296,7 @@ var YANDEX_SECTION_ALIASES = {
138537
138296
 
138538
138297
  // src/commands/yandex-analysis/run-batch.ts
138539
138298
  init_auth();
138540
- import * as path46 from "path";
138299
+ import * as path45 from "path";
138541
138300
  import { performance as performance8 } from "perf_hooks";
138542
138301
  init_version();
138543
138302
 
@@ -138677,8 +138436,8 @@ function endpointHintForYandexSection(def) {
138677
138436
  }
138678
138437
 
138679
138438
  // src/commands/yandex-analysis/merge-snapshot.ts
138680
- import * as fs35 from "fs/promises";
138681
- import * as path45 from "path";
138439
+ import * as fs34 from "fs/promises";
138440
+ import * as path44 from "path";
138682
138441
  function asRecord28(value) {
138683
138442
  if (value && typeof value === "object" && !Array.isArray(value)) {
138684
138443
  return value;
@@ -138728,7 +138487,7 @@ function pickMetrics2(row, extras = []) {
138728
138487
  }
138729
138488
  async function loadSectionPayload3(snapshotDir, file) {
138730
138489
  try {
138731
- const raw = await fs35.readFile(path45.join(snapshotDir, file), "utf8");
138490
+ const raw = await fs34.readFile(path44.join(snapshotDir, file), "utf8");
138732
138491
  return JSON.parse(raw);
138733
138492
  } catch {
138734
138493
  return null;
@@ -138738,7 +138497,7 @@ async function readManifest6(snapshotDir, accountId) {
138738
138497
  const candidates = [];
138739
138498
  if (accountId) candidates.push(reportManifestFile(accountId));
138740
138499
  try {
138741
- const entries = await fs35.readdir(snapshotDir);
138500
+ const entries = await fs34.readdir(snapshotDir);
138742
138501
  for (const name2 of entries.filter(
138743
138502
  (n) => n.startsWith("report-manifest") && n.endsWith(".json")
138744
138503
  )) {
@@ -138748,7 +138507,7 @@ async function readManifest6(snapshotDir, accountId) {
138748
138507
  }
138749
138508
  for (const name2 of candidates) {
138750
138509
  try {
138751
- const raw = await fs35.readFile(path45.join(snapshotDir, name2), "utf8");
138510
+ const raw = await fs34.readFile(path44.join(snapshotDir, name2), "utf8");
138752
138511
  const parsed = JSON.parse(raw);
138753
138512
  if (Array.isArray(parsed.artifacts) && parsed.artifacts.length > 0) return parsed;
138754
138513
  } catch {
@@ -138907,7 +138666,7 @@ function mapDeviceRows2(payload) {
138907
138666
  return asItems(payload).map((r) => pickMetrics2(r, ["device", "network"]));
138908
138667
  }
138909
138668
  async function mergeYandexAnalysisSnapshotIntoReport(payload, snapshotDir) {
138910
- const absDir = path45.resolve(snapshotDir);
138669
+ const absDir = path44.resolve(snapshotDir);
138911
138670
  const metaAccountId = typeof asRecord28(payload.meta)?.accountId === "string" ? asRecord28(payload.meta)?.accountId : void 0;
138912
138671
  const manifest = await readManifest6(snapshotDir, metaAccountId);
138913
138672
  if (!manifest) {
@@ -139093,7 +138852,7 @@ async function runAllYandexSections(opts) {
139093
138852
  const results = await runWithConcurrency6(tasks, concurrency);
139094
138853
  const succeeded = results.filter((r) => r.ok).length;
139095
138854
  const failed = results.length - succeeded;
139096
- const absoluteSnapshotDir = path46.resolve(opts.jsonOut);
138855
+ const absoluteSnapshotDir = path45.resolve(opts.jsonOut);
139097
138856
  const summary = {
139098
138857
  kind: "siluzan-tso-yandex-analysis-snapshot-batch",
139099
138858
  absoluteSnapshotDir,
@@ -139111,9 +138870,9 @@ async function runAllYandexSections(opts) {
139111
138870
  }
139112
138871
 
139113
138872
  // src/commands/yandex-analysis/render-report.ts
139114
- import fs36 from "fs";
138873
+ import fs35 from "fs";
139115
138874
  import fsPromises7 from "fs/promises";
139116
- import path47 from "path";
138875
+ import path46 from "path";
139117
138876
  import { fileURLToPath as fileURLToPath11 } from "url";
139118
138877
 
139119
138878
  // src/commands/yandex-analysis/report-content.ts
@@ -139317,14 +139076,14 @@ function formatYandexPeriodReportErrors(result) {
139317
139076
  var TEMPLATE_BASENAME5 = "yandex-period-report.html";
139318
139077
  var INJECT_MARKER6 = "window.__YANDEX_PERIOD_REPORT__ = window.__YANDEX_PERIOD_REPORT__ || null;";
139319
139078
  function resolveSkillTemplatePath8(basename13) {
139320
- const dir = path47.dirname(fileURLToPath11(import.meta.url));
139079
+ const dir = path46.dirname(fileURLToPath11(import.meta.url));
139321
139080
  const candidates = [
139322
- path47.join(dir, "skill", "report-templates", basename13),
139323
- path47.join(dir, "skill", "siluzan-ads", "report-templates", basename13),
139324
- path47.join(dir, "..", "..", "assets", "siluzan-ads", "report-templates", basename13)
139081
+ path46.join(dir, "skill", "report-templates", basename13),
139082
+ path46.join(dir, "skill", "siluzan-ads", "report-templates", basename13),
139083
+ path46.join(dir, "..", "..", "assets", "siluzan-ads", "report-templates", basename13)
139325
139084
  ];
139326
139085
  for (const p of candidates) {
139327
- if (fs36.existsSync(p)) return p;
139086
+ if (fs35.existsSync(p)) return p;
139328
139087
  }
139329
139088
  return candidates[0];
139330
139089
  }
@@ -139366,10 +139125,10 @@ function injectReportData7(html, payload) {
139366
139125
  return html.replace(INJECT_MARKER6, `window.__YANDEX_PERIOD_REPORT__ = ${json};`);
139367
139126
  }
139368
139127
  async function runYandexAnalysisRender(opts) {
139369
- const dataPath = path47.resolve(opts.dataFile);
139128
+ const dataPath = path46.resolve(opts.dataFile);
139370
139129
  let data = asRecord30(await readJsonFile7(dataPath));
139371
139130
  if (opts.snapshotDir?.trim()) {
139372
- data = await mergeYandexAnalysisSnapshotIntoReport(data, path47.resolve(opts.snapshotDir));
139131
+ data = await mergeYandexAnalysisSnapshotIntoReport(data, path46.resolve(opts.snapshotDir));
139373
139132
  }
139374
139133
  data = refreshWeeklyFromDaily(data);
139375
139134
  const contentCheck = validateYandexPeriodReportContent(data);
@@ -139394,10 +139153,10 @@ async function runYandexAnalysisRender(opts) {
139394
139153
  `);
139395
139154
  process.exit(1);
139396
139155
  }
139397
- const outPath = path47.resolve(
139398
- opts.out ?? path47.join(path47.dirname(dataPath), "yandex-period-report.html")
139156
+ const outPath = path46.resolve(
139157
+ opts.out ?? path46.join(path46.dirname(dataPath), "yandex-period-report.html")
139399
139158
  );
139400
- const outDir = path47.dirname(outPath);
139159
+ const outDir = path46.dirname(outPath);
139401
139160
  await fsPromises7.mkdir(outDir, { recursive: true });
139402
139161
  await fsPromises7.writeFile(outPath, injectReportData7(html, data), "utf8");
139403
139162
  const { stats } = contentCheck;
@@ -139411,7 +139170,472 @@ async function runYandexAnalysisRender(opts) {
139411
139170
  console.log("\u5728\u6D4F\u89C8\u5668\u4E2D\u6253\u5F00 HTML \u6587\u4EF6\u5373\u53EF\u67E5\u770B\u5B8C\u6574\u7AE0\u8282\uFF08\u6837\u5F0F\u5BF9\u9F50\u5F00\u53D1\u6837\u4F8B\uFF09\u3002\n");
139412
139171
  }
139413
139172
 
139173
+ // src/commands/yandex-analysis/entities.ts
139174
+ init_auth();
139175
+ init_cli_json_snapshot();
139176
+ init_cli_table();
139177
+
139178
+ // src/commands/yandex-analysis/yandex-api.ts
139179
+ init_auth();
139180
+ var YANDEX_AD_STATUSES = [
139181
+ "DRAFT",
139182
+ "MODERATION",
139183
+ "PREACCEPTED",
139184
+ "ACCEPTED",
139185
+ "REJECTED",
139186
+ "UNKNOWN"
139187
+ ];
139188
+ var YANDEX_INSIGHTS_LEVELS = [
139189
+ "daily",
139190
+ "geo",
139191
+ "devices",
139192
+ "keywords",
139193
+ "campaigns",
139194
+ "adgroups",
139195
+ "ads"
139196
+ ];
139197
+ var YANDEX_PATH_CAPS = {
139198
+ overview: {},
139199
+ daily: {},
139200
+ campaigns: { limit: true, timeIncrement: true, network: true },
139201
+ adgroups: { limit: true, timeIncrement: true, campaignId: true },
139202
+ ads: { limit: true, timeIncrement: true, status: true, campaignId: true, adGroupId: true },
139203
+ keywords: { limit: true },
139204
+ geo: { limit: true, network: true },
139205
+ devices: { network: true }
139206
+ };
139207
+ function localYmd(d = /* @__PURE__ */ new Date()) {
139208
+ const y = d.getFullYear();
139209
+ const m = String(d.getMonth() + 1).padStart(2, "0");
139210
+ const day = String(d.getDate()).padStart(2, "0");
139211
+ return `${y}-${m}-${day}`;
139212
+ }
139213
+ function parseYandexTimeIncrement(raw) {
139214
+ if (raw == null || String(raw).trim() === "") return void 0;
139215
+ const t = String(raw).trim();
139216
+ if (t !== "1") {
139217
+ throw new Error("--time-increment \u53EA\u5141\u8BB8 1\uFF08\u6309\u65E5\uFF09\uFF1B\u4E0D\u4F20=\u533A\u95F4\u6C47\u603B\u3002Direct \u6CA1\u6709\u5C0F\u65F6\u7EF4\u5EA6\u3002");
139218
+ }
139219
+ return 1;
139220
+ }
139221
+ function parseYandexNetwork(raw) {
139222
+ if (raw == null || String(raw).trim() === "") return void 0;
139223
+ const t = String(raw).trim().toUpperCase();
139224
+ if (t !== "SEARCH" && t !== "ALL") {
139225
+ throw new Error(
139226
+ "--network \u53EA\u5141\u8BB8 SEARCH \u6216 ALL\uFF08\u9ED8\u8BA4 SEARCH\uFF1BALL=\u5168\u7F51\u4E00\u884C\u5408\u8BA1\uFF0C\u884C\u5185 network \u4E3A null\uFF09\u3002"
139227
+ );
139228
+ }
139229
+ return t;
139230
+ }
139231
+ function parseYandexAdStatus(raw) {
139232
+ if (raw == null || String(raw).trim() === "") return void 0;
139233
+ const parts = String(raw).split(",").map((x) => x.trim().toUpperCase()).filter(Boolean);
139234
+ if (parts.length === 0) return void 0;
139235
+ const unknown = parts.filter((p) => !YANDEX_AD_STATUSES.includes(p));
139236
+ if (unknown.length > 0) {
139237
+ throw new Error(
139238
+ `--status \u975E\u6CD5\u503C\uFF1A${unknown.join(", ")}\u3002\u5408\u6CD5\uFF1A${YANDEX_AD_STATUSES.join(", ")}\u3002`
139239
+ );
139240
+ }
139241
+ return [...new Set(parts)].join(",");
139242
+ }
139243
+ function parseYandexInsightsLevel(raw) {
139244
+ const t = raw.trim();
139245
+ if (!YANDEX_INSIGHTS_LEVELS.includes(t)) {
139246
+ throw new Error(
139247
+ `--level \u53EA\u5141\u8BB8 ${YANDEX_INSIGHTS_LEVELS.join(" / ")}\uFF08daily/geo/devices/keywords \u6216\u4E0E\u5B9E\u4F53\u5B50\u547D\u4EE4\u540C\u53E3\u5F84\u7684 campaigns/adgroups/ads\uFF09\u3002`
139248
+ );
139249
+ }
139250
+ return t;
139251
+ }
139252
+ function optionalId(raw) {
139253
+ const t = raw?.trim();
139254
+ return t ? t : void 0;
139255
+ }
139256
+ function insightsLevelToPath(level) {
139257
+ return level;
139258
+ }
139259
+ function assertYandexAnalysisQuery(path48, query) {
139260
+ const caps = YANDEX_PATH_CAPS[path48];
139261
+ if (query.timeIncrement != null && !caps.timeIncrement) {
139262
+ throw new Error(`--time-increment \u4E0D\u80FD\u7528\u4E8E /${path48}\uFF08\u4EC5 campaigns / adgroups / ads\uFF09\u3002`);
139263
+ }
139264
+ if (query.network != null && !caps.network) {
139265
+ throw new Error(`--network \u4E0D\u80FD\u7528\u4E8E /${path48}\uFF08\u4EC5 campaigns / geo / devices\uFF09\u3002`);
139266
+ }
139267
+ if (query.status != null && !caps.status) {
139268
+ throw new Error(`--status \u4EC5\u7528\u4E8E /ads\uFF08\u62D2\u5BA1/\u5BA1\u6838\u6001\u8D70\u7ED3\u6784\u67E5\u8BE2\uFF0C\u884C\u5185 spend \u4E3A 0\uFF09\u3002`);
139269
+ }
139270
+ if (query.campaignId != null && !caps.campaignId) {
139271
+ throw new Error(`--campaign-id \u4EC5\u7528\u4E8E /adgroups \u4E0E /ads\u3002`);
139272
+ }
139273
+ if (query.adGroupId != null && !caps.adGroupId) {
139274
+ throw new Error(`--adgroup-id \u4EC5\u7528\u4E8E /ads\u3002`);
139275
+ }
139276
+ if (query.status != null && query.timeIncrement != null) {
139277
+ throw new Error(
139278
+ "--status \u4E0E --time-increment \u4E0D\u80FD\u540C\u65F6\u4F20\uFF08\u7F51\u5173 400\uFF09\u3002\u62D2\u5BA1\u7528\u533A\u95F4\u6C47\u603B\uFF0C\u4E0D\u8981\u52A0\u6309\u65E5\u3002"
139279
+ );
139280
+ }
139281
+ if (query.limit != null && !caps.limit) {
139282
+ throw new Error(`--limit \u4E0D\u80FD\u7528\u4E8E /${path48}\uFF08overview / daily / devices \u65E0\u6B64\u53C2\u6570\uFF09\u3002`);
139283
+ }
139284
+ }
139285
+ function buildYandexAnalysisSearchParams(path48, query) {
139286
+ assertYandexAnalysisQuery(path48, query);
139287
+ const caps = YANDEX_PATH_CAPS[path48];
139288
+ const params = new URLSearchParams({
139289
+ account: query.account,
139290
+ start: query.start,
139291
+ end: query.end
139292
+ });
139293
+ if (caps.limit && query.limit != null) {
139294
+ params.set("limit", String(resolveYandexLimit(query.limit)));
139295
+ }
139296
+ if (caps.timeIncrement && query.timeIncrement === 1) {
139297
+ params.set("timeIncrement", "1");
139298
+ }
139299
+ if (caps.network && query.network) {
139300
+ params.set("network", query.network);
139301
+ }
139302
+ if (caps.status && query.status) {
139303
+ params.set("status", query.status);
139304
+ }
139305
+ if (caps.campaignId && query.campaignId) {
139306
+ params.set("campaignId", query.campaignId);
139307
+ }
139308
+ if (caps.adGroupId && query.adGroupId) {
139309
+ params.set("adGroupId", query.adGroupId);
139310
+ }
139311
+ return params;
139312
+ }
139313
+ async function fetchYandexAnalysisPath(config, path48, query, verbose) {
139314
+ const yandexApiUrl = requireYandexApi(config);
139315
+ const params = buildYandexAnalysisSearchParams(path48, query);
139316
+ const url = analysisUrl(yandexApiUrl, path48, params.toString());
139317
+ return apiFetch2(url, config, {}, verbose);
139318
+ }
139319
+ function unwrapYandexItems(raw) {
139320
+ if (raw && typeof raw === "object" && Array.isArray(raw.items)) {
139321
+ return raw.items;
139322
+ }
139323
+ return [];
139324
+ }
139325
+ function asRecord31(raw) {
139326
+ return raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
139327
+ }
139328
+
139329
+ // src/commands/yandex-analysis/entities.ts
139330
+ function fail3(label, err) {
139331
+ const msg = err instanceof Error ? err.message : String(err);
139332
+ console.error(`
139333
+ \u274C ${label}\uFF1A${msg}
139334
+ `);
139335
+ process.exit(1);
139336
+ }
139337
+ function cell2(value) {
139338
+ if (value == null || value === "") return "";
139339
+ if (Array.isArray(value)) return value.map((x) => String(x)).join(" | ");
139340
+ return String(value);
139341
+ }
139342
+ function resolveRange(start, end) {
139343
+ if (!start && !end) {
139344
+ const today = localYmd();
139345
+ return resolveYandexDateRange(today, today);
139346
+ }
139347
+ return resolveYandexDateRange(start, end);
139348
+ }
139349
+ function parseCommonFlags(opts) {
139350
+ return {
139351
+ timeIncrement: parseYandexTimeIncrement(opts.timeIncrement),
139352
+ network: parseYandexNetwork(opts.network),
139353
+ status: parseYandexAdStatus(opts.status),
139354
+ campaignId: optionalId(opts.campaignId),
139355
+ adGroupId: optionalId(opts.adGroupId)
139356
+ };
139357
+ }
139358
+ async function emitOrTable(opts, args) {
139359
+ if (await emitCliJsonOrSnapshot(opts, {
139360
+ section: args.section,
139361
+ commandLabel: args.commandLabel,
139362
+ commandHint: args.accountId,
139363
+ payload: args.payload,
139364
+ idSuffix: args.accountId
139365
+ })) {
139366
+ return;
139367
+ }
139368
+ console.log(`
139369
+ ${args.title}
139370
+ `);
139371
+ if (args.rows.length === 0) {
139372
+ console.log(` ${args.empty}
139373
+ `);
139374
+ return;
139375
+ }
139376
+ printCliTable(args.rows, args.columns);
139377
+ console.log(` ${args.footnote}
139378
+ `);
139379
+ }
139380
+ async function fetchPath(opts, path48, extra) {
139381
+ const accountId = assertYandexAccountId(opts.account);
139382
+ const { startDate, endDate } = resolveRange(opts.start, opts.end);
139383
+ const config = loadConfig(opts.token);
139384
+ const raw = await fetchYandexAnalysisPath(
139385
+ config,
139386
+ path48,
139387
+ {
139388
+ account: accountId,
139389
+ start: startDate,
139390
+ end: endDate,
139391
+ ...extra
139392
+ },
139393
+ !!opts.verbose
139394
+ );
139395
+ return { accountId, startDate, endDate, raw };
139396
+ }
139397
+ async function runYandexAccountStatus(opts) {
139398
+ let result;
139399
+ try {
139400
+ result = await fetchPath(opts, "overview", {});
139401
+ } catch (err) {
139402
+ fail3("\u67E5\u8BE2 Yandex \u8D26\u6237\u603B\u89C8\u5931\u8D25", err);
139403
+ }
139404
+ const row = asRecord31(result.raw);
139405
+ await emitOrTable(opts, {
139406
+ section: "yandex-account-status",
139407
+ commandLabel: "yandex-analysis account-status",
139408
+ accountId: result.accountId,
139409
+ payload: result.raw,
139410
+ title: `Yandex \u8D26\u6237\u603B\u89C8\uFF08${result.accountId}\uFF0C${result.startDate}~${result.endDate}\uFF09`,
139411
+ empty: "\u65E0\u603B\u89C8\u6570\u636E\u3002",
139412
+ footnote: "archived=true \u8868\u793A\u5E7F\u544A\u4E3B\u5DF2\u5F52\u6863\uFF08inactive\uFF09\u3002\u5B98\u65B9\u65E0\u5C01\u6237\u72B6\u6001\u4E0E\u539F\u56E0\u3002\u4F59\u989D\u770B balance / currency\uFF1B\u5B98\u65B9\u65E0\u72EC\u7ACB\u989D\u5EA6\u3002",
139413
+ rows: [
139414
+ {
139415
+ account: cell2(row.account ?? result.accountId),
139416
+ archived: cell2(row.archived),
139417
+ balance: cell2(row.balance),
139418
+ currency: cell2(row.currency),
139419
+ spend: cell2(row.spend),
139420
+ conversions: cell2(row.conversions)
139421
+ }
139422
+ ],
139423
+ columns: [
139424
+ { key: "account", header: "\u8D26\u6237" },
139425
+ { key: "archived", header: "archived" },
139426
+ { key: "balance", header: "\u4F59\u989D" },
139427
+ { key: "currency", header: "\u5E01\u79CD" },
139428
+ { key: "spend", header: "\u533A\u95F4\u82B1\u8D39" },
139429
+ { key: "conversions", header: "\u8F6C\u5316" }
139430
+ ]
139431
+ });
139432
+ }
139433
+ async function runYandexCampaignEntities(opts) {
139434
+ let flags;
139435
+ let result;
139436
+ try {
139437
+ flags = parseCommonFlags(opts);
139438
+ result = await fetchPath(opts, "campaigns", {
139439
+ limit: opts.limit,
139440
+ timeIncrement: flags.timeIncrement,
139441
+ network: flags.network
139442
+ });
139443
+ } catch (err) {
139444
+ fail3("\u67E5\u8BE2 Yandex \u7CFB\u5217\u5931\u8D25", err);
139445
+ }
139446
+ const items2 = unwrapYandexItems(result.raw);
139447
+ await emitOrTable(opts, {
139448
+ section: "yandex-campaign-entities",
139449
+ commandLabel: "yandex-analysis campaign-entities",
139450
+ accountId: result.accountId,
139451
+ payload: result.raw,
139452
+ title: `Yandex \u5E7F\u544A\u7CFB\u5217\uFF08${result.accountId}\uFF0C${result.startDate}~${result.endDate}\uFF0C\u5171 ${items2.length} \u884C\uFF09`,
139453
+ empty: "\u5F53\u524D\u8FC7\u6EE4\u4E0B\u65E0\u7CFB\u5217\u884C\uFF08\u9ED8\u8BA4\u53EA\u51FA\u73B0\u6709\u6D88\u8017\u7684\u5BF9\u8C61\uFF09\u3002",
139454
+ footnote: "\u9ED8\u8BA4 SEARCH\u3002\u5168\u6E20\u9053\u82B1\u8D39\u987B --network ALL\uFF08\u884C\u5185 network \u4E3A null\uFF09\u3002budget \u662F\u7CFB\u5217\u65E5\u9884\u7B97\uFF0C\u81EA\u52A8\u7B56\u7565\u5E38\u4E3A\u7A7A\uFF1B\u5BF9\u7167 weeklyBudget\u3002\u81EA\u52A8\u51FA\u4EF7\u4E0D\u8981\u5F53\u624B\u52A8 CPC \u6539\u4EF7\u3002",
139455
+ rows: items2.map((r) => ({
139456
+ campaignId: cell2(r.campaignId),
139457
+ name: cell2(r.campaignName),
139458
+ spend: cell2(r.spend),
139459
+ budget: cell2(r.budget),
139460
+ weeklyBudget: cell2(r.weeklyBudget),
139461
+ strategy: cell2(r.strategy),
139462
+ targetCpa: cell2(r.targetCpa),
139463
+ status: cell2(r.status),
139464
+ date: cell2(r.date)
139465
+ })),
139466
+ columns: [
139467
+ { key: "campaignId", header: "\u7CFB\u5217ID" },
139468
+ { key: "name", header: "\u540D\u79F0" },
139469
+ { key: "spend", header: "spend" },
139470
+ { key: "budget", header: "\u65E5\u9884\u7B97" },
139471
+ { key: "weeklyBudget", header: "\u5468\u9884\u7B97" },
139472
+ { key: "strategy", header: "\u7B56\u7565" },
139473
+ { key: "targetCpa", header: "\u76EE\u6807CPA" },
139474
+ { key: "status", header: "\u72B6\u6001" },
139475
+ { key: "date", header: "date" }
139476
+ ]
139477
+ });
139478
+ }
139479
+ async function runYandexAdGroupEntities(opts) {
139480
+ let flags;
139481
+ let result;
139482
+ try {
139483
+ flags = parseCommonFlags(opts);
139484
+ result = await fetchPath(opts, "adgroups", {
139485
+ limit: opts.limit,
139486
+ timeIncrement: flags.timeIncrement,
139487
+ campaignId: flags.campaignId
139488
+ });
139489
+ } catch (err) {
139490
+ fail3("\u67E5\u8BE2 Yandex \u5E7F\u544A\u7EC4\u5931\u8D25", err);
139491
+ }
139492
+ const items2 = unwrapYandexItems(result.raw);
139493
+ await emitOrTable(opts, {
139494
+ section: "yandex-adgroup-entities",
139495
+ commandLabel: "yandex-analysis adgroup-entities",
139496
+ accountId: result.accountId,
139497
+ payload: result.raw,
139498
+ title: `Yandex \u5E7F\u544A\u7EC4\uFF08${result.accountId}\uFF0C${result.startDate}~${result.endDate}\uFF0C\u5171 ${items2.length} \u884C\uFF09`,
139499
+ empty: "\u5F53\u524D\u8FC7\u6EE4\u4E0B\u65E0\u5E7F\u544A\u7EC4\u884C\uFF08\u9ED8\u8BA4\u53EA\u51FA\u73B0\u6709\u6D88\u8017\u7684\u5BF9\u8C61\uFF09\u3002",
139500
+ footnote: "campaignTargetCpa \u662F\u7CFB\u5217\u76EE\u6807\uFF08\u53EA\u53D6 Search\uFF09\uFF0C\u4E0D\u662F\u7EC4\u7EA7\u76EE\u6807\u4EF7\u3002conversions<=0 \u65F6\u4E0D\u8981\u5224 CPA\u3002\u672C\u6279\u6CA1\u6709\u6539\u4EF7\u63A5\u53E3\u3002",
139501
+ rows: items2.map((r) => ({
139502
+ adGroupId: cell2(r.adGroupId),
139503
+ name: cell2(r.adGroupName),
139504
+ campaignId: cell2(r.campaignId),
139505
+ spend: cell2(r.spend),
139506
+ conversions: cell2(r.conversions),
139507
+ cpa: cell2(r.costPerConversion),
139508
+ targetCpa: cell2(r.campaignTargetCpa),
139509
+ weeklyBudget: cell2(r.campaignWeeklyBudget),
139510
+ strategy: cell2(r.campaignStrategy),
139511
+ date: cell2(r.date)
139512
+ })),
139513
+ columns: [
139514
+ { key: "adGroupId", header: "\u7EC4ID" },
139515
+ { key: "name", header: "\u540D\u79F0" },
139516
+ { key: "campaignId", header: "\u7CFB\u5217ID" },
139517
+ { key: "spend", header: "spend" },
139518
+ { key: "conversions", header: "\u8F6C\u5316" },
139519
+ { key: "cpa", header: "\u5B9E\u9645CPA" },
139520
+ { key: "targetCpa", header: "\u7CFB\u5217\u76EE\u6807CPA" },
139521
+ { key: "weeklyBudget", header: "\u7CFB\u5217\u5468\u9884\u7B97" },
139522
+ { key: "strategy", header: "\u7B56\u7565" },
139523
+ { key: "date", header: "date" }
139524
+ ]
139525
+ });
139526
+ }
139527
+ async function runYandexAdEntities(opts) {
139528
+ let flags;
139529
+ let result;
139530
+ try {
139531
+ flags = parseCommonFlags(opts);
139532
+ result = await fetchPath(opts, "ads", {
139533
+ limit: opts.limit,
139534
+ timeIncrement: flags.timeIncrement,
139535
+ status: flags.status,
139536
+ campaignId: flags.campaignId,
139537
+ adGroupId: flags.adGroupId
139538
+ });
139539
+ } catch (err) {
139540
+ fail3("\u67E5\u8BE2 Yandex \u5E7F\u544A\u5931\u8D25", err);
139541
+ }
139542
+ const items2 = unwrapYandexItems(result.raw);
139543
+ const filtered = flags.status != null;
139544
+ await emitOrTable(opts, {
139545
+ section: "yandex-ad-entities",
139546
+ commandLabel: "yandex-analysis ad-entities",
139547
+ accountId: result.accountId,
139548
+ payload: result.raw,
139549
+ title: `Yandex \u5E7F\u544A\uFF08${result.accountId}\uFF0C${result.startDate}~${result.endDate}\uFF0C\u5171 ${items2.length} \u884C\uFF09`,
139550
+ empty: filtered ? "\u5F53\u524D\u5BA1\u6838\u8FC7\u6EE4\u4E0B\u65E0\u8BB0\u5F55\uFF08\u7A7A\u5217\u8868=\u6210\u529F\u4E14\u6CA1\u6709\u672A\u5F52\u6863\u5339\u914D\u9879\uFF09\u3002" : "\u5F53\u524D\u8FC7\u6EE4\u4E0B\u65E0\u5E7F\u544A\u884C\uFF08\u9ED8\u8BA4\u53EA\u51FA\u73B0\u533A\u95F4\u5185\u6709\u6D88\u8017\u7684\u5E7F\u544A\uFF09\u3002",
139551
+ footnote: "landingUrls \u7A7A\u6570\u7EC4\u4E0D\u662F\u6B7B\u94FE\uFF08Dynamic/Smart/Shopping \u6216\u4EC5 TurboPage \u5E38\u4E3A []\uFF09\u3002CLI \u4E0D\u63A2\u6D3B HTTP\u3002\u62D2\u5BA1\u7528 --status REJECTED\uFF08\u4E0E --time-increment \u4E92\u65A5\uFF1B\u5DF2\u5F52\u6863\u4E0D\u4F1A\u51FA\u73B0\uFF09\u3002",
139552
+ rows: items2.map((r) => ({
139553
+ adId: cell2(r.adId),
139554
+ campaignId: cell2(r.campaignId),
139555
+ adGroupId: cell2(r.adGroupId),
139556
+ spend: cell2(r.spend),
139557
+ conversions: cell2(r.conversions),
139558
+ ctr: cell2(r.ctr),
139559
+ roi: cell2(r.roi),
139560
+ status: cell2(r.status),
139561
+ landing: cell2(r.landingUrls)
139562
+ })),
139563
+ columns: [
139564
+ { key: "adId", header: "\u5E7F\u544AID" },
139565
+ { key: "campaignId", header: "\u7CFB\u5217ID" },
139566
+ { key: "adGroupId", header: "\u7EC4ID" },
139567
+ { key: "spend", header: "spend" },
139568
+ { key: "conversions", header: "\u8F6C\u5316" },
139569
+ { key: "ctr", header: "ctr" },
139570
+ { key: "roi", header: "roi" },
139571
+ { key: "status", header: "\u5BA1\u6838\u6001" },
139572
+ { key: "landing", header: "\u843D\u5730\u9875" }
139573
+ ]
139574
+ });
139575
+ }
139576
+ async function runYandexInsights(opts) {
139577
+ let level;
139578
+ let flags;
139579
+ let result;
139580
+ try {
139581
+ level = parseYandexInsightsLevel(opts.level);
139582
+ flags = parseCommonFlags(opts);
139583
+ result = await fetchPath(opts, insightsLevelToPath(level), {
139584
+ limit: opts.limit,
139585
+ timeIncrement: flags.timeIncrement,
139586
+ network: flags.network,
139587
+ status: flags.status,
139588
+ campaignId: flags.campaignId,
139589
+ adGroupId: flags.adGroupId
139590
+ });
139591
+ } catch (err) {
139592
+ fail3("\u67E5\u8BE2 Yandex insights \u5931\u8D25", err);
139593
+ }
139594
+ const items2 = unwrapYandexItems(result.raw);
139595
+ await emitOrTable(opts, {
139596
+ section: "yandex-insights",
139597
+ commandLabel: "yandex-analysis insights",
139598
+ accountId: result.accountId,
139599
+ payload: result.raw,
139600
+ title: `Yandex insights ${level}\uFF08${result.accountId}\uFF0C${result.startDate}~${result.endDate}\uFF0C\u5171 ${items2.length} \u884C\uFF09`,
139601
+ empty: "\u65E0\u62A5\u8868\u884C\uFF08\u9ED8\u8BA4\u53EA\u51FA\u73B0\u533A\u95F4\u5185\u6709\u6D88\u8017\u7684\u5BF9\u8C61\uFF09\u3002",
139602
+ footnote: "revenue \u662F\u6210\u4EA4\u989D PurchaseRevenue\uFF0C\u4E0D\u662F\u76EE\u6807\u8D4B\u503C\u3002roi=(\u6210\u4EA4\u989D\u2212\u82B1\u8D39)/\u82B1\u8D39\u3002geo/devices \u9ED8\u8BA4 SEARCH\uFF0C\u5168\u7F51\u987B --network ALL\u3002\u65E0\u5C0F\u65F6\u7EF4\u5EA6\u3002",
139603
+ rows: items2.map((r) => ({
139604
+ id: cell2(
139605
+ r.adId ?? r.adGroupId ?? r.campaignId ?? r.keywordId ?? r.regionName ?? r.device ?? r.date
139606
+ ),
139607
+ name: cell2(
139608
+ r.adName ?? r.adGroupName ?? r.campaignName ?? r.keyword ?? r.regionName ?? r.device
139609
+ ),
139610
+ spend: cell2(r.spend),
139611
+ conversions: cell2(r.conversions),
139612
+ ctr: cell2(r.ctr),
139613
+ roi: cell2(r.roi),
139614
+ date: cell2(r.date)
139615
+ })),
139616
+ columns: [
139617
+ { key: "id", header: "\u5BF9\u8C61" },
139618
+ { key: "name", header: "\u540D\u79F0" },
139619
+ { key: "spend", header: "spend" },
139620
+ { key: "conversions", header: "\u8F6C\u5316" },
139621
+ { key: "ctr", header: "ctr" },
139622
+ { key: "roi", header: "roi" },
139623
+ { key: "date", header: "date" }
139624
+ ]
139625
+ });
139626
+ }
139627
+
139414
139628
  // src/commands/yandex-analysis/register-cli.ts
139629
+ var ACCOUNT_OPTION4 = [
139630
+ "-a, --account <id>",
139631
+ "Yandex Client-Login / mediaCustomerId\uFF08\u5982 porg-xxx\uFF0C\u4E0E list-accounts -m Yandex \u4E00\u81F4\uFF09"
139632
+ ];
139633
+ var JSON_OUT_OPTION_DESC4 = "\u843D\u76D8\uFF08\u76EE\u5F55\u6216 *.json \u6587\u4EF6\u8DEF\u5F84\uFF09\u5E76\u66F4\u65B0 cli-manifest[-<\u67E5\u8BE2id>].json\uFF1Bstdout \u4E00\u884C\u6458\u8981 JSON";
139634
+ var START_OPTION = [
139635
+ "--start <date>",
139636
+ "\u5F00\u59CB\u65E5\u671F YYYY-MM-DD\uFF08\u4E0E --end \u540C\u4F20\u6216\u540C\u7701\u7565\uFF1B\u7701\u7565=\u5F53\u5929\uFF09"
139637
+ ];
139638
+ var END_OPTION = ["--end <date>", "\u7ED3\u675F\u65E5\u671F YYYY-MM-DD"];
139415
139639
  function registerBatchCommand4(sectionHelp, aliasHelp) {
139416
139640
  return new Command5("run").description("\u6279\u91CF\u62C9\u53D6 YandexAPI /yandex-analysis \u5404\u7EF4\u5EA6\uFF08\u7701\u7565\u5B50\u547D\u4EE4\u540D\u65F6\u9ED8\u8BA4\u6267\u884C\u672C\u547D\u4EE4\uFF09").requiredOption(
139417
139641
  "-a, --account <id>",
@@ -139437,7 +139661,7 @@ function registerYandexAnalysisCommands(program2) {
139437
139661
  const sectionHelp = YANDEX_SECTION_NAMES.join(", ");
139438
139662
  const aliasHelp = Object.keys(YANDEX_SECTION_ALIASES).join(", ");
139439
139663
  const root = program2.command("yandex-analysis").description(
139440
- "Yandex \u8D26\u6237\u5206\u6790\uFF1A\u6279\u91CF\u62C9\u53D6 /yandex-analysis \u53EA\u8BFB\u6570\u636E\uFF08\u9ED8\u8BA4 run\uFF09\uFF0C\u6216\u7531 render \u751F\u6210 yandex-period-report.html \u7EC8\u7A3F\uFF08\u91D1\u989D\u5DF2\u4E3A\u8D26\u6237\u5E01\u79CD\u5C0F\u6570\uFF1Bsearch-terms \u4EC5\u8FD1 180 \u5929\uFF09"
139664
+ "Yandex \u8D26\u6237\u5206\u6790\uFF1A\u6279\u91CF\u62C9\u53D6 /yandex-analysis \u5468\u671F\u62A5\u8868\uFF08\u9ED8\u8BA4 run\uFF09\u3001render HTML\uFF0C\u6216\u67E5\u8BE2\u8D26\u6237\u5F52\u6863/\u7CFB\u5217/\u7EC4/\u5E7F\u544A/insights\uFF08\u53EA\u8BFB\u8FD0\u8425\uFF1B\u672C\u6279\u4E0D\u80FD\u6682\u505C/\u6539\u4EF7/\u6539\u9884\u7B97\uFF09"
139441
139665
  );
139442
139666
  root.addCommand(registerBatchCommand4(sectionHelp, aliasHelp), { isDefault: true });
139443
139667
  root.command("render").description(
@@ -139452,6 +139676,44 @@ function registerYandexAnalysisCommands(program2) {
139452
139676
  out: opts.out
139453
139677
  });
139454
139678
  });
139679
+ root.command("account-status").description(
139680
+ "\u8D26\u6237\u5F52\u6863/\u4F59\u989D/\u533A\u95F4 KPI\uFF08GET /overview\uFF1Barchived=true \u4E3A\u5DF2\u5F52\u6863\uFF1B\u5B98\u65B9\u65E0\u5C01\u6237\u539F\u56E0\uFF1B\u7701\u7565\u65E5\u671F=\u5F53\u5929\uFF09"
139681
+ ).requiredOption(...ACCOUNT_OPTION4).option(...START_OPTION).option(...END_OPTION).option("-t, --token <token>", "Auth Token").option("--json-out <path>", JSON_OUT_OPTION_DESC4).option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(
139682
+ async (opts) => {
139683
+ await runYandexAccountStatus(opts);
139684
+ }
139685
+ );
139686
+ root.command("campaign-entities").description(
139687
+ "\u7CFB\u5217\u7EE9\u6548+\u9884\u7B97/\u7B56\u7565\uFF08GET /campaigns\uFF1Aspend/weeklyBudget/budget/strategy/targetCpa\uFF1B\u5168\u6E20\u9053\u82B1\u8D39\u987B --network ALL\uFF1B\u53EF --time-increment 1 \u6309\u65E5\uFF09"
139688
+ ).requiredOption(...ACCOUNT_OPTION4).option(...START_OPTION).option(...END_OPTION).option("--time-increment <n>", "\u4F20 1 \u6309\u65E5\u5207\u5206\uFF1B\u4E0D\u4F20=\u533A\u95F4\u6C47\u603B\u3002Direct \u65E0\u5C0F\u65F6\u7EF4\u5EA6").option("--network <value>", "SEARCH\uFF08\u9ED8\u8BA4\uFF09\u6216 ALL\uFF08\u5168\u7F51\u4E00\u884C\u5408\u8BA1\uFF0C\u884C\u5185 network \u4E3A null\uFF09").option("--limit <n>", "\u6761\u6570\u4E0A\u9650\uFF08\u9ED8\u8BA4\u7F51\u5173 100\uFF0C\u6700\u5927 10000\uFF09", (v) => parseInt(v, 10)).option("-t, --token <token>", "Auth Token").option("--json-out <path>", JSON_OUT_OPTION_DESC4).option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(
139689
+ async (opts) => {
139690
+ await runYandexCampaignEntities(opts);
139691
+ }
139692
+ );
139693
+ root.command("adgroup-entities").description(
139694
+ "\u5E7F\u544A\u7EC4\u7EE9\u6548+\u7CFB\u5217\u76EE\u6807 CPA/\u5468\u9884\u7B97\uFF08GET /adgroups\uFF1B\u9ED8\u8BA4\u5168\u7F51\uFF1BCPA \u98D9\u5347\u770B\u8FD1 3 \u65E5\u533A\u95F4\u6C47\u603B\uFF0C\u4E0D\u8981\u4F20 timeIncrement\uFF09"
139695
+ ).requiredOption(...ACCOUNT_OPTION4).option(...START_OPTION).option(...END_OPTION).option("--time-increment <n>", "\u4F20 1 \u6309\u65E5\u5207\u5206\uFF1B\u4E0D\u4F20=\u533A\u95F4\u6C47\u603B").option("--campaign-id <id>", "\u53EA\u62C9\u8BE5\u7CFB\u5217\u4E0B\u7684\u7EC4").option("--limit <n>", "\u6761\u6570\u4E0A\u9650\uFF08\u9ED8\u8BA4\u7F51\u5173 100\uFF0C\u6700\u5927 10000\uFF09", (v) => parseInt(v, 10)).option("-t, --token <token>", "Auth Token").option("--json-out <path>", JSON_OUT_OPTION_DESC4).option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(
139696
+ async (opts) => {
139697
+ await runYandexAdGroupEntities(opts);
139698
+ }
139699
+ );
139700
+ root.command("ad-entities").description(
139701
+ `\u5E7F\u544A\u7EE9\u6548+\u843D\u5730\u9875/\u62D2\u5BA1\uFF08GET /ads\uFF1B\u62D2\u5BA1\u4F20 --status REJECTED\uFF1B\u5408\u6CD5\uFF1A${YANDEX_AD_STATUSES.join(",")}\uFF1B\u4E0E --time-increment \u4E92\u65A5\uFF09`
139702
+ ).requiredOption(...ACCOUNT_OPTION4).option(...START_OPTION).option(...END_OPTION).option("--time-increment <n>", "\u4F20 1 \u6309\u65E5\u5207\u5206\uFF1B\u4E0D\u4F20=\u533A\u95F4\u6C47\u603B\u3002\u4E0D\u8981\u548C --status \u540C\u65F6\u4F20").option(
139703
+ "--status <list>",
139704
+ "\u5BA1\u6838\u6001\u9017\u53F7\u5206\u9694\uFF0C\u5982 REJECTED \u6216 MODERATION,REJECTED\uFF1B\u5E26 status \u65F6\u4E0D\u62C9\u7EE9\u6548\uFF08spend=0\uFF09"
139705
+ ).option("--campaign-id <id>", "\u53EA\u62C9\u8BE5\u7CFB\u5217\u4E0B\u7684\u5E7F\u544A").option("--adgroup-id <id>", "\u53EA\u62C9\u8BE5\u7EC4\u4E0B\u7684\u5E7F\u544A").option("--limit <n>", "\u6761\u6570\u4E0A\u9650\uFF08\u9ED8\u8BA4\u7F51\u5173 100\uFF0C\u6700\u5927 10000\uFF09", (v) => parseInt(v, 10)).option("-t, --token <token>", "Auth Token").option("--json-out <path>", JSON_OUT_OPTION_DESC4).option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(
139706
+ async (opts) => {
139707
+ await runYandexAdEntities(opts);
139708
+ }
139709
+ );
139710
+ root.command("insights").description(
139711
+ "YandexAPI \u62A5\u8868\u5207\u7247\uFF08GET /daily|/geo|/devices|/keywords \u6216 campaigns/adgroups/ads\uFF1B\u53EF\u542B\u4ECA\u5929\uFF1B\u65E0\u5C0F\u65F6\u7EF4\u5EA6\u3002geo/devices \u5168\u7F51\u987B --network ALL\uFF09"
139712
+ ).requiredOption(...ACCOUNT_OPTION4).requiredOption("--level <level>", YANDEX_INSIGHTS_LEVELS.join(" / ")).option(...START_OPTION).option(...END_OPTION).option("--time-increment <n>", "\u4EC5 campaigns/adgroups/ads\uFF1A\u4F20 1 \u6309\u65E5\uFF1B\u4E0D\u8981\u548C --status \u540C\u65F6\u4F20").option("--network <value>", "\u4EC5 campaigns/geo/devices\uFF1ASEARCH \u6216 ALL").option("--status <list>", "\u4EC5 --level ads\uFF1A\u5BA1\u6838\u6001\u8FC7\u6EE4").option("--campaign-id <id>", "\u4EC5 adgroups/ads").option("--adgroup-id <id>", "\u4EC5 ads").option("--limit <n>", "\u6709 limit \u7684 path\uFF1A\u9ED8\u8BA4\u7F51\u5173 100\uFF0C\u6700\u5927 10000", (v) => parseInt(v, 10)).option("-t, --token <token>", "Auth Token").option("--json-out <path>", JSON_OUT_OPTION_DESC4).option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(
139713
+ async (opts) => {
139714
+ await runYandexInsights(opts);
139715
+ }
139716
+ );
139455
139717
  }
139456
139718
 
139457
139719
  // src/index.ts
@@ -139528,9 +139790,9 @@ function interceptAgentCompatArgv(argv) {
139528
139790
  installProcessHandlers();
139529
139791
  function getVersion() {
139530
139792
  try {
139531
- const __dirname3 = path48.dirname(fileURLToPath12(import.meta.url));
139532
- const pkgPath = path48.join(__dirname3, "..", "package.json");
139533
- const pkg = JSON.parse(fs37.readFileSync(pkgPath, "utf8"));
139793
+ const __dirname3 = path47.dirname(fileURLToPath12(import.meta.url));
139794
+ const pkgPath = path47.join(__dirname3, "..", "package.json");
139795
+ const pkg = JSON.parse(fs36.readFileSync(pkgPath, "utf8"));
139534
139796
  return pkg.version ?? "0.0.0";
139535
139797
  } catch {
139536
139798
  return "0.0.0";
@@ -139551,7 +139813,7 @@ configureCliJsonSnapshot({
139551
139813
  configureSiluzanClientIdentity({ client: "tso-cli", resolveVersion: getVersion });
139552
139814
  var program = new Command6();
139553
139815
  program.name("siluzan-tso").description(
139554
- "Siluzan \u5E7F\u544A\u8D26\u6237\u7BA1\u7406\uFF1A\u8D26\u6237\u67E5\u8BE2\u3001\u4F59\u989D\u3001\u6295\u653E\u6570\u636E\u3001\u5F00\u6237\u7533\u8BF7\uFF08Google/TikTok/Yandex/Bing/Kwai\uFF09\u3001\n\u8D26\u53F7\u5206\u4EAB/\u89E3\u7ED1\u3001\u4F18\u5316\u62A5\u544A\u3001Google/Meta/TikTok/Bing/Yandex \u8D26\u6237\u5206\u6790\u3001Google \u5E7F\u544A\u8BCA\u65AD\u62A5\u544A\uFF08google-ads-diagnosis render\uFF09\u3001\u7F51\u7AD9\u8BCA\u65AD\uFF08website-diagnosis\uFF09\u3001\u6218\u7565\u5E02\u573A\u5206\u6790\uFF08market-analysis\uFF0CAgent \u751F\u6210\u62A5\u544A\uFF09\u3001\u5145\u503C\u8F6C\u8D26\u3001\u5F00\u7968\u3001\u667A\u80FD\u9884\u8B66\u3001Google \u5E7F\u544A\u7BA1\u7406\uFF08\u542B\u5F02\u6B65\u6279\u91CF\uFF09\u3002"
139816
+ "Siluzan \u5E7F\u544A\u8D26\u6237\u7BA1\u7406\uFF1A\u8D26\u6237\u67E5\u8BE2\u3001\u4F59\u989D\u3001\u6295\u653E\u6570\u636E\u3001\u5F00\u6237\u7533\u8BF7\uFF08Google/TikTok/Yandex/Bing\uFF09\u3001\n\u8D26\u53F7\u5206\u4EAB/\u89E3\u7ED1\u3001\u4F18\u5316\u62A5\u544A\u3001Google/Meta/TikTok/Bing/Yandex \u8D26\u6237\u5206\u6790\u3001Google \u5E7F\u544A\u8BCA\u65AD\u62A5\u544A\uFF08google-ads-diagnosis render\uFF09\u3001\u7F51\u7AD9\u8BCA\u65AD\uFF08website-diagnosis\uFF09\u3001\u6218\u7565\u5E02\u573A\u5206\u6790\uFF08market-analysis\uFF0CAgent \u751F\u6210\u62A5\u544A\uFF09\u3001\u5145\u503C\u8F6C\u8D26\u3001\u5F00\u7968\u3001\u667A\u80FD\u9884\u8B66\u3001Google \u5E7F\u544A\u7BA1\u7406\uFF08\u542B\u5F02\u6B65\u6279\u91CF\uFF09\u3002"
139555
139817
  ).version(getVersion());
139556
139818
  program.option("--commit <text>", "\u5199\u64CD\u4F5C\u8BF4\u660E\uFF1B\u8BB0\u5165\u672C\u673A\u5199\u5BA1\u8BA1 JSONL");
139557
139819
  program.hook("preAction", async () => {