qingflow-mcp 0.3.18 → 0.3.19
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 +63 -1
- package/dist/qingflow-client.js +36 -0
- package/dist/server.js +787 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
This MCP server wraps Qingflow OpenAPI for:
|
|
4
4
|
|
|
5
5
|
- `qf_apps_list`
|
|
6
|
+
- `qf_apps_info_list`
|
|
7
|
+
- `qf_app_info_get`
|
|
8
|
+
- `qf_app_packages_list`
|
|
6
9
|
- `qf_departments_list`
|
|
7
10
|
- `qf_department_users_list`
|
|
8
11
|
- `qf_users_list`
|
|
@@ -17,6 +20,8 @@ This MCP server wraps Qingflow OpenAPI for:
|
|
|
17
20
|
- `qf_export_json`
|
|
18
21
|
- `qf_query` (unified read entry: list / record / summary)
|
|
19
22
|
- `qf_records_aggregate` (deterministic grouped metrics)
|
|
23
|
+
- `qf_apply_audit_records_list`
|
|
24
|
+
- `qf_apply_audit_record_get`
|
|
20
25
|
- `qf_record_create`
|
|
21
26
|
- `qf_record_update`
|
|
22
27
|
- `qf_operation_get`
|
|
@@ -112,7 +117,7 @@ npm i -g git+https://github.com/853046310/qingflow-mcp.git
|
|
|
112
117
|
Install from npm (pinned version):
|
|
113
118
|
|
|
114
119
|
```bash
|
|
115
|
-
npm i -g qingflow-mcp@0.3.
|
|
120
|
+
npm i -g qingflow-mcp@0.3.19
|
|
116
121
|
```
|
|
117
122
|
|
|
118
123
|
Or one-click installer:
|
|
@@ -159,6 +164,18 @@ Directory / org flow:
|
|
|
159
164
|
3. `qf_users_list` for workspace-wide pagination.
|
|
160
165
|
4. `qf_user_get` for one exact user.
|
|
161
166
|
|
|
167
|
+
Admin app flow:
|
|
168
|
+
|
|
169
|
+
1. `qf_apps_list` for lightweight visible app listing.
|
|
170
|
+
2. `qf_apps_info_list` for admin-level app detail listing.
|
|
171
|
+
3. `qf_app_info_get` for one exact app.
|
|
172
|
+
4. `qf_app_packages_list` for user-visible app packages.
|
|
173
|
+
|
|
174
|
+
Audit flow:
|
|
175
|
+
|
|
176
|
+
1. `qf_apply_audit_records_list` to inspect one record's workflow history.
|
|
177
|
+
2. `qf_apply_audit_record_get` to inspect one audit record's field modifications.
|
|
178
|
+
|
|
162
179
|
Full calling contract (Chinese):
|
|
163
180
|
|
|
164
181
|
- [MCP 调用规范](./docs/MCP_CALLING_SPEC.md)
|
|
@@ -215,6 +232,51 @@ qingflow-mcp cli call qf_users_list --args '{"pageNum":1,"pageSize":100}'
|
|
|
215
232
|
qingflow-mcp cli call qf_user_get --args '{"userId":"u_123"}'
|
|
216
233
|
```
|
|
217
234
|
|
|
235
|
+
## Admin App Tools
|
|
236
|
+
|
|
237
|
+
These tools expose admin-facing app and package metadata without routing through `qf_query`:
|
|
238
|
+
|
|
239
|
+
1. `qf_apps_info_list`
|
|
240
|
+
- required `page_num`, `page_size`
|
|
241
|
+
- optional `app_key`
|
|
242
|
+
- aliases: `pageNum`, `pageSize`, `appKey`
|
|
243
|
+
2. `qf_app_info_get`
|
|
244
|
+
- required `app_key`
|
|
245
|
+
- alias: `appKey`
|
|
246
|
+
3. `qf_app_packages_list`
|
|
247
|
+
- required `user_id`
|
|
248
|
+
- optional `tag_id`, `keyword`, `limit`, `offset`
|
|
249
|
+
- aliases: `userId`, `tagId`
|
|
250
|
+
|
|
251
|
+
CLI examples:
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
qingflow-mcp cli call qf_apps_info_list --args '{"pageNum":1,"pageSize":50}'
|
|
255
|
+
|
|
256
|
+
qingflow-mcp cli call qf_app_info_get --args '{"appKey":"app_demo"}'
|
|
257
|
+
|
|
258
|
+
qingflow-mcp cli call qf_app_packages_list --args '{"userId":"u_123","tagId":1001}'
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## Audit Tools
|
|
262
|
+
|
|
263
|
+
These tools expose workflow log history as read-only MCP tools:
|
|
264
|
+
|
|
265
|
+
1. `qf_apply_audit_records_list`
|
|
266
|
+
- required `apply_id`
|
|
267
|
+
- alias: `applyId`
|
|
268
|
+
2. `qf_apply_audit_record_get`
|
|
269
|
+
- required `apply_id`, `audit_rcd_id`
|
|
270
|
+
- aliases: `applyId`, `auditRcdId`
|
|
271
|
+
|
|
272
|
+
CLI examples:
|
|
273
|
+
|
|
274
|
+
```bash
|
|
275
|
+
qingflow-mcp cli call qf_apply_audit_records_list --args '{"applyId":"50001234"}'
|
|
276
|
+
|
|
277
|
+
qingflow-mcp cli call qf_apply_audit_record_get --args '{"applyId":"50001234","auditRcdId":"1111"}'
|
|
278
|
+
```
|
|
279
|
+
|
|
218
280
|
Return shape:
|
|
219
281
|
|
|
220
282
|
1. success: structured payload `{ "ok": true, "data": ... }` (`meta` only in `output_profile=verbose`)
|
package/dist/qingflow-client.js
CHANGED
|
@@ -33,6 +33,42 @@ export class QingflowClient {
|
|
|
33
33
|
}
|
|
34
34
|
});
|
|
35
35
|
}
|
|
36
|
+
listAppsInfo(options) {
|
|
37
|
+
return this.request({
|
|
38
|
+
method: "GET",
|
|
39
|
+
path: "/apps",
|
|
40
|
+
options: {
|
|
41
|
+
query: {
|
|
42
|
+
appKey: options.appKey,
|
|
43
|
+
pageNum: options.pageNum,
|
|
44
|
+
pageSize: options.pageSize
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
listAppPackages(options) {
|
|
50
|
+
return this.request({
|
|
51
|
+
method: "GET",
|
|
52
|
+
path: "/tags",
|
|
53
|
+
options: {
|
|
54
|
+
query: {
|
|
55
|
+
userId: options.userId
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
listApplyAuditRecords(applyId) {
|
|
61
|
+
return this.request({
|
|
62
|
+
method: "GET",
|
|
63
|
+
path: `/apply/${encodeURIComponent(applyId)}/auditRecord`
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
getApplyAuditRecord(applyId, auditRcdId) {
|
|
67
|
+
return this.request({
|
|
68
|
+
method: "GET",
|
|
69
|
+
path: `/apply/${encodeURIComponent(applyId)}/auditRecord/${encodeURIComponent(auditRcdId)}`
|
|
70
|
+
});
|
|
71
|
+
}
|
|
36
72
|
listDepartments(options = {}) {
|
|
37
73
|
return this.request({
|
|
38
74
|
method: "GET",
|
package/dist/server.js
CHANGED
|
@@ -65,7 +65,7 @@ const REQUEST_TIMEOUT_MS = toPositiveInt(process.env.QINGFLOW_REQUEST_TIMEOUT_MS
|
|
|
65
65
|
const EXECUTION_BUDGET_MS = toPositiveInt(process.env.QINGFLOW_EXECUTION_BUDGET_MS) ?? 20000;
|
|
66
66
|
const WAIT_RESULT_DEFAULT_TIMEOUT_MS = toPositiveInt(process.env.QINGFLOW_WAIT_RESULT_TIMEOUT_MS) ?? 5000;
|
|
67
67
|
const WAIT_RESULT_POLL_INTERVAL_MS = toPositiveInt(process.env.QINGFLOW_WAIT_RESULT_POLL_INTERVAL_MS) ?? 500;
|
|
68
|
-
const SERVER_VERSION = "0.3.
|
|
68
|
+
const SERVER_VERSION = "0.3.19";
|
|
69
69
|
const accessToken = process.env.QINGFLOW_ACCESS_TOKEN;
|
|
70
70
|
const baseUrl = process.env.QINGFLOW_BASE_URL;
|
|
71
71
|
if (!accessToken) {
|
|
@@ -353,6 +353,186 @@ const formSuccessOutputSchema = z.object({
|
|
|
353
353
|
const formOutputSchema = formSuccessOutputSchema;
|
|
354
354
|
const publicStringSchema = z.string().min(1);
|
|
355
355
|
const publicFieldSelectorSchema = z.union([publicStringSchema, z.number().int()]);
|
|
356
|
+
const appAuthUserSchema = z.object({
|
|
357
|
+
user_id: z.string().nullable(),
|
|
358
|
+
user_name: z.string().nullable()
|
|
359
|
+
});
|
|
360
|
+
const appAuthDepartmentSchema = z.object({
|
|
361
|
+
dept_id: z.number().int().nullable(),
|
|
362
|
+
dept_name: z.string().nullable()
|
|
363
|
+
});
|
|
364
|
+
const appAuthRoleSchema = z.object({
|
|
365
|
+
role_id: z.number().int().nullable(),
|
|
366
|
+
role_name: z.string().nullable()
|
|
367
|
+
});
|
|
368
|
+
const appAuthMembersSchema = z.object({
|
|
369
|
+
users: z.array(appAuthUserSchema),
|
|
370
|
+
departments: z.array(appAuthDepartmentSchema),
|
|
371
|
+
roles: z.array(appAuthRoleSchema)
|
|
372
|
+
});
|
|
373
|
+
const appCreatorSchema = z.object({
|
|
374
|
+
user_id: z.string().nullable(),
|
|
375
|
+
nick_name: z.string().nullable(),
|
|
376
|
+
head_img: z.string().nullable()
|
|
377
|
+
});
|
|
378
|
+
const appTagRefSchema = z.object({
|
|
379
|
+
tag_id: z.number().int().nullable(),
|
|
380
|
+
tag_name: z.string().nullable()
|
|
381
|
+
});
|
|
382
|
+
const appInfoSchema = z.object({
|
|
383
|
+
app_key: z.string().nullable(),
|
|
384
|
+
app_name: z.string().nullable(),
|
|
385
|
+
app_auth: z.number().int().nullable(),
|
|
386
|
+
app_icon: z.string().nullable(),
|
|
387
|
+
auth_members: appAuthMembersSchema,
|
|
388
|
+
creator: appCreatorSchema,
|
|
389
|
+
create_time: z.string().nullable(),
|
|
390
|
+
tags: z.array(appTagRefSchema),
|
|
391
|
+
app_publish_status: z.number().int().nullable()
|
|
392
|
+
});
|
|
393
|
+
const appInfoListInputPublicSchema = z.object({
|
|
394
|
+
page_num: z.number().int().positive().optional(),
|
|
395
|
+
pageNum: z.number().int().positive().optional(),
|
|
396
|
+
page_size: z.number().int().positive().optional(),
|
|
397
|
+
pageSize: z.number().int().positive().optional(),
|
|
398
|
+
app_key: publicStringSchema.optional(),
|
|
399
|
+
appKey: publicStringSchema.optional()
|
|
400
|
+
});
|
|
401
|
+
const appInfoListInputSchema = z.preprocess(normalizeAppInfoListInput, z.object({
|
|
402
|
+
page_num: z.number().int().positive().optional(),
|
|
403
|
+
page_size: z.number().int().positive().optional(),
|
|
404
|
+
app_key: z.string().min(1).optional()
|
|
405
|
+
}));
|
|
406
|
+
const appInfoListOutputSchema = z.object({
|
|
407
|
+
ok: z.literal(true),
|
|
408
|
+
data: z.object({
|
|
409
|
+
pagination: z.object({
|
|
410
|
+
page_num: z.number().int().positive(),
|
|
411
|
+
page_size: z.number().int().positive(),
|
|
412
|
+
page_amount: z.number().int().nonnegative(),
|
|
413
|
+
result_amount: z.number().int().nonnegative()
|
|
414
|
+
}),
|
|
415
|
+
apps: z.array(appInfoSchema)
|
|
416
|
+
}),
|
|
417
|
+
meta: apiMetaSchema
|
|
418
|
+
});
|
|
419
|
+
const appInfoGetInputPublicSchema = z.object({
|
|
420
|
+
app_key: publicStringSchema.optional(),
|
|
421
|
+
appKey: publicStringSchema.optional()
|
|
422
|
+
});
|
|
423
|
+
const appInfoGetInputSchema = z.preprocess(normalizeAppInfoGetInput, z.object({
|
|
424
|
+
app_key: z.string().min(1).optional()
|
|
425
|
+
}));
|
|
426
|
+
const appInfoGetOutputSchema = z.object({
|
|
427
|
+
ok: z.literal(true),
|
|
428
|
+
data: z.object({
|
|
429
|
+
app: appInfoSchema
|
|
430
|
+
}),
|
|
431
|
+
meta: apiMetaSchema
|
|
432
|
+
});
|
|
433
|
+
const appPackageAppSchema = z.object({
|
|
434
|
+
app_key: z.string().nullable(),
|
|
435
|
+
app_name: z.string().nullable()
|
|
436
|
+
});
|
|
437
|
+
const dashboardRefSchema = z.object({
|
|
438
|
+
dash_key: z.string().nullable(),
|
|
439
|
+
dash_name: z.string().nullable()
|
|
440
|
+
});
|
|
441
|
+
const appPackageSchema = z.object({
|
|
442
|
+
tag_id: z.number().int().nullable(),
|
|
443
|
+
tag_name: z.string().nullable(),
|
|
444
|
+
tag_icon: z.string().nullable(),
|
|
445
|
+
apps: z.array(appPackageAppSchema),
|
|
446
|
+
dashboards: z.array(dashboardRefSchema)
|
|
447
|
+
});
|
|
448
|
+
const appPackageListInputPublicSchema = z.object({
|
|
449
|
+
user_id: publicStringSchema.optional(),
|
|
450
|
+
userId: publicStringSchema.optional(),
|
|
451
|
+
tag_id: publicDirectorySelectorSchema.optional(),
|
|
452
|
+
tagId: publicDirectorySelectorSchema.optional(),
|
|
453
|
+
keyword: publicStringSchema.optional(),
|
|
454
|
+
limit: z.number().int().positive().max(500).optional(),
|
|
455
|
+
offset: z.number().int().nonnegative().optional()
|
|
456
|
+
});
|
|
457
|
+
const appPackageListInputSchema = z.preprocess(normalizeAppPackageListInput, z.object({
|
|
458
|
+
user_id: z.string().min(1).optional(),
|
|
459
|
+
tag_id: z.union([z.string().min(1), z.number().int()]).optional(),
|
|
460
|
+
keyword: z.string().min(1).optional(),
|
|
461
|
+
limit: z.number().int().positive().max(500).optional(),
|
|
462
|
+
offset: z.number().int().nonnegative().optional()
|
|
463
|
+
}));
|
|
464
|
+
const appPackageListOutputSchema = z.object({
|
|
465
|
+
ok: z.literal(true),
|
|
466
|
+
data: z.object({
|
|
467
|
+
user_id: z.string(),
|
|
468
|
+
tag_id_filter: z.union([z.string(), z.number(), z.null()]),
|
|
469
|
+
total_packages: z.number().int().nonnegative(),
|
|
470
|
+
returned_packages: z.number().int().nonnegative(),
|
|
471
|
+
limit: z.number().int().positive(),
|
|
472
|
+
offset: z.number().int().nonnegative(),
|
|
473
|
+
packages: z.array(appPackageSchema)
|
|
474
|
+
}),
|
|
475
|
+
meta: apiMetaSchema
|
|
476
|
+
});
|
|
477
|
+
const auditUserInfoSchema = z.object({
|
|
478
|
+
user_id: z.string().nullable(),
|
|
479
|
+
user_name: z.string().nullable(),
|
|
480
|
+
nick_name: z.string().nullable(),
|
|
481
|
+
head_img: z.string().nullable()
|
|
482
|
+
});
|
|
483
|
+
const auditRecordSummarySchema = z.object({
|
|
484
|
+
audit_rcd_id: z.number().int().nullable(),
|
|
485
|
+
audit_node_id: z.number().int().nullable(),
|
|
486
|
+
audit_node_name: z.string().nullable(),
|
|
487
|
+
audit_time_ms: z.number().int().nullable(),
|
|
488
|
+
audit_result: z.unknown().nullable(),
|
|
489
|
+
audit_feedback: z.string().nullable(),
|
|
490
|
+
audit_user: auditUserInfoSchema.nullable(),
|
|
491
|
+
wait_audit_users: z.array(auditUserInfoSchema)
|
|
492
|
+
});
|
|
493
|
+
const applyAuditRecordsInputPublicSchema = z.object({
|
|
494
|
+
apply_id: publicStringSchema.optional(),
|
|
495
|
+
applyId: publicStringSchema.optional()
|
|
496
|
+
});
|
|
497
|
+
const applyAuditRecordsInputSchema = z.preprocess(normalizeApplyAuditRecordsInput, z.object({
|
|
498
|
+
apply_id: z.string().min(1).optional()
|
|
499
|
+
}));
|
|
500
|
+
const applyAuditRecordsOutputSchema = z.object({
|
|
501
|
+
ok: z.literal(true),
|
|
502
|
+
data: z.object({
|
|
503
|
+
apply_id: z.string(),
|
|
504
|
+
apply_status: z.unknown().nullable(),
|
|
505
|
+
audit_records: z.array(auditRecordSummarySchema),
|
|
506
|
+
current_nodes: z.array(auditRecordSummarySchema)
|
|
507
|
+
}),
|
|
508
|
+
meta: apiMetaSchema
|
|
509
|
+
});
|
|
510
|
+
const auditModifySchema = z.object({
|
|
511
|
+
que_id: z.union([z.number(), z.string(), z.null()]),
|
|
512
|
+
que_title: z.string().nullable(),
|
|
513
|
+
que_type: z.unknown().nullable(),
|
|
514
|
+
before_answer: z.array(z.unknown()),
|
|
515
|
+
after_answer: z.array(z.unknown())
|
|
516
|
+
});
|
|
517
|
+
const applyAuditRecordGetInputPublicSchema = z.object({
|
|
518
|
+
apply_id: publicStringSchema.optional(),
|
|
519
|
+
applyId: publicStringSchema.optional(),
|
|
520
|
+
audit_rcd_id: publicStringSchema.optional(),
|
|
521
|
+
auditRcdId: publicStringSchema.optional()
|
|
522
|
+
});
|
|
523
|
+
const applyAuditRecordGetInputSchema = z.preprocess(normalizeApplyAuditRecordGetInput, z.object({
|
|
524
|
+
apply_id: z.string().min(1).optional(),
|
|
525
|
+
audit_rcd_id: z.string().min(1).optional()
|
|
526
|
+
}));
|
|
527
|
+
const applyAuditRecordGetOutputSchema = z.object({
|
|
528
|
+
ok: z.literal(true),
|
|
529
|
+
data: z.object({
|
|
530
|
+
apply_id: z.string(),
|
|
531
|
+
audit_rcd_id: z.union([z.string(), z.number()]),
|
|
532
|
+
modifies: z.array(auditModifySchema)
|
|
533
|
+
}),
|
|
534
|
+
meta: apiMetaSchema
|
|
535
|
+
});
|
|
356
536
|
const publicSortItemSchema = z.object({
|
|
357
537
|
que_id: publicFieldSelectorSchema,
|
|
358
538
|
ascend: z.boolean().optional()
|
|
@@ -1418,6 +1598,300 @@ server.registerTool("qf_apps_list", {
|
|
|
1418
1598
|
return errorResult(error);
|
|
1419
1599
|
}
|
|
1420
1600
|
});
|
|
1601
|
+
server.registerTool("qf_apps_info_list", {
|
|
1602
|
+
title: "Qingflow Apps Info List",
|
|
1603
|
+
description: "List app admin info with explicit pagination. Requires admin-level visibility.",
|
|
1604
|
+
inputSchema: appInfoListInputPublicSchema,
|
|
1605
|
+
outputSchema: appInfoListOutputSchema,
|
|
1606
|
+
annotations: {
|
|
1607
|
+
readOnlyHint: true,
|
|
1608
|
+
idempotentHint: true
|
|
1609
|
+
}
|
|
1610
|
+
}, async (args) => {
|
|
1611
|
+
try {
|
|
1612
|
+
const parsedArgs = appInfoListInputSchema.parse(args);
|
|
1613
|
+
if (parsedArgs.page_num === undefined) {
|
|
1614
|
+
throw missingRequiredFieldError({
|
|
1615
|
+
field: "page_num",
|
|
1616
|
+
tool: "qf_apps_info_list",
|
|
1617
|
+
fixHint: "Provide page_num (or pageNum), for example: {\"page_num\":1,\"page_size\":50}."
|
|
1618
|
+
});
|
|
1619
|
+
}
|
|
1620
|
+
if (parsedArgs.page_size === undefined) {
|
|
1621
|
+
throw missingRequiredFieldError({
|
|
1622
|
+
field: "page_size",
|
|
1623
|
+
tool: "qf_apps_info_list",
|
|
1624
|
+
fixHint: "Provide page_size (or pageSize), for example: {\"page_num\":1,\"page_size\":50}."
|
|
1625
|
+
});
|
|
1626
|
+
}
|
|
1627
|
+
let response;
|
|
1628
|
+
try {
|
|
1629
|
+
response = await client.listAppsInfo({
|
|
1630
|
+
appKey: parsedArgs.app_key,
|
|
1631
|
+
pageNum: parsedArgs.page_num,
|
|
1632
|
+
pageSize: parsedArgs.page_size
|
|
1633
|
+
});
|
|
1634
|
+
}
|
|
1635
|
+
catch (error) {
|
|
1636
|
+
if (parsedArgs.app_key) {
|
|
1637
|
+
throw translateAdminApiError(error, {
|
|
1638
|
+
tool: "qf_apps_info_list",
|
|
1639
|
+
entity: "app",
|
|
1640
|
+
appKey: parsedArgs.app_key
|
|
1641
|
+
});
|
|
1642
|
+
}
|
|
1643
|
+
throw error;
|
|
1644
|
+
}
|
|
1645
|
+
const result = asObject(response.result);
|
|
1646
|
+
const apps = asArray(result?.apps).map((item) => normalizeAppInfo(item));
|
|
1647
|
+
return okResult({
|
|
1648
|
+
ok: true,
|
|
1649
|
+
data: {
|
|
1650
|
+
pagination: {
|
|
1651
|
+
page_num: toPositiveInt(result?.pageNum) ?? parsedArgs.page_num,
|
|
1652
|
+
page_size: toPositiveInt(result?.pageSize) ?? parsedArgs.page_size,
|
|
1653
|
+
page_amount: toNonNegativeInt(result?.pageAmount) ?? 0,
|
|
1654
|
+
result_amount: toNonNegativeInt(result?.resultAmount) ?? apps.length
|
|
1655
|
+
},
|
|
1656
|
+
apps
|
|
1657
|
+
},
|
|
1658
|
+
meta: buildMeta(response)
|
|
1659
|
+
}, `Returned ${apps.length} app info rows`);
|
|
1660
|
+
}
|
|
1661
|
+
catch (error) {
|
|
1662
|
+
return errorResult(error);
|
|
1663
|
+
}
|
|
1664
|
+
});
|
|
1665
|
+
server.registerTool("qf_app_info_get", {
|
|
1666
|
+
title: "Qingflow App Info Get",
|
|
1667
|
+
description: "Get one app's admin info by app_key. Requires admin-level visibility.",
|
|
1668
|
+
inputSchema: appInfoGetInputPublicSchema,
|
|
1669
|
+
outputSchema: appInfoGetOutputSchema,
|
|
1670
|
+
annotations: {
|
|
1671
|
+
readOnlyHint: true,
|
|
1672
|
+
idempotentHint: true
|
|
1673
|
+
}
|
|
1674
|
+
}, async (args) => {
|
|
1675
|
+
try {
|
|
1676
|
+
const parsedArgs = appInfoGetInputSchema.parse(args);
|
|
1677
|
+
if (!parsedArgs.app_key) {
|
|
1678
|
+
throw missingRequiredFieldError({
|
|
1679
|
+
field: "app_key",
|
|
1680
|
+
tool: "qf_app_info_get",
|
|
1681
|
+
fixHint: "Provide app_key (or appKey), for example: {\"app_key\":\"21b3d559\"}."
|
|
1682
|
+
});
|
|
1683
|
+
}
|
|
1684
|
+
let response;
|
|
1685
|
+
try {
|
|
1686
|
+
response = await client.listAppsInfo({
|
|
1687
|
+
appKey: parsedArgs.app_key,
|
|
1688
|
+
pageNum: 1,
|
|
1689
|
+
pageSize: 1
|
|
1690
|
+
});
|
|
1691
|
+
}
|
|
1692
|
+
catch (error) {
|
|
1693
|
+
throw translateAdminApiError(error, {
|
|
1694
|
+
tool: "qf_app_info_get",
|
|
1695
|
+
entity: "app",
|
|
1696
|
+
appKey: parsedArgs.app_key
|
|
1697
|
+
});
|
|
1698
|
+
}
|
|
1699
|
+
const result = asObject(response.result);
|
|
1700
|
+
const app = asArray(result?.apps)
|
|
1701
|
+
.map((item) => normalizeAppInfo(item))
|
|
1702
|
+
.find((item) => item.app_key === parsedArgs.app_key);
|
|
1703
|
+
if (!app) {
|
|
1704
|
+
throw new InputValidationError({
|
|
1705
|
+
message: `App \"${parsedArgs.app_key}\" not found`,
|
|
1706
|
+
errorCode: "APP_NOT_FOUND",
|
|
1707
|
+
fixHint: "Call qf_apps_list or qf_apps_info_list first to confirm the exact app_key.",
|
|
1708
|
+
details: {
|
|
1709
|
+
tool: "qf_app_info_get",
|
|
1710
|
+
app_key: parsedArgs.app_key
|
|
1711
|
+
}
|
|
1712
|
+
});
|
|
1713
|
+
}
|
|
1714
|
+
return okResult({
|
|
1715
|
+
ok: true,
|
|
1716
|
+
data: {
|
|
1717
|
+
app
|
|
1718
|
+
},
|
|
1719
|
+
meta: buildMeta(response)
|
|
1720
|
+
}, `Fetched app ${parsedArgs.app_key}`);
|
|
1721
|
+
}
|
|
1722
|
+
catch (error) {
|
|
1723
|
+
return errorResult(error);
|
|
1724
|
+
}
|
|
1725
|
+
});
|
|
1726
|
+
server.registerTool("qf_app_packages_list", {
|
|
1727
|
+
title: "Qingflow App Packages List",
|
|
1728
|
+
description: "List app packages visible to one user, with optional local tag/keyword slicing.",
|
|
1729
|
+
inputSchema: appPackageListInputPublicSchema,
|
|
1730
|
+
outputSchema: appPackageListOutputSchema,
|
|
1731
|
+
annotations: {
|
|
1732
|
+
readOnlyHint: true,
|
|
1733
|
+
idempotentHint: true
|
|
1734
|
+
}
|
|
1735
|
+
}, async (args) => {
|
|
1736
|
+
try {
|
|
1737
|
+
const parsedArgs = appPackageListInputSchema.parse(args);
|
|
1738
|
+
if (!parsedArgs.user_id) {
|
|
1739
|
+
throw missingRequiredFieldError({
|
|
1740
|
+
field: "user_id",
|
|
1741
|
+
tool: "qf_app_packages_list",
|
|
1742
|
+
fixHint: "Provide user_id (or userId), for example: {\"user_id\":\"u_123\"}."
|
|
1743
|
+
});
|
|
1744
|
+
}
|
|
1745
|
+
const response = await client.listAppPackages({
|
|
1746
|
+
userId: parsedArgs.user_id
|
|
1747
|
+
});
|
|
1748
|
+
const keyword = parsedArgs.keyword?.trim().toLowerCase() ?? null;
|
|
1749
|
+
const limit = parsedArgs.limit ?? 50;
|
|
1750
|
+
const offset = parsedArgs.offset ?? 0;
|
|
1751
|
+
let packages = asArray(asObject(response.result)?.tagList).map((item) => normalizeAppPackage(item));
|
|
1752
|
+
if (parsedArgs.tag_id !== undefined) {
|
|
1753
|
+
packages = packages.filter((item) => String(item.tag_id ?? "") === String(parsedArgs.tag_id));
|
|
1754
|
+
if (packages.length === 0) {
|
|
1755
|
+
throw new InputValidationError({
|
|
1756
|
+
message: `App package \"${String(parsedArgs.tag_id)}\" not found`,
|
|
1757
|
+
errorCode: "APP_PACKAGE_NOT_FOUND",
|
|
1758
|
+
fixHint: "Call qf_app_packages_list without tag_id first to confirm the exact package id.",
|
|
1759
|
+
details: {
|
|
1760
|
+
tool: "qf_app_packages_list",
|
|
1761
|
+
tag_id: parsedArgs.tag_id,
|
|
1762
|
+
user_id: parsedArgs.user_id
|
|
1763
|
+
}
|
|
1764
|
+
});
|
|
1765
|
+
}
|
|
1766
|
+
}
|
|
1767
|
+
const filtered = keyword
|
|
1768
|
+
? packages.filter((item) => {
|
|
1769
|
+
const values = [
|
|
1770
|
+
item.tag_name ?? "",
|
|
1771
|
+
...item.apps.map((app) => app.app_name ?? ""),
|
|
1772
|
+
...item.dashboards.map((dash) => dash.dash_name ?? "")
|
|
1773
|
+
];
|
|
1774
|
+
return values.some((value) => value.toLowerCase().includes(keyword));
|
|
1775
|
+
})
|
|
1776
|
+
: packages;
|
|
1777
|
+
const sliced = filtered.slice(offset, offset + limit);
|
|
1778
|
+
return okResult({
|
|
1779
|
+
ok: true,
|
|
1780
|
+
data: {
|
|
1781
|
+
user_id: parsedArgs.user_id,
|
|
1782
|
+
tag_id_filter: parsedArgs.tag_id ?? null,
|
|
1783
|
+
total_packages: filtered.length,
|
|
1784
|
+
returned_packages: sliced.length,
|
|
1785
|
+
limit,
|
|
1786
|
+
offset,
|
|
1787
|
+
packages: sliced
|
|
1788
|
+
},
|
|
1789
|
+
meta: buildMeta(response)
|
|
1790
|
+
}, `Returned ${sliced.length}/${filtered.length} app packages`);
|
|
1791
|
+
}
|
|
1792
|
+
catch (error) {
|
|
1793
|
+
return errorResult(error);
|
|
1794
|
+
}
|
|
1795
|
+
});
|
|
1796
|
+
server.registerTool("qf_apply_audit_records_list", {
|
|
1797
|
+
title: "Qingflow Apply Audit Records List",
|
|
1798
|
+
description: "List one record's workflow audit log and current pending nodes.",
|
|
1799
|
+
inputSchema: applyAuditRecordsInputPublicSchema,
|
|
1800
|
+
outputSchema: applyAuditRecordsOutputSchema,
|
|
1801
|
+
annotations: {
|
|
1802
|
+
readOnlyHint: true,
|
|
1803
|
+
idempotentHint: true
|
|
1804
|
+
}
|
|
1805
|
+
}, async (args) => {
|
|
1806
|
+
try {
|
|
1807
|
+
const parsedArgs = applyAuditRecordsInputSchema.parse(args);
|
|
1808
|
+
if (!parsedArgs.apply_id) {
|
|
1809
|
+
throw missingRequiredFieldError({
|
|
1810
|
+
field: "apply_id",
|
|
1811
|
+
tool: "qf_apply_audit_records_list",
|
|
1812
|
+
fixHint: "Provide apply_id (or applyId), for example: {\"apply_id\":\"50001234\"}."
|
|
1813
|
+
});
|
|
1814
|
+
}
|
|
1815
|
+
let response;
|
|
1816
|
+
try {
|
|
1817
|
+
response = await client.listApplyAuditRecords(parsedArgs.apply_id);
|
|
1818
|
+
}
|
|
1819
|
+
catch (error) {
|
|
1820
|
+
throw translateAdminApiError(error, {
|
|
1821
|
+
tool: "qf_apply_audit_records_list",
|
|
1822
|
+
entity: "apply",
|
|
1823
|
+
applyId: parsedArgs.apply_id
|
|
1824
|
+
});
|
|
1825
|
+
}
|
|
1826
|
+
const result = asObject(response.result);
|
|
1827
|
+
return okResult({
|
|
1828
|
+
ok: true,
|
|
1829
|
+
data: {
|
|
1830
|
+
apply_id: parsedArgs.apply_id,
|
|
1831
|
+
apply_status: result?.applyStatus ?? null,
|
|
1832
|
+
audit_records: asArray(result?.auditRecords).map((item) => normalizeAuditRecordSummary(item)),
|
|
1833
|
+
current_nodes: asArray(result?.currentNodes).map((item) => normalizeAuditRecordSummary(item))
|
|
1834
|
+
},
|
|
1835
|
+
meta: buildMeta(response)
|
|
1836
|
+
}, `Fetched audit records for apply ${parsedArgs.apply_id}`);
|
|
1837
|
+
}
|
|
1838
|
+
catch (error) {
|
|
1839
|
+
return errorResult(error);
|
|
1840
|
+
}
|
|
1841
|
+
});
|
|
1842
|
+
server.registerTool("qf_apply_audit_record_get", {
|
|
1843
|
+
title: "Qingflow Apply Audit Record Get",
|
|
1844
|
+
description: "Get one workflow audit record detail by apply_id and audit_rcd_id.",
|
|
1845
|
+
inputSchema: applyAuditRecordGetInputPublicSchema,
|
|
1846
|
+
outputSchema: applyAuditRecordGetOutputSchema,
|
|
1847
|
+
annotations: {
|
|
1848
|
+
readOnlyHint: true,
|
|
1849
|
+
idempotentHint: true
|
|
1850
|
+
}
|
|
1851
|
+
}, async (args) => {
|
|
1852
|
+
try {
|
|
1853
|
+
const parsedArgs = applyAuditRecordGetInputSchema.parse(args);
|
|
1854
|
+
if (!parsedArgs.apply_id) {
|
|
1855
|
+
throw missingRequiredFieldError({
|
|
1856
|
+
field: "apply_id",
|
|
1857
|
+
tool: "qf_apply_audit_record_get",
|
|
1858
|
+
fixHint: "Provide apply_id (or applyId), for example: {\"apply_id\":\"50001234\",\"audit_rcd_id\":\"1111\"}."
|
|
1859
|
+
});
|
|
1860
|
+
}
|
|
1861
|
+
if (!parsedArgs.audit_rcd_id) {
|
|
1862
|
+
throw missingRequiredFieldError({
|
|
1863
|
+
field: "audit_rcd_id",
|
|
1864
|
+
tool: "qf_apply_audit_record_get",
|
|
1865
|
+
fixHint: "Provide audit_rcd_id (or auditRcdId), for example: {\"apply_id\":\"50001234\",\"audit_rcd_id\":\"1111\"}."
|
|
1866
|
+
});
|
|
1867
|
+
}
|
|
1868
|
+
let response;
|
|
1869
|
+
try {
|
|
1870
|
+
response = await client.getApplyAuditRecord(parsedArgs.apply_id, parsedArgs.audit_rcd_id);
|
|
1871
|
+
}
|
|
1872
|
+
catch (error) {
|
|
1873
|
+
throw translateAdminApiError(error, {
|
|
1874
|
+
tool: "qf_apply_audit_record_get",
|
|
1875
|
+
entity: "audit_record",
|
|
1876
|
+
applyId: parsedArgs.apply_id,
|
|
1877
|
+
auditRcdId: parsedArgs.audit_rcd_id
|
|
1878
|
+
});
|
|
1879
|
+
}
|
|
1880
|
+
const result = asObject(response.result);
|
|
1881
|
+
return okResult({
|
|
1882
|
+
ok: true,
|
|
1883
|
+
data: {
|
|
1884
|
+
apply_id: parsedArgs.apply_id,
|
|
1885
|
+
audit_rcd_id: result?.auditRcdId ?? parsedArgs.audit_rcd_id,
|
|
1886
|
+
modifies: normalizeAuditModifies(result?.auditModifies)
|
|
1887
|
+
},
|
|
1888
|
+
meta: buildMeta(response)
|
|
1889
|
+
}, `Fetched audit record ${parsedArgs.audit_rcd_id} for apply ${parsedArgs.apply_id}`);
|
|
1890
|
+
}
|
|
1891
|
+
catch (error) {
|
|
1892
|
+
return errorResult(error);
|
|
1893
|
+
}
|
|
1894
|
+
});
|
|
1421
1895
|
server.registerTool("qf_departments_list", {
|
|
1422
1896
|
title: "Qingflow Departments List",
|
|
1423
1897
|
description: "List departments with optional dept_id filter and local keyword slicing.",
|
|
@@ -2391,6 +2865,174 @@ function normalizeUser(raw) {
|
|
|
2391
2865
|
superior_id: asNullableString(obj.superiorId)
|
|
2392
2866
|
};
|
|
2393
2867
|
}
|
|
2868
|
+
function normalizeAppAuthMembers(raw) {
|
|
2869
|
+
const obj = asObject(raw) ?? {};
|
|
2870
|
+
return {
|
|
2871
|
+
users: asArray(obj.users).map((item) => {
|
|
2872
|
+
const entry = asObject(item) ?? {};
|
|
2873
|
+
return {
|
|
2874
|
+
user_id: asNullableString(entry.userId),
|
|
2875
|
+
user_name: asNullableString(entry.userName)
|
|
2876
|
+
};
|
|
2877
|
+
}),
|
|
2878
|
+
departments: asArray(obj.depts).map((item) => {
|
|
2879
|
+
const entry = asObject(item) ?? {};
|
|
2880
|
+
return {
|
|
2881
|
+
dept_id: toNonNegativeInt(entry.deptId),
|
|
2882
|
+
dept_name: asNullableString(entry.deptName)
|
|
2883
|
+
};
|
|
2884
|
+
}),
|
|
2885
|
+
roles: asArray(obj.roles).map((item) => {
|
|
2886
|
+
const entry = asObject(item) ?? {};
|
|
2887
|
+
return {
|
|
2888
|
+
role_id: toNonNegativeInt(entry.roleId),
|
|
2889
|
+
role_name: asNullableString(entry.roleName)
|
|
2890
|
+
};
|
|
2891
|
+
})
|
|
2892
|
+
};
|
|
2893
|
+
}
|
|
2894
|
+
function normalizeAppInfo(raw) {
|
|
2895
|
+
const obj = asObject(raw) ?? {};
|
|
2896
|
+
const creator = asObject(obj.creator) ?? {};
|
|
2897
|
+
return {
|
|
2898
|
+
app_key: asNullableString(obj.appKey),
|
|
2899
|
+
app_name: asNullableString(obj.appName),
|
|
2900
|
+
app_auth: toNonNegativeInt(obj.appAuth),
|
|
2901
|
+
app_icon: asNullableString(obj.appIcon),
|
|
2902
|
+
auth_members: normalizeAppAuthMembers(obj.authmembers ?? obj.authMembers),
|
|
2903
|
+
creator: {
|
|
2904
|
+
user_id: asNullableString(creator.userId),
|
|
2905
|
+
nick_name: asNullableString(creator.nickName),
|
|
2906
|
+
head_img: asNullableString(creator.headImg)
|
|
2907
|
+
},
|
|
2908
|
+
create_time: asNullableString(obj.createTime),
|
|
2909
|
+
tags: asArray(obj.tags).map((item) => {
|
|
2910
|
+
const entry = asObject(item) ?? {};
|
|
2911
|
+
return {
|
|
2912
|
+
tag_id: toNonNegativeInt(entry.tagId),
|
|
2913
|
+
tag_name: asNullableString(entry.tagName)
|
|
2914
|
+
};
|
|
2915
|
+
}),
|
|
2916
|
+
app_publish_status: toNonNegativeInt(obj.appPublishStatus)
|
|
2917
|
+
};
|
|
2918
|
+
}
|
|
2919
|
+
function normalizeAppPackage(raw) {
|
|
2920
|
+
const obj = asObject(raw) ?? {};
|
|
2921
|
+
return {
|
|
2922
|
+
tag_id: toNonNegativeInt(obj.tagId),
|
|
2923
|
+
tag_name: asNullableString(obj.tagName),
|
|
2924
|
+
tag_icon: asNullableString(obj.tagIcon),
|
|
2925
|
+
apps: asArray(obj.appList).map((item) => {
|
|
2926
|
+
const entry = asObject(item) ?? {};
|
|
2927
|
+
return {
|
|
2928
|
+
app_key: asNullableString(entry.appKey),
|
|
2929
|
+
app_name: asNullableString(entry.appName)
|
|
2930
|
+
};
|
|
2931
|
+
}),
|
|
2932
|
+
dashboards: asArray(obj.dashList).map((item) => {
|
|
2933
|
+
const entry = asObject(item) ?? {};
|
|
2934
|
+
return {
|
|
2935
|
+
dash_key: asNullableString(entry.dashKey),
|
|
2936
|
+
dash_name: asNullableString(entry.dashName)
|
|
2937
|
+
};
|
|
2938
|
+
})
|
|
2939
|
+
};
|
|
2940
|
+
}
|
|
2941
|
+
function normalizeAuditUserInfo(raw) {
|
|
2942
|
+
const obj = asObject(raw) ?? {};
|
|
2943
|
+
return {
|
|
2944
|
+
user_id: asNullableString(obj.userId),
|
|
2945
|
+
user_name: asNullableString(obj.userName),
|
|
2946
|
+
nick_name: asNullableString(obj.nickName),
|
|
2947
|
+
head_img: asNullableString(obj.headImg)
|
|
2948
|
+
};
|
|
2949
|
+
}
|
|
2950
|
+
function toNullableSpecialId(value) {
|
|
2951
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
2952
|
+
return Math.trunc(value);
|
|
2953
|
+
}
|
|
2954
|
+
if (typeof value === "string" && value.trim()) {
|
|
2955
|
+
const normalized = value.trim();
|
|
2956
|
+
if (/^\d+$/.test(normalized)) {
|
|
2957
|
+
return Number(normalized);
|
|
2958
|
+
}
|
|
2959
|
+
return normalized;
|
|
2960
|
+
}
|
|
2961
|
+
const obj = asObject(value);
|
|
2962
|
+
if (!obj) {
|
|
2963
|
+
return null;
|
|
2964
|
+
}
|
|
2965
|
+
const candidate = obj.queId ?? obj.id ?? obj.value ?? obj.dataValue ?? null;
|
|
2966
|
+
return candidate === null ? null : toNullableSpecialId(candidate);
|
|
2967
|
+
}
|
|
2968
|
+
function normalizeAuditRecordSummary(raw) {
|
|
2969
|
+
const obj = asObject(raw) ?? {};
|
|
2970
|
+
return {
|
|
2971
|
+
audit_rcd_id: toNonNegativeInt(obj.auditRcdId),
|
|
2972
|
+
audit_node_id: toNonNegativeInt(obj.auditNodeId),
|
|
2973
|
+
audit_node_name: asNullableString(obj.auditNodeName),
|
|
2974
|
+
audit_time_ms: toNonNegativeInt(obj.auditTime),
|
|
2975
|
+
audit_result: obj.auditResult ?? null,
|
|
2976
|
+
audit_feedback: asNullableString(obj.auditFeedback),
|
|
2977
|
+
audit_user: obj.auditUser ? normalizeAuditUserInfo(obj.auditUser) : null,
|
|
2978
|
+
wait_audit_users: asArray(obj.waitAuditUserList).map((item) => normalizeAuditUserInfo(item))
|
|
2979
|
+
};
|
|
2980
|
+
}
|
|
2981
|
+
function normalizeAuditModifies(raw) {
|
|
2982
|
+
const source = Array.isArray(raw)
|
|
2983
|
+
? raw
|
|
2984
|
+
: asObject(raw)
|
|
2985
|
+
? Object.values(raw)
|
|
2986
|
+
: [];
|
|
2987
|
+
return source.map((item) => {
|
|
2988
|
+
const entry = asObject(item) ?? {};
|
|
2989
|
+
return {
|
|
2990
|
+
que_id: toNullableSpecialId(entry.queId),
|
|
2991
|
+
que_title: asNullableString(entry.queTitle),
|
|
2992
|
+
que_type: entry.queType ?? null,
|
|
2993
|
+
before_answer: asArray(entry.beforeAnswer),
|
|
2994
|
+
after_answer: asArray(entry.afterAnswer)
|
|
2995
|
+
};
|
|
2996
|
+
});
|
|
2997
|
+
}
|
|
2998
|
+
function translateAdminApiError(error, params) {
|
|
2999
|
+
if (error instanceof QingflowApiError &&
|
|
3000
|
+
(error.httpStatus === 404 || error.errCode === 404)) {
|
|
3001
|
+
if (params.entity === "app") {
|
|
3002
|
+
return new InputValidationError({
|
|
3003
|
+
message: `App \"${params.appKey}\" not found`,
|
|
3004
|
+
errorCode: "APP_NOT_FOUND",
|
|
3005
|
+
fixHint: "Call qf_apps_list or qf_apps_info_list first to confirm the exact app_key.",
|
|
3006
|
+
details: {
|
|
3007
|
+
tool: params.tool,
|
|
3008
|
+
app_key: params.appKey
|
|
3009
|
+
}
|
|
3010
|
+
});
|
|
3011
|
+
}
|
|
3012
|
+
if (params.entity === "apply") {
|
|
3013
|
+
return new InputValidationError({
|
|
3014
|
+
message: `Apply \"${params.applyId}\" not found`,
|
|
3015
|
+
errorCode: "APPLY_NOT_FOUND",
|
|
3016
|
+
fixHint: "Use qf_record_get or your record query tools first to confirm the exact apply_id.",
|
|
3017
|
+
details: {
|
|
3018
|
+
tool: params.tool,
|
|
3019
|
+
apply_id: params.applyId
|
|
3020
|
+
}
|
|
3021
|
+
});
|
|
3022
|
+
}
|
|
3023
|
+
return new InputValidationError({
|
|
3024
|
+
message: `Audit record \"${params.auditRcdId}\" for apply \"${params.applyId}\" not found`,
|
|
3025
|
+
errorCode: "AUDIT_RECORD_NOT_FOUND",
|
|
3026
|
+
fixHint: "Call qf_apply_audit_records_list first to confirm the exact audit_rcd_id.",
|
|
3027
|
+
details: {
|
|
3028
|
+
tool: params.tool,
|
|
3029
|
+
apply_id: params.applyId,
|
|
3030
|
+
audit_rcd_id: params.auditRcdId
|
|
3031
|
+
}
|
|
3032
|
+
});
|
|
3033
|
+
}
|
|
3034
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
3035
|
+
}
|
|
2394
3036
|
function translateDirectoryApiError(error, params) {
|
|
2395
3037
|
if (error instanceof QingflowApiError &&
|
|
2396
3038
|
(error.httpStatus === 404 || error.errCode === 404)) {
|
|
@@ -2437,6 +3079,7 @@ function missingRequiredFieldError(params) {
|
|
|
2437
3079
|
const COMMON_INPUT_ALIASES = {
|
|
2438
3080
|
appKey: "app_key",
|
|
2439
3081
|
userId: "user_id",
|
|
3082
|
+
tagId: "tag_id",
|
|
2440
3083
|
pageNum: "page_num",
|
|
2441
3084
|
pageSize: "page_size",
|
|
2442
3085
|
pageToken: "page_token",
|
|
@@ -2448,6 +3091,7 @@ const COMMON_INPUT_ALIASES = {
|
|
|
2448
3091
|
queryMode: "query_mode",
|
|
2449
3092
|
queryLogic: "query_logic",
|
|
2450
3093
|
applyId: "apply_id",
|
|
3094
|
+
auditRcdId: "audit_rcd_id",
|
|
2451
3095
|
applyIds: "apply_ids",
|
|
2452
3096
|
maxRows: "max_rows",
|
|
2453
3097
|
rowLimit: "max_rows",
|
|
@@ -2582,6 +3226,87 @@ function normalizeUserGetInput(raw) {
|
|
|
2582
3226
|
user_id: coerceStringLike(normalizedObj.user_id)
|
|
2583
3227
|
};
|
|
2584
3228
|
}
|
|
3229
|
+
function normalizeAppInfoListInput(raw) {
|
|
3230
|
+
const parsedRoot = parseJsonLikeDeep(raw);
|
|
3231
|
+
const obj = asObject(parsedRoot);
|
|
3232
|
+
if (!obj) {
|
|
3233
|
+
return parsedRoot;
|
|
3234
|
+
}
|
|
3235
|
+
const normalizedObj = applyAliases(obj, {
|
|
3236
|
+
appKey: "app_key",
|
|
3237
|
+
pageNum: "page_num",
|
|
3238
|
+
pageSize: "page_size"
|
|
3239
|
+
});
|
|
3240
|
+
return {
|
|
3241
|
+
...normalizedObj,
|
|
3242
|
+
app_key: coerceStringLike(normalizedObj.app_key),
|
|
3243
|
+
page_num: coerceNumberLike(normalizedObj.page_num),
|
|
3244
|
+
page_size: coerceNumberLike(normalizedObj.page_size)
|
|
3245
|
+
};
|
|
3246
|
+
}
|
|
3247
|
+
function normalizeAppInfoGetInput(raw) {
|
|
3248
|
+
const parsedRoot = parseJsonLikeDeep(raw);
|
|
3249
|
+
const obj = asObject(parsedRoot);
|
|
3250
|
+
if (!obj) {
|
|
3251
|
+
return parsedRoot;
|
|
3252
|
+
}
|
|
3253
|
+
const normalizedObj = applyAliases(obj, {
|
|
3254
|
+
appKey: "app_key"
|
|
3255
|
+
});
|
|
3256
|
+
return {
|
|
3257
|
+
...normalizedObj,
|
|
3258
|
+
app_key: coerceStringLike(normalizedObj.app_key)
|
|
3259
|
+
};
|
|
3260
|
+
}
|
|
3261
|
+
function normalizeAppPackageListInput(raw) {
|
|
3262
|
+
const parsedRoot = parseJsonLikeDeep(raw);
|
|
3263
|
+
const obj = asObject(parsedRoot);
|
|
3264
|
+
if (!obj) {
|
|
3265
|
+
return parsedRoot;
|
|
3266
|
+
}
|
|
3267
|
+
const normalizedObj = applyAliases(obj, {
|
|
3268
|
+
userId: "user_id",
|
|
3269
|
+
tagId: "tag_id"
|
|
3270
|
+
});
|
|
3271
|
+
return {
|
|
3272
|
+
...normalizedObj,
|
|
3273
|
+
user_id: coerceStringLike(normalizedObj.user_id),
|
|
3274
|
+
tag_id: coerceNumberLike(normalizeSelectorInputValue(normalizedObj.tag_id)),
|
|
3275
|
+
keyword: coerceStringLike(normalizedObj.keyword),
|
|
3276
|
+
limit: coerceNumberLike(normalizedObj.limit),
|
|
3277
|
+
offset: coerceNumberLike(normalizedObj.offset)
|
|
3278
|
+
};
|
|
3279
|
+
}
|
|
3280
|
+
function normalizeApplyAuditRecordsInput(raw) {
|
|
3281
|
+
const parsedRoot = parseJsonLikeDeep(raw);
|
|
3282
|
+
const obj = asObject(parsedRoot);
|
|
3283
|
+
if (!obj) {
|
|
3284
|
+
return parsedRoot;
|
|
3285
|
+
}
|
|
3286
|
+
const normalizedObj = applyAliases(obj, {
|
|
3287
|
+
applyId: "apply_id"
|
|
3288
|
+
});
|
|
3289
|
+
return {
|
|
3290
|
+
...normalizedObj,
|
|
3291
|
+
apply_id: coerceStringLike(normalizedObj.apply_id)
|
|
3292
|
+
};
|
|
3293
|
+
}
|
|
3294
|
+
function normalizeApplyAuditRecordGetInput(raw) {
|
|
3295
|
+
const parsedRoot = parseJsonLikeDeep(raw);
|
|
3296
|
+
const obj = asObject(parsedRoot);
|
|
3297
|
+
if (!obj) {
|
|
3298
|
+
return parsedRoot;
|
|
3299
|
+
}
|
|
3300
|
+
const normalizedObj = applyAliases(obj, {
|
|
3301
|
+
applyId: "apply_id",
|
|
3302
|
+
auditRcdId: "audit_rcd_id"
|
|
3303
|
+
});
|
|
3304
|
+
return {
|
|
3305
|
+
...normalizedObj,
|
|
3306
|
+
apply_id: coerceStringLike(normalizedObj.apply_id),
|
|
3307
|
+
audit_rcd_id: coerceStringLike(normalizedObj.audit_rcd_id)
|
|
3308
|
+
};
|
|
3309
|
+
}
|
|
2585
3310
|
function buildToolSpecCatalog() {
|
|
2586
3311
|
return [
|
|
2587
3312
|
{
|
|
@@ -2611,6 +3336,67 @@ function buildToolSpecCatalog() {
|
|
|
2611
3336
|
limit: 20
|
|
2612
3337
|
}
|
|
2613
3338
|
},
|
|
3339
|
+
{
|
|
3340
|
+
tool: "qf_apps_info_list",
|
|
3341
|
+
required: ["page_num", "page_size"],
|
|
3342
|
+
limits: {
|
|
3343
|
+
input_contract: "strict JSON only; page_num/page_size must be native JSON numbers"
|
|
3344
|
+
},
|
|
3345
|
+
aliases: collectAliasHints(["page_num", "page_size", "app_key"], {}),
|
|
3346
|
+
minimal_example: {
|
|
3347
|
+
page_num: 1,
|
|
3348
|
+
page_size: 50,
|
|
3349
|
+
app_key: "21b3d559"
|
|
3350
|
+
}
|
|
3351
|
+
},
|
|
3352
|
+
{
|
|
3353
|
+
tool: "qf_app_info_get",
|
|
3354
|
+
required: ["app_key"],
|
|
3355
|
+
limits: {
|
|
3356
|
+
input_contract: "strict JSON only; app_key must be a native JSON string"
|
|
3357
|
+
},
|
|
3358
|
+
aliases: collectAliasHints(["app_key"], {}),
|
|
3359
|
+
minimal_example: {
|
|
3360
|
+
app_key: "21b3d559"
|
|
3361
|
+
}
|
|
3362
|
+
},
|
|
3363
|
+
{
|
|
3364
|
+
tool: "qf_app_packages_list",
|
|
3365
|
+
required: ["user_id"],
|
|
3366
|
+
limits: {
|
|
3367
|
+
limit_max: 500,
|
|
3368
|
+
offset_min: 0,
|
|
3369
|
+
input_contract: "strict JSON only; user_id must be a native JSON string when provided"
|
|
3370
|
+
},
|
|
3371
|
+
aliases: collectAliasHints(["user_id", "tag_id"], {}),
|
|
3372
|
+
minimal_example: {
|
|
3373
|
+
user_id: "u_123",
|
|
3374
|
+
limit: 20
|
|
3375
|
+
}
|
|
3376
|
+
},
|
|
3377
|
+
{
|
|
3378
|
+
tool: "qf_apply_audit_records_list",
|
|
3379
|
+
required: ["apply_id"],
|
|
3380
|
+
limits: {
|
|
3381
|
+
input_contract: "strict JSON only; apply_id must be a native JSON string"
|
|
3382
|
+
},
|
|
3383
|
+
aliases: collectAliasHints(["apply_id"], {}),
|
|
3384
|
+
minimal_example: {
|
|
3385
|
+
apply_id: "50001234"
|
|
3386
|
+
}
|
|
3387
|
+
},
|
|
3388
|
+
{
|
|
3389
|
+
tool: "qf_apply_audit_record_get",
|
|
3390
|
+
required: ["apply_id", "audit_rcd_id"],
|
|
3391
|
+
limits: {
|
|
3392
|
+
input_contract: "strict JSON only; apply_id/audit_rcd_id must be native JSON strings"
|
|
3393
|
+
},
|
|
3394
|
+
aliases: collectAliasHints(["apply_id", "audit_rcd_id"], {}),
|
|
3395
|
+
minimal_example: {
|
|
3396
|
+
apply_id: "50001234",
|
|
3397
|
+
audit_rcd_id: "1111"
|
|
3398
|
+
}
|
|
3399
|
+
},
|
|
2614
3400
|
{
|
|
2615
3401
|
tool: "qf_departments_list",
|
|
2616
3402
|
required: [],
|