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.
Files changed (58) hide show
  1. hap_cli/README.md +194 -0
  2. hap_cli/README_CN.md +601 -0
  3. hap_cli/__init__.py +3 -0
  4. hap_cli/commands/__init__.py +1 -0
  5. hap_cli/commands/ai_cmd.py +224 -0
  6. hap_cli/commands/app_cmd.py +308 -0
  7. hap_cli/commands/calendar_cmd.py +138 -0
  8. hap_cli/commands/chat_cmd.py +101 -0
  9. hap_cli/commands/config_cmd.py +169 -0
  10. hap_cli/commands/contact_cmd.py +125 -0
  11. hap_cli/commands/department_cmd.py +168 -0
  12. hap_cli/commands/group_cmd.py +128 -0
  13. hap_cli/commands/instance_cmd.py +310 -0
  14. hap_cli/commands/node_cmd.py +538 -0
  15. hap_cli/commands/optionset_cmd.py +99 -0
  16. hap_cli/commands/page_cmd.py +102 -0
  17. hap_cli/commands/plugin_cmd.py +133 -0
  18. hap_cli/commands/post_cmd.py +155 -0
  19. hap_cli/commands/record_cmd.py +228 -0
  20. hap_cli/commands/role_cmd.py +221 -0
  21. hap_cli/commands/workflow_cmd.py +284 -0
  22. hap_cli/commands/worksheet_cmd.py +342 -0
  23. hap_cli/context.py +43 -0
  24. hap_cli/core/__init__.py +1 -0
  25. hap_cli/core/ai.py +133 -0
  26. hap_cli/core/app.py +307 -0
  27. hap_cli/core/auth.py +219 -0
  28. hap_cli/core/calendar_mod.py +114 -0
  29. hap_cli/core/chat.py +73 -0
  30. hap_cli/core/contact.py +85 -0
  31. hap_cli/core/department.py +131 -0
  32. hap_cli/core/flow_node.py +1001 -0
  33. hap_cli/core/group.py +99 -0
  34. hap_cli/core/instance.py +572 -0
  35. hap_cli/core/optionset.py +112 -0
  36. hap_cli/core/page.py +138 -0
  37. hap_cli/core/plugin.py +87 -0
  38. hap_cli/core/post.py +118 -0
  39. hap_cli/core/record.py +268 -0
  40. hap_cli/core/role.py +227 -0
  41. hap_cli/core/session.py +348 -0
  42. hap_cli/core/workflow.py +556 -0
  43. hap_cli/core/worksheet.py +403 -0
  44. hap_cli/hap_cli.py +105 -0
  45. hap_cli/skills/SKILL.md +383 -0
  46. hap_cli/skills/__init__.py +0 -0
  47. hap_cli/tests/__init__.py +1 -0
  48. hap_cli/tests/test_core.py +1824 -0
  49. hap_cli/tests/test_full_e2e.py +136 -0
  50. hap_cli/tests/test_integration.py +805 -0
  51. hap_cli/utils/__init__.py +1 -0
  52. hap_cli/utils/formatting.py +111 -0
  53. hap_cli/utils/options.py +10 -0
  54. hap_cli-0.5.0.dist-info/METADATA +223 -0
  55. hap_cli-0.5.0.dist-info/RECORD +58 -0
  56. hap_cli-0.5.0.dist-info/WHEEL +5 -0
  57. hap_cli-0.5.0.dist-info/entry_points.txt +2 -0
  58. hap_cli-0.5.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,556 @@
