hap-cli 0.8.14__tar.gz → 0.8.15__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 (253) hide show
  1. {hap_cli-0.8.14 → hap_cli-0.8.15}/PKG-INFO +1 -1
  2. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/__init__.py +1 -1
  3. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/commands/instance_cmd.py +58 -24
  4. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/commands/role_cmd.py +2 -1
  5. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/instance.py +36 -15
  6. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/role_perm_builder.py +22 -1
  7. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/locale/messages.json +19 -13
  8. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_core.py +100 -2
  9. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_destructive_confirm_cli.py +1 -1
  10. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli.egg-info/PKG-INFO +1 -1
  11. {hap_cli-0.8.14 → hap_cli-0.8.15}/MANIFEST.in +0 -0
  12. {hap_cli-0.8.14 → hap_cli-0.8.15}/README.md +0 -0
  13. {hap_cli-0.8.14 → hap_cli-0.8.15}/app_live_tests/__init__.py +0 -0
  14. {hap_cli-0.8.14 → hap_cli-0.8.15}/app_live_tests/__main__.py +0 -0
  15. {hap_cli-0.8.14 → hap_cli-0.8.15}/app_live_tests/config.py +0 -0
  16. {hap_cli-0.8.14 → hap_cli-0.8.15}/app_live_tests/harness.py +0 -0
  17. {hap_cli-0.8.14 → hap_cli-0.8.15}/app_live_tests/smoke.py +0 -0
  18. {hap_cli-0.8.14 → hap_cli-0.8.15}/app_live_tests/state.py +0 -0
  19. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/README.md +0 -0
  20. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/README_CN.md +0 -0
  21. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/__main__.py +0 -0
  22. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/commands/__init__.py +0 -0
  23. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/commands/app_cmd.py +0 -0
  24. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/commands/app_creator_cmd.py +0 -0
  25. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/commands/app_editor_cmd.py +0 -0
  26. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/commands/auth_cmd.py +0 -0
  27. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/commands/calendar_cmd.py +0 -0
  28. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/commands/chart_cmd.py +0 -0
  29. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/commands/chat_cmd.py +0 -0
  30. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/commands/chatbot_cmd.py +0 -0
  31. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/commands/config_cmd.py +0 -0
  32. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/commands/contact_cmd.py +0 -0
  33. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/commands/department_cmd.py +0 -0
  34. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/commands/group_cmd.py +0 -0
  35. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/commands/icon_cmd.py +0 -0
  36. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/commands/node_cmd.py +0 -0
  37. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/commands/optionset_cmd.py +0 -0
  38. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/commands/page_cmd.py +0 -0
  39. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/commands/post_cmd.py +0 -0
  40. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/commands/record_cmd.py +0 -0
  41. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/commands/region_cmd.py +0 -0
  42. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/commands/update_cmd.py +0 -0
  43. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/commands/upload_cmd.py +0 -0
  44. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/commands/v3_registry.py +0 -0
  45. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/commands/workflow_cmd.py +0 -0
  46. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/commands/worksheet_cmd.py +0 -0
  47. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/context.py +0 -0
  48. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/__init__.py +0 -0
  49. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/action_spec_adapter.py +0 -0
  50. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app.py +0 -0
  51. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/__init__.py +0 -0
  52. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/_hapmeta/__init__.py +0 -0
  53. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/_hapmeta/control_type_codes.py +0 -0
  54. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/_hapmeta/worksheet_templates.py +0 -0
  55. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/charts.py +0 -0
  56. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/cleanup.py +0 -0
  57. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/compiler.py +0 -0
  58. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/config.py +0 -0
  59. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/design/design.schema.json +0 -0
  60. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/errors.py +0 -0
  61. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/examples/minimal.design.json +0 -0
  62. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/executor.py +0 -0
  63. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/fields.py +0 -0
  64. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/hap.py +0 -0
  65. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/merge.py +0 -0
  66. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/recording/__init__.py +0 -0
  67. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/recording/console.py +0 -0
  68. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/recording/jsonl.py +0 -0
  69. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/recording/mirror.py +0 -0
  70. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/recording/report.py +0 -0
  71. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/schema.py +0 -0
  72. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/seed/INSTRUCTIONS.md +0 -0
  73. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/seed/__init__.py +0 -0
  74. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/seed/cli.py +0 -0
  75. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/seed/executor.py +0 -0
  76. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/seed/resources/attachments.json +0 -0
  77. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/seed/resources/sample.docx +0 -0
  78. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/seed/resources/sample.pdf +0 -0
  79. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/seed/resources/sample_images.json +0 -0
  80. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/seed/template.py +0 -0
  81. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/selftest.py +0 -0
  82. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/smoke.py +0 -0
  83. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/steps.py +0 -0
  84. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/store.py +0 -0
  85. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/validate.py +0 -0
  86. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/app_creator/workflow_dsl.py +0 -0
  87. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/auth.py +0 -0
  88. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/calendar_mod.py +0 -0
  89. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/chart.py +0 -0
  90. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/chat.py +0 -0
  91. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/chatbot.py +0 -0
  92. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/cli_access.py +0 -0
  93. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/contact.py +0 -0
  94. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/control_type_codes.py +0 -0
  95. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/department.py +0 -0
  96. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/editor/__init__.py +0 -0
  97. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/editor/_hapmeta/__init__.py +0 -0
  98. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/editor/_hapmeta/control_type_codes.py +0 -0
  99. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/editor/apply.py +0 -0
  100. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/editor/componentlower.py +0 -0
  101. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/editor/editspec.py +0 -0
  102. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/editor/errors.py +0 -0
  103. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/editor/fieldlower.py +0 -0
  104. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/editor/jsonschema_mini.py +0 -0
  105. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/editor/models.py +0 -0
  106. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/editor/ops.py +0 -0
  107. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/editor/planner.py +0 -0
  108. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/editor/reader.py +0 -0
  109. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/field_normalizer.py +0 -0
  110. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/field_spec_adapter.py +0 -0
  111. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/filter_translator.py +0 -0
  112. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/flow_node.py +0 -0
  113. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/global_meta.py +0 -0
  114. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/group.py +0 -0
  115. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/icon_index.py +0 -0
  116. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/logger.py +0 -0
  117. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/optionset.py +0 -0
  118. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/page.py +0 -0
  119. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/post.py +0 -0
  120. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/record.py +0 -0
  121. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/response_crypto.py +0 -0
  122. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/role.py +0 -0
  123. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/session.py +0 -0
  124. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/token_crypto.py +0 -0
  125. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/update.py +0 -0
  126. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/upload.py +0 -0
  127. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/v3/__init__.py +0 -0
  128. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/v3/dispatcher.py +0 -0
  129. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/v3/render.py +0 -0
  130. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/v3/schema.py +0 -0
  131. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/view_spec_adapter.py +0 -0
  132. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/workflow.py +0 -0
  133. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/workflow_node_dsl.py +0 -0
  134. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/worksheet.py +0 -0
  135. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/core/worksheet_templates.py +0 -0
  136. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/hap_cli.py +0 -0
  137. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/i18n.py +0 -0
  138. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/locale/__init__.py +0 -0
  139. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/locale/messages.schema.json +0 -0
  140. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/__init__.py +0 -0
  141. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/conftest.py +0 -0
  142. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_app_creator.py +0 -0
  143. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_app_editor.py +0 -0
  144. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_app_export_usage.py +0 -0
  145. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_auth_prerelease.py +0 -0
  146. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_bug_036430.py +0 -0
  147. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_chart.py +0 -0
  148. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_cli_access.py +0 -0
  149. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_config_cmd.py +0 -0
  150. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_full_e2e.py +0 -0
  151. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_global_meta.py +0 -0
  152. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_i18n.py +0 -0
  153. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_instance_history_cli.py +0 -0
  154. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_integration.py +0 -0
  155. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_integration_approval.py +0 -0
  156. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_integration_approval_actions.py +0 -0
  157. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_integration_calendar.py +0 -0
  158. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_integration_destructive.py +0 -0
  159. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_integration_misc.py +0 -0
  160. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_integration_post.py +0 -0
  161. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_integration_social.py +0 -0
  162. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_integration_v3.py +0 -0
  163. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_integration_workflow.py +0 -0
  164. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_integration_worksheet_extra.py +0 -0
  165. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_multi_profile.py +0 -0
  166. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_org_approval_v3_semantic_cli.py +0 -0
  167. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_org_id_cli.py +0 -0
  168. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_org_id_docs.py +0 -0
  169. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_parameter_conventions.py +0 -0
  170. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_parameter_mapping_registry.py +0 -0
  171. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_record_batch_v3_semantic_cli.py +0 -0
  172. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_record_field_alias.py +0 -0
  173. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_record_v3_semantic_cli.py +0 -0
  174. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_semantic_types_registry.py +0 -0
  175. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_update.py +0 -0
  176. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_v3_api_schema_loader.py +0 -0
  177. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_v3_dispatcher.py +0 -0
  178. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_v3_registry_coverage.py +0 -0
  179. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_v3_session.py +0 -0
  180. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_v3_yaml_translation.py +0 -0
  181. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_workflow_list_cli.py +0 -0
  182. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_workflow_v3_semantic_cli.py +0 -0
  183. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_worksheet_crud_cli.py +0 -0
  184. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/tests/test_worksheet_v3_semantic_cli.py +0 -0
  185. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/utils/__init__.py +0 -0
  186. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/utils/formatting.py +0 -0
  187. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/utils/options.py +0 -0
  188. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli/utils/parameter_mapping.py +0 -0
  189. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli.egg-info/SOURCES.txt +0 -0
  190. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli.egg-info/dependency_links.txt +0 -0
  191. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli.egg-info/entry_points.txt +0 -0
  192. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli.egg-info/requires.txt +0 -0
  193. {hap_cli-0.8.14 → hap_cli-0.8.15}/hap_cli.egg-info/top_level.txt +0 -0
  194. {hap_cli-0.8.14 → hap_cli-0.8.15}/live_tests/__init__.py +0 -0
  195. {hap_cli-0.8.14 → hap_cli-0.8.15}/live_tests/__main__.py +0 -0
  196. {hap_cli-0.8.14 → hap_cli-0.8.15}/live_tests/_wftest.py +0 -0
  197. {hap_cli-0.8.14 → hap_cli-0.8.15}/live_tests/charts.py +0 -0
  198. {hap_cli-0.8.14 → hap_cli-0.8.15}/live_tests/cleanup.py +0 -0
  199. {hap_cli-0.8.14 → hap_cli-0.8.15}/live_tests/compiler.py +0 -0
  200. {hap_cli-0.8.14 → hap_cli-0.8.15}/live_tests/config.py +0 -0
  201. {hap_cli-0.8.14 → hap_cli-0.8.15}/live_tests/errors.py +0 -0
  202. {hap_cli-0.8.14 → hap_cli-0.8.15}/live_tests/executor.py +0 -0
  203. {hap_cli-0.8.14 → hap_cli-0.8.15}/live_tests/fields.py +0 -0
  204. {hap_cli-0.8.14 → hap_cli-0.8.15}/live_tests/hap.py +0 -0
  205. {hap_cli-0.8.14 → hap_cli-0.8.15}/live_tests/recording/__init__.py +0 -0
  206. {hap_cli-0.8.14 → hap_cli-0.8.15}/live_tests/recording/console.py +0 -0
  207. {hap_cli-0.8.14 → hap_cli-0.8.15}/live_tests/recording/jsonl.py +0 -0
  208. {hap_cli-0.8.14 → hap_cli-0.8.15}/live_tests/recording/mirror.py +0 -0
  209. {hap_cli-0.8.14 → hap_cli-0.8.15}/live_tests/recording/report.py +0 -0
  210. {hap_cli-0.8.14 → hap_cli-0.8.15}/live_tests/schema.py +0 -0
  211. {hap_cli-0.8.14 → hap_cli-0.8.15}/live_tests/seed/__init__.py +0 -0
  212. {hap_cli-0.8.14 → hap_cli-0.8.15}/live_tests/seed/cli.py +0 -0
  213. {hap_cli-0.8.14 → hap_cli-0.8.15}/live_tests/seed/executor.py +0 -0
  214. {hap_cli-0.8.14 → hap_cli-0.8.15}/live_tests/seed/template.py +0 -0
  215. {hap_cli-0.8.14 → hap_cli-0.8.15}/live_tests/selftest.py +0 -0
  216. {hap_cli-0.8.14 → hap_cli-0.8.15}/live_tests/smoke.py +0 -0
  217. {hap_cli-0.8.14 → hap_cli-0.8.15}/live_tests/step.py +0 -0
  218. {hap_cli-0.8.14 → hap_cli-0.8.15}/live_tests/steps.py +0 -0
  219. {hap_cli-0.8.14 → hap_cli-0.8.15}/live_tests/store.py +0 -0
  220. {hap_cli-0.8.14 → hap_cli-0.8.15}/live_tests/workflow_dsl.py +0 -0
  221. {hap_cli-0.8.14 → hap_cli-0.8.15}/setup.cfg +0 -0
  222. {hap_cli-0.8.14 → hap_cli-0.8.15}/setup.py +0 -0
  223. {hap_cli-0.8.14 → hap_cli-0.8.15}/skills/cli/hap-cli-app-editor/scripts/editspec/component.schema.json +0 -0
  224. {hap_cli-0.8.14 → hap_cli-0.8.15}/skills/cli/hap-cli-app-editor/scripts/editspec/custom-action.schema.json +0 -0
  225. {hap_cli-0.8.14 → hap_cli-0.8.15}/skills/cli/hap-cli-app-editor/scripts/editspec/envelope.schema.json +0 -0
  226. {hap_cli-0.8.14 → hap_cli-0.8.15}/skills/cli/hap-cli-app-editor/scripts/editspec/field.schema.json +0 -0
  227. {hap_cli-0.8.14 → hap_cli-0.8.15}/sources/v3-api-schema/INDEX.json +0 -0
  228. {hap_cli-0.8.14 → hap_cli-0.8.15}/sources/v3-api-schema/add_member_to_role.yaml +0 -0
  229. {hap_cli-0.8.14 → hap_cli-0.8.15}/sources/v3-api-schema/batch_delete_records.yaml +0 -0
  230. {hap_cli-0.8.14 → hap_cli-0.8.15}/sources/v3-api-schema/create_optionset.yaml +0 -0
  231. {hap_cli-0.8.14 → hap_cli-0.8.15}/sources/v3-api-schema/create_role.yaml +0 -0
  232. {hap_cli-0.8.14 → hap_cli-0.8.15}/sources/v3-api-schema/delete_optionset.yaml +0 -0
  233. {hap_cli-0.8.14 → hap_cli-0.8.15}/sources/v3-api-schema/delete_record.yaml +0 -0
  234. {hap_cli-0.8.14 → hap_cli-0.8.15}/sources/v3-api-schema/delete_role.yaml +0 -0
  235. {hap_cli-0.8.14 → hap_cli-0.8.15}/sources/v3-api-schema/delete_worksheet.yaml +0 -0
  236. {hap_cli-0.8.14 → hap_cli-0.8.15}/sources/v3-api-schema/get_app_info.yaml +0 -0
  237. {hap_cli-0.8.14 → hap_cli-0.8.15}/sources/v3-api-schema/get_app_knowledge_list.yaml +0 -0
  238. {hap_cli-0.8.14 → hap_cli-0.8.15}/sources/v3-api-schema/get_app_worksheets_list.yaml +0 -0
  239. {hap_cli-0.8.14 → hap_cli-0.8.15}/sources/v3-api-schema/get_optionset_list.yaml +0 -0
  240. {hap_cli-0.8.14 → hap_cli-0.8.15}/sources/v3-api-schema/get_record_details.yaml +0 -0
  241. {hap_cli-0.8.14 → hap_cli-0.8.15}/sources/v3-api-schema/get_record_discussions.yaml +0 -0
  242. {hap_cli-0.8.14 → hap_cli-0.8.15}/sources/v3-api-schema/get_record_list.yaml +0 -0
  243. {hap_cli-0.8.14 → hap_cli-0.8.15}/sources/v3-api-schema/get_record_logs.yaml +0 -0
  244. {hap_cli-0.8.14 → hap_cli-0.8.15}/sources/v3-api-schema/get_record_pivot_data.yaml +0 -0
  245. {hap_cli-0.8.14 → hap_cli-0.8.15}/sources/v3-api-schema/get_record_relations.yaml +0 -0
  246. {hap_cli-0.8.14 → hap_cli-0.8.15}/sources/v3-api-schema/get_record_share_link.yaml +0 -0
  247. {hap_cli-0.8.14 → hap_cli-0.8.15}/sources/v3-api-schema/get_regions.yaml +0 -0
  248. {hap_cli-0.8.14 → hap_cli-0.8.15}/sources/v3-api-schema/get_role_details.yaml +0 -0
  249. {hap_cli-0.8.14 → hap_cli-0.8.15}/sources/v3-api-schema/get_role_list.yaml +0 -0
  250. {hap_cli-0.8.14 → hap_cli-0.8.15}/sources/v3-api-schema/knowledge_search.yaml +0 -0
  251. {hap_cli-0.8.14 → hap_cli-0.8.15}/sources/v3-api-schema/leave_all_roles.yaml +0 -0
  252. {hap_cli-0.8.14 → hap_cli-0.8.15}/sources/v3-api-schema/remove_member_from_role.yaml +0 -0
  253. {hap_cli-0.8.14 → hap_cli-0.8.15}/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.14
