siluzan-tso-cli 1.1.14-beta.2 → 1.1.14-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/README.md +1 -3
  2. package/dist/index.js +131 -1
  3. package/dist/skill/SKILL.md +42 -16
  4. package/dist/skill/_meta.json +2 -2
  5. package/dist/skill/references/account-analytics.md +48 -2
  6. package/dist/skill/references/accounts.md +3 -3
  7. package/dist/skill/references/google-ads.md +66 -66
  8. package/dist/skill/references/hosted-automation-monitoring-json.md +94 -0
  9. package/dist/skill/references/hosted-automation-optimize-ab-winner.md +69 -0
  10. package/dist/skill/references/hosted-automation-optimize-index.md +32 -0
  11. package/dist/skill/references/hosted-automation-optimize-scale.md +90 -0
  12. package/dist/skill/references/hosted-automation-optimize-weak-downbid.md +94 -0
  13. package/dist/skill/references/hosted-automation-scenarios.md +22 -0
  14. package/dist/skill/references/hosted-automation-self-control.md +212 -0
  15. package/dist/skill/references/open-account-google-ui.md +0 -6
  16. package/dist/skill/references/workflows.md +14 -1
  17. package/dist/skill/report-templates/google-account-diagnosis-report.md +1 -1
  18. package/dist/skill/report-templates/google-period-report.md +1 -0
  19. package/eval/cases/accounts-entityid-vs-mediaccustomerid.scenario.json +23 -0
  20. package/eval/cases/accounts-mcc-bind-inquiry.scenario.json +12 -0
  21. package/eval/cases/accounts-single-balance-not-bulk.scenario.json +23 -0
  22. package/eval/cases/budget-display-not-raw-micros.scenario.json +17 -0
  23. package/eval/cases/clue-meta-leads-json.scenario.json +23 -0
  24. package/eval/cases/clue-tiktok-leads-json.scenario.json +20 -0
  25. package/eval/cases/destructive-account-delink-needs-confirm.scenario.json +15 -0
  26. package/eval/cases/destructive-forewarning-delete-needs-confirm.scenario.json +15 -0
  27. package/eval/cases/destructive-invoice-apply-needs-confirm.scenario.json +15 -0
  28. package/eval/cases/destructive-unshare-needs-confirm.scenario.json +9 -0
  29. package/eval/cases/finance-invoice-info-list.scenario.json +17 -0
  30. package/eval/cases/forewarning-list-google.scenario.json +20 -0
  31. package/eval/cases/google-ads-no-structural-without-confirm.scenario.json +12 -0
  32. package/eval/cases/google-analysis-keywords-route.scenario.json +23 -0
  33. package/eval/cases/hosted-sop-cpa-spike-downbid.scenario.json +14 -0
  34. package/eval/cases/hosted-sop-daily-budget-circuit-breaker.scenario.json +13 -0
  35. package/eval/cases/hosted-sop-empty-spend-pause-p1.scenario.json +14 -0
  36. package/eval/cases/human-p1-multiturn.scenario.json +17 -0
  37. package/eval/cases/meta-single-balance-not-bulk.scenario.json +26 -0
  38. package/eval/cases/open-account-bing-noninteractive.scenario.json +13 -0
  39. package/eval/cases/open-account-google-noninteractive.scenario.json +12 -0
  40. package/eval/cases/open-account-tiktok-license-file.scenario.json +12 -0
  41. package/eval/cases/optimize-list-by-account.scenario.json +17 -0
  42. package/eval/cases/p1-single-account-profile.scenario.json +20 -0
  43. package/eval/cases/p2-balance-scan-bulk.scenario.json +18 -0
  44. package/eval/cases/p3-accounts-digest.scenario.json +20 -0
  45. package/eval/cases/p4-period-report-window.scenario.json +17 -0
  46. package/eval/cases/report-list-google.scenario.json +20 -0
  47. package/eval/cases/report-push-list-google.scenario.json +20 -0
  48. package/eval/cases/reporting-vs-account-analytics-routing.scenario.json +13 -0
  49. package/eval/cases/setup-login-or-env.scenario.json +12 -0
  50. package/eval/cases/setup-siluzan-data-permission-env.scenario.json +19 -0
  51. package/eval/cases/skill-async-poll-guidance.scenario.json +9 -0
  52. package/eval/cases/skill-optimize-vs-google-ads-distinction.scenario.json +13 -0
  53. package/eval/cases/tiktok-bc-bind-inquiry.scenario.json +12 -0
  54. package/eval/cases/time-range-must-ask.scenario.json +16 -0
  55. package/eval/cases/time-range-user-delegates-default.scenario.json +17 -0
  56. package/eval/cases/tips-json-filtering.scenario.json +12 -0
  57. package/eval/cases/tips-large-json-pagination.scenario.json +19 -0
  58. package/eval/cases/uj-ad-bluetooth-keywords-exclude-cheap-free.scenario.json +9 -0
  59. package/eval/cases/uj-ad-keywords-camping-tent-outdoor-plan.scenario.json +9 -0
  60. package/eval/cases/uj-ad-outdoor-campgear-search-plan.scenario.json +12 -0
  61. package/eval/cases/uj-analytics-30d-pdf-campaign-device-geo.scenario.json +29 -0
  62. package/eval/cases/uj-analytics-compare-google-tiktok-last-month-roi.scenario.json +17 -0
  63. package/eval/cases/uj-analytics-google-weekly-trends-campaigns-keywords.scenario.json +20 -0
  64. package/eval/cases/uj-analytics-report-push-weekly-email.scenario.json +12 -0
  65. package/eval/cases/uj-finance-invoice-records-this-month.scenario.json +20 -0
  66. package/eval/cases/uj-life-newbie-siluzan-google-end-to-end.scenario.json +13 -0
  67. package/eval/cases/uj-ops-google-accounts-list-normal.scenario.json +23 -0
  68. package/eval/cases/uj-ops-google-yesterday-spend-conversions.scenario.json +23 -0
  69. package/eval/cases/uj-ops-open-google-b2c-usd-shenzhen.scenario.json +13 -0
  70. package/eval/cases/uj-ops-pause-worst-adgroup-confirm.scenario.json +12 -0
  71. package/eval/cases/uj-ops-tiktok-leads-last-week.scenario.json +23 -0
  72. package/eval/cases/uj-patrol-all-media-balance-stats-forewarning.scenario.json +9 -0
  73. package/eval/cases/uj-patrol-cpc-spike-adgroups-over-15.scenario.json +18 -0
  74. package/eval/cases/uj-patrol-forewarning-create-daily-cap-3000.scenario.json +12 -0
  75. package/eval/cases/uj-patrol-forewarning-trigger-records.scenario.json +23 -0
  76. package/eval/cases/uj-patrol-google-balances-low.scenario.json +20 -0
  77. package/eval/cases/uj-roi-full-google-account-diagnosis.scenario.json +9 -0
  78. package/eval/cases/uj-roi-keywords-high-cpa-low-cvr-triage.scenario.json +9 -0
  79. package/eval/cases/uj-roi-optimize-records-then-execute-cautiously.scenario.json +20 -0
  80. package/eval/cases/uj-roi-search-terms-add-negative-keywords.scenario.json +23 -0
  81. package/eval/stub-fixtures/accounts-digest.json +33 -0
  82. package/eval/stub-fixtures/ad-campaigns.json +14 -0
  83. package/eval/stub-fixtures/balance-meta.json +6 -0
  84. package/eval/stub-fixtures/balance-scan.json +21 -0
  85. package/eval/stub-fixtures/balance.json +6 -0
  86. package/eval/stub-fixtures/clue-meta.json +7 -0
  87. package/eval/stub-fixtures/clue-tiktok.json +7 -0
  88. package/eval/stub-fixtures/forewarning-create-ok.json +1 -0
  89. package/eval/stub-fixtures/forewarning-records.json +7 -0
  90. package/eval/stub-fixtures/generic-ok.json +1 -0
  91. package/eval/stub-fixtures/google-analysis-search-terms.json +10 -0
  92. package/eval/stub-fixtures/google-analysis.json +7 -0
  93. package/eval/stub-fixtures/invoice-billable.json +7 -0
  94. package/eval/stub-fixtures/invoice-info-list.json +13 -0
  95. package/eval/stub-fixtures/invoice-list.json +10 -0
  96. package/eval/stub-fixtures/list-accounts.json +13 -0
  97. package/eval/stub-fixtures/optimize-list.json +7 -0
  98. package/eval/stub-fixtures/report-push-list.json +7 -0
  99. package/eval/stub-fixtures/stats.json +9 -0
  100. package/package.json +5 -1
  101. package/dist/skill/references/open-account-by-media.md +0 -61
