@bty/customer-service-cli 0.5.5 → 0.6.2
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 +22 -0
- package/README.md +50 -0
- package/dist/bin.js +836 -136
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.6.2 (2026-06-15)
|
|
4
|
+
|
|
5
|
+
- `workspace` 新增 `points-consumes` 子命令:分页查询当前工作空间的积分账户消耗流水(`POST /v1/workspace/points_consumes`),支持 `--page` / `--page-size`,CLI 固定传 `debug: true`,返回中包含服务端 `extra` 调试字段。
|
|
6
|
+
- `customer-servhub-api` 的 `POST /v1/workspace/points_consumes` 新增 `debug` 请求参数:默认 `false` 不返回 `extra`,传 `true` 时返回 `extra` 方便调试。
|
|
7
|
+
|
|
8
|
+
## 0.6.1 (2026-06-11)
|
|
9
|
+
|
|
10
|
+
- `product` 新增 `related-knowledge` 子命令组,支持按商品维护“关联知识库”文件级绑定:
|
|
11
|
+
- `product related-knowledge list --agent <id> --product-id <id>`:列出商品绑定的 QA / 扩展知识库文件。
|
|
12
|
+
- `product related-knowledge add --agent <id> --product-id <id> --type qa|common (--file <name> | --file-id <id> --partition-id <id>)`:给商品追加绑定文件,重复文件幂等去重。
|
|
13
|
+
- `product related-knowledge remove --agent <id> --product-id <id> --type qa|common --file-id <id>`:移除指定绑定,目标不存在时保持幂等。
|
|
14
|
+
- `product related-knowledge set --agent <id> --product-id <id> --bindings <json|@file>`:覆盖商品的全部关联知识库文件。
|
|
15
|
+
- `faq` / `knowledge` 新增文件侧 `bind-products` 子命令组,分别固定写入 `knowledge_type=qa` / `knowledge_type=common`:
|
|
16
|
+
- `list`:按知识库文件反查绑定商品。
|
|
17
|
+
- `add` / `remove`:read-modify-replace 维护绑定商品,重复添加或移除不存在的商品保持幂等。
|
|
18
|
+
- `set`:覆盖该文件绑定的全部商品。
|
|
19
|
+
- 新增 `product-knowledge-binding-api` 客户端封装,对接 customer-servhub-api `/v1/knowledge/product-bindings*` 现有接口;CLI 不改变服务端绑定表或 sop-engine 命中逻辑。
|
|
20
|
+
|
|
21
|
+
- 新增 `node-template describe [--stage <s>]`:节点编写说明书命令(AI 编写前必读)——输出每个节点的职责/可编辑面/输出契约/平台锁定段,以及该节点可 `@引用` 的变量目录。纯静态、与具体 agent 无关,无需 `--agent`。
|
|
22
|
+
- `node-template` 节点 stage 新增 `image_understanding` 伪 stage(图片理解方法论可配置化,spec 2026-06-08):`describe` / `get` / `set-draft` / `publish` / `versions` / `version` / `restore` 均纳入;发布前 `{{}}` 合法性校验白名单同步放行。
|
|
23
|
+
- **下线 `node-template enroll` / `enroll-status` 命令**:高级模式开关从「运维 CLI 灰度准入」改为「客户在 cs-client 内自助开关」(spec 2026-06-09),CLI 不再提供开启路径;servhub `enrolled` 端点仍在,供 cs-client 使用。
|
|
24
|
+
|
|
3
25
|
## 0.5.5 (2026-06-07)
|
|
4
26
|
|
|
5
27
|
- 修复 `debug ask --messages` 重放多轮对话时,历史消息时间戳晚于当前时间导致本次 Agent 回复插入历史消息中间、review 页面消息乱序的问题。
|
package/README.md
CHANGED
|
@@ -227,6 +227,10 @@ cs-cli workspace points-consumes-daily --start 2026-04-01 --end 2026-04-23
|
|
|
227
227
|
| `product identify-all --agent <id>` | 一键增强学习当前 Agent 下所有待增强商品 |
|
|
228
228
|
| `product sync-taobao --agent <id> [--skip-hash-check] [--sync-type <full\|incremental>]` | 触发淘宝店铺商品同步 |
|
|
229
229
|
| `product sync-taobao-item --agent <id> --product-id <商品ID>` | 触发单个淘宝商品同步 |
|
|
230
|
+
| `product related-knowledge list --agent <id> --product-id <商品ID>` | 列出商品详情绑定的 QA / 扩展知识库文件 |
|
|
231
|
+
| `product related-knowledge add --agent <id> --product-id <商品ID> --type <qa\|common> (--file <文件名> \| --file-id <id> --partition-id <id>)` | 给商品追加关联知识库文件 |
|
|
232
|
+
| `product related-knowledge remove --agent <id> --product-id <商品ID> --type <qa\|common> --file-id <id>` | 移除商品绑定的指定知识库文件 |
|
|
233
|
+
| `product related-knowledge set --agent <id> --product-id <商品ID> --bindings <json\|@file>` | 覆盖商品绑定的全部知识库文件 |
|
|
230
234
|
|
|
231
235
|
`product update` 支持更新的字段包括:`卖点`、`补充知识`、`tag`、`参数`、`轮播图识别结果`、`商品详情页识别结果` 等。`--update` 接受 JSON 字符串或 `@文件路径`。
|
|
232
236
|
|
|
@@ -240,6 +244,8 @@ cs-cli workspace points-consumes-daily --start 2026-04-01 --end 2026-04-23
|
|
|
240
244
|
|
|
241
245
|
注意:这两个命令仅对已开通“高级工具”的店铺 Agent 生效。未开通高级工具时,即使 `--agent` 已绑定淘宝授权店铺,请求也可能在服务端失败。
|
|
242
246
|
|
|
247
|
+
`product related-knowledge` 管理商品详情的“关联知识库”文件级绑定。`--type qa` 对应 FAQ 知识库,`--type common` 对应扩展知识库。`add` / `remove` 会先读取当前绑定,再通过服务端全量替换接口写回;重复添加或移除不存在的文件保持幂等。`--file <文件名>` 会按当前 Agent 的知识库文件列表做精确匹配;文件名不存在或不唯一时,改用 `--file-id` + `--partition-id` 显式模式。
|
|
248
|
+
|
|
243
249
|
```bash
|
|
244
250
|
# 更新卖点
|
|
245
251
|
cs-cli product update --agent <id> --product-id <商品ID> --update '{"卖点":"新卖点内容"}'
|
|
@@ -255,6 +261,12 @@ cs-cli product update-sku --agent <id> --sku "颜色分类:粉红" --update '{"
|
|
|
255
261
|
|
|
256
262
|
# 更新 SKU 补充知识(按 sku_id 定位,推荐)
|
|
257
263
|
cs-cli product update-sku --agent <id> --sku-id 6072595054179 --update '{"补充知识":"说明内容"}'
|
|
264
|
+
|
|
265
|
+
# 给商品绑定一个 FAQ 文件
|
|
266
|
+
cs-cli product related-knowledge add --agent <id> --product-id <商品ID> --type qa --file "常见问题.xlsx"
|
|
267
|
+
|
|
268
|
+
# 显式 ID 模式绑定扩展知识文件
|
|
269
|
+
cs-cli product related-knowledge add --agent <id> --product-id <商品ID> --type common --file-id 622474 --partition-id 12345 --file-name "售后规则.md"
|
|
258
270
|
```
|
|
259
271
|
|
|
260
272
|
|
|
@@ -299,6 +311,24 @@ cs-cli activity delete 6
|
|
|
299
311
|
cs-cli activity v2-enabled --agent <cfg_id> --enabled true
|
|
300
312
|
```
|
|
301
313
|
|
|
314
|
+
### 节点模板 (`node-template`)
|
|
315
|
+
|
|
316
|
+
高级模板(4 真节点提示词 + `image_understanding` 图片理解方法论伪 stage)操作:编写说明书 + 获取内容 + 改动发布 + 历史/回溯。服务端 `customer-servhub-api /v1/customer-agent/{config_id}/customer_config/node-templates*`;契约见 [`docs/devkit/specs/2026-06-08-节点模板-cli-操作面.md`](../../docs/devkit/specs/2026-06-08-节点模板-cli-操作面.md)。**节点 stage:`planner|composer|qa_inspector|image_understanding`(`tool_selector` 暂不放出)。**
|
|
317
|
+
|
|
318
|
+
> 高级模式开关已改为**客户自助**(在 cs-client 内开关),CLI 不再提供 `enroll` / `enroll-status` 开启路径(已下线)。
|
|
319
|
+
|
|
320
|
+
| 命令 | 说明 |
|
|
321
|
+
| --- | --- |
|
|
322
|
+
| `node-template describe [--stage <s>]` | 节点编写说明书(AI 编写前必读):每节点职责/可编辑面/输出契约/平台锁定段 + 可 `@引用` 变量目录;纯静态、无需 `--agent` |
|
|
323
|
+
| `node-template get --agent <id> [--stage <s>]` | 获取内容(不传 stage=全部已开放节点) |
|
|
324
|
+
| `node-template set-draft --agent <id> --stage <s> (--content <t>\|--content-file <p>\|--stdin)` | 写单节点草稿(整段覆盖;空串=回落出厂默认) |
|
|
325
|
+
| `node-template publish --agent <id> --stage <s> [--force]` | 发布草稿上线(发布前校验 `{{}}`,`--force` 越过) |
|
|
326
|
+
| `node-template versions --agent <id> --stage <s>` | 列该节点历史 |
|
|
327
|
+
| `node-template version --agent <id> --stage <s> --version <n>` | 取某版本正文 |
|
|
328
|
+
| `node-template restore --agent <id> --stage <s> --version <n>` | 回溯某版本成草稿(需再 publish) |
|
|
329
|
+
|
|
330
|
+
典型流(该 agent 已由客户在 cs-client 开启高级模式后):`get` 看现状 → `set-draft` 改草稿 → `publish` 上线。`publish` 会拒绝含非法 `{{插值}}` 名的草稿(笔误防呆)。
|
|
331
|
+
|
|
302
332
|
### 工单管理 (`issue`)
|
|
303
333
|
|
|
304
334
|
|
|
@@ -387,11 +417,17 @@ CLI 把 `description` + `expected` 拼成 `content`:
|
|
|
387
417
|
| `faq add --agent <id> --file <文件名> --questions <问题1,问题2> --answers <答案=xxx>` | 添加 FAQ 内容 |
|
|
388
418
|
| `faq update --agent <id> --file <文件名> --group-id <id> [--questions <...>] [--answers <...>] [--delete-chunks <id1,id2>]` | 更新已有 FAQ 答案组(`--questions` / `--answers` / `--delete-chunks` 至少一个) |
|
|
389
419
|
| `faq delete --agent <id> --file <文件名> --group-id <id>` | 删除 FAQ 答案组 |
|
|
420
|
+
| `faq bind-products list --agent <id> (--file <文件名> \| --file-id <id> --partition-id <id>)` | 列出 FAQ 文件绑定的商品 |
|
|
421
|
+
| `faq bind-products add --agent <id> (--file <文件名> \| --file-id <id> --partition-id <id>) --product-id <商品ID...>` | 给 FAQ 文件追加绑定商品 |
|
|
422
|
+
| `faq bind-products remove --agent <id> (--file <文件名> \| --file-id <id> --partition-id <id>) --product-id <商品ID...>` | 从 FAQ 文件移除绑定商品 |
|
|
423
|
+
| `faq bind-products set --agent <id> (--file <文件名> \| --file-id <id> --partition-id <id>) --product-id <商品ID...>` | 覆盖 FAQ 文件绑定的全部商品 |
|
|
390
424
|
|
|
391
425
|
`faq content` 走 `GET /mebsuta/api/v1/dataset/{knowledge_id}/faq_contents`,列出文件内的答案组及其 `answer_group_id`,是 `faq update` / `faq delete` 拿 `--group-id` 的来源(`faq list` 只给文件,文件内的 group-id 要靠这条命令查)。支持 `--keyword` 搜索、`--page-size` 分页、`--next-group-id` 游标续翻。
|
|
392
426
|
|
|
393
427
|
`faq update` 按 `answer_group_id` 定位目标组,POST 同一个 `faq_contents/save` 接口完成字段替换、问题替换与 chunk 级删除。`faq delete` 走 `DELETE /faq_contents/{group_id}` 整组删除。
|
|
394
428
|
|
|
429
|
+
`faq bind-products` 固定写入 `knowledge_type=qa` 的商品绑定关系,适合从 FAQ 文件视角批量维护关联商品。`--file` 为精确文件名匹配;文件名不唯一时请传 `--file-id` 和 `--partition-id`。
|
|
430
|
+
|
|
395
431
|
### 扩展知识库 (`knowledge`)
|
|
396
432
|
|
|
397
433
|
Agent 关联的通用规则知识库(`suffix_type=_common`),与 FAQ / 商品知识并列的第三类知识源,支持段落(chunk)级 CRUD,统一走 `/mebsuta/api/v1/dataset/{id}/contents/perform-operations`。
|
|
@@ -403,9 +439,15 @@ Agent 关联的通用规则知识库(`suffix_type=_common`),与 FAQ / 商
|
|
|
403
439
|
| `knowledge content add --knowledge-id <id> --content <text\|@file> [--keyword <k...>] [--after <chunk_id>]` | 新增段落 |
|
|
404
440
|
| `knowledge content update --knowledge-id <id> --chunk-id <id> [--content <text\|@file>] [--keyword <k...>] [--enable \| --disable]` | 更新段落(四个变更字段至少一个;未指定 `--enable` / `--disable` 时自动保留当前启停状态,避免后端 enable 必填校验失败) |
|
|
405
441
|
| `knowledge content delete --knowledge-id <id> --chunk-id <id>` | 删除段落 |
|
|
442
|
+
| `knowledge bind-products list --agent <id> (--file <文件名> \| --file-id <id> --partition-id <id>)` | 列出扩展知识文件绑定的商品 |
|
|
443
|
+
| `knowledge bind-products add --agent <id> (--file <文件名> \| --file-id <id> --partition-id <id>) --product-id <商品ID...>` | 给扩展知识文件追加绑定商品 |
|
|
444
|
+
| `knowledge bind-products remove --agent <id> (--file <文件名> \| --file-id <id> --partition-id <id>) --product-id <商品ID...>` | 从扩展知识文件移除绑定商品 |
|
|
445
|
+
| `knowledge bind-products set --agent <id> (--file <文件名> \| --file-id <id> --partition-id <id>) --product-id <商品ID...>` | 覆盖扩展知识文件绑定的全部商品 |
|
|
406
446
|
|
|
407
447
|
`knowledge content add` / `update` 的 `--content` 支持 `@路径` 前缀从文件读取**纯文本**(不是 JSON)。`--keyword` 为 variadic 选项,空格分隔多个关键词。
|
|
408
448
|
|
|
449
|
+
`knowledge bind-products` 固定写入 `knowledge_type=common` 的商品绑定关系,适合从扩展知识文件视角批量维护关联商品。`add` / `remove` 会 read-modify-replace,重复添加或移除不存在的商品保持幂等。
|
|
450
|
+
|
|
409
451
|
|
|
410
452
|
### 会话管理 (`conversation`)
|
|
411
453
|
|
|
@@ -435,6 +477,14 @@ Agent 关联的通用规则知识库(`suffix_type=_common`),与 FAQ / 商
|
|
|
435
477
|
|
|
436
478
|
`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` 字段获取。
|
|
437
479
|
|
|
480
|
+
### 工作空间 (`workspace`)
|
|
481
|
+
|
|
482
|
+
| 命令 | 说明 |
|
|
483
|
+
| --- | --- |
|
|
484
|
+
| `workspace list` | 列出当前账号可访问的工作空间 |
|
|
485
|
+
| `workspace points-consumes [--page <n>] [--page-size <n>]` | 分页查询积分账户消耗流水,固定返回 `extra` 调试字段 |
|
|
486
|
+
| `workspace points-consumes-daily [--start <YYYY-MM-DD>] [--end <YYYY-MM-DD>]` | 按天查询积分消耗趋势 |
|
|
487
|
+
|
|
438
488
|
- `--env <dev|prod>`:指定 Langfuse 环境,默认 `prod`。只接受 `dev` / `prod`,传其它值命令直接报错并以非 0 退出(不发请求)。
|
|
439
489
|
|
|
440
490
|
```bash
|
package/dist/bin.js
CHANGED
|
@@ -31,7 +31,24 @@ function formatOutput(response, table) {
|
|
|
31
31
|
if (Array.isArray(data)) {
|
|
32
32
|
renderArrayTable(data);
|
|
33
33
|
} else if (data !== null && typeof data === "object") {
|
|
34
|
-
|
|
34
|
+
const obj = data;
|
|
35
|
+
const innerArray = findInnerArray(obj);
|
|
36
|
+
if (innerArray) {
|
|
37
|
+
renderArrayTable(innerArray);
|
|
38
|
+
const total = obj.total ?? obj.count;
|
|
39
|
+
const pageNo = obj.page_no ?? obj.page;
|
|
40
|
+
const pageSize = obj.page_size;
|
|
41
|
+
if (total !== void 0) {
|
|
42
|
+
const paginationParts = [`total: ${total}`];
|
|
43
|
+
if (pageNo !== void 0) paginationParts.push(`page: ${pageNo}`);
|
|
44
|
+
if (pageSize !== void 0) paginationParts.push(`page_size: ${pageSize}`);
|
|
45
|
+
process.stdout.write(`
|
|
46
|
+
${paginationParts.join(" | ")}
|
|
47
|
+
`);
|
|
48
|
+
}
|
|
49
|
+
} else {
|
|
50
|
+
renderObjectTable(obj);
|
|
51
|
+
}
|
|
35
52
|
} else {
|
|
36
53
|
process.stdout.write(JSON.stringify(response, null, 2));
|
|
37
54
|
return;
|
|
@@ -43,6 +60,16 @@ Page ${page} | ${pageSize} per page | ${total} total
|
|
|
43
60
|
`);
|
|
44
61
|
}
|
|
45
62
|
}
|
|
63
|
+
function findInnerArray(obj) {
|
|
64
|
+
const paginationKeys = /* @__PURE__ */ new Set(["total", "count", "page_no", "page", "page_size"]);
|
|
65
|
+
const arrayKey = Object.keys(obj).find(
|
|
66
|
+
(k) => Array.isArray(obj[k]) && !paginationKeys.has(k)
|
|
67
|
+
);
|
|
68
|
+
if (!arrayKey) return null;
|
|
69
|
+
const arr = obj[arrayKey];
|
|
70
|
+
if (arr.length === 0 || typeof arr[0] !== "object" || arr[0] === null) return null;
|
|
71
|
+
return arr;
|
|
72
|
+
}
|
|
46
73
|
function renderArrayTable(data) {
|
|
47
74
|
const first = data[0];
|
|
48
75
|
if (first == null) {
|
|
@@ -52,7 +79,14 @@ function renderArrayTable(data) {
|
|
|
52
79
|
const headers = Object.keys(first);
|
|
53
80
|
const table = new Table({ head: headers });
|
|
54
81
|
for (const row of data) {
|
|
55
|
-
table.push(
|
|
82
|
+
table.push(
|
|
83
|
+
headers.map((h) => {
|
|
84
|
+
const val = row[h];
|
|
85
|
+
if (Array.isArray(val)) return val.length === 0 ? "[]" : `[${val.length} items]`;
|
|
86
|
+
if (val !== null && typeof val === "object") return JSON.stringify(val);
|
|
87
|
+
return String(val ?? "");
|
|
88
|
+
})
|
|
89
|
+
);
|
|
56
90
|
}
|
|
57
91
|
process.stdout.write(`${table.toString()}
|
|
58
92
|
`);
|
|
@@ -60,7 +94,15 @@ function renderArrayTable(data) {
|
|
|
60
94
|
function renderObjectTable(data) {
|
|
61
95
|
const table = new Table();
|
|
62
96
|
for (const [key, value] of Object.entries(data)) {
|
|
63
|
-
|
|
97
|
+
let display;
|
|
98
|
+
if (Array.isArray(value)) {
|
|
99
|
+
display = value.length === 0 ? "[]" : `[${value.length} items]`;
|
|
100
|
+
} else if (value !== null && typeof value === "object") {
|
|
101
|
+
display = JSON.stringify(value);
|
|
102
|
+
} else {
|
|
103
|
+
display = String(value ?? "");
|
|
104
|
+
}
|
|
105
|
+
table.push({ [key]: display });
|
|
64
106
|
}
|
|
65
107
|
process.stdout.write(`${table.toString()}
|
|
66
108
|
`);
|
|
@@ -436,7 +478,6 @@ function isTokenExpired(expiresAt) {
|
|
|
436
478
|
// src/client/helpers.ts
|
|
437
479
|
var DEFAULT_CS_API_URL = "https://customer-servhub-api.betteryeah.com";
|
|
438
480
|
var DEFAULT_AI_API_URL = "https://ai-api.betteryeah.com";
|
|
439
|
-
var DEFAULT_CUSTOMER_AGENT_API_URL = "https://customer-agent.bantouyan.com";
|
|
440
481
|
var DEFAULT_CS_ADMIN_URL = "https://customer-service-admin.betteryeah.com";
|
|
441
482
|
function getCustomerServiceUrl() {
|
|
442
483
|
const envUrl = process.env.CS_CS_API_URL;
|
|
@@ -450,12 +491,6 @@ function getAiApiUrl() {
|
|
|
450
491
|
const config = readConfig();
|
|
451
492
|
return config?.aiApiUrl ?? DEFAULT_AI_API_URL;
|
|
452
493
|
}
|
|
453
|
-
function getCustomerAgentUrl() {
|
|
454
|
-
const envUrl = process.env.CS_CUSTOMER_AGENT_URL;
|
|
455
|
-
if (envUrl) return envUrl;
|
|
456
|
-
const config = readConfig();
|
|
457
|
-
return config?.customerAgentApiUrl ?? DEFAULT_CUSTOMER_AGENT_API_URL;
|
|
458
|
-
}
|
|
459
494
|
function getCsAdminUrl() {
|
|
460
495
|
const envUrl = process.env.CS_CS_ADMIN_URL;
|
|
461
496
|
if (envUrl) return envUrl;
|
|
@@ -477,15 +512,6 @@ function getWorkspaceId(overrideWorkspaceId) {
|
|
|
477
512
|
if (globalConfig?.defaultWorkspaceId) return globalConfig.defaultWorkspaceId;
|
|
478
513
|
throw new APIError(1, "\u672A\u8BBE\u7F6E\u5DE5\u4F5C\u7A7A\u95F4\uFF0C\u8BF7\u8FD0\u884C: cs-cli config set-workspace <id>");
|
|
479
514
|
}
|
|
480
|
-
function buildCookieHeaders() {
|
|
481
|
-
const creds = readCredentials();
|
|
482
|
-
if (!creds) throw new APIError(2, "\u672A\u767B\u5F55\uFF0C\u8BF7\u8FD0\u884C: cs-cli auth login");
|
|
483
|
-
if (isTokenExpired(creds.expiresAt)) {
|
|
484
|
-
clearCredentials();
|
|
485
|
-
throw new APIError(2, "Token \u5DF2\u8FC7\u671F\uFF0C\u8BF7\u8FD0\u884C: cs-cli auth login");
|
|
486
|
-
}
|
|
487
|
-
return { Cookie: `auth_token=${creds.accessToken}` };
|
|
488
|
-
}
|
|
489
515
|
|
|
490
516
|
// src/client/activity-api.ts
|
|
491
517
|
var PATH_PREFIX = "/v1/activity";
|
|
@@ -1104,6 +1130,17 @@ async function getDailyDeduction(opts) {
|
|
|
1104
1130
|
}
|
|
1105
1131
|
);
|
|
1106
1132
|
}
|
|
1133
|
+
async function getPointsConsumes(opts) {
|
|
1134
|
+
const request = createRequest();
|
|
1135
|
+
return request(
|
|
1136
|
+
getCustomerServiceUrl(),
|
|
1137
|
+
"/v1/workspace/points_consumes",
|
|
1138
|
+
{
|
|
1139
|
+
method: "POST",
|
|
1140
|
+
body: { page: opts.page, page_size: opts.pageSize, debug: true }
|
|
1141
|
+
}
|
|
1142
|
+
);
|
|
1143
|
+
}
|
|
1107
1144
|
|
|
1108
1145
|
// src/commands/config.ts
|
|
1109
1146
|
function registerConfigCommand(program2) {
|
|
@@ -2064,6 +2101,442 @@ async function deleteFaqGroup(opts) {
|
|
|
2064
2101
|
);
|
|
2065
2102
|
}
|
|
2066
2103
|
|
|
2104
|
+
// src/client/knowledge-api.ts
|
|
2105
|
+
async function listExternalKnowledge(opts) {
|
|
2106
|
+
const request = createRequest();
|
|
2107
|
+
return request(getCustomerServiceUrl(), "/v1/knowledge/external", {
|
|
2108
|
+
method: "GET",
|
|
2109
|
+
query: {
|
|
2110
|
+
customer_agent_config_id: opts.agentConfigId,
|
|
2111
|
+
page: opts.page ?? 1,
|
|
2112
|
+
page_size: opts.pageSize ?? 20,
|
|
2113
|
+
suffix_type: "_common"
|
|
2114
|
+
}
|
|
2115
|
+
});
|
|
2116
|
+
}
|
|
2117
|
+
async function listKnowledgeContents(opts) {
|
|
2118
|
+
const request = createRequest();
|
|
2119
|
+
return request(getAiApiUrl(), `/mebsuta/api/v1/dataset/${opts.knowledgeId}/contents`, {
|
|
2120
|
+
method: "GET",
|
|
2121
|
+
query: {
|
|
2122
|
+
page_size: opts.pageSize ?? 20,
|
|
2123
|
+
need_total: opts.needTotal ?? true,
|
|
2124
|
+
direction: opts.direction ?? "down"
|
|
2125
|
+
}
|
|
2126
|
+
});
|
|
2127
|
+
}
|
|
2128
|
+
async function addKnowledgeContent(opts) {
|
|
2129
|
+
const request = createRequest();
|
|
2130
|
+
const ts = (opts.now ?? Date.now)();
|
|
2131
|
+
const identifier = `temp_${ts}`;
|
|
2132
|
+
const body = {
|
|
2133
|
+
operations: [
|
|
2134
|
+
{
|
|
2135
|
+
action: "add",
|
|
2136
|
+
original_identifier: opts.afterChunkId ?? "0",
|
|
2137
|
+
identifier
|
|
2138
|
+
}
|
|
2139
|
+
],
|
|
2140
|
+
content_updates: { [identifier]: opts.content },
|
|
2141
|
+
keywords_updates: { [identifier]: opts.keywords ?? [] },
|
|
2142
|
+
extra_info_updates: { [identifier]: { chunk_status: "done" } }
|
|
2143
|
+
};
|
|
2144
|
+
return request(
|
|
2145
|
+
getAiApiUrl(),
|
|
2146
|
+
`/mebsuta/api/v1/dataset/${opts.knowledgeId}/contents/perform-operations`,
|
|
2147
|
+
{
|
|
2148
|
+
method: "POST",
|
|
2149
|
+
body
|
|
2150
|
+
}
|
|
2151
|
+
);
|
|
2152
|
+
}
|
|
2153
|
+
async function updateKnowledgeContent(opts) {
|
|
2154
|
+
const request = createRequest();
|
|
2155
|
+
const operation = {
|
|
2156
|
+
action: "update",
|
|
2157
|
+
identifier: opts.chunkId,
|
|
2158
|
+
enable: opts.enable
|
|
2159
|
+
};
|
|
2160
|
+
const contentUpdates = opts.content !== void 0 ? { [opts.chunkId]: opts.content } : {};
|
|
2161
|
+
const keywordsUpdates = opts.keywords !== void 0 ? { [opts.chunkId]: opts.keywords } : {};
|
|
2162
|
+
const extraInfoUpdates = opts.content !== void 0 || opts.keywords !== void 0 ? { [opts.chunkId]: { chunk_status: "done" } } : {};
|
|
2163
|
+
const body = {
|
|
2164
|
+
operations: [operation],
|
|
2165
|
+
content_updates: contentUpdates,
|
|
2166
|
+
keywords_updates: keywordsUpdates,
|
|
2167
|
+
extra_info_updates: extraInfoUpdates
|
|
2168
|
+
};
|
|
2169
|
+
return request(
|
|
2170
|
+
getAiApiUrl(),
|
|
2171
|
+
`/mebsuta/api/v1/dataset/${opts.knowledgeId}/contents/perform-operations`,
|
|
2172
|
+
{
|
|
2173
|
+
method: "POST",
|
|
2174
|
+
body
|
|
2175
|
+
}
|
|
2176
|
+
);
|
|
2177
|
+
}
|
|
2178
|
+
async function findKnowledgeChunk(opts) {
|
|
2179
|
+
const result = await listKnowledgeContents({
|
|
2180
|
+
knowledgeId: opts.knowledgeId,
|
|
2181
|
+
pageSize: opts.pageSize ?? 500,
|
|
2182
|
+
needTotal: true,
|
|
2183
|
+
direction: "down"
|
|
2184
|
+
});
|
|
2185
|
+
return result.contents?.find((c) => c.chunk_id === opts.chunkId);
|
|
2186
|
+
}
|
|
2187
|
+
async function deleteKnowledgeContent(opts) {
|
|
2188
|
+
const request = createRequest();
|
|
2189
|
+
const body = {
|
|
2190
|
+
operations: [{ action: "delete", identifier: opts.chunkId }],
|
|
2191
|
+
content_updates: {},
|
|
2192
|
+
keywords_updates: {},
|
|
2193
|
+
extra_info_updates: {}
|
|
2194
|
+
};
|
|
2195
|
+
return request(
|
|
2196
|
+
getAiApiUrl(),
|
|
2197
|
+
`/mebsuta/api/v1/dataset/${opts.knowledgeId}/contents/perform-operations`,
|
|
2198
|
+
{
|
|
2199
|
+
method: "POST",
|
|
2200
|
+
body
|
|
2201
|
+
}
|
|
2202
|
+
);
|
|
2203
|
+
}
|
|
2204
|
+
|
|
2205
|
+
// src/client/product-knowledge-binding-api.ts
|
|
2206
|
+
var PATH_PREFIX2 = "/v1/knowledge/product-bindings";
|
|
2207
|
+
async function listProductKnowledgeBindings(opts) {
|
|
2208
|
+
const request = createRequest();
|
|
2209
|
+
return request(getCustomerServiceUrl(), PATH_PREFIX2, {
|
|
2210
|
+
method: "GET",
|
|
2211
|
+
query: {
|
|
2212
|
+
customer_agent_config_id: opts.agentConfigId,
|
|
2213
|
+
product_id: opts.productId,
|
|
2214
|
+
knowledge_type: opts.knowledgeType,
|
|
2215
|
+
file_id: opts.fileId
|
|
2216
|
+
}
|
|
2217
|
+
});
|
|
2218
|
+
}
|
|
2219
|
+
async function replaceProductKnowledgeBindingsByProduct(opts) {
|
|
2220
|
+
const request = createRequest();
|
|
2221
|
+
return request(getCustomerServiceUrl(), `${PATH_PREFIX2}/by-product`, {
|
|
2222
|
+
method: "PUT",
|
|
2223
|
+
body: {
|
|
2224
|
+
customer_agent_config_id: opts.agentConfigId,
|
|
2225
|
+
product_id: opts.productId,
|
|
2226
|
+
bindings: opts.bindings
|
|
2227
|
+
}
|
|
2228
|
+
});
|
|
2229
|
+
}
|
|
2230
|
+
async function replaceProductKnowledgeBindingsByFile(opts) {
|
|
2231
|
+
const request = createRequest();
|
|
2232
|
+
return request(getCustomerServiceUrl(), `${PATH_PREFIX2}/by-file`, {
|
|
2233
|
+
method: "PUT",
|
|
2234
|
+
body: {
|
|
2235
|
+
customer_agent_config_id: opts.agentConfigId,
|
|
2236
|
+
knowledge_type: opts.knowledgeType,
|
|
2237
|
+
file_id: opts.fileId,
|
|
2238
|
+
file_name: opts.fileName,
|
|
2239
|
+
partition_id: opts.partitionId,
|
|
2240
|
+
partition_name: opts.partitionName,
|
|
2241
|
+
products: opts.productIds.map((product_id) => ({ product_id }))
|
|
2242
|
+
}
|
|
2243
|
+
});
|
|
2244
|
+
}
|
|
2245
|
+
|
|
2246
|
+
// src/commands/product-knowledge-binding.ts
|
|
2247
|
+
function parsePositiveInt(value, fieldName) {
|
|
2248
|
+
const n = Number(value);
|
|
2249
|
+
if (!Number.isInteger(n) || n <= 0) {
|
|
2250
|
+
throw new Error(`${fieldName} \u5FC5\u987B\u4E3A\u6B63\u6574\u6570`);
|
|
2251
|
+
}
|
|
2252
|
+
return n;
|
|
2253
|
+
}
|
|
2254
|
+
function parseKnowledgeType(value) {
|
|
2255
|
+
if (value === "qa" || value === "common") return value;
|
|
2256
|
+
throw new Error("--type \u4EC5\u63A5\u53D7 qa | common");
|
|
2257
|
+
}
|
|
2258
|
+
function dedupeStrings(values) {
|
|
2259
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2260
|
+
const result = [];
|
|
2261
|
+
for (const value of values) {
|
|
2262
|
+
const trimmed = String(value || "").trim();
|
|
2263
|
+
if (!trimmed || seen.has(trimmed)) continue;
|
|
2264
|
+
seen.add(trimmed);
|
|
2265
|
+
result.push(trimmed);
|
|
2266
|
+
}
|
|
2267
|
+
return result;
|
|
2268
|
+
}
|
|
2269
|
+
function bindingKey(item) {
|
|
2270
|
+
return `${item.knowledge_type}:${item.file_id}`;
|
|
2271
|
+
}
|
|
2272
|
+
function toBindingInput(item) {
|
|
2273
|
+
return {
|
|
2274
|
+
knowledge_type: item.knowledge_type,
|
|
2275
|
+
file_id: parsePositiveInt(item.file_id, "file_id"),
|
|
2276
|
+
file_name: item.file_name ?? null,
|
|
2277
|
+
partition_id: parsePositiveInt(item.partition_id, "partition_id"),
|
|
2278
|
+
partition_name: item.partition_name ?? null
|
|
2279
|
+
};
|
|
2280
|
+
}
|
|
2281
|
+
function normalizeBindingInput(value) {
|
|
2282
|
+
if (!value || typeof value !== "object") {
|
|
2283
|
+
throw new Error("bindings \u6BCF\u9879\u5FC5\u987B\u662F\u5BF9\u8C61");
|
|
2284
|
+
}
|
|
2285
|
+
const item = value;
|
|
2286
|
+
return {
|
|
2287
|
+
knowledge_type: parseKnowledgeType(String(item.knowledge_type ?? "")),
|
|
2288
|
+
file_id: parsePositiveInt(item.file_id, "file_id"),
|
|
2289
|
+
file_name: item.file_name ?? null,
|
|
2290
|
+
partition_id: parsePositiveInt(item.partition_id, "partition_id"),
|
|
2291
|
+
partition_name: item.partition_name ?? null
|
|
2292
|
+
};
|
|
2293
|
+
}
|
|
2294
|
+
function parseBindingsOption(raw) {
|
|
2295
|
+
const parsed = parseDataOption(raw);
|
|
2296
|
+
if (!Array.isArray(parsed)) {
|
|
2297
|
+
throw new Error("--bindings \u5FC5\u987B\u662F\u6570\u7EC4");
|
|
2298
|
+
}
|
|
2299
|
+
return parsed.map(normalizeBindingInput);
|
|
2300
|
+
}
|
|
2301
|
+
function fileIdOf(item) {
|
|
2302
|
+
return parsePositiveInt(item.knowledge_id ?? item.file_id, "file_id");
|
|
2303
|
+
}
|
|
2304
|
+
function partitionIdOf(item) {
|
|
2305
|
+
return parsePositiveInt(item.partition_id, "partition_id");
|
|
2306
|
+
}
|
|
2307
|
+
function failWithMessage(message) {
|
|
2308
|
+
outputError(1, message);
|
|
2309
|
+
process.exit(1);
|
|
2310
|
+
}
|
|
2311
|
+
async function listFilesByType(knowledgeType, agentConfigId) {
|
|
2312
|
+
const result = knowledgeType === "qa" ? await listFaqFiles({ agentConfigId, page: 1, pageSize: 100 }) : await listExternalKnowledge({ agentConfigId, page: 1, pageSize: 100 });
|
|
2313
|
+
return result.items ?? [];
|
|
2314
|
+
}
|
|
2315
|
+
async function resolveFile(opts) {
|
|
2316
|
+
if (opts.file && (opts.fileId || opts.partitionId)) {
|
|
2317
|
+
throw new Error("--file \u4E0E --file-id/--partition-id \u4E0D\u80FD\u540C\u65F6\u4F7F\u7528");
|
|
2318
|
+
}
|
|
2319
|
+
if (opts.file) {
|
|
2320
|
+
const files = await listFilesByType(opts.knowledgeType, opts.agentConfigId);
|
|
2321
|
+
const matched = files.filter((item2) => item2.file_name === opts.file);
|
|
2322
|
+
if (matched.length === 0) {
|
|
2323
|
+
failWithMessage(`\u672A\u627E\u5230\u77E5\u8BC6\u5E93\u6587\u4EF6: ${opts.file}`);
|
|
2324
|
+
}
|
|
2325
|
+
if (matched.length > 1) {
|
|
2326
|
+
failWithMessage(`\u77E5\u8BC6\u5E93\u6587\u4EF6\u540D\u4E0D\u552F\u4E00: ${opts.file}\uFF0C\u8BF7\u6539\u7528 --file-id/--partition-id`);
|
|
2327
|
+
}
|
|
2328
|
+
const item = matched[0];
|
|
2329
|
+
return {
|
|
2330
|
+
fileId: fileIdOf(item),
|
|
2331
|
+
fileName: item.file_name ?? opts.file,
|
|
2332
|
+
partitionId: partitionIdOf(item),
|
|
2333
|
+
partitionName: item.partition_name ?? null
|
|
2334
|
+
};
|
|
2335
|
+
}
|
|
2336
|
+
if (!opts.fileId || !opts.partitionId) {
|
|
2337
|
+
throw new Error("\u8BF7\u63D0\u4F9B --file \u6216\u540C\u65F6\u63D0\u4F9B --file-id \u4E0E --partition-id");
|
|
2338
|
+
}
|
|
2339
|
+
return {
|
|
2340
|
+
fileId: parsePositiveInt(opts.fileId, "file_id"),
|
|
2341
|
+
fileName: opts.fileName,
|
|
2342
|
+
partitionId: parsePositiveInt(opts.partitionId, "partition_id"),
|
|
2343
|
+
partitionName: opts.partitionName
|
|
2344
|
+
};
|
|
2345
|
+
}
|
|
2346
|
+
async function replaceProductBindings(opts) {
|
|
2347
|
+
return replaceProductKnowledgeBindingsByProduct({
|
|
2348
|
+
agentConfigId: opts.agentConfigId,
|
|
2349
|
+
productId: opts.productId,
|
|
2350
|
+
bindings: opts.bindings
|
|
2351
|
+
});
|
|
2352
|
+
}
|
|
2353
|
+
async function getProductBindingInputs(opts) {
|
|
2354
|
+
const current = await listProductKnowledgeBindings({
|
|
2355
|
+
agentConfigId: opts.agentConfigId,
|
|
2356
|
+
productId: opts.productId
|
|
2357
|
+
});
|
|
2358
|
+
return (current.items ?? []).map(toBindingInput);
|
|
2359
|
+
}
|
|
2360
|
+
async function replaceFileBindings(opts) {
|
|
2361
|
+
return replaceProductKnowledgeBindingsByFile({
|
|
2362
|
+
agentConfigId: opts.agentConfigId,
|
|
2363
|
+
knowledgeType: opts.knowledgeType,
|
|
2364
|
+
fileId: opts.file.fileId,
|
|
2365
|
+
fileName: opts.file.fileName,
|
|
2366
|
+
partitionId: opts.file.partitionId,
|
|
2367
|
+
partitionName: opts.file.partitionName,
|
|
2368
|
+
productIds: opts.productIds
|
|
2369
|
+
});
|
|
2370
|
+
}
|
|
2371
|
+
async function getFileProductIds(opts) {
|
|
2372
|
+
const current = await listProductKnowledgeBindings({
|
|
2373
|
+
agentConfigId: opts.agentConfigId,
|
|
2374
|
+
knowledgeType: opts.knowledgeType,
|
|
2375
|
+
fileId: opts.fileId
|
|
2376
|
+
});
|
|
2377
|
+
return dedupeStrings((current.items ?? []).map((item) => item.product_id));
|
|
2378
|
+
}
|
|
2379
|
+
function handleError(err) {
|
|
2380
|
+
reportCaughtError(err);
|
|
2381
|
+
process.exit(toExitCode(err));
|
|
2382
|
+
}
|
|
2383
|
+
function registerProductRelatedKnowledgeCommand(product, program2) {
|
|
2384
|
+
const related = product.command("related-knowledge").description("\u5546\u54C1\u8BE6\u60C5\u5173\u8054\u77E5\u8BC6\u5E93\u6587\u4EF6\u7BA1\u7406\uFF1Alist / add / remove / set");
|
|
2385
|
+
related.command("list").description("\u5217\u51FA\u6307\u5B9A\u5546\u54C1\u7ED1\u5B9A\u7684 QA / \u6269\u5C55\u77E5\u8BC6\u5E93\u6587\u4EF6").requiredOption("--agent <config_id>", "Agent \u914D\u7F6E ID").requiredOption("--product-id <product_id>", "\u5546\u54C1 ID").action(async (opts) => {
|
|
2386
|
+
try {
|
|
2387
|
+
const data = await listProductKnowledgeBindings({
|
|
2388
|
+
agentConfigId: opts.agent,
|
|
2389
|
+
productId: opts.productId
|
|
2390
|
+
});
|
|
2391
|
+
formatOutput({ success: true, data }, program2.opts().table);
|
|
2392
|
+
} catch (err) {
|
|
2393
|
+
handleError(err);
|
|
2394
|
+
}
|
|
2395
|
+
});
|
|
2396
|
+
related.command("add").description(
|
|
2397
|
+
"\u7ED9\u5546\u54C1\u8FFD\u52A0\u4E00\u4E2A\u5173\u8054\u77E5\u8BC6\u5E93\u6587\u4EF6\u3002\u652F\u6301 --file \u7CBE\u786E\u5339\u914D\uFF0C\u6216\u663E\u5F0F\u4F20 --file-id + --partition-id"
|
|
2398
|
+
).requiredOption("--agent <config_id>", "Agent \u914D\u7F6E ID").requiredOption("--product-id <product_id>", "\u5546\u54C1 ID").requiredOption("--type <qa|common>", "\u77E5\u8BC6\u5E93\u7C7B\u578B\uFF1Aqa \u6216 common").option("--file <exact_name>", "\u77E5\u8BC6\u5E93\u6587\u4EF6\u540D\uFF0C\u7CBE\u786E\u5339\u914D").option("--file-id <id>", "\u77E5\u8BC6\u5E93\u6587\u4EF6 ID").option("--file-name <name>", "\u77E5\u8BC6\u5E93\u6587\u4EF6\u540D\u5FEB\u7167").option("--partition-id <id>", "\u77E5\u8BC6\u5E93\u5206\u533A ID").option("--partition-name <name>", "\u77E5\u8BC6\u5E93\u5206\u533A\u540D\u5FEB\u7167").action(async (opts) => {
|
|
2399
|
+
try {
|
|
2400
|
+
const knowledgeType = parseKnowledgeType(opts.type);
|
|
2401
|
+
const file = await resolveFile({ ...opts, agentConfigId: opts.agent, knowledgeType });
|
|
2402
|
+
const current = await getProductBindingInputs({
|
|
2403
|
+
agentConfigId: opts.agent,
|
|
2404
|
+
productId: opts.productId
|
|
2405
|
+
});
|
|
2406
|
+
const byKey = new Map(current.map((item) => [bindingKey(item), item]));
|
|
2407
|
+
byKey.set(bindingKey({ knowledge_type: knowledgeType, file_id: file.fileId }), {
|
|
2408
|
+
knowledge_type: knowledgeType,
|
|
2409
|
+
file_id: file.fileId,
|
|
2410
|
+
file_name: file.fileName ?? null,
|
|
2411
|
+
partition_id: file.partitionId,
|
|
2412
|
+
partition_name: file.partitionName ?? null
|
|
2413
|
+
});
|
|
2414
|
+
const data = await replaceProductBindings({
|
|
2415
|
+
agentConfigId: opts.agent,
|
|
2416
|
+
productId: opts.productId,
|
|
2417
|
+
bindings: Array.from(byKey.values())
|
|
2418
|
+
});
|
|
2419
|
+
formatOutput({ success: true, data }, program2.opts().table);
|
|
2420
|
+
} catch (err) {
|
|
2421
|
+
handleError(err);
|
|
2422
|
+
}
|
|
2423
|
+
});
|
|
2424
|
+
related.command("remove").description("\u79FB\u9664\u5546\u54C1\u7ED1\u5B9A\u7684\u4E00\u4E2A\u77E5\u8BC6\u5E93\u6587\u4EF6\uFF1B\u76EE\u6807\u4E0D\u5B58\u5728\u65F6\u4FDD\u6301\u5E42\u7B49\u6210\u529F").requiredOption("--agent <config_id>", "Agent \u914D\u7F6E ID").requiredOption("--product-id <product_id>", "\u5546\u54C1 ID").requiredOption("--type <qa|common>", "\u77E5\u8BC6\u5E93\u7C7B\u578B\uFF1Aqa \u6216 common").requiredOption("--file-id <id>", "\u77E5\u8BC6\u5E93\u6587\u4EF6 ID").action(async (opts) => {
|
|
2425
|
+
try {
|
|
2426
|
+
const knowledgeType = parseKnowledgeType(opts.type);
|
|
2427
|
+
const fileId = parsePositiveInt(opts.fileId, "file_id");
|
|
2428
|
+
const current = await getProductBindingInputs({
|
|
2429
|
+
agentConfigId: opts.agent,
|
|
2430
|
+
productId: opts.productId
|
|
2431
|
+
});
|
|
2432
|
+
const next = current.filter(
|
|
2433
|
+
(item) => !(item.knowledge_type === knowledgeType && item.file_id === fileId)
|
|
2434
|
+
);
|
|
2435
|
+
const data = await replaceProductBindings({
|
|
2436
|
+
agentConfigId: opts.agent,
|
|
2437
|
+
productId: opts.productId,
|
|
2438
|
+
bindings: next
|
|
2439
|
+
});
|
|
2440
|
+
formatOutput({ success: true, data }, program2.opts().table);
|
|
2441
|
+
} catch (err) {
|
|
2442
|
+
handleError(err);
|
|
2443
|
+
}
|
|
2444
|
+
});
|
|
2445
|
+
related.command("set").description("\u8986\u76D6\u6307\u5B9A\u5546\u54C1\u7684\u5168\u90E8\u5173\u8054\u77E5\u8BC6\u5E93\u6587\u4EF6\u3002--bindings \u652F\u6301 JSON \u6216 @file").requiredOption("--agent <config_id>", "Agent \u914D\u7F6E ID").requiredOption("--product-id <product_id>", "\u5546\u54C1 ID").requiredOption("--bindings <json>", "\u7ED1\u5B9A\u6570\u7EC4 JSON \u6216 @\u6587\u4EF6\u8DEF\u5F84").action(async (opts) => {
|
|
2446
|
+
try {
|
|
2447
|
+
const bindings = parseBindingsOption(opts.bindings);
|
|
2448
|
+
const data = await replaceProductBindings({
|
|
2449
|
+
agentConfigId: opts.agent,
|
|
2450
|
+
productId: opts.productId,
|
|
2451
|
+
bindings
|
|
2452
|
+
});
|
|
2453
|
+
formatOutput({ success: true, data }, program2.opts().table);
|
|
2454
|
+
} catch (err) {
|
|
2455
|
+
handleError(err);
|
|
2456
|
+
}
|
|
2457
|
+
});
|
|
2458
|
+
}
|
|
2459
|
+
function registerKnowledgeFileBindProductsCommand(parent, program2, kind) {
|
|
2460
|
+
const knowledgeType = kind === "faq" ? "qa" : "common";
|
|
2461
|
+
const bind = parent.command("bind-products").description("\u77E5\u8BC6\u5E93\u6587\u4EF6\u7ED1\u5B9A\u5546\u54C1\u7BA1\u7406\uFF1Alist / add / remove / set");
|
|
2462
|
+
function addFileOptions(command) {
|
|
2463
|
+
return command.requiredOption("--agent <config_id>", "Agent \u914D\u7F6E ID").option("--file <exact_name>", "\u77E5\u8BC6\u5E93\u6587\u4EF6\u540D\uFF0C\u7CBE\u786E\u5339\u914D").option("--file-id <id>", "\u77E5\u8BC6\u5E93\u6587\u4EF6 ID").option("--file-name <name>", "\u77E5\u8BC6\u5E93\u6587\u4EF6\u540D\u5FEB\u7167").option("--partition-id <id>", "\u77E5\u8BC6\u5E93\u5206\u533A ID").option("--partition-name <name>", "\u77E5\u8BC6\u5E93\u5206\u533A\u540D\u5FEB\u7167");
|
|
2464
|
+
}
|
|
2465
|
+
bind.command("list").description("\u5217\u51FA\u6307\u5B9A\u77E5\u8BC6\u5E93\u6587\u4EF6\u7ED1\u5B9A\u7684\u5546\u54C1").requiredOption("--agent <config_id>", "Agent \u914D\u7F6E ID").option("--file <exact_name>", "\u77E5\u8BC6\u5E93\u6587\u4EF6\u540D\uFF0C\u7CBE\u786E\u5339\u914D").option("--file-id <id>", "\u77E5\u8BC6\u5E93\u6587\u4EF6 ID").option("--file-name <name>", "\u77E5\u8BC6\u5E93\u6587\u4EF6\u540D\u5FEB\u7167").option("--partition-id <id>", "\u77E5\u8BC6\u5E93\u5206\u533A ID").option("--partition-name <name>", "\u77E5\u8BC6\u5E93\u5206\u533A\u540D\u5FEB\u7167").action(async (opts) => {
|
|
2466
|
+
try {
|
|
2467
|
+
const file = await resolveFile({ ...opts, agentConfigId: opts.agent, knowledgeType });
|
|
2468
|
+
const data = await listProductKnowledgeBindings({
|
|
2469
|
+
agentConfigId: opts.agent,
|
|
2470
|
+
knowledgeType,
|
|
2471
|
+
fileId: file.fileId
|
|
2472
|
+
});
|
|
2473
|
+
formatOutput({ success: true, data }, program2.opts().table);
|
|
2474
|
+
} catch (err) {
|
|
2475
|
+
handleError(err);
|
|
2476
|
+
}
|
|
2477
|
+
});
|
|
2478
|
+
addFileOptions(
|
|
2479
|
+
bind.command("add").description("\u7ED9\u77E5\u8BC6\u5E93\u6587\u4EF6\u8FFD\u52A0\u7ED1\u5B9A\u5546\u54C1\uFF1B\u5DF2\u7ED1\u5B9A\u5546\u54C1\u4F1A\u81EA\u52A8\u53BB\u91CD").requiredOption("--product-id <id...>", "\u5546\u54C1 ID\uFF0C\u53EF\u4F20\u591A\u4E2A")
|
|
2480
|
+
).action(async (opts) => {
|
|
2481
|
+
try {
|
|
2482
|
+
const file = await resolveFile({ ...opts, agentConfigId: opts.agent, knowledgeType });
|
|
2483
|
+
const currentIds = await getFileProductIds({
|
|
2484
|
+
agentConfigId: opts.agent,
|
|
2485
|
+
knowledgeType,
|
|
2486
|
+
fileId: file.fileId
|
|
2487
|
+
});
|
|
2488
|
+
const productIds = dedupeStrings([...currentIds, ...opts.productId ?? []]);
|
|
2489
|
+
const data = await replaceFileBindings({
|
|
2490
|
+
agentConfigId: opts.agent,
|
|
2491
|
+
knowledgeType,
|
|
2492
|
+
file,
|
|
2493
|
+
productIds
|
|
2494
|
+
});
|
|
2495
|
+
formatOutput({ success: true, data }, program2.opts().table);
|
|
2496
|
+
} catch (err) {
|
|
2497
|
+
handleError(err);
|
|
2498
|
+
}
|
|
2499
|
+
});
|
|
2500
|
+
addFileOptions(
|
|
2501
|
+
bind.command("remove").description("\u4ECE\u77E5\u8BC6\u5E93\u6587\u4EF6\u79FB\u9664\u7ED1\u5B9A\u5546\u54C1\uFF1B\u76EE\u6807\u4E0D\u5B58\u5728\u65F6\u4FDD\u6301\u5E42\u7B49\u6210\u529F").requiredOption("--product-id <id...>", "\u5546\u54C1 ID\uFF0C\u53EF\u4F20\u591A\u4E2A")
|
|
2502
|
+
).action(async (opts) => {
|
|
2503
|
+
try {
|
|
2504
|
+
const file = await resolveFile({ ...opts, agentConfigId: opts.agent, knowledgeType });
|
|
2505
|
+
const removing = new Set(dedupeStrings(opts.productId ?? []));
|
|
2506
|
+
const currentIds = await getFileProductIds({
|
|
2507
|
+
agentConfigId: opts.agent,
|
|
2508
|
+
knowledgeType,
|
|
2509
|
+
fileId: file.fileId
|
|
2510
|
+
});
|
|
2511
|
+
const data = await replaceFileBindings({
|
|
2512
|
+
agentConfigId: opts.agent,
|
|
2513
|
+
knowledgeType,
|
|
2514
|
+
file,
|
|
2515
|
+
productIds: currentIds.filter((productId) => !removing.has(productId))
|
|
2516
|
+
});
|
|
2517
|
+
formatOutput({ success: true, data }, program2.opts().table);
|
|
2518
|
+
} catch (err) {
|
|
2519
|
+
handleError(err);
|
|
2520
|
+
}
|
|
2521
|
+
});
|
|
2522
|
+
addFileOptions(
|
|
2523
|
+
bind.command("set").description("\u8986\u76D6\u77E5\u8BC6\u5E93\u6587\u4EF6\u7ED1\u5B9A\u7684\u5168\u90E8\u5546\u54C1").requiredOption("--product-id <id...>", "\u5546\u54C1 ID\uFF0C\u53EF\u4F20\u591A\u4E2A")
|
|
2524
|
+
).action(async (opts) => {
|
|
2525
|
+
try {
|
|
2526
|
+
const file = await resolveFile({ ...opts, agentConfigId: opts.agent, knowledgeType });
|
|
2527
|
+
const data = await replaceFileBindings({
|
|
2528
|
+
agentConfigId: opts.agent,
|
|
2529
|
+
knowledgeType,
|
|
2530
|
+
file,
|
|
2531
|
+
productIds: dedupeStrings(opts.productId ?? [])
|
|
2532
|
+
});
|
|
2533
|
+
formatOutput({ success: true, data }, program2.opts().table);
|
|
2534
|
+
} catch (err) {
|
|
2535
|
+
handleError(err);
|
|
2536
|
+
}
|
|
2537
|
+
});
|
|
2538
|
+
}
|
|
2539
|
+
|
|
2067
2540
|
// src/commands/faq.ts
|
|
2068
2541
|
function parseQuestions(input) {
|
|
2069
2542
|
return input.split(",").map((q) => q.trim()).filter((q) => q.length > 0).map((q) => ({ content: q, keywords: [], enable: true }));
|
|
@@ -2196,6 +2669,7 @@ function registerFaqCommand(program2) {
|
|
|
2196
2669
|
process.exit(toExitCode(err));
|
|
2197
2670
|
}
|
|
2198
2671
|
});
|
|
2672
|
+
registerKnowledgeFileBindProductsCommand(faq, program2, "faq");
|
|
2199
2673
|
}
|
|
2200
2674
|
|
|
2201
2675
|
// src/client/issue-api.ts
|
|
@@ -2261,11 +2735,9 @@ async function getIssueStats(opts) {
|
|
|
2261
2735
|
const query = {};
|
|
2262
2736
|
if (opts.dateStart) query.date_start = opts.dateStart;
|
|
2263
2737
|
if (opts.dateEnd) query.date_end = opts.dateEnd;
|
|
2264
|
-
const result = await request(
|
|
2738
|
+
const result = await request(getCsAdminUrl(), "/api/issues/stats", {
|
|
2265
2739
|
method: "GET",
|
|
2266
|
-
query
|
|
2267
|
-
headers: buildCookieHeaders(),
|
|
2268
|
-
skipAuth: true
|
|
2740
|
+
query
|
|
2269
2741
|
});
|
|
2270
2742
|
return result.data ?? result;
|
|
2271
2743
|
}
|
|
@@ -2965,109 +3437,6 @@ async function resolveSessionsForIssues(issues, workspaceId) {
|
|
|
2965
3437
|
|
|
2966
3438
|
// src/commands/knowledge.ts
|
|
2967
3439
|
import fs8 from "fs";
|
|
2968
|
-
|
|
2969
|
-
// src/client/knowledge-api.ts
|
|
2970
|
-
async function listExternalKnowledge(opts) {
|
|
2971
|
-
const request = createRequest();
|
|
2972
|
-
return request(getCustomerServiceUrl(), "/v1/knowledge/external", {
|
|
2973
|
-
method: "GET",
|
|
2974
|
-
query: {
|
|
2975
|
-
customer_agent_config_id: opts.agentConfigId,
|
|
2976
|
-
page: opts.page ?? 1,
|
|
2977
|
-
page_size: opts.pageSize ?? 20,
|
|
2978
|
-
suffix_type: "_common"
|
|
2979
|
-
}
|
|
2980
|
-
});
|
|
2981
|
-
}
|
|
2982
|
-
async function listKnowledgeContents(opts) {
|
|
2983
|
-
const request = createRequest();
|
|
2984
|
-
return request(getAiApiUrl(), `/mebsuta/api/v1/dataset/${opts.knowledgeId}/contents`, {
|
|
2985
|
-
method: "GET",
|
|
2986
|
-
query: {
|
|
2987
|
-
page_size: opts.pageSize ?? 20,
|
|
2988
|
-
need_total: opts.needTotal ?? true,
|
|
2989
|
-
direction: opts.direction ?? "down"
|
|
2990
|
-
}
|
|
2991
|
-
});
|
|
2992
|
-
}
|
|
2993
|
-
async function addKnowledgeContent(opts) {
|
|
2994
|
-
const request = createRequest();
|
|
2995
|
-
const ts = (opts.now ?? Date.now)();
|
|
2996
|
-
const identifier = `temp_${ts}`;
|
|
2997
|
-
const body = {
|
|
2998
|
-
operations: [
|
|
2999
|
-
{
|
|
3000
|
-
action: "add",
|
|
3001
|
-
original_identifier: opts.afterChunkId ?? "0",
|
|
3002
|
-
identifier
|
|
3003
|
-
}
|
|
3004
|
-
],
|
|
3005
|
-
content_updates: { [identifier]: opts.content },
|
|
3006
|
-
keywords_updates: { [identifier]: opts.keywords ?? [] },
|
|
3007
|
-
extra_info_updates: { [identifier]: { chunk_status: "done" } }
|
|
3008
|
-
};
|
|
3009
|
-
return request(
|
|
3010
|
-
getAiApiUrl(),
|
|
3011
|
-
`/mebsuta/api/v1/dataset/${opts.knowledgeId}/contents/perform-operations`,
|
|
3012
|
-
{
|
|
3013
|
-
method: "POST",
|
|
3014
|
-
body
|
|
3015
|
-
}
|
|
3016
|
-
);
|
|
3017
|
-
}
|
|
3018
|
-
async function updateKnowledgeContent(opts) {
|
|
3019
|
-
const request = createRequest();
|
|
3020
|
-
const operation = {
|
|
3021
|
-
action: "update",
|
|
3022
|
-
identifier: opts.chunkId,
|
|
3023
|
-
enable: opts.enable
|
|
3024
|
-
};
|
|
3025
|
-
const contentUpdates = opts.content !== void 0 ? { [opts.chunkId]: opts.content } : {};
|
|
3026
|
-
const keywordsUpdates = opts.keywords !== void 0 ? { [opts.chunkId]: opts.keywords } : {};
|
|
3027
|
-
const extraInfoUpdates = opts.content !== void 0 || opts.keywords !== void 0 ? { [opts.chunkId]: { chunk_status: "done" } } : {};
|
|
3028
|
-
const body = {
|
|
3029
|
-
operations: [operation],
|
|
3030
|
-
content_updates: contentUpdates,
|
|
3031
|
-
keywords_updates: keywordsUpdates,
|
|
3032
|
-
extra_info_updates: extraInfoUpdates
|
|
3033
|
-
};
|
|
3034
|
-
return request(
|
|
3035
|
-
getAiApiUrl(),
|
|
3036
|
-
`/mebsuta/api/v1/dataset/${opts.knowledgeId}/contents/perform-operations`,
|
|
3037
|
-
{
|
|
3038
|
-
method: "POST",
|
|
3039
|
-
body
|
|
3040
|
-
}
|
|
3041
|
-
);
|
|
3042
|
-
}
|
|
3043
|
-
async function findKnowledgeChunk(opts) {
|
|
3044
|
-
const result = await listKnowledgeContents({
|
|
3045
|
-
knowledgeId: opts.knowledgeId,
|
|
3046
|
-
pageSize: opts.pageSize ?? 500,
|
|
3047
|
-
needTotal: true,
|
|
3048
|
-
direction: "down"
|
|
3049
|
-
});
|
|
3050
|
-
return result.contents?.find((c) => c.chunk_id === opts.chunkId);
|
|
3051
|
-
}
|
|
3052
|
-
async function deleteKnowledgeContent(opts) {
|
|
3053
|
-
const request = createRequest();
|
|
3054
|
-
const body = {
|
|
3055
|
-
operations: [{ action: "delete", identifier: opts.chunkId }],
|
|
3056
|
-
content_updates: {},
|
|
3057
|
-
keywords_updates: {},
|
|
3058
|
-
extra_info_updates: {}
|
|
3059
|
-
};
|
|
3060
|
-
return request(
|
|
3061
|
-
getAiApiUrl(),
|
|
3062
|
-
`/mebsuta/api/v1/dataset/${opts.knowledgeId}/contents/perform-operations`,
|
|
3063
|
-
{
|
|
3064
|
-
method: "POST",
|
|
3065
|
-
body
|
|
3066
|
-
}
|
|
3067
|
-
);
|
|
3068
|
-
}
|
|
3069
|
-
|
|
3070
|
-
// src/commands/knowledge.ts
|
|
3071
3440
|
function readContentArg(value) {
|
|
3072
3441
|
if (value.startsWith("@")) {
|
|
3073
3442
|
return fs8.readFileSync(value.slice(1), "utf-8");
|
|
@@ -3203,6 +3572,7 @@ function registerKnowledgeCommand(program2) {
|
|
|
3203
3572
|
process.exit(toExitCode(err));
|
|
3204
3573
|
}
|
|
3205
3574
|
});
|
|
3575
|
+
registerKnowledgeFileBindProductsCommand(knowledge, program2, "common");
|
|
3206
3576
|
}
|
|
3207
3577
|
|
|
3208
3578
|
// src/client/monitor-api.ts
|
|
@@ -3786,6 +4156,317 @@ function registerMonitorCommand(program2) {
|
|
|
3786
4156
|
});
|
|
3787
4157
|
}
|
|
3788
4158
|
|
|
4159
|
+
// src/commands/node-template.ts
|
|
4160
|
+
import { readFileSync } from "fs";
|
|
4161
|
+
|
|
4162
|
+
// src/client/node-template-api.ts
|
|
4163
|
+
function base(configId) {
|
|
4164
|
+
return `/v1/customer-agent/${configId}/customer_config/node-templates`;
|
|
4165
|
+
}
|
|
4166
|
+
async function getNodeTemplates(configId) {
|
|
4167
|
+
const request = createRequest();
|
|
4168
|
+
return request(getCustomerServiceUrl(), base(configId), {
|
|
4169
|
+
method: "GET"
|
|
4170
|
+
});
|
|
4171
|
+
}
|
|
4172
|
+
async function setNodeTemplateDraft(configId, stage, content) {
|
|
4173
|
+
const request = createRequest();
|
|
4174
|
+
return request(
|
|
4175
|
+
getCustomerServiceUrl(),
|
|
4176
|
+
`${base(configId)}/${stage}/draft`,
|
|
4177
|
+
{ method: "PUT", body: { content } }
|
|
4178
|
+
);
|
|
4179
|
+
}
|
|
4180
|
+
async function publishNodeTemplate(configId, stage) {
|
|
4181
|
+
const request = createRequest();
|
|
4182
|
+
return request(
|
|
4183
|
+
getCustomerServiceUrl(),
|
|
4184
|
+
`${base(configId)}/${stage}/publish`,
|
|
4185
|
+
{ method: "POST", body: {} }
|
|
4186
|
+
);
|
|
4187
|
+
}
|
|
4188
|
+
async function listNodeTemplateVersions(configId, stage) {
|
|
4189
|
+
const request = createRequest();
|
|
4190
|
+
return request(
|
|
4191
|
+
getCustomerServiceUrl(),
|
|
4192
|
+
`${base(configId)}/${stage}/versions`,
|
|
4193
|
+
{ method: "GET" }
|
|
4194
|
+
);
|
|
4195
|
+
}
|
|
4196
|
+
async function getNodeTemplateVersion(configId, stage, versionNo) {
|
|
4197
|
+
const request = createRequest();
|
|
4198
|
+
return request(
|
|
4199
|
+
getCustomerServiceUrl(),
|
|
4200
|
+
`${base(configId)}/${stage}/versions/${versionNo}`,
|
|
4201
|
+
{ method: "GET" }
|
|
4202
|
+
);
|
|
4203
|
+
}
|
|
4204
|
+
async function restoreNodeTemplateVersion(configId, stage, versionNo) {
|
|
4205
|
+
const request = createRequest();
|
|
4206
|
+
return request(
|
|
4207
|
+
getCustomerServiceUrl(),
|
|
4208
|
+
`${base(configId)}/${stage}/versions/${versionNo}/restore`,
|
|
4209
|
+
{ method: "POST", body: {} }
|
|
4210
|
+
);
|
|
4211
|
+
}
|
|
4212
|
+
|
|
4213
|
+
// src/lib/node-template-references.ts
|
|
4214
|
+
var NODE_TEMPLATE_REFERENCES = [
|
|
4215
|
+
// ── 数据源 fact_alias(当轮实时事实,运行时取最新数据) ──
|
|
4216
|
+
{ name: "product_data", label: "\u5546\u54C1\u4E8B\u5B9E", desc: "\u5546\u54C1\u53C2\u6570/\u5E93\u5B58/\u4EF7\u683C\u7B49\u5546\u54C1\u4E8B\u5B9E\u6570\u636E", category: "fact_alias", stages: ["tool_selector", "composer"] },
|
|
4217
|
+
{ name: "order_status", label: "\u8BA2\u5355/\u7269\u6D41\u72B6\u6001", desc: "\u8BA2\u5355\u72B6\u6001\u3001\u7269\u6D41\u8FDB\u5EA6\u7B49", category: "fact_alias", stages: ["tool_selector", "composer"] },
|
|
4218
|
+
{ name: "faq_knowledge", label: "FAQ/\u5386\u53F2\u95EE\u7B54", desc: "\u5E97\u94FA\u5E38\u89C1\u95EE\u7B54\u4E0E\u5386\u53F2\u95EE\u7B54", category: "fact_alias", stages: ["tool_selector", "composer"] },
|
|
4219
|
+
{ name: "common_knowledge", label: "\u901A\u7528\u77E5\u8BC6", desc: "\u5E97\u94FA\u901A\u7528\u77E5\u8BC6/\u8865\u5145\u77E5\u8BC6", category: "fact_alias", stages: ["tool_selector", "composer"] },
|
|
4220
|
+
{ name: "activity_knowledge", label: "\u6D3B\u52A8\u77E5\u8BC6", desc: "\u5F53\u524D\u5E97\u94FA\u6D3B\u52A8\u4FE1\u606F", category: "fact_alias", stages: ["tool_selector", "composer"] },
|
|
4221
|
+
{ name: "product_recommendation", label: "\u5546\u54C1\u63A8\u8350", desc: "\u627E\u76F8\u4F3C\u6B3E/\u63A8\u8350\u5546\u54C1", category: "fact_alias", stages: ["tool_selector", "composer"] },
|
|
4222
|
+
{ name: "size_recommendation", label: "\u5C3A\u7801\u63A8\u8350", desc: "\u6309\u8EAB\u9AD8\u4F53\u91CD\u7B49\u63A8\u8350\u5C3A\u7801", category: "fact_alias", stages: ["tool_selector", "composer"] },
|
|
4223
|
+
// ── 店铺设置 customer_slot(你在「个性化」里填的 SOP 文本,可引用进模板) ──
|
|
4224
|
+
{ name: "intent_instruction", label: "\u610F\u56FE\u8BC6\u522B\u89C4\u5219", desc: "\u4F60\u586B\u7684\u5E97\u94FA\u7EA7\u610F\u56FE\u8DEF\u7531 SOP", category: "customer_slot", stages: ["planner"] },
|
|
4225
|
+
{ name: "general_qa_instruction", label: "\u901A\u7528\u54A8\u8BE2\u8BDD\u672F", desc: "\u4F60\u586B\u7684\u901A\u7528\u54A8\u8BE2/\u5BA2\u670D\u8EAB\u4EFD SOP", category: "customer_slot", stages: ["planner", "composer"] },
|
|
4226
|
+
{ name: "recommendation_instruction", label: "\u63A8\u8350\u8BDD\u672F", desc: "\u4F60\u586B\u7684\u5546\u54C1\u63A8\u8350\u8BDD\u672F\u89C4\u5219", category: "customer_slot", stages: ["composer"] },
|
|
4227
|
+
{ name: "takeover_rule_instruction", label: "\u8F6C\u4EBA\u5DE5\u63A5\u7BA1\u7B56\u7565", desc: "\u4F60\u586B\u7684\u633D\u7559/\u8F6C\u4EBA\u5DE5\u89C4\u5219", category: "customer_slot", stages: ["planner", "composer"] },
|
|
4228
|
+
{ name: "image_rule_instruction", label: "\u56FE\u7247\u573A\u666F\u89C4\u5219", desc: "\u4F60\u586B\u7684\u56FE\u7247\u76F8\u5173\u4E1A\u52A1 SOP", category: "customer_slot", stages: ["planner", "composer", "qa_inspector"] },
|
|
4229
|
+
{ name: "forbidden_words", label: "\u8FDD\u7981\u8BCD", desc: "\u4F60\u914D\u7F6E\u7684\u8FDD\u7981\u8BCD\u6E05\u5355", category: "customer_slot", stages: ["composer"] },
|
|
4230
|
+
// ── 平台只读块 platform_block(平台运行时注入,内容锁定,作者只决定是否/在哪引用) ──
|
|
4231
|
+
{ name: "glossary_block", label: "\u672F\u8BED\u8868", desc: "\u5E73\u53F0\u672F\u8BED/\u6982\u5FF5\u5B9A\u4E49", category: "platform_block", stages: ["planner", "tool_selector", "qa_inspector"], readOnly: true },
|
|
4232
|
+
{ name: "sa_summaries_block", label: "SA \u6458\u8981\u7D22\u5F15", desc: "\u5F53\u8F6E\u547D\u4E2D\u7684\u573A\u666F\u6458\u8981\u5217\u8868", category: "platform_block", stages: ["planner"], readOnly: true },
|
|
4233
|
+
{ name: "tool_results_block", label: "\u5F53\u8F6E\u5DE5\u5177\u7ED3\u679C", desc: "\u672C\u8F6E\u5DF2\u53D6\u56DE\u7684\u5DE5\u5177\u4E8B\u5B9E\u6458\u8981", category: "platform_block", stages: ["composer", "qa_inspector"], readOnly: true },
|
|
4234
|
+
{ name: "environment_awareness_block", label: "\u73AF\u5883/\u65F6\u95F4", desc: "\u5E73\u53F0\u4E0E\u5F53\u524D\u65F6\u95F4\u4FE1\u606F", category: "platform_block", stages: ["planner", "composer", "qa_inspector"], readOnly: true },
|
|
4235
|
+
{ name: "image_understanding_rules", label: "\u56FE\u7247\u4FE1\u53F7\u89C4\u5219", desc: "\u5E73\u53F0\u56FE\u7247\u7406\u89E3\u89C4\u5219", category: "platform_block", stages: ["planner", "tool_selector", "composer", "qa_inspector"], readOnly: true },
|
|
4236
|
+
{ name: "shop_image_rule_block", label: "\u5E97\u94FA\u56FE\u7247\u89C4\u5219", desc: "\u6709\u56FE\u7247\u4FE1\u53F7\u65F6\u6CE8\u5165\u7684\u5E97\u94FA\u56FE\u7247\u89C4\u5219", category: "platform_block", stages: ["composer", "qa_inspector"], readOnly: true },
|
|
4237
|
+
// 「① 背景层下放」(spec 2026-06-08)新增 @平台块:原 ① shell 直注的背景,现作者可 @引用 / 删 / 换。
|
|
4238
|
+
{ name: "internal_terms_blacklist", label: "\u5185\u90E8\u672F\u8BED\u9ED1\u540D\u5355", desc: "\u7981\u8BCD/\u6CC4\u9732\u8BCD\u6E05\u7406\u5F15\u7528\u7684\u5185\u90E8\u672F\u8BED\u6E05\u5355", category: "platform_block", stages: ["composer", "qa_inspector"], readOnly: true },
|
|
4239
|
+
{ name: "dialog_consumption_rules", label: "\u591A\u8F6E\u6D88\u8D39\u89C4\u5219", desc: "recent_chat / \u5BF9\u8BDD\u5386\u53F2\u7684\u6D88\u8D39\u89C4\u5219", category: "platform_block", stages: ["composer", "planner"], readOnly: true },
|
|
4240
|
+
{ name: "takeover_entry_background", label: "\u63A5\u7BA1\u5165\u53E3\u80CC\u666F", desc: "\u7528\u6237\u4E3B\u52A8\u8981\u4EBA\u5DE5\u65F6\u627F\u63A5\u7684\u5E73\u53F0\u80CC\u666F\u5B9A\u4E49", category: "platform_block", stages: ["composer"], readOnly: true },
|
|
4241
|
+
{ name: "takeover_reversal_background", label: "\u63A5\u7BA1\u53CD\u8F6C\u80CC\u666F", desc: "takeover \u573A\u666F\u53CD\u8F6C\u6821\u9A8C\u7684\u5E73\u53F0\u80CC\u666F\u5B9A\u4E49", category: "platform_block", stages: ["qa_inspector"], readOnly: true },
|
|
4242
|
+
{ name: "action_description_signal_rules", label: "\u52A8\u4F5C\u63CF\u8FF0\u4FE1\u53F7\u89C4\u5219", desc: "\u8DEF\u7531\u7528\u52A8\u4F5C\u63CF\u8FF0\u4FE1\u53F7\u7684\u6D88\u8D39\u89C4\u5219", category: "platform_block", stages: ["planner"], readOnly: true },
|
|
4243
|
+
{ name: "fact_trust_rules", label: "\u4E8B\u5B9E\u4FE1\u4EFB\u5C42\u7EA7", desc: "\u5F53\u524D\u8F6E\u4E8B\u5B9E vs \u5386\u53F2\u4E8B\u5B9E\u7684\u4FE1\u4EFB\u89C4\u5219", category: "platform_block", stages: ["planner"], readOnly: true },
|
|
4244
|
+
{ name: "takeover_trigger_background", label: "\u63A5\u7BA1\u89E6\u53D1\u80CC\u666F", desc: "\u5E97\u94FA\u8F6C\u4EBA\u5DE5\u63A5\u7BA1\u89E6\u53D1\u6761\u4EF6\u80CC\u666F\u5B9A\u4E49", category: "platform_block", stages: ["planner"], readOnly: true }
|
|
4245
|
+
];
|
|
4246
|
+
var ALL_REFERENCE_NAMES = NODE_TEMPLATE_REFERENCES.map((r) => r.name);
|
|
4247
|
+
function referencesForStage(stage) {
|
|
4248
|
+
return NODE_TEMPLATE_REFERENCES.filter((r) => r.stages.includes(stage));
|
|
4249
|
+
}
|
|
4250
|
+
var NODE_CHARTERS = {
|
|
4251
|
+
planner: {
|
|
4252
|
+
role: "\u610F\u56FE\u8BC6\u522B / \u8DEF\u7531\u8282\u70B9\uFF1A\u5224\u5B9A\u672C\u8F6E\u8D70\u5B8C\u6574\u4E1A\u52A1\u94FE\u8DEF\u8FD8\u662F\u8F6C\u4EBA\u5DE5\uFF0C\u5E76\u4EA7\u51FA\u300CSA \u6458\u8981 \u2192 \u547D\u4E2D scene\u300D\u7684\u8DEF\u7531\u3002",
|
|
4253
|
+
editable: "\u2461 \u4F5C\u8005\u6B63\u6587\uFF1A\u8DEF\u7531\u5224\u65AD\u903B\u8F91\u3001\u8DEF\u7531\u7EAA\u5F8B\u3001\u552E\u540E\u573A\u666F\u5224\u65AD\u3001@\u5F15\u7528\u5E97\u94FA\u610F\u56FE/\u63A5\u7BA1 SOP\u3002",
|
|
4254
|
+
mustOutput: "JSON \u5BF9\u8C61 {d, a, r}\uFF1Ad=\u51B3\u7B56\u7F16\u7801\uFF08business_full\u21922 / transfer\u21923\uFF09\uFF0Ca=\u662F\u5426\u552E\u540E\u573A\u666F\uFF08bool\uFF09\uFF0Cr=\u53CC\u4E0B\u6807\u8DEF\u7531\u6570\u7EC4 [[sa, sc], ...]\u3002\u683C\u5F0F\u7531\u5E73\u53F0 \u2462 \u9501\u5B9A\u2014\u2014\u4F60\u7684\u6B63\u6587\u7528\u51B3\u7B56\u540D\u5224\u65AD\u5373\u53EF\uFF0C\u4E0D\u8981\u81EA\u9020\u8F93\u51FA\u683C\u5F0F\u3002",
|
|
4255
|
+
locked: ["\u2462 \u8F93\u51FA\u5951\u7EA6 / JSON Schema\uFF08{d,a,r} \u7F16\u7801\u4E0E r \u53CC\u4E0B\u6807\u89C4\u5219\uFF09", "\u2463 \u8FD0\u884C\u65F6\u6570\u636E\u533A\uFF08SA \u6458\u8981 / \u8DEF\u7531\u4FE1\u53F7 / \u73AF\u5883\u65F6\u95F4\uFF0C\u6BCF\u8F6E\u81EA\u52A8\u6CE8\u5165\uFF09"]
|
|
4256
|
+
},
|
|
4257
|
+
composer: {
|
|
4258
|
+
role: "\u6210\u6587\u8282\u70B9\uFF1A\u4F9D\u636E\u5F53\u8F6E\u4E8B\u5B9E/\u6D41\u7A0B\uFF0C\u751F\u6210\u6700\u7EC8\u53D1\u7ED9\u7528\u6237\u7684\u5BA2\u670D\u8BDD\u672F\uFF08\u542B\u8F6C\u4EBA\u5DE5\u4FE1\u53F7\uFF09\u3002",
|
|
4259
|
+
editable: "\u2461 \u4F5C\u8005\u6B63\u6587\uFF1A\u56DE\u590D\u7B56\u7565\u3001\u8C03\u6027\u3001\u4E8B\u5B9E\u6D88\u8D39\u89C4\u5219\u3001@\u5F15\u7528\u5E97\u94FA\u901A\u7528\u8BDD\u672F/\u63A8\u8350/\u63A5\u7BA1 SOP\u3002",
|
|
4260
|
+
mustOutput: "JSON \u5BF9\u8C61 {messages:[...], transfer_to_human:bool}\uFF1Amessages \u4E3A\u7EAF\u6587\u672C\u6D88\u606F\u6570\u7EC4\uFF08\u56FE\u7247 URL \u5355\u72EC\u6210\u6761\uFF09\uFF0C\u8F6C\u4EBA\u5DE5\u7F6E transfer_to_human=true\u3002\u683C\u5F0F\u7531\u5E73\u53F0 \u2462 \u9501\u5B9A\u3002",
|
|
4261
|
+
locked: ["\u2462 \u8F93\u51FA\u5951\u7EA6 / JSON Schema\uFF08messages + transfer_to_human + \u5E73\u53F0\u8C03\u6027\u793A\u4F8B\uFF09", "\u2463 \u8FD0\u884C\u65F6\u6570\u636E\u533A\uFF08\u5DE5\u5177\u7ED3\u679C / SA action / \u4E8B\u5B9E\u5206\u7EA7\uFF0C\u6BCF\u8F6E\u81EA\u52A8\u6CE8\u5165\uFF09"]
|
|
4262
|
+
},
|
|
4263
|
+
qa_inspector: {
|
|
4264
|
+
role: "\u8D28\u68C0\u8282\u70B9\uFF1A\u5BF9 composer \u4EA7\u51FA\u7684\u7528\u6237\u53EF\u89C1\u56DE\u590D\u505A\u5408\u89C4/\u91CD\u590D\u6821\u9A8C\uFF0C\u51B3\u5B9A\u653E\u884C / \u6539\u5199 / \u8F6C\u4EBA\u5DE5\u3002",
|
|
4265
|
+
editable: "\u2461 \u4F5C\u8005\u6B63\u6587\uFF1A\u5224\u5B9A\u6807\u51C6\uFF08\u4F55\u4E3A\u5408\u683C / \u95EE\u9898 / \u8BED\u4E49\u91CD\u590D / \u8BE5\u8F6C\u4EBA\u5DE5\uFF09\u3001\u6E05\u7406\u89C4\u5219\u3001@\u5F15\u7528\u56FE\u7247\u89C4\u5219\u3002",
|
|
4266
|
+
mustOutput: '\u7ED3\u8BBA\u6309\u5E73\u53F0 \u2462 \u7F16\u7801\uFF1A\u5408\u683C\u2192`0`\uFF0C\u8BED\u4E49\u91CD\u590D\u2192`-1`\uFF0C\u6539\u5199\u2192`{"messages":[...]}`\uFF0C\u8F6C\u4EBA\u5DE5\u2192`{"messages":[...,"TRANSFER"]}`\uFF08\u672B\u9879\u6052\u4E3A "TRANSFER"\uFF09\u3002\u2462 \u53EA\u5B9A\u4E49\u300C\u7ED3\u8BBA\u2192\u7F16\u7801\u300D\u63A5\u53E3\uFF0C\u5224\u5B9A\u6807\u51C6\u5168\u5728\u4F60\u7684\u6B63\u6587\u3002',
|
|
4267
|
+
locked: ["\u2462 \u8F93\u51FA\u5951\u7EA6\uFF08\u7ED3\u8BBA\u2192\u7F16\u7801\uFF1A0 / -1 / JSON / TRANSFER \u534F\u8BAE\uFF09", "\u2463 \u8FD0\u884C\u65F6\u6570\u636E\u533A\uFF08\u73AF\u5883 / \u65F6\u95F4\uFF0C\u6BCF\u8F6E\u81EA\u52A8\u6CE8\u5165\uFF09"]
|
|
4268
|
+
},
|
|
4269
|
+
// 伪 stage(spec 2026-06-08):不是产出完整 system prompt 的真节点,而是被 planner/tool_selector/
|
|
4270
|
+
// composer/qa 四节点共享注入的「图片处理方法论」片段。
|
|
4271
|
+
image_understanding: {
|
|
4272
|
+
role: "\u56FE\u7247\u7406\u89E3\u65B9\u6CD5\u8BBA\uFF08\u4F2A stage\uFF09\uFF1A\u5B9A\u4E49\u770B\u5230\u56FE\u7247\u540E\u600E\u4E48\u63D0\u53D6\u4E8B\u5B9E / \u7ED3\u5408\u610F\u56FE / \u8DEF\u7531\uFF0C\u88AB 4 \u4E2A\u8282\u70B9\u5171\u4EAB\u6CE8\u5165\u3002",
|
|
4273
|
+
editable: "\u6574\u6BB5\u65B9\u6CD5\u8BBA\uFF1A\u56FE\u7247\u4E09\u6B65\u6D41\u7A0B\u7684\u63AA\u8F9E\u3001\u5E97\u94FA\u8BC6\u522B\u8868 / \u6613\u6DF7\u6DC6\u89C4\u5219 / \u56DE\u7B54\u5185\u5BB9\u5E93\u3002\u6BCF\u5BB6\u5E97\u56FE\u7247\u4E1A\u52A1\u4E0D\u540C\uFF0C\u53EF\u81EA\u7531\u6539\u5199\u3002",
|
|
4274
|
+
mustOutput: "\u65E0\u72EC\u7ACB\u8F93\u51FA\u5951\u7EA6\u2014\u2014\u672C\u914D\u7F6E\u662F\u88AB\u6CE8\u5165\u8FDB {{image_understanding_rules}} \u7684\u65B9\u6CD5\u8BBA\u7247\u6BB5\uFF0C\u4E0D\u4EA7\u51FA JSON\u3002\u9501\u5B9A\u7684\u54C1\u724C\u5F52\u5C5E\u7EA2\u7EBF / \u56FE\u7247\u4E8B\u5B9E\u7EA2\u7EBF / \u56FE\u7247\u5448\u73B0\u673A\u5236\u7531\u5E73\u53F0 code-assemble \u5305\u88F9\uFF0C\u4E0D\u5728\u4F60\u7684\u53EF\u7F16\u8F91\u5185\u5BB9\u91CC\u3001\u4E5F\u65E0\u6CD5\u88AB\u5220\u6539\u3002",
|
|
4275
|
+
locked: ["\u54C1\u724C\u5F52\u5C5E\u7EA2\u7EBF\uFF08\u4EC5 composer/qa reply \u8282\u70B9 code-assemble\uFF09", "\u56FE\u7247\u4E8B\u5B9E\u7EA2\u7EBF reply_fact\uFF08\u542B\u7EAF\u56FE\u5148\u6F84\u6E05\uFF0C\u4EC5 reply \u8282\u70B9\uFF09", "\u56FE\u7247\u5448\u73B0\u673A\u5236\uFF08\u6700\u8FD1\u56FE\u7247\u76F4\u63A5\u770B / \u66F4\u65E9\u56FE\u7247 [\u5386\u53F2\u56FE\u7247] \u5360\u4F4D\uFF09"]
|
|
4276
|
+
}
|
|
4277
|
+
};
|
|
4278
|
+
var EDITING_RULES = "\u6B63\u6587\u91CC @\u5F15\u7528 \u5199 {{name}}\uFF08\u4EC5 ASCII \u6807\u8BC6\u7B26\u88AB\u89E3\u6790\uFF1B\u4E2D\u6587/\u591A\u8BCD\u6309\u5B57\u9762\u6587\u672C\u4E0D\u89E3\u6790\uFF09\uFF1B\u53EA\u80FD\u5F15\u7528 variables \u91CC\u7684 name\uFF1B\u2462\u2463 \u5E73\u53F0\u9501\u5B9A\u3001\u4E0D\u51FA\u73B0\u5728\u4F60\u7684\u6B63\u6587\u91CC\uFF0C\u522B\u5C1D\u8BD5\u6539\uFF1B\u7A7A\u4E32\u8349\u7A3F = \u56DE\u843D\u5E73\u53F0\u51FA\u5382\u9ED8\u8BA4\u3002";
|
|
4279
|
+
function buildNodeDescribe(stage) {
|
|
4280
|
+
const charter = NODE_CHARTERS[stage];
|
|
4281
|
+
if (!charter) {
|
|
4282
|
+
throw new Error(`\u65E0\u8BE5\u8282\u70B9 charter\uFF1A${stage}`);
|
|
4283
|
+
}
|
|
4284
|
+
return {
|
|
4285
|
+
stage,
|
|
4286
|
+
charter,
|
|
4287
|
+
variables: referencesForStage(stage).map((r) => ({
|
|
4288
|
+
name: r.name,
|
|
4289
|
+
label: r.label,
|
|
4290
|
+
desc: r.desc,
|
|
4291
|
+
category: r.category,
|
|
4292
|
+
readOnly: !!r.readOnly
|
|
4293
|
+
})),
|
|
4294
|
+
editing_rules: EDITING_RULES
|
|
4295
|
+
};
|
|
4296
|
+
}
|
|
4297
|
+
|
|
4298
|
+
// src/utils/node-template-validate.ts
|
|
4299
|
+
var EXPOSED_NODE_STAGES = ["planner", "composer", "qa_inspector", "image_understanding"];
|
|
4300
|
+
function isExposedStage(stage) {
|
|
4301
|
+
return EXPOSED_NODE_STAGES.includes(stage);
|
|
4302
|
+
}
|
|
4303
|
+
var INTERP_RE = /\{\{\s*([A-Za-z_][A-Za-z0-9_]*)\s*\}\}/g;
|
|
4304
|
+
function extractInterpolationNames(text) {
|
|
4305
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4306
|
+
const out = [];
|
|
4307
|
+
for (const m of text.matchAll(INTERP_RE)) {
|
|
4308
|
+
const name = m[1];
|
|
4309
|
+
if (!seen.has(name)) {
|
|
4310
|
+
seen.add(name);
|
|
4311
|
+
out.push(name);
|
|
4312
|
+
}
|
|
4313
|
+
}
|
|
4314
|
+
return out;
|
|
4315
|
+
}
|
|
4316
|
+
function computeUnknownNames(content, factoryDefault) {
|
|
4317
|
+
const legal = /* @__PURE__ */ new Set([
|
|
4318
|
+
...ALL_REFERENCE_NAMES,
|
|
4319
|
+
...extractInterpolationNames(factoryDefault)
|
|
4320
|
+
]);
|
|
4321
|
+
return extractInterpolationNames(content).filter((n) => !legal.has(n));
|
|
4322
|
+
}
|
|
4323
|
+
|
|
4324
|
+
// src/commands/node-template.ts
|
|
4325
|
+
var STAGE_HINT = EXPOSED_NODE_STAGES.join("|");
|
|
4326
|
+
function assertStage(stage) {
|
|
4327
|
+
if (!isExposedStage(stage)) {
|
|
4328
|
+
throw new Error(`\u4E0D\u652F\u6301\u7684\u8282\u70B9\uFF1A${stage}\uFF08\u5F53\u524D\u53EF\u7528\uFF1A${STAGE_HINT}\uFF09`);
|
|
4329
|
+
}
|
|
4330
|
+
return stage;
|
|
4331
|
+
}
|
|
4332
|
+
function parseVersionNo(raw) {
|
|
4333
|
+
const n = Number(raw);
|
|
4334
|
+
if (!Number.isInteger(n) || n <= 0) {
|
|
4335
|
+
throw new Error(`\u975E\u6CD5\u7684 version_no: ${raw}\uFF08\u5FC5\u987B\u4E3A\u6B63\u6574\u6570\uFF09`);
|
|
4336
|
+
}
|
|
4337
|
+
return n;
|
|
4338
|
+
}
|
|
4339
|
+
function resolveContent(opts) {
|
|
4340
|
+
const provided = [opts.content !== void 0, !!opts.contentFile, !!opts.stdin].filter(Boolean).length;
|
|
4341
|
+
if (provided !== 1) {
|
|
4342
|
+
throw new Error("\u5185\u5BB9\u6765\u6E90\u987B\u6070\u597D\u4E00\u4E2A\uFF1A--content <\u6587\u672C> | --content-file <\u8DEF\u5F84> | --stdin");
|
|
4343
|
+
}
|
|
4344
|
+
if (opts.content !== void 0) return opts.content;
|
|
4345
|
+
if (opts.contentFile) return readFileSync(opts.contentFile, "utf8");
|
|
4346
|
+
return readFileSync(0, "utf8");
|
|
4347
|
+
}
|
|
4348
|
+
function registerNodeTemplateCommand(program2) {
|
|
4349
|
+
const nt = program2.command("node-template").description(
|
|
4350
|
+
`\u8282\u70B9\u6A21\u677F\uFF08\u9AD8\u7EA7\u6A21\u677F\uFF09\u64CD\u4F5C \u2014\u2014 \u83B7\u53D6\u5185\u5BB9\u3001\u6539\u52A8\u53D1\u5E03\u3001\u5386\u53F2/\u56DE\u6EAF\u3002\u8282\u70B9 stage\uFF1A${STAGE_HINT}\uFF08tool_selector \u6682\u4E0D\u653E\u51FA\uFF09\u3002\u9AD8\u7EA7\u6A21\u5F0F\u5F00\u5173\u5DF2\u6539\u4E3A\u5BA2\u6237\u81EA\u52A9\uFF08cs-client \u5185\u5F00\u5173\uFF09\uFF0CCLI \u4E0D\u518D\u63D0\u4F9B enroll \u5F00\u542F\u8DEF\u5F84\u3002\u670D\u52A1\u7AEF\uFF1Acustomer-servhub-api /v1/customer-agent/{config_id}/customer_config/node-templates*\uFF1B\u5951\u7EA6 docs/devkit/specs/2026-06-08-\u8282\u70B9\u6A21\u677F-cli-\u64CD\u4F5C\u9762.md`
|
|
4351
|
+
);
|
|
4352
|
+
nt.command("describe").description(
|
|
4353
|
+
`\u8282\u70B9\u7F16\u5199\u8BF4\u660E\u4E66\uFF08AI \u7F16\u5199\u524D\u5FC5\u8BFB\uFF09\uFF1A\u6BCF\u4E2A\u8282\u70B9\u7684\u804C\u8D23/\u53EF\u7F16\u8F91\u9762/\u8F93\u51FA\u5951\u7EA6/\u5E73\u53F0\u9501\u5B9A\u6BB5 + \u672C\u8282\u70B9\u53EF @\u5F15\u7528 \u7684\u53D8\u91CF\u76EE\u5F55\u3002\u4E0D\u4F20 --stage = \u5168\u90E8\u5DF2\u5F00\u653E\u8282\u70B9\uFF08${STAGE_HINT}\uFF09\u3002\u7EAF\u9759\u6001\u3001\u4E0E\u5177\u4F53 agent \u65E0\u5173\uFF0C\u65E0\u9700 --agent\u3002`
|
|
4354
|
+
).option("--stage <stage>", `\u5355\u8282\u70B9\uFF1A${STAGE_HINT}`).action((opts) => {
|
|
4355
|
+
try {
|
|
4356
|
+
if (opts.stage) {
|
|
4357
|
+
const stage = assertStage(opts.stage);
|
|
4358
|
+
formatOutput({ success: true, data: buildNodeDescribe(stage) }, program2.opts().table);
|
|
4359
|
+
return;
|
|
4360
|
+
}
|
|
4361
|
+
const data = EXPOSED_NODE_STAGES.map((s) => buildNodeDescribe(s));
|
|
4362
|
+
formatOutput({ success: true, data }, program2.opts().table);
|
|
4363
|
+
} catch (err) {
|
|
4364
|
+
reportCaughtError(err);
|
|
4365
|
+
process.exit(toExitCode(err));
|
|
4366
|
+
}
|
|
4367
|
+
});
|
|
4368
|
+
nt.command("get").description("\u83B7\u53D6\u8282\u70B9\u6A21\u677F\u5185\u5BB9\uFF08\u4E0D\u4F20 --stage=\u5168\u90E8\u5DF2\u5F00\u653E\u8282\u70B9\uFF1Btool_selector \u4E00\u5F8B\u6EE4\u9664\uFF09").requiredOption("--agent <id>", "customer_agent_config_id").option("--stage <stage>", `\u5355\u8282\u70B9\u8FC7\u6EE4\uFF1A${STAGE_HINT}`).action(async (opts) => {
|
|
4369
|
+
try {
|
|
4370
|
+
const payload = await getNodeTemplates(opts.agent);
|
|
4371
|
+
if (opts.stage) {
|
|
4372
|
+
const stage = assertStage(opts.stage);
|
|
4373
|
+
const data2 = {
|
|
4374
|
+
config_id: payload.config_id,
|
|
4375
|
+
stage,
|
|
4376
|
+
node: payload.nodes?.[stage],
|
|
4377
|
+
factory_default: payload.factory_defaults?.[stage] ?? ""
|
|
4378
|
+
};
|
|
4379
|
+
formatOutput({ success: true, data: data2 }, program2.opts().table);
|
|
4380
|
+
return;
|
|
4381
|
+
}
|
|
4382
|
+
const exposed = new Set(EXPOSED_NODE_STAGES);
|
|
4383
|
+
const nodes = {};
|
|
4384
|
+
for (const [k, v] of Object.entries(payload.nodes ?? {})) {
|
|
4385
|
+
if (exposed.has(k)) nodes[k] = v;
|
|
4386
|
+
}
|
|
4387
|
+
const factory = {};
|
|
4388
|
+
for (const [k, v] of Object.entries(payload.factory_defaults ?? {})) {
|
|
4389
|
+
if (exposed.has(k)) factory[k] = v;
|
|
4390
|
+
}
|
|
4391
|
+
const data = {
|
|
4392
|
+
config_id: payload.config_id,
|
|
4393
|
+
stages: (payload.stages ?? []).filter((s) => exposed.has(s)),
|
|
4394
|
+
nodes,
|
|
4395
|
+
factory_defaults: factory
|
|
4396
|
+
};
|
|
4397
|
+
formatOutput({ success: true, data }, program2.opts().table);
|
|
4398
|
+
} catch (err) {
|
|
4399
|
+
reportCaughtError(err);
|
|
4400
|
+
process.exit(toExitCode(err));
|
|
4401
|
+
}
|
|
4402
|
+
});
|
|
4403
|
+
nt.command("set-draft").description("\u5199\u5355\u8282\u70B9\u8349\u7A3F\uFF08\u6574\u6BB5\u8986\u76D6\uFF1B\u7A7A\u4E32=\u56DE\u843D\u51FA\u5382\u9ED8\u8BA4\uFF09\u3002\u5185\u5BB9\u4E09\u9009\u4E00\uFF0C\u957F prompt \u5EFA\u8BAE --content-file").requiredOption("--agent <id>", "customer_agent_config_id").requiredOption("--stage <stage>", `\u8282\u70B9\uFF1A${STAGE_HINT}`).option("--content <text>", "\u5185\u8054\u6B63\u6587").option("--content-file <path>", "\u4ECE\u6587\u4EF6\u8BFB\u6B63\u6587").option("--stdin", "\u4ECE\u6807\u51C6\u8F93\u5165\u8BFB\u6B63\u6587", false).action(async (opts) => {
|
|
4404
|
+
try {
|
|
4405
|
+
const stage = assertStage(opts.stage);
|
|
4406
|
+
const content = resolveContent(opts);
|
|
4407
|
+
const data = await setNodeTemplateDraft(opts.agent, stage, content);
|
|
4408
|
+
formatOutput({ success: true, data }, program2.opts().table);
|
|
4409
|
+
} catch (err) {
|
|
4410
|
+
reportCaughtError(err);
|
|
4411
|
+
process.exit(toExitCode(err));
|
|
4412
|
+
}
|
|
4413
|
+
});
|
|
4414
|
+
nt.command("publish").description("\u53D1\u5E03\u8BE5\u8282\u70B9\u5F53\u524D\u8349\u7A3F\u4E0A\u7EBF\uFF08\u53D1\u5E03\u524D\u6821\u9A8C {{}} \u5408\u6CD5\u6027\uFF0C\u4E0D\u5408\u6CD5\u62D2\u7EDD\uFF1B--force \u8D8A\u8FC7\u6821\u9A8C\uFF09").requiredOption("--agent <id>", "customer_agent_config_id").requiredOption("--stage <stage>", `\u8282\u70B9\uFF1A${STAGE_HINT}`).option("--force", "\u8DF3\u8FC7 {{}} \u5408\u6CD5\u6027\u6821\u9A8C\u76F4\u63A5\u53D1\u5E03", false).action(async (opts) => {
|
|
4415
|
+
try {
|
|
4416
|
+
const stage = assertStage(opts.stage);
|
|
4417
|
+
if (!opts.force) {
|
|
4418
|
+
const payload = await getNodeTemplates(opts.agent);
|
|
4419
|
+
const node = payload.nodes?.[stage];
|
|
4420
|
+
const draft = node?.content ?? "";
|
|
4421
|
+
const factory = payload.factory_defaults?.[stage] ?? "";
|
|
4422
|
+
const unknown = computeUnknownNames(draft, factory);
|
|
4423
|
+
if (unknown.length > 0) {
|
|
4424
|
+
throw new Error(
|
|
4425
|
+
`\u8349\u7A3F\u542B\u975E\u6CD5\u63D2\u503C\u540D\uFF0C\u62D2\u7EDD\u53D1\u5E03\uFF1A${unknown.map((n) => `{{${n}}}`).join(" ")}\u3002\u8BF7\u4FEE\u6B63\u4E3A\u5408\u6CD5\u5F15\u7528\u540D\uFF0C\u6216\u786E\u8BA4\u65E0\u8BEF\u540E\u52A0 --force \u8D8A\u8FC7\u6821\u9A8C\u3002`
|
|
4426
|
+
);
|
|
4427
|
+
}
|
|
4428
|
+
}
|
|
4429
|
+
const data = await publishNodeTemplate(opts.agent, stage);
|
|
4430
|
+
formatOutput({ success: true, data }, program2.opts().table);
|
|
4431
|
+
} catch (err) {
|
|
4432
|
+
reportCaughtError(err);
|
|
4433
|
+
process.exit(toExitCode(err));
|
|
4434
|
+
}
|
|
4435
|
+
});
|
|
4436
|
+
nt.command("versions").description("\u5217\u8BE5\u8282\u70B9\u5386\u53F2\u7248\u672C\u65F6\u95F4\u7EBF").requiredOption("--agent <id>", "customer_agent_config_id").requiredOption("--stage <stage>", `\u8282\u70B9\uFF1A${STAGE_HINT}`).action(async (opts) => {
|
|
4437
|
+
try {
|
|
4438
|
+
const stage = assertStage(opts.stage);
|
|
4439
|
+
const data = await listNodeTemplateVersions(opts.agent, stage);
|
|
4440
|
+
formatOutput({ success: true, data }, program2.opts().table);
|
|
4441
|
+
} catch (err) {
|
|
4442
|
+
reportCaughtError(err);
|
|
4443
|
+
process.exit(toExitCode(err));
|
|
4444
|
+
}
|
|
4445
|
+
});
|
|
4446
|
+
nt.command("version").description("\u53D6\u8BE5\u8282\u70B9\u67D0\u7248\u672C\u6B63\u6587\uFF08\u9884\u89C8/diff\uFF09").requiredOption("--agent <id>", "customer_agent_config_id").requiredOption("--stage <stage>", `\u8282\u70B9\uFF1A${STAGE_HINT}`).requiredOption("--version <no>", "\u7248\u672C\u53F7\uFF08\u6B63\u6574\u6570\uFF09").action(async (opts) => {
|
|
4447
|
+
try {
|
|
4448
|
+
const stage = assertStage(opts.stage);
|
|
4449
|
+
const versionNo = parseVersionNo(opts.version);
|
|
4450
|
+
const data = await getNodeTemplateVersion(opts.agent, stage, versionNo);
|
|
4451
|
+
formatOutput({ success: true, data }, program2.opts().table);
|
|
4452
|
+
} catch (err) {
|
|
4453
|
+
reportCaughtError(err);
|
|
4454
|
+
process.exit(toExitCode(err));
|
|
4455
|
+
}
|
|
4456
|
+
});
|
|
4457
|
+
nt.command("restore").description("\u628A\u8BE5\u8282\u70B9\u67D0\u5386\u53F2\u7248\u672C\u590D\u5236\u6210\u8349\u7A3F\uFF08\u4E0D\u76F4\u63A5\u751F\u6548\uFF0C\u9700\u518D publish\uFF09").requiredOption("--agent <id>", "customer_agent_config_id").requiredOption("--stage <stage>", `\u8282\u70B9\uFF1A${STAGE_HINT}`).requiredOption("--version <no>", "\u8981\u56DE\u6EAF\u5230\u7684\u7248\u672C\u53F7\uFF08\u6B63\u6574\u6570\uFF09").action(async (opts) => {
|
|
4458
|
+
try {
|
|
4459
|
+
const stage = assertStage(opts.stage);
|
|
4460
|
+
const versionNo = parseVersionNo(opts.version);
|
|
4461
|
+
const data = await restoreNodeTemplateVersion(opts.agent, stage, versionNo);
|
|
4462
|
+
formatOutput({ success: true, data }, program2.opts().table);
|
|
4463
|
+
} catch (err) {
|
|
4464
|
+
reportCaughtError(err);
|
|
4465
|
+
process.exit(toExitCode(err));
|
|
4466
|
+
}
|
|
4467
|
+
});
|
|
4468
|
+
}
|
|
4469
|
+
|
|
3789
4470
|
// src/client/ops-agent-api.ts
|
|
3790
4471
|
async function listOpsAgentConversations(opts) {
|
|
3791
4472
|
const workspaceId = getWorkspaceId(opts.workspaceId);
|
|
@@ -3825,7 +4506,7 @@ function registerOpsAgentCommand(program2) {
|
|
|
3825
4506
|
}
|
|
3826
4507
|
|
|
3827
4508
|
// src/client/operations-record-api.ts
|
|
3828
|
-
var
|
|
4509
|
+
var PATH_PREFIX3 = "/v1/agent_operations_records";
|
|
3829
4510
|
async function listOperationsRecords(opts) {
|
|
3830
4511
|
const request = createRequest();
|
|
3831
4512
|
const query = {};
|
|
@@ -3833,34 +4514,34 @@ async function listOperationsRecords(opts) {
|
|
|
3833
4514
|
if (opts.agentId) query.agent_id = opts.agentId;
|
|
3834
4515
|
if (opts.page) query.page = opts.page;
|
|
3835
4516
|
if (opts.pageSize) query.page_size = opts.pageSize;
|
|
3836
|
-
return request(getCustomerServiceUrl(),
|
|
4517
|
+
return request(getCustomerServiceUrl(), PATH_PREFIX3, {
|
|
3837
4518
|
method: "GET",
|
|
3838
4519
|
query
|
|
3839
4520
|
});
|
|
3840
4521
|
}
|
|
3841
4522
|
async function getOperationsRecord(recordId) {
|
|
3842
4523
|
const request = createRequest();
|
|
3843
|
-
return request(getCustomerServiceUrl(), `${
|
|
4524
|
+
return request(getCustomerServiceUrl(), `${PATH_PREFIX3}/${recordId}`, {
|
|
3844
4525
|
method: "GET"
|
|
3845
4526
|
});
|
|
3846
4527
|
}
|
|
3847
4528
|
async function createOperationsRecord(data) {
|
|
3848
4529
|
const request = createRequest();
|
|
3849
|
-
return request(getCustomerServiceUrl(),
|
|
4530
|
+
return request(getCustomerServiceUrl(), PATH_PREFIX3, {
|
|
3850
4531
|
method: "POST",
|
|
3851
4532
|
body: data
|
|
3852
4533
|
});
|
|
3853
4534
|
}
|
|
3854
4535
|
async function updateOperationsRecord(recordId, data) {
|
|
3855
4536
|
const request = createRequest();
|
|
3856
|
-
return request(getCustomerServiceUrl(), `${
|
|
4537
|
+
return request(getCustomerServiceUrl(), `${PATH_PREFIX3}/${recordId}`, {
|
|
3857
4538
|
method: "PUT",
|
|
3858
4539
|
body: data
|
|
3859
4540
|
});
|
|
3860
4541
|
}
|
|
3861
4542
|
async function deleteOperationsRecord(recordId) {
|
|
3862
4543
|
const request = createRequest();
|
|
3863
|
-
return request(getCustomerServiceUrl(), `${
|
|
4544
|
+
return request(getCustomerServiceUrl(), `${PATH_PREFIX3}/${recordId}`, {
|
|
3864
4545
|
method: "DELETE"
|
|
3865
4546
|
});
|
|
3866
4547
|
}
|
|
@@ -4247,10 +4928,11 @@ function registerProductCommand(program2) {
|
|
|
4247
4928
|
process.exit(toExitCode(err));
|
|
4248
4929
|
}
|
|
4249
4930
|
});
|
|
4931
|
+
registerProductRelatedKnowledgeCommand(product, program2);
|
|
4250
4932
|
}
|
|
4251
4933
|
|
|
4252
4934
|
// src/client/repair-record-api.ts
|
|
4253
|
-
var
|
|
4935
|
+
var PATH_PREFIX4 = "/api/repair-records";
|
|
4254
4936
|
async function listRepairRecords(opts) {
|
|
4255
4937
|
const request = createRequest();
|
|
4256
4938
|
const query = {};
|
|
@@ -4259,21 +4941,21 @@ async function listRepairRecords(opts) {
|
|
|
4259
4941
|
if (opts.workspaceId) query.workspace_id = opts.workspaceId;
|
|
4260
4942
|
if (opts.page) query.page = opts.page;
|
|
4261
4943
|
if (opts.pageSize) query.page_size = opts.pageSize;
|
|
4262
|
-
return request(getCsAdminUrl(),
|
|
4944
|
+
return request(getCsAdminUrl(), PATH_PREFIX4, {
|
|
4263
4945
|
method: "GET",
|
|
4264
4946
|
query
|
|
4265
4947
|
});
|
|
4266
4948
|
}
|
|
4267
4949
|
async function createRepairRecord(data) {
|
|
4268
4950
|
const request = createRequest();
|
|
4269
|
-
return request(getCsAdminUrl(),
|
|
4951
|
+
return request(getCsAdminUrl(), PATH_PREFIX4, {
|
|
4270
4952
|
method: "POST",
|
|
4271
4953
|
body: data
|
|
4272
4954
|
});
|
|
4273
4955
|
}
|
|
4274
4956
|
async function updateRepairRecord(recordId, data) {
|
|
4275
4957
|
const request = createRequest();
|
|
4276
|
-
return request(getCsAdminUrl(), `${
|
|
4958
|
+
return request(getCsAdminUrl(), `${PATH_PREFIX4}/${recordId}`, {
|
|
4277
4959
|
method: "PUT",
|
|
4278
4960
|
body: data
|
|
4279
4961
|
});
|
|
@@ -5350,6 +6032,23 @@ function registerWorkspaceCommand(program2) {
|
|
|
5350
6032
|
process.exit(toExitCode(err));
|
|
5351
6033
|
}
|
|
5352
6034
|
});
|
|
6035
|
+
workspace.command("points-consumes").description("\u5206\u9875\u67E5\u8BE2\u5F53\u524D\u5DE5\u4F5C\u7A7A\u95F4\u7684\u79EF\u5206\u8D26\u6237\u6D88\u8017\u6D41\u6C34\uFF0C\u56FA\u5B9A\u8FD4\u56DE extra \u8C03\u8BD5\u5B57\u6BB5").option("--page <number>", "\u9875\u7801\uFF0C\u9ED8\u8BA4 1", "1").option("--page-size <number>", "\u6BCF\u9875\u6570\u91CF\uFF0C\u9ED8\u8BA4 20", "20").action(async (opts) => {
|
|
6036
|
+
try {
|
|
6037
|
+
const page = Number(opts.page);
|
|
6038
|
+
const pageSize = Number(opts.pageSize);
|
|
6039
|
+
if (!Number.isInteger(page) || page <= 0) {
|
|
6040
|
+
throw new Error("--page \u5FC5\u987B\u4E3A\u6B63\u6574\u6570");
|
|
6041
|
+
}
|
|
6042
|
+
if (!Number.isInteger(pageSize) || pageSize <= 0) {
|
|
6043
|
+
throw new Error("--page-size \u5FC5\u987B\u4E3A\u6B63\u6574\u6570");
|
|
6044
|
+
}
|
|
6045
|
+
const data = await getPointsConsumes({ page, pageSize });
|
|
6046
|
+
formatOutput({ success: true, data }, program2.opts().table);
|
|
6047
|
+
} catch (err) {
|
|
6048
|
+
reportCaughtError(err);
|
|
6049
|
+
process.exit(toExitCode(err));
|
|
6050
|
+
}
|
|
6051
|
+
});
|
|
5353
6052
|
workspace.command("points-consumes-daily").description(
|
|
5354
6053
|
"\u6309\u5929\u67E5\u8BE2\u5F53\u524D\u5DE5\u4F5C\u7A7A\u95F4\u7684\u79EF\u5206\u6D88\u8017\u3002\u9ED8\u8BA4\u6700\u8FD1 30 \u5929\uFF08end=\u4ECA\u5929\uFF0Cstart=\u4ECA\u5929-29d\uFF09\uFF0C\u8FD4\u56DE consume_date / total_consume_points \u5217\u8868"
|
|
5355
6054
|
).option("--start <YYYY-MM-DD>", "\u8D77\u59CB\u65E5\u671F\uFF08\u542B\uFF09\uFF0C\u9ED8\u8BA4\u4ECA\u5929-29d").option("--end <YYYY-MM-DD>", "\u7ED3\u675F\u65E5\u671F\uFF08\u542B\uFF09\uFF0C\u9ED8\u8BA4\u4ECA\u5929").action(async (opts) => {
|
|
@@ -5416,6 +6115,7 @@ registerFaqCommand(program);
|
|
|
5416
6115
|
registerConversationCommand(program);
|
|
5417
6116
|
registerDebugCommand(program);
|
|
5418
6117
|
registerMonitorCommand(program);
|
|
6118
|
+
registerNodeTemplateCommand(program);
|
|
5419
6119
|
registerDashboardCommand(program);
|
|
5420
6120
|
registerRepairRecordCommand(program);
|
|
5421
6121
|
registerOperationsRecordCommand(program);
|