@bty/customer-service-cli 0.2.0 → 0.3.0

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.
Files changed (3) hide show
  1. package/README.md +25 -11
  2. package/dist/bin.js +21 -11
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -26,13 +26,14 @@ pnpm build
26
26
  安装后即可使用,无需额外配置 API 地址。内置默认地址:
27
27
 
28
28
 
29
- | 服务 | 默认地址 |
30
- | ------ | --------------------------------------------- |
31
- | 客服 API | `https://customer-servhub-api.betteryeah.com` |
32
- | 认证 API | `https://ai-api.betteryeah.com` |
33
- | AI API | `https://ai-api.betteryeah.com` |
34
- | Langfuse | `http://192.168.40.10:3000` |
29
+ | 服务 | 默认地址 |
30
+ | -------------- | --------------------------------------------- |
31
+ | 客服 API | `https://customer-servhub-api.betteryeah.com` |
32
+ | AI API | `https://ai-api.betteryeah.com` |
33
+ | Customer Agent | `https://customer-agent.bantouyan.com` |
34
+ | Langfuse | `http://192.168.40.10:3000` |
35
35
 
36
+ > AI API 同时服务于登录认证(`auth login` / `auth whoami`),不再区分独立的 "认证 API" 字段。
36
37
 
37
38
  如需覆盖,可通过 `cs-cli config set` 修改:
38
39
 
@@ -40,6 +41,16 @@ pnpm build
40
41
  cs-cli config set --cs-api https://your-api.example.com
41
42
  ```
42
43
 
44
+ ### API 地址优先级
45
+
46
+ 每个 API 地址的读取顺序为 `环境变量 > config.json > 内置默认值`。环境变量为 `undefined` 或空字符串 `""` 都视为未设置,继续向下 fallback。
47
+
48
+ | 环境变量 | 覆盖字段 | 默认值 |
49
+ | ----------------------- | ------------------- | --------------------------------------------- |
50
+ | `CS_CS_API_URL` | `customerServiceApiUrl` | `https://customer-servhub-api.betteryeah.com` |
51
+ | `CS_AI_API_URL` | `aiApiUrl`(同时服务 auth 调用) | `https://ai-api.betteryeah.com` |
52
+ | `CS_CUSTOMER_AGENT_URL` | `customerAgentApiUrl` | `https://customer-agent.bantouyan.com` |
53
+
43
54
  ## 快速开始
44
55
 
45
56
  ```bash
@@ -157,7 +168,7 @@ cs-cli --workspace ws-other agent list # ❌ 报错:CS_WORKSPACE_ID 已被
157
168
 
158
169
  | 命令 | 说明 |
159
170
  | ----------------------------------------------------------- | ---------------------------- |
160
- | `config set --cs-api <url> --auth-api <url> --ai-api <url>` | 设置 API 地址 |
171
+ | `config set --cs-api <url> --ai-api <url>` | 设置 API 地址 |
161
172
  | `config get` | 查看当前配置(含全局和本地) |
162
173
  | `config init` | 在当前目录初始化本地配置 (`.cs-cli.json`) |
163
174
  | `config set-workspace <workspace_id> [--global]` | 设置默认工作空间 |
@@ -199,7 +210,7 @@ cs-cli --workspace ws-other agent list # ❌ 报错:CS_WORKSPACE_ID 已被
199
210
  | `product list --agent <id> [--keyword <关键词>] [--status <状态>] [--tag <标签>]` | 列出商品 |
200
211
  | `product get --agent <id> --product-id <商品ID>` | 获取商品详情(自动获取 db_id) |
201
212
  | `product update --agent <id> --product-id <商品ID> --update <json\|@file>` | 更新商品信息 |
202
- | `product update-sku --agent <id> --sku <SKU名称> --update <json\|@file>` | 更新 SKU 信息 |
213
+ | `product update-sku --agent <id> (--sku <SKU名称> \| --sku-id <id>) --update <json\|@file>` | 更新 SKU 信息(`--sku-id` 优先于 `--sku`) |
203
214
  | `product learn --agent <id> --url <URL...> [--source <type>] [--no-identify]` | 通过商品 URL 异步学习(manual / identify 默认开启) |
204
215
 
205
216
  `product update` 支持更新的字段包括:`卖点`、`补充知识`、`tag`、`参数`、`轮播图识别结果`、`商品详情页识别结果` 等。`--update` 接受 JSON 字符串或 `@文件路径`。
@@ -216,8 +227,11 @@ cs-cli product update --agent <id> --product-id <商品ID> --update '{"tag":"[\"
216
227
  # 添加商品补充知识
217
228
  cs-cli product update --agent <id> --product-id <商品ID> --update '{"补充知识":"[{\"question\":\"问题\",\"answer\":\"回答\"}]"}'
218
229
 
219
- # 更新 SKU 补充知识
230
+ # 更新 SKU 补充知识(按 SKU 名称定位)
220
231
  cs-cli product update-sku --agent <id> --sku "颜色分类:粉红" --update '{"补充知识":"说明内容"}'
232
+
233
+ # 更新 SKU 补充知识(按 sku_id 定位,推荐)
234
+ cs-cli product update-sku --agent <id> --sku-id 6072595054179 --update '{"补充知识":"说明内容"}'
221
235
  ```
