@josephyan/qingflow-app-user-mcp 0.2.0-beta.1007 → 0.2.0-beta.1008
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 +2 -2
- package/package.json +1 -1
- package/pyproject.toml +1 -1
- package/src/qingflow_mcp/__init__.py +1 -1
- package/src/qingflow_mcp/cli/commands/task.py +37 -56
package/README.md
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
Install:
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
|
-
npm install @josephyan/qingflow-app-user-mcp@0.2.0-beta.
|
|
6
|
+
npm install @josephyan/qingflow-app-user-mcp@0.2.0-beta.1008
|
|
7
7
|
```
|
|
8
8
|
|
|
9
9
|
Run:
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
npx -y -p @josephyan/qingflow-app-user-mcp@0.2.0-beta.
|
|
12
|
+
npx -y -p @josephyan/qingflow-app-user-mcp@0.2.0-beta.1008 qingflow-app-user-mcp
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
Environment:
|
package/package.json
CHANGED
package/pyproject.toml
CHANGED
|
@@ -212,25 +212,15 @@ def _run_task_workbench_task_loop(args: argparse.Namespace, context: CliContext)
|
|
|
212
212
|
detail_selection = _show_task_workbench_detail(args, task_context)
|
|
213
213
|
if detail_selection.status == "cancelled":
|
|
214
214
|
return "back", ""
|
|
215
|
-
|
|
215
|
+
selected_value = str(detail_selection.value or "").strip()
|
|
216
|
+
if selected_value == "exit":
|
|
216
217
|
return "result", cancelled_result("已退出")
|
|
217
|
-
if
|
|
218
|
+
if selected_value == "back":
|
|
218
219
|
return "back", ""
|
|
219
|
-
|
|
220
|
-
action_selection = _choose_task_action_interactively(
|
|
221
|
-
args,
|
|
222
|
-
task_context,
|
|
223
|
-
fields={},
|
|
224
|
-
title=_build_task_action_title(task_context),
|
|
225
|
-
)
|
|
226
|
-
if action_selection.status == "cancelled":
|
|
227
|
-
continue
|
|
228
|
-
if action_selection.status == "empty":
|
|
220
|
+
if not selected_value:
|
|
229
221
|
continue
|
|
230
|
-
if action_selection.status != "selected":
|
|
231
|
-
return "result", cancelled_result("已退出")
|
|
232
222
|
|
|
233
|
-
args.action =
|
|
223
|
+
args.action = selected_value
|
|
234
224
|
payload_selection = _resolve_action_payload_or_select(args, task_context, payload={})
|
|
235
225
|
if _is_cancelled_result(payload_selection):
|
|
236
226
|
continue
|
|
@@ -421,35 +411,8 @@ def _choose_task_action_interactively(
|
|
|
421
411
|
fields: dict[str, Any],
|
|
422
412
|
title: str = "选择操作",
|
|
423
413
|
):
|
|
424
|
-
data = task_context.get("data") if isinstance(task_context.get("data"), dict) else {}
|
|
425
|
-
available_actions = [str(item).strip() for item in (data.get("available_actions") or []) if str(item).strip()]
|
|
426
|
-
extras = data.get("extras") if isinstance(data.get("extras"), dict) else {}
|
|
427
|
-
action_metadata = data.get("action_metadata") if isinstance(data.get("action_metadata"), dict) else {}
|
|
428
|
-
feedback_required = {
|
|
429
|
-
str(item).strip()
|
|
430
|
-
for item in (action_metadata.get("feedback_required_for") or [])
|
|
431
|
-
if str(item).strip()
|
|
432
|
-
}
|
|
433
|
-
rollback_count = _count_candidate_items(extras.get("rollback_candidates"))
|
|
434
|
-
transfer_count = _count_candidate_items(extras.get("transfer_candidates"))
|
|
435
|
-
|
|
436
414
|
def load_options() -> list[SelectionOption[str]]:
|
|
437
|
-
|
|
438
|
-
for action in available_actions:
|
|
439
|
-
if action == "save_only" and not fields:
|
|
440
|
-
continue
|
|
441
|
-
label = TASK_ACTION_LABELS.get(action, action)
|
|
442
|
-
hint_parts = [action]
|
|
443
|
-
if action in feedback_required:
|
|
444
|
-
hint_parts.append("需要理由")
|
|
445
|
-
if action == "rollback":
|
|
446
|
-
hint_parts.append(f"可退回节点 {rollback_count}")
|
|
447
|
-
if action == "transfer":
|
|
448
|
-
hint_parts.append(f"可转交成员 {transfer_count}")
|
|
449
|
-
if action == "save_only":
|
|
450
|
-
hint_parts.append("仅保存字段,不推进流程")
|
|
451
|
-
options.append(SelectionOption(value=action, label=label, hint=" · ".join(hint_parts)))
|
|
452
|
-
return options
|
|
415
|
+
return _task_interactive_action_options(task_context, fields=fields)
|
|
453
416
|
|
|
454
417
|
return resolve_interactive_selection(
|
|
455
418
|
args,
|
|
@@ -461,14 +424,11 @@ def _choose_task_action_interactively(
|
|
|
461
424
|
|
|
462
425
|
|
|
463
426
|
def _show_task_workbench_detail(args: argparse.Namespace, task_context: dict[str, Any]):
|
|
464
|
-
has_actions = _task_has_interactive_actions(task_context)
|
|
465
|
-
|
|
466
427
|
def load_options() -> list[SelectionOption[str]]:
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
]
|
|
428
|
+
options = _task_interactive_action_options(task_context, fields={})
|
|
429
|
+
if options:
|
|
430
|
+
options.append(SelectionOption(value="back", label="返回列表", hint="回到待办列表"))
|
|
431
|
+
return options
|
|
472
432
|
return [
|
|
473
433
|
SelectionOption(value="back", label="返回列表", hint="当前节点没有可执行动作"),
|
|
474
434
|
SelectionOption(value="exit", label="退出工作台", hint="结束当前待办工作台"),
|
|
@@ -697,10 +657,6 @@ def _build_task_detail_title(task_context: dict[str, Any]) -> str:
|
|
|
697
657
|
return "\n".join(lines)
|
|
698
658
|
|
|
699
659
|
|
|
700
|
-
def _build_task_action_title(task_context: dict[str, Any]) -> str:
|
|
701
|
-
return _build_task_detail_title(task_context) + "\n\n选择操作"
|
|
702
|
-
|
|
703
|
-
|
|
704
660
|
def _task_initiator_label(initiator: dict[str, Any]) -> str:
|
|
705
661
|
for key in ("display_name", "displayName", "name", "email", "uid"):
|
|
706
662
|
value = initiator.get(key)
|
|
@@ -709,10 +665,35 @@ def _task_initiator_label(initiator: dict[str, Any]) -> str:
|
|
|
709
665
|
return "-"
|
|
710
666
|
|
|
711
667
|
|
|
712
|
-
def
|
|
668
|
+
def _task_interactive_action_options(task_context: dict[str, Any], *, fields: dict[str, Any]) -> list[SelectionOption[str]]:
|
|
713
669
|
data = task_context.get("data") if isinstance(task_context.get("data"), dict) else {}
|
|
714
670
|
available_actions = [str(item).strip() for item in (data.get("available_actions") or []) if str(item).strip()]
|
|
715
|
-
|
|
671
|
+
action_metadata = data.get("action_metadata") if isinstance(data.get("action_metadata"), dict) else {}
|
|
672
|
+
extras = data.get("extras") if isinstance(data.get("extras"), dict) else {}
|
|
673
|
+
feedback_required = {
|
|
674
|
+
str(item).strip()
|
|
675
|
+
for item in (action_metadata.get("feedback_required_for") or [])
|
|
676
|
+
if str(item).strip()
|
|
677
|
+
}
|
|
678
|
+
rollback_count = _count_candidate_items(extras.get("rollback_candidates"))
|
|
679
|
+
transfer_count = _count_candidate_items(extras.get("transfer_candidates"))
|
|
680
|
+
|
|
681
|
+
options: list[SelectionOption[str]] = []
|
|
682
|
+
for action in available_actions:
|
|
683
|
+
if action == "save_only" and not fields:
|
|
684
|
+
continue
|
|
685
|
+
label = TASK_ACTION_LABELS.get(action, action)
|
|
686
|
+
hint_parts = [action]
|
|
687
|
+
if action in feedback_required:
|
|
688
|
+
hint_parts.append("需要理由")
|
|
689
|
+
if action == "rollback":
|
|
690
|
+
hint_parts.append(f"可退回节点 {rollback_count}")
|
|
691
|
+
if action == "transfer":
|
|
692
|
+
hint_parts.append(f"可转交成员 {transfer_count}")
|
|
693
|
+
if action == "save_only":
|
|
694
|
+
hint_parts.append("仅保存字段,不推进流程")
|
|
695
|
+
options.append(SelectionOption(value=action, label=label, hint=" · ".join(hint_parts)))
|
|
696
|
+
return options
|
|
716
697
|
|
|
717
698
|
|
|
718
699
|
def _full_display(value: Any) -> str:
|