package/README.md CHANGED
@@ -19,8 +19,6 @@
19
19
  | 项目 | 说明 |
20
20
  | --------------- | --------------------------------------------------------------- |
21
21
  | API Key / Token | 存储在 `~/.siluzan/config.json`,用于所有 API 调用鉴权 |
22
- | TSO API | `tso-api.siluzan.com`(生产)/ `tso-api-ci.siluzan.com`(测试) |
23
- | Google API 网关 | `googleapi.mysiluzan.com` / `googleapi-ci.mysiluzan.com` |
24
22
  | 前端页面 | `www.siluzan.com`(充值、激活等浏览器操作) |
25
23
  | 错误追踪 | `o605862.ingest.us.sentry.io`(匿名崩溃日志) |
26
24
  | 版本检查 | `registry.npmjs.org` |
@@ -53,7 +51,7 @@ siluzan-tso init -d /path/to/skills # 写入自定义目录
53
51
  siluzan-tso init --force # 强制覆盖已存在文件
54
52
  ```
55
53
 
56
- > **注意**:当前为测试版(1.1.14-beta.2),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-tso-cli`。
54
+ > **注意**:当前为测试版(1.1.14-beta.3),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-tso-cli`。
57
55
 
58
56
  | 助手 | 建议 `--ai` |
59
57
  | ----------------------- | ------------------------------------ |
package/dist/index.js CHANGED
@@ -5184,6 +5184,12 @@ var SECTIONS = [
5184
5184
  dateMode: "range",
5185
5185
  path: (id) => `/reporting/media-account/${id}/CampaignSectionData`
5186
5186
  },
5187
+ {
5188
+ name: "campaign-hour",
5189
+ description: "\u7CFB\u5217\u6309\u5C0F\u65F6 campaign-hour\uFF08Query\uFF1AstartDate\u3001endDate\uFF09",
5190
+ dateMode: "range",
5191
+ path: (id) => `/reporting/media-account/${id}/campaign-hour`
5192
+ },
5187
5193
  {
5188
5194
  name: "ads",
5189
5195
  description: "\u5E7F\u544A\u7EA7\u5217\u8868 admanagement/v2/list",
@@ -5319,6 +5325,55 @@ async function fetchJson(config, pathWithQuery, verbose) {
5319
5325
  const url = `${config.googleApiUrl}${pathWithQuery}`;
5320
5326
  return apiFetch2(url, config, {}, verbose);
5321
5327
  }
5328
+ function assertNever(x, ctx) {
5329
+ throw new Error(`${ctx}\uFF1A\u672A\u5904\u7406\u7684\u5206\u652F ${String(x)}`);
5330
+ }
5331
+ async function fetchGoogleAnalysisSectionJson(config, fullPath, verbose, name) {
5332
+ switch (name) {
5333
+ case "overview":
5334
+ return fetchJson(config, fullPath, verbose);
5335
+ case "keywords":
5336
+ return fetchJson(config, fullPath, verbose);
5337
+ case "search-terms":
5338
+ return fetchJson(config, fullPath, verbose);
5339
+ case "campaigns":
5340
+ return fetchJson(config, fullPath, verbose);
5341
+ case "campaign-hour":
5342
+ return fetchJson(config, fullPath, verbose);
5343
+ case "ads":
5344
+ return fetchJson(config, fullPath, verbose);
5345
+ case "extensions":
5346
+ return fetchJson(config, fullPath, verbose);
5347
+ case "devices":
5348
+ return fetchJson(config, fullPath, verbose);
5349
+ case "geographic":
5350
+ return fetchJson(config, fullPath, verbose);
5351
+ case "audience":
5352
+ return fetchJson(config, fullPath, verbose);
5353
+ case "asset-images":
5354
+ return fetchJson(config, fullPath, verbose);
5355
+ case "videos":
5356
+ return fetchJson(config, fullPath, verbose);
5357
+ case "resource-counts":
5358
+ return fetchJson(config, fullPath, verbose);
5359
+ case "conversion-actions":
5360
+ return fetchJson(config, fullPath, verbose);
5361
+ case "daily-metrics":
5362
+ return fetchJson(config, fullPath, verbose);
5363
+ case "gold-account":
5364
+ return fetchJson(config, fullPath, verbose);
5365
+ case "ads-index":
5366
+ return fetchJson(config, fullPath, verbose);
5367
+ case "final-urls":
5368
+ return fetchJson(config, fullPath, verbose);
5369
+ case "dimension-summary":
5370
+ return fetchJson(config, fullPath, verbose);
5371
+ case "campaign-types":
5372
+ return fetchJson(config, fullPath, verbose);
5373
+ default:
5374
+ return assertNever(name, "google-analysis");
5375
+ }
5376
+ }
5322
5377
  function summarizeHuman(section, data) {
5323
5378
  if (data === null || data === void 0) return "\u65E0\u6570\u636E";
5324
5379
  if (Array.isArray(data)) return `\u6570\u7EC4\uFF0C\u5171 ${data.length} \u6761`;
@@ -5389,7 +5444,12 @@ async function runOneSection(def, opts) {
5389
5444
  );
5390
5445
  return;
5391
5446
  }
5392
- const data = await fetchJson(config, fullPath, !!opts.verbose);
5447
+ const data = await fetchGoogleAnalysisSectionJson(
5448
+ config,
5449
+ fullPath,
5450
+ !!opts.verbose,
5451
+ def.name
5452
+ );
5393
5453
  if (opts.json) {
5394
5454
  console.log(JSON.stringify(stripLegacyGoogleFieldsIfV2Present(data), null, 2));
5395
5455
  return;
@@ -8044,6 +8104,53 @@ async function runAdGroupRename(opts) {
8044
8104
  \u2705 \u5E7F\u544A\u7EC4 ${opts.id} \u5DF2\u6539\u540D\u4E3A\u300C${opts.name}\u300D
8045
8105
  `);