222
236
 
223
237
 
@@ -475,8 +489,8 @@ cs-cli product update --agent <id> --product-id 977691714398 --update '{"卖点"
475
489
  # 更新商品标签
476
490
  cs-cli product update --agent <id> --product-id 977691714398 --update '{"tag":"春季新品,热卖"}'
477
491
 
478
- # 更新 SKU 补充知识
479
- cs-cli product update-sku --agent <id> --sku "颜色分类:粉红" --update '{"补充知识":"粉红色为浅粉调"}'
492
+ # 更新 SKU 补充知识(按 sku_id 定位,推荐)
493
+ cs-cli product update-sku --agent <id> --sku-id 6072595054179 --update '{"补充知识":"粉红色为浅粉调"}'
480
494
 
481
495
  # 添加 FAQ
482
496
  cs-cli faq add --agent <id> --file "常见问题" --questions "怎么退款,如何退款" --answers "答案=请联系客服处理退款"
package/dist/bin.js CHANGED
@@ -428,25 +428,26 @@ function isTokenExpired(expiresAt) {
428
428
 
429
429
  // src/client/helpers.ts
430
430
  var DEFAULT_CS_API_URL = "https://customer-servhub-api.betteryeah.com";
431
- var DEFAULT_AUTH_API_URL = "https://ai-api.betteryeah.com";
432
431
  var DEFAULT_AI_API_URL = "https://ai-api.betteryeah.com";
433
432
  var DEFAULT_CUSTOMER_AGENT_API_URL = "https://customer-agent.bantouyan.com";
434
433
  var DEFAULT_LANGFUSE_HOST = "http://192.168.40.10:3000";
435
434
  var DEFAULT_LANGFUSE_PUBLIC_KEY = "pk-lf-1b3aece4-021a-4a81-be4a-abd6334c5929";
436
435
  var DEFAULT_LANGFUSE_SECRET_KEY = "sk-lf-edc22ac8-5d0a-4f72-b285-6556adfa8f71";
437
436
  function getCustomerServiceUrl() {
437
+ const envUrl = process.env.CS_CS_API_URL;
438
+ if (envUrl) return envUrl;
438
439
  const config = readConfig();
439
440
  return config?.customerServiceApiUrl ?? DEFAULT_CS_API_URL;
440
441
  }
441
- function getAuthUrl() {
442
- const config = readConfig();
443
- return config?.authApiUrl ?? DEFAULT_AUTH_API_URL;
444
- }
445
442
  function getAiApiUrl() {
443
+ const envUrl = process.env.CS_AI_API_URL;
444
+ if (envUrl) return envUrl;
446
445
  const config = readConfig();
447
446
  return config?.aiApiUrl ?? DEFAULT_AI_API_URL;
448
447
  }
449
448
  function getCustomerAgentUrl() {
449
+ const envUrl = process.env.CS_CUSTOMER_AGENT_URL;
450
+ if (envUrl) return envUrl;
450
451
  const config = readConfig();
451
452
  return config?.customerAgentApiUrl ?? DEFAULT_CUSTOMER_AGENT_API_URL;
452
453
  }
@@ -599,7 +600,7 @@ function encryptPassword(password) {
599
600
  return CryptoJS.enc.Base64.stringify(result);
600
601
  }
601
602
  async function login(phone, password) {
602
- const authApiUrl = getAuthUrl();
603
+ const authApiUrl = getAiApiUrl();
603
604
  const encryptedPassword = encryptPassword(password);
604
605
  const formData = new FormData();
605
606
  formData.append("phone", phone);
@@ -644,7 +645,7 @@ async function login(phone, password) {
644
645
  }
645
646
  async function whoami() {
646
647
  const request = createRequest();
647
- return request(getAuthUrl(), "/v1/users/me", { method: "GET" });
648
+ return request(getAiApiUrl(), "/v1/users/me", { method: "GET" });
648
649
  }
649
650
 
650
651
  // src/commands/auth.ts
@@ -731,10 +732,9 @@ function registerConfigCommand(program2) {
731
732
  const config = program2.command("config").description(
732
733
  "\u914D\u7F6E\u7BA1\u7406 \u2014\u2014 API \u5730\u5740\u3001\u9ED8\u8BA4\u5DE5\u4F5C\u7A7A\u95F4\u7B49\u6301\u4E45\u5316\u8BBE\u7F6E\u3002\u652F\u6301\u5168\u5C40\u914D\u7F6E\u548C\u76EE\u5F55\u7EA7\u672C\u5730\u914D\u7F6E\uFF08.cs-cli.json\uFF09"
733
734
  );
734
- config.command("set").description("\u8BBE\u7F6E API \u5730\u5740").option("--cs-api <url>", "\u5BA2\u670D API \u5730\u5740").option("--auth-api <url>", "\u8BA4\u8BC1 API \u5730\u5740").option("--ai-api <url>", "AI API \u5730\u5740").option("--agent-api <url>", "Customer Agent API \u5730\u5740").option("--langfuse-host <url>", "Langfuse \u5730\u5740").option("--langfuse-public-key <key>", "Langfuse Public Key").option("--langfuse-secret-key <key>", "Langfuse Secret Key").action((opts) => {
735
+ config.command("set").description("\u8BBE\u7F6E API \u5730\u5740").option("--cs-api <url>", "\u5BA2\u670D API \u5730\u5740").option("--ai-api <url>", "AI API \u5730\u5740").option("--agent-api <url>", "Customer Agent API \u5730\u5740").option("--langfuse-host <url>", "Langfuse \u5730\u5740").option("--langfuse-public-key <key>", "Langfuse Public Key").option("--langfuse-secret-key <key>", "Langfuse Secret Key").action((opts) => {
735
736
  const updates = {};
736
737
  if (opts.csApi) updates.customerServiceApiUrl = opts.csApi;
737
- if (opts.authApi) updates.authApiUrl = opts.authApi;
738
738
  if (opts.aiApi) updates.aiApiUrl = opts.aiApi;
739
739
  if (opts.agentApi) updates.customerAgentApiUrl = opts.agentApi;
740
740
  if (opts.langfuseHost) updates.langfuseHost = opts.langfuseHost;
@@ -2609,11 +2609,15 @@ async function uploadProductByUrl(opts) {
2609
2609
  });
2610
2610
  }
2611
2611
  async function updateSku(opts) {
2612
+ if (!opts.skuId && !opts.sku) {
2613
+ throw new Error("updateSku \u9700\u8981\u63D0\u4F9B sku \u6216 sku_id \u5176\u4E2D\u4E4B\u4E00");
2614
+ }
2615
+ const identifier = opts.skuId ? { sku_id: opts.skuId } : { sku: opts.sku };
2612
2616
  const request = createRequest();
2613
2617
  return request(getCustomerServiceUrl(), "/v1/knowledge/sku/update", {
2614
2618
  method: "POST",
2615
2619
  body: {
2616
- sku: opts.sku,
2620
+ ...identifier,
2617
2621
  customer_agent_config_id: opts.agentConfigId,
2618
2622
  update_dict: opts.updateDict
2619
2623
  }
@@ -2728,14 +2732,20 @@ function registerProductCommand(program2) {
2728
2732
  process.exit(toExitCode(err));
2729
2733
  }
2730
2734
  });
2731
- product.command("update-sku").description('\u66F4\u65B0\u6307\u5B9A SKU \u7684\u77E5\u8BC6\u4FE1\u606F\uFF08\u5982\u8865\u5145\u77E5\u8BC6\uFF09\u3002SKU \u540D\u79F0\u9700\u7CBE\u786E\u5339\u914D\uFF08\u5982 "\u989C\u8272\u5206\u7C7B:\u7C89\u7EA2"\uFF09').requiredOption("--agent <config_id>", "Agent \u914D\u7F6E ID\uFF08\u4ECE agent list \u83B7\u53D6\uFF09").requiredOption("--sku <name>", 'SKU \u540D\u79F0\uFF08\u7CBE\u786E\u5339\u914D\uFF0C\u5982 "\u989C\u8272\u5206\u7C7B:\u7C89\u7EA2"\uFF09').requiredOption(
2735
+ product.command("update-sku").description(
2736
+ "\u66F4\u65B0\u6307\u5B9A SKU \u7684\u77E5\u8BC6\u4FE1\u606F\uFF08\u5982\u8865\u5145\u77E5\u8BC6\uFF09\u3002\u652F\u6301\u901A\u8FC7 SKU \u540D\u79F0\u6216 sku_id \u5B9A\u4F4D\uFF0C\u540C\u65F6\u63D0\u4F9B\u65F6\u4F18\u5148\u4F7F\u7528 sku_id"
2737
+ ).requiredOption("--agent <config_id>", "Agent \u914D\u7F6E ID\uFF08\u4ECE agent list \u83B7\u53D6\uFF09").option("--sku <name>", 'SKU \u540D\u79F0\uFF08\u7CBE\u786E\u5339\u914D\uFF0C\u5982 "\u989C\u8272\u5206\u7C7B:\u7C89\u7EA2"\uFF09').option("--sku-id <id>", "SKU ID\uFF08\u5168\u5C40\u552F\u4E00\uFF0C\u4F18\u5148\u4E8E --sku\uFF09").requiredOption(
2732
2738
  "--update <json>",
2733
2739
  '\u66F4\u65B0\u5185\u5BB9 JSON \u6216 @\u6587\u4EF6\u8DEF\u5F84\u3002\u793A\u4F8B: {"\u8865\u5145\u77E5\u8BC6":"\u7C89\u7EA2\u8272\u4E3A\u6D45\u7C89\u8C03"}'
2734
2740
  ).action(async (opts) => {
2735
2741
  try {
2742
+ if (!opts.sku && !opts.skuId) {
2743
+ throw new Error("\u8BF7\u63D0\u4F9B --sku \u6216 --sku-id \u5176\u4E2D\u4E4B\u4E00");
2744
+ }
2736
2745
  const updateDict = parseDataOption(opts.update);
2737
2746
  const data = await updateSku({
2738
2747
  sku: opts.sku,
2748
+ skuId: opts.skuId,
2739
2749
  agentConfigId: opts.agent,
2740
2750
  updateDict
2741
2751
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bty/customer-service-cli",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "AI Customer Service CLI - Agent friendly",
5
5
  "type": "module",
6
6
  "main": "./dist/bin.js",