viatris-exam-cli 1.4.1 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -3
- package/package.json +1 -1
- package/skills/viatris-exam-cli/SKILL.md +5 -2
- package/skills/viatris-exam-cli/references/cli-reference.md +48 -2
- package/skills/viatris-exam-cli.zip +0 -0
- package/src/args.js +1 -1
- package/src/command-handlers/knowledge.js +5 -2
- package/src/command-handlers/products.js +37 -0
- package/src/help.js +5 -1
- package/src/metadata.js +31 -2
package/README.md
CHANGED
|
@@ -72,15 +72,26 @@ viatris-exam describe --compact
|
|
|
72
72
|
|
|
73
73
|
## 命令
|
|
74
74
|
|
|
75
|
+
### 产品主数据
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
viatris-exam products list
|
|
79
|
+
viatris-exam products create --input product.json
|
|
80
|
+
viatris-exam products update "$PRODUCT_ID" --input verified-medical-data.json
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
创建产品时仅中文名称 `name` 必填;`code` 和 `nameEn` 可省略,省略 `code` 时由服务端生成。创建会同步初始化规范知识树根节点。更新命令仅用于补充经资料核验的英文名、通用名、适应症、剂型规格和备注。
|
|
84
|
+
|
|
75
85
|
### 产品知识树
|
|
76
86
|
|
|
77
87
|
```bash
|
|
78
88
|
viatris-exam products get "$PRODUCT_ID"
|
|
79
89
|
viatris-exam products update-knowledge-tree "$PRODUCT_ID" \
|
|
80
90
|
--input knowledge-tree.json
|
|
91
|
+
viatris-exam products delete-knowledge-tree "$PRODUCT_ID"
|
|
81
92
|
```
|
|
82
93
|
|
|
83
|
-
|
|
94
|
+
产品主数据不属于业务知识树层级;详情查询使用产品主数据 ID,并兼容历史知识树根节点 ID。固定维度为 L1;知识树回写是完整替换操作,必须一次提交全部 15-500 个 L2/L3/L4 动态节点。整树删除会保留产品根和固定维度,但级联删除动态节点及文档并解绑题目,只能在明确要求时执行。
|
|
84
95
|
|
|
85
96
|
### 知识节点与文档
|
|
86
97
|
|
|
@@ -91,7 +102,7 @@ viatris-exam knowledge nodes create --input node.json
|
|
|
91
102
|
viatris-exam knowledge nodes get <node-id>
|
|
92
103
|
viatris-exam knowledge nodes update <node-id> --input changes.json
|
|
93
104
|
viatris-exam knowledge nodes move <node-id> --input move.json
|
|
94
|
-
viatris-exam knowledge nodes delete <node-id>
|
|
105
|
+
viatris-exam knowledge nodes delete <node-id> [--recursive]
|
|
95
106
|
viatris-exam knowledge documents list <node-id>
|
|
96
107
|
viatris-exam knowledge documents create <node-id> --input document.json
|
|
97
108
|
viatris-exam knowledge documents upsert <node-id> --input documents.json
|
|
@@ -99,7 +110,7 @@ viatris-exam knowledge documents update <document-id> --input changes.json
|
|
|
99
110
|
viatris-exam knowledge documents delete <document-id>
|
|
100
111
|
```
|
|
101
112
|
|
|
102
|
-
|
|
113
|
+
节点删除默认在存在子节点或题目绑定时返回冲突;`--recursive` 才会级联删除整棵子树及文档并解绑题目。产品根和固定维度受保护,不能改名、移动或删除。
|
|
103
114
|
|
|
104
115
|
`/knowledge` CRUD 响应中的 `level` 是物理存储层级(产品根为 1、固定维度为 2);产品生成接口使用业务层级(产品隐藏、固定维度为 L1、动态节点为 L2-L4)。
|
|
105
116
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: viatris-exam-cli
|
|
3
3
|
description: Operate the Viatris exam OpenAPI through its agent-friendly CLI. Use for products, knowledge nodes or documents, generation tasks, exam records, scoring, exams, questions, or medical search.
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.6.0
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Viatris Exam CLI
|
|
@@ -22,11 +22,14 @@ Use the repository-local CLI for every supported API operation. Do not call the
|
|
|
22
22
|
- Prefer `--input <file>` for existing payloads and stdin for generated payloads.
|
|
23
23
|
- Parse successful `stdout` as JSON.
|
|
24
24
|
- Parse failed `stderr` as JSON and branch on both exit code and `error.type`.
|
|
25
|
+
- Use `products list` to resolve product master IDs and stable codes before product-specific workflows. `products create` requires only a Chinese name and also initializes the canonical knowledge-tree root.
|
|
26
|
+
- Use `products update` only for verified optional medical master data. Do not infer English names, generic names, indications, dosage forms, or remarks without evidence.
|
|
25
27
|
- Preserve `externalRef` when retrying question submission. It is the idempotency key.
|
|
26
28
|
- For product-wide generation tasks, create one or more questions for every entry in `knowledgeContexts` and include its `knowledgeNodeId`.
|
|
27
29
|
- Apply every returned generation rule. Product-scoped rules identify applicable product codes through `products`; global rules return an empty `products` array.
|
|
28
30
|
- Prefer scoring rule V2 for generated questions and scoring results. Use stable point and deduction-rule IDs.
|
|
29
|
-
- Treat product
|
|
31
|
+
- Treat product master records as outside business knowledge-tree levels. Fixed dimensions are business L1; generated nodes are L2-L4. Product detail lookup also accepts a historical knowledge-tree root ID.
|
|
32
|
+
- Treat knowledge-tree and recursive node deletion as destructive. Inspect the target first and perform them only when the user explicitly requests deletion.
|
|
30
33
|
- Do not automatically retry POST, PUT, PATCH, or DELETE commands. Inspect the returned error and determine whether the server accepted the request.
|
|
31
34
|
- Keep temporary payloads outside the repository unless they are requested deliverables.
|
|
32
35
|
|
|
@@ -42,13 +42,50 @@ node src/cli.js --version
|
|
|
42
42
|
|
|
43
43
|
## Commands
|
|
44
44
|
|
|
45
|
+
List product master data:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
node src/cli.js products list --compact
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The response is `{ "items": [...] }`, ordered by `sortOrder` and then name. Each record includes the stable `code`, Chinese name, optional English name, generic name, indication, dosage form, `active` or `inactive` status, remark, and timestamps.
|
|
52
|
+
|
|
53
|
+
Create a product and initialize its canonical knowledge-tree root:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
node src/cli.js products create --json '{
|
|
57
|
+
"name": "络活喜",
|
|
58
|
+
"genericName": "苯磺酸氨氯地平片",
|
|
59
|
+
"indication": "高血压、冠心病",
|
|
60
|
+
"dosageForm": "片剂",
|
|
61
|
+
"sortOrder": 20,
|
|
62
|
+
"remark": "由外部系统创建"
|
|
63
|
+
}'
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Only `name` is required and the Chinese name must be unique. `code` is optional; when supplied it must contain only lowercase letters, digits, and hyphens and be globally unique, while omission lets the server generate it. `nameEn` and the remaining fields are optional. Omitted `sortOrder` defaults to 0. This POST is not automatically retried; after an uncertain network outcome, list products and resolve by name or code before attempting another create.
|
|
67
|
+
|
|
45
68
|
Get a product and its fixed L1 dimensions:
|
|
46
69
|
|
|
47
70
|
```bash
|
|
48
71
|
node src/cli.js products get "$PRODUCT_ID" --compact
|
|
49
72
|
```
|
|
50
73
|
|
|
51
|
-
|
|
74
|
+
Use the product master `id`; historical knowledge-tree root IDs remain accepted for compatibility. The response also contains nullable `nameEn`, `genericName`, `indication`, `dosageForm`, and `remark`. Product master data is outside business levels L1-L4. Use each returned `fixedDimensions[].clientRef` as the parent reference for an L2 node. Each fixed dimension also returns `level: 1` and a display `codePrefix`.
|
|
75
|
+
|
|
76
|
+
Update verified optional medical master data:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
node src/cli.js products update "$PRODUCT_ID" --json '{
|
|
80
|
+
"nameEn": "Lipitor",
|
|
81
|
+
"genericName": "阿托伐他汀钙片",
|
|
82
|
+
"indication": "高胆固醇血症、混合型血脂异常及心血管疾病预防",
|
|
83
|
+
"dosageForm": "片剂 10mg/20mg/40mg",
|
|
84
|
+
"remark": "生产企业:辉瑞制药有限公司"
|
|
85
|
+
}'
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Only supplied fields are updated. Each supplied value must be a nonempty string within the API length limit. Update these fields only from verified source material; this endpoint does not update `code`, Chinese `name`, status, or sort order.
|
|
52
89
|
|
|
53
90
|
Replace a product knowledge tree:
|
|
54
91
|
|
|
@@ -100,6 +137,14 @@ Payload shape:
|
|
|
100
137
|
|
|
101
138
|
Submit the complete L2/L3/L4 node set, between 15 and 500 nodes. Every `clientRef` must be unique within the payload. L2 nodes use `dimension:<code>` as `parentClientRef`; L3/L4 nodes use their direct parent's `clientRef`. Every L4 node needs at least one document. A successful PUT replaces the previous dynamic nodes, so do not send a partial tree.
|
|
102
139
|
|
|
140
|
+
Delete all dynamic knowledge-tree content:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
node src/cli.js products delete-knowledge-tree "$PRODUCT_ID"
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
This destructive operation preserves the product root and five fixed L1 dimensions, deletes all L2-L4 nodes and evidence documents, and unbinds affected questions. Inspect the product and tree first, and execute only when the user explicitly requests the full reset.
|
|
147
|
+
|
|
103
148
|
### Incremental Knowledge Management
|
|
104
149
|
|
|
105
150
|
Get the complete physical tree and all product documents:
|
|
@@ -135,9 +180,10 @@ node src/cli.js knowledge nodes update "$NODE_ID" \
|
|
|
135
180
|
node src/cli.js knowledge nodes move "$NODE_ID" \
|
|
136
181
|
--json '{"newParentId":"NEW_PARENT_ID","sortOrder":30}'
|
|
137
182
|
node src/cli.js knowledge nodes delete "$NODE_ID"
|
|
183
|
+
node src/cli.js knowledge nodes delete "$NODE_ID" --recursive
|
|
138
184
|
```
|
|
139
185
|
|
|
140
|
-
Product roots and fixed dimensions are protected from rename, move, and deletion. Moving cannot cross products, target the node itself or its descendants, or produce levels deeper than L4.
|
|
186
|
+
Product roots and fixed dimensions are protected from rename, move, and deletion. Moving cannot cross products, target the node itself or its descendants, or produce levels deeper than L4. Plain deletion is the safe default and returns HTTP 409 when children or question bindings exist. `--recursive` deletes the full subtree and documents and unbinds affected questions. Inspect the node first and use recursive deletion only when explicitly requested.
|
|
141
187
|
|
|
142
188
|
Manage documents:
|
|
143
189
|
|
|
Binary file
|
package/src/args.js
CHANGED
|
@@ -61,9 +61,12 @@ export async function resolveKnowledge(positionals, options) {
|
|
|
61
61
|
|
|
62
62
|
if (area === "nodes" && action === "delete") {
|
|
63
63
|
assertNoExtraPositionals(positionals, 4);
|
|
64
|
-
assertOptions(options);
|
|
64
|
+
assertOptions(options, ["recursive"]);
|
|
65
65
|
const id = nodePath(positionals, "knowledge node ID");
|
|
66
|
-
return {
|
|
66
|
+
return {
|
|
67
|
+
method: "DELETE",
|
|
68
|
+
path: `/openapi/knowledge/nodes/${id}${options.recursive ? "?recursive=true" : ""}`,
|
|
69
|
+
};
|
|
67
70
|
}
|
|
68
71
|
|
|
69
72
|
if (area === "nodes" && action === "move") {
|
|
@@ -9,6 +9,22 @@ export async function resolveProducts(positionals, options) {
|
|
|
9
9
|
const [resource, action] = positionals;
|
|
10
10
|
if (resource !== "products") return null;
|
|
11
11
|
|
|
12
|
+
if (action === "list") {
|
|
13
|
+
assertNoExtraPositionals(positionals, 2);
|
|
14
|
+
assertOptions(options);
|
|
15
|
+
return { method: "GET", path: "/openapi/products" };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (action === "create") {
|
|
19
|
+
assertNoExtraPositionals(positionals, 2);
|
|
20
|
+
assertOptions(options, ["input", "json"]);
|
|
21
|
+
return {
|
|
22
|
+
method: "POST",
|
|
23
|
+
path: "/openapi/products",
|
|
24
|
+
body: await readJsonInput(options),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
12
28
|
if (action === "get") {
|
|
13
29
|
assertNoExtraPositionals(positionals, 3);
|
|
14
30
|
assertOptions(options);
|
|
@@ -16,6 +32,17 @@ export async function resolveProducts(positionals, options) {
|
|
|
16
32
|
return { method: "GET", path: `/openapi/products/${id}` };
|
|
17
33
|
}
|
|
18
34
|
|
|
35
|
+
if (action === "update") {
|
|
36
|
+
assertNoExtraPositionals(positionals, 3);
|
|
37
|
+
assertOptions(options, ["input", "json"]);
|
|
38
|
+
const id = requiredId(positionals, 2, "product ID");
|
|
39
|
+
return {
|
|
40
|
+
method: "PATCH",
|
|
41
|
+
path: `/openapi/products/${id}`,
|
|
42
|
+
body: await readJsonInput(options),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
19
46
|
if (action === "update-knowledge-tree") {
|
|
20
47
|
assertNoExtraPositionals(positionals, 3);
|
|
21
48
|
assertOptions(options, ["input", "json"]);
|
|
@@ -27,5 +54,15 @@ export async function resolveProducts(positionals, options) {
|
|
|
27
54
|
};
|
|
28
55
|
}
|
|
29
56
|
|
|
57
|
+
if (action === "delete-knowledge-tree") {
|
|
58
|
+
assertNoExtraPositionals(positionals, 3);
|
|
59
|
+
assertOptions(options);
|
|
60
|
+
const id = requiredId(positionals, 2, "product ID");
|
|
61
|
+
return {
|
|
62
|
+
method: "DELETE",
|
|
63
|
+
path: `/openapi/products/${id}/knowledge-tree`,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
30
67
|
return null;
|
|
31
68
|
}
|
package/src/help.js
CHANGED
|
@@ -8,14 +8,18 @@ Usage:
|
|
|
8
8
|
viatris-exam describe
|
|
9
9
|
|
|
10
10
|
Commands:
|
|
11
|
+
products list
|
|
12
|
+
products create --input <file|->
|
|
11
13
|
products get <product-id>
|
|
14
|
+
products update <product-id> --input <file|->
|
|
12
15
|
products update-knowledge-tree <product-id> --input <file|->
|
|
16
|
+
products delete-knowledge-tree <product-id>
|
|
13
17
|
knowledge tree <product-code>
|
|
14
18
|
knowledge nodes by-path --input <file|->
|
|
15
19
|
knowledge nodes create --input <file|->
|
|
16
20
|
knowledge nodes get <node-id>
|
|
17
21
|
knowledge nodes update <node-id> --input <file|->
|
|
18
|
-
knowledge nodes delete <node-id>
|
|
22
|
+
knowledge nodes delete <node-id> [--recursive]
|
|
19
23
|
knowledge nodes move <node-id> --input <file|->
|
|
20
24
|
knowledge documents list <node-id>
|
|
21
25
|
knowledge documents create <node-id> --input <file|->
|
package/src/metadata.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const VERSION = "1.
|
|
1
|
+
export const VERSION = "1.6.0";
|
|
2
2
|
export const DEFAULT_TIMEOUT_MS = 30_000;
|
|
3
3
|
export const DEFAULT_RETRIES = 2;
|
|
4
4
|
|
|
@@ -15,12 +15,32 @@ export const API_ENVIRONMENT_ALIASES = Object.freeze({
|
|
|
15
15
|
});
|
|
16
16
|
|
|
17
17
|
export const COMMANDS = Object.freeze([
|
|
18
|
+
{
|
|
19
|
+
command: "products list",
|
|
20
|
+
method: "GET",
|
|
21
|
+
path: "/openapi/products",
|
|
22
|
+
summary: "List all product master records in display order.",
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
command: "products create",
|
|
26
|
+
method: "POST",
|
|
27
|
+
path: "/openapi/products",
|
|
28
|
+
input: "{name, code?, nameEn?, genericName?, indication?, dosageForm?, sortOrder?, remark?}",
|
|
29
|
+
summary: "Create a product and initialize its canonical knowledge-tree root.",
|
|
30
|
+
},
|
|
18
31
|
{
|
|
19
32
|
command: "products get <product-id>",
|
|
20
33
|
method: "GET",
|
|
21
34
|
path: "/openapi/products/{id}",
|
|
22
35
|
summary: "Get a product, knowledge-tree status, and fixed dimensions.",
|
|
23
36
|
},
|
|
37
|
+
{
|
|
38
|
+
command: "products update <product-id>",
|
|
39
|
+
method: "PATCH",
|
|
40
|
+
path: "/openapi/products/{id}",
|
|
41
|
+
input: "{nameEn?, genericName?, indication?, dosageForm?, remark?}",
|
|
42
|
+
summary: "Update verified optional medical product master data.",
|
|
43
|
+
},
|
|
24
44
|
{
|
|
25
45
|
command: "products update-knowledge-tree <product-id>",
|
|
26
46
|
method: "PUT",
|
|
@@ -28,6 +48,12 @@ export const COMMANDS = Object.freeze([
|
|
|
28
48
|
input: "{nodes: [...]}",
|
|
29
49
|
summary: "Replace the product's dynamic L2/L3/L4 knowledge-tree nodes.",
|
|
30
50
|
},
|
|
51
|
+
{
|
|
52
|
+
command: "products delete-knowledge-tree <product-id>",
|
|
53
|
+
method: "DELETE",
|
|
54
|
+
path: "/openapi/products/{id}/knowledge-tree",
|
|
55
|
+
summary: "Delete all dynamic product knowledge-tree nodes and documents.",
|
|
56
|
+
},
|
|
31
57
|
{
|
|
32
58
|
command: "knowledge tree <product-code>",
|
|
33
59
|
method: "GET",
|
|
@@ -65,7 +91,10 @@ export const COMMANDS = Object.freeze([
|
|
|
65
91
|
command: "knowledge nodes delete <node-id>",
|
|
66
92
|
method: "DELETE",
|
|
67
93
|
path: "/openapi/knowledge/nodes/{id}",
|
|
68
|
-
|
|
94
|
+
options: {
|
|
95
|
+
"--recursive": "delete descendants, documents, and node bindings",
|
|
96
|
+
},
|
|
97
|
+
summary: "Delete a node, optionally recursing through its subtree.",
|
|
69
98
|
},
|
|
70
99
|
{
|
|
71
100
|
command: "knowledge nodes move <node-id>",
|