3
+ Version: 0.8.15
4
4
  Summary: CLI harness for Mingdao HAP - Enterprise no-code platform
5
5
  Author: hap-cli
6
6
  License: Apache-2.0
@@ -1,3 +1,3 @@
1
1
  """CLI harness for Mingdao HAP (hap-cli)."""
2
2
 
3
- __version__ = "0.8.14"
3
+ __version__ = "0.8.15"
@@ -243,7 +243,11 @@ def instance_retry(ctx, instance_id):
243
243
  @click.option("--work-id", "-w", default="", help="Work item ID")
244
244
  @pass_context
245
245
  def instance_restart(ctx, instance_id, work_id):
246
- """Re-initiate a completed/rejected instance."""
246
+ """Re-initiate a flow the initiator has revoked.
247
+
248
+ Use this after the initiator revoked (withdrew) a still-running flow to
249
+ start it again. It does not apply to flows that already finished.
250
+ """
247
251
  try:
248
252
  session = ctx.get_session()
249
253
  data = inst_mod.restart_instance(session, instance_id, work_id)
@@ -354,15 +358,24 @@ def instance_batch(ctx, action, type_, process_id, select, instances_json,
354
358
 
355
359
 
356
360
  def _batch_lifecycle_options(fn):
357
- """Shared options for end-batch / retry-batch — both take
358
- ``RequestStartProcess`` shape (see instanceVersion.js:144)."""
361
+ """Shared options for end-batch / retry-batch.
362
+
363
+ The primary path takes one or more INSTANCE_IDS (the ids shown in the flow
364
+ history list) as positional arguments — these become ``sources`` and are
365
+ the only thing the server needs. The ``--app-id`` + ``--all`` + filter
366
+ options drive the alternative "select all in a worksheet view" mode.
367
+ """
359
368
  decorators = [
360
- click.argument("app_id"),
361
- click.option("--trigger-id", default="", help="Trigger/button ID"),
362
- click.option("--view-id", default="", help="Source view ID"),
363
- click.option("--source", "-s", multiple=True, help="Explicit row ID to act on (repeat)"),
364
- click.option("--all", "is_all", is_flag=True, default=False, help="Select all matching rows"),
365
- click.option("--keywords", default="", help="Search keyword over rows"),
369
+ click.argument("instance_ids", nargs=-1),
370
+ click.option("--source", "-s", multiple=True,
371
+ help="Instance ID to act on (repeat; merged with positional IDs)"),
372
+ click.option("--app-id", "app_id", default="",
373
+ help="Worksheet ID only needed with --all to select every matching row"),
374
+ click.option("--all", "is_all", is_flag=True, default=False,
375
+ help="Select all matching rows (requires --app-id)"),
376
+ click.option("--view-id", default="", help="Source view ID (for --all)"),
377
+ click.option("--trigger-id", default="", help="Trigger/button ID (for --all)"),
378
+ click.option("--keywords", default="", help="Search keyword over rows (for --all)"),
366
379
  click.option("--filter-controls", default="", help="JSON array of filter conditions"),
367
380
  click.option("--fast-filters", default="", help="JSON array of fast filters"),
368
381
  click.option("--nav-group-filters", default="", help="JSON array of nav-group filters"),
@@ -376,12 +389,21 @@ def _batch_lifecycle_options(fn):
376
389
 
377
390
 
378
391
  def _resolve_batch_lifecycle_kwargs(
379
- source, is_all, keywords,
392
+ instance_ids, source, app_id, is_all, keywords,
380
393
  filter_controls, fast_filters, nav_group_filters, filters_group,
381
394
  data_log, push_unique_id,
382
395
  ):
396
+ sources = list(instance_ids) + list(source)
397
+ if not sources and not is_all:
398
+ raise click.UsageError(
399
+ "Provide at least one INSTANCE_ID (or --source), "
400
+ "or use --all with --app-id to select a whole view."
401
+ )
402
+ if is_all and not app_id:
403
+ raise click.UsageError("--all requires --app-id (the worksheet ID).")
383
404
  return {
384
- "sources": list(source) if source else None,
405
+ "app_id": app_id,
406
+ "sources": sources or None,
385
407
  "is_all": is_all,
386
408
  "key_words": keywords,
387
409
  "filter_controls": _json.loads(filter_controls) if filter_controls else None,
@@ -398,21 +420,27 @@ def _resolve_batch_lifecycle_kwargs(
398
420
  @click.option("--yes", "-y", is_flag=True, help="Skip confirmation")
399
421
  @pass_context
400
422
  def instance_end_batch(
401
- ctx, app_id, trigger_id, view_id, source, is_all, keywords,
423
+ ctx, instance_ids, source, app_id, is_all, view_id, trigger_id, keywords,
402
424
  filter_controls, fast_filters, nav_group_filters, filters_group,
403
425
  data_log, push_unique_id, yes,
404
426
  ):
405
- """Terminate instances in bulk (``v1/instance/endInstanceList``)."""
427
+ """Terminate one or more running flows in bulk.
428
+
429
+ Pass the instance IDs from the flow history list as arguments:
430
+
431
+ hap approval end-batch <INSTANCE_ID> [<INSTANCE_ID> ...]
432
+ """
406
433
  try:
434
+ kwargs = _resolve_batch_lifecycle_kwargs(
435
+ instance_ids, source, app_id, is_all, keywords,
436
+ filter_controls, fast_filters, nav_group_filters, filters_group,
437
+ data_log, push_unique_id,
438
+ )
407
439
  if not yes:
408
440
  click.confirm("Terminate the matching instances?", abort=True)
409
441
  session = ctx.get_session()
410
- kwargs = _resolve_batch_lifecycle_kwargs(
411
- source, is_all, keywords, filter_controls, fast_filters,
412
- nav_group_filters, filters_group, data_log, push_unique_id,
413
- )
414
442
  data = inst_mod.end_instance_batch(
415
- session, app_id, trigger_id=trigger_id, view_id=view_id, **kwargs,
443
+ session, view_id=view_id, trigger_id=trigger_id, **kwargs,
416
444
  )
417
445
  ctx.output(data, lambda d: click.echo(f"Batch terminate dispatched: {d}"))
418
446
  except Exception as e:
@@ -423,19 +451,25 @@ def instance_end_batch(
423
451
  @_batch_lifecycle_options
424
452
  @pass_context
425
453
  def instance_retry_batch(
426
- ctx, app_id, trigger_id, view_id, source, is_all, keywords,
454
+ ctx, instance_ids, source, app_id, is_all, view_id, trigger_id, keywords,
427
455
  filter_controls, fast_filters, nav_group_filters, filters_group,
428
456
  data_log, push_unique_id,
429
457
  ):
430
- """Retry failed instances in bulk (``v1/instance/resetInstanceList``)."""
458
+ """Retry one or more failed flows in bulk.
459
+
460
+ Pass the instance IDs from the flow history list as arguments:
461
+
462
+ hap approval retry-batch <INSTANCE_ID> [<INSTANCE_ID> ...]
463
+ """
431
464
  try:
432
- session = ctx.get_session()
433
465
  kwargs = _resolve_batch_lifecycle_kwargs(
434
- source, is_all, keywords, filter_controls, fast_filters,
435
- nav_group_filters, filters_group, data_log, push_unique_id,
466
+ instance_ids, source, app_id, is_all, keywords,
467
+ filter_controls, fast_filters, nav_group_filters, filters_group,
468
+ data_log, push_unique_id,
436
469
  )
470
+ session = ctx.get_session()
437
471
  data = inst_mod.reset_instance_batch(
438
- session, app_id, trigger_id=trigger_id, view_id=view_id, **kwargs,
472
+ session, view_id=view_id, trigger_id=trigger_id, **kwargs,
439
473
  )
440
474
  ctx.output(data, lambda d: click.echo(f"Batch retry dispatched: {d}"))
441
475
  except Exception as e:
@@ -69,7 +69,8 @@ def role_create(ctx, app_id, name, desc, permission):
69
69
  "views are fetched and the full permission structure is "
70
70
  "filled in (unspecified fields/views default to allowed).")
71
71
  @click.option("--page-permissions", "page_perms_json", default="",
72
- help="Page permission JSON: list of {pageId, enable}.")
72
+ help="Page permission JSON: list of {id, enable}, where 'id' is "
73
+ "the custom-page id ('pageId' is also accepted).")
73
74
  @click.option("--hide-app-for-members", is_flag=True, default=False,
74
75
  help="Hide the app from members of this role.")
75
76
  @pass_context
@@ -628,7 +628,12 @@ def restart_instance(
628
628
  instance_id: str,
629
629
  work_id: str = "",
630
630
  ) -> dict[str, Any]:
631
- """Re-initiate a rejected/completed instance.
631
+ """Re-initiate an instance that the initiator has revoked.
632
+
633
+ This is the "撤回后重新发起" action (instance/restart, paired with
634
+ instance/revoke; operation types 13/19 in ExecDialog/StepItem). It applies
635
+ to an instance the initiator previously revoked while it was still running
636
+ — NOT to an already-completed or rejected instance.
632
637
 
633
638
  Args:
634
639
  session: Active session
@@ -647,13 +652,22 @@ def restart_instance(
647
652
  # ── Batch lifecycle ─────────────────────────────────────────────────────
648
653
  #
649
654
  # ``endInstanceList`` and ``resetInstanceList`` take a ``RequestStartProcess``
650
- # payload that describes a selection over a worksheet view (same shape used
651
- # by worksheet trigger batch ops). Callers either enumerate explicit
652
- # ``sources`` row ids OR flip ``is_all`` on and describe the filter.
655
+ # payload (instanceVersion.js:144). There are two ways to select the target
656
+ # instances:
657
+ # 1. Explicit ``sources`` = a list of instance ids (the ids returned by the
658
+ # flow-history list). This is the only shape the frontend ever sends —
659
+ # HistoryHeader.jsx:95/112 calls ``{sources: [id, ...]}`` with nothing
660
+ # else. ``appId`` is NOT required and must NOT be injected, otherwise the
661
+ # server 500s when it is given a value that is not a real worksheet id.
662
+ # 2. ``is_all`` selection over a worksheet view — then ``appId`` (the
663
+ # worksheet id, named ``appId`` in the schema) plus the filter fields are
664
+ # required.
665
+ # Therefore ``appId`` and ``isAll`` are only added to the body when they carry
666
+ # meaning; an empty ``appId`` or ``isAll=False`` must not leak into the payload.
653
667
 
654
668
 
655
669
  def _build_request_start_process(
656
- app_id: str,
670
+ app_id: str = "",
657
671
  trigger_id: str = "",
658
672
  view_id: str = "",
659
673
  sources: Optional[list] = None,
@@ -666,11 +680,16 @@ def _build_request_start_process(
666
680
  data_log: str = "",
667
681
  push_unique_id: str = "",
668
682
  ) -> dict[str, Any]:
669
- """Assemble a ``RequestStartProcess`` body per instanceVersion.js:144."""
670
- data: dict[str, Any] = {
671
- "appId": app_id,
672
- "isAll": is_all,
673
- }
683
+ """Assemble a ``RequestStartProcess`` body per instanceVersion.js:144.
684
+
685
+ ``appId`` is only emitted when non-empty and ``isAll`` only when ``True``;
686
+ the explicit-``sources`` path (the common case) sends just ``sources``.
687
+ """
688
+ data: dict[str, Any] = {}
689
+ if app_id:
690
+ data["appId"] = app_id
691
+ if is_all:
692
+ data["isAll"] = is_all
674
693
  if trigger_id:
675
694
  data["triggerId"] = trigger_id
676
695
  if view_id:
@@ -696,7 +715,7 @@ def _build_request_start_process(
696
715
 
697
716
  def end_instance_batch(
698
717
  session: Session,
699
- app_id: str,
718
+ app_id: str = "",
700
719
  *,
701
720
  trigger_id: str = "",
702
721
  view_id: str = "",
@@ -712,9 +731,11 @@ def end_instance_batch(
712
731
  ) -> dict[str, Any]:
713
732
  """Terminate instances in bulk (``v1/instance/endInstanceList``).
714
733
 
715
- Either pass ``sources`` (explicit row ids) or flip ``is_all=True`` and
716
- describe the selection filter via ``filter_controls`` / ``fast_filters``
717
- / ``filters_group`` / etc.
734
+ Either pass ``sources`` (explicit instance ids from the flow-history list)
735
+ or flip ``is_all=True`` with ``app_id`` (the worksheet id) and describe the
736
+ selection filter via ``filter_controls`` / ``fast_filters`` /
737
+ ``filters_group`` / etc. In the common ``sources`` path ``app_id`` is left
738
+ empty and is not sent.
718
739
  """
719
740
  data = _build_request_start_process(
720
741
  app_id, trigger_id=trigger_id, view_id=view_id,
@@ -728,7 +749,7 @@ def end_instance_batch(
728
749
 
729
750
  def reset_instance_batch(
730
751
  session: Session,
731
- app_id: str,
752
+ app_id: str = "",
732
753
  *,
733
754
  trigger_id: str = "",
734
755
  view_id: str = "",
@@ -142,6 +142,27 @@ def complete_worksheet_permission(
142
142
  }
143
143
 
144
144
 
145
+ def _normalize_page_permissions(
146
+ page_permissions: Optional[list[dict[str, Any]]],
147
+ ) -> list[dict[str, Any]]:
148
+ """Normalize each custom-page permission to the V3 ``{id, enable}`` shape.
149
+
150
+ The V3 ``/v3/app/roles`` schema requires ``id`` (the custom-page id) for
151
+ each entry. ``pageId`` is accepted as a friendly alias and rewritten to
152
+ ``id`` so both spellings work.
153
+ """
154
+ normalized: list[dict[str, Any]] = []
155
+ for pp in page_permissions or []:
156
+ if not isinstance(pp, dict):
157
+ normalized.append(pp)
158
+ continue
159
+ entry = dict(pp)
160
+ if "id" not in entry and "pageId" in entry:
161
+ entry["id"] = entry.pop("pageId")
162
+ normalized.append(entry)
163
+ return normalized
164
+
165
+
145
166
  def create_role_fine_grained(
146
167
  session: Any,
147
168
  app_id: str,
@@ -168,7 +189,7 @@ def create_role_fine_grained(
168
189
  "permissionScope": 0,
169
190
  "hideAppForMembers": hide_app_for_members,
170
191
  "worksheetPermissions": complete_ws_perms,
171
- "pagePermissions": page_permissions or [],
192
+ "pagePermissions": _normalize_page_permissions(page_permissions),
172
193
  }
173
194
  return session.v3_call(
174
195
  "POST", "/v3/app/roles", app_id=app_id, body=body,
@@ -1156,10 +1156,10 @@
1156
1156
  "en": "0=end, 1=active"
1157
1157
  },
1158
1158
  "approval end-batch": {
1159
- "en": "Terminate instances in bulk (``v1/instance/endInstanceList``)."
1159
+ "en": "Terminate one or more running flows in bulk.\n\nPass the instance IDs from the flow history list as arguments:\n\n hap approval end-batch <INSTANCE_ID> [<INSTANCE_ID> ...]"
1160
1160
  },
1161
1161
  "approval end-batch --all": {
1162
- "en": "Select all matching rows"
1162
+ "en": "Select all matching rows (requires --app-id)"
1163
1163
  },
1164
1164
  "approval end-batch --data-log": {
1165
1165
  "en": "Extended trigger context blob"
@@ -1174,7 +1174,7 @@
1174
1174
  "en": "JSON array of custom-page filter groups"
1175
1175
  },
1176
1176
  "approval end-batch --keywords": {
1177
- "en": "Search keyword over rows"
1177
+ "en": "Search keyword over rows (for --all)"
1178
1178
  },
1179
1179
  "approval end-batch --nav-group-filters": {
1180
1180
  "en": "JSON array of nav-group filters"
@@ -1183,13 +1183,13 @@
1183
1183
  "en": "Client-side push dedup id"
1184
1184
  },
1185
1185
  "approval end-batch --source": {
1186
- "en": "Explicit row ID to act on (repeat)"
1186
+ "en": "Instance ID to act on (repeat; merged with positional IDs)"
1187
1187
  },
1188
1188
  "approval end-batch --trigger-id": {
1189
- "en": "Trigger/button ID"
1189
+ "en": "Trigger/button ID (for --all)"
1190
1190
  },
1191
1191
  "approval end-batch --view-id": {
1192
- "en": "Source view ID"
1192
+ "en": "Source view ID (for --all)"
1193
1193
  },
1194
1194
  "approval forward": {
1195
1195
  "en": "Forward a task to another user."
@@ -1276,7 +1276,7 @@
1276
1276
  "en": "Work item ID"
1277
1277
  },
1278
1278
  "approval restart": {
1279
- "en": "Re-initiate a completed/rejected instance."
1279
+ "en": "Re-initiate a flow the initiator has revoked.\n\nUse this after the initiator revoked (withdrew) a still-running flow to start it again. It does not apply to flows that already finished."
1280
1280
  },
1281
1281
  "approval restart --work-id": {
1282
1282
  "en": "Work item ID"
@@ -1285,10 +1285,10 @@
1285
1285
  "en": "Retry a failed instance."
1286
1286
  },
1287
1287
  "approval retry-batch": {
1288
- "en": "Retry failed instances in bulk (``v1/instance/resetInstanceList``)."
1288
+ "en": "Retry one or more failed flows in bulk.\n\nPass the instance IDs from the flow history list as arguments:\n\n hap approval retry-batch <INSTANCE_ID> [<INSTANCE_ID> ...]"
1289
1289
  },
1290
1290
  "approval retry-batch --all": {
1291
- "en": "Select all matching rows"
1291
+ "en": "Select all matching rows (requires --app-id)"
1292
1292
  },
1293
1293
  "approval retry-batch --data-log": {
1294
1294
  "en": "Extended trigger context blob"
@@ -1303,7 +1303,7 @@
1303
1303
  "en": "JSON array of custom-page filter groups"
1304
1304
  },
1305
1305
  "approval retry-batch --keywords": {
1306
- "en": "Search keyword over rows"
1306
+ "en": "Search keyword over rows (for --all)"
1307
1307
  },
1308
1308
  "approval retry-batch --nav-group-filters": {
1309
1309
  "en": "JSON array of nav-group filters"
@@ -1312,13 +1312,13 @@
1312
1312
  "en": "Client-side push dedup id"
1313
1313
  },
1314
1314
  "approval retry-batch --source": {
1315
- "en": "Explicit row ID to act on (repeat)"
1315
+ "en": "Instance ID to act on (repeat; merged with positional IDs)"
1316
1316
  },
1317
1317
  "approval retry-batch --trigger-id": {
1318
- "en": "Trigger/button ID"
1318
+ "en": "Trigger/button ID (for --all)"
1319
1319
  },
1320
1320
  "approval retry-batch --view-id": {
1321
- "en": "Source view ID"
1321
+ "en": "Source view ID (for --all)"
1322
1322
  },
1323
1323
  "approval revoke": {
1324
1324
  "en": "Revoke/withdraw a submitted instance."
@@ -3257,6 +3257,12 @@
3257
3257
  },
3258
3258
  "worksheet view sort": {
3259
3259
  "en": "Reorder worksheet views. Pass view IDs in desired order."
3260
+ },
3261
+ "approval end-batch --app-id": {
3262
+ "en": "Worksheet ID — only needed with --all to select every matching row"
3263
+ },
3264
+ "approval retry-batch --app-id": {
3265
+ "en": "Worksheet ID — only needed with --all to select every matching row"
3260
3266
  }
3261
3267
  }
3262
3268
  }
@@ -6710,6 +6710,23 @@ class TestWave6CustomPageCLI:
6710
6710
  class TestApprovalBatchLifecycle:
6711
6711
  """Wave 8 — batch terminate/retry via ``RequestStartProcess`` payload."""
6712
6712
 
6713
+ @patch("hap_cli.core.session.requests.post")
6714
+ def test_end_instance_batch_sources_only(self, mock_post, mock_session):
6715
+ """The common path sends just ``sources`` (instance ids) — no appId /
6716
+ isAll, mirroring HistoryHeader.jsx. Injecting an appId that is not a
6717
+ real worksheet id makes the server 500 (bug #036701)."""
6718
+ mock_post.return_value = _mock_response(True)
6719
+ inst_mod.end_instance_batch(
6720
+ mock_session,
6721
+ sources=["i1", "i2"],
6722
+ )
6723
+ url = mock_post.call_args[0][0]
6724
+ body = mock_post.call_args[1]["json"]
6725
+ assert url.endswith("/v1/instance/endInstanceList")
6726
+ assert body == {"sources": ["i1", "i2"]}
6727
+ assert "appId" not in body
6728
+ assert "isAll" not in body
6729
+
6713
6730
  @patch("hap_cli.core.session.requests.post")
6714
6731
  def test_end_instance_batch_sends_request_start_process(self, mock_post, mock_session):
6715
6732
  mock_post.return_value = _mock_response(True)
@@ -6719,7 +6736,7 @@ class TestApprovalBatchLifecycle:
6719
6736
  trigger_id="btn1",
6720
6737
  view_id="view1",
6721
6738
  sources=["r1", "r2"],
6722
- is_all=False,
6739
+ is_all=True,
6723
6740
  key_words="urgent",
6724
6741
  )
6725
6742
  url = mock_post.call_args[0][0]
@@ -6729,7 +6746,7 @@ class TestApprovalBatchLifecycle:
6729
6746
  assert body["triggerId"] == "btn1"
6730
6747
  assert body["viewId"] == "view1"
6731
6748
  assert body["sources"] == ["r1", "r2"]
6732
- assert body["isAll"] is False
6749
+ assert body["isAll"] is True
6733
6750
  assert body["keyWords"] == "urgent"
6734
6751
 
6735
6752
  @patch("hap_cli.core.session.requests.post")
@@ -7025,6 +7042,69 @@ class TestApprovalCLI:
7025
7042
  assert sub in result.output, f"Missing delegation subcommand: {sub}"
7026
7043
 
7027
7044
 
7045
+ class TestApprovalBatchLifecycleCLI:
7046
+ """Bug #036701 — end-batch / retry-batch take instance ids positionally
7047
+ and must send only ``sources`` (no appId) so the server does not 500."""
7048
+
7049
+ @patch("hap_cli.core.session.requests.post")
7050
+ def test_end_batch_positional_ids_send_sources_only(self, mock_post, tmp_config):
7051
+ mock_post.return_value = _mock_response(True)
7052
+ Session(server_url="https://t.com", auth_token="tok").save()
7053
+ result = CliRunner().invoke(
7054
+ cli, ["approval", "end-batch", "i1", "i2", "-y"])
7055
+ assert result.exit_code == 0, result.output
7056
+ url = mock_post.call_args[0][0]
7057
+ body = mock_post.call_args[1]["json"]
7058
+ assert url.endswith("/v1/instance/endInstanceList")
7059
+ assert body == {"sources": ["i1", "i2"]}
7060
+
7061
+ @patch("hap_cli.core.session.requests.post")
7062
+ def test_retry_batch_positional_ids_send_sources_only(self, mock_post, tmp_config):
7063
+ mock_post.return_value = _mock_response(True)
7064
+ Session(server_url="https://t.com", auth_token="tok").save()
7065
+ result = CliRunner().invoke(
7066
+ cli, ["approval", "retry-batch", "i9"])
7067
+ assert result.exit_code == 0, result.output
7068
+ url = mock_post.call_args[0][0]
7069
+ body = mock_post.call_args[1]["json"]
7070
+ assert url.endswith("/v1/instance/resetInstanceList")
7071
+ assert body == {"sources": ["i9"]}
7072
+
7073
+ @patch("hap_cli.core.session.requests.post")
7074
+ def test_end_batch_requires_a_target(self, mock_post, tmp_config):
7075
+ Session(server_url="https://t.com", auth_token="tok").save()
7076
+ result = CliRunner().invoke(cli, ["approval", "end-batch", "-y"])
7077
+ assert result.exit_code != 0
7078
+ assert "INSTANCE_ID" in result.output
7079
+ mock_post.assert_not_called()
7080
+
7081
+ @patch("hap_cli.core.session.requests.post")
7082
+ def test_end_batch_all_requires_app_id(self, mock_post, tmp_config):
7083
+ Session(server_url="https://t.com", auth_token="tok").save()
7084
+ result = CliRunner().invoke(cli, ["approval", "end-batch", "--all", "-y"])
7085
+ assert result.exit_code != 0
7086
+ assert "--app-id" in result.output
7087
+ mock_post.assert_not_called()
7088
+
7089
+ @patch("hap_cli.core.session.requests.post")
7090
+ def test_end_batch_all_mode_sends_appid_and_isall(self, mock_post, tmp_config):
7091
+ mock_post.return_value = _mock_response(True)
7092
+ Session(server_url="https://t.com", auth_token="tok").save()
7093
+ result = CliRunner().invoke(
7094
+ cli, ["approval", "end-batch", "--all", "--app-id", "ws1", "-y"])
7095
+ assert result.exit_code == 0, result.output
7096
+ body = mock_post.call_args[1]["json"]
7097
+ assert body["appId"] == "ws1"
7098
+ assert body["isAll"] is True
7099
+
7100
+ def test_restart_help_describes_revoke_semantics(self, tmp_config):
7101
+ Session(server_url="https://t.com", auth_token="tok").save()
7102
+ result = CliRunner().invoke(cli, ["approval", "restart", "--help"])
7103
+ assert result.exit_code == 0
7104
+ assert "revoke" in result.output.lower()
7105
+ assert "completed/rejected" not in result.output
7106
+
7107
+
7028
7108
  # ── Friendly auth-error handling ─────────────────────────────────────────
7029
7109
  #
7030
7110
  # The HAP server returns HTTP 401 (or a state=0 body whose message implies
@@ -8809,6 +8889,24 @@ class TestRolePermBuilder:
8809
8889
  assert body["permissionScope"] == 0
8810
8890
  assert body["worksheetPermissions"][0]["id"] == "ws1"
8811
8891
 
8892
+ def test_page_permissions_accept_pageid_alias(self):
8893
+ """Bug #036701 — the V3 schema requires {id, enable} for page perms.
8894
+ Accept the friendly 'pageId' spelling and rewrite it to 'id'."""
8895
+ from hap_cli.core import role_perm_builder as rpb
8896
+ sess = MagicMock()
8897
+ sess.v3_call.return_value = {"data": {"id": "role1"}}
8898
+ rpb.create_role_fine_grained(
8899
+ sess, "app1", "管理员",
8900
+ page_permissions=[
8901
+ {"pageId": "p1", "enable": False},
8902
+ {"id": "p2", "enable": True},
8903
+ ])
8904
+ body = sess.v3_call.call_args.kwargs["body"]
8905
+ assert body["pagePermissions"] == [
8906
+ {"id": "p1", "enable": False},
8907
+ {"id": "p2", "enable": True},
8908
+ ]
8909
+
8812
8910
 
8813
8911
  class TestWorkflowNodeNesting:
8814
8912
  """§2.J branch + approval_block / sub_process nesting. Structural
@@ -144,7 +144,7 @@ class TestLegacyDeleteConfirm:
144
144
  @patch("hap_cli.core.session.requests.post")
145
145
  def test_end_batch_aborts_without_yes(self, mock_post, tmp_config):
146
146
  result = CliRunner().invoke(cli, [
147
- "approval", "end-batch", "a1", "--all",
147
+ "approval", "end-batch", "i1",
148
148
  ])
149
149
  assert result.exit_code != 0
150
150
  assert "Terminate the matching instances?" in result.output
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hap-cli
3
- Version: 0.8.14
3
+ Version: 0.8.15
4
4
  Summary: CLI harness for Mingdao HAP - Enterprise no-code platform
5
5
  Author: hap-cli
6
6
  License: Apache-2.0
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes