hap-cli 0.8.4__tar.gz → 0.8.5__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 (210) hide show
  1. {hap_cli-0.8.4 → hap_cli-0.8.5}/PKG-INFO +8 -1
  2. {hap_cli-0.8.4/hap_cli → hap_cli-0.8.5}/README.md +7 -0
  3. {hap_cli-0.8.4 → hap_cli-0.8.5/hap_cli}/README.md +7 -0
  4. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/README_CN.md +7 -0
  5. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/__init__.py +1 -1
  6. hap_cli-0.8.5/hap_cli/__main__.py +11 -0
  7. hap_cli-0.8.5/hap_cli/commands/update_cmd.py +101 -0
  8. hap_cli-0.8.5/hap_cli/core/update.py +294 -0
  9. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/hap_cli.py +18 -0
  10. hap_cli-0.8.5/hap_cli/tests/test_update.py +423 -0
  11. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli.egg-info/PKG-INFO +8 -1
  12. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli.egg-info/SOURCES.txt +4 -0
  13. {hap_cli-0.8.4 → hap_cli-0.8.5}/MANIFEST.in +0 -0
  14. {hap_cli-0.8.4 → hap_cli-0.8.5}/app_live_tests/__init__.py +0 -0
  15. {hap_cli-0.8.4 → hap_cli-0.8.5}/app_live_tests/__main__.py +0 -0
  16. {hap_cli-0.8.4 → hap_cli-0.8.5}/app_live_tests/config.py +0 -0
  17. {hap_cli-0.8.4 → hap_cli-0.8.5}/app_live_tests/harness.py +0 -0
  18. {hap_cli-0.8.4 → hap_cli-0.8.5}/app_live_tests/smoke.py +0 -0
  19. {hap_cli-0.8.4 → hap_cli-0.8.5}/app_live_tests/state.py +0 -0
  20. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/commands/__init__.py +0 -0
  21. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/commands/app_cmd.py +0 -0
  22. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/commands/app_editor_cmd.py +0 -0
  23. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/commands/auth_cmd.py +0 -0
  24. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/commands/calendar_cmd.py +0 -0
  25. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/commands/chart_cmd.py +0 -0
  26. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/commands/chat_cmd.py +0 -0
  27. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/commands/chatbot_cmd.py +0 -0
  28. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/commands/config_cmd.py +0 -0
  29. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/commands/contact_cmd.py +0 -0
  30. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/commands/department_cmd.py +0 -0
  31. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/commands/group_cmd.py +0 -0
  32. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/commands/icon_cmd.py +0 -0
  33. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/commands/instance_cmd.py +0 -0
  34. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/commands/node_cmd.py +0 -0
  35. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/commands/optionset_cmd.py +0 -0
  36. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/commands/page_cmd.py +0 -0
  37. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/commands/post_cmd.py +0 -0
  38. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/commands/record_cmd.py +0 -0
  39. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/commands/region_cmd.py +0 -0
  40. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/commands/role_cmd.py +0 -0
  41. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/commands/upload_cmd.py +0 -0
  42. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/commands/v3_registry.py +0 -0
  43. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/commands/workflow_cmd.py +0 -0
  44. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/commands/worksheet_cmd.py +0 -0
  45. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/context.py +0 -0
  46. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/__init__.py +0 -0
  47. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/action_spec_adapter.py +0 -0
  48. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/app.py +0 -0
  49. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/auth.py +0 -0
  50. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/calendar_mod.py +0 -0
  51. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/chart.py +0 -0
  52. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/chat.py +0 -0
  53. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/chatbot.py +0 -0
  54. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/contact.py +0 -0
  55. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/control_type_codes.py +0 -0
  56. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/department.py +0 -0
  57. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/editor/__init__.py +0 -0
  58. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/editor/_hapmeta/__init__.py +0 -0
  59. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/editor/_hapmeta/control_type_codes.py +0 -0
  60. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/editor/apply.py +0 -0
  61. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/editor/componentlower.py +0 -0
  62. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/editor/editspec.py +0 -0
  63. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/editor/errors.py +0 -0
  64. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/editor/fieldlower.py +0 -0
  65. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/editor/jsonschema_mini.py +0 -0
  66. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/editor/models.py +0 -0
  67. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/editor/ops.py +0 -0
  68. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/editor/planner.py +0 -0
  69. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/editor/reader.py +0 -0
  70. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/field_normalizer.py +0 -0
  71. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/field_spec_adapter.py +0 -0
  72. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/filter_translator.py +0 -0
  73. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/flow_node.py +0 -0
  74. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/global_meta.py +0 -0
  75. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/group.py +0 -0
  76. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/icon_index.py +0 -0
  77. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/instance.py +0 -0
  78. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/logger.py +0 -0
  79. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/optionset.py +0 -0
  80. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/page.py +0 -0
  81. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/post.py +0 -0
  82. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/record.py +0 -0
  83. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/response_crypto.py +0 -0
  84. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/role.py +0 -0
  85. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/role_perm_builder.py +0 -0
  86. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/session.py +0 -0
  87. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/token_crypto.py +0 -0
  88. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/upload.py +0 -0
  89. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/v3/__init__.py +0 -0
  90. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/v3/dispatcher.py +0 -0
  91. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/v3/render.py +0 -0
  92. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/v3/schema.py +0 -0
  93. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/view_spec_adapter.py +0 -0
  94. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/workflow.py +0 -0
  95. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/workflow_node_dsl.py +0 -0
  96. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/worksheet.py +0 -0
  97. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/core/worksheet_templates.py +0 -0
  98. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/i18n.py +0 -0
  99. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/locale/__init__.py +0 -0
  100. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/locale/messages.json +0 -0
  101. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/locale/messages.schema.json +0 -0
  102. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/__init__.py +0 -0
  103. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/conftest.py +0 -0
  104. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_app_editor.py +0 -0
  105. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_app_export_usage.py +0 -0
  106. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_auth_prerelease.py +0 -0
  107. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_bug_036430.py +0 -0
  108. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_chart.py +0 -0
  109. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_config_cmd.py +0 -0
  110. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_core.py +0 -0
  111. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_destructive_confirm_cli.py +0 -0
  112. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_full_e2e.py +0 -0
  113. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_global_meta.py +0 -0
  114. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_i18n.py +0 -0
  115. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_integration.py +0 -0
  116. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_integration_approval.py +0 -0
  117. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_integration_approval_actions.py +0 -0
  118. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_integration_calendar.py +0 -0
  119. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_integration_destructive.py +0 -0
  120. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_integration_misc.py +0 -0
  121. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_integration_post.py +0 -0
  122. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_integration_social.py +0 -0
  123. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_integration_v3.py +0 -0
  124. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_integration_workflow.py +0 -0
  125. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_integration_worksheet_extra.py +0 -0
  126. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_multi_profile.py +0 -0
  127. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_org_approval_v3_semantic_cli.py +0 -0
  128. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_org_id_cli.py +0 -0
  129. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_org_id_docs.py +0 -0
  130. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_parameter_conventions.py +0 -0
  131. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_parameter_mapping_registry.py +0 -0
  132. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_record_batch_v3_semantic_cli.py +0 -0
  133. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_record_v3_semantic_cli.py +0 -0
  134. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_semantic_types_registry.py +0 -0
  135. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_v3_api_schema_loader.py +0 -0
  136. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_v3_dispatcher.py +0 -0
  137. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_v3_registry_coverage.py +0 -0
  138. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_v3_session.py +0 -0
  139. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_v3_yaml_translation.py +0 -0
  140. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_workflow_v3_semantic_cli.py +0 -0
  141. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_worksheet_crud_cli.py +0 -0
  142. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/tests/test_worksheet_v3_semantic_cli.py +0 -0
  143. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/utils/__init__.py +0 -0
  144. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/utils/formatting.py +0 -0
  145. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/utils/options.py +0 -0
  146. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli/utils/parameter_mapping.py +0 -0
  147. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli.egg-info/dependency_links.txt +0 -0
  148. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli.egg-info/entry_points.txt +0 -0
  149. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli.egg-info/requires.txt +0 -0
  150. {hap_cli-0.8.4 → hap_cli-0.8.5}/hap_cli.egg-info/top_level.txt +0 -0
  151. {hap_cli-0.8.4 → hap_cli-0.8.5}/live_tests/__init__.py +0 -0
  152. {hap_cli-0.8.4 → hap_cli-0.8.5}/live_tests/__main__.py +0 -0
  153. {hap_cli-0.8.4 → hap_cli-0.8.5}/live_tests/_wftest.py +0 -0
  154. {hap_cli-0.8.4 → hap_cli-0.8.5}/live_tests/charts.py +0 -0
  155. {hap_cli-0.8.4 → hap_cli-0.8.5}/live_tests/cleanup.py +0 -0
  156. {hap_cli-0.8.4 → hap_cli-0.8.5}/live_tests/compiler.py +0 -0
  157. {hap_cli-0.8.4 → hap_cli-0.8.5}/live_tests/config.py +0 -0
  158. {hap_cli-0.8.4 → hap_cli-0.8.5}/live_tests/errors.py +0 -0
  159. {hap_cli-0.8.4 → hap_cli-0.8.5}/live_tests/executor.py +0 -0
  160. {hap_cli-0.8.4 → hap_cli-0.8.5}/live_tests/fields.py +0 -0
  161. {hap_cli-0.8.4 → hap_cli-0.8.5}/live_tests/hap.py +0 -0
  162. {hap_cli-0.8.4 → hap_cli-0.8.5}/live_tests/recording/__init__.py +0 -0
  163. {hap_cli-0.8.4 → hap_cli-0.8.5}/live_tests/recording/console.py +0 -0
  164. {hap_cli-0.8.4 → hap_cli-0.8.5}/live_tests/recording/jsonl.py +0 -0
  165. {hap_cli-0.8.4 → hap_cli-0.8.5}/live_tests/recording/mirror.py +0 -0
  166. {hap_cli-0.8.4 → hap_cli-0.8.5}/live_tests/recording/report.py +0 -0
  167. {hap_cli-0.8.4 → hap_cli-0.8.5}/live_tests/schema.py +0 -0
  168. {hap_cli-0.8.4 → hap_cli-0.8.5}/live_tests/seed/__init__.py +0 -0
  169. {hap_cli-0.8.4 → hap_cli-0.8.5}/live_tests/seed/cli.py +0 -0
  170. {hap_cli-0.8.4 → hap_cli-0.8.5}/live_tests/seed/executor.py +0 -0
  171. {hap_cli-0.8.4 → hap_cli-0.8.5}/live_tests/seed/template.py +0 -0
  172. {hap_cli-0.8.4 → hap_cli-0.8.5}/live_tests/selftest.py +0 -0
  173. {hap_cli-0.8.4 → hap_cli-0.8.5}/live_tests/smoke.py +0 -0
  174. {hap_cli-0.8.4 → hap_cli-0.8.5}/live_tests/step.py +0 -0
  175. {hap_cli-0.8.4 → hap_cli-0.8.5}/live_tests/steps.py +0 -0
  176. {hap_cli-0.8.4 → hap_cli-0.8.5}/live_tests/store.py +0 -0
  177. {hap_cli-0.8.4 → hap_cli-0.8.5}/live_tests/workflow_dsl.py +0 -0
  178. {hap_cli-0.8.4 → hap_cli-0.8.5}/setup.cfg +0 -0
  179. {hap_cli-0.8.4 → hap_cli-0.8.5}/setup.py +0 -0
  180. {hap_cli-0.8.4 → hap_cli-0.8.5}/skills/hap-cli-app-editor/scripts/editspec/component.schema.json +0 -0
  181. {hap_cli-0.8.4 → hap_cli-0.8.5}/skills/hap-cli-app-editor/scripts/editspec/custom-action.schema.json +0 -0
  182. {hap_cli-0.8.4 → hap_cli-0.8.5}/skills/hap-cli-app-editor/scripts/editspec/envelope.schema.json +0 -0
  183. {hap_cli-0.8.4 → hap_cli-0.8.5}/skills/hap-cli-app-editor/scripts/editspec/field.schema.json +0 -0
  184. {hap_cli-0.8.4 → hap_cli-0.8.5}/sources/v3-api-schema/INDEX.json +0 -0
  185. {hap_cli-0.8.4 → hap_cli-0.8.5}/sources/v3-api-schema/add_member_to_role.yaml +0 -0
  186. {hap_cli-0.8.4 → hap_cli-0.8.5}/sources/v3-api-schema/batch_delete_records.yaml +0 -0
  187. {hap_cli-0.8.4 → hap_cli-0.8.5}/sources/v3-api-schema/create_optionset.yaml +0 -0
  188. {hap_cli-0.8.4 → hap_cli-0.8.5}/sources/v3-api-schema/create_role.yaml +0 -0
  189. {hap_cli-0.8.4 → hap_cli-0.8.5}/sources/v3-api-schema/delete_optionset.yaml +0 -0
  190. {hap_cli-0.8.4 → hap_cli-0.8.5}/sources/v3-api-schema/delete_record.yaml +0 -0
  191. {hap_cli-0.8.4 → hap_cli-0.8.5}/sources/v3-api-schema/delete_role.yaml +0 -0
  192. {hap_cli-0.8.4 → hap_cli-0.8.5}/sources/v3-api-schema/delete_worksheet.yaml +0 -0
  193. {hap_cli-0.8.4 → hap_cli-0.8.5}/sources/v3-api-schema/get_app_info.yaml +0 -0
  194. {hap_cli-0.8.4 → hap_cli-0.8.5}/sources/v3-api-schema/get_app_knowledge_list.yaml +0 -0
  195. {hap_cli-0.8.4 → hap_cli-0.8.5}/sources/v3-api-schema/get_app_worksheets_list.yaml +0 -0
  196. {hap_cli-0.8.4 → hap_cli-0.8.5}/sources/v3-api-schema/get_optionset_list.yaml +0 -0
  197. {hap_cli-0.8.4 → hap_cli-0.8.5}/sources/v3-api-schema/get_record_details.yaml +0 -0
  198. {hap_cli-0.8.4 → hap_cli-0.8.5}/sources/v3-api-schema/get_record_discussions.yaml +0 -0
  199. {hap_cli-0.8.4 → hap_cli-0.8.5}/sources/v3-api-schema/get_record_list.yaml +0 -0
  200. {hap_cli-0.8.4 → hap_cli-0.8.5}/sources/v3-api-schema/get_record_logs.yaml +0 -0
  201. {hap_cli-0.8.4 → hap_cli-0.8.5}/sources/v3-api-schema/get_record_pivot_data.yaml +0 -0
  202. {hap_cli-0.8.4 → hap_cli-0.8.5}/sources/v3-api-schema/get_record_relations.yaml +0 -0
  203. {hap_cli-0.8.4 → hap_cli-0.8.5}/sources/v3-api-schema/get_record_share_link.yaml +0 -0
  204. {hap_cli-0.8.4 → hap_cli-0.8.5}/sources/v3-api-schema/get_regions.yaml +0 -0
  205. {hap_cli-0.8.4 → hap_cli-0.8.5}/sources/v3-api-schema/get_role_details.yaml +0 -0
  206. {hap_cli-0.8.4 → hap_cli-0.8.5}/sources/v3-api-schema/get_role_list.yaml +0 -0
  207. {hap_cli-0.8.4 → hap_cli-0.8.5}/sources/v3-api-schema/knowledge_search.yaml +0 -0
  208. {hap_cli-0.8.4 → hap_cli-0.8.5}/sources/v3-api-schema/leave_all_roles.yaml +0 -0
  209. {hap_cli-0.8.4 → hap_cli-0.8.5}/sources/v3-api-schema/remove_member_from_role.yaml +0 -0
  210. {hap_cli-0.8.4 → hap_cli-0.8.5}/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.8.4
