hap-cli 0.6.10__tar.gz → 0.7.1__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.
Files changed (178) hide show
  1. {hap_cli-0.6.10 → hap_cli-0.7.1}/PKG-INFO +13 -5
  2. {hap_cli-0.6.10/hap_cli → hap_cli-0.7.1}/README.md +12 -4
  3. hap_cli-0.7.1/app_live_tests/__init__.py +11 -0
  4. hap_cli-0.7.1/app_live_tests/__main__.py +32 -0
  5. hap_cli-0.7.1/app_live_tests/config.py +20 -0
  6. hap_cli-0.7.1/app_live_tests/harness.py +73 -0
  7. hap_cli-0.7.1/app_live_tests/smoke.py +450 -0
  8. hap_cli-0.7.1/app_live_tests/state.py +91 -0
  9. {hap_cli-0.6.10 → hap_cli-0.7.1/hap_cli}/README.md +12 -4
  10. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/README_CN.md +12 -4
  11. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/__init__.py +1 -1
  12. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/commands/auth_cmd.py +9 -4
  13. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/commands/chatbot_cmd.py +36 -0
  14. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/commands/instance_cmd.py +10 -4
  15. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/commands/node_cmd.py +81 -123
  16. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/commands/role_cmd.py +42 -0
  17. hap_cli-0.7.1/hap_cli/commands/upload_cmd.py +54 -0
  18. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/commands/v3_registry.py +1 -0
  19. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/commands/worksheet_cmd.py +84 -0
  20. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/app.py +24 -5
  21. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/auth.py +289 -32
  22. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/chatbot.py +34 -0
  23. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/flow_node.py +11 -327
  24. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/icon_index.py +169 -137
  25. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/instance.py +45 -32
  26. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/record.py +4 -0
  27. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/role.py +34 -5
  28. hap_cli-0.7.1/hap_cli/core/role_perm_builder.py +175 -0
  29. hap_cli-0.7.1/hap_cli/core/upload.py +245 -0
  30. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/view_spec_adapter.py +64 -1
  31. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/workflow.py +29 -1
  32. hap_cli-0.7.1/hap_cli/core/workflow_node_dsl.py +1707 -0
  33. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/worksheet.py +75 -4
  34. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/hap_cli.py +2 -0
  35. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/tests/test_core.py +1087 -371
  36. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/tests/test_full_e2e.py +1 -1
  37. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/tests/test_global_meta.py +2 -2
  38. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/tests/test_integration_approval.py +83 -0
  39. hap_cli-0.7.1/hap_cli/tests/test_integration_approval_actions.py +237 -0
  40. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/tests/test_integration_destructive.py +63 -0
  41. hap_cli-0.7.1/hap_cli/tests/test_worksheet_crud_cli.py +79 -0
  42. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli.egg-info/PKG-INFO +13 -5
  43. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli.egg-info/SOURCES.txt +39 -0
  44. hap_cli-0.7.1/hap_cli.egg-info/top_level.txt +3 -0
  45. hap_cli-0.7.1/live_tests/__init__.py +16 -0
  46. hap_cli-0.7.1/live_tests/__main__.py +39 -0
  47. hap_cli-0.7.1/live_tests/_wftest.py +72 -0
  48. hap_cli-0.7.1/live_tests/charts.py +454 -0
  49. hap_cli-0.7.1/live_tests/cleanup.py +67 -0
  50. hap_cli-0.7.1/live_tests/compiler.py +129 -0
  51. hap_cli-0.7.1/live_tests/config.py +33 -0
  52. hap_cli-0.7.1/live_tests/errors.py +51 -0
  53. hap_cli-0.7.1/live_tests/executor.py +152 -0
  54. hap_cli-0.7.1/live_tests/fields.py +430 -0
  55. hap_cli-0.7.1/live_tests/hap.py +147 -0
  56. hap_cli-0.7.1/live_tests/recording/__init__.py +4 -0
  57. hap_cli-0.7.1/live_tests/recording/console.py +59 -0
  58. hap_cli-0.7.1/live_tests/recording/jsonl.py +41 -0
  59. hap_cli-0.7.1/live_tests/recording/mirror.py +45 -0
  60. hap_cli-0.7.1/live_tests/recording/report.py +127 -0
  61. hap_cli-0.7.1/live_tests/schema.py +223 -0
  62. hap_cli-0.7.1/live_tests/seed/__init__.py +21 -0
  63. hap_cli-0.7.1/live_tests/seed/cli.py +81 -0
  64. hap_cli-0.7.1/live_tests/seed/executor.py +264 -0
  65. hap_cli-0.7.1/live_tests/seed/template.py +154 -0
  66. hap_cli-0.7.1/live_tests/selftest.py +272 -0
  67. hap_cli-0.7.1/live_tests/smoke.py +123 -0
  68. hap_cli-0.7.1/live_tests/step.py +86 -0
  69. hap_cli-0.7.1/live_tests/steps.py +1125 -0
  70. hap_cli-0.7.1/live_tests/store.py +332 -0
  71. hap_cli-0.7.1/live_tests/workflow_dsl.py +456 -0
  72. hap_cli-0.6.10/hap_cli.egg-info/top_level.txt +0 -1
  73. {hap_cli-0.6.10 → hap_cli-0.7.1}/MANIFEST.in +0 -0
  74. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/commands/__init__.py +0 -0
  75. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/commands/app_cmd.py +0 -0
  76. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/commands/calendar_cmd.py +0 -0
  77. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/commands/chart_cmd.py +0 -0
  78. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/commands/chat_cmd.py +0 -0
  79. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/commands/config_cmd.py +0 -0
  80. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/commands/contact_cmd.py +0 -0
  81. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/commands/department_cmd.py +0 -0
  82. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/commands/group_cmd.py +0 -0
  83. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/commands/icon_cmd.py +0 -0
  84. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/commands/optionset_cmd.py +0 -0
  85. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/commands/page_cmd.py +0 -0
  86. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/commands/post_cmd.py +0 -0
  87. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/commands/record_cmd.py +0 -0
  88. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/commands/region_cmd.py +0 -0
  89. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/commands/workflow_cmd.py +0 -0
  90. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/context.py +0 -0
  91. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/__init__.py +0 -0
  92. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/action_spec_adapter.py +0 -0
  93. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/calendar_mod.py +0 -0
  94. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/chart.py +0 -0
  95. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/chat.py +0 -0
  96. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/contact.py +0 -0
  97. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/control_type_codes.py +0 -0
  98. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/department.py +0 -0
  99. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/field_normalizer.py +0 -0
  100. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/field_spec_adapter.py +0 -0
  101. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/filter_translator.py +0 -0
  102. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/global_meta.py +0 -0
  103. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/group.py +0 -0
  104. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/logger.py +0 -0
  105. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/optionset.py +0 -0
  106. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/page.py +0 -0
  107. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/post.py +0 -0
  108. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/response_crypto.py +0 -0
  109. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/session.py +0 -0
  110. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/token_crypto.py +0 -0
  111. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/v3/__init__.py +0 -0
  112. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/v3/dispatcher.py +0 -0
  113. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/v3/render.py +0 -0
  114. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/v3/schema.py +0 -0
  115. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/core/worksheet_templates.py +0 -0
  116. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/i18n.py +0 -0
  117. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/locale/__init__.py +0 -0
  118. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/locale/messages.json +0 -0
  119. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/locale/messages.schema.json +0 -0
  120. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/tests/__init__.py +0 -0
  121. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/tests/conftest.py +0 -0
  122. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/tests/test_auth_prerelease.py +0 -0
  123. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/tests/test_chart.py +0 -0
  124. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/tests/test_config_cmd.py +0 -0
  125. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/tests/test_i18n.py +0 -0
  126. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/tests/test_integration.py +0 -0
  127. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/tests/test_integration_calendar.py +0 -0
  128. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/tests/test_integration_misc.py +0 -0
  129. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/tests/test_integration_post.py +0 -0
  130. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/tests/test_integration_social.py +0 -0
  131. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/tests/test_integration_v3.py +0 -0
  132. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/tests/test_integration_workflow.py +0 -0
  133. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/tests/test_integration_worksheet_extra.py +0 -0
  134. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/tests/test_org_id_cli.py +0 -0
  135. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/tests/test_org_id_docs.py +0 -0
  136. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/tests/test_parameter_conventions.py +0 -0
  137. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/tests/test_parameter_mapping_registry.py +0 -0
  138. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/tests/test_v3_api_schema_loader.py +0 -0
  139. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/tests/test_v3_dispatcher.py +0 -0
  140. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/tests/test_v3_registry_coverage.py +0 -0
  141. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/tests/test_v3_session.py +0 -0
  142. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/tests/test_v3_yaml_translation.py +0 -0
  143. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/utils/__init__.py +0 -0
  144. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/utils/formatting.py +0 -0
  145. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/utils/options.py +0 -0
  146. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli/utils/parameter_mapping.py +0 -0
  147. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli.egg-info/dependency_links.txt +0 -0
  148. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli.egg-info/entry_points.txt +0 -0
  149. {hap_cli-0.6.10 → hap_cli-0.7.1}/hap_cli.egg-info/requires.txt +0 -0
  150. {hap_cli-0.6.10 → hap_cli-0.7.1}/setup.cfg +0 -0
  151. {hap_cli-0.6.10 → hap_cli-0.7.1}/setup.py +0 -0
  152. {hap_cli-0.6.10 → hap_cli-0.7.1}/sources/v3-api-schema/INDEX.json +0 -0
  153. {hap_cli-0.6.10 → hap_cli-0.7.1}/sources/v3-api-schema/add_member_to_role.yaml +0 -0
  154. {hap_cli-0.6.10 → hap_cli-0.7.1}/sources/v3-api-schema/batch_delete_records.yaml +0 -0
  155. {hap_cli-0.6.10 → hap_cli-0.7.1}/sources/v3-api-schema/create_optionset.yaml +0 -0
  156. {hap_cli-0.6.10 → hap_cli-0.7.1}/sources/v3-api-schema/create_role.yaml +0 -0
  157. {hap_cli-0.6.10 → hap_cli-0.7.1}/sources/v3-api-schema/delete_optionset.yaml +0 -0
  158. {hap_cli-0.6.10 → hap_cli-0.7.1}/sources/v3-api-schema/delete_record.yaml +0 -0
  159. {hap_cli-0.6.10 → hap_cli-0.7.1}/sources/v3-api-schema/delete_role.yaml +0 -0
  160. {hap_cli-0.6.10 → hap_cli-0.7.1}/sources/v3-api-schema/delete_worksheet.yaml +0 -0
  161. {hap_cli-0.6.10 → hap_cli-0.7.1}/sources/v3-api-schema/get_app_info.yaml +0 -0
  162. {hap_cli-0.6.10 → hap_cli-0.7.1}/sources/v3-api-schema/get_app_knowledge_list.yaml +0 -0
  163. {hap_cli-0.6.10 → hap_cli-0.7.1}/sources/v3-api-schema/get_app_worksheets_list.yaml +0 -0
  164. {hap_cli-0.6.10 → hap_cli-0.7.1}/sources/v3-api-schema/get_optionset_list.yaml +0 -0
  165. {hap_cli-0.6.10 → hap_cli-0.7.1}/sources/v3-api-schema/get_record_details.yaml +0 -0
  166. {hap_cli-0.6.10 → hap_cli-0.7.1}/sources/v3-api-schema/get_record_discussions.yaml +0 -0
  167. {hap_cli-0.6.10 → hap_cli-0.7.1}/sources/v3-api-schema/get_record_list.yaml +0 -0
  168. {hap_cli-0.6.10 → hap_cli-0.7.1}/sources/v3-api-schema/get_record_logs.yaml +0 -0
  169. {hap_cli-0.6.10 → hap_cli-0.7.1}/sources/v3-api-schema/get_record_pivot_data.yaml +0 -0
  170. {hap_cli-0.6.10 → hap_cli-0.7.1}/sources/v3-api-schema/get_record_relations.yaml +0 -0
  171. {hap_cli-0.6.10 → hap_cli-0.7.1}/sources/v3-api-schema/get_record_share_link.yaml +0 -0
  172. {hap_cli-0.6.10 → hap_cli-0.7.1}/sources/v3-api-schema/get_regions.yaml +0 -0
  173. {hap_cli-0.6.10 → hap_cli-0.7.1}/sources/v3-api-schema/get_role_details.yaml +0 -0
  174. {hap_cli-0.6.10 → hap_cli-0.7.1}/sources/v3-api-schema/get_role_list.yaml +0 -0
  175. {hap_cli-0.6.10 → hap_cli-0.7.1}/sources/v3-api-schema/knowledge_search.yaml +0 -0
  176. {hap_cli-0.6.10 → hap_cli-0.7.1}/sources/v3-api-schema/leave_all_roles.yaml +0 -0
  177. {hap_cli-0.6.10 → hap_cli-0.7.1}/sources/v3-api-schema/remove_member_from_role.yaml +0 -0
  178. {hap_cli-0.6.10 → hap_cli-0.7.1}/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.6.10
3
+ Version: 0.7.1
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 switch-org ORG_ID # switch the saved current org
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 switch-org` only changes the default organization. The default app
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 switch-org ORG_ID` | Switch the saved current organization |
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 switch-org` changes the default *organization* only — it does not
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 switch-org ORG_ID # switch the saved current org
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 switch-org` only changes the default organization. The default app
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 switch-org ORG_ID` | Switch the saved current organization |
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 switch-org` changes the default *organization* only — it does not
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-cli-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-cli-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)