8046
8106
  }
8107
+ async function runAdGroupEdit(opts) {
8108
+ const hasName = opts.name !== void 0 && opts.name.trim() !== "";
8109
+ const hasMax = opts.maxCPCAmount !== void 0;
8110
+ const hasTcpa = opts.targetCpaAmount !== void 0;
8111
+ if (!hasName && !hasMax && !hasTcpa) {
8112
+ console.error(
8113
+ "\n\u274C \u8BF7\u81F3\u5C11\u6307\u5B9A\u4E00\u9879\u4FEE\u6539\uFF1A--name / --max-cpc / --target-cpa\n"
8114
+ );
8115
+ process.exit(1);
8116
+ }
8117
+ if (hasMax && (!Number.isFinite(opts.maxCPCAmount) || opts.maxCPCAmount < 0)) {
8118
+ console.error("\n\u274C --max-cpc \u987B\u4E3A\u975E\u8D1F\u6570\u5B57\n");
8119
+ process.exit(1);
8120
+ }
8121
+ if (hasTcpa && (!Number.isFinite(opts.targetCpaAmount) || opts.targetCpaAmount < 0)) {
8122
+ console.error("\n\u274C --target-cpa \u987B\u4E3A\u975E\u8D1F\u6570\u5B57\n");
8123
+ process.exit(1);
8124
+ }
8125
+ const config = loadConfig(opts.token);
8126
+ const googleApiUrl = requireGoogleApi(config);
8127
+ const listUrl = adgroupListUrl(googleApiUrl, opts.account, opts.startDate, opts.endDate);
8128
+ let adgroup;
8129
+ try {
8130
+ adgroup = await findItemInList(listUrl, config, opts.id, opts.verbose);
8131
+ } catch (err) {
8132
+ console.error(`
8133
+ \u274C \u67E5\u8BE2\u5E7F\u544A\u7EC4\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
8134
+ `);
8135
+ process.exit(1);
8136
+ }
8137
+ const body = { ...adgroup };
8138
+ if (hasName) body["name"] = opts.name.trim();
8139
+ if (hasMax) body["maxCPCAmount"] = Math.round(opts.maxCPCAmount);
8140
+ if (hasTcpa) body["targetCpaAmount"] = Math.round(opts.targetCpaAmount);
8141
+ const putUrl = `${googleApiUrl}/adgroupnmanagement/adgroup/${opts.account}/${opts.id}`;
8142
+ try {
8143
+ await apiFetch2(putUrl, config, { method: "PUT", body: JSON.stringify(body) }, opts.verbose);
8144
+ } catch (err) {
8145
+ console.error(`
8146
+ \u274C \u7F16\u8F91\u5E7F\u544A\u7EC4\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
8147
+ `);
8148
+ process.exit(1);
8149
+ }
8150
+ console.log(`
8151
+ \u2705 \u5E7F\u544A\u7EC4 ${opts.id} \u5DF2\u66F4\u65B0
8152
+ `);
8153
+ }
8047
8154
  async function runAdEdit(opts) {
8048
8155
  const config = await ensureDataPermission(loadConfig(opts.token));
8049
8156
  const googleApiUrl = requireGoogleApi(config);
@@ -13310,6 +13417,29 @@ adCmd.command("adgroup-rename").description("\u4FEE\u6539\u5E7F\u544A\u7EC4\u540
13310
13417
  });
13311
13418
  }
13312
13419
  );
