siluzan-tso-cli 1.1.22-beta.2 → 1.1.22-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/index.js +139 -30
- package/dist/skill/AGENTS.md +45 -0
- package/dist/skill/SKILL.md +60 -347
- package/dist/skill/_meta.json +2 -2
- package/dist/skill/assets/campaign-create-template.md +4 -4
- package/dist/skill/assets/pmax-create-template.md +4 -3
- package/dist/skill/docs/skill-guide.md +44 -0
- package/dist/skill/references/README.md +73 -0
- package/dist/skill/references/{accounts.md → accounts/accounts.md} +7 -7
- package/dist/skill/references/{currency.md → accounts/currency.md} +7 -7
- package/dist/skill/references/accounts/open-account-by-media.md +151 -0
- package/dist/skill/references/{open-account-google-ui.md → accounts/open-account-google-ui.md} +2 -2
- package/dist/skill/references/{account-analytics.md → analytics/account-analytics.md} +2 -2
- package/dist/skill/references/{google-analysis-batch.md → analytics/google-analysis-batch.md} +2 -2
- package/dist/skill/references/{keyword-planner-workflows.md → analytics/keyword-planner-workflows.md} +9 -9
- package/dist/skill/references/{rag.md → analytics/rag.md} +5 -5
- package/dist/skill/references/{reporting.md → analytics/reporting.md} +4 -4
- package/dist/skill/references/core/agent-conventions.md +180 -0
- package/dist/skill/references/core/playbooks.md +141 -0
- package/dist/skill/references/core/skill-authoring.md +192 -0
- package/dist/skill/references/{tips.md → core/tips.md} +5 -5
- package/dist/skill/references/{workflows.md → core/workflows.md} +23 -25
- package/dist/skill/references/{google-ads-campaign-plan.md → google-ads/google-ads-campaign-plan.md} +22 -22
- package/dist/skill/references/{google-ads.md → google-ads/google-ads.md} +11 -11
- package/dist/skill/references/google-ads/rules/README.md +21 -0
- package/dist/skill/references/{google-ads-rules → google-ads/rules}/google-ads-keyword-taxonomy.md +2 -2
- package/dist/skill/references/{google-ads-rules → google-ads/rules}/google-ads-launch-plan-template.md +8 -8
- package/dist/skill/references/{google-ads-rules → google-ads/rules}/google-ads-pmax-guide.md +1 -1
- package/dist/skill/references/{tso-home.md → misc/tso-home.md} +4 -4
- package/dist/skill/references/{hosted-automation-monitoring-json.md → operations/hosted-automation-monitoring-json.md} +8 -8
- package/dist/skill/references/{hosted-automation-optimize-ab-winner.md → operations/hosted-automation-optimize-ab-winner.md} +2 -2
- package/dist/skill/references/{hosted-automation-optimize-index.md → operations/hosted-automation-optimize-index.md} +6 -6
- package/dist/skill/references/{hosted-automation-optimize-scale.md → operations/hosted-automation-optimize-scale.md} +2 -2
- package/dist/skill/references/{hosted-automation-optimize-weak-downbid.md → operations/hosted-automation-optimize-weak-downbid.md} +5 -5
- package/dist/skill/references/operations/hosted-automation-scenarios.md +23 -0
- package/dist/skill/references/{hosted-automation-self-control.md → operations/hosted-automation-self-control.md} +14 -14
- package/{assets/siluzan-ads/references → dist/skill/references/operations}/hosted-automation-user-catalog.md +12 -12
- package/dist/skill/report-templates/README.md +2 -1
- package/dist/skill/report-templates/REPORT-WORKFLOW.md +2 -2
- package/dist/skill/report-templates/google-ads-diagnosis.md +1 -1
- package/dist/skill/report-templates/google-inquiry-analysis.md +6 -6
- package/dist/skill/report-templates/google-period-report.md +1 -1
- package/dist/skill/report-templates/okki-weekly-google-client.md +4 -4
- 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 +2 -2
- package/eval/cases/accounts-mcc-bind-inquiry.scenario.json +3 -3
- package/eval/cases/accounts-single-balance-not-bulk.scenario.json +2 -2
- package/eval/cases/clue-meta-leads-json.scenario.json +2 -2
- package/eval/cases/clue-tiktok-leads-json.scenario.json +2 -2
- package/eval/cases/destructive-account-delink-needs-confirm.scenario.json +1 -1
- package/eval/cases/destructive-forewarning-delete-needs-confirm.scenario.json +1 -1
- package/eval/cases/destructive-invoice-apply-needs-confirm.scenario.json +1 -1
- package/eval/cases/finance-invoice-info-list.scenario.json +2 -2
- package/eval/cases/forewarning-list-google.scenario.json +2 -2
- package/eval/cases/google-ads-no-structural-without-confirm.scenario.json +3 -3
- package/eval/cases/google-analysis-keywords-route.scenario.json +2 -2
- package/eval/cases/hosted-sop-cpa-spike-downbid.scenario.json +5 -5
- package/eval/cases/hosted-sop-daily-budget-circuit-breaker.scenario.json +3 -3
- package/eval/cases/hosted-sop-empty-spend-pause-p1.scenario.json +5 -5
- package/eval/cases/meta-single-balance-not-bulk.scenario.json +2 -2
- package/eval/cases/open-account-bing-noninteractive.scenario.json +3 -3
- package/eval/cases/open-account-google-noninteractive.scenario.json +2 -2
- package/eval/cases/open-account-tiktok-license-file.scenario.json +2 -2
- package/eval/cases/optimize-list-by-account.scenario.json +2 -2
- package/eval/cases/rag-before-keyword-expand.scenario.json +3 -3
- package/eval/cases/rag-list-then-query.scenario.json +2 -2
- package/eval/cases/report-list-google.scenario.json +2 -2
- package/eval/cases/report-push-list-google.scenario.json +3 -3
- package/eval/cases/reporting-vs-account-analytics-routing.scenario.json +4 -4
- package/eval/cases/setup-login-or-env.scenario.json +2 -2
- package/eval/cases/setup-siluzan-data-permission-env.scenario.json +2 -2
- package/eval/cases/skill-optimize-vs-google-ads-distinction.scenario.json +4 -4
- package/eval/cases/tiktok-bc-bind-inquiry.scenario.json +2 -2
- package/eval/cases/tips-json-filtering.scenario.json +4 -4
- package/eval/cases/tips-large-json-pagination.scenario.json +3 -3
- package/eval/cases/uj-ad-bluetooth-keywords-exclude-cheap-free.scenario.json +1 -1
- package/eval/cases/uj-ad-campaign-validate-before-create-stub.scenario.json +2 -2
- package/eval/cases/uj-ad-keywords-camping-tent-outdoor-plan.scenario.json +1 -1
- package/eval/cases/uj-ad-outdoor-campgear-search-plan.scenario.json +3 -3
- package/eval/cases/uj-analytics-30d-pdf-campaign-device-geo.scenario.json +2 -2
- package/eval/cases/uj-analytics-compare-google-tiktok-last-month-roi.scenario.json +1 -1
- package/eval/cases/uj-analytics-google-weekly-trends-campaigns-keywords.scenario.json +2 -2
- package/eval/cases/uj-analytics-report-push-weekly-email.scenario.json +3 -3
- package/eval/cases/uj-finance-invoice-records-this-month.scenario.json +2 -2
- package/eval/cases/uj-life-newbie-siluzan-google-end-to-end.scenario.json +2 -2
- package/eval/cases/uj-ops-google-accounts-list-normal.scenario.json +2 -2
- package/eval/cases/uj-ops-google-yesterday-spend-conversions.scenario.json +2 -2
- package/eval/cases/uj-ops-open-google-b2c-usd-shenzhen.scenario.json +3 -3
- package/eval/cases/uj-ops-pause-worst-adgroup-confirm.scenario.json +2 -2
- package/eval/cases/uj-ops-tiktok-leads-last-week.scenario.json +2 -2
- package/eval/cases/uj-patrol-cpc-spike-adgroups-over-15.scenario.json +3 -3
- package/eval/cases/uj-patrol-forewarning-create-daily-cap-3000.scenario.json +3 -3
- package/eval/cases/uj-patrol-forewarning-trigger-records.scenario.json +2 -2
- package/eval/cases/uj-patrol-google-balances-low.scenario.json +2 -2
- package/eval/cases/uj-roi-full-google-account-diagnosis.scenario.json +1 -1
- package/eval/cases/uj-roi-keywords-high-cpa-low-cvr-triage.scenario.json +1 -1
- package/eval/cases/uj-roi-optimize-records-then-execute-cautiously.scenario.json +2 -2
- package/eval/cases/uj-roi-search-terms-add-negative-keywords.scenario.json +2 -2
- package/package.json +2 -2
- package/dist/skill/references/hosted-automation-scenarios.md +0 -23
- package/dist/skill/references/hosted-automation-user-catalog.md +0 -38
- /package/dist/skill/references/{finance.md → accounts/finance.md} +0 -0
- /package/dist/skill/references/{write-audit-restore.md → accounts/write-audit-restore.md} +0 -0
- /package/dist/skill/references/{geo-continents.json → analytics/geo-continents.json} +0 -0
- /package/dist/skill/references/{setup.md → core/setup.md} +0 -0
- /package/dist/skill/references/{pmax-api.md → google-ads/pmax-api.md} +0 -0
- /package/dist/skill/references/{google-ads-rules → google-ads/rules}/google-ads-account-audit.md +0 -0
- /package/dist/skill/references/{google-ads-rules → google-ads/rules}/google-ads-audience-strategy.md +0 -0
- /package/dist/skill/references/{google-ads-rules → google-ads/rules}/google-ads-campaign-optimization.md +0 -0
- /package/dist/skill/references/{google-ads-rules → google-ads/rules}/google-ads-compliance.md +0 -0
- /package/dist/skill/references/{google-ads-rules → google-ads/rules}/google-ads-conversion-architecture.md +0 -0
- /package/dist/skill/references/{google-ads-rules → google-ads/rules}/google-ads-creative-optimization.md +0 -0
- /package/dist/skill/references/{google-ads-rules → google-ads/rules}/google-ads-keyword-optimization.md +0 -0
- /package/dist/skill/references/{google-ads-rules → google-ads/rules}/google-ads-keyword-strategy.md +0 -0
- /package/dist/skill/references/{google-ads-rules → google-ads/rules}/google-ads-landing-page-discovery-via-webfetch.md +0 -0
- /package/dist/skill/references/{google-ads-rules → google-ads/rules}/sensitive-industries.md +0 -0
- /package/dist/skill/references/{clue.md → operations/clue.md} +0 -0
- /package/dist/skill/references/{forewarning.md → operations/forewarning.md} +0 -0
- /package/dist/skill/references/{optimize.md → operations/optimize.md} +0 -0
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.22-beta.
|
|
54
|
+
> **注意**:当前为测试版(1.1.22-beta.3),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-tso-cli`。
|
|
55
55
|
|
|
56
56
|
| 助手 | 建议 `--ai` |
|
|
57
57
|
| ----------------------- | ------------------------------------ |
|
|
@@ -69,7 +69,7 @@ siluzan-tso init --force # 强制覆盖已存在文件
|
|
|
69
69
|
|
|
70
70
|
**若用户已安装 `siluzan-cso` 并完成登录,无需重复操作,直接跳到第 4 步。**
|
|
71
71
|
|
|
72
|
-
**推荐顺序**:① **手机号 + 验证码**(首选)完整参数与排错见 `references/setup.md`(随 Skill 安装到本地)。
|
|
72
|
+
**推荐顺序**:① **手机号 + 验证码**(首选)完整参数与排错见 `references/core/setup.md`(随 Skill 安装到本地)。
|
|
73
73
|
|
|
74
74
|
### 方式 A:手机号 + 验证码(**推荐**)
|
|
75
75
|
|
package/dist/index.js
CHANGED
|
@@ -4019,7 +4019,7 @@ var init_cli_json = __esm({
|
|
|
4019
4019
|
SCHEMA_VERSION = 1;
|
|
4020
4020
|
OUTLINE_AGENT_HINT = "\u5904\u7406\u987A\u5E8F\uFF1A\u5148\u8BFB outlineFile\uFF08schema \u63CF\u8FF0\uFF0C\u975E\u6570\u636E\uFF09\u4E86\u89E3\u5B57\u6BB5\u7C7B\u578B\uFF0C\u518D\u7528\u811A\u672C\u8BFB writtenFiles[0]\uFF08\u771F\u5B9E JSON \u6570\u636E\uFF09\u505A\u7B5B\u9009/\u805A\u5408\uFF1B\u4E0D\u8981\u628A outline \u5F53\u6210\u6570\u636E\uFF0C\u4E5F\u4E0D\u8981\u628A JSON \u5F53\u6210 schema\u3002";
|
|
4021
4021
|
DEFAULT_FIELD_GUIDE = {
|
|
4022
|
-
markdownRefs: ["references/currency.md", "references/tips.md", "references/accounts.md"]
|
|
4022
|
+
markdownRefs: ["references/accounts/currency.md", "references/core/tips.md", "references/accounts/accounts.md"]
|
|
4023
4023
|
};
|
|
4024
4024
|
TS_LIKE_ARRAY_SAMPLE_MAX = 8;
|
|
4025
4025
|
}
|
|
@@ -4731,7 +4731,7 @@ var init_google_analysis = __esm({
|
|
|
4731
4731
|
CLI_PACKAGE2 = "siluzan-tso-cli";
|
|
4732
4732
|
SCHEMA_VERSION2 = 2;
|
|
4733
4733
|
DEFAULT_FIELD_GUIDE2 = {
|
|
4734
|
-
markdownRefs: ["references/currency.md", "references/account-analytics.md"],
|
|
4734
|
+
markdownRefs: ["references/accounts/currency.md", "references/analytics/account-analytics.md"],
|
|
4735
4735
|
tsTypesModule: "tso-cli/src/types/google-analysis-api.ts"
|
|
4736
4736
|
};
|
|
4737
4737
|
GOOGLE_ANALYSIS_CAMPAIGNS_OUTLINE_BUDGET_HINTS = [
|
|
@@ -105686,7 +105686,7 @@ function reportManifestFile(accountId) {
|
|
|
105686
105686
|
return `${applyIdSuffix("report-manifest", accountId)}.json`;
|
|
105687
105687
|
}
|
|
105688
105688
|
var DEFAULT_FIELD_GUIDE3 = {
|
|
105689
|
-
markdownRefs: ["references/account-analytics.md"]
|
|
105689
|
+
markdownRefs: ["references/analytics/account-analytics.md"]
|
|
105690
105690
|
};
|
|
105691
105691
|
function sectionToFilename(section, accountId) {
|
|
105692
105692
|
if (!/^[a-z0-9_-]+$/.test(section)) {
|
|
@@ -108655,7 +108655,7 @@ function register17(program2) {
|
|
|
108655
108655
|
const optimizeCmd = program2.command("optimize").description("AI \u5E7F\u544A\u4F18\u5316\uFF08Google\uFF09");
|
|
108656
108656
|
optimizeCmd.command("list").description("\u67E5\u8BE2\u8D26\u6237\u7EA7\u4F18\u5316\u4E3B\u5217\u8868\uFF08\u5BF9\u5E94\u9875\u9762 /advertising/intelligentOptimization\uFF09").option("-a, --account <id>", "\u8D26\u6237 mediaCustomerId\uFF08\u7559\u7A7A\u67E5\u5168\u90E8\uFF09").option(
|
|
108657
108657
|
"--match-media-customer-id <id>",
|
|
108658
|
-
"\u5728\u5168\u91CF\u5217\u8868\u4E2D\u7B5B\u9009\u8BE5 Google \u5BA2\u6237 ID\uFF08\u81EA\u52A8\u7FFB\u9875\uFF1B\u5DF2\u8131\u7BA1\u52FF\u7528 -a\uFF0C\u89C1 optimize.md\uFF09"
|
|
108658
|
+
"\u5728\u5168\u91CF\u5217\u8868\u4E2D\u7B5B\u9009\u8BE5 Google \u5BA2\u6237 ID\uFF08\u81EA\u52A8\u7FFB\u9875\uFF1B\u5DF2\u8131\u7BA1\u52FF\u7528 -a\uFF0C\u89C1 operations/optimize.md\uFF09"
|
|
108659
108659
|
).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", parseInt).option("-t, --token <token>", "Auth Token").option("--json", "JSON \u683C\u5F0F\u8F93\u51FA", false).option(
|
|
108660
108660
|
"--json-out <path>",
|
|
108661
108661
|
"\u843D\u76D8\uFF08\u76EE\u5F55\u6216 *.json \u6587\u4EF6\u8DEF\u5F84\uFF09\u5E76\u66F4\u65B0 cli-manifest[-<\u67E5\u8BE2id>].json\uFF08\u4E0E --json \u4E92\u65A5\uFF09\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",
|
|
@@ -109499,12 +109499,16 @@ init_cli_table();
|
|
|
109499
109499
|
function pushLengthViolation(violations, item) {
|
|
109500
109500
|
violations.push({ ...item, excess: item.actual - item.limit });
|
|
109501
109501
|
}
|
|
109502
|
-
function
|
|
109502
|
+
function lengthViolationAgentHint(revalidateCommand = "campaign-validate") {
|
|
109503
|
+
return `\u52FF\u81EA\u52A8\u622A\u65AD JSON\u3002\u8BFB\u53D6\u843D\u76D8 JSON \u7684 lengthViolations\uFF0C\u5C06\u5168\u90E8\u6761\u76EE\u4E0E\u4FEE\u6539\u65B9\u6848\u5217\u7ED9\u7528\u6237\uFF0C\u786E\u8BA4\u540E\u5199\u5165\u914D\u7F6E\u5E76\u91CD\u65B0 ${revalidateCommand}\u3002`;
|
|
109504
|
+
}
|
|
109505
|
+
function formatLengthViolationsReport(violations, opts) {
|
|
109503
109506
|
if (violations.length === 0) return "";
|
|
109507
|
+
const cmd = opts?.revalidateCommand ?? "campaign-validate";
|
|
109504
109508
|
const lines = [
|
|
109505
109509
|
"",
|
|
109506
109510
|
`\u{1F4CF} \u8D85\u957F\u5185\u5BB9\u6E05\u5355\uFF08\u5171 ${violations.length} \u9879\uFF09`,
|
|
109507
|
-
|
|
109511
|
+
` \u8BF7\u52FF\u5728 JSON \u4E2D\u81EA\u52A8\u622A\u65AD\uFF1B\u8BF7\u5C06\u5168\u90E8\u6761\u76EE\u4E0E\u4FEE\u6539\u65B9\u6848\u5217\u7ED9\u7528\u6237\uFF0C\u786E\u8BA4\u540E\u518D\u6539 JSON \u5E76\u91CD\u65B0 ${cmd}\u3002`,
|
|
109508
109512
|
""
|
|
109509
109513
|
];
|
|
109510
109514
|
for (let i = 0; i < violations.length; i++) {
|
|
@@ -113751,9 +113755,6 @@ var BUSINESS_NAME_MAX = 25;
|
|
|
113751
113755
|
function pushErr3(errors, msg) {
|
|
113752
113756
|
errors.push(msg);
|
|
113753
113757
|
}
|
|
113754
|
-
function pushWarn3(warnings, msg) {
|
|
113755
|
-
warnings.push(msg);
|
|
113756
|
-
}
|
|
113757
113758
|
function nonEmptyStrings(list) {
|
|
113758
113759
|
return (list ?? []).map((s) => s?.trim()).filter((s) => Boolean(s));
|
|
113759
113760
|
}
|
|
@@ -113784,20 +113785,28 @@ function normalizeBidding(raw) {
|
|
|
113784
113785
|
};
|
|
113785
113786
|
return byNum[n] ?? null;
|
|
113786
113787
|
}
|
|
113787
|
-
function
|
|
113788
|
+
function validateTextLengths(errors, lengthViolations, texts, arrayField, kind, limit, label) {
|
|
113788
113789
|
texts.forEach((text, i) => {
|
|
113789
113790
|
const len = calcGoogleCharLength(text);
|
|
113790
113791
|
if (len > limit) {
|
|
113791
|
-
|
|
113792
|
-
|
|
113793
|
-
|
|
113794
|
-
|
|
113792
|
+
const field = `${arrayField}[${i}]`;
|
|
113793
|
+
pushLengthViolation(lengthViolations, {
|
|
113794
|
+
path: field,
|
|
113795
|
+
field,
|
|
113796
|
+
kind,
|
|
113797
|
+
limit,
|
|
113798
|
+
actual: len,
|
|
113799
|
+
countMode: "google",
|
|
113800
|
+
text
|
|
113801
|
+
});
|
|
113802
|
+
pushErr3(errors, `${label}[${i}] \u8D85\u8FC7 ${limit} \u5B57\u7B26\uFF08\u5F53\u524D ${len}\uFF0CCJK \u8BA1 2\uFF09\uFF1A"${text}"`);
|
|
113795
113803
|
}
|
|
113796
113804
|
});
|
|
113797
113805
|
}
|
|
113798
113806
|
function runPmaxCreateValidation(cfg) {
|
|
113799
113807
|
const errors = [];
|
|
113800
113808
|
const warnings = [];
|
|
113809
|
+
const lengthViolations = [];
|
|
113801
113810
|
const account = cfg.account?.toString().trim();
|
|
113802
113811
|
if (!account) {
|
|
113803
113812
|
pushErr3(errors, "account\uFF08\u5A92\u4F53\u5BA2\u6237 ID\uFF09\u5FC5\u586B");
|
|
@@ -113893,19 +113902,53 @@ function runPmaxCreateValidation(cfg) {
|
|
|
113893
113902
|
}
|
|
113894
113903
|
}
|
|
113895
113904
|
}
|
|
113896
|
-
|
|
113897
|
-
|
|
113898
|
-
|
|
113905
|
+
validateTextLengths(
|
|
113906
|
+
errors,
|
|
113907
|
+
lengthViolations,
|
|
113908
|
+
headlines,
|
|
113909
|
+
"headlines",
|
|
113910
|
+
"pmax_headline",
|
|
113911
|
+
HEADLINE_MAX,
|
|
113912
|
+
"headlines"
|
|
113913
|
+
);
|
|
113914
|
+
validateTextLengths(
|
|
113915
|
+
errors,
|
|
113916
|
+
lengthViolations,
|
|
113917
|
+
longHeadlines,
|
|
113918
|
+
"longHeadlines",
|
|
113919
|
+
"pmax_long_headline",
|
|
113920
|
+
LONG_HEADLINE_MAX,
|
|
113921
|
+
"longHeadlines"
|
|
113922
|
+
);
|
|
113923
|
+
validateTextLengths(
|
|
113924
|
+
errors,
|
|
113925
|
+
lengthViolations,
|
|
113926
|
+
descriptions,
|
|
113927
|
+
"descriptions",
|
|
113928
|
+
"pmax_description",
|
|
113929
|
+
DESCRIPTION_MAX,
|
|
113930
|
+
"descriptions"
|
|
113931
|
+
);
|
|
113899
113932
|
if (cfg.businessName?.trim()) {
|
|
113900
|
-
const
|
|
113933
|
+
const bnText = cfg.businessName.trim();
|
|
113934
|
+
const bn = calcGoogleCharLength(bnText);
|
|
113901
113935
|
if (bn > BUSINESS_NAME_MAX) {
|
|
113902
|
-
|
|
113903
|
-
|
|
113904
|
-
|
|
113936
|
+
pushLengthViolation(lengthViolations, {
|
|
113937
|
+
path: "businessName",
|
|
113938
|
+
field: "businessName",
|
|
113939
|
+
kind: "pmax_business_name",
|
|
113940
|
+
limit: BUSINESS_NAME_MAX,
|
|
113941
|
+
actual: bn,
|
|
113942
|
+
countMode: "google",
|
|
113943
|
+
text: bnText
|
|
113944
|
+
});
|
|
113945
|
+
pushErr3(
|
|
113946
|
+
errors,
|
|
113947
|
+
`businessName \u8D85\u8FC7 ${BUSINESS_NAME_MAX} \u5B57\u7B26\uFF08\u5F53\u524D ${bn}\uFF0CCJK \u8BA1 2\uFF09\uFF1A"${bnText}"`
|
|
113905
113948
|
);
|
|
113906
113949
|
}
|
|
113907
113950
|
}
|
|
113908
|
-
return { errors, warnings };
|
|
113951
|
+
return { errors, warnings, lengthViolations };
|
|
113909
113952
|
}
|
|
113910
113953
|
|
|
113911
113954
|
// src/commands/ad/pmax-image-validate.ts
|
|
@@ -114082,6 +114125,7 @@ async function runPmaxImageValidation(configFile, cfg) {
|
|
|
114082
114125
|
}
|
|
114083
114126
|
|
|
114084
114127
|
// src/commands/ad/pmax-image-resolve.ts
|
|
114128
|
+
init_auth();
|
|
114085
114129
|
import { basename as basename4, dirname as dirname8, isAbsolute as isAbsolute3, resolve as resolve7 } from "path";
|
|
114086
114130
|
import { readFileSync as readFileSync5 } from "fs";
|
|
114087
114131
|
|
|
@@ -114167,6 +114211,7 @@ var SLOT_META = {
|
|
|
114167
114211
|
label: "Logo (LOGO)"
|
|
114168
114212
|
}
|
|
114169
114213
|
};
|
|
114214
|
+
var MAX_BASE64_UPLOAD_BYTES = 2e5;
|
|
114170
114215
|
function guessContentType(fileName) {
|
|
114171
114216
|
const lower = fileName.toLowerCase();
|
|
114172
114217
|
if (lower.endsWith(".png")) return "image/png";
|
|
@@ -114183,10 +114228,8 @@ function normalizePmaxAssetId(value) {
|
|
|
114183
114228
|
const m = s.match(/\/assets\/(\d+)\s*$/);
|
|
114184
114229
|
return m ? m[1] : s;
|
|
114185
114230
|
}
|
|
114186
|
-
async function
|
|
114231
|
+
async function uploadPmaxImageFileMultipart(config, googleApiUrl, accountId, absImagePath, assetName, fileBuffer, verbose) {
|
|
114187
114232
|
const fileName = basename4(absImagePath);
|
|
114188
|
-
const assetName = (name2 ?? fileName).trim() || fileName;
|
|
114189
|
-
const fileBuffer = readFileSync5(absImagePath);
|
|
114190
114233
|
const mimeType = guessContentType(fileName);
|
|
114191
114234
|
const form = new FormData();
|
|
114192
114235
|
form.append("file", new Blob([fileBuffer], { type: mimeType }), fileName);
|
|
@@ -114215,6 +114258,54 @@ async function uploadPmaxImageFile(config, googleApiUrl, accountId, absImagePath
|
|
|
114215
114258
|
}
|
|
114216
114259
|
return id;
|
|
114217
114260
|
}
|
|
114261
|
+
async function uploadPmaxImageFileBase64(config, googleApiUrl, accountId, absImagePath, assetName, fileBuffer, verbose) {
|
|
114262
|
+
const url = pmaxImageAssetUrl(googleApiUrl, accountId);
|
|
114263
|
+
let data;
|
|
114264
|
+
try {
|
|
114265
|
+
data = await apiFetch2(
|
|
114266
|
+
url,
|
|
114267
|
+
config,
|
|
114268
|
+
{
|
|
114269
|
+
method: "POST",
|
|
114270
|
+
body: JSON.stringify({ name: assetName, base64String: fileBuffer.toString("base64") })
|
|
114271
|
+
},
|
|
114272
|
+
verbose
|
|
114273
|
+
);
|
|
114274
|
+
} catch (err) {
|
|
114275
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
114276
|
+
throw new Error(`\u4E0A\u4F20\u56FE\u7247\u8D44\u4EA7\u5931\u8D25\uFF1A${msg}\uFF08${absImagePath}\uFF09`);
|
|
114277
|
+
}
|
|
114278
|
+
const id = normalizePmaxAssetId(data["id"]);
|
|
114279
|
+
if (!id) {
|
|
114280
|
+
throw new Error(`\u4E0A\u4F20\u56FE\u7247\u8D44\u4EA7\u672A\u8FD4\u56DE id\uFF08${absImagePath}\uFF09`);
|
|
114281
|
+
}
|
|
114282
|
+
return id;
|
|
114283
|
+
}
|
|
114284
|
+
async function uploadPmaxImageFile(config, googleApiUrl, accountId, absImagePath, name2, verbose) {
|
|
114285
|
+
const fileName = basename4(absImagePath);
|
|
114286
|
+
const assetName = (name2 ?? fileName).trim() || fileName;
|
|
114287
|
+
const fileBuffer = readFileSync5(absImagePath);
|
|
114288
|
+
if (fileBuffer.length <= MAX_BASE64_UPLOAD_BYTES) {
|
|
114289
|
+
return uploadPmaxImageFileBase64(
|
|
114290
|
+
config,
|
|
114291
|
+
googleApiUrl,
|
|
114292
|
+
accountId,
|
|
114293
|
+
absImagePath,
|
|
114294
|
+
assetName,
|
|
114295
|
+
fileBuffer,
|
|
114296
|
+
verbose
|
|
114297
|
+
);
|
|
114298
|
+
}
|
|
114299
|
+
return uploadPmaxImageFileMultipart(
|
|
114300
|
+
config,
|
|
114301
|
+
googleApiUrl,
|
|
114302
|
+
accountId,
|
|
114303
|
+
absImagePath,
|
|
114304
|
+
assetName,
|
|
114305
|
+
fileBuffer,
|
|
114306
|
+
verbose
|
|
114307
|
+
);
|
|
114308
|
+
}
|
|
114218
114309
|
async function resolveOneSlot(configFile, cfg, kind, accountId, config, googleApiUrl, verbose) {
|
|
114219
114310
|
const meta = SLOT_META[kind];
|
|
114220
114311
|
const presetId = String(cfg[meta.configAssetIdKey] ?? "").trim();
|
|
@@ -114343,7 +114434,11 @@ function buildPmaxCreateUrl(googleApiUrl, accountId) {
|
|
|
114343
114434
|
// src/commands/ad/pmax-create.ts
|
|
114344
114435
|
async function runAdPmaxCreate(opts) {
|
|
114345
114436
|
const cfg = loadPmaxCreateConfig(opts.configFile);
|
|
114346
|
-
const {
|
|
114437
|
+
const {
|
|
114438
|
+
errors: cfgErrors,
|
|
114439
|
+
warnings: cfgWarnings,
|
|
114440
|
+
lengthViolations: cfgLengthViolations
|
|
114441
|
+
} = runPmaxCreateValidation(cfg);
|
|
114347
114442
|
const { errors: imgErrors, warnings: imgWarnings } = await runPmaxImageValidation(
|
|
114348
114443
|
opts.configFile,
|
|
114349
114444
|
cfg
|
|
@@ -114357,6 +114452,10 @@ async function runAdPmaxCreate(opts) {
|
|
|
114357
114452
|
if (errors.length > 0) {
|
|
114358
114453
|
console.error("\n\u274C PMax \u914D\u7F6E\u6821\u9A8C\u5931\u8D25\uFF1A");
|
|
114359
114454
|
for (const e of errors) console.error(` \u2022 ${e}`);
|
|
114455
|
+
const lengthReport = formatLengthViolationsReport(cfgLengthViolations, {
|
|
114456
|
+
revalidateCommand: "pmax-validate"
|
|
114457
|
+
});
|
|
114458
|
+
if (lengthReport) console.error(lengthReport);
|
|
114360
114459
|
console.error();
|
|
114361
114460
|
process.exit(1);
|
|
114362
114461
|
}
|
|
@@ -114432,13 +114531,18 @@ import { writeFileSync as writeFileSync3 } from "fs";
|
|
|
114432
114531
|
init_cli_json_snapshot();
|
|
114433
114532
|
async function runAdPmaxValidate(opts) {
|
|
114434
114533
|
const cfg = loadPmaxCreateConfig(opts.configFile);
|
|
114435
|
-
const {
|
|
114534
|
+
const {
|
|
114535
|
+
errors: cfgErrors,
|
|
114536
|
+
warnings: cfgWarnings,
|
|
114537
|
+
lengthViolations: cfgLengthViolations
|
|
114538
|
+
} = runPmaxCreateValidation(cfg);
|
|
114436
114539
|
const { errors: imgErrors, warnings: imgWarnings } = await runPmaxImageValidation(
|
|
114437
114540
|
opts.configFile,
|
|
114438
114541
|
cfg
|
|
114439
114542
|
);
|
|
114440
114543
|
const errors = [...cfgErrors, ...imgErrors];
|
|
114441
114544
|
const warnings = [...cfgWarnings, ...imgWarnings];
|
|
114545
|
+
const lengthViolations = cfgLengthViolations;
|
|
114442
114546
|
if (opts.writeNormalized) {
|
|
114443
114547
|
const toWrite = stripMetaKeysForExport(cfg);
|
|
114444
114548
|
writeFileSync3(opts.writeNormalized, `${JSON.stringify(toWrite, null, 2)}
|
|
@@ -114449,7 +114553,9 @@ async function runAdPmaxValidate(opts) {
|
|
|
114449
114553
|
configFile: opts.configFile,
|
|
114450
114554
|
account: cfg.account?.toString().trim() || void 0,
|
|
114451
114555
|
errors,
|
|
114452
|
-
warnings
|
|
114556
|
+
warnings,
|
|
114557
|
+
lengthViolations,
|
|
114558
|
+
agentHint: lengthViolations.length > 0 ? lengthViolationAgentHint("pmax-validate") : void 0
|
|
114453
114559
|
};
|
|
114454
114560
|
const accountSuffix = payload.account;
|
|
114455
114561
|
if (await emitCliJsonOrSnapshot(opts, {
|
|
@@ -114469,6 +114575,10 @@ async function runAdPmaxValidate(opts) {
|
|
|
114469
114575
|
if (errors.length > 0) {
|
|
114470
114576
|
console.error("\n\u274C PMax \u914D\u7F6E\u6821\u9A8C\u5931\u8D25\uFF1A");
|
|
114471
114577
|
for (const e of errors) console.error(` \u2022 ${e}`);
|
|
114578
|
+
const lengthReport = formatLengthViolationsReport(lengthViolations, {
|
|
114579
|
+
revalidateCommand: "pmax-validate"
|
|
114580
|
+
});
|
|
114581
|
+
if (lengthReport) console.error(lengthReport);
|
|
114472
114582
|
console.error();
|
|
114473
114583
|
process.exit(1);
|
|
114474
114584
|
}
|
|
@@ -115283,7 +115393,6 @@ PMax \u5730\u7406\u62A5\u8868\uFF08\u6D3B\u52A8\xD7\u56FD\u5BB6\uFF0C${query.get
|
|
|
115283
115393
|
// src/commands/ad/campaign-validate.ts
|
|
115284
115394
|
import { writeFileSync as writeFileSync4 } from "fs";
|
|
115285
115395
|
init_cli_json_snapshot();
|
|
115286
|
-
var LENGTH_VIOLATION_AGENT_HINT = "\u52FF\u81EA\u52A8\u622A\u65AD JSON\u3002\u8BFB\u53D6\u843D\u76D8 JSON \u7684 lengthViolations\uFF0C\u5C06\u5168\u90E8\u6761\u76EE\u4E0E\u4FEE\u6539\u65B9\u6848\u5217\u7ED9\u7528\u6237\uFF0C\u786E\u8BA4\u540E\u5199\u5165 campaign.json \u5E76\u91CD\u65B0 campaign-validate\u3002";
|
|
115287
115396
|
async function runAdCampaignValidate(opts) {
|
|
115288
115397
|
const cfg = loadCampaignCreateConfig(opts.configFile);
|
|
115289
115398
|
const { errors, warnings, lengthViolations } = runCampaignCreateValidation(cfg);
|
|
@@ -115299,7 +115408,7 @@ async function runAdCampaignValidate(opts) {
|
|
|
115299
115408
|
errors,
|
|
115300
115409
|
warnings,
|
|
115301
115410
|
lengthViolations,
|
|
115302
|
-
agentHint: lengthViolations.length > 0 ?
|
|
115411
|
+
agentHint: lengthViolations.length > 0 ? lengthViolationAgentHint("campaign-validate") : void 0
|
|
115303
115412
|
};
|
|
115304
115413
|
const accountSuffix = payload.account || void 0;
|
|
115305
115414
|
if (await emitCliJsonOrSnapshot(opts, {
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# siluzan-tso — Agent 文档目录
|
|
2
|
+
|
|
3
|
+
> 单一 Skill 包(`name: siluzan-tso`)。运行时入口:`SKILL.md` → 按域 lazy-load `references/`。
|
|
4
|
+
|
|
5
|
+
## 启动顺序
|
|
6
|
+
|
|
7
|
+
1. Read `SKILL.md`(路由 + 任务→文档表)
|
|
8
|
+
2. **每个新任务** Read `references/core/agent-conventions.md`
|
|
9
|
+
3. 按任务表 Read 对应域文档后再执行 `siluzan-tso …`
|
|
10
|
+
|
|
11
|
+
## 文档域(gstack-style domains)
|
|
12
|
+
|
|
13
|
+
| 域 | 路径 | 何时 Read |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| **Core** | `references/core/` | 纪律、安装、tips、playbooks、workflows |
|
|
16
|
+
| **Accounts** | `references/accounts/` | 列表、余额、开户、财务、审计 |
|
|
17
|
+
| **Google Ads** | `references/google-ads/` | CRUD、PMax、搜索系列流水线;`rules/` 为优化 SOP |
|
|
18
|
+
| **Analytics** | `references/analytics/` | 拉数、批处理、拓词、RAG、TSO 报告 |
|
|
19
|
+
| **Operations** | `references/operations/` | 预警、线索、优化记录、宿主编排自动化 |
|
|
20
|
+
| **Templates** | `assets/`、`report-templates/` | JSON 契约、报告纲要 |
|
|
21
|
+
|
|
22
|
+
## Playbook(标准动作)
|
|
23
|
+
|
|
24
|
+
| ID | 文档 |
|
|
25
|
+
| --- | --- |
|
|
26
|
+
| P1–P7 | `references/core/playbooks.md` |
|
|
27
|
+
| OKKI 周报 | `report-templates/okki-weekly-google-client.md` |
|
|
28
|
+
| 询盘分析 | `report-templates/google-inquiry-analysis.md` |
|
|
29
|
+
|
|
30
|
+
## 维护
|
|
31
|
+
|
|
32
|
+
- 结构规范:`references/core/skill-authoring.md`
|
|
33
|
+
- 人类深读:`docs/skill-guide.md`
|
|
34
|
+
- 源码唯一真相:`tso-cli/assets/siluzan-ads/`(勿编辑 `skills/siluzan-tso/` 副本)
|
|
35
|
+
|
|
36
|
+
## CLI 代码域(与文档对齐)
|
|
37
|
+
|
|
38
|
+
| CLI 模块 | 文档域 |
|
|
39
|
+
| --- | --- |
|
|
40
|
+
| `src/commands/list-accounts/`、`accounts-digest/`、`balance-scan/` | accounts |
|
|
41
|
+
| `src/commands/open-account/`、`account-manage-register.ts` | accounts |
|
|
42
|
+
| `src/commands/ad/` | google-ads |
|
|
43
|
+
| `src/commands/google-analysis/`、`google-analysis-batch.ts` | analytics |
|
|
44
|
+
| `src/commands/report/` | analytics + report-templates |
|
|
45
|
+
| `src/commands/forewarning/`、`optimize/`、`clue.ts` | operations |
|