siluzan-tso-cli 1.1.37-beta.14 → 1.1.37-beta.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.js +260 -32
- package/dist/skill/AGENTS.md +28 -21
- package/dist/skill/SKILL.md +12 -11
- package/dist/skill/_meta.json +2 -2
- package/dist/skill/assets/pmax-create-template.md +1 -1
- package/dist/skill/references/README.md +10 -10
- package/dist/skill/references/accounts/accounts-balance-stats.md +35 -18
- package/dist/skill/references/accounts/accounts-list.md +1 -1
- package/dist/skill/references/accounts/accounts-permissions.md +2 -9
- package/dist/skill/references/accounts/accounts.md +3 -3
- package/dist/skill/references/accounts/finance.md +1 -2
- package/dist/skill/references/accounts/open-account-by-media.md +1 -2
- package/dist/skill/references/analytics/account-analytics.md +4 -7
- package/dist/skill/references/analytics/google-analysis-batch.md +1 -2
- package/dist/skill/references/analytics/keyword-planner-workflows.md +3 -3
- package/dist/skill/references/analytics/market-analysis-guide.md +1 -4
- package/dist/skill/references/analytics/reporting.md +1 -3
- package/dist/skill/references/core/agent-conventions.md +72 -8
- package/dist/skill/references/core/intent-routing.md +54 -11
- package/dist/skill/references/core/playbooks.md +24 -19
- package/dist/skill/references/core/setup.md +1 -4
- package/dist/skill/references/core/skill-authoring.md +18 -6
- package/dist/skill/references/core/user-communication-guide.md +2 -116
- package/dist/skill/references/core/workflows.md +17 -18
- package/dist/skill/references/google-ads/google-ads-batch.md +3 -4
- package/dist/skill/references/google-ads/google-ads-campaign-plan.md +2 -2
- package/dist/skill/references/google-ads/google-ads-read.md +3 -4
- package/dist/skill/references/google-ads/google-ads-write.md +3 -4
- package/dist/skill/references/google-ads/google-ads.md +3 -3
- package/dist/skill/references/google-ads/rules/README.md +3 -4
- package/dist/skill/references/google-ads/rules/google-ads-account-audit.md +2 -3
- package/dist/skill/references/google-ads/rules/google-ads-audience-strategy.md +1 -2
- package/dist/skill/references/google-ads/rules/google-ads-campaign-optimization.md +1 -3
- package/dist/skill/references/google-ads/rules/google-ads-compliance.md +2 -4
- package/dist/skill/references/google-ads/rules/google-ads-conversion-architecture.md +1 -2
- package/dist/skill/references/google-ads/rules/google-ads-creative-optimization.md +1 -3
- package/dist/skill/references/google-ads/rules/google-ads-keyword-optimization.md +1 -3
- package/dist/skill/references/google-ads/rules/google-ads-keyword-strategy.md +1 -3
- package/dist/skill/references/google-ads/rules/google-ads-keyword-taxonomy.md +1 -2
- package/dist/skill/references/google-ads/rules/google-ads-launch-plan-template.md +1 -5
- package/dist/skill/references/google-ads/rules/google-ads-plan-source-fidelity.md +1 -4
- package/dist/skill/references/google-ads/rules/google-ads-pmax-guide.md +1 -2
- package/dist/skill/references/google-ads/rules/sensitive-industries.md +1 -3
- package/dist/skill/references/operations/clue.md +1 -3
- package/dist/skill/references/operations/hosted-automation-optimize-scale.md +1 -2
- package/dist/skill/references/operations/hosted-automation-user-catalog.md +1 -3
- package/dist/skill/references/operations/optimize.md +1 -3
- package/dist/skill/references/report-templates/google-inquiry-analysis.md +1 -3
- package/dist/skill/references/report-templates/meta-period-report-excel.md +1 -2
- package/dist/skill/report-templates/google-inquiry-analysis.md +1 -3
- package/dist/skill/report-templates/meta-period-report-excel.md +1 -2
- package/dist/skill/scripts/install.ps1 +1 -1
- package/dist/skill/scripts/install.sh +1 -1
- package/eval/cases/accounts-entityid-vs-mediaccustomerid.scenario.json +14 -2
- package/eval/cases/accounts-mcc-bind-inquiry.scenario.json +3 -1
- package/eval/cases/accounts-single-balance-not-bulk.scenario.json +14 -3
- package/eval/cases/budget-display-not-raw-micros.scenario.json +8 -1
- package/eval/cases/clue-meta-leads-json.scenario.json +14 -2
- package/eval/cases/clue-tiktok-leads-json.scenario.json +11 -2
- package/eval/cases/destructive-account-delink-needs-confirm.scenario.json +9 -3
- package/eval/cases/destructive-forewarning-delete-needs-confirm.scenario.json +9 -3
- package/eval/cases/destructive-invoice-apply-needs-confirm.scenario.json +9 -3
- package/eval/cases/facebook-analysis-google-section-aliases.scenario.json +11 -2
- package/eval/cases/facebook-analysis-not-google-keywords.scenario.json +10 -3
- package/eval/cases/facebook-analysis-period-default.scenario.json +14 -2
- package/eval/cases/finance-invoice-info-list.scenario.json +11 -3
- package/eval/cases/forewarning-list-google.scenario.json +14 -3
- package/eval/cases/google-ads-no-structural-without-confirm.scenario.json +6 -2
- package/eval/cases/google-analysis-keywords-route.scenario.json +14 -2
- package/eval/cases/human-p1-multiturn.scenario.json +5 -1
- package/eval/cases/ir-p1-vs-p8-account-vs-url.scenario.json +17 -5
- package/eval/cases/ir-p3-cpa-monitor-not-p7.scenario.json +33 -0
- package/eval/cases/ir-p3-zero-inquiry-not-p7.scenario.json +27 -0
- package/eval/cases/ir-p4-period-not-diagnosis.scenario.json +16 -3
- package/eval/cases/ir-p8-network-diagnosis-with-url.scenario.json +25 -3
- package/eval/cases/ir-p8-website-monitor-report-with-url.scenario.json +28 -3
- package/eval/cases/ir-p8-website-test-report-no-url.scenario.json +14 -3
- package/eval/cases/ir-p9-industry-not-p8.scenario.json +19 -3
- package/eval/cases/ir-vague-report-clarify.scenario.json +14 -3
- package/eval/cases/ir-w3-vs-p8-from-website.scenario.json +8 -2
- package/eval/cases/ir-w5-keyword-planner-url-core-terms.scenario.json +22 -2
- package/eval/cases/meta-single-balance-not-bulk.scenario.json +17 -3
- package/eval/cases/no-legacy-json-flag.scenario.json +6 -2
- package/eval/cases/open-account-google-noninteractive.scenario.json +3 -1
- package/eval/cases/open-account-tiktok-license-file.scenario.json +3 -1
- package/eval/cases/optimize-list-by-account.scenario.json +11 -3
- package/eval/cases/p1-single-account-profile.scenario.json +11 -1
- package/eval/cases/p2-balance-scan-bulk.scenario.json +9 -2
- package/eval/cases/p3-accounts-digest.scenario.json +5 -1
- package/eval/cases/p3-cpa-scan-max-cpa.scenario.json +23 -0
- package/eval/cases/p4-fb-meta-period-report.scenario.json +12 -2
- package/eval/cases/p4-period-report-window.scenario.json +8 -1
- package/eval/cases/pmax-asset-group-create-with-bg.scenario.json +13 -2
- package/eval/cases/pmax-brand-edit-routing.scenario.json +16 -3
- package/eval/cases/pmax-edit-not-campaign-edit.scenario.json +12 -2
- package/eval/cases/pmax-enable-brand-guidelines.scenario.json +12 -2
- package/eval/cases/pmax-no-assets-update-brand-fields.scenario.json +14 -3
- package/eval/cases/rag-before-keyword-expand.scenario.json +11 -1
- package/eval/cases/rag-list-then-query.scenario.json +14 -2
- package/eval/cases/report-list-google.scenario.json +11 -2
- package/eval/cases/report-push-list-google.scenario.json +11 -2
- package/eval/cases/setup-login-or-env.scenario.json +3 -1
- package/eval/cases/setup-siluzan-data-permission-env.scenario.json +3 -1
- package/eval/cases/tiktok-bc-bind-inquiry.scenario.json +6 -2
- package/eval/cases/time-range-user-delegates-default.scenario.json +8 -1
- package/eval/cases/tips-json-out-filtering.scenario.json +3 -1
- package/eval/cases/tips-large-json-pagination.scenario.json +3 -1
- package/eval/cases/uj-ad-campaign-validate-before-create-stub.scenario.json +11 -2
- package/eval/cases/uj-ad-outdoor-campgear-search-plan.scenario.json +3 -1
- package/eval/cases/uj-ad-website-search-plan-table-format.scenario.json +3 -1
- package/eval/cases/uj-analytics-30d-pdf-campaign-device-geo.scenario.json +18 -6
- package/eval/cases/uj-analytics-compare-google-tiktok-last-month-roi.scenario.json +8 -1
- package/eval/cases/uj-analytics-ecommerce-industry-report.scenario.json +14 -2
- package/eval/cases/uj-analytics-google-weekly-trends-campaigns-keywords.scenario.json +11 -2
- package/eval/cases/uj-analytics-report-push-weekly-email.scenario.json +3 -1
- package/eval/cases/uj-finance-invoice-records-this-month.scenario.json +11 -2
- package/eval/cases/uj-life-newbie-siluzan-google-end-to-end.scenario.json +4 -1
- package/eval/cases/uj-ops-google-accounts-list-normal.scenario.json +17 -2
- package/eval/cases/uj-ops-google-yesterday-spend-conversions.scenario.json +14 -2
- package/eval/cases/uj-ops-pause-worst-adgroup-confirm.scenario.json +6 -2
- package/eval/cases/uj-ops-tiktok-leads-last-week.scenario.json +17 -3
- package/eval/cases/uj-patrol-cpc-spike-adgroups-over-15.scenario.json +5 -1
- package/eval/cases/uj-patrol-forewarning-create-daily-cap-3000.scenario.json +3 -1
- package/eval/cases/uj-patrol-forewarning-trigger-records.scenario.json +17 -3
- package/eval/cases/uj-patrol-google-balances-low.scenario.json +11 -2
- package/eval/cases/uj-roi-optimize-records-then-execute-cautiously.scenario.json +14 -3
- package/eval/cases/uj-roi-search-terms-add-negative-keywords.scenario.json +14 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -51,7 +51,7 @@ siluzan-tso init -d /path/to/skills # 写入自定义目录
|
|
|
51
51
|
siluzan-tso init --force # 强制覆盖已存在文件
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
> **注意**:当前为测试版(1.1.37-beta.
|
|
54
|
+
> **注意**:当前为测试版(1.1.37-beta.16),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-tso-cli`。
|
|
55
55
|
|
|
56
56
|
| 助手 | 建议 `--ai` |
|
|
57
57
|
| ----------------------- | ------------------------------------ |
|
package/dist/index.js
CHANGED
|
@@ -5023,6 +5023,33 @@ var init_list_fetch = __esm({
|
|
|
5023
5023
|
}
|
|
5024
5024
|
});
|
|
5025
5025
|
|
|
5026
|
+
// src/commands/accounts-digest/filters.ts
|
|
5027
|
+
function keepDigestRow(row, opts) {
|
|
5028
|
+
const { maxCpa, zeroConversions } = opts;
|
|
5029
|
+
if (maxCpa == null && !zeroConversions) return true;
|
|
5030
|
+
const spend = row.spend ?? 0;
|
|
5031
|
+
const conv = row.conversions;
|
|
5032
|
+
const cpa = row.cpa;
|
|
5033
|
+
if (zeroConversions) {
|
|
5034
|
+
if (spend > 0 && (conv == null || conv === 0)) return true;
|
|
5035
|
+
if (maxCpa == null) return false;
|
|
5036
|
+
}
|
|
5037
|
+
if (maxCpa != null) {
|
|
5038
|
+
if (cpa != null && cpa > maxCpa) return true;
|
|
5039
|
+
if (spend > 0 && conv === 0) return true;
|
|
5040
|
+
return false;
|
|
5041
|
+
}
|
|
5042
|
+
return false;
|
|
5043
|
+
}
|
|
5044
|
+
function countNullConversions(rows) {
|
|
5045
|
+
return rows.reduce((n, r) => n + (r.conversions == null ? 1 : 0), 0);
|
|
5046
|
+
}
|
|
5047
|
+
var init_filters = __esm({
|
|
5048
|
+
"src/commands/accounts-digest/filters.ts"() {
|
|
5049
|
+
"use strict";
|
|
5050
|
+
}
|
|
5051
|
+
});
|
|
5052
|
+
|
|
5026
5053
|
// src/commands/accounts-digest/run.ts
|
|
5027
5054
|
function round2(n) {
|
|
5028
5055
|
if (n == null) return null;
|
|
@@ -5136,7 +5163,7 @@ async function runAccountsDigest(opts) {
|
|
|
5136
5163
|
const ctr = impressions && impressions > 0 && clicks != null ? clicks / impressions : null;
|
|
5137
5164
|
const cpc = clicks && clicks > 0 && spend != null ? spend / clicks : null;
|
|
5138
5165
|
const cpa = conversions && conversions > 0 && spend != null ? spend / conversions : null;
|
|
5139
|
-
|
|
5166
|
+
const row = {
|
|
5140
5167
|
mediaCustomerId: id,
|
|
5141
5168
|
name: ma.mediaCustomerName ?? bal?.name ?? ov?.mediaCustomerName ?? null,
|
|
5142
5169
|
advertiserName: item.mag?.advertiserName ?? null,
|
|
@@ -5151,7 +5178,14 @@ async function runAccountsDigest(opts) {
|
|
|
5151
5178
|
cpc: round2(cpc),
|
|
5152
5179
|
cpa: round2(cpa),
|
|
5153
5180
|
invalidOAuthToken: !!ma.invalidOAuthToken
|
|
5154
|
-
}
|
|
5181
|
+
};
|
|
5182
|
+
if (!keepDigestRow(row, {
|
|
5183
|
+
maxCpa: opts.maxCpa,
|
|
5184
|
+
zeroConversions: opts.zeroConversions
|
|
5185
|
+
})) {
|
|
5186
|
+
continue;
|
|
5187
|
+
}
|
|
5188
|
+
rows.push(row);
|
|
5155
5189
|
}
|
|
5156
5190
|
rows.sort((a, b) => (b.spend ?? 0) - (a.spend ?? 0));
|
|
5157
5191
|
const totals = rows.reduce(
|
|
@@ -5175,6 +5209,12 @@ async function runAccountsDigest(opts) {
|
|
|
5175
5209
|
/** 取数策略:list = 全量翻清单后过滤,subset = 跳过翻页直接对 -a 指定的 ID 拉数据 */
|
|
5176
5210
|
source: scannedFromList ? "list" : "subset",
|
|
5177
5211
|
returned: rows.length,
|
|
5212
|
+
nullConversionCount: countNullConversions(rows),
|
|
5213
|
+
filters: {
|
|
5214
|
+
minSpend,
|
|
5215
|
+
maxCpa: opts.maxCpa ?? null,
|
|
5216
|
+
zeroConversions: !!opts.zeroConversions
|
|
5217
|
+
},
|
|
5178
5218
|
batchChunkSize: validIds.length > 0 ? batchChunkSize : null,
|
|
5179
5219
|
totals: {
|
|
5180
5220
|
spend: +totals.spend.toFixed(2),
|
|
@@ -5234,13 +5274,20 @@ ${media} \u8D26\u6237\u6295\u653E\u753B\u50CF\uFF1A\u8FD4\u56DE ${rows.length} \
|
|
|
5234
5274
|
balance: formatMoneyDisplay(r.balance, r.currencyCode)
|
|
5235
5275
|
}));
|
|
5236
5276
|
printCliTable(tableRows, cols);
|
|
5277
|
+
if (meta.nullConversionCount > 0) {
|
|
5278
|
+
process.stderr.write(
|
|
5279
|
+
`\u26A0 \u8F6C\u5316\u5B57\u6BB5\u4E3A\u7A7A ${meta.nullConversionCount} \u6237\uFF1A\u52FF\u7528\u6570\u503C\u6BD4\u8F83 null\uFF1B\u8FC7\u6EE4\u89C1 --max-cpa / --zero-conversions
|
|
5280
|
+
`
|
|
5281
|
+
);
|
|
5282
|
+
}
|
|
5237
5283
|
console.log(
|
|
5238
5284
|
`
|
|
5239
|
-
\u6C47\u603B\uFF1A\u6D88\u8017 ${meta.totals.spend}\uFF0C\u70B9\u51FB ${meta.totals.clicks}\uFF0C\u5C55\u793A ${meta.totals.impressions}\uFF0C\u8F6C\u5316 ${meta.totals.conversions}
|
|
5285
|
+
\u6C47\u603B\uFF1A\u6D88\u8017 ${meta.totals.spend}\uFF0C\u70B9\u51FB ${meta.totals.clicks}\uFF0C\u5C55\u793A ${meta.totals.impressions}\uFF0C\u8F6C\u5316 ${meta.totals.conversions}\uFF08\u8F6C\u5316\u672A\u8FD4\u56DE ${meta.nullConversionCount} \u6237\uFF09
|
|
5240
5286
|
\u63D0\u793A\uFF1A
|
|
5241
5287
|
- \u91D1\u989D\u4F7F\u7528\u5404\u8D26\u6237\u4E3B\u5E01\u79CD\uFF1B\u8DE8\u5E01\u79CD\u8D26\u6237\u52A0 --json-out \u81EA\u884C\u6309 currencyCode \u805A\u5408
|
|
5242
5288
|
- \u6307\u5B9A\u8D26\u6237\u5B50\u96C6\uFF1A--accounts <id1,id2,...>\uFF08\u4E0E list-accounts \u7684 mediaCustomerId \u4E00\u81F4\uFF09
|
|
5243
|
-
- \u8FC7\u6EE4\u4F4E\u6D88\u8017\uFF1A--min-spend 10\
|
|
5289
|
+
- \u8FC7\u6EE4\u4F4E\u6D88\u8017\uFF1A--min-spend 10\uFF1B\u9AD8 CPA\uFF1A--max-cpa 500\uFF1B\u96F6\u8F6C\u5316\uFF1A--zero-conversions
|
|
5290
|
+
- \u65E0 --period\uFF1B\u533A\u95F4\u7528 --start/--end\uFF08\u6216 --start-date/--end-date\uFF09
|
|
5244
5291
|
`
|
|
5245
5292
|
);
|
|
5246
5293
|
}
|
|
@@ -5255,23 +5302,32 @@ var init_run = __esm({
|
|
|
5255
5302
|
init_media_account_batch();
|
|
5256
5303
|
init_media_account_lookup();
|
|
5257
5304
|
init_list_fetch();
|
|
5305
|
+
init_filters();
|
|
5258
5306
|
}
|
|
5259
5307
|
});
|
|
5260
5308
|
|
|
5261
5309
|
// src/commands/accounts-digest/_register.ts
|
|
5262
5310
|
function register10(program2) {
|
|
5263
5311
|
program2.command("accounts-digest").description(
|
|
5264
|
-
"\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\u3002"
|
|
5312
|
+
"\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"
|
|
5265
5313
|
).requiredOption(
|
|
5266
5314
|
"-m, --media <type>",
|
|
5267
5315
|
"\u5A92\u4F53\u7C7B\u578B\uFF1AGoogle | TikTok | Yandex | MetaAd | BingV2 | Kwai"
|
|
5268
5316
|
).option(
|
|
5269
5317
|
"-a, --accounts <ids>",
|
|
5270
5318
|
"\u6307\u5B9A\u8D26\u6237 mediaCustomerId\uFF0C\u9017\u53F7\u5206\u9694\uFF1B\u7559\u7A7A\u5219\u626B\u63CF\u8BE5\u5A92\u4F53\u4E0B\u5168\u90E8\u8D26\u6237"
|
|
5271
|
-
).option("--start <date>", "\u7EDF\u8BA1\u5F00\u59CB\u65E5\u671F YYYY-MM-DD\uFF08SKILL \u8981\u6C42 AI \u5148\u4E0E\u7528\u6237\u786E\u8BA4\uFF09").option("--end <date>", "\u7EDF\u8BA1\u7ED3\u675F\u65E5\u671F YYYY-MM-DD\uFF08SKILL \u8981\u6C42 AI \u5148\u4E0E\u7528\u6237\u786E\u8BA4\uFF09").option(
|
|
5319
|
+
).option("--start <date>", "\u7EDF\u8BA1\u5F00\u59CB\u65E5\u671F YYYY-MM-DD\uFF08SKILL \u8981\u6C42 AI \u5148\u4E0E\u7528\u6237\u786E\u8BA4\uFF09").option("--end <date>", "\u7EDF\u8BA1\u7ED3\u675F\u65E5\u671F YYYY-MM-DD\uFF08SKILL \u8981\u6C42 AI \u5148\u4E0E\u7528\u6237\u786E\u8BA4\uFF09").option("--start-date <date>", "\u540C --start\uFF08\u6587\u6863/Playbook \u517C\u5BB9\u522B\u540D\uFF09").option("--end-date <date>", "\u540C --end\uFF08\u6587\u6863/Playbook \u517C\u5BB9\u522B\u540D\uFF09").option(
|
|
5272
5320
|
"--min-spend <n>",
|
|
5273
5321
|
"\u8FC7\u6EE4\uFF1A\u533A\u95F4\u5185\u6D88\u8017 \u2264 \u6B64\u503C\u7684\u8D26\u6237\u4E0D\u8FD4\u56DE\uFF08\u9ED8\u8BA4 0\uFF09",
|
|
5274
5322
|
(v) => parseFloat(v)
|
|
5323
|
+
).option(
|
|
5324
|
+
"--max-cpa <n>",
|
|
5325
|
+
"\u8FC7\u6EE4\uFF1A\u4FDD\u7559 CPA > \u6B64\u503C\u7684\u8D26\u6237\uFF1B\u6709\u6D88\u8017\u4E14\u8F6C\u5316\u4E3A 0 \u89C6\u4E3A\u547D\u4E2D\uFF08CPA \u65E0\u7A77\uFF09",
|
|
5326
|
+
(v) => parseFloat(v)
|
|
5327
|
+
).option(
|
|
5328
|
+
"--zero-conversions",
|
|
5329
|
+
"\u8FC7\u6EE4\uFF1A\u4FDD\u7559\u533A\u95F4\u6D88\u8017 > 0 \u4E14\u8F6C\u5316 = 0 \u6216\u8F6C\u5316\u672A\u8FD4\u56DE\u7684\u8D26\u6237",
|
|
5330
|
+
false
|
|
5275
5331
|
).option("--page-size <n>", "\u8D26\u6237\u6E05\u5355\u5206\u9875\u5927\u5C0F\uFF08\u9ED8\u8BA4 200\uFF0C\u4E0A\u9650 500\uFF09", (v) => parseInt(v, 10)).option("--max-pages <n>", "\u6700\u591A\u626B\u63CF\u9875\u6570\uFF08\u9ED8\u8BA4 20\uFF0C\u4E0A\u9650 200\uFF09", (v) => parseInt(v, 10)).option("-t, --token <token>", "Token\uFF08\u53EF\u9009\uFF1B\u4F18\u5148\u4E8E ~/.siluzan/config.json\uFF09").option(
|
|
5276
5332
|
"--json-out <path>",
|
|
5277
5333
|
"\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",
|
|
@@ -5282,9 +5338,11 @@ function register10(program2) {
|
|
|
5282
5338
|
token: opts.token,
|
|
5283
5339
|
media: opts.media,
|
|
5284
5340
|
accounts: opts.accounts,
|
|
5285
|
-
startDate: opts.start,
|
|
5286
|
-
endDate: opts.end,
|
|
5341
|
+
startDate: opts.start ?? opts.startDate,
|
|
5342
|
+
endDate: opts.end ?? opts.endDate,
|
|
5287
5343
|
minSpend: opts.minSpend,
|
|
5344
|
+
maxCpa: opts.maxCpa,
|
|
5345
|
+
zeroConversions: opts.zeroConversions,
|
|
5288
5346
|
pageSize: opts.pageSize,
|
|
5289
5347
|
maxPages: opts.maxPages,
|
|
5290
5348
|
jsonOut: opts.jsonOut,
|
|
@@ -5307,6 +5365,7 @@ var init_accounts_digest = __esm({
|
|
|
5307
5365
|
"use strict";
|
|
5308
5366
|
init_run();
|
|
5309
5367
|
init_list_fetch();
|
|
5368
|
+
init_filters();
|
|
5310
5369
|
init_register();
|
|
5311
5370
|
}
|
|
5312
5371
|
});
|
|
@@ -103436,8 +103495,8 @@ async function cmdRun(opts) {
|
|
|
103436
103495
|
const result = await executeBatchRun({
|
|
103437
103496
|
jsonOut: opts.jsonOut,
|
|
103438
103497
|
runId: opts.runId,
|
|
103439
|
-
start: opts.start,
|
|
103440
|
-
end: opts.end,
|
|
103498
|
+
start: opts.start ?? opts.startDate,
|
|
103499
|
+
end: opts.end ?? opts.endDate,
|
|
103441
103500
|
sections,
|
|
103442
103501
|
explicitAccountIds: explicitIds.length > 0 ? explicitIds : void 0,
|
|
103443
103502
|
accountConcurrency,
|
|
@@ -103612,7 +103671,7 @@ function registerGoogleAnalysisBatchCommands(program2) {
|
|
|
103612
103671
|
grp.command("run").description("\u4E00\u6B21\u6027\u6279\u8DD1\uFF1A\u81EA\u52A8\u62C9\u8D26\u6237\u6E05\u5355 + \u6309\u8D26\u6237\xD7\u7EF4\u5EA6\u5E76\u53D1\u6267\u884C + \u843D\u76D8 manifest/progress").requiredOption("--json-out <baseDir>", "\u4EA7\u7269\u6839\u76EE\u5F55\uFF08\u6BCF\u4E2A runId \u4E00\u4E2A\u5B50\u76EE\u5F55\uFF09").option("--run-id <id>", "\u53EF\u9009\u81EA\u5B9A\u4E49 runId\uFF08\u7559\u7A7A\u81EA\u52A8\u751F\u6210 run-YYYYMMDD-HHmmss-<rand4>\uFF09").option(
|
|
103613
103672
|
"-a, --accounts <ids>",
|
|
103614
103673
|
"\u663E\u5F0F\u6307\u5B9A mediaCustomerId \u5217\u8868\uFF08\u9017\u53F7\u5206\u9694\uFF09\uFF1B\u4F20\u5165\u5219\u8DF3\u8FC7\u8D26\u6237\u6E05\u5355\u62C9\u53D6\u4E0E --min-spend \u8FC7\u6EE4"
|
|
103615
|
-
).option("--start <date>", "\u7EDF\u8BA1\u5F00\u59CB\u65E5\u671F YYYY-MM-DD\uFF08\u5F3A\u70C8\u5EFA\u8BAE\u663E\u5F0F\u6307\u5B9A\uFF09").option("--end <date>", "\u7EDF\u8BA1\u7ED3\u675F\u65E5\u671F YYYY-MM-DD").option("--sections <list>", `\u8981\u62C9\u53D6\u7684\u7EF4\u5EA6\uFF08\u9017\u53F7\u5206\u9694\uFF09\uFF0C\u9ED8\u8BA4 ${DEFAULT_SECTIONS.join(",")}`).option(
|
|
103674
|
+
).option("--start <date>", "\u7EDF\u8BA1\u5F00\u59CB\u65E5\u671F YYYY-MM-DD\uFF08\u5F3A\u70C8\u5EFA\u8BAE\u663E\u5F0F\u6307\u5B9A\uFF09").option("--end <date>", "\u7EDF\u8BA1\u7ED3\u675F\u65E5\u671F YYYY-MM-DD").option("--start-date <date>", "\u540C --start\uFF08\u6587\u6863/Playbook \u517C\u5BB9\u522B\u540D\uFF09").option("--end-date <date>", "\u540C --end\uFF08\u6587\u6863/Playbook \u517C\u5BB9\u522B\u540D\uFF09").option("--sections <list>", `\u8981\u62C9\u53D6\u7684\u7EF4\u5EA6\uFF08\u9017\u53F7\u5206\u9694\uFF09\uFF0C\u9ED8\u8BA4 ${DEFAULT_SECTIONS.join(",")}`).option(
|
|
103616
103675
|
"--account-concurrency <n>",
|
|
103617
103676
|
`\u8D26\u6237\u7EA7\u5E76\u53D1\uFF0C\u9ED8\u8BA4 ${DEFAULT_ACCOUNT_CONCURRENCY}\uFF08\u4E0A\u9650 16\uFF09`,
|
|
103618
103677
|
(v) => parseInt(v, 10)
|
|
@@ -103681,6 +103740,13 @@ var init_google_analysis_batch = __esm({
|
|
|
103681
103740
|
import * as path30 from "path";
|
|
103682
103741
|
import { performance as performance4 } from "perf_hooks";
|
|
103683
103742
|
import { Command } from "commander";
|
|
103743
|
+
function normalizeAnalysisDateOpts(opts) {
|
|
103744
|
+
return {
|
|
103745
|
+
...opts,
|
|
103746
|
+
start: opts.start ?? opts.startDate,
|
|
103747
|
+
end: opts.end ?? opts.endDate
|
|
103748
|
+
};
|
|
103749
|
+
}
|
|
103684
103750
|
function resolveSectionList(sections, exclude) {
|
|
103685
103751
|
const allNames = SECTIONS.map((s) => s.name);
|
|
103686
103752
|
const splitClean = (s) => (s ?? "").split(",").map((x) => x.trim()).filter(Boolean);
|
|
@@ -103900,7 +103966,7 @@ function registerRunCommand() {
|
|
|
103900
103966
|
).option("-t, --token <token>", "Auth Token").option(
|
|
103901
103967
|
"--start <date>",
|
|
103902
103968
|
"\u5F00\u59CB\u65E5\u671F YYYY-MM-DD\uFF08range \u7C7B\u7EF4\u5EA6\u751F\u6548\uFF1B\u7701\u7565=\u8FD1 7 \u5929\u622A\u81F3\u6628\u5929\uFF1B\u4E0E --end \u540C\u4F20\u6216\u540C\u7701\uFF09"
|
|
103903
|
-
).option("--end <date>", "\u7ED3\u675F\u65E5\u671F YYYY-MM-DD").option(
|
|
103969
|
+
).option("--end <date>", "\u7ED3\u675F\u65E5\u671F YYYY-MM-DD").option("--start-date <date>", "\u540C --start\uFF08\u6587\u6863/Playbook \u517C\u5BB9\u522B\u540D\uFF09").option("--end-date <date>", "\u540C --end\uFF08\u6587\u6863/Playbook \u517C\u5BB9\u522B\u540D\uFF09").option(
|
|
103904
103970
|
"--sections <list>",
|
|
103905
103971
|
"\u4EC5\u6267\u884C\u6307\u5B9A\u7EF4\u5EA6\uFF08\u9017\u53F7\u5206\u9694\uFF09\uFF0C\u5982 overview,keywords,ads\uFF1B\u7701\u7565=\u5168\u90E8 25 \u4E2A"
|
|
103906
103972
|
).option(
|
|
@@ -103971,20 +104037,21 @@ ${fixHint}
|
|
|
103971
104037
|
);
|
|
103972
104038
|
process.exit(1);
|
|
103973
104039
|
}
|
|
103974
|
-
const
|
|
104040
|
+
const normalized = normalizeAnalysisDateOpts(opts);
|
|
104041
|
+
const ids = parseAccountIdsForAnalysis(normalized.account ?? "");
|
|
103975
104042
|
if (ids.length === 0) {
|
|
103976
104043
|
console.error("\n\u274C --account \u4E0D\u80FD\u4E3A\u7A7A\u3002\n");
|
|
103977
104044
|
process.exit(1);
|
|
103978
104045
|
}
|
|
103979
104046
|
if (ids.length >= 2) {
|
|
103980
|
-
if (!
|
|
104047
|
+
if (!normalized.jsonOut?.trim()) {
|
|
103981
104048
|
console.error("\n\u274C \u591A\u8D26\u6237\u6A21\u5F0F\u5FC5\u987B\u4F20 --json-out <\u76EE\u5F55>\uFF08\u6309 runId \u5B50\u76EE\u5F55\u7EC4\u7EC7\u4EA7\u7269\uFF09\u3002\n");
|
|
103982
104049
|
process.exit(1);
|
|
103983
104050
|
}
|
|
103984
|
-
await runMultiAccountViaBatch(ids,
|
|
104051
|
+
await runMultiAccountViaBatch(ids, normalized);
|
|
103985
104052
|
return;
|
|
103986
104053
|
}
|
|
103987
|
-
await runAllSections({ ...
|
|
104054
|
+
await runAllSections({ ...normalized, account: ids[0] });
|
|
103988
104055
|
});
|
|
103989
104056
|
}
|
|
103990
104057
|
function registerGoogleAnalysisCommands(program2) {
|
|
@@ -106606,6 +106673,37 @@ async function fetchAllAccountPages(media, pageSize, maxPages, config, verbose)
|
|
|
106606
106673
|
return { items: allItems, total };
|
|
106607
106674
|
}
|
|
106608
106675
|
|
|
106676
|
+
// src/commands/balance-scan/data-health.ts
|
|
106677
|
+
function assessBalanceScanDataHealth(input) {
|
|
106678
|
+
const { scannedAccounts, validAccounts, balances } = input;
|
|
106679
|
+
if (scannedAccounts <= 0) {
|
|
106680
|
+
return {
|
|
106681
|
+
code: "no_accounts",
|
|
106682
|
+
message: "\u672A\u626B\u5230\u4EFB\u4F55\u8D26\u6237\uFF1A\u8BF7\u786E\u8BA4 -m \u5A92\u4F53\u7C7B\u578B\uFF0C\u6216\u7528 -a \u6307\u5B9A mediaCustomerId\uFF1B\u5168\u91CF\u6A21\u5F0F\u68C0\u67E5\u767B\u5F55\u4E0E list-accounts \u662F\u5426\u6709\u6570\u636E"
|
|
106683
|
+
};
|
|
106684
|
+
}
|
|
106685
|
+
if (validAccounts <= 0) {
|
|
106686
|
+
return {
|
|
106687
|
+
code: "all_oauth_invalid",
|
|
106688
|
+
message: "\u8D26\u6237\u5747\u56E0 OAuth \u5931\u6548\u88AB\u8DF3\u8FC7\uFF1A\u8BF7\u5728\u4E1D\u8DEF\u8D5E\u91CD\u65B0\u6388\u6743\u540E\u518D balance-scan\uFF1B\u6216\u7528 -a \u6307\u5B9A\u4ECD\u6709\u6548\u7684\u8D26\u6237"
|
|
106689
|
+
};
|
|
106690
|
+
}
|
|
106691
|
+
if (balances.length === 0) {
|
|
106692
|
+
return {
|
|
106693
|
+
code: "all_balances_null",
|
|
106694
|
+
message: "\u672A\u62C9\u5230\u4EFB\u4F55\u4F59\u989D\u884C\uFF1A\u8BF7\u52A0 --verbose \u67E5\u770B\u63A5\u53E3\u9519\u8BEF\uFF1B\u53EF\u8BD5 --refresh-dp \u6216 siluzan-tso login \u540E\u91CD\u8BD5"
|
|
106695
|
+
};
|
|
106696
|
+
}
|
|
106697
|
+
const allNull = balances.every((b) => b == null);
|
|
106698
|
+
if (allNull) {
|
|
106699
|
+
return {
|
|
106700
|
+
code: "all_balances_null",
|
|
106701
|
+
message: "\u5168\u90E8\u8D26\u6237\u4F59\u989D\u4E3A null\uFF08\u63A5\u53E3\u672A\u8FD4\u56DE\u53EF\u7528\u4F59\u989D\uFF09\uFF1A\u65E0\u6CD5\u8BA1\u7B97\u7EED\u822A\u3002\u8BF7\u68C0\u67E5\u5A92\u4F53\u6388\u6743/\u8D26\u6237\u72B6\u6001\uFF0C\u52A0 --verbose \u770B\u539F\u59CB\u54CD\u5E94\uFF0C\u6216 --refresh-dp / \u91CD\u65B0 login \u540E\u91CD\u8BD5"
|
|
106702
|
+
};
|
|
106703
|
+
}
|
|
106704
|
+
return null;
|
|
106705
|
+
}
|
|
106706
|
+
|
|
106609
106707
|
// src/commands/balance-scan/run.ts
|
|
106610
106708
|
async function runBalanceScan(opts) {
|
|
106611
106709
|
let config = loadConfig(opts.token);
|
|
@@ -106750,6 +106848,12 @@ async function runBalanceScan(opts) {
|
|
|
106750
106848
|
const bd = b.remainingDays ?? Number.POSITIVE_INFINITY;
|
|
106751
106849
|
return ad - bd;
|
|
106752
106850
|
});
|
|
106851
|
+
const balancesForHealth = validIds.map((id) => balanceMap.get(id)?.remainingAccountBudget);
|
|
106852
|
+
const dataIssue = assessBalanceScanDataHealth({
|
|
106853
|
+
scannedAccounts: allItems.length,
|
|
106854
|
+
validAccounts: validIds.length,
|
|
106855
|
+
balances: balancesForHealth
|
|
106856
|
+
});
|
|
106753
106857
|
const meta = {
|
|
106754
106858
|
media,
|
|
106755
106859
|
source: isSubset ? "subset" : "list",
|
|
@@ -106757,6 +106861,9 @@ async function runBalanceScan(opts) {
|
|
|
106757
106861
|
validAccounts: validIds.length,
|
|
106758
106862
|
skippedInvalidOAuth: allItems.length - validIds.length,
|
|
106759
106863
|
hitCount: evaluated.length,
|
|
106864
|
+
nullBalanceCount: balancesForHealth.filter((b) => b == null).length,
|
|
106865
|
+
dataIssue: dataIssue?.code ?? null,
|
|
106866
|
+
dataIssueMessage: dataIssue?.message ?? null,
|
|
106760
106867
|
thresholds: {
|
|
106761
106868
|
days: thresholdDays,
|
|
106762
106869
|
minBalance,
|
|
@@ -106769,14 +106876,24 @@ async function runBalanceScan(opts) {
|
|
|
106769
106876
|
totalReported: total ?? null,
|
|
106770
106877
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
106771
106878
|
};
|
|
106772
|
-
const scanPayload = { ok:
|
|
106773
|
-
|
|
106879
|
+
const scanPayload = { ok: !dataIssue, data: { items: evaluated }, meta };
|
|
106880
|
+
const wroteJson = await emitCliJsonOrSnapshot(opts, {
|
|
106774
106881
|
section: `balance-scan-${media}`,
|
|
106775
106882
|
commandLabel: "balance-scan",
|
|
106776
106883
|
commandHint: media,
|
|
106777
106884
|
payload: scanPayload,
|
|
106778
106885
|
idSuffix: media
|
|
106779
|
-
})
|
|
106886
|
+
});
|
|
106887
|
+
if (dataIssue) {
|
|
106888
|
+
console.error(`
|
|
106889
|
+
\u274C balance-scan \u6570\u636E\u5F02\u5E38\uFF08${dataIssue.code}\uFF09\uFF1A${dataIssue.message}
|
|
106890
|
+
`);
|
|
106891
|
+
if (wroteJson) {
|
|
106892
|
+
console.error(" \u5DF2\u5199\u5165 --json-out\uFF08ok=false\uFF0C\u89C1 meta.dataIssue\uFF09\uFF1B\u8BF7\u4FEE\u590D\u540E\u91CD\u8DD1\uFF0C\u52FF\u5F53\u4F5C\u300C\u65E0\u9884\u8B66\u547D\u4E2D\u300D\u3002\n");
|
|
106893
|
+
}
|
|
106894
|
+
process.exit(2);
|
|
106895
|
+
}
|
|
106896
|
+
if (wroteJson) {
|
|
106780
106897
|
return;
|
|
106781
106898
|
}
|
|
106782
106899
|
if (isSubset) {
|
|
@@ -106794,7 +106911,7 @@ ${media} \u8D26\u6237\u4F59\u989D\u626B\u63CF\u5B8C\u6210\uFF1A\u5171\u626B\u63C
|
|
|
106794
106911
|
);
|
|
106795
106912
|
}
|
|
106796
106913
|
if (evaluated.length === 0) {
|
|
106797
|
-
console.log(" \u2705 \u65E0\u547D\u4E2D\u8D26\u6237\u3002\n");
|
|
106914
|
+
console.log(" \u2705 \u65E0\u547D\u4E2D\u8D26\u6237\uFF08\u9608\u503C\u5185\u65E0\u9884\u8B66\uFF1B\u6570\u636E\u5DF2\u6B63\u5E38\u8FD4\u56DE\uFF09\u3002\n");
|
|
106798
106915
|
return;
|
|
106799
106916
|
}
|
|
106800
106917
|
const cols = [
|
|
@@ -116225,6 +116342,7 @@ function runPmaxCreateValidation(cfg) {
|
|
|
116225
116342
|
}
|
|
116226
116343
|
|
|
116227
116344
|
// src/commands/ad/pmax-image-validate.ts
|
|
116345
|
+
import { existsSync as existsSync3 } from "fs";
|
|
116228
116346
|
import { isAbsolute as isAbsolute2, resolve as resolve6, dirname as dirname7 } from "path";
|
|
116229
116347
|
|
|
116230
116348
|
// src/commands/ad/pmax-image-dims.ts
|
|
@@ -116384,6 +116502,12 @@ async function runPmaxImageValidation(configFile, cfg) {
|
|
|
116384
116502
|
fileSizeKB = Math.ceil(b64.trim().length * 0.75 / 1024);
|
|
116385
116503
|
} else if (pathRaw?.trim()) {
|
|
116386
116504
|
const abs = resolveImagePath(configFile, pathRaw.trim());
|
|
116505
|
+
if (!existsSync3(abs)) {
|
|
116506
|
+
errors.push(
|
|
116507
|
+
`${spec.label}\uFF1A\u56FE\u7247\u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${abs}\uFF08\u76F8\u5BF9\u8DEF\u5F84\u76F8\u5BF9 --config-file \u6240\u5728\u76EE\u5F55\u89E3\u6790\uFF1B\u8BF7\u6539\u7528\u7EDD\u5BF9\u8DEF\u5F84\u6216\u628A\u56FE\u653E\u5230\u914D\u7F6E\u65C1\uFF09`
|
|
116508
|
+
);
|
|
116509
|
+
continue;
|
|
116510
|
+
}
|
|
116387
116511
|
const result = readImageDimsFromPath(abs);
|
|
116388
116512
|
if (result) {
|
|
116389
116513
|
dims = result;
|
|
@@ -116407,7 +116531,7 @@ async function runPmaxImageValidation(configFile, cfg) {
|
|
|
116407
116531
|
// src/commands/ad/pmax-image-resolve.ts
|
|
116408
116532
|
init_auth();
|
|
116409
116533
|
import { basename as basename4, dirname as dirname8, isAbsolute as isAbsolute3, resolve as resolve7 } from "path";
|
|
116410
|
-
import { readFileSync as readFileSync10 } from "fs";
|
|
116534
|
+
import { existsSync as existsSync4, readFileSync as readFileSync10 } from "fs";
|
|
116411
116535
|
|
|
116412
116536
|
// src/commands/ad/pmax-urls.ts
|
|
116413
116537
|
function pmaxChannelTypesUrl(googleApiUrl) {
|
|
@@ -116570,7 +116694,19 @@ async function uploadPmaxImageFileBase64(config, googleApiUrl, accountId, absIma
|
|
|
116570
116694
|
async function uploadPmaxImageFile(config, googleApiUrl, accountId, absImagePath, name2, verbose) {
|
|
116571
116695
|
const fileName = basename4(absImagePath);
|
|
116572
116696
|
const assetName = (name2 ?? fileName).trim() || fileName;
|
|
116573
|
-
|
|
116697
|
+
if (!existsSync4(absImagePath)) {
|
|
116698
|
+
throw new Error(
|
|
116699
|
+
`\u56FE\u7247\u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${absImagePath}\uFF08\u76F8\u5BF9\u8DEF\u5F84\u76F8\u5BF9 --config-file \u6240\u5728\u76EE\u5F55\uFF1B\u8BF7\u6838\u5BF9 imagePaths \u6216\u6539\u7528\u7EDD\u5BF9\u8DEF\u5F84\uFF09`
|
|
116700
|
+
);
|
|
116701
|
+
}
|
|
116702
|
+
let fileBuffer;
|
|
116703
|
+
try {
|
|
116704
|
+
fileBuffer = readFileSync10(absImagePath);
|
|
116705
|
+
} catch (err) {
|
|
116706
|
+
throw new Error(
|
|
116707
|
+
`\u8BFB\u53D6\u56FE\u7247\u5931\u8D25\uFF08${absImagePath}\uFF09\uFF1A${err instanceof Error ? err.message : String(err)}`
|
|
116708
|
+
);
|
|
116709
|
+
}
|
|
116574
116710
|
if (fileBuffer.length <= MAX_BASE64_UPLOAD_BYTES) {
|
|
116575
116711
|
return uploadPmaxImageFileBase64(
|
|
116576
116712
|
config,
|
|
@@ -117345,7 +117481,7 @@ function buildPmaxCreateUrl(googleApiUrl, accountId) {
|
|
|
117345
117481
|
}
|
|
117346
117482
|
|
|
117347
117483
|
// src/commands/ad/pmax-video-upload.ts
|
|
117348
|
-
import { existsSync as
|
|
117484
|
+
import { existsSync as existsSync5, readFileSync as readFileSync13 } from "fs";
|
|
117349
117485
|
import { basename as basename5, dirname as dirname10, isAbsolute as isAbsolute5, resolve as resolve9 } from "path";
|
|
117350
117486
|
|
|
117351
117487
|
// src/commands/ad/pmax-shared.ts
|
|
@@ -117552,7 +117688,7 @@ function runPmaxVideoValidation(configFile, cfg) {
|
|
|
117552
117688
|
);
|
|
117553
117689
|
}
|
|
117554
117690
|
const abs = resolveVideoPath(configFile, videoPath);
|
|
117555
|
-
if (!
|
|
117691
|
+
if (!existsSync5(abs)) {
|
|
117556
117692
|
errors.push(`videoPath \u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${abs}`);
|
|
117557
117693
|
return { errors, warnings };
|
|
117558
117694
|
}
|
|
@@ -117674,7 +117810,7 @@ function validatePmaxVideoPathQuick(absPath) {
|
|
|
117674
117810
|
if (!VIDEO_UPLOAD_SUFFIX.test(absPath)) {
|
|
117675
117811
|
return `videoPath \u6269\u5C55\u540D\u4E0D\u53D7\u652F\u6301\uFF0C\u8BF7\u4F7F\u7528 .mp4 / .mov / .webm / .avi / .mpeg / .mpg`;
|
|
117676
117812
|
}
|
|
117677
|
-
if (!
|
|
117813
|
+
if (!existsSync5(absPath)) {
|
|
117678
117814
|
return `\u89C6\u9891\u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${absPath}`;
|
|
117679
117815
|
}
|
|
117680
117816
|
try {
|
|
@@ -117744,6 +117880,45 @@ async function linkPmaxVideoAfterCreate(opts) {
|
|
|
117744
117880
|
}
|
|
117745
117881
|
}
|
|
117746
117882
|
|
|
117883
|
+
// src/commands/ad/pmax-create-http-error.ts
|
|
117884
|
+
function classifyPmaxCreateHttpError(raw) {
|
|
117885
|
+
const msg = raw.trim() || "\u672A\u77E5\u9519\u8BEF";
|
|
117886
|
+
const lower = msg.toLowerCase();
|
|
117887
|
+
const hints = [];
|
|
117888
|
+
if (/^HTTP 400\b/i.test(msg) || lower.includes("bad request")) {
|
|
117889
|
+
if (/budget|日预算|budgetamount|micros/i.test(msg)) {
|
|
117890
|
+
hints.push("\u68C0\u67E5 campaign.budget / \u65E5\u9884\u7B97\u91D1\u989D\u4E0E\u5E01\u79CD\u662F\u5426\u5408\u7406");
|
|
117891
|
+
}
|
|
117892
|
+
if (/bidding|target.?cpa|target.?roas|maximize|出价/i.test(msg)) {
|
|
117893
|
+
hints.push("\u68C0\u67E5 BiddingStrategyTypeV2 \u4E0E\u914D\u5957\u91D1\u989D\u5B57\u6BB5\uFF08tCPA/tROAS\uFF09\u662F\u5426\u9F50\u5168\u4E14\u517C\u5BB9");
|
|
117894
|
+
}
|
|
117895
|
+
if (/image|asset|marketing|logo|图片/i.test(msg)) {
|
|
117896
|
+
hints.push("\u68C0\u67E5\u6A2A\u56FE/\u65B9\u56FE/Logo \u662F\u5426\u5DF2\u4E0A\u4F20\u6210\u529F\u3001\u89C4\u683C\u662F\u5426\u8FBE\u6807\uFF08\u5148\u8DD1 ad pmax-validate\uFF09");
|
|
117897
|
+
}
|
|
117898
|
+
if (/final.?url|landing|落地页|url/i.test(msg)) {
|
|
117899
|
+
hints.push("\u68C0\u67E5 finalUrls \u662F\u5426\u4E3A\u53EF\u8BBF\u95EE\u7684 http(s) \u843D\u5730\u9875");
|
|
117900
|
+
}
|
|
117901
|
+
if (/name|duplicate|已存在|同名/i.test(msg)) {
|
|
117902
|
+
hints.push("\u7CFB\u5217\u540D\u53EF\u80FD\u91CD\u590D\uFF1B\u6362\u4E00\u4E2A name \u518D\u8BD5");
|
|
117903
|
+
}
|
|
117904
|
+
if (/geo|location|language|地域|语言/i.test(msg)) {
|
|
117905
|
+
hints.push("\u68C0\u67E5 geo / language id \u662F\u5426\u6765\u81EA ad geo resolve / \u6587\u6863\u679A\u4E3E");
|
|
117906
|
+
}
|
|
117907
|
+
if (hints.length === 0) {
|
|
117908
|
+
hints.push(
|
|
117909
|
+
"\u5E38\u89C1\uFF1A\u9884\u7B97/\u51FA\u4EF7\u4E0D\u517C\u5BB9\u3001\u56FE\u7247\u8D44\u4EA7\u65E0\u6548\u3001finalUrl \u65E0\u6548\u3001\u7CFB\u5217\u91CD\u540D\uFF1B\u5148 ad pmax-validate\uFF0C\u4ECD\u5931\u8D25\u52A0 --verbose \u770B\u7F51\u5173\u539F\u6587"
|
|
117910
|
+
);
|
|
117911
|
+
}
|
|
117912
|
+
} else if (/^HTTP 403\b/i.test(msg)) {
|
|
117913
|
+
hints.push("\u8D26\u6237\u53EF\u80FD\u65E0\u6743\u521B\u5EFA\uFF1B\u5148 account check-access -a <id>\uFF0C\u786E\u8BA4\u5728\u5F53\u524D\u4E1D\u8DEF\u8D5E\u8D26\u53F7\u4E0B");
|
|
117914
|
+
} else if (/^HTTP 401\b/i.test(msg)) {
|
|
117915
|
+
hints.push("\u9274\u6743\u5931\u6548\uFF1B\u6267\u884C siluzan-tso login \u540E\u91CD\u8BD5");
|
|
117916
|
+
}
|
|
117917
|
+
if (hints.length === 0) return msg;
|
|
117918
|
+
return `${msg}
|
|
117919
|
+
\u63D0\u793A\uFF1A${hints.join("\uFF1B")}`;
|
|
117920
|
+
}
|
|
117921
|
+
|
|
117747
117922
|
// src/commands/ad/pmax-create.ts
|
|
117748
117923
|
function printVideoLinkRecoveryHint(accountId, assetGroupId, campaignId, youtubeTarget) {
|
|
117749
117924
|
const cid = campaignId != null ? ` --campaign-id ${campaignId}` : "";
|
|
@@ -117831,11 +118006,10 @@ async function runAdPmaxCreate(opts) {
|
|
|
117831
118006
|
opts.verbose
|
|
117832
118007
|
);
|
|
117833
118008
|
} catch (err) {
|
|
117834
|
-
|
|
117835
|
-
|
|
117836
|
-
\u274C \u521B\u5EFA PMax \u5E7F\u544A\u7CFB\u5217\u5931\u8D25\uFF1A${
|
|
117837
|
-
`
|
|
117838
|
-
);
|
|
118009
|
+
const raw = err instanceof Error ? err.message : String(err);
|
|
118010
|
+
console.error(`
|
|
118011
|
+
\u274C \u521B\u5EFA PMax \u5E7F\u544A\u7CFB\u5217\u5931\u8D25\uFF1A${classifyPmaxCreateHttpError(raw)}
|
|
118012
|
+
`);
|
|
117839
118013
|
process.exit(1);
|
|
117840
118014
|
}
|
|
117841
118015
|
const campaignId = data["campaignId"] ?? data["campaign_id"];
|
|
@@ -119081,7 +119255,7 @@ async function runAdCampaignValidate(opts) {
|
|
|
119081
119255
|
}
|
|
119082
119256
|
|
|
119083
119257
|
// src/commands/ad/pmax-image-convert.ts
|
|
119084
|
-
import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync5, readFileSync as readFileSync14, existsSync as
|
|
119258
|
+
import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync5, readFileSync as readFileSync14, existsSync as existsSync6 } from "fs";
|
|
119085
119259
|
import { resolve as resolve10, dirname as dirname11, basename as basename7, extname } from "path";
|
|
119086
119260
|
var SPECS = [
|
|
119087
119261
|
{ kind: "marketing", width: 1200, height: 628, fit: "cover", suffix: "_marketing" },
|
|
@@ -119142,7 +119316,7 @@ async function runAdPmaxImageConvert(opts) {
|
|
|
119142
119316
|
continue;
|
|
119143
119317
|
}
|
|
119144
119318
|
const absInput = resolve10(src);
|
|
119145
|
-
if (!
|
|
119319
|
+
if (!existsSync6(absInput)) {
|
|
119146
119320
|
console.error(`\u274C \u8F93\u5165\u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${absInput}`);
|
|
119147
119321
|
hasError = true;
|
|
119148
119322
|
continue;
|
|
@@ -122906,6 +123080,31 @@ async function runAccountBmBind(opts) {
|
|
|
122906
123080
|
// src/commands/account-manage-register.ts
|
|
122907
123081
|
function register23(program2) {
|
|
122908
123082
|
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");
|
|
123083
|
+
accountCmd.command("list", { hidden: true }).description("\uFF08\u517C\u5BB9\u522B\u540D\uFF09\u540C list-accounts").option(
|
|
123084
|
+
"-m, --media <type>",
|
|
123085
|
+
"\u5A92\u4F53\u7C7B\u578B\uFF1AGoogle | TikTok | Yandex | MetaAd | BingV2 | Kwai\uFF08\u7559\u7A7A\u5219\u67E5\u8BE2\u5168\u90E8\u5A92\u4F53\uFF09"
|
|
123086
|
+
).option("-k, --keyword <text>", "\u5173\u952E\u5B57\uFF08\u516C\u53F8/\u8D26\u6237\u540D/\u8D26\u6237ID \u6A21\u7CCA\u5339\u914D\uFF09").option(
|
|
123087
|
+
"-s, --status <status>",
|
|
123088
|
+
"\u8D26\u6237\u72B6\u6001\uFF1Anormal\uFF08\u6B63\u5E38\uFF09| invalid\uFF08\u5931\u6548\uFF09| all\uFF08\u5168\u90E8\uFF0C\u9ED8\u8BA4\uFF09",
|
|
123089
|
+
"all"
|
|
123090
|
+
).option("-p, --page <n>", "\u9875\u7801\uFF08\u9ED8\u8BA4 1\uFF09", parseInt).option("--page-size <n>", "\u6BCF\u9875\u6570\u91CF\uFF08\u9ED8\u8BA4 20\uFF09", parseInt).option("-t, --token <token>", "Token\uFF08\u53EF\u9009\uFF1B\u4F18\u5148\u4E8E ~/.siluzan/config.json\uFF09").option("--json-out <path>", "\u843D\u76D8\u76EE\u5F55\u6216 *.json\uFF1Bstdout \u4E00\u884C\u6458\u8981", void 0).option("--refresh-dp", "\u5F3A\u5236\u91CD\u62C9 Datapermission", false).option("--verbose", "\u663E\u793A\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(
|
|
123091
|
+
async (opts) => {
|
|
123092
|
+
process.stderr.write(
|
|
123093
|
+
"\u2139 `account list` \u5DF2\u8F6C\u53D1\u4E3A `list-accounts`\uFF08\u8BF7\u4F18\u5148\u4F7F\u7528 list-accounts\uFF09\u3002\n"
|
|
123094
|
+
);
|
|
123095
|
+
await runListAccounts({
|
|
123096
|
+
token: opts.token,
|
|
123097
|
+
media: opts.media,
|
|
123098
|
+
keyword: opts.keyword,
|
|
123099
|
+
status: opts.status,
|
|
123100
|
+
page: opts.page,
|
|
123101
|
+
pageSize: opts.pageSize,
|
|
123102
|
+
jsonOut: opts.jsonOut,
|
|
123103
|
+
refreshDp: opts.refreshDp,
|
|
123104
|
+
verbose: opts.verbose
|
|
123105
|
+
});
|
|
123106
|
+
}
|
|
123107
|
+
);
|
|
122909
123108
|
accountCmd.command("me").description(
|
|
122910
123109
|
"\u67E5\u8BE2\u5F53\u524D\u767B\u5F55\u4E1D\u8DEF\u8D5E\u8D26\u53F7\u4FE1\u606F\uFF08GET /query/account/me\uFF09\uFF1B--check-phone \u7528\u4E8E\u6821\u9A8C\u7528\u6237\u6307\u5B9A\u7684\u4F01\u4E1A\u7BA1\u5BB6\u624B\u673A\u53F7"
|
|
122911
123110
|
).option("-t, --token <token>", "Auth Token").option(
|
|
@@ -131954,6 +132153,34 @@ function registerTikTokAnalysisCommands(program2) {
|
|
|
131954
132153
|
// src/index.ts
|
|
131955
132154
|
init_version();
|
|
131956
132155
|
init_cli_json_snapshot();
|
|
132156
|
+
|
|
132157
|
+
// src/utils/agent-compat-argv.ts
|
|
132158
|
+
function agentCompatFatalMessage(argv) {
|
|
132159
|
+
const args = argv.slice(2);
|
|
132160
|
+
if (args.includes("--period") || args.some((a) => a.startsWith("--period="))) {
|
|
132161
|
+
return "\n\u274C \u6CA1\u6709 --period \u9009\u9879\u3002\u8BF7\u7528 --start/--end\uFF08\u6216\u517C\u5BB9\u522B\u540D --start-date/--end-date\uFF09\u6307\u5B9A YYYY-MM-DD \u533A\u95F4\u3002\n";
|
|
132162
|
+
}
|
|
132163
|
+
const cmd = args[0];
|
|
132164
|
+
if (cmd === "google-ads") {
|
|
132165
|
+
return "\n\u274C \u6CA1\u6709 `google-ads` \u547D\u540D\u7A7A\u95F4\u3002\u8BF7\u6539\u7528\uFF1A\n - \u8D26\u6237\u5206\u6790\u62C9\u6570\uFF1Asiluzan-tso google-analysis \u2026\n - \u5E7F\u544A\u7CFB\u5217/\u7EC4/\u5173\u952E\u8BCD CRUD\uFF1Asiluzan-tso ad \u2026\n - \u5E7F\u544A\u8BCA\u65AD\u62A5\u544A\uFF1Asiluzan-tso google-ads-diagnosis \u2026\n";
|
|
132166
|
+
}
|
|
132167
|
+
if (cmd === "list" && (args.length === 1 || args[1]?.startsWith("-"))) {
|
|
132168
|
+
return "\n\u274C \u6CA1\u6709\u9876\u5C42 `list` \u547D\u4EE4\u3002\u67E5\u8BE2\u5E7F\u544A\u8D26\u6237\u5217\u8868\u8BF7\u7528\uFF1A\n siluzan-tso list-accounts [-m Google] [-k <id\u6216\u5173\u952E\u5B57>] --json-out <dir>\n";
|
|
132169
|
+
}
|
|
132170
|
+
if (cmd === "accounts") {
|
|
132171
|
+
return "\n\u274C \u6CA1\u6709 `accounts` \u547D\u540D\u7A7A\u95F4\u3002\u67E5\u8BE2\u8D26\u6237\u5217\u8868\u8BF7\u7528\uFF1A\n siluzan-tso list-accounts \u2026\n \u591A\u8D26\u6237\u753B\u50CF\uFF1Asiluzan-tso accounts-digest \u2026\n";
|
|
132172
|
+
}
|
|
132173
|
+
return null;
|
|
132174
|
+
}
|
|
132175
|
+
function interceptAgentCompatArgv(argv) {
|
|
132176
|
+
const msg = agentCompatFatalMessage(argv);
|
|
132177
|
+
if (msg) {
|
|
132178
|
+
console.error(msg);
|
|
132179
|
+
process.exit(1);
|
|
132180
|
+
}
|
|
132181
|
+
}
|
|
132182
|
+
|
|
132183
|
+
// src/index.ts
|
|
131957
132184
|
installProcessHandlers();
|
|
131958
132185
|
function getVersion() {
|
|
131959
132186
|
try {
|
|
@@ -132036,4 +132263,5 @@ function argvHasDeprecatedJsonFlag(argv) {
|
|
|
132036
132263
|
if (argvHasDeprecatedJsonFlag(process.argv)) {
|
|
132037
132264
|
rejectDeprecatedJsonFlag(true, process.argv[2] ?? "siluzan-tso");
|
|
132038
132265
|
}
|
|
132266
|
+
interceptAgentCompatArgv(process.argv);
|
|
132039
132267
|
program.parseAsync();
|
package/dist/skill/AGENTS.md
CHANGED
|
@@ -1,28 +1,35 @@
|
|
|
1
|
-
# siluzan-tso —
|
|
1
|
+
# siluzan-tso — 文档目录
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> 入口:`SKILL.md` → 按路由表 Read 列出的文件。改文档结构时对齐 `references/core/skill-authoring.md`。
|
|
4
|
+
|
|
5
|
+
## 怎么找文档
|
|
6
|
+
|
|
7
|
+
| 要做什么 | 读哪里 |
|
|
8
|
+
| -------- | ------ |
|
|
9
|
+
| 锁定工作流 | `SKILL.md` 路由表 |
|
|
10
|
+
| 报告类话术模糊 | `references/core/intent-routing.md` |
|
|
11
|
+
| 步骤与产物 | `playbooks.md`(P*)或 `workflows.md`(W*) |
|
|
12
|
+
| 命令参数 / 字段 | 路由表「必读文档」 |
|
|
13
|
+
| 纪律与对用户怎么说 | `references/core/agent-conventions.md` |
|
|
14
|
+
| 报告结构纲要 | `report-templates/*.md`(勿读 `*.html`) |
|
|
4
15
|
|
|
5
16
|
## 启动顺序
|
|
6
17
|
|
|
7
18
|
1. Read `SKILL.md` 路由表,锁定唯一工作流
|
|
8
|
-
2. 报告类模糊 → Read `
|
|
9
|
-
3. Read
|
|
10
|
-
4. 写操作 / 报告交付 /
|
|
11
|
-
5. P5/P6/P7 或长 CLI:可选 `
|
|
12
|
-
|
|
13
|
-
## 文档域
|
|
14
|
-
|
|
15
|
-
| 域 | 路径 | 何时 Read |
|
|
16
|
-
| -- | ---- | --------- |
|
|
17
|
-
| Core | `references/core/` | 纪律、intent-routing、playbooks、workflows |
|
|
18
|
-
| Accounts | `references/accounts/` | `accounts-list` / `accounts-balance-stats` / `accounts-permissions`(`accounts.md` 仅索引) |
|
|
19
|
-
| Google Ads | `references/google-ads/` | `google-ads-read` / `write` / `batch`(索引:`google-ads.md`);`rules/` 先 README 再单文件 |
|
|
20
|
-
| Analytics | `references/analytics/` | 拉数、批处理、拓词、RAG |
|
|
21
|
-
| Operations | `references/operations/` | 预警、线索;自动化仅用户问起时 |
|
|
22
|
-
| Templates | `report-templates/*.md`、`assets/` | 报告纲要 / JSON 契约;**禁止** Read `*.html` |
|
|
19
|
+
2. 报告类模糊 → Read `intent-routing.md`
|
|
20
|
+
3. Read「必读文档」+ 对应 playbook/workflow 卡片
|
|
21
|
+
4. 写操作 / 报告交付 / 批量 / 对用户写结论 → Read `agent-conventions.md` 相关节
|
|
22
|
+
5. P5/P6/P7 或长 CLI:可选 `subagent-orchestration.md`
|
|
23
23
|
|
|
24
|
-
##
|
|
24
|
+
## 按域
|
|
25
|
+
|
|
26
|
+
| 域 | 路径 | 说明 |
|
|
27
|
+
| -- | ---- | ---- |
|
|
28
|
+
| Core | `references/core/` | conventions、intent-routing、playbooks、workflows |
|
|
29
|
+
| Accounts | `references/accounts/` | 直接读 `accounts-list` / `accounts-balance-stats` / `accounts-permissions` |
|
|
30
|
+
| Google Ads | `references/google-ads/` | `google-ads-read` / `write` / `batch`;`rules/` 先 README 再单文件 |
|
|
31
|
+
| Analytics | `references/analytics/` | 拉数、批处理、拓词 |
|
|
32
|
+
| Operations | `references/operations/` | 预警、线索;自动化仅用户问起时 |
|
|
33
|
+
| Templates | `report-templates/*.md`、`assets/` | 报告纲要 / JSON 契约 |
|
|
25
34
|
|
|
26
|
-
|
|
27
|
-
- 纪律真相源:`references/core/agent-conventions.md`
|
|
28
|
-
- 规范:`references/core/skill-authoring.md`
|
|
35
|
+
源码目录:`tso-cli/assets/siluzan-ads/`。
|