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,221 @@
1
+ """CLI commands for role management."""
2
+
3
+ import json
4
+
5
+ import click
6
+
7
+ from hap_cli.context import pass_context
8
+ from hap_cli.core import role as role_mod
9
+ from hap_cli.utils.formatting import output_json, output_kv, output_table
10
+
11
+
12
+ @click.group()
13
+ def role():
14
+ """Role management."""
15
+ pass
16
+
17
+
18
+ @role.command("list")
19
+ @click.argument("app_id", default="")
20
+ @pass_context
21
+ def role_list(ctx, app_id):
22
+ """List roles for an application."""
23
+ try:
24
+ session = ctx.get_session()
25
+ aid = app_id or session.default_app_id
26
+ if not aid:
27
+ raise click.UsageError("App ID required.")
28
+ roles = role_mod.get_roles(session, aid)
29
+ ctx.output(
30
+ roles,
31
+ lambda d: output_table(
32
+ d,
33
+ ["roleId", "name", "permissionWay", "description"],
34
+ ["Role ID", "Name", "Permission", "Description"],
35
+ ),
36
+ )
37
+ except Exception as e:
38
+ ctx.handle_error(e)
39
+
40
+
41
+ @role.command("create")
42
+ @click.argument("app_id")
43
+ @click.option("--name", "-n", required=True, help="Role name")
44
+ @click.option("--desc", "-d", default="", help="Description")
45
+ @click.option(
46
+ "--permission", "-p", default=10, type=int,
47
+ help="Permission type: 0=custom, 10=readonly, 50=member, 100=admin",
48
+ )
49
+ @pass_context
50
+ def role_create(ctx, app_id, name, desc, permission):
51
+ """Create a new role."""
52
+ try:
53
+ session = ctx.get_session()
54
+ data = role_mod.create_role(session, app_id, name, desc, permission)
55
+ ctx.output(data, lambda d: click.echo(f"Created role: {d}"))
56
+ except Exception as e:
57
+ ctx.handle_error(e)
58
+
59
+
60
+ @role.command("delete")
61
+ @click.argument("app_id")
62
+ @click.argument("role_id")
63
+ @click.option("--move-to", "-m", default="", help="Move members to this role ID")
64
+ @click.option("--yes", "-y", is_flag=True, help="Skip confirmation")
65
+ @pass_context
66
+ def role_delete(ctx, app_id, role_id, move_to, yes):
67
+ """Delete a role."""
68
+ try:
69
+ if not yes:
70
+ click.confirm(f"Delete role {role_id}?", abort=True)
71
+ session = ctx.get_session()
72
+ data = role_mod.delete_role(session, app_id, role_id, move_to)
73
+ ctx.output(data, lambda d: click.echo(f"Deleted role."))
74
+ except Exception as e:
75
+ ctx.handle_error(e)
76
+
77
+
78
+ @role.command("add-member")
79
+ @click.argument("app_id")
80
+ @click.argument("role_id")
81
+ @click.option("--user", "-u", multiple=True, help="User ID to add")
82
+ @click.option("--dept", "-d", multiple=True, help="Department ID to add")
83
+ @pass_context
84
+ def role_add_member(ctx, app_id, role_id, user, dept):
85
+ """Add members to a role."""
86
+ try:
87
+ session = ctx.get_session()
88
+ data = role_mod.add_role_members(
89
+ session, app_id, role_id,
90
+ user_ids=list(user) if user else None,
91
+ department_ids=list(dept) if dept else None,
92
+ )
93
+ ctx.output(data, lambda d: click.echo("Members added."))
94
+ except Exception as e:
95
+ ctx.handle_error(e)
96
+
97
+
98
+ @role.command("remove-member")
99
+ @click.argument("app_id")
100
+ @click.argument("role_id")
101
+ @click.option("--user", "-u", multiple=True, help="User ID to remove")
102
+ @click.option("--dept", "-d", multiple=True, help="Department ID to remove")
103
+ @pass_context
104
+ def role_remove_member(ctx, app_id, role_id, user, dept):
105
+ """Remove members from a role."""
106
+ try:
107
+ session = ctx.get_session()
108
+ data = role_mod.remove_role_members(
109
+ session, app_id, role_id,
110
+ user_ids=list(user) if user else None,
111
+ department_ids=list(dept) if dept else None,
112
+ )
113
+ ctx.output(data, lambda d: click.echo("Members removed."))
114
+ except Exception as e:
115
+ ctx.handle_error(e)
116
+
117
+
118
+ @role.command("permissions")
119
+ @click.argument("app_id")
120
+ @click.argument("role_id")
121
+ @pass_context
122
+ def role_permissions(ctx, app_id, role_id):
123
+ """Get role detail including permissions."""
124
+ try:
125
+ session = ctx.get_session()
126
+ data = role_mod.get_role_detail(session, app_id, role_id)
127
+ ctx.output(data, lambda d: output_json(d))
128
+ except Exception as e:
129
+ ctx.handle_error(e)
130
+
131
+
132
+ @role.command("set-permissions")
133
+ @click.argument("app_id")
134
+ @click.argument("role_id")
135
+ @click.option("--permissions", "-P", default="", help="Permissions as JSON string")
136
+ @click.option("--permission-way", type=int, default=0, help="Permission type: 0=custom, 10=readonly, 50=member, 100=admin")
137
+ @pass_context
138
+ def role_set_permissions(ctx, app_id, role_id, permissions, permission_way):
139
+ """Edit role permissions."""
140
+ try:
141
+ session = ctx.get_session()
142
+ perms = json.loads(permissions) if permissions else None
143
+ data = role_mod.edit_role(
144
+ session, app_id, role_id,
145
+ permission_way=permission_way, permissions=perms,
146
+ )
147
+ ctx.output(data, lambda d: click.echo("Permissions updated."))
148
+ except Exception as e:
149
+ ctx.handle_error(e)
150
+
151
+
152
+ @role.command("rename")
153
+ @click.argument("app_id")
154
+ @click.argument("role_id")
155
+ @click.option("--name", "-n", required=True, help="New role name")
156
+ @pass_context
157
+ def role_rename(ctx, app_id, role_id, name):
158
+ """Rename a role."""
159
+ try:
160
+ session = ctx.get_session()
161
+ data = role_mod.rename_role(session, app_id, role_id, name)
162
+ ctx.output(data, lambda d: click.echo(f"Role renamed to: {name}"))
163
+ except Exception as e:
164
+ ctx.handle_error(e)
165
+
166
+
167
+ @role.command("apply")
168
+ @click.argument("app_id")
169
+ @click.argument("role_id")
170
+ @pass_context
171
+ def role_apply(ctx, app_id, role_id):
172
+ """Apply to join a role."""
173
+ try:
174
+ session = ctx.get_session()
175
+ data = role_mod.apply_role(session, app_id, role_id)
176
+ ctx.output(data, lambda d: click.echo("Role application submitted."))
177
+ except Exception as e:
178
+ ctx.handle_error(e)
179
+
180
+
181
+ @role.command("approve")
182
+ @click.argument("app_id")
183
+ @click.argument("role_id")
184
+ @click.argument("account_id")
185
+ @pass_context
186
+ def role_approve(ctx, app_id, role_id, account_id):
187
+ """Approve a user's role application."""
188
+ try:
189
+ session = ctx.get_session()
190
+ data = role_mod.approve_role_apply(session, app_id, role_id, account_id)
191
+ ctx.output(data, lambda d: click.echo("Application approved."))
192
+ except Exception as e:
193
+ ctx.handle_error(e)
194
+
195
+
196
+ @role.command("reject")
197
+ @click.argument("app_id")
198
+ @click.argument("role_id")
199
+ @click.argument("account_id")
200
+ @pass_context
201
+ def role_reject(ctx, app_id, role_id, account_id):
202
+ """Reject a user's role application."""
203
+ try:
204
+ session = ctx.get_session()
205
+ data = role_mod.reject_role_apply(session, app_id, role_id, account_id)
206
+ ctx.output(data, lambda d: click.echo("Application rejected."))
207
+ except Exception as e:
208
+ ctx.handle_error(e)
209
+
210
+
211
+ @role.command("pending")
212
+ @click.argument("app_id")
213
+ @pass_context
214
+ def role_pending(ctx, app_id):
215
+ """Get users with pending role applications."""
216
+ try:
217
+ session = ctx.get_session()
218
+ data = role_mod.get_pending_role_users(session, app_id)
219
+ ctx.output(data, lambda d: output_json(d))
220
+ except Exception as e:
221
+ ctx.handle_error(e)
@@ -0,0 +1,284 @@
1
+ """CLI commands for workflow process lifecycle management."""
2
+
3
+ import json
4
+
5
+ import click
6
+
7
+ from hap_cli.context import pass_context
8
+ from hap_cli.core import workflow as wf_mod
9
+ from hap_cli.utils.formatting import output_json, output_table, output_kv
10
+
11
+
12
+ @click.group()
13
+ def workflow():
14
+ """Workflow process lifecycle management."""
15
+ pass
16
+
17
+
18
+ @workflow.command("list")
19
+ @click.argument("app_id", default="")
20
+ @click.option("--keyword", "-k", default="", help="Search keyword")
21
+ @click.option("--enabled/--disabled", default=None, help="Filter by status")
22
+ @click.option("--page-size", "-n", default=50, help="Items per page")
23
+ @click.option("--page", "-p", default=1, help="Page number")
24
+ @pass_context
25
+ def workflow_list(ctx, app_id, keyword, enabled, page_size, page):
26
+ """List workflows in an application."""
27
+ try:
28
+ session = ctx.get_session()
29
+ aid = app_id or session.default_app_id
30
+ if not aid:
31
+ raise click.UsageError("App ID required.")
32
+ result = wf_mod.get_process_list(
33
+ session, aid, keyword=keyword,
34
+ page_index=page, page_size=page_size,
35
+ )
36
+ ctx.output(
37
+ result,
38
+ lambda d: output_table(
39
+ d.get("data", []),
40
+ ["id", "name", "enabled", "child"],
41
+ ["Process ID", "Name", "Enabled", "Sub-processes"],
42
+ ),
43
+ )
44
+ except Exception as e:
45
+ ctx.handle_error(e)
46
+
47
+
48
+ @workflow.command("get")
49
+ @click.argument("process_id")
50
+ @pass_context
51
+ def workflow_get(ctx, process_id):
52
+ """Get workflow process details."""
53
+ try:
54
+ session = ctx.get_session()
55
+ data = wf_mod.get_process_by_id(session, process_id)
56
+ ctx.output(data, lambda d: output_kv(d))
57
+ except Exception as e:
58
+ ctx.handle_error(e)
59
+
60
+
61
+ @workflow.command("create")
62
+ @click.option("--company-id", "-c", required=True, help="Organization/project ID")
63
+ @click.option("--name", "-n", required=True, help="Process name")
64
+ @click.option("--app-id", "-a", default="", help="Related app ID")
65
+ @click.option("--type", "start_type", default=1, type=int,
66
+ help="Trigger type: 1=worksheet, 5=scheduled, 6=date")
67
+ @click.option("--desc", "-d", default="", help="Description")
68
+ @pass_context
69
+ def workflow_create(ctx, company_id, name, app_id, start_type, desc):
70
+ """Create a new workflow process."""
71
+ try:
72
+ session = ctx.get_session()
73
+ data = wf_mod.create_process(
74
+ session, company_id, name,
75
+ relation_id=app_id,
76
+ start_event_app_type=start_type,
77
+ explain=desc,
78
+ )
79
+ ctx.output(data, lambda d: click.echo(f"Created workflow: {d}"))
80
+ except Exception as e:
81
+ ctx.handle_error(e)
82
+
83
+
84
+ @workflow.command("update")
85
+ @click.argument("process_id")
86
+ @click.option("--name", "-n", default="", help="New name")
87
+ @click.option("--desc", "-d", default="", help="New description")
88
+ @click.option("--icon-color", default="", help="Icon color hex")
89
+ @pass_context
90
+ def workflow_update(ctx, process_id, name, desc, icon_color):
91
+ """Update workflow process info."""
92
+ try:
93
+ session = ctx.get_session()
94
+ data = wf_mod.update_process(
95
+ session, process_id, name=name, explain=desc, icon_color=icon_color,
96
+ )
97
+ ctx.output(data, lambda d: click.echo("Workflow updated."))
98
+ except Exception as e:
99
+ ctx.handle_error(e)
100
+
101
+
102
+ @workflow.command("delete")
103
+ @click.argument("process_id")
104
+ @click.option("--yes", "-y", is_flag=True, help="Skip confirmation")
105
+ @pass_context
106
+ def workflow_delete(ctx, process_id, yes):
107
+ """Delete a workflow process."""
108
+ try:
109
+ if not yes:
110
+ click.confirm(f"Delete workflow {process_id}?", abort=True)
111
+ session = ctx.get_session()
112
+ data = wf_mod.delete_process(session, process_id)
113
+ ctx.output(data, lambda d: click.echo("Workflow deleted."))
114
+ except Exception as e:
115
+ ctx.handle_error(e)
116
+
117
+
118
+ @workflow.command("copy")
119
+ @click.argument("process_id")
120
+ @click.option("--name", "-n", required=True, help="Name for the copy")
121
+ @click.option("--sub-process", is_flag=True, help="Include sub-processes")
122
+ @pass_context
123
+ def workflow_copy(ctx, process_id, name, sub_process):
124
+ """Copy/clone a workflow process."""
125
+ try:
126
+ session = ctx.get_session()
127
+ data = wf_mod.copy_process(session, process_id, name, sub_process)
128
+ ctx.output(data, lambda d: click.echo(f"Copied: {d}"))
129
+ except Exception as e:
130
+ ctx.handle_error(e)
131
+
132
+
133
+ @workflow.command("move")
134
+ @click.argument("process_id")
135
+ @click.argument("target_app_id")
136
+ @pass_context
137
+ def workflow_move(ctx, process_id, target_app_id):
138
+ """Move workflow to another application."""
139
+ try:
140
+ session = ctx.get_session()
141
+ data = wf_mod.move_process(session, process_id, target_app_id)
142
+ ctx.output(data, lambda d: click.echo("Workflow moved."))
143
+ except Exception as e:
144
+ ctx.handle_error(e)
145
+
146
+
147
+ @workflow.command("publish")
148
+ @click.argument("process_id")
149
+ @click.option("--disable", is_flag=True, help="Disable instead of publish")
150
+ @pass_context
151
+ def workflow_publish(ctx, process_id, disable):
152
+ """Publish (enable) or disable a workflow."""
153
+ try:
154
+ session = ctx.get_session()
155
+ data = wf_mod.publish(session, process_id, is_publish=not disable)
156
+ action = "Disabled" if disable else "Published"
157
+ ctx.output(data, lambda d: click.echo(f"{action} workflow."))
158
+ except Exception as e:
159
+ ctx.handle_error(e)
160
+
161
+
162
+ @workflow.command("rollback")
163
+ @click.argument("process_id")
164
+ @click.option("--yes", "-y", is_flag=True, help="Skip confirmation")
165
+ @pass_context
166
+ def workflow_rollback(ctx, process_id, yes):
167
+ """Rollback to previous version."""
168
+ try:
169
+ if not yes:
170
+ click.confirm(f"Rollback workflow {process_id}?", abort=True)
171
+ session = ctx.get_session()
172
+ data = wf_mod.rollback_version(session, process_id)
173
+ ctx.output(data, lambda d: click.echo("Rolled back to previous version."))
174
+ except Exception as e:
175
+ ctx.handle_error(e)
176
+
177
+
178
+ @workflow.command("history")
179
+ @click.argument("process_id")
180
+ @click.option("--page-size", "-n", default=20, help="Items per page")
181
+ @click.option("--page", "-p", default=1, help="Page number")
182
+ @pass_context
183
+ def workflow_history(ctx, process_id, page_size, page):
184
+ """Get workflow version history."""
185
+ try:
186
+ session = ctx.get_session()
187
+ data = wf_mod.get_version_history(session, process_id, page, page_size)
188
+ ctx.output(data, lambda d: output_json(d))
189
+ except Exception as e:
190
+ ctx.handle_error(e)
191
+
192
+
193
+ @workflow.command("config-get")
194
+ @click.argument("process_id")
195
+ @pass_context
196
+ def workflow_config_get(ctx, process_id):
197
+ """Get workflow global configuration."""
198
+ try:
199
+ session = ctx.get_session()
200
+ data = wf_mod.get_process_config(session, process_id)
201
+ ctx.output(data, lambda d: output_json(d))
202
+ except Exception as e:
203
+ ctx.handle_error(e)
204
+
205
+
206
+ @workflow.command("config-set")
207
+ @click.argument("process_id")
208
+ @click.option("--config", "-c", required=True, help="JSON config string")
209
+ @pass_context
210
+ def workflow_config_set(ctx, process_id, config):
211
+ """Save workflow global configuration (JSON string)."""
212
+ try:
213
+ session = ctx.get_session()
214
+ config_dict = json.loads(config)
215
+ data = wf_mod.save_process_config(session, process_id, config_dict)
216
+ ctx.output(data, lambda d: click.echo("Config saved."))
217
+ except json.JSONDecodeError as e:
218
+ ctx.handle_error(click.UsageError(f"Invalid JSON: {e}"))
219
+ except Exception as e:
220
+ ctx.handle_error(e)
221
+
222
+
223
+ @workflow.command("trigger")
224
+ @click.argument("process_id")
225
+ @click.option("--source-id", "-s", default="", help="Source record ID")
226
+ @pass_context
227
+ def workflow_trigger(ctx, process_id, source_id):
228
+ """Trigger/start a workflow by process ID."""
229
+ try:
230
+ session = ctx.get_session()
231
+ data = wf_mod.start_process_by_id(session, process_id, source_id)
232
+ ctx.output(data, lambda d: click.echo(f"Triggered: {d}"))
233
+ except Exception as e:
234
+ ctx.handle_error(e)
235
+
236
+
237
+ @workflow.command("trigger-pbp")
238
+ @click.argument("process_id")
239
+ @click.option("--app-id", "-a", required=True, help="Application ID")
240
+ @click.option("--trigger-id", default="", help="Trigger ID")
241
+ @click.option("--title", default="", help="Instance title")
242
+ @pass_context
243
+ def workflow_trigger_pbp(ctx, process_id, app_id, trigger_id, title):
244
+ """Trigger a PBP (Packaged Business Process) workflow."""
245
+ try:
246
+ session = ctx.get_session()
247
+ data = wf_mod.start_process_by_pbp(
248
+ session, process_id, app_id, trigger_id, title,
249
+ )
250
+ ctx.output(data, lambda d: click.echo(f"PBP triggered: {d}"))
251
+ except Exception as e:
252
+ ctx.handle_error(e)
253
+
254
+
255
+ @workflow.command("groups")
256
+ @click.argument("app_id", default="")
257
+ @pass_context
258
+ def workflow_groups(ctx, app_id):
259
+ """List workflow groups."""
260
+ try:
261
+ session = ctx.get_session()
262
+ aid = app_id or session.default_app_id
263
+ if not aid:
264
+ raise click.UsageError("App ID required.")
265
+ data = wf_mod.get_group_list(session, aid)
266
+ ctx.output(
267
+ data,
268
+ lambda d: output_table(d, ["id", "name"], ["Group ID", "Name"]),
269
+ )
270
+ except Exception as e:
271
+ ctx.handle_error(e)
272
+
273
+
274
+ @workflow.command("stats")
275
+ @click.option("--company-id", "-c", required=True, help="Organization ID")
276
+ @pass_context
277
+ def workflow_stats(ctx, company_id):
278
+ """Get workflow usage statistics."""
279
+ try:
280
+ session = ctx.get_session()
281
+ data = wf_mod.get_process_use_count(session, company_id)
282
+ ctx.output(data, lambda d: output_kv(d))
283
+ except Exception as e:
284
+ ctx.handle_error(e)