3
+ Version: 0.8.5
4
4
  Summary: CLI harness for MingDAO HAP - Enterprise no-code platform
5
5
  Author: hap-cli
6
6
  License: Apache-2.0
@@ -313,6 +313,13 @@ body, and a redacted `Authorization` header (first 16 chars). `password`
313
313
  and other sensitive keys are masked. `HAP_LOG_LEVEL=DEBUG` temporarily
314
314
  overrides the persisted level.
315
315
 
316
+ ### update — keep the CLI current
317
+
318
+ | Command | Description |
319
+ |---|---|
320
+ | `update` | Check PyPI for a newer release and upgrade in place, using the same tool the CLI was installed with (pip / pipx / uv) |
321
+ | `update --check` | Only report whether a newer version exists, without installing |
322
+
316
323
  ---
317
324
 
318
325
  ## Default app & organization
@@ -284,6 +284,13 @@ body, and a redacted `Authorization` header (first 16 chars). `password`
284
284
  and other sensitive keys are masked. `HAP_LOG_LEVEL=DEBUG` temporarily
285
285
  overrides the persisted level.
286
286
 
287
+ ### update — keep the CLI current
288
+
289
+ | Command | Description |
290
+ |---|---|
291
+ | `update` | Check PyPI for a newer release and upgrade in place, using the same tool the CLI was installed with (pip / pipx / uv) |
292
+ | `update --check` | Only report whether a newer version exists, without installing |
293
+
287
294
  ---