1
+ """Workflow process lifecycle management for MingDAO HAP.
2
+
3
+ Covers: create, delete, update, copy, publish, version history,
4
+ process config, trigger, and process querying.
5
+ """
6
+
7
+ from typing import Any, Optional
8
+
9
+ from hap_cli.core.session import Session
10
+
11
+
12
+ # ── Process CRUD ─────────────────────────────────────────────────────────
13
+
14
+
15
+ def create_process(
16
+ session: Session,
17
+ company_id: str,
18
+ name: str,
19
+ relation_id: str = "",
20
+ relation_type: int = 0,
21
+ start_event_app_type: int = 1,
22
+ explain: str = "",
23
+ icon_name: str = "",
24
+ icon_color: str = "",
25
+ ) -> dict[str, Any]:
26
+ """Create a new workflow process.
27
+
28
+ Args:
29
+ session: Active session
30
+ company_id: Organization/project ID
31
+ name: Process name
32
+ relation_id: Related app ID
33
+ relation_type: Relation type (0=app)
34
+ start_event_app_type: Trigger type (1=worksheet, 5=scheduled, 6=date)
35
+ explain: Process description
36
+ icon_name: Icon name
37
+ icon_color: Icon color hex
38
+
39
+ Returns:
40
+ Created process info with processId
41
+ """
42
+ data: dict[str, Any] = {
43
+ "companyId": company_id,
44
+ "name": name,
45
+ "startEventAppType": start_event_app_type,
46
+ }
47
+ if relation_id:
48
+ data["relationId"] = relation_id
49
+ if relation_type:
50
+ data["relationType"] = relation_type
51
+ if explain:
52
+ data["explain"] = explain
53
+ if icon_name:
54
+ data["iconName"] = icon_name
55
+ if icon_color:
56
+ data["iconColor"] = icon_color
57
+ return session.workflow_call("process/add", data)
58
+
59
+
60
+ def delete_process(session: Session, process_id: str) -> dict[str, Any]:
61
+ """Delete a workflow process.
62
+
63
+ Args:
64
+ session: Active session
65
+ process_id: Process ID to delete
66
+
67
+ Returns:
68
+ Deletion result
69
+ """
70
+ return session.workflow_call("process/deleteProcess", {"processId": process_id})
71
+
72
+
73
+ def update_process(
74
+ session: Session,
75
+ process_id: str,
76
+ name: str = "",
77
+ explain: str = "",
78
+ icon_name: str = "",
79
+ icon_color: str = "",
80
+ company_id: str = "",
81
+ ) -> dict[str, Any]:
82
+ """Update workflow process basic info.
83
+
84
+ Args:
85
+ session: Active session
86
+ process_id: Process ID
87
+ name: New name
88
+ explain: New description
89
+ icon_name: New icon
90
+ icon_color: New color
91
+ company_id: Organization ID
92
+
93
+ Returns:
94
+ Update result
95
+ """
96
+ data: dict[str, Any] = {"processId": process_id}
97
+ if name:
98
+ data["name"] = name
99
+ if explain:
100
+ data["explain"] = explain
101
+ if icon_name:
102
+ data["iconName"] = icon_name
103
+ if icon_color:
104
+ data["iconColor"] = icon_color
105
+ if company_id:
106
+ data["companyId"] = company_id
107
+ return session.workflow_call("process/updateProcess", data)
108
+
109
+
110
+ def copy_process(
111
+ session: Session,
112
+ process_id: str,
113
+ name: str,
114
+ sub_process: bool = False,
115
+ ) -> dict[str, Any]:
116
+ """Copy/clone a workflow process.
117
+
118
+ Args:
119
+ session: Active session
120
+ process_id: Source process ID
121
+ name: Name for the copy
122
+ sub_process: Include sub-processes
123
+
124
+ Returns:
125
+ New process info
126
+ """
127
+ return session.workflow_call(
128
+ "process/copyProcess",
129
+ {"processId": process_id, "name": name, "subProcess": sub_process},
130
+ )
131
+
132
+
133
+ def move_process(
134
+ session: Session,
135
+ process_id: str,
136
+ relation_id: str,
137
+ ) -> dict[str, Any]:
138
+ """Move process to another application.
139
+
140
+ Args:
141
+ session: Active session
142
+ process_id: Process ID
143
+ relation_id: Target app ID
144
+
145
+ Returns:
146
+ Move result
147
+ """
148
+ return session.workflow_call(
149
+ "process/move",
150
+ {"processId": process_id, "relationId": relation_id},
151
+ )
152
+
153
+
154
+ def get_process_by_id(session: Session, process_id: str) -> dict[str, Any]:
155
+ """Get process details by ID.
156
+
157
+ Args:
158
+ session: Active session
159
+ process_id: Process ID
160
+
161
+ Returns:
162
+ Process detail dict
163
+ """
164
+ return session.workflow_call("process/getProcessById", {"id": process_id})
165
+
166
+
167
+ # ── Publish & Version ────────────────────────────────────────────────────
168
+
169
+
170
+ def publish(
171
+ session: Session,
172
+ process_id: str,
173
+ is_publish: bool = True,
174
+ ) -> dict[str, Any]:
175
+ """Publish or unpublish (enable/disable) a workflow.
176
+
177
+ Args:
178
+ session: Active session
179
+ process_id: Process ID
180
+ is_publish: True to publish/enable, False to disable
181
+
182
+ Returns:
183
+ Publish result
184
+ """
185
+ return session.workflow_call(
186
+ "process/publish",
187
+ {"processId": process_id, "isPublish": is_publish},
188
+ )
189
+
190
+
191
+ def get_publish_info(
192
+ session: Session,
193
+ process_id: str,
194
+ instance_id: str = "",
195
+ ) -> dict[str, Any]:
196
+ """Get publish version information.
197
+
198
+ Args:
199
+ session: Active session
200
+ process_id: Process ID
201
+ instance_id: Optional instance ID
202
+
203
+ Returns:
204
+ Publish info
205
+ """
206
+ data: dict[str, Any] = {"processId": process_id}
207
+ if instance_id:
208
+ data["instanceId"] = instance_id
209
+ return session.workflow_call("process/getProcessPublish", data)
210
+
211
+
212
+ def get_version_history(
213
+ session: Session,
214
+ process_id: str,
215
+ page_index: int = 1,
216
+ page_size: int = 20,
217
+ ) -> dict[str, Any]:
218
+ """Get workflow version history.
219
+
220
+ Args:
221
+ session: Active session
222
+ process_id: Process ID
223
+ page_index: Page number
224
+ page_size: Items per page
225
+
226
+ Returns:
227
+ Version history list
228
+ """
229
+ return session.workflow_call(
230
+ "process/getHistory",
231
+ {"processId": process_id, "pageIndex": page_index, "pageSize": page_size},
232
+ )
233
+
234
+
235
+ def rollback_version(session: Session, process_id: str) -> dict[str, Any]:
236
+ """Rollback to previous version.
237
+
238
+ Args:
239
+ session: Active session
240
+ process_id: Process ID
241
+
242
+ Returns:
243
+ Rollback result
244
+ """
245
+ return session.workflow_call("process/goBack", {"processId": process_id})
246
+
247
+
248
+ # ── Process Config ───────────────────────────────────────────────────────
249
+
250
+
251
+ def get_process_config(session: Session, process_id: str) -> dict[str, Any]:
252
+ """Get workflow global configuration.
253
+
254
+ Args:
255
+ session: Active session
256
+ process_id: Process ID
257
+
258
+ Returns:
259
+ Process config dict
260
+ """
261
+ return session.workflow_call("process/getProcessConfig", {"processId": process_id})
262
+
263
+
264
+ def save_process_config(
265
+ session: Session,
266
+ process_id: str,
267
+ config: dict[str, Any],
268
+ ) -> dict[str, Any]:
269
+ """Save workflow global configuration.
270
+
271
+ Args:
272
+ session: Active session
273
+ process_id: Process ID
274
+ config: Configuration dict. Supported keys include:
275
+ - executeType: Execution type
276
+ - allowRevoke: Allow initiator to revoke
277
+ - allowTaskRevoke: Allow approver to revoke
278
+ - allowUrge: Allow urging
279
+ - triggerType: Trigger type
280
+ - triggerView: Trigger view ID
281
+ - errorInterval: Error retry interval
282
+ - errorNotifiers: Error notification recipients
283
+ - processVariables: Process variables list
284
+ - agents: Agent configurations
285
+ - defaultAgent: Default agent
286
+ - required/requiredIds: Required fields
287
+ - pbcConfig: PBP configuration
288
+ - And many more (see API docs)
289
+
290
+ Returns:
291
+ Save result
292
+ """
293
+ data = {"processId": process_id}
294
+ data.update(config)
295
+ return session.workflow_call("process/saveProcessConfig", data)
296
+
297
+
298
+ # ── Trigger / Start ─────────────────────────────────────────────────────
299
+
300
+
301
+ def start_process_by_id(
302
+ session: Session,
303
+ process_id: str,
304
+ source_id: str = "",
305
+ fields: Optional[list] = None,
306
+ debug_events: Optional[list] = None,
307
+ ) -> dict[str, Any]:
308
+ """Manually trigger a workflow by process ID.
309
+
310
+ Args:
311
+ session: Active session
312
+ process_id: Process ID
313
+ source_id: Source record ID
314
+ fields: Field values for the trigger
315
+ debug_events: Debug event data
316
+
317
+ Returns:
318
+ Trigger result with instance info
319
+ """
320
+ data: dict[str, Any] = {"processId": process_id}
321
+ if source_id:
322
+ data["sourceId"] = source_id
323
+ if fields:
324
+ data["fields"] = fields
325
+ if debug_events:
326
+ data["debugEvents"] = debug_events
327
+ return session.workflow_call("process/startProcessById", data)
328
+
329
+
330
+ def start_process_by_pbp(
331
+ session: Session,
332
+ process_id: str,
333
+ app_id: str,
334
+ trigger_id: str = "",
335
+ title: str = "",
336
+ controls: Optional[list] = None,
337
+ ) -> dict[str, Any]:
338
+ """Trigger a PBP (Packaged Business Process) workflow.
339
+
340
+ Args:
341
+ session: Active session
342
+ process_id: Process ID
343
+ app_id: Application ID
344
+ trigger_id: Trigger ID
345
+ title: Instance title
346
+ controls: Input control values
347
+
348
+ Returns:
349
+ Trigger result
350
+ """
351
+ data: dict[str, Any] = {"processId": process_id, "appId": app_id}
352
+ if trigger_id:
353
+ data["triggerId"] = trigger_id
354
+ if title:
355
+ data["title"] = title
356
+ if controls:
357
+ data["controls"] = controls
358
+ return session.workflow_call("process/startProcessByPBC", data)
359
+
360
+
361
+ def start_process(
362
+ session: Session,
363
+ app_id: str,
364
+ trigger_id: str,
365
+ sources: Optional[list[str]] = None,
366
+ view_id: str = "",
367
+ is_all: bool = False,
368
+ ) -> dict[str, Any]:
369
+ """Trigger workflow from worksheet button.
370
+
371
+ Args:
372
+ session: Active session
373
+ app_id: Application ID
374
+ trigger_id: Button trigger ID
375
+ sources: Source record IDs
376
+ view_id: View ID
377
+ is_all: Apply to all records in view
378
+
379
+ Returns:
380
+ Trigger result
381
+ """
382
+ data: dict[str, Any] = {"appId": app_id, "triggerId": trigger_id}
383
+ if sources:
384
+ data["sources"] = sources
385
+ if view_id:
386
+ data["viewId"] = view_id
387
+ if is_all:
388
+ data["isAll"] = is_all
389
+ return session.workflow_call("process/startProcess", data)
390
+
391
+
392
+ # ── Listing ──────────────────────────────────────────────────────────────
393
+
394
+
395
+ def get_process_list(
396
+ session: Session,
397
+ relation_id: str,
398
+ keyword: str = "",
399
+ page_index: int = 1,
400
+ page_size: int = 50,
401
+ process_list_type: int = 0,
402
+ ) -> dict[str, Any]:
403
+ """List workflows for an app.
404
+
405
+ Args:
406
+ session: Active session
407
+ relation_id: App ID
408
+ keyword: Search keyword
409
+ page_index: Page number
410
+ page_size: Items per page
411
+ process_list_type: List type filter
412
+
413
+ Returns:
414
+ Dict with list and count
415
+ """
416
+ data: dict[str, Any] = {
417
+ "relationId": relation_id,
418
+ "pageIndex": page_index,
419
+ "pageSize": page_size,
420
+ }
421
+ if keyword:
422
+ data["keyWords"] = keyword
423
+ if process_list_type:
424
+ data["processListType"] = process_list_type
425
+ result = session.workflow_call("v1/process/listAll", data)
426
+ if isinstance(result, dict):
427
+ return {
428
+ "data": result.get("data", result.get("list", [])),
429
+ "count": result.get("count", result.get("total", 0)),
430
+ }
431
+ return {"data": result, "count": len(result)}
432
+
433
+
434
+ def get_process_by_company(
435
+ session: Session,
436
+ company_id: str,
437
+ keyword: str = "",
438
+ enabled: Optional[bool] = None,
439
+ page_index: int = 1,
440
+ page_size: int = 50,
441
+ apk_id: str = "",
442
+ ) -> dict[str, Any]:
443
+ """List all workflows in an organization.
444
+
445
+ Args:
446
+ session: Active session
447
+ company_id: Organization ID
448
+ keyword: Search keyword
449
+ enabled: Filter by enabled status
450
+ page_index: Page number
451
+ page_size: Items per page
452
+ apk_id: Filter by app ID
453
+
454
+ Returns:
455
+ Dict with list and count
456
+ """
457
+ data: dict[str, Any] = {
458
+ "companyId": company_id,
459
+ "pageIndex": page_index,
460
+ "pageSize": page_size,
461
+ }
462
+ if keyword:
463
+ data["keyWords"] = keyword
464
+ if enabled is not None:
465
+ data["enabled"] = enabled
466
+ if apk_id:
467
+ data["apkId"] = apk_id
468
+ result = session.workflow_call("v1/process/getProcessByCompanyId", data)
469
+ if isinstance(result, dict):
470
+ return {
471
+ "data": result.get("data", result.get("list", [])),
472
+ "count": result.get("count", result.get("total", 0)),
473
+ }
474
+ return {"data": result, "count": len(result)}
475
+
476
+
477
+ def get_process_use_count(
478
+ session: Session,
479
+ company_id: str,
480
+ ) -> dict[str, Any]:
481
+ """Get workflow usage statistics.
482
+
483
+ Args:
484
+ session: Active session
485
+ company_id: Organization ID
486
+
487
+ Returns:
488
+ Usage count info
489
+ """
490
+ return session.workflow_call(
491
+ "v1/process/getProcessUseCount",
492
+ {"companyId": company_id},
493
+ )
494
+
495
+
496
+ # ── Process Groups ───────────────────────────────────────────────────────
497
+
498
+
499
+ def get_group_list(
500
+ session: Session,
501
+ relation_id: str,
502
+ ) -> list[dict[str, Any]]:
503
+ """Get workflow groups for an app.
504
+
505
+ Args:
506
+ session: Active session
507
+ relation_id: App ID
508
+
509
+ Returns:
510
+ List of group dicts
511
+ """
512
+ result = session.workflow_call(
513
+ "processGroup/getGroupList",
514
+ {"relationId": relation_id},
515
+ )
516
+ return result if isinstance(result, list) else result.get("list", [])
517
+
518
+
519
+ def create_group(
520
+ session: Session,
521
+ relation_id: str,
522
+ name: str,
523
+ ) -> dict[str, Any]:
524
+ """Create a workflow group.
525
+
526
+ Args:
527
+ session: Active session
528
+ relation_id: App ID
529
+ name: Group name
530
+
531
+ Returns:
532
+ Created group info
533
+ """
534
+ return session.workflow_call(
535
+ "processGroup/addGroup",
536
+ {"relationId": relation_id, "name": name},
537
+ )
538
+
539
+
540
+ def delete_group(
541
+ session: Session,
542
+ group_id: str,
543
+ ) -> dict[str, Any]:
544
+ """Delete a workflow group.
545
+
546
+ Args:
547
+ session: Active session
548
+ group_id: Group ID
549
+
550
+ Returns:
551
+ Deletion result
552
+ """
553
+ return session.workflow_call(
554
+ "processGroup/deleteGroup",
555
+ {"groupId": group_id},
556
+ )