siluzan-tso-cli 1.1.33-beta.3 → 1.1.34-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.js +49 -14
- package/dist/skill/_meta.json +2 -2
- package/dist/skill/references/report-templates/google-ads-diagnosis.md +8 -1
- package/dist/skill/report-templates/GoogleAdsDiagnosisReport.html +42 -9
- package/dist/skill/report-templates/google-ads-diagnosis.md +8 -1
- package/dist/skill/scripts/install.ps1 +1 -1
- package/dist/skill/scripts/install.sh +1 -1
- 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.
|
|
54
|
+
> **注意**:当前为测试版(1.1.34-beta.2),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-tso-cli`。
|
|
55
55
|
|
|
56
56
|
| 助手 | 建议 `--ai` |
|
|
57
57
|
| ----------------------- | ------------------------------------ |
|
package/dist/index.js
CHANGED
|
@@ -126091,7 +126091,7 @@ function validateNewFeatureRecommendations(data) {
|
|
|
126091
126091
|
const warnings = [];
|
|
126092
126092
|
for (let i = 0; i < items.length; i++) {
|
|
126093
126093
|
const row = asRecord5(items[i]);
|
|
126094
|
-
const name2 = String(row?.strategyName ?? row?.strategy ?? i);
|
|
126094
|
+
const name2 = String(row?.strategyName ?? row?.feature ?? row?.strategy ?? i);
|
|
126095
126095
|
if (!hasNarrativeContent(row?.optimizerRecommendation)) {
|
|
126096
126096
|
warnings.push(`newFeatures.items[${name2}].optimizerRecommendation \u4E3A\u7A7A\uFF08\u987B\u7531 Agent \u586B\u5199\uFF09`);
|
|
126097
126097
|
}
|
|
@@ -126161,6 +126161,13 @@ var GOOGLE_ADS_DIAGNOSIS_COMPARISON_MODULES = [
|
|
|
126161
126161
|
"geographic",
|
|
126162
126162
|
"keywords"
|
|
126163
126163
|
];
|
|
126164
|
+
var GOOGLE_ADS_DIAGNOSIS_BIDDING_STRATEGY_MODULE = "biddingStrategy";
|
|
126165
|
+
var GOOGLE_ADS_DIAGNOSIS_NEW_FEATURES_MODULE = "newFeatures";
|
|
126166
|
+
var GOOGLE_ADS_DIAGNOSIS_RESTORE_ITEM_MODULES = [
|
|
126167
|
+
...GOOGLE_ADS_DIAGNOSIS_COMPARISON_MODULES,
|
|
126168
|
+
GOOGLE_ADS_DIAGNOSIS_BIDDING_STRATEGY_MODULE,
|
|
126169
|
+
GOOGLE_ADS_DIAGNOSIS_NEW_FEATURES_MODULE
|
|
126170
|
+
];
|
|
126164
126171
|
function asRecord6(value) {
|
|
126165
126172
|
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
126166
126173
|
return value;
|
|
@@ -126183,21 +126190,48 @@ function isComparisonTableRowValid(row) {
|
|
|
126183
126190
|
if (!isValidRateChange(rec.cvrRateChange)) return false;
|
|
126184
126191
|
return true;
|
|
126185
126192
|
}
|
|
126186
|
-
function
|
|
126193
|
+
function isNewFeatureRowValid(row) {
|
|
126194
|
+
const rec = asRecord6(row);
|
|
126195
|
+
if (!rec) return false;
|
|
126196
|
+
return Boolean(String(rec.strategyName ?? rec.feature ?? rec.strategy ?? "").trim());
|
|
126197
|
+
}
|
|
126198
|
+
function isBiddingStrategyRowValid(row) {
|
|
126199
|
+
const rec = asRecord6(row);
|
|
126200
|
+
if (!rec) return false;
|
|
126201
|
+
if (!String(rec.campaignName ?? "").trim()) return false;
|
|
126202
|
+
if (!Number.isFinite(Number(rec.duration)) || Number(rec.duration) <= 0) return false;
|
|
126203
|
+
if (!String(rec.biddingStrategyType ?? "").trim()) return false;
|
|
126204
|
+
return true;
|
|
126205
|
+
}
|
|
126206
|
+
var MODULE_ITEM_VALIDATORS = {
|
|
126207
|
+
campaigns: isComparisonTableRowValid,
|
|
126208
|
+
geographic: isComparisonTableRowValid,
|
|
126209
|
+
keywords: isComparisonTableRowValid,
|
|
126210
|
+
biddingStrategy: isBiddingStrategyRowValid,
|
|
126211
|
+
newFeatures: isNewFeatureRowValid
|
|
126212
|
+
};
|
|
126213
|
+
var MODULE_ITEM_ERROR_HINT = {
|
|
126214
|
+
campaigns: "\u7F3A\u5C11 title/currentCost/currentClicks \u6216\u73AF\u6BD4\u5B57\u6BB5\u88AB\u5199\u6210\u5B57\u7B26\u4E32\uFF08\u987B\u4FDD\u7559 collect \u4E8B\u5B9E\u884C\uFF0C\u4EC5\u7531 Agent \u586B\u5199 analysis/suggestions\uFF09",
|
|
126215
|
+
geographic: "\u7F3A\u5C11 title/currentCost/currentClicks \u6216\u73AF\u6BD4\u5B57\u6BB5\u88AB\u5199\u6210\u5B57\u7B26\u4E32\uFF08\u987B\u4FDD\u7559 collect \u4E8B\u5B9E\u884C\uFF0C\u4EC5\u7531 Agent \u586B\u5199 analysis/suggestions\uFF09",
|
|
126216
|
+
keywords: "\u7F3A\u5C11 title/currentCost/currentClicks \u6216\u73AF\u6BD4\u5B57\u6BB5\u88AB\u5199\u6210\u5B57\u7B26\u4E32\uFF08\u987B\u4FDD\u7559 collect \u4E8B\u5B9E\u884C\uFF0C\u4EC5\u7531 Agent \u586B\u5199 analysis/suggestions\uFF09",
|
|
126217
|
+
biddingStrategy: "\u7F3A\u5C11 campaignName/duration(\u5929\u6570)/biddingStrategyType\uFF08Agent \u52FF\u628A duration \u5199\u6210\u6587\u6848\u5B57\u7B26\u4E32\uFF0C\u52FF\u7528 currentStrategy \u66FF\u4EE3 biddingStrategyType\uFF09",
|
|
126218
|
+
newFeatures: "\u7F3A\u5C11 strategyName/strategy\uFF08collect \u4E8B\u5B9E\u884C\uFF1BAgent \u53EA\u586B optimizerRecommendation\uFF0C\u52FF\u6539\u7528 feature \u5B57\u6BB5\u66FF\u4EE3 strategyName\uFF09"
|
|
126219
|
+
};
|
|
126220
|
+
function moduleItemsNeedRestore(items, validator) {
|
|
126187
126221
|
if (!Array.isArray(items) || items.length === 0) return false;
|
|
126188
|
-
return items.some((row) => !
|
|
126222
|
+
return items.some((row) => !validator(row));
|
|
126189
126223
|
}
|
|
126190
|
-
function
|
|
126224
|
+
function getFactItemsErrors(data) {
|
|
126191
126225
|
const errors = [];
|
|
126192
|
-
for (const mod of
|
|
126226
|
+
for (const mod of GOOGLE_ADS_DIAGNOSIS_RESTORE_ITEM_MODULES) {
|
|
126227
|
+
const validator = MODULE_ITEM_VALIDATORS[mod];
|
|
126228
|
+
const hint = MODULE_ITEM_ERROR_HINT[mod];
|
|
126193
126229
|
const block = asRecord6(data[mod]);
|
|
126194
126230
|
const items = block?.items;
|
|
126195
126231
|
if (!Array.isArray(items) || items.length === 0) continue;
|
|
126196
126232
|
for (let i = 0; i < items.length; i++) {
|
|
126197
|
-
if (!
|
|
126198
|
-
errors.push(
|
|
126199
|
-
`${mod}.items[${i}] \u7F3A\u5C11 title/currentCost/currentClicks \u6216\u73AF\u6BD4\u5B57\u6BB5\u88AB\u5199\u6210\u5B57\u7B26\u4E32\uFF08\u987B\u4FDD\u7559 collect \u4E8B\u5B9E\u884C\uFF0C\u4EC5\u7531 Agent \u586B\u5199 analysis/suggestions\uFF09`
|
|
126200
|
-
);
|
|
126233
|
+
if (!validator(items[i])) {
|
|
126234
|
+
errors.push(`${mod}.items[${i}] ${hint}`);
|
|
126201
126235
|
}
|
|
126202
126236
|
}
|
|
126203
126237
|
}
|
|
@@ -126206,12 +126240,13 @@ function getComparisonTableErrors(data) {
|
|
|
126206
126240
|
function mergeComparisonItemsFromCollect(finalData, collectReportData) {
|
|
126207
126241
|
const data = { ...finalData };
|
|
126208
126242
|
const restoredModules = [];
|
|
126209
|
-
for (const mod of
|
|
126243
|
+
for (const mod of GOOGLE_ADS_DIAGNOSIS_RESTORE_ITEM_MODULES) {
|
|
126244
|
+
const validator = MODULE_ITEM_VALIDATORS[mod];
|
|
126210
126245
|
const finalBlock = asRecord6(data[mod]);
|
|
126211
126246
|
const collectBlock = asRecord6(collectReportData[mod]);
|
|
126212
126247
|
const finalItems = finalBlock?.items;
|
|
126213
126248
|
const collectItems = collectBlock?.items;
|
|
126214
|
-
if (!moduleItemsNeedRestore(finalItems)) continue;
|
|
126249
|
+
if (!moduleItemsNeedRestore(finalItems, validator)) continue;
|
|
126215
126250
|
if (!Array.isArray(collectItems) || collectItems.length === 0) continue;
|
|
126216
126251
|
data[mod] = {
|
|
126217
126252
|
...finalBlock ?? {},
|
|
@@ -126265,16 +126300,16 @@ async function runGoogleAdsDiagnosisRender(opts) {
|
|
|
126265
126300
|
if (restoredModules.length > 0) {
|
|
126266
126301
|
console.log(
|
|
126267
126302
|
`
|
|
126268
|
-
\u2139\uFE0F \u5DF2\u4ECE collect \u6062\u590D
|
|
126303
|
+
\u2139\uFE0F \u5DF2\u4ECE collect \u6062\u590D\u4E8B\u5B9E items\uFF08${restoredModules.join("\u3001")}\uFF09\uFF1BAgent \u53EA\u5E94\u586B\u5199 analysis/suggestions\uFF0C\u52FF\u6539\u5199 items \u884C\uFF08\u542B biddingStrategy.duration \u5929\u6570\uFF09\u3002
|
|
126269
126304
|
\u6765\u6E90\uFF1A${collectPath}
|
|
126270
126305
|
`
|
|
126271
126306
|
);
|
|
126272
126307
|
}
|
|
126273
126308
|
}
|
|
126274
126309
|
}
|
|
126275
|
-
const comparisonErrors =
|
|
126310
|
+
const comparisonErrors = getFactItemsErrors(data);
|
|
126276
126311
|
if (comparisonErrors.length > 0) {
|
|
126277
|
-
console.error("\n\u274C \
|
|
126312
|
+
console.error("\n\u274C \u4E8B\u5B9E items \u4E0D\u5B8C\u6574\uFF0CHTML \u4E2D\u90E8\u5206\u8868\u683C\u4F1A\u663E\u793A\u4E3A\u7A7A\uFF1A\n");
|
|
126278
126313
|
for (const err of comparisonErrors) {
|
|
126279
126314
|
console.error(` \xB7 ${err}`);
|
|
126280
126315
|
}
|
package/dist/skill/_meta.json
CHANGED
|
@@ -351,6 +351,8 @@ siluzan-tso google-ads-diagnosis render \
|
|
|
351
351
|
**区块 ID**:`section-bidding-strategy`
|
|
352
352
|
**数据**:`biddingStrategy.items`(仅「有问题」的系列进入表格;无数据时页面为「出价策略配置良好」)
|
|
353
353
|
|
|
354
|
+
**items 行字段(collect 事实,Agent 禁止改写)**:`campaignName`、`duration`(**天数 number**,如 `34`,勿写 `"2026-05-28 至今"` 文案)、`biddingStrategyType`(如 `MANUAL_CPC`,勿用 `currentStrategy` 替代)、`recommendedStrategy`、`recommendationReason`、`isCorrect`
|
|
355
|
+
|
|
354
356
|
| 广告系列 | 投放时长 | 当前出价策略 | 推荐出价策略 | 状态 |
|
|
355
357
|
| -------- | -------- | ------------ | ------------ | ---- |
|
|
356
358
|
| | | | | |
|
|
@@ -381,7 +383,12 @@ siluzan-tso google-ads-diagnosis render \
|
|
|
381
383
|
## 11 新产品应用
|
|
382
384
|
|
|
383
385
|
**区块 ID**:`section-new-features`
|
|
384
|
-
**数据**:`newFeatures.items`
|
|
386
|
+
**数据**:`newFeatures.items`(collect 来自 campaign-types;过滤 `strategy === "AiMax"` 的行)
|
|
387
|
+
|
|
388
|
+
**items 行字段**:
|
|
389
|
+
- collect 事实(勿改):`strategy`(如 `PerformanceMax`)、`strategyName`(如 `效果最大化`)、`accountStatus`(**boolean**,`true`=已启用)
|
|
390
|
+
- Agent 只填:`optimizerRecommendation`
|
|
391
|
+
- **禁止**用 `feature` 替代 `strategyName`(render 模板会兜底读 `feature`,但 collect 合并校验会告警)
|
|
385
392
|
|
|
386
393
|
| 策略/功能 (Strategy/Feature) | 账户状态 (Account Status) | 优化师建议 (Senior Optimizer Recommendation) |
|
|
387
394
|
| ---------------------------- | ------------------------- | -------------------------------------------- |
|
|
@@ -3799,24 +3799,39 @@
|
|
|
3799
3799
|
const list = Array.isArray(items) ? items.slice() : [];
|
|
3800
3800
|
const placeholder =
|
|
3801
3801
|
'<tr><td colspan="5" class="empty-row">暂无出价策略问题,所有系列符合推荐规则</td></tr>';
|
|
3802
|
+
const formatBiddingDuration = (item) => {
|
|
3803
|
+
const raw = item?.duration;
|
|
3804
|
+
if (typeof raw === "string" && raw.trim()) return raw.trim();
|
|
3805
|
+
const days = Number(raw);
|
|
3806
|
+
if (Number.isFinite(days) && days > 0) {
|
|
3807
|
+
return `${formatNumber(days, 0)} 天`;
|
|
3808
|
+
}
|
|
3809
|
+
return "—";
|
|
3810
|
+
};
|
|
3811
|
+
const resolveStrategyCorrect = (item) => {
|
|
3812
|
+
if (typeof item?.isCorrect === "boolean") return item.isCorrect;
|
|
3813
|
+
const status = String(item?.status ?? "");
|
|
3814
|
+
if (/匹配|正常|达标/.test(status)) return true;
|
|
3815
|
+
if (/优化|需/.test(status)) return false;
|
|
3816
|
+
return false;
|
|
3817
|
+
};
|
|
3802
3818
|
const rowBuilder = (item) => {
|
|
3803
3819
|
const campaign = escapeHtml(
|
|
3804
3820
|
String(item?.campaignName || "未命名系列"),
|
|
3805
3821
|
);
|
|
3806
|
-
const duration = escapeHtml(
|
|
3807
|
-
`${formatNumber(item?.duration, 0)} 天`,
|
|
3808
|
-
);
|
|
3822
|
+
const duration = escapeHtml(formatBiddingDuration(item));
|
|
3809
3823
|
const currentStrategy = buildStrategyTag(
|
|
3810
|
-
item?.biddingStrategyType,
|
|
3824
|
+
item?.biddingStrategyType ?? item?.currentStrategy,
|
|
3811
3825
|
false,
|
|
3812
3826
|
);
|
|
3813
3827
|
const recommended = buildRecommendedStrategyCell(
|
|
3814
3828
|
item?.recommendedStrategy,
|
|
3815
3829
|
item?.recommendationReason,
|
|
3816
3830
|
);
|
|
3817
|
-
const
|
|
3831
|
+
const isCorrect = resolveStrategyCorrect(item);
|
|
3832
|
+
const status = isCorrect
|
|
3818
3833
|
? '<span class="status-tag status-qualified">策略匹配</span>'
|
|
3819
|
-
: `<span class="status-tag status-unqualified" style="cursor: help;" title="${escapeHtml(item?.recommendationReason || "")}">
|
|
3834
|
+
: `<span class="status-tag status-unqualified" style="cursor: help;" title="${escapeHtml(item?.recommendationReason || item?.status || "")}">
|
|
3820
3835
|
需优化
|
|
3821
3836
|
<span style="margin-left:4px;cursor:pointer;color:#64748b;">?</span>
|
|
3822
3837
|
</span>
|
|
@@ -4004,6 +4019,18 @@
|
|
|
4004
4019
|
};
|
|
4005
4020
|
};
|
|
4006
4021
|
|
|
4022
|
+
const resolveFeatureEnabled = (item) => {
|
|
4023
|
+
const raw = item?.accountStatus;
|
|
4024
|
+
if (typeof raw === "boolean") return raw;
|
|
4025
|
+
const text = String(raw ?? "")
|
|
4026
|
+
.trim()
|
|
4027
|
+
.toLowerCase();
|
|
4028
|
+
if (!text) return false;
|
|
4029
|
+
if (/未启用|disabled|false|否/.test(text)) return false;
|
|
4030
|
+
if (/已启用|enabled|true|是/.test(text)) return true;
|
|
4031
|
+
return Boolean(raw);
|
|
4032
|
+
};
|
|
4033
|
+
|
|
4007
4034
|
const buildNewFeaturesRows = (items) => {
|
|
4008
4035
|
const list = (Array.isArray(items) ? items : []).filter(
|
|
4009
4036
|
(item) => String(item?.strategy ?? "") !== "AiMax",
|
|
@@ -4012,16 +4039,22 @@
|
|
|
4012
4039
|
'<tr><td colspan="3" class="empty-row">暂无新产品应用数据</td></tr>';
|
|
4013
4040
|
const rowBuilder = (item) => {
|
|
4014
4041
|
const name = escapeHtml(
|
|
4015
|
-
String(
|
|
4042
|
+
String(
|
|
4043
|
+
item?.strategyName ||
|
|
4044
|
+
item?.feature ||
|
|
4045
|
+
item?.strategy ||
|
|
4046
|
+
"未命名功能",
|
|
4047
|
+
),
|
|
4016
4048
|
);
|
|
4017
|
-
const
|
|
4049
|
+
const enabled = resolveFeatureEnabled(item);
|
|
4050
|
+
const status = enabled
|
|
4018
4051
|
? '<span class="feature-status is-enabled"><span class="feature-icon">✅</span>已启用</span>'
|
|
4019
4052
|
: '<span class="feature-status is-disabled"><span class="feature-icon">❌</span>未启用</span>';
|
|
4020
4053
|
const recommendation = String(
|
|
4021
4054
|
item?.optimizerRecommendation || "",
|
|
4022
4055
|
).trim();
|
|
4023
4056
|
const recommendationHtml = recommendation
|
|
4024
|
-
? `<span class="recommendation-text${
|
|
4057
|
+
? `<span class="recommendation-text${enabled ? " is-excellent" : ""}">${escapeHtml(
|
|
4025
4058
|
recommendation,
|
|
4026
4059
|
)}</span>`
|
|
4027
4060
|
: '<span class="recommendation-text">暂无建议</span>';
|
|
@@ -351,6 +351,8 @@ siluzan-tso google-ads-diagnosis render \
|
|
|
351
351
|
**区块 ID**:`section-bidding-strategy`
|
|
352
352
|
**数据**:`biddingStrategy.items`(仅「有问题」的系列进入表格;无数据时页面为「出价策略配置良好」)
|
|
353
353
|
|
|
354
|
+
**items 行字段(collect 事实,Agent 禁止改写)**:`campaignName`、`duration`(**天数 number**,如 `34`,勿写 `"2026-05-28 至今"` 文案)、`biddingStrategyType`(如 `MANUAL_CPC`,勿用 `currentStrategy` 替代)、`recommendedStrategy`、`recommendationReason`、`isCorrect`
|
|
355
|
+
|
|
354
356
|
| 广告系列 | 投放时长 | 当前出价策略 | 推荐出价策略 | 状态 |
|
|
355
357
|
| -------- | -------- | ------------ | ------------ | ---- |
|
|
356
358
|
| | | | | |
|
|
@@ -381,7 +383,12 @@ siluzan-tso google-ads-diagnosis render \
|
|
|
381
383
|
## 11 新产品应用
|
|
382
384
|
|
|
383
385
|
**区块 ID**:`section-new-features`
|
|
384
|
-
**数据**:`newFeatures.items`
|
|
386
|
+
**数据**:`newFeatures.items`(collect 来自 campaign-types;过滤 `strategy === "AiMax"` 的行)
|
|
387
|
+
|
|
388
|
+
**items 行字段**:
|
|
389
|
+
- collect 事实(勿改):`strategy`(如 `PerformanceMax`)、`strategyName`(如 `效果最大化`)、`accountStatus`(**boolean**,`true`=已启用)
|
|
390
|
+
- Agent 只填:`optimizerRecommendation`
|
|
391
|
+
- **禁止**用 `feature` 替代 `strategyName`(render 模板会兜底读 `feature`,但 collect 合并校验会告警)
|
|
385
392
|
|
|
386
393
|
| 策略/功能 (Strategy/Feature) | 账户状态 (Account Status) | 优化师建议 (Senior Optimizer Recommendation) |
|
|
387
394
|
| ---------------------------- | ------------------------- | -------------------------------------------- |
|
|
@@ -9,7 +9,7 @@ $ErrorActionPreference = 'Stop'
|
|
|
9
9
|
# -- Package info (injected at build time) ------------------------------------
|
|
10
10
|
$PKG_NAME = 'siluzan-tso-cli'
|
|
11
11
|
# PKG_VERSION 锁定到与本脚本同批构建产物一致的版本,避免与 dist/skill 错位
|
|
12
|
-
$PKG_VERSION = '1.1.
|
|
12
|
+
$PKG_VERSION = '1.1.34-beta.2'
|
|
13
13
|
$CLI_BIN = 'siluzan-tso'
|
|
14
14
|
$SKILL_LABEL = 'Siluzan TSO'
|
|
15
15
|
$INSTALL_CMD = 'npm install -g siluzan-tso-cli@beta'
|
|
@@ -9,7 +9,7 @@ set -euo pipefail
|
|
|
9
9
|
# -- Package info (injected at build time) ------------------------------------
|
|
10
10
|
readonly PKG_NAME="siluzan-tso-cli"
|
|
11
11
|
# PKG_VERSION 锁定到与本脚本同批构建产物一致的版本,避免与 dist/skill 错位
|
|
12
|
-
readonly PKG_VERSION="1.1.
|
|
12
|
+
readonly PKG_VERSION="1.1.34-beta.2"
|
|
13
13
|
readonly CLI_BIN="siluzan-tso"
|
|
14
14
|
readonly SKILL_LABEL="Siluzan TSO"
|
|
15
15
|
readonly INSTALL_CMD="npm install -g siluzan-tso-cli@beta"
|