@bty/customer-service-cli 0.5.2 → 0.5.4

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,26 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.4 (2026-06-03)
4
+
5
+ - `ops-agent` 新增 `conversations` 子命令:`ops-agent conversations [--agent-id <id>] [--customer-id <id>] [--page N] [--page-size N]`,对接 `GET /v1/ops-agent/conversations`,按当前 workspace 查询客服助手会话列表,返回 `workspace_id`、`customer_id`、`title`、`agent_id`、`created_at`、`updated_at`。
6
+ - 补充 `ops-agent` 命令注册测试与 API 客户端测试,覆盖会话列表查询命令注册、请求路径、workspace 透传与筛选参数。
7
+ - `product` 新增 `identify-all` 子命令:`product identify-all --agent <id>`,对接 `POST /v1/knowledge/products/identify/all`,为当前 Agent 一键提交所有待增强商品进入增强学习队列。
8
+ - 补充 `product` CLI 测试与 API 客户端测试,覆盖增强学习命令注册、请求路径与请求体。
9
+ - `testset` 新增 `create` 子命令:`testset create --customer-agent-config-id <id> --file <cases.xlsx> [--name <text>] [--description <text>] [--use-type <text>]`,对接 `POST /v1/test_sets/file/upload`,通过 xlsx 模板上传创建测试集。
10
+
11
+ ## 0.5.3 (2026-05-28)
12
+
13
+ - 新增 `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):
14
+ - `activity list --agent <id> [--page N] [--page-size N] [--search <text>]`:列出活动(含 `total`、`v2_activity_enabled`、`items[]`)。
15
+ - `activity by-product --agent <id> --product-id <id>`:按 product_id 反查当前生效活动(仅 enabled,items[].products 恒为 [])。
16
+ - `activity create --data <json|@file>`:创建活动(完整 `IActivityWritePayload`,文件路径加 `@` 前缀走 JSON 解析)。
17
+ - `activity update <activity_id> --data <json|@file>`:整体更新活动(products 整组替换,非增量 diff;customer_agent_config_id 不可变更)。
18
+ - `activity set-enabled <activity_id> --enabled true|false`:列表行 toggle 用,PATCH `/enabled`,仅写 enabled 一个字段。
19
+ - `activity delete <activity_id>`:软删活动 + 级联软删 activity_product 关联。
20
+ - `activity v2-enabled --agent <id> --enabled true|false`:per-tenant 总开关,写 `agent_activity_setting.v2_activity_enabled`,控制 sop V2 链路是否生效。
21
+ - `activity_id` 路径参数本地校验为正整数;`--enabled` 仅接受 `true|false`,非法值直接报错优于让服务端 500。
22
+ - 业务失败统一服务端 200 + `code:400`,CLI 透传为 `exit 1` + `INVALID_PAYLOAD: …` 消息。
23
+
3
24
  ## 0.5.2 (2026-05-28)
4
25
 
5
26
  **修复:`repair-record` 命令 404 问题**
package/README.md CHANGED
@@ -224,6 +224,7 @@ cs-cli workspace points-consumes-daily --start 2026-04-01 --end 2026-04-23
224
224
  | `product update-sku --agent <id> (--sku <SKU名称> \| --sku-id <id>) --update <json\|@file>` | 更新 SKU 信息(`--sku-id` 优先于 `--sku`) |
225
225
  | `product add --agent <id> --data <json\|@file> [--source <type>] [--no-identify]` | 直接传入结构化商品数据(JSON 数组)异步学习(manual / identify 默认开启) |
226
226
  | `product learn --agent <id> --url <URL...> [--source <type>] [--no-identify]` | 通过商品 URL 异步学习(manual / identify 默认开启) |
227
+ | `product identify-all --agent <id>` | 一键增强学习当前 Agent 下所有待增强商品 |
227
228
  | `product sync-taobao --agent <id> [--skip-hash-check] [--sync-type <full\|incremental>]` | 触发淘宝店铺商品同步 |
228
229
  | `product sync-taobao-item --agent <id> --product-id <商品ID>` | 触发单个淘宝商品同步 |
229
230
 
@@ -233,6 +234,8 @@ cs-cli workspace points-consumes-daily --start 2026-04-01 --end 2026-04-23
233
234
 
234
235
  `product learn` 提交商品详情页 URL 进入异步学习队列(`/v1/knowledge/products/upload`),返回 `flow_id` 和 `knowledge_ids`。`--url` 可多值,用空格分隔;`--source` 默认 `manual`;传 `--no-identify` 可关闭自动识别。
235
236
 
237
+ `product identify-all` 对接 `POST /v1/knowledge/products/identify/all`,会为当前 Agent 一键提交所有“已可用但尚未增强”的商品进入增强学习队列。它不是全量重学;当没有待增强商品时,服务端会返回“暂无需要识图的商品”。
238
+
236
239
  `product sync-taobao` / `product sync-taobao-item` 调用 customer-servhub-api 的授权店铺同步接口,要求 `--agent` 已唯一绑定一个淘宝授权店铺。前者支持 `--sync-type full|incremental`,默认 `full`;后者按 `product_id` 补同步单个淘宝商品。
237
240
 
238
241
  注意:这两个命令仅对已开通“高级工具”的店铺 Agent 生效。未开通高级工具时,即使 `--agent` 已绑定淘宝授权店铺,请求也可能在服务端失败。
@@ -255,6 +258,47 @@ cs-cli product update-sku --agent <id> --sku-id 6072595054179 --update '{"补充
255
258
  ```
256
259
 
257
260
 
261
+ ### 活动管理 (`activity`)
262
+
263
+ 活动 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)。
264
+
265
+ | 命令 | 说明 |
266
+ | --- | --- |
267
+ | `activity list --agent <id> [--page N] [--page-size N] [--search <text>]` | 列出活动(返回 `total` / `v2_activity_enabled` / `items[]`) |
268
+ | `activity by-product --agent <id> --product-id <id>` | 按 `product_id` 反查当前生效活动(仅 enabled、product_scope='all' 必入) |
269
+ | `activity create --data <json\|@file>` | 创建活动(payload 见 `IActivityWritePayload`) |
270
+ | `activity update <activity_id> --data <json\|@file>` | 整体更新活动(products 整组替换,非增量) |
271
+ | `activity set-enabled <activity_id> --enabled <true\|false>` | 切换单条活动启用状态(仅写 enabled) |
272
+ | `activity delete <activity_id>` | 软删活动 + 级联软删关联 |
273
+ | `activity v2-enabled --agent <id> --enabled <true\|false>` | per-tenant 启停 V2 链路 |
274
+
275
+ - `--agent <id>` 对应服务端 `customer_agent_config_id`(与 `sa` / `product` 命令同口径)。
276
+ - `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`。
277
+ - 业务失败(参数非法 / 跨 workspace / 不存在)服务端返 HTTP 200 + `code:400`,CLI 转为 `exit 1` 并打印 `INVALID_PAYLOAD: …`。
278
+
279
+ ```bash
280
+ # 列出活动
281
+ cs-cli activity list --agent <cfg_id> --search 返现
282
+
283
+ # 按商品反查
284
+ cs-cli activity by-product --agent <cfg_id> --product-id 914494989518
285
+
286
+ # 创建活动(从文件读 payload)
287
+ cs-cli activity create --data @activity.json
288
+
289
+ # 整体更新
290
+ cs-cli activity update 6 --data @activity.json
291
+
292
+ # 列表行 toggle 启用
293
+ cs-cli activity set-enabled 6 --enabled false
294
+
295
+ # 软删活动
296
+ cs-cli activity delete 6
297
+
298
+ # 为某 agent 启用 V2 链路
299
+ cs-cli activity v2-enabled --agent <cfg_id> --enabled true
300
+ ```
301
+
258
302
  ### 工单管理 (`issue`)
259
303
 
260
304
 
@@ -537,6 +581,7 @@ cs-cli change-consumer delivery complete <delivery_id> --status completed \
537
581
  | 命令 | 说明 |
538
582
  | --- | --- |
539
583
  | `testset list --customer-agent-config-id <id>` | 列出测试集(分页,Agent ID 必填) |
584
+ | `testset create --customer-agent-config-id <id> --file <cases.xlsx> [--name ...] [--description ...] [--use-type ...]` | 通过 xlsx 模板上传创建测试集 |
540
585
  | `testset show <id>` | 测试集详情 |
541
586
  | `testset update <id> [--name ...] [--description ...] [--data @file.json]` | 更新测试集元数据(至少一项) |
542
587
  | `testset delete <id>` | 软删除测试集 |
@@ -786,3 +831,19 @@ cs-cli ops-record update <record_id> --data '{"remark":"已完成配置更新","
786
831
  # 删除运维操作记录
787
832
  cs-cli ops-record delete <record_id>
