@bty/customer-service-cli 0.6.7 → 0.6.8

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 CHANGED
@@ -9,6 +9,10 @@
9
9
  - `product supplement append-media --agent <id> --product-id <id> --index <n> [--image ...] [--video ...] [--dry-run] [--backup <path>]`:仅向目标下标条目追加媒体,其它条目原样保留;去重合并,未提供任何媒体时报错。
10
10
  - Dashboard 命令使用客服 API 原域名下的 `/observability` 网关前缀,无需新增地址配置。
11
11
 
12
+ ## 0.6.8 (2026-08-10)
13
+
14
+ - `conversation transfer-human` 新增 `--only-abnormal`:默认仍返回全部转人工会话;开启后仅保留异常会话,排除正常 SOP 转人工、`专家agent无法回答`、`存在无法处理的消息类型:...` 三类正常情况。
15
+
12
16
  ## 0.6.7 (2026-07-30)
13
17
 
14
18
  > 版本号说明:registry 实际发布序列 0.6.2 → 0.6.4 → 0.6.5 → 0.6.6(0.6.3 从未发布,0.6.4–0.6.6 由其它分支占用),故本条目落 0.6.7。
package/README.md CHANGED
@@ -520,7 +520,7 @@ Agent 关联的通用规则知识库(`suffix_type=_common`),与 FAQ / 商
520
520
  | `conversation list [--agent <id>] [--equipment-id <设备ID>] [--user <用户名>] [--start <日期>] [--end <日期>]` | 搜索会话 |
521
521
  | `conversation records <conversation_id> [--page-size N] [--direction prev|next]` | 获取会话聊天记录 |
522
522
  | `conversation context-search --query <文本> [--start <时间>] [--end <时间>]` | 通过上下文内容模糊搜索对话记录(返回匹配消息详情,时间范围最多 3 天) |
523
- | `conversation transfer-human --agent <customer_agent_config_id> --start <时间> --end <时间>` | 查询转人工会话及对应转人工消息记录(时间范围最多 7 天,自动 cursor 翻页) |
523
+ | `conversation transfer-human --agent <customer_agent_config_id> --start <时间> --end <时间> [--only-abnormal]` | 查询转人工会话及对应转人工消息记录(时间范围最多 7 天,自动 cursor 翻页;`--only-abnormal` 仅保留异常会话) |
524
524
 
525
525
 
526
526
  ### Agent 调试 (`debug`)
package/dist/bin.js CHANGED
@@ -526,6 +526,7 @@ async function listActivities(opts) {
526
526
  page_size: opts.pageSize ?? 20
527
527
  };
528
528
  if (opts.search) query.search = opts.search;
