@josephyan/qingflow-app-user-mcp 0.2.0-beta.20 → 0.2.0-beta.21
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/skills/qingflow-app-user/SKILL.md +183 -113
- package/skills/qingflow-app-user/references/data-gotchas.md +20 -30
- package/skills/qingflow-app-user/references/environments.md +1 -1
- package/skills/qingflow-app-user/references/record-patterns.md +80 -66
- package/skills/qingflow-app-user/references/workflow-usage.md +10 -8
- package/skills/qingflow-record-analysis/SKILL.md +4 -4
- package/skills/qingflow-record-analysis/agents/openai.yaml +1 -1
- package/skills/qingflow-record-analysis/references/analysis-gotchas.md +2 -2
- package/skills/qingflow-record-analysis/references/analysis-patterns.md +2 -2
- package/skills/qingflow-record-analysis/references/confidence-reporting.md +2 -2
- package/src/qingflow_mcp/__init__.py +1 -1
- package/src/qingflow_mcp/server.py +6 -6
- package/src/qingflow_mcp/server_app_user.py +8 -183
- package/src/qingflow_mcp/tools/approval_tools.py +357 -75
- package/src/qingflow_mcp/tools/directory_tools.py +158 -28
- package/src/qingflow_mcp/tools/record_tools.py +619 -120
- package/src/qingflow_mcp/tools/task_tools.py +376 -225
|
@@ -18,14 +18,19 @@ class ApprovalTools(ToolBase):
|
|
|
18
18
|
|
|
19
19
|
def register(self, mcp: FastMCP) -> None:
|
|
20
20
|
@mcp.tool()
|
|
21
|
-
def
|
|
22
|
-
|
|
21
|
+
def record_comment_write(
|
|
22
|
+
profile: str = DEFAULT_PROFILE,
|
|
23
|
+
app_key: str = "",
|
|
24
|
+
record_id: int = 0,
|
|
25
|
+
payload: dict[str, Any] | None = None,
|
|
26
|
+
) -> dict[str, Any]:
|
|
27
|
+
return self.record_comment_write(profile=profile, app_key=app_key, record_id=record_id, payload=payload or {})
|
|
23
28
|
|
|
24
29
|
@mcp.tool()
|
|
25
30
|
def record_comment_list(
|
|
26
31
|
profile: str = DEFAULT_PROFILE,
|
|
27
32
|
app_key: str = "",
|
|
28
|
-
|
|
33
|
+
record_id: int = 0,
|
|
29
34
|
page_size: int = 20,
|
|
30
35
|
list_type: int | None = None,
|
|
31
36
|
page_num: int | None = 1,
|
|
@@ -33,26 +38,26 @@ class ApprovalTools(ToolBase):
|
|
|
33
38
|
return self.record_comment_list(
|
|
34
39
|
profile=profile,
|
|
35
40
|
app_key=app_key,
|
|
36
|
-
apply_id=
|
|
41
|
+
apply_id=record_id,
|
|
37
42
|
page_size=page_size,
|
|
38
43
|
list_type=list_type,
|
|
39
44
|
page_num=page_num,
|
|
40
45
|
)
|
|
41
46
|
|
|
42
47
|
@mcp.tool()
|
|
43
|
-
def
|
|
48
|
+
def record_comment_mentions(
|
|
44
49
|
profile: str = DEFAULT_PROFILE,
|
|
45
50
|
app_key: str = "",
|
|
46
|
-
|
|
51
|
+
record_id: int = 0,
|
|
47
52
|
page_size: int = 20,
|
|
48
53
|
page_num: int = 1,
|
|
49
54
|
list_type: int | None = None,
|
|
50
55
|
keyword: str | None = None,
|
|
51
56
|
) -> dict[str, Any]:
|
|
52
|
-
return self.
|
|
57
|
+
return self.record_comment_mentions(
|
|
53
58
|
profile=profile,
|
|
54
59
|
app_key=app_key,
|
|
55
|
-
|
|
60
|
+
record_id=record_id,
|
|
56
61
|
page_size=page_size,
|
|
57
62
|
page_num=page_num,
|
|
58
63
|
list_type=list_type,
|
|
@@ -60,84 +65,180 @@ class ApprovalTools(ToolBase):
|
|
|
60
65
|
)
|
|
61
66
|
|
|
62
67
|
@mcp.tool()
|
|
63
|
-
def record_comment_mark_read(profile: str = DEFAULT_PROFILE, app_key: str = "",
|
|
64
|
-
return self.record_comment_mark_read(profile=profile, app_key=app_key, apply_id=
|
|
65
|
-
|
|
66
|
-
@mcp.tool()
|
|
67
|
-
def record_comment_stats(profile: str = DEFAULT_PROFILE, app_key: str = "", apply_id: int = 0) -> dict[str, Any]:
|
|
68
|
-
return self.record_comment_stats(profile=profile, app_key=app_key, apply_id=apply_id)
|
|
68
|
+
def record_comment_mark_read(profile: str = DEFAULT_PROFILE, app_key: str = "", record_id: int = 0) -> dict[str, Any]:
|
|
69
|
+
return self.record_comment_mark_read(profile=profile, app_key=app_key, apply_id=record_id)
|
|
69
70
|
|
|
70
|
-
@mcp.tool(description=self._high_risk_tool_description(operation="approve", target="workflow
|
|
71
|
-
def
|
|
72
|
-
return self.
|
|
73
|
-
|
|
74
|
-
@mcp.tool(description=self._high_risk_tool_description(operation="reject", target="workflow record"))
|
|
75
|
-
def record_reject(profile: str = DEFAULT_PROFILE, app_key: str = "", apply_id: int = 0, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
76
|
-
return self.record_reject(profile=profile, app_key=app_key, apply_id=apply_id, payload=payload or {})
|
|
77
|
-
|
|
78
|
-
@mcp.tool()
|
|
79
|
-
def record_rollback_candidates(profile: str = DEFAULT_PROFILE, app_key: str = "", apply_id: int = 0, audit_node_id: int = 0) -> dict[str, Any]:
|
|
80
|
-
return self.record_rollback_candidates(profile=profile, app_key=app_key, apply_id=apply_id, audit_node_id=audit_node_id)
|
|
81
|
-
|
|
82
|
-
@mcp.tool()
|
|
83
|
-
def record_rollback(profile: str = DEFAULT_PROFILE, app_key: str = "", apply_id: int = 0, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
84
|
-
return self.record_rollback(profile=profile, app_key=app_key, apply_id=apply_id, payload=payload or {})
|
|
71
|
+
@mcp.tool(description=self._high_risk_tool_description(operation="approve", target="workflow task"))
|
|
72
|
+
def task_approve(profile: str = DEFAULT_PROFILE, app_key: str = "", record_id: int = 0, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
73
|
+
return self.task_approve(profile=profile, app_key=app_key, record_id=record_id, payload=payload or {})
|
|
85
74
|
|
|
86
|
-
@mcp.tool()
|
|
87
|
-
def
|
|
88
|
-
return self.
|
|
75
|
+
@mcp.tool(description=self._high_risk_tool_description(operation="reject", target="workflow task"))
|
|
76
|
+
def task_reject(profile: str = DEFAULT_PROFILE, app_key: str = "", record_id: int = 0, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
77
|
+
return self.task_reject(profile=profile, app_key=app_key, record_id=record_id, payload=payload or {})
|
|
89
78
|
|
|
90
79
|
@mcp.tool()
|
|
91
|
-
def
|
|
80
|
+
def task_rollback_candidates(
|
|
92
81
|
profile: str = DEFAULT_PROFILE,
|
|
93
82
|
app_key: str = "",
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
page_num: int = 1,
|
|
97
|
-
audit_node_id: int = 0,
|
|
98
|
-
keyword: str | None = None,
|
|
83
|
+
record_id: int = 0,
|
|
84
|
+
workflow_node_id: int = 0,
|
|
99
85
|
) -> dict[str, Any]:
|
|
100
|
-
return self.
|
|
101
|
-
profile=profile,
|
|
102
|
-
app_key=app_key,
|
|
103
|
-
apply_id=apply_id,
|
|
104
|
-
page_size=page_size,
|
|
105
|
-
page_num=page_num,
|
|
106
|
-
audit_node_id=audit_node_id,
|
|
107
|
-
keyword=keyword,
|
|
108
|
-
)
|
|
86
|
+
return self.task_rollback_candidates(profile=profile, app_key=app_key, record_id=record_id, workflow_node_id=workflow_node_id)
|
|
109
87
|
|
|
110
88
|
@mcp.tool()
|
|
111
|
-
def
|
|
112
|
-
return self.
|
|
89
|
+
def task_rollback(profile: str = DEFAULT_PROFILE, app_key: str = "", record_id: int = 0, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
90
|
+
return self.task_rollback(profile=profile, app_key=app_key, record_id=record_id, payload=payload or {})
|
|
113
91
|
|
|
114
92
|
@mcp.tool()
|
|
115
|
-
def
|
|
116
|
-
return self.
|
|
93
|
+
def task_transfer(profile: str = DEFAULT_PROFILE, app_key: str = "", record_id: int = 0, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
94
|
+
return self.task_transfer(profile=profile, app_key=app_key, record_id=record_id, payload=payload or {})
|
|
117
95
|
|
|
118
96
|
@mcp.tool()
|
|
119
|
-
def
|
|
97
|
+
def task_transfer_candidates(
|
|
120
98
|
profile: str = DEFAULT_PROFILE,
|
|
121
99
|
app_key: str = "",
|
|
122
|
-
|
|
100
|
+
record_id: int = 0,
|
|
123
101
|
page_size: int = 20,
|
|
124
102
|
page_num: int = 1,
|
|
125
|
-
|
|
126
|
-
|
|
103
|
+
workflow_node_id: int = 0,
|
|
104
|
+
keyword: str | None = None,
|
|
127
105
|
) -> dict[str, Any]:
|
|
128
|
-
return self.
|
|
106
|
+
return self.task_transfer_candidates(
|
|
129
107
|
profile=profile,
|
|
130
108
|
app_key=app_key,
|
|
131
|
-
|
|
109
|
+
record_id=record_id,
|
|
132
110
|
page_size=page_size,
|
|
133
111
|
page_num=page_num,
|
|
134
|
-
|
|
135
|
-
|
|
112
|
+
workflow_node_id=workflow_node_id,
|
|
113
|
+
keyword=keyword,
|
|
136
114
|
)
|
|
137
115
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
116
|
+
def record_comment_write(self, *, profile: str, app_key: str, record_id: int, payload: dict[str, Any]) -> dict[str, Any]:
|
|
117
|
+
raw = self.record_comment_add(profile=profile, app_key=app_key, apply_id=record_id, payload=payload)
|
|
118
|
+
return self._public_action_response(
|
|
119
|
+
raw,
|
|
120
|
+
action="record_comment_write",
|
|
121
|
+
resource={"app_key": app_key, "record_id": record_id},
|
|
122
|
+
selection={},
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
def record_comment_mentions(
|
|
126
|
+
self,
|
|
127
|
+
*,
|
|
128
|
+
profile: str,
|
|
129
|
+
app_key: str,
|
|
130
|
+
record_id: int,
|
|
131
|
+
page_size: int = 20,
|
|
132
|
+
page_num: int = 1,
|
|
133
|
+
list_type: int | None = None,
|
|
134
|
+
keyword: str | None = None,
|
|
135
|
+
) -> dict[str, Any]:
|
|
136
|
+
raw = self.record_comment_mention_candidates(
|
|
137
|
+
profile=profile,
|
|
138
|
+
app_key=app_key,
|
|
139
|
+
apply_id=record_id,
|
|
140
|
+
page_size=page_size,
|
|
141
|
+
page_num=page_num,
|
|
142
|
+
list_type=list_type,
|
|
143
|
+
keyword=keyword,
|
|
144
|
+
)
|
|
145
|
+
items = _approval_page_items(raw.get("page"))
|
|
146
|
+
return self._public_page_response(
|
|
147
|
+
raw,
|
|
148
|
+
items=items,
|
|
149
|
+
pagination={
|
|
150
|
+
"page": page_num,
|
|
151
|
+
"page_size": page_size,
|
|
152
|
+
"returned_items": len(items),
|
|
153
|
+
"page_amount": _approval_page_amount(raw.get("page")),
|
|
154
|
+
"reported_total": _approval_page_total(raw.get("page")),
|
|
155
|
+
},
|
|
156
|
+
selection={"app_key": app_key, "record_id": record_id, "list_type": list_type, "keyword": keyword},
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
def task_approve(self, *, profile: str, app_key: str, record_id: int, payload: dict[str, Any]) -> dict[str, Any]:
|
|
160
|
+
raw = self.record_approve(profile=profile, app_key=app_key, apply_id=record_id, payload=payload)
|
|
161
|
+
return self._public_action_response(
|
|
162
|
+
raw,
|
|
163
|
+
action="task_approve",
|
|
164
|
+
resource={"app_key": app_key, "record_id": record_id},
|
|
165
|
+
selection={},
|
|
166
|
+
human_review=True,
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
def task_reject(self, *, profile: str, app_key: str, record_id: int, payload: dict[str, Any]) -> dict[str, Any]:
|
|
170
|
+
raw = self.record_reject(profile=profile, app_key=app_key, apply_id=record_id, payload=payload)
|
|
171
|
+
return self._public_action_response(
|
|
172
|
+
raw,
|
|
173
|
+
action="task_reject",
|
|
174
|
+
resource={"app_key": app_key, "record_id": record_id},
|
|
175
|
+
selection={},
|
|
176
|
+
human_review=True,
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
def task_rollback_candidates(self, *, profile: str, app_key: str, record_id: int, workflow_node_id: int) -> dict[str, Any]:
|
|
180
|
+
raw = self.record_rollback_candidates(profile=profile, app_key=app_key, apply_id=record_id, audit_node_id=workflow_node_id)
|
|
181
|
+
items = _approval_page_items(raw.get("result"))
|
|
182
|
+
return self._public_page_response(
|
|
183
|
+
raw,
|
|
184
|
+
items=items,
|
|
185
|
+
pagination={"returned_items": len(items)},
|
|
186
|
+
selection={"app_key": app_key, "record_id": record_id, "workflow_node_id": workflow_node_id},
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
def task_rollback(self, *, profile: str, app_key: str, record_id: int, payload: dict[str, Any]) -> dict[str, Any]:
|
|
190
|
+
raw = self.record_rollback(profile=profile, app_key=app_key, apply_id=record_id, payload=payload)
|
|
191
|
+
return self._public_action_response(
|
|
192
|
+
raw,
|
|
193
|
+
action="task_rollback",
|
|
194
|
+
resource={"app_key": app_key, "record_id": record_id},
|
|
195
|
+
selection={},
|
|
196
|
+
human_review=True,
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
def task_transfer(self, *, profile: str, app_key: str, record_id: int, payload: dict[str, Any]) -> dict[str, Any]:
|
|
200
|
+
raw = self.record_transfer(profile=profile, app_key=app_key, apply_id=record_id, payload=payload)
|
|
201
|
+
return self._public_action_response(
|
|
202
|
+
raw,
|
|
203
|
+
action="task_transfer",
|
|
204
|
+
resource={"app_key": app_key, "record_id": record_id},
|
|
205
|
+
selection={},
|
|
206
|
+
human_review=True,
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
def task_transfer_candidates(
|
|
210
|
+
self,
|
|
211
|
+
*,
|
|
212
|
+
profile: str,
|
|
213
|
+
app_key: str,
|
|
214
|
+
record_id: int,
|
|
215
|
+
page_size: int = 20,
|
|
216
|
+
page_num: int = 1,
|
|
217
|
+
workflow_node_id: int = 0,
|
|
218
|
+
keyword: str | None = None,
|
|
219
|
+
) -> dict[str, Any]:
|
|
220
|
+
raw = self.record_transfer_candidates(
|
|
221
|
+
profile=profile,
|
|
222
|
+
app_key=app_key,
|
|
223
|
+
apply_id=record_id,
|
|
224
|
+
page_size=page_size,
|
|
225
|
+
page_num=page_num,
|
|
226
|
+
audit_node_id=workflow_node_id,
|
|
227
|
+
keyword=keyword,
|
|
228
|
+
)
|
|
229
|
+
items = _approval_page_items(raw.get("page"))
|
|
230
|
+
return self._public_page_response(
|
|
231
|
+
raw,
|
|
232
|
+
items=items,
|
|
233
|
+
pagination={
|
|
234
|
+
"page": page_num,
|
|
235
|
+
"page_size": page_size,
|
|
236
|
+
"returned_items": len(items),
|
|
237
|
+
"page_amount": _approval_page_amount(raw.get("page")),
|
|
238
|
+
"reported_total": _approval_page_total(raw.get("page")),
|
|
239
|
+
},
|
|
240
|
+
selection={"app_key": app_key, "record_id": record_id, "workflow_node_id": workflow_node_id, "keyword": keyword},
|
|
241
|
+
)
|
|
141
242
|
|
|
142
243
|
def record_comment_add(self, *, profile: str, app_key: str, apply_id: int, payload: dict[str, Any]) -> dict[str, Any]:
|
|
143
244
|
self._require_app_and_apply(app_key, apply_id)
|
|
@@ -145,7 +246,14 @@ class ApprovalTools(ToolBase):
|
|
|
145
246
|
|
|
146
247
|
def runner(session_profile, context):
|
|
147
248
|
result = self.backend.request("POST", context, f"/app/{app_key}/apply/{apply_id}/comment", json_body=payload)
|
|
148
|
-
return {
|
|
249
|
+
return {
|
|
250
|
+
"profile": profile,
|
|
251
|
+
"ws_id": session_profile.selected_ws_id,
|
|
252
|
+
"app_key": app_key,
|
|
253
|
+
"apply_id": apply_id,
|
|
254
|
+
"result": result,
|
|
255
|
+
"request_route": self._request_route_payload(context),
|
|
256
|
+
}
|
|
149
257
|
|
|
150
258
|
return self._run(profile, runner)
|
|
151
259
|
|
|
@@ -167,9 +275,23 @@ class ApprovalTools(ToolBase):
|
|
|
167
275
|
"list_type": list_type,
|
|
168
276
|
"list_type_label": get_record_list_type_label(list_type),
|
|
169
277
|
"page": result,
|
|
278
|
+
"request_route": self._request_route_payload(context),
|
|
170
279
|
}
|
|
171
280
|
|
|
172
|
-
|
|
281
|
+
raw = self._run(profile, runner)
|
|
282
|
+
items = _approval_page_items(raw.get("page"))
|
|
283
|
+
return self._public_page_response(
|
|
284
|
+
raw,
|
|
285
|
+
items=items,
|
|
286
|
+
pagination={
|
|
287
|
+
"page": page_num,
|
|
288
|
+
"page_size": page_size,
|
|
289
|
+
"returned_items": len(items),
|
|
290
|
+
"page_amount": _approval_page_amount(raw.get("page")),
|
|
291
|
+
"reported_total": _approval_page_total(raw.get("page")),
|
|
292
|
+
},
|
|
293
|
+
selection={"app_key": app_key, "record_id": apply_id, "list_type": list_type},
|
|
294
|
+
)
|
|
173
295
|
|
|
174
296
|
def record_comment_mention_candidates(
|
|
175
297
|
self,
|
|
@@ -199,6 +321,7 @@ class ApprovalTools(ToolBase):
|
|
|
199
321
|
"list_type": list_type,
|
|
200
322
|
"list_type_label": get_record_list_type_label(list_type),
|
|
201
323
|
"page": result,
|
|
324
|
+
"request_route": self._request_route_payload(context),
|
|
202
325
|
}
|
|
203
326
|
|
|
204
327
|
return self._run(profile, runner)
|
|
@@ -208,16 +331,36 @@ class ApprovalTools(ToolBase):
|
|
|
208
331
|
|
|
209
332
|
def runner(session_profile, context):
|
|
210
333
|
result = self.backend.request("POST", context, f"/app/{app_key}/apply/{apply_id}/comment/read")
|
|
211
|
-
return {
|
|
334
|
+
return {
|
|
335
|
+
"profile": profile,
|
|
336
|
+
"ws_id": session_profile.selected_ws_id,
|
|
337
|
+
"app_key": app_key,
|
|
338
|
+
"apply_id": apply_id,
|
|
339
|
+
"result": result,
|
|
340
|
+
"request_route": self._request_route_payload(context),
|
|
341
|
+
}
|
|
212
342
|
|
|
213
|
-
|
|
343
|
+
raw = self._run(profile, runner)
|
|
344
|
+
return self._public_action_response(
|
|
345
|
+
raw,
|
|
346
|
+
action="record_comment_mark_read",
|
|
347
|
+
resource={"app_key": app_key, "record_id": apply_id},
|
|
348
|
+
selection={},
|
|
349
|
+
)
|
|
214
350
|
|
|
215
351
|
def record_comment_stats(self, *, profile: str, app_key: str, apply_id: int) -> dict[str, Any]:
|
|
216
352
|
self._require_app_and_apply(app_key, apply_id)
|
|
217
353
|
|
|
218
354
|
def runner(session_profile, context):
|
|
219
355
|
result = self.backend.request("GET", context, f"/app/{app_key}/apply/{apply_id}/comment/statistic")
|
|
220
|
-
return {
|
|
356
|
+
return {
|
|
357
|
+
"profile": profile,
|
|
358
|
+
"ws_id": session_profile.selected_ws_id,
|
|
359
|
+
"app_key": app_key,
|
|
360
|
+
"apply_id": apply_id,
|
|
361
|
+
"result": result,
|
|
362
|
+
"request_route": self._request_route_payload(context),
|
|
363
|
+
}
|
|
221
364
|
|
|
222
365
|
return self._run(profile, runner)
|
|
223
366
|
|
|
@@ -273,7 +416,14 @@ class ApprovalTools(ToolBase):
|
|
|
273
416
|
f"/app/{app_key}/apply/{apply_id}/revertNode",
|
|
274
417
|
params={"auditNodeId": audit_node_id},
|
|
275
418
|
)
|
|
276
|
-
return {
|
|
419
|
+
return {
|
|
420
|
+
"profile": profile,
|
|
421
|
+
"ws_id": session_profile.selected_ws_id,
|
|
422
|
+
"app_key": app_key,
|
|
423
|
+
"apply_id": apply_id,
|
|
424
|
+
"result": result,
|
|
425
|
+
"request_route": self._request_route_payload(context),
|
|
426
|
+
}
|
|
277
427
|
|
|
278
428
|
return self._run(profile, runner)
|
|
279
429
|
|
|
@@ -284,7 +434,14 @@ class ApprovalTools(ToolBase):
|
|
|
284
434
|
|
|
285
435
|
def runner(session_profile, context):
|
|
286
436
|
result = self.backend.request("POST", context, f"/app/{app_key}/apply/{apply_id}/rollback", json_body=body)
|
|
287
|
-
return {
|
|
437
|
+
return {
|
|
438
|
+
"profile": profile,
|
|
439
|
+
"ws_id": session_profile.selected_ws_id,
|
|
440
|
+
"app_key": app_key,
|
|
441
|
+
"apply_id": apply_id,
|
|
442
|
+
"result": result,
|
|
443
|
+
"request_route": self._request_route_payload(context),
|
|
444
|
+
}
|
|
288
445
|
|
|
289
446
|
return self._run(profile, runner)
|
|
290
447
|
|
|
@@ -295,7 +452,14 @@ class ApprovalTools(ToolBase):
|
|
|
295
452
|
|
|
296
453
|
def runner(session_profile, context):
|
|
297
454
|
result = self.backend.request("POST", context, f"/app/{app_key}/apply/{apply_id}/transfer", json_body=body)
|
|
298
|
-
return {
|
|
455
|
+
return {
|
|
456
|
+
"profile": profile,
|
|
457
|
+
"ws_id": session_profile.selected_ws_id,
|
|
458
|
+
"app_key": app_key,
|
|
459
|
+
"apply_id": apply_id,
|
|
460
|
+
"result": result,
|
|
461
|
+
"request_route": self._request_route_payload(context),
|
|
462
|
+
}
|
|
299
463
|
|
|
300
464
|
return self._run(profile, runner)
|
|
301
465
|
|
|
@@ -319,7 +483,14 @@ class ApprovalTools(ToolBase):
|
|
|
319
483
|
if keyword:
|
|
320
484
|
params["keyword"] = keyword
|
|
321
485
|
result = self.backend.request("GET", context, f"/app/{app_key}/apply/{apply_id}/transfer/member", params=params)
|
|
322
|
-
return {
|
|
486
|
+
return {
|
|
487
|
+
"profile": profile,
|
|
488
|
+
"ws_id": session_profile.selected_ws_id,
|
|
489
|
+
"app_key": app_key,
|
|
490
|
+
"apply_id": apply_id,
|
|
491
|
+
"page": result,
|
|
492
|
+
"request_route": self._request_route_payload(context),
|
|
493
|
+
}
|
|
323
494
|
|
|
324
495
|
return self._run(profile, runner)
|
|
325
496
|
|
|
@@ -328,7 +499,14 @@ class ApprovalTools(ToolBase):
|
|
|
328
499
|
|
|
329
500
|
def runner(session_profile, context):
|
|
330
501
|
result = self.backend.request("GET", context, f"/app/{app_key}/apply/{apply_id}/reassign")
|
|
331
|
-
return {
|
|
502
|
+
return {
|
|
503
|
+
"profile": profile,
|
|
504
|
+
"ws_id": session_profile.selected_ws_id,
|
|
505
|
+
"app_key": app_key,
|
|
506
|
+
"apply_id": apply_id,
|
|
507
|
+
"result": result,
|
|
508
|
+
"request_route": self._request_route_payload(context),
|
|
509
|
+
}
|
|
332
510
|
|
|
333
511
|
return self._run(profile, runner)
|
|
334
512
|
|
|
@@ -338,7 +516,14 @@ class ApprovalTools(ToolBase):
|
|
|
338
516
|
|
|
339
517
|
def runner(session_profile, context):
|
|
340
518
|
result = self.backend.request("POST", context, f"/app/{app_key}/apply/{apply_id}/reassign", json_body=body)
|
|
341
|
-
return {
|
|
519
|
+
return {
|
|
520
|
+
"profile": profile,
|
|
521
|
+
"ws_id": session_profile.selected_ws_id,
|
|
522
|
+
"app_key": app_key,
|
|
523
|
+
"apply_id": apply_id,
|
|
524
|
+
"result": result,
|
|
525
|
+
"request_route": self._request_route_payload(context),
|
|
526
|
+
}
|
|
342
527
|
|
|
343
528
|
return self._run(profile, runner)
|
|
344
529
|
|
|
@@ -362,7 +547,14 @@ class ApprovalTools(ToolBase):
|
|
|
362
547
|
if search_key:
|
|
363
548
|
params["searchKey"] = search_key
|
|
364
549
|
result = self.backend.request("GET", context, f"/app/{app_key}/apply/{apply_id}/countersign/member", params=params)
|
|
365
|
-
return {
|
|
550
|
+
return {
|
|
551
|
+
"profile": profile,
|
|
552
|
+
"ws_id": session_profile.selected_ws_id,
|
|
553
|
+
"app_key": app_key,
|
|
554
|
+
"apply_id": apply_id,
|
|
555
|
+
"page": result,
|
|
556
|
+
"request_route": self._request_route_payload(context),
|
|
557
|
+
}
|
|
366
558
|
|
|
367
559
|
return self._run(profile, runner)
|
|
368
560
|
|
|
@@ -373,10 +565,29 @@ class ApprovalTools(ToolBase):
|
|
|
373
565
|
|
|
374
566
|
def runner(session_profile, context):
|
|
375
567
|
result = self.backend.request("POST", context, f"/app/{app_key}/apply/{apply_id}/countersign", json_body=body)
|
|
376
|
-
return {
|
|
568
|
+
return {
|
|
569
|
+
"profile": profile,
|
|
570
|
+
"ws_id": session_profile.selected_ws_id,
|
|
571
|
+
"app_key": app_key,
|
|
572
|
+
"apply_id": apply_id,
|
|
573
|
+
"result": result,
|
|
574
|
+
"request_route": self._request_route_payload(context),
|
|
575
|
+
}
|
|
377
576
|
|
|
378
577
|
return self._run(profile, runner)
|
|
379
578
|
|
|
579
|
+
def _request_route_payload(self, context) -> JSONObject: # type: ignore[no-untyped-def]
|
|
580
|
+
describe_route = getattr(self.backend, "describe_route", None)
|
|
581
|
+
if callable(describe_route):
|
|
582
|
+
payload = describe_route(context)
|
|
583
|
+
if isinstance(payload, dict):
|
|
584
|
+
return payload
|
|
585
|
+
return {
|
|
586
|
+
"base_url": getattr(context, "base_url", None),
|
|
587
|
+
"qf_version": getattr(context, "qf_version", None),
|
|
588
|
+
"qf_version_source": getattr(context, "qf_version_source", None) or ("context" if getattr(context, "qf_version", None) else "unknown"),
|
|
589
|
+
}
|
|
590
|
+
|
|
380
591
|
def _require_app_and_apply(self, app_key: str, apply_id: int) -> None:
|
|
381
592
|
if not app_key:
|
|
382
593
|
raise_tool_error(QingflowApiError.config_error("app_key is required"))
|
|
@@ -485,6 +696,47 @@ class ApprovalTools(ToolBase):
|
|
|
485
696
|
if payload.get("handSignImageUrl"):
|
|
486
697
|
raise_tool_error(QingflowApiError.not_supported("NOT_SUPPORTED_IN_V1: handSignImageUrl is not supported"))
|
|
487
698
|
|
|
699
|
+
def _public_page_response(
|
|
700
|
+
self,
|
|
701
|
+
raw: dict[str, Any],
|
|
702
|
+
*,
|
|
703
|
+
items: list[dict[str, Any]],
|
|
704
|
+
pagination: dict[str, Any],
|
|
705
|
+
selection: dict[str, Any],
|
|
706
|
+
) -> dict[str, Any]:
|
|
707
|
+
response = dict(raw)
|
|
708
|
+
response["ok"] = bool(raw.get("ok", True))
|
|
709
|
+
response["warnings"] = []
|
|
710
|
+
response["output_profile"] = "normal"
|
|
711
|
+
response["data"] = {
|
|
712
|
+
"items": items,
|
|
713
|
+
"pagination": pagination,
|
|
714
|
+
"selection": selection,
|
|
715
|
+
}
|
|
716
|
+
return response
|
|
717
|
+
|
|
718
|
+
def _public_action_response(
|
|
719
|
+
self,
|
|
720
|
+
raw: dict[str, Any],
|
|
721
|
+
*,
|
|
722
|
+
action: str,
|
|
723
|
+
resource: dict[str, Any],
|
|
724
|
+
selection: dict[str, Any],
|
|
725
|
+
human_review: bool = False,
|
|
726
|
+
) -> dict[str, Any]:
|
|
727
|
+
response = dict(raw)
|
|
728
|
+
response["ok"] = bool(raw.get("ok", True))
|
|
729
|
+
response["warnings"] = []
|
|
730
|
+
response["output_profile"] = "normal"
|
|
731
|
+
response["data"] = {
|
|
732
|
+
"action": action,
|
|
733
|
+
"resource": resource,
|
|
734
|
+
"selection": selection,
|
|
735
|
+
"result": raw.get("result"),
|
|
736
|
+
"human_review": human_review,
|
|
737
|
+
}
|
|
738
|
+
return response
|
|
739
|
+
|
|
488
740
|
def _request_route_payload(self, context) -> JSONObject: # type: ignore[no-untyped-def]
|
|
489
741
|
describe_route = getattr(self.backend, "describe_route", None)
|
|
490
742
|
if callable(describe_route):
|
|
@@ -496,3 +748,33 @@ class ApprovalTools(ToolBase):
|
|
|
496
748
|
"qf_version": context.qf_version,
|
|
497
749
|
"qf_version_source": getattr(context, "qf_version_source", None) or ("context" if getattr(context, "qf_version", None) else "unknown"),
|
|
498
750
|
}
|
|
751
|
+
|
|
752
|
+
|
|
753
|
+
def _approval_page_items(payload: Any) -> list[dict[str, Any]]:
|
|
754
|
+
if isinstance(payload, list):
|
|
755
|
+
return [item for item in payload if isinstance(item, dict)]
|
|
756
|
+
if not isinstance(payload, dict):
|
|
757
|
+
return []
|
|
758
|
+
for key in ("list", "items", "rows", "result"):
|
|
759
|
+
value = payload.get(key)
|
|
760
|
+
if isinstance(value, list):
|
|
761
|
+
return [item for item in value if isinstance(item, dict)]
|
|
762
|
+
for container_key in ("data", "page"):
|
|
763
|
+
nested = payload.get(container_key)
|
|
764
|
+
if isinstance(nested, dict):
|
|
765
|
+
nested_items = _approval_page_items(nested)
|
|
766
|
+
if nested_items:
|
|
767
|
+
return nested_items
|
|
768
|
+
return []
|
|
769
|
+
|
|
770
|
+
|
|
771
|
+
def _approval_page_amount(payload: Any) -> Any:
|
|
772
|
+
if isinstance(payload, dict):
|
|
773
|
+
return payload.get("pageAmount", payload.get("page_amount"))
|
|
774
|
+
return None
|
|
775
|
+
|
|
776
|
+
|
|
777
|
+
def _approval_page_total(payload: Any) -> Any:
|
|
778
|
+
if isinstance(payload, dict):
|
|
779
|
+
return payload.get("total", payload.get("count"))
|
|
780
|
+
return None
|