13420
+ adCmd.command("adgroup-edit").description("\u7F16\u8F91\u5E7F\u544A\u7EC4\uFF08\u540D\u79F0\u3001\u6700\u9AD8 CPC\u3001\u7EC4\u7EA7\u76EE\u6807 CPA\uFF1B\u81F3\u5C11\u4F20\u4E00\u9879\uFF1B\u4E0E\u7F51\u5173 PUT \u4E00\u81F4\uFF09").requiredOption("-a, --account <id>", "Google \u8D26\u6237 mediaCustomerId").requiredOption("--id <adgroupId>", "\u5E7F\u544A\u7EC4 ID").option("--name <name>", "\u65B0\u540D\u79F0").option(
13421
+ "--max-cpc <n>",
13422
+ "\u6700\u9AD8 CPC\uFF0C\u4E0E ad groups --json \u7684 maxCPCAmount \u540C\u53E3\u5F84\uFF08\u4E3B\u5E01\u79CD\u91D1\u989D\xD7100\uFF0C\u89C1 references/google-ads.md\uFF09",
13423
+ parseFloat
13424
+ ).option(
13425
+ "--target-cpa <n>",
13426
+ "\u7EC4\u7EA7\u76EE\u6807 CPA\uFF0C\u4E0E ad groups --json \u7684 targetCpaAmount \u540C\u53E3\u5F84\uFF08\xD7100 \u5206\u5355\u4F4D\uFF09",
13427
+ parseFloat
13428
+ ).option("--start <date>", "\u5217\u8868\u67E5\u8BE2\u8D77\u59CB\u65E5\u671F YYYY-MM-DD").option("--end <date>", "\u5217\u8868\u67E5\u8BE2\u7ED3\u675F\u65E5\u671F YYYY-MM-DD").option("-t, --token <token>", "Auth Token").option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(
13429
+ async (opts) => {
13430
+ await runAdGroupEdit({
13431
+ token: opts.token,
13432
+ account: opts.account,
13433
+ id: opts.id,
13434
+ name: opts.name,
13435
+ maxCPCAmount: opts.maxCpc,
13436
+ targetCpaAmount: opts.targetCpa,
13437
+ startDate: opts.start,
13438
+ endDate: opts.end,
13439
+ verbose: opts.verbose
13440
+ });
13441
+ }
13442
+ );
13313
13443
  adCmd.command("ad-edit").description(
13314
13444
  "\u7F16\u8F91\u81EA\u9002\u5E94\u641C\u7D22\u5E7F\u544A\uFF08RESPONSIVE_SEARCH_AD\uFF09\uFF1A\u6807\u9898/\u63CF\u8FF0/\u843D\u5730\u9875/\u8DEF\u5F84/\u72B6\u6001\uFF1B\u4E0E\u7F51\u9875 PUT admanagement/campaign \u884C\u4E3A\u4E00\u81F4"
13315
13445
  ).requiredOption("-a, --account <id>", "Google \u8D26\u6237 mediaCustomerId").requiredOption("--id <adId>", "\u5E7F\u544A ID").option(
@@ -50,11 +50,12 @@ allowed-tools: Bash(siluzan-tso:*) Read
50
50
  | 文档 | 功能 |
51
51
  |------|------|
52
52
  | `references/setup.md` | 安装、登录、配置、环境切换、更新 |
53
- | `references/workflows.md` | 多步骤业务流程与跨命令串联场景 |
53
+ | `references/workflows.md` | 多步骤业务流程、跨命令串联;入口指向宿主编排自控详页 |
54
+ | `references/hosted-automation-scenarios.md` | **宿主编排(Google)索引**;自控见 `references/hosted-automation-self-control.md`;监控见 `references/hosted-automation-monitoring-json.md`;**自动优化 SOP** 见 `references/hosted-automation-optimize-index.md` |
54
55
  | `references/tips.md` | `--json`、Node 过滤、分页与调试技巧 |
55
56
  | `references/accounts.md` | 账户列表、余额、消耗、开户记录、授权/解绑/分享/MCC/BC/BM/邮箱授权 |
56
57
  | `references/open-account-by-media.md` | 各媒体开户、参数与资料要求 |
57
- | `references/google-ads.md` | Google Ads 创建、修改、优化与管理主流程 |
58
+ | `references/google-ads.md` | Google Ads 创建、修改、优化与管理主流程;**含 `ad list` / `google-analysis ads` 的 `--json` 拒审字段**(`policyApprovalStatusV2`、`approvalStatusDetails` 等,见该文档「拒审与政策字段」) |
58
59
  | `references/reporting.md` | Siluzan TSO 优化报告(Google/TikTok)的生成、推送与查看 |
59
60
  | `references/account-analytics.md` | 广告平台账户分析数据拉取与分析/诊断报告模板 |
60
61
  | `references/optimize.md` | AI 优化建议记录、详情与历史查询 |
@@ -65,6 +66,27 @@ allowed-tools: Bash(siluzan-tso:*) Read
65
66
 
66
67
  ---
67
68
 
69
+ ## 职责划分
70
+
71
+ **定位**:`siluzan-tso` + 本 Skill 提供 **可组合的读能力(检查项)** 与 **可验证的写能力(最终操作)**;**不负责**在进程内长期驻留、定时轮询、复合条件规则引擎、或替代宿主的通知渠道。
72
+
73
+ | 由 **本 Skill + CLI** 保证 | 由 **宿主客户端 / 外部调度** 负责 |
74
+ |---------------------------|-----------------------------------|
75
+ | 单次/按需调用下,命令能拉取验证所需的 **JSON 字段**(`--json`、分页见 `references/tips.md`) | **何时**跑一轮检查(cron、事件、对话触发) |
76
+ | 写操作命令语义清晰,且文档给出 **写后如何用读命令复核**(成对验证) | **IF 条件**(多指标 AND/OR、滑动时间窗、相对预算比例等)的计算与决策 |
77
+ | 金额与 ID 口径与文档一致(`*Display`、`entityId` vs `mediaCustomerId` 等硬规范) | 命中后的 **触达**(钉钉/飞书/Slack 等)与内部 **P1/工单** 流程 |
78
+ | `references/google-ads.md` 等与命令、字段含义对齐 | 多账户、多系列的 **批处理循环**、限速、失败重试策略 |
79
+
80
+ **宿主集成时的推荐约定**:
81
+
82
+ 1. **监控与编排**:配置定时或事件;每轮用本 Skill 指明的命令拉数,在宿主侧用脚本 / `node -e` 做条件判断。
83
+ 2. **执行写操作**:仍遵守本 Skill **计划 →(按策略)确认 → 执行 → 验证**;若宿主策略为「全自动写」,须由**用户或配置**显式授权,避免与默认安全规范冲突。
84
+ 3. **验证**:每次写入后,用文档中的 **读命令对同一 `id` 再拉一次**(例如 `ad campaign-status` 后 `ad campaigns --json` 看 `statusV2`;`adgroup-edit` 后 `ad groups --json` 看 `maxCPCAmount` / `targetCpaAmount`)。
85
+ 4. **`forewarning`**:仍是丝路赞侧 **微信通知** 的可选通道;宿主已有独立通知 skill 时,**不必**重复依赖 `forewarning` 完成「告警」——二者可并行或只选其一。
86
+
87
+ 更具体的 **检查项 ↔ 命令** 见 **`references/hosted-automation-self-control.md`**(三类自控);异常监控 **`--json` 键名** 见 **`references/hosted-automation-monitoring-json.md`**;**自动优化(降价/扩量/A/B)** 见 **`references/hosted-automation-optimize-index.md`**(分文件 SOP);主题入口 **`references/hosted-automation-scenarios.md`**。总览见 **`references/workflows.md`**「宿主编排下的投放自控」。
88
+
89
+
68
90
  ## Skill要如何使用
69
91
 
70
92
  ### 报告的生成
@@ -89,7 +111,7 @@ allowed-tools: Bash(siluzan-tso:*) Read
89
111
  - Google广告优化记录功能(`references/optimize.md`),这个也跟优化报告类似,你调用接口,Siluzan平台按照一定的优化逻辑自动执行,你只能查询到结果,不能控制优化流程 注意不要与`google-ads.md`中的优化流程混淆两个是互相独立的功能,`references/google-ads.md`中的优化功能更为强大,在实际的优化过程中,也推荐使用`references/google-ads.md`中提供的内容
90
112
  - TikTok / Meta 线索表单请阅读:`references/clue.md`
91
113
  - Siluzan平台提供的预警功能请阅读:`references/forewarning.md`
92
- - 预警由Siluzan平台发送,当前仅支持微信推送,如果需要自定义的通知触达端,需要安装对应插件或skill+创建定时任务来完成
114
+ - 预警由 Siluzan 平台发送,当前仅支持微信推送。若监控与通知由 **OpenClaw / WorkBuddy 等宿主**承担,可将 `forewarning` 仅作补充或不用;自定义触达仍可用宿主插件 / skill + 定时任务(见上文职责划分)。
93
115
  - 转账、开票、发票抬头、充值网页引导请阅读:`references/finance.md`
94
116
  -
95
117
 
@@ -364,19 +386,23 @@ HTML 报告模板(`report-templates/*.html`)引用了以下外部 CDN 资源
364
386
 
365
387
  ### 异常监控与报警系统
366
388
 
367
- | 功能名称 | 监控层级 / 说明 |
368
- | ----------------- | ----------------------------------------------------------- |
369
- | 1. 账户被封禁 | |
370
- | 2. 落地页死链强停 | 网站宕机或链接填错,紧急自动暂停关联广告,防止把钱扔水里。 |
371
- | 3. 广告素材拒审 | 发现被 Google 封号或快没钱了,立刻发送企微/钉钉高优强提醒。 |
372
- | 4. 花费异动监控 | 花费突然暴涨或断崖式下跌,系统即时报警提示人工盯盘。 |
373
- | 5. 余额枯竭预警 | 广告被 Google 拦截,系统自动帮你打包违规原因并定时推送。 |
389
+ 编排(定时、HTTP 探活、通知)在宿主;**读哪些 JSON 字段、用什么命令** 以 **`references/hosted-automation-monitoring-json.md`** 为准(键名以当次 `--json` 为准,勿套用 Google Ads API 官方字段名解析本 CLI 输出)。
390
+
391
+ | 功能名称 | 监控层级 / 说明 | CLI 检查入口(`--json`) |
392
+ | ----------------- | --------------- | ------------------------ |
393
+ | 1. 账户被封禁 | 账户级;与 Google `CustomerStatus` 及 `list-accounts` 的字段映射**暂不写进本 skill**,由宿主约定。 | `list-accounts`、`balance` 等见 `references/accounts.md` |
394
+ | 2. 落地页死链强停 | URL 不可用或跳错页时暂停关联创意,避免无效消耗。 | **`google-analysis final-urls`**;或 **`ad list`** / **`google-analysis ads`** 取落地页字段后由宿主 HTTP 校验 |
395
+ | 3. 广告素材拒审 | 创意政策状态异常时告警或配合工单。 | **`ad list`** / **`google-analysis ads`**:`policyApprovalStatusV2`、`approvalStatusDetails` 等(见 **`references/google-ads.md`**) |
396
+ | 4. 花费异动监控 | 系列或账户维度花费相对历史异常波动。 | **`google-analysis campaign-hour`**:按 `campaignId` + `date` + `hour` 看 **`spend`** |
397
+ | 5. 余额枯竭预警 | 余额过低或按日均推算续航不足。 | **`balance-scan`**(`balance`、`remainingDays`、`hitReason`、`meta`)或 **`balance`** / **`google-analysis overview`**(`remainingAccountBudget`、`averageDailyCost` 等) |
374
398
 
375
399
  ### 自动优化
376
400
 
377
- | 功能名称 | 监控层级 |
378
- | ----------------------- | -------------------------------------------------------------------------- |
379
- | 1. 表现差广告降价/关停 | 发现转化极好的「好苗子」,以安全幅度自动涨预算/提价去抢量。 |
380
- | 2. 高转化广告提价扩量 | 连续几天表现垫底的垃圾素材,系统扮演无情杀手自动关停。 |
381
- | 3. A/B测试自动决出胜者 | 科学赛马,根据真实转化价值自动关停输家,把流量全给赢家。 |
382
- | 4. 异动根因自动排查建议 | 老板问为什么成本翻倍?系统一键生成诊断报告(揪出外部竞对或内部操作失误)。 |
401
+ 编排与阈值在宿主;**命令、JSON 键名、聚合与写后复核** 见 **`references/hosted-automation-optimize-index.md`**(及链出的三份 SOP)。
402
+
403
+ | 功能名称 | 说明 | SOP |
404
+ | ----------------------- | ---- | ----- |
405
+ | 1. 表现差广告降价/关停 | 组/创意:CTR、CPA、转化等触达后 **下调 `targetCpa` 或 `Paused`**。 | [`hosted-automation-optimize-weak-downbid.md`](references/hosted-automation-optimize-weak-downbid.md) |
406
+ | 2. 高转化广告提价扩量 | 系列/组:ROAS 代理、预算丢失份额等触达后 **提预算 / 上调目标 CPA**。 | [`hosted-automation-optimize-scale.md`](references/hosted-automation-optimize-scale.md) |
407
+ | 3. A/B 测试自动决出胜者 | 同组多创意:聚合后比 **CVPI / all conv** 等,**停输家**。 | [`hosted-automation-optimize-ab-winner.md`](references/hosted-automation-optimize-ab-winner.md) |
408
+ | 4. 异动根因自动排查建议 | 诊断报告与归因:用 `account-analytics`、报告模板等,见 `references/account-analytics.md` 与 `report-templates/`。 | (未单独拆 SOP,沿用分析文档) |
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "slug": "siluzan-tso",
3
- "version": "1.1.14-beta.2",
4
- "publishedAt": 1776838977656
3
+ "version": "1.1.14-beta.3",
4
+ "publishedAt": 1776995703860
5
5
  }
