@bty/customer-service-cli 0.6.8 → 0.6.9
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/CHANGELOG.md +4 -1
- package/dist/bin.js +112 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 0.6.9 (2026-08-24)
|
|
4
4
|
|
|
5
|
+
- 新增 `channel-metric` 命令组,查询千牛等渠道店铺客服的每日排行指标(`channel_metric_snapshot`):
|
|
6
|
+
- `channel-metric query --workspace-id <ws> --start <date> --end <date> [--agent <id>] [--platform <channel>]`:按 workspace + 日期区间(+ 可选 agent / 渠道)查询指标,按日期×渠道分组输出。
|
|
7
|
+
- `channel-metric backfill --channel <channel> --start <date> --end <date> [--workspace-id <ws>...]`:手动补数据,采集指定日期区间的渠道指标;`--workspace-id` 可重复传,缺省采集所有已开启配置的 workspace。
|
|
5
8
|
- 新增 `media upload` 命令与 `product supplement` 子命令组,支持商品「补充知识」图片/视频维护,与前端上传行为一致:
|
|
6
9
|
- `media upload --file <path> --type image|video [--path-prefix /ai/knowledge/supplement] [--dry-run]`:本地图片/视频先经 `/v1/upload_sts` 取 STS 凭证上传到公开 OSS(`resource_bucket`),返回公网 URL;已是 http(s) URL 直接拒绝(无需上传)。上传 key 与前端一致:`${prefix}/${timestamp}_${filename}`。图片上限 10MB、视频上限 200MB,超限/类型不符在发起上传请求前直接失败。
|
|
7
10
|
- `product supplement list --agent <id> --product-id <id>`:读取并解析商品「补充知识」条目(容错解析数组 / JSON 字符串 / 多层编码)。
|
package/dist/bin.js
CHANGED
|
@@ -1095,6 +1095,115 @@ function registerChangeConsumerCommand(program2) {
|
|
|
1095
1095
|
});
|
|
1096
1096
|
}
|
|
1097
1097
|
|
|
1098
|
+
// src/commands/channel-metric.ts
|
|
1099
|
+
import Table2 from "cli-table3";
|
|
1100
|
+
|
|
1101
|
+
// src/client/channel-metric-api.ts
|
|
1102
|
+
var CHANNEL_METRIC_PREFIX = "/v1/channel-metric";
|
|
1103
|
+
async function backfillChannelMetrics(opts) {
|
|
1104
|
+
const request = createRequest();
|
|
1105
|
+
const body = {
|
|
1106
|
+
channel: opts.channel,
|
|
1107
|
+
start_date: opts.startDate,
|
|
1108
|
+
end_date: opts.endDate
|
|
1109
|
+
};
|
|
1110
|
+
if (opts.workspaceIds && opts.workspaceIds.length > 0) {
|
|
1111
|
+
body.workspace_ids = opts.workspaceIds;
|
|
1112
|
+
}
|
|
1113
|
+
return request(getObservabilityUrl(), `${CHANNEL_METRIC_PREFIX}/backfill`, {
|
|
1114
|
+
method: "POST",
|
|
1115
|
+
body
|
|
1116
|
+
});
|
|
1117
|
+
}
|
|
1118
|
+
async function queryChannelMetrics(opts) {
|
|
1119
|
+
const request = createRequest();
|
|
1120
|
+
const query = {
|
|
1121
|
+
workspace_id: opts.workspaceId,
|
|
1122
|
+
start_date: opts.startDate,
|
|
1123
|
+
end_date: opts.endDate
|
|
1124
|
+
};
|
|
1125
|
+
if (opts.configId) query.config_id = opts.configId;
|
|
1126
|
+
if (opts.channel) query.channel = opts.channel;
|
|
1127
|
+
return request(getObservabilityUrl(), `${CHANNEL_METRIC_PREFIX}/metrics`, {
|
|
1128
|
+
method: "GET",
|
|
1129
|
+
query
|
|
1130
|
+
});
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
// src/commands/channel-metric.ts
|
|
1134
|
+
function collect(value, previous) {
|
|
1135
|
+
return previous.concat([value]);
|
|
1136
|
+
}
|
|
1137
|
+
function renderGroupedTable(groups) {
|
|
1138
|
+
let total = 0;
|
|
1139
|
+
for (const group of groups) {
|
|
1140
|
+
process.stdout.write(`
|
|
1141
|
+
=== ${group.stat_date} \xB7 ${group.channel}\uFF08${group.items.length} \u4E2A\u8D26\u53F7\uFF09===
|
|
1142
|
+
`);
|
|
1143
|
+
const first = group.items[0];
|
|
1144
|
+
const headers = (first?.metrics_json ?? []).map((field) => field.label);
|
|
1145
|
+
const table = new Table2({ head: ["account_id", ...headers] });
|
|
1146
|
+
for (const row of group.items) {
|
|
1147
|
+
table.push([
|
|
1148
|
+
String(row.account_id),
|
|
1149
|
+
...row.metrics_json.map(
|
|
1150
|
+
(field) => field.value === void 0 || field.value === null ? "-" : String(field.value)
|
|
1151
|
+
)
|
|
1152
|
+
]);
|
|
1153
|
+
}
|
|
1154
|
+
process.stdout.write(`${table.toString()}
|
|
1155
|
+
`);
|
|
1156
|
+
total += group.items.length;
|
|
1157
|
+
}
|
|
1158
|
+
process.stdout.write(`
|
|
1159
|
+
\u5171 ${total} \u6761\u8BB0\u5F55
|
|
1160
|
+
`);
|
|
1161
|
+
}
|
|
1162
|
+
function registerChannelMetricCommand(program2) {
|
|
1163
|
+
const channelMetric = program2.command("channel-metric").description("\u6E20\u9053\u76D1\u63A7\u6307\u6807\u67E5\u8BE2 \u2014\u2014 \u67E5\u8BE2\u5343\u725B\u7B49\u6E20\u9053\u5E97\u94FA\u5BA2\u670D\u7684\u6BCF\u65E5\u6392\u884C\u6307\u6807\uFF08channel_metric_snapshot\uFF09");
|
|
1164
|
+
channelMetric.command("query").description(
|
|
1165
|
+
"\u6309 workspace + \u65E5\u671F\u533A\u95F4\uFF08+ \u53EF\u9009 agent / \u6E20\u9053\uFF09\u67E5\u8BE2\u6307\u6807\uFF0C\u6309\u65E5\u671F\xD7\u6E20\u9053\u5206\u7EC4\u8F93\u51FA\u3002\u4E0D\u4F20 --agent \u8F93\u51FA\u8BE5 workspace \u4E0B\u5168\u90E8 agent\uFF0C\u4E0D\u4F20 --platform \u8F93\u51FA\u5168\u90E8\u6E20\u9053"
|
|
1166
|
+
).requiredOption("--workspace-id <workspace_id>", "\u5DE5\u4F5C\u7A7A\u95F4 ID\uFF08\u5FC5\u4F20\uFF0C\u4E0E\u670D\u52A1\u7AEF\u5F52\u5C5E\u6821\u9A8C\u4E00\u81F4\uFF09").option("--agent <agent_id>", "Agent \u914D\u7F6E ID\uFF1B\u7F3A\u7701\u67E5\u8BE2\u8BE5 workspace \u4E0B\u5168\u90E8 agent").requiredOption("--start <date>", "\u8D77\u59CB\u65E5\u671F\uFF08YYYY-MM-DD\uFF09").requiredOption("--end <date>", "\u7ED3\u675F\u65E5\u671F\uFF08YYYY-MM-DD\uFF09").option("--platform <channel>", "\u6E20\u9053\uFF08platform\uFF09\uFF0C\u5982 qianniu\uFF1B\u7F3A\u7701\u67E5\u8BE2\u5168\u90E8\u6E20\u9053").action(async (opts) => {
|
|
1167
|
+
try {
|
|
1168
|
+
setRuntimeWorkspaceId(opts.workspaceId);
|
|
1169
|
+
const data = await queryChannelMetrics({
|
|
1170
|
+
workspaceId: opts.workspaceId,
|
|
1171
|
+
configId: opts.agent,
|
|
1172
|
+
startDate: opts.start,
|
|
1173
|
+
endDate: opts.end,
|
|
1174
|
+
channel: opts.platform
|
|
1175
|
+
});
|
|
1176
|
+
const groups = data?.groups ?? [];
|
|
1177
|
+
if (groups.length === 0) {
|
|
1178
|
+
process.stdout.write("(empty)\n");
|
|
1179
|
+
return;
|
|
1180
|
+
}
|
|
1181
|
+
renderGroupedTable(groups);
|
|
1182
|
+
} catch (err) {
|
|
1183
|
+
reportCaughtError(err);
|
|
1184
|
+
process.exit(toExitCode(err));
|
|
1185
|
+
}
|
|
1186
|
+
});
|
|
1187
|
+
channelMetric.command("backfill").description(
|
|
1188
|
+
"\u624B\u52A8\u8865\u6570\u636E\uFF1A\u91C7\u96C6\u6307\u5B9A\u65E5\u671F\u533A\u95F4\u7684\u6E20\u9053\u6307\u6807\u3002\u53EF\u6307\u5B9A workspace\uFF08\u53EF\u91CD\u590D\u4F20\uFF09\uFF1B\u4E0D\u4F20 --workspace-id = \u91C7\u96C6\u6240\u6709\u5DF2\u5F00\u542F\u914D\u7F6E\u7684 workspace"
|
|
1189
|
+
).requiredOption("--channel <channel>", "\u6E20\u9053\uFF08platform\uFF09\uFF0C\u5982 qianniu").requiredOption("--start <date>", "\u8D77\u59CB\u65E5\u671F\uFF08YYYY-MM-DD\uFF09").requiredOption("--end <date>", "\u7ED3\u675F\u65E5\u671F\uFF08YYYY-MM-DD\uFF09").option("--workspace-id <workspace_id>", "\u5DE5\u4F5C\u7A7A\u95F4 ID\uFF08\u53EF\u91CD\u590D\u4F20\uFF1B\u7F3A\u7701 = \u91C7\u96C6\u6240\u6709\u5DF2\u5F00\u542F\u914D\u7F6E\u7684 ws\uFF09", collect).action(async (opts) => {
|
|
1190
|
+
try {
|
|
1191
|
+
const workspaceIds = opts.workspaceId?.length ? opts.workspaceId : void 0;
|
|
1192
|
+
setRuntimeWorkspaceId(workspaceIds?.[0]);
|
|
1193
|
+
const data = await backfillChannelMetrics({
|
|
1194
|
+
channel: opts.channel,
|
|
1195
|
+
startDate: opts.start,
|
|
1196
|
+
endDate: opts.end,
|
|
1197
|
+
workspaceIds
|
|
1198
|
+
});
|
|
1199
|
+
formatOutput({ success: true, data }, program2.opts().table);
|
|
1200
|
+
} catch (err) {
|
|
1201
|
+
reportCaughtError(err);
|
|
1202
|
+
process.exit(toExitCode(err));
|
|
1203
|
+
}
|
|
1204
|
+
});
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1098
1207
|
// src/client/chat-history-api.ts
|
|
1099
1208
|
async function listChatHistory(opts) {
|
|
1100
1209
|
const request = createRequest();
|
|
@@ -1608,7 +1717,7 @@ async function writeBinaryToFile(filePath, buffer) {
|
|
|
1608
1717
|
}
|
|
1609
1718
|
|
|
1610
1719
|
// src/commands/dashboard.ts
|
|
1611
|
-
function
|
|
1720
|
+
function collect2(value, previous) {
|
|
1612
1721
|
return previous.concat([value]);
|
|
1613
1722
|
}
|
|
1614
1723
|
function registerDashboardCommand(program2) {
|
|
@@ -1663,7 +1772,7 @@ function registerDashboardCommand(program2) {
|
|
|
1663
1772
|
});
|
|
1664
1773
|
dashboard.command("export").description(
|
|
1665
1774
|
"\u5BFC\u51FA\u5E97\u94FA\u7EF4\u5EA6\u6BCF\u65E5\u660E\u7EC6\uFF08\u63A5\u5F85\u5BA2\u6237\u6570/AI\u72EC\u7ACB\u627F\u63A5/\u8F6C\u4EBA\u5DE5/AI\u56DE\u590D\u6D88\u606F\u6570\uFF09\u3002\u9ED8\u8BA4\u89E3\u6790\u4E3A JSON \u884C\uFF1B--out \u843D\u76D8\u539F\u59CB CSV\u3002\u53EF\u91CD\u590D --config-id \u9650\u5B9A\u5E97\u94FA"
|
|
1666
|
-
).requiredOption("--start <date>", "\u5F00\u59CB\u65E5\u671F (YYYY-MM-DD)\uFF0C\u5FC5\u586B").requiredOption("--end <date>", "\u7ED3\u675F\u65E5\u671F (YYYY-MM-DD)\uFF0C\u5FC5\u586B\uFF0C\u4E0D\u80FD\u665A\u4E8E\u6628\u5929").option("--config-id <id>", "\u5E97\u94FA\u914D\u7F6E ID\uFF08\u53EF\u91CD\u590D\u4F20\uFF1B\u4E0D\u4F20=\u5168\u90E8\u5E97\u94FA\uFF09",
|
|
1775
|
+
).requiredOption("--start <date>", "\u5F00\u59CB\u65E5\u671F (YYYY-MM-DD)\uFF0C\u5FC5\u586B").requiredOption("--end <date>", "\u7ED3\u675F\u65E5\u671F (YYYY-MM-DD)\uFF0C\u5FC5\u586B\uFF0C\u4E0D\u80FD\u665A\u4E8E\u6628\u5929").option("--config-id <id>", "\u5E97\u94FA\u914D\u7F6E ID\uFF08\u53EF\u91CD\u590D\u4F20\uFF1B\u4E0D\u4F20=\u5168\u90E8\u5E97\u94FA\uFF09", collect2, []).option("--channel <channel>", "\u6E20\u9053\u7B5B\u9009: qianniu | jingdong | pinduoduo | douyin").option("--out <path>", "\u843D\u76D8\u539F\u59CB CSV \u8DEF\u5F84\uFF08\u7236\u76EE\u5F55\u81EA\u52A8 mkdir -p\uFF09").action(async (opts) => {
|
|
1667
1776
|
try {
|
|
1668
1777
|
const result = await exportShopData({
|
|
1669
1778
|
startDate: opts.start,
|
|
@@ -7470,6 +7579,7 @@ registerMediaCommand(program);
|
|
|
7470
7579
|
registerKnowledgeCommand(program);
|
|
7471
7580
|
registerActivityCommand(program);
|
|
7472
7581
|
registerIssueCommand(program);
|
|
7582
|
+
registerChannelMetricCommand(program);
|
|
7473
7583
|
registerChatHistoryCommand(program);
|
|
7474
7584
|
registerFaqCommand(program);
|
|
7475
7585
|
registerConversationCommand(program);
|