@bty/customer-service-cli 0.6.2 → 0.6.5
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 +14 -0
- package/README.md +17 -9
- package/dist/bin.js +527 -220
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.6.5 (2026-07-14)
|
|
4
|
+
|
|
5
|
+
- `debug ask` / `debug reproduce` 新增 `--mock <json|@file>`(工具结果 mock,形如 `[{ tool_name, result }]`)与 `--data-overlay <json|@file>`(本轮 `debug_data_overlay` 数据覆盖),发送时透传给 `/v1/debug/chat/agent_message`;`reproduce --dry-run` 输出中同步包含 mock 与 overlay。
|
|
6
|
+
- 新增 `debug data snapshot --agent <id> [--product-id <商品ID...>]`:把当前 Agent 的 SOP / 商品 / 活动等数据导出为 `debug_data_overlay` v1 JSON(写 stdout),配合 `--data-overlay @file` 复跑固定数据集;`--product-id` 可重复传多个只导指定商品,不传则分页导出全量商品。
|
|
7
|
+
|
|
8
|
+
## 0.6.4 (2026-07-04)
|
|
9
|
+
|
|
10
|
+
- `conversation transfer-human` 适配服务端 cursor 分页:移除 CLI 暴露的 `--page` 参数,CLI 自动沿 `next_cursor` 拉取全部结果并合并返回,避免深翻页请求压垮数据库。
|
|
11
|
+
- `transfer-human` 客户端保留 7 天查询窗口校验,并新增最多 500 个 cursor 页的保护,超出时提示缩小查询时间范围。
|
|
12
|
+
|
|
13
|
+
## 0.6.3 (2026-06-25)
|
|
14
|
+
|
|
15
|
+
- 修复 `product update` / `product update-sku` 在商品数超过 100 时,对位置靠后的商品报「未找到商品 product_id=xxx」的问题:`findProduct` 由只取第一页(`page:1, pageSize:100`)改为翻页查找,直到命中目标商品或翻完所有页。
|
|
16
|
+
|
|
3
17
|
## 0.6.2 (2026-06-15)
|
|
4
18
|
|
|
5
19
|
- `workspace` 新增 `points-consumes` 子命令:分页查询当前工作空间的积分账户消耗流水(`POST /v1/workspace/points_consumes`),支持 `--page` / `--page-size`,CLI 固定传 `debug: true`,返回中包含服务端 `extra` 调试字段。
|
package/README.md
CHANGED
|
@@ -457,7 +457,7 @@ Agent 关联的通用规则知识库(`suffix_type=_common`),与 FAQ / 商
|
|
|
457
457
|
| `conversation list [--agent <id>] [--equipment-id <设备ID>] [--user <用户名>] [--start <日期>] [--end <日期>]` | 搜索会话 |
|
|
458
458
|
| `conversation records <conversation_id> [--page-size N] [--direction prev|next]` | 获取会话聊天记录 |
|
|
459
459
|
| `conversation context-search --query <文本> [--start <时间>] [--end <时间>]` | 通过上下文内容模糊搜索对话记录(返回匹配消息详情,时间范围最多 3 天) |
|
|
460
|
-
| `conversation transfer-human --agent <customer_agent_config_id> --start <时间> --end
|
|
460
|
+
| `conversation transfer-human --agent <customer_agent_config_id> --start <时间> --end <时间>` | 查询转人工会话及对应转人工消息记录(时间范围最多 7 天,自动 cursor 翻页) |
|
|
461
461
|
|
|
462
462
|
|
|
463
463
|
### Agent 调试 (`debug`)
|
|
@@ -465,15 +465,26 @@ Agent 关联的通用规则知识库(`suffix_type=_common`),与 FAQ / 商
|
|
|
465
465
|
|
|
466
466
|
| 命令 | 说明 |
|
|
467
467
|
| ----------------------------------------------------------------------------------------------------------- | -------------------- |
|
|
468
|
-
| `debug ask --agent <id> --text <消息> [--user <用户名>] [--url <图片URL>] [--conversation <会话ID>] [--timeout <秒>]` | 向 Agent 发送消息并等待回复 |
|
|
469
|
-
| `debug reproduce <record_id> [--agent <id>] [--timeout <秒>] [--dry-run]` | 根据 record_id 复现 Agent 回复(自动获取上下文) |
|
|
468
|
+
| `debug ask --agent <id> (--text <消息> \| --messages <json\|@file>) [--user <用户名>] [--url <图片URL>] [--conversation <会话ID>] [--mock <json\|@file>] [--data-overlay <json\|@file>] [--timeout <秒>] [--poll-interval <毫秒>]` | 向 Agent 发送消息并等待回复 |
|
|
469
|
+
| `debug reproduce <record_id> [--agent <id>] [--mock <json\|@file>] [--data-overlay <json\|@file>] [--timeout <秒>] [--poll-interval <毫秒>] [--dry-run]` | 根据 record_id 复现 Agent 回复(自动获取上下文) |
|
|
470
|
+
| `debug data snapshot --agent <id> [--product-id <商品ID...>]` | 生成可传给 `--data-overlay @file` 的 debug 数据覆盖 JSON |
|
|
470
471
|
| `debug record <record_id>` | 获取记录的调试信息(flow_info),返回中包含 `trace_id` |
|
|
471
472
|
| `debug trace <trace_id> [--env <dev\|prod>]` | 根据 Langfuse Trace ID 获取完整 Trace 详情(经服务端代理,默认 `prod`) |
|
|
472
473
|
|
|
473
474
|
|
|
474
|
-
`debug ask` 会自动创建调试会话、发送消息、轮询等待 Agent 回复,默认最大等待 30
|
|
475
|
+
`debug ask` 会自动创建调试会话、发送消息、轮询等待 Agent 回复,默认最大等待 30 秒,默认轮询间隔 2000ms。`--text` 与 `--messages` 二选一:`--text` 发送单条消息,`--url` 只在 `--text` 模式下作为附图 URL;`--messages` 传入完整消息列表(JSON 或 @文件)重放多轮对话,既接受 JSON 数组,也接受 `conversation records` 原始 `{ "msg_list": [...] }` 对象。`--conversation` 可复用已有 debug 会话继续对话;`--mock` 可传工具结果 mock;`--data-overlay` 可传 `debug_data_overlay` JSON 或 @文件。
|
|
475
476
|
|
|
476
|
-
`debug reproduce` 根据一条回复记录自动复现 Agent 回复:通过 recordId 获取关联会话和 Agent 配置,拉取完整会话记录并截取目标 record 之前的上下文,使用原始用户名创建新 debug
|
|
477
|
+
`debug reproduce` 根据一条回复记录自动复现 Agent 回复:通过 recordId 获取关联会话和 Agent 配置,拉取完整会话记录并截取目标 record 之前的上下文,使用原始用户名创建新 debug 会话并发送。默认最大等待 60 秒,默认轮询间隔 2000ms。`--agent` 可指定另一个 Agent 复现同一段上下文(A/B 对比);`--mock` 和 `--data-overlay` 会在复现发送时透传;`--dry-run` 仅输出截断后的 `msg_list`、mock 和 overlay,不发送。
|
|
478
|
+
|
|
479
|
+
`debug data snapshot` 生成 `debug_data_overlay` v1 JSON,适合把当前 Agent 的 SOP / 商品 / 活动等数据固定成一次 debug 覆盖输入,再通过 `debug ask --data-overlay @file` 或 `debug reproduce --data-overlay @file` 复跑。`--agent <id>` 必填;`--product-id <商品ID...>` 可重复传多个商品 ID,只导出指定商品,不传则分页导出全量商品。命令输出写到 stdout,通常重定向到文件保存。
|
|
480
|
+
|
|
481
|
+
```bash
|
|
482
|
+
# 只导出指定商品相关 overlay
|
|
483
|
+
cs-cli debug data snapshot --agent <id> --product-id 586812046546 > overlay.json
|
|
484
|
+
|
|
485
|
+
# 使用 overlay 跑一次 ask
|
|
486
|
+
cs-cli debug ask --agent <id> --text "https://item.taobao.com/item.htm?id=586812046546 这个商品名称是啥" --data-overlay @overlay.json
|
|
487
|
+
```
|
|
477
488
|
|
|
478
489
|
`debug trace`(v0.4.0 起,**行为变更**)不再由 CLI 直连 Langfuse REST API,改为请求 customer-servhub-api 的 `GET /v1/debug/langfuse/trace/{trace_id}?env=<env>`,走 CLI 标准 Bearer 鉴权,由服务端按 env 选择 Langfuse 凭据并代理拉取 Trace。Trace ID 从 `debug record` 返回的 `trace_id` 字段获取。
|
|
479
490
|
|
|
@@ -842,12 +853,9 @@ cs-cli product add --agent <id> --data @products.json --source batch --no-identi
|
|
|
842
853
|
# 通过上下文内容模糊搜索对话记录(自动使用当前工作空间,查询窗口最多 3 天)
|
|
843
854
|
cs-cli conversation context-search --query "退款问题" --start 2026-03-22T00:00:00 --end 2026-03-22T23:59:59
|
|
844
855
|
|
|
845
|
-
# 查询转人工会话及对应转人工消息记录(按 MANUAL_TAKEOVER_REQUIRED 事件时间过滤,查询窗口最多 7
|
|
856
|
+
# 查询转人工会话及对应转人工消息记录(按 MANUAL_TAKEOVER_REQUIRED 事件时间过滤,查询窗口最多 7 天,自动 cursor 翻页)
|
|
846
857
|
cs-cli conversation transfer-human --agent <customer_agent_config_id> --start 2026-05-24T00:00:00 --end 2026-05-24T23:59:59
|
|
847
858
|
|
|
848
|
-
# 查询第 2 页转人工会话
|
|
849
|
-
cs-cli conversation transfer-human --agent <customer_agent_config_id> --start 2026-05-24T00:00:00 --end 2026-05-24T23:59:59 --page 2
|
|
850
|
-
|
|
851
859
|
# 复现某条回复(自动获取上下文、原始用户名、Agent 配置)
|
|
852
860
|
cs-cli debug reproduce <record_id>
|
|
853
861
|
|
package/dist/bin.js
CHANGED
|
@@ -1224,6 +1224,7 @@ function registerConfigCommand(program2) {
|
|
|
1224
1224
|
// src/client/conversation-api.ts
|
|
1225
1225
|
var MAX_CONTEXT_SEARCH_RANGE_MS = 3 * 24 * 60 * 60 * 1e3;
|
|
1226
1226
|
var MAX_TRANSFER_HUMAN_RANGE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
1227
|
+
var MAX_TRANSFER_HUMAN_CURSOR_PAGES = 500;
|
|
1227
1228
|
function parseSearchTime(value, fieldName) {
|
|
1228
1229
|
const parsed = new Date(value);
|
|
1229
1230
|
if (Number.isNaN(parsed.getTime())) {
|
|
@@ -1296,15 +1297,36 @@ async function listConversations(opts) {
|
|
|
1296
1297
|
async function listTransferHumanConversations(opts) {
|
|
1297
1298
|
validateTransferHumanRange(opts.startDate, opts.endDate);
|
|
1298
1299
|
const request = createRequest();
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1300
|
+
const items = [];
|
|
1301
|
+
let cursor;
|
|
1302
|
+
let fetchedPages = 0;
|
|
1303
|
+
let pagination = {};
|
|
1304
|
+
while (fetchedPages < MAX_TRANSFER_HUMAN_CURSOR_PAGES) {
|
|
1305
|
+
fetchedPages += 1;
|
|
1306
|
+
const page = await request(
|
|
1307
|
+
getCustomerServiceUrl(),
|
|
1308
|
+
"/v1/chat/conversations/transfer-human",
|
|
1309
|
+
{
|
|
1310
|
+
method: "GET",
|
|
1311
|
+
query: {
|
|
1312
|
+
customer_agent_config_id: opts.customerAgentConfigId,
|
|
1313
|
+
start_date: opts.startDate,
|
|
1314
|
+
end_date: opts.endDate,
|
|
1315
|
+
page: 1,
|
|
1316
|
+
cursor
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
);
|
|
1320
|
+
items.push(...page.items ?? []);
|
|
1321
|
+
pagination = page.pagination ?? {};
|
|
1322
|
+
const hasMore = pagination.has_more === true;
|
|
1323
|
+
const nextCursor = typeof pagination.next_cursor === "string" && pagination.next_cursor ? pagination.next_cursor : void 0;
|
|
1324
|
+
if (!hasMore || !nextCursor) {
|
|
1325
|
+
return { ...page, items, pagination: { ...pagination, fetched_pages: fetchedPages } };
|
|
1326
|
+
}
|
|
1327
|
+
cursor = nextCursor;
|
|
1328
|
+
}
|
|
1329
|
+
throw new Error(`\u8F6C\u4EBA\u5DE5\u4F1A\u8BDD\u5206\u9875\u8D85\u8FC7 ${MAX_TRANSFER_HUMAN_CURSOR_PAGES} \u9875\uFF0C\u8BF7\u7F29\u5C0F\u67E5\u8BE2\u65F6\u95F4\u8303\u56F4`);
|
|
1308
1330
|
}
|
|
1309
1331
|
|
|
1310
1332
|
// src/commands/conversation.ts
|
|
@@ -1360,13 +1382,12 @@ function registerConversationCommand(program2) {
|
|
|
1360
1382
|
process.exit(toExitCode(err));
|
|
1361
1383
|
}
|
|
1362
1384
|
});
|
|
1363
|
-
conversation.command("transfer-human").description("\u67E5\u8BE2\u8F6C\u4EBA\u5DE5\u4F1A\u8BDD\u53CA\u5BF9\u5E94\u8F6C\u4EBA\u5DE5\u6D88\u606F\u8BB0\u5F55").requiredOption("--agent <config_id>", "Agent \u914D\u7F6E ID\uFF08customer_agent_config_id\uFF09").requiredOption("--start <date>", "\u5F00\u59CB\u65F6\u95F4\uFF08ISO \u683C\u5F0F\uFF0C\u5982 2026-05-20T00:00:00\uFF09").requiredOption("--end <date>", "\u7ED3\u675F\u65F6\u95F4\uFF08ISO \u683C\u5F0F\uFF0C\u5982 2026-05-20T23:59:59\uFF09").
|
|
1385
|
+
conversation.command("transfer-human").description("\u67E5\u8BE2\u8F6C\u4EBA\u5DE5\u4F1A\u8BDD\u53CA\u5BF9\u5E94\u8F6C\u4EBA\u5DE5\u6D88\u606F\u8BB0\u5F55").requiredOption("--agent <config_id>", "Agent \u914D\u7F6E ID\uFF08customer_agent_config_id\uFF09").requiredOption("--start <date>", "\u5F00\u59CB\u65F6\u95F4\uFF08ISO \u683C\u5F0F\uFF0C\u5982 2026-05-20T00:00:00\uFF09").requiredOption("--end <date>", "\u7ED3\u675F\u65F6\u95F4\uFF08ISO \u683C\u5F0F\uFF0C\u5982 2026-05-20T23:59:59\uFF09").action(async (opts) => {
|
|
1364
1386
|
try {
|
|
1365
1387
|
const data = await listTransferHumanConversations({
|
|
1366
1388
|
customerAgentConfigId: opts.agent,
|
|
1367
1389
|
startDate: opts.start,
|
|
1368
|
-
endDate: opts.end
|
|
1369
|
-
page: Number(opts.page)
|
|
1390
|
+
endDate: opts.end
|
|
1370
1391
|
});
|
|
1371
1392
|
formatOutput({ success: true, data }, program2.opts().table);
|
|
1372
1393
|
} catch (err) {
|
|
@@ -1722,16 +1743,23 @@ async function sendAgentMessage(opts) {
|
|
|
1722
1743
|
];
|
|
1723
1744
|
}
|
|
1724
1745
|
const request = createRequest();
|
|
1746
|
+
const body = {
|
|
1747
|
+
msg_list: msgList,
|
|
1748
|
+
is_stream: false,
|
|
1749
|
+
conversation_id: opts.conversationId
|
|
1750
|
+
};
|
|
1751
|
+
if (opts.mock !== void 0) {
|
|
1752
|
+
body.mock = opts.mock;
|
|
1753
|
+
}
|
|
1754
|
+
if (opts.debugDataOverlay !== void 0) {
|
|
1755
|
+
body.debug_data_overlay = opts.debugDataOverlay;
|
|
1756
|
+
}
|
|
1725
1757
|
return request(
|
|
1726
1758
|
getCustomerServiceUrl(),
|
|
1727
1759
|
"/v1/debug/chat/agent_message",
|
|
1728
1760
|
{
|
|
1729
1761
|
method: "POST",
|
|
1730
|
-
body
|
|
1731
|
-
msg_list: msgList,
|
|
1732
|
-
is_stream: false,
|
|
1733
|
-
conversation_id: opts.conversationId
|
|
1734
|
-
}
|
|
1762
|
+
body
|
|
1735
1763
|
}
|
|
1736
1764
|
);
|
|
1737
1765
|
}
|
|
@@ -1851,6 +1879,441 @@ async function getLangfuseTrace(traceId, env) {
|
|
|
1851
1879
|
);
|
|
1852
1880
|
}
|
|
1853
1881
|
|
|
1882
|
+
// src/client/product-api.ts
|
|
1883
|
+
async function listProducts(opts) {
|
|
1884
|
+
const request = createRequest();
|
|
1885
|
+
return request(getCustomerServiceUrl(), "/v1/knowledge/products", {
|
|
1886
|
+
method: "GET",
|
|
1887
|
+
query: {
|
|
1888
|
+
customer_agent_config_id: opts.agentConfigId,
|
|
1889
|
+
search: opts.keyword,
|
|
1890
|
+
status: opts.status?.join(","),
|
|
1891
|
+
tags: opts.tags?.length ? JSON.stringify(opts.tags) : void 0,
|
|
1892
|
+
page: opts.page ?? 1,
|
|
1893
|
+
page_size: opts.pageSize ?? 20
|
|
1894
|
+
}
|
|
1895
|
+
});
|
|
1896
|
+
}
|
|
1897
|
+
async function getProductDetail(opts) {
|
|
1898
|
+
const request = createRequest();
|
|
1899
|
+
return request(getCustomerServiceUrl(), "/v1/knowledge/product/detail", {
|
|
1900
|
+
method: "GET",
|
|
1901
|
+
query: {
|
|
1902
|
+
customer_agent_config_id: opts.agentConfigId,
|
|
1903
|
+
db_id: opts.dbId,
|
|
1904
|
+
product_id: opts.productId
|
|
1905
|
+
}
|
|
1906
|
+
});
|
|
1907
|
+
}
|
|
1908
|
+
async function updateProduct(opts) {
|
|
1909
|
+
const request = createRequest();
|
|
1910
|
+
return request(getCustomerServiceUrl(), "/v1/knowledge/product/update", {
|
|
1911
|
+
method: "POST",
|
|
1912
|
+
body: {
|
|
1913
|
+
data_id: opts.dataId,
|
|
1914
|
+
knowledge_id: opts.knowledgeId,
|
|
1915
|
+
db_id: opts.dbId,
|
|
1916
|
+
update_dict: opts.updateDict
|
|
1917
|
+
}
|
|
1918
|
+
});
|
|
1919
|
+
}
|
|
1920
|
+
async function uploadProductByUrl(opts) {
|
|
1921
|
+
const request = createRequest();
|
|
1922
|
+
return request(getCustomerServiceUrl(), "/v1/knowledge/products/upload", {
|
|
1923
|
+
method: "POST",
|
|
1924
|
+
body: {
|
|
1925
|
+
customer_agent_config_id: opts.agentConfigId,
|
|
1926
|
+
source_type: opts.sourceType ?? "manual",
|
|
1927
|
+
identify: opts.identify ?? true,
|
|
1928
|
+
product_urls: opts.productUrls
|
|
1929
|
+
}
|
|
1930
|
+
});
|
|
1931
|
+
}
|
|
1932
|
+
async function uploadProductData(opts) {
|
|
1933
|
+
const request = createRequest();
|
|
1934
|
+
return request(getCustomerServiceUrl(), "/v1/knowledge/products/upload", {
|
|
1935
|
+
method: "POST",
|
|
1936
|
+
body: {
|
|
1937
|
+
customer_agent_config_id: opts.agentConfigId,
|
|
1938
|
+
source_type: opts.sourceType ?? "manual",
|
|
1939
|
+
identify: opts.identify ?? true,
|
|
1940
|
+
product_items: opts.productItems
|
|
1941
|
+
}
|
|
1942
|
+
});
|
|
1943
|
+
}
|
|
1944
|
+
async function updateSku(opts) {
|
|
1945
|
+
if (!opts.skuId && !opts.sku) {
|
|
1946
|
+
throw new Error("updateSku \u9700\u8981\u63D0\u4F9B sku \u6216 sku_id \u5176\u4E2D\u4E4B\u4E00");
|
|
1947
|
+
}
|
|
1948
|
+
const identifier = opts.skuId ? { sku_id: opts.skuId } : { sku: opts.sku };
|
|
1949
|
+
const request = createRequest();
|
|
1950
|
+
return request(getCustomerServiceUrl(), "/v1/knowledge/sku/update", {
|
|
1951
|
+
method: "POST",
|
|
1952
|
+
body: {
|
|
1953
|
+
...identifier,
|
|
1954
|
+
customer_agent_config_id: opts.agentConfigId,
|
|
1955
|
+
update_dict: opts.updateDict
|
|
1956
|
+
}
|
|
1957
|
+
});
|
|
1958
|
+
}
|
|
1959
|
+
async function syncTaobaoProducts(opts) {
|
|
1960
|
+
const request = createRequest();
|
|
1961
|
+
return request(getCustomerServiceUrl(), "/v1/authorized-shop/sync-taobao-products", {
|
|
1962
|
+
method: "POST",
|
|
1963
|
+
body: {
|
|
1964
|
+
customer_agent_config_id: opts.agentConfigId,
|
|
1965
|
+
skip_hash_check: opts.skipHashCheck ?? false,
|
|
1966
|
+
sync_type: opts.syncType ?? "full"
|
|
1967
|
+
}
|
|
1968
|
+
});
|
|
1969
|
+
}
|
|
1970
|
+
async function syncSingleTaobaoProduct(opts) {
|
|
1971
|
+
const request = createRequest();
|
|
1972
|
+
return request(getCustomerServiceUrl(), "/v1/authorized-shop/sync-single-product", {
|
|
1973
|
+
method: "POST",
|
|
1974
|
+
body: {
|
|
1975
|
+
customer_agent_config_id: opts.agentConfigId,
|
|
1976
|
+
product_id: opts.productId
|
|
1977
|
+
}
|
|
1978
|
+
});
|
|
1979
|
+
}
|
|
1980
|
+
async function identifyAllProducts(opts) {
|
|
1981
|
+
const request = createRequest();
|
|
1982
|
+
return request(getCustomerServiceUrl(), "/v1/knowledge/products/identify/all", {
|
|
1983
|
+
method: "POST",
|
|
1984
|
+
body: {
|
|
1985
|
+
customer_agent_config_id: opts.agentConfigId
|
|
1986
|
+
}
|
|
1987
|
+
});
|
|
1988
|
+
}
|
|
1989
|
+
|
|
1990
|
+
// src/client/sa-api.ts
|
|
1991
|
+
async function listSituationActions(opts) {
|
|
1992
|
+
const request = createRequest();
|
|
1993
|
+
return request(getCustomerServiceUrl(), "/v1/knowledge/situation-actions/list", {
|
|
1994
|
+
method: "GET",
|
|
1995
|
+
query: {
|
|
1996
|
+
customer_agent_config_id: opts.agentConfigId,
|
|
1997
|
+
sub_agent_intent: opts.subAgentIntent ?? "GENERAL_QA",
|
|
1998
|
+
event_first_label: opts.firstLabel ?? "",
|
|
1999
|
+
event_second_label: opts.secondLabel ?? "",
|
|
2000
|
+
page: opts.page ?? 1,
|
|
2001
|
+
page_size: opts.pageSize ?? 500
|
|
2002
|
+
}
|
|
2003
|
+
});
|
|
2004
|
+
}
|
|
2005
|
+
async function searchSituationActions(opts) {
|
|
2006
|
+
const request = createRequest();
|
|
2007
|
+
return request(getCustomerServiceUrl(), "/v1/knowledge/situation-actions/search", {
|
|
2008
|
+
method: "GET",
|
|
2009
|
+
query: { customer_agent_config_id: opts.agentConfigId, keyword: opts.keyword }
|
|
2010
|
+
});
|
|
2011
|
+
}
|
|
2012
|
+
async function createSituationAction(opts) {
|
|
2013
|
+
const request = createRequest();
|
|
2014
|
+
return request(getCustomerServiceUrl(), "/v1/knowledge/situation-actions/create", {
|
|
2015
|
+
method: "POST",
|
|
2016
|
+
body: {
|
|
2017
|
+
customer_agent_config_id: opts.agentConfigId,
|
|
2018
|
+
sub_agent_intent: opts.subAgentIntent ?? "GENERAL_QA",
|
|
2019
|
+
event_first_label: opts.firstLabel,
|
|
2020
|
+
event_second_label: opts.secondLabel,
|
|
2021
|
+
situation: opts.situation,
|
|
2022
|
+
action: opts.action,
|
|
2023
|
+
transfer_to_human: opts.transferToHuman ?? false
|
|
2024
|
+
}
|
|
2025
|
+
});
|
|
2026
|
+
}
|
|
2027
|
+
async function updateSituationAction(opts) {
|
|
2028
|
+
const request = createRequest();
|
|
2029
|
+
return request(getCustomerServiceUrl(), "/v1/knowledge/situation-actions/update", {
|
|
2030
|
+
method: "POST",
|
|
2031
|
+
body: {
|
|
2032
|
+
customer_agent_config_id: opts.agentConfigId,
|
|
2033
|
+
situation_action_id: opts.situationActionId,
|
|
2034
|
+
sub_agent_intent: opts.subAgentIntent ?? "GENERAL_QA",
|
|
2035
|
+
event_first_label: opts.firstLabel,
|
|
2036
|
+
event_second_label: opts.secondLabel,
|
|
2037
|
+
situation: opts.situation,
|
|
2038
|
+
action: opts.action,
|
|
2039
|
+
transfer_to_human: opts.transferToHuman ?? false
|
|
2040
|
+
}
|
|
2041
|
+
});
|
|
2042
|
+
}
|
|
2043
|
+
async function deleteSituationAction(opts) {
|
|
2044
|
+
const request = createRequest();
|
|
2045
|
+
return request(getCustomerServiceUrl(), "/v1/knowledge/situation-actions/delete", {
|
|
2046
|
+
method: "POST",
|
|
2047
|
+
body: {
|
|
2048
|
+
customer_agent_config_id: opts.agentConfigId,
|
|
2049
|
+
situation_action_id: opts.situationActionId,
|
|
2050
|
+
event_first_label: opts.firstLabel,
|
|
2051
|
+
event_second_label: opts.secondLabel
|
|
2052
|
+
}
|
|
2053
|
+
});
|
|
2054
|
+
}
|
|
2055
|
+
async function listSituationActionVersions(opts) {
|
|
2056
|
+
const request = createRequest();
|
|
2057
|
+
return request(
|
|
2058
|
+
getCustomerServiceUrl(),
|
|
2059
|
+
"/v1/knowledge/situation-actions/list/versions",
|
|
2060
|
+
{
|
|
2061
|
+
method: "GET",
|
|
2062
|
+
query: {
|
|
2063
|
+
customer_agent_config_id: opts.agentConfigId,
|
|
2064
|
+
situation_action_id: opts.situationActionId
|
|
2065
|
+
}
|
|
2066
|
+
}
|
|
2067
|
+
);
|
|
2068
|
+
}
|
|
2069
|
+
|
|
2070
|
+
// src/commands/debug-snapshot.ts
|
|
2071
|
+
var SA_PAGE_SIZE = 500;
|
|
2072
|
+
var ACTIVITY_PAGE_SIZE = 100;
|
|
2073
|
+
var PRODUCT_PAGE_SIZE = 100;
|
|
2074
|
+
var PRODUCT_DETAIL_CONCURRENCY = 4;
|
|
2075
|
+
var PERSONALIZATION_SLOTS = [
|
|
2076
|
+
"intent",
|
|
2077
|
+
"general_qa",
|
|
2078
|
+
"recommend",
|
|
2079
|
+
"takeover_rule",
|
|
2080
|
+
"image_rule",
|
|
2081
|
+
"custom_qa"
|
|
2082
|
+
];
|
|
2083
|
+
var ACTIVITY_FIELDS = [
|
|
2084
|
+
"activity_name",
|
|
2085
|
+
"activity_rule",
|
|
2086
|
+
"participate_condition",
|
|
2087
|
+
"benefit_content",
|
|
2088
|
+
"redeem_desc",
|
|
2089
|
+
"other_info",
|
|
2090
|
+
"qa"
|
|
2091
|
+
];
|
|
2092
|
+
var PRODUCT_FIELDS = [
|
|
2093
|
+
"\u5546\u54C1\u6807\u9898",
|
|
2094
|
+
"\u5546\u54C1\u54C1\u7C7B",
|
|
2095
|
+
"\u53C2\u6570",
|
|
2096
|
+
"\u5356\u70B9",
|
|
2097
|
+
"\u8865\u5145\u77E5\u8BC6",
|
|
2098
|
+
"\u8F6E\u64AD\u56FE\u8BC6\u522B\u7ED3\u679C",
|
|
2099
|
+
"\u5546\u54C1\u8BE6\u60C5\u9875\u8BC6\u522B\u7ED3\u679C",
|
|
2100
|
+
"\u5173\u8054\u77E5\u8BC6\u5E93\u547D\u4E2D"
|
|
2101
|
+
];
|
|
2102
|
+
var SKU_FIELDS = ["\u8865\u5145\u77E5\u8BC6", "sku\u56FE\u8BC6\u522B\u7ED3\u679C"];
|
|
2103
|
+
function asRecord(value) {
|
|
2104
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
|
|
2105
|
+
}
|
|
2106
|
+
function asArray(value) {
|
|
2107
|
+
return Array.isArray(value) ? value : [];
|
|
2108
|
+
}
|
|
2109
|
+
function toStringId(value) {
|
|
2110
|
+
if (typeof value === "string" && value.length > 0) return value;
|
|
2111
|
+
if (typeof value === "number" && Number.isFinite(value)) return String(value);
|
|
2112
|
+
return void 0;
|
|
2113
|
+
}
|
|
2114
|
+
function hasDefined(record, key) {
|
|
2115
|
+
return Object.prototype.hasOwnProperty.call(record, key) && record[key] !== void 0;
|
|
2116
|
+
}
|
|
2117
|
+
function readPageItems(result) {
|
|
2118
|
+
const record = asRecord(result);
|
|
2119
|
+
return {
|
|
2120
|
+
items: asArray(record.items).map(asRecord),
|
|
2121
|
+
total: typeof record.total === "number" ? record.total : void 0
|
|
2122
|
+
};
|
|
2123
|
+
}
|
|
2124
|
+
function isExhausted(fetchedCount, pageItemsCount, pageSize, total) {
|
|
2125
|
+
if (typeof total === "number") return fetchedCount >= total;
|
|
2126
|
+
return pageItemsCount < pageSize;
|
|
2127
|
+
}
|
|
2128
|
+
async function listAllSituationActions(agentConfigId) {
|
|
2129
|
+
const all = [];
|
|
2130
|
+
for (let page = 1; ; page += 1) {
|
|
2131
|
+
const result = await listSituationActions({
|
|
2132
|
+
agentConfigId,
|
|
2133
|
+
page,
|
|
2134
|
+
pageSize: SA_PAGE_SIZE
|
|
2135
|
+
});
|
|
2136
|
+
const { items, total } = readPageItems(result);
|
|
2137
|
+
all.push(...items);
|
|
2138
|
+
if (isExhausted(all.length, items.length, SA_PAGE_SIZE, total)) return all;
|
|
2139
|
+
}
|
|
2140
|
+
}
|
|
2141
|
+
async function listAllActivities(agentConfigId) {
|
|
2142
|
+
const all = [];
|
|
2143
|
+
for (let page = 1; ; page += 1) {
|
|
2144
|
+
const result = await listActivities({
|
|
2145
|
+
customerAgentConfigId: agentConfigId,
|
|
2146
|
+
page,
|
|
2147
|
+
pageSize: ACTIVITY_PAGE_SIZE
|
|
2148
|
+
});
|
|
2149
|
+
const { items, total } = readPageItems(result);
|
|
2150
|
+
all.push(...items);
|
|
2151
|
+
if (isExhausted(all.length, items.length, ACTIVITY_PAGE_SIZE, total)) return all;
|
|
2152
|
+
}
|
|
2153
|
+
}
|
|
2154
|
+
function readProductId(record) {
|
|
2155
|
+
const productInfo = asRecord(record["\u5546\u54C1\u4FE1\u606F"]);
|
|
2156
|
+
return toStringId(record.product_id) ?? toStringId(record["\u5546\u54C1id"]) ?? toStringId(productInfo["\u5546\u54C1id"]) ?? toStringId(record.id);
|
|
2157
|
+
}
|
|
2158
|
+
async function listAllProductIds(agentConfigId) {
|
|
2159
|
+
const productIds = [];
|
|
2160
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2161
|
+
let fetchedCount = 0;
|
|
2162
|
+
for (let page = 1; ; page += 1) {
|
|
2163
|
+
const result = await listProducts({
|
|
2164
|
+
agentConfigId,
|
|
2165
|
+
page,
|
|
2166
|
+
pageSize: PRODUCT_PAGE_SIZE
|
|
2167
|
+
});
|
|
2168
|
+
const { items, total } = readPageItems(result);
|
|
2169
|
+
fetchedCount += items.length;
|
|
2170
|
+
for (const item of items) {
|
|
2171
|
+
const productId = readProductId(item);
|
|
2172
|
+
if (productId && !seen.has(productId)) {
|
|
2173
|
+
seen.add(productId);
|
|
2174
|
+
productIds.push(productId);
|
|
2175
|
+
}
|
|
2176
|
+
}
|
|
2177
|
+
if (isExhausted(fetchedCount, items.length, PRODUCT_PAGE_SIZE, total)) return productIds;
|
|
2178
|
+
}
|
|
2179
|
+
}
|
|
2180
|
+
function buildPersonalization(agent) {
|
|
2181
|
+
const customerConfig = asRecord(agent.customer_config);
|
|
2182
|
+
const personalization = {};
|
|
2183
|
+
for (const slot of PERSONALIZATION_SLOTS) {
|
|
2184
|
+
const source = asRecord(customerConfig[slot]);
|
|
2185
|
+
if (hasDefined(source, "flow_instruction")) {
|
|
2186
|
+
personalization[slot] = { flow_instruction: source.flow_instruction };
|
|
2187
|
+
}
|
|
2188
|
+
}
|
|
2189
|
+
return personalization;
|
|
2190
|
+
}
|
|
2191
|
+
function buildSituationActions(items) {
|
|
2192
|
+
const groups = /* @__PURE__ */ new Map();
|
|
2193
|
+
for (const item of items) {
|
|
2194
|
+
const eventOne = toStringId(item.event_first_label) ?? "";
|
|
2195
|
+
const eventTwo = toStringId(item.event_second_label) ?? "";
|
|
2196
|
+
const key = `${eventOne}__${eventTwo}`;
|
|
2197
|
+
let group = groups.get(key);
|
|
2198
|
+
if (!group) {
|
|
2199
|
+
group = {
|
|
2200
|
+
sa_key: key,
|
|
2201
|
+
event_one: eventOne,
|
|
2202
|
+
event_two: eventTwo,
|
|
2203
|
+
items: []
|
|
2204
|
+
};
|
|
2205
|
+
groups.set(key, group);
|
|
2206
|
+
}
|
|
2207
|
+
const situation = toStringId(item.situation) ?? "";
|
|
2208
|
+
const patchItem = {
|
|
2209
|
+
match: { situation },
|
|
2210
|
+
situation,
|
|
2211
|
+
scene_summary: hasDefined(item, "scene_summary") ? item.scene_summary : situation
|
|
2212
|
+
};
|
|
2213
|
+
if (hasDefined(item, "action")) patchItem.action = item.action;
|
|
2214
|
+
if (hasDefined(item, "transfer_to_human")) {
|
|
2215
|
+
patchItem.transfer_to_human = item.transfer_to_human;
|
|
2216
|
+
}
|
|
2217
|
+
if (hasDefined(item, "react_loop_count")) {
|
|
2218
|
+
patchItem.react_loop_count = item.react_loop_count;
|
|
2219
|
+
}
|
|
2220
|
+
group.items.push(patchItem);
|
|
2221
|
+
}
|
|
2222
|
+
return [...groups.values()];
|
|
2223
|
+
}
|
|
2224
|
+
function buildActivities(items) {
|
|
2225
|
+
return items.flatMap((item) => {
|
|
2226
|
+
const activityId = toStringId(item.activity_id ?? item.id);
|
|
2227
|
+
if (!activityId) return [];
|
|
2228
|
+
const activity = { activity_id: activityId };
|
|
2229
|
+
for (const field of ACTIVITY_FIELDS) {
|
|
2230
|
+
if (hasDefined(item, field)) activity[field] = item[field];
|
|
2231
|
+
}
|
|
2232
|
+
return [activity];
|
|
2233
|
+
});
|
|
2234
|
+
}
|
|
2235
|
+
function buildSkuItems(detail) {
|
|
2236
|
+
const rawSkuItems = asArray(detail.skus).length > 0 ? asArray(detail.skus) : asArray(detail.sku);
|
|
2237
|
+
return rawSkuItems.flatMap((raw) => {
|
|
2238
|
+
const item = asRecord(raw);
|
|
2239
|
+
const sku = toStringId(item.sku ?? item.sku_id);
|
|
2240
|
+
if (!sku) return [];
|
|
2241
|
+
const skuPatch = {
|
|
2242
|
+
match: { sku },
|
|
2243
|
+
sku
|
|
2244
|
+
};
|
|
2245
|
+
for (const field of SKU_FIELDS) {
|
|
2246
|
+
if (hasDefined(item, field)) skuPatch[field] = item[field];
|
|
2247
|
+
}
|
|
2248
|
+
return [skuPatch];
|
|
2249
|
+
});
|
|
2250
|
+
}
|
|
2251
|
+
function readProductField(detail, productInfo, field) {
|
|
2252
|
+
if (hasDefined(detail, field)) return detail[field];
|
|
2253
|
+
if (hasDefined(productInfo, field)) return productInfo[field];
|
|
2254
|
+
return void 0;
|
|
2255
|
+
}
|
|
2256
|
+
function buildProductKnowledgeItem(detail, fallbackProductId) {
|
|
2257
|
+
const productInfo = asRecord(detail["\u5546\u54C1\u4FE1\u606F"]);
|
|
2258
|
+
const productId = readProductId(detail) ?? fallbackProductId;
|
|
2259
|
+
const product = { product_id: productId };
|
|
2260
|
+
for (const field of PRODUCT_FIELDS) {
|
|
2261
|
+
const value = readProductField(detail, productInfo, field);
|
|
2262
|
+
if (value !== void 0) product[field] = value;
|
|
2263
|
+
}
|
|
2264
|
+
product.sku = buildSkuItems(detail);
|
|
2265
|
+
return product;
|
|
2266
|
+
}
|
|
2267
|
+
async function fetchProductDetails(opts) {
|
|
2268
|
+
const details = [];
|
|
2269
|
+
for (let i = 0; i < opts.productIds.length; i += PRODUCT_DETAIL_CONCURRENCY) {
|
|
2270
|
+
const batch = opts.productIds.slice(i, i + PRODUCT_DETAIL_CONCURRENCY);
|
|
2271
|
+
const batchDetails = await Promise.all(
|
|
2272
|
+
batch.map(async (productId) => {
|
|
2273
|
+
const detail = await getProductDetail({
|
|
2274
|
+
agentConfigId: opts.agentConfigId,
|
|
2275
|
+
dbId: opts.dbId,
|
|
2276
|
+
productId
|
|
2277
|
+
});
|
|
2278
|
+
return buildProductKnowledgeItem(asRecord(detail), productId);
|
|
2279
|
+
})
|
|
2280
|
+
);
|
|
2281
|
+
details.push(...batchDetails);
|
|
2282
|
+
}
|
|
2283
|
+
return details;
|
|
2284
|
+
}
|
|
2285
|
+
async function buildDebugDataOverlaySnapshot(opts) {
|
|
2286
|
+
const agent = asRecord(await getAgent(opts.agentConfigId));
|
|
2287
|
+
const productIds = opts.productIds && opts.productIds.length > 0 ? [...new Set(opts.productIds)] : await listAllProductIds(opts.agentConfigId);
|
|
2288
|
+
const dbId = toStringId(agent.database_id);
|
|
2289
|
+
if (productIds.length > 0 && !dbId) {
|
|
2290
|
+
throw new Error("Agent \u8BE6\u60C5\u4E2D\u672A\u627E\u5230 database_id");
|
|
2291
|
+
}
|
|
2292
|
+
const [saItems, activityItems, productKnowledge] = await Promise.all([
|
|
2293
|
+
listAllSituationActions(opts.agentConfigId),
|
|
2294
|
+
listAllActivities(opts.agentConfigId),
|
|
2295
|
+
dbId ? fetchProductDetails({
|
|
2296
|
+
agentConfigId: opts.agentConfigId,
|
|
2297
|
+
dbId,
|
|
2298
|
+
productIds
|
|
2299
|
+
}) : Promise.resolve([])
|
|
2300
|
+
]);
|
|
2301
|
+
return {
|
|
2302
|
+
version: 1,
|
|
2303
|
+
servhub: {
|
|
2304
|
+
customer_config: buildPersonalization(agent),
|
|
2305
|
+
forbidden_words: asArray(agent.forbidden_words),
|
|
2306
|
+
platform_config: {}
|
|
2307
|
+
},
|
|
2308
|
+
sop: {
|
|
2309
|
+
node_templates: {},
|
|
2310
|
+
sa: buildSituationActions(saItems),
|
|
2311
|
+
activities: buildActivities(activityItems),
|
|
2312
|
+
product_knowledge: productKnowledge
|
|
2313
|
+
}
|
|
2314
|
+
};
|
|
2315
|
+
}
|
|
2316
|
+
|
|
1854
2317
|
// src/commands/debug.ts
|
|
1855
2318
|
function registerDebugCommand(program2) {
|
|
1856
2319
|
const debug = program2.command("debug").description(
|
|
@@ -1861,7 +2324,7 @@ function registerDebugCommand(program2) {
|
|
|
1861
2324
|
).requiredOption("--agent <config_id>", "Agent \u914D\u7F6E ID\uFF08\u4ECE agent list \u83B7\u53D6\uFF09").option("--text <message>", "\u53D1\u9001\u7684\u6D88\u606F\u5185\u5BB9\uFF08\u4E0E --messages \u4E92\u65A5\uFF0C\u4E8C\u9009\u4E00\uFF09").option(
|
|
1862
2325
|
"--messages <json>",
|
|
1863
2326
|
'\u5B8C\u6574\u6D88\u606F\u5217\u8868 JSON \u6216 @\u6587\u4EF6\u8DEF\u5F84\uFF0C\u7528\u4E8E\u91CD\u653E\u591A\u8F6E\u5BF9\u8BDD\uFF08\u4E0E --text \u4E92\u65A5\uFF09\u3002\u63A5\u53D7\u4E24\u79CD\u683C\u5F0F\uFF1A(1) JSON \u6570\u7EC4 [{ match_id, content: { text, image_url? }, timestamp, type: "TEXT", role: "user"|"assistant" }, ...] (2) \u542B msg_list \u5B57\u6BB5\u7684\u5BF9\u8C61 { msg_list: [...] }\uFF08conversation records \u7684\u539F\u59CB\u683C\u5F0F\u53EF\u76F4\u63A5\u4F7F\u7528\uFF09'
|
|
1864
|
-
).option("--user <name>", "\u6A21\u62DF\u7684\u7528\u6237\u540D\uFF08\u9ED8\u8BA4\u4F7F\u7528\u767B\u5F55\u7528\u6237\u540D\uFF09").option("--url <image_url>", "\u9644\u5E26\u7684\u56FE\u7247 URL\uFF08\u4EC5 --text \u6A21\u5F0F\u6709\u6548\uFF09").option("--conversation <id>", "\u590D\u7528\u5DF2\u6709\u4F1A\u8BDD ID\uFF0C\u7528\u4E8E\u5728\u540C\u4E00\u4E0A\u4E0B\u6587\u4E2D\u7EE7\u7EED\u5BF9\u8BDD").option("--timeout <seconds>", "\u6700\u5927\u7B49\u5F85\u56DE\u590D\u65F6\u95F4\uFF08\u79D2\uFF09\uFF0C\u590D\u6742 Agent \u5EFA\u8BAE\u8C03\u9AD8", "30").option("--poll-interval <ms>", "\u8F6E\u8BE2\u95F4\u9694\uFF08\u6BEB\u79D2\uFF09", "2000").action(async (opts) => {
|
|
2327
|
+
).option("--user <name>", "\u6A21\u62DF\u7684\u7528\u6237\u540D\uFF08\u9ED8\u8BA4\u4F7F\u7528\u767B\u5F55\u7528\u6237\u540D\uFF09").option("--url <image_url>", "\u9644\u5E26\u7684\u56FE\u7247 URL\uFF08\u4EC5 --text \u6A21\u5F0F\u6709\u6548\uFF09").option("--conversation <id>", "\u590D\u7528\u5DF2\u6709\u4F1A\u8BDD ID\uFF0C\u7528\u4E8E\u5728\u540C\u4E00\u4E0A\u4E0B\u6587\u4E2D\u7EE7\u7EED\u5BF9\u8BDD").option("--mock <json>", "\u5DE5\u5177\u7ED3\u679C mock JSON \u6216 @\u6587\u4EF6\u8DEF\u5F84\uFF0C\u5F62\u5982 [{ tool_name, result }]").option("--data-overlay <json>", "debug_data_overlay JSON \u6216 @\u6587\u4EF6\u8DEF\u5F84\uFF0C\u7528\u4E8E\u672C\u8F6E debug \u6570\u636E\u8986\u76D6").option("--timeout <seconds>", "\u6700\u5927\u7B49\u5F85\u56DE\u590D\u65F6\u95F4\uFF08\u79D2\uFF09\uFF0C\u590D\u6742 Agent \u5EFA\u8BAE\u8C03\u9AD8", "30").option("--poll-interval <ms>", "\u8F6E\u8BE2\u95F4\u9694\uFF08\u6BEB\u79D2\uFF09", "2000").action(async (opts) => {
|
|
1865
2328
|
try {
|
|
1866
2329
|
if (!opts.text && !opts.messages) {
|
|
1867
2330
|
outputError(1, "\u5FC5\u987B\u6307\u5B9A --text \u6216 --messages \u5176\u4E2D\u4E4B\u4E00");
|
|
@@ -1887,11 +2350,15 @@ function registerDebugCommand(program2) {
|
|
|
1887
2350
|
process.exit(1);
|
|
1888
2351
|
}
|
|
1889
2352
|
}
|
|
2353
|
+
const mock = opts.mock ? parseDataOption(opts.mock) : void 0;
|
|
2354
|
+
const debugDataOverlay = opts.dataOverlay ? parseDataOption(opts.dataOverlay) : void 0;
|
|
1890
2355
|
await sendAgentMessage({
|
|
1891
2356
|
conversationId,
|
|
1892
2357
|
text: opts.text,
|
|
1893
2358
|
imageUrl: opts.url,
|
|
1894
|
-
msgList
|
|
2359
|
+
msgList,
|
|
2360
|
+
mock,
|
|
2361
|
+
debugDataOverlay
|
|
1895
2362
|
});
|
|
1896
2363
|
const agentRecords = await pollAgentReply(conversationId, {
|
|
1897
2364
|
timeout: Number(opts.timeout) * 1e3,
|
|
@@ -1918,10 +2385,10 @@ function registerDebugCommand(program2) {
|
|
|
1918
2385
|
false
|
|
1919
2386
|
).option("--flow-workspace <id>", "flow \u6240\u5728 workspace ID\uFF08--deep \u65F6\u4F7F\u7528\uFF0C\u9ED8\u8BA4\u4F7F\u7528\u5185\u7F6E\u56FA\u5B9A\u503C\uFF09").action(async (recordId, opts) => {
|
|
1920
2387
|
try {
|
|
1921
|
-
const
|
|
2388
|
+
const data2 = await getRecordDebugInfo(recordId);
|
|
1922
2389
|
let deep;
|
|
1923
2390
|
if (opts.deep) {
|
|
1924
|
-
const flowInfo =
|
|
2391
|
+
const flowInfo = data2.flow_info;
|
|
1925
2392
|
const flowId = flowInfo?.flow_id;
|
|
1926
2393
|
const taskId = flowInfo?.task_id;
|
|
1927
2394
|
if (!flowId || !taskId) {
|
|
@@ -1939,7 +2406,7 @@ function registerDebugCommand(program2) {
|
|
|
1939
2406
|
}
|
|
1940
2407
|
}
|
|
1941
2408
|
formatOutput(
|
|
1942
|
-
{ success: true, data: opts.deep ? { ...
|
|
2409
|
+
{ success: true, data: opts.deep ? { ...data2, deep } : data2 },
|
|
1943
2410
|
program2.opts().table
|
|
1944
2411
|
);
|
|
1945
2412
|
} catch (err) {
|
|
@@ -1949,7 +2416,7 @@ function registerDebugCommand(program2) {
|
|
|
1949
2416
|
});
|
|
1950
2417
|
debug.command("reproduce").description(
|
|
1951
2418
|
"\u6839\u636E record_id \u590D\u73B0\u4E00\u6B21 Agent \u56DE\u590D\u3002\u81EA\u52A8\u83B7\u53D6\u5173\u8054\u4F1A\u8BDD\u3001\u622A\u53D6\u4E0A\u4E0B\u6587\u3001\u7528\u539F\u59CB user_name \u521B\u5EFA debug \u4F1A\u8BDD\u5E76\u91CD\u65B0\u53D1\u9001"
|
|
1952
|
-
).argument("<record_id>", "\u8981\u590D\u73B0\u7684\u56DE\u590D\u8BB0\u5F55 ID").option("--agent <config_id>", "\u4F7F\u7528\u6307\u5B9A Agent \u590D\u73B0\uFF08\u9ED8\u8BA4\u4F7F\u7528\u539F\u59CB Agent\uFF09").option("--timeout <seconds>", "\u6700\u5927\u7B49\u5F85\u56DE\u590D\u65F6\u95F4\uFF08\u79D2\uFF09", "60").option("--poll-interval <ms>", "\u8F6E\u8BE2\u95F4\u9694\uFF08\u6BEB\u79D2\uFF09", "2000").option("--dry-run", "\u4EC5\u8F93\u51FA\u622A\u65AD\u540E\u7684\u4E0A\u4E0B\u6587 msg_list\uFF0C\u4E0D\u53D1\u9001", false).action(async (recordId, opts) => {
|
|
2419
|
+
).argument("<record_id>", "\u8981\u590D\u73B0\u7684\u56DE\u590D\u8BB0\u5F55 ID").option("--agent <config_id>", "\u4F7F\u7528\u6307\u5B9A Agent \u590D\u73B0\uFF08\u9ED8\u8BA4\u4F7F\u7528\u539F\u59CB Agent\uFF09").option("--timeout <seconds>", "\u6700\u5927\u7B49\u5F85\u56DE\u590D\u65F6\u95F4\uFF08\u79D2\uFF09", "60").option("--poll-interval <ms>", "\u8F6E\u8BE2\u95F4\u9694\uFF08\u6BEB\u79D2\uFF09", "2000").option("--mock <json>", "\u5DE5\u5177\u7ED3\u679C mock JSON \u6216 @\u6587\u4EF6\u8DEF\u5F84\uFF0C\u5F62\u5982 [{ tool_name, result }]").option("--data-overlay <json>", "debug_data_overlay JSON \u6216 @\u6587\u4EF6\u8DEF\u5F84\uFF0C\u7528\u4E8E\u672C\u8F6E debug \u6570\u636E\u8986\u76D6").option("--dry-run", "\u4EC5\u8F93\u51FA\u622A\u65AD\u540E\u7684\u4E0A\u4E0B\u6587 msg_list\uFF0C\u4E0D\u53D1\u9001", false).action(async (recordId, opts) => {
|
|
1953
2420
|
try {
|
|
1954
2421
|
const relations = await getRecordRelations(recordId);
|
|
1955
2422
|
const { conversation, agent_config: agentConfig } = relations;
|
|
@@ -1963,6 +2430,8 @@ function registerDebugCommand(program2) {
|
|
|
1963
2430
|
});
|
|
1964
2431
|
const truncated = truncateBeforeRecord(records, recordId);
|
|
1965
2432
|
const msgList = recordsToMsgList(truncated);
|
|
2433
|
+
const mock = opts.mock ? parseDataOption(opts.mock) : void 0;
|
|
2434
|
+
const debugDataOverlay = opts.dataOverlay ? parseDataOption(opts.dataOverlay) : void 0;
|
|
1966
2435
|
if (opts.dryRun) {
|
|
1967
2436
|
formatOutput(
|
|
1968
2437
|
{
|
|
@@ -1973,7 +2442,9 @@ function registerDebugCommand(program2) {
|
|
|
1973
2442
|
agent_config_name: agentConfig.config_name,
|
|
1974
2443
|
user_name: userName,
|
|
1975
2444
|
context_messages_count: msgList.length,
|
|
1976
|
-
msg_list: msgList
|
|
2445
|
+
msg_list: msgList,
|
|
2446
|
+
mock,
|
|
2447
|
+
debug_data_overlay: debugDataOverlay
|
|
1977
2448
|
}
|
|
1978
2449
|
},
|
|
1979
2450
|
program2.opts().table
|
|
@@ -1986,7 +2457,9 @@ function registerDebugCommand(program2) {
|
|
|
1986
2457
|
});
|
|
1987
2458
|
await sendAgentMessage({
|
|
1988
2459
|
conversationId: conv.conversation_id,
|
|
1989
|
-
msgList
|
|
2460
|
+
msgList,
|
|
2461
|
+
mock,
|
|
2462
|
+
debugDataOverlay
|
|
1990
2463
|
});
|
|
1991
2464
|
const agentRecords = await pollAgentReply(conv.conversation_id, {
|
|
1992
2465
|
timeout: Number(opts.timeout) * 1e3,
|
|
@@ -2020,6 +2493,20 @@ function registerDebugCommand(program2) {
|
|
|
2020
2493
|
process.exit(toExitCode(err));
|
|
2021
2494
|
}
|
|
2022
2495
|
});
|
|
2496
|
+
const data = debug.command("data").description("debug \u6570\u636E\u5DE5\u5177");
|
|
2497
|
+
data.command("snapshot").description("\u751F\u6210\u53EF\u76F4\u63A5\u4F20\u7ED9 --data-overlay @file \u7684 debug_data_overlay v1 JSON").requiredOption("--agent <config_id>", "Agent \u914D\u7F6E ID\uFF08\u4ECE agent list \u83B7\u53D6\uFF09").option("--product-id <id...>", "\u53EA\u5BFC\u51FA\u6307\u5B9A\u5546\u54C1 ID\uFF1B\u4E0D\u4F20\u5219\u5206\u9875\u5BFC\u51FA\u5168\u91CF\u5546\u54C1").action(async (opts) => {
|
|
2498
|
+
try {
|
|
2499
|
+
const snapshot = await buildDebugDataOverlaySnapshot({
|
|
2500
|
+
agentConfigId: opts.agent,
|
|
2501
|
+
productIds: opts.productId
|
|
2502
|
+
});
|
|
2503
|
+
process.stdout.write(`${JSON.stringify(snapshot, null, 2)}
|
|
2504
|
+
`);
|
|
2505
|
+
} catch (err) {
|
|
2506
|
+
reportCaughtError(err);
|
|
2507
|
+
process.exit(toExitCode(err));
|
|
2508
|
+
}
|
|
2509
|
+
});
|
|
2023
2510
|
debug.command("trace").description(
|
|
2024
2511
|
"\u6839\u636E Langfuse Trace ID \u83B7\u53D6\u5B8C\u6574\u7684 Trace \u8BE6\u60C5\uFF08\u4ECE debug record \u8FD4\u56DE\u7684 flow_info \u4E2D\u63D0\u53D6 traceId\uFF09"
|
|
2025
2512
|
).argument("<trace_id>", "Langfuse Trace ID\uFF08\u4ECE flow_info \u4E2D\u83B7\u53D6\uFF09").option("--env <env>", "langfuse \u73AF\u5883 dev|prod", "prod").action(async (traceId, opts) => {
|
|
@@ -2028,8 +2515,8 @@ function registerDebugCommand(program2) {
|
|
|
2028
2515
|
outputError(1, "--env \u4EC5\u652F\u6301 dev \u6216 prod");
|
|
2029
2516
|
process.exit(1);
|
|
2030
2517
|
}
|
|
2031
|
-
const
|
|
2032
|
-
formatOutput({ success: true, data }, program2.opts().table);
|
|
2518
|
+
const data2 = await getLangfuseTrace(traceId, opts.env);
|
|
2519
|
+
formatOutput({ success: true, data: data2 }, program2.opts().table);
|
|
2033
2520
|
} catch (err) {
|
|
2034
2521
|
reportCaughtError(err);
|
|
2035
2522
|
process.exit(toExitCode(err));
|
|
@@ -4619,114 +5106,6 @@ function registerOperationsRecordCommand(program2) {
|
|
|
4619
5106
|
});
|
|
4620
5107
|
}
|
|
4621
5108
|
|
|
4622
|
-
// src/client/product-api.ts
|
|
4623
|
-
async function listProducts(opts) {
|
|
4624
|
-
const request = createRequest();
|
|
4625
|
-
return request(getCustomerServiceUrl(), "/v1/knowledge/products", {
|
|
4626
|
-
method: "GET",
|
|
4627
|
-
query: {
|
|
4628
|
-
customer_agent_config_id: opts.agentConfigId,
|
|
4629
|
-
search: opts.keyword,
|
|
4630
|
-
status: opts.status?.join(","),
|
|
4631
|
-
tags: opts.tags?.length ? JSON.stringify(opts.tags) : void 0,
|
|
4632
|
-
page: opts.page ?? 1,
|
|
4633
|
-
page_size: opts.pageSize ?? 20
|
|
4634
|
-
}
|
|
4635
|
-
});
|
|
4636
|
-
}
|
|
4637
|
-
async function getProductDetail(opts) {
|
|
4638
|
-
const request = createRequest();
|
|
4639
|
-
return request(getCustomerServiceUrl(), "/v1/knowledge/product/detail", {
|
|
4640
|
-
method: "GET",
|
|
4641
|
-
query: {
|
|
4642
|
-
customer_agent_config_id: opts.agentConfigId,
|
|
4643
|
-
db_id: opts.dbId,
|
|
4644
|
-
product_id: opts.productId
|
|
4645
|
-
}
|
|
4646
|
-
});
|
|
4647
|
-
}
|
|
4648
|
-
async function updateProduct(opts) {
|
|
4649
|
-
const request = createRequest();
|
|
4650
|
-
return request(getCustomerServiceUrl(), "/v1/knowledge/product/update", {
|
|
4651
|
-
method: "POST",
|
|
4652
|
-
body: {
|
|
4653
|
-
data_id: opts.dataId,
|
|
4654
|
-
knowledge_id: opts.knowledgeId,
|
|
4655
|
-
db_id: opts.dbId,
|
|
4656
|
-
update_dict: opts.updateDict
|
|
4657
|
-
}
|
|
4658
|
-
});
|
|
4659
|
-
}
|
|
4660
|
-
async function uploadProductByUrl(opts) {
|
|
4661
|
-
const request = createRequest();
|
|
4662
|
-
return request(getCustomerServiceUrl(), "/v1/knowledge/products/upload", {
|
|
4663
|
-
method: "POST",
|
|
4664
|
-
body: {
|
|
4665
|
-
customer_agent_config_id: opts.agentConfigId,
|
|
4666
|
-
source_type: opts.sourceType ?? "manual",
|
|
4667
|
-
identify: opts.identify ?? true,
|
|
4668
|
-
product_urls: opts.productUrls
|
|
4669
|
-
}
|
|
4670
|
-
});
|
|
4671
|
-
}
|
|
4672
|
-
async function uploadProductData(opts) {
|
|
4673
|
-
const request = createRequest();
|
|
4674
|
-
return request(getCustomerServiceUrl(), "/v1/knowledge/products/upload", {
|
|
4675
|
-
method: "POST",
|
|
4676
|
-
body: {
|
|
4677
|
-
customer_agent_config_id: opts.agentConfigId,
|
|
4678
|
-
source_type: opts.sourceType ?? "manual",
|
|
4679
|
-
identify: opts.identify ?? true,
|
|
4680
|
-
product_items: opts.productItems
|
|
4681
|
-
}
|
|
4682
|
-
});
|
|
4683
|
-
}
|
|
4684
|
-
async function updateSku(opts) {
|
|
4685
|
-
if (!opts.skuId && !opts.sku) {
|
|
4686
|
-
throw new Error("updateSku \u9700\u8981\u63D0\u4F9B sku \u6216 sku_id \u5176\u4E2D\u4E4B\u4E00");
|
|
4687
|
-
}
|
|
4688
|
-
const identifier = opts.skuId ? { sku_id: opts.skuId } : { sku: opts.sku };
|
|
4689
|
-
const request = createRequest();
|
|
4690
|
-
return request(getCustomerServiceUrl(), "/v1/knowledge/sku/update", {
|
|
4691
|
-
method: "POST",
|
|
4692
|
-
body: {
|
|
4693
|
-
...identifier,
|
|
4694
|
-
customer_agent_config_id: opts.agentConfigId,
|
|
4695
|
-
update_dict: opts.updateDict
|
|
4696
|
-
}
|
|
4697
|
-
});
|
|
4698
|
-
}
|
|
4699
|
-
async function syncTaobaoProducts(opts) {
|
|
4700
|
-
const request = createRequest();
|
|
4701
|
-
return request(getCustomerServiceUrl(), "/v1/authorized-shop/sync-taobao-products", {
|
|
4702
|
-
method: "POST",
|
|
4703
|
-
body: {
|
|
4704
|
-
customer_agent_config_id: opts.agentConfigId,
|
|
4705
|
-
skip_hash_check: opts.skipHashCheck ?? false,
|
|
4706
|
-
sync_type: opts.syncType ?? "full"
|
|
4707
|
-
}
|
|
4708
|
-
});
|
|
4709
|
-
}
|
|
4710
|
-
async function syncSingleTaobaoProduct(opts) {
|
|
4711
|
-
const request = createRequest();
|
|
4712
|
-
return request(getCustomerServiceUrl(), "/v1/authorized-shop/sync-single-product", {
|
|
4713
|
-
method: "POST",
|
|
4714
|
-
body: {
|
|
4715
|
-
customer_agent_config_id: opts.agentConfigId,
|
|
4716
|
-
product_id: opts.productId
|
|
4717
|
-
}
|
|
4718
|
-
});
|
|
4719
|
-
}
|
|
4720
|
-
async function identifyAllProducts(opts) {
|
|
4721
|
-
const request = createRequest();
|
|
4722
|
-
return request(getCustomerServiceUrl(), "/v1/knowledge/products/identify/all", {
|
|
4723
|
-
method: "POST",
|
|
4724
|
-
body: {
|
|
4725
|
-
customer_agent_config_id: opts.agentConfigId
|
|
4726
|
-
}
|
|
4727
|
-
});
|
|
4728
|
-
}
|
|
4729
|
-
|
|
4730
5109
|
// src/commands/product.ts
|
|
4731
5110
|
async function getDbId(agentConfigId) {
|
|
4732
5111
|
const agent = await getAgent(agentConfigId);
|
|
@@ -4736,12 +5115,20 @@ async function getDbId(agentConfigId) {
|
|
|
4736
5115
|
return agent.database_id;
|
|
4737
5116
|
}
|
|
4738
5117
|
async function findProduct(agentConfigId, productId) {
|
|
4739
|
-
const
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
|
|
5118
|
+
const pageSize = 100;
|
|
5119
|
+
for (let page = 1; ; page += 1) {
|
|
5120
|
+
const result = await listProducts({ agentConfigId, page, pageSize });
|
|
5121
|
+
const items = result.items ?? [];
|
|
5122
|
+
const matched = items.find((p) => p.product_id === productId);
|
|
5123
|
+
if (matched) {
|
|
5124
|
+
return matched;
|
|
5125
|
+
}
|
|
5126
|
+
const fetched = page * pageSize;
|
|
5127
|
+
const exhausted = items.length < pageSize || typeof result.total === "number" && fetched >= result.total;
|
|
5128
|
+
if (exhausted) {
|
|
5129
|
+
throw new Error(`\u672A\u627E\u5230\u5546\u54C1 product_id=${productId}`);
|
|
5130
|
+
}
|
|
4743
5131
|
}
|
|
4744
|
-
return matched;
|
|
4745
5132
|
}
|
|
4746
5133
|
function registerProductCommand(program2) {
|
|
4747
5134
|
const product = program2.command("product").description(
|
|
@@ -5031,86 +5418,6 @@ function registerRepairRecordCommand(program2) {
|
|
|
5031
5418
|
});
|
|
5032
5419
|
}
|
|
5033
5420
|
|
|
5034
|
-
// src/client/sa-api.ts
|
|
5035
|
-
async function listSituationActions(opts) {
|
|
5036
|
-
const request = createRequest();
|
|
5037
|
-
return request(getCustomerServiceUrl(), "/v1/knowledge/situation-actions/list", {
|
|
5038
|
-
method: "GET",
|
|
5039
|
-
query: {
|
|
5040
|
-
customer_agent_config_id: opts.agentConfigId,
|
|
5041
|
-
sub_agent_intent: opts.subAgentIntent ?? "GENERAL_QA",
|
|
5042
|
-
event_first_label: opts.firstLabel ?? "",
|
|
5043
|
-
event_second_label: opts.secondLabel ?? "",
|
|
5044
|
-
page: opts.page ?? 1,
|
|
5045
|
-
page_size: opts.pageSize ?? 500
|
|
5046
|
-
}
|
|
5047
|
-
});
|
|
5048
|
-
}
|
|
5049
|
-
async function searchSituationActions(opts) {
|
|
5050
|
-
const request = createRequest();
|
|
5051
|
-
return request(getCustomerServiceUrl(), "/v1/knowledge/situation-actions/search", {
|
|
5052
|
-
method: "GET",
|
|
5053
|
-
query: { customer_agent_config_id: opts.agentConfigId, keyword: opts.keyword }
|
|
5054
|
-
});
|
|
5055
|
-
}
|
|
5056
|
-
async function createSituationAction(opts) {
|
|
5057
|
-
const request = createRequest();
|
|
5058
|
-
return request(getCustomerServiceUrl(), "/v1/knowledge/situation-actions/create", {
|
|
5059
|
-
method: "POST",
|
|
5060
|
-
body: {
|
|
5061
|
-
customer_agent_config_id: opts.agentConfigId,
|
|
5062
|
-
sub_agent_intent: opts.subAgentIntent ?? "GENERAL_QA",
|
|
5063
|
-
event_first_label: opts.firstLabel,
|
|
5064
|
-
event_second_label: opts.secondLabel,
|
|
5065
|
-
situation: opts.situation,
|
|
5066
|
-
action: opts.action,
|
|
5067
|
-
transfer_to_human: opts.transferToHuman ?? false
|
|
5068
|
-
}
|
|
5069
|
-
});
|
|
5070
|
-
}
|
|
5071
|
-
async function updateSituationAction(opts) {
|
|
5072
|
-
const request = createRequest();
|
|
5073
|
-
return request(getCustomerServiceUrl(), "/v1/knowledge/situation-actions/update", {
|
|
5074
|
-
method: "POST",
|
|
5075
|
-
body: {
|
|
5076
|
-
customer_agent_config_id: opts.agentConfigId,
|
|
5077
|
-
situation_action_id: opts.situationActionId,
|
|
5078
|
-
sub_agent_intent: opts.subAgentIntent ?? "GENERAL_QA",
|
|
5079
|
-
event_first_label: opts.firstLabel,
|
|
5080
|
-
event_second_label: opts.secondLabel,
|
|
5081
|
-
situation: opts.situation,
|
|
5082
|
-
action: opts.action,
|
|
5083
|
-
transfer_to_human: opts.transferToHuman ?? false
|
|
5084
|
-
}
|
|
5085
|
-
});
|
|
5086
|
-
}
|
|
5087
|
-
async function deleteSituationAction(opts) {
|
|
5088
|
-
const request = createRequest();
|
|
5089
|
-
return request(getCustomerServiceUrl(), "/v1/knowledge/situation-actions/delete", {
|
|
5090
|
-
method: "POST",
|
|
5091
|
-
body: {
|
|
5092
|
-
customer_agent_config_id: opts.agentConfigId,
|
|
5093
|
-
situation_action_id: opts.situationActionId,
|
|
5094
|
-
event_first_label: opts.firstLabel,
|
|
5095
|
-
event_second_label: opts.secondLabel
|
|
5096
|
-
}
|
|
5097
|
-
});
|
|
5098
|
-
}
|
|
5099
|
-
async function listSituationActionVersions(opts) {
|
|
5100
|
-
const request = createRequest();
|
|
5101
|
-
return request(
|
|
5102
|
-
getCustomerServiceUrl(),
|
|
5103
|
-
"/v1/knowledge/situation-actions/list/versions",
|
|
5104
|
-
{
|
|
5105
|
-
method: "GET",
|
|
5106
|
-
query: {
|
|
5107
|
-
customer_agent_config_id: opts.agentConfigId,
|
|
5108
|
-
situation_action_id: opts.situationActionId
|
|
5109
|
-
}
|
|
5110
|
-
}
|
|
5111
|
-
);
|
|
5112
|
-
}
|
|
5113
|
-
|
|
5114
5421
|
// src/commands/sa.ts
|
|
5115
5422
|
function registerSACommand(program2) {
|
|
5116
5423
|
const sa = program2.command("sa").description(
|