@@ -82,6 +82,48 @@
82
82
 
83
83
  ---
84
84
 
85
+ ### CampaignSectionData(`campaigns[]`)
86
+
87
+ **路由**:`GET …/reporting/media-account/{mediaCustomerId}/CampaignSectionData?startDate=&endDate=`(以及 TikTok 等媒体在路径中插入媒体段,如 `…/TikTok/{id}/CampaignSectionData?…`)。
88
+
89
+ **CLI**:Google 为 `siluzan-tso google-analysis campaigns`;TikTok 为 `siluzan-tso report tiktok-campaigns`(另带 `take`,默认 100)。
90
+
91
+ `campaigns` 数组每一行在既有指标外,另包含:
92
+
93
+ | 字段 | 说明 |
94
+ | --- | --- |
95
+ | `conversionsValue` | 转化价值 |
96
+ | `conversionsValuePerCost` | 转化价值相对消耗;接口按 **`conversionsValue / spend`** 计算,当 **`spend ≤ 0`** 时为 **`0`** |
97
+ | `campaignTargetCpaMicros` | 系列目标 CPA(微货币单位) |
98
+ | `maximizeConversionsTargetCpaMicros` | 「尽可能提高转化次数」下的目标 CPA(微货币单位) |
99
+ | `manualCpcEnhancedCpcEnabled` | 人工 CPC 是否启用增强 CPC |
100
+ | `percentCpcEnhancedCpcEnabled` | 百分比 CPC 是否启用增强 CPC |
101
+
102
+ 展示微货币字段时须按账户 `currencyCode` 换算为金额,**不要**把 micros 直接当元展示。
103
+
104
+ ---
105
+
106
+ ### campaign-hour(系列按小时)
107
+
108
+ **路由**:`GET {googleApiUrl}/reporting/media-account/{mediaCustomerId}/campaign-hour?startDate=&endDate=`(与 `google-analysis` 其它带区间接口相同,**`--start` / `--end` 须同传或同省略**)。
109
+
110
+ **CLI**:`siluzan-tso google-analysis campaign-hour -a <mediaCustomerId> [--start YYYY-MM-DD --end YYYY-MM-DD] --json`
111
+
112
+ 响应体为 **JSON 数组**(非 `{ campaigns: … }` 包装)。元素常见字段:
113
+
114
+ | 字段 | 说明 |
115
+ | --- | --- |
116
+ | `campaignId` | 广告系列 ID |
117
+ | `campaignName` | 广告系列名称 |
118
+ | `date` | 日期 |
119
+ | `hour` | 小时 |
120
+ | `spend` | 消耗 |
121
+ | `impressions` | 展示 |
122
+ | `clicks` | 点击 |
123
+ | `conversions` | 转化 |
124
+
125
+ ---
126
+
85
127
  ### google-analysis
