@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.
- package/README.md +25 -11
- package/dist/bin.js +21 -11
- 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
|
|
32
|
-
|
|
|
33
|
-
|
|
|
34
|
-
| Langfuse
|
|
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> --
|
|
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
|
|
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 =
|
|
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(
|
|
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("--
|
|
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
|
-
|
|
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(
|
|
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
|
});
|