@josephyan/qingflow-cli 0.2.0-beta.55 → 0.2.0-beta.56
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/cli/commands/app.py +16 -16
- package/src/qingflow_mcp/cli/commands/auth.py +16 -19
- package/src/qingflow_mcp/cli/commands/builder.py +139 -124
- package/src/qingflow_mcp/cli/commands/common.py +95 -21
- package/src/qingflow_mcp/cli/commands/imports.py +34 -42
- package/src/qingflow_mcp/cli/commands/record.py +133 -131
- package/src/qingflow_mcp/cli/commands/task.py +44 -43
- package/src/qingflow_mcp/cli/commands/workspace.py +10 -10
- package/src/qingflow_mcp/cli/context.py +32 -35
- package/src/qingflow_mcp/cli/formatters.py +121 -124
- package/src/qingflow_mcp/cli/main.py +17 -52
- package/src/qingflow_mcp/ops/__init__.py +3 -0
- package/src/qingflow_mcp/ops/apps.py +64 -0
- package/src/qingflow_mcp/ops/auth.py +121 -0
- package/src/qingflow_mcp/ops/base.py +290 -0
- package/src/qingflow_mcp/ops/builder.py +323 -0
- package/src/qingflow_mcp/ops/context.py +120 -0
- package/src/qingflow_mcp/ops/directory.py +171 -0
- package/src/qingflow_mcp/ops/feedback.py +49 -0
- package/src/qingflow_mcp/ops/files.py +78 -0
- package/src/qingflow_mcp/ops/imports.py +140 -0
- package/src/qingflow_mcp/ops/records.py +415 -0
- package/src/qingflow_mcp/ops/tasks.py +171 -0
- package/src/qingflow_mcp/ops/workspace.py +76 -0
- package/src/qingflow_mcp/server_app_builder.py +190 -122
- package/src/qingflow_mcp/server_app_user.py +662 -63
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from .base import normalize_exception, success_result, tool_payload
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TaskOperations:
|
|
9
|
+
def __init__(self, tools: Any) -> None:
|
|
10
|
+
self._tools = tools
|
|
11
|
+
|
|
12
|
+
def list(
|
|
13
|
+
self,
|
|
14
|
+
*,
|
|
15
|
+
profile: str,
|
|
16
|
+
task_box: str,
|
|
17
|
+
flow_status: str,
|
|
18
|
+
app_key: str | None,
|
|
19
|
+
workflow_node_id: int | None,
|
|
20
|
+
query: str | None,
|
|
21
|
+
page: int,
|
|
22
|
+
page_size: int,
|
|
23
|
+
) -> dict:
|
|
24
|
+
try:
|
|
25
|
+
raw = self._tools.task.task_list(
|
|
26
|
+
profile=profile,
|
|
27
|
+
task_box=task_box,
|
|
28
|
+
flow_status=flow_status,
|
|
29
|
+
app_key=app_key,
|
|
30
|
+
workflow_node_id=workflow_node_id,
|
|
31
|
+
query=query,
|
|
32
|
+
page=page,
|
|
33
|
+
page_size=page_size,
|
|
34
|
+
)
|
|
35
|
+
except Exception as error: # noqa: BLE001
|
|
36
|
+
return normalize_exception(error)
|
|
37
|
+
data = tool_payload(raw)
|
|
38
|
+
if isinstance(data, dict) and isinstance(data.get("items"), list):
|
|
39
|
+
items = []
|
|
40
|
+
for item in data["items"]:
|
|
41
|
+
if not isinstance(item, dict):
|
|
42
|
+
continue
|
|
43
|
+
title = item.get("title") or item.get("task_name") or item.get("node_name")
|
|
44
|
+
if not title:
|
|
45
|
+
app_name = item.get("app_name") or item.get("app_key") or "任务"
|
|
46
|
+
record_id = item.get("record_id")
|
|
47
|
+
title = f"{app_name}#{record_id}" if record_id is not None else str(app_name)
|
|
48
|
+
normalized = dict(item)
|
|
49
|
+
normalized["title"] = title
|
|
50
|
+
items.append(normalized)
|
|
51
|
+
data = dict(data)
|
|
52
|
+
data["items"] = items
|
|
53
|
+
return success_result(
|
|
54
|
+
"TASKS_LISTED",
|
|
55
|
+
"已读取待办列表",
|
|
56
|
+
data=data if isinstance(data, dict) else {"items": data},
|
|
57
|
+
warnings=raw.get("warnings") if isinstance(raw, dict) and isinstance(raw.get("warnings"), list) else [],
|
|
58
|
+
meta={"profile": profile},
|
|
59
|
+
legacy=raw,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
def show(
|
|
63
|
+
self,
|
|
64
|
+
*,
|
|
65
|
+
profile: str,
|
|
66
|
+
app_key: str,
|
|
67
|
+
record_id: int,
|
|
68
|
+
workflow_node_id: int,
|
|
69
|
+
include_candidates: bool,
|
|
70
|
+
include_associated_reports: bool,
|
|
71
|
+
) -> dict:
|
|
72
|
+
try:
|
|
73
|
+
raw = self._tools.task.task_get(
|
|
74
|
+
profile=profile,
|
|
75
|
+
app_key=app_key,
|
|
76
|
+
record_id=record_id,
|
|
77
|
+
workflow_node_id=workflow_node_id,
|
|
78
|
+
include_candidates=include_candidates,
|
|
79
|
+
include_associated_reports=include_associated_reports,
|
|
80
|
+
)
|
|
81
|
+
except Exception as error: # noqa: BLE001
|
|
82
|
+
return normalize_exception(error)
|
|
83
|
+
return success_result(
|
|
84
|
+
"TASK_READY",
|
|
85
|
+
"已读取待办详情",
|
|
86
|
+
data=tool_payload(raw),
|
|
87
|
+
warnings=raw.get("warnings") if isinstance(raw, dict) and isinstance(raw.get("warnings"), list) else [],
|
|
88
|
+
meta={"profile": profile},
|
|
89
|
+
legacy=raw,
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
def act(
|
|
93
|
+
self,
|
|
94
|
+
*,
|
|
95
|
+
profile: str,
|
|
96
|
+
app_key: str,
|
|
97
|
+
record_id: int,
|
|
98
|
+
workflow_node_id: int,
|
|
99
|
+
action: str,
|
|
100
|
+
payload: dict,
|
|
101
|
+
) -> dict:
|
|
102
|
+
try:
|
|
103
|
+
raw = self._tools.task.task_action_execute(
|
|
104
|
+
profile=profile,
|
|
105
|
+
app_key=app_key,
|
|
106
|
+
record_id=record_id,
|
|
107
|
+
workflow_node_id=workflow_node_id,
|
|
108
|
+
action=action,
|
|
109
|
+
payload=payload,
|
|
110
|
+
)
|
|
111
|
+
except Exception as error: # noqa: BLE001
|
|
112
|
+
return normalize_exception(error)
|
|
113
|
+
return success_result(
|
|
114
|
+
"TASK_ACTION_EXECUTED",
|
|
115
|
+
"已执行待办动作",
|
|
116
|
+
data=tool_payload(raw),
|
|
117
|
+
warnings=raw.get("warnings") if isinstance(raw, dict) and isinstance(raw.get("warnings"), list) else [],
|
|
118
|
+
meta={"profile": profile, "verification": raw.get("verification") if isinstance(raw, dict) else None},
|
|
119
|
+
legacy=raw,
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
def log(self, *, profile: str, app_key: str, record_id: int, workflow_node_id: int) -> dict:
|
|
123
|
+
try:
|
|
124
|
+
raw = self._tools.task.task_workflow_log_get(
|
|
125
|
+
profile=profile,
|
|
126
|
+
app_key=app_key,
|
|
127
|
+
record_id=record_id,
|
|
128
|
+
workflow_node_id=workflow_node_id,
|
|
129
|
+
)
|
|
130
|
+
except Exception as error: # noqa: BLE001
|
|
131
|
+
return normalize_exception(error)
|
|
132
|
+
return success_result(
|
|
133
|
+
"TASK_LOG_READY",
|
|
134
|
+
"已读取流程日志",
|
|
135
|
+
data=tool_payload(raw),
|
|
136
|
+
warnings=raw.get("warnings") if isinstance(raw, dict) and isinstance(raw.get("warnings"), list) else [],
|
|
137
|
+
meta={"profile": profile},
|
|
138
|
+
legacy=raw,
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
def associated_report_detail(
|
|
142
|
+
self,
|
|
143
|
+
*,
|
|
144
|
+
profile: str,
|
|
145
|
+
app_key: str,
|
|
146
|
+
record_id: int,
|
|
147
|
+
workflow_node_id: int,
|
|
148
|
+
report_id: int,
|
|
149
|
+
page: int,
|
|
150
|
+
page_size: int,
|
|
151
|
+
) -> dict:
|
|
152
|
+
try:
|
|
153
|
+
raw = self._tools.task.task_associated_report_detail_get(
|
|
154
|
+
profile=profile,
|
|
155
|
+
app_key=app_key,
|
|
156
|
+
record_id=record_id,
|
|
157
|
+
workflow_node_id=workflow_node_id,
|
|
158
|
+
report_id=report_id,
|
|
159
|
+
page=page,
|
|
160
|
+
page_size=page_size,
|
|
161
|
+
)
|
|
162
|
+
except Exception as error: # noqa: BLE001
|
|
163
|
+
return normalize_exception(error)
|
|
164
|
+
return success_result(
|
|
165
|
+
"TASK_ASSOCIATED_REPORT_READY",
|
|
166
|
+
"已读取关联报表详情",
|
|
167
|
+
data=tool_payload(raw),
|
|
168
|
+
warnings=raw.get("warnings") if isinstance(raw, dict) and isinstance(raw.get("warnings"), list) else [],
|
|
169
|
+
meta={"profile": profile},
|
|
170
|
+
legacy=raw,
|
|
171
|
+
)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from .base import normalize_exception, success_result
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class WorkspaceOperations:
|
|
9
|
+
def __init__(self, tools: Any) -> None:
|
|
10
|
+
self._tools = tools
|
|
11
|
+
|
|
12
|
+
def list(
|
|
13
|
+
self,
|
|
14
|
+
*,
|
|
15
|
+
profile: str,
|
|
16
|
+
page_num: int,
|
|
17
|
+
page_size: int,
|
|
18
|
+
include_external: bool,
|
|
19
|
+
) -> dict:
|
|
20
|
+
try:
|
|
21
|
+
raw = self._tools.workspace.workspace_list(
|
|
22
|
+
profile=profile,
|
|
23
|
+
page_num=page_num,
|
|
24
|
+
page_size=page_size,
|
|
25
|
+
include_external=include_external,
|
|
26
|
+
)
|
|
27
|
+
except Exception as error: # noqa: BLE001
|
|
28
|
+
return normalize_exception(error)
|
|
29
|
+
page = raw.get("page") if isinstance(raw.get("page"), dict) else {}
|
|
30
|
+
items = page.get("list") if isinstance(page.get("list"), list) else []
|
|
31
|
+
normalized = [
|
|
32
|
+
{
|
|
33
|
+
"ws_id": item.get("wsId"),
|
|
34
|
+
"name": item.get("workspaceName") or item.get("wsName"),
|
|
35
|
+
"remark": item.get("remark"),
|
|
36
|
+
"system_version": item.get("systemVersion"),
|
|
37
|
+
}
|
|
38
|
+
for item in items
|
|
39
|
+
if isinstance(item, dict)
|
|
40
|
+
]
|
|
41
|
+
return success_result(
|
|
42
|
+
"WORKSPACES_LISTED",
|
|
43
|
+
"已读取工作区列表",
|
|
44
|
+
data={
|
|
45
|
+
"items": normalized,
|
|
46
|
+
"page_num": page_num,
|
|
47
|
+
"page_size": page_size,
|
|
48
|
+
"include_external": include_external,
|
|
49
|
+
"total": page.get("total"),
|
|
50
|
+
},
|
|
51
|
+
meta={"profile": profile},
|
|
52
|
+
legacy=raw,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
def use(self, *, profile: str, ws_id: int) -> dict:
|
|
56
|
+
try:
|
|
57
|
+
raw = self._tools.workspace.workspace_select(profile=profile, ws_id=ws_id)
|
|
58
|
+
except Exception as error: # noqa: BLE001
|
|
59
|
+
return normalize_exception(error)
|
|
60
|
+
workspace = raw.get("workspace") if isinstance(raw.get("workspace"), dict) else {}
|
|
61
|
+
return success_result(
|
|
62
|
+
"WORKSPACE_SELECTED",
|
|
63
|
+
"已切换工作区",
|
|
64
|
+
data={
|
|
65
|
+
"workspace": {
|
|
66
|
+
"ws_id": raw.get("selected_ws_id", ws_id),
|
|
67
|
+
"name": raw.get("selected_ws_name"),
|
|
68
|
+
"remark": workspace.get("remark"),
|
|
69
|
+
"system_version": workspace.get("systemVersion"),
|
|
70
|
+
},
|
|
71
|
+
"qf_version": raw.get("qf_version"),
|
|
72
|
+
"qf_version_source": raw.get("qf_version_source"),
|
|
73
|
+
},
|
|
74
|
+
meta={"profile": profile, "request_route": raw.get("request_route")},
|
|
75
|
+
legacy=raw,
|
|
76
|
+
)
|