288
295
 
289
296
  ## Default app & organization
@@ -284,6 +284,13 @@ body, and a redacted `Authorization` header (first 16 chars). `password`
284
284
  and other sensitive keys are masked. `HAP_LOG_LEVEL=DEBUG` temporarily
285
285
  overrides the persisted level.
286
286
 
287
+ ### update — keep the CLI current
288
+
289
+ | Command | Description |
290
+ |---|---|
291
+ | `update` | Check PyPI for a newer release and upgrade in place, using the same tool the CLI was installed with (pip / pipx / uv) |
292
+ | `update --check` | Only report whether a newer version exists, without installing |
293
+
287
294
  ---
288
295
 
289
296
  ## Default app & organization
@@ -260,6 +260,13 @@ hap --json worksheet record list WORKSHEET_ID
260
260
 
261
261
  日志默认写入 `~/.hap-cli/hap-cli.log`,10 MB × 3 滚动。开启后每次 API 调用以 `INFO` 级别记录 URL、请求体、响应体,以及脱敏后的 `Authorization` 头(仅前 16 字符);`password` 等敏感字段会被自动打码。临时调试可设 `HAP_LOG_LEVEL=DEBUG`。
262
262
 
263
+ ### update — 升级 CLI
264
+
265
+ | 命令 | 说明 |
266
+ |---|---|
267
+ | `update` | 检查 PyPI 上的最新版本,有新版则用安装时的工具(pip / pipx / uv)原地升级 |
268
+ | `update --check` | 只检查是否有新版本,不安装 |
269
+
263
270
  ---
264
271
 
265
272
  ## 默认应用与组织
@@ -1,3 +1,3 @@
1
1
  """CLI harness for MingDAO HAP (hap-cli)."""
2
2
 
3
- __version__ = "0.8.4"
3
+ __version__ = "0.8.5"
@@ -0,0 +1,11 @@
1
+ """Allow ``python -m hap_cli`` — used by the detached background
2
+ update child (``hap update --background``), which is spawned with
3
+ ``sys.executable -m hap_cli`` so it always runs in the same
4
+ environment as the parent process regardless of how the ``hap``
5
+ console script was installed.
6
+ """
7
+
8
+ from hap_cli.hap_cli import main
9
+
10
+ if __name__ == "__main__":
11
+ main()
@@ -0,0 +1,101 @@
1
+ """CLI command for self-updating hap-cli from PyPI.
2
+
3
+ The hidden ``--background`` flag is the entry point for the detached
4
+ child process spawned by the exit-time hook in ``hap_cli.py`` — it is
5
+ internal plumbing and intentionally absent from ``--help`` and docs.
6
+ """
7
+
8
+ import time
9
+
10
+ import click
11
+
12
+ from hap_cli.context import pass_context
13
+ from hap_cli.core import update as upd
14
+
15
+
16
+ @click.command("update")
17
+ @click.option(
18
+ "--check",
19
+ "check_only",
20
+ is_flag=True,
21
+ help="Only check whether a newer version exists; do not install.",
22
+ )
23
+ @click.option("--background", is_flag=True, hidden=True)
24
+ @pass_context
25
+ def update(ctx, check_only, background):
26
+ """Upgrade hap-cli to the latest version from PyPI.
27
+
28
+ Checks for a newer release and installs it using the same tool the
29
+ CLI was installed with (pip, pipx, or uv). Installs that are not
30
+ managed from PyPI are left untouched.
31
+ """
32
+ if background:
33
+ # Detached child: silent check-and-upgrade; results go to the
34
+ # state file and are surfaced on the next foreground run.
35
+ upd.run_background_update()
36
+ return
37
+
38
+ from hap_cli import __version__
39
+
40
+ kind = upd.get_install_kind()
41
+ if kind in ("editable", "unknown"):
42
+ ctx.output(
43
+ {"current": __version__, "install": kind, "updated": False},
44
+ lambda d: click.echo(
45
+ "This copy of hap-cli is not managed from PyPI "
46
+ f"(current version {__version__}) — nothing to update."
47
+ ),
48
+ )
49
+ return
50
+
51
+ latest = upd.fetch_latest_version()
52
+ if latest is None:
53
+ ctx.handle_error(Exception("Could not reach PyPI to check for updates."))
54
+ return
55
+
56
+ if not upd.is_newer(latest, __version__):
57
+ upd.save_state(
58
+ {
59
+ "last_check_at": time.time(),
60
+ "latest_version": latest,
61
+ "last_result": "up_to_date",
62
+ "notified": True,
63
+ }
64
+ )
65
+ ctx.output(
66
+ {"current": __version__, "latest": latest, "updated": False},
67
+ lambda d: click.echo(
68
+ f"hap-cli {__version__} is already the latest version."
69
+ ),
70
+ )
71
+ return
72
+
73
+ if check_only:
74
+ ctx.output(
75
+ {"current": __version__, "latest": latest, "updated": False},
76
+ lambda d: click.echo(
77
+ f"A newer version is available: {latest} "
78
+ f"(current {__version__}). Run `hap update` to upgrade."
79
+ ),
80
+ )
81
+ return
82
+
83
+ click.echo(f"Upgrading hap-cli {__version__} -> {latest} ...")
84
+ ok, output = upd.perform_upgrade(kind)
85
+ upd.save_state(
86
+ {
87
+ "last_check_at": time.time(),
88
+ "latest_version": latest,
89
+ "last_result": "upgraded" if ok else "upgrade_failed",
90
+ "upgraded_to": latest if ok else None,
91
+ "notified": True,
92
+ }
93
+ )
94
+ if ok:
95
+ ctx.output(
96
+ {"current": __version__, "latest": latest, "updated": True},
97
+ lambda d: click.echo(f"Upgraded to hap-cli {latest}."),
98
+ )
99
+ else:
100
+ click.echo(output, err=True)
101
+ ctx.handle_error(Exception(f"Upgrade to {latest} failed."))
@@ -0,0 +1,294 @@
1
+ """Self-update support for hap-cli.
2
+
3
+ Two entry paths share this module:
4
+
5
+ - ``hap update`` — synchronous, user-invoked check/upgrade.
6
+ - ``hap update --background`` — hidden; spawned as a detached child
7
+ process when a command exits and the last check is older than
8
+ ``UPDATE_CHECK_INTERVAL_SECONDS``. It checks PyPI, auto-upgrades if
9
+ newer, and records the outcome in the state file so the *next* run
10
+ can surface a one-line notice.
11
+
12
+ Editable installs (PEP 660 ``direct_url.json`` with
13
+ ``dir_info.editable: true``) and unrecognized install origins disable
14
+ the feature entirely — they are by definition not managed via PyPI.
15
+ """
16
+
17
+ import json
18
+ import logging
19
+ import os
20
+ import re
21
+ import subprocess
22
+ import sys
23
+ import time
24
+ from typing import Any, Optional
25
+
26
+ import requests
27
+
28
+ logger = logging.getLogger("hap_cli.update")
29
+
30
+ PYPI_PACKAGE = "hap-cli"
31
+ PYPI_JSON_URL = f"https://pypi.org/pypi/{PYPI_PACKAGE}/json"
32
+
33
+ # Deliberately short while the tool is iterating quickly; once releases
34
+ # stabilize, bump this in a regular release (it ships with the code, so
35
+ # every upgrade can retune the cadence).
36
+ UPDATE_CHECK_INTERVAL_SECONDS = 3600
37
+
38
+ # Only final releases (digits and dots) are auto-upgrade candidates;
39
+ # pre/dev/post markers ("0.9.0rc1", "1.0.dev2") are skipped.
40
+ _FINAL_RELEASE_RE = re.compile(r"^\d+(\.\d+)*$")
41
+
42
+
43
+ def _state_file():
44
+ # Resolve lazily through the session module so tests (and
45
+ # HAP_CLI_HOME) that repoint CONFIG_DIR are honored.
46
+ from hap_cli.core import session
47
+
48
+ return session.CONFIG_DIR / "update_check.json"
49
+
50
+
51
+ # ── Install-kind detection ───────────────────────────────────────────────
52
+
53
+
54
+ def get_install_kind() -> str:
55
+ """Classify how this copy of hap-cli was installed.
56
+
57
+ Returns one of ``editable`` / ``pip`` / ``pipx`` / ``uv`` /
58
+ ``unknown``. Only ``pip`` / ``pipx`` / ``uv`` are upgradable from
59
+ PyPI; the other two disable the update feature.
60
+ """
61
+ import importlib.metadata
62
+
63
+ try:
64
+ dist = importlib.metadata.distribution(PYPI_PACKAGE)
65
+ direct_url_text = dist.read_text("direct_url.json")
66
+ except Exception as e:
67
+ logger.warning("install-kind detection failed: %s", e)
68
+ return "unknown"
69
+
70
+ if direct_url_text:
71
+ try:
72
+ direct_url = json.loads(direct_url_text)
73
+ except ValueError:
74
+ return "unknown"
75
+ if direct_url.get("dir_info", {}).get("editable"):
76
+ return "editable"
77
+ # Installed from a direct URL/path but not editable — we don't
78
+ # know how to keep it current, so stay hands-off.
79
+ return "unknown"
80
+
81
+ prefix = sys.prefix.replace(os.sep, "/")
82
+ if "pipx/venvs" in prefix:
83
+ return "pipx"
84
+ if "uv/tools" in prefix:
85
+ return "uv"
86
+ return "pip"
87
+
88
+
89
+ def build_upgrade_command(kind: str) -> Optional[list]:
90
+ """Upgrade argv for an install kind, or None if not upgradable."""
91
+ if kind == "pip":
92
+ return [sys.executable, "-m", "pip", "install", "--upgrade", PYPI_PACKAGE]
93
+ if kind == "pipx":
94
+ return ["pipx", "upgrade", PYPI_PACKAGE]
95
+ if kind == "uv":
96
+ return ["uv", "tool", "upgrade", PYPI_PACKAGE]
97
+ return None
98
+
99
+
100
+ # ── Version handling ─────────────────────────────────────────────────────
101
+
102
+
103
+ def _version_tuple(version: str) -> tuple:
104
+ return tuple(int(part) for part in version.split("."))
105
+
106
+
107
+ def is_newer(latest: str, current: str) -> bool:
108
+ """True if ``latest`` is strictly newer than ``current``."""
109
+ try:
110
+ return _version_tuple(latest) > _version_tuple(current)
111
+ except ValueError:
112
+ logger.warning(
113
+ "cannot compare versions latest=%r current=%r", latest, current
114
+ )
115
+ return False
116
+
117
+
118
+ def fetch_latest_version(timeout: int = 5) -> Optional[str]:
119
+ """Latest final (non-prerelease, non-yanked) version on PyPI.
120
+
121
+ Returns None on any network/parse error — callers treat that as
122
+ "couldn't check", never as an error surfaced to the user.
123
+ """
124
+ from hap_cli.core.logger import format_response_for_log
125
+
126
+ logger.info("HAP GET %s params={} Authorization=<none>", PYPI_JSON_URL)
127
+ try:
128
+ response = requests.get(PYPI_JSON_URL, timeout=timeout)
129
+ logger.info(
130
+ "HAP GET %s -> %d %s",
131
+ PYPI_JSON_URL,
132
+ response.status_code,
133
+ format_response_for_log(getattr(response, "text", "") or ""),
134
+ )
135
+ response.raise_for_status()
136
+ payload = response.json()
137
+ except Exception as e:
138
+ logger.warning("PyPI version check failed: %s", e)
139
+ return None
140
+
141
+ candidates = []
142
+ for version, files in (payload.get("releases") or {}).items():
143
+ if not _FINAL_RELEASE_RE.match(version):
144
+ continue
145
+ if not files or all(f.get("yanked") for f in files):
146
+ continue
147
+ candidates.append(version)
148
+ if not candidates:
149
+ return None
150
+ return max(candidates, key=_version_tuple)
151
+
152
+
153
+ # ── State file ───────────────────────────────────────────────────────────
154
+
155
+
156
+ def load_state() -> dict:
157
+ """Read the update-check state; empty dict if missing/corrupt."""
158
+ try:
159
+ with open(_state_file(), encoding="utf-8") as f:
160
+ data = json.load(f)
161
+ return data if isinstance(data, dict) else {}
162
+ except FileNotFoundError:
163
+ return {}
164
+ except Exception as e:
165
+ logger.warning("corrupt update state file, resetting: %s", e)
166
+ return {}
167
+
168
+
169
+ def save_state(state: dict) -> None:
170
+ """Atomically persist the update-check state."""
171
+ path = _state_file()
172
+ path.parent.mkdir(parents=True, exist_ok=True)
173
+ tmp = path.with_suffix(".json.tmp")
174
+ tmp.write_text(json.dumps(state, ensure_ascii=False), encoding="utf-8")
175
+ os.replace(tmp, path)
176
+
177
+
178
+ # ── Background check orchestration ───────────────────────────────────────
179
+
180
+
181
+ def maybe_spawn_background_check() -> None:
182
+ """Spawn a detached background update check if it is due.
183
+
184
+ Called when a CLI command finishes. The timestamp is bumped
185
+ *before* spawning so rapid consecutive commands cannot stack
186
+ duplicate children — at worst a failed child costs one interval.
187
+ """
188
+ kind = get_install_kind()
189
+ if kind in ("editable", "unknown"):
190
+ return
191
+
192
+ state = load_state()
193
+ last = state.get("last_check_at") or 0
194
+ now = time.time()
195
+ if now - last < UPDATE_CHECK_INTERVAL_SECONDS:
196
+ return
197
+
198
+ state["last_check_at"] = now
199
+ save_state(state)
200
+
201
+ try:
202
+ subprocess.Popen(
203
+ [sys.executable, "-m", "hap_cli", "update", "--background"],
204
+ stdin=subprocess.DEVNULL,
205
+ stdout=subprocess.DEVNULL,
206
+ stderr=subprocess.DEVNULL,
207
+ start_new_session=True,
208
+ )
209
+ logger.info("spawned background update check (install kind: %s)", kind)
210
+ except Exception as e:
211
+ logger.warning("failed to spawn background update check: %s", e)
212
+
213
+
214
+ def perform_upgrade(kind: str) -> tuple:
215
+ """Run the upgrade command for ``kind``. Returns (ok, output)."""
216
+ cmd = build_upgrade_command(kind)
217
+ if cmd is None:
218
+ return False, f"no upgrade command for install kind {kind!r}"
219
+ logger.info("running upgrade command: %s", " ".join(cmd))
220
+ try:
221
+ proc = subprocess.run(
222
+ cmd, capture_output=True, text=True, timeout=600
223
+ )
224
+ except Exception as e:
225
+ logger.error("upgrade command failed to run: %s", e)
226
+ return False, str(e)
227
+ output = (proc.stdout or "") + (proc.stderr or "")
228
+ logger.info("upgrade command exited %d", proc.returncode)
229
+ return proc.returncode == 0, output
230
+
231
+
232
+ def run_background_update() -> None:
233
+ """Body of the hidden ``hap update --background`` child process.
234
+
235
+ Silent by design: outcomes go to the state file (surfaced by the
236
+ next foreground run) and the log, never to the terminal.
237
+ """
238
+ from hap_cli import __version__
239
+
240
+ state = load_state()
241
+ state["last_check_at"] = time.time()
242
+
243
+ latest = fetch_latest_version()
244
+ if latest is None:
245
+ state["last_result"] = "check_failed"
246
+ save_state(state)
247
+ return
248
+
249
+ state["latest_version"] = latest
250
+ if not is_newer(latest, __version__):
251
+ state["last_result"] = "up_to_date"
252
+ save_state(state)
253
+ return
254
+
255
+ ok, output = perform_upgrade(get_install_kind())
256
+ if ok:
257
+ state["last_result"] = "upgraded"
258
+ state["upgraded_to"] = latest
259
+ else:
260
+ state["last_result"] = "upgrade_failed"
261
+ state["error"] = output[-500:]
262
+ logger.error("background upgrade to %s failed: %s", latest, output)
263
+ state["notified"] = False
264
+ save_state(state)
265
+
266
+
267
+ def consume_startup_notice() -> Optional[str]:
268
+ """One-shot user notice from the last background run, if any.
269
+
270
+ Returns the message and marks it notified so it is shown exactly
271
+ once. Silent results (check_failed / up_to_date) return None.
272
+ """
273
+ state = load_state()
274
+ if state.get("notified", True):
275
+ return None
276
+
277
+ result = state.get("last_result")
278
+ if result == "upgraded":
279
+ msg = (
280
+ f"hap-cli was auto-upgraded to {state.get('upgraded_to')} "
281
+ "(takes effect from this run)."
282
+ )
283
+ elif result == "upgrade_failed":
284
+ latest = state.get("latest_version") or "a newer version"
285
+ msg = (
286
+ f"Automatic upgrade to {latest} failed — "
287
+ "run `hap update` to upgrade manually."
288
+ )
289
+ else:
290
+ return None
291
+
292
+ state["notified"] = True
293
+ save_state(state)
294
+ return msg
@@ -41,6 +41,11 @@ from hap_cli.commands.region_cmd import region
41
41
  from hap_cli.commands.icon_cmd import icon