86
128
 
87
129
  使用已配置的 `googleApiUrl` 与 Token,无需手写 curl。
@@ -102,7 +144,7 @@ siluzan-tso google-analysis <子命令> -a <mediaCustomerId> [选项]
102
144
  | `-t, --token` | 鉴权 Token(可选,默认读配置) |
103
145
  | `--verbose` | 打印详细错误 |
104
146
 
105
- **子命令与网关路径对应**
147
+ **子命令与拉数路径**
106
148
 
107
149
  | 子命令 | 说明 |
108
150
  | -------------------- | --------------------------------------------------------------------------------------- |
@@ -110,6 +152,7 @@ siluzan-tso google-analysis <子命令> -a <mediaCustomerId> [选项]
110
152
  | `keywords` | 关键词 `KeywordSectionData`;可选 `--limit`、`--no-order-by-cost` |
111
153
  | `search-terms` | 搜索词 `searchtermmanagement/v2/list`;同上 |
112
154
  | `campaigns` | 系列 `CampaignSectionData` |
155
+ | `campaign-hour` | 系列按小时 `campaign-hour`(`?startDate=&endDate=`;**根为 JSON 数组**) |
113
156
  | `ads` | 广告 `admanagement/v2/list` |
114
157
  | `extensions` | 附加信息 `extensionmanagement/v2/list`;可选 `--level`(Account / Campaign / Ad Group) |
115
158
  | `devices` | 设备 `DeviceSectionData` |
@@ -127,15 +170,18 @@ siluzan-tso google-analysis <子命令> -a <mediaCustomerId> [选项]
127
170
  | `dimension-summary` | 账户汇总 `reports/combined` |
128
171
  | `campaign-types` | 系列类型(**不要**传 `--start`/`--end`) |
129
172
 
173
+ `ads` 与 **`ad list`** 同源;带日期区间时创意可能 **按日多行**,宿主编排(降价/扩量/A/B)见 **`references/hosted-automation-optimize-index.md`**。
174
+
130
175
  **示例**
131
176
 
132
177
  ```bash
133
178
  siluzan-tso google-analysis overview -a 6326027735 --start 2026-03-01 --end 2026-03-31 --json
134
179
  siluzan-tso google-analysis keywords -a 6326027735 --limit 50
180
+ siluzan-tso google-analysis campaign-hour -a 6326027735 --start 2026-03-01 --end 2026-03-07 --json
135
181
  siluzan-tso google-analysis final-urls -a 6326027735 --json
136
182
  ```
137
183
 
138
- **CPC / 花费异常巡检(先查后停)**:用户要先定位异常再考虑暂停时,在确认统计区间后,优先用 `google-analysis` 拉**带花费/CPC 粒度**的数据(如 `campaigns`、`daily-metrics`、`keywords` 等,按 CLI `siluzan-tso google-analysis --help` 选择子命令),**不要**在未拉数前就把暂停阈值与写操作一并推进;暂停类命令须遵守 `references/google-ads.md` 的确认流程。
184
+ **CPC / 花费异常巡检(先查后停)**:用户要先定位异常再考虑暂停时,在确认统计区间后,优先用 `google-analysis` 拉**带花费/CPC 粒度**的数据(如 `campaigns`、`campaign-hour`、`daily-metrics`、`keywords` 等,按 CLI `siluzan-tso google-analysis --help` 选择子命令),**不要**在未拉数前就把暂停阈值与写操作一并推进;暂停类命令须遵守 `references/google-ads.md` 的确认流程。
139
185
 
140
186
  ---
141
187
 
@@ -66,7 +66,7 @@ siluzan-tso account-active-bills -m <媒体> --id <entityId> [--json]
66
66
  | `--id <entityId>` | 必填:账户 `entityId` |
67
67
  | `--json` | 输出接口原始 JSON |
68
68
 
69
- **响应体常用字段(以后端为准):**
69
+ **响应体常用字段(以接口返回为准):**
70
70
 
71
71
  | 字段 | 说明 |
72
72
  | ------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
@@ -517,7 +517,7 @@ siluzan-tso open-account kwai \
517
517
  >
518
518
  > 对应网页:`/foreign_trade/tso/manageAccounts` → 选中 TikTok 账户 → 关闭账户
519
519
  >
520
- > **实现说明(与网页 `manageAccounts` 一致)**:先请求 TikTok 网关 `CheckAdvDisable`(不满足条件如余额未清零会失败),再 `POST .../AdvertiserDisable`;Body 为各账户的 **entityId**。你只需传入 `list-accounts` 中的 **mediaCustomerId**,CLI 会解析 entityId;旧版误把 mediaCustomerId 当 Body 会导致 HTTP 成功但关户不生效。
520
+ > **实现说明(与网页 `manageAccounts` 一致)**:先经 TikTok `CheckAdvDisable` 校验(不满足条件如余额未清零会失败),再 `POST .../AdvertiserDisable`;Body 为各账户的 **entityId**。你只需传入 `list-accounts` 中的 **mediaCustomerId**,CLI 会解析 entityId;旧版误把 mediaCustomerId 当 Body 会导致 HTTP 成功但关户不生效。
521
521
 
