@bty/customer-service-cli 0.5.2 → 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,18 @@
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
+
3
16
  ## 0.5.2 (2026-05-28)
4
17
 
5
18
  **修复:`repair-record` 命令 404 问题**
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
 
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(
@@ -3595,7 +3770,7 @@ function registerMonitorCommand(program2) {
3595
3770
  }
3596
3771
 
3597
3772
  // src/client/operations-record-api.ts
3598
- var PATH_PREFIX = "/v1/agent_operations_records";
3773
+ var PATH_PREFIX2 = "/v1/agent_operations_records";
3599
3774
  async function listOperationsRecords(opts) {
3600
3775
  const request = createRequest();
3601
3776
  const query = {};
@@ -3603,34 +3778,34 @@ async function listOperationsRecords(opts) {
3603
3778
  if (opts.agentId) query.agent_id = opts.agentId;
3604
3779
  if (opts.page) query.page = opts.page;
3605
3780
  if (opts.pageSize) query.page_size = opts.pageSize;
3606
- return request(getCustomerServiceUrl(), PATH_PREFIX, {
3781
+ return request(getCustomerServiceUrl(), PATH_PREFIX2, {
3607
3782
  method: "GET",
3608
3783
  query
3609
3784
  });
3610
3785
  }
3611
3786
  async function getOperationsRecord(recordId) {
3612
3787
  const request = createRequest();
3613
- return request(getCustomerServiceUrl(), `${PATH_PREFIX}/${recordId}`, {
3788
+ return request(getCustomerServiceUrl(), `${PATH_PREFIX2}/${recordId}`, {
3614
3789
  method: "GET"
3615
3790
  });
3616
3791
  }
3617
3792
  async function createOperationsRecord(data) {
3618
3793
  const request = createRequest();
3619
- return request(getCustomerServiceUrl(), PATH_PREFIX, {
3794
+ return request(getCustomerServiceUrl(), PATH_PREFIX2, {
3620
3795
  method: "POST",
3621
3796
  body: data
3622
3797
  });
3623
3798
  }
3624
3799
  async function updateOperationsRecord(recordId, data) {
3625
3800
  const request = createRequest();
3626
- return request(getCustomerServiceUrl(), `${PATH_PREFIX}/${recordId}`, {
3801
+ return request(getCustomerServiceUrl(), `${PATH_PREFIX2}/${recordId}`, {
3627
3802
  method: "PUT",
3628
3803
  body: data
3629
3804
  });
3630
3805
  }
3631
3806
  async function deleteOperationsRecord(recordId) {
3632
3807
  const request = createRequest();
3633
- return request(getCustomerServiceUrl(), `${PATH_PREFIX}/${recordId}`, {
3808
+ return request(getCustomerServiceUrl(), `${PATH_PREFIX2}/${recordId}`, {
3634
3809
  method: "DELETE"
3635
3810
  });
3636
3811
  }
@@ -3998,7 +4173,7 @@ function registerProductCommand(program2) {
3998
4173
  }
3999
4174
 
4000
4175
  // src/client/repair-record-api.ts
4001
- var PATH_PREFIX2 = "/api/repair-records";
4176
+ var PATH_PREFIX3 = "/api/repair-records";
4002
4177
  async function listRepairRecords(opts) {
4003
4178
  const request = createRequest();
4004
4179
  const query = {};
@@ -4007,21 +4182,21 @@ async function listRepairRecords(opts) {
4007
4182
  if (opts.workspaceId) query.workspace_id = opts.workspaceId;
4008
4183
  if (opts.page) query.page = opts.page;
4009
4184
  if (opts.pageSize) query.page_size = opts.pageSize;
4010
- return request(getCsAdminUrl(), PATH_PREFIX2, {
4185
+ return request(getCsAdminUrl(), PATH_PREFIX3, {
4011
4186
  method: "GET",
4012
4187
  query
4013
4188
  });
4014
4189
  }
4015
4190
  async function createRepairRecord(data) {
4016
4191
  const request = createRequest();
4017
- return request(getCsAdminUrl(), PATH_PREFIX2, {
4192
+ return request(getCsAdminUrl(), PATH_PREFIX3, {
4018
4193
  method: "POST",
4019
4194
  body: data
4020
4195
  });
4021
4196
  }
4022
4197
  async function updateRepairRecord(recordId, data) {
4023
4198
  const request = createRequest();
4024
- return request(getCsAdminUrl(), `${PATH_PREFIX2}/${recordId}`, {
4199
+ return request(getCsAdminUrl(), `${PATH_PREFIX3}/${recordId}`, {
4025
4200
  method: "PUT",
4026
4201
  body: data
4027
4202
  });
@@ -4993,6 +5168,7 @@ registerAgentCommand(program);
4993
5168
  registerSACommand(program);
4994
5169
  registerProductCommand(program);
4995
5170
  registerKnowledgeCommand(program);
5171
+ registerActivityCommand(program);
4996
5172
  registerIssueCommand(program);
4997
5173
  registerChatHistoryCommand(program);
4998
5174
  registerFaqCommand(program);
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.3",
4
4
  "description": "AI Customer Service CLI - Agent friendly",
5
5
  "type": "module",
6
6
  "main": "./dist/bin.js",