42
42
  from hap_cli.commands.upload_cmd import upload
43
43
  from hap_cli.commands.app_editor_cmd import app_editor
44
+ from hap_cli.commands.update_cmd import update as update_cmd
45
+ from hap_cli.core.update import (
46
+ consume_startup_notice,
47
+ maybe_spawn_background_check,
48
+ )
44
49
 
45
50
 
46
51
  def clone_group(source, *, name=None, hidden=False):
@@ -71,6 +76,18 @@ def cli(ctx, json_mode, profile):
71
76
  ctx.obj.json_mode = json_mode
72
77
  ctx.obj.profile = profile
73
78
 
79
+ # Self-update plumbing. Both halves are local-file-only on the hot
80
+ # path: the notice reads a small JSON state file, and the spawn hook
81
+ # only forks a detached child when the last check is older than the
82
+ # interval (the child does the actual network I/O). Skipped for
83
+ # `update` itself (it manages the state directly) and `repl`
84
+ # (cli() re-runs per REPL line).
85
+ notice = consume_startup_notice()
86
+ if notice:
87
+ click.echo(notice, err=True)
88
+ if ctx.invoked_subcommand not in ("update", "repl"):
89
+ ctx.call_on_close(maybe_spawn_background_check)
90
+
74
91
 
75
92
  # Register command groups
76
93
  app.add_command(clone_group(role, name="role"))
@@ -127,6 +144,7 @@ cli.add_command(icon)
127
144
  cli.add_command(upload)
128
145
  cli.add_command(config_group)
129
146
  cli.add_command(app_editor)
147
+ cli.add_command(update_cmd)
130
148
 
131
149
 
132
150
  # Hidden top-level alias for the old `hap completion` command. The