529
+ if (opts.state) query.state = opts.state;
529
530
  return request(getCustomerServiceUrl(), `${PATH_PREFIX}/list`, {
530
531
  method: "GET",
531
532
  query
@@ -615,6 +616,11 @@ function parseEnabledFlag(raw) {
615
616
  if (raw === "false") return false;
616
617
  throw new Error("--enabled \u4EC5\u63A5\u53D7 true | false");
617
618
  }
619
+ var VALID_LIST_STATES = ["all", "pending", "ongoing", "ended"];
620
+ function parseStateFlag(raw) {
621
+ if (VALID_LIST_STATES.includes(raw)) return raw;
622
+ throw new Error(`--state \u4EC5\u63A5\u53D7 ${VALID_LIST_STATES.join(" | ")}`);
623
+ }
618
624
  function parseActivityId(raw) {
619
625
  const n = Number(raw);
620
626
  if (!Number.isInteger(n) || n <= 0) {
@@ -627,14 +633,18 @@ function registerActivityCommand(program2) {
627
633
  "\u6D3B\u52A8 V2 \u7BA1\u7406 \u2014\u2014 \u589E\u5220\u6539\u67E5\u6D3B\u52A8\u3001\u6309\u5546\u54C1\u53CD\u67E5\u3001\u5355\u6761\u542F\u7528 toggle\u3001per-tenant V2 \u603B\u5F00\u5173\u3002\u670D\u52A1\u7AEF\uFF1Acustomer-servhub-api /v1/activity*\uFF1B\u5951\u7EA6\u53C2\u8003 docs/devkit/specs/2026-05-28-activity-v2-api-reference.md"
628
634
  );
629
635
  activity.command("list").description(
630
- "\u5217\u51FA\u6D3B\u52A8\uFF08\u5206\u9875 + \u540D\u79F0\u641C\u7D22\uFF09\u3002\u8FD4\u56DE total / v2_activity_enabled / items[]\uFF0Citems \u542B id\u3001activity_name\u3001effective_type\u3001enabled\u3001product_scope\u3001products \u7B49"
631
- ).requiredOption("--agent <id>", "customer_agent_config_id\uFF08agent \u914D\u7F6E ID\uFF0C\u4ECE agent list \u83B7\u53D6\uFF09").option("--page <number>", "\u9875\u7801\uFF08\u22651\uFF09", "1").option("--page-size <number>", "\u6BCF\u9875\u6570\u91CF\uFF081-100\uFF09", "20").option("--search <text>", "\u6309\u6D3B\u52A8\u540D\u6A21\u7CCA\u5339\u914D").action(async (opts) => {
636
+ "\u5217\u51FA\u6D3B\u52A8\uFF08\u5206\u9875 + \u540D\u79F0\u641C\u7D22 + \u72B6\u6001\u8FC7\u6EE4\uFF09\u3002\u8FD4\u56DE total / v2_activity_enabled / items[]\uFF0Citems \u542B id\u3001activity_name\u3001effective_type\u3001enabled\u3001product_scope\u3001products \u7B49\uFF1Btotal \u4E0E state/search \u8FC7\u6EE4\u540C\u53E3\u5F84"
637
+ ).requiredOption("--agent <id>", "customer_agent_config_id\uFF08agent \u914D\u7F6E ID\uFF0C\u4ECE agent list \u83B7\u53D6\uFF09").option("--page <number>", "\u9875\u7801\uFF08\u22651\uFF09", "1").option("--page-size <number>", "\u6BCF\u9875\u6570\u91CF\uFF081-100\uFF09", "20").option("--search <text>", "\u6309\u6D3B\u52A8\u540D\u6A21\u7CCA\u5339\u914D").option(
638
+ "--state <state>",
639
+ "\u5C55\u793A\u72B6\u6001\u8FC7\u6EE4\uFF1Aall | pending | ongoing | ended\uFF08\u7F3A\u7701=all\uFF0C\u542B\u65F6\u95F4\u5F02\u5E38\u6761\u76EE\uFF1Blong_term \u6052 ongoing\uFF09"
640
+ ).action(async (opts) => {
632
641
  try {
633
642
  const data = await listActivities({
634
643
  customerAgentConfigId: opts.agent,
635
644
  page: Number(opts.page),
636
645
  pageSize: Number(opts.pageSize),
637
- search: opts.search
646
+ search: opts.search,
647
+ state: opts.state === void 0 ? void 0 : parseStateFlag(opts.state)
638
648
  });
639
649
  formatOutput({ success: true, data }, program2.opts().table);
640
650
  } catch (err) {
@@ -1228,6 +1238,11 @@ function registerConfigCommand(program2) {
1228
1238
  var MAX_CONTEXT_SEARCH_RANGE_MS = 3 * 24 * 60 * 60 * 1e3;
1229
1239
  var MAX_TRANSFER_HUMAN_RANGE_MS = 7 * 24 * 60 * 60 * 1e3;
1230
1240
  var MAX_TRANSFER_HUMAN_CURSOR_PAGES = 500;
1241
+ var NORMAL_TRANSFER_EVENTS = /* @__PURE__ */ new Set([
1242
+ "\u9700\u8981\u4EBA\u5DE5\u63A5\u7BA1, SOP\u5F15\u64CE\u8BF7\u6C42\u8F6C\u4EBA\u5DE5\u5904\u7406",
1243
+ "\u9700\u8981\u4EBA\u5DE5\u63A5\u7BA1, \u4E13\u5BB6agent\u65E0\u6CD5\u56DE\u7B54"
1244
+ ]);
1245
+ var NORMAL_TRANSFER_EVENT_PREFIXES = ["\u9700\u8981\u4EBA\u5DE5\u63A5\u7BA1, \u5B58\u5728\u65E0\u6CD5\u5904\u7406\u7684\u6D88\u606F\u7C7B\u578B\uFF1A"];
1231
1246
  function parseSearchTime(value, fieldName) {
1232
1247
  const parsed = new Date(value);
1233
1248
  if (Number.isNaN(parsed.getTime())) {
@@ -1256,6 +1271,22 @@ function validateTransferHumanRange(startTime, endTime) {
1256
1271
  throw new Error("\u67E5\u8BE2\u65F6\u95F4\u8303\u56F4\u4E0D\u80FD\u8D85\u8FC77\u5929");
1257
1272
  }
1258
1273
  }
1274
+ function shouldKeepTransferHumanConversation(item, onlyAbnormal) {
1275
+ if (!onlyAbnormal) return true;
1276
+ if (!item || typeof item !== "object") return true;
1277
+ const takeoverEvents = item.takeover_event_record;
1278
+ if (!Array.isArray(takeoverEvents) || takeoverEvents.length === 0) return true;
1279
+ const eventNames = takeoverEvents.map((event) => {
1280
+ if (!event || typeof event !== "object") return void 0;
1281
+ const eventName = event.event_name;
1282
+ return typeof eventName === "string" ? eventName : void 0;
1283
+ }).filter((eventName) => typeof eventName === "string");
1284
+ if (eventNames.length === 0) return true;
1285
+ return eventNames.some((eventName) => {
1286
+ if (NORMAL_TRANSFER_EVENTS.has(eventName)) return false;
1287
+ return !NORMAL_TRANSFER_EVENT_PREFIXES.some((prefix) => eventName.startsWith(prefix));
1288
+ });
1289
+ }
1259
1290
  async function contextSearchRecords(opts) {
1260
1291
  validateContextSearchRange(opts.startTime, opts.endTime);
1261
1292
  const wsId = getWorkspaceId(opts.workspaceId);
@@ -1320,7 +1351,8 @@ async function listTransferHumanConversations(opts) {
1320
1351
  }
1321
1352
  }
1322
1353
  );
1323
- items.push(...page.items ?? []);
1354
+ const pageItems = page.items ?? [];
1355
+ items.push(...pageItems.filter((item) => shouldKeepTransferHumanConversation(item, opts.onlyAbnormal ?? false)));
1324
1356
  pagination = page.pagination ?? {};
1325
1357
  const hasMore = pagination.has_more === true;
1326
1358
  const nextCursor = typeof pagination.next_cursor === "string" && pagination.next_cursor ? pagination.next_cursor : void 0;
@@ -1385,12 +1417,13 @@ function registerConversationCommand(program2) {
1385
1417
  process.exit(toExitCode(err));
1386
1418
  }
1387
1419
  });
1388
- conversation.command("transfer-human").description("\u67E5\u8BE2\u8F6C\u4EBA\u5DE5\u4F1A\u8BDD\u53CA\u5BF9\u5E94\u8F6C\u4EBA\u5DE5\u6D88\u606F\u8BB0\u5F55").requiredOption("--agent <config_id>", "Agent \u914D\u7F6E ID\uFF08customer_agent_config_id\uFF09").requiredOption("--start <date>", "\u5F00\u59CB\u65F6\u95F4\uFF08ISO \u683C\u5F0F\uFF0C\u5982 2026-05-20T00:00:00\uFF09").requiredOption("--end <date>", "\u7ED3\u675F\u65F6\u95F4\uFF08ISO \u683C\u5F0F\uFF0C\u5982 2026-05-20T23:59:59\uFF09").action(async (opts) => {
1420
+ conversation.command("transfer-human").description("\u67E5\u8BE2\u8F6C\u4EBA\u5DE5\u4F1A\u8BDD\u53CA\u5BF9\u5E94\u8F6C\u4EBA\u5DE5\u6D88\u606F\u8BB0\u5F55\uFF08\u53EF\u9009\u4EC5\u4FDD\u7559\u5F02\u5E38\u4F1A\u8BDD\uFF09").requiredOption("--agent <config_id>", "Agent \u914D\u7F6E ID\uFF08customer_agent_config_id\uFF09").requiredOption("--start <date>", "\u5F00\u59CB\u65F6\u95F4\uFF08ISO \u683C\u5F0F\uFF0C\u5982 2026-05-20T00:00:00\uFF09").requiredOption("--end <date>", "\u7ED3\u675F\u65F6\u95F4\uFF08ISO \u683C\u5F0F\uFF0C\u5982 2026-05-20T23:59:59\uFF09").option("--only-abnormal", "\u4EC5\u4FDD\u7559\u5F02\u5E38\u4F1A\u8BDD\uFF08\u6392\u9664\u6B63\u5E38 SOP \u8F6C\u4EBA\u5DE5\u3001agent \u65E0\u6CD5\u56DE\u7B54\u3001\u8F93\u5165/\u6D88\u606F\u7C7B\u578B\u5F02\u5E38\uFF09", false).action(async (opts) => {
1389
1421
  try {
1390
1422
  const data = await listTransferHumanConversations({
1391
1423
  customerAgentConfigId: opts.agent,
1392
1424
  startDate: opts.start,
1393
- endDate: opts.end
1425
+ endDate: opts.end,
1426
+ onlyAbnormal: opts.onlyAbnormal
1394
1427
  });
1395
1428
  formatOutput({ success: true, data }, program2.opts().table);
1396
1429
  } catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bty/customer-service-cli",
3
- "version": "0.6.7",
3
+ "version": "0.6.8",
4
4
  "description": "AI Customer Service CLI - Agent friendly",
5
5
  "type": "module",
6
6
  "main": "./dist/bin.js",