522
522
  ```bash
523
523
  siluzan-tso account close --accounts <mediaCustomerId>
@@ -692,7 +692,7 @@ siluzan-tso account email-auth-list -c <mediaCustomerId> [--agent-type <type>]
692
692
  | 选项 | 说明 |
693
693
  | ------------------------ | -------------------------------------------------------------------------- |
694
694
  | `-c, --customer-id <id>` | Google 广告账户 `mediaCustomerId`(与网页查询参数 `customerId` 一致) |
695
- | `--agent-type <type>` | 可选;网关需要时再传(与 `list-accounts --json` 的 `ma.accountType` 一致) |
695
+ | `--agent-type <type>` | 可选;平台需要时再传(与 `list-accounts --json` 的 `ma.accountType` 一致) |
696
696
  | `--json` | 输出原始 JSON |
697
697
 
698
698
  ---
@@ -256,6 +256,38 @@ siluzan-tso ad adgroup-status -a 6326027735 --id adgroup_001 --status Enabled
256
256
 
257
257
  ---
258
258
 
259
+ ### 广告组编辑(名称 / 最高 CPC / 组级目标 CPA)
260
+
261
+ 与 `adgroup-status`、`adgroup-rename` 相同:先用 **`ad groups … --json`** 查看当前 **`maxCPCAmount`**、**`targetCpaAmount`** 等,再用本命令只改传入的字段(由 CLI 与 `siluzan-tso` 合并提交)。
262
+
263
+ ```bash
264
+ siluzan-tso ad adgroup-edit \
265
+ -a <accountId> \
266
+ --id <adGroupId> \
267
+ [--name <新名称>] \
268
+ [--max-cpc <n>] \
269
+ [--target-cpa <n>] \
270
+ [--start <YYYY-MM-DD>] [--end <YYYY-MM-DD>]
271
+ ```
272
+
273
+ | 选项 | 说明 |
274
+ |------|------|
275
+ | `--max-cpc` | 与 **`ad groups --json`** 中 **`maxCPCAmount`** 同一整数口径;与主币种展示关系见 **`maxCPCAmountDisplay`**(`SKILL.md` 金额硬规范)。 |
276
+ | `--target-cpa` | 与 **`ad groups --json`** 中 **`targetCpaAmount`** 同一整数口径。写入 **> 0** 的值才会更新组级目标 CPA;为 `0` 或不传则通常不改变该项。 |
277
+ | `--name` | 新名称(可选)。 |
278
+
279
+ **示例:**
280
+
281
+ ```bash
282
+ # 先取 JSON,用 maxCPCAmount / targetCpaAmount 算好新值后再写回
283
+ siluzan-tso ad groups -a 6326027735 --json
284
+
285
+ siluzan-tso ad adgroup-edit -a 6326027735 --id 195548094874 --max-cpc 200
286
+ siluzan-tso ad adgroup-edit -a 6326027735 --id 195548094874 --target-cpa 5000 --name "核心词_降价后"
287
+ ```
288
+
289
+ ---
290
+
259
291
  ### 广告组删除
260
292
 
261
293
  ```bash
@@ -294,6 +326,28 @@ siluzan-tso ad list -a 6326027735
294
326
  siluzan-tso ad list -a 6326027735 --json
295
327
  ```
296
328
 
329
+ ### 拒审与政策(`ad list --json`)
330
+
331
+ 使用 **`siluzan-tso ad list -a <accountId> [--start/--end] --json`**(或 **`siluzan-tso google-analysis ads … --json`**,与 `references/account-analytics.md` 中 `ads` 子命令一致)巡检素材审核状态。
332
+
333
+ **在 JSON 中可重点查看的键名(以当次 stdout 为准,多为 camelCase):**
334
+
335
+ - **`policyApprovalStatusV2`**(及可能出现的 **`policyApprovalStatus`**):审核总状态。常见数值含义(若为数字):**`2`** 表示不通过(拒审)、**`3`** 表示受限通过;若为字符串则按字面量解析。
336
+ - **`approvalStatusDetails`**:政策相关说明的**摘要串**,多条证据之间常用 **`;`** 分隔。**不提供**与控制台一一对应的「政策主题」结构化数组;需要更细粒度编码时须另辟数据源或与维护方确认。
337
+ - **`statusV2`**:广告启用状态;排除已移除条目时用 **`Removed`** 等值过滤(以实际枚举为准)。
338
+
339
+ **同源拉数**:`ad list` 与 **`google-analysis ads`** 列表数据一致;任选其一做拒审巡检即可,仍以 **当次 `--json`** 为准。
340
+
341
+ ### 转化与价值(`ad list --json`,需网关已返回对应字段)
342
+
343
+ 在已部署的 Google 网关上,创意列表 JSON 中除 **`spend`**、**`conversions`**、**`impressions`**、**`ctr`** 等外,还可关注(键名以当次输出为准):
344
+
345
+ - **`allConversions`**
346
+ - **`conversionsValue`**
347
+ - **`conversionsValuePerImpression`**(可能由后端计算属性序列化;若无则用 **`conversionsValue / impressions`** 在聚合后自行计算)
348
+
349
+ 带 **`--start` / `--end`** 时,底层按日分段,**同一创意 `id` 可能多行**;做窗口汇总或 A/B 比较前须在宿主 **按 `id` 聚合** 后再算比率。宿主编排下的 **自动优化 SOP** 见 **`references/hosted-automation-optimize-index.md`**。
350
+
297
351
  ---
298
352
 
299
353
  ### 创建广告(自适应搜索广告 RSA)
@@ -622,7 +676,7 @@ siluzan-tso keyword -k "running shoes" --json
622
676
 
623
677
  > - 默认行为:不加 `--draft` 时,CLI 直接走「立即发布」路径(`DraftStatus: Published`)。
624
678
  > - 草稿行为:加上 `--draft` 时,仅创建草稿记录(`DraftStatus: Draft`),需后续用 `ad batch publish` 才真正提交给 Google。
625
- > 广告组、关键词、广告创意的直接创建走另一套 Google 网关 API,均有对应的 `adgroup-create`、`keyword-create`、`ad-create` 等命令。
679
+ > 广告组、关键词、广告创意的分步创建请使用 `adgroup-create`、`keyword-create`、`ad-create` 等命令。
626
680
  > 任务异步处理,任务 ID 可通过 `ad batch get --id <id>` 跟进进度。
627
681
 
628
682
  ---
@@ -809,18 +863,18 @@ siluzan-tso ad adgroup-rename -a 6326027735 --id 195548094874 --name "核心词_
809
863
 
810
864
  ## ad ad-edit — 广告创意编辑(自适应搜索广告 RSA)
811
865
 
812
- 与网页端一致:先按日期范围从 **`GET {googleApi}/admanagement/v2/list/{account}`** 拉取该广告完整对象,再 **`PUT {googleApi}/admanagement/campaign/{account}/{adId}`** 提交合并后的 JSON。成功时响应体与请求体字段结构一致(含 `id`、`activeuseridg`、`typeV2`、`statusV2` 等)。
866
+ 与网页端一致:先用 **`siluzan-tso ad list -a <accountId> [--start/--end] --json`** 取得该广告的完整 JSON,再用本命令只修改传入的选项;未改动的字段由 **`siluzan-tso`** 按列表原值带回。
813
867
 
814
- CLI 会在请求前自动设置 **Datapermission**(与浏览器 `datapermission` 头同源逻辑),避免网关侧权限相关错误。
868
+ CLI 会自动附带数据权限相关请求头,减少权限类错误。
815
869
 
816
- ### 网关 JSON CLI 参数对应(常用字段)
870
+ ### `ad list --json` 常见键名与 CLI 选项(常用)
817
871
 
818
- | 网关字段 | 说明 | CLI |
872
+ | 列表 JSON 键名 | 说明 | CLI |
819
873
  | --------------------------------------------------- | --------------------------------------- | ------------------------------------------- |
820
874
  | `id` | 广告 ID | `--id` |
821
875
  | `activeuseridg` | 账户 mediaCustomerId | `-a` / `--account` |
822
876
  | `headlinePart1` / `headlinePart2` / `headlinePart3` | 前 3 条标题 | `--headlines` 前 3 项 |
823
- | `AddtionalHeadlines` | 第 4~15 条标题(网关拼写为 Addtional) | `--headlines` 第 4 项起 |
877
+ | `AddtionalHeadlines` | 第 4~15 条标题(历史拼写 Addtional) | `--headlines` 第 4 项起 |
824
878
  | `adDescription` / `adDescription2` | 前 2 条描述 | `--descriptions` 前 2 项 |
825
879
  | `AddtionalAdDescriptions` | 第 3~4 条描述 | `--descriptions` 第 3 项起 |
826
880
  | `finalUrl` | 落地页 | `--final-url` |
@@ -843,30 +897,6 @@ siluzan-tso ad ad-edit \
843
897
  [--status Enabled|Paused]
844
898
  ```
