hap-cli 0.5.0__py3-none-any.whl
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.
- hap_cli/README.md +194 -0
- hap_cli/README_CN.md +601 -0
- hap_cli/__init__.py +3 -0
- hap_cli/commands/__init__.py +1 -0
- hap_cli/commands/ai_cmd.py +224 -0
- hap_cli/commands/app_cmd.py +308 -0
- hap_cli/commands/calendar_cmd.py +138 -0
- hap_cli/commands/chat_cmd.py +101 -0
- hap_cli/commands/config_cmd.py +169 -0
- hap_cli/commands/contact_cmd.py +125 -0
- hap_cli/commands/department_cmd.py +168 -0
- hap_cli/commands/group_cmd.py +128 -0
- hap_cli/commands/instance_cmd.py +310 -0
- hap_cli/commands/node_cmd.py +538 -0
- hap_cli/commands/optionset_cmd.py +99 -0
- hap_cli/commands/page_cmd.py +102 -0
- hap_cli/commands/plugin_cmd.py +133 -0
- hap_cli/commands/post_cmd.py +155 -0
- hap_cli/commands/record_cmd.py +228 -0
- hap_cli/commands/role_cmd.py +221 -0
- hap_cli/commands/workflow_cmd.py +284 -0
- hap_cli/commands/worksheet_cmd.py +342 -0
- hap_cli/context.py +43 -0
- hap_cli/core/__init__.py +1 -0
- hap_cli/core/ai.py +133 -0
- hap_cli/core/app.py +307 -0
- hap_cli/core/auth.py +219 -0
- hap_cli/core/calendar_mod.py +114 -0
- hap_cli/core/chat.py +73 -0
- hap_cli/core/contact.py +85 -0
- hap_cli/core/department.py +131 -0
- hap_cli/core/flow_node.py +1001 -0
- hap_cli/core/group.py +99 -0
- hap_cli/core/instance.py +572 -0
- hap_cli/core/optionset.py +112 -0
- hap_cli/core/page.py +138 -0
- hap_cli/core/plugin.py +87 -0
- hap_cli/core/post.py +118 -0
- hap_cli/core/record.py +268 -0
- hap_cli/core/role.py +227 -0
- hap_cli/core/session.py +348 -0
- hap_cli/core/workflow.py +556 -0
- hap_cli/core/worksheet.py +403 -0
- hap_cli/hap_cli.py +105 -0
- hap_cli/skills/SKILL.md +383 -0
- hap_cli/skills/__init__.py +0 -0
- hap_cli/tests/__init__.py +1 -0
- hap_cli/tests/test_core.py +1824 -0
- hap_cli/tests/test_full_e2e.py +136 -0
- hap_cli/tests/test_integration.py +805 -0
- hap_cli/utils/__init__.py +1 -0
- hap_cli/utils/formatting.py +111 -0
- hap_cli/utils/options.py +10 -0
- hap_cli-0.5.0.dist-info/METADATA +223 -0
- hap_cli-0.5.0.dist-info/RECORD +58 -0
- hap_cli-0.5.0.dist-info/WHEEL +5 -0
- hap_cli-0.5.0.dist-info/entry_points.txt +2 -0
- hap_cli-0.5.0.dist-info/top_level.txt +1 -0
hap_cli/core/group.py
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"""Group management for MingDAO HAP."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Optional
|
|
4
|
+
|
|
5
|
+
from hap_cli.core.session import Session
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def get_groups(
|
|
9
|
+
session: Session,
|
|
10
|
+
project_id: str,
|
|
11
|
+
page_index: int = 1,
|
|
12
|
+
page_size: int = 50,
|
|
13
|
+
) -> dict[str, Any]:
|
|
14
|
+
"""Get group list."""
|
|
15
|
+
return session.api_call(
|
|
16
|
+
"Group", "GetGroups",
|
|
17
|
+
{"projectId": project_id, "pageIndex": page_index, "pageSize": page_size},
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def get_group_info(
|
|
22
|
+
session: Session,
|
|
23
|
+
group_id: str,
|
|
24
|
+
) -> dict[str, Any]:
|
|
25
|
+
"""Get group information."""
|
|
26
|
+
return session.api_call("Group", "GetGroupInfo", {"groupId": group_id})
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def add_group(
|
|
30
|
+
session: Session,
|
|
31
|
+
project_id: str,
|
|
32
|
+
group_name: str,
|
|
33
|
+
about: str = "",
|
|
34
|
+
member_ids: Optional[list[str]] = None,
|
|
35
|
+
) -> dict[str, Any]:
|
|
36
|
+
"""Create a new group."""
|
|
37
|
+
data: dict[str, Any] = {"projectId": project_id, "groupName": group_name}
|
|
38
|
+
if about:
|
|
39
|
+
data["about"] = about
|
|
40
|
+
if member_ids:
|
|
41
|
+
data["memberIds"] = member_ids
|
|
42
|
+
return session.api_call("Group", "AddGroup", data)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def remove_group(
|
|
46
|
+
session: Session,
|
|
47
|
+
group_id: str,
|
|
48
|
+
) -> dict[str, Any]:
|
|
49
|
+
"""Delete/disband a group."""
|
|
50
|
+
return session.api_call("Group", "RemoveGroup", {"groupId": group_id})
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def get_group_users(
|
|
54
|
+
session: Session,
|
|
55
|
+
group_id: str,
|
|
56
|
+
page_index: int = 1,
|
|
57
|
+
page_size: int = 50,
|
|
58
|
+
) -> dict[str, Any]:
|
|
59
|
+
"""Get members of a group."""
|
|
60
|
+
return session.api_call(
|
|
61
|
+
"Group", "GetGroupUsers",
|
|
62
|
+
{"groupId": group_id, "pageIndex": page_index, "pageSize": page_size},
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def remove_user(
|
|
67
|
+
session: Session,
|
|
68
|
+
group_id: str,
|
|
69
|
+
account_id: str,
|
|
70
|
+
) -> dict[str, Any]:
|
|
71
|
+
"""Remove a user from a group."""
|
|
72
|
+
return session.api_call(
|
|
73
|
+
"Group", "RemoveUser",
|
|
74
|
+
{"groupId": group_id, "accountId": account_id},
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def update_group_name(
|
|
79
|
+
session: Session,
|
|
80
|
+
group_id: str,
|
|
81
|
+
group_name: str,
|
|
82
|
+
) -> dict[str, Any]:
|
|
83
|
+
"""Update group name."""
|
|
84
|
+
return session.api_call(
|
|
85
|
+
"Group", "UpdateGroupName",
|
|
86
|
+
{"groupId": group_id, "groupName": group_name},
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def update_group_about(
|
|
91
|
+
session: Session,
|
|
92
|
+
group_id: str,
|
|
93
|
+
about: str,
|
|
94
|
+
) -> dict[str, Any]:
|
|
95
|
+
"""Update group about/announcement."""
|
|
96
|
+
return session.api_call(
|
|
97
|
+
"Group", "UpdateGroupAbout",
|
|
98
|
+
{"groupId": group_id, "about": about},
|
|
99
|
+
)
|
hap_cli/core/instance.py
ADDED
|
@@ -0,0 +1,572 @@
|
|
|
1
|
+
"""Workflow instance and approval management for MingDAO HAP.
|
|
2
|
+
|
|
3
|
+
Covers: todo lists, instance details, approval operations (pass/reject/forward/sign),
|
|
4
|
+
execution history, batch operations, and instance lifecycle.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Any, Optional
|
|
8
|
+
|
|
9
|
+
from hap_cli.core.session import Session
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# ── Instance Query ───────────────────────────────────────────────────────
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def get_todo_count(session: Session) -> dict[str, Any]:
|
|
16
|
+
"""Get count of pending workflow tasks.
|
|
17
|
+
|
|
18
|
+
Returns:
|
|
19
|
+
Counts by type (pending approval, pending fill, pending view)
|
|
20
|
+
"""
|
|
21
|
+
return session.workflow_call("v1/instance/getTodoCount", {})
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def get_todo_list(
|
|
25
|
+
session: Session,
|
|
26
|
+
page_index: int = 1,
|
|
27
|
+
page_size: int = 50,
|
|
28
|
+
type_: int = -1,
|
|
29
|
+
status: int = 0,
|
|
30
|
+
keyword: str = "",
|
|
31
|
+
process_id: str = "",
|
|
32
|
+
start_app_id: str = "",
|
|
33
|
+
start_date: str = "",
|
|
34
|
+
end_date: str = "",
|
|
35
|
+
apk_id: str = "",
|
|
36
|
+
) -> dict[str, Any]:
|
|
37
|
+
"""Get pending task list.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
session: Active session
|
|
41
|
+
page_index: Page number
|
|
42
|
+
page_size: Items per page
|
|
43
|
+
type_: Task type (-1=all pending, 0=initiated, 3=fill, 4=approval, 5=view)
|
|
44
|
+
status: Status filter
|
|
45
|
+
keyword: Search keyword
|
|
46
|
+
process_id: Filter by process
|
|
47
|
+
start_app_id: Filter by source app
|
|
48
|
+
start_date: Start date filter (YYYY-MM-DD)
|
|
49
|
+
end_date: End date filter (YYYY-MM-DD)
|
|
50
|
+
apk_id: Filter by app
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
Dict with task list and count
|
|
54
|
+
"""
|
|
55
|
+
data: dict[str, Any] = {
|
|
56
|
+
"pageIndex": page_index,
|
|
57
|
+
"pageSize": page_size,
|
|
58
|
+
"type": type_,
|
|
59
|
+
}
|
|
60
|
+
if status:
|
|
61
|
+
data["status"] = status
|
|
62
|
+
if keyword:
|
|
63
|
+
data["keyword"] = keyword
|
|
64
|
+
if process_id:
|
|
65
|
+
data["processId"] = process_id
|
|
66
|
+
if start_app_id:
|
|
67
|
+
data["startAppId"] = start_app_id
|
|
68
|
+
if start_date:
|
|
69
|
+
data["startDate"] = start_date
|
|
70
|
+
if end_date:
|
|
71
|
+
data["endDate"] = end_date
|
|
72
|
+
if apk_id:
|
|
73
|
+
data["apkId"] = apk_id
|
|
74
|
+
result = session.workflow_call("v1/instance/getTodoList", data)
|
|
75
|
+
if isinstance(result, dict):
|
|
76
|
+
return {
|
|
77
|
+
"data": result.get("data", result.get("list", [])),
|
|
78
|
+
"count": result.get("count", result.get("total", 0)),
|
|
79
|
+
}
|
|
80
|
+
return {"data": result, "count": len(result)}
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def get_instance(session: Session, instance_id: str) -> dict[str, Any]:
|
|
84
|
+
"""Get instance basic info.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
session: Active session
|
|
88
|
+
instance_id: Instance ID
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
Instance detail
|
|
92
|
+
"""
|
|
93
|
+
return session.workflow_call(
|
|
94
|
+
"instance/getInstance", {"instanceId": instance_id}
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def get_instance_detail(
|
|
99
|
+
session: Session,
|
|
100
|
+
instance_id: str,
|
|
101
|
+
work_id: str = "",
|
|
102
|
+
) -> dict[str, Any]:
|
|
103
|
+
"""Get instance flow detail (v2).
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
session: Active session
|
|
107
|
+
instance_id: Instance ID
|
|
108
|
+
work_id: Work item ID
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
Instance flow detail with node statuses
|
|
112
|
+
"""
|
|
113
|
+
data: dict[str, Any] = {"id": instance_id}
|
|
114
|
+
if work_id:
|
|
115
|
+
data["workId"] = work_id
|
|
116
|
+
return session.workflow_call("v2/instance/get", data)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def get_operation_detail(
|
|
120
|
+
session: Session,
|
|
121
|
+
instance_id: str,
|
|
122
|
+
work_id: str = "",
|
|
123
|
+
) -> dict[str, Any]:
|
|
124
|
+
"""Get available operations for a task.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
session: Active session
|
|
128
|
+
instance_id: Instance ID
|
|
129
|
+
work_id: Work item ID
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
Operation options (approve, reject, etc.)
|
|
133
|
+
"""
|
|
134
|
+
data: dict[str, Any] = {"id": instance_id}
|
|
135
|
+
if work_id:
|
|
136
|
+
data["workId"] = work_id
|
|
137
|
+
return session.workflow_call("instance/getOperationDetail", data)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def get_operation_history(
|
|
141
|
+
session: Session,
|
|
142
|
+
instance_id: str,
|
|
143
|
+
) -> list[dict[str, Any]]:
|
|
144
|
+
"""Get operation history of an instance.
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
session: Active session
|
|
148
|
+
instance_id: Instance ID
|
|
149
|
+
|
|
150
|
+
Returns:
|
|
151
|
+
List of operation records
|
|
152
|
+
"""
|
|
153
|
+
result = session.workflow_call(
|
|
154
|
+
"instance/getOperationHistoryList",
|
|
155
|
+
{"instanceId": instance_id},
|
|
156
|
+
)
|
|
157
|
+
return result if isinstance(result, list) else result.get("list", [])
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
# ── Approval Operations ─────────────────────────────────────────────────
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def _build_action_data(
|
|
164
|
+
instance_id: str,
|
|
165
|
+
work_id: str = "",
|
|
166
|
+
opinion: str = "",
|
|
167
|
+
back_node_id: str = "",
|
|
168
|
+
form_data: Optional[dict] = None,
|
|
169
|
+
signature: Optional[dict] = None,
|
|
170
|
+
) -> dict[str, Any]:
|
|
171
|
+
"""Build common approval action parameters."""
|
|
172
|
+
data: dict[str, Any] = {"id": instance_id}
|
|
173
|
+
if work_id:
|
|
174
|
+
data["workId"] = work_id
|
|
175
|
+
if opinion:
|
|
176
|
+
data["opinion"] = opinion
|
|
177
|
+
if back_node_id:
|
|
178
|
+
data["backNodeId"] = back_node_id
|
|
179
|
+
if form_data:
|
|
180
|
+
data["formData"] = form_data
|
|
181
|
+
if signature:
|
|
182
|
+
data["signature"] = signature
|
|
183
|
+
return data
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def approve(
|
|
187
|
+
session: Session,
|
|
188
|
+
instance_id: str,
|
|
189
|
+
work_id: str = "",
|
|
190
|
+
opinion: str = "",
|
|
191
|
+
form_data: Optional[dict] = None,
|
|
192
|
+
signature: Optional[dict] = None,
|
|
193
|
+
) -> dict[str, Any]:
|
|
194
|
+
"""Approve/pass a workflow task.
|
|
195
|
+
|
|
196
|
+
Args:
|
|
197
|
+
session: Active session
|
|
198
|
+
instance_id: Instance ID
|
|
199
|
+
work_id: Work item ID
|
|
200
|
+
opinion: Approval comment
|
|
201
|
+
form_data: Form data updates
|
|
202
|
+
signature: Signature data
|
|
203
|
+
|
|
204
|
+
Returns:
|
|
205
|
+
Approval result
|
|
206
|
+
"""
|
|
207
|
+
data = _build_action_data(instance_id, work_id, opinion, form_data=form_data, signature=signature)
|
|
208
|
+
return session.workflow_call("instance/pass", data)
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def reject(
|
|
212
|
+
session: Session,
|
|
213
|
+
instance_id: str,
|
|
214
|
+
work_id: str = "",
|
|
215
|
+
opinion: str = "",
|
|
216
|
+
back_node_id: str = "",
|
|
217
|
+
form_data: Optional[dict] = None,
|
|
218
|
+
signature: Optional[dict] = None,
|
|
219
|
+
) -> dict[str, Any]:
|
|
220
|
+
"""Reject/overrule a workflow task.
|
|
221
|
+
|
|
222
|
+
Args:
|
|
223
|
+
session: Active session
|
|
224
|
+
instance_id: Instance ID
|
|
225
|
+
work_id: Work item ID
|
|
226
|
+
opinion: Rejection reason
|
|
227
|
+
back_node_id: Node ID to return to (for resubmission)
|
|
228
|
+
form_data: Form data updates
|
|
229
|
+
signature: Signature data
|
|
230
|
+
|
|
231
|
+
Returns:
|
|
232
|
+
Rejection result
|
|
233
|
+
"""
|
|
234
|
+
data = _build_action_data(instance_id, work_id, opinion, back_node_id, form_data, signature)
|
|
235
|
+
return session.workflow_call("instance/overrule", data)
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def forward(
|
|
239
|
+
session: Session,
|
|
240
|
+
instance_id: str,
|
|
241
|
+
forward_account_id: str,
|
|
242
|
+
work_id: str = "",
|
|
243
|
+
opinion: str = "",
|
|
244
|
+
) -> dict[str, Any]:
|
|
245
|
+
"""Forward/transfer a task to another user.
|
|
246
|
+
|
|
247
|
+
Args:
|
|
248
|
+
session: Active session
|
|
249
|
+
instance_id: Instance ID
|
|
250
|
+
forward_account_id: Target user account ID
|
|
251
|
+
work_id: Work item ID
|
|
252
|
+
opinion: Forward comment
|
|
253
|
+
|
|
254
|
+
Returns:
|
|
255
|
+
Forward result
|
|
256
|
+
"""
|
|
257
|
+
data = _build_action_data(instance_id, work_id, opinion)
|
|
258
|
+
data["forwardAccountId"] = forward_account_id
|
|
259
|
+
return session.workflow_call("instance/forward", data)
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def sign_task(
|
|
263
|
+
session: Session,
|
|
264
|
+
instance_id: str,
|
|
265
|
+
forward_account_id: str,
|
|
266
|
+
before: bool = True,
|
|
267
|
+
work_id: str = "",
|
|
268
|
+
opinion: str = "",
|
|
269
|
+
) -> dict[str, Any]:
|
|
270
|
+
"""Add a co-signer to a task.
|
|
271
|
+
|
|
272
|
+
Args:
|
|
273
|
+
session: Active session
|
|
274
|
+
instance_id: Instance ID
|
|
275
|
+
forward_account_id: Co-signer user ID
|
|
276
|
+
before: True=sign before current user, False=sign after
|
|
277
|
+
work_id: Work item ID
|
|
278
|
+
opinion: Comment
|
|
279
|
+
|
|
280
|
+
Returns:
|
|
281
|
+
Sign result
|
|
282
|
+
"""
|
|
283
|
+
data = _build_action_data(instance_id, work_id, opinion)
|
|
284
|
+
data["forwardAccountId"] = forward_account_id
|
|
285
|
+
data["before"] = before
|
|
286
|
+
return session.workflow_call("instance/sign", data)
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
def submit(
|
|
290
|
+
session: Session,
|
|
291
|
+
instance_id: str,
|
|
292
|
+
work_id: str = "",
|
|
293
|
+
opinion: str = "",
|
|
294
|
+
form_data: Optional[dict] = None,
|
|
295
|
+
) -> dict[str, Any]:
|
|
296
|
+
"""Submit a fill-in task.
|
|
297
|
+
|
|
298
|
+
Args:
|
|
299
|
+
session: Active session
|
|
300
|
+
instance_id: Instance ID
|
|
301
|
+
work_id: Work item ID
|
|
302
|
+
opinion: Submit comment
|
|
303
|
+
form_data: Form data
|
|
304
|
+
|
|
305
|
+
Returns:
|
|
306
|
+
Submit result
|
|
307
|
+
"""
|
|
308
|
+
data = _build_action_data(instance_id, work_id, opinion, form_data=form_data)
|
|
309
|
+
return session.workflow_call("instance/submit", data)
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
def revoke(
|
|
313
|
+
session: Session,
|
|
314
|
+
instance_id: str,
|
|
315
|
+
work_id: str = "",
|
|
316
|
+
) -> dict[str, Any]:
|
|
317
|
+
"""Revoke/withdraw a submitted instance (by initiator).
|
|
318
|
+
|
|
319
|
+
Args:
|
|
320
|
+
session: Active session
|
|
321
|
+
instance_id: Instance ID
|
|
322
|
+
work_id: Work item ID
|
|
323
|
+
|
|
324
|
+
Returns:
|
|
325
|
+
Revoke result
|
|
326
|
+
"""
|
|
327
|
+
return session.workflow_call(
|
|
328
|
+
"instance/revoke",
|
|
329
|
+
_build_action_data(instance_id, work_id),
|
|
330
|
+
)
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
def task_revoke(
|
|
334
|
+
session: Session,
|
|
335
|
+
instance_id: str,
|
|
336
|
+
work_id: str = "",
|
|
337
|
+
) -> dict[str, Any]:
|
|
338
|
+
"""Revoke by approver (undo their own approval).
|
|
339
|
+
|
|
340
|
+
Args:
|
|
341
|
+
session: Active session
|
|
342
|
+
instance_id: Instance ID
|
|
343
|
+
work_id: Work item ID
|
|
344
|
+
|
|
345
|
+
Returns:
|
|
346
|
+
Revoke result
|
|
347
|
+
"""
|
|
348
|
+
return session.workflow_call(
|
|
349
|
+
"instance/taskRevoke",
|
|
350
|
+
_build_action_data(instance_id, work_id),
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
def transfer(
|
|
355
|
+
session: Session,
|
|
356
|
+
instance_id: str,
|
|
357
|
+
forward_account_id: str,
|
|
358
|
+
work_id: str = "",
|
|
359
|
+
opinion: str = "",
|
|
360
|
+
) -> dict[str, Any]:
|
|
361
|
+
"""Transfer a fill-in task to another user.
|
|
362
|
+
|
|
363
|
+
Args:
|
|
364
|
+
session: Active session
|
|
365
|
+
instance_id: Instance ID
|
|
366
|
+
forward_account_id: Target user ID
|
|
367
|
+
work_id: Work item ID
|
|
368
|
+
opinion: Comment
|
|
369
|
+
|
|
370
|
+
Returns:
|
|
371
|
+
Transfer result
|
|
372
|
+
"""
|
|
373
|
+
data = _build_action_data(instance_id, work_id, opinion)
|
|
374
|
+
data["forwardAccountId"] = forward_account_id
|
|
375
|
+
return session.workflow_call("instance/transfer", data)
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
def urge(
|
|
379
|
+
session: Session,
|
|
380
|
+
instance_id: str,
|
|
381
|
+
work_id: str = "",
|
|
382
|
+
) -> dict[str, Any]:
|
|
383
|
+
"""Send an urge/reminder for a pending task.
|
|
384
|
+
|
|
385
|
+
Args:
|
|
386
|
+
session: Active session
|
|
387
|
+
instance_id: Instance ID
|
|
388
|
+
work_id: Work item ID
|
|
389
|
+
|
|
390
|
+
Returns:
|
|
391
|
+
Urge result
|
|
392
|
+
"""
|
|
393
|
+
data: dict[str, Any] = {"id": instance_id, "operationType": 18}
|
|
394
|
+
if work_id:
|
|
395
|
+
data["workId"] = work_id
|
|
396
|
+
return session.workflow_call("instance/operation", data)
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
# ── Batch Operations ────────────────────────────────────────────────────
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
def batch_operation(
|
|
403
|
+
session: Session,
|
|
404
|
+
batch_operation_type: int,
|
|
405
|
+
instance_id: str = "",
|
|
406
|
+
work_id: str = "",
|
|
407
|
+
page_index: int = 1,
|
|
408
|
+
page_size: int = 50,
|
|
409
|
+
type_: int = -1,
|
|
410
|
+
apk_id: str = "",
|
|
411
|
+
process_id: str = "",
|
|
412
|
+
selects: Optional[list] = None,
|
|
413
|
+
) -> dict[str, Any]:
|
|
414
|
+
"""Batch approve/reject/forward tasks.
|
|
415
|
+
|
|
416
|
+
Args:
|
|
417
|
+
session: Active session
|
|
418
|
+
batch_operation_type: 4=pass, 5=reject
|
|
419
|
+
instance_id: Instance ID (for single)
|
|
420
|
+
work_id: Work item ID
|
|
421
|
+
page_index: Page
|
|
422
|
+
page_size: Size
|
|
423
|
+
type_: Task type filter
|
|
424
|
+
apk_id: App filter
|
|
425
|
+
process_id: Process filter
|
|
426
|
+
selects: Selected item IDs for batch
|
|
427
|
+
|
|
428
|
+
Returns:
|
|
429
|
+
Batch result
|
|
430
|
+
"""
|
|
431
|
+
data: dict[str, Any] = {
|
|
432
|
+
"batchOperationType": batch_operation_type,
|
|
433
|
+
"pageIndex": page_index,
|
|
434
|
+
"pageSize": page_size,
|
|
435
|
+
"type": type_,
|
|
436
|
+
}
|
|
437
|
+
if instance_id:
|
|
438
|
+
data["id"] = instance_id
|
|
439
|
+
if work_id:
|
|
440
|
+
data["workId"] = work_id
|
|
441
|
+
if apk_id:
|
|
442
|
+
data["apkId"] = apk_id
|
|
443
|
+
if process_id:
|
|
444
|
+
data["processId"] = process_id
|
|
445
|
+
if selects:
|
|
446
|
+
data["selects"] = selects
|
|
447
|
+
return session.workflow_call("v2/instance/batch", data)
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
# ── Execution History ────────────────────────────────────────────────────
|
|
451
|
+
|
|
452
|
+
|
|
453
|
+
def get_history_list(
|
|
454
|
+
session: Session,
|
|
455
|
+
process_id: str = "",
|
|
456
|
+
page_index: int = 1,
|
|
457
|
+
page_size: int = 50,
|
|
458
|
+
status: int = 0,
|
|
459
|
+
title: str = "",
|
|
460
|
+
start_date: str = "",
|
|
461
|
+
end_date: str = "",
|
|
462
|
+
instance_id: str = "",
|
|
463
|
+
) -> dict[str, Any]:
|
|
464
|
+
"""Get workflow execution history.
|
|
465
|
+
|
|
466
|
+
Args:
|
|
467
|
+
session: Active session
|
|
468
|
+
process_id: Filter by process
|
|
469
|
+
page_index: Page number
|
|
470
|
+
page_size: Items per page
|
|
471
|
+
status: Status filter (1=running, 2=completed, 3=rejected, 4=failed)
|
|
472
|
+
title: Title search
|
|
473
|
+
start_date: Start date (YYYY-MM-DD)
|
|
474
|
+
end_date: End date (YYYY-MM-DD)
|
|
475
|
+
instance_id: Specific instance ID
|
|
476
|
+
|
|
477
|
+
Returns:
|
|
478
|
+
History list with count
|
|
479
|
+
"""
|
|
480
|
+
data: dict[str, Any] = {"pageIndex": page_index, "pageSize": page_size}
|
|
481
|
+
if process_id:
|
|
482
|
+
data["processId"] = process_id
|
|
483
|
+
if status:
|
|
484
|
+
data["status"] = status
|
|
485
|
+
if title:
|
|
486
|
+
data["title"] = title
|
|
487
|
+
if start_date:
|
|
488
|
+
data["startDate"] = start_date
|
|
489
|
+
if end_date:
|
|
490
|
+
data["endDate"] = end_date
|
|
491
|
+
if instance_id:
|
|
492
|
+
data["instanceId"] = instance_id
|
|
493
|
+
result = session.workflow_call("instance/getHistoryList", data)
|
|
494
|
+
if isinstance(result, dict):
|
|
495
|
+
return {
|
|
496
|
+
"data": result.get("data", result.get("list", [])),
|
|
497
|
+
"count": result.get("count", result.get("total", 0)),
|
|
498
|
+
}
|
|
499
|
+
return {"data": result, "count": len(result)}
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
def get_history_detail(
|
|
503
|
+
session: Session,
|
|
504
|
+
instance_id: str,
|
|
505
|
+
) -> dict[str, Any]:
|
|
506
|
+
"""Get execution history detail.
|
|
507
|
+
|
|
508
|
+
Args:
|
|
509
|
+
session: Active session
|
|
510
|
+
instance_id: Instance ID
|
|
511
|
+
|
|
512
|
+
Returns:
|
|
513
|
+
History detail with node execution info
|
|
514
|
+
"""
|
|
515
|
+
return session.workflow_call(
|
|
516
|
+
"instance/getHistoryDetail",
|
|
517
|
+
{"instanceId": instance_id},
|
|
518
|
+
)
|
|
519
|
+
|
|
520
|
+
|
|
521
|
+
# ── Instance Lifecycle ───────────────────────────────────────────────────
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+
def end_instance(session: Session, instance_id: str) -> dict[str, Any]:
|
|
525
|
+
"""Terminate a running instance.
|
|
526
|
+
|
|
527
|
+
Args:
|
|
528
|
+
session: Active session
|
|
529
|
+
instance_id: Instance ID
|
|
530
|
+
|
|
531
|
+
Returns:
|
|
532
|
+
Termination result
|
|
533
|
+
"""
|
|
534
|
+
return session.workflow_call(
|
|
535
|
+
"v1/instance/endInstance", {"instanceId": instance_id}
|
|
536
|
+
)
|
|
537
|
+
|
|
538
|
+
|
|
539
|
+
def reset_instance(session: Session, instance_id: str) -> dict[str, Any]:
|
|
540
|
+
"""Retry a failed instance.
|
|
541
|
+
|
|
542
|
+
Args:
|
|
543
|
+
session: Active session
|
|
544
|
+
instance_id: Instance ID
|
|
545
|
+
|
|
546
|
+
Returns:
|
|
547
|
+
Reset result
|
|
548
|
+
"""
|
|
549
|
+
return session.workflow_call(
|
|
550
|
+
"v1/instance/resetInstance", {"instanceId": instance_id}
|
|
551
|
+
)
|
|
552
|
+
|
|
553
|
+
|
|
554
|
+
def restart_instance(
|
|
555
|
+
session: Session,
|
|
556
|
+
instance_id: str,
|
|
557
|
+
work_id: str = "",
|
|
558
|
+
) -> dict[str, Any]:
|
|
559
|
+
"""Re-initiate a rejected/completed instance.
|
|
560
|
+
|
|
561
|
+
Args:
|
|
562
|
+
session: Active session
|
|
563
|
+
instance_id: Instance ID
|
|
564
|
+
work_id: Work item ID
|
|
565
|
+
|
|
566
|
+
Returns:
|
|
567
|
+
Restart result
|
|
568
|
+
"""
|
|
569
|
+
return session.workflow_call(
|
|
570
|
+
"instance/restart",
|
|
571
|
+
_build_action_data(instance_id, work_id),
|
|
572
|
+
)
|