788
833
  ```
834
+
835
+ ### Ops Agent (`ops-agent`)
836
+
837
+ | 命令 | 说明 |
838
+ | --- | --- |
839
+ | `ops-agent conversations [--agent-id <id>] [--customer-id <id>] [--page N] [--page-size N]` | 查询客服助手会话列表 |
840
+
841
+ `ops-agent conversations` 对接 `customer-servhub-api /v1/ops-agent/conversations`,返回字段固定为 `workspace_id`、`customer_id`、`title`、`agent_id`、`created_at`、`updated_at`。命令会自动带当前 `workspace-id`;`--agent-id` 对应 Ops Agent 配置 ID(`customer_agent_config_id`),`--customer-id` 可选。
842
+
843
+ ```bash
844
+ # 查询当前 workspace 下某个客服运维助手的会话
845
+ cs-cli ops-agent conversations --agent-id <customer_agent_config_id>
846
+
847
+ # 按 customer 进一步过滤
848
+ cs-cli ops-agent conversations --agent-id <customer_agent_config_id> --customer-id <customer_id>
849
+ ```
package/dist/bin.js CHANGED
@@ -276,7 +276,7 @@ function toExitCode(err) {
276
276
  return 1;
277
277
  }
278
278
  function createRequest(globalTimeout) {
279
- return async function request(baseUrl, path5, options) {
279
+ return async function request(baseUrl, path6, options) {
280
280
  const headers = {
281
281
  "Content-Type": "application/json",
282
282
  ...options.headers
@@ -304,7 +304,7 @@ function createRequest(globalTimeout) {
304
304
  if (workspaceId) {
305
305
  headers["workspace-id"] = workspaceId;
306
306
  }
307
- let url = `${baseUrl}${path5}`;
307
+ let url = `${baseUrl}${path6}`;
308
308
  if (options.query) {
309
309
  const params = new URLSearchParams();
310
310
  for (const [key, value] of Object.entries(options.query)) {
@@ -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(
@@ -1168,22 +1343,22 @@ function registerConversationCommand(program2) {
1168
1343
  var DASHBOARD_PREFIX = "/v1/dashboard";
1169
1344
  async function getDashboardSummary(opts) {
1170
1345
  const request = createRequest();
1171
- const path5 = opts.configId ? `${DASHBOARD_PREFIX}/${opts.configId}/summary` : `${DASHBOARD_PREFIX}/summary`;
1346
+ const path6 = opts.configId ? `${DASHBOARD_PREFIX}/${opts.configId}/summary` : `${DASHBOARD_PREFIX}/summary`;
1172
1347
  const query = {};
1173
1348
  if (opts.startDate) query.start_date = opts.startDate;
1174
1349
  if (opts.endDate) query.end_date = opts.endDate;
1175
1350
  if (opts.channel) query.channel = opts.channel;
1176
- return request(getCustomerServiceUrl(), path5, { method: "GET", query });
1351
+ return request(getCustomerServiceUrl(), path6, { method: "GET", query });
1177
1352
  }
1178
1353
  async function getDashboardTrend(opts) {
1179
1354
  const request = createRequest();
1180
- const path5 = opts.configId ? `${DASHBOARD_PREFIX}/${opts.configId}/trend` : `${DASHBOARD_PREFIX}/trend`;
1355
+ const path6 = opts.configId ? `${DASHBOARD_PREFIX}/${opts.configId}/trend` : `${DASHBOARD_PREFIX}/trend`;
1181
1356
  const query = {};
1182
1357
  if (opts.startDate) query.start_date = opts.startDate;
1183
1358
  if (opts.endDate) query.end_date = opts.endDate;
1184
1359
  if (opts.granularity) query.granularity = opts.granularity;
1185
1360
  if (opts.channel) query.channel = opts.channel;
1186
- return request(getCustomerServiceUrl(), path5, { method: "GET", query });
1361
+ return request(getCustomerServiceUrl(), path6, { method: "GET", query });
1187
1362
  }
1188
1363
  async function listShopStatistics(opts) {
1189
1364
  const request = createRequest();
@@ -1403,12 +1578,12 @@ function registerDashboardCommand(program2) {
1403
1578
  channel: opts.channel
1404
1579
  });
1405
1580
  if (opts.out) {
1406
- const { path: path5, bytes } = await writeBinaryToFile(
1581
+ const { path: path6, bytes } = await writeBinaryToFile(
1407
1582
  opts.out,
1408
1583
  Buffer.from(result.csv, "utf-8")
1409
1584
  );
1410
1585
  formatOutput(
1411
- { success: true, data: { path: path5, bytes, count: result.rows.length } },
1586
+ { success: true, data: { path: path6, bytes, count: result.rows.length } },
1412
1587
  program2.opts().table
1413
1588
  );
1414
1589
  } else {
@@ -3594,8 +3769,46 @@ function registerMonitorCommand(program2) {
3594
3769
  });
3595
3770
  }
3596
3771
 
3772
+ // src/client/ops-agent-api.ts
3773
+ async function listOpsAgentConversations(opts) {
3774
+ const workspaceId = getWorkspaceId(opts.workspaceId);
3775
+ const request = createRequest();
3776
+ const query = {
3777
+ page: opts.page ?? 1,
3778
+ page_size: opts.pageSize ?? 20
3779
+ };
3780
+ if (opts.customerId) query.customer_id = opts.customerId;
3781
+ if (opts.agentId) query.agent_id = opts.agentId;
3782
+ return request(getCustomerServiceUrl(), "/v1/ops-agent/conversations", {
3783
+ method: "GET",
3784
+ query,
3785
+ headers: { "workspace-id": workspaceId }
3786
+ });
3787
+ }
3788
+
3789
+ // src/commands/ops-agent.ts
3790
+ function registerOpsAgentCommand(program2) {
3791
+ const opsAgent = program2.command("ops-agent").description("Ops Agent\uFF08\u5BA2\u670D\u52A9\u624B\uFF09\u67E5\u8BE2\u547D\u4EE4");
3792
+ opsAgent.command("conversations").description(
3793
+ "\u67E5\u8BE2\u5BA2\u670D\u52A9\u624B\u4F1A\u8BDD\u5217\u8868\u3002\u8FD4\u56DE workspace_id\u3001customer_id\u3001title\u3001agent_id\u3001created_at\u3001updated_at"
3794
+ ).option("--customer-id <id>", "\u6309 customer_id \u7B5B\u9009").option("--agent-id <id>", "\u6309 Ops Agent \u914D\u7F6E ID\uFF08customer_agent_config_id\uFF09\u7B5B\u9009").option("--page <number>", "\u9875\u7801", "1").option("--page-size <number>", "\u6BCF\u9875\u6570\u91CF", "20").action(async (opts) => {
3795
+ try {
3796
+ const data = await listOpsAgentConversations({
3797
+ customerId: opts.customerId,
3798
+ agentId: opts.agentId,
3799
+ page: Number(opts.page),
3800
+ pageSize: Number(opts.pageSize)
3801
+ });
3802
+ formatOutput({ success: true, data }, program2.opts().table);
3803
+ } catch (err) {
3804
+ reportCaughtError(err);
3805
+ process.exit(toExitCode(err));
3806
+ }
3807
+ });
3808
+ }
3809
+
3597
3810
  // src/client/operations-record-api.ts
3598
- var PATH_PREFIX = "/v1/agent_operations_records";
3811
+ var PATH_PREFIX2 = "/v1/agent_operations_records";
3599
3812
  async function listOperationsRecords(opts) {
3600
3813
  const request = createRequest();
3601
3814
  const query = {};
@@ -3603,34 +3816,34 @@ async function listOperationsRecords(opts) {
3603
3816
  if (opts.agentId) query.agent_id = opts.agentId;
3604
3817
  if (opts.page) query.page = opts.page;
3605
3818
  if (opts.pageSize) query.page_size = opts.pageSize;
3606
- return request(getCustomerServiceUrl(), PATH_PREFIX, {
3819
+ return request(getCustomerServiceUrl(), PATH_PREFIX2, {
3607
3820
  method: "GET",
3608
3821
  query
3609
3822
  });
3610
3823
  }
3611
3824
  async function getOperationsRecord(recordId) {
3612
3825
  const request = createRequest();
3613
- return request(getCustomerServiceUrl(), `${PATH_PREFIX}/${recordId}`, {
3826
+ return request(getCustomerServiceUrl(), `${PATH_PREFIX2}/${recordId}`, {
3614
3827
  method: "GET"
3615
3828
  });
3616
3829
  }
3617
3830
  async function createOperationsRecord(data) {
3618
3831
  const request = createRequest();
3619
- return request(getCustomerServiceUrl(), PATH_PREFIX, {
3832
+ return request(getCustomerServiceUrl(), PATH_PREFIX2, {
3620
3833
  method: "POST",
3621
3834
  body: data
3622
3835
  });
3623
3836
  }
3624
3837
  async function updateOperationsRecord(recordId, data) {
3625
3838
  const request = createRequest();
3626
- return request(getCustomerServiceUrl(), `${PATH_PREFIX}/${recordId}`, {
3839
+ return request(getCustomerServiceUrl(), `${PATH_PREFIX2}/${recordId}`, {
3627
3840
  method: "PUT",
3628
3841
  body: data
3629
3842
  });
3630
3843
  }
3631
3844
  async function deleteOperationsRecord(recordId) {
3632
3845
  const request = createRequest();
3633
- return request(getCustomerServiceUrl(), `${PATH_PREFIX}/${recordId}`, {
3846
+ return request(getCustomerServiceUrl(), `${PATH_PREFIX2}/${recordId}`, {
3634
3847
  method: "DELETE"
3635
3848
  });
3636
3849
  }
@@ -3806,6 +4019,15 @@ async function syncSingleTaobaoProduct(opts) {
3806
4019
  }
3807
4020
  });
3808
4021
  }
4022
+ async function identifyAllProducts(opts) {
4023
+ const request = createRequest();
4024
+ return request(getCustomerServiceUrl(), "/v1/knowledge/products/identify/all", {
4025
+ method: "POST",
4026
+ body: {
4027
+ customer_agent_config_id: opts.agentConfigId
4028
+ }
4029
+ });
4030
+ }
3809
4031
 
3810
4032
  // src/commands/product.ts
3811
4033
  async function getDbId(agentConfigId) {
@@ -3943,6 +4165,19 @@ function registerProductCommand(program2) {
3943
4165
  process.exit(toExitCode(err));
3944
4166
  }
3945
4167
  });
4168
+ product.command("identify-all").description(
4169
+ "\u4E00\u952E\u589E\u5F3A\u5B66\u4E60\u5F53\u524D Agent \u4E0B\u6240\u6709\u5F85\u589E\u5F3A\u5546\u54C1\u3002\u5BF9\u63A5 POST /v1/knowledge/products/identify/all\uFF0C\u5F02\u6B65\u63D0\u4EA4\u5546\u54C1\u589E\u5F3A\u5B66\u4E60\u4EFB\u52A1"
4170
+ ).requiredOption("--agent <config_id>", "Agent \u914D\u7F6E ID\uFF08\u4ECE agent list \u83B7\u53D6\uFF09").action(async (opts) => {
4171
+ try {
4172
+ const data = await identifyAllProducts({
4173
+ agentConfigId: opts.agent
4174
+ });
4175
+ formatOutput({ success: true, data }, program2.opts().table);
4176
+ } catch (err) {
4177
+ reportCaughtError(err);
4178
+ process.exit(toExitCode(err));
4179
+ }
4180
+ });
3946
4181
  product.command("sync-taobao").description(
3947
4182
  "\u89E6\u53D1\u6DD8\u5B9D\u5E97\u94FA\u5546\u54C1\u540C\u6B65\u3002\u8C03\u7528 customer-servhub-api \u7684\u6388\u6743\u5E97\u94FA\u540C\u6B65\u63A5\u53E3\uFF0C\u6309 Agent \u914D\u7F6E\u627E\u5230\u552F\u4E00\u7ED1\u5B9A\u5E97\u94FA\u540E\u5F02\u6B65\u542F\u52A8\u540C\u6B65\u4EFB\u52A1"
3948
4183
  ).requiredOption("--agent <config_id>", "Agent \u914D\u7F6E ID\uFF08\u5FC5\u987B\u5DF2\u552F\u4E00\u7ED1\u5B9A\u4E00\u4E2A\u6DD8\u5B9D\u6388\u6743\u5E97\u94FA\uFF09").option("--skip-hash-check", "\u8DF3\u8FC7\u54C8\u5E0C\u6821\u9A8C\uFF0C\u5F3A\u5236\u91CD\u65B0\u540C\u6B65\u5546\u54C1").option("--sync-type <type>", "\u540C\u6B65\u7C7B\u578B\uFF1Afull / incremental\uFF0C\u9ED8\u8BA4 full", "full").action(async (opts) => {
@@ -3998,7 +4233,7 @@ function registerProductCommand(program2) {
3998
4233
  }
3999
4234
 
4000
4235
  // src/client/repair-record-api.ts
4001
- var PATH_PREFIX2 = "/api/repair-records";
4236
+ var PATH_PREFIX3 = "/api/repair-records";
4002
4237
  async function listRepairRecords(opts) {
4003
4238
  const request = createRequest();
4004
4239
  const query = {};
@@ -4007,21 +4242,21 @@ async function listRepairRecords(opts) {
4007
4242
  if (opts.workspaceId) query.workspace_id = opts.workspaceId;
4008
4243
  if (opts.page) query.page = opts.page;
4009
4244
  if (opts.pageSize) query.page_size = opts.pageSize;
4010
- return request(getCsAdminUrl(), PATH_PREFIX2, {
4245
+ return request(getCsAdminUrl(), PATH_PREFIX3, {
4011
4246
  method: "GET",
4012
4247
  query
4013
4248
  });
4014
4249
  }
4015
4250
  async function createRepairRecord(data) {
4016
4251
  const request = createRequest();
4017
- return request(getCsAdminUrl(), PATH_PREFIX2, {
4252
+ return request(getCsAdminUrl(), PATH_PREFIX3, {
4018
4253
  method: "POST",
4019
4254
  body: data
4020
4255
  });
4021
4256
  }
4022
4257
  async function updateRepairRecord(recordId, data) {
4023
4258
  const request = createRequest();
4024
- return request(getCsAdminUrl(), `${PATH_PREFIX2}/${recordId}`, {
4259
+ return request(getCsAdminUrl(), `${PATH_PREFIX3}/${recordId}`, {
4025
4260
  method: "PUT",
4026
4261
  body: data
4027
4262
  });
@@ -4292,10 +4527,132 @@ function registerSACommand(program2) {
4292
4527
  });
4293
4528
  }
4294
4529
 
4295
- // src/commands/testset.ts
4530
+ // src/commands/special-project.ts
4296
4531
  import fs9 from "fs";
4297
4532
 
4533
+ // src/client/special-project-api.ts
4534
+ async function createSpecialProject(input) {
4535
+ const request = createRequest();
4536
+ return request(getCsAdminUrl(), "/api/special-projects", {
4537
+ method: "POST",
4538
+ body: input
4539
+ });
4540
+ }
4541
+ async function listSpecialProjects(opts = {}) {
4542
+ const request = createRequest();
4543
+ const query = {};
4544
+ if (opts.ownerUserId !== void 0) query.ownerUserId = opts.ownerUserId;
4545
+ if (opts.status) query.status = opts.status;
4546
+ const result = await request(getCsAdminUrl(), "/api/special-projects", {
4547
+ method: "GET",
4548
+ query
4549
+ });
4550
+ return result.rows ?? [];
4551
+ }
4552
+ async function updateSpecialProject(projectId, patch) {
4553
+ const request = createRequest();
4554
+ return request(
4555
+ getCsAdminUrl(),
4556
+ `/api/special-projects/${projectId}`,
4557
+ { method: "PATCH", body: patch }
4558
+ );
4559
+ }
4560
+ async function closeSpecialProject(projectId) {
4561
+ return updateSpecialProject(projectId, { status: "\u5DF2\u5B8C\u6210" });
4562
+ }
4563
+ async function upsertSpecialProjects(items, apply) {
4564
+ const request = createRequest();
4565
+ return request(getCsAdminUrl(), "/api/special-projects/batch", {
4566
+ method: "POST",
4567
+ body: { items, apply }
4568
+ });
4569
+ }
4570
+
4571
+ // src/commands/special-project.ts
4572
+ function readJsonArg(value) {
4573
+ if (value.startsWith("@")) {
4574
+ return fs9.readFileSync(value.slice(1), "utf-8");
4575
+ }
4576
+ return value;
4577
+ }
4578
+ function registerSpecialProjectCommand(program2) {
4579
+ const sp = program2.command("special-project").description(
4580
+ "\u4E13\u9879\uFF08special_project\uFF09\u7BA1\u7406 \u2014\u2014 \u5DE5\u4F5C\u8D1F\u8F7D\u770B\u677F\u7684\u4E13\u9879\u6570\u636E\u3002\u4E3B\u529B\u5F55\u5165\u901A\u9053\uFF1A\u65E9\u4F1A\u9010\u5B57\u7A3F \u2192 Agent \u89E3\u6790 \u2192 upsert\uFF08\u5148\u770B diff\uFF0C\u786E\u8BA4\u540E --apply\uFF09"
4581
+ );
4582
+ sp.command("create").description("\u521B\u5EFA\u5355\u4E2A\u4E13\u9879").requiredOption("--name <name>", "\u4E13\u9879\u540D").requiredOption("--owner <id>", "\u627F\u63A5\u5DE5\u7A0B\u5E08 cs_admin_user_id").requiredOption("--daily-effort <personDays>", "\u9884\u4F30\u6BCF\u65E5\u6295\u5165\uFF08\u4EBA\u5929\uFF0C\u5982 0.5\uFF09").requiredOption("--start-date <YYYY-MM-DD>", "\u5F00\u59CB\u65E5\u671F").requiredOption("--duration-days <n>", "\u9884\u4F30\u6709\u6548\u6295\u5165\u5929\u6570").option("--workspace <id>", "\u5173\u8054\u5BA2\u6237 workspace_id\uFF08\u53EF\u7A7A\uFF0C\u5185\u90E8\u4E13\u9879\u4E0D\u586B\uFF09").option("--description <text>", "\u63CF\u8FF0").option("--source-ref <ref>", "\u7A33\u5B9A\u5916\u90E8\u952E\uFF08\u9010\u5B57\u7A3F\u6765\u6E90 id\uFF09\uFF0Cupsert \u5E42\u7B49\u7528").action(async (opts) => {
4583
+ try {
4584
+ const data = await createSpecialProject({
4585
+ name: opts.name,
4586
+ ownerUserId: Number(opts.owner),
4587
+ dailyEffort: Number(opts.dailyEffort),
4588
+ startDate: opts.startDate,
4589
+ durationDays: Number(opts.durationDays),
4590
+ workspaceId: opts.workspace,
4591
+ description: opts.description,
4592
+ sourceRef: opts.sourceRef
4593
+ });
4594
+ formatOutput({ success: true, data }, program2.opts().table);
4595
+ } catch (err) {
4596
+ reportCaughtError(err);
4597
+ process.exit(toExitCode(err));
4598
+ }
4599
+ });
4600
+ sp.command("list").description("\u5217\u51FA\u4E13\u9879").option("--owner <id>", "\u6309\u627F\u63A5\u5DE5\u7A0B\u5E08 cs_admin_user_id \u8FC7\u6EE4").option("--status <status>", "\u6309\u72B6\u6001\u8FC7\u6EE4\uFF08\u8FDB\u884C\u4E2D/\u6682\u505C/\u9700\u786E\u8BA4/\u5DF2\u5B8C\u6210\uFF09").action(async (opts) => {
4601
+ try {
4602
+ const data = await listSpecialProjects({
4603
+ ownerUserId: opts.owner !== void 0 ? Number(opts.owner) : void 0,
4604
+ status: opts.status
4605
+ });
4606
+ formatOutput({ success: true, data }, program2.opts().table);
4607
+ } catch (err) {
4608
+ reportCaughtError(err);
4609
+ process.exit(toExitCode(err));
4610
+ }
4611
+ });
4612
+ sp.command("update <id>").description("\u66F4\u65B0\u4E13\u9879\uFF08\u4EFB\u610F\u5B50\u96C6\uFF1B\u72B6\u6001\u8FC1\u79FB\u53D7\u670D\u52A1\u7AEF\u72B6\u6001\u673A\u7EA6\u675F\uFF09").option("--progress <n>", "\u8FDB\u5EA6 0-100").option("--status <status>", "\u72B6\u6001\uFF08\u8FDB\u884C\u4E2D/\u6682\u505C/\u9700\u786E\u8BA4/\u5DF2\u5B8C\u6210\uFF09").option("--daily-effort <personDays>", "\u6BCF\u65E5\u6295\u5165\uFF08\u4EBA\u5929\uFF09").option("--duration-days <n>", "\u6709\u6548\u6295\u5165\u5929\u6570").option("--description <text>", "\u63CF\u8FF0").action(async (id, opts) => {
4613
+ try {
4614
+ const patch = {};
4615
+ if (opts.progress !== void 0) patch.progress = Number(opts.progress);
4616
+ if (opts.status !== void 0) patch.status = opts.status;
4617
+ if (opts.dailyEffort !== void 0) patch.dailyEffort = Number(opts.dailyEffort);
4618
+ if (opts.durationDays !== void 0) patch.durationDays = Number(opts.durationDays);
4619
+ if (opts.description !== void 0) patch.description = opts.description;
4620
+ const data = await updateSpecialProject(Number(id), patch);
4621
+ formatOutput({ success: true, data }, program2.opts().table);
4622
+ } catch (err) {
4623
+ reportCaughtError(err);
4624
+ process.exit(toExitCode(err));
4625
+ }
4626
+ });
4627
+ sp.command("close <id>").description("\u5173\u95ED\u4E13\u9879\uFF08\u7F6E\u4E3A\u5DF2\u5B8C\u6210\uFF09").action(async (id) => {
4628
+ try {
4629
+ const data = await closeSpecialProject(Number(id));
4630
+ formatOutput({ success: true, data }, program2.opts().table);
4631
+ } catch (err) {
4632
+ reportCaughtError(err);
4633
+ process.exit(toExitCode(err));
4634
+ }
4635
+ });
4636
+ sp.command("upsert").description(
4637
+ "\u6279\u91CF upsert\uFF08\u9010\u5B57\u7A3F\u540C\u6B65\uFF09\u3002--items \u63A5 JSON \u6570\u7EC4\u6216 @\u6587\u4EF6\u3002\u9ED8\u8BA4\u53EA\u6253\u5370 diff \u4E0D\u5199\u5E93\uFF1B\u52A0 --apply \u624D\u843D\u5E93"
4638
+ ).requiredOption("--items <json|@file>", "items JSON \u6570\u7EC4\uFF0C\u6216 @path \u8BFB\u6587\u4EF6").option("--apply", "\u843D\u5E93\uFF08\u7F3A\u7701\u53EA\u7B97 diff \u4E0D\u5199\uFF09", false).action(async (opts) => {
4639
+ try {
4640
+ const items = JSON.parse(readJsonArg(opts.items));
4641
+ const data = await upsertSpecialProjects(items, opts.apply === true);
4642
+ formatOutput({ success: true, data }, program2.opts().table);
4643
+ } catch (err) {
4644
+ reportCaughtError(err);
4645
+ process.exit(toExitCode(err));
4646
+ }
4647
+ });
4648
+ }
4649
+
4650
+ // src/commands/testset.ts
4651
+ import fs11 from "fs";
4652
+
4298
4653
  // src/client/testset-api.ts
4654
+ import fs10 from "fs";
4655
+ import path5 from "path";
4299
4656
  function unwrapPaginated(raw, fallbackPageSize) {
4300
4657
  return {
4301
4658
  items: Array.isArray(raw?.data) ? raw?.data : [],
@@ -4321,6 +4678,28 @@ async function listTestSets(query) {
4321
4678
  );
4322
4679
  return unwrapPaginated(raw, query.pageSize ?? 20);
4323
4680
  }
4681
+ async function createTestSetFromFile(input) {
4682
+ const request = createRequest();
4683
+ const fileBytes = fs10.readFileSync(input.filePath);
4684
+ const formData = new FormData();
4685
+ formData.append(
4686
+ "file",
4687
+ new Blob([fileBytes], {
4688
+ type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
4689
+ }),
4690
+ path5.basename(input.filePath)
4691
+ );
4692
+ return request(getCustomerServiceUrl(), "/v1/test_sets/file/upload", {
4693
+ method: "POST",
4694
+ query: {
4695
+ customer_agent_config_id: input.customerAgentConfigId,
4696
+ test_set_name: input.testSetName,
4697
+ test_set_description: input.testSetDescription,
4698
+ use_type: input.useType
4699
+ },
4700
+ body: formData
4701
+ });
4702
+ }
4324
4703
  async function getTestSet(id) {
4325
4704
  const request = createRequest();
4326
4705
  return request(getCustomerServiceUrl(), `/v1/test_sets/${id}`, {
@@ -4805,7 +5184,7 @@ function readPromptInput(value) {
4805
5184
  if (!filePath) {
4806
5185
  throw new Error("File path cannot be empty after @");
4807
5186
  }
4808
- return fs9.readFileSync(filePath, "utf-8");
5187
+ return fs11.readFileSync(filePath, "utf-8");
4809
5188
  }
4810
5189
  return value;
4811
5190
  }
@@ -4838,6 +5217,25 @@ function registerTestsetCommand(program2) {
4838
5217
  process.exit(toExitCode(err));
4839
5218
  }
4840
5219
  });
5220
+ testset.command("create").description("\u901A\u8FC7 xlsx \u6587\u4EF6\u521B\u5EFA\u6D4B\u8BD5\u96C6").requiredOption("--customer-agent-config-id <id>", "Agent \u914D\u7F6E ID\uFF08\u5FC5\u586B\uFF0C\u4E0E\u540E\u7AEF\u5951\u7EA6\u5BF9\u9F50\uFF09").requiredOption("--file <path>", "\u6D4B\u8BD5\u96C6 xlsx \u6587\u4EF6\u8DEF\u5F84").option("--name <text>", "\u6D4B\u8BD5\u96C6\u540D\u79F0\uFF1B\u4E0D\u4F20\u5219\u540E\u7AEF\u53D6\u6587\u4EF6\u540D").option("--description <text>", "\u6D4B\u8BD5\u96C6\u63CF\u8FF0").option("--use-type <text>", "\u6587\u4EF6\u7528\u9014\u6807\u8BC6").action(async (opts) => {
5221
+ try {
5222
+ if (!fs11.existsSync(opts.file)) {
5223
+ outputError(1, `\u6587\u4EF6\u4E0D\u5B58\u5728: ${opts.file}`);
5224
+ process.exit(1);
5225
+ }
5226
+ const data = await createTestSetFromFile({
5227
+ customerAgentConfigId: opts.customerAgentConfigId,
5228
+ filePath: opts.file,
5229
+ testSetName: opts.name,
5230
+ testSetDescription: opts.description,
5231
+ useType: opts.useType
5232
+ });
5233
+ formatOutput({ success: true, data }, program2.opts().table);
5234
+ } catch (err) {
5235
+ reportCaughtError(err);
5236
+ process.exit(toExitCode(err));
5237
+ }
5238
+ });
4841
5239
  testset.command("show").description("\u67E5\u770B\u5355\u4E2A\u6D4B\u8BD5\u96C6\u8BE6\u60C5").argument("<id>", "\u6D4B\u8BD5\u96C6 ID").action(async (id) => {
4842
5240
  try {
4843
5241
  const data = await getTestSet(id);
@@ -4990,9 +5388,11 @@ registerAuthCommand(program);
4990
5388
  registerConfigCommand(program);
4991
5389
  registerWorkspaceCommand(program);
4992
5390
  registerAgentCommand(program);
5391
+ registerOpsAgentCommand(program);
4993
5392
  registerSACommand(program);
4994
5393
  registerProductCommand(program);
4995
5394
  registerKnowledgeCommand(program);
5395
+ registerActivityCommand(program);
4996
5396
  registerIssueCommand(program);
4997
5397
  registerChatHistoryCommand(program);
4998
5398
  registerFaqCommand(program);
@@ -5004,6 +5404,7 @@ registerRepairRecordCommand(program);
5004
5404
  registerOperationsRecordCommand(program);
5005
5405
  registerChangeConsumerCommand(program);
5006
5406
  registerTestsetCommand(program);
5407
+ registerSpecialProjectCommand(program);
5007
5408
  process.on("uncaughtException", (err) => {
5008
5409
  outputError(3, err.message);
5009
5410
  process.exit(3);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bty/customer-service-cli",
3
- "version": "0.5.2",
3
+ "version": "0.5.4",
4
4
  "description": "AI Customer Service CLI - Agent friendly",
5
5
  "type": "module",
6
6
  "main": "./dist/bin.js",