@bty/customer-service-cli 0.5.0 → 0.5.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/CHANGELOG.md CHANGED
@@ -1,5 +1,41 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.3 (2026-05-28)
4
+
5
+ - 新增 `activity` 主语,覆盖活动 V2(Issue #34)增删改查 + per-tenant 总开关。对接 `customer-servhub-api /v1/activity*`,契约详情参见 [`docs/devkit/specs/2026-05-28-activity-v2-api-reference.md`](../../docs/devkit/specs/2026-05-28-activity-v2-api-reference.md):
6
+ - `activity list --agent <id> [--page N] [--page-size N] [--search <text>]`:列出活动(含 `total`、`v2_activity_enabled`、`items[]`)。
7
+ - `activity by-product --agent <id> --product-id <id>`:按 product_id 反查当前生效活动(仅 enabled,items[].products 恒为 [])。
8
+ - `activity create --data <json|@file>`:创建活动(完整 `IActivityWritePayload`,文件路径加 `@` 前缀走 JSON 解析)。
9
+ - `activity update <activity_id> --data <json|@file>`:整体更新活动(products 整组替换,非增量 diff;customer_agent_config_id 不可变更)。
10
+ - `activity set-enabled <activity_id> --enabled true|false`:列表行 toggle 用,PATCH `/enabled`,仅写 enabled 一个字段。
11
+ - `activity delete <activity_id>`:软删活动 + 级联软删 activity_product 关联。
12
+ - `activity v2-enabled --agent <id> --enabled true|false`:per-tenant 总开关,写 `agent_activity_setting.v2_activity_enabled`,控制 sop V2 链路是否生效。
13
+ - `activity_id` 路径参数本地校验为正整数;`--enabled` 仅接受 `true|false`,非法值直接报错优于让服务端 500。
14
+ - 业务失败统一服务端 200 + `code:400`,CLI 透传为 `exit 1` + `INVALID_PAYLOAD: …` 消息。
15
+
16
+ ## 0.5.2 (2026-05-28)
17
+
18
+ **修复:`repair-record` 命令 404 问题**
19
+
20
+ - `repair-record-api` 三处请求从 `getCustomerAgentUrl()`(`customer-agent.bantouyan.com`)改为 `getCsAdminUrl()`(`customer-service-admin.betteryeah.com`)。服务端路由部署在 `apps/cs-admin`,之前打错了 host。
21
+ - 鉴权方式从 Cookie(`auth_token`)改为标准 Bearer token,与 cs-admin headless 调用规范一致。
22
+
23
+ Issue #65
24
+
25
+ ## 0.5.1 (2026-05-28)
26
+
27
+ **新增:数据看板(`dashboard`)子命令**
28
+
29
+ - 对接后端 `/v1/dashboard` 看板接口,只产结构化数据,运营报告交由上层(LLM)按场景加工。
30
+ - `dashboard summary [--config-id]`:全局 / 单店 KPI 汇总 + 环比(接待客户数、转人工率、AI 独立承接率)。
31
+ - `dashboard trend [--config-id] [--granularity day/week/month]`:接待量 / 转人工趋势。
32
+ - `dashboard shops`:全部店铺统计列表(默认按转人工客户数降序),横向对比。
33
+ - `dashboard export --start --end [--config-id ...] [--out <path>]`:店铺维度每日明细。两段式(POST 拿 OSS `download_url` → 拉取 CSV),默认解析为 JSON 行(稳定英文 key + 计数转 number),`--out` 落盘原始 CSV。
34
+ - `dashboard intent --config-id`:单店各意图消息级转人工统计。
35
+ - `dashboard intent-conversations --config-id --event-one --event-two`:某意图下会话列表下钻。
36
+ - 复用现有 `request`(`Bearer` + `workspace-id`)/ `getCustomerServiceUrl` / 输出与退出码体系,无额外鉴权逻辑。
37
+ - 口径备注:`接待客户数(customers)` 按客户去重 ≈ 看板"会话/接待量";`AI回复消息数(ai_reply_messages)` 是真实回复条数;`对话轮次 ≈ ai_reply_messages / customers`。**数据 T+1**(`--end` ≤ 昨天),`--start`/`--end` 闭区间。
38
+
3
39
  ## 0.5.0 (2026-05-28)
4
40
 
5
41
  **Breaking change**
package/README.md CHANGED
@@ -255,6 +255,47 @@ cs-cli product update-sku --agent <id> --sku-id 6072595054179 --update '{"补充
255
255
  ```
256
256
 
257
257
 
258
+ ### 活动管理 (`activity`)
259
+
260
+ 活动 V2(Issue #34)增删改查 + per-tenant V2 总开关。服务端 `customer-servhub-api /v1/activity*`;契约详情参见 [`docs/devkit/specs/2026-05-28-activity-v2-api-reference.md`](../../docs/devkit/specs/2026-05-28-activity-v2-api-reference.md)。
261
+
262
+ | 命令 | 说明 |
263
+ | --- | --- |
264
+ | `activity list --agent <id> [--page N] [--page-size N] [--search <text>]` | 列出活动(返回 `total` / `v2_activity_enabled` / `items[]`) |
265
+ | `activity by-product --agent <id> --product-id <id>` | 按 `product_id` 反查当前生效活动(仅 enabled、product_scope='all' 必入) |
266
+ | `activity create --data <json\|@file>` | 创建活动(payload 见 `IActivityWritePayload`) |
267
+ | `activity update <activity_id> --data <json\|@file>` | 整体更新活动(products 整组替换,非增量) |
268
+ | `activity set-enabled <activity_id> --enabled <true\|false>` | 切换单条活动启用状态(仅写 enabled) |
269
+ | `activity delete <activity_id>` | 软删活动 + 级联软删关联 |
270
+ | `activity v2-enabled --agent <id> --enabled <true\|false>` | per-tenant 启停 V2 链路 |
271
+
272
+ - `--agent <id>` 对应服务端 `customer_agent_config_id`(与 `sa` / `product` 命令同口径)。
273
+ - `activity create` / `update` payload 必填:`customer_agent_config_id`、`activity_name`、`effective_type`、`activity_rule`;`effective_type=time_range` 要求 `start_time` + `end_time`;`product_scope='specific'`(缺省)要求 `products ≥ 1`。
274
+ - 业务失败(参数非法 / 跨 workspace / 不存在)服务端返 HTTP 200 + `code:400`,CLI 转为 `exit 1` 并打印 `INVALID_PAYLOAD: …`。
275
+
276
+ ```bash
277
+ # 列出活动
278
+ cs-cli activity list --agent <cfg_id> --search 返现
279
+
280
+ # 按商品反查
281
+ cs-cli activity by-product --agent <cfg_id> --product-id 914494989518
282
+
283
+ # 创建活动(从文件读 payload)
284
+ cs-cli activity create --data @activity.json
285
+
286
+ # 整体更新
287
+ cs-cli activity update 6 --data @activity.json
288
+
289
+ # 列表行 toggle 启用
290
+ cs-cli activity set-enabled 6 --enabled false
291
+
292
+ # 软删活动
293
+ cs-cli activity delete 6
294
+
295
+ # 为某 agent 启用 V2 链路
296
+ cs-cli activity v2-enabled --agent <cfg_id> --enabled true
297
+ ```
298
+
258
299
  ### 工单管理 (`issue`)
259
300
 
260
301
 
@@ -582,6 +623,26 @@ cs-cli change-consumer delivery complete <delivery_id> --status completed \
582
623
 
583
624
  **xlsx 二进制输出**:`export --output <path>` 必填路径,stdout 仅承载 JSON 报告 `{success:true, data:{path, bytes}}`,不支持 stdout pipe(避免与 JSON-by-default 冲突)。
584
625
 
626
+ ### 数据看板 (`dashboard`)
627
+
628
+ 转人工率 / 接待量 / AI 回复量等运营指标。**数据 T+1**(`--end` 不能晚于昨天,否则后端返回 400);`--start` / `--end` 为**闭区间**。渠道枚举:`qianniu`(千牛/淘宝)/ `jingdong` / `pinduoduo` / `douyin`。CLI 只产结构化数据,运营报告由上层(如 LLM)按场景加工。
629
+
630
+ | 命令 | 说明 |
631
+ | --- | --- |
632
+ | `dashboard summary [--config-id <id>] [--start <d>] [--end <d>] [--channel <c>]` | 全局或单店 KPI 汇总 + 环比(不传 `--config-id` 为全店铺聚合) |
633
+ | `dashboard trend [--config-id <id>] [--start <d>] [--end <d>] [--granularity day/week/month] [--channel <c>]` | 趋势(每日/周/月接待客户数、转人工数、转人工率),`--granularity` 默认 `day` |
634
+ | `dashboard shops [--start <d>] [--end <d>] [--channel <c>]` | 全部店铺统计列表(默认按转人工客户数降序),用于横向对比 |
635
+ | `dashboard export --start <d> --end <d> [--config-id <id> ...] [--channel <c>] [--out <path>]` | 店铺维度每日明细。默认解析为 JSON 行;`--out` 落盘原始 CSV。`--config-id` 可重复传,不传=全部店铺 |
636
+ | `dashboard intent --config-id <id> [--start <d>] [--end <d>]` | 单店各意图(一级/二级标签)消息级转人工统计,默认按转人工消息数降序 |
637
+ | `dashboard intent-conversations --config-id <id> --event-one <l> --event-two <l> [--start <d>] [--end <d>] [--page <n>] [--page-size <n>]` | 某意图下会话列表下钻 |
638
+
639
+ **口径要点**:
640
+
641
+ - `summary` / `trend` / `shops` / `intent` 直接透传后端 JSON(`total_customers` / `transfer_rate` / `avg_*` 等英文 key)。
642
+ - `export` 把 CSV 表头映射为稳定英文 key:`date / shop_name / channel / customers / ai_independent_customers / ai_independent_rate / transfer_customers / transfer_rate / ai_reply_messages`;计数字段转 number,比率字段保留原始字符串(如 `"46.0%"`)。
643
+ - **接待客户数(customers)** 按客户去重,是看板口径的"会话/接待量";**AI 回复消息数(ai_reply_messages)** 是真实 AI 回复条数;`对话轮次 ≈ ai_reply_messages / customers`。
644
+ - `dashboard export --out <path>` 落盘原始 CSV 时,stdout 仅返回 `{path, bytes, count}`。
645
+
585
646
  ## 输出格式
586
647
 
587
648
  默认输出 JSON:
package/dist/bin.js CHANGED
@@ -487,26 +487,66 @@ function buildCookieHeaders() {
487
487
  return { Cookie: `auth_token=${creds.accessToken}` };
488
488
  }
489
489
 
490
- // src/client/agent-api.ts
491
- async function listAgents(opts) {
492
- const wsId = getWorkspaceId(opts.workspaceId);
490
+ // src/client/activity-api.ts
491
+ var PATH_PREFIX = "/v1/activity";
492
+ async function listActivities(opts) {
493
493
  const request = createRequest();
494
- return request(getCustomerServiceUrl(), "/v1/customer-agent/list", {
494
+ const query = {
495
+ customer_agent_config_id: opts.customerAgentConfigId,
496
+ page: opts.page ?? 1,
497
+ page_size: opts.pageSize ?? 20
498
+ };
499
+ if (opts.search) query.search = opts.search;
500
+ return request(getCustomerServiceUrl(), `${PATH_PREFIX}/list`, {
495
501
  method: "GET",
496
- query: { page: opts.page ?? 1, page_size: opts.pageSize ?? 20, workspace_id: wsId }
502
+ query
497
503
  });
498
504
  }
499
- async function getAgent(configId) {
505
+ async function listActivitiesByProduct(opts) {
500
506
  const request = createRequest();
501
- return request(getCustomerServiceUrl(), `/v1/customer-agent/${configId}`, {
502
- method: "GET"
507
+ return request(getCustomerServiceUrl(), `${PATH_PREFIX}/by-product`, {
508
+ method: "GET",
509
+ query: {
510
+ customer_agent_config_id: opts.customerAgentConfigId,
511
+ product_id: opts.productId
512
+ }
503
513
  });
504
514
  }
505
- async function updateAgent(configId, data) {
515
+ async function createActivity(body) {
506
516
  const request = createRequest();
507
- return request(getCustomerServiceUrl(), `/v1/customer-agent/${configId}`, {
517
+ return request(getCustomerServiceUrl(), PATH_PREFIX, {
518
+ method: "POST",
519
+ body
520
+ });
521
+ }
522
+ async function updateActivity(activityId, body) {
523
+ const request = createRequest();
524
+ return request(getCustomerServiceUrl(), `${PATH_PREFIX}/${activityId}`, {
508
525
  method: "PUT",
509
- body: data
526
+ body
527
+ });
528
+ }
529
+ async function patchActivityEnabled(activityId, enabled) {
530
+ const request = createRequest();
531
+ return request(getCustomerServiceUrl(), `${PATH_PREFIX}/${activityId}/enabled`, {
532
+ method: "PATCH",
533
+ body: { enabled }
534
+ });
535
+ }
536
+ async function deleteActivity(activityId) {
537
+ const request = createRequest();
538
+ return request(getCustomerServiceUrl(), `${PATH_PREFIX}/${activityId}`, {
539
+ method: "DELETE"
540
+ });
541
+ }
542
+ async function setV2Enabled(opts) {
543
+ const request = createRequest();
544
+ return request(getCustomerServiceUrl(), `${PATH_PREFIX}/v2-enabled`, {
545
+ method: "PUT",
546
+ body: {
547
+ customer_agent_config_id: opts.customerAgentConfigId,
548
+ enabled: opts.enabled
549
+ }
510
550
  });
511
551
  }
512
552
 
@@ -540,6 +580,141 @@ function parseDataOption(value) {
540
580
  }
541
581
  }
542
582
 
583
+ // src/commands/activity.ts
584
+ function parseEnabledFlag(raw) {
585
+ if (raw === "true") return true;
586
+ if (raw === "false") return false;
587
+ throw new Error("--enabled \u4EC5\u63A5\u53D7 true | false");
588
+ }
589
+ function parseActivityId(raw) {
590
+ const n = Number(raw);
591
+ if (!Number.isInteger(n) || n <= 0) {
592
+ throw new Error(`\u975E\u6CD5\u7684 activity_id: ${raw}\uFF08\u5FC5\u987B\u4E3A\u6B63\u6574\u6570\uFF09`);
593
+ }
594
+ return n;
595
+ }
596
+ function registerActivityCommand(program2) {
597
+ const activity = program2.command("activity").description(
598
+ "\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"
599
+ );
600
+ activity.command("list").description(
601
+ "\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"
602
+ ).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) => {
603
+ try {
604
+ const data = await listActivities({
605
+ customerAgentConfigId: opts.agent,
606
+ page: Number(opts.page),
607
+ pageSize: Number(opts.pageSize),
608
+ search: opts.search
609
+ });
610
+ formatOutput({ success: true, data }, program2.opts().table);
611
+ } catch (err) {
612
+ reportCaughtError(err);
613
+ process.exit(toExitCode(err));
614
+ }
615
+ });
616
+ activity.command("by-product").description(
617
+ "\u6309 product_id \u53CD\u67E5\u5F53\u524D\u751F\u6548\u6D3B\u52A8\uFF08enabled=true \u4E14\u672A\u8F6F\u5220\uFF1Bproduct_scope='all' \u5FC5\u5165\uFF0C'specific' \u8D70 activity_product \u53CD\u67E5\uFF1B\u54CD\u5E94 items[].products \u6052\u4E3A []\uFF09"
618
+ ).requiredOption("--agent <id>", "customer_agent_config_id").requiredOption("--product-id <id>", "\u5916\u90E8\u5546\u54C1 ID\uFF08\u4E0E activity_product.product_id \u540C\u6E90\uFF09").action(async (opts) => {
619
+ try {
620
+ const data = await listActivitiesByProduct({
621
+ customerAgentConfigId: opts.agent,
622
+ productId: opts.productId
623
+ });
624
+ formatOutput({ success: true, data }, program2.opts().table);
625
+ } catch (err) {
626
+ reportCaughtError(err);
627
+ process.exit(toExitCode(err));
628
+ }
629
+ });
630
+ activity.command("create").description(
631
+ "\u521B\u5EFA\u6D3B\u52A8\u3002--data \u4E3A\u5B8C\u6574 IActivityWritePayload\uFF08JSON \u6216 @\u6587\u4EF6\uFF09\u3002\u5FC5\u586B\u5B57\u6BB5\uFF1Acustomer_agent_config_id\u3001activity_name\u3001effective_type\u3001activity_rule\uFF1Beffective_type=time_range \u65F6 start_time + end_time \u5FC5\u586B\uFF1Bproduct_scope='specific'\uFF08\u7F3A\u7701\uFF09\u8981\u6C42 products \u2265 1 \u884C"
632
+ ).requiredOption("--data <json>", "\u6D3B\u52A8 payload\uFF08JSON \u5B57\u7B26\u4E32\u6216 @\u6587\u4EF6\u8DEF\u5F84\uFF09").action(async (opts) => {
633
+ try {
634
+ const body = parseDataOption(opts.data);
635
+ const data = await createActivity(body);
636
+ formatOutput({ success: true, data }, program2.opts().table);
637
+ } catch (err) {
638
+ reportCaughtError(err);
639
+ process.exit(toExitCode(err));
640
+ }
641
+ });
642
+ activity.command("update").description(
643
+ "\u6574\u4F53\u66F4\u65B0\u6D3B\u52A8\uFF08products \u6574\u7EC4\u66FF\u6362\uFF0C\u4E0D\u505A\u589E\u91CF diff\uFF09\u3002customer_agent_config_id \u4E0D\u53EF\u53D8\u66F4\uFF0C\u4E0E\u73B0\u884C\u4E0D\u4E00\u81F4\u4F1A\u4E1A\u52A1\u5931\u8D25 400"
644
+ ).argument("<activity_id>", "\u6D3B\u52A8 ID\uFF08\u4ECE activity list \u8FD4\u56DE\u7684 id \u83B7\u53D6\uFF09").requiredOption("--data <json>", "\u5B8C\u6574 IActivityWritePayload\uFF08JSON \u5B57\u7B26\u4E32\u6216 @\u6587\u4EF6\u8DEF\u5F84\uFF09").action(async (activityIdRaw, opts) => {
645
+ try {
646
+ const activityId = parseActivityId(activityIdRaw);
647
+ const body = parseDataOption(opts.data);
648
+ const data = await updateActivity(activityId, body);
649
+ formatOutput({ success: true, data }, program2.opts().table);
650
+ } catch (err) {
651
+ reportCaughtError(err);
652
+ process.exit(toExitCode(err));
653
+ }
654
+ });
655
+ activity.command("set-enabled").description(
656
+ "\u5207\u6362\u5355\u6761\u6D3B\u52A8\u542F\u7528\u72B6\u6001\uFF08\u5217\u8868\u884C toggle \u7528\uFF0CPATCH /enabled\uFF09\u3002\u4EC5\u5199 enabled \u4E00\u4E2A\u5B57\u6BB5\uFF0C\u5176\u5B83 payload \u5B57\u6BB5\u5FFD\u7565"
657
+ ).argument("<activity_id>", "\u6D3B\u52A8 ID").requiredOption("--enabled <bool>", "true | false").action(async (activityIdRaw, opts) => {
658
+ try {
659
+ const activityId = parseActivityId(activityIdRaw);
660
+ const enabled = parseEnabledFlag(opts.enabled);
661
+ const data = await patchActivityEnabled(activityId, enabled);
662
+ formatOutput({ success: true, data }, program2.opts().table);
663
+ } catch (err) {
664
+ reportCaughtError(err);
665
+ process.exit(toExitCode(err));
666
+ }
667
+ });
668
+ activity.command("delete").description("\u8F6F\u5220\u6D3B\u52A8 + \u7EA7\u8054\u8F6F\u5220 activity_product \u5173\u8054").argument("<activity_id>", "\u6D3B\u52A8 ID").action(async (activityIdRaw) => {
669
+ try {
670
+ const activityId = parseActivityId(activityIdRaw);
671
+ const data = await deleteActivity(activityId);
672
+ formatOutput({ success: true, data }, program2.opts().table);
673
+ } catch (err) {
674
+ reportCaughtError(err);
675
+ process.exit(toExitCode(err));
676
+ }
677
+ });
678
+ activity.command("v2-enabled").description(
679
+ "per-tenant V2 \u603B\u5F00\u5173 \u2014\u2014 \u5199 agent_activity_setting.v2_activity_enabled\uFF0C\u63A7\u5236 sop V2 \u94FE\u8DEF\u662F\u5426\u751F\u6548"
680
+ ).requiredOption("--agent <id>", "customer_agent_config_id").requiredOption("--enabled <bool>", "true | false").action(async (opts) => {
681
+ try {
682
+ const enabled = parseEnabledFlag(opts.enabled);
683
+ const data = await setV2Enabled({
684
+ customerAgentConfigId: opts.agent,
685
+ enabled
686
+ });
687
+ formatOutput({ success: true, data }, program2.opts().table);
688
+ } catch (err) {
689
+ reportCaughtError(err);
690
+ process.exit(toExitCode(err));
691
+ }
692
+ });
693
+ }
694
+
695
+ // src/client/agent-api.ts
696
+ async function listAgents(opts) {
697
+ const wsId = getWorkspaceId(opts.workspaceId);
698
+ const request = createRequest();
699
+ return request(getCustomerServiceUrl(), "/v1/customer-agent/list", {
700
+ method: "GET",
701
+ query: { page: opts.page ?? 1, page_size: opts.pageSize ?? 20, workspace_id: wsId }
702
+ });
703
+ }
704
+ async function getAgent(configId) {
705
+ const request = createRequest();
706
+ return request(getCustomerServiceUrl(), `/v1/customer-agent/${configId}`, {
707
+ method: "GET"
708
+ });
709
+ }
710
+ async function updateAgent(configId, data) {
711
+ const request = createRequest();
712
+ return request(getCustomerServiceUrl(), `/v1/customer-agent/${configId}`, {
713
+ method: "PUT",
714
+ body: data
715
+ });
716
+ }
717
+
543
718
  // src/commands/agent.ts
544
719
  function registerAgentCommand(program2) {
545
720
  const agent = program2.command("agent").description(
@@ -1164,6 +1339,293 @@ function registerConversationCommand(program2) {
1164
1339
  });
1165
1340
  }
1166
1341
 
1342
+ // src/client/dashboard-api.ts
1343
+ var DASHBOARD_PREFIX = "/v1/dashboard";
1344
+ async function getDashboardSummary(opts) {
1345
+ const request = createRequest();
1346
+ const path5 = opts.configId ? `${DASHBOARD_PREFIX}/${opts.configId}/summary` : `${DASHBOARD_PREFIX}/summary`;
1347
+ const query = {};
1348
+ if (opts.startDate) query.start_date = opts.startDate;
1349
+ if (opts.endDate) query.end_date = opts.endDate;
1350
+ if (opts.channel) query.channel = opts.channel;
1351
+ return request(getCustomerServiceUrl(), path5, { method: "GET", query });
1352
+ }
1353
+ async function getDashboardTrend(opts) {
1354
+ const request = createRequest();
1355
+ const path5 = opts.configId ? `${DASHBOARD_PREFIX}/${opts.configId}/trend` : `${DASHBOARD_PREFIX}/trend`;
1356
+ const query = {};
1357
+ if (opts.startDate) query.start_date = opts.startDate;
1358
+ if (opts.endDate) query.end_date = opts.endDate;
1359
+ if (opts.granularity) query.granularity = opts.granularity;
1360
+ if (opts.channel) query.channel = opts.channel;
1361
+ return request(getCustomerServiceUrl(), path5, { method: "GET", query });
1362
+ }
1363
+ async function listShopStatistics(opts) {
1364
+ const request = createRequest();
1365
+ const query = {};
1366
+ if (opts.startDate) query.start_date = opts.startDate;
1367
+ if (opts.endDate) query.end_date = opts.endDate;
1368
+ if (opts.channel) query.channel = opts.channel;
1369
+ return request(getCustomerServiceUrl(), `${DASHBOARD_PREFIX}/shop-statistics`, {
1370
+ method: "GET",
1371
+ query
1372
+ });
1373
+ }
1374
+ async function getIntentStatistics(opts) {
1375
+ const request = createRequest();
1376
+ const query = {};
1377
+ if (opts.startDate) query.start_date = opts.startDate;
1378
+ if (opts.endDate) query.end_date = opts.endDate;
1379
+ return request(
1380
+ getCustomerServiceUrl(),
1381
+ `${DASHBOARD_PREFIX}/${opts.configId}/intent-statistics`,
1382
+ { method: "GET", query }
1383
+ );
1384
+ }
1385
+ async function listIntentConversations(opts) {
1386
+ const request = createRequest();
1387
+ const query = {
1388
+ event_one: opts.eventOne,
1389
+ event_two: opts.eventTwo
1390
+ };
1391
+ if (opts.startDate) query.start_date = opts.startDate;
1392
+ if (opts.endDate) query.end_date = opts.endDate;
1393
+ if (opts.page) query.page = opts.page;
1394
+ if (opts.pageSize) query.page_size = opts.pageSize;
1395
+ return request(
1396
+ getCustomerServiceUrl(),
1397
+ `${DASHBOARD_PREFIX}/${opts.configId}/intent-conversations`,
1398
+ { method: "GET", query }
1399
+ );
1400
+ }
1401
+ var EXPORT_HEADER_MAP = {
1402
+ \u65E5\u671F: "date",
1403
+ \u5E97\u94FA\u540D\u79F0: "shop_name",
1404
+ \u6E20\u9053: "channel",
1405
+ \u63A5\u5F85\u5BA2\u6237\u6570: "customers",
1406
+ AI\u72EC\u7ACB\u627F\u63A5\u5BA2\u6237\u6570: "ai_independent_customers",
1407
+ AI\u72EC\u7ACB\u627F\u63A5\u7387: "ai_independent_rate",
1408
+ \u8F6C\u4EBA\u5DE5\u5BA2\u6237\u6570: "transfer_customers",
1409
+ \u8F6C\u4EBA\u5DE5\u7387: "transfer_rate",
1410
+ AI\u56DE\u590D\u6D88\u606F\u6570: "ai_reply_messages"
1411
+ };
1412
+ var EXPORT_NUMERIC_KEYS = /* @__PURE__ */ new Set([
1413
+ "customers",
1414
+ "ai_independent_customers",
1415
+ "transfer_customers",
1416
+ "ai_reply_messages"
1417
+ ]);
1418
+ function parseCsv(text) {
1419
+ const s = text.charCodeAt(0) === 65279 ? text.slice(1) : text;
1420
+ const rows = [];
1421
+ let row = [];
1422
+ let field = "";
1423
+ let inQuotes = false;
1424
+ for (let i = 0; i < s.length; i++) {
1425
+ const c = s[i];
1426
+ if (inQuotes) {
1427
+ if (c === '"') {
1428
+ if (s[i + 1] === '"') {
1429
+ field += '"';
1430
+ i++;
1431
+ } else {
1432
+ inQuotes = false;
1433
+ }
1434
+ } else {
1435
+ field += c;
1436
+ }
1437
+ } else if (c === '"') {
1438
+ inQuotes = true;
1439
+ } else if (c === ",") {
1440
+ row.push(field);
1441
+ field = "";
1442
+ } else if (c === "\n") {
1443
+ row.push(field);
1444
+ rows.push(row);
1445
+ row = [];
1446
+ field = "";
1447
+ } else if (c !== "\r") {
1448
+ field += c;
1449
+ }
1450
+ }
1451
+ if (field.length > 0 || row.length > 0) {
1452
+ row.push(field);
1453
+ rows.push(row);
1454
+ }
1455
+ return rows;
1456
+ }
1457
+ function csvToRows(csv) {
1458
+ const table = parseCsv(csv).filter((r) => r.some((cell) => cell.trim() !== ""));
1459
+ if (table.length === 0) return [];
1460
+ const headers = table[0].map((h) => EXPORT_HEADER_MAP[h.trim()] ?? h.trim());
1461
+ return table.slice(1).map((cells) => {
1462
+ const obj = {};
1463
+ headers.forEach((key, idx) => {
1464
+ const raw = cells[idx] ?? "";
1465
+ if (EXPORT_NUMERIC_KEYS.has(key)) {
1466
+ const n = Number(raw);
1467
+ obj[key] = Number.isNaN(n) ? raw : n;
1468
+ } else {
1469
+ obj[key] = raw;
1470
+ }
1471
+ });
1472
+ return obj;
1473
+ });
1474
+ }
1475
+ async function exportShopData(opts) {
1476
+ const request = createRequest();
1477
+ const body = {
1478
+ start_date: opts.startDate,
1479
+ end_date: opts.endDate
1480
+ };
1481
+ if (opts.configIds && opts.configIds.length > 0) body.config_ids = opts.configIds;
1482
+ if (opts.channel) body.channel = opts.channel;
1483
+ const data = await request(
1484
+ getCustomerServiceUrl(),
1485
+ `${DASHBOARD_PREFIX}/export`,
1486
+ { method: "POST", body }
1487
+ );
1488
+ const downloadUrl = data?.download_url;
1489
+ if (!downloadUrl) {
1490
+ throw new APIError(1, "\u5BFC\u51FA\u63A5\u53E3\u672A\u8FD4\u56DE download_url");
1491
+ }
1492
+ const timeoutMs = getRuntimeRequestTimeoutMs() ?? 6e4;
1493
+ const resp = await fetch(downloadUrl, { signal: AbortSignal.timeout(timeoutMs) });
1494
+ if (!resp.ok) {
1495
+ throw new APIError(resp.status, `\u4E0B\u8F7D\u5BFC\u51FA CSV \u5931\u8D25 HTTP ${resp.status}`);
1496
+ }
1497
+ const csv = await resp.text();
1498
+ return { downloadUrl, csv, rows: csvToRows(csv) };
1499
+ }
1500
+
1501
+ // src/utils/file-output.ts
1502
+ import fs5 from "fs";
1503
+ import path4 from "path";
1504
+ async function writeBinaryToFile(filePath, buffer) {
1505
+ try {
1506
+ const dir = path4.dirname(filePath);
1507
+ fs5.mkdirSync(dir, { recursive: true });
1508
+ fs5.writeFileSync(filePath, buffer);
1509
+ } catch (err) {
1510
+ const msg = err instanceof Error ? err.message : String(err);
1511
+ throw new APIError(1, `\u6587\u4EF6\u5199\u5165\u5931\u8D25: ${msg}`);
1512
+ }
1513
+ return { path: filePath, bytes: buffer.length };
1514
+ }
1515
+
1516
+ // src/commands/dashboard.ts
1517
+ function collect(value, previous) {
1518
+ return previous.concat([value]);
1519
+ }
1520
+ function registerDashboardCommand(program2) {
1521
+ const dashboard = program2.command("dashboard").description(
1522
+ "\u6570\u636E\u770B\u677F \u2014\u2014 \u8F6C\u4EBA\u5DE5\u7387/\u63A5\u5F85\u91CF/AI\u56DE\u590D\u91CF\u7B49\u8FD0\u8425\u6307\u6807\uFF08\u6570\u636E T+1\uFF0Cend \u2264 \u6628\u5929\uFF1Bstart/end \u4E3A\u95ED\u533A\u95F4\uFF09\u3002\u53EA\u4EA7\u7ED3\u6784\u5316\u6570\u636E\uFF0C\u62A5\u544A\u7531\u4E0A\u5C42\u6309\u573A\u666F\u52A0\u5DE5"
1523
+ );
1524
+ dashboard.command("summary").description(
1525
+ "\u5168\u5C40\u6216\u5355\u5E97\u94FA KPI \u6C47\u603B + \u73AF\u6BD4\uFF08\u63A5\u5F85\u5BA2\u6237\u6570\u3001\u8F6C\u4EBA\u5DE5\u7387\u3001AI\u72EC\u7ACB\u627F\u63A5\u7387\uFF09\u3002\u4F20 --config-id \u67E5\u5355\u5E97"
1526
+ ).option("--config-id <id>", "\u5E97\u94FA\u914D\u7F6E ID\uFF08\u4E0D\u4F20=\u5168\u5E97\u94FA\u805A\u5408\uFF09").option("--start <date>", "\u5F00\u59CB\u65E5\u671F (YYYY-MM-DD)\uFF0C\u9ED8\u8BA4\u6628\u65E5").option("--end <date>", "\u7ED3\u675F\u65E5\u671F (YYYY-MM-DD)\uFF0C\u9ED8\u8BA4\u6628\u65E5\uFF0C\u4E0D\u80FD\u665A\u4E8E\u6628\u5929").option("--channel <channel>", "\u6E20\u9053\u7B5B\u9009: qianniu | jingdong | pinduoduo | douyin").action(async (opts) => {
1527
+ try {
1528
+ const data = await getDashboardSummary({
1529
+ configId: opts.configId,
1530
+ startDate: opts.start,
1531
+ endDate: opts.end,
1532
+ channel: opts.channel
1533
+ });
1534
+ formatOutput({ success: true, data }, program2.opts().table);
1535
+ } catch (err) {
1536
+ reportCaughtError(err);
1537
+ process.exit(toExitCode(err));
1538
+ }
1539
+ });
1540
+ dashboard.command("trend").description(
1541
+ "\u5168\u5C40\u6216\u5355\u5E97\u94FA\u8D8B\u52BF\uFF08\u6BCF\u65E5/\u5468/\u6708\u63A5\u5F85\u5BA2\u6237\u6570\u3001\u8F6C\u4EBA\u5DE5\u6570\u3001\u8F6C\u4EBA\u5DE5\u7387\uFF09\u3002\u4F20 --config-id \u67E5\u5355\u5E97"
1542
+ ).option("--config-id <id>", "\u5E97\u94FA\u914D\u7F6E ID\uFF08\u4E0D\u4F20=\u5168\u5E97\u94FA\u805A\u5408\uFF09").option("--start <date>", "\u5F00\u59CB\u65E5\u671F (YYYY-MM-DD)\uFF0C\u9ED8\u8BA4\u6628\u65E5").option("--end <date>", "\u7ED3\u675F\u65E5\u671F (YYYY-MM-DD)\uFF0C\u9ED8\u8BA4\u6628\u65E5\uFF0C\u4E0D\u80FD\u665A\u4E8E\u6628\u5929").option("--granularity <g>", "\u7C92\u5EA6: day | week | month", "day").option("--channel <channel>", "\u6E20\u9053\u7B5B\u9009: qianniu | jingdong | pinduoduo | douyin").action(async (opts) => {
1543
+ try {
1544
+ const data = await getDashboardTrend({
1545
+ configId: opts.configId,
1546
+ startDate: opts.start,
1547
+ endDate: opts.end,
1548
+ granularity: opts.granularity,
1549
+ channel: opts.channel
1550
+ });
1551
+ formatOutput({ success: true, data }, program2.opts().table);
1552
+ } catch (err) {
1553
+ reportCaughtError(err);
1554
+ process.exit(toExitCode(err));
1555
+ }
1556
+ });
1557
+ dashboard.command("shops").description("\u5168\u90E8\u5E97\u94FA\u7EDF\u8BA1\u5217\u8868\uFF08\u9ED8\u8BA4\u6309\u8F6C\u4EBA\u5DE5\u5BA2\u6237\u6570\u964D\u5E8F\uFF09\uFF0C\u7528\u4E8E\u6A2A\u5411\u5BF9\u6BD4").option("--start <date>", "\u5F00\u59CB\u65E5\u671F (YYYY-MM-DD)\uFF0C\u9ED8\u8BA4\u6628\u65E5").option("--end <date>", "\u7ED3\u675F\u65E5\u671F (YYYY-MM-DD)\uFF0C\u9ED8\u8BA4\u6628\u65E5\uFF0C\u4E0D\u80FD\u665A\u4E8E\u6628\u5929").option("--channel <channel>", "\u6E20\u9053\u7B5B\u9009: qianniu | jingdong | pinduoduo | douyin").action(async (opts) => {
1558
+ try {
1559
+ const data = await listShopStatistics({
1560
+ startDate: opts.start,
1561
+ endDate: opts.end,
1562
+ channel: opts.channel
1563
+ });
1564
+ formatOutput({ success: true, data }, program2.opts().table);
1565
+ } catch (err) {
1566
+ reportCaughtError(err);
1567
+ process.exit(toExitCode(err));
1568
+ }
1569
+ });
1570
+ dashboard.command("export").description(
1571
+ "\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"
1572
+ ).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", collect, []).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) => {
1573
+ try {
1574
+ const result = await exportShopData({
1575
+ startDate: opts.start,
1576
+ endDate: opts.end,
1577
+ configIds: opts.configId,
1578
+ channel: opts.channel
1579
+ });
1580
+ if (opts.out) {
1581
+ const { path: path5, bytes } = await writeBinaryToFile(
1582
+ opts.out,
1583
+ Buffer.from(result.csv, "utf-8")
1584
+ );
1585
+ formatOutput(
1586
+ { success: true, data: { path: path5, bytes, count: result.rows.length } },
1587
+ program2.opts().table
1588
+ );
1589
+ } else {
1590
+ formatOutput({ success: true, data: result.rows }, program2.opts().table);
1591
+ }
1592
+ } catch (err) {
1593
+ reportCaughtError(err);
1594
+ process.exit(toExitCode(err));
1595
+ }
1596
+ });
1597
+ dashboard.command("intent").description("\u5355\u5E97\u94FA\u5404\u610F\u56FE\uFF08\u4E00\u7EA7/\u4E8C\u7EA7\u6807\u7B7E\uFF09\u7684\u6D88\u606F\u7EA7\u8F6C\u4EBA\u5DE5\u7EDF\u8BA1\uFF0C\u9ED8\u8BA4\u6309\u8F6C\u4EBA\u5DE5\u6D88\u606F\u6570\u964D\u5E8F").requiredOption("--config-id <id>", "\u5E97\u94FA\u914D\u7F6E ID\uFF08\u5FC5\u586B\uFF09").option("--start <date>", "\u5F00\u59CB\u65E5\u671F (YYYY-MM-DD)\uFF0C\u9ED8\u8BA4\u6628\u65E5").option("--end <date>", "\u7ED3\u675F\u65E5\u671F (YYYY-MM-DD)\uFF0C\u9ED8\u8BA4\u6628\u65E5\uFF0C\u4E0D\u80FD\u665A\u4E8E\u6628\u5929").action(async (opts) => {
1598
+ try {
1599
+ const data = await getIntentStatistics({
1600
+ configId: opts.configId,
1601
+ startDate: opts.start,
1602
+ endDate: opts.end
1603
+ });
1604
+ formatOutput({ success: true, data }, program2.opts().table);
1605
+ } catch (err) {
1606
+ reportCaughtError(err);
1607
+ process.exit(toExitCode(err));
1608
+ }
1609
+ });
1610
+ dashboard.command("intent-conversations").description("\u67D0\u610F\u56FE\u4E0B\u7684\u4F1A\u8BDD\u5217\u8868\u4E0B\u94BB\uFF08\u542B\u8BE5\u610F\u56FE\u5728\u4F1A\u8BDD\u4E2D\u7684\u8F6C\u4EBA\u5DE5\u6B21\u6570\uFF09").requiredOption("--config-id <id>", "\u5E97\u94FA\u914D\u7F6E ID\uFF08\u5FC5\u586B\uFF09").requiredOption("--event-one <label>", "\u4E00\u7EA7\u610F\u56FE\uFF08\u5FC5\u586B\uFF09").requiredOption("--event-two <label>", "\u4E8C\u7EA7\u610F\u56FE\uFF08\u5FC5\u586B\uFF09").option("--start <date>", "\u5F00\u59CB\u65E5\u671F (YYYY-MM-DD)").option("--end <date>", "\u7ED3\u675F\u65E5\u671F (YYYY-MM-DD)").option("--page <number>", "\u9875\u7801", "1").option("--page-size <number>", "\u6BCF\u9875\u6570\u91CF\uFF08\u6700\u5927 100\uFF09", "20").action(async (opts) => {
1611
+ try {
1612
+ const data = await listIntentConversations({
1613
+ configId: opts.configId,
1614
+ eventOne: opts.eventOne,
1615
+ eventTwo: opts.eventTwo,
1616
+ startDate: opts.start,
1617
+ endDate: opts.end,
1618
+ page: Number(opts.page),
1619
+ pageSize: Number(opts.pageSize)
1620
+ });
1621
+ formatOutput({ success: true, data }, program2.opts().table);
1622
+ } catch (err) {
1623
+ reportCaughtError(err);
1624
+ process.exit(toExitCode(err));
1625
+ }
1626
+ });
1627
+ }
1628
+
1167
1629
  // src/client/debug-api.ts
1168
1630
  var DEFAULT_FLOW_WORKSPACE_ID = "531c14d1ece047cbaec22914e1f1364d";
1169
1631
  async function createDebugConversation(opts) {
@@ -1801,7 +2263,7 @@ async function batchReassignOwner(params) {
1801
2263
  }
1802
2264
 
1803
2265
  // src/utils/batch-input.ts
1804
- import fs5 from "fs";
2266
+ import fs6 from "fs";
1805
2267
  function parseIdsInput(opts) {
1806
2268
  const hasIds = opts.ids !== void 0 && opts.ids.trim() !== "";
1807
2269
  const hasFile = opts.idsFile !== void 0 && opts.idsFile.trim() !== "";
@@ -1818,7 +2280,7 @@ function parseIdsInput(opts) {
1818
2280
  const filePath = opts.idsFile;
1819
2281
  let content;
1820
2282
  try {
1821
- content = fs5.readFileSync(filePath, "utf8");
2283
+ content = fs6.readFileSync(filePath, "utf8");
1822
2284
  } catch (err) {
1823
2285
  const msg = err instanceof Error ? err.message : String(err);
1824
2286
  throw new Error(`\u8BFB\u53D6 --ids-file \u5931\u8D25: ${msg}`);
@@ -1840,7 +2302,7 @@ function parseIdsInput(opts) {
1840
2302
  }
1841
2303
 
1842
2304
  // src/utils/issue-batch-input.ts
1843
- import fs6 from "fs";
2305
+ import fs7 from "fs";
1844
2306
  var PRIORITY_VALUES = ["critical", "high", "medium", "low"];
1845
2307
  function readSource(opts) {
1846
2308
  const hasFile = typeof opts.file === "string" && opts.file.trim() !== "";
@@ -1853,7 +2315,7 @@ function readSource(opts) {
1853
2315
  }
1854
2316
  if (hasFile) {
1855
2317
  try {
1856
- return fs6.readFileSync(opts.file, "utf8");
2318
+ return fs7.readFileSync(opts.file, "utf8");
1857
2319
  } catch (err) {
1858
2320
  const msg = err instanceof Error ? err.message : String(err);
1859
2321
  throw new Error(`\u8BFB\u53D6 --file \u5931\u8D25: ${msg}`);
@@ -2485,7 +2947,7 @@ async function resolveSessionsForIssues(issues, workspaceId) {
2485
2947
  }
2486
2948
 
2487
2949
  // src/commands/knowledge.ts
2488
- import fs7 from "fs";
2950
+ import fs8 from "fs";
2489
2951
 
2490
2952
  // src/client/knowledge-api.ts
2491
2953
  async function listExternalKnowledge(opts) {
@@ -2591,7 +3053,7 @@ async function deleteKnowledgeContent(opts) {
2591
3053
  // src/commands/knowledge.ts
2592
3054
  function readContentArg(value) {
2593
3055
  if (value.startsWith("@")) {
2594
- return fs7.readFileSync(value.slice(1), "utf-8");
3056
+ return fs8.readFileSync(value.slice(1), "utf-8");
2595
3057
  }
2596
3058
  return value;
2597
3059
  }
@@ -3308,7 +3770,7 @@ function registerMonitorCommand(program2) {
3308
3770
  }
3309
3771
 
3310
3772
  // src/client/operations-record-api.ts
3311
- var PATH_PREFIX = "/v1/agent_operations_records";
3773
+ var PATH_PREFIX2 = "/v1/agent_operations_records";
3312
3774
  async function listOperationsRecords(opts) {
3313
3775
  const request = createRequest();
3314
3776
  const query = {};
@@ -3316,34 +3778,34 @@ async function listOperationsRecords(opts) {
3316
3778
  if (opts.agentId) query.agent_id = opts.agentId;
3317
3779
  if (opts.page) query.page = opts.page;
3318
3780
  if (opts.pageSize) query.page_size = opts.pageSize;
3319
- return request(getCustomerServiceUrl(), PATH_PREFIX, {
3781
+ return request(getCustomerServiceUrl(), PATH_PREFIX2, {
3320
3782
  method: "GET",
3321
3783
  query
3322
3784
  });
3323
3785
  }
3324
3786
  async function getOperationsRecord(recordId) {
3325
3787
  const request = createRequest();
3326
- return request(getCustomerServiceUrl(), `${PATH_PREFIX}/${recordId}`, {
3788
+ return request(getCustomerServiceUrl(), `${PATH_PREFIX2}/${recordId}`, {
3327
3789
  method: "GET"
3328
3790
  });
3329
3791
  }
3330
3792
  async function createOperationsRecord(data) {
3331
3793
  const request = createRequest();
3332
- return request(getCustomerServiceUrl(), PATH_PREFIX, {
3794
+ return request(getCustomerServiceUrl(), PATH_PREFIX2, {
3333
3795
  method: "POST",
3334
3796
  body: data
3335
3797
  });
3336
3798
  }
3337
3799
  async function updateOperationsRecord(recordId, data) {
3338
3800
  const request = createRequest();
3339
- return request(getCustomerServiceUrl(), `${PATH_PREFIX}/${recordId}`, {
3801
+ return request(getCustomerServiceUrl(), `${PATH_PREFIX2}/${recordId}`, {
3340
3802
  method: "PUT",
3341
3803
  body: data
3342
3804
  });
3343
3805
  }
3344
3806
  async function deleteOperationsRecord(recordId) {
3345
3807
  const request = createRequest();
3346
- return request(getCustomerServiceUrl(), `${PATH_PREFIX}/${recordId}`, {
3808
+ return request(getCustomerServiceUrl(), `${PATH_PREFIX2}/${recordId}`, {
3347
3809
  method: "DELETE"
3348
3810
  });
3349
3811
  }
@@ -3711,7 +4173,7 @@ function registerProductCommand(program2) {
3711
4173
  }
3712
4174
 
3713
4175
  // src/client/repair-record-api.ts
3714
- var PATH_PREFIX2 = "/api/repair-records";
4176
+ var PATH_PREFIX3 = "/api/repair-records";
3715
4177
  async function listRepairRecords(opts) {
3716
4178
  const request = createRequest();
3717
4179
  const query = {};
@@ -3720,29 +4182,23 @@ async function listRepairRecords(opts) {
3720
4182
  if (opts.workspaceId) query.workspace_id = opts.workspaceId;
3721
4183
  if (opts.page) query.page = opts.page;
3722
4184
  if (opts.pageSize) query.page_size = opts.pageSize;
3723
- return request(getCustomerAgentUrl(), PATH_PREFIX2, {
4185
+ return request(getCsAdminUrl(), PATH_PREFIX3, {
3724
4186
  method: "GET",
3725
- query,
3726
- headers: buildCookieHeaders(),
3727
- skipAuth: true
4187
+ query
3728
4188
  });
3729
4189
  }
3730
4190
  async function createRepairRecord(data) {
3731
4191
  const request = createRequest();
3732
- return request(getCustomerAgentUrl(), PATH_PREFIX2, {
4192
+ return request(getCsAdminUrl(), PATH_PREFIX3, {
3733
4193
  method: "POST",
3734
- body: data,
3735
- headers: buildCookieHeaders(),
3736
- skipAuth: true
4194
+ body: data
3737
4195
  });
3738
4196
  }
3739
4197
  async function updateRepairRecord(recordId, data) {
3740
4198
  const request = createRequest();
3741
- return request(getCustomerAgentUrl(), `${PATH_PREFIX2}/${recordId}`, {
4199
+ return request(getCsAdminUrl(), `${PATH_PREFIX3}/${recordId}`, {
3742
4200
  method: "PUT",
3743
- body: data,
3744
- headers: buildCookieHeaders(),
3745
- skipAuth: true
4201
+ body: data
3746
4202
  });
3747
4203
  }
3748
4204
 
@@ -4014,21 +4470,6 @@ function registerSACommand(program2) {
4014
4470
  // src/commands/testset.ts
4015
4471
  import fs9 from "fs";
4016
4472
 
4017
- // src/utils/file-output.ts
4018
- import fs8 from "fs";
4019
- import path4 from "path";
4020
- async function writeBinaryToFile(filePath, buffer) {
4021
- try {
4022
- const dir = path4.dirname(filePath);
4023
- fs8.mkdirSync(dir, { recursive: true });
4024
- fs8.writeFileSync(filePath, buffer);
4025
- } catch (err) {
4026
- const msg = err instanceof Error ? err.message : String(err);
4027
- throw new APIError(1, `\u6587\u4EF6\u5199\u5165\u5931\u8D25: ${msg}`);
4028
- }
4029
- return { path: filePath, bytes: buffer.length };
4030
- }
4031
-
4032
4473
  // src/client/testset-api.ts
4033
4474
  function unwrapPaginated(raw, fallbackPageSize) {
4034
4475
  return {
@@ -4698,7 +5139,7 @@ var require2 = createRequire(import.meta.url);
4698
5139
  var { version } = require2("../package.json");
4699
5140
  var program = new Command();
4700
5141
  program.name("cs-cli").description(
4701
- "BetterYeah AI \u5BA2\u670D\u5E73\u53F0 CLI\u3002\u6838\u5FC3\u6982\u5FF5\uFF1Aworkspace\uFF08\u5DE5\u4F5C\u7A7A\u95F4\uFF09\u2192 agent\uFF08AI \u5BA2\u670D\u673A\u5668\u4EBA\uFF09\u2192 SA/product/FAQ\uFF08\u77E5\u8BC6\u914D\u7F6E\uFF09\u2192 issue\uFF08\u5DE5\u5355\uFF09\u2192 debug\uFF08\u8C03\u8BD5\u9A8C\u8BC1\uFF09\u2192 monitor\uFF08\u8FD0\u8425\u76D1\u63A7\uFF09\u2192 repair-record\uFF08\u4FEE\u590D\u5BA1\u8BA1\uFF09\u2192 change-consumer\uFF08\u5546\u54C1\u53D8\u66F4\u4E8B\u4EF6\u6D88\u8D39\uFF09\u3002\u6240\u6709\u547D\u4EE4\u9ED8\u8BA4\u8F93\u51FA JSON\uFF0C\u8FFD\u52A0 --table \u53EF\u5207\u6362\u4E3A\u4EBA\u7C7B\u53EF\u8BFB\u8868\u683C"
5142
+ "BetterYeah AI \u5BA2\u670D\u5E73\u53F0 CLI\u3002\u6838\u5FC3\u6982\u5FF5\uFF1Aworkspace\uFF08\u5DE5\u4F5C\u7A7A\u95F4\uFF09\u2192 agent\uFF08AI \u5BA2\u670D\u673A\u5668\u4EBA\uFF09\u2192 SA/product/FAQ\uFF08\u77E5\u8BC6\u914D\u7F6E\uFF09\u2192 issue\uFF08\u5DE5\u5355\uFF09\u2192 debug\uFF08\u8C03\u8BD5\u9A8C\u8BC1\uFF09\u2192 monitor\uFF08\u8FD0\u8425\u76D1\u63A7\uFF09\u2192 dashboard\uFF08\u6570\u636E\u770B\u677F\uFF09\u2192 repair-record\uFF08\u4FEE\u590D\u5BA1\u8BA1\uFF09\u2192 change-consumer\uFF08\u5546\u54C1\u53D8\u66F4\u4E8B\u4EF6\u6D88\u8D39\uFF09\u3002\u6240\u6709\u547D\u4EE4\u9ED8\u8BA4\u8F93\u51FA JSON\uFF0C\u8FFD\u52A0 --table \u53EF\u5207\u6362\u4E3A\u4EBA\u7C7B\u53EF\u8BFB\u8868\u683C"
4702
5143
  ).version(version).option("--table", "\u4EE5\u8868\u683C\u5F62\u5F0F\u8F93\u51FA\uFF08\u9ED8\u8BA4 JSON\uFF09\u3002\u4EBA\u5DE5\u67E5\u770B\u65F6\u4F7F\u7528", false).option("--workspace <id>", "\u4E34\u65F6\u8986\u76D6\u9ED8\u8BA4\u5DE5\u4F5C\u7A7A\u95F4 ID\uFF0C\u4E0D\u4FEE\u6539\u6301\u4E45\u5316\u914D\u7F6E").option(
4703
5144
  "--request-timeout <ms>",
4704
5145
  "\u5355\u4E2A HTTP \u8BF7\u6C42\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09\uFF0C\u590D\u6742 Agent \u56DE\u590D\u5EFA\u8BAE\u8C03\u9AD8\u3002\u4E0D\u8981\u5199 --timeout\uFF0C\u90A3\u662F\u5B50\u547D\u4EE4\u7684\u8F6E\u8BE2\u7A97\u53E3\uFF08\u79D2\uFF09",
@@ -4727,12 +5168,14 @@ registerAgentCommand(program);
4727
5168
  registerSACommand(program);
4728
5169
  registerProductCommand(program);
4729
5170
  registerKnowledgeCommand(program);
5171
+ registerActivityCommand(program);
4730
5172
  registerIssueCommand(program);
4731
5173
  registerChatHistoryCommand(program);
4732
5174
  registerFaqCommand(program);
4733
5175
  registerConversationCommand(program);
4734
5176
  registerDebugCommand(program);
4735
5177
  registerMonitorCommand(program);
5178
+ registerDashboardCommand(program);
4736
5179
  registerRepairRecordCommand(program);
4737
5180
  registerOperationsRecordCommand(program);
4738
5181
  registerChangeConsumerCommand(program);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bty/customer-service-cli",
3
- "version": "0.5.0",
3
+ "version": "0.5.3",
4
4
  "description": "AI Customer Service CLI - Agent friendly",
5
5
  "type": "module",
6
6
  "main": "./dist/bin.js",