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
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
"""Worksheet management module for MingDAO HAP."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Optional
|
|
4
|
+
|
|
5
|
+
from hap_cli.core.session import Session
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def get_worksheet_info(
|
|
9
|
+
session: Session,
|
|
10
|
+
worksheet_id: str,
|
|
11
|
+
app_id: str = "",
|
|
12
|
+
get_template: bool = False,
|
|
13
|
+
get_views: bool = False,
|
|
14
|
+
) -> dict[str, Any]:
|
|
15
|
+
"""Get worksheet information.
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
session: Active session
|
|
19
|
+
worksheet_id: Worksheet ID
|
|
20
|
+
app_id: Optional application ID
|
|
21
|
+
get_template: Include template controls
|
|
22
|
+
get_views: Include views
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
Worksheet info dict
|
|
26
|
+
"""
|
|
27
|
+
data = {
|
|
28
|
+
"worksheetId": worksheet_id,
|
|
29
|
+
"getTemplate": get_template,
|
|
30
|
+
"getViews": get_views,
|
|
31
|
+
}
|
|
32
|
+
if app_id:
|
|
33
|
+
data["appId"] = app_id
|
|
34
|
+
return session.api_call("Worksheet", "GetWorksheetInfo", data)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def get_worksheet_controls(
|
|
38
|
+
session: Session,
|
|
39
|
+
worksheet_id: str,
|
|
40
|
+
app_id: str = "",
|
|
41
|
+
) -> list[dict[str, Any]]:
|
|
42
|
+
"""Get worksheet fields/controls with full metadata (type, options, etc.).
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
session: Active session
|
|
46
|
+
worksheet_id: Worksheet ID
|
|
47
|
+
app_id: Optional application ID
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
List of control/field definitions
|
|
51
|
+
"""
|
|
52
|
+
data = {
|
|
53
|
+
"worksheetId": worksheet_id,
|
|
54
|
+
"getRelationSearch": True,
|
|
55
|
+
"resultType": 3, # Return full control metadata
|
|
56
|
+
}
|
|
57
|
+
if app_id:
|
|
58
|
+
data["appId"] = app_id
|
|
59
|
+
result = session.api_call("Worksheet", "GetWorksheetControls", data)
|
|
60
|
+
if isinstance(result, list):
|
|
61
|
+
return result
|
|
62
|
+
# Response is double-nested: {code, data: {sourceId, controls: [...]}}
|
|
63
|
+
if isinstance(result, dict):
|
|
64
|
+
inner = result.get("data")
|
|
65
|
+
if isinstance(inner, dict):
|
|
66
|
+
return inner.get("controls", [])
|
|
67
|
+
if isinstance(inner, list):
|
|
68
|
+
return inner
|
|
69
|
+
return result.get("controls", [])
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def get_worksheet_views(
|
|
73
|
+
session: Session,
|
|
74
|
+
worksheet_id: str,
|
|
75
|
+
app_id: str = "",
|
|
76
|
+
) -> list[dict[str, Any]]:
|
|
77
|
+
"""Get worksheet views.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
session: Active session
|
|
81
|
+
worksheet_id: Worksheet ID
|
|
82
|
+
app_id: Optional application ID
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
List of view definitions
|
|
86
|
+
"""
|
|
87
|
+
data = {"worksheetId": worksheet_id}
|
|
88
|
+
if app_id:
|
|
89
|
+
data["appId"] = app_id
|
|
90
|
+
result = session.api_call("Worksheet", "GetWorksheetViews", data)
|
|
91
|
+
if isinstance(result, list):
|
|
92
|
+
return result
|
|
93
|
+
return result.get("views", [])
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
# ── Field type constants ─────────────────────────────────────────────────
|
|
97
|
+
|
|
98
|
+
FIELD_TYPES = {
|
|
99
|
+
"TEXT": 2,
|
|
100
|
+
"MOBILE_PHONE": 3,
|
|
101
|
+
"TELEPHONE": 4,
|
|
102
|
+
"EMAIL": 5,
|
|
103
|
+
"NUMBER": 6,
|
|
104
|
+
"CRED": 7,
|
|
105
|
+
"MONEY": 8,
|
|
106
|
+
"FLAT_MENU": 9,
|
|
107
|
+
"MULTI_SELECT": 10,
|
|
108
|
+
"DROP_DOWN": 11,
|
|
109
|
+
"ATTACHMENT": 14,
|
|
110
|
+
"DATE": 15,
|
|
111
|
+
"DATE_TIME": 16,
|
|
112
|
+
"AREA_PROVINCE": 19,
|
|
113
|
+
"RELATION": 21,
|
|
114
|
+
"SPLIT_LINE": 22,
|
|
115
|
+
"AREA_CITY": 23,
|
|
116
|
+
"AREA_COUNTY": 24,
|
|
117
|
+
"MONEY_CN": 25,
|
|
118
|
+
"USER_PICKER": 26,
|
|
119
|
+
"DEPARTMENT": 27,
|
|
120
|
+
"SCORE": 28,
|
|
121
|
+
"RELATE_SHEET": 29,
|
|
122
|
+
"SHEET_FIELD": 30,
|
|
123
|
+
"FORMULA_NUMBER": 31,
|
|
124
|
+
"CONCATENATE": 32,
|
|
125
|
+
"AUTO_ID": 33,
|
|
126
|
+
"SUB_LIST": 34,
|
|
127
|
+
"CASCADER": 35,
|
|
128
|
+
"SWITCH": 36,
|
|
129
|
+
"SUBTOTAL": 37,
|
|
130
|
+
"FORMULA_DATE": 38,
|
|
131
|
+
"LOCATION": 40,
|
|
132
|
+
"RICH_TEXT": 41,
|
|
133
|
+
"SIGNATURE": 42,
|
|
134
|
+
"OCR": 43,
|
|
135
|
+
"EMBED": 45,
|
|
136
|
+
"TIME": 46,
|
|
137
|
+
"BAR_CODE": 47,
|
|
138
|
+
"ORG_ROLE": 48,
|
|
139
|
+
"SEARCH_BTN": 49,
|
|
140
|
+
"SEARCH": 50,
|
|
141
|
+
"RELATION_SEARCH": 51,
|
|
142
|
+
"SECTION": 52,
|
|
143
|
+
"FORMULA_FUNC": 53,
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
# ── Worksheet CRUD ───────────────────────────────────────────────────────
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def create_worksheet(
|
|
151
|
+
session: Session,
|
|
152
|
+
app_id: str,
|
|
153
|
+
name: str,
|
|
154
|
+
project_id: str = "",
|
|
155
|
+
section_id: str = "",
|
|
156
|
+
) -> dict[str, Any]:
|
|
157
|
+
"""Create a new worksheet."""
|
|
158
|
+
data: dict[str, Any] = {"appId": app_id, "name": name}
|
|
159
|
+
if project_id:
|
|
160
|
+
data["projectId"] = project_id
|
|
161
|
+
if section_id:
|
|
162
|
+
data["appSectionId"] = section_id # API requires appSectionId
|
|
163
|
+
return session.api_call("AppManagement", "AddWorkSheet", data)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def copy_worksheet(
|
|
167
|
+
session: Session,
|
|
168
|
+
worksheet_id: str,
|
|
169
|
+
name: str,
|
|
170
|
+
app_id: str = "",
|
|
171
|
+
project_id: str = "",
|
|
172
|
+
copy_rows: bool = False,
|
|
173
|
+
) -> dict[str, Any]:
|
|
174
|
+
"""Copy a worksheet."""
|
|
175
|
+
data: dict[str, Any] = {"worksheetId": worksheet_id, "name": name}
|
|
176
|
+
if app_id:
|
|
177
|
+
data["appId"] = app_id
|
|
178
|
+
if project_id:
|
|
179
|
+
data["projectId"] = project_id
|
|
180
|
+
data["isCopyRows"] = copy_rows
|
|
181
|
+
return session.api_call("Worksheet", "CopyWorksheet", data)
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def update_worksheet(
|
|
185
|
+
session: Session,
|
|
186
|
+
worksheet_id: str,
|
|
187
|
+
alias: str = "",
|
|
188
|
+
desc: str = "",
|
|
189
|
+
app_id: str = "",
|
|
190
|
+
) -> dict[str, Any]:
|
|
191
|
+
"""Update worksheet alias and/or description."""
|
|
192
|
+
result = {}
|
|
193
|
+
if alias:
|
|
194
|
+
result = session.api_call(
|
|
195
|
+
"Worksheet", "UpdateWorksheetAlias",
|
|
196
|
+
{"worksheetId": worksheet_id, "alias": alias, "appId": app_id},
|
|
197
|
+
)
|
|
198
|
+
if desc:
|
|
199
|
+
result = session.api_call(
|
|
200
|
+
"Worksheet", "UpdateWorksheetDec",
|
|
201
|
+
{"worksheetId": worksheet_id, "dec": desc},
|
|
202
|
+
)
|
|
203
|
+
return result
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
# ── Field/Control management ─────────────────────────────────────────────
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def save_controls(
|
|
210
|
+
session: Session,
|
|
211
|
+
worksheet_id: str,
|
|
212
|
+
controls: list[dict[str, Any]],
|
|
213
|
+
) -> dict[str, Any]:
|
|
214
|
+
"""Save the complete controls list for a worksheet (add/update/delete via full replacement).
|
|
215
|
+
|
|
216
|
+
Workflow: call get_worksheet_controls() first to get the current list,
|
|
217
|
+
modify it as needed, then pass the full modified list here.
|
|
218
|
+
|
|
219
|
+
Args:
|
|
220
|
+
session: Active session
|
|
221
|
+
worksheet_id: Worksheet ID (used as sourceId)
|
|
222
|
+
controls: Complete list of control definitions (old + new + modified)
|
|
223
|
+
|
|
224
|
+
Returns:
|
|
225
|
+
API response dict
|
|
226
|
+
"""
|
|
227
|
+
return session.api_call(
|
|
228
|
+
"Worksheet", "SaveWorksheetControls",
|
|
229
|
+
{"version": 3, "sourceId": worksheet_id, "controls": controls},
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def add_controls(
|
|
234
|
+
session: Session,
|
|
235
|
+
worksheet_id: str,
|
|
236
|
+
controls: list[dict[str, Any]],
|
|
237
|
+
) -> dict[str, Any]:
|
|
238
|
+
"""Add new fields/controls to a worksheet (legacy endpoint)."""
|
|
239
|
+
return session.api_call(
|
|
240
|
+
"Worksheet", "AddWorksheetControls",
|
|
241
|
+
{"worksheetId": worksheet_id, "controls": controls},
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
# ── View management ──────────────────────────────────────────────────────
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def save_view(
|
|
249
|
+
session: Session,
|
|
250
|
+
worksheet_id: str,
|
|
251
|
+
name: str,
|
|
252
|
+
view_type: int = 0,
|
|
253
|
+
view_id: str = "",
|
|
254
|
+
config: Optional[dict] = None,
|
|
255
|
+
app_id: str = "",
|
|
256
|
+
) -> dict[str, Any]:
|
|
257
|
+
"""Create or update a worksheet view."""
|
|
258
|
+
data: dict[str, Any] = {
|
|
259
|
+
"worksheetId": worksheet_id,
|
|
260
|
+
"name": name,
|
|
261
|
+
"viewType": view_type,
|
|
262
|
+
}
|
|
263
|
+
if view_id:
|
|
264
|
+
data["viewId"] = view_id
|
|
265
|
+
if config:
|
|
266
|
+
data.update(config)
|
|
267
|
+
if app_id:
|
|
268
|
+
data["appId"] = app_id
|
|
269
|
+
return session.api_call("Worksheet", "SaveWorksheetView", data)
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def delete_view(
|
|
273
|
+
session: Session, worksheet_id: str, view_id: str, app_id: str = "",
|
|
274
|
+
) -> dict[str, Any]:
|
|
275
|
+
"""Delete a worksheet view."""
|
|
276
|
+
data: dict[str, Any] = {"worksheetId": worksheet_id, "viewId": view_id}
|
|
277
|
+
if app_id:
|
|
278
|
+
data["appId"] = app_id
|
|
279
|
+
return session.api_call("Worksheet", "DeleteWorksheetView", data)
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def copy_view(
|
|
283
|
+
session: Session, worksheet_id: str, view_id: str, name: str,
|
|
284
|
+
) -> dict[str, Any]:
|
|
285
|
+
"""Copy a worksheet view."""
|
|
286
|
+
return session.api_call(
|
|
287
|
+
"Worksheet", "CopyWorksheetView",
|
|
288
|
+
{"worksheetId": worksheet_id, "viewId": view_id, "viewName": name},
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def sort_views(
|
|
293
|
+
session: Session, worksheet_id: str, view_ids: list[str],
|
|
294
|
+
) -> dict[str, Any]:
|
|
295
|
+
"""Reorder worksheet views."""
|
|
296
|
+
return session.api_call(
|
|
297
|
+
"Worksheet", "SortWorksheetViews",
|
|
298
|
+
{"worksheetId": worksheet_id, "viewIds": view_ids},
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
# ── Business Rules ───────────────────────────────────────────────────────
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
def get_control_rules(
|
|
306
|
+
session: Session, worksheet_id: str, control_id: str = "",
|
|
307
|
+
) -> dict[str, Any]:
|
|
308
|
+
"""Get business rules for worksheet controls."""
|
|
309
|
+
data: dict[str, Any] = {"worksheetId": worksheet_id}
|
|
310
|
+
if control_id:
|
|
311
|
+
data["controlId"] = control_id
|
|
312
|
+
return session.api_call("Worksheet", "GetControlRules", data)
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
def save_control_rule(
|
|
316
|
+
session: Session,
|
|
317
|
+
worksheet_id: str,
|
|
318
|
+
rules: list[dict[str, Any]],
|
|
319
|
+
control_id: str = "",
|
|
320
|
+
) -> dict[str, Any]:
|
|
321
|
+
"""Save business rules for worksheet controls."""
|
|
322
|
+
data: dict[str, Any] = {"worksheetId": worksheet_id, "rules": rules}
|
|
323
|
+
if control_id:
|
|
324
|
+
data["controlId"] = control_id
|
|
325
|
+
return session.api_call("Worksheet", "SaveControlRule", data)
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
# ── Custom Buttons ───────────────────────────────────────────────────────
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
def get_buttons(
|
|
332
|
+
session: Session, worksheet_id: str,
|
|
333
|
+
) -> dict[str, Any]:
|
|
334
|
+
"""Get custom action buttons for a worksheet."""
|
|
335
|
+
return session.api_call(
|
|
336
|
+
"Worksheet", "GetWorksheetBtns", {"worksheetId": worksheet_id},
|
|
337
|
+
)
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
def save_button(
|
|
341
|
+
session: Session,
|
|
342
|
+
worksheet_id: str,
|
|
343
|
+
btn_data: dict[str, Any],
|
|
344
|
+
btn_id: str = "",
|
|
345
|
+
) -> dict[str, Any]:
|
|
346
|
+
"""Create or update a custom action button.
|
|
347
|
+
|
|
348
|
+
On creation, the API auto-creates a linked workflow.
|
|
349
|
+
Response 'data' field contains the triggerId (button's workflow trigger ID).
|
|
350
|
+
"""
|
|
351
|
+
data: dict[str, Any] = {"worksheetId": worksheet_id}
|
|
352
|
+
if btn_id:
|
|
353
|
+
data["btnId"] = btn_id
|
|
354
|
+
data.update(btn_data)
|
|
355
|
+
return session.api_call("Worksheet", "SaveWorksheetBtn", data)
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
def delete_button(
|
|
359
|
+
session: Session, worksheet_id: str, btn_id: str,
|
|
360
|
+
) -> dict[str, Any]:
|
|
361
|
+
"""Delete a custom action button."""
|
|
362
|
+
return session.api_call(
|
|
363
|
+
"Worksheet", "SaveWorksheetBtn",
|
|
364
|
+
{"worksheetId": worksheet_id, "btnId": btn_id, "isDelete": True},
|
|
365
|
+
)
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
# ── Feature Switches ────────────────────────────────────────────────────
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
def get_switches(
|
|
372
|
+
session: Session, worksheet_id: str,
|
|
373
|
+
) -> dict[str, Any]:
|
|
374
|
+
"""Get feature switches for a worksheet."""
|
|
375
|
+
return session.api_call(
|
|
376
|
+
"Worksheet", "GetSwitch", {"worksheetId": worksheet_id},
|
|
377
|
+
)
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
def edit_switch(
|
|
381
|
+
session: Session, worksheet_id: str, switch_id: int, value: bool,
|
|
382
|
+
) -> dict[str, Any]:
|
|
383
|
+
"""Edit a single feature switch."""
|
|
384
|
+
return session.api_call(
|
|
385
|
+
"Worksheet", "EditSwitch",
|
|
386
|
+
{"worksheetId": worksheet_id, "state": switch_id, "value": value},
|
|
387
|
+
)
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
# ── Logs ─────────────────────────────────────────────────────────────────
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
def get_worksheet_logs(
|
|
394
|
+
session: Session,
|
|
395
|
+
worksheet_id: str,
|
|
396
|
+
page_index: int = 1,
|
|
397
|
+
page_size: int = 50,
|
|
398
|
+
) -> dict[str, Any]:
|
|
399
|
+
"""Get worksheet operation logs."""
|
|
400
|
+
return session.api_call(
|
|
401
|
+
"Worksheet", "GetWorksheetOperationLogs",
|
|
402
|
+
{"worksheetId": worksheet_id, "pageIndex": page_index, "pageSize": page_size},
|
|
403
|
+
)
|
hap_cli/hap_cli.py
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"""Main CLI entry point for hap-cli harness.
|
|
2
|
+
|
|
3
|
+
Usage:
|
|
4
|
+
hap [--json] <command> [args...]
|
|
5
|
+
hap repl
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import cmd
|
|
9
|
+
import shlex
|
|
10
|
+
|
|
11
|
+
import click
|
|
12
|
+
|
|
13
|
+
from hap_cli.context import Context, pass_context
|
|
14
|
+
|
|
15
|
+
# Import command groups
|
|
16
|
+
from hap_cli.commands.config_cmd import config
|
|
17
|
+
from hap_cli.commands.app_cmd import app
|
|
18
|
+
from hap_cli.commands.worksheet_cmd import worksheet
|
|
19
|
+
from hap_cli.commands.record_cmd import record
|
|
20
|
+
from hap_cli.commands.workflow_cmd import workflow
|
|
21
|
+
from hap_cli.commands.node_cmd import node
|
|
22
|
+
from hap_cli.commands.instance_cmd import instance
|
|
23
|
+
from hap_cli.commands.role_cmd import role
|
|
24
|
+
from hap_cli.commands.optionset_cmd import optionset
|
|
25
|
+
from hap_cli.commands.page_cmd import page
|
|
26
|
+
from hap_cli.commands.contact_cmd import contact
|
|
27
|
+
from hap_cli.commands.department_cmd import department
|
|
28
|
+
from hap_cli.commands.post_cmd import post
|
|
29
|
+
from hap_cli.commands.calendar_cmd import calendar
|
|
30
|
+
from hap_cli.commands.chat_cmd import chat
|
|
31
|
+
from hap_cli.commands.group_cmd import group
|
|
32
|
+
from hap_cli.commands.ai_cmd import ai
|
|
33
|
+
from hap_cli.commands.plugin_cmd import plugin
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@click.group()
|
|
37
|
+
@click.option("--json", "json_mode", is_flag=True, help="Output in JSON format")
|
|
38
|
+
@click.pass_context
|
|
39
|
+
def cli(ctx, json_mode):
|
|
40
|
+
"""CLI harness for MingDAO HAP (hap) - Enterprise no-code platform."""
|
|
41
|
+
ctx.ensure_object(Context)
|
|
42
|
+
ctx.obj.json_mode = json_mode
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# Register command groups
|
|
46
|
+
cli.add_command(config)
|
|
47
|
+
cli.add_command(app)
|
|
48
|
+
cli.add_command(worksheet)
|
|
49
|
+
cli.add_command(record)
|
|
50
|
+
cli.add_command(workflow)
|
|
51
|
+
cli.add_command(node)
|
|
52
|
+
cli.add_command(instance)
|
|
53
|
+
cli.add_command(role)
|
|
54
|
+
cli.add_command(optionset)
|
|
55
|
+
cli.add_command(page)
|
|
56
|
+
cli.add_command(contact)
|
|
57
|
+
cli.add_command(department)
|
|
58
|
+
cli.add_command(post)
|
|
59
|
+
cli.add_command(calendar)
|
|
60
|
+
cli.add_command(chat)
|
|
61
|
+
cli.add_command(group)
|
|
62
|
+
cli.add_command(ai)
|
|
63
|
+
cli.add_command(plugin)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
# ── REPL ─────────────────────────────────────────────────────────────────
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class HapREPL(cmd.Cmd):
|
|
70
|
+
"""Interactive REPL for hap-cli."""
|
|
71
|
+
|
|
72
|
+
intro = "hap-cli REPL. Type 'help' for commands, 'quit' to exit."
|
|
73
|
+
prompt = "hap> "
|
|
74
|
+
|
|
75
|
+
def default(self, line):
|
|
76
|
+
"""Execute CLI commands."""
|
|
77
|
+
try:
|
|
78
|
+
args = shlex.split(line)
|
|
79
|
+
cli.main(args, standalone_mode=False)
|
|
80
|
+
except SystemExit:
|
|
81
|
+
pass
|
|
82
|
+
except Exception as e:
|
|
83
|
+
click.echo(f"Error: {e}", err=True)
|
|
84
|
+
|
|
85
|
+
def do_quit(self, _arg):
|
|
86
|
+
"""Exit the REPL."""
|
|
87
|
+
return True
|
|
88
|
+
|
|
89
|
+
do_exit = do_quit
|
|
90
|
+
do_EOF = do_quit
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@cli.command()
|
|
94
|
+
def repl():
|
|
95
|
+
"""Start interactive REPL mode."""
|
|
96
|
+
HapREPL().cmdloop()
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def main():
|
|
100
|
+
"""Entry point for the CLI."""
|
|
101
|
+
cli()
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
if __name__ == "__main__":
|
|
105
|
+
main()
|