hap-cli 0.6.10__tar.gz → 0.7.0__tar.gz
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-0.6.10 → hap_cli-0.7.0}/PKG-INFO +13 -5
- {hap_cli-0.6.10/hap_cli → hap_cli-0.7.0}/README.md +12 -4
- hap_cli-0.7.0/app_live_tests/__init__.py +11 -0
- hap_cli-0.7.0/app_live_tests/__main__.py +32 -0
- hap_cli-0.7.0/app_live_tests/config.py +20 -0
- hap_cli-0.7.0/app_live_tests/harness.py +73 -0
- hap_cli-0.7.0/app_live_tests/smoke.py +450 -0
- hap_cli-0.7.0/app_live_tests/state.py +91 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0/hap_cli}/README.md +12 -4
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/README_CN.md +12 -4
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/__init__.py +1 -1
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/commands/auth_cmd.py +9 -4
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/commands/chatbot_cmd.py +36 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/commands/node_cmd.py +81 -123
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/commands/role_cmd.py +42 -0
- hap_cli-0.7.0/hap_cli/commands/upload_cmd.py +54 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/commands/v3_registry.py +1 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/commands/worksheet_cmd.py +84 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/app.py +24 -5
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/auth.py +289 -32
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/chatbot.py +34 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/flow_node.py +11 -327
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/icon_index.py +169 -137
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/record.py +4 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/role.py +34 -5
- hap_cli-0.7.0/hap_cli/core/role_perm_builder.py +175 -0
- hap_cli-0.7.0/hap_cli/core/upload.py +245 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/view_spec_adapter.py +64 -1
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/workflow.py +29 -1
- hap_cli-0.7.0/hap_cli/core/workflow_node_dsl.py +1699 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/worksheet.py +75 -4
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/hap_cli.py +2 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/tests/test_core.py +994 -343
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/tests/test_full_e2e.py +1 -1
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/tests/test_global_meta.py +2 -2
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/tests/test_integration_destructive.py +63 -0
- hap_cli-0.7.0/hap_cli/tests/test_worksheet_crud_cli.py +79 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli.egg-info/PKG-INFO +13 -5
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli.egg-info/SOURCES.txt +38 -0
- hap_cli-0.7.0/hap_cli.egg-info/top_level.txt +3 -0
- hap_cli-0.7.0/live_tests/__init__.py +16 -0
- hap_cli-0.7.0/live_tests/__main__.py +39 -0
- hap_cli-0.7.0/live_tests/_wftest.py +72 -0
- hap_cli-0.7.0/live_tests/charts.py +454 -0
- hap_cli-0.7.0/live_tests/cleanup.py +67 -0
- hap_cli-0.7.0/live_tests/compiler.py +129 -0
- hap_cli-0.7.0/live_tests/config.py +33 -0
- hap_cli-0.7.0/live_tests/errors.py +51 -0
- hap_cli-0.7.0/live_tests/executor.py +152 -0
- hap_cli-0.7.0/live_tests/fields.py +430 -0
- hap_cli-0.7.0/live_tests/hap.py +147 -0
- hap_cli-0.7.0/live_tests/recording/__init__.py +4 -0
- hap_cli-0.7.0/live_tests/recording/console.py +59 -0
- hap_cli-0.7.0/live_tests/recording/jsonl.py +41 -0
- hap_cli-0.7.0/live_tests/recording/mirror.py +45 -0
- hap_cli-0.7.0/live_tests/recording/report.py +127 -0
- hap_cli-0.7.0/live_tests/schema.py +223 -0
- hap_cli-0.7.0/live_tests/seed/__init__.py +21 -0
- hap_cli-0.7.0/live_tests/seed/cli.py +81 -0
- hap_cli-0.7.0/live_tests/seed/executor.py +264 -0
- hap_cli-0.7.0/live_tests/seed/template.py +154 -0
- hap_cli-0.7.0/live_tests/selftest.py +272 -0
- hap_cli-0.7.0/live_tests/smoke.py +123 -0
- hap_cli-0.7.0/live_tests/step.py +86 -0
- hap_cli-0.7.0/live_tests/steps.py +1125 -0
- hap_cli-0.7.0/live_tests/store.py +332 -0
- hap_cli-0.7.0/live_tests/workflow_dsl.py +456 -0
- hap_cli-0.6.10/hap_cli.egg-info/top_level.txt +0 -1
- {hap_cli-0.6.10 → hap_cli-0.7.0}/MANIFEST.in +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/commands/__init__.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/commands/app_cmd.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/commands/calendar_cmd.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/commands/chart_cmd.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/commands/chat_cmd.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/commands/config_cmd.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/commands/contact_cmd.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/commands/department_cmd.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/commands/group_cmd.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/commands/icon_cmd.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/commands/instance_cmd.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/commands/optionset_cmd.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/commands/page_cmd.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/commands/post_cmd.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/commands/record_cmd.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/commands/region_cmd.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/commands/workflow_cmd.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/context.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/__init__.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/action_spec_adapter.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/calendar_mod.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/chart.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/chat.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/contact.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/control_type_codes.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/department.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/field_normalizer.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/field_spec_adapter.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/filter_translator.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/global_meta.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/group.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/instance.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/logger.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/optionset.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/page.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/post.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/response_crypto.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/session.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/token_crypto.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/v3/__init__.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/v3/dispatcher.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/v3/render.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/v3/schema.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/core/worksheet_templates.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/i18n.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/locale/__init__.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/locale/messages.json +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/locale/messages.schema.json +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/tests/__init__.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/tests/conftest.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/tests/test_auth_prerelease.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/tests/test_chart.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/tests/test_config_cmd.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/tests/test_i18n.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/tests/test_integration.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/tests/test_integration_approval.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/tests/test_integration_calendar.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/tests/test_integration_misc.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/tests/test_integration_post.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/tests/test_integration_social.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/tests/test_integration_v3.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/tests/test_integration_workflow.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/tests/test_integration_worksheet_extra.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/tests/test_org_id_cli.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/tests/test_org_id_docs.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/tests/test_parameter_conventions.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/tests/test_parameter_mapping_registry.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/tests/test_v3_api_schema_loader.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/tests/test_v3_dispatcher.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/tests/test_v3_registry_coverage.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/tests/test_v3_session.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/tests/test_v3_yaml_translation.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/utils/__init__.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/utils/formatting.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/utils/options.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli/utils/parameter_mapping.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli.egg-info/dependency_links.txt +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli.egg-info/entry_points.txt +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/hap_cli.egg-info/requires.txt +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/setup.cfg +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/setup.py +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/sources/v3-api-schema/INDEX.json +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/sources/v3-api-schema/add_member_to_role.yaml +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/sources/v3-api-schema/batch_delete_records.yaml +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/sources/v3-api-schema/create_optionset.yaml +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/sources/v3-api-schema/create_role.yaml +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/sources/v3-api-schema/delete_optionset.yaml +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/sources/v3-api-schema/delete_record.yaml +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/sources/v3-api-schema/delete_role.yaml +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/sources/v3-api-schema/delete_worksheet.yaml +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/sources/v3-api-schema/get_app_info.yaml +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/sources/v3-api-schema/get_app_knowledge_list.yaml +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/sources/v3-api-schema/get_app_worksheets_list.yaml +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/sources/v3-api-schema/get_optionset_list.yaml +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/sources/v3-api-schema/get_record_details.yaml +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/sources/v3-api-schema/get_record_discussions.yaml +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/sources/v3-api-schema/get_record_list.yaml +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/sources/v3-api-schema/get_record_logs.yaml +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/sources/v3-api-schema/get_record_pivot_data.yaml +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/sources/v3-api-schema/get_record_relations.yaml +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/sources/v3-api-schema/get_record_share_link.yaml +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/sources/v3-api-schema/get_regions.yaml +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/sources/v3-api-schema/get_role_details.yaml +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/sources/v3-api-schema/get_role_list.yaml +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/sources/v3-api-schema/knowledge_search.yaml +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/sources/v3-api-schema/leave_all_roles.yaml +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/sources/v3-api-schema/remove_member_from_role.yaml +0 -0
- {hap_cli-0.6.10 → hap_cli-0.7.0}/sources/v3-api-schema/update_optionset.yaml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hap-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: CLI harness for MingDAO HAP - Enterprise no-code platform
|
|
5
5
|
Author: hap-cli
|
|
6
6
|
License: Apache-2.0
|
|
@@ -71,7 +71,7 @@ hap auth logout # clear the saved token
|
|
|
71
71
|
|
|
72
72
|
```bash
|
|
73
73
|
hap auth list-my-orgs # current org marked with *
|
|
74
|
-
hap auth
|
|
74
|
+
hap auth set-current-org ORG_ID # switch the saved current org
|
|
75
75
|
hap app list # uses the saved current org
|
|
76
76
|
hap app list --org-id ORG_ID # explicit override
|
|
77
77
|
|
|
@@ -80,7 +80,7 @@ hap app select APP_ID
|
|
|
80
80
|
hap app unselect # clear it
|
|
81
81
|
```
|
|
82
82
|
|
|
83
|
-
`hap auth
|
|
83
|
+
`hap auth set-current-org` only changes the default organization. The default app
|
|
84
84
|
is managed independently with `hap app select` / `hap app unselect`.
|
|
85
85
|
|
|
86
86
|
### 3. Explore worksheets and records
|
|
@@ -117,7 +117,7 @@ discover every subcommand.
|
|
|
117
117
|
| `auth logout` | Clear the saved auth token |
|
|
118
118
|
| `auth whoami` | Show current user and current organization |
|
|
119
119
|
| `auth list-my-orgs` | List every org for the current account (current marked `*`) |
|
|
120
|
-
| `auth
|
|
120
|
+
| `auth set-current-org ORG_ID` | Switch the saved current organization |
|
|
121
121
|
|
|
122
122
|
### app — application management
|
|
123
123
|
|
|
@@ -264,6 +264,14 @@ discover every subcommand.
|
|
|
264
264
|
| `icon search` | Search icons by Chinese/English keyword (OR across terms, more matches rank higher); no keyword lists all |
|
|
265
265
|
| `icon list` | List every icon with its keywords |
|
|
266
266
|
|
|
267
|
+
### upload — file upload
|
|
268
|
+
|
|
269
|
+
| Command | Description |
|
|
270
|
+
|---|---|
|
|
271
|
+
| `upload [SOURCES...]` | Upload local paths or http(s) URLs to the file store; prints neutral uploaded-file descriptors (fileID/key/url/serverName/filePath/fileName/fileExt/originalFileName/fileSize) |
|
|
272
|
+
|
|
273
|
+
> A cross-feature capability — the same descriptors can be attached to a worksheet Attachment field, a chat message, a post, a calendar event, or a comment. Use `--files '[{"name":"cover.png","url":"https://..."}]'` to set display names; `--worksheet-id` / `--app-id` refine upload-token routing.
|
|
274
|
+
|
|
267
275
|
### config — local CLI settings
|
|
268
276
|
|
|
269
277
|
| Command | Description |
|
|
@@ -291,7 +299,7 @@ Every command that needs an `--app-id` resolves it in this order:
|
|
|
291
299
|
2. The default app saved by `hap app select`;
|
|
292
300
|
3. Otherwise the command exits with an error suggesting `hap app select APP_ID`.
|
|
293
301
|
|
|
294
|
-
`hap auth
|
|
302
|
+
`hap auth set-current-org` changes the default *organization* only — it does not
|
|
295
303
|
touch the default app.
|
|
296
304
|
|
|
297
305
|
## REPL mode
|
|
@@ -42,7 +42,7 @@ hap auth logout # clear the saved token
|
|
|
42
42
|
|
|
43
43
|
```bash
|
|
44
44
|
hap auth list-my-orgs # current org marked with *
|
|
45
|
-
hap auth
|
|
45
|
+
hap auth set-current-org ORG_ID # switch the saved current org
|
|
46
46
|
hap app list # uses the saved current org
|
|
47
47
|
hap app list --org-id ORG_ID # explicit override
|
|
48
48
|
|
|
@@ -51,7 +51,7 @@ hap app select APP_ID
|
|
|
51
51
|
hap app unselect # clear it
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
`hap auth
|
|
54
|
+
`hap auth set-current-org` only changes the default organization. The default app
|
|
55
55
|
is managed independently with `hap app select` / `hap app unselect`.
|
|
56
56
|
|
|
57
57
|
### 3. Explore worksheets and records
|
|
@@ -88,7 +88,7 @@ discover every subcommand.
|
|
|
88
88
|
| `auth logout` | Clear the saved auth token |
|
|
89
89
|
| `auth whoami` | Show current user and current organization |
|
|
90
90
|
| `auth list-my-orgs` | List every org for the current account (current marked `*`) |
|
|
91
|
-
| `auth
|
|
91
|
+
| `auth set-current-org ORG_ID` | Switch the saved current organization |
|
|
92
92
|
|
|
93
93
|
### app — application management
|
|
94
94
|
|
|
@@ -235,6 +235,14 @@ discover every subcommand.
|
|
|
235
235
|
| `icon search` | Search icons by Chinese/English keyword (OR across terms, more matches rank higher); no keyword lists all |
|
|
236
236
|
| `icon list` | List every icon with its keywords |
|
|
237
237
|
|
|
238
|
+
### upload — file upload
|
|
239
|
+
|
|
240
|
+
| Command | Description |
|
|
241
|
+
|---|---|
|
|
242
|
+
| `upload [SOURCES...]` | Upload local paths or http(s) URLs to the file store; prints neutral uploaded-file descriptors (fileID/key/url/serverName/filePath/fileName/fileExt/originalFileName/fileSize) |
|
|
243
|
+
|
|
244
|
+
> A cross-feature capability — the same descriptors can be attached to a worksheet Attachment field, a chat message, a post, a calendar event, or a comment. Use `--files '[{"name":"cover.png","url":"https://..."}]'` to set display names; `--worksheet-id` / `--app-id` refine upload-token routing.
|
|
245
|
+
|
|
238
246
|
### config — local CLI settings
|
|
239
247
|
|
|
240
248
|
| Command | Description |
|
|
@@ -262,7 +270,7 @@ Every command that needs an `--app-id` resolves it in this order:
|
|
|
262
270
|
2. The default app saved by `hap app select`;
|
|
263
271
|
3. Otherwise the command exits with an error suggesting `hap app select APP_ID`.
|
|
264
272
|
|
|
265
|
-
`hap auth
|
|
273
|
+
`hap auth set-current-org` changes the default *organization* only — it does not
|
|
266
274
|
touch the default app.
|
|
267
275
|
|
|
268
276
|
## REPL mode
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""Repeatable live smoke tests for the hap-app-editor skill.
|
|
2
|
+
|
|
3
|
+
This is a top-level, stdlib-only package (no ``test_*.py`` files, so the
|
|
4
|
+
default pytest run never collects it — mirror of ``live_tests/``). It
|
|
5
|
+
drives the *real* editor entry point (``python3 -m scripts apply`` inside
|
|
6
|
+
the skill) plus the ``hap`` binary for setup/assertions, against a
|
|
7
|
+
persistent test app that it creates on first run and reuses thereafter.
|
|
8
|
+
|
|
9
|
+
python3 -m app_live_tests smoke # run all scenarios
|
|
10
|
+
python3 -m app_live_tests cleanup # delete the persistent app
|
|
11
|
+
"""
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""``python -m app_live_tests <smoke|cleanup> ...`` dispatch."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import sys
|
|
5
|
+
|
|
6
|
+
_USAGE = (
|
|
7
|
+
"usage: python -m app_live_tests <command>\n"
|
|
8
|
+
" smoke [--case worksheet|field|view] run live scenarios on the persistent app\n"
|
|
9
|
+
" cleanup delete the persistent test app\n"
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def main(argv: list[str] | None = None) -> int:
|
|
14
|
+
argv = list(sys.argv[1:] if argv is None else argv)
|
|
15
|
+
if not argv or argv[0] in ("-h", "--help"):
|
|
16
|
+
print(_USAGE)
|
|
17
|
+
return 0 if argv else 1
|
|
18
|
+
cmd, rest = argv[0], argv[1:]
|
|
19
|
+
if cmd == "smoke":
|
|
20
|
+
from app_live_tests.smoke import main as run
|
|
21
|
+
return run(rest)
|
|
22
|
+
if cmd == "cleanup":
|
|
23
|
+
from app_live_tests import state
|
|
24
|
+
app_id = state.delete_app()
|
|
25
|
+
print(f"deleted {app_id}" if app_id else "no persistent app to delete")
|
|
26
|
+
return 0
|
|
27
|
+
print(f"unknown command: {cmd}\n{_USAGE}", file=sys.stderr)
|
|
28
|
+
return 1
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
if __name__ == "__main__":
|
|
32
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""Paths and binary config for the app_live_tests harness."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
# The installed CLI (PATH lookup by default; override with HAP_BIN).
|
|
8
|
+
HAP_BIN = os.environ.get("HAP_BIN", "hap")
|
|
9
|
+
|
|
10
|
+
# Python used to invoke the editor skill (defaults to the running one).
|
|
11
|
+
PYTHON_BIN = os.environ.get("HAP_EDITOR_PYTHON", "") # "" -> sys.executable
|
|
12
|
+
|
|
13
|
+
_PKG_DIR = Path(__file__).resolve().parent
|
|
14
|
+
REPO_ROOT = _PKG_DIR.parent
|
|
15
|
+
SKILL_DIR = REPO_ROOT / "skills" / "hap-app-editor"
|
|
16
|
+
|
|
17
|
+
STATE_DIR = _PKG_DIR / "state"
|
|
18
|
+
STATE_FILE = STATE_DIR / "current_app.json"
|
|
19
|
+
|
|
20
|
+
TIMEOUT = int(os.environ.get("HAP_EDITOR_TIMEOUT", "120"))
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""Subprocess helpers: drive the ``hap`` binary and the editor skill.
|
|
2
|
+
|
|
3
|
+
``hap(...)`` runs the CLI in --json mode and returns the parsed payload.
|
|
4
|
+
``editor(...)`` runs ``python3 -m scripts <args>`` inside the skill
|
|
5
|
+
directory — the exact entry point a user invokes — and returns
|
|
6
|
+
(returncode, stdout, stderr).
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import json
|
|
11
|
+
import subprocess
|
|
12
|
+
import sys
|
|
13
|
+
import tempfile
|
|
14
|
+
import time
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
from typing import Any
|
|
17
|
+
|
|
18
|
+
from app_live_tests import config
|
|
19
|
+
|
|
20
|
+
_TRANSIENT = ("SSLError", "SSLEOFError", "UNEXPECTED_EOF", "Max retries",
|
|
21
|
+
"Connection aborted", "timed out", "RemoteDisconnected")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def hap(args: list[str], *, check: bool = True) -> Any:
|
|
25
|
+
"""Run ``hap --json <args>``; return parsed JSON (unwrapped if enveloped).
|
|
26
|
+
|
|
27
|
+
Retries a few times on transient network failures.
|
|
28
|
+
"""
|
|
29
|
+
argv = [config.HAP_BIN, "--json", *args]
|
|
30
|
+
for attempt in range(1, 4):
|
|
31
|
+
proc = subprocess.run(argv, capture_output=True, text=True,
|
|
32
|
+
timeout=config.TIMEOUT)
|
|
33
|
+
blob = f"{proc.stdout}\n{proc.stderr}"
|
|
34
|
+
if proc.returncode == 0 or not any(m in blob for m in _TRANSIENT):
|
|
35
|
+
break
|
|
36
|
+
if attempt < 3:
|
|
37
|
+
time.sleep(1.5 * attempt)
|
|
38
|
+
if check and proc.returncode != 0:
|
|
39
|
+
raise RuntimeError(f"hap {' '.join(args)} failed: "
|
|
40
|
+
f"{proc.stderr.strip() or proc.stdout.strip()}")
|
|
41
|
+
text = proc.stdout.strip()
|
|
42
|
+
if not text:
|
|
43
|
+
return {}
|
|
44
|
+
try:
|
|
45
|
+
data = json.loads(text)
|
|
46
|
+
except json.JSONDecodeError:
|
|
47
|
+
return {"_raw": text}
|
|
48
|
+
if isinstance(data, dict) and "data" in data and set(data.keys()) <= {
|
|
49
|
+
"data", "state", "exception", "success", "error_code", "code",
|
|
50
|
+
}:
|
|
51
|
+
return data["data"]
|
|
52
|
+
return data
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def editor(args: list[str]) -> tuple[int, str, str]:
|
|
56
|
+
"""Run the editor skill (``python -m scripts <args>``) in the skill dir."""
|
|
57
|
+
py = config.PYTHON_BIN or sys.executable
|
|
58
|
+
argv = [py, "-m", "scripts", *args]
|
|
59
|
+
proc = subprocess.run(argv, capture_output=True, text=True,
|
|
60
|
+
cwd=str(config.SKILL_DIR), timeout=config.TIMEOUT)
|
|
61
|
+
return proc.returncode, proc.stdout, proc.stderr
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def editor_apply(spec: dict) -> tuple[int, str, str]:
|
|
65
|
+
"""Write a spec to a temp file and ``editor apply`` it."""
|
|
66
|
+
with tempfile.NamedTemporaryFile(
|
|
67
|
+
"w", suffix=".edit.json", delete=False, encoding="utf-8") as fh:
|
|
68
|
+
json.dump(spec, fh, ensure_ascii=False)
|
|
69
|
+
path = fh.name
|
|
70
|
+
try:
|
|
71
|
+
return editor(["apply", path])
|
|
72
|
+
finally:
|
|
73
|
+
Path(path).unlink(missing_ok=True)
|