845
899
 
846
- **与 curl 等价的网页请求形态(示意,勿把真实 Token 写入文档或仓库):**
847
-
848
- ```http
849
- PUT {googleApi}/admanagement/campaign/{activeuseridg}/{id}
850
- Content-Type: application/json
851
-
852
- {
853
- "id": "<adId>",
854
- "activeuseridg": "<account>",
855
- "headlinePart1": "...",
856
- "headlinePart2": "...",
857
- "headlinePart3": "...",
858
- "adDescription": "...",
859
- "adDescription2": "...",
860
- "adGroupId": "...",
861
- "adGroup": "...",
862
- "finalUrl": "https://...",
863
- "path1": "...",
864
- "path2": "...",
865
- "typeV2": "RESPONSIVE_SEARCH_AD",
866
- "statusV2": "Paused"
867
- }
868
- ```
869
-
870
900
  **示例:**
871
901
 
872
902
  ```bash
@@ -886,7 +916,7 @@ siluzan-tso ad ad-edit -a 6326027735 --id 802428202775 --status Paused
886
916
 
887
917
  ## ad keyword-delete — 搜索关键词删除
888
918
 
889
- 与网页一致:**`DELETE {googleApi}/keywordmanagement/Keyword/{account}/batch`**,请求体为 **JSON 数组**,每项至少包含 **`adGroupId`**、**`id`**(关键词资源 id)。成功时 HTTP 2xx **响应体常为空**,属正常现象;CLI 只要未报错即表示删除请求已送达网关。请求前会自动设置 **Datapermission**;DELETE 使用带 **Content-Length** 的原始请求,避免部分网关对带 body DELETE 解析异常。
919
+ 先用 **`siluzan-tso ad keywords -a <accountId> --json`** 取得关键词 **`id`** **`adGroupId`**,再执行删除。成功时 CLI 正常结束;可用 **`ad keywords --json`** 再次核对列表。
890
920
 
891
921
  ```bash
892
922
  siluzan-tso ad keyword-delete \
@@ -895,16 +925,7 @@ siluzan-tso ad keyword-delete \
895
925
  --adgroup-id <adGroupId>
896
926
  ```
897
927
 
898
- > `--id` 与 `--adgroup-id` 来自 `ad keywords --json` `id`、`adGroupId`(与网关字段名一致)。
899
-
900
- **与 curl 等价的请求形态(示意):**
901
-
902
- ```http
903
- DELETE {googleApi}/keywordmanagement/Keyword/{account}/batch
904
- Content-Type: application/json
905
-
906
- [{"adGroupId":"193360670606","id":"2474194779750"}]
907
- ```
928
+ > `--id` 与 `--adgroup-id` 来自 **`ad keywords --json`** 中的 **`id`**、**`adGroupId`**。
908
929
 
909
930
  **示例:**
910
931
 
@@ -920,11 +941,11 @@ siluzan-tso ad keyword-delete -a 6326027735 --id 2464982882313 --adgroup-id 1955
920
941
 
921
942
  ## ad keyword-edit — 搜索关键词编辑
922
943
 
923
- 与网页一致:**先**按日期范围从 **`GET {googleApi}/keywordmanagement/v2/list/{account}`** 取该关键词完整对象,**再** **`PUT {googleApi}/keywordmanagement/Keyword/{account}/batch`**,请求体为 **JSON 数组**(通常一条),元素为合并后的关键词对象。CLI 会自动设置 **Datapermission**。
944
+ 与网页一致:**先** **`siluzan-tso ad keywords --json`** 取该关键词完整对象,**再**用本命令提交修改;未改字段随列表结果保留。
924
945
 
925
- ### 网关字段与 CLI 对应(常用)
946
+ ### `ad keywords --json` 常见键名与 CLI 选项(常用)
926
947
 
927
- | 网关字段 | 说明 | CLI |
948
+ | 列表 JSON 键名 | 说明 | CLI |
928
949
  | ----------------------------- | ----------------------------------------- | ---------------------------- |
929
950
  | `id` | 关键词资源 id | `--id` |
930
951
  | `keywordText` | 关键词文案(数组,一般一项) | `--text` → `["..."]` |
@@ -934,7 +955,7 @@ siluzan-tso ad keyword-delete -a 6326027735 --id 2464982882313 --adgroup-id 1955
934
955
  | `finalURL` | 关键词级最终到达网址 | `--final-url` |
935
956
  | `adGroupId` / `campaignId` 等 | 层级与统计字段 | 从列表保留 |
936
957
 
937
- **注意:** 成功响应也是数组;**`id` 可能与请求不一致**(网关可能返回新资源 id)。CLI 若检测到变化会打印提示,后续请用 **返回体中的新 `id`** 再查列表或再编辑。
958
+ **注意:** 成功响应也可能是数组;**`id` 可能与请求不一致**。CLI 若检测到变化会打印提示,后续请用 **返回体中的新 `id`** 再查列表或再编辑。
938
959
 
939
960
  **约束:** `--text`、`--match-type`、`--max-cpc`、`--final-url` 至少传一项。
940
961
 
@@ -948,27 +969,6 @@ siluzan-tso ad keyword-edit \
948
969
  [--final-url <url>]
949
970
  ```
950
971
 
951
- **与 curl 等价的请求形态(示意,勿写入真实 Token):**
952
-
953
- ```http
954
- PUT {googleApi}/keywordmanagement/Keyword/{account}/batch
955
- Content-Type: application/json
956
-
957
- [
958
- {
959
- "id": "<keywordId>",
960
- "keywordText": ["广告工具1"],
961
- "matchType": "EXACT",
962
- "matchTypeV2": "Broad",
963
- "maxCPC": 0,
964
- "finalURL": "https://example.com",
965
- "adGroupId": "...",
966
- "campaignId": "...",
967
- "...": "其余字段来自 list 接口"
968
- }
969
- ]
970
- ```
971
-
972
972
  **示例:**
973
973
 
974
974
  ```bash